DEFINE_XAMO(amominu_d)
DEFINE_XAMO(amomaxu_d)
+ DEFINE_XAMO(lr_w)
+ DEFINE_XAMO(sc_w)
+ DEFINE_XAMO(lr_d)
+ DEFINE_XAMO(sc_d)
+
DEFINE_FLOAD(flw)
DEFINE_FLOAD(fld)
--- /dev/null
+require_xpr64;
+RD = mmu.load_reserved_int64(RS1);
--- /dev/null
+RD = mmu.load_reserved_int32(RS1);
--- /dev/null
+require_xpr64;
+RD = mmu.store_conditional_uint64(RS1, RS2);
--- /dev/null
+RD = mmu.store_conditional_uint32(RS1, RS2);
void sim_t::interactive_run(const std::string& cmd, const std::vector<std::string>& args, bool noisy)
{
- if (args.size())
- step_all(atoll(args[0].c_str()), 1, noisy);
- else
- while (1) step_all(1, 1, noisy);
+ size_t steps = args.size() ? atoll(args[0].c_str()) : -1;
+ step(steps, noisy);
}
void sim_t::interactive_run_proc_noisy(const std::string& cmd, const std::vector<std::string>& args)
if(p >= (int)num_cores())
return;
- if(a.size() == 2)
- procs[p]->step(atoi(a[1].c_str()),noisy);
- else
- while (1) procs[p]->step(1, noisy);
+ size_t steps = a.size() > 1 ? atoll(a[1].c_str()) : -1;
+ procs[p]->step(steps, noisy);
}
void sim_t::interactive_quit(const std::string& cmd, const std::vector<std::string>& args)
if(cmd == "while" && current != val)
break;
- step_all(1,1,false);
+ step(1, false);
}
}
mmu_t::mmu_t(char* _mem, size_t _memsz)
: mem(_mem), memsz(_memsz), badvaddr(0),
- ptbr(0), sr(SR_S)
+ ptbr(0)
{
- flush_tlb();
+ set_sr(SR_S);
}
mmu_t::~mmu_t()
flush_icache();
}
+void mmu_t::set_sr(uint32_t _sr)
+{
+ sr = _sr;
+ flush_tlb();
+ yield_load_reservation();
+}
+
reg_t mmu_t::refill_tlb(reg_t addr, reg_t bytes, bool store, bool fetch)
{
reg_t idx = (addr >> PGSHIFT) % TLB_ENTRIES;
} \
reg_t paddr = translate(addr, sizeof(type##_t), false, false); \
return *(type##_t*)(mem + paddr); \
+ } \
+ type##_t load_reserved_##type(reg_t addr) { \
+ load_reservation = addr; \
+ return load_##type(addr); \
}
// load value from memory at aligned address; zero extend to register width
} \
reg_t paddr = translate(addr, sizeof(type##_t), true, false); \
*(type##_t*)(mem + paddr) = val; \
+ } \
+ reg_t store_conditional_##type(reg_t addr, type##_t val) { \
+ if (addr == load_reservation) { \
+ store_##type(addr, val); \
+ return 0; \
+ } else return 1; \
}
// store value to memory at aligned address
// get/set the page table base register
reg_t get_ptbr() { return ptbr; }
void set_ptbr(reg_t addr) { ptbr = addr & ~(PGSIZE-1); flush_tlb(); }
- // keep the MMU in sync with processor mode
- void set_sr(uint32_t _sr) { sr = _sr; }
+ void yield_load_reservation() { load_reservation = -1; }
+ void set_sr(uint32_t sr); // keep the MMU in sync with the processor mode
// flush the TLB and instruction cache
void flush_tlb();
private:
char* mem;
size_t memsz;
+ reg_t load_reservation;
reg_t badvaddr;
reg_t ptbr;
uint32_t sr;
DECLARE_INSN(vfsstw, 0x150f, 0x1ffff)
DECLARE_INSN(remuw, 0x7bb, 0x1ffff)
DECLARE_INSN(fmin_d, 0x180d3, 0x1ffff)
+DECLARE_INSN(lr_w, 0x1012b, 0x3fffff)
DECLARE_INSN(vlsthu, 0x128b, 0x1ffff)
DECLARE_INSN(c_swsp, 0x8, 0x1f)
DECLARE_INSN(bltu, 0x363, 0x3ff)
DECLARE_INSN(vsstw, 0x110f, 0x1ffff)
DECLARE_INSN(mtfsr, 0x1f053, 0x3fffff)
DECLARE_INSN(vssth, 0x108f, 0x1ffff)
+DECLARE_INSN(sc_w, 0x1052b, 0x1ffff)
DECLARE_INSN(rem, 0x733, 0x1ffff)
DECLARE_INSN(srliw, 0x29b, 0x3f83ff)
DECLARE_INSN(lui, 0x37, 0x7f)
DECLARE_INSN(vssegd, 0x218f, 0x1ffff)
DECLARE_INSN(srl, 0x2b3, 0x1ffff)
DECLARE_INSN(venqcmd, 0x2b7b, 0xf801ffff)
+DECLARE_INSN(fsub_d, 0x10d3, 0x1f1ff)
DECLARE_INSN(vfmts, 0x1973, 0x1ffff)
DECLARE_INSN(venqimm1, 0x2f7b, 0xf801ffff)
DECLARE_INSN(fsgnjx_s, 0x7053, 0x1ffff)
DECLARE_INSN(fnmadd_d, 0xcf, 0x1ff)
DECLARE_INSN(amoadd_d, 0x1ab, 0x1ffff)
DECLARE_INSN(c_sw, 0xd, 0x1f)
-DECLARE_INSN(amomax_w, 0x152b, 0x1ffff)
+DECLARE_INSN(lr_d, 0x101ab, 0x3fffff)
DECLARE_INSN(c_move, 0x2, 0x801f)
DECLARE_INSN(fmovn, 0xef7, 0x1ffff)
DECLARE_INSN(c_fsw, 0x16, 0x1f)
DECLARE_INSN(vflsegd, 0x258b, 0x1ffff)
DECLARE_INSN(vflsegw, 0x250b, 0x1ffff)
DECLARE_INSN(vlsegsth, 0x88b, 0xfff)
+DECLARE_INSN(amomax_w, 0x152b, 0x1ffff)
DECLARE_INSN(fsgnj_d, 0x50d3, 0x1ffff)
DECLARE_INSN(vflsegstw, 0xd0b, 0xfff)
DECLARE_INSN(c_sub, 0x801a, 0x801f)
DECLARE_INSN(c_add, 0x1a, 0x801f)
DECLARE_INSN(fcvt_lu_d, 0x90d3, 0x3ff1ff)
DECLARE_INSN(vfld, 0x58b, 0x3fffff)
-DECLARE_INSN(fsub_d, 0x10d3, 0x1f1ff)
+DECLARE_INSN(sc_d, 0x105ab, 0x1ffff)
DECLARE_INSN(fmadd_s, 0x43, 0x1ff)
DECLARE_INSN(fcvt_w_s, 0xa053, 0x3ff1ff)
DECLARE_INSN(vssegh, 0x208f, 0x1ffff)
#endif
sr &= ~SR_ZERO;
mmu.set_sr(sr);
- mmu.flush_tlb();
- // set the fixed-point register length
- xprlen = ((sr & SR_S) ? (sr & SR_S64) : (sr & SR_U64)) ? 64 : 32;
break;
case PCR_EPC:
epc = val;
regfile_t<reg_t, NXPR, true> XPR;
regfile_t<freg_t, NFPR, false> FPR;
reg_t pc;
-
- // counters
reg_t cycle;
// privileged control registers
uint32_t count;
uint32_t compare;
- // # of bits in an XPR (32 or 64). (redundant with sr)
- int xprlen;
-
bool run; // !reset
// functions
sim_t::sim_t(int _nprocs, int mem_mb, const std::vector<std::string>& args)
: htif(new htif_isasim_t(this, args)),
- procs(_nprocs)
+ procs(_nprocs), current_step(0), current_proc(0)
{
// allocate target machine's memory, shrinking it as necessary
// until the allocation succeeds
while (!htif->done())
{
if(!debug)
- step_all(10000, 1000, false);
+ step(INTERLEAVE, false);
else
interactive();
}
}
-void sim_t::step_all(size_t n, size_t interleave, bool noisy)
+void sim_t::step(size_t n, bool noisy)
{
- htif->tick();
- for(size_t j = 0; j < n; j+=interleave)
+ for (size_t i = 0, steps = 0; i < n; i += steps)
{
- for(int i = 0; i < (int)num_cores(); i++)
- procs[i]->step(interleave,noisy);
+ htif->tick();
+
+ steps = std::min(n - i, INTERLEAVE - current_step);
+ procs[current_proc]->step(steps, noisy);
+
+ current_step += steps;
+ if (current_step == INTERLEAVE)
+ {
+ current_step = 0;
+ procs[current_proc]->mmu.yield_load_reservation();
+ if (++current_proc == num_cores())
+ current_proc = 0;
+ }
}
}
private:
htif_isasim_t* htif;
-
- // main memory, shared between processors
- char* mem;
+ char* mem; // main memory
size_t memsz; // memory size in bytes
mmu_t* mmu; // debug port into main memory
-
- // processors
std::vector<processor_t*> procs;
- // run each processor for n instructions; interleave instructions are
- // run on a processor before moving on to the next processor.
- // interleave must divide n.
- // if noisy, print out the instructions as they execute.
- void step_all(size_t n, size_t interleave, bool noisy);
+ void step(size_t n, bool noisy); // step through simulation
+ static const size_t INTERLEAVE = 5000;
+ size_t current_step;
+ size_t current_proc;
// presents a prompt for introspection into the simulation
void interactive();