From 94a3d31b5564b9557d531fcc709f94931ae28fab Mon Sep 17 00:00:00 2001 From: ChinYikMing Date: Wed, 26 Feb 2025 01:18:07 +0800 Subject: [PATCH 1/3] CI: Fix deploy-wasm trigger condition The potential performance effect files are not tracked when deploying Wasm, so they are now added to the file detection list. Additionally, the repository_workflow event is now being listened to since most ELF files are built and stored in the rv32emu-prebuilt repository. When a release is published in rv32emu-prebuilt, it triggers the repository_workflow event in rv32emu to deploy Wasm via Github REST api( see the workflow of rv32emu-prebuilt), ensuring that new ELF or Linux images are properly synced. Close #505 --- .github/workflows/deploy-wasm.yml | 51 +++++++++++++++++++++++-------- 1 file changed, 39 insertions(+), 12 deletions(-) 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 From 667a4faa35afa457b0ee4336afb88f1b6a481dfc Mon Sep 17 00:00:00 2001 From: ChinYikMing Date: Wed, 26 Feb 2025 01:20:02 +0800 Subject: [PATCH 2/3] Tweak emcc CFLAGS The build directory has a build dependency file (.o.d), SHA checksum file of prebuilt artifact and else which are useless for WASM execution. Additionally, these files increase the size of WASM, leading to longer download time for WASM. Thus, only embed mandatory artifacts when build. Enlarge the MEM_SIZE to make all ELF runnable. --- mk/wasm.mk | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/mk/wasm.mk b/mk/wasm.mk index 4785f7c0..3e677f13 100644 --- a/mk/wasm.mk +++ b/mk/wasm.mk @@ -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 \ From c429166e964b78691721fa7af412647fba7f4590 Mon Sep 17 00:00:00 2001 From: ChinYikMing Date: Wed, 26 Feb 2025 01:29:49 +0800 Subject: [PATCH 3/3] Miscellaneous changes - cycle_per_step is hooked by build variable CYCLE_PER_STEP, so hard-coded is not needed. - emscripten_cancel_main_loop is done in src/emulate.c, so show the terminating log at there too. - Drop redundant WASM assets. - Add ignore list and apply Black formatter for tools/gen-elf-list-js.py. --- assets/html/index.html | 243 ----------------------------- assets/js/coi-serviceworker.min.js | 2 - assets/js/pre.js | 9 -- mk/wasm.mk | 4 +- src/emulate.c | 1 + src/riscv.c | 1 - tools/gen-elf-list-js.py | 33 +++- 7 files changed, 31 insertions(+), 262 deletions(-) delete mode 100644 assets/html/index.html delete mode 100644 assets/js/coi-serviceworker.min.js delete mode 100644 assets/js/pre.js 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 3e677f13..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") 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()