aboutsummaryrefslogtreecommitdiffstats
path: root/ice40/pack.cc
diff options
context:
space:
mode:
authorDavid Shah <davey1576@gmail.com>2018-06-16 17:44:35 +0200
committerDavid Shah <davey1576@gmail.com>2018-06-16 17:44:35 +0200
commit1e6124309fb02824c43549e0861d4023fc5827d8 (patch)
tree9b60248aa76cb911fe6af0eca037113d1af986b6 /ice40/pack.cc
parentbb92dc09a8d3450a7d356edf0ac2e9971083cf2f (diff)
downloadnextpnr-1e6124309fb02824c43549e0861d4023fc5827d8.tar.gz
nextpnr-1e6124309fb02824c43549e0861d4023fc5827d8.tar.bz2
nextpnr-1e6124309fb02824c43549e0861d4023fc5827d8.zip
ice40: Proper global promotion
Signed-off-by: David Shah <davey1576@gmail.com>
Diffstat (limited to 'ice40/pack.cc')
-rw-r--r--ice40/pack.cc79
1 files changed, 57 insertions, 22 deletions
diff --git a/ice40/pack.cc b/ice40/pack.cc
index d88870e0..dde8ed57 100644
--- a/ice40/pack.cc
+++ b/ice40/pack.cc
@@ -289,13 +289,15 @@ static void insert_global(Design *design, NetInfo *net, bool is_reset,
pr.cell = gb;
pr.port = "GLOBAL_BUFFER_OUTPUT";
NetInfo *glbnet = new NetInfo();
- glbnet->name = net->name.str() + "_glb";
+ glbnet->name = net->name.str() + std::string("_glb_") +
+ (is_reset ? "sr" : (is_cen ? "ce" : "clk"));
glbnet->driver = pr;
design->nets[glbnet->name] = glbnet;
gb->ports["GLOBAL_BUFFER_OUTPUT"].net = glbnet;
std::vector<PortRef> keep_users;
for (auto user : net->users) {
- if (is_clock_port(user) || (is_reset && is_reset_port(user))) {
+ if (is_clock_port(user) || (is_reset && is_reset_port(user)) ||
+ (is_cen && is_enable_port(user))) {
user.cell->ports[user.port].net = glbnet;
glbnet->users.push_back(user);
} else {
@@ -311,39 +313,72 @@ static void promote_globals(Design *design)
{
log_info("Promoting globals..\n");
- std::unordered_map<IdString, int> clock_count;
- std::unordered_map<IdString, int> reset_count;
-
+ std::unordered_map<IdString, int> clock_count, reset_count, cen_count;
for (auto net : design->nets) {
NetInfo *ni = net.second;
if (ni->driver.cell != nullptr && !is_global_net(ni)) {
clock_count[net.first] = 0;
reset_count[net.first] = 0;
+ cen_count[net.first] = 0;
+
for (auto user : ni->users) {
if (is_clock_port(user))
clock_count[net.first]++;
if (is_reset_port(user))
reset_count[net.first]++;
+ if (is_enable_port(user))
+ cen_count[net.first]++;
}
}
}
- auto global_clock = std::max_element(clock_count.begin(), clock_count.end(),
- [](const std::pair<IdString, int> &a,
- const std::pair<IdString, int> &b) {
- return a.second < b.second;
- });
- if (global_clock->second > 0) {
- NetInfo *clknet = design->nets[global_clock->first];
- insert_global(design, clknet, false, false);
- }
- auto global_reset = std::max_element(reset_count.begin(), reset_count.end(),
- [](const std::pair<IdString, int> &a,
- const std::pair<IdString, int> &b) {
- return a.second < b.second;
- });
- if (global_reset->second > 0) {
- NetInfo *rstnet = design->nets[global_reset->first];
- insert_global(design, rstnet, true, false);
+ int prom_globals = 0, prom_resets = 0, prom_cens = 0;
+ int gbs_available = 8;
+ for (auto cell : design->cells)
+ if (is_gbuf(cell.second))
+ --gbs_available;
+ while (prom_globals < gbs_available) {
+ auto global_clock =
+ std::max_element(clock_count.begin(), clock_count.end(),
+ [](const std::pair<IdString, int> &a,
+ const std::pair<IdString, int> &b) {
+ return a.second < b.second;
+ });
+
+ auto global_reset =
+ std::max_element(reset_count.begin(), reset_count.end(),
+ [](const std::pair<IdString, int> &a,
+ const std::pair<IdString, int> &b) {
+ return a.second < b.second;
+ });
+ auto global_cen =
+ std::max_element(cen_count.begin(), cen_count.end(),
+ [](const std::pair<IdString, int> &a,
+ const std::pair<IdString, int> &b) {
+ return a.second < b.second;
+ });
+ if (global_reset->second > global_clock->second && prom_resets < 4) {
+ NetInfo *rstnet = design->nets[global_reset->first];
+ insert_global(design, rstnet, true, false);
+ ++prom_globals;
+ ++prom_resets;
+ clock_count.erase(rstnet->name);
+ reset_count.erase(rstnet->name);
+
+ } else if (global_cen->second > global_clock->second && prom_cens < 4) {
+ NetInfo *cennet = design->nets[global_cen->first];
+ insert_global(design, cennet, false, true);
+ ++prom_globals;
+ ++prom_cens;
+ cen_count.erase(cennet->name);
+ clock_count.erase(cennet->name);
+ } else if (global_clock->second != 0) {
+ NetInfo *clknet = design->nets[global_clock->first];
+ insert_global(design, clknet, false, false);
+ ++prom_globals;
+ clock_count.erase(clknet->name);
+ } else {
+ break;
+ }
}
}