diff --git a/libs/libclkarchopenfpga/src/base/clock_network.cpp b/libs/libclkarchopenfpga/src/base/clock_network.cpp index 3dfbe64bc..ad0848137 100644 --- a/libs/libclkarchopenfpga/src/base/clock_network.cpp +++ b/libs/libclkarchopenfpga/src/base/clock_network.cpp @@ -230,6 +230,11 @@ vtr::Point ClockNetwork::spine_switch_point( return spine_switch_coords_[spine_id][size_t(switch_point_id)]; } +std::vector ClockNetwork::spine_taps(const ClockSpineId& spine_id) const { + VTR_ASSERT(valid_spine_id(spine_id)); + return spine_taps_[spine_id]; +} + ClockSpineId ClockNetwork::find_spine(const std::string& name) const { auto result = spine_name2id_map_.find(name); if (result == spine_name2id_map_.end()) { @@ -332,6 +337,7 @@ ClockSpineId ClockNetwork::create_spine(const std::string& name) { spine_parents_.emplace_back(); spine_children_.emplace_back(); spine_parent_trees_.emplace_back(); + spine_taps_.emplace_back(); /* Register to the lookup */ VTR_ASSERT(valid_spine_id(spine_id)); @@ -388,6 +394,11 @@ void ClockNetwork::add_spine_switch_point(const ClockSpineId& spine_id, spine_children_[spine_id].push_back(drive_spine_id); } +void ClockNetwork::add_spine_tap(const ClockSpineId& spine_id, const std::string& pin_name) { + VTR_ASSERT(valid_spine_id(spine_id)); + spine_taps_.push_back(pin_name); +} + bool ClockNetwork::link() { for (ClockTreeId tree_id : trees()) { if (!link_tree(tree_id)) { diff --git a/libs/libclkarchopenfpga/src/base/clock_network.h b/libs/libclkarchopenfpga/src/base/clock_network.h index 7687273e9..9a9cd154a 100644 --- a/libs/libclkarchopenfpga/src/base/clock_network.h +++ b/libs/libclkarchopenfpga/src/base/clock_network.h @@ -104,6 +104,7 @@ class ClockNetwork { vtr::Point spine_switch_point( const ClockSpineId& spine_id, const ClockSwitchPointId& switch_point_id) const; + std::vector spine_taps(const ClockSpineId& spine_id) const; /* Find a spine with a given name, if not found, return an valid id, otherwise * return an invalid one */ ClockSpineId find_spine(const std::string& name) const; @@ -146,6 +147,7 @@ class ClockNetwork { void add_spine_switch_point(const ClockSpineId& spine_id, const ClockSpineId& drive_spine_id, const vtr::Point& coord); + void add_spine_tap(const ClockSpineId& spine_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 * using the data! */ @@ -201,6 +203,7 @@ class ClockNetwork { vtr::vector spine_levels_; vtr::vector> spine_start_points_; vtr::vector> spine_end_points_; + vtr::vector> spine_taps_; 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 417e3d9db..8dc9871ec 100644 --- a/libs/libclkarchopenfpga/src/io/clock_network_xml_constants.h +++ b/libs/libclkarchopenfpga/src/io/clock_network_xml_constants.h @@ -21,5 +21,7 @@ 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"; constexpr const char* XML_CLOCK_SPINE_SWITCH_POINT_ATTRIBUTE_Y = "y"; +constexpr const char* XML_CLOCK_SPINE_TAP_NODE_NAME = "tap"; +constexpr const char* XML_CLOCK_SPINE_TAP_ATTRIBUTE_TILE_PIN = "tile_pin"; #endif diff --git a/libs/libclkarchopenfpga/src/io/read_xml_clock_network.cpp b/libs/libclkarchopenfpga/src/io/read_xml_clock_network.cpp index c8bd9835e..ee1ee34f9 100644 --- a/libs/libclkarchopenfpga/src/io/read_xml_clock_network.cpp +++ b/libs/libclkarchopenfpga/src/io/read_xml_clock_network.cpp @@ -24,6 +24,24 @@ namespace openfpga { // Begin namespace openfpga +/******************************************************************** + * Parse XML codes of a to an object of ClockNetwork + *******************************************************************/ +static void read_xml_clock_spine_tap( + pugi::xml_node& xml_switch_point, const pugiutil::loc_data& loc_data, + ClockNetwork& clk_ntwk, const ClockSpineId& spine_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 tile_pin_name = + get_attribute(xml_switch_point, XML_CLOCK_SPINE_TAP_ATTRIBUTE_TILE_PIN, + loc_data) + .as_string(); + clk_ntwk.add_spine_tap(spine_id, tile_pin_name); +} + /******************************************************************** * Parse XML codes of a to an object of ClockNetwork *******************************************************************/ @@ -109,13 +127,17 @@ static void read_xml_clock_spine(pugi::xml_node& xml_spine, 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() != + if (xml_switch_point.name() == std::string(XML_CLOCK_SPINE_SWITCH_POINT_NODE_NAME)) { + read_xml_clock_spine_switch_point(xml_switch_point, loc_data, clk_ntwk, + spine_id); + } else if (xml_switch_point.name() == + std::string(XML_CLOCK_SPINE_TAP_NODE_NAME)) { + read_xml_clock_spine_tap(xml_switch_point, loc_data, clk_ntwk, spine_id); + } else { bad_tag(xml_switch_point, loc_data, xml_spine, - {XML_CLOCK_SPINE_SWITCH_POINT_NODE_NAME}); + {XML_CLOCK_SPINE_SWITCH_POINT_NODE_NAME, XML_CLOCK_SPINE_TAP_NODE_NAME}); } - read_xml_clock_spine_switch_point(xml_switch_point, loc_data, clk_ntwk, - spine_id); } } diff --git a/libs/libclkarchopenfpga/src/io/write_xml_clock_network.cpp b/libs/libclkarchopenfpga/src/io/write_xml_clock_network.cpp index e2524a0ae..7910d6333 100644 --- a/libs/libclkarchopenfpga/src/io/write_xml_clock_network.cpp +++ b/libs/libclkarchopenfpga/src/io/write_xml_clock_network.cpp @@ -23,6 +23,22 @@ namespace openfpga { // Begin namespace openfpga +static int write_xml_clock_spine_taps( + std::fstream& fp, const ClockNetwork& clk_ntwk, const ClockSpineId& spine_id) { + for (const std::string& tile_pin_name : clk_ntwk.spine_taps(spine_id)) { + openfpga::write_tab_to_file(fp, 3); + fp << "<" << XML_CLOCK_SPINE_TAP_NODE_NAME << ""; + + write_xml_attribute( + fp, XML_CLOCK_SPINE_TAP_ATTRIBUTE_TILE_PIN, + tile_pin_name.c_str()); + fp << "/>" + << "\n"; + } + + return 0; +} + static int write_xml_clock_spine_switch_point( std::fstream& fp, const ClockNetwork& clk_ntwk, const ClockSpineId& spine_id, const ClockSwitchPointId& switch_point_id) { @@ -66,6 +82,7 @@ static int write_xml_clock_spine(std::fstream& fp, const ClockNetwork& clk_ntwk, clk_ntwk.spine_switch_points(spine_id)) { write_xml_clock_spine_switch_point(fp, clk_ntwk, spine_id, switch_point_id); } + write_xml_clock_spine_taps(fp, clk_ntwk, spine_id); openfpga::write_tab_to_file(fp, 2); fp << "