1 # SPDX-License-Identifier: LGPL-2.1-or-later
2 # See Notices.txt for copyright information
3 """Integer Multiplication."""
5 from nmigen
import Signal
, Value
, Cat
, C
7 def make_partition(mask
, width
):
8 """ from a mask and a bitwidth, create partition points.
9 note that the assumption is that the mask indicates the
10 breakpoints in regular intervals, and that the last bit (MSB)
11 of the mask is therefore *ignored*.
12 mask len = 4, width == 16 will return:
13 {4: mask[0], 8: mask[1], 12: mask[2]}
14 mask len = 8, width == 64 will return:
15 {8: mask[0], 16: mask[1], 24: mask[2], .... 56: mask[6]}
18 mlen
= mask
.shape()[0]
21 while ppos
< width
and midx
< mlen
: # -1, ignore last bit
22 ppoints
[ppos
] = mask
[midx
]
28 class PartitionPoints(dict):
29 """Partition points and corresponding ``Value``s.
31 The points at where an ALU is partitioned along with ``Value``s that
32 specify if the corresponding partition points are enabled.
34 For example: ``{1: True, 5: True, 10: True}`` with
35 ``width == 16`` specifies that the ALU is split into 4 sections:
38 * bits 5 <= ``i`` < 10
39 * bits 10 <= ``i`` < 16
41 If the partition_points were instead ``{1: True, 5: a, 10: True}``
42 where ``a`` is a 1-bit ``Signal``:
43 * If ``a`` is asserted:
46 * bits 5 <= ``i`` < 10
47 * bits 10 <= ``i`` < 16
50 * bits 1 <= ``i`` < 10
51 * bits 10 <= ``i`` < 16
54 def __init__(self
, partition_points
=None):
55 """Create a new ``PartitionPoints``.
57 :param partition_points: the input partition points to values mapping.
60 if partition_points
is not None:
61 for point
, enabled
in partition_points
.items():
62 if not isinstance(point
, int):
63 raise TypeError("point must be a non-negative integer")
65 raise ValueError("point must be a non-negative integer")
66 self
[point
] = Value
.cast(enabled
)
68 def like(self
, name
=None, src_loc_at
=0, mul
=1):
69 """Create a new ``PartitionPoints`` with ``Signal``s for all values.
71 :param name: the base name for the new ``Signal``s.
72 :param mul: a multiplication factor on the indices
75 name
= Signal(src_loc_at
=1+src_loc_at
).name
# get variable name
76 retval
= PartitionPoints()
77 for point
, enabled
in self
.items():
79 retval
[point
] = Signal(enabled
.shape(), name
=f
"{name}_{point}")
83 """Assign ``PartitionPoints`` using ``Signal.eq``."""
84 if set(self
.keys()) != set(rhs
.keys()):
85 raise ValueError("incompatible point set")
86 for point
, enabled
in self
.items():
87 yield enabled
.eq(rhs
[point
])
89 def as_mask(self
, width
, mul
=1):
90 """Create a bit-mask from `self`.
92 Each bit in the returned mask is clear only if the partition point at
93 the same bit-index is enabled.
95 :param width: the bit width of the resulting mask
96 :param mul: a "multiplier" which in-place expands the partition points
97 typically set to "2" when used for multipliers
100 for i
in range(width
):
102 if i
.is_integer() and int(i
) in self
:
103 bits
.append(~self
[i
])
109 """Create a straight concatenation of `self` signals
111 return Cat(self
.values())
113 def get_max_partition_count(self
, width
):
114 """Get the maximum number of partitions.
116 Gets the number of partitions when all partition points are enabled.
119 for point
in self
.keys():
124 def fits_in_width(self
, width
):
125 """Check if all partition points are smaller than `width`."""
126 for point
in self
.keys():
131 def part_byte(self
, index
, mfactor
=1): # mfactor used for "expanding"
132 if index
== -1 or index
== 7:
134 assert index
>= 0 and index
< 8
135 return self
[(index
* 8 + 8)*mfactor
]