Menu

#96 Add WebAssembly target

Unstable (example)
open
nobody
None
5
2020-10-19
2020-07-23
No

Summary

This patch makes it possible to compile ngspice as a library for wasm target.

Usage

First, download emsdk. Using the sdk install the latest target, as well as well as binaryen.

To compile ngspice library, run:

emconfigure ./configure --with-ngshared --disable-debug
emmake make

This will produce src/.libs/libngspice.so.0.0.0. Despite what the extension would suggest, this is not a shared object, but a wasm static library that can be statically linked to other wasm code.

Compile example code

// sim.cpp

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

#include "sharedspice.h"

using namespace std;

int recieve_char(char * str, int id, void* p){
    printf("recieved %s\n", str);
    return 0;
}

int recieve_stat(char* status, int id, void* p){
    printf("status: %s\n", status);
    return 0;
}

int ngexit(int status, bool unload, bool exit, int id, void* p){
    printf("exit: %d\n", status);
    return 0;
}

int recieve_data(vecvaluesall* data, int numstructs, int id, void* p){
    printf("data recieved: %f\n", data->vecsa[0]->creal);
    return 0;
}

int recieve_init_data(vecinfoall* data, int id, void* p){
    printf("init data recieved from: %d\n", id);
    return 0;
}

int ngrunning(bool running, int id, void* p){
    if(running){
        printf("ng is running\n");
    }else{
        printf("ng is not running\n");
    }
    return 0;
}


int main(){

    ngSpice_Init(&recieve_char, &recieve_stat, &ngexit,
             &recieve_data, &recieve_init_data, &ngrunning, (void*) NULL);

    char** circarray = (char**)malloc(sizeof(char*) * 7);
    circarray[0] = strdup("test array");
    circarray[1] = strdup("V1 1 0 1");
    circarray[2] = strdup("R1 1 2 1");
    circarray[3] = strdup("C1 2 0 1 ic=0");
    circarray[4] = strdup(".tran 10u 3 uic");
    circarray[5] = strdup(".end");
    circarray[6] = NULL;
    ngSpice_Circ(circarray);

    ngSpice_Command("run");

    return 0;
}

To complile, run:

em++ -o sim.html sim.cpp lib/libngspice.so.0.0.0

where libngspice.so.0.0.0 is the library produced in the previous step.

Justification of changes in the patch

  • frontend/outitf.c: Signatures of sh_vecinit, didn't match up, leading to a runtime error.

  • main.c: for some reason even when compiling with flag --with-ngshared, the library file contained the main function, leading to a duplicate symbol error, so the main function needed to be removed by macros.

  • misc/misc_time.c: getrusage doesn't work properly with wasm/emscripten. It runs into an error with memset, but even if it worked, it would only return fake values. FYI, this is how it is implemented:

function ___sys_getrusage(who, usage) {try {

  _memset(usage, 0, 136);
  HEAP32[((usage)>>2)]=1; // fake some values
  HEAP32[(((usage)+(4))>>2)]=2;
  HEAP32[(((usage)+(8))>>2)]=3;
  HEAP32[(((usage)+(12))>>2)]=4;
  return 0;
} catch (e) {
if (typeof FS === 'undefined' || !(e instanceof FS.ErrnoError)) abort(e);
return -e.errno;
}
}
  • sharedspice.c: wasm couldn't possibly access user configuration files, so that section had to be removed by a macro.
1 Attachments

Discussion

  • Holger Vogt

    Holger Vogt - 2020-07-26

    branch pre-master:

    sh_vecinit is fixed
    compilation of main.c is suppressed, when SHARED_MODULE is set

    getrusage is used at other places in the code as well. It might be better to not set HAVE_GETRUSAGE already during ./configure , that is we might need some entry in configure.ac. Is there an alternative time information available?

    There is a ngspice install time configuration file spinit. Is this read? It is used to enable the XSPICE code models. If not available, the commands to load the code models may be sent via the interface, e.g. as
    codemodel <path>/analog.com
    Code models may be required when applying standard OpAmp subcircuit models containing poly source statements.

    The user defined initialization files may contain commands like
    set ngbehavior=ps
    which is required when PSPICE OpAmp models are to bew used. This command may be sent via the interface as well.

    Your patch does not show any additions/changes to configure.ac. Should we declare emscripten as a target of its own?

     
  • Danial Chitnis

    Danial Chitnis - 2020-10-19

    The shared library doesn't seem to work. I have followed this here:
    https://sourceforge.net/p/ngspice/patches/99/

     

    Last edit: Danial Chitnis 2020-10-19

Log in to post a comment.