石小疯 发表于 2025-3-18 06:17:06

DFT mode下hard phy STA Nopath

hard Phy boundary No Path

1. shift mode;

shift cornor出现No Path的;
PHY SI SO在shift mode必须有timing的path; 展示为No constrained path;
check step:

report_timing -though
NO constrained path
set timing_report_unconstrained true
report again
https://i-blog.csdnimg.cn/direct/390eb4de5f74415f9481e541ccfc656e.png
you will get a potential path;
get the clock of startpiont
https://i-blog.csdnimg.cn/direct/f9ffc53f244049a3bad51e9516f40ebc.png
now the no path reason would be two case:

[*]start point & end point is in two difference clock group;
[*]Lib is no include the timing arc of this pin;
check the lib:
https://i-blog.csdnimg.cn/direct/bce45dd3c2e144e2b1c2f554758a4ec9.png
发现在shift mode吧 bypass func的lib也读入了; 通过remove lib 确认最终读如的lib:
https://i-blog.csdnimg.cn/direct/b67173ccab574c41b599a40d4eb8a7b7.png
重新读入lib, shift path 出现;
2.dc capture mode

同样发现 hard phy SI SO的出现 no path;

[*]在DC capture mode 本身是不会颠末SI D path; 所以SI Q path不存在本身也是合理的;(结论是否正确)
[*]存在的Path 为bypass 的pass ,是由于同属一个clock group ,DFT未插lock up latch导致; Path 为 true path, 须要后端修;
https://i-blog.csdnimg.cn/direct/b8f7fd3d330849cda51af5e4df486918.png
其他非SI SO pin的no path;
优先查看Lib中在此mode是否存在 timing arc;
附加处理lib的脚本;

import re
def read_pinlist(pinlist_file):
    """
    Read pinlist from a text file, where each line contains one pin_name.

    Parameters:
      pinlist_file (str): Path to the pinlist file.

    Returns:
      list: A list of pin_names.
    """
    try:
      with open(pinlist_file, 'r') as f:
            # Read lines, strip whitespace, and skip empty lines
            pinlist =
      return pinlist
    except FileNotFoundError:
      print(f"Error: File {pinlist_file} not found")
      return []
def parse_lib(lib_content):
    """
    Parse the lib file content and return a dictionary with pin_name as keys and their corresponding timing block modes as values.

    Parameters:
      lib_content (str): The text content of the lib file.

    Returns:
      dict: A dictionary containing pin_name and its timing block modes.
    """
    pin_dict = {}
    # Regular expression to match pin blocks
    pin_pattern = r'pin\((.*?)\)\s*{([^{}]*)}'
    pin_matches = re.findall(pin_pattern, lib_content, re.DOTALL)
   
    for pin_match in pin_matches:
      # Extract pin_name and remove leading/trailing spaces and quotes
      pin_name = pin_match.strip().strip('"')
      pin_content = pin_match
      
      # Match timing blocks
      timing_pattern = r'timing\(\)\s*{([^{}]*)}'
      timing_matches = re.findall(timing_pattern, pin_content, re.DOTALL)
      
      modes = []
      for timing_match in timing_matches:
            timing_content = timing_match
            # Match mode field
            mode_pattern = r'mode\(etm_mode\s*,\s*"([^"]*)"\s*\);'
            mode_match = re.search(mode_pattern, timing_content)
            if mode_match:
                mode_name = mode_match.group(1).strip()# Remove leading/trailing spaces from mode_name
                modes.append(mode_name)
      
      pin_dict = modes
   
    return pin_dict

def check_pins(pinlist, pin_dict):
    """
    Check the status of each pin_name in pinlist based on the lib file and print the results.

    Parameters:
      pinlist (list): A list of pin_names to check.
      pin_dict (dict): A dictionary parsed from the lib file containing pin information.
    """
    for pin_name in pinlist:
      if pin_name not in pin_dict:
            print(f"{pin_name}: NO pin_name")
      else:
            modes = pin_dict
            if not modes:
                print(f"{pin_name}: NO timing arc")
            elif "stuckat_cap" not in modes:
                print(f"{pin_name}: NO stuckat_cap mode")
            else:
                print(f"{pin_name}: Exist stuckat_cap mode")

def main():
    # Example lib file path (modify according to actual path)
    lib_file_path = "lib.txt"
    try:
      with open(lib_file_path, "r") as f:
            lib_content = f.read()
    except FileNotFoundError:
      print(f"Error: File {lib_file_path} not found")
      return
   
    # Parse the lib file
    pin_dict = parse_lib(lib_content)
   
    # Example pinlist (modify according to actual needs)
    pinlist = ["pin1", "pin2", "pin3", "pin4"]
   
    # Check and print results
    check_pins(pinlist, pin_dict)

if __name__ == "__main__":
    main()

import re

def parse_lib(lib_content):
    """Parse the lib file content and return a dictionary with pin_name as keys and their corresponding pin content as values."""
    pins = {}
    lines = lib_content.split('\n')
    current_pin = None
    pin_content = []
    brace_level = 0
    collecting = False

    for line in lines:
      stripped = line.strip()
      if not collecting and stripped.startswith('pin('):
            # Extract pin name
            pin_start = stripped.find('(') + 1
            pin_end = stripped.find(')')
            if pin_end == -1:
                continue# Skip if format is incorrect
            current_pin = stripped.strip()
            brace_start = stripped.find('{', pin_end)
            if brace_start != -1:
                brace_level = 1
                collecting = True
                # Add the first line content (if any)
                rest = stripped.strip()
                if rest:
                  pin_content.append(rest)
      elif collecting:
            # Calculate brace level
            brace_level += line.count('{')
            brace_level -= line.count('}')
            
            if brace_level > 0:
                pin_content.append(line)
            else:
                collecting = False
                pins = '\n'.join(pin_content)
                current_pin = None
                pin_content = []
    return pins

def analyze_pin(pin_content):
    """Analyze the content of a single pin and return its status."""
    # Check if there are timing blocks
    timing_blocks = []
    in_timing = False
    current_block = []
    brace_level = 0
   
    for line in pin_content.split('\n'):
      stripped = line.strip()
      if not in_timing and stripped.startswith('timing('):
            in_timing = True
            brace_level = 0
            current_block = []
      
      if in_timing:
            current_block.append(line)
            brace_level += line.count('{')
            brace_level -= line.count('}')
            
            if brace_level <= 0:
                in_timing = False
                timing_blocks.append('\n'.join(current_block))
   
    if not timing_blocks:
      return "NO timing arc"
   
    # Check if any timing block contains stuckat_cap mode
    pattern = re.compile(r'mode\s*\(\s*etm_mode\s*,\s*"\s*stuckat_cap\s*"\s*\)')
    for block in timing_blocks:
      if pattern.search(block):
            return "OK"
   
    return "NO stuckat_cp mode"

def main(pinlist_file, lib_file):
    with open(lib_file, 'r') as f:
      content = f.read()
   
    pins = parse_lib(content)
    pinlist= read_pinlist(pinlist_file);
    if not pinlist:
      print("Pinlist is empty or file not exist");
      return
      
    for pin_name in pinlist:
      if pin_name not in pins:
            print(f"{pin_name}: Not found")
            continue
      
      status = analyze_pin(pins)
      print(f"{pin_name}: {status}")

# Example usage
if __name__ == "__main__":
    pinlist_file = "./file_name"# Replace with actual pin list
    lib_file = "your_lib.lib"         # Replace with actual lib file path
    main(pinlist, lib_file)

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
页: [1]
查看完整版本: DFT mode下hard phy STA Nopath