### timing semantics ### sub ALF_IsPositiveUnate { local($fromedge,$toedge) = @_; &ALF_IsRisingEdge($fromedge) && &ALF_IsRisingEdge($toedge) || &ALF_IsFallingEdge($fromedge) && &ALF_IsFallingEdge($toedge); } sub ALF_IsNegativeUnate { local($fromedge,$toedge) = @_; &ALF_IsFallingEdge($fromedge) && &ALF_IsRisingEdge($toedge) || &ALF_IsRisingEdge($fromedge) && &ALF_IsFallingEdge($toedge); } sub ALF_IsRisingEdge { local($edge) = @_; local ($initial,$final) = &ALF_GetBitLiterals($edge); (&ALF_LogicalValue($initial) ne &ALF_LogicalValue($final)) && ( (&ALF_LogicalValue($initial) eq 'false') || (&ALF_LogicalValue($final) eq 'true') ); } sub ALF_IsFallingEdge { local($edge) = @_; local ($initial,$final) = &ALF_GetBitLiterals($edge); (&ALF_LogicalValue($initial) ne &ALF_LogicalValue($final)) && ( (&ALF_LogicalValue($initial) eq 'true') || (&ALF_LogicalValue($final) eq 'false') ); } sub ALF_IsThreeStateEnable { local($edge) = @_; local ($initial,$final) = &ALF_GetBitLiterals($edge); (&ALF_DriveStrength($initial) eq 'zero') && (&ALF_DriveStrength($final) ne 'zero'); } sub ALF_IsThreeStateDisable { local($edge) = @_; local ($initial,$final) = &ALF_GetBitLiterals($edge); (&ALF_DriveStrength($initial) ne 'zero') && (&ALF_DriveStrength($final) eq 'zero'); } ### access to timing data ### sub ALF_TimingArc { local($object) = @_; local $vector = &ALF_FindAncestor($object,'VECTOR'); local $expression = $ALF_Expression{$vector}; local $from = &ALF_FindMatchingObject($object,'FROM'); local ($fromedge,$frompin) = &ALF_TimingEdge($from,$expression) if defined($from); local $to = &ALF_FindMatchingObject($object,'TO'); local ($toedge,$topin) = &ALF_TimingEdge($to,$expression) if defined($to); print("# ALF Data Error:\tobject $object ",&ALF_ObjectInfoText($object)," has incomplete timing arc\n") unless (defined($fromedge) && defined($frompin) && defined($toedge) && defined ($topin)); ($fromedge,$frompin,$toedge,$topin); } sub ALF_TimingEdge { local($object,$expression) = @_; local $pin_annotation = &ALF_FindMatchingObject($object,'PIN'); local $edge_number = &ALF_FindMatchingObject($object,'EDGE_NUMBER'); local ($pin,$edge); if (defined($pin_annotation)) { $pin = $ALF_Value{$pin_annotation}; $edge = &ALF_FindEdgeLiteral($expression,$pin,$edge_number); } ($edge,$pin); } sub ALF_TimingThresholds { local($parent,$type) = @_; local $model = &ALF_FindMatchingObject($parent,$type,0); local ($from_rise,$from_fall,$to_rise,$to_fall); if (defined($model)) { local $from = &ALF_FindMatchingObject($model,'FROM'); ($from_rise,$from_fall) = &ALF_TimingThreshold($from); local $to = &ALF_FindMatchingObject($model,'TO'); ($to_rise,$to_fall) = &ALF_TimingThreshold($to); } ($from_rise,$from_fall,$to_rise,$to_fall); } sub ALF_TimingThreshold { local($parent) = @_; local $threshold = &ALF_FindMatchingObject($parent,'THRESHOLD'); local ($rise,$fall); if (defined($threshold)) { $rise = &ALF_FindMatchingObject($threshold,'RISE'); $fall = &ALF_FindMatchingObject($threshold,'FALL'); } defined($ALF_Value{$threshold})? ($threshold,$threshold) : ($rise,$fall); } ### Liberty timing semantics ### sub ALF_LibertyTimingAnnotations { local(@timing_objects) = @_; local ($combinational,$three_state_enable,$three_state_disable,$rising_edge,$falling_edge,$preset,$clear); local ($setup_rising,$setup_falling); local ($hold_rising,$hold_falling); local ($recovery_rising,$recovery_falling); local ($removal_rising,$removal_falling); foreach $object (@timing_objects) { local $alf_type = $ALF_Type{$object}; if (&StringMatch($alf_type,'DELAY')) { $combinational = 1; $three_state_enable = 1; $three_state_disable = 1; $rising_edge = 1; $falling_edge = 1; $preset = 1; $clear = 1; } elsif (&StringMatch($alf_type,'SETUP')) { $setup_rising = 1; $setup_falling = 1; } elsif (&StringMatch($alf_type,'HOLD')) { $hold_rising = 1; $hold_falling = 1; } elsif (&StringMatch($alf_type,'RECOVERY')) { $recovery_rising = 1; $recovery_falling = 1; } elsif (&StringMatch($alf_type,'REMOVAL')) { $removal_rising = 1; $removal_falling = 1; } } local $positive_unate = 1; local $negative_unate = 1; foreach $object (@timing_objects) { local ($fromedge,$frompin,$toedge,$topin) = &ALF_TimingArc($object); $positive_unate = $positive_unate && &ALF_IsPositiveUnate($fromedge,$toedge); $negative_unate = $negative_unate && &ALF_IsNegativeUnate($fromedge,$toedge); local $alf_type = $ALF_Type{$object}; if (&StringMatch($alf_type,'DELAY')) { $three_state_enable = $three_state_enable && &ALF_IsThreeStateEnable($toedge); $three_state_disable = $three_state_disable && &ALF_IsThreeStateDisable($toedge); $rising_edge = $rising_edge && &ALF_IsRisingEdge($fromedge); $falling_edge = $falling_edge && &ALF_IsFallingEdge($fromedge); $preset = $preset && &ALF_IsRisingEdge($toedge); $clear = $clear && &ALF_IsFallingEdge($toedge); #print("delay($fromedge $frompin -> $toedge $topin):\tcomb=$combinational\t3enb=$three_state_enable\t3dis=$three_state_disable\trise=$rising_edge\tfall=$falling_edge\tpreset=$preset\tclear=$clear\n"); } elsif (&StringMatch($alf_type,'SETUP')) { $setup_rising = $setup_rising && &ALF_IsRisingEdge($toedge); $setup_falling = $setup_falling && &ALF_IsFallingEdge($toedge); #print("setup($fromedge $frompin -> $toedge $topin):\trise=$setup_rising\tfall=$setup_falling\n"); } elsif (&StringMatch($alf_type,'HOLD')) { $hold_rising = $hold_rising && &ALF_IsRisingEdge($fromedge); $hold_falling = $hold_falling && &ALF_IsFallingEdge($fromedge); #print("hold($fromedge $frompin -> $toedge $topin):\trise=$hold_rising\tfall=$hold_falling\n"); } elsif (&StringMatch($alf_type,'RECOVERY')) { $recovery_rising = $recovery_rising && &ALF_IsRisingEdge($toedge); $recovery_falling = $recovery_falling && &ALF_IsFallingEdge($toedge); #print("recovery($fromedge $frompin -> $toedge $topin):\trise=$recovery_rising\tfall=$recovery_falling\n"); } elsif (&StringMatch($alf_type,'REMOVAL')) { $removal_rising = $removal_rising && &ALF_IsRisingEdge($fromedge); $removal_falling = $removal_falling && &ALF_IsFallingEdge($fromedge); #print("removal($fromedge $frompin -> $toedge $topin):\trise=$removal_rising\tfall=$removal_falling\n"); } } local $timing_type = $three_state_enable? 'three_state_enable' : $three_state_disable? 'three_state_disable' : $preset? 'preset' : $clear? 'clear' : $rising_edge? 'rising_edge' : $falling_edge? 'falling_edge' : $setup_rising? 'setup_rising' : $setup_falling? 'setup_falling' : $hold_rising? 'hold_rising' : $hold_falling? 'hold_falling' : $recovery_rising? 'recovery_rising' : $recovery_falling? 'recovery_falling' : $removal_rising? 'removal_rising' : $removal_falling? 'removal_falling' : $combinational? 'combinational' : undef; local $timing_sense = ( $positive_unate && !$negative_unate)? 'positive_unate' : ( $negative_unate && !$positive_unate)? 'negative_unate' : (!$positive_unate && !$negative_unate)? 'non_unate' : undef; ($timing_type,$timing_sense); } 1;