From 9ec6a4b3b2609f0a6e68810c0312b413eee2f01c Mon Sep 17 00:00:00 2001 From: Luke Kenneth Casson Leighton Date: Wed, 22 Jan 2020 14:21:24 +0000 Subject: [PATCH] add partition test add unit test --- src/ieee754/part/partsig.py | 16 +++-- src/ieee754/part/test/test_partsig.py | 91 ++++++++++++++++++++++++++ src/ieee754/part_mul_add/partpoints.py | 2 +- 3 files changed, 102 insertions(+), 7 deletions(-) create mode 100644 src/ieee754/part/test/test_partsig.py diff --git a/src/ieee754/part/partsig.py b/src/ieee754/part/partsig.py index 47a7625c..949bebc2 100644 --- a/src/ieee754/part/partsig.py +++ b/src/ieee754/part/partsig.py @@ -1,3 +1,6 @@ +# SPDX-License-Identifier: LGPL-2.1-or-later +# See Notices.txt for copyright information + """ Copyright (C) 2020 Luke Kenneth Casson Leighton @@ -13,23 +16,24 @@ from nmigen import (Module, Signal, Elaboratable, from ieee754.part_mul_add.adder import PartitionedAdder class PartitionedSignal(Elaboratable): - def __init__(self, partition_points, *args, **kwargs) - reset=0, reset_less=False, - attrs=None, decoder=None, src_loc_at=0): + def __init__(self, partition_points, *args, **kwargs): self.partpoints = partition_points self.sig = Signal(*args, **kwargs) self.modnames = {} for name in ['add']: self.modnames[name] = 0 + self.m = Module() - def elaboratable(self, platform): - self.m = m = Module() - return m + def elaborate(self, platform): + return self.m def get_modname(self, category): self.modnames[category] += 1 return "%s%d" % (category, self.modnames[category]) + def eq(self, val): + return self.sig.eq(val) + def __xor__(self, other): if isinstance(other, PartitionedSignal): return self.sig ^ other.sig diff --git a/src/ieee754/part/test/test_partsig.py b/src/ieee754/part/test/test_partsig.py new file mode 100644 index 00000000..cae067dc --- /dev/null +++ b/src/ieee754/part/test/test_partsig.py @@ -0,0 +1,91 @@ +#!/usr/bin/env python3 +# SPDX-License-Identifier: LGPL-2.1-or-later +# See Notices.txt for copyright information + +from ieee754.part.partsig import PartitionedSignal +from nmigen import Signal, Module, Elaboratable +from nmigen.back.pysim import Simulator, Delay, Tick, Passive +from nmigen.cli import verilog, rtlil + +import unittest + +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, + vcd_file=open(test_name + ".vcd", "w"), + gtkw_file=open(test_name + ".gtkw", "w"), + traces=traces) + +class TestAddMod(Elaboratable): + def __init__(self, width, partpoints): + self.a = PartitionedSignal(partpoints, width) + self.b = PartitionedSignal(partpoints, width) + self.add_output = Signal(width) + + def elaborate(self, platform): + m = Module() + m.submodules.a = self.a + m.submodules.b = self.b + m.d.comb += self.add_output.eq(self.a + self.b) + + return m + + +class TestPartitionPoints(unittest.TestCase): + def test(self): + width = 16 + partition_nibbles = Signal() # divide into 4-bits + partition_bytes = Signal() # divide on 8-bits + partpoints = {0x4: partition_nibbles, + 0x8: partition_bytes | partition_nibbles, + 0xC: partition_nibbles} + module = TestAddMod(width, partpoints) + + sim = create_simulator(module, + [partition_nibbles, + partition_bytes, + module.a.sig, + module.b.sig, + module.add_output], + "part_sig_add") + def async_process(): + def test_add(msg_prefix, *mask_list): + for a, b in [(0x0000, 0x0000), + (0x1234, 0x1234), + (0xABCD, 0xABCD), + (0xFFFF, 0x0000), + (0x0000, 0x0000), + (0xFFFF, 0xFFFF), + (0x0000, 0xFFFF)]: + yield module.a.eq(a) + yield module.b.eq(b) + yield Delay(0.1e-6) + y = 0 + for mask in mask_list: + y |= mask & ((a & mask) + (b & mask)) + outval = (yield module.add_output) + msg = f"{msg_prefix}: 0x{a:X} + 0x{b:X}" + \ + f" => 0x{y:X} != 0x{outval:X}" + self.assertEqual(y, outval, msg) + yield partition_nibbles.eq(0) + yield partition_bytes.eq(0) + yield from test_add("16-bit", 0xFFFF) + yield partition_nibbles.eq(0) + yield partition_bytes.eq(1) + yield from test_add("8-bit", 0xFF00, 0x00FF) + yield partition_nibbles.eq(1) + yield partition_bytes.eq(0) + yield from test_add("4-bit", 0xF000, 0x0F00, 0x00F0, 0x000F) + + sim.add_process(async_process) + sim.run() + +if __name__ == '__main__': + unittest.main() + diff --git a/src/ieee754/part_mul_add/partpoints.py b/src/ieee754/part_mul_add/partpoints.py index 0ea3668f..13ea5647 100644 --- a/src/ieee754/part_mul_add/partpoints.py +++ b/src/ieee754/part_mul_add/partpoints.py @@ -43,7 +43,7 @@ class PartitionPoints(dict): raise TypeError("point must be a non-negative integer") if point < 0: raise ValueError("point must be a non-negative integer") - self[point] = Value.wrap(enabled) + self[point] = Value.cast(enabled) def like(self, name=None, src_loc_at=0, mul=1): """Create a new ``PartitionPoints`` with ``Signal``s for all values. -- 2.30.2