# and shifting, as well as carry and overflow generation. This module
# however should not gate the carry or overflow, that's up to the
# output stage
-from nmigen import (Module, Signal)
+from nmigen import (Module, Signal, Cat, Repl)
from nmutil.pipemodbase import PipeModBase
from soc.alu.pipe_data import ALUInputData, ALUOutputData
from ieee754.part.partsig import PartitionedSignal
from soc.decoder.power_enums import InternalOp
+from soc.alu.maskgen import MaskGen
+from soc.alu.rotl import ROTL
class ALUMainStage(PipeModBase):
add_output = Signal(self.i.a.width + 1, reset_less=True)
comb += add_output.eq(self.i.a + self.i.b + self.i.carry_in)
+ # Signals for rotates and shifts
+ rotl_out = Signal.like(self.i.a)
+ mask = Signal.like(self.i.a)
+ m.submodules.maskgen = maskgen = MaskGen(64)
+ m.submodules.rotl = rotl = ROTL(64)
+ m.submodules.rotl32 = rotl32 = ROTL(32)
+
+ comb += [
+ rotl.a.eq(self.i.a),
+ rotl.b.eq(self.i.b),
+ rotl32.a.eq(self.i.a[0:32]),
+ rotl32.b.eq(self.i.b)]
+
+ with m.If(self.i.ctx.op.is_32bit):
+ comb += rotl_out.eq(Cat(rotl32.o, Repl(0, 32)))
+ with m.Else():
+ comb += rotl_out.eq(rotl.o)
+
+
with m.Switch(self.i.ctx.op.insn_type):
with m.Case(InternalOp.OP_ADD):
with m.Case(InternalOp.OP_XOR):
comb += self.o.o.eq(self.i.a ^ self.i.b)
with m.Case(InternalOp.OP_SHL):
- comb += self.o.o.eq(self.i.a << self.i.b)
+ comb += maskgen.mb.eq(32)
+ comb += maskgen.me.eq(63-self.i.b[0:5])
+ with m.If(self.i.ctx.op.is_32bit):
+ with m.If(self.i.b[5]):
+ comb += mask.eq(0)
+ with m.Else():
+ comb += mask.eq(maskgen.o)
+ comb += self.o.o.eq(rotl_out & mask)
###### sticky overflow and context, both pass-through #####
--- /dev/null
+from nmigen import (Elaboratable, Signal, Module)
+import math
+
+class ROTL(Elaboratable):
+ def __init__(self, width):
+ self.width = width
+ self.shiftwidth = math.ceil(math.log2(width))
+ self.a = Signal(width, reset_less=True)
+ self.b = Signal(self.shiftwidth, reset_less=True)
+
+ self.o = Signal(width, reset_less=True)
+
+ def elaborate(self, platform):
+ m = Module()
+ comb = m.d.comb
+
+ shl = Signal.like(self.a)
+ shr = Signal.like(self.a)
+
+ comb += shl.eq(self.a << self.b)
+ comb += shr.eq(self.a >> (self.width - self.b))
+
+ comb += self.o.eq(shl | shr)
+ return m
with Program(lst) as program:
sim = self.run_tst_program(program, initial_regs)
- def test_rlwinm(self):
- for i in range(0, 10):
-
+ def test_shift(self):
+ for i in range(10):
lst = ["slw 3, 1, 2"]
initial_regs = [0] * 32
initial_regs[1] = random.randint(0, (1<<64)-1)
initial_regs[2] = random.randint(0, 63)
+ print(initial_regs[1], initial_regs[2])
with Program(lst) as program:
sim = self.run_tst_program(program, initial_regs)