[lib] clock tap syntax are reworked. Support region, single, all and from/to ports
This commit is contained in:
parent
ec1ad94d4a
commit
381a8cb535
|
@ -20,6 +20,8 @@ ClockNetwork::ClockNetwork() {
|
|||
default_segment_id_ = RRSegmentId::INVALID();
|
||||
default_tap_switch_id_ = RRSwitchId::INVALID();
|
||||
default_driver_switch_id_ = RRSwitchId::INVALID();
|
||||
/* Set a default invalid bounding box */
|
||||
empty_tap_bb_ = vtr::Rect<size_t>(1, 0, 1, 0);
|
||||
is_dirty_ = true;
|
||||
}
|
||||
|
||||
|
@ -345,17 +347,67 @@ std::string ClockNetwork::internal_driver_port(
|
|||
return internal_driver_ports_[int_driver_id];
|
||||
}
|
||||
|
||||
std::vector<std::string> ClockNetwork::tree_taps(
|
||||
std::vector<ClockTapId> ClockNetwork::tree_taps(
|
||||
const ClockTreeId& tree_id) const {
|
||||
VTR_ASSERT(valid_tree_id(tree_id));
|
||||
return tree_taps_[tree_id];
|
||||
}
|
||||
|
||||
std::vector<std::string> ClockNetwork::tree_flatten_taps(
|
||||
std::string ClockNetwork::tap_from_port(const ClockTapId& tap_id) const {
|
||||
VTR_ASSERT(valid_tap_id(tap_id));
|
||||
return tap_from_ports_[tap_id];
|
||||
}
|
||||
|
||||
std::string ClockNetwork::tap_to_port(const ClockTapId& tap_id) const {
|
||||
VTR_ASSERT(valid_tap_id(tap_id));
|
||||
return tap_to_ports_[tap_id];
|
||||
}
|
||||
|
||||
ClockNetwork::e_tap_type ClockNetwork::tap_type(const ClockTapId& tap_id) const {
|
||||
VTR_ASSERT(valid_tap_id(tap_id));
|
||||
/* If not a region, it is a default type covering all the coordinates*/
|
||||
if (tap_bbs_[tap_id] == empty_tap_bb_) {
|
||||
return ClockNetwork::e_tap_type::ALL;
|
||||
}
|
||||
/* Now check if this a single point */
|
||||
if (tap_bbs_[tap_id].height() == 0 && tap_bbs_[tap_id].width() == 0) {
|
||||
return ClockNetwork::e_tap_type::SINGLE;
|
||||
}
|
||||
return ClockNetwork::e_tap_type::REGION;
|
||||
}
|
||||
|
||||
size_t ClockNetwork::tap_x(const ClockTapId& tap_id) const {
|
||||
VTR_ASSERT(tap_type(tap_id) == ClockNetwork::e_tap_type::SINGLE);
|
||||
return tap_bbs_[tap_id].xmin();
|
||||
}
|
||||
|
||||
size_t ClockNetwork::tap_y(const ClockTapId& tap_id) const {
|
||||
VTR_ASSERT(tap_type(tap_id) == ClockNetwork::e_tap_type::SINGLE);
|
||||
return tap_bbs_[tap_id].ymin();
|
||||
}
|
||||
|
||||
vtr::Rect<size_t> ClockNetwork::tap_bounding_box(const ClockTapId& tap_id) const {
|
||||
VTR_ASSERT(tap_type(tap_id) == ClockNetwork::e_tap_type::REGION);
|
||||
return tap_bbs_[tap_id];
|
||||
}
|
||||
|
||||
size_t ClockNetwork::tap_step_x(const ClockTapId& tap_id) const {
|
||||
VTR_ASSERT(tap_type(tap_id) == ClockNetwork::e_tap_type::REGION);
|
||||
return tap_bb_steps_[tap_id].x();
|
||||
}
|
||||
|
||||
size_t ClockNetwork::tap_step_y(const ClockTapId& tap_id) const {
|
||||
VTR_ASSERT(tap_type(tap_id) == ClockNetwork::e_tap_type::REGION);
|
||||
return tap_bb_steps_[tap_id].y();
|
||||
}
|
||||
|
||||
std::vector<std::string> ClockNetwork::tree_flatten_tap_to_ports(
|
||||
const ClockTreeId& tree_id, const ClockTreePinId& clk_pin_id) const {
|
||||
VTR_ASSERT(valid_tree_id(tree_id));
|
||||
std::vector<std::string> flatten_taps;
|
||||
for (const std::string& tap_name : tree_taps_[tree_id]) {
|
||||
for (ClockTapId tap_id : tree_taps_[tree_id]) {
|
||||
VTR_ASSERT(valid_tap_id(tap_id));
|
||||
std::string tap_name = tap_to_ports_[tap_id];
|
||||
StringToken tokenizer(tap_name);
|
||||
std::vector<std::string> pin_tokens = tokenizer.split(".");
|
||||
if (pin_tokens.size() != 2) {
|
||||
|
@ -649,10 +701,53 @@ ClockInternalDriverId ClockNetwork::add_spine_switch_point_internal_driver(
|
|||
return int_driver_id;
|
||||
}
|
||||
|
||||
void ClockNetwork::add_tree_tap(const ClockTreeId& tree_id,
|
||||
const std::string& pin_name) {
|
||||
ClockTapId ClockNetwork::add_tree_tap(const ClockTreeId& tree_id,
|
||||
const std::string& from_port,
|
||||
const std::string& to_port,
|
||||
const ) {
|
||||
VTR_ASSERT(valid_tree_id(tree_id));
|
||||
tree_taps_[tree_id].push_back(pin_name);
|
||||
/* TODO: Consider find existing tap template and avoid duplication in storage */
|
||||
ClockTapId tap_id = ClockTapId(tap_ids_.size());
|
||||
tap_ids_.push_back(tap_id);
|
||||
tap_from_ports_.push_back(from_port);
|
||||
tap_to_ports_.push_back(to_port);
|
||||
tap_bbs_.emplace_back(empty_tap_bb_);
|
||||
tap_bb_steps_.emplace_back(vtr::Point<size_t>(1, 1));
|
||||
tree_taps_[tree_id].push_back(tap_id);
|
||||
return tap_id;
|
||||
}
|
||||
|
||||
bool ClockNetwork::set_tap_bounding_box(const ClockTapId& tap_id, const vtr::Rect<size_t>& bb) {
|
||||
VTR_ASSERT(valid_tap_id(tap_id));
|
||||
/* Check the bounding box, ensure it must be valid */
|
||||
if (bb.height() < 0 || bb.width() < 0) {
|
||||
VTR_LOG_ERROR("Invalid bounding box (xlow=%lu, ylow=%lu) -> (xhigh=%lu, yhigh=%lu)! Must follow: xlow <= xhigh, ylow <= yhigh!\n", bb.xmin(), bb.ymin(), bb.xmax(), bb.ymax());
|
||||
return false;
|
||||
}
|
||||
tap_bbs_[tap_id] = bb;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ClockNetwork::set_tap_step_x(const ClockTapId& tap_id, const size_t step) {
|
||||
VTR_ASSERT(valid_tap_id(tap_id));
|
||||
/* Must be a valid step >= 1 */
|
||||
if (step == 0) {
|
||||
VTR_LOG_ERROR("Invalid x-direction step (=%lu) for any bounding box! Expect an integer >= 1!\n", step);
|
||||
return false;
|
||||
}
|
||||
tap_bbs_[tap_id].set_x(step);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ClockNetwork::set_tap_step_y(const ClockTapId& tap_id, const size_t step) {
|
||||
VTR_ASSERT(valid_tap_id(tap_id));
|
||||
/* Must be a valid step >= 1 */
|
||||
if (step == 0) {
|
||||
VTR_LOG_ERROR("Invalid y-direction step (=%lu) for any bounding box! Expect an integer >= 1!\n", step);
|
||||
return false;
|
||||
}
|
||||
tap_bbs_[tap_id].set_y(step);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ClockNetwork::link() {
|
||||
|
@ -807,6 +902,12 @@ bool ClockNetwork::valid_internal_driver_id(
|
|||
(int_driver_id == internal_driver_ids_[int_driver_id]);
|
||||
}
|
||||
|
||||
bool ClockNetwork::valid_tap_id(
|
||||
const ClockTapId& tap_id) const {
|
||||
return (size_t(tap_id) < tap_ids_.size()) &&
|
||||
(tap_id == tap_ids_[tap_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));
|
||||
|
|
|
@ -48,6 +48,13 @@ class ClockNetwork {
|
|||
/* Create range */
|
||||
typedef vtr::Range<clock_internal_driver_iterator>
|
||||
clock_internal_driver_range;
|
||||
/* Type of tap points */
|
||||
enum class : unsigned char {
|
||||
ALL = 0,
|
||||
SINGLE,
|
||||
REGION,
|
||||
NUM_TYPES
|
||||
};
|
||||
|
||||
public: /* Constructors */
|
||||
ClockNetwork();
|
||||
|
@ -133,12 +140,30 @@ class ClockNetwork {
|
|||
|
||||
/* 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;
|
||||
std::vector<ClockTapId> tree_taps(const ClockTreeId& tree_id) const;
|
||||
/* Return the source ports for a given tap */
|
||||
std::string tap_from_port(const ClockTapId& tap_id) const;
|
||||
/* Return the destination ports for a given tap */
|
||||
std::string tap_to_port(const ClockTapId& tap_id) const;
|
||||
/* Find the type of tap point:
|
||||
* all -> all coordinates in efpga are required to tap
|
||||
* single -> only 1 coordinate is required to tap
|
||||
* region -> coordinates in a region required to tap. Steps in region may be required
|
||||
*/
|
||||
e_tap_type tap_type(const ClockTapId& tap_id) const;
|
||||
/* Require the type of single */
|
||||
size_t tap_x(const ClockTapId& tap_id) const;
|
||||
size_t tap_y(const ClockTapId& tap_id) const;
|
||||
/* Require the type of region */
|
||||
vtr::Rect<size_t> tap_bounding_box(const ClockTapId& tap_id) const;
|
||||
/* Steps are only available when type is region */
|
||||
size_t tap_step_x(const ClockTapId& tap_id) const;
|
||||
size_t tap_step_y(const ClockTapId& tap_id) const;
|
||||
/* Return the list of flatten tap pins. For example: clb[0:1].clk[2:2] is
|
||||
* flatten to { clb[0].clk[2], clb[1].clk[2] } Useful to build clock routing
|
||||
* resource graph Note that the clk_pin_id limits only 1 clock to be accessed
|
||||
*/
|
||||
std::vector<std::string> tree_flatten_taps(
|
||||
std::vector<std::string> tree_flatten_tap_to_ports(
|
||||
const ClockTreeId& tree_id, const ClockTreePinId& clk_pin_id) const;
|
||||
/* Find a spine with a given name, if not found, return an valid id, otherwise
|
||||
* return an invalid one */
|
||||
|
@ -193,7 +218,10 @@ class ClockNetwork {
|
|||
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);
|
||||
ClockTapId add_tree_tap(const ClockTreeId& tree_id, const std::string& from_port, const std::string& to_port);
|
||||
bool set_tap_bounding_box(const ClockTapId& tap_id, const vtr::Rect<size_t>& bb);
|
||||
bool set_tap_step_x(const ClockTapId& tap_id, const size_t& step);
|
||||
bool set_tap_step_y(const ClockTapId& tap_id, const size_t& step);
|
||||
/* 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! */
|
||||
|
@ -202,8 +230,6 @@ 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;
|
||||
|
@ -233,6 +259,11 @@ class ClockNetwork {
|
|||
/* Ensure tree data is clean. All the spines are valid, and switch points are
|
||||
* valid */
|
||||
bool validate_tree() const;
|
||||
/* Show if the internal driver id is a valid for data queries */
|
||||
bool valid_internal_driver_id(
|
||||
const ClockInternalDriverId& int_driver_id) const;
|
||||
/* Show if the tap id is a valid for data queries */
|
||||
bool valid_tap_id(const ClockTapId& tap_id) const;
|
||||
|
||||
private: /* Private mutators */
|
||||
/* Build internal links between spines under a given tree */
|
||||
|
@ -253,7 +284,7 @@ class ClockNetwork {
|
|||
vtr::vector<ClockTreeId, size_t> tree_widths_;
|
||||
vtr::vector<ClockTreeId, size_t> tree_depths_;
|
||||
vtr::vector<ClockTreeId, std::vector<ClockSpineId>> tree_top_spines_;
|
||||
vtr::vector<ClockTreeId, std::vector<std::string>> tree_taps_;
|
||||
vtr::vector<ClockTreeId, ClockTapId> tree_taps_;
|
||||
|
||||
/* Basic information of each spine */
|
||||
vtr::vector<ClockSpineId, ClockSpineId> spine_ids_;
|
||||
|
@ -275,6 +306,12 @@ class ClockNetwork {
|
|||
vtr::vector<ClockInternalDriverId, ClockInternalDriverId>
|
||||
internal_driver_ids_;
|
||||
vtr::vector<ClockInternalDriverId, std::string> internal_driver_ports_;
|
||||
/* Basic information about tap */
|
||||
vtr::vector<ClockTapId, ClockTapId> tap_ids_;
|
||||
vtr::vector<ClockTapId, std::string> tap_from_ports_;
|
||||
vtr::vector<ClockTapId, std::string> tap_to_ports_;
|
||||
vtr::vector<ClockTapId, vtr::Rect<size_t>> tap_bbs_; /* Bounding box for tap points, (xlow, ylow) -> (xhigh, yhigh) */
|
||||
vtr::vector<ClockTapId, vtr::Point<size_t>> tap_bb_steps_; /* x() -> x-direction step, y() -> y-direction step */
|
||||
|
||||
/* Default routing resource */
|
||||
std::string default_segment_name_; /* The routing segment representing the
|
||||
|
@ -291,6 +328,9 @@ class ClockNetwork {
|
|||
std::map<std::string, ClockTreeId> tree_name2id_map_;
|
||||
std::map<std::string, ClockSpineId> spine_name2id_map_;
|
||||
|
||||
/* Constants */
|
||||
vtr::Rect<size_t> empty_tap_bb_;
|
||||
|
||||
/* Flags */
|
||||
mutable bool is_dirty_;
|
||||
};
|
||||
|
|
|
@ -20,6 +20,7 @@ struct clock_tree_pin_id_tag;
|
|||
struct clock_spine_id_tag;
|
||||
struct clock_switch_point_id_tag;
|
||||
struct clock_internal_driver_id_tag;
|
||||
struct clock_tap_id_tag;
|
||||
|
||||
typedef vtr::StrongId<clock_level_id_tag> ClockLevelId;
|
||||
typedef vtr::StrongId<clock_tree_id_tag> ClockTreeId;
|
||||
|
@ -27,6 +28,7 @@ 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;
|
||||
typedef vtr::StrongId<clock_tap_id_tag> ClockTapId;
|
||||
|
||||
/* Short declaration of class */
|
||||
class ClockNetwork;
|
||||
|
|
|
@ -30,7 +30,18 @@ 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_TREE_TAPS_NODE_NAME = "taps";
|
||||
constexpr const char* XML_CLOCK_TREE_TAP_NODE_NAME = "tap";
|
||||
constexpr const char* XML_CLOCK_TREE_TAP_ATTRIBUTE_TILE_PIN = "tile_pin";
|
||||
constexpr const char* XML_CLOCK_TREE_TAP_ALL_NODE_NAME = "all";
|
||||
constexpr const char* XML_CLOCK_TREE_TAP_REGION_NODE_NAME = "region";
|
||||
constexpr const char* XML_CLOCK_TREE_TAP_SINGLE_NODE_NAME = "single";
|
||||
constexpr const char* XML_CLOCK_TREE_TAP_ATTRIBUTE_FROM_PIN = "from_pin";
|
||||
constexpr const char* XML_CLOCK_TREE_TAP_ATTRIBUTE_TO_PIN = "to_pin";
|
||||
constexpr const char* XML_CLOCK_TREE_TAP_ATTRIBUTE_X = "x";
|
||||
constexpr const char* XML_CLOCK_TREE_TAP_ATTRIBUTE_Y = "y";
|
||||
constexpr const char* XML_CLOCK_TREE_TAP_ATTRIBUTE_STARTX = "start_x";
|
||||
constexpr const char* XML_CLOCK_TREE_TAP_ATTRIBUTE_STARTY = "start_y";
|
||||
constexpr const char* XML_CLOCK_TREE_TAP_ATTRIBUTE_ENDX = "end_x";
|
||||
constexpr const char* XML_CLOCK_TREE_TAP_ATTRIBUTE_ENDY = "end_y";
|
||||
constexpr const char* XML_CLOCK_TREE_TAP_ATTRIBUTE_REPEATX = "repeat_x";
|
||||
constexpr const char* XML_CLOCK_TREE_TAP_ATTRIBUTE_REPEATY = "repeat_y";
|
||||
|
||||
#endif
|
||||
|
|
|
@ -25,10 +25,10 @@
|
|||
namespace openfpga { // Begin namespace openfpga
|
||||
|
||||
/********************************************************************
|
||||
* Parse XML codes of a <tap> to an object of ClockNetwork
|
||||
* Parse XML codes of a <all> to an object of ClockNetwork
|
||||
*******************************************************************/
|
||||
static void read_xml_clock_tree_tap(pugi::xml_node& xml_tap,
|
||||
const pugiutil::loc_data& loc_data,
|
||||
static void read_xml_clock_tree_tap_type_all(pugi::xml_node& xml_tap,
|
||||
const pugiutil::loc_data& loc_data,
|
||||
ClockNetwork& clk_ntwk,
|
||||
const ClockTreeId& tree_id) {
|
||||
if (!clk_ntwk.valid_tree_id(tree_id)) {
|
||||
|
@ -36,10 +36,89 @@ static void read_xml_clock_tree_tap(pugi::xml_node& xml_tap,
|
|||
"Invalid id of a clock tree!\n");
|
||||
}
|
||||
|
||||
std::string tile_pin_name =
|
||||
get_attribute(xml_tap, XML_CLOCK_TREE_TAP_ATTRIBUTE_TILE_PIN, loc_data)
|
||||
std::string from_pin_name =
|
||||
get_attribute(xml_tap, XML_CLOCK_TREE_TAP_ATTRIBUTE_FROM_PIN, loc_data)
|
||||
.as_string();
|
||||
clk_ntwk.add_tree_tap(tree_id, tile_pin_name);
|
||||
std::string to_pin_name =
|
||||
get_attribute(xml_tap, XML_CLOCK_TREE_TAP_ATTRIBUTE_TO_PIN, loc_data)
|
||||
.as_string();
|
||||
clk_ntwk.add_tree_tap(tree_id, from_pin_name, to_pin_name);
|
||||
}
|
||||
|
||||
/********************************************************************
|
||||
* Parse XML codes of a <single> to an object of ClockNetwork
|
||||
*******************************************************************/
|
||||
static void read_xml_clock_tree_tap_type_single(pugi::xml_node& xml_tap,
|
||||
const pugiutil::loc_data& loc_data,
|
||||
ClockNetwork& clk_ntwk,
|
||||
const ClockTreeId& tree_id) {
|
||||
if (!clk_ntwk.valid_tree_id(tree_id)) {
|
||||
archfpga_throw(loc_data.filename_c_str(), loc_data.line(xml_tap),
|
||||
"Invalid id of a clock tree!\n");
|
||||
}
|
||||
|
||||
std::string from_pin_name =
|
||||
get_attribute(xml_tap, XML_CLOCK_TREE_TAP_ATTRIBUTE_FROM_PIN, loc_data)
|
||||
.as_string();
|
||||
std::string to_pin_name =
|
||||
get_attribute(xml_tap, XML_CLOCK_TREE_TAP_ATTRIBUTE_TO_PIN, loc_data)
|
||||
.as_string();
|
||||
ClockTapId tap_id = clk_ntwk.add_tree_tap(tree_id, from_pin_name, to_pin_name);
|
||||
|
||||
/* Single tap only require a coordinate */
|
||||
size_t tap_x =
|
||||
get_attribute(xml_tap, XML_CLOCK_TREE_TAP_ATTRIBUTE_X, loc_data, pugi::ReqOpt::REQUIRED)
|
||||
.as_int();
|
||||
size_t tap_y =
|
||||
get_attribute(xml_tap, XML_CLOCK_TREE_TAP_ATTRIBUTE_Y, loc_data, pugi::ReqOpt::REQUIRED)
|
||||
.as_int();
|
||||
clk_ntwk.set_tap_bounding_box(tap_id, vtr::Rect<size_t>(tap_x, tap_y, tap_x, tap_y));
|
||||
}
|
||||
|
||||
/********************************************************************
|
||||
* Parse XML codes of a <region> to an object of ClockNetwork
|
||||
*******************************************************************/
|
||||
static void read_xml_clock_tree_tap_type_region(pugi::xml_node& xml_tap,
|
||||
const pugiutil::loc_data& loc_data,
|
||||
ClockNetwork& clk_ntwk,
|
||||
const ClockTreeId& tree_id) {
|
||||
if (!clk_ntwk.valid_tree_id(tree_id)) {
|
||||
archfpga_throw(loc_data.filename_c_str(), loc_data.line(xml_tap),
|
||||
"Invalid id of a clock tree!\n");
|
||||
}
|
||||
|
||||
std::string from_pin_name =
|
||||
get_attribute(xml_tap, XML_CLOCK_TREE_TAP_ATTRIBUTE_FROM_PIN, loc_data)
|
||||
.as_string();
|
||||
std::string to_pin_name =
|
||||
get_attribute(xml_tap, XML_CLOCK_TREE_TAP_ATTRIBUTE_TO_PIN, loc_data)
|
||||
.as_string();
|
||||
ClockTapId tap_id = clk_ntwk.add_tree_tap(tree_id, from_pin_name, to_pin_name);
|
||||
|
||||
/* Region require a bounding box */
|
||||
size_t tap_start_x =
|
||||
get_attribute(xml_tap, XML_CLOCK_TREE_TAP_ATTRIBUTE_STARTX, loc_data, pugi::ReqOpt::REQUIRED)
|
||||
.as_int();
|
||||
size_t tap_start_y =
|
||||
get_attribute(xml_tap, XML_CLOCK_TREE_TAP_ATTRIBUTE_STARTY, loc_data, pugi::ReqOpt::REQUIRED)
|
||||
.as_int();
|
||||
size_t tap_end_x =
|
||||
get_attribute(xml_tap, XML_CLOCK_TREE_TAP_ATTRIBUTE_ENDX, loc_data, pugi::ReqOpt::REQUIRED)
|
||||
.as_int();
|
||||
size_t tap_end_y =
|
||||
get_attribute(xml_tap, XML_CLOCK_TREE_TAP_ATTRIBUTE_ENDY, loc_data, pugi::ReqOpt::REQUIRED)
|
||||
.as_int();
|
||||
clk_ntwk.set_tap_bounding_box(tap_id, vtr::Rect<size_t>(tap_start_x, tap_start_y, tap_end_x, tap_end_y));
|
||||
|
||||
/* Default step is all 1 */
|
||||
size_t tap_step_x =
|
||||
get_attribute(xml_tap, XML_CLOCK_TREE_TAP_ATTRIBUTE_REPEATX, loc_data)
|
||||
.as_int(1);
|
||||
size_t tap_step_y =
|
||||
get_attribute(xml_tap, XML_CLOCK_TREE_TAP_ATTRIBUTE_REPEATY, loc_data)
|
||||
.as_int(1);
|
||||
clk_ntwk.set_tap_step_x(tap_id, tap_step_x);
|
||||
clk_ntwk.set_tap_step_y(tap_id, tap_step_y);
|
||||
}
|
||||
|
||||
static void read_xml_clock_tree_taps(pugi::xml_node& xml_taps,
|
||||
|
@ -48,10 +127,14 @@ static void read_xml_clock_tree_taps(pugi::xml_node& xml_taps,
|
|||
const ClockTreeId& tree_id) {
|
||||
for (pugi::xml_node xml_tap : xml_taps.children()) {
|
||||
/* Error out if the XML child has an invalid name! */
|
||||
if (xml_tap.name() == std::string(XML_CLOCK_TREE_TAP_NODE_NAME)) {
|
||||
read_xml_clock_tree_tap(xml_tap, loc_data, clk_ntwk, tree_id);
|
||||
if (xml_tap.name() == std::string(XML_CLOCK_TREE_TAP_ALL_NODE_NAME)) {
|
||||
read_xml_clock_tree_tap_type_all(xml_tap, loc_data, clk_ntwk, tree_id);
|
||||
} else if (xml_tap.name() == std::string(XML_CLOCK_TREE_TAP_REGION_NODE_NAME)) {
|
||||
read_xml_clock_tree_tap_type_region(xml_tap, loc_data, clk_ntwk, tree_id);
|
||||
} else if (xml_tap.name() == std::string(XML_CLOCK_TREE_TAP_SINGLE_NODE_NAME)) {
|
||||
read_xml_clock_tree_tap_type_single(xml_tap, loc_data, clk_ntwk, tree_id);
|
||||
} else {
|
||||
bad_tag(xml_taps, loc_data, xml_tap, {XML_CLOCK_TREE_TAP_NODE_NAME});
|
||||
bad_tag(xml_taps, loc_data, xml_tap, {XML_CLOCK_TREE_TAP_ALL_NODE_NAME, XML_CLOCK_TREE_TAP_REGION_NODE_NAME, XML_CLOCK_TREE_TAP_SINGLE_NODE_NAME});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -28,15 +28,60 @@ static int write_xml_clock_tree_taps(std::fstream& fp,
|
|||
const ClockTreeId& tree_id) {
|
||||
openfpga::write_tab_to_file(fp, 3);
|
||||
fp << "<" << XML_CLOCK_TREE_TAPS_NODE_NAME << ">\n";
|
||||
for (const std::string& tile_pin_name : clk_ntwk.tree_taps(tree_id)) {
|
||||
openfpga::write_tab_to_file(fp, 4);
|
||||
fp << "<" << XML_CLOCK_TREE_TAP_NODE_NAME << "";
|
||||
|
||||
write_xml_attribute(fp, XML_CLOCK_TREE_TAP_ATTRIBUTE_TILE_PIN,
|
||||
tile_pin_name.c_str());
|
||||
fp << "/>"
|
||||
<< "\n";
|
||||
}
|
||||
/* Depends on the type */
|
||||
for (ClockTapId tap_id : clk_ntwk.tree_taps(tree_id)) {
|
||||
switch clk_ntwk.tap_type(tap_id): {
|
||||
case ClockNetwork::e_tap_type::ALL: {
|
||||
openfpga::write_tab_to_file(fp, 4);
|
||||
fp << "<" << XML_CLOCK_TREE_TAP_ALL_NODE_NAME << "";
|
||||
write_xml_attribute(fp, XML_CLOCK_TREE_TAP_ATTRIBUTE_FROM_PIN,
|
||||
clk_ntwk.tap_from_port(tap_id).c_str());
|
||||
write_xml_attribute(fp, XML_CLOCK_TREE_TAP_ATTRIBUTE_TO_PIN,
|
||||
clk_ntwk.tap_to_port(tap_id).c_str());
|
||||
fp << "/>"
|
||||
<< "\n";
|
||||
}
|
||||
case ClockNetwork::e_tap_type::SINGLE: {
|
||||
openfpga::write_tab_to_file(fp, 4);
|
||||
fp << "<" << XML_CLOCK_TREE_TAP_SINGLE_NODE_NAME << "";
|
||||
write_xml_attribute(fp, XML_CLOCK_TREE_TAP_ATTRIBUTE_FROM_PIN,
|
||||
clk_ntwk.tap_from_port(tap_id).c_str());
|
||||
write_xml_attribute(fp, XML_CLOCK_TREE_TAP_ATTRIBUTE_TO_PIN,
|
||||
clk_ntwk.tap_to_port(tap_id).c_str());
|
||||
write_xml_attribute(fp, XML_CLOCK_TREE_TAP_ATTRIBUTE_X,
|
||||
clk_ntwk.tap_x(tap_id));
|
||||
write_xml_attribute(fp, XML_CLOCK_TREE_TAP_ATTRIBUTE_Y,
|
||||
clk_ntwk.tap_y(tap_id));
|
||||
fp << "/>"
|
||||
<< "\n";
|
||||
}
|
||||
case ClockNetwork::e_tap_type::REGION: {
|
||||
openfpga::write_tab_to_file(fp, 4);
|
||||
fp << "<" << XML_CLOCK_TREE_TAP_SINGLE_NODE_NAME << "";
|
||||
write_xml_attribute(fp, XML_CLOCK_TREE_TAP_ATTRIBUTE_FROM_PIN,
|
||||
clk_ntwk.tap_from_port(tap_id).c_str());
|
||||
write_xml_attribute(fp, XML_CLOCK_TREE_TAP_ATTRIBUTE_TO_PIN,
|
||||
clk_ntwk.tap_to_port(tap_id).c_str());
|
||||
write_xml_attribute(fp, XML_CLOCK_TREE_TAP_ATTRIBUTE_STARTX,
|
||||
clk_ntwk.tap_bounding_box(tap_id).xmin());
|
||||
write_xml_attribute(fp, XML_CLOCK_TREE_TAP_ATTRIBUTE_STARTY,
|
||||
clk_ntwk.tap_bounding_box(tap_id).ymin());
|
||||
write_xml_attribute(fp, XML_CLOCK_TREE_TAP_ATTRIBUTE_ENDX,
|
||||
clk_ntwk.tap_bounding_box(tap_id).xmax());
|
||||
write_xml_attribute(fp, XML_CLOCK_TREE_TAP_ATTRIBUTE_ENDY,
|
||||
clk_ntwk.tap_bounding_box(tap_id).ymax());
|
||||
write_xml_attribute(fp, XML_CLOCK_TREE_TAP_ATTRIBUTE_REPEATX,
|
||||
clk_ntwk.tap_step_x(tap_id));
|
||||
write_xml_attribute(fp, XML_CLOCK_TREE_TAP_ATTRIBUTE_REPEATY,
|
||||
clk_ntwk.tap_step_y(tap_id));
|
||||
fp << "/>"
|
||||
<< "\n";
|
||||
}
|
||||
default: {
|
||||
VTR_LOG_ERROR("Invalid type of tap point!\n");
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
openfpga::write_tab_to_file(fp, 3);
|
||||
fp << "</" << XML_CLOCK_TREE_TAPS_NODE_NAME << ">\n";
|
||||
|
|
Loading…
Reference in New Issue