aboutsummaryrefslogtreecommitdiffstats
path: root/common
diff options
context:
space:
mode:
Diffstat (limited to 'common')
-rw-r--r--common/design_utils.cc24
-rw-r--r--common/design_utils.h3
-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.cc2
-rw-r--r--common/pybindings.h2
-rw-r--r--common/pycontainers.h2
-rw-r--r--common/route.cc4
-rw-r--r--common/util.h61
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