diff --git a/app/benchmark/timing/aborted-computation.cc b/app/benchmark/timing/aborted-computation.cc index e5e483334457464590137303bc838981cedd993a..944523a6ee7e8763fe46afc99868d16dad5f4a41 100644 --- a/app/benchmark/timing/aborted-computation.cc +++ b/app/benchmark/timing/aborted-computation.cc @@ -12,11 +12,17 @@ DeclareEvent(ComputationAborted); GENERATE_TIME_CONSUMER(computation, 5000) +extern "C" { + void timing_entry() { + ActivateTask(Computation); + WaitEvent(ComputationFinished | ComputationAborted); + } +} + TASK(Control) { timing_start(0); - ActivateTask(Computation); - WaitEvent(ComputationFinished | ComputationAborted); + timing_entry(); timing_end(TIMING_POINT_NO_INTERRUPTS_IN_BLOCK | 0); /* ABB Split Point */ diff --git a/app/benchmark/timing/manual-syswcet.py b/app/benchmark/timing/manual-syswcet.py index 5f593b581920e0efbd0912d8bf4a4934d0ccf406..ecdd3d52ba9a97fd558718964fd1100037b13bfc 100755 --- a/app/benchmark/timing/manual-syswcet.py +++ b/app/benchmark/timing/manual-syswcet.py @@ -10,6 +10,8 @@ import shlex import subprocess import threading import re +import logging +import tempfile class Execution: def __init__(self, command, proc): @@ -76,16 +78,20 @@ def run_wait_timeout(cmd, stdin_data, timeout): return proc RELATIVE_BUILD_DIR = '../../../build' -DREF_KEY = 'app/benchmark/timing/' +DREF_KEY = 'MANUAL/cycles' def parse_args(): parser = ArgumentParser(description="script for manual evaluation of sysbench") - + parser.add_argument('-b', '--bench', dest='bench', help='the benchmark under analysis', - choices=['tmr','computation_irq','aborted_computation'], + choices=['tmr','computation_alarm','aborted_computation'], required=False, default=None) - + + parser.add_argument('-d', '--dref', dest='dref_file', + help='file for the manual results', + required=False, default="bench-timing-manual.dref") + parser.add_argument('-a', '--all', dest='all', action='store_true', help='process all benchmarks', required=False, default=False) @@ -93,8 +99,8 @@ def parse_args(): parser.add_argument('-v', '--verbose', dest='verbose', action='store_true', help='activate verbose output', required=False, default=False) - - + + return parser, parser.parse_args() @@ -106,91 +112,137 @@ def dref_get_value(key, file): if match: cy = match.group(1) return cy - + return None def get_elf(args_bench): build_dir = os.path.abspath(RELATIVE_BUILD_DIR) if not os.path.exists(build_dir): sys.exit("build directory missing: %s" % build_dir) - + elf=os.path.join(build_dir, 'bench-timing-' + args_bench) - + return elf def setup_paths(args_bench): elf = get_elf(args_bench) build_dir = os.path.abspath(RELATIVE_BUILD_DIR) - cmake_binary_dir = os.path.join(build_dir, DREF_KEY) - bench_out_dir = os.path.join(cmake_binary_dir, 'bench-timing-' + args_bench) - system_pml = os.path.join(bench_out_dir, 'system.pml') - gcfg_pml = os.path.join(bench_out_dir, 'gcfg.pml') - + bench_out_dir = os.path.join(build_dir, ) + system_pml = os.path.join(build_dir, 'bench-timing-%s-system.pml'%(args_bench)) + gcfg_pml = os.path.join(build_dir, 'bench-timing-%s-gcfg.pml'%(args_bench)) + return (elf, system_pml, gcfg_pml) -def write_result_file(elf, cycles): - result_file = elf + '-' + 'manual.dref' - f = open(result_file, 'w') - f.write('\drefset{' + DREF_KEY + '}' + '{' + str(cycles) + '}') - f.close() - - print('written: ' + result_file) -def get_cycles_from_entry(entry, bench): +def dref_key(dref_file, key, value): + logging.info("drefset: %s = %d", key, value) + content = [] + if os.path.exists(dref_file): + with open(dref_file) as fd: + content += [x.strip() for x in fd.readlines()] + line = '\\drefset{/%s/%s}{%s}' %(key, DREF_KEY, value) + found = False + for idx in range(0, len(content)): + if content[idx].startswith("\\drefset{%s}" % key): + content[idx] = line + found = True + break + if not found: + content.append(line) + with open(dref_file, "w+") as fd: + fd.write("\n".join(content) + "\n") + +def get_cycles_from_entry(entry, bench, flow_facts = []): elf, system_pml, gcfg_pml = setup_paths(bench) - - dref= elf + '-' + 'entry=' + entry + '.dref' + + (fd, dref) = tempfile.mkstemp() cmd = 'platin wcet -i ' + system_pml + ' -i ' + gcfg_pml + \ - ' --binary ' + elf + ' --wca-count-instructions ' + \ - ' --disable-ait --wca-detect-gurobi --dref-stats ' + dref + \ - ' -e ' + entry # GCFG:timing-' + str(circuit) + ' --binary ' + elf + ' --wca-count-instructions ' + \ + ' --disable-ait --wca-detect-gurobi --dref-stats ' + dref + \ + ' -e ' + entry # GCFG:timing-' + str(circuit) + for ff in flow_facts: + cmd += " --add-flowfact " + repr(ff) proc = run_wait(cmd, None) proc.assert_retcode(0) cy_entry = int(dref_get_value('/WCA/cycles', dref)) + logging.info("%s, %s = %d", bench, entry, cy_entry) + os.unlink(dref) + os.close(fd) return cy_entry +def add_events_with_iat(cy_base, events = []): + cy_total = cy_base + cy_total_last = None + occurences = {} + while cy_total != cy_total_last: + cy_total_last = cy_total + cy_total = cy_base + for (iat, cyc, name) in events: + occ = (int(cy_total) // int(iat)) + 1 + cy_total += occ * cyc + occurences[name] = occ + return cy_total, occurences + + def main(): parser, args = parse_args() - + if "VERBOSE" in os.environ: args.verbose = True - + + if args.verbose: + logging.basicConfig(level=logging.DEBUG) + + logging.info("Updating %s", args.dref_file) + args.dref_file = os.path.abspath(args.dref_file) + # cd "$(dirname "$0")" dirname = os.path.dirname(os.path.realpath(__file__)) os.chdir(dirname) - + # 1. tmr (non-hierarchical call chains) if args.all or args.bench == 'tmr': args.bench = 'tmr' - cy_entry = get_cycles_from_entry('timing_entry', args.bench) - + cy_timing_entry = get_cycles_from_entry('timing_entry', args.bench) + cy_computation = get_cycles_from_entry('OSEKOS_TASK_FUNC_Calculation', args.bench) + # take three times the entry - cy_total = cy_entry * 3 - - write_result_file(get_elf(args.bench), int(cy_total)) - - + cy_total = cy_timing_entry + cy_computation * 3 + + dref_key(args.dref_file, "tmr", int(cy_total)) + + # 2. computation IRQ (operating system semantic) - if args.all or args.bench == 'computation_irq': - args.bench = 'computation_irq' - cy_timing_0 = get_cycles_from_entry('timing_0', args.bench) - cy_isr = get_cycles_from_entry('OSEKOS_ISR_ISR1', args.bench) - - occurences = (cy_timing_0 / cy_isr) + 1 # +1 => worst case - cy_total = (occurences * cy_isr) + cy_timing_0 - - write_result_file(get_elf(args.bench), int(cy_total)) - + if args.all or args.bench == 'computation_alarm': + args.bench = 'computation_alarm' + cy_timing_entry = get_cycles_from_entry('timing_entry', args.bench) + cy_task4 = get_cycles_from_entry('OSEKOS_TASK_FUNC_Task4', args.bench) + cy_isr = get_cycles_from_entry('irq_entry', args.bench, ["irq_entry : <> : timer_isr = 1"]) + + iat_timer = 100000 + iat_task4 = 3 * iat_timer + + cy_total, occurences = add_events_with_iat( + cy_timing_entry, [(iat_timer, cy_isr, "timer"), (iat_task4, cy_task4, "alarms")]) + + logging.info("%s = %d", occurences, cy_total) + + dref_key(args.dref_file, "computation alarm", int(cy_total)) + # 3 aborted computation (interrupt handling) if args.all or args.bench == 'aborted_computation': args.bench = 'aborted_computation' + cy_timing_entry = get_cycles_from_entry('timing_entry', args.bench) cy_computation = get_cycles_from_entry('OSEKOS_TASK_FUNC_Computation', args.bench) - cy_activate_task = get_cycles_from_entry('OSEKOS_ActivateTask_BB8', args.bench) - cy_ISR_abort = get_cycles_from_entry('OSEKOS_ISR_Abort', args.bench) - - cy_total = cy_computation + cy_activate_task + cy_ISR_abort - - write_result_file(get_elf(args.bench), int(cy_total)) + cy_ISR_abort = get_cycles_from_entry('irq_entry', args.bench, ["irq_entry : <> : OSEKOS_ISR_Abort = 1"]) + + iat_isr = 10000 + + cy_total, occurences = add_events_with_iat( + cy_timing_entry + cy_computation, [(iat_isr, cy_ISR_abort, "isr")]) + + dref_key(args.dref_file, "aborted computation", int(cy_total)) + if __name__=='__main__': main()