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
12 * http://libre-riscv.org/3d_gpu/architecture/dynamic_simd/eq
13 * http://bugs.libre-riscv.org/show_bug.cgi?id=132
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
.gt_combiner
import GTCombiner
23 class PartitionedEqGtGe(Elaboratable
):
25 # Expansion of the partitioned equals module to handle Greater
26 # Than and Greater than or Equal to. The function being evaluated
27 # is selected by the opcode signal, where:
31 def __init__(self
, width
, partition_points
):
32 """Create a ``PartitionedEq`` operator
35 self
.a
= Signal(width
, reset_less
=True)
36 self
.b
= Signal(width
, reset_less
=True)
37 self
.opcode
= Signal(2)
38 self
.partition_points
= PartitionPoints(partition_points
)
39 self
.mwidth
= len(self
.partition_points
)+1
40 self
.output
= Signal(self
.mwidth
, reset_less
=True)
41 if not self
.partition_points
.fits_in_width(width
):
42 raise ValueError("partition_points doesn't fit in width")
44 def elaborate(self
, platform
):
47 m
.submodules
.gtc
= gtc
= GTCombiner(self
.mwidth
)
49 # make a series of "eqs" and "gts", splitting a and b into partition chunks
50 eqs
= Signal(self
.mwidth
, reset_less
=True)
52 gts
= Signal(self
.mwidth
, reset_less
=True)
55 keys
= list(self
.partition_points
.keys()) + [self
.width
]
57 for i
in range(len(keys
)):
59 eql
.append(self
.a
[start
:end
] == self
.b
[start
:end
])
60 gtl
.append(self
.a
[start
:end
] > self
.b
[start
:end
])
61 start
= end
# for next time round loop
62 comb
+= eqs
.eq(Cat(*eql
))
63 comb
+= gts
.eq(Cat(*gtl
))
65 # Signal to control the constant injected into the partition next to a closed gate
67 # Signal to enable or disable the gt input for the gt partition combiner
70 with m
.Switch(self
.opcode
):
71 with m
.Case(0b00): # equals
72 comb
+= aux_input
.eq(1)
74 with m
.Case(0b01): # greater than
75 comb
+= aux_input
.eq(0)
77 with m
.Case(0b10): # greater than or equal to
78 comb
+= aux_input
.eq(1)
81 comb
+= gtc
.gates
.eq(self
.partition_points
.as_sig())
82 comb
+= gtc
.eqs
.eq(eqs
)
83 comb
+= gtc
.gts
.eq(gts
)
84 comb
+= gtc
.aux_input
.eq(aux_input
)
85 comb
+= gtc
.gt_en
.eq(gt_en
)
86 comb
+= self
.output
.eq(gtc
.outputs
)