summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rwxr-xr-xbin/generate-dfa-benchmark.py47
-rw-r--r--lib/harness.py44
-rw-r--r--lib/runner.py20
3 files changed, 75 insertions, 36 deletions
diff --git a/bin/generate-dfa-benchmark.py b/bin/generate-dfa-benchmark.py
index 3019a2e..95fbbb3 100755
--- a/bin/generate-dfa-benchmark.py
+++ b/bin/generate-dfa-benchmark.py
@@ -45,6 +45,7 @@ if __name__ == '__main__':
'instance= '
'run= '
'sleep= '
+ 'timer-pin= '
)
raw_opts, args = getopt.getopt(sys.argv[1:], "", optspec.split(' '))
@@ -72,7 +73,12 @@ if __name__ == '__main__':
else:
pta = PTA.from_yaml(yaml.safe_load(f))
- harness = OnboardTimerHarness('GPIO::p1_0')
+ if 'timer-pin' in opt:
+ timer_pin = opt['timer-pin']
+ else:
+ timer_pin = 'GPIO::p1_0'
+
+ harness = OnboardTimerHarness(timer_pin)
outbuf = io.StringIO()
@@ -90,21 +96,27 @@ if __name__ == '__main__':
class_prefix = ''
if 'instance' in opt:
class_prefix = '{}.'.format(opt['instance'])
- elif 'intance' in pta.codegen:
+ elif 'instance' in pta.codegen:
class_prefix = '{}.'.format(pta.codegen['instance'])
num_transitions = 0
for run in pta.dfs(opt['depth'], with_arguments = True, with_parameters = True):
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_state(transition.origin.name, param)
+ harness.append_transition(transition.name, param)
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, parameter))
+ outbuf.write(harness.pass_transition(pta.get_transition_id(transition), transition_code, transition = transition, parameter = parameter))
+
+ param = parameter
if 'sleep' in opt:
outbuf.write('arch.delay_ms({:d});\n'.format(opt['sleep']))
@@ -113,6 +125,7 @@ if __name__ == '__main__':
outbuf.write('\n')
outbuf.write(harness.stop_benchmark())
+ print(harness.traces)
outbuf.write('}\n')
outbuf.write('int main(void)\n')
outbuf.write('{\n')
@@ -136,20 +149,24 @@ if __name__ == '__main__':
run_timeout = num_transitions * opt['sleep'] / 1000
else:
run_timeout = num_transitions * 10 / 1000
- monitor = runner.get_monitor(opt['arch'], peek = True)
+ monitor = runner.get_monitor(opt['arch'], callback = harness.parser_cb)
runner.build(opt['arch'], opt['app'], opt['run'].split())
runner.flash(opt['arch'], opt['app'], opt['run'].split())
- try:
- slept = 0
- while True:
- time.sleep(5)
- slept += 5
- if slept < run_timeout:
- print('[MON] approx. {:.0f}% done'.format(slept * 100 / run_timeout))
- except KeyboardInterrupt:
- pass
- lines = monitor.get_lines()
- monitor.close()
+ if opt['arch'] != 'posix':
+ try:
+ slept = 0
+ while True:
+ time.sleep(5)
+ slept += 5
+ if slept < run_timeout:
+ print('[MON] approx. {:.0f}% done'.format(slept * 100 / run_timeout))
+ except KeyboardInterrupt:
+ pass
+ lines = monitor.get_lines()
+ monitor.close()
+ else:
+ print('[MON] Will run benchmark for {:.0f} seconds'.format(2 * run_timeout))
+ lines = monitor.run(int(2 * run_timeout))
print(lines)
sys.exit(0)
diff --git a/lib/harness.py b/lib/harness.py
index 2705193..ade42d6 100644
--- a/lib/harness.py
+++ b/lib/harness.py
@@ -3,6 +3,7 @@ Harnesses for various types of benchmark logs.
tbd
"""
+import re
# TODO prepare benchmark log JSON with parameters etc.
# Should be independent of PTA class, as benchmarks may also be
@@ -32,24 +33,28 @@ class TransitionHarness:
def start_trace(self):
self.traces.append({
'id' : self.trace_id,
- 'trace' : [{
- 'name' : 'UNINITIALIZED',
- 'isa' : 'state',
- 'parameter' : dict(),
- 'offline_aggregates' : list(),
- }]
+ 'trace' : list(),
})
self.trace_id += 1
- #def append_state(self):
+ def append_state(self, state_name, param):
+ self.traces[-1]['trace'].append({
+ 'name': state_name,
+ 'isa': 'state',
+ 'parameter': param,
+ })
- #def append_transition(self, ):
+ def append_transition(self, transition_name, param):
+ self.traces[-1]['trace'].append({
+ 'name': transition_name,
+ 'isa': 'transition',
+ 'parameter': param,
+ })
def start_run(self):
- self.start_trace()
return 'ptalog.reset();\n'
- def pass_transition(self, transition_id, transition_code, parameter = dict()):
+ def pass_transition(self, transition_id, transition_code, transition: object = None, parameter: dict = dict()):
ret = 'ptalog.passTransition({:d});\n'.format(transition_id)
ret += 'ptalog.startTransition();\n'
ret += '{}\n'.format(transition_code)
@@ -62,6 +67,23 @@ class TransitionHarness:
def stop_benchmark(self):
return ''
+ def parse_log(self, lines):
+ sync = False
+ for line in lines:
+ print(line)
+ res = re.fullmatch('\[PTA\] (.*=.*)', line)
+ if re.fullmatch('\[PTA\] benchmark start, id=(.*)', line):
+ print('> got sync')
+ sync = True
+ elif not sync:
+ continue
+ elif re.fullmatch('\[PTA\] trace, count=(.*)', line):
+ print('> got transition')
+ pass
+ elif res:
+ print(dict(map(lambda x: x.split('='), res.group(1).split())))
+ pass
+
class OnboardTimerHarness(TransitionHarness):
def __init__(self, gpio_pin = None):
super().__init__(gpio_pin = gpio_pin)
@@ -79,7 +101,7 @@ class OnboardTimerHarness(TransitionHarness):
ret += super().start_benchmark()
return ret
- def pass_transition(self, transition_id, transition_code, parameter = dict()):
+ def pass_transition(self, transition_id, transition_code, transition: object = None, parameter: dict = dict()):
ret = 'ptalog.passTransition({:d});\n'.format(transition_id)
ret += 'ptalog.startTransition();\n'
ret += 'counter.start();\n'
diff --git a/lib/runner.py b/lib/runner.py
index 9b95e6b..c9179c2 100644
--- a/lib/runner.py
+++ b/lib/runner.py
@@ -24,9 +24,9 @@ class SerialReader(serial.threaded.Protocol):
Reads in new data whenever it becomes available and exposes a line-based
interface to applications.
"""
- def __init__(self, peek = False):
+ def __init__(self, callback = None):
"""Create a new SerialReader object."""
- self.peek = peek
+ self.callback = callback
self.recv_buf = ''
self.lines = []
@@ -48,8 +48,8 @@ class SerialReader(serial.threaded.Protocol):
if len(lines) > 1:
self.lines.extend(lines[:-1])
self.recv_buf = lines[-1]
- if self.peek:
- print('\n'.join(lines[:-1]))
+ if self.callback:
+ self.callback(lines[:-1])
except UnicodeDecodeError:
pass
@@ -82,7 +82,7 @@ class SerialReader(serial.threaded.Protocol):
class SerialMonitor:
"""SerialMonitor captures serial output for a specific amount of time."""
- def __init__(self, port: str, baud: int, peek = False):
+ def __init__(self, port: str, baud: int, callback = None):
"""
Create a new SerialMonitor connected to port at the specified baud rate.
@@ -101,7 +101,7 @@ class SerialMonitor:
sys.stderr.write('Could not open serial port {}: {}\n'.format(self.ser.name, e))
sys.exit(1)
- self.reader = SerialReader(peek = peek)
+ self.reader = SerialReader(callback = callback)
self.worker = serial.threaded.ReaderThread(self.ser, self.reader)
self.worker.start()
@@ -124,14 +124,14 @@ class SerialMonitor:
class ShellMonitor:
"""SerialMonitor runs a program and captures its output for a specific amount of time."""
- def __init__(self, script: str, peek = None):
+ def __init__(self, script: str, callback = None):
"""
Create a new ShellMonitor object.
Does not start execution and monitoring yet.
"""
self.script = script
- self.peek = peek
+ self.callback = callback
def run(self, timeout: int = 4) -> list:
"""
@@ -144,8 +144,8 @@ class ShellMonitor:
res = subprocess.run(['timeout', '{:d}s'.format(timeout), self.script],
stdout = subprocess.PIPE, stderr = subprocess.PIPE,
universal_newlines = True)
- if self.peek:
- print(res.stdout)
+ if self.callback:
+ self.callback(res.stdout.split('\n'))
return res.stdout.split('\n')
def monitor(self):