2019-08-12 15:20:11 -05:00
/**********************************************************
* MIT License
*
* Copyright ( c ) 2018 LNIS - The University of Utah
*
* Permission is hereby granted , free of charge , to any person obtaining a copy
* of this software and associated documentation files ( the " Software " ) , to deal
* in the Software without restriction , including without limitation the rights
* to use , copy , modify , merge , publish , distribute , sublicense , and / or sell
* copies of the Software , and to permit persons to whom the Software is
* furnished to do so , subject to the following conditions :
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software .
*
* THE SOFTWARE IS PROVIDED " AS IS " , WITHOUT WARRANTY OF ANY KIND , EXPRESS OR
* IMPLIED , INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY ,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT . IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM , DAMAGES OR OTHER
* LIABILITY , WHETHER IN AN ACTION OF CONTRACT , TORT OR OTHERWISE , ARISING FROM ,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/************************************************************************
* Filename : read_xml_spice . c
* Created by : Xifan Tang
* Change history :
* + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +
* | Date | Author | Notes
* + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +
* | 2015 / XX / XX | Xifan Tang | Created
* + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +
* | 2019 / 08 / 12 | Xifan Tang | Code construction for circuit library
* + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2018-07-26 12:28:21 -05:00
# include <string.h>
# include <assert.h>
# include "util.h"
# include "arch_types.h"
# include "ReadLine.h"
# include "ezxml.h"
# include "read_xml_util.h"
/* SPICE Support headers*/
# include "read_xml_spice_util.h"
# include "read_xml_spice.h"
2019-08-08 18:25:27 -05:00
# include "circuit_library.h"
2019-08-12 15:20:11 -05:00
# include "check_circuit_library.h"
2019-08-08 18:25:27 -05:00
2018-07-26 12:28:21 -05:00
/*********** Subroutines Declaration (only called in this source file) **********/
static void ProcessSpiceMeasParams ( ezxml_t Parent ,
t_spice_meas_params * meas_params ) ;
static void ProcessSpiceStimulateParamsRiseFall ( ezxml_t Parent ,
float * rise_param ,
float * fall_param ,
enum e_spice_accuracy_type * rise_type ,
enum e_spice_accuracy_type * fall_type ) ;
static void ProcessSpiceStimulateParams ( ezxml_t Parent ,
t_spice_stimulate_params * stimulate_params ) ;
static void ProcessSpiceParams ( ezxml_t Parent ,
t_spice_params * spice_params ) ;
static void ProcessSpiceModel ( ezxml_t Parent ,
t_spice_model * spice_model ) ;
static void ProcessSpiceModelPort ( ezxml_t Node ,
t_spice_model_port * port ) ;
static void ProcessSpiceModelPassGateLogic ( ezxml_t Node ,
t_spice_model_pass_gate_logic * pass_gate_logic ) ;
static void ProcessSpiceModelBuffer ( ezxml_t Node ,
t_spice_model_buffer * buffer ) ;
static void ProcessSpiceTransistorType ( ezxml_t Parent ,
t_spice_transistor_type * spice_trans ,
enum e_spice_trans_type trans_type ) ;
static void ProcessSpiceTechLibTransistors ( ezxml_t Parent ,
t_spice_tech_lib * spice_tech_lib ) ;
static
void ProcessSpiceSRAMOrganization ( INOUTP ezxml_t Node ,
OUTP t_sram_inf_orgz * cur_sram_inf_orgz ,
boolean required ) ;
/************ Subroutines***********/
static void ProcessSpiceMeasParams ( ezxml_t Parent ,
t_spice_meas_params * meas_params ) {
ezxml_t Node , Cur ;
/* Check */
if ( meas_params = = NULL ) {
vpr_printf ( TIO_MESSAGE_ERROR , " (File: %s,[LINE%d])meas_params is NULL! \n " , __FILE__ , __LINE__ ) ;
exit ( 1 ) ;
}
/* Number of simulation clock cycles */
if ( 0 = = strcmp ( " auto " , FindProperty ( Parent , " sim_num_clock_cycle " , FALSE ) ) ) {
meas_params - > sim_num_clock_cycle = - 1 ;
meas_params - > auto_select_sim_num_clk_cycle = TRUE ;
} else {
meas_params - > sim_num_clock_cycle = GetIntProperty ( Parent , " sim_num_clock_cycle " , FALSE , - 1 ) ;
meas_params - > auto_select_sim_num_clk_cycle = FALSE ;
}
ezxml_set_attr ( Parent , " sim_num_clock_cycle " , NULL ) ;
/* Accuracy type: either frac or abs, set frac by default*/
if ( NULL = = FindProperty ( Parent , " accuracy_type " , FALSE ) ) {
meas_params - > accuracy_type = SPICE_ABS ;
meas_params - > accuracy = 1e-13 ;
} else {
if ( 0 = = strcmp ( FindProperty ( Parent , " accuracy_type " , TRUE ) , " abs " ) ) {
meas_params - > accuracy_type = SPICE_ABS ;
} else if ( 0 = = strcmp ( FindProperty ( Parent , " accuracy_type " , TRUE ) , " frac " ) ) {
meas_params - > accuracy_type = SPICE_FRAC ;
} else {
vpr_printf ( TIO_MESSAGE_ERROR , " (File:%s, [LINE%d])Invalid accuracy_type at ARCH_XML[LINE%d]! Expect [frac|abs]. \n " ,
__FILE__ , __LINE__ , Parent - > line ) ;
}
meas_params - > accuracy = GetFloatProperty ( Parent , " accuracy " , TRUE , 1e-13 ) ;
}
ezxml_set_attr ( Parent , " accuracy " , NULL ) ;
ezxml_set_attr ( Parent , " accuracy_type " , NULL ) ;
/* Process slew parameters*/
Node = FindElement ( Parent , " slew " , FALSE ) ;
if ( Node ) {
/* Find rise*/
Cur = FindElement ( Node , " rise " , FALSE ) ;
if ( Cur ) {
/* Search for properties*/
/* Rise */
meas_params - > slew_upper_thres_pct_rise = GetFloatProperty ( Cur , " upper_thres_pct " , TRUE , 0.9 ) ;
ezxml_set_attr ( Cur , " upper_thres_pct " , NULL ) ;
meas_params - > slew_lower_thres_pct_rise = GetFloatProperty ( Cur , " lower_thres_pct " , TRUE , 0.1 ) ;
ezxml_set_attr ( Cur , " lower_thres_pct " , NULL ) ;
/* Free */
FreeNode ( Cur ) ;
}
/* Find fall*/
Cur = FindElement ( Node , " fall " , FALSE ) ;
if ( Cur ) {
meas_params - > slew_upper_thres_pct_fall = GetFloatProperty ( Cur , " upper_thres_pct " , TRUE , 0.1 ) ;
ezxml_set_attr ( Cur , " upper_thres_pct " , NULL ) ;
meas_params - > slew_lower_thres_pct_fall = GetFloatProperty ( Cur , " lower_thres_pct " , TRUE , 0.9 ) ;
ezxml_set_attr ( Cur , " lower_thres_pct " , NULL ) ;
/* Free */
FreeNode ( Cur ) ;
}
FreeNode ( Node ) ;
}
/* Process delay parameters*/
Node = FindElement ( Parent , " delay " , FALSE ) ;
if ( Node ) {
/* Find rise*/
Cur = FindElement ( Node , " rise " , FALSE ) ;
if ( Cur ) {
/* Search for properties*/
/* Rise */
meas_params - > input_thres_pct_rise = GetFloatProperty ( Cur , " input_thres_pct " , TRUE , 0.5 ) ;
ezxml_set_attr ( Cur , " input_thres_pct " , NULL ) ;
meas_params - > output_thres_pct_rise = GetFloatProperty ( Cur , " output_thres_pct " , TRUE , 0.5 ) ;
ezxml_set_attr ( Cur , " output_thres_pct " , NULL ) ;
/* Free */
FreeNode ( Cur ) ;
}
/* Find fall*/
Cur = FindElement ( Node , " fall " , FALSE ) ;
if ( Cur ) {
meas_params - > input_thres_pct_fall = GetFloatProperty ( Cur , " input_thres_pct " , TRUE , 0.5 ) ;
ezxml_set_attr ( Cur , " input_thres_pct " , NULL ) ;
meas_params - > output_thres_pct_fall = GetFloatProperty ( Cur , " output_thres_pct " , TRUE , 0.5 ) ;
ezxml_set_attr ( Cur , " output_thres_pct " , NULL ) ;
/* Free */
FreeNode ( Cur ) ;
}
FreeNode ( Node ) ;
}
return ;
}
static void ProcessSpiceStimulateParamsRiseFall ( ezxml_t Parent ,
float * rise_param ,
float * fall_param ,
enum e_spice_accuracy_type * rise_type ,
enum e_spice_accuracy_type * fall_type ) {
ezxml_t Node ;
/* Check */
assert ( NULL ! = rise_param ) ;
assert ( NULL ! = fall_param ) ;
assert ( NULL ! = rise_type ) ;
assert ( NULL ! = fall_type ) ;
/* initial to 0 */
( * rise_param ) = 0. ;
( * fall_param ) = 0. ;
( * rise_type ) = SPICE_FRAC ;
( * fall_type ) = SPICE_FRAC ;
/* Rise parameters */
Node = FindElement ( Parent , " rise " , TRUE ) ;
if ( Node ) {
if ( 0 = = strcmp ( " frac " , FindProperty ( Node , " slew_type " , TRUE ) ) ) {
( * rise_type ) = SPICE_FRAC ;
} else if ( 0 = = strcmp ( " abs " , FindProperty ( Node , " slew_type " , TRUE ) ) ) {
( * rise_type ) = SPICE_ABS ;
} else {
vpr_printf ( TIO_MESSAGE_ERROR , " Property(%s) should be defined in [LINE%d]! \n " ,
" slew_type " , Node - > line ) ;
exit ( 1 ) ;
}
( * rise_param ) = GetFloatProperty ( Node , " slew_time " , TRUE , 0.05 ) ;
ezxml_set_attr ( Node , " slew_time " , NULL ) ;
ezxml_set_attr ( Node , " slew_type " , NULL ) ;
/* Free */
FreeNode ( Node ) ;
}
/* Fall parameters */
Node = FindElement ( Parent , " fall " , TRUE ) ;
if ( Node ) {
if ( 0 = = strcmp ( " frac " , FindProperty ( Node , " slew_type " , TRUE ) ) ) {
( * fall_type ) = SPICE_FRAC ;
} else if ( 0 = = strcmp ( " abs " , FindProperty ( Node , " slew_type " , TRUE ) ) ) {
( * fall_type ) = SPICE_ABS ;
} else {
vpr_printf ( TIO_MESSAGE_ERROR , " Property(%s) should be defined in [LINE%d]! \n " ,
" slew_type " , Node - > line ) ;
exit ( 1 ) ;
}
( * fall_param ) = GetFloatProperty ( Node , " slew_time " , TRUE , 0.05 ) ;
ezxml_set_attr ( Node , " slew_time " , NULL ) ;
ezxml_set_attr ( Node , " slew_type " , NULL ) ;
/* Free */
FreeNode ( Node ) ;
}
return ;
}
static void ProcessSpiceStimulateParams ( ezxml_t Parent ,
t_spice_stimulate_params * stimulate_params ) {
ezxml_t Node ;
/* Check */
if ( stimulate_params = = NULL ) {
vpr_printf ( TIO_MESSAGE_ERROR , " (File: %s,[LINE%d])stimulate_params is NULL! \n " , __FILE__ , __LINE__ ) ;
exit ( 1 ) ;
}
/* Find Clock */
Node = FindElement ( Parent , " clock " , FALSE ) ;
if ( Node ) {
/* op_freq, sim_slack, prog_freq */
stimulate_params - > op_clock_freq = OPEN ;
/* op_freq (operation clock frequency) must be defined, either as a number or as "auto" */
if ( 0 = = strcmp ( " auto " , FindProperty ( Node , " op_freq " , TRUE ) ) ) {
/* We need a sim_slack */
} else {
stimulate_params - > op_clock_freq = GetFloatProperty ( Node , " op_freq " , TRUE , OPEN ) ;
/* We do not need a sim_slack */
}
ezxml_set_attr ( Node , " op_freq " , NULL ) ;
/* Read sim_slack */
stimulate_params - > sim_clock_freq_slack = GetFloatProperty ( Node , " sim_slack " , FALSE , 0.2 ) ;
ezxml_set_attr ( Node , " sim_slack " , NULL ) ;
/* Read prog_freq (programming clock frequency): mandatory! */
stimulate_params - > prog_clock_freq = GetFloatProperty ( Node , " prog_freq " , TRUE , OPEN ) ;
/* For rising/falling slew */
ProcessSpiceStimulateParamsRiseFall ( Node , & ( stimulate_params - > clock_slew_rise_time ) , & ( stimulate_params - > clock_slew_fall_time ) , & ( stimulate_params - > clock_slew_rise_type ) , & ( stimulate_params - > clock_slew_fall_type ) ) ;
/* Free */
FreeNode ( Node ) ;
}
/* Find input */
Node = FindElement ( Parent , " input " , FALSE ) ;
if ( Node ) {
/* Free */
/* For rising/falling slew */
ProcessSpiceStimulateParamsRiseFall ( Node , & ( stimulate_params - > input_slew_rise_time ) , & ( stimulate_params - > input_slew_fall_time ) , & ( stimulate_params - > input_slew_rise_type ) , & ( stimulate_params - > input_slew_fall_type ) ) ;
FreeNode ( Node ) ;
}
return ;
}
static void ProcessSpiceMCVariationParams ( ezxml_t Parent ,
t_spice_mc_variation_params * variation_params ) {
/* Check */
if ( variation_params = = NULL ) {
vpr_printf ( TIO_MESSAGE_ERROR , " (File: %s,[LINE%d])variation_params is NULL! \n " ,
__FILE__ , __LINE__ ) ;
exit ( 1 ) ;
}
variation_params - > abs_variation = GetFloatProperty ( Parent , " abs_variation " , TRUE , 0 ) ;
ezxml_set_attr ( Parent , " abs_variation " , NULL ) ;
variation_params - > num_sigma = GetIntProperty ( Parent , " num_sigma " , TRUE , 1 ) ;
ezxml_set_attr ( Parent , " num_sigma " , NULL ) ;
return ;
}
static void ProcessSpiceMonteCarloParams ( ezxml_t Parent ,
t_spice_mc_params * mc_params ) {
ezxml_t Node ;
/* Check */
if ( mc_params = = NULL ) {
vpr_printf ( TIO_MESSAGE_ERROR , " (File: %s,[LINE%d])mc_params is NULL! \n " ,
__FILE__ , __LINE__ ) ;
exit ( 1 ) ;
}
mc_params - > mc_sim = FALSE ;
if ( 0 = = strcmp ( " on " , FindProperty ( Parent , " mc_sim " , TRUE ) ) ) {
mc_params - > mc_sim = TRUE ;
}
ezxml_set_attr ( Parent , " mc_sim " , NULL ) ;
mc_params - > num_mc_points = GetIntProperty ( Parent , " num_mc_points " , mc_params - > mc_sim , 1 ) ;
ezxml_set_attr ( Parent , " num_mc_points " , NULL ) ;
/* Process CMOS variations */
mc_params - > cmos_variation . variation_on = FALSE ;
if ( NULL = = FindProperty ( Parent , " cmos_variation " , FALSE ) ) {
mc_params - > cmos_variation . variation_on = FALSE ;
} else if ( 0 = = strcmp ( " on " , FindProperty ( Parent , " cmos_variation " , FALSE ) ) ) {
mc_params - > cmos_variation . variation_on = TRUE ;
}
Node = FindElement ( Parent , " cmos " , mc_params - > cmos_variation . variation_on ) ;
if ( Node ) {
ProcessSpiceMCVariationParams ( Node , & ( mc_params - > cmos_variation ) ) ;
FreeNode ( Node ) ;
}
ezxml_set_attr ( Parent , " cmos_variation " , NULL ) ;
mc_params - > rram_variation . variation_on = FALSE ;
if ( NULL = = FindProperty ( Parent , " rram_variation " , FALSE ) ) {
mc_params - > rram_variation . variation_on = FALSE ;
} else if ( 0 = = strcmp ( " on " , FindProperty ( Parent , " rram_variation " , FALSE ) ) ) {
mc_params - > rram_variation . variation_on = TRUE ;
}
Node = FindElement ( Parent , " rram " , mc_params - > rram_variation . variation_on ) ;
if ( Node ) {
ProcessSpiceMCVariationParams ( Node , & ( mc_params - > rram_variation ) ) ;
FreeNode ( Node ) ;
}
ezxml_set_attr ( Parent , " rram_variation " , NULL ) ;
mc_params - > wire_variation . variation_on = FALSE ;
if ( NULL = = FindProperty ( Parent , " wire_variation " , FALSE ) ) {
mc_params - > wire_variation . variation_on = FALSE ;
} else if ( 0 = = strcmp ( " on " , FindProperty ( Parent , " wire_variation " , FALSE ) ) ) {
mc_params - > wire_variation . variation_on = TRUE ;
}
Node = FindElement ( Parent , " wire " , mc_params - > wire_variation . variation_on ) ;
if ( Node ) {
ProcessSpiceMCVariationParams ( Node , & ( mc_params - > wire_variation ) ) ;
FreeNode ( Node ) ;
}
ezxml_set_attr ( Parent , " wire_variation " , NULL ) ;
return ;
}
static void ProcessSpiceParams ( ezxml_t Parent ,
t_spice_params * spice_params ) {
ezxml_t Node ;
InitSpiceParams ( spice_params ) ;
/* Check */
if ( spice_params = = NULL ) {
vpr_printf ( TIO_MESSAGE_ERROR , " (File: %s,[LINE%d])spice_params is NULL! \n " , __FILE__ , __LINE__ ) ;
exit ( 1 ) ;
}
/* Options*/
Node = FindElement ( Parent , " options " , FALSE ) ;
if ( Node ) {
spice_params - > sim_temp = GetIntProperty ( Node , " sim_temp " , TRUE , 25 ) ;
ezxml_set_attr ( Node , " sim_temp " , NULL ) ;
/* OPTION post */
if ( 0 = = strcmp ( " on " , FindProperty ( Node , " post " , TRUE ) ) ) {
spice_params - > post = TRUE ;
} else if ( 0 = = strcmp ( " off " , FindProperty ( Node , " post " , TRUE ) ) ) {
spice_params - > post = FALSE ;
} else {
vpr_printf ( TIO_MESSAGE_INFO , " Invalid value for post(Arch_file, LINE[%d])! \n " , Node - > line ) ;
exit ( 1 ) ;
}
ezxml_set_attr ( Node , " post " , NULL ) ;
/* OPTION captab */
if ( 0 = = strcmp ( " on " , FindProperty ( Node , " captab " , TRUE ) ) ) {
spice_params - > captab = TRUE ;
} else if ( 0 = = strcmp ( " off " , FindProperty ( Node , " captab " , TRUE ) ) ) {
spice_params - > captab = FALSE ;
} else {
vpr_printf ( TIO_MESSAGE_INFO , " Invalid value for captab(Arch_file, LINE[%d])! \n " , Node - > line ) ;
exit ( 1 ) ;
}
ezxml_set_attr ( Node , " captab " , NULL ) ;
/* OPTION fast */
if ( 0 = = strcmp ( " on " , FindProperty ( Node , " fast " , TRUE ) ) ) {
spice_params - > fast = TRUE ;
} else if ( 0 = = strcmp ( " off " , FindProperty ( Node , " fast " , TRUE ) ) ) {
spice_params - > fast = FALSE ;
} else {
vpr_printf ( TIO_MESSAGE_INFO , " Invalid value for fast(Arch_file, LINE[%d])! \n " , Node - > line ) ;
exit ( 1 ) ;
}
ezxml_set_attr ( Node , " fast " , NULL ) ;
/* Free*/
FreeNode ( Node ) ;
}
/* Process Monte Carlo Settings */
Node = FindElement ( Parent , " monte_carlo " , FALSE ) ;
if ( Node ) {
ProcessSpiceMonteCarloParams ( Node , & ( spice_params - > mc_params ) ) ;
FreeNode ( Node ) ;
}
/* Process measure parameters*/
Node = FindElement ( Parent , " measure " , FALSE ) ;
if ( Node ) {
ProcessSpiceMeasParams ( Node , & ( spice_params - > meas_params ) ) ;
FreeNode ( Node ) ;
}
/* Process stimulate parameters*/
Node = FindElement ( Parent , " stimulate " , FALSE ) ;
if ( Node ) {
ProcessSpiceStimulateParams ( Node , & ( spice_params - > stimulate_params ) ) ;
FreeNode ( Node ) ;
}
return ;
}
static void ProcessSpiceTransistorType ( ezxml_t Parent ,
t_spice_transistor_type * spice_trans ,
enum e_spice_trans_type trans_type ) {
if ( spice_trans = = NULL ) {
vpr_printf ( TIO_MESSAGE_ERROR , " ProcessSpiceTransistorType: spice_trans is NULL! \n " ) ;
exit ( 1 ) ;
}
spice_trans - > type = trans_type ;
spice_trans - > model_name = my_strdup ( FindProperty ( Parent , " model_name " , TRUE ) ) ;
ezxml_set_attr ( Parent , " model_name " , NULL ) ;
spice_trans - > chan_length = GetFloatProperty ( Parent , " chan_length " , TRUE , 0 ) ;
ezxml_set_attr ( Parent , " chan_length " , NULL ) ;
spice_trans - > min_width = GetFloatProperty ( Parent , " min_width " , TRUE , 0 ) ;
ezxml_set_attr ( Parent , " min_width " , NULL ) ;
}
static void ProcessSpiceModelBuffer ( ezxml_t Node ,
t_spice_model_buffer * buffer ) {
boolean read_buf_info = FALSE ;
2018-08-01 15:04:28 -05:00
boolean read_spice_model = FALSE ;
2018-07-26 12:28:21 -05:00
char * Prop = NULL ;
/* Be smart to find all the details */
/* Find "exist"*/
Prop = my_strdup ( FindProperty ( Node , " exist " , FALSE ) ) ;
if ( NULL = = Prop ) {
buffer - > exist = 0 ;
} else if ( 0 = = strcmp ( Prop , " on " ) ) {
buffer - > exist = 1 ;
} else if ( 0 = = strcmp ( Prop , " off " ) ) {
buffer - > exist = 0 ;
}
ezxml_set_attr ( Node , " exist " , NULL ) ;
/* If buffer existed, we need to further find the spice_model_name */
if ( 1 = = buffer - > exist ) {
2018-08-01 15:04:28 -05:00
read_buf_info = FALSE ;
read_spice_model = TRUE ;
2018-07-26 12:28:21 -05:00
} else if ( 0 = = strcmp ( " design_technology " , Node - > name ) ) {
/* Only under the design technology Node, this contains buffer information */
read_buf_info = TRUE ;
2018-08-01 15:04:28 -05:00
read_spice_model = FALSE ;
2018-07-26 12:28:21 -05:00
}
2019-07-12 17:18:28 -05:00
buffer - > spice_model_name = my_strdup ( FindProperty ( Node , " circuit_model_name " , read_spice_model ) ) ;
ezxml_set_attr ( Node , " circuit_model_name " , NULL ) ;
2018-08-01 15:04:28 -05:00
2018-07-26 12:28:21 -05:00
/*Find Type*/
Prop = my_strdup ( FindProperty ( Node , " topology " , read_buf_info ) ) ;
if ( NULL ! = Prop ) {
if ( 0 = = strcmp ( Prop , " inverter " ) ) {
buffer - > type = SPICE_MODEL_BUF_INV ;
} else if ( 0 = = strcmp ( Prop , " buffer " ) ) {
buffer - > type = SPICE_MODEL_BUF_BUF ;
} else {
vpr_printf ( TIO_MESSAGE_ERROR , " [LINE %d] Invalid value for type in input_buffer. Should be [inverter|buffer]. \n " ,
Node - > line ) ;
exit ( 1 ) ;
}
}
ezxml_set_attr ( Node , " topology " , NULL ) ;
/*Find Tapered*/
2019-08-21 22:50:26 -05:00
/* Set default values*/
buffer - > tapered_buf = 0 ;
buffer - > tap_buf_level = 2 ;
buffer - > f_per_stage = 4 ;
/* Parse XML */
2018-07-26 12:28:21 -05:00
Prop = my_strdup ( FindProperty ( Node , " tapered " , read_buf_info ) ) ;
if ( NULL ! = Prop ) {
if ( 0 = = strcmp ( Prop , " on " ) ) {
buffer - > tapered_buf = 1 ;
/* Try to dig more properites ...*/
2019-08-21 22:50:26 -05:00
buffer - > tap_buf_level = GetIntProperty ( Node , " tap_drive_level " , TRUE , 2 ) ;
buffer - > f_per_stage = GetIntProperty ( Node , " f_per_stage " , FALSE , 4 ) ;
2019-07-12 17:18:28 -05:00
ezxml_set_attr ( Node , " tap_drive_level " , NULL ) ;
2018-07-26 12:28:21 -05:00
ezxml_set_attr ( Node , " f_per_stage " , NULL ) ;
} else if ( 0 = = strcmp ( FindProperty ( Node , " tapered " , TRUE ) , " off " ) ) {
buffer - > tapered_buf = 0 ;
} else {
vpr_printf ( TIO_MESSAGE_ERROR , " [LINE %d] Invalid value for tapered buffer. Should be [on|off]. \n " ,
Node - > line ) ;
exit ( 1 ) ;
}
}
ezxml_set_attr ( Node , " tapered " , NULL ) ;
/* Find size*/
buffer - > size = GetFloatProperty ( Node , " size " , read_buf_info , 0. ) ;
ezxml_set_attr ( Node , " size " , NULL ) ;
2019-04-26 13:23:47 -05:00
/* Read location map */
buffer - > location_map = my_strdup ( FindProperty ( Node , " location_map " , FALSE ) ) ;
ezxml_set_attr ( Node , " location_map " , NULL ) ;
2018-07-26 12:28:21 -05:00
return ;
}
static void ProcessSpiceModelPassGateLogic ( ezxml_t Node ,
t_spice_model_pass_gate_logic * pass_gate_logic ) {
if ( 0 = = strcmp ( FindProperty ( Node , " topology " , TRUE ) , " transmission_gate " ) ) {
pass_gate_logic - > type = SPICE_MODEL_PASS_GATE_TRANSMISSION ;
} else if ( 0 = = strcmp ( FindProperty ( Node , " topology " , TRUE ) , " pass_transistor " ) ) {
pass_gate_logic - > type = SPICE_MODEL_PASS_GATE_TRANSISTOR ;
} else {
vpr_printf ( TIO_MESSAGE_ERROR , " [LINE %d] Invalid topology of pass_gate_logic. Should be [transmission_gate|pass_transistor]. \n " ,
Node - > line ) ;
exit ( 1 ) ;
}
ezxml_set_attr ( Node , " topology " , NULL ) ;
pass_gate_logic - > nmos_size = GetFloatProperty ( Node , " nmos_size " , TRUE , 0 ) ;
ezxml_set_attr ( Node , " nmos_size " , NULL ) ;
/* If the type of pass_gate_logic is pass transistor,
* the pmos_size is the size of level - restorer at the output node
*/
pass_gate_logic - > pmos_size = GetFloatProperty ( Node , " pmos_size " , TRUE , 0 ) ;
ezxml_set_attr ( Node , " pmos_size " , NULL ) ;
return ;
}
2019-04-26 13:23:47 -05:00
static void ProcessSpiceModelRRAM ( ezxml_t Node ,
t_spice_model_rram * rram_info ) {
rram_info - > ron = GetFloatProperty ( Node , " ron " , TRUE , 0 ) ;
ezxml_set_attr ( Node , " ron " , NULL ) ;
rram_info - > roff = GetFloatProperty ( Node , " roff " , TRUE , 0 ) ;
ezxml_set_attr ( Node , " roff " , NULL ) ;
rram_info - > wprog_set_nmos = GetFloatProperty ( Node , " wprog_set_nmos " , TRUE , 0 ) ;
ezxml_set_attr ( Node , " wprog_set_nmos " , NULL ) ;
rram_info - > wprog_set_pmos = GetFloatProperty ( Node , " wprog_set_pmos " , TRUE , 0 ) ;
ezxml_set_attr ( Node , " wprog_set_nmos " , NULL ) ;
rram_info - > wprog_reset_nmos = GetFloatProperty ( Node , " wprog_reset_nmos " , TRUE , 0 ) ;
ezxml_set_attr ( Node , " wprog_reset_nmos " , NULL ) ;
rram_info - > wprog_reset_pmos = GetFloatProperty ( Node , " wprog_reset_pmos " , TRUE , 0 ) ;
ezxml_set_attr ( Node , " wprog_reset_pmos " , NULL ) ;
return ;
}
static void ProcessSpiceModelMUX ( ezxml_t Node ,
t_spice_model * spice_model ,
t_spice_model_mux * mux_info ) {
/* Default: tree, no const_inputs */
mux_info - > structure = SPICE_MODEL_STRUCTURE_TREE ;
mux_info - > add_const_input = FALSE ;
mux_info - > const_input_val = 0 ;
if ( 0 = = strcmp ( FindProperty ( Node , " structure " , TRUE ) , " tree " ) ) {
mux_info - > structure = SPICE_MODEL_STRUCTURE_TREE ;
} else if ( 0 = = strcmp ( FindProperty ( Node , " structure " , TRUE ) , " one-level " ) ) {
mux_info - > structure = SPICE_MODEL_STRUCTURE_ONELEVEL ;
} else if ( 0 = = strcmp ( FindProperty ( Node , " structure " , TRUE ) , " multi-level " ) ) {
mux_info - > structure = SPICE_MODEL_STRUCTURE_MULTILEVEL ;
/* New Structure: crossbar
} else if ( 0 = = strcmp ( FindProperty ( Node , " structure " , TRUE ) , " crossbar " ) ) {
spice_model - > design_tech_info . structure = SPICE_MODEL_STRUCTURE_CROSSBAR ;
*/
} else {
/* Set default to RRAM MUX */
if ( SPICE_MODEL_DESIGN_RRAM = = spice_model - > design_tech ) {
mux_info - > structure = SPICE_MODEL_STRUCTURE_ONELEVEL ;
} else {
/* Set default to SRAM MUX */
mux_info - > structure = SPICE_MODEL_STRUCTURE_TREE ;
}
}
/* Parse the const inputs */
mux_info - > add_const_input = GetBooleanProperty ( Node , " add_const_input " , FALSE , FALSE ) ;
mux_info - > const_input_val = GetIntProperty ( Node , " const_input_val " , FALSE , 0 ) ;
ezxml_set_attr ( Node , " structure " , NULL ) ;
ezxml_set_attr ( Node , " add_const_input " , NULL ) ;
ezxml_set_attr ( Node , " const_input_val " , NULL ) ;
if ( SPICE_MODEL_STRUCTURE_MULTILEVEL = = mux_info - > structure ) {
mux_info - > mux_num_level = GetIntProperty ( Node , " num_level " , TRUE , 1 ) ;
/* For num_level == 1, auto convert to one-level structure */
if ( 1 = = mux_info - > mux_num_level ) {
mux_info - > structure = SPICE_MODEL_STRUCTURE_ONELEVEL ;
vpr_printf ( TIO_MESSAGE_INFO , " [LINE%d] Automatically convert structure of spice model(%s) to one-level. \n " ,
Node - > line , spice_model - > name ) ;
}
} else if ( SPICE_MODEL_STRUCTURE_ONELEVEL = = mux_info - > structure ) {
/* Set mux_num_level for other structure: one-level and tree */
mux_info - > mux_num_level = 1 ;
}
ezxml_set_attr ( Node , " num_level " , NULL ) ;
/* Specify if should use the advanced 4T1R MUX design */
mux_info - > advanced_rram_design = GetBooleanProperty ( Node , " advanced_rram_design " , FALSE , FALSE ) ;
ezxml_set_attr ( Node , " advanced_rram_design " , NULL ) ;
2019-08-02 17:22:52 -05:00
/* Specify if should use a local encoder for this multiplexer */
mux_info - > local_encoder = GetBooleanProperty ( Node , " local_encoder " , FALSE , FALSE ) ;
ezxml_set_attr ( Node , " local_encoder " , NULL ) ;
2019-04-26 13:23:47 -05:00
return ;
}
static void ProcessSpiceModelLUT ( ezxml_t Node ,
t_spice_model_lut * lut_info ) {
lut_info - > frac_lut = GetBooleanProperty ( Node , " fracturable_lut " , FALSE , FALSE ) ;
return ;
}
static void ProcessSpiceModelGate ( ezxml_t Node ,
t_spice_model_gate * gate_info ) {
if ( 0 = = strcmp ( FindProperty ( Node , " topology " , TRUE ) , " AND " ) ) {
gate_info - > type = SPICE_MODEL_GATE_AND ;
} else if ( 0 = = strcmp ( FindProperty ( Node , " topology " , TRUE ) , " OR " ) ) {
gate_info - > type = SPICE_MODEL_GATE_OR ;
2019-07-17 08:54:23 -05:00
} else if ( 0 = = strcmp ( FindProperty ( Node , " topology " , TRUE ) , " MUX2 " ) ) {
gate_info - > type = SPICE_MODEL_GATE_MUX2 ;
2019-04-26 13:23:47 -05:00
} else {
2019-07-17 08:54:23 -05:00
vpr_printf ( TIO_MESSAGE_ERROR , " [LINE %d] Invalid topology of gates. Should be [AND|OR|MUX2]. \n " ,
2019-04-26 13:23:47 -05:00
Node - > line ) ;
exit ( 1 ) ;
}
ezxml_set_attr ( Node , " topology " , NULL ) ;
return ;
}
static void ProcessSpiceModelPortLutOutputMask ( ezxml_t Node ,
t_spice_model_port * port ) {
const char * Prop = NULL ;
int ipin ;
char * Prop_cpy = NULL ;
char * pch = NULL ;
port - > lut_output_mask = ( int * ) my_malloc ( sizeof ( int ) * port - > size ) ;
Prop = FindProperty ( Node , " lut_output_mask " , FALSE ) ;
if ( NULL = = Prop ) {
/* give a default value */
for ( ipin = 0 ; ipin < port - > size ; ipin + + ) {
port - > lut_output_mask [ ipin ] = ipin ;
}
} else {
/* decode the output_maski, split the string by "," */
ipin = 0 ;
Prop_cpy = my_strdup ( Prop ) ;
pch = strtok ( Prop_cpy , " , " ) ;
while ( NULL ! = pch ) {
port - > lut_output_mask [ ipin ] = my_atoi ( pch ) ;
ipin + + ;
pch = strtok ( NULL , " , " ) ;
}
/* Error out, fail to match the port size*/
if ( ipin ! = port - > size ) {
vpr_printf ( TIO_MESSAGE_ERROR , " [LINE %d] Invalid lut_output_mask(%s): Fail to match the port size (%d). \n " ,
Node - > line , Prop , port - > size ) ;
exit ( 1 ) ;
}
}
ezxml_set_attr ( Node , " lut_output_mask " , NULL ) ;
return ;
}
2018-07-26 12:28:21 -05:00
static void ProcessSpiceModelPort ( ezxml_t Node ,
t_spice_model_port * port ) {
2019-04-26 13:23:47 -05:00
2018-07-26 12:28:21 -05:00
if ( 0 = = strcmp ( FindProperty ( Node , " type " , TRUE ) , " input " ) ) {
port - > type = SPICE_MODEL_PORT_INPUT ;
} else if ( 0 = = strcmp ( FindProperty ( Node , " type " , TRUE ) , " output " ) ) {
port - > type = SPICE_MODEL_PORT_OUTPUT ;
} else if ( 0 = = strcmp ( FindProperty ( Node , " type " , TRUE ) , " clock " ) ) {
port - > type = SPICE_MODEL_PORT_CLOCK ;
} else if ( 0 = = strcmp ( FindProperty ( Node , " type " , TRUE ) , " sram " ) ) {
port - > type = SPICE_MODEL_PORT_SRAM ;
} else if ( 0 = = strcmp ( FindProperty ( Node , " type " , TRUE ) , " bl " ) ) {
port - > type = SPICE_MODEL_PORT_BL ;
} else if ( 0 = = strcmp ( FindProperty ( Node , " type " , TRUE ) , " wl " ) ) {
port - > type = SPICE_MODEL_PORT_WL ;
} else if ( 0 = = strcmp ( FindProperty ( Node , " type " , TRUE ) , " blb " ) ) {
port - > type = SPICE_MODEL_PORT_BLB ;
} else if ( 0 = = strcmp ( FindProperty ( Node , " type " , TRUE ) , " wlb " ) ) {
port - > type = SPICE_MODEL_PORT_WLB ;
} else if ( 0 = = strcmp ( FindProperty ( Node , " type " , TRUE ) , " inout " ) ) {
port - > type = SPICE_MODEL_PORT_INOUT ;
} else {
vpr_printf ( TIO_MESSAGE_ERROR , " [LINE %d] Invalid type of port. Should be [input|output|clock|sram|bl|wl]. \n " ,
Node - > line ) ;
exit ( 1 ) ;
}
ezxml_set_attr ( Node , " type " , NULL ) ;
/* Assign prefix and size*/
2019-04-26 13:23:47 -05:00
port - > prefix = my_strdup ( FindProperty ( Node , " prefix " , TRUE ) ) ;
2018-07-26 12:28:21 -05:00
ezxml_set_attr ( Node , " prefix " , NULL ) ;
2019-04-26 13:23:47 -05:00
/* Assign port name in the std library
* Ff not found , it will be by default the same as prefix */
port - > lib_name = my_strdup ( FindProperty ( Node , " lib_name " , FALSE ) ) ;
ezxml_set_attr ( Node , " lib_name " , NULL ) ;
if ( NULL = = port - > lib_name ) {
port - > lib_name = my_strdup ( port - > prefix ) ;
}
/* Create an inverter prefix to ease the mapping to standard cells */
port - > inv_prefix = my_strdup ( FindProperty ( Node , " inv_prefix " , FALSE ) ) ;
ezxml_set_attr ( Node , " inv_prefix " , NULL ) ;
port - > size = GetIntProperty ( Node , " size " , TRUE , 1 ) ;
2018-07-26 12:28:21 -05:00
ezxml_set_attr ( Node , " size " , NULL ) ;
/* See if this is a mode selector.
* Currently , we only allow a SRAM port to be a mode selector */
if ( SPICE_MODEL_PORT_SRAM = = port - > type ) {
port - > mode_select = GetBooleanProperty ( Node , " mode_select " , FALSE , FALSE ) ;
ezxml_set_attr ( Node , " mode_select " , NULL ) ;
}
/* Assign a default value for a port, which is useful in customizing the SRAM bit of idle LUTs */
port - > default_val = GetIntProperty ( Node , " default_val " , FALSE , 0 ) ;
ezxml_set_attr ( Node , " default_val " , NULL ) ;
2019-04-26 13:23:47 -05:00
/* Tri-state map */
port - > tri_state_map = my_strdup ( FindProperty ( Node , " tri_state_map " , FALSE ) ) ;
ezxml_set_attr ( Node , " tri_state_map " , NULL ) ;
/* fracturable LUT: define at which level the output should be fractured */
port - > lut_frac_level = GetIntProperty ( Node , " lut_frac_level " , FALSE , - 1 ) ;
ezxml_set_attr ( Node , " lut_frac_level " , NULL ) ;
/* Output mast of a fracturable LUT, which is to identify which intermediate LUT output will be connected to outputs */
ProcessSpiceModelPortLutOutputMask ( Node , port ) ;
2018-07-26 12:28:21 -05:00
/* See if this is a global signal
* We assume that global signals are shared by all the SPICE Model / blocks .
* We need to check if other SPICE model has the same port name
*/
port - > is_global = GetBooleanProperty ( Node , " is_global " , FALSE , FALSE ) ;
ezxml_set_attr ( Node , " is_global " , NULL ) ;
/* Check if this port is a set or reset port */
port - > is_reset = GetBooleanProperty ( Node , " is_reset " , FALSE , FALSE ) ;
ezxml_set_attr ( Node , " is_reset " , NULL ) ;
port - > is_set = GetBooleanProperty ( Node , " is_set " , FALSE , FALSE ) ;
ezxml_set_attr ( Node , " is_set " , NULL ) ;
port - > is_prog = GetBooleanProperty ( Node , " is_prog " , FALSE , FALSE ) ;
ezxml_set_attr ( Node , " is_prog " , NULL ) ;
/* Check if this port is a config_done port */
port - > is_config_enable = GetBooleanProperty ( Node , " is_config_enable " , FALSE , FALSE ) ;
ezxml_set_attr ( Node , " is_config_enable " , NULL ) ;
/* Check if this port is linked to another spice_model*/
2019-07-12 17:18:28 -05:00
port - > spice_model_name = my_strdup ( FindProperty ( Node , " circuit_model_name " , FALSE ) ) ;
ezxml_set_attr ( Node , " circuit_model_name " , NULL ) ;
2018-07-26 12:28:21 -05:00
/* For BL/WL, BLB/WLB ports, we need to get the spice_model for inverters */
if ( ( SPICE_MODEL_PORT_BL = = port - > type )
| | ( SPICE_MODEL_PORT_WL = = port - > type )
| | ( SPICE_MODEL_PORT_BLB = = port - > type )
| | ( SPICE_MODEL_PORT_WLB = = port - > type ) ) {
2019-07-12 17:18:28 -05:00
port - > inv_spice_model_name = my_strdup ( FindProperty ( Node , " inv_circuit_model_name " , FALSE ) ) ;
ezxml_set_attr ( Node , " inv_circuit_model_name " , NULL ) ;
2019-08-08 18:25:27 -05:00
} else {
port - > inv_spice_model_name = NULL ;
2018-07-26 12:28:21 -05:00
}
2019-08-02 15:28:35 -05:00
/* Add a feature to enable/disable the configuration encoders for multiplexers */
const char * Prop = FindProperty ( Node , " organization " , FALSE ) ;
if ( NULL = = Prop ) {
port - > organization = SPICE_SRAM_STANDALONE ; /* Default */
} else if ( 0 = = strcmp ( " scan-chain " , Prop ) ) {
port - > organization = SPICE_SRAM_SCAN_CHAIN ;
} else if ( 0 = = strcmp ( " memory-bank " , Prop ) ) {
port - > organization = SPICE_SRAM_MEMORY_BANK ;
} else if ( 0 = = strcmp ( " standalone " , Prop ) ) {
port - > organization = SPICE_SRAM_STANDALONE ;
} else if ( 0 = = strcmp ( " local-encoder " , Prop ) ) {
port - > organization = SPICE_SRAM_LOCAL_ENCODER ;
} else {
vpr_printf ( TIO_MESSAGE_ERROR ,
" [LINE %d] Unknown property %s for SRAM organization \n " ,
Node - > line , FindProperty ( Node , " organization " , FALSE ) ) ;
exit ( 1 ) ;
}
ezxml_set_attr ( Node , " organization " , NULL ) ;
2018-07-26 12:28:21 -05:00
return ;
}
2019-04-26 13:23:47 -05:00
static
void ProcessSpiceModelDelayInfo ( ezxml_t Node ,
t_spice_model_delay_info * cur_delay_info ) {
/* Find the type */
if ( 0 = = strcmp ( FindProperty ( Node , " type " , TRUE ) , " rise " ) ) {
cur_delay_info - > type = SPICE_MODEL_DELAY_RISE ;
} else if ( 0 = = strcmp ( FindProperty ( Node , " type " , TRUE ) , " fall " ) ) {
cur_delay_info - > type = SPICE_MODEL_DELAY_FALL ;
} else {
vpr_printf ( TIO_MESSAGE_ERROR , " [LINE %d] Invalid type of delay_info. Should be [rise|fall]. \n " ,
Node - > line ) ;
exit ( 1 ) ;
}
ezxml_set_attr ( Node , " type " , NULL ) ;
/* Find the input and output ports */
cur_delay_info - > in_port_name = my_strdup ( FindProperty ( Node , " in_port " , TRUE ) ) ;
ezxml_set_attr ( Node , " in_port " , NULL ) ;
cur_delay_info - > out_port_name = my_strdup ( FindProperty ( Node , " out_port " , TRUE ) ) ;
ezxml_set_attr ( Node , " out_port " , NULL ) ;
/* Find delay matrix */
cur_delay_info - > value = my_strdup ( Node - > txt ) ;
ezxml_set_txt ( Node , " " ) ;
return ;
}
2018-12-04 18:32:09 -06:00
2018-07-26 12:28:21 -05:00
static void ProcessSpiceModelWireParam ( ezxml_t Parent ,
t_spice_model_wire_param * wire_param ) {
if ( 0 = = strcmp ( " pie " , FindProperty ( Parent , " model_type " , TRUE ) ) ) {
wire_param - > type = WIRE_MODEL_PIE ;
} else if ( 0 = = strcmp ( " t " , FindProperty ( Parent , " model_type " , TRUE ) ) ) {
wire_param - > type = WIRE_MODEL_T ;
} else {
vpr_printf ( TIO_MESSAGE_ERROR , " [LINE %d] Invalid type of wire model(%s). Should be [pie|t]. \n " ,
Parent - > line , FindProperty ( Parent , " model_type " , TRUE ) ) ;
exit ( 1 ) ;
}
ezxml_set_attr ( Parent , " model_type " , NULL ) ;
wire_param - > res_val = GetFloatProperty ( Parent , " res_val " , TRUE , 0 ) ;
wire_param - > cap_val = GetFloatProperty ( Parent , " cap_val " , TRUE , 0 ) ;
wire_param - > level = GetIntProperty ( Parent , " level " , TRUE , 0 ) ;
ezxml_set_attr ( Parent , " res_val " , NULL ) ;
ezxml_set_attr ( Parent , " cap_val " , NULL ) ;
ezxml_set_attr ( Parent , " level " , NULL ) ;
return ;
}
static void ProcessSpiceModel ( ezxml_t Parent ,
t_spice_model * spice_model ) {
ezxml_t Node , Cur ;
2018-12-04 18:32:09 -06:00
int iport , i ;
2018-07-26 12:28:21 -05:00
/* Basic Information*/
if ( 0 = = strcmp ( FindProperty ( Parent , " type " , TRUE ) , " mux " ) ) {
spice_model - > type = SPICE_MODEL_MUX ;
} else if ( 0 = = strcmp ( FindProperty ( Parent , " type " , TRUE ) , " chan_wire " ) ) {
spice_model - > type = SPICE_MODEL_CHAN_WIRE ;
} else if ( 0 = = strcmp ( FindProperty ( Parent , " type " , TRUE ) , " wire " ) ) {
spice_model - > type = SPICE_MODEL_WIRE ;
} else if ( 0 = = strcmp ( FindProperty ( Parent , " type " , TRUE ) , " lut " ) ) {
spice_model - > type = SPICE_MODEL_LUT ;
} else if ( 0 = = strcmp ( FindProperty ( Parent , " type " , TRUE ) , " ff " ) ) {
spice_model - > type = SPICE_MODEL_FF ;
} else if ( 0 = = strcmp ( FindProperty ( Parent , " type " , TRUE ) , " sram " ) ) {
spice_model - > type = SPICE_MODEL_SRAM ;
} else if ( 0 = = strcmp ( FindProperty ( Parent , " type " , TRUE ) , " hard_logic " ) ) {
spice_model - > type = SPICE_MODEL_HARDLOGIC ;
} else if ( 0 = = strcmp ( FindProperty ( Parent , " type " , TRUE ) , " sff " ) ) {
2019-09-26 12:32:57 -05:00
spice_model - > type = SPICE_MODEL_CCFF ;
2018-07-26 12:28:21 -05:00
} else if ( 0 = = strcmp ( FindProperty ( Parent , " type " , TRUE ) , " iopad " ) ) {
spice_model - > type = SPICE_MODEL_IOPAD ;
} else if ( 0 = = strcmp ( FindProperty ( Parent , " type " , TRUE ) , " inv_buf " ) ) {
spice_model - > type = SPICE_MODEL_INVBUF ;
} else if ( 0 = = strcmp ( FindProperty ( Parent , " type " , TRUE ) , " pass_gate " ) ) {
spice_model - > type = SPICE_MODEL_PASSGATE ;
2019-04-26 13:23:47 -05:00
} else if ( 0 = = strcmp ( FindProperty ( Parent , " type " , TRUE ) , " gate " ) ) {
spice_model - > type = SPICE_MODEL_GATE ;
2018-07-26 12:28:21 -05:00
} else {
2019-04-26 13:23:47 -05:00
vpr_printf ( TIO_MESSAGE_ERROR , " [LINE %d] Invalid type of spice model(%s). Should be [chan_wire|wire|mux|lut|ff|sram|hard_logic|sff|iopad|inv_buf|pass_gate|gate]. \n " ,
2018-07-26 12:28:21 -05:00
Parent - > line , FindProperty ( Parent , " type " , TRUE ) ) ;
exit ( 1 ) ;
}
ezxml_set_attr ( Parent , " type " , NULL ) ;
spice_model - > name = my_strdup ( FindProperty ( Parent , " name " , TRUE ) ) ;
ezxml_set_attr ( Parent , " name " , NULL ) ;
spice_model - > prefix = my_strdup ( FindProperty ( Parent , " prefix " , TRUE ) ) ;
ezxml_set_attr ( Parent , " prefix " , NULL ) ;
/* Find a spice_netlist path if we can*/
spice_model - > model_netlist = my_strdup ( FindProperty ( Parent , " spice_netlist " , FALSE ) ) ;
if ( spice_model - > model_netlist ) {
ezxml_set_attr ( Parent , " spice_netlist " , NULL ) ;
}
/* Find a verilog_netlist path if we can*/
spice_model - > verilog_netlist = my_strdup ( FindProperty ( Parent , " verilog_netlist " , FALSE ) ) ;
if ( spice_model - > verilog_netlist ) {
ezxml_set_attr ( Parent , " verilog_netlist " , NULL ) ;
}
/* Find the is_default if we can*/
spice_model - > is_default = GetIntProperty ( Parent , " is_default " , FALSE , 0 ) ;
ezxml_set_attr ( Parent , " default " , NULL ) ;
/* Find a verilog_netlist path if we can*/
spice_model - > dump_structural_verilog = GetBooleanProperty ( Parent , " dump_structural_verilog " , FALSE , FALSE ) ;
ezxml_set_attr ( Parent , " dump_structural_verilog " , NULL ) ;
2019-04-26 13:23:47 -05:00
/* Find a verilog_netlist path if we can*/
spice_model - > dump_explicit_port_map = GetBooleanProperty ( Parent , " dump_explicit_port_map " , FALSE , FALSE ) ;
ezxml_set_attr ( Parent , " dump_explicit_port_map " , NULL ) ;
2018-07-26 12:28:21 -05:00
/* Check the design technology settings*/
Node = ezxml_child ( Parent , " design_technology " ) ;
2019-08-08 18:25:27 -05:00
/* Initialize */
spice_model - > design_tech_info . buffer_info = NULL ;
spice_model - > design_tech_info . pass_gate_info = NULL ;
spice_model - > design_tech_info . rram_info = NULL ;
spice_model - > design_tech_info . mux_info = NULL ;
spice_model - > design_tech_info . lut_info = NULL ;
spice_model - > design_tech_info . gate_info = NULL ;
2018-07-26 12:28:21 -05:00
if ( Node ) {
/* Specify if this spice_model is power gated or not*/
spice_model - > design_tech_info . power_gated = GetBooleanProperty ( Node , " power_gated " , FALSE , FALSE ) ;
ezxml_set_attr ( Node , " power_gated " , NULL ) ;
/* More options*/
if ( 0 = = strcmp ( FindProperty ( Node , " type " , TRUE ) , " cmos " ) ) {
spice_model - > design_tech = SPICE_MODEL_DESIGN_CMOS ;
/* If this spice model is an inverter, buffer or pass_gate,
* we need to read more settings
*/
spice_model - > design_tech_info . buffer_info = NULL ;
spice_model - > design_tech_info . pass_gate_info = NULL ;
switch ( spice_model - > type ) {
case SPICE_MODEL_INVBUF :
spice_model - > design_tech_info . buffer_info = ( t_spice_model_buffer * ) my_malloc ( sizeof ( t_spice_model_buffer ) ) ;
ProcessSpiceModelBuffer ( Node , spice_model - > design_tech_info . buffer_info ) ;
break ;
case SPICE_MODEL_PASSGATE :
spice_model - > design_tech_info . pass_gate_info = ( t_spice_model_pass_gate_logic * ) my_malloc ( sizeof ( t_spice_model_pass_gate_logic ) ) ;
ProcessSpiceModelPassGateLogic ( Node , spice_model - > design_tech_info . pass_gate_info ) ;
break ;
default :
break ;
}
} else if ( 0 = = strcmp ( FindProperty ( Node , " type " , TRUE ) , " rram " ) ) {
spice_model - > design_tech = SPICE_MODEL_DESIGN_RRAM ;
2019-04-26 13:23:47 -05:00
/* Malloc RRAM info */
2019-08-08 18:25:27 -05:00
spice_model - > design_tech_info . rram_info = ( t_spice_model_rram * ) my_calloc ( 1 , sizeof ( t_spice_model_rram ) ) ;
2019-04-26 13:23:47 -05:00
/* Fill information */
ProcessSpiceModelRRAM ( Node , spice_model - > design_tech_info . rram_info ) ;
2018-07-26 12:28:21 -05:00
} else {
vpr_printf ( TIO_MESSAGE_ERROR , " [LINE %d] Invalid value for design_technology in spice model(%s). Should be [cmos|rram]. \n " ,
Node - > line , spice_model - > name ) ;
exit ( 1 ) ;
}
ezxml_set_attr ( Node , " type " , NULL ) ;
2019-04-26 13:23:47 -05:00
2018-07-26 12:28:21 -05:00
/* Read in the structure if defined */
2019-04-26 13:23:47 -05:00
spice_model - > design_tech_info . mux_info = NULL ;
2018-07-26 12:28:21 -05:00
if ( SPICE_MODEL_MUX = = spice_model - > type ) {
2019-04-26 13:23:47 -05:00
/* Malloc */
2019-08-08 18:25:27 -05:00
spice_model - > design_tech_info . mux_info = ( t_spice_model_mux * ) my_calloc ( 1 , sizeof ( t_spice_model_mux ) ) ;
2019-04-26 13:23:47 -05:00
/* Fill information */
ProcessSpiceModelMUX ( Node , spice_model , spice_model - > design_tech_info . mux_info ) ;
2018-07-26 12:28:21 -05:00
}
2019-04-26 13:23:47 -05:00
/* If this is a LUT, more options are available */
spice_model - > design_tech_info . lut_info = NULL ;
if ( SPICE_MODEL_LUT = = spice_model - > type ) {
/* Malloc */
2019-08-08 18:25:27 -05:00
spice_model - > design_tech_info . lut_info = ( t_spice_model_lut * ) my_calloc ( 1 , sizeof ( t_spice_model_lut ) ) ;
2019-04-26 13:23:47 -05:00
/* Fill information */
ProcessSpiceModelLUT ( Node , spice_model - > design_tech_info . lut_info ) ;
/* Malloc */
2019-08-08 18:25:27 -05:00
spice_model - > design_tech_info . mux_info = ( t_spice_model_mux * ) my_calloc ( 1 , sizeof ( t_spice_model_mux ) ) ;
2019-04-26 13:23:47 -05:00
/* Fill information */
/* Default: tree, no const_inputs */
spice_model - > design_tech_info . mux_info - > structure = SPICE_MODEL_STRUCTURE_TREE ;
spice_model - > design_tech_info . mux_info - > add_const_input = FALSE ;
spice_model - > design_tech_info . mux_info - > const_input_val = 0 ;
2019-08-13 14:25:23 -05:00
spice_model - > design_tech_info . mux_info - > advanced_rram_design = FALSE ;
spice_model - > design_tech_info . mux_info - > local_encoder = FALSE ;
2018-07-26 12:28:21 -05:00
}
2019-04-26 13:23:47 -05:00
ezxml_set_attr ( Node , " fracturable_lut " , NULL ) ;
spice_model - > design_tech_info . gate_info = NULL ;
if ( SPICE_MODEL_GATE = = spice_model - > type ) {
/* Malloc */
spice_model - > design_tech_info . gate_info = ( t_spice_model_gate * ) my_calloc ( 1 , sizeof ( t_spice_model_gate ) ) ;
/* Fill information */
ProcessSpiceModelGate ( Node , spice_model - > design_tech_info . gate_info ) ;
}
2018-07-26 12:28:21 -05:00
} else {
vpr_printf ( TIO_MESSAGE_ERROR , " [LINE %d] design_technology is expected in spice_model(%s). \n " ,
Node - > line , spice_model - > name ) ;
exit ( 1 ) ;
}
2019-04-26 13:23:47 -05:00
FreeNode ( Node ) ;
2018-07-26 12:28:21 -05:00
/* LUT input_buffers */
Node = ezxml_child ( Parent , " lut_input_buffer " ) ;
spice_model - > lut_input_buffer = NULL ;
if ( Node ) {
/* Malloc the lut_input_buffer */
2019-04-26 13:23:47 -05:00
spice_model - > lut_input_buffer = ( t_spice_model_buffer * ) my_calloc ( 1 , sizeof ( t_spice_model_buffer ) ) ;
2018-07-26 12:28:21 -05:00
ProcessSpiceModelBuffer ( Node , spice_model - > lut_input_buffer ) ;
FreeNode ( Node ) ;
} else if ( SPICE_MODEL_LUT = = spice_model - > type ) {
vpr_printf ( TIO_MESSAGE_ERROR , " [LINE %d] lut_input_buffer is expected in spice_model(%s). \n " ,
Parent - > line , spice_model - > name ) ;
exit ( 1 ) ;
}
2019-04-26 13:23:47 -05:00
/* LUT input_buffers */
Node = ezxml_child ( Parent , " lut_input_inverter " ) ;
spice_model - > lut_input_inverter = NULL ;
if ( Node ) {
/* Malloc the lut_input_buffer */
spice_model - > lut_input_inverter = ( t_spice_model_buffer * ) my_calloc ( 1 , sizeof ( t_spice_model_buffer ) ) ;
ProcessSpiceModelBuffer ( Node , spice_model - > lut_input_inverter ) ;
FreeNode ( Node ) ;
} else if ( SPICE_MODEL_LUT = = spice_model - > type ) {
vpr_printf ( TIO_MESSAGE_ERROR , " [LINE %d] lut_input_inverter is expected in spice_model(%s). \n " ,
Parent - > line , spice_model - > name ) ;
exit ( 1 ) ;
}
/* LUT intermediate buffers */
Node = ezxml_child ( Parent , " lut_intermediate_buffer " ) ;
2019-08-13 15:19:40 -05:00
spice_model - > lut_intermediate_buffer = NULL ;
2019-04-26 13:23:47 -05:00
if ( Node ) {
2019-08-13 15:19:40 -05:00
spice_model - > lut_intermediate_buffer = ( t_spice_model_buffer * ) my_calloc ( 1 , sizeof ( t_spice_model_buffer ) ) ;
2019-04-26 13:23:47 -05:00
/* Malloc the lut_input_buffer */
ProcessSpiceModelBuffer ( Node , spice_model - > lut_intermediate_buffer ) ;
FreeNode ( Node ) ;
} else if ( ( SPICE_MODEL_LUT = = spice_model - > type )
| | ( SPICE_MODEL_MUX = = spice_model - > type ) ) {
2019-08-13 15:19:40 -05:00
spice_model - > lut_intermediate_buffer = ( t_spice_model_buffer * ) my_calloc ( 1 , sizeof ( t_spice_model_buffer ) ) ;
2019-04-26 13:23:47 -05:00
/* Assign default values */
spice_model - > lut_intermediate_buffer - > exist = 0 ;
spice_model - > lut_intermediate_buffer - > spice_model = NULL ;
spice_model - > lut_intermediate_buffer - > location_map = NULL ;
}
2018-07-26 12:28:21 -05:00
/* Input Buffers*/
Node = ezxml_child ( Parent , " input_buffer " ) ;
spice_model - > input_buffer = NULL ;
if ( Node ) {
/*Alloc*/
2019-08-08 18:25:27 -05:00
spice_model - > input_buffer = ( t_spice_model_buffer * ) my_calloc ( 1 , sizeof ( t_spice_model_buffer ) ) ;
2018-07-26 12:28:21 -05:00
ProcessSpiceModelBuffer ( Node , spice_model - > input_buffer ) ;
FreeNode ( Node ) ;
} else if ( SPICE_MODEL_INVBUF ! = spice_model - > type ) {
vpr_printf ( TIO_MESSAGE_ERROR , " [LINE %d] input_buffer is expected in spice_model(%s). \n " ,
Parent - > line , spice_model - > name ) ;
exit ( 1 ) ;
}
/* Output Buffers*/
Node = ezxml_child ( Parent , " output_buffer " ) ;
spice_model - > output_buffer = NULL ;
if ( Node ) {
2019-08-08 18:25:27 -05:00
spice_model - > output_buffer = ( t_spice_model_buffer * ) my_calloc ( 1 , sizeof ( t_spice_model_buffer ) ) ;
2018-07-26 12:28:21 -05:00
ProcessSpiceModelBuffer ( Node , spice_model - > output_buffer ) ;
FreeNode ( Node ) ;
} else if ( SPICE_MODEL_INVBUF ! = spice_model - > type ) {
vpr_printf ( TIO_MESSAGE_ERROR , " [LINE %d] output_buffer is expected in spice_model(%s). \n " ,
Parent - > line , spice_model - > name ) ;
exit ( 1 ) ;
}
/* Pass_gate_logic*/
Node = ezxml_child ( Parent , " pass_gate_logic " ) ;
spice_model - > pass_gate_logic = NULL ;
if ( Node ) {
2019-08-08 18:25:27 -05:00
spice_model - > pass_gate_logic = ( t_spice_model_pass_gate_logic * ) my_calloc ( 1 , sizeof ( t_spice_model_pass_gate_logic ) ) ;
2018-07-26 12:28:21 -05:00
/* Find spice_model_name */
2019-07-12 17:18:28 -05:00
spice_model - > pass_gate_logic - > spice_model_name = my_strdup ( FindProperty ( Node , " circuit_model_name " , TRUE ) ) ;
ezxml_set_attr ( Node , " circuit_model_name " , NULL ) ;
2018-07-26 12:28:21 -05:00
FreeNode ( Node ) ;
} else if ( ( SPICE_MODEL_MUX = = spice_model - > type )
| | ( SPICE_MODEL_LUT = = spice_model - > type ) ) {
/* We have some exceptions: VDD, GND, dff, sram and hard_logic*/
vpr_printf ( TIO_MESSAGE_ERROR , " [LINE %d] pass_gate_logic is expected in spice_model(%s). \n " ,
Node - > line , spice_model - > name ) ;
exit ( 1 ) ;
}
/* Find All the ports*/
spice_model - > num_port = CountChildren ( Parent , " port " , 1 ) ;
/*Alloc*/
2019-08-08 18:25:27 -05:00
spice_model - > ports = ( t_spice_model_port * ) my_calloc ( spice_model - > num_port , sizeof ( t_spice_model_port ) ) ;
2018-07-26 12:28:21 -05:00
/* Assign each found spice model*/
for ( iport = 0 ; iport < spice_model - > num_port ; iport + + ) {
Cur = FindFirstElement ( Parent , " port " , TRUE ) ;
ProcessSpiceModelPort ( Cur , & ( spice_model - > ports [ iport ] ) ) ;
FreeNode ( Cur ) ;
}
/* Read in wire parameters */
2019-08-08 18:25:27 -05:00
spice_model - > wire_param = NULL ;
2018-07-26 12:28:21 -05:00
if ( ( SPICE_MODEL_CHAN_WIRE = = spice_model - > type ) | | ( SPICE_MODEL_WIRE = = spice_model - > type ) ) {
2019-08-08 18:25:27 -05:00
spice_model - > wire_param = ( t_spice_model_wire_param * ) my_calloc ( 1 , sizeof ( t_spice_model_wire_param ) ) ;
2018-07-26 12:28:21 -05:00
Node = ezxml_child ( Parent , " wire_param " ) ;
if ( Node ) {
ProcessSpiceModelWireParam ( Node , spice_model - > wire_param ) ;
} else {
vpr_printf ( TIO_MESSAGE_ERROR , " [LINE %d] wire_param is expected in spice_model(%s). \n " ,
Node - > line , spice_model - > name ) ;
exit ( 1 ) ;
}
FreeNode ( Node ) ;
}
2019-04-26 13:23:47 -05:00
/* Find delay info */
spice_model - > num_delay_info = CountChildren ( Parent , " delay_matrix " , 0 ) ;
/*Alloc*/
2019-08-08 18:25:27 -05:00
spice_model - > delay_info = ( t_spice_model_delay_info * ) my_calloc ( spice_model - > num_delay_info , sizeof ( t_spice_model_delay_info ) ) ;
2019-04-26 13:23:47 -05:00
/* Assign each found spice model*/
for ( i = 0 ; i < spice_model - > num_delay_info ; i + + ) {
Cur = FindFirstElement ( Parent , " delay_matrix " , TRUE ) ;
ProcessSpiceModelDelayInfo ( Cur , & ( spice_model - > delay_info [ i ] ) ) ;
FreeNode ( Cur ) ;
}
2018-12-04 18:32:09 -06:00
2018-07-26 12:28:21 -05:00
/* Initialize the counter*/
spice_model - > cnt = 0 ;
return ;
}
/* Read XML under the Node of Organization */
static
void ProcessSpiceSRAMOrganization ( INOUTP ezxml_t Node ,
OUTP t_sram_inf_orgz * cur_sram_inf_orgz ,
boolean required ) {
const char * Prop ;
if ( NULL = = Node ) {
return ;
}
2019-07-12 17:18:28 -05:00
cur_sram_inf_orgz - > spice_model_name = my_strdup ( FindProperty ( Node , " circuit_model_name " , required ) ) ;
2018-07-26 12:28:21 -05:00
cur_sram_inf_orgz - > spice_model = NULL ;
2019-07-12 17:18:28 -05:00
ezxml_set_attr ( Node , " circuit_model_name " , NULL ) ;
2018-07-26 12:28:21 -05:00
/* read organization type*/
Prop = FindProperty ( Node , " organization " , required ) ;
if ( NULL = = Prop ) {
cur_sram_inf_orgz - > type = SPICE_SRAM_STANDALONE ; /* Default */
} else if ( 0 = = strcmp ( " scan-chain " , Prop ) ) {
cur_sram_inf_orgz - > type = SPICE_SRAM_SCAN_CHAIN ;
2019-04-26 13:23:47 -05:00
} else if ( 0 = = strcmp ( " memory-bank " , Prop ) ) {
2018-07-26 12:28:21 -05:00
cur_sram_inf_orgz - > type = SPICE_SRAM_MEMORY_BANK ;
} else if ( 0 = = strcmp ( " standalone " , Prop ) ) {
cur_sram_inf_orgz - > type = SPICE_SRAM_STANDALONE ;
} else {
vpr_printf ( TIO_MESSAGE_ERROR ,
" [LINE %d] Unknown property %s for SRAM organization \n " ,
Node - > line , FindProperty ( Node , " organization " , required ) ) ;
exit ( 1 ) ;
}
ezxml_set_attr ( Node , " organization " , NULL ) ;
return ;
}
/* Read XML under the Node of SRAM */
void ProcessSpiceSRAM ( INOUTP ezxml_t Node , OUTP struct s_arch * arch ) {
ezxml_t Cur ;
/* Process area */
if ( NULL = = Node ) {
return ;
}
arch - > sram_inf . area = GetFloatProperty ( Node , " area " , FALSE , 6 ) ;
/* Read the SPICE sram organization details */
Cur = FindElement ( Node , " spice " , arch - > read_xml_spice ) ;
if ( NULL ! = Cur ) {
/* Malloc */
arch - > sram_inf . spice_sram_inf_orgz = ( t_sram_inf_orgz * ) my_malloc ( sizeof ( t_sram_inf_orgz ) ) ;
ProcessSpiceSRAMOrganization ( Cur , arch - > sram_inf . spice_sram_inf_orgz , arch - > read_xml_spice ) ;
FreeNode ( Cur ) ;
} else {
arch - > sram_inf . spice_sram_inf_orgz = NULL ;
}
/* Read the SPICE sram organization details */
Cur = FindElement ( Node , " verilog " , arch - > read_xml_spice ) ;
if ( NULL ! = Cur ) {
/* Malloc */
arch - > sram_inf . verilog_sram_inf_orgz = ( t_sram_inf_orgz * ) my_malloc ( sizeof ( t_sram_inf_orgz ) ) ;
ProcessSpiceSRAMOrganization ( Cur , arch - > sram_inf . verilog_sram_inf_orgz , arch - > read_xml_spice ) ;
FreeNode ( Cur ) ;
} else {
arch - > sram_inf . verilog_sram_inf_orgz = NULL ;
}
return ;
}
/* Check Codes: We should check if we need to define the I/O transistors */
static void check_tech_lib ( t_spice_tech_lib tech_lib ,
int num_spice_model ,
t_spice_model * spice_models ) {
int i ;
int rram_mux_found = 0 ;
int io_nmos_found = 0 ;
int io_pmos_found = 0 ;
for ( i = 0 ; i < num_spice_model ; i + + ) {
if ( ( SPICE_MODEL_MUX = = spice_models [ i ] . type )
& & ( SPICE_MODEL_DESIGN_RRAM = = spice_models [ i ] . design_tech ) ) {
rram_mux_found = 1 ;
break ;
}
}
/* RRAM MUX is not defined, no need to check the tech library*/
if ( 0 = = rram_mux_found ) {
return ;
}
/* RRAM MUX is defined, check the tech library by searching for io_nmos and io_pmos */
for ( i = 0 ; i < tech_lib . num_transistor_type ; i + + ) {
if ( SPICE_TRANS_IO_NMOS = = tech_lib . transistor_types [ i ] . type ) {
io_nmos_found = 1 ;
}
if ( SPICE_TRANS_IO_PMOS = = tech_lib . transistor_types [ i ] . type ) {
io_pmos_found = 1 ;
}
}
if ( ( 0 = = io_nmos_found ) | | ( 0 = = io_pmos_found ) ) {
vpr_printf ( TIO_MESSAGE_ERROR , " (File:%s,[LINE%d]) I/O transistors are not defined for RRAM MUX! \n Check your tech_lib! \n " ,
__FILE__ , __LINE__ ) ;
exit ( 1 ) ;
}
return ;
}
/* Check Codes: We should check the spice models */
static void check_spice_models ( int num_spice_model ,
t_spice_model * spice_models ) {
int i , j ;
int has_sram = 0 ;
int has_io = 0 ;
int has_mux = 0 ;
int has_in_port = 0 ;
int has_out_port = 0 ;
int has_clock_port = 0 ;
int has_sram_port = 0 ;
for ( i = 0 ; i < num_spice_model ; i + + ) {
/* Check whether spice models share the same name or prefix*/
for ( j = 0 ; j < num_spice_model ; j + + ) {
if ( i = = j ) {
continue ;
}
if ( 0 = = strcmp ( spice_models [ i ] . prefix , spice_models [ j ] . prefix ) ) {
vpr_printf ( TIO_MESSAGE_ERROR , " Spice model(%s) and (%s) share the same prefix(%s), which is invalid! \n " ,
spice_models [ i ] . name , spice_models [ j ] . name , spice_models [ i ] . prefix ) ;
exit ( 1 ) ;
}
if ( 0 = = strcmp ( spice_models [ i ] . name , spice_models [ j ] . name ) ) {
vpr_printf ( TIO_MESSAGE_ERROR , " Spice model(%s) and (%s) share the same name(%s), which is invalid! \n " ,
spice_models [ i ] . name , spice_models [ j ] . name , spice_models [ i ] . name ) ;
exit ( 1 ) ;
}
}
/* Check io has been defined and has input and output ports*/
if ( SPICE_MODEL_IOPAD = = spice_models [ i ] . type ) {
has_io = 1 ;
has_in_port = 0 ;
has_out_port = 0 ;
for ( j = 0 ; j < spice_models [ i ] . num_port ; j + + ) {
if ( SPICE_MODEL_PORT_INPUT = = spice_models [ i ] . ports [ j ] . type ) {
has_in_port = 1 ;
} else if ( SPICE_MODEL_PORT_OUTPUT = = spice_models [ i ] . ports [ j ] . type ) {
has_out_port = 1 ;
}
}
/* Check if we have two ports*/
if ( ( 0 = = has_in_port ) | | ( 0 = = has_out_port ) ) {
vpr_printf ( TIO_MESSAGE_ERROR , " IO Spice model(%s) does not have input|output port \n " , spice_models [ i ] . name ) ;
exit ( 1 ) ;
}
}
/* Check mux has been defined and has input and output ports*/
if ( SPICE_MODEL_MUX = = spice_models [ i ] . type ) {
has_mux = 1 ;
has_in_port = 0 ;
has_out_port = 0 ;
has_sram_port = 0 ;
for ( j = 0 ; j < spice_models [ i ] . num_port ; j + + ) {
if ( SPICE_MODEL_PORT_INPUT = = spice_models [ i ] . ports [ j ] . type ) {
has_in_port = 1 ;
} else if ( SPICE_MODEL_PORT_OUTPUT = = spice_models [ i ] . ports [ j ] . type ) {
has_out_port = 1 ;
} else if ( SPICE_MODEL_PORT_SRAM = = spice_models [ i ] . ports [ j ] . type ) {
has_sram_port = 1 ;
}
}
/* Check if we have two ports*/
if ( ( 0 = = has_in_port ) | | ( 0 = = has_out_port ) | | ( 0 = = has_sram_port ) ) {
vpr_printf ( TIO_MESSAGE_ERROR , " MUX Spice model(%s) does not have input|output|sram port \n " , spice_models [ i ] . name ) ;
exit ( 1 ) ;
}
/* Check the I/O transistors are defined when RRAM MUX is selected */
if ( SPICE_MODEL_DESIGN_RRAM = = spice_models [ i ] . design_tech ) {
2019-04-26 13:23:47 -05:00
if ( ! ( 0. < spice_models [ i ] . design_tech_info . rram_info - > wprog_set_nmos ) ) {
2018-07-26 12:28:21 -05:00
vpr_printf ( TIO_MESSAGE_ERROR , " wprog_set_nmos(%g) should be >0 for a RRAM MUX SPICE model (%s)! \n " ,
2019-04-26 13:23:47 -05:00
spice_models [ i ] . design_tech_info . rram_info - > wprog_set_nmos , spice_models [ i ] . name ) ;
2018-07-26 12:28:21 -05:00
exit ( 1 ) ;
}
2019-04-26 13:23:47 -05:00
if ( ! ( 0. < spice_models [ i ] . design_tech_info . rram_info - > wprog_set_pmos ) ) {
2018-07-26 12:28:21 -05:00
vpr_printf ( TIO_MESSAGE_ERROR , " wprog_set_pmos(%g) should be >0 for a RRAM MUX SPICE model (%s)! \n " ,
2019-04-26 13:23:47 -05:00
spice_models [ i ] . design_tech_info . rram_info - > wprog_set_pmos , spice_models [ i ] . name ) ;
2018-07-26 12:28:21 -05:00
exit ( 1 ) ;
}
2019-04-26 13:23:47 -05:00
if ( ! ( 0. < spice_models [ i ] . design_tech_info . rram_info - > wprog_reset_nmos ) ) {
2018-07-26 12:28:21 -05:00
vpr_printf ( TIO_MESSAGE_ERROR , " wprog_reset_nmos(%g) should be >0 for a RRAM MUX SPICE model (%s)! \n " ,
2019-04-26 13:23:47 -05:00
spice_models [ i ] . design_tech_info . rram_info - > wprog_reset_nmos , spice_models [ i ] . name ) ;
2018-07-26 12:28:21 -05:00
exit ( 1 ) ;
}
2019-04-26 13:23:47 -05:00
if ( ! ( 0. < spice_models [ i ] . design_tech_info . rram_info - > wprog_reset_pmos ) ) {
2018-07-26 12:28:21 -05:00
vpr_printf ( TIO_MESSAGE_ERROR , " wprog_reset_pmos(%g) should be >0 for a RRAM MUX SPICE model (%s)! \n " ,
2019-04-26 13:23:47 -05:00
spice_models [ i ] . design_tech_info . rram_info - > wprog_reset_pmos , spice_models [ i ] . name ) ;
2018-07-26 12:28:21 -05:00
exit ( 1 ) ;
}
}
}
/* Check sram has been defined and has input and output ports*/
if ( SPICE_MODEL_SRAM = = spice_models [ i ] . type ) {
has_sram = 1 ;
has_out_port = 0 ;
for ( j = 0 ; j < spice_models [ i ] . num_port ; j + + ) {
2019-06-10 16:29:44 -05:00
if ( SPICE_MODEL_PORT_OUTPUT = = spice_models [ i ] . ports [ j ] . type ) {
2018-07-26 12:28:21 -05:00
has_out_port = 1 ;
}
}
/* Check if we have two ports*/
2019-06-10 16:29:44 -05:00
if ( 0 = = has_out_port ) {
vpr_printf ( TIO_MESSAGE_ERROR , " SRAM Spice model(%s) does not have output port \n " , spice_models [ i ] . name ) ;
2018-07-26 12:28:21 -05:00
exit ( 1 ) ;
}
}
/* Check dff has input and output, clock ports*/
if ( SPICE_MODEL_FF = = spice_models [ i ] . type ) {
has_clock_port = 0 ;
has_in_port = 0 ;
has_out_port = 0 ;
for ( j = 0 ; j < spice_models [ i ] . num_port ; j + + ) {
if ( SPICE_MODEL_PORT_INPUT = = spice_models [ i ] . ports [ j ] . type ) {
has_in_port = 1 ;
} else if ( SPICE_MODEL_PORT_OUTPUT = = spice_models [ i ] . ports [ j ] . type ) {
has_out_port = 1 ;
} else if ( SPICE_MODEL_PORT_CLOCK = = spice_models [ i ] . ports [ j ] . type ) {
has_clock_port = 1 ;
}
}
/* Check if we have two ports*/
if ( ( 0 = = has_in_port ) | | ( 0 = = has_out_port ) | | ( 0 = = has_clock_port ) ) {
vpr_printf ( TIO_MESSAGE_ERROR , " FF Spice model(%s) does not have input|output|clock port \n " , spice_models [ i ] . name ) ;
exit ( 1 ) ;
}
}
2019-04-26 13:23:47 -05:00
/* Check scan-chain dff has input and output, clock ports*/
2019-09-26 12:32:57 -05:00
if ( SPICE_MODEL_CCFF = = spice_models [ i ] . type ) {
2019-04-26 13:23:47 -05:00
has_sram = 1 ;
has_clock_port = 0 ;
has_in_port = 0 ;
has_out_port = 0 ;
for ( j = 0 ; j < spice_models [ i ] . num_port ; j + + ) {
if ( SPICE_MODEL_PORT_INPUT = = spice_models [ i ] . ports [ j ] . type ) {
has_in_port = 1 ;
} else if ( SPICE_MODEL_PORT_OUTPUT = = spice_models [ i ] . ports [ j ] . type ) {
has_out_port = 1 ;
} else if ( SPICE_MODEL_PORT_CLOCK = = spice_models [ i ] . ports [ j ] . type ) {
has_clock_port = 1 ;
}
}
/* Check if we have two ports*/
if ( ( 0 = = has_in_port ) | | ( 0 = = has_out_port ) | | ( 0 = = has_clock_port ) ) {
vpr_printf ( TIO_MESSAGE_ERROR , " FF Spice model(%s) does not have input|output|clock port \n " , spice_models [ i ] . name ) ;
exit ( 1 ) ;
}
}
2018-07-26 12:28:21 -05:00
/* Check lut has input and output, clock ports*/
if ( SPICE_MODEL_LUT = = spice_models [ i ] . type ) {
has_sram_port = 0 ;
has_in_port = 0 ;
has_out_port = 0 ;
for ( j = 0 ; j < spice_models [ i ] . num_port ; j + + ) {
if ( SPICE_MODEL_PORT_INPUT = = spice_models [ i ] . ports [ j ] . type ) {
has_in_port = 1 ;
} else if ( SPICE_MODEL_PORT_OUTPUT = = spice_models [ i ] . ports [ j ] . type ) {
has_out_port = 1 ;
} else if ( SPICE_MODEL_PORT_SRAM = = spice_models [ i ] . ports [ j ] . type ) {
has_sram_port = 1 ;
}
}
/* Check if we have two ports*/
if ( ( 0 = = has_in_port ) | | ( 0 = = has_out_port ) | | ( 0 = = has_sram_port ) ) {
vpr_printf ( TIO_MESSAGE_ERROR , " LUT Spice model(%s) does not have input|output|sram port \n " , spice_models [ i ] . name ) ;
exit ( 1 ) ;
}
}
}
if ( ( 0 = = has_io ) | | ( 0 = = has_sram ) | | ( 0 = = has_mux ) ) {
vpr_printf ( TIO_MESSAGE_ERROR , " At least 1 io,sram,mux spice model should be defined! \n " ) ;
exit ( 1 ) ;
}
return ;
}
static void ProcessSpiceTechLibTransistors ( ezxml_t Parent ,
t_spice_tech_lib * spice_tech_lib ) {
ezxml_t Node , Cur ;
int itrans ;
/* TODO: move to a function for this */
/* Check the tech_lib*/
Node = FindElement ( Parent , " tech_lib " , TRUE ) ;
if ( Node ) {
/* Check the type first*/
if ( 0 = = strcmp ( " academia " , FindProperty ( Node , " lib_type " , TRUE ) ) ) {
spice_tech_lib - > type = SPICE_LIB_ACADEMIA ;
} else if ( 0 = = strcmp ( " industry " , FindProperty ( Node , " lib_type " , TRUE ) ) ) {
spice_tech_lib - > type = SPICE_LIB_INDUSTRY ;
} else {
vpr_printf ( TIO_MESSAGE_ERROR , " [LINE %d] tech_lib type should be [industry|academia]. \n " ,
Node - > line ) ;
exit ( 1 ) ;
}
ezxml_set_attr ( Node , " lib_type " , NULL ) ;
if ( SPICE_LIB_INDUSTRY = = spice_tech_lib - > type ) {
spice_tech_lib - > transistor_type = my_strdup ( FindProperty ( Node , " transistor_type " , TRUE ) ) ;
}
ezxml_set_attr ( Node , " transistor_type " , NULL ) ;
spice_tech_lib - > path = my_strdup ( FindProperty ( Node , " lib_path " , TRUE ) ) ;
ezxml_set_attr ( Node , " lib_path " , NULL ) ;
/* Norminal VDD for standard transistors*/
spice_tech_lib - > nominal_vdd = GetFloatProperty ( Node , " nominal_vdd " , TRUE , 0. ) ;
ezxml_set_attr ( Node , " nominal_vdd " , NULL ) ;
/* Norminal VDD for IO transistors : by default, give the value of nominal vdd */
spice_tech_lib - > io_vdd = GetFloatProperty ( Node , " io_vdd " , FALSE , spice_tech_lib - > nominal_vdd ) ;
ezxml_set_attr ( Node , " io_vdd " , NULL ) ;
/* Current Node search ends*/
FreeNode ( Node ) ;
} else {
vpr_printf ( TIO_MESSAGE_ERROR , " [LINE %d] tech_lib does not exist in spice_settings. \n " ,
Node - > line ) ;
exit ( 1 ) ;
}
/* Check the transistors*/
Node = FindElement ( Parent , " transistors " , TRUE ) ;
if ( Node ) {
spice_tech_lib - > pn_ratio = GetFloatProperty ( Node , " pn_ratio " , TRUE , 0 ) ;
spice_tech_lib - > model_ref = my_strdup ( FindProperty ( Node , " model_ref " , TRUE ) ) ;
ezxml_set_attr ( Node , " pn_ratio " , NULL ) ;
ezxml_set_attr ( Node , " model_ref " , NULL ) ;
/* Fill transistor_type number*/
spice_tech_lib - > num_transistor_type = 0 ;
spice_tech_lib - > num_transistor_type + = CountChildren ( Node , " nmos " , 1 ) ;
assert ( 1 = = spice_tech_lib - > num_transistor_type ) ;
spice_tech_lib - > num_transistor_type + = CountChildren ( Node , " pmos " , 1 ) ;
assert ( 2 = = spice_tech_lib - > num_transistor_type ) ;
spice_tech_lib - > num_transistor_type + = CountChildren ( Node , " io_nmos " , 0 ) ;
spice_tech_lib - > num_transistor_type + = CountChildren ( Node , " io_pmos " , 0 ) ;
assert ( ( 2 = = spice_tech_lib - > num_transistor_type ) | | ( 4 = = spice_tech_lib - > num_transistor_type ) ) ;
/*Alloc*/
spice_tech_lib - > transistor_types = ( t_spice_transistor_type * ) my_malloc ( spice_tech_lib - > num_transistor_type * sizeof ( t_spice_transistor_type ) ) ;
/* Fill Standard NMOS */
itrans = 0 ;
Cur = FindFirstElement ( Node , " nmos " , TRUE ) ;
ProcessSpiceTransistorType ( Cur , & ( spice_tech_lib - > transistor_types [ itrans ] ) , SPICE_TRANS_NMOS ) ;
FreeNode ( Cur ) ;
itrans + + ;
/* Fill Standard PMOS */
Cur = FindFirstElement ( Node , " pmos " , TRUE ) ;
ProcessSpiceTransistorType ( Cur , & ( spice_tech_lib - > transistor_types [ itrans ] ) , SPICE_TRANS_PMOS ) ;
FreeNode ( Cur ) ;
itrans + + ;
/* Standard NMOS and PMOS are mandatory */
assert ( 2 = = itrans ) ;
/* Fill IO NMOS */
Cur = FindFirstElement ( Node , " io_nmos " , FALSE ) ;
if ( NULL ! = Cur ) {
ProcessSpiceTransistorType ( Cur , & ( spice_tech_lib - > transistor_types [ itrans ] ) , SPICE_TRANS_IO_NMOS ) ;
FreeNode ( Cur ) ;
itrans + + ;
vpr_printf ( TIO_MESSAGE_INFO , " Read I/O NMOS into tech. lib. successfully. \n " ) ;
}
/* Fill IO PMOS */
Cur = FindFirstElement ( Node , " io_pmos " , FALSE ) ;
if ( NULL ! = Cur ) {
ProcessSpiceTransistorType ( Cur , & ( spice_tech_lib - > transistor_types [ itrans ] ) , SPICE_TRANS_IO_PMOS ) ;
FreeNode ( Cur ) ;
itrans + + ;
vpr_printf ( TIO_MESSAGE_INFO , " Read I/O PMOS into tech. lib. successfully. \n " ) ;
}
assert ( ( 2 = = itrans ) | | ( 4 = = itrans ) ) ;
/* Finish parsing this node*/
FreeNode ( Node ) ;
}
return ;
}
2019-08-08 18:25:27 -05:00
/* Build a circuit library based on the spice_models
* This function does a quick conversion , so that we can proceed to update the downstream codes
* TODO : The circuit library should be incrementally built during XML parsing
* when the downstream is updated , the legacy spice_models will be removed
*/
static
CircuitLibrary build_circuit_library ( int num_spice_model , t_spice_model * spice_models ) {
CircuitLibrary circuit_lib ;
/* Go spice_model by spice_model */
for ( int imodel = 0 ; imodel < num_spice_model ; + + imodel ) {
/* Add a spice model to the circuit_lib */
2019-08-20 16:14:28 -05:00
CircuitModelId model_id = circuit_lib . add_model ( spice_models [ imodel ] . type ) ;
2019-08-08 18:25:27 -05:00
/* Fill fundamental attributes */
/* Basic information*/
std : : string name ( spice_models [ imodel ] . name ) ;
2019-08-19 21:43:35 -05:00
circuit_lib . set_model_name ( model_id , name ) ;
2019-08-08 18:25:27 -05:00
std : : string prefix ( spice_models [ imodel ] . prefix ) ;
2019-08-19 21:43:35 -05:00
circuit_lib . set_model_prefix ( model_id , prefix ) ;
2019-08-08 18:25:27 -05:00
if ( NULL ! = spice_models [ imodel ] . verilog_netlist ) {
std : : string verilog_netlist ( spice_models [ imodel ] . verilog_netlist ) ;
2019-08-19 21:43:35 -05:00
circuit_lib . set_model_verilog_netlist ( model_id , verilog_netlist ) ;
2019-08-08 18:25:27 -05:00
}
if ( NULL ! = spice_models [ imodel ] . model_netlist ) {
std : : string spice_netlist ( spice_models [ imodel ] . model_netlist ) ;
2019-08-19 21:43:35 -05:00
circuit_lib . set_model_spice_netlist ( model_id , spice_netlist ) ;
2019-08-08 18:25:27 -05:00
}
2019-08-19 21:43:35 -05:00
circuit_lib . set_model_is_default ( model_id , 0 ! = spice_models [ imodel ] . is_default ) ;
2019-08-08 18:25:27 -05:00
/* Verilog generatioin options */
2019-08-19 21:43:35 -05:00
circuit_lib . set_model_dump_structural_verilog ( model_id , TRUE = = spice_models [ imodel ] . dump_structural_verilog ) ;
2019-08-08 18:25:27 -05:00
2019-08-19 21:43:35 -05:00
circuit_lib . set_model_dump_explicit_port_map ( model_id , TRUE = = spice_models [ imodel ] . dump_explicit_port_map ) ;
2019-08-08 18:25:27 -05:00
/* Design technology information */
2019-08-19 21:43:35 -05:00
circuit_lib . set_model_design_tech_type ( model_id , spice_models [ imodel ] . design_tech ) ;
2019-08-08 18:25:27 -05:00
2019-08-19 21:43:35 -05:00
circuit_lib . set_model_is_power_gated ( model_id , TRUE = = spice_models [ imodel ] . design_tech_info . power_gated ) ;
2019-08-08 18:25:27 -05:00
/* Buffer linking information */
if ( NULL ! = spice_models [ imodel ] . input_buffer ) {
std : : string model_name ;
if ( NULL ! = spice_models [ imodel ] . input_buffer - > spice_model_name ) {
model_name = spice_models [ imodel ] . input_buffer - > spice_model_name ;
}
2019-08-19 21:43:35 -05:00
circuit_lib . set_model_input_buffer ( model_id , 0 ! = spice_models [ imodel ] . input_buffer - > exist , model_name ) ;
2019-08-08 18:25:27 -05:00
}
if ( NULL ! = spice_models [ imodel ] . output_buffer ) {
std : : string model_name ;
if ( NULL ! = spice_models [ imodel ] . output_buffer - > spice_model_name ) {
model_name = spice_models [ imodel ] . output_buffer - > spice_model_name ;
}
2019-08-19 21:43:35 -05:00
circuit_lib . set_model_output_buffer ( model_id , 0 ! = spice_models [ imodel ] . output_buffer - > exist , model_name ) ;
2019-08-08 18:25:27 -05:00
}
if ( NULL ! = spice_models [ imodel ] . lut_input_buffer ) {
std : : string model_name ;
if ( NULL ! = spice_models [ imodel ] . lut_input_buffer - > spice_model_name ) {
model_name = spice_models [ imodel ] . lut_input_buffer - > spice_model_name ;
}
2019-08-19 21:43:35 -05:00
circuit_lib . set_model_lut_input_buffer ( model_id , 0 ! = spice_models [ imodel ] . lut_input_buffer - > exist , model_name ) ;
2019-08-08 18:25:27 -05:00
}
if ( NULL ! = spice_models [ imodel ] . lut_input_inverter ) {
std : : string model_name ;
if ( NULL ! = spice_models [ imodel ] . lut_input_inverter - > spice_model_name ) {
model_name = spice_models [ imodel ] . lut_input_inverter - > spice_model_name ;
}
2019-08-19 21:43:35 -05:00
circuit_lib . set_model_lut_input_inverter ( model_id , 0 ! = spice_models [ imodel ] . lut_input_inverter - > exist , model_name ) ;
2019-08-08 18:25:27 -05:00
}
2019-08-13 14:25:23 -05:00
if ( ( NULL ! = spice_models [ imodel ] . lut_intermediate_buffer )
& & ( 1 = = spice_models [ imodel ] . lut_intermediate_buffer - > exist ) ) {
2019-08-08 18:25:27 -05:00
std : : string model_name ;
if ( NULL ! = spice_models [ imodel ] . lut_intermediate_buffer - > spice_model_name ) {
model_name = spice_models [ imodel ] . lut_intermediate_buffer - > spice_model_name ;
}
2019-08-19 21:43:35 -05:00
circuit_lib . set_model_lut_intermediate_buffer ( model_id , 0 ! = spice_models [ imodel ] . lut_intermediate_buffer - > exist , model_name ) ;
2019-08-08 18:25:27 -05:00
std : : string model_location_map ;
if ( NULL ! = spice_models [ imodel ] . lut_intermediate_buffer - > location_map ) {
model_location_map = spice_models [ imodel ] . lut_intermediate_buffer - > location_map ;
}
2019-08-19 21:43:35 -05:00
circuit_lib . set_model_lut_intermediate_buffer_location_map ( model_id , model_location_map ) ;
2019-08-08 18:25:27 -05:00
}
/* Pass-gate-logic linking information */
if ( NULL ! = spice_models [ imodel ] . pass_gate_logic ) {
std : : string model_name ( spice_models [ imodel ] . pass_gate_logic - > spice_model_name ) ;
2019-08-19 21:43:35 -05:00
circuit_lib . set_model_pass_gate_logic ( model_id , model_name ) ;
2019-08-08 18:25:27 -05:00
}
/* Buffer information */
if ( NULL ! = spice_models [ imodel ] . design_tech_info . buffer_info ) {
circuit_lib . set_buffer_type ( model_id , spice_models [ imodel ] . design_tech_info . buffer_info - > type ) ;
circuit_lib . set_buffer_size ( model_id , spice_models [ imodel ] . design_tech_info . buffer_info - > size ) ;
if ( TRUE = = spice_models [ imodel ] . design_tech_info . buffer_info - > tapered_buf ) {
circuit_lib . set_buffer_num_levels ( model_id , spice_models [ imodel ] . design_tech_info . buffer_info - > tap_buf_level ) ;
circuit_lib . set_buffer_f_per_stage ( model_id , spice_models [ imodel ] . design_tech_info . buffer_info - > f_per_stage ) ;
}
}
/* Pass-gate information */
if ( NULL ! = spice_models [ imodel ] . design_tech_info . pass_gate_info ) {
circuit_lib . set_pass_gate_logic_type ( model_id , spice_models [ imodel ] . design_tech_info . pass_gate_info - > type ) ;
circuit_lib . set_pass_gate_logic_nmos_size ( model_id , spice_models [ imodel ] . design_tech_info . pass_gate_info - > nmos_size ) ;
circuit_lib . set_pass_gate_logic_pmos_size ( model_id , spice_models [ imodel ] . design_tech_info . pass_gate_info - > pmos_size ) ;
}
/* Multiplexer information */
if ( NULL ! = spice_models [ imodel ] . design_tech_info . mux_info ) {
circuit_lib . set_mux_structure ( model_id , spice_models [ imodel ] . design_tech_info . mux_info - > structure ) ;
circuit_lib . set_mux_num_levels ( model_id , spice_models [ imodel ] . design_tech_info . mux_info - > mux_num_level ) ;
if ( TRUE = = spice_models [ imodel ] . design_tech_info . mux_info - > add_const_input ) {
circuit_lib . set_mux_const_input_value ( model_id , spice_models [ imodel ] . design_tech_info . mux_info - > const_input_val ) ;
}
circuit_lib . set_mux_use_local_encoder ( model_id , TRUE = = spice_models [ imodel ] . design_tech_info . mux_info - > local_encoder ) ;
circuit_lib . set_mux_use_advanced_rram_design ( model_id , TRUE = = spice_models [ imodel ] . design_tech_info . mux_info - > advanced_rram_design ) ;
}
/* LUT information */
if ( NULL ! = spice_models [ imodel ] . design_tech_info . lut_info ) {
circuit_lib . set_lut_is_fracturable ( model_id , TRUE = = spice_models [ imodel ] . design_tech_info . lut_info - > frac_lut ) ;
}
/* Gate information */
if ( NULL ! = spice_models [ imodel ] . design_tech_info . gate_info ) {
circuit_lib . set_gate_type ( model_id , spice_models [ imodel ] . design_tech_info . gate_info - > type ) ;
}
/* RRAM information */
if ( NULL ! = spice_models [ imodel ] . design_tech_info . rram_info ) {
circuit_lib . set_rram_rlrs ( model_id , spice_models [ imodel ] . design_tech_info . rram_info - > ron ) ;
circuit_lib . set_rram_rhrs ( model_id , spice_models [ imodel ] . design_tech_info . rram_info - > roff ) ;
circuit_lib . set_rram_wprog_set_nmos ( model_id , spice_models [ imodel ] . design_tech_info . rram_info - > wprog_set_nmos ) ;
circuit_lib . set_rram_wprog_set_pmos ( model_id , spice_models [ imodel ] . design_tech_info . rram_info - > wprog_set_pmos ) ;
circuit_lib . set_rram_wprog_reset_nmos ( model_id , spice_models [ imodel ] . design_tech_info . rram_info - > wprog_reset_nmos ) ;
circuit_lib . set_rram_wprog_reset_pmos ( model_id , spice_models [ imodel ] . design_tech_info . rram_info - > wprog_reset_pmos ) ;
}
/* Delay information */
for ( int idelay = 0 ; idelay < spice_models [ imodel ] . num_delay_info ; + + idelay ) {
circuit_lib . add_delay_info ( model_id , spice_models [ imodel ] . delay_info [ idelay ] . type ) ;
std : : string in_port_names ( spice_models [ imodel ] . delay_info [ idelay ] . in_port_name ) ;
circuit_lib . set_delay_in_port_names ( model_id , spice_models [ imodel ] . delay_info [ idelay ] . type , in_port_names ) ;
std : : string out_port_names ( spice_models [ imodel ] . delay_info [ idelay ] . out_port_name ) ;
circuit_lib . set_delay_out_port_names ( model_id , spice_models [ imodel ] . delay_info [ idelay ] . type , out_port_names ) ;
std : : string delay_values ( spice_models [ imodel ] . delay_info [ idelay ] . value ) ;
circuit_lib . set_delay_values ( model_id , spice_models [ imodel ] . delay_info [ idelay ] . type , delay_values ) ;
}
/* Wire parameters */
if ( NULL ! = spice_models [ imodel ] . wire_param ) {
circuit_lib . set_wire_type ( model_id , spice_models [ imodel ] . wire_param - > type ) ;
circuit_lib . set_wire_r ( model_id , spice_models [ imodel ] . wire_param - > res_val ) ;
circuit_lib . set_wire_c ( model_id , spice_models [ imodel ] . wire_param - > cap_val ) ;
circuit_lib . set_wire_num_levels ( model_id , spice_models [ imodel ] . wire_param - > level ) ;
}
/* Ports */
for ( int iport = 0 ; iport < spice_models [ imodel ] . num_port ; + + iport ) {
2019-08-20 16:14:28 -05:00
CircuitPortId port_id = circuit_lib . add_model_port ( model_id , spice_models [ imodel ] . ports [ iport ] . type ) ;
2019-08-08 18:25:27 -05:00
/* Fill fundamental attributes */
2019-08-20 16:14:28 -05:00
circuit_lib . set_port_size ( port_id , spice_models [ imodel ] . ports [ iport ] . size ) ;
2019-08-08 18:25:27 -05:00
std : : string port_prefix ( spice_models [ imodel ] . ports [ iport ] . prefix ) ;
2019-08-20 16:14:28 -05:00
circuit_lib . set_port_prefix ( port_id , port_prefix ) ;
2019-08-08 18:25:27 -05:00
std : : string port_lib_name ( spice_models [ imodel ] . ports [ iport ] . lib_name ) ;
2019-08-20 16:14:28 -05:00
circuit_lib . set_port_lib_name ( port_id , port_lib_name ) ;
2019-08-08 18:25:27 -05:00
if ( NULL ! = spice_models [ imodel ] . ports [ iport ] . inv_prefix ) {
std : : string port_inv_prefix ( spice_models [ imodel ] . ports [ iport ] . inv_prefix ) ;
2019-08-20 16:14:28 -05:00
circuit_lib . set_port_inv_prefix ( port_id , port_inv_prefix ) ;
2019-08-08 18:25:27 -05:00
}
2019-08-20 16:14:28 -05:00
circuit_lib . set_port_default_value ( port_id , spice_models [ imodel ] . ports [ iport ] . default_val ) ;
2019-08-08 18:25:27 -05:00
2019-08-20 16:14:28 -05:00
circuit_lib . set_port_is_mode_select ( port_id , TRUE = = spice_models [ imodel ] . ports [ iport ] . mode_select ) ;
circuit_lib . set_port_is_global ( port_id , TRUE = = spice_models [ imodel ] . ports [ iport ] . is_global ) ;
circuit_lib . set_port_is_reset ( port_id , TRUE = = spice_models [ imodel ] . ports [ iport ] . is_reset ) ;
circuit_lib . set_port_is_set ( port_id , TRUE = = spice_models [ imodel ] . ports [ iport ] . is_set ) ;
circuit_lib . set_port_is_config_enable ( port_id , TRUE = = spice_models [ imodel ] . ports [ iport ] . is_config_enable ) ;
circuit_lib . set_port_is_prog ( port_id , TRUE = = spice_models [ imodel ] . ports [ iport ] . is_prog ) ;
2019-08-08 18:25:27 -05:00
if ( NULL ! = spice_models [ imodel ] . ports [ iport ] . spice_model_name ) {
std : : string port_model_name ( spice_models [ imodel ] . ports [ iport ] . spice_model_name ) ;
2019-08-20 16:14:28 -05:00
circuit_lib . set_port_tri_state_model_name ( port_id , port_model_name ) ;
2019-08-08 18:25:27 -05:00
}
if ( NULL ! = spice_models [ imodel ] . ports [ iport ] . inv_spice_model_name ) {
std : : string port_inv_model_name ( spice_models [ imodel ] . ports [ iport ] . inv_spice_model_name ) ;
2019-08-20 16:14:28 -05:00
circuit_lib . set_port_inv_model_name ( port_id , port_inv_model_name ) ;
2019-08-08 18:25:27 -05:00
}
if ( NULL ! = spice_models [ imodel ] . ports [ iport ] . tri_state_map ) {
std : : string port_tri_state_map ( spice_models [ imodel ] . ports [ iport ] . tri_state_map ) ;
2019-08-20 16:14:28 -05:00
circuit_lib . set_port_tri_state_map ( port_id , port_tri_state_map ) ;
2019-08-08 18:25:27 -05:00
}
if ( SPICE_MODEL_LUT = = spice_models [ imodel ] . type ) {
2019-08-20 16:14:28 -05:00
circuit_lib . set_port_lut_frac_level ( port_id , spice_models [ imodel ] . ports [ iport ] . lut_frac_level ) ;
2019-08-08 18:25:27 -05:00
std : : vector < size_t > port_lut_output_mask ;
for ( int ipin = 0 ; ipin < spice_models [ imodel ] . ports [ iport ] . size ; + + ipin ) {
port_lut_output_mask . push_back ( spice_models [ imodel ] . ports [ iport ] . lut_output_mask [ ipin ] ) ;
}
2019-08-20 16:14:28 -05:00
circuit_lib . set_port_lut_output_mask ( port_id , port_lut_output_mask ) ;
2019-08-08 18:25:27 -05:00
}
if ( SPICE_MODEL_PORT_SRAM = = spice_models [ imodel ] . ports [ iport ] . type ) {
2019-08-20 16:14:28 -05:00
circuit_lib . set_port_sram_orgz ( port_id , spice_models [ imodel ] . ports [ iport ] . organization ) ;
2019-08-08 18:25:27 -05:00
}
}
}
2019-08-08 22:20:28 -05:00
/* Build circuit_model links */
2019-08-19 21:43:35 -05:00
circuit_lib . build_model_links ( ) ;
2019-08-08 22:20:28 -05:00
/* Build timing graph */
circuit_lib . build_timing_graphs ( ) ;
2019-08-08 18:25:27 -05:00
return circuit_lib ;
}
2018-07-26 12:28:21 -05:00
/* Process the SPICE Settings*/
void ProcessSpiceSettings ( ezxml_t Parent ,
t_spice * spice ) {
ezxml_t Node , Cur ;
int imodel ;
InitSpice ( spice ) ;
/* Check the parameters*/
Node = FindElement ( Parent , " parameters " , FALSE ) ;
if ( Node ) {
ProcessSpiceParams ( Node , & ( spice - > spice_params ) ) ;
FreeNode ( Node ) ;
}
/* Technology Library and Transistors */
ProcessSpiceTechLibTransistors ( Parent , & ( spice - > tech_lib ) ) ;
/* module spice models*/
2019-07-12 17:18:28 -05:00
Node = FindElement ( Parent , " module_circuit_models " , FALSE ) ;
2018-07-26 12:28:21 -05:00
if ( Node ) {
2019-07-12 17:18:28 -05:00
spice - > num_spice_model = CountChildren ( Node , " circuit_model " , 1 ) ;
2018-07-26 12:28:21 -05:00
/*Alloc*/
spice - > spice_models = ( t_spice_model * ) my_malloc ( spice - > num_spice_model * sizeof ( t_spice_model ) ) ;
/* Assign each found spice model*/
for ( imodel = 0 ; imodel < spice - > num_spice_model ; imodel + + ) {
2019-07-12 17:18:28 -05:00
Cur = FindFirstElement ( Node , " circuit_model " , TRUE ) ;
2018-07-26 12:28:21 -05:00
ProcessSpiceModel ( Cur , & ( spice - > spice_models [ imodel ] ) ) ;
FreeNode ( Cur ) ;
}
assert ( imodel = = spice - > num_spice_model ) ;
FreeNode ( Node ) ;
}
2019-08-08 18:25:27 -05:00
/* Build the CircuitLibrary here from spice_models */
spice - > circuit_lib = build_circuit_library ( spice - > num_spice_model , spice - > spice_models ) ;
2019-08-12 17:45:33 -05:00
check_circuit_library ( spice - > circuit_lib ) ;
2018-07-26 12:28:21 -05:00
/* Check codes*/
check_tech_lib ( spice - > tech_lib , spice - > num_spice_model , spice - > spice_models ) ;
check_spice_models ( spice - > num_spice_model , spice - > spice_models ) ;
return ;
}
2019-08-12 15:20:11 -05:00
/************************************************************************
* End of file : read_xml_spice . c
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */