This commit is contained in:
YRabbit 2026-02-15 09:21:57 +00:00 committed by GitHub
commit 00c99e5493
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
7 changed files with 115 additions and 6 deletions

View File

@ -991,6 +991,13 @@ X(LAST_IN_CHAIN)
X(MULTALU18X18_MODE)
X(MULTADDALU18X18_MODE)
X(MULTALU36X18_MODE)
X(MULT12X12)
X(MULT27X36)
X(MULTALU27X18)
X(MULTADDALU12X12)
X(MULTACC)
X(RESET0)
X(RESET1)
// IOB types
X(IBUF)

View File

@ -51,7 +51,6 @@ struct GowinImpl : HimbaechelAPI
bool getClusterPlacement(ClusterId cluster, BelId root_bel,
std::vector<std::pair<CellInfo *, BelId>> &placement) const override;
void configurePlacerHeap(PlacerHeapCfg &cfg) override;
private:
@ -73,6 +72,8 @@ struct GowinImpl : HimbaechelAPI
// dsp info
const NetInfo *dsp_asign = nullptr, *dsp_bsign = nullptr, *dsp_asel = nullptr, *dsp_bsel = nullptr,
*dsp_ce = nullptr, *dsp_clk = nullptr, *dsp_reset = nullptr;
const NetInfo *dsp_5a_clk0 = nullptr, *dsp_5a_clk1 = nullptr, *dsp_5a_ce0 = nullptr, *dsp_5a_ce1 = nullptr,
*dsp_5a_reset0 = nullptr, *dsp_5a_reset1 = nullptr;
bool dsp_soa_reg;
};
std::vector<GowinCellInfo> fast_cell_info;
@ -274,6 +275,9 @@ void GowinImpl::pack()
// We also indicate to the router which Bel's pin to use.
void GowinImpl::adjust_dsp_pin_mapping(void)
{
if (gwu.has_5A_DSP()) {
return;
}
for (auto b2c : dsp_bel2cell) {
BelId bel = b2c.first;
Loc loc = ctx->getBelLocation(bel);
@ -728,6 +732,7 @@ bool GowinImpl::isBelLocationValid(BelId bel, bool explain_invalid) const
case ID_PADD9: /* fall-through */
case ID_PADD18: /* fall-through */
case ID_MULT9X9: /* fall-through */
case ID_MULT12X12: /* fall-through */
case ID_MULT18X18: /* fall-through */
case ID_MULTADDALU18X18: /* fall-through */
case ID_MULTALU18X18: /* fall-through */
@ -860,6 +865,12 @@ void GowinImpl::assign_cell_info()
fc.dsp_asel = get_net(id_ASEL);
fc.dsp_bsel = get_net(id_BSEL);
fc.dsp_soa_reg = ci->params.count(id_SOA_REG) && ci->params.at(id_SOA_REG).as_int64() == 1;
fc.dsp_5a_clk0 = get_net(id_CLK0);
fc.dsp_5a_clk1 = get_net(id_CLK1);
fc.dsp_5a_ce0 = get_net(id_CE0);
fc.dsp_5a_ce1 = get_net(id_CE1);
fc.dsp_5a_reset0 = get_net(id_RESET0);
fc.dsp_5a_reset1 = get_net(id_RESET1);
}
}
}
@ -987,6 +998,26 @@ bool GowinImpl::dsp_valid(Loc l, IdString bel_type, bool explain_invalid) const
}
}
}
if (bel_type == id_MULT12X12) {
int pair_z = gwu.get_dsp_paired_12(l.z);
const CellInfo *adj_dsp12 = ctx->getBoundBelCell(ctx->getBelByLocation(Loc(l.x, l.y, pair_z)));
if (adj_dsp12 != nullptr) {
const auto &adj_dsp12_data = fast_cell_info.at(adj_dsp12->flat_index);
if ((dsp_data.dsp_5a_clk0 != adj_dsp12_data.dsp_5a_clk0) ||
(dsp_data.dsp_5a_clk1 != adj_dsp12_data.dsp_5a_clk1) ||
(dsp_data.dsp_5a_ce0 != adj_dsp12_data.dsp_5a_ce0) ||
(dsp_data.dsp_5a_ce1 != adj_dsp12_data.dsp_5a_ce1) ||
(dsp_data.dsp_5a_reset0 != adj_dsp12_data.dsp_5a_reset0) ||
(dsp_data.dsp_5a_reset1 != adj_dsp12_data.dsp_5a_reset1)) {
if (explain_invalid) {
log_nonfatal_error("For MULT12X12 primitives the control signals must be same.\n");
}
return false;
}
}
}
// check for control nets "overflow"
BelId dsp_bel = ctx->getBelByLocation(Loc(l.x, l.y, BelZ::DSP_Z));
if (dsp_info.count(dsp_bel)) {
@ -1295,7 +1326,6 @@ void GowinImpl::configurePlacerHeap(PlacerHeapCfg &cfg)
cfg.ioBufTypes.insert(id_GSR);
}
} // namespace
NEXTPNR_NAMESPACE_END

View File

@ -73,7 +73,7 @@ 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_MULTALU36X18, id_MULTADDALU18X18, id_MULT12X12);
}
inline bool is_dsp(const CellInfo *cell) { return type_is_dsp(cell->type); }
@ -222,6 +222,7 @@ NPNR_PACKED_STRUCT(struct Extra_chip_data_POD {
static constexpr int32_t NEED_SDP_FIX = 2048;
static constexpr int32_t NEED_CFGPINS_INVERSION = 4096;
static constexpr int32_t HAS_I2CCFG = 8192;
static constexpr int32_t HAS_5A_DSP = 16384;
});
} // namespace
@ -329,7 +330,10 @@ enum
CLKDIV_0_Z = 620,
CLKDIV_1_Z = 621,
CLKDIV_2_Z = 622,
CLKDIV_3_Z = 623
CLKDIV_3_Z = 623,
MULT12X12_0_Z = 640,
MULT12X12_1_Z = 641
};
}

View File

@ -33,6 +33,7 @@ CHIP_NEED_BSRAM_RESET_FIX = 0x400
CHIP_NEED_SDP_FIX = 0x800
CHIP_NEED_CFGPINS_INVERSION = 0x1000
CHIP_HAS_I2CCFG = 0x2000
CHIP_HAS_5A_DSP = 0x4000
# Tile flags
TILE_I3C_CAPABLE_IO = 0x1
@ -136,6 +137,9 @@ CLKDIV_1_Z = 621
CLKDIV_2_Z = 622
CLKDIV_3_Z = 623
MULT12X12_0_Z = 640
MULT12X12_1_Z = 641
# =======================================
# Chipdb additional info
# =======================================
@ -1155,6 +1159,44 @@ def create_bsram_tiletype(chip: Chip, db: chipdb, x: int, y: int, ttyp: int, tde
tdesc.tiletype = tiletype
return tt
# GW5A series has different DSP
def create_dsp_5a_tiletype(chip: Chip, db: chipdb, x: int, y: int, ttyp: int, tdesc: TypeDesc):
typename = "DSP"
tiletype = f"{typename}_{ttyp}"
if tdesc.sfx != 0:
tiletype += f"_{tdesc.sfx}"
tt = chip.create_tile_type(tiletype)
tt.extra_data = TileExtraData(chip.strs.id(typename))
# create big DSP
belname = f'DSP'
dsp = tt.create_bel(belname, "DSP", DSP_Z)
dsp.flags = BEL_FLAG_HIDDEN
# create DSP macro
belname = 'DSP0'
dsp = tt.create_bel(belname, "DSP", DSP_0_Z)
dsp.flags = BEL_FLAG_HIDDEN
for idx in range(2):
belname = f'MULT12X120{idx}'
portmap = db[y, x].bels[belname].portmap
dsp = tt.create_bel(belname, "MULT12X12", eval(f'MULT12X12_{idx}_Z'))
for sfx in {'A', 'B'}:
for inp in range(12):
add_port_wire(tt, dsp, portmap, f"{sfx}{inp}", "DSP_I", PinType.INPUT)
for inp in range(2):
add_port_wire(tt, dsp, portmap, f"CE{inp}", "DSP_I", PinType.INPUT)
add_port_wire(tt, dsp, portmap, f"CLK{inp}", "DSP_I", PinType.INPUT)
add_port_wire(tt, dsp, portmap, f"RESET{inp}", "DSP_I", PinType.INPUT)
for outp in range(24):
add_port_wire(tt, dsp, portmap, f"DOUT{outp}", "DSP_O", PinType.OUTPUT)
tdesc.tiletype = tiletype
return tt
# DSP
_mult_inputs = {'ASEL', 'BSEL', 'ASIGN', 'BSIGN'}
def create_dsp_tiletype(chip: Chip, db: chipdb, x: int, y: int, ttyp: int, tdesc: TypeDesc):
@ -1167,7 +1209,6 @@ def create_dsp_tiletype(chip: Chip, db: chipdb, x: int, y: int, ttyp: int, tdesc
# create big DSP
belname = f'DSP'
portmap = db[y, x].bels[belname].portmap
dsp = tt.create_bel(belname, "DSP", DSP_Z)
dsp.flags = BEL_FLAG_HIDDEN
@ -1687,8 +1728,10 @@ def main():
chip_flags |= CHIP_NEED_SDP_FIX;
if "NEED_CFGPINS_INVERSION" in db.chip_flags:
chip_flags |= CHIP_NEED_CFGPINS_INVERSION;
if "CHIP_HAS_I2CCFG" in db.chip_flags:
if "HAS_I2CCFG" in db.chip_flags:
chip_flags |= CHIP_HAS_I2CCFG;
if "HAS_5A_DSP" in db.chip_flags:
chip_flags |= CHIP_HAS_5A_DSP;
X = db.cols;
Y = db.rows;
@ -1710,6 +1753,7 @@ def main():
pll_tiletypes = db.tile_types['P']
bsram_tiletypes = db.tile_types.get('B', set())
dsp_tiletypes = db.tile_types.get('D', set())
dsp_5a_tiletypes = db.tile_types.get('D5A', set())
# If Apicula does not specify a special location for the global GND and VCC
# sources, place them at X0Y0.
@ -1731,6 +1775,8 @@ def main():
create_tiletype(create_bsram_tiletype, ch, db, x, y, ttyp)
elif ttyp in dsp_tiletypes:
create_tiletype(create_dsp_tiletype, ch, db, x, y, ttyp)
elif ttyp in dsp_5a_tiletypes:
create_tiletype(create_dsp_5a_tiletype, ch, db, x, y, ttyp)
else:
create_tiletype(create_null_tiletype, ch, db, x, y, ttyp)

View File

@ -462,6 +462,12 @@ std::unique_ptr<CellInfo> GowinUtils::create_cell(IdString name, IdString type)
}
// DSP
bool GowinUtils::has_5A_DSP(void) const
{
const Extra_chip_data_POD *extra = reinterpret_cast<const Extra_chip_data_POD *>(ctx->chip_info->extra_data.get());
return extra->chip_flags & Extra_chip_data_POD::HAS_5A_DSP;
}
Loc GowinUtils::get_dsp_next_9_in_chain(Loc from) const
{
Loc res;

View File

@ -131,10 +131,12 @@ struct GowinUtils
bool has_spine_enable_nets(void) const;
// DSP
bool has_5A_DSP(void) const;
inline int get_dsp_18_z(int z) const { return z & (~3); }
inline int get_dsp_9_idx(int z) const { return z & 3; }
inline int get_dsp_18_idx(int z) const { return z & 4; }
inline int get_dsp_paired_9(int z) const { return (3 - get_dsp_9_idx(z)) | (z & (~3)); }
inline int get_dsp_paired_12(int z) const { return BelZ::MULT12X12_1_Z - (z & 1); }
inline int get_dsp_mult_from_padd(int padd_z) const { return padd_z + 8; }
inline int get_dsp_padd_from_mult(int mult_z) const { return mult_z - 8; }
inline int get_dsp_next_macro(int z) const { return z + 32; }

View File

@ -3190,6 +3190,20 @@ struct GowinPacker
}
}
} break;
case ID_MULT12X12: {
for (int i = 0; i < 2; ++i) {
ci->renamePort(ctx->idf("CLK[%d]", i), ctx->idf("CLK%d", i));
ci->renamePort(ctx->idf("CE[%d]", i), ctx->idf("CE%d", i));
ci->renamePort(ctx->idf("RESET[%d]", i), ctx->idf("RESET%d", i));
}
for (int i = 0; i < 12; ++i) {
ci->renamePort(ctx->idf("A[%d]", i), ctx->idf("A%d", i));
ci->renamePort(ctx->idf("B[%d]", i), ctx->idf("B%d", i));
}
for (int i = 0; i < 24; ++i) {
ci->renamePort(ctx->idf("DOUT[%d]", i), ctx->idf("DOUT%d", i));
}
} break;
case ID_MULT18X18: {
pass_net_type(ci, id_ASEL);
pass_net_type(ci, id_BSEL);