Compare commits

...
3 Commits
Author SHA1 Message Date
etwenandClaude Opus 5.5 1d3fb4f929 docs: Record V1.2.3 in Script A's history and add the release note
Script A: header to V1.2.3 / 2026-09-23; five entries under V1.2.3 for
setup_pmon.ttl, ddr5_temp.sh, hsc_temp_readback.sh, avt_pmpower.sh and
Script 4, with notes on the ~4 s per snapshot, the exec bit, the CRLF in
hsc_temp_readback.sh v1.0.0 and AVT not being shipped.

CLAUDE.md: status to V1.2.3; the PMON temperatures and Script 4's CPU
power in the overview; a commands block for the three new scripts; fix
the stale Script 5 file name and the "last release V1.1.5" line.

ARCHITECTURE.md: Script A ref to V1.2.3; the three scripts in the tree
and in setup_pmon's comment; avt_pmpower.sh in Script 4's row; the git
tag checkbox to V1.2.3.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UniUXkxgCG2Ty74advL8Pd
2026-09-23 14:44:07 +08:00
etwenandClaude Opus 5.5 0ad76ea8b0 feat(pwr): Log AMD CPU package power in the Script 4 loop
avt_pmpower.sh runs AVTCMD -module pmm "get_pmdata()" and summarizes
SktPwr, PPT Fast / Slow against their limits, and MemPwr. -p takes the
AVTCMD path, -q drops the raw PM table. Exit 2 = AVTCMD missing,
3 = AVTCMD failed, 4 = nothing parsed. The values are SMU telemetry, not
a measurement.

Script 4 calls it every round after the two TH6_SWB power readbacks, so
switch rails and CPU package power sit side by side in each sample.

AVT is under NDA and not shipped in Blanton_Script. It has to be
unpacked on the DUT at ~/AVT_Linux_NDA_2.8.37/ beforehand; otherwise the
call exits 2 each round and the loop continues without the reading.
Without -q the full PM table is logged once a minute.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UniUXkxgCG2Ty74advL8Pd
2026-09-23 14:43:28 +08:00
etwenandClaude Opus 5.5 4ce4d6c62e feat(temp): Add DDR5 DIMM and hot-swap controller temperatures to PMON
ddr5_temp.sh reads the SPD5118 hub on each DDR5 DIMM (i2c bus 5,
0x50/0x51, register 0x31: bit[12:2], sign bit 12, 0.25 C/LSB). A failed
read prints 'read fail' instead of a number. Bus and addresses can be
passed as arguments.

hsc_temp_readback.sh reads the LTC4287 hot-swap controllers on i2c bus
28: HSC_MAIN @ 0x40 and HSC_STBY @ 0x45, internal and external sensor
each, selected through 0xF3 and read from 0x8D (Kelvin). v1.0.1 adds the
header, corrects the delay comments (DELAY is 0.5 s, not 100 ms) and
converts the file from CRLF to LF - CRLF fails outright under bash on
SONiC.

utils/setup_pmon.ttl calls both right after 'show platform temperature'.
It is shared, so every PMON snapshot gets them: Script A's baseline,
each Script B soak round, Script C, the Script 4 loop and every Script 5
check point. hsc_temp_readback.sh adds ~4 s to each snapshot.

Both are called by path and need the exec bit on the DUT.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UniUXkxgCG2Ty74advL8Pd
2026-09-23 14:43:28 +08:00
9 changed files with 367 additions and 9 deletions
+7 -3
View File
@@ -174,6 +174,7 @@ Blanton_TTL_Script/
│ ├── pcie_bus.ttl # lspci -tvvv / -vv │ ├── pcie_bus.ttl # lspci -tvvv / -vv
│ ├── setup_pmon.ttl # show platform summary/fan/temperature/psustatus/voltage/ │ ├── setup_pmon.ttl # show platform summary/fan/temperature/psustatus/voltage/
│ │ # current/ssdhealth/leak status/leak channels + TPM(11 項) │ │ # current/ssdhealth/leak status/leak channels + TPM(11 項)
│ │ # V1.2.3 起 + ddr5_temp.sh + hsc_temp_readback.sh
│ ├── show_dmesg.ttl # dmesg -T 合併 error 正則 + i2c 過濾 + dmesg -C 清空 │ ├── show_dmesg.ttl # dmesg -T 合併 error 正則 + i2c 過濾 + dmesg -C 清空
│ ├── show_margin_status.ttl # source margin_status_all.sh(掃 9 顆 LTC2980) │ ├── show_margin_status.ttl # source margin_status_all.sh(掃 9 顆 LTC2980)
│ ├── kill_all_process.ttl # kill $(jobs -p) │ ├── kill_all_process.ttl # kill $(jobs -p)
@@ -215,6 +216,9 @@ Blanton_TTL_Script/
├── TH6_SWB0_power_readback.sh # SWB0 19 條軌 V×I + 總功耗 ├── TH6_SWB0_power_readback.sh # SWB0 19 條軌 V×I + 總功耗
├── TH6_SWB1_power_readback.sh # SWB1 同上 ├── TH6_SWB1_power_readback.sh # SWB1 同上
│ # ⚠️ 已納入交付,但 A/B/C 的呼叫仍註解掉(bring-up 中) │ # ⚠️ 已納入交付,但 A/B/C 的呼叫仍註解掉(bring-up 中)
├── ddr5_temp.sh # DDR5 DIMM 溫度(SPD5118 @ i2c-5 0x50/0x51,reg 0x31)
├── hsc_temp_readback.sh # LTC4287 HSC 溫度(i2c-28 0x40/0x45,內/外部感溫)
├── avt_pmpower.sh # AMD CPU 封裝功耗(AVTCMD pmm get_pmdata;AVT 是 NDA,不隨包)
├── usb_target.sh # 偵測 USB 裝置節點/掛載點(排除系統碟) ├── usb_target.sh # 偵測 USB 裝置節點/掛載點(排除系統碟)
├── bmc_monitor.sh # BMC 監控:free -m + I2C 寫入/讀回圖樣測試 ├── bmc_monitor.sh # BMC 監控:free -m + I2C 寫入/讀回圖樣測試
├── bmc_monitor_ddr.sh # ⚠️ 已停用:V1.1.9 起 B/C 內的註解區塊已刪除,DDR 壓力走 bgctl + bmc-manager ├── bmc_monitor_ddr.sh # ⚠️ 已停用:V1.1.9 起 B/C 內的註解區塊已刪除,DDR 壓力走 bgctl + bmc-manager
@@ -377,10 +381,10 @@ PROFILE_CHANNELS=( "0:high:8" "1:low:8" ... ) # "channel:operation:change_perc
| 模組 | 進入點 | 功能 | | 模組 | 進入點 | 功能 |
|------|--------|------| |------|--------|------|
| **Script A(Pre-test)** | `1_Blanton_Script_A.ttl` V1.2.2 | root 登入 → `date -s` 對時 → 清 job log → **收掉前一輪殘留**(`hw-test-session finish` → `bgctl reset --yes` → `bgctl stop --all` → `bgctl list` 確認清空)→ `hw-test-session start` → **設定風扇轉速** → **等資料面就緒**(`wait_init.ttl`)→ DUT 清單(boot/version/fwutil/syseeprom/ssdhealth/TPM/NVMe)→ BMC enroll + version/status → source bash 工具 → 清/讀 7 組 PCIe AER + `ras-mc-ctl --summary` → `lspci` → margin → PMON → dmesg → **10G/1G 管理網路 ping** → **NFC 基線**(start → 30s → stop → report)→ 100G uplink 設定與狀態 → **BER 基線掃描**(依 `SWB_UNIT`,V1.2.1 新增)→ **一輪流量基線** → **SerDes DSC 基線**(`EN_TX_FIR`)→ `show uptime` | | **Script A(Pre-test)** | `1_Blanton_Script_A.ttl` V1.2.3 | root 登入 → `date -s` 對時 → 清 job log → **收掉前一輪殘留**(`hw-test-session finish` → `bgctl reset --yes` → `bgctl stop --all` → `bgctl list` 確認清空)→ `hw-test-session start` → **設定風扇轉速** → **等資料面就緒**(`wait_init.ttl`)→ DUT 清單(boot/version/fwutil/syseeprom/ssdhealth/TPM/NVMe)→ BMC enroll + version/status → source bash 工具 → 清/讀 7 組 PCIe AER + `ras-mc-ctl --summary` → `lspci` → margin → PMON → dmesg → **10G/1G 管理網路 ping** → **NFC 基線**(start → 30s → stop → report)→ 100G uplink 設定與狀態 → **BER 基線掃描**(依 `SWB_UNIT`,V1.2.1 新增)→ **一輪流量基線** → **SerDes DSC 基線**(`EN_TX_FIR`)→ `show uptime` |
| **Script B(Stress)** | `2_Blanton_Script_B.ttl` | **V1.1.8 起 `mlucas-avx2 -cpu 0:15` 由 `systemd-run --unit=mlucas-amm`(`Type=exec`、`Restart=always`)啟動,不再是 shell 的 `&` 背景 job** + `bgctl run` 的 `memtester` / SSD / USB 壓力(v1.1.7 起 SSD/USB 的 `--runtime`/`--passes` 讀 `config.ttl` 的 `SSD_RUNTIME`/`SSD_COUNT`、`USB_RUNTIME`/`USB_COUNT`;BMC memtester 不帶次數 = 跑到被停) + BMC DDR(`bmc-manager run memtester`)→ BMC USB net test(探測 cdc_ncm 介面,`systemd-run` 掛 `BMC_USB_RUNTIME` 秒的 ping,V1.1.8 前寫死 4 小時)→ 啟動 mgmt ping 監控 → **啟動 NFC 輪詢** → `jobs` / `systemctl is-active mlucas-amm` / `bgctl list` → traffic(依 `SWB_UNIT`)→ `while 1` 每輪 PMON + `bgctl list`/`jobs`/`systemctl is-active mlucas-amm` + `sleep 60`(**V1.1.4 起 margin 不在迴圈內**;V1.2.0 起等待走 DUT 端 `sleep` 而非 macro 端 `pause`)| | **Script B(Stress)** | `2_Blanton_Script_B.ttl` | **V1.1.8 起 `mlucas-avx2 -cpu 0:15` 由 `systemd-run --unit=mlucas-amm`(`Type=exec`、`Restart=always`)啟動,不再是 shell 的 `&` 背景 job** + `bgctl run` 的 `memtester` / SSD / USB 壓力(v1.1.7 起 SSD/USB 的 `--runtime`/`--passes` 讀 `config.ttl` 的 `SSD_RUNTIME`/`SSD_COUNT`、`USB_RUNTIME`/`USB_COUNT`;BMC memtester 不帶次數 = 跑到被停) + BMC DDR(`bmc-manager run memtester`)→ BMC USB net test(探測 cdc_ncm 介面,`systemd-run` 掛 `BMC_USB_RUNTIME` 秒的 ping,V1.1.8 前寫死 4 小時)→ 啟動 mgmt ping 監控 → **啟動 NFC 輪詢** → `jobs` / `systemctl is-active mlucas-amm` / `bgctl list` → traffic(依 `SWB_UNIT`)→ `while 1` 每輪 PMON + `bgctl list`/`jobs`/`systemctl is-active mlucas-amm` + `sleep 60`(**V1.1.4 起 margin 不在迴圈內**;V1.2.0 起等待走 DUT 端 `sleep` 而非 macro 端 `pause`)|
| **Script C(Post-test)** | `3_Blanton_Script_C.ttl` | `kill $(jobs -p)` + **`systemctl stop mlucas-amm`**(systemd unit 不是 shell job,`jobs -p` 抓不到)+ `bgctl stop --all` / `reset` + 停 BMC USB unit、mgmt ping 與 **NFC 輪詢** → PMON + dmesg → 7 組 AER + `ras-mc-ctl` → BMC USB `journalctl` **寫進 `log/bmc_usb_net.log`**(不再印在 console) → `ip -s link show eth0/eth1` → `cat` mlucas log(並 `cp` 進 job 目錄一起帶走)→ **NFC `report`** → traffic `stop` + `report` → **SerDes DSC 收尾**(`EN_TX_FIR`)→ **BER 掃描**(依 `SWB_UNIT`)→ NVMe 健康 → `show reboot-cause` → **margin 掃描**(`EN_Margin`,V1.1.4 由 Script B 移來)→ `uptime` → **job log 複製到 USB(帶時戳)** → `exit` + wait『Script done』→ `hw-test-session finish` | | **Script C(Post-test)** | `3_Blanton_Script_C.ttl` | `kill $(jobs -p)` + **`systemctl stop mlucas-amm`**(systemd unit 不是 shell job,`jobs -p` 抓不到)+ `bgctl stop --all` / `reset` + 停 BMC USB unit、mgmt ping 與 **NFC 輪詢** → PMON + dmesg → 7 組 AER + `ras-mc-ctl` → BMC USB `journalctl` **寫進 `log/bmc_usb_net.log`**(不再印在 console) → `ip -s link show eth0/eth1` → `cat` mlucas log(並 `cp` 進 job 目錄一起帶走)→ **NFC `report`** → traffic `stop` + `report` → **SerDes DSC 收尾**(`EN_TX_FIR`)→ **BER 掃描**(依 `SWB_UNIT`)→ NVMe 健康 → `show reboot-cause` → **margin 掃描**(`EN_Margin`,V1.1.4 由 Script B 移來)→ `uptime` → **job log 複製到 USB(帶時戳)** → `exit` + wait『Script done』→ `hw-test-session finish` |
| **Script 4(Thermal / Safety)** | `4_Blanton_Script_thermal_safety.ttl` | **獨立腳本,不接 A→B→C。** Script A 式的環境建立(登入 / session / 風扇 / `wait_init` / DUT 清單 / BMC / PCIe 清除 / `pcie_bus` / PMON / dmesg)→ **滿載**(`mlucas-avx2 -cpu 0:15`,V1.1.8 起與 Script B 同樣掛成 `mlucas-amm` systemd unit + `blanton_tr518.sh start`)→ `while 1`:PMON + `TH6_SWB0/1_power_readback.sh` + `bgctl list` / `jobs` / `systemctl is-active mlucas-amm`,`pause 60`。**沒有收尾段** —— 中斷後 DUT 仍在 `port cd lb=mac` / `l2 learn off` / `test mode nr=yes`,且 CPU 仍滿載,要手動 `blanton_tr518.sh stop` + `systemctl stop mlucas-amm` | | **Script 4(Thermal / Safety)** | `4_Blanton_Script_thermal_safety.ttl` | **獨立腳本,不接 A→B→C。** Script A 式的環境建立(登入 / session / 風扇 / `wait_init` / DUT 清單 / BMC / PCIe 清除 / `pcie_bus` / PMON / dmesg)→ **滿載**(`mlucas-avx2 -cpu 0:15`,V1.1.8 起與 Script B 同樣掛成 `mlucas-amm` systemd unit + `blanton_tr518.sh start`)→ `while 1`:PMON + `TH6_SWB0/1_power_readback.sh` + `avt_pmpower.sh`(CPU 封裝功耗,V1.2.3)+ `bgctl list` / `jobs` / `systemctl is-active mlucas-amm`,`pause 60`。**沒有收尾段** —— 中斷後 DUT 仍在 `port cd lb=mac` / `l2 learn off` / `test mode nr=yes`,且 CPU 仍滿載,要手動 `blanton_tr518.sh stop` + `systemctl stop mlucas-amm` |
| **Script 5(Reboot Cycle)** | `5_Blanton_Script_Reboot_Cycle.ttl` | **獨立腳本,不接 A→B→C。** `while 1`:登入 → `sudo -i` → 對時 → 風扇 → **Check Pt1~Pt13**(DUT/BMC info、mgmt ping、NFC、SSD、USB、BMC USB、port status + 15s traffic、BER、NVMe、platform data、dmesg i2c、PCIe error counters)→ `show uptime` → `reboot` → `wait "Booting in blind mode"`。`cnt_cycle` 每輪 +1 印在標頭。**沒有結束條件** —— 要停就關掉 Tera Term 的 macro。**尚未上機驗證** | | **Script 5(Reboot Cycle)** | `5_Blanton_Script_Reboot_Cycle.ttl` | **獨立腳本,不接 A→B→C。** `while 1`:登入 → `sudo -i` → 對時 → 風扇 → **Check Pt1~Pt13**(DUT/BMC info、mgmt ping、NFC、SSD、USB、BMC USB、port status + 15s traffic、BER、NVMe、platform data、dmesg i2c、PCIe error counters)→ `show uptime` → `reboot` → `wait "Booting in blind mode"`。`cnt_cycle` 每輪 +1 印在標頭。**沒有結束條件** —— 要停就關掉 Tera Term 的 macro。**尚未上機驗證** |
| **SWB loopback 流量** | `blanton_traffic_linespeed <sub> [-u 0\|1\|all]` | `init`(VLAN 30..137,成對 `cdN`/`cdN+32`)→ `clear` → `start`(`tx 200 length=324 PatternRandom=yes`,v0.7.0 起)→ `stop` → `report`(per-pair TX/RX 交叉比對 PASS/FAIL);另有 `ps`(link/speed)與 `run`(一條龍)。**V0.6.0 起含 100G uplink `ce0`**(VLAN 138):它沒有 loopback 對象,靠 **ingress mirror 打回自己**維持循環,`report` 最後一列就是它,底下再接一份跨 unit summary | | **SWB loopback 流量** | `blanton_traffic_linespeed <sub> [-u 0\|1\|all]` | `init`(VLAN 30..137,成對 `cdN`/`cdN+32`)→ `clear` → `start`(`tx 200 length=324 PatternRandom=yes`,v0.7.0 起)→ `stop` → `report`(per-pair TX/RX 交叉比對 PASS/FAIL);另有 `ps`(link/speed)與 `run`(一條龍)。**V0.6.0 起含 100G uplink `ce0`**(VLAN 138):它沒有 loopback 對象,靠 **ingress mirror 打回自己**維持循環,`report` 最後一列就是它,底下再接一份跨 unit summary |
| **FPGA 暫存器存取** | `cb_fpga <fn> <addr> [data]`、`fpga_rescan` | pcimem 打 `resource0` + BAR 相對 offset,32-bit word;BDF 於 source 時自動偵測;`pmc/icb/swb0/swb1_fpga` 走 VSPI 窗口 | | **FPGA 暫存器存取** | `cb_fpga <fn> <addr> [data]`、`fpga_rescan` | pcimem 打 `resource0` + BAR 相對 offset,32-bit word;BDF 於 source 時自動偵測;`pmc/icb/swb0/swb1_fpga` 走 VSPI 窗口 |
@@ -808,7 +812,7 @@ margin status、全部 VRM 軌的 Vin/Vout/Iout/Temp、CB + ICB 溫感讀值,
- [ ] `CHANGELOG.md`:延續三支腳本頂端的 Version History,集中成一份 - [ ] `CHANGELOG.md`:延續三支腳本頂端的 Version History,集中成一份
- [ ] 三支腳本的 header 版號與 `CHANGELOG.md` 對齊,`config.ttl` 加 `script_version` 並寫進 log 開頭 - [ ] 三支腳本的 header 版號與 `CHANGELOG.md` 對齊,`config.ttl` 加 `script_version` 並寫進 log 開頭
- [ ] `docs/TTL_Script_Blanton_Status_*.xlsx` 更新為全 OK,或把剩餘項目移進 Future Extensions - [ ] `docs/TTL_Script_Blanton_Status_*.xlsx` 更新為全 OK,或把剩餘項目移進 Future Extensions
- [x] 打 git tag,push `nas` + `gitea`(已至 `V1.2.2`;`publish/` 依 Script A 檔頭版號打包) - [x] 打 git tag,push `nas` + `gitea`(已至 `V1.2.3`;`publish/` 依 Script A 檔頭版號打包)
**驗收條件:** 從 zip 解壓到一台乾淨的測試 NB,照 README 操作,不看原始碼就能完成一輪 A→B→C **驗收條件:** 從 zip 解壓到一台乾淨的測試 NB,照 README 操作,不看原始碼就能完成一輪 A→B→C
並產出 summary;`publish/` 內容與 git tag 一致。 並產出 summary;`publish/` 內容與 git tag 一致。
+15 -4
View File
@@ -9,7 +9,7 @@ DUT 端的取數能力由一組 **bash 工具庫** 提供(CB FPGA `pcimem` →
完整架構見 [ARCHITECTURE.md](ARCHITECTURE.md)。 完整架構見 [ARCHITECTURE.md](ARCHITECTURE.md)。
**目前狀態(2026-09-15)**:Script A 為 **V1.2.2**(A 集中記錄所有 TTL 的變更)。涵蓋 **目前狀態(2026-09-23)**:Script A 為 **V1.2.3**(A 集中記錄所有 TTL 的變更)。涵蓋
PCIe AER / DDR EDAC / PMON+TPM / 電壓 margin(9 顆 LTC2980)/ SWB loopback 線速流量 / PCIe AER / DDR EDAC / PMON+TPM / 電壓 margin(9 顆 LTC2980)/ SWB loopback 線速流量 /
10G+1G 管理網路 ping / BMC DDR 與 USB / NVMe 健康,壓力層走平台的 `bgctl`。 10G+1G 管理網路 ping / BMC DDR 與 USB / NVMe 健康,壓力層走平台的 `bgctl`。
switch unit 數量由 `config.ttl` 的 `SWB_UNIT0` / `SWB_UNIT1` 宣告,風扇轉速由 `FAN_SPEED` 指定 switch unit 數量由 `config.ttl` 的 `SWB_UNIT0` / `SWB_UNIT1` 宣告,風扇轉速由 `FAN_SPEED` 指定
@@ -33,12 +33,14 @@ Script A 開頭會先收掉前一輪殘留(`hw-test-session finish` + `bgctl r
再 `bgctl list` 確認沒有 job 留著佔資源。 再 `bgctl list` 確認沒有 job 留著佔資源。
NFC tag 讀取由 `nfc_polling.sh` 背景輪詢(A 做基線、B 起、C 停並 report)。 NFC tag 讀取由 `nfc_polling.sh` 背景輪詢(A 做基線、B 起、C 停並 report)。
另有 **`4_Blanton_Script_thermal_safety.ttl`**(熱 / 安規,**獨立跑不接 A→B→C**,滿載後每分鐘 另有 **`4_Blanton_Script_thermal_safety.ttl`**(熱 / 安規,**獨立跑不接 A→B→C**,滿載後每分鐘
取 PMON + 兩片 SWB 的軌功耗;**沒有收尾段**,中斷後要手動 `blanton_tr518.sh stop`)。 取 PMON + 兩片 SWB 的軌功耗 + **AMD CPU 封裝功耗**(`avt_pmpower.sh`,V1.2.3);**沒有收尾段**,中斷後要手動 `blanton_tr518.sh stop`)。
以及 **`5_Blanton_Script_Reboot_Cycle.ttl`**(重開機循環,**獨立跑不接 A→B→C**:登入 → 風扇 → **V1.2.3 起 PMON 快照(`utils/setup_pmon.ttl`)多了 DDR5 DIMM 溫度(`ddr5_temp.sh`)與 LTC4287 HSC 溫度
(`hsc_temp_readback.sh`)**,A/B/C/4/5 全部吃到;HSC 那支每次約 +4 秒。
以及 **`5_Blanton_Script_Boot_Cycle.ttl`**(重開機循環,**獨立跑不接 A→B→C**:登入 → 風扇 →
Check Pt1~Pt13 → `reboot` → `wait "Booting in blind mode"`,`cnt_cycle` 每輪遞增,`while 1` 無止境, Check Pt1~Pt13 → `reboot` → `wait "Booting in blind mode"`,`cnt_cycle` 每輪遞增,`while 1` 無止境,
要停就關 Tera Term 的 macro)。**尚未上機驗證**。 要停就關 Tera Term 的 macro)。**尚未上機驗證**。
流程圖:`docs/Blanton_Test_Flow.drawio`。 流程圖:`docs/Blanton_Test_Flow.drawio`。
最後一次發布是 **V1.1.5**;SWB 的 I2C 通道與位址已於 2026-08-19 上機驗證。 最後一次發布是 **V1.2.3**;SWB 的 I2C 通道與位址已於 2026-08-19 上機驗證。
margin 的 `VNOM` 已於 2026-08-30 改為 Blanton 實測中位數(144 條軌中 86 條上調 0.8~2.5%)。 margin 的 `VNOM` 已於 2026-08-30 改為 Blanton 實測中位數(144 條軌中 86 條上調 0.8~2.5%)。
交付用 `./publish/publish.sh` 打包。 交付用 `./publish/publish.sh` 打包。
@@ -129,6 +131,15 @@ bash ~/Blanton_Script/port_prbs_monitor.sh report # PASS/FAIL 統計(沒
bash ~/Blanton_Script/port_prbs_monitor.sh stop # 收尾會跑 prbsstat STOp + prbs clear bash ~/Blanton_Script/port_prbs_monitor.sh stop # 收尾會跑 prbsstat STOp + prbs clear
# ⚠️ PRBS 打起來時 link 會顯示 down,這是正常的 —— 所以 start 刻意不印 port status # ⚠️ PRBS 打起來時 link 會顯示 down,這是正常的 —— 所以 start 刻意不印 port status
# ── 溫度 / CPU 功耗(V1.2.3,已接進 PMON / Script 4)──
~/Blanton_Script/ddr5_temp.sh # DDR5 DIMM 溫度(SPD5118,預設 bus 5, 0x50 0x51)
~/Blanton_Script/ddr5_temp.sh 5 0x50 # 指定 bus / 位址
~/Blanton_Script/hsc_temp_readback.sh # LTC4287 HSC_MAIN(0x40)/HSC_STBY(0x45) 內外部溫度,bus 28,約 4 秒
~/Blanton_Script/avt_pmpower.sh -p ~/AVT_Linux_NDA_2.8.37/AVTCMD # CPU SktPwr / PPT / MemPwr
~/Blanton_Script/avt_pmpower.sh -q -p ... # 只印摘要,不倒整張 PM table
# ⚠️ AVT 是 NDA,不在交付包裡:DUT 上要先解壓到 ~/AVT_Linux_NDA_2.8.37/,沒有就每輪 exit 2
# ⚠️ 數值是 SMU telemetry 不是量測,要準就對照 VR 的 PMBus READ_POUT
# ── PDB / CPB power brick 讀值 ────────────────────── # ── PDB / CPB power brick 讀值 ──────────────────────
./Blanton_Script/pwr_brick.sh show # Vin/Iin/Vout/Iout/Temp × 5 顆 ./Blanton_Script/pwr_brick.sh show # Vin/Iin/Vout/Iout/Temp × 5 顆
./Blanton_Script/pwr_brick.sh show -r # 多印 raw word ./Blanton_Script/pwr_brick.sh show -r # 多印 raw word
+53
View File
@@ -0,0 +1,53 @@
# v1.2.3 — DIMM and hot-swap temperatures in every snapshot, and CPU power next to the switch rails
## ✨ New features
**Every PMON snapshot now reads DDR5 DIMM and hot-swap controller temperatures**
* `utils/setup_pmon.ttl` runs `ddr5_temp.sh` and `hsc_temp_readback.sh` right after `show platform temperature`. Because `setup_pmon` is shared, this lands everywhere a snapshot is taken: Script A's baseline, each Script B soak round, Script C, the Script 4 loop and every Script 5 check point.
* `ddr5_temp.sh` reads the SPD5118 hub on each DIMM: i2c bus 5, `0x50` / `0x51`, register `0x31` (`bit[12:2]`, sign bit 12, 0.25 °C/LSB). A read that fails prints `read fail` — never a number it did not read. Bus and addresses can be passed: `ddr5_temp.sh [bus] [addr ...]`.
* `hsc_temp_readback.sh` reads both LTC4287 hot-swap controllers on i2c bus 28 — `HSC_MAIN @ 0x40` (PU11 internal / PQ1 external) and `HSC_STBY @ 0x45` (PU46 internal / PQ53 external). The source is selected through `0xF3`, then `READ_TEMPERATURE` `0x8D` is read in Kelvin and converted.
**Script 4 logs AMD CPU package power every round**
* `avt_pmpower.sh` runs `AVTCMD -module pmm "get_pmdata()"` and summarizes `SktPwr`, `PPT Fast` / `PPT Slow` against their limits, and `MemPwr`.
* It runs after the two `TH6_SWB` power readbacks, so each sample now puts the switch rails and the CPU package side by side.
* `-q` prints the summary only. Exit `2` = AVTCMD not found, `3` = AVTCMD failed, `4` = the PM table parsed to nothing (format changed).
## 🐛 Bug fixes
**`hsc_temp_readback.sh` was saved with CRLF line endings**
* Copied to the DUT as-is, bash on SONiC fails on the first line (`$'\r': command not found`). The shipped file is LF.
* Its comments said the delay between I2C transactions was 100 ms; `DELAY=0.5` is what actually runs. Comments corrected and a Version History header added.
## 📦 Downloads
| File | Contents |
|---|---|
| `Script_ABC_Blanton_V1.2.3.zip` | The full Tera Term working directory, including `Blanton_Script/` to copy onto the DUT |
```bash
chmod +x ~/Blanton_Script/*.sh
grep -rlU $'\r' ~/Blanton_Script # expect no output
ls ~/AVT_Linux_NDA_2.8.37/AVTCMD # Script 4 only - must already be there
```
## ⚠️ Before you run
* **Redeploy `Blanton_Script/`.** If an earlier copy of `hsc_temp_readback.sh` reached the DUT, it is CRLF and will not run.
* **`chmod +x` after deploying.** `setup_pmon` calls both new scripts by path. Without the exec bit each call is `Permission denied` and the snapshot carries on without those rows — nothing stops, nothing warns.
* **Each PMON snapshot is ~4 s longer.** `hsc_temp_readback.sh` sleeps 0.5 s twice for each of its four readings. It adds up in Script 5, which snapshots at every check point.
* **AVT is not in this package (NDA).** Unpack it on the DUT at exactly `~/AVT_Linux_NDA_2.8.37/` before Script 4. Missing, the call exits `2` every round and the loop runs on without a CPU power reading.
* **Script 4 logs the full PM table once a minute**, because the call is made without `-q`.
* **CPU power is SMU telemetry, not a measurement.** Its absolute accuracy is whatever the BIOS SVI calibration gives — cross-check against the VR's PMBus `READ_POUT` when the number matters.
* **None of the three new scripts has been checked against the Script A/B/C flow on hardware yet.**
* **Do not run the boot cycle with `EN_Cold_Warm_boot = 0`**, and check the hard-coded BDF on every board before the cold path (see v1.2.2).
* **BER, the DSC cycle, `blanton_traffic_linespeed` and `blanton_tr518.sh` cannot overlap.** They all take the same ports.
* **Script 4 has no teardown**: finish it with `blanton_tr518.sh stop` **and** `systemctl stop mlucas-amm`.
* **`blanton_multiphase_margin.sh save` is permanent**, and must not be mixed with `margin.sh`.
* **`FAN_SPEED` is 100.**
## 🔗 Links
* [ARCHITECTURE.md](https://etgit.et-wen.com/etwen/Blanton_TTL_Script/src/branch/main/ARCHITECTURE.md) — test flow, data models, constraints
* [CLAUDE.md](https://etgit.et-wen.com/etwen/Blanton_TTL_Script/src/branch/main/CLAUDE.md) — commands and the bench gotchas
**Full changelog:** [V1.2.2...V1.2.3](https://etgit.et-wen.com/etwen/Blanton_TTL_Script/compare/V1.2.2...V1.2.3)
+50 -2
View File
@@ -1,7 +1,7 @@
; ============================================================================= ; =============================================================================
; Script A for Blanton ; Script A for Blanton
; Version : V1.2.2 ; Version : V1.2.3
; Date : 2026-09-15 ; Date : 2026-09-23
; Author : ETWen ; Author : ETWen
; ============================================================================= ; =============================================================================
; Version History: ; Version History:
@@ -692,6 +692,54 @@
; version of the commands, kept so the .sh can be checked ; version of the commands, kept so the .sh can be checked
; against what a person would actually type. Change one and ; against what a person would actually type. Change one and
; change the other ; change the other
; V1.2.3 2026-09-23 utils/setup_pmon.ttl Add DDR5 DIMM temperature + hot-swap controller temperature
; ~/Blanton_Script/ddr5_temp.sh, then hsc_temp_readback.sh,
; right after 'show platform temperature'
; setup_pmon is shared, so this lands in every PMON snapshot:
; ScriptA baseline, every ScriptB soak round, ScriptC, the
; Script 4 loop and each Script 5 check point
; !! hsc_temp_readback.sh sleeps 0.5 s twice per reading and
; takes four readings - ~4 s added to every PMON snapshot
; !! both are called by path, not through bash, so they need
; the exec bit on the DUT: chmod +x ~/Blanton_Script/*.sh
; after deploying. Without it each call is Permission
; denied and the snapshot just goes on without the rows
; Blanton_Script/ddr5_temp.sh Created v1.0.1 - DDR5 DIMM temperature from the SPD5118 hub
; i2cget bus 5, DIMM 0x50 / 0x51, register 0x31 (MR49/MR50)
; bit[12:2], sign bit 12, 0.25 C/LSB. Bus and addresses can
; be given as arguments: ddr5_temp.sh [bus] [addr ...]
; A failed read prints 'read fail' and moves on to the next
; DIMM - it never prints a number it did not read
; Blanton_Script/hsc_temp_readback.sh Created - LTC4287 hot-swap controller temperatures
; Native i2c bus 28. HSC_MAIN @ 0x40 (PU11 internal / PQ1
; external) and HSC_STBY @ 0x45 (PU46 internal / PQ53
; external). Source picked by writing 0xF3 (0xEB internal,
; 0xEF external), then READ_TEMPERATURE 0x8D, Kelvin -> C
; v1.0.1 Add the header + Version History, fix the delay
; comments (they said 100 ms; DELAY is 0.5 s)
; !! v1.0.0 was saved with CRLF line endings. On SONiC that
; fails outright ($'\r': command not found) - now LF
; Blanton_Script/avt_pmpower.sh Created v1.0.0 - AMD CPU package power from the AVT PM table
; AVTCMD -module pmm "get_pmdata()", then a summary of
; SktPwr, PPT Fast / Slow against their limits, and MemPwr
; -p <AVTCMD path>, -q for the summary without the raw table
; Exit 2 = AVTCMD not found, 3 = AVTCMD failed, 4 = the table
; parsed to nothing (format changed)
; !! SMU telemetry, not a measurement - its absolute accuracy
; is whatever the BIOS SVI calibration gives. Cross-check
; against the VR's PMBus READ_POUT when the number matters
; 4_Blanton_Script_thermal_safety.ttl Add CPU package power to every loop round
; avt_pmpower.sh -p ~/AVT_Linux_NDA_2.8.37/AVTCMD, after the
; two TH6_SWB power readbacks - so each round now has the
; switch rails and the CPU package side by side
; !! AVT is NOT in Blanton_Script and does not travel with
; this package (NDA). It has to be unpacked on the DUT at
; exactly ~/AVT_Linux_NDA_2.8.37/ beforehand. If it is not
; there the script exits 2 every round and the loop carries
; on without a CPU power reading
; !! without -q the full PM table is printed every round, and
; Script 4 loops once a minute - the log grows by one full
; table per minute
; ============================================================================= ; =============================================================================
include "config.ttl" include "config.ttl"
@@ -152,6 +152,8 @@ while 1
sendln "~/Blanton_Script/TH6_SWB0_power_readback.sh" sendln "~/Blanton_Script/TH6_SWB0_power_readback.sh"
wait prompt_sonic_root wait prompt_sonic_root
sendln "~/Blanton_Script/TH6_SWB1_power_readback.sh" sendln "~/Blanton_Script/TH6_SWB1_power_readback.sh"
wait prompt_sonic_root
sendln "~/Blanton_Script/avt_pmpower.sh -p ~/AVT_Linux_NDA_2.8.37/AVTCMD"
; Background jobs Check ; Background jobs Check
wait prompt_sonic_root wait prompt_sonic_root
@@ -0,0 +1,137 @@
#!/bin/bash
#===============================================================================
# Script : avt_pmpower.sh
# Purpose : Dump AMD AVT PM table (get_pmdata) and summarize package power.
#
# Author : ETWen
# Date : 20260923
#
# Version History
# V1.0.0 20260923 Initial Version
#
# Usage : ./avt_pmpower.sh [-p <AVTCMD path>] [-q] [-h]
# -p Path to AVTCMD (default: $AVTCMD_PATH or ./AVTCMD)
# -q Quiet: summary only, suppress raw PM table
# -h Help
#
# Exit : 0 ok / 1 usage / 2 AVTCMD not found / 3 AVTCMD failed
# 4 parse failed (no power fields found)
#
# Note : Values come from SMU telemetry, not direct measurement. Absolute
# accuracy depends on BIOS SVI telemetry calibration. Cross-check
# against VR PMBus READ_POUT when accuracy matters.
#===============================================================================
set -u
set -o pipefail
#------------------------------------------------------------------------------
# Defaults
#------------------------------------------------------------------------------
AVTCMD_BIN="${AVTCMD_PATH:-./AVTCMD}"
AVT_MODULE="pmm"
AVT_CMD="get_pmdata()"
QUIET=0
#------------------------------------------------------------------------------
# usage - print help
#------------------------------------------------------------------------------
usage() {
sed -n '/^# Usage/,/^# Exit/p' "$0" | sed 's/^# \{0,1\}//'
}
#------------------------------------------------------------------------------
# Argument parsing
#------------------------------------------------------------------------------
while getopts ":p:qh" opt; do
case "$opt" in
p) AVTCMD_BIN="$OPTARG" ;;
q) QUIET=1 ;;
h) usage; exit 0 ;;
:) echo "ERROR: -$OPTARG requires an argument" >&2; usage >&2; exit 1 ;;
\?) echo "ERROR: unknown option -$OPTARG" >&2; usage >&2; exit 1 ;;
esac
done
#------------------------------------------------------------------------------
# Pre-flight check
#------------------------------------------------------------------------------
if [ ! -x "$AVTCMD_BIN" ]; then
echo "ERROR: AVTCMD not found or not executable: $AVTCMD_BIN" >&2
echo " Use -p <path> or export AVTCMD_PATH=<path>" >&2
exit 2
fi
if [ "$(id -u)" -ne 0 ]; then
echo "WARN : not running as root, AVTCMD may fail to access SMU." >&2
fi
#------------------------------------------------------------------------------
# Collect PM table
#------------------------------------------------------------------------------
RAW="$("$AVTCMD_BIN" -module "$AVT_MODULE" "$AVT_CMD" 2>&1)"
RC=$?
if [ $RC -ne 0 ]; then
echo "ERROR: AVTCMD exited with code $RC" >&2
echo "$RAW" >&2
exit 3
fi
if [ "$QUIET" -eq 0 ]; then
printf '%s\n' "$RAW"
fi
#------------------------------------------------------------------------------
# Parse & summarize
# - split on whitespace and comma, keep only "key:number" tokens
# - bracketed tokens ([Pkg:0], [MISC]) are skipped by the regex anchor
#------------------------------------------------------------------------------
printf '%s\n' "$RAW" | awk '
{
n = split($0, a, /[ ,]+/)
for (i = 1; i <= n; i++) {
if (a[i] ~ /^[A-Za-z0-9_()]+:[-0-9.]+$/) {
split(a[i], kv, ":")
m[kv[1]] = kv[2]
found++
}
}
}
# pct - usage against limit, guard divide-by-zero
function pct(v, l) {
return (l > 0) ? sprintf("%5.1f%%", 100 * v / l) : " n/a"
}
# has - field present in PM table
function has(k) {
return (k in m)
}
END {
if (found == 0) {
print "ERROR: no PM fields parsed, PM table format may have changed." > "/dev/stderr"
exit 4
}
print "===== Package Power (live) ====="
if (has("SktPwr(W)"))
printf "%-9s: %7.2f W\n", "SktPwr", m["SktPwr(W)"]
if (has("PPT_VALUE_FAST"))
printf "%-9s: %7.2f / %3d W %s\n", "PPT Fast",
m["PPT_VALUE_FAST"], m["PPT_LIMIT_FAST"],
pct(m["PPT_VALUE_FAST"], m["PPT_LIMIT_FAST"])
if (has("PPT_VALUE_SLOW"))
printf "%-9s: %7.2f / %3d W %s (%ss avg)\n", "PPT Slow",
m["PPT_VALUE_SLOW"], m["PPT_LIMIT_SLOW"],
pct(m["PPT_VALUE_SLOW"], m["PPT_LIMIT_SLOW"]),
(has("SlowPPTTimeConstant") ? m["SlowPPTTimeConstant"] : "?")
if (has("MemPwr(W)"))
printf "%-9s: %7.2f W\n", "MemPwr", m["MemPwr(W)"]
}
'
exit $?
@@ -0,0 +1,34 @@
#!/bin/bash
#==============================================================================
# Author : ETWen
# Date : 20260923
# Purpose : Read DDR5 DIMM temperature from SPD5118 hub (MR49/MR50 @ 0x31)
# Usage : ./ddr5_temp_V1.0.1.sh [bus] [addr ...]
# default: bus=5, addr=0x50 0x51
#
# Version History:
# V1.0.0 20260923 Initial Version
# V1.0.1 20260923 Output label "DDR temp"
#==============================================================================
BUS=${1:-5}
shift 2>/dev/null
ADDRS=("$@")
[[ ${#ADDRS[@]} -eq 0 ]] && ADDRS=(0x50 0x51)
REG_TEMP=0x31
for ADDR in "${ADDRS[@]}"; do
raw=$(i2cget -y "$BUS" "$ADDR" "$REG_TEMP" w 2>&1)
if [[ $? -ne 0 || ! $raw =~ ^0x[0-9a-fA-F]+$ ]]; then
echo "[bus $BUS $ADDR] read fail: $raw"
continue
fi
# bit[12:2] = temperature, bit12 = sign, 0.25 C/LSB
v=$(( (raw >> 2) & 0x7FF ))
(( v & 0x400 )) && v=$(( v - 0x800 ))
awk -v b="$BUS" -v a="$ADDR" -v r="$raw" -v v="$v" \
'BEGIN { printf "[bus %s %s] DDR temp: %.2f C (raw=%s)\n", b, a, v * 0.25, r }'
done
@@ -0,0 +1,65 @@
#!/bin/bash
#==============================================================================
# Author : ETWen
# Date : 20260923
# Purpose : Read LTC4287 hot-swap controller temperatures (HSC_MAIN / HSC_STBY)
# Select source via 0xF3 (0xEB internal / 0xEF external), then read
# READ_TEMPERATURE 0x8D (Kelvin) and convert to Celsius
# Usage : ./hsc_temp_readback.sh
# bus = BUS (28), HSC_MAIN @ 0x40, HSC_STBY @ 0x45
#
# Version History:
# V1.0.0 20260922 Initial Version
# V1.0.1 20260923 Add header; fix delay comments (DELAY is 0.5 s, not 100 ms);
# CRLF -> LF (CRLF breaks bash on SONiC)
#==============================================================================
BUS=28
DELAY=0.5 # seconds between I2C transactions; ~4 s per run (4 readings x 2)
read_temp() {
local addr="$1"
local name="$2"
local sel="$3"
# Select temperature source
i2ctransfer -f -y "$BUS" w3@"$addr" 0xF3 "$sel" 0x00 > /dev/null
# DELAY between I2C transactions
sleep "$DELAY"
# Read temperature register 0x8D
raw=$(i2cget -f -y "$BUS" "$addr" 0x8D w 2>/dev/null)
if [ -z "$raw" ]; then
printf "%-32s : READ ERROR\n" "$name"
sleep "$DELAY"
return
fi
# Remove 0x prefix and convert hexadecimal to decimal
raw_dec=$((16#${raw#0x}))
# LTC4287 temperature is in Kelvin
temp_c=$(awk "BEGIN {printf \"%.2f\", $raw_dec - 273.15}")
printf "%-32s : %8s °C (raw %s)\n" \
"$name" "$temp_c" "$raw"
# DELAY before next I2C transaction
sleep "$DELAY"
}
echo "=========================================================="
echo " LTC4287 Temperature Readback"
echo "=========================================================="
# HSC_MAIN - LTC4287 @ 0x40
read_temp 0x40 "HSC_MAIN Internal (PU11)" 0xEB
read_temp 0x40 "HSC_MAIN External (PQ1)" 0xEF
# HSC_STBY - LTC4287 @ 0x45
read_temp 0x45 "HSC_STBY Internal (PU46)" 0xEB
read_temp 0x45 "HSC_STBY External (PQ53)" 0xEF
echo "=========================================================="
@@ -5,6 +5,10 @@ sendln "show platform fan"
wait prompt_sonic_root wait prompt_sonic_root
sendln "show platform temperature" sendln "show platform temperature"
wait prompt_sonic_root wait prompt_sonic_root
sendln "~/Blanton_Script/ddr5_temp.sh"
wait prompt_sonic_root
sendln "~/Blanton_Script/hsc_temp_readback.sh"
wait prompt_sonic_root
sendln "show platform psustatus" sendln "show platform psustatus"
wait prompt_sonic_root wait prompt_sonic_root
sendln "show platform voltage" sendln "show platform voltage"