From 0c442f6238abf3e5df96693ac3ffd4ed4e0f04bf Mon Sep 17 00:00:00 2001 From: tangxifan Date: Mon, 24 Jun 2024 17:54:58 -0700 Subject: [PATCH] [lib] add syntax to support internal drivers in clock network parsers --- .../src/base/clock_network.cpp | 46 ++++++++++++++++++- .../src/base/clock_network.h | 21 ++++++++- .../src/base/clock_network_fwd.h | 2 + .../src/io/clock_network_xml_constants.h | 2 + .../src/io/read_xml_clock_network.cpp | 35 +++++++++++++- .../src/io/write_xml_clock_network.cpp | 20 ++++++-- 6 files changed, 119 insertions(+), 7 deletions(-) diff --git a/libs/libclkarchopenfpga/src/base/clock_network.cpp b/libs/libclkarchopenfpga/src/base/clock_network.cpp index c235bab7a..4972e303b 100644 --- a/libs/libclkarchopenfpga/src/base/clock_network.cpp +++ b/libs/libclkarchopenfpga/src/base/clock_network.cpp @@ -32,6 +32,10 @@ ClockNetwork::clock_tree_range ClockNetwork::trees() const { return vtr::make_range(tree_ids_.begin(), tree_ids_.end()); } +ClockNetwork::clock_internal_driver_range ClockNetwork::internal_drivers() const { + return vtr::make_range(internal_driver_ids_.begin(), internal_driver_ids_.end()); +} + std::vector ClockNetwork::levels( const ClockTreeId& tree_id) const { std::vector ret; @@ -325,6 +329,18 @@ vtr::Point ClockNetwork::spine_switch_point( return spine_switch_coords_[spine_id][size_t(switch_point_id)]; } +std::vector ClockNetwork::spine_switch_point_internal_drivers( + const ClockSpineId& spine_id, + const ClockSwitchPointId& switch_point_id) const { + VTR_ASSERT(valid_spine_switch_point_id(spine_id, switch_point_id)); + return spine_switch_internal_drivers_[spine_id][size_t(switch_point_id)]; +} + +std::string ClockNetwork::internal_driver_port(const ClockInternalDriverId& int_driver_id) const { + VTR_ASSERT(valid_internal_driver_id(int_driver_id)); + return internal_driver_ports_[int_driver_id]; +} + std::vector ClockNetwork::tree_taps( const ClockTreeId& tree_id) const { VTR_ASSERT(valid_tree_id(tree_id)); @@ -410,6 +426,7 @@ void ClockNetwork::reserve_spines(const size_t& num_spines) { spine_track_types_.reserve(num_spines); spine_switch_points_.reserve(num_spines); spine_switch_coords_.reserve(num_spines); + spine_switch_internal_drivers_.reserve(num_spines); spine_parents_.reserve(num_spines); spine_children_.reserve(num_spines); spine_parent_trees_.reserve(num_spines); @@ -494,6 +511,7 @@ ClockSpineId ClockNetwork::create_spine(const std::string& name) { spine_track_types_.emplace_back(NUM_RR_TYPES); spine_switch_points_.emplace_back(); spine_switch_coords_.emplace_back(); + spine_switch_internal_drivers_.emplace_back(); spine_parents_.emplace_back(); spine_children_.emplace_back(); spine_parent_trees_.emplace_back(); @@ -544,7 +562,7 @@ void ClockNetwork::set_spine_track_type(const ClockSpineId& spine_id, spine_track_types_[spine_id] = type; } -void ClockNetwork::add_spine_switch_point(const ClockSpineId& spine_id, +ClockSwitchPointId ClockNetwork::add_spine_switch_point(const ClockSpineId& spine_id, const ClockSpineId& drive_spine_id, const vtr::Point& coord) { VTR_ASSERT(valid_spine_id(spine_id)); @@ -563,6 +581,27 @@ void ClockNetwork::add_spine_switch_point(const ClockSpineId& spine_id, } spine_parents_[drive_spine_id] = spine_id; spine_children_[spine_id].push_back(drive_spine_id); + return ClockSwitchPointId(spine_switch_points_[spine_id].size() - 1); +} + +ClockInternalDriverId ClockNetwork::add_spine_switch_point_internal_driver(const ClockSpineId& spine_id, + const ClockSwitchPointId& switch_point_id, + const std::string& int_driver_port) { + VTR_ASSERT(valid_spine_id(spine_id)); + VTR_ASSERT(valid_spine_switch_point_id(spine_id, switch_point_id)); + /* Find any existing id for the driver port */ + for (ClockInternalDriverId int_driver_id : internal_driver_ids_) { + if (internal_driver_ports_[int_driver_id] == int_driver_port) { + spine_switch_internal_drivers_[spine_id][size_t(switch_point_id)].push_back(int_driver_id); + return int_driver_id; + } + } + /* Reaching here, no existing id can be reused, create a new one */ + ClockInternalDriverId int_driver_id = ClockInternalDriverId(internal_driver_ids_.size()); + internal_driver_ids_.push_back(int_driver_id); + internal_driver_ports_.push_back(int_driver_port); + spine_switch_internal_drivers_[spine_id][size_t(switch_point_id)].push_back(int_driver_id); + return int_driver_id; } void ClockNetwork::add_tree_tap(const ClockTreeId& tree_id, @@ -717,6 +756,11 @@ bool ClockNetwork::valid_tree_id(const ClockTreeId& tree_id) const { (tree_id == tree_ids_[tree_id]); } +bool ClockNetwork::valid_internal_driver_id(const ClockInternalDriverId& int_driver_id) const { + return (size_t(int_driver_id) < internal_driver_ids_.size()) && + (int_driver_id == internal_driver_ids_[int_driver_id]); +} + bool ClockNetwork::valid_level_id(const ClockTreeId& tree_id, const ClockLevelId& lvl_id) const { return valid_tree_id(tree_id) && (size_t(lvl_id) < tree_depth(tree_id)); diff --git a/libs/libclkarchopenfpga/src/base/clock_network.h b/libs/libclkarchopenfpga/src/base/clock_network.h index 3cf37a79a..836781ee6 100644 --- a/libs/libclkarchopenfpga/src/base/clock_network.h +++ b/libs/libclkarchopenfpga/src/base/clock_network.h @@ -42,6 +42,10 @@ class ClockNetwork { clock_tree_iterator; /* Create range */ typedef vtr::Range clock_tree_range; + typedef vtr::vector::const_iterator + clock_internal_driver_iterator; + /* Create range */ + typedef vtr::Range clock_internal_driver_range; public: /* Constructors */ ClockNetwork(); @@ -49,6 +53,7 @@ class ClockNetwork { public: /* Accessors: aggregates */ size_t num_trees() const; clock_tree_range trees() const; + clock_internal_driver_range internal_drivers() const; /* Return the range of clock levels */ std::vector levels(const ClockTreeId& tree_id) const; /* Return a list of spine id under a clock tree */ @@ -116,6 +121,11 @@ class ClockNetwork { vtr::Point spine_switch_point( const ClockSpineId& spine_id, const ClockSwitchPointId& switch_point_id) const; + std::vector spine_switch_point_internal_drivers( + const ClockSpineId& spine_id, + const ClockSwitchPointId& switch_point_id) const; + std::string internal_driver_port(const ClockInternalDriverId& int_driver_id) const; + /* Return the original list of tap pins that is in storage; useful for parsers */ std::vector tree_taps(const ClockTreeId& tree_id) const; @@ -172,9 +182,12 @@ class ClockNetwork { 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, + ClockSwitchPointId add_spine_switch_point(const ClockSpineId& spine_id, const ClockSpineId& drive_spine_id, const vtr::Point& coord); + ClockInternalDriverId add_spine_switch_point_internal_driver(const ClockSpineId& spine_id, + const ClockSwitchPointId& switch_point_id, + const std::string& internal_driver_port); void add_tree_tap(const ClockTreeId& tree_id, const std::string& pin_name); /* Build internal links between clock tree, spines etc. This is also an * validator to verify the correctness of the clock network. Must run before @@ -184,6 +197,7 @@ class ClockNetwork { public: /* Public invalidators/validators */ /* Show if the tree id is a valid for data queries */ bool valid_tree_id(const ClockTreeId& tree_id) const; + bool valid_internal_driver_id(const ClockInternalDriverId& int_driver_id) const; /* Show if the level id is a valid for a given tree */ bool valid_level_id(const ClockTreeId& tree_id, const ClockLevelId& lvl_id) const; @@ -245,10 +259,15 @@ class ClockNetwork { vtr::vector spine_track_types_; vtr::vector> spine_switch_points_; vtr::vector>> spine_switch_coords_; + vtr::vector>> spine_switch_internal_drivers_; vtr::vector spine_parents_; vtr::vector> spine_children_; vtr::vector spine_parent_trees_; + /* Basic Information about internal drivers */ + vtr::vector internal_driver_ids_; + vtr::vector internal_driver_ports_; + /* Default routing resource */ std::string default_segment_name_; /* The routing segment representing the clock wires */ diff --git a/libs/libclkarchopenfpga/src/base/clock_network_fwd.h b/libs/libclkarchopenfpga/src/base/clock_network_fwd.h index 1285f069c..e9602d384 100644 --- a/libs/libclkarchopenfpga/src/base/clock_network_fwd.h +++ b/libs/libclkarchopenfpga/src/base/clock_network_fwd.h @@ -19,12 +19,14 @@ struct clock_tree_id_tag; struct clock_tree_pin_id_tag; struct clock_spine_id_tag; struct clock_switch_point_id_tag; +struct clock_internal_driver_id_tag; typedef vtr::StrongId ClockLevelId; typedef vtr::StrongId ClockTreeId; typedef vtr::StrongId ClockTreePinId; typedef vtr::StrongId ClockSpineId; typedef vtr::StrongId ClockSwitchPointId; +typedef vtr::StrongId ClockInternalDriverId; /* Short declaration of class */ class ClockNetwork; diff --git a/libs/libclkarchopenfpga/src/io/clock_network_xml_constants.h b/libs/libclkarchopenfpga/src/io/clock_network_xml_constants.h index a172b88ec..6856a49f2 100644 --- a/libs/libclkarchopenfpga/src/io/clock_network_xml_constants.h +++ b/libs/libclkarchopenfpga/src/io/clock_network_xml_constants.h @@ -22,6 +22,8 @@ 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_INTERNAL_DRIVER_NODE_NAME = "internal_driver"; +constexpr const char* XML_CLOCK_SPINE_SWITCH_POINT_INTERNAL_DRIVER_ARRIBUTER_TILE_PIN = "tile_pin"; constexpr const char* XML_CLOCK_SPINE_SWITCH_POINT_ATTRIBUTE_TAP = "tap"; constexpr const char* XML_CLOCK_SPINE_SWITCH_POINT_ATTRIBUTE_X = "x"; constexpr const char* XML_CLOCK_SPINE_SWITCH_POINT_ATTRIBUTE_Y = "y"; diff --git a/libs/libclkarchopenfpga/src/io/read_xml_clock_network.cpp b/libs/libclkarchopenfpga/src/io/read_xml_clock_network.cpp index 372ec0c81..bdd3c6ab1 100644 --- a/libs/libclkarchopenfpga/src/io/read_xml_clock_network.cpp +++ b/libs/libclkarchopenfpga/src/io/read_xml_clock_network.cpp @@ -56,6 +56,24 @@ static void read_xml_clock_tree_taps(pugi::xml_node& xml_taps, } } +/******************************************************************** + * Parse XML codes of a to an object of ClockNetwork + *******************************************************************/ +static void read_xml_clock_spine_switch_point_internal_driver( + pugi::xml_node& xml_int_driver, const pugiutil::loc_data& loc_data, + ClockNetwork& clk_ntwk, const ClockSpineId& spine_id, const ClockSwitchPointId& switch_point_id) { + if (!clk_ntwk.valid_spine_id(spine_id)) { + archfpga_throw(loc_data.filename_c_str(), loc_data.line(xml_switch_point), + "Invalid id of a clock spine!\n"); + } + + std::string int_driver_port_name = + get_attribute(xml_int_driver, XML_CLOCK_SPINE_SWITCH_POINT_INTERNAL_DRIVER_ATTRIBUTE_TILE_PIN, + loc_data) + .as_string(); + clk_ntwk.add_spine_switch_point(spine_id, switch_point_id, int_driver_port_name); +} + /******************************************************************** * Parse XML codes of a to an object of ClockNetwork *******************************************************************/ @@ -90,8 +108,21 @@ static void read_xml_clock_spine_switch_point( XML_CLOCK_SPINE_SWITCH_POINT_ATTRIBUTE_Y, loc_data) .as_int(); - clk_ntwk.add_spine_switch_point(spine_id, tap_spine_id, - vtr::Point(tap_x, tap_y)); + ClockSwitchPointId switch_point_id = clk_ntwk.add_spine_switch_point(spine_id, tap_spine_id, + vtr::Point(tap_x, tap_y)); + + /* Add internal drivers if possible */ + for (pugi::xml_node xml_int_driver : xml_switch_point.children()) { + /* Error out if the XML child has an invalid name! */ + if (xml_int_driver.name() == + std::string(XML_CLOCK_SPINE_SWITCH_POINT_INTERNAL_DRIVER_NODE_NAME)) { + read_xml_clock_spine_switch_point_internal_driver(xml_int_driver, loc_data, clk_ntwk, + spine_id, switch_point_id); + } else { + bad_tag(xml_int_driver, loc_data, xml_switch_point, + {XML_CLOCK_SPINE_SWITCH_POINT_INTERNAL_DRIVER_NODE_NAME}); + } + } } /******************************************************************** diff --git a/libs/libclkarchopenfpga/src/io/write_xml_clock_network.cpp b/libs/libclkarchopenfpga/src/io/write_xml_clock_network.cpp index a71051fe1..ce8380c77 100644 --- a/libs/libclkarchopenfpga/src/io/write_xml_clock_network.cpp +++ b/libs/libclkarchopenfpga/src/io/write_xml_clock_network.cpp @@ -59,9 +59,23 @@ static int write_xml_clock_spine_switch_point( clk_ntwk.spine_switch_point(spine_id, switch_point_id); write_xml_attribute(fp, XML_CLOCK_SPINE_SWITCH_POINT_ATTRIBUTE_X, coord.x()); write_xml_attribute(fp, XML_CLOCK_SPINE_SWITCH_POINT_ATTRIBUTE_Y, coord.y()); - - fp << "/>" - << "\n"; + + /* Optional: internal drivers */ + if (clk_ntwk.spine_switch_point_internal_drivers(spine_id, switch_point_id).empty()) { + fp << "/>" + << "\n"; + } else { + fp << ">" + << "\n"; + for (ClockInternalDriverId int_driver_id : clk_ntwk.spine_switch_point_internal_drivers(spine_id, switch_point_id)) { + openfpga::write_tab_to_file(fp, 4); + fp << "<" << XML_CLOCK_SPINE_SWITCH_POINT_INTERNAL_DRIVER_NODE_NAME; + write_xml_attribute(fp, XML_CLOCK_SPINE_SWITCH_POINT_INTERNAL_DRIVER_ARRIBUTER_TILE_PIN, clk_ntwk.internal_driver_port(int_driver_id).c_str()); + fp << "/>" + << "\n"; + } + fp << "\n"; + } return 0; }