diff options
-rw-r--r-- | lib/harness.py | 3 | ||||
-rw-r--r-- | lib/loader.py | 158 | ||||
-rw-r--r-- | lib/runner.py | 17 |
3 files changed, 163 insertions, 15 deletions
diff --git a/lib/harness.py b/lib/harness.py index 3b9db89..7c99f5d 100644 --- a/lib/harness.py +++ b/lib/harness.py @@ -440,9 +440,10 @@ class OnboardTimerHarness(TransitionHarness): return ret def stop_benchmark(self): - ret = super().stop_benchmark() + ret = "" if self.energytrace_sync == "led": ret += "runLASync();\n" + ret += super().stop_benchmark() return ret def pass_transition( diff --git a/lib/loader.py b/lib/loader.py index c0a1694..38d59fc 100644 --- a/lib/loader.py +++ b/lib/loader.py @@ -1621,6 +1621,7 @@ class EnergyTraceWithLogicAnalyzer: transition_names: list, with_traces=False, ): + """ Create a new EnergyTraceWithLogicAnalyzer object. @@ -1636,9 +1637,13 @@ class EnergyTraceWithLogicAnalyzer: self.errors = list() def load_data(self, log_data): - # TODO Daten laden - print("########################") - print(log_data[0].split("\n")[0]) + from data.timing.SigrokInterface import SigrokResult + from data.energy.EnergyInterface import EnergyInterface + + # Daten laden + self.sync_data = SigrokResult.fromString(log_data[0]) + self.energy_data = EnergyInterface.getDataFromString(str(log_data[1])) + pass def analyze_states(self, traces, offline_index: int): @@ -1666,7 +1671,89 @@ class EnergyTraceWithLogicAnalyzer: * `W_mean_delta_next`: Differenz zwischen W_mean und W_mean des Folgezustands """ - # TODO Tatsächlich Daten auswerten + # Tatsächlich Daten auswerten + # +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + # +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + # remove Dirty Data from previously running program (happens if logic Analyzer Measurement starts earlier than + # the HW Reset from energytrace) + use_data_after_index = 0 + for x in range(1, len(self.sync_data.timestamps)): + if self.sync_data.timestamps[x] - self.sync_data.timestamps[x - 1] > 1.3: + use_data_after_index = x + break + + time_stamp_data = self.sync_data.timestamps[use_data_after_index:] + + start_offset = None + start_timestamp = None + end_offset = None + end_timestamp = None + + last_values = [] # maybe needed to flatten the data + plot_data_x = [] + plot_data_y = [] + last_data = [0, 0, 0, 0] + + power_sync_watt = 0.0162 + + # MAIN ENERGY DATA ITERATION + for energytrace_dataset in self.energy_data: + usedtime = energytrace_dataset[0] - last_data[0] + usedenergy = energytrace_dataset[3] - last_data[3] + power = usedenergy / usedtime * 10 ** -3 # in watts + + if power > 0: + if power > power_sync_watt and start_offset is None: + # automatic START offset calculation + start_offset = energytrace_dataset[0] / 1_000_000 - time_stamp_data[0] + start_timestamp = energytrace_dataset[0] / 1_000_000 + if power > power_sync_watt and start_offset is not None: # TODO BETTER + # automatic END offset calculation (Drift) + end_offset = energytrace_dataset[0] / 1_000_000 - time_stamp_data[-1] - start_offset + end_timestamp = energytrace_dataset[0] / 1_000_000 + if len(last_values) > 10: + last_values.pop(0) + last_values.append(power) + # print("%s \tUsed Energy: %i \tUsed Time: %i \tPower: %f \t l_10: %f" % (now_data[0], usedenergy, usedtime, power, sum(last_values) / len(last_values))) + plot_data_x.append(energytrace_dataset[0] / 1_000_000) + plot_data_y.append(power) + + last_data = energytrace_dataset + + # -------------------- + # add start offset to the data + modified_timestamps_with_offset = [] + for x in time_stamp_data: + if x + start_offset >= 0: + modified_timestamps_with_offset.append(x + start_offset) + + # -------------------- + # Add drift to datapoints + modified_timestamps_with_drift = [] + endFactor = (end_timestamp + end_offset - start_timestamp) / (end_timestamp - start_timestamp) + for x in modified_timestamps_with_offset: + modified_timestamps_with_drift.append(((x - start_timestamp) * endFactor) + start_timestamp) + + self.start_offset = 0 + def getPowerBetween(start, end): + first_index = 0 + all_power = 0 + all_power_count = 0 + for ind in range(self.start_offset, len(plot_data_x)): + first_index = ind + if plot_data_x[ind] > start: + break + + for ind in range(first_index, len(plot_data_x)): + all_power += plot_data_y[ind] + all_power_count += 1 + if plot_data_x[ind] > end: + self.start_offset = ind - 1 + break + return all_power / all_power_count + + # +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + # +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ energy_trace = list() @@ -1697,7 +1784,65 @@ class EnergyTraceWithLogicAnalyzer: ) return energy_trace - for name, duration in expected_transitions: + + # +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + # +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + + end_transition_ts = None + timestamps_sync_start = 0 + energy_trace_new = list() + + for ts_index in range(0 + timestamps_sync_start, int(len(modified_timestamps_with_drift) / 2)): + start_transition_ts = modified_timestamps_with_drift[ts_index * 2] + if end_transition_ts is not None: + power = getPowerBetween(end_transition_ts, start_transition_ts) + #print("STATE", end_transition_ts * 10 ** 6, start_transition_ts * 10 ** 6, (start_transition_ts - end_transition_ts) * 10 ** 6, power) + if (start_transition_ts - end_transition_ts) * 10 ** 6 > 900_000 and power > power_sync_watt * 0.9 and ts_index > 10: + #remove last transition and stop (upcoming data only sync) + del energy_trace_new[-1] + break + pass + + state = { + "isa": "state", + "W_mean": power, + "W_std": 0.0001, + "s": (start_transition_ts - end_transition_ts), #* 10 ** 6, + } + energy_trace_new.append(state) + + energy_trace_new[-2]["W_mean_delta_next"] = ( + energy_trace_new[-2]["W_mean"] - energy_trace_new[-1]["W_mean"] + ) + + # get energy end_transition_ts + end_transition_ts = modified_timestamps_with_drift[ts_index * 2 + 1] + power = getPowerBetween(start_transition_ts, end_transition_ts) + #print("TRANS", start_transition_ts * 10 ** 6, end_transition_ts * 10 ** 6, (end_transition_ts - start_transition_ts) * 10 ** 6, power) + transition = { + "isa": "transition", + "W_mean": power, + "W_std": 0.0001, + "s": (end_transition_ts - start_transition_ts), #* 10 ** 6, + } + + if (end_transition_ts - start_transition_ts) * 10 ** 6 > 2_000_000: + # TODO Last data set corrupted? HOT FIX!!!!!!!!!!!! REMOVE LATER + for x in range(4): + del energy_trace_new[-1] + break + pass + + energy_trace_new.append(transition) + # print(start_transition_ts, "-", end_transition_ts, "-", end_transition_ts - start_transition_ts) + + # +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + # +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + + energy_trace_new = energy_trace_new[4:] + + for number, item in enumerate(expected_transitions): + name, duration = item transition = { "isa": "transition", "W_mean": max(np.random.normal(0.023, 0.002), 0), @@ -1725,7 +1870,8 @@ class EnergyTraceWithLogicAnalyzer: energy_trace[-2]["W_mean"] - energy_trace[-1]["W_mean"] ) - return energy_trace + #print(len(energy_trace_new), " - ", len(energy_trace), " - ", ",".join([str(x["s"]) for x in energy_trace_new[-6:]]), " - ", ",".join([str(x["s"]) for x in energy_trace[-6:]])) + return energy_trace_new class EnergyTraceWithTimer(EnergyTraceWithLogicAnalyzer): diff --git a/lib/runner.py b/lib/runner.py index 3a201fc..3092d5a 100644 --- a/lib/runner.py +++ b/lib/runner.py @@ -165,6 +165,7 @@ class EnergyTraceMonitor(SerialMonitor): # Benchmark fertig -> externe Hilfsprogramme beenden def close(self): + print("EnergyTrace Close") super().close() self._logger.send_signal(subprocess.signal.SIGINT) stdout, stderr = self._logger.communicate(timeout=15) @@ -172,6 +173,7 @@ class EnergyTraceMonitor(SerialMonitor): # Zusätzliche Dateien, die mit dem Benchmark-Log und -Plan abgespeichert werden sollen # (hier: Die von msp430-etv generierten Logfiles) def get_files(self) -> list: + print("EnergyTrace Get Files") return [self._output] # Benchmark-Konfiguration. Hier: Die (konstante) Spannung. @@ -189,7 +191,7 @@ class EnergyTraceLogicAnalyzerMonitor(EnergyTraceMonitor): def __init__(self, port: str, baud: int, callback=None, voltage=3.3): super().__init__(port=port, baud=baud, callback=callback, voltage=voltage) - #TODO get length + #TODO Max length options = {'length': 90, 'fake': False, 'sample_rate': 1_000_000} self.log_file = 'logic_output_log_%s.json' % (time.strftime("%Y%m%d-%H%M%S")) @@ -198,23 +200,22 @@ class EnergyTraceLogicAnalyzerMonitor(EnergyTraceMonitor): sample_count=options['length'] * options['sample_rate'], fake=options['fake']) # Start Measurements - print("[ET LA] START MEASURE") self.sig.runMeasureAsynchronous() def close(self): super().close() # Read measured data - print("[ET LA] Wait MEASURE") - self.sig.waitForAsynchronousMeasure() - print("[ET LA] WRITE MEASURE") + #self.sig.waitForAsynchronousMeasure() + self.sig.forceStopMeasure() + time.sleep(0.2) sync_data = self.sig.getData() - print("[ET LA] MEASURE LEN", len(sync_data.timestamps)) with open(self.log_file, 'w') as fp: json.dump(sync_data.getDict(), fp) def get_files(self) -> list: - print("[ET LA] FILE REQUEST") - return [self.log_file] + files = [self.log_file] + files.extend(super().get_files()) + return files class MIMOSAMonitor(SerialMonitor): |