From: Luke Kenneth Casson Leighton Date: Sat, 9 May 2020 18:19:20 +0000 (+0100) Subject: bit of reorg, trick on add - put carry in into the LSB X-Git-Tag: div_pipeline~1302 X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=91399d351480c7afcd0bb6f8df7ad87ba5a7fdb4;p=soc.git bit of reorg, trick on add - put carry in into the LSB --- diff --git a/src/soc/alu/main_stage.py b/src/soc/alu/main_stage.py index 5385c5aa..0feb74fc 100644 --- a/src/soc/alu/main_stage.py +++ b/src/soc/alu/main_stage.py @@ -26,14 +26,12 @@ class ALUMainStage(PipeModBase): m = Module() comb = m.d.comb + # check if op is 32-bit, and get sign bit from operand a is_32bit = Signal(reset_less=True) - comb += is_32bit.eq(self.i.ctx.op.is_32bit) sign_bit = Signal(reset_less=True) + comb += is_32bit.eq(self.i.ctx.op.is_32bit) comb += sign_bit.eq(Mux(is_32bit, self.i.a[31], self.i.a[63])) - 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) @@ -52,19 +50,38 @@ class ALUMainStage(PipeModBase): comb += rotl_out.eq(Cat(rotl32.o, Repl(0, 32))) with m.Else(): comb += rotl_out.eq(rotl.o) - + ########################## + # main switch-statement for handling arithmetic and logic operations with m.Switch(self.i.ctx.op.insn_type): + #### add #### with m.Case(InternalOp.OP_ADD): - comb += self.o.o.eq(add_output[0:64]) - comb += self.o.carry_out.eq(add_output[64]) + # little trick: do the add using only one add (not 2) + add_a = Signal(self.i.a.width + 2, reset_less=True) + add_b = Signal(self.i.a.width + 2, reset_less=True) + add_output = Signal(self.i.a.width + 2, reset_less=True) + # in bit 0, 1+carry_in creates carry into bit 1 and above + comb += add_a.eq(Cat(self.i.carry_in, a, Const(0, 1))) + comb += add_b.eq(Cat(Const(1, 1), b, Const(0, 1))) + comb += add_output.eq(a + b) + # bit 0 is not part of the result, top bit is the carry-out + comb += self.o.o.eq(add_output[1:-1]) + comb += self.o.carry_out.eq(add_output[-1]) + + #### and #### with m.Case(InternalOp.OP_AND): comb += self.o.o.eq(self.i.a & self.i.b) + + #### or #### with m.Case(InternalOp.OP_OR): comb += self.o.o.eq(self.i.a | self.i.b) + + #### xor #### with m.Case(InternalOp.OP_XOR): comb += self.o.o.eq(self.i.a ^ self.i.b) + + #### shift left #### with m.Case(InternalOp.OP_SHL): comb += maskgen.mb.eq(Mux(is_32bit, 32, 0)) comb += maskgen.me.eq(63-self.i.b[0:6]) @@ -80,6 +97,8 @@ class ALUMainStage(PipeModBase): with m.Else(): comb += mask.eq(maskgen.o) comb += self.o.o.eq(rotl_out & mask) + + #### shift right #### with m.Case(InternalOp.OP_SHR): comb += maskgen.mb.eq(Mux(is_32bit, 32, 0) + self.i.b[0:6]) comb += maskgen.me.eq(63) @@ -95,9 +114,10 @@ class ALUMainStage(PipeModBase): with m.Else(): comb += mask.eq(maskgen.o) with m.If(self.i.ctx.op.is_signed): - comb += self.o.o.eq(rotl_out & mask | - Mux(sign_bit, ~mask, 0)) - comb += self.o.carry_out.eq(sign_bit & ((rotl_out & mask) != 0)) + out = rotl_out & mask | Mux(sign_bit, ~mask, 0)) + cout = sign_bit & ((rotl_out & mask) != 0)) + comb += self.o.o.eq(out) + comb += self.o.carry_out.eq(cout) with m.Else(): comb += self.o.o.eq(rotl_out & mask)