1 from functools
import reduce
2 from operator
import or_
4 from nmigen
import Elaboratable
, Module
, Signal
, Record
, Const
5 from nmigen
.hdl
.rec
import DIR_FANOUT
7 from ..wishbone
import wishbone_layout
10 __all__
= ["rvfi_layout", "RVFIController"]
12 # RISC-V Formal Interface
13 # https://github.com/SymbioticEDA/riscv-formal/blob/master/docs/rvfi.md
16 ("valid", 1, DIR_FANOUT
),
17 ("order", 64, DIR_FANOUT
),
18 ("insn", 32, DIR_FANOUT
),
19 ("trap", 1, DIR_FANOUT
),
20 ("halt", 1, DIR_FANOUT
),
21 ("intr", 1, DIR_FANOUT
),
22 ("mode", 2, DIR_FANOUT
),
23 ("ixl", 2, DIR_FANOUT
),
25 ("rs1_addr", 5, DIR_FANOUT
),
26 ("rs2_addr", 5, DIR_FANOUT
),
27 ("rs1_rdata", 32, DIR_FANOUT
),
28 ("rs2_rdata", 32, DIR_FANOUT
),
29 ("rd_addr", 5, DIR_FANOUT
),
30 ("rd_wdata", 32, DIR_FANOUT
),
32 ("pc_rdata", 32, DIR_FANOUT
),
33 ("pc_wdata", 32, DIR_FANOUT
),
35 ("mem_addr", 32, DIR_FANOUT
),
36 ("mem_rmask", 4, DIR_FANOUT
),
37 ("mem_wmask", 4, DIR_FANOUT
),
38 ("mem_rdata", 32, DIR_FANOUT
),
39 ("mem_wdata", 32, DIR_FANOUT
)
43 class RVFIController(Elaboratable
):
45 self
.rvfi
= Record(rvfi_layout
)
47 self
.d_insn
= Signal
.like(self
.rvfi
.insn
)
48 self
.d_rs1_addr
= Signal
.like(self
.rvfi
.rs1_addr
)
49 self
.d_rs2_addr
= Signal
.like(self
.rvfi
.rs2_addr
)
50 self
.d_rs1_rdata
= Signal
.like(self
.rvfi
.rs1_rdata
)
51 self
.d_rs2_rdata
= Signal
.like(self
.rvfi
.rs2_rdata
)
52 self
.d_stall
= Signal()
53 self
.x_mem_addr
= Signal
.like(self
.rvfi
.mem_addr
)
54 self
.x_mem_wmask
= Signal
.like(self
.rvfi
.mem_wmask
)
55 self
.x_mem_rmask
= Signal
.like(self
.rvfi
.mem_rmask
)
56 self
.x_mem_wdata
= Signal
.like(self
.rvfi
.mem_wdata
)
57 self
.x_stall
= Signal()
58 self
.m_mem_rdata
= Signal
.like(self
.rvfi
.mem_rdata
)
59 self
.m_fetch_misaligned
= Signal()
60 self
.m_illegal_insn
= Signal()
61 self
.m_load_misaligned
= Signal()
62 self
.m_store_misaligned
= Signal()
63 self
.m_exception
= Signal()
64 self
.m_mret
= Signal()
65 self
.m_branch_taken
= Signal()
66 self
.m_branch_target
= Signal(32)
67 self
.m_pc_rdata
= Signal
.like(self
.rvfi
.pc_rdata
)
68 self
.m_stall
= Signal()
69 self
.m_valid
= Signal()
70 self
.w_rd_addr
= Signal
.like(self
.rvfi
.rd_addr
)
71 self
.w_rd_wdata
= Signal
.like(self
.rvfi
.rd_wdata
)
73 self
.mtvec_r_base
= Signal(30)
74 self
.mepc_r_value
= Signal(32)
76 def elaborate(self
, platform
):
79 # Instruction Metadata
81 with m
.If(~self
.m_stall
):
82 m
.d
.sync
+= self
.rvfi
.valid
.eq(self
.m_valid
)
83 with m
.Elif(self
.rvfi
.valid
):
84 m
.d
.sync
+= self
.rvfi
.valid
.eq(0)
86 with m
.If(self
.rvfi
.valid
):
87 m
.d
.sync
+= self
.rvfi
.order
.eq(self
.rvfi
.order
+ 1)
89 x_insn
= Signal
.like(self
.rvfi
.insn
)
90 m_insn
= Signal
.like(self
.rvfi
.insn
)
92 with m
.If(~self
.d_stall
):
93 m
.d
.sync
+= x_insn
.eq(self
.d_insn
)
94 with m
.If(~self
.x_stall
):
95 m
.d
.sync
+= m_insn
.eq(x_insn
)
96 with m
.If(~self
.m_stall
):
97 m
.d
.sync
+= self
.rvfi
.insn
.eq(m_insn
)
99 with m
.If(~self
.m_stall
):
101 self
.rvfi
.trap
.eq(reduce(or_
, (
102 self
.m_fetch_misaligned
,
104 self
.m_load_misaligned
,
105 self
.m_store_misaligned
107 self
.rvfi
.intr
.eq(self
.m_pc_rdata
== self
.mtvec_r_base
<< 2)
111 self
.rvfi
.mode
.eq(Const(3)), # M-mode
112 self
.rvfi
.ixl
.eq(Const(1)) # XLEN=32
115 # Integer Register Read/Write
117 x_rs1_addr
= Signal
.like(self
.rvfi
.rs1_addr
)
118 x_rs2_addr
= Signal
.like(self
.rvfi
.rs2_addr
)
119 x_rs1_rdata
= Signal
.like(self
.rvfi
.rs1_rdata
)
120 x_rs2_rdata
= Signal
.like(self
.rvfi
.rs2_rdata
)
122 m_rs1_addr
= Signal
.like(self
.rvfi
.rs1_addr
)
123 m_rs2_addr
= Signal
.like(self
.rvfi
.rs2_addr
)
124 m_rs1_rdata
= Signal
.like(self
.rvfi
.rs1_rdata
)
125 m_rs2_rdata
= Signal
.like(self
.rvfi
.rs2_rdata
)
127 with m
.If(~self
.d_stall
):
129 x_rs1_addr
.eq(self
.d_rs1_addr
),
130 x_rs2_addr
.eq(self
.d_rs2_addr
),
131 x_rs1_rdata
.eq(self
.d_rs1_rdata
),
132 x_rs2_rdata
.eq(self
.d_rs2_rdata
)
134 with m
.If(~self
.x_stall
):
136 m_rs1_addr
.eq(x_rs1_addr
),
137 m_rs2_addr
.eq(x_rs2_addr
),
138 m_rs1_rdata
.eq(x_rs1_rdata
),
139 m_rs2_rdata
.eq(x_rs2_rdata
)
141 with m
.If(~self
.m_stall
):
143 self
.rvfi
.rs1_addr
.eq(m_rs1_addr
),
144 self
.rvfi
.rs2_addr
.eq(m_rs2_addr
),
145 self
.rvfi
.rs1_rdata
.eq(m_rs1_rdata
),
146 self
.rvfi
.rs2_rdata
.eq(m_rs2_rdata
)
150 self
.rvfi
.rd_addr
.eq(self
.w_rd_addr
),
151 self
.rvfi
.rd_wdata
.eq(self
.w_rd_wdata
)
156 m_pc_wdata
= Signal
.like(self
.rvfi
.pc_wdata
)
158 with m
.If(self
.m_exception
):
159 m
.d
.comb
+= m_pc_wdata
.eq(self
.mtvec_r_base
<< 2)
160 with m
.Elif(self
.m_mret
):
161 m
.d
.comb
+= m_pc_wdata
.eq(self
.mepc_r_value
)
162 with m
.Elif(self
.m_branch_taken
):
163 m
.d
.comb
+= m_pc_wdata
.eq(self
.m_branch_target
)
165 m
.d
.comb
+= m_pc_wdata
.eq(self
.m_pc_rdata
+ 4)
167 with m
.If(~self
.m_stall
):
169 self
.rvfi
.pc_rdata
.eq(self
.m_pc_rdata
),
170 self
.rvfi
.pc_wdata
.eq(m_pc_wdata
)
175 m_mem_addr
= Signal
.like(self
.rvfi
.mem_addr
)
176 m_mem_wmask
= Signal
.like(self
.rvfi
.mem_wmask
)
177 m_mem_rmask
= Signal
.like(self
.rvfi
.mem_rmask
)
178 m_mem_wdata
= Signal
.like(self
.rvfi
.mem_wdata
)
180 with m
.If(~self
.x_stall
):
182 m_mem_addr
.eq(self
.x_mem_addr
),
183 m_mem_wmask
.eq(self
.x_mem_wmask
),
184 m_mem_rmask
.eq(self
.x_mem_rmask
),
185 m_mem_wdata
.eq(self
.x_mem_wdata
)
187 with m
.If(~self
.m_stall
):
189 self
.rvfi
.mem_addr
.eq(m_mem_addr
),
190 self
.rvfi
.mem_wmask
.eq(m_mem_wmask
),
191 self
.rvfi
.mem_rmask
.eq(m_mem_rmask
),
192 self
.rvfi
.mem_wdata
.eq(m_mem_wdata
),
193 self
.rvfi
.mem_rdata
.eq(self
.m_mem_rdata
)