Allow the formal engine to perform a same-cycle result in the ALU
[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.pspec = pspec
21 self.ctx = PipeContext(pspec) # context for ReservationStation usage
22 self.muxid = self.ctx.muxid
23 self.data = []
24 self.is_output = output
25 # take regspec and create data attributes (in or out)
26 # TODO: use widspec to create reduced bit mapping.
27 print (self.regspec)
28 for i, (regfile, regname, widspec) in enumerate(self.regspec):
29 wid = get_regspec_bitwidth([self.regspec], 0, i)
30 if output:
31 sig = Data(wid, name=regname)
32 else:
33 sig = Signal(wid, name=regname, reset_less=True)
34 setattr(self, regname, sig)
35 self.data.append(sig)
36 # optional exception type
37 if exc_kls is not None:
38 name = "exc_o" if output else "exc_i"
39 self.exception = exc_kls(name=name)
40
41 def __iter__(self):
42 yield from self.ctx
43 yield from self.data
44 if hasattr(self, "exception"):
45 yield from self.exception.ports()
46
47 # convenience function to return 0:63 if XLEN=64, 0:31 if XLEN=32 etc.
48 @property
49 def intrange(self):
50 return "0:%d" % (self.pspec.XLEN-1)
51
52 def eq(self, i):
53 eqs = [self.ctx.eq(i.ctx)]
54 assert len(self.data) == len(i.data), \
55 "length of %s mismatch against %s: %s %s" % \
56 (repr(self), repr(i), repr(self.data), repr(i.data))
57 for j in range(len(self.data)):
58 assert type(self.data[j]) == type(i.data[j]), \
59 "type mismatch in FUBaseData %s %s" % \
60 (repr(self.data[j]), repr(i.data[j]))
61 eqs.append(self.data[j].eq(i.data[j]))
62 if hasattr(self, "exception"):
63 eqs.append(self.exception.eq(i.exception))
64 return eqs
65
66 def ports(self):
67 return self.ctx.ports() # TODO: include self.data
68
69
70 # hmmm there has to be a better way than this
71 def get_rec_width(rec):
72 recwidth = 0
73 # Setup random inputs for dut.op
74 for p in rec.ports():
75 width = p.width
76 recwidth += width
77 return recwidth
78
79
80 class CommonPipeSpec:
81 """CommonPipeSpec: base class for all pipeline specifications
82 see README.md for explanation of members.
83 """
84
85 def __init__(self, id_wid, parent_pspec):
86 self.pipekls = SimpleHandshakeRedir
87 self.id_wid = id_wid
88 self.opkls = lambda _: self.opsubsetkls()
89 self.op_wid = get_rec_width(self.opkls(None)) # hmm..
90 self.stage = None
91 self.parent_pspec = parent_pspec
92
93 # forward attributes from parent_pspec
94 def __getattr__(self, name):
95 return getattr(self.parent_pspec, name)
96
97
98 def get_pspec_draft_bitmanip(pspec):
99 """ True if the draft bitmanip instructions are enabled in the provided
100 pspec. The instructions enabled by this are draft instructions -- they are
101 not official OpenPower instructions, they are intended to be eventually
102 submitted to the OpenPower ISA WG.
103
104 https://libre-soc.org/openpower/sv/bitmanip/
105 """
106 # use `is True` to account for Mock absurdities
107 return getattr(pspec, "draft_bitmanip", False) is True