Clone of official tools
Diff: targets.py
- Revision:
- 31:8ea194f6145b
- Parent:
- 30:f12ce67666d0
- Child:
- 35:da9c89f8be7d
--- a/targets.py Mon Aug 29 11:56:59 2016 +0100 +++ b/targets.py Wed Jan 04 11:58:24 2017 -0600 @@ -21,10 +21,15 @@ import shutil import inspect import sys +from collections import namedtuple from tools.patch import patch from tools.paths import TOOLS_BOOTLOADERS from tools.utils import json_file_to_dict +__all__ = ["target", "TARGETS", "TARGET_MAP", "TARGET_NAMES", "CORE_LABELS", + "HookError", "generate_py_target", "Target", + "CUMULATIVE_ATTRIBUTES", "get_resolution_order"] + CORE_LABELS = { "ARM7TDMI-S": ["ARM7", "LIKE_CORTEX_ARM7"], "Cortex-M0" : ["M0", "CORTEX_M", "LIKE_CORTEX_M0"], @@ -60,15 +65,58 @@ return CACHES[(func.__name__, args)] return wrapper -class Target(object): + +# Cumulative attributes can have values appended to them, so they +# need to be computed differently than regular attributes +CUMULATIVE_ATTRIBUTES = ['extra_labels', 'macros', 'device_has', 'features'] + + +def get_resolution_order(json_data, target_name, order, level=0): + """ Return the order in which target descriptions are searched for + attributes. This mimics the Python 2.2 method resolution order, which + is what the old targets.py module used. For more details, check + http://makina-corpus.com/blog/metier/2014/python-tutorial-understanding-python-mro-class-search-path + The resolution order contains (name, level) tuples, where "name" is the + name of the class and "level" is the level in the inheritance hierarchy + (the target itself is at level 0, its first parent at level 1, its + parent's parent at level 2 and so on) + """ + # the resolution order can't contain duplicate target names + if target_name not in [l[0] for l in order]: + order.append((target_name, level)) + parents = json_data[target_name].get("inherits", []) + for par in parents: + order = get_resolution_order(json_data, par, order, level + 1) + return order + + +def target(name, json_data): + """Construct a target object""" + resolution_order = get_resolution_order(json_data, name, []) + resolution_order_names = [tgt for tgt, _ in resolution_order] + return Target(name=name, + json_data={key: value for key, value in json_data.items() + if key in resolution_order_names}, + resolution_order=resolution_order, + resolution_order_names=resolution_order_names) + +def generate_py_target(new_targets, name): + """Add one or more new target(s) represented as a Python dictionary + in 'new_targets'. It is an error to add a target with a name that + already exists. + """ + base_targets = Target.get_json_target_data() + for new_target in new_targets.keys(): + if new_target in base_targets: + raise Exception("Attempt to add target '%s' that already exists" + % new_target) + total_data = {} + total_data.update(new_targets) + total_data.update(base_targets) + return target(name, total_data) + +class Target(namedtuple("Target", "name json_data resolution_order resolution_order_names")): """An object to represent a Target (MCU/Board)""" - # Cumulative attributes can have values appended to them, so they - # need to be computed differently than regular attributes - cumulative_attributes = ['extra_labels', 'macros', 'device_has', 'features'] - - # List of targets that were added dynamically using "add_py_targets" (see - # below) - __py_targets = set() # Default location of the 'targets.json' file __targets_json_location_default = os.path.join( @@ -99,24 +147,6 @@ return dict([(m[0], m[1]) for m in inspect.getmembers(sys.modules[__name__])]) - def __get_resolution_order(self, target_name, order, level=0): - """ Return the order in which target descriptions are searched for - attributes. This mimics the Python 2.2 method resolution order, which - is what the old targets.py module used. For more details, check - http://makina-corpus.com/blog/metier/2014/python-tutorial-understanding-python-mro-class-search-path - The resolution order contains (name, level) tuples, where "name" is the - name of the class and "level" is the level in the inheritance hierarchy - (the target itself is at level 0, its first parent at level 1, its - parent's parent at level 2 and so on) - """ - # the resolution order can't contain duplicate target names - if target_name not in [l[0] for l in order]: - order.append((target_name, level)) - parents = self.get_json_target_data()[target_name].get("inherits", []) - for par in parents: - order = self.__get_resolution_order(par, order, level + 1) - return order - @staticmethod def __add_paths_to_progen(data): """Modify the exporter specification ("progen") by changing all @@ -137,14 +167,14 @@ """Look for the attribute in the class and its parents, as defined by the resolution order """ - tdata = self.get_json_target_data() + tdata = self.json_data # For a cumulative attribute, figure out when it was defined the # last time (in attribute resolution order) then follow the "_add" # and "_remove" data fields - for idx, target in enumerate(self.resolution_order): + for idx, tgt in enumerate(self.resolution_order): # the attribute was defined at this level in the resolution # order - if attrname in tdata[target[0]]: + if attrname in tdata[tgt[0]]: def_idx = idx break else: @@ -196,13 +226,13 @@ def __getattr_helper(self, attrname): """Compute the value of a given target attribute""" - if attrname in self.cumulative_attributes: + if attrname in CUMULATIVE_ATTRIBUTES: return self.__getattr_cumulative(attrname) else: - tdata = self.get_json_target_data() + tdata = self.json_data starting_value = None - for target in self.resolution_order: - data = tdata[target[0]] + for tgt in self.resolution_order: + data = tdata[tgt[0]] if data.has_key(attrname): starting_value = data[attrname] break @@ -227,40 +257,11 @@ return result @staticmethod - def add_py_targets(new_targets): - """Add one or more new target(s) represented as a Python dictionary - in 'new_targets'. It is an error to add a target with a name that - already exists. - """ - crt_data = Target.get_json_target_data() - for target_key, target_value in new_targets.items(): - if crt_data.has_key(target_key): - raise Exception( - "Attempt to add target '%s' that already exists" - % target_key) - # Add target data to the internal target dictionary - crt_data[target_key] = target_value - # Create the new target and add it to the relevant data structures - new_target = Target(target_key) - TARGETS.append(new_target) - TARGET_MAP[target_key] = new_target - TARGET_NAMES.append(target_key) - - @staticmethod @cached def get_target(target_name): """ Return the target instance starting from the target name """ - return Target(target_name) - - def __init__(self, target_name): - self.name = target_name + return target(target_name, Target.get_json_target_data()) - # Compute resolution order once (it will be used later in __getattr__) - self.resolution_order = self.__get_resolution_order(self.name, []) - # Create also a list with only the names of the targets in the - # resolution order - self.resolution_order_names = [target[0] for target - in self.resolution_order] @property def program_cycle_s(self): @@ -272,7 +273,8 @@ except AttributeError: return 4 if self.is_disk_virtual else 1.5 - def get_labels(self): + @property + def labels(self): """Get all possible labels for this target""" labels = [self.name] + CORE_LABELS[self.core] + self.extra_labels # Automatically define UVISOR_UNSUPPORTED if the target doesn't @@ -485,6 +487,12 @@ with open(binf.replace(".bin", ".hex"), "w") as fileout: binh.tofile(fileout, format='hex') +class NCS36510TargetCode: + @staticmethod + def ncs36510_addfib(t_self, resources, elf, binf): + from tools.add_fib import add_fib_at_start + print("binf ", binf) + add_fib_at_start(binf[:-4]) ################################################################################ # Instantiate all public targets @@ -505,9 +513,9 @@ """ Returns dictionary mapping detect_code -> platform_name """ result = {} - for target in TARGETS: - for detect_code in target.detect_code: - result[detect_code] = target.name + for tgt in TARGETS: + for detect_code in tgt.detect_code: + result[detect_code] = tgt.name return result def set_targets_json_location(location=None): @@ -518,9 +526,9 @@ # 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(target) for target, obj + TARGETS[:] = [Target.get_target(tgt) for tgt, obj in Target.get_json_target_data().items() if obj.get("public", True)] TARGET_MAP.clear() - TARGET_MAP.update(dict([(target.name, target) for target in TARGETS])) + TARGET_MAP.update(dict([(tgt.name, tgt) for tgt in TARGETS])) TARGET_NAMES[:] = TARGET_MAP.keys()