[core] developing validators and annotate rr_segment for clock arch
This commit is contained in:
parent
4bd952027f
commit
780fc0f26d
|
@ -20,6 +20,7 @@ set_target_properties(libclkarchopenfpga PROPERTIES PREFIX "") #Avoid extra 'lib
|
|||
#Specify link-time dependancies
|
||||
target_link_libraries(libclkarchopenfpga
|
||||
libopenfpgautil
|
||||
libopenfpgashell
|
||||
libarchopenfpga
|
||||
librrgraph
|
||||
libvtrutil
|
||||
|
|
|
@ -14,7 +14,11 @@ namespace openfpga { // Begin namespace openfpga
|
|||
/************************************************************************
|
||||
* Constructors
|
||||
***********************************************************************/
|
||||
ClockNetwork::ClockNetwork() { is_dirty_ = true; }
|
||||
ClockNetwork::ClockNetwork() {
|
||||
default_segment_id_ = RRSegmentId::INVALID();
|
||||
default_switch_id_ = RRSwitchId::INVALID();
|
||||
is_dirty_ = true;
|
||||
}
|
||||
|
||||
/************************************************************************
|
||||
* Public Accessors : aggregates
|
||||
|
@ -115,6 +119,10 @@ std::string ClockNetwork::default_segment_name() const {
|
|||
return default_segment_name_;
|
||||
}
|
||||
|
||||
RRSegmentId ClockNetwork::default_segment() const {
|
||||
return default_segment_id_;
|
||||
}
|
||||
|
||||
std::string ClockNetwork::default_switch_name() const {
|
||||
return default_switch_name_;
|
||||
}
|
||||
|
@ -227,6 +235,10 @@ void ClockNetwork::reserve_trees(const size_t& num_trees) {
|
|||
tree_top_spines_.reserve(num_trees);
|
||||
}
|
||||
|
||||
void ClockNetwork::set_default_segment(const RRSegmentId& seg_id) {
|
||||
default_segment_id_ = seg_id;
|
||||
}
|
||||
|
||||
void ClockNetwork::set_default_segment_name(const std::string& name) {
|
||||
default_segment_name_ = name;
|
||||
}
|
||||
|
@ -339,13 +351,46 @@ void ClockNetwork::add_spine_switch_point(const ClockSpineId& spine_id,
|
|||
}
|
||||
|
||||
bool ClockNetwork::link() {
|
||||
is_dirty_ = true;
|
||||
for (ClockTreeId tree_id : trees()) {
|
||||
if (!link_tree(tree_id)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ClockNetwork::validate_tree() const {
|
||||
for (ClockTreeId tree_id : trees()) {
|
||||
for (ClockSpineId spine_id : spines(tree_id)) {
|
||||
for (ClockSwitchPointId switch_point_id : spine_switch_points(spine_id)) {
|
||||
if (!valid_spine_switch_point_id(spine_id, switch_point_id)) {
|
||||
VTR_LOG_ERROR(
|
||||
"Spine '%s' contains invalid switching point (%lu, %lu)\n",
|
||||
spine_name(spine_id).c_str(),
|
||||
spine_switch_point(spine_id, switch_point_id).x(),
|
||||
spine_switch_point(spine_id, switch_point_id).y());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (!valid_spine_start_end_points(spine_id)) {
|
||||
VTR_LOG_ERROR(
|
||||
"Spine '%s' contains invalid starting point (%lu, %lu) or ending "
|
||||
"point (%lu, %lu)\n",
|
||||
spine_name(spine_id).c_str(), spine_start_point(spine_id).x(),
|
||||
spine_start_point(spine_id).y(), spine_end_point(spine_id).x(),
|
||||
spine_end_point(spine_id).y());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ClockNetwork::validate() const {
|
||||
is_dirty_ = true;
|
||||
if (default_segment_id_ && default_switch_id_ && validate_tree()) {
|
||||
is_dirty_ = false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -62,6 +62,9 @@ class ClockNetwork {
|
|||
size_t num_tracks(const ClockTreeId& tree_id, const ClockLevelId& level,
|
||||
const t_rr_type& track_type,
|
||||
const Direction& direction) const;
|
||||
/* Return the id of default routing segment, use this to find detailed segment
|
||||
* information from RRGraph */
|
||||
RRSegmentId default_segment() const;
|
||||
std::string default_segment_name() const;
|
||||
std::string default_switch_name() const;
|
||||
std::string tree_name(const ClockTreeId& tree_id) const;
|
||||
|
@ -106,6 +109,7 @@ class ClockNetwork {
|
|||
void reserve_spines(const size_t& num_spines);
|
||||
/* Reserve a number of trees to be memory efficent */
|
||||
void reserve_trees(const size_t& num_trees);
|
||||
void set_default_segment(const RRSegmentId& seg_id);
|
||||
void set_default_segment_name(const std::string& name);
|
||||
void set_default_switch_name(const std::string& name);
|
||||
/* Create a new tree, by default the tree can accomodate only 1 clock signal;
|
||||
|
@ -145,6 +149,14 @@ 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;
|
||||
/* Validate the internal data. Required to ensure clean data before usage. If
|
||||
* validation is successful, is_valid() will return true */
|
||||
bool validate() const;
|
||||
|
||||
private: /* Public invalidators/validators */
|
||||
/* Ensure tree data is clean. All the spines are valid, and switch points are
|
||||
* valid */
|
||||
bool validate_tree() const;
|
||||
|
||||
private: /* Private mutators */
|
||||
/* Build internal links between spines under a given tree */
|
||||
|
@ -189,7 +201,7 @@ class ClockNetwork {
|
|||
std::map<std::string, ClockSpineId> spine_name2id_map_;
|
||||
|
||||
/* Flags */
|
||||
bool is_dirty_;
|
||||
mutable bool is_dirty_;
|
||||
};
|
||||
|
||||
} // End of namespace openfpga
|
||||
|
|
|
@ -0,0 +1,29 @@
|
|||
#include "clock_network_utils.h"
|
||||
|
||||
#include "command_exit_codes.h"
|
||||
#include "vtr_assert.h"
|
||||
#include "vtr_time.h"
|
||||
|
||||
namespace openfpga { // Begin namespace openfpga
|
||||
|
||||
/********************************************************************
|
||||
* Link all the segments that are defined in a routing resource graph to a given
|
||||
*clock network
|
||||
*******************************************************************/
|
||||
int link_clock_network_rr_segments(ClockNetwork& clk_ntwk,
|
||||
const RRGraphView& rr_graph) {
|
||||
/* default segment id */
|
||||
std::string default_segment_name = clk_ntwk.default_segment_name();
|
||||
for (size_t rr_seg_id = 0; rr_seg_id < rr_graph.num_rr_segments();
|
||||
++rr_seg_id) {
|
||||
if (rr_graph.rr_segments(RRSegmentId(rr_seg_id)).name ==
|
||||
default_segment_name) {
|
||||
clk_ntwk.set_default_segment(RRSegmentId(rr_seg_id));
|
||||
return CMD_EXEC_SUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
return CMD_EXEC_FATAL_ERROR;
|
||||
}
|
||||
|
||||
} // End of namespace openfpga
|
|
@ -0,0 +1,21 @@
|
|||
#ifndef CLOCK_NETWORK_UTILS_H
|
||||
#define CLOCK_NETWORK_UTILS_H
|
||||
|
||||
/********************************************************************
|
||||
* Include header files that are required by function declaration
|
||||
*******************************************************************/
|
||||
#include "clock_network.h"
|
||||
#include "rr_graph_view.h"
|
||||
|
||||
/********************************************************************
|
||||
* Function declaration
|
||||
*******************************************************************/
|
||||
|
||||
namespace openfpga { // Begin namespace openfpga
|
||||
|
||||
int link_clock_network_rr_segments(ClockNetwork& clk_ntwk,
|
||||
const RRGraphView& rr_graph);
|
||||
|
||||
} // End of namespace openfpga
|
||||
|
||||
#endif
|
|
@ -116,7 +116,6 @@ static void add_rr_graph_block_clock_nodes(RRGraphBuilder& rr_graph_builder,
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
/********************************************************************
|
||||
* Add clock nodes one by one to the routing resource graph.
|
||||
* Assign node-level attributes properly
|
||||
|
@ -182,16 +181,17 @@ void add_rr_graph_block_clock_edges(RRGraphBuilder& rr_graph_builder,
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
/********************************************************************
|
||||
* Add edges to interconnect clock nodes
|
||||
* Walk through the routing tracks in each connection block (driver nodes)
|
||||
* and add edge to their fan-out clock nodes
|
||||
* Note that
|
||||
* - clock nodes at the same level of a clock tree can only go straight
|
||||
* - clock nodes can only drive clock nodes belong to the same clock index (a clock tree may contain multiple clocks)
|
||||
* - clock nodes can only drive clock nodes (by making a turn, straight connection is not allowed) which are 1 level lower in the same clock tree with the same clock index
|
||||
* For example
|
||||
* - clock nodes can only drive clock nodes belong to the same clock index (a
|
||||
*clock tree may contain multiple clocks)
|
||||
* - clock nodes can only drive clock nodes (by making a turn, straight
|
||||
*connection is not allowed) which are 1 level lower in the same clock tree with
|
||||
*the same clock index For example
|
||||
*
|
||||
* clk0_lvl1_chany[1][2]
|
||||
* ^
|
||||
|
@ -235,7 +235,6 @@ void add_rr_graph_clock_edges(RRGraphBuilder& rr_graph_builder,
|
|||
chany_coord, CHANY);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/********************************************************************
|
||||
|
@ -262,7 +261,8 @@ int append_clock_rr_graph(DeviceContext& vpr_device_ctx,
|
|||
/* Report any clock structure we do not support yet! */
|
||||
if (clk_ntwk.num_trees() > 1) {
|
||||
VTR_LOG(
|
||||
"Currently only support 1 clock tree in programmable clock architecture\nPlease update your clock architecture definition\n");
|
||||
"Currently only support 1 clock tree in programmable clock "
|
||||
"architecture\nPlease update your clock architecture definition\n");
|
||||
return CMD_EXEC_FATAL_ERROR;
|
||||
}
|
||||
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
#include "check_circuit_library.h"
|
||||
#include "check_tile_annotation.h"
|
||||
#include "circuit_library_utils.h"
|
||||
#include "clock_network_utils.h"
|
||||
#include "command.h"
|
||||
#include "command_context.h"
|
||||
#include "command_exit_codes.h"
|
||||
|
@ -236,6 +237,14 @@ int read_openfpga_clock_arch_template(T& openfpga_context, const Command& cmd,
|
|||
read_xml_clock_network(arch_file_name.c_str());
|
||||
/* Build internal links */
|
||||
openfpga_context.mutable_clock_arch().link();
|
||||
link_clock_network_rr_segments(openfpga_context.mutable_clock_arch(),
|
||||
g_vpr_ctx.device().rr_graph);
|
||||
/* Ensure clean data */
|
||||
openfpga_context.clock_arch().validate();
|
||||
if (!openfpga_context.clock_arch().is_valid()) {
|
||||
VTR_LOG_ERROR("Pre-checking clock architecture failed!");
|
||||
return CMD_EXEC_FATAL_ERROR;
|
||||
}
|
||||
|
||||
/* TODO: should identify the error code from internal function execution */
|
||||
return CMD_EXEC_SUCCESS;
|
||||
|
|
Loading…
Reference in New Issue