def check_name(self, node, name): orig_name = name if len(name) > 2 and name[-2] == '_' and name[-1] in 'oib': name = name[:-2] if name.endswith('_n'): name = name[:-2] if name.endswith('_a'): name = name[:-2] while True: if name.endswith('_p'): name = name[:-2] elif name.endswith('_d'): name = name[:-2] elif (len(name) > 3 and name[-3] == '_' and name[-2] == 'd' and name[-1].isdigit()): name = name[:-3] else: break if name.endswith('_n'): self.error( Location.from_node(node), "'_n' suffix of signal '{}' is too early".format(orig_name)) if name.endswith('_a'): self.error( Location.from_node(node), "'_a' suffix of signal '{}' is too early".format(orig_name))
def check(self, input, dsgn): if self._standard_ids is None: self._standard_ids = self.gather_identifiers( thin.Standard_Package.value) pkgs = nodeutils.extract_packages_from_context_clause(dsgn) for pkg in pkgs: lib = iirs.Get_Library( iirs.Get_Design_File(iirs.Get_Design_Unit(pkg))) if iirs.Get_Identifier(lib) == std_names.Name.Ieee \ and pkg not in self._ieee_pkgs: self._ieee_pkgs.append(pkg) self._ieee_ids = self._ieee_ids.union( self.gather_identifiers(pkg)) lu = iirs.Get_Library_Unit(dsgn) for d in thinutils.declarations_iter(lu): id = iirs.Get_Identifier(d) if id in self._standard_ids: self.error( Location.from_node(d), "declaration of {} uses a standard name".format( nodeutils.get_identifier_str(d))) if id in self._ieee_ids: self.error( Location.from_node(d), "declaration of {} uses an ieee name".format( nodeutils.get_identifier_str(d)))
def extract_use(self, n): if iirs.Get_Use_Clause_Chain(n): self.error(Location.from_node(n), "there must be an one package per use") name = iirs.Get_Selected_Name(n) if iirs.Get_Kind(name) != iirs.Iir_Kind.Selected_By_All_Name: self.error(Location.from_node(n), "missing .all after package name") return [] prefix = iirs.Get_Prefix(name) if iirs.Get_Kind(prefix) != iirs.Iir_Kind.Selected_Name: self.error(Location.from_node(n), "use-d name must be a selected name") return [] lib_prefix = iirs.Get_Prefix(prefix) if iirs.Get_Kind(lib_prefix) != iirs.Iir_Kind.Simple_Name: self.error(Location.from_node(n), "use-d prefix name must be a simple name") return [] loc = iirs.Get_Location(n) _, ln, _ = utils.Location_To_File_Line_Col(loc) return [{'kind': 'use', 'node': n, 'name': iirs.Get_Identifier(prefix), 'library': iirs.Get_Identifier(lib_prefix), 'line': ln}]
def check_assocs(self, n, inters, assocs): if assocs == thin.Null_Iir: # Also cover the case of no interfaces return inter = inters for assoc in thinutils.chain_iter(assocs): if iirs.Get_Kind(assoc) \ == iirs.Iir_Kind.Association_Element_By_Individual: continue formal = iirs.Get_Formal(assoc) if formal == thin.Null_Iir: self.error( Location.from_node(assoc), "association by position for {}".format( nodeutils.get_identifier_str(inter))) # Should the tool report all errors ? return assoc_inter = thin.Iirs_Utils.Get_Interface_Of_Formal(formal) while assoc_inter != inter: if inter == thin.Null_Iir: self.error( Location.from_node(assoc), "incorrect association order for {}".format( nodeutils.get_identifier_str(assoc_inter))) return inter = iirs.Get_Chain(inter) if iirs.Get_Whole_Association_Flag(assoc): inter = iirs.Get_Chain(inter)
def check_entity(self, units): ent = iirs.Get_Library_Unit(units[0]) assert iirs.Get_Kind(ent) == iirs.Iir_Kind.Entity_Declaration arch = iirs.Get_Library_Unit(units[1]) if iirs.Get_Kind(arch) != iirs.Iir_Kind.Architecture_Body: self.error(Location.from_node(arch), "second unit of a file must be an architecture") return arch_ent = iirs.Get_Entity_Name(arch) if iirs.Get_Kind(arch_ent) != iirs.Iir_Kind.Simple_Name: # Strictly speaking, a selected name is allowed. self.error(Location.from_node(arch_ent), "weird entity name in architecture") return if iirs.Get_Identifier(arch_ent) != iirs.Get_Identifier(ent): self.error(Location.from_node(arch_ent), "unrelated architecture after entity") return if len(units) == 2: return conf = iirs.Get_Library_Unit(units[2]) if iirs.Get_Kind(conf) != iirs.Iir_Kind.Configuration_Declaration: self.error(Location.from_node(arch), "third unit must be a configuration") # TODO: check it is related to the architecture if len(units) > 3: self.error(Location.from_node(units[3]), "too many units in a file")
def check_register(self, proc, clk, rst): slist = iirs.Get_Sensitivity_List(proc) if not self.in_sensitivity(slist, clk): self.error(Location.from_node(proc), "clock not in sensitivity list") if thin.Lists.Get_Nbr_Elements(slist) != 1: self.error(Location.from_node(proc), "too many signals in sensitivity list")
def check(self, input, node): k = iirs.Get_Kind(node) if k == iirs.Iir_Kind.Group_Declaration: self.error(Location.from_node(node), "group declaration not allowed") elif k == iirs.Iir_Kind.Group_Template_Declaration: self.error(Location.from_node(node), "group template declaration not allowed")
def check(self, input, node): if nodeutils.is_generic(node): s = nodeutils.get_identifier_str(node) if not s.startswith("g_"): self.error(Location.from_node(node), "generic '{0}' must start with 'g_'".format(s)) if not s[2:].isupper(): self.error( Location.from_node(node), "generic '{0}' must be in upper case after 'g_'".format(s))
def check_entity(self, ent): decl = iirs.Get_Declaration_Chain(ent) if decl != thin.Null_Iir: self.error(Location.from_node(decl), "declaration not allowed in entity") first_stmt = iirs.Get_Concurrent_Statement_Chain(ent) for s in thinutils.chain_iter(first_stmt): k = iirs.Get_Kind(s) if k != iirs.Iir_Kind.Concurrent_Assertion_Statement: self.error(Location.from_node(s), "concurrent statement not allowed in entity")
def check(self, input, node): if nodeutils.is_port(node): mode = iirs.Get_Mode(node) if mode == iirs.Iir_Mode.Buffer_Mode: self.error( Location.from_node(node), "buffer port '{0}' not allowed".format( nodeutils.get_identifier_str(node))) elif mode == iirs.Iir_Mode.Linkage_Mode: self.error( Location.from_node(node), "linkage port '{0}' not allowed".format( nodeutils.get_identifier_str(node)))
def check(self, input, node): if iirs.Get_Kind(node) == iirs.Iir_Kind.Block_Statement: hdr = iirs.Get_Block_Header(node) if hdr != thin.Null_Iir: if iirs.Get_Generic_Chain(hdr) != thin.Null_Iir: self.error(Location.from_node(node), "block cannot declare generics") if iirs.Get_Port_Chain(hdr) != thin.Null_Iir: self.error(Location.from_node(node), "block cannot declare ports") if iirs.Get_Guard_Decl(node) != thin.Null_Iir: self.error(Location.from_node(node), "block cannot have an implicit GUARD signal")
def check_predicate(self, p, node, s): """Test predicate :param p: on string :param s:. The predicate shall return an error message in case of error or None if the name is correct.""" res = p(s) if isinstance(res, str): self.error(Location.from_node(node), res) return True elif res is None or res: return False else: self.error(Location.from_node(node), "incorrect name '{}'".format(s)) return True
def check_package(self, units): decl = iirs.Get_Library_Unit(units[0]) assert iirs.Get_Kind(decl) == iirs.Iir_Kind.Package_Declaration bod = iirs.Get_Library_Unit(units[1]) if iirs.Get_Kind(bod) != iirs.Iir_Kind.Package_Body: self.error(Location.from_node(bod), "second unit of a file must be a package body") return if iirs.Get_Identifier(bod) != iirs.Get_Identifier(decl): self.error(Location.from_node(bod), "unrelated package body after package declaration") return if len(units) > 2: self.error(Location.from_node(units[2]), "too many units in a file")
def check(self, input, node): if iirs.Get_Kind(node) == iirs.Iir_Kind.Use_Clause: parent = iirs.Get_Parent(node) if iirs.Get_Kind(parent) != iirs.Iir_Kind.Design_Unit: self.error( Location.from_node(node), "use clause must be global (placed before the unit)")
def report_unused(self, unit): for n in thinutils.declarations_iter(unit): if n in self._used \ or nodeutils.is_predefined_node(n): # Node is used (or not user defined) continue k = iirs.Get_Kind(n) if k in [iirs.Iir_Kind.Function_Body, iirs.Iir_Kind.Procedure_Body]: # Bodies are never referenced. continue if self.is_second_subprogram(n): # Subprogram specification of a body is never referenced. continue if k in iirs.Iir_Kinds.Interface_Object_Declaration: p = iirs.Get_Parent(n) if p != thin.Null_Iir \ and self.is_second_subprogram(p): # Interfaces without parent are from implicit subprograms. # Interfaces of the subprg spec of the body aren't # referenced. continue if k in [iirs.Iir_Kind.Anonymous_Type_Declaration]: # Anonymous types are never referenced. continue if k == iirs.Iir_Kind.Iterator_Declaration \ and thin.Get_Name_Length(iirs.Get_Identifier(n)) == 1: # Loop iterator with a very short name (for i in ...) # Allow it to be unused. continue self.error( Location.from_node(n), "{} is not used".format( nodeutils.get_identifier_str(n)))
def check(self, input, ast): assert iirs.Get_Kind(ast) == iirs.Iir_Kind.Design_File units = thinutils.chain_to_list(iirs.Get_First_Design_Unit(ast)) pattern = '' letter = {iirs.Iir_Kind.Entity_Declaration: 'E', iirs.Iir_Kind.Architecture_Body: 'A', iirs.Iir_Kind.Configuration_Declaration: 'C', iirs.Iir_Kind.Package_Declaration: 'P', iirs.Iir_Kind.Package_Body: 'B'} pattern = ''.join([letter[iirs.Get_Kind(iirs.Get_Library_Unit(u))] for u in units]) if pattern not in self.patterns: self.error(Location(input.filename), "sequence of units not allowed") if len(units) <= 1: # Always ok to have one unit. Zero unit is not allowed by vhdl. return first = iirs.Get_Library_Unit(units[0]) if iirs.Get_Kind(first) == iirs.Iir_Kind.Entity_Declaration: self.check_entity(units) elif iirs.Get_Kind(first) == iirs.Iir_Kind.Package_Declaration: self.check_package(units) else: self.error(Location.from_node(first), "first unit must be either an entity or a package")
def check_declarations(self, decl): decl_col = -1 colon_col = -1 subtype_col = -1 assign_col = -1 line = -1 while decl != thin.Null_Iir: loc = elocations.Get_Start_Location(decl) fe, ln, co = utils.Location_To_File_Line_Col(loc) if ln <= line: self.error(Location.from_node(decl), "one generic/port per line") else: if co != decl_col and decl_col >= 0: self.error(Location.from_node(decl), "name is not aligned with previous one") # Check alignment of ':' colon_loc = elocations.Get_Colon_Location(decl) _, ln1, colon_co = utils.Location_To_File_Line_Col(colon_loc) if colon_co != colon_col and colon_col >= 0: self.error(Location.from_node(decl), "':' is not aligned with previous one") colon_col = colon_co # Check alignment of subtype. st = iirs.Get_Subtype_Indication(decl) if st != thin.Null_Iir: st_loc = thinutils.leftest_location(st) _, ln1, st_co = utils.Location_To_File_Line_Col(st_loc) if st_co != subtype_col and subtype_col >= 0: self.error(Location.from_node(decl), "subtype is not aligned with previous one") subtype_col = st_co # Check alignment of ':=' assign_loc = elocations.Get_Assign_Location(decl) if assign_loc != thin.No_Location: _, ln1, assign_co = \ utils.Location_To_File_Line_Col(assign_loc) if assign_co != assign_col and assign_col >= 0: self.error(Location.from_node(decl), "':=' is not aligned with previous one") assign_col = assign_co decl_col = co line = ln decl = iirs.Get_Chain(decl)
def check(self, input, node): if iirs.Get_Kind(node) == iirs.Iir_Kind.Attribute_Declaration: s = nodeutils.get_identifier_str(node) if string.lower(s) not in self.allowed: self.error( Location.from_node(node), "user attribute declaration for '{0}' not allowed".format( s))
def extract_library(self, n): name = iirs.Get_Identifier(n) if iirs.Get_Has_Identifier_List(n): self.error(Location.from_node(n), "library must be alone") if name == std_names.Name.Std: self.error(Location.from_node(n), "do not use library clause for 'std'") elif name == std_names.Name.Work: self.error(Location.from_node(n), "do not use library clause for 'work'") loc = iirs.Get_Location(n) _, ln, _ = utils.Location_To_File_Line_Col(loc) return [{'kind': 'library', 'node': n, 'name': name, 'line': ln}]
def check(self, input, node): if iirs.Get_Kind(node) == iirs.Iir_Kind.Enumeration_Literal: s = nodeutils.get_identifier_str(node) if not s.isupper(): self.error( Location.from_node(node), "enumeration literal '{0}' must be in upper case".format( s))
def check(self, input, node): k = iirs.Get_Kind(node) if k == iirs.Iir_Kind.Signal_Declaration \ or k == iirs.Iir_Kind.Interface_Signal_Declaration: if iirs.Get_Guarded_Signal_Flag(node): self.error( Location.from_node(node), "signal '{0}' must not be guarded".format( nodeutils.get_identifier_str(node)))
def check_clause(self, cl): name = iirs.Get_Selected_Name(cl) if iirs.Get_Kind(name) == iirs.Iir_Kind.Selected_By_All_Name: name = iirs.Get_Prefix(name) if iirs.Get_Kind(name) != iirs.Iir_Kind.Selected_Name: self.error(Location.from_node(name), "unhandled use clause form") return lib = iirs.Get_Prefix(name) if iirs.Get_Kind(lib) != iirs.Iir_Kind.Simple_Name: self.error(Location.from_node(name), "unhandled use clause form") return if iirs.Get_Identifier(lib) != std_names.Name.Ieee: # User package ? return if iirs.Get_Identifier(name) not in self._allowed_id: self.error( Location.from_node(name), "non-allowed use of IEEE package {}".format( nodeutils.get_identifier_str(name)))
def check(self, input, unit): for n in thinutils.concurrent_stmts_iter(unit): k = iirs.Get_Kind(n) if k == iirs.Iir_Kind.Process_Statement: self.error(Location.from_node(n), "non-sentized process not allowed in synth unit") elif k == iirs.Iir_Kind.Sensitized_Process_Statement: self.check_process(n) else: # Check for non-postponed ? pass
def check(self, input, ast): if 'top' not in input.props: return unit = iirs.Get_Library_Unit(ast) if iirs.Get_Kind(unit) != iirs.Iir_Kind.Entity_Declaration: return for port in thinutils.chain_iter(iirs.Get_Port_Chain(unit)): if not self.check_type(iirs.Get_Type(port)): self.error( Location.from_node(port), "type of port '{0}' must be std_logic/_vector".format( nodeutils.get_identifier_str(port)))
def check(self, input, ast): for node in thinutils.concurrent_stmts_iter(ast): if iirs.Get_Kind(node) not in iirs.Iir_Kinds.Process_Statement: continue if iirs.Get_Label(node) != thin.Null_Identifier: continue loc = iirs.Get_Location(node) fil = thin.Location_To_File(loc) line = thin.Location_File_To_Line(loc, fil) if input.comments.get(line - 1, None) is None: self.error( Location.from_node(node), "missing label or comment for process")
def check(self, input, node): if nodeutils.is_port(node): s = nodeutils.get_identifier_str(node) mode = iirs.Get_Mode(node) if mode == iirs.Iir_Mode.Out_Mode: if not s.endswith('_o'): self.error(Location.from_node(node), "out port '{0}' must end with '_o'".format(s)) elif mode == iirs.Iir_Mode.In_Mode: if not s.endswith('_i'): self.error(Location.from_node(node), "in port '{0}' must end with '_i'".format(s)) elif mode == iirs.Iir_Mode.Inout_Mode: if not s.endswith('_b'): self.error(Location.from_node(node), "inout port '{0}' must end with '_b'".format(s)) elif mode == iirs.Iir_Mode.Buffer_Mode: self.error(Location.from_node(node), "buffer port '{0}' not allowed".format(s)) elif mode == iirs.Iir_Mode.Linkage_Mode: self.error(Location.from_node(node), "linkage port '{0}' not allowed".format(s))
def check_process(self, proc): stmt = iirs.Get_Sequential_Statement_Chain(proc) if nodeutils.is_one_stmt(stmt) \ and iirs.Get_Kind(stmt) == iirs.Iir_Kind.If_Statement: (clk, rst) = self.is_register(stmt) if clk is not None: self.check_register(proc, clk, rst) return slist = iirs.Get_Sensitivity_List(proc) clist = thin.Lists.Create_Iir_List() thin.Canon.Extract_Sequential_Statement_Chain_Sensitivity( iirs.Get_Sequential_Statement_Chain(proc), clist) for el in thinutils.list_iter(clist): if not self.in_sensitivity(slist, el): self.error(Location.from_node(el), "signal not in sensitivity list") thin.Lists.Destroy_Iir_List(clist)
def check(self, input, ast): for du in thinutils.chain_iter(iirs.Get_First_Design_Unit(ast)): ent = iirs.Get_Library_Unit(du) if iirs.Get_Kind(ent) != iirs.Iir_Kind.Entity_Declaration: continue gen = iirs.Get_Generic_Chain(ent) if gen != thin.Null_Iir: self.check_declarations(gen) ports = iirs.Get_Port_Chain(ent) if ports != thin.Null_Iir: self.check_declarations(ports) port = ports while port != thin.Null_Iir: if not iirs.Get_Has_Mode(port): self.error(Location.from_node(port), "in/out/inout required for port") port = iirs.Get_Chain(port)
def check_parenthesis(self, expr): if expr == thin.Null_Iir: # For else clause. return if iirs.Get_Kind(expr) != iirs.Iir_Kind.Parenthesis_Expression: return left_loc = iirs.Get_Location(expr) right_loc = elocations.Get_Right_Paren_Location(expr) fe = thin.Location_To_File(left_loc) assert fe == thin.Location_To_File(right_loc) left_line = thin.Location_File_To_Line(left_loc, fe) right_line = thin.Location_File_To_Line(right_loc, fe) if left_line != right_line: # Assume that's for grouping return self.error(Location.from_node(expr), "useless parenthesis around expression")
def check_identifier(self, node, dfn): if dfn == 0: # Can happen for architecture in entity aspect return ref_str = nodeutils.get_identifier_str(node) handler = self.find_handler(dfn) def_str = handler(dfn, ref_str) if ref_str == def_str: # OK! return if iirs.Get_Kind(dfn) == iirs.Iir_Kind.Guard_Signal_Declaration: # Guard signals are implicitely declared def_str = "GUARD" if ref_str == def_str: return self.error( Location.from_node(node), "{} is not the correct spelling for '{}'".format(ref_str, def_str))