PathrockNetwork Gno Explorer
HomeBlocksTransactionsTokensRealmsPackagesValidatorsAnalytics

PathrockNetwork Gno Explorer — an independent explorer for Gno.land Mainnet (gnoland-1), operated by PathrockNetwork. Not an official Gno.land service.

gnowebarchive RPC

gno.land/p/moul/x/vm/riscv/v0

Package
Open in gnoweb ↗

Overview

Kind
Pure package
Name
v0
Namespace
moul / x / vm / riscv
Files
17 (README)(gnomod.toml)
Exported functions
n/a — not supported for pure packages by the node (vm/qfuncs)
Module
gno.land/p/moul/x/vm/riscv/v0
gno
0.9

Files (17)

  • README.mdmarkdown
  • gnomod.tomltoml
  • decode.gnogno
  • ecall.gnogno
  • exec.gnogno
  • guests.gnogno
  • mem.gnogno
  • predecode.gnogno
  • snapshot.gnogno
  • bench_test.gnogno
  • clang_test.gnogno
  • conformance_test.gnogno
  • decode_test.gnogno
  • predecode_test.gnogno
  • riscv_test.gnogno
  • rust_test.gnogno
  • switchcost_test.gnogno
  • clang_test.gnogno
    1package riscv23import (4	"testing"56	"gno.land/p/moul/x/vm/vmkit/v0"7	"gno.land/p/nt/uassert/v0"8

    Functions

    not supported for pure packages by the node (vm/qfuncs)

    Signatures reconstructed verbatim from vm/qfuncs — interface params keep their inline definitions.

    )
    9
    10// A guest compiled by a real compiler, which is the only test here that was
    11// not written by the same person who wrote the emulator.
    12//
    13// The image is guests.gno's, built from tools/riscv-guests/fnv by clang. It
    14// exercises what hand-written tests do not: a real function prologue spilling
    15// ra and s0 to a stack the host set up, .bss addressed far above a read-only
    16// text segment, LLVM's constant materialization through lui/addi pairs, and
    17// MUL in an inner loop.
    18
    19// The expected hashes come from an independent FNV-1a, not from this VM.
    20func TestClangCompiledGuest(t *testing.T) {
    21 cases := []struct {
    22 in string
    23 want string
    24 }{
    25 {"", "811c9dc5"},
    26 {"a", "e40c292c"},
    27 {"Hello", "f55c314b"},
    28 {"gno.land", "fb7ffba0"},
    29 }
    30 for _, c := range cases {
    31 m, err := NewMachine(GuestFNV(), entry)
    32 uassert.NoError(t, err)
    33 if m == nil {
    34 continue
    35 }
    36 h := vmkit.NewTestHost().WithInput([]byte(c.in))
    37 _, status := m.Step(h, vmkit.Unmetered)
    38 uassert.Equal(t, "halted", status.String(), "input "+c.in+": "+m.Trap())
    39 uassert.Equal(t, c.want, string(h.Out()), "fnv1a of "+c.in)
    40 }
    41}
    42
    43// Compiled code pauses and resumes like anything else. This is the property a
    44// realm depends on, run against output a compiler produced rather than against
    45// a loop written to be sliceable.
    46func TestClangGuestSurvivesSlicing(t *testing.T) {
    47 image := GuestFNV()
    48 h := vmkit.NewTestHost().WithInput([]byte("gno.land"))
    49
    50 sliced, err := NewMachine(image, entry)
    51 uassert.NoError(t, err)
    52 status := vmkit.Running
    53 slices := 0
    54 for i := 0; i < 500 && status == vmkit.Running; i++ {
    55 var fresh Machine
    56 uassert.NoError(t, fresh.Restore(sliced.Snapshot()))
    57 _, status = fresh.Step(h, 3)
    58 sliced = &fresh
    59 slices++
    60 }
    61 uassert.Equal(t, "halted", status.String())
    62 uassert.True(t, slices > 10, "a sliced run must actually have been sliced")
    63 uassert.Equal(t, "fb7ffba0", string(h.Out()))
    64}
    65
    66// The guest writes its globals at 0x40000, which the linker script put well
    67// above the text segment on purpose. If it had put them adjacent, W xor X
    68// would trap on the first store, so this is the test that the memory layout
    69// the toolchain was told to use is the one the host actually provides.
    70func TestClangGuestWritesAboveItsText(t *testing.T) {
    71 m, err := NewMachine(GuestFNV(), entry)
    72 uassert.NoError(t, err)
    73 h := vmkit.NewTestHost().WithInput([]byte("gno.land"))
    74 _, status := m.Step(h, vmkit.Unmetered)
    75 uassert.Equal(t, "halted", status.String())
    76
    77 // The text pages, the .bss page at 0x40000, and the stack page at the top.
    78 uassert.True(t, m.Memory().DirtyPages() >= 3,
    79 "the guest must have written outside its text segment")
    80 uassert.True(t, m.Memory().DirtyPages() <= 8,
    81 "a 196-byte program must not have dirtied the address space")
    82}
    83
    84// Image is what every caller uses to turn words into a program, so a byte
    85// order mistake here would look like a decoder bug everywhere else.
    86func TestImageIsLittleEndian(t *testing.T) {
    87 b := Image([]uint32{0x04030201, 0xFF000000})
    88 uassert.Equal(t, 8, len(b))
    89 uassert.Equal(t, uint64(0x01), uint64(b[0]))
    90 uassert.Equal(t, uint64(0x04), uint64(b[3]))
    91 uassert.Equal(t, uint64(0x00), uint64(b[4]))
    92 uassert.Equal(t, uint64(0xFF), uint64(b[7]))
    93
    94 // And it agrees with the assembler the other tests use.
    95 words := []uint32{addi(5, 0, 1), ecall()}
    96 a, i := asm(words), Image(words)
    97 uassert.Equal(t, len(a), len(i))
    98 for k := range a {
    99 uassert.Equal(t, uint64(a[k]), uint64(i[k]))
    100 }
    101}
    102
    103// GuestFNV must not hand out a slice a caller can scribble on, because the
    104// next caller gets the same program.
    105func TestGuestFNVIsACopy(t *testing.T) {
    106 a := GuestFNV()
    107 a[0] = 0xFF
    108 b := GuestFNV()
    109 uassert.False(t, b[0] == 0xFF, "GuestFNV must return a fresh image each call")
    110}
    111