Allow the formal engine to perform a same-cycle result in the ALU
[soc.git] / src / soc / experiment / imem.py
1 from soc.minerva.units.fetch import FetchUnitInterface
2 from nmigen import Signal, Module, Elaboratable, Mux
3 from soc.experiment.testmem import TestMemory
4 from nmigen.cli import rtlil
5
6
7 class TestMemFetchUnit(FetchUnitInterface, Elaboratable):
8
9 def __init__(self, pspec):
10 print("testmemfetchunit", pspec.addr_wid, pspec.reg_wid)
11 super().__init__(pspec)
12 # limit TestMemory to 2^6 entries of regwid size
13 self.mem = TestMemory(self.data_wid, 6, readonly=True)
14
15 def _get_memory(self):
16 return self.mem.mem
17
18 def elaborate(self, platform):
19 m = Module()
20 regwid, addrwid = self.data_wid, self.addr_wid
21 adr_lsb = self.adr_lsbs
22
23 m.submodules.mem = mem = self.mem
24
25 do_fetch = Signal() # set when fetch while valid and not stalled
26 m.d.comb += do_fetch.eq(self.a_i_valid & ~self.a_stall_i)
27
28 # bit of a messy FSM that progresses from idle to in progress
29 # to done.
30 op_actioned = Signal(reset=0)
31 op_in_progress = Signal(reset=0)
32 with m.If(~op_actioned & do_fetch): # idle
33 m.d.sync += op_actioned.eq(1)
34 m.d.sync += op_in_progress.eq(1)
35 with m.Elif(op_in_progress): # in progress
36 m.d.sync += op_actioned.eq(0)
37 with m.If(~do_fetch): # done
38 m.d.sync += op_in_progress.eq(0)
39
40 m.d.comb += self.a_busy_o.eq(op_actioned & self.a_i_valid)
41 # fetch
42 m.d.comb += mem.rdport.addr.eq(self.a_pc_i[adr_lsb:])
43 m.d.comb += self.f_instr_o.eq(mem.rdport.data)
44
45 return m
46
47 def __iter__(self): # TODO
48 yield self.a_pc_i
49 yield self.f_instr_o
50
51 def ports(self):
52 return list(self)
53
54
55 if __name__ == '__main__':
56 dut = TestMemFetchUnit(addr_wid=32, data_wid=32)
57 vl = rtlil.convert(dut, ports=[]) # TODOdut.ports())
58 with open("test_imem.il", "w") as f:
59 f.write(vl)