#!/usr/bin/env bash set -euo pipefail root="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")/.." && pwd)" env_root="${RV_ENV_ROOT:-/home/user/dev/edu/rv32i-hazard3-student-env}" tb="${HAZARD3_TB:-$env_root/vendor/Hazard3/test/sim/tb_verilator/tb}" objdump="${RISCV_PREFIX:-riscv64-unknown-elf-}objdump" if [[ ! -x "$tb" ]]; then make -C "$(dirname -- "$tb")" tb >/dev/null fi make -C "$root" -s tasks "RV_ENV_ROOT=$env_root" run_task() { local task="$1" shift local log="$root/build/$task/oracle.log" "$tb" --bin "$root/build/$task/prog.bin" --cycles 500000 --cpuret --logfile "$log" if grep -Eq 'Unhandled trap|Max cycles reached' "$log"; then printf 'FAIL %s: trap or timeout\n' "$task" >&2 sed -n '1,160p' "$log" >&2 return 1 fi local expected for expected in "$@"; do grep -Fqx "$expected" "$log" || { printf 'FAIL %s: missing <%s>\n' "$task" "$expected" >&2 sed -n '1,160p' "$log" >&2 return 1 } done printf 'PASS Hazard3 oracle: %s\n' "$task" } run_task task01_mtime_consistent_read \ 'T01 retry=00000001' \ 'T01 value_high=00000001' \ 'T01 monotonic=00000001' \ 'T01 pass=00000001' run_task task02_oneshot_timer_irq \ 'T02 count=00000001' \ 'T02 mcause=80000007' \ 'T02 pending_before=00000000' \ 'T02 pending_after=00000000' \ 'T02 resumed=00000001' \ 'T02 deadline_reached=00000001' \ 'T02 pass=00000001' run_task task03_periodic_absolute_deadline \ 'T03 count=00000004' \ 'T03 causes=00000004' \ 'T03 period_low=00000640' \ 'T03 step_ok=00000001' \ 'T03 ordered=00000001' \ 'T03 late_math=00000001' \ 'T03 naive_shift_ok=00000001' \ 'T03 pass=00000001' # Independent relations: do not accept a program's pass flag as the only oracle. t01_attempts_hex="$(sed -n 's/^T01 attempts=//p' \ "$root/build/task01_mtime_consistent_read/oracle.log")" (( 16#$t01_attempts_hex > 1 )) || { echo "FAIL task01: rollover did not force a retry" >&2 exit 1 } mapfile -t t03_deadline < <(sed -n 's/^T03 deadline_low=//p' \ "$root/build/task03_periodic_absolute_deadline/oracle.log") mapfile -t t03_observed < <(sed -n 's/^T03 observed_low=//p' \ "$root/build/task03_periodic_absolute_deadline/oracle.log") mapfile -t t03_lateness < <(sed -n 's/^T03 lateness_low=//p' \ "$root/build/task03_periodic_absolute_deadline/oracle.log") [[ ${#t03_deadline[@]} -eq 4 && ${#t03_observed[@]} -eq 4 && ${#t03_lateness[@]} -eq 4 ]] for i in 0 1 2 3; do d=$((16#${t03_deadline[$i]})) o=$((16#${t03_observed[$i]})) l=$((16#${t03_lateness[$i]})) (( o >= d && o - d == l )) || { echo "FAIL task03: invalid observed/deadline/lateness relation at tick $i" >&2 exit 1 } if (( i > 0 )); then previous=$((16#${t03_deadline[$((i - 1))]})) (( d - previous == 1600 )) || { echo "FAIL task03: deadline step is not 1600 at tick $i" >&2 exit 1 } fi done for task in task02_oneshot_timer_irq task03_periodic_absolute_deadline; do "$objdump" -d "$root/build/$task/prog.elf" | sed -n '/:/,/^$/p' | grep -Eq '[[:space:]]mret$' || { echo "FAIL $task: ISR does not end in mret" >&2 exit 1 } done printf 'PASS independent oracle: rollover retry, periodic arithmetic, ISR mret\n'