aboutsummaryrefslogtreecommitdiffstats
path: root/frontend
diff options
context:
space:
mode:
authorDavid Shah <dave@ds0.me>2019-11-14 20:13:57 +0000
committerDavid Shah <dave@ds0.me>2019-12-27 10:44:30 +0000
commit98f93f39be7385179036e565fdf9e51eafbce173 (patch)
tree7c07b00d0871e6cf30517918125e025cdb82ab9e /frontend
parentbed053251eece5a45e32eebc958fd5f3c683a9c1 (diff)
downloadnextpnr-98f93f39be7385179036e565fdf9e51eafbce173.tar.gz
nextpnr-98f93f39be7385179036e565fdf9e51eafbce173.tar.bz2
nextpnr-98f93f39be7385179036e565fdf9e51eafbce173.zip
frontend/base: Functions for hierarchical submodule cell import
Signed-off-by: David Shah <dave@ds0.me>
Diffstat (limited to 'frontend')
-rw-r--r--frontend/frontend_base.h121
1 files changed, 76 insertions, 45 deletions
diff --git a/frontend/frontend_base.h b/frontend/frontend_base.h
index beb0e31a..dbf4b4bc 100644
--- a/frontend/frontend_base.h
+++ b/frontend/frontend_base.h
@@ -128,6 +128,7 @@ template <typename FrontendType> struct GenericFrontend
using bitvector_t = typename FrontendType::BitVectorDataType;
std::unordered_map<IdString, ModuleInfo> mods;
+ std::unordered_map<IdString, const mod_dat_t&> mod_refs;
IdString top;
// Process the list of modules and determine
@@ -137,6 +138,7 @@ template <typename FrontendType> struct GenericFrontend
impl.foreach_module([&](const std::string &name, const mod_dat_t &mod) {
IdString mod_id = ctx->id(name);
auto &mi = mods[mod_id];
+ mod_refs[mod_id] = mod;
impl.foreach_attr(mod, [&](const std::string &name, const Property &value) {
if (name == "top")
mi.is_top = (value.intval != 0);
@@ -354,75 +356,104 @@ template <typename FrontendType> struct GenericFrontend
});
}
- void create_constant_net(HierModuleState &m, const std::string name_hint, char constval)
- {
+ void create_constant_net(HierModuleState &m, const std::string name_hint, char constval) {
IdString name = unique_name(m.base, name_hint);
NetInfo *ni = ctx->createNet(name);
add_constant_driver(m, ni, constval);
}
// Import a leaf cell - (white|black)box
- void import_leaf_cell(HierModuleState &m, const std::string &name, const cell_dat_t &cd)
- {
+ void import_leaf_cell(HierModuleState &m, const std::string &name, const cell_dat_t &cd) {
IdString inst_name = unique_name(m.base, name, false);
CellInfo *ci = ctx->createCell(inst_name, ctx->id(get_cell_type(cd)));
// Import port directions
std::unordered_map<IdString, PortType> port_dirs;
- impl.foreach_port_dir(cd, [&](const std::string &port, PortType dir) { port_dirs[ctx->id(port)] = dir; });
+ impl.foreach_port_dir(cd, [&](const std::string &port, PortType dir) {
+ port_dirs[ctx->id(port)] = dir;
+ });
// Import port connectivity
impl.foreach_port_conn(cd, [&](const std::string &name, const bitvector_t &bits) {
- if (!port_dirs.count(ctx->id(name)))
- log_error("Failed to get direction for port '%s' of cell '%s'\n", name.c_str(), inst_name.c_str(ctx));
- PortType dir = port_dirs.at(ctx->id(name));
+ if (!port_dirs.count(ctx->id(name)))
+ log_error("Failed to get direction for port '%s' of cell '%s'\n", name.c_str(), inst_name.c_str(ctx));
+ PortType dir = port_dirs.at(ctx->id(name));
+ int width = impl.get_vector_length(bits);
+ for (int i = 0; i < width; i++) {
+ std::string port_bit_name = get_bit_name(name, i, width);
+ IdString port_bit_ids = ctx->id(port_bit_name);
+ // Create cell port
+ ci->ports[port_bit_ids].name = port_bit_ids;
+ ci->ports[port_bit_ids].type = dir;
+ // Resolve connectivity
+ NetInfo *net;
+ if (impl.is_vector_bit_constant(bits, i)) {
+ // Create a constant driver if one is needed
+ net = create_constant_net(m, name + "." + port_bit_name + "$const", impl.get_vector_bit_constval(bits, i));
+ } else {
+ // Otherwise, lookup (creating if needed) the net with this index
+ net = create_or_get_net(m, impl.get_vector_bit_signal(bits, i));
+ }
+ NPNR_ASSERT(net != nullptr);
+
+ // Check for multiple drivers
+ if (dir == PORT_OUT && net->driver.cell != nullptr)
+ log_error("Net '%s' is multiply driven by cell ports %s.%s and %s.%s\n", ctx->nameOf(net),
+ ctx->nameOf(net->driver.cell), ctx->nameOf(net->driver.port), ctx->nameOf(inst_name), port_bit_name.c_str());
+ connect_port(ctx, net, ci, port_bit_ids);
+ }
+ });
+ // Import attributes and parameters
+ impl.foreach_attr(cd, [&](const std::string &name, const Property &value) {
+ ci->attrs[ctx->id(name)] = value;
+ });
+ impl.foreach_param(cd, [&](const std::string &name, const Property &value) {
+ ci->params[ctx->id(name)] = value;
+ });
+ }
+
+ // Import a submodule cell
+ void import_submodule_cell(HierModuleState &m, const std::string &name, const cell_dat_t &cd) {
+ HierModuleState submod;
+ submod.is_toplevel = false;
+ // Create mapping from submodule port to nets (referenced by index in flatindex)
+ impl.foreach_port_conn(cd, [&](const std::string &name, const bitvector_t &bits) {
int width = impl.get_vector_length(bits);
for (int i = 0; i < width; i++) {
- std::string port_bit_name = get_bit_name(name, i, width);
- IdString port_bit_ids = ctx->id(port_bit_name);
- // Create cell port
- ci->ports[port_bit_ids].name = port_bit_ids;
- ci->ports[port_bit_ids].type = dir;
- // Resolve connectivity
- NetInfo *net;
+ // Index of port net in flatindex
+ int net_ref = -1;
if (impl.is_vector_bit_constant(bits, i)) {
// Create a constant driver if one is needed
- net = create_constant_net(m, name + "." + port_bit_name + "$const",
- impl.get_vector_bit_constval(bits, i));
+ std::string port_bit_name = get_bit_name(name, i, width);
+ NetInfo *cnet = create_constant_net(m, name + "." + port_bit_name + "$const", impl.get_vector_bit_constval(bits, i));
+ cnet->udata = int(net_flatindex.size());
+ net_flatindex.push_back(cnet);
+ net_ref = cnet->udata;
} else {
- // Otherwise, lookup (creating if needed) the net with this index
- net = create_or_get_net(m, impl.get_vector_bit_signal(bits, i));
+ // Otherwise, lookup (creating if needed) the net with given in-module index
+ net_ref = create_or_get_net(m, impl.get_vector_bit_signal(bits, i))->udata;
}
- NPNR_ASSERT(net != nullptr);
-
- // Check for multiple drivers
- if (dir == PORT_OUT && net->driver.cell != nullptr)
- log_error("Net '%s' is multiply driven by cell ports %s.%s and %s.%s\n", ctx->nameOf(net),
- ctx->nameOf(net->driver.cell), ctx->nameOf(net->driver.port), ctx->nameOf(inst_name),
- port_bit_name.c_str());
- connect_port(ctx, net, ci, port_bit_ids);
+ NPNR_ASSERT(net_ref != -1);
+ submod.port_to_bus[ctx->id(name)].push_back(net_ref);
}
});
- // Import attributes and parameters
- impl.foreach_attr(cd,
- [&](const std::string &name, const Property &value) { ci->attrs[ctx->id(name)] = value; });
- impl.foreach_param(cd,
- [&](const std::string &name, const Property &value) { ci->params[ctx->id(name)] = value; });
+ // Create prefix for submodule
+ submod.prefix = m.prefix;
+ submod.prefix += name;
+ submod.prefix += '.';
+ // Do the submodule import
+ import_module(submod, mod_refs.at(ctx->id(impl.get_cell_type(cd))));
}
- // Import a submodule cell
- void import_submodule_cell(HierModuleState &m, const std::string &name, const cell_dat_t &cd) {}
-
// Import the cells section of a module
- void import_module_cells(HierModuleState &m, const mod_dat_t &data)
- {
+ void import_module_cells(HierModuleState &m, const mod_dat_t &data) {
m.foreach_cell(data, [&](const std::string &cellname, const cell_dat_t &cd) {
- IdString type = ctx->id(get_cell_type(cd));
- if (mods.count(type) && !mods.at(type).is_box()) {
- // Module type is known; and not boxed. Import as a submodule by flattening hierarchy
- import_submodule_cell(m, cellname, cd);
- } else {
- // Module type is unknown or boxes. Import as a leaf cell (nextpnr CellInfo)
- import_leaf_cell(m, cellname, cd);
- }
+ IdString type = ctx->id(get_cell_type(cd));
+ if (mods.count(type) && !mods.at(type).is_box()) {
+ // Module type is known; and not boxed. Import as a submodule by flattening hierarchy
+ import_submodule_cell(m, cellname, cd);
+ } else {
+ // Module type is unknown or boxes. Import as a leaf cell (nextpnr CellInfo)
+ import_leaf_cell(m, cellname, cd);
+ }
});
}