diff --git a/machxo2/pack.cc b/machxo2/pack.cc index 3b48e084..3a99b256 100644 --- a/machxo2/pack.cc +++ b/machxo2/pack.cc @@ -286,192 +286,6 @@ class MachXO2Packer return false; } - // Pass to pack LUT5s into a newly created slice - void pack_lut5xs() - { - log_info("Packing LUT5-7s...\n"); - - // Gets the "COMB1" side of a LUT5, where we pack a LUT[67] into - auto get_comb1_from_lut5 = [&](CellInfo *lut5) { - NetInfo *f1 = lut5->getPort(id_F1); - NPNR_ASSERT(f1 != nullptr); - NPNR_ASSERT(f1->driver.cell != nullptr); - return f1->driver.cell; - }; - - dict> lut5_roots, lut6_roots, lut7_roots; - for (auto &cell : ctx->cells) { - CellInfo *ci = cell.second.get(); - if (is_pfumx(ctx, ci)) { - NetInfo *f0 = ci->ports.at(id_BLUT).net; - - if (f0 == nullptr) - log_error("PFUMX '%s' has disconnected port 'BLUT'\n", ci->name.c_str(ctx)); - NetInfo *f1 = ci->ports.at(id_ALUT).net; - if (f1 == nullptr) - log_error("PFUMX '%s' has disconnected port 'ALUT'\n", ci->name.c_str(ctx)); - - CellInfo *lut0 = - (f0->driver.cell && f0->driver.cell->type == id_TRELLIS_COMB && f0->driver.port == id_F) - ? f0->driver.cell - : nullptr; - CellInfo *lut1 = - (f1->driver.cell && f1->driver.cell->type == id_TRELLIS_COMB && f1->driver.port == id_F) - ? f1->driver.cell - : nullptr; - if (lut0 == nullptr || lut0->cluster != ClusterId()) - log_error("PFUMX '%s' has BLUT driven by cell other than a LUT\n", ci->name.c_str(ctx)); - if (lut1 == nullptr || lut1->cluster != ClusterId()) - log_error("PFUMX '%s' has ALUT driven by cell other than a LUT\n", ci->name.c_str(ctx)); - lut0->addInput(id_F1); - lut0->addInput(id_M); - lut0->addOutput(id_OFX); - - ci->movePortTo(id_Z, lut0, id_OFX); - ci->movePortTo(id_ALUT, lut0, id_F1); - ci->movePortTo(id_C0, lut0, id_M); - ci->disconnectPort(id_BLUT); - - lut5_roots[lut0->name] = {lut0, lut1}; - packed_cells.insert(ci->name); - } - } - flush_cells(); - // Pack LUT6s - for (auto &cell : ctx->cells) { - CellInfo *ci = cell.second.get(); - if (is_l6mux(ctx, ci)) { - NetInfo *ofx0_0 = ci->ports.at(id_D0).net; - if (ofx0_0 == nullptr) - log_error("L6MUX21 '%s' has disconnected port 'D0'\n", ci->name.c_str(ctx)); - NetInfo *ofx0_1 = ci->ports.at(id_D1).net; - if (ofx0_1 == nullptr) - log_error("L6MUX21 '%s' has disconnected port 'D1'\n", ci->name.c_str(ctx)); - CellInfo *comb0 = (ofx0_0->driver.cell && ofx0_0->driver.cell->type == id_TRELLIS_COMB && - ofx0_0->driver.port == id_OFX) - ? ofx0_0->driver.cell - : nullptr; - CellInfo *comb1 = (ofx0_1->driver.cell && ofx0_1->driver.cell->type == id_TRELLIS_COMB && - ofx0_1->driver.port == id_OFX) - ? ofx0_1->driver.cell - : nullptr; - if (comb0 == nullptr) { - if (!net_driven_by(ctx, ofx0_0, is_l6mux, id_Z)) - log_error("L6MUX21 '%s' has D0 driven by cell other than a SLICE OFX0 but not a LUT7 mux " - "('%s.%s')\n", - ci->name.c_str(ctx), ofx0_0->driver.cell->name.c_str(ctx), - ofx0_0->driver.port.c_str(ctx)); - continue; - } - if (lut6_roots.count(comb0->name)) - continue; - - if (comb1 == nullptr) { - if (!net_driven_by(ctx, ofx0_1, is_l6mux, id_Z)) - log_error("L6MUX21 '%s' has D1 driven by cell other than a SLICE OFX0 but not a LUT7 mux " - "('%s.%s')\n", - ci->name.c_str(ctx), ofx0_0->driver.cell->name.c_str(ctx), - ofx0_0->driver.port.c_str(ctx)); - continue; - } - if (lut6_roots.count(comb1->name)) - continue; - if (ctx->verbose) - log_info(" mux '%s' forms part of a LUT6\n", cell.first.c_str(ctx)); - comb0 = get_comb1_from_lut5(comb0); - comb1 = get_comb1_from_lut5(comb1); - - comb1->addInput(id_FXA); - comb1->addInput(id_FXB); - comb1->addInput(id_M); - comb1->addOutput(id_OFX); - ci->movePortTo(id_D0, comb1, id_FXA); - ci->movePortTo(id_D1, comb1, id_FXB); - ci->movePortTo(id_SD, comb1, id_M); - ci->movePortTo(id_Z, comb1, id_OFX); - lut6_roots[comb1->name] = {comb0, comb1}; - packed_cells.insert(ci->name); - } - } - flush_cells(); - // Pack LUT7s - for (auto &cell : ctx->cells) { - CellInfo *ci = cell.second.get(); - if (is_l6mux(ctx, ci)) { - NetInfo *ofx1_0 = ci->ports.at(id_D0).net; - if (ofx1_0 == nullptr) - log_error("L6MUX21 '%s' has disconnected port 'D0'\n", ci->name.c_str(ctx)); - NetInfo *ofx1_1 = ci->ports.at(id_D1).net; - if (ofx1_1 == nullptr) - log_error("L6MUX21 '%s' has disconnected port 'D1'\n", ci->name.c_str(ctx)); - CellInfo *comb1 = (ofx1_0->driver.cell && ofx1_0->driver.cell->type == id_TRELLIS_COMB && - ofx1_0->driver.port == id_OFX) - ? ofx1_0->driver.cell - : nullptr; - CellInfo *comb3 = (ofx1_1->driver.cell && ofx1_1->driver.cell->type == id_TRELLIS_COMB && - ofx1_1->driver.port == id_OFX) - ? ofx1_1->driver.cell - : nullptr; - if (comb1 == nullptr) - log_error("L6MUX21 '%s' has D0 driven by cell other than a SLICE OFX ('%s.%s')\n", - ci->name.c_str(ctx), ofx1_0->driver.cell->name.c_str(ctx), - ofx1_0->driver.port.c_str(ctx)); - if (comb3 == nullptr) - log_error("L6MUX21 '%s' has D1 driven by cell other than a SLICE OFX ('%s.%s')\n", - ci->name.c_str(ctx), ofx1_1->driver.cell->name.c_str(ctx), - ofx1_1->driver.port.c_str(ctx)); - - NetInfo *fxa_0 = comb1->ports.at(id_FXA).net; - if (fxa_0 == nullptr) - log_error("SLICE '%s' has disconnected port 'FXA'\n", comb1->name.c_str(ctx)); - NetInfo *fxa_1 = comb3->ports.at(id_FXA).net; - if (fxa_1 == nullptr) - log_error("SLICE '%s' has disconnected port 'FXA'\n", comb3->name.c_str(ctx)); - - CellInfo *comb2 = net_driven_by( - ctx, fxa_1, - [](const Context *ctx, const CellInfo *ci) { - (void)ctx; - return ci->type == id_TRELLIS_COMB; - }, - id_OFX); - if (comb2 == nullptr) - log_error("SLICE '%s' has FXA driven by cell other than a SLICE OFX0 ('%s.%s')\n", - comb3->name.c_str(ctx), fxa_1->driver.cell->name.c_str(ctx), - fxa_1->driver.port.c_str(ctx)); - comb2 = get_comb1_from_lut5(comb2); - comb2->addInput(id_FXA); - comb2->addInput(id_FXB); - comb2->addInput(id_M); - comb2->addOutput(id_OFX); - ci->movePortTo(id_D0, comb2, id_FXA); - ci->movePortTo(id_D1, comb2, id_FXB); - ci->movePortTo(id_SD, comb2, id_M); - ci->movePortTo(id_Z, comb2, id_OFX); - - lut7_roots[comb2->name] = {comb1, comb3}; - packed_cells.insert(ci->name); - } - } - - for (auto &root : lut7_roots) { - auto &cells = root.second; - cells.second->cluster = cells.second->name; - cells.second->constr_abs_z = true; - cells.second->constr_z = (1 << Arch::lc_idx_shift) | Arch::BEL_COMB; - rel_constr_cells(cells.second, cells.first, (4 << Arch::lc_idx_shift)); - } - for (auto &root : lut6_roots) { - auto &cells = root.second; - rel_constr_cells(cells.second, cells.first, (2 << Arch::lc_idx_shift)); - } - for (auto &root : lut5_roots) { - auto &cells = root.second; - rel_constr_cells(cells.first, cells.second, (1 << Arch::lc_idx_shift)); - } - flush_cells(); - } - // Simple "packer" to remove nextpnr IOBUFs, this assumes IOBUFs are manually instantiated void pack_io() { @@ -1222,32 +1036,6 @@ class MachXO2Packer new_cells.push_back(std::move(zero_cell)); } - int lookup_delay(const std::string &del_mode) - { - if (del_mode == "USER_DEFINED") - return 0; - else if (del_mode == "DQS_ALIGNED_X2") - return 6; - else if (del_mode == "DQS_CMD_CLK") - return 9; - else if (del_mode == "ECLK_ALIGNED") - return 21; - else if (del_mode == "ECLK_CENTERED") - return 11; - else if (del_mode == "ECLKBRIDGE_ALIGNED") - return 39; - else if (del_mode == "ECLKBRIDGE_CENTERED") - return 29; - else if (del_mode == "SCLK_ALIGNED") - return 50; - else if (del_mode == "SCLK_CENTERED") - return 39; - else if (del_mode == "SCLK_ZEROHOLD") - return 59; - else - log_error("Unsupported DEL_MODE '%s'\n", del_mode.c_str()); - } - void generate_constraints() { log_info("Generating derived timing constraints...\n"); @@ -1460,7 +1248,6 @@ class MachXO2Packer pack_dram(); pack_carries(); pack_luts(); - pack_lut5xs(); pack_ffs(); generate_constraints(); ctx->fixupHierarchy();