diff --git a/openfpga/src/annotation/annotate_pb_graph.cpp b/openfpga/src/annotation/annotate_pb_graph.cpp index 92f1b90b2..d720426cc 100644 --- a/openfpga/src/annotation/annotate_pb_graph.cpp +++ b/openfpga/src/annotation/annotate_pb_graph.cpp @@ -10,6 +10,7 @@ #include "pb_graph_utils.h" #include "annotate_pb_graph.h" +#include "check_pb_graph_annotation.h" /* begin namespace openfpga */ namespace openfpga { @@ -435,6 +436,9 @@ void annotate_pb_graph(const DeviceContext& vpr_device_ctx, VTR_LOG("Binding operating pb_graph nodes/pins to physical pb_graph nodes/pins...\n"); annotate_physical_pb_graph_node(vpr_device_ctx, vpr_pb_type_annotation); VTR_LOG("Done\n"); + + /* Check each primitive pb_graph_node and pin has been binded to a physical node and pin */ + check_physical_pb_graph_node_annotation(vpr_device_ctx, const_cast(vpr_pb_type_annotation)); } } /* end namespace openfpga */ diff --git a/openfpga/src/annotation/check_pb_graph_annotation.cpp b/openfpga/src/annotation/check_pb_graph_annotation.cpp new file mode 100644 index 000000000..92cabefb4 --- /dev/null +++ b/openfpga/src/annotation/check_pb_graph_annotation.cpp @@ -0,0 +1,124 @@ +/******************************************************************** + * This file includes functions to check the annotation on + * the physical pb_graph_node and pb_graph_pin + *******************************************************************/ +/* Headers from vtrutil library */ +#include "vtr_time.h" +#include "vtr_assert.h" +#include "vtr_log.h" + +#include "pb_type_utils.h" +#include "check_pb_graph_annotation.h" + +/* begin namespace openfpga */ +namespace openfpga { + +/******************************************************************** + * A function to check if a physical pb_graph_pin for a pb_graph_pin + * Print error to log file/screen when checking fails + *******************************************************************/ +static +bool check_physical_pb_graph_pin(t_pb_graph_pin* pb_graph_pin, + const VprPbTypeAnnotation& vpr_pb_type_annotation) { + if (nullptr == vpr_pb_type_annotation.physical_pb_graph_pin(pb_graph_pin)) { + VTR_LOG_ERROR("Found a pb_graph_pin '%s' missing physical pb_graph_pin binding!\n", + pb_graph_pin->port->name); + return false; + } + + return true; +} + +/******************************************************************** + * This function will recursively walk through all the pb_graph nodes + * starting from a top node. + * It aims to check + * - if each primitive pb_graph node has been binded to a physical + * pb_graph_node + * - if each pin of the primitive pb_graph node has been binded to + * a physical graph_pin + *******************************************************************/ +static +void rec_check_vpr_physical_pb_graph_node_annotation(t_pb_graph_node* pb_graph_node, + const VprPbTypeAnnotation& vpr_pb_type_annotation, + size_t& num_err) { + /* Go recursive first until we touch the primitive node */ + if (false == is_primitive_pb_type(pb_graph_node->pb_type)) { + for (int imode = 0; imode < pb_graph_node->pb_type->num_modes; ++imode) { + for (int ipb = 0; ipb < pb_graph_node->pb_type->modes[imode].num_pb_type_children; ++ipb) { + /* Each child may exist multiple times in the hierarchy*/ + for (int jpb = 0; jpb < pb_graph_node->pb_type->modes[imode].pb_type_children[ipb].num_pb; ++jpb) { + rec_check_vpr_physical_pb_graph_node_annotation(&(pb_graph_node->child_pb_graph_nodes[imode][ipb][jpb]), + vpr_pb_type_annotation, num_err); + } + } + } + return; + } + + /* Ensure that the pb_graph_node has been mapped to a physical node */ + t_pb_graph_node* physical_pb_graph_node = vpr_pb_type_annotation.physical_pb_graph_node(pb_graph_node); + if (nullptr == physical_pb_graph_node) { + VTR_LOG_ERROR("Found a pb_graph_node '%s' missing physical pb_graph_node binding!\n", + physical_pb_graph_node->pb_type->name); + num_err++; + return; /* Invalid pointer already, further check is not applicable */ + } + + /* Reach here, we should have a valid pointer to the physical pb_graph_node, + * Check the physical pb_graph_pin for each pin + */ + for (int iport = 0; iport < physical_pb_graph_node->num_input_ports; ++iport) { + for (int ipin = 0; ipin < physical_pb_graph_node->num_input_pins[iport]; ++ipin) { + if (false == check_physical_pb_graph_pin(&(physical_pb_graph_node->input_pins[iport][ipin]), + vpr_pb_type_annotation)) { + num_err++; + } + } + } + + for (int iport = 0; iport < physical_pb_graph_node->num_output_ports; ++iport) { + for (int ipin = 0; ipin < physical_pb_graph_node->num_output_pins[iport]; ++ipin) { + if (false == check_physical_pb_graph_pin(&(physical_pb_graph_node->output_pins[iport][ipin]), + vpr_pb_type_annotation)) { + num_err++; + } + } + } + + for (int iport = 0; iport < physical_pb_graph_node->num_clock_ports; ++iport) { + for (int ipin = 0; ipin < physical_pb_graph_node->num_clock_pins[iport]; ++ipin) { + if (false == check_physical_pb_graph_pin(&(physical_pb_graph_node->clock_pins[iport][ipin]), + vpr_pb_type_annotation)) { + num_err++; + } + } + } +} + +/******************************************************************** + * Check each primitive pb_graph_node + * - It has been binded to an physical pb_graph_node + * - Each pin has been binded to a physical pb_graph_node pin + *******************************************************************/ +void check_physical_pb_graph_node_annotation(const DeviceContext& vpr_device_ctx, + const VprPbTypeAnnotation& vpr_pb_type_annotation) { + size_t num_err = 0; + + for (const t_logical_block_type& lb_type : vpr_device_ctx.logical_block_types) { + /* By pass nullptr for pb_graph head */ + if (nullptr == lb_type.pb_graph_head) { + continue; + } + rec_check_vpr_physical_pb_graph_node_annotation(lb_type.pb_graph_head, vpr_pb_type_annotation, num_err); + } + + if (0 == num_err) { + VTR_LOG("Check pb_graph annotation for physical nodes and pins passed.\n"); + } else { + VTR_LOG_ERROR("Check pb_graph annotation for physical nodes and pins failed with %ld errors!\n", + num_err); + } +} + +} /* end namespace openfpga */ diff --git a/openfpga/src/annotation/check_pb_graph_annotation.h b/openfpga/src/annotation/check_pb_graph_annotation.h new file mode 100644 index 000000000..c482943c5 --- /dev/null +++ b/openfpga/src/annotation/check_pb_graph_annotation.h @@ -0,0 +1,23 @@ +#ifndef CHECK_PB_GRAPH_ANNOTATION_H +#define CHECK_PB_GRAPH_ANNOTATION_H + +/******************************************************************** + * Include header files that are required by function declaration + *******************************************************************/ +#include "vpr_context.h" +#include "openfpga_context.h" +#include "vpr_pb_type_annotation.h" + +/******************************************************************** + * Function declaration + *******************************************************************/ + +/* begin namespace openfpga */ +namespace openfpga { + +void check_physical_pb_graph_node_annotation(const DeviceContext& vpr_device_ctx, + const VprPbTypeAnnotation& vpr_pb_type_annotation); + +} /* end namespace openfpga */ + +#endif