Răsfoiți Sursa

ldgen: determinism in mapping rule order

This MR imposes some determinism in the mapping rule order in the output
file. For each section, the archives are arranged alphabetically
(ascending), and the mapping rules in each archive are arranged by
increasing specificity then alphabetically (ascending). The default
rules remain the very first rule for each section.
Renz Bagaporo 5 ani în urmă
părinte
comite
4011393920
2 a modificat fișierele cu 62 adăugiri și 3 ștergeri
  1. 6 3
      tools/ldgen/generation.py
  2. 56 0
      tools/ldgen/test/test_generation.py

+ 6 - 3
tools/ldgen/generation.py

@@ -322,8 +322,6 @@ class GenerationModel:
         return scheme_dictionary
 
     def generate_rules(self, sections_infos):
-        placement_rules = collections.defaultdict(list)
-
         scheme_dictionary = self._build_scheme_dictionary()
 
         # Generate default rules
@@ -353,14 +351,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())
+
+        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():

+ 56 - 0
tools/ldgen/test/test_generation.py

@@ -1349,6 +1349,62 @@ entries:
 
             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
+        test = u"""
+[mapping:freertos2]
+archive: libfreertos2.a
+entries:
+    croutine2 (noflash_text)
+    croutine (noflash_text)
+
+[mapping:freertos]
+archive: libfreertos.a
+entries:
+    croutine:prvCheckPendingReadyList (noflash_text)
+    croutine:prvCheckDelayedList (noflash_text)
+"""
+        self.add_fragments(test)
+
+        actual = self.model.generate_rules(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"])
+        self.assertListEqual(actual["iram0_text"], expected["iram0_text"])
+
 
 if __name__ == "__main__":
     unittest.main()