133b37203a473bfe3cfea73559c589987ccfedf3
1 from nmigen
.compat
.sim
import run_simulation
2 from nmigen
.cli
import verilog
, rtlil
3 from nmigen
import Module
, Signal
, Cat
, Elaboratable
5 """ Group Picker: to select an instruction that is permitted to read (or write)
6 based on the Function Unit expressing a *desire* to read (or write).
8 The job of the Group Picker is extremely simple yet extremely important.
9 It sits in front of a register file port (read or write) and stops it from
10 being corrupted. It's a "port contention selector", basically.
14 * Function Units need to read from (or write to) the register file,
15 in order to get (or store) their operands, so they each have a signal,
16 readable (or writable), which "expresses" this need. This is an
19 * The Function Units also have a signal which indicates that they
20 are requesting "release" of the register file port (this because
21 in the scoreboard, readable/writable can be permanently HI even
22 if the FU is idle, whereas the "release" signal is very specifically
23 only HI if the read (or write) latch is still active)
25 * The Group Picker takes this unary encoding of the desire to read
26 (or write) and, on a priority basis, activates one *and only* one
27 of those signals, again as an unary output.
29 * Due to the way that the Computation Unit works, that signal (Go_Read
30 or Go_Write) will fire for one (and only one) cycle, and can be used
31 to enable the register file port read (or write) lines. The Go_Read/Wr
32 signal basically loops back to the Computation Unit and resets the
33 "desire-to-read/write-expressing" latch.
35 In theory (and in practice!) the following is possible:
37 * Separate src1 and src2 Group Pickers. This would allow instructions
38 with only one operand to read to not block up other instructions,
39 and it would also allow 3-operand instructions to be interleaved
40 with 1 and 2 operand instructions.
42 * *Multiple* Group Pickers (multi-issue). This would require
43 a corresponding increase in the number of register file ports,
44 either 4R2W (or more) or by "striping" the register file into
45 split banks (a strategy best deployed on Vector Processors)
49 class PriorityPicker(Elaboratable
):
50 """ implements a priority-picker. input: N bits, output: N bits
52 def __init__(self
, wid
):
55 self
.i
= Signal(wid
, reset_less
=True)
56 self
.o
= Signal(wid
, reset_less
=True)
58 def elaborate(self
, platform
):
62 ni
= Signal(self
.wid
, reset_less
= True)
63 m
.d
.comb
+= ni
.eq(~self
.i
)
64 for i
in range(0, self
.wid
):
65 t
= Signal(reset_less
= True)
68 m
.d
.comb
+= t
.eq(self
.i
[i
])
70 m
.d
.comb
+= t
.eq(~
Cat(ni
[i
], *self
.i
[:i
]).bool())
72 # we like Cat(*xxx). turn lists into concatenated bits
73 m
.d
.comb
+= self
.o
.eq(Cat(*res
))
85 class GroupPicker(Elaboratable
):
86 """ implements 10.5 mitch alsup group picker, p27
88 def __init__(self
, wid
):
91 self
.readable_i
= Signal(wid
, reset_less
=True) # readable in (top)
92 self
.writable_i
= Signal(wid
, reset_less
=True) # writable in (top)
93 self
.rd_rel_i
= Signal(wid
, reset_less
=True) # go read in (top)
94 self
.req_rel_i
= Signal(wid
, reset_less
=True) # release request in (top)
97 self
.go_rd_o
= Signal(wid
, reset_less
=True) # go read (bottom)
98 self
.go_wr_o
= Signal(wid
, reset_less
=True) # go write (bottom)
100 def elaborate(self
, platform
):
103 m
.submodules
.rpick
= rpick
= PriorityPicker(self
.gp_wid
)
104 m
.submodules
.wpick
= wpick
= PriorityPicker(self
.gp_wid
)
106 # combine release (output ready signal) with writeable
107 m
.d
.comb
+= wpick
.i
.eq(self
.writable_i
& self
.req_rel_i
)
108 m
.d
.comb
+= self
.go_wr_o
.eq(wpick
.o
)
110 m
.d
.comb
+= rpick
.i
.eq(self
.readable_i
& self
.rd_rel_i
)
111 m
.d
.comb
+= self
.go_rd_o
.eq(rpick
.o
)
116 yield self
.readable_i
117 yield self
.writable_i
126 def grp_pick_sim(dut
):
127 yield dut
.dest_i
.eq(1)
128 yield dut
.issue_i
.eq(1)
130 yield dut
.issue_i
.eq(0)
132 yield dut
.src1_i
.eq(1)
133 yield dut
.issue_i
.eq(1)
137 yield dut
.issue_i
.eq(0)
139 yield dut
.rd_rel_i
.eq(1)
141 yield dut
.rd_rel_i
.eq(0)
143 yield dut
.go_wr_i
.eq(1)
145 yield dut
.go_wr_i
.eq(0)
150 vl
= rtlil
.convert(dut
, ports
=dut
.ports())
151 with
open("test_grp_pick.il", "w") as f
:
154 run_simulation(dut
, grp_pick_sim(dut
), vcd_name
='test_grp_pick.vcd')
156 if __name__
== '__main__':