From ed9b2dbc03b49cdeecd937a05fa6b62f554ad5b3 Mon Sep 17 00:00:00 2001 From: Ayke van Laethem Date: Wed, 8 Jan 2020 17:48:34 +0100 Subject: [PATCH] runtime/hifive1: use CLINT peripheral for timekeeping The CLINT is implemented both on the fe310-g002 chip and in the sifive_e QEMU machine type. Therefore, use that peripheral for consistency. The only difference is the clock speed, which runs at 10MHz in QEMU for some reason instead of 32.768kHz as on the physical HiFive1 boards. --- src/runtime/runtime_fe310.go | 25 ++++++++++++++++++++++-- src/runtime/runtime_fe310_baremetal.go | 27 ++------------------------ src/runtime/runtime_fe310_qemu.go | 12 ++---------- 3 files changed, 27 insertions(+), 37 deletions(-) diff --git a/src/runtime/runtime_fe310.go b/src/runtime/runtime_fe310.go index 5b315542..b7a3774b 100644 --- a/src/runtime/runtime_fe310.go +++ b/src/runtime/runtime_fe310.go @@ -14,8 +14,6 @@ import ( type timeUnit int64 -const tickMicros = 32768 // RTC runs at 32.768kHz - //go:extern _sbss var _sbss unsafe.Pointer @@ -82,3 +80,26 @@ func putchar(c byte) { } const asyncScheduler = false + +func ticks() timeUnit { + // Combining the low bits and the high bits yields a time span of over 270 + // years without counter rollover. + highBits := sifive.CLINT.MTIMEH.Get() + for { + lowBits := sifive.CLINT.MTIME.Get() + newHighBits := sifive.CLINT.MTIMEH.Get() + if newHighBits == highBits { + // High bits stayed the same. + return timeUnit(lowBits) | (timeUnit(highBits) << 32) + } + // Retry, because there was a rollover in the low bits (happening every + // 1.5 days). + highBits = newHighBits + } +} + +func sleepTicks(d timeUnit) { + target := ticks() + d + for ticks() < target { + } +} \ No newline at end of file diff --git a/src/runtime/runtime_fe310_baremetal.go b/src/runtime/runtime_fe310_baremetal.go index 7c9fcf7f..e04560c4 100644 --- a/src/runtime/runtime_fe310_baremetal.go +++ b/src/runtime/runtime_fe310_baremetal.go @@ -4,36 +4,13 @@ package runtime import ( "device/riscv" - "device/sifive" ) +const tickMicros = 32768 // RTC clock runs at 32.768kHz + func abort() { // lock up forever for { riscv.Asm("wfi") } } - -func ticks() timeUnit { - // Combining the low bits and the high bits yields a time span of over 270 - // years without counter rollover. - highBits := sifive.RTC.RTCHI.Get() - for { - lowBits := sifive.RTC.RTCLO.Get() - newHighBits := sifive.RTC.RTCHI.Get() - if newHighBits == highBits { - // High bits stayed the same. - println("bits:", highBits, lowBits) - return timeUnit(lowBits) | (timeUnit(highBits) << 32) - } - // Retry, because there was a rollover in the low bits (happening every - // 1.5 days). - highBits = newHighBits - } -} - -func sleepTicks(d timeUnit) { - target := ticks() + d - for ticks() < target { - } -} diff --git a/src/runtime/runtime_fe310_qemu.go b/src/runtime/runtime_fe310_qemu.go index c5c38081..132515e7 100644 --- a/src/runtime/runtime_fe310_qemu.go +++ b/src/runtime/runtime_fe310_qemu.go @@ -7,6 +7,8 @@ import ( "unsafe" ) +const tickMicros = 100 // CLINT.MTIME increments every 100ns + // Special memory-mapped device to exit tests, created by SiFive. var testExit = (*volatile.Register32)(unsafe.Pointer(uintptr(0x100000))) @@ -16,13 +18,3 @@ func abort() { // Signal a successful exit. testExit.Set(0x5555) } - -func ticks() timeUnit { - return timestamp -} - -func sleepTicks(d timeUnit) { - // Note: QEMU doesn't seem to support the RTC peripheral at the time of - // writing so just simulate sleeping here. - timestamp += d -}