[fesvr,xcc,sim] fixed multicore sim for akaros
authorAndrew Waterman <waterman@s141.Millennium.Berkeley.EDU>
Sun, 29 May 2011 04:59:25 +0000 (21:59 -0700)
committerAndrew Waterman <waterman@s141.Millennium.Berkeley.EDU>
Sun, 29 May 2011 04:59:25 +0000 (21:59 -0700)
riscv/applink.cc
riscv/decode.h
riscv/insns/mfpcr.h
riscv/insns/mtpcr.h
riscv/mmu.h
riscv/processor.cc
riscv/processor.h
riscv/sim.cc
riscv/sim.h
riscv/trap.h

index 5ced3203cb0b669c326009f3afcd98429e55929d..476c10847e972ca4c426561aad561ac59bad099f 100644 (file)
@@ -112,7 +112,7 @@ int appserver_link_t::wait_for_packet()
         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");
+        demand(p.addr <= sim->memsz && p.addr+p.data_size <= sim->memsz, "out of bounds: 0x%llx",(unsigned long long)p.addr);
         memcpy(ackpacket.data,sim->mem+p.addr,p.data_size);
         ackpacket.data_size = p.data_size;
         break;
@@ -120,7 +120,7 @@ int appserver_link_t::wait_for_packet()
         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");
+        demand(p.addr <= sim->memsz && p.addr+p.data_size <= sim->memsz, "out of bounds: 0x%llx",(unsigned long long)p.addr);
         memcpy(sim->mem+p.addr,p.data,p.data_size);
         break;
       case APP_CMD_READ_CONTROL_REG:
index 7638de90b9926b45f72a376ada0a204d1ab886f8..496b31ad034e28237b541080ff28c66d6d94d8da 100644 (file)
@@ -45,6 +45,7 @@ const int JUMP_ALIGN_BITS = 1;
 #define SR_VM    0x0000000000010000ULL
 #define SR_ZERO  ~(SR_ET|SR_EF|SR_EV|SR_EC|SR_PS|SR_S|SR_UX|SR_SX|SR_IM|SR_VM)
 #define SR_IM_SHIFT 8
+#define IPI_IRQ 5
 #define TIMER_IRQ 7
 
 #define CAUSE_EXCCODE 0x000000FF
index c1f629ac2fdff5948f4a4e84adb35f1c8992f1d4..b72b850416fb3b115917bba3dd071276315c974f 100644 (file)
@@ -34,10 +34,18 @@ switch(insn.rtype.rs2)
     val = mmu.get_ptbr();
     break;
 
+  case 10:
+    val = id;
+    break;
+
   case 11:
     val = vecbanks;
     break;
 
+  case 12:
+    val = sim->num_cores();
+    break;
+
   case 17:
     fromhost = val = sim->get_fromhost();
     break;
index 2f0e1f42f0d6536dd1bf077141b0c4930465af08..46fbfdb23375ecd01955678a68a18adf178d6722 100644 (file)
@@ -19,6 +19,10 @@ switch(insn.rtype.rs2)
     compare = RS1;
     break;
 
+  case 7:
+    sim->send_ipi(RS1);
+    break;
+
   case 9:
     mmu.set_ptbr(RS1);
     break;
index 65186a5eb0555adee3af7c4989bcba78463feb51..4c2cfcf407635ba6944856483253b6a8ccf400a8 100644 (file)
@@ -12,16 +12,16 @@ const reg_t PPN_BITS = 8*sizeof(reg_t) - PGSHIFT;
 
 struct pte_t
 {
-  reg_t v  : 1;
+  reg_t t  : 1;
   reg_t e  : 1;
   reg_t r  : 1;
   reg_t d  : 1;
   reg_t ux : 1;
-  reg_t ur : 1;
   reg_t uw : 1;
+  reg_t ur : 1;
   reg_t sx : 1;
-  reg_t sr : 1;
   reg_t sw : 1;
+  reg_t sr : 1;
   reg_t unused1 : 2;
   reg_t ppn : PPN_BITS;
 };
@@ -176,10 +176,10 @@ private:
                 : fetch ? trap_instruction_access_fault
                 :         trap_load_access_fault;
 
-    if(!pte.v || tag != (addr >> PGSHIFT))
+    if(!pte.e || tag != (addr >> PGSHIFT))
     {
       pte = walk(addr);
-      if(!pte.v)
+      if(!pte.e)
         throw trap;
 
       tlb_data[idx] = pte;
@@ -200,16 +200,16 @@ private:
   
     if(!vm_enabled)
     {
-      pte.v = addr < memsz;
-      pte.e = 1;
+      pte.t = 0;
+      pte.e = addr < memsz;
       pte.r = pte.d = 0;
       pte.ur = pte.uw = pte.ux = pte.sr = pte.sw = pte.sx = 1;
       pte.ppn = addr >> PGSHIFT;
     }
     else
     {
-      pte.v = 0;
-  
+      pte.t = pte.e = 0;
+
       int lg_ptesz = sizeof(pte_t) == 4 ? 2
                    : sizeof(pte_t) == 8 ? 3
                    : 0;
@@ -217,22 +217,31 @@ private:
   
       reg_t base = ptbr;
   
-      for(int i = LEVELS-1; i >= 0; i++)
+      for(int i = LEVELS-1; i >= 0; i--)
       {
-        reg_t idx = addr >> (PGSHIFT + i*(PGSHIFT - lg_ptesz));
-        idx &= (1<<(PGSHIFT - lg_ptesz)) - 1;
+        int idxbits = PGSHIFT - lg_ptesz;
+        int shift = PGSHIFT + i*idxbits;
+        reg_t idx = addr >> shift;
+        idx &= (1 << idxbits) - 1;
   
         reg_t pte_addr = base + idx*sizeof(pte_t);
         if(pte_addr >= memsz)
           break;
   
         pte = *(pte_t*)(mem+pte_addr);
-        if(!pte.v || pte.e)
+        if(pte.e)
+        {
+          // if this PTE is from a larger PT, fake a leaf
+          // PTE so the TLB will work right
+          reg_t vpn = addr >> PGSHIFT;
+          pte.ppn += vpn & ((1<<(i*idxbits))-1);
+          break;
+        }
+        if(!pte.t)
           break;
   
         base = pte.ppn << PGSHIFT;
       }
-      pte.v &= pte.e;
     }
   
     return pte;
index 4e06da48b809ee972efd3b9fb956f89e01c1b56a..ae757b5c038ac447c87ee36aeaf20e0ca4d90d4e 100644 (file)
 processor_t::processor_t(sim_t* _sim, char* _mem, size_t _memsz)
   : sim(_sim), mmu(_mem,_memsz)
 {
-  memset(XPR,0,sizeof(XPR));
-  memset(FPR,0,sizeof(FPR));
-  pc = 0;
-  evec = 0;
-  epc = 0;
-  badvaddr = 0;
-  cause = 0;
-  pcr_k0 = 0;
-  pcr_k1 = 0;
-  tohost = 0;
-  fromhost = 0;
-  count = 0;
-  compare = 0;
-  cycle = 0;
-  set_sr(SR_S | SR_SX);  // SX ignored if 64b mode not supported
-  set_fsr(0);
-
-  // vector stuff
-  vecbanks = 0xff;
-  vecbanks_count = 8;
-  utidx = -1;
-  vlmax = 32;
-  vl = 0;
-  nxfpr_bank = 256;
-  nxpr_use = 32;
-  nfpr_use = 32;
-  for (int i=0; i<MAX_UTS; i++)
-    uts[i] = NULL;
-
   // a few assumptions about endianness, including freg_t union
   static_assert(BYTE_ORDER == LITTLE_ENDIAN);
   static_assert(sizeof(freg_t) == 8);
@@ -56,6 +27,8 @@ processor_t::processor_t(sim_t* _sim, char* _mem, size_t _memsz)
   dcsim = NULL;
   itlbsim = NULL;
   dtlbsim = NULL;
+
+  reset();
 }
 
 processor_t::~processor_t()
@@ -105,6 +78,41 @@ void processor_t::init(uint32_t _id, icsim_t* default_icache,
   #endif
 }
 
+void processor_t::reset()
+{
+  run = false;
+
+  memset(XPR,0,sizeof(XPR));
+  memset(FPR,0,sizeof(FPR));
+
+  pc = 0;
+  evec = 0;
+  epc = 0;
+  badvaddr = 0;
+  cause = 0;
+  pcr_k0 = 0;
+  pcr_k1 = 0;
+  tohost = 0;
+  fromhost = 0;
+  count = 0;
+  compare = 0;
+  cycle = 0;
+  set_sr(SR_S | SR_SX);  // SX ignored if 64b mode not supported
+  set_fsr(0);
+
+  // vector stuff
+  vecbanks = 0xff;
+  vecbanks_count = 8;
+  utidx = -1;
+  vlmax = 32;
+  vl = 0;
+  nxfpr_bank = 256;
+  nxpr_use = 32;
+  nfpr_use = 32;
+  for (int i=0; i<MAX_UTS; i++)
+    uts[i] = NULL;
+}
+
 void processor_t::set_sr(uint32_t val)
 {
   sr = val & ~SR_ZERO;
@@ -151,7 +159,7 @@ void processor_t::setvl(int vlapp)
 void processor_t::step(size_t n, bool noisy)
 {
   size_t i = 0;
-  while(1) try
+  while(run) try
   {
     for( ; i < n; i++)
     {
@@ -188,6 +196,10 @@ void processor_t::step(size_t n, bool noisy)
     if (cmd == vt_command_stop)
       return;
   }
+  catch(halt_t t)
+  {
+    reset();
+  }
 }
 
 void processor_t::take_trap(trap_t t, bool noisy)
@@ -206,6 +218,12 @@ void processor_t::take_trap(trap_t t, bool noisy)
   badvaddr = mmu.get_badvaddr();
 }
 
+void processor_t::deliver_ipi()
+{
+  cause |= 1 << (IPI_IRQ+CAUSE_IP_SHIFT);
+  run = true;
+}
+
 void processor_t::disasm(insn_t insn, reg_t pc)
 {
   printf("core %3d: 0x%016llx (0x%08x) ",id,(unsigned long long)pc,insn.bits);
index 1f458d584ba707763bb1eb41ef56297d1974bc78..28b7e28e79f7682cc61319a2e75322bf447422b1 100644 (file)
@@ -18,6 +18,7 @@ public:
   ~processor_t();
   void init(uint32_t _id, icsim_t* defualt_icache, icsim_t* default_dcache);
   void step(size_t n, bool noisy);
+  void deliver_ipi();
 
 private:
   sim_t* sim;
@@ -41,6 +42,8 @@ private:
   uint32_t count;
   uint32_t compare;
 
+  bool run;
+
   // unprivileged control registers
   uint32_t fsr;
 
@@ -54,6 +57,7 @@ private:
   reg_t cycle;
 
   // functions
+  void reset();
   void set_sr(uint32_t val);
   void set_fsr(uint32_t val);
   void take_trap(trap_t t, bool noisy);
index c503ccbb922bf150f4c9f01da00193acef31c9b4..ba8992fe9336dfef433c3c17de0c5613a1b0d451 100644 (file)
@@ -14,7 +14,7 @@ sim_t::sim_t(int _nprocs, size_t _memsz, appserver_link_t* _applink, icsim_t* de
 {
   demand(mem != MAP_FAILED, "couldn't allocate target machine's memory");
 
-  for(int i = 0; i < (int)procs.size(); i++)
+  for(int i = 0; i < (int)num_cores(); i++)
     procs[i].init(i, default_icache, default_dcache);
 
   applink->init(this);
@@ -37,10 +37,19 @@ reg_t sim_t::get_fromhost()
   return fromhost;
 }
 
+void sim_t::send_ipi(reg_t who)
+{
+  if(who < num_cores())
+    procs[who].deliver_ipi();
+}
+
 void sim_t::run(bool debug)
 {
   applink->wait_for_start();
 
+  // start core 0
+  send_ipi(0);
+
   while(1)
   {
     if(!debug)
@@ -93,7 +102,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 < (int)procs.size(); i++)
+    for(int i = 0; i < (int)num_cores(); i++)
       procs[i].step(interleave,noisy);
 }
 
@@ -131,7 +140,7 @@ void sim_t::interactive_run_proc(const std::string& cmd, const std::vector<std::
     return;
 
   int p = atoi(a[0].c_str());
-  if(p >= (int)procs.size())
+  if(p >= (int)num_cores())
     return;
 
   if(a.size() == 2)
@@ -151,7 +160,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 >= (int)procs.size())
+  if(p >= (int)num_cores())
     throw trap_illegal_instruction;
 
   return procs[p].pc;
@@ -164,7 +173,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 >= (int)procs.size() || r >= NXPR)
+  if(p >= (int)num_cores() || r >= NXPR)
     throw trap_illegal_instruction;
 
   return procs[p].XPR[r];
@@ -177,7 +186,7 @@ reg_t sim_t::get_freg(const std::vector<std::string>& args)
 
   int p = atoi(args[0].c_str());
   int r = atoi(args[1].c_str());
-  if(p >= (int)procs.size() || r >= NFPR)
+  if(p >= (int)num_cores() || r >= NFPR)
     throw trap_illegal_instruction;
 
   return procs[p].FPR[r];
@@ -189,7 +198,7 @@ reg_t sim_t::get_tohost(const std::vector<std::string>& args)
     throw trap_illegal_instruction;
 
   int p = atoi(args[0].c_str());
-  if(p >= (int)procs.size())
+  if(p >= (int)num_cores())
     throw trap_illegal_instruction;
 
   return procs[p].tohost;
@@ -223,14 +232,26 @@ void sim_t::interactive_fregd(const std::string& cmd, const std::vector<std::str
 
 reg_t sim_t::get_mem(const std::vector<std::string>& args)
 {
-  if(args.size() != 1)
+  if(args.size() != 1 && args.size() != 2)
     throw trap_illegal_instruction;
 
-  reg_t addr = strtol(args[0].c_str(),NULL,16), val;
+  std::string addr_str = args[0];
+  mmu_t mmu(mem, memsz);
+  mmu.set_supervisor(true);
+  if(args.size() == 2)
+  {
+    int p = atoi(args[0].c_str());
+    if(p >= (int)num_cores())
+      throw trap_illegal_instruction;
+    mmu.set_vm_enabled(!!(procs[p].sr & SR_VM));
+    mmu.set_ptbr(procs[p].mmu.get_ptbr());
+    addr_str = args[1];
+  }
+
+  reg_t addr = strtol(addr_str.c_str(),NULL,16), val;
   if(addr == LONG_MAX)
-    addr = strtoul(args[0].c_str(),NULL,16);
+    addr = strtoul(addr_str.c_str(),NULL,16);
 
-  mmu_t mmu(mem,memsz);
   switch(addr % 8)
   {
     case 0:
index c3f308e2e9421491c8ce2d3e06d659c42b5c4735..27d36a89363980ef4b971f691854efc678a8643c 100644 (file)
@@ -18,6 +18,9 @@ public:
 
   void set_tohost(reg_t val);
   reg_t get_fromhost();
+  void send_ipi(reg_t who);
+
+  size_t num_cores() { return procs.size(); }
 
 private:
   // global architected state
index 1a6db73bec38460a7a7034f77dda543290f80276..12a1c04b72392b6bbc71d3a0df97741566d02142 100644 (file)
@@ -36,6 +36,8 @@ enum trap_t
   NUM_TRAPS
 };
 
+struct halt_t {}; // thrown to stop the processor from running
+
 extern "C" const char* trap_name(trap_t t);
 
 #endif