- m.submodules.p_8 = p_8 = Parts(8, eps, len(part_8.parts))
- m.submodules.p_16 = p_16 = Parts(8, eps, len(part_16.parts))
- m.submodules.p_32 = p_32 = Parts(8, eps, len(part_32.parts))
- m.submodules.p_64 = p_64 = Parts(8, eps, len(part_64.parts))
+ :attribute part_pts: the input partition points. Has a partition point at
+ multiples of 8 in 0 < i < 64. Each partition point's associated
+ ``Value`` is a ``Signal``. Modification not supported, except for by
+ ``Signal.eq``.
+ :attribute part_ops: the operation for each byte. The operation for a
+ particular partition is selected by assigning the selected operation
+ code to each byte in the partition. The allowed operation codes are:
+
+ :attribute OP_MUL_LOW: the LSB half of the product. Equivalent to
+ RISC-V's `mul` instruction.
+ :attribute OP_MUL_SIGNED_HIGH: the MSB half of the product where both
+ ``a`` and ``b`` are signed. Equivalent to RISC-V's `mulh`
+ instruction.
+ :attribute OP_MUL_SIGNED_UNSIGNED_HIGH: the MSB half of the product
+ where ``a`` is signed and ``b`` is unsigned. Equivalent to RISC-V's
+ `mulhsu` instruction.
+ :attribute OP_MUL_UNSIGNED_HIGH: the MSB half of the product where both
+ ``a`` and ``b`` are unsigned. Equivalent to RISC-V's `mulhu`
+ instruction.
+ """
+
+ def __init__(self, register_levels=()):
+ """ register_levels: specifies the points in the cascade at which
+ flip-flops are to be inserted.
+ """
+
+ # parameter(s)
+ self.register_levels = list(register_levels)
+
+ self.i = self.ispec()
+ self.o = self.ospec()
+
+ # inputs
+ self.part_pts = self.i.part_pts
+ self.part_ops = self.i.part_ops
+ self.a = self.i.a
+ self.b = self.i.b
+
+ # output
+ self.intermediate_output = self.o.intermediate_output
+ self.output = self.o.output
+
+ def ispec(self):
+ return InputData()
+
+ def ospec(self):
+ return OutputData()
+
+ def elaborate(self, platform):
+ m = Module()
+
+ part_pts = self.part_pts
+
+ n_inputs = 64 + 4
+ n_parts = 8
+ t = AllTerms(n_inputs, 128, n_parts, self.register_levels)
+ m.submodules.allterms = t
+ m.d.comb += t.i.eq(self.i)
+
+ terms = t.o.terms
+
+ at = AddReduceInternal(t.o, 128, partition_step=2)
+
+ i = at.i
+ for idx in range(len(at.levels)):
+ mcur = at.levels[idx]
+ setattr(m.submodules, "addreduce_%d" % idx, mcur)
+ if idx in self.register_levels:
+ m.d.sync += mcur.i.eq(i)
+ else:
+ m.d.comb += mcur.i.eq(i)
+ i = mcur.o # for next loop