Example #1
0
def parse_tech_lef(filename, find_via=False):
    techLEF_dict = {}
    metal_layer = 1

    with open(filename) as f:
        start_parsing_layer_info = False
        start_parsing_via_info = False
        find_cutclass = False
        find_open_quote_cutclass = False
        find_layer_cut_info = False
        find_layer_routing_info = False
        find_via_dimesion = False

        storage = []

        for line in f:
            if re.match(r'^LAYER\s+(\w+)', line):
                layer_name = re.match(r'^LAYER\s+(\w+)', line).group(1)
                start_parsing_layer_info = True

            # PART I: Parsing the information of the metal layer
            if start_parsing_layer_info:
                if re.match(r'^\s+TYPE\s+\w+\s*;', line):
                    type_of_layer = re.match(r'^\s+TYPE\s+(\w+)\s*;',
                                             line).group(1)
                    if type_of_layer == 'CUT':
                        find_layer_cut_info = True  # Set the Flag

                        # initialize the dictionary
                        if not 'Layer' in techLEF_dict:
                            techLEF_dict['Layer'] = {}
                        techLEF_dict['Layer'][layer_name] = {
                            'type': type_of_layer
                        }
                        continue

                    if type_of_layer == 'ROUTING':
                        find_layer_routing_info = True
                        cur_ml = cl.LEF_Metal_Routing(layer=layer_name,
                                                      layer_type=type_of_layer,
                                                      layer_number=metal_layer)
                        metal_layer += 1
                        continue

                # PART IA: Get the information of CUT layers
                if find_layer_cut_info:
                    if re.match(r'^\s*PROPERTY\s+LEF58_CUTCLASS', line):
                        find_cutclass = True

                    if find_cutclass:
                        if re.search(r'"',
                                     line) and not find_open_quote_cutclass:
                            find_open_quote_cutclass = True

                        elif re.search(r'"',
                                       line) and find_open_quote_cutclass:
                            find_open_quote_cutclass = False

                        if re.search(r';',
                                     line) and not find_open_quote_cutclass:
                            find_cutclass = False

                        if find_open_quote_cutclass:
                            if re.match('^\s+CUTCLASS\s+\w+', line):
                                cutclass = re.match(r'^\s+CUTCLASS\s+(\w+)',
                                                    line)
                                # Initialize the class to store the info
                                cur_ml = cl.LEF_Metal_Cut(
                                    layer=layer_name, layer_type=type_of_layer)
                                cur_ml.set_layerClassName(cutclass.group(1))
                                cur_ml.set_cutClass(True)

                            if re.search(r'\s+WIDTH\s+([-+]?\d*\.\d+)', line):
                                width = re.search(
                                    r'\s+WIDTH\s+([-+]?\d*\.\d+)', line)
                                cur_ml.set_viaWidth(width.group(1))

                            if re.search(r'\s+LENGTH\s+([-+]?\d*\.\d+|\w+)',
                                         line):
                                length = re.search(
                                    r'\s+LENGTH\s+([-+]?\d*\.\d+)', line)
                                cur_ml.set_viaLength(length.group(1))

                            if re.search(r'\s+CUTS\s+([-+]?\d*\.\d+|\w+)',
                                         line):
                                cuts = re.search(r'\s+CUTS\s*(\d+)', line)
                                cur_ml.set_viaCuts(cuts.group(1))

                            if re.search(r';', line):
                                storage.append(cur_ml)

                    if re.match(r'^\s*WIDTH\s+([-+]?\d*\.\d+)', line):
                        wid = re.search(r'^\s*WIDTH\s+([-+]?\d*\.\d+)\s*;',
                                        line)
                        cur_ml = cl.LEF_Metal_Cut(layer=layer_name,
                                                  layer_type=type_of_layer)
                        cur_ml.set_viaWidth(wid.group(1))
                        storage.append(cur_ml)

                    if start_parsing_layer_info and re.match(
                            r'^\s*END\s+' + re.escape(layer_name), line):
                        start_parsing_layer_info = False
                        find_layer_cut_info = False

                # PART IB: Get the information of ROUTING layers
                if find_layer_routing_info:
                    if re.match('^\s+DIRECTION\s+\w+', line):
                        direction = re.match(r'^\s+DIRECTION\s+(\w+)\s+;',
                                             line)
                        cur_ml.set_layerDirection(direction.group(1))

                    if re.match('^\s+WIDTH\s+([-+]?\d*\.\d+)\s+;', line):
                        width = re.match(r'^\s+WIDTH\s+([-+]?\d*\.\d+)', line)
                        cur_ml.set_layerWidth(width.group(1))

                    if re.match('^\s+PITCH\s+([-+]?\d*\.\d+)\s+;', line):
                        pitch = re.match(r'^\s+PITCH\s+([-+]?\d*\.\d+|\w+)',
                                         line)
                        cur_ml.set_layerPitch(pitch.group(1))

                    if re.match('^\s+SPACING\s+([-+]?\d*\.\d+)\s+;', line):
                        spacing = re.match(
                            r'^\s+SPACING\s+([-+]?\d*\.\d+|\w+)', line)
                        cur_ml.set_layerSpacing(spacing.group(1))

                    if re.match('^\s+TYPE\s+\w+\s*;', line):
                        check = re.match('^\s+TYPE\s+(\w+)\s*;', line).group(1)
                        if check == 'MIMCAP' or check == 'PASSIVATION' or check == 'HIGHR' or check == 'TSV':
                            start_parsing_layer_info = False
                            find_layer_routing_info = False

                    if start_parsing_layer_info and re.match(
                            r'^\s*END\s+' + re.escape(layer_name), line):
                        start_parsing_layer_info = False
                        find_layer_routing_info = False
                        storage.append(cur_ml)


#             PART II: Parsing the information of VIA section --> # of cuts
            if re.match(r'^\s*VIA\s+(\w+)', line):
                start_parsing_via_info = True
                via_name = re.match(r'^\s*VIA\s+(\w+)', line).group(1)
                cur_via = cl.LEF_VIA_Info(via_name=via_name)

            if start_parsing_via_info and re.match(
                    r'^\s*END\s+' + re.escape(via_name) + '', line):
                start_parsing_via_info = False
                cur_via.set_viaCuts(
                    compute_via_number_of_cuts(cur_via, techLEF_dict))
                storage.append(cur_via)

            if start_parsing_via_info:
                if re.match(r'^\s+LAYER\s+(\w+)\s+;', line):
                    layer = re.match(r'\s+LAYER\s+(\w+)\s+;', line).group(1)
                    if techLEF_dict['Layer'][layer]['type'] == 'CUT':
                        find_via_dimesion = True
                        cur_via.set_viaCutLayer(layer)
                    else:
                        cur_via.set_viaLayerAssignemnt(layer, techLEF_dict)
                        find_via_dimesion = False

                # If the CUT layer is detected
                if find_via_dimesion:
                    if re.match(r'^\s+RECT\s+.+;$', line):
                        pin_dimension = re.findall('([-+]?\d*\.\d+)+', line)
                        cur_via.set_viaDimension(pin_dimension)

            if len(storage) != 0:
                convert_techLEF_dictionary(storage, techLEF_dict)
                storage.clear()

        # Function to get the list of via used in the calibration script
        if find_via:
            find_via_for_each_layer(techLEF_dict)

        else:
            return techLEF_dict