c5471f51020aab84e5c3502dc9eeb76e886ee3d1
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 "xor" class, directly equivalent
8 to Signal.xor() 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
, Mux
, Repl
17 from nmigen
.cli
import main
19 from ieee754
.part_mul_add
.partpoints
import PartitionPoints
20 from ieee754
.part_cmp
.experiments
.eq_combiner
import XORCombiner
23 class PartitionedXOR(Elaboratable
):
25 def __init__(self
, width
, partition_points
):
26 """Create a ``PartitionedXOR`` operator
29 self
.a
= Signal(width
, reset_less
=True)
30 self
.partition_points
= PartitionPoints(partition_points
)
31 self
.mwidth
= len(self
.partition_points
)+1
32 self
.output
= Signal(self
.mwidth
, reset_less
=True)
33 if not self
.partition_points
.fits_in_width(width
):
34 raise ValueError("partition_points doesn't fit in width")
36 def elaborate(self
, platform
):
39 m
.submodules
.xorc
= xorc
= XORCombiner(self
.mwidth
)
41 # make a series of "xor", splitting a and b into partition chunks
42 xors
= Signal(self
.mwidth
, reset_less
=True)
44 keys
= list(self
.partition_points
.keys()) + [self
.width
]
46 for i
in range(len(keys
)):
48 xorl
.append(self
.a
[start
:end
].xor())
49 start
= end
# for next time round loop
50 comb
+= xors
.eq(Cat(*xorl
))
52 # put the partial results through the combiner
53 comb
+= xorc
.gates
.eq(self
.partition_points
.as_sig())
54 comb
+= xorc
.neqs
.eq(xors
)
55 comb
+= self
.output
.eq(xorc
.outputs
)