Merge branch 'refactoring' into dev

This commit is contained in:
tangxifan 2020-01-29 14:30:50 -07:00
commit 741d6d03bf
15 changed files with 1008 additions and 167 deletions

View File

@ -61,7 +61,7 @@ std::string PbTypeAnnotation::idle_mode_name() const {
return idle_mode_name_;
}
std::string PbTypeAnnotation::mode_bits() const {
std::vector<size_t> PbTypeAnnotation::mode_bits() const {
return mode_bits_;
}
@ -155,7 +155,7 @@ void PbTypeAnnotation::set_idle_mode_name(const std::string& name) {
idle_mode_name_ = name;
}
void PbTypeAnnotation::set_mode_bits(const std::string& mode_bits) {
void PbTypeAnnotation::set_mode_bits(const std::vector<size_t>& mode_bits) {
mode_bits_ = mode_bits;
}

View File

@ -43,7 +43,7 @@ class PbTypeAnnotation {
bool is_physical_pb_type() const;
std::string physical_mode_name() const;
std::string idle_mode_name() const;
std::string mode_bits() const;
std::vector<size_t> mode_bits() const;
std::string circuit_model_name() const;
int physical_pb_type_index_factor() const;
int physical_pb_type_index_offset() const;
@ -61,7 +61,7 @@ class PbTypeAnnotation {
void set_physical_parent_mode_names(const std::vector<std::string>& names);
void set_physical_mode_name(const std::string& name);
void set_idle_mode_name(const std::string& name);
void set_mode_bits(const std::string& mode_bits);
void set_mode_bits(const std::vector<size_t>& mode_bits);
void set_circuit_model_name(const std::string& name);
void set_physical_pb_type_index_factor(const int& value);
void set_physical_pb_type_index_offset(const int& value);
@ -102,7 +102,7 @@ class PbTypeAnnotation {
std::string idle_mode_name_;
/* Configuration bits to select an operting mode for the circuit mode name */
std::string mode_bits_;
std::vector<size_t> mode_bits_;
/* Circuit mode name linked to a physical pb_type.
* This is only applicable to the physical pb_type

View File

@ -63,6 +63,31 @@ void read_xml_pb_port_annotation(pugi::xml_node& xml_port,
pb_type_annotation.set_physical_pin_rotate_offset(name_attr, get_attribute(xml_port, "physical_mode_pin_rotate_offset", loc_data, pugiutil::ReqOpt::OPTIONAL).as_int(0));
}
/********************************************************************
* Parse mode_bits: convert from string to array of digits
* We only allow the bit to either '0' or '1'
*******************************************************************/
static
std::vector<size_t> parse_mode_bits(pugi::xml_node& xml_mode_bits,
const pugiutil::loc_data& loc_data,
const std::string& mode_bit_str) {
std::vector<size_t> mode_bits;
for (const char& bit_char : mode_bit_str) {
if ('0' == bit_char) {
mode_bits.push_back(0);
} else if ('1' == bit_char) {
mode_bits.push_back(1);
} else {
archfpga_throw(loc_data.filename_c_str(), loc_data.line(xml_mode_bits),
"Unexpected '%c' character found in the mode bit '%s'! Only allow either '0' or '1'\n",
bit_char, mode_bit_str.c_str());
}
}
return mode_bits;
}
/********************************************************************
* Parse XML description for a pb_type annotation under a <pb_type> XML node
*******************************************************************/
@ -119,7 +144,8 @@ void read_xml_pb_type_annotation(pugi::xml_node& xml_pb_type,
pb_type_annotation.set_idle_mode_name(get_attribute(xml_pb_type, "idle_mode_name", loc_data, pugiutil::ReqOpt::OPTIONAL).as_string());
/* Parse mode bits which are applied to both pb_types */
pb_type_annotation.set_mode_bits(get_attribute(xml_pb_type, "mode_bits", loc_data, pugiutil::ReqOpt::OPTIONAL).as_string());
std::vector<size_t> mode_bit_data = parse_mode_bits(xml_pb_type, loc_data, get_attribute(xml_pb_type, "mode_bits", loc_data, pugiutil::ReqOpt::OPTIONAL).as_string());
pb_type_annotation.set_mode_bits(mode_bit_data);
/* If this is a physical pb_type, circuit model name is an optional attribute,
* which is applicable to leaf pb_type in the hierarchy

View File

@ -159,7 +159,12 @@ void write_xml_pb_type_annotation(std::fstream& fp,
/* Output mode_bits */
if (!pb_type_annotation.mode_bits().empty()) {
write_xml_attribute(fp, "mode_bits", pb_type_annotation.mode_bits().c_str());
/* Convert the vector of integer to string */
std::string mode_bits_str;
for (const size_t& bit : pb_type_annotation.mode_bits()) {
mode_bits_str += std::to_string(bit);
}
write_xml_attribute(fp, "mode_bits", mode_bits_str.c_str());
}
/* Output circuit model name */

View File

@ -10,6 +10,7 @@
#include "vpr_pb_type_annotation.h"
#include "pb_type_utils.h"
#include "annotate_pb_graph.h"
#include "check_pb_type_annotation.h"
#include "annotate_pb_types.h"
/* begin namespace openfpga */
@ -178,88 +179,6 @@ void build_vpr_physical_pb_mode_implicit_annotation(const DeviceContext& vpr_dev
}
}
/********************************************************************
* This function will recursively traverse pb_type graph to ensure
* 1. there is only a physical mode under each pb_type
* 2. physical mode appears only when its parent is a physical mode.
*******************************************************************/
static
void rec_check_vpr_physical_pb_mode_annotation(t_pb_type* cur_pb_type,
const bool& expect_physical_mode,
const VprPbTypeAnnotation& vpr_pb_type_annotation,
size_t& num_err) {
/* We do not check any primitive pb_type */
if (true == is_primitive_pb_type(cur_pb_type)) {
return;
}
/* For non-primitive pb_type:
* - If we expect a physical mode to exist under this pb_type
* we should be able to find one in the annoation
* - If we do NOT expect a physical mode, make sure we find
* nothing in the annotation
*/
if (true == expect_physical_mode) {
if (nullptr == vpr_pb_type_annotation.physical_mode(cur_pb_type)) {
VTR_LOG_ERROR("Unable to find a physical mode for a multi-mode pb_type '%s'!\n",
cur_pb_type->name);
VTR_LOG_ERROR("Please specify in the OpenFPGA architecture\n");
num_err++;
return;
}
} else {
VTR_ASSERT_SAFE(false == expect_physical_mode);
if (nullptr != vpr_pb_type_annotation.physical_mode(cur_pb_type)) {
VTR_LOG_ERROR("Find a physical mode '%s' for pb_type '%s' which is not under any physical mode!\n",
vpr_pb_type_annotation.physical_mode(cur_pb_type)->name,
cur_pb_type->name);
num_err++;
return;
}
}
/* Traverse all the modes
* - for pb_type children under a physical mode, we expect an physical mode
* - for pb_type children under non-physical mode, we expect no physical mode
*/
for (int imode = 0; imode < cur_pb_type->num_modes; ++imode) {
bool expect_child_physical_mode = false;
if (&(cur_pb_type->modes[imode]) == vpr_pb_type_annotation.physical_mode(cur_pb_type)) {
expect_child_physical_mode = true && expect_physical_mode;
}
for (int ichild = 0; ichild < cur_pb_type->modes[imode].num_pb_type_children; ++ichild) {
rec_check_vpr_physical_pb_mode_annotation(&(cur_pb_type->modes[imode].pb_type_children[ichild]),
expect_child_physical_mode, vpr_pb_type_annotation,
num_err);
}
}
}
/********************************************************************
* This function will check the physical mode annotation for
* each pb_type in the device
*******************************************************************/
static
void check_vpr_physical_pb_mode_annotation(const DeviceContext& vpr_device_ctx,
const VprPbTypeAnnotation& vpr_pb_type_annotation) {
size_t num_err = 0;
for (const t_logical_block_type& lb_type : vpr_device_ctx.logical_block_types) {
/* By pass nullptr for pb_type head */
if (nullptr == lb_type.pb_type) {
continue;
}
/* Top pb_type should always has a physical mode! */
rec_check_vpr_physical_pb_mode_annotation(lb_type.pb_type, true, vpr_pb_type_annotation, num_err);
}
if (0 == num_err) {
VTR_LOG("Check physical mode annotation for pb_types passed.\n");
} else {
VTR_LOG("Check physical mode annotation for pb_types failed with %ld errors!\n",
num_err);
}
}
/********************************************************************
* This function aims to make a pair of operating and physical
* pb_types:
@ -500,88 +419,66 @@ void build_vpr_physical_pb_type_implicit_annotation(const DeviceContext& vpr_dev
}
/********************************************************************
* This function will check
* - if a primitive pb_type has been mapped to a physical pb_type
* - if every port of the pb_type have been linked a port of a physical pb_type
* This function aims to link all the ports defined under a physical
* pb_type to the ports of circuit model in the circuit library
* The binding assumes that pb_type port should be defined with the same name
* as the circuit port
*******************************************************************/
static
void check_vpr_physical_primitive_pb_type_annotation(t_pb_type* cur_pb_type,
const VprPbTypeAnnotation& vpr_pb_type_annotation,
size_t& num_err) {
if (nullptr == vpr_pb_type_annotation.physical_pb_type(cur_pb_type)) {
VTR_LOG_ERROR("Find a pb_type '%s' which has not been mapped to any physical pb_type!\n",
cur_pb_type->name);
VTR_LOG_ERROR("Please specify in the OpenFPGA architecture\n");
num_err++;
return;
}
/* Now we need to check each port of the pb_type */
for (t_port* pb_port : pb_type_ports(cur_pb_type)) {
if (nullptr == vpr_pb_type_annotation.physical_pb_port(pb_port)) {
VTR_LOG_ERROR("Find a port '%s' of pb_type '%s' which has not been mapped to any physical port!\n",
pb_port->name, cur_pb_type->name);
VTR_LOG_ERROR("Please specify in the OpenFPGA architecture\n");
num_err++;
}
}
return;
}
/********************************************************************
* This function will recursively traverse pb_type graph to ensure
* 1. there is only a physical mode under each pb_type
* 2. physical mode appears only when its parent is a physical mode.
*******************************************************************/
static
void rec_check_vpr_physical_pb_type_annotation(t_pb_type* cur_pb_type,
const VprPbTypeAnnotation& vpr_pb_type_annotation,
size_t& num_err) {
/* Primitive pb_type should always been binded to a physical pb_type */
if (true == is_primitive_pb_type(cur_pb_type)) {
check_vpr_physical_primitive_pb_type_annotation(cur_pb_type, vpr_pb_type_annotation, num_err);
return;
}
/* Traverse all the modes
* - for pb_type children under a physical mode, we expect an physical mode
* - for pb_type children under non-physical mode, we expect no physical mode
bool link_physical_pb_port_to_circuit_port(t_pb_type* physical_pb_type,
const CircuitLibrary& circuit_lib,
const CircuitModelId& circuit_model,
VprPbTypeAnnotation& vpr_pb_type_annotation) {
bool link_success = true;
/* Iterate over the pb_ports
* Note:
* - Not every port defined in the circuit model will appear under the pb_type
* Some circuit ports are just for physical implementation
*/
for (int imode = 0; imode < cur_pb_type->num_modes; ++imode) {
for (int ichild = 0; ichild < cur_pb_type->modes[imode].num_pb_type_children; ++ichild) {
rec_check_vpr_physical_pb_type_annotation(&(cur_pb_type->modes[imode].pb_type_children[ichild]),
vpr_pb_type_annotation,
num_err);
}
}
}
for (t_port* pb_port : pb_type_ports(physical_pb_type)) {
CircuitPortId circuit_port = circuit_lib.model_port(circuit_model, std::string(pb_port->name));
/********************************************************************
* This function will check the physical pb_type annotation for
* each pb_type in the device
* Every pb_type should have been linked to a physical pb_type
* and every port of the pb_type have been linked a port of a physical pb_type
*******************************************************************/
static
void check_vpr_physical_pb_type_annotation(const DeviceContext& vpr_device_ctx,
const VprPbTypeAnnotation& vpr_pb_type_annotation) {
size_t num_err = 0;
for (const t_logical_block_type& lb_type : vpr_device_ctx.logical_block_types) {
/* By pass nullptr for pb_type head */
if (nullptr == lb_type.pb_type) {
/* If we cannot find a port with the same name, error out */
if (CircuitPortId::INVALID() == circuit_port) {
VTR_LOG_ERROR("Pb type port '%s' is not found in any port of circuit model '%s'!\n",
pb_port->name, circuit_lib.model_name(circuit_model).c_str());
link_success = false;
continue;
}
/* Top pb_type should always has a physical mode! */
rec_check_vpr_physical_pb_type_annotation(lb_type.pb_type, vpr_pb_type_annotation, num_err);
}
if (0 == num_err) {
VTR_LOG("Check physical pb_type annotation for pb_types passed.\n");
} else {
VTR_LOG("Check physical pb_type annotation for pb_types failed with %ld errors!\n",
num_err);
/* If the port width does not match, error out */
if ((size_t)(pb_port->num_pins) != circuit_lib.port_size(circuit_port)) {
VTR_LOG_ERROR("Pb type port '%s[%d:%d]' does not match the port '%s[%d:%d]' of circuit model '%s' in size!\n",
pb_port->name,
0, pb_port->num_pins - 1,
circuit_lib.port_prefix(circuit_port).c_str(),
0, circuit_lib.port_size(circuit_port) - 1,
circuit_lib.model_name(circuit_model).c_str());
link_success = false;
continue;
}
/* If the port type does not match, error out */
if (ERR_PORT == circuit_port_require_pb_port_type(circuit_lib.port_type(circuit_port))) {
VTR_LOG_ERROR("Pb type port '%s' type does not match the port type '%s' of circuit model '%s'!\n",
pb_port->name,
circuit_lib.port_prefix(circuit_port).c_str(),
circuit_lib.model_name(circuit_model).c_str());
link_success = false;
continue;
}
/* Reach here, it means that mapping should be ok, update the vpr_pb_type_annotation */
vpr_pb_type_annotation.add_pb_circuit_port(pb_port, circuit_port);
VTR_LOG("Bind pb type '%s' port '%s' to circuit model '%s' port '%s'\n",
physical_pb_type->name,
pb_port->name,
circuit_lib.model_name(circuit_model).c_str(),
circuit_lib.port_prefix(circuit_port).c_str());
}
return link_success;
}
/********************************************************************
@ -613,6 +510,11 @@ bool link_physical_pb_type_to_circuit_model(t_pb_type* physical_pb_type,
return false;
}
/* Ensure that the pb_type ports can be matched in the circuit model ports */
if (false == link_physical_pb_port_to_circuit_port(physical_pb_type, circuit_lib, circuit_model_id, vpr_pb_type_annotation)) {
return false;
}
/* Now the circuit model is valid, update the vpr_pb_type_annotation */
vpr_pb_type_annotation.add_pb_type_circuit_model(physical_pb_type, circuit_model_id);
return true;
@ -663,6 +565,19 @@ bool link_physical_pb_interconnect_to_circuit_model(t_pb_type* physical_pb_type,
physical_pb_type->name);
return false;
}
/* Double check the type of circuit model, it should be the same as required physical type */
e_circuit_model_type required_circuit_model_type = pb_interconnect_require_circuit_model_type(vpr_pb_type_annotation.interconnect_physical_type(pb_interc));
if (circuit_lib.model_type(circuit_model_id) != required_circuit_model_type) {
VTR_LOG_ERROR("Circuit model '%s' type '%s' does not match required type '%s' for interconnect '%s' under physical mode '%s' of pb_type '%s'!\n",
circuit_lib.model_name(circuit_model_id).c_str(),
CIRCUIT_MODEL_TYPE_STRING[circuit_lib.model_type(circuit_model_id)],
CIRCUIT_MODEL_TYPE_STRING[required_circuit_model_type],
pb_interc->name,
physical_mode->name,
physical_pb_type->name);
return false;
}
/* Now the circuit model is valid, update the vpr_pb_type_annotation */
vpr_pb_type_annotation.add_interconnect_circuit_model(pb_interc, circuit_model_id);
@ -930,6 +845,117 @@ void link_vpr_pb_interconnect_to_circuit_model_implicit_annotation(const DeviceC
}
}
/********************************************************************
* This function will bind mode selection bits to a primitive pb_type
* in the vpr_pb_type_annotation
*******************************************************************/
static
bool link_primitive_pb_type_to_mode_bits(t_pb_type* primitive_pb_type,
const PbTypeAnnotation& pb_type_annotation,
VprPbTypeAnnotation& vpr_pb_type_annotation) {
/* Error out if this is not a primitive pb_type */
if (false == is_primitive_pb_type(primitive_pb_type)) {
VTR_LOG_ERROR("Mode selection is only applicable to primitive pb_type while pb_type '%s' is not primitve !\n",
primitive_pb_type->name);
return false;
}
/* Update the annotation */
vpr_pb_type_annotation.add_pb_type_mode_bits(primitive_pb_type, pb_type_annotation.mode_bits());
return true;
}
/********************************************************************
* This function will link
* - pb_type to mode bits by following
* the explicit definition in OpenFPGA architecture XML
*
* Note:
* - This function should be executed only AFTER
* the physical mode and physical pb_type annotation is completed
* the physical pb_type circuit model annotation is completed
*******************************************************************/
static
void link_vpr_pb_type_to_mode_bits_explicit_annotation(const DeviceContext& vpr_device_ctx,
const Arch& openfpga_arch,
VprPbTypeAnnotation& vpr_pb_type_annotation) {
/* Walk through the pb_type annotation stored in the openfpga arch */
for (const PbTypeAnnotation& pb_type_annotation : openfpga_arch.pb_type_annotations) {
if (true == pb_type_annotation.mode_bits().empty()) {
continue;
}
/* Convert the vector of integer to string */
std::string mode_bits_str;
for (const size_t& bit : pb_type_annotation.mode_bits()) {
mode_bits_str += std::to_string(bit);
}
/* Collect the information about the full hierarchy of physical pb_type to be annotated */
std::vector<std::string> target_pb_type_names;
std::vector<std::string> target_pb_mode_names;
if (true == pb_type_annotation.is_operating_pb_type()) {
target_pb_type_names = pb_type_annotation.operating_parent_pb_type_names();
target_pb_type_names.push_back(pb_type_annotation.operating_pb_type_name());
target_pb_mode_names = pb_type_annotation.operating_parent_mode_names();
}
if (true == pb_type_annotation.is_physical_pb_type()) {
target_pb_type_names = pb_type_annotation.physical_parent_pb_type_names();
target_pb_type_names.push_back(pb_type_annotation.physical_pb_type_name());
target_pb_mode_names = pb_type_annotation.physical_parent_mode_names();
}
/* We must have at least one pb_type in the list */
VTR_ASSERT_SAFE(0 < target_pb_type_names.size());
/* Pb type information are located at the logic_block_types in the device context of VPR
* We iterate over the vectors and find the pb_type matches the parent_pb_type_name
*/
bool link_success = false;
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;
}
/* Check the name of the top-level pb_type, if it does not match, we can bypass */
if (target_pb_type_names[0] != std::string(lb_type.pb_type->name)) {
continue;
}
/* Match the name in the top-level, we go further to search the operating as well as
* physical pb_types in the graph */
t_pb_type* target_pb_type = try_find_pb_type_with_given_path(lb_type.pb_type, target_pb_type_names,
target_pb_mode_names);
if (nullptr == target_pb_type) {
continue;
}
/* Only try to bind pb_type to circuit model when it is defined by users */
if (true == link_primitive_pb_type_to_mode_bits(target_pb_type,
pb_type_annotation, vpr_pb_type_annotation)) {
/* Give a message */
VTR_LOG("Bind physical pb_type '%s' to mode selection bits '%s'\n",
target_pb_type->name,
mode_bits_str.c_str());
link_success = true;
break;
}
}
if (false == link_success) {
/* Not found, error out! */
VTR_LOG_ERROR("Unable to bind pb_type '%s' to mode_selection bits '%s'!\n",
target_pb_type_names.back().c_str(),
mode_bits_str.c_str());
return;
}
}
}
/********************************************************************
* Top-level function to link openfpga architecture to VPR, including:
* - physical pb_type
@ -940,6 +966,8 @@ void annotate_pb_types(const DeviceContext& vpr_device_ctx,
VprPbTypeAnnotation& vpr_pb_type_annotation) {
/* Annotate physical mode to pb_type in the VPR pb_type graph */
VTR_LOG("\n");
VTR_LOG("Building annotation for physical modes in pb_type...\n");
build_vpr_physical_pb_mode_explicit_annotation(vpr_device_ctx, openfpga_arch,
vpr_pb_type_annotation);
@ -953,10 +981,15 @@ void annotate_pb_types(const DeviceContext& vpr_device_ctx,
* Must run AFTER physical mode annotation is done and
* BEFORE inferring the circuit model for interconnect
*/
VTR_LOG("\n");
VTR_LOG("Building annotation about physical types for pb_type interconnection...");
annotate_pb_graph_interconnect_physical_type(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 */
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,
vpr_pb_type_annotation);
@ -970,15 +1003,24 @@ 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! */
VTR_LOG("\n");
VTR_LOG("Building annotation between physical pb_types and circuit models...\n");
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);
check_vpr_pb_type_circuit_model_annotation(vpr_device_ctx, openfpga_arch.circuit_lib,
const_cast<const VprPbTypeAnnotation&>(vpr_pb_type_annotation));
/* Link physical pb_type to mode_bits */
VTR_LOG("\n");
VTR_LOG("Building annotation between physical pb_types and mode selection bits...\n");
link_vpr_pb_type_to_mode_bits_explicit_annotation(vpr_device_ctx, openfpga_arch,
vpr_pb_type_annotation);
check_vpr_pb_type_mode_bits_annotation(vpr_device_ctx, openfpga_arch.circuit_lib,
const_cast<const VprPbTypeAnnotation&>(vpr_pb_type_annotation));
}

View File

@ -0,0 +1,381 @@
/********************************************************************
* This file includes functions to build links between pb_types
* in particular to annotate the physical mode and physical pb_type
*******************************************************************/
/* Headers from vtrutil library */
#include "vtr_time.h"
#include "vtr_assert.h"
#include "vtr_log.h"
#include "pb_type_utils.h"
#include "circuit_library_utils.h"
#include "check_pb_type_annotation.h"
/* begin namespace openfpga */
namespace openfpga {
/********************************************************************
* This function will recursively traverse pb_type graph to ensure
* 1. there is only a physical mode under each pb_type
* 2. physical mode appears only when its parent is a physical mode.
*******************************************************************/
static
void rec_check_vpr_physical_pb_mode_annotation(t_pb_type* cur_pb_type,
const bool& expect_physical_mode,
const VprPbTypeAnnotation& vpr_pb_type_annotation,
size_t& num_err) {
/* We do not check any primitive pb_type */
if (true == is_primitive_pb_type(cur_pb_type)) {
return;
}
/* For non-primitive pb_type:
* - If we expect a physical mode to exist under this pb_type
* we should be able to find one in the annoation
* - If we do NOT expect a physical mode, make sure we find
* nothing in the annotation
*/
if (true == expect_physical_mode) {
if (nullptr == vpr_pb_type_annotation.physical_mode(cur_pb_type)) {
VTR_LOG_ERROR("Unable to find a physical mode for a multi-mode pb_type '%s'!\n",
cur_pb_type->name);
VTR_LOG_ERROR("Please specify in the OpenFPGA architecture\n");
num_err++;
return;
}
} else {
VTR_ASSERT_SAFE(false == expect_physical_mode);
if (nullptr != vpr_pb_type_annotation.physical_mode(cur_pb_type)) {
VTR_LOG_ERROR("Find a physical mode '%s' for pb_type '%s' which is not under any physical mode!\n",
vpr_pb_type_annotation.physical_mode(cur_pb_type)->name,
cur_pb_type->name);
num_err++;
return;
}
}
/* Traverse all the modes
* - for pb_type children under a physical mode, we expect an physical mode
* - for pb_type children under non-physical mode, we expect no physical mode
*/
for (int imode = 0; imode < cur_pb_type->num_modes; ++imode) {
bool expect_child_physical_mode = false;
if (&(cur_pb_type->modes[imode]) == vpr_pb_type_annotation.physical_mode(cur_pb_type)) {
expect_child_physical_mode = true && expect_physical_mode;
}
for (int ichild = 0; ichild < cur_pb_type->modes[imode].num_pb_type_children; ++ichild) {
rec_check_vpr_physical_pb_mode_annotation(&(cur_pb_type->modes[imode].pb_type_children[ichild]),
expect_child_physical_mode, vpr_pb_type_annotation,
num_err);
}
}
}
/********************************************************************
* This function will check the physical mode annotation for
* each pb_type in the device
*******************************************************************/
void check_vpr_physical_pb_mode_annotation(const DeviceContext& vpr_device_ctx,
const VprPbTypeAnnotation& vpr_pb_type_annotation) {
size_t num_err = 0;
for (const t_logical_block_type& lb_type : vpr_device_ctx.logical_block_types) {
/* By pass nullptr for pb_type head */
if (nullptr == lb_type.pb_type) {
continue;
}
/* Top pb_type should always has a physical mode! */
rec_check_vpr_physical_pb_mode_annotation(lb_type.pb_type, true, vpr_pb_type_annotation, num_err);
}
if (0 == num_err) {
VTR_LOG("Check physical mode annotation for pb_types passed.\n");
} else {
VTR_LOG_ERROR("Check physical mode annotation for pb_types failed with %ld errors!\n",
num_err);
}
}
/********************************************************************
* This function will check
* - if a primitive pb_type has been mapped to a physical pb_type
* - if every port of the pb_type have been linked a port of a physical pb_type
*******************************************************************/
static
void check_vpr_physical_primitive_pb_type_annotation(t_pb_type* cur_pb_type,
const VprPbTypeAnnotation& vpr_pb_type_annotation,
size_t& num_err) {
if (nullptr == vpr_pb_type_annotation.physical_pb_type(cur_pb_type)) {
VTR_LOG_ERROR("Find a pb_type '%s' which has not been mapped to any physical pb_type!\n",
cur_pb_type->name);
VTR_LOG_ERROR("Please specify in the OpenFPGA architecture\n");
num_err++;
return;
}
/* Now we need to check each port of the pb_type */
for (t_port* pb_port : pb_type_ports(cur_pb_type)) {
if (nullptr == vpr_pb_type_annotation.physical_pb_port(pb_port)) {
VTR_LOG_ERROR("Find a port '%s' of pb_type '%s' which has not been mapped to any physical port!\n",
pb_port->name, cur_pb_type->name);
VTR_LOG_ERROR("Please specify in the OpenFPGA architecture\n");
num_err++;
}
}
return;
}
/********************************************************************
* This function will recursively traverse pb_type graph to ensure
* 1. there is only a physical mode under each pb_type
* 2. physical mode appears only when its parent is a physical mode.
*******************************************************************/
static
void rec_check_vpr_physical_pb_type_annotation(t_pb_type* cur_pb_type,
const VprPbTypeAnnotation& vpr_pb_type_annotation,
size_t& num_err) {
/* Primitive pb_type should always been binded to a physical pb_type */
if (true == is_primitive_pb_type(cur_pb_type)) {
check_vpr_physical_primitive_pb_type_annotation(cur_pb_type, vpr_pb_type_annotation, num_err);
return;
}
/* Traverse all the modes */
for (int imode = 0; imode < cur_pb_type->num_modes; ++imode) {
for (int ichild = 0; ichild < cur_pb_type->modes[imode].num_pb_type_children; ++ichild) {
rec_check_vpr_physical_pb_type_annotation(&(cur_pb_type->modes[imode].pb_type_children[ichild]),
vpr_pb_type_annotation,
num_err);
}
}
}
/********************************************************************
* This function will check the physical pb_type annotation for
* each pb_type in the device
* Every pb_type should have been linked to a physical pb_type
* and every port of the pb_type have been linked a port of a physical pb_type
*******************************************************************/
void check_vpr_physical_pb_type_annotation(const DeviceContext& vpr_device_ctx,
const VprPbTypeAnnotation& vpr_pb_type_annotation) {
size_t num_err = 0;
for (const t_logical_block_type& lb_type : vpr_device_ctx.logical_block_types) {
/* By pass nullptr for pb_type head */
if (nullptr == lb_type.pb_type) {
continue;
}
/* Top pb_type should always has a physical mode! */
rec_check_vpr_physical_pb_type_annotation(lb_type.pb_type, vpr_pb_type_annotation, num_err);
}
if (0 == num_err) {
VTR_LOG("Check physical pb_type annotation for pb_types passed.\n");
} else {
VTR_LOG_ERROR("Check physical pb_type annotation for pb_types failed with %ld errors!\n",
num_err);
}
}
/********************************************************************
* This function will recursively traverse only the physical mode
* and physical pb_types in the graph to ensure
* - Every physical pb_type should be linked to a valid circuit model
* - Every port of the pb_type have been linked to a valid port of a circuit model
* - Every interconnect has been linked to a valid circuit model
* in a correct type
*******************************************************************/
static
void rec_check_vpr_pb_type_circuit_model_annotation(t_pb_type* cur_pb_type,
const CircuitLibrary& circuit_lib,
const VprPbTypeAnnotation& vpr_pb_type_annotation,
size_t& num_err) {
/* Primitive pb_type should always been binded to a physical pb_type */
if (true == is_primitive_pb_type(cur_pb_type)) {
/* Every physical pb_type should be linked to a valid circuit model */
if (CircuitModelId::INVALID() == vpr_pb_type_annotation.pb_type_circuit_model(cur_pb_type)) {
VTR_LOG_ERROR("Found a physical pb_type '%s' missing circuit model binding!\n",
cur_pb_type->name);
num_err++;
return; /* Invalid id already, further check is not applicable */
}
/* Every port of the pb_type have been linked to a valid port of a circuit model */
for (t_port* port : pb_type_ports(cur_pb_type)) {
if (CircuitPortId::INVALID() == vpr_pb_type_annotation.pb_circuit_port(port)) {
VTR_LOG_ERROR("Found a port '%s' of physical pb_type '%s' missing circuit port binding!\n",
port->name, cur_pb_type->name);
num_err++;
}
}
return;
}
/* Every interconnect in the physical mode has been linked to a valid circuit model in a correct type */
t_mode* physical_mode = vpr_pb_type_annotation.physical_mode(cur_pb_type);
for (t_interconnect* interc : pb_mode_interconnects(physical_mode)) {
CircuitModelId interc_circuit_model = vpr_pb_type_annotation.interconnect_circuit_model(interc);
if (CircuitModelId::INVALID() == interc_circuit_model) {
VTR_LOG_ERROR("Found an interconnect '%s' under physical mode '%s' of pb_type '%s' missing circuit model binding!\n",
interc->name,
physical_mode->name,
cur_pb_type->name);
num_err++;
continue;
}
e_circuit_model_type required_circuit_model_type = pb_interconnect_require_circuit_model_type(vpr_pb_type_annotation.interconnect_physical_type(interc));
if (circuit_lib.model_type(interc_circuit_model) != required_circuit_model_type) {
VTR_LOG_ERROR("Found an interconnect '%s' under physical mode '%s' of pb_type '%s' linked to a circuit model '%s' with a wrong type!\nExpect: '%s' Linked: '%s'\n",
interc->name,
physical_mode->name,
cur_pb_type->name,
circuit_lib.model_name(interc_circuit_model).c_str(),
CIRCUIT_MODEL_TYPE_STRING[circuit_lib.model_type(interc_circuit_model)],
CIRCUIT_MODEL_TYPE_STRING[required_circuit_model_type]);
num_err++;
}
}
/* Traverse only the physical mode */
for (int ichild = 0; ichild < physical_mode->num_pb_type_children; ++ichild) {
rec_check_vpr_pb_type_circuit_model_annotation(&(physical_mode->pb_type_children[ichild]),
circuit_lib,
vpr_pb_type_annotation,
num_err);
}
}
/********************************************************************
* This function will check the circuit model annotation for
* each physical pb_type in the device
* - Every physical pb_type should be linked to a valid circuit model
* - Every port of the pb_type have been linked a valid port of a circuit model
* - Every interconnect has been linked to a valid circuit model
* in a correct type
*******************************************************************/
void check_vpr_pb_type_circuit_model_annotation(const DeviceContext& vpr_device_ctx,
const CircuitLibrary& circuit_lib,
const VprPbTypeAnnotation& vpr_pb_type_annotation) {
size_t num_err = 0;
for (const t_logical_block_type& lb_type : vpr_device_ctx.logical_block_types) {
/* By pass nullptr for pb_type head */
if (nullptr == lb_type.pb_type) {
continue;
}
/* Top pb_type should always has a physical mode! */
rec_check_vpr_pb_type_circuit_model_annotation(lb_type.pb_type, circuit_lib, vpr_pb_type_annotation, num_err);
}
if (0 == num_err) {
VTR_LOG("Check physical pb_type annotation for circuit model passed.\n");
} else {
VTR_LOG_ERROR("Check physical pb_type annotation for circuit model failed with %ld errors!\n",
num_err);
}
}
/********************************************************************
* This function will recursively traverse all the primitive pb_types
* in the graph to ensure
* - If a primitive pb_type has mode bits, it must have been linked to a physical pb_type
* and the circuit model must have a port for mode selection.
* And the port size must match the length of mode bits
*******************************************************************/
static
void rec_check_vpr_pb_type_mode_bits_annotation(t_pb_type* cur_pb_type,
const CircuitLibrary& circuit_lib,
const VprPbTypeAnnotation& vpr_pb_type_annotation,
size_t& num_err) {
/* Primitive pb_type should always been binded to a physical pb_type */
if (true == is_primitive_pb_type(cur_pb_type)) {
/* Find the physical pb_type
* If the physical pb_type has mode selection bits, this pb_type must have as well!
*/
t_pb_type* physical_pb_type = vpr_pb_type_annotation.physical_pb_type(cur_pb_type);
if (nullptr == physical_pb_type) {
VTR_LOG_ERROR("Find a pb_type '%s' which has not been mapped to any physical pb_type!\n",
cur_pb_type->name);
VTR_LOG_ERROR("Please specify in the OpenFPGA architecture\n");
num_err++;
return;
}
if (vpr_pb_type_annotation.pb_type_mode_bits(cur_pb_type).size() != vpr_pb_type_annotation.pb_type_mode_bits(physical_pb_type).size()) {
VTR_LOG_ERROR("Found different sizes of mode_bits for pb_type '%s' and its physical pb_type '%s'\n",
cur_pb_type->name,
physical_pb_type->name);
num_err++;
return;
}
/* Try to find a mode selection port for the circuit model linked to the circuit model */
CircuitModelId circuit_model = vpr_pb_type_annotation.pb_type_circuit_model(physical_pb_type);
if (CircuitModelId::INVALID() == vpr_pb_type_annotation.pb_type_circuit_model(physical_pb_type)) {
VTR_LOG_ERROR("Found a physical pb_type '%s' missing circuit model binding!\n",
physical_pb_type->name);
num_err++;
return; /* Invalid id already, further check is not applicable */
}
if (0 == vpr_pb_type_annotation.pb_type_mode_bits(cur_pb_type).size()) {
/* No mode bits to be checked! */
return;
}
/* Search the ports of this circuit model and we must have a mode selection port */
std::vector<CircuitPortId> mode_select_ports = find_circuit_mode_select_sram_ports(circuit_lib, circuit_model);
size_t port_num_mode_bits = 0;
for (const CircuitPortId& mode_select_port : mode_select_ports) {
port_num_mode_bits += circuit_lib.port_size(mode_select_port);
}
if (port_num_mode_bits != vpr_pb_type_annotation.pb_type_mode_bits(cur_pb_type).size()) {
VTR_LOG_ERROR("Length of mode bits of pb_type '%s' does not match the size(%ld) of mode selection ports of circuit model '%s'!\n",
cur_pb_type->name,
port_num_mode_bits,
circuit_lib.model_name(circuit_model).c_str());
num_err++;
}
return;
}
/* Traverse all the modes */
for (int imode = 0; imode < cur_pb_type->num_modes; ++imode) {
for (int ichild = 0; ichild < cur_pb_type->modes[imode].num_pb_type_children; ++ichild) {
rec_check_vpr_pb_type_mode_bits_annotation(&(cur_pb_type->modes[imode].pb_type_children[ichild]),
circuit_lib, vpr_pb_type_annotation,
num_err);
}
}
}
/********************************************************************
* This function will check the mode_bits annotation for each pb_type
* - If a primitive pb_type has mode bits, it must have been linked to a physical pb_type
* - If a primitive pb_type has mode bits, the circuit model must have
* a port for mode selection. And the port size must match the length of mode bits
*
* Note:
* - This function should be run after circuit mode and mode bits annotation
* is completed
*******************************************************************/
void check_vpr_pb_type_mode_bits_annotation(const DeviceContext& vpr_device_ctx,
const CircuitLibrary& circuit_lib,
const VprPbTypeAnnotation& vpr_pb_type_annotation) {
size_t num_err = 0;
for (const t_logical_block_type& lb_type : vpr_device_ctx.logical_block_types) {
/* By pass nullptr for pb_type head */
if (nullptr == lb_type.pb_type) {
continue;
}
/* Top pb_type should always has a physical mode! */
rec_check_vpr_pb_type_mode_bits_annotation(lb_type.pb_type, circuit_lib, vpr_pb_type_annotation, num_err);
}
if (0 == num_err) {
VTR_LOG("Check pb_type annotation for mode selection bits passed.\n");
} else {
VTR_LOG_ERROR("Check physical pb_type annotation for mode selection bits failed with %ld errors!\n",
num_err);
}
}
} /* end namespace openfpga */

View File

@ -0,0 +1,34 @@
#ifndef CHECK_PB_TYPE_ANNOTATION_H
#define CHECK_PB_TYPE_ANNOTATION_H
/********************************************************************
* Include header files that are required by function declaration
*******************************************************************/
#include "vpr_context.h"
#include "openfpga_context.h"
#include "vpr_pb_type_annotation.h"
/********************************************************************
* Function declaration
*******************************************************************/
/* begin namespace openfpga */
namespace openfpga {
void check_vpr_physical_pb_mode_annotation(const DeviceContext& vpr_device_ctx,
const VprPbTypeAnnotation& vpr_pb_type_annotation);
void check_vpr_physical_pb_type_annotation(const DeviceContext& vpr_device_ctx,
const VprPbTypeAnnotation& vpr_pb_type_annotation);
void check_vpr_pb_type_circuit_model_annotation(const DeviceContext& vpr_device_ctx,
const CircuitLibrary& circuit_lib,
const VprPbTypeAnnotation& vpr_pb_type_annotation);
void check_vpr_pb_type_mode_bits_annotation(const DeviceContext& vpr_device_ctx,
const CircuitLibrary& circuit_lib,
const VprPbTypeAnnotation& vpr_pb_type_annotation);
} /* end namespace openfpga */
#endif

View File

@ -89,12 +89,32 @@ e_interconnect VprPbTypeAnnotation::interconnect_physical_type(t_interconnect* p
/* 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 an invalid interconnect type */
return NUM_INTERC_TYPES;
}
return interconnect_physical_types_.at(pb_interconnect);
}
CircuitPortId VprPbTypeAnnotation::pb_circuit_port(t_port* pb_port) const {
/* Ensure that the pb_type is in the list */
std::map<t_port*, CircuitPortId>::const_iterator it = pb_circuit_ports_.find(pb_port);
if (it == pb_circuit_ports_.end()) {
/* Return an invalid circuit port id */
return CircuitPortId::INVALID();
}
return pb_circuit_ports_.at(pb_port);
}
std::vector<size_t> VprPbTypeAnnotation::pb_type_mode_bits(t_pb_type* pb_type) const {
/* Ensure that the pb_type is in the list */
std::map<t_pb_type*, std::vector<size_t>>::const_iterator it = pb_type_mode_bits_.find(pb_type);
if (it == pb_type_mode_bits_.end()) {
/* Return an empty vector */
return std::vector<size_t>();
}
return pb_type_mode_bits_.at(pb_type);
}
/************************************************************************
* Public mutators
***********************************************************************/
@ -179,4 +199,26 @@ void VprPbTypeAnnotation::add_interconnect_physical_type(t_interconnect* pb_inte
interconnect_physical_types_[pb_interconnect] = physical_type;
}
void VprPbTypeAnnotation::add_pb_circuit_port(t_port* pb_port, const CircuitPortId& circuit_port) {
/* Warn any override attempt */
std::map<t_port*, CircuitPortId>::const_iterator it = pb_circuit_ports_.find(pb_port);
if (it != pb_circuit_ports_.end()) {
VTR_LOG_WARN("Override the circuit port mapping for pb_type port '%s'!\n",
pb_port->name);
}
pb_circuit_ports_[pb_port] = circuit_port;
}
void VprPbTypeAnnotation::add_pb_type_mode_bits(t_pb_type* pb_type, const std::vector<size_t>& mode_bits) {
/* Warn any override attempt */
std::map<t_pb_type*, std::vector<size_t>>::const_iterator it = pb_type_mode_bits_.find(pb_type);
if (it != pb_type_mode_bits_.end()) {
VTR_LOG_WARN("Override the mode bits mapping for pb_type '%s'!\n",
pb_type->name);
}
pb_type_mode_bits_[pb_type] = mode_bits;
}
} /* End namespace openfpga*/

View File

@ -37,6 +37,8 @@ class VprPbTypeAnnotation {
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;
CircuitPortId pb_circuit_port(t_port* pb_port) const;
std::vector<size_t> pb_type_mode_bits(t_pb_type* pb_type) 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);
@ -45,6 +47,8 @@ class VprPbTypeAnnotation {
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);
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);
private: /* Internal data */
/* Pair a regular pb_type to its physical pb_type */
std::map<t_pb_type*, t_pb_type*> physical_pb_types_;
@ -80,7 +84,7 @@ class VprPbTypeAnnotation {
* - if the pb_type is an operating pb_type, the mode bits will be applied
* when the operating pb_type is used by packer
*/
std::map<t_pb_type*, std::vector<bool>> pb_type_mode_bits_;
std::map<t_pb_type*, std::vector<size_t>> pb_type_mode_bits_;
/* Pair a pb_port to its physical pb_port
* Note:
@ -94,6 +98,12 @@ class VprPbTypeAnnotation {
*/
std::map<t_port*, BasicPort> physical_pb_port_ranges_;
/* Pair a pb_port to a circuit port in circuit model
* Note:
* - the parent of physical pb_port MUST be a physical pb_type
*/
std::map<t_port*, CircuitPortId> pb_circuit_ports_;
/* 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

View File

@ -0,0 +1,229 @@
/************************************************************************
* Function to perform fundamental operation for the circuit library
* These functions are not universal methods for the CircuitLibrary class
* They are made to ease the development in some specific purposes
* Please classify such functions in this file
***********************************************************************/
#include <algorithm>
/* Headers from vtr util library */
#include "vtr_assert.h"
#include "vtr_log.h"
#include "circuit_library_utils.h"
/* begin namespace openfpga */
namespace openfpga {
/********************************************************************
* Get the model id of a SRAM model that is used to configure
* a circuit model
*******************************************************************/
std::vector<CircuitModelId> find_circuit_sram_models(const CircuitLibrary& circuit_lib,
const CircuitModelId& circuit_model) {
/* SRAM model id is stored in the sram ports of a circuit model */
std::vector<CircuitPortId> sram_ports = circuit_lib.model_ports_by_type(circuit_model, CIRCUIT_MODEL_PORT_SRAM);
std::vector<CircuitModelId> sram_models;
/* Create a list of sram models, but avoid duplicated model ids */
for (const auto& sram_port : sram_ports) {
CircuitModelId sram_model = circuit_lib.port_tri_state_model(sram_port);
VTR_ASSERT( true == circuit_lib.valid_model_id(sram_model) );
if (sram_models.end() != std::find(sram_models.begin(), sram_models.end(), sram_model)) {
continue; /* Already in the list, skip the addition */
}
/* Not in the list, add it */
sram_models.push_back(sram_model);
}
return sram_models;
}
/********************************************************************
* Find regular (not mode select) sram ports of a circuit model
*******************************************************************/
std::vector<CircuitPortId> find_circuit_regular_sram_ports(const CircuitLibrary& circuit_lib,
const CircuitModelId& circuit_model) {
std::vector<CircuitPortId> sram_ports = circuit_lib.model_ports_by_type(circuit_model, CIRCUIT_MODEL_PORT_SRAM, true);
std::vector<CircuitPortId> regular_sram_ports;
for (const auto& port : sram_ports) {
if (true == circuit_lib.port_is_mode_select(port)) {
continue;
}
regular_sram_ports.push_back(port);
}
return regular_sram_ports;
}
/********************************************************************
* Find mode select sram ports of a circuit model
*******************************************************************/
std::vector<CircuitPortId> find_circuit_mode_select_sram_ports(const CircuitLibrary& circuit_lib,
const CircuitModelId& circuit_model) {
std::vector<CircuitPortId> sram_ports = circuit_lib.model_ports_by_type(circuit_model, CIRCUIT_MODEL_PORT_SRAM, true);
std::vector<CircuitPortId> mode_select_sram_ports;
for (const auto& port : sram_ports) {
if (false == circuit_lib.port_is_mode_select(port)) {
continue;
}
mode_select_sram_ports.push_back(port);
}
return mode_select_sram_ports;
}
/********************************************************************
* Find the number of shared configuration bits for a ReRAM circuit
* TODO: this function is subjected to be changed due to ReRAM-based SRAM cell design!!!
*******************************************************************/
static
size_t find_rram_circuit_num_shared_config_bits(const CircuitLibrary& circuit_lib,
const CircuitModelId& rram_model,
const e_config_protocol_type& config_protocol_type) {
size_t num_shared_config_bits = 0;
/* Branch on the organization of configuration protocol */
switch (config_protocol_type) {
case CONFIG_MEM_STANDALONE:
case CONFIG_MEM_SCAN_CHAIN:
break;
case CONFIG_MEM_MEMORY_BANK: {
/* Find BL/WL ports */
std::vector<CircuitPortId> blb_ports = circuit_lib.model_ports_by_type(rram_model, CIRCUIT_MODEL_PORT_BLB);
for (auto blb_port : blb_ports) {
num_shared_config_bits = std::max((int)num_shared_config_bits, (int)circuit_lib.port_size(blb_port) - 1);
}
break;
}
default:
VTR_LOG_ERROR("Invalid type of configuration protocol!\n");
exit(1);
}
return num_shared_config_bits;
}
/********************************************************************
* A generic function to find the number of shared configuration bits
* for circuit model
* It will return 0 for CMOS circuits
* It will return the maximum shared configuration bits across ReRAM models
*
* Note: This function may give WRONG results when all the SRAM ports
* are not properly linked to its circuit models!
* So, it should be called after the SRAM linking is done!!!
*
* IMPORTANT: This function should NOT be used to find the number of shared configuration bits
* for a multiplexer, because the multiplexer size is determined during
* the FPGA architecture generation (NOT during the XML parsing).
*******************************************************************/
size_t find_circuit_num_shared_config_bits(const CircuitLibrary& circuit_lib,
const CircuitModelId& circuit_model,
const e_config_protocol_type& config_protocol_type) {
size_t num_shared_config_bits = 0;
std::vector<CircuitPortId> sram_ports = circuit_lib.model_ports_by_type(circuit_model, CIRCUIT_MODEL_PORT_SRAM);
for (auto sram_port : sram_ports) {
CircuitModelId sram_model = circuit_lib.port_tri_state_model(sram_port);
VTR_ASSERT( true == circuit_lib.valid_model_id(sram_model) );
/* Depend on the design technolgy of SRAM model, the number of configuration bits will be different */
switch (circuit_lib.design_tech_type(sram_model)) {
case CIRCUIT_MODEL_DESIGN_CMOS:
/* CMOS circuit do not need shared configuration bits */
break;
case CIRCUIT_MODEL_DESIGN_RRAM:
/* RRAM circuit do need shared configuration bits, but it is subjected to the largest one among different SRAM models */
num_shared_config_bits = std::max((int)num_shared_config_bits, (int)find_rram_circuit_num_shared_config_bits(circuit_lib, sram_model, config_protocol_type));
break;
default:
VTR_LOG_ERROR("Invalid design technology for SRAM circuit model!\n",
circuit_lib.model_name(circuit_model).c_str());
exit(1);
}
}
return num_shared_config_bits;
}
/********************************************************************
* A generic function to find the number of configuration bits
* for circuit model
* It will sum up the sizes of all the sram ports
*
* IMPORTANT: This function should NOT be used to find the number of configuration bits
* for a multiplexer, because the multiplexer size is determined during
* the FPGA architecture generation (NOT during the XML parsing).
*******************************************************************/
size_t find_circuit_num_config_bits(const CircuitLibrary& circuit_lib,
const CircuitModelId& circuit_model) {
size_t num_config_bits = 0;
std::vector<CircuitPortId> sram_ports = circuit_lib.model_ports_by_type(circuit_model, CIRCUIT_MODEL_PORT_SRAM);
for (auto sram_port : sram_ports) {
num_config_bits += circuit_lib.port_size(sram_port);
}
return num_config_bits;
}
/********************************************************************
* A generic function to find all the global ports in a circuit library
*
* IMPORTANT: This function will uniquify the global ports whose share
* share the same name !!!
*******************************************************************/
std::vector<CircuitPortId> find_circuit_library_global_ports(const CircuitLibrary& circuit_lib) {
std::vector<CircuitPortId> global_ports;
for (auto port : circuit_lib.ports()) {
/* By pass non-global ports*/
if (false == circuit_lib.port_is_global(port)) {
continue;
}
/* Check if a same port with the same name has already been in the list */
bool add_to_list = true;
for (const auto& global_port : global_ports) {
if (0 == circuit_lib.port_prefix(port).compare(circuit_lib.port_prefix(global_port))) {
/* Same name, skip list update */
add_to_list = false;
break;
}
}
if (true == add_to_list) {
/* Add the global_port to the list */
global_ports.push_back(port);
}
}
return global_ports;
}
/********************************************************************
* A generic function to find all the unique user-defined
* Verilog netlists in a circuit library
* Netlists with same names will be considered as one
*******************************************************************/
std::vector<std::string> find_circuit_library_unique_verilog_netlists(const CircuitLibrary& circuit_lib) {
std::vector<std::string> netlists;
for (const CircuitModelId& model : circuit_lib.models()) {
/* Skip empty netlist names */
if (true == circuit_lib.model_verilog_netlist(model).empty()) {
continue;
}
/* See if the netlist name is already in the list */
std::vector<std::string>::iterator it = std::find(netlists.begin(), netlists.end(), circuit_lib.model_verilog_netlist(model));
if (it == netlists.end()) {
netlists.push_back(circuit_lib.model_verilog_netlist(model));
}
}
return netlists;
}
} /* end namespace openfpga */

View File

@ -0,0 +1,44 @@
/********************************************************************
* Header file for circuit_library_utils.cpp
*******************************************************************/
#ifndef CIRCUIT_LIBRARY_UTILS_H
#define CIRCUIT_LIBRARY_UTILS_H
/********************************************************************
* Include header files that are required by function declaration
*******************************************************************/
#include <vector>
#include "circuit_types.h"
#include "circuit_library.h"
/********************************************************************
* Function declaration
*******************************************************************/
/* begin namespace openfpga */
namespace openfpga {
std::vector<CircuitModelId> find_circuit_sram_models(const CircuitLibrary& circuit_lib,
const CircuitModelId& circuit_model);
std::vector<CircuitPortId> find_circuit_regular_sram_ports(const CircuitLibrary& circuit_lib,
const CircuitModelId& circuit_model);
std::vector<CircuitPortId> find_circuit_mode_select_sram_ports(const CircuitLibrary& circuit_lib,
const CircuitModelId& circuit_model);
size_t find_circuit_num_shared_config_bits(const CircuitLibrary& circuit_lib,
const CircuitModelId& circuit_model,
const e_config_protocol_type& sram_orgz_type);
size_t find_circuit_num_config_bits(const CircuitLibrary& circuit_lib,
const CircuitModelId& circuit_model);
std::vector<CircuitPortId> find_circuit_library_global_ports(const CircuitLibrary& circuit_lib);
std::vector<std::string> find_circuit_library_unique_verilog_netlists(const CircuitLibrary& circuit_lib);
} /* end namespace openfpga */
#endif

View File

@ -228,4 +228,30 @@ e_circuit_model_type pb_interconnect_require_circuit_model_type(const e_intercon
return type_mapping.at(pb_interc_type);
}
/********************************************************************
* This function aims to find the required type for a pb_port
* when it is linked to a port of a circuit model
* We start from the view of a circuit port here.
* This is due to circuit port has more types than a pb_type port
* as it is designed for physical implementation
* As such, a few types of circuit port may be directed the same type of pb_type port
* This is done to make the mapping much simpler than doing in the opposite direction
*******************************************************************/
enum PORTS circuit_port_require_pb_port_type(const e_circuit_model_port_type& circuit_port_type) {
std::map<e_circuit_model_port_type, enum PORTS> type_mapping;
/* These circuit model ports may be founed in the pb_type ports */
type_mapping[CIRCUIT_MODEL_PORT_INPUT] = IN_PORT;
type_mapping[CIRCUIT_MODEL_PORT_OUTPUT] = OUT_PORT;
type_mapping[CIRCUIT_MODEL_PORT_INOUT] = INOUT_PORT;
type_mapping[CIRCUIT_MODEL_PORT_CLOCK] = IN_PORT;
/* Other circuit model ports should not be found when mapping to the pb_type ports */
if (type_mapping.end() == type_mapping.find(circuit_port_type)) {
return ERR_PORT;
}
return type_mapping.at(circuit_port_type);
}
} /* end namespace openfpga */

View File

@ -41,6 +41,8 @@ e_interconnect pb_interconnect_physical_type(t_interconnect* pb_interc,
e_circuit_model_type pb_interconnect_require_circuit_model_type(const e_interconnect& pb_interc_type);
enum PORTS circuit_port_require_pb_port_type(const e_circuit_model_port_type& circuit_port_type);
} /* end namespace openfpga */
#endif