Merge branch 'feature/ldgen_output_determinism_v3.3' into 'release/v3.3'

ldgen: determinism in mapping rule order (v3.3)

See merge request espressif/esp-idf!8662
This commit is contained in:
Angus Gratton 2020-05-13 11:30:48 +08:00
commit 5738c3a9c6
2 changed files with 65 additions and 3 deletions

View file

@ -322,8 +322,6 @@ class GenerationModel:
return scheme_dictionary
def generate_rules(self, sdkconfig, sections_infos):
placement_rules = collections.defaultdict(list)
scheme_dictionary = self._build_scheme_dictionary()
# Generate default rules
@ -373,14 +371,19 @@ class GenerationModel:
for mapping_rules in all_mapping_rules.values():
self._create_exclusions(mapping_rules, default_rules, sections_infos)
placement_rules = collections.defaultdict(list)
# Add the default rules grouped by target
for default_rule in default_rules:
existing_rules = placement_rules[default_rule.target]
if default_rule.get_section_names():
existing_rules.append(default_rule)
for mapping_rules in all_mapping_rules.values():
archives = sorted(all_mapping_rules.keys(), key=lambda a: a.replace("_a", ".a"))
for archive in archives:
# Add the mapping rules grouped by target
mapping_rules = sorted(all_mapping_rules[archive], key=lambda m: (m.specificity, str(m)))
for mapping_rule in mapping_rules:
existing_rules = placement_rules[mapping_rule.target]
if mapping_rule.get_section_names():

View file

@ -1176,6 +1176,65 @@ class GenerationModelTest(unittest.TestCase):
self._compare_rules(expected, actual)
def test_rules_order(self):
# The fragments are structured such that ldgen will:
# - parse freertos2 mapping first
# - entry for prvCheckPendingReadyList is parsed first before prvCheckDelayedList
# We expect that despite this, ldgen will output rules in a set order:
# by increasing specificity and alphabetically
rules_order_mapping_1 = """
[mapping]
archive: libfreertos2.a
entries:
croutine2 (noflash_text)
croutine (noflash_text)
"""
rules_order_mapping_2 = """
[mapping]
archive: libfreertos.a
entries:
croutine:prvCheckPendingReadyList (noflash_text)
croutine:prvCheckDelayedList (noflash_text)
"""
self._add_mapping(rules_order_mapping_2)
self._add_mapping(rules_order_mapping_1)
actual = self.model.generate_rules(self.sdkconfig, self.sections_info)
expected = self._generate_default_rules()
flash_text_default = self._get_default("flash_text", expected)
iram0_text_E1 = PlacementRule("libfreertos2.a", "croutine2", None, self.model.sections["text"].entries, "iram0_text")
iram0_text_E2 = PlacementRule("libfreertos2.a", "croutine", None, self.model.sections["text"].entries, "iram0_text")
iram0_text_E3 = PlacementRule("libfreertos.a", "croutine", "prvCheckPendingReadyList", self.model.sections["text"].entries, "iram0_text")
iram0_text_E4 = PlacementRule("libfreertos.a", "croutine", "prvCheckDelayedList", self.model.sections["text"].entries, "iram0_text")
flash_text_extra = PlacementRule("libfreertos.a", "croutine", None, [".text.*", ".literal.*"], "flash_text")
# Add the exclusions
flash_text_default.add_exclusion(iram0_text_E1, self.sections_info)
flash_text_default.add_exclusion(iram0_text_E2, self.sections_info)
flash_text_default.add_exclusion(flash_text_extra, self.sections_info)
flash_text_extra.add_exclusion(iram0_text_E3, self.sections_info)
flash_text_extra.add_exclusion(iram0_text_E4, self.sections_info)
# Add the rules, arranged by expected order
expected["flash_text"].append(flash_text_extra)
expected["iram0_text"].append(iram0_text_E4)
expected["iram0_text"].append(iram0_text_E3)
expected["iram0_text"].append(iram0_text_E2)
expected["iram0_text"].append(iram0_text_E1)
# Perform general comparison for all sections
self._compare_rules(expected, actual)
# Perform ordered comparison
self.assertListEqual(actual["flash_text"], expected["flash_text"])
if __name__ == "__main__":
unittest.main()