aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrew Waterman <aswaterman@gmail.com>2018-07-10 09:56:32 -0700
committerGitHub <noreply@github.com>2018-07-10 09:56:32 -0700
commit95487c248a6eb660b9bd1aa49e28da5a1ab21059 (patch)
tree011bc774a4cb6eb647f0fbaca3cb4bc41cfe277b
parentcc50a327a552f1aa84679c8d3020ec40edc2948f (diff)
downloadspike-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).
-rw-r--r--riscv/insns/lr_d.h2
-rw-r--r--riscv/insns/lr_w.h2
-rw-r--r--riscv/insns/sc_d.h4
-rw-r--r--riscv/insns/sc_w.h4
-rw-r--r--riscv/mmu.cc1
-rw-r--r--riscv/mmu.h24
-rw-r--r--riscv/processor.cc3
-rw-r--r--riscv/processor.h3
-rw-r--r--riscv/sim.cc2
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);