- sync_rtl/common/: skid_buffer, pipeline_reg, defines (valid/ready) - sync_rtl/mod_add/: modular adder example with Verilator C++ TB - test_framework/: Python-driven Verilator compile/sim/compare pipeline - test_framework/modules/mod_add/: 50-vector test plan, full鏈路 PASS - .trellis/spec/: RTL and test_framework conventions documented
111 lines
3.6 KiB
Python
Executable File
111 lines
3.6 KiB
Python
Executable File
#!/usr/bin/env python3
|
|
"""run_all.py - CLI entry point for the ML-KEM RTL test framework.
|
|
|
|
Usage:
|
|
python3 run_all.py # Run all modules
|
|
python3 run_all.py --module mod_add # Run specific module
|
|
python3 run_all.py --list # List all registered modules
|
|
python3 run_all.py --module mod_add --case basic # Run single case
|
|
python3 run_all.py --quick # Quick mode (reduced vectors)
|
|
"""
|
|
|
|
import os
|
|
import sys
|
|
import time
|
|
import argparse
|
|
from pathlib import Path
|
|
|
|
# Ensure test_framework/lib is on the path
|
|
sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))
|
|
|
|
from lib.test_runner import TestRunner
|
|
from lib.reporter import Reporter
|
|
|
|
|
|
def main():
|
|
parser = argparse.ArgumentParser(
|
|
description='ML-KEM RTL Test Framework'
|
|
)
|
|
parser.add_argument('--module', '-m', type=str, default=None,
|
|
help='Run specific module only')
|
|
parser.add_argument('--case', '-c', type=str, default=None,
|
|
help='Run specific test case only')
|
|
parser.add_argument('--list', '-l', action='store_true',
|
|
help='List all registered modules')
|
|
parser.add_argument('--quick', '-q', action='store_true',
|
|
help='Quick mode (reduced vectors)')
|
|
parser.add_argument('--config', type=str, default='test_framework/config.json',
|
|
help='Path to config.json')
|
|
|
|
args = parser.parse_args()
|
|
|
|
# Change to project root (parent of test_framework/)
|
|
script_dir = os.path.dirname(os.path.abspath(__file__))
|
|
project_root = os.path.dirname(script_dir)
|
|
os.chdir(project_root)
|
|
|
|
runner = TestRunner(config_path=args.config)
|
|
modules = runner.discover_modules()
|
|
|
|
if args.list:
|
|
print("\nRegistered test modules:")
|
|
if not modules:
|
|
print(" (none found)")
|
|
for name, plan in sorted(modules.items()):
|
|
num_cases = len(plan.get('cases', []))
|
|
print(f" {name}: {num_cases} case(s)")
|
|
for case in plan.get('cases', []):
|
|
print(f" - {case['id']}: {case.get('description', '')}")
|
|
print()
|
|
return 0
|
|
|
|
if not modules:
|
|
print("No test modules found in test_framework/modules/")
|
|
return 1
|
|
|
|
# Determine which modules to run
|
|
if args.module:
|
|
if args.module not in modules:
|
|
print(f"Error: Module '{args.module}' not found.")
|
|
print(f"Available: {', '.join(sorted(modules.keys()))}")
|
|
return 1
|
|
to_run = [args.module]
|
|
else:
|
|
to_run = sorted(modules.keys())
|
|
|
|
# Run tests
|
|
results = {}
|
|
total_start = time.time()
|
|
|
|
reporter = Reporter(runner.config.get('report_root', 'test_framework/reports'))
|
|
|
|
for module_name in to_run:
|
|
print(f"\n{'='*50}")
|
|
print(f" Testing: {module_name}")
|
|
print(f"{'='*50}")
|
|
|
|
result = runner.run_module(
|
|
module_name,
|
|
quick=args.quick,
|
|
single_case=args.case
|
|
)
|
|
results[module_name] = result
|
|
|
|
if result['status'] == 'COMPILE_ERROR':
|
|
print(f" ERROR: Verilator compilation failed for {module_name}")
|
|
elif result['status'] == 'ERROR':
|
|
print(f" ERROR: {result.get('error', 'Unknown error')}")
|
|
elif result['status'] == 'NOT_FOUND':
|
|
print(f" ERROR: {result.get('error', 'Module not found')}")
|
|
|
|
total_elapsed = time.time() - total_start
|
|
|
|
# Print summary
|
|
all_pass = reporter.print_summary(results, total_elapsed)
|
|
|
|
return 0 if all_pass else 1
|
|
|
|
|
|
if __name__ == '__main__':
|
|
sys.exit(main())
|