diff --git a/libs/libarchfpga/src/physical_types.h b/libs/libarchfpga/src/physical_types.h index 503427303..153fd981e 100644 --- a/libs/libarchfpga/src/physical_types.h +++ b/libs/libarchfpga/src/physical_types.h @@ -165,6 +165,7 @@ enum e_interconnect { MUX_INTERC = 3, NUM_INTERC_TYPES }; +constexpr std::array INTERCONNECT_TYPE_STRING = {{"complete", "direct", "mux"}}; //String versions of interconnection type /* Orientations. */ enum e_side : unsigned char { diff --git a/openfpga/src/annotation/annotate_pb_graph.cpp b/openfpga/src/annotation/annotate_pb_graph.cpp index 92f1b90b2..2043c2098 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 { @@ -27,7 +28,8 @@ namespace openfpga { *******************************************************************/ static void rec_build_vpr_pb_graph_interconnect_physical_type_annotation(t_pb_graph_node* pb_graph_node, - VprPbTypeAnnotation& vpr_pb_type_annotation) { + VprPbTypeAnnotation& vpr_pb_type_annotation, + const bool& verbose_output) { /* Skip the root node because we start from the inputs of child pb_graph node * * pb_graph_node @@ -85,6 +87,9 @@ void rec_build_vpr_pb_graph_interconnect_physical_type_annotation(t_pb_graph_nod /* Skip annotation if we have already done! */ continue; } + VTR_LOGV(verbose_output, + "Infer physical type '%s' of interconnect '%s' (was '%s')\n", + INTERCONNECT_TYPE_STRING[interc_physical_type], interc->name, INTERCONNECT_TYPE_STRING[interc->type]); vpr_pb_type_annotation.add_interconnect_physical_type(interc, interc_physical_type); } } @@ -100,7 +105,9 @@ void rec_build_vpr_pb_graph_interconnect_physical_type_annotation(t_pb_graph_nod for (int ipb = 0; ipb < physical_mode->num_pb_type_children; ++ipb) { /* Each child may exist multiple times in the hierarchy*/ for (int jpb = 0; jpb < physical_mode->pb_type_children[ipb].num_pb; ++jpb) { - rec_build_vpr_pb_graph_interconnect_physical_type_annotation(&(pb_graph_node->child_pb_graph_nodes[physical_mode->index][ipb][jpb]), vpr_pb_type_annotation); + rec_build_vpr_pb_graph_interconnect_physical_type_annotation(&(pb_graph_node->child_pb_graph_nodes[physical_mode->index][ipb][jpb]), + vpr_pb_type_annotation, + verbose_output); } } } @@ -115,13 +122,14 @@ void rec_build_vpr_pb_graph_interconnect_physical_type_annotation(t_pb_graph_nod * build_vpr_physical_pb_mode_implicit_annotation() *******************************************************************/ void annotate_pb_graph_interconnect_physical_type(const DeviceContext& vpr_device_ctx, - VprPbTypeAnnotation& vpr_pb_type_annotation) { + VprPbTypeAnnotation& vpr_pb_type_annotation, + const bool& verbose_output) { 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_build_vpr_pb_graph_interconnect_physical_type_annotation(lb_type.pb_graph_head, vpr_pb_type_annotation); + rec_build_vpr_pb_graph_interconnect_physical_type_annotation(lb_type.pb_graph_head, vpr_pb_type_annotation, verbose_output); } } @@ -221,6 +229,24 @@ bool try_match_pb_graph_pin(t_pb_graph_pin* operating_pb_graph_pin, return true; } +/******************************************************************** + * A function to print message to log file/screen when physical pb_graph_pin + * binding succeed + *******************************************************************/ +static +void print_success_bind_pb_graph_pin(t_pb_graph_pin* operating_pb_graph_pin, + t_pb_graph_pin* physical_pb_graph_pin) { + VTR_LOG("Bind a pb_graph_node '%s[%d]' pin '%s[%d]' to a pb_graph_node '%s[%d]' pin '%s[%d]'!\n", + operating_pb_graph_pin->parent_node->pb_type->name, + operating_pb_graph_pin->parent_node->placement_index, + operating_pb_graph_pin->port->name, + operating_pb_graph_pin->pin_number, + physical_pb_graph_pin->parent_node->pb_type->name, + physical_pb_graph_pin->parent_node->placement_index, + physical_pb_graph_pin->port->name, + physical_pb_graph_pin->pin_number); +} + /******************************************************************** * Bind a pb_graph_pin from an operating pb_graph_node to * a pb_graph_pin from a physical pb_graph_node @@ -229,7 +255,8 @@ bool try_match_pb_graph_pin(t_pb_graph_pin* operating_pb_graph_pin, static void annotate_physical_pb_graph_pin(t_pb_graph_pin* operating_pb_graph_pin, t_pb_graph_node* physical_pb_graph_node, - VprPbTypeAnnotation& vpr_pb_type_annotation) { + VprPbTypeAnnotation& vpr_pb_type_annotation, + const bool& verbose_output) { /* Iterate over every port and pin of the operating pb_graph_node * and find the physical pins */ @@ -244,15 +271,9 @@ void annotate_physical_pb_graph_pin(t_pb_graph_pin* operating_pb_graph_pin, * We can pair the pin and return */ vpr_pb_type_annotation.add_physical_pb_graph_pin(operating_pb_graph_pin, &(physical_pb_graph_node->input_pins[iport][ipin])); - VTR_LOG("Bind a pb_graph_node '%s[%d]' pin '%s[%d]' to a pb_graph_node '%s[%d]' pin '%s[%d]'!\n", - operating_pb_graph_pin->parent_node->pb_type->name, - operating_pb_graph_pin->parent_node->placement_index, - operating_pb_graph_pin->port->name, - operating_pb_graph_pin->pin_number, - physical_pb_graph_node->pb_type->name, - physical_pb_graph_node->placement_index, - physical_pb_graph_node->input_pins[iport][ipin].port->name, - physical_pb_graph_node->input_pins[iport][ipin].pin_number); + if (true == verbose_output) { + print_success_bind_pb_graph_pin(operating_pb_graph_pin, vpr_pb_type_annotation.physical_pb_graph_pin(operating_pb_graph_pin)); + } return; } } @@ -268,15 +289,9 @@ void annotate_physical_pb_graph_pin(t_pb_graph_pin* operating_pb_graph_pin, * We can pair the pin and return */ vpr_pb_type_annotation.add_physical_pb_graph_pin(operating_pb_graph_pin, &(physical_pb_graph_node->output_pins[iport][ipin])); - VTR_LOG("Bind a pb_graph_node '%s[%d]' pin '%s[%d]' to a pb_graph_node '%s[%d]' pin '%s[%d]'!\n", - operating_pb_graph_pin->parent_node->pb_type->name, - operating_pb_graph_pin->parent_node->placement_index, - operating_pb_graph_pin->port->name, - operating_pb_graph_pin->pin_number, - physical_pb_graph_node->pb_type->name, - physical_pb_graph_node->placement_index, - physical_pb_graph_node->output_pins[iport][ipin].port->name, - physical_pb_graph_node->output_pins[iport][ipin].pin_number); + if (true == verbose_output) { + print_success_bind_pb_graph_pin(operating_pb_graph_pin, vpr_pb_type_annotation.physical_pb_graph_pin(operating_pb_graph_pin)); + } return; } } @@ -292,15 +307,9 @@ void annotate_physical_pb_graph_pin(t_pb_graph_pin* operating_pb_graph_pin, * We can pair the pin and return */ vpr_pb_type_annotation.add_physical_pb_graph_pin(operating_pb_graph_pin, &(physical_pb_graph_node->clock_pins[iport][ipin])); - VTR_LOG("Bind a pb_graph_node '%s[%d]' pin '%s[%d]' to a pb_graph_node '%s[%d]' pin '%s[%d]'!\n", - operating_pb_graph_pin->parent_node->pb_type->name, - operating_pb_graph_pin->parent_node->placement_index, - operating_pb_graph_pin->port->name, - operating_pb_graph_pin->pin_number, - physical_pb_graph_node->pb_type->name, - physical_pb_graph_node->placement_index, - physical_pb_graph_node->clock_pins[iport][ipin].port->name, - physical_pb_graph_node->clock_pins[iport][ipin].pin_number); + if (true == verbose_output) { + print_success_bind_pb_graph_pin(operating_pb_graph_pin, vpr_pb_type_annotation.physical_pb_graph_pin(operating_pb_graph_pin)); + } return; } } @@ -320,28 +329,32 @@ void annotate_physical_pb_graph_pin(t_pb_graph_pin* operating_pb_graph_pin, static void annotate_physical_pb_graph_node_pins(t_pb_graph_node* operating_pb_graph_node, t_pb_graph_node* physical_pb_graph_node, - VprPbTypeAnnotation& vpr_pb_type_annotation) { + VprPbTypeAnnotation& vpr_pb_type_annotation, + const bool& verbose_output) { /* Iterate over every port and pin of the operating pb_graph_node * and find the physical pins */ for (int iport = 0; iport < operating_pb_graph_node->num_input_ports; ++iport) { for (int ipin = 0; ipin < operating_pb_graph_node->num_input_pins[iport]; ++ipin) { annotate_physical_pb_graph_pin(&(operating_pb_graph_node->input_pins[iport][ipin]), - physical_pb_graph_node, vpr_pb_type_annotation); + physical_pb_graph_node, vpr_pb_type_annotation, + verbose_output); } } for (int iport = 0; iport < operating_pb_graph_node->num_output_ports; ++iport) { for (int ipin = 0; ipin < operating_pb_graph_node->num_output_pins[iport]; ++ipin) { annotate_physical_pb_graph_pin(&(operating_pb_graph_node->output_pins[iport][ipin]), - physical_pb_graph_node, vpr_pb_type_annotation); + physical_pb_graph_node, vpr_pb_type_annotation, + verbose_output); } } for (int iport = 0; iport < operating_pb_graph_node->num_clock_ports; ++iport) { for (int ipin = 0; ipin < operating_pb_graph_node->num_clock_pins[iport]; ++ipin) { annotate_physical_pb_graph_pin(&(operating_pb_graph_node->clock_pins[iport][ipin]), - physical_pb_graph_node, vpr_pb_type_annotation); + physical_pb_graph_node, vpr_pb_type_annotation, + verbose_output); } } } @@ -356,7 +369,8 @@ void annotate_physical_pb_graph_node_pins(t_pb_graph_node* operating_pb_graph_no *******************************************************************/ static void rec_build_vpr_physical_pb_graph_node_annotation(t_pb_graph_node* pb_graph_node, - VprPbTypeAnnotation& vpr_pb_type_annotation) { + VprPbTypeAnnotation& vpr_pb_type_annotation, + const bool& verbose_output) { /* 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) { @@ -364,7 +378,8 @@ void rec_build_vpr_physical_pb_graph_node_annotation(t_pb_graph_node* pb_graph_n /* 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_build_vpr_physical_pb_graph_node_annotation(&(pb_graph_node->child_pb_graph_nodes[imode][ipb][jpb]), - vpr_pb_type_annotation); + vpr_pb_type_annotation, + verbose_output); } } } @@ -394,12 +409,13 @@ void rec_build_vpr_physical_pb_graph_node_annotation(t_pb_graph_node* pb_graph_n VTR_ASSERT(nullptr != physical_pb_graph_node); vpr_pb_type_annotation.add_physical_pb_graph_node(pb_graph_node, physical_pb_graph_node); - VTR_LOG("Bind operating pb_graph_node '%s' to physical pb_graph_node '%s'\n", - pb_graph_node->hierarchical_type_name().c_str(), - physical_pb_graph_node->hierarchical_type_name().c_str()); + VTR_LOGV(verbose_output, + "Bind operating pb_graph_node '%s' to physical pb_graph_node '%s'\n", + pb_graph_node->hierarchical_type_name().c_str(), + physical_pb_graph_node->hierarchical_type_name().c_str()); /* Try to bind each pins under this pb_graph_node to physical_pb_graph_node */ - annotate_physical_pb_graph_node_pins(pb_graph_node, physical_pb_graph_node, vpr_pb_type_annotation); + annotate_physical_pb_graph_node_pins(pb_graph_node, physical_pb_graph_node, vpr_pb_type_annotation, verbose_output); } /******************************************************************** @@ -409,13 +425,14 @@ void rec_build_vpr_physical_pb_graph_node_annotation(t_pb_graph_node* pb_graph_n *******************************************************************/ static void annotate_physical_pb_graph_node(const DeviceContext& vpr_device_ctx, - VprPbTypeAnnotation& vpr_pb_type_annotation) { + VprPbTypeAnnotation& vpr_pb_type_annotation, + const bool& verbose_output) { 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_build_vpr_physical_pb_graph_node_annotation(lb_type.pb_graph_head, vpr_pb_type_annotation); + rec_build_vpr_physical_pb_graph_node_annotation(lb_type.pb_graph_head, vpr_pb_type_annotation, verbose_output); } } @@ -426,15 +443,21 @@ void annotate_physical_pb_graph_node(const DeviceContext& vpr_device_ctx, * - Bind pins from operating pb_graph_node to their physical pb_graph_node pins *******************************************************************/ void annotate_pb_graph(const DeviceContext& vpr_device_ctx, - VprPbTypeAnnotation& vpr_pb_type_annotation) { + VprPbTypeAnnotation& vpr_pb_type_annotation, + const bool& verbose_output) { VTR_LOG("Assigning unique indices for primitive pb_graph nodes..."); + VTR_LOGV(verbose_output, "\n"); annotate_primitive_pb_graph_node_unique_index(vpr_device_ctx, vpr_pb_type_annotation); VTR_LOG("Done\n"); - 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("Binding operating pb_graph nodes/pins to physical pb_graph nodes/pins..."); + VTR_LOGV(verbose_output, "\n"); + annotate_physical_pb_graph_node(vpr_device_ctx, vpr_pb_type_annotation, verbose_output); 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/annotate_pb_graph.h b/openfpga/src/annotation/annotate_pb_graph.h index e809d3cfa..64eced256 100644 --- a/openfpga/src/annotation/annotate_pb_graph.h +++ b/openfpga/src/annotation/annotate_pb_graph.h @@ -16,10 +16,12 @@ namespace openfpga { void annotate_pb_graph_interconnect_physical_type(const DeviceContext& vpr_device_ctx, - VprPbTypeAnnotation& vpr_pb_type_annotation); + VprPbTypeAnnotation& vpr_pb_type_annotation, + const bool& verbose_output); void annotate_pb_graph(const DeviceContext& vpr_device_ctx, - VprPbTypeAnnotation& vpr_pb_type_annotation); + VprPbTypeAnnotation& vpr_pb_type_annotation, + const bool& verbose_output); } /* end namespace openfpga */ diff --git a/openfpga/src/annotation/annotate_pb_types.cpp b/openfpga/src/annotation/annotate_pb_types.cpp index 8dc89251a..d70ab7427 100644 --- a/openfpga/src/annotation/annotate_pb_types.cpp +++ b/openfpga/src/annotation/annotate_pb_types.cpp @@ -24,7 +24,8 @@ namespace openfpga { static void build_vpr_physical_pb_mode_explicit_annotation(const DeviceContext& vpr_device_ctx, const Arch& openfpga_arch, - VprPbTypeAnnotation& vpr_pb_type_annotation) { + VprPbTypeAnnotation& vpr_pb_type_annotation, + const bool& verbose_output) { /* Walk through the pb_type annotation stored in the openfpga arch */ for (const PbTypeAnnotation& pb_type_annotation : openfpga_arch.pb_type_annotations) { /* Since our target is to annotate the physical mode name, @@ -82,8 +83,9 @@ void build_vpr_physical_pb_mode_explicit_annotation(const DeviceContext& vpr_dev vpr_pb_type_annotation.add_pb_type_physical_mode(target_pb_type, physical_mode); /* Give a message */ - VTR_LOG("Annotate pb_type '%s' with physical mode '%s'\n", - target_pb_type->name, physical_mode->name); + VTR_LOGV(verbose_output, + "Annotate pb_type '%s' with physical mode '%s'\n", + target_pb_type->name, physical_mode->name); link_success = true; break; @@ -110,7 +112,8 @@ void build_vpr_physical_pb_mode_explicit_annotation(const DeviceContext& vpr_dev *******************************************************************/ static void rec_infer_vpr_physical_pb_mode_annotation(t_pb_type* cur_pb_type, - VprPbTypeAnnotation& vpr_pb_type_annotation) { + VprPbTypeAnnotation& vpr_pb_type_annotation, + const bool& verbose_output) { /* We do not check any primitive pb_type */ if (true == is_primitive_pb_type(cur_pb_type)) { return; @@ -128,8 +131,9 @@ void rec_infer_vpr_physical_pb_mode_annotation(t_pb_type* cur_pb_type, if (nullptr == vpr_pb_type_annotation.physical_mode(cur_pb_type)) { /* Not assigned by explicit annotation, we should infer here */ vpr_pb_type_annotation.add_pb_type_physical_mode(cur_pb_type, &(cur_pb_type->modes[0])); - VTR_LOG("Implicitly infer physical mode '%s' for pb_type '%s'\n", - cur_pb_type->modes[0].name, cur_pb_type->name); + VTR_LOGV(verbose_output, + "Implicitly infer physical mode '%s' for pb_type '%s'\n", + cur_pb_type->modes[0].name, cur_pb_type->name); } } else { VTR_ASSERT(1 < cur_pb_type->num_modes); @@ -151,7 +155,8 @@ void rec_infer_vpr_physical_pb_mode_annotation(t_pb_type* cur_pb_type, /* Traverse the pb_type children under the physical mode */ for (int ichild = 0; ichild < physical_mode->num_pb_type_children; ++ichild) { rec_infer_vpr_physical_pb_mode_annotation(&(physical_mode->pb_type_children[ichild]), - vpr_pb_type_annotation); + vpr_pb_type_annotation, + verbose_output); } } @@ -169,13 +174,14 @@ void rec_infer_vpr_physical_pb_mode_annotation(t_pb_type* cur_pb_type, *******************************************************************/ static void build_vpr_physical_pb_mode_implicit_annotation(const DeviceContext& vpr_device_ctx, - VprPbTypeAnnotation& vpr_pb_type_annotation) { + VprPbTypeAnnotation& vpr_pb_type_annotation, + const bool& verbose_output) { for (const t_logical_block_type& lb_type : vpr_device_ctx.logical_block_types) { /* By pass nullptr for pb_type head */ if (nullptr == lb_type.pb_type) { continue; } - rec_infer_vpr_physical_pb_mode_annotation(lb_type.pb_type, vpr_pb_type_annotation); + rec_infer_vpr_physical_pb_mode_annotation(lb_type.pb_type, vpr_pb_type_annotation, verbose_output); } } @@ -257,7 +263,8 @@ bool pair_operating_and_physical_pb_types(t_pb_type* operating_pb_type, static void build_vpr_physical_pb_type_explicit_annotation(const DeviceContext& vpr_device_ctx, const Arch& openfpga_arch, - VprPbTypeAnnotation& vpr_pb_type_annotation) { + VprPbTypeAnnotation& vpr_pb_type_annotation, + const bool& verbose_output) { /* Walk through the pb_type annotation stored in the openfpga arch */ for (const PbTypeAnnotation& pb_type_annotation : openfpga_arch.pb_type_annotations) { /* Since our target is to annotate the operating pb_type tp physical pb_type @@ -324,8 +331,9 @@ void build_vpr_physical_pb_type_explicit_annotation(const DeviceContext& vpr_dev pb_type_annotation, vpr_pb_type_annotation)) { /* Give a message */ - VTR_LOG("Annotate operating pb_type '%s' to its physical pb_type '%s'\n", - target_op_pb_type->name, target_phy_pb_type->name); + VTR_LOGV(verbose_output, + "Annotate operating pb_type '%s' to its physical pb_type '%s'\n", + target_op_pb_type->name, target_phy_pb_type->name); link_success = true; break; @@ -376,7 +384,8 @@ bool self_pair_physical_pb_types(t_pb_type* physical_pb_type, *******************************************************************/ static void rec_infer_vpr_physical_pb_type_annotation(t_pb_type* cur_pb_type, - VprPbTypeAnnotation& vpr_pb_type_annotation) { + VprPbTypeAnnotation& vpr_pb_type_annotation, + const bool& verbose_output) { /* Physical pb_type is mainly for the primitive pb_type */ if (true == is_primitive_pb_type(cur_pb_type)) { /* If the physical pb_type has been mapped, we can skip it */ @@ -386,8 +395,9 @@ void rec_infer_vpr_physical_pb_type_annotation(t_pb_type* cur_pb_type, /* Create the pair here */ if (true == self_pair_physical_pb_types(cur_pb_type, vpr_pb_type_annotation)) { /* Give a message */ - VTR_LOG("Implicitly infer the physical pb_type for pb_type '%s' itself\n", - cur_pb_type->name); + VTR_LOGV(verbose_output, + "Implicitly infer the physical pb_type for pb_type '%s' itself\n", + cur_pb_type->name); } else { VTR_LOG_ERROR("Unable to infer the physical pb_type for pb_type '%s' itself!\n", cur_pb_type->name); @@ -403,7 +413,8 @@ void rec_infer_vpr_physical_pb_type_annotation(t_pb_type* cur_pb_type, /* Traverse the pb_type children under the physical mode */ for (int ichild = 0; ichild < physical_mode->num_pb_type_children; ++ichild) { rec_infer_vpr_physical_pb_type_annotation(&(physical_mode->pb_type_children[ichild]), - vpr_pb_type_annotation); + vpr_pb_type_annotation, + verbose_output); } } @@ -418,13 +429,14 @@ void rec_infer_vpr_physical_pb_type_annotation(t_pb_type* cur_pb_type, *******************************************************************/ static void build_vpr_physical_pb_type_implicit_annotation(const DeviceContext& vpr_device_ctx, - VprPbTypeAnnotation& vpr_pb_type_annotation) { + VprPbTypeAnnotation& vpr_pb_type_annotation, + const bool& verbose_output) { for (const t_logical_block_type& lb_type : vpr_device_ctx.logical_block_types) { /* By pass nullptr for pb_type head */ if (nullptr == lb_type.pb_type) { continue; } - rec_infer_vpr_physical_pb_type_annotation(lb_type.pb_type, vpr_pb_type_annotation); + rec_infer_vpr_physical_pb_type_annotation(lb_type.pb_type, vpr_pb_type_annotation, verbose_output); } } @@ -438,7 +450,8 @@ static bool link_physical_pb_port_to_circuit_port(t_pb_type* physical_pb_type, const CircuitLibrary& circuit_lib, const CircuitModelId& circuit_model, - VprPbTypeAnnotation& vpr_pb_type_annotation) { + VprPbTypeAnnotation& vpr_pb_type_annotation, + const bool& verbose_output) { bool link_success = true; /* Iterate over the pb_ports * Note: @@ -481,11 +494,12 @@ bool link_physical_pb_port_to_circuit_port(t_pb_type* physical_pb_type, /* Reach here, it means that mapping should be ok, update the vpr_pb_type_annotation */ vpr_pb_type_annotation.add_pb_circuit_port(pb_port, circuit_port); - VTR_LOG("Bind pb type '%s' port '%s' to circuit model '%s' port '%s'\n", - physical_pb_type->name, - pb_port->name, - circuit_lib.model_name(circuit_model).c_str(), - circuit_lib.port_prefix(circuit_port).c_str()); + VTR_LOGV(verbose_output, + "Bind pb type '%s' port '%s' to circuit model '%s' port '%s'\n", + physical_pb_type->name, + pb_port->name, + circuit_lib.model_name(circuit_model).c_str(), + circuit_lib.port_prefix(circuit_port).c_str()); } return link_success; @@ -499,7 +513,8 @@ static bool link_physical_pb_type_to_circuit_model(t_pb_type* physical_pb_type, const CircuitLibrary& circuit_lib, const PbTypeAnnotation& pb_type_annotation, - VprPbTypeAnnotation& vpr_pb_type_annotation) { + VprPbTypeAnnotation& vpr_pb_type_annotation, + const bool& verbose_output) { /* Reach here, we should have valid operating and physical pb_types */ VTR_ASSERT(nullptr != physical_pb_type); @@ -521,7 +536,8 @@ bool link_physical_pb_type_to_circuit_model(t_pb_type* physical_pb_type, } /* Ensure that the pb_type ports can be matched in the circuit model ports */ - if (false == link_physical_pb_port_to_circuit_port(physical_pb_type, circuit_lib, circuit_model_id, vpr_pb_type_annotation)) { + if (false == link_physical_pb_port_to_circuit_port(physical_pb_type, circuit_lib, circuit_model_id, + vpr_pb_type_annotation, verbose_output)) { return false; } @@ -539,7 +555,8 @@ bool link_physical_pb_interconnect_to_circuit_model(t_pb_type* physical_pb_type, const std::string& interconnect_name, const CircuitLibrary& circuit_lib, const PbTypeAnnotation& pb_type_annotation, - VprPbTypeAnnotation& vpr_pb_type_annotation) { + VprPbTypeAnnotation& vpr_pb_type_annotation, + const bool& verbose_output) { /* The physical pb_type should NOT be a primitive, otherwise it should never contain any interconnect */ if (true == is_primitive_pb_type(physical_pb_type)) { VTR_LOG_ERROR("Link interconnect to circuit model is not allowed for a primitive pb_type '%s'!\n", @@ -592,7 +609,8 @@ bool link_physical_pb_interconnect_to_circuit_model(t_pb_type* physical_pb_type, /* Now the circuit model is valid, update the vpr_pb_type_annotation */ vpr_pb_type_annotation.add_interconnect_circuit_model(pb_interc, circuit_model_id); - VTR_LOG("Bind pb_type '%s' physical mode '%s' interconnect '%s' to circuit model '%s'\n", + VTR_LOGV(verbose_output, + "Bind pb_type '%s' physical mode '%s' interconnect '%s' to circuit model '%s'\n", physical_pb_type->name, physical_mode->name, pb_interc->name, @@ -613,7 +631,8 @@ bool link_physical_pb_interconnect_to_circuit_model(t_pb_type* physical_pb_type, static void link_vpr_pb_type_to_circuit_model_explicit_annotation(const DeviceContext& vpr_device_ctx, const Arch& openfpga_arch, - VprPbTypeAnnotation& vpr_pb_type_annotation) { + VprPbTypeAnnotation& vpr_pb_type_annotation, + const bool& verbose_output) { /* Walk through the pb_type annotation stored in the openfpga arch */ for (const PbTypeAnnotation& pb_type_annotation : openfpga_arch.pb_type_annotations) { /* Since our target is to annotate the circuti model for physical pb_type @@ -664,11 +683,13 @@ void link_vpr_pb_type_to_circuit_model_explicit_annotation(const DeviceContext& /* Only try to bind pb_type to circuit model when it is defined by users */ if (true == link_physical_pb_type_to_circuit_model(target_phy_pb_type, openfpga_arch.circuit_lib, - pb_type_annotation, vpr_pb_type_annotation)) { + pb_type_annotation, vpr_pb_type_annotation, + verbose_output)) { /* Give a message */ - VTR_LOG("Bind physical pb_type '%s' to its circuit model '%s'\n", - target_phy_pb_type->name, - openfpga_arch.circuit_lib.model_name(vpr_pb_type_annotation.pb_type_circuit_model(target_phy_pb_type)).c_str()); + VTR_LOGV(verbose_output, + "Bind physical pb_type '%s' to its circuit model '%s'\n", + target_phy_pb_type->name, + openfpga_arch.circuit_lib.model_name(vpr_pb_type_annotation.pb_type_circuit_model(target_phy_pb_type)).c_str()); link_success = true; break; @@ -697,7 +718,8 @@ void link_vpr_pb_type_to_circuit_model_explicit_annotation(const DeviceContext& static void link_vpr_pb_interconnect_to_circuit_model_explicit_annotation(const DeviceContext& vpr_device_ctx, const Arch& openfpga_arch, - VprPbTypeAnnotation& vpr_pb_type_annotation) { + VprPbTypeAnnotation& vpr_pb_type_annotation, + const bool& verbose_output) { /* Walk through the pb_type annotation stored in the openfpga arch */ for (const PbTypeAnnotation& pb_type_annotation : openfpga_arch.pb_type_annotations) { /* Since our target is to annotate the circuti model for physical pb_type @@ -749,7 +771,8 @@ void link_vpr_pb_interconnect_to_circuit_model_explicit_annotation(const DeviceC /* Only try to bind interconnect to circuit model when it is defined by users */ for (const std::string& interc_name : pb_type_annotation.interconnect_names()) { if (false == link_physical_pb_interconnect_to_circuit_model(target_phy_pb_type, interc_name, openfpga_arch.circuit_lib, - pb_type_annotation, vpr_pb_type_annotation)) { + pb_type_annotation, vpr_pb_type_annotation, + verbose_output)) { VTR_LOG_ERROR("Unable to bind pb_type '%s' interconnect '%s' to circuit model '%s'!\n", target_phy_pb_type_names.back().c_str(), interc_name.c_str(), @@ -789,7 +812,8 @@ void link_vpr_pb_interconnect_to_circuit_model_explicit_annotation(const DeviceC static void rec_infer_vpr_pb_interconnect_circuit_model_annotation(t_pb_type* cur_pb_type, const CircuitLibrary& circuit_lib, - VprPbTypeAnnotation& vpr_pb_type_annotation) { + VprPbTypeAnnotation& vpr_pb_type_annotation, + const bool& verbose_output) { /* We do not check any primitive pb_type */ if (true == is_primitive_pb_type(cur_pb_type)) { return; @@ -818,17 +842,19 @@ void rec_infer_vpr_pb_interconnect_circuit_model_annotation(t_pb_type* cur_pb_ty cur_pb_type->name); } vpr_pb_type_annotation.add_interconnect_circuit_model(pb_interc, default_circuit_model); - VTR_LOG("Implicitly infer a circuit model '%s' for interconnect '%s' under physical mode '%s' of pb_type '%s'\n", - circuit_lib.model_name(default_circuit_model).c_str(), - pb_interc->name, - physical_mode->name, - cur_pb_type->name); + VTR_LOGV(verbose_output, + "Implicitly infer a circuit model '%s' for interconnect '%s' under physical mode '%s' of pb_type '%s'\n", + circuit_lib.model_name(default_circuit_model).c_str(), + pb_interc->name, + physical_mode->name, + cur_pb_type->name); } /* Traverse the pb_type children under the physical mode */ for (int ichild = 0; ichild < physical_mode->num_pb_type_children; ++ichild) { rec_infer_vpr_pb_interconnect_circuit_model_annotation(&(physical_mode->pb_type_children[ichild]), - circuit_lib, vpr_pb_type_annotation); + circuit_lib, vpr_pb_type_annotation, + verbose_output); } } @@ -845,13 +871,14 @@ void rec_infer_vpr_pb_interconnect_circuit_model_annotation(t_pb_type* cur_pb_ty static void link_vpr_pb_interconnect_to_circuit_model_implicit_annotation(const DeviceContext& vpr_device_ctx, const CircuitLibrary& circuit_lib, - VprPbTypeAnnotation& vpr_pb_type_annotation) { + VprPbTypeAnnotation& vpr_pb_type_annotation, + const bool& verbose_output) { for (const t_logical_block_type& lb_type : vpr_device_ctx.logical_block_types) { /* By pass nullptr for pb_type head */ if (nullptr == lb_type.pb_type) { continue; } - rec_infer_vpr_pb_interconnect_circuit_model_annotation(lb_type.pb_type, circuit_lib, vpr_pb_type_annotation); + rec_infer_vpr_pb_interconnect_circuit_model_annotation(lb_type.pb_type, circuit_lib, vpr_pb_type_annotation, verbose_output); } } @@ -889,7 +916,8 @@ bool link_primitive_pb_type_to_mode_bits(t_pb_type* primitive_pb_type, static void link_vpr_pb_type_to_mode_bits_explicit_annotation(const DeviceContext& vpr_device_ctx, const Arch& openfpga_arch, - VprPbTypeAnnotation& vpr_pb_type_annotation) { + VprPbTypeAnnotation& vpr_pb_type_annotation, + const bool& verbose_output) { /* Walk through the pb_type annotation stored in the openfpga arch */ for (const PbTypeAnnotation& pb_type_annotation : openfpga_arch.pb_type_annotations) { if (true == pb_type_annotation.mode_bits().empty()) { @@ -947,9 +975,10 @@ void link_vpr_pb_type_to_mode_bits_explicit_annotation(const DeviceContext& vpr_ if (true == link_primitive_pb_type_to_mode_bits(target_pb_type, pb_type_annotation, vpr_pb_type_annotation)) { /* Give a message */ - VTR_LOG("Bind physical pb_type '%s' to mode selection bits '%s'\n", - target_pb_type->name, - mode_bits_str.c_str()); + VTR_LOGV(verbose_output, + "Bind physical pb_type '%s' to mode selection bits '%s'\n", + target_pb_type->name, + mode_bits_str.c_str()); link_success = true; break; @@ -973,16 +1002,21 @@ void link_vpr_pb_type_to_mode_bits_explicit_annotation(const DeviceContext& vpr_ *******************************************************************/ void annotate_pb_types(const DeviceContext& vpr_device_ctx, const Arch& openfpga_arch, - VprPbTypeAnnotation& vpr_pb_type_annotation) { + VprPbTypeAnnotation& vpr_pb_type_annotation, + const bool& verbose_output) { /* Annotate physical mode to pb_type in the VPR pb_type graph */ VTR_LOG("\n"); - VTR_LOG("Building annotation for physical modes in pb_type...\n"); + VTR_LOG("Building annotation for physical modes in pb_type..."); + VTR_LOGV(verbose_output, "\n"); build_vpr_physical_pb_mode_explicit_annotation(vpr_device_ctx, openfpga_arch, - vpr_pb_type_annotation); + vpr_pb_type_annotation, + verbose_output); build_vpr_physical_pb_mode_implicit_annotation(vpr_device_ctx, - vpr_pb_type_annotation); + vpr_pb_type_annotation, + verbose_output); + VTR_LOG("Done\n"); check_vpr_physical_pb_mode_annotation(vpr_device_ctx, const_cast(vpr_pb_type_annotation)); @@ -993,8 +1027,10 @@ void annotate_pb_types(const DeviceContext& vpr_device_ctx, */ VTR_LOG("\n"); VTR_LOG("Building annotation about physical types for pb_type interconnection..."); + VTR_LOGV(verbose_output, "\n"); annotate_pb_graph_interconnect_physical_type(vpr_device_ctx, - vpr_pb_type_annotation); + vpr_pb_type_annotation, + verbose_output); VTR_LOG("Done\n"); /* Annotate physical pb_types to operating pb_type in the VPR pb_type graph @@ -1004,12 +1040,16 @@ void annotate_pb_types(const DeviceContext& vpr_device_ctx, * - physical_pin_rotate_offset */ VTR_LOG("\n"); - VTR_LOG("Building annotation between operating and physical pb_types...\n"); + VTR_LOG("Building annotation between operating and physical pb_types..."); + VTR_LOGV(verbose_output, "\n"); build_vpr_physical_pb_type_explicit_annotation(vpr_device_ctx, openfpga_arch, - vpr_pb_type_annotation); + vpr_pb_type_annotation, + verbose_output); build_vpr_physical_pb_type_implicit_annotation(vpr_device_ctx, - vpr_pb_type_annotation); + vpr_pb_type_annotation, + verbose_output); + VTR_LOG("Done\n"); check_vpr_physical_pb_type_annotation(vpr_device_ctx, const_cast(vpr_pb_type_annotation)); @@ -1019,21 +1059,33 @@ void annotate_pb_types(const DeviceContext& vpr_device_ctx, * - interconnect of physical pb_type to circuit model */ VTR_LOG("\n"); - VTR_LOG("Building annotation between physical pb_types and circuit models...\n"); + VTR_LOG("Building annotation between physical pb_types and circuit models..."); + VTR_LOGV(verbose_output, "\n"); link_vpr_pb_type_to_circuit_model_explicit_annotation(vpr_device_ctx, openfpga_arch, - vpr_pb_type_annotation); + vpr_pb_type_annotation, + verbose_output); + link_vpr_pb_interconnect_to_circuit_model_explicit_annotation(vpr_device_ctx, openfpga_arch, - vpr_pb_type_annotation); + vpr_pb_type_annotation, + verbose_output); + link_vpr_pb_interconnect_to_circuit_model_implicit_annotation(vpr_device_ctx, openfpga_arch.circuit_lib, - vpr_pb_type_annotation); + vpr_pb_type_annotation, + verbose_output); + VTR_LOG("Done\n"); + check_vpr_pb_type_circuit_model_annotation(vpr_device_ctx, openfpga_arch.circuit_lib, const_cast(vpr_pb_type_annotation)); /* Link physical pb_type to mode_bits */ VTR_LOG("\n"); - VTR_LOG("Building annotation between physical pb_types and mode selection bits...\n"); + VTR_LOG("Building annotation between physical pb_types and mode selection bits..."); + VTR_LOGV(verbose_output, "\n"); link_vpr_pb_type_to_mode_bits_explicit_annotation(vpr_device_ctx, openfpga_arch, - vpr_pb_type_annotation); + vpr_pb_type_annotation, + verbose_output); + VTR_LOG("Done\n"); + check_vpr_pb_type_mode_bits_annotation(vpr_device_ctx, openfpga_arch.circuit_lib, const_cast(vpr_pb_type_annotation)); diff --git a/openfpga/src/annotation/annotate_pb_types.h b/openfpga/src/annotation/annotate_pb_types.h index 494b2c771..4be50aed6 100644 --- a/openfpga/src/annotation/annotate_pb_types.h +++ b/openfpga/src/annotation/annotate_pb_types.h @@ -17,7 +17,8 @@ namespace openfpga { void annotate_pb_types(const DeviceContext& vpr_device_ctx, const Arch& openfpga_arch, - VprPbTypeAnnotation& vpr_pb_type_annotation); + VprPbTypeAnnotation& vpr_pb_type_annotation, + const bool& verbose_output); } /* 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 diff --git a/openfpga/src/base/openfpga_link_arch.cpp b/openfpga/src/base/openfpga_link_arch.cpp index e6762485e..8f7b5b54d 100644 --- a/openfpga/src/base/openfpga_link_arch.cpp +++ b/openfpga/src/base/openfpga_link_arch.cpp @@ -27,17 +27,21 @@ namespace openfpga { * - physical pb_graph nodes and pb_graph pins * - circuit models for global routing architecture *******************************************************************/ -void link_arch(OpenfpgaContext& openfpga_context) { +void link_arch(OpenfpgaContext& openfpga_context, + const Command& cmd, const CommandContext& cmd_context) { vtr::ScopedStartFinishTimer timer("Link OpenFPGA architecture to VPR architecture"); + CommandOptionId opt_verbose = cmd.option("verbose"); + /* Annotate pb_type graphs * - physical pb_type * - mode selection bits for pb_type and pb interconnect * - circuit models for pb_type and pb interconnect */ annotate_pb_types(g_vpr_ctx.device(), openfpga_context.arch(), - openfpga_context.mutable_vpr_pb_type_annotation()); + openfpga_context.mutable_vpr_pb_type_annotation(), + cmd_context.option_enable(cmd, opt_verbose)); /* Annotate pb_graph_nodes * - Give unique index to each node in the same type @@ -45,7 +49,8 @@ void link_arch(OpenfpgaContext& openfpga_context) { * - Bind pins from operating pb_graph_node to their physical pb_graph_node pins */ annotate_pb_graph(g_vpr_ctx.device(), - openfpga_context.mutable_vpr_pb_type_annotation()); + openfpga_context.mutable_vpr_pb_type_annotation(), + cmd_context.option_enable(cmd, opt_verbose)); } } /* end namespace openfpga */ diff --git a/openfpga/src/base/openfpga_link_arch.h b/openfpga/src/base/openfpga_link_arch.h index 3775ee789..742c29541 100644 --- a/openfpga/src/base/openfpga_link_arch.h +++ b/openfpga/src/base/openfpga_link_arch.h @@ -4,6 +4,8 @@ /******************************************************************** * Include header files that are required by function declaration *******************************************************************/ +#include "command.h" +#include "command_context.h" #include "openfpga_context.h" /******************************************************************** @@ -13,7 +15,8 @@ /* begin namespace openfpga */ namespace openfpga { -void link_arch(OpenfpgaContext& openfpga_context); +void link_arch(OpenfpgaContext& openfpga_context, + const Command& cmd, const CommandContext& cmd_context); } /* end namespace openfpga */ diff --git a/openfpga/src/base/openfpga_setup_command.cpp b/openfpga/src/base/openfpga_setup_command.cpp index 9a3eee970..ef392a4c4 100644 --- a/openfpga/src/base/openfpga_setup_command.cpp +++ b/openfpga/src/base/openfpga_setup_command.cpp @@ -52,6 +52,8 @@ void add_openfpga_setup_commands(openfpga::Shell& shell) { * Command 'link_openfpga_arch' */ Command shell_cmd_link_openfpga_arch("link_openfpga_arch"); + /* Add an option '--verbose' */ + shell_cmd_link_openfpga_arch.add_option("verbose", false, "Show verbose outputs"); /* Add command 'link_openfpga_arch' to the Shell */ ShellCommandId shell_cmd_link_openfpga_arch_id = shell.add_command(shell_cmd_link_openfpga_arch, "Bind OpenFPGA architecture to VPR"); @@ -67,7 +69,7 @@ void add_openfpga_setup_commands(openfpga::Shell& shell) { * Command 'check_netlist_naming_conflict' */ Command shell_cmd_check_netlist_naming_conflict("check_netlist_naming_conflict"); - /* Add an option '--correction' */ + /* Add an option '--fix' */ shell_cmd_check_netlist_naming_conflict.add_option("fix", false, "Apply correction to any conflicts found"); /* Add an option '--report' */ CommandOptionId check_netlist_opt_rpt = shell_cmd_check_netlist_naming_conflict.add_option("report", false, "Output a report file about what any correction applied");