A cross-platform simulator for the GreenArrays GA144 multi-computer chip.
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

update to zig 0.16.0-dev for fun

+168 -130
+1 -1
.github/workflows/main.yml
··· 44 44 45 45 - uses: mlugg/setup-zig@v2 46 46 with: 47 - version: "0.14.0" 47 + version: "0.16.0-dev.2905+5d71e3051" 48 48 49 49 - run: zig env 50 50
+19 -13
README.md
··· 4 4 Inc.](https://www.greenarraychips.com) [GA144 multi-computer 5 5 chip](https://www.greenarraychips.com/home/documents/index.php#GA144). 6 6 7 - ## Building 8 - 9 - To build `gasim`, [zig 0.14.0](https://ziglang.org/download/) is required. 10 - 11 - ```bash 12 - zig build -Doptimize=ReleaseFast 13 - ``` 14 - 15 - `gasim` executable will be available in `./zig-out/bin/gasim`. 16 - 17 7 ## Usage 18 8 19 9 ```bash ··· 24 14 with the contents of the provided binary file. 25 15 26 16 The expected file format is 288 8-bit bytes, with the first 144 bytes 27 - containing the RAM contents and the next 144 bytes containing the ROM contents. 17 + containing the RAM contents and the next 144 bytes containing the ROM. 18 + 19 + ## Download 20 + 21 + [Download](https://sadbeast.com/gasim/download.html) a static binary for your operating system. 22 + 23 + If you have Nix installed, try `nix run github:coat/gasim#`. 24 + 25 + ## Building 26 + 27 + To build `gasim`, [zig 0.16.0-dev](https://ziglang.org/download/) is required. 28 + 29 + ```bash 30 + zig build -Doptimize=ReleaseFast 31 + ``` 32 + 33 + `gasim` will be available in `./zig-out/bin/gasim`. 28 34 29 35 ### TODO 30 36 ··· 33 39 34 40 ## Prior Art 35 41 36 - - GreenArrays own SOFTSIM available in their free [arrayForth 42 + - GreenArrays' own SOFTSIM available in their free [arrayForth 37 43 distribution](https://www.greenarraychips.com/home/support/download-03d.php). 38 44 Works well under wine. 39 45 - [AshleyF/Color](https://github.com/AshleyF/Color) - A colorForth editor, ··· 47 53 series](https://github.com/AshleyF/Color/blob/master/Docs/chuck_moores_creations.md) 48 54 by [AshleyF](https://github.com/AshleyF) that introduces the F18 architecture 49 55 and instruction set. 50 - - GreenArrays own concise, but very informative 56 + - GreenArrays' own concise, but very informative 51 57 [documentation](https://www.greenarraychips.com/home/documents/index.php) on 52 58 the GA144 chip and F18 architecture. 53 59 - [colorForth instruction
+48 -15
build.zig
··· 6 6 7 7 const coverage = b.option(bool, "coverage", "Generate a coverage report with kcov") orelse false; 8 8 9 - const exe_mod = b.createModule(.{ 10 - .root_source_file = b.path("src/main.zig"), 9 + // const zul_mod = b.dependency("zul", .{ 10 + // .target = target, 11 + // .optimize = optimize, 12 + // }).module("zul"); 13 + // 14 + // const vaxis_mod = b.dependency("vaxis", .{ 15 + // .target = target, 16 + // .optimize = optimize, 17 + // }).module("vaxis"); 18 + 19 + const mod = b.addModule("gasim", .{ 20 + .root_source_file = b.path("src/root.zig"), 11 21 .target = target, 12 - .optimize = optimize, 13 22 }); 14 23 15 24 const exe = b.addExecutable(.{ 16 25 .name = "gasim", 17 - .root_module = exe_mod, 26 + .root_module = b.createModule(.{ 27 + .root_source_file = b.path("src/main.zig"), 28 + .target = target, 29 + .optimize = optimize, 30 + .imports = &.{ 31 + .{ .name = "gasim", .module = mod }, 32 + }, 33 + }), 18 34 }); 19 35 20 36 b.installArtifact(exe); ··· 30 46 const run_step = b.step("run", "Run gasim"); 31 47 run_step.dependOn(&run_cmd.step); 32 48 33 - const exe_unit_tests = b.addTest(.{ 34 - .root_module = exe_mod, 49 + const mod_tests = b.addTest(.{ 50 + .root_module = mod, 51 + .use_llvm = coverage, 52 + }); 53 + 54 + const run_mod_tests = b.addRunArtifact(mod_tests); 55 + 56 + const exe_tests = b.addTest(.{ 57 + .root_module = exe.root_module, 58 + .use_llvm = coverage, 35 59 }); 36 60 37 - const run_tests = b.addRunArtifact(exe_unit_tests); 61 + const run_exe_tests = b.addRunArtifact(exe_tests); 38 62 39 63 const test_step = b.step("test", "Run unit tests"); 40 - test_step.dependOn(&run_tests.step); 64 + test_step.dependOn(&run_mod_tests.step); 65 + test_step.dependOn(&run_exe_tests.step); 41 66 42 67 if (coverage) { 68 + var run_test_steps: std.ArrayList(*std.Build.Step.Run) = .empty; 69 + run_test_steps.append(b.allocator, run_mod_tests) catch @panic("OOM"); 70 + run_test_steps.append(b.allocator, run_exe_tests) catch @panic("OOM"); 71 + 43 72 const kcov_bin = b.findProgram(&.{"kcov"}, &.{}) catch "kcov"; 73 + 44 74 const merge_step = std.Build.Step.Run.create(b, "merge coverage"); 45 75 merge_step.addArgs(&.{ kcov_bin, "--merge" }); 46 76 merge_step.rename_step_with_output_arg = false; 47 77 const merged_coverage_output = merge_step.addOutputFileArg("."); 48 78 49 - run_tests.setName(b.fmt("{s} (collect coverage)", .{run_tests.step.name})); 50 - // prepend the kcov exec args 51 - const argv = run_tests.argv.toOwnedSlice(b.allocator) catch @panic("OOM"); 52 - run_tests.addArgs(&.{ kcov_bin, "--collect-only" }); 53 - run_tests.addPrefixedDirectoryArg("--include-pattern=", b.path("src")); 54 - merge_step.addDirectoryArg(run_tests.addOutputFileArg(run_tests.producer.?.name)); 55 - run_tests.argv.appendSlice(b.allocator, argv) catch @panic("OOM"); 79 + for (run_test_steps.items) |step| { 80 + step.setName(b.fmt("{s} (collect coverage)", .{step.step.name})); 81 + 82 + // prepend the kcov exec args 83 + const argv = step.argv.toOwnedSlice(b.allocator) catch @panic("OOM"); 84 + step.addArgs(&.{ kcov_bin, "--collect-only" }); 85 + step.addPrefixedDirectoryArg("--include-pattern=", b.path("src")); 86 + merge_step.addDirectoryArg(step.addOutputFileArg(step.producer.?.name)); 87 + step.argv.appendSlice(b.allocator, argv) catch @panic("OOM"); 88 + } 56 89 57 90 const install_coverage = b.addInstallDirectory(.{ 58 91 .source_dir = merged_coverage_output,
+1 -1
build.zig.zon
··· 5 5 6 6 .fingerprint = 0xbf21d72499244c75, // Changing this has security and trust implications. 7 7 8 - .minimum_zig_version = "0.14.0", 8 + .minimum_zig_version = "0.16.0-dev.2905+5d71e3051", 9 9 10 10 .dependencies = .{}, 11 11
+24 -49
flake.lock
··· 16 16 "type": "github" 17 17 } 18 18 }, 19 - "flake-utils": { 20 - "inputs": { 21 - "systems": "systems" 22 - }, 19 + "nixpkgs": { 23 20 "locked": { 24 - "lastModified": 1705309234, 25 - "narHash": "sha256-uNRRNRKmJyCRC/8y1RqBkqWBLM034y4qN7EprSdmgyA=", 26 - "owner": "numtide", 27 - "repo": "flake-utils", 28 - "rev": "1ef2e671c3b0c19053962c07dbda38332dcebf26", 21 + "lastModified": 1773524153, 22 + "narHash": "sha256-Jms57zzlFf64ayKzzBWSE2SGvJmK+NGt8Gli71d9kmY=", 23 + "owner": "NixOS", 24 + "repo": "nixpkgs", 25 + "rev": "e9f278faa1d0c2fc835bd331d4666b59b505a410", 29 26 "type": "github" 30 27 }, 31 28 "original": { 32 - "owner": "numtide", 33 - "repo": "flake-utils", 34 - "type": "github" 29 + "id": "nixpkgs", 30 + "ref": "nixos-25.11", 31 + "type": "indirect" 35 32 } 36 33 }, 37 - "gitignore": { 38 - "inputs": { 39 - "nixpkgs": [ 40 - "nixpkgs" 41 - ] 42 - }, 34 + "nixpkgs_2": { 43 35 "locked": { 44 - "lastModified": 1709087332, 45 - "narHash": "sha256-HG2cCnktfHsKV0s4XW83gU3F57gaTljL9KNSuG6bnQs=", 46 - "owner": "hercules-ci", 47 - "repo": "gitignore.nix", 48 - "rev": "637db329424fd7e46cf4185293b9cc8c88c95394", 49 - "type": "github" 50 - }, 51 - "original": { 52 - "owner": "hercules-ci", 53 - "repo": "gitignore.nix", 54 - "type": "github" 55 - } 56 - }, 57 - "nixpkgs": { 58 - "locked": { 59 - "lastModified": 1742596159, 60 - "narHash": "sha256-SH9ein8zlFHD1xk/se3OXE3ZuxGHNyY8DlVb0fFj/bg=", 61 - "owner": "nixos", 36 + "lastModified": 1771043024, 37 + "narHash": "sha256-O1XDr7EWbRp+kHrNNgLWgIrB0/US5wvw9K6RERWAj6I=", 38 + "owner": "NixOS", 62 39 "repo": "nixpkgs", 63 - "rev": "904178ac5c12ff07a359fbb20453a977f0b7effd", 40 + "rev": "3aadb7ca9eac2891d52a9dec199d9580a6e2bf44", 64 41 "type": "github" 65 42 }, 66 43 "original": { 67 - "owner": "nixos", 68 - "ref": "release-24.11", 44 + "owner": "NixOS", 45 + "ref": "nixos-25.11", 69 46 "repo": "nixpkgs", 70 47 "type": "github" 71 48 } 72 49 }, 73 50 "root": { 74 51 "inputs": { 75 - "gitignore": "gitignore", 76 52 "nixpkgs": "nixpkgs", 77 - "zig-overlay": "zig-overlay" 53 + "zig": "zig" 78 54 } 79 55 }, 80 56 "systems": { 57 + "flake": false, 81 58 "locked": { 82 59 "lastModified": 1681028828, 83 60 "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", ··· 92 69 "type": "github" 93 70 } 94 71 }, 95 - "zig-overlay": { 72 + "zig": { 96 73 "inputs": { 97 74 "flake-compat": "flake-compat", 98 - "flake-utils": "flake-utils", 99 - "nixpkgs": [ 100 - "nixpkgs" 101 - ] 75 + "nixpkgs": "nixpkgs_2", 76 + "systems": "systems" 102 77 }, 103 78 "locked": { 104 - "lastModified": 1742559123, 105 - "narHash": "sha256-hIODf8UGo/fbK5LDx+Ese4Jt9n5FZjwZvYCM70HtO8A=", 79 + "lastModified": 1773535989, 80 + "narHash": "sha256-4QrOLlcnYK9nOasE2iZ2ZfoyedB5IUVciX8SWFDGHqM=", 106 81 "owner": "mitchellh", 107 82 "repo": "zig-overlay", 108 - "rev": "bd5dc568a93b43b78aadb11a3a585c6e30333199", 83 + "rev": "6e337a61797e7e56ad21443fc67b950aa857bc5e", 109 84 "type": "github" 110 85 }, 111 86 "original": {
+16 -44
flake.nix
··· 1 1 { 2 2 description = "A simulator for the GA144 multi-computer"; 3 3 4 - inputs = { 5 - # We want to stay as up to date as possible but need to be careful that the 6 - # glibc versions used by our dependencies from Nix are compatible with the 7 - # system glibc that the user is building for. 8 - nixpkgs.url = "github:nixos/nixpkgs/release-24.11"; 9 - 10 - zig-overlay.url = "github:mitchellh/zig-overlay"; 11 - zig-overlay.inputs.nixpkgs.follows = "nixpkgs"; 12 - 13 - gitignore.url = "github:hercules-ci/gitignore.nix"; 14 - gitignore.inputs.nixpkgs.follows = "nixpkgs"; 15 - }; 4 + inputs.nixpkgs.url = "nixpkgs/nixos-25.11"; 5 + inputs.zig.url = "github:mitchellh/zig-overlay"; 16 6 17 7 outputs = { 18 8 nixpkgs, 19 - zig-overlay, 20 - gitignore, 9 + zig, 21 10 ... 22 - }: 11 + }: let 12 + systems = ["x86_64-linux" "aarch64-linux" "x86_64-darwin" "aarch64-darwin"]; 13 + in 23 14 builtins.foldl' nixpkgs.lib.recursiveUpdate {} ( 24 15 builtins.map ( 25 16 system: let 26 - pkgs = nixpkgs.legacyPackages.${system}; 27 - zig = zig-overlay.packages.${system}."0.14.0"; 28 - gitignoreSource = gitignore.lib.gitignoreSource; 29 - target = builtins.replaceStrings ["darwin"] ["macos"] system; 17 + pkgs = import nixpkgs { 18 + inherit system; 19 + overlays = [zig.overlays.default]; 20 + }; 30 21 in { 31 22 devShells.${system}.default = pkgs.mkShell { 32 - nativeBuildInputs = with pkgs; 23 + packages = with pkgs; 33 24 [ 34 - zig 25 + zigpkgs.master 35 26 ] 36 - ++ (pkgs.lib.optionals pkgs.stdenv.isLinux [kcov]); 27 + ++ (pkgs.lib.optionals pkgs.stdenv.isLinux [elfkickers kcov]); 37 28 }; 38 29 39 30 formatter.${system} = pkgs.alejandra; 40 31 41 - packages.${system} = rec { 42 - default = gasim; 43 - gasim = pkgs.stdenvNoCC.mkDerivation { 44 - name = "gasim"; 45 - version = "0.1.0"; 46 - meta.mainProgram = "gasim"; 47 - src = gitignoreSource ./.; 48 - nativeBuildInputs = [zig]; 49 - dontConfigure = true; 50 - dontInstall = true; 51 - doCheck = true; 52 - buildPhase = '' 53 - NO_COLOR=1 # prevent escape codes from messing up the `nix log` 54 - zig build install --global-cache-dir $(pwd)/.cache -Dtarget=${target} -Doptimize=ReleaseSafe --prefix $out 55 - ''; 56 - checkPhase = '' 57 - zig build test --global-cache-dir $(pwd)/.cache -Dtarget=${target} 58 - ''; 59 - }; 60 - }; 32 + packages.${system}.default = pkgs.callPackage ./package.nix {zig = pkgs.zigpkgs.master;}; 61 33 } 62 - # Our supported systems are the same supported systems as the Zig binaries. 63 - ) (builtins.attrNames zig-overlay.packages) 34 + ) 35 + systems 64 36 ); 65 37 }
+28
package.nix
··· 1 + { 2 + lib, 3 + stdenv, 4 + elfkickers, 5 + zig, 6 + }: 7 + stdenv.mkDerivation ( 8 + finalAttrs: { 9 + name = "gasim"; 10 + version = "0.0.1"; 11 + src = lib.cleanSource ./.; 12 + nativeBuildInputs = 13 + [ 14 + zig.hook 15 + ] 16 + ++ lib.optionals stdenv.hostPlatform.isLinux [elfkickers]; 17 + 18 + zigBuildFlags = [ 19 + "-Doptimize=ReleaseSmall" 20 + "--color off" 21 + ]; 22 + 23 + meta = { 24 + mainProgram = finalAttrs.name; 25 + license = lib.licenses.mit; 26 + }; 27 + } 28 + )
+19 -5
src/main.zig
··· 1 1 //! gasim 2 2 3 - pub fn main() !void {} 3 + const log = std.log.scoped(.main); 4 4 5 - test { 6 - _ = @import("f18.zig"); 7 - _ = @import("opcodes.zig"); 8 - _ = @import("stack.zig"); 5 + pub fn main(init: std.process.Init) !void { 6 + var node: Computer = .reset; 7 + for (0..1024) |_| node.step(); 8 + 9 + const io = init.io; 10 + 11 + var stdout_buffer: [1024]u8 = undefined; 12 + var stdout_file_writer: Io.File.Writer = .init(.stdout(), io, &stdout_buffer); 13 + const stdout_writer = &stdout_file_writer.interface; 14 + 15 + try stdout_writer.print("Total simulated time: {d}us\n", .{node.execution_time}); 16 + 17 + try stdout_writer.flush(); // Don't forget to flush! 9 18 } 19 + 20 + const std = @import("std"); 21 + const Io = std.Io; 22 + 23 + const Computer = @import("gasim").Computer;
+10
src/root.zig
··· 1 + pub const Address = f18.Address; 2 + pub const Computer = f18.Computer; 3 + pub const Word = f18.Word; 4 + 5 + const f18 = @import("f18.zig"); 6 + 7 + test { 8 + _ = @import("opcodes.zig"); 9 + _ = @import("stack.zig"); 10 + }
+2 -2
src/stack.zig
··· 21 21 return old_t; 22 22 } 23 23 24 - pub const empty: @This() = .{ 24 + pub const empty: DataStack = .{ 25 25 .stack = @splat(0), 26 26 .index = 0, 27 27 .t = 0, ··· 49 49 return old_t; 50 50 } 51 51 52 - pub const empty: @This() = .{ 52 + pub const empty: ReturnStack = .{ 53 53 .stack = @splat(0), 54 54 .index = 0, 55 55 .t = 0,