add option to add exception type to FUBaseData (pipe_data)
[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 openpower.decoder.power_decoder2 import Data
5 from soc.fu.regspec import get_regspec_bitwidth
6
7
8 class FUBaseData:
9 """FUBaseData: base class for all pipeline data structures
10
11 see README.md for explanation of parameters and purpose.
12
13 note the mode parameter - output. XXXInputData specs must
14 have this set to "False", and XXXOutputData specs (and anything
15 that creates intermediary outputs which propagate through a
16 pipeline *to* output) must have it set to "True".
17 """
18
19 def __init__(self, pspec, output, exc_kls=None):
20 self.ctx = PipeContext(pspec) # context for ReservationStation usage
21 self.muxid = self.ctx.muxid
22 self.data = []
23 self.is_output = output
24 # take regspec and create data attributes (in or out)
25 # TODO: use widspec to create reduced bit mapping.
26 for i, (regfile, regname, widspec) in enumerate(self.regspec):
27 wid = get_regspec_bitwidth([self.regspec], 0, i)
28 if output:
29 sig = Data(wid, name=regname)
30 else:
31 sig = Signal(wid, name=regname, reset_less=True)
32 setattr(self, regname, sig)
33 self.data.append(sig)
34 # optional exception type
35 if exc_kls is not None:
36 name = "exc_o" if output else "exc_i"
37 self.exception = exc_kls(name=name)
38 self.data.append(self.exception)
39
40 def __iter__(self):
41 yield from self.ctx
42 yield from self.data
43
44 def eq(self, i):
45 eqs = [self.ctx.eq(i.ctx)]
46 assert len(self.data) == len(i.data), \
47 "length of %s mismatch against %s: %s %s" % \
48 (repr(self), repr(i), repr(self.data), repr(i.data))
49 for j in range(len(self.data)):
50 assert type(self.data[j]) == type(i.data[j]), \
51 "type mismatch in FUBaseData %s %s" % \
52 (repr(self.data[j]), repr(i.data[j]))
53 eqs.append(self.data[j].eq(i.data[j]))
54 return eqs
55
56 def ports(self):
57 return self.ctx.ports() # TODO: include self.data
58
59
60 # hmmm there has to be a better way than this
61 def get_rec_width(rec):
62 recwidth = 0
63 # Setup random inputs for dut.op
64 for p in rec.ports():
65 width = p.width
66 recwidth += width
67 return recwidth
68
69
70 class CommonPipeSpec:
71 """CommonPipeSpec: base class for all pipeline specifications
72 see README.md for explanation of members.
73 """
74 def __init__(self, id_wid):
75 self.pipekls = SimpleHandshakeRedir
76 self.id_wid = id_wid
77 self.opkls = lambda _: self.opsubsetkls()
78 self.op_wid = get_rec_width(self.opkls(None)) # hmm..
79 self.stage = None