1
0
mirror of https://github.com/TomHarte/CLK.git synced 2024-11-26 23:52:26 +00:00

Applies trace testing to EmuTOS.

This commit is contained in:
Thomas Harte 2019-04-29 16:55:21 -04:00
parent c466b6f9e7
commit 5b5bfc8445
5 changed files with 33 additions and 29 deletions

View File

@ -246,6 +246,7 @@
4B83348A1F5DB94B0097E338 /* IRQDelegatePortHandler.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B8334891F5DB94B0097E338 /* IRQDelegatePortHandler.cpp */; }; 4B83348A1F5DB94B0097E338 /* IRQDelegatePortHandler.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B8334891F5DB94B0097E338 /* IRQDelegatePortHandler.cpp */; };
4B83348C1F5DB99C0097E338 /* 6522Base.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B83348B1F5DB99C0097E338 /* 6522Base.cpp */; }; 4B83348C1F5DB99C0097E338 /* 6522Base.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B83348B1F5DB99C0097E338 /* 6522Base.cpp */; };
4B8334951F5E25B60097E338 /* C1540.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B8334941F5E25B60097E338 /* C1540.cpp */; }; 4B8334951F5E25B60097E338 /* C1540.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B8334941F5E25B60097E338 /* C1540.cpp */; };
4B85322D227793CB00F26553 /* etos192uk.trace.txt.gz in Resources */ = {isa = PBXBuildFile; fileRef = 4B85322C227793CA00F26553 /* etos192uk.trace.txt.gz */; };
4B86E25B1F8C628F006FAA45 /* Keyboard.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B86E2591F8C628F006FAA45 /* Keyboard.cpp */; }; 4B86E25B1F8C628F006FAA45 /* Keyboard.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B86E2591F8C628F006FAA45 /* Keyboard.cpp */; };
4B8805F01DCFC99C003085B1 /* Acorn.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B8805EE1DCFC99C003085B1 /* Acorn.cpp */; }; 4B8805F01DCFC99C003085B1 /* Acorn.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B8805EE1DCFC99C003085B1 /* Acorn.cpp */; };
4B8805F41DCFD22A003085B1 /* Commodore.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B8805F21DCFD22A003085B1 /* Commodore.cpp */; }; 4B8805F41DCFD22A003085B1 /* Commodore.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B8805F21DCFD22A003085B1 /* Commodore.cpp */; };
@ -964,6 +965,7 @@
4B8334911F5E24FF0097E338 /* C1540Base.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = C1540Base.hpp; path = Implementation/C1540Base.hpp; sourceTree = "<group>"; }; 4B8334911F5E24FF0097E338 /* C1540Base.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = C1540Base.hpp; path = Implementation/C1540Base.hpp; sourceTree = "<group>"; };
4B8334941F5E25B60097E338 /* C1540.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = C1540.cpp; path = Implementation/C1540.cpp; sourceTree = "<group>"; }; 4B8334941F5E25B60097E338 /* C1540.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = C1540.cpp; path = Implementation/C1540.cpp; sourceTree = "<group>"; };
4B85322922778E4200F26553 /* Comparative68000.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = Comparative68000.hpp; sourceTree = "<group>"; }; 4B85322922778E4200F26553 /* Comparative68000.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = Comparative68000.hpp; sourceTree = "<group>"; };
4B85322C227793CA00F26553 /* etos192uk.trace.txt.gz */ = {isa = PBXFileReference; lastKnownFileType = archive.gzip; path = etos192uk.trace.txt.gz; sourceTree = "<group>"; };
4B86E2591F8C628F006FAA45 /* Keyboard.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Keyboard.cpp; sourceTree = "<group>"; }; 4B86E2591F8C628F006FAA45 /* Keyboard.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Keyboard.cpp; sourceTree = "<group>"; };
4B86E25A1F8C628F006FAA45 /* Keyboard.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = Keyboard.hpp; sourceTree = "<group>"; }; 4B86E25A1F8C628F006FAA45 /* Keyboard.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = Keyboard.hpp; sourceTree = "<group>"; };
4B8805EE1DCFC99C003085B1 /* Acorn.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = Acorn.cpp; path = Parsers/Acorn.cpp; sourceTree = "<group>"; }; 4B8805EE1DCFC99C003085B1 /* Acorn.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = Acorn.cpp; path = Parsers/Acorn.cpp; sourceTree = "<group>"; };
@ -1567,6 +1569,7 @@
4B1414631B588A1100E04248 /* Test Binaries */ = { 4B1414631B588A1100E04248 /* Test Binaries */ = {
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
4B85322B227793CA00F26553 /* TOS Startup */,
4B9252CD1E74D28200B76AF1 /* Atari ROMs */, 4B9252CD1E74D28200B76AF1 /* Atari ROMs */,
4B44EBF81DC9898E00A7820C /* BCDTEST_beeb */, 4B44EBF81DC9898E00A7820C /* BCDTEST_beeb */,
4B98A1CD1FFADEC400ADF63B /* MSX ROMs */, 4B98A1CD1FFADEC400ADF63B /* MSX ROMs */,
@ -2256,6 +2259,14 @@
name = Implementation; name = Implementation;
sourceTree = "<group>"; sourceTree = "<group>";
}; };
4B85322B227793CA00F26553 /* TOS Startup */ = {
isa = PBXGroup;
children = (
4B85322C227793CA00F26553 /* etos192uk.trace.txt.gz */,
);
path = "TOS Startup";
sourceTree = "<group>";
};
4B86E2581F8C628F006FAA45 /* Inputs */ = { 4B86E2581F8C628F006FAA45 /* Inputs */ = {
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
@ -3457,6 +3468,7 @@
4BB298FB1B587D8400A49093 /* ancb in Resources */, 4BB298FB1B587D8400A49093 /* ancb in Resources */,
4BB299431B587D8400A49093 /* dcma in Resources */, 4BB299431B587D8400A49093 /* dcma in Resources */,
4BB298FD1B587D8400A49093 /* andax in Resources */, 4BB298FD1B587D8400A49093 /* andax in Resources */,
4B85322D227793CB00F26553 /* etos192uk.trace.txt.gz in Resources */,
4BB299401B587D8400A49093 /* cpya in Resources */, 4BB299401B587D8400A49093 /* cpya in Resources */,
4BB299BE1B587D8400A49093 /* rraix in Resources */, 4BB299BE1B587D8400A49093 /* rraix in Resources */,
4BB299E41B587D8400A49093 /* tayn in Resources */, 4BB299E41B587D8400A49093 /* tayn in Resources */,

View File

@ -32,7 +32,7 @@ class ComparativeBusHandler: public CPU::MC68000::BusHandler {
// Generate state locally. // Generate state locally.
const auto state = get_state(); const auto state = get_state();
char local_state[300]; char local_state[300];
sprintf(local_state, "%04x: %02x %08x %08x %08x %08x %08x %08x %08x %08x %08x %08x %08x %08x %08x %08x %08x %08x \n", sprintf(local_state, "%04x: %02x %08x %08x %08x %08x %08x %08x %08x %08x %08x %08x %08x %08x %08x %08x %08x %08x\n",
address, address,
state.status, state.status,
state.data[0], state.data[1], state.data[2], state.data[3], state.data[4], state.data[5], state.data[6], state.data[7], state.data[0], state.data[1], state.data[2], state.data[3], state.data[4], state.data[5], state.data[6], state.data[7],
@ -43,8 +43,8 @@ class ComparativeBusHandler: public CPU::MC68000::BusHandler {
// Check that the two coincide. // Check that the two coincide.
if(strcmp(correct_state, local_state)) { if(strcmp(correct_state, local_state)) {
fprintf(stderr, "Diverges at line %d\n", line_count); fprintf(stderr, "Diverges at line %d\n", line_count);
fprintf(stderr, "Good: %s\n", correct_state); fprintf(stderr, "Good: %s", correct_state);
fprintf(stderr, "Bad: %s\n", local_state); fprintf(stderr, "Bad: %s", local_state);
assert(false); assert(false);
} }
} }

View File

@ -12,11 +12,12 @@
#include <cassert> #include <cassert>
#include "68000.hpp" #include "68000.hpp"
#include "Comparative68000.hpp"
#include "CSROMFetcher.hpp" #include "CSROMFetcher.hpp"
class EmuTOS: public CPU::MC68000::BusHandler { class EmuTOS: public ComparativeBusHandler {
public: public:
EmuTOS(const std::vector<uint8_t> &emuTOS) : m68000_(*this) { EmuTOS(const std::vector<uint8_t> &emuTOS, const char *trace_name) : ComparativeBusHandler(trace_name), m68000_(*this) {
assert(!(emuTOS.size() & 1)); assert(!(emuTOS.size() & 1));
emuTOS_.resize(emuTOS.size() / 2); emuTOS_.resize(emuTOS.size() / 2);
@ -29,10 +30,18 @@ class EmuTOS: public CPU::MC68000::BusHandler {
m68000_.run_for(cycles); m68000_.run_for(cycles);
} }
CPU::MC68000::ProcessorState get_state() override {
return m68000_.get_state();
}
HalfCycles perform_bus_operation(const CPU::MC68000::Microcycle &cycle, int is_supervisor) { HalfCycles perform_bus_operation(const CPU::MC68000::Microcycle &cycle, int is_supervisor) {
const uint32_t address = cycle.word_address(); const uint32_t address = cycle.word_address();
uint32_t word_address = address; uint32_t word_address = address;
if(cycle.address) {
printf("%04x\n", *cycle.address);
}
// As much about the Atari ST's memory map as is relevant here: the ROM begins // As much about the Atari ST's memory map as is relevant here: the ROM begins
// at 0xfc0000, and the first eight bytes are mirrored to the first four memory // at 0xfc0000, and the first eight bytes are mirrored to the first four memory
// addresses in order for /RESET to work properly. RAM otherwise fills the first // addresses in order for /RESET to work properly. RAM otherwise fills the first
@ -42,9 +51,9 @@ class EmuTOS: public CPU::MC68000::BusHandler {
const bool is_rom = word_address > (0xfc0000 >> 1) || word_address < 4; const bool is_rom = word_address > (0xfc0000 >> 1) || word_address < 4;
uint16_t *const base = is_rom ? emuTOS_.data() : ram_.data(); uint16_t *const base = is_rom ? emuTOS_.data() : ram_.data();
if(is_rom) { if(is_rom) {
word_address &= 0xffff; word_address %= emuTOS_.size();
} else { } else {
word_address &= 0x3ffff; word_address %= ram_.size();
} }
using Microcycle = CPU::MC68000::Microcycle; using Microcycle = CPU::MC68000::Microcycle;
@ -72,20 +81,14 @@ class EmuTOS: public CPU::MC68000::BusHandler {
case Microcycle::SelectWord | Microcycle::Read: case Microcycle::SelectWord | Microcycle::Read:
cycle.value->full = is_peripheral ? peripheral_result : base[word_address]; cycle.value->full = is_peripheral ? peripheral_result : base[word_address];
// if(!(cycle.operation & Microcycle::IsProgram)) printf("[word r %08x -> %04x] ", *cycle.address, cycle.value->full);
break; break;
case Microcycle::SelectByte | Microcycle::Read: case Microcycle::SelectByte | Microcycle::Read:
cycle.value->halves.low = (is_peripheral ? peripheral_result : base[word_address]) >> cycle.byte_shift(); cycle.value->halves.low = (is_peripheral ? peripheral_result : base[word_address]) >> cycle.byte_shift();
// if(!(cycle.operation & Microcycle::IsProgram)) printf("[byte r %08x -> %02x] ", *cycle.address, cycle.value->halves.low);
break; break;
case Microcycle::SelectWord: case Microcycle::SelectWord:
assert(!(is_rom && !is_peripheral));
// if(!(cycle.operation & Microcycle::IsProgram)) printf("[word w %04x -> %08x] ", cycle.value->full, *cycle.address);
base[word_address] = cycle.value->full; base[word_address] = cycle.value->full;
break; break;
case Microcycle::SelectByte: case Microcycle::SelectByte:
assert(!(is_rom && !is_peripheral));
// if(!(cycle.operation & Microcycle::IsProgram)) printf("[byte w %02x -> %08x] ", cycle.value->halves.low, *cycle.address);
base[word_address] = (cycle.value->halves.low << cycle.byte_shift()) | (base[word_address] & (0xffff ^ cycle.byte_mask())); base[word_address] = (cycle.value->halves.low << cycle.byte_shift()) | (base[word_address] & (0xffff ^ cycle.byte_mask()));
break; break;
} }
@ -95,7 +98,7 @@ class EmuTOS: public CPU::MC68000::BusHandler {
} }
private: private:
CPU::MC68000::Processor<EmuTOS, true> m68000_; CPU::MC68000::Processor<EmuTOS, true, true> m68000_;
std::vector<uint16_t> emuTOS_; std::vector<uint16_t> emuTOS_;
std::array<uint16_t, 256*1024> ram_; std::array<uint16_t, 256*1024> ram_;
@ -108,19 +111,10 @@ class EmuTOS: public CPU::MC68000::BusHandler {
std::unique_ptr<EmuTOS> _machine; std::unique_ptr<EmuTOS> _machine;
} }
- (void)setUp { - (void)testEmuTOSStartup {
// Put setup code here. This method is called before the invocation of each test method in the class. const auto roms = CSROMFetcher()("AtariST", {"etos192uk.img"});
const auto roms = CSROMFetcher()("AtariST", {"tos100.img"}); NSString *const traceLocation = [[NSBundle bundleForClass:[self class]] pathForResource:@"etos192uk" ofType:@"trace.txt.gz"];
_machine.reset(new EmuTOS(*roms[0])); _machine.reset(new EmuTOS(*roms[0], traceLocation.UTF8String));
}
- (void)tearDown {
// Put teardown code here. This method is called after the invocation of each test method in the class.
}
- (void)testStartup {
// This is an example of a functional test case.
// Use XCTAssert and related functions to verify your tests produce the correct results.
_machine->run_for(HalfCycles(8000000)); _machine->run_for(HalfCycles(8000000));
} }

View File

@ -107,8 +107,6 @@ class QL: public ComparativeBusHandler {
// This is how many cycles it takes to exhaust the supplied trace file. // This is how many cycles it takes to exhaust the supplied trace file.
_machine->run_for(HalfCycles(23923180)); _machine->run_for(HalfCycles(23923180));
_machine.reset();
} }
@end @end