--- /dev/null
+proof_*/**
--- /dev/null
+# Proof of correctness for partitioned dynamic shifter
+# Copyright (C) 2020 Michael Nolan <mtnolan2640@gmail.com>
+
+from nmigen import Module, Signal, Elaboratable, Mux, Cat
+from nmigen.asserts import Assert, AnyConst, Assume
+from nmigen.test.utils import FHDLTestCase
+from nmigen.cli import rtlil
+
+from ieee754.part_mul_add.partpoints import PartitionPoints
+from ieee754.part_shift.part_shift_dynamic import \
+ PartitionedDynamicShift
+import unittest
+
+
+# This defines a module to drive the device under test and assert
+# properties about its outputs
+class ShifterDriver(Elaboratable):
+ def __init__(self):
+ # inputs and outputs
+ pass
+
+ def get_intervals(self, signal, points):
+ start = 0
+ interval = []
+ keys = list(points.keys()) + [signal.width]
+ for key in keys:
+ end = key
+ interval.append(signal[start:end])
+ start = end
+ return interval
+
+ def elaborate(self, platform):
+ m = Module()
+ comb = m.d.comb
+ width = 24
+ mwidth = 3
+
+ # setup the inputs and outputs of the DUT as anyconst
+ a = Signal(width)
+ b = Signal(width)
+ out = Signal(width)
+ points = PartitionPoints()
+ gates = Signal(mwidth-1)
+ step = int(width/mwidth)
+ for i in range(mwidth-1):
+ points[(i+1)*step] = gates[i]
+ print(points)
+
+ comb += [a.eq(AnyConst(width)),
+ b.eq(AnyConst(width)),
+ gates.eq(AnyConst(mwidth-1))]
+
+ m.submodules.dut = dut = PartitionedDynamicShift(width, points)
+
+ a_intervals = self.get_intervals(a, points)
+ b_intervals = self.get_intervals(b, points)
+ out_intervals = self.get_intervals(out, points)
+
+ comb += [dut.a.eq(a),
+ dut.b.eq(b),
+ out.eq(dut.output)]
+
+
+ with m.Switch(points.as_sig()):
+ with m.Case(0b00):
+ comb += Assume(b < 24)
+ comb += Assert(out == (a<<b[0:5]) & 0xffffff)
+ with m.Case(0b01):
+ comb += Assume(b_intervals[0] <= 8)
+ comb += Assert(out_intervals[0] ==
+ (a_intervals[0]<<b_intervals[0]) & 0xff)
+ comb += Assume(b_intervals[1] <= 16)
+ comb += Assert(Cat(out_intervals[1:3]) ==
+ (Cat(a_intervals[1:3])
+ <<b_intervals[1]) & 0xffff)
+ with m.Case(0b10):
+ comb += Assume(b_intervals[0] <= 16)
+ comb += Assert(Cat(out_intervals[0:2]) ==
+ (Cat(a_intervals[0:2])
+ <<b_intervals[0]) & 0xffff)
+ comb += Assume(b_intervals[2] <= 16)
+ comb += Assert(out_intervals[2] ==
+ (a_intervals[2]<<b_intervals[2]) & 0xff)
+ with m.Case(0b11):
+ for i, o in enumerate(out_intervals):
+ comb += Assume(b_intervals[i] < 8)
+ comb += Assert(o ==
+ (a_intervals[i] << b_intervals[i]) & 0xff)
+
+ return m
+
+class PartitionedDynamicShiftTestCase(FHDLTestCase):
+ def test_shift(self):
+ module = ShifterDriver()
+ self.assertFormal(module, mode="bmc", depth=4)
+ def test_ilang(self):
+ width = 64
+ mwidth = 8
+ gates = Signal(mwidth-1)
+ points = PartitionPoints()
+ step = int(width/mwidth)
+ for i in range(mwidth-1):
+ points[(i+1)*step] = gates[i]
+ print(points)
+ dut = PartitionedDynamicShift(width, points)
+ vl = rtlil.convert(dut, ports=[gates, dut.a, dut.b, dut.output])
+ with open("dynamic_shift.il", "w") as f:
+ f.write(vl)
+
+
+if __name__ == "__main__":
+ unittest.main()
+
--- /dev/null
+# Proof of correctness for partitioned scalar shifter
+# Copyright (C) 2020 Michael Nolan <mtnolan2640@gmail.com>
+
+from nmigen import Module, Signal, Elaboratable, Mux, Cat
+from nmigen.asserts import Assert, AnyConst, Assume
+from nmigen.test.utils import FHDLTestCase
+from nmigen.cli import rtlil
+
+from ieee754.part_mul_add.partpoints import PartitionPoints
+from ieee754.part_shift_scalar.part_shift_scalar import PartitionedScalarShift
+import unittest
+
+
+# This defines a module to drive the device under test and assert
+# properties about its outputs
+class ShifterDriver(Elaboratable):
+ def __init__(self):
+ # inputs and outputs
+ pass
+
+ def get_intervals(self, signal, points):
+ start = 0
+ interval = []
+ keys = list(points.keys()) + [signal.width]
+ for key in keys:
+ end = key
+ interval.append(signal[start:end])
+ start = end
+ return interval
+
+ def elaborate(self, platform):
+ m = Module()
+ comb = m.d.comb
+ width = 24
+ shifterwidth = 5
+ mwidth = 3
+
+ # setup the inputs and outputs of the DUT as anyconst
+ data = Signal(width)
+ out = Signal(width)
+ shifter = Signal(shifterwidth)
+ points = PartitionPoints()
+ gates = Signal(mwidth-1)
+ step = int(width/mwidth)
+ for i in range(mwidth-1):
+ points[(i+1)*step] = gates[i]
+ print(points)
+
+ comb += [data.eq(AnyConst(width)),
+ shifter.eq(AnyConst(shifterwidth)),
+ gates.eq(AnyConst(mwidth-1))]
+
+ m.submodules.dut = dut = PartitionedScalarShift(width, points)
+
+ data_intervals = self.get_intervals(data, points)
+ out_intervals = self.get_intervals(out, points)
+
+ comb += [dut.data.eq(data),
+ dut.shifter.eq(shifter),
+ out.eq(dut.output)]
+
+ expected = Signal(width)
+ comb += expected.eq(data << shifter)
+
+ with m.Switch(points.as_sig()):
+ with m.Case(0b00):
+ comb += Assert(out[0:24] == (data[0:24] << shifter) & 0xffffff)
+
+ with m.Case(0b01):
+ comb += Assert(out[0:8] == expected[0:8])
+ comb += Assert(out[8:24] == (data[8:24] << shifter) & 0xffff)
+
+ with m.Case(0b10):
+ comb += Assert(out[16:24] == (data[16:24] << shifter) & 0xff)
+ comb += Assert(out[0:16] == (data[0:16] << shifter) & 0xffff)
+
+ with m.Case(0b11):
+ comb += Assert(out[0:8] == expected[0:8])
+ comb += Assert(out[8:16] == (data[8:16] << shifter) & 0xff)
+ comb += Assert(out[16:24] == (data[16:24] << shifter) & 0xff)
+ return m
+
+class PartitionedScalarShiftTestCase(FHDLTestCase):
+ def test_shift(self):
+ module = ShifterDriver()
+ self.assertFormal(module, mode="bmc", depth=4)
+
+if __name__ == "__main__":
+ unittest.main()
+
--- /dev/null
+# SPDX-License-Identifier: LGPL-2.1-or-later
+# See Notices.txt for copyright information
+
+"""
+Copyright (C) 2020 Luke Kenneth Casson Leighton <lkcl@lkcl.net>
+Copyright (C) 2020 Michael Nolan <mtnolan2640@gmail.com>
+
+dynamically partitionable shifter. Unlike part_shift_scalar, both
+operands can be partitioned
+
+See:
+
+* http://libre-riscv.org/3d_gpu/architecture/dynamic_simd/shift/
+* http://bugs.libre-riscv.org/show_bug.cgi?id=173
+"""
+from nmigen import Signal, Module, Elaboratable, Cat, Mux
+from ieee754.part_mul_add.partpoints import PartitionPoints
+import math
+
+
+class PartitionedDynamicShift(Elaboratable):
+ def __init__(self, width, partition_points):
+ self.width = width
+ self.partition_points = PartitionPoints(partition_points)
+
+ self.a = Signal(width)
+ self.b = Signal(width)
+ self.output = Signal(width)
+
+ def elaborate(self, platform):
+ m = Module()
+ comb = m.d.comb
+ width = self.width
+ gates = Signal(self.partition_points.get_max_partition_count(width)-1)
+ comb += gates.eq(self.partition_points.as_sig())
+
+ matrix = []
+ keys = list(self.partition_points.keys()) + [self.width]
+ start = 0
+
+ for i in range(len(keys)):
+ row = []
+ start = 0
+ for j in range(len(keys)):
+ end = keys[j]
+ row.append(Signal(width - start,
+ name="matrix[%d][%d]" % (i, j)))
+ matrix.append(row)
+
+ a_intervals = []
+ b_intervals = []
+ out_intervals = []
+ intervals = []
+ start = 0
+ for i in range(len(keys)):
+ end = keys[i]
+ a_intervals.append(self.a[start:end])
+ b_intervals.append(self.b[start:end])
+ out_intervals.append(self.output[start:end])
+ intervals.append([start,end])
+ start = end
+
+ for i, b in enumerate(b_intervals):
+ start = 0
+ for j, a in enumerate(a_intervals):
+ end = keys[i]
+ comb += matrix[i][j].eq(a << b)
+ start = end
+
+ intermed = matrix[0][0]
+ comb += out_intervals[0].eq(intermed)
+ for i in range(1, len(out_intervals)):
+ index = gates[:i] # selects the 'i' least significant bits
+ # of gates
+ element = Signal(width, name="element%d" % i)
+ for index in range(1<<i):
+ print(index)
+ with m.Switch(gates[:i]):
+ with m.Case(index):
+ index = math.ceil(math.log2(index + 1))
+ comb += element.eq(matrix[index][i])
+ print(keys[i-1])
+ temp = Signal(width, name="intermed%d" % i)
+ print(intermed[keys[0]:])
+ intermed = Mux(gates[i-1], element, element | intermed[keys[0]:])
+ comb += temp.eq(intermed)
+ comb += out_intervals[i].eq(intermed)
+
+
+ return m
+
--- /dev/null
+# SPDX-License-Identifier: LGPL-2.1-or-later
+# See Notices.txt for copyright information
+
+"""
+Copyright (C) 2020 Michael Nolan <mtnolan2640@gmail.com>
+
+dynamically partitionable shifter. Only the operand to be shifted can
+be partitioned, the amount to shift by *must* be a scalar
+
+See:
+
+* http://libre-riscv.org/3d_gpu/architecture/dynamic_simd/shift/
+* http://bugs.libre-riscv.org/show_bug.cgi?id=173
+"""
+from nmigen import Signal, Module, Elaboratable, Cat, Mux
+from ieee754.part_mul_add.partpoints import PartitionPoints
+import math
+
+
+class PartitionedScalarShift(Elaboratable):
+ def __init__(self, width, partition_points):
+ self.width = width
+ self.partition_points = PartitionPoints(partition_points)
+
+ self.data = Signal(width)
+ self.shiftbits = math.ceil(math.log2(width))
+ self.shifter = Signal(self.shiftbits)
+ self.output = Signal(width)
+
+ def elaborate(self, platform):
+ m = Module()
+ comb = m.d.comb
+ width = self.width
+ shiftbits = self.shiftbits
+ shifted = Signal(self.data.width)
+ gates = self.partition_points.as_sig()
+ comb += shifted.eq(self.data << self.shifter)
+
+ parts = []
+ outputs = []
+ shiftparts = []
+ intervals = []
+ keys = list(self.partition_points.keys()) + [self.width]
+ start = 0
+ for i in range(len(keys)):
+ end = keys[i]
+ parts.append(self.data[start:end])
+ outputs.append(self.output[start:end])
+ intervals.append((start,end))
+
+ sp = Signal(width)
+ comb += sp[start:].eq(self.data[start:end] << self.shifter)
+ shiftparts.append(sp)
+
+ start = end # for next time round loop
+
+ for i, interval in enumerate(intervals):
+ start, end = interval
+ if i == 0:
+ intermed = shiftparts[i]
+ else:
+ intermed = shiftparts[i] | Mux(gates[i-1], 0, prev)
+ comb += outputs[i].eq(intermed[start:end])
+ prev = intermed
+
+ return m
--- /dev/null
+from nmigen import Module, Signal
+from nmigen.back.pysim import Simulator, Delay, Settle
+from nmigen.test.utils import FHDLTestCase
+from ieee754.part_mul_add.partpoints import PartitionPoints
+
+from ieee754.part_shift.part_shift_dynamic import \
+ PartitionedDynamicShift
+
+import unittest
+
+class DynamicShiftTestCase(FHDLTestCase):
+ def get_intervals(self, signal, points):
+ start = 0
+ interval = []
+ keys = list(points.keys()) + [signal.width]
+ for key in keys:
+ end = key
+ interval.append(signal[start:end])
+ start = end
+ return interval
+
+ def test_dynamic(self):
+ m = Module()
+ comb = m.d.comb
+ mwidth = 4
+ width = 32
+ step = int(width/mwidth)
+ gates = Signal(mwidth-1)
+ points = PartitionPoints()
+ for i in range(mwidth-1):
+ points[(i+1)*step] = gates[i]
+ a = Signal(width)
+ b = Signal(width)
+ output = Signal(width)
+ a_intervals = self.get_intervals(a, points)
+ b_intervals = self.get_intervals(b, points)
+ output_intervals = self.get_intervals(output, points)
+
+ m.submodules.dut = dut = PartitionedDynamicShift(width, points)
+ comb += [dut.a.eq(a),
+ dut.b.eq(b),
+ output.eq(dut.output)]
+
+ sim = Simulator(m)
+ def process():
+ yield a.eq(0x01010101)
+ yield b.eq(0x04030201)
+ for i in range(1<<(mwidth-1)):
+ yield gates.eq(i)
+ yield Delay(1e-6)
+ yield Settle()
+ yield gates.eq(1)
+ yield Delay(1e-6)
+ yield Settle()
+ yield gates.eq(0)
+ yield Delay(1e-6)
+ yield Settle()
+
+
+ sim.add_process(process)
+ with sim.write_vcd("test.vcd", "test.gtkw", traces=[a,b,output]):
+ sim.run()
+
+if __name__ == "__main__":
+ unittest.main()
+
+
+
+
+++ /dev/null
-proof_*/**
+++ /dev/null
-# Proof of correctness for partitioned dynamic shifter
-# Copyright (C) 2020 Michael Nolan <mtnolan2640@gmail.com>
-
-from nmigen import Module, Signal, Elaboratable, Mux, Cat
-from nmigen.asserts import Assert, AnyConst, Assume
-from nmigen.test.utils import FHDLTestCase
-from nmigen.cli import rtlil
-
-from ieee754.part_mul_add.partpoints import PartitionPoints
-from ieee754.part_shift_scalar.part_shift_dynamic import \
- PartitionedDynamicShift
-import unittest
-
-
-# This defines a module to drive the device under test and assert
-# properties about its outputs
-class ShifterDriver(Elaboratable):
- def __init__(self):
- # inputs and outputs
- pass
-
- def get_intervals(self, signal, points):
- start = 0
- interval = []
- keys = list(points.keys()) + [signal.width]
- for key in keys:
- end = key
- interval.append(signal[start:end])
- start = end
- return interval
-
- def elaborate(self, platform):
- m = Module()
- comb = m.d.comb
- width = 24
- mwidth = 3
-
- # setup the inputs and outputs of the DUT as anyconst
- a = Signal(width)
- b = Signal(width)
- out = Signal(width)
- points = PartitionPoints()
- gates = Signal(mwidth-1)
- step = int(width/mwidth)
- for i in range(mwidth-1):
- points[(i+1)*step] = gates[i]
- print(points)
-
- comb += [a.eq(AnyConst(width)),
- b.eq(AnyConst(width)),
- gates.eq(AnyConst(mwidth-1))]
-
- m.submodules.dut = dut = PartitionedDynamicShift(width, points)
-
- a_intervals = self.get_intervals(a, points)
- b_intervals = self.get_intervals(b, points)
- out_intervals = self.get_intervals(out, points)
-
- comb += [dut.a.eq(a),
- dut.b.eq(b),
- out.eq(dut.output)]
-
-
- with m.Switch(points.as_sig()):
- with m.Case(0b00):
- comb += Assume(b < 24)
- comb += Assert(out == (a<<b[0:5]) & 0xffffff)
- with m.Case(0b01):
- comb += Assume(b_intervals[0] <= 8)
- comb += Assert(out_intervals[0] ==
- (a_intervals[0]<<b_intervals[0]) & 0xff)
- comb += Assume(b_intervals[1] <= 16)
- comb += Assert(Cat(out_intervals[1:3]) ==
- (Cat(a_intervals[1:3])
- <<b_intervals[1]) & 0xffff)
- with m.Case(0b10):
- comb += Assume(b_intervals[0] <= 16)
- comb += Assert(Cat(out_intervals[0:2]) ==
- (Cat(a_intervals[0:2])
- <<b_intervals[0]) & 0xffff)
- comb += Assume(b_intervals[2] <= 16)
- comb += Assert(out_intervals[2] ==
- (a_intervals[2]<<b_intervals[2]) & 0xff)
- with m.Case(0b11):
- for i, o in enumerate(out_intervals):
- comb += Assume(b_intervals[i] < 8)
- comb += Assert(o ==
- (a_intervals[i] << b_intervals[i]) & 0xff)
-
- return m
-
-class PartitionedDynamicShiftTestCase(FHDLTestCase):
- def test_shift(self):
- module = ShifterDriver()
- self.assertFormal(module, mode="bmc", depth=4)
- def test_ilang(self):
- width = 64
- mwidth = 8
- gates = Signal(mwidth-1)
- points = PartitionPoints()
- step = int(width/mwidth)
- for i in range(mwidth-1):
- points[(i+1)*step] = gates[i]
- print(points)
- dut = PartitionedDynamicShift(width, points)
- vl = rtlil.convert(dut, ports=[gates, dut.a, dut.b, dut.output])
- with open("dynamic_shift.il", "w") as f:
- f.write(vl)
-
-
-if __name__ == "__main__":
- unittest.main()
-
+++ /dev/null
-# Proof of correctness for partitioned scalar shifter
-# Copyright (C) 2020 Michael Nolan <mtnolan2640@gmail.com>
-
-from nmigen import Module, Signal, Elaboratable, Mux, Cat
-from nmigen.asserts import Assert, AnyConst, Assume
-from nmigen.test.utils import FHDLTestCase
-from nmigen.cli import rtlil
-
-from ieee754.part_mul_add.partpoints import PartitionPoints
-from ieee754.part_shift_scalar.part_shift_scalar import PartitionedScalarShift
-import unittest
-
-
-# This defines a module to drive the device under test and assert
-# properties about its outputs
-class ShifterDriver(Elaboratable):
- def __init__(self):
- # inputs and outputs
- pass
-
- def get_intervals(self, signal, points):
- start = 0
- interval = []
- keys = list(points.keys()) + [signal.width]
- for key in keys:
- end = key
- interval.append(signal[start:end])
- start = end
- return interval
-
- def elaborate(self, platform):
- m = Module()
- comb = m.d.comb
- width = 24
- shifterwidth = 5
- mwidth = 3
-
- # setup the inputs and outputs of the DUT as anyconst
- data = Signal(width)
- out = Signal(width)
- shifter = Signal(shifterwidth)
- points = PartitionPoints()
- gates = Signal(mwidth-1)
- step = int(width/mwidth)
- for i in range(mwidth-1):
- points[(i+1)*step] = gates[i]
- print(points)
-
- comb += [data.eq(AnyConst(width)),
- shifter.eq(AnyConst(shifterwidth)),
- gates.eq(AnyConst(mwidth-1))]
-
- m.submodules.dut = dut = PartitionedScalarShift(width, points)
-
- data_intervals = self.get_intervals(data, points)
- out_intervals = self.get_intervals(out, points)
-
- comb += [dut.data.eq(data),
- dut.shifter.eq(shifter),
- out.eq(dut.output)]
-
- expected = Signal(width)
- comb += expected.eq(data << shifter)
-
- with m.Switch(points.as_sig()):
- with m.Case(0b00):
- comb += Assert(out[0:24] == (data[0:24] << shifter) & 0xffffff)
-
- with m.Case(0b01):
- comb += Assert(out[0:8] == expected[0:8])
- comb += Assert(out[8:24] == (data[8:24] << shifter) & 0xffff)
-
- with m.Case(0b10):
- comb += Assert(out[16:24] == (data[16:24] << shifter) & 0xff)
- comb += Assert(out[0:16] == (data[0:16] << shifter) & 0xffff)
-
- with m.Case(0b11):
- comb += Assert(out[0:8] == expected[0:8])
- comb += Assert(out[8:16] == (data[8:16] << shifter) & 0xff)
- comb += Assert(out[16:24] == (data[16:24] << shifter) & 0xff)
-
- return m
-
-class PartitionedScalarShiftTestCase(FHDLTestCase):
- def test_shift(self):
- module = ShifterDriver()
- self.assertFormal(module, mode="bmc", depth=4)
-
-if __name__ == "__main__":
- unittest.main()
-
+++ /dev/null
-# SPDX-License-Identifier: LGPL-2.1-or-later
-# See Notices.txt for copyright information
-
-"""
-Copyright (C) 2020 Luke Kenneth Casson Leighton <lkcl@lkcl.net>
-Copyright (C) 2020 Michael Nolan <mtnolan2640@gmail.com>
-
-dynamically partitionable shifter. Unlike part_shift_scalar, both
-operands can be partitioned
-
-See:
-
-* http://libre-riscv.org/3d_gpu/architecture/dynamic_simd/shift/
-* http://bugs.libre-riscv.org/show_bug.cgi?id=173
-"""
-from nmigen import Signal, Module, Elaboratable, Cat, Mux
-from ieee754.part_mul_add.partpoints import PartitionPoints
-import math
-
-
-class PartitionedDynamicShift(Elaboratable):
- def __init__(self, width, partition_points):
- self.width = width
- self.partition_points = PartitionPoints(partition_points)
-
- self.a = Signal(width)
- self.b = Signal(width)
- self.output = Signal(width)
-
- def elaborate(self, platform):
- m = Module()
- comb = m.d.comb
- width = self.width
- gates = Signal(self.partition_points.get_max_partition_count(width)-1)
- comb += gates.eq(self.partition_points.as_sig())
-
- matrix = []
- keys = list(self.partition_points.keys()) + [self.width]
- start = 0
-
- for i in range(len(keys)):
- row = []
- start = 0
- for j in range(len(keys)):
- end = keys[j]
- row.append(Signal(width - start,
- name="matrix[%d][%d]" % (i, j)))
- matrix.append(row)
-
- a_intervals = []
- b_intervals = []
- out_intervals = []
- intervals = []
- start = 0
- for i in range(len(keys)):
- end = keys[i]
- a_intervals.append(self.a[start:end])
- b_intervals.append(self.b[start:end])
- out_intervals.append(self.output[start:end])
- intervals.append([start,end])
- start = end
-
- for i, b in enumerate(b_intervals):
- start = 0
- for j, a in enumerate(a_intervals):
- end = keys[i]
- comb += matrix[i][j].eq(a << b)
- start = end
-
- intermed = matrix[0][0]
- comb += out_intervals[0].eq(intermed)
- for i in range(1, len(out_intervals)):
- index = gates[:i] # selects the 'i' least significant bits
- # of gates
- element = Signal(width, name="element%d" % i)
- for index in range(1<<i):
- print(index)
- with m.Switch(gates[:i]):
- with m.Case(index):
- index = math.ceil(math.log2(index + 1))
- comb += element.eq(matrix[index][i])
- print(keys[i-1])
- temp = Signal(width, name="intermed%d" % i)
- print(intermed[keys[0]:])
- intermed = Mux(gates[i-1], element, element | intermed[keys[0]:])
- comb += temp.eq(intermed)
- comb += out_intervals[i].eq(intermed)
-
-
- return m
-
+++ /dev/null
-# SPDX-License-Identifier: LGPL-2.1-or-later
-# See Notices.txt for copyright information
-
-"""
-Copyright (C) 2020 Michael Nolan <mtnolan2640@gmail.com>
-
-dynamically partitionable shifter. Only the operand to be shifted can
-be partitioned, the amount to shift by *must* be a scalar
-
-See:
-
-* http://libre-riscv.org/3d_gpu/architecture/dynamic_simd/shift/
-* http://bugs.libre-riscv.org/show_bug.cgi?id=173
-"""
-from nmigen import Signal, Module, Elaboratable, Cat, Mux
-from ieee754.part_mul_add.partpoints import PartitionPoints
-import math
-
-
-class PartitionedScalarShift(Elaboratable):
- def __init__(self, width, partition_points):
- self.width = width
- self.partition_points = PartitionPoints(partition_points)
-
- self.data = Signal(width)
- self.shiftbits = math.ceil(math.log2(width))
- self.shifter = Signal(self.shiftbits)
- self.output = Signal(width)
-
- def elaborate(self, platform):
- m = Module()
- comb = m.d.comb
- width = self.width
- shiftbits = self.shiftbits
- shifted = Signal(self.data.width)
- gates = self.partition_points.as_sig()
- comb += shifted.eq(self.data << self.shifter)
-
- parts = []
- outputs = []
- shiftparts = []
- intervals = []
- keys = list(self.partition_points.keys()) + [self.width]
- start = 0
- for i in range(len(keys)):
- end = keys[i]
- parts.append(self.data[start:end])
- outputs.append(self.output[start:end])
- intervals.append((start,end))
-
- sp = Signal(width)
- comb += sp[start:].eq(self.data[start:end] << self.shifter)
- shiftparts.append(sp)
-
- start = end # for next time round loop
-
- for i, interval in enumerate(intervals):
- start, end = interval
- if i == 0:
- intermed = shiftparts[i]
- else:
- intermed = shiftparts[i] | Mux(gates[i-1], 0, prev)
- comb += outputs[i].eq(intermed[start:end])
- prev = intermed
-
- return m
+++ /dev/null
-from nmigen import Module, Signal
-from nmigen.back.pysim import Simulator, Delay, Settle
-from nmigen.test.utils import FHDLTestCase
-from ieee754.part_mul_add.partpoints import PartitionPoints
-
-from ieee754.part_shift_scalar.part_shift_dynamic import \
- PartitionedDynamicShift
-
-import unittest
-
-class DynamicShiftTestCase(FHDLTestCase):
- def get_intervals(self, signal, points):
- start = 0
- interval = []
- keys = list(points.keys()) + [signal.width]
- for key in keys:
- end = key
- interval.append(signal[start:end])
- start = end
- return interval
-
- def test_dynamic(self):
- m = Module()
- comb = m.d.comb
- mwidth = 4
- width = 32
- step = int(width/mwidth)
- gates = Signal(mwidth-1)
- points = PartitionPoints()
- for i in range(mwidth-1):
- points[(i+1)*step] = gates[i]
- a = Signal(width)
- b = Signal(width)
- output = Signal(width)
- a_intervals = self.get_intervals(a, points)
- b_intervals = self.get_intervals(b, points)
- output_intervals = self.get_intervals(output, points)
-
- m.submodules.dut = dut = PartitionedDynamicShift(width, points)
- comb += [dut.a.eq(a),
- dut.b.eq(b),
- output.eq(dut.output)]
-
- sim = Simulator(m)
- def process():
- yield a.eq(0x01010101)
- yield b.eq(0x04030201)
- for i in range(1<<(mwidth-1)):
- yield gates.eq(i)
- yield Delay(1e-6)
- yield Settle()
- yield gates.eq(1)
- yield Delay(1e-6)
- yield Settle()
- yield gates.eq(0)
- yield Delay(1e-6)
- yield Settle()
-
-
- sim.add_process(process)
- with sim.write_vcd("test.vcd", "test.gtkw", traces=[a,b,output]):
- sim.run()
-
-if __name__ == "__main__":
- unittest.main()
-
-
-
-