4 from nmigen
import Elaboratable
, Signal
, Module
, Repl
5 from nmigen
.asserts
import Assert
, Cover
7 from nmutil
.formaltest
import FHDLTestCase
8 from nmutil
.gtkw
import write_gtkw
10 from ieee754
.part
.formal
.proof_partition
import GateGenerator
, make_partitions
11 from ieee754
.part_cmp
.eq_gt_ge
import PartitionedEqGtGe
14 class Driver(Elaboratable
):
25 # Setup partition points and gates
26 step
= int(width
/mwidth
)
27 points
, gates
= make_partitions(step
, mwidth
)
29 m
.submodules
.dut
= dut
= PartitionedEqGtGe(width
, points
)
30 # instantiate the partitioned gate generator and connect the gates
31 m
.submodules
.gen
= gen
= GateGenerator(mwidth
)
32 comb
+= gates
.eq(gen
.gates
)
33 p_offset
= gen
.p_offset
35 # generate shifted down inputs and outputs
36 p_output
= Signal(mwidth
)
39 for pos
in range(mwidth
):
40 with m
.If(p_offset
== pos
):
41 comb
+= p_output
.eq(dut
.output
[pos
:])
42 comb
+= p_a
.eq(dut
.a
[pos
* step
:])
43 comb
+= p_b
.eq(dut
.b
[pos
* step
:])
44 # generate and check expected values for all possible partition sizes
45 for w
in range(1, mwidth
+1):
46 with m
.If(p_width
== w
):
47 # calculate the expected output, for the given bit width,
48 # truncating the inputs to the partition size
49 input_bit_width
= w
* step
51 expected
= Signal(output_bit_width
, name
=f
"expected_{w}")
52 a
= Signal(input_bit_width
, name
=f
"a_{w}")
53 b
= Signal(input_bit_width
, name
=f
"b_{w}")
54 lsb
= Signal(name
=f
"lsb_{w}")
55 comb
+= a
.eq(p_a
[:input_bit_width
])
56 comb
+= b
.eq(p_b
[:input_bit_width
])
57 with m
.If(dut
.opcode
== PartitionedEqGtGe
.EQ
):
58 comb
+= lsb
.eq(a
== b
)
59 with m
.Elif(dut
.opcode
== PartitionedEqGtGe
.GT
):
61 with m
.Elif(dut
.opcode
== PartitionedEqGtGe
.GE
):
62 comb
+= lsb
.eq(a
>= b
)
63 comb
+= expected
.eq(Repl(lsb
, output_bit_width
))
64 # truncate the output, compare and assert
65 comb
+= Assert(p_output
[:output_bit_width
] == expected
)
67 # make the selected partition not start at the very beginning
68 comb
+= Cover((p_offset
!= 0) & (p_width
== 3) & (dut
.a
!= dut
.b
))
72 class PartitionedEqTestCase(FHDLTestCase
):
74 def test_formal(self
):
76 'dec': {'base': 'dec'},
77 'bin': {'base': 'bin'}
80 ('p_offset[2:0]', 'dec'),
81 ('p_width[3:0]', 'dec'),
82 ('p_gates[8:0]', 'bin'),
83 ('dut', {'submodule': 'dut'}, [
84 ('gates[6:0]', 'bin'),
86 ('output[7:0]', 'bin')]),
87 ('ripple', {'submodule': 'ripple'}, [
88 ('output[7:0]', 'bin')]),
89 ('p_output[7:0]', 'bin'),
90 ('expected_3[2:0]', 'bin')]
92 'proof_partitioned_eq_gt_ge_cover.gtkw',
93 os
.path
.dirname(__file__
) +
94 '/proof_partitioned_eq_gt_ge_formal/engine_0/trace0.vcd',
100 'proof_partitioned_eq_gt_ge_bmc.gtkw',
101 os
.path
.dirname(__file__
) +
102 '/proof_partitioned_eq_gt_ge_formal/engine_0/trace.vcd',
108 self
.assertFormal(module
, mode
="bmc", depth
=1)
109 self
.assertFormal(module
, mode
="cover", depth
=1)
112 if __name__
== '__main__':