feat: init mlkem project with Verilator test framework
- 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
This commit is contained in:
110
test_framework/run_all.py
Executable file
110
test_framework/run_all.py
Executable file
@@ -0,0 +1,110 @@
|
||||
#!/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())
|
||||
Reference in New Issue
Block a user