summaryrefslogtreecommitdiff
path: root/test
diff options
context:
space:
mode:
Diffstat (limited to 'test')
-rw-r--r--test/anc/v1/1rops.asm109
-rw-r--r--test/anc/v1/2rops.asm26
-rw-r--r--test/anc/v1/3rops.asm70
-rw-r--r--test/anc/v1/addrs.asm75
-rw-r--r--test/anc/v1/allos.asm33
-rw-r--r--test/anc/v1/ifnzs.asm50
-rw-r--r--test/anc/v1/ioops.asm104
-rw-r--r--test/anc/v1/jumps.asm56
-rw-r--r--test/anc/v1/mbops.asm17
-rw-r--r--test/anc/v1/noops.asm42
-rw-r--r--test/anc/v1/stack.asm51
-rw-r--r--test/test_build.py114
-rw-r--r--test/test_determinism.py50
-rw-r--r--test/test_general.py58
-rw-r--r--test/test_run.py59
-rw-r--r--test/test_v1.py51
-rw-r--r--test/ui/asa4/links.json1
-rw-r--r--test/ui/asa4/ui.c29
-rw-r--r--test/ui/null/links.json1
-rw-r--r--test/ui/null/ui.c24
-rw-r--r--test/ui/push/links.json1
-rw-r--r--test/ui/push/ui.c26
-rw-r--r--test/ui/v1/1rops/links.json1
-rw-r--r--test/ui/v1/1rops/ui.c74
-rw-r--r--test/ui/v1/2rops/links.json1
-rw-r--r--test/ui/v1/2rops/ui.c56
-rw-r--r--test/ui/v1/3rops/links.json1
-rw-r--r--test/ui/v1/3rops/ui.c65
-rw-r--r--test/ui/v1/addrs/links.json1
-rw-r--r--test/ui/v1/addrs/ui.c58
-rw-r--r--test/ui/v1/allos/links.json1
-rw-r--r--test/ui/v1/allos/ui.c80
-rw-r--r--test/ui/v1/ifnzs/links.json1
-rw-r--r--test/ui/v1/ifnzs/ui.c56
-rw-r--r--test/ui/v1/ioops/links.json1
-rw-r--r--test/ui/v1/ioops/ui.c66
-rw-r--r--test/ui/v1/jumps/links.json1
-rw-r--r--test/ui/v1/jumps/ui.c31
-rw-r--r--test/ui/v1/mbops/links.json1
-rw-r--r--test/ui/v1/mbops/ui.c46
-rw-r--r--test/ui/v1/noops/links.json1
-rw-r--r--test/ui/v1/noops/ui.c136
-rw-r--r--test/ui/v1/stack/links.json1
-rw-r--r--test/ui/v1/stack/ui.c85
44 files changed, 1811 insertions, 0 deletions
diff --git a/test/anc/v1/1rops.asm b/test/anc/v1/1rops.asm
new file mode 100644
index 0000000..6ab33a9
--- /dev/null
+++ b/test/anc/v1/1rops.asm
@@ -0,0 +1,109 @@
+; file : test/anc/v1/1rops.asm
+; project : Salis-VM
+; author : Paul Oliver <contact@pauloliver.dev>
+
+incn
+incn
+nop0
+incn
+nop1
+nop2
+incn
+nop2
+nop3
+nop0
+incn
+nop3
+
+noop
+
+decn
+decn
+nop0
+decn
+nop1
+nop2
+decn
+nop2
+nop3
+nop0
+decn
+nop3
+
+noop
+
+incn
+incn
+incn
+notn
+notn
+nop0
+notn
+nop1
+nop2
+notn
+nop2
+nop3
+nop0
+notn
+nop3
+
+noop
+
+shfl
+shfl
+nop0
+shfl
+nop1
+nop2
+shfl
+nop2
+nop3
+nop0
+shfl
+nop3
+
+noop
+
+shfr
+shfr
+nop0
+shfr
+nop1
+nop2
+shfr
+nop2
+nop3
+nop0
+shfr
+nop3
+
+noop
+
+zero
+zero
+nop0
+zero
+nop1
+nop2
+zero
+nop2
+nop3
+nop0
+zero
+nop3
+
+noop
+
+unit
+unit
+nop0
+unit
+nop1
+nop2
+unit
+nop2
+nop3
+nop0
+unit
+nop3
diff --git a/test/anc/v1/2rops.asm b/test/anc/v1/2rops.asm
new file mode 100644
index 0000000..c1021d9
--- /dev/null
+++ b/test/anc/v1/2rops.asm
@@ -0,0 +1,26 @@
+; file : test/anc/v1/2rops.asm
+; project : Salis-VM
+; author : Paul Oliver <contact@pauloliver.dev>
+
+incn
+incn
+incn
+
+noop
+
+rdup
+nop0
+nop1
+rdup
+nop2
+rdup
+nop1
+nop3
+
+noop
+
+rswp
+nop1
+rswp
+nop3
+nop2
diff --git a/test/anc/v1/3rops.asm b/test/anc/v1/3rops.asm
new file mode 100644
index 0000000..84c6596
--- /dev/null
+++ b/test/anc/v1/3rops.asm
@@ -0,0 +1,70 @@
+; file : test/anc/v1/3rops.asm
+; project : Salis-VM
+; author : Paul Oliver <contact@pauloliver.dev>
+
+incn
+addn
+addn
+nop0
+addn
+nop1
+nop0
+addn
+nop2
+nop1
+nop0
+addn
+nop3
+nop2
+nop1
+
+noop
+
+subn
+nop3
+nop2
+nop1
+subn
+nop3
+nop2
+subn
+nop3
+subn
+nop1
+nop2
+subn
+
+noop
+
+incn
+incn
+muln
+muln
+nop0
+muln
+nop1
+nop0
+muln
+nop2
+nop1
+nop0
+muln
+nop3
+nop2
+nop1
+
+noop
+
+divn
+nop3
+nop2
+nop1
+divn
+nop3
+nop2
+divn
+nop3
+divn
+nop1
+nop2
+divn
diff --git a/test/anc/v1/addrs.asm b/test/anc/v1/addrs.asm
new file mode 100644
index 0000000..b67532e
--- /dev/null
+++ b/test/anc/v1/addrs.asm
@@ -0,0 +1,75 @@
+; file : test/anc/v1/addrs.asm
+; project : Salis-VM
+; author : Paul Oliver <contact@pauloliver.dev>
+
+lokb
+lokd
+lokf
+lokh
+lokj
+lokl
+lokn
+lokp
+
+noop
+noop
+
+adrf
+keya
+adrb
+keyb
+nop1
+adrf
+keyc
+nop2
+adrb
+keyd
+nop3
+adrf
+keye
+nop0
+adrb
+keyf
+nop1
+adrf
+keyg
+nop2
+adrb
+keyh
+nop3
+adrf
+keyi
+nop0
+adrb
+keyj
+nop1
+adrf
+keyk
+nop2
+adrb
+keyl
+nop3
+adrf
+keym
+nop0
+adrb
+keyn
+nop1
+adrf
+keyo
+nop2
+adrb
+keyp
+nop3
+
+noop
+noop
+
+loka
+lokc
+loke
+lokg
+loki
+lokk
+lokm
+loko
diff --git a/test/anc/v1/allos.asm b/test/anc/v1/allos.asm
new file mode 100644
index 0000000..37f8540
--- /dev/null
+++ b/test/anc/v1/allos.asm
@@ -0,0 +1,33 @@
+; file : test/anc/v1/allos.asm
+; project : Salis-VM
+; author : Paul Oliver <contact@pauloliver.dev>
+
+incn
+shfl
+shfl
+
+malf
+nop0
+nop1
+malf
+malb
+bspl
+bspl
+bspl
+
+malf
+nop0
+nop1
+malb
+malf
+bswp
+bclr
+
+noop
+noop
+noop
+
+malb
+nop0
+nop1
+bspl
diff --git a/test/anc/v1/ifnzs.asm b/test/anc/v1/ifnzs.asm
new file mode 100644
index 0000000..86899b0
--- /dev/null
+++ b/test/anc/v1/ifnzs.asm
@@ -0,0 +1,50 @@
+; file : test/anc/v1/ifnzs.asm
+; project : Salis-VM
+; author : Paul Oliver <contact@pauloliver.dev>
+
+ifnz
+incn
+incn
+ifnz
+nop0
+incn
+nop0
+
+noop
+
+ifnz
+nop1
+incn
+nop1
+incn
+nop1
+ifnz
+nop1
+incn
+nop1
+
+noop
+
+ifnz
+nop2
+incn
+nop2
+incn
+nop2
+ifnz
+nop2
+incn
+nop2
+
+noop
+
+ifnz
+nop3
+incn
+nop3
+incn
+nop3
+ifnz
+nop3
+incn
+nop3
diff --git a/test/anc/v1/ioops.asm b/test/anc/v1/ioops.asm
new file mode 100644
index 0000000..ca02d57
--- /dev/null
+++ b/test/anc/v1/ioops.asm
@@ -0,0 +1,104 @@
+; file : test/anc/v1/ioops.asm
+; project : Salis-VM
+; author : Paul Oliver <contact@pauloliver.dev>
+
+keya
+lokb
+keyc
+lokd
+keye
+lokf
+keyg
+lokh
+
+noop
+
+incn
+nop1
+incn
+nop2
+incn
+nop2
+incn
+nop3
+incn
+nop3
+incn
+nop3
+rpsh
+rpsh
+nop1
+rpsh
+nop2
+rpsh
+nop3
+
+noop
+
+rloa
+rloa
+nop1
+nop1
+rloa
+nop2
+nop2
+rloa
+nop3
+nop3
+
+rpop
+nop3
+rpop
+nop2
+rpop
+nop1
+rpop
+rpsh
+rpsh
+nop1
+rpsh
+nop2
+rpsh
+nop3
+
+noop
+
+rloa
+nop2
+nop3
+rloa
+nop1
+nop2
+rloa
+nop0
+nop1
+rloa
+
+noop
+
+muln
+nop0
+nop1
+nop2
+muln
+nop1
+nop2
+nop3
+muln
+nop2
+nop3
+zero
+nop3
+
+rwrt
+nop3
+incn
+nop3
+rwrt
+nop3
+nop1
+incn
+nop3
+rwrt
+nop3
+nop2
diff --git a/test/anc/v1/jumps.asm b/test/anc/v1/jumps.asm
new file mode 100644
index 0000000..6cde582
--- /dev/null
+++ b/test/anc/v1/jumps.asm
@@ -0,0 +1,56 @@
+; file : test/anc/v1/jumps.asm
+; project : Salis-VM
+; author : Paul Oliver <contact@pauloliver.dev>
+
+jmpf
+keya
+lokb
+jmpf
+keyc
+lokd
+jmpf
+keye
+lokf
+jmpf
+keyg
+lokh
+jmpf
+keyi
+lokj
+jmpf
+keyk
+lokl
+jmpf
+keym
+lokn
+jmpf
+keyo
+lokp
+
+noop
+noop
+
+loka
+jmpb
+keyb
+lokc
+jmpb
+keyd
+loke
+jmpb
+keyf
+lokg
+jmpb
+keyh
+loki
+jmpb
+keyj
+lokk
+jmpb
+keyl
+lokm
+jmpb
+keyn
+loko
+jmpb
+keyp
diff --git a/test/anc/v1/mbops.asm b/test/anc/v1/mbops.asm
new file mode 100644
index 0000000..b57e88b
--- /dev/null
+++ b/test/anc/v1/mbops.asm
@@ -0,0 +1,17 @@
+; file : test/anc/v1/mbops.asm
+; project : Salis-VM
+; author : Paul Oliver <contact@pauloliver.dev>
+
+incn
+shfl
+shfl
+malf
+
+bswp
+bswp
+bswp
+
+bclr
+
+bswp
+bclr
diff --git a/test/anc/v1/noops.asm b/test/anc/v1/noops.asm
new file mode 100644
index 0000000..e4547c2
--- /dev/null
+++ b/test/anc/v1/noops.asm
@@ -0,0 +1,42 @@
+; file : test/anc/v1/noops.asm
+; project : Salis-VM
+; author : Paul Oliver <contact@pauloliver.dev>
+
+noop
+nop0
+nop1
+nop2
+nop3
+
+keya
+keyb
+keyc
+keyd
+keye
+keyf
+keyg
+keyh
+keyi
+keyj
+keyk
+keyl
+keym
+keyn
+keyo
+keyp
+loka
+lokb
+lokc
+lokd
+loke
+lokf
+lokg
+lokh
+loki
+lokj
+lokk
+lokl
+lokm
+lokn
+loko
+lokp
diff --git a/test/anc/v1/stack.asm b/test/anc/v1/stack.asm
new file mode 100644
index 0000000..bce1a25
--- /dev/null
+++ b/test/anc/v1/stack.asm
@@ -0,0 +1,51 @@
+; file : test/anc/v1/stack.asm
+; project : Salis-VM
+; author : Paul Oliver <contact@pauloliver.dev>
+
+incn
+incn
+nop1
+shfl
+nop1
+incn
+nop2
+shfl
+nop2
+shfl
+nop2
+
+noop
+
+rpsh
+rpsh
+nop1
+rpsh
+nop2
+rpsh
+nop3
+rpsh
+nop0
+rpsh
+nop1
+rpsh
+nop2
+rpsh
+nop3
+
+noop
+
+rpop
+rpop
+nop1
+rpop
+nop2
+rpop
+nop3
+rpop
+nop0
+rpop
+nop1
+rpop
+nop2
+rpop
+nop3
diff --git a/test/test_build.py b/test/test_build.py
new file mode 100644
index 0000000..e13669a
--- /dev/null
+++ b/test/test_build.py
@@ -0,0 +1,114 @@
+# file : test/test_build.py
+# project : Salis-VM
+# author : Paul Oliver <contact@pauloliver.dev>
+
+# index:
+# [section] command lists
+# [section] tests null
+# [section] tests v1
+# [section] tests server & client
+
+import signal
+
+from test_general import SalisTest
+
+class TestBuild(SalisTest):
+ SIM_NAME = "test-build.sim"
+
+ # --------------------------------------------------------------------------
+ # [section] command lists
+ # --------------------------------------------------------------------------
+ def commands_new(self, anc, arch):
+ return [
+ f"./salis.py new -a{anc} -b -f -g{compiler} -H{self.tempdir.name} -n{self.SIM_NAME} {log_trace} {optimized} -s{seed} -u{ui} -v{arch}"
+ for compiler in ["clang", "gcc", "tcc"]
+ for log_trace in ["", "-l"]
+ for optimized in ["", "-o"]
+ for seed in [-1, 0, 1234]
+ for ui in ["curses", "daemon"]
+ ]
+
+ def commands_load(self):
+ return [
+ f"./salis.py load -b -g{compiler} -H{self.tempdir.name} -n{self.SIM_NAME} {log_trace} {optimized} -u{ui}"
+ for compiler in ["clang", "gcc", "tcc"]
+ for log_trace in ["", "-l"]
+ for optimized in ["", "-o"]
+ for ui in ["curses", "daemon"]
+ ]
+
+ def cmds_server(self):
+ return [
+ f"./salis.py server -b -g{compiler} -H{self.tempdir.name} -n{self.SIM_NAME} {optimized}"
+ for compiler in ["clang", "gcc"]
+ for optimized in ["", "-o"]
+ ]
+
+ def cmds_client(self):
+ return [
+ f"./salis.py client -b -g{c_compiler} -G{cpp_compiler} {optimized}"
+ for c_compiler, cpp_compiler in [("clang", "clang++"), ("gcc", "g++")]
+ for optimized in ["", "-o"]
+ ]
+
+ # --------------------------------------------------------------------------
+ # [section] tests null
+ # --------------------------------------------------------------------------
+ def test_null_new(self):
+ for command in self.commands_new("0123", "null"):
+ self.run_subprocess(command)
+ self.assert_files_exist([f"{self.tempdir.name}/{self.SIM_NAME}/opts.json"])
+
+ def test_null_load(self):
+ self.run_subprocess(self.commands_new("0123", "null")[0])
+ self.assert_files_exist([f"{self.tempdir.name}/{self.SIM_NAME}/opts.json"])
+
+ for command in self.commands_load():
+ self.run_subprocess(command)
+ self.assert_files_exist([f"{self.tempdir.name}/{self.SIM_NAME}/opts.json"])
+
+ # --------------------------------------------------------------------------
+ # [section] tests v1
+ # --------------------------------------------------------------------------
+ def test_v1_new(self):
+ for command in self.commands_new("55a", "v1"):
+ self.run_subprocess(command)
+ self.assert_files_exist([f"{self.tempdir.name}/{self.SIM_NAME}/opts.json"])
+
+ def test_v1_load(self):
+ self.run_subprocess(self.commands_new("55a", "v1")[0])
+ self.assert_files_exist([f"{self.tempdir.name}/{self.SIM_NAME}/opts.json"])
+
+ for command in self.commands_load():
+ self.run_subprocess(command)
+ self.assert_files_exist([f"{self.tempdir.name}/{self.SIM_NAME}/opts.json"])
+
+ # --------------------------------------------------------------------------
+ # [section] tests server & client
+ # --------------------------------------------------------------------------
+ def client_test(self):
+ with self.run_pipe(f"./salis.py server -H{self.tempdir.name}") as server_proc:
+ for line in server_proc.stdout:
+ if "Listening..." in line:
+ break
+
+ for cmd in self.cmds_client():
+ self.run_subprocess(cmd)
+
+ server_proc.send_signal(signal.SIGINT)
+
+ def test_server(self):
+ self.run_subprocess(self.commands_new("0123", "null")[0])
+ self.assert_files_exist([f"{self.tempdir.name}/{self.SIM_NAME}/opts.json"])
+
+ for cmd in self.cmds_server():
+ self.run_subprocess(cmd)
+ self.assert_files_exist([f"{self.tempdir.name}/{self.SIM_NAME}/opts.json"])
+
+ def test_client_null(self):
+ self.run_ui_test("0123", "anc", "null", "test/ui", "null")
+ self.client_test()
+
+ def test_client_v1(self):
+ self.run_ui_test("55a", "anc", "null", "test/ui", "v1")
+ self.client_test()
diff --git a/test/test_determinism.py b/test/test_determinism.py
new file mode 100644
index 0000000..0d40fcb
--- /dev/null
+++ b/test/test_determinism.py
@@ -0,0 +1,50 @@
+# file : test/test_determinism.py
+# project : Salis-VM
+# author : Paul Oliver <contact@pauloliver.dev>
+#
+# This test ensures simulator produces deterministic results.
+# Resulting save, eva and DB files must be exactly the same for all simulations,
+# whenever the same seed value is used.
+
+import hashlib
+import os
+
+from test_general import SalisTest
+
+class TestDeterminism(SalisTest):
+ SIM_OPTS = {
+ "anc": "55a",
+ "anc_path": "anc",
+ "name": "determinism.sim",
+ "ui_path": "test/ui",
+ "vm_arch": "v1",
+ }
+
+ SIM_OPTS_ASA4 = SIM_OPTS | {"ui": "asa4"}
+ SIM_OPTS_PUSH = SIM_OPTS | {"ui": "push"}
+
+ def get_asa4_sums(self):
+ self.run_ui_test(**self.SIM_OPTS_ASA4, clones=2, cores=2, mvec_pow=16, seed=8765432, data_push_pow=20, sync_pow=16, auto_save_pow=20)
+ sim_path = f"{self.tempdir.name}/{self.SIM_OPTS["name"]}"
+ auto_saves = sorted(f"{sim_path}/{f}" for f in os.listdir(sim_path))
+ auto_saves = filter(lambda f: f.startswith(f"{sim_path}/{self.SIM_OPTS["name"]}-"), auto_saves)
+ auto_saves = list(auto_saves)[:4]
+ evas = sorted(f"{sim_path}/evas/{f}" for f in os.listdir(f"{sim_path}/evas"))
+ evas = list(evas)[:4]
+ return {f: hashlib.md5(open(f, "rb").read()).hexdigest() for f in auto_saves + evas}
+
+ def get_db_sums(self):
+ self.run_ui_test(**self.SIM_OPTS_PUSH, clones=2, cores=2, mvec_pow=16, seed=8765432, data_push_pow=20, sync_pow=16, auto_save_pow=20)
+ sim_path = f"{self.tempdir.name}/{self.SIM_OPTS["name"]}"
+ db_path = f"{sim_path}/{self.SIM_OPTS["name"]}.sqlite3"
+ return hashlib.md5(open(db_path, "rb").read()).hexdigest()
+
+ def test_deterministic_saves_and_evas(self):
+ sums_1 = self.get_asa4_sums()
+ sums_2 = self.get_asa4_sums()
+ self.assertEqual(sums_1, sums_2)
+
+ def test_deterministic_db(self):
+ sum_1 = self.get_db_sums()
+ sum_2 = self.get_db_sums()
+ self.assertEqual(sum_1, sum_2)
diff --git a/test/test_general.py b/test/test_general.py
new file mode 100644
index 0000000..2286b4f
--- /dev/null
+++ b/test/test_general.py
@@ -0,0 +1,58 @@
+# file : test/test_general.py
+# project : Salis-VM
+# author : Paul Oliver <contact@pauloliver.dev>
+
+# index:
+# [section] setup/teardown
+# [section] file lists
+# [section] assertions
+# [section] subprocess
+
+import os
+import subprocess
+import unittest
+
+from tempfile import TemporaryDirectory
+
+class SalisTest(unittest.TestCase):
+ # --------------------------------------------------------------------------
+ # [section] setup/teardown
+ # --------------------------------------------------------------------------
+ def setUp(self):
+ self.tempdir = TemporaryDirectory(prefix="salis_test_")
+
+ def tearDown(self):
+ self.tempdir.cleanup()
+
+ # --------------------------------------------------------------------------
+ # [section] file lists
+ # --------------------------------------------------------------------------
+ def files_on_new(self, name):
+ return [
+ f"{self.tempdir.name}/{name}/evas/evas-{0:016x}",
+ f"{self.tempdir.name}/{name}/opts.json",
+ f"{self.tempdir.name}/{name}/{name}",
+ f"{self.tempdir.name}/{name}/{name}-{0:016x}",
+ f"{self.tempdir.name}/{name}/{name}.sqlite3",
+ ]
+
+ # --------------------------------------------------------------------------
+ # [section] assertions
+ # --------------------------------------------------------------------------
+ def assert_files_exist(self, files):
+ for file in files:
+ assert os.path.isfile(file), f"{file} does not exist"
+
+ # --------------------------------------------------------------------------
+ # [section] subprocess
+ # --------------------------------------------------------------------------
+ def run_subprocess(self, command):
+ subprocess.run(command.split(), check=True, stdout=subprocess.DEVNULL)
+
+ def run_pipe(self, command):
+ return subprocess.Popen(command.split(), stdout=subprocess.PIPE, text=True)
+
+ def run_ui_test(self, anc, anc_path, ui, ui_path, vm_arch, clones=1, cores=1, mvec_pow=20, name="def.sim", seed=0, data_push_pow=28, sync_pow=20, auto_save_pow=36, **kwargs):
+ command = f"./salis.py new -a{anc} -A{anc_path} -C{clones} -c{cores} -d{data_push_pow} -f -H{self.tempdir.name} -m{mvec_pow} -n{name} -s{seed} -u{ui} -U{ui_path} -v{vm_arch} -y{sync_pow} -z{auto_save_pow}"
+ self.run_subprocess(command)
+ self.assert_files_exist(self.files_on_new(name))
diff --git a/test/test_run.py b/test/test_run.py
new file mode 100644
index 0000000..c86b42b
--- /dev/null
+++ b/test/test_run.py
@@ -0,0 +1,59 @@
+# file : test/test_run.py
+# project : Salis-VM
+# author : Paul Oliver <contact@pauloliver.dev>
+
+# index:
+# [section] command lists
+# [section] file lists
+# [section] tests null
+# [section] tests v1
+
+from test_general import SalisTest
+
+class TestRun(SalisTest):
+ SIM_NAME = "test-run.sim"
+ PUSH_POW = 8
+
+ # --------------------------------------------------------------------------
+ # [section] command lists
+ # --------------------------------------------------------------------------
+ def commands(self, anc, arch):
+ return [
+ (
+ f"./salis.py new -a{anc} -d{self.PUSH_POW} -f -g{compiler} -H{self.tempdir.name} {log_trace} -n{self.SIM_NAME} {optimized} -s{seed} -upush -Utest/ui/ -v{arch} -y{self.PUSH_POW}",
+ f"./salis.py load -g{compiler} -H{self.tempdir.name} {log_trace} -n{self.SIM_NAME} {optimized} -upush -Utest/ui/",
+ )
+ for compiler in ["clang", "gcc", "tcc"]
+ for log_trace in ["", "-l"]
+ for optimized in ["", "-o"]
+ for seed in [-1, 0, 1234]
+ ]
+
+ # --------------------------------------------------------------------------
+ # [section] file lists
+ # --------------------------------------------------------------------------
+ def files_on_first_push(self):
+ return [*self.files_on_new(self.SIM_NAME), f"{self.tempdir.name}/{self.SIM_NAME}/evas/evas-{2 ** self.PUSH_POW:016x}"]
+
+ def files_on_second_push(self):
+ return [*self.files_on_first_push(), f"{self.tempdir.name}/{self.SIM_NAME}/evas/evas-{2 * (2 ** self.PUSH_POW):016x}"]
+
+ # --------------------------------------------------------------------------
+ # [section] tests null
+ # --------------------------------------------------------------------------
+ def test_null(self):
+ for command in self.commands("0123", "null"):
+ self.run_subprocess(command[0])
+ self.assert_files_exist(self.files_on_first_push())
+ self.run_subprocess(command[1])
+ self.assert_files_exist(self.files_on_second_push())
+
+ # --------------------------------------------------------------------------
+ # [section] tests v1
+ # --------------------------------------------------------------------------
+ def test_v1(self):
+ for command in self.commands("55a", "v1"):
+ self.run_subprocess(command[0])
+ self.assert_files_exist(self.files_on_first_push())
+ self.run_subprocess(command[1])
+ self.assert_files_exist(self.files_on_second_push())
diff --git a/test/test_v1.py b/test/test_v1.py
new file mode 100644
index 0000000..b84feb2
--- /dev/null
+++ b/test/test_v1.py
@@ -0,0 +1,51 @@
+# file : test/test_v1.py
+# project : Salis-VM
+# author : Paul Oliver <contact@pauloliver.dev>
+
+# index:
+# [section] tests
+
+from test_general import SalisTest
+
+class TestV1(SalisTest):
+ SIM_OPTS = {
+ "anc_path": "test/anc",
+ "ui_path": "test/ui/v1",
+ "vm_arch": "v1",
+ }
+
+ # --------------------------------------------------------------------------
+ # [section] tests
+ # --------------------------------------------------------------------------
+ def test_noops(self):
+ self.run_ui_test(**self.SIM_OPTS, anc="noops", ui="noops")
+
+ def test_jumps(self):
+ self.run_ui_test(**self.SIM_OPTS, anc="jumps", ui="jumps")
+
+ def test_addrs(self):
+ self.run_ui_test(**self.SIM_OPTS, anc="addrs", ui="addrs")
+
+ def test_ifnzs(self):
+ self.run_ui_test(**self.SIM_OPTS, anc="ifnzs", ui="ifnzs")
+
+ def test_allos(self):
+ self.run_ui_test(**self.SIM_OPTS, anc="allos", ui="allos")
+
+ def test_mbops(self):
+ self.run_ui_test(**self.SIM_OPTS, anc="mbops", ui="mbops")
+
+ def test_3rops(self):
+ self.run_ui_test(**self.SIM_OPTS, anc="3rops", ui="3rops")
+
+ def test_1rops(self):
+ self.run_ui_test(**self.SIM_OPTS, anc="1rops", ui="1rops")
+
+ def test_stack(self):
+ self.run_ui_test(**self.SIM_OPTS, anc="stack", ui="stack")
+
+ def test_ioops(self):
+ self.run_ui_test(**self.SIM_OPTS, anc="ioops", ui="ioops")
+
+ def test_2rops(self):
+ self.run_ui_test(**self.SIM_OPTS, anc="2rops", ui="2rops")
diff --git a/test/ui/asa4/links.json b/test/ui/asa4/links.json
new file mode 100644
index 0000000..fe51488
--- /dev/null
+++ b/test/ui/asa4/links.json
@@ -0,0 +1 @@
+[]
diff --git a/test/ui/asa4/ui.c b/test/ui/asa4/ui.c
new file mode 100644
index 0000000..5a96e3f
--- /dev/null
+++ b/test/ui/asa4/ui.c
@@ -0,0 +1,29 @@
+// file : test/ui/asa4/ui.c
+// project : Salis-VM
+// author : Paul Oliver <contact@pauloliver.dev>
+
+#include <stdbool.h>
+#include <stdint.h>
+#include <threads.h>
+#include <zlib.h>
+
+#include "arch_spec.h"
+#include "arch_inst.h"
+#include "compress.h"
+#include "logger.h"
+#include "salis.h"
+
+int main(void) {
+ salis_init();
+
+ // Run threads until 4 autosaves are made
+ while (g_step < AUTOSAVE_INTERVAL * 4) {
+ salis_start();
+ sleep(1);
+ salis_signal_stop();
+ salis_wait();
+ }
+
+ salis_save_and_free();
+ return 0;
+}
diff --git a/test/ui/null/links.json b/test/ui/null/links.json
new file mode 100644
index 0000000..fe51488
--- /dev/null
+++ b/test/ui/null/links.json
@@ -0,0 +1 @@
+[]
diff --git a/test/ui/null/ui.c b/test/ui/null/ui.c
new file mode 100644
index 0000000..7366e53
--- /dev/null
+++ b/test/ui/null/ui.c
@@ -0,0 +1,24 @@
+// file : test/ui/null/ui.c
+// project : Salis-VM
+// author : Paul Oliver <contact@pauloliver.dev>
+
+#include <stdbool.h>
+#include <stdint.h>
+#include <threads.h>
+#include <zlib.h>
+
+#include "arch_spec.h"
+#include "arch_inst.h"
+#include "compress.h"
+#include "logger.h"
+#include "salis.h"
+
+int main(void) {
+#if defined(COMMAND_NEW)
+ salis_init();
+#elif defined(COMMAND_LOAD)
+ salis_load();
+#endif
+ salis_save_and_free();
+ return 0;
+}
diff --git a/test/ui/push/links.json b/test/ui/push/links.json
new file mode 100644
index 0000000..fe51488
--- /dev/null
+++ b/test/ui/push/links.json
@@ -0,0 +1 @@
+[]
diff --git a/test/ui/push/ui.c b/test/ui/push/ui.c
new file mode 100644
index 0000000..cc5922f
--- /dev/null
+++ b/test/ui/push/ui.c
@@ -0,0 +1,26 @@
+// file : test/ui/push/ui.c
+// project : Salis-VM
+// author : Paul Oliver <contact@pauloliver.dev>
+
+#include <stdbool.h>
+#include <stdint.h>
+#include <threads.h>
+#include <zlib.h>
+
+#include "arch_spec.h"
+#include "arch_inst.h"
+#include "compress.h"
+#include "logger.h"
+#include "salis.h"
+
+int main(void) {
+#if defined(COMMAND_NEW)
+ salis_init();
+#elif defined(COMMAND_LOAD)
+ salis_load();
+#endif
+
+ salis_step(DATA_PUSH_INTERVAL);
+ salis_save_and_free();
+ return 0;
+}
diff --git a/test/ui/v1/1rops/links.json b/test/ui/v1/1rops/links.json
new file mode 100644
index 0000000..fe51488
--- /dev/null
+++ b/test/ui/v1/1rops/links.json
@@ -0,0 +1 @@
+[]
diff --git a/test/ui/v1/1rops/ui.c b/test/ui/v1/1rops/ui.c
new file mode 100644
index 0000000..637e3f5
--- /dev/null
+++ b/test/ui/v1/1rops/ui.c
@@ -0,0 +1,74 @@
+// file : test/ui/v1/1rops/ui.c
+// project : Salis-VM
+// author : Paul Oliver <contact@pauloliver.dev>
+
+#include <assert.h>
+#include <stdint.h>
+#include <threads.h>
+#include <zlib.h>
+
+#include "arch_spec.h"
+#include "arch_inst.h"
+#include "compress.h"
+#include "salis.h"
+
+int main(void) {
+ salis_init();
+
+ while (mvec_is_proc_owner(g_cores, g_cores->pvec->ip, g_cores->pcur)) {
+ uint8_t inst = mvec_get_inst(g_cores, g_cores->pvec->ip);
+
+ if (inst != incn && inst != decn && inst != notn && inst != shfl && inst != shfr && inst != zero && inst != unit) {
+ salis_step(1);
+ continue;
+ }
+
+ uint64_t *reg = &g_cores->pvec->r0x;
+
+ switch (mvec_get_inst(g_cores, g_cores->pvec->ip + 1)) {
+ case nop0:
+ reg = &g_cores->pvec->r0x;
+ break;
+ case nop1:
+ reg = &g_cores->pvec->r1x;
+ break;
+ case nop2:
+ reg = &g_cores->pvec->r2x;
+ break;
+ case nop3:
+ reg = &g_cores->pvec->r3x;
+ break;
+ }
+
+ uint64_t reg_val = *reg;
+
+ salis_step(1);
+
+ switch (inst) {
+ case incn:
+ assert(*reg == reg_val + 1);
+ break;
+ case decn:
+ assert(*reg == reg_val - 1);
+ break;
+ case notn:
+ assert(*reg == !reg_val);
+ break;
+ case shfl:
+ assert(*reg == reg_val << 1);
+ break;
+ case shfr:
+ assert(*reg == reg_val >> 1);
+ break;
+ case zero:
+ assert(*reg == 0);
+ break;
+ case unit:
+ assert(*reg == 1);
+ break;
+ }
+ }
+
+ salis_save_and_free();
+ return 0;
+}
diff --git a/test/ui/v1/2rops/links.json b/test/ui/v1/2rops/links.json
new file mode 100644
index 0000000..fe51488
--- /dev/null
+++ b/test/ui/v1/2rops/links.json
@@ -0,0 +1 @@
+[]
diff --git a/test/ui/v1/2rops/ui.c b/test/ui/v1/2rops/ui.c
new file mode 100644
index 0000000..e74172b
--- /dev/null
+++ b/test/ui/v1/2rops/ui.c
@@ -0,0 +1,56 @@
+// file : test/ui/v1/2rops/ui.c
+// project : Salis-VM
+// author : Paul Oliver <contact@pauloliver.dev>
+
+#include <assert.h>
+#include <stdint.h>
+#include <threads.h>
+#include <zlib.h>
+
+#include "arch_spec.h"
+#include "arch_inst.h"
+#include "compress.h"
+#include "salis.h"
+
+int main(void) {
+ salis_init();
+
+ while (mvec_is_proc_owner(g_cores, g_cores->pvec->ip, g_cores->pcur)) {
+ uint8_t inst = mvec_get_inst(g_cores, g_cores->pvec->ip);
+
+ if (inst != rdup && inst != rswp) {
+ salis_step(1);
+ continue;
+ }
+
+ uint64_t *regs[2] = {
+ &g_cores->pvec->r0x,
+ &g_cores->pvec->r0x,
+ };
+
+ for (uint64_t i = 0; i < 2; i++) {
+ uint8_t rmod = mvec_get_inst(g_cores, g_cores->pvec->ip + 1 + i);
+ if (rmod == nop0) regs[i] = &g_cores->pvec->r0x;
+ else if (rmod == nop1) regs[i] = &g_cores->pvec->r1x;
+ else if (rmod == nop2) regs[i] = &g_cores->pvec->r2x;
+ else if (rmod == nop3) regs[i] = &g_cores->pvec->r3x;
+ else break;
+ }
+
+ uint64_t reg_vals[2] = {*regs[0], *regs[1]};
+ salis_step(1);
+
+ switch (inst) {
+ case rdup:
+ assert(*regs[1] == reg_vals[0]);
+ break;
+ case rswp:
+ assert(*regs[0] == reg_vals[1]);
+ assert(*regs[1] == reg_vals[0]);
+ break;
+ }
+ }
+
+ salis_save_and_free();
+ return 0;
+}
diff --git a/test/ui/v1/3rops/links.json b/test/ui/v1/3rops/links.json
new file mode 100644
index 0000000..fe51488
--- /dev/null
+++ b/test/ui/v1/3rops/links.json
@@ -0,0 +1 @@
+[]
diff --git a/test/ui/v1/3rops/ui.c b/test/ui/v1/3rops/ui.c
new file mode 100644
index 0000000..2a53197
--- /dev/null
+++ b/test/ui/v1/3rops/ui.c
@@ -0,0 +1,65 @@
+// file : test/ui/v1/3rops/ui.c
+// project : Salis-VM
+// author : Paul Oliver <contact@pauloliver.dev>
+
+#include <assert.h>
+#include <stdint.h>
+#include <threads.h>
+#include <zlib.h>
+
+#include "arch_spec.h"
+#include "arch_inst.h"
+#include "compress.h"
+#include "salis.h"
+
+int main(void) {
+ salis_init();
+
+ while (mvec_is_proc_owner(g_cores, g_cores->pvec->ip, g_cores->pcur)) {
+ uint8_t inst = mvec_get_inst(g_cores, g_cores->pvec->ip);
+
+ if (inst != addn && inst != subn && inst != muln && inst != divn) {
+ salis_step(1);
+ continue;
+ }
+
+ uint64_t *regs[3] = {
+ &g_cores->pvec->r0x,
+ &g_cores->pvec->r0x,
+ &g_cores->pvec->r0x,
+ };
+
+ for (uint64_t i = 0; i < 3; i++) {
+ uint8_t rmod = mvec_get_inst(g_cores, g_cores->pvec->ip + 1 + i);
+
+ if (rmod == nop0) regs[i] = &g_cores->pvec->r0x;
+ else if (rmod == nop1) regs[i] = &g_cores->pvec->r1x;
+ else if (rmod == nop2) regs[i] = &g_cores->pvec->r2x;
+ else if (rmod == nop3) regs[i] = &g_cores->pvec->r3x;
+ else break;
+ }
+
+ uint64_t reg_vals[3] = {*regs[0], *regs[1], *regs[2]};
+ salis_step(1);
+ uint64_t result = *regs[0];
+
+ switch (inst) {
+ case addn:
+ assert(result == reg_vals[1] + reg_vals[2]);
+ break;
+ case subn:
+ assert(result == reg_vals[1] - reg_vals[2]);
+ break;
+ case muln:
+ assert(result == reg_vals[1] * reg_vals[2]);
+ break;
+ case divn:
+ assert(reg_vals[2] != 0);
+ assert(result == reg_vals[1] / reg_vals[2]);
+ break;
+ }
+ }
+
+ salis_save_and_free();
+ return 0;
+}
diff --git a/test/ui/v1/addrs/links.json b/test/ui/v1/addrs/links.json
new file mode 100644
index 0000000..fe51488
--- /dev/null
+++ b/test/ui/v1/addrs/links.json
@@ -0,0 +1 @@
+[]
diff --git a/test/ui/v1/addrs/ui.c b/test/ui/v1/addrs/ui.c
new file mode 100644
index 0000000..eb4361c
--- /dev/null
+++ b/test/ui/v1/addrs/ui.c
@@ -0,0 +1,58 @@
+// file : test/ui/v1/addrs/ui.c
+// project : Salis-VM
+// author : Paul Oliver <contact@pauloliver.dev>
+
+#include <assert.h>
+#include <stdint.h>
+#include <threads.h>
+#include <zlib.h>
+
+#include "arch_spec.h"
+#include "arch_inst.h"
+#include "compress.h"
+#include "salis.h"
+
+static void check_found(uint64_t addr, uint64_t lok, uint64_t regi) {
+ assert(mvec_get_inst(g_cores, addr - 1) == (regi % 2 == 0 ? adrf : adrb));
+ assert(mvec_get_inst(g_cores, (&g_cores->pvec->r0x)[regi]) == lok);
+}
+
+int main(void) {
+ uint64_t regi = 0;
+
+ salis_init();
+
+ while (mvec_is_proc_owner(g_cores, g_cores->pvec->ip, g_cores->pcur)) {
+ uint8_t inst = mvec_get_inst(g_cores, g_cores->pvec->ip);
+
+ switch (inst) {
+#define CASE(id) \
+ case key##id: \
+ check_found(g_cores->pvec->ip, lok##id, regi); \
+ regi = (regi + 1) % 4; \
+ break;
+ CASE(a)
+ CASE(b)
+ CASE(c)
+ CASE(d)
+ CASE(e)
+ CASE(f)
+ CASE(g)
+ CASE(h)
+ CASE(i)
+ CASE(j)
+ CASE(k)
+ CASE(l)
+ CASE(m)
+ CASE(n)
+ CASE(o)
+ CASE(p)
+#undef CASE
+ }
+
+ salis_step(1);
+ }
+
+ salis_save_and_free();
+ return 0;
+}
diff --git a/test/ui/v1/allos/links.json b/test/ui/v1/allos/links.json
new file mode 100644
index 0000000..fe51488
--- /dev/null
+++ b/test/ui/v1/allos/links.json
@@ -0,0 +1 @@
+[]
diff --git a/test/ui/v1/allos/ui.c b/test/ui/v1/allos/ui.c
new file mode 100644
index 0000000..5b0da79
--- /dev/null
+++ b/test/ui/v1/allos/ui.c
@@ -0,0 +1,80 @@
+// file : test/ui/v1/allos/ui.c
+// project : Salis-VM
+// author : Paul Oliver <contact@pauloliver.dev>
+
+#include <assert.h>
+#include <stdint.h>
+#include <threads.h>
+#include <zlib.h>
+
+#include "arch_spec.h"
+#include "arch_inst.h"
+#include "compress.h"
+#include "salis.h"
+
+#define CHILD_SIZE 4
+
+static const struct Proc *first_proc(void) {
+ return proc_fetch(g_cores, g_cores->pfst);
+}
+
+static void check_new_proc(void) {
+ const struct Proc *proc = proc_get(g_cores, g_cores->plst);
+
+ assert(proc->mb0s == CHILD_SIZE);
+ assert(proc->mb1a == 0);
+ assert(proc->mb1s == 0);
+ assert(proc->r0x == 0);
+ assert(proc->r1x == 0);
+ assert(proc->r2x == 0);
+ assert(proc->r3x == 0);
+ assert(proc->s0 == 0);
+ assert(proc->s1 == 0);
+ assert(proc->s2 == 0);
+ assert(proc->s3 == 0);
+ assert(proc->s4 == 0);
+ assert(proc->s5 == 0);
+ assert(proc->s6 == 0);
+ assert(proc->s7 == 0);
+
+ uint64_t birth_addr = (uint64_t)-1;
+
+ switch (g_cores->plst) {
+ case 1:
+ birth_addr = ANC_SIZE;
+ break;
+ case 2:
+ birth_addr = ANC_SIZE - 7;
+ break;
+ default:
+ assert(false);
+ }
+
+ assert(proc->ip == birth_addr);
+ assert(proc->sp == birth_addr);
+ assert(proc->mb0a == birth_addr);
+}
+
+int main(void) {
+ salis_init();
+
+ while (first_proc()->ip < (ANC_SIZE + (CHILD_SIZE * 2))) {
+ bool will_split = g_cores->pcur == g_cores->pfst && mvec_get_inst(g_cores, first_proc()->ip) == bspl && first_proc()->mb1s;
+ uint64_t pnum = g_cores->pnum;
+
+ salis_step(1);
+
+ if (will_split) {
+ assert(g_cores->pnum == pnum + 1);
+ assert(g_cores->plst == pnum);
+ check_new_proc();
+ } else {
+ assert(g_cores->pnum == pnum);
+ }
+ }
+
+ assert(g_cores->pnum == 3);
+
+ salis_save_and_free();
+ return 0;
+}
diff --git a/test/ui/v1/ifnzs/links.json b/test/ui/v1/ifnzs/links.json
new file mode 100644
index 0000000..fe51488
--- /dev/null
+++ b/test/ui/v1/ifnzs/links.json
@@ -0,0 +1 @@
+[]
diff --git a/test/ui/v1/ifnzs/ui.c b/test/ui/v1/ifnzs/ui.c
new file mode 100644
index 0000000..0c3921e
--- /dev/null
+++ b/test/ui/v1/ifnzs/ui.c
@@ -0,0 +1,56 @@
+// file : test/ui/v1/ifnzs/ui.c
+// project : Salis-VM
+// author : Paul Oliver <contact@pauloliver.dev>
+
+#include <assert.h>
+#include <stdint.h>
+#include <threads.h>
+#include <zlib.h>
+
+#include "arch_spec.h"
+#include "arch_inst.h"
+#include "compress.h"
+#include "salis.h"
+
+int main(void) {
+ uint64_t next_addr = 0;
+
+ salis_init();
+
+ while (mvec_is_proc_owner(g_cores, g_cores->pvec->ip, g_cores->pcur)) {
+ assert(g_cores->pvec->ip == next_addr);
+
+ if (mvec_get_inst(g_cores, g_cores->pvec->ip) == ifnz) {
+ switch (mvec_get_inst(g_cores, g_cores->pvec->ip + 1)) {
+ case nop0:
+ next_addr += g_cores->pvec->r0x ? 1 : 2;
+ break;
+ case nop1:
+ next_addr += g_cores->pvec->r1x ? 1 : 2;
+ break;
+ case nop2:
+ next_addr += g_cores->pvec->r2x ? 1 : 2;
+ break;
+ case nop3:
+ next_addr += g_cores->pvec->r3x ? 1 : 2;
+ break;
+ default:
+ next_addr += g_cores->pvec->r0x ? 0 : 1;
+ }
+ }
+
+ salis_step(1);
+ next_addr++;
+
+ assert(g_cores->pvec->ip == next_addr);
+ }
+
+ assert(g_cores->pvec->ip == ANC_SIZE);
+ assert(g_cores->pvec->r0x == 2);
+ assert(g_cores->pvec->r1x == 2);
+ assert(g_cores->pvec->r2x == 2);
+ assert(g_cores->pvec->r3x == 2);
+
+ salis_save_and_free();
+ return 0;
+}
diff --git a/test/ui/v1/ioops/links.json b/test/ui/v1/ioops/links.json
new file mode 100644
index 0000000..fe51488
--- /dev/null
+++ b/test/ui/v1/ioops/links.json
@@ -0,0 +1 @@
+[]
diff --git a/test/ui/v1/ioops/ui.c b/test/ui/v1/ioops/ui.c
new file mode 100644
index 0000000..8ec21b2
--- /dev/null
+++ b/test/ui/v1/ioops/ui.c
@@ -0,0 +1,66 @@
+// file : test/ui/v1/ioops/ui.c
+// project : Salis-VM
+// author : Paul Oliver <contact@pauloliver.dev>
+
+#include <assert.h>
+#include <stdint.h>
+#include <threads.h>
+#include <zlib.h>
+
+#include "arch_spec.h"
+#include "arch_inst.h"
+#include "compress.h"
+#include "salis.h"
+
+int main(void) {
+ salis_init();
+
+ while (mvec_is_proc_owner(g_cores, g_cores->pvec->ip, g_cores->pcur)) {
+ uint8_t inst = mvec_get_inst(g_cores, g_cores->pvec->ip);
+
+ if (inst != rloa && inst != rwrt) {
+ salis_step(1);
+ continue;
+ }
+
+ uint64_t *regs[2] = {
+ &g_cores->pvec->r0x,
+ &g_cores->pvec->r0x,
+ };
+
+ for (uint64_t i = 0; i < 2; i++) {
+ uint8_t rmod = mvec_get_inst(g_cores, g_cores->pvec->ip + 1 + i);
+
+ if (rmod == nop0) regs[i] = &g_cores->pvec->r0x;
+ else if (rmod == nop1) regs[i] = &g_cores->pvec->r1x;
+ else if (rmod == nop2) regs[i] = &g_cores->pvec->r2x;
+ else if (rmod == nop3) regs[i] = &g_cores->pvec->r3x;
+ else break;
+ }
+
+ if (g_cores->pvec->sp != *regs[0]) {
+ salis_step(1);
+ continue;
+ }
+
+ uint64_t reg_vals[2] = {*regs[0], *regs[1]};
+
+ assert(g_cores->pvec->sp == *regs[0]);
+ salis_step(1);
+ assert(g_cores->pvec->sp == g_cores->pvec->ip);
+
+ switch (inst) {
+ case rloa:
+ assert(*regs[1] == (uint64_t)mvec_get_inst(g_cores, reg_vals[0]));
+ break;
+ case rwrt:
+ assert(*regs[0] == reg_vals[0]);
+ assert(*regs[1] == reg_vals[1]);
+ assert(mvec_get_inst(g_cores, *regs[0]) == (*regs[1] & ARCH_INST_MASK));
+ break;
+ }
+ }
+
+ salis_save_and_free();
+ return 0;
+}
diff --git a/test/ui/v1/jumps/links.json b/test/ui/v1/jumps/links.json
new file mode 100644
index 0000000..fe51488
--- /dev/null
+++ b/test/ui/v1/jumps/links.json
@@ -0,0 +1 @@
+[]
diff --git a/test/ui/v1/jumps/ui.c b/test/ui/v1/jumps/ui.c
new file mode 100644
index 0000000..2ef5caa
--- /dev/null
+++ b/test/ui/v1/jumps/ui.c
@@ -0,0 +1,31 @@
+// file : test/ui/v1/jumps/ui.c
+// project : Salis-VM
+// author : Paul Oliver <contact@pauloliver.dev>
+
+#include <assert.h>
+#include <stdint.h>
+#include <threads.h>
+#include <zlib.h>
+
+#include "arch_spec.h"
+#include "arch_inst.h"
+#include "compress.h"
+#include "salis.h"
+
+int main(void) {
+ uint8_t lok = loka;
+
+ salis_init();
+
+ while (lok != lokp) {
+ if (mvec_get_inst(g_cores, g_cores->pvec->ip) == lok) {
+ lok = lok + 1;
+ }
+
+ salis_step(1);
+ assert(g_cores->pvec->ip < ANC_SIZE);
+ }
+
+ salis_save_and_free();
+ return 0;
+}
diff --git a/test/ui/v1/mbops/links.json b/test/ui/v1/mbops/links.json
new file mode 100644
index 0000000..fe51488
--- /dev/null
+++ b/test/ui/v1/mbops/links.json
@@ -0,0 +1 @@
+[]
diff --git a/test/ui/v1/mbops/ui.c b/test/ui/v1/mbops/ui.c
new file mode 100644
index 0000000..ea417d6
--- /dev/null
+++ b/test/ui/v1/mbops/ui.c
@@ -0,0 +1,46 @@
+// file : test/ui/v1/mbops/ui.c
+// project : Salis-VM
+// author : Paul Oliver <contact@pauloliver.dev>
+
+#include <assert.h>
+#include <stdint.h>
+#include <threads.h>
+#include <zlib.h>
+
+#include "arch_spec.h"
+#include "arch_inst.h"
+#include "compress.h"
+#include "salis.h"
+
+int main(void) {
+ salis_init();
+
+ while (g_cores->pvec->ip < ANC_SIZE) {
+ bool on_swap = mvec_get_inst(g_cores, g_cores->pvec->ip) == bswp;
+ bool on_clear = mvec_get_inst(g_cores, g_cores->pvec->ip) == bclr;
+
+ uint64_t mb0a = g_cores->pvec->mb0a;
+ uint64_t mb0s = g_cores->pvec->mb0s;
+ uint64_t mb1a = g_cores->pvec->mb1a;
+ uint64_t mb1s = g_cores->pvec->mb1s;
+
+ salis_step(1);
+
+ if (on_swap) {
+ if (mb1s) {
+ assert(g_cores->pvec->mb0a == mb1a);
+ assert(g_cores->pvec->mb0s == mb1s);
+ assert(g_cores->pvec->mb1a == mb0a);
+ assert(g_cores->pvec->mb1s == mb0s);
+ }
+ }
+
+ if (on_clear) {
+ assert(g_cores->pvec->mb1a == 0);
+ assert(g_cores->pvec->mb1s == 0);
+ }
+ }
+
+ salis_save_and_free();
+ return 0;
+}
diff --git a/test/ui/v1/noops/links.json b/test/ui/v1/noops/links.json
new file mode 100644
index 0000000..fe51488
--- /dev/null
+++ b/test/ui/v1/noops/links.json
@@ -0,0 +1 @@
+[]
diff --git a/test/ui/v1/noops/ui.c b/test/ui/v1/noops/ui.c
new file mode 100644
index 0000000..b0ad004
--- /dev/null
+++ b/test/ui/v1/noops/ui.c
@@ -0,0 +1,136 @@
+// file : test/ui/v1/noops/ui.c
+// project : Salis-VM
+// author : Paul Oliver <contact@pauloliver.dev>
+
+#include <assert.h>
+#include <stdint.h>
+#include <threads.h>
+#include <zlib.h>
+
+#include "arch_spec.h"
+#include "arch_inst.h"
+#include "compress.h"
+#include "salis.h"
+
+static uint8_t g_anc_bytes[] = ANC_BYTES;
+
+static void check_invariants(void) {
+ assert(g_cores->mall == ANC_SIZE);
+ assert(g_cores->muta[0] == 0);
+ assert(g_cores->muta[1] == 0);
+ assert(g_cores->muta[2] == 0);
+ assert(g_cores->muta[3] == 0);
+ assert(g_cores->pnum == 1);
+ assert(g_cores->pcap == 1);
+ assert(g_cores->pfst == 0);
+ assert(g_cores->plst == 0);
+ assert(g_cores->pcur == 0);
+ assert(g_cores->psli == 1);
+
+ for (uint64_t i = 0; i < SYNC_INTERVAL; i++) {
+ assert(g_cores->ivav[i] == 0);
+ assert(g_cores->iviv[i] == 0);
+ }
+
+ for (uint64_t i = 0; i < MVEC_SIZE; i++) {
+ if (i < ANC_SIZE) {
+ assert(mvec_get_inst(g_cores, i) == g_anc_bytes[i]);
+ } else {
+ assert(mvec_get_inst(g_cores, i) == 0);
+ }
+ }
+
+ assert(g_cores->pvec->mb0a == 0);
+ assert(g_cores->pvec->mb0s == ANC_SIZE);
+ assert(g_cores->pvec->mb1a == 0);
+ assert(g_cores->pvec->mb1s == 0);
+ assert(g_cores->pvec->r0x == 0);
+ assert(g_cores->pvec->r1x == 0);
+ assert(g_cores->pvec->r2x == 0);
+ assert(g_cores->pvec->r3x == 0);
+ assert(g_cores->pvec->s0 == 0);
+ assert(g_cores->pvec->s1 == 0);
+ assert(g_cores->pvec->s2 == 0);
+ assert(g_cores->pvec->s3 == 0);
+ assert(g_cores->pvec->s4 == 0);
+ assert(g_cores->pvec->s5 == 0);
+ assert(g_cores->pvec->s6 == 0);
+ assert(g_cores->pvec->s7 == 0);
+
+ assert(g_cores->amb0 == 0.);
+ assert(g_cores->amb1 == 0.);
+
+ assert(g_cores->emb1 == 0);
+ assert(g_cores->eliv == 0);
+ assert(g_cores->edea == 0);
+
+ for (uint64_t i = 0; i < MVEC_SIZE; i++) {
+ assert(g_cores->aeva.data[i] == 0);
+ assert(g_cores->beva.data[i] == 0);
+ }
+
+ // V1 arch specific
+ for (uint64_t i = 0; i < ARCH_INST_COUNT; i++) {
+ assert(g_cores->ipop[i] == 0);
+ assert(g_cores->iwrt[i] == 0);
+ }
+
+ assert(g_cores->wmb0 == 0);
+ assert(g_cores->wmb1 == 0);
+ assert(g_cores->wdea == 0);
+ assert(g_cores->hlts == 0);
+
+ for (uint64_t i = 0; i < MVEC_SIZE; i++) {
+ assert(g_cores->weva.data[i] == 0);
+ assert(g_cores->xeva.data[i] == 0);
+ }
+}
+
+static void check_variants(void) {
+ assert(g_cores->step == g_step);
+ assert(g_cores->cycl == g_step);
+ assert(g_cores->ivpt == g_step);
+
+ assert(g_cores->pvec->ip == g_step);
+ assert(g_cores->pvec->sp == g_step);
+
+ assert(g_cores->emb0 == g_step);
+
+ for (uint64_t i = 0; i < MVEC_SIZE; i++) {
+ assert(g_cores->eeva.data[i] == (i < g_step ? 1 : 0));
+ }
+
+ // V1 arch specific
+ for (uint64_t i = 0; i < ARCH_INST_COUNT; i++) {
+ uint64_t exed = 0;
+
+ for (uint64_t j = 0; j < g_step; j++) {
+ if (mvec_get_inst(g_cores, j) == i) {
+ exed++;
+ }
+ }
+
+ assert(g_cores->iexe[i] == exed);
+ }
+}
+
+static void check_final(void) {
+ assert(g_cores->pvec->ip == ANC_SIZE);
+ assert(g_cores->pvec->sp == ANC_SIZE);
+}
+
+int main(void) {
+ salis_init();
+ check_invariants();
+ check_variants();
+
+ while (mvec_is_proc_owner(g_cores, g_cores->pvec->ip, g_cores->pcur)) {
+ salis_step(1);
+ check_invariants();
+ check_variants();
+ }
+
+ check_final();
+ salis_save_and_free();
+ return 0;
+}
diff --git a/test/ui/v1/stack/links.json b/test/ui/v1/stack/links.json
new file mode 100644
index 0000000..fe51488
--- /dev/null
+++ b/test/ui/v1/stack/links.json
@@ -0,0 +1 @@
+[]
diff --git a/test/ui/v1/stack/ui.c b/test/ui/v1/stack/ui.c
new file mode 100644
index 0000000..f74b629
--- /dev/null
+++ b/test/ui/v1/stack/ui.c
@@ -0,0 +1,85 @@
+// file : test/ui/v1/stack/ui.c
+// project : Salis-VM
+// author : Paul Oliver <contact@pauloliver.dev>
+
+#include <assert.h>
+#include <stdint.h>
+#include <threads.h>
+#include <zlib.h>
+
+#include "arch_spec.h"
+#include "arch_inst.h"
+#include "compress.h"
+#include "salis.h"
+
+int main(void) {
+ salis_init();
+
+ while (mvec_is_proc_owner(g_cores, g_cores->pvec->ip, g_cores->pcur)) {
+ uint8_t inst = mvec_get_inst(g_cores, g_cores->pvec->ip);
+
+ if (inst != rpsh && inst != rpop) {
+ salis_step(1);
+ continue;
+ }
+
+ uint64_t *reg = &g_cores->pvec->r0x;
+
+ switch (mvec_get_inst(g_cores, g_cores->pvec->ip + 1)) {
+ case nop0:
+ reg = &g_cores->pvec->r0x;
+ break;
+ case nop1:
+ reg = &g_cores->pvec->r1x;
+ break;
+ case nop2:
+ reg = &g_cores->pvec->r2x;
+ break;
+ case nop3:
+ reg = &g_cores->pvec->r3x;
+ break;
+ }
+
+ uint64_t reg_val = *reg;
+ uint64_t stack_val[8] = {
+ g_cores->pvec->s0,
+ g_cores->pvec->s1,
+ g_cores->pvec->s2,
+ g_cores->pvec->s3,
+ g_cores->pvec->s4,
+ g_cores->pvec->s5,
+ g_cores->pvec->s6,
+ g_cores->pvec->s7,
+ };
+
+ salis_step(1);
+
+ switch (inst) {
+ case rpsh:
+ assert(*reg == reg_val);
+ assert(g_cores->pvec->s0 == *reg);
+ assert(g_cores->pvec->s1 == stack_val[0]);
+ assert(g_cores->pvec->s2 == stack_val[1]);
+ assert(g_cores->pvec->s3 == stack_val[2]);
+ assert(g_cores->pvec->s4 == stack_val[3]);
+ assert(g_cores->pvec->s5 == stack_val[4]);
+ assert(g_cores->pvec->s6 == stack_val[5]);
+ assert(g_cores->pvec->s7 == stack_val[6]);
+ break;
+ case rpop:
+ assert(*reg == stack_val[0]);
+ assert(g_cores->pvec->s0 == stack_val[1]);
+ assert(g_cores->pvec->s1 == stack_val[2]);
+ assert(g_cores->pvec->s2 == stack_val[3]);
+ assert(g_cores->pvec->s3 == stack_val[4]);
+ assert(g_cores->pvec->s4 == stack_val[5]);
+ assert(g_cores->pvec->s5 == stack_val[6]);
+ assert(g_cores->pvec->s6 == stack_val[7]);
+ assert(g_cores->pvec->s7 == 0);
+ break;
+ }
+ }
+
+ salis_save_and_free();
+ return 0;
+}