From d571a2b45c8081c278c712c61e3f1290abf1233e Mon Sep 17 00:00:00 2001 From: Michael Nolan Date: Fri, 8 May 2020 13:23:09 -0400 Subject: [PATCH] Begin adding main ALU stage --- src/soc/alu/formal/proof_main_stage.py | 75 ++++++++++++++++++++++++++ src/soc/alu/main_stage.py | 32 +++++++++++ src/soc/alu/pipe_data.py | 14 +++++ 3 files changed, 121 insertions(+) create mode 100644 src/soc/alu/formal/proof_main_stage.py create mode 100644 src/soc/alu/main_stage.py diff --git a/src/soc/alu/formal/proof_main_stage.py b/src/soc/alu/formal/proof_main_stage.py new file mode 100644 index 00000000..4b7da69b --- /dev/null +++ b/src/soc/alu/formal/proof_main_stage.py @@ -0,0 +1,75 @@ +# Proof of correctness for partitioned equal signal combiner +# Copyright (C) 2020 Michael Nolan + +from nmigen import Module, Signal, Elaboratable, Mux +from nmigen.asserts import Assert, AnyConst, Assume, Cover +from nmigen.test.utils import FHDLTestCase +from nmigen.cli import rtlil + +from soc.alu.main_stage import ALUMainStage +from soc.alu.pipe_data import ALUPipeSpec +from soc.alu.alu_input_record import CompALUOpSubset +from soc.decoder.power_enums import InternalOp +import unittest + + +# This defines a module to drive the device under test and assert +# properties about its outputs +class Driver(Elaboratable): + def __init__(self): + # inputs and outputs + pass + + def elaborate(self, platform): + m = Module() + comb = m.d.comb + + rec = CompALUOpSubset() + recwidth = 0 + # Setup random inputs for dut.op + for p in rec.ports(): + width = p.width + recwidth += width + comb += p.eq(AnyConst(width)) + + pspec = ALUPipeSpec(id_wid=2, op_wid=recwidth) + m.submodules.dut = dut = ALUMainStage(pspec) + + a = Signal(64) + b = Signal(64) + comb += [dut.i.a.eq(a), + dut.i.b.eq(b), + a.eq(AnyConst(64)), + b.eq(AnyConst(64))] + + + comb += dut.i.ctx.op.eq(rec) + + + # Assert that op gets copied from the input to output + for p in rec.ports(): + name = p.name + rec_sig = p + dut_sig = getattr(dut.o.ctx.op, name) + comb += Assert(dut_sig == rec_sig) + + with m.If(rec.insn_type == InternalOp.OP_ADD): + comb += Assert(dut.o.o == (a + b) & ((1<<64)-1)) + + + return m + +class GTCombinerTestCase(FHDLTestCase): + def test_formal(self): + module = Driver() + self.assertFormal(module, mode="bmc", depth=4) + self.assertFormal(module, mode="cover", depth=4) + def test_ilang(self): + dut = Driver() + vl = rtlil.convert(dut, ports=[]) + with open("main_stage.il", "w") as f: + f.write(vl) + + +if __name__ == '__main__': + unittest.main() diff --git a/src/soc/alu/main_stage.py b/src/soc/alu/main_stage.py new file mode 100644 index 00000000..941f567c --- /dev/null +++ b/src/soc/alu/main_stage.py @@ -0,0 +1,32 @@ +from nmigen import (Module, Signal) +from nmutil.pipemodbase import PipeModBase +from soc.alu.pipe_data import ALUInitialData, ALUOutputData +from ieee754.part.partsig import PartitionedSignal +from soc.decoder.power_enums import InternalOp + + +class ALUMainStage(PipeModBase): + def __init__(self, pspec): + super().__init__(pspec, "main") + + def ispec(self): + return ALUInitialData(self.pspec) + + def ospec(self): + return ALUOutputData(self.pspec) + + def elaborate(self, platform): + m = Module() + comb = m.d.comb + + add_output = Signal(self.i.a.width + 1, reset_less=True) + comb += add_output.eq(self.i.a + self.i.b) + + + with m.Switch(self.i.ctx.op.insn_type): + with m.Case(InternalOp.OP_ADD): + comb += self.o.o.eq(add_output) + + comb += self.o.ctx.eq(self.i.ctx) + + return m diff --git a/src/soc/alu/pipe_data.py b/src/soc/alu/pipe_data.py index a1bbc7c3..9db5c9bc 100644 --- a/src/soc/alu/pipe_data.py +++ b/src/soc/alu/pipe_data.py @@ -33,6 +33,20 @@ class ALUInitialData(IntegerData): lst = super().eq(i) return lst + [self.a.eq(i.a), self.b.eq(i.b)] + +class ALUOutputData(IntegerData): + def __init__(self, pspec): + super().__init__(pspec) + self.o = Signal(64, reset_less=True) + + def __iter__(self): + yield from super().__iter__() + yield self.o + + def eq(self, i): + lst = super().eq(i) + return lst + [self.o.eq(i.o)] + class IntPipeSpec: def __init__(self, id_wid=2, op_wid=1): self.id_wid = id_wid -- 2.30.2