Example #1
0
 def run(self, edit, args):
     settings = self.view.settings()
     isAutoConnect = settings.get('sv.autoconnect', False)
     isParamOneLine = settings.get('sv.param_oneline', True)
     isInstOneLine = settings.get('sv.inst_oneline', True)
     isColumnAlignment = settings.get('sv.param_port_alignment', True)
     indent_level = settings.get('sv.decl_indent')
     param_decl = ''
     pm = args['pm']
     # print(pm)
     # Update Module information with parameter value for later signal declaration using correct type
     for p in args['pv']:
         for pmp in pm['param']:
             if pmp['name'] == p['name']:
                 if p['value'].startswith('parameter') or p[
                         'value'].startswith('localparam'):
                     pmp['value'] = p['name']
                     param_decl += indent_level * '\t' + p['value'] + ';\n'
                     m = re.search(r"(?P<name>\w+)\s*=", p['value'])
                     p['value'] = m.group('name')
                 else:
                     pmp['value'] = p['value']
                 break
     # print('[VerilogDoModuleInstCommand] pm = '+ str(pm))
     decl = ''
     ac = {}
     wc = {}
     # Add signal port declaration
     if isAutoConnect and pm['port']:
         (decl, ac, wc) = self.get_connect(self.view, settings, pm)
         #Find location where to insert signal declaration: default to just before module instantiation
         if decl or param_decl:
             r = self.get_region_decl(self.view, settings)
             self.view.insert(edit, r, '\n' + param_decl + decl)
             sublime.status_message('Adding ' +
                                    str(len(decl.splitlines())) +
                                    ' signals declaration')
     inst_name = settings.get('sv.instance_prefix',
                              '') + pm['name'] + settings.get(
                                  'sv.instance_suffix', '')
     # Check if instantiation can fit on one line only
     if isInstOneLine:
         len_inst = len(pm['name']) + 1 + len(inst_name) + 2
         if len(args['pv']) > 0:
             len_inst += 2
             for p in args['pv']:
                 len_inst += len(p['name']) + len(p['value']) + 5
         if len_inst + 3 > settings.get('sv.max_line_length', 120):
             isParamOneLine = False
         elif pm['port']:
             for p in pm['port']:
                 len_inst += len(p['name']) + 5
                 if p['name'] in ac.keys():
                     len_inst += len(ac[p['name']])
                 else:
                     len_inst += len(p['name'])
         if len_inst + 3 > settings.get('sv.max_line_length', 120):
             isInstOneLine = False
     # Instantiation
     inst = pm['name'] + " "
     # Parameters: bind only parameters for which a value different from default was set
     if len(args['pv']) > 0:
         if isParamOneLine or not isColumnAlignment:
             max_len = 0
         else:
             max_len = max([len(x['name']) for x in args['pv']])
         inst += "#("
         if not isParamOneLine:
             inst += "\n"
         for i in range(len(args['pv'])):
             if not isParamOneLine:
                 inst += "\t"
             inst += "." + args['pv'][i]['name'].ljust(
                 max_len) + "(" + args['pv'][i]['value'] + ")"
             if i < len(args['pv']) - 1:
                 inst += ","
             if not isParamOneLine:
                 inst += "\n"
             elif i < len(args['pv']) - 1:
                 inst += " "
         inst += ") "
     #Port binding
     inst += inst_name + " ("
     if not isInstOneLine:
         inst += "\n"
     if pm['port']:
         # Get max length of a port to align everything
         if isInstOneLine or not isColumnAlignment:
             max_len_p = 0
             max_len_s = 0
         else:
             max_len_p = max([len(x['name']) for x in pm['port']])
             max_len_s = max_len_p
             # print('Autoconnect dict = ' + str([ac[x] for x in ac]))
             if len(ac) > 0:
                 max_len_s = max([len(ac[x]) for x in ac])
                 if max_len_p > max_len_s:
                     max_len_s = max_len_p
         for i in range(len(pm['port'])):
             portname = pm['port'][i]['name']
             if not isInstOneLine:
                 inst += "\t"
             inst += "." + portname.ljust(max_len_p) + "("
             if isAutoConnect:
                 if portname in ac.keys():
                     inst += ac[portname].ljust(max_len_s)
                 else:
                     inst += portname.ljust(max_len_s)
             inst += ")"
             if i < len(pm['port']) - 1:
                 inst += ","
             if not isInstOneLine:
                 if portname in wc.keys():
                     inst += " // TODO: Check connection ! " + wc[portname]
                 inst += "\n"
             elif i < len(pm['port']) - 1:
                 inst += " "
     inst += ");\n"
     self.view.insert(edit, self.view.sel()[0].a, inst)
     # Status report
     nb_decl = len(decl.splitlines())
     s = ''
     if nb_decl:
         s += 'Adding ' + str(nb_decl) + ' signal(s) declaration(s)\n'
     if len(ac) > 0:
         s += 'Non-perfect name match for ' + str(
             len(ac)) + ' port(s) : ' + str(ac) + '\n'
     if len(wc) > 0:
         s += 'Found ' + str(len(wc)) + ' mismatch(es) for port(s): ' + str(
             [x for x in wc.keys()]) + '\n'
     if s != '':
         sublimeutil.print_to_panel(s, 'SystemVerilog')
Example #2
0
 def run(self, edit):
     if len(self.view.sel()) == 0: return
     r = self.view.sel()[0]
     scope = self.view.scope_name(r.a)
     if 'meta.module.inst' not in scope:
         return
     # Select whole module instantiation
     r = sublimeutil.expand_to_scope(self.view, 'meta.module.inst', r)
     if self.view.classify(r.a) & sublime.CLASS_LINE_START == 0:
         r.a = self.view.find_by_class(r.a, False, sublime.CLASS_LINE_START)
     # print(self.view.substr(r))
     txt = verilogutil.clean_comment(self.view.substr(r))
     # Parse module definition
     mname = re.findall(r'\w+', txt)[0]
     filelist = self.view.window().lookup_symbol_in_index(mname)
     if not filelist:
         return
     for f in filelist:
         fname = sublimeutil.normalize_fname(f[0])
         mi = verilogutil.parse_module_file(fname, mname, no_inst=True)
         if mi:
             break
     if not mi:
         sublime.status_message(
             'Unable to retrieve module information for ' + mname)
         return
     settings = self.view.settings()
     mpl = [x['name'] for x in mi['port']]
     mpal = [x['name'] for x in mi['param']]
     #Extract existing binding
     bl = re.findall(r'(?s)\.(\w+)\s*\(\s*(.*?)\s*\)\s*(,|\))',
                     txt,
                     flags=re.MULTILINE)
     # Handle case of binding by position (TODO: support parameter as well ...)
     if not bl:
         m = re.search(
             r'(?s)(#\s*\((?P<params>.*?)\)\s*)?\s*\w+\s*\((?P<ports>.*?)\)\s*;',
             txt,
             flags=re.MULTILINE)
         pl = m.group('ports')
         if pl:
             pa = pl.split(',')
             bt = ''
             for i, p in enumerate(pa):
                 if i >= len(mpl):
                     break
                 bl.append((mpl[i], p.strip()))
                 bt += '.{portName}({sigName}),\n'.format(
                     portName=bl[-1][0], sigName=bl[-1][1])
             # Replace connection by position by connection by name
             r_tmp = self.view.find(pl, r.a, sublime.LITERAL)
             if r.contains(r_tmp):
                 self.view.replace(edit, r_tmp, bt)
                 # Update region
                 r = sublimeutil.expand_to_scope(self.view,
                                                 'meta.module.inst', r)
     ipl = [x[0] for x in bl]
     # Check for added port
     apl = [x for x in mpl if x not in ipl]
     if apl:
         (decl, ac, wc) = VerilogDoModuleInstCommand.get_connect(
             self, self.view, settings, mi)
         last_char = self.view.substr(sublime.Region(r.a, r.b -
                                                     2)).strip(' \t')[-1]
         b = '\n' if last_char != '\n' else ''
         for p in apl:
             b += "." + p + "("
             if p in ac.keys():
                 b += ac[p]
             else:
                 b += p
             b += "),"
             if p in wc.keys():
                 b += " // TODO: Check connection ! " + wc[p]
             b += "\n"
         # Add binding at the end of the instantiation
         self.view.insert(edit, r.b - 2, b)
     # Check for deleted port
     dpl = [x for x in ipl if x not in mpl and x not in mpal]
     for p in dpl:
         r_tmp = self.view.find(r'(?s)\.' + p + r'\s*\(.*?\)\s*(,|\)\s*;)',
                                r.a)
         if r.contains(r_tmp):
             s = self.view.substr(r_tmp)
             if s[-1] == ';':
                 s_tmp = s[:-1].strip()[:-1]
                 r_tmp.b -= (len(s) - len(s_tmp))
             self.view.erase(edit, r_tmp)
             r_tmp = self.view.full_line(r_tmp.a)
             # cleanup comment
             m = re.search(r'^\s*(\/\/.*)?$', self.view.substr(r_tmp))
             if m:
                 self.view.erase(edit, r_tmp)
     # Print status
     # print('[reconnect] Module   Port list = ' + str(mpl))
     # print('[reconnect] Instance Port list = ' + str(ipl))
     # print('[reconnect]  => Removed Port list = ' + str(dpl))
     # print('[reconnect]  => Added   Port list = ' + str(apl))
     s = ''
     if dpl:
         s += "Removed %d ports: %s\n" % (len(dpl), str(dpl))
     if apl:
         s += "Added %d ports: %s\n" % (len(apl), str(apl))
         decl_clean = ''
         ac_clean = {}
         for p in apl:
             if p in ac:
                 ac_clean[p] = ac[p]
             m = re.search(r'^.*\b' + p + r'\b.*;', decl, re.MULTILINE)
             if m:
                 decl_clean += m.group(0) + '\n'
         for p in ipl:
             if p in wc:
                 wc.pop(p)
         nb_decl = len(decl_clean.splitlines())
         if decl_clean:
             r_start = VerilogDoModuleInstCommand.get_region_decl(
                 self, self.view, settings, r.a)
             self.view.insert(edit, r_start, '\n' + decl_clean)
             s += 'Adding ' + str(nb_decl) + ' signal(s) declaration(s)\n'
         if len(ac_clean) > 0:
             s += 'Non-perfect name match for ' + str(
                 len(ac_clean)) + ' port(s) : ' + str(ac_clean) + '\n'
         if len(wc) > 0:
             s += 'Found ' + str(
                 len(wc)) + ' mismatch(es) for port(s): ' + str(
                     [x for x in wc.keys()]) + '\n'
     if s:
         sublimeutil.print_to_panel(s, 'SystemVerilog')
     # Realign
     self.view.run_command("verilog_align")