diff --git a/tools/ldgen/fragments.py b/tools/ldgen/fragments.py index dd8295f86..0339f5849 100644 --- a/tools/ldgen/fragments.py +++ b/tools/ldgen/fragments.py @@ -279,6 +279,7 @@ class Mapping(Fragment): def __init__(self): Fragment.__init__(self) self.entries = set() + self.deprecated = False def set_key_value(self, key, parse_results): if key == "archive": @@ -382,6 +383,7 @@ class DeprecatedMapping(): fragment = Mapping() fragment.archive = toks[0].archive fragment.name = re.sub(r"[^0-9a-zA-Z]+", "_", fragment.archive) + fragment.deprecated = True fragment.entries = set() condition_true = False diff --git a/tools/ldgen/generation.py b/tools/ldgen/generation.py index b411c56b4..686defc3a 100644 --- a/tools/ldgen/generation.py +++ b/tools/ldgen/generation.py @@ -334,8 +334,8 @@ class GenerationModel: # Generate rules based on mapping fragments for mapping in self.mappings.values(): - mapping_rules = list() archive = mapping.archive + mapping_rules = all_mapping_rules[archive] for (obj, symbol, scheme_name) in mapping.entries: try: if not (obj == Mapping.MAPPING_ALL_OBJECTS and symbol is None and @@ -345,8 +345,6 @@ class GenerationModel: message = GenerationException.UNDEFINED_REFERENCE + " to scheme '" + scheme_name + "'." raise GenerationException(message, mapping) - all_mapping_rules[mapping.archive] = mapping_rules - # Detect rule conflicts for mapping_rules in all_mapping_rules.items(): self._detect_conflicts(mapping_rules) @@ -453,21 +451,24 @@ class GenerationModel: for fragment in fragment_file.fragments: dict_to_append_to = None - if isinstance(fragment, Scheme): - dict_to_append_to = self.schemes - elif isinstance(fragment, Sections): - dict_to_append_to = self.sections + if isinstance(fragment, Mapping) and fragment.deprecated and fragment.name in self.mappings.keys(): + self.mappings[fragment.name].entries |= fragment.entries else: - dict_to_append_to = self.mappings + if isinstance(fragment, Scheme): + dict_to_append_to = self.schemes + elif isinstance(fragment, Sections): + dict_to_append_to = self.sections + 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) + # 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 + 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 48f7742f7..ec5de6728 100755 --- a/tools/ldgen/test/test_generation.py +++ b/tools/ldgen/test/test_generation.py @@ -1246,6 +1246,109 @@ entries: self.compare_rules(expected, actual) + def test_rule_generation_multiple_deprecated_mapping_definitions(self): + multiple_deprecated_definitions = u""" +[mapping] +archive: lib.a +entries: + : PERFORMANCE_LEVEL = 0 + : PERFORMANCE_LEVEL = 1 + obj1 (noflash) + : PERFORMANCE_LEVEL = 2 + obj1 (noflash) + : PERFORMANCE_LEVEL = 3 + obj1 (noflash) + +[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) +""" + + for perf_level in range(0, 4): + self.sdkconfig.config.syms["PERFORMANCE_LEVEL"].set_value(str(perf_level)) + + self.model.mappings = {} + self.add_fragments(multiple_deprecated_definitions) + + actual = self.model.generate_rules(self.sections_info) + expected = self.generate_default_rules() + + if perf_level < 4: + for append_no in range(1, perf_level + 1): + flash_text_default = self.get_default("flash_text", expected) + flash_rodata_default = self.get_default("flash_rodata", expected) + + 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) + + def test_rule_generation_multiple_mapping_definitions(self): + multiple_deprecated_definitions = u""" +[mapping:base] +archive: lib.a +entries: + if PERFORMANCE_LEVEL = 1: + obj1 (noflash) + elif PERFORMANCE_LEVEL = 2: + obj1 (noflash) + elif PERFORMANCE_LEVEL = 3: + obj1 (noflash) + else: + * (default) + +[mapping:extra] +archive: lib.a +entries: + if PERFORMANCE_LEVEL = 1: + obj1 (noflash) # ignore duplicate definition + elif PERFORMANCE_LEVEL = 2: + obj2 (noflash) + elif PERFORMANCE_LEVEL = 3: + obj2 (noflash) + obj3 (noflash) + else: + * (default) +""" + + for perf_level in range(0, 4): + self.sdkconfig.config.syms["PERFORMANCE_LEVEL"].set_value(str(perf_level)) + + self.model.mappings = {} + self.add_fragments(multiple_deprecated_definitions) + + actual = self.model.generate_rules(self.sections_info) + expected = self.generate_default_rules() + + if perf_level < 4: + for append_no in range(1, perf_level + 1): + flash_text_default = self.get_default("flash_text", expected) + flash_rodata_default = self.get_default("flash_rodata", expected) + + 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()