diff options
Diffstat (limited to 'model')
-rw-r--r-- | model/riscv_analysis.sail | 176 | ||||
-rw-r--r-- | model/riscv_fetch_rvfi.sail | 2 | ||||
-rw-r--r-- | model/riscv_insts_base.sail | 46 | ||||
-rw-r--r-- | model/riscv_pc_access.sail | 10 | ||||
-rw-r--r-- | model/riscv_platform.sail | 9 | ||||
-rw-r--r-- | model/riscv_step_rvfi.sail | 2 |
6 files changed, 240 insertions, 5 deletions
diff --git a/model/riscv_analysis.sail b/model/riscv_analysis.sail index 34572f8..ec8c96f 100644 --- a/model/riscv_analysis.sail +++ b/model/riscv_analysis.sail @@ -10,6 +10,8 @@ let GPRstr : vector(32, dec, string) = [ "x31", "x30", "x29", "x28", "x27", "x26 let CIA_fp = RFull("CIA") let NIA_fp = RFull("NIA") +$ifndef FEATURE_UNION_BARRIER + function initial_analysis (instr:ast) -> (regfps,regfps,regfps,niafps,diafp,instruction_kind) = { iR = [| |] : regfps; oR = [| |] : regfps; @@ -180,3 +182,177 @@ function initial_analysis (instr:ast) -> (regfps,regfps,regfps,niafps,diafp,inst }; (iR,oR,aR,Nias,Dia,ik) } + +$else + +function initial_analysis (instr:ast) -> (regfps,regfps,regfps,niafps,diafp,instruction_kind) = { + iR = [| |] : regfps; + oR = [| |] : regfps; + aR = [| |] : regfps; + ik = IK_simple() : instruction_kind; + Nias = [| NIAFP_successor() |] : niafps; + Dia = DIAFP_none() : diafp; + + match instr { + EBREAK() => (), + UTYPE(imm, rd, op) => { + if (rd == 0) then () else oR = RFull(GPRstr[rd]) :: oR; + }, + RISCV_JAL(imm, rd) => { + if (rd == 0) then () else oR = RFull(GPRstr[rd]) :: oR; + let offset : bits(64) = EXTS(imm) in + Nias = [| NIAFP_concrete_address (PC + offset) |]; + ik = IK_branch(); + }, + RISCV_JALR(imm, rs, rd) => { + if (rs == 0) then () else iR = RFull(GPRstr[rs]) :: iR; + if (rd == 0) then () else oR = RFull(GPRstr[rd]) :: oR; + let offset : bits(64) = EXTS(imm) in + Nias = [| NIAFP_indirect_address() |]; + ik = IK_branch(); + }, + BTYPE(imm, rs2, rs1, op) => { + if (rs2 == 0) then () else iR = RFull(GPRstr[rs2]) :: iR; + if (rs1 == 0) then () else iR = RFull(GPRstr[rs1]) :: iR; + ik = IK_branch(); + let offset : bits(64) = EXTS(imm) in + Nias = [| NIAFP_concrete_address(PC + offset), NIAFP_successor() |]; + }, + ITYPE(imm, rs, rd, op) => { + if (rs == 0) then () else iR = RFull(GPRstr[rs]) :: iR; + if (rd == 0) then () else oR = RFull(GPRstr[rd]) :: oR; + }, + SHIFTIOP(imm, rs, rd, op) => { + if (rs == 0) then () else iR = RFull(GPRstr[rs]) :: iR; + if (rd == 0) then () else oR = RFull(GPRstr[rd]) :: oR; + }, + RTYPE(rs2, rs1, rd, op) => { + if (rs2 == 0) then () else iR = RFull(GPRstr[rs2]) :: iR; + if (rs1 == 0) then () else iR = RFull(GPRstr[rs1]) :: iR; + if (rd == 0) then () else oR = RFull(GPRstr[rd]) :: oR; + }, + CSR(csr, rs1, rd, is_imm, op) => { + let isWrite : bool = match op { + CSRRW => true, + _ => if is_imm then unsigned(rs1) != 0 else unsigned(rs1) != 0 + }; + iR = RFull(csr_name(csr)) :: iR; + if ~(is_imm) then { + iR = RFull(GPRstr[rs1]) :: iR; + }; + if isWrite then { + oR = RFull(csr_name(csr)) :: oR; + }; + oR = RFull(GPRstr[rd]) :: oR; + }, + LOAD(imm, rs, rd, unsign, width, aq, rl) => { /* XXX "unsigned" causes name conflict in lem shallow embedding... */ + if (rs == 0) then () else iR = RFull(GPRstr[rs]) :: iR; + if (rd == 0) then () else oR = RFull(GPRstr[rd]) :: oR; + aR = iR; + ik = + match (aq, rl) { + (false, false) => IK_mem_read (Read_plain), + (true, false) => IK_mem_read (Read_RISCV_acquire), + (true, true) => IK_mem_read (Read_RISCV_strong_acquire), + + _ => internal_error("LOAD type not implemented in initial_analysis") + } + }, + STORE(imm, rs2, rs1, width, aq, rl) => { + if (rs2 == 0) then () else iR = RFull(GPRstr[rs2]) :: iR; + if (rs1 == 0) then () else iR = RFull(GPRstr[rs1]) :: iR; + if (rs1 == 0) then () else aR = RFull(GPRstr[rs1]) :: aR; + ik = + match (aq, rl) { + (false, false) => IK_mem_write (Write_plain), + (false, true) => IK_mem_write (Write_RISCV_release), + (true, true) => IK_mem_write (Write_RISCV_strong_release), + + _ => internal_error("STORE type not implemented in initial_analysis") + } + }, + ADDIW(imm, rs, rd) => { + if (rs == 0) then () else iR = RFull(GPRstr[rs]) :: iR; + if (rd == 0) then () else oR = RFull(GPRstr[rd]) :: oR; + }, + SHIFTW(imm, rs, rd, op) => { + if (rs == 0) then () else iR = RFull(GPRstr[rs]) :: iR; + if (rd == 0) then () else oR = RFull(GPRstr[rd]) :: oR; + }, + RTYPEW(rs2, rs1, rd, op) => { + if (rs2 == 0) then () else iR = RFull(GPRstr[rs2]) :: iR; + if (rs1 == 0) then () else iR = RFull(GPRstr[rs1]) :: iR; + if (rd == 0) then () else oR = RFull(GPRstr[rd]) :: oR; + }, + FENCE(pred, succ) => { + ik = + match (pred, succ) { + (_ : bits(2) @ 0b11, _ : bits(2) @ 0b11) => IK_barrier (Barrier_RISCV_rw_rw ()), + (_ : bits(2) @ 0b10, _ : bits(2) @ 0b11) => IK_barrier (Barrier_RISCV_r_rw ()), + (_ : bits(2) @ 0b10, _ : bits(2) @ 0b10) => IK_barrier (Barrier_RISCV_r_r ()), + (_ : bits(2) @ 0b11, _ : bits(2) @ 0b01) => IK_barrier (Barrier_RISCV_rw_w ()), + (_ : bits(2) @ 0b01, _ : bits(2) @ 0b01) => IK_barrier (Barrier_RISCV_w_w ()), + (_ : bits(2) @ 0b01, _ : bits(2) @ 0b11) => IK_barrier (Barrier_RISCV_w_rw ()), + (_ : bits(2) @ 0b11, _ : bits(2) @ 0b10) => IK_barrier (Barrier_RISCV_rw_r ()), + (_ : bits(2) @ 0b10, _ : bits(2) @ 0b01) => IK_barrier (Barrier_RISCV_r_w ()), + (_ : bits(2) @ 0b01, _ : bits(2) @ 0b10) => IK_barrier (Barrier_RISCV_w_r ()), + + (_ : bits(2) @ 0b00, _ : bits(2) @ 0b00) => IK_simple (), + + _ => internal_error("barrier type not implemented in initial_analysis") + }; + }, + FENCE_TSO(pred, succ) => { + ik = + match (pred, succ) { + (_ : bits(2) @ 0b11, _ : bits(2) @ 0b11) => IK_barrier (Barrier_RISCV_tso ()), + _ => internal_error("barrier type not implemented in initial_analysis") + }; + }, + FENCEI() => { + ik = IK_simple (); // for RMEM, should morally be Barrier_RISCV_i + }, + LOADRES(aq, rl, rs1, width, rd) => { + if (rs1 == 0) then () else iR = RFull(GPRstr[rs1]) :: iR; + if (rd == 0) then () else oR = RFull(GPRstr[rd]) :: oR; + aR = iR; + ik = match (aq, rl) { + (false, false) => IK_mem_read (Read_RISCV_reserved), + (true, false) => IK_mem_read (Read_RISCV_reserved_acquire), + (true, true) => IK_mem_read (Read_RISCV_reserved_strong_acquire), + (false, true) => internal_error("LOADRES type not implemented in initial_analysis") + }; + }, + STORECON(aq, rl, rs2, rs1, width, rd) => { + if (rs2 == 0) then () else iR = RFull(GPRstr[rs2]) :: iR; + if (rs1 == 0) then () else iR = RFull(GPRstr[rs1]) :: iR; + if (rs1 == 0) then () else aR = RFull(GPRstr[rs1]) :: aR; + if (rd == 0) then () else oR = RFull(GPRstr[rd]) :: oR; + ik = match (aq, rl) { + (false, false) => IK_mem_write (Write_RISCV_conditional), + (false, true) => IK_mem_write (Write_RISCV_conditional_release), + (true, true) => IK_mem_write (Write_RISCV_conditional_strong_release), + + (true, false) => internal_error("STORECON type not implemented in initial_analysis") + }; + }, + AMO(op, aq, rl, rs2, rs1, width, rd) => { + if (rs2 == 0) then () else iR = RFull(GPRstr[rs2]) :: iR; + if (rs1 == 0) then () else iR = RFull(GPRstr[rs1]) :: iR; + if (rs1 == 0) then () else aR = RFull(GPRstr[rs1]) :: aR; + if (rd == 0) then () else oR = RFull(GPRstr[rd]) :: oR; + ik = match (aq, rl) { + (false, false) => IK_mem_rmw (Read_RISCV_reserved, Write_RISCV_conditional), + (false, true) => IK_mem_rmw (Read_RISCV_reserved, Write_RISCV_conditional_release), + (true, false) => IK_mem_rmw (Read_RISCV_reserved_acquire, + Write_RISCV_conditional), + (true, true) => IK_mem_rmw (Read_RISCV_reserved_acquire, + Write_RISCV_conditional_release) + }; + }, + _ => () + }; + (iR,oR,aR,Nias,Dia,ik) +} + +$endif diff --git a/model/riscv_fetch_rvfi.sail b/model/riscv_fetch_rvfi.sail index 03b6010..c2a5e74 100644 --- a/model/riscv_fetch_rvfi.sail +++ b/model/riscv_fetch_rvfi.sail @@ -5,7 +5,7 @@ function fetch() -> FetchResult = else { let i = rvfi_instruction.rvfi_insn(); rvfi_exec->rvfi_order() = minstret; - rvfi_exec->rvfi_pc_rdata() = EXTZ(PC); + rvfi_exec->rvfi_pc_rdata() = EXTZ(get_arch_pc()); rvfi_exec->rvfi_insn() = EXTZ(i); /* TODO: should we write these even if they're not really registers? */ diff --git a/model/riscv_insts_base.sail b/model/riscv_insts_base.sail index 0df5ce8..10f3117 100644 --- a/model/riscv_insts_base.sail +++ b/model/riscv_insts_base.sail @@ -17,7 +17,7 @@ function clause execute UTYPE(imm, rd, op) = { let off : xlenbits = EXTS(imm @ 0x000); let ret : xlenbits = match op { RISCV_LUI => off, - RISCV_AUIPC => PC + off + RISCV_AUIPC => get_arch_pc() + off }; X(rd) = ret; RETIRE_SUCCESS @@ -564,6 +564,31 @@ union clause ast = FENCE : (bits(4), bits(4)) mapping clause encdec = FENCE(pred, succ) <-> 0b0000 @ pred @ succ @ 0b00000 @ 0b000 @ 0b00000 @ 0b0001111 +/* For future versions of Sail where barriers can be parameterised */ +$ifdef FEATURE_UNION_BARRIER + +function clause execute (FENCE(pred, succ)) = { + match (pred, succ) { + (_ : bits(2) @ 0b11, _ : bits(2) @ 0b11) => __barrier(Barrier_RISCV_rw_rw()), + (_ : bits(2) @ 0b10, _ : bits(2) @ 0b11) => __barrier(Barrier_RISCV_r_rw()), + (_ : bits(2) @ 0b10, _ : bits(2) @ 0b10) => __barrier(Barrier_RISCV_r_r()), + (_ : bits(2) @ 0b11, _ : bits(2) @ 0b01) => __barrier(Barrier_RISCV_rw_w()), + (_ : bits(2) @ 0b01, _ : bits(2) @ 0b01) => __barrier(Barrier_RISCV_w_w()), + (_ : bits(2) @ 0b01, _ : bits(2) @ 0b11) => __barrier(Barrier_RISCV_w_rw()), + (_ : bits(2) @ 0b11, _ : bits(2) @ 0b10) => __barrier(Barrier_RISCV_rw_r()), + (_ : bits(2) @ 0b10, _ : bits(2) @ 0b01) => __barrier(Barrier_RISCV_r_w()), + (_ : bits(2) @ 0b01, _ : bits(2) @ 0b10) => __barrier(Barrier_RISCV_w_r()), + + (_ : bits(2) @ 0b00, _ : bits(2) @ 0b00) => (), + + _ => { print("FIXME: unsupported fence"); + () } + }; + RETIRE_SUCCESS +} + +$else + function clause execute (FENCE(pred, succ)) = { match (pred, succ) { (_ : bits(2) @ 0b11, _ : bits(2) @ 0b11) => __barrier(Barrier_RISCV_rw_rw), @@ -584,6 +609,8 @@ function clause execute (FENCE(pred, succ)) = { RETIRE_SUCCESS } +$endif + mapping bit_maybe_r : bits(1) <-> string = { 0b1 <-> "r", 0b0 <-> "" @@ -617,6 +644,21 @@ union clause ast = FENCE_TSO : (bits(4), bits(4)) mapping clause encdec = FENCE_TSO(pred, succ) <-> 0b1000 @ pred @ succ @ 0b00000 @ 0b000 @ 0b00000 @ 0b0001111 +$ifdef FEATURE_UNION_BARRIER + +function clause execute (FENCE_TSO(pred, succ)) = { + match (pred, succ) { + (_ : bits(2) @ 0b11, _ : bits(2) @ 0b11) => __barrier(Barrier_RISCV_tso()), + (_ : bits(2) @ 0b00, _ : bits(2) @ 0b00) => (), + + _ => { print("FIXME: unsupported fence"); + () } + }; + RETIRE_SUCCESS +} + +$else + function clause execute (FENCE_TSO(pred, succ)) = { match (pred, succ) { (_ : bits(2) @ 0b11, _ : bits(2) @ 0b11) => __barrier(Barrier_RISCV_tso), @@ -628,6 +670,8 @@ function clause execute (FENCE_TSO(pred, succ)) = { RETIRE_SUCCESS } +$endif + mapping clause assembly = FENCE_TSO(pred, succ) <-> "fence.tso" ^ spc() ^ fence_bits(pred) ^ sep() ^ fence_bits(succ) diff --git a/model/riscv_pc_access.sail b/model/riscv_pc_access.sail index a51e627..2de44ba 100644 --- a/model/riscv_pc_access.sail +++ b/model/riscv_pc_access.sail @@ -1,5 +1,13 @@ /* accessors for default architectural addresses, for use from within instructions */ -/* FIXME: see note in cheri_addr_checks.sail */ + +/*! + Retrieves the architectural PC value. This is not necessarily the value + found in the PC register as extensions may choose to override this function. + The value in the PC register is the absolute virtual address of the instruction + to fetch. + */ +val get_arch_pc : unit -> xlenbits effect {rreg} +function get_arch_pc() = PC val get_next_pc : unit -> xlenbits effect {rreg} function get_next_pc() = nextPC diff --git a/model/riscv_platform.sail b/model/riscv_platform.sail index 9184f02..52511a9 100644 --- a/model/riscv_platform.sail +++ b/model/riscv_platform.sail @@ -337,12 +337,19 @@ function htif_tick() = { } /* Top-level MMIO dispatch */ - +$ifndef RVFI_DII function within_mmio_readable forall 'n, 0 < 'n <= max_mem_access . (addr : xlenbits, width : atom('n)) -> bool = within_clint(addr, width) | (within_htif_readable(addr, width) & 1 <= 'n) +$else +function within_mmio_readable forall 'n, 0 < 'n <= max_mem_access . (addr : xlenbits, width : atom('n)) -> bool = false +$endif +$ifndef RVFI_DII function within_mmio_writable forall 'n, 0 < 'n <= max_mem_access . (addr : xlenbits, width : atom('n)) -> bool = within_clint(addr, width) | (within_htif_writable(addr, width) & 'n <= 8) +$else +function within_mmio_writable forall 'n, 0 < 'n <= max_mem_access . (addr : xlenbits, width : atom('n)) -> bool = false +$endif function mmio_read forall 'n, 0 < 'n <= max_mem_access . (addr : xlenbits, width : atom('n)) -> MemoryOpResult(bits(8 * 'n)) = if within_clint(addr, width) diff --git a/model/riscv_step_rvfi.sail b/model/riscv_step_rvfi.sail index 0efcdce..0ab482a 100644 --- a/model/riscv_step_rvfi.sail +++ b/model/riscv_step_rvfi.sail @@ -6,7 +6,7 @@ function ext_pre_step_hook() -> unit = () function ext_post_step_hook() -> unit = { /* record the next pc */ - rvfi_exec->rvfi_pc_wdata() = EXTZ(PC) + rvfi_exec->rvfi_pc_wdata() = EXTZ(get_arch_pc()) } val ext_init : unit -> unit effect {wreg} |