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 test_library_child_instance_creation(self): l = Library('l_name',{'key1':'value1', 'key2':'value2' }) self.assertEqual(l['key1'], 'value1', 'Library properties init shorcut error') l.create_definition("l_d_name", {'key1': 50, 'key2':'value2' }) self.assertEqual('l_d_name', l.definitions[0].name, 'library\'s definition cretion shorcut error') self.assertEqual(l.definitions[0]['key1'], 50, 'library\'s definition cretion shorcut error') l2 = Library() l2.create_definition(properties = {'key1': 50, 'key2':'value2' }) self.assertEqual(l2.definitions[0]['key1'], 50, 'library\'s definition cretion shorcut error')
def create_library(self, name=None, properties=None): """Create a library and add it to the netlist and return that library parameters ---------- name - (str) the name of the library properties - (dict) the dictionary which holds the properties of the library """ library = Library(name, properties) self.add_library(library) return library
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')
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')
def parse_library_like_element(self, is_external=False): library = Library() if is_external: library['EDIF.external'] = True self.append_new_element(library) self.parse_nameDef() self.parse_construct(self.parse_edifLevel) self.parse_construct(self.parse_technology) has_status = False while self.begin_construct(): if self.construct_is(STATUS): has_status = self.check_for_multiples(STATUS, has_status) self.parse_status() elif self.construct_is(CELL): definition = self.parse_cell() library = self.elements[-1] add_exception = None try: library.add_definition(definition) except ValueError as e: name = definition.name identifier = definition['EDIF.identifier'] if name != identifier: try: definition.name = identifier library.add_definition(definition) except ValueError: raise e else: add_exception = e if add_exception: raise add_exception elif self.construct_is(COMMENT): self.parse_comment() elif self.construct_is(USER_DATA): self.parse_userData() else: self.expect("|".join([STATUS, CELL, COMMENT, USER_DATA])) self.expect_end_construct() return self.pop_element()
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