[lib] now clock spine requires explicit definition of track type and direction when coordinate is vague

This commit is contained in:
tangxifan 2023-03-02 21:33:32 -08:00
parent b9f7c72a96
commit 02b50e3464
6 changed files with 133 additions and 7 deletions

View File

@ -82,7 +82,10 @@ std::vector<ClockTreePinId> 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<int>& 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

View File

@ -163,6 +163,10 @@ class ClockNetwork {
const vtr::Point<int>& coord);
void set_spine_end_point(const ClockSpineId& spine_id,
const vtr::Point<int>& 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<int>& 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<ClockSpineId, size_t> spine_levels_;
vtr::vector<ClockSpineId, vtr::Point<int>> spine_start_points_;
vtr::vector<ClockSpineId, vtr::Point<int>> spine_end_points_;
vtr::vector<ClockSpineId, Direction> spine_directions_;
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, ClockSpineId> spine_parents_;

View File

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

View File

@ -94,6 +94,37 @@ static void read_xml_clock_spine_switch_point(
vtr::Point<int>(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<t_rr_type>(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<Direction>(itype);
}
}
/* Reach here, we have an invalid value, error out */
return Direction::NUM_DIRECTIONS;
}
/********************************************************************
* Parse XML codes of a <spine> 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<int>(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() ==

View File

@ -79,6 +79,10 @@ static int write_xml_clock_spine(std::fstream& fp, const ClockNetwork& clk_ntwk,
vtr::Point<int> 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";

View File

@ -6,10 +6,10 @@
<switch_point tap="rib_lvl1_sw1_upper" x="2" y="1"/>
<switch_point tap="rib_lvl1_sw1_lower" x="2" y="1"/>
</spine>
<spine name="rib_lvl1_sw0_upper" start_x="1" start_y="2" end_x="1" end_y="2"/>
<spine name="rib_lvl1_sw0_lower" start_x="1" start_y="1" end_x="1" end_y="1"/>
<spine name="rib_lvl1_sw1_upper" start_x="2" start_y="2" end_x="2" end_y="2"/>
<spine name="rib_lvl1_sw1_lower" start_x="2" start_y="1" end_x="2" end_y="1"/>
<spine name="rib_lvl1_sw0_upper" start_x="1" start_y="2" end_x="1" end_y="2" type="CHANY" direction="inc"/>
<spine name="rib_lvl1_sw0_lower" start_x="1" start_y="1" end_x="1" end_y="1" type="CHANY" direction="inc"/>
<spine name="rib_lvl1_sw1_upper" start_x="2" start_y="2" end_x="2" end_y="2" type="CHANY" direction="inc"/>
<spine name="rib_lvl1_sw1_lower" start_x="2" start_y="1" end_x="2" end_y="1" type="CHANY" direction="inc"/>
<taps>
<tap tile_pin="clb[0:0].clk[0:0]"/>
</taps>