diff options
| -rw-r--r-- | README.md | 1 | ||||
| -rw-r--r-- | arch/dummy/vars.py | 1 | ||||
| -rw-r--r-- | arch/v1/vars.py | 1 | ||||
| -rw-r--r-- | core/client.cpp | 8 | ||||
| -rw-r--r-- | core/logger.c | 1 | ||||
| -rw-r--r-- | core/salis.c | 19 | ||||
| -rwxr-xr-x | salis.py | 51 | ||||
| -rw-r--r-- | test/anc/v1/noops.asm | 38 | ||||
| -rw-r--r-- | test/test_build.py | 80 | ||||
| -rw-r--r-- | test/test_general.py | 31 | ||||
| -rw-r--r-- | test/test_v1.py | 6 | ||||
| -rw-r--r-- | test/ui/null/ui.c | 10 | ||||
| -rw-r--r-- | test/ui/null/vars.py | 3 | ||||
| -rw-r--r-- | test/ui/v1/noops/ui.c | 114 | ||||
| -rw-r--r-- | test/ui/v1/noops/vars.py | 3 |
15 files changed, 335 insertions, 32 deletions
@@ -94,7 +94,6 @@ user@host$ ./salis.py client -o -i ${SERVER_IP} ## Dependencies (data client) - GLFW -- GLU - ImGui - ImPlot - OpenGL diff --git a/arch/dummy/vars.py b/arch/dummy/vars.py index 7150767..fce888a 100644 --- a/arch/dummy/vars.py +++ b/arch/dummy/vars.py @@ -7,6 +7,7 @@ inst_set = [(["dummy", f"{i:02x}"], symbol) for i, symbol in enumerate( core_data_fields = [] core_fields = [] +muta_flip = False mvec_loop = True proc_fields = [ ("uint64_t", "ip"), diff --git a/arch/v1/vars.py b/arch/v1/vars.py index cf4f376..4eac4e7 100644 --- a/arch/v1/vars.py +++ b/arch/v1/vars.py @@ -76,6 +76,7 @@ core_data_fields = [ ("uint64_t", f"xeva[{2 ** globals()["args"].mvec_pow}]"), # memory block swap events array ] core_fields = [] +muta_flip = False mvec_loop = False proc_fields = [ ("uint64_t", "ip"), diff --git a/core/client.cpp b/core/client.cpp index d541129..750f2be 100644 --- a/core/client.cpp +++ b/core/client.cpp @@ -22,7 +22,6 @@ // [section] includes // ---------------------------------------------------------------------------- #include <arpa/inet.h> -#include <GL/glu.h> #include <GLFW/glfw3.h> #include <imgui_impl_glfw.h> #include <imgui_impl_opengl3.h> @@ -348,8 +347,6 @@ std::array g_hm_colormap = std::to_array<ImVec4>({ {0.988f, 1.000f, 0.643f, 1.f}, }); -PFNGLCOPYIMAGESUBDATAPROC glCopyImageSubData; - // ---------------------------------------------------------------------------- // [section] string comparator definition // ---------------------------------------------------------------------------- @@ -747,7 +744,7 @@ void PlotHeatmap::render_internal(const ImVec2 &frame_size) { assert(new_tex_id); if (m_tex_id) { - glCopyImageSubData( + ((PFNGLCOPYIMAGESUBDATAPROC)glfwGetProcAddress("glCopyImageSubData"))( m_tex_id, GL_TEXTURE_2D, 0, 0, rows_to_chop_off, 0, new_tex_id, GL_TEXTURE_2D, 0, 0, 0, 0, g_hm_pixel_count, m_rows_rendered - rows_to_chop_off, 1 @@ -1464,9 +1461,6 @@ void init() { glfwSwapInterval(0); #endif - glCopyImageSubData = (PFNGLCOPYIMAGESUBDATAPROC)glfwGetProcAddress("glCopyImageSubData"); - assert(glCopyImageSubData); - log_info("Initializing ImGui"); IMGUI_CHECKVERSION(); ImGui::CreateContext(); diff --git a/core/logger.c b/core/logger.c index 2c8746f..af41dcc 100644 --- a/core/logger.c +++ b/core/logger.c @@ -79,6 +79,7 @@ void log_msg(enum LogLevel level, bool colored, const char *format, va_list args char buff[LOG_LINE_SIZE]; log_msg_to_buff(buff, LOG_LINE_SIZE, level, colored, format, args); printf("\r%s\n", buff); + fflush(stdout); } void log_info_default(const char *format, ...) { diff --git a/core/salis.c b/core/salis.c index 9f9a3d0..dac9e52 100644 --- a/core/salis.c +++ b/core/salis.c @@ -310,6 +310,7 @@ uint64_t mvec_get_owner(const struct Core *core, uint64_t addr) { // ---------------------------------------------------------------------------- // [section] mutator functions // ---------------------------------------------------------------------------- +#if SEED != 0 #if defined(COMMAND_NEW) uint64_t muta_smix(uint64_t *seed) { assert(seed); @@ -357,6 +358,7 @@ void muta_cosmic_ray(struct Core *core) { #endif } } +#endif // ---------------------------------------------------------------------------- // [section] process functions @@ -491,12 +493,15 @@ void core_init(struct Core *core, uint64_t *seed) { assert(core); assert(seed); - if (*seed) { - core->muta[0] = muta_smix(seed); - core->muta[1] = muta_smix(seed); - core->muta[2] = muta_smix(seed); - core->muta[3] = muta_smix(seed); - } +#if SEED != 0 + assert(*seed); + core->muta[0] = muta_smix(seed); + core->muta[1] = muta_smix(seed); + core->muta[2] = muta_smix(seed); + core->muta[3] = muta_smix(seed); +#else + (void)seed; +#endif core->pnum = CLONES; core->pcap = CLONES; @@ -642,7 +647,9 @@ void core_step(struct Core *core) { proc_kill(core); } +#if SEED != 0 muta_cosmic_ray(core); +#endif core_step(core); } @@ -2,6 +2,7 @@ # index # [section] argument parser +# [section] run unit tests # [section] build class # [section] logging # [section] options dict formatter @@ -20,6 +21,7 @@ import shutil import socket import subprocess import sys +import unittest from argparse import ArgumentDefaultsHelpFormatter, ArgumentParser, ArgumentTypeError, RawTextHelpFormatter from tempfile import TemporaryDirectory @@ -39,9 +41,7 @@ new = sub_parsers.add_parser("new", formatter_class=formatter_class, help="creat load = sub_parsers.add_parser("load", formatter_class=formatter_class, help="load saved simulation") server = sub_parsers.add_parser("server", formatter_class=formatter_class, help="run data server") client = sub_parsers.add_parser("client", formatter_class=formatter_class, help="run data client") - -architectures = os.listdir("./arch") -uis = os.listdir("./ui") +test = sub_parsers.add_parser("test", formatter_class=formatter_class, help="run unit tests") def seed(i): ival = int(i, 0) @@ -67,14 +67,14 @@ fmt_id = lambda val: val fmt_hex = lambda val: hex(int(val, 0)) if type(val) == str else hex(val) options = { - (("A", "anc"), (new,), fmt_id): {"metavar": "ANC", "help": "ancestor file name without extension; to be compiled on all cores; ANC points to 'anc/{arch}/{ANC}.asm'", "required": True, "type": str}, - (("a", "arch"), (new,), fmt_id): {"choices": architectures, "help": "VM architecture", "default": "dummy", "required": False, "type": str}, + (("a", "anc"), (new,), fmt_id): {"metavar": "ANC", "help": "ancestor file name without extension; to be compiled on all cores; ANC points to '{anc-path}/{arch}/{ANC}.asm'", "required": True, "type": str}, + (("A", "anc-path"), (new,), fmt_id): {"metavar": "PATH", "help": "path to search for ancestor files", "default": "anc", "required": False, "type": str}, + (("b", "build-only"), (new, load, server, client), fmt_id): {"action": "store_true", "help": "only build (do not run) executable", "required": False}, (("C", "clones"), (new,), fmt_id): {"metavar": "N", "help": "number of ancestor clones on each core", "default": 1, "required": False, "type": nat}, (("c", "cores"), (new,), fmt_id): {"metavar": "N", "help": "number of simulator cores", "default": 2, "required": False, "type": nat}, (("d", "data-push-pow"), (new,), fmt_id): {"metavar": "POW", "help": "data aggregation interval exponent; interval = 2^{POW} >= {sync-pow}", "default": 28, "required": False, "type": nat}, - (("F", "font"), (client,), fmt_id): {"metavar": "FILE", "help": "font face to use", "default": "/usr/share/fonts/droid/DroidSansMono.ttf", "required": False}, + (("f", "font"), (client,), fmt_id): {"metavar": "FILE", "help": "font face to use", "default": "/usr/share/fonts/droid/DroidSansMono.ttf", "required": False}, (("f", "force"), (new,), fmt_id): {"action": "store_true", "help": "overwrite existing simulation of given name", "required": False}, - (("F", "muta-flip"), (new,), fmt_id): {"action": "store_true", "help": "cosmic rays flip bits instead of randomizing whole bytes", "required": False}, (("g", "c-compiler"), (new, load, server, client), fmt_id): {"metavar": "CC", "help": "C compiler to use", "default": "gcc", "required": False, "type": str}, (("G", "c-compiler-flags"), (new, load, server, client), fmt_id): {"metavar": "FLAGS", "help": "base set of flags to pass to C compiler", "default": "-Wall -Wextra -Werror -Wno-overlength-strings -pedantic", "required": False, "type": str}, (("H", "home"), (new, load, server), fmt_id): {"metavar": "PATH", "help": "salis home directory", "default": os.path.join(os.environ["HOME"], ".salis"), "required": False, "type": str}, @@ -83,13 +83,16 @@ options = { (("m", "mvec-pow"), (new,), fmt_id): {"metavar": "POW", "help": "memory core size exponent; size = 2^{POW}", "default": 20, "required": False, "type": pos}, (("n", "name"), (new, load, server), fmt_id): {"metavar": "NAME", "help": "name of new or loaded simulation", "default": "def.sim", "required": False, "type": str}, (("o", "optimized"), (new, load, server, client), fmt_id): {"action": "store_true", "help": "build with optimizations", "required": False}, + (("p", "pattern"), (test,), fmt_id): {"metavar": "PATTERN", "help": "pattern for unit test discovery", "default": "*", "required": False, "type": str}, (("P", "port"), (server, client), fmt_id): {"metavar": "PORT", "help": "port number for data server", "default": 8080, "required": False, "type": port}, (("p", "pre-cmd"), (new, load, server, client), fmt_id): {"metavar": "CMD", "help": "shell command with which to wrap call to executable; e.g. gdb, time, valgrind, etc.", "required": False, "type": str}, (("s", "seed"), (new,), fmt_hex): {"metavar": "SEED", "help": "seed value for new simulation; a value of 0 disables cosmic rays; a value of -1 creates a random seed", "default": 0, "required": False, "type": seed}, (("T", "keep-temp-dir"), (new, load, server, client), fmt_id): {"action": "store_true", "help": "keep temporary directory on exit", "required": False}, (("t", "thread-gap"), (new, load), fmt_hex): {"metavar": "N", "help": "memory gap between core elements in bytes; may help reduce cache misses", "default": 0x100, "required": False, "type": nat}, - (("u", "ui"), (new, load), fmt_id): {"choices": uis, "help": "user interface", "default": "curses", "required": False, "type": str}, + (("u", "ui"), (new, load), fmt_id): {"metavar": "UI", "help": "user interface", "default": "curses", "required": False, "type": str}, + (("U", "ui-path"), (new, load), fmt_id): {"metavar": "PATH", "help": "path to search for UIs", "default": "ui", "required": False, "type": str}, (("v", "no-vsync"), (client,), fmt_id): {"action": "store_true", "help": "disable vsync", "required": False}, + (("v", "vm-arch"), (new,), fmt_id): {"metavar": "ARCH", "help": "VM architecture", "default": "dummy", "required": False, "type": str}, (("x", "cpp-compiler"), (client,), fmt_id): {"metavar": "CXX", "help": "C++ compiler to use", "default": "g++", "required": False, "type": str}, (("X", "cpp-compiler-flags"), (client,), fmt_id): {"metavar": "FLAGS", "help": "base set of flags to pass to C++ compiler", "default": "-Wall -Wextra -Werror -pedantic -std=c++20 -lstdc++", "required": False, "type": str}, (("y", "sync-pow"), (new,), fmt_id): {"metavar": "POW", "help": "core sync interval exponent; sync events occur every N steps, where N = 2^{POW}", "default": 20, "required": False, "type": pos}, @@ -103,6 +106,16 @@ for (name, sub_parsers, _), kwargs in options.items(): args = parser.parse_args() # ------------------------------------------------------------------------------ +# [section] run unit tests +# ------------------------------------------------------------------------------ +if args.command == "test": + test_runner = unittest.TextTestRunner(verbosity=2) + test_loader = unittest.TestLoader() + test_loader.testNamePatterns = [args.pattern] + test_runner.run(test_loader.discover("test")) + sys.exit(0) + +# ------------------------------------------------------------------------------ # [section] build class # ------------------------------------------------------------------------------ class Build: @@ -296,14 +309,14 @@ if args.command == "client": # ------------------------------------------------------------------------------ # [section] source architecture variables # ------------------------------------------------------------------------------ -arch_path = os.path.join("arch", args.arch, "vars.py") +arch_path = os.path.join("arch", args.vm_arch, "vars.py") log.info(f"Loading architecture variables from: {arch_path}") arch_vars = runpy.run_path(arch_path, init_globals=globals()) # ------------------------------------------------------------------------------ # [section] ancestor assembler # ------------------------------------------------------------------------------ -anc_path = os.path.join("anc", args.arch, f"{args.anc}.asm") +anc_path = os.path.join(args.anc_path, args.vm_arch, f"{args.anc}.asm") if not os.path.isfile(anc_path): raise RuntimeError(f"Could not find ancestor file: {anc_path}") @@ -337,11 +350,11 @@ log.info(f"Compiled ancestor file '{anc_path}' into byte array: {anc_repr}") # [section] compiler flags # ------------------------------------------------------------------------------ def pop_ui_vars(): - ns.ui_path = os.path.join("ui", args.ui, "vars.py") - ns.ui_vars = runpy.run_path(ns.ui_path, init_globals=globals()) - log.info(f"Sourced UI variables from: {ns.ui_path}") + ns.ui_vars_path = os.path.join(args.ui_path, args.ui, "vars.py") + ns.ui_vars = runpy.run_path(ns.ui_vars_path, init_globals=globals()) + log.info(f"Sourced UI variables from: {ns.ui_vars_path}") - ns.b.flags.add(f"-Iui/{args.ui}") + ns.b.flags.add(f"-I{args.ui_path}/{args.ui}") ns.b.flags.update({*ns.ui_vars["flags"]}) ns.b.defines.update({*ns.ui_vars["defines"]}) ns.b.links.update({*ns.ui_vars["links"]}) @@ -362,10 +375,10 @@ def pop_net_vars(): ns.b.links.add("-ljson-c") def pop_general(): - ns.b.flags.add(f"-Iarch/{args.arch}") + ns.b.flags.add(f"-Iarch/{args.vm_arch}") ns.b.flags.add("-Icore") - if args.muta_flip: + if arch_vars["muta_flip"]: ns.b.defines.add("-DMUTA_FLIP") if arch_vars["mvec_loop"]: @@ -374,7 +387,7 @@ def pop_general(): ns.b.defines.add(f"-DANC=\"{args.anc}\"") ns.b.defines.add(f"-DANC_BYTES={anc_repr}") ns.b.defines.add(f"-DANC_SIZE={len(anc_bytes)}") - ns.b.defines.add(f"-DARCH=\"{args.arch}\"") + ns.b.defines.add(f"-DARCH=\"{args.vm_arch}\"") ns.b.defines.add(f"-DAUTOSAVE_INTERVAL={2 ** args.auto_save_pow}ul") ns.b.defines.add(f"-DCLONES={args.clones}") ns.b.defines.add(f"-DCOMMAND_{args.command.upper()}") @@ -445,4 +458,6 @@ if args.command == "client": # [section] build and launch # ------------------------------------------------------------------------------ ns.b.build() -ns.b.exec() + +if not args.build_only: + ns.b.exec() diff --git a/test/anc/v1/noops.asm b/test/anc/v1/noops.asm new file mode 100644 index 0000000..77862c4 --- /dev/null +++ b/test/anc/v1/noops.asm @@ -0,0 +1,38 @@ +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/test_build.py b/test/test_build.py new file mode 100644 index 0000000..e0fecef --- /dev/null +++ b/test/test_build.py @@ -0,0 +1,80 @@ +import signal + +from test_general import SalisTest + +class TestBuild(SalisTest): + def cmds_new(self, anc, arch): + return ( + f"./salis.py new -a{anc} -b -f -g{compiler} -H{self.tempdir.name} {optimized} -s{seed} -u{ui} -v{arch}" + for compiler in ["clang", "gcc"] + for optimized in ["", "-o"] + for seed in [-1, 0, 1234] + for ui in ["curses", "daemon"] + ) + + def cmds_new_dummy(self): + return self.cmds_new("0123", "dummy") + + def cmds_new_v1(self): + return self.cmds_new("55a", "v1") + + def cmds_load(self): + return ( + f"./salis.py load -b -g{compiler} -H{self.tempdir.name} {optimized} -u{ui}" + for compiler in ["clang", "gcc"] + 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} {optimized}" + for compiler in ["clang", "gcc"] + for optimized in ["", "-o"] + ) + + def cmds_client(self): + return ( + f"./salis.py client -b -g{c_compiler} {optimized} -x{cxx_compiler}" + for c_compiler in ["clang", "gcc"] + for cxx_compiler in ["clang", "gcc"] + for optimized in ["", "-o"] + ) + + def test_dummy_new(self): + for cmd in self.cmds_new_dummy(): + SalisTest.run_subprocess(cmd) + + def test_v1_new(self): + for cmd in self.cmds_new_v1(): + SalisTest.run_subprocess(cmd) + + def test_dummy_load(self): + SalisTest.run_subprocess(next(self.cmds_new_dummy())) + + for cmd in self.cmds_load(): + SalisTest.run_subprocess(cmd) + + def test_v1_load(self): + SalisTest.run_subprocess(next(self.cmds_new_v1())) + + for cmd in self.cmds_load(): + SalisTest.run_subprocess(cmd) + + def test_server(self): + SalisTest.run_subprocess(next(self.cmds_new_dummy())) + + for cmd in self.cmds_server(): + SalisTest.run_subprocess(cmd) + + @SalisTest.run_ui_test(anc="0123", anc_path="anc", name="def.sim", ui="null", ui_path="test/ui", vm_arch="dummy") + def test_client(self): + with SalisTest.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(): + SalisTest.run_subprocess(cmd) + + server_proc.send_signal(signal.SIGINT) diff --git a/test/test_general.py b/test/test_general.py new file mode 100644 index 0000000..eb3185d --- /dev/null +++ b/test/test_general.py @@ -0,0 +1,31 @@ +import subprocess +import unittest + +from tempfile import TemporaryDirectory + +class SalisTest(unittest.TestCase): + def setUp(self): + self.tempdir = TemporaryDirectory(prefix="salis_test_") + + def tearDown(self): + self.tempdir.cleanup() + + @staticmethod + def run_subprocess(cmd): + subprocess.run(cmd.split(), check=True, stdout=subprocess.DEVNULL) + + @staticmethod + def run_pipe(cmd): + return subprocess.Popen(cmd.split(), stdout=subprocess.PIPE, text=True) + + @staticmethod + def run_ui_test(anc, anc_path, ui, ui_path, vm_arch, clones=1, cores=1, name="def.sim"): + def test_decorator(test_case): + def test_wrapper(self): + cmd = f"./salis.py new -a{anc} -A{anc_path} -C{clones} -c{cores} -H{self.tempdir.name} -n{name} -u{ui} -U{ui_path} -v{vm_arch}" + subprocess.run(cmd.split(), check=True, stdout=subprocess.DEVNULL) + test_case(self) + + return test_wrapper + + return test_decorator diff --git a/test/test_v1.py b/test/test_v1.py new file mode 100644 index 0000000..466e4bd --- /dev/null +++ b/test/test_v1.py @@ -0,0 +1,6 @@ +from test_general import SalisTest + +class TestV1(SalisTest): + @SalisTest.run_ui_test(anc="noops", anc_path="test/anc", ui="noops", ui_path="test/ui/v1", vm_arch="v1") + def test_ui_v1_noops(self): + pass diff --git a/test/ui/null/ui.c b/test/ui/null/ui.c new file mode 100644 index 0000000..5872342 --- /dev/null +++ b/test/ui/null/ui.c @@ -0,0 +1,10 @@ +int main(void) { +#if defined(COMMAND_NEW) + salis_init(); +#elif defined(COMMAND_LOAD) + salis_load(); +#endif + salis_save(SIM_PATH); + salis_free(); + return 0; +} diff --git a/test/ui/null/vars.py b/test/ui/null/vars.py new file mode 100644 index 0000000..9c2a9f3 --- /dev/null +++ b/test/ui/null/vars.py @@ -0,0 +1,3 @@ +flags = set() +defines = set() +links = set() diff --git a/test/ui/v1/noops/ui.c b/test/ui/v1/noops/ui.c new file mode 100644 index 0000000..230e98d --- /dev/null +++ b/test/ui/v1/noops/ui.c @@ -0,0 +1,114 @@ +#if !defined(COMMAND_NEW) +#error +#endif + +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 == 0); + + for (uint64_t i = 0; i < SYNC_INTERVAL; i++) { + assert(g_cores->ivav[i] == 0); + assert(g_cores->iviv[i] == 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[i] == 0); + assert(g_cores->beva[i] == 0); + } + + for (uint64_t i = 0; i < 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); + + for (uint64_t i = 0; i < MVEC_SIZE; i++) { + assert(g_cores->weva[i] == 0); + assert(g_cores->xeva[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); +} + +void check_variants(uint64_t step) { + assert(g_cores->cycl == step); + assert(g_cores->ivpt == step); + + assert(g_cores->emb0 == step); + + for (uint64_t i = 0; i < MVEC_SIZE; i++) { + assert(g_cores->eeva[i] == (i < step ? 1 : 0)); + } + + for (uint64_t i = 0; i < INST_COUNT; i++) { + uint64_t exed = 0; + + for (uint64_t j = 0; j < step; j++) { + if (mvec_get_inst(g_cores, j) == i) { + exed = 1; + } + } + + assert(g_cores->iexe[i] == exed); + } + + assert(g_cores->pvec->ip == step); + assert(g_cores->pvec->sp == step); +} + +void check_final(void) { + assert(g_cores->pvec->ip == ANC_SIZE); + assert(g_cores->pvec->sp == ANC_SIZE); +} + +int main(void) { + uint64_t step = 0; + + salis_init(); + check_invariants(); + check_variants(step); + + while (mvec_is_proc_owner(g_cores, g_cores->pvec->ip, g_cores->pcur)) { + salis_step(1); + step++; + + check_invariants(); + check_variants(step); + } + + check_final(); + salis_free(); + return 0; +} diff --git a/test/ui/v1/noops/vars.py b/test/ui/v1/noops/vars.py new file mode 100644 index 0000000..9c2a9f3 --- /dev/null +++ b/test/ui/v1/noops/vars.py @@ -0,0 +1,3 @@ +flags = set() +defines = set() +links = set() |
