289 lines
12 KiB
C++
289 lines
12 KiB
C++
/************************************************************************
|
|
* Check functions for the content of tile annotation to avoid conflicts with
|
|
* other data structures
|
|
* These functions are not universal methods for the TileAnnotation class
|
|
* They are made to ease the development in some specific purposes
|
|
* Please classify such functions in this file
|
|
***********************************************************************/
|
|
|
|
#include <algorithm>
|
|
|
|
/* Headers from vtrutil library */
|
|
#include "check_tile_annotation.h"
|
|
#include "circuit_library_utils.h"
|
|
#include "openfpga_physical_tile_utils.h"
|
|
#include "vtr_assert.h"
|
|
#include "vtr_log.h"
|
|
|
|
/* begin namespace openfpga */
|
|
namespace openfpga {
|
|
|
|
/********************************************************************
|
|
* Check if the tile annotation is valid without any conflict with
|
|
* circuit library content.
|
|
* Items to check:
|
|
* - The global port defined in tile annotation has no conflicts with
|
|
* the global ports which are defined in circuit library:
|
|
* - If a port has the same name, must ensure that its attributes are the same
|
|
* i.e., is_clock, is_reset, is_set
|
|
* - Otherwise, error out
|
|
*******************************************************************/
|
|
static int check_tile_annotation_conflicts_with_circuit_library(
|
|
const TileAnnotation& tile_annotation, const CircuitLibrary& circuit_lib) {
|
|
int num_err = 0;
|
|
|
|
std::vector<CircuitPortId> ckt_global_ports =
|
|
find_circuit_library_global_ports(circuit_lib);
|
|
for (const TileGlobalPortId& tile_global_port :
|
|
tile_annotation.global_ports()) {
|
|
for (const CircuitPortId& ckt_global_port : ckt_global_ports) {
|
|
if (tile_annotation.global_port_name(tile_global_port) !=
|
|
circuit_lib.port_prefix(ckt_global_port)) {
|
|
continue;
|
|
}
|
|
/* All the global clock port here must be operating clock */
|
|
bool is_both_op_signal = !circuit_lib.port_is_prog(ckt_global_port);
|
|
if (false == is_both_op_signal) {
|
|
VTR_LOGF_ERROR(
|
|
__FILE__, __LINE__,
|
|
"Global port '%s' in tile annotation share the same name as global "
|
|
"port '%s' in circuit library, which is defined for programming "
|
|
"usage!\n",
|
|
tile_annotation.global_port_name(tile_global_port).c_str(),
|
|
circuit_lib.port_prefix(ckt_global_port).c_str());
|
|
num_err++;
|
|
}
|
|
|
|
/* Error out if one is defined as clock while another is not */
|
|
bool is_clock_attr_same =
|
|
(tile_annotation.global_port_is_clock(tile_global_port) !=
|
|
(CIRCUIT_MODEL_PORT_CLOCK == circuit_lib.port_type(ckt_global_port)));
|
|
if (false == is_clock_attr_same) {
|
|
VTR_LOGF_ERROR(
|
|
__FILE__, __LINE__,
|
|
"Global port '%s' in tile annotation share the same name as global "
|
|
"port '%s' in circuit library but has different definition as "
|
|
"clock!\n",
|
|
tile_annotation.global_port_name(tile_global_port).c_str(),
|
|
circuit_lib.port_prefix(ckt_global_port).c_str());
|
|
num_err++;
|
|
}
|
|
|
|
/* Error out if one is defined as reset while another is not */
|
|
bool is_reset_attr_same =
|
|
(tile_annotation.global_port_is_reset(tile_global_port) !=
|
|
circuit_lib.port_is_reset(ckt_global_port));
|
|
if (false == is_reset_attr_same) {
|
|
VTR_LOGF_ERROR(
|
|
__FILE__, __LINE__,
|
|
"Global port '%s' in tile annotation share the same name as global "
|
|
"port '%s' in circuit library but has different definition as "
|
|
"reset!\n",
|
|
tile_annotation.global_port_name(tile_global_port).c_str(),
|
|
circuit_lib.port_prefix(ckt_global_port).c_str());
|
|
num_err++;
|
|
}
|
|
|
|
/* Error out if one is defined as set while another is not */
|
|
bool is_set_attr_same =
|
|
(tile_annotation.global_port_is_set(tile_global_port) !=
|
|
circuit_lib.port_is_set(ckt_global_port));
|
|
if (false == is_set_attr_same) {
|
|
VTR_LOGF_ERROR(
|
|
__FILE__, __LINE__,
|
|
"Global port '%s' in tile annotation share the same name as global "
|
|
"port '%s' in circuit library but has different definition as set!\n",
|
|
tile_annotation.global_port_name(tile_global_port).c_str(),
|
|
circuit_lib.port_prefix(ckt_global_port).c_str());
|
|
num_err++;
|
|
}
|
|
}
|
|
}
|
|
|
|
return num_err;
|
|
}
|
|
|
|
/********************************************************************
|
|
* Check if the tile annotation is valid without any conflict with
|
|
* physical tile definition.
|
|
* Items to check:
|
|
* - The global port defined in tile annotation is a valid port/pin in
|
|
* the physical tile definition.
|
|
* - If the port properties match:
|
|
* - the port in physical tile should have Fc = 0
|
|
* - a clock port should be also a clock port in physical tile
|
|
* - a non-clock port should be defined as a non-clock global port in physical
|
|
*tile
|
|
*******************************************************************/
|
|
static int check_tile_annotation_conflicts_with_physical_tile(
|
|
const TileAnnotation& tile_annotation,
|
|
const std::vector<t_physical_tile_type>& physical_tile_types) {
|
|
int num_err = 0;
|
|
|
|
for (const TileGlobalPortId& tile_global_port :
|
|
tile_annotation.global_ports()) {
|
|
for (size_t tile_info_id = 0;
|
|
tile_info_id <
|
|
tile_annotation.global_port_tile_names(tile_global_port).size();
|
|
++tile_info_id) {
|
|
/* Must find a valid physical tile in the same name */
|
|
size_t found_matched_physical_tile = 0;
|
|
|
|
std::string required_tile_name =
|
|
tile_annotation.global_port_tile_names(tile_global_port)[tile_info_id];
|
|
BasicPort required_tile_port =
|
|
tile_annotation.global_port_tile_ports(tile_global_port)[tile_info_id];
|
|
|
|
for (const t_physical_tile_type& physical_tile : physical_tile_types) {
|
|
if (std::string(physical_tile.name) != required_tile_name) {
|
|
continue;
|
|
}
|
|
|
|
/* Found a match, increment the counter */
|
|
found_matched_physical_tile++;
|
|
|
|
/* Must found a valid port where both port name and port size must
|
|
* match!!! */
|
|
for (const t_sub_tile& sub_tile : physical_tile.sub_tiles) {
|
|
size_t found_matched_physical_tile_port = 0;
|
|
for (const t_physical_tile_port& tile_port : sub_tile.ports) {
|
|
if (std::string(tile_port.name) != required_tile_port.get_name()) {
|
|
continue;
|
|
}
|
|
|
|
BasicPort ref_tile_port(
|
|
tile_port.name, sub_tile.capacity.total() * tile_port.num_pins);
|
|
/* Port size must be in range!!! */
|
|
if (false == ref_tile_port.contained(required_tile_port)) {
|
|
VTR_LOG_ERROR(
|
|
"Tile annotation port '%s[%lu:%lu]' is out of the range of "
|
|
"physical tile port '%s[%lu:%lu]'!",
|
|
required_tile_port.get_name().c_str(),
|
|
required_tile_port.get_lsb(), required_tile_port.get_msb(),
|
|
ref_tile_port.get_name().c_str(), ref_tile_port.get_lsb(),
|
|
ref_tile_port.get_msb());
|
|
num_err++;
|
|
continue;
|
|
}
|
|
|
|
/* Check if port property matches */
|
|
int grid_pin_index = sub_tile.sub_tile_to_tile_pin_indices
|
|
[tile_port.absolute_first_pin_index];
|
|
|
|
if (tile_port.is_clock !=
|
|
tile_annotation.global_port_is_clock(tile_global_port)) {
|
|
VTR_LOGF_ERROR(
|
|
__FILE__, __LINE__,
|
|
"Tile port '%s.%s[%ld:%ld]' in tile annotation '%s' does not "
|
|
"match physical tile port %s.%s in clock property (one is "
|
|
"defined as clock while the other is not)!\n",
|
|
required_tile_name.c_str(),
|
|
required_tile_port.get_name().c_str(),
|
|
required_tile_port.get_lsb(), required_tile_port.get_msb(),
|
|
tile_annotation.global_port_name(tile_global_port).c_str(),
|
|
physical_tile.name, tile_port.name);
|
|
num_err++;
|
|
}
|
|
|
|
if ((false == tile_port.is_clock) &&
|
|
(false == tile_port.is_non_clock_global)) {
|
|
VTR_LOGF_ERROR(
|
|
__FILE__, __LINE__,
|
|
"Tile port '%s.%s[%ld:%ld]' in tile annotation '%s' match "
|
|
"physical tile port %s.%s but is not defined as a non-clock "
|
|
"global port!\n",
|
|
required_tile_name.c_str(),
|
|
required_tile_port.get_name().c_str(),
|
|
required_tile_port.get_lsb(), required_tile_port.get_msb(),
|
|
tile_annotation.global_port_name(tile_global_port).c_str(),
|
|
physical_tile.name, tile_port.name);
|
|
num_err++;
|
|
}
|
|
|
|
float pin_Fc =
|
|
find_physical_tile_pin_Fc(&physical_tile, grid_pin_index);
|
|
if (0. != pin_Fc) {
|
|
VTR_LOGF_ERROR(
|
|
__FILE__, __LINE__,
|
|
"Tile port '%s.%s[%ld:%ld]' in tile annotation '%s' match "
|
|
"physical tile port %s.%s but its Fc is not zero '%g' !\n",
|
|
required_tile_name.c_str(),
|
|
required_tile_port.get_name().c_str(),
|
|
required_tile_port.get_lsb(), required_tile_port.get_msb(),
|
|
tile_annotation.global_port_name(tile_global_port).c_str(),
|
|
physical_tile.name, tile_port.name, pin_Fc);
|
|
}
|
|
|
|
found_matched_physical_tile_port++;
|
|
}
|
|
if (0 == found_matched_physical_tile_port) {
|
|
VTR_LOGF_ERROR(
|
|
__FILE__, __LINE__,
|
|
"Tile port '%s.%s[%ld:%ld]' in tile annotation '%s' does not "
|
|
"match "
|
|
"any physical tile port!\n",
|
|
required_tile_name.c_str(), required_tile_port.get_name().c_str(),
|
|
required_tile_port.get_lsb(), required_tile_port.get_msb(),
|
|
tile_annotation.global_port_name(tile_global_port).c_str());
|
|
num_err++;
|
|
}
|
|
if (1 < found_matched_physical_tile_port) {
|
|
VTR_LOGF_ERROR(
|
|
__FILE__, __LINE__,
|
|
"Tile port '%s.%s[%ld:%ld]' in tile annotation '%s' match more "
|
|
"than "
|
|
"1 physical tile port!\n",
|
|
required_tile_name.c_str(), required_tile_port.get_name().c_str(),
|
|
required_tile_port.get_lsb(), required_tile_port.get_msb(),
|
|
tile_annotation.global_port_name(tile_global_port).c_str());
|
|
num_err++;
|
|
}
|
|
}
|
|
}
|
|
|
|
/* If we found no match, error out */
|
|
if (0 == found_matched_physical_tile) {
|
|
VTR_LOGF_ERROR(
|
|
__FILE__, __LINE__,
|
|
"Tile name '%s' in tile annotation '%s' does not match any physical "
|
|
"tile!\n",
|
|
required_tile_name.c_str(),
|
|
tile_annotation.global_port_name(tile_global_port).c_str());
|
|
num_err++;
|
|
}
|
|
/* If we found more than 1 match, error out */
|
|
if (1 < found_matched_physical_tile) {
|
|
VTR_LOGF_ERROR(
|
|
__FILE__, __LINE__,
|
|
"Tile name '%s' in tile annotation '%s' match more than 1 physical "
|
|
"tile!\n",
|
|
required_tile_name.c_str(),
|
|
tile_annotation.global_port_name(tile_global_port).c_str());
|
|
num_err++;
|
|
}
|
|
}
|
|
}
|
|
|
|
return num_err;
|
|
}
|
|
|
|
/********************************************************************
|
|
* Check if the tile annotation is valid without any conflict with
|
|
* circuit library content and physical tiles.
|
|
*******************************************************************/
|
|
bool check_tile_annotation(
|
|
const TileAnnotation& tile_annotation, const CircuitLibrary& circuit_lib,
|
|
const std::vector<t_physical_tile_type>& physical_tile_types) {
|
|
int num_err = 0;
|
|
num_err += check_tile_annotation_conflicts_with_circuit_library(
|
|
tile_annotation, circuit_lib);
|
|
|
|
num_err += check_tile_annotation_conflicts_with_physical_tile(
|
|
tile_annotation, physical_tile_types);
|
|
|
|
VTR_LOG("Found %ld errors when checking tile annotation!\n", num_err);
|
|
return (0 == num_err);
|
|
}
|
|
|
|
} /* end namespace openfpga */
|