diff options
Diffstat (limited to 'common')
-rw-r--r-- | common/design_utils.cc | 24 | ||||
-rw-r--r-- | common/design_utils.h | 3 | ||||
-rw-r--r-- | common/place_sa.cc (renamed from common/place.cc) | 70 | ||||
-rw-r--r-- | common/place_sa.h (renamed from common/place.h) | 0 | ||||
-rw-r--r-- | common/pybindings.cc | 2 | ||||
-rw-r--r-- | common/pybindings.h | 2 | ||||
-rw-r--r-- | common/pycontainers.h | 2 | ||||
-rw-r--r-- | common/route.cc | 4 | ||||
-rw-r--r-- | common/util.h | 61 |
9 files changed, 144 insertions, 24 deletions
diff --git a/common/design_utils.cc b/common/design_utils.cc index 85895a75..ae6e21ed 100644 --- a/common/design_utils.cc +++ b/common/design_utils.cc @@ -2,6 +2,7 @@ * nextpnr -- Next Generation Place and Route * * Copyright (C) 2018 Clifford Wolf <clifford@clifford.at> + * Copyright (C) 2018 David Shah <david@symbioticeda.com> * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -18,7 +19,9 @@ */ #include "design_utils.h" - +#include <map> +#include "log.h" +#include "util.h" NEXTPNR_NAMESPACE_BEGIN void replace_port(CellInfo *old_cell, IdString old_name, CellInfo *rep_cell, @@ -49,4 +52,23 @@ void replace_port(CellInfo *old_cell, IdString old_name, CellInfo *rep_cell, } } +// Print utilisation of a design +void print_utilisation(const Design *design) +{ + // Sort by Bel type + std::map<BelType, int> used_types; + for (auto cell : design->cells) { + used_types[belTypeFromId(cell.second->type)]++; + } + std::map<BelType, int> available_types; + for (auto bel : design->chip.getBels()) { + available_types[design->chip.getBelType(bel)]++; + } + log("\nDesign utilisation:\n"); + for (auto type : available_types) { + log("\t%20s: %5d/%5d\n", belTypeToId(type.first).c_str(), + get_or_default(used_types, type.first, 0), type.second); + } +} + NEXTPNR_NAMESPACE_END diff --git a/common/design_utils.h b/common/design_utils.h index 8d231d4c..d640bf68 100644 --- a/common/design_utils.h +++ b/common/design_utils.h @@ -2,6 +2,7 @@ * nextpnr -- Next Generation Place and Route * * Copyright (C) 2018 Clifford Wolf <clifford@clifford.at> + * Copyright (C) 2018 David Shah <david@symbioticeda.com> * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -83,6 +84,8 @@ CellInfo *net_driven_by(const NetInfo *net, F1 cell_pred, IdString port) } } +void print_utilisation(const Design *design); + NEXTPNR_NAMESPACE_END #endif diff --git a/common/place.cc b/common/place_sa.cc index 55a4d021..22e750c2 100644 --- a/common/place.cc +++ b/common/place_sa.cc @@ -2,6 +2,10 @@ * nextpnr -- Next Generation Place and Route * * Copyright (C) 2018 Clifford Wolf <clifford@clifford.at> + * Copyright (C) 2018 David Shah <david@symbioticeda.com> + * + * Simulated annealing implementation based on arachne-pnr + * Copyright (C) 2015-2018 Cotton Seed * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -17,7 +21,7 @@ * */ -#include "place.h" +#include "place_sa.h" #include <algorithm> #include <cmath> #include <iostream> @@ -107,6 +111,7 @@ struct SAState int n_move, n_accept; int diameter = 35; std::vector<std::vector<std::vector<std::vector<BelId>>>> fast_bels; + std::unordered_set<BelId> locked_bels; }; // Get the total estimated wirelength for a net @@ -122,6 +127,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)); if (!consider_driver) return 0; for (auto load : net->users) { @@ -131,8 +138,12 @@ 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); - 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; } @@ -171,13 +182,17 @@ static bool try_swap_position(Design *design, CellInfo *cell, BelId newBel, } chip.bindBel(newBel, cell->name); + if (other != IdString()) { - if (!isValidBelForCell(design, other_cell, oldBel)) { - chip.unbindBel(newBel); - goto swap_fail; - } else { - chip.bindBel(oldBel, other_cell->name); - } + chip.bindBel(oldBel, other_cell->name); + } + + if (!isBelLocationValid(design, newBel) || + ((other != IdString() && !isBelLocationValid(design, oldBel)))) { + chip.unbindBel(newBel); + if (other != IdString()) + chip.unbindBel(oldBel); + goto swap_fail; } cell->bel = newBel; @@ -246,12 +261,17 @@ BelId random_bel_for_cell(Design *design, CellInfo *cell, SAState &state, const auto &fb = state.fast_bels.at(int(targetType)).at(nx).at(ny); if (fb.size() == 0) continue; - return fb.at(random_int_between(rnd, 0, fb.size())); + BelId bel = fb.at(random_int_between(rnd, 0, fb.size())); + if (state.locked_bels.find(bel) != state.locked_bels.end()) + continue; + return bel; } } void place_design_sa(Design *design) { + SAState state; + size_t total_cells = design->cells.size(), placed_cells = 0; std::queue<CellInfo *> visit_cells; // Initial constraints placer @@ -277,6 +297,7 @@ void place_design_sa(Design *design) cell->bel = bel; design->chip.bindBel(bel, cell->name); + state.locked_bels.insert(bel); placed_cells++; visit_cells.push(cell); } @@ -285,16 +306,19 @@ void place_design_sa(Design *design) rnd_state rnd; rnd.state = 1; std::vector<CellInfo *> autoplaced; - SAState state; - // Place cells randomly initially + // Sort to-place cells for deterministic initial placement for (auto cell : design->cells) { CellInfo *ci = cell.second; if (ci->bel == BelId()) { - place_initial(design, ci, rnd); autoplaced.push_back(cell.second); - placed_cells++; } - log_info("placed %d/%d\n", int(placed_cells), int(total_cells)); + } + std::sort(autoplaced.begin(), autoplaced.end(), + [](CellInfo *a, CellInfo *b) { return a->name < b->name; }); + // Place cells randomly initially + for (auto cell : autoplaced) { + place_initial(design, cell, rnd); + placed_cells++; } // Build up a fast position/type to Bel lookup table int max_x = 0, max_y = 0; @@ -330,9 +354,9 @@ void place_design_sa(Design *design) state.n_move = state.n_accept = 0; state.improved = false; - // if (iter % 50 == 0) - log(" at iteration #%d: temp = %f, wire length = %f\n", iter, - state.temp, state.curr_wirelength); + if (iter % 5 == 0) + log(" at iteration #%d: temp = %f, wire length = %f\n", iter, + state.temp, state.curr_wirelength); for (int m = 0; m < 15; ++m) { // Loop through all automatically placed cells @@ -382,6 +406,16 @@ void place_design_sa(Design *design) } } } + for (auto bel : design->chip.getBels()) { + if (!isBelLocationValid(design, bel)) { + std::string cell_text = "no cell"; + IdString cell = design->chip.getBelCell(bel, false); + if (cell != IdString()) + cell_text = std::string("cell '") + cell.str() + "'"; + log_error("post-placement validity check failed for Bel '%s' (%s)", + design->chip.getBelName(bel).c_str(), cell_text.c_str()); + } + } } NEXTPNR_NAMESPACE_END diff --git a/common/place.h b/common/place_sa.h index f320111e..f320111e 100644 --- a/common/place.h +++ b/common/place_sa.h diff --git a/common/pybindings.cc b/common/pybindings.cc index 10bbab7b..89f98716 100644 --- a/common/pybindings.cc +++ b/common/pybindings.cc @@ -2,7 +2,7 @@ * nextpnr -- Next Generation Place and Route * * Copyright (C) 2018 Clifford Wolf <clifford@clifford.at> - * Copyright (C) 2018 David Shah <dave@ds0.me> + * Copyright (C) 2018 David Shah <david@symbioticeda.com> * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above diff --git a/common/pybindings.h b/common/pybindings.h index de6aa4c7..7616c055 100644 --- a/common/pybindings.h +++ b/common/pybindings.h @@ -2,7 +2,7 @@ * nextpnr -- Next Generation Place and Route * * Copyright (C) 2018 Clifford Wolf <clifford@clifford.at> - * Copyright (C) 2018 David Shah <dave@ds0.me> + * Copyright (C) 2018 David Shah <david@symbioticeda.com> * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above diff --git a/common/pycontainers.h b/common/pycontainers.h index 992d0de9..9160dfb6 100644 --- a/common/pycontainers.h +++ b/common/pycontainers.h @@ -2,7 +2,7 @@ * nextpnr -- Next Generation Place and Route * * Copyright (C) 2018 Clifford Wolf <clifford@clifford.at> - * Copyright (C) 2018 David Shah <dave@ds0.me> + * Copyright (C) 2018 David Shah <david@symbioticeda.com> * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above diff --git a/common/route.cc b/common/route.cc index 247c8840..32212c7d 100644 --- a/common/route.cc +++ b/common/route.cc @@ -440,8 +440,8 @@ void route_design(Design *design, bool verbose) "routing.\n", int(netsQueue.size())); - ripup_pip_penalty *= 1.5; - ripup_wire_penalty *= 1.5; + ripup_pip_penalty += 5; + ripup_wire_penalty += 5; } } diff --git a/common/util.h b/common/util.h new file mode 100644 index 00000000..34b2ed02 --- /dev/null +++ b/common/util.h @@ -0,0 +1,61 @@ +/* + * nextpnr -- Next Generation Place and Route + * + * Copyright (C) 2018 David Shah <david@symbioticeda.com> + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + */ + +#ifndef UTIL_H +#define UTIL_H + +#include <string> +#include "nextpnr.h" + +NEXTPNR_NAMESPACE_BEGIN + +// Get a value from a map-style container, returning default if value is not +// found +template <typename Container, typename KeyType, typename ValueType> +ValueType get_or_default(const Container &ct, const KeyType &key, + ValueType def = ValueType()) +{ + auto found = ct.find(key); + if (found == ct.end()) + return def; + else + return found->second; +}; + +// Get a value from a map-style container, converting to int, and returning +// default if value is not found +template <typename Container, typename KeyType> +int int_or_default(const Container &ct, const KeyType &key, int def = 0) +{ + auto found = ct.find(key); + if (found == ct.end()) + return def; + else + return std::stoi(found->second); +}; + +// As above, but convert to bool +template <typename Container, typename KeyType> +bool bool_or_default(const Container &ct, const KeyType &key, bool def = false) +{ + return bool(int_or_default(ct, key, int(def))); +}; +NEXTPNR_NAMESPACE_END + +#endif |