[lib] now clock spine requires explicit definition of track type and direction when coordinate is vague
This commit is contained in:
parent
b9f7c72a96
commit
02b50e3464
|
@ -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
|
||||
|
|
|
@ -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_;
|
||||
|
|
|
@ -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";
|
||||
|
|
|
@ -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() ==
|
||||
|
|
|
@ -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";
|
||||
|
|
|
@ -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>
|
||||
|
|
Loading…
Reference in New Issue