Initial memory support

This commit is contained in:
Miodrag Milanovic 2024-05-14 16:45:22 +02:00
parent de090c7a77
commit 1437f1c209
5 changed files with 398 additions and 1 deletions

View File

@ -349,6 +349,12 @@ struct BitstreamJsonBackend
close_instance();
}
void write_rf(CellInfo *cell) {
open_instance(cell, "RF");
add_config("wck_edge", bool_or_default(cell->params, ctx->id("wck_edge"), false));
close_instance();
}
void write_interconnections()
{
for (auto &net : ctx->nets) {
@ -400,7 +406,8 @@ struct BitstreamJsonBackend
//case id_XLUT.index:
//case id_RAM.index:
//case id_RF.index:
//case id_XRF.index:
case id_RF.index: write_rf(cell.second.get()); break;
//case id_XRF.index: write_xrf(cell.second.get()); break;
//case id_FIFO.index:
//case id_XFIFO.index:
//case id_CDC.index:

View File

@ -42,6 +42,60 @@ enum ClusterPlacement
PLACE_CY_FE2,
PLACE_CY_FE3,
PLACE_CY_FE4,
PLACE_XRF_I1,
PLACE_XRF_I2,
PLACE_XRF_I3,
PLACE_XRF_I4,
PLACE_XRF_I5,
PLACE_XRF_I6,
PLACE_XRF_I7,
PLACE_XRF_I8,
PLACE_XRF_I9,
PLACE_XRF_I10,
PLACE_XRF_I11,
PLACE_XRF_I12,
PLACE_XRF_I13,
PLACE_XRF_I14,
PLACE_XRF_I15,
PLACE_XRF_I16,
PLACE_XRF_I17,
PLACE_XRF_I18,
PLACE_XRF_I19,
PLACE_XRF_I20,
PLACE_XRF_I21,
PLACE_XRF_I22,
PLACE_XRF_I23,
PLACE_XRF_I24,
PLACE_XRF_I25,
PLACE_XRF_I26,
PLACE_XRF_I27,
PLACE_XRF_I28,
PLACE_XRF_I29,
PLACE_XRF_I30,
PLACE_XRF_I31,
PLACE_XRF_I32,
PLACE_XRF_I33,
PLACE_XRF_I34,
PLACE_XRF_I35,
PLACE_XRF_I36,
PLACE_XRF_RA1,
PLACE_XRF_RA2,
PLACE_XRF_RA3,
PLACE_XRF_RA4,
PLACE_XRF_RA5,
PLACE_XRF_RA6,
PLACE_XRF_RA7,
PLACE_XRF_RA8,
PLACE_XRF_RA9,
PLACE_XRF_RA10,
PLACE_XRF_WA1,
PLACE_XRF_WA2,
PLACE_XRF_WA3,
PLACE_XRF_WA4,
PLACE_XRF_WA5,
PLACE_XRF_WA6,
PLACE_XRF_WE,
PLACE_XRF_WEA,
};
enum PipExtra

View File

@ -347,6 +347,78 @@ Loc getCYFE(Loc root, int pos)
return result;
}
Loc getXRFFE(Loc root, int pos)
{
static const std::vector<Loc> map =
{
Loc(-1, 0, 1),// I/O1
Loc(-1, 0, 2),// I/O2
Loc(-1, 0, 5),// I/O3
Loc(-1, 0, 6),// I/O4
Loc(-1, 0, 7),// I/O5
Loc(-1, 0, 9),// I/O6
Loc(-1, 0, 10),// I/O7
Loc(-1, 0, 13),// I/O8
Loc(-1, 0, 14),// I/O9
Loc(-1, 0, 15),// I/O10
Loc(-1, 0, 16),// I/O11
Loc(-1, 0, 17),// I/O12
Loc(-1, 0, 18),// I/O13
Loc(-1, 0, 21),// I/O14
Loc(-1, 0, 24),// I/O15
Loc(-1, 0, 25),// I/O16
Loc(-1, 0, 26),// I/O17
Loc(-1, 0, 29),// I/O18
Loc(+1, 0, 1),// I/O19
Loc(+1, 0, 2),// I/O20
Loc(+1, 0, 5),// I/O21
Loc(+1, 0, 6),// I/O22
Loc(+1, 0, 7),// I/O23
Loc(+1, 0, 9),// I/O24
Loc(+1, 0, 10),// I/O25
Loc(+1, 0, 13),// I/O26
Loc(+1, 0, 14),// I/O27
Loc(+1, 0, 15),// I/O28
Loc(+1, 0, 16),// I/O29
Loc(+1, 0, 17),// I/O30
Loc(+1, 0, 18),// I/O31
Loc(+1, 0, 21),// I/O32
Loc(+1, 0, 24),// I/O33
Loc(+1, 0, 25),// I/O34
Loc(+1, 0, 26),// I/O35
Loc(+1, 0, 29),// I/O36
Loc(-1, 0, 4),// RA1
Loc(-1, 0, 12),// RA2
Loc(-1, 0, 20),// RA3
Loc(-1, 0, 27),// RA4
Loc(-1, 0, 31),// RA5
Loc(+1, 0, 4),// RA6
Loc(+1, 0, 12),// RA7
Loc(+1, 0, 20),// RA8
Loc(+1, 0, 27),// RA9
Loc(+1, 0, 31),// RA10
Loc(-1, 0, 3),// WA1
Loc(-1, 0, 11),// WA2
Loc(-1, 0, 19),// WA3
Loc(-1, 0, 23),// WA4
Loc(-1, 0, 28),// WA5
Loc(+1, 0, 3),// WA6
Loc(-1, 0, 0),// WE
Loc(-1, 0, 8),// WEA
};
Loc result = map.at(pos);
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
{
@ -359,6 +431,61 @@ bool NgUltraImpl::getChildPlacement(const BaseClusterInfo *cluster, Loc root_loc
case PLACE_CY_FE2: return getCYFE(root_loc,1);
case PLACE_CY_FE3: return getCYFE(root_loc,2);
case PLACE_CY_FE4: return getCYFE(root_loc,3);
case PLACE_XRF_I1:
case PLACE_XRF_I2:
case PLACE_XRF_I3:
case PLACE_XRF_I4:
case PLACE_XRF_I5:
case PLACE_XRF_I6:
case PLACE_XRF_I7:
case PLACE_XRF_I8:
case PLACE_XRF_I9:
case PLACE_XRF_I10:
case PLACE_XRF_I11:
case PLACE_XRF_I12:
case PLACE_XRF_I13:
case PLACE_XRF_I14:
case PLACE_XRF_I15:
case PLACE_XRF_I16:
case PLACE_XRF_I17:
case PLACE_XRF_I18:
case PLACE_XRF_I19:
case PLACE_XRF_I20:
case PLACE_XRF_I21:
case PLACE_XRF_I22:
case PLACE_XRF_I23:
case PLACE_XRF_I24:
case PLACE_XRF_I25:
case PLACE_XRF_I26:
case PLACE_XRF_I27:
case PLACE_XRF_I28:
case PLACE_XRF_I29:
case PLACE_XRF_I30:
case PLACE_XRF_I31:
case PLACE_XRF_I32:
case PLACE_XRF_I33:
case PLACE_XRF_I34:
case PLACE_XRF_I35:
case PLACE_XRF_I36:
case PLACE_XRF_RA1:
case PLACE_XRF_RA2:
case PLACE_XRF_RA3:
case PLACE_XRF_RA4:
case PLACE_XRF_RA5:
case PLACE_XRF_RA6:
case PLACE_XRF_RA7:
case PLACE_XRF_RA8:
case PLACE_XRF_RA9:
case PLACE_XRF_RA10:
case PLACE_XRF_WA1:
case PLACE_XRF_WA2:
case PLACE_XRF_WA3:
case PLACE_XRF_WA4:
case PLACE_XRF_WA5:
case PLACE_XRF_WA6:
case PLACE_XRF_WE:
case PLACE_XRF_WEA:
return getXRFFE(root_loc, child->constr_z - PLACE_XRF_I1 );
default:
Loc result;
result.x = root_loc.x + child->constr_x;

View File

@ -717,6 +717,211 @@ void NgUltraPacker::pack_cys(void)
flush_cells();
}
ClusterPlacement getPortPlacement(Context *ctx, IdString port)
{
switch(port.index)
{
case id_I1.index : return PLACE_XRF_I1;
case id_I2.index : return PLACE_XRF_I2;
case id_I3.index : return PLACE_XRF_I3;
case id_I4.index : return PLACE_XRF_I4;
case id_I5.index : return PLACE_XRF_I5;
case id_I6.index : return PLACE_XRF_I6;
case id_I7.index : return PLACE_XRF_I7;
case id_I8.index : return PLACE_XRF_I8;
case id_I9.index : return PLACE_XRF_I9;
case id_I10.index : return PLACE_XRF_I10;
case id_I11.index : return PLACE_XRF_I11;
case id_I12.index : return PLACE_XRF_I12;
case id_I13.index : return PLACE_XRF_I13;
case id_I14.index : return PLACE_XRF_I14;
case id_I15.index : return PLACE_XRF_I15;
case id_I16.index : return PLACE_XRF_I16;
case id_I17.index : return PLACE_XRF_I17;
case id_I18.index : return PLACE_XRF_I18;
case id_I19.index : return PLACE_XRF_I19;
case id_I20.index : return PLACE_XRF_I20;
case id_I21.index : return PLACE_XRF_I21;
case id_I22.index : return PLACE_XRF_I22;
case id_I23.index : return PLACE_XRF_I23;
case id_I24.index : return PLACE_XRF_I24;
case id_I25.index : return PLACE_XRF_I25;
case id_I26.index : return PLACE_XRF_I26;
case id_I27.index : return PLACE_XRF_I27;
case id_I28.index : return PLACE_XRF_I28;
case id_I29.index : return PLACE_XRF_I29;
case id_I30.index : return PLACE_XRF_I30;
case id_I31.index : return PLACE_XRF_I31;
case id_I32.index : return PLACE_XRF_I32;
case id_I33.index : return PLACE_XRF_I33;
case id_I34.index : return PLACE_XRF_I34;
case id_I35.index : return PLACE_XRF_I35;
case id_I36.index : return PLACE_XRF_I36;
case id_RA1.index : return PLACE_XRF_RA1;
case id_RA2.index : return PLACE_XRF_RA2;
case id_RA3.index : return PLACE_XRF_RA3;
case id_RA4.index : return PLACE_XRF_RA4;
case id_RA5.index : return PLACE_XRF_RA5;
case id_RA6.index : return PLACE_XRF_RA6;
case id_RA7.index : return PLACE_XRF_RA7;
case id_RA8.index : return PLACE_XRF_RA8;
case id_RA9.index : return PLACE_XRF_RA9;
case id_RA10.index : return PLACE_XRF_RA10;
case id_WA1.index : return PLACE_XRF_WA1;
case id_WA2.index : return PLACE_XRF_WA2;
case id_WA3.index : return PLACE_XRF_WA3;
case id_WA4.index : return PLACE_XRF_WA4;
case id_WA5.index : return PLACE_XRF_WA5;
case id_WA6.index : return PLACE_XRF_WA6;
case id_WE.index : return PLACE_XRF_WE;
case id_WEA.index : return PLACE_XRF_WEA;
default:
log_error("Unhandled port %s\n", port.c_str(ctx));
}
}
void NgUltraPacker::pack_xrf_input_and_output(CellInfo *xrf, IdString cluster, IdString in_port, IdString out_port, int &lut_only, int &lut_and_ff, int &dff_only)
{
NetInfo *net = xrf->getPort(in_port);
NetInfo *net_out = nullptr;
if (out_port != IdString())
net_out = xrf->getPort(out_port);
if (!net && !net_out) return;
CellInfo *fe = create_cell_ptr(id_BEYOND_FE, ctx->id(xrf->name.str(ctx) + "$" + in_port.c_str(ctx)));
if (net) {
if (net->name.in(ctx->id("$PACKER_GND"), ctx->id("$PACKER_VCC"))) {
fe->params[id_lut_table] = Property((net->name ==ctx->id("$PACKER_GND")) ? 0x0000 : 0xffff, 16);
fe->params[id_lut_used] = Property(1,1);
xrf->disconnectPort(in_port);
NetInfo *new_out = ctx->createNet(ctx->id(fe->name.str(ctx) + "$o"));
fe->connectPort(id_LO, new_out);
xrf->connectPort(in_port, new_out);
} else {
CellInfo *lut = net_driven_by(ctx, net, is_lut, id_O);
if (lut && net->users.entries()==1) {
if (!lut->params.count(id_lut_table))
log_error("Cell '%s' missing lut_table\n", lut->name.c_str(ctx));
lut_to_fe(lut, fe, false, lut->params[id_lut_table]);
packed_cells.insert(lut->name);
} else {
fe->params[id_lut_table] = Property(0xaaaa, 16);
fe->params[id_lut_used] = Property(1,1);
xrf->disconnectPort(in_port);
NetInfo *new_out = ctx->createNet(ctx->id(fe->name.str(ctx) + "$o"));
fe->connectPort(id_I1, net);
fe->connectPort(id_LO, new_out);
xrf->connectPort(in_port, new_out);
}
}
lut_only++;
}
if (net_out) {
CellInfo *dff = net_only_drives(ctx, net_out, is_dff, id_I, true);
if (dff) {
if (ctx->verbose)
log_info("found attached dff %s\n", dff->name.c_str(ctx));
dff_to_fe(dff, fe, false);
packed_cells.insert(dff->name);
if (net) {
lut_only--;
lut_and_ff++;
} else
dff_only++;
}
}
fe->cluster = cluster;
fe->constr_z = getPortPlacement(ctx,in_port);
xrf->constr_children.push_back(fe);
}
void NgUltraPacker::pack_rfs(void)
{
log_info("Packing RFs..\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_RFB_U))
continue;
ci.type = id_RF;
//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;
//NetInfo *net = ci.getPort(id_WCK);
//if (net) {
// ci.disconnectPort(id_WCK);
//
//ci.connectPort(id_WCK1, net);
//ci.connectPort(id_WCK2, net);
//}
ci.cluster = ci.name;
pack_xrf_input_and_output(&ci, ci.name, id_I1, id_O1, lut_only, lut_and_ff, dff_only);
pack_xrf_input_and_output(&ci, ci.name, id_I2, id_O2, lut_only, lut_and_ff, dff_only);
pack_xrf_input_and_output(&ci, ci.name, id_I3, id_O3, lut_only, lut_and_ff, dff_only);
pack_xrf_input_and_output(&ci, ci.name, id_I4, id_O4, lut_only, lut_and_ff, dff_only);
pack_xrf_input_and_output(&ci, ci.name, id_I5, id_O5, lut_only, lut_and_ff, dff_only);
pack_xrf_input_and_output(&ci, ci.name, id_I6, id_O6, lut_only, lut_and_ff, dff_only);
pack_xrf_input_and_output(&ci, ci.name, id_I7, id_O7, lut_only, lut_and_ff, dff_only);
pack_xrf_input_and_output(&ci, ci.name, id_I8, id_O8, lut_only, lut_and_ff, dff_only);
pack_xrf_input_and_output(&ci, ci.name, id_I9, id_O9, lut_only, lut_and_ff, dff_only);
pack_xrf_input_and_output(&ci, ci.name, id_I10, id_O10, lut_only, lut_and_ff, dff_only);
pack_xrf_input_and_output(&ci, ci.name, id_I11, id_O11, lut_only, lut_and_ff, dff_only);
pack_xrf_input_and_output(&ci, ci.name, id_I12, id_O12, lut_only, lut_and_ff, dff_only);
pack_xrf_input_and_output(&ci, ci.name, id_I13, id_O13, lut_only, lut_and_ff, dff_only);
pack_xrf_input_and_output(&ci, ci.name, id_I14, id_O14, lut_only, lut_and_ff, dff_only);
pack_xrf_input_and_output(&ci, ci.name, id_I15, id_O15, lut_only, lut_and_ff, dff_only);
pack_xrf_input_and_output(&ci, ci.name, id_I16, id_O16, lut_only, lut_and_ff, dff_only);
pack_xrf_input_and_output(&ci, ci.name, id_I17, id_O17, lut_only, lut_and_ff, dff_only);
pack_xrf_input_and_output(&ci, ci.name, id_I18, id_O18, lut_only, lut_and_ff, dff_only);
pack_xrf_input_and_output(&ci, ci.name, id_I19, id_O19, lut_only, lut_and_ff, dff_only);
pack_xrf_input_and_output(&ci, ci.name, id_I20, id_O20, lut_only, lut_and_ff, dff_only);
pack_xrf_input_and_output(&ci, ci.name, id_I21, id_O21, lut_only, lut_and_ff, dff_only);
pack_xrf_input_and_output(&ci, ci.name, id_I22, id_O22, lut_only, lut_and_ff, dff_only);
pack_xrf_input_and_output(&ci, ci.name, id_I23, id_O23, lut_only, lut_and_ff, dff_only);
pack_xrf_input_and_output(&ci, ci.name, id_I24, id_O24, lut_only, lut_and_ff, dff_only);
pack_xrf_input_and_output(&ci, ci.name, id_I25, id_O25, lut_only, lut_and_ff, dff_only);
pack_xrf_input_and_output(&ci, ci.name, id_I26, id_O26, lut_only, lut_and_ff, dff_only);
pack_xrf_input_and_output(&ci, ci.name, id_I27, id_O27, lut_only, lut_and_ff, dff_only);
pack_xrf_input_and_output(&ci, ci.name, id_I28, id_O28, lut_only, lut_and_ff, dff_only);
pack_xrf_input_and_output(&ci, ci.name, id_I29, id_O29, lut_only, lut_and_ff, dff_only);
pack_xrf_input_and_output(&ci, ci.name, id_I30, id_O30, lut_only, lut_and_ff, dff_only);
pack_xrf_input_and_output(&ci, ci.name, id_I31, id_O31, lut_only, lut_and_ff, dff_only);
pack_xrf_input_and_output(&ci, ci.name, id_I32, id_O32, lut_only, lut_and_ff, dff_only);
pack_xrf_input_and_output(&ci, ci.name, id_I33, id_O33, lut_only, lut_and_ff, dff_only);
pack_xrf_input_and_output(&ci, ci.name, id_I34, id_O34, lut_only, lut_and_ff, dff_only);
pack_xrf_input_and_output(&ci, ci.name, id_I35, id_O35, lut_only, lut_and_ff, dff_only);
pack_xrf_input_and_output(&ci, ci.name, id_I36, id_O36, lut_only, lut_and_ff, dff_only);
pack_xrf_input_and_output(&ci, ci.name, id_RA1, IdString(), lut_only, lut_and_ff, dff_only);
pack_xrf_input_and_output(&ci, ci.name, id_RA2, IdString(), lut_only, lut_and_ff, dff_only);
pack_xrf_input_and_output(&ci, ci.name, id_RA3, IdString(), lut_only, lut_and_ff, dff_only);
pack_xrf_input_and_output(&ci, ci.name, id_RA4, IdString(), lut_only, lut_and_ff, dff_only);
pack_xrf_input_and_output(&ci, ci.name, id_RA5, IdString(), lut_only, lut_and_ff, dff_only);
pack_xrf_input_and_output(&ci, ci.name, id_RA6, IdString(), lut_only, lut_and_ff, dff_only);
pack_xrf_input_and_output(&ci, ci.name, id_RA7, IdString(), lut_only, lut_and_ff, dff_only);
pack_xrf_input_and_output(&ci, ci.name, id_RA8, IdString(), lut_only, lut_and_ff, dff_only);
pack_xrf_input_and_output(&ci, ci.name, id_RA9, IdString(), lut_only, lut_and_ff, dff_only);
pack_xrf_input_and_output(&ci, ci.name, id_RA10, IdString(), lut_only, lut_and_ff, dff_only);
pack_xrf_input_and_output(&ci, ci.name, id_WA1, IdString(), lut_only, lut_and_ff, dff_only);
pack_xrf_input_and_output(&ci, ci.name, id_WA2, IdString(), lut_only, lut_and_ff, dff_only);
pack_xrf_input_and_output(&ci, ci.name, id_WA3, IdString(), lut_only, lut_and_ff, dff_only);
pack_xrf_input_and_output(&ci, ci.name, id_WA4, IdString(), lut_only, lut_and_ff, dff_only);
pack_xrf_input_and_output(&ci, ci.name, id_WA5, IdString(), lut_only, lut_and_ff, dff_only);
pack_xrf_input_and_output(&ci, ci.name, id_WA6, IdString(), lut_only, lut_and_ff, dff_only);
pack_xrf_input_and_output(&ci, ci.name, id_WE, IdString(), lut_only, lut_and_ff, dff_only);
pack_xrf_input_and_output(&ci, ci.name, id_WEA, IdString(), 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();
}
// There are 20 dedicated clock inputs capable of being routed using global network
// to be able to best route them, IOM needs to be used to propagate these clock signals
void NgUltraPacker::promote_globals()
@ -815,6 +1020,7 @@ void NgUltraImpl::pack()
packer.update_dffs();
packer.pack_iobs();
packer.pack_ioms();
packer.pack_rfs();
packer.pack_cys();
packer.pack_lut_dffs();
packer.pack_dffs();

View File

@ -48,6 +48,7 @@ struct NgUltraPacker
void pack_lut_dffs();
void pack_dffs();
void pack_cys();
void pack_rfs();
// IO
void pack_iobs();
@ -63,6 +64,8 @@ private:
void exchange_if_constant(CellInfo *cell, IdString input1, IdString input2);
void pack_cy_input_and_output(CellInfo *cy, IdString cluster, IdString in_port, IdString out_port, int placer, int &lut_only, int &lut_and_ff, int &dff_only);
void pack_xrf_input_and_output(CellInfo *cy, IdString cluster, IdString in_port, IdString out_port, int &lut_only, int &lut_and_ff, int &dff_only);
// General helper functions
void flush_cells();