diff --git a/common/place_sa.cc b/common/place_sa.cc index 22e750c2..61f9f748 100644 --- a/common/place_sa.cc +++ b/common/place_sa.cc @@ -72,33 +72,58 @@ static int random_int_between(rnd_state &rnd, int a, int b) // Initial random placement static void place_initial(Design *design, CellInfo *cell, rnd_state &rnd) { - BelId best_bel = BelId(); - float best_score = std::numeric_limits::infinity(); - Chip &chip = design->chip; - if (cell->bel != BelId()) { - chip.unbindBel(cell->bel); - cell->bel = BelId(); - } - BelType targetType = belTypeFromId(cell->type); - for (auto bel : chip.getBels()) { - if (chip.getBelType(bel) == targetType && chip.checkBelAvail(bel) && - isValidBelForCell(design, cell, bel)) { - float score = random_float_upto(rnd, 1.0); - if (score <= best_score) { - best_score = score; - best_bel = bel; + bool all_placed = false; + int iters = 25; + while(!all_placed) { + BelId best_bel = BelId(); + float best_score = std::numeric_limits::infinity(), best_ripup_score = std::numeric_limits::infinity(); + Chip &chip = design->chip; + CellInfo *ripup_target = nullptr; + BelId ripup_bel = BelId(); + if (cell->bel != BelId()) { + chip.unbindBel(cell->bel); + cell->bel = BelId(); + } + BelType targetType = belTypeFromId(cell->type); + for (auto bel : chip.getBels()) { + if (chip.getBelType(bel) == targetType && isValidBelForCell(design, cell, bel)) { + if (chip.checkBelAvail(bel)) { + float score = random_float_upto(rnd, 1.0); + if (score <= best_score) { + best_score = score; + best_bel = bel; + } + } else { + float score = random_float_upto(rnd, 1.0); + if (score <= best_ripup_score) { + best_ripup_score = score; + ripup_target = design->cells.at(chip.getBelCell(bel, true)); + ripup_bel = bel; + } + + } + } } - } - if (best_bel == BelId()) { - log_error("failed to place cell '%s' of type '%s'\n", - cell->name.c_str(), cell->type.c_str()); - } - cell->bel = best_bel; - chip.bindBel(cell->bel, cell->name); + if (best_bel == BelId()) { + if (iters == 0 || ripup_bel == BelId()) + log_error("failed to place cell '%s' of type '%s'\n", + cell->name.c_str(), cell->type.c_str()); + --iters; + chip.unbindBel(ripup_target->bel); + ripup_target->bel = BelId(); + best_bel = ripup_bel; + } else { + all_placed = true; + } + cell->bel = best_bel; + chip.bindBel(cell->bel, cell->name); + + // Back annotate location + cell->attrs["BEL"] = chip.getBelName(cell->bel).str(); + cell = ripup_target; + } - // Back annotate location - cell->attrs["BEL"] = chip.getBelName(cell->bel).str(); } // Stores the state of the SA placer diff --git a/ice40/arch_place.cc b/ice40/arch_place.cc index 1c6361a1..276a9378 100644 --- a/ice40/arch_place.cc +++ b/ice40/arch_place.cc @@ -38,7 +38,8 @@ static bool logicCellsCompatible(const std::vector &cells) { bool dffs_exist = false, dffs_neg = false; const NetInfo *cen = nullptr, *clk = nullptr, *sr = nullptr; - std::unordered_set locals; + static std::unordered_set locals; + locals.clear(); for (auto cell : cells) { if (bool_or_default(cell->params, "DFF_ENABLE")) { diff --git a/ice40/pack.cc b/ice40/pack.cc index 0b76f3f3..6840d8d1 100644 --- a/ice40/pack.cc +++ b/ice40/pack.cc @@ -279,7 +279,9 @@ static void pack_io(Design *design) static void insert_global(Design *design, NetInfo *net, bool is_reset, bool is_cen) { - CellInfo *gb = create_ice_cell(design, "SB_GB"); + std::string glb_name = net->name.str() + std::string("_$glb_") + + (is_reset ? "sr" : (is_cen ? "ce" : "clk")); + CellInfo *gb = create_ice_cell(design, "SB_GB", "$gbuf_" + glb_name); gb->ports["USER_SIGNAL_TO_GLOBAL_BUFFER"].net = net; PortRef pr; pr.cell = gb; @@ -289,8 +291,7 @@ 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() + std::string("_glb_") + - (is_reset ? "sr" : (is_cen ? "ce" : "clk")); + glbnet->name = glb_name; glbnet->driver = pr; design->nets[glbnet->name] = glbnet; gb->ports["GLOBAL_BUFFER_OUTPUT"].net = glbnet; @@ -363,19 +364,22 @@ static void promote_globals(Design *design) ++prom_resets; clock_count.erase(rstnet->name); reset_count.erase(rstnet->name); - + cen_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); + reset_count.erase(cennet->name); + cen_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); + reset_count.erase(clknet->name); + cen_count.erase(clknet->name); } else { break; }