Compare commits

...
25 Commits
Author SHA1 Message Date
etwenandClaude Opus 5 b911ccd658 docs: Record V1.2.2 in Script A's history and add the release note
Script A: four entries under V1.2.2 for blanton_ber.sh v1.1.0 and
v1.1.1, bcm_100g_dsc_cycle.sh, and tools/100G_dsc_cycle.txt; header date
to 2026-09-15.

CLAUDE.md: status to V1.2.2; the BER paragraph notes port 268 and the
per-unit group summary; a commands block for bcm_100g_dsc_cycle.sh; the
BER command block notes the three summary rows and that a zero-lane
group is a failure; and a new gotcha that 'prbs get' output is data, not
diagnostics.

ARCHITECTURE.md: Script A ref to V1.2.2; the BER row covers port 268 and
the group summary; a Key Features row for the 100G cycle test; both new
files in the tree; the git tag checkbox to V1.2.2; a known issue for the
unverified cycle script; and one recording that a completeness check
which cannot see a failure has now bitten this repo three times -
bcm_dsc_scan.sh counting its own markers, blanton_ber.sh reading lane
results as shell errors, and the power-cycle report parser turning a
100% packet loss into "no data".

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014RetWKFZFG1ZHcitQAyhwM
2026-09-15 21:27:40 +08:00
etwenandClaude Opus 5 dd558a7b0f feat(dsc): Add the 100G link down/up cycle test
bcm_100g_dsc_cycle.sh tunes once - gbsyncd paused, serdes-tx-set on
sys 0..7, tx_taps per lane - then repeats: port 268 en=0, wait, en=1,
wait, phydiag 268 dsc on both units, and the retimer read back with
serdes-tx-get / serdes-rx-get for sys 0..7. One log per run under
~/dsc_log, split by "### TEST CYCLE n/N", ending in
"### DSC_CYCLE_DONE rc=<n>" for a TTL wait to key on.

Waiting for a link state polls "bcmcmd ps <port>" rather than reading
"show interfaces status". "port en=" changes the SDK, and the SONiC
table only follows once gbsyncd and orchagent have synced it - and this
test pauses gbsyncd, so the SONiC table was the wrong thing to wait on.
The state is read from the row whose first field ends in "(<port>)", and
"down" is tested as "not up" so !ena counts.

All output is ASCII English on purpose: the DUT serial console mangles
UTF-8, and a Chinese error message came back as "ERROR: -c ? 1" - an
error you cannot read is worse than none. -d echoes every command as a
grey [CMD] line, CMD_DELAY paces them, and -n is a dry run that touches
nothing and sleeps not at all. The cycle count may be given as a bare
argument, which is what people type first.

Not verified on hardware. gbsyncd is unpaused again on exit, Ctrl-C
included.

tools/100G_dsc_cycle.txt is the hand-typed bench version of the same
commands, kept the way BER_Test.txt and TR518.txt are, so the script can
be checked against what a person would actually run.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014RetWKFZFG1ZHcitQAyhwM
2026-09-15 21:27:25 +08:00
etwenandClaude Opus 5 690be5db7d feat(ber): Measure port 268, and stop reading lane results as shell errors
The port list ran 256-259 straight to 270-308, so ce0(268) - the 100G
uplink - was never measured. It is now its own group:

    BER_PORTS_200G   the cabled 200G ports
    BER_PORTS_100G   268, one per unit

They go out on one phydiag command and come back reported apart. The
summary gives each unit three rows - 200G ports, 100G p268, TOTAL -
because unit 0 and unit 1 each have their own ce0(268), and a marginal
uplink lane averaged into 432 others is invisible. TOTAL is not a
hand-added sum: every lane is folded into its own group and into ALL
separately, so the parts cannot drift from the whole. A group that
reports no lane at all counts as a failure - silence on the port under
test is the easiest way to ship a green report that measured nothing.

Separately, a fix that has been needed since v1.0.0. init kept answering

    [ERR ] unit 1: the BCM shell rejected 'phydiag ... prbs get'

on runs that were working. 'prbs get' prints one line per lane, a lane
that has not locked says "PRBS Error!", and the rejection check grepped
the whole output case-insensitively for ERROR|Invalid|... - so the
measurement matched the pattern meant for shell diagnostics.

The false alarm was the smaller half. The function returned early, which
skipped the lock count that was supposed to judge those very lanes: the
operator saw an error they could not act on, and did not see which lanes
had failed to lock. Per-lane lines are now excluded from the check, the
match is case-sensitive, and a genuine rejection prints the offending
line.

Developed on the bench as blanton_ber_test.sh and folded back over this
file once proven, so there is one BER script again rather than two with
diverging port lists.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014RetWKFZFG1ZHcitQAyhwM
2026-09-15 21:27:25 +08:00
etwenandClaude Opus 5 a5b7c4757b feat(boot): Name the log and the banner after the kind of boot
EN_Cold_Warm_boot = 1 opens Logs\Blanton_Reboot_Cycle_<ts>.log and prints
a "Reboot Cycle : N" banner each round; = 2 opens
Blanton_Power_Cycle_<ts>.log and prints "Power Cycle : N". Three sites
branch on the flag now: the log name, the banner, and the boot itself.

Two things follow from it.

With EN_Cold_Warm_boot = 0 there is no longer a logopen either, so the
run that already hangs at wait "Booting in blind mode" now also leaves no
log to show where it stopped. EN_log = 1 on its own no longer produces a
log from this macro.

And anything that parses these logs has to accept both banners. The cycle
banner is the record separator the check-point and per-segment timing
reports are built on, so a parser that only greps "Reboot Cycle :" finds
zero cycles in a power-cycle log and reports nothing without complaining.

The logopen timestamp flag stays a literal 1 rather than EN_timestamp the
way Script A does it. That is the right call here - the per-segment
timing analysis is derived from those timestamps and there is no other
way to recover them - but it does mean this macro ignores
EN_timestamp = 0.

Recorded under V1.2.2 in Script A's history; the header version is
unchanged because V1.2.2 has not been tagged.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014RetWKFZFG1ZHcitQAyhwM
2026-09-09 10:15:39 +08:00
etwenandClaude Opus 5 f5694345fb feat(boot): Rename Script 5 to Boot Cycle, add a cold path and stop the log growing
The macro does warm and cold now, so "Reboot" was too narrow:
5_Blanton_Script_Reboot_Cycle.ttl -> 5_Blanton_Script_Boot_Cycle.ttl.

EN_Cold_Warm_boot in config.ttl picks which:

  0  neither - for the A/B/C flow, where this macro is not used
  1  reboot (warm), what the macro always did
  2  cold, by writing the CB FPGA:
     pcimem .../0000:05:00.0/resource0 0x480 w 0xD0000

Three things about that worth knowing before anyone runs it. Setting 0 and
then running this macro hangs it: nothing reboots, and the
wait "Booting in blind mode" underneath has no timeout, so it waits for a
boot that will never come. 0x480 is ICB_CTRL_REG in
docs/Blantons_FPGA_Registers.md and that table has no bit definitions for
it, nor is 0xD0000 written down anywhere in this repo. And the BDF
0000:05:00.0 is hard-coded, while blanton_fpga_pcimem.sh auto-detects the
CB FPGA precisely because it moves per unit - on a DUT where it is not at
05:00.0 this is a raw 32-bit write to an unknown register on some other
device. The cold path has not been run on hardware.

Separately, both stress logs are now removed before each run:

  rm -rf /host/hw-eval/jobs/qfx5252-stress-{ssd,usb}.log

qfx5252-stress-* appends to its --log file and the macro cats the whole
thing afterwards, so every cycle printed back everything the cycles
before it had written. On the 199-cycle log from 2026-09-04 that was 289
lines at cycle 1 and 36,555 at cycle 199; at ~6.2 ms a line, which is
what a 115200 baud console costs, it accounts for +212 s of the +214 s
the cycle grew over the run. The stress itself is fixed at --runtime 30,
and the other eleven gaps between check points drifted by under 1.5 s
each. The DUT was never getting slower - the test was reading its own
history aloud, once per cycle.

Script A's header goes to V1.2.2 and its Version History covers all of
the above.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014RetWKFZFG1ZHcitQAyhwM
2026-09-09 09:14:09 +08:00
etwenandClaude Opus 5 7a1967bc9a docs: Update CLAUDE / ARCHITECTURE for V1.2.1 and add the release note
CLAUDE.md: status to V1.2.1 / 2026-09-08; the BER paragraph now says
Script A takes a baseline as well as Script C taking the closing sweep;
and a new gotcha that 'clear' is what puts the lanes back, with the
Script A versus Script C traffic reports as the way to tell whether they
came back in time.

ARCHITECTURE.md: Script A ref to V1.2.1 and its row updated with the
baseline sweep; the BER row notes both call sites; the sleep 30 /
BER_INTERVAL known issue now says three places rather than two; a new
known issue for the missing settle between Script A's BER clear and its
first traffic run; and the git tag checkbox to V1.2.1.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014RetWKFZFG1ZHcitQAyhwM
2026-09-08 09:35:36 +08:00
etwenandClaude Opus 5 496e3ab650 feat(ttl): Take a BER baseline in Script A, before the first traffic run
blanton_ber.sh init -> start -> sleep 30 -> report -> stop -> clear,
branched on SWB_UNIT0 / SWB_UNIT1 the same way the traffic block beside it
is.

Script C already took the closing sweep after its traffic report. With
this one at the front the pair brackets the soak, the same shape the DSC
scans got in V1.2.0 and for the same reason: one BER figure says very
little, a change in it says a lot.

The sleep 30 is blanton_ber.sh's BER_INTERVAL. Reporting before a full
interval has accumulated reads a window that has not finished, and
nothing warns about it - that number now lives in three places.

The block was copied out of Script C, whose comment says it runs after
the traffic report, because there it does. Here it runs before. The
comment was rewritten to describe where the code actually sits and why
'clear' has to happen before the traffic block.

Not yet run on hardware. Nothing settles between blanton_ber.sh clear and
the blanton_traffic_linespeed ps that follows it, and 'clear' is what
releases lanes PRBS was holding out of normal operation. Script C does
not have that ordering, so the two traffic reports are a built-in
comparison: NA or FAIL pairs in Script A's that are absent from
Script C's mean the lanes had not come back, and a sleep after 'clear'
is the fix.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014RetWKFZFG1ZHcitQAyhwM
2026-09-08 09:35:36 +08:00
etwenandClaude Opus 5 29ec4c2239 docs: Update CLAUDE / ARCHITECTURE for V1.2.0 and add the release note
CLAUDE.md: status to V1.2.0 / 2026-09-07; the PRBS paragraph now says the
A/B/C call sites were deleted in V1.1.9 rather than commented out; the
DSC scan and parser get a commands block and a line in the status
summary; the soak loop uses sleep 60; the bcmcmd gotcha records that
bcm_dsc_scan.sh hit the same stdin trap on 2026-09-07 and why the
existing marker check could not see it; and a new gotcha on pause versus
sleep.

ARCHITECTURE.md: bcm_dsc_scan.sh / bcm_dsc_parse.sh in the tree and a
Key Features row of their own; EN_TX_FIR in the config.ttl line; Script A
ref to V1.2.0 and the A / B / C rows updated for the DSC steps and sleep;
constraint 10 extended with the recurrence; new constraint 18 (pause
stops the macro, sleep stops the DUT) with the old 18 renumbered to 19
and EN_TX_FIR added to it; the git tag checkbox to V1.2.0; the PRBS and
bmc_monitor_ddr known issues corrected from "commented out" to "deleted";
and a new known issue for the DSC scan being off by default and sharing
ports with the other traffic tools.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014RetWKFZFG1ZHcitQAyhwM
2026-09-07 10:02:42 +08:00
etwenandClaude Opus 5 d73b119dc3 feat(ttl): Wait on the DUT with sleep, and gate the DSC scan on EN_TX_FIR
Every 'pause N' in Scripts A, B and C is now 'sendln "sleep N"' followed
by 'wait prompt_sonic_root'.

pause stops the macro for N seconds without touching the DUT: the shell
sits idle and the macro is guessing how long the previous command needed.
On a loaded DUT the guess runs short, the next command goes out before
the previous one has finished, and the whole run ends up a beat ahead of
the switch. Putting the wait on the DUT means the macro resumes when the
prompt actually returns, so the two cannot drift apart - and the wait
lands in the console log with a timestamp, so a round that ran long is
visible afterwards.

Durations changed with it: the management-ping sample in Script A is 15 s
(was 30) and the settle after each traffic 'clear' is 5 s (was 15). The
traffic run stays 15 s and Script B's monitor loop stays 60 s. Script 4
and Script 5 were not converted; the 'pause 1' at the top of B and C
stays, since it runs before there is a prompt to wait for.

EN_TX_FIR gates the DSC scan in Script A and Script C, and the four cp
lines that carry blanton_dsc_Script{A,C}_u{0,1}.log out with the job
logs. It defaults to 0: a full scan is ~10 min and both scripts do one,
so leaving it off keeps ~20 min out of a routine run.

Script C also stops printing bmc_poll.log and mlucas_amm_log to the
console. Both are still copied to /host/hw-eval/jobs and out to the USB
stick, so nothing is lost - the master log is just shorter.

Script A's header goes to V1.2.0 and its Version History covers all of
the above.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014RetWKFZFG1ZHcitQAyhwM
2026-09-07 10:02:42 +08:00
etwenandClaude Opus 5 79a3604ac4 fix(dsc): bcmcmd was eating the port list, so only one port was scanned
The scan loop read its port file on stdin. bcmcmd reads stdin too, so the
first call swallowed the rest of the file and the loop ended after a
single port.

Nothing about that looked wrong. The log held one PORT marker and one dsc
block, the marker-to-dump comparison passed because both counts shrank
together, the exit code was 0, and a 445-port scan just finished in
seconds.

The loop now reads on fd 3 (done 3< "$PORTFILE") and bcmcmd is given
< /dev/null. A second check compares the iteration count against the port
list count - the marker/dump comparison cannot see a loop that ends
early, so it needed a number that does not shrink with it. The Saved:
line reports dumps out of TOTAL rather than out of markers.

This is the same bcmcmd trap blanton_traffic_linespeed.sh hit at v0.3.1,
where only the first VLAN was configured.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014RetWKFZFG1ZHcitQAyhwM
2026-09-07 10:02:25 +08:00
etwenandClaude Opus 5 b84188322d feat(ttl): Take a SerDes DSC dump in Script A and Script C
Script A scans just before 'show uptime', Script C just before the NVMe
error info, so the pair brackets the soak:

    ./Blanton_Script/bcm_dsc_scan.sh -f blanton_dsc_ScriptA.log -F
    ./Blanton_Script/bcm_dsc_scan.sh -f blanton_dsc_ScriptC.log -F

Neither name carries %u, so the scan inserts _u0 / _u1 itself and unit 1
cannot overwrite unit 0 - that is where the four file names Script C
copies to /host/hw-eval/jobs come from. The scan already copies its own
output there; the explicit cp lines are a second pass, so a copy that
fails inside the scan still leaves the data on the USB stick.

Also removed the commented-out 100G PRBS call sites from all three
macros, along with a duplicated commented 100G port status block in
Script A and the stale bmc_monitor_ddr.sh block in Script C. They had
been dead since bring-up. port_prbs_monitor.sh still ships and still
runs by hand.

Script A's header goes to V1.1.9 and its Version History covers all of
the above, including the note that both new scripts are recorded 100644
and need chmod +x on the DUT.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014RetWKFZFG1ZHcitQAyhwM
2026-09-06 23:22:59 +08:00
etwenandClaude Opus 5 b4148c9571 feat(dsc): Add the SerDes DSC scan and its offline CSV parser
bcm_dsc_scan.sh runs

    bcmcmd -n <unit> -c "dsh -c 'phydiag <port> dsc'"

over the whole port list (one 100G port plus the 200G ranges, ~445 in
total) on both units, writes the raw log under <script_dir>/log, and
copies it to /host/hw-eval/jobs. -f names the log (%u -> u0/u1, %t ->
timestamp), -F overwrites, -u picks one unit, -n dry runs, -C skips the
copy.

Two things it deliberately does not do:

  - judge success by bcmcmd's exit code. The diag shell rejects commands
    and bcmcmd still exits 0, so the script counts
    "SERDES DISPLAY DIAG DATA END" markers instead. Same trap
    blanton_traffic_linespeed.sh hit.
  - resolve ~. Script A calls it after sudo -i, so paths are derived
    from $0 rather than $HOME.

Output is one line per port when stdout is not a tty, so it does not
flood the Tera Term log, and it ends with "### DSC_SCAN_DONE rc=<n>" for
a TTL wait to key on.

bcm_dsc_parse.sh is the host-side half: raw log -> <prefix>_lane.csv
(TXEQ / RXFFE / DFE / EYE / SNR per lane) and <prefix>_pm.csv (per
pm_id). POSIX sh + awk, no Python. Lane rows are read by the order of
their bracket groups rather than by fixed columns, so the SDK re-spacing
its output does not break parsing; a row whose group count is not 9 is
reported as UNPARSED on stderr instead of being parsed wrongly.

A full scan is about 10 minutes.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014RetWKFZFG1ZHcitQAyhwM
2026-09-06 23:22:50 +08:00
etwenandClaude Opus 5 eacb218da8 feat(ttl): Run Script 4's CPU stress as the same systemd unit
The thermal / safety macro started mlucas-avx2 with '&', exactly as
Script B used to, so it carried the same failure: the load ended quietly
when the console went away - in the one test where a long, steady full
load is the entire point of the run.

It now uses the same mlucas-amm transient unit, and 'systemctl is-active
mlucas-amm' joins 'bgctl list' and 'jobs' in the monitor loop.

Script 4 still has no teardown section, so the matching stop stays
manual, and it is now two commands rather than one:

    blanton_tr518.sh stop
    systemctl stop mlucas-amm

Closing Tera Term no longer stops the CPU load, and 'kill $(jobs -p)'
never could reach a unit. Script A's V1.1.8 history, CLAUDE.md,
ARCHITECTURE.md and the release note all say so now; the version stays
V1.1.8.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014RetWKFZFG1ZHcitQAyhwM
2026-09-06 17:31:33 +08:00
etwenandClaude Opus 5 4648f936c7 docs: Update CLAUDE / ARCHITECTURE for V1.1.8 and add the release note
CLAUDE.md: status to V1.1.8 / 2026-09-06; the soak loop now prints
'systemctl is-active mlucas-amm'; hammer/ added to the folder list with
why it is not in git; the --runtime gotcha notes the new 3600 default;
three new gotchas - kill_all_process.ttl cannot reach a systemd unit, a
missing config.ttl variable aborts the macro rather than reading as 0,
and the log timestamp FORMAT lives in TERATERM.INI, not in the script.

ARCHITECTURE.md: hammer/ and the config.ttl knobs in the project tree;
Script A ref V1.1.7 -> V1.1.8; Script B and Script C rows rewritten for
the systemd unit; constraint 1 notes that mlucas-amm now outlives the
session; two new constraints (17 - whoever moves a stress job to systemd
owns the matching stop, and Script 4 still uses '&'; 18 - config.ttl
completeness and the TERATERM.INI timestamp format); the git tag
checkbox to V1.1.8; and three known issues - the bundle no longer ships
hammer/, mlucas-amm's '~' depends on systemd's environment, and the
three stress durations are deliberately different lengths.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014RetWKFZFG1ZHcitQAyhwM
2026-09-06 17:22:00 +08:00
etwenandClaude Opus 5 9cdd651d79 feat(ttl): Run the CPU stress as a systemd unit, and add two config knobs
mlucas-avx2 was backgrounded with '&' in the login shell, so it belonged
to that one terminal. Close Tera Term, drop the console, or reconnect on
a different session and the load was gone - and 'jobs' from the new
session showed nothing to say so. A multi-day soak could spend most of
its length with an idle CPU while the thermal numbers looked fine.

Script B now starts it as a transient unit:

  systemd-run --unit=mlucas-amm --property=Type=exec \
    --property=Restart=always --property=RestartSec=2 ...

The log is truncated once with '>' before the unit starts and appended
with '>>' inside it, so a restart adds to the run instead of erasing it.
'systemctl is-active mlucas-amm' now sits beside 'jobs', both in the
one-shot check and in every pass of the monitor loop. The old '&' line is
kept commented out above the new one to fall back to.

Script C has the matching stop. utils/kill_all_process.ttl is only
"kill $(jobs -p)" and a systemd unit is not a shell job, so without this
the load would have run through the post-test snapshot and into the next
test - every temperature and power reading taken at full load, with
nothing in 'show interfaces status' to reveal it. mlucas_amm_log is
copied to /host/hw-eval/jobs/ with the other stress logs.

Two values move into config.ttl:

  EN_timestamp      feeds logopen's 5th argument in Script A, so the
                    per-line timestamp is a knob rather than a literal 1
  BMC_USB_RUNTIME   feeds Script B's ping unit; it was hard-coded to
                    -w 14400 (4 h), which no longer matched the soak
                    lengths the SSD and USB knobs were being set to

SSD_RUNTIME and USB_RUNTIME also go 600 -> 3600, so the shipped default
is a one hour stress rather than the ten minutes V1.1.7 went out with.
--runtime is still the job's overall limit; COUNT does not multiply it.

Script A's Version History carries the V1.1.8 entries for all of this.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014RetWKFZFG1ZHcitQAyhwM
2026-09-06 17:21:52 +08:00
etwenandClaude Opus 5 4f2f9ed090 chore(publish): Keep the mlucas binaries out of git and the bundle
src/Script_ABC_Blanton/hammer/ is ~99 MB of unstripped mlucas ELF
binaries (avx512 / avx2 / avx / sse2 / generic-c). They come with the DUT
image, so this repo has no reason to carry them - and a binary tree that
size is permanent once committed: every clone pays for it forever.

publish.sh excluded them too, because rsync copies whatever happens to be
sitting in src/. Without the exclude the delivery bundle was ~100 MB from
a machine that had the binaries and ~200 KB from a fresh clone.

While there, usage() read a fixed line range of the header, so adding a
Version History entry pushed code into the usage text. It now reads up to
the first line of code.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014RetWKFZFG1ZHcitQAyhwM
2026-09-06 17:21:39 +08:00
etwenandClaude Opus 5 1a06367ade docs: Record V1.1.7 in Script A's history, and update CLAUDE / ARCHITECTURE
Script A's Version History gains the reboot-cycle macro, the Script B timeout
fix, the tmp/ rule and the stress knobs.

CLAUDE.md: current status to V1.1.7, a Script 5 paragraph, tmp/ in the folder
list, and two gotchas rewritten - the timeout one now covers both restore
positions, and --runtime is described as the job's overall limit rather than
"a 24 hour ceiling". Dropped the stale "TR518 not scripted yet" line.

ARCHITECTURE.md: Script 5 in the tree and in Key Features, tmp/ in the tree,
constraint 14 extended with "copy the :label along with the goto", and two
known issues added for the parts not yet run on hardware.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014RetWKFZFG1ZHcitQAyhwM
2026-09-04 22:44:21 +08:00
etwenandClaude Opus 5 1fbdcc23d6 feat(reboot): Add a standalone reboot-cycle macro
5_Blanton_Script_Reboot_Cycle.ttl loops: login -> sudo -i -> date -s -> fan
speed -> wait_init -> Check Pt1..Pt13 -> show uptime -> reboot -> wait for the
next boot. The cycle number is printed in the banner of every round.

Like Script 4 it is standalone: it does not chain to A -> B -> C and does not
use hw-test-session. Every cycle is a fresh boot, so there is nothing to carry
over and nothing to tear down.

The cdc_ncm probe was copied out of Script B without its :skip_ping label, so
'goto skip_ping' had no target. Tera Term does not check labels at load time -
it raises the error only when it actually jumps, i.e. only when the NCM
interface is missing, which is exactly the run where something is already
wrong. The label is now there, and timeout is restored BEFORE the branch so
one line covers both paths: the ping block waits on a 'sleep 10', already two
thirds of the 15 s cap on a loaded DUT.

Dmesg_i2c and PCIE Error Counters both announced themselves as Check Pt12;
the second is now Pt13.

Not verified on hardware yet. Two things to confirm on the bench: that
wait "Booting in blind mode" really appears in this build's boot output (it
has no timeout guard, so a changed string waits forever), and that re-running
bmc-first-enroll every cycle is safe.

Also ignore tmp/ - scripts not yet run on a DUT stage there, so an unverified
script cannot reach the publish bundle where the tester cannot tell it apart
from the rest.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014RetWKFZFG1ZHcitQAyhwM
2026-09-04 22:44:21 +08:00
etwenandClaude Opus 5 0d2faef565 feat(scriptb): Move the stress durations into config.ttl, and restore the timeout sooner
SSD_RUNTIME / SSD_COUNT and USB_RUNTIME / USB_COUNT replace the values that
were hard-coded in Script B, so a site changes them in one place. COUNT is
passed straight through as --passes.

--runtime is the job's OVERALL limit, not a per-pass one: qfx5252-stress-*
stops after RUNTIME seconds whatever --passes says. RUNTIME 600 is a ten
minute stress, not 600 x COUNT. A 24 hour soak needs RUNTIME 86400.

Also restore timeout = 0 on the cdc_ncm success path. It was restored only at
:skip_ping, which the success path reaches several waits later - until then
every wait gave up after 15 s instead of blocking, and a wait that returns
without eating the prompt puts the macro a beat ahead of the DUT.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014RetWKFZFG1ZHcitQAyhwM
2026-09-04 22:44:05 +08:00
etwenandClaude Opus 5 a9c56ee1d4 feat(multiphase): Add a way back from a margin without a power cycle
blanton_multiphase_margin.sh gains 'normal', which returns all 38 rails
to their nominal set point from tools/Multiphase_Normal.txt. Same rails,
same per-rail reporting, same -u 0|1|all as the margin profiles.

Until now the tool could apply high3/low3/comboA/comboB and commit with
save, but had no way to undo. That left a power cycle as the only exit -
and worse, a save run while still margined would have written the offsets
into NVM, which a power cycle does not undo either.

Emitted commands were diffed against the source file: argv identical.

The nominal labels in the source carry extra text ("0.900V (nominal)",
"0.8V(nominal) , 0.8591V with load line"); the per-rail line prints just
the voltage so the column matches the other profiles. The load-line note
is kept as a comment above the data block, because reading 0.859 V back
from TH6_CORE after 'normal' looks like a failed write and is not one.

Script A -> V1.1.7.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014RetWKFZFG1ZHcitQAyhwM
2026-09-04 09:23:25 +08:00
etwenandClaude Opus 5 78a8f641c9 fix(scriptc): Capture the BMC USB service log to a file, not the console
journalctl now runs with -o short-iso into log/bmc_usb_net.log and is
copied into the job directory with the other monitor logs. rm -f first so
the file covers this run only, and the ISO timestamps line up with
mgmt_ping.log and nfc_poll.log for cross-referencing.

The cost, recorded rather than glossed over: it is no longer echoed to
the console, so the USB copy is the only copy. That cp return value is
not checked - the same shape as the nfc_polling.log filename bug, which
failed silently and was only noticed back at the desk with a job archive
missing a file.

Folded into V1.1.6 rather than bumping: the tag has not moved on and this
is the same delivery.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014RetWKFZFG1ZHcitQAyhwM
2026-09-02 21:44:06 +08:00
etwenandClaude Opus 5 25e1ce0068 fix(pdb): Read the bricks on the pages the datasheet actually specifies
Every PDB reading came back NA, and the cause was a base error. The four
ADPM12200 bricks put each measurement on its own PMBus PAGE, written
before the read. The bring-up spreadsheet listed those page numbers in
decimal but with an 0x prefix:

    Vin  PAGE 9  -> it said 0x00   (0x09)
    Iin  PAGE 10 -> it said 0x10   (0x0A)
    Vout PAGE 2  -> it said 0x02    correct by luck
    Iout PAGE 14 -> it said 0x14   (0x0E)
    Temp PAGE 18 -> it said 0x18   (0x12)

Only Vout worked, because 2 reads the same in either base. Hence Iin and
Iout answering 0xFFFF, Temp answering 0x0000, and a Vin scale factor
having to be invented to make 50 V appear out of a page-0 register.

pwr_brick.sh reads all five bricks with the right pages and the
datasheet's DIRECT equation, X = (1/m)(Y x 10^-R - b): voltage Y x 8 mV,
current Y x 0.04 A, temperature Y x 0.01 C. Cross-checked rather than
assumed - READ_VOUT 0x05D4 decodes to 11936 mV, exactly what
'show platform voltage' reports for that rail through a separate sensor
path. The datasheet is committed alongside so the numbers are checkable.

Left flagged: Table 3 does not list READ_VIN or READ_IIN. They borrow the
voltage and current coefficients here, which is consistent with a ~50 V
input but is not something the datasheet states.

Each value is re-read until it passes three checks: not 0xFFFF, not
0x0000, and inside a plausibility window. The window is the one that
matters - this bus corrupts the HIGH BYTE only, which turns 11.98 V into
32.00 V. Positive, plausible in magnitude, and invisible to any all-ones
filter. 0x0000 is rejected for the mirror-image reason: on the
temperature register it decodes to a believable 0 C.

Adds comboA/comboB margin profiles per board. comboB is comboA with every
direction flipped, so the pair covers each rail high and low while its
neighbours sit the other way. NC channels stay nominal in both - there is
nothing to margin on an unused rail.

Script C re-enables the BMC USB journalctl dump, which had been commented
out, so that service log now reaches the master log.

Script A -> V1.1.6.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014RetWKFZFG1ZHcitQAyhwM
2026-09-02 16:35:45 +08:00
etwenandClaude Opus 5 215fed6e95 fix(stress): Keep the SSD and USB jobs alive for the whole soak
qfx5252-stress-usb was started with --runtime 60. It finished a minute
into an overnight run and the USB path sat idle for the rest of the
night - nothing failed, nothing said so, and the log looked complete.
SSD had the same shape at --runtime 3600. Both are now 86400, and the
BMC DDR memtester drops its loop count so it runs until stopped.

86400 is 24h, not forever. Past that SSD and USB die quietly and the
only clue is the shorter bgctl list Script B already prints each round.
Said so in the version history, the release notes and ARCHITECTURE.

Adds blanton_multiphase_margin.sh: the multiphase controllers on both
switch boards over the native i2c buses (SWB0 on i2c-13/15, SWB1 on
-14/-16), 19 rails each. high3/low3/comboA/comboB set voltages and print
one line per rail; save commits them and prints Multiphase Save All,
because that list has no per-rail mapping to report against.

Two hazards it carries: save is STORE_USER_ALL and permanent, and these
are NOT the LTC2980s margin.sh drives - the two tools reach the same
rails from opposite sides with no interlock between them.

The emitted commands were diffed against tools/Multiphase_*.txt: argv
identical for all five. The rail-to-netname mapping was cross-checked
against the bus numbers rather than trusted by line position - blocks
1..19 are all bus 13/15 and 20..38 all 14/16, matching the SWB0/SWB1
split of Multiphase_Netname.

blanton_traffic_linespeed v0.7.0 appends PatternRandom=yes to every tx
including ce0, and the defaults become tx 200 length=324. A fixed
pattern can sit on a benign bit sequence for a whole run; a changing one
is what exposes a weak lane. -r no forces fixed, -r "" omits the
argument for an SDK that will not take it. Bytes per burst went 51200 ->
64800, so absolute counter totals do not carry across this build - the
pair cross-check that decides PASS/FAIL does.

Script A -> V1.1.5.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014RetWKFZFG1ZHcitQAyhwM
2026-09-01 11:04:45 +08:00
etwenandClaude Opus 5 db44f72352 feat(thermal): Add a standalone thermal/safety run, and move margin out of the soak loop
4_Blanton_Script_thermal_safety.ttl brings the DUT up the way Script A
does, then loads it - mlucas-avx2 -cpu 0:15 in the background plus
blanton_tr518.sh start - and samples platform data and both switch
boards' rail power every minute. Power per rail under sustained full
load, over hours, is the whole point of it.

It is standalone: nothing starts it, it starts nothing, and it must not
share a DUT with Script B because both take over the cd ports.

It also has no teardown. When you interrupt it the unit is still in
port cd lb=mac / l2 learn off / test mode nr=yes and mlucas is still
running, and show interfaces status does not reveal any of that. Called
out in the version history, the release notes, CLAUDE.md gotchas and the
ARCHITECTURE future-work list, because whoever uses the box next will not
find out on their own.

Script B's per-round loop drops the margin scan. The loop is meant to be
a quick minute-by-minute sample and margin_status_all.sh walks nine
LTC2980s over I2C, which dominated the round. Script C takes it instead,
once, before show uptime. The trade-off is real: margin drift DURING the
soak is no longer visible, only a start and an end reading. Documented
rather than glossed over, with a suggestion (scan every N rounds) if it
needs to come back.

Script C also sends exit and waits for "Script done" before
hw-test-session finish, so finish runs in the login shell rather than
inside the session it is closing.

Adds docs/Blanton_Test_Flow.drawio: all four scripts side by side, with
the config flags that change each step marked, Script B's one real goto
drawn, and the A->B->C handoffs shown as the manual steps they are.

The new script arrived LF-only while every other .ttl is CRLF and
.gitattributes marks *.ttl as -text, so what is committed is exactly what
Tera Term reads. Converted.

Script A -> V1.1.4.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014RetWKFZFG1ZHcitQAyhwM
2026-08-31 22:19:38 +08:00
etwenandClaude Opus 5 9cc41f6fbd fix(margin): Reference VNOM to what the rails run at, and split profiles per CONN
86 of the 144 margin channels moved up +0.8% .. +2.5% to the measured
median for this platform (3.3 -> 3.38, 0.9 -> 0.915, 0.8 -> 0.82, ...).

That is not a display change. VNOM is the denominator of margin_status'
deviation %, and it is also the basis margin_set derives high/low/OV/UV
from - so both the number you read and the voltage you apply move with
it. A rail steady at 0.756 V used to read +0.80% against a nominal 0.75
and now reads 0.00%. Margin logs from before and after cannot be
compared: the reference moved, the hardware did not.

comboA/comboB are replaced by combo_SWB_CONN13..16_{high,low}. The
per-channel percentages are positional, so they follow the rails of one
specific board - applying a CONN13 profile to a CONN16 margins the wrong
rails and nothing detects it. SWB0 and SWB1 share a profile per CONN
because their rails are identical.

Fixes two things the deletion broke:
  - margin_apply_profile_all.sh still named comboA for all nine boards,
    which would now stop at "Profile not found" nine times over. It names
    the matching per-CONN profile instead, with CB on the generic
    combo_high3, and a note that the low pass is _high -> _low.
  - docs/LTC2980_channel_map.csv is generated from settings/*.conf, so
    all 86 changed rails were stale in it. Regenerated.

The eight new profiles also still carried comboA's header comment
("alternating high/low"), which describes neither what they contain nor
what they are for.

Script A -> V1.1.3.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014RetWKFZFG1ZHcitQAyhwM
2026-08-30 22:13:43 +08:00
68 changed files with 7050 additions and 405 deletions
+6
View File
@@ -28,3 +28,9 @@ publish/*
# 客戶板 schematic 原始檔(機密,勿入 repo) # 客戶板 schematic 原始檔(機密,勿入 repo)
*.DSN *.DSN
*.dsn *.dsn
# 尚未上機驗證的腳本暫存區(不入 repo,測過再搬進 src/)
tmp/
# mlucas 的 ELF binary(~99 MB),DUT image 已內含,不入 repo
src/Script_ABC_Blanton/hammer/
+168 -23
View File
@@ -112,7 +112,7 @@ Blanton_TTL_Script/
│ │
├── CLAUDE.md # 專案記憶 & 給 Claude 的指令 ├── CLAUDE.md # 專案記憶 & 給 Claude 的指令
├── ARCHITECTURE.md # 本架構文件 ├── ARCHITECTURE.md # 本架構文件
├── .gitignore # secret/ + For_AI/ + logs + publish 產出 ├── .gitignore # secret/ + For_AI/ + tmp/ + hammer/ + logs + publish 產出
├── .gitattributes # 換行符政策:.sh/.conf 釘 LF、.ttl 保持 CRLF ├── .gitattributes # 換行符政策:.sh/.conf 釘 LF、.ttl 保持 CRLF
│ │
├── docs/ # 規格與狀態文件(客戶提供 / 專案產出) ├── docs/ # 規格與狀態文件(客戶提供 / 專案產出)
@@ -120,6 +120,8 @@ Blanton_TTL_Script/
│ ├── Blantons_FPGA_Registers_draft.docx # 同上,客戶原始 docx │ ├── Blantons_FPGA_Registers_draft.docx # 同上,客戶原始 docx
│ ├── Blantons_FPGA_Registers_Map_draft.xlsx │ ├── Blantons_FPGA_Registers_Map_draft.xlsx
│ ├── Blantons_PCIe_AER_and_DDR_EDAC_checks.pdf # AER / EDAC 檢查點依據 │ ├── Blantons_PCIe_AER_and_DDR_EDAC_checks.pdf # AER / EDAC 檢查點依據
│ ├── ADPM12200CMLZxx_DS_Datasheet_*.pdf # PDB brick 手冊(PAGE 與 DIRECT 係數的來源)
│ ├── Blanton_Test_Flow.drawio # A/B/C + 熱安規四支的測試流程圖(draw.io)
│ ├── LTC2980_channel_map.csv # 9 個 settings/*.conf 合併:Board,CONN,Ch,NetName,Vnom(144 列) │ ├── LTC2980_channel_map.csv # 9 個 settings/*.conf 合併:Board,CONN,Ch,NetName,Vnom(144 列)
│ ├── TTL_Script_Blanton_Status_20260814.xlsx │ ├── TTL_Script_Blanton_Status_20260814.xlsx
│ └── TTL_Script_Blanton_Status_20260817.xlsx # ⭐ 最新:三支腳本逐項 Status(OK / On-Going + Owner) │ └── TTL_Script_Blanton_Status_20260817.xlsx # ⭐ 最新:三支腳本逐項 Status(OK / On-Going + Owner)
@@ -134,6 +136,9 @@ Blanton_TTL_Script/
│ ├── 100G_PRBS.txt # 100G PRBS 原始指令(port_prbs_monitor.sh 的來源) │ ├── 100G_PRBS.txt # 100G PRBS 原始指令(port_prbs_monitor.sh 的來源)
│ ├── TR518.txt # 內建封包測試 tr 518 → blanton_tr518.sh │ ├── TR518.txt # 內建封包測試 tr 518 → blanton_tr518.sh
│ ├── BER_Test.txt # 全機 PRBS BER 指令 → blanton_ber.sh │ ├── BER_Test.txt # 全機 PRBS BER 指令 → blanton_ber.sh
│ ├── 100G_dsc_cycle.txt # 100G tuning + link 循環 + DSC → bcm_100g_dsc_cycle.sh
│ ├── Multiphase_{high3,low3,comboA,comboB,Save}.txt # → blanton_multiphase_margin.sh
│ ├── Multiphase_Netname # 38 條軌的 net 名稱(區塊順序對應)
│ ├── 100G_Traffic.txt # ce0 VLAN 138 打流 → blanton_traffic_linespeed.sh │ ├── 100G_Traffic.txt # ce0 VLAN 138 打流 → blanton_traffic_linespeed.sh
│ ├── fan_ctrl.txt # MAX31790 unbind/bind + fan-speed-control.sh 30 │ ├── fan_ctrl.txt # MAX31790 unbind/bind + fan-speed-control.sh 30
│ └── gen_channel_map.sh # settings/*.conf → docs/LTC2980_channel_map.csv(需 gawk) │ └── gen_channel_map.sh # settings/*.conf → docs/LTC2980_channel_map.csv(需 gawk)
@@ -149,10 +154,18 @@ Blanton_TTL_Script/
│ ├── publish.sh # ✅ committed — 打包工具(版號讀 Script A 檔頭) │ ├── publish.sh # ✅ committed — 打包工具(版號讀 Script A 檔頭)
│ └── Script_ABC_Blanton_<Ver>/ # 🚫 產出,gitignored(-z 另出同名 .zip) │ └── Script_ABC_Blanton_<Ver>/ # 🚫 產出,gitignored(-z 另出同名 .zip)
│ │
├── tmp/ # 🚫 gitignored — 尚未上機驗證的腳本暫存區
│ └── blanton_reboottest.sh # 5_..._Reboot_Cycle.ttl 的 bash 版,測過再搬進 Blanton_Script/
│
└── src/ └── src/
└── Script_ABC_Blanton/ # ← Tera Term 的工作目錄(整包給測試員) └── Script_ABC_Blanton/ # ← Tera Term 的工作目錄(整包給測試員)
│ │
├── config.ttl # 全域設定:testcase 名、EN_Margin / EN_log、三個 prompt 字串 ├── 4_Blanton_Script_thermal_safety.ttl # 熱 / 安規:獨立跑,不接 A→B→C
├── 5_Blanton_Script_Reboot_Cycle.ttl # 重開機循環:獨立跑,while 1 無止境(未上機驗證)
├── config.ttl # 全域設定:testcase 名、EN_Margin / EN_TX_FIR / EN_log / EN_timestamp、
│ # 風扇與 SWB 宣告、SSD/USB/BMC_USB 壓力秒數、三個 prompt 字串
├── hammer/ # 🚫 gitignored — mlucas ELF binary(~99 MB),DUT image 自帶,
│ # publish.sh 也排除;Script B / Script 4 只負責 chmod +x 後執行
├── 1_Blanton_Script_A.ttl # Pre-test:登入 → 對時 → source 工具 → 清 AER → 抓基線 ├── 1_Blanton_Script_A.ttl # Pre-test:登入 → 對時 → source 工具 → 清 AER → 抓基線
├── 2_Blanton_Script_B.ttl # Stress:開壓力程序 → while 1 每輪抓 fan/temp/margin ├── 2_Blanton_Script_B.ttl # Stress:開壓力程序 → while 1 每輪抓 fan/temp/margin
├── 3_Blanton_Script_C.ttl # Post-test:kill → 再抓一次 → 比對 stress log ├── 3_Blanton_Script_C.ttl # Post-test:kill → 再抓一次 → 比對 stress log
@@ -187,7 +200,15 @@ Blanton_TTL_Script/
├── mgmt_ping_monitor.sh # 10G/1G 管理網路 ping 監控(iproute2) ├── mgmt_ping_monitor.sh # 10G/1G 管理網路 ping 監控(iproute2)
│ # eth0→TARGET_10G、eth1→TARGET_1G,兩張卡同時持續 ping │ # eth0→TARGET_10G、eth1→TARGET_1G,兩張卡同時持續 ping
├── port_prbs_monitor.sh # 100G uplink PRBS 測試(bcmcmd phy diag) ├── port_prbs_monitor.sh # 100G uplink PRBS 測試(bcmcmd phy diag)
│ # ⚠️ V1.1.9 起 A/B/C 內註解掉的呼叫已整段刪除,只剩手動執行
├── blanton_ber.sh # 全機 SerDes BER 掃描(phydiag prbs / prbsstat) ├── blanton_ber.sh # 全機 SerDes BER 掃描(phydiag prbs / prbsstat)
│ # V1.2.2 起含 port 268(100G ce0),summary 每 unit 分 200G/100G/TOTAL
├── bcm_100g_dsc_cycle.sh # 100G link down/up 循環 + 每輪 DSC 與 retimer TX/RX 讀回(未驗證)
├── bcm_dsc_scan.sh # 全機 SerDes DSC dump(phydiag <port> dsc,~445 port × 2 unit)
│ # 由 EN_TX_FIR 控制,A 與 C 各掃一次;單次約 10 分鐘
├── bcm_dsc_parse.sh # DSC raw log → <prefix>_lane.csv / _pm.csv(純 sh + awk)
├── blanton_multiphase_margin.sh # 多相 VRM margin(原生 i2c,38 條軌)
├── pwr_brick.sh # PDB / CPB power brick 讀值(VI2C ch4)
├── nfc_polling.sh # NFC tag 背景輪詢 + PASS/FAIL 統計 ├── nfc_polling.sh # NFC tag 背景輪詢 + PASS/FAIL 統計
├── blantons_nfc_validate.py # NFC/NCI 驗證工具(廠商提供,未修改) ├── blantons_nfc_validate.py # NFC/NCI 驗證工具(廠商提供,未修改)
├── blanton_tr518.sh # TR518 封包測試,量功耗前的負載來源 ├── blanton_tr518.sh # TR518 封包測試,量功耗前的負載來源
@@ -196,13 +217,16 @@ Blanton_TTL_Script/
│ # ⚠️ 已納入交付,但 A/B/C 的呼叫仍註解掉(bring-up 中) │ # ⚠️ 已納入交付,但 A/B/C 的呼叫仍註解掉(bring-up 中)
├── 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 # ⚠️ 已停用:B/C 內呼叫處已註解,DDR 壓力改走 bgctl + bmc-manager ├── bmc_monitor_ddr.sh # ⚠️ 已停用:V1.1.9 起 B/C 內的註解區塊已刪除,DDR 壓力走 bgctl + bmc-manager
│ # ↑ 三支都要 chmod +x 才能跑(見 Key Constraints) │ # ↑ 三支都要 chmod +x 才能跑(見 Key Constraints)
└── LTC2980_Margin_Script/ # 電壓 margin 子專案(另有獨立 repo) └── LTC2980_Margin_Script/ # 電壓 margin 子專案(另有獨立 repo)
├── margin.sh # margin_init/status/set/apply_profile/save ├── margin.sh # margin_init/status/set/apply_profile/save
# # v2.7.0:margin_save all / margin_save blanton # # v2.7.0:margin_save all / margin_save blanton
├── settings/*.conf # 一個 .conf = 一顆 LTC2980(CB + SWB0/1 × CONN13~16) ├── settings/*.conf # 一個 .conf = 一顆 LTC2980(CB + SWB0/1 × CONN13~16)
├── profiles/*.conf # 16-ch 批次組合(comboA/B、high3/5、low3/5、normal、off) ├── profiles/*.conf # 16-ch 批次組合。SWB 為 per-CONN:
# # combo_SWB_CONN13~16_{high,low}(百分比對應該片的軌)
# # comboA/comboB_{CB,SWB_CONN13~16}(互補棋盤配對)
# # 通用:high3/5、low3/5、normal、all_off
├── script/*_all.sh # 跨 9 顆 LTC2980 的批次 status / apply / save ├── script/*_all.sh # 跨 9 顆 LTC2980 的批次 status / apply / save
├── Ref/margin_command_trace.md # 指令追蹤參考(SWB 章節已標過期,見文件內警告) ├── Ref/margin_command_trace.md # 指令追蹤參考(SWB 章節已標過期,見文件內警告)
└── logs/ # margin 操作 log └── logs/ # margin 操作 log
@@ -243,11 +267,20 @@ Log 檔名規則:`<mdir>\Logs\<project_name>_<strTestcase>_<YYYYmmdd-HHMMSS>.l
| `CB_I2C_CH` | int | `TRANSPORT="swb"` 時的 FPGA I2C 通道(6/7/8/9) | | `CB_I2C_CH` | int | `TRANSPORT="swb"` 時的 FPGA I2C 通道(6/7/8/9) |
| `CHIPS[]` | string[2] | `"bus:addr"`,index 0 → CH0~7、index 1 → CH8~15 | | `CHIPS[]` | string[2] | `"bus:addr"`,index 0 → CH0~7、index 1 → CH8~15 |
| `CHIP_PRE_CMD[]` / `CHIP_POST_CMD[]` | string[1] | mux 切換等前後置指令,`;` 分隔多筆 | | `CHIP_PRE_CMD[]` / `CHIP_POST_CMD[]` | string[1] | mux 切換等前後置指令,`;` 分隔多筆 |
| `CH<n>_VNOM` | string | 標稱電壓(`"-"` = 未使用 / NC) | | `CH<n>_VNOM` | string | 這條軌的**基準電壓**(`"-"` = 未使用 / NC) |
| `CH<n>_NET` | string | 電路 net name(對照 schematic) | | `CH<n>_NET` | string | 電路 net name(對照 schematic) |
Channel 定址:`ch / 8` → `CHIPS[]` index,`ch % 8` → LTC2977 PMBus PAGE(0x00~0x07)。 Channel 定址:`ch / 8` → `CHIPS[]` index,`ch % 8` → LTC2977 PMBus PAGE(0x00~0x07)。
**`VNOM` 自 2026-08-30 起是「Blanton 實測中位數」,不是規格標稱值。** 144 條軌裡有 86 條
被改上去 +0.8% ~ +2.5%(例:`PVDD3_3V_SYNTH_LDO_*` 3.3 → 3.38、`P0V9_AVDD_*` 0.9 → 0.915、
`PVDD0_8V_T3` 0.8 → 0.82)。這件事影響兩處,**不是只有顯示**:
- `margin_status` 的偏差 % 是對 `VNOM` 算的 —— 以前一條穩定在 0.756 V 的軌顯示 `+0.80%`,
現在顯示 `0.00%`。**舊 log 的偏差 % 不能跟新 log 直接比。**
- `margin_set` 的 high / low / OV / UV **全部由 `VNOM` 推算**(`VNOM × (1 ± change%)`),
所以整個 margin 視窗跟著平移。同樣下 `+3%`,實際打到的絕對電壓比以前高。
**SWB 通道與位址對應(2026-08-19 上機驗證,`ababb2c`):** **SWB 通道與位址對應(2026-08-19 上機驗證,`ababb2c`):**
| FPGA I2C 通道 | 板 / 接頭 | LTC2977 位址(lo / hi) | | FPGA I2C 通道 | 板 / 接頭 | LTC2977 位址(lo / hi) |
@@ -344,23 +377,29 @@ PROFILE_CHANNELS=( "0:high:8" "1:low:8" ... ) # "channel:operation:change_perc
| 模組 | 進入點 | 功能 | | 模組 | 進入點 | 功能 |
|------|--------|------| |------|--------|------|
| **Script A(Pre-test)** | `1_Blanton_Script_A.ttl` V1.1.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 設定與狀態 → **一輪流量基線** → `show uptime` | | **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 B(Stress)** | `2_Blanton_Script_B.ttl` | `mlucas-avx2 -cpu 0:15` + `bgctl run` 的 `memtester` / SSD / USB 壓力 + BMC DDR(`bmc-manager run memtester`)→ BMC USB net test(探測 cdc_ncm 介面,`systemd-run` 掛 4 小時 ping)→ 啟動 mgmt ping 監控 → **啟動 NFC 輪詢** → `jobs` / `bgctl list` → traffic(依 `SWB_UNIT`)→ `while 1` 每輪完整 PMON + margin | | **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)` + `bgctl stop --all` / `reset` + 停 BMC USB unit、mgmt ping 與 **NFC 輪詢** → PMON + dmesg → 7 組 AER + `ras-mc-ctl` → BMC USB `journalctl` → `ip -s link show eth0/eth1` → `cat` mlucas log → **NFC `report`** → traffic `stop` + `report` → **BER 掃描**(依 `SWB_UNIT`)→ NVMe 健康 → `show reboot-cause` / `uptime` → **job log 複製到 USB(帶時戳)** → `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` |
| **SWB loopback 流量** | `blanton_traffic_linespeed <sub> [-u 0\|1\|all]` | `init`(VLAN 30..137,成對 `cdN`/`cdN+32`)→ `clear` → `start`(`tx 100 length=512`)→ `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 | | **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 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 |
| **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 窗口 |
| **CB I2C / PMBus** | `cb_i2c_init/scan/read/write`、`cb_pmbus_read/write/linear16` | FPGA F3 OpenCores master,**讀用 Repeated START**(SMBus/PMBus 裝置必需) | | **CB I2C / PMBus** | `cb_i2c_init/scan/read/write`、`cb_pmbus_read/write/linear16` | FPGA F3 OpenCores master,**讀用 Repeated START**(SMBus/PMBus 裝置必需) |
| **ICB / PDB 存取** | `vi2c_init/scan/read/write`、`vi2c_scan_all` | CB F3 VI2C proxy,~3.3 ms/reg,取代 VSPI 的 ~18 ms/reg(後者會踩 SMBus 25–35 ms timeout) | | **ICB / PDB 存取** | `vi2c_init/scan/read/write`、`vi2c_scan_all` | CB F3 VI2C proxy,~3.3 ms/reg,取代 VSPI 的 ~18 ms/reg(後者會踩 SMBus 25–35 ms timeout) |
| **溫度** | `temp_cb` / `temp_icb` / `temp_all` | TMP75(12-bit 左靠齊 ×0.0625)、TMP432(含 RANGE bit 的 −64 偏移、remote1/2) | | **溫度** | `temp_cb` / `temp_icb` / `temp_all` | TMP75(12-bit 左靠齊 ×0.0625)、TMP432(含 RANGE bit 的 −64 偏移、remote1/2) |
| **電源資料** | `pwr_data` / `pwr_data_pdb` / `pwr_pdb_id` | SWB VRM 全軌 Vin/Vout/Iout/Temp 對齊表;MP29816 解析度**執行期從 `MFR_VOUT_SCALE_LOOP` 讀**,不寫死 | | **電源資料** | `pwr_data` / `pwr_data_pdb` / `pwr_pdb_id` | SWB VRM 全軌 Vin/Vout/Iout/Temp 對齊表;MP29816 解析度**執行期從 `MFR_VOUT_SCALE_LOOP` 讀**,不寫死 |
| **電壓 Margin** | `margin_init/status/set/apply_profile/save` + `*_all.sh` | 9 顆 LTC2980(CB CONN13、SWB0/1 CONN13~16)批次 high/low margin 與狀態掃描。v2.6.0 起 SWB 路徑真正接上共用 cb_i2c 後端,並有 `margin_swb_info/probe/scan/reset/sem` 除錯包裝 | | **電壓 Margin** | `margin_init/status/set/apply_profile/save` + `*_all.sh` | 9 顆 LTC2980(CB CONN13、SWB0/1 CONN13~16)批次 high/low margin 與狀態掃描。`VNOM` 為 Blanton 實測中位數(2026-08-30);SWB 的 profile 是 per-CONN,套錯 CONN 會 margin 到錯的軌且不報錯。v2.6.0 起 SWB 路徑真正接上共用 cb_i2c 後端,並有 `margin_swb_info/probe/scan/reset/sem` 除錯包裝 |
| **Multiphase VRM margin** | `blanton_multiphase_margin.sh {high3\|low3\|comboA\|comboB\|save} [-u 0\|1\|all]` | 兩片 SWB 的多相控制器(**不是** `margin.sh` 管的 LTC2980),走原生 i2c bus:SWB0 = `/dev/i2c-13`+`-15`、SWB1 = `-14`+`-16`。每片 19 條軌、共 38 條,逐條印 `SWB0_0V9_ANLG0 - 0.930V Configure Done`。`save` 沒有 per-rail 對應,只印 `Multiphase Save All`。⚠️ `save` 是 `STORE_USER_ALL`(0x15,TH6 core 用 0x17)**永久寫 NVM**;⚠️ 與 `margin.sh` 從兩側摸同一批軌,**不可同時用** |
| **Margin 寫 NVM** | `margin_save` / `margin_save all` / `margin_save blanton` | ⚠️ 永久寫入。`0x15` 送 PMBus **send-byte**(不帶 data byte)。`all` = 依 `settings/` 走 9 顆、跑完還原原本載入的板子;`blanton` = 本平台捷徑,18 顆全走原生 i2c bus(`MARGIN_BLANTON_STORE` 表),不需 `margin_init`。每筆之間 `MARGIN_STORE_SETTLE`(0.5s),工具**不 poll busy bit** | | **Margin 寫 NVM** | `margin_save` / `margin_save all` / `margin_save blanton` | ⚠️ 永久寫入。`0x15` 送 PMBus **send-byte**(不帶 data byte)。`all` = 依 `settings/` 走 9 顆、跑完還原原本載入的板子;`blanton` = 本平台捷徑,18 顆全走原生 i2c bus(`MARGIN_BLANTON_STORE` 表),不需 `margin_init`。每筆之間 `MARGIN_STORE_SETTLE`(0.5s),工具**不 poll busy bit** |
| **管理網路 ping** | `mgmt_ping_monitor.sh {start\|stop\|status\|fg\|tail\|clear\|summary}` | 一輪 = 10G leg + 1G leg,各自 `ip address/route replace` 後 `ping -I <if>` 打自己的對端;兩張卡都保持 up。每 leg 記 `ip -s link show` 與該卡的 TX/RX packet delta,另出一行可 grep 的 `RESULT` | | **管理網路 ping** | `mgmt_ping_monitor.sh {start\|stop\|status\|fg\|tail\|clear\|summary}` | 一輪 = 10G leg + 1G leg,各自 `ip address/route replace` 後 `ping -I <if>` 打自己的對端;兩張卡都保持 up。每 leg 記 `ip -s link show` 與該卡的 TX/RX packet delta,另出一行可 grep 的 `RESULT` |
| **BMC 監控** | `bmc_monitor.sh {start\|stop\|status\|fg\|tail\|clear}` | 由 host 端 `bmc-manager run` 週期取樣 `free -m`,另加一組 **I2C 寫入/讀回圖樣測試**(bus 1、addr 0x41、offset 0x00C0,寫 `55AA55AA` 讀回、再寫 `AA55AA55` 讀回)。B 啟動、C 停止並 `cat log/bmc_poll.log` | | **BMC 監控** | `bmc_monitor.sh {start\|stop\|status\|fg\|tail\|clear}` | 由 host 端 `bmc-manager run` 週期取樣 `free -m`,另加一組 **I2C 寫入/讀回圖樣測試**(bus 1、addr 0x41、offset 0x00C0,寫 `55AA55AA` 讀回、再寫 `AA55AA55` 讀回)。B 啟動、C 停止並 `cat log/bmc_poll.log` |
| **BMC DDR 壓力** | `bmc_monitor_ddr.sh` | ⚠️ **已停用** —— B/C 內呼叫處已註解,改由 `bgctl run bmc-manager run memtester` 取代。檔案保留未刪 | | **BMC DDR 壓力** | `bmc_monitor_ddr.sh` | ⚠️ **已停用** —— V1.1.9 起 B/C 內的註解區塊已刪除,改由 `bgctl run bmc-manager run memtester` 取代。檔案保留未刪 |
| **100G PRBS** | `port_prbs_monitor.sh {start [both\|a\|b]\|stop\|status\|report\|clear}` | 兩個 uplink 各一個 worker,可同時或單獨跑。setup(`lpmode off` → `prbs set` → `prbsstat STArt`)→ 週期 `prbs get`(判定)+ `prbsstat Ber`(只記錄)→ teardown(`STOp` + `prbs clear`)。輸出含 `PRBS OK!` 才算 PASS。**⚠️ A/B/C 的呼叫目前註解掉** | | **SerDes DSC 擷取** | `bcm_dsc_scan.sh [-u 0\|1] [-f <name>] [-F] [-n] [-C]` + `bcm_dsc_parse.sh -i <log> -o <prefix>` | `bcmcmd -n <unit> -c "dsh -c 'phydiag <port> dsc'"` 掃全清單(1 個 100G + 445 個 200G port)× 2 unit,raw log 寫進 `<script_dir>/log` 再 `cp` 到 `/host/hw-eval/jobs`。`-f` 支援 `%u` / `%t`;沒帶 `%u` 時自動插 `_u0`/`_u1`。成功與否**不看 `bcmcmd` 的 exit code**,改比對 `SERDES DISPLAY DIAG DATA END` 數量 + 實際迭代筆數,結尾印 `### DSC_SCAN_DONE rc=<n>`。parse 端輸出 `_lane.csv`(每 lane:TXEQ/RXFFE/DFE/EYE/SNR)與 `_pm.csv`(每 pm_id:溫度/PLL/lane 數/統計)。**由 `EN_TX_FIR` 控制,預設關** |
| **SerDes BER 掃描** | `blanton_ber.sh {init\|clear\|start\|stop\|report} [-u 0\|1\|all]` | 全機每個對接 port 的 PRBS BER:`prbs set p=3` + `prbs get`(確認每條 lane 都鎖上)→ `prbsstat STArt Interval=30` →(等一個 interval)→ `prbsstat Ber` → `STOp` → `prbs clear`。`report` 一列一條 lane,**BER < 1e-6 才 PASS**,最後跨 unit 的 summary 帶最差 lane。⚠️ PRBS 期間 link 顯示 DOWN、不過流量 | | **100G PRBS** | `port_prbs_monitor.sh {start [both\|a\|b]\|stop\|status\|report\|clear}` | 兩個 uplink 各一個 worker,可同時或單獨跑。setup(`lpmode off` → `prbs set` → `prbsstat STArt`)→ 週期 `prbs get`(判定)+ `prbsstat Ber`(只記錄)→ teardown(`STOp` + `prbs clear`)。輸出含 `PRBS OK!` 才算 PASS。**⚠️ V1.1.9 起 A/B/C 內的註解呼叫已刪除,只能手動跑** |
| **SerDes BER 掃描** | `blanton_ber.sh {init\|clear\|start\|stop\|report} [-u 0\|1\|all]` | 全機每個對接 port 的 PRBS BER:`prbs set p=3` + `prbs get`(確認每條 lane 都鎖上)→ `prbsstat STArt Interval=30` →(等一個 interval)→ `prbsstat Ber` → `STOp` → `prbs clear`。`report` 一列一條 lane,**BER < 1e-6 才 PASS**,最後跨 unit 的 summary 帶最差 lane。⚠️ PRBS 期間 link 顯示 DOWN、不過流量。V1.2.1 起 Script A 與 Script C 各跑一次(A 在流量之前、C 在流量報表之後),夾住 soak。**V1.2.2(腳本 v1.1.0)起清單納入 port 268(100G uplink ce0)**,summary 每個 unit 拆成 200G ports / 100G p268 / TOTAL 三列;某組零 lane 算 FAIL |
| **100G link 循環 + DSC** | `bcm_100g_dsc_cycle.sh <cycles> [-d] [-T] [-P] [-n]` | tuning(`docker pause gbsyncd*` → `serdes-tx-set sys 0..7` → 每 lane `tx_taps set`)一次,之後每輪:`port 268 en=0` → 輪詢 `bcmcmd ps 268` 等 `!ena` → `en=1` → 等 `up` → 兩個 unit 的 `phydiag 268 dsc` + `serdes-tx-get`/`serdes-rx-get sys 0..7`。log 一次執行一份(`~/dsc_log/`),每輪一段 `### TEST CYCLE n/N`,結尾 `### DSC_CYCLE_DONE rc=<n>`。**全 ASCII 輸出**(DUT console 會把 UTF-8 弄成亂碼)。⚠️ 尚未上機驗證 |
| **TR518 負載** | `blanton_tr518.sh {start\|stop} [-u 0\|1\|all]` | `port cd lb=mac` → `l2 learn off` → `test mode nr=yes` → `tr 518 ... testphase=1`,然後 settle `TR_SETTLE_SEC`(120s)再讓人量功耗。`stop` 只送 `port cd lb=none`(照 `TR518.txt`),L2 學習與 test mode **不會還原**,`TR_RESTORE_*=1` 才會 | | **TR518 負載** | `blanton_tr518.sh {start\|stop} [-u 0\|1\|all]` | `port cd lb=mac` → `l2 learn off` → `test mode nr=yes` → `tr 518 ... testphase=1`,然後 settle `TR_SETTLE_SEC`(120s)再讓人量功耗。`stop` 只送 `port cd lb=none`(照 `TR518.txt`),L2 學習與 test mode **不會還原**,`TR_RESTORE_*=1` 才會 |
| **PDB / CPB brick** | `pwr_brick.sh show [-r]` | 5 顆 brick 的 Vin / Iin / Vout / Iout / Temp(SWB0 `0x62`/`0x63`、SWB1 `0x60`/`0x61`、CPB `0x26`)。四顆 ADPM12200 **每個量各自一個 PMBus PAGE**(Vin 9、Iin 10、Vout 2、Iout 14、Temp 18),讀之前一定要先寫 PAGE —— `blanton_pwr_data.sh` 完全沒寫,所以整張 PDB 表都是 NA。換算用手冊 DIRECT 公式 `X=(1/m)(Y×10⁻ᴿ−b)`。每個值重讀到通過三道檢查為止(非 `0xFFFF`、非 `0x0000`、落在合理範圍)—— 這條匯流排**只壞高位元組**,`11.98 V` 會變成 `32.00 V`,全一過濾擋不住 |
| **SWB 軌功耗** | `TH6_SWB{0,1}_power_readback.sh` | 讀 `show platform voltage/current` **各一次**,19 條軌 V×I 與總功耗。舊版每軌各讀一次(38 次呼叫、每軌不同時刻),總和是不同瞬間的加總 | | **SWB 軌功耗** | `TH6_SWB{0,1}_power_readback.sh` | 讀 `show platform voltage/current` **各一次**,19 條軌 V×I 與總功耗。舊版每軌各讀一次(38 次呼叫、每軌不同時刻),總和是不同瞬間的加總 |
| **NFC 讀取輪詢** | `nfc_polling.sh {start\|stop\|status\|tail\|report\|clear\|fg}` | 背景重複跑 `blantons_nfc_validate.py`,每輪追加一行機器可讀的 `RESULT=`(PASS/FAIL 取自工具自己的摘要行,兩者皆無則 **ERROR**,與 FAIL 分開計數)。`start` 會先清空 log;`report` **只讀 log,polling 中隨時可跑**,並標示 `RUNNING` 免得快照被當最終結果。`tail` **不 follow** | | **NFC 讀取輪詢** | `nfc_polling.sh {start\|stop\|status\|tail\|report\|clear\|fg}` | 背景重複跑 `blantons_nfc_validate.py`,每輪追加一行機器可讀的 `RESULT=`(PASS/FAIL 取自工具自己的摘要行,兩者皆無則 **ERROR**,與 FAIL 分開計數)。`start` 會先清空 log;`report` **只讀 log,polling 中隨時可跑**,並標示 `RUNNING` 免得快照被當最終結果。`tail` **不 follow** |
| **USB 目標偵測** | `usb_target.sh [-o dev\|mnt\|both\|id] [-n] [-r sec]` | 找出插入的 USB 儲存裝置,排除 `/` 與 `/host` 的底層碟(本平台可能從 USB DOM 開機),多顆時拒絕猜;掛載時會驗證真的可寫 | | **USB 目標偵測** | `usb_target.sh [-o dev\|mnt\|both\|id] [-n] [-r sec]` | 找出插入的 USB 儲存裝置,排除 `/` 與 `/host` 的底層碟(本平台可能從 USB DOM 開機),多顆時拒絕猜;掛載時會驗證真的可寫 |
@@ -452,6 +491,8 @@ pwr_data
1. **A → B → C 必須依序跑,且 B 之後才能跑 C。** Script B 的背景 job 只存在於那個 shell session, 1. **A → B → C 必須依序跑,且 B 之後才能跑 C。** Script B 的背景 job 只存在於那個 shell session,
Script C 的 `kill $(jobs -p)` 依賴同一個 session;中途斷線就得手動收程序。 Script C 的 `kill $(jobs -p)` 依賴同一個 session;中途斷線就得手動收程序。
V1.1.8 起 `mlucas-amm` 例外 —— 它是 systemd transient unit,**跨 session 存活**,
所以 Script C 必須另外 `systemctl stop mlucas-amm`(見第 17 條)。
2. **A / B / C 共用同一個 log 檔**:只有 Script A `logopen`,B / C 用 `logwrite` 續寫分隔線。 2. **A / B / C 共用同一個 log 檔**:只有 Script A `logopen`,B / C 用 `logwrite` 續寫分隔線。
跑 B/C 前若關掉了 Tera Term,log 就斷了。 跑 B/C 前若關掉了 Tera Term,log 就斷了。
3. **PCIe AER 的判定是「差值」不是「絕對值」**:Script A 抓基線、Script C 抓結果, 3. **PCIe AER 的判定是「差值」不是「絕對值」**:Script A 抓基線、Script C 抓結果,
@@ -478,6 +519,11 @@ pwr_data
`vlan create` 的 `Entry exists`(重跑 init)與 `vlan remove` 的 `not found`(init 前先 stop) `vlan create` 的 `Entry exists`(重跑 init)與 `vlan remove` 的 `not found`(init 前先 stop)
當良性情況分開計數。另外 `bcmcmd` 一律以 `</dev/null` 執行 —— 當良性情況分開計數。另外 `bcmcmd` 一律以 `</dev/null` 執行 ——
否則它會吃掉 while 迴圈的 stdin,導致**只有第一個 VLAN 被設定**(V0.3.1 修的 bug)。 否則它會吃掉 while 迴圈的 stdin,導致**只有第一個 VLAN 被設定**(V0.3.1 修的 bug)。
**2026-09-07 `bcm_dsc_scan.sh` 又踩了同一個坑**(port 清單走 stdin,445 個 port 只掃了 1 個),
而且因為 `### PORT` marker 與 dsc 區塊數量一起變少,原本的比對檢查完全看不出來、`rc=0`。
修法:迴圈改讀 fd 3(`done 3< "$PORTFILE"`)+ `bcmcmd ... < /dev/null`,再加一道
「實際迭代筆數 == 清單筆數」的獨立檢查。**寫任何餵檔案給 `while` 又在裡面呼叫 `bcmcmd` 的迴圈,
都要假設它會讀 stdin;而且完整性檢查不能只比對兩個會一起變少的數字。**
11. **DUT 密碼不得進 git**:`1_Blanton_Script_A.ttl` 目前的 `sendln "YourPaSsWoRd"` 是 placeholder, 11. **DUT 密碼不得進 git**:`1_Blanton_Script_A.ttl` 目前的 `sendln "YourPaSsWoRd"` 是 placeholder,
實際帳密必須放 `secret/config_secret.ttl`(gitignored)並由 `config.ttl` include。 實際帳密必須放 `secret/config_secret.ttl`(gitignored)並由 `config.ttl` include。
12. **`.sh` / `.conf` 必須是 LF**:CRLF 的 shell script 在 SONiC 上直接掛 12. **`.sh` / `.conf` 必須是 LF**:CRLF 的 shell script 在 SONiC 上直接掛
@@ -494,8 +540,13 @@ pwr_data
`Permission denied`、Script C 的 `cat` 撲空(BMC 段全空但不會報錯)。 `Permission denied`、Script C 的 `cat` 撲空(BMC 段全空但不會報錯)。
14. **TTL 的 `timeout` 是全域的,設了就要還原**:`timeout = N` 之後**每一個** `wait` 都被限制在 N 秒, 14. **TTL 的 `timeout` 是全域的,設了就要還原**:`timeout = N` 之後**每一個** `wait` 都被限制在 N 秒,
逾時的 `wait` 會直接返回而沒吃到 prompt,於是下一個指令在前一個還沒跑完就送出,之後整輪錯開一拍。 逾時的 `wait` 會直接返回而沒吃到 prompt,於是下一個指令在前一個還沒跑完就送出,之後整輪錯開一拍。
`wait_init.ttl` 設 60 後還原 0;Script B 的 cdc_ncm 探測設 15,在 `:skip_ping`(兩條路徑的匯流點)還原。 `wait_init.ttl` 設 60 後還原 0;Script B 的 cdc_ncm 探測設 15,成功路徑在 `endif` 之後還原、
加新的 `timeout` 時務必配一個 `timeout = 0`。 跳過路徑在 `:skip_ping` 還原(兩處各一次)。
Script 5 抄了同一段,但它的 ping 區塊要 `wait` 一個 `sleep 10` —— DUT 一忙就逼近 15 s 上限,
所以**還原點提前到 `if` 之前**:分支之前還原,一行就涵蓋兩條路徑,`:skip_ping` 的那行留作備援。
加新的 `timeout` 時務必配一個 `timeout = 0`;**抄有 `goto` 的段落時連 `:label` 一起抄** ——
標籤沒定義 Tera Term 不會在載入時報錯,要真的跳進那條分支才會彈錯誤視窗停住整輪
(Script 5 原本就漏了 `:skip_ping`,只有抓不到 NCM 介面時才會發作,已補)。
15. **兩張管理網卡同網段時會 ARP flux**:`mgmt_ping_monitor.sh` 讓 eth0/eth1 同時 up,若兩者在同一個 15. **兩張管理網卡同網段時會 ARP flux**:`mgmt_ping_monitor.sh` 讓 eth0/eth1 同時 up,若兩者在同一個
/24(本專案預設 `192.168.1.99` / `.101`),對端 ARP 可能由任一張卡回應,回包落在沒送封包的那張, /24(本專案預設 `192.168.1.99` / `.101`),對端 ARP 可能由任一張卡回應,回包落在沒送封包的那張,
量到的數字不能歸屬。`ARP_STRICT=1` 會設 `arp_ignore=1` / `arp_announce=2` 擋掉; 量到的數字不能歸屬。`ARP_STRICT=1` 會設 `arp_ignore=1` / `arp_announce=2` 擋掉;
@@ -503,6 +554,27 @@ pwr_data
**ping 成功但 `nic_tx` 接近 0 就代表封包從另一張卡出去了**。兩張卡在不同網段時可設 0。 **ping 成功但 `nic_tx` 接近 0 就代表封包從另一張卡出去了**。兩張卡在不同網段時可設 0。
16. **客戶 NDA**:`docs/` 內含客戶 FPGA 規格與 schematic 衍生資訊,**本 repo 只推 NAS + Gitea, 16. **客戶 NDA**:`docs/` 內含客戶 FPGA 規格與 schematic 衍生資訊,**本 repo 只推 NAS + Gitea,
絕不推 GitHub**。 絕不推 GitHub**。
17. **改用 `systemd-run` 起壓力工作,就要自己補停的那一行。** `utils/kill_all_process.ttl` 的內容
只有 `kill $(jobs -p)`,而 systemd unit 不是 shell job,它抓不到。V1.1.8 把 `mlucas-avx2`
搬到 `mlucas-amm` unit(好處:掉線不會停、`jobs` 看不見的問題消失、`Restart=always` 會自動拉回),
代價是 Script C 少了那行 `systemctl stop` 就會讓 CPU 滿載燒進收工量測與下一輪測試 ——
而 `show interfaces status` 之類的檢查完全看不出來。目前 `mlucas-amm` 與
`qfx5252-bmc-usb-net-test` 兩個 unit 都已在 Script C 收掉。
⚠️ **`4_Blanton_Script_thermal_safety.ttl` 用同一個 `mlucas-amm` unit,但它沒有收尾段**,
所以那行 `systemctl stop mlucas-amm` 必須由測試員手動下 —— 這是 Script 4 目前
唯一一個「不下就會延續到下一輪」的負載。
18. **`pause` 停的是 macro,`sleep` 停的是 DUT。** V1.2.0 起 A/B/C 的等待一律改成
`sendln "sleep N"` + `wait prompt_sonic_root`。`pause N` 期間 macro 不理會 DUT,shell 是閒著的,
等於用猜的估上一個指令要跑多久 —— DUT 一忙就會提早往下送指令;改成 DUT 端 `sleep` 之後,
prompt 回來才繼續,兩邊不可能走散,而且這段等待會帶時戳進 log,事後看得出哪一輪跑久了。
⚠️ **Script 4 與 Script 5 尚未轉換,仍在用 `pause`**;B/C 開頭的 `pause 1` 也保留
(它在登入前執行,沒有 prompt 可等)。
19. **`config.ttl` 少一個變數會讓 macro 當場中止**,不是當成 0。V1.1.8 新增 `EN_timestamp`
(Script A `logopen` 的第 5 個參數)與 `BMC_USB_RUNTIME`(Script B 的 ping unit);
V1.2.0 再加 `EN_TX_FIR`(A/C 的 DSC 掃描與 C 的四行 `cp`,預設 0)。
只更新 `.ttl` 卻沿用舊的 `config.ttl`,Script A 會停在 `logopen` 那一行。
另外 **時間戳的「格式」不在 macro 裡** —— 它在 Tera Term 的
Setup → Additional settings → Log,存在那台電腦的 `TERATERM.INI`,會跟著 PC 而不是跟著腳本走。
--- ---
@@ -736,7 +808,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
- [ ] 打 git tag `v1.1.0`,push `nas` + `gitea` - [x] 打 git tag,push `nas` + `gitea`(已至 `V1.2.2`;`publish/` 依 Script A 檔頭版號打包)
**驗收條件:** 從 zip 解壓到一台乾淨的測試 NB,照 README 操作,不看原始碼就能完成一輪 A→B→C **驗收條件:** 從 zip 解壓到一台乾淨的測試 NB,照 README 操作,不看原始碼就能完成一輪 A→B→C
並產出 summary;`publish/` 內容與 git tag 一致。 並產出 summary;`publish/` 內容與 git tag 一致。
@@ -770,14 +842,40 @@ margin status、全部 VRM 軌的 Vin/Vout/Iout/Temp、CB + ICB 溫感讀值,
Script A 既不往下走也不報錯。可加最大重試次數 + `messagebox` 提示。 Script A 既不往下走也不報錯。可加最大重試次數 + `messagebox` 提示。
- **腳本的執行權**:`mgmt_ping_monitor.sh` 與 `bmc_monitor.sh`(以及已停用的 `bmc_monitor_ddr.sh`)需人工 `chmod +x`。 - **腳本的執行權**:`mgmt_ping_monitor.sh` 與 `bmc_monitor.sh`(以及已停用的 `bmc_monitor_ddr.sh`)需人工 `chmod +x`。
可在 Script B 起它之前補一行(比照既有的 `chmod +x ~/hammer/tools/amd/mlucas-avx2`),或在 publish 時處理。 可在 Script B 起它之前補一行(比照既有的 `chmod +x ~/hammer/tools/amd/mlucas-avx2`),或在 publish 時處理。
- **`bmc_monitor_ddr.sh` 已停用**:B/C 內的呼叫已註解,DDR 壓力改由 `bgctl run bmc-manager run memtester` - **`bmc_monitor_ddr.sh` 已停用**:V1.1.9 起 B/C 內那段註解掉的呼叫已刪除,DDR 壓力由
取代。檔案還留在 repo,待確認不再需要後刪除,或在檔頭標註停用。 `bgctl run bmc-manager run memtester` 取代。檔案還留在 repo,待確認不再需要後刪除,或在檔頭標註停用。
(`bmc_monitor.sh` 已於 2026-08-25 重新啟用,並加上 I2C 寫入/讀回圖樣測試。) (`bmc_monitor.sh` 已於 2026-08-25 重新啟用,並加上 I2C 寫入/讀回圖樣測試。)
- **`rm /host/hw-eval/jobs/*` 清不掉子目錄**:Script A 用的是不帶 `-r` 的 `rm`,但 Script C - **`rm /host/hw-eval/jobs/*` 清不掉子目錄**:Script A 用的是不帶 `-r` 的 `rm`,但 Script C
是 `cp -r` 那個目錄,代表裡面可能有子目錄。清不乾淨的話,上一輪的 job log 會被當成這輪的一起 是 `cp -r` 那個目錄,代表裡面可能有子目錄。清不乾淨的話,上一輪的 job log 會被當成這輪的一起
複製到 USB。要確認 `bgctl` 的產出結構,必要時改成 `rm -rf .../jobs/*`。 複製到 USB。要確認 `bgctl` 的產出結構,必要時改成 `rm -rf .../jobs/*`。
- **100G PRBS 尚未接進 A/B/C**:`port_prbs_monitor.sh` 已隨包交付、可手動執行,但三支腳本裡的呼叫 - **100G PRBS 已從 A/B/C 移除**:`port_prbs_monitor.sh` 仍隨包交付、仍可手動執行,但 V1.1.9 起
都還註解著(bring-up 中)。要啟用時記得 PRBS 期間 link 會顯示 down,`stop` 之後才會回來。 三支腳本裡那些註解掉的呼叫已整段刪除(連同 Script C 的 `bmc_monitor_ddr.sh` 區塊)。
要接回去得重寫,不是把註解拿掉。啟用時記得 PRBS 期間 link 會顯示 down,`stop` 之後才會回來。
- **DSC 擷取預設是關的**:`EN_TX_FIR = 0`,所以出貨設定不會跑 `bcm_dsc_scan.sh`。
開啟後 Script A 與 Script C 各掃一次、整輪多約 20 分鐘;只要單邊資料可以在腳本裡改成 `-u 0`。
掃描本身是唯讀(`phydiag ... dsc` 不改 SerDes 設定),但**它與 `blanton_ber.sh` /
`blanton_traffic_linespeed` / `blanton_tr518.sh` 一樣都在動同一批 port,不要同時跑**。
- **`bcm_100g_dsc_cycle.sh` 尚未上機驗證**:`port en=0/1` 之後 link 多久會動、以及
`docker pause gbsyncd*` 期間的影響,都要上機才知道。等待是讀 SDK(`bcmcmd ps <port>`)而不是
`show interfaces status`,所以理論上不受 gbsyncd 暫停影響,但沒實測過。
結束時(含 Ctrl-C)會自動 `docker unpause`,`RESUME_GBSYNCD=0` 可關掉。
- **Script 5(Reboot Cycle)尚未上機驗證**:`5_Blanton_Script_Reboot_Cycle.ttl` 隨 V1.1.7 交付,
但還沒在真 DUT 上跑過一輪完整循環。兩個要現場確認的點:`wait "Booting in blind mode"` 是否
真的在每一版開機訊息裡出現(沒出現就會永遠等下去,而且沒有 `timeout` 保護);以及每輪重跑
`bmc-first-enroll` 是否安全。**沒有結束條件**,測夠了要自己關掉 macro。
- **`tmp/blanton_reboottest.sh`(bash 版重開循環)也未上機驗證**:不用 Tera Term、由 systemd 在
每次開機跑一輪並自動 `reboot`,登入下 `stop` 才停。整個 `tmp/` 是 gitignored,**不會進交付包** ——
驗證過再搬進 `Blanton_Script/`。未驗證的腳本混進 `Blanton_Script/` 之後,測試員分不出哪支能信。
- **交付包不含 `hammer/`,但 Script B 與 Script 4 都要用它**:V1.1.8 起 `hammer/` 是 gitignored
且被 `publish.sh` 排除(~99 MB 的 mlucas binary,進 git 就永久留在 history)。這是刻意的 ——
binary 由 DUT image 帶 —— 但代表**測試員解開交付包後 `~/hammer` 必須已經在 DUT 上**,
否則 Script B 會在 `chmod +x ~/hammer/tools/amd/mlucas-avx2` 那一行失敗,而且 macro 不會停,
接著的 `systemd-run` 只是起一個立刻失敗又被 `Restart=always` 反覆重拉的 unit。
上機前先 `ls ~/hammer/tools/amd/mlucas-avx2` 確認一次。
- **`mlucas-amm` 的 `~` 依賴 systemd 的環境**:unit 是
`/bin/bash -c '~/hammer/... >> ~/hammer/mlucas_amm_log'`,system service 沒有 `User=` 時 systemd
**不會設 `HOME`**,bash 才退回 passwd 的家目錄(root → `/root`)解出同一條路徑。目前會通,
但那是剛好對上而不是保證;改成絕對路徑 `/root/hammer/...` 就不用賭。**尚未上機驗證。**
- **Script C 的 USB 掛載走 `mount` 而非 `usb_target.sh -o mnt`**:目前是 `-o dev` 取節點再自己 - **Script C 的 USB 掛載走 `mount` 而非 `usb_target.sh -o mnt`**:目前是 `-o dev` 取節點再自己
`mount <dev> /mnt/usb`,繞過了工具內建的 `mkdir -p`、exfat/ntfs `modprobe` 與可寫性驗證。 `mount <dev> /mnt/usb`,繞過了工具內建的 `mkdir -p`、exfat/ntfs `modprobe` 與可寫性驗證。
掛載點不存在、檔案系統模組沒載、或媒體唯讀時只會失敗一行,job log 就沒帶出來。 掛載點不存在、檔案系統模組沒載、或媒體唯讀時只會失敗一行,job log 就沒帶出來。
@@ -790,9 +888,56 @@ margin status、全部 VRM 軌的 Vin/Vout/Iout/Temp、CB + ICB 溫感讀值,
**`sleep 120` 的方向還沒驗證** —— 若 `tr 518` 的流量是有時限的(參數含 `runtime=1`、 **`sleep 120` 的方向還沒驗證** —— 若 `tr 518` 的流量是有時限的(參數含 `runtime=1`、
`CheckDataTime=200`),等 120 秒可能量到已經降下來的值,要上機比對 0s / 30s / 120s 三次; `CheckDataTime=200`),等 120 秒可能量到已經降下來的值,要上機比對 0s / 30s / 120s 三次;
TTL 尚未呼叫它。 TTL 尚未呼叫它。
- **`blanton_ber.sh` 的 `sleep 30` 與 `BER_INTERVAL` 是兩處要同步改的數字**:Script C 寫死 - **`--runtime` 是整個 job 的總時限,不是每個 pass 的**:V1.1.7 起由 `config.ttl` 宣告
`sendln "sleep 30"`,腳本預設 `BER_INTERVAL=30`。改一邊沒改另一邊,report 會讀到還沒累積完 (`SSD_RUNTIME`/`SSD_COUNT`、`USB_RUNTIME`/`USB_COUNT`,COUNT 直接對應 `--passes`)。
一個 interval 的數字,而且不會有任何警告。 `qfx5252-stress-*` 跑滿 RUNTIME 秒就結束,**`--passes` 不會把它延長**,所以
`RUNTIME=600, COUNT=720` 是 10 分鐘的壓力而不是 120 小時。要跑滿一天就把 RUNTIME 填 `86400`。
**V1.1.8 起出貨預設是 `RUNTIME=3600`(1 小時)**,`BMC_USB_RUNTIME` 則是 `172800`(2 天)——
三個壓力源的長度目前刻意不一致,開跑前要照當次 soak 的時間各自對一次。
壓力提早結束時 Script B 每輪的 `bgctl list` 數量會變少,但**沒有任何東西會主動報警**;
要比 24 小時更久則得加一段重啟 job 的邏輯。
- **BMC USB 的 service log 只剩隨身碟一份**:Script C 把 `journalctl` 導進
`log/bmc_usb_net.log` 再 `cp` 到 job 目錄,**不再印在 master console log**。
那個 `cp` 沒有檢查回傳值(`nfc_polling.log` 檔名打錯那次就是這樣安靜失敗的),
失敗的話這份 log 就完全消失。要嘛在 `cp` 之後補一次 `ls` 驗證,要嘛保留一份
`cat` 到 console。
- **`READ_VIN` / `READ_IIN` 不在 ADPM12200 手冊的 Table 3 裡**:`pwr_brick.sh` 讓它們沿用
Voltage / Current 那兩組係數。50 V 輸入算得出來、數量級也對,但**手冊沒有明說**。要定案
得找 ADI 確認,或找一個能獨立比對輸入電壓的量測點(`READ_VOUT` 就是靠 `show platform
voltage` 的 `PDB_IBC_*` 對上的)。
- **VI2C 沒有硬體號誌**(`vi2c_muxsel` 的 help 自己寫了「VI2C has no SEM_REG」),而平台的
sensor 驅動會週期性讀同一批 PDB 裝置。`pwr_brick.sh` 用「重讀到合理為止」繞過去,但根本
問題沒解:`_vrd` 裡的 `_vwait` 逾時後仍然回傳半成品,呼叫端也沒檢查它的回傳值。修
`blanton_icb_vi2c.sh` 會影響所有走 VI2C 的工具(ICB 溫感、風扇、EEPROM),值得先確認
是不是跟 pmon 競爭再動。
- **`blanton_multiphase_margin.sh` 與 `margin.sh` 沒有互斥機制**:兩支從不同側(原生 i2c vs
LTC2980 PMBus)摸同一批軌,各自都假設自己是唯一的寫入者。目前只靠文件與 help 提醒,
沒有任何執行期檢查。
- **Script 4 沒有收尾段**:`while 1` 之後就是檔案結尾,中斷時 DUT 停在 `port cd lb=mac` /
`l2 learn off` / `test mode nr=yes`,而且 CPU 壓力還在跑。要手動
`blanton_tr518.sh stop` + `systemctl stop mlucas-amm`(V1.1.8 起它是 systemd unit,
關掉 Tera Term 或 `kill $(jobs -p)` 都收不掉),否則下一輪任何測試都在被污染的狀態上開始
(Script A 的 `bgctl reset/stop --all` 收得掉 job,但收不掉 bcm 的 loopback 設定)。
可考慮加一支對應的收尾腳本,或在檔尾用 `messagebox` 提示要下哪些指令。
- **margin 在 soak 期間不再取樣**(V1.1.4):只剩 Script A 的起始值與 Script C 的結束值。
漂移發生在中間就看不到了。若要恢復,比較好的做法是在 B 的迴圈內每 N 輪才掃一次,
而不是每輪都掃。
- ✅ **`blanton_ber.sh` 不再把 lane 的量測結果當成 shell 錯誤**(v1.1.1,2026-09-15):
`prbs get` 每條 lane 一行,沒鎖上的會印 `PRBS Error!`,而錯誤樣式是拿
`grep -i 'ERROR|Invalid|...'` 掃整份輸出的 —— 於是正常的 init 會報「the BCM shell rejected」,
而且提早 return,**把「哪幾條 lane 沒鎖」這個真正有用的資訊吞掉**。現在 per-lane 行排除在
掃描外、改成大小寫敏感、真正的拒絕會把該行印出來。
⚠️ **這類「完整性檢查自己看不到失敗」的錯在這個 repo 已經出現三次**
(`bcm_dsc_scan.sh` v1.3.0 數 marker、`blanton_ber.sh` v1.1.1、以及 power cycle 報告的
ping 解析把 100% 丟包當成「沒資料」)。寫檢查時要問:**失敗長什麼樣,這段程式碼看得到嗎?**
- **`blanton_ber.sh` 的 `sleep 30` 與 `BER_INTERVAL` 是兩處要同步改的數字**:Script A(V1.2.1 起)
與 Script C 都寫死 `sendln "sleep 30"`,腳本預設 `BER_INTERVAL=30`。改一邊沒改另一邊,report 會
讀到還沒累積完一個 interval 的數字,而且不會有任何警告。現在有**三處**要一起改。
- **Script A 的 BER `clear` 與第一輪流量之間沒有 settle**:V1.2.1 把 BER 掃描放在流量**之前**,
而 PRBS 是把 lane 拉出正常運作、`clear` 才放回去的。Script A 的 `blanton_ber.sh clear` 之後
緊接著就是 `blanton_traffic_linespeed ps` / `init`,中間沒有等待;Script C 的 BER 在流量報表
之後,沒有這個順序。上機時比對兩份 traffic report —— Script A 有 NA/FAIL 而 Script C 沒有,
就是 lane 尚未回穩,在 `clear` 後加一個 `sleep` 即可。**尚未上機驗證。**
- **`ce0` 的 ingress mirror 尚未上機驗證**:`mirror port ce0 Mode=Ingress DestPort=ce0` 這條路是 - **`ce0` 的 ingress mirror 尚未上機驗證**:`mirror port ce0 Mode=Ingress DestPort=ce0` 這條路是
推論出來的(鏡像複本不受 egress filter 的 source-port knockout 限制),語法取自 DUT 的 推論出來的(鏡像複本不受 egress filter 的 source-port knockout 限制),語法取自 DUT 的
`help mirror`,但**還沒證明硬體真的接受 destport == srcport**。驗證方式是隔 10 秒看兩次 `help mirror`,但**還沒證明硬體真的接受 destport == srcport**。驗證方式是隔 10 秒看兩次
+138 -7
View File
@@ -9,21 +9,37 @@ DUT 端的取數能力由一組 **bash 工具庫** 提供(CB FPGA `pcimem` →
完整架構見 [ARCHITECTURE.md](ARCHITECTURE.md)。 完整架構見 [ARCHITECTURE.md](ARCHITECTURE.md)。
**目前狀態(2026-08-28)**:Script A 為 **V1.1.2**(A 集中記錄 A/B/C 三支的變更)。涵蓋 **目前狀態(2026-09-15)**:Script A 為 **V1.2.2**(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` 指定
(預設 100 = 全速;soak 是熱測試,散熱不該是變因)。 (預設 100 = 全速;soak 是熱測試,散熱不該是變因)。
測試 job log 收在 DUT 的 `/host/hw-eval/jobs/`,Script C 結束時掛好 USB 再帶時戳複製到 `/mnt/usb/`。 測試 job log 收在 DUT 的 `/host/hw-eval/jobs/`,Script C 結束時掛好 USB 再帶時戳複製到 `/mnt/usb/`。
100G PRBS(`port_prbs_monitor.sh`)已隨包交付,但 **A/B/C 的呼叫仍註解掉**,還在 bring-up。 100G PRBS(`port_prbs_monitor.sh`)已隨包交付、可手動執行,但 **V1.1.9 起 A/B/C 裡註解掉的呼叫已整段刪除**,
Script B 的 soak 迴圈每輪印 `bgctl list` + `jobs`,並 `pause 60`(V1.0.10 之前完全沒有 pause)。 要接回去得重寫(`bmc_monitor_ddr.sh` 在 Script C 的註解區塊同時移除)。
V1.1.0 新增全機 SerDes BER 掃描(`blanton_ber.sh`,**Script C 已接**,依 `SWB_UNIT` 分支)、 V1.1.9 新增 **SerDes DSC 擷取**:`bcm_dsc_scan.sh`(DUT 端,`phydiag <port> dsc` 掃全機 ~445 port × 2 unit,
約 10 分鐘)由 Script A 與 Script C 各跑一次夾住 soak,`bcm_dsc_parse.sh`(Host 端)把 raw log 轉成
`_lane.csv` / `_pm.csv`。**由 `config.ttl` 的 `EN_TX_FIR` 控制,預設 0(關)** —— 開了整輪測試多 ~20 分鐘。
Script B 的 soak 迴圈每輪印 `bgctl list` + `jobs` + `systemctl is-active mlucas-amm`,並 `sendln "sleep 60"`
(V1.0.10 之前完全沒有間隔;V1.2.0 起 A/B/C 的等待一律改成 DUT 端 `sleep` 而非 macro 端 `pause`)。V1.1.8 起 AMD CPU 壓力(`mlucas-avx2`)由 `systemd-run` 掛成
`mlucas-amm` transient unit(`Restart=always`),不再是 shell 的 `&` 背景 job —— 掉線也不會停,
Script C 用 `systemctl stop mlucas-amm` 收掉並把 log 複製到隨身碟。
V1.1.0 新增全機 SerDes BER 掃描(`blanton_ber.sh`,依 `SWB_UNIT` 分支);**V1.2.1 起 Script A 也接了一次**,
**V1.2.2 起清單納入 port 268(100G uplink,ce0)**,summary 每個 unit 拆成「200G ports / 100G p268 / TOTAL」三列;
在第一輪流量之前取基線,與 Script C 流量報表之後的收尾掃描一起夾住 soak(同 DSC 的做法)。另有
TR518 負載(`blanton_tr518.sh`,**TTL 尚未接**)、SWB 軌功耗(`TH6_SWB{0,1}_power_readback.sh`), TR518 負載(`blanton_tr518.sh`,**TTL 尚未接**)、SWB 軌功耗(`TH6_SWB{0,1}_power_readback.sh`),
線速流量也納入 100G `ce0`(VLAN 138,靠 ingress mirror 維持循環)。 線速流量也納入 100G `ce0`(VLAN 138,靠 ingress mirror 維持循環)。
Script A 開頭會先收掉前一輪殘留(`hw-test-session finish` + `bgctl reset/stop --all`), Script A 開頭會先收掉前一輪殘留(`hw-test-session finish` + `bgctl reset/stop --all`),
再 `bgctl list` 確認沒有 job 留著佔資源。 再 `bgctl list` 確認沒有 job 留著佔資源。
NFC tag 讀取由 `nfc_polling.sh` 背景輪詢(A 做基線、B 起、C 停並 report)。 NFC tag 讀取由 `nfc_polling.sh` 背景輪詢(A 做基線、B 起、C 停並 report)。
最後一次發布是 **V1.1.1**;SWB 的 I2C 通道與位址已於 2026-08-19 上機驗證。 另有 **`4_Blanton_Script_thermal_safety.ttl`**(熱 / 安規,**獨立跑不接 A→B→C**,滿載後每分鐘
取 PMON + 兩片 SWB 的軌功耗;**沒有收尾段**,中斷後要手動 `blanton_tr518.sh stop`)。
以及 **`5_Blanton_Script_Reboot_Cycle.ttl`**(重開機循環,**獨立跑不接 A→B→C**:登入 → 風扇 →
Check Pt1~Pt13 → `reboot` → `wait "Booting in blind mode"`,`cnt_cycle` 每輪遞增,`while 1` 無止境,
要停就關 Tera Term 的 macro)。**尚未上機驗證**。
流程圖:`docs/Blanton_Test_Flow.drawio`。
最後一次發布是 **V1.1.5**;SWB 的 I2C 通道與位址已於 2026-08-19 上機驗證。
margin 的 `VNOM` 已於 2026-08-30 改為 Blanton 實測中位數(144 條軌中 86 條上調 0.8~2.5%)。
交付用 `./publish/publish.sh` 打包。 交付用 `./publish/publish.sh` 打包。
## 技術棧 ## 技術棧
@@ -113,6 +129,23 @@ 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
# ── PDB / CPB power brick 讀值 ──────────────────────
./Blanton_Script/pwr_brick.sh show # Vin/Iin/Vout/Iout/Temp × 5 顆
./Blanton_Script/pwr_brick.sh show -r # 多印 raw word
# 四顆 ADPM12200 每個量各一個 PMBus PAGE:Vin 9 / Iin 10 / Vout 2 / Iout 14 / Temp 18
# CPB.PU37 (0x26) 是不同零件:不寫 PAGE,自己一套換算
# PB_TRIES=1 ... show -r 可看未經重試的原始行為
# ── 多相 VRM margin(原生 i2c,38 條軌)──────────────
./Blanton_Script/blanton_multiphase_margin.sh high3 # 全部 +3%
./Blanton_Script/blanton_multiphase_margin.sh low3 # 全部 -3%
./Blanton_Script/blanton_multiphase_margin.sh comboA # 混合,組合 A
./Blanton_Script/blanton_multiphase_margin.sh comboB # 混合,組合 B
./Blanton_Script/blanton_multiphase_margin.sh save # ⚠️ 永久寫 NVM
# -u 0 / -u 1 單邊(SWB0=i2c-13/15,SWB1=i2c-14/16);-n 只印指令
# 逐條印 SWB0_0V9_ANLG0 - 0.930V Configure Done;save 只印 Multiphase Save All
# ⚠️ 這不是 margin.sh 管的 LTC2980,兩支摸同一批軌,不要同時用
# ── 全機 SerDes BER(PRBS,期間 link 會顯示 DOWN)──── # ── 全機 SerDes BER(PRBS,期間 link 會顯示 DOWN)────
./Blanton_Script/blanton_ber.sh init # prbs set p=3 + prbs get(檢查每條 lane 鎖定) ./Blanton_Script/blanton_ber.sh init # prbs set p=3 + prbs get(檢查每條 lane 鎖定)
./Blanton_Script/blanton_ber.sh start # prbsstat STArt Interval=30 ./Blanton_Script/blanton_ber.sh start # prbsstat STArt Interval=30
@@ -120,9 +153,38 @@ sleep 30 # 至少等一個 interval 再 rep
./Blanton_Script/blanton_ber.sh report # 每 lane 一列,BER < 1e-6 才 PASS,最後 summary ./Blanton_Script/blanton_ber.sh report # 每 lane 一列,BER < 1e-6 才 PASS,最後 summary
./Blanton_Script/blanton_ber.sh stop # prbsstat STOp ./Blanton_Script/blanton_ber.sh stop # prbsstat STOp
./Blanton_Script/blanton_ber.sh clear # prbs clear(會解除 PRBS,要重測得再 init) ./Blanton_Script/blanton_ber.sh clear # prbs clear(會解除 PRBS,要重測得再 init)
# summary 每個 unit 三列:200G ports / 100G p268 / TOTAL(兩個 unit 各有自己的 ce0(268))
# ⚠️ 某一組「一條 lane 都沒回報」算 FAIL 不算 PASS —— 待測的 port 沉默不是通過
# -u 0 / -u 1 單邊;-c 1e-9 換門檻;-F 只列失敗;-f <log> 離線重解 # -u 0 / -u 1 單邊;-c 1e-9 換門檻;-F 只列失敗;-f <log> 離線重解
# ⚠️ 不能跟 blanton_traffic_linespeed / blanton_tr518 同時跑(都會接管同一批 port) # ⚠️ 不能跟 blanton_traffic_linespeed / blanton_tr518 同時跑(都會接管同一批 port)
# ── SerDes DSC 擷取(TX_FIR / RXFFE / DFE / EYE / SNR)──
./Blanton_Script/bcm_dsc_scan.sh # unit 0+1 全掃,約 10 分鐘
./Blanton_Script/bcm_dsc_scan.sh -u 0 # 只掃一個 unit(時間減半)
./Blanton_Script/bcm_dsc_scan.sh -f my.log -F # 自訂檔名 + 覆蓋
./Blanton_Script/bcm_dsc_scan.sh -n # dry-run,只列要掃的 port
# log: ~/Blanton_Script/log/,掃完自動 cp 到 /host/hw-eval/jobs(-C 可關)
# 檔名沒帶 %u 時會自動插 _u0 / _u1,所以兩個 unit 不會互相覆蓋
# 結尾固定印 "### DSC_SCAN_DONE rc=<n>";rc=0 才是全部 port 都拿到完整 dump
# ⚠️ 由 TTL 的 EN_TX_FIR 控制,預設 0(關)—— A 與 C 各掃一次,開了整輪多 ~20 分鐘
# ── DSC raw log → CSV(離線解,Host 或 DUT 都可)──────
sh ~/Blanton_Script/bcm_dsc_parse.sh -i blanton_dsc_ScriptA_u0.log -o u0
# 產出 u0_lane.csv(每 lane 一列)+ u0_pm.csv(每 pm_id 一列)
# 純 sh + awk(mawk 相容),欄位靠括號群組順序抓,SDK 改排版不會壞;
# 群組數 != 9 的列標成 UNPARSED 印到 stderr,不會安靜解錯
# ── 100G link down/up 循環 + DSC(TTL 尚未接)────────
./Blanton_Script/bcm_100g_dsc_cycle.sh # 印說明
./Blanton_Script/bcm_100g_dsc_cycle.sh 200 # 跑 200 輪(-c 200 亦可)
./Blanton_Script/bcm_100g_dsc_cycle.sh 200 -d # 每行指令以灰色 [CMD] 印出來
./Blanton_Script/bcm_100g_dsc_cycle.sh 20 -T # 跳過 tuning
./Blanton_Script/bcm_100g_dsc_cycle.sh 1 -n # dry-run,不碰硬體也不 sleep
# log: ~/dsc_log/100G_dsc_cycle_test_<ts>.log,每輪一段 '### TEST CYCLE n/N'
# 每輪收:兩個 unit 的 phydiag dsc + serdes-tx-get / serdes-rx-get sys 0..7
# 等 link 是輪詢 'bcmcmd ps 268'(每 -p 秒,上限 -w 秒),不是 show interfaces status
# ⚠️ 尚未上機驗證;與 blanton_ber / blanton_traffic_linespeed / blanton_tr518 互斥
# ── TR518 負載 + 量功耗(TTL 尚未接)───────────────── # ── TR518 負載 + 量功耗(TTL 尚未接)─────────────────
./Blanton_Script/blanton_tr518.sh start # 兩 unit,跑完 settle 120s ./Blanton_Script/blanton_tr518.sh start # 兩 unit,跑完 settle 120s
./Blanton_Script/TH6_SWB0_power_readback.sh # 19 條軌 V×I + TOTAL POWER ./Blanton_Script/TH6_SWB0_power_readback.sh # 19 條軌 V×I + TOTAL POWER
@@ -218,6 +280,46 @@ Tera Term 連 COM port (115200-8-N-1)
- ⚠️ **ICB/PDB 一律走 VI2C(`blanton_icb_vi2c.sh`),不要走 VSPI**:VSPI ~18 ms/reg 會讓 I2C - ⚠️ **ICB/PDB 一律走 VI2C(`blanton_icb_vi2c.sh`),不要走 VSPI**:VSPI ~18 ms/reg 會讓 I2C
byte 相間隔拉到 ~50 ms,踩中 SMBus 25–35 ms timeout,裝置直接 NACK。實測全掃 9.4 s vs 34.0 s。 byte 相間隔拉到 ~50 ms,踩中 SMBus 25–35 ms timeout,裝置直接 NACK。實測全掃 9.4 s vs 34.0 s。
- ⚠️ **I2C 讀一律 Repeated START**(不是 STOP + START),否則 PMBus/SMBus 裝置(VRM、EFUSE)不理。 - ⚠️ **I2C 讀一律 Repeated START**(不是 STOP + START),否則 PMBus/SMBus 裝置(VRM、EFUSE)不理。
- ⚠️ **Script C 的 BMC USB service log 不進 master log**:改成
`journalctl ... > log/bmc_usb_net.log` 再複製到隨身碟,**那是唯一一份**。
收工後翻不到就先確認 job 目錄裡有沒有這個檔
- ⚠️ **VI2C 這條路的壞法是「只壞高位元組」**,不是整包壞掉。`11.98 V` 會變成 `32.00 V`
—— 正的、數量級也不誇張,**擋全一/全零的過濾完全攔不到**。寫任何 VI2C 讀值工具都要有
合理範圍檢查 + 重讀,光靠 `PDB_REJECT_FFFF` 那種是不夠的(`pwr_brick.sh` 的教訓)
- ⚠️ **PMBus 的 PAGE 不是只有 VRM 通道在用**:ADPM12200 把每個量測放在不同 PAGE
(Vin 9 / Iin 10 / Vout 2 / Iout 14 / Temp 18),沒寫 PAGE 就讀,回的是 `0xFFFF` 或
`0x0000`。`blanton_pwr_data.sh` 的 PDB 表 page 是 `-`,這就是它整張表 NA 的原因
- ⚠️ **`--runtime` 是整個 job 的總時限,不是每個 pass 的**:V1.1.7 起由 `config.ttl` 的
`SSD_RUNTIME`/`SSD_COUNT`、`USB_RUNTIME`/`USB_COUNT` 指定(COUNT 就是 `--passes`)。
`qfx5252-stress-*` 跑滿 RUNTIME 秒就停,**`--passes` 不會把它延長** —— `RUNTIME=600` 就是
10 分鐘,不是 600×COUNT。要 24 小時就填 `86400`。壓力提早結束時 `bgctl list` 數量變少是
唯一線索,**不會報警**。V1.1.8 起出貨預設改為 `RUNTIME=3600`(1 小時),2 天 soak 要填 `172800`
- ⚠️ **`utils/kill_all_process.ttl` 只有 `kill $(jobs -p)`,抓不到 systemd unit**:把壓力工作改成
`systemd-run` 之後,Script C 一定要補對應的 `systemctl stop <unit>`,否則它會活過 Script C 燒進
下一輪,**收工的溫度/功耗全部是在滿載下量的**。V1.1.8 已為 `mlucas-amm` 補上。
Script 4 也改用同一個 unit,但它**沒有收尾段**,所以那行 `systemctl stop` 得由人手動下
- ⚠️ **`config.ttl` 少一個變數會讓 macro 當場中止,不是當成 0**:`EN_timestamp`(V1.1.8 新增,
餵 Script A `logopen` 的第 5 個參數)、`BMC_USB_RUNTIME` 都是必要項。只更新 `.ttl` 卻沿用舊的
`config.ttl`,Script A 會停在 `logopen` 那一行
- ⚠️ **log 時間戳的「格式」不在腳本裡**:`EN_timestamp` 只決定開不開,格式在 Tera Term 的
Setup → Additional settings → Log,存在**那台電腦的 `TERATERM.INI`**。同一份 macro 在兩台機器上
可以產生不同格式的 log,跨機比對前先確認
- ⚠️ **多相 VRM 與 LTC2980 是同一批軌的兩條路**:`blanton_multiphase_margin.sh`(原生 i2c)
和 `margin.sh`(LTC2980 PMBus)都假設自己是唯一寫入者,**沒有互斥檢查**,只靠人記得
- ⚠️ **traffic 的計數器基準在 v0.7.0 變了**:`tx 100 length=512` → `tx 200 length=324`,
每 burst 的位元組數 +27%。PASS/FAIL 是成對交叉比對不受影響,但**絕對值不能跟舊 log 比**
- ⚠️ **Script 4(thermal/safety)沒有收尾**:`while 1` 之後就是檔尾。中斷後 DUT 停在
`port cd lb=mac` / `l2 learn off` / `test mode nr=yes`,`mlucas-avx2` 也還在背景。
下一個測試會在被污染的狀態上開始,而且 **`show interfaces status` 看不出來**。
收尾:`blanton_tr518.sh stop` + `kill $(jobs -p)` + **`systemctl stop mlucas-amm`**
(V1.1.8 起 CPU 壓力是 systemd unit,`kill $(jobs -p)` 收不掉,少這一行 CPU 會一直滿載)
- ⚠️ **Script 4 與 Script B 不能共用同一台 DUT**:兩者都會接管 `port cd` 的 loopback
- ⚠️ **`settings/*.conf` 的 `VNOM` 是實測中位數,不是規格值**(2026-08-30 起)。它同時是
`margin_status` 偏差 % 的分母、也是 `margin_set` 推算 high/low/OV/UV 的基準,所以改它會
同時移動「看到的數字」和「實際打出去的電壓」。**跨這個日期的 margin log 不能直接互比。**
- ⚠️ **SWB 的 margin profile 是 per-CONN 的**:`combo_SWB_CONN13~16_{high,low}` 各自的百分比
對應該片板子的軌。套到別的 CONN 會 margin 到錯的軌,而且**不會報錯**。CB 沒有專屬 profile,
用通用的 `combo_high3` / `combo_low3`
- ⚠️ **`margin_save` / `STORE_USER_ALL` 會永久寫 NVM**,斷電保留 → **測試流程中絕不執行**, - ⚠️ **`margin_save` / `STORE_USER_ALL` 會永久寫 NVM**,斷電保留 → **測試流程中絕不執行**,
以免覆蓋客戶出廠 config。`margin.sh` 的 auto-enable(`ON_OFF_CONFIG=0x1a`)只改 RAM,斷電復原。 以免覆蓋客戶出廠 config。`margin.sh` 的 auto-enable(`ON_OFF_CONFIG=0x1a`)只改 RAM,斷電復原。
v2.7.0 新增的 **`margin_save all` / `margin_save blanton` 一次寫 18 個 LTC2977**, v2.7.0 新增的 **`margin_save all` / `margin_save blanton` 一次寫 18 個 LTC2977**,
@@ -237,9 +339,17 @@ Tera Term 連 COM port (115200-8-N-1)
`Failed to execute the diagnostic command` 都照樣回 0),所以 `blanton_traffic_linespeed.sh` `Failed to execute the diagnostic command` 都照樣回 0),所以 `blanton_traffic_linespeed.sh`
是**比對輸出**而非看 exit code。另外 `bcmcmd` 一律要 `</dev/null` —— 是**比對輸出**而非看 exit code。另外 `bcmcmd` 一律要 `</dev/null` ——
否則它會吃掉 while 迴圈的 stdin,**只有第一個 VLAN 被設定**(V0.3.1 修過的 bug,很難看出來)。 否則它會吃掉 while 迴圈的 stdin,**只有第一個 VLAN 被設定**(V0.3.1 修過的 bug,很難看出來)。
**2026-09-07 `bcm_dsc_scan.sh` 又踩了同一個坑**:port 清單走 stdin,第一次 `bcmcmd` 就把剩下的吃光,
445 個 port 只掃了 1 個,而且 marker 與 dump 數量一起變少 → 比對通過、exit 0、log 看起來正常。
修法是迴圈改讀 fd 3(`done 3< "$PORTFILE"`)+ `bcmcmd ... < /dev/null`,並加一道
「實際迭代筆數 == 清單筆數」的檢查。**任何 `while ... done < file` 裡呼叫 `bcmcmd` 都要當它會讀 stdin。**
- ⚠️ **`stress_hhmd.py` / `stress_pcie.py` 已於 2026-08-17 由 KC 移除**(Status 表 ScriptB #5/#7)。 - ⚠️ **`stress_hhmd.py` / `stress_pcie.py` 已於 2026-08-17 由 KC 移除**(Status 表 ScriptB #5/#7)。
Script B 現在是 **8 個背景 job**(1 mlucas + 5 mem + ssd + usb),不是 10 個。 Script B 現在是 **8 個背景 job**(1 mlucas + 5 mem + ssd + usb),不是 10 個。
I2C/PCIe 的持續讀取壓力目前沒有替代品。 I2C/PCIe 的持續讀取壓力目前沒有替代品。
- ⚠️ **`pause` 是停 macro,`sleep` 是停 DUT**(V1.2.0 起 A/B/C 一律用後者):`pause N` 期間 macro 不理會
DUT,shell 是閒著的,等於用猜的估上一個指令跑多久;`sendln "sleep N"` + `wait prompt_sonic_root`
把等待放到 DUT 上,prompt 回來才繼續,兩邊不會走散,而且這一段會帶時戳進 log。
**Script 4 / Script 5 尚未轉換,仍在用 `pause`**;B/C 開頭那個 `pause 1` 也保留(登入前沒有 prompt 可等)
- ⚠️ **soak 迴圈沒有 `pause`**:取樣間隔不是 Status 表寫的 10 分鐘,而是取決於指令執行時間。 - ⚠️ **soak 迴圈沒有 `pause`**:取樣間隔不是 Status 表寫的 10 分鐘,而是取決於指令執行時間。
(`-u 0` 已於 `491e807` 移除,A/B/C 現在都跑兩個 switch unit。) (`-u 0` 已於 `491e807` 移除,A/B/C 現在都跑兩個 switch unit。)
- 🔒 **`.sh` / `.conf` 一定要 LF**。CRLF 的 shell script 在 SONiC 上直接掛(`$'\r': command not found`); - 🔒 **`.sh` / `.conf` 一定要 LF**。CRLF 的 shell script 在 SONiC 上直接掛(`$'\r': command not found`);
@@ -249,10 +359,24 @@ Tera Term 連 COM port (115200-8-N-1)
(`--renormalize` 只在進 index 的路上轉換)。驗證要看 byte:`grep -rlU $'\r' <dir>` (`--renormalize` 只在進 index 的路上轉換)。驗證要看 byte:`grep -rlU $'\r' <dir>`
- ⚠️ **TTL 的 `timeout` 是全域的**:`timeout = N` 之後**每一個** `wait` 都被限制在 N 秒。逾時的 `wait` - ⚠️ **TTL 的 `timeout` 是全域的**:`timeout = N` 之後**每一個** `wait` 都被限制在 N 秒。逾時的 `wait`
直接返回而沒吃到 prompt,下一個指令就在前一個還沒跑完時送出,之後整輪錯開一拍。**設了一定要 直接返回而沒吃到 prompt,下一個指令就在前一個還沒跑完時送出,之後整輪錯開一拍。**設了一定要
配一個 `timeout = 0` 還原**(`wait_init.ttl` 60→0;Script B 的 cdc_ncm 探測 15→0 在 `:skip_ping`) 配一個 `timeout = 0` 還原**(`wait_init.ttl` 60→0;Script B 的 cdc_ncm 探測 15→0 兩處各還原一次
—— `endif` 之後走成功路徑、`:skip_ping` 走跳過路徑;Script 5 同一段**直接還原在 `if` 之前**,
一行涵蓋兩條路徑,因為它的 ping 區塊要 `wait` 一個 `sleep 10`,DUT 一忙就逼近 15 s 上限)
- ⚠️ **`goto` 的標籤沒定義,Tera Term 是執行到才報錯**:Script 5 從 Script B 抄 cdc_ncm 探測時
只帶走 `goto skip_ping` 沒帶 `:skip_ping`,平常測不出來 —— 只有真的抓不到 NCM 介面走進那條分支
才會跳錯誤視窗停住整個循環(已補)。抄段落過去時**連標籤一起抄**
- ⚠️ **兩張管理網卡同網段會 ARP flux**:`mgmt_ping_monitor.sh` 讓 eth0/eth1 同時 up,同一個 /24 下 - ⚠️ **兩張管理網卡同網段會 ARP flux**:`mgmt_ping_monitor.sh` 讓 eth0/eth1 同時 up,同一個 /24 下
對端 ARP 可能由任一張卡回應,回包落在沒送封包的那張。`ARP_STRICT=1` 擋掉;判讀時看 `RESULT` 行的 對端 ARP 可能由任一張卡回應,回包落在沒送封包的那張。`ARP_STRICT=1` 擋掉;判讀時看 `RESULT` 行的
`nic_tx`/`nic_rx`(該卡自己的 packet delta)—— **ping 成功但 `nic_tx` 接近 0 = 封包從另一張卡出去的** `nic_tx`/`nic_rx`(該卡自己的 packet delta)—— **ping 成功但 `nic_tx` 接近 0 = 封包從另一張卡出去的**
- ⚠️ **`prbs get` 印的每一行是資料,不是 shell 的錯誤訊息**:沒鎖上的 lane 會印 `PRBS Error!`,
而 `blanton_ber.sh` 從 v1.0.0 就用 `grep -i 'ERROR|Invalid|...'` 掃**整份輸出**判斷「指令被拒絕」——
於是**跑得好好的 init 會報 `the BCM shell rejected 'phydiag ... prbs get'`**,而且因為提早 return,
那段「數 PRBS OK / 總數」的檢查根本沒跑,**你看到一個假錯誤,卻看不到哪幾條 lane 真的沒鎖**。
v1.1.1 已把 per-lane 行排除在錯誤掃描外、改成大小寫敏感,並把真正的拒絕訊息印出來
- ⚠️ **BER 的 `clear` 才是把 lane 放回正常運作的動作**:V1.2.1 起 Script A 在第一輪流量**之前**跑 BER,
而 `blanton_ber.sh clear` 與緊接著的 `blanton_traffic_linespeed ps` 之間**沒有任何 settle**。
Script C 是流量報表之後才跑 BER,沒有這個順序問題。第一次上機時比對兩邊的 traffic report ——
**Script A 有 NA/FAIL 而 Script C 沒有,就是 lane 還沒回穩**,在 `clear` 後補一個 `sleep` 即可
- ⚠️ **PRBS 跑起來時 `show interfaces status` 會顯示 DOWN**,那是 link 離開正常運作模式,不是故障。 - ⚠️ **PRBS 跑起來時 `show interfaces status` 會顯示 DOWN**,那是 link 離開正常運作模式,不是故障。
`port_prbs_monitor.sh` 的 `start` 因此刻意不印 port status(避免測試員誤判),只在 `prbs clear` 之後的報表裡印 `port_prbs_monitor.sh` 的 `start` 因此刻意不印 port status(避免測試員誤判),只在 `prbs clear` 之後的報表裡印
- ⚠️ **`ip -s link` 的欄位順序是 `bytes packets errors ...`**,要 packet 數取的是**第 2 欄**不是第 1 欄 - ⚠️ **`ip -s link` 的欄位順序是 `bytes packets errors ...`**,要 packet 數取的是**第 2 欄**不是第 1 欄
@@ -292,7 +416,14 @@ Tera Term 連 COM port (115200-8-N-1)
- `tools/` — Host / 離線端:`bcm_mibpair_report_V1.1.0.py`(drivshell log → per-pair 報表)、 - `tools/` — Host / 離線端:`bcm_mibpair_report_V1.1.0.py`(drivshell log → per-pair 報表)、
`traffic_loopback_*.txt`(bcmcmd 原始指令表,`blanton_traffic_linespeed.sh` 是其 bash 版, `traffic_loopback_*.txt`(bcmcmd 原始指令表,`blanton_traffic_linespeed.sh` 是其 bash 版,
**改 loopback 線路時兩邊要同步**)、`100G_PRBS.txt` / `TR518.txt` / `fan_ctrl.txt` **改 loopback 線路時兩邊要同步**)、`100G_PRBS.txt` / `TR518.txt` / `fan_ctrl.txt`
(上機手貼用的原始指令;PRBS 已有 `.sh`,TR518 尚未腳本化) (上機手貼用的原始指令;PRBS / TR518 / 100G traffic / multiphase normal 都已有對應 `.sh`)
- `publish/` — `publish.sh`(打包工具,**進 git**)+ `Script_ABC_Blanton_<Ver>/` 產出(**gitignored**) - `publish/` — `publish.sh`(打包工具,**進 git**)+ `Script_ABC_Blanton_<Ver>/` 產出(**gitignored**)
- `tmp/` — 🚫 gitignored:**還沒上機驗證**的腳本暫存區(目前 `blanton_reboottest.sh`)。
上機測過才搬進 `src/Script_ABC_Blanton/Blanton_Script/` 並進 git —— 未驗證的東西不該混在
交付包裡,publish 時測試員分不出哪支能信
- `src/Script_ABC_Blanton/hammer/` — 🚫 gitignored:mlucas 的 ELF binary(~99 MB,avx512 / avx2 /
avx / sse2 / generic-c)。Script B 與 Script 4 會 `chmod +x` 後執行,但**它由 DUT image 帶**,
不從這個 repo 發 —— binary 一旦進 git 就永久留在 history,每個 clone 都要付這個代價。
`publish.sh` 也把它排除,所以打包結果不會因為誰的工作目錄有沒有 binary 而變成 100 MB
- `secret/` — 🚫 gitignored(除 `README.md` 與 `*.example`):DUT 帳密、per-unit BDF 覆寫、COM 設定 - `secret/` — 🚫 gitignored(除 `README.md` 與 `*.example`):DUT 帳密、per-unit BDF 覆寫、COM 設定
- `For_AI/` — 🚫 gitignored:AI 協作素材(波形截圖、草稿筆記) - `For_AI/` — 🚫 gitignored:AI 協作素材(波形截圖、草稿筆記)
Binary file not shown.
+172
View File
@@ -0,0 +1,172 @@
<mxfile host="app.diagrams.net" agent="Blanton_TTL_Script/tools" version="24.7.17">
<diagram id="blanton-test-flow" name="Blanton Test Flow">
<mxGraphModel dx="1400" dy="900" grid="1" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="1" pageScale="1" pageWidth="1670" pageHeight="1785" math="0" shadow="0">
<root>
<mxCell id="0"/>
<mxCell id="1" parent="0"/>
<mxCell id="n11" value="Blanton (Project Helios) — 測試流程" style="text;html=1;align=center;verticalAlign=middle;fontSize=20;fontStyle=1;" vertex="1" parent="1"><mxGeometry x="30" y="20" width="1610" height="34" as="geometry"/></mxCell>
<mxCell id="n12" value="來源:src/Script_ABC_Blanton/{1,2,3}_Blanton_Script_*.ttl(Script A V1.1.3) · ⟨…⟩ = 由 config.ttl 的旗標決定" style="text;html=1;align=center;verticalAlign=middle;fontSize=11;fontColor=#666666;" vertex="1" parent="1"><mxGeometry x="30" y="54" width="1610" height="20" as="geometry"/></mxCell>
<mxCell id="n13" value="Script A — Pre-test(基線 / 環境建立)" style="swimlane;html=1;startSize=34;fillColor=#ffffff;strokeColor=#4d4d4d;fontSize=14;fontStyle=1;horizontal=1;" vertex="1" parent="1"><mxGeometry x="30" y="96" width="380" height="1459" as="geometry"/></mxCell>
<mxCell id="n14" value="&lt;b&gt;include config.ttl&lt;/b&gt;&lt;br&gt;project_name, strTestcase, EN_Margin,&lt;br&gt;EN_log, FAN_SPEED, SWB_UNIT0/1" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#fff2cc;strokeColor=#d6b656;align=left;spacingLeft=8;verticalAlign=middle;fontSize=11;" vertex="1" parent="n13"><mxGeometry x="18" y="44" width="344" height="64" as="geometry"/></mxCell>
<mxCell id="n15" value="&lt;b&gt;logopen&lt;/b&gt; Logs/&amp;lt;proj&amp;gt;_&amp;lt;case&amp;gt;_&amp;lt;ts&amp;gt;.log&lt;br&gt;&lt;i&gt;⟨EN_log = 1⟩&lt;/i&gt;" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#fff2cc;strokeColor=#d6b656;align=left;spacingLeft=8;verticalAlign=middle;fontSize=11;" vertex="1" parent="n13"><mxGeometry x="18" y="124" width="344" height="49" as="geometry"/></mxCell>
<mxCell id="e16" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;strokeColor=#4d4d4d;" edge="1" parent="1" source="n14" target="n15"><mxGeometry relative="1" as="geometry"/></mxCell>
<mxCell id="n17" value="&lt;b&gt;Root Login&lt;/b&gt;&lt;br&gt;login → sudo -i → root@sonic:~#" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;align=left;spacingLeft=8;verticalAlign=middle;fontSize=11;" vertex="1" parent="n13"><mxGeometry x="18" y="189" width="344" height="49" as="geometry"/></mxCell>
<mxCell id="e18" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;strokeColor=#4d4d4d;" edge="1" parent="1" source="n15" target="n17"><mxGeometry relative="1" as="geometry"/></mxCell>
<mxCell id="n19" value="&lt;b&gt;Pre Setting&lt;/b&gt;&lt;br&gt;date -s 對時 · rm /host/hw-eval/jobs/*" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;align=left;spacingLeft=8;verticalAlign=middle;fontSize=11;" vertex="1" parent="n13"><mxGeometry x="18" y="254" width="344" height="49" as="geometry"/></mxCell>
<mxCell id="e20" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;strokeColor=#4d4d4d;" edge="1" parent="1" source="n17" target="n19"><mxGeometry relative="1" as="geometry"/></mxCell>
<mxCell id="n21" value="&lt;b&gt;HW Test Session — 收前一輪&lt;/b&gt;&lt;br&gt;hw-test-session finish · bgctl reset --yes&lt;br&gt;bgctl stop --all · &lt;b&gt;bgctl list 必須空&lt;/b&gt;" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#f8cecc;strokeColor=#b85450;align=left;spacingLeft=8;verticalAlign=middle;fontSize=11;" vertex="1" parent="n13"><mxGeometry x="18" y="319" width="344" height="64" as="geometry"/></mxCell>
<mxCell id="e22" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;strokeColor=#4d4d4d;" edge="1" parent="1" source="n19" target="n21"><mxGeometry relative="1" as="geometry"/></mxCell>
<mxCell id="n23" value="&lt;b&gt;hw-test-session start&lt;/b&gt;" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;align=left;spacingLeft=8;verticalAlign=middle;fontSize=11;" vertex="1" parent="n13"><mxGeometry x="18" y="399" width="344" height="34" as="geometry"/></mxCell>
<mxCell id="e24" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;strokeColor=#4d4d4d;" edge="1" parent="1" source="n21" target="n23"><mxGeometry relative="1" as="geometry"/></mxCell>
<mxCell id="n25" value="&lt;b&gt;FAN SPEED&lt;/b&gt;&lt;br&gt;max31790 rebind ×2 → fan-speed-control.sh $FAN_SPEED" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;align=left;spacingLeft=8;verticalAlign=middle;fontSize=11;" vertex="1" parent="n13"><mxGeometry x="18" y="449" width="344" height="49" as="geometry"/></mxCell>
<mxCell id="e26" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;strokeColor=#4d4d4d;" edge="1" parent="1" source="n23" target="n25"><mxGeometry relative="1" as="geometry"/></mxCell>
<mxCell id="n27" value="&lt;b&gt;Wait DUT Init&lt;/b&gt; utils/wait_init.ttl&lt;br&gt;輪詢 bcmcmd ps,兩 unit link up ≥ 216&lt;br&gt;&lt;i&gt;⟨SWB_UNIT0 / SWB_UNIT1⟩ · 無逾時出口&lt;/i&gt;" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#fff2cc;strokeColor=#d6b656;align=left;spacingLeft=8;verticalAlign=middle;fontSize=11;" vertex="1" parent="n13"><mxGeometry x="18" y="514" width="344" height="64" as="geometry"/></mxCell>
<mxCell id="e28" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;strokeColor=#4d4d4d;" edge="1" parent="1" source="n25" target="n27"><mxGeometry relative="1" as="geometry"/></mxCell>
<mxCell id="n29" value="&lt;b&gt;DUT Info&lt;/b&gt;&lt;br&gt;show boot/version/platform · fwutil · syseeprom&lt;br&gt;ssdhealth · TPM · NVMe" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;align=left;spacingLeft=8;verticalAlign=middle;fontSize=11;" vertex="1" parent="n13"><mxGeometry x="18" y="594" width="344" height="64" as="geometry"/></mxCell>
<mxCell id="e30" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;strokeColor=#4d4d4d;" edge="1" parent="1" source="n27" target="n29"><mxGeometry relative="1" as="geometry"/></mxCell>
<mxCell id="n31" value="&lt;b&gt;BMC&lt;/b&gt; bmc-first-enroll · version · status" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;align=left;spacingLeft=8;verticalAlign=middle;fontSize=11;" vertex="1" parent="n13"><mxGeometry x="18" y="674" width="344" height="34" as="geometry"/></mxCell>
<mxCell id="e32" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;strokeColor=#4d4d4d;" edge="1" parent="1" source="n29" target="n31"><mxGeometry relative="1" as="geometry"/></mxCell>
<mxCell id="n33" value="&lt;b&gt;Load Shell Script&lt;/b&gt;&lt;br&gt;source blanton_fpga_pcimem / cb_i2c / icb_vi2c /&lt;br&gt;temp_sensor / pwr_data / traffic_linespeed / margin" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;align=left;spacingLeft=8;verticalAlign=middle;fontSize=11;" vertex="1" parent="n13"><mxGeometry x="18" y="724" width="344" height="64" as="geometry"/></mxCell>
<mxCell id="e34" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;strokeColor=#4d4d4d;" edge="1" parent="1" source="n31" target="n33"><mxGeometry relative="1" as="geometry"/></mxCell>
<mxCell id="n35" value="&lt;b&gt;CLEAR PCIe Error&lt;/b&gt; ×7&lt;br&gt;TH6_SWB0 · TH6_SWB1 · FPGA · BMC · DDR · I210 · SSD" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;align=left;spacingLeft=8;verticalAlign=middle;fontSize=11;" vertex="1" parent="n13"><mxGeometry x="18" y="804" width="344" height="49" as="geometry"/></mxCell>
<mxCell id="e36" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;strokeColor=#4d4d4d;" edge="1" parent="1" source="n33" target="n35"><mxGeometry relative="1" as="geometry"/></mxCell>
<mxCell id="n37" value="&lt;b&gt;PCIe tree / link / bandwidth&lt;/b&gt; utils/pcie_bus.ttl" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;align=left;spacingLeft=8;verticalAlign=middle;fontSize=11;" vertex="1" parent="n13"><mxGeometry x="18" y="869" width="344" height="34" as="geometry"/></mxCell>
<mxCell id="e38" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;strokeColor=#4d4d4d;" edge="1" parent="1" source="n35" target="n37"><mxGeometry relative="1" as="geometry"/></mxCell>
<mxCell id="n39" value="&lt;b&gt;Check Margin&lt;/b&gt; margin_status_all.sh(9 顆 LTC2980)&lt;br&gt;&lt;i&gt;⟨EN_Margin = 1⟩&lt;/i&gt;" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#fff2cc;strokeColor=#d6b656;align=left;spacingLeft=8;verticalAlign=middle;fontSize=11;" vertex="1" parent="n13"><mxGeometry x="18" y="919" width="344" height="49" as="geometry"/></mxCell>
<mxCell id="e40" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;strokeColor=#4d4d4d;" edge="1" parent="1" source="n37" target="n39"><mxGeometry relative="1" as="geometry"/></mxCell>
<mxCell id="n41" value="&lt;b&gt;TAKE DATA&lt;/b&gt; setup_pmon.ttl(9 項)+ show_dmesg.ttl" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;align=left;spacingLeft=8;verticalAlign=middle;fontSize=11;" vertex="1" parent="n13"><mxGeometry x="18" y="984" width="344" height="34" as="geometry"/></mxCell>
<mxCell id="e42" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;strokeColor=#4d4d4d;" edge="1" parent="1" source="n39" target="n41"><mxGeometry relative="1" as="geometry"/></mxCell>
<mxCell id="n43" value="&lt;b&gt;10G/1G MGMT Ping&lt;/b&gt;&lt;br&gt;start → 30s → report → clear" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;align=left;spacingLeft=8;verticalAlign=middle;fontSize=11;" vertex="1" parent="n13"><mxGeometry x="18" y="1034" width="344" height="49" as="geometry"/></mxCell>
<mxCell id="e44" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;strokeColor=#4d4d4d;" edge="1" parent="1" source="n41" target="n43"><mxGeometry relative="1" as="geometry"/></mxCell>
<mxCell id="n45" value="&lt;b&gt;NFC Test&lt;/b&gt;&lt;br&gt;start → status → 30s → stop → report" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;align=left;spacingLeft=8;verticalAlign=middle;fontSize=11;" vertex="1" parent="n13"><mxGeometry x="18" y="1099" width="344" height="49" as="geometry"/></mxCell>
<mxCell id="e46" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;strokeColor=#4d4d4d;" edge="1" parent="1" source="n43" target="n45"><mxGeometry relative="1" as="geometry"/></mxCell>
<mxCell id="n47" value="&lt;b&gt;100G Port Status&lt;/b&gt; Ethernet513 / 514" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;align=left;spacingLeft=8;verticalAlign=middle;fontSize=11;" vertex="1" parent="n13"><mxGeometry x="18" y="1164" width="344" height="34" as="geometry"/></mxCell>
<mxCell id="e48" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;strokeColor=#4d4d4d;" edge="1" parent="1" source="n45" target="n47"><mxGeometry relative="1" as="geometry"/></mxCell>
<mxCell id="n49" value="&lt;b&gt;100G PRBS&lt;/b&gt; port_prbs_monitor.sh&lt;br&gt;&lt;i&gt;整段註解 — bring-up 中&lt;/i&gt;" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#f5f5f5;strokeColor=#999999;dashed=1;align=left;spacingLeft=8;verticalAlign=middle;fontSize=11;fontColor=#808080;" vertex="1" parent="n13"><mxGeometry x="18" y="1214" width="344" height="49" as="geometry"/></mxCell>
<mxCell id="e50" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;strokeColor=#4d4d4d;" edge="1" parent="1" source="n47" target="n49"><mxGeometry relative="1" as="geometry"/></mxCell>
<mxCell id="n51" value="&lt;b&gt;First Traffic Test(基線)&lt;/b&gt;&lt;br&gt;ps → init → clear → 15s → show → start → 15s → report&lt;br&gt;&lt;i&gt;⟨SWB_UNIT⟩ 兩邊 / -u 0 / -u 1 / skip&lt;/i&gt;" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#fff2cc;strokeColor=#d6b656;align=left;spacingLeft=8;verticalAlign=middle;fontSize=11;" vertex="1" parent="n13"><mxGeometry x="18" y="1279" width="344" height="64" as="geometry"/></mxCell>
<mxCell id="e52" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;strokeColor=#4d4d4d;" edge="1" parent="1" source="n49" target="n51"><mxGeometry relative="1" as="geometry"/></mxCell>
<mxCell id="n53" value="&lt;b&gt;Show power-on uptime&lt;/b&gt;" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;align=left;spacingLeft=8;verticalAlign=middle;fontSize=11;" vertex="1" parent="n13"><mxGeometry x="18" y="1359" width="344" height="34" as="geometry"/></mxCell>
<mxCell id="e54" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;strokeColor=#4d4d4d;" edge="1" parent="1" source="n51" target="n53"><mxGeometry relative="1" as="geometry"/></mxCell>
<mxCell id="n55" value="messagebox 『Script A DONE / Start Script B』" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#ffe6cc;strokeColor=#d79b00;align=center;verticalAlign=middle;fontSize=11;fontStyle=1;" vertex="1" parent="n13"><mxGeometry x="18" y="1409" width="344" height="34" as="geometry"/></mxCell>
<mxCell id="e56" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;strokeColor=#4d4d4d;" edge="1" parent="1" source="n53" target="n55"><mxGeometry relative="1" as="geometry"/></mxCell>
<mxCell id="n57" value="Script B — Stress(壓力 soak,人為中斷才結束)" style="swimlane;html=1;startSize=34;fillColor=#ffffff;strokeColor=#4d4d4d;fontSize=14;fontStyle=1;horizontal=1;" vertex="1" parent="1"><mxGeometry x="440" y="96" width="380" height="1014" as="geometry"/></mxCell>
<mxCell id="n58" value="&lt;b&gt;include config.ttl&lt;/b&gt;" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#fff2cc;strokeColor=#d6b656;align=left;spacingLeft=8;verticalAlign=middle;fontSize=11;" vertex="1" parent="n57"><mxGeometry x="18" y="44" width="344" height="34" as="geometry"/></mxCell>
<mxCell id="n59" value="&lt;b&gt;CLEAR EVENT&lt;/b&gt;" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;align=left;spacingLeft=8;verticalAlign=middle;fontSize=11;" vertex="1" parent="n57"><mxGeometry x="18" y="94" width="344" height="34" as="geometry"/></mxCell>
<mxCell id="e60" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;strokeColor=#4d4d4d;" edge="1" parent="1" source="n58" target="n59"><mxGeometry relative="1" as="geometry"/></mxCell>
<mxCell id="n61" value="&lt;b&gt;AMD CPU Stress&lt;/b&gt; mlucas-avx2 -cpu 0:15" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;align=left;spacingLeft=8;verticalAlign=middle;fontSize=11;" vertex="1" parent="n57"><mxGeometry x="18" y="144" width="344" height="34" as="geometry"/></mxCell>
<mxCell id="e62" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;strokeColor=#4d4d4d;" edge="1" parent="1" source="n59" target="n61"><mxGeometry relative="1" as="geometry"/></mxCell>
<mxCell id="n63" value="&lt;b&gt;BMC DDR Stress&lt;/b&gt; bgctl run bmc-manager memtester" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;align=left;spacingLeft=8;verticalAlign=middle;fontSize=11;" vertex="1" parent="n57"><mxGeometry x="18" y="194" width="344" height="34" as="geometry"/></mxCell>
<mxCell id="e64" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;strokeColor=#4d4d4d;" edge="1" parent="1" source="n61" target="n63"><mxGeometry relative="1" as="geometry"/></mxCell>
<mxCell id="n65" value="&lt;b&gt;BMC Monitor&lt;/b&gt; bmc_monitor.sh start&lt;br&gt;free -m + I2C 寫入/讀回圖樣測試" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;align=left;spacingLeft=8;verticalAlign=middle;fontSize=11;" vertex="1" parent="n57"><mxGeometry x="18" y="244" width="344" height="49" as="geometry"/></mxCell>
<mxCell id="e66" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;strokeColor=#4d4d4d;" edge="1" parent="1" source="n63" target="n65"><mxGeometry relative="1" as="geometry"/></mxCell>
<mxCell id="n67" value="&lt;b&gt;DDR Memory Stress&lt;/b&gt; bgctl run memtester" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;align=left;spacingLeft=8;verticalAlign=middle;fontSize=11;" vertex="1" parent="n57"><mxGeometry x="18" y="309" width="344" height="34" as="geometry"/></mxCell>
<mxCell id="e68" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;strokeColor=#4d4d4d;" edge="1" parent="1" source="n65" target="n67"><mxGeometry relative="1" as="geometry"/></mxCell>
<mxCell id="n69" value="&lt;b&gt;SSD read/write&lt;/b&gt; bgctl run qfx5252-stress-ssd" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;align=left;spacingLeft=8;verticalAlign=middle;fontSize=11;" vertex="1" parent="n57"><mxGeometry x="18" y="359" width="344" height="34" as="geometry"/></mxCell>
<mxCell id="e70" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;strokeColor=#4d4d4d;" edge="1" parent="1" source="n67" target="n69"><mxGeometry relative="1" as="geometry"/></mxCell>
<mxCell id="n71" value="&lt;b&gt;USB read/write&lt;/b&gt; usb_target.sh -o dev → bgctl run&lt;br&gt;qfx5252-stress-usb" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;align=left;spacingLeft=8;verticalAlign=middle;fontSize=11;" vertex="1" parent="n57"><mxGeometry x="18" y="409" width="344" height="49" as="geometry"/></mxCell>
<mxCell id="e72" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;strokeColor=#4d4d4d;" edge="1" parent="1" source="n69" target="n71"><mxGeometry relative="1" as="geometry"/></mxCell>
<mxCell id="n73" value="&lt;b&gt;SHOW Background job&lt;/b&gt; bgctl list" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;align=left;spacingLeft=8;verticalAlign=middle;fontSize=11;" vertex="1" parent="n57"><mxGeometry x="18" y="474" width="344" height="34" as="geometry"/></mxCell>
<mxCell id="e74" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;strokeColor=#4d4d4d;" edge="1" parent="1" source="n71" target="n73"><mxGeometry relative="1" as="geometry"/></mxCell>
<mxCell id="n75" value="&lt;b&gt;BMC USB Test&lt;/b&gt; 偵測 cdc_ncm 介面" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;align=left;spacingLeft=8;verticalAlign=middle;fontSize=11;" vertex="1" parent="n57"><mxGeometry x="18" y="524" width="344" height="34" as="geometry"/></mxCell>
<mxCell id="e76" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;strokeColor=#4d4d4d;" edge="1" parent="1" source="n73" target="n75"><mxGeometry relative="1" as="geometry"/></mxCell>
<mxCell id="n77" value="&lt;b&gt;:skip_ping&lt;/b&gt; &lt;b&gt;timeout = 0&lt;/b&gt;(還原全域逾時)" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#f8cecc;strokeColor=#b85450;align=left;spacingLeft=8;verticalAlign=middle;fontSize=11;" vertex="1" parent="n57"><mxGeometry x="18" y="574" width="344" height="34" as="geometry"/></mxCell>
<mxCell id="e78" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;strokeColor=#4d4d4d;" edge="1" parent="1" source="n75" target="n77"><mxGeometry relative="1" as="geometry"/></mxCell>
<mxCell id="n79" value="&lt;b&gt;10G/1G MGMT Ping&lt;/b&gt; start → status" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;align=left;spacingLeft=8;verticalAlign=middle;fontSize=11;" vertex="1" parent="n57"><mxGeometry x="18" y="624" width="344" height="34" as="geometry"/></mxCell>
<mxCell id="e80" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;strokeColor=#4d4d4d;" edge="1" parent="1" source="n77" target="n79"><mxGeometry relative="1" as="geometry"/></mxCell>
<mxCell id="n81" value="&lt;b&gt;NFC Test&lt;/b&gt; start → status" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;align=left;spacingLeft=8;verticalAlign=middle;fontSize=11;" vertex="1" parent="n57"><mxGeometry x="18" y="674" width="344" height="34" as="geometry"/></mxCell>
<mxCell id="e82" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;strokeColor=#4d4d4d;" edge="1" parent="1" source="n79" target="n81"><mxGeometry relative="1" as="geometry"/></mxCell>
<mxCell id="n83" value="&lt;b&gt;100G Port&lt;/b&gt; lpmode off · config interface startup" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;align=left;spacingLeft=8;verticalAlign=middle;fontSize=11;" vertex="1" parent="n57"><mxGeometry x="18" y="724" width="344" height="34" as="geometry"/></mxCell>
<mxCell id="e84" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;strokeColor=#4d4d4d;" edge="1" parent="1" source="n81" target="n83"><mxGeometry relative="1" as="geometry"/></mxCell>
<mxCell id="n85" value="&lt;b&gt;100G PRBS&lt;/b&gt; &lt;i&gt;整段註解 — bring-up 中&lt;/i&gt;" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#f5f5f5;strokeColor=#999999;dashed=1;align=left;spacingLeft=8;verticalAlign=middle;fontSize=11;fontColor=#808080;" vertex="1" parent="n57"><mxGeometry x="18" y="774" width="344" height="34" as="geometry"/></mxCell>
<mxCell id="e86" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;strokeColor=#4d4d4d;" edge="1" parent="1" source="n83" target="n85"><mxGeometry relative="1" as="geometry"/></mxCell>
<mxCell id="n87" value="&lt;b&gt;Traffic START&lt;/b&gt;&lt;br&gt;ps → init → clear → 15s → show → start&lt;br&gt;&lt;i&gt;⟨SWB_UNIT⟩ 兩邊 / -u 0 / -u 1 / skip&lt;/i&gt;" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#fff2cc;strokeColor=#d6b656;align=left;spacingLeft=8;verticalAlign=middle;fontSize=11;" vertex="1" parent="n57"><mxGeometry x="18" y="824" width="344" height="64" as="geometry"/></mxCell>
<mxCell id="e88" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;strokeColor=#4d4d4d;" edge="1" parent="1" source="n85" target="n87"><mxGeometry relative="1" as="geometry"/></mxCell>
<mxCell id="n89" value="&lt;b&gt;while 1 — soak 監控迴圈&lt;/b&gt;&lt;br&gt;setup_pmon.ttl(9 項)&lt;br&gt;bgctl list + jobs&lt;br&gt;&lt;b&gt;pause 60&lt;/b&gt;&lt;br&gt;&lt;i&gt;V1.1.4 起 margin 移到 Script C&lt;/i&gt;" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#d5e8d4;strokeColor=#82b366;align=left;spacingLeft=8;verticalAlign=middle;fontSize=11;" vertex="1" parent="n57"><mxGeometry x="18" y="904" width="344" height="94" as="geometry"/></mxCell>
<mxCell id="e90" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;strokeColor=#4d4d4d;" edge="1" parent="1" source="n87" target="n89"><mxGeometry relative="1" as="geometry"/></mxCell>
<mxCell id="n91" value="Script C — Post-test(收尾 / 判定 / 收 log)" style="swimlane;html=1;startSize=34;fillColor=#ffffff;strokeColor=#4d4d4d;fontSize=14;fontStyle=1;horizontal=1;" vertex="1" parent="1"><mxGeometry x="850" y="96" width="380" height="1259" as="geometry"/></mxCell>
<mxCell id="n92" value="&lt;b&gt;include config.ttl&lt;/b&gt;" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#fff2cc;strokeColor=#d6b656;align=left;spacingLeft=8;verticalAlign=middle;fontSize=11;" vertex="1" parent="n91"><mxGeometry x="18" y="44" width="344" height="34" as="geometry"/></mxCell>
<mxCell id="n93" value="&lt;b&gt;Kill Process&lt;/b&gt; utils/kill_all_process.ttl&lt;br&gt;kill $(jobs -p) · bgctl stop --all ×2&lt;br&gt;停 BMC USB service · mgmt_ping stop · &lt;b&gt;nfc stop&lt;/b&gt;" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#f8cecc;strokeColor=#b85450;align=left;spacingLeft=8;verticalAlign=middle;fontSize=11;" vertex="1" parent="n91"><mxGeometry x="18" y="94" width="344" height="64" as="geometry"/></mxCell>
<mxCell id="e94" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;strokeColor=#4d4d4d;" edge="1" parent="1" source="n92" target="n93"><mxGeometry relative="1" as="geometry"/></mxCell>
<mxCell id="n95" value="&lt;b&gt;100G PRBS STOP&lt;/b&gt; &lt;i&gt;整段註解&lt;/i&gt;" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#f5f5f5;strokeColor=#999999;dashed=1;align=left;spacingLeft=8;verticalAlign=middle;fontSize=11;fontColor=#808080;" vertex="1" parent="n91"><mxGeometry x="18" y="174" width="344" height="34" as="geometry"/></mxCell>
<mxCell id="e96" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;strokeColor=#4d4d4d;" edge="1" parent="1" source="n93" target="n95"><mxGeometry relative="1" as="geometry"/></mxCell>
<mxCell id="n97" value="&lt;b&gt;TAKE DATA&lt;/b&gt; setup_pmon.ttl + show_dmesg.ttl" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;align=left;spacingLeft=8;verticalAlign=middle;fontSize=11;" vertex="1" parent="n91"><mxGeometry x="18" y="224" width="344" height="34" as="geometry"/></mxCell>
<mxCell id="e98" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;strokeColor=#4d4d4d;" edge="1" parent="1" source="n95" target="n97"><mxGeometry relative="1" as="geometry"/></mxCell>
<mxCell id="n99" value="&lt;b&gt;Check PCIe error counters&lt;/b&gt; ×7(同 Script A)" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;align=left;spacingLeft=8;verticalAlign=middle;fontSize=11;" vertex="1" parent="n91"><mxGeometry x="18" y="274" width="344" height="34" as="geometry"/></mxCell>
<mxCell id="e100" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;strokeColor=#4d4d4d;" edge="1" parent="1" source="n97" target="n99"><mxGeometry relative="1" as="geometry"/></mxCell>
<mxCell id="n101" value="&lt;b&gt;BMC DDR / BMC Monitor 取值&lt;/b&gt; cat bmc_ddr.log · bmc_poll.log" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;align=left;spacingLeft=8;verticalAlign=middle;fontSize=11;" vertex="1" parent="n91"><mxGeometry x="18" y="324" width="344" height="34" as="geometry"/></mxCell>
<mxCell id="e102" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;strokeColor=#4d4d4d;" edge="1" parent="1" source="n99" target="n101"><mxGeometry relative="1" as="geometry"/></mxCell>
<mxCell id="n103" value="&lt;b&gt;BMC USB Test result&lt;/b&gt; journalctl" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;align=left;spacingLeft=8;verticalAlign=middle;fontSize=11;" vertex="1" parent="n91"><mxGeometry x="18" y="374" width="344" height="34" as="geometry"/></mxCell>
<mxCell id="e104" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;strokeColor=#4d4d4d;" edge="1" parent="1" source="n101" target="n103"><mxGeometry relative="1" as="geometry"/></mxCell>
<mxCell id="n105" value="&lt;b&gt;CHECK Stress results&lt;/b&gt;&lt;br&gt;cat mlucas / memtester / ssd / usb log" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;align=left;spacingLeft=8;verticalAlign=middle;fontSize=11;" vertex="1" parent="n91"><mxGeometry x="18" y="424" width="344" height="49" as="geometry"/></mxCell>
<mxCell id="e106" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;strokeColor=#4d4d4d;" edge="1" parent="1" source="n103" target="n105"><mxGeometry relative="1" as="geometry"/></mxCell>
<mxCell id="n107" value="&lt;b&gt;10G/1G MGMT result&lt;/b&gt; ip -s link show eth0/eth1 · cat log" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;align=left;spacingLeft=8;verticalAlign=middle;fontSize=11;" vertex="1" parent="n91"><mxGeometry x="18" y="489" width="344" height="34" as="geometry"/></mxCell>
<mxCell id="e108" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;strokeColor=#4d4d4d;" edge="1" parent="1" source="n105" target="n107"><mxGeometry relative="1" as="geometry"/></mxCell>
<mxCell id="n109" value="&lt;b&gt;NFC Test result&lt;/b&gt; nfc_polling.sh report" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;align=left;spacingLeft=8;verticalAlign=middle;fontSize=11;" vertex="1" parent="n91"><mxGeometry x="18" y="539" width="344" height="34" as="geometry"/></mxCell>
<mxCell id="e110" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;strokeColor=#4d4d4d;" edge="1" parent="1" source="n107" target="n109"><mxGeometry relative="1" as="geometry"/></mxCell>
<mxCell id="n111" value="&lt;b&gt;100G Port&lt;/b&gt; show interfaces status" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;align=left;spacingLeft=8;verticalAlign=middle;fontSize=11;" vertex="1" parent="n91"><mxGeometry x="18" y="589" width="344" height="34" as="geometry"/></mxCell>
<mxCell id="e112" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;strokeColor=#4d4d4d;" edge="1" parent="1" source="n109" target="n111"><mxGeometry relative="1" as="geometry"/></mxCell>
<mxCell id="n113" value="&lt;b&gt;CHECK Traffic counters&lt;/b&gt;&lt;br&gt;stop → report(per-pair TX/RX + ce0)&lt;br&gt;&lt;i&gt;⟨SWB_UNIT⟩ 兩邊 / -u 0 / -u 1 / skip&lt;/i&gt;" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#fff2cc;strokeColor=#d6b656;align=left;spacingLeft=8;verticalAlign=middle;fontSize=11;" vertex="1" parent="n91"><mxGeometry x="18" y="639" width="344" height="64" as="geometry"/></mxCell>
<mxCell id="e114" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;strokeColor=#4d4d4d;" edge="1" parent="1" source="n111" target="n113"><mxGeometry relative="1" as="geometry"/></mxCell>
<mxCell id="n115" value="&lt;b&gt;BER 掃描&lt;/b&gt; blanton_ber.sh&lt;br&gt;init → start → &lt;b&gt;sleep 30&lt;/b&gt; → report → stop → clear&lt;br&gt;&lt;i&gt;⟨SWB_UNIT⟩ · sleep 30 要與 BER_INTERVAL 同步&lt;/i&gt;" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#fff2cc;strokeColor=#d6b656;align=left;spacingLeft=8;verticalAlign=middle;fontSize=11;" vertex="1" parent="n91"><mxGeometry x="18" y="719" width="344" height="64" as="geometry"/></mxCell>
<mxCell id="e116" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;strokeColor=#4d4d4d;" edge="1" parent="1" source="n113" target="n115"><mxGeometry relative="1" as="geometry"/></mxCell>
<mxCell id="n117" value="&lt;b&gt;NVMe Err Info&lt;/b&gt; nvme smart-log · smartctl -x" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;align=left;spacingLeft=8;verticalAlign=middle;fontSize=11;" vertex="1" parent="n91"><mxGeometry x="18" y="799" width="344" height="34" as="geometry"/></mxCell>
<mxCell id="e118" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;strokeColor=#4d4d4d;" edge="1" parent="1" source="n115" target="n117"><mxGeometry relative="1" as="geometry"/></mxCell>
<mxCell id="n119" value="&lt;b&gt;show reboot-cause&lt;/b&gt;" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;align=left;spacingLeft=8;verticalAlign=middle;fontSize=11;" vertex="1" parent="n91"><mxGeometry x="18" y="849" width="344" height="34" as="geometry"/></mxCell>
<mxCell id="e120" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;strokeColor=#4d4d4d;" edge="1" parent="1" source="n117" target="n119"><mxGeometry relative="1" as="geometry"/></mxCell>
<mxCell id="n121" value="&lt;b&gt;Check Margin&lt;/b&gt; margin_status_all.sh(9 顆)&lt;br&gt;&lt;i&gt;⟨EN_Margin = 1⟩ · V1.1.4 從 Script B 移來&lt;/i&gt;" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#fff2cc;strokeColor=#d6b656;align=left;spacingLeft=8;verticalAlign=middle;fontSize=11;" vertex="1" parent="n91"><mxGeometry x="18" y="899" width="344" height="49" as="geometry"/></mxCell>
<mxCell id="e122" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;strokeColor=#4d4d4d;" edge="1" parent="1" source="n119" target="n121"><mxGeometry relative="1" as="geometry"/></mxCell>
<mxCell id="n123" value="&lt;b&gt;show uptime&lt;/b&gt;" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;align=left;spacingLeft=8;verticalAlign=middle;fontSize=11;" vertex="1" parent="n91"><mxGeometry x="18" y="964" width="344" height="34" as="geometry"/></mxCell>
<mxCell id="e124" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;strokeColor=#4d4d4d;" edge="1" parent="1" source="n121" target="n123"><mxGeometry relative="1" as="geometry"/></mxCell>
<mxCell id="n125" value="&lt;b&gt;Copy Stress Log to USB&lt;/b&gt;&lt;br&gt;usb_target.sh → mount → cp 各 log 進 jobs/&lt;br&gt;→ 帶時戳複製到 /mnt/usb/" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;align=left;spacingLeft=8;verticalAlign=middle;fontSize=11;" vertex="1" parent="n91"><mxGeometry x="18" y="1014" width="344" height="64" as="geometry"/></mxCell>
<mxCell id="e126" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;strokeColor=#4d4d4d;" edge="1" parent="1" source="n123" target="n125"><mxGeometry relative="1" as="geometry"/></mxCell>
<mxCell id="n127" value="&lt;b&gt;exit&lt;/b&gt; → wait 『Script done』&lt;br&gt;離開 hw-test-session 的 shell" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;align=left;spacingLeft=8;verticalAlign=middle;fontSize=11;" vertex="1" parent="n91"><mxGeometry x="18" y="1094" width="344" height="49" as="geometry"/></mxCell>
<mxCell id="e128" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;strokeColor=#4d4d4d;" edge="1" parent="1" source="n125" target="n127"><mxGeometry relative="1" as="geometry"/></mxCell>
<mxCell id="n129" value="&lt;b&gt;hw-test-session finish&lt;/b&gt; · bgctl reset --yes" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;align=left;spacingLeft=8;verticalAlign=middle;fontSize=11;" vertex="1" parent="n91"><mxGeometry x="18" y="1159" width="344" height="34" as="geometry"/></mxCell>
<mxCell id="e130" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;strokeColor=#4d4d4d;" edge="1" parent="1" source="n127" target="n129"><mxGeometry relative="1" as="geometry"/></mxCell>
<mxCell id="n131" value="messagebox 『GOOD JOB! Test Case DONE』" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#ffe6cc;strokeColor=#d79b00;align=center;verticalAlign=middle;fontSize=11;fontStyle=1;" vertex="1" parent="n91"><mxGeometry x="18" y="1209" width="344" height="34" as="geometry"/></mxCell>
<mxCell id="e132" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;strokeColor=#4d4d4d;" edge="1" parent="1" source="n129" target="n131"><mxGeometry relative="1" as="geometry"/></mxCell>
<mxCell id="n133" value="Script 4 — Thermal &amp;amp; Safety(獨立跑,不接 A/B/C)" style="swimlane;html=1;startSize=34;fillColor=#ffffff;strokeColor=#4d4d4d;fontSize=14;fontStyle=1;horizontal=1;" vertex="1" parent="1"><mxGeometry x="1260" y="96" width="380" height="929" as="geometry"/></mxCell>
<mxCell id="n134" value="&lt;b&gt;include config.ttl&lt;/b&gt;" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#fff2cc;strokeColor=#d6b656;align=left;spacingLeft=8;verticalAlign=middle;fontSize=11;" vertex="1" parent="n133"><mxGeometry x="18" y="44" width="344" height="34" as="geometry"/></mxCell>
<mxCell id="n135" value="&lt;b&gt;logopen&lt;/b&gt; &lt;i&gt;⟨EN_log = 1⟩&lt;/i&gt;" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#fff2cc;strokeColor=#d6b656;align=left;spacingLeft=8;verticalAlign=middle;fontSize=11;" vertex="1" parent="n133"><mxGeometry x="18" y="94" width="344" height="34" as="geometry"/></mxCell>
<mxCell id="e136" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;strokeColor=#4d4d4d;" edge="1" parent="1" source="n134" target="n135"><mxGeometry relative="1" as="geometry"/></mxCell>
<mxCell id="n137" value="&lt;b&gt;Root Login&lt;/b&gt; → sudo -i" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;align=left;spacingLeft=8;verticalAlign=middle;fontSize=11;" vertex="1" parent="n133"><mxGeometry x="18" y="144" width="344" height="34" as="geometry"/></mxCell>
<mxCell id="e138" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;strokeColor=#4d4d4d;" edge="1" parent="1" source="n135" target="n137"><mxGeometry relative="1" as="geometry"/></mxCell>
<mxCell id="n139" value="&lt;b&gt;Pre Setting&lt;/b&gt; mkdir ./logs · date -s · rm jobs/*" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;align=left;spacingLeft=8;verticalAlign=middle;fontSize=11;" vertex="1" parent="n133"><mxGeometry x="18" y="194" width="344" height="34" as="geometry"/></mxCell>
<mxCell id="e140" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;strokeColor=#4d4d4d;" edge="1" parent="1" source="n137" target="n139"><mxGeometry relative="1" as="geometry"/></mxCell>
<mxCell id="n141" value="&lt;b&gt;HW Test Session&lt;/b&gt; finish → bgctl reset/stop --all → list&lt;br&gt;→ start → log → status" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#f8cecc;strokeColor=#b85450;align=left;spacingLeft=8;verticalAlign=middle;fontSize=11;" vertex="1" parent="n133"><mxGeometry x="18" y="244" width="344" height="49" as="geometry"/></mxCell>
<mxCell id="e142" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;strokeColor=#4d4d4d;" edge="1" parent="1" source="n139" target="n141"><mxGeometry relative="1" as="geometry"/></mxCell>
<mxCell id="n143" value="&lt;b&gt;FAN SPEED&lt;/b&gt; max31790 rebind ×2 → fan-speed-control.sh" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;align=left;spacingLeft=8;verticalAlign=middle;fontSize=11;" vertex="1" parent="n133"><mxGeometry x="18" y="309" width="344" height="34" as="geometry"/></mxCell>
<mxCell id="e144" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;strokeColor=#4d4d4d;" edge="1" parent="1" source="n141" target="n143"><mxGeometry relative="1" as="geometry"/></mxCell>
<mxCell id="n145" value="&lt;b&gt;Wait DUT Init&lt;/b&gt; utils/wait_init.ttl&lt;br&gt;&lt;i&gt;無逾時出口&lt;/i&gt;" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#fff2cc;strokeColor=#d6b656;align=left;spacingLeft=8;verticalAlign=middle;fontSize=11;" vertex="1" parent="n133"><mxGeometry x="18" y="359" width="344" height="49" as="geometry"/></mxCell>
<mxCell id="e146" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;strokeColor=#4d4d4d;" edge="1" parent="1" source="n143" target="n145"><mxGeometry relative="1" as="geometry"/></mxCell>
<mxCell id="n147" value="&lt;b&gt;DUT Info&lt;/b&gt; boot/version/fwutil/system-memory/service&lt;br&gt;syseeprom · ssdhealth · TPM · NVMe" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;align=left;spacingLeft=8;verticalAlign=middle;fontSize=11;" vertex="1" parent="n133"><mxGeometry x="18" y="424" width="344" height="49" as="geometry"/></mxCell>
<mxCell id="e148" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;strokeColor=#4d4d4d;" edge="1" parent="1" source="n145" target="n147"><mxGeometry relative="1" as="geometry"/></mxCell>
<mxCell id="n149" value="&lt;b&gt;BMC&lt;/b&gt; enroll · version · status" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;align=left;spacingLeft=8;verticalAlign=middle;fontSize=11;" vertex="1" parent="n133"><mxGeometry x="18" y="489" width="344" height="34" as="geometry"/></mxCell>
<mxCell id="e150" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;strokeColor=#4d4d4d;" edge="1" parent="1" source="n147" target="n149"><mxGeometry relative="1" as="geometry"/></mxCell>
<mxCell id="n151" value="&lt;b&gt;CLEAR PCIe Error&lt;/b&gt; ×7 + ras-mc-ctl --summary" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;align=left;spacingLeft=8;verticalAlign=middle;fontSize=11;" vertex="1" parent="n133"><mxGeometry x="18" y="539" width="344" height="34" as="geometry"/></mxCell>
<mxCell id="e152" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;strokeColor=#4d4d4d;" edge="1" parent="1" source="n149" target="n151"><mxGeometry relative="1" as="geometry"/></mxCell>
<mxCell id="n153" value="&lt;b&gt;PCIe tree / link / bandwidth&lt;/b&gt;" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;align=left;spacingLeft=8;verticalAlign=middle;fontSize=11;" vertex="1" parent="n133"><mxGeometry x="18" y="589" width="344" height="34" as="geometry"/></mxCell>
<mxCell id="e154" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;strokeColor=#4d4d4d;" edge="1" parent="1" source="n151" target="n153"><mxGeometry relative="1" as="geometry"/></mxCell>
<mxCell id="n155" value="&lt;b&gt;TAKE DATA&lt;/b&gt; setup_pmon.ttl + show_dmesg.ttl" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;align=left;spacingLeft=8;verticalAlign=middle;fontSize=11;" vertex="1" parent="n133"><mxGeometry x="18" y="639" width="344" height="34" as="geometry"/></mxCell>
<mxCell id="e156" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;strokeColor=#4d4d4d;" edge="1" parent="1" source="n153" target="n155"><mxGeometry relative="1" as="geometry"/></mxCell>
<mxCell id="n157" value="&lt;b&gt;Full Load — CPU&lt;/b&gt;&lt;br&gt;chmod +x → mlucas-avx2 -s l -cpu 0:15 &amp;amp;" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;align=left;spacingLeft=8;verticalAlign=middle;fontSize=11;" vertex="1" parent="n133"><mxGeometry x="18" y="689" width="344" height="49" as="geometry"/></mxCell>
<mxCell id="e158" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;strokeColor=#4d4d4d;" edge="1" parent="1" source="n155" target="n157"><mxGeometry relative="1" as="geometry"/></mxCell>
<mxCell id="n159" value="&lt;b&gt;Full Load — 資料面&lt;/b&gt;&lt;br&gt;blanton_tr518.sh start(含 120s settle)" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#f8cecc;strokeColor=#b85450;align=left;spacingLeft=8;verticalAlign=middle;fontSize=11;" vertex="1" parent="n133"><mxGeometry x="18" y="754" width="344" height="49" as="geometry"/></mxCell>
<mxCell id="e160" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;strokeColor=#4d4d4d;" edge="1" parent="1" source="n157" target="n159"><mxGeometry relative="1" as="geometry"/></mxCell>
<mxCell id="n161" value="&lt;b&gt;while 1 — 熱 / 安規監控迴圈&lt;/b&gt;&lt;br&gt;setup_pmon.ttl(9 項)&lt;br&gt;TH6_SWB0 / SWB1_power_readback.sh&lt;br&gt;bgctl list + jobs&lt;br&gt;&lt;b&gt;pause 60&lt;/b&gt;" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#d5e8d4;strokeColor=#82b366;align=left;spacingLeft=8;verticalAlign=middle;fontSize=11;" vertex="1" parent="n133"><mxGeometry x="18" y="819" width="344" height="94" as="geometry"/></mxCell>
<mxCell id="e162" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;strokeColor=#4d4d4d;" edge="1" parent="1" source="n159" target="n161"><mxGeometry relative="1" as="geometry"/></mxCell>
<mxCell id="e163" value="人工啟動 Script B" style="edgeStyle=orthogonalEdgeStyle;rounded=1;html=1;strokeColor=#d79b00;strokeWidth=2;dashed=1;fontSize=10;fontColor=#d79b00;" edge="1" parent="1" source="n55" target="n58"><mxGeometry relative="1" as="geometry"/></mxCell>
<mxCell id="e164" value="soak 結束後人工中斷,啟動 Script C" style="edgeStyle=orthogonalEdgeStyle;rounded=1;html=1;strokeColor=#d79b00;strokeWidth=2;dashed=1;fontSize=10;fontColor=#d79b00;" edge="1" parent="1" source="n89" target="n92"><mxGeometry relative="1" as="geometry"/></mxCell>
<mxCell id="n165" value="圖例" style="text;html=1;align=left;verticalAlign=middle;fontSize=13;fontStyle=1;" vertex="1" parent="1"><mxGeometry x="30" y="1585" width="200" height="24" as="geometry"/></mxCell>
<mxCell id="n166" value="一般步驟" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;align=left;spacingLeft=8;verticalAlign=middle;fontSize=11;" vertex="1" parent="1"><mxGeometry x="30" y="1613" width="230" height="32" as="geometry"/></mxCell>
<mxCell id="n167" value="受 config.ttl 旗標影響" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#fff2cc;strokeColor=#d6b656;align=left;spacingLeft=8;verticalAlign=middle;fontSize=11;" vertex="1" parent="1"><mxGeometry x="280" y="1613" width="230" height="32" as="geometry"/></mxCell>
<mxCell id="n168" value="迴圈 / 持續執行" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#d5e8d4;strokeColor=#82b366;align=left;spacingLeft=8;verticalAlign=middle;fontSize=11;" vertex="1" parent="1"><mxGeometry x="530" y="1613" width="230" height="32" as="geometry"/></mxCell>
<mxCell id="n169" value="目前註解停用" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#f5f5f5;strokeColor=#999999;dashed=1;align=left;spacingLeft=8;verticalAlign=middle;fontSize=11;fontColor=#808080;" vertex="1" parent="1"><mxGeometry x="30" y="1655" width="230" height="32" as="geometry"/></mxCell>
<mxCell id="n170" value="狀態變更 / 需留意" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#f8cecc;strokeColor=#b85450;align=left;spacingLeft=8;verticalAlign=middle;fontSize=11;" vertex="1" parent="1"><mxGeometry x="280" y="1655" width="230" height="32" as="geometry"/></mxCell>
<mxCell id="n171" value="人工交接點" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#ffe6cc;strokeColor=#d79b00;align=center;verticalAlign=middle;fontSize=11;fontStyle=1;" vertex="1" parent="1"><mxGeometry x="530" y="1655" width="230" height="32" as="geometry"/></mxCell>
<mxCell id="n172" value="⚠️ 已知待辦:① 100G PRBS 三支腳本內呼叫仍註解(bring-up 中) ② wait_init.ttl 與風扇確認 wait 沒有逾時出口,起不來會無限等待 ③ Script C 的 sleep 30 需與 blanton_ber.sh 的 BER_INTERVAL 同步 ④ Script 4 沒有收尾段:中斷後 tr518 留下 port cd lb=mac / l2 learn off / test mode nr=yes,需手動 blanton_tr518.sh stop" style="text;html=1;align=left;verticalAlign=top;fontSize=11;fontColor=#b85450;" vertex="1" parent="1"><mxGeometry x="30" y="1703" width="1610" height="46" as="geometry"/></mxCell>
</root>
</mxGraphModel>
</diagram>
</mxfile>
+86 -86
View File
@@ -6,7 +6,7 @@ CB,CONN13,CH3,V1P8_ALW,1.8
CB,CONN13,CH4,PWR_APU_VDDIO_SUS,1.1 CB,CONN13,CH4,PWR_APU_VDDIO_SUS,1.1
CB,CONN13,CH5,PWR_VDD_MISC_RUN,0.75 CB,CONN13,CH5,PWR_VDD_MISC_RUN,0.75
CB,CONN13,CH6,PWR_APU_VDD_MEM_RUN,0.78 CB,CONN13,CH6,PWR_APU_VDD_MEM_RUN,0.78
CB,CONN13,CH7,V0P8_PHY2_DVDD,0.8 CB,CONN13,CH7,V0P8_PHY2_DVDD,0.816
CB,CONN13,CH8,V0P8_AVDD,0.8 CB,CONN13,CH8,V0P8_AVDD,0.8
CB,CONN13,CH9,V0P8_PHY,0.8 CB,CONN13,CH9,V0P8_PHY,0.8
CB,CONN13,CH10,V1P8_FPGA,1.8 CB,CONN13,CH10,V1P8_FPGA,1.8
@@ -14,132 +14,132 @@ CB,CONN13,CH11,V2P5_FPGA,2.5
CB,CONN13,CH12,V1P1_FPGA,1.1 CB,CONN13,CH12,V1P1_FPGA,1.1
CB,CONN13,CH13,P5V_STBY,5.0 CB,CONN13,CH13,P5V_STBY,5.0
CB,CONN13,CH14,P3V3_STBY,3.3 CB,CONN13,CH14,P3V3_STBY,3.3
CB,CONN13,CH15,V0P8_PHY2_AVDD,0.8 CB,CONN13,CH15,V0P8_PHY2_AVDD,0.816
SWB0,CONN13,CH0,P0V75_DVDD_47,0.75 SWB0,CONN13,CH0,P0V75_DVDD_47,0.75
SWB0,CONN13,CH1,P0V75_AVDD_47,0.75 SWB0,CONN13,CH1,P0V75_AVDD_47,0.756
SWB0,CONN13,CH2,P1V5_AVDD_47,1.5 SWB0,CONN13,CH2,P1V5_AVDD_47,1.524
SWB0,CONN13,CH3,P0V9_AVDD_47,0.9 SWB0,CONN13,CH3,P0V9_AVDD_47,0.915
SWB0,CONN13,CH4,P1V8_1,1.8 SWB0,CONN13,CH4,P1V8_1,1.816
SWB0,CONN13,CH5,PVDD3_3V_SYNTH_LDO_A3,3.3 SWB0,CONN13,CH5,PVDD3_3V_SYNTH_LDO_A3,3.38
SWB0,CONN13,CH6,PVDD3_3V_SYNTH_LDO_B1,3.3 SWB0,CONN13,CH6,PVDD3_3V_SYNTH_LDO_B1,3.38
SWB0,CONN13,CH7,P1V8_3,1.8 SWB0,CONN13,CH7,P1V8_3,1.816
SWB0,CONN13,CH8,P1V8_DVDDIO_3,1.8 SWB0,CONN13,CH8,P1V8_DVDDIO_3,1.8
SWB0,CONN13,CH9,P0V75_DVDD_39,0.75 SWB0,CONN13,CH9,P0V75_DVDD_39,0.75
SWB0,CONN13,CH10,P0V75_AVDD_39,0.75 SWB0,CONN13,CH10,P0V75_AVDD_39,0.756
SWB0,CONN13,CH11,P1V5_AVDD_39,1.5 SWB0,CONN13,CH11,P1V5_AVDD_39,1.524
SWB0,CONN13,CH12,P0V9_AVDD_39,0.9 SWB0,CONN13,CH12,P0V9_AVDD_39,0.915
SWB0,CONN13,CH13,PVDD1V5_2,1.5 SWB0,CONN13,CH13,PVDD1V5_2,1.5
SWB0,CONN13,CH14,PVDD1V8_DUT,1.8 SWB0,CONN13,CH14,PVDD1V8_DUT,1.8
SWB0,CONN13,CH15,PVDD_MDIO,1.2 SWB0,CONN13,CH15,PVDD_MDIO,1.2
SWB0,CONN14,CH0,P0V75_AVDD_7,0.75 SWB0,CONN14,CH0,P0V75_AVDD_7,0.756
SWB0,CONN14,CH1,P1V5_AVDD_7,1.5 SWB0,CONN14,CH1,P1V5_AVDD_7,1.524
SWB0,CONN14,CH2,P0V9_AVDD_7,0.9 SWB0,CONN14,CH2,P0V9_AVDD_7,0.915
SWB0,CONN14,CH3,P1V8_5,1.8 SWB0,CONN14,CH3,P1V8_5,1.816
SWB0,CONN14,CH4,P1V8_2,1.8 SWB0,CONN14,CH4,P1V8_2,1.816
SWB0,CONN14,CH5,PVDD3_3V_SYNTH_LDO_B2,3.3 SWB0,CONN14,CH5,PVDD3_3V_SYNTH_LDO_B2,3.38
SWB0,CONN14,CH6,PVDD3_3V_SYNTH_LDO_A2,3.3 SWB0,CONN14,CH6,PVDD3_3V_SYNTH_LDO_A2,3.38
SWB0,CONN14,CH7,PVDD3_3V_SYNTH_LDO_A1,3.3 SWB0,CONN14,CH7,PVDD3_3V_SYNTH_LDO_A1,3.38
SWB0,CONN14,CH8,PVDD1V5_TSC,1.5 SWB0,CONN14,CH8,PVDD1V5_TSC,1.516
SWB0,CONN14,CH9,PVDD1V5_ANLG,1.5 SWB0,CONN14,CH9,PVDD1V5_ANLG,1.516
SWB0,CONN14,CH10,NC,- SWB0,CONN14,CH10,NC,-
SWB0,CONN14,CH11,NC,- SWB0,CONN14,CH11,NC,-
SWB0,CONN14,CH12,PVDD1V5_1,1.5 SWB0,CONN14,CH12,PVDD1V5_1,1.5
SWB0,CONN14,CH13,NC,- SWB0,CONN14,CH13,NC,-
SWB0,CONN14,CH14,P1V8_DVDDIO_1,1.8 SWB0,CONN14,CH14,P1V8_DVDDIO_1,1.8
SWB0,CONN14,CH15,P0V75_DVDD_7,0.75 SWB0,CONN14,CH15,P0V75_DVDD_7,0.75
SWB0,CONN15,CH0,P1V5_AVDD_55,1.5 SWB0,CONN15,CH0,P1V5_AVDD_55,1.524
SWB0,CONN15,CH1,P0V9_AVDD_55,0.9 SWB0,CONN15,CH1,P0V9_AVDD_55,0.915
SWB0,CONN15,CH2,P0V75_DVDD_63,0.75 SWB0,CONN15,CH2,P0V75_DVDD_63,0.75
SWB0,CONN15,CH3,P0V75_AVDD_63,0.75 SWB0,CONN15,CH3,P0V75_AVDD_63,0.756
SWB0,CONN15,CH4,P1V5_AVDD_63,1.5 SWB0,CONN15,CH4,P1V5_AVDD_63,1.524
SWB0,CONN15,CH5,P0V9_AVDD_63,0.9 SWB0,CONN15,CH5,P0V9_AVDD_63,0.915
SWB0,CONN15,CH6,PVDD3_3V_SYNTH_LDO_B3,3.3 SWB0,CONN15,CH6,PVDD3_3V_SYNTH_LDO_B3,3.38
SWB0,CONN15,CH7,PVDD1V5_3,1.5 SWB0,CONN15,CH7,PVDD1V5_3,1.5
SWB0,CONN15,CH8,P0V85_STBY,0.85 SWB0,CONN15,CH8,P0V85_STBY,0.85
SWB0,CONN15,CH9,P1V8_STBY,1.8 SWB0,CONN15,CH9,P1V8_STBY,1.8
SWB0,CONN15,CH10,NC,- SWB0,CONN15,CH10,NC,-
SWB0,CONN15,CH11,P3V3_STBY,3.3 SWB0,CONN15,CH11,P3V3_STBY,3.3
SWB0,CONN15,CH12,PVDD0V9_2,0.9 SWB0,CONN15,CH12,PVDD0V9_2,0.91
SWB0,CONN15,CH13,P0V75_DVDD_55,0.75 SWB0,CONN15,CH13,P0V75_DVDD_55,0.75
SWB0,CONN15,CH14,P0V75_AVDD_55,0.75 SWB0,CONN15,CH14,P0V75_AVDD_55,0.756
SWB0,CONN15,CH15,P1V8_DVDDIO_4,1.8 SWB0,CONN15,CH15,P1V8_DVDDIO_4,1.8
SWB0,CONN16,CH0,PVDD1V5_0,1.5 SWB0,CONN16,CH0,PVDD1V5_0,1.5
SWB0,CONN16,CH1,P1V8_4,1.8 SWB0,CONN16,CH1,P1V8_4,1.816
SWB0,CONN16,CH2,PVDD3_3V_SYNTH_LDO_B5,3.3 SWB0,CONN16,CH2,PVDD3_3V_SYNTH_LDO_B5,3.38
SWB0,CONN16,CH3,PVDD3_3V_SYNTH_LDO_A5,3.3 SWB0,CONN16,CH3,PVDD3_3V_SYNTH_LDO_A5,3.38
SWB0,CONN16,CH4,PVDD3_3V_SYNTH_LDO_B4,3.3 SWB0,CONN16,CH4,PVDD3_3V_SYNTH_LDO_B4,3.38
SWB0,CONN16,CH5,PVDD3_3V_SYNTH_LDO_A4,3.3 SWB0,CONN16,CH5,PVDD3_3V_SYNTH_LDO_A4,3.38
SWB0,CONN16,CH6,P3V3,3.3 SWB0,CONN16,CH6,P3V3,3.327
SWB0,CONN16,CH7,PVDD0_8V_T3,0.8 SWB0,CONN16,CH7,PVDD0_8V_T3,0.82
SWB0,CONN16,CH8,P0V75_DVDD_1,0.75 SWB0,CONN16,CH8,P0V75_DVDD_1,0.75
SWB0,CONN16,CH9,P0V75_AVDD_1,0.75 SWB0,CONN16,CH9,P0V75_AVDD_1,0.756
SWB0,CONN16,CH10,P1V5_AVDD_1,1.5 SWB0,CONN16,CH10,P1V5_AVDD_1,1.524
SWB0,CONN16,CH11,P0V9_AVDD_1,0.9 SWB0,CONN16,CH11,P0V9_AVDD_1,0.915
SWB0,CONN16,CH12,PVDD0V9_0,0.9 SWB0,CONN16,CH12,PVDD0V9_0,0.915
SWB0,CONN16,CH13,PVDD0V9_1,0.9 SWB0,CONN16,CH13,PVDD0V9_1,0.91
SWB0,CONN16,CH14,PVDD0V9_3,0.9 SWB0,CONN16,CH14,PVDD0V9_3,0.915
SWB0,CONN16,CH15,PVDD1V2_T3,1.2 SWB0,CONN16,CH15,PVDD1V2_T3,1.224
SWB1,CONN13,CH0,P0V75_DVDD_47,0.75 SWB1,CONN13,CH0,P0V75_DVDD_47,0.75
SWB1,CONN13,CH1,P0V75_AVDD_47,0.75 SWB1,CONN13,CH1,P0V75_AVDD_47,0.756
SWB1,CONN13,CH2,P1V5_AVDD_47,1.5 SWB1,CONN13,CH2,P1V5_AVDD_47,1.524
SWB1,CONN13,CH3,P0V9_AVDD_47,0.9 SWB1,CONN13,CH3,P0V9_AVDD_47,0.915
SWB1,CONN13,CH4,P1V8_1,1.8 SWB1,CONN13,CH4,P1V8_1,1.816
SWB1,CONN13,CH5,PVDD3_3V_SYNTH_LDO_A3,3.3 SWB1,CONN13,CH5,PVDD3_3V_SYNTH_LDO_A3,3.38
SWB1,CONN13,CH6,PVDD3_3V_SYNTH_LDO_B1,3.3 SWB1,CONN13,CH6,PVDD3_3V_SYNTH_LDO_B1,3.38
SWB1,CONN13,CH7,P1V8_3,1.8 SWB1,CONN13,CH7,P1V8_3,1.816
SWB1,CONN13,CH8,P1V8_DVDDIO_3,1.8 SWB1,CONN13,CH8,P1V8_DVDDIO_3,1.8
SWB1,CONN13,CH9,P0V75_DVDD_39,0.75 SWB1,CONN13,CH9,P0V75_DVDD_39,0.75
SWB1,CONN13,CH10,P0V75_AVDD_39,0.75 SWB1,CONN13,CH10,P0V75_AVDD_39,0.756
SWB1,CONN13,CH11,P1V5_AVDD_39,1.5 SWB1,CONN13,CH11,P1V5_AVDD_39,1.524
SWB1,CONN13,CH12,P0V9_AVDD_39,0.9 SWB1,CONN13,CH12,P0V9_AVDD_39,0.915
SWB1,CONN13,CH13,PVDD1V5_2,1.5 SWB1,CONN13,CH13,PVDD1V5_2,1.5
SWB1,CONN13,CH14,PVDD1V8_DUT,1.8 SWB1,CONN13,CH14,PVDD1V8_DUT,1.8
SWB1,CONN13,CH15,PVDD_MDIO,1.2 SWB1,CONN13,CH15,PVDD_MDIO,1.2
SWB1,CONN14,CH0,P0V75_AVDD_7,0.75 SWB1,CONN14,CH0,P0V75_AVDD_7,0.756
SWB1,CONN14,CH1,P1V5_AVDD_7,1.5 SWB1,CONN14,CH1,P1V5_AVDD_7,1.524
SWB1,CONN14,CH2,P0V9_AVDD_7,0.9 SWB1,CONN14,CH2,P0V9_AVDD_7,0.915
SWB1,CONN14,CH3,P1V8_5,1.8 SWB1,CONN14,CH3,P1V8_5,1.816
SWB1,CONN14,CH4,P1V8_2,1.8 SWB1,CONN14,CH4,P1V8_2,1.816
SWB1,CONN14,CH5,PVDD3_3V_SYNTH_LDO_B2,3.3 SWB1,CONN14,CH5,PVDD3_3V_SYNTH_LDO_B2,3.38
SWB1,CONN14,CH6,PVDD3_3V_SYNTH_LDO_A2,3.3 SWB1,CONN14,CH6,PVDD3_3V_SYNTH_LDO_A2,3.38
SWB1,CONN14,CH7,PVDD3_3V_SYNTH_LDO_A1,3.3 SWB1,CONN14,CH7,PVDD3_3V_SYNTH_LDO_A1,3.38
SWB1,CONN14,CH8,PVDD1V5_TSC,1.5 SWB1,CONN14,CH8,PVDD1V5_TSC,1.516
SWB1,CONN14,CH9,PVDD1V5_ANLG,1.5 SWB1,CONN14,CH9,PVDD1V5_ANLG,1.516
SWB1,CONN14,CH10,NC,- SWB1,CONN14,CH10,NC,-
SWB1,CONN14,CH11,NC,- SWB1,CONN14,CH11,NC,-
SWB1,CONN14,CH12,PVDD1V5_1,1.5 SWB1,CONN14,CH12,PVDD1V5_1,1.5
SWB1,CONN14,CH13,NC,- SWB1,CONN14,CH13,NC,-
SWB1,CONN14,CH14,P1V8_DVDDIO_1,1.8 SWB1,CONN14,CH14,P1V8_DVDDIO_1,1.8
SWB1,CONN14,CH15,P0V75_DVDD_7,0.75 SWB1,CONN14,CH15,P0V75_DVDD_7,0.75
SWB1,CONN15,CH0,P1V5_AVDD_55,1.5 SWB1,CONN15,CH0,P1V5_AVDD_55,1.524
SWB1,CONN15,CH1,P0V9_AVDD_55,0.9 SWB1,CONN15,CH1,P0V9_AVDD_55,0.915
SWB1,CONN15,CH2,P0V75_DVDD_63,0.75 SWB1,CONN15,CH2,P0V75_DVDD_63,0.75
SWB1,CONN15,CH3,P0V75_AVDD_63,0.75 SWB1,CONN15,CH3,P0V75_AVDD_63,0.756
SWB1,CONN15,CH4,P1V5_AVDD_63,1.5 SWB1,CONN15,CH4,P1V5_AVDD_63,1.524
SWB1,CONN15,CH5,P0V9_AVDD_63,0.9 SWB1,CONN15,CH5,P0V9_AVDD_63,0.915
SWB1,CONN15,CH6,PVDD3_3V_SYNTH_LDO_B3,3.3 SWB1,CONN15,CH6,PVDD3_3V_SYNTH_LDO_B3,3.38
SWB1,CONN15,CH7,PVDD1V5_3,1.5 SWB1,CONN15,CH7,PVDD1V5_3,1.5
SWB1,CONN15,CH8,P0V85_STBY,0.85 SWB1,CONN15,CH8,P0V85_STBY,0.85
SWB1,CONN15,CH9,P1V8_STBY,1.8 SWB1,CONN15,CH9,P1V8_STBY,1.8
SWB1,CONN15,CH10,NC,- SWB1,CONN15,CH10,NC,-
SWB1,CONN15,CH11,P3V3_STBY,3.3 SWB1,CONN15,CH11,P3V3_STBY,3.3
SWB1,CONN15,CH12,PVDD0V9_2,0.9 SWB1,CONN15,CH12,PVDD0V9_2,0.91
SWB1,CONN15,CH13,P0V75_DVDD_55,0.75 SWB1,CONN15,CH13,P0V75_DVDD_55,0.75
SWB1,CONN15,CH14,P0V75_AVDD_55,0.75 SWB1,CONN15,CH14,P0V75_AVDD_55,0.756
SWB1,CONN15,CH15,P1V8_DVDDIO_4,1.8 SWB1,CONN15,CH15,P1V8_DVDDIO_4,1.8
SWB1,CONN16,CH0,PVDD1V5_0,1.5 SWB1,CONN16,CH0,PVDD1V5_0,1.5
SWB1,CONN16,CH1,P1V8_4,1.8 SWB1,CONN16,CH1,P1V8_4,1.816
SWB1,CONN16,CH2,PVDD3_3V_SYNTH_LDO_B5,3.3 SWB1,CONN16,CH2,PVDD3_3V_SYNTH_LDO_B5,3.38
SWB1,CONN16,CH3,PVDD3_3V_SYNTH_LDO_A5,3.3 SWB1,CONN16,CH3,PVDD3_3V_SYNTH_LDO_A5,3.38
SWB1,CONN16,CH4,PVDD3_3V_SYNTH_LDO_B4,3.3 SWB1,CONN16,CH4,PVDD3_3V_SYNTH_LDO_B4,3.38
SWB1,CONN16,CH5,PVDD3_3V_SYNTH_LDO_A4,3.3 SWB1,CONN16,CH5,PVDD3_3V_SYNTH_LDO_A4,3.38
SWB1,CONN16,CH6,P3V3,3.3 SWB1,CONN16,CH6,P3V3,3.327
SWB1,CONN16,CH7,PVDD0_8V_T3,0.8 SWB1,CONN16,CH7,PVDD0_8V_T3,0.82
SWB1,CONN16,CH8,P0V75_DVDD_1,0.75 SWB1,CONN16,CH8,P0V75_DVDD_1,0.75
SWB1,CONN16,CH9,P0V75_AVDD_1,0.75 SWB1,CONN16,CH9,P0V75_AVDD_1,0.756
SWB1,CONN16,CH10,P1V5_AVDD_1,1.5 SWB1,CONN16,CH10,P1V5_AVDD_1,1.524
SWB1,CONN16,CH11,P0V9_AVDD_1,0.9 SWB1,CONN16,CH11,P0V9_AVDD_1,0.915
SWB1,CONN16,CH12,PVDD0V9_0,0.9 SWB1,CONN16,CH12,PVDD0V9_0,0.915
SWB1,CONN16,CH13,PVDD0V9_1,0.9 SWB1,CONN16,CH13,PVDD0V9_1,0.91
SWB1,CONN16,CH14,PVDD0V9_3,0.9 SWB1,CONN16,CH14,PVDD0V9_3,0.915
SWB1,CONN16,CH15,PVDD1V2_T3,1.2 SWB1,CONN16,CH15,PVDD1V2_T3,1.224
1 Board CONN Ch NetName Vnom
6 CB CONN13 CH4 PWR_APU_VDDIO_SUS 1.1
7 CB CONN13 CH5 PWR_VDD_MISC_RUN 0.75
8 CB CONN13 CH6 PWR_APU_VDD_MEM_RUN 0.78
9 CB CONN13 CH7 V0P8_PHY2_DVDD 0.8 0.816
10 CB CONN13 CH8 V0P8_AVDD 0.8
11 CB CONN13 CH9 V0P8_PHY 0.8
12 CB CONN13 CH10 V1P8_FPGA 1.8
14 CB CONN13 CH12 V1P1_FPGA 1.1
15 CB CONN13 CH13 P5V_STBY 5.0
16 CB CONN13 CH14 P3V3_STBY 3.3
17 CB CONN13 CH15 V0P8_PHY2_AVDD 0.8 0.816
18 SWB0 CONN13 CH0 P0V75_DVDD_47 0.75
19 SWB0 CONN13 CH1 P0V75_AVDD_47 0.75 0.756
20 SWB0 CONN13 CH2 P1V5_AVDD_47 1.5 1.524
21 SWB0 CONN13 CH3 P0V9_AVDD_47 0.9 0.915
22 SWB0 CONN13 CH4 P1V8_1 1.8 1.816
23 SWB0 CONN13 CH5 PVDD3_3V_SYNTH_LDO_A3 3.3 3.38
24 SWB0 CONN13 CH6 PVDD3_3V_SYNTH_LDO_B1 3.3 3.38
25 SWB0 CONN13 CH7 P1V8_3 1.8 1.816
26 SWB0 CONN13 CH8 P1V8_DVDDIO_3 1.8
27 SWB0 CONN13 CH9 P0V75_DVDD_39 0.75
28 SWB0 CONN13 CH10 P0V75_AVDD_39 0.75 0.756
29 SWB0 CONN13 CH11 P1V5_AVDD_39 1.5 1.524
30 SWB0 CONN13 CH12 P0V9_AVDD_39 0.9 0.915
31 SWB0 CONN13 CH13 PVDD1V5_2 1.5
32 SWB0 CONN13 CH14 PVDD1V8_DUT 1.8
33 SWB0 CONN13 CH15 PVDD_MDIO 1.2
34 SWB0 CONN14 CH0 P0V75_AVDD_7 0.75 0.756
35 SWB0 CONN14 CH1 P1V5_AVDD_7 1.5 1.524
36 SWB0 CONN14 CH2 P0V9_AVDD_7 0.9 0.915
37 SWB0 CONN14 CH3 P1V8_5 1.8 1.816
38 SWB0 CONN14 CH4 P1V8_2 1.8 1.816
39 SWB0 CONN14 CH5 PVDD3_3V_SYNTH_LDO_B2 3.3 3.38
40 SWB0 CONN14 CH6 PVDD3_3V_SYNTH_LDO_A2 3.3 3.38
41 SWB0 CONN14 CH7 PVDD3_3V_SYNTH_LDO_A1 3.3 3.38
42 SWB0 CONN14 CH8 PVDD1V5_TSC 1.5 1.516
43 SWB0 CONN14 CH9 PVDD1V5_ANLG 1.5 1.516
44 SWB0 CONN14 CH10 NC -
45 SWB0 CONN14 CH11 NC -
46 SWB0 CONN14 CH12 PVDD1V5_1 1.5
47 SWB0 CONN14 CH13 NC -
48 SWB0 CONN14 CH14 P1V8_DVDDIO_1 1.8
49 SWB0 CONN14 CH15 P0V75_DVDD_7 0.75
50 SWB0 CONN15 CH0 P1V5_AVDD_55 1.5 1.524
51 SWB0 CONN15 CH1 P0V9_AVDD_55 0.9 0.915
52 SWB0 CONN15 CH2 P0V75_DVDD_63 0.75
53 SWB0 CONN15 CH3 P0V75_AVDD_63 0.75 0.756
54 SWB0 CONN15 CH4 P1V5_AVDD_63 1.5 1.524
55 SWB0 CONN15 CH5 P0V9_AVDD_63 0.9 0.915
56 SWB0 CONN15 CH6 PVDD3_3V_SYNTH_LDO_B3 3.3 3.38
57 SWB0 CONN15 CH7 PVDD1V5_3 1.5
58 SWB0 CONN15 CH8 P0V85_STBY 0.85
59 SWB0 CONN15 CH9 P1V8_STBY 1.8
60 SWB0 CONN15 CH10 NC -
61 SWB0 CONN15 CH11 P3V3_STBY 3.3
62 SWB0 CONN15 CH12 PVDD0V9_2 0.9 0.91
63 SWB0 CONN15 CH13 P0V75_DVDD_55 0.75
64 SWB0 CONN15 CH14 P0V75_AVDD_55 0.75 0.756
65 SWB0 CONN15 CH15 P1V8_DVDDIO_4 1.8
66 SWB0 CONN16 CH0 PVDD1V5_0 1.5
67 SWB0 CONN16 CH1 P1V8_4 1.8 1.816
68 SWB0 CONN16 CH2 PVDD3_3V_SYNTH_LDO_B5 3.3 3.38
69 SWB0 CONN16 CH3 PVDD3_3V_SYNTH_LDO_A5 3.3 3.38
70 SWB0 CONN16 CH4 PVDD3_3V_SYNTH_LDO_B4 3.3 3.38
71 SWB0 CONN16 CH5 PVDD3_3V_SYNTH_LDO_A4 3.3 3.38
72 SWB0 CONN16 CH6 P3V3 3.3 3.327
73 SWB0 CONN16 CH7 PVDD0_8V_T3 0.8 0.82
74 SWB0 CONN16 CH8 P0V75_DVDD_1 0.75
75 SWB0 CONN16 CH9 P0V75_AVDD_1 0.75 0.756
76 SWB0 CONN16 CH10 P1V5_AVDD_1 1.5 1.524
77 SWB0 CONN16 CH11 P0V9_AVDD_1 0.9 0.915
78 SWB0 CONN16 CH12 PVDD0V9_0 0.9 0.915
79 SWB0 CONN16 CH13 PVDD0V9_1 0.9 0.91
80 SWB0 CONN16 CH14 PVDD0V9_3 0.9 0.915
81 SWB0 CONN16 CH15 PVDD1V2_T3 1.2 1.224
82 SWB1 CONN13 CH0 P0V75_DVDD_47 0.75
83 SWB1 CONN13 CH1 P0V75_AVDD_47 0.75 0.756
84 SWB1 CONN13 CH2 P1V5_AVDD_47 1.5 1.524
85 SWB1 CONN13 CH3 P0V9_AVDD_47 0.9 0.915
86 SWB1 CONN13 CH4 P1V8_1 1.8 1.816
87 SWB1 CONN13 CH5 PVDD3_3V_SYNTH_LDO_A3 3.3 3.38
88 SWB1 CONN13 CH6 PVDD3_3V_SYNTH_LDO_B1 3.3 3.38
89 SWB1 CONN13 CH7 P1V8_3 1.8 1.816
90 SWB1 CONN13 CH8 P1V8_DVDDIO_3 1.8
91 SWB1 CONN13 CH9 P0V75_DVDD_39 0.75
92 SWB1 CONN13 CH10 P0V75_AVDD_39 0.75 0.756
93 SWB1 CONN13 CH11 P1V5_AVDD_39 1.5 1.524
94 SWB1 CONN13 CH12 P0V9_AVDD_39 0.9 0.915
95 SWB1 CONN13 CH13 PVDD1V5_2 1.5
96 SWB1 CONN13 CH14 PVDD1V8_DUT 1.8
97 SWB1 CONN13 CH15 PVDD_MDIO 1.2
98 SWB1 CONN14 CH0 P0V75_AVDD_7 0.75 0.756
99 SWB1 CONN14 CH1 P1V5_AVDD_7 1.5 1.524
100 SWB1 CONN14 CH2 P0V9_AVDD_7 0.9 0.915
101 SWB1 CONN14 CH3 P1V8_5 1.8 1.816
102 SWB1 CONN14 CH4 P1V8_2 1.8 1.816
103 SWB1 CONN14 CH5 PVDD3_3V_SYNTH_LDO_B2 3.3 3.38
104 SWB1 CONN14 CH6 PVDD3_3V_SYNTH_LDO_A2 3.3 3.38
105 SWB1 CONN14 CH7 PVDD3_3V_SYNTH_LDO_A1 3.3 3.38
106 SWB1 CONN14 CH8 PVDD1V5_TSC 1.5 1.516
107 SWB1 CONN14 CH9 PVDD1V5_ANLG 1.5 1.516
108 SWB1 CONN14 CH10 NC -
109 SWB1 CONN14 CH11 NC -
110 SWB1 CONN14 CH12 PVDD1V5_1 1.5
111 SWB1 CONN14 CH13 NC -
112 SWB1 CONN14 CH14 P1V8_DVDDIO_1 1.8
113 SWB1 CONN14 CH15 P0V75_DVDD_7 0.75
114 SWB1 CONN15 CH0 P1V5_AVDD_55 1.5 1.524
115 SWB1 CONN15 CH1 P0V9_AVDD_55 0.9 0.915
116 SWB1 CONN15 CH2 P0V75_DVDD_63 0.75
117 SWB1 CONN15 CH3 P0V75_AVDD_63 0.75 0.756
118 SWB1 CONN15 CH4 P1V5_AVDD_63 1.5 1.524
119 SWB1 CONN15 CH5 P0V9_AVDD_63 0.9 0.915
120 SWB1 CONN15 CH6 PVDD3_3V_SYNTH_LDO_B3 3.3 3.38
121 SWB1 CONN15 CH7 PVDD1V5_3 1.5
122 SWB1 CONN15 CH8 P0V85_STBY 0.85
123 SWB1 CONN15 CH9 P1V8_STBY 1.8
124 SWB1 CONN15 CH10 NC -
125 SWB1 CONN15 CH11 P3V3_STBY 3.3
126 SWB1 CONN15 CH12 PVDD0V9_2 0.9 0.91
127 SWB1 CONN15 CH13 P0V75_DVDD_55 0.75
128 SWB1 CONN15 CH14 P0V75_AVDD_55 0.75 0.756
129 SWB1 CONN15 CH15 P1V8_DVDDIO_4 1.8
130 SWB1 CONN16 CH0 PVDD1V5_0 1.5
131 SWB1 CONN16 CH1 P1V8_4 1.8 1.816
132 SWB1 CONN16 CH2 PVDD3_3V_SYNTH_LDO_B5 3.3 3.38
133 SWB1 CONN16 CH3 PVDD3_3V_SYNTH_LDO_A5 3.3 3.38
134 SWB1 CONN16 CH4 PVDD3_3V_SYNTH_LDO_B4 3.3 3.38
135 SWB1 CONN16 CH5 PVDD3_3V_SYNTH_LDO_A4 3.3 3.38
136 SWB1 CONN16 CH6 P3V3 3.3 3.327
137 SWB1 CONN16 CH7 PVDD0_8V_T3 0.8 0.82
138 SWB1 CONN16 CH8 P0V75_DVDD_1 0.75
139 SWB1 CONN16 CH9 P0V75_AVDD_1 0.75 0.756
140 SWB1 CONN16 CH10 P1V5_AVDD_1 1.5 1.524
141 SWB1 CONN16 CH11 P0V9_AVDD_1 0.9 0.915
142 SWB1 CONN16 CH12 PVDD0V9_0 0.9 0.915
143 SWB1 CONN16 CH13 PVDD0V9_1 0.9 0.91
144 SWB1 CONN16 CH14 PVDD0V9_3 0.9 0.915
145 SWB1 CONN16 CH15 PVDD1V2_T3 1.2 1.224
+59
View File
@@ -0,0 +1,59 @@
# v1.1.3 — Margin now measures against what this platform actually runs at
## ✨ New features
**Per-CONN margin profiles for the switch boards**
* `combo_SWB_CONN13_high` / `_low` through `combo_SWB_CONN16_high` / `_low` replace the old `comboA` / `comboB` pair. Each file's per-channel percentages follow the rails on *that* board, so a CONN13 profile is no longer a rough fit for CONN16.
* SWB0 and SWB1 share a profile per CONN — the two boards carry identical rails and differ only by I2C bus.
* A high pass and a low pass are now the same run with `_high` swapped for `_low`.
* **A profile applied to the wrong CONN margins the wrong rails and says nothing.** The percentages are positional, so nothing detects the mismatch. `margin_apply_profile_all.sh` now names the right profile per board instead of one name for all nine.
## 🐛 Bug fixes
**`VNOM` was the spec value, not what the rails actually sit at**
* 86 of the 144 channels moved up between +0.8% and +2.5% to the measured median for this platform — `PVDD3_3V_SYNTH_LDO_*` 3.3 → 3.38, `P0V9_AVDD_*` 0.9 → 0.915, `PVDD0_8V_T3` 0.8 → 0.82, and so on.
* **This is not a display change.** `VNOM` is the denominator of `margin_status`'s deviation %, *and* the basis `margin_set` derives high / low / OV / UV from. A rail sitting steady at 0.756 V used to read `+0.80%` against a nominal 0.75 and now reads `0.00%`; and asking for `+3%` now lands on a different absolute voltage than it did last week.
* **Margin logs from before and after this build cannot be compared directly.** The numbers moved because the reference moved, not because the hardware did.
**The batch profile script pointed at files that no longer exist**
* `margin_apply_profile_all.sh` still named `comboA` for all nine boards. With `comboA.conf` removed, every board would have stopped at `Profile not found` — a nine-line wall of errors on a script that is normally left to run.
**The channel map CSV was stale**
* `docs/LTC2980_channel_map.csv` is generated from `settings/*.conf`, so all 86 changed rails were wrong in it. Regenerated with `tools/gen_channel_map.sh`. It is output, not source — regenerate it, never hand-edit it.
## 📦 Downloads
| File | Contents |
|---|---|
| `Script_ABC_Blanton_V1.1.3.zip` | The full Tera Term working directory, including `Blanton_Script/` to copy onto the DUT |
**After copying to the DUT:**
```bash
chmod +x ~/Blanton_Script/*.sh # see below
grep -rlU $'\r' ~/Blanton_Script # expect no output
```
`blanton_ber.sh` and `nfc_polling.sh` are invoked by the macros through `./` or `~/`, so they need the execute bit along with `bmc_monitor.sh` and `usb_target.sh` — neither git nor a Windows/USB copy carries it reliably.
## ⚠️ Before you run
* **Re-baseline your margin expectations.** Any pass/fail limits or golden logs derived from the old `VNOM` values need redoing against this build.
* **`margin_save` in any form writes NVM permanently** and now writes margin windows derived from the new reference. Run `margin_status_all.sh` first and never call it during a test.
* **SWB profiles are per-CONN.** Applying `combo_SWB_CONN13_high` to a CONN16 board is silently wrong.
* **These three tests cannot share the switch**: `blanton_ber.sh`, `blanton_tr518.sh` and `blanton_traffic_linespeed`.
* **PRBS takes the links down** while `blanton_ber.sh` is armed.
* **`ce0` keeps running until you stop it.**
* **Two numbers must stay in step**: Script C's `sleep 30` and `blanton_ber.sh`'s `BER_INTERVAL`.
* **`FAN_SPEED` is 100** — the fans run flat out unless you change `config.ttl`.
* **`nfc_polling.sh start` clears the log**, so Script B wipes Script A's NFC baseline file (the numbers are already in the console log).
* **The NFC tool is written for the customer's tag.** It polls Type A / B / F only and parses Type A strictly; a tag of another technology is never discovered and fails as `no RF interface activation notification received`. Without `--expected-id` it does not check identity, so a different tag of the same type still passes.
* **The three items listed as unverified in v1.1.0 are still unverified**: the `ce0` ingress mirror, the 120s settle in `blanton_tr518.sh`, and `test mode nr=no` on stop.
## 🔗 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
* [LTC2980_channel_map.csv](https://etgit.et-wen.com/etwen/Blanton_TTL_Script/src/branch/main/docs/LTC2980_channel_map.csv) — all 144 margin channels with the new `VNOM`
**Full changelog:** [V1.1.2...V1.1.3](https://etgit.et-wen.com/etwen/Blanton_TTL_Script/compare/V1.1.2...V1.1.3)
+61
View File
@@ -0,0 +1,61 @@
# v1.1.4 — A thermal and safety run that loads the box and watches the rails
## ✨ New features
**`4_Blanton_Script_thermal_safety.ttl`**
* A **standalone** script — it is not part of the A → B → C chain and is not started by any of them. Run it on its own when the question is thermal or safety rather than functional.
* Brings the DUT up the same way Script A does (login, session reset, fan speed, `wait_init`, DUT inventory, BMC, PCIe error clear, `pcie_bus`, PMON, dmesg), then loads it: `mlucas-avx2 -cpu 0:15` in the background and `blanton_tr518.sh start` on the data plane.
* Then loops every minute: platform data, **both switch boards' rail power** via `TH6_SWB0/1_power_readback.sh`, and `bgctl list` / `jobs`. That is the point of the script — power per rail under sustained full load, sampled over hours.
* **It has no teardown.** When you interrupt it the DUT is still in `port cd lb=mac`, `l2 learn off` and `test mode nr=yes`, and `mlucas-avx2` is still running. Run `blanton_tr518.sh stop` and `kill $(jobs -p)` before anything else uses the box — nothing in `show interfaces status` reveals the leftover state.
* **It cannot share a DUT with Script B.** Both take over the `cd` ports.
**Test flow diagram**
* `docs/Blanton_Test_Flow.drawio` draws all four scripts side by side, with the config flags that change each step marked, the one real `goto` in Script B drawn, and the manual handoffs between A → B → C shown as such.
## 🐛 Bug fixes
**The soak loop spent most of its minute reading margin**
* Script B's per-round loop is meant to be a quick sample. `margin_status_all.sh` walks nine LTC2980s over I2C and dominated the round. The scan moved to Script C, which takes it once before `show uptime`.
* **The trade-off is real and worth knowing**: margin is now only measured at the start (Script A) and the end (Script C). Drift that happens *during* the soak is no longer visible.
**`hw-test-session finish` ran from inside the session's own shell**
* Script C now sends `exit` and waits for `Script done` first, so `finish` runs in the login shell that opened the session.
**The new script arrived with LF line endings**
* Every other `.ttl` in the repo is CRLF, and `.gitattributes` marks `*.ttl` as `-text` — whatever is committed is exactly what Tera Term gets. Converted to CRLF to match.
## 📦 Downloads
| File | Contents |
|---|---|
| `Script_ABC_Blanton_V1.1.4.zip` | The full Tera Term working directory, including `Blanton_Script/` to copy onto the DUT |
**After copying to the DUT:**
```bash
chmod +x ~/Blanton_Script/*.sh # see below
grep -rlU $'\r' ~/Blanton_Script # expect no output
```
`blanton_ber.sh`, `nfc_polling.sh`, `blanton_tr518.sh` and the two `TH6_SWB*_power_readback.sh` are invoked through `./` or `~/`, so they need the execute bit along with `bmc_monitor.sh` and `usb_target.sh` — neither git nor a Windows/USB copy carries it reliably.
## ⚠️ Before you run
* **Script 4 leaves the switch loaded and looped back.** Always finish with `blanton_tr518.sh stop`. If the next test starts without it, traffic and BER results are meaningless and nothing warns you.
* **Do not run Script 4 and Script B on the same DUT.** Same ports, same L2 settings.
* **Margin is no longer sampled during the soak** — only Script A (start) and Script C (end).
* **Re-baseline your margin limits if you have not already**: `VNOM` became the measured median in v1.1.3, which moved both the deviation % and the margin window.
* **These three cannot share the switch**: `blanton_ber.sh`, `blanton_tr518.sh`, `blanton_traffic_linespeed`.
* **PRBS takes the links down** while `blanton_ber.sh` is armed.
* **`ce0` keeps circulating until you stop it.**
* **Two numbers must stay in step**: Script C's `sleep 30` and `blanton_ber.sh`'s `BER_INTERVAL`.
* **`FAN_SPEED` is 100** — relevant here more than anywhere: a thermal run at full fan is not the same test as one at 30%.
* **The three items listed as unverified in v1.1.0 are still unverified**: the `ce0` ingress mirror, the 120s settle in `blanton_tr518.sh`, and `test mode nr=no` on stop. The settle matters most for this release — Script 4 depends on `tr 518` still driving traffic minutes after it was started.
## 🔗 Links
* [Blanton_Test_Flow.drawio](https://etgit.et-wen.com/etwen/Blanton_TTL_Script/src/branch/main/docs/Blanton_Test_Flow.drawio) — the four scripts side by side
* [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.1.3...V1.1.4](https://etgit.et-wen.com/etwen/Blanton_TTL_Script/compare/V1.1.3...V1.1.4)
+67
View File
@@ -0,0 +1,67 @@
# v1.1.5 — The stress jobs now last the whole soak
## 🐛 Bug fixes
**USB stress ran for sixty seconds of an overnight soak**
* `qfx5252-stress-usb` was started with `--runtime 60`. It finished a minute in and the USB path sat idle for the rest of the night. Nothing failed, nothing said so, and the run looked complete.
* SSD stress had the same shape at `--runtime 3600` — one hour of a soak that usually runs far longer.
* Both are now `--runtime 86400`, and the BMC DDR memtester lost its loop count (`64M 1` → `64M`) so it runs until it is stopped rather than finishing one pass.
* **86400 is 24 hours, not "forever".** A soak longer than a day leaves SSD and USB dead for the remainder. Script B prints `bgctl list` every round (since v1.0.10), so the shorter list is visible there — but nothing raises an alarm.
## ✨ New features
**Multiphase VRM margin**
* New `blanton_multiphase_margin.sh` drives the multiphase controllers on both switch boards over the native i2c buses — SWB0 on `/dev/i2c-13` and `-15`, SWB1 on `-14` and `-16`. 19 rails per board, 38 in all.
* `high3` / `low3` / `comboA` / `comboB` set the voltages and report one line per rail:
```
SWB0_0V9_ANLG0 - 0.930V Configure Done
SWB0_0V75_ANLG0 - 0.775V Configure Done
...
[ OK ] high3: 38 rail(s) configured
```
* `save` commits them. It has no per-rail mapping, so it reports as one operation: `Multiphase Save All`.
* `-u 0` / `-u 1` for a single board; rails belonging to the other board are skipped and counted separately, not failed.
* **`save` writes NVM permanently** (PMBus `STORE_USER_ALL`, and `0x17` on the TH6 core rail). A power cycle does not undo it.
* **These are not the LTC2980s that `margin.sh` drives.** The two tools reach the same rails from different sides and each assumes it is the only writer. There is no interlock — do not run both.
**Traffic bursts carry a random pattern**
* `blanton_traffic_linespeed` v0.7.0 appends `PatternRandom=yes` to every `tx`, `ce0` included. A fixed pattern can sit on a benign bit sequence for an entire run; a changing one is what makes a weak lane show itself.
* `-r no` forces the fixed pattern; `-r ""` leaves the argument off entirely, which is the pre-v0.7.0 wire format if a future SDK rejects it.
* Defaults change from `tx 100 length=512` to `tx 200 length=324`.
* **Counter totals are not comparable across this build**: 64800 bytes per burst instead of 51200, about 27% more. The PASS/FAIL cross-check compares a pair against each other and is unaffected — only absolute figures moved.
## 📦 Downloads
| File | Contents |
|---|---|
| `Script_ABC_Blanton_V1.1.5.zip` | The full Tera Term working directory, including `Blanton_Script/` to copy onto the DUT |
**After copying to the DUT:**
```bash
chmod +x ~/Blanton_Script/*.sh # see below
grep -rlU $'\r' ~/Blanton_Script # expect no output
```
`blanton_ber.sh`, `nfc_polling.sh`, `blanton_tr518.sh`, `blanton_multiphase_margin.sh` and the two `TH6_SWB*_power_readback.sh` are invoked through `./` or `~/`, so they need the execute bit along with `bmc_monitor.sh` and `usb_target.sh` — neither git nor a Windows/USB copy carries it reliably.
## ⚠️ Before you run
* **A soak longer than 24 hours needs the runtimes raised.** `--runtime 86400` is a ceiling; past it, SSD and USB are idle and only a shorter `bgctl list` hints at it.
* **`blanton_multiphase_margin.sh save` is permanent.** Read the rails back before committing, and never run it during a test.
* **Do not mix `blanton_multiphase_margin.sh` and `margin.sh`** — same rails, two different access paths, no interlock.
* **Traffic counters changed scale.** Any absolute thresholds taken from earlier logs need redoing.
* **Script 4 (thermal/safety) has no teardown** — finish with `blanton_tr518.sh stop` and `kill $(jobs -p)`.
* **These three cannot share the switch**: `blanton_ber.sh`, `blanton_tr518.sh`, `blanton_traffic_linespeed`.
* **Margin is only sampled at the start and end of a soak** (since v1.1.4), not during it.
* **`FAN_SPEED` is 100** — the fans run flat out unless you change `config.ttl`.
* **The three items listed as unverified in v1.1.0 are still unverified**: the `ce0` ingress mirror, the 120s settle in `blanton_tr518.sh`, and `test mode nr=no` on stop.
## 🔗 Links
* [Blanton_Test_Flow.drawio](https://etgit.et-wen.com/etwen/Blanton_TTL_Script/src/branch/main/docs/Blanton_Test_Flow.drawio) — the four scripts side by side
* [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.1.4...V1.1.5](https://etgit.et-wen.com/etwen/Blanton_TTL_Script/compare/V1.1.4...V1.1.5)
+74
View File
@@ -0,0 +1,74 @@
# v1.1.6 — The PDB bricks were never being asked the right question
## 🐛 Bug fixes
**Every PDB reading was `NA`, and the cause was a page number written in the wrong base**
* The four ADPM12200 bricks put each measurement on its own PMBus PAGE, and the page has to be written before every read. The bring-up spreadsheet listed those page numbers in decimal but with an `0x` prefix, so four of the five selected the wrong page:
| Reading | Datasheet PAGE | Should send | Spreadsheet said |
|---|---|---|---|
| Vin | 9 | `0x09` | `0x00` |
| Iin | 10 | `0x0A` | `0x10` |
| Vout | 2 | `0x02` | `0x02` ✅ |
| Iout | 14 | `0x0E` | `0x14` |
| Temp | 18 | `0x12` | `0x18` |
* Only Vout worked — because 2 reads the same in either base. That is why Iin and Iout answered `0xFFFF` and the temperature answered `0x0000`, and why a Vin scaling had to be invented to make 50 V appear.
* `blanton_pwr_data.sh` sends no page at all (its PDB table has `page "-"`), which is the reason it reports the whole PDB section as `NA`.
## ✨ New features
**`pwr_brick.sh` — the five power bricks, read properly**
* `show` prints Vin / Iin / Vout / Iout / Temp for all five: `SWB0.PU207` (0x62), `SWB0.PU13` (0x63), `SWB1.PU332` (0x60), `SWB1.PU85` (0x61) and `CPB.PU37` (0x26). `-r` adds the raw words.
* Conversions come from the datasheet's DIRECT equation, `X = (1/m)(Y × 10⁻ᴿ − b)`, with Table 3's coefficients: voltage `Y × 8 mV`, current `Y × 0.04 A`, temperature `Y × 0.01 °C`.
* **Cross-checked, not assumed**: `READ_VOUT` returns `0x05D4` → 1492 × 8 = 11936 mV, which is exactly the figure `show platform voltage` reports for that rail from a completely separate sensor path.
* `CPB.PU37` is a different part — no page writes and its own scaling — and is handled separately.
* The datasheet is now in the repo (`docs/ADPM12200CMLZxx_DS_*.pdf`) so the pages and coefficients can be checked without hunting for it.
**Every value is validated before it is printed**
* This bus corrupts the **high byte only**. That turns `11.98 V` into `32.00 V` — positive, plausible in magnitude, and invisible to any "reject 0xFFFF" filter. Each value is re-read (up to `PB_TRIES`, default 8) until it is not `0xFFFF`, not `0x0000`, and lands inside a plausibility window.
* `0x0000` is rejected as a raw word for the same reason: on the temperature register it decodes to a perfectly believable 0 °C.
**Complementary margin profiles per board**
* `comboA` / `comboB` for CB and each SWB CONN. `comboB` is `comboA` with every direction flipped, so running both covers each rail high and low while its neighbours sit the other way.
* NC channels stay at `nominal` in both — there is nothing to margin on an unused rail (CONN14 CH10/11/13, CONN15 CH10).
**The BMC USB service log is captured again — to a file**
* Script C's `journalctl` dump had been commented out, so that service log reached nothing at all. It now runs with `-o short-iso` into `log/bmc_usb_net.log` and is copied into the job directory for the USB archive. The ISO timestamps line up with the other monitor logs, and `rm -f` first keeps the file to one run.
* **It is no longer printed to the console**, so the USB copy is the only copy. If that `cp` fails — and nothing checks it — the service log is gone. Check the job directory before packing up.
## 📦 Downloads
| File | Contents |
|---|---|
| `Script_ABC_Blanton_V1.1.6.zip` | The full Tera Term working directory, including `Blanton_Script/` to copy onto the DUT |
**After copying to the DUT:**
```bash
chmod +x ~/Blanton_Script/*.sh # see below
grep -rlU $'\r' ~/Blanton_Script # expect no output
```
`blanton_ber.sh`, `nfc_polling.sh`, `blanton_tr518.sh`, `blanton_multiphase_margin.sh`, `pwr_brick.sh` and the two `TH6_SWB*_power_readback.sh` are invoked through `./` or `~/`, so they need the execute bit along with `bmc_monitor.sh` and `usb_target.sh` — neither git nor a Windows/USB copy carries it reliably.
## ⚠️ Before you run
* **`READ_VIN` and `READ_IIN` are not in the datasheet's coefficient table.** They are decoded here with the voltage and current coefficients — consistent with a ~50 V input, but not stated by the datasheet. Anything quoting brick Vin should have that confirmed first. `PB_VIN_M` / `PB_IIN_M` are where to change it.
* **The BMC USB service log only exists on the USB stick.** It is not in the master console log any more.
* **`NA` has two meanings**: nothing readable, or read but outside its plausibility window. Use `PB_TRIES=1 ./Blanton_Script/pwr_brick.sh show -r` to see the unretried raw words and tell them apart.
* **Margin profiles are positional.** `comboA_SWB_CONN13` applied to a CONN16 board margins the wrong rails and nothing detects it.
* **`blanton_multiphase_margin.sh save` is permanent**, and it must not be mixed with `margin.sh` — same rails, two access paths, no interlock.
* **A soak longer than 24 hours needs the stress runtimes raised** — `--runtime 86400` is a ceiling.
* **Script 4 (thermal/safety) has no teardown** — finish with `blanton_tr518.sh stop` and `kill $(jobs -p)`.
* **These three cannot share the switch**: `blanton_ber.sh`, `blanton_tr518.sh`, `blanton_traffic_linespeed`.
* **`FAN_SPEED` is 100.**
* **The three items listed as unverified in v1.1.0 are still unverified**: the `ce0` ingress mirror, the 120s settle in `blanton_tr518.sh`, and `test mode nr=no` on stop.
## 🔗 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
* [Blanton_Test_Flow.drawio](https://etgit.et-wen.com/etwen/Blanton_TTL_Script/src/branch/main/docs/Blanton_Test_Flow.drawio) — the four scripts side by side
**Full changelog:** [V1.1.5...V1.1.6](https://etgit.et-wen.com/etwen/Blanton_TTL_Script/compare/V1.1.5...V1.1.6)
+73
View File
@@ -0,0 +1,73 @@
# v1.1.7 — A way back from a margin, and a reboot cycle that runs itself
## ✨ New features
**`blanton_multiphase_margin.sh normal` — put the rails back without a power cycle**
* `normal` returns all 38 multiphase rails to their nominal set point, with the same per-rail reporting as the margin profiles (`SWB0_0V9_ANLG0 - 0.930V Configure Done`). `-u 0|1|all` as usual.
* Until now the only way out of a margin was to power-cycle the DUT. That mattered more than it sounds: `save` run while the board was still margined would have written the offsets into NVM, where a power cycle does not help either.
* The commands it sends are in `tools/Multiphase_Normal.txt` for anyone driving the bench by hand.
> ⚠️ `TH6_CORE` is 0.8 V nominal but settles near **0.8591 V** once the load line is active. Reading back 0.859 after `normal` is the load line doing its job, not a failed write.
**`5_Blanton_Script_Reboot_Cycle.ttl` — an unattended reboot-cycle run**
* A standalone macro, like Script 4: it does **not** chain to A → B → C and does not use `hw-test-session`. Every cycle is a fresh boot, so there is nothing to carry over and nothing to tear down.
* Each round: login → `sudo -i` → `date -s` → fan speed → `wait_init` → **Check Pt1 … Pt13** → `show uptime` → `reboot` → wait for the next boot. The cycle number is printed in the banner of every round.
| | | | |
|---|---|---|---|
| **Pt1** DUT info | **Pt2** BMC info + tools | **Pt3** mgmt ping | **Pt4** NFC poll |
| **Pt5** SSD stress | **Pt6** USB stress | **Pt7** BMC USB net | **Pt8** port status + 15 s traffic |
| **Pt9** BER sweep | **Pt10** NVMe errors | **Pt11** platform data | **Pt12** dmesg i2c |
| **Pt13** PCIe error counters | | | |
* The USB step takes its device node from `usb_target.sh`, not a hard-coded `/dev/sda1`.
**The SSD and USB stress durations are declared in `config.ttl`**
* `SSD_RUNTIME` / `SSD_COUNT` and `USB_RUNTIME` / `USB_COUNT` replace the values that were hard-coded in Script B, so a site changes them in one place. `COUNT` is passed straight through as `--passes`.
## 🐛 Bug fixes
**Script B left the global `timeout` at 15 s for the rest of the cdc_ncm section**
* The NCM probe sets `timeout = 15` and restored it only at `:skip_ping` — which the *success* path reaches several `wait`s later. Until then every `wait` gave up after 15 s instead of blocking, and a `wait` that returns without eating the prompt puts the whole macro a beat ahead of the DUT. It is now restored on the success path too.
**`goto skip_ping` in the reboot-cycle macro had no label to jump to**
* The probe was copied out of Script B without its `:skip_ping` label. Tera Term does not check labels when it loads a macro — it raises the error only when it actually jumps, which here means only when the NCM interface is missing. The failure mode was an error dialog stopping the whole cycle, on the one run where something was already wrong. The label is there now, and the `timeout` is restored **before** the branch so one line covers both paths.
**Two check points both numbered 12**
* `Dmesg_i2c` and `PCIE Error Counters` both announced themselves as `Check Pt12`. The second is now `Pt13`; Pt1 … Pt13 are unique.
## 📦 Downloads
| File | Contents |
|---|---|
| `Script_ABC_Blanton_V1.1.7.zip` | The full Tera Term working directory, including `Blanton_Script/` to copy onto the DUT |
**After copying to the DUT:**
```bash
chmod +x ~/Blanton_Script/*.sh # see below
grep -rlU $'\r' ~/Blanton_Script # expect no output
```
`blanton_ber.sh`, `nfc_polling.sh`, `blanton_tr518.sh`, `blanton_multiphase_margin.sh`, `pwr_brick.sh` and the two `TH6_SWB*_power_readback.sh` are invoked through `./` or `~/`, so they need the execute bit along with `bmc_monitor.sh` and `usb_target.sh` — neither git nor a Windows/USB copy carries it reliably.
## ⚠️ Before you run
* **`--runtime` is the job's overall limit, not a per-pass one.** `qfx5252-stress-*` stops after `RUNTIME` seconds whatever `--passes` says, so `SSD_RUNTIME=600` is a **10 minute** stress, not 600 × `SSD_COUNT`. For a 24 hour soak set `RUNTIME` to `86400`. The shipped defaults are 600.
* **Script 5 has not been run on hardware yet.** Two things to confirm on the bench: that `wait "Booting in blind mode"` really appears in this build's boot output — it has no `timeout` guard, so a changed string waits forever — and that re-running `bmc-first-enroll` every cycle is safe.
* **Script 5 has no exit condition.** `while 1` with a `reboot` at the end of each round; stop it by closing the Tera Term macro.
* **`blanton_multiphase_margin.sh save` is permanent**, and must not be mixed with `margin.sh` — same rails, two access paths, no interlock. Never run it while the board is margined.
* **`READ_VIN` and `READ_IIN` are still not in the ADPM12200 coefficient table** — `pwr_brick.sh` decodes them with the voltage and current coefficients. Confirm before quoting brick Vin.
* **The BMC USB service log only exists on the USB stick.**
* **Script 4 (thermal/safety) has no teardown** — finish with `blanton_tr518.sh stop` and `kill $(jobs -p)`.
* **These three cannot share the switch**: `blanton_ber.sh`, `blanton_tr518.sh`, `blanton_traffic_linespeed`.
* **`FAN_SPEED` is 100.**
* **Still unverified from v1.1.0**: the `ce0` ingress mirror, the 120 s settle in `blanton_tr518.sh`, and `test mode nr=no` on stop.
## 🔗 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
* [Blanton_Test_Flow.drawio](https://etgit.et-wen.com/etwen/Blanton_TTL_Script/src/branch/main/docs/Blanton_Test_Flow.drawio) — the scripts side by side
**Full changelog:** [V1.1.6...V1.1.7](https://etgit.et-wen.com/etwen/Blanton_TTL_Script/compare/V1.1.6...V1.1.7)
+71
View File
@@ -0,0 +1,71 @@
# v1.1.8 — The CPU stress no longer dies with your terminal
## ✨ New features
**`mlucas` now runs as a systemd unit, so it survives a lost session**
* The AMD CPU load is started as `systemd-run --unit=mlucas-amm --property=Type=exec --property=Restart=always --property=RestartSec=2`, instead of being backgrounded with `&` in the login shell. Script B and the thermal/safety macro (Script 4) both use it.
* As a shell job it belonged to that one terminal: close Tera Term, drop the console, reconnect on a different session, and the load was gone — while `jobs` from the new session showed nothing to tell you. A multi-day soak could spend most of its length with an idle CPU and produce thermal numbers that looked fine because nothing was loading the part.
* `Restart=always` brings it back if it exits on its own, and the log is appended (`>>`) inside the unit while being truncated (`>`) once before the unit starts, so a restart adds to the run rather than erasing it.
* Script B now prints `systemctl is-active mlucas-amm` beside `jobs`, both in the one-shot check and in every pass of the monitor loop. One word — `active` — tells you the CPU is still loaded.
> The old `&` line is kept commented out directly above the new one, to fall back to if `systemd-run` is not available on a build.
**Script C stops the unit and brings its log home**
* `systemctl stop mlucas-amm` was added next to the existing `kill $(jobs -p)`, and `mlucas_amm_log` is copied into `/host/hw-eval/jobs/` with the other stress logs.
* `kill $(jobs -p)` cannot reach a systemd unit, so without this the load would have run straight through the post-test snapshot and into the next test — every temperature and power reading taken at full load, with nothing in `show interfaces status` to reveal it.
**`EN_timestamp` — turn the per-line log timestamp on or off from `config.ttl`**
* Script A's `logopen` takes its 5th argument from the new flag: `logopen filename 0 1 1 EN_timestamp`. The argument order (`<file> <binary> <append> <PlainText> <timestamp>`) is now spelled out above the call.
**`BMC_USB_RUNTIME` — the BMC USB ping duration is a knob, not a constant**
* It was hard-coded to `-w 14400` (4 hours), which no longer matched the soak lengths the SSD and USB knobs were being set to. The shipped default is `172800` (2 days).
**The shipped stress defaults are now one hour**
* `SSD_RUNTIME` and `USB_RUNTIME` go from 600 to `3600`. v1.1.7 shipped a 10 minute stress by default.
## 🐛 Bug fixes
**`publish.sh` produced a different bundle depending on whose machine it ran on**
* `rsync` copied whatever sat in `src/Script_ABC_Blanton/`, so a developer with the `hammer/` mlucas binaries in their working tree shipped a ~100 MB zip while a fresh clone shipped ~200 KB. `hammer/` is now excluded from the bundle and ignored by git.
* `publish.sh -h` also printed the first lines of code along with the usage text, and would have truncated the usage block as the header grew. It now reads the header up to the first line of code.
## 📦 Downloads
| File | Contents |
|---|---|
| `Script_ABC_Blanton_V1.1.8.zip` | The full Tera Term working directory, including `Blanton_Script/` to copy onto the DUT |
**After copying to the DUT:**
```bash
chmod +x ~/Blanton_Script/*.sh # see below
grep -rlU $'\r' ~/Blanton_Script # expect no output
ls ~/hammer/tools/amd/mlucas-avx2 # must already be there - see below
```
`blanton_ber.sh`, `nfc_polling.sh`, `blanton_tr518.sh`, `blanton_multiphase_margin.sh`, `pwr_brick.sh` and the two `TH6_SWB*_power_readback.sh` are invoked through `./` or `~/`, so they need the execute bit along with `bmc_monitor.sh` and `usb_target.sh` — neither git nor a Windows/USB copy carries it reliably.
## ⚠️ Before you run
* **Replace `config.ttl` along with the macros.** `EN_timestamp` and `BMC_USB_RUNTIME` are new, and Tera Term aborts the macro on an undefined variable rather than treating it as 0 — keeping an old `config.ttl` stops Script A at the `logopen` line.
* **`hammer/` is not in the bundle.** The ~99 MB of mlucas binaries comes with the DUT image, not from this repo. If `~/hammer/tools/amd/mlucas-avx2` is missing, Script B does not stop — it starts a unit that fails and is restarted every 2 seconds. Check for the file before you start.
* **The timestamp format is not in the macro.** `EN_timestamp` only decides whether there is one; the format lives in Tera Term's Setup → Additional settings → Log, stored in that PC's `TERATERM.INI`. Two benches running the same macro can produce differently stamped logs.
* **The three stress durations are deliberately different**: SSD and USB at 1 hour, the BMC USB ping at 2 days. Set each to match the soak you are actually running.
* **`--runtime` is the job's overall limit, not a per-pass one.** `qfx5252-stress-*` stops after `RUNTIME` seconds whatever `--passes` says. For a 24 hour soak set `RUNTIME` to `86400`.
* **`mlucas-amm` has not been run on hardware yet.** The unit resolves `~` through bash's fallback to the passwd entry, because systemd does not set `HOME` for a system service without `User=`. It should land on `/root/hammer`, the same path the interactive shell uses — confirm it on the bench, or change both paths to an absolute `/root/hammer/...`.
* **Script 4 uses the same unit but has no teardown.** The thermal/safety macro now starts `mlucas-amm` the same way Script B does, and it still ends at `while 1` — so stopping it means `blanton_tr518.sh stop` **and** `systemctl stop mlucas-amm`. Closing Tera Term does not stop the CPU load any more.
* **Script 5 (reboot cycle) is still unverified on hardware**, still has no exit condition, and `wait "Booting in blind mode"` still has no `timeout` guard.
* **`blanton_multiphase_margin.sh save` is permanent**, and must not be mixed with `margin.sh` — same rails, two access paths, no interlock.
* **`READ_VIN` and `READ_IIN` are still not in the ADPM12200 coefficient table.**
* **The BMC USB service log only exists on the USB stick.**
* **These three cannot share the switch**: `blanton_ber.sh`, `blanton_tr518.sh`, `blanton_traffic_linespeed`.
* **`FAN_SPEED` is 100.**
* **Still unverified from v1.1.0**: the `ce0` ingress mirror, the 120 s settle in `blanton_tr518.sh`, and `test mode nr=no` on stop.
## 🔗 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
* [Blanton_Test_Flow.drawio](https://etgit.et-wen.com/etwen/Blanton_TTL_Script/src/branch/main/docs/Blanton_Test_Flow.drawio) — the scripts side by side
**Full changelog:** [V1.1.7...V1.1.8](https://etgit.et-wen.com/etwen/Blanton_TTL_Script/compare/V1.1.7...V1.1.8)
+76
View File
@@ -0,0 +1,76 @@
# v1.2.0 — SerDes DSC capture, and the macro now waits on the DUT
## ✨ New features
**Full-machine SerDes DSC capture, before and after the soak**
* `bcm_dsc_scan.sh` runs `phydiag <port> dsc` through the Broadcom diag shell across the whole port list — one 100G port plus the 200G ranges, about 445 per unit, on both units — and writes the raw log under `Blanton_Script/log/`, then copies it to `/host/hw-eval/jobs/`.
* Script A takes a baseline and Script C takes a closing dump, so the pair brackets the stress run and the two are directly comparable.
* `-u 0` scans one unit, `-f <name>` names the log (`%u` → `u0`/`u1`, `%t` → timestamp), `-F` overwrites, `-n` dry runs, `-C` skips the copy. A name without `%u` gets `_u0` / `_u1` inserted automatically, so unit 1 can never overwrite unit 0.
* Every run ends with `### DSC_SCAN_DONE rc=<n>`. `rc=0` means every port returned a complete dump.
* `phydiag ... dsc` is read-only — it does not change any SerDes setting.
**`bcm_dsc_parse.sh` turns a raw DSC log into two CSVs**
* `<prefix>_lane.csv` — one row per lane: TXEQ, RXFFE, DFE, EYE, SNR and the rest.
* `<prefix>_pm.csv` — one row per `pm_id`: temperature, PLL, lane count, SNR/EYE statistics.
* POSIX `sh` + `awk`, no Python, so it runs on the DUT as happily as on a laptop. Lane rows are read by the order of their bracket groups rather than by fixed column positions, so the SDK re-spacing its output does not break parsing; a row that does not yield 9 groups is reported as `UNPARSED` on stderr instead of being parsed wrongly.
**`EN_TX_FIR` in `config.ttl` — the DSC scan is off by default**
* A full scan is about 10 minutes and both Script A and Script C do one, so the shipped default (`0`) keeps ~20 minutes out of a routine run. Set it to `1` when the SerDes data is what you are after.
**The macro now waits on the DUT instead of on itself**
* Every `pause N` in Scripts A, B and C became `sendln "sleep N"` followed by `wait prompt_sonic_root`.
* `pause` stopped the macro for N seconds without touching the DUT — the shell sat idle and the macro was guessing how long the previous command would take. On a loaded DUT the guess ran short and the next command went out before the previous one had finished, putting the whole run a beat ahead of the switch. Now the wait happens on the DUT and the macro resumes when the prompt actually comes back.
* It also means the wait appears in the console log with a timestamp, so a round that ran long is visible afterwards.
* Timings changed with it: the management-ping sample in Script A is 15 s (was 30), the settle after each traffic `clear` is 5 s (was 15). The traffic run itself stays 15 s and Script B's monitor loop stays 60 s.
## 🐛 Bug fixes
**The DSC scan only ever scanned one port — and reported success**
* The scan loop read its port list on stdin, and `bcmcmd` reads stdin too, so the first call swallowed the rest of the file and the loop ended after a single port.
* Nothing looked wrong. The log held one port marker and one dsc block, the marker-to-dump comparison passed because both numbers shrank together, the exit code was 0, and a 445-port scan simply finished in seconds.
* The loop now reads on file descriptor 3 and `bcmcmd` is given `< /dev/null`, and there is a new check that the number of iterations matches the number of ports in the list — a check that cannot be fooled by the loop ending early.
**Dead call sites removed from Scripts A, B and C**
* The commented-out 100G PRBS calls, a duplicated commented 100G port-status block in Script A, and the stale `bmc_monitor_ddr.sh` block in Script C have been deleted. They had been dead since bring-up.
* `port_prbs_monitor.sh` still ships and still runs by hand — but re-enabling it means writing the calls again, not un-commenting them.
## 🔧 Changes
* **Script C no longer prints the BMC poll log or the mlucas log to the console.** Both files are still copied to `/host/hw-eval/jobs/` and out to the USB stick with everything else; only the master log got shorter.
## 📦 Downloads
| File | Contents |
|---|---|
| `Script_ABC_Blanton_V1.2.0.zip` | The full Tera Term working directory, including `Blanton_Script/` to copy onto the DUT |
**After copying to the DUT:**
```bash
chmod +x ~/Blanton_Script/*.sh # bcm_dsc_scan.sh is invoked as ./Blanton_Script/... and needs it
grep -rlU $'\r' ~/Blanton_Script # expect no output
ls ~/hammer/tools/amd/mlucas-avx2 # must already be there
```
## ⚠️ Before you run
* **Replace `config.ttl` along with the macros.** `EN_TX_FIR` is new, and Tera Term aborts on an undefined variable rather than treating it as 0.
* **`bcm_dsc_scan.sh` needs the execute bit.** Script A and Script C invoke it as `./Blanton_Script/bcm_dsc_scan.sh`. Without `chmod +x` it fails with `Permission denied`, the macro walks straight past it, and Script C's four `cp` lines then each report a missing file.
* **The DSC scan shares the ports with `blanton_ber.sh`, `blanton_traffic_linespeed` and `blanton_tr518.sh`** — do not run it alongside any of them.
* **Script 4 and Script 5 still use `pause`.** Only A, B and C were converted.
* **`--runtime` is the job's overall limit, not a per-pass one.** `--passes` does not extend it; for a 24 hour soak set `RUNTIME` to `86400`.
* **Script 4 has no teardown**: finish it with `blanton_tr518.sh stop` **and** `systemctl stop mlucas-amm`.
* **Script 5 (reboot cycle) is still unverified on hardware**, has no exit condition, and its `wait "Booting in blind mode"` has no `timeout` guard.
* **`blanton_multiphase_margin.sh save` is permanent**, and must not be mixed with `margin.sh`.
* **`READ_VIN` and `READ_IIN` are still not in the ADPM12200 coefficient table.**
* **The BMC USB service log only exists on the USB stick.**
* **`FAN_SPEED` is 100.**
* **Still unverified from v1.1.0**: the `ce0` ingress mirror, the 120 s settle in `blanton_tr518.sh`, and `test mode nr=no` on stop.
## 🔗 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
* [Blanton_Test_Flow.drawio](https://etgit.et-wen.com/etwen/Blanton_TTL_Script/src/branch/main/docs/Blanton_Test_Flow.drawio) — the scripts side by side
**Full changelog:** [V1.1.8...V1.2.0](https://etgit.et-wen.com/etwen/Blanton_TTL_Script/compare/V1.1.8...V1.2.0)
+49
View File
@@ -0,0 +1,49 @@
# v1.2.1 — A BER baseline, so the SerDes numbers have something to be compared against
## ✨ New features
**Script A now takes a SerDes BER sweep before the first traffic run**
* `blanton_ber.sh init → start → sleep 30 → report → stop → clear`, branched on `SWB_UNIT0` / `SWB_UNIT1` exactly like the traffic block beside it.
* Script C already ran the closing sweep after its traffic report. With this one at the front, the pair brackets the soak — the same shape as the DSC scans added in v1.2.0, and the same reason: a BER figure on its own says very little, a *change* in it says a lot.
* The `sleep 30` matches `blanton_ber.sh`'s `BER_INTERVAL`. Reporting before one full interval has accumulated reads a window that has not finished, and nothing warns you about it.
## 🐛 Bug fixes
**The new block's comment described the wrong position**
* It was copied out of Script C, which runs BER *after* the traffic report, and the comment came with it and still said "after". In Script A the block runs *before* traffic. The comment now says what the code does and why the ordering is what it is.
## ⚠️ Before you run
* **Watch Script A's first traffic report on the first run.** PRBS holds the lanes out of normal operation and `blanton_ber.sh clear` is what releases them — and in Script A nothing settles between that `clear` and the `blanton_traffic_linespeed ps` / `init` that follows. Script C does not have this ordering, so the two reports are a built-in comparison: **if Script A shows NA or FAIL pairs that Script C does not, the lanes had not come back yet**, and a `sleep` after `clear` is the fix. This has not been run on hardware yet.
* **`sleep 30` and `BER_INTERVAL` now live in three places** — Script A, Script C, and `blanton_ber.sh` itself. Changing one without the others silently reports a partial interval.
* **BER, `blanton_traffic_linespeed` and `blanton_tr518.sh` cannot overlap.** They all take over the same ports. Script A now touches those ports twice before the soak even starts.
* **`EN_TX_FIR` is still 0 by default**, so the DSC scans do not run unless you turn them on; a full scan is ~10 min in each of Script A and Script C.
* **Replace `config.ttl` along with the macros.** Tera Term aborts the macro on an undefined variable rather than treating it as 0.
* **`bcm_dsc_scan.sh` needs the execute bit**: `chmod +x ~/Blanton_Script/*.sh` after copying.
* **`--runtime` is the job's overall limit, not a per-pass one.** `--passes` does not extend it.
* **Script 4 has no teardown**: finish it with `blanton_tr518.sh stop` **and** `systemctl stop mlucas-amm`.
* **Script 5 (reboot cycle) has no exit condition.** A 199-cycle / 60-hour run has now been analysed: PCIe AER stayed at 0, all 218 traffic pairs and all 864 lanes passed every cycle, and the BMC never reset. Two things it did surface — `bmc-first-enroll` does not exist on that BMC build, and NFC returned FAIL on every cycle.
* **`blanton_multiphase_margin.sh save` is permanent**, and must not be mixed with `margin.sh`.
* **`READ_VIN` and `READ_IIN` are still not in the ADPM12200 coefficient table.**
* **The BMC USB service log only exists on the USB stick.**
* **`FAN_SPEED` is 100.**
* **Still unverified from v1.1.0**: the `ce0` ingress mirror, the 120 s settle in `blanton_tr518.sh`, and `test mode nr=no` on stop.
## 📦 Downloads
| File | Contents |
|---|---|
| `Script_ABC_Blanton_V1.2.1.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 ~/hammer/tools/amd/mlucas-avx2 # must already be there
```
## 🔗 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.0...V1.2.1](https://etgit.et-wen.com/etwen/Blanton_TTL_Script/compare/V1.2.0...V1.2.1)
+63
View File
@@ -0,0 +1,63 @@
# v1.2.2 — The 100G uplink joins the BER sweep, and a boot cycle that can pull the power
## ✨ New features
**The BER sweep now measures port 268, the 100G uplink**
* The port list ran `256-259` straight to `270-308`, so `ce0(268)` — the 100G uplink — was never in it. It is now its own group alongside the 200G ports.
* The summary gives **each unit three rows**: `200G ports`, `100G p268`, and `TOTAL`. Unit 0 and unit 1 each have their own `ce0(268)`, and a marginal uplink lane averaged into 432 others is invisible; on its own row it is not.
* A group that reports no lane at all now counts as a **failure**, not a pass. Silence on the port under test is the easiest way to ship a green report that measured nothing.
**Script 5 is now a boot cycle, warm or cold**
* `5_Blanton_Script_Reboot_Cycle.ttl` → `5_Blanton_Script_Boot_Cycle.ttl`, with `EN_Cold_Warm_boot` in `config.ttl` choosing: `1` = `reboot` (warm), `2` = a cold cycle by writing the CB FPGA, `0` = neither.
* The log file and the per-round banner are named after the kind of boot: `Blanton_Reboot_Cycle_<ts>.log` / `Reboot Cycle : N`, or `Blanton_Power_Cycle_<ts>.log` / `Power Cycle : N`.
* Both stress logs are removed before each run. `qfx5252-stress-*` appends to its `--log` and the macro `cat`s the whole thing, so every cycle was printing back everything the earlier cycles had written — 289 lines at cycle 1 and 36,555 by cycle 199. At roughly 6.2 ms a line on a 115200 console that accounted for **+212 s of the +214 s the cycle grew** over a 199-cycle run. The DUT was never getting slower.
**`bcm_100g_dsc_cycle.sh` — 100G link down/up cycling with SerDes capture**
* Tuning once, then N cycles of `port 268 en=0` → wait → `en=1` → wait → `phydiag 268 dsc` on both units → retimer `serdes-tx-get` / `serdes-rx-get` for `sys 0..7`. One log per run under `~/dsc_log/`, split by `### TEST CYCLE n/N`.
* Waiting is a **poll of `bcmcmd ps 268`**, not `show interfaces status`. `port en=` changes the SDK, and the SONiC table only follows once gbsyncd has synced it — and this test pauses gbsyncd.
* `-d` echoes every command as a grey `[CMD]` line before running it; `-n` is a dry run that touches nothing; the cycle count can be a bare argument (`./bcm_100g_dsc_cycle.sh 200`).
## 🐛 Bug fixes
**`blanton_ber.sh init` reported a hard error on runs that were working**
* `[ERR ] unit 1: the BCM shell rejected 'phydiag ... prbs get'` — except the command was fine. `prbs get` prints one line per lane, a lane that has not locked says `PRBS Error!`, and the rejection check grepped the **whole** output case-insensitively for `ERROR|Invalid|...`.
* Worse than the false alarm: the function returned early, so the lock count that was meant to judge those very lanes never ran. The operator saw an error they could not act on, and did **not** see which lanes had failed to lock. That check has been there since v1.0.0.
* Per-lane result lines are now excluded, the match is case-sensitive, and a genuine rejection prints the offending line.
## 🔧 Changes
* **Script A takes a BER baseline before its first traffic run** (v1.2.1), so together with Script C's closing sweep the pair brackets the soak.
* **`EN_TX_FIR`** gates the SerDes DSC scans in Script A and Script C. Default `0`: a full scan is ~10 min and both scripts do one.
## 📦 Downloads
| File | Contents |
|---|---|
| `Script_ABC_Blanton_V1.2.2.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 ~/hammer/tools/amd/mlucas-avx2 # must already be there
```
## ⚠️ Before you run
* **Replace `config.ttl` with the macros.** `EN_Cold_Warm_boot` is new, and Tera Term aborts on an undefined variable rather than treating it as 0.
* **Do not run the boot cycle with `EN_Cold_Warm_boot = 0`.** Nothing reboots, the `wait "Booting in blind mode"` underneath has no timeout, and since v1.2.2 there is no `logopen` either — so it hangs *and* leaves no log showing where. `0` is the value for the A → B → C flow, where that macro is not used.
* **The cold path writes a raw FPGA register.** `0x480` is `ICB_CTRL_REG`; the register map carries no bit definitions for it and `0xD0000` is not documented anywhere in this repo. The BDF `0000:05:00.0` is hard-coded while `blanton_fpga_pcimem.sh` auto-detects it because it moves per unit — **check the BDF on every board before running the cold path**.
* **Anything that parses these logs must accept both banners**, `Reboot Cycle : N` and `Power Cycle : N`. A parser that greps only the first finds zero cycles in a power-cycle log and reports nothing without complaining.
* **`bcm_100g_dsc_cycle.sh` has not been run on hardware.** It pauses `gbsyncd0/1` for tuning and unpauses them on exit, Ctrl-C included; `-P` leaves them alone.
* **`sleep 30` and `BER_INTERVAL` now live in three places** — Script A, Script C and `blanton_ber.sh`.
* **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`.
* **`READ_VIN` and `READ_IIN` are still not in the ADPM12200 coefficient table.**
* **`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.1...V1.2.2](https://etgit.et-wen.com/etwen/Blanton_TTL_Script/compare/V1.2.1...V1.2.2)
+14 -2
View File
@@ -7,6 +7,9 @@
# publish/Script_ABC_Blanton_<Version>, taking <Version> # publish/Script_ABC_Blanton_<Version>, taking <Version>
# from the "; Version : Vx.y.z" header of # from the "; Version : Vx.y.z" header of
# 1_Blanton_Script_A.ttl. # 1_Blanton_Script_A.ttl.
# V1.0.1 2026-09-06 Exclude hammer/ (the mlucas binaries) from the bundle,
# so the output no longer depends on whether the developer
# has them in their working tree.
# ============================================================================= # =============================================================================
# #
# The version is READ FROM Script A rather than passed in, so the folder name # The version is READ FROM Script A rather than passed in, so the folder name
@@ -33,7 +36,9 @@ info() { printf '[\033[34mINFO\033[0m] %s\n' "$*"; }
ok() { printf '[\033[32m OK \033[0m] %s\n' "$*"; } ok() { printf '[\033[32m OK \033[0m] %s\n' "$*"; }
die() { printf '[\033[31mERR \033[0m] %s\n' "$*" >&2; exit 1; } die() { printf '[\033[31mERR \033[0m] %s\n' "$*" >&2; exit 1; }
usage() { sed -n '2,26p' "${BASH_SOURCE[0]}" | sed 's/^# \{0,1\}//'; exit 0; } # Print the header block above, up to (but not including) the first line of
# code, so adding a Version History entry never truncates the usage text.
usage() { sed -n '2,/^set -u/p' "${BASH_SOURCE[0]}" | sed '$d' | sed 's/^# \{0,1\}//'; exit 0; }
while [ $# -gt 0 ]; do while [ $# -gt 0 ]; do
case "$1" in case "$1" in
@@ -86,12 +91,19 @@ fi
# Captured console logs are per-run and often carry DUT serials, so they are # Captured console logs are per-run and often carry DUT serials, so they are
# never shipped; the empty logs/ directory itself is kept because Script A's # never shipped; the empty logs/ directory itself is kept because Script A's
# logopen writes into it. # logopen writes into it.
#
# hammer/ is excluded as well: it is ~99 MB of mlucas ELF binaries that the DUT
# image already carries, and it is gitignored. Without this exclude the bundle
# would depend on whether the developer happened to have the binaries sitting in
# src/ - 100 MB from one machine, 200 KB from a fresh clone.
mkdir -p -- "${DEST}" || die "cannot create ${DEST}" mkdir -p -- "${DEST}" || die "cannot create ${DEST}"
if command -v rsync >/dev/null 2>&1; then if command -v rsync >/dev/null 2>&1; then
rsync -a --exclude='*.log' "${SRC_DIR}/" "${DEST}/" || die "rsync failed" rsync -a --exclude='*.log' --exclude='hammer/' "${SRC_DIR}/" "${DEST}/" \
|| die "rsync failed"
else else
cp -a -- "${SRC_DIR}/." "${DEST}/" || die "cp failed" cp -a -- "${SRC_DIR}/." "${DEST}/" || die "cp failed"
find "${DEST}" -type f -name '*.log' -delete find "${DEST}" -type f -name '*.log' -delete
rm -rf -- "${DEST}/hammer"
fi fi
# Tera Term's logopen target, in case the source tree never had one # Tera Term's logopen target, in case the source tree never had one
+608 -40
View File
@@ -1,7 +1,7 @@
; ============================================================================= ; =============================================================================
; Script A for Blanton ; Script A for Blanton
; Version : V1.1.2 ; Version : V1.2.2
; Date : 2026-08-28 ; Date : 2026-09-15
; Author : ETWen ; Author : ETWen
; ============================================================================= ; =============================================================================
; Version History: ; Version History:
@@ -161,6 +161,537 @@
; the job dir for the USB archive ; the job dir for the USB archive
; Fix: that cp said nfc_polling.log - the file is ; Fix: that cp said nfc_polling.log - the file is
; nfc_poll.log, so the NFC log never reached the USB ; nfc_poll.log, so the NFC log never reached the USB
; V1.1.3 2026-08-30 LTC2980_Margin_Script/settings/*.conf VNOM is now the measured median, not the spec value
; 86 of 144 rails moved up +0.8% .. +2.5%
; (3.3 -> 3.38, 0.9 -> 0.915, 0.8 -> 0.82, ...)
; This is NOT display-only: VNOM is the denominator of
; margin_status deviation % AND the basis margin_set
; derives high/low/OV/UV from, so the whole margin
; window shifts with it
; !! margin logs from before/after cannot be compared
; LTC2980_Margin_Script/profiles/ Add per-CONN SWB profiles, drop comboA/comboB
; combo_SWB_CONN13..16_{high,low} - the percentages
; follow that board rails, so applying one to a
; different CONN margins the wrong things, silently
; SWB0 and SWB1 share a profile per CONN (same rails)
; LTC2980_Margin_Script/script/*.sh Fix: margin_apply_profile_all.sh still pointed every
; board at comboA, which this change deleted - all 9
; boards would have failed with "Profile not found"
; docs/LTC2980_channel_map.csv Regenerated (tools/gen_channel_map.sh) - it is output
; V1.1.4 2026-08-31 4_Blanton_Script_thermal_safety.ttl Add the thermal / safety run - a STANDALONE script,
; not part of the A -> B -> C chain
; Script A style setup (login, session, fan, wait_init,
; DUT info, BMC, PCIe clear, pcie_bus, pmon, dmesg)
; then FULL LOAD: mlucas-avx2 -cpu 0:15 in the
; background + blanton_tr518.sh start
; then while 1: setup_pmon + TH6_SWB0/SWB1 power
; readback + bgctl list + jobs, pause 60
; !! no teardown section: after you interrupt it the
; unit is still on port cd lb=mac / l2 learn off /
; test mode nr=yes - run blanton_tr518.sh stop
; !! it drives the same ports as traffic and BER, so it
; cannot share a DUT with Script B
; ScriptB Drop the margin scan from the soak loop
; The loop is a fast per-minute sample; margin_status
; walks 9 LTC2980 over I2C and dominated the round
; ScriptC Take the margin scan instead, once, before uptime
; Trade-off: no margin drift DURING the soak any more,
; only a start (Script A) and end (Script C) reading
; ScriptC exit + wait "Script done" before hw-test-session
; finish - leaves the session shell first, so finish
; runs in the login shell that opened it
; docs/Blanton_Test_Flow.drawio Add the A/B/C + thermal flow diagram
; V1.1.5 2026-09-01 ScriptB Stress jobs now last the whole soak
; BMC DDR memtester 64M 1 -> 64M (loop count
; dropped = runs until stopped)
; SSD --runtime 3600 -> 86400
; USB --runtime 60 -> 86400
; The USB one finished after 60 SECONDS, so an
; overnight run had USB idle for all but the first
; minute and nothing said so
; !! 86400 is 24h: a soak longer than that leaves SSD
; and USB dead for the remainder - the per-round
; bgctl list (V1.0.10) is where that shows up
; Blanton_Script/blanton_multiphase_margin.sh Add multiphase VRM margin over the native i2c buses
; high3 / low3 / comboA / comboB / save, -u 0|1|all
; 38 rails (19 per SWB), one line each:
; SWB0_0V9_ANLG0 - 0.930V Configure Done
; save has no per-rail map, prints Multiphase Save All
; !! save is STORE_USER_ALL - permanent, survives a
; power cycle
; !! these are NOT the LTC2980s margin.sh drives; the
; two tools reach the same rails from different
; sides - do not run both
; Blanton_Script/blanton_traffic_linespeed.sh v0.7.0 tx gains PatternRandom, defaults change
; tx 100 length=512 -> tx 200 length=324
; every burst now ends PatternRandom=yes, ce0 included
; A fixed pattern can sit on a benign bit sequence for
; a whole run; random is what exposes a weak lane
; -r no forces the fixed pattern, -r "" omits the
; argument entirely (pre-v0.7.0 wire format)
; !! bytes per burst went 51200 -> 64800 (+27%), so
; counter totals are not comparable across this
; build - the PASS/FAIL cross-check is unaffected
; tools/Multiphase_*.txt Bench command references for the new script
; V1.1.6 2026-09-02 Blanton_Script/pwr_brick.sh Add PDB / CPB power brick readings
; 5 devices, Vin / Iin / Vout / Iout / Temp:
; SWB0.PU207 0x62 SWB0.PU13 0x63
; SWB1.PU332 0x60 SWB1.PU85 0x61
; CPB.PU37 0x26
; The four ADPM12200 put each measurement on its own
; PMBus PAGE, so a PAGE write has to precede every
; read - blanton_pwr_data.sh sends none, which is why
; it reports the whole PDB table as NA
; Vin PAGE 9 Iin PAGE 10 Vout PAGE 2
; Iout PAGE 14 Temp PAGE 18
; !! the bring-up spreadsheet wrote those page numbers
; in decimal but with an 0x prefix (10 -> 0x10,
; 14 -> 0x14, 18 -> 0x18). Only Vout worked,
; because 2 reads the same either way
; Conversions are the datasheet DIRECT equation
; X = (1/m)(Y x 10^-R - b), Table 3: voltage Y x 8mV,
; current Y x 0.04A, temperature Y x 0.01C
; Checked: READ_VOUT 0x05D4 -> 11936 mV, the same
; figure show platform reports for that rail
; !! Table 3 does NOT list READ_VIN / READ_IIN; they
; borrow the voltage / current coefficients here
; Each value is re-read until it passes: not 0xFFFF,
; not 0x0000, and inside a plausibility window. This
; bus corrupts the HIGH BYTE only, which turns 11.98 V
; into 32.00 V - a value no all-ones filter catches
; docs/ADPM12200..._Datasheet_2025_12_19.pdf The brick datasheet the pages and coefficients above
; came from
; ScriptC Re-enable the BMC USB service log, and send it to
; a file instead of the console
; journalctl ... -o short-iso > log/bmc_usb_net.log
; then cp it into the job dir for the USB archive
; rm -f first, so the file is this run only
; -o short-iso gives it timestamps that line up with
; the other monitor logs
; !! it no longer appears in the master console log,
; so the USB copy is now the ONLY copy - if that
; cp fails the service log is gone
; LTC2980_Margin_Script/profiles/ Add comboA / comboB per board (CB + SWB CONN13..16)
; Checkerboard pair: comboB is comboA with every
; direction flipped, so running both covers each rail
; high and low while its neighbours sit the other way
; NC channels stay nominal in both (CONN14 CH10/11/13,
; CONN15 CH10) - nothing to margin on an unused rail
; V1.1.7 2026-09-04 Blanton_Script/blanton_multiphase_margin.sh v1.1.0 Add the 'normal' sub-command
; Puts all 38 rails back to their nominal set point,
; from tools/Multiphase_Normal.txt - same rails and the
; same per-rail reporting as the margin profiles
; Until now the only way back from a margin was a power
; cycle, and 'save' run while margined would have
; committed the offsets to NVM, where a power cycle does
; not help either
; !! TH6_CORE is 0.8 V nominal but settles near 0.8591 V
; once the load line is active - reading back 0.859
; after 'normal' is the load line, not a failed write
; tools/Multiphase_Normal.txt Bench command reference for the above
; 5_Blanton_Script_Reboot_Cycle.ttl Created Reboot-cycle run - a STANDALONE script, not
; chained to A -> B -> C and not using hw-test-session:
; every cycle is a fresh boot, so there is nothing to
; carry over and nothing to tear down
; while 1: login -> sudo -i -> date -s -> fans -> wait_init
; -> Check Pt1..Pt13 -> show uptime -> reboot ->
; wait 'Booting in blind mode'
; cnt_cycle is printed in the banner of every round
; Pt1 DUT info (boot/version/fwutil/syseeprom/ssdhealth/
; TPM/NVMe) Pt2 BMC info + source the bash tools
; Pt3 mgmt ping Pt4 NFC poll (20 s)
; Pt5 SSD stress Pt6 USB stress (node from
; usb_target.sh, not a fixed sda1)
; Pt7 BMC USB net Pt8 100G port status + 15 s traffic
; Pt9 BER sweep Pt10 NVMe error info
; Pt11 platform data Pt12 dmesg i2c
; Pt13 PCIe error counters + ras-mc-ctl
; !! there is NO exit condition - the only way to stop it
; is to close the Tera Term macro
; !! NOT verified on hardware yet
; The cdc_ncm probe sets timeout = 15 and restores it to 0
; BEFORE the if, so both branches are covered in one line -
; the ping block below it waits on a 'sleep 10', which is
; already two thirds of the cap on a loaded DUT
; The probe was copied from Script B without its :skip_ping
; label, so 'goto skip_ping' had no target. Tera Term only
; raises that when it actually jumps, i.e. only when the
; NCM interface is missing - the label is now there
; Renumbered the second 'Check Pt12' (PCIe error counters)
; to Pt13; Pt1..Pt13 are now unique
; ScriptB Restore timeout = 0 on the cdc_ncm success path too
; It was only restored at :skip_ping, which the success
; path reaches several waits later - until then every wait
; was capped at 15 s instead of blocking
; .gitignore Ignore tmp/ - scripts not yet verified on hardware
; blanton_reboottest.sh (the bash port of the reboot cycle,
; for running without Tera Term) lives there until it has
; been run on a DUT. Unverified scripts must not reach the
; publish bundle: the tester cannot tell which ones to
; trust once they are side by side in Blanton_Script/
; config.ttl Add SSD_RUNTIME / SSD_COUNT / USB_RUNTIME / USB_COUNT
; The SSD and USB stress durations were hard-coded in
; ScriptB (--runtime 86400 --passes 5 / 1); they are now
; declared in one place per site
; !! --runtime is the job's OVERALL limit, not per pass:
; qfx5252-stress-* stops at RUNTIME seconds whatever
; --passes says. RUNTIME 600 = a 10 minute stress,
; not 600 x COUNT. For a 24 h soak set RUNTIME 86400
; ScriptB Build the SSD / USB stress commands from those knobs
; sprintf2 cmd_ssd ... SSD_RUNTIME SSD_COUNT, and the same
; for USB; the old hard-coded lines are left commented out
; next to them
; V1.1.8 2026-09-06
; ScriptA Drive logopen's timestamp flag from EN_timestamp
; logopen filename 0 1 1 EN_timestamp, with the argument
; order spelled out above the call: <file> <binary>
; <append> <PlainText> <timestamp>
; binary must stay 0. In binary mode Tera Term writes the
; raw stream and both PlainText and the timestamp are
; ignored
; !! EN_timestamp has to exist in config.ttl. An undefined
; variable aborts the macro at logopen, it is not read
; as 0
; !! the timestamp FORMAT lives in TERATERM.INI (Setup >
; Additional settings > Log), so it follows the PC and
; not this script. Two testers can produce differently
; stamped logs from one macro
; ScriptB Run mlucas as a systemd unit, not a shell background job
; systemd-run --unit=mlucas-amm --property=Type=exec
; --property=Restart=always --property=RestartSec=2
; The '&' job belonged to the interactive shell: it died
; with the session, and 'jobs' could not see it from a
; reconnected one, so a soak that lost its terminal quietly
; stopped loading the CPU
; The log is truncated with '>' before the unit starts and
; appended with '>>' inside it, so a restart adds to the
; run instead of erasing it
; 'systemctl is-active mlucas-amm' now sits beside 'jobs',
; both in the one-shot check and in the monitor loop at the
; end
; !! the old '&' line is kept commented out directly above
; it, to fall back to if systemd-run is unavailable
; ScriptB Take the BMC USB ping duration from BMC_USB_RUNTIME
; sprintf2 cmd '... -w %d ...' ncm_if BMC_USB_RUNTIME. It
; was hard-coded to 14400 (4 h), which no longer matched
; the soak the SSD and USB knobs were set for
; ScriptC Stop mlucas-amm and copy its log to the USB stick
; utils/kill_all_process.ttl is only "kill $(jobs -p)", and
; a systemd unit is not a shell job
; ScriptB's change on its own would have left mlucas
; loading all 16 cores through ScriptC and into the next
; run, so every temperature and power reading after it
; would have been taken under load
; cp ~/hammer/tools/amd/mlucas_amm_log /host/hw-eval/jobs/
; joins the other stress logs
; !! ScriptB and ScriptC change together. Whoever moves a
; stress job to systemd owns the matching stop in
; ScriptC
; Script4 Use the same mlucas-amm systemd unit as ScriptB
; The thermal / safety macro started mlucas the same way
; ScriptB used to, with '&', so it had the same failure:
; the load quietly ended when the console went away, in the
; one test where a long steady full load is the whole point
; 'systemctl is-active mlucas-amm' joins 'bgctl list' and
; 'jobs' in the monitor loop
; !! Script4 still has no teardown section, so the matching
; stop is manual: blanton_tr518.sh stop AND systemctl
; stop mlucas-amm. Closing Tera Term no longer stops the
; CPU load, and 'kill $(jobs -p)' never reached a unit
; config.ttl Add EN_timestamp and BMC_USB_RUNTIME, raise stress runtimes
; EN_timestamp = 1 feeds ScriptA's logopen; BMC_USB_RUNTIME
; = 172800 feeds ScriptB's ping unit
; SSD_RUNTIME and USB_RUNTIME 600 -> 3600, so the shipped
; default is a one hour stress rather than the ten minutes
; V1.1.7 went out with
; !! --runtime is still the job's OVERALL limit. RUNTIME
; 3600 = one hour of stress; COUNT does not multiply it.
; For a 2 day soak set RUNTIME 172800
; .gitignore Ignore src/Script_ABC_Blanton/hammer/
; ~99 MB of unstripped mlucas ELF binaries (avx512 / avx2 /
; avx / sse2 / generic-c) that ScriptB and the thermal
; macro chmod and run on the DUT
; !! they are deliberately NOT in git. A binary tree that
; large is permanent once committed and every clone pays
; for it forever; the DUT image already carries hammer/
; publish/publish.sh Exclude hammer/ from the delivery bundle
; rsync copies whatever sits in src/, so a developer who
; happened to have the binaries locally would have shipped
; a 100 MB zip while a clone shipped 200 KB. The bundle is
; now the same either way
; V1.1.9 2026-09-07
; Blanton_Script/bcm_dsc_scan.sh Created V1.2.0 - batch SerDes DSC dump
; Runs bcmcmd -n <unit> -c "dsh -c 'phydiag <port> dsc'"
; over the whole port list (1 x 100G + 445 x 200G ranges),
; both units, and leaves the raw log in <script_dir>/log
; before copying it to /host/hw-eval/jobs
; -f names the log (%u -> u0/u1, %t -> timestamp), -F
; overwrites, -u picks one unit, -n dry runs, -C skips the
; copy. -f takes a filename only; the directory comes from
; -o
; bcmcmd exits 0 even when the diag shell rejects a
; command, so success is judged by counting 'SERDES DISPLAY
; DIAG DATA END' markers, not by the exit code - the same
; trap blanton_traffic_linespeed.sh hit
; Paths come from $0, not $HOME, because Script A runs it
; after sudo -i and a literal ~ would depend on the
; environment. Ends with '### DSC_SCAN_DONE rc=<n>' for a
; TTL wait to key on
; Non-tty output is one line per port instead of a progress
; bar, so it does not flood the Tera Term log
; !! phydiag dsc is read-only and does not change any
; SerDes setting, but a full scan is ~10 min per run.
; ScriptA and ScriptC each do one, so the test is ~20
; min longer than before. Do not set DELAY to 0
; Blanton_Script/bcm_dsc_parse.sh Created V1.0.0 - offline DSC log to CSV
; Host side. -i <raw log> -o <prefix> produces
; <prefix>_lane.csv (one row per lane: TXEQ / RXFFE / DFE /
; EYE / SNR) and <prefix>_pm.csv (one row per pm_id:
; temperature / PLL / lane count / SNR-EYE stats)
; POSIX sh + awk, mawk compatible, no Python. Lane rows are
; read by the order of their bracket groups rather than
; fixed columns, so re-spacing by the SDK does not break
; it; a row whose group count is not 9 is marked UNPARSED
; on stderr instead of being parsed wrongly
; SD / LCK sticky '*' flags are kept as separate columns
; and not interpreted; a BER field of '!chk_en' means the
; checker was off and is passed through unchanged
; ScriptA Collect the SerDes DSC baseline before 'show uptime'
; ./Blanton_Script/bcm_dsc_scan.sh -f
; blanton_dsc_ScriptA.log -F
; The name has no %u, so the script inserts _u0 / _u1
; itself and unit 1 cannot overwrite unit 0 - that is where
; the file names ScriptC copies come from
; ScriptA / ScriptB / ScriptC Remove the commented-out 100G PRBS blocks
; The port_prbs_monitor.sh calls had been commented out in
; all three since bring-up, together with a second copy of
; the 100G port status block in ScriptA and the stale
; bmc_monitor_ddr.sh block in ScriptC
; port_prbs_monitor.sh still ships and still runs by hand;
; only the dead call sites are gone
; ScriptC Collect the closing DSC dump and carry the four logs out
; ./Blanton_Script/bcm_dsc_scan.sh -f
; blanton_dsc_ScriptC.log -F, then cp of
; blanton_dsc_Script{A,C}_u{0,1}.log into
; /host/hw-eval/jobs/
; The scan already copies its own output there; these four
; are a second pass so a failed copy inside the scan still
; leaves the data on the USB stick
; Blanton_Script Both new scripts need the execute bit on the DUT
; !! git records them 100644 like every other .sh here, and
; ScriptA / ScriptC invoke them as
; ./Blanton_Script/bcm_dsc_scan.sh, so they join
; bmc_monitor.sh and friends in the chmod +x line after
; deployment. Without it both scans fail with Permission
; denied and the macro walks straight past it
; V1.2.0 2026-09-07
; Blanton_Script/bcm_dsc_scan.sh v1.3.0 bcmcmd was eating the port list
; The scan loop read the port file on stdin, and bcmcmd
; reads stdin too, so the first call swallowed the rest of
; the file and the loop ended after ONE port
; Nothing looked wrong: the log held one PORT marker and
; one dsc block, markers == dumps, exit code 0. A 445 port
; scan finished in seconds and reported success
; Fixed by reading the loop on fd 3 (done 3< "$PORTFILE")
; and giving bcmcmd < /dev/null
; Added a check that the iteration count equals the port
; list count. The marker / dump comparison cannot catch a
; loop that ends early, because both numbers shrink
; together; the Saved: line now reports dumps out of TOTAL,
; not out of markers
; !! this is the same bcmcmd trap
; blanton_traffic_linespeed.sh hit at v0.3.1, where only
; the first VLAN was configured. Every while ... done <
; file loop that calls bcmcmd needs < /dev/null - assume
; it will read stdin unless proven otherwise
; ScriptA / ScriptB / ScriptC Wait on the DUT with 'sleep', not on the macro with 'pause'
; pause N stops the macro for N seconds without touching
; the DUT: the shell sits idle and the macro is guessing
; how long the last command took. sendln "sleep N" + wait
; prompt_sonic_root moves the wait onto the DUT, so the
; macro resumes when the prompt actually comes back and the
; two cannot drift apart
; It also lands in the console log with a timestamp, so a
; round that ran long is visible afterwards instead of
; invisible
; Durations changed with it: ScriptA mgmt ping 30 -> 15 s;
; the settle after every traffic 'clear' 15 -> 5 s; the
; traffic run itself stays 15 s; ScriptB's monitor loop
; stays 60 s
; !! Script4 and Script5 were NOT converted and still use
; pause. The 'pause 1' at the top of ScriptB / ScriptC
; also stays - it only spaces the log header and runs
; before there is a prompt to wait for
; config.ttl Add EN_TX_FIR to gate the SerDes DSC scan
; EN_TX_FIR = 1 enables bcm_dsc_scan.sh in ScriptA and
; ScriptC, and the four cp lines that carry
; blanton_dsc_Script{A,C}_u{0,1}.log to /host/hw-eval/jobs.
; Default is 0
; A full scan is ~10 min and both scripts do one, so
; leaving it off keeps ~20 min out of a routine run. Turn
; it on when the SerDes data is what you are after
; ScriptC Stop printing the BMC poll and mlucas logs to the console
; cat bmc_poll.log and cat mlucas_amm_log are commented
; out. Both files are still copied to /host/hw-eval/jobs
; and out to the USB stick with everything else, so no data
; is lost - the master log is just shorter
; V1.2.1 2026-09-08
; ScriptA Add a BER baseline sweep before the traffic run
; blanton_ber.sh init / start / sleep 30 / report / stop /
; clear, branched on SWB_UNIT0 and SWB_UNIT1 the same way
; the traffic block is. ScriptC already took the closing
; sweep after its traffic report, so the two now bracket
; the soak the way the DSC scans do
; sleep 30 is not arbitrary: it is blanton_ber.sh's
; BER_INTERVAL. 'report' before one full interval has
; accumulated reads a window that has not finished
; The block was copied from ScriptC, which runs it AFTER
; traffic, and its comment said so. In ScriptA it runs
; BEFORE traffic, so the comment was rewritten to match
; where the code actually is
; !! nothing settles between 'blanton_ber.sh clear' and
; 'blanton_traffic_linespeed ps' that follows it. PRBS
; holds the lanes out of normal operation and 'clear' is
; what releases them, so the first traffic run of
; ScriptA now starts on lanes that have just been
; released. ScriptC does not have this ordering. Watch
; ScriptA's first traffic report for NA or FAIL pairs
; that ScriptC's does not show - if they appear, a sleep
; after 'clear' is the fix
; !! ScriptA now runs BER twice as far as the switch is
; concerned: once here and once inside ScriptC. Neither
; can overlap blanton_traffic_linespeed or
; blanton_tr518.sh - they all take over the same ports
; V1.2.2 2026-09-15
; 5_.._Boot_Cycle.ttl Renamed from 5_Blanton_Script_Reboot_Cycle.ttl
; It does warm and cold now, so 'Reboot' was too narrow.
; Same macro otherwise - git records it as a rename
; 5_.._Boot_Cycle.ttl Warm or cold boot, chosen by EN_Cold_Warm_boot
; 1 = 'reboot' (warm, what the macro always did). 2 = cold,
; by writing the CB FPGA: pcimem
; /sys/bus/pci/devices/0000:05:00.0/resource0 0x480 w
; 0xD0000. 0 = neither
; !! EN_Cold_Warm_boot = 0 hangs the macro. Neither branch
; runs, so nothing reboots, and the 'wait "Booting in
; blind mode"' underneath has no timeout - cycle 1
; finishes and the macro then waits for a boot that will
; never come. 0 is the value for the A/B/C flow, where
; this macro is not used at all; do not run ScriptBoot
; with it
; !! 0x480 is ICB_CTRL_REG in
; docs/Blantons_FPGA_Registers.md, and that table
; carries no bit definitions for it. 0xD0000 is not
; written down anywhere in this repo either. Whoever
; knows what those bits do should put it in the register
; doc before someone changes the value
; !! the BDF 0000:05:00.0 is hard-coded here, while
; blanton_fpga_pcimem.sh auto-detects the CB FPGA
; precisely because it moves per unit (see the V1.0.x
; notes and Key Constraints #4). On a DUT where the FPGA
; is not at 05:00.0 this becomes a raw 32-bit write to
; an unknown register on some other device. Verify the
; BDF on every unit before running the cold path
; !! NOT verified on hardware. The warm path has 199 cycles
; behind it; the cold path has none
; 5_.._Boot_Cycle.ttl Truncate the two stress logs before each run
; rm -rf /host/hw-eval/jobs/qfx5252-stress-ssd.log and the
; usb one, added ahead of each qfx5252-stress-* call
; qfx5252-stress-* APPENDS to its --log file and the macro
; cats the whole thing afterwards, so every cycle printed
; back everything the ones before it had written
; Measured on the 199 cycle log from 2026-09-04: cycle 1
; printed 289 lines, cycle 199 printed 36,555. At ~6.2 ms a
; line - which is what a 115200 baud console costs - that
; is +212 s of the +214 s the cycle grew over the run. The
; stress itself is fixed at --runtime 30, and the other
; eleven segments between check points drifted by less than
; 1.5 s each. The DUT was never getting slower; the test
; was reading its own history aloud once per cycle
; 5_.._Boot_Cycle.ttl Name the log file and the banner after the kind of boot
; EN_Cold_Warm_boot = 1 gives
; Logs\Blanton_Reboot_Cycle_<ts>.log and a 'Reboot Cycle :
; N' banner; = 2 gives Blanton_Power_Cycle_<ts>.log and
; 'Power Cycle : N'. Three sites now branch on the flag:
; the log name, the banner and the boot itself
; !! with 0 there is no longer a logopen either, so the run
; that already hangs at wait "Booting in blind mode" now
; also leaves no log to show where it stopped. EN_log =
; 1 no longer guarantees a log in this macro -
; EN_Cold_Warm_boot has to be 1 or 2 as well
; !! anything that parses these logs has to accept BOTH
; banners. The cycle banner is the record separator the
; check-point and per-segment timing reports are built
; on, so a parser that only greps 'Reboot Cycle :' finds
; zero cycles in a power-cycle log and silently reports
; nothing at all
; The logopen timestamp flag is still a literal 1 here
; rather than EN_timestamp the way ScriptA does it. Leaving
; it on is the right call - the per-segment timing analysis
; is derived from those timestamps and there is nothing
; else to recover them from - but it does mean this macro
; ignores EN_timestamp = 0
; config.ttl Add EN_Cold_Warm_boot
; 0 = normal test (A/B/C), 1 = reboot cycle, 2 = power
; cycle. Default 0 so that opening the shared config cannot
; reboot anyone's DUT by accident
; Blanton_Script/blanton_ber.sh v1.1.0 Add port 268, the 100G uplink
; The port list jumps 256-259 -> 270-308, so 268 (ce0) was
; never measured. It is now its own group: BER_PORTS_200G
; and BER_PORTS_100G, joined for the phydiag command but
; reported apart
; The summary gives each unit three rows - 200G ports /
; 100G p268 / TOTAL - because unit 0 and unit 1 each have
; their own ce0(268). A bad uplink lane averaged into 432
; others is invisible; on its own row it is not
; TOTAL is not a hand-added sum: every lane is folded into
; its own group and into ALL separately, so the parts
; cannot drift from the whole
; !! a group that reports no lane at all is a FAILURE, not
; a pass. Silence on the port under test is the easiest
; way to ship a green report that measured nothing
; Blanton_Script/blanton_ber.sh v1.1.1 Stop reading lane results as shell errors
; init kept answering "the BCM shell rejected 'phydiag ...
; prbs get'" on runs that were working. The check grepped
; the WHOLE output case-insensitively for
; ERROR|Invalid|..., and 'prbs get' prints one line per
; lane - a lane that had not locked says PRBS Error!, which
; matched
; So a good run reported a hard error, and worse, the
; function returned before the lock-count check that was
; supposed to judge those very lanes. The operator saw a
; failure and did NOT see which lanes were unlocked
; Per-lane lines are now excluded from the check, the match
; is case-sensitive, and a genuine rejection prints the
; offending line so it can be read
; !! this was in the file from v1.0.0. Any earlier init
; that printed that error was probably fine, and any
; earlier init that passed said nothing about lanes that
; had failed to lock
; Blanton_Script/bcm_100g_dsc_cycle.sh Created v1.2.0 - 100G link down/up cycle with DSC capture
; Tuning once (gbsyncd pause, serdes-tx-set sys 0..7,
; tx_taps per lane), then N cycles of: port en=0, wait,
; port en=1, wait, phydiag dsc on both units, serdes-tx-get
; and serdes-rx-get sys 0..7. One log per run under
; ~/dsc_log, split by '### TEST CYCLE n/N'
; Waiting polls 'bcmcmd ps <port>' every -p seconds up to
; -w, and reads the state from the row whose first field
; ends in (<port>). Asking the SDK matters here: 'port en='
; changes the SDK, while 'show interfaces status' only
; follows once gbsyncd has synced it - and this test pauses
; gbsyncd
; -d prints every command as [CMD] in grey before running
; it, CMD_DELAY paces them, -n is a dry run that touches
; nothing and sleeps not at all
; !! all output is ASCII English on purpose. The DUT serial
; console mangles UTF-8: a Chinese error message came
; back as "ERROR: -c ? 1", which is worse than no
; message
; !! NOT verified on hardware
; tools/100G_dsc_cycle.txt Created - the hand-typed command list behind that script
; Same role as BER_Test.txt and TR518.txt: the bench
; version of the commands, kept so the .sh can be checked
; against what a person would actually type. Change one and
; change the other
; ============================================================================= ; =============================================================================
include "config.ttl" include "config.ttl"
@@ -173,7 +704,11 @@ getdir mdir
if EN_log = 1 then if EN_log = 1 then
sprintf2 filename '%s\Logs\%s_%s_%s.log' mdir project_name strTestcase str_starttime sprintf2 filename '%s\Logs\%s_%s_%s.log' mdir project_name strTestcase str_starttime
logopen filename 0 1 1 1 ; logopen <file> <binary> <append> <PlainText> <timestamp>
; binary=0 text mode, so PlainText / timestamp are honoured
; append=1 keep earlier cycles, do not overwrite
; PlainText=1 strip the ANSI colour codes SONiC emits
logopen filename 0 1 1 EN_timestamp
endif endif
; ========== Root Login ========== ; ========== Root Login ==========
@@ -322,7 +857,8 @@ include "utils/show_dmesg.ttl"
wait prompt_sonic_root wait prompt_sonic_root
sendln "./Blanton_Script/mgmt_ping_monitor.sh start" sendln "./Blanton_Script/mgmt_ping_monitor.sh start"
wait prompt_sonic_root wait prompt_sonic_root
pause 30 sendln "sleep 15"
wait prompt_sonic_root
sendln "~/Blanton_Script/mgmt_ping_monitor.sh stop" sendln "~/Blanton_Script/mgmt_ping_monitor.sh stop"
wait prompt_sonic_root wait prompt_sonic_root
sendln "cat ~/Blanton_Script/log/mgmt_ping.log" sendln "cat ~/Blanton_Script/log/mgmt_ping.log"
@@ -357,36 +893,6 @@ sendln "config save -y"
wait prompt_sonic_root wait prompt_sonic_root
sendln "show interfaces status Ethernet513,Ethernet514" sendln "show interfaces status Ethernet513,Ethernet514"
;=============================================================================================================
; ========== 100G PRBS ==========
;wait prompt_sonic_root
;sendln "~/Blanton_Script/port_prbs_monitor.sh start"
;wait prompt_sonic_root
;sendln "sleep 10"
;wait prompt_sonic_root
;sendln "~/Blanton_Script/port_prbs_monitor.sh status"
;wait prompt_sonic_root
;sendln "~/Blanton_Script/port_prbs_monitor.sh stop"
;wait prompt_sonic_root
;sendln "~/Blanton_Script/port_prbs_monitor.sh report"
;wait prompt_sonic_root
;sendln "~/Blanton_Script/port_prbs_monitor.sh clear"
; ========== 100G Port Status ==========
;wait prompt_sonic_root
;sendln "sudo sfputil lpmode off Ethernet513"
;wait prompt_sonic_root
;sendln "sudo sfputil lpmode off Ethernet514"
;wait prompt_sonic_root
;sendln "config interface -n asic0 startup Ethernet513"
;wait prompt_sonic_root
;sendln "config interface -n asic1 startup Ethernet514"
;wait prompt_sonic_root
;sendln "config save -y"
;wait prompt_sonic_root
;sendln "show interfaces status Ethernet513,Ethernet514"
;=============================================================================================================
; ========== First Traffic Test ========== ; ========== First Traffic Test ==========
; Silent MAC ; Silent MAC
@@ -395,6 +901,56 @@ sendln "config feature state lldp disabled"
wait prompt_sonic_root wait prompt_sonic_root
sendln "config save -y" sendln "config save -y"
; ========== BER ==========
; Baseline sweep, taken BEFORE the traffic run - ScriptC takes the closing
; one after its traffic report, so the pair brackets the soak.
; PRBS takes the SerDes out of normal operation; 'clear' is what puts the
; lanes back, so it has to run before the traffic block below.
; sleep 30 matches blanton_ber.sh BER_INTERVAL - reporting earlier reads an
; interval that has not finished accumulating.
if SWB_UNIT0 = 1 && SWB_UNIT1 = 1 then
wait prompt_sonic_root
sendln "./Blanton_Script/blanton_ber.sh init"
wait prompt_sonic_root
sendln "./Blanton_Script/blanton_ber.sh start"
wait prompt_sonic_root
sendln "sleep 30"
wait prompt_sonic_root
sendln "./Blanton_Script/blanton_ber.sh report"
wait prompt_sonic_root
sendln "./Blanton_Script/blanton_ber.sh stop"
wait prompt_sonic_root
sendln "./Blanton_Script/blanton_ber.sh clear"
elseif SWB_UNIT0 = 1 && SWB_UNIT1 = 0 then
wait prompt_sonic_root
sendln "./Blanton_Script/blanton_ber.sh init -u 0"
wait prompt_sonic_root
sendln "./Blanton_Script/blanton_ber.sh start -u 0"
wait prompt_sonic_root
sendln "sleep 30"
wait prompt_sonic_root
sendln "./Blanton_Script/blanton_ber.sh report -u 0"
wait prompt_sonic_root
sendln "./Blanton_Script/blanton_ber.sh stop -u 0"
wait prompt_sonic_root
sendln "./Blanton_Script/blanton_ber.sh clear -u 0"
elseif SWB_UNIT0 = 0 && SWB_UNIT1 = 1 then
wait prompt_sonic_root
sendln "./Blanton_Script/blanton_ber.sh init -u 1"
wait prompt_sonic_root
sendln "./Blanton_Script/blanton_ber.sh start -u 1"
wait prompt_sonic_root
sendln "sleep 30"
wait prompt_sonic_root
sendln "./Blanton_Script/blanton_ber.sh report -u 1"
wait prompt_sonic_root
sendln "./Blanton_Script/blanton_ber.sh stop -u 1"
wait prompt_sonic_root
sendln "./Blanton_Script/blanton_ber.sh clear -u 1"
else
endif
if SWB_UNIT0 = 1 && SWB_UNIT1 = 1 then if SWB_UNIT0 = 1 && SWB_UNIT1 = 1 then
wait prompt_sonic_root wait prompt_sonic_root
sendln "blanton_traffic_linespeed ps" sendln "blanton_traffic_linespeed ps"
@@ -403,12 +959,14 @@ if SWB_UNIT0 = 1 && SWB_UNIT1 = 1 then
wait prompt_sonic_root wait prompt_sonic_root
sendln "blanton_traffic_linespeed clear" sendln "blanton_traffic_linespeed clear"
wait prompt_sonic_root wait prompt_sonic_root
pause 15 sendln "sleep 5"
wait prompt_sonic_root
sendln "blanton_traffic_linespeed show" sendln "blanton_traffic_linespeed show"
wait prompt_sonic_root wait prompt_sonic_root
sendln "blanton_traffic_linespeed start" sendln "blanton_traffic_linespeed start"
wait prompt_sonic_root wait prompt_sonic_root
pause 15 sendln "sleep 15"
wait prompt_sonic_root
sendln "blanton_traffic_linespeed stop" sendln "blanton_traffic_linespeed stop"
wait prompt_sonic_root wait prompt_sonic_root
sendln "blanton_traffic_linespeed report" sendln "blanton_traffic_linespeed report"
@@ -420,12 +978,14 @@ elseif SWB_UNIT0 = 1 && SWB_UNIT1 = 0 then
wait prompt_sonic_root wait prompt_sonic_root
sendln "blanton_traffic_linespeed clear -u 0" sendln "blanton_traffic_linespeed clear -u 0"
wait prompt_sonic_root wait prompt_sonic_root
pause 15 sendln "sleep 5"
wait prompt_sonic_root
sendln "blanton_traffic_linespeed show -u 0" sendln "blanton_traffic_linespeed show -u 0"
wait prompt_sonic_root wait prompt_sonic_root
sendln "blanton_traffic_linespeed start -u 0" sendln "blanton_traffic_linespeed start -u 0"
wait prompt_sonic_root wait prompt_sonic_root
pause 15 sendln "sleep 15"
wait prompt_sonic_root
sendln "blanton_traffic_linespeed stop -u 0" sendln "blanton_traffic_linespeed stop -u 0"
wait prompt_sonic_root wait prompt_sonic_root
sendln "blanton_traffic_linespeed report -u 0" sendln "blanton_traffic_linespeed report -u 0"
@@ -437,12 +997,14 @@ elseif SWB_UNIT0 = 0 && SWB_UNIT1 = 1 then
wait prompt_sonic_root wait prompt_sonic_root
sendln "blanton_traffic_linespeed clear -u 1" sendln "blanton_traffic_linespeed clear -u 1"
wait prompt_sonic_root wait prompt_sonic_root
pause 15 sendln "sleep 5"
wait prompt_sonic_root
sendln "blanton_traffic_linespeed show -u 1" sendln "blanton_traffic_linespeed show -u 1"
wait prompt_sonic_root wait prompt_sonic_root
sendln "blanton_traffic_linespeed start -u 1" sendln "blanton_traffic_linespeed start -u 1"
wait prompt_sonic_root wait prompt_sonic_root
pause 15 sendln "sleep 15"
wait prompt_sonic_root
sendln "blanton_traffic_linespeed stop -u 1" sendln "blanton_traffic_linespeed stop -u 1"
wait prompt_sonic_root wait prompt_sonic_root
sendln "blanton_traffic_linespeed report -u 1" sendln "blanton_traffic_linespeed report -u 1"
@@ -450,6 +1012,12 @@ else
endif endif
if EN_TX_FIR = 1 then
; ========== Collect bcm dsc data ==========
wait prompt_sonic_root
sendln "./Blanton_Script/bcm_dsc_scan.sh -f blanton_dsc_ScriptA.log -F"
endif
; ========== Show Power on uptime ========== ; ========== Show Power on uptime ==========
wait prompt_sonic_root wait prompt_sonic_root
sendln "show uptime" sendln "show uptime"
+30 -21
View File
@@ -15,10 +15,15 @@ pause 1
;sendln "command" ;sendln "command"
; ========== AMD CPU STRESS TEST ========== ; ========== AMD CPU STRESS TEST ==========
; Clear the log file first
wait prompt_sonic_root
sendln "> ~/hammer/tools/amd/mlucas_amm_log"
wait prompt_sonic_root wait prompt_sonic_root
sendln 'chmod +x ~/hammer/tools/amd/mlucas-avx2' sendln 'chmod +x ~/hammer/tools/amd/mlucas-avx2'
wait prompt_sonic_root wait prompt_sonic_root
sendln "~/hammer/tools/amd/mlucas-avx2 -s l -cpu 0:15 > ~/hammer/tools/amd/mlucas_amm_log 2>&1 &" ;sendln "~/hammer/tools/amd/mlucas-avx2 -s l -cpu 0:15 > ~/hammer/tools/amd/mlucas_amm_log 2>&1 &"
sendln "systemd-run --unit=mlucas-amm --property=Type=exec --property=Restart=always --property=RestartSec=2 /bin/bash -c '~/hammer/tools/amd/mlucas-avx2 -s l -cpu 0:15 >> ~/hammer/tools/amd/mlucas_amm_log 2>&1'"
; ========== BMC DDR Stress Test ========== ; ========== BMC DDR Stress Test ==========
;wait prompt_sonic_root ;wait prompt_sonic_root
@@ -26,7 +31,8 @@ sendln "~/hammer/tools/amd/mlucas-avx2 -s l -cpu 0:15 > ~/hammer/tools/amd/mluca
;wait prompt_sonic_root ;wait prompt_sonic_root
;sendln "./Blanton_Script/bmc_monitor.sh start" ;sendln "./Blanton_Script/bmc_monitor.sh start"
wait prompt_sonic_root wait prompt_sonic_root
sendln "bgctl run bmc-manager run '/usr/bin/memtester 64M 1'" ;sendln "bgctl run bmc-manager run '/usr/bin/memtester 64M 1'"
sendln "bgctl run bmc-manager run '/usr/bin/memtester 64M'" ; Continue Execture
; ========== BMC Monitor Test ========== ; ========== BMC Monitor Test ==========
wait prompt_sonic_root wait prompt_sonic_root
@@ -39,8 +45,10 @@ wait prompt_sonic_root
sendln "bgctl run /usr/sbin/memtester 1G" ; Continue Execture sendln "bgctl run /usr/sbin/memtester 1G" ; Continue Execture
; ========== SSD read/write ========== ; ========== SSD read/write ==========
sprintf2 cmd_ssd "bgctl run qfx5252-stress-ssd 1G --runtime %d --passes %d --write --force --log /host/hw-eval/jobs/qfx5252-stress-ssd.log" SSD_RUNTIME SSD_COUNT
wait prompt_sonic_root wait prompt_sonic_root
sendln "bgctl run qfx5252-stress-ssd 1G --runtime 3600 --passes 5 --write --force --log /host/hw-eval/jobs/qfx5252-stress-ssd.log" ;sendln "bgctl run qfx5252-stress-ssd 1G --runtime 86400 --passes 5 --write --force --log /host/hw-eval/jobs/qfx5252-stress-ssd.log"
sendln cmd_ssd
; ========== USB read/write ========== ; ========== USB read/write ==========
; ---- Get USB partition node -> usb_dev ---- ; ---- Get USB partition node -> usb_dev ----
@@ -51,7 +59,8 @@ waitregex '<<DEV=([^>]*)>>'
usb_dev = groupmatchstr1 usb_dev = groupmatchstr1
wait prompt_sonic_root wait prompt_sonic_root
sprintf2 cmd "bgctl run qfx5252-stress-usb %s 256M --runtime 60 --passes 1 --write --log /host/hw-eval/jobs/qfx5252-stress-usb.log" usb_dev ;sprintf2 cmd "bgctl run qfx5252-stress-usb %s 256M --runtime 86400 --passes 1 --write --log /host/hw-eval/jobs/qfx5252-stress-usb.log" usb_dev
sprintf2 cmd "bgctl run qfx5252-stress-usb %s 256M --runtime %d --passes %d --write --log /host/hw-eval/jobs/qfx5252-stress-usb.log" usb_dev USB_RUNTIME USB_COUNT
sendln cmd sendln cmd
;wait prompt_sonic_root ;wait prompt_sonic_root
@@ -61,6 +70,8 @@ sendln cmd
wait prompt_sonic_root wait prompt_sonic_root
sendln "jobs" sendln "jobs"
wait prompt_sonic_root wait prompt_sonic_root
sendln "systemctl is-active mlucas-amm"
wait prompt_sonic_root
sendln "bgctl list" sendln "bgctl list"
; ========== BMC USB Test ========== ; ========== BMC USB Test ==========
@@ -72,6 +83,7 @@ if result = 0 then
messagebox 'cdc_ncm interface not found. Ping test skipped.' 'ERROR' messagebox 'cdc_ncm interface not found. Ping test skipped.' 'ERROR'
goto skip_ping goto skip_ping
endif endif
timeout = 0
strlen matchstr strlen matchstr
cut_len = result - 6 ; 'NCMIF=' = 6 chars cut_len = result - 6 ; 'NCMIF=' = 6 chars
strcopy matchstr 7 cut_len ncm_if ; -> ncm_if = "eth2" / "eth3" strcopy matchstr 7 cut_len ncm_if ; -> ncm_if = "eth2" / "eth3"
@@ -84,7 +96,7 @@ wait prompt_sonic_root
sendln 'systemctl stop qfx5252-bmc-usb-net-test.service 2>/dev/null || true' sendln 'systemctl stop qfx5252-bmc-usb-net-test.service 2>/dev/null || true'
wait prompt_sonic_root wait prompt_sonic_root
sendln 'systemctl reset-failed qfx5252-bmc-usb-net-test.service 2>/dev/null || true' sendln 'systemctl reset-failed qfx5252-bmc-usb-net-test.service 2>/dev/null || true'
sprintf2 cmd 'systemd-run --unit=qfx5252-bmc-usb-net-test --property=Type=exec /usr/bin/ping -I %s -i 1 -W 2 -w 14400 192.168.200.200' ncm_if sprintf2 cmd 'systemd-run --unit=qfx5252-bmc-usb-net-test --property=Type=exec /usr/bin/ping -I %s -i 1 -W 2 -w %d 192.168.200.200' ncm_if BMC_USB_RUNTIME
wait prompt_sonic_root wait prompt_sonic_root
sendln cmd sendln cmd
@@ -97,7 +109,8 @@ timeout = 0
wait prompt_sonic_root wait prompt_sonic_root
sendln "./Blanton_Script/mgmt_ping_monitor.sh start" sendln "./Blanton_Script/mgmt_ping_monitor.sh start"
wait prompt_sonic_root wait prompt_sonic_root
pause 3 sendln "sleep 3"
wait prompt_sonic_root
sendln "./Blanton_Script/mgmt_ping_monitor.sh status" sendln "./Blanton_Script/mgmt_ping_monitor.sh status"
; ========== NFC Test ========== ; ========== NFC Test ==========
@@ -111,12 +124,6 @@ sendln "~/Blanton_Script/nfc_polling.sh status"
wait prompt_sonic_root wait prompt_sonic_root
sendln "show interfaces status Ethernet513,Ethernet514" sendln "show interfaces status Ethernet513,Ethernet514"
;=============================================================================================================
; ========== 100G PRBS ==========
;wait prompt_sonic_root
;sendln "~/Blanton_Script/port_prbs_monitor.sh start"
;=============================================================================================================
; ========== Traffic START ========== ; ========== Traffic START ==========
; Silent MAC ; Silent MAC
@@ -133,7 +140,8 @@ if SWB_UNIT0 = 1 && SWB_UNIT1 = 1 then
wait prompt_sonic_root wait prompt_sonic_root
sendln "blanton_traffic_linespeed clear" sendln "blanton_traffic_linespeed clear"
wait prompt_sonic_root wait prompt_sonic_root
pause 15 sendln "sleep 5"
wait prompt_sonic_root
sendln "blanton_traffic_linespeed show" sendln "blanton_traffic_linespeed show"
wait prompt_sonic_root wait prompt_sonic_root
sendln "blanton_traffic_linespeed start" sendln "blanton_traffic_linespeed start"
@@ -145,7 +153,8 @@ elseif SWB_UNIT0 = 1 && SWB_UNIT1 = 0 then
wait prompt_sonic_root wait prompt_sonic_root
sendln "blanton_traffic_linespeed clear -u 0" sendln "blanton_traffic_linespeed clear -u 0"
wait prompt_sonic_root wait prompt_sonic_root
pause 15 sendln "sleep 5"
wait prompt_sonic_root
sendln "blanton_traffic_linespeed show -u 0" sendln "blanton_traffic_linespeed show -u 0"
wait prompt_sonic_root wait prompt_sonic_root
sendln "blanton_traffic_linespeed start -u 0" sendln "blanton_traffic_linespeed start -u 0"
@@ -157,7 +166,8 @@ elseif SWB_UNIT0 = 0 && SWB_UNIT1 = 1 then
wait prompt_sonic_root wait prompt_sonic_root
sendln "blanton_traffic_linespeed clear -u 1" sendln "blanton_traffic_linespeed clear -u 1"
wait prompt_sonic_root wait prompt_sonic_root
pause 15 sendln "sleep 5"
wait prompt_sonic_root
sendln "blanton_traffic_linespeed show -u 1" sendln "blanton_traffic_linespeed show -u 1"
wait prompt_sonic_root wait prompt_sonic_root
sendln "blanton_traffic_linespeed start -u 1" sendln "blanton_traffic_linespeed start -u 1"
@@ -167,16 +177,15 @@ endif
; ========== Monitor loop: platform data + background jobs (pause 60s per round) ========== ; ========== Monitor loop: platform data + background jobs (sleep 60s per round) ==========
while 1 while 1
include "utils/setup_pmon.ttl" include "utils/setup_pmon.ttl"
wait prompt_sonic_root wait prompt_sonic_root
sendln "bgctl list" sendln "bgctl list"
wait prompt_sonic_root wait prompt_sonic_root
sendln "jobs" sendln "jobs"
; ========== Check Margin ========== wait prompt_sonic_root
if EN_Margin = 1 then sendln "systemctl is-active mlucas-amm"
include "utils/show_margin_status.ttl" wait prompt_sonic_root
endif sendln "sleep 60"
pause 60
endwhile endwhile
+41 -36
View File
@@ -12,6 +12,11 @@ pause 1
; ========== Kill Process ========== ; ========== Kill Process ==========
include "utils/kill_all_process.ttl" include "utils/kill_all_process.ttl"
wait prompt_sonic_root
sendln "systemctl is-active mlucas-amm"
wait prompt_sonic_root
sendln "systemctl stop mlucas-amm"
; bgctrl all stop ; bgctrl all stop
wait prompt_sonic_root wait prompt_sonic_root
sendln "bgctl stop --all" sendln "bgctl stop --all"
@@ -28,23 +33,6 @@ sendln "~/Blanton_Script/mgmt_ping_monitor.sh stop"
wait prompt_sonic_root wait prompt_sonic_root
sendln "~/Blanton_Script/nfc_polling.sh stop" sendln "~/Blanton_Script/nfc_polling.sh stop"
;=============================================================================================================
; 100G PRBS STOP
;wait prompt_sonic_root
;sendln "~/Blanton_Script/port_prbs_monitor.sh stop"
;wait prompt_sonic_root
;sendln "sudo sfputil lpmode off Ethernet513"
;wait prompt_sonic_root
;sendln "sudo sfputil lpmode off Ethernet514"
;wait prompt_sonic_root
;sendln "config interface -n asic0 startup Ethernet513"
;wait prompt_sonic_root
;sendln "config interface -n asic1 startup Ethernet514"
;=============================================================================================================
; ========== TAKE DATA ========== ; ========== TAKE DATA ==========
include "utils/setup_pmon.ttl" include "utils/setup_pmon.ttl"
include "utils/show_dmesg.ttl" include "utils/show_dmesg.ttl"
@@ -61,30 +49,23 @@ include "utils/show_pcie_error_reg_SSD.ttl"
wait prompt_sonic_root wait prompt_sonic_root
sendln "/usr/sbin/ras-mc-ctl --summary" sendln "/usr/sbin/ras-mc-ctl --summary"
; ========== BMC DDR TAKE DATA ==========
;wait prompt_sonic_root
;sendln "./Blanton_Script/bmc_monitor_ddr.sh stop"
;wait prompt_sonic_root
;sendln "./Blanton_Script/bmc_monitor.sh stop"
;wait prompt_sonic_root
;sendln "cat ./Blanton_Script/log/bmc_poll.log"
;wait prompt_sonic_root
;sendln "cat ./Blanton_Script/log/bmc_ddr.log"
; ========== BMC Monitor TAKE DATA ========== ; ========== BMC Monitor TAKE DATA ==========
wait prompt_sonic_root wait prompt_sonic_root
sendln "./Blanton_Script/bmc_monitor.sh stop" sendln "./Blanton_Script/bmc_monitor.sh stop"
wait prompt_sonic_root ; wait prompt_sonic_root
sendln "cat ./Blanton_Script/log/bmc_poll.log" ; sendln "cat ./Blanton_Script/log/bmc_poll.log"
; ========== BMC USB Test result ========== ; ========== BMC USB Test result ==========
;wait prompt_sonic_root wait prompt_sonic_root
;sendln "journalctl -u qfx5252-bmc-usb-net-test.service --no-pager" sendln "rm -f ~/Blanton_Script/log/bmc_usb_net.log"
wait prompt_sonic_root
sendln "journalctl -u qfx5252-bmc-usb-net-test.service --no-pager -o short-iso > ~/Blanton_Script/log/bmc_usb_net.log"
; ========== CHECK Stress results ========== ; ========== CHECK Stress results ==========
wait prompt_sonic_root ; wait prompt_sonic_root
sendln "cat ~/hammer/tools/amd/mlucas_amm_log" ; sendln "cat ~/hammer/tools/amd/mlucas_amm_log"
wait prompt_sonic_root wait prompt_sonic_root
sendln "cat /host/hw-eval/jobs/qfx5252-stress-ssd.log" sendln "cat /host/hw-eval/jobs/qfx5252-stress-ssd.log"
wait prompt_sonic_root wait prompt_sonic_root
@@ -101,10 +82,6 @@ sendln "~/Blanton_Script/nfc_polling.sh report"
; ========== 100G Port ========== ; ========== 100G Port ==========
wait prompt_sonic_root wait prompt_sonic_root
sendln "show interfaces status Ethernet513,Ethernet514" sendln "show interfaces status Ethernet513,Ethernet514"
;=============================================================================================================
;wait prompt_sonic_root
;sendln "cat ~/Blanton_Script/log/port_prbs.log "
;=============================================================================================================
; ========== CHECK Traffic counters ========== ; ========== CHECK Traffic counters ==========
if SWB_UNIT0 = 1 && SWB_UNIT1 = 1 then if SWB_UNIT0 = 1 && SWB_UNIT1 = 1 then
@@ -173,6 +150,11 @@ else
endif endif
if EN_TX_FIR = 1 then
; ========== Collect bcm dsc data ==========
wait prompt_sonic_root
sendln "./Blanton_Script/bcm_dsc_scan.sh -f blanton_dsc_ScriptC.log -F"
endif
; ========== NVME Err Info ========== ; ========== NVME Err Info ==========
wait prompt_sonic_root wait prompt_sonic_root
@@ -184,6 +166,11 @@ sendln "/usr/sbin/smartctl -x /dev/nvme0"
wait prompt_sonic_root wait prompt_sonic_root
sendln "show reboot-cause" sendln "show reboot-cause"
; ========== Check Margin ==========
if EN_Margin = 1 then
include "utils/show_margin_status.ttl"
endif
; ========== Show Power on uptime ========== ; ========== Show Power on uptime ==========
wait prompt_sonic_root wait prompt_sonic_root
sendln "show uptime" sendln "show uptime"
@@ -204,12 +191,27 @@ sendln cmd
; ========== Copy Stress Log to USB ========== ; ========== Copy Stress Log to USB ==========
wait prompt_sonic_root wait prompt_sonic_root
sendln "cp ~/hammer/tools/amd/mlucas_amm_log /host/hw-eval/jobs/"
wait prompt_sonic_root
sendln "cp ./Blanton_Script/log/bmc_usb_net.log /host/hw-eval/jobs/"
wait prompt_sonic_root
sendln "cp ./Blanton_Script/log/bmc_poll.log /host/hw-eval/jobs/" sendln "cp ./Blanton_Script/log/bmc_poll.log /host/hw-eval/jobs/"
wait prompt_sonic_root wait prompt_sonic_root
sendln "cp ./Blanton_Script/log/mgmt_ping.log /host/hw-eval/jobs/" sendln "cp ./Blanton_Script/log/mgmt_ping.log /host/hw-eval/jobs/"
wait prompt_sonic_root wait prompt_sonic_root
sendln "cp ./Blanton_Script/log/nfc_poll.log /host/hw-eval/jobs/" sendln "cp ./Blanton_Script/log/nfc_poll.log /host/hw-eval/jobs/"
if EN_TX_FIR = 1 then
wait prompt_sonic_root
sendln "cp ./Blanton_Script/log/blanton_dsc_ScriptA_u0.log /host/hw-eval/jobs/"
wait prompt_sonic_root
sendln "cp ./Blanton_Script/log/blanton_dsc_ScriptA_u1.log /host/hw-eval/jobs/"
wait prompt_sonic_root
sendln "cp ./Blanton_Script/log/blanton_dsc_ScriptC_u0.log /host/hw-eval/jobs/"
wait prompt_sonic_root
sendln "cp ./Blanton_Script/log/blanton_dsc_ScriptC_u1.log /host/hw-eval/jobs/"
endif
wait prompt_sonic_root wait prompt_sonic_root
getdate ts_date "%Y%m%d" getdate ts_date "%Y%m%d"
gettime ts_time "%H%M" gettime ts_time "%H%M"
@@ -219,6 +221,9 @@ sendln cmd
; ========== HW Test Session ========== ; ========== HW Test Session ==========
wait prompt_sonic_root wait prompt_sonic_root
sendln "exit"
wait "Script done"
wait prompt_sonic_root
sendln "hw-test-session finish" sendln "hw-test-session finish"
wait prompt_sonic_root wait prompt_sonic_root
sendln "bgctl reset --yes" sendln "bgctl reset --yes"
@@ -0,0 +1,164 @@
include "config.ttl"
flushrecv
;================================================================
; Log File Creation
;================================================================
gettime str_starttime "%Y%m%d-%H%M%S"
getdir mdir
if EN_log = 1 then
sprintf2 filename '%s\Logs\%s_%s_%s.log' mdir project_name strTestcase str_starttime
logopen filename 0 1 1 1
endif
; ========== Root Login ==========
wait prompt_login
sendln "admin"
wait "Password:"
sendln "YourPaSsWoRd"
wait prompt_sonic
sendln "sudo -i"
; ========== Pre Setting ==========
; Make log directory
wait prompt_sonic_root
sendln "mkdir ./logs"
; Setting System Time
getdate datestr
gettime timestr
sprintf2 cmd 'sudo date -s "%s %s"' datestr timestr
sendln cmd
;Stress log clear
wait prompt_sonic_root
sendln "rm /host/hw-eval/jobs/*"
; ========== HW Test Session ==========
; Clear session
wait prompt_sonic_root
sendln "hw-test-session finish"
wait prompt_sonic_root
sendln "bgctl reset --yes"
wait prompt_sonic_root
sendln "bgctl stop --all"
wait prompt_sonic_root
sendln "bgctl list"
wait prompt_sonic_root
sendln "hw-test-session start"
wait prompt_sonic_root
sendln "hw-test-session log"
wait prompt_sonic_root
sendln "hw-test-session status"
; ========== FAN SPEED ==========
wait prompt_sonic_root
sendln "echo 18-0020 > /sys/bus/i2c/drivers/max31790/unbind"
wait prompt_sonic_root
sendln "sleep .5"
wait prompt_sonic_root
sendln "echo 18-0020 > /sys/bus/i2c/drivers/max31790/bind"
wait prompt_sonic_root
sendln "echo 25-0020 > /sys/bus/i2c/drivers/max31790/unbind"
wait prompt_sonic_root
sendln "sleep .5"
wait prompt_sonic_root
sendln "echo 25-0020 > /sys/bus/i2c/drivers/max31790/bind"
wait prompt_sonic_root
sprintf2 fan_ctrl_cmd 'fan-speed-control.sh %d' FAN_SPEED
sendln fan_ctrl_cmd
wait "Set all configured fan channels to"
sendln "y"
; ========== Wait DUT Init ==========
include "utils/wait_init.ttl"
; ========== DUT Info ==========
wait prompt_sonic_root
sendln "show boot"
wait prompt_sonic_root
sendln "show version"
wait prompt_sonic_root
sendln "fwutil show status"
wait prompt_sonic_root
sendln "show system-memory"
wait prompt_sonic_root
sendln "show service"
wait prompt_sonic_root
sendln "show platform syseeprom"
wait prompt_sonic_root
sendln "show platform ssdhealth"
wait prompt_sonic_root
sendln "qfx5252-tpm-version"
wait prompt_sonic_root
sendln "/usr/sbin/nvme smart-log -H /dev/nvme0"
wait prompt_sonic_root
sendln "/usr/sbin/smartctl -x /dev/nvme0"
; ========== BMC version ==========
;wait prompt_sonic_root
;sendln "bmc-manager run 'cat /etc/issue'"
wait prompt_sonic_root
sendln "bmc-first-enroll"
wait prompt_sonic_root
sendln "bmc-manager version"
wait prompt_sonic_root
sendln "bmc-manager status"
; ========== CLEAR PCIE Error ==========
include "utils/show_pcie_error_reg_TH6_SWB0.ttl"
include "utils/show_pcie_error_reg_TH6_SWB1.ttl"
include "utils/show_pcie_error_reg_FPGA.ttl"
include "utils/show_pcie_error_reg_BMC.ttl"
include "utils/show_pcie_error_reg_DDR.ttl"
include "utils/show_pcie_error_reg_I210.ttl"
include "utils/show_pcie_error_reg_SSD.ttl"
wait prompt_sonic_root
sendln "/usr/sbin/ras-mc-ctl --summary"
; ========== Check PCIE tree + PCIE link status + GET PCIE bandwidth Test ==========
include "utils/pcie_bus.ttl"
; ========== TAKE DATA ==========
include "utils/setup_pmon.ttl"
include "utils/show_dmesg.ttl"
; ========== Full Load ==========
; AMD CPU STRESS TEST
; Clear the log file first
wait prompt_sonic_root
sendln "> ~/hammer/tools/amd/mlucas_amm_log"
wait prompt_sonic_root
sendln 'chmod +x ~/hammer/tools/amd/mlucas-avx2'
wait prompt_sonic_root
;sendln "~/hammer/tools/amd/mlucas-avx2 -s l -cpu 0:15 > ~/hammer/tools/amd/mlucas_amm_log 2>&1 &"
sendln "systemd-run --unit=mlucas-amm --property=Type=exec --property=Restart=always --property=RestartSec=2 /bin/bash -c '~/hammer/tools/amd/mlucas-avx2 -s l -cpu 0:15 >> ~/hammer/tools/amd/mlucas_amm_log 2>&1'"
; TR518 TEST
wait prompt_sonic_root
sendln "~/Blanton_Script/blanton_tr518.sh start"
while 1
; Base info polling
include "utils/setup_pmon.ttl"
; TH6 Power Polling
wait prompt_sonic_root
sendln "~/Blanton_Script/TH6_SWB0_power_readback.sh"
wait prompt_sonic_root
sendln "~/Blanton_Script/TH6_SWB1_power_readback.sh"
; Background jobs Check
wait prompt_sonic_root
sendln "bgctl list"
wait prompt_sonic_root
sendln "jobs"
wait prompt_sonic_root
sendln "systemctl is-active mlucas-amm"
pause 60
endwhile
@@ -0,0 +1,443 @@
include "config.ttl"
flushrecv
;================================================================
; Log File Creation
;================================================================
gettime str_starttime "%Y%m%d-%H%M%S"
getdir mdir
if EN_log = 1 then
if EN_Cold_Warm_boot = 1 then
sprintf2 filename '%s\Logs\%s_%s_%s.log' mdir project_name "Reboot_Cycle" str_starttime
logopen filename 0 1 1 1
elseif EN_Cold_Warm_boot = 2 then
sprintf2 filename '%s\Logs\%s_%s_%s.log' mdir project_name "Power_Cycle" str_starttime
logopen filename 0 1 1 1
else
endif
endif
cnt_cycle = 0
while 1
cnt_cycle = cnt_cycle + 1
; ========== Root Login ==========
wait prompt_login
sendln "admin"
wait "Password:"
sendln "YourPaSsWoRd"
wait prompt_sonic
sendln "sudo -i"
wait prompt_sonic_root
sendln "sleep 10"
if EN_Cold_Warm_boot = 1 then
wait prompt_sonic_root
sprintf2 strTitle "echo -e '\033[1;32mReboot Cycle : %d \033[0m'" cnt_cycle
sendln strTitle
elseif EN_Cold_Warm_boot = 2 then
wait prompt_sonic_root
sprintf2 strTitle "echo -e '\033[1;32mPower Cycle : %d \033[0m'" cnt_cycle
sendln strTitle
else
endif
; ========== Pre Setting ==========
; Make log directory
wait prompt_sonic_root
sendln "mkdir ./logs"
; Setting System Time
getdate datestr
gettime timestr
sprintf2 cmd 'sudo date -s "%s %s"' datestr timestr
sendln cmd
; ========== FAN SPEED ==========
wait prompt_sonic_root
sendln "echo 18-0020 > /sys/bus/i2c/drivers/max31790/unbind"
wait prompt_sonic_root
sendln "sleep .5"
wait prompt_sonic_root
sendln "echo 18-0020 > /sys/bus/i2c/drivers/max31790/bind"
wait prompt_sonic_root
sendln "echo 25-0020 > /sys/bus/i2c/drivers/max31790/unbind"
wait prompt_sonic_root
sendln "sleep .5"
wait prompt_sonic_root
sendln "echo 25-0020 > /sys/bus/i2c/drivers/max31790/bind"
wait prompt_sonic_root
sprintf2 fan_ctrl_cmd 'fan-speed-control.sh %d' FAN_SPEED
sendln fan_ctrl_cmd
wait "Set all configured fan channels to"
sendln "y"
; ========== Wait DUT Init ==========
include "utils/wait_init.ttl"
; ========== DUT Info ==========
wait prompt_sonic_root
sprintf2 strCKPt1 "echo -e '\033[36mCheck Pt1 : DUT Info\033[0m'"
sendln strCKPt1
wait prompt_sonic_root
sendln "show boot"
wait prompt_sonic_root
sendln "show version"
wait prompt_sonic_root
sendln "fwutil show status"
wait prompt_sonic_root
sendln "show system-memory"
wait prompt_sonic_root
sendln "show service"
wait prompt_sonic_root
sendln "show platform syseeprom"
wait prompt_sonic_root
sendln "show platform ssdhealth"
wait prompt_sonic_root
sendln "qfx5252-tpm-version"
wait prompt_sonic_root
sendln "/usr/sbin/nvme smart-log -H /dev/nvme0"
wait prompt_sonic_root
sendln "/usr/sbin/smartctl -x /dev/nvme0"
; ========== BMC version ==========
wait prompt_sonic_root
sprintf2 strCKPt2 "echo -e '\033[36mCheck Pt2 : BMC Info\033[0m'"
sendln strCKPt2
wait prompt_sonic_root
sendln "bmc-first-enroll"
wait prompt_sonic_root
sendln "bmc-manager version"
wait prompt_sonic_root
sendln "bmc-manager status"
; ========== Load Shell Script ==========
wait prompt_sonic_root
sendln "source ~/Blanton_Script/blanton_fpga_pcimem.sh"
wait prompt_sonic_root
sendln "source ~/Blanton_Script/blanton_cb_i2c.sh"
wait prompt_sonic_root
sendln "source ~/Blanton_Script/blanton_icb_vi2c.sh"
wait prompt_sonic_root
sendln "source ~/Blanton_Script/blanton_pwr_data.sh"
wait prompt_sonic_root
sendln "source ~/Blanton_Script/blanton_traffic_linespeed.sh"
wait prompt_sonic_root
sendln "source ~/Blanton_Script/LTC2980_Margin_Script/margin.sh"
; ========== CLEAR PCIE Error ==========
include "utils/show_pcie_error_reg_TH6_SWB0.ttl"
include "utils/show_pcie_error_reg_TH6_SWB1.ttl"
include "utils/show_pcie_error_reg_FPGA.ttl"
include "utils/show_pcie_error_reg_BMC.ttl"
include "utils/show_pcie_error_reg_DDR.ttl"
include "utils/show_pcie_error_reg_I210.ttl"
include "utils/show_pcie_error_reg_SSD.ttl"
wait prompt_sonic_root
sendln "/usr/sbin/ras-mc-ctl --summary"
; ========== Check PCIE tree + PCIE link status + GET PCIE bandwidth Test ==========
include "utils/pcie_bus.ttl"
; ========== TAKE DATA ==========
include "utils/setup_pmon.ttl"
include "utils/show_dmesg.ttl"
; ========== 10G/1G MGMT Ping Test ==========
wait prompt_sonic_root
sprintf2 strCKPt3 "echo -e '\033[36mCheck Pt3 : Mgmt Ping Test\033[0m'"
sendln strCKPt3
wait prompt_sonic_root
sendln "./Blanton_Script/mgmt_ping_monitor.sh start"
wait prompt_sonic_root
pause 30
sendln "~/Blanton_Script/mgmt_ping_monitor.sh stop"
wait prompt_sonic_root
sendln "cat ~/Blanton_Script/log/mgmt_ping.log"
wait prompt_sonic_root
sendln "~/Blanton_Script/mgmt_ping_monitor.sh clear"
; ========== NFC Test ==========
wait prompt_sonic_root
sprintf2 strCKPt4 "echo -e '\033[36mCheck Pt4 : NFC Test\033[0m'"
sendln strCKPt4
wait prompt_sonic_root
sendln "~/Blanton_Script/nfc_polling.sh start"
wait prompt_sonic_root
sendln "~/Blanton_Script/nfc_polling.sh status"
wait prompt_sonic_root
sendln "sleep 20"
wait prompt_sonic_root
sendln "~/Blanton_Script/nfc_polling.sh stop"
wait prompt_sonic_root
sendln "~/Blanton_Script/nfc_polling.sh report"
; ========== SSD read/write ==========
wait prompt_sonic_root
sprintf2 strCKPt5 "echo -e '\033[36mCheck Pt5 : SSD Test\033[0m'"
sendln strCKPt5
wait prompt_sonic_root
sendln "rm -rf /host/hw-eval/jobs/qfx5252-stress-ssd.log"
wait prompt_sonic_root
sendln "qfx5252-stress-ssd 1G --runtime 30 --passes 2 --write --force --log /host/hw-eval/jobs/qfx5252-stress-ssd.log"
wait prompt_sonic_root
sendln "cat /host/hw-eval/jobs/qfx5252-stress-ssd.log"
; ========== USB read/write ==========
wait prompt_sonic_root
sprintf2 strCKPt6 "echo -e '\033[36mCheck Pt6 : USB Test\033[0m'"
sendln strCKPt6
; ---- Get USB partition node -> usb_dev ----
usb_dev = ''
wait prompt_sonic_root
sendln 'D=$(bash ~/Blanton_Script/usb_target.sh -o dev 2>/dev/null); echo "<<D""EV=${D:-NONE}>>"'
waitregex '<<DEV=([^>]*)>>'
usb_dev = groupmatchstr1
wait prompt_sonic_root
sendln "rm -rf /host/hw-eval/jobs/qfx5252-stress-usb.log"
wait prompt_sonic_root
sprintf2 cmd "qfx5252-stress-usb %s 256M --runtime 30 --passes 2 --write --log /host/hw-eval/jobs/qfx5252-stress-usb.log" usb_dev
sendln cmd
wait prompt_sonic_root
sendln "cat /host/hw-eval/jobs/qfx5252-stress-usb.log"
; ========== BMC USB Test ==========
wait prompt_sonic_root
sprintf2 strCKPt7 "echo -e '\033[36mCheck Pt7 : BMC USB Test\033[0m'"
sendln strCKPt7
wait prompt_sonic_root
sendln 'echo "NCMIF=$(ls -d /sys/bus/usb/drivers/cdc_ncm/*/net/* 2>/dev/null | head -n 1 | xargs -r basename)"'
; timeout is GLOBAL and sticky: left at 15, every 'wait' below gives up after
; 15 s instead of blocking, the macro runs ahead of the DUT and the whole
; cycle desynchronises. Restore it BEFORE the branch so both paths are
; covered - the ping block below waits on 'sleep 10', which is already two
; thirds of the 15 s cap on a loaded DUT.
timeout = 15
waitregex 'NCMIF=[A-Za-z0-9_-]+'
ncm_found = result ; hold it: 'result' is reused below
timeout = 0 ; restore, both paths
if ncm_found = 0 then
messagebox 'cdc_ncm interface not found. Ping test skipped.' 'ERROR'
goto skip_ping
endif
strlen matchstr
cut_len = result - 6 ; 'NCMIF=' = 6 chars
strcopy matchstr 7 cut_len ncm_if ; -> ncm_if = "eth2" / "eth3"
sprintf2 cmd 'ip -br link show %s' ncm_if
wait prompt_sonic_root
sendln cmd
wait prompt_sonic_root
sendln 'systemctl stop qfx5252-bmc-usb-net-test.service 2>/dev/null || true'
wait prompt_sonic_root
sendln 'systemctl reset-failed qfx5252-bmc-usb-net-test.service 2>/dev/null || true'
sprintf2 cmd 'systemd-run --unit=qfx5252-bmc-usb-net-test --property=Type=exec /usr/bin/ping -I %s -i 1 -W 2 -w 14400 192.168.200.200' ncm_if
wait prompt_sonic_root
sendln cmd
wait prompt_sonic_root
sendln "sleep 10"
wait prompt_sonic_root
sendln "systemctl stop qfx5252-bmc-usb-net-test.service"
wait prompt_sonic_root
sendln "journalctl -u qfx5252-bmc-usb-net-test.service --no-pager"
:skip_ping
timeout = 0 ; backstop, same as Script B
; ========== 100G Port Setting ==========
wait prompt_sonic_root
sendln "sudo sfputil lpmode off Ethernet513"
wait prompt_sonic_root
sendln "sudo sfputil lpmode off Ethernet514"
wait prompt_sonic_root
sendln "config interface -n asic0 startup Ethernet513"
wait prompt_sonic_root
sendln "config interface -n asic1 startup Ethernet514"
wait prompt_sonic_root
sendln "config save -y"
; ========== First Traffic Test ==========
; Silent MAC
wait prompt_sonic_root
sendln "config feature state lldp disabled"
wait prompt_sonic_root
sendln "config save -y"
; ========== 100G Port Status ==========
wait prompt_sonic_root
sprintf2 strCKPt8 "echo -e '\033[36mCheck Pt8 : Port Status and 15sec Traffic \033[0m'"
sendln strCKPt8
wait prompt_sonic_root
sendln "show interfaces status Ethernet513,Ethernet514"
; ========== Traffic Test ==========
if SWB_UNIT0 = 1 && SWB_UNIT1 = 1 then
wait prompt_sonic_root
sendln "blanton_traffic_linespeed ps"
wait prompt_sonic_root
sendln "blanton_traffic_linespeed init"
wait prompt_sonic_root
sendln "blanton_traffic_linespeed clear"
wait prompt_sonic_root
sendln "blanton_traffic_linespeed show"
wait prompt_sonic_root
sendln "blanton_traffic_linespeed start"
wait prompt_sonic_root
pause 15
sendln "blanton_traffic_linespeed stop"
wait prompt_sonic_root
sendln "blanton_traffic_linespeed report"
elseif SWB_UNIT0 = 1 && SWB_UNIT1 = 0 then
wait prompt_sonic_root
sendln "blanton_traffic_linespeed ps -u 0"
wait prompt_sonic_root
sendln "blanton_traffic_linespeed init -u 0"
wait prompt_sonic_root
sendln "blanton_traffic_linespeed clear -u 0"
wait prompt_sonic_root
sendln "blanton_traffic_linespeed show -u 0"
wait prompt_sonic_root
sendln "blanton_traffic_linespeed start -u 0"
wait prompt_sonic_root
pause 15
sendln "blanton_traffic_linespeed stop -u 0"
wait prompt_sonic_root
sendln "blanton_traffic_linespeed report -u 0"
elseif SWB_UNIT0 = 0 && SWB_UNIT1 = 1 then
wait prompt_sonic_root
sendln "blanton_traffic_linespeed ps -u 1"
wait prompt_sonic_root
sendln "blanton_traffic_linespeed init -u 1"
wait prompt_sonic_root
sendln "blanton_traffic_linespeed clear -u 1"
wait prompt_sonic_root
sendln "blanton_traffic_linespeed show -u 1"
wait prompt_sonic_root
sendln "blanton_traffic_linespeed start -u 1"
wait prompt_sonic_root
pause 15
sendln "blanton_traffic_linespeed stop -u 1"
wait prompt_sonic_root
sendln "blanton_traffic_linespeed report -u 1"
else
endif
; ========== BER ==========
; PRBS takes the SerDes out of normal operation, so this runs AFTER the
; traffic report. sleep 30 matches blanton_ber.sh BER_INTERVAL - reporting
; earlier reads an interval that has not finished accumulating.
wait prompt_sonic_root
sprintf2 strCKPt8 "echo -e '\033[36mCheck Pt9 : BER Test \033[0m'"
sendln strCKPt8
if SWB_UNIT0 = 1 && SWB_UNIT1 = 1 then
wait prompt_sonic_root
sendln "./Blanton_Script/blanton_ber.sh init"
wait prompt_sonic_root
sendln "./Blanton_Script/blanton_ber.sh start"
wait prompt_sonic_root
sendln "sleep 30"
wait prompt_sonic_root
sendln "./Blanton_Script/blanton_ber.sh report"
wait prompt_sonic_root
sendln "./Blanton_Script/blanton_ber.sh stop"
wait prompt_sonic_root
sendln "./Blanton_Script/blanton_ber.sh clear"
elseif SWB_UNIT0 = 1 && SWB_UNIT1 = 0 then
wait prompt_sonic_root
sendln "./Blanton_Script/blanton_ber.sh init -u 0"
wait prompt_sonic_root
sendln "./Blanton_Script/blanton_ber.sh start -u 0"
wait prompt_sonic_root
sendln "sleep 30"
wait prompt_sonic_root
sendln "./Blanton_Script/blanton_ber.sh report -u 0"
wait prompt_sonic_root
sendln "./Blanton_Script/blanton_ber.sh stop -u 0"
wait prompt_sonic_root
sendln "./Blanton_Script/blanton_ber.sh clear -u 0"
elseif SWB_UNIT0 = 0 && SWB_UNIT1 = 1 then
wait prompt_sonic_root
sendln "./Blanton_Script/blanton_ber.sh init -u 1"
wait prompt_sonic_root
sendln "./Blanton_Script/blanton_ber.sh start -u 1"
wait prompt_sonic_root
sendln "sleep 30"
wait prompt_sonic_root
sendln "./Blanton_Script/blanton_ber.sh report -u 1"
wait prompt_sonic_root
sendln "./Blanton_Script/blanton_ber.sh stop -u 1"
wait prompt_sonic_root
sendln "./Blanton_Script/blanton_ber.sh clear -u 1"
else
endif
; ========== NVME Err Info ==========
wait prompt_sonic_root
sprintf2 strCKPt9 "echo -e '\033[36mCheck Pt10 : NVME Err Info \033[0m'"
sendln strCKPt9
wait prompt_sonic_root
sendln "/usr/sbin/nvme smart-log -H /dev/nvme0"
wait prompt_sonic_root
sendln "/usr/sbin/smartctl -x /dev/nvme0"
; ========== TAKE DATA ==========
wait prompt_sonic_root
sprintf2 strCKPt10 "echo -e '\033[36mCheck Pt11 : Platform Data \033[0m'"
sendln strCKPt10
include "utils/setup_pmon.ttl"
wait prompt_sonic_root
sprintf2 strCKPt12 "echo -e '\033[36mCheck Pt12 : Dmesg_i2c \033[0m'"
sendln strCKPt12
include "utils/show_dmesg.ttl"
; ========== Check PCIE error counters ==========
wait prompt_sonic_root
sprintf2 strCKPt13 "echo -e '\033[36mCheck Pt13 : PCIE Error Counters \033[0m'"
sendln strCKPt13
include "utils/show_pcie_error_reg_TH6_SWB0.ttl"
include "utils/show_pcie_error_reg_TH6_SWB1.ttl"
include "utils/show_pcie_error_reg_FPGA.ttl"
include "utils/show_pcie_error_reg_BMC.ttl"
include "utils/show_pcie_error_reg_DDR.ttl"
include "utils/show_pcie_error_reg_I210.ttl"
include "utils/show_pcie_error_reg_SSD.ttl"
wait prompt_sonic_root
sendln "/usr/sbin/ras-mc-ctl --summary"
; ========== Show Power on uptime ==========
wait prompt_sonic_root
sendln "show uptime"
; ========== Show Power on uptime ==========
if EN_Cold_Warm_boot = 1 then
wait prompt_sonic_root
sendln "reboot"
elseif EN_Cold_Warm_boot = 2 then
wait prompt_sonic_root
sendln "pcimem /sys/bus/pci/devices/0000:05:00.0/resource0 0x480 w 0xD0000"
else
endif
wait "Booting in blind mode"
endwhile
@@ -72,13 +72,13 @@ margin_operation 0 high
margin_operation 0 nominal margin_operation 0 nominal
# 批次套用 profile(套在當前載入的 LTC2980) # 批次套用 profile(套在當前載入的 LTC2980)
margin_apply_profile profiles/comboA.conf margin_apply_profile profiles/combo_SWB_CONN13_high.conf
margin_apply_profile profiles/comboB.conf margin_apply_profile profiles/combo_SWB_CONN13_low.conf
margin_apply_profile profiles/all_off.conf margin_apply_profile profiles/all_off.conf
# 切換到另一顆 LTC2980 # 切換到另一顆 LTC2980
margin_init Blanton_SWB1_CONN16 margin_init Blanton_SWB1_CONN16
margin_apply_profile profiles/comboA.conf margin_apply_profile profiles/combo_SWB_CONN16_high.conf
# 儲存到 NVM(斷電後保留) # 儲存到 NVM(斷電後保留)
margin_save # 只寫當前載入的那顆 margin_save # 只寫當前載入的那顆
@@ -108,7 +108,7 @@ BOARDS=(
## 一次套 profile 到所有 LTC2980 ## 一次套 profile 到所有 LTC2980
`script/margin_apply_profile_all.sh` 對多顆 LTC2980 依 `BOARDS[i]` 配對 `script/margin_apply_profile_all.sh` 對多顆 LTC2980 依 `BOARDS[i]` 配對
`PROFILES[i]` 套用 profile(預設全部 `comboA`)。 `PROFILES[i]` 套用 profile(預設 SWB 各用自己 CONN 的 `_high`,CB 用 `combo_high3`)。
```bash ```bash
source script/margin_apply_profile_all.sh source script/margin_apply_profile_all.sh
@@ -124,8 +124,8 @@ BOARDS=(
) )
PROFILES=( PROFILES=(
"comboA" # Blanton_CB_CONN13 "combo_high3" # Blanton_CB_CONN13
"comboB" # Blanton_SWB0_CONN13 ← 改成 comboB "combo_SWB_CONN13_high" # Blanton_SWB0_CONN13
... ...
) )
``` ```
@@ -133,6 +133,10 @@ PROFILES=(
`PROFILES` 寫名字即可(不含路徑跟 `.conf`),script 會自動展開成 `PROFILES` 寫名字即可(不含路徑跟 `.conf`),script 會自動展開成
`profiles/<name>.conf`。兩個陣列長度不一致會直接報錯。 `profiles/<name>.conf`。兩個陣列長度不一致會直接報錯。
> ⚠️ **SWB 的 profile 是 per-CONN 的**:每個檔的百分比對應該片板子的軌,
> 套到別的 CONN 會 margin 到錯的東西(而且不會報錯)。這裡不能全部填同一個名字。
> HIGH / LOW 兩輪就是把 `_high` 全換成 `_low` 再跑一次。
## 一次把所有 LTC2980 寫入 NVM ## 一次把所有 LTC2980 寫入 NVM
> ⚠️ `margin_save` 會把當前 margin / OV / UV 設定**永久寫入 NVM**, > ⚠️ `margin_save` 會把當前 margin / OV / UV 設定**永久寫入 NVM**,
@@ -217,6 +221,22 @@ i2cset -f -y 14 0x62 0x15 ; i2cset -f -y 14 0x64 0x15 # SWB1 CONN16
不要讓它去打不存在的板子。bus 節點不存在(`/dev/i2c-N` 沒有)與晶片不回應(NACK) 不要讓它去打不存在的板子。bus 節點不存在(`/dev/i2c-N` 沒有)與晶片不回應(NACK)
會分別報不同訊息 —— 前者代表 FPGA 的 i2c adapter 根本沒 enumerate,後者才是板子的問題。 會分別報不同訊息 —— 前者代表 FPGA 的 i2c adapter 根本沒 enumerate,後者才是板子的問題。
## Profile 一覽
| Profile | 適用 | 說明 |
|---|---|---|
| `combo_SWB_CONN13_high` / `_low` | **SWB CONN13 專用** | 每個 channel 依該板的軌給 3% 或 5% |
| `combo_SWB_CONN14_high` / `_low` | **SWB CONN14 專用** | 同上 |
| `combo_SWB_CONN15_high` / `_low` | **SWB CONN15 專用** | 同上 |
| `combo_SWB_CONN16_high` / `_low` | **SWB CONN16 專用** | 同上 |
| `combo_high3` / `combo_low3` | 通用 | 全部 channel ±3% |
| `combo_high5` / `combo_low5` | 通用 | 全部 channel ±5% |
| `combo_normal` | 通用 | 全部回 nominal |
| `all_off` | 通用 | 全部 OPERATION off |
SWB0 和 SWB1 的同號 CONN 共用同一個 profile(兩片板的軌完全相同,
只差 I2C bus)。CB CONN13 沒有專屬 profile,用通用的 `combo_high3` / `combo_low3`。
## Operation 對應 ## Operation 對應
| 參數 | PMBus 0x01 值 | 說明 | | 參數 | PMBus 0x01 值 | 說明 |
@@ -1,22 +0,0 @@
# Profile: comboA - alternating high/low (even=high, odd=low)
# Applied to whichever LTC2980 is currently loaded via margin_init
# Format: "channel:operation:change_percent"
PROFILE_CHANNELS=(
"0:high:8"
"1:low:8"
"2:high:8"
"3:low:8"
"4:high:8"
"5:low:8"
"6:high:8"
"7:low:8"
"8:high:8"
"9:low:8"
"10:high:8"
"11:low:8"
"12:high:8"
"13:low:8"
"14:high:8"
"15:low:8"
)
@@ -0,0 +1,26 @@
# Profile: comboA_CB - checkerboard, the complement of comboB_CB
# Board: CB only. The channel list is positional, so applying this to a
# different board margins the wrong rails and nothing detects it.
# Run comboA then comboB to cover every rail in both directions while its
# neighbours sit the other way.
# Applied to whichever LTC2980 is currently loaded via margin_init
# Format: "channel:operation:change_percent"
PROFILE_CHANNELS=(
"0:low:5"
"1:low:5"
"2:high:5"
"3:low:5"
"4:high:5"
"5:high:5"
"6:high:5"
"7:high:5"
"8:low:5"
"9:high:5"
"10:high:5"
"11:high:5"
"12:low:5"
"13:high:5"
"14:high:5"
"15:low:5"
)
@@ -0,0 +1,26 @@
# Profile: comboA_SWB_CONN13 - checkerboard, the complement of comboB_SWB_CONN13
# Board: SWB_CONN13 only. The channel list is positional, so applying this to a
# different board margins the wrong rails and nothing detects it.
# Run comboA then comboB to cover every rail in both directions while its
# neighbours sit the other way.
# Applied to whichever LTC2980 is currently loaded via margin_init
# Format: "channel:operation:change_percent"
PROFILE_CHANNELS=(
"0:high:3"
"1:high:3"
"2:low:3"
"3:low:3"
"4:high:5"
"5:low:5"
"6:high:5"
"7:high:5"
"8:high:5"
"9:high:3"
"10:high:3"
"11:low:3"
"12:low:3"
"13:high:3"
"14:high:3"
"15:low:5"
)
@@ -0,0 +1,28 @@
# Profile: comboA_SWB_CONN14 - checkerboard, the complement of comboB_SWB_CONN14
# Board: SWB_CONN14 only. The channel list is positional, so applying this to a
# different board margins the wrong rails and nothing detects it.
# Run comboA then comboB to cover every rail in both directions while its
# neighbours sit the other way.
# CH 10, 11, 13 stay nominal: they are NC on this board, so there is
# nothing to margin.
# Applied to whichever LTC2980 is currently loaded via margin_init
# Format: "channel:operation:change_percent"
PROFILE_CHANNELS=(
"0:high:3"
"1:low:3"
"2:low:3"
"3:high:5"
"4:high:5"
"5:high:5"
"6:low:5"
"7:low:5"
"8:low:3"
"9:low:3"
"10:nominal:5"
"11:nominal:5"
"12:high:3"
"13:nominal:5"
"14:high:5"
"15:high:3"
)
@@ -0,0 +1,28 @@
# Profile: comboA_SWB_CONN15 - checkerboard, the complement of comboB_SWB_CONN15
# Board: SWB_CONN15 only. The channel list is positional, so applying this to a
# different board margins the wrong rails and nothing detects it.
# Run comboA then comboB to cover every rail in both directions while its
# neighbours sit the other way.
# CH 10 stay nominal: they are NC on this board, so there is
# nothing to margin.
# Applied to whichever LTC2980 is currently loaded via margin_init
# Format: "channel:operation:change_percent"
PROFILE_CHANNELS=(
"0:low:3"
"1:low:3"
"2:high:3"
"3:high:3"
"4:low:3"
"5:low:3"
"6:high:5"
"7:high:3"
"8:high:5"
"9:low:5"
"10:nominal:5"
"11:low:5"
"12:low:3"
"13:high:3"
"14:high:3"
"15:high:5"
)
@@ -0,0 +1,26 @@
# Profile: comboA_SWB_CONN16 - checkerboard, the complement of comboB_SWB_CONN16
# Board: SWB_CONN16 only. The channel list is positional, so applying this to a
# different board margins the wrong rails and nothing detects it.
# Run comboA then comboB to cover every rail in both directions while its
# neighbours sit the other way.
# Applied to whichever LTC2980 is currently loaded via margin_init
# Format: "channel:operation:change_percent"
PROFILE_CHANNELS=(
"0:high:3"
"1:high:5"
"2:high:5"
"3:low:5"
"4:high:5"
"5:low:5"
"6:high:5"
"7:high:3"
"8:high:3"
"9:high:3"
"10:low:3"
"11:low:3"
"12:low:3"
"13:low:3"
"14:low:3"
"15:high:3"
)
@@ -1,22 +0,0 @@
# Profile: comboB - inverse of comboA (even=low, odd=high)
# Applied to whichever LTC2980 is currently loaded via margin_init
# Format: "channel:operation:change_percent"
PROFILE_CHANNELS=(
"0:low:8"
"1:high:8"
"2:low:8"
"3:high:8"
"4:low:8"
"5:high:8"
"6:low:8"
"7:high:8"
"8:low:8"
"9:high:8"
"10:low:8"
"11:high:8"
"12:low:8"
"13:high:8"
"14:low:8"
"15:high:8"
)
@@ -0,0 +1,26 @@
# Profile: comboB_CB - checkerboard, the complement of comboA_CB
# Board: CB only. The channel list is positional, so applying this to a
# different board margins the wrong rails and nothing detects it.
# Run comboB then comboA to cover every rail in both directions while its
# neighbours sit the other way.
# Applied to whichever LTC2980 is currently loaded via margin_init
# Format: "channel:operation:change_percent"
PROFILE_CHANNELS=(
"0:high:5"
"1:high:5"
"2:low:5"
"3:high:5"
"4:low:5"
"5:low:5"
"6:low:5"
"7:low:5"
"8:high:5"
"9:low:5"
"10:low:5"
"11:low:5"
"12:high:5"
"13:low:5"
"14:low:5"
"15:high:5"
)
@@ -0,0 +1,26 @@
# Profile: comboB_SWB_CONN13 - checkerboard, the complement of comboA_SWB_CONN13
# Board: SWB_CONN13 only. The channel list is positional, so applying this to a
# different board margins the wrong rails and nothing detects it.
# Run comboB then comboA to cover every rail in both directions while its
# neighbours sit the other way.
# Applied to whichever LTC2980 is currently loaded via margin_init
# Format: "channel:operation:change_percent"
PROFILE_CHANNELS=(
"0:low:3"
"1:low:3"
"2:high:3"
"3:high:3"
"4:low:5"
"5:high:5"
"6:low:5"
"7:low:5"
"8:low:5"
"9:low:3"
"10:low:3"
"11:high:3"
"12:high:3"
"13:low:3"
"14:low:3"
"15:high:5"
)
@@ -0,0 +1,28 @@
# Profile: comboB_SWB_CONN14 - checkerboard, the complement of comboA_SWB_CONN14
# Board: SWB_CONN14 only. The channel list is positional, so applying this to a
# different board margins the wrong rails and nothing detects it.
# Run comboB then comboA to cover every rail in both directions while its
# neighbours sit the other way.
# CH 10, 11, 13 stay nominal: they are NC on this board, so there is
# nothing to margin.
# Applied to whichever LTC2980 is currently loaded via margin_init
# Format: "channel:operation:change_percent"
PROFILE_CHANNELS=(
"0:low:3"
"1:high:3"
"2:high:3"
"3:low:5"
"4:low:5"
"5:low:5"
"6:high:5"
"7:high:5"
"8:high:3"
"9:high:3"
"10:nominal:5"
"11:nominal:5"
"12:low:3"
"13:nominal:5"
"14:low:5"
"15:low:3"
)
@@ -0,0 +1,28 @@
# Profile: comboB_SWB_CONN15 - checkerboard, the complement of comboA_SWB_CONN15
# Board: SWB_CONN15 only. The channel list is positional, so applying this to a
# different board margins the wrong rails and nothing detects it.
# Run comboB then comboA to cover every rail in both directions while its
# neighbours sit the other way.
# CH 10 stay nominal: they are NC on this board, so there is
# nothing to margin.
# Applied to whichever LTC2980 is currently loaded via margin_init
# Format: "channel:operation:change_percent"
PROFILE_CHANNELS=(
"0:high:3"
"1:high:3"
"2:low:3"
"3:low:3"
"4:high:3"
"5:high:3"
"6:low:5"
"7:low:3"
"8:low:5"
"9:high:5"
"10:nominal:5"
"11:high:5"
"12:high:3"
"13:low:3"
"14:low:3"
"15:low:5"
)
@@ -0,0 +1,26 @@
# Profile: comboB_SWB_CONN16 - checkerboard, the complement of comboA_SWB_CONN16
# Board: SWB_CONN16 only. The channel list is positional, so applying this to a
# different board margins the wrong rails and nothing detects it.
# Run comboB then comboA to cover every rail in both directions while its
# neighbours sit the other way.
# Applied to whichever LTC2980 is currently loaded via margin_init
# Format: "channel:operation:change_percent"
PROFILE_CHANNELS=(
"0:low:3"
"1:low:5"
"2:low:5"
"3:high:5"
"4:low:5"
"5:high:5"
"6:low:5"
"7:low:3"
"8:low:3"
"9:low:3"
"10:high:3"
"11:high:3"
"12:high:3"
"13:high:3"
"14:high:3"
"15:low:3"
)
@@ -0,0 +1,24 @@
# Profile: combo_SWB_CONN13_high - every channel margin HIGH, per-channel percentage
# For the SWB CONN13 board only: the percentages follow that board's
# rails, so applying it to a different CONN margins the wrong things.
# Applied to whichever LTC2980 is currently loaded via margin_init
# Format: "channel:operation:change_percent"
PROFILE_CHANNELS=(
"0:high:3"
"1:high:3"
"2:high:3"
"3:high:3"
"4:high:5"
"5:high:5"
"6:high:5"
"7:high:5"
"8:high:5"
"9:high:3"
"10:high:3"
"11:high:3"
"12:high:3"
"13:high:3"
"14:high:3"
"15:high:5"
)
@@ -0,0 +1,24 @@
# Profile: combo_SWB_CONN13_low - every channel margin LOW, per-channel percentage
# For the SWB CONN13 board only: the percentages follow that board's
# rails, so applying it to a different CONN margins the wrong things.
# Applied to whichever LTC2980 is currently loaded via margin_init
# Format: "channel:operation:change_percent"
PROFILE_CHANNELS=(
"0:low:3"
"1:low:3"
"2:low:3"
"3:low:3"
"4:low:5"
"5:low:5"
"6:low:5"
"7:low:5"
"8:low:5"
"9:low:3"
"10:low:3"
"11:low:3"
"12:low:3"
"13:low:3"
"14:low:3"
"15:low:5"
)
@@ -0,0 +1,24 @@
# Profile: combo_SWB_CONN14_high - every channel margin HIGH, per-channel percentage
# For the SWB CONN14 board only: the percentages follow that board's
# rails, so applying it to a different CONN margins the wrong things.
# Applied to whichever LTC2980 is currently loaded via margin_init
# Format: "channel:operation:change_percent"
PROFILE_CHANNELS=(
"0:high:3"
"1:high:3"
"2:high:3"
"3:high:5"
"4:high:5"
"5:high:5"
"6:high:5"
"7:high:5"
"8:high:3"
"9:high:3"
"10:nominal:5"
"11:nominal:5"
"12:high:3"
"13:nominal:5"
"14:high:5"
"15:high:3"
)
@@ -0,0 +1,24 @@
# Profile: combo_SWB_CONN14_low - every channel margin LOW, per-channel percentage
# For the SWB CONN14 board only: the percentages follow that board's
# rails, so applying it to a different CONN margins the wrong things.
# Applied to whichever LTC2980 is currently loaded via margin_init
# Format: "channel:operation:change_percent"
PROFILE_CHANNELS=(
"0:low:3"
"1:low:3"
"2:low:3"
"3:low:5"
"4:low:5"
"5:low:5"
"6:low:5"
"7:low:5"
"8:low:3"
"9:low:3"
"10:nominal:5"
"11:nominal:5"
"12:low:3"
"13:nominal:5"
"14:low:5"
"15:low:3"
)
@@ -0,0 +1,24 @@
# Profile: combo_SWB_CONN15_high - every channel margin HIGH, per-channel percentage
# For the SWB CONN15 board only: the percentages follow that board's
# rails, so applying it to a different CONN margins the wrong things.
# Applied to whichever LTC2980 is currently loaded via margin_init
# Format: "channel:operation:change_percent"
PROFILE_CHANNELS=(
"0:high:3"
"1:high:3"
"2:high:3"
"3:high:3"
"4:high:3"
"5:high:3"
"6:high:5"
"7:high:3"
"8:high:5"
"9:high:5"
"10:nominal:5"
"11:high:5"
"12:high:3"
"13:high:3"
"14:high:3"
"15:high:5"
)
@@ -0,0 +1,24 @@
# Profile: combo_SWB_CONN15_low - every channel margin LOW, per-channel percentage
# For the SWB CONN15 board only: the percentages follow that board's
# rails, so applying it to a different CONN margins the wrong things.
# Applied to whichever LTC2980 is currently loaded via margin_init
# Format: "channel:operation:change_percent"
PROFILE_CHANNELS=(
"0:low:3"
"1:low:3"
"2:low:3"
"3:low:3"
"4:low:3"
"5:low:3"
"6:low:5"
"7:low:3"
"8:low:5"
"9:low:5"
"10:nominal:5"
"11:low:5"
"12:low:3"
"13:low:3"
"14:low:3"
"15:low:5"
)
@@ -0,0 +1,24 @@
# Profile: combo_SWB_CONN16_high - every channel margin HIGH, per-channel percentage
# For the SWB CONN16 board only: the percentages follow that board's
# rails, so applying it to a different CONN margins the wrong things.
# Applied to whichever LTC2980 is currently loaded via margin_init
# Format: "channel:operation:change_percent"
PROFILE_CHANNELS=(
"0:high:3"
"1:high:5"
"2:high:5"
"3:high:5"
"4:high:5"
"5:high:5"
"6:high:5"
"7:high:3"
"8:high:3"
"9:high:3"
"10:high:3"
"11:high:3"
"12:high:3"
"13:high:3"
"14:high:3"
"15:high:3"
)
@@ -0,0 +1,24 @@
# Profile: combo_SWB_CONN16_low - every channel margin LOW, per-channel percentage
# For the SWB CONN16 board only: the percentages follow that board's
# rails, so applying it to a different CONN margins the wrong things.
# Applied to whichever LTC2980 is currently loaded via margin_init
# Format: "channel:operation:change_percent"
PROFILE_CHANNELS=(
"0:low:3"
"1:low:5"
"2:low:5"
"3:low:5"
"4:low:5"
"5:low:5"
"6:low:5"
"7:low:3"
"8:low:3"
"9:low:3"
"10:low:3"
"11:low:3"
"12:low:3"
"13:low:3"
"14:low:3"
"15:low:3"
)
@@ -17,17 +17,24 @@ BOARDS=(
"Blanton_SWB1_CONN16" "Blanton_SWB1_CONN16"
) )
# 對應的 profile 名稱(不含路徑與 .conf 副檔名),預設全部 comboA # 對應的 profile 名稱(不含路徑與 .conf 副檔名)。
#
# SWB 的 profile 是 per-CONN 的:百分比對應該片板子的軌,套到別的 CONN 會 margin
# 到錯的東西,所以這裡不能全部填同一個名字。
#
# 這份預設是 HIGH 那一輪;LOW 那一輪把下面的 _high 全換成 _low 再跑一次
# (或 sed -i 's/_high/_low/' 這個檔)。
# CB 沒有 per-CONN profile,沿用通用的 combo_high3 / combo_low3。
PROFILES=( PROFILES=(
"comboA" # Blanton_CB_CONN13 "combo_high3" # Blanton_CB_CONN13 (低壓軌多,用通用 +3%)
"comboA" # Blanton_SWB0_CONN13 "combo_SWB_CONN13_high" # Blanton_SWB0_CONN13
"comboA" # Blanton_SWB0_CONN14 "combo_SWB_CONN14_high" # Blanton_SWB0_CONN14
"comboA" # Blanton_SWB0_CONN15 "combo_SWB_CONN15_high" # Blanton_SWB0_CONN15
"comboA" # Blanton_SWB0_CONN16 "combo_SWB_CONN16_high" # Blanton_SWB0_CONN16
"comboA" # Blanton_SWB1_CONN13 "combo_SWB_CONN13_high" # Blanton_SWB1_CONN13
"comboA" # Blanton_SWB1_CONN14 "combo_SWB_CONN14_high" # Blanton_SWB1_CONN14
"comboA" # Blanton_SWB1_CONN15 "combo_SWB_CONN15_high" # Blanton_SWB1_CONN15
"comboA" # Blanton_SWB1_CONN16 "combo_SWB_CONN16_high" # Blanton_SWB1_CONN16
) )
# --- Source margin.sh if not already loaded --- # --- Source margin.sh if not already loaded ---
@@ -41,7 +41,7 @@ CH3_VNOM="1.8"; CH3_NET="V1P8_ALW"
CH4_VNOM="1.1"; CH4_NET="PWR_APU_VDDIO_SUS" CH4_VNOM="1.1"; CH4_NET="PWR_APU_VDDIO_SUS"
CH5_VNOM="0.75"; CH5_NET="PWR_VDD_MISC_RUN" CH5_VNOM="0.75"; CH5_NET="PWR_VDD_MISC_RUN"
CH6_VNOM="0.78"; CH6_NET="PWR_APU_VDD_MEM_RUN" CH6_VNOM="0.78"; CH6_NET="PWR_APU_VDD_MEM_RUN"
CH7_VNOM="0.8"; CH7_NET="V0P8_PHY2_DVDD" CH7_VNOM="0.816"; CH7_NET="V0P8_PHY2_DVDD"
CH8_VNOM="0.8"; CH8_NET="V0P8_AVDD" CH8_VNOM="0.8"; CH8_NET="V0P8_AVDD"
CH9_VNOM="0.8"; CH9_NET="V0P8_PHY" CH9_VNOM="0.8"; CH9_NET="V0P8_PHY"
CH10_VNOM="1.8"; CH10_NET="V1P8_FPGA" CH10_VNOM="1.8"; CH10_NET="V1P8_FPGA"
@@ -49,4 +49,4 @@ CH11_VNOM="2.5"; CH11_NET="V2P5_FPGA"
CH12_VNOM="1.1"; CH12_NET="V1P1_FPGA" CH12_VNOM="1.1"; CH12_NET="V1P1_FPGA"
CH13_VNOM="5.0"; CH13_NET="P5V_STBY" CH13_VNOM="5.0"; CH13_NET="P5V_STBY"
CH14_VNOM="3.3"; CH14_NET="P3V3_STBY" CH14_VNOM="3.3"; CH14_NET="P3V3_STBY"
CH15_VNOM="0.8"; CH15_NET="V0P8_PHY2_AVDD" CH15_VNOM="0.816"; CH15_NET="V0P8_PHY2_AVDD"
@@ -35,18 +35,18 @@ CHIP_POST_CMD=(
# chip1: SWB0 (CONN13) # chip1: SWB0 (CONN13)
# ============================================================ # ============================================================
CH0_VNOM="0.75"; CH0_NET="P0V75_DVDD_47" CH0_VNOM="0.75"; CH0_NET="P0V75_DVDD_47"
CH1_VNOM="0.75"; CH1_NET="P0V75_AVDD_47" CH1_VNOM="0.756"; CH1_NET="P0V75_AVDD_47"
CH2_VNOM="1.5"; CH2_NET="P1V5_AVDD_47" CH2_VNOM="1.524"; CH2_NET="P1V5_AVDD_47"
CH3_VNOM="0.9"; CH3_NET="P0V9_AVDD_47" CH3_VNOM="0.915"; CH3_NET="P0V9_AVDD_47"
CH4_VNOM="1.8"; CH4_NET="P1V8_1" CH4_VNOM="1.816"; CH4_NET="P1V8_1"
CH5_VNOM="3.3"; CH5_NET="PVDD3_3V_SYNTH_LDO_A3" CH5_VNOM="3.38"; CH5_NET="PVDD3_3V_SYNTH_LDO_A3"
CH6_VNOM="3.3"; CH6_NET="PVDD3_3V_SYNTH_LDO_B1" CH6_VNOM="3.38"; CH6_NET="PVDD3_3V_SYNTH_LDO_B1"
CH7_VNOM="1.8"; CH7_NET="P1V8_3" CH7_VNOM="1.816"; CH7_NET="P1V8_3"
CH8_VNOM="1.8"; CH8_NET="P1V8_DVDDIO_3" CH8_VNOM="1.8"; CH8_NET="P1V8_DVDDIO_3"
CH9_VNOM="0.75"; CH9_NET="P0V75_DVDD_39" CH9_VNOM="0.75"; CH9_NET="P0V75_DVDD_39"
CH10_VNOM="0.75"; CH10_NET="P0V75_AVDD_39" CH10_VNOM="0.756"; CH10_NET="P0V75_AVDD_39"
CH11_VNOM="1.5"; CH11_NET="P1V5_AVDD_39" CH11_VNOM="1.524"; CH11_NET="P1V5_AVDD_39"
CH12_VNOM="0.9"; CH12_NET="P0V9_AVDD_39" CH12_VNOM="0.915"; CH12_NET="P0V9_AVDD_39"
CH13_VNOM="1.5"; CH13_NET="PVDD1V5_2" CH13_VNOM="1.5"; CH13_NET="PVDD1V5_2"
CH14_VNOM="1.8"; CH14_NET="PVDD1V8_DUT" CH14_VNOM="1.8"; CH14_NET="PVDD1V8_DUT"
CH15_VNOM="1.2"; CH15_NET="PVDD_MDIO" CH15_VNOM="1.2"; CH15_NET="PVDD_MDIO"
@@ -34,16 +34,16 @@ CHIP_POST_CMD=(
# ============================================================ # ============================================================
# chip1: SWB0 (CONN14) # chip1: SWB0 (CONN14)
# ============================================================ # ============================================================
CH0_VNOM="0.75"; CH0_NET="P0V75_AVDD_7" CH0_VNOM="0.756"; CH0_NET="P0V75_AVDD_7"
CH1_VNOM="1.5"; CH1_NET="P1V5_AVDD_7" CH1_VNOM="1.524"; CH1_NET="P1V5_AVDD_7"
CH2_VNOM="0.9"; CH2_NET="P0V9_AVDD_7" CH2_VNOM="0.915"; CH2_NET="P0V9_AVDD_7"
CH3_VNOM="1.8"; CH3_NET="P1V8_5" CH3_VNOM="1.816"; CH3_NET="P1V8_5"
CH4_VNOM="1.8"; CH4_NET="P1V8_2" CH4_VNOM="1.816"; CH4_NET="P1V8_2"
CH5_VNOM="3.3"; CH5_NET="PVDD3_3V_SYNTH_LDO_B2" CH5_VNOM="3.38"; CH5_NET="PVDD3_3V_SYNTH_LDO_B2"
CH6_VNOM="3.3"; CH6_NET="PVDD3_3V_SYNTH_LDO_A2" CH6_VNOM="3.38"; CH6_NET="PVDD3_3V_SYNTH_LDO_A2"
CH7_VNOM="3.3"; CH7_NET="PVDD3_3V_SYNTH_LDO_A1" CH7_VNOM="3.38"; CH7_NET="PVDD3_3V_SYNTH_LDO_A1"
CH8_VNOM="1.5"; CH8_NET="PVDD1V5_TSC" CH8_VNOM="1.516"; CH8_NET="PVDD1V5_TSC"
CH9_VNOM="1.5"; CH9_NET="PVDD1V5_ANLG" CH9_VNOM="1.516"; CH9_NET="PVDD1V5_ANLG"
CH10_VNOM="-"; CH10_NET="NC" CH10_VNOM="-"; CH10_NET="NC"
CH11_VNOM="-"; CH11_NET="NC" CH11_VNOM="-"; CH11_NET="NC"
CH12_VNOM="1.5"; CH12_NET="PVDD1V5_1" CH12_VNOM="1.5"; CH12_NET="PVDD1V5_1"
@@ -34,19 +34,19 @@ CHIP_POST_CMD=(
# ============================================================ # ============================================================
# chip1: SWB0 (CONN15) # chip1: SWB0 (CONN15)
# ============================================================ # ============================================================
CH0_VNOM="1.5"; CH0_NET="P1V5_AVDD_55" CH0_VNOM="1.524"; CH0_NET="P1V5_AVDD_55"
CH1_VNOM="0.9"; CH1_NET="P0V9_AVDD_55" CH1_VNOM="0.915"; CH1_NET="P0V9_AVDD_55"
CH2_VNOM="0.75"; CH2_NET="P0V75_DVDD_63" CH2_VNOM="0.75"; CH2_NET="P0V75_DVDD_63"
CH3_VNOM="0.75"; CH3_NET="P0V75_AVDD_63" CH3_VNOM="0.756"; CH3_NET="P0V75_AVDD_63"
CH4_VNOM="1.5"; CH4_NET="P1V5_AVDD_63" CH4_VNOM="1.524"; CH4_NET="P1V5_AVDD_63"
CH5_VNOM="0.9"; CH5_NET="P0V9_AVDD_63" CH5_VNOM="0.915"; CH5_NET="P0V9_AVDD_63"
CH6_VNOM="3.3"; CH6_NET="PVDD3_3V_SYNTH_LDO_B3" CH6_VNOM="3.38"; CH6_NET="PVDD3_3V_SYNTH_LDO_B3"
CH7_VNOM="1.5"; CH7_NET="PVDD1V5_3" CH7_VNOM="1.5"; CH7_NET="PVDD1V5_3"
CH8_VNOM="0.85"; CH8_NET="P0V85_STBY" CH8_VNOM="0.85"; CH8_NET="P0V85_STBY"
CH9_VNOM="1.8"; CH9_NET="P1V8_STBY" CH9_VNOM="1.8"; CH9_NET="P1V8_STBY"
CH10_VNOM="-"; CH10_NET="NC" CH10_VNOM="-"; CH10_NET="NC"
CH11_VNOM="3.3"; CH11_NET="P3V3_STBY" CH11_VNOM="3.3"; CH11_NET="P3V3_STBY"
CH12_VNOM="0.9"; CH12_NET="PVDD0V9_2" CH12_VNOM="0.91"; CH12_NET="PVDD0V9_2"
CH13_VNOM="0.75"; CH13_NET="P0V75_DVDD_55" CH13_VNOM="0.75"; CH13_NET="P0V75_DVDD_55"
CH14_VNOM="0.75"; CH14_NET="P0V75_AVDD_55" CH14_VNOM="0.756"; CH14_NET="P0V75_AVDD_55"
CH15_VNOM="1.8"; CH15_NET="P1V8_DVDDIO_4" CH15_VNOM="1.8"; CH15_NET="P1V8_DVDDIO_4"
@@ -35,18 +35,18 @@ CHIP_POST_CMD=(
# chip1: SWB0 (CONN16) # chip1: SWB0 (CONN16)
# ============================================================ # ============================================================
CH0_VNOM="1.5"; CH0_NET="PVDD1V5_0" CH0_VNOM="1.5"; CH0_NET="PVDD1V5_0"
CH1_VNOM="1.8"; CH1_NET="P1V8_4" CH1_VNOM="1.816"; CH1_NET="P1V8_4"
CH2_VNOM="3.3"; CH2_NET="PVDD3_3V_SYNTH_LDO_B5" CH2_VNOM="3.38"; CH2_NET="PVDD3_3V_SYNTH_LDO_B5"
CH3_VNOM="3.3"; CH3_NET="PVDD3_3V_SYNTH_LDO_A5" CH3_VNOM="3.38"; CH3_NET="PVDD3_3V_SYNTH_LDO_A5"
CH4_VNOM="3.3"; CH4_NET="PVDD3_3V_SYNTH_LDO_B4" CH4_VNOM="3.38"; CH4_NET="PVDD3_3V_SYNTH_LDO_B4"
CH5_VNOM="3.3"; CH5_NET="PVDD3_3V_SYNTH_LDO_A4" CH5_VNOM="3.38"; CH5_NET="PVDD3_3V_SYNTH_LDO_A4"
CH6_VNOM="3.3"; CH6_NET="P3V3" CH6_VNOM="3.327"; CH6_NET="P3V3"
CH7_VNOM="0.8"; CH7_NET="PVDD0_8V_T3" CH7_VNOM="0.82"; CH7_NET="PVDD0_8V_T3"
CH8_VNOM="0.75"; CH8_NET="P0V75_DVDD_1" CH8_VNOM="0.75"; CH8_NET="P0V75_DVDD_1"
CH9_VNOM="0.75"; CH9_NET="P0V75_AVDD_1" CH9_VNOM="0.756"; CH9_NET="P0V75_AVDD_1"
CH10_VNOM="1.5"; CH10_NET="P1V5_AVDD_1" CH10_VNOM="1.524"; CH10_NET="P1V5_AVDD_1"
CH11_VNOM="0.9"; CH11_NET="P0V9_AVDD_1" CH11_VNOM="0.915"; CH11_NET="P0V9_AVDD_1"
CH12_VNOM="0.9"; CH12_NET="PVDD0V9_0" CH12_VNOM="0.915"; CH12_NET="PVDD0V9_0"
CH13_VNOM="0.9"; CH13_NET="PVDD0V9_1" CH13_VNOM="0.91"; CH13_NET="PVDD0V9_1"
CH14_VNOM="0.9"; CH14_NET="PVDD0V9_3" CH14_VNOM="0.915"; CH14_NET="PVDD0V9_3"
CH15_VNOM="1.2"; CH15_NET="PVDD1V2_T3" CH15_VNOM="1.224"; CH15_NET="PVDD1V2_T3"
@@ -35,18 +35,18 @@ CHIP_POST_CMD=(
# chip1: SWB1 (CONN13) # chip1: SWB1 (CONN13)
# ============================================================ # ============================================================
CH0_VNOM="0.75"; CH0_NET="P0V75_DVDD_47" CH0_VNOM="0.75"; CH0_NET="P0V75_DVDD_47"
CH1_VNOM="0.75"; CH1_NET="P0V75_AVDD_47" CH1_VNOM="0.756"; CH1_NET="P0V75_AVDD_47"
CH2_VNOM="1.5"; CH2_NET="P1V5_AVDD_47" CH2_VNOM="1.524"; CH2_NET="P1V5_AVDD_47"
CH3_VNOM="0.9"; CH3_NET="P0V9_AVDD_47" CH3_VNOM="0.915"; CH3_NET="P0V9_AVDD_47"
CH4_VNOM="1.8"; CH4_NET="P1V8_1" CH4_VNOM="1.816"; CH4_NET="P1V8_1"
CH5_VNOM="3.3"; CH5_NET="PVDD3_3V_SYNTH_LDO_A3" CH5_VNOM="3.38"; CH5_NET="PVDD3_3V_SYNTH_LDO_A3"
CH6_VNOM="3.3"; CH6_NET="PVDD3_3V_SYNTH_LDO_B1" CH6_VNOM="3.38"; CH6_NET="PVDD3_3V_SYNTH_LDO_B1"
CH7_VNOM="1.8"; CH7_NET="P1V8_3" CH7_VNOM="1.816"; CH7_NET="P1V8_3"
CH8_VNOM="1.8"; CH8_NET="P1V8_DVDDIO_3" CH8_VNOM="1.8"; CH8_NET="P1V8_DVDDIO_3"
CH9_VNOM="0.75"; CH9_NET="P0V75_DVDD_39" CH9_VNOM="0.75"; CH9_NET="P0V75_DVDD_39"
CH10_VNOM="0.75"; CH10_NET="P0V75_AVDD_39" CH10_VNOM="0.756"; CH10_NET="P0V75_AVDD_39"
CH11_VNOM="1.5"; CH11_NET="P1V5_AVDD_39" CH11_VNOM="1.524"; CH11_NET="P1V5_AVDD_39"
CH12_VNOM="0.9"; CH12_NET="P0V9_AVDD_39" CH12_VNOM="0.915"; CH12_NET="P0V9_AVDD_39"
CH13_VNOM="1.5"; CH13_NET="PVDD1V5_2" CH13_VNOM="1.5"; CH13_NET="PVDD1V5_2"
CH14_VNOM="1.8"; CH14_NET="PVDD1V8_DUT" CH14_VNOM="1.8"; CH14_NET="PVDD1V8_DUT"
CH15_VNOM="1.2"; CH15_NET="PVDD_MDIO" CH15_VNOM="1.2"; CH15_NET="PVDD_MDIO"
@@ -34,16 +34,16 @@ CHIP_POST_CMD=(
# ============================================================ # ============================================================
# chip1: SWB1 (CONN14) # chip1: SWB1 (CONN14)
# ============================================================ # ============================================================
CH0_VNOM="0.75"; CH0_NET="P0V75_AVDD_7" CH0_VNOM="0.756"; CH0_NET="P0V75_AVDD_7"
CH1_VNOM="1.5"; CH1_NET="P1V5_AVDD_7" CH1_VNOM="1.524"; CH1_NET="P1V5_AVDD_7"
CH2_VNOM="0.9"; CH2_NET="P0V9_AVDD_7" CH2_VNOM="0.915"; CH2_NET="P0V9_AVDD_7"
CH3_VNOM="1.8"; CH3_NET="P1V8_5" CH3_VNOM="1.816"; CH3_NET="P1V8_5"
CH4_VNOM="1.8"; CH4_NET="P1V8_2" CH4_VNOM="1.816"; CH4_NET="P1V8_2"
CH5_VNOM="3.3"; CH5_NET="PVDD3_3V_SYNTH_LDO_B2" CH5_VNOM="3.38"; CH5_NET="PVDD3_3V_SYNTH_LDO_B2"
CH6_VNOM="3.3"; CH6_NET="PVDD3_3V_SYNTH_LDO_A2" CH6_VNOM="3.38"; CH6_NET="PVDD3_3V_SYNTH_LDO_A2"
CH7_VNOM="3.3"; CH7_NET="PVDD3_3V_SYNTH_LDO_A1" CH7_VNOM="3.38"; CH7_NET="PVDD3_3V_SYNTH_LDO_A1"
CH8_VNOM="1.5"; CH8_NET="PVDD1V5_TSC" CH8_VNOM="1.516"; CH8_NET="PVDD1V5_TSC"
CH9_VNOM="1.5"; CH9_NET="PVDD1V5_ANLG" CH9_VNOM="1.516"; CH9_NET="PVDD1V5_ANLG"
CH10_VNOM="-"; CH10_NET="NC" CH10_VNOM="-"; CH10_NET="NC"
CH11_VNOM="-"; CH11_NET="NC" CH11_VNOM="-"; CH11_NET="NC"
CH12_VNOM="1.5"; CH12_NET="PVDD1V5_1" CH12_VNOM="1.5"; CH12_NET="PVDD1V5_1"
@@ -34,19 +34,19 @@ CHIP_POST_CMD=(
# ============================================================ # ============================================================
# chip1: SWB1 (CONN15) # chip1: SWB1 (CONN15)
# ============================================================ # ============================================================
CH0_VNOM="1.5"; CH0_NET="P1V5_AVDD_55" CH0_VNOM="1.524"; CH0_NET="P1V5_AVDD_55"
CH1_VNOM="0.9"; CH1_NET="P0V9_AVDD_55" CH1_VNOM="0.915"; CH1_NET="P0V9_AVDD_55"
CH2_VNOM="0.75"; CH2_NET="P0V75_DVDD_63" CH2_VNOM="0.75"; CH2_NET="P0V75_DVDD_63"
CH3_VNOM="0.75"; CH3_NET="P0V75_AVDD_63" CH3_VNOM="0.756"; CH3_NET="P0V75_AVDD_63"
CH4_VNOM="1.5"; CH4_NET="P1V5_AVDD_63" CH4_VNOM="1.524"; CH4_NET="P1V5_AVDD_63"
CH5_VNOM="0.9"; CH5_NET="P0V9_AVDD_63" CH5_VNOM="0.915"; CH5_NET="P0V9_AVDD_63"
CH6_VNOM="3.3"; CH6_NET="PVDD3_3V_SYNTH_LDO_B3" CH6_VNOM="3.38"; CH6_NET="PVDD3_3V_SYNTH_LDO_B3"
CH7_VNOM="1.5"; CH7_NET="PVDD1V5_3" CH7_VNOM="1.5"; CH7_NET="PVDD1V5_3"
CH8_VNOM="0.85"; CH8_NET="P0V85_STBY" CH8_VNOM="0.85"; CH8_NET="P0V85_STBY"
CH9_VNOM="1.8"; CH9_NET="P1V8_STBY" CH9_VNOM="1.8"; CH9_NET="P1V8_STBY"
CH10_VNOM="-"; CH10_NET="NC" CH10_VNOM="-"; CH10_NET="NC"
CH11_VNOM="3.3"; CH11_NET="P3V3_STBY" CH11_VNOM="3.3"; CH11_NET="P3V3_STBY"
CH12_VNOM="0.9"; CH12_NET="PVDD0V9_2" CH12_VNOM="0.91"; CH12_NET="PVDD0V9_2"
CH13_VNOM="0.75"; CH13_NET="P0V75_DVDD_55" CH13_VNOM="0.75"; CH13_NET="P0V75_DVDD_55"
CH14_VNOM="0.75"; CH14_NET="P0V75_AVDD_55" CH14_VNOM="0.756"; CH14_NET="P0V75_AVDD_55"
CH15_VNOM="1.8"; CH15_NET="P1V8_DVDDIO_4" CH15_VNOM="1.8"; CH15_NET="P1V8_DVDDIO_4"
@@ -35,18 +35,18 @@ CHIP_POST_CMD=(
# chip1: SWB1 (CONN16) # chip1: SWB1 (CONN16)
# ============================================================ # ============================================================
CH0_VNOM="1.5"; CH0_NET="PVDD1V5_0" CH0_VNOM="1.5"; CH0_NET="PVDD1V5_0"
CH1_VNOM="1.8"; CH1_NET="P1V8_4" CH1_VNOM="1.816"; CH1_NET="P1V8_4"
CH2_VNOM="3.3"; CH2_NET="PVDD3_3V_SYNTH_LDO_B5" CH2_VNOM="3.38"; CH2_NET="PVDD3_3V_SYNTH_LDO_B5"
CH3_VNOM="3.3"; CH3_NET="PVDD3_3V_SYNTH_LDO_A5" CH3_VNOM="3.38"; CH3_NET="PVDD3_3V_SYNTH_LDO_A5"
CH4_VNOM="3.3"; CH4_NET="PVDD3_3V_SYNTH_LDO_B4" CH4_VNOM="3.38"; CH4_NET="PVDD3_3V_SYNTH_LDO_B4"
CH5_VNOM="3.3"; CH5_NET="PVDD3_3V_SYNTH_LDO_A4" CH5_VNOM="3.38"; CH5_NET="PVDD3_3V_SYNTH_LDO_A4"
CH6_VNOM="3.3"; CH6_NET="P3V3" CH6_VNOM="3.327"; CH6_NET="P3V3"
CH7_VNOM="0.8"; CH7_NET="PVDD0_8V_T3" CH7_VNOM="0.82"; CH7_NET="PVDD0_8V_T3"
CH8_VNOM="0.75"; CH8_NET="P0V75_DVDD_1" CH8_VNOM="0.75"; CH8_NET="P0V75_DVDD_1"
CH9_VNOM="0.75"; CH9_NET="P0V75_AVDD_1" CH9_VNOM="0.756"; CH9_NET="P0V75_AVDD_1"
CH10_VNOM="1.5"; CH10_NET="P1V5_AVDD_1" CH10_VNOM="1.524"; CH10_NET="P1V5_AVDD_1"
CH11_VNOM="0.9"; CH11_NET="P0V9_AVDD_1" CH11_VNOM="0.915"; CH11_NET="P0V9_AVDD_1"
CH12_VNOM="0.9"; CH12_NET="PVDD0V9_0" CH12_VNOM="0.915"; CH12_NET="PVDD0V9_0"
CH13_VNOM="0.9"; CH13_NET="PVDD0V9_1" CH13_VNOM="0.91"; CH13_NET="PVDD0V9_1"
CH14_VNOM="0.9"; CH14_NET="PVDD0V9_3" CH14_VNOM="0.915"; CH14_NET="PVDD0V9_3"
CH15_VNOM="1.2"; CH15_NET="PVDD1V2_T3" CH15_VNOM="1.224"; CH15_NET="PVDD1V2_T3"
@@ -0,0 +1,608 @@
#!/bin/sh
# =============================================================================
# bcm_100g_dsc_cycle.sh
#
# Author : ETWen
# Date : 20260909
#
# Version History
# V1.0.0 20260909 Initial Version
# V1.1.0 20260909 All runtime output is ASCII English - the DUT serial
# console mangles UTF-8 (a Chinese error message came
# back as "ERROR: -c ? 1"). Cycle count may be given as
# a bare argument. Added -d to echo every command, and
# CMD_DELAY to pace them.
# V1.2.0 20260909 Wait on "bcmcmd ps <port>" instead of
# "show interfaces status". The state comes from the
# SDK, which is what "port en=" actually changes, so it
# no longer depends on gbsyncd syncing into the DB.
#
# Description:
# Link down/up cycling on the 100G uplink. After every re-link it collects a
# SerDes DSC dump and reads the retimer back, so you can see whether the
# tuned TX taps settle to the same place each time the link comes up.
#
# One run has two parts:
# 1. Tuning -- once. pause gbsyncd -> serdes-tx-set sys 0..7
# -> tx_taps set on four lanes of each unit
# 2. Cycle -- repeated N times:
# port en=0 -> wait until "ps <port>" reads !ena on both units
# port en=1 -> wait until "ps <port>" reads up on both units
# phydiag <port> dsc on each unit
# serdes-tx-get / serdes-rx-get sys 0..7
# all of it appended to one log, under a per-cycle heading
#
# Command source: tools/100G_dsc_cycle.txt (the hand-typed bench version).
# Change that file and this one together.
#
# Deployment:
# Script : /root/Blanton_Script/bcm_100g_dsc_cycle.sh
# Log : ~/dsc_log/100G_dsc_cycle_test_<YYYYmmdd_HHMMSS>.log
# One file per run, every cycle in it, split by "### TEST CYCLE n/N".
#
# Paths come from $HOME. Run as root (after sudo -i) and ~ is /root.
#
# Usage:
# ./bcm_100g_dsc_cycle.sh # print this help
# ./bcm_100g_dsc_cycle.sh 200 # 200 cycles
# ./bcm_100g_dsc_cycle.sh -c 200 # same thing
# ./bcm_100g_dsc_cycle.sh -c 200 -d # echo every command as it is issued
# ./bcm_100g_dsc_cycle.sh -c 10 -T # skip tuning, cycle only
# ./bcm_100g_dsc_cycle.sh -c 1 -n # dry run, print commands, touch nothing
#
# Exit code:
# 0 = every cycle linked down and up as expected, and all data was collected
# 1 = a cycle timed out waiting for link, or data was missing
# 2 = bad argument / path
# 3 = a required tool is missing (bcmcmd / show / blanton_barchetta_tool)
#
# The last line is always "### DSC_CYCLE_DONE rc=<n>", for a TTL wait to
# key on.
#
# Design notes:
# - POSIX sh. No bash, no Python.
# - All runtime output is plain ASCII. The DUT console is not UTF-8 clean:
# Chinese comes back as "M-^A"-style garbage, and an error you cannot read
# is worse than no error at all. Comments are English for the same reason -
# whoever debugs this on the bench is reading it through that console.
# - Link state comes from "bcmcmd -n <unit> -c 'ps <port>'". Its header is
# two stacked lines, so a column index cannot be derived from it the way
# it can from a SONiC table. Instead the data row is found by its first
# field ending in "(<port>)" - e.g. ce0(268) - and the state is the field
# after it:
# ce0(268) !ena 4 100G FD ... <- port disabled
# ce0(268) up 4 100G FD ... <- link up
# "down" is therefore tested as "not up", which covers !ena as well as an
# enabled port whose link has not come back.
# - Asking the SDK rather than "show interfaces status" matters here: "port
# en=" changes the SDK, and the SONiC table only follows once gbsyncd and
# orchagent have synced it into the DB. Since this test pauses gbsyncd,
# the SONiC table was the wrong thing to wait on.
# - bcmcmd reads stdin, and inside a while loop it will swallow the loop's
# input. blanton_traffic_linespeed.sh hit this at v0.3.1 (only the first
# VLAN was configured) and bcm_dsc_scan.sh hit it again at v1.3.0 (only
# the first port was scanned). Every external command here gets
# < /dev/null.
# - bcmcmd exits 0 even when the diag shell rejects a command, so the DSC is
# verified by counting "SERDES DISPLAY DIAG DATA END", and the retimer read
# by counting sections that actually have output under them - not by exit
# code, and not by counting headings this script prints itself.
#
# Cautions:
# - !! While gbsyncd is paused the gearbox state stops being synced into the
# DB. The wait reads the SDK directly ("ps <port>") so it is not affected,
# but anything you check by hand with "show interfaces status" during the
# run may be stale. Set PAUSE_GBSYNCD=0 (or -P) if that gets in the way.
# - !! On exit, including Ctrl-C, both gbsyncd containers are unpaused again
# so nothing is left paused. Set RESUME_GBSYNCD=0 to keep them paused.
# - !! phydiag dsc is read-only, but port en=0/1 and tx_taps set do change
# the hardware. Do not run this at the same time as blanton_ber.sh,
# blanton_traffic_linespeed or blanton_tr518.sh - they take the same ports.
# - !! NOT verified on hardware yet.
# =============================================================================
set -u
# ----------------------------------------------------------------------------
# Knobs - change these for a different DUT or port, not the flow below
# ----------------------------------------------------------------------------
PORT=268 # bcmcmd port number, not a port name
UNITS="0 1" # units to drive
SYS_LANES="0 1 2 3 4 5 6 7" # blanton_barchetta_tool sys lanes, tuning
SYS_TX="pre=-10 main=87 post=0" # TX setting applied to each of them
# tx_taps, one line per lane: "<unit> <lane> <main> <pre1> <post1>"
TX_TAPS="
0 0 31 4 13
0 1 31 4 13
0 2 27 4 13
0 3 29 4 13
1 0 29 4 13
1 1 30 4 13
1 2 31 4 13
1 3 30 4 13
"
TX_LANES="0 1 2 3 4 5 6 7" # retimer TX lanes read back each cycle
RX_LANES="0 1 2 3 4 5 6 7" # retimer RX lanes read back each cycle
SUDO="" # set to "sudo" if not running as root
PAUSE_GBSYNCD=1 # pause gbsyncd0/1 before tuning
RESUME_GBSYNCD=1 # unpause again on exit, Ctrl-C included
GBSYNCD="gbsyncd0 gbsyncd1"
LINK_WAIT=90 # give up waiting for a link state after this
POLL=2 # seconds between "ps <port>" reads while waiting
SETTLE=2 # quiet time after link up, before collecting
CMD_DELAY=0.2 # pause after every command issued to the DUT
OUTDIR="${HOME:-/root}/dsc_log"
# ----------------------------------------------------------------------------
CYCLES=0
DRYRUN=0
DOTUNE=1
DEBUG=0
RC=0
usage() {
cat >&2 << 'USAGE'
Usage: bcm_100g_dsc_cycle.sh <cycles> [options]
bcm_100g_dsc_cycle.sh -c <cycles> [options]
-c <n> how many cycles to run. May also be given as a bare argument.
-o <dir> log directory (default: ~/dsc_log)
-w <sec> how long to wait for a link state (default: 90)
-p <sec> how often to re-read the port state (default: 2)
-s <sec> quiet time after link up, before collecting (default: 2)
-d debug: echo every command as [CMD] before running it
-T skip tuning, go straight to the cycles
-P leave gbsyncd alone (no pause, no unpause)
-n dry run: print the commands, touch nothing
-h this help
One log per run:
~/dsc_log/100G_dsc_cycle_test_<YYYYmmdd_HHMMSS>.log
Each cycle is one "### TEST CYCLE n/N" section holding, in order: the "ps"
output showing the port down, the same showing it up, phydiag dsc for both
units, and the retimer serdes-tx-get / serdes-rx-get for sys 0..7.
Waiting for a port state is a poll, not a single read: "bcmcmd ps <port>" on
every unit, every -p seconds, until both agree or -w seconds have passed.
Examples:
./bcm_100g_dsc_cycle.sh 200
./bcm_100g_dsc_cycle.sh 200 -d
./bcm_100g_dsc_cycle.sh -c 20 -T -w 120
USAGE
exit 1
}
[ $# -eq 0 ] && usage
# getopts stops at the first argument that is not an option, so "200 -d" would
# leave -d unread. Parse, take the bare count, then parse whatever followed it.
# getopts inside a function reads the function's own arguments; OPTIND is
# global, so it has to be reset on each entry.
PARSED=0
parse_opts() {
OPTIND=1
while getopts "c:o:w:p:s:dTPnh" opt; do
case "$opt" in
c) CYCLES="$OPTARG" ;;
o) OUTDIR="$OPTARG" ;;
w) LINK_WAIT="$OPTARG" ;;
p) POLL="$OPTARG" ;;
s) SETTLE="$OPTARG" ;;
d) DEBUG=1 ;;
T) DOTUNE=0 ;;
P) PAUSE_GBSYNCD=0; RESUME_GBSYNCD=0 ;;
n) DRYRUN=1 ;;
*) usage ;;
esac
done
PARSED=$((OPTIND - 1))
}
parse_opts "$@"
shift "$PARSED"
# Allow the count as a bare argument: "... 200" == "... -c 200". That is what
# most people type first, and answering it with an error helps nobody.
if [ "$CYCLES" = "0" ] && [ $# -ge 1 ]; then
case "$1" in
-*) : ;; # an option; leave it for the second pass
*) CYCLES="$1"; shift ;; # anything else is meant to be the count,
esac # and the check below says so if it is not
fi
# Anything after the count is options again: "200 -d -T"
if [ $# -gt 0 ]; then
parse_opts "$@"
shift "$PARSED"
fi
if [ $# -gt 0 ]; then
echo "ERROR: unexpected argument '$1'" >&2
echo " run with no argument to see the usage" >&2
exit 2
fi
case "$CYCLES" in
''|*[!0-9]*)
echo "ERROR: cycle count must be a positive integer (got: '$CYCLES')" >&2
echo " try: $0 200 or $0 -c 200" >&2
exit 2 ;;
esac
if [ "$CYCLES" -lt 1 ]; then
echo "ERROR: cycle count must be at least 1 (got: $CYCLES)" >&2
exit 2
fi
# ----------------------------------------------------------------------------
# Colour, only when stdout is a terminal, so a redirected run stays clean
# ----------------------------------------------------------------------------
if [ -t 1 ] && [ -z "${NO_COLOR:-}" ]; then
C_INFO=$(printf '\033[1;34m') # blue
C_OK=$(printf '\033[1;32m') # green
C_WARN=$(printf '\033[1;33m') # yellow
C_ERR=$(printf '\033[1;31m') # red
C_CMD=$(printf '\033[90m') # dark grey
C_OFF=$(printf '\033[0m')
else
C_INFO=''; C_OK=''; C_WARN=''; C_ERR=''; C_CMD=''; C_OFF=''
fi
# A dry run touches nothing, so it must not sleep either - otherwise
# "-c 200 -n" sits there for as long as the real thing would.
naptime() { [ "$DRYRUN" = "1" ] && return 0; [ "${1:-0}" = "0" ] && return 0; sleep "$1"; }
info() { printf '%s[info]%s %s\n' "$C_INFO" "$C_OFF" "$*"; }
ok() { printf '%s[ OK ]%s %s\n' "$C_OK" "$C_OFF" "$*"; }
warn() { printf '%s[warn]%s %s\n' "$C_WARN" "$C_OFF" "$*" >&2; }
err() { printf '%s[ERR ]%s %s\n' "$C_ERR" "$C_OFF" "$*" >&2; }
# Both -d and -n print commands. During collection the whole block is
# redirected into a temp file, so those lines would end up in the file with
# nothing on screen. Bind fd 9 to the terminal up front and print there.
if { [ "$DEBUG" = "1" ] || [ "$DRYRUN" = "1" ]; } && ( true > /dev/tty ) 2>/dev/null; then
exec 9> /dev/tty
else
exec 9>&1
fi
# ':' is a special built-in in dash (the DUT's /bin/sh); a failed redirection
# on one kills the whole shell with no message. Hence (true > /dev/tty) in a
# subshell above - if that cannot open, only the subshell dies.
# Print a command the way you would type it: quote any argument that needs it,
# so the line can be copied back to the prompt as is.
# NOTE: sh has no local variables - every name assigned here is global. All
# helper variables are therefore prefixed. _show_cmd used to assign "tag",
# which silently overwrote the caller's cycle label and turned every later
# message into "[info] [CMD] : Wait Port Link Down".
_show_cmd() {
_sc_tag="$1"; _sc_col="$2"; shift 2
{
printf '%s%s%s' "$_sc_col" "$_sc_tag" "$C_OFF"
for a in "$@"; do
case "$a" in
''|*[!A-Za-z0-9_./=:,+-]*) printf " '%s'" "$a" ;;
*) printf ' %s' "$a" ;;
esac
done
printf '\n'
} >&9
}
# Every external command goes through here: never reads stdin, echoed when
# asked, and paced by CMD_DELAY so the DUT is not hammered.
run() {
[ "$DEBUG" = "1" ] && [ "$DRYRUN" = "0" ] && _show_cmd '[CMD]' "$C_CMD" "$@"
if [ "$DRYRUN" = "1" ]; then
_show_cmd ' +' "$C_CMD" "$@"
return 0
fi
"$@" < /dev/null
_cmd_rc=$?
naptime "$CMD_DELAY"
return $_cmd_rc
}
# Same, but discards output. Do not write "> /dev/null" at the call site or
# the [CMD] line goes with it.
runq() {
[ "$DEBUG" = "1" ] && [ "$DRYRUN" = "0" ] && _show_cmd '[CMD]' "$C_CMD" "$@"
if [ "$DRYRUN" = "1" ]; then
_show_cmd ' +' "$C_CMD" "$@"
return 0
fi
"$@" < /dev/null > /dev/null 2>&1
_cmd_rc=$?
naptime "$CMD_DELAY"
return $_cmd_rc
}
# ----------------------------------------------------------------------------
# Preflight
# ----------------------------------------------------------------------------
if [ "$DRYRUN" = "0" ]; then
command -v bcmcmd > /dev/null 2>&1 || { err "not found: bcmcmd"; exit 3; }
# -T only skips tuning; the per-cycle retimer read still needs this tool
if [ ! -x /usr/sbin/blanton_barchetta_tool ]; then
err "not found: /usr/sbin/blanton_barchetta_tool (tuning and the per-cycle retimer read both use it)"
exit 3
fi
fi
# busybox sleep may not take a fraction
if [ "$DRYRUN" = "0" ] && [ "$CMD_DELAY" != "0" ] && ! sleep "$CMD_DELAY" 2>/dev/null; then
warn "sleep '$CMD_DELAY' not supported, falling back to 1"
CMD_DELAY=1
fi
mkdir -p "$OUTDIR" 2>/dev/null || { err "cannot create outdir: $OUTDIR"; exit 2; }
[ -w "$OUTDIR" ] || { err "outdir not writable: $OUTDIR"; exit 2; }
TS=$(date '+%Y%m%d_%H%M%S')
LOG="${OUTDIR}/100G_dsc_cycle_test_${TS}.log"
: > "$LOG" || { err "cannot write $LOG"; exit 2; }
STATUS_TMP=$(mktemp) || { err "mktemp failed"; exit 2; }
CYCLE_TMP=$(mktemp) || { err "mktemp failed"; exit 2; }
# ----------------------------------------------------------------------------
# gbsyncd must go back the way it was found, or the container stays paused
# ----------------------------------------------------------------------------
PAUSED=0
resume_gbsyncd() {
[ "$PAUSED" = "1" ] || return 0
[ "$RESUME_GBSYNCD" = "1" ] || return 0
PAUSED=0
for _rg_c in $GBSYNCD; do
if runq $SUDO docker unpause "$_rg_c"; then
info "gbsyncd resumed: $_rg_c"
else
warn "docker unpause $_rg_c failed - check it by hand"
fi
done
}
on_exit() { rm -f "$STATUS_TMP" "$CYCLE_TMP"; resume_gbsyncd; }
on_int() {
echo ""
warn "interrupted by user"
resume_gbsyncd
printf '\n### DSC_CYCLE_DONE rc=130 (INTERRUPTED)\n' >> "$LOG"
printf '### DSC_CYCLE_DONE rc=130 (INTERRUPTED)\n'
rm -f "$STATUS_TMP" "$CYCLE_TMP"
exit 130
}
trap on_exit EXIT
trap on_int INT TERM
tee_log() { tee -a "$LOG"; }
# ----------------------------------------------------------------------------
# Link state. Find which field "Oper" is from the header row, then read that
# field on every data row. Returns 0 only when every interface matches.
# The table itself is left in $STATUS_TMP for the caller to print.
# ----------------------------------------------------------------------------
# $1 = "up" or "down". Runs "ps <port>" on every unit, leaves the combined
# output in $STATUS_TMP for the caller to print, and returns 0 only when every
# unit agrees.
link_is() {
_li_want="$1"
: > "$STATUS_TMP"
for _li_u in $UNITS; do
printf '\n[unit %s] bcmcmd -n %s -c "ps %s"\n' "$_li_u" "$_li_u" "$PORT" >> "$STATUS_TMP"
if [ "$DRYRUN" = "1" ]; then
_show_cmd ' +' "$C_CMD" bcmcmd -n "$_li_u" -c "ps $PORT"
printf ' ce0(%s) %s 4 100G FD (dry-run)\n' \
"$PORT" "$([ "$_li_want" = up ] && echo 'up ' || echo '!ena')" >> "$STATUS_TMP"
continue
fi
[ "$DEBUG" = "1" ] && _show_cmd '[CMD]' "$C_CMD" bcmcmd -n "$_li_u" -c "ps $PORT"
bcmcmd -n "$_li_u" -c "ps $PORT" < /dev/null >> "$STATUS_TMP" 2>&1
naptime "$CMD_DELAY"
done
# The data row is the one whose first field ends in "(<port>)"; the state
# is the field right after it. "down" is "not up", so !ena counts.
awk -v port="$PORT" -v want="$_li_want" -v units="$(echo "$UNITS" | wc -w)" '
$1 ~ ("\\(" port "\\)$") {
n++
if (want == "up") { if ($2 != "up") bad++ }
else { if ($2 == "up") bad++ }
}
END { exit (n >= units && bad == 0) ? 0 : 1 }
' "$STATUS_TMP"
}
# $1 = wanted state (Down/up), $2 = label for the messages
wait_link() {
_wl_want="$1"; _wl_tag="$2"
_wl_waited=0
while :; do
if link_is "$_wl_want"; then
{
printf '\n--- port %s after %ss ---\n' "$_wl_want" "$_wl_waited"
cat "$STATUS_TMP"
} | tee_log
ok "$_wl_tag : port $_wl_want after ${_wl_waited}s"
return 0
fi
[ "$_wl_waited" -ge "$LINK_WAIT" ] && break
naptime "$POLL"
_wl_waited=$((_wl_waited + POLL))
done
{
printf '\n--- TIMEOUT waiting for port %s (%ss) ---\n' "$_wl_want" "$LINK_WAIT"
cat "$STATUS_TMP"
} | tee_log
err "$_wl_tag : TIMEOUT waiting for port $_wl_want (${LINK_WAIT}s)"
return 1
}
port_en() {
for _pe_u in $UNITS; do
runq bcmcmd -n "$_pe_u" -c "port ${PORT} en=$1"
done
}
# ----------------------------------------------------------------------------
# Log header
# ----------------------------------------------------------------------------
{
printf '=====================================================================\n'
printf '100G DSC cycle test\n'
printf ' script : bcm_100g_dsc_cycle.sh V1.2.0\n'
printf ' started : %s\n' "$(date '+%Y-%m-%d %H:%M:%S')"
printf ' cycles : %s\n' "$CYCLES"
printf ' port : %s units : %s\n' "$PORT" "$UNITS"
printf ' tuning : %s\n' "$([ "$DOTUNE" = 1 ] && echo yes || echo 'skipped (-T)')"
printf ' tx lanes : %s\n' "$TX_LANES"
printf ' rx lanes : %s\n' "$RX_LANES"
printf ' link wait: %ss poll %ss settle %ss cmd delay %ss\n' \
"$LINK_WAIT" "$POLL" "$SETTLE" "$CMD_DELAY"
printf '=====================================================================\n'
} >> "$LOG"
info "log : $LOG"
# ----------------------------------------------------------------------------
# 1. Tuning, once
# ----------------------------------------------------------------------------
if [ "$DOTUNE" = "1" ]; then
info "Tuning"
printf '\n### TUNING %s\n' "$(date '+%Y-%m-%d %H:%M:%S')" >> "$LOG"
if [ "$PAUSE_GBSYNCD" = "1" ]; then
for c in $GBSYNCD; do
if runq $SUDO docker pause "$c"; then
PAUSED=1
info "gbsyncd paused: $c"
else
warn "docker pause $c failed (container not running?)"
fi
done
fi
run $SUDO /usr/sbin/blanton_barchetta_tool --serdes-tx-get sys 0 2>&1 | tee_log
for l in $SYS_LANES; do
# shellcheck disable=SC2086
run $SUDO /usr/sbin/blanton_barchetta_tool --serdes-tx-set sys "$l" $SYS_TX 2>&1 | tee_log
done
echo "$TX_TAPS" | while read -r u lane main pre1 post1; do
[ -n "${u:-}" ] || continue
run bcmcmd -n "$u" -c \
" dsh -c 'phydiag ${PORT} tx_taps set lane=${lane} main=${main} pre1=${pre1} post1=${post1}' " \
2>&1 | tee_log
done
ok "Tuning done"
fi
# ----------------------------------------------------------------------------
# 2. Test cycles
# ----------------------------------------------------------------------------
n=1
while [ "$n" -le "$CYCLES" ]; do
tag="Test Cycle $n / $CYCLES"
printf '\n\n### TEST CYCLE %s/%s %s\n' "$n" "$CYCLES" \
"$(date '+%Y-%m-%d %H:%M:%S')" >> "$LOG"
# ---- Disable Port ------------------------------------------------------
info "$tag : Disable Port"
port_en 0
info "$tag : Wait Port Link Down"
wait_link down "$tag" || RC=1
# ---- Enable Port -------------------------------------------------------
info "$tag : Enable Port"
port_en 1
info "$tag : Wait Link up"
if wait_link up "$tag"; then
naptime "$SETTLE"
else
RC=1
fi
# ---- Collect -----------------------------------------------------------
# Written to a per-cycle temp file first, then appended. Appending to the
# log and then re-reading it to check would mean re-reading an ever larger
# file every round - O(n^2) over 200 cycles.
info "$tag : Collect Data"
: > "$CYCLE_TMP"
for u in $UNITS; do
{
printf '\n--- phydiag %s dsc : unit %s ---\n' "$PORT" "$u"
run bcmcmd -n "$u" -c "dsh -c 'phydiag ${PORT} dsc'" 2>&1
} >> "$CYCLE_TMP"
done
info "$tag : Read Retimer TX"
for l in $TX_LANES; do
{
printf '\n--- serdes-tx-get sys %s ---\n' "$l"
run $SUDO /usr/sbin/blanton_barchetta_tool --serdes-tx-get sys "$l" 2>&1
} >> "$CYCLE_TMP"
done
info "$tag : Read Retimer RX"
for l in $RX_LANES; do
{
printf '\n--- serdes-rx-get sys %s ---\n' "$l"
run $SUDO /usr/sbin/blanton_barchetta_tool --serdes-rx-get sys "$l" 2>&1
} >> "$CYCLE_TMP"
done
cat "$CYCLE_TMP" >> "$LOG"
if [ "$DRYRUN" = "0" ]; then
# bcmcmd exits 0 even when it failed, so count the end marker instead
got=$(grep -c 'SERDES DISPLAY DIAG DATA END' "$CYCLE_TMP" 2>/dev/null || true)
want=$(echo "$UNITS" | wc -w)
if [ "${got:-0}" -lt "$want" ]; then
err "$tag : got only ${got:-0}/${want} DSC dumps"
RC=1
fi
# The section headings are printed by this script, so counting them
# only proves the loop ran. Count sections that have output under them.
for d in tx rx; do
case "$d" in
tx) wantl="$TX_LANES" ;;
rx) wantl="$RX_LANES" ;;
esac
got_l=$(awk -v pat="--- serdes-${d}-get sys " '
index($0, pat) == 1 { if (insec && body) ok++; insec = 1; body = 0; next }
/^--- / || /^### / { if (insec && body) ok++; insec = 0; next }
insec && NF { body = 1 }
END { if (insec && body) ok++; print ok + 0 }
' "$CYCLE_TMP")
want_l=$(echo "$wantl" | wc -w)
if [ "${got_l:-0}" -lt "$want_l" ]; then
err "$tag : retimer $(echo "$d" | tr 'a-z' 'A-Z') returned data for only ${got_l:-0}/${want_l} lanes"
RC=1
fi
done
fi
n=$((n + 1))
done
resume_gbsyncd
printf '\n### DSC_CYCLE_DONE rc=%s\n' "$RC" >> "$LOG"
if [ "$RC" = "0" ]; then
ok "all $CYCLES cycles done -> $LOG"
else
err "some cycles did not complete as expected - see $LOG"
fi
printf '### DSC_CYCLE_DONE rc=%s\n' "$RC"
exit "$RC"
@@ -0,0 +1,204 @@
#!/bin/sh
# =============================================================================
# bcm_dsc_parse_V1.0.0.sh
#
# Author : ETWen
# Date : 20260906
#
# Version History
# V1.0.0 20260906 Initial Version
#
# Description:
# Parse Broadcom diag shell "phydiag <pm_id> dsc" raw log into CSV.
# 支援多個 pm_id 串接在同一份 log,以 "pm_id =" 當 record separator。
#
# Output:
# <prefix>_lane.csv : 每個 lane 一列(TXEQ / RXFFE / DFE / EYE / SNR ...)
# <prefix>_pm.csv : 每個 pm_id 一列(溫度 / PLL / lane 數 / SNR-EYE 統計)
#
# Usage:
# ./bcm_dsc_parse_V1.0.0.sh -i dsc_raw.log [-o out_prefix]
#
# Design notes:
# - 純 POSIX sh + awk(mawk 相容),不依賴 Python。
# - Lane row 採「括號群組出現順序」抽取,而非固定欄位位置,對排版空白
# 變動免疫。SDK 若增減欄位,群組數不等於 9,該列會被標記 UNPARSED
# 並輸出到 stderr,不會靜默解析錯誤。
# - 已知 header 名稱數與資料欄數不一致之處:
# * (P RX, CDRxN, UC_CFG, UC_STS, RST, STP) 6 個名字 / 7 個值
# (RST 實際是 "0,0" 兩欄)
# * TXEQ 尾端多一個逗號
# * AVG_TMON 顯示為 "(11) 66C" 兩個 token
# - SD / LCK 的 "*" 為 sticky 旗標,本版拆成獨立欄位保留,不做判讀。
# - BER 欄若為 "!chk_en" 表示 checker 未開啟,值無效,原樣保留。
# =============================================================================
set -e
IN=""
PREFIX="dsc"
usage() {
echo "Usage: $0 -i <raw_log> [-o <out_prefix>]" >&2
exit 1
}
while getopts "i:o:h" opt; do
case "$opt" in
i) IN="$OPTARG" ;;
o) PREFIX="$OPTARG" ;;
*) usage ;;
esac
done
[ -n "$IN" ] || usage
[ -f "$IN" ] || { echo "ERROR: input not found: $IN" >&2; exit 2; }
LANE_CSV="${PREFIX}_lane.csv"
PM_CSV="${PREFIX}_pm.csv"
# 先去掉 CR(console / telnet log 常帶),再交給 awk
tr -d '\r' < "$IN" | awk -v LANE_CSV="$LANE_CSV" -v PM_CSV="$PM_CSV" '
function trim(s) { sub(/^[ \t]+/, "", s); sub(/[ \t]+$/, "", s); return s }
# 掃描一列,取出所有頂層括號群組到 G[],群組前的英數 prefix 到 P[],
# 其餘純量文字留在 REST。回傳群組數。
function split_groups(line, i, ch, d, buf, ng, rest, prefix) {
split("", G, ":"); split("", P, ":")
ng = 0; d = 0; buf = ""; rest = ""; prefix = ""
for (i = 1; i <= length(line); i++) {
ch = substr(line, i, 1)
if (ch == "(") {
d++
if (d == 1) {
buf = ""; prefix = ""
if (match(rest, /[A-Za-z_]+$/)) {
prefix = substr(rest, RSTART, RLENGTH)
rest = substr(rest, 1, RSTART - 1)
}
continue
}
}
if (ch == ")") {
d--
if (d == 0) { ng++; G[ng] = buf; P[ng] = prefix; rest = rest " "; continue }
}
if (d > 0) { buf = buf ch; continue }
rest = rest ch
}
REST = rest
return ng
}
# 取括號群組的第 n 個子欄位(以逗號分隔)
function gf(idx, n, a, c) {
c = split(G[idx], a, ",")
if (n > c) return ""
return trim(a[n])
}
function is_num(s) { return (s ~ /^[+-]?[0-9]+(\.[0-9]+)?$/) }
function reset_pm() {
core = ""; sdtype = ""; hw_lanes = ""; lane_sel = ""
live_temp = ""; avg_tmon = ""; pll_lock = ""
n_lane = 0; snr_min = ""; snr_max = ""; eye_min = ""; all_lck = 1
}
function flush_pm() {
if (pm == "") return
printf "%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s\n",
pm, core, sdtype, hw_lanes, lane_sel, n_lane,
live_temp, avg_tmon, pll_lock,
(snr_min == "" ? "NA" : snr_min),
(eye_min == "" ? "NA" : eye_min),
(n_lane == 0 ? "NA" : (all_lck ? "PASS" : "FAIL")) > PM_CSV
}
BEGIN {
pm = ""; in_lane = 0; core_row = 0; bad = 0
print "pm_id,core,lane,serdes_type,sd,sd_sticky,lck,lck_sticky,rxppm,txppm," \
"txeq_n3,txeq_n2,txeq_n1,txeq_m,txeq_p1,txeq_p2,txeq_sum," \
"rxffe_n3,rxffe_n2,rxffe_n1,rxffe_m,rxffe_p1,rxffe_p2," \
"dfe1,dfe2,pf_m,pf_l,pf_h,vga,dco,tp0,tp1,tp2,flt_m,flt_s," \
"nlc_u,nlc_l,eye_u,eye_m,eye_l,link_time,snr,ber," \
"live_temp,avg_tmon,pll_lock,rx_pol,cdr,uc_cfg,uc_sts,rst,stp" > LANE_CSV
print "pm_id,core,serdes_type,hw_lanes,lane_select,active_lanes," \
"live_temp,avg_tmon,pll_lock,snr_min,eye_min,lck_all" > PM_CSV
}
/^pm_id[ \t]*=/ { flush_pm(); pm = $NF; reset_pm(); in_lane = 0; next }
/^Core[ \t]*=/ { if (match($0, /Core[ \t]*=[ \t]*[0-9]+/)) { core = $0; sub(/.*Core[ \t]*=[ \t]*/, "", core); sub(/[^0-9].*/, "", core) } next }
/^SerDes type[ \t]*=/ { sdtype = $NF; next }
/^Rev ID # Lanes/ { hw_lanes = $NF; next }
/^lane_select[ \t]*=/ { lane_sel = $NF; next }
/^CORE[ \t]+RST_ST/ { core_row = 1; next }
core_row == 1 {
line = $0
gsub(/\([^)]*\)[ \t]*/, "", line) # 去掉 AVG_TMON 的 "(11)"
n = split(trim(line), c, /[ \t]+/)
if (n >= 15) { live_temp = c[9]; avg_tmon = c[10]; pll_lock = c[15] }
core_row = 0
next
}
/^LN[ \t]*\(/ { in_lane = 1; next }
/SERDES DISPLAY DIAG DATA END/ { in_lane = 0; next }
in_lane && /^[0-9]+[ \t]*\(/ {
ng = split_groups($0)
if (ng != 9) {
printf "UNPARSED (groups=%d) pm_id=%s: %s\n", ng, pm, $0 > "/dev/stderr"
bad++
next
}
nr = split(trim(REST), r, /[ \t]+/)
if (nr != 10) {
printf "UNPARSED (scalars=%d) pm_id=%s: %s\n", nr, pm, $0 > "/dev/stderr"
bad++
next
}
lane = r[1]
sd = r[2]; sd_st = (sd ~ /\*/) ? 1 : 0; gsub(/\*/, "", sd)
lck = r[3]; lck_st = (lck ~ /\*/) ? 1 : 0; gsub(/\*/, "", lck)
rxppm = r[4]; vga = r[5]; dco = r[6]; txppm = r[7]
link_time = r[8]; snr = r[9]; ber = r[10]
# TXEQ 六個 tap 與總和(僅在全為數值時計算)
tsum = 0; tok = 1
for (i = 1; i <= 6; i++) {
tq[i] = gf(7, i)
if (is_num(tq[i])) tsum += tq[i]; else tok = 0
}
printf "%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,", pm, core, lane, sdtype, sd, sd_st, lck, lck_st, rxppm, txppm > LANE_CSV
printf "%s,%s,%s,%s,%s,%s,%s,", tq[1], tq[2], tq[3], tq[4], tq[5], tq[6], (tok ? tsum : "NA") > LANE_CSV
printf "%s,%s,%s,%s,%s,%s,", gf(4,1), gf(4,2), gf(4,3), gf(4,4), gf(4,5), gf(4,6) > LANE_CSV
printf "%s,%s,", gf(5,1), gf(5,2) > LANE_CSV
printf "%s,%s,%s,%s,%s,", gf(2,1), gf(2,2), gf(2,3), vga, dco > LANE_CSV
printf "%s,%s,%s,%s,%s,", gf(3,1), gf(3,2), gf(3,3), gf(6,1), gf(6,2) > LANE_CSV
printf "%s,%s,%s,%s,%s,", gf(8,1), gf(8,2), gf(9,1), gf(9,2), gf(9,3) > LANE_CSV
printf "%s,%s,%s,", link_time, snr, ber > LANE_CSV
printf "%s,%s,%s,", live_temp, avg_tmon, pll_lock > LANE_CSV
printf "%s,%s,%s,%s,%s/%s,%s\n", gf(1,1), gf(1,2), gf(1,3), gf(1,4), gf(1,5), gf(1,6), gf(1,7) > LANE_CSV
# per-PM 統計
n_lane++
if (lck != "1" || sd != "1") all_lck = 0
if (is_num(snr)) { if (snr_min == "" || snr + 0 < snr_min + 0) snr_min = snr }
for (i = 1; i <= 3; i++) {
e = gf(9, i)
if (is_num(e)) { if (eye_min == "" || e + 0 < eye_min + 0) eye_min = e }
}
next
}
END {
flush_pm()
if (bad > 0) printf "WARN: %d lane row(s) unparsed\n", bad > "/dev/stderr"
}
'
echo "OK: ${LANE_CSV}, ${PM_CSV}"
@@ -0,0 +1,347 @@
#!/bin/sh
# =============================================================================
# bcm_dsc_scan.sh
#
# Author : ETWen
# Date : 20260906
#
# Version History
# V1.0.0 20260906 Initial Version
# V1.1.0 20260906 Log 預設輸出至 <script_dir>/log,掃描後自動複製到
# /host/hw-eval/jobs/;非 tty 環境改用逐行進度輸出,
# 避免灌爆 Tera Term logopen 的 log
# V1.2.0 20260906 新增 -f 自訂 log 檔名(支援 %u / %t 佔位符)與
# -F 強制覆蓋;預設不覆蓋既有檔案,自動加序號
# V1.3.0 20260907 修正 bcmcmd 讀取 stdin 導致掃描迴圈在第一筆之後
# 提前結束的問題(迴圈改用 fd 3,bcmcmd 導向
# /dev/null);新增實際迭代筆數與清單筆數的檢查
#
# Description:
# 在 Blanton SONiC DUT 上批次執行 Broadcom diag shell 的
# "phydiag <port> dsc",收集 raw log 供離線解析。
#
# 實際下的指令為:
# bcmcmd -n <unit> -c "dsh -c 'phydiag <port> dsc'"
#
# Deployment:
# Script : /root/Blanton_Script/bcm_dsc_scan.sh
# Log : /root/Blanton_Script/log/dsc_raw_u<unit>_<YYYYmmdd_HHMMSS>.log
# Copy : /host/hw-eval/jobs/
#
# Log 檔名可用 -f 覆寫,支援兩個佔位符:
# %u -> u0 / u1
# %t -> YYYYmmdd_HHMMSS
# -f 只接受檔名,不接受路徑;目錄一律由 -o 決定。
# 同時掃兩個 unit 但檔名未含 %u 時,會自動在副檔名前插入 _u<unit>,
# 避免第二個 unit 覆蓋掉第一個。
#
# 路徑由 $0 推導,不依賴 $HOME。Script A 以 sudo -i 執行時 ~ 為 /root,
# 直接寫死 ~ 會有風險,故一律使用絕對路徑。
#
# Usage:
# ./bcm_dsc_scan.sh # unit 0 與 1 都掃,掃完自動複製
# ./bcm_dsc_scan.sh -u 0 # 只掃 unit 0
# ./bcm_dsc_scan.sh -n # dry-run,只列出要掃的 port
# ./bcm_dsc_scan.sh -C # 不複製到 /host/hw-eval/jobs
# ./bcm_dsc_scan.sh -c /other/dir # 指定複製目的地
# ./bcm_dsc_scan.sh -u 0 -f dsc_before_reboot.log
# ./bcm_dsc_scan.sh -f blanton_dsc_%u_%t.log
#
# Exit code:
# 0 = 全部 port 皆取得完整 dump
# 1 = 有 port 未取得完整 dump,或複製失敗
# 2 = 參數 / 路徑錯誤
# 3 = 找不到 bcmcmd
#
# 結束時固定輸出一行 "### DSC_SCAN_DONE rc=<n>",供 TTL 端 wait 判斷。
#
# Design notes:
# - 純 POSIX sh,不依賴 bash / Python。
# - Port 清單以「範圍字串」定義在下方 PORTS_* 變數,展開後去重。
# 100G 清單先展開,故重複的 port 會被判定為 100G(目前僅 port 268)。
# - bcmcmd 即使指令失敗通常仍回傳 0,因此不以 exit code 判斷成功與否;
# 改由 marker 行 + "SERDES DISPLAY DIAG DATA END" 數量比對。
# - 先寫入本機 log 目錄再複製,而非直接寫遠端,避免中途失敗遺失整份資料。
#
# Assumptions:
# - unit 0 與 unit 1 使用相同的 port 清單。
# - phydiag 的參數為此清單中的 port 編號(非 port name)。
# - 由 root 執行(Script A 的 sudo -i 之後),故不呼叫 sudo。
#
# Cautions:
# - 全清單約 445 port x 2 unit,估計 10 分鐘,請勿把 DELAY 設為 0。
# - phydiag ... dsc 為唯讀操作,不會變更 SerDes 設定。
# =============================================================================
set -u
# ----------------------------------------------------------------------------
# Port list (以空白分隔的範圍或單一值)
# ----------------------------------------------------------------------------
PORTS_100G="268"
PORTS_200G="1-24 40-96 112-168 184-240 256-308 310-327 342-380 382-399 414-452 454-471 486-524 526-543 558-565"
# ----------------------------------------------------------------------------
# Paths / defaults
# ----------------------------------------------------------------------------
SCRIPT_DIR=$(CDPATH= cd -- "$(dirname -- "$0")" && pwd) || exit 2
UNITS="0 1"
OUTDIR="${SCRIPT_DIR}/log"
COPYDIR="/host/hw-eval/jobs"
DELAY="0.2"
DRYRUN=0
DOCOPY=1
LOGNAME="" # -f 指定的 log 檔名,空字串表示使用預設命名
FORCE=0 # -F 允許覆蓋既有檔案
PROGRESS_EVERY=50 # 非 tty 環境每 N 筆印一行進度
usage() {
cat >&2 << 'USAGE'
Usage: bcm_dsc_scan.sh [-u <0|1>] [-o <outdir>] [-f <logname>] [-F]
[-c <copydir>] [-C] [-d <sec>] [-n] [-h]
-u <unit> 只掃指定 unit。省略則 unit 0 與 1 都掃。
-o <dir> log 輸出目錄 (default: <script_dir>/log)
-f <name> 自訂 log 檔名(僅檔名,不含路徑)
佔位符: %u -> u0/u1 , %t -> YYYYmmdd_HHMMSS
default: dsc_raw_%u_%t.log
-F 允許覆蓋既有同名檔案 (default: 自動加序號 _1 / _2 ...)
-c <dir> 掃描後複製目的地 (default: /host/hw-eval/jobs)
-C 不複製
-d <sec> 每筆 phydiag 之間的間隔 (default: 0.2)
-n dry-run,列出展開後的 port 清單與指令,不實際執行
-h 顯示此說明
USAGE
exit 1
}
while getopts "u:o:f:Fc:Cd:nh" opt; do
case "$opt" in
u)
case "$OPTARG" in
0|1) UNITS="$OPTARG" ;;
*) echo "ERROR: -u 只接受 0 或 1 (got: $OPTARG)" >&2; exit 2 ;;
esac
;;
o) OUTDIR="$OPTARG" ;;
f)
case "$OPTARG" in
"") echo "ERROR: -f 不可為空" >&2; exit 2 ;;
*/*) echo "ERROR: -f 只接受檔名,路徑請用 -o (got: $OPTARG)" >&2; exit 2 ;;
*) LOGNAME="$OPTARG" ;;
esac
;;
F) FORCE=1 ;;
c) COPYDIR="$OPTARG" ;;
C) DOCOPY=0 ;;
d) DELAY="$OPTARG" ;;
n) DRYRUN=1 ;;
*) usage ;;
esac
done
mkdir -p "$OUTDIR" 2>/dev/null || { echo "ERROR: cannot create outdir: $OUTDIR" >&2; exit 2; }
[ -w "$OUTDIR" ] || { echo "ERROR: outdir not writable: $OUTDIR" >&2; exit 2; }
# ----------------------------------------------------------------------------
# sleep 是否支援小數秒(busybox sleep 可能只吃整數)
# ----------------------------------------------------------------------------
if ! sleep "$DELAY" 2>/dev/null; then
echo "WARN: sleep '$DELAY' 不支援,改用 sleep 1" >&2
DELAY="1"
fi
# ----------------------------------------------------------------------------
# 展開 port 清單。100G 先展開,重複者以 100G 為準。
# 輸出格式: "<port>,<speed>",依 port 數值排序。
# ----------------------------------------------------------------------------
PORTFILE=$(mktemp) || { echo "ERROR: mktemp failed" >&2; exit 2; }
trap 'rm -f "$PORTFILE"' EXIT
trap 'echo "" >&2; echo "### DSC_SCAN_DONE rc=130 (INTERRUPTED)" >&2; rm -f "$PORTFILE"; exit 130' INT TERM
awk -v a="$PORTS_100G" -v b="$PORTS_200G" '
function expand(s, spd, n, i, j, p, k, lo, hi) {
n = split(s, p, /[ \t]+/)
for (i = 1; i <= n; i++) {
if (p[i] == "") continue
if (split(p[i], k, "-") == 2) { lo = k[1] + 0; hi = k[2] + 0 }
else { lo = p[i] + 0; hi = lo }
if (hi < lo) { printf "ERROR: bad range %s\n", p[i] > "/dev/stderr"; continue }
for (j = lo; j <= hi; j++) if (!(j in SPD)) SPD[j] = spd
}
}
BEGIN {
expand(a, "100G") # 先展開 100G,重複的 port 由 100G 取得
expand(b, "200G")
for (p in SPD) print p "," SPD[p]
}' | sort -t, -k1,1n > "$PORTFILE"
TOTAL=$(wc -l < "$PORTFILE" | tr -d ' ')
[ "$TOTAL" -gt 0 ] || { echo "ERROR: port list is empty" >&2; exit 2; }
N100=$(grep -c ',100G$' "$PORTFILE" || true)
N200=$(grep -c ',200G$' "$PORTFILE" || true)
echo "Script dir : $SCRIPT_DIR" >&2
echo "Log dir : $OUTDIR" >&2
echo "Port list : $TOTAL ports (200G x2: $N200, 100G: $N100)" >&2
echo "Units : $UNITS" >&2
echo "Delay : ${DELAY}s" >&2
# ----------------------------------------------------------------------------
# Dry-run
# ----------------------------------------------------------------------------
if [ "$DRYRUN" -eq 1 ]; then
for U in $UNITS; do
echo "--- unit $U ---"
while IFS=, read -r P SPD; do
printf 'bcmcmd -n %s -c "dsh -c '\''phydiag %s dsc'\''" # %s\n' "$U" "$P" "$SPD"
done < "$PORTFILE"
done
echo "### DSC_SCAN_DONE rc=0 (dry-run)" >&2
exit 0
fi
command -v bcmcmd > /dev/null 2>&1 || {
echo "ERROR: bcmcmd not found in PATH" >&2
echo "### DSC_SCAN_DONE rc=3" >&2
exit 3
}
# stderr 是 tty 才用 \r 進度條;被導向檔案(Tera Term logopen)時改逐行輸出
if [ -t 2 ]; then TTY=1; else TTY=0; fi
# ----------------------------------------------------------------------------
# Log 檔名處理
# ----------------------------------------------------------------------------
# 純 POSIX 的字串取代,避免 sed 對檔名中的特殊字元誤判
replace_all() { # $1=haystack $2=needle $3=replacement
_s=$1; _n=$2; _r=$3; _out=""
while :; do
case "$_s" in
*"$_n"*)
_out="${_out}${_s%%"$_n"*}${_r}"
_s=${_s#*"$_n"}
;;
*) _out="${_out}${_s}"; break ;;
esac
done
printf '%s' "$_out"
}
# 依 unit 組出 log 檔名。未指定 -f 時使用預設命名。
build_logname() { # $1=unit
_u=$1
_n=${LOGNAME:-dsc_raw_%u_%t.log}
case "$_n" in *%u*) _has_u=1 ;; *) _has_u=0 ;; esac
_n=$(replace_all "$_n" '%u' "u${_u}")
_n=$(replace_all "$_n" '%t' "$TS")
# 掃兩個 unit 但檔名沒有 %u,第二個 unit 會覆蓋第一個,故自動加上 _u<unit>
if [ "$_has_u" -eq 0 ] && [ "$MULTI" -eq 1 ]; then
case "$_n" in
*.*) _n="${_n%.*}_u${_u}.${_n##*.}" ;;
*) _n="${_n}_u${_u}" ;;
esac
fi
printf '%s' "$_n"
}
# 檔案已存在時自動加序號,避免覆蓋掉先前的掃描結果(-F 可強制覆蓋)
uniquify() { # $1=filename
_f=$1
[ -e "${OUTDIR}/${_f}" ] || { printf '%s' "$_f"; return; }
if [ "$FORCE" -eq 1 ]; then
echo "WARN: 覆蓋既有檔案 ${OUTDIR}/${_f}" >&2
printf '%s' "$_f"; return
fi
case "$_f" in
*.*) _b=${_f%.*}; _e=".${_f##*.}" ;;
*) _b=$_f; _e="" ;;
esac
_i=1
while [ -e "${OUTDIR}/${_b}_${_i}${_e}" ]; do _i=$((_i + 1)); done
echo "WARN: ${_f} 已存在,改用 ${_b}_${_i}${_e}(-F 可強制覆蓋)" >&2
printf '%s' "${_b}_${_i}${_e}"
}
MULTI=0
[ "$(echo "$UNITS" | wc -w | tr -d ' ')" -gt 1 ] && MULTI=1
# ----------------------------------------------------------------------------
# Scan
# ----------------------------------------------------------------------------
TS=$(date +%Y%m%d_%H%M%S)
RC=0
LOGS=""
for U in $UNITS; do
LOG="${OUTDIR}/$(uniquify "$(build_logname "$U")")"
: > "$LOG" || { echo "ERROR: cannot write $LOG" >&2; exit 2; }
LOGS="$LOGS $LOG"
printf '### SCAN_BEGIN unit=%s time=%s total=%s script=bcm_dsc_scan_V1.3.0\n' \
"$U" "$(date '+%Y-%m-%d %H:%M:%S')" "$TOTAL" >> "$LOG"
echo "[unit $U] scanning $TOTAL ports -> $LOG" >&2
SEQ=0
while IFS=, read -r P SPD <&3; do
SEQ=$((SEQ + 1))
printf '### PORT unit=%s port=%s speed=%s seq=%s/%s\n' "$U" "$P" "$SPD" "$SEQ" "$TOTAL" >> "$LOG"
# bcmcmd 會讀取 stdin,若不導成 /dev/null 會把 PORTFILE 剩餘內容吸走,
# 導致迴圈在第一筆之後就讀到 EOF 而提前結束。
bcmcmd -n "$U" -c "dsh -c 'phydiag $P dsc'" >> "$LOG" 2>&1 < /dev/null || RC=1
if [ "$TTY" -eq 1 ]; then
printf '\r[unit %s] %s/%s port=%-5s' "$U" "$SEQ" "$TOTAL" "$P" >&2
elif [ $((SEQ % PROGRESS_EVERY)) -eq 0 ] || [ "$SEQ" -eq "$TOTAL" ]; then
printf '[unit %s] %s/%s port=%s\n' "$U" "$SEQ" "$TOTAL" "$P" >&2
fi
sleep "$DELAY"
done 3< "$PORTFILE"
[ "$TTY" -eq 1 ] && printf '\n' >&2
printf '### SCAN_END unit=%s time=%s\n' "$U" "$(date '+%Y-%m-%d %H:%M:%S')" >> "$LOG"
# 檢查 1:實際迭代筆數是否等於 port 清單筆數。
# 迴圈若因 stdin 被子程序吸走而提前結束,只靠下面的 marker/dump 比對抓不到。
if [ "$SEQ" -ne "$TOTAL" ]; then
echo "ERROR: unit $U 只跑了 $SEQ/$TOTAL 筆,迴圈提前結束" >&2
RC=1
fi
# 檢查 2:每筆 PORT marker 應對應一個 dsc 區塊
MARK=$(grep -c '^### PORT ' "$LOG" || true)
DUMP=$(grep -c 'SERDES DISPLAY DIAG DATA END' "$LOG" || true)
if [ "$MARK" -ne "$DUMP" ]; then
echo "WARN: unit $U markers=$MARK dsc_blocks=$DUMP (有 port 未取得完整 dump)" >&2
RC=1
fi
echo "Saved: $LOG (${DUMP}/${TOTAL} dumps)" >&2
done
# ----------------------------------------------------------------------------
# Copy to job directory
# ----------------------------------------------------------------------------
if [ "$DOCOPY" -eq 1 ]; then
if mkdir -p "$COPYDIR" 2>/dev/null && [ -w "$COPYDIR" ]; then
for L in $LOGS; do
if cp -p "$L" "$COPYDIR/"; then
echo "Copied: $COPYDIR/$(basename "$L")" >&2
else
echo "ERROR: copy failed: $L -> $COPYDIR" >&2
RC=1
fi
done
sync
else
echo "ERROR: copydir not writable: $COPYDIR (log 仍保留在 $OUTDIR)" >&2
RC=1
fi
fi
echo "### DSC_SCAN_DONE rc=${RC}" >&2
exit "$RC"
@@ -1,8 +1,31 @@
#!/usr/bin/env bash #!/usr/bin/env bash
# ============================================================================= # =============================================================================
# blanton_ber.sh -- SerDes BER test over every cabled port (PRBS via phydiag) # blanton_ber.sh -- SerDes BER test, cabled ports PLUS the 100G uplink
# ============================================================================= # =============================================================================
# Version History: # Version History:
# V1.1.1 2026-09-15 Fix: "the BCM shell rejected 'phydiag ... prbs get'" on
# a run that was in fact working. The rejection check
# grepped the WHOLE output, case-insensitively, for
# ERROR|Invalid|... -- and 'prbs get' prints one line per
# lane, so a lane that had not locked ("PRBS Error!")
# matched. The command was fine; the output was data.
# Two consequences: a good run reported a hard error, and
# the lock-count check that was supposed to judge exactly
# those lanes never ran. Per-lane result lines are now
# excluded from the check, the match is case-sensitive,
# and a real rejection prints the offending line.
# The rejection check had been there since V1.0.0, so
# every earlier run carried the same blind spot.
# V1.1.0 2026-09-15 Adds port 268, the 100G uplink, which the old port list
# deliberately skipped (it jumps 256-259 -> 270-308).
# The per-lane table is unchanged; the summary now breaks
# each unit into "200G ports" and "100G p268" plus a
# TOTAL row, so the uplink cannot hide inside a 432-lane
# average. A group that reports no lane at all counts as
# a failure, not a pass - silence on the port under test
# is not a result. Developed on the bench as
# blanton_ber_test.sh and folded back over this file once
# it was proven, so there is one BER script again.
# V1.0.1 2026-08-28 Fix: every lane reported NA and the Port column showed # V1.0.1 2026-08-28 Fix: every lane reported NA and the Port column showed
# "NA". bcmcmd returns CRLF, and the BER is the last token # "NA". bcmcmd returns CRLF, and the BER is the last token
# on its line, so the CR stayed glued to the number: it # on its line, so the CR stayed glued to the number: it
@@ -19,8 +42,24 @@
# ============================================================================= # =============================================================================
# #
# This is the WHOLE-SWITCH BER sweep: every cabled port, both lanes, PRBS-31 # This is the WHOLE-SWITCH BER sweep: every cabled port, both lanes, PRBS-31
# through the SerDes. Not to be confused with port_prbs_monitor.sh, which drives # through the SerDes -- and, unlike blanton_ber.sh, the 100G uplink as well.
# the two 100G uplinks only and polls them continuously. # Not to be confused with port_prbs_monitor.sh, which drives the two 100G
# uplinks only and polls them continuously.
#
# The port list is two groups:
# BER_PORTS_200G the cabled 200G ports (432 lanes per unit)
# BER_PORTS_100G the 100G uplink, port 268 = ce0, one per unit
# They are measured in one phydiag pass, but the summary reports them
# separately per unit, plus a TOTAL:
#
# Unit GROUP LANES PASS FAIL NA WORST BER ...
# unit 0 200G ports 432 432 0 0 2.07e-08 PASS
# unit 0 100G p268 4 4 0 0 1.10e-11 PASS
# unit 0 TOTAL 436 436 0 0 2.07e-08 PASS
# unit 1 ...
#
# A 100G row of "NO DATA" means the uplink reported no lane at all, and is
# treated as a failure -- silence on the port under test is not a pass.
# #
# Order of operations (matches tools/BER_Test.txt): # Order of operations (matches tools/BER_Test.txt):
# init phydiag <ports> prbs set p=3 arm PRBS on every lane # init phydiag <ports> prbs set p=3 arm PRBS on every lane
@@ -51,7 +90,7 @@
# -u|--unit <0|1|all|0,1> bcmcmd unit(s). Default: $BER_UNITS ("0 1") # -u|--unit <0|1|all|0,1> bcmcmd unit(s). Default: $BER_UNITS ("0 1")
# -c|--criteria <ber> report: PASS threshold (default $BER_MAX) # -c|--criteria <ber> report: PASS threshold (default $BER_MAX)
# -i|--interval <sec> start: prbsstat Interval (default $BER_INTERVAL) # -i|--interval <sec> start: prbsstat Interval (default $BER_INTERVAL)
# -p|--ports <list> override the port list # -p|--ports <list> override the whole port list (both groups)
# -F|--fail-only report: list only the lanes that FAIL # -F|--fail-only report: list only the lanes that FAIL
# --tsv report: tab-separated (paste into Excel) # --tsv report: tab-separated (paste into Excel)
# --raw report: also print the raw 'prbsstat Ber' output # --raw report: also print the raw 'prbsstat Ber' output
@@ -63,7 +102,8 @@
# #
# Environment overrides: # Environment overrides:
# BCMCMD_CMD=bcmcmd BER_UNITS="0 1" BER_MAX=1e-6 BER_INTERVAL=30 # BCMCMD_CMD=bcmcmd BER_UNITS="0 1" BER_MAX=1e-6 BER_INTERVAL=30
# BER_PORTS="1-24,..." BER_POLY=p=3 BER_LOG_DIR=/tmp DEBUG_MODE=1 # BER_PORTS="1-24,..." BER_PORTS_200G=... BER_PORTS_100G=268
# BER_POLY=p=3 BER_LOG_DIR=/tmp DEBUG_MODE=1
# ============================================================================= # =============================================================================
# === Config ================================================================== # === Config ==================================================================
@@ -73,7 +113,18 @@ BER_UNITS="${BER_UNITS:-0 1}" # one DUT = two switch boards (0 and 1)
# The cabled ports, in bcm logical-port numbering. Same list as # The cabled ports, in bcm logical-port numbering. Same list as
# blanton_traffic_linespeed.sh's TL_PS_PORTS -- kept as one string so it can be # blanton_traffic_linespeed.sh's TL_PS_PORTS -- kept as one string so it can be
# pasted straight from/into a manual phydiag command. # pasted straight from/into a manual phydiag command.
BER_PORTS="${BER_PORTS:-1-24,40-96,112-168,184-240,256-259,270-308,310-327,342-380,382-399,414-452,454-471,486-524,526-543,558-565}" #
# Note the gap: the list runs 256-259 then 270-308, so 260..269 are not in it.
# 268 is ce0, the 100G uplink, and it is the reason this fork exists.
BER_PORTS_200G="${BER_PORTS_200G:-1-24,40-96,112-168,184-240,256-259,270-308,310-327,342-380,382-399,414-452,454-471,486-524,526-543,558-565}"
# The 100G uplink. One port per unit -- unit 0 and unit 1 each have their own
# ce0(268), so a two-unit run measures two of them. Comma-separated if more are
# ever added; the summary treats everything in here as the "100G" group.
BER_PORTS_100G="${BER_PORTS_100G:-268}"
# What actually goes on the phydiag command line. -p|--ports overrides the lot.
BER_PORTS="${BER_PORTS:-${BER_PORTS_200G},${BER_PORTS_100G}}"
BER_POLY="${BER_POLY:-p=3}" # passed to 'prbs set' BER_POLY="${BER_POLY:-p=3}" # passed to 'prbs set'
BER_INTERVAL="${BER_INTERVAL:-30}" # passed to 'prbsstat STArt Interval=' BER_INTERVAL="${BER_INTERVAL:-30}" # passed to 'prbsstat STArt Interval='
@@ -111,6 +162,24 @@ _ber_dbg() { [ "$DEBUG_MODE" = "1" ] && echo -e "\033[90m[DEBG] $*\033[0m" >&2;
BER_ERR_PAT="${BER_ERR_PAT:-ERROR|Failed to execute|Invalid|Syntax error|Unavailable|Unknown command}" BER_ERR_PAT="${BER_ERR_PAT:-ERROR|Failed to execute|Invalid|Syntax error|Unavailable|Unknown command}"
BER_BENIGN_PAT="${BER_BENIGN_PAT:-polling socket timeout}" BER_BENIGN_PAT="${BER_BENIGN_PAT:-polling socket timeout}"
# A per-lane result line -- " 185 : PRBS OK!..." from 'prbs get', or
# " 203[1] : 5.05e-09" from 'prbsstat Ber'. These are MEASUREMENTS, never
# shell diagnostics, and they must be kept out of the rejection check:
# a lane that did not lock prints its own wording (PRBS Error!, and similar),
# which a case-insensitive match on "ERROR" reads as the BCM shell refusing
# the command. That is what turned a perfectly good run into
# [ERR ] unit 1: the BCM shell rejected 'phydiag ... prbs get'
# while init/start/report were in fact working -- and it skipped the
# lock-count check that was supposed to judge those very lanes.
BER_LANE_LINE='^[ \t]*[0-9]+(\[[0-9]+\])?[ \t]*:'
# _ber_shell_error <output> -- echo the offending line(s), return 0 if any
_ber_shell_error() {
printf '%s\n' "$1" | tr -d '\r' \
| grep -vE "$BER_LANE_LINE" \
| grep -E "$BER_ERR_PAT"
}
# _ber_bcm <unit> <phydiag args...> -- wraps in dsh -c 'phydiag <ports> ...' # _ber_bcm <unit> <phydiag args...> -- wraps in dsh -c 'phydiag <ports> ...'
# echoes the DUT output on stdout, returns 0 ok / 1 failed # echoes the DUT output on stdout, returns 0 ok / 1 failed
_ber_bcm() { _ber_bcm() {
@@ -125,11 +194,14 @@ _ber_bcm() {
local out rc local out rc
out=$("$BCMCMD_CMD" -n "$unit" -c "$cmd" </dev/null 2>&1); rc=$? out=$("$BCMCMD_CMD" -n "$unit" -c "$cmd" </dev/null 2>&1); rc=$?
printf '%s\n' "$out" printf '%s\n' "$out"
if echo "$out" | grep -qiE "$BER_ERR_PAT"; then local why
why=$(_ber_shell_error "$out")
if [ -n "$why" ]; then
_ber_err "unit $unit: the BCM shell rejected 'phydiag ... $*'" _ber_err "unit $unit: the BCM shell rejected 'phydiag ... $*'"
printf '%s\n' "$why" | sed 's/^/ /' >&2
return 1 return 1
fi fi
if [ "$rc" -ne 0 ] && ! echo "$out" | grep -qiE "$BER_BENIGN_PAT"; then if [ "$rc" -ne 0 ] && ! printf '%s\n' "$out" | grep -qiE "$BER_BENIGN_PAT"; then
_ber_err "unit $unit: bcmcmd exited $rc on 'phydiag ... $*'" _ber_err "unit $unit: bcmcmd exited $rc on 'phydiag ... $*'"
return 1 return 1
fi fi
@@ -243,13 +315,32 @@ _ber_render() {
-v FAILONLY="$BER_FAIL_ONLY" \ -v FAILONLY="$BER_FAIL_ONLY" \
-v TSV="$BER_TSV" \ -v TSV="$BER_TSV" \
-v COLOR="$color" \ -v COLOR="$color" \
-v SIDE="$side" ' -v SIDE="$side" \
-v P100="$BER_PORTS_100G" '
function vc(v) { function vc(v) {
if (!COLOR) return v if (!COLOR) return v
if (v == "PASS") return "\033[32m" v "\033[0m" if (v == "PASS") return "\033[32m" v "\033[0m"
if (v == "FAIL") return "\033[31m" v "\033[0m" if (v == "FAIL") return "\033[31m" v "\033[0m"
return "\033[33m" v "\033[0m" return "\033[33m" v "\033[0m"
} }
# Fold one lane into a group tally. Called once for its own group and
# and once for ALL, so the TOTAL row is never a hand-added sum that can
# drift away from the parts.
function acct(g, verdict, berstr, berval, label) {
GN[g]++
if (verdict == "PASS") GP[g]++
else if (verdict == "FAIL") GF[g]++
else GNA[g]++
if (berval >= 0 && (!(g in GW) || berval > GW[g])) {
GW[g] = berval; GWS[g] = berstr; GWL[g] = label
}
}
function emit(g, lanes) {
lanes = GN[g] + 0
printf "SUM %s %d %d %d %d %s %s\n", g, lanes, GP[g] + 0, GF[g] + 0, GNA[g] + 0,
(lanes > 0 && (g in GWS)) ? GWS[g] : "-",
(lanes > 0 && (g in GWL)) ? GWL[g] : "-" > SIDE
}
BEGIN { BEGIN {
LIM = MAXBER + 0 LIM = MAXBER + 0
NC = 4 NC = 4
@@ -258,6 +349,18 @@ _ber_render() {
HDR[3] = "BER"; AL[3] = 1 HDR[3] = "BER"; AL[3] = 1
HDR[4] = "RESULT"; AL[4] = 1 HDR[4] = "RESULT"; AL[4] = 1
worst = -1; worstlane = "-" worst = -1; worstlane = "-"
# Expand the 100G list ("268" or "268,270-271") into a lookup, so a lane
# can be put in the right group by its port number alone.
np = split(P100, pp, /[ ,\t]+/)
for (i2 = 1; i2 <= np; i2++) {
if (pp[i2] == "") continue
if (split(pp[i2], rr, "-") == 2) {
for (j2 = rr[1] + 0; j2 <= rr[2] + 0; j2++) IS100[j2] = 1
} else {
IS100[pp[i2] + 0] = 1
}
}
} }
# bcmcmd hands back CRLF. On the cd/traffic report the counter is followed by # bcmcmd hands back CRLF. On the cd/traffic report the counter is followed by
# a delta, so the CR got trimmed with the rest of the line; here the BER is # a delta, so the CR got trimmed with the rest of the line; here the BER is
@@ -282,6 +385,8 @@ _ber_render() {
seen++ seen++
n++ n++
PORT[n] = port; LANE[n] = lane; BERS[n] = ber PORT[n] = port; LANE[n] = lane; BERS[n] = ber
grp = ((port + 0) in IS100) ? "P100" : "P200"
GRP[n] = grp
# a lane that reported something non-numeric has no usable measurement # a lane that reported something non-numeric has no usable measurement
if (ber ~ /^[0-9]+(\.[0-9]+)?([eE][-+]?[0-9]+)?$/) { if (ber ~ /^[0-9]+(\.[0-9]+)?([eE][-+]?[0-9]+)?$/) {
v = ber + 0 v = ber + 0
@@ -290,7 +395,10 @@ _ber_render() {
if (v > worst) { worst = v; worstlane = port "[" lane "]"; worststr = ber } if (v > worst) { worst = v; worstlane = port "[" lane "]"; worststr = ber }
} else { } else {
V[n] = "NA"; nna++ V[n] = "NA"; nna++
v = -1
} }
acct(grp, V[n], ber, v, port "[" lane "]")
acct("ALL", V[n], ber, v, port "[" lane "]")
} }
END { END {
if (seen == 0) { if (seen == 0) {
@@ -327,19 +435,32 @@ _ber_render() {
} }
print "" print ""
printf "# lanes measured : %d\n", n printf "# lanes measured : %d (200G %d, 100G %d)\n", n, GN["P200"] + 0, GN["P100"] + 0
printf "# %s %d %s %d %s %d (criteria BER < %s)\n", \ printf "# %s %d %s %d %s %d (criteria BER < %s)\n", \
vc("PASS"), npass + 0, vc("FAIL"), nfail + 0, vc("NA"), nna + 0, MAXBER vc("PASS"), npass + 0, vc("FAIL"), nfail + 0, vc("NA"), nna + 0, MAXBER
if (worst >= 0) if (worst >= 0)
printf "# worst lane : %s %s\n", worstlane, worststr printf "# worst lane : %s %s\n", worstlane, worststr
if (SIDE != "" && SIDE != "/dev/null") if (GN["P100"] + 0 == 0)
printf "SUM %d %d %d %d %s %s\n", n, npass + 0, nfail + 0, nna + 0, \ printf "# %s the 100G port list (%s) matched no lane in this capture\n", vc("NA"), P100
(worst >= 0 ? worststr : "-"), worstlane > SIDE else
printf "# 100G p%s : %s %d %s %d %s %d worst %s %s\n", P100,
vc("PASS"), GP["P100"] + 0, vc("FAIL"), GF["P100"] + 0,
vc("NA"), GNA["P100"] + 0,
("P100" in GWS) ? GWS["P100"] : "-",
("P100" in GWL) ? GWL["P100"] : "-"
if (SIDE != "" && SIDE != "/dev/null") {
emit("P200"); emit("P100"); emit("ALL")
}
exit (nfail || nna) ? 2 : 0 exit (nfail || nna) ? 2 : 0
}' "$log" }' "$log"
} }
# _ber_summary <stamp> -- one table for every unit, printed last # _ber_summary <stamp> -- one table for every unit, printed last.
#
# Each unit gets three rows: the 200G ports, the 100G uplink on its own, and a
# TOTAL. Unit 0 and unit 1 each have their own ce0(268), so the 100G row is per
# unit too -- a bad uplink on one board is what this fork exists to make
# visible, and averaged into 432 other lanes it would not be.
_ber_summary() { _ber_summary() {
local stamp="$1" unit side g r y n worst=0 local stamp="$1" unit side g r y n worst=0
g=$'\033[32m'; r=$'\033[31m'; y=$'\033[33m'; n=$'\033[0m' g=$'\033[32m'; r=$'\033[31m'; y=$'\033[33m'; n=$'\033[0m'
@@ -347,27 +468,41 @@ _ber_summary() {
echo "" echo ""
echo "===== summary : all units =====" echo "===== summary : all units ====="
printf '%-8s %8s %8s %8s %8s %-12s %-10s %s\n' \ printf '%-8s %-12s %7s %7s %7s %7s %-12s %-12s %s\n' \
"Unit" "LANES" "PASS" "FAIL" "NA" "WORST BER" "WORST LANE" "RESULT" "Unit" "GROUP" "LANES" "PASS" "FAIL" "NA" "WORST BER" "WORST LANE" "RESULT"
local tag lanes pass fail na wber wlane v any=0 local tag grp lanes pass fail na wber wlane v any=0 label
for unit in $BER_UNITS; do for unit in $BER_UNITS; do
side="$BER_LOG_DIR/berside_unit${unit}_${stamp}" side="$BER_LOG_DIR/bertside_unit${unit}_${stamp}"
[ -r "$side" ] || continue [ -r "$side" ] || continue
read -r tag lanes pass fail na wber wlane < "$side" 2>/dev/null while read -r tag grp lanes pass fail na wber wlane; do
[ "$tag" = "SUM" ] || continue [ "$tag" = "SUM" ] || continue
any=1 any=1
if [ "${fail:-0}" -gt 0 ] || [ "${na:-0}" -gt 0 ]; then case "$grp" in
v="${r}FAIL${n}"; worst=2 P200) label="200G ports" ;;
else P100) label="100G p${BER_PORTS_100G}" ;;
v="${g}PASS${n}" ALL) label="TOTAL" ;;
fi *) label="$grp" ;;
printf '%-8s %8s %8s %8s %8s %-12s %-10s %b\n' \ esac
"unit $unit" "$lanes" "$pass" "$fail" "$na" "$wber" "$wlane" "$v" # A group with no lanes is not a pass. On the 100G row it means the
# uplink never reported -- exactly the case worth flagging.
if [ "${lanes:-0}" -eq 0 ]; then
v="${y}NO DATA${n}"
[ "$grp" = "P100" ] && worst=2
elif [ "${fail:-0}" -gt 0 ] || [ "${na:-0}" -gt 0 ]; then
v="${r}FAIL${n}"; worst=2
else
v="${g}PASS${n}"
fi
printf '%-8s %-12s %7s %7s %7s %7s %-12s %-12s %b\n' \
"unit $unit" "$label" "$lanes" "$pass" "$fail" "$na" \
"$wber" "$wlane" "$v"
done < "$side"
done done
[ "$any" = "1" ] || echo " (no unit produced a result)" [ "$any" = "1" ] || echo " (no unit produced a result)"
echo "" echo ""
printf 'criteria: BER < %s\n' "$BER_MAX" printf 'criteria: BER < %s\n' "$BER_MAX"
printf '100G group: port(s) %s -- one per unit\n' "$BER_PORTS_100G"
echo "" echo ""
return "$worst" return "$worst"
} }
@@ -391,7 +526,7 @@ blanton_ber_report() {
stamp=$(date +%Y%m%d_%H%M%S 2>/dev/null || echo now) stamp=$(date +%Y%m%d_%H%M%S 2>/dev/null || echo now)
for unit in $BER_UNITS; do for unit in $BER_UNITS; do
log="$BER_LOG_DIR/prbsber_unit${unit}_${stamp}.log" log="$BER_LOG_DIR/prbsber_unit${unit}_${stamp}.log"
side="$BER_LOG_DIR/berside_unit${unit}_${stamp}" side="$BER_LOG_DIR/bertside_unit${unit}_${stamp}"
: > "$side" : > "$side"
if ! _ber_bcm "$unit" "prbsstat Ber" > "$log" 2>&1; then if ! _ber_bcm "$unit" "prbsstat Ber" > "$log" 2>&1; then
_ber_err "unit $unit: 'prbsstat Ber' failed (see $log)"; worst=1; continue _ber_err "unit $unit: 'prbsstat Ber' failed (see $log)"; worst=1; continue
@@ -409,22 +544,24 @@ blanton_ber_report() {
_ber_summary "$stamp"; rc=$? _ber_summary "$stamp"; rc=$?
[ "$rc" -gt "$worst" ] && worst=$rc [ "$rc" -gt "$worst" ] && worst=$rc
rm -f "$BER_LOG_DIR"/berside_unit*_"${stamp}" rm -f "$BER_LOG_DIR"/bertside_unit*_"${stamp}"
return "$worst" return "$worst"
} }
# === Help ==================================================================== # === Help ====================================================================
blanton_ber_help() { blanton_ber_help() {
echo -e "\033[1mblanton_ber.sh - SerDes BER test over every cabled port (PRBS via phydiag)\033[0m" echo -e "\033[1mblanton_ber.sh - SerDes BER test: cabled 200G ports + the 100G uplink\033[0m"
echo "" echo ""
echo -e " Units : \033[36m$BER_UNITS\033[0m poly: \033[36m$BER_POLY\033[0m interval: \033[36m${BER_INTERVAL}s\033[0m" echo -e " Units : \033[36m$BER_UNITS\033[0m poly: \033[36m$BER_POLY\033[0m interval: \033[36m${BER_INTERVAL}s\033[0m"
echo -e " Criteria : BER < \033[36m$BER_MAX\033[0m" echo -e " Criteria : BER < \033[36m$BER_MAX\033[0m"
echo -e " Ports : \033[36m$BER_PORTS\033[0m" echo -e " 200G : \033[36m$BER_PORTS_200G\033[0m"
echo -e " 100G : \033[36m$BER_PORTS_100G\033[0m (ce0, one per unit -- reported on its own row)"
echo "" echo ""
echo -e "\033[1mSubcommands\033[0m" echo -e "\033[1mSubcommands\033[0m"
echo -e " \033[33minit\033[0m prbs set $BER_POLY + prbs get (checks every lane locked)" echo -e " \033[33minit\033[0m prbs set $BER_POLY + prbs get (checks every lane locked)"
echo -e " \033[33mstart\033[0m prbsstat STArt Interval=$BER_INTERVAL" echo -e " \033[33mstart\033[0m prbsstat STArt Interval=$BER_INTERVAL"
echo -e " \033[33mreport\033[0m prbsstat Ber -> per-lane table + PASS/FAIL + summary" echo -e " \033[33mreport\033[0m prbsstat Ber -> per-lane table + PASS/FAIL + summary"
echo -e " summary splits each unit into 200G ports / 100G p$BER_PORTS_100G / TOTAL"
echo -e " \033[33mstop\033[0m prbsstat STOp" echo -e " \033[33mstop\033[0m prbsstat STOp"
echo -e " \033[33mclear\033[0m prbs clear (disarms PRBS -- 'init' again before measuring)" echo -e " \033[33mclear\033[0m prbs clear (disarms PRBS -- 'init' again before measuring)"
echo -e " \033[33mhelp\033[0m" echo -e " \033[33mhelp\033[0m"
@@ -433,7 +570,7 @@ blanton_ber_help() {
echo -e " \033[33m-u|--unit\033[0m <0|1|all> bcmcmd unit(s); 'all' = 0 1 (default: $BER_UNITS)" echo -e " \033[33m-u|--unit\033[0m <0|1|all> bcmcmd unit(s); 'all' = 0 1 (default: $BER_UNITS)"
echo -e " \033[33m-c|--criteria\033[0m <ber> PASS threshold (default $BER_MAX)" echo -e " \033[33m-c|--criteria\033[0m <ber> PASS threshold (default $BER_MAX)"
echo -e " \033[33m-i|--interval\033[0m <sec> prbsstat Interval (default $BER_INTERVAL)" echo -e " \033[33m-i|--interval\033[0m <sec> prbsstat Interval (default $BER_INTERVAL)"
echo -e " \033[33m-p|--ports\033[0m <list> override the port list" echo -e " \033[33m-p|--ports\033[0m <list> override the whole port list (both groups)"
echo -e " \033[33m-F|--fail-only\033[0m report: list only failing lanes" echo -e " \033[33m-F|--fail-only\033[0m report: list only failing lanes"
echo -e " \033[33m--tsv\033[0m report: tab-separated" echo -e " \033[33m--tsv\033[0m report: tab-separated"
echo -e " \033[33m--raw\033[0m report: also print the raw output" echo -e " \033[33m--raw\033[0m report: also print the raw output"
File diff suppressed because it is too large Load Diff
@@ -6,7 +6,7 @@
# V0.1.0 2026-08-17 First version. Bash port of the three Tera Term macros # V0.1.0 2026-08-17 First version. Bash port of the three Tera Term macros
# utils/traffic_loopback_vlan_setting.ttl (VLAN 30..137, # utils/traffic_loopback_vlan_setting.ttl (VLAN 30..137,
# port pair cdN <-> cdN+32), utils/traffic_loopback_start.ttl # port pair cdN <-> cdN+32), utils/traffic_loopback_start.ttl
# (tx 100 length=512 VLantag=<vid>) and # (tx <count> length=<len> VLantag=<vid>) and
# utils/traffic_loopback_vlan_remove.ttl. # utils/traffic_loopback_vlan_remove.ttl.
# One DUT = two switch boards -> bcmcmd unit 0 and 1 # One DUT = two switch boards -> bcmcmd unit 0 and 1
# (bcmcmd -n <unit>), default both. # (bcmcmd -n <unit>), default both.
@@ -90,6 +90,16 @@
# With only one unit selected the summary reports # With only one unit selected the summary reports
# UNDECIDED (exit 3) instead of guessing. # UNDECIDED (exit 3) instead of guessing.
# TL_CE_ENABLE=0 restores the old cd-pairs-only behaviour. # TL_CE_ENABLE=0 restores the old cd-pairs-only behaviour.
# V0.7.0 2026-09-01 Change: tx bursts carry PatternRandom=yes and the defaults
# become tx 200 length=324 (were 100 / 512).
# Random payload keeps the bit pattern changing instead of
# repeating, which is what makes a marginal lane show up;
# a fixed pattern can sit on a benign sequence all run.
# TL_TX_RANDOM=no forces the fixed pattern, "" leaves the
# argument off entirely (pre-V0.7.0 wire format).
# NOTE: counters scale with count x length, so totals from
# before this build are not comparable - 200x324 moves
# about 27% more bytes per burst than 100x512.
# V0.6.0 2026-08-28 Add: ce0 traffic is now SUSTAINED, not a single burst. # V0.6.0 2026-08-28 Add: ce0 traffic is now SUSTAINED, not a single burst.
# A cd pair keeps its packets circulating because they # A cd pair keeps its packets circulating because they
# flood to the partner port; ce0 has no partner and a # flood to the partner port; ce0 has no partner and a
@@ -142,6 +152,8 @@
# aliases: -tx | --tx # aliases: -tx | --tx
# -l|--length <n> tx packet length (default $TL_TX_LENGTH) # -l|--length <n> tx packet length (default $TL_TX_LENGTH)
# aliases: -length | --len # aliases: -length | --len
# -r|--random <yes|no> tx PatternRandom (default $TL_TX_RANDOM;
# empty string omits the argument)
# -p|--ports <list|all> ps: port list ('all' = plain 'ps', every port) # -p|--ports <list|all> ps: port list ('all' = plain 'ps', every port)
# -T|--tolerance <n> report: allowed |delta| in packets (default 0; # -T|--tolerance <n> report: allowed |delta| in packets (default 0;
# -T 1 absorbs the normal snapshot skew) # -T 1 absorbs the normal snapshot skew)
@@ -161,7 +173,8 @@
# -h|--help help # -h|--help help
# #
# Environment overrides: # Environment overrides:
# BCMCMD_CMD=bcmcmd TL_UNITS="0 1" TL_TX_COUNT=100 TL_TX_LENGTH=512 # BCMCMD_CMD=bcmcmd TL_UNITS="0 1" TL_TX_COUNT=200 TL_TX_LENGTH=324
# TL_TX_RANDOM=yes
# TL_PS_PORTS="1-24,40-96,..." TL_TOLERANCE=0 TL_LOG_DIR=/tmp # TL_PS_PORTS="1-24,40-96,..." TL_TOLERANCE=0 TL_LOG_DIR=/tmp
# DEBUG_MODE=1 # DEBUG_MODE=1
# #
@@ -173,8 +186,14 @@
# === Config ================================================================== # === Config ==================================================================
BCMCMD_CMD="${BCMCMD_CMD:-bcmcmd}" BCMCMD_CMD="${BCMCMD_CMD:-bcmcmd}"
TL_UNITS="${TL_UNITS:-0 1}" # one DUT = two switch boards (0 and 1) TL_UNITS="${TL_UNITS:-0 1}" # one DUT = two switch boards (0 and 1)
TL_TX_COUNT="${TL_TX_COUNT:-100}" TL_TX_COUNT="${TL_TX_COUNT:-200}"
TL_TX_LENGTH="${TL_TX_LENGTH:-512}" TL_TX_LENGTH="${TL_TX_LENGTH:-324}"
# PatternRandom=yes|no is appended to every tx burst. Random payload exercises
# the SerDes with changing bit patterns instead of the repeating one a fixed
# pattern produces, which is what makes a marginal lane show up.
# Set to "" to leave the argument off entirely (pre-V0.7.0 behaviour).
TL_TX_RANDOM="${TL_TX_RANDOM:-yes}"
TL_DEFAULT_VLAN="${TL_DEFAULT_VLAN:-1}" TL_DEFAULT_VLAN="${TL_DEFAULT_VLAN:-1}"
TL_DEFAULT_VLAN_PBM="${TL_DEFAULT_VLAN_PBM:-cd}" TL_DEFAULT_VLAN_PBM="${TL_DEFAULT_VLAN_PBM:-cd}"
@@ -515,17 +534,23 @@ traffic_linespeed_start() {
_tl_units_check || return 1 _tl_units_check || return 1
_tl_is_uint "$TL_TX_COUNT" || { _tl_err "tx count '$TL_TX_COUNT' is not a positive integer (-tx|-c <n>)"; return 1; } _tl_is_uint "$TL_TX_COUNT" || { _tl_err "tx count '$TL_TX_COUNT' is not a positive integer (-tx|-c <n>)"; return 1; }
_tl_is_uint "$TL_TX_LENGTH" || { _tl_err "tx length '$TL_TX_LENGTH' is not a positive integer (-length|-l <n>)"; return 1; } _tl_is_uint "$TL_TX_LENGTH" || { _tl_err "tx length '$TL_TX_LENGTH' is not a positive integer (-length|-l <n>)"; return 1; }
local rnd=""
case "$TL_TX_RANDOM" in
yes|no) rnd=" PatternRandom=$TL_TX_RANDOM" ;;
"") rnd="" ;;
*) _tl_err "PatternRandom '$TL_TX_RANDOM' must be yes, no or empty (-r|--random)"; return 1 ;;
esac
local unit vid pa pb n fail local unit vid pa pb n fail
for unit in $TL_UNITS; do for unit in $TL_UNITS; do
n=0; fail=0 n=0; fail=0
_tl_info "unit $unit: tx $TL_TX_COUNT length=$TL_TX_LENGTH per VLAN 30..137" _tl_info "unit $unit: tx $TL_TX_COUNT length=$TL_TX_LENGTH${rnd} per VLAN 30..137"
while read -r vid pa pb <&3; do while read -r vid pa pb <&3; do
[ -z "$vid" ] && continue [ -z "$vid" ] && continue
_tl_bcm_q "$unit" "tx $TL_TX_COUNT length=$TL_TX_LENGTH VLantag=$vid" || fail=$((fail+1)) _tl_bcm_q "$unit" "tx $TL_TX_COUNT length=$TL_TX_LENGTH VLantag=$vid${rnd}" || fail=$((fail+1))
n=$((n+1)) n=$((n+1))
done 3<<< "$TL_PAIRS" done 3<<< "$TL_PAIRS"
if [ "$TL_CE_ENABLE" = "1" ]; then if [ "$TL_CE_ENABLE" = "1" ]; then
_tl_bcm_q "$unit" "tx $TL_TX_COUNT length=$TL_TX_LENGTH VLantag=$TL_CE_VLAN" || fail=$((fail+1)) _tl_bcm_q "$unit" "tx $TL_TX_COUNT length=$TL_TX_LENGTH VLantag=$TL_CE_VLAN${rnd}" || fail=$((fail+1))
n=$((n+1)) n=$((n+1))
fi fi
if [ "$fail" -eq 0 ]; then if [ "$fail" -eq 0 ]; then
@@ -949,7 +974,7 @@ traffic_linespeed_run() {
blanton_traffic_linespeed_help() { blanton_traffic_linespeed_help() {
echo -e "\033[1mblanton_traffic_linespeed.sh - SWB loopback line-speed traffic (bcmcmd)\033[0m" echo -e "\033[1mblanton_traffic_linespeed.sh - SWB loopback line-speed traffic (bcmcmd)\033[0m"
echo "" echo ""
echo -e " Units: \033[36m$TL_UNITS\033[0m tx: \033[36m$TL_TX_COUNT pkt x ${TL_TX_LENGTH}B\033[0m" echo -e " Units: \033[36m$TL_UNITS\033[0m tx: \033[36m$TL_TX_COUNT pkt x ${TL_TX_LENGTH}B\033[0m PatternRandom: \033[36m${TL_TX_RANDOM:-(不加)}\033[0m"
echo -e " VLANs: 30..137 ($(_tl_pair_count) loopback pairs, cdN <-> cdN+32)" echo -e " VLANs: 30..137 ($(_tl_pair_count) loopback pairs, cdN <-> cdN+32)"
[ "$TL_CE_ENABLE" = "1" ] && \ [ "$TL_CE_ENABLE" = "1" ] && \
echo -e " 100G : VLAN \033[36m$TL_CE_VLAN\033[0m port \033[36m$TL_CE_PORT\033[0m mode=\033[36m$TL_CE_MODE\033[0m (cross = unit0.$TL_CE_PORT <-> unit1.$TL_CE_PORT cabled)" echo -e " 100G : VLAN \033[36m$TL_CE_VLAN\033[0m port \033[36m$TL_CE_PORT\033[0m mode=\033[36m$TL_CE_MODE\033[0m (cross = unit0.$TL_CE_PORT <-> unit1.$TL_CE_PORT cabled)"
@@ -958,7 +983,7 @@ blanton_traffic_linespeed_help() {
echo -e " \033[33minit\033[0m step 1 vlan remove 1 pbm=cd, vlan create/add each pair" echo -e " \033[33minit\033[0m step 1 vlan remove 1 pbm=cd, vlan create/add each pair"
echo -e " \033[33mclear\033[0m step 2 clear c" echo -e " \033[33mclear\033[0m step 2 clear c"
echo -e " \033[33mshow\033[0m step 3/6 show c (run before and after traffic)" echo -e " \033[33mshow\033[0m step 3/6 show c (run before and after traffic)"
echo -e " \033[33mstart\033[0m step 4 tx <count> length=<len> VLantag=<vid> per VLAN" echo -e " \033[33mstart\033[0m step 4 tx <count> length=<len> VLantag=<vid> [PatternRandom=<yes|no>] per VLAN"
echo -e " \033[33mstop\033[0m step 5 vlan remove <vid> pbm=<pair> [--destroy also destroys]" echo -e " \033[33mstop\033[0m step 5 vlan remove <vid> pbm=<pair> [--destroy also destroys]"
[ "$TL_CE_ENABLE" = "1" ] && [ "$TL_CE_MIRROR" = "1" ] && \ [ "$TL_CE_ENABLE" = "1" ] && [ "$TL_CE_MIRROR" = "1" ] && \
echo -e " \033[33m^ also turns the $TL_CE_PORT mirror off -- without it the 100G loop keeps running\033[0m" echo -e " \033[33m^ also turns the $TL_CE_PORT mirror off -- without it the 100G loop keeps running\033[0m"
@@ -972,6 +997,7 @@ blanton_traffic_linespeed_help() {
echo -e " \033[33m-u|--unit\033[0m <0|1|all> bcmcmd unit(s); 'all' = 0 1 (default: $TL_UNITS)" echo -e " \033[33m-u|--unit\033[0m <0|1|all> bcmcmd unit(s); 'all' = 0 1 (default: $TL_UNITS)"
echo -e " \033[33m-c|--count|-tx\033[0m <n> tx packet count (default $TL_TX_COUNT)" echo -e " \033[33m-c|--count|-tx\033[0m <n> tx packet count (default $TL_TX_COUNT)"
echo -e " \033[33m-l|--length|-length\033[0m <n> tx packet length (default $TL_TX_LENGTH)" echo -e " \033[33m-l|--length|-length\033[0m <n> tx packet length (default $TL_TX_LENGTH)"
echo -e " \033[33m-r|--random\033[0m <yes|no> tx PatternRandom (default $TL_TX_RANDOM; \"\" 完全不加)"
echo -e " \033[33m-p|--ports\033[0m <list> ps port list, or 'all' for every port" echo -e " \033[33m-p|--ports\033[0m <list> ps port list, or 'all' for every port"
echo -e " \033[33m-T|--tolerance\033[0m <n> report: allowed |delta| pkts (default $TL_TOLERANCE; -T 1 = snapshot skew)" echo -e " \033[33m-T|--tolerance\033[0m <n> report: allowed |delta| pkts (default $TL_TOLERANCE; -T 1 = snapshot skew)"
echo -e " \033[33m-a|--all\033[0m report: kept for compatibility (all pairs are listed)" echo -e " \033[33m-a|--all\033[0m report: kept for compatibility (all pairs are listed)"
@@ -995,7 +1021,8 @@ blanton_traffic_linespeed_help() {
echo -e " blanton_traffic_linespeed report -u 1 -q | grep -v PASS" echo -e " blanton_traffic_linespeed report -u 1 -q | grep -v PASS"
echo -e " blanton_traffic_linespeed report -f /tmp/showc_unit1_*.log -a" echo -e " blanton_traffic_linespeed report -f /tmp/showc_unit1_*.log -a"
echo -e " blanton_traffic_linespeed show -u 1 | grep -iE 'error|discard|drop'" echo -e " blanton_traffic_linespeed show -u 1 | grep -iE 'error|discard|drop'"
echo -e " blanton_traffic_linespeed start -u 0 -tx 100 -length 512" echo -e " blanton_traffic_linespeed start -u 0 -tx 200 -length 324"
echo -e " blanton_traffic_linespeed start -r no # 固定樣式,不隨機"
echo -e " blanton_traffic_linespeed start -tx 100000 -length 9216 -d" echo -e " blanton_traffic_linespeed start -tx 100000 -length 9216 -d"
echo -e " blanton_traffic_linespeed stop --destroy" echo -e " blanton_traffic_linespeed stop --destroy"
echo "" echo ""
@@ -1019,6 +1046,7 @@ blanton_traffic_linespeed() {
shift 2 ;; shift 2 ;;
-c|--count|-tx|--tx) TL_TX_COUNT="$2"; shift 2 ;; -c|--count|-tx|--tx) TL_TX_COUNT="$2"; shift 2 ;;
-l|-length|--length|--len) TL_TX_LENGTH="$2"; shift 2 ;; -l|-length|--length|--len) TL_TX_LENGTH="$2"; shift 2 ;;
-r|--random|-PatternRandom|--pattern-random) TL_TX_RANDOM="$2"; shift 2 ;;
-p|--ports) TL_PS_PORTS="$2"; shift 2 ;; -p|--ports) TL_PS_PORTS="$2"; shift 2 ;;
-T|--tolerance) TL_TOLERANCE="$2"; shift 2 ;; -T|--tolerance) TL_TOLERANCE="$2"; shift 2 ;;
-f|--file) TL_REPORT_FILE="$2"; shift 2 ;; -f|--file) TL_REPORT_FILE="$2"; shift 2 ;;
@@ -0,0 +1,241 @@
#!/usr/bin/env bash
# =============================================================================
# pwr_brick.sh -- PDB / CPB power brick Vin / Iin / Vout / Iout / Temp
# =============================================================================
# Version History:
# V1.1.0 2026-09-02 PAGE values and conversions taken from the ADPM12200
# datasheet instead of the bring-up spreadsheet.
# The spreadsheet wrote every PAGE in decimal but with an
# 0x prefix, so four of the five selected the wrong page:
# Vin PAGE 9 -> it said 0x00 (should be 0x09)
# Iin PAGE 10 -> it said 0x10 (should be 0x0A)
# Vout PAGE 2 -> it said 0x02 correct by luck
# Iout PAGE 14 -> it said 0x14 (should be 0x0E)
# Temp PAGE 18 -> it said 0x18 (should be 0x12)
# Only Vout worked, because 2 reads the same either way.
# That is why Iin/Iout answered 0xFFFF and Temp 0x0000.
# Conversions now use the datasheet DIRECT equation; the
# reverse-engineered BRICK_VIN_LSB is gone.
# V1.0.0 2026-09-02 First version.
# =============================================================================
#
# Path: CB FPGA F3 VI2C ch4 -> TCA954x mux 0x72 ch0 -> the bricks
#
# The four ADPM12200 modules put each measurement on its own PMBus PAGE, so a
# PAGE write has to precede every read. blanton_pwr_data.sh does not send one
# at all (its PDB table has page "-"), which is why it reports them as NA.
#
# READ_VIN 0x88 PAGE 9
# READ_IIN 0x89 PAGE 10
# READ_VOUT 0x8B PAGE 2
# READ_IOUT 0x8C PAGE 14
# READ_TEMPERATURE_1 0x8D PAGE 18
#
# DIRECT format, datasheet Table 3 ("PMBus Command Code Coefficients"):
#
# X = (1/m) x (Y x 10^-R - b) Y = the 2-byte two's complement word
#
# Voltage m=0.125 b=0 R=0 units mV -> X = Y x 8 mV
# Current m=0.25 b=0 R=2 units A -> X = Y x 0.04 A
# Temperature m=1 b=0 R=2 units degC -> X = Y x 0.01 degC
#
# Sanity check: READ_VOUT 0x05D4 = 1492 -> 1492 x 8 = 11936 mV, which is exactly
# what PDB_IBC_SWB1_A_VOUT reports in 'show platform voltage'.
#
# ⚠️ Table 3 does not list READ_VIN or READ_IIN. They are decoded here with the
# Voltage and Current coefficients respectively - reasonable, and consistent
# with a ~50 V input, but not stated by the datasheet. PB_VIN_M / PB_IIN_M
# below are where to change that if the part turns out to differ.
#
# ⚠️ CPB.PU37 (0x26) is a DIFFERENT part: no PAGE writes, and its own scaling
# (Vin 0.25 V, Vout 2^-11 V, Iout 0.5 A per count of the mantissa). Those
# three were confirmed against words this DUT returns.
#
# Usage:
# ./pwr_brick.sh show # the table
# ./pwr_brick.sh show -r # add the raw words
# ./pwr_brick.sh help
# =============================================================================
# --- User Configurable Section ----------------------------------------------
PB_CH="${PB_CH:-4}" # ICB VI2C channel
PB_MUX="${PB_MUX:-0x72}" # TCA954x address
PB_MUX_SEL="${PB_MUX_SEL:-0x01}" # control byte: bit0 = channel 0
PB_TRIES="${PB_TRIES:-8}" # reads per value before giving up
# PMBus PAGE per measurement (ADPM12200). Decimal page numbers written in hex.
PB_PAGE_VIN="${PB_PAGE_VIN:-0x09}" # 9
PB_PAGE_IIN="${PB_PAGE_IIN:-0x0A}" # 10
PB_PAGE_VOUT="${PB_PAGE_VOUT:-0x02}" # 2
PB_PAGE_IOUT="${PB_PAGE_IOUT:-0x0E}" # 14
PB_PAGE_TEMP="${PB_PAGE_TEMP:-0x12}" # 18
# DIRECT coefficients: m, R, and the divisor that takes the datasheet unit to
# the displayed unit (mV -> V is 1000; A and degC are already right).
PB_VOUT_M="${PB_VOUT_M:-0.125}"; PB_VOUT_R="${PB_VOUT_R:-0}"; PB_VOUT_DIV="${PB_VOUT_DIV:-1000}"
PB_VIN_M="${PB_VIN_M:-0.125}"; PB_VIN_R="${PB_VIN_R:-0}"; PB_VIN_DIV="${PB_VIN_DIV:-1000}"
PB_IOUT_M="${PB_IOUT_M:-0.25}"; PB_IOUT_R="${PB_IOUT_R:-2}"; PB_IOUT_DIV="${PB_IOUT_DIV:-1}"
PB_IIN_M="${PB_IIN_M:-0.25}"; PB_IIN_R="${PB_IIN_R:-2}"; PB_IIN_DIV="${PB_IIN_DIV:-1}"
PB_TEMP_M="${PB_TEMP_M:-1}"; PB_TEMP_R="${PB_TEMP_R:-2}"; PB_TEMP_DIV="${PB_TEMP_DIV:-1}"
# CPB.PU37 only (different part, no PAGE, mantissa-based)
CPB_VIN_LSB="${CPB_VIN_LSB:-0.25}" # V per count of the mantissa
CPB_IOUT_LSB="${CPB_IOUT_LSB:-0.5}" # A per count of the mantissa
# Plausibility windows. A decoded value outside its window is discarded and the
# read retried; this is what rejects the corrupted words this bus produces - a
# bad high byte turns 11.98 V into 32.00 V, which "reject 0xFFFF" never catches.
PB_VIN_LO="${PB_VIN_LO:-30}"; PB_VIN_HI="${PB_VIN_HI:-70}"
PB_VOUT_LO="${PB_VOUT_LO:-8}"; PB_VOUT_HI="${PB_VOUT_HI:-14}"
PB_IIN_LO="${PB_IIN_LO:-0}"; PB_IIN_HI="${PB_IIN_HI:-100}"
PB_IOUT_LO="${PB_IOUT_LO:-0}"; PB_IOUT_HI="${PB_IOUT_HI:-300}"
PB_TEMP_LO="${PB_TEMP_LO:-0}"; PB_TEMP_HI="${PB_TEMP_HI:-125}"
# All-ones and all-zeros are the two ways this bus says "nobody answered", and
# both can decode into a value that sits inside its window - 0x0000 on the
# temperature register reads as a perfectly plausible 0 C. Rejected as raw
# words, before any conversion, so no window has to be bent to catch them.
PB_REJECT_FFFF="${PB_REJECT_FFFF:-1}"
PB_REJECT_0000="${PB_REJECT_0000:-1}"
# "location:bricks:slave:netname:kind" kind = adpm (PAGE per read) | cpb
PB_DEVS=(
"SWB0.PU207:BRICKS1:0x62:P12V_SWB0_L:adpm"
"SWB0.PU13:BRICKS2:0x63:P12V_SWB0_L:adpm"
"SWB1.PU332:BRICKS1:0x60:P12V_SWB1_R:adpm"
"SWB1.PU85:BRICKS2:0x61:P12V_SWB1_R:adpm"
"CPB.PU37:BRICK:0x26:P12V_STBY:cpb"
)
# -----------------------------------------------------------------------------
PB_NA="NA"
PB_RAW=0
PB_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" 2>/dev/null && pwd)"
_pb_err() { echo -e "[\033[31mERR \033[0m] $*" >&2; }
# --- backend -----------------------------------------------------------------
if ! declare -F vi2c_read >/dev/null 2>&1; then
if [ -r "$PB_DIR/blanton_icb_vi2c.sh" ]; then
# shellcheck source=/dev/null
source "$PB_DIR/blanton_icb_vi2c.sh" >/dev/null 2>&1
else
_pb_err "blanton_icb_vi2c.sh not found next to this script"; exit 1
fi
fi
declare -F vi2c_read >/dev/null 2>&1 || { _pb_err "vi2c_read() still undefined"; exit 1; }
# --- decoders ----------------------------------------------------------------
# DIRECT: X = (1/m) x (Y x 10^-R - b), b = 0. Y is two's complement, so a word
# above 0x7FFF is negative - that matters for temperature, not for the rails.
_pb_direct() {
awk -v w=$(( $1 )) -v m="$2" -v r="$3" -v d="$4" 'BEGIN{
if (w > 32767) w -= 65536
printf "%.3f", ((w * (10 ^ -r)) / m) / d
}'
}
# SLINEAR11 mantissa only (bits[10:0], two's complement) - CPB.PU37 path.
_pb_mant() { awk -v w=$(( $1 )) 'BEGIN{ m = w % 2048; if (m > 1023) m -= 2048; print m }'; }
_pb_mul() { awk -v a="$1" -v b="$2" 'BEGIN{ printf "%.3f", a * b }'; }
_pb_lin11() { awk -v w=$(( $1 )) 'BEGIN{ printf "%.4f", w * (2.0 ^ -11) }'; }
_pb_in() { awk -v x="$1" -v lo="$2" -v hi="$3" 'BEGIN{ exit !(x >= lo && x <= hi) }'; }
# _pb_word <slave> <page|-> <reg> -> "0xWWWW"
_pb_word() {
local slave="$1" page="$2" reg="$3" out
[ "$page" != "-" ] && vi2c_write "$PB_CH" "$slave" 0x00 "$page" >/dev/null 2>&1
out=$(vi2c_read "$PB_CH" "$slave" "$reg" 2 2>/dev/null \
| sed -n 's/.*\[0x\(..\) 0x\(..\)\].*/0x\2\1/p')
[ -n "$out" ] && echo "$out"
}
# _pb_val <slave> <page|-> <reg> <decoder> <a1> <a2> <a3> <lo> <hi>
# Retries until the decoded value lands inside the window; echoes "value raw".
_pb_val() {
local slave="$1" page="$2" reg="$3" dec="$4" a1="$5" a2="$6" a3="$7" lo="$8" hi="$9"
local i w v
for (( i = 0; i < PB_TRIES; i++ )); do
w=$(_pb_word "$slave" "$page" "$reg") || continue
[ -z "$w" ] && continue
[ "$PB_REJECT_FFFF" = "1" ] && [ "$(( w ))" -eq 65535 ] && continue
[ "$PB_REJECT_0000" = "1" ] && [ "$(( w ))" -eq 0 ] && continue
case "$dec" in
direct) v=$(_pb_direct "$w" "$a1" "$a2" "$a3") ;;
mant) v=$(_pb_mul "$(_pb_mant "$w")" "$a1") ;;
lin11) v=$(_pb_lin11 "$w") ;;
esac
_pb_in "$v" "$lo" "$hi" || continue
echo "$v $w"; return 0
done
echo "$PB_NA -"; return 1
}
_pb_mux_open() {
# The mux takes a bare control byte and vi2c_write always sends a register
# first, so passing 0x01 as both makes the part latch 0x01 either way.
vi2c_init "$PB_CH" >/dev/null 2>&1
vi2c_write "$PB_CH" "$PB_MUX" "$PB_MUX_SEL" "$PB_MUX_SEL" >/dev/null 2>&1
return 0
}
# --- show --------------------------------------------------------------------
pwr_brick_show() {
_pb_mux_open
echo "==== PDB / CPB power bricks (VI2C ch${PB_CH} -> mux ${PB_MUX} ch0) ===="
printf '%-3s %-12s %-8s %-7s %-14s %10s %10s %10s %10s %9s\n' \
"No." "Location" "Bricks" "SlaveID" "Netname" \
"Vin(V)" "Iin(A)" "Vout(V)" "Iout(A)" "Temp(C)"
printf '%s\n' "--------------------------------------------------------------------------------------------------------------"
local n=0 entry loc bk slave net kind vi ii vo io tp
for entry in "${PB_DEVS[@]}"; do
IFS=':' read -r loc bk slave net kind <<< "$entry"
n=$(( n + 1 ))
if [ "$kind" = "cpb" ]; then
vi=$(_pb_val "$slave" - 0x88 mant "$CPB_VIN_LSB" "" "" "$PB_VIN_LO" "$PB_VIN_HI")
ii="$PB_NA -" # no input current on this part
vo=$(_pb_val "$slave" - 0x8B lin11 "" "" "" "$PB_VOUT_LO" "$PB_VOUT_HI")
io=$(_pb_val "$slave" - 0x8C mant "$CPB_IOUT_LSB" "" "" "$PB_IOUT_LO" "$PB_IOUT_HI")
tp=$(_pb_val "$slave" - 0x8D direct 1 2 1 "$PB_TEMP_LO" "$PB_TEMP_HI")
else
vi=$(_pb_val "$slave" "$PB_PAGE_VIN" 0x88 direct "$PB_VIN_M" "$PB_VIN_R" "$PB_VIN_DIV" "$PB_VIN_LO" "$PB_VIN_HI")
ii=$(_pb_val "$slave" "$PB_PAGE_IIN" 0x89 direct "$PB_IIN_M" "$PB_IIN_R" "$PB_IIN_DIV" "$PB_IIN_LO" "$PB_IIN_HI")
vo=$(_pb_val "$slave" "$PB_PAGE_VOUT" 0x8B direct "$PB_VOUT_M" "$PB_VOUT_R" "$PB_VOUT_DIV" "$PB_VOUT_LO" "$PB_VOUT_HI")
io=$(_pb_val "$slave" "$PB_PAGE_IOUT" 0x8C direct "$PB_IOUT_M" "$PB_IOUT_R" "$PB_IOUT_DIV" "$PB_IOUT_LO" "$PB_IOUT_HI")
tp=$(_pb_val "$slave" "$PB_PAGE_TEMP" 0x8D direct "$PB_TEMP_M" "$PB_TEMP_R" "$PB_TEMP_DIV" "$PB_TEMP_LO" "$PB_TEMP_HI")
fi
printf '%-3s %-12s %-8s %-7s %-14s %10s %10s %10s %10s %9s\n' \
"$n" "$loc" "$bk" "$slave" "$net" \
"${vi%% *}" "${ii%% *}" "${vo%% *}" "${io%% *}" "${tp%% *}"
[ "$PB_RAW" = "1" ] && printf '%-3s %-12s %-8s %-7s %-14s %10s %10s %10s %10s %9s\n' \
"" "" "" "" "raw" "${vi##* }" "${ii##* }" "${vo##* }" "${io##* }" "${tp##* }"
done
# No trailing notes on stdout: this table gets pasted into reports and
# captured into the master console log, and a caveat printed every run stops
# being read after the second time. The caveats live in the file header -
# the one that still matters is that READ_VIN / READ_IIN are not in the
# datasheet coefficient table and borrow the Voltage / Current sets.
}
pwr_brick_help() {
echo -e "\033[1mpwr_brick.sh - PDB / CPB power brick readings\033[0m"
echo ""
echo -e " \033[33mshow\033[0m [-r] Vin / Iin / Vout / Iout / Temp for all 5 bricks (-r adds raw)"
echo -e " \033[33mhelp\033[0m"
echo ""
echo -e " Path : VI2C ch$PB_CH -> mux $PB_MUX ch0"
echo -e " The four ADPM12200 modules need a PMBus PAGE per measurement:"
echo -e " Vin $PB_PAGE_VIN(9) Iin $PB_PAGE_IIN(10) Vout $PB_PAGE_VOUT(2) Iout $PB_PAGE_IOUT(14) Temp $PB_PAGE_TEMP(18)"
echo -e " DIRECT format, datasheet Table 3: X = (1/m) x (Y x 10^-R - b)"
echo -e " CPB.PU37 (0x26) is a different part - no PAGE, its own scaling."
echo -e " \033[33mREAD_VIN / READ_IIN are not in Table 3; they borrow Voltage / Current.\033[0m"
}
case "${1:-help}" in
show)
shift 2>/dev/null
[ "${1:-}" = "-r" ] && PB_RAW=1
pwr_brick_show ;;
help|-h|--help) pwr_brick_help ;;
*) _pb_err "unknown sub-command: $1"; pwr_brick_help; exit 1 ;;
esac
+21
View File
@@ -5,7 +5,10 @@ project_name = "Blanton"
strTestcase="ENV" ;ENV,EMC,Margin...etc strTestcase="ENV" ;ENV,EMC,Margin...etc
EN_Margin = 0 ; 1: Enable Margin Test, 0: Disable Margin Test EN_Margin = 0 ; 1: Enable Margin Test, 0: Disable Margin Test
EN_TX_FIR = 0 ; 1: Enable bcm_dsc_scan.sh collect port TX_FIR, 0: Disable (saves ~20 min: ScriptA and ScriptC each scan for ~10 min)
EN_log = 1 ; 1: Enable log, 0: Disable log EN_log = 1 ; 1: Enable log, 0: Disable log
EN_timestamp = 1 ; 1: Enable timestamp in log, 0: Disable timestamp in log
;================================================================ ;================================================================
; FAN_SPEED ; FAN_SPEED
@@ -17,9 +20,27 @@ FAN_SPEED = 100
SWB_UNIT0 = 1 ; 1 = this DUT has switch unit 0, wait for it ; 0 = skip SWB_UNIT0 = 1 ; 1 = this DUT has switch unit 0, wait for it ; 0 = skip
SWB_UNIT1 = 1 ; 1 = this DUT has switch unit 1, wait for it ; 0 = skip SWB_UNIT1 = 1 ; 1 = this DUT has switch unit 1, wait for it ; 0 = skip
;================================================================
; Stress_Test
;================================================================
SSD_RUNTIME = 3600 ; Unit seconds, 3600 = 1 hour
SSD_COUNT = 240 ; Total time = SSD_RUNTIME * SSD_COUNT
USB_RUNTIME = 3600 ; Unit seconds, 3600 = 1 hour
USB_COUNT = 240 ; Total time = USB_RUNTIME * USB_COUNT
BMC_USB_RUNTIME = 172800 ; Unit seconds, 172800 = 2 days
;================================================================ ;================================================================
; Prompt Definitions ; Prompt Definitions
;================================================================ ;================================================================
prompt_login = "sonic login:" prompt_login = "sonic login:"
prompt_sonic = "admin@sonic:~$" prompt_sonic = "admin@sonic:~$"
prompt_sonic_root = "root@sonic:~#" prompt_sonic_root = "root@sonic:~#"
;================================================================
; Reboot or Power Cycle
;================================================================
; 0: Normal Test
; 1: Enable Reboot Cycle
; 2: Enable Power Cycle
EN_Cold_Warm_boot = 0
+90
View File
@@ -0,0 +1,90 @@
cd /usr/sbin
sudo docker pause gbsyncd1
sudo docker pause gbsyncd0
sudo /usr/sbin/blanton_barchetta_tool --serdes-tx-get sys 0
//Tuning
sudo /usr/sbin/blanton_barchetta_tool --serdes-tx-set sys 0 pre=-10 main=87 post=0
sudo /usr/sbin/blanton_barchetta_tool --serdes-tx-set sys 1 pre=-10 main=87 post=0
sudo /usr/sbin/blanton_barchetta_tool --serdes-tx-set sys 2 pre=-10 main=87 post=0
sudo /usr/sbin/blanton_barchetta_tool --serdes-tx-set sys 3 pre=-10 main=87 post=0
sudo /usr/sbin/blanton_barchetta_tool --serdes-tx-set sys 4 pre=-10 main=87 post=0
sudo /usr/sbin/blanton_barchetta_tool --serdes-tx-set sys 5 pre=-10 main=87 post=0
sudo /usr/sbin/blanton_barchetta_tool --serdes-tx-set sys 6 pre=-10 main=87 post=0
sudo /usr/sbin/blanton_barchetta_tool --serdes-tx-set sys 7 pre=-10 main=87 post=0
bcmcmd -n 0 -c " dsh -c 'phydiag 268 tx_taps set lane=0 main=31 pre1=4 post1=13' "
bcmcmd -n 0 -c " dsh -c 'phydiag 268 tx_taps set lane=1 main=31 pre1=4 post1=13' "
bcmcmd -n 0 -c " dsh -c 'phydiag 268 tx_taps set lane=2 main=27 pre1=4 post1=13' "
bcmcmd -n 0 -c " dsh -c 'phydiag 268 tx_taps set lane=3 main=29 pre1=4 post1=13' "
bcmcmd -n 1 -c " dsh -c 'phydiag 268 tx_taps set lane=0 main=29 pre1=4 post1=13' "
bcmcmd -n 1 -c " dsh -c 'phydiag 268 tx_taps set lane=1 main=30 pre1=4 post1=13' "
bcmcmd -n 1 -c " dsh -c 'phydiag 268 tx_taps set lane=2 main=31 pre1=4 post1=13' "
bcmcmd -n 1 -c " dsh -c 'phydiag 268 tx_taps set lane=3 main=30 pre1=4 post1=13' "
以下Test Cycle 目標200次
//Disable Port
bcmcmd -n 0 -c "port 268 en=0"
bcmcmd -n 1 -c "port 268 en=0"
//Wait Link Down
bcmcmd -n 0 -c "ps 268"
bcmcmd -n 1 -c "ps 268"
root@sonic:~# bcmcmd -n 0 -c "ps 268"
ps 268
ena/ speed/ link auto STP lrn max cut loop
port link Lns duplex scan neg? state pause discrd ops medium frame thru FEC back
ce0(268) !ena 4 100G FD SW No Forward Untag FA Backplane 9122 No RS528
drivshell>
root@sonic:~# bcmcmd -n 1 -c "ps 268"
ps 268
ena/ speed/ link auto STP lrn max cut loop
port link Lns duplex scan neg? state pause discrd ops medium frame thru FEC back
ce0(268) !ena 4 100G FD SW No Forward Untag FA Backplane 9122 No RS528
drivshell>
root@sonic:~#
//Enable Port
bcmcmd -n 0 -c "port 268 en=1"
bcmcmd -n 1 -c "port 268 en=1"
//Wait Link Up
bcmcmd -n 0 -c "ps 268"
bcmcmd -n 1 -c "ps 268"
root@sonic:~# bcmcmd -n 0 -c "ps 268"
ps 268
ena/ speed/ link auto STP lrn max cut loop
port link Lns duplex scan neg? state pause discrd ops medium frame thru FEC back
ce0(268) up 4 100G FD SW No Forward Untag FA Backplane 9122 No RS528
drivshell>
root@sonic:~# bcmcmd -n 1 -c "ps 268"
ps 268
ena/ speed/ link auto STP lrn max cut loop
port link Lns duplex scan neg? state pause discrd ops medium frame thru FEC back
ce0(268) up 4 100G FD SW No Forward Untag FA Backplane 9122 No RS528
drivshell>
root@sonic:~#
//Collect DSC Data
bcmcmd -n 0 -c "dsh -c 'phydiag 268 dsc'"
bcmcmd -n 1 -c "dsh -c 'phydiag 268 dsc'"
//讀Retimer TX/RX
sudo /usr/sbin/blanton_barchetta_tool --serdes-tx-get sys 0
sudo /usr/sbin/blanton_barchetta_tool --serdes-tx-get sys 1
sudo /usr/sbin/blanton_barchetta_tool --serdes-tx-get sys 2
sudo /usr/sbin/blanton_barchetta_tool --serdes-tx-get sys 3
sudo /usr/sbin/blanton_barchetta_tool --serdes-tx-get sys 4
sudo /usr/sbin/blanton_barchetta_tool --serdes-tx-get sys 5
sudo /usr/sbin/blanton_barchetta_tool --serdes-tx-get sys 6
sudo /usr/sbin/blanton_barchetta_tool --serdes-tx-get sys 7
sudo /usr/sbin/blanton_barchetta_tool --serdes-rx-get sys 0
sudo /usr/sbin/blanton_barchetta_tool --serdes-rx-get sys 1
sudo /usr/sbin/blanton_barchetta_tool --serdes-rx-get sys 2
sudo /usr/sbin/blanton_barchetta_tool --serdes-rx-get sys 3
sudo /usr/sbin/blanton_barchetta_tool --serdes-rx-get sys 4
sudo /usr/sbin/blanton_barchetta_tool --serdes-rx-get sys 5
sudo /usr/sbin/blanton_barchetta_tool --serdes-rx-get sys 6
sudo /usr/sbin/blanton_barchetta_tool --serdes-rx-get sys 7
+40
View File
@@ -0,0 +1,40 @@
SWB0_0V9_ANLG0
SWB0_0V9_ANLG1
SWB0_0V75_ANLG0
SWB0_0V75_ANLG1
SWB0_PHYTILE_P0
SWB0_PHYTILE_P1
SWB0_PHYTILE_P2
SWB0_PHYTILE_P3
SWB0_PHYTILE_P4
SWB0_PHYTILE_P5
SWB0_PHYTILE_P6
SWB0_PHYTILE_P7
SWB0_PVDD1V5_CNDR0
SWB0_PVDD1V5_CNDR1
SWB0_PVDDA_PHYT0
SWB0_PVDDA_PHYT1
SWB0_PVDDA_PHYT2
SWB0_PVDDA_PHYT3
SWB0_TH6_CORE
SWB1_0V9_ANLG0
SWB1_0V9_ANLG1
SWB1_0V75_ANLG0
SWB1_0V75_ANLG1
SWB1_PHYTILE_P0
SWB1_PHYTILE_P1
SWB1_PHYTILE_P2
SWB1_PHYTILE_P3
SWB1_PHYTILE_P4
SWB1_PHYTILE_P5
SWB1_PHYTILE_P6
SWB1_PHYTILE_P7
SWB1_PVDD1V5_CNDR0
SWB1_PVDD1V5_CNDR1
SWB1_PVDDA_PHYT0
SWB1_PVDDA_PHYT1
SWB1_PVDDA_PHYT2
SWB1_PVDDA_PHYT3
SWB1_TH6_CORE
+188
View File
@@ -0,0 +1,188 @@
//0.900V (nominal)
i2cset -f -y 13 0x25 0x00 0
i2ctransfer -f -y 13 w3@0x25 0x21 0x83 0x00
i2cset -f -y 13 0x25 0x00 2
i2ctransfer -f -y 13 w3@0x25 0x0D 0x74 0x10
//0.900V (nominal)
i2cset -f -y 15 0x26 0x00 0
i2ctransfer -f -y 15 w3@0x26 0x21 0x83 0x00
i2cset -f -y 15 0x26 0x00 2
i2ctransfer -f -y 15 w3@0x26 0x0D 0x74 0x10
//0.75V (nominal)
i2cset -f -y 13 0x25 0x00 1
i2ctransfer -f -y 13 w3@0x25 0x21 0x65 0x00
i2cset -f -y 13 0x25 0x00 2
i2ctransfer -f -y 13 w3@0x25 0x1D 0x5A 0x06
//0.75V (nominal)
i2cset -f -y 15 0x26 0x00 1
i2ctransfer -f -y 15 w3@0x26 0x21 0x65 0x00
i2cset -f -y 15 0x26 0x00 2
i2ctransfer -f -y 15 w3@0x26 0x1D 0x5A 0x06
//0.75V (nominal)
i2cset -f -y 13 0x21 0x00 0
i2ctransfer -f -y 13 w3@0x21 0x21 0x65 0x00
i2cset -f -y 13 0x21 0x00 2
i2ctransfer -f -y 13 w3@0x21 0x0D 0xB2 0x0C
//0.75V (nominal)
i2cset -f -y 13 0x21 0x00 1
i2ctransfer -f -y 13 w3@0x21 0x21 0x65 0x00
i2cset -f -y 13 0x21 0x00 2
i2ctransfer -f -y 13 w3@0x21 0x1D 0x5A 0x06
//0.75V (nominal)
i2cset -f -y 13 0x22 0x00 0
i2ctransfer -f -y 13 w3@0x22 0x21 0x65 0x00
i2cset -f -y 13 0x22 0x00 2
i2ctransfer -f -y 13 w3@0x22 0x0D 0xB2 0x0C
//0.75V (nominal)
i2cset -f -y 13 0x22 0x00 1
i2ctransfer -f -y 13 w3@0x22 0x21 0x65 0x00
i2cset -f -y 13 0x22 0x00 2
i2ctransfer -f -y 13 w3@0x22 0x1D 0x5A 0x06
//0.75V (nominal)
i2cset -f -y 15 0x23 0x00 0
i2ctransfer -f -y 15 w3@0x23 0x21 0x65 0x00
i2cset -f -y 15 0x23 0x00 2
i2ctransfer -f -y 15 w3@0x23 0x0D 0xB2 0x0C
//0.75V (nominal)
i2cset -f -y 15 0x23 0x00 1
i2ctransfer -f -y 15 w3@0x23 0x21 0x65 0x00
i2cset -f -y 15 0x23 0x00 2
i2ctransfer -f -y 15 w3@0x23 0x1D 0x5A 0x06
//0.75V (nominal)
i2cset -f -y 15 0x24 0x00 0
i2ctransfer -f -y 15 w3@0x24 0x21 0x65 0x00
i2cset -f -y 15 0x24 0x00 2
i2ctransfer -f -y 15 w3@0x24 0x0D 0xB2 0x0C
//0.75V (nominal)
i2cset -f -y 15 0x24 0x00 1
i2ctransfer -f -y 15 w3@0x24 0x21 0x65 0x00
i2cset -f -y 15 0x24 0x00 2
i2ctransfer -f -y 15 w3@0x24 0x1D 0x5A 0x06
//1.5V (nominal)
i2cset -f -y 13 0x29 0x00 0
i2ctransfer -f -y 13 w3@0x29 0x21 0xFB 0x00
i2cset -f -y 13 0x29 0x00 2
i2ctransfer -f -y 13 w3@0x29 0x0D 0x71 0x1F
//1.5V (nominal)
i2cset -f -y 13 0x29 0x00 1
i2ctransfer -f -y 13 w3@0x29 0x21 0xFB 0x00
i2cset -f -y 13 0x29 0x00 2
i2ctransfer -f -y 13 w3@0x29 0x1D 0xB9 0x0F
//0.720V
i2cset -f -y 13 0x27 0x00 0
i2ctransfer -f -y 13 w3@0x27 0x21 0x5F 0x00
i2cset -f -y 13 0x27 0x00 2
i2ctransfer -f -y 13 w3@0x27 0x0D 0xF4 0x0B
//0.720V
i2cset -f -y 13 0x27 0x00 1
i2ctransfer -f -y 13 w3@0x27 0x21 0x5F 0x00
i2cset -f -y 13 0x27 0x00 2
i2ctransfer -f -y 13 w3@0x27 0x1D 0xFC 0x05
//0.720V
i2cset -f -y 15 0x28 0x00 0
i2ctransfer -f -y 15 w3@0x28 0x21 0x5F 0x00
i2cset -f -y 15 0x28 0x00 2
i2ctransfer -f -y 15 w3@0x28 0x0D 0xF4 0x0B
//0.720V
i2cset -f -y 15 0x28 0x00 1
i2ctransfer -f -y 15 w3@0x28 0x21 0x5F 0x00
i2cset -f -y 15 0x28 0x00 2
i2ctransfer -f -y 15 w3@0x28 0x1D 0xFC 0x05
//0.8V(nominal) , 0.8591V with load line
i2cset -f -y 13 0x20 0x00 0
i2ctransfer -f -y 13 w3@0x20 0x21 0x57 0x01
//0.900V (nominal)
i2cset -f -y 14 0x25 0x00 0
i2ctransfer -f -y 14 w3@0x25 0x21 0x83 0x00
i2cset -f -y 14 0x25 0x00 2
i2ctransfer -f -y 14 w3@0x25 0x0D 0x74 0x10
//0.900V (nominal)
i2cset -f -y 16 0x26 0x00 0
i2ctransfer -f -y 16 w3@0x26 0x21 0x83 0x00
i2cset -f -y 16 0x26 0x00 2
i2ctransfer -f -y 16 w3@0x26 0x0D 0x74 0x10
//0.75V (nominal)
i2cset -f -y 14 0x25 0x00 1
i2ctransfer -f -y 14 w3@0x25 0x21 0x65 0x00
i2cset -f -y 14 0x25 0x00 2
i2ctransfer -f -y 14 w3@0x25 0x1D 0x5A 0x06
//0.75V (nominal)
i2cset -f -y 16 0x26 0x00 1
i2ctransfer -f -y 16 w3@0x26 0x21 0x65 0x00
i2cset -f -y 16 0x26 0x00 2
i2ctransfer -f -y 16 w3@0x26 0x1D 0x5A 0x06
//0.75V (nominal)
i2cset -f -y 14 0x21 0x00 0
i2ctransfer -f -y 14 w3@0x21 0x21 0x65 0x00
i2cset -f -y 14 0x21 0x00 2
i2ctransfer -f -y 14 w3@0x21 0x0D 0xB2 0x0C
//0.75V (nominal)
i2cset -f -y 14 0x21 0x00 1
i2ctransfer -f -y 14 w3@0x21 0x21 0x65 0x00
i2cset -f -y 14 0x21 0x00 2
i2ctransfer -f -y 14 w3@0x21 0x1D 0x5A 0x06
//0.75V (nominal)
i2cset -f -y 14 0x22 0x00 0
i2ctransfer -f -y 14 w3@0x22 0x21 0x65 0x00
i2cset -f -y 14 0x22 0x00 2
i2ctransfer -f -y 14 w3@0x22 0x0D 0xB2 0x0C
//0.75V (nominal)
i2cset -f -y 14 0x22 0x00 1
i2ctransfer -f -y 14 w3@0x22 0x21 0x65 0x00
i2cset -f -y 14 0x22 0x00 2
i2ctransfer -f -y 14 w3@0x22 0x1D 0x5A 0x06
//0.75V (nominal)
i2cset -f -y 16 0x23 0x00 0
i2ctransfer -f -y 16 w3@0x23 0x21 0x65 0x00
i2cset -f -y 16 0x23 0x00 2
i2ctransfer -f -y 16 w3@0x23 0x0D 0xB2 0x0C
//0.75V (nominal)
i2cset -f -y 16 0x23 0x00 1
i2ctransfer -f -y 16 w3@0x23 0x21 0x65 0x00
i2cset -f -y 16 0x23 0x00 2
i2ctransfer -f -y 16 w3@0x23 0x1D 0x5A 0x06
//0.75V (nominal)
i2cset -f -y 16 0x24 0x00 0
i2ctransfer -f -y 16 w3@0x24 0x21 0x65 0x00
i2cset -f -y 16 0x24 0x00 2
i2ctransfer -f -y 16 w3@0x24 0x0D 0xB2 0x0C
//0.75V (nominal)
i2cset -f -y 16 0x24 0x00 1
i2ctransfer -f -y 16 w3@0x24 0x21 0x65 0x00
i2cset -f -y 16 0x24 0x00 2
i2ctransfer -f -y 16 w3@0x24 0x1D 0x5A 0x06
//1.5V (nominal)
i2cset -f -y 14 0x29 0x00 0
i2ctransfer -f -y 14 w3@0x29 0x21 0xFB 0x00
i2cset -f -y 14 0x29 0x00 2
i2ctransfer -f -y 14 w3@0x29 0x0D 0x71 0x1F
//1.5V (nominal)
i2cset -f -y 14 0x29 0x00 1
i2ctransfer -f -y 14 w3@0x29 0x21 0xFB 0x00
i2cset -f -y 14 0x29 0x00 2
i2ctransfer -f -y 14 w3@0x29 0x1D 0xB9 0x0F
//0.720V (nominal)
i2cset -f -y 14 0x27 0x00 0
i2ctransfer -f -y 14 w3@0x27 0x21 0x5F 0x00
i2cset -f -y 14 0x27 0x00 2
i2ctransfer -f -y 14 w3@0x27 0x0D 0xF4 0x0B
//0.720V (nominal)
i2cset -f -y 14 0x27 0x00 1
i2ctransfer -f -y 14 w3@0x27 0x21 0x5F 0x00
i2cset -f -y 14 0x27 0x00 2
i2ctransfer -f -y 14 w3@0x27 0x1D 0xFC 0x05
//0.720V (nominal)
i2cset -f -y 16 0x28 0x00 0
i2ctransfer -f -y 16 w3@0x28 0x21 0x5F 0x00
i2cset -f -y 16 0x28 0x00 2
i2ctransfer -f -y 16 w3@0x28 0x0D 0xF4 0x0B
//0.720V (nominal)
i2cset -f -y 16 0x28 0x00 1
i2ctransfer -f -y 16 w3@0x28 0x21 0x5F 0x00
i2cset -f -y 16 0x28 0x00 2
i2ctransfer -f -y 16 w3@0x28 0x1D 0xFC 0x05
//0.8V(nominal) , 0.8591V with load line
i2cset -f -y 14 0x20 0x00 0
i2ctransfer -f -y 14 w3@0x20 0x21 0x57 0x01
+48
View File
@@ -0,0 +1,48 @@
i2cset -f -y 13 0x25 0x00 0
i2cset -f -y 13 0x25 0x15
i2cset -f -y 15 0x26 0x00 0
i2cset -f -y 15 0x26 0x15
i2cset -f -y 13 0x25 0x00 0
i2cset -f -y 13 0x25 0x15
i2cset -f -y 15 0x26 0x00 0
i2cset -f -y 15 0x26 0x15
i2cset -f -y 13 0x21 0x00 0
i2cset -f -y 13 0x21 0x15
i2cset -f -y 13 0x22 0x00 0
i2cset -f -y 13 0x22 0x15
i2cset -f -y 15 0x23 0x00 0
i2cset -f -y 15 0x23 0x15
i2cset -f -y 15 0x24 0x00 0
i2cset -f -y 15 0x24 0x15
i2cset -f -y 13 0x29 0x00 0
i2cset -f -y 13 0x29 0x15
i2cset -f -y 13 0x27 0x00 0
i2cset -f -y 13 0x27 0x15
i2cset -f -y 15 0x28 0x00 0
i2cset -f -y 15 0x28 0x15
i2cset -f -y 13 0x20 0x00 0
i2cset -f -y 13 0x20 0x17
i2cset -f -y 14 0x25 0x00 0
i2cset -f -y 14 0x25 0x15
i2cset -f -y 16 0x26 0x00 0
i2cset -f -y 16 0x26 0x15
i2cset -f -y 14 0x25 0x00 0
i2cset -f -y 14 0x25 0x15
i2cset -f -y 16 0x26 0x00 0
i2cset -f -y 16 0x26 0x15
i2cset -f -y 14 0x21 0x00 0
i2cset -f -y 14 0x21 0x15
i2cset -f -y 14 0x22 0x00 0
i2cset -f -y 14 0x22 0x15
i2cset -f -y 16 0x23 0x00 0
i2cset -f -y 16 0x23 0x15
i2cset -f -y 16 0x24 0x00 0
i2cset -f -y 16 0x24 0x15
i2cset -f -y 14 0x29 0x00 0
i2cset -f -y 14 0x29 0x15
i2cset -f -y 14 0x27 0x00 0
i2cset -f -y 14 0x27 0x15
i2cset -f -y 16 0x28 0x00 0
i2cset -f -y 16 0x28 0x15
i2cset -f -y 14 0x20 0x00 0
i2cset -f -y 14 0x20 0x17
+188
View File
@@ -0,0 +1,188 @@
//0.930V
i2cset -f -y 13 0x25 0x00 0
i2ctransfer -f -y 13 w3@0x25 0x21 0x89 0x00
i2cset -f -y 13 0x25 0x00 2
i2ctransfer -f -y 13 w3@0x25 0x0D 0x34 0x11
//0.930V
i2cset -f -y 15 0x26 0x00 0
i2ctransfer -f -y 15 w3@0x26 0x21 0x89 0x00
i2cset -f -y 15 0x26 0x00 2
i2ctransfer -f -y 15 w3@0x26 0x0D 0x34 0x11
//0.725V
i2cset -f -y 13 0x25 0x00 1
i2ctransfer -f -y 13 w3@0x25 0x21 0x60 0x00
i2cset -f -y 13 0x25 0x00 2
i2ctransfer -f -y 13 w3@0x25 0x1D 0x0A 0x06
//0.725V
i2cset -f -y 15 0x26 0x00 1
i2ctransfer -f -y 15 w3@0x26 0x21 0x60 0x00
i2cset -f -y 15 0x26 0x00 2
i2ctransfer -f -y 15 w3@0x26 0x1D 0x0A 0x06
//0.725V
i2cset -f -y 13 0x21 0x00 0
i2ctransfer -f -y 13 w3@0x21 0x21 0x60 0x00
i2cset -f -y 13 0x21 0x00 2
i2ctransfer -f -y 13 w3@0x21 0x0D 0x12 0x0C
//0.725V
i2cset -f -y 13 0x21 0x00 1
i2ctransfer -f -y 13 w3@0x21 0x21 0x60 0x00
i2cset -f -y 13 0x21 0x00 2
i2ctransfer -f -y 13 w3@0x21 0x1D 0x0A 0x06
//0.725V
i2cset -f -y 13 0x22 0x00 0
i2ctransfer -f -y 13 w3@0x22 0x21 0x60 0x00
i2cset -f -y 13 0x22 0x00 2
i2ctransfer -f -y 13 w3@0x22 0x0D 0x12 0x0C
//0.725V
i2cset -f -y 13 0x22 0x00 1
i2ctransfer -f -y 13 w3@0x22 0x21 0x60 0x00
i2cset -f -y 13 0x22 0x00 2
i2ctransfer -f -y 13 w3@0x22 0x1D 0x0A 0x06
//0.725V
i2cset -f -y 15 0x23 0x00 0
i2ctransfer -f -y 15 w3@0x23 0x21 0x60 0x00
i2cset -f -y 15 0x23 0x00 2
i2ctransfer -f -y 15 w3@0x23 0x0D 0x12 0x0C
//0.725V
i2cset -f -y 15 0x23 0x00 1
i2ctransfer -f -y 15 w3@0x23 0x21 0x60 0x00
i2cset -f -y 15 0x23 0x00 2
i2ctransfer -f -y 15 w3@0x23 0x1D 0x0A 0x06
//0.725V
i2cset -f -y 15 0x24 0x00 0
i2ctransfer -f -y 15 w3@0x24 0x21 0x60 0x00
i2cset -f -y 15 0x24 0x00 2
i2ctransfer -f -y 15 w3@0x24 0x0D 0x12 0x0C
//0.725V
i2cset -f -y 15 0x24 0x00 1
i2ctransfer -f -y 15 w3@0x24 0x21 0x60 0x00
i2cset -f -y 15 0x24 0x00 2
i2ctransfer -f -y 15 w3@0x24 0x1D 0x0A 0x06
//1.545V
i2cset -f -y 13 0x29 0x00 0
i2ctransfer -f -y 13 w3@0x29 0x21 0x04 0x01
i2cset -f -y 13 0x29 0x00 2
i2ctransfer -f -y 13 w3@0x29 0x0D 0x91 0x20
//1.545V
i2cset -f -y 13 0x29 0x00 1
i2ctransfer -f -y 13 w3@0x29 0x21 0x04 0x01
i2cset -f -y 13 0x29 0x00 2
i2ctransfer -f -y 13 w3@0x29 0x1D 0x49 0x10
//0.745V
i2cset -f -y 13 0x27 0x00 0
i2ctransfer -f -y 13 w3@0x27 0x21 0x64 0x00
i2cset -f -y 13 0x27 0x00 2
i2ctransfer -f -y 13 w3@0x27 0x0D 0x94 0x0C
//0.745V
i2cset -f -y 13 0x27 0x00 1
i2ctransfer -f -y 13 w3@0x27 0x21 0x64 0x00
i2cset -f -y 13 0x27 0x00 2
i2ctransfer -f -y 13 w3@0x27 0x1D 0x4C 0x06
//0.745V
i2cset -f -y 15 0x28 0x00 0
i2ctransfer -f -y 15 w3@0x28 0x21 0x64 0x00
i2cset -f -y 15 0x28 0x00 2
i2ctransfer -f -y 15 w3@0x28 0x0D 0x94 0x0C
//0.745V
i2cset -f -y 15 0x28 0x00 1
i2ctransfer -f -y 15 w3@0x28 0x21 0x64 0x00
i2cset -f -y 15 0x28 0x00 2
i2ctransfer -f -y 15 w3@0x28 0x1D 0x4C 0x06
//0.885V
i2cset -f -y 13 0x20 0x00 0
i2ctransfer -f -y 13 w3@0x20 0x21 0x62 0x01
//0.930V
i2cset -f -y 14 0x25 0x00 0
i2ctransfer -f -y 14 w3@0x25 0x21 0x89 0x00
i2cset -f -y 14 0x25 0x00 2
i2ctransfer -f -y 14 w3@0x25 0x0D 0x34 0x11
//0.930V
i2cset -f -y 16 0x26 0x00 0
i2ctransfer -f -y 16 w3@0x26 0x21 0x89 0x00
i2cset -f -y 16 0x26 0x00 2
i2ctransfer -f -y 16 w3@0x26 0x0D 0x34 0x11
//0.725V
i2cset -f -y 14 0x25 0x00 1
i2ctransfer -f -y 14 w3@0x25 0x21 0x60 0x00
i2cset -f -y 14 0x25 0x00 2
i2ctransfer -f -y 14 w3@0x25 0x1D 0x0A 0x06
//0.725V
i2cset -f -y 16 0x26 0x00 1
i2ctransfer -f -y 16 w3@0x26 0x21 0x60 0x00
i2cset -f -y 16 0x26 0x00 2
i2ctransfer -f -y 16 w3@0x26 0x1D 0x0A 0x06
//0.725V
i2cset -f -y 14 0x21 0x00 0
i2ctransfer -f -y 14 w3@0x21 0x21 0x60 0x00
i2cset -f -y 14 0x21 0x00 2
i2ctransfer -f -y 14 w3@0x21 0x0D 0x12 0x0C
//0.725V
i2cset -f -y 14 0x21 0x00 1
i2ctransfer -f -y 14 w3@0x21 0x21 0x60 0x00
i2cset -f -y 14 0x21 0x00 2
i2ctransfer -f -y 14 w3@0x21 0x1D 0x0A 0x06
//0.725V
i2cset -f -y 14 0x22 0x00 0
i2ctransfer -f -y 14 w3@0x22 0x21 0x60 0x00
i2cset -f -y 14 0x22 0x00 2
i2ctransfer -f -y 14 w3@0x22 0x0D 0x12 0x0C
//0.725V
i2cset -f -y 14 0x22 0x00 1
i2ctransfer -f -y 14 w3@0x22 0x21 0x60 0x00
i2cset -f -y 14 0x22 0x00 2
i2ctransfer -f -y 14 w3@0x22 0x1D 0x0A 0x06
//0.725V
i2cset -f -y 16 0x23 0x00 0
i2ctransfer -f -y 16 w3@0x23 0x21 0x60 0x00
i2cset -f -y 16 0x23 0x00 2
i2ctransfer -f -y 16 w3@0x23 0x0D 0x12 0x0C
//0.725V
i2cset -f -y 16 0x23 0x00 1
i2ctransfer -f -y 16 w3@0x23 0x21 0x60 0x00
i2cset -f -y 16 0x23 0x00 2
i2ctransfer -f -y 16 w3@0x23 0x1D 0x0A 0x06
//0.725V
i2cset -f -y 16 0x24 0x00 0
i2ctransfer -f -y 16 w3@0x24 0x21 0x60 0x00
i2cset -f -y 16 0x24 0x00 2
i2ctransfer -f -y 16 w3@0x24 0x0D 0x12 0x0C
//0.725V
i2cset -f -y 16 0x24 0x00 1
i2ctransfer -f -y 16 w3@0x24 0x21 0x60 0x00
i2cset -f -y 16 0x24 0x00 2
i2ctransfer -f -y 16 w3@0x24 0x1D 0x0A 0x06
//1.545V
i2cset -f -y 14 0x29 0x00 0
i2ctransfer -f -y 14 w3@0x29 0x21 0x04 0x01
i2cset -f -y 14 0x29 0x00 2
i2ctransfer -f -y 14 w3@0x29 0x0D 0x91 0x20
//1.545V
i2cset -f -y 14 0x29 0x00 1
i2ctransfer -f -y 14 w3@0x29 0x21 0x04 0x01
i2cset -f -y 14 0x29 0x00 2
i2ctransfer -f -y 14 w3@0x29 0x1D 0x49 0x10
//0.745V
i2cset -f -y 14 0x27 0x00 0
i2ctransfer -f -y 14 w3@0x27 0x21 0x64 0x00
i2cset -f -y 14 0x27 0x00 2
i2ctransfer -f -y 14 w3@0x27 0x0D 0x94 0x0C
//0.745V
i2cset -f -y 14 0x27 0x00 1
i2ctransfer -f -y 14 w3@0x27 0x21 0x64 0x00
i2cset -f -y 14 0x27 0x00 2
i2ctransfer -f -y 14 w3@0x27 0x1D 0x4C 0x06
//0.745V
i2cset -f -y 16 0x28 0x00 0
i2ctransfer -f -y 16 w3@0x28 0x21 0x64 0x00
i2cset -f -y 16 0x28 0x00 2
i2ctransfer -f -y 16 w3@0x28 0x0D 0x94 0x0C
//0.745V
i2cset -f -y 16 0x28 0x00 1
i2ctransfer -f -y 16 w3@0x28 0x21 0x64 0x00
i2cset -f -y 16 0x28 0x00 2
i2ctransfer -f -y 16 w3@0x28 0x1D 0x4C 0x06
//0.885V
i2cset -f -y 14 0x20 0x00 0
i2ctransfer -f -y 14 w3@0x20 0x21 0x62 0x01
+188
View File
@@ -0,0 +1,188 @@
//0.870V
i2cset -f -y 13 0x25 0x00 0
i2ctransfer -f -y 13 w3@0x25 0x21 0x7D 0x00
i2cset -f -y 13 0x25 0x00 2
i2ctransfer -f -y 13 w3@0x25 0x0D 0xB4 0x0F
//0.870V
i2cset -f -y 15 0x26 0x00 0
i2ctransfer -f -y 15 w3@0x26 0x21 0x7D 0x00
i2cset -f -y 15 0x26 0x00 2
i2ctransfer -f -y 15 w3@0x26 0x0D 0xB4 0x0F
//0.775V
i2cset -f -y 13 0x25 0x00 1
i2ctransfer -f -y 13 w3@0x25 0x21 0x6A 0x00
i2cset -f -y 13 0x25 0x00 2
i2ctransfer -f -y 13 w3@0x25 0x1D 0xAA 0x06
//0.775V
i2cset -f -y 15 0x26 0x00 1
i2ctransfer -f -y 15 w3@0x26 0x21 0x6A 0x00
i2cset -f -y 15 0x26 0x00 2
i2ctransfer -f -y 15 w3@0x26 0x1D 0xAA 0x06
//0.775V
i2cset -f -y 13 0x21 0x00 0
i2ctransfer -f -y 13 w3@0x21 0x21 0x6A 0x00
i2cset -f -y 13 0x21 0x00 2
i2ctransfer -f -y 13 w3@0x21 0x0D 0x52 0x0D
//0.775V
i2cset -f -y 13 0x21 0x00 1
i2ctransfer -f -y 13 w3@0x21 0x21 0x6A 0x00
i2cset -f -y 13 0x21 0x00 2
i2ctransfer -f -y 13 w3@0x21 0x1D 0xAA 0x06
//0.775V
i2cset -f -y 13 0x22 0x00 0
i2ctransfer -f -y 13 w3@0x22 0x21 0x6A 0x00
i2cset -f -y 13 0x22 0x00 2
i2ctransfer -f -y 13 w3@0x22 0x0D 0x52 0x0D
//0.775V
i2cset -f -y 13 0x22 0x00 1
i2ctransfer -f -y 13 w3@0x22 0x21 0x6A 0x00
i2cset -f -y 13 0x22 0x00 2
i2ctransfer -f -y 13 w3@0x22 0x1D 0xAA 0x06
//0.775V
i2cset -f -y 15 0x23 0x00 0
i2ctransfer -f -y 15 w3@0x23 0x21 0x6A 0x00
i2cset -f -y 15 0x23 0x00 2
i2ctransfer -f -y 15 w3@0x23 0x0D 0x52 0x0D
//0.775V
i2cset -f -y 15 0x23 0x00 1
i2ctransfer -f -y 15 w3@0x23 0x21 0x6A 0x00
i2cset -f -y 15 0x23 0x00 2
i2ctransfer -f -y 15 w3@0x23 0x1D 0xAA 0x06
//0.775V
i2cset -f -y 15 0x24 0x00 0
i2ctransfer -f -y 15 w3@0x24 0x21 0x6A 0x00
i2cset -f -y 15 0x24 0x00 2
i2ctransfer -f -y 15 w3@0x24 0x0D 0x52 0x0D
//0.775V
i2cset -f -y 15 0x24 0x00 1
i2ctransfer -f -y 15 w3@0x24 0x21 0x6A 0x00
i2cset -f -y 15 0x24 0x00 2
i2ctransfer -f -y 15 w3@0x24 0x1D 0xAA 0x06
//1.455V
i2cset -f -y 13 0x29 0x00 0
i2ctransfer -f -y 13 w3@0x29 0x21 0xF2 0x00
i2cset -f -y 13 0x29 0x00 2
i2ctransfer -f -y 13 w3@0x29 0x0D 0x51 0x1E
//1.455V
i2cset -f -y 13 0x29 0x00 1
i2ctransfer -f -y 13 w3@0x29 0x21 0xF2 0x00
i2cset -f -y 13 0x29 0x00 2
i2ctransfer -f -y 13 w3@0x29 0x1D 0x29 0x0F
//0.695V
i2cset -f -y 13 0x27 0x00 0
i2ctransfer -f -y 13 w3@0x27 0x21 0x5A 0x00
i2cset -f -y 13 0x27 0x00 2
i2ctransfer -f -y 13 w3@0x27 0x0D 0x54 0x0B
//0.695V
i2cset -f -y 13 0x27 0x00 1
i2ctransfer -f -y 13 w3@0x27 0x21 0x5A 0x00
i2cset -f -y 13 0x27 0x00 2
i2ctransfer -f -y 13 w3@0x27 0x1D 0xAC 0x05
//0.695V
i2cset -f -y 15 0x28 0x00 0
i2ctransfer -f -y 15 w3@0x28 0x21 0x5A 0x00
i2cset -f -y 15 0x28 0x00 2
i2ctransfer -f -y 15 w3@0x28 0x0D 0x54 0x0B
//0.695V
i2cset -f -y 15 0x28 0x00 1
i2ctransfer -f -y 15 w3@0x28 0x21 0x5A 0x00
i2cset -f -y 15 0x28 0x00 2
i2ctransfer -f -y 15 w3@0x28 0x1D 0xAC 0x05
//0.753V
i2cset -f -y 13 0x20 0x00 0
i2ctransfer -f -y 13 w3@0x20 0x21 0x2D 0x01
//0.870V
i2cset -f -y 14 0x25 0x00 0
i2ctransfer -f -y 14 w3@0x25 0x21 0x7D 0x00
i2cset -f -y 14 0x25 0x00 2
i2ctransfer -f -y 14 w3@0x25 0x0D 0xB4 0x0F
//0.870V
i2cset -f -y 16 0x26 0x00 0
i2ctransfer -f -y 16 w3@0x26 0x21 0x7D 0x00
i2cset -f -y 16 0x26 0x00 2
i2ctransfer -f -y 16 w3@0x26 0x0D 0xB4 0x0F
//0.775V
i2cset -f -y 14 0x25 0x00 1
i2ctransfer -f -y 14 w3@0x25 0x21 0x6A 0x00
i2cset -f -y 14 0x25 0x00 2
i2ctransfer -f -y 14 w3@0x25 0x1D 0xAA 0x06
//0.775V
i2cset -f -y 16 0x26 0x00 1
i2ctransfer -f -y 16 w3@0x26 0x21 0x6A 0x00
i2cset -f -y 16 0x26 0x00 2
i2ctransfer -f -y 16 w3@0x26 0x1D 0xAA 0x06
//0.775V
i2cset -f -y 14 0x21 0x00 0
i2ctransfer -f -y 14 w3@0x21 0x21 0x6A 0x00
i2cset -f -y 14 0x21 0x00 2
i2ctransfer -f -y 14 w3@0x21 0x0D 0x52 0x0D
//0.775V
i2cset -f -y 14 0x21 0x00 1
i2ctransfer -f -y 14 w3@0x21 0x21 0x6A 0x00
i2cset -f -y 14 0x21 0x00 2
i2ctransfer -f -y 14 w3@0x21 0x1D 0xAA 0x06
//0.775V
i2cset -f -y 14 0x22 0x00 0
i2ctransfer -f -y 14 w3@0x22 0x21 0x6A 0x00
i2cset -f -y 14 0x22 0x00 2
i2ctransfer -f -y 14 w3@0x22 0x0D 0x52 0x0D
//0.775V
i2cset -f -y 14 0x22 0x00 1
i2ctransfer -f -y 14 w3@0x22 0x21 0x6A 0x00
i2cset -f -y 14 0x22 0x00 2
i2ctransfer -f -y 14 w3@0x22 0x1D 0xAA 0x06
//0.775V
i2cset -f -y 16 0x23 0x00 0
i2ctransfer -f -y 16 w3@0x23 0x21 0x6A 0x00
i2cset -f -y 16 0x23 0x00 2
i2ctransfer -f -y 16 w3@0x23 0x0D 0x52 0x0D
//0.775V
i2cset -f -y 16 0x23 0x00 1
i2ctransfer -f -y 16 w3@0x23 0x21 0x6A 0x00
i2cset -f -y 16 0x23 0x00 2
i2ctransfer -f -y 16 w3@0x23 0x1D 0xAA 0x06
//0.775V
i2cset -f -y 16 0x24 0x00 0
i2ctransfer -f -y 16 w3@0x24 0x21 0x6A 0x00
i2cset -f -y 16 0x24 0x00 2
i2ctransfer -f -y 16 w3@0x24 0x0D 0x52 0x0D
//0.775V
i2cset -f -y 16 0x24 0x00 1
i2ctransfer -f -y 16 w3@0x24 0x21 0x6A 0x00
i2cset -f -y 16 0x24 0x00 2
i2ctransfer -f -y 16 w3@0x24 0x1D 0xAA 0x06
//1.455V
i2cset -f -y 14 0x29 0x00 0
i2ctransfer -f -y 14 w3@0x29 0x21 0xF2 0x00
i2cset -f -y 14 0x29 0x00 2
i2ctransfer -f -y 14 w3@0x29 0x0D 0x51 0x1E
//1.455V
i2cset -f -y 14 0x29 0x00 1
i2ctransfer -f -y 14 w3@0x29 0x21 0xF2 0x00
i2cset -f -y 14 0x29 0x00 2
i2ctransfer -f -y 14 w3@0x29 0x1D 0x29 0x0F
//0.695V
i2cset -f -y 14 0x27 0x00 0
i2ctransfer -f -y 14 w3@0x27 0x21 0x5A 0x00
i2cset -f -y 14 0x27 0x00 2
i2ctransfer -f -y 14 w3@0x27 0x0D 0x54 0x0B
//0.695V
i2cset -f -y 14 0x27 0x00 1
i2ctransfer -f -y 14 w3@0x27 0x21 0x5A 0x00
i2cset -f -y 14 0x27 0x00 2
i2ctransfer -f -y 14 w3@0x27 0x1D 0xAC 0x05
//0.695V
i2cset -f -y 16 0x28 0x00 0
i2ctransfer -f -y 16 w3@0x28 0x21 0x5A 0x00
i2cset -f -y 16 0x28 0x00 2
i2ctransfer -f -y 16 w3@0x28 0x0D 0x54 0x0B
//0.695V
i2cset -f -y 16 0x28 0x00 1
i2ctransfer -f -y 16 w3@0x28 0x21 0x5A 0x00
i2cset -f -y 16 0x28 0x00 2
i2ctransfer -f -y 16 w3@0x28 0x1D 0xAC 0x05
//0.753V
i2cset -f -y 14 0x20 0x00 0
i2ctransfer -f -y 14 w3@0x20 0x21 0x2D 0x01
+188
View File
@@ -0,0 +1,188 @@
//0.930V
i2cset -f -y 13 0x25 0x00 0
i2ctransfer -f -y 13 w3@0x25 0x21 0x89 0x00
i2cset -f -y 13 0x25 0x00 2
i2ctransfer -f -y 13 w3@0x25 0x0D 0x34 0x11
//0.930V
i2cset -f -y 15 0x26 0x00 0
i2ctransfer -f -y 15 w3@0x26 0x21 0x89 0x00
i2cset -f -y 15 0x26 0x00 2
i2ctransfer -f -y 15 w3@0x26 0x0D 0x34 0x11
//0.775V
i2cset -f -y 13 0x25 0x00 1
i2ctransfer -f -y 13 w3@0x25 0x21 0x6A 0x00
i2cset -f -y 13 0x25 0x00 2
i2ctransfer -f -y 13 w3@0x25 0x1D 0xAA 0x06
//0.775V
i2cset -f -y 15 0x26 0x00 1
i2ctransfer -f -y 15 w3@0x26 0x21 0x6A 0x00
i2cset -f -y 15 0x26 0x00 2
i2ctransfer -f -y 15 w3@0x26 0x1D 0xAA 0x06
//0.775V
i2cset -f -y 13 0x21 0x00 0
i2ctransfer -f -y 13 w3@0x21 0x21 0x6A 0x00
i2cset -f -y 13 0x21 0x00 2
i2ctransfer -f -y 13 w3@0x21 0x0D 0x52 0x0D
//0.775V
i2cset -f -y 13 0x21 0x00 1
i2ctransfer -f -y 13 w3@0x21 0x21 0x6A 0x00
i2cset -f -y 13 0x21 0x00 2
i2ctransfer -f -y 13 w3@0x21 0x1D 0xAA 0x06
//0.775V
i2cset -f -y 13 0x22 0x00 0
i2ctransfer -f -y 13 w3@0x22 0x21 0x6A 0x00
i2cset -f -y 13 0x22 0x00 2
i2ctransfer -f -y 13 w3@0x22 0x0D 0x52 0x0D
//0.775V
i2cset -f -y 13 0x22 0x00 1
i2ctransfer -f -y 13 w3@0x22 0x21 0x6A 0x00
i2cset -f -y 13 0x22 0x00 2
i2ctransfer -f -y 13 w3@0x22 0x1D 0xAA 0x06
//0.775V
i2cset -f -y 15 0x23 0x00 0
i2ctransfer -f -y 15 w3@0x23 0x21 0x6A 0x00
i2cset -f -y 15 0x23 0x00 2
i2ctransfer -f -y 15 w3@0x23 0x0D 0x52 0x0D
//0.775V
i2cset -f -y 15 0x23 0x00 1
i2ctransfer -f -y 15 w3@0x23 0x21 0x6A 0x00
i2cset -f -y 15 0x23 0x00 2
i2ctransfer -f -y 15 w3@0x23 0x1D 0xAA 0x06
//0.775V
i2cset -f -y 15 0x24 0x00 0
i2ctransfer -f -y 15 w3@0x24 0x21 0x6A 0x00
i2cset -f -y 15 0x24 0x00 2
i2ctransfer -f -y 15 w3@0x24 0x0D 0x52 0x0D
//0.775V
i2cset -f -y 15 0x24 0x00 1
i2ctransfer -f -y 15 w3@0x24 0x21 0x6A 0x00
i2cset -f -y 15 0x24 0x00 2
i2ctransfer -f -y 15 w3@0x24 0x1D 0xAA 0x06
//1.545V
i2cset -f -y 13 0x29 0x00 0
i2ctransfer -f -y 13 w3@0x29 0x21 0x04 0x01
i2cset -f -y 13 0x29 0x00 2
i2ctransfer -f -y 13 w3@0x29 0x0D 0x91 0x20
//1.545V
i2cset -f -y 13 0x29 0x00 1
i2ctransfer -f -y 13 w3@0x29 0x21 0x04 0x01
i2cset -f -y 13 0x29 0x00 2
i2ctransfer -f -y 13 w3@0x29 0x1D 0x49 0x10
//0.745V
i2cset -f -y 13 0x27 0x00 0
i2ctransfer -f -y 13 w3@0x27 0x21 0x64 0x00
i2cset -f -y 13 0x27 0x00 2
i2ctransfer -f -y 13 w3@0x27 0x0D 0x94 0x0C
//0.745V
i2cset -f -y 13 0x27 0x00 1
i2ctransfer -f -y 13 w3@0x27 0x21 0x64 0x00
i2cset -f -y 13 0x27 0x00 2
i2ctransfer -f -y 13 w3@0x27 0x1D 0x4C 0x06
//0.745V
i2cset -f -y 15 0x28 0x00 0
i2ctransfer -f -y 15 w3@0x28 0x21 0x64 0x00
i2cset -f -y 15 0x28 0x00 2
i2ctransfer -f -y 15 w3@0x28 0x0D 0x94 0x0C
//0.745V
i2cset -f -y 15 0x28 0x00 1
i2ctransfer -f -y 15 w3@0x28 0x21 0x64 0x00
i2cset -f -y 15 0x28 0x00 2
i2ctransfer -f -y 15 w3@0x28 0x1D 0x4C 0x06
//0.885V
i2cset -f -y 13 0x20 0x00 0
i2ctransfer -f -y 13 w3@0x20 0x21 0x62 0x01
//0.930V
i2cset -f -y 14 0x25 0x00 0
i2ctransfer -f -y 14 w3@0x25 0x21 0x89 0x00
i2cset -f -y 14 0x25 0x00 2
i2ctransfer -f -y 14 w3@0x25 0x0D 0x34 0x11
//0.930V
i2cset -f -y 16 0x26 0x00 0
i2ctransfer -f -y 16 w3@0x26 0x21 0x89 0x00
i2cset -f -y 16 0x26 0x00 2
i2ctransfer -f -y 16 w3@0x26 0x0D 0x34 0x11
//0.775V
i2cset -f -y 14 0x25 0x00 1
i2ctransfer -f -y 14 w3@0x25 0x21 0x6A 0x00
i2cset -f -y 14 0x25 0x00 2
i2ctransfer -f -y 14 w3@0x25 0x1D 0xAA 0x06
//0.775V
i2cset -f -y 16 0x26 0x00 1
i2ctransfer -f -y 16 w3@0x26 0x21 0x6A 0x00
i2cset -f -y 16 0x26 0x00 2
i2ctransfer -f -y 16 w3@0x26 0x1D 0xAA 0x06
//0.775V
i2cset -f -y 14 0x21 0x00 0
i2ctransfer -f -y 14 w3@0x21 0x21 0x6A 0x00
i2cset -f -y 14 0x21 0x00 2
i2ctransfer -f -y 14 w3@0x21 0x0D 0x52 0x0D
//0.775V
i2cset -f -y 14 0x21 0x00 1
i2ctransfer -f -y 14 w3@0x21 0x21 0x6A 0x00
i2cset -f -y 14 0x21 0x00 2
i2ctransfer -f -y 14 w3@0x21 0x1D 0xAA 0x06
//0.775V
i2cset -f -y 14 0x22 0x00 0
i2ctransfer -f -y 14 w3@0x22 0x21 0x6A 0x00
i2cset -f -y 14 0x22 0x00 2
i2ctransfer -f -y 14 w3@0x22 0x0D 0x52 0x0D
//0.775V
i2cset -f -y 14 0x22 0x00 1
i2ctransfer -f -y 14 w3@0x22 0x21 0x6A 0x00
i2cset -f -y 14 0x22 0x00 2
i2ctransfer -f -y 14 w3@0x22 0x1D 0xAA 0x06
//0.775V
i2cset -f -y 16 0x23 0x00 0
i2ctransfer -f -y 16 w3@0x23 0x21 0x6A 0x00
i2cset -f -y 16 0x23 0x00 2
i2ctransfer -f -y 16 w3@0x23 0x0D 0x52 0x0D
//0.775V
i2cset -f -y 16 0x23 0x00 1
i2ctransfer -f -y 16 w3@0x23 0x21 0x6A 0x00
i2cset -f -y 16 0x23 0x00 2
i2ctransfer -f -y 16 w3@0x23 0x1D 0xAA 0x06
//0.775V
i2cset -f -y 16 0x24 0x00 0
i2ctransfer -f -y 16 w3@0x24 0x21 0x6A 0x00
i2cset -f -y 16 0x24 0x00 2
i2ctransfer -f -y 16 w3@0x24 0x0D 0x52 0x0D
//0.775V
i2cset -f -y 16 0x24 0x00 1
i2ctransfer -f -y 16 w3@0x24 0x21 0x6A 0x00
i2cset -f -y 16 0x24 0x00 2
i2ctransfer -f -y 16 w3@0x24 0x1D 0xAA 0x06
//1.545V
i2cset -f -y 14 0x29 0x00 0
i2ctransfer -f -y 14 w3@0x29 0x21 0x04 0x01
i2cset -f -y 14 0x29 0x00 2
i2ctransfer -f -y 14 w3@0x29 0x0D 0x91 0x20
//1.545V
i2cset -f -y 14 0x29 0x00 1
i2ctransfer -f -y 14 w3@0x29 0x21 0x04 0x01
i2cset -f -y 14 0x29 0x00 2
i2ctransfer -f -y 14 w3@0x29 0x1D 0x49 0x10
//0.745V
i2cset -f -y 14 0x27 0x00 0
i2ctransfer -f -y 14 w3@0x27 0x21 0x64 0x00
i2cset -f -y 14 0x27 0x00 2
i2ctransfer -f -y 14 w3@0x27 0x0D 0x94 0x0C
//0.745V
i2cset -f -y 14 0x27 0x00 1
i2ctransfer -f -y 14 w3@0x27 0x21 0x64 0x00
i2cset -f -y 14 0x27 0x00 2
i2ctransfer -f -y 14 w3@0x27 0x1D 0x4C 0x06
//0.745V
i2cset -f -y 16 0x28 0x00 0
i2ctransfer -f -y 16 w3@0x28 0x21 0x64 0x00
i2cset -f -y 16 0x28 0x00 2
i2ctransfer -f -y 16 w3@0x28 0x0D 0x94 0x0C
//0.745V
i2cset -f -y 16 0x28 0x00 1
i2ctransfer -f -y 16 w3@0x28 0x21 0x64 0x00
i2cset -f -y 16 0x28 0x00 2
i2ctransfer -f -y 16 w3@0x28 0x1D 0x4C 0x06
//0.885V
i2cset -f -y 14 0x20 0x00 0
i2ctransfer -f -y 14 w3@0x20 0x21 0x62 0x01
+188
View File
@@ -0,0 +1,188 @@
//0.870V
i2cset -f -y 13 0x25 0x00 0
i2ctransfer -f -y 13 w3@0x25 0x21 0x7D 0x00
i2cset -f -y 13 0x25 0x00 2
i2ctransfer -f -y 13 w3@0x25 0x0D 0xB4 0x0F
//0.870V
i2cset -f -y 15 0x26 0x00 0
i2ctransfer -f -y 15 w3@0x26 0x21 0x7D 0x00
i2cset -f -y 15 0x26 0x00 2
i2ctransfer -f -y 15 w3@0x26 0x0D 0xB4 0x0F
//0.725V
i2cset -f -y 13 0x25 0x00 1
i2ctransfer -f -y 13 w3@0x25 0x21 0x60 0x00
i2cset -f -y 13 0x25 0x00 2
i2ctransfer -f -y 13 w3@0x25 0x1D 0x0A 0x06
//0.725V
i2cset -f -y 15 0x26 0x00 1
i2ctransfer -f -y 15 w3@0x26 0x21 0x60 0x00
i2cset -f -y 15 0x26 0x00 2
i2ctransfer -f -y 15 w3@0x26 0x1D 0x0A 0x06
//0.725V
i2cset -f -y 13 0x21 0x00 0
i2ctransfer -f -y 13 w3@0x21 0x21 0x60 0x00
i2cset -f -y 13 0x21 0x00 2
i2ctransfer -f -y 13 w3@0x21 0x0D 0x12 0x0C
//0.725V
i2cset -f -y 13 0x21 0x00 1
i2ctransfer -f -y 13 w3@0x21 0x21 0x60 0x00
i2cset -f -y 13 0x21 0x00 2
i2ctransfer -f -y 13 w3@0x21 0x1D 0x0A 0x06
//0.725V
i2cset -f -y 13 0x22 0x00 0
i2ctransfer -f -y 13 w3@0x22 0x21 0x60 0x00
i2cset -f -y 13 0x22 0x00 2
i2ctransfer -f -y 13 w3@0x22 0x0D 0x12 0x0C
//0.725V
i2cset -f -y 13 0x22 0x00 1
i2ctransfer -f -y 13 w3@0x22 0x21 0x60 0x00
i2cset -f -y 13 0x22 0x00 2
i2ctransfer -f -y 13 w3@0x22 0x1D 0x0A 0x06
//0.725V
i2cset -f -y 15 0x23 0x00 0
i2ctransfer -f -y 15 w3@0x23 0x21 0x60 0x00
i2cset -f -y 15 0x23 0x00 2
i2ctransfer -f -y 15 w3@0x23 0x0D 0x12 0x0C
//0.725V
i2cset -f -y 15 0x23 0x00 1
i2ctransfer -f -y 15 w3@0x23 0x21 0x60 0x00
i2cset -f -y 15 0x23 0x00 2
i2ctransfer -f -y 15 w3@0x23 0x1D 0x0A 0x06
//0.725V
i2cset -f -y 15 0x24 0x00 0
i2ctransfer -f -y 15 w3@0x24 0x21 0x60 0x00
i2cset -f -y 15 0x24 0x00 2
i2ctransfer -f -y 15 w3@0x24 0x0D 0x12 0x0C
//0.725V
i2cset -f -y 15 0x24 0x00 1
i2ctransfer -f -y 15 w3@0x24 0x21 0x60 0x00
i2cset -f -y 15 0x24 0x00 2
i2ctransfer -f -y 15 w3@0x24 0x1D 0x0A 0x06
//1.455V
i2cset -f -y 13 0x29 0x00 0
i2ctransfer -f -y 13 w3@0x29 0x21 0xF2 0x00
i2cset -f -y 13 0x29 0x00 2
i2ctransfer -f -y 13 w3@0x29 0x0D 0x51 0x1E
//1.455V
i2cset -f -y 13 0x29 0x00 1
i2ctransfer -f -y 13 w3@0x29 0x21 0xF2 0x00
i2cset -f -y 13 0x29 0x00 2
i2ctransfer -f -y 13 w3@0x29 0x1D 0x29 0x0F
//0.695V
i2cset -f -y 13 0x27 0x00 0
i2ctransfer -f -y 13 w3@0x27 0x21 0x5A 0x00
i2cset -f -y 13 0x27 0x00 2
i2ctransfer -f -y 13 w3@0x27 0x0D 0x54 0x0B
//0.695V
i2cset -f -y 13 0x27 0x00 1
i2ctransfer -f -y 13 w3@0x27 0x21 0x5A 0x00
i2cset -f -y 13 0x27 0x00 2
i2ctransfer -f -y 13 w3@0x27 0x1D 0xAC 0x05
//0.695V
i2cset -f -y 15 0x28 0x00 0
i2ctransfer -f -y 15 w3@0x28 0x21 0x5A 0x00
i2cset -f -y 15 0x28 0x00 2
i2ctransfer -f -y 15 w3@0x28 0x0D 0x54 0x0B
//0.695V
i2cset -f -y 15 0x28 0x00 1
i2ctransfer -f -y 15 w3@0x28 0x21 0x5A 0x00
i2cset -f -y 15 0x28 0x00 2
i2ctransfer -f -y 15 w3@0x28 0x1D 0xAC 0x05
//0.753V
i2cset -f -y 13 0x20 0x00 0
i2ctransfer -f -y 13 w3@0x20 0x21 0x2D 0x01
//0.870V
i2cset -f -y 14 0x25 0x00 0
i2ctransfer -f -y 14 w3@0x25 0x21 0x7D 0x00
i2cset -f -y 14 0x25 0x00 2
i2ctransfer -f -y 14 w3@0x25 0x0D 0xB4 0x0F
//0.870V
i2cset -f -y 16 0x26 0x00 0
i2ctransfer -f -y 16 w3@0x26 0x21 0x7D 0x00
i2cset -f -y 16 0x26 0x00 2
i2ctransfer -f -y 16 w3@0x26 0x0D 0xB4 0x0F
//0.725V
i2cset -f -y 14 0x25 0x00 1
i2ctransfer -f -y 14 w3@0x25 0x21 0x60 0x00
i2cset -f -y 14 0x25 0x00 2
i2ctransfer -f -y 14 w3@0x25 0x1D 0x0A 0x06
//0.725V
i2cset -f -y 16 0x26 0x00 1
i2ctransfer -f -y 16 w3@0x26 0x21 0x60 0x00
i2cset -f -y 16 0x26 0x00 2
i2ctransfer -f -y 16 w3@0x26 0x1D 0x0A 0x06
//0.725V
i2cset -f -y 14 0x21 0x00 0
i2ctransfer -f -y 14 w3@0x21 0x21 0x60 0x00
i2cset -f -y 14 0x21 0x00 2
i2ctransfer -f -y 14 w3@0x21 0x0D 0x12 0x0C
//0.725V
i2cset -f -y 14 0x21 0x00 1
i2ctransfer -f -y 14 w3@0x21 0x21 0x60 0x00
i2cset -f -y 14 0x21 0x00 2
i2ctransfer -f -y 14 w3@0x21 0x1D 0x0A 0x06
//0.725V
i2cset -f -y 14 0x22 0x00 0
i2ctransfer -f -y 14 w3@0x22 0x21 0x60 0x00
i2cset -f -y 14 0x22 0x00 2
i2ctransfer -f -y 14 w3@0x22 0x0D 0x12 0x0C
//0.725V
i2cset -f -y 14 0x22 0x00 1
i2ctransfer -f -y 14 w3@0x22 0x21 0x60 0x00
i2cset -f -y 14 0x22 0x00 2
i2ctransfer -f -y 14 w3@0x22 0x1D 0x0A 0x06
//0.725V
i2cset -f -y 16 0x23 0x00 0
i2ctransfer -f -y 16 w3@0x23 0x21 0x60 0x00
i2cset -f -y 16 0x23 0x00 2
i2ctransfer -f -y 16 w3@0x23 0x0D 0x12 0x0C
//0.725V
i2cset -f -y 16 0x23 0x00 1
i2ctransfer -f -y 16 w3@0x23 0x21 0x60 0x00
i2cset -f -y 16 0x23 0x00 2
i2ctransfer -f -y 16 w3@0x23 0x1D 0x0A 0x06
//0.725V
i2cset -f -y 16 0x24 0x00 0
i2ctransfer -f -y 16 w3@0x24 0x21 0x60 0x00
i2cset -f -y 16 0x24 0x00 2
i2ctransfer -f -y 16 w3@0x24 0x0D 0x12 0x0C
//0.725V
i2cset -f -y 16 0x24 0x00 1
i2ctransfer -f -y 16 w3@0x24 0x21 0x60 0x00
i2cset -f -y 16 0x24 0x00 2
i2ctransfer -f -y 16 w3@0x24 0x1D 0x0A 0x06
//1.455V
i2cset -f -y 14 0x29 0x00 0
i2ctransfer -f -y 14 w3@0x29 0x21 0xF2 0x00
i2cset -f -y 14 0x29 0x00 2
i2ctransfer -f -y 14 w3@0x29 0x0D 0x51 0x1E
//1.455V
i2cset -f -y 14 0x29 0x00 1
i2ctransfer -f -y 14 w3@0x29 0x21 0xF2 0x00
i2cset -f -y 14 0x29 0x00 2
i2ctransfer -f -y 14 w3@0x29 0x1D 0x29 0x0F
//0.695V
i2cset -f -y 14 0x27 0x00 0
i2ctransfer -f -y 14 w3@0x27 0x21 0x5A 0x00
i2cset -f -y 14 0x27 0x00 2
i2ctransfer -f -y 14 w3@0x27 0x0D 0x54 0x0B
//0.695V
i2cset -f -y 14 0x27 0x00 1
i2ctransfer -f -y 14 w3@0x27 0x21 0x5A 0x00
i2cset -f -y 14 0x27 0x00 2
i2ctransfer -f -y 14 w3@0x27 0x1D 0xAC 0x05
//0.695V
i2cset -f -y 16 0x28 0x00 0
i2ctransfer -f -y 16 w3@0x28 0x21 0x5A 0x00
i2cset -f -y 16 0x28 0x00 2
i2ctransfer -f -y 16 w3@0x28 0x0D 0x54 0x0B
//0.695V
i2cset -f -y 16 0x28 0x00 1
i2ctransfer -f -y 16 w3@0x28 0x21 0x5A 0x00
i2cset -f -y 16 0x28 0x00 2
i2ctransfer -f -y 16 w3@0x28 0x1D 0xAC 0x05
//0.753V
i2cset -f -y 14 0x20 0x00 0
i2ctransfer -f -y 14 w3@0x20 0x21 0x2D 0x01