resources: update riscv-fs resource for gem5-develop
This change also removes the device.dts file as bbl
no longer needs to be compiled with a device tree rather
it can be created through gem5 config scripts.
Change-Id: Ib52dc8709c436efc3afd4951a413d4477555b6ab
Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5-resources/+/46019
Reviewed-by: Hoa Nguyen <hoanguyen@ucdavis.edu>
Maintainer: Jason Lowe-Power <power.jg@gmail.com>
Tested-by: Jason Lowe-Power <power.jg@gmail.com>
diff --git a/src/riscv-fs/README.md b/src/riscv-fs/README.md
index 08b386e..cdca282 100644
--- a/src/riscv-fs/README.md
+++ b/src/riscv-fs/README.md
@@ -17,7 +17,7 @@
The used disk image is based on [busybox](https://busybox.net/) and [UCanLinux](https://github.com/UCanLinux/). It is built using the instructions, mostly from [here](https://github.com/UCanLinux/riscv64-sample).
-All components are cross compiled on an x86 host using a riscv tool chain.
+**Note:** All components are cross compiled on an x86 host using a riscv tool chain. We used `88b004d4c2a7d4e4f08b17ee32d2` commit of the riscv tool chain source while building the source (riscv gcc version 10.2.0).
We assume the following directory structure while following the instructions in this README file:
@@ -27,8 +27,6 @@
|
|___ riscv-disk # built disk image will go here
|
- |___ device.dts # device tree file to use with bbl
- |
|___ riscv-gnu-toolchain # riscv tool chain for cross compilation
|
|___ riscv64-sample # UCanLinux source
@@ -57,6 +55,7 @@
# clone riscv gnu toolchain source
git clone https://github.com/riscv/riscv-gnu-toolchain
cd riscv-gnu-toolchain
+git checkout 88b004d4c2a7d4e4f08b17ee32d2
# change the prefix to your directory
# of choice for installation of the
@@ -86,7 +85,7 @@
git clone https://github.com/UCanLinux/riscv64-sample
```
-This source contains already built bootloader and disk images as well. Though the given disk image might be usable with gem5, the `bbl` (bootloader image) will not work with gem5 and we need to compile `bbl` with an input device tree (`.dts`) file separately. The following sections provide instructions to build both `bbl` and disk images.
+The following sections provide instructions to build both `bbl` and disk images.
## Linux Kernel
@@ -130,10 +129,9 @@
apt-get install device-tree-compiler
-# copy the device tree file from riscv-fs
-cp ../../../device.dts .
+# configure bbl build
+../configure --host=riscv64-unknown-linux-gnu --with-payload=../../linux/vmlinux --prefix=/opt/riscv/
-../configure --host=riscv64-unknown-linux-gnu --with-payload=../../linux/vmlinux --prefix=/opt/riscv/ --with-dts=device.dts
make -j$(nproc)
chmod 755 bbl
@@ -155,7 +153,7 @@
cd busybox
git checkout 1_30_stable # checkout the latest stable branch
make menuconfig
-cp ../sample/busybox.config .config # optional
+cp ../busybox.config .config # optional
make menuconfig
make CROSS_COMPILE=riscv64-unknown-linux-gnu- all -j$(nproc)
make CROSS_COMPILE=riscv64-unknown-linux-gnu- install
@@ -167,7 +165,7 @@
```sh
# going back to riscv64-sample directory
-cd ../..
+cd ../
mkdir RootFS
cd RootFS
@@ -191,10 +189,10 @@
# build m5 util for riscv and move
# it to the root file system as well
-cd ../../../
+cd ../../../../
cd gem5/util/m5
-scons -C util/m5 build/riscv/out/m5
-cp build/riscv/out/m5 ../../../RootFS/sbin/
+scons build/riscv/out/m5
+cp build/riscv/out/m5 ../../../riscv64-sample/RootFS/sbin/
```
## Disk Image
@@ -214,12 +212,10 @@
sudo mkdir /mnt/rootfs
sudo mount riscv_disk /mnt/rootfs
-sudo cp -a RootFS/* /mnt/rootfs
+sudo cp -a riscv64-sample/RootFS/* /mnt/rootfs
sudo chown -R -h root:root /mnt/rootfs/
df /mnt/rootfs
-# make sure you are in riscv64-sample dir
-cd ../riscv64-sample
sudo umount /mnt/rootfs
```
@@ -254,7 +250,7 @@
An example use of this script is the following:
```sh
-[gem5 binary] -re configs/run_exit.py [path to bbl] [path to the disk image] atomic 4
+[gem5 binary] -re configs/run_riscv.py [path to bbl] [path to the disk image] atomic 1
```
To interact with the simulated system's console:
diff --git a/src/riscv-fs/configs-riscv-fs/run_riscv.py b/src/riscv-fs/configs-riscv-fs/run_riscv.py
index 1ca8665..3e3b747 100755
--- a/src/riscv-fs/configs-riscv-fs/run_riscv.py
+++ b/src/riscv-fs/configs-riscv-fs/run_riscv.py
@@ -26,8 +26,8 @@
"""
This script is supposed to run full system simulation for RISCV targets.
-It has been tested with classic memory system and Atomic
-and TimingSimpleCPU so far.
+It has been tested with classic memory system and Atomic,
+TimingSimpleCPU, and MinorCPU so far.
"""
import time
diff --git a/src/riscv-fs/configs-riscv-fs/system/system.py b/src/riscv-fs/configs-riscv-fs/system/system.py
index 0150972..94dfd6c 100755
--- a/src/riscv-fs/configs-riscv-fs/system/system.py
+++ b/src/riscv-fs/configs-riscv-fs/system/system.py
@@ -23,10 +23,12 @@
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
import m5
from m5.objects import *
from m5.util import convert
+from os import path
'''
This class creates a bare bones RISCV full system.
@@ -37,6 +39,43 @@
d3c2-44ea-85fb-acc1df282e21_FU540-C000-v1p3.pdf
'''
+# Dtb generation code from configs/example/riscv/fs_linux.py
+def generateMemNode(state, mem_range):
+ node = FdtNode("memory@%x" % int(mem_range.start))
+ node.append(FdtPropertyStrings("device_type", ["memory"]))
+ node.append(FdtPropertyWords("reg",
+ state.addrCells(mem_range.start) +
+ state.sizeCells(mem_range.size()) ))
+ return node
+
+def generateDtb(system):
+ """
+ Autogenerate DTB. Arguments are the folder where the DTB
+ will be stored, and the name of the DTB file.
+ """
+ state = FdtState(addr_cells=2, size_cells=2, cpu_cells=1)
+ root = FdtNode('/')
+ root.append(state.addrCellsProperty())
+ root.append(state.sizeCellsProperty())
+ root.appendCompatible(["riscv-virtio"])
+
+ for mem_range in system.mem_ranges:
+ root.append(generateMemNode(state, mem_range))
+
+ sections = [*system.cpu, system.platform]
+
+ for section in sections:
+ for node in section.generateDeviceTree(state):
+ if node.get_name() == root.get_name():
+ root.merge(node)
+ else:
+ root.append(node)
+
+ fdt = Fdt()
+ fdt.add_rootnode(root)
+ fdt.writeDtsFile(path.join(m5.options.outdir, 'device.dts'))
+ fdt.writeDtbFile(path.join(m5.options.outdir, 'device.dtb'))
+
class RiscvSystem(System):
def __init__(self, bbl, disk, cpu_type, num_cpus):
@@ -55,41 +94,24 @@
# This connects to main memory
self.membus = SystemXBar(width = 64) # 64-byte width
+ # Add a bad addr responder
+ self.membus.badaddr_responder = BadAddr()
+ self.membus.default = self.membus.badaddr_responder.pio
+
# Set up the system port for functional access from the simulator
self.system_port = self.membus.cpu_side_ports
# Create the CPUs for our system.
self.createCPU(cpu_type, num_cpus)
- # using RISCV bare metal as the base full system workload
- self.workload = RiscvBareMetal()
-
- # this is user passed berkeley boot loader binary
- # currently the Linux kernel payload is compiled into this
- # as well
- self.workload.bootloader = bbl
-
# HiFive platform
# This is based on a HiFive RISCV board and has
# only a limited number of devices so far i.e.
# PLIC, CLINT, UART, VirtIOMMIO
self.platform = HiFive()
- # Next, create and intialize devices
- # currently supported for RISCV
-
- # add a disk image
- self.attachDisk(disk)
-
- # set up core and platform
- # level interrupt controllers
- self.setupIntrCtrl()
-
- # set up PMA checker
- self.pmaChecker()
-
- # attach off and on chip IO
- self.attachIO(self.membus)
+ # create and intialize devices currently supported for RISCV
+ self.initDevices(self.membus, disk)
# Create the cache heirarchy for the system.
self.createCacheHierarchy()
@@ -99,6 +121,28 @@
self.setupInterrupts()
+ # using RiscvLinux as the base full system workload
+ self.workload = RiscvLinux()
+
+ # this is user passed berkeley boot loader binary
+ # currently the Linux kernel payload is compiled into this
+ # as well
+ self.workload.object_file = bbl
+
+ # Generate DTB (from configs/example/riscv/fs_linux.py)
+ generateDtb(self)
+ self.workload.dtb_filename = path.join(m5.options.outdir, 'device.dtb')
+ # Default DTB address if bbl is bulit with --with-dts option
+ self.workload.dtb_addr = 0x87e00000
+
+ # Linux boot command flags
+ kernel_cmd = [
+ "console=ttyS0",
+ "root=/dev/vda",
+ "ro"
+ ]
+ self.workload.command_line = " ".join(kernel_cmd)
+
def createCPU(self, cpu_type, num_cpus):
if cpu_type == "atomic":
self.cpu = [AtomicSimpleCPU(cpu_id = i)
@@ -108,6 +152,10 @@
self.cpu = [TimingSimpleCPU(cpu_id = i)
for i in range(num_cpus)]
self.mem_mode = 'timing'
+ elif cpu_type == "minor":
+ self.cpu = [MinorCPU(cpu_id = i)
+ for i in range(num_cpus)]
+ self.mem_mode = 'timing'
else:
m5.fatal("No CPU type {}".format(cpu_type))
@@ -170,20 +218,11 @@
port = self.membus.mem_side_ports)
]
- def attachIO(self, membus):
+ def initDevices(self, membus, disk):
+
self.iobus = IOXBar()
+ self.intrctrl = IntrControl()
- self.bridge = Bridge(delay='50ns')
- self.bridge.master = self.iobus.slave
- self.bridge.slave = self.membus.master
- self.bridge.ranges = self.platform._off_chip_ranges()
-
- # Connecting on chip and off chip IO to the mem
- # and IO bus
- self.platform.attachOnChipIO(self.membus)
- self.platform.attachOffChipIO(self.iobus)
-
- def setupIntrCtrl(self):
# Set the frequency of RTC (real time clock) used by
# CLINT (core level interrupt controller).
# This frequency is 1MHz in SiFive's U54MC.
@@ -193,12 +232,17 @@
# RTC sends the clock signal to CLINT via an interrupt pin.
self.platform.clint.int_pin = self.platform.rtc.int_pin
- # Attach the PLIC (platform level interrupt controller)
- # to the platform. This initializes the PLIC with
- # interrupt sources coming from off chip devices
- self.platform.attachPlic()
+ # VirtIOMMIO
+ image = CowDiskImage(child=RawDiskImage(read_only=True), read_only=False)
+ image.child.image_file = disk
+ # using reserved memory space
+ self.platform.disk = MmioVirtIO(
+ vio=VirtIOBlock(image=image),
+ interrupt_id=0x8,
+ pio_size = 4096,
+ pio_addr=0x10008000
+ )
- def pmaChecker(self):
# From riscv/fs_linux.py
uncacheable_range = [
*self.platform._on_chip_ranges(),
@@ -211,16 +255,20 @@
# or MMU-level (system.cpu[0].mmu.pma_checker). It will be resolved
# by RiscvTLB's Parent.any proxy
- self.pma_checker = PMAChecker(uncacheable=uncacheable_range)
+ for cpu in self.cpu:
+ cpu.mmu.pma_checker = PMAChecker(uncacheable=uncacheable_range)
- def attachDisk(self, disk):
- # VirtIOMMIO
- image = CowDiskImage(child=RawDiskImage(read_only=True), read_only=False)
- image.child.image_file = disk
- # using reserved memory space
- self.platform.disk = MmioVirtIO(
- vio=VirtIOBlock(image=image),
- interrupt_id=0x8,
- pio_size = 4096,
- pio_addr=0x10008000
- )
+ self.bridge = Bridge(delay='50ns')
+ self.bridge.mem_side_port = self.iobus.cpu_side_ports
+ self.bridge.cpu_side_port = self.membus.mem_side_ports
+ self.bridge.ranges = self.platform._off_chip_ranges()
+
+ # Connecting on chip and off chip IO to the mem
+ # and IO bus
+ self.platform.attachOnChipIO(self.membus)
+ self.platform.attachOffChipIO(self.iobus)
+
+ # Attach the PLIC (platform level interrupt controller)
+ # to the platform. This initializes the PLIC with
+ # interrupt sources coming from off chip devices
+ self.platform.attachPlic()
diff --git a/src/riscv-fs/device.dts b/src/riscv-fs/device.dts
deleted file mode 100644
index 7181c6c..0000000
--- a/src/riscv-fs/device.dts
+++ /dev/null
@@ -1,80 +0,0 @@
-/dts-v1/;
-
-/ {
- #address-cells = <0x2>;
- #size-cells = <0x2>;
- compatible = "riscv-virtio";
- model = "riscv-virtio,qemu";
-
- chosen {
- bootargs = "root=/dev/vda ro console=ttyS0";
- stdout-path = "/soc/uart@10000000";
- };
-
- memory@80000000 {
- device_type = "memory";
- reg = <0x0 0x80000000 0x0 0x8000000>;
- };
-
- cpus {
- #address-cells = <0x1>;
- #size-cells = <0x0>;
- timebase-frequency = <0x989680>;
-
- cpu@0 {
- phandle = <0x1>;
- device_type = "cpu";
- reg = <0x0>;
- status = "okay";
- compatible = "riscv";
- riscv,isa = "rv64imafdcsu";
- mmu-type = "riscv,sv48";
-
- interrupt-controller {
- #interrupt-cells = <0x1>;
- interrupt-controller;
- compatible = "riscv,cpu-intc";
- phandle = <0x2>;
- };
- };
- };
-
- soc {
- #address-cells = <0x2>;
- #size-cells = <0x2>;
- compatible = "simple-bus";
- ranges;
-
- uart@10000000 {
- interrupts = <0xa>;
- interrupt-parent = <0x3>;
- clock-frequency = <0x384000>;
- reg = <0x0 0x10000000 0x0 0x008>;
- compatible = "ns8250";
- };
-
- plic@c000000 {
- phandle = <0x3>;
- riscv,ndev = <0xa>;
- reg = <0x0 0xc000000 0x0 0x210000>;
- interrupts-extended = <0x2 0xb 0x2 0x9>;
- interrupt-controller;
- compatible = "riscv,plic0";
- #interrupt-cells = <0x1>;
- #address-cells = <0x0>;
- };
-
- virtio_mmio@10008000 {
- interrupts = <0x8>;
- interrupt-parent = <0x3>;
- reg = <0x0 0x10008000 0x0 0x1000>;
- compatible = "virtio,mmio";
- };
-
- clint@2000000 {
- interrupts-extended = <0x2 0x3 0x2 0x7>;
- reg = <0x0 0x2000000 0x0 0x10000>;
- compatible = "riscv,clint0";
- };
- };
-};