def test_dfs_objects(self): pta = PTA(["IDLE", "TX"]) pta.add_transition("UNINITIALIZED", "IDLE", "init") pta.add_transition("IDLE", "TX", "send") pta.add_transition("TX", "IDLE", "txComplete") traces = list(pta.dfs(2)) self.assertEqual(len(traces), 1) trace = traces[0] self.assertEqual(len(trace), 3) self.assertEqual(trace[0][0].name, "init") self.assertEqual(trace[1][0].name, "send") self.assertEqual(trace[2][0].name, "txComplete") self.assertEqual(pta.get_transition_id(trace[0][0]), 0) self.assertEqual(pta.get_transition_id(trace[1][0]), 1) self.assertEqual(pta.get_transition_id(trace[2][0]), 2)
def test_dfs_with_sleep(self): pta = PTA(["IDLE", "TX"]) pta.add_transition("UNINITIALIZED", "IDLE", "init") pta.add_transition("IDLE", "TX", "send") pta.add_transition("TX", "IDLE", "txComplete") traces = list(pta.dfs(2, sleep=10)) self.assertEqual(len(traces), 1) trace = traces[0] self.assertEqual(len(trace), 6) self.assertIsNone(trace[0][0]) self.assertEqual(trace[1][0].name, "init") self.assertIsNone(trace[2][0]) self.assertEqual(trace[3][0].name, "send") self.assertIsNone(trace[4][0]) self.assertEqual(trace[5][0].name, "txComplete") self.assertEqual(pta.get_transition_id(trace[1][0]), 0) self.assertEqual(pta.get_transition_id(trace[3][0]), 1) self.assertEqual(pta.get_transition_id(trace[5][0]), 2)
def benchmark_from_runs( pta: PTA, runs: list, harness: OnboardTimerHarness, benchmark_id: int = 0, dummy=False, repeat=0, ) -> io.StringIO: outbuf = io.StringIO() outbuf.write(target.app_header()) if dummy: outbuf.write('#include "driver/dummy.h"\n') elif "includes" in pta.codegen: for include in pta.codegen["includes"]: outbuf.write('#include "{}"\n'.format(include)) outbuf.write(harness.global_code()) outbuf.write(target.app_function_start()) # There is a race condition between flashing the code and starting the UART log. # When starting the log before flashing, output from a previous benchmark may cause bogus data to be added. # When flashing first and then starting the log, the first log lines may be lost. # To work around this, we flash first, then start the log, and use this delay statement to ensure that no output is lost. # This is also useful to faciliate MIMOSA calibration after flashing # For MIMOSA, the DUT is disconnected from power during calibration, so # it must be set up after the calibration delay. # For energytrace, the device is connected to VCC and set up before # the initialization delay to -- this puts it into a well-defined state and # decreases pre-sync power consumption if "energytrace" not in opt: if "mimosa" in opt: outbuf.write(target.app_delay(12000)) else: outbuf.write(target.app_delay(2000)) # Output some newlines to ensure the parser can determine the start of the first real output line outbuf.write(target.app_newlines()) if "setup" in pta.codegen: for call in pta.codegen["setup"]: outbuf.write(call) if "energytrace" in opt: outbuf.write("for (unsigned char j = 0; j < 10; j++) {\n") outbuf.write(target.app_sleep(250)) outbuf.write("}\n") # Output some newlines to ensure the parser can determine the start of the first real output line outbuf.write(target.app_newlines()) if repeat: outbuf.write("unsigned char i = 0;\n") outbuf.write("while (i++ < {}) {{\n".format(repeat)) else: outbuf.write("while (1) {\n") outbuf.write(harness.start_benchmark()) class_prefix = "" if "instance" in opt: class_prefix = "{}.".format(opt["instance"]) elif "instance" in pta.codegen: class_prefix = "{}.".format(pta.codegen["instance"]) num_transitions = 0 num_traces = 0 for run in runs: outbuf.write(harness.start_run()) harness.start_trace() param = pta.get_initial_param_dict() for transition, arguments, parameter in run: num_transitions += 1 harness.append_transition(transition.name, param, arguments) harness.append_state(transition.destination.name, parameter.copy()) outbuf.write("// {} -> {}\n".format(transition.origin.name, transition.destination.name)) if transition.is_interrupt: outbuf.write("// wait for {} interrupt\n".format( transition.name)) transition_code = "// TODO add startTransition / stopTransition calls to interrupt routine" else: transition_code = "{}{}({});".format( class_prefix, transition.name, ", ".join(map(str, arguments))) outbuf.write( harness.pass_transition( pta.get_transition_id(transition), transition_code, transition=transition, )) param = parameter outbuf.write("// current parameters: {}\n".format(", ".join( map(lambda kv: "{}={}".format(*kv), param.items())))) if "delay_after_ms" in transition.codegen: if "energytrace" in opt: outbuf.write( target.app_sleep( transition.codegen["delay_after_ms"], f"{transition.destination.name} -- delay mandated by codegen.delay_after_ms", )) else: outbuf.write( target.app_delay( transition.codegen["delay_after_ms"], f"{transition.destination.name} -- delay mandated by codegen.delay_after_ms", )) elif opt["sleep"]: if "energytrace" in opt: outbuf.write(f"// -> {transition.destination.name}\n") outbuf.write(target.sleep_ms(opt["sleep"])) else: outbuf.write(f"// -> {transition.destination.name}\n") outbuf.write(target.app_delay(opt["sleep"])) outbuf.write(harness.stop_run(num_traces)) if dummy: outbuf.write( 'kout << "[Energy] " << {}getEnergy() << endl;\n'.format( class_prefix)) outbuf.write("\n") num_traces += 1 outbuf.write(harness.stop_benchmark()) outbuf.write("}\n") # Ensure logging can be terminated after the specified number of measurements outbuf.write(harness.start_benchmark()) outbuf.write(target.app_function_end()) return outbuf