1 # SPDX-License-Identifier: LGPL-2.1-or-later
2 # See Notices.txt for copyright information
5 Copyright (C) 2020 Luke Kenneth Casson Leighton <lkcl@lkcl.net>
7 dynamically-partitionable "comparison" class, directly equivalent
8 to Signal.__eq__ except SIMD-partitionable
11 from nmigen
import Signal
, Module
, Elaboratable
, Cat
, C
, Mux
, Repl
12 from nmigen
.cli
import main
14 from ieee754
.part_mul_add
.partpoints
import PartitionPoints
16 class PartitionedEq(Elaboratable
):
18 def __init__(self
, width
, partition_points
):
19 """Create a ``PartitionedEq`` operator
22 self
.a
= Signal(width
, reset_less
=True)
23 self
.b
= Signal(width
, reset_less
=True)
24 self
.partition_points
= PartitionPoints(partition_points
)
25 self
.mwidth
= len(self
.partition_points
)+1
26 self
.output
= Signal(self
.mwidth
, reset_less
=True)
27 if not self
.partition_points
.fits_in_width(width
):
28 raise ValueError("partition_points doesn't fit in width")
30 def elaborate(self
, platform
):
33 # make a series of "eqs", splitting a and b into partition chunks
34 eqs
= Signal(self
.mwidth
, reset_less
=True)
36 keys
= list(self
.partition_points
.keys()) + [self
.width
]
38 for i
in range(len(keys
)):
40 eql
.append(self
.a
[start
:end
] == self
.b
[start
:end
])
41 start
= end
# for next time round loop
42 m
.d
.comb
+= eqs
.eq(Cat(*eql
))
44 # now, based on the partition points, create the (multi-)boolean result
46 for i
in range(self
.mwidth
):
47 eqsig
= Signal(self
.mwidth
, name
="eqsig%d"%i, reset_less
=True)
49 m
.d
.comb
+= eqsig
.eq(eqs
[i
])
51 ppt
= self
.partition_points
[keys
[i
-1]]
52 m
.d
.comb
+= eqsig
.eq(eqs
[i
] & ppt
& eqsigs
[i
-1])
54 print ("eqsigs", eqsigs
, self
.output
.shape())
55 # XXX moo?? something going on here
56 for i
in range(self
.mwidth
):
57 m
.d
.comb
+= self
.output
[i
].eq(eqsigs
[i
])