First commit

This commit is contained in:
2026-05-21 21:31:17 +02:00
commit 6f14bec123
10 changed files with 2508 additions and 0 deletions
+98
View File
@@ -0,0 +1,98 @@
const Simulator = @This();
const std = @import("std");
const Allocator = std.mem.Allocator;
const Scheduler = @import("scheduler.zig");
const Network = @import("network.zig");
const Node = @import("node.zig");
pub const EntryPoint = Scheduler.EntryPoint;
const SpawnOptions = struct {
stack_size: usize = 64 * 1024,
addresses: []const u32 = &[0]u32 {}, // TODO: How do I make an empty slice?
};
const SpawnError = error {
InvalidCommand,
NoSuchProgram,
} || Allocator.Error || std.process.Environ.CreateMapError;
const ExecutableName = struct {
name : []const u8,
entry: EntryPoint,
};
gpa: Allocator,
scheduler: Scheduler,
network: Network,
nodes: std.ArrayList(*Node),
executables: std.ArrayList(ExecutableName),
real_io: std.Io,
pub fn init(self: *Simulator, gpa: Allocator, real_io: std.Io) void {
self.gpa = gpa;
self.scheduler.init(gpa);
self.network.init(gpa);
self.nodes = .empty;
self.executables = .empty;
self.real_io = real_io;
}
pub fn deinit(self: *Simulator) void {
for (self.nodes.items) |node| {
node.deinit();
self.gpa.destroy(node);
}
self.executables.deinit(self.gpa);
self.nodes.deinit(self.gpa);
self.network.deinit();
self.scheduler.deinit();
}
pub fn addExecutable(self: *Simulator, name: []const u8, entry: EntryPoint) Allocator.Error!void {
try self.executables.append(self.gpa, ExecutableName {
.name = name,
.entry = entry,
});
}
pub fn spawn(self: *Simulator, command: []const u8, options: SpawnOptions) SpawnError!void {
const name = extractProgramNameFromCommand(command) orelse return SpawnError.InvalidCommand;
const entry = self.getExecutableEntryPoint(name) orelse return SpawnError.NoSuchProgram;
const node = try self.gpa.create(Node);
errdefer self.gpa.destroy(node);
try node.init(self.real_io, &self.scheduler, &self.network, command, options.addresses, self.gpa);
try self.nodes.append(self.gpa, node);
errdefer _ = self.nodes.swapRemove(self.nodes.items.len-1);
try self.scheduler.spawn(node, entry, options.stack_size);
}
pub fn scheduleOne(self: *Simulator) bool {
return self.scheduler.scheduleOne();
}
// Reads the first word of a command
// "program arg1 arg2 arg3" -> "program"
fn extractProgramNameFromCommand(command: []const u8) ?[]const u8 {
var cur: usize = 0;
while (cur < command.len and command[cur] != ' ')
cur += 1;
if (cur == 0)
return null;
return command[0..cur];
}
fn getExecutableEntryPoint(self: *Simulator, name: []const u8) ?EntryPoint {
for (self.executables.items) |executable| {
if (std.mem.eql(u8, executable.name, name))
return executable.entry;
}
return null;
}