Initial commit: retroDE_ps2 — first-of-its-kind PS2 GS FPGA core (DE25-Nano / Agilex 5)

RTL (GS rasterizer, EE core stub, platform bridge, LPDDR4B path), sim regression
(272 TBs), docs, and tooling. Copyrighted PS2 content (BIOS, game code, GS dumps,
and all dump-derived textures/traces) is excluded via .gitignore and stays local.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-06-29 20:10:50 -04:00
commit ec82764bef
2462 changed files with 2174303 additions and 0 deletions
+45
View File
@@ -0,0 +1,45 @@
# retroDE_ps2 — DobieStation headless trace runner build
#
# Links against the libCore.a produced by the DobieStation build in
# third_party/DobieStation/build/. Requires that build to exist first:
#
# cd ../../../third_party/DobieStation
# mkdir -p build && cd build && cmake .. && make -j$(nproc)
#
# Then from this directory:
#
# make
# ./trace_runner ../../vectors/bios/nop_sled.bin
#
# See also: trace_runner.cpp header comment.
RUNNER_DIR := $(CURDIR)
REPO_ROOT := $(abspath $(RUNNER_DIR)/../../..)
DOBIE_ROOT := $(REPO_ROOT)/third_party/DobieStation
DOBIE_BUILD := $(DOBIE_ROOT)/build
CXX := g++
CXXFLAGS := -std=c++17 -O2 -Wall -Wno-unused
INCLUDES := -I$(DOBIE_ROOT)/src/core -I$(DOBIE_ROOT)/ext
LIBCORE_A := $(DOBIE_BUILD)/src/core/libCore.a
LIBCHDR_A := $(DOBIE_BUILD)/ext/libchdr/liblibchdr.a
LIBLZMA_A := $(DOBIE_BUILD)/ext/lzma/liblzma.a
LIBFLAC_A := $(DOBIE_BUILD)/ext/libFLAC/liblibFLAC.a
LIBZLIB_A := $(DOBIE_BUILD)/ext/zlib/libzlib.a
LDFLAGS := $(LIBCORE_A) $(LIBCHDR_A) $(LIBLZMA_A) $(LIBFLAC_A) $(LIBZLIB_A) \
-pthread
.PHONY: all clean check-libcore
all: trace_runner
check-libcore:
@test -f $(DOBIE_BUILD)/src/core/libCore.a || \
(echo "ERROR: $(DOBIE_BUILD)/src/core/libCore.a missing — build DobieStation first" && exit 1)
trace_runner: trace_runner.cpp check-libcore
$(CXX) $(CXXFLAGS) $(INCLUDES) $< -o $@ $(LDFLAGS)
clean:
rm -f trace_runner
@@ -0,0 +1,13 @@
// Minimal smoke test: construct + reset. No BIOS, no run.
#include <cstdio>
#include "emulator.hpp"
int main()
{
std::fprintf(stderr, "[smoke] constructing Emulator...\n");
Emulator e;
std::fprintf(stderr, "[smoke] constructed\n");
e.reset();
std::fprintf(stderr, "[smoke] reset done\n");
return 0;
}
@@ -0,0 +1,74 @@
// retroDE_ps2 — DobieStation headless trace runner
//
// Minimal harness for the golden-reference harness. Loads a BIOS image,
// boots the EE in interpreter mode, runs a bounded number of frames, and
// exits. The EE instruction-fetch trace is emitted by the tap added in
// third_party/DobieStation/src/core/ee/emotion.cpp when the environment
// variable RETRODE_PS2_EE_TRACE is set to a file path.
//
// Intended for Wave 1 / Checkpoint 2 of the harness: NOP-sled BIOS,
// short run, compare first-N fetches against the RTL stub trace.
//
// Usage:
// RETRODE_PS2_EE_TRACE=/path/to/dobie_ee.trace ./trace_runner <bios.bin> [frames]
//
// Notes:
// - BIOS image must be exactly 4 MiB. Anything shorter is zero-padded;
// anything longer is truncated.
// - `frames` defaults to 1. One frame is ~4.9M EE cycles, which is far
// more than Checkpoint 2 needs; keep it small.
#include <cstdint>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <fstream>
#include <vector>
#include "emulator.hpp"
int main(int argc, char** argv)
{
if (argc < 2)
{
std::fprintf(stderr,
"usage: %s <bios.bin> [frames]\n"
"env: RETRODE_PS2_EE_TRACE=<path> enable EE fetch trace\n",
argv[0]);
return 2;
}
const char* bios_path = argv[1];
int max_frames = (argc >= 3) ? std::atoi(argv[2]) : 1;
if (max_frames <= 0) max_frames = 1;
constexpr size_t BIOS_SIZE = 4 * 1024 * 1024;
std::vector<uint8_t> bios(BIOS_SIZE, 0);
std::ifstream f(bios_path, std::ios::binary);
if (!f)
{
std::fprintf(stderr, "[trace_runner] cannot open %s\n", bios_path);
return 2;
}
f.read(reinterpret_cast<char*>(bios.data()), BIOS_SIZE);
std::fprintf(stderr, "[trace_runner] loaded %zd bytes from %s\n",
f.gcount(), bios_path);
Emulator emu;
emu.reset();
emu.load_BIOS(bios.data());
emu.set_ee_mode(CPU_MODE::INTERPRETER);
emu.set_vu0_mode(CPU_MODE::INTERPRETER);
emu.set_vu1_mode(CPU_MODE::INTERPRETER);
for (int i = 0; i < max_frames; i++)
{
std::fprintf(stderr, "[trace_runner] running frame %d/%d\n",
i + 1, max_frames);
emu.run();
}
std::fprintf(stderr, "[trace_runner] done\n");
return 0;
}