Add missing input stage and pipe_data
authorMichael Nolan <mtnolan2640@gmail.com>
Wed, 13 May 2020 18:52:26 +0000 (14:52 -0400)
committerMichael Nolan <mtnolan2640@gmail.com>
Wed, 13 May 2020 18:52:54 +0000 (14:52 -0400)
src/soc/shift_rot/input_stage.py [new file with mode: 0644]
src/soc/shift_rot/pipe_data.py [new file with mode: 0644]

diff --git a/src/soc/shift_rot/input_stage.py b/src/soc/shift_rot/input_stage.py
new file mode 100644 (file)
index 0000000..72e4c92
--- /dev/null
@@ -0,0 +1,58 @@
+# This stage is intended to adjust the input data before sending it to
+# the acutal ALU. Things like handling inverting the input, carry_in
+# generation for subtraction, and handling of immediates should happen
+# here
+from nmigen import (Module, Signal, Cat, Const, Mux, Repl, signed,
+                    unsigned)
+from nmutil.pipemodbase import PipeModBase
+from soc.decoder.power_enums import InternalOp
+from soc.shift_rot.pipe_data import ShiftRotInputData
+from soc.decoder.power_enums import CryIn
+
+
+class ShiftRotInputStage(PipeModBase):
+    def __init__(self, pspec):
+        super().__init__(pspec, "input")
+
+    def ispec(self):
+        return ShiftRotInputData(self.pspec)
+
+    def ospec(self):
+        return ShiftRotInputData(self.pspec)
+
+    def elaborate(self, platform):
+        m = Module()
+        comb = m.d.comb
+
+        ##### operand A #####
+
+        # operand a to be as-is or inverted
+        a = Signal.like(self.i.ra)
+
+        with m.If(self.i.ctx.op.invert_a):
+            comb += a.eq(~self.i.ra)
+        with m.Else():
+            comb += a.eq(self.i.ra)
+
+        comb += self.o.ra.eq(a)
+        comb += self.o.rb.eq(self.i.rb)
+        comb += self.o.rs.eq(self.i.rs)
+
+
+        ##### carry-in #####
+
+        # either copy incoming carry or set to 1/0 as defined by op
+        with m.Switch(self.i.ctx.op.input_carry):
+            with m.Case(CryIn.ZERO):
+                comb += self.o.carry_in.eq(0)
+            with m.Case(CryIn.ONE):
+                comb += self.o.carry_in.eq(1)
+            with m.Case(CryIn.CA):
+                comb += self.o.carry_in.eq(self.i.carry_in)
+
+        ##### sticky overflow and context (both pass-through) #####
+
+        comb += self.o.so.eq(self.i.so)
+        comb += self.o.ctx.eq(self.i.ctx)
+
+        return m
diff --git a/src/soc/shift_rot/pipe_data.py b/src/soc/shift_rot/pipe_data.py
new file mode 100644 (file)
index 0000000..291ecf0
--- /dev/null
@@ -0,0 +1,42 @@
+from nmigen import Signal, Const
+from nmutil.dynamicpipe import SimpleHandshakeRedir
+from soc.alu.alu_input_record import CompALUOpSubset
+from ieee754.fpcommon.getop import FPPipeContext
+
+
+class IntegerData:
+
+    def __init__(self, pspec):
+        self.ctx = FPPipeContext(pspec)
+        self.muxid = self.ctx.muxid
+
+    def __iter__(self):
+        yield from self.ctx
+
+    def eq(self, i):
+        return [self.ctx.eq(i.ctx)]
+
+
+class ShiftRotInputData(IntegerData):
+    def __init__(self, pspec):
+        super().__init__(pspec)
+        self.ra = Signal(64, reset_less=True) # RA
+        self.rs = Signal(64, reset_less=True) # RS
+        self.rb = Signal(64, reset_less=True) # RB/immediate
+        self.so = Signal(reset_less=True)
+        self.carry_in = Signal(reset_less=True)
+
+    def __iter__(self):
+        yield from super().__iter__()
+        yield self.ra
+        yield self.rs
+        yield self.rb
+        yield self.carry_in
+        yield self.so
+
+    def eq(self, i):
+        lst = super().eq(i)
+        return lst + [self.rs.eq(i.rs), self.ra.eq(i.ra),
+                      self.rb.eq(i.rb),
+                      self.carry_in.eq(i.carry_in),
+                      self.so.eq(i.so)]