13e854344c3eb3cbdb9b2e2857619da443f28bc8
[soc.git] / src / soc / fu / pipe_data.py
1 from nmutil.concurrentunit import PipeContext
2 from nmutil.dynamicpipe import SimpleHandshakeRedir
3 from nmigen import Signal
4 from soc.decoder.power_decoder2 import Data
5 from soc.fu.regspec import get_regspec_bitwidth
6
7
8 class IntegerData:
9 """IntegerData: base class for all pipeline data structures
10
11 this class auto-constructs parameters (placing them in self.data)
12 based on "regspecs". this is conceptually similar to nmigen Record
13 (Layout, actually) except that Layout does not contain the right type
14 of information for connecting up to Register Files.
15
16 by having a base class that handles creation of pipeline input/output
17 in a structured fashion, CompUnits may conform to that same structured
18 API, and when it comes to actually connecting up to regfiles, the same
19 holds true.
20
21 the alternative is mountains of explicit code (which quickly becomes
22 unmaintainable).
23
24 note the mode parameter - output. output pipeline data structures
25 need to have an "ok" flag added, which is used by the CompUnit and
26 by the Register File to determine if the output shall in fact be
27 written to the register file or not.
28
29 input data has *already* been determined to have had to have been read,
30 this by PowerDecoder2.
31 """
32
33 def __init__(self, pspec, output):
34 self.ctx = PipeContext(pspec) # context for ReservationStation usage
35 self.muxid = self.ctx.muxid
36 self.data = []
37 self.is_output = output
38 for i, (regfile, regname, widspec) in enumerate(self.regspec):
39 wid = get_regspec_bitwidth([self.regspec], 0, i)
40 if output:
41 sig = Data(wid, name=regname)
42 else:
43 sig = Signal(wid, name=regname, reset_less=True)
44 setattr(self, regname, sig)
45 self.data.append(sig)
46
47 def __iter__(self):
48 yield from self.ctx
49 yield from self.data
50
51 def eq(self, i):
52 eqs = [self.ctx.eq(i.ctx)]
53 assert len(self.data) == len(i.data), \
54 "length of %s mismatch against %s: %s %s" % \
55 (repr(self), repr(i), repr(self.data), repr(i.data))
56 for j in range(len(self.data)):
57 assert type(self.data[j]) == type(i.data[j]), \
58 "type mismatch in IntegerData %s %s" % \
59 (repr(self.data[j]), repr(i.data[j]))
60 eqs.append(self.data[j].eq(i.data[j]))
61 return eqs
62
63 def ports(self):
64 return self.ctx.ports() # TODO: include self.data
65
66
67 # hmmm there has to be a better way than this
68 def get_rec_width(rec):
69 recwidth = 0
70 # Setup random inputs for dut.op
71 for p in rec.ports():
72 width = p.width
73 recwidth += width
74 return recwidth
75
76
77 class CommonPipeSpec:
78 def __init__(self, id_wid):
79 self.pipekls = SimpleHandshakeRedir
80 self.id_wid = id_wid
81 self.opkls = lambda _: self.opsubsetkls(name="op")
82 self.op_wid = get_rec_width(self.opkls(None)) # hmm..
83 self.stage = None