aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--riscv/execute.cc55
-rwxr-xr-xriscv/gen_icache8
-rw-r--r--riscv/riscv.mk.in7
3 files changed, 12 insertions, 58 deletions
diff --git a/riscv/execute.cc b/riscv/execute.cc
index ee8257f..62ae019 100644
--- a/riscv/execute.cc
+++ b/riscv/execute.cc
@@ -256,6 +256,7 @@ void processor_t::step(size_t n)
if (unlikely(slow_path()))
{
+ // Main simulation loop, slow path.
while (instret < n)
{
if (unlikely(!state.serialized && state.single_step == state.STEP_STEPPED)) {
@@ -280,49 +281,17 @@ void processor_t::step(size_t n)
}
else while (instret < n)
{
- // This code uses a modified Duff's Device to improve the performance
- // of executing instructions. While typical Duff's Devices are used
- // for software pipelining, the switch statement below primarily
- // benefits from separate call points for the fetch.func function call
- // found in each execute_insn. This function call is an indirect jump
- // that depends on the current instruction. By having an indirect jump
- // dedicated for each icache entry, you improve the performance of the
- // host's next address predictor. Each case in the switch statement
- // allows for the program flow to contine to the next case if it
- // corresponds to the next instruction in the program and instret is
- // still less than n.
- //
- // According to Andrew Waterman's recollection, this optimization
- // resulted in approximately a 2x performance increase.
-
- // This figures out where to jump to in the switch statement
- size_t idx = _mmu->icache_index(pc);
-
- // This gets the cached decoded instruction from the MMU. If the MMU
- // does not have the current pc cached, it will refill the MMU and
- // return the correct entry. ic_entry->data.func is the C++ function
- // corresponding to the instruction.
- auto ic_entry = _mmu->access_icache(pc);
-
- // This macro is included in "icache.h" included within the switch
- // statement below. The indirect jump corresponding to the instruction
- // is located within the execute_insn() function call.
- #define ICACHE_ACCESS(i) { \
- insn_fetch_t fetch = ic_entry->data; \
- pc = execute_insn(this, pc, fetch); \
- ic_entry = ic_entry->next; \
- if (i == mmu_t::ICACHE_ENTRIES-1) break; \
- if (unlikely(ic_entry->tag != pc)) break; \
- if (unlikely(instret+1 == n)) break; \
- instret++; \
- state.pc = pc; \
- }
-
- // This switch statement implements the modified Duff's device as
- // explained above.
- switch (idx) {
- // "icache.h" is generated by the gen_icache script
- #include "icache.h"
+ // Main simulation loop, fast path.
+ for (auto ic_entry = _mmu->access_icache(pc); ; ) {
+ auto fetch = ic_entry->data;
+ pc = execute_insn(this, pc, fetch);
+ ic_entry = ic_entry->next;
+ if (unlikely(ic_entry->tag != pc))
+ break;
+ if (unlikely(instret + 1 == n))
+ break;
+ instret++;
+ state.pc = pc;
}
advance_pc();
diff --git a/riscv/gen_icache b/riscv/gen_icache
deleted file mode 100755
index 67c0d69..0000000
--- a/riscv/gen_icache
+++ /dev/null
@@ -1,8 +0,0 @@
-#!/bin/sh
-i=0
-while [ $i -lt $1 ]
-do
- echo case $i: ICACHE_ACCESS\($i\)\;
- i=$((i+1))
-done
-echo
diff --git a/riscv/riscv.mk.in b/riscv/riscv.mk.in
index 055d6d1..622d2ad 100644
--- a/riscv/riscv.mk.in
+++ b/riscv/riscv.mk.in
@@ -63,7 +63,6 @@ riscv_srcs = \
riscv_test_srcs =
riscv_gen_hdrs = \
- icache.h \
insn_list.h \
@@ -1286,12 +1285,6 @@ riscv_insn_list = \
riscv_gen_srcs = \
$(addsuffix .cc,$(riscv_insn_list))
-icache_entries := `grep "ICACHE_ENTRIES =" $(src_dir)/riscv/mmu.h | sed 's/.* = \(.*\);/\1/'`
-
-icache.h: mmu.h
- $(src_dir)/riscv/gen_icache $(icache_entries) > $@.tmp
- mv $@.tmp $@
-
insn_list.h: $(src_dir)/riscv/riscv.mk.in
for insn in $(foreach insn,$(riscv_insn_list),$(subst .,_,$(insn))) ; do \
printf 'DEFINE_INSN(%s)\n' "$${insn}" ; \