Skip to content

Commit

Permalink
Merge pull request verilog-to-routing#2337 from verilog-to-routing/pa…
Browse files Browse the repository at this point in the history
…r_router

This commit has a bunch of cleanups piggybacked onto the
baseline parallel router:

  * Use RRNodeId where possible
  * Remove dead code and docs left from breadth-first router
  * Fix nondeterminism in parallel tatum
  * Fix performance penalty from NetPinTimingInvalidator
  • Loading branch information
duck2 authored Aug 1, 2023
2 parents 9479f9d + 33e9014 commit f2783e2
Show file tree
Hide file tree
Showing 92 changed files with 3,215 additions and 1,817 deletions.
2 changes: 1 addition & 1 deletion abc/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
cmake_minimum_required(VERSION 3.3.0)
cmake_minimum_required(VERSION 3.3.0...3.13) # ! This line is edited to get rid of a CMake deprecation error

include(CMakeParseArguments)
include(CheckCCompilerFlag)
Expand Down
15 changes: 3 additions & 12 deletions doc/src/vpr/command_line_usage.rst
Original file line number Diff line number Diff line change
Expand Up @@ -1127,7 +1127,7 @@ VPR uses a negotiated congestion algorithm (based on Pathfinder) to perform rout

* ``delay_normalized_length_frequency`` like ``delay_normalized``, but scaled by routing resource length and scaled inversely by routing resource frequency.

**Default:** ``delay_normalized_length`` for the timing-driven router and ``demand_only`` for the breadth-first router
**Default:** ``delay_normalized_length``

.. option:: --bend_cost <float>

Expand Down Expand Up @@ -1172,22 +1172,13 @@ VPR uses a negotiated congestion algorithm (based on Pathfinder) to perform rout

This option attempts to verify the minimum by routing at successively lower channel widths until two consecutive routing failures are observed.

.. option:: --router_algorithm {breadth_first | timing_driven}
.. option:: --router_algorithm {parallel | timing_driven}

Selects which router algorithm to use.

.. warning::

The ``breadth_first`` router **should NOT be used to compare the run-time/quality** of alternate routing algorithms.

It is inferrior to the ``timing_driven`` router from a circuit speed (2x - 10x slower) and run-time perspective (takes 10-100x longer on the large benchmarks).
The ``breadth_first`` router is deprecated and may be removed in a future release.

The ``breadth_first`` router :cite:`betz_arch_cad` focuses solely on routing a design successfully, while the ``timing_driven`` router :cite:`betz_arch_cad,murray_air` focuses both on achieving a successful route and achieving good circuit speed.

The breadth-first router is capable of routing a design using slightly fewer tracks than the timing-driving router (typically 5% if the timing-driven router uses its default parameters.
This can be reduced to about 2% if the router parameters are set so the timing-driven router pays more attention to routability and less to area).
The designs produced by the timing-driven router are much faster, however, (2x - 10x) and it uses less CPU time to route.
The ``parallel`` router is experimental. (TODO: more explanation)

**Default:** ``timing_driven``

Expand Down
2 changes: 1 addition & 1 deletion libs/EXTERNAL/capnproto/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
cmake_minimum_required(VERSION 3.4)
cmake_minimum_required(VERSION 3.4...3.13) # ! This line is edited to get rid of a CMake deprecation error
project("Cap'n Proto Root" CXX)
add_subdirectory(c++)
2 changes: 1 addition & 1 deletion libs/EXTERNAL/capnproto/c++/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
cmake_minimum_required(VERSION 3.4)
cmake_minimum_required(VERSION 3.4...3.13) # ! This line is edited to get rid of a CMake deprecation error
project("Cap'n Proto" CXX)
set(VERSION 0.9.1)

Expand Down
4 changes: 2 additions & 2 deletions libs/EXTERNAL/libargparse/argparse_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -399,10 +399,10 @@ int main(
.show_in(argparse::ShowIn::HELP_ONLY);
route_grp.add_argument(args.router_algorithm, "--router_algorithm")
.help("Specifies the router algorithm to use.\n"
" * breadth_first: focuses solely on routability\n"
" * parallel: timing_driven with tricks to run on multiple cores (may be worse)\n"
" * timing driven: focuses on routability and circuit speed\n")
.default_value("timing_driven")
.choices({"breadth_first", "timing_driven"})
.choices({"parallel", "timing_driven"})
.show_in(argparse::ShowIn::HELP_ONLY);
route_grp.add_argument(args.min_incremental_reroute_fanout, "--min_incremental_reroute_fanout")
.help("The net fanout thershold above which nets will be re-routed incrementally.")
Expand Down
3 changes: 1 addition & 2 deletions libs/EXTERNAL/libtatum/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,7 @@ cmake_minimum_required(VERSION 3.16)

project("tatum")

# Parallel tatum gives non-deterministic results. Use serial by default until resolved
set(TATUM_EXECUTION_ENGINE "serial" CACHE STRING "Specify the framework for (potential) parallel execution")
set(TATUM_EXECUTION_ENGINE "auto" CACHE STRING "Specify the framework for (potential) parallel execution")
set_property(CACHE TATUM_EXECUTION_ENGINE PROPERTY STRINGS auto serial tbb)

list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake/modules")
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
#pragma once
#include <algorithm>

#ifdef TATUM_USE_TBB
#include <tbb/concurrent_vector.h>
#endif

#include "tatum/graph_walkers/TimingGraphWalker.hpp"
#include "tatum/TimingGraph.hpp"
#include "tatum/delay_calc/DelayCalculator.hpp"
Expand Down Expand Up @@ -431,9 +436,16 @@ class SerialIncrWalker : public TimingGraphWalker {
t_incr_traversal_update incr_arr_update_;
t_incr_traversal_update incr_req_update_;

//Set of invalidated edges, and bitset for membership
/** Set of invalidated edges, and bitset for membership.
* Use thread safe alternatives when TBB is on, since invalidate_edge_impl
* may be called concurrently */
#ifdef TATUM_USE_TBB
tbb::concurrent_vector<EdgeId> invalidated_edges_;
tatum::util::linear_map<EdgeId, size_t> edge_invalidated_;
#else
std::vector<EdgeId> invalidated_edges_;
tatum::util::linear_map<EdgeId,bool> edge_invalidated_;
tatum::util::linear_map<EdgeId, bool> edge_invalidated_;
#endif

//Nodes which have been modified during timing update, and bitset for membership
std::vector<NodeId> nodes_modified_;
Expand Down
14 changes: 8 additions & 6 deletions libs/EXTERNAL/libtatum/libtatum/tatum/util/tatum_strong_id.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -176,22 +176,24 @@ class StrongId {
//Default to the sentinel value
constexpr StrongId() : id_(sentinel) {}

//Only allow explict constructions from a raw Id (no automatic conversions)
explicit StrongId(T id) noexcept : id_(id) {}
//Only allow explicit constructions from a raw Id (no automatic conversions)
explicit constexpr StrongId(T id) noexcept : id_(id) {}

//Allow some explicit conversion to useful types

//Allow explicit conversion to bool (e.g. if(id))
explicit operator bool() const { return *this != INVALID(); }
explicit operator bool() const { return id_ != sentinel; }

/// @brief Another name for the bool cast
constexpr bool is_valid() const { return id_ != sentinel; }

//Allow explicit conversion to size_t (e.g. my_vector[size_t(strong_id)])
explicit operator std::size_t() const { return static_cast<std::size_t>(id_); }


//To enable hasing Ids
//To enable hashing Ids
friend std::hash<StrongId<tag,T,sentinel>>;

//To enable comparisions between Ids
//To enable comparisons between Ids
// Note that since these are templated functions we provide an empty set of template parameters
// after the function name (i.e. <>)
friend bool operator== <>(const StrongId<tag,T,sentinel>& lhs, const StrongId<tag,T,sentinel>& rhs);
Expand Down
2 changes: 1 addition & 1 deletion libs/librrgraph/src/base/check_rr_graph.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -608,7 +608,7 @@ static void check_rr_edge(const RRGraphView& rr_graph,
std::string msg = "Non-configurable BUFFER type switch must have only one driver. ";
msg += vtr::string_fmt(" Actual fan-in was %d (expected 1).\n", to_fanin);
msg += " Possible cause is complex block output pins connecting to:\n";
msg += " " + describe_rr_node(rr_graph, grid, rr_indexed_data, to_node, is_flat);
msg += " " + describe_rr_node(rr_graph, grid, rr_indexed_data, RRNodeId(to_node), is_flat);
VPR_FATAL_ERROR(VPR_ERROR_ROUTE, msg.c_str());
}
break;
Expand Down
15 changes: 9 additions & 6 deletions libs/librrgraph/src/base/rr_graph_fwd.h
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
#ifndef RR_GRAPH_OBJ_FWD_H
#define RR_GRAPH_OBJ_FWD_H

#include <cstdint>

#include "vtr_strong_id.h"

/***************************************************************
Expand All @@ -20,11 +23,11 @@ struct rr_switch_id_tag;
struct rr_segment_id_tag;
struct rc_index_tag;

typedef vtr::StrongId<rr_node_id_tag, unsigned int> RRNodeId;
typedef vtr::StrongId<rr_edge_id_tag, unsigned int> RREdgeId;
typedef vtr::StrongId<rr_indexed_data_id_tag, unsigned int> RRIndexedDataId;
typedef vtr::StrongId<rr_switch_id_tag, short> RRSwitchId;
typedef vtr::StrongId<rr_segment_id_tag, short> RRSegmentId;
typedef vtr::StrongId<rc_index_tag, short> NodeRCIndex;
typedef vtr::StrongId<rr_node_id_tag, uint32_t> RRNodeId;
typedef vtr::StrongId<rr_edge_id_tag, uint32_t> RREdgeId;
typedef vtr::StrongId<rr_indexed_data_id_tag, uint32_t> RRIndexedDataId;
typedef vtr::StrongId<rr_switch_id_tag, uint16_t> RRSwitchId;
typedef vtr::StrongId<rr_segment_id_tag, uint16_t> RRSegmentId;
typedef vtr::StrongId<rc_index_tag, uint16_t> NodeRCIndex;

#endif
37 changes: 18 additions & 19 deletions libs/librrgraph/src/utils/describe_rr_node.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,51 +4,50 @@
#include "physical_types_util.h"
#include "vtr_util.h"

/* TODO: This function should adapt RRNodeId */
std::string describe_rr_node(const RRGraphView& rr_graph,
const DeviceGrid& grid,
const vtr::vector<RRIndexedDataId, t_rr_indexed_data>& rr_indexed_data,
int inode,
RRNodeId inode,
bool is_flat) {

std::string msg = vtr::string_fmt("RR node: %d", inode);

if (rr_graph.node_type(RRNodeId(inode)) == CHANX || rr_graph.node_type(RRNodeId(inode)) == CHANY) {
auto cost_index = rr_graph.node_cost_index(RRNodeId(inode));
if (rr_graph.node_type(inode) == CHANX || rr_graph.node_type(inode) == CHANY) {
auto cost_index = rr_graph.node_cost_index(inode);

int seg_index = rr_indexed_data[cost_index].seg_index;
std::string rr_node_direction_string = rr_graph.node_direction_string(RRNodeId(inode));
std::string rr_node_direction_string = rr_graph.node_direction_string(inode);

if (seg_index < (int)rr_graph.num_rr_segments()) {
msg += vtr::string_fmt(" track: %d longline: %d",
rr_graph.node_track_num(RRNodeId(inode)),
rr_graph.node_track_num(inode),
rr_graph.rr_segments(RRSegmentId(seg_index)).longline);
} else {
msg += vtr::string_fmt(" track: %d seg_type: ILLEGAL_SEG_INDEX %d",
rr_graph.node_track_num(RRNodeId(inode)),
rr_graph.node_track_num(inode),
seg_index);
}
} else if (rr_graph.node_type(RRNodeId(inode)) == IPIN || rr_graph.node_type(RRNodeId(inode)) == OPIN) {
auto type = grid.get_physical_type({rr_graph.node_xlow(RRNodeId(inode)),
rr_graph.node_ylow(RRNodeId(inode)),
rr_graph.node_layer(RRNodeId(inode))});
} else if (rr_graph.node_type(inode) == IPIN || rr_graph.node_type(inode) == OPIN) {
auto type = grid.get_physical_type({rr_graph.node_xlow(inode),
rr_graph.node_ylow(inode),
rr_graph.node_layer(inode)});

std::string pin_name = block_type_pin_index_to_name(type, rr_graph.node_pin_num(RRNodeId(inode)), is_flat);
std::string pin_name = block_type_pin_index_to_name(type, rr_graph.node_pin_num(inode), is_flat);

msg += vtr::string_fmt(" pin: %d pin_name: %s",
rr_graph.node_pin_num(RRNodeId(inode)),
rr_graph.node_pin_num(inode),
pin_name.c_str());
} else {
VTR_ASSERT(rr_graph.node_type(RRNodeId(inode)) == SOURCE || rr_graph.node_type(RRNodeId(inode)) == SINK);
VTR_ASSERT(rr_graph.node_type(inode) == SOURCE || rr_graph.node_type(inode) == SINK);

msg += vtr::string_fmt(" class: %d", rr_graph.node_class_num(RRNodeId(inode)));
msg += vtr::string_fmt(" class: %d", rr_graph.node_class_num(inode));
}

msg += vtr::string_fmt(" capacity: %d", rr_graph.node_capacity(RRNodeId(inode)));
msg += vtr::string_fmt(" fan-in: %d", rr_graph.node_fan_in(RRNodeId(inode)));
msg += vtr::string_fmt(" fan-out: %d", rr_graph.num_edges(RRNodeId(inode)));
msg += vtr::string_fmt(" capacity: %d", rr_graph.node_capacity(inode));
msg += vtr::string_fmt(" fan-in: %d", rr_graph.node_fan_in(inode));
msg += vtr::string_fmt(" fan-out: %d", rr_graph.num_edges(inode));

msg += " " + rr_graph.node_coordinate_to_string(RRNodeId(inode));
msg += " " + rr_graph.node_coordinate_to_string(inode);

return msg;
}
2 changes: 1 addition & 1 deletion libs/librrgraph/src/utils/describe_rr_node.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
std::string describe_rr_node(const RRGraphView& rr_graph,
const DeviceGrid& grid,
const vtr::vector<RRIndexedDataId, t_rr_indexed_data>& rr_indexed_data,
int inode,
RRNodeId inode,
bool is_flat);

#endif
18 changes: 9 additions & 9 deletions libs/libvtrutil/src/vtr_range.h
Original file line number Diff line number Diff line change
Expand Up @@ -41,21 +41,21 @@ template<typename T>
class Range {
public:
///@brief constructor
Range(T b, T e)
constexpr Range(T b, T e)
: begin_(b)
, end_(e) {}
///@brief Return an iterator to the start of the range
T begin() { return begin_; }
constexpr T begin() { return begin_; }
///@brief Return an iterator to the end of the range
T end() { return end_; }
constexpr T end() { return end_; }
///@brief Return an iterator to the start of the range (immutable)
const T begin() const { return begin_; }
constexpr const T begin() const { return begin_; }
///@brief Return an iterator to the end of the range (immutable)
const T end() const { return end_; }
constexpr const T end() const { return end_; }
///@brief Return true if empty
bool empty() { return begin_ == end_; }
constexpr bool empty() { return begin_ == end_; }
///@brief Return the range size
size_t size() { return std::distance(begin_, end_); }
constexpr size_t size() { return std::distance(begin_, end_); }

private:
T begin_;
Expand All @@ -72,13 +72,13 @@ class Range {
* auto my_range = vtr::make_range(my_vec.begin(), my_vec.end());
*/
template<typename T>
auto make_range(T b, T e) { return Range<T>(b, e); }
constexpr auto make_range(T b, T e) { return Range<T>(b, e); }

/**
* @brief Creates a vtr::Range from a container
*/
template<typename Container>
auto make_range(const Container& c) { return make_range(std::begin(c), std::end(c)); }
inline auto make_range(const Container& c) { return make_range(std::begin(c), std::end(c)); }

} // namespace vtr

Expand Down
Loading

0 comments on commit f2783e2

Please sign in to comment.