link up PriorityPickers on read channels
[soc.git] / src / soc / simple / core.py
1 """simple core
2
3 not in any way intended for production use. connects up FunctionUnits to
4 Register Files in a brain-dead fashion that only permits one and only one
5 Function Unit to be operational.
6 """
7 from nmigen import Elaboratable, Module, Signal
8 from nmigen.cli import rtlil
9
10 from nmutil.picker import PriorityPicker
11
12 from soc.fu.compunits.compunits import AllFunctionUnits
13 from soc.regfile.regfiles import RegFiles
14 from soc.decoder.power_decoder import create_pdecode
15 from soc.decoder.power_decoder2 import PowerDecode2
16
17
18 class NonProductionCore(Elaboratable):
19 def __init__(self):
20 self.fus = AllFunctionUnits()
21 self.regs = RegFiles()
22 self.pdecode = pdecode = create_pdecode()
23 self.pdecode2 = PowerDecode2(pdecode) # instruction decoder
24 self.ivalid_i = self.pdecode2.e.valid # instruction is valid
25
26 def elaborate(self, platform):
27 m = Module()
28 comb = m.d.comb
29
30 m.submodules.pdecode2 = dec2 = self.pdecode2
31 m.submodules.fus = self.fus
32 self.regs.elaborate_into(m, platform)
33 regs = self.regs
34 fus = self.fus.fus
35
36 # enable-signals for each FU, get one bit for each FU (by name)
37 fu_enable = Signal(len(fus), reset_less=True)
38 fu_bitdict = {}
39 for i, funame in enumerate(fus.keys()):
40 fu_bitdict[funame] = fu_enable[i]
41
42 # dictionary of lists of regfile read ports
43 byregfiles_rd = {}
44 byregfiles_rdspec = {}
45 for (funame, fu) in fus.items():
46 print ("read ports for %s" % funame)
47 for idx in range(fu.n_src):
48 (regfile, regname, wid) = fu.get_in_spec(idx)
49 print (" %s %s %s" % (regfile, regname, str(wid)))
50 rdflag, read, _ = dec2.regspecmap(regfile, regname)
51 if regfile not in byregfiles_rd:
52 byregfiles_rd[regfile] = {}
53 byregfiles_rdspec[regfile] = (regname, rdflag, read, wid)
54 # here we start to create "lanes"
55 if idx not in byregfiles_rd[regfile]:
56 byregfiles_rd[regfile][idx] = []
57 fuspec = (funame, fu)
58 byregfiles_rd[regfile][idx].append(fuspec)
59
60 # ok just print that out, for convenience
61 for regfile, spec in byregfiles_rd.items():
62 print ("regfile read ports:", regfile)
63 for idx, fuspec in spec.items():
64 print (" regfile read port %s lane: %d" % (regfile, idx))
65 (regname, rdflag, read, wid) = byregfiles_rdspec[regfile]
66 print (" %s" % regname, wid, read, rdflag)
67 for (funame, fu) in fuspec:
68 print (" ", funame, fu, fu.src_i[idx])
69 print ()
70
71 # okaay, now we need a PriorityPicker per regfile per regfile port
72 # loootta pickers... peter piper picked a pack of pickled peppers...
73 rdpickers = {}
74 for regfile, spec in byregfiles_rd.items():
75 rdpickers[regfile] = {}
76 for idx, fuspec in spec.items():
77 rdpickers[regfile][idx] = rdpick = PriorityPicker(len(fuspec))
78 setattr(m.submodules, "rdpick_%s_%d" % (regfile, idx), rdpick)
79 for pi, (funame, fu) in enumerate(fuspec):
80 # connect request-read to picker input, and output to go-rd
81 fu_active = fu_bitdict[funame]
82 comb += rdpick.i[pi].eq(fu.rd_rel_o[idx] & fu_active)
83 comb += fu.go_rd_i[idx].eq(rdpick.o[pi])
84
85 return m
86
87 def __iter__(self):
88 yield from self.fus.ports()
89 yield from self.pdecode2.ports()
90 # TODO: regs
91
92 def ports(self):
93 return list(self)
94
95
96 if __name__ == '__main__':
97 dut = NonProductionCore()
98 vl = rtlil.convert(dut, ports=dut.ports())
99 with open("non_production_core.il", "w") as f:
100 f.write(vl)