diff options
author | David Shah <dave@ds0.me> | 2019-09-13 19:01:26 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2019-09-13 19:01:26 +0100 |
commit | bc6b47efe097b5086fd6aaf4fb8be51d97435719 (patch) | |
tree | d3d88bd0f0ce92817504754ac8670c107e2db417 | |
parent | 3975424ff544406915a9e995ef14a0b060b30661 (diff) | |
parent | 95540763b972bc389b76000397d4e210d59fa4bf (diff) | |
download | nextpnr-bc6b47efe097b5086fd6aaf4fb8be51d97435719.tar.gz nextpnr-bc6b47efe097b5086fd6aaf4fb8be51d97435719.tar.bz2 nextpnr-bc6b47efe097b5086fd6aaf4fb8be51d97435719.zip |
Merge pull request #329 from YosysHQ/dave/net_aliases
json: Add support for net aliases
-rw-r--r-- | common/nextpnr.cc | 4 | ||||
-rw-r--r-- | common/nextpnr.h | 5 | ||||
-rw-r--r-- | ecp5/arch_pybindings.cc | 5 | ||||
-rw-r--r-- | ice40/arch_pybindings.cc | 5 | ||||
-rw-r--r-- | json/jsonparse.cc | 32 |
5 files changed, 44 insertions, 7 deletions
diff --git a/common/nextpnr.cc b/common/nextpnr.cc index ab4601a6..d73c0c02 100644 --- a/common/nextpnr.cc +++ b/common/nextpnr.cc @@ -474,10 +474,10 @@ void BaseCtx::addClock(IdString net, float freq) cc->period = getCtx()->getDelayFromNS(1000 / freq); cc->high = getCtx()->getDelayFromNS(500 / freq); cc->low = getCtx()->getDelayFromNS(500 / freq); - if (!nets.count(net)) { + if (!net_aliases.count(net)) { log_warning("net '%s' does not exist in design, ignoring clock constraint\n", net.c_str(this)); } else { - nets.at(net)->clkconstr = std::move(cc); + getNetByAlias(net)->clkconstr = std::move(cc); log_info("constraining clock net '%s' to %.02f MHz\n", net.c_str(this), freq); } } diff --git a/common/nextpnr.h b/common/nextpnr.h index 177048bf..4f9f7f23 100644 --- a/common/nextpnr.h +++ b/common/nextpnr.h @@ -609,6 +609,9 @@ struct BaseCtx std::unordered_map<IdString, std::unique_ptr<NetInfo>> nets; std::unordered_map<IdString, std::unique_ptr<CellInfo>> cells; + // Aliases for nets, which may have more than one name due to assignments and hierarchy + std::unordered_map<IdString, IdString> net_aliases; + // Top-level ports std::unordered_map<IdString, PortInfo> ports; @@ -738,6 +741,8 @@ struct BaseCtx TimingConstrObjectId timingCellObject(CellInfo *cell); TimingConstrObjectId timingPortObject(CellInfo *cell, IdString port); + NetInfo *getNetByAlias(IdString alias) const { return nets.at(net_aliases.at(alias)).get(); } + void addConstraint(std::unique_ptr<TimingConstraint> constr); void removeConstraint(IdString constrName); diff --git a/ecp5/arch_pybindings.cc b/ecp5/arch_pybindings.cc index 18d21112..275956f3 100644 --- a/ecp5/arch_pybindings.cc +++ b/ecp5/arch_pybindings.cc @@ -125,12 +125,17 @@ void arch_wrap_python() typedef std::unordered_map<IdString, std::unique_ptr<CellInfo>> CellMap; typedef std::unordered_map<IdString, std::unique_ptr<NetInfo>> NetMap; + typedef std::unordered_map<IdString, IdString> AliasMap; readonly_wrapper<Context, decltype(&Context::cells), &Context::cells, wrap_context<CellMap &>>::def_wrap(ctx_cls, "cells"); readonly_wrapper<Context, decltype(&Context::nets), &Context::nets, wrap_context<NetMap &>>::def_wrap(ctx_cls, "nets"); + readonly_wrapper<Context, decltype(&Context::net_aliases), &Context::net_aliases, + wrap_context<AliasMap &>>::def_wrap(ctx_cls, "net_aliases"); + fn_wrapper_1a<Context, decltype(&Context::getNetByAlias), &Context::getNetByAlias, deref_and_wrap<NetInfo>, + conv_from_str<IdString>>::def_wrap(ctx_cls, "getNetByAlias"); fn_wrapper_2a_v<Context, decltype(&Context::addClock), &Context::addClock, conv_from_str<IdString>, pass_through<float>>::def_wrap(ctx_cls, "addClock"); fn_wrapper_5a_v<Context, decltype(&Context::createRectangularRegion), &Context::createRectangularRegion, diff --git a/ice40/arch_pybindings.cc b/ice40/arch_pybindings.cc index bc0bfb84..194d7c6d 100644 --- a/ice40/arch_pybindings.cc +++ b/ice40/arch_pybindings.cc @@ -136,12 +136,17 @@ void arch_wrap_python() typedef std::unordered_map<IdString, std::unique_ptr<CellInfo>> CellMap; typedef std::unordered_map<IdString, std::unique_ptr<NetInfo>> NetMap; + typedef std::unordered_map<IdString, IdString> AliasMap; readonly_wrapper<Context, decltype(&Context::cells), &Context::cells, wrap_context<CellMap &>>::def_wrap(ctx_cls, "cells"); readonly_wrapper<Context, decltype(&Context::nets), &Context::nets, wrap_context<NetMap &>>::def_wrap(ctx_cls, "nets"); + readonly_wrapper<Context, decltype(&Context::net_aliases), &Context::net_aliases, + wrap_context<AliasMap &>>::def_wrap(ctx_cls, "net_aliases"); + fn_wrapper_1a<Context, decltype(&Context::getNetByAlias), &Context::getNetByAlias, deref_and_wrap<NetInfo>, + conv_from_str<IdString>>::def_wrap(ctx_cls, "getNetByAlias"); fn_wrapper_2a_v<Context, decltype(&Context::addClock), &Context::addClock, conv_from_str<IdString>, pass_through<float>>::def_wrap(ctx_cls, "addClock"); fn_wrapper_5a_v<Context, decltype(&Context::createRectangularRegion), &Context::createRectangularRegion, diff --git a/json/jsonparse.cc b/json/jsonparse.cc index ad21daf2..fb712b28 100644 --- a/json/jsonparse.cc +++ b/json/jsonparse.cc @@ -805,7 +805,7 @@ void json_import(Context *ctx, string modname, JsonNode *node) }; // Import netnames - std::vector<std::string> netlabels; + std::vector<std::vector<std::string>> netlabels; if (node->data_dict.count("netnames")) { JsonNode *cell_parent = node->data_dict.at("netnames"); for (int nnid = 0; nnid < GetSize(cell_parent->data_dict_keys); nnid++) { @@ -838,15 +838,26 @@ void json_import(Context *ctx, string modname, JsonNode *node) ndx = start_offset + num_bits - i - 1; std::string name = basename + (num_bits == 1 ? "" : std::string("[") + std::to_string(ndx) + std::string("]")); - if (prefer_netlabel(name, netlabels.at(netid))) - netlabels.at(netid) = name; + netlabels.at(netid).push_back(name); } } } } std::vector<IdString> netids; - std::transform(netlabels.begin(), netlabels.end(), std::back_inserter(netids), - [ctx](const std::string &s) { return ctx->id(s); }); + for (size_t i = 0; i < netlabels.size(); i++) { + auto &labels = netlabels.at(i); + if (labels.empty()) { + // Backup for unnamed nets (not sure if these should actually happen) + netids.push_back(ctx->id("$nextpnr$unknown_netname$" + std::to_string(i))); + } else { + // Pick a primary name for the net according to a simple heuristic + std::string pref = labels.at(0); + for (size_t j = 1; j < labels.size(); j++) + if (prefer_netlabel(labels.at(j), pref)) + pref = labels.at(j); + netids.push_back(ctx->id(pref)); + } + } if (node->data_dict.count("cells")) { JsonNode *cell_parent = node->data_dict.at("cells"); // @@ -921,6 +932,17 @@ void json_import(Context *ctx, string modname, JsonNode *node) } } } + // Import net aliases + for (size_t i = 0; i < netids.size(); i++) { + IdString netname = netids.at(i); + if (!ctx->nets.count(netname)) + continue; + for (auto &label : netlabels.at(i)) { + IdString labelid = ctx->id(label); + NPNR_ASSERT(!ctx->net_aliases.count(labelid)); + ctx->net_aliases[labelid] = netname; + } + } check_all_nets_driven(ctx); ctx->settings[ctx->id("synth")] = 1; } |