From 568ed120c2a6784f4429eec40b30491ab50ad4af Mon Sep 17 00:00:00 2001 From: tangxifan Date: Wed, 29 Jan 2020 21:53:56 -0700 Subject: [PATCH 1/4] change report naming fix-up to be XML format --- openfpga/test_script/s298.openfpga | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openfpga/test_script/s298.openfpga b/openfpga/test_script/s298.openfpga index cafc16074..216f6d8c4 100644 --- a/openfpga/test_script/s298.openfpga +++ b/openfpga/test_script/s298.openfpga @@ -8,7 +8,7 @@ read_openfpga_arch -f ./test_openfpga_arch/k6_N10_40nm_openfpga.xml link_openfpga_arch # Check and correct any naming conflicts in the BLIF netlist -check_netlist_naming_conflict --fix --report ./netlist_renaming.rpt +check_netlist_naming_conflict --fix --report ./netlist_renaming.xml # Finish and exit OpenFPGA exit From e48ab8cb44a8964acde6866b8e44788db8bdc212 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Thu, 30 Jan 2020 13:37:41 -0700 Subject: [PATCH 2/4] move annotation source files to a separated folder --- openfpga/src/{base => annotation}/annotate_pb_graph.cpp | 0 openfpga/src/{base => annotation}/annotate_pb_graph.h | 0 openfpga/src/{base => annotation}/annotate_pb_types.cpp | 0 openfpga/src/{base => annotation}/annotate_pb_types.h | 0 .../src/{base => annotation}/check_netlist_naming_conflict.cpp | 0 openfpga/src/{base => annotation}/check_netlist_naming_conflict.h | 0 openfpga/src/{base => annotation}/check_pb_type_annotation.cpp | 0 openfpga/src/{base => annotation}/check_pb_type_annotation.h | 0 openfpga/src/{base => annotation}/vpr_netlist_annotation.cpp | 0 openfpga/src/{base => annotation}/vpr_netlist_annotation.h | 0 openfpga/src/{base => annotation}/vpr_pb_type_annotation.cpp | 0 openfpga/src/{base => annotation}/vpr_pb_type_annotation.h | 0 12 files changed, 0 insertions(+), 0 deletions(-) rename openfpga/src/{base => annotation}/annotate_pb_graph.cpp (100%) rename openfpga/src/{base => annotation}/annotate_pb_graph.h (100%) rename openfpga/src/{base => annotation}/annotate_pb_types.cpp (100%) rename openfpga/src/{base => annotation}/annotate_pb_types.h (100%) rename openfpga/src/{base => annotation}/check_netlist_naming_conflict.cpp (100%) rename openfpga/src/{base => annotation}/check_netlist_naming_conflict.h (100%) rename openfpga/src/{base => annotation}/check_pb_type_annotation.cpp (100%) rename openfpga/src/{base => annotation}/check_pb_type_annotation.h (100%) rename openfpga/src/{base => annotation}/vpr_netlist_annotation.cpp (100%) rename openfpga/src/{base => annotation}/vpr_netlist_annotation.h (100%) rename openfpga/src/{base => annotation}/vpr_pb_type_annotation.cpp (100%) rename openfpga/src/{base => annotation}/vpr_pb_type_annotation.h (100%) diff --git a/openfpga/src/base/annotate_pb_graph.cpp b/openfpga/src/annotation/annotate_pb_graph.cpp similarity index 100% rename from openfpga/src/base/annotate_pb_graph.cpp rename to openfpga/src/annotation/annotate_pb_graph.cpp diff --git a/openfpga/src/base/annotate_pb_graph.h b/openfpga/src/annotation/annotate_pb_graph.h similarity index 100% rename from openfpga/src/base/annotate_pb_graph.h rename to openfpga/src/annotation/annotate_pb_graph.h diff --git a/openfpga/src/base/annotate_pb_types.cpp b/openfpga/src/annotation/annotate_pb_types.cpp similarity index 100% rename from openfpga/src/base/annotate_pb_types.cpp rename to openfpga/src/annotation/annotate_pb_types.cpp diff --git a/openfpga/src/base/annotate_pb_types.h b/openfpga/src/annotation/annotate_pb_types.h similarity index 100% rename from openfpga/src/base/annotate_pb_types.h rename to openfpga/src/annotation/annotate_pb_types.h diff --git a/openfpga/src/base/check_netlist_naming_conflict.cpp b/openfpga/src/annotation/check_netlist_naming_conflict.cpp similarity index 100% rename from openfpga/src/base/check_netlist_naming_conflict.cpp rename to openfpga/src/annotation/check_netlist_naming_conflict.cpp diff --git a/openfpga/src/base/check_netlist_naming_conflict.h b/openfpga/src/annotation/check_netlist_naming_conflict.h similarity index 100% rename from openfpga/src/base/check_netlist_naming_conflict.h rename to openfpga/src/annotation/check_netlist_naming_conflict.h diff --git a/openfpga/src/base/check_pb_type_annotation.cpp b/openfpga/src/annotation/check_pb_type_annotation.cpp similarity index 100% rename from openfpga/src/base/check_pb_type_annotation.cpp rename to openfpga/src/annotation/check_pb_type_annotation.cpp diff --git a/openfpga/src/base/check_pb_type_annotation.h b/openfpga/src/annotation/check_pb_type_annotation.h similarity index 100% rename from openfpga/src/base/check_pb_type_annotation.h rename to openfpga/src/annotation/check_pb_type_annotation.h diff --git a/openfpga/src/base/vpr_netlist_annotation.cpp b/openfpga/src/annotation/vpr_netlist_annotation.cpp similarity index 100% rename from openfpga/src/base/vpr_netlist_annotation.cpp rename to openfpga/src/annotation/vpr_netlist_annotation.cpp diff --git a/openfpga/src/base/vpr_netlist_annotation.h b/openfpga/src/annotation/vpr_netlist_annotation.h similarity index 100% rename from openfpga/src/base/vpr_netlist_annotation.h rename to openfpga/src/annotation/vpr_netlist_annotation.h diff --git a/openfpga/src/base/vpr_pb_type_annotation.cpp b/openfpga/src/annotation/vpr_pb_type_annotation.cpp similarity index 100% rename from openfpga/src/base/vpr_pb_type_annotation.cpp rename to openfpga/src/annotation/vpr_pb_type_annotation.cpp diff --git a/openfpga/src/base/vpr_pb_type_annotation.h b/openfpga/src/annotation/vpr_pb_type_annotation.h similarity index 100% rename from openfpga/src/base/vpr_pb_type_annotation.h rename to openfpga/src/annotation/vpr_pb_type_annotation.h From d62c9fe86f85c307ed70576b357300de9c0600a2 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Thu, 30 Jan 2020 16:40:13 -0700 Subject: [PATCH 3/4] adding pb_graph_node annotation --- openfpga/src/annotation/annotate_pb_graph.cpp | 145 ++++++++++++++++++ openfpga/src/annotation/annotate_pb_graph.h | 3 + openfpga/src/annotation/annotate_pb_types.cpp | 22 ++- .../src/annotation/vpr_pb_type_annotation.cpp | 132 ++++++++++++++++ .../src/annotation/vpr_pb_type_annotation.h | 33 ++++ openfpga/src/base/openfpga_link_arch.cpp | 8 +- 6 files changed, 339 insertions(+), 4 deletions(-) diff --git a/openfpga/src/annotation/annotate_pb_graph.cpp b/openfpga/src/annotation/annotate_pb_graph.cpp index 82e214067..bb9ab08c8 100644 --- a/openfpga/src/annotation/annotate_pb_graph.cpp +++ b/openfpga/src/annotation/annotate_pb_graph.cpp @@ -118,5 +118,150 @@ void annotate_pb_graph_interconnect_physical_type(const DeviceContext& vpr_devic } } +/******************************************************************** + * This function will recursively walk through all the pb_graph nodes + * starting from a top node. + * It aims to give an unique index to each pb_graph node + * + * Therefore, the sequence in visiting the nodes is critical + * Here, we will follow the strategy where primitive nodes are visited first + *******************************************************************/ +static +void rec_build_vpr_primitive_pb_graph_node_unique_index(t_pb_graph_node* pb_graph_node, + VprPbTypeAnnotation& vpr_pb_type_annotation) { + /* 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_build_vpr_primitive_pb_graph_node_unique_index(&(pb_graph_node->child_pb_graph_nodes[imode][ipb][jpb]), + vpr_pb_type_annotation); + } + } + } + return; + } + + /* Give a unique index to the pb_graph_node */ + vpr_pb_type_annotation.add_pb_graph_node_unique_index(pb_graph_node); +} + +/******************************************************************** + * This function aims to assign an unique index to each + * primitive pb_graph_node by following a recursive way in walking + * through the pb_graph + * + * Note: + * - The unique index is different from the placement_index in VPR's + * pb_graph_node data structure. The placement index is only unique + * for a node under its parent node. If the parent node is duplicated + * across the graph, the placement index is not unique. + * For example, a CLB contains 10 LEs and each of LE contains 2 LUTs + * Inside each LE, the placement index of the LUTs are 0 and 1 respectively. + * But these indices are not unique in the graph, as there are 20 LUTs in total + *******************************************************************/ +static +void annotate_primitive_pb_graph_node_unique_index(const DeviceContext& vpr_device_ctx, + VprPbTypeAnnotation& vpr_pb_type_annotation) { + 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_primitive_pb_graph_node_unique_index(lb_type.pb_graph_head, vpr_pb_type_annotation); + } +} + +/******************************************************************** + * This function will recursively walk through all the pb_graph nodes + * starting from a top node. + * It aims to give an unique index to each pb_graph node + * + * Therefore, the sequence in visiting the nodes is critical + * Here, we will follow the strategy where primitive nodes are visited first + *******************************************************************/ +static +void rec_build_vpr_physical_pb_graph_node_annotation(t_pb_graph_node* pb_graph_node, + VprPbTypeAnnotation& vpr_pb_type_annotation) { + /* 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_build_vpr_physical_pb_graph_node_annotation(&(pb_graph_node->child_pb_graph_nodes[imode][ipb][jpb]), + vpr_pb_type_annotation); + } + } + } + return; + } + + /* To bind operating pb_graph_node to their physical pb_graph_node: + * - Get the physical pb_type that this type of pb_graph_node should be mapped to + * - Calculate the unique index of physical pb_graph_node to which + * this pb_graph_node should be binded + * - Find the physical pb_graph_node with the given index + * To bind pins from operating pb_graph_node to their physical pb_graph_node pins + */ + t_pb_type* physical_pb_type = vpr_pb_type_annotation.physical_pb_type(pb_graph_node->pb_type); + VTR_ASSERT(nullptr != physical_pb_type); + + /* Index inference: + * physical_pb_graph_node_unique_index = operating_pb_graph_node_unique_index * factor + offset + * where factor and offset are provided by users + */ + PbGraphNodeId physical_pb_graph_node_id = PbGraphNodeId( + vpr_pb_type_annotation.physical_pb_type_index_factor(pb_graph_node->pb_type) + * (size_t)vpr_pb_type_annotation.pb_graph_node_unique_index(pb_graph_node) + + vpr_pb_type_annotation.physical_pb_type_index_offset(pb_graph_node->pb_type) + ); + t_pb_graph_node* physical_pb_graph_node = vpr_pb_type_annotation.pb_graph_node(pb_graph_node->pb_type, physical_pb_graph_node_id); + 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()); + + /* Try to bind each pins under this pb_graph_node to physical_pb_graph_node */ +} + +/******************************************************************** + * Find the physical pb_graph_node for each primitive pb_graph_node + * - Bind operating pb_graph_node to their physical pb_graph_node + * - Bind pins from operating pb_graph_node to their physical pb_graph_node pins + *******************************************************************/ +static +void annotate_physical_pb_graph_node(const DeviceContext& vpr_device_ctx, + VprPbTypeAnnotation& vpr_pb_type_annotation) { + 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); + } +} + +/******************************************************************** + * Top-level function to annotate all the pb_graph nodes and pins + * - Give unique index to each primitive node in the same type + * - Bind operating pb_graph_node to their physical pb_graph_node + * - 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) { + + VTR_LOG("Assigning unique indices for primitive pb_graph nodes..."); + 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("Done\n"); +} + } /* end namespace openfpga */ diff --git a/openfpga/src/annotation/annotate_pb_graph.h b/openfpga/src/annotation/annotate_pb_graph.h index 8749cd28f..e809d3cfa 100644 --- a/openfpga/src/annotation/annotate_pb_graph.h +++ b/openfpga/src/annotation/annotate_pb_graph.h @@ -18,6 +18,9 @@ namespace openfpga { void annotate_pb_graph_interconnect_physical_type(const DeviceContext& vpr_device_ctx, VprPbTypeAnnotation& vpr_pb_type_annotation); +void annotate_pb_graph(const DeviceContext& vpr_device_ctx, + VprPbTypeAnnotation& vpr_pb_type_annotation); + } /* end namespace openfpga */ #endif diff --git a/openfpga/src/annotation/annotate_pb_types.cpp b/openfpga/src/annotation/annotate_pb_types.cpp index 023154c9b..fb2905637 100644 --- a/openfpga/src/annotation/annotate_pb_types.cpp +++ b/openfpga/src/annotation/annotate_pb_types.cpp @@ -223,13 +223,24 @@ bool pair_operating_and_physical_pb_types(t_pb_type* operating_pb_type, if (false == expected_physical_pb_port.contained(BasicPort(physical_pb_port->name, physical_pb_port->num_pins))) { return false; } - /* Now, port mapping should succeed, we update the vpr_pb_type_annotation */ + /* Now, port mapping should succeed, we update the vpr_pb_type_annotation + * - port binding + * - port range + * - port pin rotate offset + */ vpr_pb_type_annotation.add_physical_pb_port(operating_pb_port, physical_pb_port); vpr_pb_type_annotation.add_physical_pb_port_range(operating_pb_port, expected_physical_pb_port); + vpr_pb_type_annotation.add_physical_pb_pin_rotate_offset(operating_pb_port, pb_type_annotation.physical_pin_rotate_offset(std::string(operating_pb_port->name))); } - /* Now, pb_type mapping should succeed, we update the vpr_pb_type_annotation */ + /* Now, pb_type mapping should succeed, we update the vpr_pb_type_annotation + * - pb_type binding + * - physical_pb_type_index_factor + * - physical_pb_type_index_offset + */ vpr_pb_type_annotation.add_physical_pb_type(operating_pb_type, physical_pb_type); + vpr_pb_type_annotation.add_physical_pb_type_index_factor(operating_pb_type, pb_type_annotation.physical_pb_type_index_factor()); + vpr_pb_type_annotation.add_physical_pb_type_index_offset(operating_pb_type, pb_type_annotation.physical_pb_type_index_offset()); return true; } @@ -987,7 +998,12 @@ void annotate_pb_types(const DeviceContext& vpr_device_ctx, vpr_pb_type_annotation); VTR_LOG("Done\n"); - /* Annotate physical pb_types to operating pb_type in the VPR pb_type graph */ + /* Annotate physical pb_types to operating pb_type in the VPR pb_type graph + * This function will also annotate + * - pb_type_index_factor + * - pb_type_index_offset + * - physical_pin_rotate_offset + */ VTR_LOG("\n"); VTR_LOG("Building annotation between operating and physical pb_types...\n"); build_vpr_physical_pb_type_explicit_annotation(vpr_device_ctx, openfpga_arch, diff --git a/openfpga/src/annotation/vpr_pb_type_annotation.cpp b/openfpga/src/annotation/vpr_pb_type_annotation.cpp index 435f46be7..407907e59 100644 --- a/openfpga/src/annotation/vpr_pb_type_annotation.cpp +++ b/openfpga/src/annotation/vpr_pb_type_annotation.cpp @@ -1,6 +1,8 @@ /************************************************************************ * Member functions for class VprPbTypeAnnotation ***********************************************************************/ +#include + #include "vtr_log.h" #include "vtr_assert.h" #include "vpr_pb_type_annotation.h" @@ -115,6 +117,84 @@ std::vector VprPbTypeAnnotation::pb_type_mode_bits(t_pb_type* pb_type) c return pb_type_mode_bits_.at(pb_type); } +PbGraphNodeId VprPbTypeAnnotation::pb_graph_node_unique_index(t_pb_graph_node* pb_graph_node) const { + /* Ensure that the pb_type is in the list */ + std::map>::const_iterator it = pb_graph_node_unique_index_.find(pb_graph_node->pb_type); + if (it == pb_graph_node_unique_index_.end()) { + /* Invalid pb_type, return a null pointer */ + return PbGraphNodeId::INVALID(); + } + + /* Try to find the pb_graph_node in the vector */ + std::vector::const_iterator it_node = std::find(pb_graph_node_unique_index_.at(pb_graph_node->pb_type).begin(), + pb_graph_node_unique_index_.at(pb_graph_node->pb_type).end(), + pb_graph_node); + /* If it exists, return the index + * Otherwise, return an invalid id + */ + if (it_node == pb_graph_node_unique_index_.at(pb_graph_node->pb_type).end()) { + return PbGraphNodeId::INVALID(); + } + return PbGraphNodeId(it_node - pb_graph_node_unique_index_.at(pb_graph_node->pb_type).begin()); +} + +t_pb_graph_node* VprPbTypeAnnotation::pb_graph_node(t_pb_type* pb_type, const PbGraphNodeId& unique_index) const { + /* Ensure that the pb_type is in the list */ + std::map>::const_iterator it = pb_graph_node_unique_index_.find(pb_type); + if (it == pb_graph_node_unique_index_.end()) { + /* Invalid pb_type, return a null pointer */ + return nullptr; + } + /* Check if the unique index is in the range: + * - Out of range: return a null pointer + * - In range: return the pointer + */ + if ((size_t)unique_index > pb_graph_node_unique_index_.at(pb_type).size() - 1) { + return nullptr; + } + + return pb_graph_node_unique_index_.at(pb_type)[size_t(unique_index)]; +} + +t_pb_graph_node* VprPbTypeAnnotation::physical_pb_graph_node(t_pb_graph_node* pb_graph_node) const { + /* Ensure that the pb_graph_node is in the list */ + std::map::const_iterator it = physical_pb_graph_nodes_.find(pb_graph_node); + if (it == physical_pb_graph_nodes_.end()) { + return nullptr; + } + return physical_pb_graph_nodes_.at(pb_graph_node); +} + +int VprPbTypeAnnotation::physical_pb_type_index_factor(t_pb_type* pb_type) const { + /* Ensure that the pb_type is in the list */ + std::map::const_iterator it = physical_pb_type_index_factors_.find(pb_type); + if (it == physical_pb_type_index_factors_.end()) { + /* Default value is 1 */ + return 1; + } + return physical_pb_type_index_factors_.at(pb_type); +} + +int VprPbTypeAnnotation::physical_pb_type_index_offset(t_pb_type* pb_type) const { + /* Ensure that the pb_type is in the list */ + std::map::const_iterator it = physical_pb_type_index_offsets_.find(pb_type); + if (it == physical_pb_type_index_offsets_.end()) { + /* Default value is 0 */ + return 0; + } + return physical_pb_type_index_offsets_.at(pb_type); +} + +int VprPbTypeAnnotation::physical_pb_pin_rotate_offset(t_port* pb_port) const { + /* Ensure that the pb_type is in the list */ + std::map::const_iterator it = physical_pb_pin_rotate_offsets_.find(pb_port); + if (it == physical_pb_pin_rotate_offsets_.end()) { + /* Default value is 0 */ + return 0; + } + return physical_pb_pin_rotate_offsets_.at(pb_port); +} + /************************************************************************ * Public mutators ***********************************************************************/ @@ -221,4 +301,56 @@ void VprPbTypeAnnotation::add_pb_type_mode_bits(t_pb_type* pb_type, const std::v pb_type_mode_bits_[pb_type] = mode_bits; } +void VprPbTypeAnnotation::add_pb_graph_node_unique_index(t_pb_graph_node* pb_graph_node) { + pb_graph_node_unique_index_[pb_graph_node->pb_type].push_back(pb_graph_node); +} + +void VprPbTypeAnnotation::add_physical_pb_graph_node(t_pb_graph_node* operating_pb_graph_node, + t_pb_graph_node* physical_pb_graph_node) { + /* Warn any override attempt */ + std::map::const_iterator it = physical_pb_graph_nodes_.find(operating_pb_graph_node); + if (it != physical_pb_graph_nodes_.end()) { + VTR_LOG_WARN("Override the annotation between operating pb_graph_node '%s[%d]' and it physical pb_graph_node '%s[%d]'!\n", + operating_pb_graph_node->pb_type->name, + operating_pb_graph_node->placement_index, + physical_pb_graph_node->pb_type->name, + physical_pb_graph_node->placement_index); + } + + physical_pb_graph_nodes_[operating_pb_graph_node] = physical_pb_graph_node; +} + +void VprPbTypeAnnotation::add_physical_pb_type_index_factor(t_pb_type* pb_type, const int& factor) { + /* Warn any override attempt */ + std::map::const_iterator it = physical_pb_type_index_factors_.find(pb_type); + if (it != physical_pb_type_index_factors_.end()) { + VTR_LOG_WARN("Override the annotation between operating pb_type '%s' and it physical pb_type index factor '%d'!\n", + pb_type->name, factor); + } + + physical_pb_type_index_factors_[pb_type] = factor; +} + +void VprPbTypeAnnotation::add_physical_pb_type_index_offset(t_pb_type* pb_type, const int& offset) { + /* Warn any override attempt */ + std::map::const_iterator it = physical_pb_type_index_offsets_.find(pb_type); + if (it != physical_pb_type_index_offsets_.end()) { + VTR_LOG_WARN("Override the annotation between operating pb_type '%s' and it physical pb_type index offset '%d'!\n", + pb_type->name, offset); + } + + physical_pb_type_index_offsets_[pb_type] = offset; +} + +void VprPbTypeAnnotation::add_physical_pb_pin_rotate_offset(t_port* pb_port, const int& offset) { + /* Warn any override attempt */ + std::map::const_iterator it = physical_pb_pin_rotate_offsets_.find(pb_port); + if (it != physical_pb_pin_rotate_offsets_.end()) { + VTR_LOG_WARN("Override the annotation between operating pb_port '%s' and it physical pb_port pin rotate offset '%d'!\n", + pb_port->name, offset); + } + + physical_pb_pin_rotate_offsets_[pb_port] = offset; +} + } /* End namespace openfpga*/ diff --git a/openfpga/src/annotation/vpr_pb_type_annotation.h b/openfpga/src/annotation/vpr_pb_type_annotation.h index 24535ee4a..bcdff9e3e 100644 --- a/openfpga/src/annotation/vpr_pb_type_annotation.h +++ b/openfpga/src/annotation/vpr_pb_type_annotation.h @@ -6,6 +6,9 @@ *******************************************************************/ #include +/* Header from vtrutil library */ +#include "vtr_strong_id.h" + /* Header from archfpga library */ #include "physical_types.h" @@ -16,6 +19,11 @@ /* Begin namespace openfpga */ namespace openfpga { +/* Unique index for pb_graph node */ +struct pb_graph_node_id_tag; + +typedef vtr::StrongId PbGraphNodeId; + /******************************************************************** * This is the critical data structure to link the pb_type in VPR * to openfpga annotations @@ -39,6 +47,14 @@ class VprPbTypeAnnotation { e_interconnect interconnect_physical_type(t_interconnect* pb_interconnect) const; CircuitPortId pb_circuit_port(t_port* pb_port) const; std::vector pb_type_mode_bits(t_pb_type* pb_type) const; + /* Get the unique index of a pb_graph_node */ + PbGraphNodeId pb_graph_node_unique_index(t_pb_graph_node* pb_graph_node) const; + /* Get the pointer to a pb_graph node using an unique index */ + t_pb_graph_node* pb_graph_node(t_pb_type* pb_type, const PbGraphNodeId& unique_index) const; + t_pb_graph_node* physical_pb_graph_node(t_pb_graph_node* pb_graph_node) const; + int physical_pb_type_index_factor(t_pb_type* pb_type) const; + int physical_pb_type_index_offset(t_pb_type* pb_type) const; + int physical_pb_pin_rotate_offset(t_port* pb_port) const; public: /* Public mutators */ void add_pb_type_physical_mode(t_pb_type* pb_type, t_mode* physical_mode); void add_physical_pb_type(t_pb_type* operating_pb_type, t_pb_type* physical_pb_type); @@ -49,9 +65,17 @@ class VprPbTypeAnnotation { void add_interconnect_physical_type(t_interconnect* pb_interconnect, const e_interconnect& physical_type); void add_pb_circuit_port(t_port* pb_port, const CircuitPortId& circuit_port); void add_pb_type_mode_bits(t_pb_type* pb_type, const std::vector& mode_bits); + void add_pb_graph_node_unique_index(t_pb_graph_node* pb_graph_node); + void add_physical_pb_graph_node(t_pb_graph_node* operating_pb_graph_node, + t_pb_graph_node* physical_pb_graph_node); + void add_physical_pb_type_index_factor(t_pb_type* pb_type, const int& factor); + void add_physical_pb_type_index_offset(t_pb_type* pb_type, const int& offset); + void add_physical_pb_pin_rotate_offset(t_port* pb_port, const int& offset); private: /* Internal data */ /* Pair a regular pb_type to its physical pb_type */ std::map physical_pb_types_; + std::map physical_pb_type_index_factors_; + std::map physical_pb_type_index_offsets_; /* Pair a physical mode for a pb_type * Note: @@ -91,6 +115,7 @@ class VprPbTypeAnnotation { * - the parent of physical pb_port MUST be a physical pb_type */ std::map physical_pb_ports_; + std::map physical_pb_pin_rotate_offsets_; /* Pair a pb_port to its LSB and MSB of a physical pb_port * Note: @@ -104,11 +129,19 @@ class VprPbTypeAnnotation { */ std::map pb_circuit_ports_; + /* Pair each pb_graph_node to an unique index in the graph + * The unique index if the index in the array of t_pb_graph_node* + */ + std::map> pb_graph_node_unique_index_; + /* Pair a pb_graph_node to a physical pb_graph_node * Note: * - the pb_type of physical pb_graph_node must be a physical pb_type */ std::map physical_pb_graph_nodes_; + + /* Pair a pb_graph_pin to a physical pb_graph_pin */ + std::map physical_pb_graph_pins_; }; } /* End namespace openfpga*/ diff --git a/openfpga/src/base/openfpga_link_arch.cpp b/openfpga/src/base/openfpga_link_arch.cpp index a30453d1c..e6762485e 100644 --- a/openfpga/src/base/openfpga_link_arch.cpp +++ b/openfpga/src/base/openfpga_link_arch.cpp @@ -39,7 +39,13 @@ void link_arch(OpenfpgaContext& openfpga_context) { annotate_pb_types(g_vpr_ctx.device(), openfpga_context.arch(), openfpga_context.mutable_vpr_pb_type_annotation()); - /* Link routing architecture to circuit model */ + /* Annotate pb_graph_nodes + * - Give unique index to each node in the same type + * - Bind operating pb_graph_node to their physical pb_graph_node + * - 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()); } } /* end namespace openfpga */ From 007e1997e63e2a6b0b028a009e1f64f4262dcb15 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Thu, 30 Jan 2020 19:40:40 -0700 Subject: [PATCH 4/4] add pb_graph pin annotation --- openfpga/src/annotation/annotate_pb_graph.cpp | 167 ++++++++++++++++++ .../src/annotation/vpr_pb_type_annotation.cpp | 59 +++++++ .../src/annotation/vpr_pb_type_annotation.h | 15 ++ 3 files changed, 241 insertions(+) diff --git a/openfpga/src/annotation/annotate_pb_graph.cpp b/openfpga/src/annotation/annotate_pb_graph.cpp index bb9ab08c8..fb94bc238 100644 --- a/openfpga/src/annotation/annotate_pb_graph.cpp +++ b/openfpga/src/annotation/annotate_pb_graph.cpp @@ -173,6 +173,172 @@ void annotate_primitive_pb_graph_node_unique_index(const DeviceContext& vpr_devi } } +/******************************************************************** + * Evaluate if the two pb_graph pins are matched by + * - pb_type port annotation + * - LSB/MSB and pin offset + *******************************************************************/ +static +bool try_match_pb_graph_pin(t_pb_graph_pin* operating_pb_graph_pin, + t_pb_graph_pin* physical_pb_graph_pin, + const VprPbTypeAnnotation& vpr_pb_type_annotation) { + /* If the parent ports of the two pins are not paired, fail */ + if (physical_pb_graph_pin->port != vpr_pb_type_annotation.physical_pb_port(operating_pb_graph_pin->port)) { + return false; + } + /* Check the pin number of physical pb_graph_pin matches the pin number of + * operating pb_graph_pin plus a rotation offset + * operating port physical port + * LSB port_range.lsb() pin_number pin_number MSB + * | | | + * Operating port | | +------ | + * | |<----offset--->| + * Physical port | + + + + * + * Note: + * - accumulated offset is NOT the pin rotate offset specified by users + * It is an aggregation of the offset during pin pairing + * Each time, we manage to pair two pins, the accumulated offset will be incremented + * by the pin rotate offset value + * The accumulated offset will be reset to 0 when it exceeds the msb() of the physical port + */ + int acc_offset = vpr_pb_type_annotation.physical_pb_pin_offset(operating_pb_graph_pin->port); + const BasicPort& physical_port_range = vpr_pb_type_annotation.physical_pb_port_range(operating_pb_graph_pin->port); + if (physical_pb_graph_pin->pin_number != operating_pb_graph_pin->pin_number + + (int)physical_port_range.get_lsb() + + acc_offset) { + return false; + } + + /* Reach here, it means all the requirements have been met */ + return true; +} + +/******************************************************************** + * Bind a pb_graph_pin from an operating pb_graph_node to + * a pb_graph_pin from a physical pb_graph_node + * - the name matching rules are already defined in the vpr_pb_type_annotation + *******************************************************************/ +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) { + /* Iterate over every port and pin of the operating pb_graph_node + * and find the physical pins + */ + 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 == try_match_pb_graph_pin(operating_pb_graph_pin, + &(physical_pb_graph_node->input_pins[iport][ipin]), + vpr_pb_type_annotation)) { + continue; + } + /* Reach here, it means the pins are matched by the annotation requirements + * 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); + return; + } + } + + 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 == try_match_pb_graph_pin(operating_pb_graph_pin, + &(physical_pb_graph_node->output_pins[iport][ipin]), + vpr_pb_type_annotation)) { + continue; + } + /* Reach here, it means the pins are matched by the annotation requirements + * 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); + return; + } + } + + 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 == try_match_pb_graph_pin(operating_pb_graph_pin, + &(physical_pb_graph_node->clock_pins[iport][ipin]), + vpr_pb_type_annotation)) { + continue; + } + /* Reach here, it means the pins are matched by the annotation requirements + * 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); + return; + } + } + + /* If we reach here, it means that pin pairing fails, error out! */ + VTR_LOG_ERROR("Fail to match a physical pin for '%s' from pb_graph_node '%s'!\n", + operating_pb_graph_pin->port->name, + physical_pb_graph_node->hierarchical_type_name().c_str()); +} + +/******************************************************************** + * This function will try bind each pin of the operating pb_graph_node + * to a pin of the physical pb_graph_node by following the annotation + * available in vpr_pb_type_annotation + * It will add the pin bindings to the vpr_pb_type_annotation + *******************************************************************/ +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) { + /* 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); + } + } + + 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); + } + } + + 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); + } + } +} + /******************************************************************** * This function will recursively walk through all the pb_graph nodes * starting from a top node. @@ -226,6 +392,7 @@ void rec_build_vpr_physical_pb_graph_node_annotation(t_pb_graph_node* pb_graph_n 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); } /******************************************************************** diff --git a/openfpga/src/annotation/vpr_pb_type_annotation.cpp b/openfpga/src/annotation/vpr_pb_type_annotation.cpp index 407907e59..3204dd597 100644 --- a/openfpga/src/annotation/vpr_pb_type_annotation.cpp +++ b/openfpga/src/annotation/vpr_pb_type_annotation.cpp @@ -195,6 +195,26 @@ int VprPbTypeAnnotation::physical_pb_pin_rotate_offset(t_port* pb_port) const { return physical_pb_pin_rotate_offsets_.at(pb_port); } +int VprPbTypeAnnotation::physical_pb_pin_offset(t_port* pb_port) const { + /* Ensure that the pb_type is in the list */ + std::map::const_iterator it = physical_pb_pin_offsets_.find(pb_port); + if (it == physical_pb_pin_offsets_.end()) { + /* Default value is 0 */ + return 0; + } + return physical_pb_pin_offsets_.at(pb_port); +} + + +t_pb_graph_pin* VprPbTypeAnnotation::physical_pb_graph_pin(t_pb_graph_pin* pb_graph_pin) const { + /* Ensure that the pb_type is in the list */ + std::map::const_iterator it = physical_pb_graph_pins_.find(pb_graph_pin); + if (it == physical_pb_graph_pins_.end()) { + return nullptr; + } + return physical_pb_graph_pins_.at(pb_graph_pin); +} + /************************************************************************ * Public mutators ***********************************************************************/ @@ -351,6 +371,45 @@ void VprPbTypeAnnotation::add_physical_pb_pin_rotate_offset(t_port* pb_port, con } physical_pb_pin_rotate_offsets_[pb_port] = offset; + /* We initialize the accumulated offset to 0 */ + physical_pb_pin_offsets_[pb_port] = 0; +} + +void VprPbTypeAnnotation::add_physical_pb_graph_pin(t_pb_graph_pin* operating_pb_graph_pin, + t_pb_graph_pin* physical_pb_graph_pin) { + /* Warn any override attempt */ + std::map::const_iterator it = physical_pb_graph_pins_.find(operating_pb_graph_pin); + if (it != physical_pb_graph_pins_.end()) { + VTR_LOG_WARN("Override the annotation between operating pb_graph_pin '%s' and it physical pb_graph_pin '%s'!\n", + operating_pb_graph_pin->port->name, physical_pb_graph_pin->port->name); + } + + physical_pb_graph_pins_[operating_pb_graph_pin] = physical_pb_graph_pin; + + /* Update the accumulated offsets for the operating port + * Each time we pair two pins, we update the offset by the pin rotate offset + * When the accumulated offset exceeds the MSB of the port range of physical port + * we reset it to 0 + * operating port physical port + * LSB port_range.lsb() pin_number pin_number MSB + * | | | + * Operating port | | +------ | + * | |<----offset--->| + * Physical port | + + + + * + */ + if (0 == physical_pb_pin_rotate_offset(operating_pb_graph_pin->port)) { + return; + } + + physical_pb_pin_offsets_[operating_pb_graph_pin->port] += physical_pb_pin_rotate_offset(operating_pb_graph_pin->port); + + if (physical_pb_port_range(operating_pb_graph_pin->port).get_msb() + < operating_pb_graph_pin->pin_number + + physical_pb_port_range(operating_pb_graph_pin->port).get_lsb() + + physical_pb_pin_offset(operating_pb_graph_pin->port)) { + physical_pb_pin_offsets_[operating_pb_graph_pin->port] = 0; + } } } /* End namespace openfpga*/ diff --git a/openfpga/src/annotation/vpr_pb_type_annotation.h b/openfpga/src/annotation/vpr_pb_type_annotation.h index bcdff9e3e..add45e42d 100644 --- a/openfpga/src/annotation/vpr_pb_type_annotation.h +++ b/openfpga/src/annotation/vpr_pb_type_annotation.h @@ -54,7 +54,18 @@ class VprPbTypeAnnotation { t_pb_graph_node* physical_pb_graph_node(t_pb_graph_node* pb_graph_node) const; int physical_pb_type_index_factor(t_pb_type* pb_type) const; int physical_pb_type_index_offset(t_pb_type* pb_type) const; + int physical_pb_pin_rotate_offset(t_port* pb_port) const; + + /**This function returns an accumulated offset. Note that the + * accumulated offset is NOT the pin rotate offset specified by users + * It is an aggregation of the offset during pin pairing + * Each time, we manage to pair two pins, the accumulated offset will be incremented + * by the pin rotate offset value + * The accumulated offset will be reset to 0 when it exceeds the msb() of the physical port + */ + int physical_pb_pin_offset(t_port* pb_port) const; + t_pb_graph_pin* physical_pb_graph_pin(t_pb_graph_pin* pb_graph_pin) const; public: /* Public mutators */ void add_pb_type_physical_mode(t_pb_type* pb_type, t_mode* physical_mode); void add_physical_pb_type(t_pb_type* operating_pb_type, t_pb_type* physical_pb_type); @@ -71,6 +82,7 @@ class VprPbTypeAnnotation { void add_physical_pb_type_index_factor(t_pb_type* pb_type, const int& factor); void add_physical_pb_type_index_offset(t_pb_type* pb_type, const int& offset); void add_physical_pb_pin_rotate_offset(t_port* pb_port, const int& offset); + void add_physical_pb_graph_pin(t_pb_graph_pin* operating_pb_graph_pin, t_pb_graph_pin* physical_pb_graph_pin); private: /* Internal data */ /* Pair a regular pb_type to its physical pb_type */ std::map physical_pb_types_; @@ -117,6 +129,9 @@ class VprPbTypeAnnotation { std::map physical_pb_ports_; std::map physical_pb_pin_rotate_offsets_; + /* Accumulated offsets for a physical pb_type port, just for internal usage */ + std::map physical_pb_pin_offsets_; + /* Pair a pb_port to its LSB and MSB of a physical pb_port * Note: * - the LSB and MSB MUST be in range of the physical pb_port