1 from nmigen
.compat
.sim
import run_simulation
2 from nmigen
.cli
import verilog
, rtlil
3 from nmigen
import Module
, Signal
, Elaboratable
, Array
, Cat
, Repl
4 from nmutil
.latch
import SRLatch
7 class MemDepRow(Elaboratable
):
8 """ implements 1st phase Memory Depencency cell
10 def __init__(self
, n_reg
):
13 self
.ld_i
= Signal(n_reg
, reset_less
=True) # Dest in (top)
14 self
.st_i
= Signal(n_reg
, reset_less
=True) # oper1 in (top)
15 self
.issue_i
= Signal(reset_less
=True) # Issue in (top)
17 self
.st_pend_i
= Signal(n_reg
, reset_less
=True) # Read pend in (top)
18 self
.ld_pend_i
= Signal(n_reg
, reset_less
=True) # Write pend in (top)
19 self
.v_st_rsel_o
= Signal(n_reg
, reset_less
=True) # Read pend out (bot)
20 self
.v_ld_rsel_o
= Signal(n_reg
, reset_less
=True) # Write pend out (bot)
22 self
.go_ld_i
= Signal(reset_less
=True) # Go Write in (left)
23 self
.go_st_i
= Signal(reset_less
=True) # Go Read in (left)
24 self
.go_die_i
= Signal(reset_less
=True) # Go Die in (left)
26 # for Register File Select Lines (vertical)
27 self
.ld_rsel_o
= Signal(n_reg
, reset_less
=True) # dest reg sel (bot)
28 self
.st_rsel_o
= Signal(n_reg
, reset_less
=True) # src1 reg sel (bot)
30 # for Function Unit "forward progress" (horizontal)
31 self
.ld_fwd_o
= Signal(n_reg
, reset_less
=True) # dest FU fw (right)
32 self
.st_fwd_o
= Signal(n_reg
, reset_less
=True) # src1 FU fw (right)
34 def elaborate(self
, platform
):
36 m
.submodules
.ld_c
= ld_c
= SRLatch(sync
=False, llen
=self
.n_reg
)
37 m
.submodules
.st_c
= st_c
= SRLatch(sync
=False, llen
=self
.n_reg
)
39 # connect go_rd / go_wr (dest->wr, src->rd)
40 ld_die
= Signal(reset_less
=True)
41 st_die
= Signal(reset_less
=True)
42 m
.d
.comb
+= ld_die
.eq(self
.go_ld_i | self
.go_die_i
)
43 m
.d
.comb
+= st_die
.eq(self
.go_st_i | self
.go_die_i
)
44 m
.d
.comb
+= ld_c
.r
.eq(Repl(ld_die
, self
.n_reg
))
45 m
.d
.comb
+= st_c
.r
.eq(Repl(st_die
, self
.n_reg
))
47 # connect input reg bit (unary)
48 i_ext
= Repl(self
.issue_i
, self
.n_reg
)
49 m
.d
.comb
+= ld_c
.s
.eq(i_ext
& self
.ld_i
)
50 m
.d
.comb
+= st_c
.s
.eq(i_ext
& self
.st_i
)
52 # connect up hazard checks: read-after-write and write-after-read
53 m
.d
.comb
+= self
.ld_fwd_o
.eq(ld_c
.q
& self
.st_pend_i
)
54 m
.d
.comb
+= self
.st_fwd_o
.eq(st_c
.q
& self
.ld_pend_i
)
56 # connect reg-sel outputs
57 st_ext
= Repl(self
.go_st_i
, self
.n_reg
)
58 ld_ext
= Repl(self
.go_ld_i
, self
.n_reg
)
59 m
.d
.comb
+= self
.ld_rsel_o
.eq(ld_c
.qlq
& ld_ext
)
60 m
.d
.comb
+= self
.st_rsel_o
.eq(st_c
.qlq
& st_ext
)
62 # to be accumulated to indicate if register is in use (globally)
63 # after ORing, is fed back in to st_pend_i / ld_pend_i
64 m
.d
.comb
+= self
.v_st_rsel_o
.eq(st_c
.qlq
)
65 m
.d
.comb
+= self
.v_ld_rsel_o
.eq(ld_c
.qlq
)
78 yield self
.v_ld_rsel_o
79 yield self
.v_st_rsel_o
91 yield dut
.issue_i
.eq(1)
93 yield dut
.issue_i
.eq(0)
96 yield dut
.issue_i
.eq(1)
100 yield dut
.issue_i
.eq(0)
102 yield dut
.go_st_i
.eq(1)
104 yield dut
.go_st_i
.eq(0)
106 yield dut
.go_ld_i
.eq(1)
108 yield dut
.go_ld_i
.eq(0)
113 vl
= rtlil
.convert(dut
, ports
=dut
.ports())
114 with
open("test_mem_drow.il", "w") as f
:
117 run_simulation(dut
, dcell_sim(dut
), vcd_name
='test_mem_dcell.vcd')
119 if __name__
== '__main__':