From 02b50e346438e766cb53b52f8ef02e67a263b612 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Thu, 2 Mar 2023 21:33:32 -0800 Subject: [PATCH] [lib] now clock spine requires explicit definition of track type and direction when coordinate is vague --- .../src/base/clock_network.cpp | 61 ++++++++++++++++++- .../src/base/clock_network.h | 12 ++++ .../src/io/clock_network_xml_constants.h | 2 + .../src/io/read_xml_clock_network.cpp | 53 ++++++++++++++++ .../src/io/write_xml_clock_network.cpp | 4 ++ .../config/clk_arch_1clk_2layer.xml | 8 +-- 6 files changed, 133 insertions(+), 7 deletions(-) diff --git a/libs/libclkarchopenfpga/src/base/clock_network.cpp b/libs/libclkarchopenfpga/src/base/clock_network.cpp index 7f8e83908..cfdfed633 100644 --- a/libs/libclkarchopenfpga/src/base/clock_network.cpp +++ b/libs/libclkarchopenfpga/src/base/clock_network.cpp @@ -82,7 +82,10 @@ std::vector ClockNetwork::pins( ***********************************************************************/ t_rr_type ClockNetwork::spine_track_type(const ClockSpineId& spine_id) const { VTR_ASSERT(valid_spine_start_end_points(spine_id)); - if (spine_start_point(spine_id).y() == spine_end_point(spine_id).y()) { + if ((spine_start_point(spine_id).x() == spine_end_point(spine_id).x()) + && (spine_start_point(spine_id).y() == spine_end_point(spine_id).y())) { + return spine_track_types_[spine_id]; + } else if (spine_start_point(spine_id).y() == spine_end_point(spine_id).y()) { return CHANX; } return CHANY; @@ -91,12 +94,16 @@ t_rr_type ClockNetwork::spine_track_type(const ClockSpineId& spine_id) const { Direction ClockNetwork::spine_direction(const ClockSpineId& spine_id) const { VTR_ASSERT(valid_spine_start_end_points(spine_id)); if (spine_track_type(spine_id) == CHANX) { - if (spine_start_point(spine_id).x() < spine_end_point(spine_id).x()) { + if (spine_start_point(spine_id).x() == spine_end_point(spine_id).x()) { + return spine_directions_[spine_id]; + } else if (spine_start_point(spine_id).x() < spine_end_point(spine_id).x()) { return Direction::INC; } } else { VTR_ASSERT(spine_track_type(spine_id) == CHANY); - if (spine_start_point(spine_id).y() < spine_end_point(spine_id).y()) { + if (spine_start_point(spine_id).y() == spine_end_point(spine_id).y()) { + return spine_directions_[spine_id]; + } else if (spine_start_point(spine_id).y() < spine_end_point(spine_id).y()) { return Direction::INC; } } @@ -370,6 +377,8 @@ void ClockNetwork::reserve_spines(const size_t& num_spines) { spine_levels_.reserve(num_spines); spine_start_points_.reserve(num_spines); spine_end_points_.reserve(num_spines); + spine_directions_.reserve(num_spines); + spine_track_types_.reserve(num_spines); spine_switch_points_.reserve(num_spines); spine_switch_coords_.reserve(num_spines); spine_parents_.reserve(num_spines); @@ -444,6 +453,8 @@ ClockSpineId ClockNetwork::create_spine(const std::string& name) { spine_levels_.emplace_back(0); spine_start_points_.emplace_back(); spine_end_points_.emplace_back(); + spine_directions_.emplace_back(Direction::NUM_DIRECTIONS); + spine_track_types_.emplace_back(NUM_RR_TYPES); spine_switch_points_.emplace_back(); spine_switch_coords_.emplace_back(); spine_parents_.emplace_back(); @@ -484,6 +495,19 @@ void ClockNetwork::set_spine_end_point(const ClockSpineId& spine_id, spine_end_points_[spine_id] = coord; } +void ClockNetwork::set_spine_direction(const ClockSpineId& spine_id, + const Direction& dir) { + VTR_ASSERT(valid_spine_id(spine_id)); + spine_directions_[spine_id] = dir; +} + +void ClockNetwork::set_spine_track_type(const ClockSpineId& spine_id, + const t_rr_type& type) { + VTR_ASSERT(valid_spine_id(spine_id)); + spine_track_types_[spine_id] = type; +} + + void ClockNetwork::add_spine_switch_point(const ClockSpineId& spine_id, const ClockSpineId& drive_spine_id, const vtr::Point& coord) { @@ -542,6 +566,19 @@ bool ClockNetwork::validate_tree() const { spine_end_point(spine_id).y()); return false; } + /* Ensure valid track types */ + if (spine_track_type(spine_id) != spine_track_types_[spine_id]) { + VTR_LOG_ERROR( + "Spine '%s' has a mismatch between inferred track type '%s' against user-defined track type '%s'\n", + spine_name(spine_id).c_str(), rr_node_typename[spine_track_type(spine_id)], rr_node_typename[spine_track_types_[spine_id]]); + return false; + } + if (spine_direction(spine_id) != spine_directions_[spine_id]) { + VTR_LOG_ERROR( + "Spine '%s' has a mismatch between inferred direction '%s' against user-defined direction '%s'\n", + spine_name(spine_id).c_str(), DIRECTION_STRING[size_t(spine_direction(spine_id))], DIRECTION_STRING[size_t(spine_directions_[spine_id])]); + return false; + } /* parent spine and child spine should be in different track type */ ClockSpineId parent_spine = spine_parents_[spine_id]; if (valid_spine_id(parent_spine)) { @@ -577,6 +614,9 @@ bool ClockNetwork::link_tree(const ClockTreeId& tree_id) { if (!update_tree_depth(tree_id)) { return false; } + if (!update_spine_attributes(tree_id)) { + return false; + } return true; } @@ -618,6 +658,16 @@ bool ClockNetwork::update_tree_depth(const ClockTreeId& tree_id) { return true; } +bool ClockNetwork::update_spine_attributes(const ClockTreeId& tree_id) { + size_t depth = 0; + for (ClockSpineId spine_id : spines(tree_id)) { + spine_track_types_[spine_id] = spine_track_type(spine_id); + spine_directions_[spine_id] = spine_direction(spine_id); + } + return true; +} + + /************************************************************************ * Internal invalidators/validators ***********************************************************************/ @@ -665,4 +715,9 @@ bool ClockNetwork::valid_spine_start_end_points( return true; } +bool ClockNetwork::is_vague_coordinate(const ClockSpineId& spine_id) const { + return ((spine_start_point(spine_id).x() == spine_end_point(spine_id).x()) && + (spine_start_point(spine_id).y() == spine_end_point(spine_id).y())); +} + } // End of namespace openfpga diff --git a/libs/libclkarchopenfpga/src/base/clock_network.h b/libs/libclkarchopenfpga/src/base/clock_network.h index e77e2b56f..34ee8bf3c 100644 --- a/libs/libclkarchopenfpga/src/base/clock_network.h +++ b/libs/libclkarchopenfpga/src/base/clock_network.h @@ -163,6 +163,10 @@ class ClockNetwork { const vtr::Point& coord); void set_spine_end_point(const ClockSpineId& spine_id, const vtr::Point& coord); + void set_spine_direction(const ClockSpineId& spine_id, + const Direction& dir); + void set_spine_track_type(const ClockSpineId& spine_id, + const t_rr_type& type); void add_spine_switch_point(const ClockSpineId& spine_id, const ClockSpineId& drive_spine_id, const vtr::Point& coord); @@ -191,6 +195,10 @@ class ClockNetwork { * X-direction spine or a Y-direction spine. Diagonal spine is not supported! */ bool valid_spine_start_end_points(const ClockSpineId& spine_id) const; + /* Definition of a vague coordinate is that start_x == end_x && start_y == end_y + * In such situation, we need specific track type and direction to be provided by user + */ + bool is_vague_coordinate(const ClockSpineId& spine_id) const; /* Validate the internal data. Required to ensure clean data before usage. If * validation is successful, is_valid() will return true */ bool validate() const; @@ -209,6 +217,8 @@ class ClockNetwork { bool rec_update_spine_level(const ClockSpineId& spine_id); /* Require sort_tree_spines() to called before! */ bool update_tree_depth(const ClockTreeId& tree_id); + /* Infer track type and directions for each spine by their coordinates */ + bool update_spine_attributes(const ClockTreeId& tree_id); private: /* Internal data */ /* Basic information of each tree */ @@ -225,6 +235,8 @@ class ClockNetwork { vtr::vector spine_levels_; vtr::vector> spine_start_points_; vtr::vector> spine_end_points_; + vtr::vector spine_directions_; + vtr::vector spine_track_types_; vtr::vector> spine_switch_points_; vtr::vector>> spine_switch_coords_; vtr::vector spine_parents_; diff --git a/libs/libclkarchopenfpga/src/io/clock_network_xml_constants.h b/libs/libclkarchopenfpga/src/io/clock_network_xml_constants.h index 569fdde7a..db7216f2d 100644 --- a/libs/libclkarchopenfpga/src/io/clock_network_xml_constants.h +++ b/libs/libclkarchopenfpga/src/io/clock_network_xml_constants.h @@ -17,6 +17,8 @@ constexpr const char* XML_CLOCK_SPINE_ATTRIBUTE_START_X = "start_x"; constexpr const char* XML_CLOCK_SPINE_ATTRIBUTE_START_Y = "start_y"; constexpr const char* XML_CLOCK_SPINE_ATTRIBUTE_END_X = "end_x"; constexpr const char* XML_CLOCK_SPINE_ATTRIBUTE_END_Y = "end_y"; +constexpr const char* XML_CLOCK_SPINE_ATTRIBUTE_TYPE = "type"; +constexpr const char* XML_CLOCK_SPINE_ATTRIBUTE_DIRECTION = "direction"; constexpr const char* XML_CLOCK_SPINE_SWITCH_POINT_NODE_NAME = "switch_point"; constexpr const char* XML_CLOCK_SPINE_SWITCH_POINT_ATTRIBUTE_TAP = "tap"; constexpr const char* XML_CLOCK_SPINE_SWITCH_POINT_ATTRIBUTE_X = "x"; diff --git a/libs/libclkarchopenfpga/src/io/read_xml_clock_network.cpp b/libs/libclkarchopenfpga/src/io/read_xml_clock_network.cpp index 5db46c6dd..f5fd17abe 100644 --- a/libs/libclkarchopenfpga/src/io/read_xml_clock_network.cpp +++ b/libs/libclkarchopenfpga/src/io/read_xml_clock_network.cpp @@ -94,6 +94,37 @@ static void read_xml_clock_spine_switch_point( vtr::Point(tap_x, tap_y)); } +/******************************************************************** + * Convert string to the enumerate of model type + *******************************************************************/ +static t_rr_type string_to_track_type( + const std::string& type_string) { + for (size_t itype = 0; itype < NUM_RR_TYPES; ++itype) { + if (std::string(rr_node_typename[itype]) == type_string) { + return static_cast(itype); + } + } + + /* Reach here, we have an invalid value, error out */ + return NUM_RR_TYPES; +} + +/******************************************************************** + * Convert string to the enumerate of model type + *******************************************************************/ +static Direction string_to_direction( + const std::string& type_string) { + for (size_t itype = 0; itype < size_t(Direction::NUM_DIRECTIONS); ++itype) { + if (std::string(DIRECTION_STRING[itype]) == type_string) { + return static_cast(itype); + } + } + + /* Reach here, we have an invalid value, error out */ + return Direction::NUM_DIRECTIONS; +} + + /******************************************************************** * Parse XML codes of a to an object of ClockNetwork *******************************************************************/ @@ -139,6 +170,28 @@ static void read_xml_clock_spine(pugi::xml_node& xml_spine, .as_int(); clk_ntwk.set_spine_end_point(spine_id, vtr::Point(end_x, end_y)); + if (clk_ntwk.is_vague_coordinate(spine_id)) { + std::string track_type_name = + get_attribute(xml_spine, XML_CLOCK_SPINE_ATTRIBUTE_TYPE, loc_data) + .as_string(); + t_rr_type track_type = string_to_track_type(track_type_name); + if (CHANX != track_type && CHANY != track_type) { + archfpga_throw(loc_data.filename_c_str(), loc_data.line(xml_spine), + "Invalid track type! Expect '%s' or '%s'!\n", rr_node_typename[CHANX], rr_node_typename[CHANY]); + } + clk_ntwk.set_spine_track_type(spine_id, track_type); + + std::string direction_name = + get_attribute(xml_spine, XML_CLOCK_SPINE_ATTRIBUTE_DIRECTION, loc_data) + .as_string(); + Direction direction_type = string_to_direction(direction_name); + if (Direction::INC != direction_type && Direction::DEC != direction_type) { + archfpga_throw(loc_data.filename_c_str(), loc_data.line(xml_spine), + "Invalid direction type! Expect '%s' or '%s'!\n", DIRECTION_STRING[size_t(Direction::INC)], DIRECTION_STRING[size_t(Direction::DEC)]); + } + clk_ntwk.set_spine_direction(spine_id, direction_type); + } + for (pugi::xml_node xml_switch_point : xml_spine.children()) { /* Error out if the XML child has an invalid name! */ if (xml_switch_point.name() == diff --git a/libs/libclkarchopenfpga/src/io/write_xml_clock_network.cpp b/libs/libclkarchopenfpga/src/io/write_xml_clock_network.cpp index 6430bf43c..4fb6991cf 100644 --- a/libs/libclkarchopenfpga/src/io/write_xml_clock_network.cpp +++ b/libs/libclkarchopenfpga/src/io/write_xml_clock_network.cpp @@ -79,6 +79,10 @@ static int write_xml_clock_spine(std::fstream& fp, const ClockNetwork& clk_ntwk, vtr::Point end_coord = clk_ntwk.spine_end_point(spine_id); write_xml_attribute(fp, XML_CLOCK_SPINE_ATTRIBUTE_END_X, end_coord.x()); write_xml_attribute(fp, XML_CLOCK_SPINE_ATTRIBUTE_END_Y, end_coord.y()); + if (clk_ntwk.is_vague_coordinate(spine_id)) { + write_xml_attribute(fp, XML_CLOCK_SPINE_ATTRIBUTE_TYPE, rr_node_typename[clk_ntwk.spine_track_type(spine_id)]); + write_xml_attribute(fp, XML_CLOCK_SPINE_ATTRIBUTE_DIRECTION, DIRECTION_STRING[size_t(clk_ntwk.spine_direction(spine_id))]); + } fp << ">" << "\n"; diff --git a/openfpga_flow/tasks/basic_tests/clock_network/homo_1clock_2layer/config/clk_arch_1clk_2layer.xml b/openfpga_flow/tasks/basic_tests/clock_network/homo_1clock_2layer/config/clk_arch_1clk_2layer.xml index 330da638d..06f233957 100644 --- a/openfpga_flow/tasks/basic_tests/clock_network/homo_1clock_2layer/config/clk_arch_1clk_2layer.xml +++ b/openfpga_flow/tasks/basic_tests/clock_network/homo_1clock_2layer/config/clk_arch_1clk_2layer.xml @@ -6,10 +6,10 @@ - - - - + + + +