[pk,sim] first cut of appserver communication link
authorAndrew Waterman <waterman@s141.Millennium.Berkeley.EDU>
Thu, 22 Jul 2010 03:12:09 +0000 (20:12 -0700)
committerAndrew Waterman <waterman@s141.Millennium.Berkeley.EDU>
Thu, 22 Jul 2010 03:12:09 +0000 (20:12 -0700)
12 files changed:
riscv/applink.cc [new file with mode: 0644]
riscv/applink.h [new file with mode: 0644]
riscv/insns/dmfc0.h
riscv/insns/dmtc0.h
riscv/insns/mfc0.h
riscv/insns/mtc0.h
riscv/processor.cc
riscv/processor.h
riscv/riscv-isa-run.cc
riscv/riscv.mk.in
riscv/sim.cc
riscv/sim.h

diff --git a/riscv/applink.cc b/riscv/applink.cc
new file mode 100644 (file)
index 0000000..fdd6cc7
--- /dev/null
@@ -0,0 +1,137 @@
+#include "applink.h"
+#include "common.h"
+#include "sim.h"
+#include <unistd.h>
+#include <stdexcept>
+
+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 (file)
index 0000000..b153b1f
--- /dev/null
@@ -0,0 +1,26 @@
+#ifndef _APPLINK_H
+#define _APPLINK_H
+
+#include <stdint.h>
+
+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
index 38b16b565e4768565cc7c3127ac698d64436c48b..b905d31f2a7b70f42f3deb86cfbdb32df03981a8 100644 (file)
@@ -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;
 }
index 0c9c4ff52683ed458646c20e5da13c0d5ef37d9c..33476057bf7c050e3ed7d714bb4384207709e68d 100644 (file)
@@ -12,4 +12,8 @@ switch(insn.rtype.rs)
   case 3:
     ebase = RT & ~0xFFF;
     break;
+
+  case 16:
+    sim->set_tohost(RT);
+    break;
 }
index 9d3595ef13453d289689b6a48799c2305218a429..f57539a94a2326c49ab08fb2959db4c53e262cbd 100644 (file)
@@ -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;
 }
index 3b34f7a2090d18c5a1c11cd062a0e2021e6d87d4..f018cf63a3959a31c5b660a5c6c5f307d1e0a307 100644 (file)
@@ -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;
 }
index d10d45cc11db577463de13a737999c7e54353ebb..23761d3cec2b54c5f13dfd672e9c325f5b51d632 100644 (file)
@@ -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;
index 6724e2c2f7cce7e60f17bfbbaec9bb549d8307e4..33ca93921efcce200f7a3eba37dd6260530a2172 100644 (file)
@@ -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;
index 1acb72166166743c2bf6ec7eb1e6a55e72b7e563..ced7913238eb144ff017d28485d62d2a8ca0fc7a 100644 (file)
@@ -1,27 +1,39 @@
 #include <unistd.h>
+#include <fcntl.h>
 #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);
 }
index ada62d5c0c85fbc7cc778d949b50b90a8ee5d758..54fc380c20229a7ab20248707a48489497db625c 100644 (file)
@@ -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 \
index a4a31ecb795cc0196fbf9fbaca84ea654d75c648..dede8de570b4d51f96e2daa716c42f994cefeacf 100644 (file)
@@ -1,4 +1,5 @@
 #include "sim.h"
+#include "applink.h"
 #include "common.h"
 #include "load_elf.h"
 #include <sys/mman.h>
@@ -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<processor_t>(_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<std::string>& 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<std::string>& 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<std::string>& 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];
index 6d2ac9be43aa46ea5724bc4b357267e7a12f694d..59795d9175ac123f4db04f253abe862b46f12112 100644 (file)
@@ -5,22 +5,31 @@
 #include <string>
 #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<processor_t> procs;
 
   void step_all(size_t n, size_t interleave, bool noisy);
 
@@ -41,6 +50,8 @@ private:
   reg_t get_reg(const std::vector<std::string>& args);
   reg_t get_mem(const std::vector<std::string>& args);
   reg_t get_pc(const std::vector<std::string>& args);
+
+  friend class appserver_link_t;
 };
 
 #endif