aboutsummaryrefslogtreecommitdiff
path: root/riscv
diff options
context:
space:
mode:
authorliweiwei <liweiwei@iscas.ac.cn>2021-12-27 11:34:02 +0800
committerWeiwei Li <liweiwei@iscas.ac.cn>2022-01-30 11:33:03 +0800
commite205ca655c12df1ae0f6f3105bc8a671b049f161 (patch)
tree5994a35a1995f8dd55aefdf5db2ae00bb61f44f5 /riscv
parent456913b2c97d55993103594991a7ac73453465f8 (diff)
downloadspike-e205ca655c12df1ae0f6f3105bc8a671b049f161.zip
spike-e205ca655c12df1ae0f6f3105bc8a671b049f161.tar.gz
spike-e205ca655c12df1ae0f6f3105bc8a671b049f161.tar.bz2
add instructions function for cmo
prefetch.* are hints and share the encoding of ORI with rd = 0. so it can share the implementation of ORI and execute as no-ops
Diffstat (limited to 'riscv')
-rw-r--r--riscv/decode.h14
-rw-r--r--riscv/insns/cbo_clean.h4
-rw-r--r--riscv/insns/cbo_flush.h4
-rw-r--r--riscv/insns/cbo_inval.h9
-rw-r--r--riscv/insns/cbo_zero.h4
-rw-r--r--riscv/insns/ori.h1
-rw-r--r--riscv/mmu.h50
-rw-r--r--riscv/riscv.mk.in7
8 files changed, 79 insertions, 14 deletions
diff --git a/riscv/decode.h b/riscv/decode.h
index c2912e4..6f99cf5 100644
--- a/riscv/decode.h
+++ b/riscv/decode.h
@@ -278,6 +278,15 @@ private:
#define require_noover_widen(astart, asize, bstart, bsize) \
require(!is_overlapped_widen(astart, asize, bstart, bsize))
#define require_vm do { if (insn.v_vm() == 0) require(insn.rd() != 0);} while(0);
+#define require_envcfg(field) \
+ do { \
+ if (((STATE.prv != PRV_M) && (m##field == 0)) || \
+ ((STATE.prv == PRV_U && !STATE.v) && (s##field == 0))) \
+ throw trap_illegal_instruction(insn.bits()); \
+ else if (STATE.v && ((h##field == 0) || \
+ ((STATE.prv == PRV_U) && (s##field == 0)))) \
+ throw trap_virtual_instruction(insn.bits()); \
+ } while(0);
#define set_fp_exceptions ({ if (softfloat_exceptionFlags) { \
STATE.fflags->write(STATE.fflags->read() | softfloat_exceptionFlags); \
@@ -3038,6 +3047,11 @@ reg_t index[P.VU.vlmax]; \
WRITE_RD(sext_xlen(rd)); \
}
+#define DECLARE_XENVCFG_VARS(field) \
+ reg_t m##field = get_field(STATE.menvcfg->read(), MENVCFG_##field); \
+ reg_t s##field = get_field(STATE.senvcfg->read(), SENVCFG_##field); \
+ reg_t h##field = get_field(STATE.henvcfg->read(), HENVCFG_##field)
+
#define DEBUG_START 0x0
#define DEBUG_END (0x1000 - 1)
diff --git a/riscv/insns/cbo_clean.h b/riscv/insns/cbo_clean.h
new file mode 100644
index 0000000..201fa44
--- /dev/null
+++ b/riscv/insns/cbo_clean.h
@@ -0,0 +1,4 @@
+require_extension(EXT_ZICBOM);
+DECLARE_XENVCFG_VARS(CBCFE);
+require_envcfg(CBCFE);
+MMU.clean_inval(RS1, true, false);
diff --git a/riscv/insns/cbo_flush.h b/riscv/insns/cbo_flush.h
new file mode 100644
index 0000000..b17f5cf
--- /dev/null
+++ b/riscv/insns/cbo_flush.h
@@ -0,0 +1,4 @@
+require_extension(EXT_ZICBOM);
+DECLARE_XENVCFG_VARS(CBCFE);
+require_envcfg(CBCFE);
+MMU.clean_inval(RS1, true, true);
diff --git a/riscv/insns/cbo_inval.h b/riscv/insns/cbo_inval.h
new file mode 100644
index 0000000..bd80a6f
--- /dev/null
+++ b/riscv/insns/cbo_inval.h
@@ -0,0 +1,9 @@
+require_extension(EXT_ZICBOM);
+DECLARE_XENVCFG_VARS(CBIE);
+require_envcfg(CBIE);
+if (((STATE.prv != PRV_M) && (mCBIE == 1)) ||
+ ((!STATE.v && (STATE.prv == PRV_U)) && (sCBIE = 1)) ||
+ (STATE.v && ((hCBIE == 1) || ((STATE.prv == PRV_U) && (sCBIE== 0)))))
+ MMU.clean_inval(RS1, true, true);
+else
+ MMU.clean_inval(RS1, false, true);
diff --git a/riscv/insns/cbo_zero.h b/riscv/insns/cbo_zero.h
new file mode 100644
index 0000000..4bbe28d
--- /dev/null
+++ b/riscv/insns/cbo_zero.h
@@ -0,0 +1,4 @@
+require_extension(EXT_ZICBOZ);
+DECLARE_XENVCFG_VARS(CBZE);
+require_envcfg(CBZE);
+MMU.cbo_zero(RS1);
diff --git a/riscv/insns/ori.h b/riscv/insns/ori.h
index 6403c39..3aba1cb 100644
--- a/riscv/insns/ori.h
+++ b/riscv/insns/ori.h
@@ -1 +1,2 @@
+// prefetch.i/r/w hint when rd = 0 and i_imm[4:0] = 0/1/3
WRITE_RD(insn.i_imm() | RS1);
diff --git a/riscv/mmu.h b/riscv/mmu.h
index af11078..017b483 100644
--- a/riscv/mmu.h
+++ b/riscv/mmu.h
@@ -184,27 +184,30 @@ public:
} \
}
+ // AMO/Zicbom faults should be reported as store faults
+ #define convert_load_traps_to_store_traps(BODY) \
+ try { \
+ BODY \
+ } catch (trap_load_address_misaligned& t) { \
+ /* Misaligned fault will not be triggered by Zicbom */ \
+ throw trap_store_address_misaligned(t.has_gva(), t.get_tval(), t.get_tval2(), t.get_tinst()); \
+ } catch (trap_load_page_fault& t) { \
+ throw trap_store_page_fault(t.has_gva(), t.get_tval(), t.get_tval2(), t.get_tinst()); \
+ } catch (trap_load_access_fault& t) { \
+ throw trap_store_access_fault(t.has_gva(), t.get_tval(), t.get_tval2(), t.get_tinst()); \
+ } catch (trap_load_guest_page_fault& t) { \
+ throw trap_store_guest_page_fault(t.get_tval(), t.get_tval2(), t.get_tinst()); \
+ }
+
// template for functions that perform an atomic memory operation
#define amo_func(type) \
template<typename op> \
type##_t amo_##type(reg_t addr, op f) { \
- try { \
+ convert_load_traps_to_store_traps({ \
auto lhs = load_##type(addr, true); \
store_##type(addr, f(lhs)); \
return lhs; \
- } catch (trap_load_address_misaligned& t) { \
- /* AMO faults should be reported as store faults */ \
- throw trap_store_address_misaligned(t.has_gva(), t.get_tval(), t.get_tval2(), t.get_tinst()); \
- } catch (trap_load_page_fault& t) { \
- /* AMO faults should be reported as store faults */ \
- throw trap_store_page_fault(t.has_gva(), t.get_tval(), t.get_tval2(), t.get_tinst()); \
- } catch (trap_load_access_fault& t) { \
- /* AMO faults should be reported as store faults */ \
- throw trap_store_access_fault(t.has_gva(), t.get_tval(), t.get_tval2(), t.get_tinst()); \
- } catch (trap_load_guest_page_fault& t) { \
- /* AMO faults should be reported as store faults */ \
- throw trap_store_guest_page_fault(t.get_tval(), t.get_tval2(), t.get_tinst()); \
- } \
+ }) \
}
void store_float128(reg_t addr, float128_t val)
@@ -242,6 +245,25 @@ public:
amo_func(uint32)
amo_func(uint64)
+ void cbo_zero(reg_t addr) {
+ auto base = addr & ~(blocksz - 1);
+ for (size_t offset = 0; offset < blocksz; offset += 1)
+ store_uint8(base + offset, 0);
+ }
+
+ void clean_inval(reg_t addr, bool clean, bool inval) {
+ convert_load_traps_to_store_traps({
+ reg_t paddr = addr & ~(blocksz - 1);
+ paddr = translate(paddr, blocksz, LOAD, 0);
+ if (auto host_addr = sim->addr_to_mem(paddr)) {
+ if (tracer.interested_in_range(paddr, paddr + PGSIZE, LOAD))
+ tracer.clean_invalidate(paddr, blocksz, clean, inval);
+ } else {
+ throw trap_store_access_fault((proc) ? proc->state.v : false, addr, 0, 0);
+ }
+ })
+ }
+
inline void yield_load_reservation()
{
load_reservation_address = (reg_t)-1;
diff --git a/riscv/riscv.mk.in b/riscv/riscv.mk.in
index 5601466..075179b 100644
--- a/riscv/riscv.mk.in
+++ b/riscv/riscv.mk.in
@@ -1260,6 +1260,12 @@ riscv_insn_svinval = \
hinval_vvma \
hinval_gvma \
+riscv_insn_ext_cmo = \
+ cbo_clean \
+ cbo_flush \
+ cbo_inval \
+ cbo_zero \
+
riscv_insn_list = \
$(riscv_insn_ext_a) \
$(riscv_insn_ext_c) \
@@ -1276,6 +1282,7 @@ riscv_insn_list = \
$(riscv_insn_ext_p) \
$(riscv_insn_priv) \
$(riscv_insn_svinval) \
+ $(riscv_insn_ext_cmo) \
riscv_gen_srcs = \
$(addsuffix .cc,$(riscv_insn_list))