ice40: Promote reset signal
Signed-off-by: David Shah <davey1576@gmail.com>
This commit is contained in:
parent
c4241db117
commit
bb92dc09a8
@ -122,7 +122,8 @@ static float get_wirelength(Chip *chip, NetInfo *net)
|
|||||||
return 0;
|
return 0;
|
||||||
consider_driver =
|
consider_driver =
|
||||||
chip->estimatePosition(driver_cell->bel, driver_x, driver_y);
|
chip->estimatePosition(driver_cell->bel, driver_x, driver_y);
|
||||||
WireId drv_wire = chip->getWireBelPin(driver_cell->bel, portPinFromId(net->driver.port));
|
WireId drv_wire = chip->getWireBelPin(driver_cell->bel,
|
||||||
|
portPinFromId(net->driver.port));
|
||||||
if (!consider_driver)
|
if (!consider_driver)
|
||||||
return 0;
|
return 0;
|
||||||
for (auto load : net->users) {
|
for (auto load : net->users) {
|
||||||
@ -132,9 +133,11 @@ static float get_wirelength(Chip *chip, NetInfo *net)
|
|||||||
int load_x = 0, load_y = 0;
|
int load_x = 0, load_y = 0;
|
||||||
if (load_cell->bel == BelId())
|
if (load_cell->bel == BelId())
|
||||||
continue;
|
continue;
|
||||||
//chip->estimatePosition(load_cell->bel, load_x, load_y);
|
// chip->estimatePosition(load_cell->bel, load_x, load_y);
|
||||||
WireId user_wire = chip->getWireBelPin(load_cell->bel, portPinFromId(load.port));
|
WireId user_wire =
|
||||||
//wirelength += std::abs(load_x - driver_x) + std::abs(load_y - driver_y);
|
chip->getWireBelPin(load_cell->bel, portPinFromId(load.port));
|
||||||
|
// wirelength += std::abs(load_x - driver_x) + std::abs(load_y -
|
||||||
|
// driver_y);
|
||||||
wirelength += chip->estimateDelay(drv_wire, user_wire);
|
wirelength += chip->estimateDelay(drv_wire, user_wire);
|
||||||
}
|
}
|
||||||
return wirelength;
|
return wirelength;
|
||||||
|
@ -99,6 +99,20 @@ bool isValidBelForCell(Design *design, CellInfo *cell, BelId bel)
|
|||||||
return logicCellsCompatible(cells);
|
return logicCellsCompatible(cells);
|
||||||
} else if (cell->type == "SB_IO") {
|
} else if (cell->type == "SB_IO") {
|
||||||
return design->chip.getBelPackagePin(bel) != "";
|
return design->chip.getBelPackagePin(bel) != "";
|
||||||
|
} else if (cell->type == "SB_GB") {
|
||||||
|
bool is_reset = false, is_cen = false;
|
||||||
|
assert(cell->ports.at("GLOBAL_BUFFER_OUTPUT").net != nullptr);
|
||||||
|
for (auto user : cell->ports.at("GLOBAL_BUFFER_OUTPUT").net->users) {
|
||||||
|
if (is_reset_port(user))
|
||||||
|
is_reset = 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)
|
||||||
|
return (glb_id % 2) == 0;
|
||||||
|
else
|
||||||
|
return true;
|
||||||
} else {
|
} else {
|
||||||
// TODO: IO cell clock checks
|
// TODO: IO cell clock checks
|
||||||
return true;
|
return true;
|
||||||
|
@ -190,6 +190,26 @@ void nxio_to_sb(CellInfo *nxio, CellInfo *sbio)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool is_clock_port(const PortRef &port)
|
||||||
|
{
|
||||||
|
if (port.cell == nullptr)
|
||||||
|
return false;
|
||||||
|
if (is_ff(port.cell))
|
||||||
|
return port.port == "C";
|
||||||
|
if (is_ram(port.cell))
|
||||||
|
return port.port == "RCLK" || port.port == "WCLK";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool is_reset_port(const PortRef &port)
|
||||||
|
{
|
||||||
|
if (port.cell == nullptr)
|
||||||
|
return false;
|
||||||
|
if (is_ff(port.cell))
|
||||||
|
return port.port == "R" || port.port == "S";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
bool is_global_net(const NetInfo *net)
|
bool is_global_net(const NetInfo *net)
|
||||||
{
|
{
|
||||||
return bool(net_driven_by(net, is_gbuf, "GLOBAL_BUFFER_OUTPUT"));
|
return bool(net_driven_by(net, is_gbuf, "GLOBAL_BUFFER_OUTPUT"));
|
||||||
|
@ -77,6 +77,12 @@ void nxio_to_sb(CellInfo *nxio, CellInfo *sbio);
|
|||||||
// Return true if a net is a global net
|
// Return true if a net is a global net
|
||||||
bool is_global_net(const NetInfo *net);
|
bool is_global_net(const NetInfo *net);
|
||||||
|
|
||||||
|
// Return true if a port is a clock port
|
||||||
|
bool is_clock_port(const PortRef &port);
|
||||||
|
|
||||||
|
// Return true if a port is a reset port
|
||||||
|
bool is_reset_port(const PortRef &port);
|
||||||
|
|
||||||
NEXTPNR_NAMESPACE_END
|
NEXTPNR_NAMESPACE_END
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -276,15 +276,34 @@ static void pack_io(Design *design)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool is_clock_port(const PortRef &port)
|
static void insert_global(Design *design, NetInfo *net, bool is_reset,
|
||||||
|
bool is_cen)
|
||||||
{
|
{
|
||||||
if (port.cell == nullptr)
|
CellInfo *gb = create_ice_cell(design, "SB_GB");
|
||||||
return false;
|
gb->ports["USER_SIGNAL_TO_GLOBAL_BUFFER"].net = net;
|
||||||
if (is_ff(port.cell))
|
PortRef pr;
|
||||||
return port.port == "C";
|
pr.cell = gb;
|
||||||
if (is_ram(port.cell))
|
pr.port = "USER_SIGNAL_TO_GLOBAL_BUFFER";
|
||||||
return port.port == "RCLK" || port.port == "WCLK";
|
net->users.push_back(pr);
|
||||||
return false;
|
|
||||||
|
pr.cell = gb;
|
||||||
|
pr.port = "GLOBAL_BUFFER_OUTPUT";
|
||||||
|
NetInfo *glbnet = new NetInfo();
|
||||||
|
glbnet->name = net->name.str() + "_glb";
|
||||||
|
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))) {
|
||||||
|
user.cell->ports[user.port].net = glbnet;
|
||||||
|
glbnet->users.push_back(user);
|
||||||
|
} else {
|
||||||
|
keep_users.push_back(user);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
net->users = keep_users;
|
||||||
|
design->cells[gb->name] = gb;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Simple global promoter (clock only)
|
// Simple global promoter (clock only)
|
||||||
@ -293,13 +312,18 @@ static void promote_globals(Design *design)
|
|||||||
log_info("Promoting globals..\n");
|
log_info("Promoting globals..\n");
|
||||||
|
|
||||||
std::unordered_map<IdString, int> clock_count;
|
std::unordered_map<IdString, int> clock_count;
|
||||||
|
std::unordered_map<IdString, int> reset_count;
|
||||||
|
|
||||||
for (auto net : design->nets) {
|
for (auto net : design->nets) {
|
||||||
NetInfo *ni = net.second;
|
NetInfo *ni = net.second;
|
||||||
if (ni->driver.cell != nullptr && !is_global_net(ni)) {
|
if (ni->driver.cell != nullptr && !is_global_net(ni)) {
|
||||||
clock_count[net.first] = 0;
|
clock_count[net.first] = 0;
|
||||||
|
reset_count[net.first] = 0;
|
||||||
for (auto user : ni->users) {
|
for (auto user : ni->users) {
|
||||||
if (is_clock_port(user))
|
if (is_clock_port(user))
|
||||||
clock_count[net.first]++;
|
clock_count[net.first]++;
|
||||||
|
if (is_reset_port(user))
|
||||||
|
reset_count[net.first]++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -310,30 +334,16 @@ static void promote_globals(Design *design)
|
|||||||
});
|
});
|
||||||
if (global_clock->second > 0) {
|
if (global_clock->second > 0) {
|
||||||
NetInfo *clknet = design->nets[global_clock->first];
|
NetInfo *clknet = design->nets[global_clock->first];
|
||||||
CellInfo *gb = create_ice_cell(design, "SB_GB");
|
insert_global(design, clknet, false, false);
|
||||||
gb->ports["USER_SIGNAL_TO_GLOBAL_BUFFER"].net = clknet;
|
}
|
||||||
PortRef pr;
|
auto global_reset = std::max_element(reset_count.begin(), reset_count.end(),
|
||||||
pr.cell = gb;
|
[](const std::pair<IdString, int> &a,
|
||||||
pr.port = "USER_SIGNAL_TO_GLOBAL_BUFFER";
|
const std::pair<IdString, int> &b) {
|
||||||
clknet->users.push_back(pr);
|
return a.second < b.second;
|
||||||
|
});
|
||||||
pr.cell = gb;
|
if (global_reset->second > 0) {
|
||||||
pr.port = "GLOBAL_BUFFER_OUTPUT";
|
NetInfo *rstnet = design->nets[global_reset->first];
|
||||||
NetInfo *glbnet = new NetInfo();
|
insert_global(design, rstnet, true, false);
|
||||||
glbnet->name = clknet->name.str() + "_glb";
|
|
||||||
glbnet->driver = pr;
|
|
||||||
design->nets[glbnet->name] = glbnet;
|
|
||||||
std::vector<PortRef> keep_users;
|
|
||||||
for (auto user : clknet->users) {
|
|
||||||
if (is_clock_port(user)) {
|
|
||||||
user.cell->ports[user.port].net = glbnet;
|
|
||||||
glbnet->users.push_back(user);
|
|
||||||
} else {
|
|
||||||
keep_users.push_back(user);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
clknet->users = keep_users;
|
|
||||||
design->cells[gb->name] = gb;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user