def parse_lef(filename, tech_lef=None, look_for_cell=None, find_desired_cell_info=False): lef = {} with open(filename, 'r') as lef_file: search = False find_pin_info = False find_layer_info = False find_poly_coordinate = False find_rect_coordinate = False find_poly_info = False macro = None desired_macro = None macros = [] pin_name = '' for line in lef_file: if re.search(r'^\s*MACRO', line, flags=re.IGNORECASE): macro = None cell_name = re.search(r'MACRO (\w+)', line, flags=re.IGNORECASE) cell_name = cell_name.group(1) if cell_name != None or cell_name != '': search = True if look_for_cell != None: if cell_name == look_for_cell: find_desired_cell_info = True macro = cl.MACRO(cell_name) else: find_desired_cell_info = False if find_desired_cell_info: macro = cl.MACRO(cell_name) if search and re.match('^\s*END\s+' + re.escape(cell_name), line): if cell_name == look_for_cell: find_desired_cell_info = False desired_macro = macro if find_desired_cell_info: macros.append(macro) search = False if search: if re.search(r'SIZE\s*\d+\.?\d*\sBY', line): ## Search for the dimension of the cell size = re.search(r'SIZE (\d+\.?\d*) BY (\d+\.?\d*)', line) ## Input the dimension to the dictionary lef[cell_name] = {'x': size.group(1), 'y': size.group(2)} ## Insert the info to the class if look_for_cell != None: if cell_name == look_for_cell: macro.set_width(float(size.group(1))) macro.set_height(float(size.group(2))) if re.match(r'^\s*PIN\s+(\w+)', line) and find_desired_cell_info: pin_name = re.match(r'^\s*PIN\s+(\w+)', line).group(1) find_pin_info = True cl_pin = cl.MACRO_PIN(pin_name) if find_desired_cell_info and re.match( r'^\s*END\s+' + re.escape(pin_name), line) and find_pin_info: find_pin_info = False if find_pin_info: if re.match(r'^\s*DIRECTION\s+(\w+)\s+;', line): direction = re.match(r'\s*DIRECTION\s+(\w+)\s+;', line).group(1) if direction == 'INPUT' or direction == 'OUTPUT': find_layer_info = True cl_pin.set_direction(direction) lef[cell_name][pin_name] = [] else: find_layer_info = False if find_layer_info: if re.match(r'^\s*LAYER\s+(\w+)\s+;', line): metal = re.match(r'^\s*LAYER\s+(\w+)', line).group(1) if (tech_lef != None and tech_lef['Layer'][metal]['type'] != 'CUT') or metal == 'M1': find_poly_info = True coordinate = [] if re.match(r'^\s*END', line): find_poly_info = False if find_poly_info: if re.search('POLY', line): cl_pin._isRect = False find_poly_coordinate = True if re.search('RECT', line): cl_pin._isRect = True find_rect_coordinate = True if find_poly_coordinate: coordinate.extend( re.findall('([-+]?\d*\.?\d+)+', line)) if look_for_cell == cell_name: cl_pin.set_coordinate(coordinate) if find_rect_coordinate: rect_pattern = r'^\s*(RECT)\s+(\s*MASK\s*\d+\s*)?(\d*\.?\d+\s*)(\d*\.?\d+\s*)(\d*\.?\d+\s*)(\d*\.?\d+\s*)\s*;' coordinate = re.search(rect_pattern, line) coordinate = [coordinate.group(1),metal,coordinate.group(3),\ coordinate.group(4),coordinate.group(5),coordinate.group(6)] lef[cell_name][pin_name].append(coordinate) if len(coordinate) > 4: coordinate = coordinate[-4:] cl_pin.set_coordinate(coordinate) if re.search(';', line) and (find_rect_coordinate or find_poly_coordinate): if find_poly_coordinate: # Only store the PIN class that has coordinate data if len(coordinate) > 0: if look_for_cell == cell_name: cl_pin.convert_coordinate_to_Point( ) coordinate.insert(0, metal) coordinate.insert(0, 'POLY') lef[cell_name][pin_name].append( coordinate) if look_for_cell == cell_name: macro.set_pin(cl_pin) find_poly_coordinate = False find_rect_coordinate = False if desired_macro != None: # Process the data POX, POY, start_length = desired_macro.get_starting_point print(str(POX) + ' ' + str(POY) + ' ' + str(start_length)) return lef