diff options
author | Daniel Friesel <daniel.friesel@uos.de> | 2020-10-13 15:20:21 +0200 |
---|---|---|
committer | Daniel Friesel <daniel.friesel@uos.de> | 2020-10-13 15:20:21 +0200 |
commit | f5125e191ab1db62e4167b00f809dba20bc54b6f (patch) | |
tree | 312ed18c55e42bd90abd98426e899ff1dd582a8c /lib/harness.py | |
parent | c3958b67834268792235faef7cfca86f1d8e8195 (diff) | |
parent | f8cf50af8564094e145124af08e5e12e13ed352f (diff) |
merge
Diffstat (limited to 'lib/harness.py')
-rw-r--r-- | lib/harness.py | 165 |
1 files changed, 131 insertions, 34 deletions
diff --git a/lib/harness.py b/lib/harness.py index ae9c28c..51013e1 100644 --- a/lib/harness.py +++ b/lib/harness.py @@ -33,6 +33,7 @@ class TransitionHarness: log_return_values=False, repeat=0, post_transition_delay_us=0, + energytrace_sync=None, ): """ Create a new TransitionHarness @@ -53,6 +54,7 @@ class TransitionHarness: self.log_return_values = log_return_values self.repeat = repeat self.post_transition_delay_us = post_transition_delay_us + self.energytrace_sync = energytrace_sync self.reset() def copy(self): @@ -63,6 +65,7 @@ class TransitionHarness: log_return_values=self.log_return_values, repeat=self.repeat, post_transition_delay_us=self.post_transition_delay_us, + energytrace_sync=self.energytrace_sync, ) new_object.traces = self.traces.copy() new_object.trace_id = self.trace_id @@ -138,9 +141,7 @@ class TransitionHarness: def start_trace(self): """Prepare a new trace/run in the internal `.traces` structure.""" - self.traces.append( - {"id": self.trace_id, "trace": list(),} - ) + self.traces.append({"id": self.trace_id, "trace": list()}) self.trace_id += 1 def append_state(self, state_name, param): @@ -151,7 +152,7 @@ class TransitionHarness: :param param: parameter dict """ self.traces[-1]["trace"].append( - {"name": state_name, "isa": "state", "parameter": param,} + {"name": state_name, "isa": "state", "parameter": param} ) def append_transition(self, transition_name, param, args=[]): @@ -175,21 +176,16 @@ class TransitionHarness: """Return C++ code used to start a new run/trace.""" return "ptalog.reset();\n" - def _pass_transition_call(self, transition_id): - if self.gpio_mode == "bar": - barcode_bits = Code128("T{}".format(transition_id), charset="B").modules - if len(barcode_bits) % 8 != 0: - barcode_bits.extend([1] * (8 - (len(barcode_bits) % 8))) - barcode_bytes = [ - 255 - int("".join(map(str, reversed(barcode_bits[i : i + 8]))), 2) - for i in range(0, len(barcode_bits), 8) - ] - inline_array = "".join(map(lambda s: "\\x{:02x}".format(s), barcode_bytes)) - return 'ptalog.startTransition("{}", {});\n'.format( - inline_array, len(barcode_bytes) - ) - else: - return "ptalog.startTransition();\n" + def _get_barcode(self, transition_id): + barcode_bits = Code128("T{}".format(transition_id), charset="B").modules + if len(barcode_bits) % 8 != 0: + barcode_bits.extend([1] * (8 - (len(barcode_bits) % 8))) + barcode_bytes = [ + 255 - int("".join(map(str, reversed(barcode_bits[i : i + 8]))), 2) + for i in range(0, len(barcode_bits), 8) + ] + inline_array = "".join(map(lambda s: "\\x{:02x}".format(s), barcode_bytes)) + return inline_array, len(barcode_bytes) def pass_transition( self, transition_id, transition_code, transition: object = None @@ -201,7 +197,12 @@ class TransitionHarness: `post_transition_delay_us` is set. """ ret = "ptalog.passTransition({:d});\n".format(transition_id) - ret += self._pass_transition_call(transition_id) + if self.gpio_mode == "bar": + ret += """ptalog.startTransition("{}", {});\n""".format( + *self._get_barcode(transition_id) + ) + else: + ret += "ptalog.startTransition();\n" if ( self.log_return_values and transition @@ -373,6 +374,7 @@ class OnboardTimerHarness(TransitionHarness): pta=self.pta, log_return_values=self.log_return_values, repeat=self.repeat, + energytrace_sync=self.energytrace_sync, ) new_harness.traces = self.traces.copy() new_harness.trace_id = self.trace_id @@ -398,24 +400,57 @@ class OnboardTimerHarness(TransitionHarness): ] def global_code(self): - ret = '#include "driver/counter.h"\n' - ret += "#define PTALOG_TIMING\n" + ret = "#define PTALOG_TIMING\n" ret += super().global_code() + if self.energytrace_sync == "led": + # TODO Make nicer + ret += """\nvoid runLASync(){ + // ======================= LED SYNC ================================ + ptalog.passTransition(0); + ptalog.startTransition(); + gpio.led_toggle(0); + gpio.led_toggle(1); + ptalog.stopTransition(); + + for (unsigned char i = 0; i < 4; i++) { + arch.sleep_ms(250); + } + + ptalog.passTransition(0); + ptalog.startTransition(); + gpio.led_toggle(0); + gpio.led_toggle(1); + ptalog.stopTransition(); + // ======================= LED SYNC ================================ + arch.sleep_ms(250); +}\n\n""" return ret def start_benchmark(self, benchmark_id=0): - ret = "counter.start();\n" - ret += "counter.stop();\n" - ret += "ptalog.passNop(counter);\n" + ret = "" + if self.energytrace_sync == "led": + ret += "runLASync();\n" + ret += "ptalog.passNop();\n" ret += super().start_benchmark(benchmark_id) return ret + def stop_benchmark(self): + ret = "" + if self.energytrace_sync == "led": + ret += "runLASync();\n" + ret += super().stop_benchmark() + return ret + def pass_transition( self, transition_id, transition_code, transition: object = None ): ret = "ptalog.passTransition({:d});\n".format(transition_id) - ret += self._pass_transition_call(transition_id) - ret += "counter.start();\n" + if self.gpio_mode == "bar": + ret += """ptalog.startTransition("{}", {});\n""".format( + *self._get_barcode(transition_id) + ) + else: + ret += "ptalog.startTransition();\n" if ( self.log_return_values and transition @@ -424,14 +459,13 @@ class OnboardTimerHarness(TransitionHarness): ret += "transition_return_value = {}\n".format(transition_code) else: ret += "{}\n".format(transition_code) - ret += "counter.stop();\n" if ( self.log_return_values and transition and len(transition.return_value_handlers) ): ret += "ptalog.logReturn(transition_return_value);\n" - ret += "ptalog.stopTransition(counter);\n" + ret += "ptalog.stopTransition();\n" return ret def _append_nondeterministic_parameter_value( @@ -453,11 +487,26 @@ class OnboardTimerHarness(TransitionHarness): res.group(1), res.group(2) ) ) - if re.match(r"\[PTA\] benchmark stop", line): + match = re.match(r"\[PTA\] benchmark stop, cycles=(\S+)/(\S+)", line) + if match: self.repetitions += 1 self.synced = False if self.repeat > 0 and self.repetitions == self.repeat: self.done = True + prev_state_cycles = int(match.group(1)) + prev_state_overflow = int(match.group(2)) + prev_state_duration_us = ( + prev_state_cycles * self.one_cycle_in_us + + prev_state_overflow * self.one_overflow_in_us + - self.nop_cycles * self.one_cycle_in_us + ) + final_state = self.traces[self.trace_id]["trace"][-1] + if "offline_aggregates" not in final_state: + final_state["offline_aggregates"] = {"duration": list()} + final_state["offline_aggregates"]["duration"].append( + prev_state_duration_us + ) + print("[HARNESS] done") return # May be repeated, e.g. if the device is reset shortly after start by @@ -473,14 +522,20 @@ class OnboardTimerHarness(TransitionHarness): self.current_transition_in_trace = 0 if self.log_return_values: res = re.match( - r"\[PTA\] transition=(\S+) cycles=(\S+)/(\S+) return=(\S+)", line + r"\[PTA\] transition=(\S+) prevcycles=(\S+)/(\S+) cycles=(\S+)/(\S+) return=(\S+)", + line, ) else: - res = re.match(r"\[PTA\] transition=(\S+) cycles=(\S+)/(\S+)", line) + res = re.match( + r"\[PTA\] transition=(\S+) prevcycles=(\S+)/(\S+) cycles=(\S+)/(\S+)", + line, + ) if res: transition_id = int(res.group(1)) - cycles = int(res.group(2)) - overflow = int(res.group(3)) + prev_state_cycles = int(res.group(2)) + prev_state_overflow = int(res.group(3)) + cycles = int(res.group(4)) + overflow = int(res.group(5)) if overflow >= self.counter_max_overflow: self.abort = True raise RuntimeError( @@ -493,11 +548,28 @@ class OnboardTimerHarness(TransitionHarness): transition_id, ) ) + if prev_state_overflow >= self.counter_max_overflow: + self.abort = True + raise RuntimeError( + "Counter overflow ({:d}/{:d}) in benchmark id={:d} trace={:d}: state before transition #{:d} (ID {:d})".format( + prev_state_cycles, + prev_state_overflow, + 0, + self.trace_id, + self.current_transition_in_trace, + transition_id, + ) + ) duration_us = ( cycles * self.one_cycle_in_us + overflow * self.one_overflow_in_us - self.nop_cycles * self.one_cycle_in_us ) + prev_state_duration_us = ( + prev_state_cycles * self.one_cycle_in_us + + prev_state_overflow * self.one_overflow_in_us + - self.nop_cycles * self.one_cycle_in_us + ) if duration_us < 0: duration_us = 0 # self.traces contains transitions and states, UART output only contains transitions -> use index * 2 @@ -505,6 +577,14 @@ class OnboardTimerHarness(TransitionHarness): log_data_target = self.traces[self.trace_id]["trace"][ self.current_transition_in_trace * 2 ] + if self.current_transition_in_trace > 0: + prev_state_data = self.traces[self.trace_id]["trace"][ + self.current_transition_in_trace * 2 - 1 + ] + elif self.current_transition_in_trace == 0 and self.trace_id > 0: + prev_state_data = self.traces[self.trace_id - 1]["trace"][-1] + else: + prev_state_data = None except IndexError: transition_name = None if self.pta: @@ -531,6 +611,17 @@ class OnboardTimerHarness(TransitionHarness): log_data_target["isa"], ) ) + if prev_state_data and prev_state_data["isa"] != "state": + self.abort = True + raise RuntimeError( + "Log mismatch in benchmark id={:d} trace={:d}: state before transition #{:d} (ID {:d}): Expected state, got {:s}".format( + 0, + self.trace_id, + self.current_transition_in_trace, + transition_id, + prev_state_data["isa"], + ) + ) if self.pta: transition = self.pta.transitions[transition_id] if transition.name != log_data_target["name"]: @@ -601,4 +692,10 @@ class OnboardTimerHarness(TransitionHarness): if "offline_aggregates" not in log_data_target: log_data_target["offline_aggregates"] = {"duration": list()} log_data_target["offline_aggregates"]["duration"].append(duration_us) + if prev_state_data is not None: + if "offline_aggregates" not in prev_state_data: + prev_state_data["offline_aggregates"] = {"duration": list()} + prev_state_data["offline_aggregates"]["duration"].append( + prev_state_duration_us + ) self.current_transition_in_trace += 1 |