1da4e3720f40bf1096526702103e2ca9590bed19
[ieee754fpu.git] / src / ieee754 / part / test / test_partsig_scope.py
1 #!/usr/bin/env python3
2 # SPDX-License-Identifier: LGPL-2.1-or-later
3 # See Notices.txt for copyright information
4
5 from nmigen import Signal, Module, Elaboratable, Mux, Cat, Shape, Repl
6 from nmigen.back.pysim import Simulator, Delay, Settle
7 from nmigen.cli import rtlil
8
9 from ieee754.part.partsig import SimdSignal, SimdShape
10 from ieee754.part.simd_scope import SimdScope
11
12 from random import randint
13 import unittest
14 import itertools
15 import math
16
17
18 def create_ilang(dut, traces, test_name):
19 vl = rtlil.convert(dut, ports=traces)
20 with open("%s.il" % test_name, "w") as f:
21 f.write(vl)
22
23
24 def create_simulator(module, traces, test_name):
25 create_ilang(module, traces, test_name)
26 return Simulator(module)
27
28
29 class TestCatMod(Elaboratable):
30 def __init__(self, width, elwid, vec_el_counts):
31 self.m = Module()
32 s = SimdScope(self.m, elwid, vec_el_counts)
33 shape = SimdShape(s, fixed_width=width)
34 shape2 = SimdShape(s, fixed_width=width*2)
35 shape3 = SimdShape(s, fixed_width=width*3)
36 self.a = s.Signal(shape)
37 self.b = s.Signal(shape2) # TODO: shape*2
38 self.o = s.Signal(shape3) # TODO: shape*3
39 self.cat_out = self.o.sig
40
41 def elaborate(self, platform):
42 m = self.m
43 comb = m.d.comb
44
45 comb += self.o.eq(Cat(self.a, self.b))
46
47 return m
48
49
50 class TestCat(unittest.TestCase):
51 def test(self):
52 width = 16
53 elwid = Signal(2) # elwid parameter
54 vec_el_counts = {0b00: 1, 0b01: 2, 0b10: 4}
55 module = TestCatMod(width, elwid, vec_el_counts)
56
57 test_name = "part_sig_cat_scope"
58 traces = [elwid,
59 module.a.sig,
60 module.b.sig,
61 module.cat_out]
62 sim = create_simulator(module, traces, test_name)
63
64 # annoying recursive import issue
65 from ieee754.part_cat.cat import get_runlengths
66
67 def async_process():
68
69 def test_catop(msg_prefix):
70 # define lengths of a/b test input
71 alen, blen = 16, 32
72 # pairs of test values a, b
73 for a, b in [(0x0000, 0x00000000),
74 (0xDCBA, 0x12345678),
75 (0xABCD, 0x01234567),
76 (0xFFFF, 0x0000),
77 (0x0000, 0x0000),
78 (0x1F1F, 0xF1F1F1F1),
79 (0x0000, 0xFFFFFFFF)]:
80
81 # convert a and b to partitions
82 apart, bpart = [], []
83 ajump, bjump = alen // 4, blen // 4
84 for i in range(4):
85 apart.append((a >> (ajump*i) & ((1 << ajump)-1)))
86 bpart.append((b >> (bjump*i) & ((1 << bjump)-1)))
87
88 print("apart bpart", hex(a), hex(b),
89 list(map(hex, apart)), list(map(hex, bpart)))
90
91 yield module.a.lower().eq(a)
92 yield module.b.lower().eq(b)
93 yield Delay(0.1e-6)
94
95 y = 0
96 # work out the runlengths for this mask.
97 # 0b011 returns [1,1,2] (for a mask of length 3)
98 mval = yield elwid
99 runlengths = get_runlengths(mval, 3)
100 j = 0
101 ai = 0
102 bi = 0
103 for i in runlengths:
104 # a first
105 for _ in range(i):
106 print("runlength", i,
107 "ai", ai,
108 "apart", hex(apart[ai]),
109 "j", j)
110 y |= apart[ai] << j
111 print(" y", hex(y))
112 j += ajump
113 ai += 1
114 # now b
115 for _ in range(i):
116 print("runlength", i,
117 "bi", bi,
118 "bpart", hex(bpart[bi]),
119 "j", j)
120 y |= bpart[bi] << j
121 print(" y", hex(y))
122 j += bjump
123 bi += 1
124
125 # check the result
126 outval = (yield module.cat_out)
127 msg = f"{msg_prefix}: cat " + \
128 f"0x{mval:X} 0x{a:X} : 0x{b:X}" + \
129 f" => 0x{y:X} != 0x{outval:X}"
130 self.assertEqual(y, outval, msg)
131
132 yield elwid.eq(0b00)
133 yield from test_catop("16-bit")
134 yield elwid.eq(0b01)
135 yield from test_catop("8-bit")
136 yield elwid.eq(0b10)
137 yield from test_catop("4-bit")
138
139 sim.add_process(async_process)
140 with sim.write_vcd(
141 vcd_file=open(test_name + ".vcd", "w"),
142 gtkw_file=open(test_name + ".gtkw", "w"),
143 traces=traces):
144 sim.run()
145
146
147 if __name__ == '__main__':
148 unittest.main()