diff options
-rw-r--r-- | common/nextpnr.cc | 5 | ||||
-rw-r--r-- | common/timing.cc | 18 | ||||
-rw-r--r-- | ecp5/bitstream.cc | 9 | ||||
-rw-r--r-- | ecp5/globals.cc | 2 | ||||
-rw-r--r-- | ecp5/pack.cc | 12 |
5 files changed, 40 insertions, 6 deletions
diff --git a/common/nextpnr.cc b/common/nextpnr.cc index 068bca6f..4e6407b2 100644 --- a/common/nextpnr.cc +++ b/common/nextpnr.cc @@ -245,6 +245,11 @@ void Context::check() const NPNR_ASSERT(ni == getBoundPipNet(w.second.pip)); } } + if (ni->driver.cell != nullptr) + NPNR_ASSERT(ni->driver.cell->ports.at(ni->driver.port).net == ni); + for (auto user : ni->users) { + NPNR_ASSERT(user.cell->ports.at(user.port).net == ni); + } } for (auto w : getWires()) { diff --git a/common/timing.cc b/common/timing.cc index 62697353..e5e90445 100644 --- a/common/timing.cc +++ b/common/timing.cc @@ -164,6 +164,24 @@ struct Timing } // Sanity check to ensure that all ports where fanins were recorded were indeed visited + if (!port_fanin.empty()) { + for (auto fanin : port_fanin) { + NetInfo *net = fanin.first->net; + if (net != nullptr) { + log_info(" remaining fanin includes %s (net %s)\n", fanin.first->name.c_str(ctx), + net->name.c_str(ctx)); + if (net->driver.cell != nullptr) + log_info(" driver = %s.%s\n", net->driver.cell->name.c_str(ctx), + net->driver.port.c_str(ctx)); + for (auto net_user : net->users) + log_info(" user: %s.%s\n", net_user.cell->name.c_str(ctx), + net_user.port.c_str(ctx)); + } else { + log_info(" remaining fanin includes %s (no net)\n", fanin.first->name.c_str(ctx)); + + } + } + } NPNR_ASSERT(port_fanin.empty()); // Go forwards topographically to find the maximum arrival time and max path length for each net diff --git a/ecp5/bitstream.cc b/ecp5/bitstream.cc index bfd51666..d8914f1a 100644 --- a/ecp5/bitstream.cc +++ b/ecp5/bitstream.cc @@ -269,6 +269,15 @@ void write_bitstream(Context *ctx, std::string base_config_file, std::string tex str_or_default(ci->params, ctx->id("INJECT1_1"), "YES")); } + if (str_or_default(ci->params, ctx->id("MODE"), "LOGIC") == "DPRAM" && slice == "SLICEA") { + cc.tiles[tname].add_enum(slice + ".WREMUX", + str_or_default(ci->params, ctx->id("WREMUX"), "WRE")); + + // FIXME: WCKMUX + NPNR_ASSERT(str_or_default(ci->params, ctx->id("WCKMUX"), "WCK") == "WCK"); + } + + // Tie unused inputs high for (auto input : {id_A0, id_B0, id_C0, id_D0, id_A1, id_B1, id_C1, id_D1}) { if (ci->ports.find(input) == ci->ports.end() || ci->ports.at(input).net == nullptr) { diff --git a/ecp5/globals.cc b/ecp5/globals.cc index 91d224e5..e5627b66 100644 --- a/ecp5/globals.cc +++ b/ecp5/globals.cc @@ -52,7 +52,7 @@ class Ecp5GlobalRouter private: bool is_clock_port(const PortRef &user) { - if (user.cell->type == id_TRELLIS_SLICE && user.port == id_CLK) + if (user.cell->type == id_TRELLIS_SLICE && (user.port == id_CLK || user.port == id_WCK)) return true; return false; } diff --git a/ecp5/pack.cc b/ecp5/pack.cc index fbe3879a..53203e33 100644 --- a/ecp5/pack.cc +++ b/ecp5/pack.cc @@ -108,7 +108,7 @@ class Ecp5Packer } // Return whether or not an FF can be added to a tile (pairing checks must also be done using the fn above) - bool can_add_ff_to_file(const std::vector<CellInfo *> &tile_ffs, CellInfo *ff0) + bool can_add_ff_to_tile(const std::vector<CellInfo *> &tile_ffs, CellInfo *ff0) { for (const auto &existing : tile_ffs) { if (net_or_nullptr(existing, ctx->id("CLK")) != net_or_nullptr(ff0, ctx->id("CLK"))) @@ -512,7 +512,7 @@ class Ecp5Packer NetInfo *f0net = slice->ports.at(ctx->id("F0")).net; if (f0net != nullptr) { ff0 = net_only_drives(ctx, f0net, is_ff, ctx->id("DI"), false); - if (ff0 != nullptr && can_add_ff_to_file(tile_ffs, ff0)) { + if (ff0 != nullptr && can_add_ff_to_tile(tile_ffs, ff0)) { ff_to_slice(ctx, ff0, slice.get(), 0, true); tile_ffs.push_back(ff0); packed_cells.insert(ff0->name); @@ -524,7 +524,7 @@ class Ecp5Packer if (f1net != nullptr) { ff1 = net_only_drives(ctx, f1net, is_ff, ctx->id("DI"), false); if (ff1 != nullptr && (ff0 == nullptr || can_pack_ffs(ff0, ff1)) && - can_add_ff_to_file(tile_ffs, ff1)) { + can_add_ff_to_tile(tile_ffs, ff1)) { ff_to_slice(ctx, ff1, slice.get(), 1, true); tile_ffs.push_back(ff1); packed_cells.insert(ff1->name); @@ -592,7 +592,7 @@ class Ecp5Packer NetInfo *f0net = slice->ports.at(ctx->id("F0")).net; if (f0net != nullptr) { ff0 = net_only_drives(ctx, f0net, is_ff, ctx->id("DI"), false); - if (ff0 != nullptr && can_add_ff_to_file(tile_ffs, ff0)) { + if (ff0 != nullptr && can_add_ff_to_tile(tile_ffs, ff0)) { ff_to_slice(ctx, ff0, slice, 0, true); tile_ffs.push_back(ff0); packed_cells.insert(ff0->name); @@ -604,7 +604,7 @@ class Ecp5Packer if (f1net != nullptr) { ff1 = net_only_drives(ctx, f1net, is_ff, ctx->id("DI"), false); if (ff1 != nullptr && (ff0 == nullptr || can_pack_ffs(ff0, ff1)) && - can_add_ff_to_file(tile_ffs, ff1)) { + can_add_ff_to_tile(tile_ffs, ff1)) { ff_to_slice(ctx, ff1, slice, 1, true); tile_ffs.push_back(ff1); packed_cells.insert(ff1->name); @@ -888,6 +888,7 @@ class Ecp5Packer { pack_io(); pack_constants(); + pack_dram(); pack_carries(); find_lutff_pairs(); pack_lut5s(); @@ -895,6 +896,7 @@ class Ecp5Packer pack_lut_pairs(); pack_remaining_luts(); pack_remaining_ffs(); + ctx->check(); } private: |