### global variables ### %ALF2Liberty_AttributeType = ( 'boolean_value' ,'boolean', 'string_value' ,'string' , 'integer' ,'integer', 'number' ,'float', ); %ALF2Liberty_GroupType = ( 'LIBRARY' ,'library', 'CELL' ,'cell', 'PIN' ,'pin', ); ### ALF to Liberty data conversion ### sub ALF_Data2Liberty { local($parent) = @_; print("# System Message:\tstarted creating Liberty view in ALF database ",&DateTime,"\n"); foreach $library (&ALF_FindMatchingObjects($parent,'LIBRARY')) { &ALF_Library2Liberty($library); &ALF_CheckALF2LibertyTranslation($library); } print("# System Message:\tfinished creating Liberty view in ALF database ",&DateTime,"\n"); 1; } sub ALF_CheckALF2LibertyTranslation { local($object) = @_; if ($ALF_Hidden{$object}) { print("# ALF Data Info:\tobject $object is not subject to translation:\t",&ALF_ObjectInfoText($object),"\n") if $ALF_Debug; } elsif ($ALF_LibertyType{$object}) { foreach $child (&Array($ALF_Children{$object})) { &ALF_CheckALF2LibertyTranslation($child); } } elsif ($ALF_Type{$object}) { local $hidden = &ArraySize($ALF_Children{$object})? 'Liberty' : 0; foreach $child (&Array($ALF_Children{$object})) { if ($ALF_LibertyType{$child}) { &ALF_CheckALF2LibertyTranslation($child); } elsif (!$ALF_Hidden{$child}) { &ALF_CheckALF2LibertyTranslation($child); $hidden = 0; } } $ALF_Hidden{$object} = $hidden; print("# ALF Data Warning:\tuntranslatable data:\t",&ALF_ObjectInfoText($object),"\n") unless $hidden; } } ### generic data ### sub ALF_Constant2Liberty { local($constant) = @_; local $return; local $name = $ALF_Name{$constant}; local $value = $ALF_Value{$constant}; if (!defined($value)) { print("# ALF Data Error:\tmissing valuetype:\t",&ALF_ObjectInfoText($constant),"\n"); } elsif (!&ALF_LexicalMatch('number',$value)) { print("# ALF Data Error:\twrong valuetype:\t",&ALF_ObjectInfoText($constant),"\n"); } else { $ALF_LibertySyntax{$constant} = 'simple_attribute'; $ALF_LibertyType{$constant} = $name; $ALF_LibertyValue{$constant} = $value; $return = $constant; } $return; } sub ALF_Property2Liberty { local($property) = @_; foreach $object (&Array($ALF_Children{$property})) { local $type = $ALF_Type{$object}; local $value = $ALF_Value{$object}; &ALF_RedefineObject($object,$ALF_Parent{$property},undef,undef,undef,'ALF_LibertyType',$type,'ALF_LibertyValue',$value); $ALF_LibertySyntax{$object} = &ArraySize($value)? 'complex_attribute' : 'simple_attribute'; } } sub ALF_Keyword2Liberty { local($keyword) = @_; $return; local $attribute_name = $ALF_Name{$keyword}; ### find attribute type local $semantics = defined($attribute_name)? &ALF_FindMatchingObject($ALF_Parent{$keyword},'SEMANTICS',$attribute_name) : undef; local $valuetype = defined($semantics)? &ALF_FindMatchingObject($semantics,'VALUETYPE') : undef; local $alf_attribute_type = defined($valuetype)? $ALF_Value{$valuetype} : undef; local $attribute_type = defined($alf_attribute_type)? $ALF2Liberty_AttributeType{$alf_attribute_type} : undef; ### find group type local $context = &ALF_FindMatchingObject($keyword,'CONTEXT'); local $alf_group_type = defined($context)? $ALF_Value{$context} : undef; local $group_type = defined($alf_group_type)? $ALF2Liberty_GroupType{$alf_group_type} : undef; ### translate if (defined($attribute_name) && defined($attribute_type) && defined($group_type)) { $ALF_LibertySyntax{$keyword} = 'define'; $ALF_LibertyType{$keyword} = 'define'; $ALF_LibertyValue{$keyword} = &CreateArray($attribute_name,$group_type,$attribute_type); $ALF_Hidden{$context} = 'Liberty'; $ALF_Hidden{$semantics} = 'Liberty'; $return = $keyword; } elsif(&StringMatch($attribute_name,@ALF_LibertyGlobal,@ALF_LibertyScaling)) { $ALF_Hidden{$keyword} = 'Liberty'; $ALF_Hidden{$semantics} = 'Liberty' if defined($semantics); } $return; } sub ALF_Template2Liberty { local($template) = @_; local $template_name = $ALF_Name{$template}; if (&StringMatch($template_name,@ALF_LibertyGlobal,@ALF_LibertyScaling)) { $ALF_Hidden{$template} = 'Liberty'; foreach $object (&ALF_FindMatchingObjects($ALF_Parent{$template},$template_name)) { $ALF_Hidden{$object} = 'Liberty'; } } } sub ALF_SingleValueAnnotation2Liberty { local($object,$libtype,$valuetype) = @_; local $value = $ALF_Value{$object}; if (defined($value)) { if (&ALF_LexicalMatch($valuetype,$value)) { $ALF_LibertySyntax{$object} = 'simple_attribute'; $ALF_LibertyType{$object} = $libtype; $ALF_LibertyValue{$object} = $value; } else { print("# ALF Data Warning:\tinvalid valuetype for annotation:\t",&ALF_ObjectInfoText($object),"\n"); } } else { print("# ALF Data Error:\tmissing value for annotation:\t",&ALF_ObjectInfoText($object),"\n"); } } sub ALF_DefinedKeywords2Liberty { local($library,$object) = @_; foreach $define (&ALF_FindMatchingLibertyObjects($library,'define')) { local ($attribute_name,$group_type,$attribute_type) = &Array($ALF_LibertyValue{$define}); if ($group_type eq $ALF2Liberty_GroupType{$ALF_Type{$object}}) { local $attribute = &ALF_FindMatchingObject($object,$attribute_name); &ALF_SingleValueAnnotation2Liberty($attribute,$attribute_name,&FindAssocKey('ALF2Liberty_AttributeType',$attribute_type)) if defined($attribute); } } } ### global technology data ### sub ALF_Library2Liberty { local($library) = @_; $ALF_LibertySyntax{$library} = 'group'; $ALF_LibertyType{$library} = 'library'; $ALF_LibertyName{$library} = &Doublequote($ALF_Name{$library}); foreach $keyword (&ALF_FindMatchingObjects($library,'KEYWORD')) { &ALF_Keyword2Liberty($keyword); } foreach $template (&ALF_FindMatchingObjects($library,'TEMPLATE')) { &ALF_Template2Liberty($template); } foreach $operating_class (&ALF_FindMatchingObjects($library,'CLASS',undef,undef,'USAGE','Liberty_OPERATING_CLASS')) { &ALF_OperatingConditions2Liberty($operating_class); } foreach $scaling_class (&ALF_FindMatchingObjects($library,'CLASS',undef,undef,'USAGE','Liberty_SCALING_CLASS')) { &ALF_ScalingFactors2Liberty($scaling_class); } foreach $select_class (&ALF_FindMatchingObjects($library,'CLASS',undef,undef,'USAGE','SELECT_CLASS')) { &ALF_Class2LibertyWireLoadSelection($select_class); $ALF_Hidden{&ALF_FindMatchingObject($select_class,'USAGE')} = 'Liberty'; } &ALF_DefinedKeywords2Liberty($library,$library); local $delay_slew = &CreateArray(); local $setup_hold = &CreateArray(); local $power = &CreateArray(); foreach $cell (&ALF_FindMatchingObjects($library,'CELL')) { &ALF_Cell2Liberty($cell); &ALF_SearchForObjects($delay_slew,$cell,'ALF_IsFullArithmeticModel','TABLE','DELAY','SLEWRATE'); &ALF_SearchForObjects($setup_hold,$cell,'ALF_IsFullArithmeticModel','TABLE','SETUP','HOLD','RECOVERY','REMOVAL'); &ALF_SearchForObjects($power,$cell,'ALF_IsFullArithmeticModel','TABLE','ENERGY'); } $ALF_Prepend{$library} = 1; local $transition = &CreateArray(); foreach $wire (&ALF_FindMatchingObjects($library,'WIRE')) { &ALF_SearchForObjects($transition,$wire,'ALF_IsFullArithmeticModel','TABLE','SLEWRATE'); local $wiretype_interconnect = &ALF_FindMatchingObject($wire,'WIRETYPE',0,'interconnect'); if ($wiretype_interconnect) { $ALF_Hidden{$wiretype_interconnect} = 'Liberty'; &ALF_Wire2LibertyTransitionDegradation($wire); } local $wiretype_estimated = &ALF_FindMatchingObject($wire,'WIRETYPE',0,'estimated'); if ($wiretype_estimated) { $ALF_Hidden{$wiretype_estimated} = 'Liberty'; &ALF_Wire2LibertyWireLoadTable($wire); } } &ALF_ArithmeticModelHeader2Liberty($library,$delay_slew,'lu_table_template','ALF_Map2LibertyDelayPowerTemplate'); &ALF_ArithmeticModelHeader2Liberty($library,$setup_hold,'lu_table_template','ALF_Map2LibertyTimingConstraintTemplate'); &ALF_ArithmeticModelHeader2Liberty($library,$power,'power_lut_template','ALF_Map2LibertyDelayPowerTemplate'); &ALF_ArithmeticModelHeader2Liberty($library,$transition,'lu_table_template','ALF_Map2LibertyTransitionDegradationTemplate'); &ALF_LibraryAttributes2Liberty($library); &ALF_DelaySlewThresholds2Liberty($library); local $property = &ALF_FindMatchingObject($library,'PROPERTY'); &ALF_Property2Liberty($property) if defined($property); local $information = &ALF_FindMatchingObject($library,'INFORMATION'); &ALF_Information2Liberty($information) if defined($information); $ALF_Prepend{$library} = 0; } sub ALF_Information2Liberty { local($information) = @_; local %libtype = ( 'VERSION','revision', 'DATETIME','date', 'TITLE','comment', 'PRODUCT','technology', ); foreach $object (&Array($ALF_Children{$information})) { local $type = $ALF_Type{$object}; local $value = $ALF_Value{$object}; local $libtype = defined($type)? $libtype{$type} : undef; local $libvalue = ($libtype eq 'technology')? &CreateArray(Unquote($value)) : defined($libtype)? $value : undef; &ALF_CreateLibertyAttribute($ALF_Parent{$information},$libtype,$libvalue) if defined($libvalue); $ALF_Hidden{$object} = 'Liberty'; } } sub ALF_DelaySlewThresholds2Liberty { local($library) = @_; local ($delay_from_rise,$delay_from_fall,$delay_to_rise,$delay_to_fall) = &ALF_TimingThresholds($library,'DELAY'); local ($slew_from_rise,$slew_from_fall,$slew_to_rise,$slew_to_fall) = &ALF_TimingThresholds($library,'SLEWRATE'); local $count; local @threshold; foreach $object ( $delay_from_rise,$delay_from_fall,$delay_to_rise,$delay_to_fall, $slew_from_rise,$slew_from_fall,$slew_to_rise,$slew_to_fall, ) { $count += 1; local $value = $ALF_Value{$object}; if (!defined($object)) { # no op } elsif (!defined($value)) { print("# ALF Data Error:\tmissing value for timing threshold:\t",&ALF_ObjectInfoText($object),"\n"); } elsif (!&ALF_LexicalMatch('number',$value)) { print("# ALF Data Error:\terroneous value for timing threshold:\t",&ALF_ObjectInfoText($object),"\n"); } elsif ($value <= 0 || $value >= 1) { print("# ALF Data Error:\tvalue out of range (0..1) for timing threshold:\t",&ALF_ObjectInfoText($object),"\n"); } else { $threshold[$#threshold+1] = &ALF_FindAncestor($object,'THRESHOLD'); $value = $value*100; &ALF_RedefineObject($object,$library,undef,undef,undef,'ALF_LibertyType','input_threshold_pct_rise','ALF_LibertyValue',$value) if ($count==1); &ALF_RedefineObject($object,$library,undef,undef,undef,'ALF_LibertyType','input_threshold_pct_fall','ALF_LibertyValue',$value) if ($count==2); &ALF_RedefineObject($object,$library,undef,undef,undef,'ALF_LibertyType','output_threshold_pct_rise','ALF_LibertyValue',$value) if ($count==3); &ALF_RedefineObject($object,$library,undef,undef,undef,'ALF_LibertyType','output_threshold_pct_fall','ALF_LibertyValue',$value) if ($count==4); &ALF_RedefineObject($object,$library,undef,undef,undef,'ALF_LibertyType','slew_lower_threshold_pct_rise','ALF_LibertyValue',$value) if ($count==5); &ALF_RedefineObject($object,$library,undef,undef,undef,'ALF_LibertyType','slew_upper_threshold_pct_fall','ALF_LibertyValue',$value) if ($count==6); &ALF_RedefineObject($object,$library,undef,undef,undef,'ALF_LibertyType','slew_upper_threshold_pct_rise','ALF_LibertyValue',$value) if ($count==7); &ALF_RedefineObject($object,$library,undef,undef,undef,'ALF_LibertyType','slew_lower_threshold_pct_fall','ALF_LibertyValue',$value) if ($count==8); $ALF_LibertySyntax{$object} = 'simple_attribute'; } } foreach $threshold (@threshold) { &ALF_CheckALF2LibertyTranslation($threshold); } foreach $threshold (@threshold) { &ALF_CheckALF2LibertyTranslation($ALF_Parent{$threshold}); } } sub ALF_LibraryAttributes2Liberty { local($library) = @_; local $return; local %object2unit = ( 'TIME','time_unit', 'RESISTANCE','pulling_resistance_unit', 'CAPACITANCE','capacitive_load_unit', 'VOLTAGE','voltage_unit', 'CURRENT','current_unit', 'POWER','leakage_power_unit', ); local @parameter = ( 'Liberty_PROCESS','nom_process', 'VOLTAGE','nom_voltage', 'TEMPERATURE','nom_temperature', ); foreach $object (&Array($ALF_Children{$library})) { local $type = $ALF_Type{$object}; local $name = $ALF_Name{$object}; local $value = $ALF_Value{$object}; local $constant = &StringMatch($type,'CONSTANT'); if (&StringMatch($type,'SLEWRATE')) { &ALF_SlewDerateFromLibrary2Liberty($object); } elsif (&StringMatch($type,keys %object2unit)) { &ALF_Unit2Liberty($object,$object2unit{$type}); } elsif ($constant && &StringMatch($name,@parameter)) { &ALF_Constant2Liberty($object); } elsif ($constant && &StringMatch($name,@ALF_Liberty_K_Factors)) { &ALF_Constant2Liberty($object); } elsif ($constant && &StringMatch($name,@ALF_Liberty_Default_Values)) { &ALF_Constant2Liberty($object); } elsif (&StringMatch($type,'Liberty_OPERATING_CLASS')) { local $class = &ALF_FindMatchingObject($library,'CLASS',$value); if (defined($class)) { $ALF_LibertySyntax{$object} = 'simple_attribute'; $ALF_LibertyType{$object} = 'default_operating_conditions'; $ALF_LibertyValue{$object} = &Doublequote($value); } } } } sub ALF_Unit2Liberty { local($object,$libtype) = @_; local $unit = &ALF_FindMatchingObject($object,'UNIT'); local $value = defined($unit)? $ALF_Value{$unit} : undef; if (&ALF_LexicalMatch('multiplier_prefix_value',$value)) { &ALF_CreateLibertyAttribute($ALF_Parent{$object},$libtype,&ALF_Unit($value)); $ALF_Hidden{$unit} = 'Liberty'; } elsif (defined($value)) { } elsif (defined($unit)) { } } sub ALF_Unit { local($unit) = @_; local $number; if (&ALF_LexicalMatch('unsigned_number',$unit)) { $number = $unit; } elsif (&ALF_LexicalMatch('giga',$unit)) { $number = 1e9; } elsif (&ALF_LexicalMatch('mega',$unit)) { $number = 1e6; } elsif (&ALF_LexicalMatch('kilo',$unit)) { $number = 1e3; } elsif (&ALF_LexicalMatch('unity',$unit)) { $number = 1e0; } elsif (&ALF_LexicalMatch('milli',$unit)) { $number = 1e-3; } elsif (&ALF_LexicalMatch('micro',$unit)) { $number = 1e-6; } elsif (&ALF_LexicalMatch('nano',$unit)) { $number = 1e-9; } elsif (&ALF_LexicalMatch('pico',$unit)) { $number = 1e-12; } elsif (&ALF_LexicalMatch('femto',$unit)) { $number = 1e-15; } $number; } sub ALF_SlewDerateFromLibrary2Liberty { local($object) = @_; local $slewunit = &ALF_FindMatchingObject($object,'UNIT'); local $slewval = defined($slewunit)? $ALF_Value{$slewunit} : undef; local $timeunit = &ALF_FindMatchingObject(&ALF_FindMatchingObject($library,'TIME'),'UNIT'); local $timeval = defined($timeunit)? $ALF_Value{$timeunit} : undef; if (&ALF_LexicalMatch('unsigned_number',$slewval) && &ALF_LexicalMatch('unsigned_number',$timeval) && $timeval > 0) { &ALF_CreateLibertyAttribute($ALF_Parent{$object},'slew_derate_from_library',$slewval/$timeval); $ALF_Hidden{$slewunit} = 'Liberty'; } } sub ALF_OperatingConditions2Liberty { local($class) = @_; local %object2parameter = ( 'Liberty_PROCESS','process', 'VOLTAGE','voltage', 'TEMPERATURE','temperature', 'Liberty_TREE_TYPE','tree_type', ); $ALF_LibertySyntax{$class} = 'group'; $ALF_LibertyType{$class} = 'operating_conditions'; $ALF_LibertyName{$class} = &Doublequote($ALF_Name{$class}); foreach $object (&Array($ALF_Children{$class})) { local $type = $ALF_Type{$object}; local $value = $ALF_Value{$object}; if (&StringMatch($type,keys %object2parameter)) { $ALF_LibertySyntax{$object} = 'simple_attribute'; $ALF_LibertyType{$object} = $object2parameter{$type}; $ALF_LibertyValue{$object} = &ALF_LexicalMatch('number',$value)? $value : &Doublequote($value); } elsif (&StringMatch($type,'USAGE')) { $ALF_Hidden{$object} = 'Liberty'; } } } sub ALF_ScalingFactors2Liberty { local ($class) = @_; $ALF_LibertySyntax{$class} = 'group'; $ALF_LibertyType{$class} = 'scaling_factors'; $ALF_LibertyName{$class} = &Doublequote($ALF_Name{$class}); foreach $object (&Array($ALF_Children{$class})) { local $type = $ALF_Type{$object}; local $name = $ALF_Name{$object}; if (&StringMatch($type,'CONSTANT') && &StringMatch($name,@ALF_Liberty_K_Factors)) { &ALF_Constant2Liberty($object); } elsif (&StringMatch($type,'USAGE')) { $ALF_Hidden{$object} = 'Liberty'; } } } ### cell data ### sub ALF_Cell2Liberty { local($cell) = @_; $ALF_LibertySyntax{$cell} = 'group'; $ALF_LibertyType{$cell} = 'cell'; $ALF_LibertyName{$cell} = &Doublequote($ALF_Name{$cell}); &ALF_DefinedKeywords2Liberty($ALF_Parent{$cell},$cell); foreach $pin (&ALF_FindMatchingObjects($cell,'PIN')) { &ALF_Pin2Liberty($pin); } local @vector = &ALF_FindMatchingObjects($cell,'VECTOR'); local @condition = (undef); foreach $vector (@vector) { local $boolean = &ALF_FindBooleanExpression($ALF_Expression{$vector}); $condition[$#condition+1] = $boolean if (defined($boolean) && !&FindArrayKey('condition',$boolean)); } #print("conditions: ",join(':',@condition),"\n"); local @inp = &ALF_FindMatchingObjects($cell,'PIN',undef,undef,'DIRECTION','input'); local @inp_group; foreach $group (&ALF_FindMatchingObjects($cell,'GROUP')) { local $is_input; foreach $input (@inp) { $is_input = &FindArrayKey($ALF_Value{$group},$ALF_Name{$input}); last if defined($is_input); } $input_group[$#input_group+1] = $group if defined($is_input); $ALF_Hidden{$group} = 'Liberty'; } local @outp = &ALF_FindMatchingObjects($cell,'PIN',undef,undef,'DIRECTION','output'); foreach $output (@outp) { foreach $input (@inp,@inp_group) { foreach $condition (@condition) { &ALF_DelayPower2Liberty($output,$input,$condition,@vector); } } } local @dta = ( &ALF_FindMatchingObjects($cell,'PIN',undef,undef,'SIGNALTYPE','data'), &ALF_FindMatchingObjects($cell,'PIN',undef,undef,'SIGNALTYPE','scan_data'), &ALF_FindMatchingObjects($cell,'PIN',undef,undef,'SIGNALTYPE','enable'), &ALF_FindMatchingObjects($cell,'PIN',undef,undef,'SIGNALTYPE','scan_enable'), &ALF_FindMatchingObjects($cell,'PIN',undef,undef,'SIGNALTYPE','out_enable'), &ALF_FindMatchingObjects($cell,'PIN',undef,undef,'SIGNALTYPE','scan_out_enable'), &ALF_FindMatchingObjects($cell,'PIN',undef,undef,'SIGNALTYPE','control'), &ALF_FindMatchingObjects($cell,'PIN',undef,undef,'SIGNALTYPE','address'), &ALF_FindMatchingObjects($cell,'PIN',undef,undef,'SIGNALTYPE','set'), &ALF_FindMatchingObjects($cell,'PIN',undef,undef,'SIGNALTYPE','clear'), ); local @clk = ( &ALF_FindMatchingObjects($cell,'PIN',undef,undef,'SIGNALTYPE','clock'), &ALF_FindMatchingObjects($cell,'PIN',undef,undef,'SIGNALTYPE','scan_clock'), &ALF_FindMatchingObjects($cell,'PIN',undef,undef,'SIGNALTYPE','master_clock'), &ALF_FindMatchingObjects($cell,'PIN',undef,undef,'SIGNALTYPE','slave_clock'), &ALF_FindMatchingObjects($cell,'PIN',undef,undef,'SIGNALTYPE','scan_master_clock'), &ALF_FindMatchingObjects($cell,'PIN',undef,undef,'SIGNALTYPE','scan_slave_clock'), ); foreach $data (@dta) { foreach $clock (@clk) { foreach $condition (@condition) { &ALF_TimingConstraint2Liberty($data,$clock,$condition,@vector); } } } foreach $pin (@inp,@outp) { foreach $condition (@condition) { &ALF_DelayPower2Liberty($pin,undef,$condition,@vector); } } $ALF_Prepend{$cell} = 1; &ALF_CellAttributes2Liberty($cell); local $function = &ALF_FindMatchingObject($cell,'FUNCTION'); &ALF_Function2Liberty($function) if defined($function); local $property = &ALF_FindMatchingObject($cell,'PROPERTY'); &ALF_Property2Liberty($property) if defined($property); $ALF_Prepend{$cell} = 0; } sub ALF_CellAttributes2Liberty { local($cell) = @_; local $power = &ALF_FindMatchingObject($cell,'POWER',undef,undef,'MEASUREMENT','static'); &ALF_TrivialArithmeticModel2Liberty($power,'cell_leakage_power','default_cell_leakage_power') if defined($power); local $area = &ALF_FindMatchingObject($cell,'AREA'); &ALF_TrivialArithmeticModel2Liberty($area,'area') if defined($area); local $swap_class = &ALF_FindMatchingObject($cell,'SWAP_CLASS'); &ALF_SingleValueAnnotation2Liberty($swap_class,'cell_footprint','identifier') if defined($swap_class); local $restrict_class = &ALF_FindMatchingObject($cell,'RESTRICT_CLASS'); &ALF_RestrictClass2Liberty($restrict_class) if defined($restrict_class); } sub ALF_RestrictClass2Liberty { local($restrict_class) = @_; foreach $value(&Array($ALF_Value{$restrict_class})) { &ALF_CreateLibertyAttribute($ALF_Parent{$restrict_class},$value,'true') if &StringMatch($value,'dont_use','dont_touch'); } $ALF_Hidden{$restrict_class} = 'Liberty'; } ### pin data ### sub ALF_Pin2Liberty { local($pin) = @_; $ALF_LibertySyntax{$pin} = 'group'; $ALF_LibertyType{$pin} = 'pin'; $ALF_LibertyName{$pin} = &Doublequote($ALF_Name{$pin}); local $direction = &ALF_FindMatchingObject($pin,'Direction'); &ALF_Direction2Liberty($direction) if $direction; local $capacitance = &ALF_FindMatchingObject($pin,'CAPACITANCE'); &ALF_PinCapacitance2Liberty($capacitance) if $capacitance; local $limit = &ALF_FindMatchingObject($pin,'LIMIT'); if ($limit) { local $caplimit = &ALF_FindMatchingObject($limit,'CAPACITANCE'); if ($caplimit) { &ALF_MinMax2Liberty($caplimit,'MIN','min_capacitance'); &ALF_MinMax2Liberty($caplimit,'MAX','max_capacitance'); } local $slewlimit = &ALF_FindMatchingObject($limit,'SLEWRATE'); if ($slewlimit) { &ALF_MinMax2Liberty($slewlimit,'MIN','min_transition'); &ALF_MinMax2Liberty($slewlimit,'MAX','max_transition'); } local $pulsewidth = &ALF_FindMatchingObject($limit,'PULSEWIDTH'); if ($pulsewidth) { local $high = &ALF_FindMatchingObject($pulsewidth,'HIGH'); if ($high) { &ALF_MinMax2Liberty($high,'MIN','min_pulse_width_high'); &ALF_MinMax2Liberty($high,'MAX','max_pulse_width_high'); } local $low = &ALF_FindMatchingObject($pulsewidth,'LOW'); if ($low) { &ALF_MinMax2Liberty($low,'MIN','min_pulse_width_low'); &ALF_MinMax2Liberty($low,'MAX','max_pulse_width_low'); } &ALF_CheckALF2LibertyTranslation($pulsewidth); } } local $signaltype = &ALF_FindMatchingObject($pin,'SIGNALTYPE'); $ALF_Hidden{$signaltype} = 'Liberty' if $signaltype; } sub ALF_Direction2Liberty { local ($direction) = @_; local $dirval = $ALF_Value{$direction}; local $libdirval = (&StringMatch($dirval,'input' ))? 'input' : (&StringMatch($dirval,'output'))? 'output' : (&StringMatch($dirval,'both' ))? 'inout' : (&StringMatch($dirval,'none' ))? 'internal' : undef; if ($libdirval) { $ALF_LibertySyntax{$direction} = 'simple_attribute'; $ALF_LibertyType{$direction} = 'direction'; $ALF_LibertyValue{$direction} = $libdirval; } else { print("# ALF Data Warning:\tdirection \42$dirval\42 cannot be converted to Liberty:\t",&ALF_ObjectInfoText($pin),"\n"); } } sub ALF_PinCapacitance2Liberty { local ($capacitance) = @_; local $capval = $ALF_Value{$capacitance}; if (defined($capval)) { $ALF_LibertySyntax{$capacitance} = 'simple_attribute'; $ALF_LibertyType{$capacitance} = 'capacitance'; $ALF_LibertyValue{$capacitance} = $capval; } local $defaultcap = &ALF_FindMatchingObject($capacitance,'DEFAULT'); if ($defaultcap) { &ALF_CreateLibertyAttribute($pin,'capacitance',$ALF_Value{$defaultcap}); $ALF_Hidden{$defaultcap} = 'Liberty'; } local $risecap = &ALF_FindMatchingObject($capacitance,'RISE'); if ($risecap) { local $risecapval = $ALF_Value{$risecap}; if (defined($risecapval)) { &ALF_CreateLibertyAttribute($pin,'rise_capacitance',$risecapval); $ALF_Hidden{$risecap} = 'Liberty'; } } local $fallcap = &ALF_FindMatchingObject($capacitance,'FALL'); if ($fallcap) { local $fallcapval = $ALF_Value{$fallcap}; if (defined($fallcapval)) { &ALF_CreateLibertyAttribute($pin,'fall_capacitance',$fallcapval); $ALF_Hidden{$fallcap} = 'Liberty'; } } &ALF_CheckALF2LibertyTranslation($capacitance); } sub ALF_MinMax2Liberty { local ($object,$minmaxtype,$libtype) = @_; local $limit = &ALF_FindAncestor($object,'LIMIT'); local $minmax = &ALF_FindMatchingObject($object,$minmaxtype); if ($minmax) { local $minmaxval = $ALF_Value{$minmax}; if ($minmaxval) { &ALF_CreateLibertyAttribute($ALF_Parent{$limit},$libtype,$minmaxval); $ALF_Hidden{$object} = 'Liberty'; } } } ### timing type based on signaltype ### sub ALF_SignalType2LibertyTimingType { local($timing) = @_; local $related_pin_annotation = &ALF_FindMatchingLibertyObject($timing,'related_pin'); local $related_pin_name = &Unquote($ALF_LibertyValue{$related_pin_annotation}); local $related_pin = &ALF_FindMatchingObject($ALF_Parent{$ALF_Parent{$timing}},'PIN',$related_pin_name); local $pin = $ALF_Parent{$timing}; local $related_signaltype = &ALF_FindMatchingObject($related_pin,'SIGNALTYPE'); local $related_signaltype_value = $ALF_Value{$related_signaltype} if $related_signaltype; local $related_polarity = &ALF_FindMatchingObject($related_pin,'POLARITY'); local $related_polarity_value = $ALF_Value{$related_polarity} if $related_polarity; #print("ALF_SignalType2LibertyTimingType\trelated pin = $related_pin_name\trelated signaltype = $related_signaltype_value\n"); &StringMatch($related_signaltype_value,'set')? 'preset' : &StringMatch($related_signaltype_value,'clear')? 'clear' : &StringMatch($related_signaltype_value,'clock') && &StringMatch($related_polarity_value,'rising_edge')? 'rising_edge' : &StringMatch($related_signaltype_value,'clock') && &StringMatch($related_polarity_value,'falling_edge')? 'falling_edge' : undef; } ### function data ### sub ALF_Function2Liberty { local($function) = @_; local $cell = $ALF_Parent{$function}; local $behavior = &ALF_FindMatchingObject($function,'BEHAVIOR'); if (defined($behavior)) { &ALF_Combinational2Liberty($cell,$behavior); foreach $sequential (&ALF_FindMatchingObjects($behavior,'@')) { &ALF_Sequential2Liberty($cell,$sequential); } local $celltype = &ALF_FindMatchingObject($cell,'CELLTYPE'); $ALF_Hidden{$function} = 'Liberty'; $ALF_Hidden{$celltype} = 'Liberty'; } else { print(" # ALF Data Warning:\tmissing behavior for cell $cell ",&ALF_InfoText($cell),"\n"); } } sub ALF_Combinational2Liberty { local($cell,$behavior) = @_; foreach $pin (&ALF_FindMatchingObjects($cell,'PIN')) { $ALF_Prepend{$pin} = 1; local $function = &ALF_FindMatchingObject($behavior,&UpperCase($ALF_Name{$pin})); if (defined($function)) { &ALF_CreateLibertyAttribute($pin,'function',&ALF_Boolean2Liberty($ALF_Value{$function})); } $ALF_Prepend{$pin} = 0; } } sub ALF_Sequential2Liberty { local($cell,$sequential) = @_; local @alternative = &ALF_FindAlternativeControlStatements($sequential); local ($q,$qn) = &ALF_FindStorageVariable($cell,$sequential,@alternative); local ($clear,$preset,$clear_preset_var1,$clear_preset_var2) = &ALF_FindClearPresetInfo($q,$qn,$sequential,@alternative); local $q_invisible = &ALF_FindMatchingObject($q ,'VIEW',undef,'none'); local $qn_invisible = &ALF_FindMatchingObject($qn,'VIEW',undef,'none'); local $iq = $q_invisible ? $ALF_Name{$q } : &AutoName; local $iqn = $qn_invisible? $ALF_Name{$qn} : &AutoName; local $index = (defined($clear_preset_var1) || defined($clear_preset_var2))? 2 : (defined($clear) && defined($preset))? 1 : (defined($clear) || defined($preset))? 0 : -1; local $clock = ($index >= 0)? $alternative[$index] : (!defined($clear) && !defined($preset))? $sequential : undef; #print("ALF_Sequential2Liberty\t",&ALF_ObjectInfoText($cell),"\n"); #print("ALF_Sequential2Liberty\tq\t",&ALF_ObjectInfoText($q),"\n"); #print("ALF_Sequential2Liberty\tqn\t",&ALF_ObjectInfoText($qn),"\n"); #print("ALF_Sequential2Liberty\tclock\t",&ALF_ObjectInfoText($clock),"\n"); local $data = ()? undef : $q ? &ALF_Boolean2Liberty($ALF_Value{&ALF_FindMatchingObject($clock,$ALF_Name{$q})}) : $qn? &ALF_Boolean2Liberty(&ALF_Inverted($ALF_Value{&ALF_FindMatchingObject($clock,$ALF_Name{$qn})})) : undef; local $model = &ALF_CreateObject($cell,undef,undef,undef,'ALF_LibertySyntax','group','ALF_LibertyName',join(',',$iq,$iqn)); &ALF_CreateLibertyAttribute($q ,'function',$iq ) if(defined($q) && !$q_invisible ); &ALF_CreateLibertyAttribute($qn,'function',$iqn) if(defined($qn) && !$qn_invisible); &ALF_CreateLibertyAttribute($model,'clear',&ALF_Boolean2Liberty(&Unbrace($ALF_Name{$clear}))) if defined($clear); &ALF_CreateLibertyAttribute($model,'preset',&ALF_Boolean2Liberty(&Unbrace($ALF_Name{$preset}))) if defined($preset); &ALF_CreateLibertyAttribute($model,'clear_preset_var1',$clear_preset_var1) if defined($clear_preset_var1); &ALF_CreateLibertyAttribute($model,'clear_preset_var2',$clear_preset_var2) if defined($clear_preset_var2); if (!defined($clock)) { $ALF_LibertyType{$model} = 'latch'; } elsif (&ALF_BooleanExpression($ALF_Expression{$clock})) { &ALF_Latch2Liberty($model,$data,$clock); } else { $ALF_LibertyType{$model} = 'ff'; local $slave_clock = ($#alternative > $index)? $alternative[$index + 1] : undef; &ALF_Flipflop2Liberty($model,$data,$clock,$slave_clock); } &ALF_SequentialAttributes2Liberty($model); } sub ALF_FindStorageVariable { local($cell,@statement) = @_; local ($q,$qn); foreach $variable (&ALF_FindControlledVariables(@statement)) { $q = &ALF_FindMatchingObject($cell,'PIN',$variable,undef,'ATTRIBUTE','non_inverted') unless $q; $qn = &ALF_FindMatchingObject($cell,'PIN',$variable,undef,'ATTRIBUTE','inverted') unless $qn; } foreach $var ($q,$qn) { if (defined($var) && &ALF_FindMatchingObject($var,'VIEW',undef,'none')) { $ALF_Hidden{$var} = 'Liberty'; ALF_HideAllChildren{$var,'Liberty'}; } } ($q,$qn); } sub ALF_FindClearPresetInfo { local($q,$qn,@statement) = @_; local ($clear,$preset,$clear_preset_var1,$clear_preset_var2); foreach $statement (@statement) { local $assign_q = $ALF_Value{&ALF_FindMatchingObject($statement,$ALF_Name{$q})} if $q; local $assign_qn = $ALF_Value{&ALF_FindMatchingObject($statement,$ALF_Name{$qn})} if $qn; if ($q && $qn) { $preset = $statement if ($assign_q eq '1' && $assign_qn eq '0'); $clear = $statement if ($assign_q eq '0' && $assign_qn eq '1'); } elsif ($q) { $preset = $statement if ($assign_q eq '1'); $clear = $statement if ($assign_q eq '0'); } elsif ($qn) { $preset = $statement if ($assign_qn eq '0'); $clear = $statement if ($assign_qn eq '1'); } } local $primary = $statement[0]; if ($preset && $clear && ($preset ne $primary) && ($clear ne $primary)) { $clear_preset_var1 = &ALF_Boolean2Liberty($ALF_Value{&ALF_FindMatchingObject($primary,$ALF_Name{$q})}); $clear_preset_var2 = &ALF_Boolean2Liberty($ALF_Value{&ALF_FindMatchingObject($primary,$ALF_Name{$qn})}); } ($clear,$preset,$clear_preset_var1,$clear_preset_var2); } sub ALF_Latch2Liberty { local($model,$data,$clock) = @_; $ALF_LibertyType{$model} = 'latch'; &ALF_CreateLibertyAttribute($model,'enable',&ALF_Boolean2Liberty(&Unbrace($ALF_Name{$clock}))); &ALF_CreateLibertyAttribute($model,'data_in',$data); } sub ALF_Flipflop2Liberty { local($model,$data,$clock,$slave_clock) = @_; $ALF_LibertyType{$model} = 'ff'; &ALF_CreateLibertyAttribute($model,'next_state',$data); local $expression = $ALF_Expression{$clock}; local ($edge,$clk) = &ALF_SingleEvent($expression); local ($edge1,$clk1,$edge2,$clk2) = &ALF_DualEvent($expression); if (defined($edge1)) { &ALF_CreateLibertyAttribute($model,'clocked_on',&ALF_Boolean2Liberty(&ALF_Edge2Boolean("$edge1 $clk1"))); &ALF_CreateLibertyAttribute($model,'clocked_on_also',&ALF_Boolean2Liberty(&ALF_Edge2Boolean("$edge2 $clk2"))); } elsif (defined($edge)) { &ALF_CreateLibertyAttribute($model,'clocked_on',&ALF_Boolean2Liberty(&ALF_Edge2Boolean("$edge $clk"))); if (defined($slave_clock)) { local $slave_expression = $ALF_Expression{$slave_clock}; ($edge2,$clk2) = &ALF_SingleEvent($slave_expression); if (defined($edge2)) { &ALF_CreateLibertyAttribute($model,'clocked_on_also',&ALF_Boolean2Liberty(&ALF_Edge2Boolean("$edge2 $clk2"))); } } } else { print("# ALF Data Error:\tinvalid clock expression \47$expression\47 for flipflop:\t",&ALF_ObjectInfoText($clock),"\n"); print(&ALF_ExpressionInfoText($expression,"# ALF Data Error:\tinvalid clock expression\t"),"\n"); } } sub ALF_SequentialAttributes2Liberty { local($model) = @_; local $cell = $ALF_Parent{$model}; local $celltype = &ALF_FindMatchingObject($cell,'CELLTYPE'); if (defined($celltype)) { local $modeltype = $ALF_LibertyType{$model}; local $expected = ($modeltype eq 'latch')? 'latch' : ($modeltype eq 'ff')? 'flipflop' : undef; unless (&StringMatch($ALF_Value{$celltype},$expected,'block','core')) { print("# ALF Data Error:\tobject not compatible with $expected:\t",&ALF_ObjectInfoText($celltype),"\n"); } } foreach $attribute (&Array($ALF_Children{$model})) { local $type = $ALF_LibertyType{$attribute}; if (&StringMatch($type,'clocked_on','clocked_on_also','enable','next_state','data_in','preset','clear')) { local $value = $ALF_LibertyValue{$attribute}; $value =~ s/\s//g; local $value_noninverted = $value; $value_noninverted =~ s/\47//g; local $pin = &ALF_FindMatchingObject($cell,'PIN',&Unquote($value_noninverted)); local $active = $value_noninverted eq $value; if ($pin) { #print("ALF_SequentialAttributes2Liberty\t",&ALF_ObjectInfoText($ALF_Parent{$pin}),"\n"); #print("ALF_SequentialAttributes2Liberty\t",&ALF_ObjectInfoText($pin),"\n"); #print("ALF_SequentialAttributes2Liberty\t",&ALF_ObjectInfoText($attribute,'ALF_LibertyType','ALF_LibertyValue'),"\n"); local $signaltype = &ALF_FindMatchingObject($pin,'SIGNALTYPE'); local $polarity = &ALF_FindMatchingObject($pin,'POLARITY'); local $action = &ALF_FindMatchingObject($pin,'ACTION'); #print("ALF_SequentialAttributes2Liberty\t",&ALF_ObjectInfoText($signaltype),"\n") if $signaltype; #print("ALF_SequentialAttributes2Liberty\t",&ALF_ObjectInfoText($polarity),"\n") if $polarity; #print("ALF_SequentialAttributes2Liberty\t",&ALF_ObjectInfoText($action),"\n") if $action; if (!defined($signaltype) && !defined($polarity) && !defined($action)) { } elsif (&StringMatch($type,'clocked_on')) { &ALF_CheckFlipflopMasterClock($signaltype,$polarity,$active); } elsif (&StringMatch($type,'clocked_on_also')) { &ALF_CheckFlipflopSlaveClock($signaltype,$polarity,$active); } elsif (&StringMatch($type,'enable')) { &ALF_CheckLatchClock($signaltype,$polarity,$active); } elsif (&StringMatch($type,'next_state','data_in')) { &ALF_CheckData($signaltype); } elsif (&StringMatch($type,'preset')) { &ALF_CheckPreset($signaltype,$polarity,$active,$action); } elsif (&StringMatch($type,'clear')) { &ALF_CheckClear($signaltype,$polarity,$active,$action); } } elsif (&ALF_LexicalMatch('identifier',&Unquote($value_noninverted))) { print("# ALF Data Error:\tmissing reference for $type = $value:\t",&ALF_ObjectInfoText($cell),"\n"); } } } } sub ALF_CheckFlipflopMasterClock { local($signaltype,$polarity,$active) = @_; if (&StringMatch($ALF_Value{$signaltype},'clock','master_clock')) { $ALF_Hidden{$signaltype} = 'Liberty'; } elsif ($signaltype) { print("# ALF Data Error:\tobject not compatible with flipflop master clock:\t",&ALF_ObjectInfoText($signaltype),"\n"); } local $expected = $active? 'rising_edge' : 'falling_edge'; if (&StringMatch($ALF_Value{$polarity},$expected,'double_edge')) { $ALF_Hidden{$polarity} = 'Liberty'; } elsif ($polarity) { print("# ALF Data Error:\tobject not compatible with $expected:\t",&ALF_ObjectInfoText($polarity),"\n"); } } sub ALF_CheckFlipflopSlaveClock { local($signaltype,$polarity,$active) = @_; if (&StringMatch($ALF_Value{$signaltype},'clock','slave_clock')) { $ALF_Hidden{$signaltype} = 'Liberty'; } elsif ($signaltype) { print("# ALF Data Error:\tobject not compatible with flipflop slave clock:\t",&ALF_ObjectInfoText($signaltype),"\n"); } local $expected = $active? 'rising_edge' : 'falling_edge'; if (&StringMatch($ALF_Value{$polarity},$expected,'double_edge')) { $ALF_Hidden{$polarity} = 'Liberty'; } elsif ($polarity) { print("# ALF Data Error:\tobject not compatible with $expected:\t",&ALF_ObjectInfoText($polarity),"\n"); } } sub ALF_CheckLatchClock { local($signaltype,$polarity,$active) = @_; if (&StringMatch($ALF_Value{$signaltype},'clock')) { $ALF_Hidden{$signaltype} = 'Liberty'; } elsif ($signaltype) { print("# ALF Data Error:\tobject not compatible with latch clock:\t",&ALF_ObjectInfoText($signaltype),"\n"); } local $expected = $active? 'high' : 'low'; if (&StringMatch($ALF_Value{$polarity},$expected)) { $ALF_Hidden{$polarity} = 'Liberty'; } elsif ($polarity) { print("# ALF Data Error:\tobject not compatible with $expected:\t",&ALF_ObjectInfoText($polarity),"\n"); } } sub ALF_CheckData { local($signaltype) = @_; if (&StringMatch($ALF_Value{$signaltype},'data','scan_data')) { $ALF_Hidden{$signaltype} = 'Liberty'; } elsif ($signaltype) { print("# ALF Data Error:\tobject not compatible with data:\t",&ALF_ObjectInfoText($signaltype),"\n"); } } sub ALF_CheckPreset { local($signaltype,$polarity,$active,$action) = @_; if (&StringMatch($ALF_Value{$signaltype},'set')) { $ALF_Hidden{$signaltype} = 'Liberty'; } elsif ($signaltype) { print("# ALF Data Error:\tobject not compatible with preset:\t",&ALF_ObjectInfoText($signaltype),"\n"); } local $expected = $active? 'high' : 'low'; if (&StringMatch($ALF_Value{$polarity},$expected)) { $ALF_Hidden{$polarity} = 'Liberty'; } elsif ($polarity) { print("# ALF Data Error:\tobject not compatible with $expected:\t",&ALF_ObjectInfoText($polarity),"\n"); } if (&StringMatch($ALF_Value{$action},'asynchronous')) { $ALF_Hidden{$action} = 'Liberty'; } elsif ($action) { print("# ALF Data Error:\tobject not compatible with asynchronous preset:\t",&ALF_ObjectInfoText($action),"\n"); } } sub ALF_CheckClear { local($signaltype,$polarity,$active,$action) = @_; if (&StringMatch($ALF_Value{$signaltype},'clear')) { $ALF_Hidden{$signaltype} = 'Liberty'; } elsif ($signaltype) { print("# ALF Data Error:\tobject not compatible with clear:\t",&ALF_ObjectInfoText($signaltype),"\n"); } local $expected = $active? 'high' : 'low'; if (&StringMatch($ALF_Value{$polarity},$expected)) { $ALF_Hidden{$polarity} = 'Liberty'; } elsif ($polarity) { print("# ALF Data Error:\tobject not compatible with $expected:\t",&ALF_ObjectInfoText($polarity),"\n"); } if (&StringMatch($ALF_Value{$action},'asynchronous')) { $ALF_Hidden{$action} = 'Liberty'; } elsif ($action) { print("# ALF Data Error:\tobject not compatible with asynchronous clear:\t",&ALF_ObjectInfoText($action),"\n"); } } sub ALF_Boolean2Liberty { local($expression) = @_; local @alf = split(/\s+/,$expression); local @liberty; local $inversion; foreach $alf (@alf) { if (&StringMatch($alf,'!','~')) { $inversion = 1; } elsif ($inversion) { $inversion = 0; $liberty[$#liberty+1] = "$alf\47"; } elsif (&StringMatch($alf,'&','&&')) { $liberty[$#liberty+1] = '*'; } elsif (&StringMatch($alf,'|','||')) { $liberty[$#liberty+1] = '+'; } elsif (&ALF_LogicalValue($alf) eq 'true') { $liberty[$#liberty+1] = 'H'; } elsif (&ALF_LogicalValue($alf) eq 'false') { $liberty[$#liberty+1] = 'L'; } else { $liberty[$#liberty+1] = $alf; } } #print("ALF_Boolean2Liberty($expression)\talf = (@alf)\tliberty = (@liberty)\n"); defined($expression)? "\42".join(' ',@liberty)."\42" : undef; } ### interconnect data ### sub ALF_Wire2LibertyTransitionDegradation { local ($wire) = @_; local $driver = &ALF_FindMatchingObject($wire,'NODE',undef,undef,'NODETYPE','driver'); local $receiver = &ALF_FindMatchingObject($wire,'NODE',undef,undef,'NODETYPE','receiver'); if ($driver && $receiver) { $ALF_Hidden{$driver} = 'Liberty'; $ALF_Hidden{$receiver} = 'Liberty'; foreach $vector (&ALF_FindMatchingObjects($wire,'VECTOR')) { local $slewrate = &ALF_FindMatchingObject($vector,'SLEWRATE',undef,undef,'PIN',$ALF_Name{$receiver}); local $edge = &ALF_FindEdgeLiteral($ALF_Expression{$vector},$ALF_Name{$receiver}); local $related_edge = &ALF_FindEdgeLiteral($ALF_Expression{$vector},$ALF_Name{$driver}); local $libtype = &ALF_IsRisingEdge(&ALF_GetBitLiterals($edge))? 'rise_transition_degradation' : &ALF_IsFallingEdge(&ALF_GetBitLiterals($edge))? 'fall_transition_degradation' : undef; if ( $libtype eq 'rise_transition_degradation' && &ALF_IsRisingEdge(&ALF_GetBitLiterals($related_edge)) || $libtype eq 'fall_transition_degradation' && &ALF_IsFallingEdge(&ALF_GetBitLiterals($related_edge)) ) { &ALF_ArithmeticModel2Liberty($slewrate,$libtype); &ALF_RedefineObject($slewrate,$ALF_Parent{$wire}); $ALF_Hidden{&ALF_FindMatchingObject($slewrate,'PIN')} = 'Liberty'; $ALF_Hidden{$vector} = 'Liberty'; } elsif ($libtype) { print("# ALF Data Error:\tincompatible transitions on driver and receiver:\t",&ALF_ObjectInfoText($vector),"\n"); } } } else { print("# ALF Data Warning:\tmissing driver and/or receiver node:\t",&ALF_ObjectInfoText($wire),"\n"); } } sub ALF_Wire2LibertyWireLoadTable { local ($wire) = @_; local %libtype = ( 'LENGTH','fanout_length', 'CAPACITANCE','fanout_capacitance', 'RESISTANCE','fanout_resistance', 'AREA','fanout_area', ); $ALF_LibertySyntax{$wire} = 'group'; $ALF_LibertyType{$wire} = 'wire_load_table'; $ALF_LibertyName{$wire} = &Doublequote($ALF_Name{$wire}); foreach $modeltype (keys %libtype) { local $model = &ALF_FindMatchingObject($wire,$modeltype); &ALF_FanoutModel2Liberty($model,$libtype{$modeltype}) if $model; } local $select_class = &ALF_FindMatchingObject($wire,'SELECT_CLASS'); $ALF_Hidden{$select_class} = 'Liberty' if $select_class; } sub ALF_FanoutModel2Liberty { local($model,$libtype) = @_; local $table = &ALF_FindMatchingObject($model,'TABLE'); local @table = $table? &Array($ALF_Value{$table}) : (); local $header = &ALF_FindMatchingObject($model,'HEADER'); local $fanout = $header? &ALF_FindMatchingObject($header,'FANOUT') : undef; local $fanout_table = $fanout? &ALF_FindMatchingObject($fanout,'TABLE') : undef; local @fanout_table = $fanout_table? &Array($ALF_Value{$fanout_table}) : (); if ($#table==$#fanout_table) { for $i (0..$#table) { &ALF_CreateLibertyAttribute($ALF_Parent{$model},$libtype,&CreateArray($fanout_table[$i],$table[$i])); } $ALF_Hidden{$model} = 'Liberty'; $ALF_Hidden{$table} = 'Liberty'; $ALF_Hidden{$header} = 'Liberty'; $ALF_Hidden{$fanout} = 'Liberty'; $ALF_Hidden{$fanout_table} = 'Liberty'; } } sub ALF_Class2LibertyWireLoadSelection { local($class) = @_; $ALF_LibertySyntax{$class} = 'group'; $ALF_LibertyType{$class} = 'wire_load_selection'; $ALF_LibertyName{$class} = &Doublequote($ALF_Name{$class}); foreach $area (&ALF_FindMatchingObject($class,'AREA')) { local $wire = &ALF_FindMatchingObject($area,'WIRE'); local $min = &ALF_FindMatchingObject($area,'MIN'); local $max = &ALF_FindMatchingObject($area,'MAX'); if ( &ALF_LexicalMatch('identifier',$ALF_Value{$wire}) && &ALF_LexicalMatch('number',$ALF_Value{$min}) && &ALF_LexicalMatch('number',$ALF_Value{$max}) ) { $ALF_LibertySyntax{$area} = 'complex_attribute'; $ALF_LibertyType{$area} = 'wire_load_from_area'; $ALF_LibertyValue{$area} = &CreateArray($ALF_Value{$min},$ALF_Value{$max},&Doublequote($ALF_Value{$wire})); $ALF_Hidden{$wire} = 'Liberty'; $ALF_Hidden{$min} = 'Liberty'; $ALF_Hidden{$max} = 'Liberty'; } } } ### cell timing & power data ### sub ALF_DelayPower2Liberty { local($output,$input,$condition,@vector) = @_; local $delay_list = &CreateArray(); local $energy_list = &CreateArray(); local @slew_list; foreach $vector (@vector) { local $edge = &ALF_FindEdgeLiteral($ALF_Expression{$vector},$ALF_Name{$output}); local $related_edge = &ALF_FindEdgeLiteral($ALF_Expression{$vector},$ALF_Name{$input}); local $boolean = &StringMatch($condition,&ALF_FindBooleanExpression($ALF_Expression{$vector})) if defined($condition); local ($single_event) = &ALF_SingleEvent($ALF_Expression{$vector}) unless defined($condition); if (defined($edge) && defined($related_edge) && ($boolean || !defined($condition))) { local $delay = &ALF_FindMatchingObject($vector,'DELAY',undef,undef, 'To.Pin',$ALF_Name{$output}, 'From.Pin',$ALF_Name{$input}, ); if (defined($delay)) { &AppendArray($delay_list,$delay); &ALF_Delay2Liberty($delay,$edge); $ALF_Hidden{&ALF_FindMatchingObject($delay,'FROM')} = 'Liberty'; $ALF_Hidden{&ALF_FindMatchingObject($delay,'TO')} = 'Liberty'; local $slewrate = &ALF_FindMatchingObject($vector,'SLEWRATE',undef,undef, 'Pin',$ALF_Name{$output}, ); if (defined($slewrate)) { $slew_list[$#slew_list+1] = $slewrate; &ALF_Slewrate2Liberty($slewrate,$edge); $ALF_Hidden{&ALF_FindMatchingObject($slewrate,'PIN')} = 'Liberty'; } } local $energy = &ALF_FindMatchingObject($vector,'ENERGY',undef,undef); if (defined($energy)) { &AppendArray($energy_list,$energy); &ALF_Energy2Liberty($energy,$edge); } } elsif ((!$input && defined($edge) || !$output && defined($related_edge)) && ($boolean || $single_event)) { local $energy = &ALF_FindMatchingObject($vector,'ENERGY',undef,undef); if (defined($energy)) { &AppendArray($energy_list,$energy); &ALF_Energy2Liberty($energy,defined($edge)? $edge : $related_edge); } } } if (&ArraySize($delay_list)) { local $timing = &ALF_CreateLibertyTiming($output,$input,&ALF_Boolean2Liberty($condition),$delay_list,@slew_list); local $actual_timing_type = $ALF_LibertyValue{&ALF_FindMatchingLibertyObject($timing,'timing_type')}; local $proposed_timing_type = &ALF_SignalType2LibertyTimingType($timing); if ($proposed_timing_type && $actual_timing_type ne $proposed_timing_type) { print("# ALF Data Warning:\tdiscrepancy between proposed timing type \42$proposed_timing_type\42 and actual timing type \42$actual_timing_type\42:\t",&ALF_ObjectInfoText($timing,'ALF_LibertyType'),"\n"); $ALF_LibertyValue{&ALF_FindMatchingLibertyObject($timing,'timing_type')} = $proposed_timing_type; } } if (&ArraySize($energy_list)) { &ALF_CreateLibertyInternalPower($output,$input,&ALF_Boolean2Liberty($condition),$energy_list); } } sub ALF_TimingConstraint2Liberty { local($data,$clock,$condition,@vector) = @_; local $setup_recovery_list = &CreateArray(); local $hold_removal_list = &CreateArray(); foreach $vector (@vector) { local $edge = &ALF_FindEdgeLiteral($ALF_Expression{$vector},$ALF_Name{$data}); local $related_edge = &ALF_FindEdgeLiteral($ALF_Expression{$vector},$ALF_Name{$clock}); local $boolean = &ALF_FindBooleanExpression($ALF_Expression{$vector}); if (defined($edge) && defined($related_edge) && ($boolean || !defined($condition))) { local $setup = &ALF_FindMatchingObject($vector,'SETUP',undef,undef, 'To.Pin',$ALF_Name{$clock}, 'From.Pin',$ALF_Name{$data}, ); if (defined($setup)) { &AppendArray($setup_recovery_list,$setup); &ALF_SetupRecovery2Liberty($setup,$edge); $ALF_Hidden{&ALF_FindMatchingObject($setup,'FROM')} = 'Liberty'; $ALF_Hidden{&ALF_FindMatchingObject($setup,'TO')} = 'Liberty'; } local $recovery = &ALF_FindMatchingObject($vector,'RECOVERY',undef,undef, 'To.Pin',$ALF_Name{$clock}, 'From.Pin',$ALF_Name{$data}, ); if (defined($recovery)) { &AppendArray($setup_recovery_list,$recovery); &ALF_SetupRecovery2Liberty($recovery,$edge); $ALF_Hidden{&ALF_FindMatchingObject($recovery,'FROM')} = 'Liberty'; $ALF_Hidden{&ALF_FindMatchingObject($recovery,'TO')} = 'Liberty'; } local $hold = &ALF_FindMatchingObject($vector,'HOLD',undef,undef, 'To.Pin',$ALF_Name{$data}, 'From.Pin',$ALF_Name{$clock}, ); if (defined($hold)) { &AppendArray($hold_removal_list,$hold); &ALF_HoldRemoval2Liberty($hold,$edge); $ALF_Hidden{&ALF_FindMatchingObject($hold,'FROM')} = 'Liberty'; $ALF_Hidden{&ALF_FindMatchingObject($hold,'TO')} = 'Liberty'; } local $removal = &ALF_FindMatchingObject($vector,'REMOVAL',undef,undef, 'To.Pin',$ALF_Name{$data}, 'From.Pin',$ALF_Name{$clock}, ); if (defined($removal)) { &AppendArray($hold_removal_list,$removal); &ALF_HoldRemoval2Liberty($removal,$edge); $ALF_Hidden{&ALF_FindMatchingObject($removal,'FROM')} = 'Liberty'; $ALF_Hidden{&ALF_FindMatchingObject($removal,'TO')} = 'Liberty'; } } } &ALF_CreateLibertyTiming($data,$clock,&ALF_Boolean2Liberty($condition),$setup_recovery_list) if &ArraySize($setup_recovery_list); &ALF_CreateLibertyTiming($data,$clock,&ALF_Boolean2Liberty($condition),$hold_removal_list) if &ArraySize($hold_removal_list); } ### auxiliary functions for timing and power ### sub ALF_Delay2Liberty { local($object,$edge) = @_; local ($initial,$final) = &ALF_GetBitLiterals($edge); local $libtype = &ALF_IsRisingEdge($initial,$final)? 'cell_rise' : &ALF_IsFallingEdge($initial,$final)? 'cell_fall' : undef; &ALF_ArithmeticModel2Liberty($object,$libtype); } sub ALF_Slewrate2Liberty { local($object,$edge) = @_; local ($initial,$final) = &ALF_GetBitLiterals($edge); local $libtype = &ALF_IsRisingEdge($initial,$final)? 'rise_transition' : &ALF_IsFallingEdge($initial,$final)? 'fall_transition' : undef; &ALF_ArithmeticModel2Liberty($object,$libtype); } sub ALF_Energy2Liberty { local($object,$edge) = @_; local ($initial,$final) = &ALF_GetBitLiterals($edge); local $libtype = &ALF_IsRisingEdge($initial,$final)? 'rise_power' : &ALF_IsFallingEdge($initial,$final)? 'fall_power' : 'power'; &ALF_ArithmeticModel2Liberty($object,$libtype); } sub ALF_SetupRecovery2Liberty { local($object,$edge) = @_; local ($initial,$final) = &ALF_GetBitLiterals($edge); local $libtype = &ALF_IsRisingEdge($initial,$final)? 'rise_constraint' : &ALF_IsFallingEdge($initial,$final)? 'fall_constraint' : undef; &ALF_ArithmeticModel2Liberty($object,$libtype); } sub ALF_HoldRemoval2Liberty { local($object,$edge) = @_; local ($initial,$final) = &ALF_GetBitLiterals($edge); local $libtype = &ALF_IsRisingEdge($initial,$final)? 'rise_constraint' : &ALF_IsFallingEdge($initial,$final)? 'fall_constraint' : undef; &ALF_ArithmeticModel2Liberty($object,$libtype); } ### lookup table data ### sub ALF_ArithmeticModelHeader2Liberty { local ($library,$models,$type,$rule) = @_; local $found = &CreateArray(); local %template = &ALF_FindArithmeticModelTableTemplates($models,$found); foreach $object (&Array($found)) { $ALF_LibertySyntax{$object} = 'group'; $ALF_LibertyName{$object} = $ALF_LibertyName{&ALF_CreateLibertyTableTemplate($library,$object,$type,$rule)}; } foreach $model (keys %template) { $ALF_LibertySyntax{$model} = 'group'; $ALF_LibertyName{$model} = $ALF_LibertyName{$template{$model}}; local $header = &ALF_FindMatchingObject($model,'HEADER'); $ALF_Hidden{$header} = 'Liberty' if defined($header); } } sub ALF_Map2LibertyDelayPowerTemplate { local($key) = @_; local $alftype = $ALF_Type{$key}; local $libtype; if (&StringMatch($alftype,'CAPACITANCE')) { local $delay = &ALF_FindMatchingObject(&ALF_FindAncestor($key,'VECTOR'),'DELAY'); local $pin = $ALF_Value{&ALF_FindMatchingObject($key,'PIN')}; local $refpin = $ALF_Value{&ALF_FindMatchingObject(&ALF_FindMatchingObject($delay,'TO'),'PIN')} if $delay; $libtype = (!$delay)? 'total_output_net_capacitance' : &StringMatch($refpin,$pin)? 'total_output_net_capacitance' : 'related_out_total_output_net_capacitance'; } elsif (&StringMatch($alftype,'SLEWRATE')) { local $model = $ALF_Parent{$ALF_Parent{$key}}; $libtype = &StringMatch($ALF_Type{$model},'ENERGY')? 'input_transition_time' : 'input_net_transition'; } $libtype; } sub ALF_Map2LibertyTimingConstraintTemplate { local($key) = @_; local $alftype = $ALF_Type{$key}; local $libtype; if (&StringMatch($alftype,'SLEWRATE')) { local $pin = &ALF_FindMatchingObject($key,'PIN'); local $cell = &ALF_FindAncestor($key,'CELL'); local $refpin = &ALF_FindMatchingObject($cell,'PIN',$ALF_Value{$pin}); local $signaltype = $ALF_Value{&ALF_FindMatchingObject($refpin,'SIGNALTYPE')}; $libtype = &StringMatch($signaltype,'data','address','set','clear')? 'constrained_pin_transition' : &StringMatch($signaltype,'clock')? 'related_pin_transition' : undef; } elsif (&StringMatch($alftype,'CAPACITANCE')) { $libtype = 'related_out_total_output_net_capacitance'; } $libtype; } sub ALF_Map2LibertyTransitionDegradationTemplate { local($key) = @_; local $alftype = $ALF_Type{$key}; local $libtype; if (&StringMatch($alftype,'SLEWRATE')) { $libtype = 'output_pin_transition'; } elsif (&StringMatch($alftype,'DELAY')) { $libtype = 'connect_delay'; } $libtype; } sub ALF_ArithmeticModel2Liberty { local($object,$libtype) = @_; if ($libtype) { $ALF_LibertySyntax{$object} = 'group'; $ALF_LibertyType{$object} = $libtype; local $value = $ALF_Value{$object}; local $table = &ALF_FindMatchingObject($object,'TABLE') unless $value; if ($value) { $ALF_LibertyName{$object} = 'scalar'; &ALF_CreateObject($object,undef,undef,undef, 'ALF_LibertySyntax', 'complex_attribute', 'ALF_LibertyType', 'values', 'ALF_LibertyValue', &CreateArray(&Doublequote($value)), ); } elsif ($table) { $ALF_Prepend{$object} = 1; local $array = $ALF_Value{$table}; local $keys = $ALF_Keys{$array}; local $index = &ArraySize($keys); foreach $key (&Array($keys)) { local $keyval = &AssocVal($ALF_KeyTable{$array},$key); $ALF_ArrayFormat{$keyval} = 0; &ALF_CreateObject($object,undef,undef,undef, 'ALF_LibertySyntax', 'complex_attribute', 'ALF_LibertyType', "index\_$index", 'ALF_LibertyValue', $keyval, ); $index -= 1; } $ALF_LibertySyntax{$table} = 'complex_attribute'; $ALF_LibertyType{$table} = 'values'; $ALF_LibertyValue{$table} = $ALF_Value{$table}; &ALF_HideAllChildren(&ALF_FindMatchingObject($object,'HEADER'),'Liberty'); } } } sub ALF_TrivialArithmeticModel2Liberty { local($object,$libtype,$default) = @_; local $value = $ALF_Value{$object}; if (defined($value)) { if (defined($default) && &StringMatch($value,$default)) { $ALF_Hidden{$object} = 'Liberty'; } elsif (&ALF_LexicalMatch('number',$value)) { $ALF_LibertySyntax{$object} = 'simple_attribute'; $ALF_LibertyType{$object} = $libtype; $ALF_LibertyValue{$object} = $value; } else { print("# ALF Data Warning:\tinvalid valuetype for arithmetic model:\t",&ALF_ObjectInfoText($object),"\n"); } &ALF_HideAllChildren($object,'Liberty'); } } 1;