Dear Gem5 community,
I try to add PCI interface in RISCV arch doing the following steps
(similar with ARM RealView - I use the gem5-v21):
1) Create a file gem5/src/dev/riscv/pci_host.cc with the following code:
#include "dev/riscv/pci_host.hh"
#include "params/GenericRiscvPciHost.hh"
GenericRiscvPciHost::GenericRiscvPciHost(const GenericRiscvPciHostParams
&p)
: GenericPciHost(p), intBase(p.int_base), intCount(p.int_count)
{
}
uint32_t
GenericRiscvPciHost::mapPciInterrupt(
const PciBusAddr &addr, PciIntPin pin) const
{
fatal_if(pin == PciIntPin::NO_INT,
"%02x:%02x.%i: Interrupt from a device without interrupts\n",
addr.bus, addr.dev, addr.func);
return intBase + (addr.dev % intCount);
}
2) Create a file gem5/src/dev/riscv/pci_host.hh with the following code:
#ifndef __DEV_RISCV_PCI_HOST_HH__
#define __DEV_RISCV_PCI_HOST_HH__
#include "dev/pci/host.hh"
struct GenericRiscvPciHostParams;
class GenericRiscvPciHost : public GenericPciHost
{
private:
const uint32_t intBase;
const uint32_t intCount;
public:
GenericRiscvPciHost(const GenericRiscvPciHostParams &p);
virtual ~GenericRiscvPciHost() {}
protected:
uint32_t mapPciInterrupt(const PciBusAddr &addr,
PciIntPin pin) const override;
};
#endif // __DEV_RISCV_PCI_HOST_HH__
3) Add the "Source('pci_host.cc')" to gem5/src/dev/riscv/SConscript
4) Add the following code in gem5/src/dev/riscv/HiFive.py according to
RealView GenericArmPciHost:
from m5.objects.Ethernet import NSGigE, IGbE_igb, IGbE_e1000
from m5.objects.Device import BasicPioDevice
from m5.objects.PciHost import *
from m5.SimObject import SimObject
class GenericRiscvPciHost(GenericPciHost): #Add this class (PCI)
type = 'GenericRiscvPciHost'
cxx_header = "dev/riscv/pci_host.hh"
int_base = Param.Unsigned("PCI interrupt base")
int_count = Param.Unsigned("Maximum number of interrupts used by
this host")
# This python parameter can be used in configuration scripts to turn
# on/off the fdt dma-coherent flag when doing dtb autogeneration
_dma_coherent = True
def generateDeviceTree(self, state):
local_state = FdtState(
addr_cells=3, size_cells=2,
cpu_cells=1, interrupt_cells=1)
node = FdtNode("pci")
if int(self.conf_device_bits) == 8:
node.appendCompatible("pci-host-cam-generic")
elif int(self.conf_device_bits) == 12:
node.appendCompatible("pci-host-ecam-generic")
else:
m5.fatal("No compatibility string for the set
conf_device_width")
node.append(FdtPropertyStrings("device_type", ["pci"]))
# Cell sizes of child nodes/peripherals
node.append(local_state.addrCellsProperty())
node.append(local_state.sizeCellsProperty())
node.append(local_state.interruptCellsProperty())
# PCI address for CPU
node.append(FdtPropertyWords("reg",
state.addrCells(self.conf_base) +
state.sizeCells(self.conf_size) ))
# Ranges mapping
# For now some of this is hard coded, because the PCI module does
not
# have a proper full understanding of the memory map, but
adapting the
# PCI module is beyond the scope of what I'm trying to do here.
# Values are taken from the VExpress_GEM5_V1 platform.
ranges = []
# Pio address range
ranges += self.pciFdtAddr(space=1, addr=0)
ranges += state.addrCells(self.pci_pio_base)
ranges += local_state.sizeCells(0x10000) # Fixed size
# AXI memory address range
ranges += self.pciFdtAddr(space=2, addr=0)
ranges += state.addrCells(self.pci_mem_base)
ranges += local_state.sizeCells(0x40000000) # Fixed size
node.append(FdtPropertyWords("ranges", ranges))
if True:
#Change this to True because Realview calls always
ARM_PCI_INT_DEV
plic = self._parent.unproxy(self).plic
int_phandle = state.phandle(plic)
# Interrupt mapping
interrupts = []
# child interrupt specifier
child_interrupt = local_state.interruptCells(0x0)
# parent unit address
parent_addr = 0x0
#get this from /gem5/system/arm/dt/platforms file
for i in range(int(self.int_count)):
parent_interrupt = int(self.int_base) + i
#RISCV uses only 1 interrupt_cell in plic
interrupts += self.pciFdtAddr(device=i, addr=0) + \
child_interrupt + [int_phandle] + [parent_addr] + \
[parent_interrupt]
node.append(FdtPropertyWords("interrupt-map", interrupts))
int_count = int(self.int_count)
if int_count & (int_count - 1):
fatal("PCI interrupt count should be power of 2")
intmask = self.pciFdtAddr(device=int_count - 1, addr=0) +
[0x0]
node.append(FdtPropertyWords("interrupt-map-mask", intmask))
else:
m5.fatal("Unsupported PCI interrupt policy " +
"for Device Tree generation")
if self._dma_coherent:
node.append(FdtProperty("dma-coherent"))
yield node
class HiFive(Platform):
.........
pci_host = GenericRiscvPciHost(
#Add these 3 lines (PCI)
conf_base=0x30000000, conf_size='256MiB', conf_device_bits=12,
pci_pio_base=0x2f000000, pci_mem_base=0x40000000,
int_base=100, int_count=4)
ethernet = IGbE_e1000(pci_bus=0, pci_dev=0, pci_func=0,
#Add IGbE_e1000 PCI device (PCI)
InterruptLine=1, InterruptPin=1)
def attachPlic(self):
"""Count number of PLIC interrupt sources
"""
plic_srcs = [self.uart_int_id]
plic_srcs.append(self.pci_host.int_base) #Add this line (PCI)
for device in self._off_chip_devices():
if hasattr(device, "interrupt_id"):
plic_srcs.append(device.interrupt_id)
self.plic.n_src = max(plic_srcs) + 1
5) Add the following code in gem5/configs/example/riscv/fs_linux.py :
#system.bridge.ranges = system.platform._off_chip_ranges() #Replaced
from 3 lines below
range_list = system.platform._off_chip_ranges()
range_list.append(AddrRange(0x2f000000, 0x80000000))
system.bridge.ranges = range_list
system.platform.pci_host.pio = system.iobus.mem_side_ports
system.platform.ethernet.host = system.platform.pci_host
system.platform.ethernet.pio = system.iobus.mem_side_ports
system.platform.ethernet.dma = system.iobus.cpu_side_ports
6) To be noticed that I use the prebuilt files from here:
https://github.com/ppeetteerrs/gem5-RISC-V-FS-Linux/. In addition, I
add the PCI and e1000 drivers to kernel.config and build the Linux
Kernel v5.10 according to this github:
CONFIG_PCI_SYSCALL=y
CONFIG_PCI_STUB=y
CONFIG_PCI_HOST_GENERIC=y
CONFIG_NET_VENDOR_INTEL=y
CONFIG_E1000=y
CONFIG_E1000E=y
CONFIG_IGB=y
CONFIG_NET_VENDOR_I825XX=y
However, when I try to execute the gem5 (build/RISCV/gem5.opt -d
$RISCV/logs configs/example/riscv/fs_linux.py --kernel=$OUT/bbl
--caches --mem-size=1024MB --mem-type=DDR4_2400_8x8
--cpu-type=AtomicSimpleCPU --disk-image=$OUT/riscv_parsec_disk -n 1) I
get the following panic:
info: Entering event queue @ 0. Starting simulation...
1086842500: system.platform.terminal: attach terminal 0
panic: invalid access size(?) for PCI configspace!
Memory Usage: 437656 KBytes
Program aborted at tick 18474133000
Please help me to add PCI interface correctly! I think that it will be
very useful to gem5 community in order to add a wide range of PCI
devices!
You can find the files with the above changes here:
https://www.dropbox.com/s/pf4iu3z31zy88vr/riscv_pci.tar.xz
Best regards,
Nikolaos
_______________________________________________
gem5-users mailing list -- gem5-users@gem5.org
To unsubscribe send an email to gem5-users-le...@gem5.org
%(web_page_url)slistinfo%(cgiext)s/%(_internal_name)s