Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Run rv32emu inside web browser via WebAssembly translation #75

Closed
jserv opened this issue Oct 20, 2022 · 49 comments
Closed

Run rv32emu inside web browser via WebAssembly translation #75

jserv opened this issue Oct 20, 2022 · 49 comments
Assignees

Comments

@jserv
Copy link
Contributor

jserv commented Oct 20, 2022

iamlouk/riscv64-sim is written in C and capable of being translated into WebAssembly. Check its web demo. Some web-based (open source) RISC-V simulations:

The goal of this task is to expand rv32emu to the simulator, which will be used to teach computer architecture fundamentals, based on the existing RISC-V codebase.
Incomplete attempt: rv32emu-wasm

@jserv
Copy link
Contributor Author

jserv commented Dec 10, 2022

We might need RISC-V instruction decoder for web-based execution. See rvcodec.js: an online encoder/decoder for RISC-V instructions

@jserv
Copy link
Contributor Author

jserv commented Jul 21, 2023

Recent rv32emu relies on tail-call optimization (TCO), which causes build problems with Emscripten. Thus, we have to turn it off. Apply the following changes:

diff --git a/src/common.h b/src/common.h
index 62b66bd..374bcf3 100644
--- a/src/common.h
+++ b/src/common.h
@@ -43,7 +43,7 @@
  * around this, the compiler attribute 'musttail' is used, which forces TCO
  * even without optimizations enabled.
  */
-#if defined(__has_attribute) && __has_attribute(musttail)
+#if defined(__has_attribute) && __has_attribute(musttail) && !defined(__wasm__)
 #define MUST_TAIL __attribute__((musttail))
 #else
 #define MUST_TAIL
diff --git a/src/io.c b/src/io.c
index 5d7a37d..f3de262 100644
--- a/src/io.c
+++ b/src/io.c
@@ -17,8 +17,8 @@
 #include "io.h"
 
 static uint8_t *data_memory_base;
-/* set memory size to 2^32 bytes */
-#define MEM_SIZE 0x100000000ULL
+/* set memory size to 2^31 bytes */
+#define MEM_SIZE 0x10000000ULL
 
 memory_t *memory_new()
 {

Then, build this project via emcc:

make CC=emcc ENABLE_SDL=0 ENABLE_GDBSTUB=0

build/rv32emu.wasm should be generated.

See Tail Call Extension

@ChinYikMing
Copy link
Collaborator

I am going to study and solve this issue. May I know if the original assignee still working on it?

@jserv jserv assigned ChinYikMing and unassigned steven1lung Dec 13, 2023
@jserv
Copy link
Contributor Author

jserv commented Dec 13, 2023

I am going to study and solve this issue. May I know if the original assignee still working on it?

Go ahead!

@ChinYikMing
Copy link
Collaborator

ChinYikMing commented Dec 16, 2023

Tail call optimization(TCO) is supported by Chrome (version 112) natively, see roadmap of webassembly. If tail call optimization is enabled during the build, only Chrome can run the wasm. So, Chrome will be the main experimental runtime environment to adapt TCO for now.

@jserv
Copy link
Contributor Author

jserv commented Dec 16, 2023

Tail call optimization is supported by Chrome (version 112) natively, see roadmap of webassembly. Thus, if tail call optimization is enabled during the build, only Chrome can run the wasm.

It is reasonably acceptable to restrict the WebAssembly runtime environments, given that the WebAssembly-built rv32emu is highly experimental.

@jserv
Copy link
Contributor Author

jserv commented Dec 16, 2023

After the initial WebAssembly build (#293), we can proceed with the following action items:

  1. Create an HTML page, which we could potentially host on GitHub Pages, to enable the WebAssembly-built rv32emu to run sample RISC-V ELF files. We will also need a web-based console for stdout.
  2. Ensure that RV32-built video games such as Doom and Quake can run on the Chrome web browser in the form of WebAssembly.
  3. (Optional) Implement single-stepping execution, along with web-based register and internal state displays, similar to what Riples provides. This would be a valuable addition.

@ChinYikMing
Copy link
Collaborator

ChinYikMing commented Dec 22, 2023

Suppress the warning that generated when exporting functions from the same translation unit of the main function (e.g., print_usage) but the main function is not exported, see issue(fixed)

@ChinYikMing
Copy link
Collaborator

ChinYikMing commented Dec 23, 2023

  1. Create an HTML page, which we could potentially host on GitHub Pages, to enable the WebAssembly-built rv32emu to run sample RISC-V ELF files. We will also need a web-based console for stdout.

This wasm branch has attempted to support this. Try it out by following the README.

It requires some source code modifications to work:

  1. Remove static modifier from MEMIO in src/main.c. So that, the translation unit of main.c (main.o) can export the functions.
  2. Allocate required memory size using pass by value because WebAssembly's page size is 64KiB thus default memory size MEM_SIZE(2^32 - 1) can not be applied. In order to fix this, I propose that declare a mem_size parameter in state_new function and this parameter is passed to memory_new function in further. Note that rv32emu can still using MEM_SIZE outside the web.

The following are the main changes:

  • src/main.c
--- a/src/main.c
+++ b/src/main.c
@@ -44,7 +44,7 @@ static bool opt_misaligned = false;

 #define MEMIO(op) on_mem_##op
 #define IO_HANDLER_IMPL(type, op, RW)                                     \
-    static IIF(RW)(                                                       \
+    IIF(RW)(                                                       \
         /* W */ void MEMIO(op)(riscv_word_t addr, riscv_##type##_t data), \
         /* R */ riscv_##type##_t MEMIO(op)(riscv_word_t addr))            \
     {                                                                     \
@@ -222,7 +222,7 @@ int main(int argc, char **args)
         .allow_misalign = opt_misaligned,
     };

-    state_t *state = state_new();
+    state_t *state = state_new(MEM_SIZE);

     /* find the start of the heap */
     const struct Elf32_Sym *end;
  • src/riscv.h
--- a/src/riscv.h
+++ b/src/riscv.h
@@ -222,7 +222,7 @@ typedef struct {
 } state_t;

 /* create a state */
-state_t *state_new(void);
+state_t *state_new(uint32_t mem_size);

 /* delete a state */
 void state_delete(state_t *s);
  • src/riscv.c
--- a/src/riscv.c
+++ b/src/riscv.c
@@ -294,11 +294,11 @@ void rv_reset(riscv_t *rv, riscv_word_t pc, int argc, char **args)
     rv->halt = false;
 }

-state_t *state_new(void)
+state_t *state_new(uint32_t mem_size)
 {
     state_t *s = malloc(sizeof(state_t));
     assert(s);
-    s->mem = memory_new();
+    s->mem = memory_new(mem_size);
     s->break_addr = 0;

     s->fd_map = map_init(int, FILE *, map_cmp_int);
  • src/io.h
--- a/src/io.h
+++ b/src/io.h
@@ -8,16 +8,23 @@
 #include <stdint.h>
 #include <string.h>

-/* Directly map a memory with a size of 2^32 bytes. All memory read/write
- * operations can access this memory through the memory subsystem.
+/*
+ * set memory size to 2^32 - 1 bytes
+ *
+ * The memory size is set to 2^32 - 1 bytes in order to make this emulator
+ * portable for both 32-bit and 64-bit platforms. As a result, it can access
+ * any segment of the memory on either platform. Furthermore, it is safe
+ * because most of the test cases' data memory usage will not exceed this
+ * memory size.
  */
+#define MEM_SIZE 0xFFFFFFFFULL

 typedef struct {
     uint8_t *mem_base;
     uint64_t mem_size;
 } memory_t;

-memory_t *memory_new(void);
+memory_t *memory_new(uint32_t mem_size);
 void memory_delete(memory_t *m);

 /* read a C-style string from memory */
  • src/io.c
--- a/src/io.c
+++ b/src/io.c
@@ -17,44 +17,33 @@

 static uint8_t *data_memory_base;

-/*
- * set memory size to 2^32 - 1 bytes
- *
- * The memory size is set to 2^32 - 1 bytes in order to make this emulator
- * portable for both 32-bit and 64-bit platforms. As a result, it can access
- * any segment of the memory on either platform. Furthermore, it is safe
- * because most of the test cases' data memory usage will not exceed this
- * memory size.
- */
-#define MEM_SIZE 0xFFFFFFFFULL
-
-memory_t *memory_new(void)
+memory_t *memory_new(uint32_t mem_size)
 {
     memory_t *mem = malloc(sizeof(memory_t));
     assert(mem);
 #if HAVE_MMAP
-    data_memory_base = mmap(NULL, MEM_SIZE, PROT_READ | PROT_WRITE,
+    data_memory_base = mmap(NULL, mem_size, PROT_READ | PROT_WRITE,
                             MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
     if (data_memory_base == MAP_FAILED) {
         free(mem);
         return NULL;
     }
 #else
-    data_memory_base = malloc(MEM_SIZE);
+    data_memory_base = malloc(mem_size);
     if (!data_memory_base) {
         free(mem);
         return NULL;

@ChinYikMing
Copy link
Collaborator

ChinYikMing commented Dec 23, 2023

Is it feasible for me to host the relevant porting files (such as HTML, JS files, etc.) and then rv32emu submodule for them? So that, rv32emu can adapt to different porting implementation.

I am not sure if an HTML submodule may be hosted on a github page.

@jserv
Copy link
Contributor Author

jserv commented Dec 24, 2023

Is it feasible for me to host the relevant porting files (such as HTML, JS files, etc.) and then rv32emu submodule for them? So that, rv32emu can adapt to different porting implementation.

I think so. Take Ripes for example. There are two directories resources and appdir preserving resources files.

I am not sure if an HTML submodule may be hosted on a github page.

We can follow the approach of rv32emu-bench.

@jserv
Copy link
Contributor Author

jserv commented Dec 24, 2023

This wasm branch has attempted to support this. Try it out by following the README.
It requires some source code modifications to work:

  1. Remove static modifier from MEMIO in src/main.c. So that, the translation unit of main.c (main.o) can export the functions.

Reflecting on the feedback from the wasm branch, it seems appropriate to refine the APIs in the src/riscv.h header. The focus should be on achieving a higher level of abstraction by integrating detailed components like memory, state, and I/O into a more unified API structure. For inspiration on creating a clean and elegant C API for executing RISC-V programs, consider examining the approach used by libriscv.

Last year, when developing semu, I improved the APIs to make them cleaner. The riscv.h header was designed to abstract the virtual machine's internals, avoiding explicit cross-references among several implementation-focused headers. Now, I believe it is time to apply a similar approach to the rv32emu project. Without this evolution, rv32emu continually faces challenges in adapting to various runtime environments.

If you are in agreement with the statement I've made, let's proceed by gradually refining our existing public headers. The aim is to enhance encapsulation while ensuring there are no disruptions to functionality.

@ChinYikMing
Copy link
Collaborator

Is it feasible for me to host the relevant porting files (such as HTML, JS files, etc.) and then rv32emu submodule for them? So that, rv32emu can adapt to different porting implementation.

I think so. Take Ripes for example. There are two directories resources and appdir preserving resources files.

I am not sure if an HTML submodule may be hosted on a github page.

We can follow the approach of rv32emu-bench.

To sum up, the Github page deployment will be a repository with two submodules: "wasm and corresponding glue js"(generated by emcc and hosted in sysprog21 organization) and "wasm porting implemention"(hosted in my personal repository). Some CI might be needed to automate the build and store actions.

@ChinYikMing
Copy link
Collaborator

ChinYikMing commented Dec 24, 2023

Reflecting on the feedback from the wasm branch, it seems appropriate to refine the APIs in the src/riscv.h header. The focus should be on achieving a higher level of abstraction by integrating detailed components like memory, state, and I/O into a more unified API structure. For inspiration on creating a clean and elegant C API for executing RISC-V programs, consider examining the approach used by libriscv.

Last year, when developing semu, I improved the APIs to make them cleaner. The riscv.h header was designed to abstract the virtual machine's internals, avoiding explicit cross-references among several implementation-focused headers. Now, I believe it is time to apply a similar approach to the rv32emu project. Without this evolution, rv32emu continually faces challenges in adapting to various runtime environments.

If you are in agreement with the statement I've made, let's proceed by gradually refining our existing public headers. The aim is to enhance encapsulation while ensuring there are no disruptions to functionality.

I agree with that the the RISC-V APIs should have higher level of abstraction. Consequently, they could be easily ported to multiple platforms (e.g., desktop) or maintained. I will try to investigate the abstraction of APIs from libriscv and semu for further discussion.

@jserv
Copy link
Contributor Author

jserv commented Dec 24, 2023

To sum up, the Github page deployment will be a repository with two submodules: "wasm and corresponding glue js"(generated by emcc and hosted in sysprog21 organization) and "wasm porting implemention"(hosted in my personal repository). Some CI might be needed to automate the build and store actions.

Consider awtk as another example - it is a window widget set written in C that also supports a web-based runtime through awtk-web. In the future, with the integration of semu's developments into rv32emu, we should be capable of hosting an online emulator akin to RVVM.

@jserv
Copy link
Contributor Author

jserv commented Dec 25, 2023

This wasm branch has attempted to support this. Try it out by following the README.

Test environment: macOS 14.2.1 + Apple Silicon (M1)

I have installed emcc via Homebrew.

$ emcc --version | head -1
emcc (Emscripten gcc/clang-like replacement + linker emulating GNU ld) 3.1.50-git

After executing make CC=emcc ENABLE_SDL=0 ENABLE_GDBSTUB=0, I got the following messages:

wasm-ld: error: unknown argument: -no_warn_duplicate_libraries

The issue was caused by my error in toolchain configuration detection, and I will fix it later.

After quick fix, both Drystone and CoreMark run inside Chrome browser. Current rv32emu/wasm performance:

  • Dhrystone: 82 DMIPS
  • CoreMark: 134 iter/s

RVVM:

  • CoreMark: 366 iter/s

@ChinYikMing
Copy link
Collaborator

ChinYikMing commented Dec 25, 2023

Test environment: macOS 14.2.1 + Apple Silicon (M1)
[...] both Drystone and CoreMark run inside Chrome browser. Current rv32emu/wasm performance:

  • Dhrystone: 82 DMIPS
  • CoreMark: 134 iter/s
    RVVM:
  • CoreMark: 366 iter/s

WebAssembly performance might be tuned after the basic simulation(e.g., sample ELF and Doom & Quake video game) are done.

@ChinYikMing
Copy link
Collaborator

ChinYikMing commented Dec 26, 2023

In order to satisfy the browser's event model, the wasm branch supported cooperative multitasking mode. Try it out at demo here(only runable in Chrome). Run "ieee754.elf" to observe a notable change. The line prints out while the program is executing rather than flushing the entire buffer once the run is complete(in other words, update DOM as soon as possible). This can increase the interaction between the user and program.

This change requires some modification of source code since it leverages the APIs of Emscripten (e.g., __EMSCRIPTEN__ predefined macro, emscripten_set_main_loop_arg, emscripten_cancel_main_loop, see commit). Is it possible for them to be added to the main branch afterwards? Actually, I am still trying to figure out how to keep the source code unchanged.

@ChinYikMing
Copy link
Collaborator

ChinYikMing commented Jan 4, 2024

  1. Ensure that RV32-built video games such as Doom and Quake can run on the Chrome web browser in the form of WebAssembly.

Shooting games like Doom and Quake may now be rendered on a web browser, however the frame rate is low(see demo). I will investigate more after sound system is set up successfully because the failure of initialization of sound system will make rv32emu exit early. see issue.

@ChinYikMing
Copy link
Collaborator

Tail call optimization(TCO) is supported by Chrome (version 112) natively, see roadmap of webassembly. If tail call optimization is enabled during the build, only Chrome can run the wasm. So, Chrome will be the main experimental runtime environment to adapt TCO for now.

Firefox version 121 supports TCO, so both Chrome and Firefox can be the experimental runtime environment now.

@ChinYikMing
Copy link
Collaborator

ChinYikMing commented Jan 6, 2024

  1. Ensure that RV32-built video games such as Doom and Quake can run on the Chrome web browser in the form of WebAssembly.

Shooting games like Doom and Quake may now be rendered on a web browser, however the frame rate is low(see demo). I will investigate more after sound system is set up successfully because the failure of initialization of sound system will make rv32emu exit early. see issue.

As I tweaking the cycle_per_step to 2000000, Doom and Quake run more smoothly than before. Sound system is set up successfully by linking the ported SDL library correctly. The sound are played by Timidity and the sound effect is decent in Quake but not very nice(especially on pistol sound effect) in Doom (maybe will try FluidSynth).

A small changes have to be applied to sound system calls(in "src/syscall_sdl.c"):

static void play_sfx(riscv_t *rv)
{
    ...
    pthread_create(&sfx_thread, NULL, sfx_handler, &sfx);
+#ifdef __EMSCRIPTEN__
+   pthread_join(sfx_thread, NULL);
+#endif
}

static void play_music(riscv_t *rv)
{
    ...
    pthread_create(&music_thread, NULL, music_handler, &music);
+#ifdef __EMSCRIPTEN__
+   pthread_join(music_thread, NULL);
+#endif
}

I found that emcc compiled web workers are not reused, so adding pthread_join makes them reusable. Otherwise, will get error: Tried to spawn a new thread, but the thread pool is exhausted. After applying this patch, the browser would suggest that blocking main thread(calling pthread_join) is dangerous, but it is safe actually since the sfx_handler and music_handler do not contain any blocking call.

Demo:

Note that due to the large size of the WASM file, the loading may take some time. I might rewrite the UI for noticing that the loading process (maybe a loading bar indicator). Also, please click the canvas to trigger the Web Audio API.

Next, I will focus on design, discuss and refactor riscv.[ch] and io.[ch] API for easier porting to different runtime.

@ChinYikMing
Copy link
Collaborator

we could potentially host on GitHub Pages

Multithreading in Emscripten requires SharedArrayBuffer. To allow the browser to support "SharedArrayBuffer", we have to add custom response headers: "Cross-Origin-Opener-Policy" and "Cross-Origin-Embedder-Policy", see security requirements. Moreover, it is necessary for the server to have an active SSL certificate for the browser to enable "SharedArrayBuffer".

Due to the limitation for the customization of github pages response headers (maybe fixed by this blog but seems cumbersome), github pages is not a suitable place to serve multithreading applications like Quake and Doom but suitable for those sample ELF executable which does not require multithreading. Thus, I believe a better way is that having a dedicated server with an active SSL certificate and the ability to set custom response headers to serve both multithreading and non-multithreading WebAssembly applications.

@ChinYikMing
Copy link
Collaborator

ChinYikMing commented Jan 13, 2024

rv32emu public APIs might be refactored over the time, writing all exported rv32emu public APIs in Makefile(see EXPORTED_FUNCTIONS in Makefile) is not an ideal choice since keep updating Makefile to adapt new rv32emu public API is weird. Instead, we can create a file to store all exported rv32emu public APIs and make emcc link to it during compile time. It is sufficient to edit the file in order to create a new rv32emu public API. See configs of awtk-web.

@jserv
Copy link
Contributor Author

jserv commented Mar 25, 2024

JIT compilers which can generate WebAssembly:

@ChinYikMing
Copy link
Collaborator

ChinYikMing commented Mar 26, 2024

Since #385 is merged, we can move forward to deploy wasm application on GitHub Pages.

Shall we host on rv32emu upstream's master or other branch? I am prefer other branch since the root directory of GitHub Pages are limited to "/docs" or "/" and we might not want to mess master branch.

@jserv
Copy link
Contributor Author

jserv commented Mar 26, 2024

Shall we host on rv32emu upstream's master or other branch? I am prefer other branch since the root directory of GitHub Pages are limited to "/docs" or "/" and we might not want to mess master branch.

I created a repository, rv32emu-demo, and specify @ChinYikMing as the administrator. Please follow the way how rv32emu-bench works.

@ChinYikMing
Copy link
Collaborator

ChinYikMing commented Mar 26, 2024

Shall we host on rv32emu upstream's master or other branch? I am prefer other branch since the root directory of GitHub Pages are limited to "/docs" or "/" and we might not want to mess master branch.

I created a repository, rv32emu-demo, and specify @ChinYikMing as the administrator. Please follow the way how rv32emu-bench works.

I would like to leverage a GitHub action workflow to deploy wasm application to rv32emu-demo.

The GitHub action workflow plan: detect if assests/html/index.html or assets/js/pre.js is modified after a pull request merged. If yes, build and deploy new wasm application to rv32emu-demo. If these two files are not modified and we want to deploy manually, we can use the workflow_dispatch. Consequently, rv32emu-demo would be updated with latest code base.

ChinYikMing added a commit to ChinYikMing/rv32emu that referenced this issue Mar 27, 2024
To deploy multithreading wasm on Github Pages, we have to make the
server to response two headers which are "Cross-Origin-Opener-Policy"
and "Cross-Origin-Embedder-Policy". Since we cannot directly control
the response headers of the Github Pages, coi-serviceworker comes to
help.

Related: sysprog21#75
ChinYikMing added a commit to ChinYikMing/rv32emu that referenced this issue Mar 27, 2024
Since wasm is deployed on Github Pages, thus it is reasonable to use CI
to deploy automatically.

The CI supports two event: merged pull request and workflow_dispatch.
The former only run after merging and latter is used to deploy by
maintainer manually. It also verifies whether any associated files
have changed. If so, carry out the CI; if not, stop.

Related: sysprog21#75
ChinYikMing added a commit to ChinYikMing/rv32emu that referenced this issue Apr 7, 2024
ELF executables might be rebuilt when new features are supported by the
rv32emu such as new SDL-related system calls for video games like Doom
and Quake or newlib has been updated.

Close: sysprog21#405
See also: sysprog21#75
ChinYikMing added a commit to ChinYikMing/rv32emu that referenced this issue Apr 7, 2024
ELF executables might be rebuilt when new features are supported by the
rv32emu such as new SDL-related system calls for video games like Doom
and Quake or newlib has been updated. ELF executables are also might be
deleted.

Change filter from "any_changed" to "any_modified" since the latter
includes delete event and this can ensure that deleted ELF executables
do not appear in the demo page.

Close: sysprog21#405
See also: sysprog21#75
@ChinYikMing
Copy link
Collaborator

ChinYikMing commented Apr 7, 2024

So far as I know, there are two main ways to execute WebAssembly programs, one is JavaScript interpreter (NodeJS or Browser JS engine), second is wasm interpreter (e.g., wasmtime).
I think you want the least dependency for deployment?

Identifying web browsers like Chrome as necessary for running Emscripten-generated programs is practical. My aim is to establish a straightforward setup for those interested in exploring WebAssembly translation within common macOS or GNU/Linux environments.

Since "coi-serviceworker.js" solves the security response headers issue, we could temporarily require a specific version of Chrome installed and provide a Makefile target to host the WebAssembly in local environment without any headache configuration of web servers.

@jserv
Copy link
Contributor Author

jserv commented Apr 7, 2024

Since "coi-serviceworker.js" solves the security response headers issue, we could temporarily require a specific version of Chrome installed and provide a Makefile target to host the WebAssembly in local environment without any headache configuration of web servers.

Can you detect the vendors and versions of web browsers, so that we can ensure TCO is supported?

@ChinYikMing
Copy link
Collaborator

Since "coi-serviceworker.js" solves the security response headers issue, we could temporarily require a specific version of Chrome installed and provide a Makefile target to host the WebAssembly in local environment without any headache configuration of web servers.

Can you detect the vendors and versions of web browsers, so that we can ensure TCO is supported?

Yes, according to the supported Feature Extensions of WebAssembly in each popular web browser, we can detect the MAJOR version of web browsers which support the TCO. For example, Chrome with MAJOR 112 and Firefox with MAJOR 121 supports TCO.

@jserv
Copy link
Contributor Author

jserv commented Apr 8, 2024

according to the supported Feature Extensions of WebAssembly in each popular web browser, we can detect the MAJOR version of web browsers which support the TCO. For example, Chrome with MAJOR 112 and Firefox with MAJOR 121 supports TCO.

It sounds great. Please send pull request(s) which detects TCO support and decides if the wasm programs should be loaded or not.

ChinYikMing added a commit to ChinYikMing/rv32emu that referenced this issue Apr 8, 2024
To enhance the user experience of using WebAssembly version of rv32emu,
we shall provide a Makefile target (serve-wasm) to serve the WebAssembly
demo page in an easy way.

Since rv32emu leverages TCO (tail call optimization) when being compiled,
so we have to tell if the user's browser supports TCO. Currently, only
Chrome with MAJOR 112 and Firefox with MAJOR 121 supports TCO execution
runtime, thus we focus on this two browsers. Also, use color text to
remind the users if they need to update their Chrome or Firefox.

See also: sysprog21#75
ChinYikMing added a commit to ChinYikMing/rv32emu that referenced this issue Apr 8, 2024
To enhance the user experience of using WebAssembly version of rv32emu,
we shall provide a Makefile target (serve-wasm) to serve the WebAssembly
demo page in an easy way.

Since rv32emu leverages TCO (tail call optimization) when being compiled,
so we have to tell if the user's browser supports TCO. Currently, only
Chrome with MAJOR 112 and Firefox with MAJOR 121 supports TCO execution
runtime, thus we focus on this two browsers. Also, use color text to
remind the users if they need to update their Chrome or Firefox.

See also: sysprog21#75
ChinYikMing added a commit to ChinYikMing/rv32emu that referenced this issue Apr 8, 2024
To enhance the user experience of using WebAssembly version of rv32emu,
we shall provide a Makefile target (start-web) to serve the WebAssembly
demo page in an easy way.

Since rv32emu leverages TCO (tail call optimization) when being compiled,
so we have to tell if the user's browser supports TCO. Currently, only
Chrome with MAJOR 112 and Firefox with MAJOR 121 supports TCO execution
runtime, thus we focus on this two browsers. Also, use color text to
remind the users if they need to update their Chrome or Firefox.

See also: sysprog21#75
ChinYikMing added a commit to ChinYikMing/rv32emu that referenced this issue Apr 9, 2024
To enhance the user experience of using WebAssembly version of rv32emu,
we shall provide a Makefile target (serve-wasm) to serve the WebAssembly
demo page in an easy way.

Since rv32emu leverages TCO (tail call optimization) when being compiled,
so we have to tell if the user's browser supports TCO. Currently, only
Chrome with MAJOR 112 and Firefox with MAJOR 121 supports TCO execution
runtime, thus we focus on this two browsers. Also, use color text to
remind the users if they need to update their Chrome or Firefox.

See also: sysprog21#75
@jserv jserv added this to the release-2024.1 milestone Apr 30, 2024
@jserv
Copy link
Contributor Author

jserv commented Apr 30, 2024

This task is considered completed.

@jserv jserv closed this as completed Apr 30, 2024
vestata pushed a commit to vestata/rv32emu that referenced this issue Jan 24, 2025
The "emcc --version" command displays information about the version of
emcc, which contains the "gcc" or "clang" string. As a result, the build
rule should only match one compiler and stop checking anymore.  If not,
the build could be failed by a mix of different compiler's CFLAGS. For
example, -flto from clang and -flto=thin from emcc.

After refactoring the riscv.[ch] public APIs in commit 415e55d, it is
now possible to adjust the memory size to accommodate varying runtime
requirements. The memory size must align to a 4KB page size for the
WASM runtime and I set 1GB as default memory size for WASM runtime.

The LTO is not supported to build emscripten-port SDL library,
so disable it when both ENABLE_LTO=1 and ENABLE_SDL=1 are set.

Related to: sysprog21#75
Close sysprog21#375
vestata pushed a commit to vestata/rv32emu that referenced this issue Jan 24, 2025
To play sound effects and musics, we would use software synthesizer,
here I choose Timidity. When doom and quake target are specified, the
Timidity related data are downloaded and extracted. As previous
dicussion in the issue forum, the web workers are not reaped after
return, thus adding pthread_join to reap them. As I tested, the sound
effects and musics are only playable using the emcc version 3.1.51
which will fetch specific SDL2_mixer library, thus warning the user if
the emcc version is not 3.1.51.

Embed all ELF and their dependencies into single wasm when building with
emcc. Consequently, a ELF executable menu bar can be introduced to select
and run desired ELF programs.

Since we are running the wasm program inside web browser, we have to
yield to the web browser in some interval, so emscripten_set_main_loop_arg
provided by emscripten comes to help. To utilize this function, we have to
update the rv_step function signature. In order to switch running ELF
programs, we have to cancel the browser main loop using
emscripten_cancel_main_loop and do some clean up to recollect memory.
_indirect_rv_halt is introduced to halt the RISC-V instance without
exposing the RISC-V instance.

assets directory will be used to store some required static web files.
assets/html/index.html is a default main page of the ported wasm rv32emu.
In order to switch running ELF programs, we have to delay some time
for finishing emscripten_cancel_main_loop. I set delay to 1 second for now.

TODO: more clean up have to be done, e.g., clear canvas, terminal and
sound thread.

Related to: sysprog21#75
vestata pushed a commit to vestata/rv32emu that referenced this issue Jan 24, 2025
To deploy multithreading wasm on Github Pages, we have to make the
server to response two headers which are "Cross-Origin-Opener-Policy"
and "Cross-Origin-Embedder-Policy". Since we cannot directly control
the response headers of the Github Pages, coi-serviceworker comes to
help.

Related: sysprog21#75
vestata pushed a commit to vestata/rv32emu that referenced this issue Jan 24, 2025
Since wasm is deployed on Github Pages, thus it is reasonable to use CI
to deploy automatically.

The CI supports two event: merged pull request and workflow_dispatch.
The former only run after merging and latter is used to deploy by
maintainer manually. It also verifies whether any associated files
have changed. If so, carry out the CI; if not, stop.

Related: sysprog21#75
vestata pushed a commit to vestata/rv32emu that referenced this issue Jan 24, 2025
ELF executables might be rebuilt when new features are supported by the
rv32emu such as new SDL-related system calls for video games like Doom
and Quake or newlib has been updated. ELF executables are also might be
deleted.

Change filter from "any_changed" to "any_modified" since the latter
includes delete event and this can ensure that deleted ELF executables
do not appear in the demo page.

Close: sysprog21#405
See also: sysprog21#75
vestata pushed a commit to vestata/rv32emu that referenced this issue Jan 24, 2025
To enhance the user experience of using WebAssembly version of rv32emu,
we shall provide a Makefile target (serve-wasm) to serve the WebAssembly
demo page in an easy way.

Since rv32emu leverages TCO (tail call optimization) when being compiled,
so we have to tell if the user's browser supports TCO. Currently, only
Chrome with MAJOR 112 and Firefox with MAJOR 121 supports TCO execution
runtime, thus we focus on this two browsers. Also, use color text to
remind the users if they need to update their Chrome or Firefox.

See also: sysprog21#75
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants
@jserv @steven1lung @ChinYikMing and others