CDC packing

This commit is contained in:
Miodrag Milanovic 2024-06-23 18:15:42 +02:00
parent 50485371fa
commit 61073f5aa7
4 changed files with 343 additions and 2 deletions

View File

@ -97,6 +97,38 @@ enum ClusterPlacement
PLACE_XRF_WE,
PLACE_XRF_WEA,
PLACE_DSP_CHAIN,
PLACE_CDC_AI1,
PLACE_CDC_AI2,
PLACE_CDC_AI3,
PLACE_CDC_AI4,
PLACE_CDC_AI5,
PLACE_CDC_AI6,
PLACE_CDC_BI1,
PLACE_CDC_BI2,
PLACE_CDC_BI3,
PLACE_CDC_BI4,
PLACE_CDC_BI5,
PLACE_CDC_BI6,
PLACE_CDC_ASRSTI,
PLACE_CDC_ADRSTI,
PLACE_CDC_BSRSTI,
PLACE_CDC_BDRSTI,
PLACE_CDC_CI1,
PLACE_CDC_CI2,
PLACE_CDC_CI3,
PLACE_CDC_CI4,
PLACE_CDC_CI5,
PLACE_CDC_CI6,
PLACE_CDC_DI1,
PLACE_CDC_DI2,
PLACE_CDC_DI3,
PLACE_CDC_DI4,
PLACE_CDC_DI5,
PLACE_CDC_DI6,
PLACE_CDC_CSRSTI,
PLACE_CDC_CDRSTI,
PLACE_CDC_DSRSTI,
PLACE_CDC_DDRSTI,
};
enum PipExtra

View File

@ -409,6 +409,14 @@ IdString NgUltraImpl::getBelBucketForCellType(IdString cell_type) const
return id_RF;
else if (cell_type.in(id_XHRF, id_XWRF, id_XPRF))
return id_XRF;
else if (cell_type.in(id_DDE, id_TDE, id_CDC, id_BGC, id_GBC))
return id_CDC;
else if (cell_type.in(id_XCDC))
return id_XCDC;
else if (cell_type.in(id_FIFO))
return id_FIFO;
else if (cell_type.in(id_XHFIFO, id_XWFIFO))
return id_XFIFO;
else if (cell_type.in(id_WFB, id_WFG))
return id_WFG;
else
@ -430,6 +438,14 @@ bool NgUltraImpl::isValidBelForCellType(IdString cell_type, BelId bel) const
return cell_type.in(id_RF,id_RFSP);
else if (bel_type == id_XRF)
return cell_type.in(id_XHRF,id_XWRF,id_XPRF);
else if (bel_type == id_CDC)
return cell_type.in(id_DDE, id_TDE, id_CDC, id_BGC, id_GBC);
else if (bel_type == id_XCDC)
return cell_type.in(id_XCDC);
else if (bel_type == id_FIFO)
return cell_type.in(id_FIFO);
else if (bel_type == id_XFIFO)
return cell_type.in(id_XHFIFO, id_XWFIFO);
else if (bel_type == id_WFG)
return cell_type.in(id_WFB,id_WFG);
else
@ -575,6 +591,109 @@ Loc getXRFFE(Loc root, int pos)
return result;
}
Loc getCDCFE(Loc root, int pos)
{
static const std::vector<Loc> cdc1 =
{
Loc(+1, 0, 1), // AI1
Loc(+1, 0, 2), // AI2
Loc(+1, 0, 9), // AI3
Loc(+1, 0, 17),// AI4
Loc(+1, 0, 18),// AI5
Loc(+1, 0, 25),// AI6
Loc(+1, 0, 3), // BI1
Loc(+1, 0, 10),// BI2
Loc(+1, 0, 11),// BI3
Loc(+1, 0, 19),// BI4
Loc(+1, 0, 26),// BI5
Loc(+1, 0, 27),// BI6
Loc( 0, 0, 22),// ASRSTI
Loc( 0, 0, 30),// ADRSTI
Loc(+1, 0, 24),// BSRSTI
Loc(+1, 0, 8), // BDRSTI
};
static const std::vector<Loc> cdc2 =
{
Loc(-1, 0, 4), // AI1
Loc(-1, 0, 5), // AI2
Loc(-1, 0, 12),// AI3
Loc(-1, 0, 20),// AI4
Loc(-1, 0, 21),// AI5
Loc(-1, 0, 28),// AI6
Loc(-1, 0, 6), // BI1
Loc(-1, 0, 13),// BI2
Loc(-1, 0, 14),// BI3
Loc(-1, 0, 22),// BI4
Loc(-1, 0, 29),// BI5
Loc(-1, 0, 30),// BI6
Loc( 0, 0, 22),// ASRSTI
Loc( 0, 0, 30),// ADRSTI
Loc(-1, 0, 23),// BSRSTI
Loc(-1, 0, 7), // BDRSTI
};
static const std::vector<Loc> xcdc =
{
Loc( 0, 0, 1), // AI1
Loc( 0, 0, 2), // AI2
Loc( 0, 0, 9), // AI3
Loc( 0, 0, 17),// AI4
Loc( 0, 0, 18),// AI5
Loc( 0, 0, 25),// AI6
Loc( 0, 0, 4), // BI1
Loc( 0, 0, 5), // BI2
Loc( 0, 0, 12),// BI3
Loc( 0, 0, 20),// BI4
Loc( 0, 0, 21),// BI5
Loc( 0, 0, 28),// BI6
Loc(-1, 0, 22),// ASRSTI
Loc(-1, 0, 30),// ADRSTI
Loc(+1, 0, 22),// BSRSTI
Loc(+1, 0, 30),// BDRSTI
Loc( 0, 0, 3), // CI1
Loc( 0, 0, 10),// CI2
Loc( 0, 0, 11),// CI3
Loc( 0, 0, 19),// CI4
Loc( 0, 0, 26),// CI5
Loc( 0, 0, 27),// CI6
Loc( 0, 0, 6), // DI1
Loc( 0, 0, 13),// DI2
Loc( 0, 0, 14),// DI3
Loc( 0, 0, 22),// DI4
Loc( 0, 0, 29),// DI5
Loc( 0, 0, 30),// DI6
Loc( 0, 0, 24),// CSRSTI
Loc( 0, 0, 8), // CDRSTI
Loc( 0, 0, 23),// DSRSTI
Loc( 0, 0, 7), // DDRSTI
};
Loc result;
if (root.z == BEL_CDC_Z) {
result = cdc1.at(pos);
} else if (root.z == BEL_CDC_Z+1) {
result = cdc2.at(pos);
} else if (root.z == BEL_XCDC_Z) {
result = xcdc.at(pos);
} else {
log_error("Trying to place CDC on wrong location.\n");
}
result.x += root.x;
result.y = root.y;
return result;
}
bool NgUltraImpl::getChildPlacement(const BaseClusterInfo *cluster, Loc root_loc,
std::vector<std::pair<CellInfo *, BelId>> &placement) const
{
@ -589,6 +708,8 @@ bool NgUltraImpl::getChildPlacement(const BaseClusterInfo *cluster, Loc root_loc
case PLACE_CY_FE4: return getCYFE(root_loc,3);
case PLACE_XRF_I1 ... PLACE_XRF_WEA:
return getXRFFE(root_loc, child->constr_z - PLACE_XRF_I1 );
case PLACE_CDC_AI1 ... PLACE_CDC_DDRSTI:
return getCDCFE(root_loc, child->constr_z - PLACE_CDC_AI1 );
case PLACE_DSP_CHAIN : { Loc l = getNextLocInDSPChain(this, prev); prev = l; return l; }
default:
Loc result;

View File

@ -988,6 +988,172 @@ void NgUltraPacker::pack_rfs(void)
flush_cells();
}
void NgUltraPacker::pack_cdcs(void)
{
log_info("Packing CDCs..\n");
int lut_only = 0, lut_and_ff = 0, dff_only = 0;
for (auto &cell : ctx->cells) {
CellInfo &ci = *cell.second;
if (!ci.type.in(id_NX_CDC_U))
continue;
int mode = int_or_default(ci.params, ctx->id("mode"), 0);
switch(mode) {
case 0 : ci.type = id_DDE; break;
case 1 : ci.type = id_TDE; break;
case 2 : ci.type = id_CDC; break;
case 3 : ci.type = id_BGC; break;
case 4 : ci.type = id_GBC; break;
case 5 : ci.type = id_XCDC; break;
default:
log_error("Unknown mode %d for cell '%s'.\n", mode, ci.name.c_str(ctx));
}
ci.cluster = ci.name;
// If unconnected, connect GND to inputs that are actually used as outputs
for (int i = 1; i <= 6; i++) {
if (ci.getPort(ctx->idf("AO%d",i))) {
connect_gnd_if_unconnected(&ci, ctx->idf("AI%d",i));
pack_xrf_input_and_output(&ci, ci.name, ctx->idf("AI%d",i), ctx->idf("AO%d",i), ClusterPlacement(PLACE_CDC_AI1 + i-1), lut_only, lut_and_ff, dff_only);
} else
disconnect_unused(&ci, ctx->idf("AI%d",i));
if (ci.getPort(ctx->idf("BO%d",i))) {
connect_gnd_if_unconnected(&ci, ctx->idf("BI%d",i));
pack_xrf_input_and_output(&ci, ci.name, ctx->idf("BI%d",i), ctx->idf("BO%d",i), ClusterPlacement(PLACE_CDC_BI1 + i-1), lut_only, lut_and_ff, dff_only);
} else
disconnect_unused(&ci, ctx->idf("BI%d",i));
if (ci.type.in(id_XCDC)) {
if (ci.getPort(ctx->idf("CO%d",i))) {
connect_gnd_if_unconnected(&ci, ctx->idf("CI%d",i));
pack_xrf_input_and_output(&ci, ci.name, ctx->idf("CI%d",i), ctx->idf("CO%d",i), ClusterPlacement(PLACE_CDC_CI1 + i-1), lut_only, lut_and_ff, dff_only);
} else
disconnect_unused(&ci, ctx->idf("CI%d",i));
if (ci.getPort(ctx->idf("DO%d",i))) {
connect_gnd_if_unconnected(&ci, ctx->idf("DI%d",i));
pack_xrf_input_and_output(&ci, ci.name, ctx->idf("DI%d",i), ctx->idf("DO%d",i), ClusterPlacement(PLACE_CDC_DI1 + i-1), lut_only, lut_and_ff, dff_only);
} else
disconnect_unused(&ci, ctx->idf("DI%d",i));
}
}
// Remove inputs and outputs that are not used for specific types
if (ci.type.in(id_BGC, id_GBC)) {
disconnect_unused(&ci, id_CK1);
disconnect_unused(&ci, id_CK2);
disconnect_unused(&ci, id_ADRSTI);
disconnect_unused(&ci, id_ADRSTO);
disconnect_unused(&ci, id_BDRSTI);
disconnect_unused(&ci, id_BDRSTO);
} else {
connect_gnd_if_unconnected(&ci, id_ADRSTI);
pack_xrf_input_and_output(&ci, ci.name, id_ADRSTI, id_ADRSTO, PLACE_CDC_ADRSTI, lut_only, lut_and_ff, dff_only);
connect_gnd_if_unconnected(&ci, id_BDRSTI);
pack_xrf_input_and_output(&ci, ci.name, id_BDRSTI, id_BDRSTO, PLACE_CDC_BDRSTI, lut_only, lut_and_ff, dff_only);
}
if (ci.type.in(id_BGC, id_GBC, id_DDE)) {
disconnect_unused(&ci, id_ASRSTI);
disconnect_unused(&ci, id_ASRSTO);
disconnect_unused(&ci, id_BSRSTI);
disconnect_unused(&ci, id_BSRSTO);
} else {
connect_gnd_if_unconnected(&ci, id_ASRSTI);
pack_xrf_input_and_output(&ci, ci.name, id_ASRSTI, id_ASRSTO, PLACE_CDC_ASRSTI, lut_only, lut_and_ff, dff_only);
connect_gnd_if_unconnected(&ci, id_BSRSTI);
pack_xrf_input_and_output(&ci, ci.name, id_BSRSTI, id_BSRSTO, PLACE_CDC_BSRSTI, lut_only, lut_and_ff, dff_only);
}
// Only XCDC is using these ports, remove from others if used
if (!ci.type.in(id_XCDC)) {
disconnect_unused(&ci, id_CDRSTI);
disconnect_unused(&ci, id_CDRSTO);
for (int i = 1; i <= 6; i++) {
disconnect_unused(&ci,ctx->idf("CI%d",i));
disconnect_unused(&ci,ctx->idf("CO%d",i));
}
disconnect_unused(&ci, id_CSRSTI);
disconnect_unused(&ci, id_CSRSTO);
disconnect_unused(&ci, id_DDRSTI);
disconnect_unused(&ci, id_DDRSTO);
for (int i = 1; i <= 6; i++) {
disconnect_unused(&ci,ctx->idf("DI%d",i));
disconnect_unused(&ci,ctx->idf("DO%d",i));
}
disconnect_unused(&ci, id_DSRSTI);
disconnect_unused(&ci, id_DSRSTO);
} else {
connect_gnd_if_unconnected(&ci, id_CDRSTI);
pack_xrf_input_and_output(&ci, ci.name, id_CDRSTI, id_CDRSTO, PLACE_CDC_CDRSTI, lut_only, lut_and_ff, dff_only);
connect_gnd_if_unconnected(&ci, id_DDRSTI);
pack_xrf_input_and_output(&ci, ci.name, id_DDRSTI, id_DDRSTO, PLACE_CDC_DDRSTI, lut_only, lut_and_ff, dff_only);
connect_gnd_if_unconnected(&ci, id_CSRSTI);
pack_xrf_input_and_output(&ci, ci.name, id_CSRSTI, id_CSRSTO, PLACE_CDC_CSRSTI, lut_only, lut_and_ff, dff_only);
connect_gnd_if_unconnected(&ci, id_DSRSTI);
pack_xrf_input_and_output(&ci, ci.name, id_DSRSTI, id_DSRSTO, PLACE_CDC_DSRSTI, lut_only, lut_and_ff, dff_only);
}
}
if (lut_only)
log_info(" %6d FEs used as LUT only\n", lut_only);
if (lut_and_ff)
log_info(" %6d FEs used as LUT and DFF\n", lut_and_ff);
if (dff_only)
log_info(" %6d FEs used as DFF only\n", dff_only);
flush_cells();
}
void NgUltraPacker::pack_fifos(void)
{
log_info("Packing FIFOs..\n");
int lut_only = 0, lut_and_ff = 0, dff_only = 0;
for (auto &cell : ctx->cells) {
CellInfo &ci = *cell.second;
if (!ci.type.in(id_NX_FIFO_U))
continue;
int mode = int_or_default(ci.params, ctx->id("mode"), 0);
switch(mode) {
case 0 : ci.type = id_FIFO; break;
case 1 : ci.type = id_XHFIFO; break;
case 2 : ci.type = id_XWFIFO; break;
default:
log_error("Unknown mode %d for cell '%s'.\n", mode, ci.name.c_str(ctx));
}
//ci.cluster = ci.name;
if (mode > 0) {
// XFIFO
ci.ports[id_WCK1].name = id_WCK1;
ci.ports[id_WCK1].type = PORT_IN;
ci.ports[id_WCK2].name = id_WCK2;
ci.ports[id_WCK2].type = PORT_IN;
ci.ports[id_RCK1].name = id_RCK1;
ci.ports[id_RCK1].type = PORT_IN;
ci.ports[id_RCK2].name = id_RCK2;
ci.ports[id_RCK2].type = PORT_IN;
NetInfo *net = ci.getPort(id_WCK);
if (net) {
ci.disconnectPort(id_WCK);
ci.connectPort(id_WCK1, net);
ci.connectPort(id_WCK2, net);
}
net = ci.getPort(id_RCK);
if (net) {
ci.disconnectPort(id_RCK);
ci.connectPort(id_RCK1, net);
ci.connectPort(id_RCK2, net);
}
}
}
if (lut_only)
log_info(" %6d FEs used as LUT only\n", lut_only);
if (lut_and_ff)
log_info(" %6d FEs used as LUT and DFF\n", lut_and_ff);
if (dff_only)
log_info(" %6d FEs used as DFF only\n", dff_only);
flush_cells();
}
void NgUltraPacker::insert_ioms()
{
std::vector<IdString> pins_needing_iom;
@ -1404,6 +1570,22 @@ void NgUltraPacker::pack_dsps(void)
}
}
}
void NgUltraPacker::remove_not_used()
{
for (auto &cell : ctx->cells) {
CellInfo &ci = *cell.second;
for (auto &p : ci.ports) {
if (p.second.type == PortType::PORT_OUT) {
NetInfo *net = ci.getPort(p.first);
if (net && net->users.entries()==0) {
ci.disconnectPort(p.first);
}
}
}
}
}
void NgUltraPacker::setup()
{
// Note: These are per Cell type not Bel type
@ -1484,6 +1666,7 @@ void NgUltraImpl::pack()
// Setup
NgUltraPacker packer(ctx, this);
packer.setup();
packer.remove_not_used();
packer.pack_constants();
packer.update_lut_init();
packer.update_dffs();
@ -1494,6 +1677,8 @@ void NgUltraImpl::pack()
// TILE
packer.pack_rfs();
packer.pack_cdcs();
packer.pack_fifos();
packer.pack_cys();
packer.pack_lut_dffs();
packer.pack_dffs();
@ -1549,7 +1734,7 @@ void NgUltraPacker::pre_place(void)
NetInfo *ref = ci.getPort(id_REF);
if (ref && ref->driver.cell && ref->driver.cell->type == id_IOM) {
IdString bank= uarch->tile_name_id(ref->driver.cell->bel.tile);
bool found = false;
//bool found = false;
for (auto &item : uarch->unused_pll) {
BelId bel = item.first;
std::pair<IdString,IdString>& ckgs = uarch->bank_to_ckg[bank];
@ -1557,7 +1742,7 @@ void NgUltraPacker::pre_place(void)
uarch->unused_pll.erase(bel);
log_info(" Using PLL in '%s' for cell '%s'.\n", uarch->tile_name(bel.tile).c_str(), ci.name.c_str(ctx));
ctx->bindBel(bel, &ci, PlaceStrength::STRENGTH_LOCKED);
found = true;
//found = true;
break;
}
}

View File

@ -38,6 +38,7 @@ struct NgUltraPacker
{
NgUltraPacker(Context *ctx, NgUltraImpl *uarch) : ctx(ctx), uarch(uarch) { h.init(ctx); };
void remove_not_used();
// Constants
void pack_constants();
void remove_constants();
@ -49,6 +50,8 @@ struct NgUltraPacker
void pack_dffs();
void pack_cys();
void pack_rfs();
void pack_cdcs();
void pack_fifos();
void pack_rams();
void pack_dsps();