diff --git a/libs/CMakeLists.txt b/libs/CMakeLists.txt index 2c043b5ef..a871fa27e 100644 --- a/libs/CMakeLists.txt +++ b/libs/CMakeLists.txt @@ -1,6 +1,7 @@ # OpenFPGA-related libraries add_subdirectory(libini) add_subdirectory(libopenfpgashell) +add_subdirectory(libclkarchopenfpga) add_subdirectory(libarchopenfpga) add_subdirectory(libopenfpgautil) add_subdirectory(libfabrickey) diff --git a/libs/libclkarchopenfpga/src/base/clock_network.cpp b/libs/libclkarchopenfpga/src/base/clock_network.cpp index 244a1a9c0..3c2915f78 100644 --- a/libs/libclkarchopenfpga/src/base/clock_network.cpp +++ b/libs/libclkarchopenfpga/src/base/clock_network.cpp @@ -38,6 +38,15 @@ size_t ClockNetwork::tree_width(const ClockTreeId& tree_id) const { return tree_widths_[tree_id]; } +size_t ClockNetwork::tree_depth(const ClockTreeId& tree_id) const { + VTR_ASSERT(valid_tree_id(tree_id)); + if (is_dirty_) { + VTR_LOG_ERROR("Unable to identify tree depth when data is still dirty!\n"); + exit(1); + } + return tree_depths_[tree_id]; +} + std::vector ClockNetwork::spines(const ClockTreeId& tree_id) const { std::vector ret; for (ClockSpineId spine_id : spine_ids_) { @@ -94,6 +103,8 @@ bool ClockNetwork::find_spine(const std::string& name) const { bool ClockNetwork::empty() const { return 0 == tree_ids_.size(); } +bool ClockNetwork::is_valid() const { return !is_dirty_; } + /************************************************************************ * Public Mutators ***********************************************************************/ @@ -124,6 +135,7 @@ ClockTreeId ClockNetwork::create_tree(const std::string& name, const size_t& wid tree_ids_.push_back(tree_id); tree_names_.push_back(name); tree_widths_.push_back(width); + tree_depths_.emplace_back(); tree_top_spines_.emplace_back(); /* Register to fast look-up */ @@ -212,11 +224,13 @@ void ClockNetwork::add_spine_switch_point(const ClockSpineId& spine_id, const Cl } bool ClockNetwork::link() { + is_dirty_ = true; for (ClockTreeId& tree_id : trees()) { if (!link_tree(tree_id)) { return false; } } + is_dirty_ = false; return true; } @@ -227,6 +241,9 @@ bool ClockNetwork::link_tree(const ClockTreeId& tree_id) { if (!sort_tree_spines(tree_id)) { return false; } + if (!update_tree_depth(tree_id)) { + return false; + } return true; } @@ -247,6 +264,7 @@ bool ClockNetwork::sort_tree_spines(const ClockTreeId& tree_id) { spine_levels_[spine_id] = 0; rec_update_spine_level(spine_id); } + return true; } bool ClockNetwork::rec_update_spine_level(const ClockSpineId& spine_id) { @@ -254,6 +272,16 @@ bool ClockNetwork::rec_update_spine_level(const ClockSpineId& spine_id) { spine_levels_[child_spine_id] = spine_levels_[spine_id] + 1; rec_update_spine_level(child_spine_id); } + return true; +} + +bool ClockNetwork::update_tree_depth(const ClockTreeId& tree_id) { + size_t depth = 0; + for (ClockSpineId spine_id : tree_spines_[tree_id]) { + depth = std::max(depth, spine_levels_[spine_id]); + } + tree_depths_[tree_id] = depth; + return true; } /************************************************************************ diff --git a/libs/libclkarchopenfpga/src/base/clock_network.h b/libs/libclkarchopenfpga/src/base/clock_network.h index 7a7e33616..316815694 100644 --- a/libs/libclkarchopenfpga/src/base/clock_network.h +++ b/libs/libclkarchopenfpga/src/base/clock_network.h @@ -53,6 +53,7 @@ class ClockNetwork { public: /* Public Accessors: Basic data query */ std::string tree_name(const ClockTreeId& tree_id) const; size_t tree_width(const ClockTreeId& tree_id) const; + size_t tree_depth(const ClockTreeId& tree_id) const; std::string spine_name(const ClockSpineId& spine_id) const; vtr::Point spine_start_point(const ClockSpineId& spine_id) const; vtr::Point spine_end_point(const ClockSpineId& spine_id) const; @@ -64,6 +65,7 @@ class ClockNetwork { ClockSpineId find_spine(const std::string& name) const; /* Check if there are clock tree */ bool empty() const; + bool is_valid() const; public: /* Public Mutators */ /* Reserve a number of spines to be memory efficent */ @@ -98,12 +100,15 @@ class ClockNetwork { /* Require link_tree_top_spines() to called before! */ bool sort_tree_spines(const ClockTreeId& tree_id); bool rec_update_spine_level(const ClockSpineId& spine_id); + /* Require sort_tree_spines() to called before! */ + bool update_tree_depth(const ClockTreeId& tree_id); private: /* Internal data */ /* Basic information of each tree */ vtr::vector tree_ids_; vtr::vector tree_names_; vtr::vector tree_widths_; + vtr::vector tree_depths_; vtr::vector> tree_top_spines_; /* Basic information of each spine */ diff --git a/libs/libclkarchopenfpga/test/xml_io_clock_network.cpp b/libs/libclkarchopenfpga/test/xml_io_clock_network.cpp index 60655bdd0..81da04ea3 100644 --- a/libs/libclkarchopenfpga/test/xml_io_clock_network.cpp +++ b/libs/libclkarchopenfpga/test/xml_io_clock_network.cpp @@ -21,11 +21,14 @@ int main(int argc, const char** argv) { clk_ntwk.trees().size()); /* Validate before write out */ - clk_ntwk.validate(); - if (!clk_ntwk.is_valid()) { + if (!clk_ntwk.link()) { VTR_LOG_ERROR("Invalid clock network.\n"); exit(1); } + VTR_ASSERT(clk_ntwk.is_valid()); + for (auto tree_id : clk_ntwk.trees()) { + VTR_LOG("Max. depth of the clock tree '%lu' is %d", size_t(tree_id), clk_ntwk.tree_depth(tree_id)); + } /* Output the bus group to an XML file * This is optional only used when there is a second argument