diff options
author | Andrew Waterman <aswaterman@gmail.com> | 2018-07-10 09:56:32 -0700 |
---|---|---|
committer | GitHub <noreply@github.com> | 2018-07-10 09:56:32 -0700 |
commit | 95487c248a6eb660b9bd1aa49e28da5a1ab21059 (patch) | |
tree | 011bc774a4cb6eb647f0fbaca3cb4bc41cfe277b /riscv | |
parent | cc50a327a552f1aa84679c8d3020ec40edc2948f (diff) | |
download | spike-95487c248a6eb660b9bd1aa49e28da5a1ab21059.zip spike-95487c248a6eb660b9bd1aa49e28da5a1ab21059.tar.gz spike-95487c248a6eb660b9bd1aa49e28da5a1ab21059.tar.bz2 |
Refactor and fix LR/SC implementation (#217)
- Use physical addresses to avoid homonym ambiguity (closes #215)
- Yield reservation on store-conditional (https://github.com/riscv/riscv-isa-manual/commit/03a5e722fc0fe7b94dd0a49f550ff7b41a63f612)
- Don't yield reservation on exceptions (it's no longer required).
Diffstat (limited to 'riscv')
-rw-r--r-- | riscv/insns/lr_d.h | 2 | ||||
-rw-r--r-- | riscv/insns/lr_w.h | 2 | ||||
-rw-r--r-- | riscv/insns/sc_d.h | 4 | ||||
-rw-r--r-- | riscv/insns/sc_w.h | 4 | ||||
-rw-r--r-- | riscv/mmu.cc | 1 | ||||
-rw-r--r-- | riscv/mmu.h | 24 | ||||
-rw-r--r-- | riscv/processor.cc | 3 | ||||
-rw-r--r-- | riscv/processor.h | 3 | ||||
-rw-r--r-- | riscv/sim.cc | 2 |
9 files changed, 34 insertions, 11 deletions
diff --git a/riscv/insns/lr_d.h b/riscv/insns/lr_d.h index 077590f..52090c3 100644 --- a/riscv/insns/lr_d.h +++ b/riscv/insns/lr_d.h @@ -1,4 +1,4 @@ require_extension('A'); require_rv64; -p->get_state()->load_reservation = RS1; +MMU.acquire_load_reservation(RS1); WRITE_RD(MMU.load_int64(RS1)); diff --git a/riscv/insns/lr_w.h b/riscv/insns/lr_w.h index 767251f..c5845a6 100644 --- a/riscv/insns/lr_w.h +++ b/riscv/insns/lr_w.h @@ -1,3 +1,3 @@ require_extension('A'); -p->get_state()->load_reservation = RS1; +MMU.acquire_load_reservation(RS1); WRITE_RD(MMU.load_int32(RS1)); diff --git a/riscv/insns/sc_d.h b/riscv/insns/sc_d.h index 01a45ce..aeeabd3 100644 --- a/riscv/insns/sc_d.h +++ b/riscv/insns/sc_d.h @@ -1,9 +1,11 @@ require_extension('A'); require_rv64; -if (RS1 == p->get_state()->load_reservation) +if (MMU.check_load_reservation(RS1)) { MMU.store_uint64(RS1, RS2); WRITE_RD(0); } else WRITE_RD(1); + +MMU.yield_load_reservation(); diff --git a/riscv/insns/sc_w.h b/riscv/insns/sc_w.h index 68ec577..4b4be50 100644 --- a/riscv/insns/sc_w.h +++ b/riscv/insns/sc_w.h @@ -1,8 +1,10 @@ require_extension('A'); -if (RS1 == p->get_state()->load_reservation) +if (MMU.check_load_reservation(RS1)) { MMU.store_uint32(RS1, RS2); WRITE_RD(0); } else WRITE_RD(1); + +MMU.yield_load_reservation(); diff --git a/riscv/mmu.cc b/riscv/mmu.cc index 3a0bd39..021f587 100644 --- a/riscv/mmu.cc +++ b/riscv/mmu.cc @@ -12,6 +12,7 @@ mmu_t::mmu_t(simif_t* sim, processor_t* proc) matched_trigger(NULL) { flush_tlb(); + yield_load_reservation(); } mmu_t::~mmu_t() diff --git a/riscv/mmu.h b/riscv/mmu.h index 4380448..715d839 100644 --- a/riscv/mmu.h +++ b/riscv/mmu.h @@ -180,6 +180,29 @@ public: amo_func(uint32) amo_func(uint64) + inline void yield_load_reservation() + { + load_reservation_address = (reg_t)-1; + } + + inline void acquire_load_reservation(reg_t vaddr) + { + reg_t paddr = translate(vaddr, LOAD); + if (auto host_addr = sim->addr_to_mem(paddr)) + load_reservation_address = refill_tlb(vaddr, paddr, host_addr, LOAD).target_offset + vaddr; + else + throw trap_load_access_fault(vaddr); // disallow LR to I/O space + } + + inline bool check_load_reservation(reg_t vaddr) + { + reg_t paddr = translate(vaddr, STORE); + if (auto host_addr = sim->addr_to_mem(paddr)) + return load_reservation_address == refill_tlb(vaddr, paddr, host_addr, STORE).target_offset + vaddr; + else + throw trap_store_access_fault(vaddr); // disallow SC to I/O space + } + static const reg_t ICACHE_ENTRIES = 1024; inline size_t icache_index(reg_t addr) @@ -261,6 +284,7 @@ private: simif_t* sim; processor_t* proc; memtracer_list_t tracer; + reg_t load_reservation_address; uint16_t fetch_temp; // implement an instruction cache for simulator performance diff --git a/riscv/processor.cc b/riscv/processor.cc index 90266b9..9fc5d5f 100644 --- a/riscv/processor.cc +++ b/riscv/processor.cc @@ -121,7 +121,6 @@ void state_t::reset(reg_t max_isa) misa = max_isa; prv = PRV_M; pc = DEFAULT_RSTVEC; - load_reservation = -1; tselect = 0; for (unsigned int i = 0; i < num_triggers; i++) mcontrol[i].type = 2; @@ -298,8 +297,6 @@ void processor_t::take_trap(trap_t& t, reg_t epc) set_csr(CSR_MSTATUS, s); set_privilege(PRV_M); } - - yield_load_reservation(); } void processor_t::disasm(insn_t insn) diff --git a/riscv/processor.h b/riscv/processor.h index 3e67215..fd90ce3 100644 --- a/riscv/processor.h +++ b/riscv/processor.h @@ -135,8 +135,6 @@ struct state_t STEP_STEPPED } single_step; - reg_t load_reservation; - #ifdef RISCV_ENABLE_COMMITLOG commit_log_reg_t log_reg_write; reg_t last_inst_priv; @@ -197,7 +195,6 @@ public: } reg_t legalize_privilege(reg_t); void set_privilege(reg_t); - void yield_load_reservation() { state.load_reservation = (reg_t)-1; } void update_histogram(reg_t pc); const disassembler_t* get_disassembler() { return disassembler; } diff --git a/riscv/sim.cc b/riscv/sim.cc index c9bbac0..b7080f0 100644 --- a/riscv/sim.cc +++ b/riscv/sim.cc @@ -109,7 +109,7 @@ void sim_t::step(size_t n) if (current_step == INTERLEAVE) { current_step = 0; - procs[current_proc]->yield_load_reservation(); + procs[current_proc]->get_mmu()->yield_load_reservation(); if (++current_proc == procs.size()) { current_proc = 0; clint->increment(INTERLEAVE / INSNS_PER_RTC_TICK); |