From 605d638068d80b4977030bfbb56fd7376a9debe5 Mon Sep 17 00:00:00 2001 From: Andrew Waterman Date: Sat, 28 May 2011 21:59:25 -0700 Subject: [PATCH] [fesvr,xcc,sim] fixed multicore sim for akaros --- riscv/applink.cc | 4 +-- riscv/decode.h | 1 + riscv/insns/mfpcr.h | 8 +++++ riscv/insns/mtpcr.h | 4 +++ riscv/mmu.h | 37 +++++++++++++-------- riscv/processor.cc | 78 ++++++++++++++++++++++++++++----------------- riscv/processor.h | 4 +++ riscv/sim.cc | 43 ++++++++++++++++++------- riscv/sim.h | 3 ++ riscv/trap.h | 2 ++ 10 files changed, 127 insertions(+), 57 deletions(-) diff --git a/riscv/applink.cc b/riscv/applink.cc index 5ced320..476c108 100644 --- a/riscv/applink.cc +++ b/riscv/applink.cc @@ -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: diff --git a/riscv/decode.h b/riscv/decode.h index 7638de9..496b31a 100644 --- a/riscv/decode.h +++ b/riscv/decode.h @@ -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 diff --git a/riscv/insns/mfpcr.h b/riscv/insns/mfpcr.h index c1f629a..b72b850 100644 --- a/riscv/insns/mfpcr.h +++ b/riscv/insns/mfpcr.h @@ -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; diff --git a/riscv/insns/mtpcr.h b/riscv/insns/mtpcr.h index 2f0e1f4..46fbfdb 100644 --- a/riscv/insns/mtpcr.h +++ b/riscv/insns/mtpcr.h @@ -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; diff --git a/riscv/mmu.h b/riscv/mmu.h index 65186a5..4c2cfcf 100644 --- a/riscv/mmu.h +++ b/riscv/mmu.h @@ -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; diff --git a/riscv/processor.cc b/riscv/processor.cc index 4e06da4..ae757b5 100644 --- a/riscv/processor.cc +++ b/riscv/processor.cc @@ -15,35 +15,6 @@ 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; iinit(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= (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& 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& 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& 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& 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& 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: diff --git a/riscv/sim.h b/riscv/sim.h index c3f308e..27d36a8 100644 --- a/riscv/sim.h +++ b/riscv/sim.h @@ -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 diff --git a/riscv/trap.h b/riscv/trap.h index 1a6db73..12a1c04 100644 --- a/riscv/trap.h +++ b/riscv/trap.h @@ -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 -- 2.30.2