Allow the formal engine to perform a same-cycle result in the ALU
[soc.git] / src / soc / fu / pipe_data.py
index 764de09fbda099faccf957cd132fdd5eb73e999f..427f5c6a0cdc52a7532a989e432782a9e57f1cb0 100644 (file)
-from ieee754.fpcommon.getop import FPPipeContext
+from nmutil.concurrentunit import PipeContext
+from nmutil.dynamicpipe import SimpleHandshakeRedir
+from nmigen import Signal
+from openpower.decoder.power_decoder2 import Data
+from soc.fu.regspec import get_regspec_bitwidth
 
 
-class IntegerData:
+class FUBaseData:
+    """FUBaseData: base class for all pipeline data structures
 
-    def __init__(self, pspec):
-        self.ctx = FPPipeContext(pspec)
+    see README.md for explanation of parameters and purpose.
+
+    note the mode parameter - output.  XXXInputData specs must
+    have this set to "False", and XXXOutputData specs (and anything
+    that creates intermediary outputs which propagate through a
+    pipeline *to* output) must have it set to "True".
+    """
+
+    def __init__(self, pspec, output, exc_kls=None):
+        self.pspec = pspec
+        self.ctx = PipeContext(pspec)  # context for ReservationStation usage
         self.muxid = self.ctx.muxid
+        self.data = []
+        self.is_output = output
+        # take regspec and create data attributes (in or out)
+        # TODO: use widspec to create reduced bit mapping.
+        print (self.regspec)
+        for i, (regfile, regname, widspec) in enumerate(self.regspec):
+            wid = get_regspec_bitwidth([self.regspec], 0, i)
+            if output:
+                sig = Data(wid, name=regname)
+            else:
+                sig = Signal(wid, name=regname, reset_less=True)
+            setattr(self, regname, sig)
+            self.data.append(sig)
+        # optional exception type
+        if exc_kls is not None:
+            name = "exc_o" if output else "exc_i"
+            self.exception = exc_kls(name=name)
 
     def __iter__(self):
         yield from self.ctx
+        yield from self.data
+        if hasattr(self, "exception"):
+            yield from self.exception.ports()
+
+    # convenience function to return 0:63 if XLEN=64, 0:31 if XLEN=32 etc.
+    @property
+    def intrange(self):
+        return "0:%d" % (self.pspec.XLEN-1)
 
     def eq(self, i):
-        return [self.ctx.eq(i.ctx)]
+        eqs = [self.ctx.eq(i.ctx)]
+        assert len(self.data) == len(i.data), \
+            "length of %s mismatch against %s: %s %s" % \
+            (repr(self), repr(i), repr(self.data), repr(i.data))
+        for j in range(len(self.data)):
+            assert type(self.data[j]) == type(i.data[j]), \
+                "type mismatch in FUBaseData %s %s" % \
+                (repr(self.data[j]), repr(i.data[j]))
+            eqs.append(self.data[j].eq(i.data[j]))
+        if hasattr(self, "exception"):
+            eqs.append(self.exception.eq(i.exception))
+        return eqs
 
     def ports(self):
-        return self.ctx.ports()
+        return self.ctx.ports()  # TODO: include self.data
+
+
+# hmmm there has to be a better way than this
+def get_rec_width(rec):
+    recwidth = 0
+    # Setup random inputs for dut.op
+    for p in rec.ports():
+        width = p.width
+        recwidth += width
+    return recwidth
+
+
+class CommonPipeSpec:
+    """CommonPipeSpec: base class for all pipeline specifications
+    see README.md for explanation of members.
+    """
+
+    def __init__(self, id_wid, parent_pspec):
+        self.pipekls = SimpleHandshakeRedir
+        self.id_wid = id_wid
+        self.opkls = lambda _: self.opsubsetkls()
+        self.op_wid = get_rec_width(self.opkls(None))  # hmm..
+        self.stage = None
+        self.parent_pspec = parent_pspec
+
+    # forward attributes from parent_pspec
+    def __getattr__(self, name):
+        return getattr(self.parent_pspec, name)
+
+
+def get_pspec_draft_bitmanip(pspec):
+    """ True if the draft bitmanip instructions are enabled in the provided
+    pspec. The instructions enabled by this are draft instructions -- they are
+    not official OpenPower instructions, they are intended to be eventually
+    submitted to the OpenPower ISA WG.
+
+    https://libre-soc.org/openpower/sv/bitmanip/
+    """
+    # use `is True` to account for Mock absurdities
+    return getattr(pspec, "draft_bitmanip", False) is True