From d2c5b5c15930668588f88bd1186031dded771261 Mon Sep 17 00:00:00 2001 From: Andrew Waterman Date: Wed, 21 Jul 2010 20:12:09 -0700 Subject: [PATCH] [pk,sim] first cut of appserver communication link --- riscv/applink.cc | 137 +++++++++++++++++++++++++++++++++++++++++ riscv/applink.h | 26 ++++++++ riscv/insns/dmfc0.h | 9 +++ riscv/insns/dmtc0.h | 4 ++ riscv/insns/mfc0.h | 9 +++ riscv/insns/mtc0.h | 4 ++ riscv/processor.cc | 10 ++- riscv/processor.h | 7 ++- riscv/riscv-isa-run.cc | 28 ++++++--- riscv/riscv.mk.in | 2 + riscv/sim.cc | 37 +++++++---- riscv/sim.h | 21 +++++-- 12 files changed, 267 insertions(+), 27 deletions(-) create mode 100644 riscv/applink.cc create mode 100644 riscv/applink.h diff --git a/riscv/applink.cc b/riscv/applink.cc new file mode 100644 index 0000000..fdd6cc7 --- /dev/null +++ b/riscv/applink.cc @@ -0,0 +1,137 @@ +#include "applink.h" +#include "common.h" +#include "sim.h" +#include +#include + +enum +{ + APP_CMD_READ_MEM, + APP_CMD_WRITE_MEM, + APP_CMD_READ_CONTROL_REG, + APP_CMD_WRITE_CONTROL_REG, + APP_CMD_START, + APP_CMD_STOP, + APP_CMD_ACK, + APP_CMD_NACK +}; + +#define APP_DATA_ALIGN 8 +#define APP_MAX_DATA_SIZE 1024 +struct packet +{ + uint16_t cmd; + uint16_t seqno; + uint32_t data_size; + uint64_t addr; + uint8_t data[APP_MAX_DATA_SIZE]; +}; + +class packet_error : public std::runtime_error +{ +public: + packet_error(const std::string& s) : std::runtime_error(s) {} +}; +class io_error : public packet_error +{ +public: + io_error(const std::string& s) : packet_error(s) {} +}; + +appserver_link_t::appserver_link_t(int _tohost_fd, int _fromhost_fd) + : sim(NULL), tohost_fd(_tohost_fd), fromhost_fd(_fromhost_fd) +{ +} + +void appserver_link_t::init(sim_t* _sim) +{ + sim = _sim; +} + +void appserver_link_t::wait_for_start() +{ + while(wait_for_packet() != APP_CMD_START); +} + +void appserver_link_t::send_packet(packet* p) +{ + while(1) try + { + int bytes = write(fromhost_fd,p,offsetof(packet,data)+p->data_size); + if(bytes == -1 || (size_t)bytes != offsetof(packet,data)+p->data_size) + throw io_error("write failed"); + } + catch(io_error e) + { + fprintf(stderr,"warning: %s\n",e.what()); + } +} + +void appserver_link_t::nack(uint16_t nack_seqno) +{ + packet p = {APP_CMD_NACK,nack_seqno,0,0}; + send_packet(&p); +} + +int appserver_link_t::wait_for_packet() +{ + while(1) try + { + packet p; + int bytes = read(fromhost_fd,&p,sizeof(p)); + if(bytes != offsetof(packet,data)) + throw io_error("read failed"); + + if(p.seqno != seqno) + { + nack(p.seqno); + continue; + } + + packet ackpacket = {APP_CMD_ACK,seqno,0,0}; + + switch(p.cmd) + { + case APP_CMD_START: + break; + case APP_CMD_STOP: + exit(0); + case APP_CMD_READ_MEM: + demand(p.addr % APP_DATA_ALIGN == 0, "misaligned address"); + demand(p.data_size % APP_DATA_ALIGN == 0, "misaligned data"); + demand(p.data_size <= APP_MAX_DATA_SIZE, "long read data"); + demand(p.addr <= sim->memsz && p.addr+p.data_size <= sim->memsz, "out of bounds"); + memcpy(ackpacket.data,sim->mem+p.addr,p.data_size); + ackpacket.data_size = p.data_size; + break; + case APP_CMD_WRITE_MEM: + demand(p.addr % APP_DATA_ALIGN == 0, "misaligned address"); + demand(p.data_size % APP_DATA_ALIGN == 0, "misaligned data"); + demand(p.data_size <= bytes - offsetof(packet,data), "short packet"); + demand(p.addr <= sim->memsz && p.addr+p.data_size <= sim->memsz, "out of bounds"); + memcpy(sim->mem+p.addr,p.data,p.data_size); + break; + case APP_CMD_READ_CONTROL_REG: + demand(p.addr == 16,"bad control reg"); + demand(p.data_size == sizeof(reg_t),"bad control reg size"); + ackpacket.data_size = sizeof(reg_t); + memcpy(ackpacket.data,&sim->tohost,sizeof(reg_t)); + break; + case APP_CMD_WRITE_CONTROL_REG: + demand(p.addr == 17,"bad control reg"); + demand(p.data_size == sizeof(reg_t),"bad control reg size"); + sim->tohost = 0; + memcpy(&sim->fromhost,ackpacket.data,sizeof(reg_t)); + break; + } + + send_packet(&ackpacket); + seqno++; + return p.cmd; + } + catch(io_error e) + { + fprintf(stderr,"warning: %s\n",e.what()); + } +} + diff --git a/riscv/applink.h b/riscv/applink.h new file mode 100644 index 0000000..b153b1f --- /dev/null +++ b/riscv/applink.h @@ -0,0 +1,26 @@ +#ifndef _APPLINK_H +#define _APPLINK_H + +#include + +class sim_t; +struct packet; +class appserver_link_t +{ +public: + appserver_link_t(int _tohost_fd, int _fromhost_fd); + void init(sim_t* _sim); + void wait_for_start(); + int wait_for_packet(); + +private: + sim_t* sim; + int tohost_fd; + int fromhost_fd; + uint16_t seqno; + + void nack(uint16_t seqno); + void send_packet(packet* p); +}; + +#endif diff --git a/riscv/insns/dmfc0.h b/riscv/insns/dmfc0.h index 38b16b5..b905d31 100644 --- a/riscv/insns/dmfc0.h +++ b/riscv/insns/dmfc0.h @@ -15,6 +15,15 @@ switch(insn.rtype.rs) case 3: RT = ebase; break; + + case 8: + RT = MEMSIZE >> 12; + break; + + case 17: + RT = sim->get_fromhost(); + break; + default: RT = -1; } diff --git a/riscv/insns/dmtc0.h b/riscv/insns/dmtc0.h index 0c9c4ff..3347605 100644 --- a/riscv/insns/dmtc0.h +++ b/riscv/insns/dmtc0.h @@ -12,4 +12,8 @@ switch(insn.rtype.rs) case 3: ebase = RT & ~0xFFF; break; + + case 16: + sim->set_tohost(RT); + break; } diff --git a/riscv/insns/mfc0.h b/riscv/insns/mfc0.h index 9d3595e..f57539a 100644 --- a/riscv/insns/mfc0.h +++ b/riscv/insns/mfc0.h @@ -14,6 +14,15 @@ switch(insn.rtype.rs) case 3: RT = sext32(ebase); break; + + case 8: + RT = sext32(MEMSIZE >> 12); + break; + + case 17: + RT = sext32(sim->get_fromhost()); + break; + default: RT = -1; } diff --git a/riscv/insns/mtc0.h b/riscv/insns/mtc0.h index 3b34f7a..f018cf6 100644 --- a/riscv/insns/mtc0.h +++ b/riscv/insns/mtc0.h @@ -20,4 +20,8 @@ switch(insn.rtype.rs) case 9: printf("%ld insns retired\n",counters[0]); exit(0); + + case 16: + sim->set_tohost(sext32(RT)); + break; } diff --git a/riscv/processor.cc b/riscv/processor.cc index d10d45c..23761d3 100644 --- a/riscv/processor.cc +++ b/riscv/processor.cc @@ -5,9 +5,10 @@ #include "processor.h" #include "common.h" #include "config.h" +#include "sim.h" -processor_t::processor_t(int _id, char* _mem, size_t _memsz) - : id(_id), mmu(_mem,_memsz) +processor_t::processor_t(sim_t* _sim, char* _mem, size_t _memsz) + : sim(_sim), mmu(_mem,_memsz) { memset(R,0,sizeof(R)); pc = 0; @@ -19,6 +20,11 @@ processor_t::processor_t(int _id, char* _mem, size_t _memsz) memset(counters,0,sizeof(counters)); } +void processor_t::init(uint32_t _id) +{ + id = _id; +} + void processor_t::set_sr(uint32_t val) { sr = val & ~SR_ZERO; diff --git a/riscv/processor.h b/riscv/processor.h index 6724e2c..33ca939 100644 --- a/riscv/processor.h +++ b/riscv/processor.h @@ -6,13 +6,18 @@ #include "trap.h" #include "mmu.h" +class sim_t; + class processor_t { public: - processor_t(int _id, char* _mem, size_t _memsz); + processor_t(sim_t* _sim, char* _mem, size_t _memsz); + void init(uint32_t _id); void step(size_t n, bool noisy); private: + sim_t* sim; + // architected state reg_t R[NGPR]; reg_t pc; diff --git a/riscv/riscv-isa-run.cc b/riscv/riscv-isa-run.cc index 1acb721..ced7913 100644 --- a/riscv/riscv-isa-run.cc +++ b/riscv/riscv-isa-run.cc @@ -1,27 +1,39 @@ #include +#include #include "common.h" #include "sim.h" +#include "applink.h" int main(int argc, char** argv) { - sim_t s(1,MEMSIZE); - bool debug = false; + int nprocs = 1; + int fromhost_fd = -1, tohost_fd = -1; - for(int c; (c = getopt(argc,argv,"-d")) != -1; ) + for(int c; (c = getopt(argc,argv,"dpf:t:")) != -1; ) { switch(c) { - case '\1': - s.load_elf(optarg); - break; case 'd': debug = true; break; - case '?': - demand(0,"unrecognized option %c",optopt); + case 'p': + nprocs = atoi(optarg); + break; + case 'f': + fromhost_fd = atoi(optarg); + break; + case 't': + tohost_fd = atoi(optarg); + break; } } + demand(fcntl(fromhost_fd,F_GETFD) >= 0, "fromhost file not open"); + demand(fcntl(tohost_fd,F_GETFD) >= 0, "tohost file not open"); + + appserver_link_t applink(fromhost_fd,tohost_fd); + + sim_t s(nprocs,MEMSIZE,&applink); s.run(debug); } diff --git a/riscv/riscv.mk.in b/riscv/riscv.mk.in index ada62d5..54fc380 100644 --- a/riscv/riscv.mk.in +++ b/riscv/riscv.mk.in @@ -1,6 +1,7 @@ riscv_subproject_deps = riscv_hdrs = \ + applink.h \ common.h \ decode.h \ execute.h \ @@ -12,6 +13,7 @@ riscv_hdrs = \ insns/*.h \ riscv_srcs = \ + applink.cc \ load_elf.cc \ processor.cc \ sim.cc \ diff --git a/riscv/sim.cc b/riscv/sim.cc index a4a31ec..dede8de 100644 --- a/riscv/sim.cc +++ b/riscv/sim.cc @@ -1,4 +1,5 @@ #include "sim.h" +#include "applink.h" #include "common.h" #include "load_elf.h" #include @@ -24,20 +25,20 @@ private: size_t size; }; -sim_t::sim_t(int _nprocs, size_t _memsz) - : nprocs(_nprocs), memsz(_memsz) +sim_t::sim_t(int _nprocs, size_t _memsz, appserver_link_t* _applink) + : applink(_applink), + memsz(_memsz), + mem((char*)mmap64(NULL, memsz, PROT_WRITE, MAP_PRIVATE | MAP_ANON, -1, 0)), + procs(std::vector(_nprocs,processor_t(this,mem,memsz))) { - mem = (char*)mmap(NULL, memsz, PROT_WRITE, MAP_PRIVATE | MAP_ANON, -1, 0); demand(mem != MAP_FAILED, "couldn't allocate target machine's memory"); - procs = (processor_t*)malloc(sizeof(*procs)*nprocs); - for(int i = 0; i < nprocs; i++) - new(&procs[i]) processor_t(i,mem,memsz); + for(int i = 0; i < (int)procs.size(); i++) + procs[i].init(i); } sim_t::~sim_t() { - free(procs); } void sim_t::load_elf(const char* fn) @@ -45,9 +46,23 @@ void sim_t::load_elf(const char* fn) memory_t loader(mem, memsz); ::load_elf(fn,&loader); } +void sim_t::set_tohost(reg_t val) +{ + fromhost = 0; + tohost = val; +} + +reg_t sim_t::get_fromhost() +{ + while(fromhost == 0) + applink->wait_for_packet(); + return fromhost; +} void sim_t::run(bool debug) { + applink->wait_for_start(); + while(1) { if(!debug) @@ -96,7 +111,7 @@ void sim_t::run(bool debug) void sim_t::step_all(size_t n, size_t interleave, bool noisy) { for(size_t j = 0; j < n; j+=interleave) - for(int i = 0; i < nprocs; i++) + for(int i = 0; i < (int)procs.size(); i++) procs[i].step(interleave,noisy); } @@ -134,7 +149,7 @@ void sim_t::interactive_run_proc(const std::vector& a, bool noisy) return; int p = atoi(a[0].c_str()); - if(p >= nprocs) + if(p >= (int)procs.size()) return; if(a.size() == 2) @@ -154,7 +169,7 @@ reg_t sim_t::get_pc(const std::vector& args) throw trap_illegal_instruction; int p = atoi(args[0].c_str()); - if(p >= nprocs) + if(p >= (int)procs.size()) throw trap_illegal_instruction; return procs[p].pc; @@ -167,7 +182,7 @@ reg_t sim_t::get_reg(const std::vector& args) int p = atoi(args[0].c_str()); int r = atoi(args[1].c_str()); - if(p >= nprocs || r >= NGPR) + if(p >= (int)procs.size() || r >= NGPR) throw trap_illegal_instruction; return procs[p].R[r]; diff --git a/riscv/sim.h b/riscv/sim.h index 6d2ac9b..59795d9 100644 --- a/riscv/sim.h +++ b/riscv/sim.h @@ -5,22 +5,31 @@ #include #include "processor.h" -const int MEMSIZE = 0x7D000000; +const long MEMSIZE = 0x100000000; + +class appserver_link_t; class sim_t { public: - sim_t(int _nprocs, size_t _memsz); + sim_t(int _nprocs, size_t _memsz, appserver_link_t* _applink); ~sim_t(); void load_elf(const char* fn); void run(bool debug); + void set_tohost(reg_t val); + reg_t get_fromhost(); + private: - processor_t* procs; - int nprocs; + // global architected state + reg_t tohost; + reg_t fromhost; + + appserver_link_t* applink; - char* mem; size_t memsz; + char* mem; + std::vector procs; void step_all(size_t n, size_t interleave, bool noisy); @@ -41,6 +50,8 @@ private: reg_t get_reg(const std::vector& args); reg_t get_mem(const std::vector& args); reg_t get_pc(const std::vector& args); + + friend class appserver_link_t; }; #endif -- 2.30.2