adding pb_graph_node annotation

This commit is contained in:
tangxifan 2020-01-30 16:40:13 -07:00
parent e48ab8cb44
commit d62c9fe86f
6 changed files with 339 additions and 4 deletions

View File

@ -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 */

View File

@ -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

View File

@ -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,

View File

@ -1,6 +1,8 @@
/************************************************************************
* Member functions for class VprPbTypeAnnotation
***********************************************************************/
#include <algorithm>
#include "vtr_log.h"
#include "vtr_assert.h"
#include "vpr_pb_type_annotation.h"
@ -115,6 +117,84 @@ std::vector<size_t> 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<t_pb_type*, std::vector<t_pb_graph_node*>>::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<t_pb_graph_node*>::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<t_pb_type*, std::vector<t_pb_graph_node*>>::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<t_pb_graph_node*, t_pb_graph_node*>::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<t_pb_type*, int>::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<t_pb_type*, int>::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<t_port*, int>::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<t_pb_graph_node*, t_pb_graph_node*>::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<t_pb_type*, int>::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<t_pb_type*, int>::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<t_port*, int>::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*/

View File

@ -6,6 +6,9 @@
*******************************************************************/
#include <map>
/* 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<pb_graph_node_id_tag> 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<size_t> 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<size_t>& 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<t_pb_type*, t_pb_type*> physical_pb_types_;
std::map<t_pb_type*, int> physical_pb_type_index_factors_;
std::map<t_pb_type*, int> 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<t_port*, t_port*> physical_pb_ports_;
std::map<t_port*, int> 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<t_port*, CircuitPortId> 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<t_pb_type*, std::vector<t_pb_graph_node*>> 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<t_pb_graph_node*, t_pb_graph_node*> physical_pb_graph_nodes_;
/* Pair a pb_graph_pin to a physical pb_graph_pin */
std::map<t_pb_graph_pin*, t_pb_graph_pin*> physical_pb_graph_pins_;
};
} /* End namespace openfpga*/

View File

@ -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 */