[lib] add syntax to support internal drivers in clock network parsers

This commit is contained in:
tangxifan 2024-06-24 17:54:58 -07:00
parent 582efc0501
commit 0c442f6238
6 changed files with 119 additions and 7 deletions

View File

@ -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<ClockLevelId> ClockNetwork::levels(
const ClockTreeId& tree_id) const {
std::vector<ClockLevelId> ret;
@ -325,6 +329,18 @@ vtr::Point<int> ClockNetwork::spine_switch_point(
return spine_switch_coords_[spine_id][size_t(switch_point_id)];
}
std::vector<ClockInternalDriverId> 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<std::string> 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<int>& 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));

View File

@ -42,6 +42,10 @@ class ClockNetwork {
clock_tree_iterator;
/* Create range */
typedef vtr::Range<clock_tree_iterator> clock_tree_range;
typedef vtr::vector<ClockInternalDriverId, ClockInternalDriverId>::const_iterator
clock_internal_driver_iterator;
/* Create range */
typedef vtr::Range<clock_internal_driver_iterator> 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<ClockLevelId> levels(const ClockTreeId& tree_id) const;
/* Return a list of spine id under a clock tree */
@ -116,6 +121,11 @@ class ClockNetwork {
vtr::Point<int> spine_switch_point(
const ClockSpineId& spine_id,
const ClockSwitchPointId& switch_point_id) const;
std::vector<ClockInternalDriverId> 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<std::string> 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<int>& 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<ClockSpineId, t_rr_type> spine_track_types_;
vtr::vector<ClockSpineId, std::vector<ClockSpineId>> spine_switch_points_;
vtr::vector<ClockSpineId, std::vector<vtr::Point<int>>> spine_switch_coords_;
vtr::vector<ClockSpineId, std::vector<std::vector<ClockInternalDriverId>>> spine_switch_internal_drivers_;
vtr::vector<ClockSpineId, ClockSpineId> spine_parents_;
vtr::vector<ClockSpineId, std::vector<ClockSpineId>> spine_children_;
vtr::vector<ClockSpineId, ClockTreeId> spine_parent_trees_;
/* Basic Information about internal drivers */
vtr::vector<ClockInternalDriverId, ClockInternalDriverId> internal_driver_ids_;
vtr::vector<ClockInternalDriverId, std::string> internal_driver_ports_;
/* Default routing resource */
std::string default_segment_name_; /* The routing segment representing the
clock wires */

View File

@ -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<clock_level_id_tag> ClockLevelId;
typedef vtr::StrongId<clock_tree_id_tag> ClockTreeId;
typedef vtr::StrongId<clock_tree_pin_id_tag> ClockTreePinId;
typedef vtr::StrongId<clock_spine_id_tag> ClockSpineId;
typedef vtr::StrongId<clock_switch_point_id_tag> ClockSwitchPointId;
typedef vtr::StrongId<clock_internal_driver_id_tag> ClockInternalDriverId;
/* Short declaration of class */
class ClockNetwork;

View File

@ -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";

View File

@ -56,6 +56,24 @@ static void read_xml_clock_tree_taps(pugi::xml_node& xml_taps,
}
}
/********************************************************************
* Parse XML codes of a <switch_point> 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 <switch_point> 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<int>(tap_x, tap_y));
ClockSwitchPointId switch_point_id = clk_ntwk.add_spine_switch_point(spine_id, tap_spine_id,
vtr::Point<int>(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});
}
}
}
/********************************************************************

View File

@ -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 << "</" << XML_CLOCK_SPINE_SWITCH_POINT_NODE_NAME << ">\n";
}
return 0;
}