Gowin. DSP. Implement MULT27X36.

The new multiplier is made from two 27x18 units by switching inputs and
creating a cluster connected via CASO->CASI.

A second pass was required to process the multipliers created on the
fly—the processing of DSP cells was separated into a separate function,
which resulted in a large diff, but in reality there were very few
changes.

An important point is that in the 5A series, there is a gap between
adjacent DSPs in one row. There are still SIA/CASI wires, so the DSPs on
either side of the gap are connected, but the distance between them is
greater than usual. We take this fact into account based on the gap
coordinates from the chip database.

Signed-off-by: YRabbit <rabbit@yrabbit.cyou>
This commit is contained in:
YRabbit 2026-03-03 19:17:34 +10:00 committed by myrtle
parent 8c2f8810d4
commit 008ccae25b
6 changed files with 920 additions and 768 deletions

View File

@ -974,6 +974,9 @@ X(ASEL1)
X(BSEL)
X(BSEL0)
X(BSEL1)
X(CSEL)
X(PSEL)
X(PADDSUB)
X(SOA_REG)
X(DSIGN)
X(ACCLOAD)
@ -1003,6 +1006,8 @@ X(RESET1)
X(ACCSEL)
X(ACCSEL0)
X(ACCSEL1)
X(MULT27X36_MAIN)
X(MULT27X36_AUX)
// IOB types
X(IBUF)

View File

@ -73,7 +73,8 @@ inline bool is_bsram(const CellInfo *cell) { return type_is_bsram(cell->type); }
inline bool type_is_dsp(IdString cell_type)
{
return cell_type.in(id_PADD9, id_PADD18, id_MULT9X9, id_MULT18X18, id_MULT36X36, id_ALU54D, id_MULTALU18X18,
id_MULTALU36X18, id_MULTADDALU18X18, id_MULT12X12, id_MULTADDALU12X12, id_MULTALU27X18);
id_MULTALU36X18, id_MULTADDALU18X18, id_MULT12X12, id_MULTADDALU12X12, id_MULTALU27X18,
id_MULT27X36);
}
inline bool is_dsp(const CellInfo *cell) { return type_is_dsp(cell->type); }
@ -197,6 +198,8 @@ NPNR_PACKED_STRUCT(struct Extra_package_data_POD { RelSlice<Constraint_POD> cst;
NPNR_PACKED_STRUCT(struct Extra_chip_data_POD {
int32_t chip_flags;
int32_t dcs_prefix;
int16_t center_row;
int16_t center_col;
Bottom_io_POD bottom_io;
RelSlice<IdString> diff_io_types;
RelSlice<Spine_bel_POD> dqce_bels;

View File

@ -295,6 +295,8 @@ class SpineSelectWire(BBAStruct):
class ChipExtraData(BBAStruct):
strs: StringPool
flags: int
center_row: int
center_col: int
dcs_prefix: IdString = field(default = None)
bottom_io: BottomIO = field(default = None)
diff_io_types: list[IdString] = field(default_factory = list)
@ -383,6 +385,8 @@ class ChipExtraData(BBAStruct):
def serialise(self, context: str, bba: BBAWriter):
bba.u32(self.flags)
bba.u32(self.dcs_prefix.index)
bba.u16(self.center_row)
bba.u16(self.center_col)
self.bottom_io.serialise(f"{context}_bottom_io", bba)
bba.slice(f"{context}_diff_io_types", len(self.diff_io_types))
bba.slice(f"{context}_dqce_bels", len(self.dqce_bels))
@ -1550,7 +1554,19 @@ def create_packages(chip: Chip, db: chipdb):
# Extra chip data
def create_extra_data(chip: Chip, db: chipdb, chip_flags: int):
chip.extra_data = ChipExtraData(chip.strs, chip_flags)
# The coordinates of the chip center are useful when building a DSP chain
# because there is an area around this particular point that does not
# contain any DSP blocks, but there are cascade and shift wires, so the gap
# between adjacent DSPs is larger than usual at this point. The coordinates
# of this particular cell may be useful when working with 138k clock MUXs
# in the future.
center_row = 0
center_col = 0
if hasattr(db, 'center_row'):
center_row = db.center_row
center_col = db.center_col
chip.extra_data = ChipExtraData(chip.strs, chip_flags, center_row, center_col)
if hasattr(db, "dcs_prefix"):
chip.extra_data.set_dcs_prefix(db.dcs_prefix)
else:

View File

@ -510,7 +510,11 @@ Loc GowinUtils::get_dsp_next_in_chain_5a(Loc from) const
Loc res;
res.y = from.y;
// next DSP
res.x = from.x + 3;
int off = 3;
if (from.y == get_center_row() && (from.x + 5) == get_center_col()) {
off = 9;
}
res.x = from.x + off;
res.z = from.z;
return res;
}
@ -741,4 +745,16 @@ void GowinUtils::find_connected_bels(const CellInfo *cell, IdString port, IdStri
}
}
// Get spec locations
int GowinUtils::get_center_row(void) const
{
const Extra_chip_data_POD *extra = reinterpret_cast<const Extra_chip_data_POD *>(ctx->chip_info->extra_data.get());
return extra->center_row;
}
int GowinUtils::get_center_col(void) const
{
const Extra_chip_data_POD *extra = reinterpret_cast<const Extra_chip_data_POD *>(ctx->chip_info->extra_data.get());
return extra->center_col;
}
NEXTPNR_NAMESPACE_END

View File

@ -240,6 +240,10 @@ struct GowinUtils
// Find a maximum matching in a bipartite graph, g
std::vector<int> kuhn_find_maximum_bipartite_matching(int n, int k, std::vector<std::vector<int>> &g);
// Get spec locations
int get_center_row(void) const;
int get_center_col(void) const;
};
NEXTPNR_NAMESPACE_END

File diff suppressed because it is too large Load Diff