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 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 clock_count; + std::unordered_map 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 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 &a, + const std::pair &b) { + return a.second < b.second; + }); + if (global_reset->second > 0) { + NetInfo *rstnet = design->nets[global_reset->first]; + insert_global(design, rstnet, true, false); } }