summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rwxr-xr-xbin/generate-dfa-benchmark.py26
-rw-r--r--lib/harness.py5
-rw-r--r--lib/runner.py40
3 files changed, 64 insertions, 7 deletions
diff --git a/bin/generate-dfa-benchmark.py b/bin/generate-dfa-benchmark.py
index e157f1f..5d89a2d 100755
--- a/bin/generate-dfa-benchmark.py
+++ b/bin/generate-dfa-benchmark.py
@@ -29,7 +29,7 @@ Options:
Override the name of the class instance used for benchmarking
--mimosa=[k=v,k=v,...]
- Perform energy measurements with MIMOSA. Takes precedence over --timing.
+ Perform energy measurements with MIMOSA. Takes precedence over --timing and --energytrace.
mimosa options are key-value pairs. Possible settings with defaults:
offset = 130 (mysterious 0V offset)
shunt = 330 (measurement shunt in ohms)
@@ -46,6 +46,9 @@ Options:
Perform timing measurements using on-chip counters (no external hardware
required)
+--energytrace
+ Perform energy measurements using MSP430 EnergyTrace hardware. Includes --timing.
+
--trace-filter=<transition,transition,transition,...>[ <transition,transition,transition,...> ...]
Only consider traces whose beginning matches one of the provided transition sequences.
E.g. --trace-filter='init,foo init,bar' will only consider traces with init as first and foo or bar as second transition,
@@ -161,7 +164,7 @@ def benchmark_from_runs(pta: PTA, runs: list, harness: OnboardTimerHarness, benc
return outbuf
def run_benchmark(application_file: str, pta: PTA, runs: list, arch: str, app: str, run_args: list, harness: object, sleep: int = 0, repeat: int = 0, run_offset: int = 0, runs_total: int = 0, dummy = False):
- if 'mimosa' in opt:
+ if 'mimosa' in opt or 'energytrace' in opt:
outbuf = benchmark_from_runs(pta, runs, harness, dummy = dummy, repeat = 1)
else:
outbuf = benchmark_from_runs(pta, runs, harness, dummy = dummy, repeat = repeat)
@@ -201,12 +204,15 @@ def run_benchmark(application_file: str, pta: PTA, runs: list, arch: str, app: s
return results
- if 'mimosa' in opt:
+ if 'mimosa' in opt or 'energytrace' in opt:
files = list()
i = 0
while i < opt['repeat']:
runner.flash(arch, app, run_args)
- monitor = runner.get_monitor(arch, callback = harness.parser_cb, mimosa = opt['mimosa'])
+ if 'mimosa' in opt:
+ monitor = runner.get_monitor(arch, callback = harness.parser_cb, mimosa = opt['mimosa'])
+ elif 'energytrace' in opt:
+ monitor = runner.get_monitor(arch, callback = harness.parser_cb, energytrace = opt['energytrace'])
sync_error = False
try:
@@ -268,6 +274,7 @@ if __name__ == '__main__':
'app= '
'depth= '
'dummy= '
+ 'energytrace= '
'instance= '
'mimosa= '
'repeat= '
@@ -316,6 +323,15 @@ if __name__ == '__main__':
if opt['repeat'] == 0:
opt['repeat'] = 1
+ if 'energytrace' in opt:
+ if opt['energytrace'] == '':
+ opt['energytrace'] = dict()
+ else:
+ opt['energytrace'] = dict(map(lambda x: x.split('='), opt['energytrace'].split(',')))
+ opt.pop('timing', None)
+ if opt['repeat'] == 0:
+ opt['repeat'] = 1
+
except getopt.GetoptError as err:
print(err)
sys.exit(2)
@@ -369,6 +385,8 @@ if __name__ == '__main__':
if 'mimosa' in opt:
harness = TransitionHarness(gpio_pin = timer_pin, pta = pta, log_return_values = need_return_values, repeat = 1, post_transition_delay_us = 20)
+ elif 'energytrace' in opt:
+ harness = OnboardTimerHarness(gpio_pin = timer_pin, pta = pta, counter_limits = runner.get_counter_limits_us(opt['arch']), log_return_values = need_return_values, repeat = 1)
elif 'timing' in opt:
harness = OnboardTimerHarness(gpio_pin = timer_pin, pta = pta, counter_limits = runner.get_counter_limits_us(opt['arch']), log_return_values = need_return_values, repeat = opt['repeat'])
diff --git a/lib/harness.py b/lib/harness.py
index f39b28c..a4724f1 100644
--- a/lib/harness.py
+++ b/lib/harness.py
@@ -321,11 +321,12 @@ class OnboardTimerHarness(TransitionHarness):
print(' Offending line: {}'.format(line))
return
if log_data_target['isa'] != 'transition':
- raise RuntimeError('Log mismatch: Expected transition, got {:s}'.format(log_data_target['isa']))
+ raise RuntimeError('Log mismatch in benchmark id={:d} trace={:d}: transition #{:d} (ID {:d}): Expected transition, got {:s}'.format(0,
+ self.trace_id, self.current_transition_in_trace, transition_id, log_data_target['isa']))
if self.pta:
transition = self.pta.transitions[transition_id]
if transition.name != log_data_target['name']:
- raise RuntimeError('Log mismatch: Expected transition {:s}, got transition {:s}'.format(log_data_target['name'], transition.name))
+ raise RuntimeError('Log mismatch in benchmark id={:d} trace={:d}: transition #{:d} (ID {:d}): Expected transition {:s}, got transition {:s}'.format(0, self.trace_id, self.current_transition_in_trace, transition_id, log_data_target['name'], transition.name))
if self.log_return_values and len(transition.return_value_handlers):
for handler in transition.return_value_handlers:
if 'parameter' in handler:
diff --git a/lib/runner.py b/lib/runner.py
index 3fa104b..1525b56 100644
--- a/lib/runner.py
+++ b/lib/runner.py
@@ -128,6 +128,32 @@ class SerialMonitor:
self.worker.stop()
self.ser.close()
+class EnergyTraceMonitor(SerialMonitor):
+ """EnergyTraceMonitor captures serial timing output and EnergyTrace energy data."""
+ def __init__(self, port: str, baud: int, callback = None, voltage = 3.3):
+ super().__init__(port = port, baud = baud, callback = callback)
+ self._voltage = voltage
+ self._output = time.strftime('%Y%m%d-%H%M%S.etlog')
+ self._start_energytrace()
+
+ def _start_energytrace(self):
+ cmd = ['msp430-etv', '--save', self._output, '0']
+ self._logger = subprocess.Popen(cmd,
+ stdout = subprocess.PIPE, stderr = subprocess.PIPE,
+ universal_newlines = True)
+
+ def close(self):
+ super().close()
+ self._logger.send_signal(subprocess.signal.SIGINT)
+ stdout, stderr = self._logger.communicate(timeout = 15)
+
+ def get_files(self) -> list:
+ return [self._output]
+
+ def get_config(self) -> dict:
+ return {
+ 'voltage' : self._voltage,
+ }
class MIMOSAMonitor(SerialMonitor):
"""MIMOSAMonitor captures serial output and MIMOSA energy data for a specific amount of time."""
@@ -282,7 +308,15 @@ def get_info(arch, opts: list = []) -> list:
return res.stdout.split('\n')
def get_monitor(arch: str, **kwargs) -> object:
- """Return a SerialMonitor or ShellMonitor, depending on "make info" output of arch."""
+ """
+ Return an appropriate monitor for arch, depending on "make info" output.
+
+ Port and Baud rate are taken from "make info".
+
+ :param arch: architecture name, e.g. 'msp430fr5994lp' or 'posix'
+ :param energytrace: `EnergyTraceMonitor` options. Returns an EnergyTrace monitor if not None.
+ :param mimosa: `MIMOSAMonitor` options. Returns a MIMOSA monitor if not None.
+ """
for line in get_info(arch):
if 'Monitor:' in line:
_, port, arg = line.split(' ')
@@ -291,7 +325,11 @@ def get_monitor(arch: str, **kwargs) -> object:
elif 'mimosa' in kwargs and kwargs['mimosa'] is not None:
mimosa_kwargs = kwargs.pop('mimosa')
return MIMOSAMonitor(port, arg, **mimosa_kwargs, **kwargs)
+ elif 'energytrace' in kwargs and kwargs['energytrace'] is not None:
+ energytrace_kwargs = kwargs.pop('energytrace')
+ return EnergyTraceMonitor(port, arg, **energytrace_kwargs, **kwargs)
else:
+ kwargs.pop('energytrace', None)
kwargs.pop('mimosa', None)
return SerialMonitor(port, arg, **kwargs)
raise RuntimeError('Monitor failure')