aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid Shah <davey1576@gmail.com>2018-06-16 17:09:41 +0200
committerDavid Shah <davey1576@gmail.com>2018-06-16 17:09:41 +0200
commitbb92dc09a8d3450a7d356edf0ac2e9971083cf2f (patch)
treeb57ea93eab5dee41bddc3921c464155a1fbed562
parentc4241db1177b6caf1d5c44d83d434136c16e3dd4 (diff)
downloadnextpnr-bb92dc09a8d3450a7d356edf0ac2e9971083cf2f.tar.gz
nextpnr-bb92dc09a8d3450a7d356edf0ac2e9971083cf2f.tar.bz2
nextpnr-bb92dc09a8d3450a7d356edf0ac2e9971083cf2f.zip
ice40: Promote reset signal
Signed-off-by: David Shah <davey1576@gmail.com>
-rw-r--r--common/place.cc11
-rw-r--r--ice40/arch_place.cc14
-rw-r--r--ice40/cells.cc20
-rw-r--r--ice40/cells.h6
-rw-r--r--ice40/pack.cc74
5 files changed, 89 insertions, 36 deletions
diff --git a/common/place.cc b/common/place.cc
index dfca313f..a6d3040f 100644
--- a/common/place.cc
+++ b/common/place.cc
@@ -122,7 +122,8 @@ static float get_wirelength(Chip *chip, NetInfo *net)
return 0;
consider_driver =
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)
return 0;
for (auto load : net->users) {
@@ -132,9 +133,11 @@ static float get_wirelength(Chip *chip, NetInfo *net)
int load_x = 0, load_y = 0;
if (load_cell->bel == BelId())
continue;
- //chip->estimatePosition(load_cell->bel, load_x, load_y);
- WireId user_wire = chip->getWireBelPin(load_cell->bel, portPinFromId(load.port));
- //wirelength += std::abs(load_x - driver_x) + std::abs(load_y - driver_y);
+ // chip->estimatePosition(load_cell->bel, load_x, load_y);
+ WireId user_wire =
+ 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);
}
return wirelength;
diff --git a/ice40/arch_place.cc b/ice40/arch_place.cc
index 492ed846..19c95816 100644
--- a/ice40/arch_place.cc
+++ b/ice40/arch_place.cc
@@ -99,6 +99,20 @@ bool isValidBelForCell(Design *design, CellInfo *cell, BelId bel)
return logicCellsCompatible(cells);
} else if (cell->type == "SB_IO") {
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 {
// TODO: IO cell clock checks
return true;
diff --git a/ice40/cells.cc b/ice40/cells.cc
index 61b24ce3..52356711 100644
--- a/ice40/cells.cc
+++ b/ice40/cells.cc
@@ -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)
{
return bool(net_driven_by(net, is_gbuf, "GLOBAL_BUFFER_OUTPUT"));
diff --git a/ice40/cells.h b/ice40/cells.h
index a2fa4c16..f1bc5d1f 100644
--- a/ice40/cells.h
+++ b/ice40/cells.h
@@ -77,6 +77,12 @@ void nxio_to_sb(CellInfo *nxio, CellInfo *sbio);
// Return true if a net is a global 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
#endif
diff --git a/ice40/pack.cc b/ice40/pack.cc
index e045c05c..d88870e0 100644
--- a/ice40/pack.cc
+++ b/ice40/pack.cc
@@ -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)
- 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;
+ CellInfo *gb = create_ice_cell(design, "SB_GB");
+ gb->ports["USER_SIGNAL_TO_GLOBAL_BUFFER"].net = net;
+ PortRef pr;
+ pr.cell = gb;
+ pr.port = "USER_SIGNAL_TO_GLOBAL_BUFFER";
+ net->users.push_back(pr);
+
+ 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)
@@ -293,13 +312,18 @@ 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;
+
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;
for (auto user : ni->users) {
if (is_clock_port(user))
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) {
NetInfo *clknet = design->nets[global_clock->first];
- CellInfo *gb = create_ice_cell(design, "SB_GB");
- gb->ports["USER_SIGNAL_TO_GLOBAL_BUFFER"].net = clknet;
- PortRef pr;
- pr.cell = gb;
- pr.port = "USER_SIGNAL_TO_GLOBAL_BUFFER";
- clknet->users.push_back(pr);
-
- pr.cell = gb;
- pr.port = "GLOBAL_BUFFER_OUTPUT";
- NetInfo *glbnet = new NetInfo();
- 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;
+ 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);
}
}