aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/runtime
diff options
context:
space:
mode:
authorAyke van Laethem <[email protected]>2020-03-22 20:11:46 +0100
committerRon Evans <[email protected]>2020-03-26 23:03:55 +0100
commit980068543a1f9d720d7bb523b00c9818d383e916 (patch)
treeb4e7b0fdb308f656f636b6e241fa11baf54364f9 /src/runtime
parentc4fd19be99c2695f25ac59057adef7a44ad61ad9 (diff)
downloadtinygo-980068543a1f9d720d7bb523b00c9818d383e916.tar.gz
tinygo-980068543a1f9d720d7bb523b00c9818d383e916.zip
riscv: implement VirtIO target
This allows running RISC-V tests in CI using QEMU, which should help catch bugs.
Diffstat (limited to 'src/runtime')
-rw-r--r--src/runtime/runtime_fe310.go33
-rw-r--r--src/runtime/runtime_tinygoriscv.go38
-rw-r--r--src/runtime/runtime_tinygoriscv_qemu.go63
3 files changed, 101 insertions, 33 deletions
diff --git a/src/runtime/runtime_fe310.go b/src/runtime/runtime_fe310.go
index 62673ad35..2af409025 100644
--- a/src/runtime/runtime_fe310.go
+++ b/src/runtime/runtime_fe310.go
@@ -16,21 +16,6 @@ import (
type timeUnit int64
-//go:extern _sbss
-var _sbss [0]byte
-
-//go:extern _ebss
-var _ebss [0]byte
-
-//go:extern _sdata
-var _sdata [0]byte
-
-//go:extern _sidata
-var _sidata [0]byte
-
-//go:extern _edata
-var _edata [0]byte
-
func postinit() {}
//go:export main
@@ -108,24 +93,6 @@ func initPeripherals() {
machine.UART0.Configure(machine.UARTConfig{})
}
-func preinit() {
- // Initialize .bss: zero-initialized global variables.
- ptr := unsafe.Pointer(&_sbss)
- for ptr != unsafe.Pointer(&_ebss) {
- *(*uint32)(ptr) = 0
- ptr = unsafe.Pointer(uintptr(ptr) + 4)
- }
-
- // Initialize .data: global variables initialized from flash.
- src := unsafe.Pointer(&_sidata)
- dst := unsafe.Pointer(&_sdata)
- for dst != unsafe.Pointer(&_edata) {
- *(*uint32)(dst) = *(*uint32)(src)
- dst = unsafe.Pointer(uintptr(dst) + 4)
- src = unsafe.Pointer(uintptr(src) + 4)
- }
-}
-
func putchar(c byte) {
machine.UART0.WriteByte(c)
}
diff --git a/src/runtime/runtime_tinygoriscv.go b/src/runtime/runtime_tinygoriscv.go
new file mode 100644
index 000000000..93bf1e45f
--- /dev/null
+++ b/src/runtime/runtime_tinygoriscv.go
@@ -0,0 +1,38 @@
+// +build tinygo.riscv
+
+package runtime
+
+import "unsafe"
+
+//go:extern _sbss
+var _sbss [0]byte
+
+//go:extern _ebss
+var _ebss [0]byte
+
+//go:extern _sdata
+var _sdata [0]byte
+
+//go:extern _sidata
+var _sidata [0]byte
+
+//go:extern _edata
+var _edata [0]byte
+
+func preinit() {
+ // Initialize .bss: zero-initialized global variables.
+ ptr := unsafe.Pointer(&_sbss)
+ for ptr != unsafe.Pointer(&_ebss) {
+ *(*uint32)(ptr) = 0
+ ptr = unsafe.Pointer(uintptr(ptr) + 4)
+ }
+
+ // Initialize .data: global variables initialized from flash.
+ src := unsafe.Pointer(&_sidata)
+ dst := unsafe.Pointer(&_sdata)
+ for dst != unsafe.Pointer(&_edata) {
+ *(*uint32)(dst) = *(*uint32)(src)
+ dst = unsafe.Pointer(uintptr(dst) + 4)
+ src = unsafe.Pointer(uintptr(src) + 4)
+ }
+}
diff --git a/src/runtime/runtime_tinygoriscv_qemu.go b/src/runtime/runtime_tinygoriscv_qemu.go
new file mode 100644
index 000000000..74a8fc198
--- /dev/null
+++ b/src/runtime/runtime_tinygoriscv_qemu.go
@@ -0,0 +1,63 @@
+// +build tinygo.riscv,qemu
+
+package runtime
+
+import (
+ "device/riscv"
+ "runtime/volatile"
+ "unsafe"
+)
+
+// This file implements the VirtIO RISC-V interface implemented in QEMU, which
+// is an interface designed for emulation.
+
+type timeUnit int64
+
+const tickMicros = 1
+
+var timestamp timeUnit
+
+func postinit() {}
+
+//go:export main
+func main() {
+ preinit()
+ run()
+ abort()
+}
+
+const asyncScheduler = false
+
+func sleepTicks(d timeUnit) {
+ // TODO: actually sleep here for the given time.
+ timestamp += d
+}
+
+func ticks() timeUnit {
+ return timestamp
+}
+
+// Memory-mapped I/O as defined by QEMU.
+// Source: https://github.com/qemu/qemu/blob/master/hw/riscv/virt.c
+// Technically this is an implementation detail but hopefully they won't change
+// the memory-mapped I/O registers.
+var (
+ // UART0 output register.
+ stdoutWrite = (*volatile.Register8)(unsafe.Pointer(uintptr(0x10000000)))
+ // SiFive test finisher
+ testFinisher = (*volatile.Register16)(unsafe.Pointer(uintptr(0x100000)))
+)
+
+func putchar(c byte) {
+ stdoutWrite.Set(uint8(c))
+}
+
+func abort() {
+ // Make sure the QEMU process exits.
+ testFinisher.Set(0x5555) // FINISHER_PASS
+
+ // Lock up forever (as a fallback).
+ for {
+ riscv.Asm("wfi")
+ }
+}