Files
vt1200/harness/sdk-scratch/bench2.py
T
SDD 7d299451da reference: TMS34010 SDK investigation; prove GSPA round trip
The 1987 DOS toolchain (GSPA/GSPLNK/GSPROM) runs under DOSBox and
reassembles 32 KB of the v2.2 ROM byte-for-byte after five documented
fixups to smart34010 output.  The 1990 r5.01 tools are OS/2 NE and do
not run in DOS.  Adds the converter, round-trip script, and the
DOSBox/dosemu benchmark.
2026-10-18 00:39:32 +03:00

104 lines
3.7 KiB
Python

#!/usr/bin/env python3
"""DOSBox vs dosemu on the real workload: GSPA assembling TMS34010 source.
Workload A: gspa t1 t1.obj t1.lst -l (4 KB region, listing)
Workload B: gspa -q rt16 rt16.obj (16 KB region, no listing)
Both headless: DOSBox with SDL dummy drivers and core=dynamic/cycles=max;
dosemu in -t (terminal/S-Lang) mode. Three measured runs each, plus one
warm-up. Raw COFF md5 differs only in the 4-byte time stamp, so a
timestamp-normalised md5 is also reported.
"""
import hashlib
import os
import statistics
import subprocess
import time
from pathlib import Path
ROOT = Path(__file__).resolve().parent
BENCH = ROOT / "bench"
DHOME = ROOT / "dosemu-home"
DBENCH = DHOME / ".dosemu" / "drive_c" / "bench"
RUNS = 3
def norm_md5(p):
if not p.exists():
return "-"
b = bytearray(p.read_bytes())
if len(b) >= 8:
b[4:8] = b"\0\0\0\0"
return hashlib.md5(bytes(b)).hexdigest()
def raw_md5(p):
return hashlib.md5(p.read_bytes()).hexdigest() if p.exists() else "-"
def clean(d, base):
for name in (base + ".OBJ", base + ".LST", "MACLIB.$$$",
base.lower() + ".obj", base.lower() + ".lst", "maclib.$$$"):
f = d / name
if f.exists():
f.unlink()
def run_dosbox(base, args):
clean(BENCH, base)
cmds = []
for _ in range(1):
cmds += ["-c", "gspa " + args]
env = dict(os.environ, SDL_VIDEODRIVER="dummy", SDL_AUDIODRIVER="dummy")
t0 = time.perf_counter()
rc = subprocess.run(
["timeout", "120", "dosbox", "-conf", str(ROOT / "dosbox-bench.conf"),
"-noprimaryconf", "-nolocalconf",
"-c", "mount c " + str(BENCH), "-c", "c:"] + cmds +
["-c", "exit", "-exit"],
env=env, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL).returncode
dt = time.perf_counter() - t0
# DOSBox uppercases 8.3 names
obj = BENCH / (base.upper() + ".OBJ")
return dt, rc, raw_md5(obj), norm_md5(obj), obj.stat().st_size if obj.exists() else 0
def run_dosemu(base, args, bat):
clean(DBENCH, base)
script = "@echo off\r\nc:\r\ncd \\bench\r\ngspa %s\r\nexitemu\r\n" % args
(DBENCH / bat).write_bytes(script.encode())
env = dict(os.environ, HOME=str(DHOME))
t0 = time.perf_counter()
rc = subprocess.run(
["timeout", "120", "dosemu", "-t", "-quiet", "-E", r"c:\bench" + "\\" + bat],
env=env, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL).returncode
dt = time.perf_counter() - t0
# dosemu/lredir keeps the lowercase names written by FreeCom
obj = DBENCH / (base.lower() + ".obj")
if not obj.exists():
obj = DBENCH / (base.upper() + ".OBJ")
return dt, rc, raw_md5(obj), norm_md5(obj), obj.stat().st_size if obj.exists() else 0
def bench(name, base, args, bat):
print("\n== %s == gspa %s" % (name, args))
run_dosbox(base, args) # warm-up
run_dosemu(base, args, bat)
results = {}
for label, fn in (("dosbox", lambda: run_dosbox(base, args)),
("dosemu", lambda: run_dosemu(base, args, bat))):
rows = [fn() for _ in range(RUNS)]
results[label] = rows
for dt, rc, raw, norm, size in rows:
print(" %-7s %6.2fs rc=%d size=%d raw=%s norm=%s" %
(label, dt, rc, size, raw[:8], norm[:8]))
print(" %-7s median %.2fs" % (label, statistics.median(r[0] for r in rows)))
n0 = {r[3] for r in results["dosbox"]}
n1 = {r[3] for r in results["dosemu"]}
print(" normalised object identical: %s (%s)" % (n0 == n1 and len(n0) == 1, n0))
if __name__ == "__main__":
bench("A: 4 KB with listing", "t1", "t1 t1.obj t1.lst -l", "bench.bat")
bench("B: 16 KB, no listing", "rt16", "-q rt16 rt16.obj", "bench16.bat")