new packer

This commit is contained in:
Marcin Kościelnicki 2020-02-02 16:19:50 +01:00
parent 1d241b1d3f
commit 1c9cf8adb1
3 changed files with 145 additions and 33 deletions

View File

@ -802,6 +802,141 @@ TimingClockingInfo Arch::getPortClockingInfo(const CellInfo *cell, IdString port
return info;
}
// TODO: validate bel subtype (SLICEM vs SLICEL, IOBM vs IOBS, ...).
bool Arch::isValidBelForCell(CellInfo *cell, BelId bel) const {
IdString type = getBelType(bel);
bool is_slice = false;
if (type == id("LEUCTRA_FF")) {
if (cell && !cell->constr_parent) {
if (0x924924ull & 1ull << bel.index)
return false;
}
is_slice = true;
}
if (type == id("LEUCTRA_LC")) {
if (cell) {
int mask = cell->attrs[id("LOCMASK")].as_int64();
int lci = bel.index / 3 % 4;
if (!(mask & 1 << lci))
return false;
if (cell->attrs[id("NEEDS_L")].as_bool()) {
if (!(getBelFlags(bel) & (BelPOD::FLAG_SLICEL | BelPOD::FLAG_SLICEM)))
return false;
}
if (cell->attrs[id("NEEDS_M")].as_bool()) {
if (!(getBelFlags(bel) & BelPOD::FLAG_SLICEM))
return false;
}
}
is_slice = true;
}
if (type == id("RAMB8BWER") && cell) {
BelId obel = bel;
obel.index = 2;
if (getBoundBelCell(obel))
return false;
}
if (type == id("RAMB16BWER") && cell) {
BelId obel = bel;
obel.index = 0;
if (getBoundBelCell(obel))
return false;
obel.index = 1;
if (getBoundBelCell(obel))
return false;
}
if (is_slice) {
int slice_z = bel.index / 12;
NetInfo *clk = nullptr;
NetInfo *we = nullptr;
NetInfo *ce = nullptr;
NetInfo *sr = nullptr;
Property ff_mode;
Property clk_inv;
bool had_ff = false;
CellInfo *lcs[4];
CellInfo *ffs[8];
bool ff_xi_used[4] = {0};
for (int i = 0; i < 4; i++) {
BelId obel = bel;
obel.index = slice_z * 12 + i * 3;
if (obel == bel)
lcs[i] = cell;
else
lcs[i] = getBoundBelCell(obel);
obel.index++;
if (obel == bel)
ffs[2*i] = cell;
else
ffs[2*i] = getBoundBelCell(obel);
ff_xi_used[i] = ffs[2*i] && !ffs[2*i]->constr_parent;
obel.index++;
if (obel == bel)
ffs[2*i+1] = cell;
else
ffs[2*i+1] = getBoundBelCell(obel);
}
for (auto ff : ffs) {
if (ff) {
if (had_ff) {
if (clk != ff->ports[id("CLK")].net)
return false;
if (ce != ff->ports[id("CE")].net)
return false;
if (sr != ff->ports[id("SR")].net)
return false;
if (ff_mode != ff->params[id("MODE")])
return false;
if (clk_inv != ff->params[id("CLKINV")])
return false;
} else {
clk = ff->ports[id("CLK")].net;
ce = ff->ports[id("CE")].net;
sr = ff->ports[id("SR")].net;
ff_mode = ff->params[id("MODE")];
clk_inv = ff->params[id("CLKINV")];
}
had_ff = true;
}
}
for (int i = 0; i < 4; i++) {
CellInfo *lc = lcs[i];
if (!lc)
continue;
if (lc->ports[id("XI")].net && ff_xi_used[i])
return false;
if (lc->ports[id("WA7")].net && ff_xi_used[2])
return false;
if (lc->ports[id("WA8")].net && ff_xi_used[1])
return false;
if (lc->ports[id("DDI8")].net && ff_xi_used[3])
return false;
if (lc->ports[id("DDI7")].net && ff_xi_used[i | 1])
return false;
if (lc->ports[id("CLK")].net) {
if (clk) {
if (clk != lc->ports[id("CLK")].net)
return false;
if (clk_inv != lc->params[id("CLKINV")])
return false;
} else {
clk = lc->ports[id("CLK")].net;
clk_inv = lc->params[id("CLKINV")];
}
}
if (lc->ports[id("WE")].net) {
if (we) {
if (we != lc->ports[id("WE")].net)
return false;
} else {
we = lc->ports[id("WE")].net;
}
}
}
}
return true;
}
// Assign arch arg info
void Arch::assignArchInfo()
{

View File

@ -1183,39 +1183,10 @@ struct Arch : BaseCtx
// -------------------------------------------------
// Placement validity checks
// TODO: validate bel subtype (SLICEM vs SLICEL, IOBM vs IOBS, ...).
bool isValidBelForCell(CellInfo *cell, BelId bel) const {
if (cell->type == id("LEUCTRA_FF")) {
if (!cell->constr_parent) {
if (0x924924ull & 1ull << bel.index)
return false;
// XXX FIX FIX FIX
if (0xffcfffull & 1ull << bel.index)
return false;
}
}
if (cell->type == id("LEUCTRA_LC")) {
int mask = cell->attrs[id("LOCMASK")].as_int64();
int lci = bel.index / 3 % 4;
if (!(mask & 1 << lci))
return false;
if (cell->attrs[id("NEEDS_L")].as_bool()) {
if (!(getBelFlags(bel) & (BelPOD::FLAG_SLICEL | BelPOD::FLAG_SLICEM)))
return false;
}
if (cell->attrs[id("NEEDS_M")].as_bool()) {
if (!(getBelFlags(bel) & BelPOD::FLAG_SLICEM))
return false;
}
// XXX more?
}
return true;
}
bool isValidBelForCell(CellInfo *cell, BelId bel) const;
bool isBelLocationValid(BelId bel) const {
CellInfo *cell = getBoundBelCell(bel);
if (cell && !isValidBelForCell(cell, bel))
return false;
return true;
return isValidBelForCell(getBoundBelCell(bel), bel);
}
// Apply UCF constraints to the context

View File

@ -547,6 +547,7 @@ CellInfo *convert_carry4(Context *ctx, CellInfo *c4, CellInfo *link, std::vector
if (co[i] || xo[i])
num = i + 1;
}
NetInfo *vcc_net = nullptr;
for (int i = 0; i < num; i++) {
// XXX more cases
if (i == 0 && !link) {
@ -607,7 +608,12 @@ CellInfo *convert_carry4(Context *ctx, CellInfo *c4, CellInfo *link, std::vector
lcs[i]->constr_children.push_back(ff);
ff->params[ctx->id("MODE")] = Property("COMB");
ff->params[ctx->id("CLKINV")] = Property("CLK_B");
set_const_port(ctx, ff, ctx->id("CLK"), true, created_cells);
if (vcc_net) {
connect_port(ctx, vcc_net, ff, ctx->id("CLK"));
} else {
set_const_port(ctx, ff, ctx->id("CLK"), true, created_cells);
vcc_net = ff->ports[ctx->id("CLK")].net;
}
connect_ports(ctx, lcs[i], ctx->id("CO"), ff, ctx->id("D"));
connect_port(ctx, co[i], ff, ctx->id("Q"));
}