Ejemplo n.º 1
0
 def parse_edif(self):
     environment = Netlist()
     self.append_new_element(environment)
     self.expect(EDIF)
     self.parse_nameDef()
     self.parse_header()
     self.parse_body()
     return self.pop_element()
Ejemplo n.º 2
0
    def _clone(self, memo):
        """Clone leaving all references in tact.

        The element can then either be ripped or ripped and replaced.
        """
        assert self not in memo, "the object should not have been copied twice in this pass"
        from spydrnet.ir import Netlist as NetlistExtended
        c = NetlistExtended()
        memo[self] = c
        c._data = deepcopy(self._data)

        new_libraries = list()
        for library in self._libraries:
            new_libraries.append(library._clone(memo))
        c._libraries = new_libraries

        if self._top_instance == None:
            c._top_instance = None
        else:
            if self._top_instance in memo:
                c._top_instance = memo[self._top_instance]
            else:
                new_top = self.top_instance._clone(memo)
                new_top._clone_rip_and_replace_in_definition(memo)
                new_top._clone_rip_and_replace_in_library(memo)
                c._top_instance = new_top

        for library in c._libraries:
            library._netlist = c
            library._clone_rip_and_replace(memo)
        return c
Ejemplo n.º 3
0
 def test_name_init_shortcut(self):
     d = Definition('d_name')
     self.assertEqual(d.name, 'd_name', 'Definition name init shorcut error')
     l = Library('l_name')
     self.assertEqual(l.name, 'l_name', 'Library name init shorcut error')
     n = Netlist('n_name')
     self.assertEqual(n.name, 'n_name', 'Netlist name init shorcut error')
     i = Instance('i_name')
     self.assertEqual(i.name, 'i_name', 'Instance name init shorcut error')
     c = Cable('c_name')
     self.assertEqual(c.name, 'c_name', 'Cable name init shorcut error')
     p = Port('p_name')
     self.assertEqual(p.name, 'p_name', 'Port name init shorcut error')
Ejemplo n.º 4
0
    def test_properties_init_shortcut(self):

        d = Definition('d_name',{'key1':1, 'key2':'value2' })
        self.assertEqual(d['key1'], 1, 'Definition properties init shorcut error')

        l = Library('l_name',{'key1':'value1', 'key2':'value2' })
        self.assertEqual(l['key1'], 'value1', 'Library properties init shorcut error')

        n = Netlist('n_name',{'key1':'value1', 'key2': 63 })
        self.assertEqual(n['key2'], 63, 'Netlist properties init shorcut error')

        i = Instance('i_name',{'key1':'value1', 'key2':'value2' })
        self.assertEqual(i['key1'], 'value1', 'Instance properties init shorcut error')

        c = Cable('c_name',{'key1':'value1', 'key2':'value2' })
        self.assertEqual(c['key2'], 'value2', 'Cable properties init shorcut error')

        p = Port('p_name',{'key1':'value1', 'key2':'value2' })
        self.assertEqual(p['key1'], 'value1', 'Port properties init shorcut error')
Ejemplo n.º 5
0
class VerilogParser:
    @staticmethod
    def from_filename(filename):
        parser = VerilogParser()
        parser.filename = filename
        return parser

    @staticmethod
    def from_file_handle(file_handle):
        parser = VerilogParser()
        parser.file_handle = file_handle
        return parser

    def __init__(self):
        self.filename = None
        self.file_handle = None
        self.elements = list()
        self.tokenizer = None
        self.netlist = None
        self.primitive_cell = False
        self.direction_string_map = dict()
        self.direction_string_map["input"] = Port.Direction.IN
        self.direction_string_map["output"] = Port.Direction.OUT
        self.direction_string_map["inout"] = Port.Direction.INOUT
        self.direction_string_map[None] = None
        self._assigner_definition = dict()
        self._assigner_library = None
        self._assignment_instance_uid = 0
        self.instance_to_port_map = dict()
        self._port_rename_in_to_out_dict = dict()
        self._port_rename_out_to_in_dict = dict()
        self._port_rename_inner_count_dictionary = dict()

    def _create_assigner_definition(self, width):
        if self._assigner_library == None:
            self._assigner_library = Library()
            self._assigner_library.name = "SDN_VERILOG_ASSIGNMENT"
            self.netlist.add_library(self._assigner_library, 0)
        definition = self._assigner_library.create_definition()
        definition.name = "SDN_VERILOG_ASSIGN_" + str(width)
        cable = definition.create_cable()
        cable.name = "ASSIGN"
        porta = definition.create_port()
        porta.name = "A"
        portb = definition.create_port()
        portb.name = "B"
        porta.direction = Port.Direction.INOUT
        portb.direction = Port.Direction.INOUT
        porta.create_pins(width)
        portb.create_pins(width)
        cable.create_wires(width)
        for i in range(width):
            pa = porta.pins[i]
            pb = portb.pins[i]
            w = cable.wires[i]
            w.connect_pin(pa)
            w.connect_pin(pb)
        self._assigner_definition[width] = definition

    def _create_assigner_instance(self, width, parent):
        if width not in self._assigner_definition:
            self._create_assigner_definition(width)
        instance = parent.create_child()
        instance.reference = self._assigner_definition[width]
        return instance

    def _assigner_get_cable_indicies_from_info(self, cable, info):
        if info[1] is None:
            return cable.lower_index, cable.lower_index + len(cable.wires) - 1
        elif info[2] is None:
            return int(info[1]), int(info[1])
        else:
            return int(info[1]), int(info[2])

    def _create_assigner(self, cable1_info, cable2_info, definition):
        cable1 = next(definition.get_cables(cable1_info[0]))
        cable2 = next(definition.get_cables(cable2_info[0]))
        assert cable1.definition == cable2.definition, "Cannot assign cable from " + cable1.definition.name + " to a cable from " + cable2.definition.name

        cable1_info1, cable1_info2 = self._assigner_get_cable_indicies_from_info(
            cable1, cable1_info)
        cable2_info1, cable2_info2 = self._assigner_get_cable_indicies_from_info(
            cable2, cable2_info)

        width = min(abs(cable1_info1 - cable1_info2),
                    abs(cable2_info1 - cable2_info2)) + 1

        assign_instance = self._create_assigner_instance(width, definition)
        assign_instance.name = "SDN_Assignment_" + str(
            self._assignment_instance_uid) + "_" + str(width)
        porta = assign_instance.reference.ports[0]
        portb = assign_instance.reference.ports[1]
        self._assignment_instance_uid += 1

        #3 general cases to consider
        #both are none,                                     map the whole wire.
        #the first is not none and the second is none,      map just the first bit.
        #the first is not none and the second is not none,  map the bits between the indicies.

        # if cable1_info[1] == None or cable2_info[1] == None:

        # elif cable1_info[2] == None or cable2_info[2] == None:
        #     ipa = porta.pins[0]
        #     ipb = portb.pins[0]
        #     cable1.wires[int(cable1_info[1])-cable1.lower_index].connect_pin(assign_instance.pins[ipa])
        #     cable2.wires[int(cable2_info[1])-cable2.lower_index].connect_pin(assign_instance.pins[ipb])
        # else:

        iterations = 0
        for val in range(min(cable1_info2, cable1_info1),
                         max(cable1_info2, cable1_info1) + 1):
            if iterations >= width:
                break
            ipa = porta.pins[iterations]
            cable1.wires[val - cable1.lower_index].connect_pin(
                assign_instance.pins[ipa])
            iterations += 1
        iterations = 0
        for val in range(min(cable2_info2, cable2_info1),
                         max(cable2_info2, cable2_info1) + 1):
            if iterations >= width:
                break
            ipb = portb.pins[iterations]
            cable2.wires[val - cable2.lower_index].connect_pin(
                assign_instance.pins[ipb])
            iterations += 1

    def _port_rename_create_assignment(self,
                                       outer_port,
                                       i,
                                       inner_cable,
                                       definition,
                                       inner_index=None):
        cable1_info = [outer_port.name, i, None]
        cable2_info = [inner_cable.name, inner_index, None]
        self._create_assigner(cable1_info, cable2_info, definition)

    def parse(self):
        self.initialize_tokenizer()
        ns_default = namespace_manager.default
        namespace_manager.default = "DEFAULT"
        self.netlist = self.parse_verilog()
        namespace_manager.default = ns_default
        self.tokenizer.__del__()
        return self.netlist

    def initialize_tokenizer(self):
        if self.filename:
            self.tokenizer = VerilogTokenizer.from_filename(self.filename)
        elif self.file_handle:
            self.tokenizer = VerilogTokenizer.from_stream(self.file_handle)

    def parse_verilog(self):
        params = dict()

        token = self.tokenizer.next()
        line_num = self.tokenizer.line_number
        self.netlist = Netlist()
        self.primitive_cell = False
        top_next = False
        while token:

            if token == '`celldefine':
                self.primitive_cell = True
            elif self.primitive_cell and token == "`endcelldefine":
                self.primitive_cell = False

            elif token == "(":
                token = self.tokenizer.next()
                assert token == "*", "unexpected ( with out a *" + " " + str(
                    self.tokenizer.line_number)
                k, v = self.parse_star_parameters()
                if k == "STRUCTURAL_NETLIST":
                    top_next = True
                k = "VERILOG.star." + k
                params[k] = v

            elif token == "module":
                definition = self.parse_module(params, self.netlist)
                #if netlist.top_instance is None:
                if top_next == True:
                    instance = Instance()
                    instance.name = definition.name
                    instance.reference = definition
                    self.netlist.top_instance = instance
                    top_next = False

            elif token[:2] == "//":
                pass  #comment

            elif token == "primitive":
                while token != "endprimitive":
                    token = self.tokenizer.next()

            else:
                #print("unsorted token", token)
                pass  #unsorted token

            if self.tokenizer.has_next():
                token = self.tokenizer.next()
                line_num = self.tokenizer.line_number
            else:
                token = None

        for instance, port_map in self.instance_to_port_map.items():
            port_pin_map = dict()
            for port in instance.reference.ports:
                port_pin_map[port] = []
            for pin in instance.pins:
                port_pin_map[pin.inner_pin.port].append(pin)
            definition = instance.parent

            for port_name, cable_list in port_map.items():

                index_offset = 0
                for cable_name in cable_list:
                    low = None
                    high = None
                    index_offset_initial = index_offset
                    if cable_name[len(cable_name) - 1] == "]" and (
                            cable_name[0] != "\\"
                            or len(cable_name.split(" ")) > 1):
                        cable_name_real, index = cable_name.split(" ")
                        indicies = index[1:len(index) - 1].split(":")
                        if len(indicies) == 1:
                            low = int(indicies[0])
                            high = None
                        else:
                            low = min(int(indicies[0]), int(indicies[1]))
                            high = max(int(indicies[0]), int(indicies[1]))
                    else:
                        cable_name_real = cable_name
                    cable_def_list = definition.get_cables(cable_name_real)
                    cable = next(cable_def_list)
                    port_list = instance.reference.get_ports(port_name)
                    port = next(port_list)
                    if low == None and high == None:
                        if len(cable.wires) == len(port_pin_map[port]):
                            for i in range(len(cable.wires)):
                                cable.wires[i].connect_pin(
                                    port_pin_map[port][i +
                                                       index_offset_initial])
                                index_offset += 1
                        else:
                            for i in range(
                                    min(len(port_pin_map[port]),
                                        len(cable.wires))):
                                cable.wires[i].connect_pin(
                                    port_pin_map[port][i +
                                                       index_offset_initial])
                                index_offset += 1
                    else:
                        if high == None:
                            # try:
                            cable.wires[low - cable.lower_index].connect_pin(
                                port_pin_map[port][0 + index_offset_initial])
                            # except Exception:
                            #     import pdb; pdb.set_trace()
                            index_offset += 1
                        else:
                            for i in range(low, high + 1):
                                cable.wires[i - cable.lower_index].connect_pin(
                                    port_pin_map[port][i - low +
                                                       index_offset_initial])
                                index_offset += 1
        return self.netlist

    def parse_star_parameters(self):
        key = self.tokenizer.next()
        token = self.tokenizer.next()
        if token == "*":
            assert self.tokenizer.next(
            ) == ")", "expected ) to end the star params" + " " + str(
                self.tokenizer.line_number)
            return key, None
        assert token == "=", "expected a = character in the key value directive got: " + token + " line " + str(
            self.tokenizer.line_number)
        value = self.tokenizer.next()
        assert self.tokenizer.next(
        ) == "*", "expected * to end star params" + " " + str(
            self.tokenizer.line_number)
        assert self.tokenizer.next(
        ) == ")", "expected ) to end the star params" + " " + str(
            self.tokenizer.line_number)
        return key, value

    def parse_module(self, params, netlist):

        definition = self.parse_module_header(self.netlist)
        for k, v in params.items():
            definition[k] = v
        if self.primitive_cell:
            self.parse_primitive_cell_body(definition)
        else:
            self.parse_module_body(definition, self.netlist)
        return definition

    def parse_primitive_cell_body(self, definition):
        definition["VERILOG.primative"] = True
        token = self.tokenizer.next()
        keywords = set(["input", "output", "inout"])
        while token != "endmodule" and token != "endprimative":
            if token in keywords:
                names, left, right = self.parse_wire()
                for name in names:
                    port = self._update_port(
                        definition, name,
                        self.my_minus(self.my_max(left, right),
                                      self.my_min(left, right)), token,
                        self.my_min(left, right), self.my_greater(left, right))
            elif token == "function":
                while token != "endfunction":
                    token = self.tokenizer.next()
            token = self.tokenizer.next()

    def _parse_rename_single(self, name, token):
        # token = self.tokenizer.next()
        if token == "[":
            name += " "
            while token != "," and token != "}" and token != ')':
                name += token
                token = self.tokenizer.next()
        return name, token

    def parse_module_header(self, netlist):
        name = self.tokenizer.next()
        definition = self._get_create_definition(self.netlist, name)
        token = self.tokenizer.next()
        if token == "#":
            self.parse_parameter_list(definition)
            token = self.tokenizer.next()
        d = None
        if token == "(":

            while True:
                verilog_rename = None
                name_list = []
                token = self.tokenizer.next()
                if token == ")":
                    break
                if token == ".":
                    verilog_rename = self.tokenizer.next()
                    token = self.tokenizer.next()
                    assert token == "(", "expected ( to create a port alias got " + token + " line " + str(
                        self.tokenizer.line_number)
                    token = self.tokenizer.next()
                    if token == "{":
                        while token != "}":
                            # name = self.tokenizer.next()
                            # token = self.tokenizer.next()
                            # if token == "[":
                            #     name += " "
                            #     while token != "," and token != "}":
                            #         name += token
                            #         token = self.tokenizer.next()
                            name = self.tokenizer.next()
                            token = self.tokenizer.next()
                            name, token = self._parse_rename_single(
                                name, token)
                            name_list.append(name)
                            assert token == "," or token == "}", "syntax error expect , or } got " + token + " line " + str(
                                self.tokenizer.line_number)
                    else:
                        name = token
                        token = self.tokenizer.peek()
                        name, token = self._parse_rename_single(name, token)
                        name_list.append(name)
                        assert token == ")", "syntax error expect ) got " + token + " line " + str(
                            self.tokenizer.line_number)

                    temp = self.tokenizer.next()
                    assert temp == ")", "expected ) to finish alias got " + temp + " line " + str(
                        self.tokenizer.line_number)
                if token == "input" or token == "output" or token == "inout":
                    d = token
                    token = self.tokenizer.next()
                left = 0
                right = 0
                if token == "[":
                    left = int(self.tokenizer.next())
                    token = self.tokenizer.next()
                    assert token == ":", "expected a : to separate the numbers in a port width  got " + str(
                        token) + " line " + self.tokenizer.line_number
                    right = int(self.tokenizer.next())
                    token = self.tokenizer.next()
                    assert token == "]", "expected ] to end the port length definition got " + str(
                        token) + " line " + self.tokenizer.line_number
                    token = self.tokenizer.next()
                if verilog_rename is None:
                    name = token
                    port = self._update_port(
                        definition,
                        name,
                        width=self.my_minus(self.my_max(left, right),
                                            self.my_min(left, right)),
                        direction=d,
                        lower_index=self.my_min(left, right),
                        is_downto=self.my_greater(left, right))
                else:
                    i = 0
                    outer_port = self._update_port(definition,
                                                   verilog_rename,
                                                   width=i,
                                                   direction=d,
                                                   lower_index=0,
                                                   is_downto=True)
                    for name in name_list:
                        name_split = name.split(" ")
                        name = name_split[0]
                        index = None
                        if len(name_split) > 1:
                            #raise Exception
                            index = name_split[1]
                            if ":" in index:
                                raise Exception
                            index = int(index.strip("]").strip("["))

                        # # port = self._update_port(definition, name, width = (max(left,right) - self.my_min(left,right)), direction=d, lower_index = self.my_min(left,right), is_downto = left > right)
                        # # port["VERILOG.port_rename_member"] = "true"
                        # # if index is not None:
                        # #     outer_port["VERILOG.port_rename."+str(i)] = name + " " + index
                        # # else:
                        # #     outer_port["VERILOG.port_rename."+str(i)] = name
                        # in_count = 1
                        # if name in self._port_rename_inner_count_dictionary:
                        #     in_count = self._port_rename_inner_count_dictionary[name]
                        #     self._port_rename_inner_count_dictionary[name] += 1
                        # else:
                        #     in_count = 1
                        #     self._port_rename_inner_count_dictionary[name] = 1

                        inner_cable = self._update_cable(
                            definition, name=name, additional_index=index)
                        # # index_of_interest = 0
                        # # if index is not None:
                        # #     index_of_interest = int(index.strip("[").strip("]"))
                        self._port_rename_in_to_out_dict[name] = outer_port
                        if outer_port not in self._port_rename_out_to_in_dict:
                            self._port_rename_out_to_in_dict[outer_port] = []
                        self._port_rename_out_to_in_dict[outer_port].append(
                            name)
                        self._port_rename_create_assignment(outer_port,
                                                            i,
                                                            inner_cable,
                                                            definition,
                                                            inner_index=index)
                        i += 1
                        outer_port = self._update_port(definition,
                                                       verilog_rename,
                                                       width=i,
                                                       direction=d,
                                                       lower_index=0,
                                                       is_downto=True)

                token = self.tokenizer.next()
                if token == ")":
                    break
                assert token == ",", "expected a , separater in the port list got " + token + " line " + str(
                    self.tokenizer.line_number)

        token = self.tokenizer.next()
        assert token == ";", "expected ; to finish the port list" + " " + str(
            self.tokenizer.line_number)
        return definition

    def parse_parameter_list(self, definition):
        token = self.tokenizer.next()
        assert token == "(", "expected a ( following the # for the parameter definitions" + " " + str(
            self.tokenizer.line_number)
        while token != ")":
            token = self.tokenizer.next()
            assert token == "parameter", "expected a parameter in the parameter list" + " " + str(
                self.tokenizer.line_number)
            token = self.tokenizer.next()
            key = ""
            if token == "integer":
                key += "integer "
                token = self.tokenizer.next()
            if token == "[":
                while token != "=":
                    key += token
                    token = self.tokenizer.next()
            else:
                key = token
                token = self.tokenizer.next()
                assert token == "=", "expected a = in the key value pair for the parameter" + " " + str(
                    self.tokenizer.line_number)
            value = self.tokenizer.next()
            if key not in definition:
                definition[key] = value
            token = self.tokenizer.next()

    def parse_module_body(self, definition, netlist):
        keywords = set([
            "input", "output", "inout", "wire", "reg", "assign"
        ])  #this is the list of words that could begin a wire list line
        portwords = set(["input", "output", "inout"])
        token = self.tokenizer.peek()
        params = dict()
        assignment_info = dict()
        while token != "endmodule":
            if token not in keywords:
                token = self.tokenizer.next()
                def_name = token
                if token == ";":
                    pass
                elif token == "(":
                    token = self.tokenizer.next()
                    assert token == "*", "unexpected ( with out a *" + " " + str(
                        self.tokenizer.line_number)
                    k, v = self.parse_star_parameters()
                    params["VERILOG.star." + k] = v
                else:
                    instance = self.parse_single_instance(
                        self.netlist, definition, def_name, params)
                    params = dict()
            elif token == "assign":
                _ = self.tokenizer.next()
                name_left, left_left, right_left = self.parse_wire_in_instance(
                )
                token = self.tokenizer.next()
                assert token == "=", "expected = but got " + token
                name_right, left_right, right_right = self.parse_wire_in_instance(
                )

                assignment_info[(name_left, left_left,
                                 right_left)] = (name_right, left_right,
                                                 right_right)

                #print("left side of the assign", name_left + "["+str(left_left) + ":" + str(right_left) + "]", "right side of the assignment", name_right + "["+str(left_right) + ":" + str(right_right) + "]")
            else:
                token = self.tokenizer.next()
                names, left, right = self.parse_wire()
                for name in names:
                    #check and see what a name lookup on the name yeids for the ports
                    #go ahead and modify it if it exists.
                    if token in portwords:
                        #print(token)
                        if name in self._port_rename_in_to_out_dict:
                            #print("unexpected")
                            outer_port = self._port_rename_in_to_out_dict[name]
                            name = outer_port.name
                            direction = outer_port.direction
                            if direction == Port.Direction.INOUT:
                                token = "inout"
                            elif direction == Port.Direction.IN:
                                if token == "output" or token == "inout":
                                    token = "inout"
                            elif direction == Port.Direction.OUT:
                                if token == "input" or token == "inout":
                                    token = "inout"
                            elif direction == Port.Direction.UNDEFINED:
                                pass
                            port = self._update_port(definition,
                                                     name,
                                                     direction=token)
                        else:
                            port = self._update_port(
                                definition,
                                name,
                                width=self.my_minus(self.my_max(left, right),
                                                    self.my_min(left, right)),
                                direction=token,
                                lower_index=self.my_min(left, right),
                                is_downto=self.my_greater(left, right))
                    else:
                        cable = self._update_cable(
                            definition,
                            name,
                            width=self.my_minus(self.my_max(left, right),
                                                self.my_min(left, right)),
                            lower_index=self.my_min(left, right),
                            is_downto=self.my_greater(left, right))
            token = self.tokenizer.peek()

        for k, v in assignment_info.items():
            self._create_assigner(k, v, definition)

        #put in assignment information

    def parse_wire_in_instance(self):
        token = self.tokenizer.next()
        name = token
        left = None
        right = None
        token = self.tokenizer.peek()
        if token == "[":
            token = self.tokenizer.next()
            try:
                str_left = self.tokenizer.next()
                left = int(str_left)
            except ValueError:
                print("expected an integer value following [ instead got " +
                      str_left + " line " + str(self.tokenizer.line_number))
                raise ValueError
            token = self.tokenizer.next()
            if token == ":":
                right = int(self.tokenizer.next())
                token = self.tokenizer.next()
            assert token == "]", "expected an end bracket got " + token + " line " + str(
                self.tokenizer.line_number)
            #token = self.tokenizer.next()
        return name, left, right

    def parse_wire(self):
        #the next token will be either [ or a letter
        #if [ then the next is the left then : then right
        #if a letter then it will just be 0 downto 0
        name = []
        token = self.tokenizer.next()
        left = None
        right = None
        verilog_types = ["reg", "wire", "integer"]
        v_type = "wire"
        if token in verilog_types:
            v_type = token  #TODO use this
            token = self.tokenizer.next()
        if token == "[":
            left = int(self.tokenizer.next())
            assert self.tokenizer.next(
            ) == ":", "expected a colon" + " " + str(
                self.tokenizer.line_number)
            right = int(self.tokenizer.next())
            assert self.tokenizer.next(
            ) == "]", "expected an end bracket" + " " + str(
                self.tokenizer.line_number)
            token = self.tokenizer.next()
        while True:
            name.append(token)
            #name, left, right = self.parse_wire_name(self)
            token = self.tokenizer.next()
            #assert token == ";", "expected ; got " + token + " line " + str(self.tokenizer.line_number)
            if token == ";":
                break
            elif token == ",":
                token = self.tokenizer.next()
            else:
                print("unexpected token in cable or port list " + token +
                      " line " + str(self.tokenizer.line_number))
        return name, left, right

    def parse_single_instance(self, netlist, parent, reference_name, params):

        ref_def = self._get_create_definition(self.netlist, reference_name)
        instance = parent.create_child()
        for k, v in params.items():
            instance[k] = v
        token = self.tokenizer.next()

        if token == "#":
            param = self.parse_instance_parameter_list()
            token = self.tokenizer.next()

            for k, v in param.items():
                instance["VERILOG.parameters." + k] = v

        name = token
        instance.name = name

        instance.reference = ref_def

        port_map = self.parse_port_map(instance)

        self.instance_to_port_map[instance] = port_map

        return instance

    def parse_instance_parameter_list(self):
        params = dict()
        token = self.tokenizer.next()
        assert token == "(", "expected list of attributes to map after #" + " " + str(
            self.tokenizer.line_number)
        token = self.tokenizer.next()
        while True:
            if token == ".":
                pass
            elif token == ",":
                pass
            elif token == "*":
                print(".* mapping is unsupported")
            elif token == ")":
                break
            else:
                key = token
                token = self.tokenizer.next()
                assert token == "(", "expected a ( in parameter mapping " + str(
                    self.tokenizer.line_number)
                value = ""
                token = self.tokenizer.next()
                while token != ")":
                    value += token
                    token = self.tokenizer.next()
                params[key] = value
            token = self.tokenizer.next()
        return params

    def parse_port_map(self, instance):
        #extract/create the port that will be wired up to I guess assume the width is the same as the wire?
        token = self.tokenizer.next()
        assert token == "(", "expected ( for port mapping but got " + token + " line " + str(
            self.tokenizer.line_number)
        token = self.tokenizer.next()
        # if token == "{":
        #     #we have a combinational port map going on... each pin on the port will be mapped individually
        #     pass
        port_map = dict()
        #import pdb; pdb.set_trace()
        while True:
            if token == ")":
                break
            elif token == "." or token == ",":
                pass
            else:
                port_name = token
                token = self.tokenizer.next()
                assert token == "(", "port needs to be followed by (cable) but got " + token + " line " + str(
                    self.tokenizer.line_number)
                token = self.tokenizer.next()
                multi_cable = False
                if token == "{":
                    multi_cable = True
                    token = self.tokenizer.next()

                while True:
                    cable_name = token
                    token = self.tokenizer.next()
                    if token == "[":  #this will be a slice. for now just put it in the value
                        cable_name += " " + token
                        while token != "]":
                            token = self.tokenizer.next()
                            cable_name += token
                        token = self.tokenizer.next()
                    if port_name not in port_map:
                        port_map[port_name] = []
                    port_map[port_name].append(cable_name)
                    #token = self.tokenizer.next()
                    if multi_cable and token == "}":
                        token = self.tokenizer.next()
                        break
                    elif multi_cable and token == ",":
                        token = self.tokenizer.next()
                    elif token == ")":
                        break
                    else:
                        print("unknown token in port mapping", token)
                assert token == ")", "cable list should end with ) but ends with " + token + " line " + str(
                    self.tokenizer.line_number)
                #token = self.tokenizer.next()
            token = self.tokenizer.next()

        assert token == ")", "port list needs to be ended with a ) but ends with " + token + " line " + str(
            self.tokenizer.line_number)

        return port_map

    def _get_create_library(self, netlist, library_name=None):
        if library_name:
            lib_list = self.netlist.get_libraries(library_name)
            lib = next(lib_list, None)
            if not lib:
                lib = self.netlist.create_library()
                lib.name = library_name
        else:
            lib_list = self.netlist.get_libraries("work")
            lib = next(lib_list, None)
            if not lib:
                lib = self.netlist.create_library()
                lib.name = "work"
        return lib

    def _get_create_definition(self, netlist, definition_name, library=None):
        if library is not None:
            d = next(library.get_definitions(definition_name), None)
            if d is None:
                d = library.create_definition()
                d.name = definition_name
            return d
        else:
            library = self._get_create_library(self.netlist)
            d = next(library.get_definitions(definition_name), None)
            if d is None:
                d = library.create_definition()
                d.name = definition_name
            return d

    def _update_instance(self,
                         netlist,
                         definition,
                         name,
                         reference=None,
                         properties=dict()):
        #pass in a definition in which to contain the instance as a child
        #pass in the name of the instance to create/find
        #pass in the reference of the instance to create/find
        #can also pass in a dictionary of properties to add to the instance.
        #return the instance that was created or found
        inst = definition.get_children(name)
        if not inst:
            inst = definition.create_child()
            inst.name = name
        if reference is not None:
            ref = self.netlist.get_definitions(reference)
            if not ref:
                lib = self._get_create_library(self.netlist)
                ref = lib.create_definition()
                ref.name = reference
            inst.reference = ref
        for k, v in properties.items():
            inst[k] = v
        return inst

    def _update_definition(self,
                           netlist,
                           name,
                           library=None,
                           properties=dict()):
        lib = self._get_create_library(self.netlist, library)
        d_list = self.netlist.get_definitions(name)
        d = next(d_list, None)
        if not d:
            d = lib.create_definition()
            d.name = name

        if library is not None:
            if d.library.name != library:
                d.library.remove_definition(d)
                lib.add_definition(d)

        for k, v in properties.items():
            d[k] = v

        return d

    def _update_port(self,
                     definition,
                     name,
                     width=None,
                     direction=None,
                     lower_index=None,
                     is_downto=None,
                     properties=dict()):
        port_list = definition.get_ports(name)
        cable_list = definition.get_cables(name)

        direction = self.direction_string_map[direction]

        port = next(port_list, None)
        cable = next(cable_list, None)

        if port is None:
            port = definition.create_port()
            port.name = name

        if cable is None:
            cable = definition.create_cable()
            cable.name = name

        if width is None and len(port.pins) == 0:
            width = 0

        if width is not None:
            width = width + 1
            current_p_width = len(port.pins)
            current_c_width = len(cable.wires)

            if width < current_p_width or width < current_c_width:
                print(
                    "updating port width does not support reducing size. a port or wire might be declared twice?"
                )
                raise NotImplementedError
            wp = width - current_p_width
            wc = width - current_c_width

            port.create_pins(wp)
            cable.create_wires(wc)

        if direction is not None:
            port.direction = direction
        if lower_index is not None:
            port.lower_index = lower_index
            cable.lower_index = lower_index
        if is_downto is not None:
            port.is_downto = is_downto
            cable.is_downto = is_downto

        for k, v in properties.items():
            port[k] = v
            cable[k] = v

        for i in range(len(port.pins)):
            if port.pins[i].wire == None:
                cable.wires[i].connect_pin(port.pins[i])

        return port

    def _update_cable(self,
                      definition,
                      name,
                      width=None,
                      direction=None,
                      lower_index=None,
                      is_downto=None,
                      properties=dict(),
                      additional_index=None):
        #use the additional index to add one index to a cable (expanding to fill any gaps and setting lower index appropriately)
        #if the index exists then nothing happens
        #width value is primary and overrides any additional index given.
        cable_list = definition.get_cables(name)

        direction = self.direction_string_map[direction]

        cable = next(cable_list, None)

        if cable is None:
            cable = definition.create_cable()
            cable.name = name

        if additional_index is not None and width is None:
            if len(cable.wires) == 0:
                lower_index = additional_index
                width = 0
            elif additional_index >= cable.lower_index and additional_index < cable.lower_index + len(
                    cable.wires):
                pass
            else:
                width = len(cable.wires)
                if additional_index < cable.lower_index:
                    additional_width = cable.lower_index - additional_index
                    width = width + additional_width
                    lower_index = additional_index
                else:
                    assert additional_index >= cable.lower_index + len(
                        cable.wires)
                    additional_width = additional_index - cable.lower_index - len(
                        cable.wires)
                    width = width + additional_width

        if width is None and len(cable.wires) == 0:
            width = 0

        if width is not None:
            width = width + 1
            current_width = len(cable.wires)

            if width < current_width:
                print(
                    "updating port width does not support reducing size. a port or wire might be declared twice with different lengths?"
                )
                raise NotImplementedError

            wire_add_count = width - current_width
            cable.create_wires(wire_add_count)

        if lower_index is not None:
            cable.lower_index = lower_index
        if is_downto is not None:
            cable.is_downto = is_downto

        for k, v in properties.items():
            cable[k] = v

        # if cable.name == "next_state_i_a2_6":
        #     print(cable.lower_index)
        #     import pdb; pdb.set_trace()

        return cable

    def my_max(self, a, b):
        if a == None:
            return b
        elif b == None:
            return a
        else:
            return max(a, b)

    def my_min(self, a, b):
        if a == None:
            return b
        elif b == None:
            return a
        else:
            return min(a, b)

    def my_greater(self, a, b):
        if a == None:
            return b
        elif b == None:
            return a
        else:
            return a > b

    def my_minus(self, a, b):
        if a == None or b == None:
            return None
        else:
            return a - b
Ejemplo n.º 6
0
    def parse_verilog(self):
        params = dict()

        token = self.tokenizer.next()
        line_num = self.tokenizer.line_number
        self.netlist = Netlist()
        self.primitive_cell = False
        top_next = False
        while token:

            if token == '`celldefine':
                self.primitive_cell = True
            elif self.primitive_cell and token == "`endcelldefine":
                self.primitive_cell = False

            elif token == "(":
                token = self.tokenizer.next()
                assert token == "*", "unexpected ( with out a *" + " " + str(
                    self.tokenizer.line_number)
                k, v = self.parse_star_parameters()
                if k == "STRUCTURAL_NETLIST":
                    top_next = True
                k = "VERILOG.star." + k
                params[k] = v

            elif token == "module":
                definition = self.parse_module(params, self.netlist)
                #if netlist.top_instance is None:
                if top_next == True:
                    instance = Instance()
                    instance.name = definition.name
                    instance.reference = definition
                    self.netlist.top_instance = instance
                    top_next = False

            elif token[:2] == "//":
                pass  #comment

            elif token == "primitive":
                while token != "endprimitive":
                    token = self.tokenizer.next()

            else:
                #print("unsorted token", token)
                pass  #unsorted token

            if self.tokenizer.has_next():
                token = self.tokenizer.next()
                line_num = self.tokenizer.line_number
            else:
                token = None

        for instance, port_map in self.instance_to_port_map.items():
            port_pin_map = dict()
            for port in instance.reference.ports:
                port_pin_map[port] = []
            for pin in instance.pins:
                port_pin_map[pin.inner_pin.port].append(pin)
            definition = instance.parent

            for port_name, cable_list in port_map.items():

                index_offset = 0
                for cable_name in cable_list:
                    low = None
                    high = None
                    index_offset_initial = index_offset
                    if cable_name[len(cable_name) - 1] == "]" and (
                            cable_name[0] != "\\"
                            or len(cable_name.split(" ")) > 1):
                        cable_name_real, index = cable_name.split(" ")
                        indicies = index[1:len(index) - 1].split(":")
                        if len(indicies) == 1:
                            low = int(indicies[0])
                            high = None
                        else:
                            low = min(int(indicies[0]), int(indicies[1]))
                            high = max(int(indicies[0]), int(indicies[1]))
                    else:
                        cable_name_real = cable_name
                    cable_def_list = definition.get_cables(cable_name_real)
                    cable = next(cable_def_list)
                    port_list = instance.reference.get_ports(port_name)
                    port = next(port_list)
                    if low == None and high == None:
                        if len(cable.wires) == len(port_pin_map[port]):
                            for i in range(len(cable.wires)):
                                cable.wires[i].connect_pin(
                                    port_pin_map[port][i +
                                                       index_offset_initial])
                                index_offset += 1
                        else:
                            for i in range(
                                    min(len(port_pin_map[port]),
                                        len(cable.wires))):
                                cable.wires[i].connect_pin(
                                    port_pin_map[port][i +
                                                       index_offset_initial])
                                index_offset += 1
                    else:
                        if high == None:
                            # try:
                            cable.wires[low - cable.lower_index].connect_pin(
                                port_pin_map[port][0 + index_offset_initial])
                            # except Exception:
                            #     import pdb; pdb.set_trace()
                            index_offset += 1
                        else:
                            for i in range(low, high + 1):
                                cable.wires[i - cable.lower_index].connect_pin(
                                    port_pin_map[port][i - low +
                                                       index_offset_initial])
                                index_offset += 1
        return self.netlist
Ejemplo n.º 7
0
 def test_netlist_top_instance_definition_shortcut(self):
     top_definition = Definition('this is my name')
     netlist = Netlist()
     netlist.top_instance = top_definition
     self.assertEqual(netlist.top_instance.reference.name,top_definition.name,'Netlist\'s top instance\'s shorcut error')
Ejemplo n.º 8
0
 def test_netlist_child_instance_creation(self):
     n = Netlist('n_name')
     self.assertEqual(n.name, 'n_name', 'Netlist name init shorcut error')
     n.create_library('l_name',{'key1':'value1', 'key2':'value2' })
     self.assertEqual(n.libraries[0]['key1'], 'value1', 'Library properties init shorcut error')