From 7c1544f4d8e5dc75d6d6a8cf973888f5c94bd1b9 Mon Sep 17 00:00:00 2001 From: Keith Rothman <537074+litghost@users.noreply.github.com> Date: Tue, 16 Feb 2021 14:51:25 -0800 Subject: [PATCH] Continue fixes. Signed-off-by: Keith Rothman <537074+litghost@users.noreply.github.com> --- .gitignore | 4 ++ fpga_interchange/arch.cc | 12 ++++++ fpga_interchange/arch.h | 13 ++---- fpga_interchange/arch_pack_io.cc | 26 ++++++++++-- fpga_interchange/fpga_interchange.cpp | 59 ++++++++++++++++++++++----- fpga_interchange/main.cc | 6 +++ 6 files changed, 97 insertions(+), 23 deletions(-) diff --git a/.gitignore b/.gitignore index eea5bf5c..1c6e2034 100644 --- a/.gitignore +++ b/.gitignore @@ -37,3 +37,7 @@ install_manifest.txt /ImportExecutables.cmake *-coverage/ *-coverage.info +*.netlist +*.phys +*.dcp +*.bit diff --git a/fpga_interchange/arch.cc b/fpga_interchange/arch.cc index 58fa3c85..fb4b1b3d 100644 --- a/fpga_interchange/arch.cc +++ b/fpga_interchange/arch.cc @@ -828,6 +828,18 @@ bool Arch::is_net_within_site(const NetInfo &net) const return true; } +size_t Arch::get_cell_type_index(IdString cell_type) const +{ + const CellMapPOD &cell_map = *chip_info->cell_map; + int cell_offset = cell_type.index - cell_map.cell_names[0]; + if((cell_offset < 0 || cell_offset >= cell_map.cell_names.ssize())) { + log_error("Cell %s is not a placable element.\n", cell_type.c_str(this)); + } + NPNR_ASSERT(cell_map.cell_names[cell_offset] == cell_type.index); + + return cell_offset; +} + // Instance constraint templates. template void Arch::ArchConstraints::bindBel(Arch::ArchConstraints::TagState *, const Arch::ConstraintRange); template void Arch::ArchConstraints::unbindBel(Arch::ArchConstraints::TagState *, const Arch::ConstraintRange); diff --git a/fpga_interchange/arch.h b/fpga_interchange/arch.h index cd987001..556aa566 100644 --- a/fpga_interchange/arch.h +++ b/fpga_interchange/arch.h @@ -1405,15 +1405,7 @@ struct Arch : ArchAPI return BelBucketId(); } - size_t get_cell_type_index(IdString cell_type) const - { - const CellMapPOD &cell_map = *chip_info->cell_map; - int cell_offset = cell_type.index - cell_map.cell_names[0]; - NPNR_ASSERT(cell_offset >= 0 && cell_offset < cell_map.cell_names.ssize()); - NPNR_ASSERT(cell_map.cell_names[cell_offset] == cell_type.index); - - return cell_offset; - } + size_t get_cell_type_index(IdString cell_type) const; BelBucketId getBelBucketForCellType(IdString cell_type) const override { @@ -1444,11 +1436,12 @@ struct Arch : ArchAPI return pads.count(bel) > 0; } - auto cell_type_index = get_cell_type_index(cell_type); const auto &bel_data = bel_info(chip_info, bel); if (bel_data.category != BEL_CATEGORY_LOGIC) { return false; } + + auto cell_type_index = get_cell_type_index(cell_type); return bel_data.pin_map[cell_type_index] != -1; } diff --git a/fpga_interchange/arch_pack_io.cc b/fpga_interchange/arch_pack_io.cc index 16d0d05f..2bddad8b 100644 --- a/fpga_interchange/arch_pack_io.cc +++ b/fpga_interchange/arch_pack_io.cc @@ -118,6 +118,7 @@ void Arch::pack_ports() // constraints between the port cell create by nextpnr and cells that are // immediately attached to that port cell. for (auto port_pair : port_cells) { + IdString port_name = port_pair.first; CellInfo *port_cell = port_pair.second; std::unordered_set tightly_attached_bels; @@ -135,6 +136,13 @@ void Arch::pack_ports() } } + if(getCtx()->verbose) { + log_info("Tightly attached BELs for port %s\n", port_name.c_str(getCtx())); + for(CellInfo * cell : tightly_attached_bels) { + log_info(" - %s : %s\n", cell->name.c_str(getCtx()), cell->type.c_str(getCtx())); + } + } + NPNR_ASSERT(tightly_attached_bels.erase(port_cell) == 1); std::unordered_set cell_types_in_io_group; for (CellInfo *cell : tightly_attached_bels) { @@ -163,6 +171,10 @@ void Arch::pack_ports() } } + if(possible_site_types.empty()) { + log_error("Port '%s' has no possible site types!\n", port_name.c_str(getCtx())); + } + auto iter = port_cell->attrs.find(id("PACKAGE_PIN")); if (iter == port_cell->attrs.end()) { // FIXME: Relax this constraint @@ -176,11 +188,12 @@ void Arch::pack_ports() log_error("Package pin '%s' not found in part %s\n", package_pin_id.c_str(getCtx()), get_part().c_str()); } NPNR_ASSERT(pin_iter != package_pin_bels.end()); + const auto &site_type_to_bel = pin_iter->second; BelId package_bel; for (IdString site_type : possible_site_types) { - auto site_iter = pin_iter->second.find(site_type); - if (site_iter != pin_iter->second.end()) { + auto site_iter = site_type_to_bel.find(site_type); + if (site_iter != site_type_to_bel.end()) { // FIXME: Need to handle case where a port can be in multiple // modes, but only one of the modes works. // @@ -188,7 +201,14 @@ void Arch::pack_ports() package_bel = site_iter->second; } } - NPNR_ASSERT(package_bel != BelId()); + + if(package_bel == BelId()) { + log_info("Failed to find BEL for package pin '%s' in any possible site types:\n", package_pin_id.c_str(getCtx())); + for (IdString site_type : possible_site_types) { + log_info(" - %s\n", site_type.c_str(getCtx())); + } + log_error("Failed to find BEL for package pin '%s'\n", package_pin_id.c_str(getCtx())); + } std::unordered_set placed_cells; bindBel(package_bel, port_cell, STRENGTH_FIXED); diff --git a/fpga_interchange/fpga_interchange.cpp b/fpga_interchange/fpga_interchange.cpp index 13f58e66..f2ac7910 100644 --- a/fpga_interchange/fpga_interchange.cpp +++ b/fpga_interchange/fpga_interchange.cpp @@ -478,6 +478,8 @@ struct ModuleReader { LogicalNetlist::Netlist::Cell::Reader cell; LogicalNetlist::Netlist::CellDeclaration::Reader cell_decl; + std::unordered_map net_indicies; + std::unordered_map disconnected_nets; std::unordered_map> connections; ModuleReader(const LogicalNetlistImpl *root, @@ -502,6 +504,7 @@ struct NetReader { const ModuleReader * module; size_t net_idx; + LogicalNetlist::Netlist::PropertyMap::Reader property_map; std::vector scratch; }; @@ -559,12 +562,19 @@ struct LogicalNetlistImpl template void foreach_netname(const ModuleReader &mod, TFunc Func) const { - auto nets = mod.cell.getNets(); - for(size_t net_idx = 0; net_idx < nets.size(); ++net_idx) { - NetReader net_reader(&mod, net_idx); - auto net = nets[net_idx]; + // std::unordered_map net_indicies; + for(auto net_pair : mod.net_indicies) { + NetReader net_reader(&mod, net_pair.first); + auto net = net_pair.second; + net_reader.property_map = net.getPropMap(); Func(strings.at(net.getName()), net_reader); } + + // std::unordered_map disconnected_nets; + for(auto net_pair : mod.disconnected_nets) { + NetReader net_reader(&mod, net_pair.first); + Func(net_pair.second, net_reader); + } } PortType get_port_type_for_direction(LogicalNetlist::Netlist::Direction dir) const { @@ -639,8 +649,7 @@ struct LogicalNetlistImpl } template void foreach_attr(const NetReader &net_reader, TFunc Func) const { - auto net = net_reader.module->cell.getNets()[net_reader.net_idx]; - foreach_prop_map(net.getPropMap(), Func); + foreach_prop_map(net_reader.property_map, Func); } template void foreach_param(const CellReader &cell_reader, TFunc Func) const @@ -734,6 +743,10 @@ ModuleReader::ModuleReader(const LogicalNetlistImpl *root, cell = root->root.getCellList()[cell_inst.getCell()]; cell_decl = root->root.getCellDecls()[cell.getIndex()]; + // Auto-assign all ports to a net index, and then re-assign based on the + // nets. + int net_idx = 2; + auto ports = root->root.getPortList(); for(auto port_idx : cell_decl.getPorts()) { auto port = ports[port_idx]; @@ -744,7 +757,10 @@ ModuleReader::ModuleReader(const LogicalNetlistImpl *root, NPNR_ASSERT(result.second); std::vector & port_connections = result.first->second; - port_connections.resize(port_width, -1); + port_connections.resize(port_width); + for(size_t i = 0; i < port_width; ++i) { + port_connections[i] = net_idx++; + } } for(auto inst_idx : cell.getInsts()) { @@ -762,13 +778,17 @@ ModuleReader::ModuleReader(const LogicalNetlistImpl *root, size_t port_width = get_port_width(inst_port); std::vector & port_connections = result.first->second; - port_connections.resize(port_width, -1); + port_connections.resize(port_width); + for(size_t i = 0; i < port_width; ++i) { + port_connections[i] = net_idx++; + } } } auto nets = cell.getNets(); - for(size_t net_idx = 0; net_idx < nets.size(); ++net_idx) { - auto net = nets[net_idx]; + for(size_t i = 0; i < nets.size(); ++i, ++net_idx) { + auto net = nets[i]; + net_indicies[net_idx] = net; for(auto port_inst : net.getPortInsts()) { int32_t inst_idx = -1; @@ -786,6 +806,25 @@ ModuleReader::ModuleReader(const LogicalNetlistImpl *root, } } } + + for(const auto & port_connections : connections) { + for(size_t i = 0; i < port_connections.second.size(); ++i) { + int32_t net_idx = port_connections.second[i]; + + auto iter = net_indicies.find(net_idx); + if(iter == net_indicies.end()) { + PortKey port_key = port_connections.first; + auto port = ports[port_key.port_idx]; + if(port_key.inst_idx != -1 && port.getDir() != LogicalNetlist::Netlist::Direction::OUTPUT) { + log_error("Cell instance %s port %s is disconnected!\n", + root->strings.at(root->root.getInstList()[port_key.inst_idx].getName()).c_str(), + root->strings.at(ports[port_key.port_idx].getName()).c_str() + ); + } + disconnected_nets[net_idx] = stringf("%s.%d", root->strings.at(port.getName()).c_str(), i); + } + } + } } void FpgaInterchange::read_logical_netlist(Context * ctx, const std::string &filename) { diff --git a/fpga_interchange/main.cc b/fpga_interchange/main.cc index 48b07584..ca9b1704 100644 --- a/fpga_interchange/main.cc +++ b/fpga_interchange/main.cc @@ -21,6 +21,8 @@ #ifdef MAIN_EXECUTABLE #include +#include + #include "command.h" #include "design_utils.h" #include "jsonwrite.h" @@ -67,6 +69,7 @@ void FpgaInterchangeCommandHandler::customBitstream(Context *ctx) std::unique_ptr FpgaInterchangeCommandHandler::createContext(std::unordered_map &values) { + auto start = std::chrono::high_resolution_clock::now(); ArchArgs chipArgs; if (!vm.count("chipdb")) { log_error("chip database binary must be provided\n"); @@ -88,6 +91,9 @@ std::unique_ptr FpgaInterchangeCommandHandler::createContext(std::unord } } + auto end = std::chrono::high_resolution_clock::now(); + log_info("createContext time %.02fs\n", std::chrono::duration(end - start).count()); + return ctx; }