mirror of
https://github.com/YosysHQ/nextpnr.git
synced 2026-02-15 20:36:31 +00:00
Start using FFs
This commit is contained in:
@@ -243,6 +243,7 @@ struct BitstreamBackend
|
||||
break;
|
||||
case id_CPE_L2T4.index:
|
||||
case id_CPE_L2T5.index:
|
||||
case id_CPE_FF.index:
|
||||
case id_CPE_RAMI.index:
|
||||
case id_CPE_RAMO.index:
|
||||
case id_CPE_RAMIO.index:
|
||||
|
||||
@@ -91,9 +91,9 @@ bool GateMateImpl::isBelLocationValid(BelId bel, bool explain_invalid) const
|
||||
if (cell->belStrength != PlaceStrength::STRENGTH_FIXED && tile_extra_data(bel.tile)->die != preferred_die)
|
||||
return false;
|
||||
|
||||
if (ctx->getBelType(bel).in(id_CPE_LT, id_CPE_LT_L, id_CPE_LT_U)) {
|
||||
if (ctx->getBelType(bel).in(id_CPE_FF, id_CPE_FF_L, id_CPE_FF_U)) {
|
||||
Loc loc = ctx->getBelLocation(bel);
|
||||
const CellInfo *adj_half = ctx->getBoundBelCell(ctx->getBelByLocation(Loc(loc.x, loc.y, loc.z == 1 ? 0 : 1)));
|
||||
const CellInfo *adj_half = ctx->getBoundBelCell(ctx->getBelByLocation(Loc(loc.x, loc.y, loc.z == 2 ? 3 : 2)));
|
||||
if (adj_half) {
|
||||
const auto &half_data = fast_cell_info.at(cell->flat_index);
|
||||
if (half_data.dff_used) {
|
||||
@@ -283,28 +283,25 @@ void GateMateImpl::assign_cell_info()
|
||||
for (auto &cell : ctx->cells) {
|
||||
CellInfo *ci = cell.second.get();
|
||||
auto &fc = fast_cell_info.at(ci->flat_index);
|
||||
if (getBelBucketForCellType(ci->type) == id_CPE_LT) {
|
||||
fc.signal_used = int_or_default(ci->params, id_C_O, -1);
|
||||
if (getBelBucketForCellType(ci->type) == id_CPE_FF) {
|
||||
fc.ff_en = ci->getPort(id_EN);
|
||||
fc.ff_clk = ci->getPort(id_CLK);
|
||||
fc.ff_sr = ci->getPort(id_SR);
|
||||
fc.ff_config = 0;
|
||||
if (fc.signal_used == 0) {
|
||||
fc.ff_config |= int_or_default(ci->params, id_C_CPE_EN, 0);
|
||||
fc.ff_config <<= 2;
|
||||
fc.ff_config |= int_or_default(ci->params, id_C_CPE_CLK, 0);
|
||||
fc.ff_config <<= 2;
|
||||
fc.ff_config |= int_or_default(ci->params, id_C_CPE_RES, 0);
|
||||
fc.ff_config <<= 2;
|
||||
fc.ff_config |= int_or_default(ci->params, id_C_CPE_SET, 0);
|
||||
fc.ff_config <<= 2;
|
||||
fc.ff_config |= int_or_default(ci->params, id_C_EN_SR, 0);
|
||||
fc.ff_config <<= 1;
|
||||
fc.ff_config |= int_or_default(ci->params, id_C_L_D, 0);
|
||||
fc.ff_config <<= 1;
|
||||
fc.ff_config |= int_or_default(ci->params, id_FF_INIT, 0);
|
||||
fc.dff_used = true;
|
||||
}
|
||||
fc.ff_config |= int_or_default(ci->params, id_C_CPE_EN, 0);
|
||||
fc.ff_config <<= 2;
|
||||
fc.ff_config |= int_or_default(ci->params, id_C_CPE_CLK, 0);
|
||||
fc.ff_config <<= 2;
|
||||
fc.ff_config |= int_or_default(ci->params, id_C_CPE_RES, 0);
|
||||
fc.ff_config <<= 2;
|
||||
fc.ff_config |= int_or_default(ci->params, id_C_CPE_SET, 0);
|
||||
fc.ff_config <<= 2;
|
||||
fc.ff_config |= int_or_default(ci->params, id_C_EN_SR, 0);
|
||||
fc.ff_config <<= 1;
|
||||
fc.ff_config |= int_or_default(ci->params, id_C_L_D, 0);
|
||||
fc.ff_config <<= 1;
|
||||
fc.ff_config |= int_or_default(ci->params, id_FF_INIT, 0);
|
||||
fc.dff_used = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -46,7 +46,7 @@ struct GateMatePacker
|
||||
void remove_not_used();
|
||||
|
||||
private:
|
||||
void dff_to_cpe(CellInfo *dff, CellInfo *cpe);
|
||||
void dff_to_cpe(CellInfo *dff);
|
||||
void insert_bufg(CellInfo *cell, IdString port);
|
||||
void disconnect_if_gnd(CellInfo *cell, IdString input);
|
||||
void pll_out(CellInfo *cell, IdString origPort, Loc fixed);
|
||||
|
||||
@@ -29,68 +29,68 @@ NEXTPNR_NAMESPACE_BEGIN
|
||||
// Return true if a cell is a flipflop
|
||||
inline bool is_dff(const BaseCtx *ctx, const CellInfo *cell) { return cell->type.in(id_CC_DFF, id_CC_DLT); }
|
||||
|
||||
void GateMatePacker::dff_to_cpe(CellInfo *dff, CellInfo *cpe)
|
||||
void GateMatePacker::dff_to_cpe(CellInfo *dff)
|
||||
{
|
||||
bool invert;
|
||||
bool is_latch = dff->type == id_CC_DLT;
|
||||
if (is_latch) {
|
||||
NetInfo *g_net = cpe->getPort(id_G);
|
||||
NetInfo *g_net = dff->getPort(id_G);
|
||||
invert = bool_or_default(dff->params, id_G_INV, 0);
|
||||
if (g_net) {
|
||||
if (g_net->name == ctx->id("$PACKER_GND")) {
|
||||
cpe->params[id_C_CPE_CLK] = Property(invert ? 0b11 : 0b00, 2);
|
||||
cpe->disconnectPort(id_G);
|
||||
dff->params[id_C_CPE_CLK] = Property(invert ? 0b11 : 0b00, 2);
|
||||
dff->disconnectPort(id_G);
|
||||
} else if (g_net->name == ctx->id("$PACKER_VCC")) {
|
||||
cpe->params[id_C_CPE_CLK] = Property(invert ? 0b00 : 0b11, 2);
|
||||
cpe->disconnectPort(id_G);
|
||||
dff->params[id_C_CPE_CLK] = Property(invert ? 0b00 : 0b11, 2);
|
||||
dff->disconnectPort(id_G);
|
||||
} else {
|
||||
cpe->params[id_C_CPE_CLK] = Property(invert ? 0b01 : 0b10, 2);
|
||||
dff->params[id_C_CPE_CLK] = Property(invert ? 0b01 : 0b10, 2);
|
||||
}
|
||||
} else {
|
||||
cpe->params[id_C_CPE_CLK] = Property(invert ? 0b11 : 0b00, 2);
|
||||
dff->params[id_C_CPE_CLK] = Property(invert ? 0b11 : 0b00, 2);
|
||||
}
|
||||
dff->unsetParam(id_G_INV);
|
||||
cpe->renamePort(id_G, id_CLK);
|
||||
dff->renamePort(id_G, id_CLK);
|
||||
|
||||
cpe->params[id_C_CPE_EN] = Property(0b11, 2);
|
||||
cpe->params[id_C_L_D] = Property(0b1, 1);
|
||||
dff->params[id_C_CPE_EN] = Property(0b11, 2);
|
||||
dff->params[id_C_L_D] = Property(0b1, 1);
|
||||
} else {
|
||||
NetInfo *en_net = cpe->getPort(id_EN);
|
||||
NetInfo *en_net = dff->getPort(id_EN);
|
||||
bool invert = bool_or_default(dff->params, id_EN_INV, 0);
|
||||
if (en_net) {
|
||||
if (en_net->name == ctx->id("$PACKER_GND")) {
|
||||
cpe->params[id_C_CPE_EN] = Property(invert ? 0b11 : 0b00, 2);
|
||||
cpe->disconnectPort(id_EN);
|
||||
dff->params[id_C_CPE_EN] = Property(invert ? 0b11 : 0b00, 2);
|
||||
dff->disconnectPort(id_EN);
|
||||
} else if (en_net->name == ctx->id("$PACKER_VCC")) {
|
||||
cpe->params[id_C_CPE_EN] = Property(invert ? 0b00 : 0b11, 2);
|
||||
cpe->disconnectPort(id_EN);
|
||||
dff->params[id_C_CPE_EN] = Property(invert ? 0b00 : 0b11, 2);
|
||||
dff->disconnectPort(id_EN);
|
||||
} else {
|
||||
cpe->params[id_C_CPE_EN] = Property(invert ? 0b01 : 0b10, 2);
|
||||
dff->params[id_C_CPE_EN] = Property(invert ? 0b01 : 0b10, 2);
|
||||
}
|
||||
} else {
|
||||
cpe->params[id_C_CPE_EN] = Property(invert ? 0b11 : 0b00, 2);
|
||||
dff->params[id_C_CPE_EN] = Property(invert ? 0b11 : 0b00, 2);
|
||||
}
|
||||
dff->unsetParam(id_EN_INV);
|
||||
|
||||
NetInfo *clk_net = cpe->getPort(id_CLK);
|
||||
NetInfo *clk_net = dff->getPort(id_CLK);
|
||||
invert = bool_or_default(dff->params, id_CLK_INV, 0);
|
||||
if (clk_net) {
|
||||
if (clk_net->name == ctx->id("$PACKER_GND")) {
|
||||
cpe->params[id_C_CPE_CLK] = Property(invert ? 0b11 : 0b00, 2);
|
||||
cpe->disconnectPort(id_CLK);
|
||||
dff->params[id_C_CPE_CLK] = Property(invert ? 0b11 : 0b00, 2);
|
||||
dff->disconnectPort(id_CLK);
|
||||
} else if (clk_net->name == ctx->id("$PACKER_VCC")) {
|
||||
cpe->params[id_C_CPE_CLK] = Property(invert ? 0b00 : 0b11, 2);
|
||||
cpe->disconnectPort(id_CLK);
|
||||
dff->params[id_C_CPE_CLK] = Property(invert ? 0b00 : 0b11, 2);
|
||||
dff->disconnectPort(id_CLK);
|
||||
} else {
|
||||
cpe->params[id_C_CPE_CLK] = Property(invert ? 0b01 : 0b10, 2);
|
||||
dff->params[id_C_CPE_CLK] = Property(invert ? 0b01 : 0b10, 2);
|
||||
}
|
||||
} else {
|
||||
cpe->params[id_C_CPE_CLK] = Property(invert ? 0b11 : 0b00, 2);
|
||||
dff->params[id_C_CPE_CLK] = Property(invert ? 0b11 : 0b00, 2);
|
||||
}
|
||||
dff->unsetParam(id_CLK_INV);
|
||||
}
|
||||
|
||||
NetInfo *sr_net = cpe->getPort(id_SR);
|
||||
NetInfo *sr_net = dff->getPort(id_SR);
|
||||
invert = bool_or_default(dff->params, id_SR_INV, 0);
|
||||
bool sr_val = bool_or_default(dff->params, id_SR_VAL, 0);
|
||||
if (sr_net) {
|
||||
@@ -98,25 +98,25 @@ void GateMatePacker::dff_to_cpe(CellInfo *dff, CellInfo *cpe)
|
||||
bool sr_signal = sr_net->name == ctx->id("$PACKER_VCC");
|
||||
if (sr_signal ^ invert)
|
||||
log_error("Currently unsupported DFF configuration for '%s'\n.", dff->name.c_str(ctx));
|
||||
cpe->params[id_C_CPE_RES] = Property(0b11, 2);
|
||||
cpe->params[id_C_CPE_SET] = Property(0b11, 2);
|
||||
cpe->disconnectPort(id_SR);
|
||||
dff->params[id_C_CPE_RES] = Property(0b11, 2);
|
||||
dff->params[id_C_CPE_SET] = Property(0b11, 2);
|
||||
dff->disconnectPort(id_SR);
|
||||
} else {
|
||||
if (sr_val) {
|
||||
cpe->params[id_C_CPE_RES] = Property(0b11, 2);
|
||||
cpe->params[id_C_CPE_SET] = Property(invert ? 0b10 : 0b01, 2);
|
||||
dff->params[id_C_CPE_RES] = Property(0b11, 2);
|
||||
dff->params[id_C_CPE_SET] = Property(invert ? 0b10 : 0b01, 2);
|
||||
if (is_latch)
|
||||
cpe->renamePort(id_SR, id_EN);
|
||||
dff->renamePort(id_SR, id_EN);
|
||||
else
|
||||
cpe->params[id_C_EN_SR] = Property(0b1, 1);
|
||||
dff->params[id_C_EN_SR] = Property(0b1, 1);
|
||||
} else {
|
||||
cpe->params[id_C_CPE_RES] = Property(invert ? 0b10 : 0b01, 2);
|
||||
cpe->params[id_C_CPE_SET] = Property(0b11, 2);
|
||||
dff->params[id_C_CPE_RES] = Property(invert ? 0b10 : 0b01, 2);
|
||||
dff->params[id_C_CPE_SET] = Property(0b11, 2);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
cpe->params[id_C_CPE_RES] = Property(0b11, 2);
|
||||
cpe->params[id_C_CPE_SET] = Property(0b11, 2);
|
||||
dff->params[id_C_CPE_RES] = Property(0b11, 2);
|
||||
dff->params[id_C_CPE_SET] = Property(0b11, 2);
|
||||
}
|
||||
dff->unsetParam(id_SR_VAL);
|
||||
dff->unsetParam(id_SR_INV);
|
||||
@@ -124,14 +124,14 @@ void GateMatePacker::dff_to_cpe(CellInfo *dff, CellInfo *cpe)
|
||||
if (dff->params.count(id_INIT) && dff->params[id_INIT].is_fully_def()) {
|
||||
bool init = bool_or_default(dff->params, id_INIT, 0);
|
||||
if (init)
|
||||
cpe->params[id_FF_INIT] = Property(0b11, 2);
|
||||
dff->params[id_FF_INIT] = Property(0b11, 2);
|
||||
else
|
||||
cpe->params[id_FF_INIT] = Property(0b10, 2);
|
||||
dff->params[id_FF_INIT] = Property(0b10, 2);
|
||||
dff->unsetParam(id_INIT);
|
||||
} else {
|
||||
dff->unsetParam(id_INIT);
|
||||
}
|
||||
cpe->timing_index = ctx->get_cell_timing_idx(id_CPE_DFF);
|
||||
//cpe->timing_index = ctx->get_cell_timing_idx(id_CPE_DFF);
|
||||
// cpe->params[id_C_O] = Property(0b00, 2);
|
||||
}
|
||||
|
||||
@@ -190,18 +190,15 @@ void GateMatePacker::pack_cpe()
|
||||
if (o) {
|
||||
CellInfo *dff = net_only_drives(ctx, o, is_dff, id_D, true);
|
||||
if (dff) {
|
||||
if (dff->type == id_CC_DLT) {
|
||||
dff->movePortTo(id_G, &ci, id_G);
|
||||
} else {
|
||||
dff->movePortTo(id_EN, &ci, id_EN);
|
||||
dff->movePortTo(id_CLK, &ci, id_CLK);
|
||||
}
|
||||
dff->movePortTo(id_SR, &ci, id_SR);
|
||||
dff->disconnectPort(id_D);
|
||||
ci.disconnectPort(id_OUT);
|
||||
dff->movePortTo(id_Q, &ci, id_OUT);
|
||||
dff_to_cpe(dff, &ci);
|
||||
packed_cells.insert(dff->name);
|
||||
dff->cluster = ci.name;
|
||||
dff->constr_abs_z = false;
|
||||
dff->constr_z = +2;
|
||||
ci.cluster = ci.name;
|
||||
ci.constr_children.push_back(dff);
|
||||
dff->renamePort(id_D, id_DIN);
|
||||
dff->renamePort(id_Q, id_DOUT);
|
||||
dff_to_cpe(dff);
|
||||
dff->type=id_CPE_FF;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -273,25 +270,47 @@ void GateMatePacker::pack_cpe()
|
||||
}
|
||||
mux_list.clear();
|
||||
|
||||
std::vector<CellInfo *> dff_list;
|
||||
for (auto &cell : ctx->cells) {
|
||||
CellInfo &ci = *cell.second;
|
||||
if (!ci.type.in(id_CC_DFF, id_CC_DLT))
|
||||
continue;
|
||||
ci.renamePort(id_Q, id_OUT);
|
||||
dff_list.push_back(&ci);
|
||||
}
|
||||
for (auto &cell : dff_list) {
|
||||
CellInfo &ci = *cell;
|
||||
printf("1\n");
|
||||
CellInfo *lt = create_cell_ptr(id_CPE_LT, ctx->idf("%s$lt", ci.name.c_str(ctx)));
|
||||
lt->cluster = ci.name;
|
||||
lt->constr_abs_z = false;
|
||||
lt->constr_z = -2;
|
||||
ci.cluster = ci.name;
|
||||
ci.constr_children.push_back(lt);
|
||||
printf("2\n");
|
||||
ci.renamePort(id_Q, id_DOUT);
|
||||
NetInfo *d_net = ci.getPort(id_D);
|
||||
printf("3\n");
|
||||
if (!d_net)
|
||||
printf("NULL\n");
|
||||
if (d_net->name == ctx->id("$PACKER_GND")) {
|
||||
ci.params[id_INIT_L00] = Property(0b0000, 4);
|
||||
lt->params[id_INIT_L00] = Property(0b0000, 4);
|
||||
ci.disconnectPort(id_D);
|
||||
} else if (d_net->name == ctx->id("$PACKER_VCC")) {
|
||||
ci.params[id_INIT_L00] = Property(0b1111, 4);
|
||||
lt->params[id_INIT_L00] = Property(0b1111, 4);
|
||||
ci.disconnectPort(id_D);
|
||||
} else {
|
||||
ci.params[id_INIT_L00] = Property(0b1010, 4);
|
||||
lt->params[id_INIT_L00] = Property(0b1010, 4);
|
||||
}
|
||||
printf("4\n");
|
||||
ci.params[id_INIT_L10] = Property(0b1010, 4);
|
||||
ci.renamePort(id_D, id_IN1);
|
||||
dff_to_cpe(&ci, &ci);
|
||||
ci.type = id_CPE_LT;
|
||||
ci.movePortTo(id_D, lt, id_IN1);
|
||||
dff_to_cpe(&ci);
|
||||
printf("5\n");
|
||||
ci.type = id_CPE_FF;
|
||||
NetInfo *conn = ctx->createNet(ctx->idf("%s$di", ci.name.c_str(ctx)));
|
||||
lt->connectPort(id_OUT, conn);
|
||||
ci.connectPort(id_DIN, conn);
|
||||
printf("6\n");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user