diff options
-rwxr-xr-x | bin/analyze-archive.py | 5 | ||||
-rwxr-xr-x | lib/automata.py | 34 | ||||
-rw-r--r-- | lib/dfatool.py | 21 |
3 files changed, 43 insertions, 17 deletions
diff --git a/bin/analyze-archive.py b/bin/analyze-archive.py index 8470ab6..a70b23b 100755 --- a/bin/analyze-archive.py +++ b/bin/analyze-archive.py @@ -74,7 +74,7 @@ Options: Load DFA hardware model from JSON or YAML --export-energymodel=<model.json> - Export energy model. Requires --hwmodel. + Export energy model. Works out of the box for v1 and v2 logfiles. Requires --hwmodel for v0 logfiles. """ import getopt @@ -283,6 +283,9 @@ if __name__ == '__main__': print('No valid data available. Abort.') sys.exit(2) + if pta is None and raw_data.pta is not None: + pta = PTA.from_json(raw_data.pta) + by_name, parameters, arg_count = pta_trace_to_aggregate(preprocessed_data, ignored_trace_indexes) filter_aggregate_by_param(by_name, parameters, opts['filter-param']) diff --git a/lib/automata.py b/lib/automata.py index 2c21389..d36acd7 100755 --- a/lib/automata.py +++ b/lib/automata.py @@ -914,17 +914,25 @@ class PTA: def update(self, static_model, param_model): for state in self.state.values(): if state.name != 'UNINITIALIZED': - state.power = static_model(state.name, 'power') - if param_model(state.name, 'power'): - state.power_function = param_model(state.name, 'power')['function'] + try: + state.power = static_model(state.name, 'power') + if param_model(state.name, 'power'): + state.power_function = param_model(state.name, 'power')['function'] + except KeyError: + print('[W] skipping model update of state {} due to missing data'.format(state.name)) + pass for transition in self.transitions: - transition.duration = static_model(transition.name, 'duration') - if param_model(transition.name, 'duration'): - transition.duration_function = param_model(transition.name, 'duration')['function'] - transition.energy = static_model(transition.name, 'energy') - if param_model(transition.name, 'energy'): - transition.energy_function = param_model(transition.name, 'energy')['function'] - if transition.is_interrupt: - transition.timeout = static_model(transition.name, 'timeout') - if param_model(transition.name, 'timeout'): - transition.timeout_function = param_model(transition.name, 'timeout')['function'] + try: + transition.duration = static_model(transition.name, 'duration') + if param_model(transition.name, 'duration'): + transition.duration_function = param_model(transition.name, 'duration')['function'] + transition.energy = static_model(transition.name, 'energy') + if param_model(transition.name, 'energy'): + transition.energy_function = param_model(transition.name, 'energy')['function'] + if transition.is_interrupt: + transition.timeout = static_model(transition.name, 'timeout') + if param_model(transition.name, 'timeout'): + transition.timeout_function = param_model(transition.name, 'timeout')['function'] + except KeyError: + print('[W] skipping model update of transition {} due to missing data'.format(state.name)) + pass
\ No newline at end of file diff --git a/lib/dfatool.py b/lib/dfatool.py index 6b5b523..9583d73 100644 --- a/lib/dfatool.py +++ b/lib/dfatool.py @@ -560,10 +560,11 @@ class RawData: self.preprocessed = False self._parameter_names = None self.ignore_clipping = False + self.pta = None with tarfile.open(filenames[0]) as tf: for member in tf.getmembers(): - if member.name == 'ptalog.json': + if member.name == 'ptalog.json' and self.version == 0: self.version = 1 # might also be version 2 # depends on whether *.etlog exists or not @@ -585,6 +586,8 @@ class RawData: cache_data = json.load(f) self.traces = cache_data['traces'] self.preprocessing_stats = cache_data['preprocessing_stats'] + if 'pta' in cache_data: + self.pta = cache_data['pta'] self.preprocessed = True def save_cache(self): @@ -595,7 +598,8 @@ class RawData: with open(self.cache_file, 'w') as f: cache_data = { 'traces': self.traces, - 'preprocessing_stats': self.preprocessing_stats + 'preprocessing_stats': self.preprocessing_stats, + 'pta': self.pta, } json.dump(cache_data, f) @@ -909,6 +913,13 @@ class RawData: # offline_aggregates['rel_energy_next'].append(offline_trace_part['W_mean_delta_next'] * offline_trace_part['s'] * 1e12) def _concatenate_traces(self, list_of_traces): + """ + Concatenate `list_of_traces` (list of lists) into a single trace while adjusting trace IDs. + + :param list_of_traces: List of list of traces. + :returns: List of traces with ['id'] in ascending order and ['orig_id'] as previous ['id'] + """ + trace_output = list() for trace in list_of_traces: trace_output.extend(trace.copy()) @@ -1007,6 +1018,7 @@ class RawData: new_filenames = list() with tarfile.open(filename) as tf: ptalog = json.load(tf.extractfile(tf.getmember('ptalog.json'))) + self.pta = ptalog['pta'] # Benchmark code may be too large to be executed in a single # run, so benchmarks (a benchmark is basically a list of DFA runs) @@ -1056,6 +1068,7 @@ class RawData: new_filenames = list() with tarfile.open(filename) as tf: ptalog = json.load(tf.extractfile(tf.getmember('ptalog.json'))) + self.pta = ptalog['pta'] # Benchmark code may be too large to be executed in a single # run, so benchmarks (a benchmark is basically a list of DFA runs) @@ -2168,7 +2181,9 @@ class EnergyTraceLog: Expects an EnergyTrace log file generated via msp430-etv / energytrace-util and a dfatool-generated benchmark. An EnergyTrace log consits of a series of measurements. Each measurement has a timestamp, mean current, voltage, - and cumulative energy since start of measurement. + and cumulative energy since start of measurement. Each transition is + preceded by a Code128 barcode embedded into the energy consumption by + toggling a LED. Note that the baseline power draw of board and peripherals is not subtracted at the moment. |