From 2f72645320b8ef19bce17fe4b914618491a33f02 Mon Sep 17 00:00:00 2001 From: Renz Christian Bagaporo Date: Mon, 4 Feb 2019 22:16:34 +0800 Subject: [PATCH] ldgen: allow combining mapping fragment definitions --- tools/ldgen/generation.py | 74 +++++++++++++++++------------ tools/ldgen/test/test_generation.py | 60 ++++++++++++++++++++++- 2 files changed, 101 insertions(+), 33 deletions(-) diff --git a/tools/ldgen/generation.py b/tools/ldgen/generation.py index d42a4284e..7ed486f11 100644 --- a/tools/ldgen/generation.py +++ b/tools/ldgen/generation.py @@ -333,34 +333,37 @@ class GenerationModel: all_mapping_rules = collections.defaultdict(list) # Generate rules based on mapping fragments - for mapping in self.mappings.values(): - for (condition, entries) in mapping.entries: - condition_true = False + for mapping_list in self.mappings.values(): + for mapping in mapping_list: + for (condition, entries) in mapping.entries: + condition_true = False - # Only non-default condition are evaluated agains sdkconfig model - if condition != Mapping.DEFAULT_CONDITION: - try: - condition_true = sdkconfig.evaluate_expression(condition) - except Exception as e: - raise GenerationException(e.message, mapping) - else: - condition_true = True - - if condition_true: - - mapping_rules = list() - - archive = mapping.archive - for (obj, symbol, scheme_name) in entries: + # Only non-default condition are evaluated agains sdkconfig model + if condition != Mapping.DEFAULT_CONDITION: try: - self._add_mapping_rules(archive, obj, symbol, scheme_name, scheme_dictionary, mapping_rules) - except KeyError: - message = GenerationException.UNDEFINED_REFERENCE + " to scheme '" + scheme_name + "'." - raise GenerationException(message, mapping) + condition_true = sdkconfig.evaluate_expression(condition) + except Exception as e: + raise GenerationException(e.message, mapping) + else: + condition_true = True - all_mapping_rules[mapping.name] = mapping_rules + if condition_true: - break # Exit on first condition that evaluates to true + mapping_rules = list() + + archive = mapping.archive + for (obj, symbol, scheme_name) in entries: + try: + self._add_mapping_rules(archive, obj, symbol, scheme_name, scheme_dictionary, mapping_rules) + except KeyError: + message = GenerationException.UNDEFINED_REFERENCE + " to scheme '" + scheme_name + "'." + raise GenerationException(message, mapping) + + for mapping_rule in mapping_rules: + if mapping_rule not in all_mapping_rules[mapping.name]: + all_mapping_rules[mapping.name].append(mapping_rule) + + break # Exit on first condition that evaluates to true # Detect rule conflicts for mapping_rules in all_mapping_rules.items(): @@ -476,14 +479,23 @@ class GenerationModel: else: dict_to_append_to = self.mappings - # Raise exception when the fragment of the same type is already in the stored fragments - if fragment.name in dict_to_append_to.keys(): - stored = dict_to_append_to[fragment.name].path - new = fragment.path - message = "Duplicate definition of fragment '%s' found in %s and %s." % (fragment.name, stored, new) - raise GenerationException(message) + if isinstance(fragment, Mapping): + try: + fragment_list = dict_to_append_to[fragment.name] + except KeyError: + fragment_list = list() + dict_to_append_to[fragment.name] = fragment_list - dict_to_append_to[fragment.name] = fragment + fragment_list.append(fragment) + else: + # Raise exception when the fragment of the same type is already in the stored fragments + if fragment.name in dict_to_append_to.keys(): + stored = dict_to_append_to[fragment.name].path + new = fragment.path + message = "Duplicate definition of fragment '%s' found in %s and %s." % (fragment.name, stored, new) + raise GenerationException(message) + + dict_to_append_to[fragment.name] = fragment class TemplateModel: diff --git a/tools/ldgen/test/test_generation.py b/tools/ldgen/test/test_generation.py index 3a6eed35c..bc8566e76 100755 --- a/tools/ldgen/test/test_generation.py +++ b/tools/ldgen/test/test_generation.py @@ -64,7 +64,12 @@ class GenerationModelTest(unittest.TestCase): def _add_mapping(self, text): parser = Mapping.get_fragment_grammar() fragment = parser.parseString(text, parseAll=True) - self.model.mappings[fragment[0].name] = fragment[0] + try: + mappings = self.model.mappings[fragment[0].name] + except KeyError: + mappings = list() + self.model.mappings[fragment[0].name] = mappings + mappings.append(fragment[0]) def _add_sections(self, text): parser = Sections.get_fragment_grammar() @@ -297,7 +302,6 @@ class GenerationModelTest(unittest.TestCase): self._add_mapping(normal) actual = self.model.generate_rules(self.sdkconfig, self.sections_info) - expected = self._generate_default_rules() flash_text_default = self._get_default("flash_text", expected) @@ -1120,6 +1124,58 @@ class GenerationModelTest(unittest.TestCase): self._compare_rules(expected, actual) + def test_rule_generation_multiple_mapping_definitions(self): + generation_with_condition1 = """ + [mapping] + archive: lib.a + entries: + : PERFORMANCE_LEVEL = 0 + : PERFORMANCE_LEVEL = 1 + obj1 (noflash) + : PERFORMANCE_LEVEL = 2 + obj1 (noflash) + : PERFORMANCE_LEVEL = 3 + obj1 (noflash) + """ + + generation_with_condition2 = """ + [mapping] + archive: lib.a + entries: + : PERFORMANCE_LEVEL = 1 + obj1 (noflash) # ignore duplicate definition + : PERFORMANCE_LEVEL = 2 + obj2 (noflash) + : PERFORMANCE_LEVEL = 3 + obj2 (noflash) + obj3 (noflash) + """ + + self._add_mapping(generation_with_condition1) + self._add_mapping(generation_with_condition2) + + for perf_level in range(0, 4): + self.sdkconfig.config.syms["PERFORMANCE_LEVEL"].set_value(str(perf_level)) + + actual = self.model.generate_rules(self.sdkconfig, self.sections_info) + expected = self._generate_default_rules() + + flash_text_default = self._get_default("flash_text", expected) + flash_rodata_default = self._get_default("flash_rodata", expected) + + if perf_level < 4: + for append_no in range(1, perf_level + 1): + iram_rule = PlacementRule("lib.a", "obj" + str(append_no), None, self.model.sections["text"].entries, "iram0_text") + dram_rule = PlacementRule("lib.a", "obj" + str(append_no), None, self.model.sections["rodata"].entries, "dram0_data") + + flash_text_default.add_exclusion(iram_rule) + flash_rodata_default.add_exclusion(dram_rule) + + expected["iram0_text"].append(iram_rule) + expected["dram0_data"].append(dram_rule) + + self._compare_rules(expected, actual) + if __name__ == "__main__": unittest.main()