aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrew Waterman <waterman@s141.Millennium.Berkeley.EDU>2011-05-28 21:59:25 -0700
committerAndrew Waterman <waterman@s141.Millennium.Berkeley.EDU>2011-05-28 21:59:25 -0700
commit605d638068d80b4977030bfbb56fd7376a9debe5 (patch)
tree8ef668bb072a1a3c8fa7a9b6889afaecf887597d
parentc42bce582a7987856f63165abddaf4cd48e3b448 (diff)
downloadspike-605d638068d80b4977030bfbb56fd7376a9debe5.zip
spike-605d638068d80b4977030bfbb56fd7376a9debe5.tar.gz
spike-605d638068d80b4977030bfbb56fd7376a9debe5.tar.bz2
[fesvr,xcc,sim] fixed multicore sim for akaros
-rw-r--r--riscv/applink.cc4
-rw-r--r--riscv/decode.h1
-rw-r--r--riscv/insns/mfpcr.h8
-rw-r--r--riscv/insns/mtpcr.h4
-rw-r--r--riscv/mmu.h37
-rw-r--r--riscv/processor.cc78
-rw-r--r--riscv/processor.h4
-rw-r--r--riscv/sim.cc43
-rw-r--r--riscv/sim.h3
-rw-r--r--riscv/trap.h2
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; 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);
diff --git a/riscv/processor.h b/riscv/processor.h
index 1f458d5..28b7e28 100644
--- a/riscv/processor.h
+++ b/riscv/processor.h
@@ -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);
diff --git a/riscv/sim.cc b/riscv/sim.cc
index c503ccb..ba8992f 100644
--- a/riscv/sim.cc
+++ b/riscv/sim.cc
@@ -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:
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