add pb_graph pin annotation

This commit is contained in:
tangxifan 2020-01-30 19:40:40 -07:00
parent d62c9fe86f
commit 007e1997e6
3 changed files with 241 additions and 0 deletions

View File

@ -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);
}
/********************************************************************

View File

@ -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<t_port*, int>::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<t_pb_graph_pin*, t_pb_graph_pin*>::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<t_pb_graph_pin*, t_pb_graph_pin*>::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*/

View File

@ -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<t_pb_type*, t_pb_type*> physical_pb_types_;
@ -117,6 +129,9 @@ class VprPbTypeAnnotation {
std::map<t_port*, t_port*> physical_pb_ports_;
std::map<t_port*, int> physical_pb_pin_rotate_offsets_;
/* Accumulated offsets for a physical pb_type port, just for internal usage */
std::map<t_port*, int> 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