ldgen: allow multiple mapping fragments to map same library

This commit is contained in:
Renz Christian Bagaporo 2019-04-05 14:32:21 +08:00
parent 87aa341e97
commit 8ee90ee2f1
3 changed files with 121 additions and 15 deletions

View file

@ -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

View file

@ -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:

View file

@ -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()