+ def __init__(self, pspec, lidx, n_inputs, partition_points,
+ partition_step=1):
+ self.lidx = lidx
+ self.partition_step = partition_step
+ self.output_width = pspec.width * 2
+ self.n_inputs = n_inputs
+ self.n_parts = pspec.n_parts
+ self.partition_points = PartitionPoints(partition_points)
+ if not self.partition_points.fits_in_width(self.output_width):
+ raise ValueError("partition_points doesn't fit in output_width")
+
+ super().__init__(pspec, "finaladd")
+
+ def ispec(self):
+ return AddReduceData(self.partition_points, self.n_inputs,
+ self.output_width, self.n_parts)
+
+ def ospec(self):
+ return FinalReduceData(self.partition_points,
+ self.output_width, self.n_parts)
+
+ def elaborate(self, platform):
+ """Elaborate this module."""
+ m = Module()
+
+ output_width = self.output_width
+ output = Signal(output_width, reset_less=True)
+ if self.n_inputs == 0:
+ # use 0 as the default output value
+ m.d.comb += output.eq(0)
+ elif self.n_inputs == 1:
+ # handle single input
+ m.d.comb += output.eq(self.i.terms[0])
+ else:
+ # base case for adding 2 inputs
+ assert self.n_inputs == 2
+ adder = PartitionedAdder(output_width,
+ self.i.part_pts, self.partition_step)
+ m.submodules.final_adder = adder
+ m.d.comb += adder.a.eq(self.i.terms[0])
+ m.d.comb += adder.b.eq(self.i.terms[1])
+ m.d.comb += output.eq(adder.output)
+
+ # create output
+ m.d.comb += self.o.eq_from(self.i.part_pts, output,
+ self.i.part_ops)
+
+ return m
+
+
+class AddReduceSingle(PipeModBase):