aboutsummaryrefslogtreecommitdiff
path: root/model/riscv_fetch_rvfi.sail
blob: 0f2ed4beae9a110e33e6b44f4bba44f2a8e2e99c (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
function fetch() -> FetchResult = {
  rvfi_exec->rvfi_order()    = minstret;
  rvfi_exec->rvfi_pc_rdata() = EXTZ(get_arch_pc());

  /* First allow extensions to check pc */
  match ext_fetch_check_pc(PC, PC) {
    Ext_FetchAddr_Error(e)   => F_Ext_Error(e),
    Ext_FetchAddr_OK(use_pc) => {
      /* then check PC alignment */
      if   (use_pc[0] != bitzero | (use_pc[1] != bitzero & (~ (haveRVC()))))
      then F_Error(E_Fetch_Addr_Align(), PC)
      else {
        let i = rvfi_instruction.rvfi_insn();
        rvfi_exec->rvfi_insn()     = EXTZ(i);
        /* TODO: should we write these even if they're not really registers? */
        rvfi_exec->rvfi_rs1_data() = EXTZ(X(i[19 .. 15]));
        rvfi_exec->rvfi_rs2_data() = EXTZ(X(i[24 .. 20]));
        rvfi_exec->rvfi_rs1_addr() = sail_zero_extend(i[19 .. 15],8);
        rvfi_exec->rvfi_rs2_addr() = sail_zero_extend(i[24 .. 20],8);
        if   (i[1 .. 0] != 0b11)
        then F_RVC(i[15 .. 0])
        else {
          /* fetch PC check for the next instruction granule */
          PC_hi : xlenbits = PC + 2;
          match ext_fetch_check_pc(PC, PC_hi) {
            Ext_FetchAddr_Error(e)      => F_Ext_Error(e),
            Ext_FetchAddr_OK(use_pc_hi) => F_Base(i)
          }
        }
      }
    }
  }
}