Implement core device storage (fixes #219).

This commit is contained in:
whitequark 2016-01-10 13:04:55 +00:00
parent 1543141cee
commit 9366a29483
11 changed files with 198 additions and 12 deletions

View File

@ -37,6 +37,18 @@ class CompileError(Exception):
def rtio_get_counter() -> TInt64: def rtio_get_counter() -> TInt64:
raise NotImplementedError("syscall not simulated") raise NotImplementedError("syscall not simulated")
@syscall
def cache_get(TStr) -> TList(TInt32):
raise NotImplementedError("syscall not simulated")
@syscall
def cache_put(TStr, TList(TInt32)):
raise NotImplementedError("syscall not simulated")
@syscall
def cache_clear(TStr):
raise NotImplementedError("syscall not simulated")
class Core: class Core:
"""Core device driver. """Core device driver.
@ -108,3 +120,15 @@ class Core:
min_now = rtio_get_counter() + 125000 min_now = rtio_get_counter() + 125000
if now_mu() < min_now: if now_mu() < min_now:
at_mu(min_now) at_mu(min_now)
@kernel
def get_cache(self, key):
return cache_get(key)
@kernel
def put_cache(self, key, value):
return cache_put(key, value)
@kernel
def clear_cache(self, key):
return cache_clear(key)

View File

@ -7,7 +7,7 @@ from misoc.integration.soc_core import mem_decoder
class KernelCPU(Module): class KernelCPU(Module):
def __init__(self, platform, def __init__(self, platform,
exec_address=0x40800000, exec_address=0x42000000,
main_mem_origin=0x40000000, main_mem_origin=0x40000000,
l2_size=8192): l2_size=8192):
self._reset = CSRStorage(reset=1) self._reset = CSRStorage(reset=1)

View File

@ -9,7 +9,8 @@ OBJECTS := isr.o clock.o rtiocrg.o flash_storage.o mailbox.o \
OBJECTS_KSUPPORT := ksupport.o artiq_personality.o mailbox.o \ OBJECTS_KSUPPORT := ksupport.o artiq_personality.o mailbox.o \
bridge.o rtio.o ttl.o dds.o bridge.o rtio.o ttl.o dds.o
CFLAGS += -I$(MISOC_DIRECTORY)/software/include/dyld \ CFLAGS += -I$(LIBALLOC_DIRECTORY) \
-I$(MISOC_DIRECTORY)/software/include/dyld \
-I$(LIBDYLD_DIRECTORY)/include \ -I$(LIBDYLD_DIRECTORY)/include \
-I$(LIBUNWIND_DIRECTORY) \ -I$(LIBUNWIND_DIRECTORY) \
-I$(LIBUNWIND_DIRECTORY)/../unwinder/include \ -I$(LIBUNWIND_DIRECTORY)/../unwinder/include \
@ -31,10 +32,11 @@ runtime.elf: $(OBJECTS)
-N -o $@ \ -N -o $@ \
../libbase/crt0-$(CPU).o \ ../libbase/crt0-$(CPU).o \
$(OBJECTS) \ $(OBJECTS) \
-L../libbase \
-L../libcompiler_rt \ -L../libcompiler_rt \
-L../libbase \
-L../liballoc \
-L../liblwip \ -L../liblwip \
-lbase -lcompiler_rt -llwip -lbase -lcompiler_rt -lalloc -llwip
@chmod -x $@ @chmod -x $@
ksupport.elf: $(OBJECTS_KSUPPORT) ksupport.elf: $(OBJECTS_KSUPPORT)
@ -48,7 +50,7 @@ ksupport.elf: $(OBJECTS_KSUPPORT)
-L../libcompiler_rt \ -L../libcompiler_rt \
-L../libunwind \ -L../libunwind \
-L../libdyld \ -L../libdyld \
-lbase -lcompiler_rt -lunwind -ldyld -lbase -lcompiler_rt -ldyld -lunwind
@chmod -x $@ @chmod -x $@
ksupport_data.o: ksupport.elf ksupport_data.o: ksupport.elf

View File

@ -3,8 +3,8 @@
#include "artiq_personality.h" #include "artiq_personality.h"
#define KERNELCPU_EXEC_ADDRESS 0x40800000 #define KERNELCPU_EXEC_ADDRESS 0x42000000
#define KERNELCPU_PAYLOAD_ADDRESS 0x40820000 #define KERNELCPU_PAYLOAD_ADDRESS 0x42020000
#define KERNELCPU_LAST_ADDRESS (0x4fffffff - 1024*1024) #define KERNELCPU_LAST_ADDRESS (0x4fffffff - 1024*1024)
#define KSUPPORT_HEADER_SIZE 0x80 #define KSUPPORT_HEADER_SIZE 0x80

View File

@ -122,6 +122,10 @@ static const struct symbol runtime_exports[] = {
{"dds_batch_exit", &dds_batch_exit}, {"dds_batch_exit", &dds_batch_exit},
{"dds_set", &dds_set}, {"dds_set", &dds_set},
{"cache_get", &cache_get},
{"cache_put", &cache_put},
{"cache_clear", &cache_clear},
/* end */ /* end */
{NULL, NULL} {NULL, NULL}
}; };
@ -444,6 +448,55 @@ void attribute_writeback(void *utypes) {
} }
} }
struct artiq_list cache_get(const char *key)
{
struct msg_cache_get_request request;
struct msg_cache_get_reply *reply;
request.type = MESSAGE_TYPE_CACHE_GET_REQUEST;
request.key = key;
mailbox_send_and_wait(&request);
reply = mailbox_wait_and_receive();
if(reply->type != MESSAGE_TYPE_CACHE_GET_REPLY) {
log("Malformed MESSAGE_TYPE_CACHE_GET_REQUEST reply type %d",
reply->type);
while(1);
}
return (struct artiq_list) { reply->length, reply->elements };
}
void cache_put(const char *key, struct artiq_list value)
{
struct msg_cache_put_request request;
struct msg_cache_put_reply *reply;
request.type = MESSAGE_TYPE_CACHE_PUT_REQUEST;
request.key = key;
request.elements = value.elements;
request.length = value.length;
mailbox_send_and_wait(&request);
reply = mailbox_wait_and_receive();
if(reply->type != MESSAGE_TYPE_CACHE_PUT_REPLY) {
log("Malformed MESSAGE_TYPE_CACHE_PUT_REQUEST reply type %d",
reply->type);
while(1);
}
if(!reply->succeeded) {
artiq_raise_from_c("CacheError",
"cannot put into a busy cache row",
0, 0, 0);
}
}
void cache_clear(const char *key)
{
cache_put(key, (struct artiq_list) { 0, NULL });
}
void lognonl(const char *fmt, ...) void lognonl(const char *fmt, ...)
{ {
struct msg_log request; struct msg_log request;

View File

@ -1,12 +1,20 @@
#ifndef __KSTARTUP_H #ifndef __KSTARTUP_H
#define __KSTARTUP_H #define __KSTARTUP_H
struct artiq_list {
int32_t length;
int32_t *elements;
};
long long int now_init(void); long long int now_init(void);
void now_save(long long int now); void now_save(long long int now);
int watchdog_set(int ms); int watchdog_set(int ms);
void watchdog_clear(int id); void watchdog_clear(int id);
void send_rpc(int service, const char *tag, ...); void send_rpc(int service, const char *tag, ...);
int recv_rpc(void *slot); int recv_rpc(void *slot);
struct artiq_list cache_get(const char *key);
void cache_put(const char *key, struct artiq_list value);
void cache_clear(const char *key);
void lognonl(const char *fmt, ...); void lognonl(const char *fmt, ...);
void log(const char *fmt, ...); void log(const char *fmt, ...);

View File

@ -3,11 +3,12 @@ ENTRY(_start)
INCLUDE generated/regions.ld INCLUDE generated/regions.ld
/* First 8M of main memory are reserved for runtime code/data /* First 32M of main memory are reserved for runtime
* then comes kernel memory. First 128K of kernel memory are for support code. * code/data/heap, then comes kernel memory.
* First 128K of kernel memory are for support code.
*/ */
MEMORY { MEMORY {
ksupport (RWX) : ORIGIN = 0x40800000, LENGTH = 0x20000 ksupport (RWX) : ORIGIN = 0x42000000, LENGTH = 0x20000
} }
/* On AMP systems, kernel stack is at the end of main RAM, /* On AMP systems, kernel stack is at the end of main RAM,

View File

@ -1,5 +1,6 @@
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
#include <alloc.h>
#include <irq.h> #include <irq.h>
#include <uart.h> #include <uart.h>
#include <console.h> #include <console.h>
@ -263,6 +264,8 @@ static int check_test_mode(void)
return 0; return 0;
} }
extern void _fheap, _eheap;
int main(void) int main(void)
{ {
irq_setmask(0); irq_setmask(0);
@ -271,6 +274,7 @@ int main(void)
puts("ARTIQ runtime built "__DATE__" "__TIME__"\n"); puts("ARTIQ runtime built "__DATE__" "__TIME__"\n");
alloc_give(&_fheap, &_eheap - &_fheap);
clock_init(); clock_init();
rtiocrg_init(); rtiocrg_init();
puts("Press 't' to enter test mode..."); puts("Press 't' to enter test mode...");

View File

@ -3,6 +3,7 @@
#include <stdarg.h> #include <stdarg.h>
#include <stddef.h> #include <stddef.h>
#include <stdint.h>
enum { enum {
MESSAGE_TYPE_LOAD_REPLY, MESSAGE_TYPE_LOAD_REPLY,
@ -18,6 +19,10 @@ enum {
MESSAGE_TYPE_RPC_RECV_REQUEST, MESSAGE_TYPE_RPC_RECV_REQUEST,
MESSAGE_TYPE_RPC_RECV_REPLY, MESSAGE_TYPE_RPC_RECV_REPLY,
MESSAGE_TYPE_RPC_BATCH, MESSAGE_TYPE_RPC_BATCH,
MESSAGE_TYPE_CACHE_GET_REQUEST,
MESSAGE_TYPE_CACHE_GET_REPLY,
MESSAGE_TYPE_CACHE_PUT_REQUEST,
MESSAGE_TYPE_CACHE_PUT_REPLY,
MESSAGE_TYPE_LOG, MESSAGE_TYPE_LOG,
MESSAGE_TYPE_BRG_READY, MESSAGE_TYPE_BRG_READY,
@ -105,6 +110,29 @@ struct msg_rpc_batch {
void *ptr; void *ptr;
}; };
struct msg_cache_get_request {
int type;
const char *key;
};
struct msg_cache_get_reply {
int type;
size_t length;
int32_t *elements;
};
struct msg_cache_put_request {
int type;
const char *key;
size_t length;
int32_t *elements;
};
struct msg_cache_put_reply {
int type;
int succeeded;
};
struct msg_log { struct msg_log {
int type; int type;
const char *fmt; const char *fmt;

View File

@ -7,7 +7,7 @@ INCLUDE generated/regions.ld
* ld does not allow this expression here. * ld does not allow this expression here.
*/ */
MEMORY { MEMORY {
runtime : ORIGIN = 0x40000000, LENGTH = 0x800000 /* 8M */ runtime : ORIGIN = 0x40000000, LENGTH = 0x2000000 /* 32M */
} }
/* Kernel memory space start right after the runtime, /* Kernel memory space start right after the runtime,
@ -65,5 +65,7 @@ SECTIONS
*(.eh_frame) *(.eh_frame)
} }
_heapstart = .; _fheap = .;
. += 0x1800000;
_eheap = .;
} }

View File

@ -908,6 +908,16 @@ static int send_rpc_request(int service, const char *tag, va_list args)
return 1; return 1;
} }
struct cache_row {
struct cache_row *next;
char *key;
size_t length;
int32_t *elements;
int borrowed;
};
static struct cache_row *cache;
/* assumes output buffer is empty when called */ /* assumes output buffer is empty when called */
static int process_kmsg(struct msg_base *umsg) static int process_kmsg(struct msg_base *umsg)
{ {
@ -984,6 +994,60 @@ static int process_kmsg(struct msg_base *umsg)
break; break;
} }
case MESSAGE_TYPE_CACHE_GET_REQUEST: {
struct msg_cache_get_request *request = (struct msg_cache_get_request *)umsg;
struct msg_cache_get_reply reply;
reply.type = MESSAGE_TYPE_CACHE_GET_REPLY;
reply.length = 0;
reply.elements = NULL;
for(struct cache_row *iter = cache; iter; iter = iter->next) {
if(!strcmp(iter->key, request->key)) {
reply.length = iter->length;
reply.elements = iter->elements;
iter->borrowed = 1;
break;
}
}
mailbox_send(&reply);
}
case MESSAGE_TYPE_CACHE_PUT_REQUEST: {
struct msg_cache_put_request *request = (struct msg_cache_put_request *)umsg;
struct msg_cache_put_reply reply;
reply.type = MESSAGE_TYPE_CACHE_PUT_REPLY;
struct cache_row *row = NULL;
for(struct cache_row *iter = cache; iter; iter = iter->next) {
if(!strcmp(iter->key, request->key)) {
free(iter->elements);
row = iter;
break;
}
}
if(!row) {
struct cache_row *row = calloc(1, sizeof(struct cache_row));
row->key = calloc(strlen(request->key) + 1, 1);
strcpy(row->key, request->key);
}
if(!row->borrowed) {
row->length = request->length;
row->elements = calloc(row->length, sizeof(int32_t));
memcpy(row->elements, request->elements,
sizeof(int32_t) * row->length);
reply.succeeded = 1;
} else {
reply.succeeded = 0;
}
mailbox_send(&reply);
}
default: { default: {
log("Received invalid message type %d from kernel CPU", log("Received invalid message type %d from kernel CPU",
umsg->type); umsg->type);