1 from functools
import reduce
2 from operator
import or_
3 from itertools
import tee
5 from nmigen
import Elaboratable
, Module
, Record
, Mux
, Const
, Signal
, Memory
6 from nmigen
.lib
.coding
import PriorityEncoder
8 from soc
.minerva
.stage
import Stage
9 from soc
.minerva
.csr
import CSRFile
10 from soc
.minerva
.units
.adder
import Adder
11 from soc
.minerva
.units
.compare
import CompareUnit
12 from soc
.minerva
.units
.debug
import DebugUnit
13 from soc
.minerva
.units
.decoder
import InstructionDecoder
14 from soc
.minerva
.units
.divider
import Divider
, DummyDivider
15 from soc
.minerva
.units
.exception
import ExceptionUnit
16 from soc
.minerva
.units
.fetch
import BareFetchUnit
, CachedFetchUnit
, PCSelector
17 from soc
.minerva
.units
.rvficon
import RVFIController
, rvfi_layout
18 from soc
.minerva
.units
.loadstore
import (BareLoadStoreUnit
, CachedLoadStoreUnit
,
20 from soc
.minerva
.units
.logic
import LogicUnit
21 from soc
.minerva
.units
.multiplier
import DummyMultiplier
, Multiplier
22 from soc
.minerva
.units
.predict
import BranchPredictor
23 from soc
.minerva
.units
.shifter
import Shifter
24 from soc
.minerva
.units
.trigger
import TriggerUnit
26 from soc
.minerva
.units
.debug
.jtag
import jtag_layout
27 from soc
.minerva
.wishbone
import wishbone_layout
50 ("fetch_badaddr", 30),
75 ("branch_target", 32),
76 ("branch_predict_taken", 1),
91 ("fetch_badaddr", 30),
93 ("loadstore_misaligned", 1),
108 ("condition_met", 1),
109 ("branch_target", 32),
111 ("branch_predict_taken", 1),
134 class Minerva(Elaboratable
):
135 def __init__(self
, reset_address
=0x00000000,
137 icache_nways
=1, icache_nlines
=256, icache_nwords
=8, icache_base
=0, icache_limit
=2**31,
139 dcache_nways
=1, dcache_nlines
=256, dcache_nwords
=8, dcache_base
=0, dcache_limit
=2**31,
142 with_trigger
=False, nb_triggers
=8,
144 self
.external_interrupt
= Signal(32)
145 self
.timer_interrupt
= Signal()
146 self
.software_interrupt
= Signal()
147 self
.ibus
= Record(wishbone_layout
)
148 self
.dbus
= Record(wishbone_layout
)
151 self
.jtag
= Record(jtag_layout
)
154 self
.rvfi
= Record(rvfi_layout
)
156 self
.reset_address
= reset_address
157 self
.with_icache
= with_icache
158 self
.icache_args
= icache_nways
, icache_nlines
, icache_nwords
, icache_base
, icache_limit
159 self
.with_dcache
= with_dcache
160 self
.dcache_args
= dcache_nways
, dcache_nlines
, dcache_nwords
, dcache_base
, dcache_limit
161 self
.with_muldiv
= with_muldiv
162 self
.with_debug
= with_debug
163 self
.with_trigger
= with_trigger
164 self
.nb_triggers
= nb_triggers
165 self
.with_rvfi
= with_rvfi
167 def elaborate(self
, platform
):
172 a
= cpu
.submodules
.a
= Stage(None, _af_layout
)
173 f
= cpu
.submodules
.f
= Stage(_af_layout
, _fd_layout
)
174 d
= cpu
.submodules
.d
= Stage(_fd_layout
, _dx_layout
)
175 x
= cpu
.submodules
.x
= Stage(_dx_layout
, _xm_layout
)
176 m
= cpu
.submodules
.m
= Stage(_xm_layout
, _mw_layout
)
177 w
= cpu
.submodules
.w
= Stage(_mw_layout
, None)
178 stages
= a
, f
, d
, x
, m
, w
180 sources
, sinks
= tee(stages
)
182 for s1
, s2
in zip(sources
, sinks
):
183 cpu
.d
.comb
+= s1
.source
.connect(s2
.sink
)
185 a
.source
.pc
.reset
= self
.reset_address
- 4
186 cpu
.d
.comb
+= a
.valid
.eq(Const(1))
190 pc_sel
= cpu
.submodules
.pc_sel
= PCSelector()
191 data_sel
= cpu
.submodules
.data_sel
= DataSelector()
192 adder
= cpu
.submodules
.adder
= Adder()
193 compare
= cpu
.submodules
.compare
= CompareUnit()
194 decoder
= cpu
.submodules
.decoder
= InstructionDecoder(self
.with_muldiv
)
195 exception
= cpu
.submodules
.exception
= ExceptionUnit()
196 logic
= cpu
.submodules
.logic
= LogicUnit()
197 predict
= cpu
.submodules
.predict
= BranchPredictor()
198 shifter
= cpu
.submodules
.shifter
= Shifter()
201 fetch
= cpu
.submodules
.fetch
= CachedFetchUnit(*self
.icache_args
)
203 fetch
= cpu
.submodules
.fetch
= BareFetchUnit()
206 loadstore
= cpu
.submodules
.loadstore
= CachedLoadStoreUnit(
209 loadstore
= cpu
.submodules
.loadstore
= BareLoadStoreUnit()
212 multiplier
= Multiplier() if not self
.with_rvfi
else DummyMultiplier()
213 divider
= Divider() if not self
.with_rvfi
else DummyDivider()
214 cpu
.submodules
.multiplier
= multiplier
215 cpu
.submodules
.divider
= divider
218 debug
= cpu
.submodules
.debug
= DebugUnit()
220 if self
.with_trigger
:
221 trigger
= cpu
.submodules
.trigger
= TriggerUnit(self
.nb_triggers
)
224 rvficon
= cpu
.submodules
.rvficon
= RVFIController()
228 gprf
= Memory(width
=32, depth
=32)
229 gprf_rp1
= gprf
.read_port()
230 gprf_rp2
= gprf
.read_port()
231 gprf_wp
= gprf
.write_port()
232 cpu
.submodules
+= gprf_rp1
, gprf_rp2
, gprf_wp
234 csrf
= cpu
.submodules
.csrf
= CSRFile()
235 csrf_rp
= csrf
.read_port()
236 csrf_wp
= csrf
.write_port()
238 csrf
.add_csrs(exception
.iter_csrs())
240 csrf
.add_csrs(debug
.iter_csrs())
241 if self
.with_trigger
:
242 csrf
.add_csrs(trigger
.iter_csrs())
247 pc_sel
.f_pc
.eq(f
.sink
.pc
),
248 pc_sel
.d_pc
.eq(d
.sink
.pc
),
249 pc_sel
.d_branch_predict_taken
.eq(
250 predict
.d_branch_taken
& ~predict
.d_fetch_misaligned
),
251 pc_sel
.d_branch_target
.eq(predict
.d_branch_target
),
252 pc_sel
.d_valid
.eq(d
.valid
),
253 pc_sel
.x_pc
.eq(x
.sink
.pc
),
254 pc_sel
.x_fence_i
.eq(x
.sink
.fence_i
),
255 pc_sel
.x_valid
.eq(x
.valid
),
256 pc_sel
.m_branch_predict_taken
.eq(m
.sink
.branch_predict_taken
),
257 pc_sel
.m_branch_taken
.eq(m
.sink
.branch_taken
),
258 pc_sel
.m_branch_target
.eq(m
.sink
.branch_target
),
259 pc_sel
.m_exception
.eq(exception
.m_raise
),
260 pc_sel
.m_mret
.eq(m
.sink
.mret
),
261 pc_sel
.m_valid
.eq(m
.valid
),
262 pc_sel
.mtvec_r_base
.eq(exception
.mtvec
.r
.base
),
263 pc_sel
.mepc_r_base
.eq(exception
.mepc
.r
.base
)
267 fetch
.a_pc
.eq(pc_sel
.a_pc
),
268 fetch
.a_stall
.eq(a
.stall
),
269 fetch
.a_valid
.eq(a
.valid
),
270 fetch
.f_stall
.eq(f
.stall
),
271 fetch
.f_valid
.eq(f
.valid
),
272 fetch
.ibus
.connect(self
.ibus
)
275 m
.stall_on(fetch
.a_busy
& a
.valid
)
276 m
.stall_on(fetch
.f_busy
& f
.valid
)
279 flush_icache
= x
.sink
.fence_i
& x
.valid
& ~x
.stall
281 flush_icache |
= debug
.resumereq
284 fetch
.a_flush
.eq(flush_icache
),
285 fetch
.f_pc
.eq(f
.sink
.pc
)
289 decoder
.instruction
.eq(d
.sink
.instruction
)
293 with cpu
.If(debug
.halt
& debug
.halted
):
294 cpu
.d
.comb
+= gprf_rp1
.addr
.eq(debug
.gprf_addr
)
295 with cpu
.Elif(~d
.stall
):
296 cpu
.d
.comb
+= gprf_rp1
.addr
.eq(fetch
.f_instruction
[15:20])
298 cpu
.d
.comb
+= gprf_rp1
.addr
.eq(decoder
.rs1
)
300 cpu
.d
.comb
+= debug
.gprf_dat_r
.eq(gprf_rp1
.data
)
302 with cpu
.If(~d
.stall
):
303 cpu
.d
.comb
+= gprf_rp1
.addr
.eq(fetch
.f_instruction
[15:20])
305 cpu
.d
.comb
+= gprf_rp1
.addr
.eq(decoder
.rs1
)
307 with cpu
.If(~d
.stall
):
308 cpu
.d
.comb
+= gprf_rp2
.addr
.eq(fetch
.f_instruction
[20:25])
310 cpu
.d
.comb
+= gprf_rp2
.addr
.eq(decoder
.rs2
)
312 with cpu
.If(~f
.stall
):
313 cpu
.d
.sync
+= csrf_rp
.addr
.eq(fetch
.f_instruction
[20:32])
314 cpu
.d
.comb
+= csrf_rp
.en
.eq(decoder
.csr
& d
.valid
)
316 # CSR set/clear instructions are translated to logic operations.
317 x_csr_set_clear
= x
.sink
.funct3
[1]
318 x_csr_clear
= x_csr_set_clear
& x
.sink
.funct3
[0]
319 x_csr_fmt_i
= x
.sink
.funct3
[2]
320 x_csr_src1
= Mux(x_csr_fmt_i
, x
.sink
.rs1
, x
.sink
.src1
)
321 x_csr_src1
= Mux(x_csr_clear
, ~x_csr_src1
, x_csr_src1
)
322 x_csr_logic_op
= x
.sink
.funct3 |
0b100
325 logic
.op
.eq(Mux(x
.sink
.csr
, x_csr_logic_op
, x
.sink
.funct3
)),
326 logic
.src1
.eq(Mux(x
.sink
.csr
, x_csr_src1
, x
.sink
.src1
)),
327 logic
.src2
.eq(x
.sink
.src2
)
331 adder
.sub
.eq(x
.sink
.adder
& x
.sink
.adder_sub |
332 x
.sink
.compare | x
.sink
.branch
),
333 adder
.src1
.eq(x
.sink
.src1
),
334 adder
.src2
.eq(Mux(x
.sink
.store
, x
.sink
.immediate
, x
.sink
.src2
))
339 multiplier
.x_op
.eq(x
.sink
.funct3
),
340 multiplier
.x_src1
.eq(x
.sink
.src1
),
341 multiplier
.x_src2
.eq(x
.sink
.src2
),
342 multiplier
.x_stall
.eq(x
.stall
),
343 multiplier
.m_stall
.eq(m
.stall
)
347 divider
.x_op
.eq(x
.sink
.funct3
),
348 divider
.x_src1
.eq(x
.sink
.src1
),
349 divider
.x_src2
.eq(x
.sink
.src2
),
350 divider
.x_valid
.eq(x
.sink
.valid
),
351 divider
.x_stall
.eq(x
.stall
)
354 m
.stall_on(divider
.m_busy
)
357 shifter
.x_direction
.eq(x
.sink
.direction
),
358 shifter
.x_sext
.eq(x
.sink
.sext
),
359 shifter
.x_shamt
.eq(x
.sink
.src2
),
360 shifter
.x_src1
.eq(x
.sink
.src1
),
361 shifter
.x_stall
.eq(x
.stall
)
365 # compare.op is shared by compare and branch instructions.
367 Mux(x
.sink
.compare
, x
.sink
.funct3
<< 1, x
.sink
.funct3
)),
368 compare
.zero
.eq(x
.sink
.src1
== x
.sink
.src2
),
369 compare
.negative
.eq(adder
.result
[-1]),
370 compare
.overflow
.eq(adder
.overflow
),
371 compare
.carry
.eq(adder
.carry
)
375 exception
.external_interrupt
.eq(self
.external_interrupt
),
376 exception
.timer_interrupt
.eq(self
.timer_interrupt
),
377 exception
.software_interrupt
.eq(self
.software_interrupt
),
378 exception
.m_fetch_misaligned
.eq(
379 m
.sink
.branch_taken
& m
.sink
.branch_target
[:2].bool()),
380 exception
.m_fetch_error
.eq(m
.sink
.fetch_error
),
381 exception
.m_fetch_badaddr
.eq(m
.sink
.fetch_badaddr
),
382 exception
.m_load_misaligned
.eq(
383 m
.sink
.load
& m
.sink
.loadstore_misaligned
),
384 exception
.m_load_error
.eq(loadstore
.m_load_error
),
385 exception
.m_store_misaligned
.eq(
386 m
.sink
.store
& m
.sink
.loadstore_misaligned
),
387 exception
.m_store_error
.eq(loadstore
.m_store_error
),
388 exception
.m_loadstore_badaddr
.eq(loadstore
.m_badaddr
),
389 exception
.m_branch_target
.eq(m
.sink
.branch_target
),
390 exception
.m_illegal
.eq(m
.sink
.illegal
),
391 exception
.m_ecall
.eq(m
.sink
.ecall
),
392 exception
.m_pc
.eq(m
.sink
.pc
),
393 exception
.m_instruction
.eq(m
.sink
.instruction
),
394 exception
.m_result
.eq(m
.sink
.result
),
395 exception
.m_mret
.eq(m
.sink
.mret
),
396 exception
.m_stall
.eq(m
.sink
.stall
),
397 exception
.m_valid
.eq(m
.valid
)
400 m_ebreak
= m
.sink
.ebreak
402 # If dcsr.ebreakm is set, EBREAK instructions enter Debug Mode.
403 # We do not want to raise an exception in this case because Debug Mode
404 # should be invisible to software execution.
405 m_ebreak
&= ~debug
.dcsr_ebreakm
406 if self
.with_trigger
:
407 m_ebreak |
= trigger
.trap
408 cpu
.d
.comb
+= exception
.m_ebreak
.eq(m_ebreak
)
410 m
.kill_on(m
.source
.exception
& m
.source
.valid
)
413 data_sel
.x_offset
.eq(adder
.result
[:2]),
414 data_sel
.x_funct3
.eq(x
.sink
.funct3
),
415 data_sel
.x_store_operand
.eq(x
.sink
.src2
),
416 data_sel
.w_offset
.eq(w
.sink
.result
[:2]),
417 data_sel
.w_funct3
.eq(w
.sink
.funct3
),
418 data_sel
.w_load_data
.eq(w
.sink
.load_data
)
422 loadstore
.x_addr
.eq(adder
.result
),
423 loadstore
.x_mask
.eq(data_sel
.x_mask
),
424 loadstore
.x_load
.eq(x
.sink
.load
),
425 loadstore
.x_store
.eq(x
.sink
.store
),
426 loadstore
.x_store_data
.eq(data_sel
.x_store_data
),
427 loadstore
.x_stall
.eq(x
.stall
),
428 loadstore
.x_valid
.eq(x
.valid
),
429 loadstore
.m_stall
.eq(m
.stall
),
430 loadstore
.m_valid
.eq(m
.valid
)
433 m
.stall_on(loadstore
.x_busy
& x
.valid
)
434 m
.stall_on(loadstore
.m_busy
& m
.valid
)
438 cpu
.d
.comb
+= loadstore
.x_flush
.eq(debug
.resumereq
)
441 loadstore
.x_fence_i
.eq(x
.sink
.fence_i
),
442 loadstore
.m_addr
.eq(m
.sink
.result
),
443 loadstore
.m_load
.eq(m
.sink
.load
),
444 loadstore
.m_store
.eq(m
.sink
.store
),
447 x
.stall_on(loadstore
.x_busy
& x
.valid
)
450 s
.kill_on(x
.sink
.fence_i
& x
.valid
)
453 with cpu
.If(debug
.halt
& debug
.halted
):
454 cpu
.d
.comb
+= debug
.dbus
.connect(self
.dbus
)
456 cpu
.d
.comb
+= loadstore
.dbus
.connect(self
.dbus
)
458 cpu
.d
.comb
+= loadstore
.dbus
.connect(self
.dbus
)
460 # RAW hazard management
476 x_raw_rs1
.eq((x
.sink
.rd
!= 0) & (
477 x
.sink
.rd
== decoder
.rs1
) & x
.sink
.rd_we
),
478 m_raw_rs1
.eq((m
.sink
.rd
!= 0) & (
479 m
.sink
.rd
== decoder
.rs1
) & m
.sink
.rd_we
),
480 w_raw_rs1
.eq((w
.sink
.rd
!= 0) & (
481 w
.sink
.rd
== decoder
.rs1
) & w
.sink
.rd_we
),
483 x_raw_rs2
.eq((x
.sink
.rd
!= 0) & (
484 x
.sink
.rd
== decoder
.rs2
) & x
.sink
.rd_we
),
485 m_raw_rs2
.eq((m
.sink
.rd
!= 0) & (
486 m
.sink
.rd
== decoder
.rs2
) & m
.sink
.rd_we
),
487 w_raw_rs2
.eq((w
.sink
.rd
!= 0) & (
488 w
.sink
.rd
== decoder
.rs2
) & w
.sink
.rd_we
),
490 x_raw_csr
.eq((x
.sink
.csr_adr
== decoder
.immediate
)
492 m_raw_csr
.eq((m
.sink
.csr_adr
== decoder
.immediate
)
495 x_lock
.eq(~x
.sink
.bypass_x
& (decoder
.rs1_re
& x_raw_rs1 |
496 decoder
.rs2_re
& x_raw_rs2
) | decoder
.csr
& x_raw_csr
),
497 m_lock
.eq(~m
.sink
.bypass_m
& (decoder
.rs1_re
& m_raw_rs1 |
498 decoder
.rs2_re
& m_raw_rs2
) | decoder
.csr
& m_raw_csr
)
502 d
.stall_on((x_lock
& x
.valid | m_lock
& m
.valid
)
503 & d
.valid
& ~debug
.dcsr_step
)
505 d
.stall_on((x_lock
& x
.valid | m_lock
& m
.valid
) & d
.valid
)
509 x_result
= Signal(32)
510 m_result
= Signal(32)
511 w_result
= Signal(32)
512 x_csr_result
= Signal(32)
514 with cpu
.If(x
.sink
.jump
):
515 cpu
.d
.comb
+= x_result
.eq(x
.sink
.pc
+ 4)
516 with cpu
.Elif(x
.sink
.logic
):
517 cpu
.d
.comb
+= x_result
.eq(logic
.result
)
518 with cpu
.Elif(x
.sink
.csr
):
519 cpu
.d
.comb
+= x_result
.eq(x
.sink
.src2
)
521 cpu
.d
.comb
+= x_result
.eq(adder
.result
)
523 with cpu
.If(m
.sink
.compare
):
524 cpu
.d
.comb
+= m_result
.eq(m
.sink
.condition_met
)
526 with cpu
.Elif(m
.sink
.divide
):
527 cpu
.d
.comb
+= m_result
.eq(divider
.m_result
)
528 with cpu
.Elif(m
.sink
.shift
):
529 cpu
.d
.comb
+= m_result
.eq(shifter
.m_result
)
531 cpu
.d
.comb
+= m_result
.eq(m
.sink
.result
)
533 with cpu
.If(w
.sink
.load
):
534 cpu
.d
.comb
+= w_result
.eq(data_sel
.w_load_result
)
536 with cpu
.Elif(w
.sink
.multiply
):
537 cpu
.d
.comb
+= w_result
.eq(multiplier
.w_result
)
539 cpu
.d
.comb
+= w_result
.eq(w
.sink
.result
)
541 with cpu
.If(x_csr_set_clear
):
542 cpu
.d
.comb
+= x_csr_result
.eq(logic
.result
)
544 cpu
.d
.comb
+= x_csr_result
.eq(x_csr_src1
)
547 csrf_wp
.en
.eq(m
.sink
.csr
& m
.sink
.csr_we
& m
.valid
&
548 ~exception
.m_raise
& ~m
.stall
),
549 csrf_wp
.addr
.eq(m
.sink
.csr_adr
),
550 csrf_wp
.data
.eq(m
.sink
.csr_result
)
554 with cpu
.If(debug
.halt
& debug
.halted
):
556 gprf_wp
.addr
.eq(debug
.gprf_addr
),
557 gprf_wp
.en
.eq(debug
.gprf_we
),
558 gprf_wp
.data
.eq(debug
.gprf_dat_w
)
562 gprf_wp
.en
.eq((w
.sink
.rd
!= 0) & w
.sink
.rd_we
&
563 w
.valid
& ~w
.sink
.exception
),
564 gprf_wp
.addr
.eq(w
.sink
.rd
),
565 gprf_wp
.data
.eq(w_result
)
569 gprf_wp
.en
.eq((w
.sink
.rd
!= 0) & w
.sink
.rd_we
& w
.valid
),
570 gprf_wp
.addr
.eq(w
.sink
.rd
),
571 gprf_wp
.data
.eq(w_result
)
574 # D stage operand selection
579 with cpu
.If(decoder
.lui
):
580 cpu
.d
.comb
+= d_src1
.eq(0)
581 with cpu
.Elif(decoder
.auipc
):
582 cpu
.d
.comb
+= d_src1
.eq(d
.sink
.pc
)
583 with cpu
.Elif(decoder
.rs1_re
& (decoder
.rs1
== 0)):
584 cpu
.d
.comb
+= d_src1
.eq(0)
585 with cpu
.Elif(x_raw_rs1
& x
.valid
):
586 cpu
.d
.comb
+= d_src1
.eq(x_result
)
587 with cpu
.Elif(m_raw_rs1
& m
.valid
):
588 cpu
.d
.comb
+= d_src1
.eq(m_result
)
589 with cpu
.Elif(w_raw_rs1
& w
.valid
):
590 cpu
.d
.comb
+= d_src1
.eq(w_result
)
592 cpu
.d
.comb
+= d_src1
.eq(gprf_rp1
.data
)
594 with cpu
.If(decoder
.csr
):
595 cpu
.d
.comb
+= d_src2
.eq(csrf_rp
.data
)
596 with cpu
.Elif(~decoder
.rs2_re
):
597 cpu
.d
.comb
+= d_src2
.eq(decoder
.immediate
)
598 with cpu
.Elif(decoder
.rs2
== 0):
599 cpu
.d
.comb
+= d_src2
.eq(0)
600 with cpu
.Elif(x_raw_rs2
& x
.valid
):
601 cpu
.d
.comb
+= d_src2
.eq(x_result
)
602 with cpu
.Elif(m_raw_rs2
& m
.valid
):
603 cpu
.d
.comb
+= d_src2
.eq(m_result
)
604 with cpu
.Elif(w_raw_rs2
& w
.valid
):
605 cpu
.d
.comb
+= d_src2
.eq(w_result
)
607 cpu
.d
.comb
+= d_src2
.eq(gprf_rp2
.data
)
612 predict
.d_branch
.eq(decoder
.branch
),
613 predict
.d_jump
.eq(decoder
.jump
),
614 predict
.d_offset
.eq(decoder
.immediate
),
615 predict
.d_pc
.eq(d
.sink
.pc
),
616 predict
.d_rs1_re
.eq(decoder
.rs1_re
)
619 a
.kill_on(predict
.d_branch_taken
& ~
620 predict
.d_fetch_misaligned
& d
.valid
)
622 s
.kill_on(m
.sink
.branch_predict_taken
& ~
623 m
.sink
.branch_taken
& m
.valid
)
625 s
.kill_on(~m
.sink
.branch_predict_taken
&
626 m
.sink
.branch_taken
& m
.valid
)
627 s
.kill_on((exception
.m_raise | m
.sink
.mret
) & m
.valid
)
633 debug
.jtag
.connect(self
.jtag
),
634 debug
.x_pc
.eq(x
.sink
.pc
),
635 debug
.x_ebreak
.eq(x
.sink
.ebreak
),
636 debug
.x_stall
.eq(x
.stall
),
637 debug
.m_branch_taken
.eq(m
.sink
.branch_taken
),
638 debug
.m_branch_target
.eq(m
.sink
.branch_target
),
639 debug
.m_mret
.eq(m
.sink
.mret
),
640 debug
.m_exception
.eq(exception
.m_raise
),
641 debug
.m_pc
.eq(m
.sink
.pc
),
642 debug
.m_valid
.eq(m
.valid
),
643 debug
.mepc_r_base
.eq(exception
.mepc
.r
.base
),
644 debug
.mtvec_r_base
.eq(exception
.mtvec
.r
.base
)
647 if self
.with_trigger
:
648 cpu
.d
.comb
+= debug
.trigger_haltreq
.eq(trigger
.haltreq
)
650 cpu
.d
.comb
+= debug
.trigger_haltreq
.eq(Const(0))
652 csrf_debug_rp
= csrf
.read_port()
653 csrf_debug_wp
= csrf
.write_port()
655 csrf_debug_rp
.addr
.eq(debug
.csrf_addr
),
656 csrf_debug_rp
.en
.eq(debug
.csrf_re
),
657 debug
.csrf_dat_r
.eq(csrf_debug_rp
.data
),
658 csrf_debug_wp
.addr
.eq(debug
.csrf_addr
),
659 csrf_debug_wp
.en
.eq(debug
.csrf_we
),
660 csrf_debug_wp
.data
.eq(debug
.csrf_dat_w
)
663 x
.stall_on(debug
.halt
)
664 m
.stall_on(debug
.dcsr_step
& m
.valid
& ~debug
.halt
)
666 s
.kill_on(debug
.killall
)
668 halted
= x
.stall
& ~
reduce(or_
, (s
.valid
for s
in (m
, w
)))
669 cpu
.d
.sync
+= debug
.halted
.eq(halted
)
671 with cpu
.If(debug
.resumereq
):
672 with cpu
.If(~debug
.dbus_busy
):
673 cpu
.d
.comb
+= debug
.resumeack
.eq(1)
674 cpu
.d
.sync
+= a
.source
.pc
.eq(debug
.dpc_value
- 4)
676 if self
.with_trigger
:
678 trigger
.x_pc
.eq(x
.sink
.pc
),
679 trigger
.x_valid
.eq(x
.valid
),
684 rvficon
.d_insn
.eq(decoder
.instruction
),
685 rvficon
.d_rs1_addr
.eq(Mux(decoder
.rs1_re
, decoder
.rs1
, 0)),
686 rvficon
.d_rs2_addr
.eq(Mux(decoder
.rs2_re
, decoder
.rs2
, 0)),
687 rvficon
.d_rs1_rdata
.eq(Mux(decoder
.rs1_re
, d_src1
, 0)),
688 rvficon
.d_rs2_rdata
.eq(Mux(decoder
.rs2_re
, d_src2
, 0)),
689 rvficon
.d_stall
.eq(d
.stall
),
690 rvficon
.x_mem_addr
.eq(loadstore
.x_addr
[2:] << 2),
691 rvficon
.x_mem_wmask
.eq(
692 Mux(loadstore
.x_store
, loadstore
.x_mask
, 0)),
693 rvficon
.x_mem_rmask
.eq(
694 Mux(loadstore
.x_load
, loadstore
.x_mask
, 0)),
695 rvficon
.x_mem_wdata
.eq(loadstore
.x_store_data
),
696 rvficon
.x_stall
.eq(x
.stall
),
697 rvficon
.m_mem_rdata
.eq(loadstore
.m_load_data
),
698 rvficon
.m_fetch_misaligned
.eq(exception
.m_fetch_misaligned
),
699 rvficon
.m_illegal_insn
.eq(m
.sink
.illegal
),
700 rvficon
.m_load_misaligned
.eq(exception
.m_load_misaligned
),
701 rvficon
.m_store_misaligned
.eq(exception
.m_store_misaligned
),
702 rvficon
.m_exception
.eq(exception
.m_raise
),
703 rvficon
.m_mret
.eq(m
.sink
.mret
),
704 rvficon
.m_branch_taken
.eq(m
.sink
.branch_taken
),
705 rvficon
.m_branch_target
.eq(m
.sink
.branch_target
),
706 rvficon
.m_pc_rdata
.eq(m
.sink
.pc
),
707 rvficon
.m_stall
.eq(m
.stall
),
708 rvficon
.m_valid
.eq(m
.valid
),
709 rvficon
.w_rd_addr
.eq(Mux(gprf_wp
.en
, gprf_wp
.addr
, 0)),
710 rvficon
.w_rd_wdata
.eq(Mux(gprf_wp
.en
, gprf_wp
.data
, 0)),
711 rvficon
.mtvec_r_base
.eq(exception
.mtvec
.r
.base
),
712 rvficon
.mepc_r_value
.eq(exception
.mepc
.r
),
713 rvficon
.rvfi
.connect(self
.rvfi
)
719 with cpu
.If(~a
.stall
):
720 cpu
.d
.sync
+= a
.source
.pc
.eq(fetch
.a_pc
)
723 with cpu
.If(~f
.stall
):
725 f
.source
.pc
.eq(f
.sink
.pc
),
726 f
.source
.instruction
.eq(fetch
.f_instruction
),
727 f
.source
.fetch_error
.eq(fetch
.f_fetch_error
),
728 f
.source
.fetch_badaddr
.eq(fetch
.f_badaddr
)
732 with cpu
.If(~d
.stall
):
734 d
.source
.pc
.eq(d
.sink
.pc
),
735 d
.source
.instruction
.eq(d
.sink
.instruction
),
736 d
.source
.fetch_error
.eq(d
.sink
.fetch_error
),
737 d
.source
.fetch_badaddr
.eq(d
.sink
.fetch_badaddr
),
738 d
.source
.illegal
.eq(decoder
.illegal
),
739 d
.source
.rd
.eq(decoder
.rd
),
740 d
.source
.rs1
.eq(decoder
.rs1
),
741 d
.source
.rd_we
.eq(decoder
.rd_we
),
742 d
.source
.rs1_re
.eq(decoder
.rs1_re
),
743 d
.source
.immediate
.eq(decoder
.immediate
),
744 d
.source
.bypass_x
.eq(decoder
.bypass_x
),
745 d
.source
.bypass_m
.eq(decoder
.bypass_m
),
746 d
.source
.funct3
.eq(decoder
.funct3
),
747 d
.source
.load
.eq(decoder
.load
),
748 d
.source
.store
.eq(decoder
.store
),
749 d
.source
.adder
.eq(decoder
.adder
),
750 d
.source
.adder_sub
.eq(decoder
.adder_sub
),
751 d
.source
.compare
.eq(decoder
.compare
),
752 d
.source
.logic
.eq(decoder
.logic
),
753 d
.source
.shift
.eq(decoder
.shift
),
754 d
.source
.direction
.eq(decoder
.direction
),
755 d
.source
.sext
.eq(decoder
.sext
),
756 d
.source
.jump
.eq(decoder
.jump
),
757 d
.source
.branch
.eq(decoder
.branch
),
758 d
.source
.fence_i
.eq(decoder
.fence_i
),
759 d
.source
.csr
.eq(decoder
.csr
),
760 d
.source
.csr_adr
.eq(decoder
.immediate
),
761 d
.source
.csr_we
.eq(decoder
.csr_we
),
762 d
.source
.ecall
.eq(decoder
.ecall
),
763 d
.source
.ebreak
.eq(decoder
.ebreak
),
764 d
.source
.mret
.eq(decoder
.mret
),
765 d
.source
.src1
.eq(d_src1
),
766 d
.source
.src2
.eq(d_src2
),
767 d
.source
.branch_predict_taken
.eq(
768 predict
.d_branch_taken
& ~predict
.d_fetch_misaligned
),
769 d
.source
.branch_target
.eq(predict
.d_branch_target
)
773 d
.source
.multiply
.eq(decoder
.multiply
),
774 d
.source
.divide
.eq(decoder
.divide
)
778 with cpu
.If(~x
.stall
):
780 x
.source
.pc
.eq(x
.sink
.pc
),
781 x
.source
.instruction
.eq(x
.sink
.instruction
),
782 x
.source
.fetch_error
.eq(x
.sink
.fetch_error
),
783 x
.source
.fetch_badaddr
.eq(x
.sink
.fetch_badaddr
),
784 x
.source
.illegal
.eq(x
.sink
.illegal
),
785 x
.source
.loadstore_misaligned
.eq(data_sel
.x_misaligned
),
786 x
.source
.ecall
.eq(x
.sink
.ecall
),
787 x
.source
.ebreak
.eq(x
.sink
.ebreak
),
788 x
.source
.rd
.eq(x
.sink
.rd
),
789 x
.source
.rd_we
.eq(x
.sink
.rd_we
),
790 x
.source
.bypass_m
.eq(x
.sink
.bypass_m | x
.sink
.bypass_x
),
791 x
.source
.funct3
.eq(x
.sink
.funct3
),
792 x
.source
.load
.eq(x
.sink
.load
),
793 x
.source
.store
.eq(x
.sink
.store
),
794 x
.source
.store_data
.eq(loadstore
.x_store_data
),
795 x
.source
.compare
.eq(x
.sink
.compare
),
796 x
.source
.shift
.eq(x
.sink
.shift
),
797 x
.source
.mret
.eq(x
.sink
.mret
),
798 x
.source
.condition_met
.eq(compare
.condition_met
),
799 x
.source
.branch_taken
.eq(
800 x
.sink
.jump | x
.sink
.branch
& compare
.condition_met
),
801 x
.source
.branch_target
.eq(
802 Mux(x
.sink
.jump
& x
.sink
.rs1_re
, adder
.result
[1:] << 1, x
.sink
.branch_target
)),
803 x
.source
.branch_predict_taken
.eq(x
.sink
.branch_predict_taken
),
804 x
.source
.csr
.eq(x
.sink
.csr
),
805 x
.source
.csr_adr
.eq(x
.sink
.csr_adr
),
806 x
.source
.csr_we
.eq(x
.sink
.csr_we
),
807 x
.source
.csr_result
.eq(x_csr_result
),
808 x
.source
.result
.eq(x_result
)
812 x
.source
.multiply
.eq(x
.sink
.multiply
),
813 x
.source
.divide
.eq(x
.sink
.divide
)
817 with cpu
.If(~m
.stall
):
819 m
.source
.pc
.eq(m
.sink
.pc
),
820 m
.source
.rd
.eq(m
.sink
.rd
),
821 m
.source
.load
.eq(m
.sink
.load
),
822 m
.source
.funct3
.eq(m
.sink
.funct3
),
823 m
.source
.load_data
.eq(loadstore
.m_load_data
),
824 m
.source
.rd_we
.eq(m
.sink
.rd_we
),
825 m
.source
.result
.eq(m_result
),
826 m
.source
.exception
.eq(exception
.m_raise
)
830 m
.source
.multiply
.eq(m
.sink
.multiply
)