6c9e2cb6d9df763fdc61efba517b2c82e08f4fa1
1 # SPDX-License-Identifier: LGPL-2.1-or-later
2 # See Notices.txt for copyright information
5 Copyright (C) 2020,2021 Luke Kenneth Casson Leighton <lkcl@lkcl.net>
7 dynamically-partitionable "bool" class, directly equivalent
8 to Signal.bool() except SIMD-partitionable
12 * http://libre-riscv.org/3d_gpu/architecture/dynamic_simd/logicops
13 * http://bugs.libre-riscv.org/show_bug.cgi?id=176
16 from nmigen
import Signal
, Module
, Elaboratable
, Cat
, C
17 from nmigen
.back
.pysim
import Simulator
, Settle
18 from nmigen
.cli
import rtlil
19 from nmutil
.ripple
import RippleLSB
21 from ieee754
.part_mul_add
.partpoints
import PartitionPoints
22 from ieee754
.part_cmp
.experiments
.eq_combiner
import EQCombiner
25 class PartitionedBool(Elaboratable
):
27 def __init__(self
, width
, partition_points
):
28 """Create a ``PartitionedBool`` operator
31 self
.a
= Signal(width
, reset_less
=True)
32 self
.partition_points
= PartitionPoints(partition_points
)
33 self
.mwidth
= len(self
.partition_points
)+1
34 self
.output
= Signal(self
.mwidth
, reset_less
=True)
35 if not self
.partition_points
.fits_in_width(width
):
36 raise ValueError("partition_points doesn't fit in width")
38 def elaborate(self
, platform
):
41 m
.submodules
.boolc
= boolc
= EQCombiner(self
.mwidth
)
43 # make a series of "bool", splitting a and b into partition chunks
44 bools
= Signal(self
.mwidth
, reset_less
=True)
46 keys
= list(self
.partition_points
.keys()) + [self
.width
]
48 for i
in range(len(keys
)):
50 booll
.append(self
.a
[start
:end
].bool())
51 start
= end
# for next time round loop
52 comb
+= bools
.eq(Cat(*booll
))
54 # put the partial results through the combiner
55 comb
+= boolc
.gates
.eq(self
.partition_points
.as_sig())
56 comb
+= boolc
.neqs
.eq(bools
)
58 m
.submodules
.ripple
= ripple
= RippleLSB(self
.mwidth
)
59 comb
+= ripple
.results_in
.eq(boolc
.outputs
)
60 comb
+= ripple
.gates
.eq(self
.partition_points
.as_sig())
61 comb
+= self
.output
.eq(~ripple
.output
)
66 return [self
.a
, self
.output
]
69 if __name__
== "__main__":
71 from ieee754
.part_mul_add
.partpoints
import make_partition
74 m
.submodules
.mbool
= mbool
= PartitionedBool(16, make_partition(mask
, 16))
76 vl
= rtlil
.convert(mbool
, ports
=mbool
.ports())
77 with
open("part_bool.il", "w") as f
:
84 yield mbool
.a
.eq(0x80c4)
86 out
= yield mbool
.output
89 print("in", hex(a
), "out", bin(out
), "mask", bin(m
))
93 out
= yield mbool
.output
96 print("in", hex(a
), "out", bin(out
), "mask", bin(m
))
100 out
= yield mbool
.output
103 print("in", hex(a
), "out", bin(out
), "mask", bin(m
))
106 yield mbool
.a
.eq(0x0300)
108 out
= yield mbool
.output
111 print("in", hex(a
), "out", bin(out
), "mask", bin(m
))
115 out
= yield mbool
.output
118 print("in", hex(a
), "out", bin(out
), "mask", bin(m
))
122 out
= yield mbool
.output
125 print("in", hex(a
), "out", bin(out
), "mask", bin(m
))
129 out
= yield mbool
.output
132 print("in", hex(a
), "out", bin(out
), "mask", bin(m
))
134 sim
.add_process(process
)
135 with sim
.write_vcd("part_bool.vcd", "part_bool.gtkw", traces
=mbool
.ports()):