diff options
Diffstat (limited to 'model/riscv_mem.sail')
-rw-r--r-- | model/riscv_mem.sail | 87 |
1 files changed, 53 insertions, 34 deletions
diff --git a/model/riscv_mem.sail b/model/riscv_mem.sail index d02c49d..b3fa37d 100644 --- a/model/riscv_mem.sail +++ b/model/riscv_mem.sail @@ -7,7 +7,7 @@ * metadata in addition to raw memory data. * * The external API for this module is - * {mem_read, mem_write_ea, mem_write_value_meta, mem_write_value} + * {mem_read, mem_read_meta, mem_write_ea, mem_write_value_meta, mem_write_value} * where mem_write_value is a special case of mem_write_value_meta that uses * a default value of the metadata. * @@ -19,43 +19,53 @@ function is_aligned_addr forall 'n. (addr : xlenbits, width : atom('n)) -> bool = unsigned(addr) % width == 0 -// only used for actual memory regions, to avoid MMIO effects -function phys_mem_read forall 'n, 0 < 'n <= max_mem_access . (t : AccessType(ext_access_type), paddr : xlenbits, width : atom('n), aq : bool, rl: bool, res : bool) -> MemoryOpResult(bits(8 * 'n)) = { - let result = (match (aq, rl, res) { - (false, false, false) => Some(read_ram(Read_plain, paddr, width)), - (true, false, false) => Some(read_ram(Read_RISCV_acquire, paddr, width)), - (true, true, false) => Some(read_ram(Read_RISCV_strong_acquire, paddr, width)), - (false, false, true) => Some(read_ram(Read_RISCV_reserved, paddr, width)), - (true, false, true) => Some(read_ram(Read_RISCV_reserved_acquire, paddr, width)), - (true, true, true) => Some(read_ram(Read_RISCV_reserved_strong_acquire, paddr, width)), +function read_kind_of_flags (aq : bool, rl : bool, res : bool) -> option(read_kind) = + match (aq, rl, res) { + (false, false, false) => Some(Read_plain), + (true, false, false) => Some(Read_RISCV_acquire), + (true, true, false) => Some(Read_RISCV_strong_acquire), + (false, false, true) => Some(Read_RISCV_reserved), + (true, false, true) => Some(Read_RISCV_reserved_acquire), + (true, true, true) => Some(Read_RISCV_reserved_strong_acquire), (false, true, false) => None(), /* should these be instead throwing error_not_implemented as below? */ (false, true, true) => None() - }) : option(bits(8 * 'n)); + } + +// only used for actual memory regions, to avoid MMIO effects +function phys_mem_read forall 'n, 0 < 'n <= max_mem_access . (t : AccessType(ext_access_type), paddr : xlenbits, width : atom('n), aq : bool, rl: bool, res : bool, meta : bool) -> MemoryOpResult((bits(8 * 'n), mem_meta)) = { + let result = (match read_kind_of_flags(aq, rl, res) { + Some(rk) => Some(read_ram(rk, paddr, width, meta)), + None() => None() + }) : option((bits(8 * 'n), mem_meta)); match (t, result) { (Execute(), None()) => MemException(E_Fetch_Access_Fault()), (Read(Data), None()) => MemException(E_Load_Access_Fault()), (_, None()) => MemException(E_SAMO_Access_Fault()), - (_, Some(v)) => { if get_config_print_mem() + (_, Some(v, m)) => { if get_config_print_mem() then print_mem("mem[" ^ to_str(t) ^ "," ^ BitStr(paddr) ^ "] -> " ^ BitStr(v)); - MemValue(v) } + MemValue(v, m) } } } /* dispatches to MMIO regions or physical memory regions depending on physical memory map */ -function checked_mem_read forall 'n, 0 < 'n <= max_mem_access . (t : AccessType(ext_access_type), paddr : xlenbits, width : atom('n), aq : bool, rl : bool, res: bool) -> MemoryOpResult(bits(8 * 'n)) = +function checked_mem_read forall 'n, 0 < 'n <= max_mem_access . (t : AccessType(ext_access_type), paddr : xlenbits, width : atom('n), aq : bool, rl : bool, res: bool, meta : bool) -> MemoryOpResult((bits(8 * 'n), mem_meta)) = if within_mmio_readable(paddr, width) - then mmio_read(paddr, width) + then MemoryOpResult_add_meta(mmio_read(t, paddr, width), default_meta) else if within_phys_mem(paddr, width) - then phys_mem_read(t, paddr, width, aq, rl, res) - else MemException(E_Load_Access_Fault()) + then phys_mem_read(t, paddr, width, aq, rl, res, meta) + else match t { + Execute() => MemException(E_Fetch_Access_Fault()), + Read(Data) => MemException(E_Load_Access_Fault()), + _ => MemException(E_SAMO_Access_Fault()) + } /* PMP checks if enabled */ -function pmp_mem_read forall 'n, 0 < 'n <= max_mem_access . (t : AccessType(ext_access_type), paddr : xlenbits, width : atom('n), aq : bool, rl : bool, res: bool) -> MemoryOpResult(bits(8 * 'n)) = +function pmp_mem_read forall 'n, 0 < 'n <= max_mem_access . (t : AccessType(ext_access_type), paddr : xlenbits, width : atom('n), aq : bool, rl : bool, res: bool, meta : bool) -> MemoryOpResult((bits(8 * 'n), mem_meta)) = if (~ (plat_enable_pmp ())) - then checked_mem_read(t, paddr, width, aq, rl, res) + then checked_mem_read(t, paddr, width, aq, rl, res, meta) else { match pmpCheck(paddr, width, t, effectivePrivilege(mstatus, cur_privilege)) { - None() => checked_mem_read(t, paddr, width, aq, rl, res), + None() => checked_mem_read(t, paddr, width, aq, rl, res, meta), Some(e) => MemException(e) } } @@ -70,7 +80,8 @@ function rvfi_read (addr, width, result) = { MemValue(v) => if width <= 8 then { rvfi_exec->rvfi_mem_rdata() = sail_zero_extend(v,64); rvfi_exec->rvfi_mem_rmask() = rvfi_encode_width_mask(width) } - else (), + else { rvfi_exec->rvfi_mem_rdata() = v[63..0]; + rvfi_exec->rvfi_mem_rmask() = 0xFF}, MemException(_) => () }; } @@ -81,24 +92,29 @@ $endif /* NOTE: The rreg effect is due to MMIO. */ $ifdef RVFI_DII -val mem_read : forall 'n, 0 < 'n <= max_mem_access . (AccessType(ext_access_type), xlenbits, atom('n), bool, bool, bool) -> MemoryOpResult(bits(8 * 'n)) effect {wreg, rmem, rreg, escape} +val mem_read : forall 'n, 0 < 'n <= max_mem_access . (AccessType(ext_access_type), xlenbits, atom('n), bool, bool, bool) -> MemoryOpResult(bits(8 * 'n)) effect {wreg, rmem, rmemt, rreg, escape} +val mem_read_meta : forall 'n, 0 < 'n <= max_mem_access . (AccessType(ext_access_type), xlenbits, atom('n), bool, bool, bool, bool) -> MemoryOpResult((bits(8 * 'n), mem_meta)) effect {wreg, rmem, rmemt, rreg, escape} $else -val mem_read : forall 'n, 0 < 'n <= max_mem_access . (AccessType(ext_access_type), xlenbits, atom('n), bool, bool, bool) -> MemoryOpResult(bits(8 * 'n)) effect {rmem, rreg, escape} +val mem_read : forall 'n, 0 < 'n <= max_mem_access . (AccessType(ext_access_type), xlenbits, atom('n), bool, bool, bool) -> MemoryOpResult(bits(8 * 'n)) effect {rmem, rmemt, rreg, escape} +val mem_read_meta : forall 'n, 0 < 'n <= max_mem_access . (AccessType(ext_access_type), xlenbits, atom('n), bool, bool, bool, bool) -> MemoryOpResult((bits(8 * 'n), mem_meta)) effect {rmem, rmemt, rreg, escape} $endif -function mem_read (typ, paddr, width, aq, rl, res) = { - let result : MemoryOpResult(bits(8 * 'n)) = - if (aq | res) & (~ (is_aligned_addr(paddr, width))) - then MemException(E_Load_Addr_Align()) - else match (aq, rl, res) { - (false, true, false) => throw(Error_not_implemented("load.rl")), - (false, true, true) => throw(Error_not_implemented("lr.rl")), - (_, _, _) => pmp_mem_read(typ, paddr, width, aq, rl, res) - }; - rvfi_read(paddr, width, result); - result +function mem_read_meta (typ, paddr, width, aq, rl, res, meta) = { + let result : MemoryOpResult((bits(8 * 'n), mem_meta)) = + if (aq | res) & (~ (is_aligned_addr(paddr, width))) + then MemException(E_Load_Addr_Align()) + else match (aq, rl, res) { + (false, true, false) => throw(Error_not_implemented("load.rl")), + (false, true, true) => throw(Error_not_implemented("lr.rl")), + (_, _, _) => pmp_mem_read(typ, paddr, width, aq, rl, res, meta) + }; + rvfi_read(paddr, width, MemoryOpResult_drop_meta(result)); + result } +function mem_read (typ, paddr, width, aq, rl, res) = + MemoryOpResult_drop_meta(mem_read_meta(typ, paddr, width, aq, rl, res, false)) + val mem_write_ea : forall 'n, 0 < 'n <= max_mem_access . (xlenbits, atom('n), bool, bool, bool) -> MemoryOpResult(unit) effect {eamem, escape} function mem_write_ea (addr, width, aq, rl, con) = { @@ -123,6 +139,9 @@ function rvfi_write (addr, width, value) = { if width <= 8 then { rvfi_exec->rvfi_mem_wdata() = sail_zero_extend(value,64); rvfi_exec->rvfi_mem_wmask() = rvfi_encode_width_mask(width); + } else { + rvfi_exec->rvfi_mem_wdata() = value[63..0]; + rvfi_exec->rvfi_mem_wmask() = 0xFF; } } $else |