Gowin. FFs placement. (#1386)
* Gowin. FFs placement. * Allow clusters to be created from FFs and LUTs; * Immediately create pass-through LUTs from free LUTs adjacent to FF - at the same time ensure alternating use of LUT inputs; * In case of constant networks, such pass-through LUTs are disconnected from networks altogether; * Allow FF to be placed directly into SSRAM slides - this is useful when using synchronous reading. Signed-off-by: YRabbit <rabbit@yrabbit.cyou> * Gowin. Fix aux name creation Signed-off-by: YRabbit <rabbit@yrabbit.cyou> * Gowin. Use I3 for pass-trough LUTs Signed-off-by: YRabbit <rabbit@yrabbit.cyou> --------- Signed-off-by: YRabbit <rabbit@yrabbit.cyou>
This commit is contained in:
parent
f36a6571c1
commit
9c2d96f86e
@ -71,6 +71,9 @@ struct GowinImpl : HimbaechelAPI
|
||||
std::vector<GowinCellInfo> fast_cell_info;
|
||||
void assign_cell_info();
|
||||
|
||||
// If there is an unused LUT adjacent to FF, use it
|
||||
void create_passthrough_luts(void);
|
||||
|
||||
// Remember HCLK sections that have been reserved to route HCLK signals
|
||||
std::set<BelId> routing_reserved_hclk_sections;
|
||||
|
||||
@ -531,6 +534,7 @@ void GowinImpl::postPlace()
|
||||
|
||||
// adjust cell pin to bel pin mapping for DSP cells (CE, CLK and RESET pins)
|
||||
adjust_dsp_pin_mapping();
|
||||
create_passthrough_luts();
|
||||
}
|
||||
|
||||
void GowinImpl::preRoute() { gowin_route_globals(ctx); }
|
||||
@ -590,8 +594,15 @@ bool GowinImpl::isBelLocationValid(BelId bel, bool explain_invalid) const
|
||||
case ID_ALU:
|
||||
return slice_valid(l.x, l.y, l.z - BelZ::ALU0_Z);
|
||||
case ID_RAM16SDP4:
|
||||
// only slices 4 and 5 are critical for RAM
|
||||
return slice_valid(l.x, l.y, l.z - BelZ::RAMW_Z + 5) && slice_valid(l.x, l.y, l.z - BelZ::RAMW_Z + 4);
|
||||
return slice_valid(l.x, l.y, 0);
|
||||
case ID_MUX2_LUT5:
|
||||
return slice_valid(l.x, l.y, (l.z - BelZ::MUX20_Z) / 2);
|
||||
case ID_MUX2_LUT6:
|
||||
return slice_valid(l.x, l.y, (l.z - BelZ::MUX21_Z) / 2 + 1);
|
||||
case ID_MUX2_LUT7:
|
||||
return slice_valid(l.x, l.y, 3);
|
||||
case ID_MUX2_LUT8:
|
||||
return slice_valid(l.x, l.y, 7);
|
||||
case ID_PADD9: /* fall-through */
|
||||
case ID_PADD18: /* fall-through */
|
||||
case ID_MULT9X9: /* fall-through */
|
||||
@ -725,6 +736,67 @@ void GowinImpl::assign_cell_info()
|
||||
}
|
||||
}
|
||||
|
||||
// If there is an unused LUT next to the DFF, use its inputs for the D input
|
||||
void GowinImpl::create_passthrough_luts(void)
|
||||
{
|
||||
std::vector<std::unique_ptr<CellInfo>> new_cells;
|
||||
for (auto &cell : ctx->cells) {
|
||||
CellInfo *ci = cell.second.get();
|
||||
if (is_dff(ci)) {
|
||||
Loc loc = ctx->getBelLocation(ci->bel);
|
||||
BelId lut_bel = ctx->getBelByLocation(Loc(loc.x, loc.y, loc.z - 1));
|
||||
CellInfo *lut = ctx->getBoundBelCell(lut_bel);
|
||||
CellInfo *alu = ctx->getBoundBelCell(ctx->getBelByLocation(Loc(loc.x, loc.y, loc.z / 2 + BelZ::ALU0_Z)));
|
||||
const CellInfo *ramw = ctx->getBoundBelCell(ctx->getBelByLocation(Loc(loc.x, loc.y, BelZ::RAMW_Z)));
|
||||
|
||||
if (!(lut || alu || ramw)) {
|
||||
if (ctx->debug) {
|
||||
log_info("Found an unused LUT:%s, ", ctx->nameOfBel(lut_bel));
|
||||
}
|
||||
// make LUT
|
||||
auto lut_cell = gwu.create_cell(gwu.create_aux_name(ci->name, 0, "_passthrough_lut$"), id_LUT4);
|
||||
CellInfo *lut = lut_cell.get();
|
||||
NetInfo *d_net = ci->getPort(id_D);
|
||||
NPNR_ASSERT(d_net != nullptr);
|
||||
|
||||
if (d_net->name == ctx->id("$PACKER_GND") || d_net->name == ctx->id("$PACKER_VCC")) {
|
||||
if (ctx->debug) {
|
||||
log("make a constant %s.\n", d_net->name == ctx->id("$PACKER_VCC") ? "VCC" : "GND");
|
||||
}
|
||||
ci->disconnectPort(id_D);
|
||||
if (d_net->name == ctx->id("$PACKER_GND")) {
|
||||
lut->setParam(id_INIT, 0x0000);
|
||||
} else {
|
||||
lut->setParam(id_INIT, 0xffff);
|
||||
}
|
||||
} else {
|
||||
if (ctx->debug) {
|
||||
log("make a pass-through.\n");
|
||||
}
|
||||
IdString lut_input = id_I3;
|
||||
int lut_init = 0xff00;
|
||||
|
||||
lut->addInput(lut_input);
|
||||
lut->cell_bel_pins[lut_input].clear();
|
||||
lut->cell_bel_pins.at(lut_input).push_back(lut_input);
|
||||
ci->movePortTo(id_D, lut, lut_input);
|
||||
lut->setParam(id_INIT, lut_init);
|
||||
}
|
||||
lut->addOutput(id_F);
|
||||
lut->cell_bel_pins[id_F].clear();
|
||||
lut->cell_bel_pins.at(id_F).push_back(id_F);
|
||||
ci->connectPorts(id_D, lut, id_F);
|
||||
|
||||
ctx->bindBel(lut_bel, lut, PlaceStrength::STRENGTH_LOCKED);
|
||||
new_cells.push_back(std::move(lut_cell));
|
||||
}
|
||||
}
|
||||
}
|
||||
for (auto &cell : new_cells) {
|
||||
ctx->cells[cell->name] = std::move(cell);
|
||||
}
|
||||
}
|
||||
|
||||
// DFFs must be same type or compatible
|
||||
inline bool incompatible_ffs(const CellInfo *ff, const CellInfo *adj_ff)
|
||||
{
|
||||
@ -798,22 +870,30 @@ bool GowinImpl::dsp_valid(Loc l, IdString bel_type, bool explain_invalid) const
|
||||
bool GowinImpl::slice_valid(int x, int y, int z) const
|
||||
{
|
||||
const CellInfo *lut = ctx->getBoundBelCell(ctx->getBelByLocation(Loc(x, y, z * 2)));
|
||||
const bool lut_in_4_5 = lut && (z == 4 || z == 5);
|
||||
const CellInfo *ff = ctx->getBoundBelCell(ctx->getBelByLocation(Loc(x, y, z * 2 + 1)));
|
||||
// There are only 6 ALUs
|
||||
const CellInfo *alu = (z < 6) ? ctx->getBoundBelCell(ctx->getBelByLocation(Loc(x, y, z + BelZ::ALU0_Z))) : nullptr;
|
||||
const CellInfo *ramw =
|
||||
(z == 4 || z == 5) ? ctx->getBoundBelCell(ctx->getBelByLocation(Loc(x, y, BelZ::RAMW_Z))) : nullptr;
|
||||
const CellInfo *ramw = ctx->getBoundBelCell(ctx->getBelByLocation(Loc(x, y, BelZ::RAMW_Z)));
|
||||
|
||||
if (alu && lut) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (ramw) {
|
||||
if (alu || ff || lut_in_4_5) {
|
||||
// FFs in slices 4 and 5 are not allowed
|
||||
if (ctx->getBoundBelCell(ctx->getBelByLocation(Loc(x, y, 4 * 2 + 1))) ||
|
||||
ctx->getBoundBelCell(ctx->getBelByLocation(Loc(x, y, 5 * 2 + 1)))) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
// ALU/LUTs in slices 4, 5, 6, 7 are not allowed
|
||||
for (int i = 4; i < 8; ++i) {
|
||||
if (ctx->getBoundBelCell(ctx->getBelByLocation(Loc(x, y, i * 2)))) {
|
||||
return false;
|
||||
}
|
||||
if (i < 6 && ctx->getBoundBelCell(ctx->getBelByLocation(Loc(x, y, i + BelZ::ALU0_Z)))) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// check for ALU/LUT in the adjacent cell
|
||||
@ -829,18 +909,19 @@ bool GowinImpl::slice_valid(int x, int y, int z) const
|
||||
return false;
|
||||
}
|
||||
|
||||
// if there is DFF it must be connected to this LUT or ALU
|
||||
if (ff) {
|
||||
static std::vector<int> mux_z = {BelZ::MUX20_Z, BelZ::MUX21_Z, BelZ::MUX20_Z + 4, BelZ::MUX23_Z,
|
||||
BelZ::MUX20_Z + 8, BelZ::MUX21_Z + 8, BelZ::MUX20_Z + 12, BelZ::MUX27_Z};
|
||||
const auto &ff_data = fast_cell_info.at(ff->flat_index);
|
||||
const NetInfo *src;
|
||||
// check implcit LUT(ALU) -> FF connection
|
||||
if (lut || alu) {
|
||||
if (lut) {
|
||||
const auto &lut_data = fast_cell_info.at(lut->flat_index);
|
||||
if (ff_data.ff_d != lut_data.lut_f) {
|
||||
return false;
|
||||
src = fast_cell_info.at(lut->flat_index).lut_f;
|
||||
} else {
|
||||
src = fast_cell_info.at(alu->flat_index).alu_sum;
|
||||
}
|
||||
}
|
||||
if (alu) {
|
||||
const auto &alu_data = fast_cell_info.at(alu->flat_index);
|
||||
if (ff_data.ff_d != alu_data.alu_sum) {
|
||||
if (ff_data.ff_d != src) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -817,11 +817,12 @@ def create_logic_tiletype(chip: Chip, db: chipdb, x: int, y: int, ttyp: int, tde
|
||||
tt.add_bel_pin(lut, f"I{j}", f"{inp_name}{i}", PinType.INPUT)
|
||||
tt.add_bel_pin(lut, "F", f"F{i}", PinType.OUTPUT)
|
||||
if i < 6:
|
||||
# FF data can come from LUT output, but we pretend that we can use
|
||||
# any LUT input
|
||||
tt.create_pip(f"F{i}", f"XD{i}", get_tm_class(db, f"F{i}"))
|
||||
for inp_name in lut_inputs:
|
||||
tt.create_pip(f"{inp_name}{i}", f"XD{i}", get_tm_class(db, f"{inp_name}{i}"))
|
||||
# also experimental input for FF using SEL wire - this theory will
|
||||
# allow to place unrelated LUT and FF next to each other
|
||||
# don't create for now
|
||||
#tt.create_pip(f"SEL{i}", f"XD{i}", get_tm_class(db, f"SEL{i}"))
|
||||
|
||||
# FF
|
||||
ff = tt.create_bel(f"DFF{i}", "DFF", z =(i * 2 + 1))
|
||||
tt.add_bel_pin(ff, "D", f"XD{i}", PinType.INPUT)
|
||||
|
@ -181,6 +181,12 @@ bool GowinUtils::need_BLKSEL_fix(void)
|
||||
return extra->chip_flags & Extra_chip_data_POD::NEED_BLKSEL_FIX;
|
||||
}
|
||||
|
||||
IdString GowinUtils::create_aux_name(IdString main_name, int idx, const char *str_suffix)
|
||||
{
|
||||
return idx ? ctx->idf("%s%s%d", main_name.c_str(ctx), str_suffix, idx)
|
||||
: ctx->idf("%s%s", main_name.c_str(ctx), str_suffix);
|
||||
}
|
||||
|
||||
std::unique_ptr<CellInfo> GowinUtils::create_cell(IdString name, IdString type)
|
||||
{
|
||||
NPNR_ASSERT(!ctx->cells.count(name));
|
||||
|
@ -107,6 +107,9 @@ struct GowinUtils
|
||||
return is_global_wire(ctx->getPipSrcWire(pip)) || is_global_wire(ctx->getPipDstWire(pip));
|
||||
}
|
||||
|
||||
// construct name
|
||||
IdString create_aux_name(IdString main_name, int idx = 0, const char *str_suffix = "_aux$");
|
||||
|
||||
// make cell but do not include it in the list of chip cells.
|
||||
std::unique_ptr<CellInfo> create_cell(IdString name, IdString type);
|
||||
|
||||
|
@ -508,15 +508,6 @@ struct GowinPacker
|
||||
make_iob_nets(*out_iob);
|
||||
}
|
||||
|
||||
IdString create_aux_name(IdString main_name, int idx = 0, const char *str_suffix = "_aux$")
|
||||
{
|
||||
std::string sfx("");
|
||||
if (idx) {
|
||||
sfx = std::to_string(idx);
|
||||
}
|
||||
return ctx->id(main_name.str(ctx) + std::string(str_suffix) + sfx);
|
||||
}
|
||||
|
||||
BelId get_aux_iologic_bel(const CellInfo &ci)
|
||||
{
|
||||
return ctx->getBelByLocation(gwu.get_pair_iologic_bel(ctx->getBelLocation(ci.bel)));
|
||||
@ -529,7 +520,7 @@ struct GowinPacker
|
||||
if (ci.type.in(id_ODDR, id_ODDRC, id_OSER4, id_IDDR, id_IDDRC, id_IDES4)) {
|
||||
return nullptr;
|
||||
}
|
||||
IdString aux_name = create_aux_name(ci.name, idx);
|
||||
IdString aux_name = gwu.create_aux_name(ci.name, idx);
|
||||
BelId bel = get_aux_iologic_bel(ci);
|
||||
BelId io_bel = gwu.get_io_bel_from_iologic(bel);
|
||||
if (!ctx->checkBelAvail(io_bel)) {
|
||||
@ -720,9 +711,9 @@ struct GowinPacker
|
||||
|
||||
// to simplify packaging, the parts of the OSER16 are presented as IOLOGIC cells
|
||||
// and one of these aux cells is declared as main
|
||||
IdString main_name = create_aux_name(ci.name);
|
||||
IdString main_name = gwu.create_aux_name(ci.name);
|
||||
|
||||
IdString aux_name = create_aux_name(ci.name, 1);
|
||||
IdString aux_name = gwu.create_aux_name(ci.name, 1);
|
||||
ctx->createCell(aux_name, id_IOLOGIC_DUMMY);
|
||||
CellInfo *aux = ctx->cells.at(aux_name).get();
|
||||
|
||||
@ -794,9 +785,9 @@ struct GowinPacker
|
||||
|
||||
// to simplify packaging, the parts of the IDES16 are presented as IOLOGIC cells
|
||||
// and one of these aux cells is declared as main
|
||||
IdString main_name = create_aux_name(ci.name);
|
||||
IdString main_name = gwu.create_aux_name(ci.name);
|
||||
|
||||
IdString aux_name = create_aux_name(ci.name, 1);
|
||||
IdString aux_name = gwu.create_aux_name(ci.name, 1);
|
||||
ctx->createCell(aux_name, id_IOLOGIC_DUMMY);
|
||||
CellInfo *aux = ctx->cells.at(aux_name).get();
|
||||
|
||||
@ -1229,7 +1220,7 @@ struct GowinPacker
|
||||
{id_DFFP, id_D}, {id_DFFPE, id_D}, {id_DFFNP, id_D}, {id_DFFNPE, id_D},
|
||||
{id_DFFC, id_D}, {id_DFFCE, id_D}, {id_DFFNC, id_D}, {id_DFFNCE, id_D}};
|
||||
|
||||
int lutffs = h.constrain_cell_pairs(lut_outs, dff_ins, 0);
|
||||
int lutffs = h.constrain_cell_pairs(lut_outs, dff_ins, 1, 1);
|
||||
log_info("Constrained %d LUTFF pairs.\n", lutffs);
|
||||
}
|
||||
|
||||
@ -1365,7 +1356,7 @@ struct GowinPacker
|
||||
}
|
||||
|
||||
// Make a decoder
|
||||
auto lut_cell = gwu.create_cell(create_aux_name(ci->name, 0, "_blksel_lut$"), id_LUT4);
|
||||
auto lut_cell = gwu.create_cell(gwu.create_aux_name(ci->name, 0, "_blksel_lut$"), id_LUT4);
|
||||
CellInfo *lut = lut_cell.get();
|
||||
lut->addInput(id_I3);
|
||||
ci->movePortTo(id_CE, lut, id_I3);
|
||||
@ -1441,7 +1432,7 @@ struct GowinPacker
|
||||
}
|
||||
|
||||
// create DFF
|
||||
auto cache_dff_cell = gwu.create_cell(create_aux_name(ci->name, i, "_cache_dff$"), dff_type);
|
||||
auto cache_dff_cell = gwu.create_cell(gwu.create_aux_name(ci->name, i, "_cache_dff$"), dff_type);
|
||||
CellInfo *cache_dff = cache_dff_cell.get();
|
||||
cache_dff->addInput(id_CE);
|
||||
cache_dff->connectPort(id_CE, oce_net);
|
||||
@ -1477,7 +1468,7 @@ struct GowinPacker
|
||||
log_info(" apply the SP fix\n");
|
||||
}
|
||||
// create WRE LUT
|
||||
auto wre_lut_cell = gwu.create_cell(create_aux_name(ci->name, 0, "_wre_lut$"), id_LUT4);
|
||||
auto wre_lut_cell = gwu.create_cell(gwu.create_aux_name(ci->name, 0, "_wre_lut$"), id_LUT4);
|
||||
CellInfo *wre_lut = wre_lut_cell.get();
|
||||
wre_lut->setParam(id_INIT, 0x8888);
|
||||
ci->movePortTo(id_CE, wre_lut, id_I0);
|
||||
@ -1486,7 +1477,7 @@ struct GowinPacker
|
||||
ci->connectPorts(id_WRE, wre_lut, id_F);
|
||||
|
||||
// create CE LUT
|
||||
auto ce_lut_cell = gwu.create_cell(create_aux_name(ci->name, 0, "_ce_lut$"), id_LUT4);
|
||||
auto ce_lut_cell = gwu.create_cell(gwu.create_aux_name(ci->name, 0, "_ce_lut$"), id_LUT4);
|
||||
CellInfo *ce_lut = ce_lut_cell.get();
|
||||
ce_lut->setParam(id_INIT, 0xeeee);
|
||||
wre_lut->copyPortTo(id_I0, ce_lut, id_I0);
|
||||
@ -1497,7 +1488,7 @@ struct GowinPacker
|
||||
// create ce reg
|
||||
int write_mode = ci->params.at(id_WRITE_MODE).as_int64();
|
||||
IdString dff_type = write_mode ? id_DFF : id_DFFR;
|
||||
auto ce_pre_dff_cell = gwu.create_cell(create_aux_name(ci->name, 0, "_ce_pre_dff$"), dff_type);
|
||||
auto ce_pre_dff_cell = gwu.create_cell(gwu.create_aux_name(ci->name, 0, "_ce_pre_dff$"), dff_type);
|
||||
CellInfo *ce_pre_dff = ce_pre_dff_cell.get();
|
||||
ce_pre_dff->addInput(id_D);
|
||||
ce_lut->copyPortTo(id_I0, ce_pre_dff, id_D);
|
||||
@ -1513,7 +1504,7 @@ struct GowinPacker
|
||||
// add delay register in pipeline mode
|
||||
int read_mode = ci->params.at(id_READ_MODE).as_int64();
|
||||
if (read_mode) {
|
||||
auto ce_pipe_dff_cell = gwu.create_cell(create_aux_name(ci->name, 0, "_ce_pipe_dff$"), id_DFF);
|
||||
auto ce_pipe_dff_cell = gwu.create_cell(gwu.create_aux_name(ci->name, 0, "_ce_pipe_dff$"), id_DFF);
|
||||
new_cells.push_back(std::move(ce_pipe_dff_cell));
|
||||
CellInfo *ce_pipe_dff = new_cells.back().get();
|
||||
ce_pipe_dff->addInput(id_D);
|
||||
@ -1533,7 +1524,7 @@ struct GowinPacker
|
||||
continue;
|
||||
}
|
||||
// create cache lut
|
||||
auto cache_lut_cell = gwu.create_cell(create_aux_name(ci->name, i, "_cache_lut$"), id_LUT4);
|
||||
auto cache_lut_cell = gwu.create_cell(gwu.create_aux_name(ci->name, i, "_cache_lut$"), id_LUT4);
|
||||
CellInfo *cache_lut = cache_lut_cell.get();
|
||||
cache_lut->setParam(id_INIT, 0xcaca);
|
||||
cache_lut->addInput(id_I0);
|
||||
@ -1544,7 +1535,7 @@ struct GowinPacker
|
||||
new_ce_net_src->connectPorts(id_Q, cache_lut, id_I2);
|
||||
|
||||
// create cache DFF
|
||||
auto cache_dff_cell = gwu.create_cell(create_aux_name(ci->name, i, "_cache_dff$"), id_DFFE);
|
||||
auto cache_dff_cell = gwu.create_cell(gwu.create_aux_name(ci->name, i, "_cache_dff$"), id_DFFE);
|
||||
CellInfo *cache_dff = cache_dff_cell.get();
|
||||
cache_dff->addInput(id_CE);
|
||||
cache_dff->addInput(id_D);
|
||||
@ -1950,7 +1941,7 @@ struct GowinPacker
|
||||
ci->constr_y = 0;
|
||||
ci->constr_y = 0;
|
||||
|
||||
IdString mult_name = create_aux_name(ci->name);
|
||||
IdString mult_name = gwu.create_aux_name(ci->name);
|
||||
std::unique_ptr<CellInfo> mult_cell = gwu.create_cell(mult_name, id_DUMMY_CELL);
|
||||
new_cells.push_back(std::move(mult_cell));
|
||||
CellInfo *mult_ci = new_cells.back().get();
|
||||
@ -2009,7 +2000,7 @@ struct GowinPacker
|
||||
ci->constr_children.clear();
|
||||
|
||||
for (int i = 0; i < 2; ++i) {
|
||||
IdString padd_name = create_aux_name(ci->name, i * 2);
|
||||
IdString padd_name = gwu.create_aux_name(ci->name, i * 2);
|
||||
std::unique_ptr<CellInfo> padd_cell = gwu.create_cell(padd_name, id_DUMMY_CELL);
|
||||
new_cells.push_back(std::move(padd_cell));
|
||||
CellInfo *padd_ci = new_cells.back().get();
|
||||
@ -2020,7 +2011,7 @@ struct GowinPacker
|
||||
padd_ci->constr_y = 0;
|
||||
padd_ci->constr_z = BelZ::PADD9_0_0_Z - BelZ::PADD18_0_0_Z + i;
|
||||
|
||||
IdString mult_name = create_aux_name(ci->name, i * 2 + 1);
|
||||
IdString mult_name = gwu.create_aux_name(ci->name, i * 2 + 1);
|
||||
std::unique_ptr<CellInfo> mult_cell = gwu.create_cell(mult_name, id_DUMMY_CELL);
|
||||
new_cells.push_back(std::move(mult_cell));
|
||||
CellInfo *mult_ci = new_cells.back().get();
|
||||
@ -2061,7 +2052,7 @@ struct GowinPacker
|
||||
ci->constr_z = 0;
|
||||
ci->constr_children.clear();
|
||||
|
||||
IdString padd_name = create_aux_name(ci->name);
|
||||
IdString padd_name = gwu.create_aux_name(ci->name);
|
||||
std::unique_ptr<CellInfo> padd_cell = gwu.create_cell(padd_name, id_DUMMY_CELL);
|
||||
new_cells.push_back(std::move(padd_cell));
|
||||
CellInfo *padd_ci = new_cells.back().get();
|
||||
@ -2103,7 +2094,7 @@ struct GowinPacker
|
||||
ci->constr_children.clear();
|
||||
|
||||
for (int i = 0; i < 2; ++i) {
|
||||
IdString padd_name = create_aux_name(ci->name, i * 2);
|
||||
IdString padd_name = gwu.create_aux_name(ci->name, i * 2);
|
||||
std::unique_ptr<CellInfo> padd_cell = gwu.create_cell(padd_name, id_DUMMY_CELL);
|
||||
new_cells.push_back(std::move(padd_cell));
|
||||
CellInfo *padd_ci = new_cells.back().get();
|
||||
@ -2114,7 +2105,7 @@ struct GowinPacker
|
||||
padd_ci->constr_y = 0;
|
||||
padd_ci->constr_z = BelZ::PADD9_0_0_Z - BelZ::MULT18X18_0_0_Z + i;
|
||||
|
||||
IdString mult_name = create_aux_name(ci->name, i * 2 + 1);
|
||||
IdString mult_name = gwu.create_aux_name(ci->name, i * 2 + 1);
|
||||
std::unique_ptr<CellInfo> mult_cell = gwu.create_cell(mult_name, id_DUMMY_CELL);
|
||||
new_cells.push_back(std::move(mult_cell));
|
||||
CellInfo *mult_ci = new_cells.back().get();
|
||||
@ -2161,7 +2152,7 @@ struct GowinPacker
|
||||
ci->constr_children.clear();
|
||||
|
||||
for (int i = 0; i < 4; ++i) {
|
||||
IdString padd_name = create_aux_name(ci->name, i * 2);
|
||||
IdString padd_name = gwu.create_aux_name(ci->name, i * 2);
|
||||
std::unique_ptr<CellInfo> padd_cell = gwu.create_cell(padd_name, id_DUMMY_CELL);
|
||||
new_cells.push_back(std::move(padd_cell));
|
||||
CellInfo *padd_ci = new_cells.back().get();
|
||||
@ -2172,7 +2163,7 @@ struct GowinPacker
|
||||
padd_ci->constr_y = 0;
|
||||
padd_ci->constr_z = BelZ::PADD9_0_0_Z - BelZ::ALU54D_0_Z + 4 * (i / 2) + (i % 2);
|
||||
|
||||
IdString mult_name = create_aux_name(ci->name, i * 2 + 1);
|
||||
IdString mult_name = gwu.create_aux_name(ci->name, i * 2 + 1);
|
||||
std::unique_ptr<CellInfo> mult_cell = gwu.create_cell(mult_name, id_DUMMY_CELL);
|
||||
new_cells.push_back(std::move(mult_cell));
|
||||
CellInfo *mult_ci = new_cells.back().get();
|
||||
@ -2266,7 +2257,7 @@ struct GowinPacker
|
||||
ci->constr_children.clear();
|
||||
|
||||
for (int i = 0; i < 2; ++i) {
|
||||
IdString padd_name = create_aux_name(ci->name, i * 2);
|
||||
IdString padd_name = gwu.create_aux_name(ci->name, i * 2);
|
||||
std::unique_ptr<CellInfo> padd_cell = gwu.create_cell(padd_name, id_DUMMY_CELL);
|
||||
new_cells.push_back(std::move(padd_cell));
|
||||
CellInfo *padd_ci = new_cells.back().get();
|
||||
@ -2277,7 +2268,7 @@ struct GowinPacker
|
||||
padd_ci->constr_y = 0;
|
||||
padd_ci->constr_z = BelZ::PADD9_0_0_Z - BelZ::MULTALU18X18_0_Z + i;
|
||||
|
||||
IdString mult_name = create_aux_name(ci->name, i * 2 + 1);
|
||||
IdString mult_name = gwu.create_aux_name(ci->name, i * 2 + 1);
|
||||
std::unique_ptr<CellInfo> mult_cell = gwu.create_cell(mult_name, id_DUMMY_CELL);
|
||||
new_cells.push_back(std::move(mult_cell));
|
||||
CellInfo *mult_ci = new_cells.back().get();
|
||||
@ -2369,7 +2360,7 @@ struct GowinPacker
|
||||
ci->constr_children.clear();
|
||||
|
||||
for (int i = 0; i < 2; ++i) {
|
||||
IdString padd_name = create_aux_name(ci->name, i * 2);
|
||||
IdString padd_name = gwu.create_aux_name(ci->name, i * 2);
|
||||
std::unique_ptr<CellInfo> padd_cell = gwu.create_cell(padd_name, id_DUMMY_CELL);
|
||||
new_cells.push_back(std::move(padd_cell));
|
||||
CellInfo *padd_ci = new_cells.back().get();
|
||||
@ -2380,7 +2371,7 @@ struct GowinPacker
|
||||
padd_ci->constr_y = 0;
|
||||
padd_ci->constr_z = BelZ::PADD9_0_0_Z - BelZ::MULTALU36X18_0_Z + i;
|
||||
|
||||
IdString mult_name = create_aux_name(ci->name, i * 2 + 1);
|
||||
IdString mult_name = gwu.create_aux_name(ci->name, i * 2 + 1);
|
||||
std::unique_ptr<CellInfo> mult_cell = gwu.create_cell(mult_name, id_DUMMY_CELL);
|
||||
new_cells.push_back(std::move(mult_cell));
|
||||
CellInfo *mult_ci = new_cells.back().get();
|
||||
@ -2463,7 +2454,7 @@ struct GowinPacker
|
||||
ci->constr_children.clear();
|
||||
|
||||
for (int i = 0; i < 2; ++i) {
|
||||
IdString padd_name = create_aux_name(ci->name, i * 2);
|
||||
IdString padd_name = gwu.create_aux_name(ci->name, i * 2);
|
||||
std::unique_ptr<CellInfo> padd_cell = gwu.create_cell(padd_name, id_DUMMY_CELL);
|
||||
new_cells.push_back(std::move(padd_cell));
|
||||
CellInfo *padd_ci = new_cells.back().get();
|
||||
@ -2474,7 +2465,7 @@ struct GowinPacker
|
||||
padd_ci->constr_y = 0;
|
||||
padd_ci->constr_z = BelZ::PADD9_0_0_Z - BelZ::MULTADDALU18X18_0_Z + i;
|
||||
|
||||
IdString mult_name = create_aux_name(ci->name, i * 2 + 1);
|
||||
IdString mult_name = gwu.create_aux_name(ci->name, i * 2 + 1);
|
||||
std::unique_ptr<CellInfo> mult_cell = gwu.create_cell(mult_name, id_DUMMY_CELL);
|
||||
new_cells.push_back(std::move(mult_cell));
|
||||
CellInfo *mult_ci = new_cells.back().get();
|
||||
@ -2549,7 +2540,7 @@ struct GowinPacker
|
||||
ci->constr_children.clear();
|
||||
|
||||
for (int i = 0; i < 8; ++i) {
|
||||
IdString padd_name = create_aux_name(ci->name, i * 2);
|
||||
IdString padd_name = gwu.create_aux_name(ci->name, i * 2);
|
||||
std::unique_ptr<CellInfo> padd_cell = gwu.create_cell(padd_name, id_DUMMY_CELL);
|
||||
new_cells.push_back(std::move(padd_cell));
|
||||
CellInfo *padd_ci = new_cells.back().get();
|
||||
@ -2562,7 +2553,7 @@ struct GowinPacker
|
||||
padd_ci->constr_y = 0;
|
||||
padd_ci->constr_z = padd_z[i / 2] - BelZ::MULT36X36_Z + i % 2;
|
||||
|
||||
IdString mult_name = create_aux_name(ci->name, i * 2 + 1);
|
||||
IdString mult_name = gwu.create_aux_name(ci->name, i * 2 + 1);
|
||||
std::unique_ptr<CellInfo> mult_cell = gwu.create_cell(mult_name, id_DUMMY_CELL);
|
||||
new_cells.push_back(std::move(mult_cell));
|
||||
CellInfo *mult_ci = new_cells.back().get();
|
||||
@ -3165,7 +3156,7 @@ struct GowinPacker
|
||||
}
|
||||
|
||||
std::unique_ptr<CellInfo> lut_cell =
|
||||
gwu.create_cell(create_aux_name(ci.name, lut_idx, "_lut$"), id_LUT4);
|
||||
gwu.create_cell(gwu.create_aux_name(ci.name, lut_idx, "_lut$"), id_LUT4);
|
||||
new_cells.push_back(std::move(lut_cell));
|
||||
CellInfo *lut = new_cells.back().get();
|
||||
lut->addInput(id_I0);
|
||||
@ -3340,8 +3331,7 @@ struct GowinPacker
|
||||
pack_alus();
|
||||
ctx->check();
|
||||
|
||||
// XXX Leads to the impossibility of placement on lower models.
|
||||
// constrain_lutffs();
|
||||
constrain_lutffs();
|
||||
ctx->check();
|
||||
|
||||
pack_pll();
|
||||
|
Loading…
Reference in New Issue
Block a user