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
Example #2
0
def def_parser(def_file,
               pins,
               nets,
               cell_coor_dict,
               load_cap_dict,
               cell_dimension,
               buildPath=True):
    print('# READING DEF')
    with open(def_file) as f:
        blocks = []
        mapping_number = 1

        # Parsing Components Section
        parsing_component = False
        comp_syn = False
        cur_comp = []

        # NET BOOLEAN
        find_net = False
        find_data = False

        # PIN BOOLEAN
        find_pin = False
        pin_info = False

        # VIAS BOOLEAN
        find_vias = False
        via_info = False

        for line in f:
            """ HEADER SECTION"""
            # Finding the PER UNIT VALUE
            if re.search('UNITS DISTANCE MICRONS', line, flags=re.IGNORECASE):
                data = re.findall(r'\d+', line)
                glob.UNIT_DISTANCE = (int(data[0]))

            if re.match('^VERSION\s*(\d+\.?\d*)\s*[;]', line):
                def_version = re.match('^VERSION\s*(\d+\.?\d*)\s*[;]',
                                       line).group(1)

            if re.match('^DIVIDERCHAR\s*["](.+)["]\s*[;]', line):
                glob.DIVIDER = re.match('^DIVIDERCHAR\s*["](.+)["]\s*[;]',
                                        line).group(1)

            if re.match('^BUSBITCHARS\s*["](.+)["]\s*[;]', line):
                glob.BUS_CHAR = re.match('^BUSBITCHARS\s*["](.+)["]\s*[;]',
                                         line).group(1)

            if re.match('^DESIGN\s*\w+\s*[;]', line):
                glob.DESIGN = re.match('^DESIGN\s*(\w+)\s*[;]', line).group(1)
            """" END HEADER SECTION """
            """FILLING THE FIRST PART OF THE RECT CLASS"""
            if re.match('^[\t ]*COMPONENTS \d+', line, flags=re.IGNORECASE):
                parsing_component = True
                continue

            if re.match('^[\t ]*END COMPONENTS', line, flags=re.IGNORECASE):
                parsing_component = False
                # Create dictionary that contains all the COMPONENTS info
                create_block_dict(blocks, load_cap_dict, cell_dimension,
                                  cell_coor_dict)
                continue

            if parsing_component:
                if re.match('^[\t ]*-[\t ]+\w+[\t ]+\w+', line):
                    comp_name = re.search(r'[\t ]*-[\t ]+(\w+)[\t ]+(\w+)',
                                          line)
                    cur_comp = cl.Component(name=comp_name.group(1),
                                            cell=comp_name.group(2),
                                            number=mapping_number)
                    comp_syn = True
                    mapping_number += 1

                if re.search('PLACED|FIXED|COVER', line,
                             flags=re.IGNORECASE) and comp_syn:
                    comp_loc = re.search(
                        r'[+] (PLACED|FIXED|COVER)\s+[(] ([-+]?\d+\.?\d*)\s+([-+]?\d+\.?\d*) [)] (\w+)',
                        line)
                    cur_comp.set_location(comp_loc.group(2), comp_loc.group(3))
                    cur_comp.set_orientation(comp_loc.group(4))

                if re.search('PLACED|FIXED|COVER', line,
                             flags=re.IGNORECASE) and comp_syn:
                    Property = re.search(
                        r'[+] (PROPERTY)\s+(\w+)\s+([-+]?\d+\.?\d*|\w+)', line)
                    if Property != None:
                        cur_comp.set_property(
                            [Property.group(2),
                             Property.group(3)])

                if re.search(
                        ';', line
                ) and comp_syn:  #semicolon at the begining of the line
                    comp_syn = False
                    blocks.append(cur_comp)
            """ FIRST PART ENDS HERE """
            """ PINS START """
            if re.match('^[\t ]*PINS \d+', line, flags=re.IGNORECASE):
                find_pin = True
                continue

            if re.match('^[\t ]*END PINS*', line, flags=re.IGNORECASE):
                find_pin = False
                continue

            if find_pin:
                if re.match('^\s*-\s+(\w+)', line):
                    pin_info = True
                    pin_class = cl.Pin(number=mapping_number)
                    pin_class.set_name(
                        re.match('^\s*-\s+(\S+)\s*', line).group(1))
                    mapping_number += 1

                if pin_info:
                    if re.match('. .+', line):
                        data = re.findall(r'(?![(|)|+|;])\S+', line)
                        processPinData(pin_class, data)

                if re.search(';', line):
                    pin_info = False
                    add_pin_info_toDict(pin_class, pins)
                    continue
            """ END PINS """
            """ VIAS SECTION """
            if find_vias:
                if re.search(r';', line):
                    via_info = False
                    # Set the cut layer of the via
                    num_cuts = compute_via_number_of_cuts(
                        cur_via, glob.TECH_LEF_DICT)
                    cur_via.set_viaCuts(num_cuts)
                    def_via.append_via_data_to_dict(cur_via,
                                                    glob.TECH_LEF_DICT)

                if via_info:
                    def_via.parse_def_via_section(line, cur_via,
                                                  glob.TECH_LEF_DICT)

                if re.match(r'^\s*[-]\s+(\w+)', line):
                    via_name = re.findall(r'\S+', line)
                    via_name = (via_name[1])
                    cur_via = cl.LEF_VIA_Info(via_name=via_name)
                    via_info = True

            if re.match('^VIAS\s+\d+\s+[;]', line):
                find_vias = True

            if re.match('^END VIAS*', line):
                find_vias = False
            """ END VIA SECTION """
            """ NETS PART """
            if re.match('^[\t ]*NETS \d+', line, flags=re.IGNORECASE):
                find_net = True
                print('# Process Nets information...')
                net_count = 0
                continue

            if re.match('^[\t ]*END NETS*', line, flags=re.IGNORECASE):
                find_net = False
                print('# Finsihed processing Nets information')
                print('# Total Net Count: {}'.format(net_count))
                continue

            if find_net == True:
                if re.match('^[\t ]*-[\t ]+\w+', line):
                    mapped = False
                    data = re.findall(r'\S+', line)
                    # Create an Instance of a net
                    cur_net = cl.NET(data[1])
                    cur_net.add_cell = blocks
                    # ADDING THE MAPPING NUMBER OF THE NET TO THE PIN INFO
                    if data[1] in pins:
                        cur_net.number = pins[data[1]]['number']
                        mapped = True

                    if not mapped:
                        cur_net.number = mapping_number
                        mapping_number += 1

                    find_data = True

                # End of the particular NET, process the wire data
                if re.search('^\s*;',
                             line):  #semicolon at the begining of the line
                    find_data = False
                    net_count += 1
                    if cur_net.wire_list == []:
                        nets.append(cur_net)
                        print(
                            '# Warning: Net {} does not contain any interconnect information!'
                            .format(cur_net.name))
                        continue

                    # Use for SPEF writer, creating PATH from DEF
                    if buildPath:
                        build_path(cur_net, cell_coor_dict, pins)

                    nets.append(cur_net)
                    continue

                if find_data:
                    parse_net(line, cur_net, cell_coor_dict)
            """ END NETS """

#    if buildPath:
#        import multiprocessing as mp
#        print('# Building Path ...')
#        processes = []
#        end = 0
#
#        cpu_count = mp.cpu_count() + 10
#        for i in range (cpu_count):
#            start = end
#
#            if i == cpu_count-1:
#                end = len(nets)
#            else:
#                end = (i+1) * int(len(nets)/cpu_count)
#
#            p = mp.Process(target=fork_build_path, args=(start, end, nets, cell_coor_dict, pins,))
#            processes.append(p)
#            p.start()
#
#        for process in processes:
#            process.join()

    print('# Finish Rading DEF')