diff options
author | William D. Jones <thor0505@comcast.net> | 2020-06-27 19:43:16 -0400 |
---|---|---|
committer | gatecat <gatecat@ds0.me> | 2021-02-12 10:36:59 +0000 |
commit | 512daf2c897e84738684566188c86024ae5abe8c (patch) | |
tree | e03abd2fd27d0cdd97ca2a8744495983f764919d | |
parent | 9704f422dcae5788d39edf35addd6ee5e9dfd428 (diff) | |
download | nextpnr-512daf2c897e84738684566188c86024ae5abe8c.tar.gz nextpnr-512daf2c897e84738684566188c86024ae5abe8c.tar.bz2 nextpnr-512daf2c897e84738684566188c86024ae5abe8c.zip |
machxo2: Remove generic packing.
-rw-r--r-- | machxo2/arch.cc | 11 | ||||
-rw-r--r-- | machxo2/pack.cc | 244 |
2 files changed, 2 insertions, 253 deletions
diff --git a/machxo2/arch.cc b/machxo2/arch.cc index 70de80cf..ed62ed37 100644 --- a/machxo2/arch.cc +++ b/machxo2/arch.cc @@ -491,16 +491,7 @@ const std::vector<std::string> Arch::availableRouters = {"router1", "router2"}; void Arch::assignArchInfo() { - for (auto &cell : getCtx()->cells) { - CellInfo *ci = cell.second.get(); - if (ci->type == id("GENERIC_SLICE")) { - ci->is_slice = true; - ci->slice_clk = get_net_or_empty(ci, id("CLK")); - } else { - ci->is_slice = false; - } - ci->user_group = int_or_default(ci->attrs, id("PACK_GROUP"), -1); - } + } bool Arch::cellsCompatible(const CellInfo **cells, int count) const diff --git a/machxo2/pack.cc b/machxo2/pack.cc index b995375a..38edc7aa 100644 --- a/machxo2/pack.cc +++ b/machxo2/pack.cc @@ -27,255 +27,13 @@ NEXTPNR_NAMESPACE_BEGIN -// Pack LUTs and LUT-FF pairs -static void pack_lut_lutffs(Context *ctx) -{ - log_info("Packing LUT-FFs..\n"); - - std::unordered_set<IdString> packed_cells; - std::vector<std::unique_ptr<CellInfo>> new_cells; - for (auto cell : sorted(ctx->cells)) { - CellInfo *ci = cell.second; - if (ctx->verbose) - log_info("cell '%s' is of type '%s'\n", ci->name.c_str(ctx), ci->type.c_str(ctx)); - if (is_lut(ctx, ci)) { - std::unique_ptr<CellInfo> packed = - create_generic_cell(ctx, ctx->id("GENERIC_SLICE"), ci->name.str(ctx) + "_LC"); - std::copy(ci->attrs.begin(), ci->attrs.end(), std::inserter(packed->attrs, packed->attrs.begin())); - packed_cells.insert(ci->name); - if (ctx->verbose) - log_info("packed cell %s into %s\n", ci->name.c_str(ctx), packed->name.c_str(ctx)); - // See if we can pack into a DFF - // TODO: LUT cascade - NetInfo *o = ci->ports.at(ctx->id("Q")).net; - CellInfo *dff = net_only_drives(ctx, o, is_ff, ctx->id("D"), true); - auto lut_bel = ci->attrs.find(ctx->id("BEL")); - bool packed_dff = false; - if (dff) { - if (ctx->verbose) - log_info("found attached dff %s\n", dff->name.c_str(ctx)); - auto dff_bel = dff->attrs.find(ctx->id("BEL")); - if (lut_bel != ci->attrs.end() && dff_bel != dff->attrs.end() && lut_bel->second != dff_bel->second) { - // Locations don't match, can't pack - } else { - lut_to_lc(ctx, ci, packed.get(), false); - dff_to_lc(ctx, dff, packed.get(), false); - ctx->nets.erase(o->name); - if (dff_bel != dff->attrs.end()) - packed->attrs[ctx->id("BEL")] = dff_bel->second; - packed_cells.insert(dff->name); - if (ctx->verbose) - log_info("packed cell %s into %s\n", dff->name.c_str(ctx), packed->name.c_str(ctx)); - packed_dff = true; - } - } - if (!packed_dff) { - lut_to_lc(ctx, ci, packed.get(), true); - } - new_cells.push_back(std::move(packed)); - } - } - for (auto pcell : packed_cells) { - ctx->cells.erase(pcell); - } - for (auto &ncell : new_cells) { - ctx->cells[ncell->name] = std::move(ncell); - } -} - -// Pack FFs not packed as LUTFFs -static void pack_nonlut_ffs(Context *ctx) -{ - log_info("Packing non-LUT FFs..\n"); - - std::unordered_set<IdString> packed_cells; - std::vector<std::unique_ptr<CellInfo>> new_cells; - - for (auto cell : sorted(ctx->cells)) { - CellInfo *ci = cell.second; - if (is_ff(ctx, ci)) { - std::unique_ptr<CellInfo> packed = - create_generic_cell(ctx, ctx->id("GENERIC_SLICE"), ci->name.str(ctx) + "_DFFLC"); - std::copy(ci->attrs.begin(), ci->attrs.end(), std::inserter(packed->attrs, packed->attrs.begin())); - if (ctx->verbose) - log_info("packed cell %s into %s\n", ci->name.c_str(ctx), packed->name.c_str(ctx)); - packed_cells.insert(ci->name); - dff_to_lc(ctx, ci, packed.get(), true); - new_cells.push_back(std::move(packed)); - } - } - for (auto pcell : packed_cells) { - ctx->cells.erase(pcell); - } - for (auto &ncell : new_cells) { - ctx->cells[ncell->name] = std::move(ncell); - } -} - -// Merge a net into a constant net -static void set_net_constant(const Context *ctx, NetInfo *orig, NetInfo *constnet, bool constval) -{ - orig->driver.cell = nullptr; - for (auto user : orig->users) { - if (user.cell != nullptr) { - CellInfo *uc = user.cell; - if (ctx->verbose) - log_info("%s user %s\n", orig->name.c_str(ctx), uc->name.c_str(ctx)); - if ((is_lut(ctx, uc) || is_lc(ctx, uc)) && (user.port.str(ctx).at(0) == 'I') && !constval) { - uc->ports[user.port].net = nullptr; - } else { - uc->ports[user.port].net = constnet; - constnet->users.push_back(user); - } - } - } - orig->users.clear(); -} - -// Pack constants (simple implementation) -static void pack_constants(Context *ctx) -{ - log_info("Packing constants..\n"); - - std::unique_ptr<CellInfo> gnd_cell = create_generic_cell(ctx, ctx->id("GENERIC_SLICE"), "$PACKER_GND"); - gnd_cell->params[ctx->id("INIT")] = Property(0, 1 << 4); - std::unique_ptr<NetInfo> gnd_net = std::unique_ptr<NetInfo>(new NetInfo); - gnd_net->name = ctx->id("$PACKER_GND_NET"); - gnd_net->driver.cell = gnd_cell.get(); - gnd_net->driver.port = ctx->id("F"); - gnd_cell->ports.at(ctx->id("F")).net = gnd_net.get(); - - std::unique_ptr<CellInfo> vcc_cell = create_generic_cell(ctx, ctx->id("GENERIC_SLICE"), "$PACKER_VCC"); - // Fill with 1s - vcc_cell->params[ctx->id("INIT")] = Property(Property::S1).extract(0, (1 << 4), Property::S1); - std::unique_ptr<NetInfo> vcc_net = std::unique_ptr<NetInfo>(new NetInfo); - vcc_net->name = ctx->id("$PACKER_VCC_NET"); - vcc_net->driver.cell = vcc_cell.get(); - vcc_net->driver.port = ctx->id("F"); - vcc_cell->ports.at(ctx->id("F")).net = vcc_net.get(); - - std::vector<IdString> dead_nets; - - bool gnd_used = false; - - for (auto net : sorted(ctx->nets)) { - NetInfo *ni = net.second; - if (ni->driver.cell != nullptr && ni->driver.cell->type == ctx->id("GND")) { - IdString drv_cell = ni->driver.cell->name; - set_net_constant(ctx, ni, gnd_net.get(), false); - gnd_used = true; - dead_nets.push_back(net.first); - ctx->cells.erase(drv_cell); - } else if (ni->driver.cell != nullptr && ni->driver.cell->type == ctx->id("VCC")) { - IdString drv_cell = ni->driver.cell->name; - set_net_constant(ctx, ni, vcc_net.get(), true); - dead_nets.push_back(net.first); - ctx->cells.erase(drv_cell); - } - } - - if (gnd_used) { - ctx->cells[gnd_cell->name] = std::move(gnd_cell); - ctx->nets[gnd_net->name] = std::move(gnd_net); - } - // Vcc cell always inserted for now, as it may be needed during carry legalisation (TODO: trim later if actually - // never used?) - ctx->cells[vcc_cell->name] = std::move(vcc_cell); - ctx->nets[vcc_net->name] = std::move(vcc_net); - - for (auto dn : dead_nets) { - ctx->nets.erase(dn); - } -} - -static bool is_nextpnr_iob(Context *ctx, CellInfo *cell) -{ - return cell->type == ctx->id("$nextpnr_ibuf") || cell->type == ctx->id("$nextpnr_obuf") || - cell->type == ctx->id("$nextpnr_iobuf"); -} - -static bool is_generic_iob(const Context *ctx, const CellInfo *cell) { return cell->type == ctx->id("GENERIC_IOB"); } - -// Pack IO buffers -static void pack_io(Context *ctx) -{ - std::unordered_set<IdString> packed_cells; - std::unordered_set<IdString> delete_nets; - - std::vector<std::unique_ptr<CellInfo>> new_cells; - log_info("Packing IOs..\n"); - - for (auto cell : sorted(ctx->cells)) { - CellInfo *ci = cell.second; - if (is_nextpnr_iob(ctx, ci)) { - CellInfo *iob = nullptr; - if (ci->type == ctx->id("$nextpnr_ibuf") || ci->type == ctx->id("$nextpnr_iobuf")) { - iob = net_only_drives(ctx, ci->ports.at(ctx->id("O")).net, is_generic_iob, ctx->id("PAD"), true, ci); - - } else if (ci->type == ctx->id("$nextpnr_obuf")) { - NetInfo *net = ci->ports.at(ctx->id("I")).net; - iob = net_only_drives(ctx, net, is_generic_iob, ctx->id("PAD"), true, ci); - } - if (iob != nullptr) { - // Trivial case, GENERIC_IOB used. Just destroy the net and the - // iobuf - log_info("%s feeds GENERIC_IOB %s, removing %s %s.\n", ci->name.c_str(ctx), iob->name.c_str(ctx), - ci->type.c_str(ctx), ci->name.c_str(ctx)); - NetInfo *net = iob->ports.at(ctx->id("PAD")).net; - if (((ci->type == ctx->id("$nextpnr_ibuf") || ci->type == ctx->id("$nextpnr_iobuf")) && - net->users.size() > 1) || - (ci->type == ctx->id("$nextpnr_obuf") && (net->users.size() > 2 || net->driver.cell != nullptr))) - log_error("PAD of %s '%s' connected to more than a single top level IO.\n", iob->type.c_str(ctx), - iob->name.c_str(ctx)); - - if (net != nullptr) { - delete_nets.insert(net->name); - iob->ports.at(ctx->id("PAD")).net = nullptr; - } - if (ci->type == ctx->id("$nextpnr_iobuf")) { - NetInfo *net2 = ci->ports.at(ctx->id("I")).net; - if (net2 != nullptr) { - delete_nets.insert(net2->name); - } - } - } else if (bool_or_default(ctx->settings, ctx->id("disable_iobs"))) { - // No IO buffer insertion; just remove nextpnr_[io]buf - for (auto &p : ci->ports) - disconnect_port(ctx, ci, p.first); - } else { - // Create a GENERIC_IOB buffer - std::unique_ptr<CellInfo> ice_cell = - create_generic_cell(ctx, ctx->id("GENERIC_IOB"), ci->name.str(ctx) + "$iob"); - nxio_to_iob(ctx, ci, ice_cell.get(), packed_cells); - new_cells.push_back(std::move(ice_cell)); - iob = new_cells.back().get(); - } - packed_cells.insert(ci->name); - if (iob != nullptr) - std::copy(ci->attrs.begin(), ci->attrs.end(), std::inserter(iob->attrs, iob->attrs.begin())); - } - } - for (auto pcell : packed_cells) { - ctx->cells.erase(pcell); - } - for (auto dnet : delete_nets) { - ctx->nets.erase(dnet); - } - for (auto &ncell : new_cells) { - ctx->cells[ncell->name] = std::move(ncell); - } -} - // Main pack function bool Arch::pack() { Context *ctx = getCtx(); + log_info("Packing implementation goes here.."); try { log_break(); - pack_constants(ctx); - pack_io(ctx); - pack_lut_lutffs(ctx); - pack_nonlut_ffs(ctx); ctx->settings[ctx->id("pack")] = 1; ctx->assignArchInfo(); log_info("Checksum: 0x%08x\n", ctx->checksum()); |