Skip to content

Commit

Permalink
Merge pull request #69 from Alignof/develop
Browse files Browse the repository at this point in the history
Ver 1.1.0
  • Loading branch information
Alignof authored Mar 29, 2023
2 parents 713decc + 012e970 commit f658bf5
Show file tree
Hide file tree
Showing 35 changed files with 1,256 additions and 672 deletions.
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "carron"
version = "1.0.0"
version = "1.1.0"
authors = ["n.takana <[email protected]>"]
edition = "2021"
description = "RV64IMAC emulator"
Expand Down
43 changes: 40 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# carron
[![Rust](https://github.com/Alignof/carron/actions/workflows/rust.yml/badge.svg)](https://github.com/Alignof/Carron/actions/workflows/rust.yml)
[![riscv_tests](https://github.com/Alignof/carron/actions/workflows/riscv_tests.yml/badge.svg)](https://github.com/Alignof/carron/actions/workflows/riscv_tests.yml)
[![Rust](https://github.com/Alignof/carron/actions/workflows/rust.yml/badge.svg)](https://github.com/Alignof/Carron/actions/workflows/rust.yml)
[![riscv\_tests](https://github.com/Alignof/carron/actions/workflows/riscv_tests.yml/badge.svg)](https://github.com/Alignof/carron/actions/workflows/riscv_tests.yml)
RV64IMAC emulator in rust

## Feature
Expand Down Expand Up @@ -40,7 +40,7 @@ cargo build --release
## Usage
```zsh
$ ./carron --help
carron 1.0.0
carron 1.1.0
n.takana <[email protected]>
RV64IMAC emulator

Expand All @@ -64,7 +64,9 @@ OPTIONS:
--loglv <log_level> Set log level
-h, --help Print help information
-V, --version Print version information
```

```zsh
$ ./carron --pk $RISCV/riscv32-unknown-elf/bin/pk ./HelloWorld

In file HelloWorld
Expand All @@ -73,3 +75,38 @@ elfcheck: OK
bbl loader
hello world!
```

```zsh
$ git clone https://github.com/buildroot/buildroot
$ cd buildroot
$ make spike_riscv64_defconfig
$ make menuconfig # disable F extension
$ make -j $(nproc)
$ ./carron --release -- --kernel /path/to/Image --initrd /path/to/rootfs.cpio /path/to/fw_jump.elf
In file /home/takana/riscv-toolchain/buildroot/output/images/fw_jump.elf
elfcheck: OK


OpenSBI v1.2
____ _____ ____ _____
/ __ \\ / ____| _ \\_ _|
| | | |_ __ ___ _ __ | (___ | |_) || |
| | | | '_ \\ / _ \\ '_ \\ \\___ \\| _ < | |
| |__| | |_) | __/ | | |____) | |_) || |_
\\____/| .__/ \\___|_| |_|_____/|____/_____|
| |
|_|

......

[ 0.091080] Freeing unused kernel image (initmem) memory: 2144K
[ 0.097300] Run /init as init process
Starting syslogd: OK
Starting klogd: OK
Running sysctl: OK
Saving 256 bits of non-creditable seed for next boot
Starting network: OK

Welcome to Buildroot
buildroot login:
```
29 changes: 18 additions & 11 deletions src/bus.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ mod mrom;
mod plic;
mod uart;

use crate::{elfload, Isa, TrapCause};
use crate::{elfload, Arguments, Isa, TrapCause};
use clint::Clint;
use dram::Dram;
use mrom::Mrom;
Expand All @@ -16,18 +16,18 @@ pub struct Bus {
pub mrom: mrom::Mrom,
pub clint: clint::Clint,
pub dram: dram::Dram,
uart: uart::Uart,
plic: plic::Plic,
pub uart: uart::Uart,
pub plic: plic::Plic,
}

impl Bus {
pub fn new(loader: elfload::ElfLoader, isa: Isa) -> Self {
pub fn new(loader: elfload::ElfLoader, args: &Arguments, isa: Isa) -> Self {
// load proxy kernel before user program when it's given
let dram = Dram::new(loader);
let dram = Dram::new(loader, args, isa);
let mut mrom = Mrom::new(dram.base_addr, isa);

// create and load DTB
mrom.load_dtb(dram.base_addr, isa);
mrom.load_dtb(dram.base_addr, dram.initrd_start, dram.initrd_end, isa);

Bus {
mrom,
Expand All @@ -47,7 +47,14 @@ impl Bus {
} else if self.dram.in_range(addr) {
self.dram.store8(addr, data)
} else if self.uart.in_range(addr) {
self.uart.store8(addr, data)
let result = self.uart.store8(addr, data);
if let Some(interrupt_level) = self.uart.interrupt_level {
const UART_INTERRUPT_ID: u32 = 1;
self.plic
.set_interrupt_level(UART_INTERRUPT_ID, interrupt_level);
self.uart.interrupt_level = None;
}
result
} else if self.plic.in_range(addr) {
self.plic.store8(addr, data)
} else {
Expand Down Expand Up @@ -172,7 +179,7 @@ impl Bus {
}
}

pub fn load32(&self, addr: u64) -> Result<u64, (Option<u64>, TrapCause, String)> {
pub fn load32(&mut self, addr: u64) -> Result<u64, (Option<u64>, TrapCause, String)> {
if self.mrom.in_range(addr) {
self.mrom.load32(addr)
} else if self.clint.in_range(addr) {
Expand All @@ -192,7 +199,7 @@ impl Bus {
}
}

pub fn load64(&self, addr: u64) -> Result<u64, (Option<u64>, TrapCause, String)> {
pub fn load64(&mut self, addr: u64) -> Result<u64, (Option<u64>, TrapCause, String)> {
if self.mrom.in_range(addr) {
self.mrom.load64(addr)
} else if self.clint.in_range(addr) {
Expand Down Expand Up @@ -282,8 +289,8 @@ pub trait Device {
fn store64(&mut self, addr: u64, data: u64) -> Result<(), (Option<u64>, TrapCause, String)>;
fn load8(&mut self, addr: u64) -> Result<u64, (Option<u64>, TrapCause, String)>;
fn load16(&self, addr: u64) -> Result<u64, (Option<u64>, TrapCause, String)>;
fn load32(&self, addr: u64) -> Result<u64, (Option<u64>, TrapCause, String)>;
fn load64(&self, addr: u64) -> Result<u64, (Option<u64>, TrapCause, String)>;
fn load32(&mut self, addr: u64) -> Result<u64, (Option<u64>, TrapCause, String)>;
fn load64(&mut self, addr: u64) -> Result<u64, (Option<u64>, TrapCause, String)>;
fn load_u8(&self, addr: u64) -> Result<u64, (Option<u64>, TrapCause, String)>;
fn load_u16(&self, addr: u64) -> Result<u64, (Option<u64>, TrapCause, String)>;
fn load_u32(&self, addr: u64) -> Result<u64, (Option<u64>, TrapCause, String)>;
Expand Down
4 changes: 2 additions & 2 deletions src/bus/clint.rs
Original file line number Diff line number Diff line change
Expand Up @@ -94,15 +94,15 @@ impl Device for Clint {
))
}

fn load32(&self, addr: u64) -> Result<u64, (Option<u64>, TrapCause, String)> {
fn load32(&mut self, addr: u64) -> Result<u64, (Option<u64>, TrapCause, String)> {
let addr = self.addr2index(addr);
Ok(((self.clint[addr + 3] as i32) << 24
| (self.clint[addr + 2] as i32) << 16
| (self.clint[addr + 1] as i32) << 8
| (self.clint[addr + 0] as i32)) as i64 as u64)
}

fn load64(&self, addr: u64) -> Result<u64, (Option<u64>, TrapCause, String)> {
fn load64(&mut self, addr: u64) -> Result<u64, (Option<u64>, TrapCause, String)> {
let addr = self.addr2index(addr);
Ok((self.clint[addr + 7] as u64) << 56
| (self.clint[addr + 6] as u64) << 48
Expand Down
17 changes: 15 additions & 2 deletions src/bus/device_tree.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,23 @@ use super::mrom::Mrom;
use crate::Isa;

impl Mrom {
pub fn load_dtb(&mut self, dram_addr: u64, isa: Isa) {
let dts: String = dts::make_dts(dram_addr, isa).replace(" ", "");
pub fn load_dtb(
&mut self,
dram_addr: u64,
initrd_start: Option<usize>,
initrd_end: Option<usize>,
isa: Isa,
) {
let dts: String = dts::make_dts(dram_addr, initrd_start, initrd_end, isa).replace(" ", "");
let dtb: Vec<u8> = dtb::make_dtb(dts);
self.mrom.extend(dtb);

const MROM_ALIGN: usize = 0x1000;
self.mrom.resize(
(self.mrom.len() + MROM_ALIGN - 1) / MROM_ALIGN * MROM_ALIGN,
0,
);

self.set_size();
}
}
31 changes: 22 additions & 9 deletions src/bus/device_tree/dts.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
use crate::Isa;

fn dts_32(dram_addr: u64) -> String {
fn dts_32(dram_addr: u64, initrd_start: Option<usize>, initrd_end: Option<usize>) -> String {
let initrd_start = initrd_start.unwrap_or(0);
let initrd_end = initrd_end.unwrap_or(0);
format!(
"/dts-v1/;
/ {{
Expand All @@ -10,7 +12,9 @@ fn dts_32(dram_addr: u64) -> String {
model = \"ucbbar,spike-bare\";
chosen {{
stdout-path = &SERIAL0;
bootargs = \"console=ttyS0 earlycon\";
linux,initrd-start = <{initrd_start}>;
linux,initrd-end = <{initrd_end}>;
bootargs = \"root=/dev/ram console=ttyS0 earlycon\";
}};
cpus {{
#address-cells = <1>;
Expand All @@ -36,7 +40,7 @@ fn dts_32(dram_addr: u64) -> String {
}};
memory@{dram_addr:x} {{
device_type = \"memory\";
reg = <0x0 0x{dram_addr:x} 0x0 0x{dram_addr:x}>;
reg = <0x0 {dram_addr:#x} 0x0 0x80000000>;
}};
soc {{
#address-cells = <2>;
Expand Down Expand Up @@ -75,7 +79,9 @@ fn dts_32(dram_addr: u64) -> String {
)
}

fn dts_64(dram_addr: u64) -> String {
fn dts_64(dram_addr: u64, initrd_start: Option<usize>, initrd_end: Option<usize>) -> String {
let initrd_start = initrd_start.unwrap_or(0);
let initrd_end = initrd_end.unwrap_or(0);
format!(
"/dts-v1/;
Expand All @@ -86,7 +92,9 @@ fn dts_64(dram_addr: u64) -> String {
model = \"ucbbar,spike-bare\";
chosen {{
stdout-path = &SERIAL0;
bootargs = \"console=ttyS0 earlycon\";
linux,initrd-start = <{initrd_start}>;
linux,initrd-end = <{initrd_end}>;
bootargs = \"root=/dev/ram console=ttyS0 earlycon\";
}};
cpus {{
#address-cells = <1>;
Expand All @@ -112,7 +120,7 @@ fn dts_64(dram_addr: u64) -> String {
}};
memory@{dram_addr:x} {{
device_type = \"memory\";
reg = <0x0 {dram_addr:x} 0x0 0x80000000>;
reg = <0x0 {dram_addr:#x} 0x0 0x80000000>;
}};
soc {{
#address-cells = <2>;
Expand Down Expand Up @@ -151,9 +159,14 @@ fn dts_64(dram_addr: u64) -> String {
)
}

pub fn make_dts(dram_addr: u64, isa: Isa) -> String {
pub fn make_dts(
dram_addr: u64,
initrd_start: Option<usize>,
initrd_end: Option<usize>,
isa: Isa,
) -> String {
match isa {
Isa::Rv32 => dts_32(dram_addr),
Isa::Rv64 => dts_64(dram_addr),
Isa::Rv32 => dts_32(dram_addr, initrd_start, initrd_end),
Isa::Rv64 => dts_64(dram_addr, initrd_start, initrd_end),
}
}
Loading

0 comments on commit f658bf5

Please sign in to comment.