feat: implement Coprocessor Interface
This commit is contained in:
241
src/lib.zig
241
src/lib.zig
@@ -32,6 +32,38 @@ pub const Interpreter = union(enum) {
|
||||
}
|
||||
};
|
||||
|
||||
test "create ARMv4T interface" {
|
||||
var bus_impl = ExampleBus{};
|
||||
var scheduler_impl = ExampleScheduler{};
|
||||
|
||||
const bus_interface = Bus.init(&bus_impl);
|
||||
const scheduler_interface = Scheduler.init(&scheduler_impl);
|
||||
|
||||
var arm7tdmi = Arm7tdmi.init(scheduler_interface, bus_interface);
|
||||
var icpu = arm7tdmi.interface();
|
||||
|
||||
icpu.reset();
|
||||
icpu.step();
|
||||
// TODO: call icpu.panic()
|
||||
}
|
||||
|
||||
test "create ARMv5TE interface" {
|
||||
var bus_impl = ExampleBus{};
|
||||
var scheduler_impl = ExampleScheduler{};
|
||||
var cop_impl = ExampleCoprocessor{};
|
||||
|
||||
const bus_interface = Bus.init(&bus_impl);
|
||||
const scheduler_interface = Scheduler.init(&scheduler_impl);
|
||||
const coprocessor_interface = Coprocessor.init(&cop_impl);
|
||||
|
||||
var arm946es = Arm946es.init(scheduler_interface, bus_interface, coprocessor_interface);
|
||||
var icpu = arm946es.interface();
|
||||
|
||||
icpu.reset();
|
||||
icpu.step();
|
||||
// TODO: call icpu.panic();
|
||||
}
|
||||
|
||||
pub const Bus = struct {
|
||||
ptr: *anyopaque,
|
||||
vtable: *const Vtable,
|
||||
@@ -196,6 +228,118 @@ pub const Bus = struct {
|
||||
}
|
||||
};
|
||||
|
||||
test "create Bus" {
|
||||
var bus_impl = ExampleBus{};
|
||||
const iface = Bus.init(&bus_impl);
|
||||
_ = iface;
|
||||
}
|
||||
|
||||
test "call Bus reads" {
|
||||
var bus_impl = ExampleBus{};
|
||||
const iface = Bus.init(&bus_impl);
|
||||
|
||||
_ = iface.read(u32, 0x0000_0000);
|
||||
_ = iface.read(u16, 0x0000_0000);
|
||||
_ = iface.read(u8, 0x0000_0000);
|
||||
|
||||
_ = iface.dbgRead(u32, 0x0000_0000);
|
||||
_ = iface.dbgRead(u16, 0x0000_0000);
|
||||
_ = iface.dbgRead(u8, 0x0000_0000);
|
||||
}
|
||||
|
||||
test "call Bus writes" {
|
||||
var bus_impl = ExampleBus{};
|
||||
const iface = Bus.init(&bus_impl);
|
||||
|
||||
_ = iface.write(u32, 0x0000_0000, 0x0000_0000);
|
||||
_ = iface.write(u16, 0x0000_0000, 0x0000);
|
||||
_ = iface.write(u8, 0x0000_0000, 0x00);
|
||||
|
||||
_ = iface.dbgWrite(u32, 0x0000_0000, 0x0000_0000);
|
||||
_ = iface.dbgWrite(u16, 0x0000_0000, 0x0000);
|
||||
_ = iface.dbgWrite(u8, 0x0000_0000, 0x00);
|
||||
}
|
||||
|
||||
pub const Coprocessor = struct {
|
||||
ptr: *anyopaque,
|
||||
|
||||
// VTable
|
||||
readFn: *const fn (ptr: *anyopaque, op1: u3, cn: u4, cm: u4, op2: u3) u32,
|
||||
writeFn: *const fn (ptr: *anyopaque, op1: u3, cn: u4, cm: u4, op2: u3, value: u32) void,
|
||||
resetFn: *const fn (ptr: *anyopaque) void,
|
||||
|
||||
pub fn init(obj: anytype) @This() {
|
||||
const P = @TypeOf(obj);
|
||||
const info = @typeInfo(P);
|
||||
|
||||
std.debug.assert(info == .Pointer); // `anytype` is a Pointer
|
||||
std.debug.assert(info.Pointer.size == .One); // Single-Item Pointer
|
||||
std.debug.assert(@typeInfo(info.Pointer.child) == .Struct); // Pointer Child is a `struct`
|
||||
|
||||
const impl = struct {
|
||||
fn read(ptr: *anyopaque, op1: u3, cn: u4, cm: u4, op2: u3) u32 {
|
||||
const self: P = @ptrCast(@alignCast(ptr));
|
||||
return self.read(op1, cn, cm, op2);
|
||||
}
|
||||
|
||||
fn write(ptr: *anyopaque, op1: u3, cn: u4, cm: u4, op2: u3, value: u32) void {
|
||||
const self: P = @ptrCast(@alignCast(ptr));
|
||||
return self.write(op1, cn, cm, op2, value);
|
||||
}
|
||||
|
||||
fn reset(ptr: *anyopaque) void {
|
||||
const self: P = @ptrCast(@alignCast(ptr));
|
||||
return self.reset();
|
||||
}
|
||||
};
|
||||
|
||||
return .{
|
||||
.ptr = obj,
|
||||
.readFn = impl.read,
|
||||
.writeFn = impl.write,
|
||||
.resetFn = impl.reset,
|
||||
};
|
||||
}
|
||||
|
||||
pub fn read(self: @This(), op1: u3, cn: u4, cm: u4, op2: u3) u32 {
|
||||
return self.readFn(self.ptr, op1, cn, cm, op2);
|
||||
}
|
||||
|
||||
pub fn write(self: @This(), op1: u3, cn: u4, cm: u4, op2: u3, value: u32) void {
|
||||
return self.writeFn(self.ptr, op1, cn, cm, op2, value);
|
||||
}
|
||||
|
||||
pub fn reset(self: @This()) void {
|
||||
return self.resetFn(self.ptr);
|
||||
}
|
||||
};
|
||||
|
||||
test "create Coprocessor" {
|
||||
var cop_impl = ExampleCoprocessor{};
|
||||
_ = Coprocessor.init(&cop_impl);
|
||||
}
|
||||
|
||||
test "Coprocessor.read" {
|
||||
var cop_impl = ExampleCoprocessor{};
|
||||
const iface = Coprocessor.init(&cop_impl);
|
||||
|
||||
try testing.expectEqual(@as(u32, 0xDEADBEEF), iface.read(0, 0, 0, 0));
|
||||
}
|
||||
|
||||
test "Coprocessor.write" {
|
||||
var cop_impl = ExampleCoprocessor{};
|
||||
const iface = Coprocessor.init(&cop_impl);
|
||||
|
||||
iface.write(0, 0, 0, 0, 0xDEADBEEF);
|
||||
}
|
||||
|
||||
test "Coprocessor.reset" {
|
||||
var cop_impl = ExampleCoprocessor{};
|
||||
const iface = Coprocessor.init(&cop_impl);
|
||||
|
||||
iface.reset();
|
||||
}
|
||||
|
||||
pub const Scheduler = struct {
|
||||
ptr: *anyopaque,
|
||||
|
||||
@@ -235,6 +379,27 @@ pub const Scheduler = struct {
|
||||
}
|
||||
};
|
||||
|
||||
test "create Scheduler" {
|
||||
var scheduler_impl = ExampleScheduler{};
|
||||
const iface = Scheduler.init(&scheduler_impl);
|
||||
_ = iface;
|
||||
}
|
||||
|
||||
test "Scheduler.now()" {
|
||||
var scheduler_impl = ExampleScheduler{};
|
||||
const iface = Scheduler.init(&scheduler_impl);
|
||||
|
||||
try testing.expectEqual(@as(u64, 0), iface.now());
|
||||
}
|
||||
|
||||
test "Scheduler.reset()" {
|
||||
var scheduler_impl = ExampleScheduler{ .tick = std.math.maxInt(u64) };
|
||||
const iface = Scheduler.init(&scheduler_impl);
|
||||
iface.reset();
|
||||
|
||||
try testing.expectEqual(@as(u64, 0), scheduler_impl.tick);
|
||||
}
|
||||
|
||||
// ---
|
||||
// TESTING
|
||||
// ---
|
||||
@@ -282,61 +447,27 @@ const ExampleScheduler = struct {
|
||||
}
|
||||
};
|
||||
|
||||
test "create IBus" {
|
||||
var bus_impl = ExampleBus{};
|
||||
const iface = Bus.init(&bus_impl);
|
||||
_ = iface;
|
||||
}
|
||||
const ExampleCoprocessor = struct {
|
||||
pub fn read(self: *@This(), op1: u3, cn: u4, cm: u4, op2: u3) u32 {
|
||||
_ = op2;
|
||||
_ = cm;
|
||||
_ = cn;
|
||||
_ = op1;
|
||||
_ = self;
|
||||
|
||||
test "call IBus reads" {
|
||||
var bus_impl = ExampleBus{};
|
||||
const iface = Bus.init(&bus_impl);
|
||||
return 0xDEADBEEF;
|
||||
}
|
||||
|
||||
_ = iface.read(u32, 0x0000_0000);
|
||||
_ = iface.read(u16, 0x0000_0000);
|
||||
_ = iface.read(u8, 0x0000_0000);
|
||||
pub fn write(self: *@This(), op1: u3, cn: u4, cm: u4, op2: u3, value: u32) void {
|
||||
_ = value;
|
||||
_ = op2;
|
||||
_ = cm;
|
||||
_ = cn;
|
||||
_ = op1;
|
||||
_ = self;
|
||||
}
|
||||
|
||||
_ = iface.dbgRead(u32, 0x0000_0000);
|
||||
_ = iface.dbgRead(u16, 0x0000_0000);
|
||||
_ = iface.dbgRead(u8, 0x0000_0000);
|
||||
}
|
||||
|
||||
test "call IBus writes" {
|
||||
var bus_impl = ExampleBus{};
|
||||
const iface = Bus.init(&bus_impl);
|
||||
|
||||
_ = iface.write(u32, 0x0000_0000, 0x0000_0000);
|
||||
_ = iface.write(u16, 0x0000_0000, 0x0000);
|
||||
_ = iface.write(u8, 0x0000_0000, 0x00);
|
||||
|
||||
_ = iface.dbgWrite(u32, 0x0000_0000, 0x0000_0000);
|
||||
_ = iface.dbgWrite(u16, 0x0000_0000, 0x0000);
|
||||
_ = iface.dbgWrite(u8, 0x0000_0000, 0x00);
|
||||
}
|
||||
|
||||
test "create ARMv4T interface" {
|
||||
var bus_impl = ExampleBus{};
|
||||
var scheduler_impl = ExampleScheduler{};
|
||||
|
||||
const bus_interface = Bus.init(&bus_impl);
|
||||
const scheduler_interface = Scheduler.init(&scheduler_impl);
|
||||
|
||||
var arm7tdmi = Arm7tdmi.init(scheduler_interface, bus_interface);
|
||||
var icpu = arm7tdmi.interface();
|
||||
|
||||
icpu.reset();
|
||||
icpu.step();
|
||||
// TODO: call icpu.panic()
|
||||
}
|
||||
|
||||
test "create ARMv5TE interface" {
|
||||
var bus_impl = ExampleBus{};
|
||||
var scheduler_impl = ExampleScheduler{};
|
||||
|
||||
const bus_interface = Bus.init(&bus_impl);
|
||||
const scheduler_interface = Scheduler.init(&scheduler_impl);
|
||||
|
||||
var arm946es = Arm946es.init(scheduler_interface, bus_interface);
|
||||
|
||||
_ = arm946es.interface();
|
||||
}
|
||||
pub fn reset(self: *@This()) void {
|
||||
self.* = .{};
|
||||
}
|
||||
};
|
||||
|
Reference in New Issue
Block a user