Exemplo n.º 1
0
def test_coremark_crc16(v1, v2):
    coremark_wasm_snippet = r"""
    (module
      (func $crc8 (param i32 i32) (result i32)
        local.get 0
        local.get 1
        i32.add)

      (func (export "crc16") (param i32 i32) (result i32)
        local.get 0
        i32.const 16
        i32.shr_u
        local.get 0
        i32.const 65535
        i32.and
        local.get 1
        call $crc8
        call $crc8)
    )
    """
    m = Module(coremark_wasm_snippet)
    py_inst = instantiate(m, target='python')
    native_inst = instantiate(m, target='native')
    res1 = py_inst.exports['crc16'](v1, v2)
    res2 = native_inst.exports['crc16'](v1, v2)
    print('results', res1, 'should be equal to', res2)
    assert res1 == res2
Exemplo n.º 2
0
def assert_equal_behavior(m):
    """ Instantiate the module in both python and native.

    Test that both operate the same.
    """
    print(m.to_string())

    # Compile / instantiate:
    py_inst = instantiate(m, target='python')
    native_inst = instantiate(m, target='native')

    # Run both python and x86 variant and compare outputs.
    res1 = py_inst.exports['my_func']()
    res2 = native_inst.exports['my_func']()
    print('results', res1, 'should be equal to', res2)
    assert res1 == res2
Exemplo n.º 3
0
    def _instantiate(self, m1):
        """ Instantiate a module. """
        # Next step: Instantiate:
        if self.target:

            def my_print() -> None:
                pass

            def print_i32(x: int) -> None:
                pass

            imports = {
                'spectest': {
                    'print_i32': print_i32,
                    'print': my_print,
                    #    'global_i32': 777,
                    'table': components.Table("$table", 'funcref', 10, 20)
                }
            }

            for reg_name, reg_instance in self._registered_instances.items():
                imports[reg_name] = {}
                # TODO: use reg_instance.exports

            mod_instance = instantiate(m1,
                                       imports=imports,
                                       target=self.target,
                                       reporter=self.reporter)
            self.logger.debug('Instantiated wasm module %s', mod_instance)
            if m1.id:
                self.named_module_instances[m1.id] = mod_instance
        else:
            mod_instance = None
        return mod_instance
Exemplo n.º 4
0
    def take_root(self, bits, target):
        # Function parameters and result:
        a = 4.0
        b = 9.0
        expected_result = 6.0

        # Python cross check:
        python_result = math.sqrt(a) * math.sqrt(b)
        assert math.isclose(python_result, expected_result, rel_tol=0.0001, abs_tol=0.0000001)

        # Now via wasm instantiation:
        module = Module(src)
        # report_filename = 'root_{}_{}.html'.format(bits, target)
        # with html_reporter(report_filename) as reporter:
        #, reporter=reporter)
        instance = instantiate(module, target=target)

        # print('root ', bits, 'instance', inst, 'for target', target)

        funcname = 'f{}.mul_sqrts'.format(bits)
        res = instance.exports[funcname](a, b)
        
        # print('Result:', res, 'expected=', expected_result, 'python says', python_result)
        
        assert math.isclose(res, expected_result, rel_tol=0.0001, abs_tol=0.0000001)
Exemplo n.º 5
0
def test_benchmark_nbody_with_ppci(benchmark):
    instance = wasm.instantiate(wasm.read_wasm(TEST_BYTES), {}, 'native')
    nbody = instance.exports.main

    def bench():
        return nbody(N)

    assert benchmark(bench)
Exemplo n.º 6
0
def test_python_to_wasm():

    m = python_to_wasm(find_prime)

    imports = {'env': {'f64_print': f64_print}}
    # TODO: for some reason, target='native' ends up in an infinite loop?
    ob = wasm.instantiate(m, imports, target='python')

    result = ob.exports.find_prime(10)
    assert result == 29
Exemplo n.º 7
0
 def __init__(self, game_module=game_module):
     # Create import dict from methods
     env = {}
     for name in dir(self):
         if name.startswith('wasm_'):
             env[name[5:]] = getattr(self, name)
     self.imports = dict(env=env)
     
     # Instantiate game module
     self.game = wasm.instantiate(game_module, self.imports, target='python')
Exemplo n.º 8
0
def assert_equal_memory(m):
    """ Instantiate the module in both python and native.

    Test that both operate the same.
    """
    print(m.to_string())

    # Compile / instantiate:
    py_inst = instantiate(m, target='python')
    native_inst = instantiate(m, target='native')

    # Run both python and x86 variant
    py_inst.exports['my_func']()
    native_inst.exports['my_func']()

    # Compare memory contents:
    py_mem = py_inst.exports['mem']
    native_mem = native_inst.exports['mem']

    assert py_mem.read(0, 100) == native_mem.read(0, 100)
Exemplo n.º 9
0
    def test_callbacks(self):
        """ Test various stuff around wasm instantiation.
        See examples/wasm/callbacks.py
        """
        module = Module(
            ('import', 'py', 'add', ('func', '$add', ('param', 'i64', 'i64'), ('result', 'i64'))),
            ('global', '$g1', ('export', 'var1'), ('mut', 'i64'), ('i64.const', 42)),
            ('func', ('export', 'main'), ('param', 'i64'), ('result', 'i64'),
                ('local.get', 0),
                ('global.get', '$g1'),
                ('call', '$add'),
            ),
            ('func', ('export', 'add'), ('param', 'i64', 'i64'), ('result', 'i64'),
                ('local.get', 0),
                ('local.get', 1),
                ('call', '$add'),
            ),
            ('memory', ('export', 'mem0ry'),
                ('data', 'abcd'),
            ),
        )

        def my_add(x: int, y: int) -> int:
            print('my add called', x, y)
            return x + y + 1

        imports = {
            'py_add': my_add
        }

        instance = instantiate(
            module,
            imports={
                'py': {
                    'add': my_add,
                }
            })

        self.assertEqual(1380, instance.exports.main(1337))
        self.assertEqual(85, instance.exports.add(42, 42))
        self.assertEqual(3, instance.exports['add'](1, 1))
        self.assertEqual(42, instance.exports.var1.read())
        instance.exports.var1.write(7)
        self.assertEqual(7, instance.exports.var1.read())
        self.assertEqual(1345, instance.exports.main(1337))
        self.assertEqual(b"abcd", instance.exports.mem0ry[0:4])
        instance.exports.mem0ry[1:3] = bytes([1,2])
        self.assertEqual(b'a\x01\x02d', instance.exports.mem0ry[0:4])
Exemplo n.º 10
0
 def __init__(self, ai_module=ai_module1):
     super().__init__()
     self.ai = wasm.instantiate(ai_module, self.imports, target='native')
Exemplo n.º 11
0
 def __init__(self, ai_module=ai_module1):
     super().__init__()
     self.ai = wasm.instantiate(ai_module, self.imports, target='native')
Exemplo n.º 12
0
  (func $fac-f32 (export "fac-f32") (type $over-f32)
    (if (result f32) (f32.eq (local.get 0) (f32.const 0.0))
      (then (f32.const 1.0))
      (else
        (f32.mul
          (local.get 0)

          (call $fac-f32
            (f32.sub (local.get 0) (f32.const 1.0))
          )
        )
      )
    )
  )
)
"""
m = Module(src)

obj = api.wasmcompile(src, 'x86_64', opt_level=0)
api.objcopy(obj, None, 'elf', 'fac_f32.o')

print(m.to_string())

inst = instantiate(m, {})
inst2 = instantiate(m, {}, target='python')

for number in [1.0, 5.0, 10.0]:
    print('number', number, 'fac', inst.exports['fac-f32'](number),
          'fac_python', inst2.exports['fac-f32'](number))
Exemplo n.º 13
0
def test_memory1():

    # The canonical form
    CODE0 = dedent(r"""
    (module
      (type $print (func (param i32)))
      (type $2 (func))
      (import "js" "print_ln" (func $print (type $print)))
      (memory $0 1 1)
      (start $main)
      (func $main (type $2)
        i32.const 0
        i32.load8_u
        call $print
        i32.const 1
        i32.load8_u
        call $print)
      (data i32.const 0 "\04\03\02")
    )
    """)

    # Test main code
    m0 = Module(CODE0)
    assert m0.to_string() == CODE0

    b0 = m0.to_bytes()
    assert Module(b0).to_bytes() == b0

    printed_numbers = []
    def print_ln(x: int) -> None:
        printed_numbers.append(x)
    imports = {
        'js': {
            'print_ln': print_ln,
        }
    }
    instantiate(m0, imports=imports, target='python')
    assert [4, 3] == printed_numbers

    if has_node():
        assert run_wasm_in_node(m0, True) == '4\n3'

    # Abbreviation: imported memory
    m3 = Module('(module (memory $m1 (import "foo" "bar_mem1") 1) )')
    assert m3.to_string() == dedent("""
    (module
      (import "foo" "bar_mem1" (memory $m1 1))
    )
    """)

    m3 = Module('(module (memory (import "foo" "bar_mem1") 2 3) )')
    assert m3.to_string() == dedent("""
    (module
      (import "foo" "bar_mem1" (memory 2 3))
    )
    """)


    # Abbeviation: inline data and unspecified (default) alignment
    CODE1 = r"""
    (module
        (type $print (func (param i32)))
        (type $2 (func))
        (import "js" "print_ln" (func $print (type $print)))
        (memory (data "\04\03\02"))
        (start $main)
        (func $main (type $2)
            i32.const 0
            i32.load8_u
            call $print
            i32.const 1
            i32.load8_u
            call $print
        )
    )
    """
    m1 = Module(CODE1)
    assert m1.to_string() == CODE0
    assert m1.to_bytes() == b0
Exemplo n.º 14
0
from ppci.wasm import instantiate, read_wasm
import demo

with open('demo.wasm', 'rb') as f:
    module = read_wasm(f)

inst = instantiate(module, {})

print(inst)
print('myAdd(0, 55)', inst.exports['myAdd'](0, 55), 'should be:',
      demo.myAdd(0, 55))
print('myAdd(7, 55)', inst.exports['myAdd'](7, 55), 'should be:',
      demo.myAdd(7, 55))
print('mySub(7, 2)', inst.exports['mySub'](7, 2), 'should be:',
      demo.mySub(7, 2))
print('mySub(17, 2)', inst.exports['mySub'](17, 2), 'should be:',
      demo.mySub(17, 2))
print('myFoo(2.2)', inst.exports['myFoo'](2.2), 'should be:', demo.myFoo(2.2))
print('myBar(7)', inst.exports['myBar'](7), 'should be:', demo.myBar(7))
Exemplo n.º 15
0
from ppci.wasm import instantiate, read_wasm

import mandel
import x
import time

with open('mandel2.wasm', 'rb') as f:
    module = read_wasm(f)

inst = instantiate(module, {'x': {'putc': x.putc, 'put_float': x.put_float}})

print(inst)
print('mandel():')
inst.exports['mandel']()
print()

print('mandel2():')
inst.exports['mandel2']()
print()
Exemplo n.º 16
0
  (func $fac-f32 (export "fac-f32") (type $over-f32)
    (if (result f32) (f32.eq (local.get 0) (f32.const 0.0))
      (then (f32.const 1.0))
      (else
        (f32.mul
          (local.get 0)

          (call $fac-f32
            (f32.sub (local.get 0) (f32.const 1.0))
          )
        )
      )
    )
  )
)
"""
m = Module(src)

obj = api.wasmcompile(src, 'x86_64', opt_level=0)
api.objcopy(obj, None, 'elf', 'fac_f32.o')

print(m.to_string())

inst = instantiate(m, target='native')
inst2 = instantiate(m, target='python')

for number in [1.0, 5.0, 10.0]:
    print('number', number, 'fac', inst.exports['fac-f32'](number),
          'fac_python', inst2.exports['fac-f32'](number))
Exemplo n.º 17
0
from ppci.wasm import instantiate, read_wasm

import mandel
import x
import time

with open('mandel.wasm', 'rb') as f:
    module = read_wasm(f)

inst = instantiate(module, {'x': {'putc': x.putc}})

print(inst)
print('python -> wasm -> native code mandel:')
t1 = time.time()
inst.exports['mandel']()
t2 = time.time()

print('Python mandel:')
t3 = time.time()
mandel.mandel()
t4 = time.time()

dt_native = t2 - t1
dt_python = t4 - t3
print('native took:', dt_native, 'python took:', dt_python, 'speedup', dt_python / dt_native)

Exemplo n.º 18
0
def test_func1():

    # The canonical form
    CODE0 = dedent("""
    (module
        (type $0 (func (param i32)))
        (type $1 (func (param i32 i32) (result i32)))
        (type $2 (func))
        (import "js" "print_ln" (func $print (type $0)))
        (start $main)
        (func $add (type $1)
            (get_local 0)
            (get_local 1)
            (i32.add)
        )
        (func $main (type $2) (local $foo i32)
            (i32.const 4)
            (i32.const 3)
            (call $add)
            (set_local $foo)
            (get_local $foo)
            (call $print)
        )
    )
    """)

    # Test main code
    m0 = Module(CODE0)
    assert m0.to_string() == CODE0

    b0 = m0.to_bytes()
    assert Module(b0).to_bytes() == b0

    # TODO: figure out what is wrong below:
    if False:
        printed_numbers = []

        def print_ln(x: int) -> None:
            printed_numbers.append(x)

        imports = {
            'js': {
                'print_ln': print_ln,
            },
        }
        instantiate(m0, imports, target='python')
        assert [7] == printed_numbers

    if has_node():
        assert run_wasm_in_node(m0, True) == '7'

    # Abbreviation: inline typedefs
    CODE1 = """
    (module
        (import "js" "print_ln" (func $print (param i32)))
        (start $main)
        (func $add (param i32 i32) (result i32)
            (get_local 0)
            (get_local 1)
            (i32.add)
        )
        (func $main (local $foo i32)
            (set_local $foo
                (call $add
                    (i32.const 4)
                    (i32.const 3)
                )
            )
            (call $print
                (get_local $foo)
            )
        )
    )
    """
    m1 = Module(CODE1)
    assert m1.to_string() == CODE0  # look at the indentation!
    assert m1.to_bytes() == b0
Exemplo n.º 19
0
print(f.getvalue())


def my_add(x: int, y: int) -> int:
    print('my add called', x, y)
    return x + y + 1


# Run in memory
imports = {'py_add': my_add}

native_module = load_obj(obj, imports=imports)
print(dir(native_module))
result = getattr(native_module, 'add')(42, 42)
print(result, '(should be 85)')

# This way a wasm module can be loaded analog to javascript:
instance = instantiate(wasm_module, imports={'py': {
    'add': my_add,
}})

print(instance.exports.main(1337), '(should be 1380)')
print(instance.exports.add(1, 1), '(should be 3)')
print('global var', instance.exports.var1.read())
instance.exports.var1.write(7)
print('global var', instance.exports.var1.read())
print(instance.exports.main(1337), '(should be 1345)')
print('mem[0:4]=', instance.exports.mem0ry[0:4])
instance.exports.mem0ry[1:3] = bytes([1, 2])
print('mem[0:4]=', instance.exports.mem0ry[0:4])
Exemplo n.º 20
0
def test_table1():

    # The canonical form
    CODE0 = dedent(r"""
    (module
      (type $print (func (param i32)))
      (type $2 (func))
      (import "js" "print_ln" (func $print (type $print)))
      (table $0 2 2 funcref)
      (start $main)
      (elem i32.const 0 $f1 $f2)
      (func $f1 (type $2)
        i32.const 101
        call $print)
      (func $f2 (type $2)
        i32.const 102
        call $print)
      (func $main (type $2)
        i32.const 0
        call_indirect (type $2)
        i32.const 1
        call_indirect (type $2))
    )
    """)

    # Test main code
    m0 = Module(CODE0)
    assert m0.to_string() == CODE0

    b0 = m0.to_bytes()
    assert Module(b0).to_bytes() == b0

    html_report = 'table_and_element_compilation_report.html'
    with open(html_report, 'w') as f, HtmlReportGenerator(f) as reporter:
        printed_numbers = []

        def print_ln(x: int) -> None:
            printed_numbers.append(x)

        imports = {
            'js': {
                'print_ln': print_ln,
            },
        }
        instantiate(m0, imports, target='python', reporter=reporter)
        assert [101, 102] == printed_numbers

        if is_platform_supported():
            printed_numbers = []

            def print_ln(x: int) -> None:
                printed_numbers.append(x)

            imports = {
                'js': {
                    'print_ln': print_ln,
                },
            }
            instantiate(m0, imports, target='native', reporter=reporter)
            assert [101, 102] == printed_numbers

    if has_node():
        assert run_wasm_in_node(m0, True) == '101\n102'

    # Abbreviation: imported table
    m3 = Module('(module (table $t1 (import "foo" "bar_table1") funcref) )')
    assert m3.to_string() == dedent("""
    (module
      (import "foo" "bar_table1" (table $t1 funcref))
    )
    """)

    m3 = Module('(module (table (import "foo" "bar_table1") 2 3 funcref) )')
    assert m3.to_string() == dedent("""
    (module
      (import "foo" "bar_table1" (table 2 3 funcref))
    )
    """)

    # Abbeviation: inline data and unspecified (default) alignment
    CODE1 = r"""
    (module
        (type $print (func (param i32)))
        (type $2 (func))
        (import "js" "print_ln" (func $print (type $print)))
        (table funcref (elem $f1 $f2))
        (start $main)
        (func $f1 (type $2)
            (i32.const 101)
            (call $print)
        )
        (func $f2 (type $2)
            (i32.const 102)
            (call $print)
        )
        (func $main (type $2)
            (i32.const 0)
            (call_indirect (type $2))
            (i32.const 1)
            (call_indirect (type $2))
        )
    )
    """
    m1 = Module(CODE1)
    assert m1.to_string() == CODE0
    assert m1.to_bytes() == b0
Exemplo n.º 21
0
    def load_module(self, s_expr):
        if 'binary' in s_expr:
            # We have (module binary "")

            # Iterate:
            elems = iter(s_expr)

            # Skip to binary tag:
            while next(elems) != 'binary':
                pass

            # fetch data from last tuple elements:
            parts = []
            for elem in elems:
                data = datastring2bytes(elem)
                parts.append(data)
            data = reduce(add, parts)

            # Load module from binary data:
            m1 = Module(data)

            # Go back
            data2 = m1.to_bytes()

            # Wont always be the same, e.g. some tests use non-minimal LEB ints
            # assert data == data2

            data3 = Module(data2).to_bytes()

            # Check that reading it in result in the same module ...
            assert data2 == data3

        else:
            # Load module from tuples:
            m1 = Module(s_expr)

            # # Convert module to text form and parse again
            # # This should yield the same binary form:
            # m2 = Module(m1.to_string())
            # assert m1.to_bytes() == m2.to_bytes()

            # NOTE: going to string format and back does not
            # guarantee that parsing was correct.

            self.reporter.dump_wasm(m1)

        self.logger.debug('loaded wasm module %s', m1)

        # Next step: Instantiate:
        if self.target:
            def my_print() -> None:
                pass

            def print_i32(x: int) -> None:
                pass

            imports = {
               'spectest': {
                   'print_i32': print_i32,
                   'print': my_print,
               }
            }
            self.mod_instance = instantiate(
                m1, imports, target=self.target, reporter=self.reporter)
            self.logger.debug('Instantiated wasm module %s', self.mod_instance)
        else:
            self.mod_instance = None
Exemplo n.º 22
0
logging.basicConfig(level=logging.INFO)

with open('wasmboy.wasm', 'rb') as f:
    wasm_module = Module(f)


def log(a: int, b: int, c: int, d: int, e: int, f: int, g: int) -> None:
    print('Log:', a, b, c, d, e, f, g)


this_dir = os.path.dirname(os.path.abspath(__file__))
html_report = os.path.join(this_dir, 'wasmboy_report.html')
with reporting.html_reporter(html_report) as reporter:
    wasm_boy = instantiate(wasm_module,
                           imports={'env': {
                               'log': log
                           }},
                           target='native',
                           reporter=reporter)

# Following this explanation:
# https://github.com/torch2424/wasmBoy/wiki/%5BWIP%5D-Core-API

rom_filename = args.rom
logging.info('Loading %s', rom_filename)
# Load in a game to CARTRIDGE_ROM_LOCATION
rom_location = wasm_boy.exports.CARTRIDGE_ROM_LOCATION.read()
with open(rom_filename, 'rb') as f:
    rom_data = f.read()
rom_size = len(rom_data)
wasm_boy.exports.memory[rom_location:rom_location + rom_size] = rom_data
Exemplo n.º 23
0
print(f.getvalue())


def my_add(x: int, y: int) -> int:
    print('my add called', x, y)
    return x + y + 1


# Run in memory
imports = {'py_add': my_add}

native_module = load_obj(obj, imports=imports)
print(dir(native_module))
result = getattr(native_module, 'add')(42, 42)
print(result, '(should be 85)')

# This way a wasm module can be loaded analog to javascript:
instance = instantiate(wasm_module, {'py': {
    'add': my_add,
}})

print(instance.exports.main(1337), '(should be 1380)')
print(instance.exports.add(1, 1), '(should be 3)')
print('global var', instance.exports.var1.read())
instance.exports.var1.write(7)
print('global var', instance.exports.var1.read())
print(instance.exports.main(1337), '(should be 1345)')
print('mem[0:4]=', instance.exports.mem0ry[0:4])
instance.exports.mem0ry[1:3] = bytes([1, 2])
print('mem[0:4]=', instance.exports.mem0ry[0:4])