From d8ab5536e110324343e02f6cf2d4718f0fee2f15 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Wed, 19 Feb 2020 21:41:05 -0700 Subject: [PATCH] add advanced check codes for lb_rr_graph --- .../src/repack/build_physical_lb_rr_graph.cpp | 4 + openfpga/src/repack/check_lb_rr_graph.cpp | 206 ++++++++++++++++++ openfpga/src/repack/check_lb_rr_graph.h | 21 ++ openfpga/src/repack/lb_rr_graph_utils.cpp | 13 ++ openfpga/src/repack/lb_rr_graph_utils.h | 3 + 5 files changed, 247 insertions(+) create mode 100644 openfpga/src/repack/check_lb_rr_graph.cpp create mode 100644 openfpga/src/repack/check_lb_rr_graph.h diff --git a/openfpga/src/repack/build_physical_lb_rr_graph.cpp b/openfpga/src/repack/build_physical_lb_rr_graph.cpp index e79985082..ae9fc4c65 100644 --- a/openfpga/src/repack/build_physical_lb_rr_graph.cpp +++ b/openfpga/src/repack/build_physical_lb_rr_graph.cpp @@ -10,6 +10,7 @@ #include "pb_type_utils.h" #include "build_physical_lb_rr_graph.h" +#include "check_lb_rr_graph.h" /* begin namespace openfpga */ namespace openfpga { @@ -399,6 +400,9 @@ void build_physical_lb_rr_graphs(const DeviceContext& device_ctx, if (false == lb_rr_graph.validate()) { exit(1); } + if (false == check_lb_rr_graph(lb_rr_graph)) { + exit(1); + } VTR_LOGV(verbose, "Check routing resource graph for logical tile passed\n"); diff --git a/openfpga/src/repack/check_lb_rr_graph.cpp b/openfpga/src/repack/check_lb_rr_graph.cpp new file mode 100644 index 000000000..9b3adbf8f --- /dev/null +++ b/openfpga/src/repack/check_lb_rr_graph.cpp @@ -0,0 +1,206 @@ +#include + +#include "vtr_log.h" + +#include "lb_rr_graph_utils.h" +#include "check_lb_rr_graph.h" + +/* begin namespace openfpga */ +namespace openfpga { + +/*********************************************************************** + * This function aims at checking any duplicated edges (with same EdgeId) + * of a given node. + * We will walkthrough the input edges of a node and see if there is any duplication + **********************************************************************/ +static bool check_lb_rr_graph_node_duplicated_edges(const LbRRGraph& lb_rr_graph, + const LbRRNodeId& node) { + bool no_duplication = true; + + /* Create a map for each input edge */ + std::map> edge_counter; + + /* Check each input edges */ + for (const auto edge : lb_rr_graph.node_in_edges(node)) { + if (nullptr == lb_rr_graph.edge_mode(edge)) { + continue; + } + auto result = edge_counter[lb_rr_graph.edge_mode(edge)].insert(std::pair(edge, 1)); + if (false == result.second) { + result.first->second++; + } + } + + for (auto& edge_mode : edge_counter) { + for (auto& elem : edge_mode.second) { + if (elem.second > 1) { + /* Reach here it means we find some duplicated edges and report errors */ + /* Print a warning! */ + VTR_LOG_WARN("Node %d has duplicated input edges (id = %d)!\n", + size_t(node), size_t(elem.first)); + print_lb_rr_node(lb_rr_graph, node); + no_duplication = false; + } + } + } + + return no_duplication; +} + +/*********************************************************************** + * Check the whole Routing Resource Graph + * identify and report any duplicated edges between two nodes + **********************************************************************/ +static bool check_lb_rr_graph_duplicated_edges(const LbRRGraph& lb_rr_graph) { + bool no_duplication = true; + /* For each node: + * Search input edges, see there are two edges with same id or address + */ + for (const auto& node : lb_rr_graph.nodes()) { + if (false == check_lb_rr_graph_node_duplicated_edges(lb_rr_graph, node)) { + no_duplication = false; + } + } + + return no_duplication; +} + +/*********************************************************************** + * Identify and report any dangling node (nodes without any fan-in or fan-out) + * in the LbRRGraph + **********************************************************************/ +static bool check_lb_rr_graph_dangling_nodes(const LbRRGraph& lb_rr_graph) { + bool no_dangling = true; + /* For each node: + * check if the number of input edges and output edges are both 0 + * If so, this is a dangling nodes and report + */ + for (auto node : lb_rr_graph.nodes()) { + if ((0 == lb_rr_graph.node_in_edges(node).size()) + && (0 == lb_rr_graph.node_out_edges(node).size())) { + /* Print a warning! */ + VTR_LOG_WARN("Node %s is dangling (zero fan-in and zero fan-out)!\n", + node); + VTR_LOG_WARN("Node details for debugging:\n"); + print_lb_rr_node(lb_rr_graph, node); + no_dangling = false; + } + } + + return no_dangling; +} + +/*********************************************************************** + * check if all the source nodes are in the right condition: + * 1. zero fan-in and non-zero fanout + **********************************************************************/ +static bool check_lb_rr_graph_source_nodes(const LbRRGraph& lb_rr_graph) { + bool invalid_sources = false; + /* For each node: + * check if the number of input edges and output edges are both 0 + * If so, this is a dangling nodes and report + */ + for (auto node : lb_rr_graph.nodes()) { + /* Pass nodes whose types are not LB_SOURCE */ + if (LB_SOURCE != lb_rr_graph.node_type(node)) { + continue; + } + if ((0 != lb_rr_graph.node_in_edges(node).size()) + || (0 == lb_rr_graph.node_out_edges(node).size())) { + /* Print a warning! */ + VTR_LOG_WARN("Source node %d is invalid (should have zero fan-in and non-zero fan-out)!\n", + size_t(node)); + VTR_LOG_WARN("Node details for debugging:\n"); + print_lb_rr_node(lb_rr_graph, node); + invalid_sources = true; + } + } + + return !invalid_sources; +} + +/*********************************************************************** + * check if all the sink nodes are in the right condition: + * 1. non-zero fan-in and zero fanout + **********************************************************************/ +static bool check_lb_rr_graph_sink_nodes(const LbRRGraph& lb_rr_graph) { + bool invalid_sinks = false; + /* For each node: + * check if the number of input edges and output edges are both 0 + * If so, this is a dangling nodes and report + */ + for (auto node : lb_rr_graph.nodes()) { + /* Pass nodes whose types are not LB_SINK */ + if (LB_SINK != lb_rr_graph.node_type(node)) { + continue; + } + if ((0 == lb_rr_graph.node_in_edges(node).size()) + || (0 != lb_rr_graph.node_out_edges(node).size())) { + /* Print a warning! */ + VTR_LOG_WARN("Sink node %s is invalid (should have non-zero fan-in and zero fan-out)!\n", + node); + VTR_LOG_WARN("Node details for debugging:\n"); + print_lb_rr_node(lb_rr_graph, node); + invalid_sinks = true; + } + } + + return !invalid_sinks; +} + +/*********************************************************************** + * This is an advanced checker for LbRRGraph object + * Note that the checker try to report as many problems as it can. + * The problems may cause routing efficiency or even failures, depending + * on routing algorithms. + * It is strongly suggested to run this sanitizer before conducting + * routing algorithms + * + * For those who will develop customized lb_rr_graphs and routers: + * On the other hand, it is suggested that developers to create their + * own checking function for the lb_rr_graph, to guarantee their routers + * will work properly. + **********************************************************************/ +bool check_lb_rr_graph(const LbRRGraph& lb_rr_graph) { + size_t num_err = 0; + + if (false == check_lb_rr_graph_duplicated_edges(lb_rr_graph)) { + VTR_LOG_WARN("Fail in checking duplicated edges !\n"); + num_err++; + } + + if (false == check_lb_rr_graph_dangling_nodes(lb_rr_graph)) { + VTR_LOG_WARN("Fail in checking dangling nodes !\n"); + num_err++; + } + + if (false == check_lb_rr_graph_source_nodes(lb_rr_graph)) { + VTR_LOG_WARN("Fail in checking source nodes!\n"); + num_err++; + } + + if (false == check_lb_rr_graph_sink_nodes(lb_rr_graph)) { + VTR_LOG_WARN("Fail in checking sink nodes!\n"); + num_err++; + } + + if (false == check_lb_rr_graph_source_nodes(lb_rr_graph)) { + VTR_LOG_WARN("Fail in checking source nodes!\n"); + num_err++; + } + + if (false == check_lb_rr_graph_sink_nodes(lb_rr_graph)) { + VTR_LOG_WARN("Fail in checking sink nodes!\n"); + num_err++; + } + + /* Error out if there is any fatal errors found */ + if (0 < num_err) { + VTR_LOG_WARN("Checked Logical tile Routing Resource graph with %d errors !\n", + num_err); + } + + return (0 == num_err); +} + +} /* end namespace openfpga */ diff --git a/openfpga/src/repack/check_lb_rr_graph.h b/openfpga/src/repack/check_lb_rr_graph.h new file mode 100644 index 000000000..232fa597c --- /dev/null +++ b/openfpga/src/repack/check_lb_rr_graph.h @@ -0,0 +1,21 @@ +#ifndef CHECK_LB_RR_GRAPH_H +#define CHECK_LB_RR_GRAPH_H + +/******************************************************************** + * Include header files that are required by function declaration + *******************************************************************/ +#include "lb_rr_graph.h" + + +/******************************************************************** + * Function declaration + *******************************************************************/ + +/* begin namespace openfpga */ +namespace openfpga { + +bool check_lb_rr_graph(const LbRRGraph& rr_graph); + +} /* end namespace openfpga */ + +#endif diff --git a/openfpga/src/repack/lb_rr_graph_utils.cpp b/openfpga/src/repack/lb_rr_graph_utils.cpp index 351103647..a2e1df63a 100644 --- a/openfpga/src/repack/lb_rr_graph_utils.cpp +++ b/openfpga/src/repack/lb_rr_graph_utils.cpp @@ -57,4 +57,17 @@ std::string describe_lb_rr_node(const LbRRGraph& lb_rr_graph, return description; } +/* This function aims to print basic information about a node */ +void print_lb_rr_node(const LbRRGraph& lb_rr_graph, + const LbRRNodeId& node) { + VTR_LOG("Node id: %d\n", size_t(node)); + VTR_LOG("Node type: %s\n", lb_rr_type_str[lb_rr_graph.node_type(node)]); + VTR_LOG("Node capacity: %d\n", lb_rr_graph.node_capacity(node)); + VTR_LOG("Node pb_graph_pin: %s\n", lb_rr_graph.node_pb_graph_pin(node)->to_string().c_str()); + VTR_LOG("Node intrinsic_cost: %f\n", lb_rr_graph.node_intrinsic_cost(node)); + VTR_LOG("Node num in_edges: %ld\n", lb_rr_graph.node_in_edges(node).size()); + VTR_LOG("Node num out_edges: %ld\n", lb_rr_graph.node_out_edges(node).size()); +} + + } /* end namespace openfpga */ diff --git a/openfpga/src/repack/lb_rr_graph_utils.h b/openfpga/src/repack/lb_rr_graph_utils.h index 392617f6a..f493caa4f 100644 --- a/openfpga/src/repack/lb_rr_graph_utils.h +++ b/openfpga/src/repack/lb_rr_graph_utils.h @@ -17,6 +17,9 @@ namespace openfpga { std::string describe_lb_rr_node(const LbRRGraph& lb_rr_graph, const LbRRNodeId& inode); +void print_lb_rr_node(const LbRRGraph& lb_rr_graph, + const LbRRNodeId& node); + } /* end namespace openfpga */ #endif