ice40: Proper global promotion
Signed-off-by: David Shah <davey1576@gmail.com>
This commit is contained in:
parent
bb92dc09a8
commit
1e6124309f
@ -105,12 +105,18 @@ bool isValidBelForCell(Design *design, CellInfo *cell, BelId bel)
|
||||
for (auto user : cell->ports.at("GLOBAL_BUFFER_OUTPUT").net->users) {
|
||||
if (is_reset_port(user))
|
||||
is_reset = true;
|
||||
if (is_enable_port(user))
|
||||
is_cen = true;
|
||||
}
|
||||
IdString glb_net = chip.getWireName(
|
||||
chip.getWireBelPin(bel, PIN_GLOBAL_BUFFER_OUTPUT));
|
||||
int glb_id = std::stoi(std::string("") + glb_net.str().back());
|
||||
if (is_reset)
|
||||
if (is_reset && is_cen)
|
||||
return false;
|
||||
else if (is_reset)
|
||||
return (glb_id % 2) == 0;
|
||||
else if (is_cen)
|
||||
return (glb_id % 2) == 1;
|
||||
else
|
||||
return true;
|
||||
} else {
|
||||
|
@ -196,7 +196,9 @@ bool is_clock_port(const PortRef &port)
|
||||
return false;
|
||||
if (is_ff(port.cell))
|
||||
return port.port == "C";
|
||||
if (is_ram(port.cell))
|
||||
if (port.cell->type == "ICESTORM_LC")
|
||||
return port.port == "CLK";
|
||||
if (is_ram(port.cell) || port.cell->type == "ICESTORM_RAM")
|
||||
return port.port == "RCLK" || port.port == "WCLK";
|
||||
return false;
|
||||
}
|
||||
@ -207,6 +209,19 @@ bool is_reset_port(const PortRef &port)
|
||||
return false;
|
||||
if (is_ff(port.cell))
|
||||
return port.port == "R" || port.port == "S";
|
||||
if (port.cell->type == "ICESTORM_LC")
|
||||
return port.port == "SR";
|
||||
return false;
|
||||
}
|
||||
|
||||
bool is_enable_port(const PortRef &port)
|
||||
{
|
||||
if (port.cell == nullptr)
|
||||
return false;
|
||||
if (is_ff(port.cell))
|
||||
return port.port == "E";
|
||||
if (port.cell->type == "ICESTORM_LC")
|
||||
return port.port == "CEN";
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -83,6 +83,9 @@ bool is_clock_port(const PortRef &port);
|
||||
// Return true if a port is a reset port
|
||||
bool is_reset_port(const PortRef &port);
|
||||
|
||||
// Return true if a port is a clock enable port
|
||||
bool is_enable_port(const PortRef &port);
|
||||
|
||||
NEXTPNR_NAMESPACE_END
|
||||
|
||||
#endif
|
||||
|
@ -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(),
|
||||
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;
|
||||
});
|
||||
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(),
|
||||
|
||||
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) {
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user