2020-01-12 19:11:00 -06:00
/************************************************************************
* Function to perform fundamental checking for the circuit library
* such as
* 1. if default circuit models are defined
* 2. if any circuit models shared the same name or prefix
* 3. if nay circuit model miss mandatory ports
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2020-01-23 21:12:30 -06:00
/* Headers from vtrutil library */
2020-01-12 19:11:00 -06:00
# include "vtr_assert.h"
# include "vtr_log.h"
2020-01-23 21:12:30 -06:00
# include "vtr_time.h"
2020-01-12 19:11:00 -06:00
# include "check_circuit_library.h"
/************************************************************************
* Circuit models have unique names , return the number of errors
* If not found , we give an error
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static
size_t check_circuit_library_unique_names ( const CircuitLibrary & circuit_lib ) {
size_t num_err = 0 ;
for ( size_t i = 0 ; i < circuit_lib . num_models ( ) ; + + i ) {
/* Skip for the last element, because the inner loop will access it */
if ( i = = circuit_lib . num_models ( ) - 1 ) {
continue ;
}
/* Get the name of reference */
const std : : string & i_name = circuit_lib . model_name ( CircuitModelId ( i ) ) ;
for ( size_t j = i + 1 ; j < circuit_lib . num_models ( ) ; + + j ) {
/* Compare the name of candidate */
const std : : string & j_name = circuit_lib . model_name ( CircuitModelId ( j ) ) ;
/* Compare the name and skip for different names */
if ( 0 ! = i_name . compare ( j_name ) ) {
continue ;
}
VTR_LOG_ERROR ( " Circuit model(index=%d) and (index=%d) share the same name, which is invalid! \n " ,
i , j , i_name . c_str ( ) ) ;
/* Incremental the counter for errors */
num_err + + ;
}
}
return num_err ;
}
/************************************************************************
* Circuit models have unique names , return the number of errors
* If not found , we give an error
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static
size_t check_circuit_library_unique_prefix ( const CircuitLibrary & circuit_lib ) {
size_t num_err = 0 ;
for ( size_t i = 0 ; i < circuit_lib . num_models ( ) ; + + i ) {
/* Skip for the last element, because the inner loop will access it */
if ( i = = circuit_lib . num_models ( ) - 1 ) {
continue ;
}
/* Get the name of reference */
const std : : string & i_prefix = circuit_lib . model_prefix ( CircuitModelId ( i ) ) ;
for ( size_t j = i + 1 ; j < circuit_lib . num_models ( ) ; + + j ) {
/* Compare the name of candidate */
const std : : string & j_prefix = circuit_lib . model_prefix ( CircuitModelId ( j ) ) ;
/* Compare the name and skip for different prefix */
if ( 0 ! = i_prefix . compare ( j_prefix ) ) {
continue ;
}
VTR_LOG_ERROR ( " Circuit model(name=%s) and (name=%s) share the same prefix, which is invalid! \n " ,
circuit_lib . model_name ( CircuitModelId ( i ) ) . c_str ( ) ,
circuit_lib . model_name ( CircuitModelId ( j ) ) . c_str ( ) ,
i_prefix . c_str ( ) ) ;
/* Incremental the counter for errors */
num_err + + ;
}
}
return num_err ;
}
/************************************************************************
* A generic function to check the port list of a circuit model in a given type
* If not found , we give an error
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static
size_t check_circuit_model_required ( const CircuitLibrary & circuit_lib ,
const enum e_circuit_model_type & circuit_model_type_to_check ) {
size_t num_err = 0 ;
/* We must have an IOPAD*/
if ( 0 = = circuit_lib . models_by_type ( circuit_model_type_to_check ) . size ( ) ) {
VTR_LOG_ERROR ( " At least one %s circuit model is required! \n " ,
CIRCUIT_MODEL_TYPE_STRING [ size_t ( circuit_model_type_to_check ) ] ) ;
/* Incremental the counter for errors */
num_err + + ;
}
return num_err ;
}
/************************************************************************
* A generic function to check the port list of a circuit model in a given type
* If not found , we give an error
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
size_t check_one_circuit_model_port_required ( const CircuitLibrary & circuit_lib ,
const CircuitModelId & circuit_model ,
const std : : vector < enum e_circuit_model_port_type > & port_types_to_check ) {
size_t num_err = 0 ;
for ( const auto & port_type : port_types_to_check ) {
if ( 0 = = circuit_lib . model_ports_by_type ( circuit_model , port_type ) . size ( ) ) {
VTR_LOG_ERROR ( " %s circuit model(name=%s) does not have %s port \n " ,
CIRCUIT_MODEL_TYPE_STRING [ size_t ( circuit_lib . model_type ( circuit_model ) ) ] ,
circuit_lib . model_name ( circuit_model ) . c_str ( ) ,
CIRCUIT_MODEL_PORT_TYPE_STRING [ size_t ( port_type ) ] ) ;
/* Incremental the counter for errors */
num_err + + ;
}
}
return num_err ;
}
/************************************************************************
* A generic function to check the port size of a given circuit model
* if the port size does not match , we give an error
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
size_t check_one_circuit_model_port_size_required ( const CircuitLibrary & circuit_lib ,
const CircuitModelId & circuit_model ,
const CircuitPortId & circuit_port ,
const size_t & port_size_to_check ) {
size_t num_err = 0 ;
if ( port_size_to_check ! = circuit_lib . port_size ( circuit_port ) ) {
2020-05-28 13:25:47 -05:00
VTR_LOG_ERROR ( " Expect circuit model %s to have %d %s ports but only see %d! \n " ,
circuit_lib . model_name ( circuit_model ) . c_str ( ) ,
port_size_to_check ,
2020-01-12 19:11:00 -06:00
CIRCUIT_MODEL_PORT_TYPE_STRING [ size_t ( circuit_lib . port_type ( circuit_port ) ) ] ,
2020-05-28 13:25:47 -05:00
circuit_lib . port_size ( circuit_port ) ) ;
2020-01-12 19:11:00 -06:00
/* Incremental the counter for errors */
num_err + + ;
}
return num_err ;
}
/************************************************************************
* A generic function to check the port size of a given circuit model
* if the number of ports in the given type does not match , we give an error
* for each port , if the port size does not match , we give an error
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
size_t check_one_circuit_model_port_type_and_size_required ( const CircuitLibrary & circuit_lib ,
const CircuitModelId & circuit_model ,
const enum e_circuit_model_port_type & port_type_to_check ,
const size_t & num_ports_to_check ,
const size_t & port_size_to_check ,
const bool & include_global_ports ) {
size_t num_err = 0 ;
std : : vector < CircuitPortId > ports = circuit_lib . model_ports_by_type ( circuit_model , port_type_to_check , false = = include_global_ports ) ;
if ( num_ports_to_check ! = ports . size ( ) ) {
VTR_LOG_ERROR ( " Expect %d %s ports for a %s circuit model, but only have %d %s ports! \n " ,
num_ports_to_check ,
CIRCUIT_MODEL_PORT_TYPE_STRING [ size_t ( port_type_to_check ) ] ,
CIRCUIT_MODEL_TYPE_STRING [ size_t ( circuit_lib . model_type ( circuit_model ) ) ] ,
ports . size ( ) ,
CIRCUIT_MODEL_PORT_TYPE_STRING [ size_t ( port_type_to_check ) ] ) ;
num_err + + ;
}
for ( const auto & port : ports ) {
num_err + = check_one_circuit_model_port_size_required ( circuit_lib ,
circuit_model ,
port , port_size_to_check ) ;
}
return num_err ;
}
/************************************************************************
* A generic function to check the port list of circuit models in a given type
* If not found , we give an error
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static
size_t check_circuit_model_port_required ( const CircuitLibrary & circuit_lib ,
const enum e_circuit_model_type & circuit_model_type_to_check ,
const std : : vector < enum e_circuit_model_port_type > & port_types_to_check ) {
size_t num_err = 0 ;
for ( const auto & id : circuit_lib . models_by_type ( circuit_model_type_to_check ) ) {
num_err + = check_one_circuit_model_port_required ( circuit_lib , id , port_types_to_check ) ;
}
return num_err ;
}
2020-08-23 14:48:22 -05:00
/************************************************************************
* A generic function to search each default circuit model by types
* that have been defined by users .
* If a type of circuit model is defined , we expect there is a default model
* to be specified
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static
size_t check_default_circuit_model_by_types ( const CircuitLibrary & circuit_lib ) {
size_t num_err = 0 ;
for ( size_t itype = 0 ; itype < NUM_CIRCUIT_MODEL_TYPES ; + + itype ) {
std : : vector < CircuitModelId > curr_models = circuit_lib . models_by_type ( e_circuit_model_type ( itype ) ) ;
if ( 0 = = curr_models . size ( ) ) {
continue ;
}
/* Go through the models and try to find a default one */
size_t found_default_counter = 0 ;
for ( const auto & curr_model : curr_models ) {
if ( true = = circuit_lib . model_is_default ( curr_model ) ) {
found_default_counter + + ;
}
}
if ( 0 = = found_default_counter ) {
VTR_LOG_ERROR ( " Miss a default circuit model for the type %s! Try to define it in your architecture file! \n " ,
CIRCUIT_MODEL_TYPE_STRING [ itype ] ) ;
num_err + + ;
}
if ( 1 < found_default_counter ) {
VTR_LOG_ERROR ( " Found >1 default circuit models for the type %s! Expect only one! \n " ,
CIRCUIT_MODEL_TYPE_STRING [ itype ] ) ;
num_err + + ;
}
}
return num_err ;
}
2020-01-12 19:11:00 -06:00
/************************************************************************
* A generic function to find the default circuit model with a given type
* If not found , we give an error
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static
size_t check_required_default_circuit_model ( const CircuitLibrary & circuit_lib ,
const enum e_circuit_model_type & circuit_model_type ) {
size_t num_err = 0 ;
if ( CircuitModelId : : INVALID ( ) = = circuit_lib . default_model ( circuit_model_type ) ) {
2020-08-23 14:48:22 -05:00
VTR_LOG_ERROR ( " Miss a default circuit model for the type %s! Try to define it in your architecture file! \n " ,
2020-01-12 19:11:00 -06:00
CIRCUIT_MODEL_TYPE_STRING [ size_t ( circuit_model_type ) ] ) ;
2020-08-23 14:48:22 -05:00
num_err + + ;
2020-01-12 19:11:00 -06:00
}
return num_err ;
}
/************************************************************************
* A function to check the port map of FF circuit model
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
size_t check_ff_circuit_model_ports ( const CircuitLibrary & circuit_lib ,
const CircuitModelId & circuit_model ) {
size_t num_err = 0 ;
/* Check the type of circuit model */
VTR_ASSERT ( CIRCUIT_MODEL_FF = = circuit_lib . model_type ( circuit_model ) ) ;
/* Check if we have D, Set and Reset */
num_err + = check_one_circuit_model_port_type_and_size_required ( circuit_lib , circuit_model ,
CIRCUIT_MODEL_PORT_INPUT ,
3 , 1 , false ) ;
/* Check if we have a clock */
num_err + = check_one_circuit_model_port_type_and_size_required ( circuit_lib , circuit_model ,
CIRCUIT_MODEL_PORT_CLOCK ,
1 , 1 , false ) ;
/* Check if we have output */
num_err + = check_one_circuit_model_port_type_and_size_required ( circuit_lib , circuit_model ,
CIRCUIT_MODEL_PORT_OUTPUT ,
1 , 1 , false ) ;
return num_err ;
}
/************************************************************************
* A function to check the port map of CCFF circuit model
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
size_t check_ccff_circuit_model_ports ( const CircuitLibrary & circuit_lib ,
const CircuitModelId & circuit_model ) {
size_t num_err = 0 ;
/* Check the type of circuit model */
VTR_ASSERT ( CIRCUIT_MODEL_CCFF = = circuit_lib . model_type ( circuit_model ) ) ;
/* Check if we have D, Set and Reset */
2021-01-04 16:13:54 -06:00
/* We can have either 1 input which is D or 2 inputs which are D and scan input */
size_t num_input_ports = circuit_lib . model_ports_by_type ( circuit_model , CIRCUIT_MODEL_PORT_INPUT , true ) . size ( ) ;
if ( ( 1 ! = num_input_ports ) & & ( 2 ! = num_input_ports ) ) {
VTR_LOG_ERROR ( " Configuration flip-flop '%s' must have either 1 or 2 %s ports! \n \t Among which the first input is a regular input (e.g., D) and the other could be scan-chain input (e.g., SI) \n " ,
circuit_lib . model_name ( circuit_model ) . c_str ( ) ,
CIRCUIT_MODEL_PORT_TYPE_STRING [ size_t ( CIRCUIT_MODEL_PORT_INPUT ) ] ) ;
num_err + + ;
}
2020-01-12 19:11:00 -06:00
num_err + = check_one_circuit_model_port_type_and_size_required ( circuit_lib , circuit_model ,
CIRCUIT_MODEL_PORT_INPUT ,
2021-01-04 16:13:54 -06:00
num_input_ports , 1 , false ) ;
2020-01-12 19:11:00 -06:00
/* Check if we have a clock */
num_err + = check_one_circuit_model_port_type_and_size_required ( circuit_lib , circuit_model ,
CIRCUIT_MODEL_PORT_CLOCK ,
1 , 1 , true ) ;
2021-01-04 16:13:54 -06:00
/* Check if we have 2 or 4 outputs */
2020-11-06 12:16:46 -06:00
size_t num_output_ports = circuit_lib . model_ports_by_type ( circuit_model , CIRCUIT_MODEL_PORT_OUTPUT , true ) . size ( ) ;
2021-01-04 16:13:54 -06:00
if ( ( 2 ! = num_output_ports ) & & ( 4 ! = num_output_ports ) ) {
VTR_LOG_ERROR ( " Configuration flip-flop '%s' must have either 2 or 4 %s ports! \n \t Among which two manadatory outputs are regular data outputs (e.g., Q and QN) and the other two could be configure-enable outputs (e.g., cfg_en_Q and cgf_en_QN) \n " ,
circuit_lib . model_name ( circuit_model ) . c_str ( ) ,
CIRCUIT_MODEL_PORT_TYPE_STRING [ size_t ( CIRCUIT_MODEL_PORT_OUTPUT ) ] ) ;
num_err + + ;
}
2020-01-12 19:11:00 -06:00
num_err + = check_one_circuit_model_port_type_and_size_required ( circuit_lib , circuit_model ,
CIRCUIT_MODEL_PORT_OUTPUT ,
2020-11-06 12:16:46 -06:00
num_output_ports , 1 , false ) ;
2020-01-12 19:11:00 -06:00
return num_err ;
}
/************************************************************************
* A function to check the port map of SRAM circuit model
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
size_t check_sram_circuit_model_ports ( const CircuitLibrary & circuit_lib ,
const CircuitModelId & circuit_model ,
const bool & check_blwl ) {
size_t num_err = 0 ;
/* Check the type of circuit model */
VTR_ASSERT ( CIRCUIT_MODEL_SRAM = = circuit_lib . model_type ( circuit_model ) ) ;
/* Check if we has 1 output with size 2 */
num_err + = check_one_circuit_model_port_type_and_size_required ( circuit_lib , circuit_model ,
CIRCUIT_MODEL_PORT_OUTPUT ,
2020-05-28 13:25:47 -05:00
2 , 1 , false ) ;
2020-01-12 19:11:00 -06:00
/* basic check finished here */
if ( false = = check_blwl ) {
return num_err ;
}
/* If bl and wl are required, check their existence */
num_err + = check_one_circuit_model_port_type_and_size_required ( circuit_lib , circuit_model ,
CIRCUIT_MODEL_PORT_BL ,
1 , 1 , false ) ;
num_err + = check_one_circuit_model_port_type_and_size_required ( circuit_lib , circuit_model ,
CIRCUIT_MODEL_PORT_WL ,
1 , 1 , false ) ;
return num_err ;
}
2020-07-22 19:47:12 -05:00
/************************************************************************
* Check all the ports make sure , they satisfy the restriction
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2020-01-12 19:11:00 -06:00
static
size_t check_circuit_library_ports ( const CircuitLibrary & circuit_lib ) {
size_t num_err = 0 ;
/* Check global ports: make sure all the global ports are input ports */
for ( const auto & port : circuit_lib . ports ( ) ) {
if ( ( circuit_lib . port_is_global ( port ) )
2020-04-05 17:01:25 -05:00
& & ( ! circuit_lib . is_input_port ( port ) )
& & ( ! circuit_lib . is_output_port ( port ) ) ) {
VTR_LOG_ERROR ( " Circuit port (type=%s) of model (name=%s) is defined as global but not an input/output port! \n " ,
2020-01-12 19:11:00 -06:00
CIRCUIT_MODEL_PORT_TYPE_STRING [ size_t ( circuit_lib . port_type ( port ) ) ] ,
circuit_lib . model_name ( port ) . c_str ( ) ) ;
num_err + + ;
}
}
2020-04-08 17:54:08 -05:00
/* Check global output ports: make sure they are all I/Os */
for ( const auto & port : circuit_lib . ports ( ) ) {
if ( ( circuit_lib . port_is_global ( port ) )
& & ( CIRCUIT_MODEL_PORT_OUTPUT = = circuit_lib . port_type ( port ) )
& & ( false = = circuit_lib . port_is_io ( port ) ) ) {
VTR_LOG_ERROR ( " Circuit port (type=%s) of model (name=%s) is defined as global output port but not an I/O! \n " ,
CIRCUIT_MODEL_PORT_TYPE_STRING [ size_t ( circuit_lib . port_type ( port ) ) ] ,
circuit_lib . model_name ( port ) . c_str ( ) ) ;
num_err + + ;
}
}
2020-01-12 19:11:00 -06:00
/* Check set/reset/config_enable ports: make sure they are all global ports */
for ( const auto & port : circuit_lib . ports ( ) ) {
if ( ( ( circuit_lib . port_is_set ( port ) )
| | ( circuit_lib . port_is_reset ( port ) )
| | ( circuit_lib . port_is_config_enable ( port ) ) )
& & ( ! circuit_lib . port_is_global ( port ) ) ) {
2020-04-05 17:01:25 -05:00
VTR_LOG_ERROR ( " Circuit port (type=%s) of model (name=%s) is defined as a set/reset/config_enable port but it is not global! \n " ,
2020-01-12 19:11:00 -06:00
CIRCUIT_MODEL_PORT_TYPE_STRING [ size_t ( circuit_lib . port_type ( port ) ) ] ,
circuit_lib . model_name ( port ) . c_str ( ) ) ;
num_err + + ;
}
}
/* Check the tri-state map of ports, the length should match the port size! */
for ( const auto & port : circuit_lib . ports ( ) ) {
if ( circuit_lib . port_tri_state_map ( port ) . empty ( ) ) {
continue ; /* No tri-state map is found, go to the next */
}
if ( circuit_lib . port_tri_state_map ( port ) . length ( ) = = circuit_lib . port_size ( port ) ) {
continue ; /* Sizes match, go to the next */
}
/* We have a problem here, sizes do not match, leave a message and raise the error flag */
VTR_LOG_ERROR ( " Tri-state map (=%s) of circuit port (type=%s) of model (name=%s) does not match the port size (=%lu)! \n " ,
circuit_lib . port_tri_state_map ( port ) . c_str ( ) ,
CIRCUIT_MODEL_PORT_TYPE_STRING [ size_t ( circuit_lib . port_type ( port ) ) ] ,
circuit_lib . model_name ( port ) . c_str ( ) ,
circuit_lib . port_size ( port ) ) ;
num_err + + ;
}
/* Check all the global ports which sare the same name also share the same attributes:
* default_value , is_config , is_reset , is_set etc .
*/
std : : vector < CircuitPortId > global_ports ;
/* Collect all the global ports */
for ( auto port : circuit_lib . ports ( ) ) {
/* By pass non-global ports*/
if ( false = = circuit_lib . port_is_global ( port ) ) {
continue ;
}
global_ports . push_back ( port ) ;
}
for ( size_t iport = 0 ; iport < global_ports . size ( ) - 1 ; + + iport ) {
for ( size_t jport = iport + 1 ; jport < global_ports . size ( ) ; + + jport ) {
/* Bypass those do not share the same name */
if ( 0 ! = circuit_lib . port_prefix ( global_ports [ iport ] ) . compare ( circuit_lib . port_prefix ( global_ports [ jport ] ) ) ) {
continue ;
}
/* Check if a same port share the same attributes */
CircuitModelId iport_parent_model = circuit_lib . port_parent_model ( global_ports [ iport ] ) ;
CircuitModelId jport_parent_model = circuit_lib . port_parent_model ( global_ports [ jport ] ) ;
if ( circuit_lib . port_default_value ( global_ports [ iport ] ) ! = circuit_lib . port_default_value ( global_ports [ jport ] ) ) {
VTR_LOG_ERROR ( " Global ports %s from circuit model %s and %s share the same name but have different dfefault values(%lu and %lu)! \n " ,
circuit_lib . port_prefix ( global_ports [ iport ] ) . c_str ( ) ,
circuit_lib . model_name ( iport_parent_model ) . c_str ( ) ,
circuit_lib . model_name ( jport_parent_model ) . c_str ( ) ,
circuit_lib . port_default_value ( global_ports [ iport ] ) ,
circuit_lib . port_default_value ( global_ports [ jport ] )
) ;
num_err + + ;
}
if ( circuit_lib . port_is_reset ( global_ports [ iport ] ) ! = circuit_lib . port_is_reset ( global_ports [ jport ] ) ) {
VTR_LOG_ERROR ( " Global ports %s from circuit model %s and %s share the same name but have different is_reset attributes! \n " ,
circuit_lib . port_prefix ( global_ports [ iport ] ) . c_str ( ) ,
circuit_lib . model_name ( iport_parent_model ) . c_str ( ) ,
circuit_lib . model_name ( jport_parent_model ) . c_str ( )
) ;
num_err + + ;
}
if ( circuit_lib . port_is_set ( global_ports [ iport ] ) ! = circuit_lib . port_is_set ( global_ports [ jport ] ) ) {
VTR_LOG_ERROR ( " Global ports %s from circuit model %s and %s share the same name but have different is_set attributes! \n " ,
circuit_lib . port_prefix ( global_ports [ iport ] ) . c_str ( ) ,
circuit_lib . model_name ( iport_parent_model ) . c_str ( ) ,
circuit_lib . model_name ( jport_parent_model ) . c_str ( )
) ;
num_err + + ;
}
if ( circuit_lib . port_is_config_enable ( global_ports [ iport ] ) ! = circuit_lib . port_is_config_enable ( global_ports [ jport ] ) ) {
VTR_LOG_ERROR ( " Global ports %s from circuit model %s and %s share the same name but have different is_config_enable attributes! \n " ,
circuit_lib . port_prefix ( global_ports [ iport ] ) . c_str ( ) ,
circuit_lib . model_name ( iport_parent_model ) . c_str ( ) ,
circuit_lib . model_name ( jport_parent_model ) . c_str ( )
) ;
num_err + + ;
}
if ( circuit_lib . port_is_prog ( global_ports [ iport ] ) ! = circuit_lib . port_is_prog ( global_ports [ jport ] ) ) {
VTR_LOG_ERROR ( " Global ports %s from circuit model %s and %s share the same name but have different is_prog attributes! \n " ,
circuit_lib . port_prefix ( global_ports [ iport ] ) . c_str ( ) ,
circuit_lib . model_name ( iport_parent_model ) . c_str ( ) ,
circuit_lib . model_name ( jport_parent_model ) . c_str ( )
) ;
num_err + + ;
}
}
}
return num_err ;
}
2020-07-22 19:47:12 -05:00
/************************************************************************
* Check the port requirements for a power - gated circuit model
* - It must have at least 2 global ports and which are config enable signals
* - It must have an Enable port which control power gating
* - It must have an EnableB port which control power gating
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static
int check_power_gated_circuit_model ( const CircuitLibrary & circuit_lib ,
const CircuitModelId & circuit_model ) {
int num_err = 0 ;
std : : vector < CircuitPortId > global_ports = circuit_lib . model_global_ports_by_type ( circuit_model , CIRCUIT_MODEL_PORT_INPUT , true , true ) ;
/* If the circuit model is power-gated, we need to find at least one global config_enable signals */
VTR_ASSERT ( true = = circuit_lib . is_power_gated ( circuit_model ) ) ;
/* Check all the ports we have are good for a power-gated circuit model */
/* We need at least one global port */
if ( 2 > global_ports . size ( ) ) {
VTR_LOGF_ERROR ( __FILE__ , __LINE__ ,
" Expect at least two global ports (a pair of EN/Enb) for circuit model '%s' which is power-gated! \n " ,
circuit_lib . model_name ( circuit_model ) . c_str ( ) ) ;
num_err + + ;
}
/* All the global ports should be config_enable */
int num_config_enable_ports = 0 ;
for ( const auto & port : global_ports ) {
if ( true = = circuit_lib . port_is_config_enable ( port ) ) {
num_config_enable_ports + + ;
}
}
if ( 2 ! = num_config_enable_ports ) {
VTR_LOGF_ERROR ( __FILE__ , __LINE__ ,
" Circuit model '%s' is power-gated. Two config-enable global ports are required! \n " ,
circuit_lib . model_name ( circuit_model ) . c_str ( ) ) ;
num_err + + ;
}
/* Report errors if there are any */
if ( 0 < num_err ) {
return num_err ;
}
/* Try to find a pair of Enable and ENb ports from the global ports */
CircuitPortId en_port = CircuitPortId : : INVALID ( ) ;
CircuitPortId enb_port = CircuitPortId : : INVALID ( ) ;
for ( const auto & port : global_ports ) {
/* Focus on config_enable ports which are power-gate control signals */
if ( false = = circuit_lib . port_is_config_enable ( port ) ) {
continue ;
}
if ( 0 = = circuit_lib . port_default_value ( port ) ) {
en_port = port ;
} else {
VTR_ASSERT ( 1 = = circuit_lib . port_default_value ( port ) ) ;
enb_port = port ;
}
}
/* We must have valid EN/ENb ports */
if ( false = = circuit_lib . valid_circuit_port_id ( en_port ) ) {
VTR_LOGF_ERROR ( __FILE__ , __LINE__ ,
" Fail to find an enable port for the circuit model '%s' is power-gated! \n " ,
circuit_lib . model_name ( circuit_model ) . c_str ( ) ) ;
}
if ( false = = circuit_lib . valid_circuit_port_id ( enb_port ) ) {
VTR_LOGF_ERROR ( __FILE__ , __LINE__ ,
" Fail to find an inverted enable port for the circuit model '%s' is power-gated! \n " ,
circuit_lib . model_name ( circuit_model ) . c_str ( ) ) ;
}
return num_err ;
}
/************************************************************************
* Check the port requirements for each power - gated circuit model
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static
int check_power_gated_circuit_models ( const CircuitLibrary & circuit_lib ) {
int num_err = 0 ;
for ( const CircuitModelId & circuit_model : circuit_lib . models ( ) ) {
if ( true = = circuit_lib . is_power_gated ( circuit_model ) ) {
num_err + = check_power_gated_circuit_model ( circuit_lib , circuit_model ) ;
}
}
return num_err ;
}
2020-11-02 14:54:31 -06:00
/************************************************************************
* Check io has been defined and has input and output ports
* - We must have global I / O port , either its type is inout , input or output
* - For each IOPAD , we must have at least an input an output
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static
size_t check_io_circuit_model ( const CircuitLibrary & circuit_lib ) {
size_t num_err = 0 ;
/* Each I/O cell must have
* - One of the following ports
2020-11-04 21:21:49 -06:00
* - At least 1 ASIC - to - FPGA ( A2F ) port that is defined as global data I / O
* - At least 1 FPGA - to - ASIC ( F2A ) port that is defined as global data I / O !
2020-11-02 14:54:31 -06:00
* - At least 1 regular port that is non - global which is connected to global routing architecture
*/
for ( const auto & io_model : circuit_lib . models_by_type ( CIRCUIT_MODEL_IOPAD ) ) {
2020-11-04 21:21:49 -06:00
bool has_data_io = false ;
bool has_data_input_only_io = false ;
bool has_data_output_only_io = false ;
2020-11-02 14:54:31 -06:00
bool has_internal_connection = false ;
for ( const auto & port : circuit_lib . model_ports ( io_model ) ) {
2020-11-04 21:21:49 -06:00
if ( ( true = = circuit_lib . port_is_io ( port ) )
& & ( true = = circuit_lib . port_is_data_io ( port ) )
& & ( CIRCUIT_MODEL_PORT_INOUT = = circuit_lib . port_type ( port ) )
& & ( true = = circuit_lib . port_is_global ( port ) ) ) {
has_data_io = true ;
continue ; /* Go to next */
}
if ( ( true = = circuit_lib . port_is_io ( port ) )
& & ( true = = circuit_lib . port_is_data_io ( port ) )
& & ( CIRCUIT_MODEL_PORT_INPUT = = circuit_lib . port_type ( port ) )
& & ( true = = circuit_lib . port_is_global ( port ) ) ) {
has_data_input_only_io = true ;
2020-11-02 14:54:31 -06:00
continue ; /* Go to next */
}
2020-11-04 21:21:49 -06:00
if ( ( true = = circuit_lib . port_is_io ( port ) )
& & ( true = = circuit_lib . port_is_data_io ( port ) )
& & ( CIRCUIT_MODEL_PORT_OUTPUT = = circuit_lib . port_type ( port ) )
& & ( true = = circuit_lib . port_is_global ( port ) ) ) {
has_data_output_only_io = true ;
continue ; /* Go to next */
}
2020-11-02 14:54:31 -06:00
if ( ( false = = circuit_lib . port_is_io ( port )
& & ( false = = circuit_lib . port_is_global ( port ) ) )
& & ( CIRCUIT_MODEL_PORT_SRAM ! = circuit_lib . port_type ( port ) ) ) {
has_internal_connection = true ;
continue ; /* Go to next */
}
}
2020-11-04 21:21:49 -06:00
/* Error out when
* - there is no data io , data input - only io and data output - only io
*/
if ( ( false = = has_data_io )
& & ( false = = has_data_input_only_io )
& & ( false = = has_data_output_only_io ) ) {
2020-11-02 14:54:31 -06:00
VTR_LOGF_ERROR ( __FILE__ , __LINE__ ,
2020-11-04 21:21:49 -06:00
" I/O circuit model '%s' does not have any data I/O port defined! \n " ,
2020-11-02 14:54:31 -06:00
circuit_lib . model_name ( io_model ) . c_str ( ) ) ;
num_err + + ;
}
if ( false = = has_internal_connection ) {
VTR_LOGF_ERROR ( __FILE__ , __LINE__ ,
" I/O circuit model '%s' does not have any port connected to FPGA core! \n " ,
circuit_lib . model_name ( io_model ) . c_str ( ) ) ;
num_err + + ;
}
}
return num_err ;
}
2020-01-12 19:11:00 -06:00
/************************************************************************
* Check points to make sure we have a valid circuit library
* Detailed checkpoints :
* 1. Circuit models have unique names
* 2. Circuit models have unique prefix
* 3. Check IOPADs have input and output ports
* 4. Check MUXes has been defined and has input and output ports
* 5. We must have at least one SRAM or CCFF
* 6. SRAM must have at least an input and an output ports
* 7. CCFF must have at least a clock , an input and an output ports
* 8. FF must have at least a clock , an input and an output ports
* 9. LUT must have at least an input , an output and a SRAM ports
* 10. We must have default circuit models for these types : MUX , channel wires and wires
2020-11-02 14:54:31 -06:00
*
* Note :
* - NO modification on the circuit library is allowed !
* The circuit library should be read - only ! ! !
2020-01-12 19:11:00 -06:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2020-05-14 21:02:42 -05:00
bool check_circuit_library ( const CircuitLibrary & circuit_lib ) {
2020-01-12 19:11:00 -06:00
size_t num_err = 0 ;
2020-01-23 21:12:30 -06:00
vtr : : ScopedStartFinishTimer timer ( " Check circuit library " ) ;
2020-01-12 19:11:00 -06:00
/* 1. Circuit models have unique names
* For each circuit model , we always make sure it does not share any name with any circuit model locating after it
*/
num_err + = check_circuit_library_unique_names ( circuit_lib ) ;
/* 2. Circuit models have unique prefix
* For each circuit model , we always make sure it does not share any prefix with any circuit model locating after it
*/
num_err + = check_circuit_library_unique_prefix ( circuit_lib ) ;
/* Check global ports */
num_err + = check_circuit_library_ports ( circuit_lib ) ;
/* 3. Check io has been defined and has input and output ports
2020-11-02 14:54:31 -06:00
* [ a ] We must have global I / O port , either its type is inout , input or output
* [ b ] For each IOPAD , we must have at least an input an output
2020-01-12 19:11:00 -06:00
*/
num_err + = check_circuit_model_required ( circuit_lib , CIRCUIT_MODEL_IOPAD ) ;
2020-11-02 14:54:31 -06:00
num_err + = check_io_circuit_model ( circuit_lib ) ;
2020-01-12 19:11:00 -06:00
/* 4. Check mux has been defined and has input and output ports
* [ a ] We must have a MUX !
* [ b ] For each MUX , we must have at least an input , an output , and an SRAM port
*/
num_err + = check_circuit_model_required ( circuit_lib , CIRCUIT_MODEL_MUX ) ;
std : : vector < enum e_circuit_model_port_type > mux_port_types_required ;
mux_port_types_required . push_back ( CIRCUIT_MODEL_PORT_INPUT ) ;
mux_port_types_required . push_back ( CIRCUIT_MODEL_PORT_OUTPUT ) ;
mux_port_types_required . push_back ( CIRCUIT_MODEL_PORT_SRAM ) ;
num_err + = check_circuit_model_port_required ( circuit_lib , CIRCUIT_MODEL_MUX , mux_port_types_required ) ;
/* 5. We must have at least one SRAM or CCFF */
if ( ( 0 = = circuit_lib . models_by_type ( CIRCUIT_MODEL_SRAM ) . size ( ) )
& & ( 0 = = circuit_lib . models_by_type ( CIRCUIT_MODEL_CCFF ) . size ( ) ) ) {
VTR_LOG_ERROR ( " At least one %s or %s circuit model is required! \n " ,
CIRCUIT_MODEL_TYPE_STRING [ size_t ( CIRCUIT_MODEL_SRAM ) ] ,
CIRCUIT_MODEL_TYPE_STRING [ size_t ( CIRCUIT_MODEL_CCFF ) ] ) ;
/* Incremental the counter for errors */
num_err + + ;
}
/* 6. SRAM must have at least an input and an output ports*/
std : : vector < enum e_circuit_model_port_type > sram_port_types_required ;
sram_port_types_required . push_back ( CIRCUIT_MODEL_PORT_OUTPUT ) ;
num_err + = check_circuit_model_port_required ( circuit_lib , CIRCUIT_MODEL_SRAM , sram_port_types_required ) ;
/* 7. CCFF must have at least a clock, an input and an output ports*/
std : : vector < enum e_circuit_model_port_type > ccff_port_types_required ;
ccff_port_types_required . push_back ( CIRCUIT_MODEL_PORT_CLOCK ) ;
ccff_port_types_required . push_back ( CIRCUIT_MODEL_PORT_INPUT ) ;
ccff_port_types_required . push_back ( CIRCUIT_MODEL_PORT_OUTPUT ) ;
num_err + = check_circuit_model_port_required ( circuit_lib , CIRCUIT_MODEL_CCFF , ccff_port_types_required ) ;
/* 8. FF must have at least a clock, an input and an output ports*/
std : : vector < enum e_circuit_model_port_type > ff_port_types_required ;
ff_port_types_required . push_back ( CIRCUIT_MODEL_PORT_CLOCK ) ;
ff_port_types_required . push_back ( CIRCUIT_MODEL_PORT_INPUT ) ;
ff_port_types_required . push_back ( CIRCUIT_MODEL_PORT_OUTPUT ) ;
num_err + = check_circuit_model_port_required ( circuit_lib , CIRCUIT_MODEL_FF , ff_port_types_required ) ;
/* 9. LUT must have at least an input, an output and a SRAM ports*/
std : : vector < enum e_circuit_model_port_type > lut_port_types_required ;
lut_port_types_required . push_back ( CIRCUIT_MODEL_PORT_SRAM ) ;
lut_port_types_required . push_back ( CIRCUIT_MODEL_PORT_INPUT ) ;
lut_port_types_required . push_back ( CIRCUIT_MODEL_PORT_OUTPUT ) ;
num_err + = check_circuit_model_port_required ( circuit_lib , CIRCUIT_MODEL_LUT , lut_port_types_required ) ;
2020-08-23 14:48:22 -05:00
/* 10. For each type of circuit models that are define, we must have 1 default model
* We must have default circuit models for these types : MUX , channel wires and wires
*/
num_err + = check_default_circuit_model_by_types ( circuit_lib ) ;
2020-01-12 19:11:00 -06:00
num_err + = check_required_default_circuit_model ( circuit_lib , CIRCUIT_MODEL_MUX ) ;
num_err + = check_required_default_circuit_model ( circuit_lib , CIRCUIT_MODEL_CHAN_WIRE ) ;
num_err + = check_required_default_circuit_model ( circuit_lib , CIRCUIT_MODEL_WIRE ) ;
2020-07-22 19:47:12 -05:00
/* 11. Check power-gated inverter/buffer models */
num_err + = check_power_gated_circuit_models ( circuit_lib ) ;
2020-01-12 19:11:00 -06:00
/* If we have any errors, exit */
if ( 0 < num_err ) {
VTR_LOG ( " Finished checking circuit library with %d errors! \n " ,
num_err ) ;
2020-05-14 21:02:42 -05:00
return false ;
2020-01-12 19:11:00 -06:00
}
VTR_LOG ( " Checking circuit library passed. \n " ) ;
2020-05-14 21:02:42 -05:00
return true ;
2020-01-12 19:11:00 -06:00
}
2020-05-25 20:02:14 -05:00