2022-10-06 19:08:50 -05:00
# include "config_protocol.h"
2020-01-18 22:19:20 -06:00
# include "vtr_assert.h"
2021-09-23 16:25:25 -05:00
# include "vtr_log.h"
2020-01-18 22:19:20 -06:00
/************************************************************************
* Member functions for class ConfigProtocol
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/************************************************************************
* Constructors
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2023-04-21 04:01:51 -05:00
ConfigProtocol : : ConfigProtocol ( ) {
INDICE_STRING_DELIM_ = ' , ' ;
}
2020-01-18 22:19:20 -06:00
/************************************************************************
* Public Accessors
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2022-10-06 19:08:50 -05:00
e_config_protocol_type ConfigProtocol : : type ( ) const { return type_ ; }
2020-01-18 22:19:20 -06:00
std : : string ConfigProtocol : : memory_model_name ( ) const {
return memory_model_name_ ;
}
2022-10-06 19:08:50 -05:00
CircuitModelId ConfigProtocol : : memory_model ( ) const { return memory_model_ ; }
2020-01-18 22:19:20 -06:00
2022-10-06 19:08:50 -05:00
int ConfigProtocol : : num_regions ( ) const { return num_regions_ ; }
2020-09-28 14:51:43 -05:00
2023-04-21 04:01:51 -05:00
std : : vector < BasicPort > ConfigProtocol : : prog_clock_ports ( ) const {
std : : vector < BasicPort > keys ;
for ( const auto & [ k , v ] : prog_clk_ccff_head_indices_ ) {
keys . push_back ( k ) ;
}
return keys ;
}
std : : string ConfigProtocol : : prog_clock_port_ccff_head_indices ( const BasicPort & port ) const {
std : : string ret ( " " ) ;
2023-04-21 23:44:34 -05:00
std : : vector < size_t > raw = prog_clock_port_ccff_head_indices ( port ) ;
if ( ! raw . empty ( ) ) {
for ( size_t idx : raw ) {
2023-04-21 04:01:51 -05:00
/* TODO: We need a join function */
ret + = std : : to_string ( idx ) + std : : string ( INDICE_STRING_DELIM ) ;
}
/* Remove the last comma */
ret . pop ( ) ;
}
return ret ;
}
2023-04-21 23:44:34 -05:00
std : : vector < size_t > ConfigProtocol : : prog_clock_port_ccff_head_indices ( const BasicPort & port ) const {
std : : vector < size_t > ret ;
auto result = prog_clk_ccff_head_indices . find ( port ) ;
if ( result ! = prog_clk_ccff_head_indices . end ( ) ) {
return result - > second ;
}
return ret ;
}
2021-09-23 16:25:25 -05:00
e_blwl_protocol_type ConfigProtocol : : bl_protocol_type ( ) const {
return bl_protocol_type_ ;
}
std : : string ConfigProtocol : : bl_memory_model_name ( ) const {
return bl_memory_model_name_ ;
}
CircuitModelId ConfigProtocol : : bl_memory_model ( ) const {
return bl_memory_model_ ;
}
2022-10-06 19:08:50 -05:00
size_t ConfigProtocol : : bl_num_banks ( ) const { return bl_num_banks_ ; }
2021-09-28 16:20:35 -05:00
2021-09-23 16:25:25 -05:00
e_blwl_protocol_type ConfigProtocol : : wl_protocol_type ( ) const {
return wl_protocol_type_ ;
}
std : : string ConfigProtocol : : wl_memory_model_name ( ) const {
return wl_memory_model_name_ ;
}
CircuitModelId ConfigProtocol : : wl_memory_model ( ) const {
return wl_memory_model_ ;
}
2022-10-06 19:08:50 -05:00
size_t ConfigProtocol : : wl_num_banks ( ) const { return wl_num_banks_ ; }
2021-09-28 16:20:35 -05:00
2020-01-18 22:19:20 -06:00
/************************************************************************
* Public Mutators
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
void ConfigProtocol : : set_type ( const e_config_protocol_type & type ) {
type_ = type ;
}
2022-10-06 19:08:50 -05:00
void ConfigProtocol : : set_memory_model_name (
const std : : string & memory_model_name ) {
2020-01-18 22:19:20 -06:00
memory_model_name_ = memory_model_name ;
}
void ConfigProtocol : : set_memory_model ( const CircuitModelId & memory_model ) {
memory_model_ = memory_model ;
}
2020-09-28 14:51:43 -05:00
void ConfigProtocol : : set_num_regions ( const int & num_regions ) {
num_regions_ = num_regions ;
}
2021-09-23 16:25:25 -05:00
2023-04-21 04:01:51 -05:00
void ConfigProtocol : : set_prog_clock_port_ccff_head_indices_pair ( const BasicPort & port , const std : : string & indices_str ) {
openfpga : : StringToken tokenizer ( indices_str ) ;
std : : vector < int > token_int ;
token_int . reserve ( tokenizer . split ( INDICE_STRING_DELIM_ ) . size ( ) ) ;
for ( std : : string token : tokenizer . split ( INDICE_STRING_DELIM_ ) ) {
token_int . push_back ( std : : atoi ( token ) ) ;
}
auto result = prog_clk_ccff_head_indices . find ( port ) ;
if ( result ! = prog_clk_ccff_head_indices . end ( ) ) {
VTR_LOG_WARN ( " Overwrite the pair between programming clock port '%s[%d:%d]' and ccff head indices (previous: '%s', current: '%s')! \n " , port . get_name ( ) . c_str ( ) , port . get_lsb ( ) , port . get_msb ( ) , prog_clock_port_ccff_head_indices ( port ) . c_str ( ) , indices_str . c_str ( ) ) ;
}
prog_clk_ccff_head_indices_ [ port ] = token_int ;
}
2021-09-23 16:25:25 -05:00
void ConfigProtocol : : set_bl_protocol_type ( const e_blwl_protocol_type & type ) {
if ( CONFIG_MEM_QL_MEMORY_BANK ! = type_ ) {
2022-10-06 19:08:50 -05:00
VTR_LOG_ERROR (
" BL protocol type is only applicable for configuration protocol '%d' " ,
CONFIG_PROTOCOL_TYPE_STRING [ type_ ] ) ;
2021-09-23 16:25:25 -05:00
return ;
}
bl_protocol_type_ = type ;
}
2022-10-06 19:08:50 -05:00
void ConfigProtocol : : set_bl_memory_model_name (
const std : : string & memory_model_name ) {
2021-09-23 16:25:25 -05:00
if ( BLWL_PROTOCOL_SHIFT_REGISTER ! = bl_protocol_type_ ) {
2022-10-06 19:08:50 -05:00
VTR_LOG_ERROR (
" BL protocol memory model is only applicable when '%d' is defined " ,
BLWL_PROTOCOL_TYPE_STRING [ bl_protocol_type_ ] ) ;
2021-09-23 16:25:25 -05:00
return ;
}
bl_memory_model_name_ = memory_model_name ;
}
void ConfigProtocol : : set_bl_memory_model ( const CircuitModelId & memory_model ) {
if ( BLWL_PROTOCOL_SHIFT_REGISTER ! = bl_protocol_type_ ) {
2022-10-06 19:08:50 -05:00
VTR_LOG_ERROR (
" BL protocol memory model is only applicable when '%d' is defined " ,
BLWL_PROTOCOL_TYPE_STRING [ bl_protocol_type_ ] ) ;
2021-09-23 16:25:25 -05:00
return ;
}
bl_memory_model_ = memory_model ;
}
2021-09-28 16:20:35 -05:00
void ConfigProtocol : : set_bl_num_banks ( const size_t & num_banks ) {
if ( BLWL_PROTOCOL_SHIFT_REGISTER ! = bl_protocol_type_ ) {
2022-10-06 19:08:50 -05:00
VTR_LOG_ERROR (
" BL protocol memory model is only applicable when '%d' is defined " ,
BLWL_PROTOCOL_TYPE_STRING [ bl_protocol_type_ ] ) ;
2021-09-28 16:20:35 -05:00
return ;
}
bl_num_banks_ = num_banks ;
}
2021-09-23 16:25:25 -05:00
void ConfigProtocol : : set_wl_protocol_type ( const e_blwl_protocol_type & type ) {
if ( CONFIG_MEM_QL_MEMORY_BANK ! = type_ ) {
2022-10-06 19:08:50 -05:00
VTR_LOG_ERROR (
" WL protocol type is only applicable for configuration protocol '%d' " ,
CONFIG_PROTOCOL_TYPE_STRING [ type_ ] ) ;
2021-09-23 16:25:25 -05:00
return ;
}
wl_protocol_type_ = type ;
}
2022-10-06 19:08:50 -05:00
void ConfigProtocol : : set_wl_memory_model_name (
const std : : string & memory_model_name ) {
2021-09-23 16:25:25 -05:00
if ( BLWL_PROTOCOL_SHIFT_REGISTER ! = wl_protocol_type_ ) {
2022-10-06 19:08:50 -05:00
VTR_LOG_ERROR (
" WL protocol memory model is only applicable when '%d' is defined " ,
BLWL_PROTOCOL_TYPE_STRING [ wl_protocol_type_ ] ) ;
2021-09-23 16:25:25 -05:00
return ;
}
wl_memory_model_name_ = memory_model_name ;
}
void ConfigProtocol : : set_wl_memory_model ( const CircuitModelId & memory_model ) {
if ( BLWL_PROTOCOL_SHIFT_REGISTER ! = wl_protocol_type_ ) {
2022-10-06 19:08:50 -05:00
VTR_LOG_ERROR (
" WL protocol memory model is only applicable when '%d' is defined " ,
BLWL_PROTOCOL_TYPE_STRING [ wl_protocol_type_ ] ) ;
2021-09-23 16:25:25 -05:00
return ;
}
wl_memory_model_ = memory_model ;
}
2021-09-28 16:20:35 -05:00
void ConfigProtocol : : set_wl_num_banks ( const size_t & num_banks ) {
if ( BLWL_PROTOCOL_SHIFT_REGISTER ! = wl_protocol_type_ ) {
2022-10-06 19:08:50 -05:00
VTR_LOG_ERROR (
" WL protocol memory model is only applicable when '%d' is defined " ,
BLWL_PROTOCOL_TYPE_STRING [ wl_protocol_type_ ] ) ;
2021-09-28 16:20:35 -05:00
return ;
}
wl_num_banks_ = num_banks ;
}
2023-04-21 23:44:34 -05:00
/************************************************************************
* Private Validators
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
int ConfigProtocol : : validate_ccff_prog_clocks ( ) {
int num_err = 0 ;
/* Initialize scoreboard */
std : : vector < int > ccff_head_scoreboard ( num_regions ( ) , 0 ) ;
for ( BasicPort port : prog_clock_ports ( ) ) {
/* Must be valid first */
if ( port . is_valid ( ) ) {
VTR_LOG_ERROR ( " Programming clock '%s[%d:%d]' is not a valid port! \n " , port . get_name ( ) . c_str ( ) , port . get_lsb ( ) , port . get_msb ( ) ) ;
num_err + + ;
}
/* Each port should have a width of 1 */
if ( port . get_width ( ) ! = 1 ) {
VTR_LOG_ERROR ( " Expect each programming clock has a size of 1 in the definition. '%s[%d:%d]' violates the rule! \n " , port . get_name ( ) . c_str ( ) , port . get_lsb ( ) , port . get_msb ( ) ) ;
num_err + + ;
}
/* Fill scoreboard */
for ( size_t ccff_head_idx : prog_clock_port_ccff_head_indices ( port ) ) {
if ( ccff_head_idx = > ccff_head_scoreboard . size ( ) ) {
VTR_LOG_ERROR ( " Programming clock '%s[%d:%d]' controlls an invalid ccff head '%ld' (Expect [0, '%ld'])! \n " , port . get_name ( ) . c_str ( ) , port . get_lsb ( ) , port . get_msb ( ) , ccff_head_idx , ccff_head_scoreboard . size ( ) - 1 ) ;
num_err + + ;
}
ccff_head_scoreboard [ ccff_head_idx ] + + ;
}
}
if ( prog_clock_ports ( ) . size ( ) ! = num_regions ( ) ) {
VTR_LOG_ERROR ( " Number of programming clocks '%ld' does not match the number of configuration regions '%ld'! \n " , prog_clock_ports ( ) . size ( ) , num_regions ( ) ) ;
num_err + + ;
}
for ( size_t iregion = 0 ; iregion < ccff_head_scoreboard . size ( ) ; iregion + + ) {
if ( ccff_head_scoreboard [ iregion ] = = 0 ) {
VTR_LOG_ERROR ( " Configuration chain '%ld' is not driven by any programming clock! \n " , iregion ) ;
num_err + + ;
}
if ( ccff_head_scoreboard [ iregion ] > 1 ) {
VTR_LOG_ERROR ( " Configuration chain '%ld' is driven by %ld programming clock! \n " , iregion , ccff_head_scoreboard [ iregion ] ) ;
num_err + + ;
}
}
return num_err ;
}
/************************************************************************
* Public Validators
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
int ConfigProtocol : : validate ( ) {
int num_err = 0 ;
if ( type ( ) = = CONFIG_MEM_SCAN_CHAIN ) {
num_err + = validate_ccff_prog_clocks ( ) ;
}
return num_err ;
}