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_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_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 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 is_predefined_node(n): k = iirs.Get_Kind(n) if k == iirs.Iir_Kind.Interface_Constant_Declaration \ and iirs.Get_Identifier(n) == 0: return True if k == iirs.Iir_Kind.Function_Declaration \ and iirs.Get_Implicit_Definition(n) < iirs.Iir_Predefined.PNone: return True return False
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 get_identifier_str(n): """Return the identifier (as it appears in the sources) for node n. The node n must have an identifier field. There is no case conversion.""" ident = iirs.Get_Identifier(n) id_len = thin.Get_Name_Length(ident) loc = iirs.Get_Location(n) fe = thin.Location_To_File(loc) pos = thin.Location_File_To_Pos(loc, fe) fptr = thin.Get_File_Buffer(fe) return ctypes.string_at(fptr + pos, id_len).decode('latin-1')
def add_identifier(self, dct, decl): id = iirs.Get_Identifier(decl) if id >= std_names.Name.First_Keyword \ and id <= std_names.Name.Last_Vhdl93: # An operator (like "and") return if id >= std_names.Name.First_Operator \ and id <= std_names.Name.Last_Operator: # An operator (like "/=") return if id >= std_names.Name.First_Character \ and id <= std_names.Name.Last_Character: # A character return dct.add(id)
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 find_handler(self, n): """Return the function to comparse the definition with the reference.""" dfn_loc = iirs.Get_Location(n) dfn_file = thin.Location_To_File(dfn_loc) handler = self._handlers.get(dfn_file, None) if handler: return handler if dfn_loc == thin.Library_Location.value: handler = self.get_lower else: while iirs.Get_Kind(n) != iirs.Iir_Kind.Library_Declaration: n = iirs.Get_Parent(n) lib_id = iirs.Get_Identifier(n) if lib_id == std_names.Name.Std: handler = self.get_standard elif lib_id == std_names.Name.Ieee: handler = self.get_lower else: handler = self.get_user self._handlers[dfn_file] = handler return handler
def check(self, input, node): if iirs.Get_Kind(node) == iirs.Iir_Kind.Enumeration_Literal: if iirs.Get_Identifier(node) <= std_names.Name.Last_Character: self.error( Location.from_node(node), "character not allowed in enumeration declaration")