forked from M-Labs/artiq
libboard_misoc: vexriscv integration
Signed-off-by: occheung <dc@m-labs.hk>
This commit is contained in:
parent
2cf144a60c
commit
82b4052cd6
|
@ -16,6 +16,8 @@ build_misoc = { path = "../libbuild_misoc" }
|
||||||
byteorder = { version = "1.0", default-features = false }
|
byteorder = { version = "1.0", default-features = false }
|
||||||
log = { version = "0.4", default-features = false, optional = true }
|
log = { version = "0.4", default-features = false, optional = true }
|
||||||
smoltcp = { version = "0.6.0", default-features = false, optional = true }
|
smoltcp = { version = "0.6.0", default-features = false, optional = true }
|
||||||
|
riscv = { version = "0.6.0", features = ["inline-asm"] }
|
||||||
|
vexriscv = { git = "https://github.com/occheung/vexriscv-rust.git", features = ["inline-asm"] }
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
uart_console = []
|
uart_console = []
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
#![no_std]
|
#![no_std]
|
||||||
#![feature(asm, try_from)]
|
#![feature(llvm_asm)]
|
||||||
|
|
||||||
extern crate byteorder;
|
extern crate byteorder;
|
||||||
#[cfg(feature = "log")]
|
#[cfg(feature = "log")]
|
||||||
|
@ -11,6 +11,16 @@ extern crate smoltcp;
|
||||||
#[path = "or1k/mod.rs"]
|
#[path = "or1k/mod.rs"]
|
||||||
mod arch;
|
mod arch;
|
||||||
|
|
||||||
|
#[cfg(target_arch = "riscv32")]
|
||||||
|
#[path = "riscv32imac/mod.rs"]
|
||||||
|
mod arch;
|
||||||
|
|
||||||
|
#[cfg(target_arch = "riscv32")]
|
||||||
|
extern crate riscv;
|
||||||
|
|
||||||
|
#[cfg(target_arch = "riscv32")]
|
||||||
|
extern crate vexriscv;
|
||||||
|
|
||||||
pub use arch::*;
|
pub use arch::*;
|
||||||
|
|
||||||
include!(concat!(env!("BUILDINC_DIRECTORY"), "/generated/mem.rs"));
|
include!(concat!(env!("BUILDINC_DIRECTORY"), "/generated/mem.rs"));
|
||||||
|
|
|
@ -0,0 +1,48 @@
|
||||||
|
use super::{irq, cache};
|
||||||
|
|
||||||
|
pub unsafe fn reset() -> ! {
|
||||||
|
irq::set_ie(false);
|
||||||
|
llvm_asm!(r#"
|
||||||
|
j _reset_handler
|
||||||
|
nop
|
||||||
|
"# : : : : "volatile");
|
||||||
|
loop {}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub unsafe fn jump(addr: usize) -> ! {
|
||||||
|
irq::set_ie(false);
|
||||||
|
cache::flush_cpu_icache();
|
||||||
|
llvm_asm!(r#"
|
||||||
|
jalr x0, 0($0)
|
||||||
|
nop
|
||||||
|
"# : : "r"(addr) : : "volatile");
|
||||||
|
loop {}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub unsafe fn hotswap(firmware: &[u8]) -> ! {
|
||||||
|
irq::set_ie(false);
|
||||||
|
llvm_asm!(r#"
|
||||||
|
# This loop overwrites itself, but it's structured in such a way
|
||||||
|
# that before that happens, it loads itself into I$$ fully.
|
||||||
|
lui a1, %hi(_reset_handler)
|
||||||
|
ori a1, a1, %lo(_reset_handler)
|
||||||
|
or a4, a1, zero
|
||||||
|
0: bnez a2, 1f
|
||||||
|
nop
|
||||||
|
jr a4
|
||||||
|
nop
|
||||||
|
1: lw a3, 0(a0)
|
||||||
|
sw a3, 0(a1)
|
||||||
|
addi a0, a0, 4
|
||||||
|
addi a1, a1, 4
|
||||||
|
addi a2, a2, -4
|
||||||
|
bnez a2, 0b
|
||||||
|
nop
|
||||||
|
"#
|
||||||
|
:
|
||||||
|
: "{a0}"(firmware.as_ptr() as usize),
|
||||||
|
"{a2}"(firmware.len())
|
||||||
|
:
|
||||||
|
: "volatile");
|
||||||
|
loop {}
|
||||||
|
}
|
|
@ -0,0 +1,35 @@
|
||||||
|
#[cfg(has_ddrphy)]
|
||||||
|
use core::ptr;
|
||||||
|
#[cfg(has_ddrphy)]
|
||||||
|
use csr;
|
||||||
|
#[cfg(has_ddrphy)]
|
||||||
|
use mem;
|
||||||
|
|
||||||
|
pub fn flush_cpu_icache() {
|
||||||
|
unsafe {
|
||||||
|
llvm_asm!(r#"
|
||||||
|
fence.i
|
||||||
|
nop
|
||||||
|
nop
|
||||||
|
nop
|
||||||
|
nop
|
||||||
|
nop
|
||||||
|
"# : : : : "volatile");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn flush_cpu_dcache() {
|
||||||
|
unsafe {
|
||||||
|
llvm_asm!(".word(0x500F)" : : : : "volatile");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(has_ddrphy)]
|
||||||
|
pub fn flush_l2_cache() {
|
||||||
|
unsafe {
|
||||||
|
for i in 0..2 * (csr::CONFIG_L2_SIZE as usize) / 4 {
|
||||||
|
let addr = mem::MAIN_RAM_BASE + i * 4;
|
||||||
|
ptr::read_volatile(addr as *const usize);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,46 @@
|
||||||
|
use core::{convert::TryFrom};
|
||||||
|
use riscv::register::mstatus;
|
||||||
|
use vexriscv::register::{vmim, vmip};
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub fn get_ie() -> bool {
|
||||||
|
mstatus::read().mie()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub fn set_ie(ie: bool) {
|
||||||
|
unsafe {
|
||||||
|
if ie {
|
||||||
|
mstatus::set_mie()
|
||||||
|
} else {
|
||||||
|
mstatus::clear_mie()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub fn get_mask() -> u32 {
|
||||||
|
u32::try_from(vmim::read()).unwrap()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub fn set_mask(mask: u32) {
|
||||||
|
vmim::write(usize::try_from(mask).unwrap())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub fn pending_mask() -> u32 {
|
||||||
|
u32::try_from(vmip::read()).unwrap()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn enable(irq: u32) {
|
||||||
|
set_mask(get_mask() | (1 << irq))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn disable(irq: u32) {
|
||||||
|
set_mask(get_mask() & !(1 << irq))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn is_pending(irq: u32) -> bool {
|
||||||
|
get_mask() & (1 << irq) != 0
|
||||||
|
}
|
|
@ -0,0 +1,3 @@
|
||||||
|
pub mod irq;
|
||||||
|
pub mod cache;
|
||||||
|
pub mod boot;
|
|
@ -0,0 +1,177 @@
|
||||||
|
# Adapted from riscv-rt project, with the following license:
|
||||||
|
#
|
||||||
|
# Copyright 2018 RISC-V team
|
||||||
|
#
|
||||||
|
# Permission to use, copy, modify, and/or distribute this software for any purpose
|
||||||
|
# with or without fee is hereby granted, provided that the above copyright notice and
|
||||||
|
# this permission notice appear in all copies.
|
||||||
|
#
|
||||||
|
# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
|
||||||
|
# REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||||
|
# FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT,
|
||||||
|
# OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA
|
||||||
|
# OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
|
||||||
|
# ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
|
||||||
|
#if __riscv_xlen == 64
|
||||||
|
# define STORE sd
|
||||||
|
# define LOAD ld
|
||||||
|
# define LOG_REGBYTES 3
|
||||||
|
#else
|
||||||
|
# define STORE sw
|
||||||
|
# define LOAD lw
|
||||||
|
# define LOG_REGBYTES 2
|
||||||
|
#endif
|
||||||
|
#define REGBYTES (1 << LOG_REGBYTES)
|
||||||
|
|
||||||
|
/*
|
||||||
|
Entry point of all programs (_reset_handler).
|
||||||
|
|
||||||
|
It initializes DWARF call frame information, the stack pointer, the
|
||||||
|
frame pointer (needed for closures to work in start_rust) and the global
|
||||||
|
pointer. Then it calls _start_rust.
|
||||||
|
*/
|
||||||
|
|
||||||
|
.section .vectors, "ax", @progbits
|
||||||
|
.global _reset_handler
|
||||||
|
|
||||||
|
_reset_handler:
|
||||||
|
/* Jump to the absolute address defined by the linker script. */
|
||||||
|
// for 32bit
|
||||||
|
.if __riscv_xlen == 32
|
||||||
|
lui ra, %hi(_abs_start)
|
||||||
|
jr %lo(_abs_start)(ra)
|
||||||
|
.endif
|
||||||
|
|
||||||
|
// for 64bit
|
||||||
|
.if __riscv_xlen == 64
|
||||||
|
.option push
|
||||||
|
.option norelax // to prevent an unsupported R_RISCV_ALIGN relocation from being generated
|
||||||
|
1:
|
||||||
|
auipc ra, %pcrel_hi(1f)
|
||||||
|
ld ra, %pcrel_lo(1b)(ra)
|
||||||
|
jr ra
|
||||||
|
.align 3
|
||||||
|
1:
|
||||||
|
.dword _abs_start
|
||||||
|
.option pop
|
||||||
|
.endif
|
||||||
|
|
||||||
|
_abs_start:
|
||||||
|
.cfi_startproc
|
||||||
|
.cfi_undefined ra
|
||||||
|
|
||||||
|
csrw mie, 0
|
||||||
|
csrw mip, 0
|
||||||
|
|
||||||
|
li x1, 0
|
||||||
|
li x2, 0
|
||||||
|
li x3, 0
|
||||||
|
li x4, 0
|
||||||
|
li x5, 0
|
||||||
|
li x6, 0
|
||||||
|
li x7, 0
|
||||||
|
li x8, 0
|
||||||
|
li x9, 0
|
||||||
|
li x10,0
|
||||||
|
li x11,0
|
||||||
|
li x12,0
|
||||||
|
li x13,0
|
||||||
|
li x14,0
|
||||||
|
li x15,0
|
||||||
|
li x16,0
|
||||||
|
li x17,0
|
||||||
|
li x18,0
|
||||||
|
li x19,0
|
||||||
|
li x20,0
|
||||||
|
li x21,0
|
||||||
|
li x22,0
|
||||||
|
li x23,0
|
||||||
|
li x24,0
|
||||||
|
li x25,0
|
||||||
|
li x26,0
|
||||||
|
li x27,0
|
||||||
|
li x28,0
|
||||||
|
li x29,0
|
||||||
|
li x30,0
|
||||||
|
li x31,0
|
||||||
|
|
||||||
|
// Check hart id
|
||||||
|
csrr a2, mhartid
|
||||||
|
|
||||||
|
// Allocate stacks
|
||||||
|
la sp, _fstack
|
||||||
|
|
||||||
|
// Set frame pointer
|
||||||
|
add s0, sp, zero
|
||||||
|
|
||||||
|
// Set trap vector
|
||||||
|
la t0, _start_trap
|
||||||
|
csrw mtvec, t0
|
||||||
|
|
||||||
|
// Zero initialize .bss
|
||||||
|
la t0, _fbss
|
||||||
|
la t1, _ebss
|
||||||
|
beq t0, t1, 2f
|
||||||
|
1: STORE zero, 0(t0)
|
||||||
|
addi t0, t0, REGBYTES
|
||||||
|
bne t0, t1, 1b
|
||||||
|
2:
|
||||||
|
// Enter main firmware
|
||||||
|
jal zero, main
|
||||||
|
|
||||||
|
.cfi_endproc
|
||||||
|
|
||||||
|
/*
|
||||||
|
Trap entry point (_start_trap)
|
||||||
|
|
||||||
|
Saves caller saved registers ra, t0..6, a0..7, calls exception,
|
||||||
|
restores caller saved registers and then returns.
|
||||||
|
*/
|
||||||
|
.section .trap, "ax"
|
||||||
|
.global _start_trap
|
||||||
|
/* Make it .weak so PAC/HAL can provide their own if needed. */
|
||||||
|
.weak _start_trap
|
||||||
|
|
||||||
|
_start_trap:
|
||||||
|
addi sp, sp, -16*REGBYTES
|
||||||
|
|
||||||
|
STORE ra, 0*REGBYTES(sp)
|
||||||
|
STORE t0, 1*REGBYTES(sp)
|
||||||
|
STORE t1, 2*REGBYTES(sp)
|
||||||
|
STORE t2, 3*REGBYTES(sp)
|
||||||
|
STORE t3, 4*REGBYTES(sp)
|
||||||
|
STORE t4, 5*REGBYTES(sp)
|
||||||
|
STORE t5, 6*REGBYTES(sp)
|
||||||
|
STORE t6, 7*REGBYTES(sp)
|
||||||
|
STORE a0, 8*REGBYTES(sp)
|
||||||
|
STORE a1, 9*REGBYTES(sp)
|
||||||
|
STORE a2, 10*REGBYTES(sp)
|
||||||
|
STORE a3, 11*REGBYTES(sp)
|
||||||
|
STORE a4, 12*REGBYTES(sp)
|
||||||
|
STORE a5, 13*REGBYTES(sp)
|
||||||
|
STORE a6, 14*REGBYTES(sp)
|
||||||
|
STORE a7, 15*REGBYTES(sp)
|
||||||
|
|
||||||
|
add a0, sp, zero
|
||||||
|
jal ra, exception
|
||||||
|
|
||||||
|
LOAD ra, 0*REGBYTES(sp)
|
||||||
|
LOAD t0, 1*REGBYTES(sp)
|
||||||
|
LOAD t1, 2*REGBYTES(sp)
|
||||||
|
LOAD t2, 3*REGBYTES(sp)
|
||||||
|
LOAD t3, 4*REGBYTES(sp)
|
||||||
|
LOAD t4, 5*REGBYTES(sp)
|
||||||
|
LOAD t5, 6*REGBYTES(sp)
|
||||||
|
LOAD t6, 7*REGBYTES(sp)
|
||||||
|
LOAD a0, 8*REGBYTES(sp)
|
||||||
|
LOAD a1, 9*REGBYTES(sp)
|
||||||
|
LOAD a2, 10*REGBYTES(sp)
|
||||||
|
LOAD a3, 11*REGBYTES(sp)
|
||||||
|
LOAD a4, 12*REGBYTES(sp)
|
||||||
|
LOAD a5, 13*REGBYTES(sp)
|
||||||
|
LOAD a6, 14*REGBYTES(sp)
|
||||||
|
LOAD a7, 15*REGBYTES(sp)
|
||||||
|
|
||||||
|
addi sp, sp, 16*REGBYTES
|
||||||
|
mret
|
Loading…
Reference in New Issue