add physical type annotation for interconnects and inference
This commit is contained in:
parent
bb7fa2af77
commit
8a7a4dc48e
|
@ -162,7 +162,8 @@ enum e_pin_type {
|
|||
enum e_interconnect {
|
||||
COMPLETE_INTERC = 1,
|
||||
DIRECT_INTERC = 2,
|
||||
MUX_INTERC = 3
|
||||
MUX_INTERC = 3,
|
||||
NUM_INTERC_TYPES
|
||||
};
|
||||
|
||||
/* Orientations. */
|
||||
|
|
|
@ -0,0 +1,122 @@
|
|||
/********************************************************************
|
||||
* This file includes functions that are used to annotate pb_graph_node
|
||||
* and pb_graph_pins from VPR to OpenFPGA
|
||||
*******************************************************************/
|
||||
/* Headers from vtrutil library */
|
||||
#include "vtr_assert.h"
|
||||
#include "vtr_log.h"
|
||||
|
||||
#include "pb_type_utils.h"
|
||||
#include "pb_graph_utils.h"
|
||||
|
||||
#include "annotate_pb_graph.h"
|
||||
|
||||
/* begin namespace openfpga */
|
||||
namespace openfpga {
|
||||
|
||||
/********************************************************************
|
||||
* This function will recursively walk through all the pb_graph nodes
|
||||
* starting from a top node.
|
||||
* It aims to annotate the physical type of each interconnect.
|
||||
* This is due to that the type of interconnect 'complete' may diverge
|
||||
* in physical implmentation.
|
||||
* - When there is only one input driving a 'complete' interconnection,
|
||||
* it will be implemented with wires
|
||||
* - When there are multiple inputs driving a 'complete' interconnection,
|
||||
* it will be implemented with routing multiplexers
|
||||
*******************************************************************/
|
||||
static
|
||||
void rec_build_vpr_pb_graph_interconnect_physical_type_annotation(t_pb_graph_node* pb_graph_node,
|
||||
VprPbTypeAnnotation& vpr_pb_type_annotation) {
|
||||
/* Skip the root node because we start from the inputs of child pb_graph node
|
||||
*
|
||||
* pb_graph_node
|
||||
* +----------------------------------
|
||||
* | child_pb_graph_node
|
||||
* | +-----------------
|
||||
* | |
|
||||
* |-------------+-->input_pins
|
||||
* | |
|
||||
* |-------------+-->clock_pins
|
||||
* |
|
||||
*
|
||||
*/
|
||||
if (false == pb_graph_node->is_root()) {
|
||||
/* We only care the physical modes! But we have to find it through the parent node */
|
||||
t_mode* child_physical_mode = vpr_pb_type_annotation.physical_mode(pb_graph_node->parent_pb_graph_node->pb_type);
|
||||
VTR_ASSERT(nullptr != child_physical_mode);
|
||||
|
||||
std::map<t_interconnect*, size_t> interc_num_inputs;
|
||||
/* Initialize the counter */
|
||||
for (t_interconnect* interc : pb_mode_interconnects(child_physical_mode)) {
|
||||
interc_num_inputs[interc] = 0;
|
||||
}
|
||||
|
||||
/* We only care input and clock pins */
|
||||
for (int iport = 0; iport < pb_graph_node->num_input_ports; ++iport) {
|
||||
for (int ipin = 0; ipin < pb_graph_node->num_input_pins[iport]; ++ipin) {
|
||||
/* For each interconnect, we count the total number of inputs */
|
||||
for (t_interconnect* interc : pb_mode_interconnects(child_physical_mode)) {
|
||||
interc_num_inputs[interc] += pb_graph_pin_inputs(&(pb_graph_node->input_pins[iport][ipin]), interc).size();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (int iport = 0; iport < pb_graph_node->num_clock_ports; ++iport) {
|
||||
for (int ipin = 0; ipin < pb_graph_node->num_clock_pins[iport]; ++ipin) {
|
||||
/* For each interconnect, we count the total number of inputs */
|
||||
for (t_interconnect* interc : pb_mode_interconnects(child_physical_mode)) {
|
||||
interc_num_inputs[interc] += pb_graph_pin_inputs(&(pb_graph_node->clock_pins[iport][ipin]), interc).size();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* For each interconnect that has more than 1 input, we can infer the physical type */
|
||||
for (t_interconnect* interc : pb_mode_interconnects(child_physical_mode)) {
|
||||
e_interconnect interc_physical_type = pb_interconnect_physical_type(interc, interc_num_inputs[interc]);
|
||||
if (interc_physical_type == vpr_pb_type_annotation.interconnect_physical_type(interc)) {
|
||||
/* Skip annotation if we have already done! */
|
||||
continue;
|
||||
}
|
||||
vpr_pb_type_annotation.add_interconnect_physical_type(interc, interc_physical_type);
|
||||
}
|
||||
}
|
||||
|
||||
/* If we reach a primitive pb_graph node, we return */
|
||||
if (true == is_primitive_pb_type(pb_graph_node->pb_type)) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* Recursively visit all the child pb_graph_nodes */
|
||||
t_mode* physical_mode = vpr_pb_type_annotation.physical_mode(pb_graph_node->pb_type);
|
||||
VTR_ASSERT(nullptr != physical_mode);
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/********************************************************************
|
||||
* This function aims to annotate the physical type for each interconnect
|
||||
* inside the pb_graph
|
||||
*
|
||||
* Note:
|
||||
* - This function should be executed AFTER functions
|
||||
* build_vpr_physical_pb_mode_explicit_annotation()
|
||||
* build_vpr_physical_pb_mode_implicit_annotation()
|
||||
*******************************************************************/
|
||||
void annotate_pb_graph_interconnect_physical_type(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_pb_graph_interconnect_physical_type_annotation(lb_type.pb_graph_head, vpr_pb_type_annotation);
|
||||
}
|
||||
}
|
||||
|
||||
} /* end namespace openfpga */
|
||||
|
|
@ -0,0 +1,23 @@
|
|||
#ifndef ANNOTATE_PB_GRAPH_H
|
||||
#define ANNOTATE_PB_GRAPH_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 annotate_pb_graph_interconnect_physical_type(const DeviceContext& vpr_device_ctx,
|
||||
VprPbTypeAnnotation& vpr_pb_type_annotation);
|
||||
|
||||
} /* end namespace openfpga */
|
||||
|
||||
#endif
|
|
@ -9,6 +9,7 @@
|
|||
|
||||
#include "vpr_pb_type_annotation.h"
|
||||
#include "pb_type_utils.h"
|
||||
#include "annotate_pb_graph.h"
|
||||
#include "annotate_pb_types.h"
|
||||
|
||||
/* begin namespace openfpga */
|
||||
|
@ -843,6 +844,92 @@ void link_vpr_pb_interconnect_to_circuit_model_explicit_annotation(const DeviceC
|
|||
}
|
||||
}
|
||||
|
||||
/********************************************************************
|
||||
* This function will recursively visit all the pb_type from the top
|
||||
* pb_type in the graph and infer the circuit model for physical mode
|
||||
* of pb_types in VPR pb_type graph without OpenFPGA architecture XML
|
||||
*
|
||||
* Because only the interconnect in physical modes need circuit model
|
||||
* annotation, we will skip all the operating modes here
|
||||
*
|
||||
* Note:
|
||||
* - This function will automatically infer the type of circuit model
|
||||
* that is required and find the default circuit model in the type
|
||||
* - Interconnect type to Circuit mode type assumption:
|
||||
* - MUX_INTERC -> CIRCUIT_MODEL_MUX
|
||||
* - DIRECT_INTERC -> CIRCUIT_MODEL_WIRE
|
||||
* - COMPLETE_INTERC (single input) -> CIRCUIT_MODEL_WIRE
|
||||
* - COMPLETE_INTERC (multiple input pins) -> CIRCUIT_MODEL_MUX
|
||||
*******************************************************************/
|
||||
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) {
|
||||
/* We do not check any primitive pb_type */
|
||||
if (true == is_primitive_pb_type(cur_pb_type)) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* Get the physical mode from annotation */
|
||||
t_mode* physical_mode = vpr_pb_type_annotation.physical_mode(cur_pb_type);
|
||||
|
||||
VTR_ASSERT(nullptr != physical_mode);
|
||||
|
||||
/* Annotate the circuit model for each interconnect under this physical mode */
|
||||
for (t_interconnect* pb_interc : pb_mode_interconnects(physical_mode)) {
|
||||
/* If the interconnect has been annotated, we skip it */
|
||||
if (CircuitModelId::INVALID() != vpr_pb_type_annotation.interconnect_circuit_model(pb_interc)) {
|
||||
continue;
|
||||
}
|
||||
/* Infer the circuit model type for a given interconnect */
|
||||
e_circuit_model_type circuit_model_type = pb_interconnect_require_circuit_model_type(vpr_pb_type_annotation.interconnect_physical_type(pb_interc));
|
||||
/* Try to find a default circuit model from the circuit library */
|
||||
CircuitModelId default_circuit_model = circuit_lib.default_model(circuit_model_type);
|
||||
/* Update the annotation if the model id is valid */
|
||||
if (CircuitModelId::INVALID() == default_circuit_model) {
|
||||
VTR_LOG_ERROR("Unable to infer a circuit model for interconnect '%s' under physical mode '%s' of pb_type '%s'!\n",
|
||||
pb_interc->name,
|
||||
physical_mode->name,
|
||||
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);
|
||||
}
|
||||
|
||||
/* 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);
|
||||
}
|
||||
}
|
||||
|
||||
/********************************************************************
|
||||
* This function will infer the circuit model for each interconnect
|
||||
* under a physical mode of a pb_type in VPR pb_type graph without
|
||||
* OpenFPGA architecture XML
|
||||
*
|
||||
* Note:
|
||||
* This function must be executed AFTER the function
|
||||
* build_vpr_physical_pb_mode_explicit_annotation()
|
||||
* build_vpr_physical_pb_mode_implicit_annotation()
|
||||
*******************************************************************/
|
||||
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) {
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
/********************************************************************
|
||||
* Top-level function to link openfpga architecture to VPR, including:
|
||||
* - physical pb_type
|
||||
|
@ -862,6 +949,13 @@ void annotate_pb_types(const DeviceContext& vpr_device_ctx,
|
|||
check_vpr_physical_pb_mode_annotation(vpr_device_ctx,
|
||||
const_cast<const VprPbTypeAnnotation&>(vpr_pb_type_annotation));
|
||||
|
||||
/* Annotate the physical type for each interconnect under physical modes
|
||||
* Must run AFTER physical mode annotation is done and
|
||||
* BEFORE inferring the circuit model for interconnect
|
||||
*/
|
||||
annotate_pb_graph_interconnect_physical_type(vpr_device_ctx,
|
||||
vpr_pb_type_annotation);
|
||||
|
||||
/* Annotate physical pb_types to operating pb_type in the VPR pb_type graph */
|
||||
build_vpr_physical_pb_type_explicit_annotation(vpr_device_ctx, openfpga_arch,
|
||||
vpr_pb_type_annotation);
|
||||
|
@ -876,10 +970,13 @@ void annotate_pb_types(const DeviceContext& vpr_device_ctx,
|
|||
* - physical pb_type to circuit model
|
||||
* - interconnect of physical pb_type to circuit model
|
||||
*/
|
||||
/* TODO: link the pb_type port to circuit model port here! */
|
||||
link_vpr_pb_type_to_circuit_model_explicit_annotation(vpr_device_ctx, openfpga_arch,
|
||||
vpr_pb_type_annotation);
|
||||
link_vpr_pb_interconnect_to_circuit_model_explicit_annotation(vpr_device_ctx, openfpga_arch,
|
||||
vpr_pb_type_annotation);
|
||||
link_vpr_pb_interconnect_to_circuit_model_implicit_annotation(vpr_device_ctx, openfpga_arch.circuit_lib,
|
||||
vpr_pb_type_annotation);
|
||||
|
||||
/* Link physical pb_type to mode_bits */
|
||||
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
#include "vpr_pb_type_annotation.h"
|
||||
#include "pb_type_utils.h"
|
||||
#include "annotate_pb_types.h"
|
||||
#include "annotate_pb_graph.h"
|
||||
#include "openfpga_link_arch.h"
|
||||
|
||||
/* Include global variables of VPR */
|
||||
|
|
|
@ -0,0 +1,41 @@
|
|||
/********************************************************************
|
||||
* This file includes most utilized functions for the pb_graph_node
|
||||
* and pb_graph_pin data structure in the OpenFPGA context
|
||||
*******************************************************************/
|
||||
/* Headers from vtrutil library */
|
||||
#include "vtr_assert.h"
|
||||
#include "vtr_log.h"
|
||||
|
||||
#include "pb_graph_utils.h"
|
||||
|
||||
/* begin namespace openfpga */
|
||||
namespace openfpga {
|
||||
|
||||
/********************************************************************
|
||||
* This function aims to find out all the pb_graph_pins that drive
|
||||
* a given pb_graph pin w.r.t. a given interconnect definition
|
||||
*******************************************************************/
|
||||
std::vector<t_pb_graph_pin*> pb_graph_pin_inputs(t_pb_graph_pin* pb_graph_pin,
|
||||
t_interconnect* selected_interconnect) {
|
||||
std::vector<t_pb_graph_pin*> inputs;
|
||||
|
||||
/* Search the input edges only, stats on the size of MUX we may need (fan-in) */
|
||||
for (int iedge = 0; iedge < pb_graph_pin->num_input_edges; ++iedge) {
|
||||
/* We care the only edges in the selected mode */
|
||||
if (selected_interconnect != pb_graph_pin->input_edges[iedge]->interconnect) {
|
||||
continue;
|
||||
}
|
||||
for (int ipin = 0; ipin < pb_graph_pin->input_edges[iedge]->num_input_pins; ++ipin) {
|
||||
/* Ensure that the pin is unique in the list */
|
||||
if (inputs.end() != std::find(inputs.begin(), inputs.end(), pb_graph_pin->input_edges[iedge]->input_pins[ipin])) {
|
||||
continue;
|
||||
}
|
||||
/* Unique pin, push to the vector */
|
||||
inputs.push_back(pb_graph_pin->input_edges[iedge]->input_pins[ipin]);
|
||||
}
|
||||
}
|
||||
|
||||
return inputs;
|
||||
}
|
||||
|
||||
} /* end namespace openfpga */
|
|
@ -0,0 +1,23 @@
|
|||
#ifndef PB_GRAPH_UTILS_H
|
||||
#define PB_GRAPH_UTILS_H
|
||||
|
||||
/********************************************************************
|
||||
* Include header files that are required by function declaration
|
||||
*******************************************************************/
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include "physical_types.h"
|
||||
|
||||
/********************************************************************
|
||||
* Function declaration
|
||||
*******************************************************************/
|
||||
|
||||
/* begin namespace openfpga */
|
||||
namespace openfpga {
|
||||
|
||||
std::vector<t_pb_graph_pin*> pb_graph_pin_inputs(t_pb_graph_pin* pb_graph_pin,
|
||||
t_interconnect* selected_interconnect);
|
||||
|
||||
} /* end namespace openfpga */
|
||||
|
||||
#endif
|
|
@ -1,7 +1,9 @@
|
|||
/********************************************************************
|
||||
* This file includes most utilized functions for the pb_type
|
||||
* and pb_graph_node data structure in the OpenFPGA context
|
||||
* This file includes most utilized functions for the t_pb_type,
|
||||
* t_mode and t_port data structure in the OpenFPGA context
|
||||
*******************************************************************/
|
||||
#include <map>
|
||||
|
||||
/* Headers from vtrutil library */
|
||||
#include "vtr_assert.h"
|
||||
#include "vtr_log.h"
|
||||
|
@ -138,6 +140,18 @@ t_pb_type* try_find_pb_type_with_given_path(t_pb_type* top_pb_type,
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
/********************************************************************
|
||||
* This function will return all the interconnects defined under a mode
|
||||
* of pb_type
|
||||
*******************************************************************/
|
||||
std::vector<t_interconnect*> pb_mode_interconnects(t_mode* pb_mode) {
|
||||
std::vector<t_interconnect*> interc;
|
||||
for (int i = 0; i < pb_mode->num_interconnect; ++i) {
|
||||
interc.push_back(&(pb_mode->interconnect[i]));
|
||||
}
|
||||
return interc;
|
||||
}
|
||||
|
||||
/********************************************************************
|
||||
* This function will try to find an interconnect defined under a mode
|
||||
* of pb_type with a given name.
|
||||
|
@ -154,4 +168,64 @@ t_interconnect* find_pb_mode_interconnect(t_mode* pb_mode, const char* interc_na
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
/********************************************************************
|
||||
* This function will automatically infer the actual type of an interconnect
|
||||
* that will be used to implement the physical design:
|
||||
* - MUX_INTERC -> MUX_INTERC
|
||||
* - DIRECT_INTERC -> DIRECT_INTERC
|
||||
* - COMPLETE_INTERC (single input) -> DIRECT_INTERC
|
||||
* - COMPLETE_INTERC (multiple input pins) -> MUX_INTERC
|
||||
*******************************************************************/
|
||||
e_interconnect pb_interconnect_physical_type(t_interconnect* pb_interc,
|
||||
const size_t& num_inputs) {
|
||||
/* Check */
|
||||
VTR_ASSERT(nullptr != pb_interc);
|
||||
|
||||
/* Initialize the interconnection type that will be implemented in SPICE netlist*/
|
||||
switch (pb_interc->type) {
|
||||
case DIRECT_INTERC:
|
||||
return DIRECT_INTERC;
|
||||
break;
|
||||
case COMPLETE_INTERC:
|
||||
if (1 == num_inputs) {
|
||||
return DIRECT_INTERC;
|
||||
} else {
|
||||
VTR_ASSERT(1 < num_inputs);
|
||||
return MUX_INTERC;
|
||||
}
|
||||
break;
|
||||
case MUX_INTERC:
|
||||
return MUX_INTERC;
|
||||
break;
|
||||
default:
|
||||
VTR_LOG_ERROR("Invalid type for interconnection '%s'!\n",
|
||||
pb_interc->name);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
return NUM_INTERC_TYPES;
|
||||
}
|
||||
|
||||
/********************************************************************
|
||||
* This function will automatically infer the actual type of an interconnect
|
||||
* that will be used to implement the physical design:
|
||||
* - MUX_INTERC -> CIRCUIT_MODEL_MUX
|
||||
* - DIRECT_INTERC -> CIRCUIT_MODEL_WIRE
|
||||
*
|
||||
* Note:
|
||||
* - COMPLETE_INTERC should not appear here!
|
||||
* - We assume the interconnect type is the physical type
|
||||
* after interconnect physical type annotation is done!
|
||||
*******************************************************************/
|
||||
e_circuit_model_type pb_interconnect_require_circuit_model_type(const e_interconnect& pb_interc_type) {
|
||||
/* A map from interconnect type to circuit model type */
|
||||
std::map<e_interconnect, e_circuit_model_type> type_mapping;
|
||||
type_mapping[MUX_INTERC] = CIRCUIT_MODEL_MUX;
|
||||
type_mapping[DIRECT_INTERC] = CIRCUIT_MODEL_WIRE;
|
||||
|
||||
VTR_ASSERT((MUX_INTERC == pb_interc_type) || (DIRECT_INTERC == pb_interc_type));
|
||||
|
||||
return type_mapping.at(pb_interc_type);
|
||||
}
|
||||
|
||||
} /* end namespace openfpga */
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
#include <string>
|
||||
#include <vector>
|
||||
#include "physical_types.h"
|
||||
#include "circuit_library.h"
|
||||
|
||||
/********************************************************************
|
||||
* Function declaration
|
||||
|
@ -31,8 +32,15 @@ t_pb_type* try_find_pb_type_with_given_path(t_pb_type* top_pb_type,
|
|||
const std::vector<std::string>& target_pb_type_names,
|
||||
const std::vector<std::string>& target_pb_mode_names);
|
||||
|
||||
std::vector<t_interconnect*> pb_mode_interconnects(t_mode* pb_mode);
|
||||
|
||||
t_interconnect* find_pb_mode_interconnect(t_mode* pb_mode, const char* interc_name);
|
||||
|
||||
e_interconnect pb_interconnect_physical_type(t_interconnect* pb_interc,
|
||||
const size_t& num_inputs);
|
||||
|
||||
e_circuit_model_type pb_interconnect_require_circuit_model_type(const e_interconnect& pb_interc_type);
|
||||
|
||||
} /* end namespace openfpga */
|
||||
|
||||
#endif
|
||||
|
|
|
@ -85,6 +85,16 @@ CircuitModelId VprPbTypeAnnotation::interconnect_circuit_model(t_interconnect* p
|
|||
return interconnect_circuit_models_.at(pb_interconnect);
|
||||
}
|
||||
|
||||
e_interconnect VprPbTypeAnnotation::interconnect_physical_type(t_interconnect* pb_interconnect) const {
|
||||
/* Ensure that the pb_type is in the list */
|
||||
std::map<t_interconnect*, e_interconnect>::const_iterator it = interconnect_physical_types_.find(pb_interconnect);
|
||||
if (it == interconnect_physical_types_.end()) {
|
||||
/* Return an invalid circuit model id */
|
||||
return NUM_INTERC_TYPES;
|
||||
}
|
||||
return interconnect_physical_types_.at(pb_interconnect);
|
||||
}
|
||||
|
||||
/************************************************************************
|
||||
* Public mutators
|
||||
***********************************************************************/
|
||||
|
@ -157,4 +167,16 @@ void VprPbTypeAnnotation::add_interconnect_circuit_model(t_interconnect* pb_inte
|
|||
interconnect_circuit_models_[pb_interconnect] = circuit_model;
|
||||
}
|
||||
|
||||
void VprPbTypeAnnotation::add_interconnect_physical_type(t_interconnect* pb_interconnect,
|
||||
const e_interconnect& physical_type) {
|
||||
/* Warn any override attempt */
|
||||
std::map<t_interconnect*, e_interconnect>::const_iterator it = interconnect_physical_types_.find(pb_interconnect);
|
||||
if (it != interconnect_physical_types_.end()) {
|
||||
VTR_LOG_WARN("Override the physical interconnect for interconnect '%s'!\n",
|
||||
pb_interconnect->name);
|
||||
}
|
||||
|
||||
interconnect_physical_types_[pb_interconnect] = physical_type;
|
||||
}
|
||||
|
||||
} /* End namespace openfpga*/
|
||||
|
|
|
@ -36,6 +36,7 @@ class VprPbTypeAnnotation {
|
|||
BasicPort physical_pb_port_range(t_port* pb_port) const;
|
||||
CircuitModelId pb_type_circuit_model(t_pb_type* physical_pb_type) const;
|
||||
CircuitModelId interconnect_circuit_model(t_interconnect* pb_interconnect) const;
|
||||
e_interconnect interconnect_physical_type(t_interconnect* pb_interconnect) 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);
|
||||
|
@ -43,6 +44,7 @@ class VprPbTypeAnnotation {
|
|||
void add_physical_pb_port_range(t_port* operating_pb_port, const BasicPort& port_range);
|
||||
void add_pb_type_circuit_model(t_pb_type* physical_pb_type, const CircuitModelId& circuit_model);
|
||||
void add_interconnect_circuit_model(t_interconnect* pb_interconnect, const CircuitModelId& circuit_model);
|
||||
void add_interconnect_physical_type(t_interconnect* pb_interconnect, const e_interconnect& physical_type);
|
||||
private: /* Internal data */
|
||||
/* Pair a regular pb_type to its physical pb_type */
|
||||
std::map<t_pb_type*, t_pb_type*> physical_pb_types_;
|
||||
|
@ -66,6 +68,12 @@ class VprPbTypeAnnotation {
|
|||
*/
|
||||
std::map<t_interconnect*, CircuitModelId> interconnect_circuit_models_;
|
||||
|
||||
/* Physical type of interconnect
|
||||
* Note:
|
||||
* - only applicable to an interconnect belongs to physical mode
|
||||
*/
|
||||
std::map<t_interconnect*, e_interconnect> interconnect_physical_types_;
|
||||
|
||||
/* Pair a pb_type to its mode selection bits
|
||||
* - if the pb_type is a physical pb_type, the mode bits are the default mode
|
||||
* where the physical pb_type will operate when used
|
||||
|
|
Loading…
Reference in New Issue