From 5f11cc1a24224cec00ec6d3ef48f84ac8ab91348 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kocsis=20Andr=C3=A1s=20Gerg=C5=91?= Date: Mon, 22 Jul 2019 18:25:22 +0200 Subject: [PATCH] Adding comments and docstrings and constants Details: - Adding constants that define the compiler names - Updating the test_project global config with the new compiler names - Updating the factories with the new compiler names --- doc/test_project/globalConfig.json | 4 +- emma_libs/mapfileProcessorFactory.py | 11 ++++- emma_libs/memoryManager.py | 50 ++++++++++++++++------- emma_libs/memoryMap.py | 36 ++++++++-------- emma_libs/specificConfiguration.py | 27 ++++++++++++ emma_libs/specificConfigurationFactory.py | 11 ++++- shared_libs/stringConstants.py | 2 + 7 files changed, 107 insertions(+), 34 deletions(-) diff --git a/doc/test_project/globalConfig.json b/doc/test_project/globalConfig.json index e2a8303..cccdacf 100644 --- a/doc/test_project/globalConfig.json +++ b/doc/test_project/globalConfig.json @@ -1,11 +1,11 @@ { "MCU": { - "compiler": "GreenHills", + "compiler": "GreenHillsCompiler", "addressSpacesPath": "addressSpaces_MCU.json", "patternsPath": "patterns_MCU.json" }, "SOC": { - "compiler": "GreenHills", + "compiler": "GreenHillsCompiler", "addressSpacesPath": "addressSpaces_SOC.json", "patternsPath": "patterns_SOC.json", "virtualSectionsPath": "virtualSections_SOC.json" diff --git a/emma_libs/mapfileProcessorFactory.py b/emma_libs/mapfileProcessorFactory.py index 02a9c93..2fd518a 100644 --- a/emma_libs/mapfileProcessorFactory.py +++ b/emma_libs/mapfileProcessorFactory.py @@ -19,12 +19,21 @@ from pypiscout.SCout_Logger import Logger as sc +from shared_libs.stringConstants import * import emma_libs.ghsMapfileProcessor def createSpecificMapfileProcesor(compiler, *args): + """ + A factory for creating an object of one of the subclasses of the SpecificMapfileProcessor class. + The concrete subclass is selected based on the received compiler name. + :param compiler: The compiler name. + :param args: The arguments that will be forwarded to the constructor during the object creation. + :return: An object of the selected subclass of the SpecificMapfileProcessor. + """ + mapfileProcessor = None - if "GreenHills" == compiler: + if COMPILER_NAME_GHS == compiler: mapfileProcessor = emma_libs.ghsMapfileProcessor.GhsMapfileProcessor(*args) else: sc().error("Unexpected compiler value: " + compiler) diff --git a/emma_libs/memoryManager.py b/emma_libs/memoryManager.py index 2ce306c..3e90794 100644 --- a/emma_libs/memoryManager.py +++ b/emma_libs/memoryManager.py @@ -31,7 +31,13 @@ class MemoryManager: + """ + A class to organize the processing of the configuration and the mapfiles and the storage of the created reports. + """ class Settings: + """ + Settings that influence the operation of the MemoryManager object. + """ def __init__(self, projectName, configurationPath, mapfilesPath, outputPath, analyseDebug, createCategories, removeUnmatched, noPrompt): self.projectName = projectName self.configurationPath = configurationPath @@ -55,6 +61,10 @@ def __init__(self, projectName, configurationPath, mapfilesPath, outputPath, ana self.categorisation = None def readConfiguration(self): + """ + A method to read the configuration. + :return: None + """ # Reading in the configuration self.configuration = emma_libs.configuration.Configuration() self.configuration.readConfiguration(self.settings.configurationPath, self.settings.mapfilesPath, self.settings.noPrompt) @@ -66,6 +76,10 @@ def readConfiguration(self): self.settings.noPrompt) def processMapfiles(self): + """ + A method to process the mapfiles. + :return: None + """ # If the configuration was already loaded if self.configuration is not None: @@ -108,17 +122,25 @@ def processMapfiles(self): sc().error("The configuration needs to be loaded before processing the mapfiles!") def createReports(self): - # Putting the same consumer collection types together - # (At this points the collections are grouped by configId then by their types) - consumerCollections = {} - for configId in self.memoryContent.keys(): - for collectionType in self.memoryContent[configId].keys(): - if collectionType not in consumerCollections: - consumerCollections[collectionType] = [] - consumerCollections[collectionType].extend(self.memoryContent[configId][collectionType]) - - # Creating reports from the consumer colections - for collectionType in consumerCollections.keys(): - reportPath = emma_libs.memoryMap.createReportPath(self.settings.outputPath, self.settings.projectName, collectionType) - emma_libs.memoryMap.writeReportToDisk(reportPath, consumerCollections[collectionType]) - sc().info("A report was stored:", os.path.abspath(reportPath)) + """ + A method to create the reports. + :return: None + """ + # If the mapfiles were already processed + if self.memoryContent is not None: + # Putting the same consumer collection types together + # (At this points the collections are grouped by configId then by their types) + consumerCollections = {} + for configId in self.memoryContent.keys(): + for collectionType in self.memoryContent[configId].keys(): + if collectionType not in consumerCollections: + consumerCollections[collectionType] = [] + consumerCollections[collectionType].extend(self.memoryContent[configId][collectionType]) + + # Creating reports from the consumer colections + for collectionType in consumerCollections.keys(): + reportPath = emma_libs.memoryMap.createReportPath(self.settings.outputPath, self.settings.projectName, collectionType) + emma_libs.memoryMap.writeReportToDisk(reportPath, consumerCollections[collectionType]) + sc().info("A report was stored:", os.path.abspath(reportPath)) + else: + sc().error("The mapfiles need to be processed before creating the reports!") diff --git a/emma_libs/memoryMap.py b/emma_libs/memoryMap.py index 9949dee..80702b5 100644 --- a/emma_libs/memoryMap.py +++ b/emma_libs/memoryMap.py @@ -26,6 +26,7 @@ from shared_libs.stringConstants import * import shared_libs.emma_helper +import emma_libs.memoryEntry # Timestamp for the report file names @@ -34,16 +35,15 @@ def resolveDuplicateContainmentOverlap(consumerCollection, memEntryHandler): """ - Goes trough the consumerCollection and checks all the elements for the following situations: + Goes trough the consumerCollection and checks and resolves all the elements for the following situations: 1 - Duplicate 2 - Containment 3 - Overlap - Assumptions: - - The consumerCollection is a list of MemEntry objects: - - It is ordered based on the startAddress attribute - - :param nameGetter: A function to get the name of the element. This is solved in this abstract way so it can work for section and object resolving as well. + :param consumerCollection: A list of MemEntry objects. It must be ordered increasingly based on the startAddress attribute of the elements. + The elements of the list will be changed during the processing. + :param memEntryHandler: A subclass of the MemEntryHandler class. + :return: None """ for actualElement in consumerCollection: for otherElement in consumerCollection: @@ -98,13 +98,17 @@ def resolveDuplicateContainmentOverlap(consumerCollection, memEntryHandler): def calculateObjectsInSections(sectionContainer, objectContainer): """ - Assumptions: - - The sectionCollection is a list of MemEntry objects: - - It is ordered based on the startAddress attribute - - The overlapping sections are already edited and the addresses corrected - - The objectCollection is a list of MemEntry objects - - It is ordered based on the startAddress attribute - - The overlapping objects are already edited and the addresses corrected + Creating a list of MemEntry objects from two lists of MemEntry objects that are representing the sections and objects. + These two lists will merged together. + From sections, new elements will be created: + - Section entry: A MemEntry object that describes the section but does not use memory space. + - Section reserce: A MemEntry object that describes the unused part of a section that was not filled up with objects. + + :param sectionContainer: A list of MemEntry objects. It must be ordered increasingly based on the startAddress attribute of the elements. + The overlapping, containing, duplicate sections must be are already edited and the addresses and lengths corrected. + :param objectContainer: A list of MemEntry objects. It must be ordered increasingly based on the startAddress attribute of the elements. + The overlapping, containing, duplicate sections must be are already edited and the addresses and lengths corrected. + :return: A list of MemEntry objects that contains all the elements of the sectionContainer and the objectContainer. """ objectsInSections = [] @@ -219,9 +223,9 @@ def createReportPath(outputPath, projectName, reportName): def writeReportToDisk(reportPath, consumerCollection): """ - Writes the consumerCollection containig MemoryEntrys to CSV - :param filepath: Absolute path to the csv file - :param consumerCollection: List containing memEntrys + Writes the consumerCollection containing MemEntry objects to a CSV file. + :param reportPath: A path of the CSV that needs to be created. + :param consumerCollection: A list of MemEntry objects. """ with open(reportPath, "w") as fp: writer = csv.writer(fp, delimiter=";", lineterminator="\n") diff --git a/emma_libs/specificConfiguration.py b/emma_libs/specificConfiguration.py index 32648d4..1d7e6d4 100644 --- a/emma_libs/specificConfiguration.py +++ b/emma_libs/specificConfiguration.py @@ -21,14 +21,41 @@ class SpecificConfiguration(abc.ABC): + """ + Abstract parent class for classes that represent the compiler specific configuration. + """ @abc.abstractmethod def __init__(self, noPrompt): + """ + Constructor of the SpecificConfiguration class. The functionality that is required to be implemented is the + storage of settings that are the parameters of the constructor. + :param noPrompt: False if during the calls to the methods can contain user prompts. + If True, then no user prompts shall be made. It is suggested that the programs fails in case + they can not decide the necessary action. + """ pass @abc.abstractmethod def readConfiguration(self, configurationPath, mapfilesPath, configId, configuration) -> None: + """ + This function will be called to read in and process the compiler specific parts of the configuration. + These parts of the configuration will be used during the compiler specific mapfile processing. + :param configurationPath: Path of the directory that contains the configuration files. + :param mapfilesPath: Path of the directory that contains the mapfiles. + :param configId: The configId to which the configuration belongs. + :param configuration: The configuration dictionary to which the configuration elements need to be added. + :return: None + """ pass @abc.abstractmethod def checkConfiguration(self, configId, configuration) -> bool: + """ + This function will be called after the readconfiguration() to check whether the configuration is correct. + The checks are fully compiler specific, there are no requirements for them. Based on the result of this function, + the configuration may be not analysed if it was marked incorrect. + :param configId: The configId to which the configuration belongs. + :param configuration: The configuration that needs to be checked. + :return: True if the configuration is correct, False otherwise. + """ pass diff --git a/emma_libs/specificConfigurationFactory.py b/emma_libs/specificConfigurationFactory.py index 41c945b..df94c28 100644 --- a/emma_libs/specificConfigurationFactory.py +++ b/emma_libs/specificConfigurationFactory.py @@ -19,12 +19,21 @@ from pypiscout.SCout_Logger import Logger as sc +from shared_libs.stringConstants import * import emma_libs.ghsConfiguration def createSpecificConfiguration(compiler, *args): + """ + A factory for creating an object of one of the subclasses of the SpecificConfiguration class. + The concrete subclass is selected based on the received compiler name. + :param compiler: The compiler name. + :param args: The arguments that will be forwarded to the constructor during the object creation. + :return: An object of the selected subclass of the SpecificConfiguration. + """ + configuration = None - if "GreenHills" == compiler: + if COMPILER_NAME_GHS == compiler: configuration = emma_libs.ghsConfiguration.GhsConfiguration(*args) else: sc().error("Unexpected compiler value: " + compiler) diff --git a/shared_libs/stringConstants.py b/shared_libs/stringConstants.py index 4ba8af6..74dad3d 100644 --- a/shared_libs/stringConstants.py +++ b/shared_libs/stringConstants.py @@ -288,3 +288,5 @@ ".mr_rw_NandFlashDataBuffer" } )) + +COMPILER_NAME_GHS = "GreenHillsCompiler"