parallaxsw / OpenSTA

GNU General Public License v3.0
52 stars 23 forks source link

Segfault when reading in Liberty file with missing `related_pin` in timing group #70

Closed akashlevy closed 3 months ago

akashlevy commented 3 months ago

Read issue title. I unfortunately cannot attach a full test case as the Liberty file is part of a proprietary PDK and I don't have direct access to it myself. However, I can give a (slightly redacted and demangled) backtrace from catchsegv that was sent to me by a customer facing the issue. The file+linenos appear to be incorrect but the function headers might be useful. The binary was compiled with -g flag on CentOS 7.

Backtrace:
opensta/liberty/Liberty.cc:2469(sta::LibertyCell::addTimingArcSet(sta::TimingArcSet*))[0x4badb1]
opensta/liberty/TimingArc.cc:195(sta::TimingArcSet::TimingArcSet(sta::LibertyCell*, sta::LibertyPort*, sta::LibertyPort*, sta::LibertyPort*, sta::TimingRole*, std::shared_ptr<sta::TimingArcAttrs>))[0x4d448f]
/opt/rh/devtoolset-8/root/usr/include/c++/8/bits/shared_ptr_base.h:727 (discriminator 2)(sta::LibertyBuilder::makeTimingArcSet(sta::LibertyCell*, sta::LibertyPort*, sta::LibertyPort*, sta::LibertyPort*, sta::TimingRole*, std::shared_ptr<sta::TimingArcAttrs>))[0x617536]
/opt/rh/devtoolset-8/root/usr/include/c++/8/bits/shared_ptr_base.h:727(sta::LibertyBuilder::makeMinPulseWidthArcs(sta::LibertyCell*, sta::LibertyPort*, sta::LibertyPort*, sta::LibertyPort*, sta::TimingRole*, std::shared_ptr<sta::TimingArcAttrs>))[0x618957]
/opt/rh/devtoolset-8/root/usr/include/c++/8/bits/shared_ptr_base.h:727(sta::LibertyBuilder::makeTimingArcs(sta::LibertyCell*, sta::LibertyPort*, sta::LibertyPort*, sta::LibertyPort*, std::shared_ptr<sta::TimingArcAttrs>, int))[0x6197fc]
/opt/rh/devtoolset-8/root/usr/include/c++/8/bits/shared_ptr_base.h:727(sta::LibertyReader::makeTimingArcs(sta::LibertyPort*, sta::LibertyPort*, sta::TimingGroup*))[0x5be5e7]
opensta/liberty/LibertyReader.cc:2273(sta::LibertyReader::makeTimingArcs(sta::LibertyPort*, sta::TimingGroup*))[0x5bc442]
opensta/liberty/LibertyReader.cc:2013 (discriminator 2)(sta::LibertyReader::makeTimingArcs(sta::PortGroup*))[0x5b4aee]
opensta/liberty/LibertyReader.cc:1944(sta::LibertyReader::finishPortGroups())[0x5b6ce2]
opensta/liberty/LibertyReader.cc:1917(sta::LibertyReader::endCell(sta::LibertyGroup*))[0x5aee97]
opensta/liberty/LibertyReader.cc:603(sta::LibertyReader::end(sta::LibertyGroup*))[0x5b873c]
/opt/rh/devtoolset-8/root/usr/include/c++/8/bits/stl_vector.h:1115(sta::libertyGroupEnd())[0x4c74b1]
opensta/liberty/LibertyParse.yy:76(LibertyParse_parse())[0x595764]
opensta/liberty/LibertyParser.cc:74(sta::parseLibertyFile(char const*, sta::LibertyGroupVisitor*, sta::Report*))[0x4c6cd4]
opensta/liberty/LibertyReader.cc:149(sta::LibertyReader::readLibertyFile(char const*, bool, sta::Network*))[0x5ae338]
opensta/liberty/LibertyReader.cc:58(sta::readLibertyFile(char const*, bool, sta::Network*))[0x5bb94c]
opensta/search/Sta.cc:680(sta::Sta::readLibertyFile(char const*, sta::Corner*, sta::MinMaxAll const*, bool))[0x5534e3]
opensta/search/Sta.cc:660(sta::Sta::readLiberty(char const*, sta::Corner*, sta::MinMaxAll const*, bool))[0x5535a0]
??:?(_Z16read_liberty_cmdPcPN3sta6CornerEPKNS0_9MinMaxAllEb)[0x448722]
StaAppTCL_wrap.cxx:?(_wrap_read_liberty_cmd)[0x46a904]
/lib64/libtcl8.5.so( 0x34eb2)[0x7f104a8baeb2]
/lib64/libtcl8.5.so( 0x7936c)[0x7f104a8ff36c]
/lib64/libtcl8.5.so(TclObjInterpProcCore 0x34d)[0x7f104a942a4d]
/lib64/libtcl8.5.so( 0x34eb2)[0x7f104a8baeb2]
/lib64/libtcl8.5.so( 0x7936c)[0x7f104a8ff36c]
/lib64/libtcl8.5.so( 0x81647)[0x7f104a907647]
/lib64/libtcl8.5.so(TclEvalObjEx 0x87)[0x7f104a8bc6b7]
/lib64/libtcl8.5.so( 0xbc27f)[0x7f104a94227f]
/lib64/libtcl8.5.so( 0x34eb2)[0x7f104a8baeb2]
/lib64/libtcl8.5.so( 0x7936c)[0x7f104a8ff36c]
/lib64/libtcl8.5.so( 0x81647)[0x7f104a907647]
/lib64/libtcl8.5.so(TclEvalObjEx 0x87)[0x7f104a8bc6b7]
/lib64/libtcl8.5.so( 0x3c1d0)[0x7f104a8c21d0]
/lib64/libtcl8.5.so( 0x34eb2)[0x7f104a8baeb2]
/lib64/libtcl8.5.so( 0x7936c)[0x7f104a8ff36c]
/lib64/libtcl8.5.so( 0x81647)[0x7f104a907647]
/lib64/libtcl8.5.so(TclEvalObjEx 0x87)[0x7f104a8bc6b7]
/lib64/libtcl8.5.so( 0x3ff00)[0x7f104a8c5f00]
/lib64/libtcl8.5.so( 0x34eb2)[0x7f104a8baeb2]
/lib64/libtcl8.5.so( 0x7936c)[0x7f104a8ff36c]
/lib64/libtcl8.5.so(TclObjInterpProcCore 0x34d)[0x7f104a942a4d]
/lib64/libtcl8.5.so( 0x34eb2)[0x7f104a8baeb2]
/lib64/libtcl8.5.so( 0x7936c)[0x7f104a8ff36c]
/lib64/libtcl8.5.so(TclObjInterpProcCore 0x34d)[0x7f104a942a4d]
/lib64/libtcl8.5.so( 0x34eb2)[0x7f104a8baeb2]
/lib64/libtcl8.5.so( 0x35f1e)[0x7f104a8bbf1e]
/lib64/libtcl8.5.so(Tcl_EvalEx 0x16)[0x7f104a8bc446]
/lib64/libtcl8.5.so(Tcl_Eval 0x15)[0x7f104a8bc465]
opensta/app/StaMain.cc:98(sta::sourceTclFile(char const*, bool, bool, Tcl_Interp*))[0x475f1f]
Main.cc:?(_ZL10tclAppInitP10Tcl_Interp)[0x42ff8a]
/lib64/libtcl8.5.so(Tcl_Main 0x1e5)[0x7f104a92a475]
??:?(main)[0x42e2ed]
/lib64/libc.so.6(__libc_start_main 0xe5)[0x7f1049794d85]
??:?(_start)[0x42fd25]

The customer sent me an example min_pulse_width constraint from the problematic Liberty file. Not sure yet if this is the exact one causing the segfault (UPDATE: it is).

        timing () {                  
            timing_type     : min_pulse_width ;

            when            : "!SD & !DSLP & (!DFTBYP & !SE) & ((!BIST & !REB) | (BIST & !REBM))" ;
            sdf_cond        : "when_sram_read" ;                               

            rise_constraint("clktran_constraint_template") { 
                values ( "0.237832, 0.238871, 0.241091, 0.243913, 0.250000" ) ;
            }                                   
            fall_constraint("clktran_constraint_template") {
                values ( "0.237832, 0.238871, 0.241091, 0.243913, 0.250000" ) ;
            }                    
        }

Sorry that I can't provide a minimal reproducible example yet. Wanted to create this issue to report this bug, in case there are any immediate insights into why this might be happening. I'll be looking into building a small example testcase over the next week (assuming it can't be resolved quickly from inspecting the backtrace).

akashlevy commented 3 months ago

Update: I have a minimal Liberty file that reproduces the problem. It happens when the related_pin/related_bus_pin is missing from the timing group and timing_type is min_pulse_width. Have not checked if it happens for other timing_types. It seems other STA tools can infer the related_pin to be self pin (CK in example below) when not specified, and certain foundries have the related_pin missing for clock pins. However, this causes OpenSTA to segfault (with a warning).

Here's the minimal example:

/* Autogenerated subset of 5 cells from library below -- DO NOT EDIT MANUALLY */
/* 
* ******************************************************************************
* *                                                                            *
* *                   Copyright (C) 2004-2011, Nangate Inc.                    *
* *                           All rights reserved.                             *
* *                                                                            *
* * Nangate and the Nangate logo are trademarks of Nangate Inc.                *
* *                                                                            *
* * All trademarks, logos, software marks, and trade names (collectively the   *
* * "Marks") in this program are proprietary to Nangate or other respective    *
* * owners that have granted Nangate the right and license to use such Marks.  *
* * You are not permitted to use the Marks without the prior written consent   *
* * of Nangate or such third party that may own the Marks.                     *
* *                                                                            *
* * This file has been provided pursuant to a License Agreement containing     *
* * restrictions on its use. This file contains valuable trade secrets and     *
* * proprietary information of Nangate Inc., and is protected by U.S. and      *
* * international laws and/or treaties.                                        *
* *                                                                            *
* * The copyright notice(s) in this file does not indicate actual or intended  *
* * publication of this file.                                                  *
* *                                                                            *
* *   NGLibraryCharacterizer, v2011.01-HR04-2011-01-19 - build 201102050200    *
* *                                                                            *
* ******************************************************************************
*
* Spice engine            : Nanspice v2011.01-HR04-2011-01-19-1102050200
* Liberty export type     : conditional
*
* Characterization Corner : fast
* Process                 : FastFast
* Temperature             : 0C
* Voltage                 : 1.25V
*
****************************************************************************/

library (NangateOpenCellLibrary) {

  /* Documentation Attributes */
  date                          : "Thu 10 Feb 2011, 18:11:35";
  revision                      : "revision 1.0";
  comment                       : "Copyright (c) 2004-2011 Nangate Inc. All Rights Reserved.";

  /* General Attributes */
  technology                      (cmos);
  delay_model                   : table_lookup;
  in_place_swap_mode            : match_footprint;
  library_features                (report_delay_calculation,report_power_calculation);

  /* Units Attributes */
  time_unit                     : "1ns";
  leakage_power_unit            : "1nW";
  voltage_unit                  : "1V";
  current_unit                  : "1mA";
  pulling_resistance_unit       : "1kohm";
  capacitive_load_unit            (1,ff);

  /* Operation Conditions */
  nom_process                   : 1.00;
  nom_temperature               : 0.00;
  nom_voltage                   : 1.25;

  voltage_map (VDD,1.25);
  voltage_map (VSS,0.00);

  define(process_corner, operating_conditions, string);
  operating_conditions (fast) {
    process_corner  : "FastFast";
    process         : 1.00;
    voltage         : 1.25;
    temperature     : 0.00;
    tree_type       : balanced_tree;
  }
  default_operating_conditions : fast;

  /* Threshold Definitions */
  slew_lower_threshold_pct_fall     : 30.00 ;
  slew_lower_threshold_pct_rise     : 30.00 ;
  slew_upper_threshold_pct_fall     : 70.00 ;
  slew_upper_threshold_pct_rise     : 70.00 ;
  slew_derate_from_library          : 1.00 ;
  input_threshold_pct_fall          : 50.00 ;
  input_threshold_pct_rise          : 50.00 ;
  output_threshold_pct_fall         : 50.00 ;
  output_threshold_pct_rise         : 50.00 ;
  default_leakage_power_density     : 0.00 ;
  default_cell_leakage_power        : 0.00 ;

  /* Default Pin Attributes */
  default_inout_pin_cap             : 1.000000;
  default_input_pin_cap             : 1.000000;
  default_output_pin_cap            : 0.000000;
  default_fanout_load               : 1.000000;
  default_max_transition            : 0.146240;

  lu_table_template (Pulse_width_3) {
    variable_1 : related_pin_transition;
    index_1 ("0.0010,0.0020,0.0030");
  }

  /******************************************************************************************
   Module           : DFF
   Cell Description : Pos.edge D-Flip-Flop with drive strength X1
  *******************************************************************************************/

  cell (DFF) {

    drive_strength      : 1;

    ff ("IQ" , "IQN") {
        next_state          : "D";
        clocked_on          : "CK";
    }

    area                : 4.522000;
    pg_pin(VDD) {
        voltage_name : VDD;
        pg_type      : primary_power;
    }
    pg_pin(VSS) {
        voltage_name : VSS;
        pg_type      : primary_ground;
    }

    pin (D) {
        direction       : input;
        related_power_pin       : "VDD";
        related_ground_pin      : "VSS";
        capacitance     : 1.157568;
    }

    pin (CK) {
        direction       : input;
        related_power_pin       : "VDD";
        related_ground_pin      : "VSS";
        clock           : true;
        capacitance     : 0.966728;

        timing () {
            timing_type    : min_pulse_width;
            fall_constraint(Pulse_width_3) {
                index_1 ("0.000932129,0.0331496,0.146240");
                values ("0.025656,0.039623,0.146386");
            }
            rise_constraint(Pulse_width_3) {
                index_1 ("0.000932129,0.0331496,0.146240");
                values ("0.029624,0.033183,0.146386");
            }
        }
    }

    pin (Q) {
        direction       : output;
        related_power_pin   : "VDD";
        related_ground_pin  : "VSS";
        max_capacitance     : 60.730000;
        function        : "IQ";
    }

    pin (QN) {
        direction       : output;
        related_power_pin   : "VDD";
        related_ground_pin  : "VSS";
        max_capacitance     : 60.272200;
        function        : "IQN";
    }
  }
}
/*
* End of file
*/

Output on my MacBook Pro M2:

akashlevy@Akashs-MacBook-Pro-M2-3 preqorsor-dev % ./opensta/app/sta
OpenSTA 2.6.0 c51fe826d6 Copyright (c) 2024, Parallax Software, Inc.
License GPLv3: GNU GPL version 3 <http://gnu.org/licenses/gpl.html>

This is free software, and you are free to change and redistribute it
under certain conditions; type `show_copying' for details. 
This program comes with ABSOLUTELY NO WARRANTY; for details type `show_warranty'.
% read_liberty test.lib
Warning: test.lib line 140, timing group missing related_pin/related_bus_pin.
zsh: segmentation fault  ./opensta/app/sta
akashlevy commented 3 months ago

I think the fix should be to infer that the related_pin is the same pin if not specified.

A slightly worse but perhaps easier alternative to implement would be to not make the timing arcs if the timing group is missing related_pin/related_bus_pin.

jjcherry56 commented 3 months ago

righto 5261a2a9 liberty min_pulse_width missing related_pin

akashlevy commented 3 months ago

Thanks a lot

jjcherry56 commented 3 months ago

No, thank YOU. You did all the work.