ca8bc1a28ad44447ad09c31614cd5f397569fed7
[ieee754fpu.git] / src / scoreboard / int_fn_unit.py
1 from nmigen.compat.sim import run_simulation
2 from nmigen.cli import verilog, rtlil
3 from nmigen import Module, Signal, Elaboratable
4 from nmutil.latch import SRLatch
5 from nmigen.lib.coding import Decoder
6
7
8 class IntFnUnit(Elaboratable):
9 """ implements 11.4.8 integer function unit, p31
10
11 notes:
12
13 * req_rel_i (request release) is the direct equivalent of pipeline
14 "output valid"
15 """
16 def __init__(self, wid):
17 self.reg_width = wid
18
19 # inputs
20 self.dest_i = Signal(wid, reset_less=True) # Dest in (top)
21 self.src1_i = Signal(wid, reset_less=True) # oper1 in (top)
22 self.src2_i = Signal(wid, reset_less=True) # oper2 in (top)
23 self.issue_i = Signal(reset_less=True) # Issue in (top)
24
25 self.go_write_i = Signal(reset_less=True) # Go Write in (left)
26 self.go_read_i = Signal(reset_less=True) # Go Read in (left)
27 self.req_rel_i = Signal(wid, reset_less=True) # request release (left)
28
29 self.g_rd_pend_i = Signal(wid, reset_less=True) # global rd (right)
30 self.g_wr_pend_i = Signal(wid, reset_less=True) # global wr (right)
31
32 # outputs
33 self.readable_o = Signal(reset_less=True) # Readable out (right)
34 self.writable_o = Signal(reset_less=True) # Writable out (right)
35
36 self.rd_pend_o = Signal(wid, reset_less=True) # rd pending (right)
37 self.wr_pend_o = Signal(wid, reset_less=True) # wr pending (right)
38
39 def elaborate(self, platform):
40 m = Module()
41 m.submodules.rd_l = rd_l = SRLatch(sync=False)
42 m.submodules.wr_l = wr_l = SRLatch(sync=False)
43 m.submodules.dest_d = dest_d = Decoder(self.reg_width)
44 m.submodules.src1_d = src1_d = Decoder(self.reg_width)
45 m.submodules.src2_d = src2_d = Decoder(self.reg_width)
46
47 # go_write latch: reset on go_write HI, set on issue
48 m.d.comb += wr_l.s.eq(self.issue_i)
49 m.d.comb += wr_l.r.eq(self.go_write_i)
50
51 # src1 latch: reset on go_read HI, set on issue
52 m.d.comb += rd_l.s.eq(self.issue_i)
53 m.d.comb += rd_l.r.eq(self.go_read_i)
54
55 # dest decoder: write-pending out
56 m.d.comb += dest_d.i.eq(self.dest_i)
57 m.d.comb += dest_d.n.eq(wr_l.q) # FIXME this is sync-delayed!
58 m.d.comb += self.wr_pend_o.eq(dest_d.o)
59
60 # src1/src2 decoder: read-pending out
61 m.d.comb += src1_d.i.eq(self.src1_i)
62 m.d.comb += src1_d.n.eq(rd_l.q) # FIXME this is sync-delayed!
63 m.d.comb += src2_d.i.eq(self.src2_i)
64 m.d.comb += src2_d.n.eq(rd_l.q) # FIXME this is sync-delayed!
65 m.d.comb += self.rd_pend_o.eq(src1_d.o | src2_d.o)
66
67 # readable output signal
68 int_g_wr = Signal(self.reg_width, reset_less=True)
69 m.d.comb += int_g_wr.eq(self.g_wr_pend_i & self.rd_pend_o)
70 m.d.comb += self.readable_o.eq(int_g_wr.bool())
71
72 # writable output signal
73 int_g_rw = Signal(self.reg_width, reset_less=True)
74 g_rw = Signal(reset_less=True)
75 m.d.comb += int_g_rw.eq(self.g_rd_pend_i & self.wr_pend_o)
76 m.d.comb += g_rw.eq(~int_g_rw.bool())
77 m.d.comb += self.writable_o.eq(g_rw & rd_l.q & self.req_rel_i)
78
79 return m
80
81 def __iter__(self):
82 yield self.dest_i
83 yield self.src1_i
84 yield self.src2_i
85 yield self.issue_i
86 yield self.go_write_i
87 yield self.go_read_i
88 yield self.req_rel_i
89 yield self.g_rd_pend_i
90 yield self.g_wr_pend_i
91 yield self.readable_o
92 yield self.writable_o
93 yield self.rd_pend_o
94 yield self.wr_pend_o
95
96 def ports(self):
97 return list(self)
98
99
100 def int_fn_unit_sim(dut):
101 yield dut.dest_i.eq(1)
102 yield dut.issue_i.eq(1)
103 yield
104 yield dut.issue_i.eq(0)
105 yield
106 yield dut.src1_i.eq(1)
107 yield dut.issue_i.eq(1)
108 yield
109 yield
110 yield
111 yield dut.issue_i.eq(0)
112 yield
113 yield dut.go_read_i.eq(1)
114 yield
115 yield dut.go_read_i.eq(0)
116 yield
117 yield dut.go_write_i.eq(1)
118 yield
119 yield dut.go_write_i.eq(0)
120 yield
121
122 def test_int_fn_unit():
123 dut = IntFnUnit(32)
124 vl = rtlil.convert(dut, ports=dut.ports())
125 with open("test_int_fn_unit.il", "w") as f:
126 f.write(vl)
127
128 run_simulation(dut, int_fn_unit_sim(dut), vcd_name='test_int_fn_unit.vcd')
129
130 if __name__ == '__main__':
131 test_int_fn_unit()