aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.gitignore4
-rw-r--r--fpga_interchange/arch.cc12
-rw-r--r--fpga_interchange/arch.h13
-rw-r--r--fpga_interchange/arch_pack_io.cc26
-rw-r--r--fpga_interchange/fpga_interchange.cpp59
-rw-r--r--fpga_interchange/main.cc6
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<ArchRanges>
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<ArchRanges>
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<CellInfo *> 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<IdString> 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<CellInfo *> 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<int32_t, LogicalNetlist::Netlist::Net::Reader> net_indicies;
+ std::unordered_map<int32_t, std::string> disconnected_nets;
std::unordered_map<PortKey, std::vector<int32_t>> 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<int32_t> scratch;
};
@@ -559,12 +562,19 @@ struct LogicalNetlistImpl
template <typename TFunc> 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<int32_t, LogicalNetlist::Netlist::Net::Reader> 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<int32_t, IdString> 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 <typename TFunc> 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 <typename TFunc> 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<int32_t> & 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<int32_t> & 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 <fstream>
+#include <chrono>
+
#include "command.h"
#include "design_utils.h"
#include "jsonwrite.h"
@@ -67,6 +69,7 @@ void FpgaInterchangeCommandHandler::customBitstream(Context *ctx)
std::unique_ptr<Context> FpgaInterchangeCommandHandler::createContext(std::unordered_map<std::string, Property> &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<Context> FpgaInterchangeCommandHandler::createContext(std::unord
}
}
+ auto end = std::chrono::high_resolution_clock::now();
+ log_info("createContext time %.02fs\n", std::chrono::duration<float>(end - start).count());
+
return ctx;
}