diff --git a/.github/workflows/deploy-wasm.yml b/.github/workflows/deploy-wasm.yml index c47e6143..cf9915e5 100644 --- a/.github/workflows/deploy-wasm.yml +++ b/.github/workflows/deploy-wasm.yml @@ -9,10 +9,14 @@ on: workflow_dispatch: branches: - master + repository_dispatch: # listening to rv32emu-prebuilt events + types: [deploy_wasm] jobs: wasm-deploy: - if: github.event.pull_request.merged == true || github.event_name == 'workflow_dispatch' + if: github.event.pull_request.merged == true || + github.event_name == 'workflow_dispatch' || + github.event_name == 'repository_dispatch' runs-on: ubuntu-latest steps: - name: Check out the repo @@ -22,12 +26,20 @@ jobs: uses: tj-actions/changed-files@v45 with: files: | - assets/html/index.html - assets/js/pre.js + assets/wasm/html/index.html + assets/wasm/js/pre.js build/*.elf + tools/gen-elf-list-js.py + # Files below may have a potential performance impact (reference from benchmark.yml) + src/riscv.c + src/decode.c + src/emulate.c + src/rv32_template.c + src/rv32_constopt.c - name: install emcc if: ${{ steps.changed-files.outputs.any_modified == 'true' || - github.event_name == 'workflow_dispatch'}} + github.event_name == 'workflow_dispatch' || + github.event_name == 'repository_dispatch' }} run: | git clone https://github.com/emscripten-core/emsdk.git cd emsdk @@ -38,14 +50,25 @@ jobs: source ./emsdk_env.sh echo "$PATH" >> $GITHUB_PATH shell: bash + - name: fetch artifact + run: | + make artifact + # Hack Cloudflare 403 Forbidden on GitHub Runner for Doom artifact download + wget --header="User-Agent: Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:122.0) Gecko/20100101 Firefox/122.0" \ + --header="Referer: https://www.doomworld.com/" \ + --header="Accept-Language: en-US,en;q=0.9" \ + -O build/shareware_doom_iwad.zip \ + "https://www.doomworld.com/3ddownloads/ports/shareware_doom_iwad.zip" + unzip -d build/ build/shareware_doom_iwad.zip - name: build with emcc and move application files to /tmp if: ${{ steps.changed-files.outputs.any_modified == 'true' || - github.event_name == 'workflow_dispatch'}} + github.event_name == 'workflow_dispatch' || + github.event_name == 'repository_dispatch' }} run: | - make CC=emcc ENABLE_GDBSTUB=0 ENABLE_SDL=1 + make CC=emcc ENABLE_SDL=1 mkdir /tmp/rv32emu-demo - mv assets/html/index.html /tmp/rv32emu-demo - mv assets/js/coi-serviceworker.min.js /tmp/rv32emu-demo + mv assets/wasm/html/index.html /tmp/rv32emu-demo + mv assets/wasm/js/coi-serviceworker.min.js /tmp/rv32emu-demo mv build/elf_list.js /tmp/rv32emu-demo mv build/rv32emu.js /tmp/rv32emu-demo mv build/rv32emu.wasm /tmp/rv32emu-demo @@ -53,14 +76,16 @@ jobs: ls -al /tmp/rv32emu-demo - name: Check out the rv32emu-demo repo if: ${{ steps.changed-files.outputs.any_modified == 'true' || - github.event_name == 'workflow_dispatch'}} + github.event_name == 'workflow_dispatch' || + github.event_name == 'repository_dispatch' }} uses: actions/checkout@v4 with: persist-credentials: false # otherwise, the token used is the GITHUB_TOKEN, instead of your personal access token. repository: sysprog21/rv32emu-demo - name: Create local changes if: ${{ steps.changed-files.outputs.any_modified == 'true' || - github.event_name == 'workflow_dispatch'}} + github.event_name == 'workflow_dispatch' || + github.event_name == 'repository_dispatch' }} run: | mv /tmp/rv32emu-demo/index.html . mv /tmp/rv32emu-demo/coi-serviceworker.min.js . @@ -70,7 +95,8 @@ jobs: mv /tmp/rv32emu-demo/rv32emu.worker.js . - name: Commit files if: ${{ steps.changed-files.outputs.any_modified == 'true' || - github.event_name == 'workflow_dispatch'}} + github.event_name == 'workflow_dispatch' || + github.event_name == 'repository_dispatch' }} run: | git config --local user.email "github-actions[bot]@users.noreply.github.com" git config --local user.name "github-actions[bot]" @@ -78,7 +104,8 @@ jobs: git commit -m "Add changes" - name: Push changes if: ${{ steps.changed-files.outputs.any_modified == 'true' || - github.event_name == 'workflow_dispatch'}} + github.event_name == 'workflow_dispatch' || + github.event_name == 'repository_dispatch' }} uses: ad-m/github-push-action@master with: repository: sysprog21/rv32emu-demo diff --git a/assets/html/index.html b/assets/html/index.html deleted file mode 100644 index 5beae7e6..00000000 --- a/assets/html/index.html +++ /dev/null @@ -1,243 +0,0 @@ - - - - - - Emscripten-Generated Code - - - - - -
-
Downloading...
- - - Resize canvas - Lock/hide mouse pointer     - - - - - - - -
- -
- -
- -
- - - - - - - - diff --git a/assets/js/coi-serviceworker.min.js b/assets/js/coi-serviceworker.min.js deleted file mode 100644 index 117f9f89..00000000 --- a/assets/js/coi-serviceworker.min.js +++ /dev/null @@ -1,2 +0,0 @@ -/*! coi-serviceworker v0.1.7 - Guido Zuidhof and contributors, licensed under MIT */ -let coepCredentialless=!1;"undefined"==typeof window?(self.addEventListener("install",(()=>self.skipWaiting())),self.addEventListener("activate",(e=>e.waitUntil(self.clients.claim()))),self.addEventListener("message",(e=>{e.data&&("deregister"===e.data.type?self.registration.unregister().then((()=>self.clients.matchAll())).then((e=>{e.forEach((e=>e.navigate(e.url)))})):"coepCredentialless"===e.data.type&&(coepCredentialless=e.data.value))})),self.addEventListener("fetch",(function(e){const o=e.request;if("only-if-cached"===o.cache&&"same-origin"!==o.mode)return;const s=coepCredentialless&&"no-cors"===o.mode?new Request(o,{credentials:"omit"}):o;e.respondWith(fetch(s).then((e=>{if(0===e.status)return e;const o=new Headers(e.headers);return o.set("Cross-Origin-Embedder-Policy",coepCredentialless?"credentialless":"require-corp"),coepCredentialless||o.set("Cross-Origin-Resource-Policy","cross-origin"),o.set("Cross-Origin-Opener-Policy","same-origin"),new Response(e.body,{status:e.status,statusText:e.statusText,headers:o})})).catch((e=>console.error(e))))}))):(()=>{const e=window.sessionStorage.getItem("coiReloadedBySelf");window.sessionStorage.removeItem("coiReloadedBySelf");const o="coepdegrade"==e,s={shouldRegister:()=>!e,shouldDeregister:()=>!1,coepCredentialless:()=>!0,coepDegrade:()=>!0,doReload:()=>window.location.reload(),quiet:!1,...window.coi},r=navigator,t=r.serviceWorker&&r.serviceWorker.controller;t&&!window.crossOriginIsolated&&window.sessionStorage.setItem("coiCoepHasFailed","true");const i=window.sessionStorage.getItem("coiCoepHasFailed");if(t){const e=s.coepDegrade()&&!(o||window.crossOriginIsolated);r.serviceWorker.controller.postMessage({type:"coepCredentialless",value:!(e||i&&s.coepDegrade())&&s.coepCredentialless()}),e&&(!s.quiet&&console.log("Reloading page to degrade COEP."),window.sessionStorage.setItem("coiReloadedBySelf","coepdegrade"),s.doReload("coepdegrade")),s.shouldDeregister()&&r.serviceWorker.controller.postMessage({type:"deregister"})}!1===window.crossOriginIsolated&&s.shouldRegister()&&(window.isSecureContext?r.serviceWorker?r.serviceWorker.register(window.document.currentScript.src).then((e=>{!s.quiet&&console.log("COOP/COEP Service Worker registered",e.scope),e.addEventListener("updatefound",(()=>{!s.quiet&&console.log("Reloading page to make use of updated COOP/COEP Service Worker."),window.sessionStorage.setItem("coiReloadedBySelf","updatefound"),s.doReload()})),e.active&&!r.serviceWorker.controller&&(!s.quiet&&console.log("Reloading page to make use of COOP/COEP Service Worker."),window.sessionStorage.setItem("coiReloadedBySelf","notcontrolling"),s.doReload())}),(e=>{!s.quiet&&console.error("COOP/COEP Service Worker failed to register:",e)})):!s.quiet&&console.error("COOP/COEP Service Worker not registered, perhaps due to private mode."):!s.quiet&&console.log("COOP/COEP Service Worker not registered, a secure context is required."))})(); \ No newline at end of file diff --git a/assets/js/pre.js b/assets/js/pre.js deleted file mode 100644 index c541967e..00000000 --- a/assets/js/pre.js +++ /dev/null @@ -1,9 +0,0 @@ -Module['noInitialRun'] = true; -Module['onRuntimeInitialized'] = function(target_elf) { - if(target_elf === undefined){ - console.warn("target elf executable is undefined"); - return; - } - - callMain([target_elf]); -}; diff --git a/mk/wasm.mk b/mk/wasm.mk index 4785f7c0..cf4d2c9e 100644 --- a/mk/wasm.mk +++ b/mk/wasm.mk @@ -6,8 +6,8 @@ WEB_JS_RESOURCES := $(ASSETS)/js EXPORTED_FUNCS := _main,_indirect_rv_halt DEMO_DIR := demo WEB_FILES := $(BIN).js \ - $(BIN).wasm \ - $(BIN).worker.js \ + $(BIN).wasm \ + $(BIN).worker.js \ $(OUT)/elf_list.js ifeq ("$(CC_IS_EMCC)", "1") @@ -29,10 +29,19 @@ CFLAGS_emcc += -sINITIAL_MEMORY=2GB \ -s"EXPORTED_FUNCTIONS=$(EXPORTED_FUNCS)" \ -sSTACK_SIZE=4MB \ -sPTHREAD_POOL_SIZE=navigator.hardwareConcurrency \ - --embed-file build@/ \ + --embed-file build/jit-bf.elf@/jit-bf.elf \ + --embed-file build/coro.elf@/coro.elf \ + --embed-file build/fibonacci.elf@/fibonacci.elf \ + --embed-file build/hello.elf@/hello.elf \ + --embed-file build/ieee754.elf@/ieee754.elf \ + --embed-file build/perfcount.elf@/perfcount.elf \ + --embed-file build/readelf.elf@/readelf.elf \ + --embed-file build/smolnes.elf@/smolnes.elf \ --embed-file build/riscv32@/riscv32 \ + --embed-file build/DOOM1.WAD@/DOOM1.WAD \ + --embed-file build/id1/pak0.pak@/id1/pak0.pak \ --embed-file build/timidity@/etc/timidity \ - -DMEM_SIZE=0x40000000 \ + -DMEM_SIZE=0x60000000 \ -DCYCLE_PER_STEP=2000000 \ --pre-js $(WEB_JS_RESOURCES)/pre.js \ -O3 \ diff --git a/src/emulate.c b/src/emulate.c index 30474c35..31656966 100644 --- a/src/emulate.c +++ b/src/emulate.c @@ -1175,6 +1175,7 @@ void rv_step(void *arg) if (rv_has_halted(rv)) { emscripten_cancel_main_loop(); rv_delete(rv); /* clean up and reuse memory */ + rv_log_info("RISC-V emulator is destroyed"); } #endif } diff --git a/src/riscv.c b/src/riscv.c index 61d95d2d..1ddaf235 100644 --- a/src/riscv.c +++ b/src/riscv.c @@ -615,7 +615,6 @@ void rv_run(riscv_t *rv) attr->data.user.elf_program #endif ); - attr->cycle_per_step = 100000000; if (!(attr->run_flag & (RV_RUN_TRACE | RV_RUN_GDBSTUB))) { #ifdef __EMSCRIPTEN__ diff --git a/tools/gen-elf-list-js.py b/tools/gen-elf-list-js.py index 05e082a1..213b2259 100755 --- a/tools/gen-elf-list-js.py +++ b/tools/gen-elf-list-js.py @@ -2,32 +2,55 @@ import os -def list_files(d): + +def list_files(d, ignore_list=None): + if ignore_list is None: + ignore_list = [] try: if d == "build": - files = [f for f in os.listdir(d) if (os.path.isfile(os.path.join(d, f)) and f.endswith('.elf'))] + files = [ + f + for f in os.listdir(d) + if os.path.isfile(os.path.join(d, f)) + and f.endswith(".elf") + and not any(f.endswith(ign) or f.startswith(ign) for ign in ignore_list) + ] else: parent_dir = os.path.dirname(d) files = [ os.path.relpath(os.path.join(d, f), start=parent_dir) for f in os.listdir(d) if os.path.isfile(os.path.join(d, f)) + and not any( + f.endswith(ign) or os.path.join(d, f).endswith(ign) + for ign in ignore_list + ) ] return files except FileNotFoundError: - print(f"Directory {directory} not found.") + print(f"Directory {d} not found.") return [] + elf_exec_dirs = ["build", "build/riscv32"] +msg_less_ignore_files = [ + "cc.elf", + "chacha20.elf", + "riscv32/lena", + "riscv32/puzzle", + "riscv32/line", + "riscv32/captcha", +] # List of files to ignore elf_exec_list = [] for d in elf_exec_dirs: - files = list_files(d) + files = list_files(d, ignore_list=msg_less_ignore_files) elf_exec_list.extend(files) -#print(elf_exec_list) + def gen_elf_list_js(): js_code = f"const elfFiles = {elf_exec_list};\n" print(js_code) + gen_elf_list_js()