From dd7ea0ab6c696025d58bcee02014572b024b5df2 Mon Sep 17 00:00:00 2001 From: Lofty Date: Fri, 25 Oct 2024 14:00:14 +0100 Subject: [PATCH] qwp: remove --- kernel/constids.inc | 1 - passes/cmds/Makefile.inc | 1 - passes/cmds/qwp.cc | 871 --------------------------------------- 3 files changed, 873 deletions(-) delete mode 100644 passes/cmds/qwp.cc diff --git a/kernel/constids.inc b/kernel/constids.inc index 3052afb49e1..d1bbb8edaf6 100644 --- a/kernel/constids.inc +++ b/kernel/constids.inc @@ -154,7 +154,6 @@ X(PORTID) X(PRIORITY) X(PRIORITY_MASK) X(Q) -X(qwp_position) X(R) X(ram_block) X(ram_style) diff --git a/passes/cmds/Makefile.inc b/passes/cmds/Makefile.inc index b0b0eb19f66..af5451b8961 100644 --- a/passes/cmds/Makefile.inc +++ b/passes/cmds/Makefile.inc @@ -31,7 +31,6 @@ OBJS += passes/cmds/cover.o OBJS += passes/cmds/trace.o OBJS += passes/cmds/plugin.o OBJS += passes/cmds/check.o -OBJS += passes/cmds/qwp.o OBJS += passes/cmds/edgetypes.o OBJS += passes/cmds/portlist.o OBJS += passes/cmds/chformal.o diff --git a/passes/cmds/qwp.cc b/passes/cmds/qwp.cc deleted file mode 100644 index 2da61244110..00000000000 --- a/passes/cmds/qwp.cc +++ /dev/null @@ -1,871 +0,0 @@ -/* - * yosys -- Yosys Open SYnthesis Suite - * - * Copyright (C) 2012 Claire Xenia Wolf - * - * 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. - * - */ - -#include "kernel/yosys.h" -#include "kernel/sigtools.h" - -#undef LOG_MATRICES -#undef PYPLOT_EDGES - -USING_YOSYS_NAMESPACE -PRIVATE_NAMESPACE_BEGIN - -static uint32_t xorshift32_state; - -static double xorshift32() -{ - xorshift32_state ^= xorshift32_state << 13; - xorshift32_state ^= xorshift32_state >> 17; - xorshift32_state ^= xorshift32_state << 5; - return (xorshift32_state % 1000000) / 1e6; -} - -struct QwpConfig -{ - bool ltr; - bool alpha; - bool verbose; - double grid; - - std::ofstream dump_file; - - QwpConfig() { - ltr = false; - alpha = false; - verbose = false; - grid = 1.0 / 16; - } -}; - -struct QwpWorker -{ - QwpConfig &config; - Module *module; - char direction; - - struct Node { - Cell *cell; - bool tied, alt_tied; - - // pos = position in current direction - // alt_pos = position in the other direction - double pos, alt_pos; - - Node() { - cell = nullptr; - tied = false; - pos = xorshift32(); - alt_tied = false; - alt_pos = xorshift32(); - } - - void tie(double v) { - tied = true; - pos = v; - } - - void alt_tie(double v) { - alt_tied = true; - alt_pos = v; - } - - void swap_alt() { - std::swap(tied, alt_tied); - std::swap(pos, alt_pos); - } - - void proj_left(double midpos) { - cell = nullptr; - tie(pos > midpos ? midpos : pos); - } - - void proj_right(double midpos) { - cell = nullptr; - tie(pos < midpos ? midpos : pos); - } - }; - - vector nodes; - dict, double> edges; - dict cell_to_node; - - // worker state variables - double midpos; - double radius; - double alt_midpos; - double alt_radius; - - QwpWorker(QwpConfig &config, Module *module, char direction = 'x') : config(config), module(module), direction(direction) - { - log_assert(direction == 'x' || direction == 'y'); - } - - void load_module() - { - log_assert(direction == 'x'); - - SigMap sigmap(module); - dict> bits_to_nodes; - - if (config.ltr || config.alpha) - { - dict alpha_inputs, alpha_outputs; - - if (config.alpha) - { - dict alpha_order; - - for (auto wire : module->wires()) { - if (wire->port_input || wire->port_output) - alpha_order[wire->name.str()] = wire; - } - - alpha_order.sort(); - - for (auto &it : alpha_order) { - if (it.second->port_input) { - int idx = GetSize(alpha_inputs); - alpha_inputs[it.second] = idx + 0.5; - } - if (it.second->port_output) { - int idx = GetSize(alpha_outputs); - alpha_outputs[it.second] = idx + 0.5; - } - } - } - - for (auto wire : module->wires()) - { - if (!wire->port_input && !wire->port_output) - continue; - - int idx = GetSize(nodes); - nodes.push_back(Node()); - - if (config.ltr) { - if (wire->port_input) - nodes[idx].tie(0.0); - else - nodes[idx].tie(1.0); - } - - if (config.alpha) { - if (wire->port_input) - nodes[idx].alt_tie(alpha_inputs.at(wire) / GetSize(alpha_inputs)); - else - nodes[idx].alt_tie(alpha_outputs.at(wire) / GetSize(alpha_outputs)); - } - - for (auto bit : sigmap(wire)) - bits_to_nodes[bit].insert(idx); - } - } - - for (auto cell : module->selected_cells()) - { - log_assert(cell_to_node.count(cell) == 0); - int idx = GetSize(nodes); - nodes.push_back(Node()); - - cell_to_node[cell] = GetSize(nodes); - nodes[idx].cell = cell; - - for (auto &conn : cell->connections()) - for (auto bit : sigmap(conn.second)) - bits_to_nodes[bit].insert(idx); - } - - for (auto &it : bits_to_nodes) - { - if (GetSize(it.second) > 100) - continue; - - for (int idx1 : it.second) - for (int idx2 : it.second) - if (idx1 < idx2) - edges[pair(idx1, idx2)] += 1.0 / GetSize(it.second); - } - } - - void solve(bool alt_mode = false) - { - // A := constraint_matrix - // y := constraint_rhs_vector - // - // AA = A' * A - // Ay = A' * y - // - // M := [AA Ay] - - if (config.verbose) - log("> System size: %d^2\n", GetSize(nodes)); - - // Row major order - int N = GetSize(nodes), N1 = N+1; - vector M(N * N1); - - if (config.verbose) - log("> Edge constraints: %d\n", GetSize(edges)); - - // Edge constraints: - // A[i,:] := [ 0 0 .... 0 weight 0 ... 0 -weight 0 ... 0 0], y[i] := 0 - // - // i.e. nonzero columns in A[i,:] at the two node indices. - for (auto &edge : edges) - { - int idx1 = edge.first.first; - int idx2 = edge.first.second; - double weight = edge.second * (1.0 + xorshift32() * 1e-3); - - M[idx1 + idx1*N1] += weight * weight; - M[idx2 + idx2*N1] += weight * weight; - - M[idx1 + idx2*N1] += -weight * weight; - M[idx2 + idx1*N1] += -weight * weight; - } - - if (config.verbose) - log("> Node constraints: %d\n", GetSize(nodes)); - - // Node constraints: - // A[i,:] := [ 0 0 .... 0 weight 0 ... 0 0], y[i] := weight * pos - // - // i.e. nonzero column in A[i,:] at the node index - // - // "tied" nodes have a large weight, pinning them in position. Untied - // nodes have a small weight, giving then a tiny preference to stay at - // the current position, making sure that AA never is singular. - for (int idx = 0; idx < GetSize(nodes); idx++) - { - auto &node = nodes[idx]; - double rhs = (alt_mode ? node.alt_pos : node.pos); - - double weight = 1e-3; - if (alt_mode ? node.alt_tied : node.tied) - weight = 1e3; - weight *= (1.0 + xorshift32() * 1e-3); - - M[idx + idx*N1] += weight * weight; - M[N + idx*N1] += rhs * weight * weight; - } - -#ifdef LOG_MATRICES - log("\n"); - for (int i = 0; i < N; i++) { - for (int j = 0; j < N+1; j++) - log(" %10.2e", M[(N+1)*i + j]); - log("\n"); - } -#endif - - if (config.verbose) - log("> Solving\n"); - - // Solve "AA*x = Ay" - // (least squares fit for "A*x = y") - // - // Using gaussian elimination to get M := [Id x] - - vector pivot_cache; - vector queue; - - for (int i = 0; i < N; i++) - queue.push_back(i); - - // gaussian elimination - for (int i = 0; i < N; i++) - { - if (config.verbose && N > 15 && ((i+1) % (N/15)) == 0) - log("> Solved %d%%: %d/%d\n", (100*(i+1))/N, i+1, N); - - // find best row - int best_row = queue.front(); - int best_row_queue_idx = 0; - double best_row_absval = 0; - - for (int k = 0; k < GetSize(queue); k++) { - int row = queue[k]; - double absval = fabs(M[i + row*N1]); - if (absval > best_row_absval) { - best_row = row; - best_row_queue_idx = k; - best_row_absval = absval; - } - } - - int row = best_row; - pivot_cache.push_back(row); - - queue[best_row_queue_idx] = queue.back(); - queue.pop_back(); - - // normalize row - for (int k = i+1; k < N1; k++) - M[k + row*N1] /= M[i + row*N1]; - M[i + row*N1] = 1.0; - - // elimination - for (int other_row : queue) { - double d = M[i + other_row*N1]; - for (int k = i+1; k < N1; k++) - M[k + other_row*N1] -= d*M[k + row*N1]; - M[i + other_row*N1] = 0.0; - } - } - - if (config.verbose) - log("> Solved\n"); - - log_assert(queue.empty()); - log_assert(GetSize(pivot_cache) == N); - - // back substitution - for (int i = N-1; i >= 0; i--) - for (int j = i+1; j < N; j++) - { - int row = pivot_cache[i]; - int other_row = pivot_cache[j]; - M[N + row*N1] -= M[j + row*N1] * M[N + other_row*N1]; - M[j + row*N1] = 0.0; - } - -#ifdef LOG_MATRICES - log("\n"); - for (int i = 0; i < N; i++) { - for (int j = 0; j < N+1; j++) - log(" %10.2e", M[(N+1)*i + j]); - log("\n"); - } -#endif - - if (config.verbose) - log("> Update nodes\n"); - - // update node positions - for (int i = 0; i < N; i++) - { - double v = M[(N+1)*i + N]; - double c = alt_mode ? alt_midpos : midpos; - double r = alt_mode ? alt_radius : radius; - - if (std::isfinite(v)) { - v = min(v, c+r); - v = max(v, c-r); - } else { - v = c; - } - - if (alt_mode) { - if (!nodes[i].alt_tied) - nodes[i].alt_pos = v; - } else { - if (!nodes[i].tied) - nodes[i].pos = v; - } - } - } - - void log_cell_coordinates(int indent, bool log_all_nodes = false) - { - for (auto &node : nodes) - { - if (node.cell == nullptr && !log_all_nodes) - continue; - - for (int i = 0; i < indent; i++) - log(" "); - - if (direction == 'x') - log("X=%.2f, Y=%.2f", node.pos, node.alt_pos); - else - log("X=%.2f, Y=%.2f", node.alt_pos, node.pos); - - if (node.tied) - log(" [%c-tied]", direction); - - if (node.alt_tied) - log(" [%c-tied]", direction == 'x' ? 'y' : 'x'); - - if (node.cell != nullptr) - log(" %s (%s)", log_id(node.cell), log_id(node.cell->type)); - else - log(" (none)"); - - log("\n"); - } - } - - void dump_svg(const pool *green_nodes = nullptr, double median = -1) - { - double x_center = direction == 'x' ? midpos : alt_midpos; - double y_center = direction == 'y' ? midpos : alt_midpos; - - double x_radius = direction == 'x' ? radius : alt_radius; - double y_radius = direction == 'y' ? radius : alt_radius; - - config.dump_file << stringf("\n"); - config.dump_file << stringf("\n"); - config.dump_file << stringf("\n"); - config.dump_file << stringf("\n"); - - double win_x = 250 + 200 * (direction == 'x' ? midpos - radius : alt_midpos - alt_radius); - double win_y = 20 + 200 * (direction == 'y' ? midpos - radius : alt_midpos - alt_radius); - - double win_w = 200 * (direction == 'x' ? 2*radius : 2*alt_radius); - double win_h = 200 * (direction == 'y' ? 2*radius : 2*alt_radius); - - config.dump_file << stringf("\n", win_x, win_y, win_w, win_h); - - if (median >= 0) - { - double x1 = 20.0, x2 = 220.0, y1 = 20.0, y2 = 220.0; - - if (direction == 'x') - x1 = x2 = 120 + 100 * (median - x_center) / x_radius; - else - y1 = y2 = 120 + 100 * (median - y_center) / y_radius; - - config.dump_file << stringf("\n", x1, y1, x2, y2); - } - - for (auto &edge : edges) - { - auto &node1 = nodes[edge.first.first]; - auto &node2 = nodes[edge.first.second]; - - double x1 = direction == 'x' ? node1.pos : node1.alt_pos; - double y1 = direction == 'y' ? node1.pos : node1.alt_pos; - - double x2 = direction == 'x' ? node2.pos : node2.alt_pos; - double y2 = direction == 'y' ? node2.pos : node2.alt_pos; - - x1 = 120 + 100 * (x1 - x_center) / x_radius; - y1 = 120 + 100 * (y1 - y_center) / y_radius; - - x2 = 120 + 100 * (x2 - x_center) / x_radius; - y2 = 120 + 100 * (y2 - y_center) / y_radius; - - config.dump_file << stringf("\n", x1, y1, x2, y2); - } - - for (int i = 0; i < GetSize(nodes); i++) - { - auto &node = nodes[i]; - - double x = direction == 'x' ? node.pos : node.alt_pos; - double y = direction == 'y' ? node.pos : node.alt_pos; - - x = 120 + 100 * (x - x_center) / x_radius; - y = 120 + 100 * (y - y_center) / y_radius; - - const char *color = node.cell == nullptr ? "blue" : "red"; - - if (green_nodes != nullptr && green_nodes->count(i)) - color = "green"; - - config.dump_file << stringf("\n", x, y, color); - } - - config.dump_file << stringf("\n"); - } - - void run_worker(int indent) - { - int count_cells = 0; - - for (auto &node : nodes) - if (node.cell != nullptr) - count_cells++; - - for (int i = 0; i < indent; i++) - log(" "); - - string range_str; - - if (direction == 'x') - range_str = stringf("X=%.2f:%.2f, Y=%.2f:%.2f", - midpos - radius, midpos + radius, - alt_midpos - alt_radius, alt_midpos + alt_radius); - else - range_str = stringf("X=%.2f:%.2f, Y=%.2f:%.2f", - alt_midpos - alt_radius, alt_midpos + alt_radius, - midpos - radius, midpos + radius); - - log("%c-qwp on %s with %d cells, %d nodes, and %d edges.\n", direction, - range_str.c_str(), count_cells, GetSize(nodes), GetSize(edges)); - - solve(); - solve(true); - - // detect median position and check for break condition - - vector> sorted_pos; - for (int i = 0; i < GetSize(nodes); i++) - if (nodes[i].cell != nullptr) - sorted_pos.push_back(pair(nodes[i].pos, i)); - - std::sort(sorted_pos.begin(), sorted_pos.end()); - int median_sidx = GetSize(sorted_pos)/2; - double median = sorted_pos[median_sidx].first; - - double left_scale = radius / (median - (midpos - radius)); - double right_scale = radius / ((midpos + radius) - median); - - if (config.dump_file.is_open()) - { - config.dump_file << stringf("

LSQ %c-Solution for %s:

\n", direction, range_str.c_str()); - - pool green_nodes; - for (int i = 0; i < median_sidx; i++) - green_nodes.insert(sorted_pos[i].second); - - dump_svg(&green_nodes, median); - } - - for (auto &node : nodes) - { - double rel_pos = node.pos - median; - if (rel_pos < 0) { - node.pos = midpos + left_scale*rel_pos; - if (std::isfinite(node.pos)) { - node.pos = min(node.pos, midpos); - node.pos = max(node.pos, midpos - radius); - } else - node.pos = midpos - radius/2; - } else { - node.pos = midpos + right_scale*rel_pos; - if (std::isfinite(node.pos)) { - node.pos = max(node.pos, midpos); - node.pos = min(node.pos, midpos + radius); - } else - node.pos = midpos + radius/2; - } - } - - if (GetSize(sorted_pos) < 2 || (2*radius <= config.grid && 2*alt_radius <= config.grid)) { - log_cell_coordinates(indent + 1); - return; - } - - // create child workers - - char child_direction = direction == 'x' ? 'y' : 'x'; - - QwpWorker left_worker(config, module, child_direction); - QwpWorker right_worker(config, module, child_direction); - - // duplicate nodes into child workers - - dict left_nodes, right_nodes; - - for (int k = 0; k < GetSize(sorted_pos); k++) - { - int i = sorted_pos[k].second; - - if (k < median_sidx) { - left_nodes[i] = GetSize(left_worker.nodes); - left_worker.nodes.push_back(nodes[i]); - if (left_worker.nodes.back().pos > midpos) - left_worker.nodes.back().pos = midpos; - left_worker.nodes.back().swap_alt(); - } else { - right_nodes[i] = GetSize(right_worker.nodes); - right_worker.nodes.push_back(nodes[i]); - if (right_worker.nodes.back().pos < midpos) - right_worker.nodes.back().pos = midpos; - right_worker.nodes.back().swap_alt(); - } - } - - // duplicate edges into child workers, project nodes as needed - - for (auto &edge : edges) - { - int idx1 = edge.first.first; - int idx2 = edge.first.second; - double weight = edge.second; - - if (nodes[idx1].cell == nullptr && nodes[idx2].cell == nullptr) - continue; - - int left_idx1 = left_nodes.count(idx1) ? left_nodes.at(idx1) : -1; - int left_idx2 = left_nodes.count(idx2) ? left_nodes.at(idx2) : -1; - - int right_idx1 = right_nodes.count(idx1) ? right_nodes.at(idx1) : -1; - int right_idx2 = right_nodes.count(idx2) ? right_nodes.at(idx2) : -1; - - if (left_idx1 >= 0 && left_worker.nodes[left_idx1].cell && left_idx2 < 0) { - left_idx2 = left_nodes[idx2] = GetSize(left_worker.nodes); - left_worker.nodes.push_back(nodes[idx2]); - left_worker.nodes.back().proj_left(midpos); - left_worker.nodes.back().swap_alt(); - } else - if (left_idx2 >= 0 && left_worker.nodes[left_idx2].cell && left_idx1 < 0) { - left_idx1 = left_nodes[idx1] = GetSize(left_worker.nodes); - left_worker.nodes.push_back(nodes[idx1]); - left_worker.nodes.back().proj_left(midpos); - left_worker.nodes.back().swap_alt(); - } - - if (right_idx1 >= 0 && right_worker.nodes[right_idx1].cell && right_idx2 < 0) { - right_idx2 = right_nodes[idx2] = GetSize(right_worker.nodes); - right_worker.nodes.push_back(nodes[idx2]); - right_worker.nodes.back().proj_right(midpos); - right_worker.nodes.back().swap_alt(); - } else - if (right_idx2 >= 0 && right_worker.nodes[right_idx2].cell && right_idx1 < 0) { - right_idx1 = right_nodes[idx1] = GetSize(right_worker.nodes); - right_worker.nodes.push_back(nodes[idx1]); - right_worker.nodes.back().proj_right(midpos); - right_worker.nodes.back().swap_alt(); - } - - if (left_idx1 >= 0 && left_idx2 >= 0) - left_worker.edges[pair(left_idx1, left_idx2)] += weight; - - if (right_idx1 >= 0 && right_idx2 >= 0) - right_worker.edges[pair(right_idx1, right_idx2)] += weight; - } - - // run child workers - - left_worker.midpos = right_worker.midpos = alt_midpos; - left_worker.radius = right_worker.radius = alt_radius; - - left_worker.alt_midpos = midpos - radius/2; - right_worker.alt_midpos = midpos + radius/2; - left_worker.alt_radius = right_worker.alt_radius = radius/2; - - left_worker.run_worker(indent+1); - right_worker.run_worker(indent+1); - - // re-integrate results - - for (auto &it : left_nodes) - if (left_worker.nodes[it.second].cell != nullptr) { - nodes[it.first].pos = left_worker.nodes[it.second].alt_pos; - nodes[it.first].alt_pos = left_worker.nodes[it.second].pos; - } - - for (auto &it : right_nodes) - if (right_worker.nodes[it.second].cell != nullptr) { - nodes[it.first].pos = right_worker.nodes[it.second].alt_pos; - nodes[it.first].alt_pos = right_worker.nodes[it.second].pos; - } - - if (config.dump_file.is_open()) { - config.dump_file << stringf("

Final %c-Solution for %s:

\n", direction, range_str.c_str()); - dump_svg(); - } - } - - void histogram(const vector &values) - { - if (values.empty()) { - log("no data\n"); - return; - } - - double min_value = values.front(); - double max_value = values.front(); - - for (auto &v : values) { - min_value = min(min_value, v); - max_value = max(max_value, v); - } - - if (fabs(max_value - min_value) < 0.001) { - log("all values in range %f .. %f\n", min_value, max_value); - return; - } - - vector buckets(60); - int max_bucket_val = 0; - - for (auto &v : values) { - int idx = min(int(GetSize(buckets) * (v - min_value) / (max_value - min_value)), GetSize(buckets)-1); - max_bucket_val = max(max_bucket_val, ++buckets.at(idx)); - } - - for (int i = 4; i >= 0; i--) { - for (int k = 0; k < GetSize(buckets); k++) { - int v = 10 * buckets[k] / max_bucket_val; - if (v >= 2*i+1) - log(v == 2*i+1 ? "." : ":"); - else - log(i == 0 ? (buckets[k] > 0 ? "," : "_") : " "); - } - log("\n"); - } - log("%-30f%30f\n", min_value, max_value); - } - - void run() - { - log("\n"); - log("Running qwp on module %s..\n", log_id(module)); - - if (config.dump_file.is_open()) - config.dump_file << stringf("

QWP protocol for module %s:

\n", log_id(module)); - - load_module(); - - midpos = 0.5; - radius = 0.5; - alt_midpos = 0.5; - alt_radius = 0.5; - run_worker(1); - - for (auto &node : nodes) - if (node.cell != nullptr) - node.cell->attributes[ID::qwp_position] = stringf("%f %f", node.pos, node.alt_pos); - - vector edge_lengths; - vector weighted_edge_lengths; - - double total_edge_length = 0; - double total_weighted_edge_length = 0; - - for (auto &edge : edges) - { - auto &node1 = nodes[edge.first.first]; - auto &node2 = nodes[edge.first.second]; - - double distance = sqrt(pow(node1.pos - node2.pos, 2) + pow(node1.alt_pos - node2.alt_pos, 2)); - double weighted_distance = distance * edge.second; - - edge_lengths.push_back(distance); - weighted_edge_lengths.push_back(weighted_distance); - - total_edge_length += distance; - total_weighted_edge_length += weighted_distance; - } - - log("\n"); - log("Summary for module %s:\n", log_id(module)); - log("Number of edges: %d\n", GetSize(edges)); - log("Total edge length: %f\n", total_edge_length); - log("Total weighted edge length: %f\n", total_weighted_edge_length); - - log("\n"); - log("Histogram over edge lengths:\n"); - histogram(edge_lengths); - - log("\n"); - log("Histogram over weighted edge lengths:\n"); - histogram(weighted_edge_lengths); - } -}; - -struct QwpPass : public Pass { - QwpPass() : Pass("qwp", "quadratic wirelength placer") { } - void help() override - { - // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| - log("\n"); - log(" qwp [options] [selection]\n"); - log("\n"); - log("This command runs quadratic wirelength placement on the selected modules and\n"); - log("annotates the cells in the design with 'qwp_position' attributes.\n"); - log("\n"); - log(" -ltr\n"); - log(" Add left-to-right constraints: constrain all inputs on the left border\n"); - log(" outputs to the right border.\n"); - log("\n"); - log(" -alpha\n"); - log(" Add constraints for inputs/outputs to be placed in alphanumerical\n"); - log(" order along the y-axis (top-to-bottom).\n"); - log("\n"); - log(" -grid N\n"); - log(" Number of grid divisions in x- and y-direction. (default=16)\n"); - log("\n"); - log(" -dump \n"); - log(" Dump a protocol of the placement algorithm to the html file.\n"); - log("\n"); - log(" -v\n"); - log(" Verbose solver output for profiling or debugging\n"); - log("\n"); - log("Note: This implementation of a quadratic wirelength placer uses exact\n"); - log("dense matrix operations. It is only a toy-placer for small circuits.\n"); - log("\n"); - } - void execute(std::vector args, RTLIL::Design *design) override - { - QwpConfig config; - xorshift32_state = 123456789; - - log_header(design, "Executing QWP pass (quadratic wirelength placer).\n"); - - size_t argidx; - for (argidx = 1; argidx < args.size(); argidx++) { - if (args[argidx] == "-ltr") { - config.ltr = true; - continue; - } - if (args[argidx] == "-alpha") { - config.alpha = true; - continue; - } - if (args[argidx] == "-v") { - config.verbose = true; - continue; - } - if (args[argidx] == "-grid" && argidx+1 < args.size()) { - config.grid = 1.0 / atoi(args[++argidx].c_str()); - continue; - } - if (args[argidx] == "-dump" && argidx+1 < args.size()) { - config.dump_file.open(args[++argidx], std::ofstream::trunc); - yosys_output_files.insert(args[argidx]); - continue; - } - break; - } - extra_args(args, argidx, design); - - for (auto module : design->selected_modules()) - { - QwpWorker worker(config, module); - worker.run(); - -#ifdef PYPLOT_EDGES - log("\n"); - log("plt.figure(figsize=(10, 10));\n"); - - for (auto &edge : worker.edges) { - log("plt.plot([%.2f, %.2f], [%.2f, %.2f], \"r-\");\n", - worker.nodes[edge.first.first].pos, - worker.nodes[edge.first.second].pos, - worker.nodes[edge.first.first].alt_pos, - worker.nodes[edge.first.second].alt_pos); - } - - for (auto &node : worker.nodes) { - const char *style = node.cell != nullptr ? "ko" : "ks"; - log("plt.plot([%.2f], [%.2f], \"%s\");\n", node.pos, node.alt_pos, style); - } -#endif - } - } -} QwpPass; - -PRIVATE_NAMESPACE_END