[lib] add syntax to support internal drivers in clock network parsers
This commit is contained in:
parent
582efc0501
commit
0c442f6238
|
@ -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));
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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";
|
||||
|
|
|
@ -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});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/********************************************************************
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue