VDK Platform Guide: Linux-Booting Keraunos PCIe Tile
Version: 1.0
Date: March 26, 2026
Author: System Architecture Team
1. Introduction
This guide documents the final validated Synopsys Virtualizer (VDK) platform that boots RISC-V Linux on the host chiplet, enumerates a PCIe Endpoint connected to the Keraunos PCIe Tile, and enables data transfer from the host to memory attached to the tile’s noc_n_initiator port.
The reference implementation is at /localdev/pdroy/ruchika_ws/Keraunos_PCIE_Tile.
1.1 What This Platform Demonstrates
Full Linux boot on a RISC-V virtual CPU (TT_Rocket_LT) via OpenSBI
PCIe link-up between a DesignWare Root Complex (host) and Endpoint (device)
Linux kernel PCIe enumeration using the
snps,dw-pciedriverBAR0 mapping and MMIO access from Linux userspace
End-to-end data transfer: Host → RC → EP → PCIE_TILE →
noc_n_initiator→ Target_Memory
2. Platform Architecture
2.1 Two-Chiplet Topology
The VDK instantiates two chiplet groups with a direct PCIe link:
2.2 PCIe Link Wiring
The PCIe link uses direct peer-to-peer binding:
Source |
Destination |
Purpose |
|---|---|---|
|
|
Downstream TLPs (host → device) |
|
|
Upstream TLPs (device → host) |
|
|
RC DMA to host memory |
|
|
EP delivers inbound TLPs to tile |
|
|
Tile sends outbound TLPs to EP |
2.3 PCIE_TILE Interface Connections
The Keraunos PCIe Tile connects to the chiplet’s SharedMemoryMap and EP:
Tile Port |
Direction |
Connected To |
Address / Offset |
|---|---|---|---|
|
Target (in) |
EP BusMaster |
Inbound TLPs from host |
|
Initiator (out) |
EP AXI_Slave |
Outbound TLPs to host |
|
Initiator (out) |
SharedMemoryMap (left) |
Start 0x0 |
|
Target (in) |
SharedMemoryMap (right) |
0x44400000, 16 MB |
|
Initiator (out) |
SharedMemoryMap (left) |
Start 0x0 |
|
Target (in) |
SharedMemoryMap (right) |
0x18000000, 8 MB |
3. Memory Maps
3.1 Host_Chiplet CPU Address Space
Address |
Size |
Target |
Description |
|---|---|---|---|
|
64 KB |
CLINT |
Machine timer and software interrupts |
|
4 MB |
PCIE_RC DBI |
RC configuration registers (DesignWare DBI) |
|
128 KB |
PCIE_RC ATU |
iATU outbound/inbound (via DBI CS2 range) |
|
256 MB |
PCIE_RC AXI_Slave |
PCIe outbound window |
|
16 MB |
— Config |
Type 0/1 Configuration TLPs (iATU-translated) |
|
240 MB |
— MEM |
Memory Read/Write TLPs to EP BARs |
|
256 MB |
DRAM |
Host main memory (OpenSBI + Linux + initramfs) |
|
256 B |
UART |
DW APB UART, 115.2 MHz clock, 7.2 Mbaud |
|
2 MB |
PLIC |
RISC-V PLIC, 64 interrupt sources |
4. Linux Boot
4.1 Boot Flow
Virtualizer loads images:
fw_payload.elfon Host_Chiplet CPU,pcie_bringup.elfon Device CPUOpenSBI initializes M-mode on Host CPU at entry
0x80000000OpenSBI transitions to S-mode and jumps to the embedded Linux kernel
Linux parses the compiled device tree (
keraunos_host.dtb)Kernel initializes CLINT (timer), PLIC (interrupts), UART (console)
The
snps,dw-pciedriver probes the PCIe RC at DBI0x44000000Driver programs iATU outbound windows and scans bus 1
EP is enumerated: vendor/device ID read, BARs assigned
Linux mounts initramfs and launches
/init(BusyBox shell)The
pcie_xferapplication is available for PCIe data transfer
4.2 Device Tree Highlights
/ {
compatible = "tt,smc-pcie-tile";
cpus { cpu@0 { riscv,isa = "rv64imac"; mmu-type = "riscv,sv39"; }; };
memory@80000000 { reg = <0x0 0x80000000 0x0 0x10000000>; }; /* 256 MB */
soc {
clint@2000000 { reg = <0x0 0x02000000 0x0 0x10000>; };
plic@c4000000 { riscv,ndev = <64>; };
uart@c000a000 { clock-frequency = <0x6DDD000>; }; /* 115.2 MHz */
pcie@44000000 {
compatible = "snps,dw-pcie";
reg = <0x0 0x44000000 0x0 0x400000>, /* DBI */
<0x0 0x70000000 0x0 0x01000000>; /* config */
bus-range = <0x0 0x1>;
ranges = <0x02000000 0x0 0x71000000
0x0 0x71000000 0x0 0x0F000000>; /* 240 MB MEM */
interrupts = <32>, <33>; /* MSI, INTx */
num-lanes = <4>;
};
};
chosen {
bootargs = "console=hvc0 earlycon=sbi rdinit=/init
pci=realloc pci=assign-busses pci=noaer pcie_aspm=off";
};
};
4.3 Key Boot Parameters
Parameter |
Value |
Purpose |
|---|---|---|
|
HVC console |
Uses SBI console calls (fastest in VP) |
|
SBI earlycon |
Early console via OpenSBI ecall |
|
Initramfs init |
Uses embedded initramfs (no disk) |
|
PCI realloc |
Reallocate PCI resources (no BIOS pre-assignment) |
|
Assign buses |
Force bus number assignment |
|
Disable AER |
Advanced Error Reporting not needed in VP |
|
Disable ASPM |
Active State Power Management not modeled |
4.4 Toolchain Requirements
Component |
Toolchain |
ISA |
Notes |
|---|---|---|---|
Linux kernel |
ASC GCC 14 ( |
rv64imac |
|
Initramfs (BusyBox) |
Musl ( |
rv64imac / lp64 |
Soft-float, static |
OpenSBI |
ASC GCC 14 |
rv64imac |
Builds |
pcie_bringup (device) |
Bare-metal GCC |
rv64imac |
No OS |
5. PCIe Enumeration and BAR Assignment
5.1 Enumeration Topology
Property |
Value |
|---|---|
RC Bus/Dev/Fn |
00:00.0 |
EP Bus/Dev/Fn |
01:00.0 |
EP BAR0 size |
16 MB ( |
EP BAR0 type |
64-bit Memory, non-prefetchable |
Config access |
iATU-translated (no ECAM hardware) |
Host MEM window |
|
5.2 iATU Configuration
The dw-pcie Linux driver programs iATU outbound windows:
Window 0 (Config): Maps
0x70000000(16 MB) → Type 0/1 config TLPs to bus 1Window 1 (MEM): Maps
0x71000000(240 MB) → Memory TLPs targeting EP BARs
Linux assigns BAR0 an address within the 0x71000000–0x7FFFFFFF MEM window. The physical address is visible in sysfs at /sys/bus/pci/devices/0000:01:00.0/resource.
6. Data Transfer Application (pcie_xfer)
6.1 Purpose
pcie_xfer is a Linux userspace C application that maps EP BAR0 into process address space (via sysfs resource0 or /dev/mem) and performs MMIO read/write operations. Each operation traverses the full data path to Target_Memory on the device chiplet.
6.2 Data Path
Host CPU (MMIO store)
→ RC AXI_Slave (0x70000000 window)
→ iATU translates to Memory Write TLP
→ RC.PCIMem → PCIe link → EP.PCIMem_Slave
→ EP.BusMaster
→ PCIE_TILE.pcie_controller_target
→ Internal tile fabric
→ noc_n_initiator
→ SharedMemoryMap decode
→ Target_Memory @ 0x0 (16 MB)
6.3 Supported Commands
Command |
Syntax |
Description |
|---|---|---|
Write |
|
Single 32-bit write at BAR0 + offset |
Read |
|
Single 32-bit read at BAR0 + offset |
Fill |
|
Fill |
Dump |
|
Hex dump |
Pattern |
|
Write `0xA0000000 |
Burst |
|
Timed burst write, reports throughput |
Verify |
|
Verify memory matches expected value |
Send |
|
Write binary file contents to BAR0 |
6.4 EP Auto-Detection
The application walks /sys/bus/pci/devices/ to find the first non-bridge device (class != 0x0604xx or 0x0600xx), reads BAR0 physical address and size from the sysfs resource file, and maps it via resource0 (falling back to /dev/mem if needed).
6.5 Building pcie_xfer
Cross-compile for the host initramfs with the musl toolchain:
riscv64-unknown-linux-musl-gcc -O2 -static -o pcie_xfer pcie_xfer.c
The static binary is included in the initramfs CPIO archive.
7. Bare-Metal Test (pcie_e2e_test)
An alternative bare-metal test (pcie_e2e_test.c) runs on the Host_Chiplet without Linux. It provides:
Trap-safe MMIO operations (catch and report access faults)
RC DBI register dump (Vendor/Device ID, Command/Status, BARs, Capabilities)
Port Logic register inspection
iATU programming and verification
End-to-end data transfer test through the PCIe link
Detailed topology verification (Bus 0 RC, Bus 1 EP)
This test is useful for pre-Linux validation of the PCIe link and tile connectivity.
8. VP Configuration Reference
8.1 Available Configurations
Name |
Active Config Path |
Description |
|---|---|---|
default |
|
Full Linux with standard kernel, quantum 6000 ps |
mini_riscv64_linux |
|
Mini Linux for fast boot, quantum 1000 ps |
Set the active config in snps.vpproject → activeConfig attribute.
8.2 Critical VPCFG Parameters
Host_Chiplet:
Parameter |
Value |
Purpose |
|---|---|---|
|
|
Start host CPU immediately |
|
|
Separate DBI window |
|
250 |
PIPE clock 250 MHz |
|
100 |
AXI/DBI/aux clocks 100 MHz |
|
|
OpenSBI + Linux |
|
6000 (default) / 1000 (mini) |
Temporal decoupling quantum |
|
115200000 |
115.2 MHz UART clock |
Keraunos_PCIE_Chiplet:
Parameter |
Value |
Purpose |
|---|---|---|
|
|
Start device CPU immediately |
|
|
Separate DBI window |
|
250 |
PIPE clock 250 MHz |
|
|
Bare-metal EP init firmware |
|
See Section 3.2 |
Chiplet address decode |
8.3 Image Loading
Critical: The host initial_image uses the format {path/fw_payload.elf,,,image+symbols,} with empty load address fields. The Virtualizer applies ELF program header addresses (entry at 0x80000000). Never set load address to 0x0 — this breaks OpenSBI execution.
9. Sideband Signal Mapping
9.1 EP ↔ PCIE_TILE Sideband
VDK Connection Source |
VDK Connection Sink |
Description |
|---|---|---|
|
|
DMA interrupts |
|
|
Parity/RAS error |
|
|
CII header valid |
|
|
CII header type |
|
|
CII header address |
|
|
Function Level Reset |
9.2 Clocks and Resets
Source |
Destination |
Notes |
|---|---|---|
|
|
System clock |
|
|
System reset |
|
|
Host clock |
|
|
Host reset |
9.3 MSI Interrupt Path
PCIE_RC.msi_ctrl_int → Host_Chiplet.SMC.irqS[11] → PLIC IRQ → Linux ISR
10. Troubleshooting
10.1 Host Crashes or Nonsense PC
Verify
fw_payload.elfuses ELF-header load addresses (not forced0x0)Check
readelf -l fw_payload.elf— VirtAddr should show0x8000xxxxEnsure kernel is built with
CONFIG_FPU=nfor rv64imac CPUVerify initramfs binaries are musl-compiled for rv64imac (no FPU instructions)
10.2 PCIe EP Not Detected
Verify
pcie_bringup.elfis loaded on device CPU and runs to completionCheck that device
RST_GEN.active_at_start = trueConfirm direct PCIe link wiring (RC.PCIMem ↔ EP.PCIMem_Slave)
Verify DT
bus-range = <0x0 0x1>and bootargs includepci=assign-busses
10.3 BAR0 Access Returns All-Ones
EP may not have BAR0 properly sized — check
pcie_bringupprogramsBAR0_MASKiATU outbound window may not cover the assigned BAR address
Verify chiplet SharedMemoryMap decode includes
0x0:0x1000000for Target_Memory
10.4 Data Mismatch on Read-Back
Check that
noc_n_initiatoris connected to SharedMemoryMap at start 0x0Verify Target_Memory size (16 MB) covers the access offset
Confirm byte-enable and data width compatibility across the path