diff --git a/openfpga/src/repack/build_physical_lb_rr_graph.cpp b/openfpga/src/repack/build_physical_lb_rr_graph.cpp index aca8cb0d1..e79985082 100644 --- a/openfpga/src/repack/build_physical_lb_rr_graph.cpp +++ b/openfpga/src/repack/build_physical_lb_rr_graph.cpp @@ -395,6 +395,13 @@ void build_physical_lb_rr_graphs(const DeviceContext& device_ctx, lb_type.pb_graph_head->pb_type->name); const LbRRGraph& lb_rr_graph = build_lb_type_physical_lb_rr_graph(lb_type.pb_graph_head, const_cast(device_annotation), verbose); + /* Check the rr_graph */ + if (false == lb_rr_graph.validate()) { + exit(1); + } + VTR_LOGV(verbose, + "Check routing resource graph for logical tile passed\n"); + device_annotation.add_physical_lb_rr_graph(lb_type.pb_graph_head, lb_rr_graph); } diff --git a/openfpga/src/repack/lb_rr_graph.cpp b/openfpga/src/repack/lb_rr_graph.cpp index 434ac0b3e..db43543da 100644 --- a/openfpga/src/repack/lb_rr_graph.cpp +++ b/openfpga/src/repack/lb_rr_graph.cpp @@ -262,4 +262,195 @@ bool LbRRGraph::valid_edge_id(const LbRREdgeId& edge_id) const { return ( size_t(edge_id) < edge_ids_.size() ) && ( edge_id == edge_ids_[edge_id] ); } +/* This function run fundamental checks on internal data + * Errors are thrown if fundamental checking fails + */ +bool LbRRGraph::validate() const { + size_t num_err = 0; + + /* Validate the sizes of nodes and node-related vectors + * Validate the sizes of edges and edge-related vectors + */ + if (false == validate_sizes()) { + VTR_LOG_WARN("Fail in validating node and edges sizes!\n"); + num_err++; + } + + /* Fundamental check */ + if (false == validate_nodes_edges()) { + VTR_LOG_WARN("Fail in validating edges connected to each node!\n"); + num_err++; + } + + /* Error out if there is any fatal errors found */ + if (0 < num_err) { + VTR_LOG_ERROR("Logical tile Routing Resource graph is not valid due to %d fatal errors !\n", + num_err); + } + + return (0 == num_err); +} + +/****************************************************************************** + * Private validators/invalidators + ******************************************************************************/ +bool LbRRGraph::validate_node_sizes() const { + size_t num_nodes = node_ids_.size(); + return node_ids_.size() == num_nodes + && node_types_.size() == num_nodes + && node_capacities_.size() == num_nodes + && node_pb_graph_pins_.size() == num_nodes + && node_intrinsic_costs_.size() == num_nodes + && node_in_edges_.size() == num_nodes + && node_out_edges_.size() == num_nodes; +} + +bool LbRRGraph::validate_edge_sizes() const { + size_t num_edges = edge_ids_.size(); + return edge_src_nodes_.size() == num_edges + && edge_sink_nodes_.size() == num_edges + && edge_intrinsic_costs_.size() == num_edges + && edge_modes_.size() == num_edges; +} + +bool LbRRGraph::validate_sizes() const { + return validate_node_sizes() && validate_edge_sizes(); +} + +/* Check if a node is in the list of source_nodes of a edge */ +bool LbRRGraph::validate_node_is_edge_src(const LbRRNodeId& node, const LbRREdgeId& edge) const { + /* Assure a valid node id */ + VTR_ASSERT_SAFE(valid_node_id(node)); + /* assure a valid edge id */ + VTR_ASSERT_SAFE(valid_edge_id(edge)); + /* find if the node is the src */ + if (node == edge_src_node(edge)) { + return true; /* confirmed source node*/ + } else { + return false; /* not a source */ + } +} + +/* Check if a node is in the list of sink_nodes of a edge */ +bool LbRRGraph::validate_node_is_edge_sink(const LbRRNodeId& node, const LbRREdgeId& edge) const { + /* Assure a valid node id */ + VTR_ASSERT_SAFE(valid_node_id(node)); + /* assure a valid edge id */ + VTR_ASSERT_SAFE(valid_edge_id(edge)); + /* find if the node is the sink */ + if (node == edge_sink_node(edge)) { + return true; /* confirmed source node*/ + } else { + return false; /* not a source */ + } +} +/* This function will check if a node has valid input edges + * 1. Check the edge ids are valid + * 2. Check the node is in the list of edge_sink_node + */ +bool LbRRGraph::validate_node_in_edges(const LbRRNodeId& node) const { + bool all_valid = true; + /* Assure a valid node id */ + VTR_ASSERT_SAFE(valid_node_id(node)); + /* Check each edge */ + for (auto edge : node_in_edges(node)) { + /* assure a valid edge id */ + VTR_ASSERT_SAFE(valid_edge_id(edge)); + /* check the node is in the list of edge_sink_node */ + if (true == validate_node_is_edge_sink(node, edge)) { + continue; + } + /* Reach here, it means there is something wrong! + * Print a warning + */ + VTR_LOG_WARN("Edge %d is in the input edge list of node %d while the node is not in edge's sink node list!\n", + size_t(edge), size_t(node)); + all_valid = false; + } + + return all_valid; +} + +/* This function will check if a node has valid output edges + * 1. Check the edge ids are valid + * 2. Check the node is in the list of edge_source_node + */ +bool LbRRGraph::validate_node_out_edges(const LbRRNodeId& node) const { + bool all_valid = true; + /* Assure a valid node id */ + VTR_ASSERT_SAFE(valid_node_id(node)); + /* Check each edge */ + for (auto edge : node_out_edges(node)) { + /* assure a valid edge id */ + VTR_ASSERT_SAFE(valid_edge_id(edge)); + /* check the node is in the list of edge_sink_node */ + if (true == validate_node_is_edge_src(node, edge)) { + continue; + } + /* Reach here, it means there is something wrong! + * Print a warning + */ + VTR_LOG_WARN("Edge %d is in the output edge list of node %d while the node is not in edge's source node list!\n", + size_t(edge), size_t(node)); + all_valid = false; + } + + return all_valid; +} + + +/* check if all the nodes' input edges are valid */ +bool LbRRGraph::validate_nodes_in_edges() const { + bool all_valid = true; + for (const LbRRNodeId& id : nodes()) { + /* Try to find if this is an invalid id or not */ + if (!valid_node_id(id)) { + /* Skip this id */ + continue; + } + if (true == validate_node_in_edges(id)) { + continue; + } + /* Reach here, it means there is something wrong! + * Print a warning + */ + all_valid = false; + } + return all_valid; +} + +/* check if all the nodes' output edges are valid */ +bool LbRRGraph::validate_nodes_out_edges() const { + bool all_valid = true; + for (const LbRRNodeId& id : nodes()) { + /* Try to find if this is an invalid id or not */ + if (!valid_node_id(id)) { + /* Skip this id */ + continue; + } + if (true == validate_node_out_edges(id)) { + continue; + } + /* Reach here, it means there is something wrong! + * Print a warning + */ + all_valid = false; + } + return all_valid; +} + +/* check all the edges of every node */ +bool LbRRGraph::validate_nodes_edges() const { + bool all_valid = true; + + if (false == validate_nodes_in_edges()) { + all_valid = false; + } + if (false == validate_nodes_out_edges()) { + all_valid = false; + } + + return all_valid; +} + } /* end namespace openfpga */ diff --git a/openfpga/src/repack/lb_rr_graph.h b/openfpga/src/repack/lb_rr_graph.h index 4500a504b..3aca85934 100644 --- a/openfpga/src/repack/lb_rr_graph.h +++ b/openfpga/src/repack/lb_rr_graph.h @@ -266,13 +266,27 @@ class LbRRGraph { LbRREdgeId create_edge(const LbRRNodeId& source, const LbRRNodeId& sink, t_mode* mode); void set_edge_intrinsic_cost(const LbRREdgeId& edge, const float& cost); - public: /* Validators */ + public: /* Public validators */ /* Validate is the node id does exist in the RRGraph */ bool valid_node_id(const LbRRNodeId& node) const; /* Validate is the edge id does exist in the RRGraph */ bool valid_edge_id(const LbRREdgeId& edge) const; + bool validate() const; + + private: /* Private Validators */ + bool validate_node_sizes() const; + bool validate_edge_sizes() const; + bool validate_sizes() const; + bool validate_node_is_edge_src(const LbRRNodeId& node, const LbRREdgeId& edge) const; + bool validate_node_is_edge_sink(const LbRRNodeId& node, const LbRREdgeId& edge) const; + bool validate_node_in_edges(const LbRRNodeId& node) const; + bool validate_node_out_edges(const LbRRNodeId& node) const; + bool validate_nodes_in_edges() const; + bool validate_nodes_out_edges() const; + bool validate_nodes_edges() const; + private: /* Internal Data */ /* Node related data */ vtr::vector node_ids_;