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