From fecd67423481822265450860b0d4ab98ec975e98 Mon Sep 17 00:00:00 2001 From: Luke Kenneth Casson Leighton Date: Mon, 25 Oct 2021 13:29:51 +0100 Subject: [PATCH] adapt/debug SimdSignal when using ElwidPartType example mini-test with test_partsig_scope.py working through issues --- src/ieee754/part/partsig.py | 21 +-- src/ieee754/part/test/test_partsig_scope.py | 146 ++++++++++++++++++++ 2 files changed, 158 insertions(+), 9 deletions(-) create mode 100644 src/ieee754/part/test/test_partsig_scope.py diff --git a/src/ieee754/part/partsig.py b/src/ieee754/part/partsig.py index f8c497c8..343aca58 100644 --- a/src/ieee754/part/partsig.py +++ b/src/ieee754/part/partsig.py @@ -89,7 +89,7 @@ class PartType: # TODO decide name # function and this class then "understands" the relationship # between elwidth and the PartitionPoints that were created # by layout() -class ElWidthPartType: # TODO decide name +class ElwidPartType: # TODO decide name def __init__(self, psig): self.psig = psig @@ -120,7 +120,7 @@ class SimdShape(Shape): fixed_width=None): # fixed overall width widths_at_elwid = width # this check is done inside layout but do it again here anyway - assert fixed_width == None and widths_at_elwidth == None, \ + assert fixed_width == None and widths_at_elwid == None, \ "both width (widths_at_elwid) and fixed_width cannot be None" (pp, bitp, lpoints, bmask, fixed_width, lane_shapes, part_wid) = \ layout(scope.elwid, @@ -143,17 +143,20 @@ class SimdSignal(UserValue): # XXX ################################################### XXX # XXX Keep these functions in the same order as ast.Value XXX # XXX ################################################### XXX - def __init__(self, mask, *args, src_loc_at=0, **kwargs): + def __init__(self, mask, shape=None, *args, src_loc_at=0, **kwargs): super().__init__(src_loc_at=src_loc_at) - self.sig = Signal(*args, **kwargs) - width = len(self.sig) # get signal width # create partition points - if False: # isinstance(mask, SimdScope): # mask parameter is a SimdScope - self.ptype = ElwidPartType(self, scope=mask) - # parse the args, get elwid from SimdMode, - # get module as well, call self.set_module(mask.module) + if isinstance(mask, SimdScope): # mask parameter is a SimdScope + self.ptype = ElwidPartType(self) + # adapt shape to a SimdShape + if not isinstance(shape, SimdShape): + shape = SimdShape(mask, shape) + self.sig = Signal(shape, *args, **kwargs) + # get partpoints from SimdShape self.partpoints = ptype.partpoints else: + self.sig = Signal(shape, *args, **kwargs) + width = len(self.sig) # get signal width if isinstance(mask, PartitionPoints): self.partpoints = mask else: diff --git a/src/ieee754/part/test/test_partsig_scope.py b/src/ieee754/part/test/test_partsig_scope.py new file mode 100644 index 00000000..19ae9560 --- /dev/null +++ b/src/ieee754/part/test/test_partsig_scope.py @@ -0,0 +1,146 @@ +#!/usr/bin/env python3 +# SPDX-License-Identifier: LGPL-2.1-or-later +# See Notices.txt for copyright information + +from nmigen import Signal, Module, Elaboratable, Mux, Cat, Shape, Repl +from nmigen.back.pysim import Simulator, Delay, Settle +from nmigen.cli import rtlil + +from ieee754.part.partsig import SimdSignal +from ieee754.part.simd_scope import SimdScope + +from random import randint +import unittest +import itertools +import math + + +def create_ilang(dut, traces, test_name): + vl = rtlil.convert(dut, ports=traces) + with open("%s.il" % test_name, "w") as f: + f.write(vl) + + +def create_simulator(module, traces, test_name): + create_ilang(module, traces, test_name) + return Simulator(module) + + + +class TestCatMod(Elaboratable): + def __init__(self, width, elwid, vec_el_counts): + self.m = Module() + with SimdScope(self.m, elwid, vec_el_counts) as s: + self.a = s.Signal(width) + self.b = s.Signal(width*2) + self.o = s.Signal(width*3) + self.cat_out = self.o.sig + + def elaborate(self, platform): + m = Module() + comb = m.d.comb + + comb += self.o.eq(Cat(self.a, self.b)) + + return m + + +class TestCat(unittest.TestCase): + def test(self): + width = 16 + elwid = Signal(2) # elwid parameter + vec_el_counts = {0b00: 1, 0b01: 2, 0b10: 4} + module = TestCatMod(width, elwid, vec_el_counts) + + test_name = "part_sig_cat_scope" + traces = [elwid, + module.a.sig, + module.b.sig, + module.cat_out] + sim = create_simulator(module, traces, test_name) + + # annoying recursive import issue + from ieee754.part_cat.cat import get_runlengths + + def async_process(): + + def test_catop(msg_prefix): + # define lengths of a/b test input + alen, blen = 16, 32 + # pairs of test values a, b + for a, b in [(0x0000, 0x00000000), + (0xDCBA, 0x12345678), + (0xABCD, 0x01234567), + (0xFFFF, 0x0000), + (0x0000, 0x0000), + (0x1F1F, 0xF1F1F1F1), + (0x0000, 0xFFFFFFFF)]: + + # convert a and b to partitions + apart, bpart = [], [] + ajump, bjump = alen // 4, blen // 4 + for i in range(4): + apart.append((a >> (ajump*i) & ((1<> (bjump*i) & ((1< 0x{y:X} != 0x{outval:X}" + self.assertEqual(y, outval, msg) + + yield elwid.eq(0b00) + yield from test_catop("16-bit") + yield elwid.eq(0b01) + yield from test_catop("8-bit") + yield elwid.eq(0b10) + yield from test_catop("4-bit") + + sim.add_process(async_process) + with sim.write_vcd( + vcd_file=open(test_name + ".vcd", "w"), + gtkw_file=open(test_name + ".gtkw", "w"), + traces=traces): + sim.run() + + +if __name__ == '__main__': + unittest.main() -- 2.30.2