mirror of
https://github.com/transistorfet/moa.git
synced 2024-11-21 19:30:52 +00:00
Added more options to run select tests to harte test runner
This commit is contained in:
parent
f3a177489e
commit
c53253c050
112
Cargo.lock
generated
112
Cargo.lock
generated
@ -170,27 +170,26 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "clap"
|
||||
version = "3.0.0-beta.5"
|
||||
version = "3.2.20"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "feff3878564edb93745d58cf63e17b63f24142506e7a20c87a5521ed7bfb1d63"
|
||||
checksum = "23b71c3ce99b7611011217b366d923f1d0a7e07a92bb2dbf1e84508c673ca3bd"
|
||||
dependencies = [
|
||||
"atty",
|
||||
"bitflags",
|
||||
"clap_derive",
|
||||
"clap_lex",
|
||||
"indexmap",
|
||||
"lazy_static",
|
||||
"os_str_bytes",
|
||||
"once_cell",
|
||||
"strsim 0.10.0",
|
||||
"termcolor",
|
||||
"textwrap 0.14.2",
|
||||
"unicase",
|
||||
"textwrap 0.15.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "clap_derive"
|
||||
version = "3.0.0-beta.5"
|
||||
version = "3.2.18"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8b15c6b4f786ffb6192ffe65a36855bc1fc2444bcd0945ae16748dcd6ed7d0d3"
|
||||
checksum = "ea0c8bce528c4be4da13ea6fead8965e95b6073585a2f05204bd8f4119f82a65"
|
||||
dependencies = [
|
||||
"heck",
|
||||
"proc-macro-error",
|
||||
@ -199,6 +198,15 @@ dependencies = [
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "clap_lex"
|
||||
version = "0.2.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2850f2f5a82cbf437dd5af4d49848fbdfc27c157c3d010345776f952765261c5"
|
||||
dependencies = [
|
||||
"os_str_bytes",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cmake"
|
||||
version = "0.1.46"
|
||||
@ -398,6 +406,18 @@ version = "0.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9b919933a397b79c37e33b77bb2aa3dc8eb6e165ad809e58ff75bc7db2e34574"
|
||||
|
||||
[[package]]
|
||||
name = "harte_tests"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"clap 3.2.20",
|
||||
"flate2",
|
||||
"moa",
|
||||
"serde",
|
||||
"serde_derive",
|
||||
"serde_json",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "hashbrown"
|
||||
version = "0.11.2"
|
||||
@ -406,12 +426,9 @@ checksum = "ab5ef0d4909ef3724cc8cce6ccc8572c5c817592e9285f5464f8e86f8bd3726e"
|
||||
|
||||
[[package]]
|
||||
name = "heck"
|
||||
version = "0.3.3"
|
||||
version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6d621efb26863f0e9924c6ac577e8275e5e6b77455db64ffa6c65c904e9e132c"
|
||||
dependencies = [
|
||||
"unicode-segmentation",
|
||||
]
|
||||
checksum = "2540771e65fc8cb83cd6e8a237f70c319bd5c29f78ed1084ba5d50eeac86f7f9"
|
||||
|
||||
[[package]]
|
||||
name = "hermit-abi"
|
||||
@ -453,6 +470,12 @@ dependencies = [
|
||||
"cfg-if 1.0.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "itoa"
|
||||
version = "1.0.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6c8af84674fe1f223a982c933a0ee1086ac4d4052aa0fb8060c12c6ad838e754"
|
||||
|
||||
[[package]]
|
||||
name = "jni"
|
||||
version = "0.19.0"
|
||||
@ -621,7 +644,7 @@ dependencies = [
|
||||
name = "moa-minifb"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"clap 3.0.0-beta.5",
|
||||
"clap 3.2.20",
|
||||
"minifb",
|
||||
"moa",
|
||||
"moa-common",
|
||||
@ -812,9 +835,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "once_cell"
|
||||
version = "1.8.0"
|
||||
version = "1.14.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "692fcb63b64b1758029e0a96ee63e049ce8c5948587f2f7208df04625e5f6b56"
|
||||
checksum = "2f7254b99e31cad77da24b08ebf628882739a608578bb1bcdfc1f9c21260d7c0"
|
||||
|
||||
[[package]]
|
||||
name = "orbclient"
|
||||
@ -833,12 +856,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "os_str_bytes"
|
||||
version = "4.2.0"
|
||||
version = "6.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "addaa943333a514159c80c97ff4a93306530d965d27e139188283cd13e06a799"
|
||||
dependencies = [
|
||||
"memchr",
|
||||
]
|
||||
checksum = "9ff7415e9ae3fff1225851df9e0d9e4e5479f947619774677a63572e55e80eff"
|
||||
|
||||
[[package]]
|
||||
name = "parking_lot"
|
||||
@ -1034,6 +1054,12 @@ version = "1.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2"
|
||||
|
||||
[[package]]
|
||||
name = "ryu"
|
||||
version = "1.0.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4501abdff3ae82a1c1b477a17252eb69cee9e66eb915c1abaa4f44d873df9f09"
|
||||
|
||||
[[package]]
|
||||
name = "same-file"
|
||||
version = "1.0.6"
|
||||
@ -1083,6 +1109,28 @@ version = "1.0.130"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f12d06de37cf59146fbdecab66aa99f9fe4f78722e3607577a5375d66bd0c913"
|
||||
|
||||
[[package]]
|
||||
name = "serde_derive"
|
||||
version = "1.0.136"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "08597e7152fcd306f41838ed3e37be9eaeed2b61c42e2117266a554fab4662f9"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_json"
|
||||
version = "1.0.85"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e55a28e3aaef9d5ce0506d0a14dbba8054ddc7e499ef522dd8b26859ec9d4a44"
|
||||
dependencies = [
|
||||
"itoa",
|
||||
"ryu",
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "shlex"
|
||||
version = "0.1.1"
|
||||
@ -1175,12 +1223,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "textwrap"
|
||||
version = "0.14.2"
|
||||
version = "0.15.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0066c8d12af8b5acd21e00547c3797fde4e8677254a7ee429176ccebbe93dd80"
|
||||
dependencies = [
|
||||
"unicode-width",
|
||||
]
|
||||
checksum = "b1141d4d61095b28419e22cb0bbf02755f5e54e0526f97f1e3d1d160e60885fb"
|
||||
|
||||
[[package]]
|
||||
name = "thiserror"
|
||||
@ -1211,21 +1256,6 @@ dependencies = [
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "unicase"
|
||||
version = "2.6.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "50f37be617794602aabbeee0be4f259dc1778fabe05e2d67ee8f79326d5cb4f6"
|
||||
dependencies = [
|
||||
"version_check",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "unicode-segmentation"
|
||||
version = "1.8.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8895849a949e7845e06bd6dc1aa51731a103c42707010a5b591c0038fb73385b"
|
||||
|
||||
[[package]]
|
||||
name = "unicode-width"
|
||||
version = "0.1.9"
|
||||
|
@ -6,6 +6,7 @@ use crate::devices::{Address, Addressable, Debuggable};
|
||||
use super::state::M68k;
|
||||
use super::decode::M68kDecoder;
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct StackTracer {
|
||||
pub calls: Vec<u32>,
|
||||
}
|
||||
@ -27,6 +28,7 @@ impl StackTracer {
|
||||
}
|
||||
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct M68kDebugger {
|
||||
pub enabled: bool,
|
||||
pub breakpoints: Vec<u32>,
|
||||
@ -68,10 +70,10 @@ impl Debuggable for M68k {
|
||||
}
|
||||
}
|
||||
|
||||
fn print_current_step(&mut self, system: &System) -> Result<(), Error> {
|
||||
fn print_current_step(&mut self, _system: &System) -> Result<(), Error> {
|
||||
self.decoder.decode_at(&mut self.port, self.state.pc)?;
|
||||
self.decoder.dump_decoded(&mut self.port);
|
||||
self.dump_state(system);
|
||||
self.dump_state();
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
@ -38,6 +38,7 @@ const OPCG_SHIFT: u8 = 0xE;
|
||||
const OPCG_FLINE: u8 = 0xF;
|
||||
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct M68kDecoder {
|
||||
pub cputype: M68kType,
|
||||
pub start: u32,
|
||||
|
@ -31,8 +31,8 @@ impl Steppable for M68k {
|
||||
self.step_internal(system)
|
||||
}
|
||||
|
||||
fn on_error(&mut self, system: &System) {
|
||||
self.dump_state(system);
|
||||
fn on_error(&mut self, _system: &System) {
|
||||
self.dump_state();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,5 +1,4 @@
|
||||
|
||||
use crate::system::System;
|
||||
use crate::devices::Address;
|
||||
use crate::timers::CpuTimer;
|
||||
use crate::memory::BusPort;
|
||||
@ -121,6 +120,7 @@ impl M68kState {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct M68k {
|
||||
pub cputype: M68kType,
|
||||
pub frequency: u32,
|
||||
@ -154,7 +154,7 @@ impl M68k {
|
||||
self.debugger = M68kDebugger::new();
|
||||
}
|
||||
|
||||
pub fn dump_state(&mut self, _system: &System) {
|
||||
pub fn dump_state(&mut self) {
|
||||
println!("Status: {:?}", self.state.status);
|
||||
println!("PC: {:#010x}", self.state.pc);
|
||||
println!("SR: {:#06x}", self.state.sr);
|
||||
|
@ -111,12 +111,14 @@ impl Transmutable for AddressAdapter {
|
||||
}
|
||||
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct Block {
|
||||
pub base: Address,
|
||||
pub length: usize,
|
||||
pub dev: TransmutableBox,
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct Bus {
|
||||
blocks: Vec<Block>,
|
||||
ignore_unmapped: bool,
|
||||
@ -238,6 +240,7 @@ impl Addressable for Bus {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct BusPort {
|
||||
offset: Address,
|
||||
address_mask: Address,
|
||||
|
@ -47,6 +47,7 @@ impl fmt::Display for AverageTimer {
|
||||
}
|
||||
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct CpuTimer {
|
||||
pub decode: AverageTimer,
|
||||
pub execute: AverageTimer,
|
||||
|
10
tests/harte_tests/run_all.sh
Executable file
10
tests/harte_tests/run_all.sh
Executable file
@ -0,0 +1,10 @@
|
||||
#!/bin/bash
|
||||
COMMIT=$(git rev-parse HEAD)
|
||||
DATE=$(date --iso)
|
||||
LOCATION=$(dirname ${BASH_SOURCE[0]})
|
||||
{
|
||||
cd $LOCATION
|
||||
echo "Last run on $DATE at commit $COMMIT" | tee latest.txt
|
||||
echo "" | tee -a latest.txt
|
||||
cargo run -- -q --testsuite "../ProcessorTests/680x0/68000/uncompressed/" | tee -a latest.txt
|
||||
}
|
@ -1,5 +1,5 @@
|
||||
|
||||
const HART_TESTS: &str = "tests/ProcessorTests/680x0/68000/v1/";
|
||||
const DEFAULT_HART_TESTS: &str = "tests/ProcessorTests/680x0/68000/v1/";
|
||||
|
||||
use std::io::prelude::*;
|
||||
use std::fmt::Debug;
|
||||
@ -23,6 +23,9 @@ use moa::cpus::m68k::state::Status;
|
||||
struct Args {
|
||||
/// Filter the tests by gzip file name
|
||||
filter: Option<String>,
|
||||
/// Only run the one test with the given number
|
||||
#[clap(short, long)]
|
||||
only: Option<String>,
|
||||
/// Dump the CPU state when a test fails
|
||||
#[clap(short, long)]
|
||||
debug: bool,
|
||||
@ -32,27 +35,14 @@ struct Args {
|
||||
/// Also test instruction timing
|
||||
#[clap(short, long)]
|
||||
timing: bool,
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord)]
|
||||
enum InfoLevel {
|
||||
Quiet,
|
||||
Normal,
|
||||
Debug,
|
||||
/// Directory to the test suite to run
|
||||
#[clap(long, default_value = DEFAULT_HART_TESTS)]
|
||||
testsuite: String,
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let args = Args::parse();
|
||||
|
||||
let level = if args.debug {
|
||||
InfoLevel::Debug
|
||||
} else if args.quiet {
|
||||
InfoLevel::Quiet
|
||||
} else {
|
||||
InfoLevel::Normal
|
||||
};
|
||||
|
||||
run_all_tests(args, level);
|
||||
run_all_tests(&args);
|
||||
}
|
||||
|
||||
|
||||
@ -91,6 +81,44 @@ struct TestCase {
|
||||
length: usize
|
||||
}
|
||||
|
||||
impl TestState {
|
||||
pub fn dump(&self) {
|
||||
println!("d0: {:08x} a0: {:08x}", self.d0, self.a0);
|
||||
println!("d1: {:08x} a1: {:08x}", self.d1, self.a1);
|
||||
println!("d2: {:08x} a2: {:08x}", self.d2, self.a2);
|
||||
println!("d3: {:08x} a3: {:08x}", self.d3, self.a3);
|
||||
println!("d4: {:08x} a4: {:08x}", self.d4, self.a4);
|
||||
println!("d5: {:08x} a5: {:08x}", self.d5, self.a5);
|
||||
println!("d6: {:08x} a6: {:08x}", self.d6, self.a6);
|
||||
println!("d7: {:08x} usp: {:08x}", self.d7, self.usp);
|
||||
println!("pc: {:08x} ssp: {:08x}", self.pc, self.ssp);
|
||||
println!("sr: {:04x}", self.sr);
|
||||
|
||||
print!("prefetch: ");
|
||||
for word in self.prefetch.iter() {
|
||||
print!("{:04x} ", *word);
|
||||
}
|
||||
println!("");
|
||||
|
||||
println!("ram: ");
|
||||
for (addr, byte) in self.ram.iter() {
|
||||
println!("{:08x} {:02x} ", *addr, *byte);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl TestCase {
|
||||
pub fn dump(&self) {
|
||||
println!("{}", self.name);
|
||||
println!("initial:");
|
||||
self.initial_state.dump();
|
||||
println!("final:");
|
||||
self.final_state.dump();
|
||||
println!("cycles: {}", self.length);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
fn init_execute_test(cputype: M68kType, state: &TestState) -> Result<(M68k, System), Error> {
|
||||
let mut system = System::new();
|
||||
|
||||
@ -205,17 +233,21 @@ fn step_cpu_and_assert(cpu: &mut M68k, system: &System, case: &TestCase, test_ti
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn run_test(case: &TestCase, level: InfoLevel, test_timing: bool) -> Result<(), Error> {
|
||||
let (mut cpu, system) = init_execute_test(M68kType::MC68010, &case.initial_state).unwrap();
|
||||
fn run_test(case: &TestCase, args: &Args) -> Result<(), Error> {
|
||||
let (mut cpu, system) = init_execute_test(M68kType::MC68000, &case.initial_state).unwrap();
|
||||
let mut initial_cpu = cpu.clone();
|
||||
|
||||
let result = step_cpu_and_assert(&mut cpu, &system, case, test_timing);
|
||||
let result = step_cpu_and_assert(&mut cpu, &system, case, args.timing);
|
||||
|
||||
match result {
|
||||
Ok(()) => Ok(()),
|
||||
Err(err) => {
|
||||
if level > InfoLevel::Quiet {
|
||||
if level == InfoLevel::Debug {
|
||||
cpu.dump_state(&system);
|
||||
if !args.quiet {
|
||||
if args.debug {
|
||||
case.dump();
|
||||
println!("");
|
||||
initial_cpu.dump_state();
|
||||
cpu.dump_state();
|
||||
}
|
||||
println!("FAILED: {}", err.msg);
|
||||
}
|
||||
@ -224,24 +256,37 @@ fn run_test(case: &TestCase, level: InfoLevel, test_timing: bool) -> Result<(),
|
||||
}
|
||||
}
|
||||
|
||||
fn test_json_file(path: PathBuf, level: InfoLevel, test_timing: bool) -> (usize, usize, String) {
|
||||
let file = File::open(&path).unwrap();
|
||||
let mut decoder = GzDecoder::new(file);
|
||||
let mut data = String::new();
|
||||
decoder.read_to_string(&mut data).unwrap();
|
||||
let cases: Vec<TestCase> = serde_json::from_str(&data).unwrap();
|
||||
fn test_json_file(path: PathBuf, args: &Args) -> (usize, usize, String) {
|
||||
let extension = path.extension().unwrap();
|
||||
|
||||
let cases: Vec<TestCase> = if extension == "gz" {
|
||||
let file = File::open(&path).unwrap();
|
||||
let mut decoder = GzDecoder::new(file);
|
||||
let mut data = String::new();
|
||||
decoder.read_to_string(&mut data).unwrap();
|
||||
serde_json::from_str(&data).unwrap()
|
||||
} else {
|
||||
let data = fs::read(&path).unwrap();
|
||||
serde_json::from_slice(&data).unwrap()
|
||||
};
|
||||
|
||||
let mut passed = 0;
|
||||
let mut failed = 0;
|
||||
for case in cases {
|
||||
if level > InfoLevel::Quiet {
|
||||
if let Some(only) = args.only.as_ref() {
|
||||
if !case.name.ends_with(only) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if !args.quiet {
|
||||
println!("Running test {}", case.name);
|
||||
}
|
||||
let result = run_test(&case, level, test_timing);
|
||||
let result = run_test(&case, args);
|
||||
|
||||
if let Err(err) = result {
|
||||
failed += 1;
|
||||
if level > InfoLevel::Quiet {
|
||||
if !args.quiet {
|
||||
println!("FAILED: {:?}", err);
|
||||
}
|
||||
} else {
|
||||
@ -260,13 +305,13 @@ fn test_json_file(path: PathBuf, level: InfoLevel, test_timing: bool) -> (usize,
|
||||
}
|
||||
|
||||
|
||||
fn run_all_tests(args: Args, level: InfoLevel) {
|
||||
fn run_all_tests(args: &Args) {
|
||||
let mut passed = 0;
|
||||
let mut failed = 0;
|
||||
let mut messages = vec![];
|
||||
|
||||
|
||||
let mut tests: Vec<PathBuf> = fs::read_dir(HART_TESTS)
|
||||
let mut tests: Vec<PathBuf> = fs::read_dir(&args.testsuite)
|
||||
.unwrap()
|
||||
.map(|dirent| dirent.unwrap().path())
|
||||
.collect();
|
||||
@ -275,7 +320,8 @@ fn run_all_tests(args: Args, level: InfoLevel) {
|
||||
let start = SystemTime::now();
|
||||
for path in tests {
|
||||
// Only test gzip files (the repo has .md files as well)
|
||||
if path.extension().unwrap() != "gz" {
|
||||
let extension = path.extension().unwrap();
|
||||
if extension != "json" && extension != "gz" {
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -287,10 +333,10 @@ fn run_all_tests(args: Args, level: InfoLevel) {
|
||||
}
|
||||
|
||||
// Run every test in the file
|
||||
let (test_passed, test_failed, message) = test_json_file(path, level, args.timing);
|
||||
let (test_passed, test_failed, message) = test_json_file(path, args);
|
||||
|
||||
// In quiet mode, print each summary as it's received to give a progress update
|
||||
if level == InfoLevel::Quiet {
|
||||
if args.quiet {
|
||||
println!("{}", message);
|
||||
}
|
||||
|
||||
@ -301,7 +347,7 @@ fn run_all_tests(args: Args, level: InfoLevel) {
|
||||
let elapsed_secs = start.elapsed().unwrap().as_secs();
|
||||
|
||||
// Print the stored summary if not in quite mode
|
||||
if level > InfoLevel::Quiet {
|
||||
if !args.quiet {
|
||||
for message in messages {
|
||||
println!("{}", message);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user