From 9bf4291d176d475810c9f126708aa3635aed60ec Mon Sep 17 00:00:00 2001 From: ETWen Date: Mon, 17 Aug 2026 16:32:42 +0800 Subject: [PATCH] feat(fpga): Auto-detect CB FPGA BDF at source time blanton_fpga_pcimem.sh V1.5.0. The four FUNCT0..3_RES sysfs paths were hard-coded and had to be edited for every DUT, because the CB FPGA's BDF changes with the PCIe enumeration (0000:03:00.x / 0000:05:00.x seen so far). Detection order at source time: FPGA_BDF override -> sysfs scan for vendor 0x1590 with all four functions exposing resource0 -> lspci -Dnn name/id match -> FPGA_BDF_FALLBACK. Adds fpga_rescan for a DUT swap, FPGA_BDF / FPGA_VENDOR_ID / FPGA_LSPCI_MATCH overrides, FPGA_BDF_ACTIVE reporting and FPGA_QUIET. Detection runs once, so cb_fpga / pmc / icb / swb keep zero per-command overhead. --- .../Blanton_Script/blanton_fpga_pcimem.sh | 138 +++++++++++++++--- 1 file changed, 119 insertions(+), 19 deletions(-) diff --git a/src/Script_ABC_Blanton/Blanton_Script/blanton_fpga_pcimem.sh b/src/Script_ABC_Blanton/Blanton_Script/blanton_fpga_pcimem.sh index 12d8d77..fb35f97 100644 --- a/src/Script_ABC_Blanton/Blanton_Script/blanton_fpga_pcimem.sh +++ b/src/Script_ABC_Blanton/Blanton_Script/blanton_fpga_pcimem.sh @@ -17,10 +17,21 @@ # V1.4.2 2026-08-10 Change: FUNCT0..3_RES BDF updated 0000:04:00.x -> 0000:03:00.x (current unit's enumeration). # V1.4.3 2026-08-12 Change: FUNCT0..3_RES BDF updated 0000:03:00.x -> 0000:05:00.x (current unit's enumeration). # V1.4.4 2026-08-12 Change: FUNCT0..3_RES BDF back to 0000:03:00.x for the DUT on COM36. -# NOTE: this BDF is per-unit. Check with -# lspci -Dnn | grep -i fpga or -# ls -d /sys/bus/pci/devices/0000:*:00.3 -# and edit the four lines below if it differs. +# V1.5.0 2026-08-17 Change: BDF is no longer hard-coded. FUNCT0..3_RES are now +# auto-detected at source time by scanning sysfs for the HPE +# vendor id (0x1590) with all four functions .0-.3 present, +# falling back to `lspci -Dnn` name/id match, then to +# FPGA_BDF_FALLBACK. No more editing this file per DUT. +# Add: fpga_rescan (re-detect after DUT swap / re-enumeration), +# FPGA_BDF / FPGA_VENDOR_ID / FPGA_LSPCI_MATCH overrides, +# FPGA_BDF_ACTIVE reporting the BDF in use. +# Note: detection runs ONCE at source time (one INFO line on +# stdout, WARN/FAIL on stderr). FPGA_QUIET=1 silences the +# INFO line. cb_fpga/pmc/icb/swb never re-scan, so there is +# no per-command output and no per-command overhead. +# NOTE: the old per-unit NOTE ("edit the four lines below") +# no longer applies - detection handles it. To pin a BDF +# manually: FPGA_BDF=0000:05:00 fpga_rescan # ============================================================================= # # SONiC hardware has no memtool / devmem, but it has pcimem. pcimem mmaps the PCI @@ -42,26 +53,112 @@ # icb_fpga [data] # swb0_fpga [data] # swb1_fpga [data] +# fpga_rescan re-detect the CB FPGA BDF (after a DUT swap) # # data present = write, absent = read. # Usage: source blanton_fpga_pcimem.sh -# === CB FPGA PCIe resource file (sysfs) === -# Use lspci -D to find the BDF (domain:bus:dev.fn); resource0 is the sysfs mapping of BAR0. -# e.g. lspci -Dnn | grep -i fpga -> 0000:02:00.0 ... -# memtool variant fills in the BAR value; pcimem variant fills in the resource file -# path instead (offset becomes relative to BAR). -FUNCT0_RES=/sys/bus/pci/devices/0000:03:00.0/resource0 -FUNCT1_RES=/sys/bus/pci/devices/0000:03:00.1/resource0 -FUNCT2_RES=/sys/bus/pci/devices/0000:03:00.2/resource0 -FUNCT3_RES=/sys/bus/pci/devices/0000:03:00.3/resource0 +# === CB FPGA PCIe resource file (sysfs) - AUTO-DETECTED === +# The CB FPGA's BDF (domain:bus:dev.fn) changes per unit / per enumeration, so it is +# detected at source time instead of being hard-coded. resource0 is the sysfs mapping +# of BAR0. (memtool variant fills in the BAR value; pcimem variant fills in the +# resource file path instead, so offsets become relative to BAR.) +# +# Detection order: +# 1. FPGA_BDF override e.g. FPGA_BDF=0000:05:00 (domain:bus:dev, WITHOUT .fn) +# 2. sysfs vendor scan /sys/bus/pci/devices/*.0 whose vendor == FPGA_VENDOR_ID +# (0x1590 = Hewlett Packard Enterprise) and that has all +# four functions .0 .1 .2 .3 exposing resource0 +# 3. lspci -Dnn fallback lines matching FPGA_LSPCI_MATCH +# ("Hewlett Packard Enterprise" or vendor id "[1590:") +# 4. FPGA_BDF_FALLBACK last-known BDF, only if 1-3 all fail +# +# Overrides (export before sourcing, or set and call fpga_rescan afterwards): +# FPGA_BDF=0000:05:00 pin a specific device, skip detection +# FPGA_VENDOR_ID=0x10ee different vendor (e.g. a Xilinx-branded board) +# FPGA_LSPCI_MATCH='...' custom lspci grep -iE pattern +FPGA_VENDOR_ID="${FPGA_VENDOR_ID:-0x1590}" +FPGA_LSPCI_MATCH="${FPGA_LSPCI_MATCH:-Hewlett Packard Enterprise|\[1590:}" +FPGA_BDF_FALLBACK="${FPGA_BDF_FALLBACK:-0000:03:00}" -# Auto-detect example (uncomment to use; needs the FPGA's BDF prefix): -# _BDF=0000:02:00 -# FUNCT0_RES=/sys/bus/pci/devices/${_BDF}.0/resource0 -# FUNCT1_RES=/sys/bus/pci/devices/${_BDF}.1/resource0 -# FUNCT2_RES=/sys/bus/pci/devices/${_BDF}.2/resource0 -# FUNCT3_RES=/sys/bus/pci/devices/${_BDF}.3/resource0 +# True if all four functions of exist and expose resource0. +# Usage: _fpga_bdf_ok +_fpga_bdf_ok() { + local bdf="$1" fn + for fn in 0 1 2 3; do + [ -e "/sys/bus/pci/devices/${bdf}.${fn}/resource0" ] || return 1 + done + return 0 +} + +# Print the detected FPGA BDF prefix (domain:bus:dev) on stdout; non-zero if none. +_fpga_detect_bdf() { + local cands="" bdf dir vend want + + # 1. explicit override wins (tolerate a trailing ".fn" being included) + if [ -n "${FPGA_BDF:-}" ]; then + bdf="$FPGA_BDF" + case "$bdf" in *.[0-7]) bdf="${bdf%.*}" ;; esac + echo "$bdf" + return 0 + fi + + want=$(echo "$FPGA_VENDOR_ID" | tr 'A-Z' 'a-z') + + # 2. sysfs vendor-ID scan (no lspci / pci.ids needed) + for dir in /sys/bus/pci/devices/*:*.0; do + [ -e "$dir/vendor" ] || continue + vend=$(tr 'A-Z' 'a-z' < "$dir/vendor" 2>/dev/null) + [ "$vend" = "$want" ] || continue + bdf="${dir##*/}"; bdf="${bdf%.0}" + _fpga_bdf_ok "$bdf" && cands="$cands $bdf" + done + + # 3. lspci fallback (device name match, in case the vendor id differs) + if [ -z "$cands" ] && command -v lspci >/dev/null 2>&1; then + for bdf in $(lspci -Dnn 2>/dev/null | grep -iE "$FPGA_LSPCI_MATCH" \ + | awk '{print $1}' | sed 's/\.[0-9a-f]*$//' | sort -u); do + _fpga_bdf_ok "$bdf" && cands="$cands $bdf" + done + fi + + set -- $cands + [ $# -eq 0 ] && return 1 + if [ $# -gt 1 ]; then + echo -e "[\033[33mWARN\033[0m] multiple candidate FPGAs found:$cands -> using $1" >&2 + echo -e " set FPGA_BDF= and run fpga_rescan to pick another." >&2 + fi + echo "$1" +} + +# (Re)detect the FPGA BDF and refresh FUNCT0..3_RES. Called once at source time; +# call again by hand after swapping/re-enumerating a DUT. +# The one-line INFO goes to STDOUT (so wrappers that already do +# `source ... >/dev/null` stay silent); WARN/FAIL go to STDERR. +# Set FPGA_QUIET=1 to suppress the INFO line entirely. +fpga_rescan() { + local bdf + bdf=$(_fpga_detect_bdf) + if [ -z "$bdf" ]; then + bdf="$FPGA_BDF_FALLBACK" + echo -e "[\033[33mWARN\033[0m] no FPGA found (vendor $FPGA_VENDOR_ID / '$FPGA_LSPCI_MATCH');" >&2 + echo -e " falling back to $bdf. Check with: lspci -Dnn | grep -iE 'Hewlett|fpga'" >&2 + fi + FPGA_BDF_ACTIVE="$bdf" + FUNCT0_RES=/sys/bus/pci/devices/${bdf}.0/resource0 + FUNCT1_RES=/sys/bus/pci/devices/${bdf}.1/resource0 + FUNCT2_RES=/sys/bus/pci/devices/${bdf}.2/resource0 + FUNCT3_RES=/sys/bus/pci/devices/${bdf}.3/resource0 + if _fpga_bdf_ok "$bdf"; then + [ "${FPGA_QUIET:-0}" = "1" ] || \ + echo -e "[\033[34mINFO\033[0m] CB FPGA BDF = \033[36m${bdf}.0-.3\033[0m (resource0)" + else + echo -e "[\033[31mFAIL\033[0m] ${bdf}.0-.3 resource0 not all present - register access will fail." >&2 + return 1 + fi +} + +fpga_rescan # === VSPI window base offset (relative to CB Function 2 resource0 start) === # NOTE: CB.F2 has TWO near-identical VSPI register blocks (see spec register map): @@ -268,6 +365,9 @@ blanton_fpga_help() { echo -e " \033[33mswb0_fpga\033[0m [data] SWB0 FPGA via VSPI" echo -e " \033[33mswb1_fpga\033[0m [data] SWB1 FPGA via VSPI" echo -e " \033[33mfpga_debug\033[0m on|off Toggle debug mode (print commands and execute)" + echo -e " \033[33mfpga_rescan\033[0m Re-detect CB FPGA BDF (after DUT swap / re-enum)" + echo "" + echo -e " Active CB FPGA BDF: \033[36m${FPGA_BDF_ACTIVE:-unknown}\033[0m .0-.3 (pin with: FPGA_BDF=0000:05:00 fpga_rescan)" echo "" echo -e " Omit [data] to \033[32mread\033[0m, provide [data] to \033[31mwrite\033[0m." echo -e " Backend: \033[36mpcimem\033[0m (sysfs resource file + relative offset)."