diff options
-rw-r--r-- | riscv/execute.cc | 55 | ||||
-rwxr-xr-x | riscv/gen_icache | 8 | ||||
-rw-r--r-- | riscv/riscv.mk.in | 7 |
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}" ; \ |