Clone of official tools

Revision:
13:ab47a20b66f0
Parent:
7:5af61d55adbe
Child:
14:ee1b877e6839
--- a/targets.py	Tue Jun 14 11:33:06 2016 +0100
+++ b/targets.py	Thu Jul 14 20:21:19 2016 +0100
@@ -25,6 +25,7 @@
     "Cortex-M4F" : ["M4", "CORTEX_M", "RTOS_M4_M7", "LIKE_CORTEX_M4"],
     "Cortex-M7" : ["M7", "CORTEX_M", "RTOS_M4_M7", "LIKE_CORTEX_M7"],
     "Cortex-M7F" : ["M7", "CORTEX_M", "RTOS_M4_M7", "LIKE_CORTEX_M7"],
+    "Cortex-M7FD" : ["M7", "CORTEX_M", "RTOS_M4_M7", "LIKE_CORTEX_M7"],
     "Cortex-A9" : ["A9", "CORTEX_A", "LIKE_CORTEX_A9"]
 }
 
@@ -50,27 +51,34 @@
 caches = {}
 def cached(func):
     def wrapper(*args, **kwargs):
-        if not caches.has_key(func):
-            caches[func] = func(*args, **kwargs)
-        return caches[func]
+        if not caches.has_key((func.__name__, args)):
+            caches[(func.__name__, args)] = func(*args, **kwargs)
+        return caches[(func.__name__, args)]
     return wrapper
 
 class Target:
     # Cumulative attributes can have values appended to them, so they
     # need to be computed differently than regular attributes
-    __cumulative_attributes = ['extra_labels', 'macros', 'features']
-
-    # {target_name: target_instance} map for all the targets in the system
-    __target_map = {}
+    __cumulative_attributes = ['extra_labels', 'macros', 'device_has', 'features']
 
     # List of targets that were added dynamically using "add_py_targets" (see below)
     __py_targets = set()
 
+    # Location of the 'targets.json' file
+    __targets_json_location = os.path.join(os.path.dirname(os.path.abspath(__file__)), '..', 'hal', 'targets.json')
+
     # Load the description of JSON target data
     @staticmethod
     @cached
     def get_json_target_data():
-        return json_file_to_dict(os.path.join(os.path.dirname(os.path.abspath(__file__)), "targets.json"))
+        return json_file_to_dict(Target.__targets_json_location)
+
+    # Set the location of the targets.json file
+    @staticmethod
+    def set_targets_json_location(location):
+        Target.__targets_json_location = location
+        # Invalidate caches, since the location of the JSON file changed
+        caches.clear()
 
     # Get the members of this module using Python's "inspect" module
     @staticmethod
@@ -202,10 +210,9 @@
 
     # Return the target instance starting from the target name
     @staticmethod
+    @cached
     def get_target(name):
-        if not Target.__target_map.has_key(name):
-            Target.__target_map[name] = Target(name)
-        return Target.__target_map[name]
+        return Target(name)
 
     def __init__(self, name):
         self.name = name
@@ -215,6 +222,7 @@
         # Create also a list with only the names of the targets in the resolution order
         self.resolution_order_names = [t[0] for t in self.resolution_order]
 
+    @property
     def program_cycle_s(self):
         try:
             return self.__getattr__("program_cycle_s")
@@ -222,7 +230,12 @@
             return 4 if self.is_disk_virtual else 1.5
 
     def get_labels(self):
-        return [self.name] + CORE_LABELS[self.core] + self.extra_labels
+        labels = [self.name] + CORE_LABELS[self.core] + self.extra_labels
+        # Automatically define UVISOR_UNSUPPORTED if the target doesn't specifically
+        # define UVISOR_SUPPORTED
+        if not "UVISOR_SUPPORTED" in labels:
+            labels.append("UVISOR_UNSUPPORTED")
+        return labels
 
     # For now, this function only allows "post binary" hooks (hooks that are executed after
     # the binary image is extracted from the executable file)
@@ -410,3 +423,15 @@
         for detect_code in target.detect_code:
             result[detect_code] = target.name
     return result
+
+# Sets the location of the JSON file that contains the targets
+def set_targets_json_location(location):
+    # First instruct Target about the new location
+    Target.set_targets_json_location(location)
+    # Then re-initialize TARGETS, TARGET_MAP and TARGET_NAMES
+    # The re-initialization does not create new variables, it keeps the old ones instead
+    # This ensures compatibility with code that does "from tools.targets import TARGET_NAMES"
+    TARGETS[:] = [Target.get_target(name) for name, value in Target.get_json_target_data().items() if value.get("public", True)]
+    TARGET_MAP.clear()
+    TARGET_MAP.update(dict([(t.name, t) for t in TARGETS]))
+    TARGET_NAMES[:] = TARGET_MAP.keys()