You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

2875 lines
130 KiB

import logging, argparse, time, sys, math, os
import yaml, json
from typing import List, Optional, Tuple
from pathlib import Path
import pandas as pd
from datetime import datetime
import pdb
import subprocess
import concurrent.futures
from concurrent.futures import ThreadPoolExecutor
import matplotlib.pyplot as plt
sys.path.append('C:\\ws\\tmp\\NexusBench-baihe-br\\nexusbench')
sys.path.append(os.path.dirname(__file__))
from parser.topology_parser import TopoMappingParser
from parser.ibias_rssi_map_parser import IbiasRssiMapParser
from toolbox.rssi_ibias_test import find_best_ibias_for_expected_rssi,find_best_ibias_for_expected_rssi_old
from gpu.biren.exp_util import DevWhiteRiverExp
from gpu.biren.smbus_http_util import SmbusHttpUtil
from gpu.biren.vuart_util import VuartUtil
from log.logger import Logger
from parser.transceiver_config_parser import TransceiverConfigParser, RegisterInfo
from toolbox.mgc_tuning_tool import MgcTuningTool, LaneErrInfo
import zlib
from functools import partial
from toolbox.regs_save_load_tool import LaneRegInfo, RouteInfo, SlotInfo, ExpInfo, HostRegInfo, OptRegValueManager
from toolbox.lowfreq_tuning_tool import LowFreqTuningTool
from toolbox.eq_tune_tool import EqTuneTool, RetimerLaneSetting
from toolbox.recv_ce_tool import RetimerLinkState, RecvCeTool
from toolbox.opt_reg_access_tool import OptRegAccessTool
from toolbox.prbs_tool import PrbsTool
print(zlib.ZLIB_VERSION)
def Authentication(bmc: DevWhiteRiverExp, exp_id: int, slot_id: int):
bmc.SetOpticalModuleRegs(exp_id, slot_id, 0, 0, 0x7a, 4, 'EA987654')
bmc.SetOpticalModuleRegs(exp_id, slot_id, 0, 0, 0xE9, 1, '04')
# bmc.SetOpticalModuleRegs(exp_id, slot_id, 0, 0xB4, 0x88, 1, '01')
def ReadModuleType(bmc: DevWhiteRiverExp, exp_id: int, slot_id: int):
res_data = bmc.GetOpticalModuleRegs(exp_id, slot_id, 0,0xB0, 0xB0, 9)
logging.debug(res_data)
bytes_data = bytes.fromhex(res_data)
type = bytes_data.decode('ascii', errors='ignore')
logging.debug(f'----------------SLOT: {slot_id}, Module type:{type}')
return type
def ExpColdReset(bmc: DevWhiteRiverExp, exp_id: int):
ret = bmc.ExpColdReset(exp_id)
logging.info(f'Exp cold reset, exp id: {exp_id}, result: {ret}')
def AutoTuneMGC(host: str, bmc: DevWhiteRiverExp, remote_bmc: DevWhiteRiverExp,
reg_tool: OptRegAccessTool, remote_reg_access_tool: OptRegAccessTool,
exp_id: int, slot_list: List[int], lane_list: List[int],
reg_table: TransceiverConfigParser, cmd: str, route_name: str):
logging.info(f"start auto tune MGC: exp_id={exp_id}, slots={slot_list}")
if rtmr_list == ['']:
retimers = [1,2,3,4]
else:
retimers = [int(x) for x in rtmr_list]
if remote_bmc is None:
remote_bmc = bmc
ibias_rssi_map_file = '/xz/gyou/nexusbench/main_data/ibias-rssi-map.json'
ibias_rssi_map = IbiasRssiMapParser(ibias_rssi_map_file)
prbs_tool = PrbsTool(bmc, remote_bmc, reg_tool, remote_reg_access_tool, route_name)
topo_map = TopoMappingParser("/xz/gyou/nexusbench/main_data/topo_mapping.yaml")
topo_map.parse()
logging.info('-------------step 3:')
mgc_tool = MgcTuningTool(host, reg_table, reg_tool, remote_reg_access_tool, bmc, topo_map, prbs_tool, route_name)
remote_mgc_tool = None
if remote_bmc != bmc:
remote_prbs_tool = PrbsTool(remote_bmc, bmc, remote_reg_access_tool, reg_tool, route_name)
remote_mgc_tool = MgcTuningTool(host, reg_table, remote_reg_access_tool, reg_tool, remote_bmc, topo_map, remote_prbs_tool, route_name)
logging.info('-------------step 4:')
# 对每个slot执行自动调优
# if route_name == '786-1-oneta' or route_name == '786-1-onoc2':
if cmd == 'mgc-auto-tune2':
mgc_tool.auto_tune2(exp_id, retimers)
elif cmd == 'tiapeak-auto-tune':
mgc_tool.auto_tia_peak_tune(exp_id, retimers)
elif cmd == 'lowfreq-auto-tune':
mgc_tool.auto_lowfreq_tune(exp_id, retimers)
elif cmd == 'highfreq-auto-tune':
mgc_tool.auto_highfreq_tune(exp_id, retimers)
elif cmd == 'opcurrent-auto-tune':
mgc_tool.auto_opcurrent_tune_test(exp_id, retimers)
elif cmd == 'opcurrent-auto-tune-test':
mgc_tool.auto_ibias_tune2(exp_id, retimers)
elif cmd == 'rt-ibias':
mgc_tool.rt_ibias(exp_id, retimers)
elif cmd == 'plot-mgc-vpeak':
prbs_tool.ResetRetimerAndEnablePrbs(exp_id, retimers, 9)
for slot in slot_list:
mgc_tool.debug_calc_target_vpeak_new(exp_id, slot)
if cmd == 'mgc-auto-tune':
prbs_tool.ResetRetimerAndEnablePrbs(exp_id, retimers, 9)
logging.info(f"---------- slot_list: {slot_list}")
for slot_id in slot_list:
if cmd == 'mgc-auto-tune':
mgc_tool.auto_tune(exp_id, slot_id, lane_list)
if remote_mgc_tool is not None:
remote_mgc_tool.auto_tune(exp_id, slot_id, lane_list)
# mgc_tool2 = MgcTuningTool(host, reg_table, reg_tool, remote_reg_access_tool, bmc, topo_map, prbs_tool, route_name)
# mgc_tool.auto_tune(exp_id, slot_id, lane_list)
elif cmd == 'mgc-manual-tune':
mgc_tool.manual_tune(exp_id, slot_id)
elif cmd == 'mgc-calc-target-vpeak':
mgc_tool.calc_target_vpeak_new(exp_id, slot_id, lane_list)
def AutoTuneLowFreq(host: str, bmc: DevWhiteRiverExp, exp_id: int, slot_list: list, reg_table_file: str, cmd: str):
logging.info(f"start auto tune low freq: exp_id={exp_id}, slots={slot_list}")
# 加载寄存器表
reg_table = TransceiverConfigParser(reg_table_file)
# 创建Low Freq 调优工具实例
lowfreq_tool = LowFreqTuningTool(host, reg_table, bmc)
logging.info('-------------step 4:')
# 对每个slot执行自动调优
for slot_id in slot_list:
lowfreq_tool.auto_tune(exp_id, slot_id)
def TuneHighFreq(reg_tool: OptRegAccessTool, exp_id: int):
# 3500 ~ 5500
reg_tool.write_opt_regs(exp_id, [0,1,2,3,4,5,6,7], [1,3,5], ['tia_peak'], '150')
reg_tool.write_opt_regs(exp_id, [0,1,2,3,4,5,6,7], [0,2,4,6,7], ['tia_peak'], '112')
reg_tool.write_opt_regs(exp_id, [0,1,2,3,4,5,6,7], [3,4], ['highfreq_eq'], '130')
reg_tool.write_opt_regs(exp_id, [0,1,2,3,4,5,6,7], [2,6,7], ['highfreq_eq'], '50')
reg_tool.write_opt_regs(exp_id, [0,1,2,3,4,5,6,7], [0], ['highfreq_eq'], '100')
reg_tool.write_opt_regs(exp_id, [0,1,2,3,4,5,6,7], [1], ['highfreq_eq'], '180')
reg_tool.write_opt_regs(exp_id, [0,1,2,3,4,5,6,7], [5], ['highfreq_eq'], '180')
reg_tool.write_opt_regs(exp_id, [0,1,2,3,4,5,6,7], [4,7], ['highfreq_eq'], '0')
reg_tool.write_opt_regs(exp_id, [0,1,2,3,4,5,6,7], [0,1,2,3,4,5,6,7], ['lowfreq_eq'], '128')
# exp_id 需替换为实际值
# reg_tool.write_opt_regs(exp_id, [0,1,2,3,4,5,6,7], [0,1,2,3,4,5,6,7], ['opcurrent'], '140')
# reg_tool.write_opt_regs(exp_id, [0,1,2,3,4,5,6,7], [0,1,2,3,4,5,6,7], ['highfreq_eq'], '200')
# reg_tool.write_opt_regs(exp_id, [0,1,2,3,4,5,6,7], [0,1,2,3,4,5,6,7], ['tia_peak'], '112')
# reg_tool.write_opt_regs(exp_id, [0], [3], ['highfreq_eq'], '100')
# reg_tool.write_opt_regs(exp_id, [1], [2], ['highfreq_eq'], '50')
# reg_tool.write_opt_regs(exp_id, [1], [5], ['highfreq_eq'], '100')
# reg_tool.write_opt_regs(exp_id, [1], [5], ['highfreq_eq'], '100')
# reg_tool.write_opt_regs(exp_id, [2], [0], ['highfreq_eq'], '100')
# reg_tool.write_opt_regs(exp_id, [2], [1], ['highfreq_eq'], '100')
# reg_tool.write_opt_regs(exp_id, [2], [3], ['highfreq_eq'], '0')
# reg_tool.write_opt_regs(exp_id, [2], [6], ['highfreq_eq'], '100')
# reg_tool.write_opt_regs(exp_id, [2], [7], ['highfreq_eq'], '100')
# reg_tool.write_opt_regs(exp_id, [3], [0], ['highfreq_eq'], '0')
# reg_tool.write_opt_regs(exp_id, [3], [1], ['highfreq_eq'], '100')
# reg_tool.write_opt_regs(exp_id, [3], [2], ['highfreq_eq'], '0')
# reg_tool.write_opt_regs(exp_id, [3], [4], ['highfreq_eq'], '0')
# reg_tool.write_opt_regs(exp_id, [3], [5], ['highfreq_eq'], '100')
# reg_tool.write_opt_regs(exp_id, [3], [6], ['highfreq_eq'], '0')
# reg_tool.write_opt_regs(exp_id, [3], [7], ['highfreq_eq'], '100')
# reg_tool.write_opt_regs(exp_id, [4], [0], ['highfreq_eq'], '50')
# reg_tool.write_opt_regs(exp_id, [4], [1], ['highfreq_eq'], '100')
# reg_tool.write_opt_regs(exp_id, [4], [2], ['highfreq_eq'], '100')
# reg_tool.write_opt_regs(exp_id, [4], [3], ['highfreq_eq'], '100')
# reg_tool.write_opt_regs(exp_id, [4], [5], ['highfreq_eq'], '0')
# reg_tool.write_opt_regs(exp_id, [4], [6], ['highfreq_eq'], '0')
# reg_tool.write_opt_regs(exp_id, [4], [7], ['highfreq_eq'], '100')
# reg_tool.write_opt_regs(exp_id, [5], [0], ['highfreq_eq'], '100')
# reg_tool.write_opt_regs(exp_id, [5], [1], ['highfreq_eq'], '100')
# reg_tool.write_opt_regs(exp_id, [5], [2], ['highfreq_eq'], '100')
# reg_tool.write_opt_regs(exp_id, [5], [3], ['highfreq_eq'], '0')
# reg_tool.write_opt_regs(exp_id, [5], [4], ['highfreq_eq'], '100')
# reg_tool.write_opt_regs(exp_id, [5], [5], ['highfreq_eq'], '50')
# reg_tool.write_opt_regs(exp_id, [5], [6], ['highfreq_eq'], '100')
# reg_tool.write_opt_regs(exp_id, [5], [7], ['highfreq_eq'], '100')
# reg_tool.write_opt_regs(exp_id, [6], [0], ['highfreq_eq'], '100')
# reg_tool.write_opt_regs(exp_id, [6], [1], ['highfreq_eq'], '100')
# reg_tool.write_opt_regs(exp_id, [6], [2], ['highfreq_eq'], '50')
# reg_tool.write_opt_regs(exp_id, [6], [4], ['highfreq_eq'], '0')
# reg_tool.write_opt_regs(exp_id, [6], [5], ['highfreq_eq'], '0')
# reg_tool.write_opt_regs(exp_id, [6], [6], ['highfreq_eq'], '0')
# reg_tool.write_opt_regs(exp_id, [7], [0], ['highfreq_eq'], '50')
# reg_tool.write_opt_regs(exp_id, [7], [1], ['highfreq_eq'], '100')
# reg_tool.write_opt_regs(exp_id, [7], [2], ['highfreq_eq'], '100')
# reg_tool.write_opt_regs(exp_id, [7], [3], ['highfreq_eq'], '100')
# reg_tool.write_opt_regs(exp_id, [7], [6], ['highfreq_eq'], '100')
# all_lane_reg_values: List[LaneRegInfo] = reg_tool.read_opt_regs(exp_id, [0,1,2,3,4,5,6,7], [0,1,2,3,4,5,6,7], ['highfreq_eq'])
# for lane_reg in all_lane_reg_values:
# if lane_reg.highfreq_eq >=200:
# reg_tool.write_opcurrent_reg(exp_id, lane_reg.slot_id, lane_reg.logic_lane, 150)
# elif lane_reg.highfreq_eq >=100:
# reg_tool.write_opcurrent_reg(exp_id, lane_reg.slot_id, lane_reg.logic_lane, 160)
# elif lane_reg.highfreq_eq >=50:
# reg_tool.write_opcurrent_reg(exp_id, lane_reg.slot_id, lane_reg.logic_lane, 165)
# elif lane_reg.highfreq_eq >=0:
# reg_tool.write_opcurrent_reg(exp_id, lane_reg.slot_id, lane_reg.logic_lane, 170)
# reg_tool.write_opt_regs(exp_id, [0,1,2,3,4,5,6,7], [0,1,2,3,4,5,6,7], ['opcurrent'], '138')
# # < 3000
# reg_tool.write_opt_regs(exp_id, [2], [4], ['highfreq_eq'], '200')
# # < 3000 -3500
# reg_tool.write_opt_regs(exp_id, [5,6,7], [4], ['highfreq_eq'], '150')
# reg_tool.write_opt_regs(exp_id, [3,7], [5], ['highfreq_eq'], '150')
# reg_tool.write_opt_regs(exp_id, [5], [1], ['highfreq_eq'], '150')
# # > 5500
# reg_tool.write_opt_regs(exp_id, [7], [3], ['highfreq_eq'], '0')
# reg_tool.write_opt_regs(exp_id, [0,1], [6], ['highfreq_eq'], '0')
# reg_tool.write_opt_regs(exp_id, [1,5], [2], ['highfreq_eq'], '0')
def SaveRegsToFile(reg_tool: OptRegAccessTool, host: str, exp_id: int,
slot_list: List[int], route_name: str,lane_list: List[int], regs: List[str],
save_file_name: str):
host_reg_info = OptRegValueManager.load_from_yaml(save_file_name)
if host_reg_info.host != '' and host_reg_info.host != host:
logging.error(f'save_file {save_file_name} is not match!')
return
if host_reg_info.host == '':
host_reg_info.host = host
for slot_id in slot_list:
logging.info(f'------------------2: regs: {regs}')
laneRegValueList = reg_tool.read_opt_registers_by_slot(exp_id, slot_id, lane_list, regs)
logging.info(f'------------------3: laneRegValueList: {laneRegValueList}')
# --- Find or Create ExpInfo ---
target_exp: Optional[ExpInfo] = None
for exp in host_reg_info.exps:
if exp.exp_id == exp_id:
target_exp = exp
break
if target_exp is None:
target_exp = ExpInfo(exp_id=exp_id)
host_reg_info.exps.append(target_exp)
logging.info(f"Created new ExpInfo for exp_id {exp_id}")
# --- Find or Create SlotInfo within ExpInfo ---
target_slot: Optional[SlotInfo] = None
for slot in target_exp.slots:
if slot.slot_id == slot_id:
target_slot = slot
break
if target_slot is None:
target_slot = SlotInfo(slot_id=slot_id)
target_exp.slots.append(target_slot)
logging.info(f"Created new SlotInfo for slot_id {slot_id}")
if route_name == '':
logging.error(f'route name is empty!')
exit(0)
# --- Find or Update/Create RouteInfo within SlotInfo ---
route_found = False
for route in target_slot.modes:
if route.mode_name == route_name:
route.lanes = laneRegValueList # Overwrite existing lanes
route_found = True
logging.info(f"Updated lanes for existing RouteInfo '{route_name}'")
break # Exit the loop once found and updated
if not route_found:
# If the route was not found, create a new one and add it
new_route = RouteInfo(mode_name=route_name, lanes=laneRegValueList)
target_slot.modes.append(new_route)
logging.info(f"Added new RouteInfo '{route_name}' with lanes")
# --- Save the updated host_reg_info ---
OptRegValueManager.save_to_yaml(host_reg_info, save_file_name)
def LoadRegsToFile(reg_tool: OptRegAccessTool, host: str, exp_id: int, slot_list: List[int],
route_name: str, regs: List[str], load_file_name: str):
logging.info(f'-----------slot_list: {slot_list}')
host_reg_info = OptRegValueManager.load_from_yaml(load_file_name)
# logging.info(host_reg_info)
if host_reg_info.host != host or host_reg_info.host == '':
logging.error(f'load_file {load_file_name} is not match!')
return
for slot_id in slot_list:
logging.info(f'------------------2: regs: {regs}')
for exp in host_reg_info.exps:
if exp_id == exp.exp_id:
for save_slot in exp.slots:
if slot_id == save_slot.slot_id:
for save_mode in save_slot.modes:
if route_name == save_mode.mode_name:
for lane_info in save_mode.lanes:
params_to_write = {
'mgc': lane_info.mgc,
# 'vpeak': lane_info.vpeak,
'tia_peak': lane_info.tia_peak,
'ibias': lane_info.ibias,
'ipcurrent': lane_info.ipcurrent,
'opcurrent': lane_info.opcurrent,
'lowfreq_eq': lane_info.lowfreq_eq,
'highfreq_eq': lane_info.highfreq_eq,
'vgc_set': lane_info.vgc_set,
# 'drv_vpeak': lane_info.drv_vpeak
}
for reg_name, param_value in params_to_write.items():
if param_value == -1:
continue
try:
reg_tool.write_opt_reg(exp_id, slot_id, lane_info.logic_lane, param_value, reg_name)
logging.info(f"Written {reg_name}={param_value} to exp={exp.exp_id}, slot={slot_id}, lane={lane_info.logic_lane}")
time.sleep(0.05)
except Exception as e:
print(f"Error writing {reg_name} for lane {lane_info.logic_lane}: {e}")
break
break
break
def get_search_values(min_val: int, max_val: int, step: int) -> List[int]:
# 生成所有可能的值
all_values = list(range(min_val, max_val + 1, step))
if not all_values:
return []
# 找到中间值的索引
mid_index = len(all_values) // 2
mid_val = all_values[mid_index]
# 从中间开始,交替向左右添加
search_values = [mid_val]
left_index = mid_index - 1
right_index = mid_index + 1
# 交替从左右两边取值
take_from_right = True # 先从右边开始(可调整)
while left_index >= 0 or right_index < len(all_values):
if take_from_right and right_index < len(all_values):
search_values.append(all_values[right_index])
right_index += 1
elif left_index >= 0: # 如果右边取完了或轮到左边
search_values.append(all_values[left_index])
left_index -= 1
# 切换方向
take_from_right = not take_from_right
logging.info(f"Search order for lane {search_values}")
return search_values
# def AutoTuneIbias(host: str, bmc: DevWhiteRiverExp, exp_id: int, slot_list: list, lane_list: List[int],
# reg_table_parser: TransceiverConfigParser, route_name: str):
# ibias_rssi_map_file = '/xz/gyou/nexusbench/main_data/ibias-rssi-map.json'
# ibias_rssi_map = IbiasRssiMapParser(ibias_rssi_map_file)
# if len(lane_list) == 8: # all, 8 is default value
# lane_list = [0,1,2,3]
# logging.info(f'lane_list: {lane_list}')
# substandard_slot = []
# for slot_id in slot_list:
# logging.info(f"start auto tune ibias: exp_id={exp_id}, slots={slot_list}")
# for ibias_lane in lane_list:
# rssi_lanes = ibias_rssi_map.get_rssi_lane(route_name, ibias_lane)
# if rssi_lanes is None:
# logging.error(f'-----------------rssi lanes is none')
# continue
# # SetPrivateLinkRegister(bmc, host, exp_id, slot_id, [ibias_lane], ['ibias'], reg_table_file, )
# # 一个一个ibias的校准
# ibias_reg = reg_table_parser.get_register_by_logic_lane("ibias", ibias_lane)
# if not ibias_reg or not ibias_reg.valid_range or \
# not ibias_reg.step or len(ibias_reg.valid_range) < 2:
# logging.error(f'-----------invalid ibias_reg or valid_range or step for ibias_reg')
# continue
# min_val = ibias_reg.valid_range[0]
# max_val = ibias_reg.valid_range[1]
# step = ibias_reg.step
# logging.info(f'-------min_val: {min_val}, max_val: {max_val}, step: {step}')
# #search_values = get_search_values(min_val, max_val, step)
# search_values = list(range(min_val, max_val + 1, step))
# # search_values.sort(reverse=True)
# logging.info(f'-------search_values: {search_values}')
# measurements_map1 = []
# measurements_map2 = []
# expect_value = -1
# for ibias_value in search_values:
# value_hex_str = f"{ibias_value:04X}"
# result = bmc.SetOpticalModuleRegs(exp_id, slot_id, ibias_reg.bank, ibias_reg.page,
# ibias_reg.offset, 2, value_hex_str)
# for index, rssi_lane in enumerate(rssi_lanes):
# reg = reg_table_parser.get_register_by_logic_lane("rssi", rssi_lane)
# if not reg or not reg.valid_range:
# logging.error(f'------------- rssi reg or valid range is none')
# continue
# value = bmc.GetOpticalModuleRegs(exp_id, slot_id, reg.bank, reg.page, reg.offset, 2)
# rssi_value = int(value, 16)
# dbm = round(10 * math.log10(rssi_value / 10000), 3)
# logging.info(f'----------rssi_lane: {rssi_lane}, ibias: {ibias_value}, rssi value: {rssi_value}, dbm: {dbm}')
# min_val = reg.valid_range[0]
# max_val = reg.valid_range[1]
# expect_value = reg.value
# if expect_value is None:
# expect_value = 7080
# if rssi_value >= int(min_val) and rssi_value <= int(max_val):
# if index == 0:
# measurements_map1.append((ibias_value, rssi_value))
# elif index == 1:
# measurements_map2.append((ibias_value, rssi_value))
# # logging.info(f'rssi1 map: {measurements_map1}')
# # logging.info(f'rssi1 map: {measurements_map2}')
# logging.info(f'rssi1 map: {measurements_map1}')
# logging.info(f'rssi2 map: {measurements_map2}')
# result = find_best_ibias_for_expected_rssi(measurements_map1, measurements_map2, expect_value)
# if result:
# ibias, rssi1, rssi2 = result
# logging.info(f"best ibias: {ibias}")
# logging.info(f" RSSI1: {rssi1}")
# logging.info(f" RSSI2: {rssi2}")
# value_hex_str = f"{ibias:04X}"
# logging.info(f'set best ibias value')
# result = bmc.SetOpticalModuleRegs(exp_id, slot_id, ibias_reg.bank, ibias_reg.page,
# ibias_reg.offset, 2, value_hex_str)
# else:
# logging.error("No ibias value present in both maps was found.")
# substandard_slot.append(slot_id)
# logging.info("Substandard SLOT:")
# for slot in substandard_slot:
# logging.error(f"exp: {exp_id}, slot: {slot}, MODULE: QDD{slot + 1}")
def AutoTuneIbiasOnetNew(host: str, bmc: DevWhiteRiverExp, exp_id: int, slot_list: list, lane_list: List[int],
remote_bmc: DevWhiteRiverExp, local_reg_tool: OptRegAccessTool, remote_reg_tool: OptRegAccessTool,
reg_table_file: str, route_name: str, ibias_rssi_map: IbiasRssiMapParser):
reg_table = TransceiverConfigParser(reg_table_file)
if len(lane_list) == 8: # all, 8 is default value
lane_list = [0,1,2,3]
logging.info(f'lane_list: {lane_list}')
substandard_slot = []
for slot_id in slot_list:
logging.info(f"start auto tune ibias: exp_id={exp_id}, slots={slot_list}")
for ibias_lane in lane_list:
rssi_lanes = ibias_rssi_map.get_rssi_lane(route_name, ibias_lane)
if rssi_lanes is None:
logging.error(f'-----------------rssi lanes is none')
continue
# 一个一个ibias的校准
ibias_reg = reg_table.get_register_by_lane("ibias", ibias_lane)
if not ibias_reg or not ibias_reg.valid_range or \
not ibias_reg.step or len(ibias_reg.valid_range) < 2:
logging.error(f'-----------invalid ibias_reg or valid_range or step for ibias_reg')
continue
min_val = ibias_reg.valid_range[0]
max_val = ibias_reg.valid_range[1]
step = ibias_reg.step
logging.info(f'-------min_val: {min_val}, max_val: {max_val}, step: {step}')
#search_values = get_search_values(min_val, max_val, step)
search_values = list(range(min_val, max_val + 1, step))
# search_values.sort(reverse=True)
logging.info(f'-------search_values: {search_values}')
measurements_map1 = []
measurements_map2 = []
expect_value = -1
for ibias_value in search_values:
value_hex_str = f"{ibias_value:04X}"
time.sleep(0.05)
result = remote_bmc.SetOpticalModuleRegs(exp_id, slot_id, ibias_reg.bank, ibias_reg.page,
ibias_reg.offset, 2, value_hex_str)
time.sleep(0.2)
for index, rssi_lane in enumerate(rssi_lanes):
reg = reg_table.get_register_by_lane("rssi", rssi_lane)
if not reg or not reg.valid_range:
logging.error(f'------------- rssi reg or valid range is none')
continue
value = bmc.GetOpticalModuleRegs(exp_id, slot_id, reg.bank, reg.page, reg.offset, 2)
rssi_value = int(value, 16)
dbm = round(10 * math.log10(rssi_value / 10000), 3)
logging.info(f'{bmc.m_smbus.server_id}<-{remote_bmc.m_smbus.server_id} slot:{slot_id}, ibias_lane: {ibias_lane}, ibias: {ibias_value}, rssi_lane: {rssi_lane}, rssi value: {rssi_value}, dbm: {dbm}')
min_val = reg.valid_range[0]
max_val = reg.valid_range[1]
# expect_value = reg.value
# if expect_value is None:
expect_value = 5623 #-2.5, old 6310 (-2.0)
# if rssi_value >= int(min_val) and rssi_value <= int(max_val):
if index == 0:
measurements_map1.append((ibias_value, rssi_value))
elif index == 1:
measurements_map2.append((ibias_value, rssi_value))
# logging.info(f'rssi1 map: {measurements_map1}')
# logging.info(f'rssi1 map: {measurements_map2}')
logging.info(f'rssi1 map: {measurements_map1}')
logging.info(f'rssi2 map: {measurements_map2}')
dbm = round(10 * math.log10(expect_value / 10000), 3)
logging.info(f'expect_value: {expect_value}, {dbm}dbm')
result = find_best_ibias_for_expected_rssi(measurements_map1, measurements_map2, expect_value)
# rssi_val1 = next((r for i, r in measurements_map1 if i == 2047), None)
# rssi_val2 = next((r for i, r in measurements_map2 if i == 2047), None)
# dbm1 = round(10 * math.log10(rssi_val1 / 10000), 3)
# dbm2 = round(10 * math.log10(rssi_val2 / 10000), 3)
# if dbm1 < -4 or dbm2 < -4:
# substandard_slot.append(slot_id)
# break
# elif dbm1 < -3.5 or dbm2 < -3.5: # -3.5 ~ -4
# except_dbm = -2.8
# expect_value = int(10000 * (10 ** (except_dbm / 10)))
# elif dbm1 < -2.5 or dbm2 < -2.5: # -2.5 ~ -3.5
# except_dbm = -2.7
# expect_value = int(10000 * (10 ** (except_dbm / 10)))
# elif dbm1 < -1.5 or dbm2 < -1.5: # -1.5 ~ -2.5
# except_dbm = -1.5
# expect_value = int(10000 * (10 ** (except_dbm / 10)))
if result:
ibias, rssi1, rssi2 = result
if ibias < 2500:
except_dbm = -1.6
expect_value = int(10000 * (10 ** (except_dbm / 10)))
logging.info(f' < 2500, use except_dbm {except_dbm}, old ibias: {ibias}')
result = find_best_ibias_for_expected_rssi_old(measurements_map1, measurements_map2, expect_value)
ibias, rssi1, rssi2 = result
if ibias > 2900:
except_dbm = -2.8
expect_value = int(10000 * (10 ** (except_dbm / 10)))
logging.info(f' > 2900, use except_dbm {except_dbm}, old ibias: {ibias}')
result = find_best_ibias_for_expected_rssi(measurements_map1, measurements_map2, expect_value)
ibias, rssi1, rssi2 = result
logging.info(f"{bmc.m_smbus.server_id}->{remote_bmc.m_smbus.server_id} ibias_lane: {ibias_lane}, best ibias: {ibias}")
logging.info(f"rssi_lane: {rssi_lanes[0]}, RSSI1: {rssi1}")
logging.info(f"rssi_lane: {rssi_lanes[1]} RSSI2: {rssi2}")
value_hex_str = f"{ibias:04X}"
logging.info(f'set best ibias value')
time.sleep(0.05)
result = remote_bmc.SetOpticalModuleRegs(exp_id, slot_id, ibias_reg.bank, ibias_reg.page,
ibias_reg.offset, 2, value_hex_str)
else:
logging.warning(f'default expect_value{expect_value} not match! use 7586(-1.2dbm)')
expect_value = 7586 # -1.2
result = find_best_ibias_for_expected_rssi(measurements_map1, measurements_map2, expect_value)
if result:
ibias, rssi1, rssi2 = result
if ibias <= 2547:
logging.info(f"{bmc.m_smbus.server_id}->{remote_bmc.m_smbus.server_id} ibias_lane: {ibias_lane}, best ibias: {ibias}")
logging.info(f"rssi_lane: {rssi_lanes[0]}, RSSI1: {rssi1}")
logging.info(f"rssi_lane: {rssi_lanes[1]} RSSI2: {rssi2}")
value_hex_str = f"{ibias:04X}"
logging.info(f'set best ibias value')
time.sleep(0.05)
result = remote_bmc.SetOpticalModuleRegs(exp_id, slot_id, ibias_reg.bank, ibias_reg.page,
ibias_reg.offset, 2, value_hex_str)
else:
logging.error("No ibias value present in both maps was found.")
substandard_slot.append(slot_id)
else:
logging.error("No ibias value present in both maps was found.")
substandard_slot.append(slot_id)
logging.info("Substandard SLOT:")
for slot in substandard_slot:
logging.error(f"exp: {exp_id}, slot: {slot}, MODULE: QDD{slot + 1}")
def AutoTuneIbiasOnet(host: str, bmc: DevWhiteRiverExp, exp_id: int, slot_list: list, lane_list: List[int],
remote_bmc: DevWhiteRiverExp, reg_table_file: str, route_name: str, ibias_rssi_map: IbiasRssiMapParser):
reg_table = TransceiverConfigParser(reg_table_file)
if len(lane_list) == 8: # all, 8 is default value
lane_list = [0,1,2,3]
logging.info(f'lane_list: {lane_list}')
substandard_slot = []
for slot_id in slot_list:
remote_bmc.SetOpticalModuleRegs(exp_id, slot_id, 0, 0xB4, 0x88, 1, '00')
time.sleep(0.05)
for slot_id in slot_list:
logging.info(f"start auto tune ibias: exp_id={exp_id}, slots={slot_list}")
for ibias_lane in lane_list:
rssi_lanes = ibias_rssi_map.get_rssi_lane(route_name, ibias_lane)
if rssi_lanes is None:
logging.error(f'-----------------rssi lanes is none')
continue
# 一个一个ibias的校准
ibias_reg = reg_table.get_register_by_lane("ibias", ibias_lane)
if not ibias_reg or not ibias_reg.valid_range or \
not ibias_reg.step or len(ibias_reg.valid_range) < 2:
logging.error(f'-----------invalid ibias_reg or valid_range or step for ibias_reg')
continue
min_val = ibias_reg.valid_range[0]
max_val = ibias_reg.valid_range[1]
step = ibias_reg.step
logging.info(f'-------min_val: {min_val}, max_val: {max_val}, step: {step}')
#search_values = get_search_values(min_val, max_val, step)
search_values = list(range(min_val, max_val + 1, step))
# search_values.sort(reverse=True)
logging.info(f'-------search_values: {search_values}')
measurements_map1 = []
measurements_map2 = []
expect_value = -1
for ibias_value in search_values:
value_hex_str = f"{ibias_value:04X}"
time.sleep(0.05)
result = remote_bmc.SetOpticalModuleRegs(exp_id, slot_id, ibias_reg.bank, ibias_reg.page,
ibias_reg.offset, 2, value_hex_str)
time.sleep(0.2)
for index, rssi_lane in enumerate(rssi_lanes):
reg = reg_table.get_register_by_lane("rssi", rssi_lane)
if not reg or not reg.valid_range:
logging.error(f'------------- rssi reg or valid range is none')
continue
value = bmc.GetOpticalModuleRegs(exp_id, slot_id, reg.bank, reg.page, reg.offset, 2)
rssi_value = int(value, 16)
dbm = round(10 * math.log10(rssi_value / 10000), 3)
logging.info(f'{bmc.m_smbus.server_id}<-{remote_bmc.m_smbus.server_id} slot:{slot_id}, ibias_lane: {ibias_lane}, ibias: {ibias_value}, rssi_lane: {rssi_lane}, rssi value: {rssi_value}, dbm: {dbm}')
min_val = reg.valid_range[0]
max_val = reg.valid_range[1]
# expect_value = reg.value
# if expect_value is None:
expect_value = 5623 #-2.5, old 6310 (-2.0)
# if rssi_value >= int(min_val) and rssi_value <= int(max_val):
if index == 0:
measurements_map1.append((ibias_value, rssi_value))
elif index == 1:
measurements_map2.append((ibias_value, rssi_value))
# logging.info(f'rssi1 map: {measurements_map1}')
# logging.info(f'rssi1 map: {measurements_map2}')
logging.info(f'rssi1 map: {measurements_map1}')
logging.info(f'rssi2 map: {measurements_map2}')
dbm = round(10 * math.log10(expect_value / 10000), 3)
logging.info(f'expect_value: {expect_value}, {dbm}dbm')
result = find_best_ibias_for_expected_rssi(measurements_map1, measurements_map2, expect_value)
# rssi_val1 = next((r for i, r in measurements_map1 if i == 2047), None)
# rssi_val2 = next((r for i, r in measurements_map2 if i == 2047), None)
# dbm1 = round(10 * math.log10(rssi_val1 / 10000), 3)
# dbm2 = round(10 * math.log10(rssi_val2 / 10000), 3)
# if dbm1 < -4 or dbm2 < -4:
# substandard_slot.append(slot_id)
# break
# elif dbm1 < -3.5 or dbm2 < -3.5: # -3.5 ~ -4
# except_dbm = -2.8
# expect_value = int(10000 * (10 ** (except_dbm / 10)))
# elif dbm1 < -2.5 or dbm2 < -2.5: # -2.5 ~ -3.5
# except_dbm = -2.7
# expect_value = int(10000 * (10 ** (except_dbm / 10)))
# elif dbm1 < -1.5 or dbm2 < -1.5: # -1.5 ~ -2.5
# except_dbm = -1.5
# expect_value = int(10000 * (10 ** (except_dbm / 10)))
if result:
ibias, rssi1, rssi2 = result
if ibias < 2500:
except_dbm = -1.6
expect_value = int(10000 * (10 ** (except_dbm / 10)))
logging.info(f' < 2500, use except_dbm {except_dbm}, old ibias: {ibias}')
result = find_best_ibias_for_expected_rssi_old(measurements_map1, measurements_map2, expect_value)
ibias, rssi1, rssi2 = result
if ibias > 2900:
except_dbm = -2.8
expect_value = int(10000 * (10 ** (except_dbm / 10)))
logging.info(f' > 2900, use except_dbm {except_dbm}, old ibias: {ibias}')
result = find_best_ibias_for_expected_rssi(measurements_map1, measurements_map2, expect_value)
ibias, rssi1, rssi2 = result
logging.info(f"{bmc.m_smbus.server_id}->{remote_bmc.m_smbus.server_id} ibias_lane: {ibias_lane}, best ibias: {ibias}")
logging.info(f"rssi_lane: {rssi_lanes[0]}, RSSI1: {rssi1}")
logging.info(f"rssi_lane: {rssi_lanes[1]} RSSI2: {rssi2}")
value_hex_str = f"{ibias:04X}"
logging.info(f'set best ibias value')
time.sleep(0.05)
result = remote_bmc.SetOpticalModuleRegs(exp_id, slot_id, ibias_reg.bank, ibias_reg.page,
ibias_reg.offset, 2, value_hex_str)
else:
logging.warning(f'default expect_value{expect_value} not match! use 7586(-1.2dbm)')
expect_value = 7586 # -1.2
result = find_best_ibias_for_expected_rssi(measurements_map1, measurements_map2, expect_value)
if result:
ibias, rssi1, rssi2 = result
if ibias <= 2547:
logging.info(f"{bmc.m_smbus.server_id}->{remote_bmc.m_smbus.server_id} ibias_lane: {ibias_lane}, best ibias: {ibias}")
logging.info(f"rssi_lane: {rssi_lanes[0]}, RSSI1: {rssi1}")
logging.info(f"rssi_lane: {rssi_lanes[1]} RSSI2: {rssi2}")
value_hex_str = f"{ibias:04X}"
logging.info(f'set best ibias value')
time.sleep(0.05)
result = remote_bmc.SetOpticalModuleRegs(exp_id, slot_id, ibias_reg.bank, ibias_reg.page,
ibias_reg.offset, 2, value_hex_str)
else:
logging.error("No ibias value present in both maps was found.")
substandard_slot.append(slot_id)
else:
logging.error("No ibias value present in both maps was found.")
substandard_slot.append(slot_id)
logging.info("Substandard SLOT:")
for slot in substandard_slot:
logging.error(f"exp: {exp_id}, slot: {slot}, MODULE: QDD{slot + 1}")
# reg_access_tool, bmc, host, exp_id, slot_list, ibias_rssi_map, route_name
def RssiCheck(reg_tool: OptRegAccessTool, remote_reg_tool: OptRegAccessTool,
bmc: DevWhiteRiverExp, host: str, exp_id: int, slot_list: List[int],
ibias_rssi_map: IbiasRssiMapParser, route_name):
bad_modules = []
for slot_id in slot_list:
for ibias_lane in [0, 1, 2, 3]:
ibias_value = remote_reg_tool.read_ibias_reg_by_ibias_lane(exp_id, slot_id, ibias_lane)
rssi_lanes = ibias_rssi_map.get_rssi_lane(route_name, ibias_lane)
if rssi_lanes is None:
logging.error(f'RSSI lanes not found for exp: {exp_id}, slot: {slot_id}, ibias_lane: {ibias_lane}')
continue
rssi1_value = reg_tool.read_rssi_reg(exp_id, slot_id, rssi_lanes[0])
rssi2_value = reg_tool.read_rssi_reg(exp_id, slot_id, rssi_lanes[1])
dbm1 = round(10 * math.log10(rssi1_value / 10000), 3)
dbm2 = round(10 * math.log10(rssi2_value / 10000), 3)
if abs(dbm1 - dbm2) > 2.0:
bad_modules.append({
'exp_id': exp_id,
'slot_id': slot_id,
'ibias_lane': ibias_lane,
'rssi1_lane': rssi_lanes[0],
'rssi2_lane': rssi_lanes[1],
'ibias': ibias_value,
'dbm1': dbm1,
'dbm2': dbm2,
'diff': abs(dbm1 - dbm2)
})
if ibias_value > 2800 and ((dbm1 < -3) or (dbm2 < -3)):
bad_modules.append({
'exp_id': exp_id,
'slot_id': slot_id,
'ibias_lane': ibias_lane,
'rssi1_lane': rssi_lanes[0],
'rssi2_lane': rssi_lanes[1],
'ibias': ibias_value,
'dbm1': dbm1,
'dbm2': dbm2,
'diff': abs(dbm1 - dbm2)
})
if ibias_value > 3000 and ((dbm1 < -2.5) or (dbm2 < -2.5)):
bad_modules.append({
'exp_id': exp_id,
'slot_id': slot_id,
'ibias_lane': ibias_lane,
'rssi1_lane': rssi_lanes[0],
'rssi2_lane': rssi_lanes[1],
'ibias': ibias_value,
'dbm1': dbm1,
'dbm2': dbm2,
'diff': abs(dbm1 - dbm2)
})
if bad_modules:
logging.error("❌ Found bad optical modules (|dBm1 - dBm2| > 2.0):")
for mod in bad_modules:
logging.error(
f"host:{host}, exp:{mod['exp_id']}, slot:{mod['slot_id']},"
f"ibias_lane:{mod['ibias_lane']} "
f"ibias:{mod['ibias']} "
f"rssi_lane{mod['rssi1_lane']}={mod['dbm1']}, "
f"rssi_lane{mod['rssi2_lane']}={mod['dbm2']} "
f"(diff:{mod['diff']:.3f}) → BAD"
)
else:
logging.info("✅ All modules passed RSSI consistency check.")
def TiaPeakTune(reg_tool: OptRegAccessTool, bmc: DevWhiteRiverExp, host: str, exp_id: int, slot_list: List[int],
lane_list: List[int], regs: List[str]):
# all
reg_tool.write_opt_regs(exp_id, [0,1,2,3,4,5,6,7], [0,1,2,3,4,5,6,7], ['tia_peak'], '138')
# # > 5500
# reg_tool.write_opt_regs(exp_id, [0,1,2,3,4,5,6,7], [0], ['tia_peak'], '100')
# reg_tool.write_opt_regs(exp_id, [2], [3], ['tia_peak'], '100')
# reg_tool.write_opt_regs(exp_id, [0,1], [2], ['tia_peak'], '100')
# # > 4500 - 5500
# reg_tool.write_opt_regs(exp_id, [0,1,3,4,5,6,7], [3], ['tia_peak'], '150')
# reg_tool.write_opt_regs(exp_id, [0], [6], ['tia_peak'], '150')
# reg_tool.write_opt_regs(exp_id, [2,3,4,5,6,7], [2], ['tia_peak'], '150')
# # < 3500
# reg_tool.write_opt_regs(exp_id, [3,4,5], [4], ['tia_peak'], '200')
# reg_tool.write_opt_regs(exp_id, [4,5,6], [5], ['tia_peak'], '200')
# reg_tool.write_opt_regs(exp_id, [0,2,3], [1], ['tia_peak'], '200')
def MgcTune(reg_tool: OptRegAccessTool, bmc: DevWhiteRiverExp, host: str, exp_id: int, slot_list: List[int],
lane_list: List[int], reg_wt_value):
if reg_wt_value != '':
ext_value = int(reg_wt_value)
else:
ext_value = 5
all_lane_reg_values = reg_tool.read_opt_regs(exp_id, [0,1,2,3,4,5,6,7], [0,1,2,3,4,5,6,7], ['mgc'])
# all_lane_reg_values = reg_tool.read_opt_regs(exp_id, [0,1,2,3,4,5,6,7], [1,5], ['mgc'])
# logging.info(f'ret data: {all_lane_reg_values}')
for lane_reg in all_lane_reg_values:
# logging.info(f'------step 1')
if lane_reg.mgc != -1:
# logging.info(f'------step 2')
new_mgc = lane_reg.mgc - ext_value
# logging.info(f'------step 3, new_mgc: {new_mgc}')
reg_tool.write_mgc_reg(exp_id, lane_reg.slot_id, lane_reg.logic_lane, new_mgc)
# logging.info(f'------step 4')
reg_tool.write_confirm_reg(exp_id, lane_reg.slot_id)
# all_lane_reg_values = reg_tool.read_opt_regs(exp_id, [0,1,2,3,4,5,6,7], [0], ['mgc'])
# for lane_reg in all_lane_reg_values:
# if lane_reg.mgc != -1:
# new_mgc = lane_reg.mgc + ext_value
# reg_tool.write_mgc_reg(exp_id, lane_reg.slot_id, lane_reg.logic_lane, new_mgc)
# reg_tool.write_confirm_reg(exp_id, lane_reg.slot_id)
# all_lane_reg_values = reg_tool.read_opt_regs(exp_id, [2], [3], ['mgc'])
# for lane_reg in all_lane_reg_values:
# if lane_reg.mgc != -1:
# new_mgc = lane_reg.mgc + ext_value
# reg_tool.write_mgc_reg(exp_id, lane_reg.slot_id, lane_reg.logic_lane, new_mgc)
# reg_tool.write_confirm_reg(exp_id, lane_reg.slot_id)
# all_lane_reg_values = reg_tool.read_opt_regs(exp_id, [0,1], [2], ['mgc'])
# for lane_reg in all_lane_reg_values:
# if lane_reg.mgc != -1:
# new_mgc = lane_reg.mgc + ext_value
# reg_tool.write_mgc_reg(exp_id, lane_reg.slot_id, lane_reg.logic_lane, new_mgc)
# reg_tool.write_confirm_reg(exp_id, lane_reg.slot_id)
def SwaAutoTune(host: str, local_bmc: DevWhiteRiverExp, exp_id: int, slot_list: list, lane_list: List[int],
remote_bmc: DevWhiteRiverExp, route_name: str,
local_reg_tool: OptRegAccessTool, remote_reg_tool: OptRegAccessTool):
logging.info(f'lane_list: {lane_list}')
ibias_rssi_map_file = '/xz/gyou/nexusbench/main_data/ibias-rssi-map.json'
ibias_rssi_map = IbiasRssiMapParser(ibias_rssi_map_file)
topo_map = TopoMappingParser("/xz/gyou/nexusbench/main_data/topo_mapping.yaml")
logging.info(f"start auto tune eq: exp_id={exp_id}, slots={slot_list}")
for slot_id in slot_list:
local_bmc.SetOpticalModuleRegs(exp_id, slot_id, 0x00, 0xD0, 0x8A, 1, "01")
for lane_id in lane_list:
max_index, max_value, min_index, min_value = get_swa_adc_per_lane(local_bmc, exp_id, slot_id, lane_id)
if max_value != 0 and min_value != 0:
# swa: max -> onoc min-> onet, swb: max -> onetb
time.sleep(0.05)
local_reg_tool.write_opt_reg(exp_id, slot_id, lane_id, max_index, 'swa_onoc_h')
time.sleep(0.08)
local_reg_tool.write_opt_reg(exp_id, slot_id, lane_id, max_index, 'swa_onoc_m')
time.sleep(0.08)
local_reg_tool.write_opt_reg(exp_id, slot_id, lane_id, max_index, 'swa_onoc_l')
time.sleep(0.08)
local_reg_tool.write_opt_reg(exp_id, slot_id, lane_id, min_index, 'swa_onet_h')
time.sleep(0.08)
local_reg_tool.write_opt_reg(exp_id, slot_id, lane_id, min_index, 'swa_onet_m')
time.sleep(0.08)
local_reg_tool.write_opt_reg(exp_id, slot_id, lane_id, min_index, 'swa_onet_l')
time.sleep(0.08)
else:
logging.error(f'Read swa pic failed')
def SwbAutoTune(host: str, local_bmc: DevWhiteRiverExp, exp_id: int, slot_list: list, lane_list: List[int],
remote_bmc: DevWhiteRiverExp, route_name: str,
local_reg_tool: OptRegAccessTool, remote_reg_tool: OptRegAccessTool):
logging.info(f'lane_list: {lane_list}')
ibias_rssi_map_file = '/xz/gyou/nexusbench/main_data/ibias-rssi-map.json'
ibias_rssi_map = IbiasRssiMapParser(ibias_rssi_map_file)
topo_map = TopoMappingParser("/xz/gyou/nexusbench/main_data/topo_mapping.yaml")
logging.info(f"start auto tune eq: exp_id={exp_id}, slots={slot_list}")
for slot_id in slot_list:
local_bmc.SetOpticalModuleRegs(exp_id, slot_id, 0x00, 0xD0, 0x8A, 1, "01")
for lane_id in lane_list:
max_index, max_value, min_index, min_value = get_swb_adc_per_lane(local_bmc, exp_id, slot_id, lane_id)
if max_value != 0 and min_value != 0:
# swa: max -> onoc min-> onet, swb: max -> onetb
time.sleep(0.05)
local_reg_tool.write_opt_reg(exp_id, slot_id, lane_id, max_index, 'swb_onetb_h')
time.sleep(0.08)
local_reg_tool.write_opt_reg(exp_id, slot_id, lane_id, max_index, 'swb_onetb_m')
time.sleep(0.08)
local_reg_tool.write_opt_reg(exp_id, slot_id, lane_id, max_index, 'swb_onetb_l')
time.sleep(0.08)
local_reg_tool.write_opt_reg(exp_id, slot_id, lane_id, min_index, 'swb_oneta_h')
time.sleep(0.08)
local_reg_tool.write_opt_reg(exp_id, slot_id, lane_id, min_index, 'swb_oneta_m')
time.sleep(0.08)
local_reg_tool.write_opt_reg(exp_id, slot_id, lane_id, min_index, 'swb_oneta_l')
time.sleep(0.08)
else:
logging.error(f'Read swb pic failed')
def get_swa_adc_per_lane(local_bmc: DevWhiteRiverExp, exp_id: int, slot_id: int, lane_id: int):
local_bmc.SetOpticalModuleRegs(exp_id, slot_id, 0x00, 0xB3, 0xAB, 1, "02")
time.sleep(0.05)
local_bmc.SetOpticalModuleRegs(exp_id, slot_id, 0x00, 0xB3, 0xAC, 1, f"{lane_id:02x}")
time.sleep(0.05)
local_bmc.SetOpticalModuleRegs(exp_id, slot_id, 0x00, 0xB3, 0xAD, 1, f"{lane_id:02x}")
time.sleep(0.05)
local_bmc.SetOpticalModuleRegs(exp_id, slot_id, 0x00, 0xB3, 0xAE, 1, f"01")
time.sleep(0.05)
local_bmc.SetOpticalModuleRegs(exp_id, slot_id, 0x00, 0xB3, 0xAF, 1, f"01")
time.sleep(0.05)
local_bmc.SetOpticalModuleRegs(exp_id, slot_id, 0x00, 0xB3, 0xAA, 1, "07")
time.sleep(0.05)
logging.info('step 1')
time.sleep(3)
status = local_bmc.GetOpticalModuleRegs(exp_id, slot_id, 0x00, 0xB3, 0xB0, 1)
if status == 'aa':
swa_adc1 = local_bmc.GetOpticalModuleRegs(exp_id, slot_id, 0x00, 0xA0, 0x80, 128)
swa_adc2 = local_bmc.GetOpticalModuleRegs(exp_id, slot_id, 0x00, 0xA1, 0x80, 128)
swa_adc3 = local_bmc.GetOpticalModuleRegs(exp_id, slot_id, 0x00, 0xA2, 0x80, 128)
swa_adc4 = local_bmc.GetOpticalModuleRegs(exp_id, slot_id, 0x00, 0xA3, 0x80, 128)
swa_adc5 = local_bmc.GetOpticalModuleRegs(exp_id, slot_id, 0x00, 0xA4, 0x80, 128)
swa_adc6 = local_bmc.GetOpticalModuleRegs(exp_id, slot_id, 0x00, 0xA5, 0x80, 128)
swa_adc7 = local_bmc.GetOpticalModuleRegs(exp_id, slot_id, 0x00, 0xA6, 0x80, 128)
swa_adc8 = local_bmc.GetOpticalModuleRegs(exp_id, slot_id, 0x00, 0xA7, 0x80, 128)
full_hex_string = swa_adc1 + swa_adc2 + swa_adc3 + swa_adc4 + swa_adc5 + swa_adc6 + swa_adc7 + swa_adc8
byte_strings = [full_hex_string[i:i+4] for i in range(0, len(full_hex_string), 4)]
data_values = [int(byte_str, 16) for byte_str in byte_strings]
max_value = max(data_values)
min_value = min(data_values)
max_index = data_values.index(max_value)
min_index = data_values.index(min_value)
x = list(range(len(data_values)))
plt.figure(figsize=(12, 6))
plt.plot(x, data_values, linewidth=1.5)
plt.title('Data Curve Plot', fontsize=16)
plt.xlabel('idac', fontsize=12)
plt.ylabel('mpd', fontsize=12)
plt.grid(True, alpha=0.3)
plt.tight_layout()
plt.savefig('data_curve.png', dpi=300, bbox_inches='tight')
plt.close()
# logging.info(f"full_hex_string: {full_hex_string}")
# logging.info(f'data_values: {data_values}')
logging.info(f"max value: {max_value}, index: {max_index}")
logging.info(f"min value: {min_value}, index: {min_index}")
return (max_index, max_value, min_index, min_value)
else:
return (0, 0, 0, 0)
def get_swb_adc_per_lane(local_bmc: DevWhiteRiverExp, exp_id: int, slot_id: int, lane_id: int):
local_bmc.SetOpticalModuleRegs(exp_id, slot_id, 0x00, 0xB3, 0xAB, 1, "03")
time.sleep(0.05)
local_bmc.SetOpticalModuleRegs(exp_id, slot_id, 0x00, 0xB3, 0xAC, 1, f"{lane_id:02x}")
time.sleep(0.05)
local_bmc.SetOpticalModuleRegs(exp_id, slot_id, 0x00, 0xB3, 0xAD, 1, f"{lane_id:02x}")
time.sleep(0.05)
local_bmc.SetOpticalModuleRegs(exp_id, slot_id, 0x00, 0xB3, 0xAE, 1, f"01")
time.sleep(0.05)
local_bmc.SetOpticalModuleRegs(exp_id, slot_id, 0x00, 0xB3, 0xAF, 1, f"01")
time.sleep(0.05)
local_bmc.SetOpticalModuleRegs(exp_id, slot_id, 0x00, 0xB3, 0xAA, 1, "07")
time.sleep(0.05)
logging.info('step 1')
time.sleep(3)
status = local_bmc.GetOpticalModuleRegs(exp_id, slot_id, 0x00, 0xB3, 0xB0, 1)
if status == 'aa':
swb_adc1 = local_bmc.GetOpticalModuleRegs(exp_id, slot_id, 0x00, 0xA0, 0x80, 128)
swb_adc2 = local_bmc.GetOpticalModuleRegs(exp_id, slot_id, 0x00, 0xA1, 0x80, 128)
swb_adc3 = local_bmc.GetOpticalModuleRegs(exp_id, slot_id, 0x00, 0xA2, 0x80, 128)
swb_adc4 = local_bmc.GetOpticalModuleRegs(exp_id, slot_id, 0x00, 0xA3, 0x80, 128)
swb_adc5 = local_bmc.GetOpticalModuleRegs(exp_id, slot_id, 0x00, 0xA4, 0x80, 128)
swb_adc6 = local_bmc.GetOpticalModuleRegs(exp_id, slot_id, 0x00, 0xA5, 0x80, 128)
swb_adc7 = local_bmc.GetOpticalModuleRegs(exp_id, slot_id, 0x00, 0xA6, 0x80, 128)
swb_adc8 = local_bmc.GetOpticalModuleRegs(exp_id, slot_id, 0x00, 0xA7, 0x80, 128)
full_hex_string = swb_adc1 + swb_adc2 + swb_adc3 + swb_adc4 + swb_adc5 + swb_adc6 + swb_adc7 + swb_adc8
byte_strings = [full_hex_string[i:i+4] for i in range(0, len(full_hex_string), 4)]
data_values = [int(byte_str, 16) for byte_str in byte_strings]
max_value = max(data_values)
min_value = min(data_values)
max_index = data_values.index(max_value)
min_index = data_values.index(min_value)
x = list(range(len(data_values)))
plt.figure(figsize=(12, 6))
plt.plot(x, data_values, linewidth=1.5)
plt.title('Data Curve Plot', fontsize=16)
plt.xlabel('idac', fontsize=12)
plt.ylabel('mpd', fontsize=12)
plt.grid(True, alpha=0.3)
plt.tight_layout()
plt.savefig(f'main_data/data_curve/data_curve_{lane_id}.png', dpi=300, bbox_inches='tight')
plt.close()
# logging.info(f"full_hex_string: {full_hex_string}")
# logging.info(f'data_values: {data_values}')
logging.info(f"max value: {max_value}, index: {max_index}")
logging.info(f"min value: {min_value}, index: {min_index}")
return (max_index, max_value, min_index, min_value)
else:
return (0, 0, 0, 0)
def find_rising_edge_47_percent(y_data):
if not y_data or len(y_data) < 2:
return None
y_min = min(y_data)
y_max = max(y_data)
if y_max == y_min:
return None # 无变化
target_y = y_min + 0.47 * (y_max - y_min)
# 从左到右扫描上升沿
for i in range(len(y_data) - 1):
y_curr = y_data[i]
y_next = y_data[i + 1]
# 必须是上升趋势
if y_next > y_curr and y_curr <= target_y < y_next:
# 线性插值
x_curr = i * 8
x_next = (i + 1) * 8
# 避免除零(虽然 y_next > y_curr 已保证)
slope = (y_next - y_curr) / (x_next - x_curr)
x_target = x_curr + (target_y - y_curr) / slope
return x_target
# 如果没找到,可能目标值在最后一点之后?再检查是否等于最后一个点
if abs(y_data[-1] - target_y) < 1e-6:
return (len(y_data) - 1) * 8
# 未找到上升沿穿越点
return None
def MzmAutoTune(host: str, local_bmc: DevWhiteRiverExp, exp_id: int, slot_list: list, lane_list: List[int],
remote_bmc: DevWhiteRiverExp, route_name: str,
local_reg_tool: OptRegAccessTool, remote_reg_tool: OptRegAccessTool):
logging.info(f'lane_list: {lane_list}')
ibias_rssi_map_file = '/xz/gyou/nexusbench/main_data/ibias-rssi-map.json'
ibias_rssi_map = IbiasRssiMapParser(ibias_rssi_map_file)
topo_map = TopoMappingParser("/xz/gyou/nexusbench/main_data/topo_mapping.yaml")
logging.info(f"start auto tune eq: exp_id={exp_id}, slots={slot_list}")
for slot_id in slot_list:
local_bmc.SetOpticalModuleRegs(exp_id, slot_id, 0x00, 0xD0, 0x8A, 1, "01")
for lane_id in lane_list:
best_mpd = 0
best_idac = 0
for vadc in range(0, 4096, 800):
local_reg_tool.write_opt_reg(exp_id, slot_id, lane_id, vadc, 'vdac_runtime')
time.sleep(0.05)
max_index, max_value, min_index, min_value = get_swa_adc_per_lane(local_bmc, exp_id, slot_id, lane_id)
if max_value > best_mpd:
best_mpd = max_value
best_idac = max_index
# set idac
logging.info(f"vadc: {vadc}, current_value: {max_value}, best: {best_idac}")
local_bmc.SetOpticalModuleRegs(exp_id, slot_id, 0x00, 0xB3, 0xAB, 1, "02")
time.sleep(0.05)
local_bmc.SetOpticalModuleRegs(exp_id, slot_id, 0x00, 0xB3, 0xAC, 1, f"{lane_id:02x}")
time.sleep(0.05)
idac_str = best_idac.to_bytes(2, 'big').hex()
local_bmc.SetOpticalModuleRegs(exp_id, slot_id, 0x00, 0xB3, 0xAD, 2, idac_str)
time.sleep(0.05)
local_bmc.SetOpticalModuleRegs(exp_id, slot_id, 0x00, 0xB3, 0xAF, 1, f"00")
time.sleep(0.05)
local_bmc.SetOpticalModuleRegs(exp_id, slot_id, 0x00, 0xB3, 0xAA, 1, "02")
time.sleep(0.05)
time.sleep(0.5)
status = local_bmc.GetOpticalModuleRegs(exp_id, slot_id, 0x00, 0xB3, 0xB0, 1)
logging.info(f'slot:{slot_id}, lane:{lane_id}, write max idac: {idac_str}, return status: {status}')
# 细扫
local_bmc.SetOpticalModuleRegs(exp_id, slot_id, 0x00, 0xB3, 0xAB, 1, f"{lane_id:02x}")
time.sleep(0.05)
local_bmc.SetOpticalModuleRegs(exp_id, slot_id, 0x00, 0xB3, 0xAC, 1, f"08")
time.sleep(0.05)
local_bmc.SetOpticalModuleRegs(exp_id, slot_id, 0x00, 0xB3, 0xAD, 1, f"02")
time.sleep(0.05)
local_bmc.SetOpticalModuleRegs(exp_id, slot_id, 0x00, 0xB3, 0xAE, 1, f"01")
time.sleep(0.05)
local_bmc.SetOpticalModuleRegs(exp_id, slot_id, 0x00, 0xB3, 0xAF, 1, f"00")
time.sleep(0.05)
local_bmc.SetOpticalModuleRegs(exp_id, slot_id, 0x00, 0xB3, 0xAA, 1, "0B")
time.sleep(0.05)
logging.info('step 1')
time.sleep(3)
status = local_bmc.GetOpticalModuleRegs(exp_id, slot_id, 0x00, 0xB3, 0xB0, 1)
if status == 'aa':
swa_adc1 = local_bmc.GetOpticalModuleRegs(exp_id, slot_id, 0x00, 0xA0, 0x80, 128)
swa_adc2 = local_bmc.GetOpticalModuleRegs(exp_id, slot_id, 0x00, 0xA1, 0x80, 128)
swa_adc3 = local_bmc.GetOpticalModuleRegs(exp_id, slot_id, 0x00, 0xA2, 0x80, 128)
swa_adc4 = local_bmc.GetOpticalModuleRegs(exp_id, slot_id, 0x00, 0xA3, 0x80, 128)
swa_adc5 = local_bmc.GetOpticalModuleRegs(exp_id, slot_id, 0x00, 0xA4, 0x80, 128)
swa_adc6 = local_bmc.GetOpticalModuleRegs(exp_id, slot_id, 0x00, 0xA5, 0x80, 128)
swa_adc7 = local_bmc.GetOpticalModuleRegs(exp_id, slot_id, 0x00, 0xA6, 0x80, 128)
swa_adc8 = local_bmc.GetOpticalModuleRegs(exp_id, slot_id, 0x00, 0xA7, 0x80, 128)
full_hex_string = swa_adc1 + swa_adc2 + swa_adc3 + swa_adc4 + swa_adc5 + swa_adc6 + swa_adc7 + swa_adc8
byte_strings = [full_hex_string[i:i+4] for i in range(0, len(full_hex_string), 4)]
data_values = [int(byte_str, 16) for byte_str in byte_strings]
max_value = max(data_values)
min_value = min(data_values)
max_index = data_values.index(max_value)
min_index = data_values.index(min_value)
x = [i * 8 for i in range(len(data_values))]
plt.figure(figsize=(12, 6))
plt.plot(x, data_values, linewidth=1.5)
plt.title('Data Curve Plot', fontsize=16)
plt.xlabel('vdac', fontsize=12)
plt.ylabel('mpd', fontsize=12)
plt.grid(True, alpha=0.3)
plt.tight_layout()
plt.savefig(f'mzm_vdac_{lane_id}.png', dpi=300, bbox_inches='tight')
plt.close()
logging.info(f"full_hex_string: {full_hex_string}")
logging.info(f'data_values: {data_values}')
logging.info(f"max value: {max_value}, index: {max_index}")
logging.info(f"min value: {min_value}, index: {min_index}")
x_at_47 = find_rising_edge_47_percent(data_values)
raw_vdac = local_reg_tool.read_opt_reg(exp_id, slot_id, lane_id, 'vdac')
logging.info(f'------------- raw_vdac: {raw_vdac}, new vdac: {x_at_47}')
else:
logging.info(f'-------- status: {status}')
def EyeCheck(host: str, local_bmc: DevWhiteRiverExp, exp_id: int, slot_list: list, lane_list: List[int],
remote_bmc: DevWhiteRiverExp, route_name: str,
local_reg_tool: OptRegAccessTool, remote_reg_tool: OptRegAccessTool):
logging.info(f'lane_list: {lane_list}')
slot_list = [0,1,2,3,4,5,6,7]
ibias_rssi_map_file = '/xz/gyou/nexusbench/main_data/ibias-rssi-map.json'
ibias_rssi_map = IbiasRssiMapParser(ibias_rssi_map_file)
topo_map = TopoMappingParser("/xz/gyou/nexusbench/main_data/topo_mapping.yaml")
logging.info(f"start auto tune eq: exp_id={exp_id}, slots={slot_list}")
tool = EqTuneTool(local_bmc, remote_bmc, local_reg_tool, remote_reg_tool, ibias_rssi_map, topo_map, route_name)
tool.eye_check(host, exp_id, route_name)
def RecvErrCheck(host: str, remote_host: str, local_bmc: DevWhiteRiverExp, exp_id: int, slot_list: list, retimers: List[int],
remote_bmc: DevWhiteRiverExp, route_name: str,
local_reg_tool: OptRegAccessTool, remote_reg_tool: OptRegAccessTool, is_only_recv = False, is_show_all = False):
logging.info(f'lane_list: {lane_list}')
slot_list = [0,1,2,3,4,5,6,7]
ibias_rssi_map_file = '/xz/gyou/nexusbench/main_data/ibias-rssi-map.json'
ibias_rssi_map = IbiasRssiMapParser(ibias_rssi_map_file)
topo_map = TopoMappingParser("/xz/gyou/nexusbench/main_data/topo_mapping.yaml")
logging.info(f"start auto tune eq: exp_id={exp_id}, slots={slot_list}")
eq_tool = EqTuneTool(local_bmc, remote_bmc, local_reg_tool, remote_reg_tool, ibias_rssi_map, topo_map, route_name)
tool = RecvCeTool(local_bmc, remote_bmc, local_reg_tool, remote_reg_tool, eq_tool, ibias_rssi_map, topo_map, route_name)
tool.recv_err_check(host, exp_id, route_name, retimers, is_only_recv, is_show_all)
if remote_host != '' and remote_host != host:
time.sleep(0.05)
remote_tool = RecvCeTool(remote_bmc, local_bmc, remote_reg_tool, local_reg_tool, eq_tool, ibias_rssi_map, topo_map, route_name)
remote_tool.recv_err_check(remote_host, exp_id, route_name, retimers, is_only_recv, is_show_all)
def CalcCtleMap(host: str, local_bmc: DevWhiteRiverExp, exp_id: int, slot_list: list, lane_list: List[int],
remote_bmc: DevWhiteRiverExp, route_name: str,
local_reg_tool: OptRegAccessTool, remote_reg_tool: OptRegAccessTool):
logging.info(f'lane_list: {lane_list}')
slot_list = [0,1,2,3,4,5,6,7]
ibias_rssi_map_file = '/xz/gyou/nexusbench/main_data/ibias-rssi-map.json'
ibias_rssi_map = IbiasRssiMapParser(ibias_rssi_map_file)
topo_map = TopoMappingParser("/xz/gyou/nexusbench/main_data/topo_mapping.yaml")
if param_list == ['']:
retimers = [1,2,3,4]
else:
retimers = [int(x) for x in param_list]
logging.info(f"start auto tune eq: exp_id={exp_id}, slots={slot_list}")
tool = EqTuneTool(local_bmc, remote_bmc, local_reg_tool, remote_reg_tool, ibias_rssi_map, topo_map, route_name)
# tool.eq_auto_tune(exp_id)
if param == '':
offset = 0
else:
offset = int(param)
# tool.calc_ctle_value_by_pcb_trace_tx_rx_decoup(offset)
tool.calc_ctle_value_by_pcb_trace_pre6_post0(offset)
def AutoTuneEq(host: str, local_bmc: DevWhiteRiverExp, exp_id: int, slot_list: list, lane_list: List[int],
remote_bmc: DevWhiteRiverExp, route_name: str,
local_reg_tool: OptRegAccessTool, remote_reg_tool: OptRegAccessTool):
logging.info(f'lane_list: {lane_list}')
slot_list = [0,1,2,3,4,5,6,7]
ibias_rssi_map_file = '/xz/gyou/nexusbench/main_data/ibias-rssi-map.json'
ibias_rssi_map = IbiasRssiMapParser(ibias_rssi_map_file)
topo_map = TopoMappingParser("/xz/gyou/nexusbench/main_data/topo_mapping.yaml")
if param_list == ['']:
retimers = [1,2,3,4]
else:
retimers = [int(x) for x in param_list]
logging.info(f"start auto tune eq: exp_id={exp_id}, slots={slot_list}")
tool = EqTuneTool(local_bmc, remote_bmc, local_reg_tool, remote_reg_tool, ibias_rssi_map, topo_map, route_name)
# tool.eq_auto_tune(exp_id)
# tool.tune_eq_by_rtmr_length(exp_id, [1,2,3,4], False)
tool.tune_eq_by_eye_width(exp_id, retimers)
# tool.tune_eq_by_eye_width_ctle(exp_id, retimers)
def TuneView(host: str, local_bmc: DevWhiteRiverExp, exp_id: int, slot_list: list, lane_list: List[int],
remote_bmc: DevWhiteRiverExp, route_name: str,
local_reg_tool: OptRegAccessTool, remote_reg_tool: OptRegAccessTool,
rtmr_id: int, rtmr_lane: int):
logging.info(f'lane_list: {lane_list}')
slot_list = [0,1,2,3,4,5,6,7]
ibias_rssi_map_file = '/xz/gyou/nexusbench/main_data/ibias-rssi-map.json'
ibias_rssi_map = IbiasRssiMapParser(ibias_rssi_map_file)
topo_map = TopoMappingParser("/xz/gyou/nexusbench/main_data/topo_mapping.yaml")
logging.info(f"start manual tune view: exp_id={exp_id}, slots={slot_list}")
tool = EqTuneTool(local_bmc, remote_bmc, local_reg_tool, remote_reg_tool, ibias_rssi_map, topo_map, route_name)
logging.info(f'------------- step 1')
tool.tune_view(exp_id, rtmr_id, rtmr_lane)
def TuneWrite(host: str, local_bmc: DevWhiteRiverExp, exp_id: int, slot_list: list, lane_list: List[int],
remote_bmc: DevWhiteRiverExp, route_name: str,
local_reg_tool: OptRegAccessTool, remote_reg_tool: OptRegAccessTool,
rtmr_id: int, rtmr_lane: int, reg_name: str, reg_value: int):
logging.info(f'lane_list: {lane_list}')
slot_list = [0,1,2,3,4,5,6,7]
ibias_rssi_map_file = '/xz/gyou/nexusbench/main_data/ibias-rssi-map.json'
ibias_rssi_map = IbiasRssiMapParser(ibias_rssi_map_file)
topo_map = TopoMappingParser("/xz/gyou/nexusbench/main_data/topo_mapping.yaml")
logging.info(f"start manual tune write: exp_id={exp_id}, slots={slot_list}")
tool = EqTuneTool(local_bmc, remote_bmc, local_reg_tool, remote_reg_tool, ibias_rssi_map, topo_map, route_name)
logging.info(f'------------- step 1')
tool.tune_write(exp_id, rtmr_id, rtmr_lane, reg_name, reg_value)
def SetPower(host: str, exp: int, local_bmc: DevWhiteRiverExp, param: str):
if param == '950':
logging.info(f'----host: {host} exp: {exp}, set power 950')
local_bmc.CmdVendorCommand(exp, "exp pause")
local_bmc.CmdVendorCommand(exp, "iicm i2c@40008400 0x61 w 0 0")
local_bmc.CmdVendorCommand(exp, "iicm i2c@40008400 0x61 w 0x24 0x32 0x00")
local_bmc.CmdVendorCommand(exp, "iicm i2c@40008400 0x61 w 0xDB 0x2E")
local_bmc.CmdVendorCommand(exp, "iicm i2c@40008400 0x61 w 0x21 0x2E 0x00")
local_bmc.CmdVendorCommand(exp, "iicm i2c@40008400 0x61 w 0x11")
local_bmc.CmdVendorCommand(exp, "exp resume")
local_bmc.CmdVendorCommand(exp, "exp")
elif param == '930':
logging.info(f'----host: {host} exp: {exp}, set power 930')
local_bmc.CmdVendorCommand(exp, "exp pause")
local_bmc.CmdVendorCommand(exp, "iicm i2c@40008400 0x61 w 0 0")
local_bmc.CmdVendorCommand(exp, "iicm i2c@40008400 0x61 w 0x24 0x32 0x00")
local_bmc.CmdVendorCommand(exp, "iicm i2c@40008400 0x61 w 0xDB 0x2C")
local_bmc.CmdVendorCommand(exp, "iicm i2c@40008400 0x61 w 0x21 0x2C 0x00")
local_bmc.CmdVendorCommand(exp, "iicm i2c@40008400 0x61 w 0x11")
local_bmc.CmdVendorCommand(exp, "exp resume")
local_bmc.CmdVendorCommand(exp, "exp")
elif param == '910':
logging.info(f'----host: {host} exp: {exp}, set power 910')
local_bmc.CmdVendorCommand(exp, "exp pause")
local_bmc.CmdVendorCommand(exp, "iicm i2c@40008400 0x61 w 0 0")
local_bmc.CmdVendorCommand(exp, "iicm i2c@40008400 0x61 w 0x24 0x2D 0x00")
local_bmc.CmdVendorCommand(exp, "iicm i2c@40008400 0x61 w 0xDB 0x2A")
local_bmc.CmdVendorCommand(exp, "iicm i2c@40008400 0x61 w 0x21 0x2A 0x00")
local_bmc.CmdVendorCommand(exp, "iicm i2c@40008400 0x61 w 0x11")
local_bmc.CmdVendorCommand(exp, "exp resume")
local_bmc.CmdVendorCommand(exp, "exp")
elif param == '950':
logging.info(f'----host: {host} exp: {exp}, set power 950')
local_bmc.CmdVendorCommand(exp, "exp pause")
local_bmc.CmdVendorCommand(exp, "iicm i2c@40008400 0x61 w 0 0")
local_bmc.CmdVendorCommand(exp, "iicm i2c@40008400 0x61 w 0x24 0x32 0x00")
local_bmc.CmdVendorCommand(exp, "iicm i2c@40008400 0x61 w 0xDB 0x2E")
local_bmc.CmdVendorCommand(exp, "iicm i2c@40008400 0x61 w 0x21 0x2E 0x00")
local_bmc.CmdVendorCommand(exp, "iicm i2c@40008400 0x61 w 0x11")
local_bmc.CmdVendorCommand(exp, "exp resume")
local_bmc.CmdVendorCommand(exp, "exp")
TCT_SN_FILE = "main_data/tct_sn.txt"
# 全局缓存,避免重复读取文件
_tct_sn_set = None
def load_tct_sn_from_file():
"""只加载一次 tct_sn.txt,返回包含所有已温循 SN 的集合"""
global _tct_sn_set
if _tct_sn_set is not None:
return _tct_sn_set
_tct_sn_set = set()
if not os.path.exists(TCT_SN_FILE):
logging.error(f"[TCT] 文件不存在: {TCT_SN_FILE}")
return _tct_sn_set
try:
with open(TCT_SN_FILE, 'r', encoding='utf-8') as f:
for line_num, line in enumerate(f, 1):
stripped = line.strip()
# 跳过空行和注释行
if not stripped or stripped.startswith('#'):
continue
_tct_sn_set.add(stripped)
logging.info(f"[TCT] 已加载 {len(_tct_sn_set)} 个经过温循的 SN")
except Exception as e:
logging.error(f"[TCT] 读取 TCT SN 文件失败: {e}")
return _tct_sn_set
def check_module_tct_status(host: str, bmc, exp_id: int, slot_list):
global _tct_sn_set
# 步骤1:加载 TCT SN 列表
if _tct_sn_set is None:
_tct_sn_set = load_tct_sn_from_file()
for slot_id in slot_list:
# 步骤2:从 BMC 读取模块 SN (字节 166 开始,共 16 字节)
try:
res_data = bmc.GetOpticalModuleRegs(exp_id, slot_id, 0, 0, 166, 16)
if not res_data:
raise ValueError("BMC 返回空数据")
bytes_data = bytes.fromhex(res_data)
# 解码为 ASCII,忽略非法字符,并去除首尾空白和填充字符(如 \x00, 空格)
raw_sn = bytes_data.decode('ascii', errors='ignore').strip('\x00 \t\n\r')
sn = raw_sn.strip() # 最终 SN
if not sn:
sn = "Unknown_SN"
except Exception as e:
logging.error(f"[BMC] 读取 host:{host}, exp:{exp_id}, slot:{slot_id} SN 失败: {e}")
sn = "Read_Error"
# 步骤3:判断是否经过温循
is_tct_passed = sn in _tct_sn_set
# 步骤4:统一格式化输出
status_str = "Yes" if is_tct_passed else "No"
logging.info(
f"host: {host}, "
f"exp: {exp_id}, "
f"slot: {slot_id}, "
f"sn: {sn}, "
f"tct_passed: {status_str}"
)
def run_remote_cmd(host, cmd_str, password='RCms@Zte3'):
full_cmd = [
'sshpass', '-p', password,
'ssh', '-o', 'StrictHostKeyChecking=no',
f'root@{host}',
cmd_str
]
logging.info(f"[RUN] {host}: {cmd_str}")
# 启动进程,实时捕获输出
proc = subprocess.Popen(
full_cmd,
stdout=subprocess.PIPE,
stderr=subprocess.STDOUT, # 合并 stderr 到 stdout
universal_newlines=True, # 返回字符串而非 bytes
bufsize=1 # 行缓冲
)
# 实时读取输出并打印
for line in iter(proc.stdout.readline, ''):
if line:
logging.info(f"[{host}] {line.rstrip()}")
proc.stdout.close()
return_code = proc.wait()
if return_code != 0:
logging.error(f"[ERROR] Command failed on {host} (exit code: {return_code})", file=sys.stderr)
else:
logging.info(f"[OK] Command succeeded on {host}")
return return_code
def gpu_cto_disable(os_host_list, password='RCms@Zte3', container='mysccl-zds'):
logging.info(">>> GPU reset on hosts: %s", os_host_list)
base_cmd_list = [
'/workspace/zds/gpu_debugger -i all -w 0x369098 0x00000010',
'/workspace/zds/gpu_debugger -i all -w 0x379098 0x00000010',
'/workspace/zds/gpu_debugger -i all -w 0x781098 0x00000010',
'/workspace/zds/gpu_debugger -i all -w 0x771098 0x00000010',
'/workspace/zds/gpu_debugger -i all -r 0x369098',
'/workspace/zds/gpu_debugger -i all -r 0x379098',
'/workspace/zds/gpu_debugger -i all -r 0x781098',
'/workspace/zds/gpu_debugger -i all -r 0x771098'
]
def exec_on_host(host):
for base_cmd in base_cmd_list:
cmd = f"docker exec {container} {base_cmd}"
run_remote_cmd(host, cmd, password)
with concurrent.futures.ThreadPoolExecutor(max_workers=len(os_host_list)) as executor:
future_to_host = {executor.submit(exec_on_host, host): host for host in os_host_list}
for future in concurrent.futures.as_completed(future_to_host):
host = future_to_host[future]
try:
future.result()
except Exception as exc:
logging.error("Host %s exception: %s", host, exc)
def gpu_reset(os_host_list, password='RCms@Zte3', container='mysccl-zds'):
base_cmd = "brsmi reset -g"
logging.info(">>> GPU reset on hosts: %s", os_host_list)
def reset_on_host(host):
cmd = f"docker exec {container} {base_cmd}"
run_remote_cmd(host, cmd, password)
with concurrent.futures.ThreadPoolExecutor(max_workers=len(os_host_list)) as executor:
future_to_host = {executor.submit(reset_on_host, host): host for host in os_host_list}
for future in concurrent.futures.as_completed(future_to_host):
host = future_to_host[future]
try:
future.result()
except Exception as exc:
logging.error("Host %s exception: %s", host, exc)
def process_exp_cold_reset(host):
logging.info(f'-----------process: {host}, exp_list: {exp_list}')
for exp_id in exp_list:
exp_id = int(exp_id)
base_url = f"https://{host}"
# logging.info(f'-------step 0, base_url: {base_url}')
exp_util = SmbusHttpUtil(base_url, "root", "0penBmc", "test")
# logging.info(f'-------step 1')
# exp_util.lock(exp_id)
vuart_util = VuartUtil(host)
bmc = DevWhiteRiverExp(exp_util, vuart_util)
logging.info(f'start exec reset: {exp_id}')
ExpColdReset(bmc, exp_id)
logging.info(f'finish exec reset: {exp_id}')
time.sleep(5)
sec = bmc.GetExpStatus(exp_id)
logging.info(f'------update:{sec}')
if sec is not None:
while sec > 8:
logging.error(f'host {host} exp {exp_id} reset failed, try again')
ExpColdReset(bmc, exp_id)
time.sleep(5)
sec = bmc.GetExpStatus(exp_id)
logging.info(f'------update:{sec}')
logging.info(f'{host} done')
def process_rtmr_waram_reset(host):
logging.info(f'-----------process: {host}, exp_list: {exp_list}')
for exp_id in exp_list:
exp_id = int(exp_id)
base_url = f"https://{host}"
# logging.info(f'-------step 0, base_url: {base_url}')
exp_util = SmbusHttpUtil(base_url, "root", "0penBmc", "test")
# logging.info(f'-------step 1')
# exp_util.lock(exp_id)
vuart_util = VuartUtil(host)
bmc = DevWhiteRiverExp(exp_util, vuart_util)
logging.info(f'start exec retimer reset: {exp_id}')
rtmr_reset_and_port_reset(bmc, exp_id)
logging.info(f'{host} done')
def rtmr_reset_and_port_reset(bmc: DevWhiteRiverExp, exp_id):
bmc.CmdVendorCommand(exp_id, 'cmis mode lp')
time.sleep(0.15)
bmc.CmdVendorCommand(exp_id, 'rtmr 1 reset')
bmc.CmdVendorCommand(exp_id, 'rtmr 2 reset')
bmc.CmdVendorCommand(exp_id, 'rtmr 3 reset')
bmc.CmdVendorCommand(exp_id, 'rtmr 4 reset')
time.sleep(0.5) # 等待load成功
bmc.SetRetimerRegs(exp_id, 1, 0x0414, '11')
bmc.SetRetimerRegs(exp_id, 2, 0x0414, '11')
bmc.SetRetimerRegs(exp_id, 3, 0x0414, '11')
bmc.SetRetimerRegs(exp_id, 4, 0x0414, '11')
time.sleep(1)
bmc.CmdVendorCommand(exp_id, 'cmis mode hp')
time.sleep(2)
bmc.SetRetimerRegs(exp_id, 1, 0x0414, '00')
bmc.SetRetimerRegs(exp_id, 2, 0x0414, '00')
bmc.SetRetimerRegs(exp_id, 3, 0x0414, '00')
bmc.SetRetimerRegs(exp_id, 4, 0x0414, '00')
logging.info(f'finish exec retimer reset: {exp_id}')
def load_ctle_config(host: str, route_name: str, exp_id: int) -> List[RetimerLaneSetting]:
config_path = os.path.join("/xz/gyou/nexusbench/main_data", "ctle", f"{host}.json")
if not os.path.exists(config_path):
logging.info(f"CTLE config file not found: {config_path}")
return []
try:
with open(config_path, 'r', encoding='utf-8') as f:
full_config = json.load(f)
# 获取当前路由模式下的子配置
mode_config = full_config.get(route_name)
if mode_config is None:
logging.info(
f"No CTLE configuration found for routing mode '{route_name}' in {config_path}"
)
return []
exps = mode_config.get("exps", {})
exp_key = str(exp_id)
if exp_key not in exps:
logging.info(
f"No CTLE config found for exp_id={exp_id} under route='{route_name}' in {config_path}"
)
return []
retimers = exps[exp_key].get("retimers", {})
results = []
for rtmr_id_str, rtmr_data in retimers.items():
lanes = rtmr_data.get("lanes", {})
for lane_str, lane_data in lanes.items():
try:
ctle_val = lane_data.get("ctle")
if ctle_val is None:
continue
setting = RetimerLaneSetting(
rtmr_id=int(rtmr_id_str),
rtmr_lane=int(lane_str),
ctle=int(ctle_val)
)
results.append(setting)
except (ValueError, TypeError) as e:
logging.warning(
f"Invalid CTLE entry in {config_path} [route={route_name}, exp={exp_id}]: "
f"retimer={rtmr_id_str}, lane={lane_str}, data={lane_data} ({e})"
)
continue
logging.info(
f"Loaded {len(results)} CTLE settings for host={host}, route={route_name}, exp={exp_id}"
)
return results
except json.JSONDecodeError as e:
logging.error(f"Failed to parse CTLE config file {config_path}: {e}")
return []
except (OSError, IOError) as e:
logging.error(f"Failed to read CTLE config file {config_path}: {e}")
return []
except Exception as e:
logging.error(f"Unexpected error loading CTLE config: {e}")
return []
def load_ctle_for_single_host_exp(host: str, port_list: List[int], need_lock = True):
for exp_id in port_list:
try:
exp_id = int(exp_id)
exp_util = SmbusHttpUtil(f"https://{host}", "root", "0penBmc", host)
vuart_util = VuartUtil(host)
bmc = DevWhiteRiverExp(exp_util, vuart_util)
if need_lock:
exp_util.lock(exp_id)
logging.info(f'----------process_host {host} exp {exp_id} locked')
time.sleep(0.05)
route_name = get_route_name(host, bmc, exp_id)
all_rtmr_lane_settings: List[RetimerLaneSetting] = load_ctle_config(host, route_name, exp_id)
for lane_setting in all_rtmr_lane_settings:
WriteRtmrCtle(host, exp_id, bmc, [lane_setting.rtmr_id], [lane_setting.rtmr_lane], lane_setting.ctle)
time.sleep(0.05)
if all_rtmr_lane_settings:
CommitRtmrCtle(exp_id, bmc, [1, 2, 3, 4])
time.sleep(0.05)
logging.info(f"✅ Completed {host} exp {exp_id}")
except Exception as e:
logging.error(f"❌ Failed to process {host} exp {exp_id}: {e}")
raise # 可选:是否让主线程感知失败
finally:
# 确保解锁(即使出错)
try:
if need_lock:
exp_util.unlock(exp_id)
logging.info(f'----------process_host {host} exp {exp_id} unlocked')
except Exception as unlock_err:
logging.warning(f"Failed to unlock {host} exp {exp_id}: {unlock_err}")
def link_train(host_list, os_host_list, port_list, topo_file_name, password='RCms@Zte3', container='mysccl-zds'):
base_cmd = "/workspace/zds"
script_disable = f"{base_cmd}/scripts/disable_port_ltssm"
topo_tool = f"{base_cmd}/ocsTopo_s"
# === Step 1: Disable LTSSM for all (host, port) pairs ===
logging.info(">>> Step 1: Disabling LTSSM on all hosts and ports...")
for port in port_list:
for host in os_host_list:
cmd = f"docker exec {container} {script_disable} {port}"
run_remote_cmd(host, cmd, password)
# # === Step 2: ocs link reset (host, port) pairs ===
logging.info(">>> Step 2: ocs link reset on all hosts and ports...")
with ThreadPoolExecutor(max_workers=len(host_list)) as executor:
executor.map(process_exp_cold_reset, host_list)
#
time.sleep(6)
# === Step 3: Load topology on all hosts ===
logging.info("\n>>> Step 2: Loading topology on all hosts...")
topo_path = f"../../{base_cmd}/{topo_file_name}"
for host in os_host_list:
cmd = f"docker exec {container} {topo_tool} -s {topo_path}"
run_remote_cmd(host, cmd, password)
# === Step 4: Load ctle values to retimer
logging.info("\n>>> Step 4: Loading ctle values to retimer...")
if not host_list or not port_list:
logging.info("No hosts or ports to process.")
return
max_workers = min(4, len(host_list))
logging.info(f"Starting parallel processing across {len(host_list)} hosts with max_workers={max_workers}")
with concurrent.futures.ThreadPoolExecutor(max_workers=max_workers) as executor:
future_to_host = {
executor.submit(load_ctle_for_single_host_exp, host, port_list): host
for host in host_list
}
for future in concurrent.futures.as_completed(future_to_host):
host = future_to_host[future]
try:
future.result()
except Exception as exc:
logging.error(f"Unexpected error in host {host} task: {exc}")
# === Step 5: Start link training (-p) on all hosts ===
logging.info("\n>>> Step 3: Starting link training on all hosts...")
def run_on_host(host, port):
"""在指定 host 上执行指定 port 的命令"""
cmd = f"docker exec {container} {topo_tool} -p {port}"
return run_remote_cmd(host, cmd, password) # 假设该函数已定义
# 外层:按 port 串行
for port in port_list:
logging.info(">>> Starting link training for port %s on all hosts...", port)
# 内层:当前 port 下,所有 host 并行
with concurrent.futures.ThreadPoolExecutor(max_workers=len(os_host_list)) as executor:
# 提交任务:每个 host 执行当前 port
future_to_host = {
executor.submit(run_on_host, host, port): host
for host in os_host_list
}
# 等待当前 port 的所有 host 完成
for future in concurrent.futures.as_completed(future_to_host):
host = future_to_host[future]
try:
future.result() # 触发异常(如有)
except Exception as exc:
logging.error("Host %s failed for port %s: %s", host, port, exc)
logging.info(">>> Completed port %s on all hosts.", port)
ENABLE_ADDR_MAP = {
0: 0x127000, 1: 0x127400, 2: 0x127800, 3: 0x127C00,
4: 0x137000, 5: 0x137400, 6: 0x137800, 7: 0x137C00,
8: 0x147000, 9: 0x147400, 10: 0x147800, 11: 0x147C00,
12: 0x157000, 13: 0x157400, 14: 0x157800, 15: 0x157C00
}
REG_ADDR_MAP = {
0: 0x127004, 1: 0x127404, 2: 0x127804, 3: 0x127C04,
4: 0x137004, 5: 0x137404, 6: 0x137804, 7: 0x137C04,
8: 0x147004, 9: 0x147404, 10: 0x147804, 11: 0x147C04,
12: 0x157004, 13: 0x157404, 14: 0x157804, 15: 0x157C04
}
def WriteRtmrCtle(host: str, exp_id: int, bmc: DevWhiteRiverExp, rtmrs: List[int], rtmr_lanes: List[int], ctle_value: int):
enable_addr_value = 0xabcdabcd
enable_addr_value_str = enable_addr_value.to_bytes(4, 'little').hex()
ctle_value_str = ctle_value.to_bytes(4, 'little').hex()
for rtmr in rtmrs:
for rtmr_lane in rtmr_lanes:
logging.info(f'{host} WriteRtmrCtle exp:{exp_id}, rtmrs:{rtmr}, lane: {rtmr_lane}, addr: {ENABLE_ADDR_MAP[rtmr_lane]}, ctle: {ctle_value}')
bmc.SetRetimerRegs(exp_id, rtmr, ENABLE_ADDR_MAP[rtmr_lane], enable_addr_value_str)
time.sleep(0.05)
bmc.SetRetimerRegs(exp_id, rtmr, REG_ADDR_MAP[rtmr_lane], ctle_value_str)
# value = 0x100
# value_str = value.to_bytes(4, 'little').hex()
# bmc.SetRetimerRegs(exp_id, rtmr, 0x414, value_str)
# time.sleep(0.5)
# value = 0x0
# value_str = value.to_bytes(4, 'little').hex()
# bmc.SetRetimerRegs(exp_id, rtmr, 0x414, value_str)
def CommitRtmrCtle(exp_id: int, bmc: DevWhiteRiverExp, rtmrs: List[int]):
logging.info(f'Commit Rtmr {rtmrs} Ctle')
for rtmr in rtmrs:
value = 0x100
value_str = value.to_bytes(4, 'little').hex()
bmc.SetRetimerRegs(exp_id, rtmr, 0x414, value_str)
time.sleep(1)
value = 0x0
value_str = value.to_bytes(4, 'little').hex()
bmc.SetRetimerRegs(exp_id, rtmr, 0x414, value_str)
def get_route_name(host, bmc, exp_id) -> str:
route_info = bmc.GetOpticalRouteStatus(exp_id, 0)
# logging.info(f'--------GetOpticalRouteStatus route_info:{route_info}')
yaml_route_map = {
'1111111111111111': '786-1-oneta',
'1212121212121212': '786-1-onetb',
'0201040306050807': '786-1-onoc1',
'0403020108070605': '786-1-onoc2',
'0807060504030201': '786-1-onoc3',
'0304010207080506': '786-1-onoc4',
'0605080702010403': '786-1-onoc5',
'0708050603040102': '786-1-onoc6',
'0506070801020304': '786-1-onoc7',
}
route_name = yaml_route_map[route_info]
return route_name
raw_data_91 = {
0: [319, 329, 314, 326, 306, 332, 318, 320],
1: [317, 338, 320, 349, 320, 328, 318, 355],
2: [322, 336, 325, 341, 318, 325, 313, 316],
3: [315, 323, 316, 338, 304, 311, 302, 318],
4: [301, 315, 314, 327, 314, 317, 301, 316],
5: [303, 306, 300, 317, 308, 330, 306, 318],
6: [308, 320, 308, 326, 313, 340, 314, 295],
7: [305, 324, 313, 324, 307, 312, 288, 322],
}
raw_data_94 = {
0: [307,316,303,325,320,335,321,326],
1: [316,333,320,345,308,338,310,324],
2: [347,334,344,322,311,333,328,337],
3: [316,339,321,337,322,337,321,332],
4: [286,307,308,313,301,323,314,321],
5: [222,234,216,236,222,244,226,234],
6: [332,325,344,344,330,339,329,353],
7: [296,305,295,322,302,320,294,315]
}
def print_general_err_matrix(host, exp, lane_data_list: List[LaneErrInfo], tune_value_list, excel_path="err_matrix.xlsx"):
tune_value_list = sorted(tune_value_list)
header_parts = ["Host", "Exp", "Preset", "Slot", "Lane", "RT_Id", "RT_Lane"] + [str(v) for v in tune_value_list]
header_format = "{:<16} {:<6} {:<8} {:<6} {:<6} {:<6} {:<10} " + " ".join("{:<6}" for _ in tune_value_list)
logging.info(header_format.format(*header_parts))
logging.info("-" * (len(header_format.format(*header_parts))))
rows = []
for info in lane_data_list:
try:
err_counts = []
for value in tune_value_list:
err = info.tmp_err_map.get(value, -2)
if err < 0:
err_str = "70000"
else:
err_str = str(err)
err_counts.append(err_str)
row_data = [
host,
exp,
info.preset,
info.slot_id,
info.logic_lane,
info.rt_phys_id,
info.rt_phys_lane,
] + err_counts
data_format = "{:<16} {:<6} {:<8} {:<6} {:<6} {:<6} {:<10} " + " ".join("{:<6}" for _ in tune_value_list)
logging.info(data_format.format(*row_data))
row_dict = dict(zip(header_parts, row_data))
row_dict["Timestamp"] = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
rows.append(row_dict)
except Exception as e:
logging.error(f"Error processing row for Slot {info.slot_id}, Lane {info.logic_lane}: {e}")
continue
# === 写入 Excel(增量追加)===
try:
# ✅ 修复点:read_excel 也要指定 engine='openpyxl'
try:
existing_df = pd.read_excel(excel_path, engine='openpyxl')
except FileNotFoundError:
existing_df = pd.DataFrame()
new_df = pd.DataFrame(rows)
updated_df = pd.concat([existing_df, new_df], ignore_index=True)
# ✅ 写入时也指定 engine(虽非必须,但更安全)
updated_df.to_excel(excel_path, index=False, engine='openpyxl')
logging.info(f"✅ Data appended to {excel_path}")
except Exception as e:
logging.error(f"Failed to write Excel file: {e}")
def load_inmpd_data(file_path="main_data/vdac/inmpd.xlsx"):
logging.info(f'load_inmpd_data')
if not os.path.exists(file_path):
raise FileNotFoundError(f"Excel file not found: {file_path}")
try:
logging.info(f"Opening Excel file: {file_path}")
xls = pd.ExcelFile(file_path, engine='openpyxl')
logging.info(f"Excel file opened successfully. Sheets: {xls.sheet_names}")
except Exception as e:
raise ValueError(f"Failed to open Excel file '{file_path}': {e}")
required_cols = ['sn', 'lane', 'inmpd', 'temp']
all_data = []
logging.info(f'step 1.1')
for sheet_name in xls.sheet_names:
try:
logging.info(f'step 2')
df = pd.read_excel(xls, sheet_name=sheet_name)
# 标准化列名:转小写并去除前后空格
df.columns = df.columns.astype(str).str.strip().str.lower()
logging.info(f'step 3')
# 检查是否包含所有必需列
if not all(col in df.columns for col in required_cols):
missing = set(required_cols) - set(df.columns)
print(f" Sheet '{sheet_name}' skipped: missing columns {missing}")
continue
# 提取所需列
selected = df[required_cols].copy()
all_data.append(selected)
except Exception as e:
print(f"❌ Error reading sheet '{sheet_name}': {e}")
if not all_data:
raise ValueError("No valid sheet contains all required columns: sn, lane, inmpd, temp")
# 合并所有有效数据
combined_df = pd.concat(all_data, ignore_index=True)
return combined_df
def inmpd_check(host: str, local_bmc: DevWhiteRiverExp, exp_id: int, slot_list: list,
local_reg_tool: OptRegAccessTool, output_dir: str = "tmp_data/inmpd"):
logging.info('step 1')
inmpd_df = load_inmpd_data() # DataFrame with columns: sn, lane, inmpd, temp
logging.info(f'Loaded {len(inmpd_df)} rows from Excel')
results = [] # 🟢 用于收集所有结果
for slot in slot_list:
sn = local_reg_tool.read_sn(exp_id, slot)
temp = local_reg_tool.read_temp(exp_id, slot)
logging.info(f"Processing slot {slot}, SN: {sn}, TEMP: {temp}")
matched_rows = inmpd_df[inmpd_df['sn'] == sn]
if matched_rows.empty:
logging.warning(f"No data found in Excel for SN: {sn}")
continue
# Step 1: 保存原始 IBIAS 并设置为 4096
ibias_lane_list = [0, 1, 2, 3]
raw_ibias_list = []
local_bmc.SetOpticalModuleRegs(exp_id, slot, 0, 0xB4, 0x88, 1, '01')
time.sleep(0.05)
for lane in ibias_lane_list:
# raw_ibias = local_reg_tool.read_ibias_reg_by_ibias_lane(exp_id, slot, lane)
# raw_ibias_list.append(raw_ibias)
# time.sleep(0.05)
local_reg_tool.write_vol_ibias_reg_by_ibias_lane(exp_id, slot, lane, 4096)
time.sleep(0.05)
time.sleep(2)
# Step 2: 读取 INMPD,并恢复 IBIAS
for lane in ibias_lane_list:
ibias = local_reg_tool.read_vol_ibias_reg_by_ibias_lane(exp_id, slot, lane)
pic_inmpd = local_reg_tool.read_pic_inmpd(exp_id, slot, lane)
try:
pic_inmpd_dbm = round(10 * math.log10(pic_inmpd / 2 * 41.88034 / 10000), 3)
except (ValueError, ZeroDivisionError):
pic_inmpd_dbm = float('nan')
# time.sleep(0.05)
# local_reg_tool.write_ibias_reg_by_ibias_lane(exp_id, slot, lane, raw_ibias_list[lane])
# time.sleep(0.05)
cm_inmpd = -1
cm_inmpd_dbm = float('nan')
cm_temp = -1
target_inmpd_lane = (lane + 1) * 2
for _, row in matched_rows.iterrows():
inmpd_lane = int(row['lane'])
if inmpd_lane == target_inmpd_lane:
cm_inmpd = int(row['inmpd'])
try:
cm_inmpd_dbm = round(10 * math.log10(cm_inmpd / 2 * 41.88034 / 10000), 3)
except (ValueError, ZeroDivisionError):
cm_inmpd_dbm = float('nan')
cm_temp = int(row['temp'])
break
# 安全计算 ratio
if cm_inmpd == 0:
ratio = float('nan')
else:
ratio = (cm_inmpd - pic_inmpd) / cm_inmpd
result_entry = {
'host': host,
'exp_id': exp_id,
'sn': sn,
'slot': slot,
'lane': lane,
'current_temp': temp,
'cm_temp': cm_temp,
'ibias': ibias,
'current_inmpd': pic_inmpd,
'cm_inmpd': cm_inmpd,
'pic_inmpd_dbm': pic_inmpd_dbm,
'cm_inmpd_dbm': cm_inmpd_dbm,
'inmpd_ratio': ratio,
}
results.append(result_entry)
# ✅ 统一打印所有结果
for entry in results:
ratio_pct = entry['inmpd_ratio'] * 100 if not pd.isna(entry['inmpd_ratio']) else float('nan')
ratio_str = f"{ratio_pct:.2f}%" if not pd.isna(ratio_pct) else "N/A"
logging.info(
f"host: {entry['host']}, "
f"exp: {entry['exp_id']}, "
f"sn: {entry['sn']}, "
f"ibias: {entry['ibias']}, "
f"slot: {entry['slot']}, "
f"lane: {entry['lane']}, "
f"temp(current/cm): {entry['current_temp']}/{entry['cm_temp']}, "
f"inmpd(current/cm): {entry['current_inmpd']}/{entry['cm_inmpd']}, "
f"inmpd_dbm(current/cm): {entry['pic_inmpd_dbm']}/{entry['cm_inmpd_dbm']}, "
f"inmpd_ratio: {ratio_str}"
)
# ✅ 保存到 Excel
if results:
df_results = pd.DataFrame(results)
os.makedirs(output_dir, exist_ok=True)
timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
filename = f"{output_dir}/inmpd_check_{host}_exp{exp_id}_{timestamp}.xlsx"
df_results.to_excel(filename, index=False)
logging.info(f"Results saved to: {filename}")
else:
logging.warning("No valid results to save.")
return results
def process_host(host, reg_table_file, exp_list, slot_list, rtmr_list, lane_list, cmd: str, param, reg_wt_value, sl_file):
# logging.info(f'-----------process: {host}')
ibias_rssi_map_file = '/xz/gyou/nexusbench/main_data/ibias-rssi-map.json'
if Path(ibias_rssi_map_file).exists() == False:
logging.error(f'ibias_rssi_map_file {ibias_rssi_map_file} not found!')
return
ibias_rssi_map = IbiasRssiMapParser(ibias_rssi_map_file)
for exp_id in exp_list:
exp_id = int(exp_id)
exp_util = SmbusHttpUtil(f"https://{host}", "root", "0penBmc", host)
exp_util.lock(exp_id)
logging.info(f'----------process_host {host} lock')
vuart_util = VuartUtil(host)
bmc = DevWhiteRiverExp(exp_util, vuart_util)
route_info = bmc.GetOpticalRouteStatus(exp_id, 0)
# logging.info(f'--------GetOpticalRouteStatus route_info:{route_info}')
yaml_route_map = {
'1111111111111111': '786-1-oneta',
'1212121212121212': '786-1-onetb',
'0201040306050807': '786-1-onoc1',
'0403020108070605': '786-1-onoc2',
'0807060504030201': '786-1-onoc3',
'0304010207080506': '786-1-onoc4',
'0605080702010403': '786-1-onoc5',
'0708050603040102': '786-1-onoc6',
'0506070801020304': '786-1-onoc7',
}
reg_table_file = f'/xz/gyou/nexusbench/main_data/{yaml_route_map[route_info]}.yaml'
route_name = yaml_route_map[route_info]
# logging.info(f'input reg_table_file is empty, use default config file:{reg_table_file}, route_name:{route_name}')
if Path(reg_table_file).exists():
# print(f"File exists: {reg_table_file}")
reg_access_tool = OptRegAccessTool(host, reg_table_file, bmc)
logging.info(f'init reg_access_tool with reg_table_file:{reg_table_file}, route_name:{route_name}')
remote_reg_access_tool = reg_access_tool
# else:
# print(f"File NOT found: {file_path}")
remote_bmc = None
remote_exp_util = exp_util
remote_host = host
if cmd in ['ibias-auto-tune', 'plot-mgc-vpeak', 'eq-auto-tune', 'tune-rd', 'tune-wt', 'rssi-check', 'err-check',
'rtmr-prbs', 'rtmr-prbs-test', 'ctle-auto-tune', 'mgc-auto-tune', 'mgc-auto-tune2', 'lowfreq-auto-tune',
'highfreq-auto-tune', 'tiapeak-auto-tune', 'opcurrent-auto-tune', 'opcurrent-auto-tune-test', 'rt-ibias', 'rt-mgc'] and remote_ip != '':
logging.info(f'------- remote_host: {remote_ip}')
remote_host = remote_ip
remote_exp_util = SmbusHttpUtil(f"https://{remote_host}", "root", "0penBmc", remote_host)
remote_bmc = DevWhiteRiverExp(remote_exp_util, vuart_util)
remote_exp_util.lock(exp_id)
logging.info(f'----------process dst host {remote_host} lock')
remote_reg_access_tool = OptRegAccessTool(remote_host, reg_table_file, remote_bmc)
if cmd in ['eq-auto-tune', 'rtmr-prbs-test', 'tune-rd', 'tune-wt', 'mgc-auto-tune2', 'lowfreq-auto-tune', 'err-check', 'highfreq-tune',
'highfreq-auto-tune', 'tiapeak-auto-tune', 'opcurrent-auto-tune', 'opcurrent-auto-tune-test', 'rt-ibias', 'rt-mgc']:
slot_list = [0,1,2,3,4,5,6,7]
if cmd in ['reg-rd', 'inmpd-check', 'reg-rd-test', 'tx-enable', 'tx-disable', 'rtmr-prbs-test', 'swa-auto-tune', 'swb-auto-tune', 'mzm-auto-tune', 'opcurrent-tune', 'reg-wt', 'rssi-check', 'eye-check', 'err-check', \
'topo-config', 'plot-mgc-vpeak', 'mgc-auto-tune', 'mgc-auto-tune2', 'lowfreq-auto-tune',
'highfreq-auto-tune', 'tiapeak-auto-tune', 'opcurrent-auto-tune', 'opcurrent-auto-tune-test', 'rt-ibias', 'rt-mgc', 'mgc-manual-tune',
'mgc-calc-target-vpeak', 'ibias-auto-tune', 'reg-save', 'reg-load',
'highfreq-tune', 'tia-peak-tune', 'eq-auto-tune', 'tune-rd', 'tune-wt']:
for slot_id in slot_list:
# read sn
logging.info('------------ Authentication 1')
Authentication(bmc, exp_id, slot_id)
# res_data = bmc.GetOpticalModuleRegs(exp_id, slot_id, 0, 0, 166, 16)
# logging.debug(res_data)
# bytes_data = bytes.fromhex(res_data)
# ascii_str = bytes_data.decode('ascii', errors='ignore')
# logging.info(f'----------------slot: {slot_id}, sn:{ascii_str}')
if remote_bmc:
logging.info('------------ Authentication 2')
Authentication(remote_bmc, exp_id, slot_id)
# res_data = remote_bmc.GetOpticalModuleRegs(exp_id, slot_id, 0, 0, 166, 16)
# logging.debug(res_data)
# bytes_data = bytes.fromhex(res_data)
# ascii_str = bytes_data.decode('ascii', errors='ignore')
# logging.info(f'----------------Remote slot: {slot_id}, sn:{ascii_str}')
# mod_type = ReadModuleType(bmc, exp_id, slot_id)
# logging.info(f'Raw mod_type: {repr(mod_type)}')
# file_module_type = reg_access_tool.parser.get_module_type()
# is_valid_combination = (
# (mod_type.startswith('0.0.0') and file_module_type == 'batch0') or
# (mod_type.startswith('ISGD5680H') and file_module_type == 'batch1') or
# (mod_type.startswith('XZDRV') and file_module_type == 'batch2'))
# if not is_valid_combination:
# logging.error(f'config file is not match!')
# sys.exit()
if cmd == 'read-sn':
logging.info(f'slot_list: {slot_list}')
check_module_tct_status(host, bmc, exp_id, slot_list)
# for slot_id in slot_list:
# res_data = bmc.GetOpticalModuleRegs(exp_id, slot_id, 0, 0, 166, 16)
# bytes_data = bytes.fromhex(res_data)
# ascii_str = bytes_data.decode('ascii', errors='ignore')
# logging.info(f'----------------host: {host}, exp: {exp_id}, slot: {slot_id}, sn:{ascii_str}')
elif cmd == 'reg-rd-test':
rd_regs = param_list
# all_lane_reg_values: List[LaneRegInfo] = reg_access_tool.read_opt_regs(exp_id, slot_list, lane_list, rd_regs)
for slot in slot_list:
value = bmc.GetOpticalModuleRegs(exp_id=exp_id, slot_id=slot, bank=0x00, page=0xCD, reg_offset=0xB0, size=14)
logging.info(f'00 CD B0: {value}')
value = bmc.GetOpticalModuleRegs(exp_id=exp_id, slot_id=slot, bank=0x00, page=0xCD, reg_offset=0x90, size=14)
logging.info(f'00 CD 90: {value}')
time.sleep(0.05)
bmc.SetOpticalModuleRegs(exp_id=exp_id, slot_id=slot, bank=0x00, page=0xCD, reg_offset=0xB0, size=14, hex_str='00c000c000c000c000c000c000c0')
time.sleep(0.05)
bmc.SetOpticalModuleRegs(exp_id=exp_id, slot_id=slot, bank=0x00, page=0xCD, reg_offset=0x90, size=14, hex_str='0080008000800080008000800080')
time.sleep(0.05)
value = bmc.GetOpticalModuleRegs(exp_id=exp_id, slot_id=slot, bank=0x00, page=0xCD, reg_offset=0xB0, size=14)
logging.info(f'00 CD B0: {value}')
value = bmc.GetOpticalModuleRegs(exp_id=exp_id, slot_id=slot, bank=0x00, page=0xCD, reg_offset=0x90, size=14)
logging.info(f'00 CD 90: {value}')
# value = bmc.GetOpticalModuleRegs(exp_id=exp_id, slot_id=0, bank=0x01, page=0xC2, reg_offset=0x88, size=16)
# logging.info(f'01 C2 88: {value}')
# value = bmc.GetOpticalModuleRegs(exp_id=exp_id, slot_id=0, bank=0x00, page=0xC5, reg_offset=0x80, size=128)
# logging.info(f'value: {value}')
# # 确保 value 是偶数长度(安全处理)
# if len(value) % 2 != 0:
# logging.warning("Hex string has odd length, padding with a leading zero.")
# value = '0' + value
# # 每两个字符一组,转为字节列表
# bytes_list = [value[i:i+2] for i in range(0, len(value), 2)]
# # 起始寄存器地址
# start_reg = 0x80
# # 打印每个字节及其对应寄存器地址
# for idx, byte_hex in enumerate(bytes_list):
# reg_addr = start_reg + idx
# logging.info(f"[0x{reg_addr:02X}] = 0x{byte_hex.upper()}")
elif cmd == 'reg-rd':
rd_regs = param_list
all_lane_reg_values: List[LaneRegInfo] = reg_access_tool.read_opt_regs(exp_id, slot_list, lane_list, rd_regs)
if not all_lane_reg_values:
print("No register data read.")
else:
# 提取 slot 和 lane 顺序(只需一次)
slots = [item.slot_id for item in all_lane_reg_values]
lanes = [item.logic_lane for item in all_lane_reg_values]
# 对 rd_regs 中每个寄存器,单独打印
for reg_name in rd_regs:
values = []
for item in all_lane_reg_values:
try:
value = getattr(item, reg_name)
values.append(value)
except AttributeError:
# 寄存器不存在,跳过该项
continue
if values: # 只有当找到至少一个有效值时才打印
print(f"host: {host} exp: {exp_id} reg: {reg_name} slot: {slot_list} lane: {lane_list}")
print(f"value: {values}\n")
elif cmd == 'reg-wt':
wt_regs = param_list
if 'ibias_runtime' in wt_regs:
for slot_id in slot_list:
bmc.SetOpticalModuleRegs(exp_id, slot_id, 0, 0xB4, 0x88, 1, '01')
time.sleep(0.05)
if 'ibias' in wt_regs:
for slot_id in slot_list:
bmc.SetOpticalModuleRegs(exp_id, slot_id, 0, 0xB4, 0x88, 1, '00')
time.sleep(0.05)
reg_access_tool.write_opt_regs(exp_id, slot_list, lane_list, wt_regs, reg_wt_value)
if 'mgc' in wt_regs:
for slot_id in slot_list:
reg_access_tool.write_confirm_reg(exp_id, slot_id)
# if host == '10.57.216.91':
# for slot_id in slot_list: # 或 for slot_id in raw_data.keys()
# lane_values = raw_data_91[slot_id]
# logging.info(f"step 1, slot{slot_id} lane_values: {lane_values}")
# for lane_id in lane_list:
# value = lane_values[lane_id]
# logging.info("step 2")
# reg_access_tool.write_opt_regs(exp_id, [slot_id], [lane_id], ['swa_h','swa_m','swa_l'],str(value))
# if host == '10.57.216.94':
# for slot_id in slot_list: # 或 for slot_id in raw_data.keys()
# lane_values = raw_data_94[slot_id]
# logging.info(f"step 1, slot{slot_id} lane_values: {lane_values}")
# for lane_id in lane_list:
# value = lane_values[lane_id]
# logging.info("step 2")
# reg_access_tool.write_opt_regs(exp_id, [slot_id], [lane_id], ['swa_h','swa_m','swa_l'],str(value))
elif cmd == 'tx-enable':
wt_regs = param_list
for slot in slot_list:
reg_access_tool.tx_enable(exp_id, slot)
elif cmd == 'tx-disable':
wt_regs = param_list
for slot in slot_list:
reg_access_tool.tx_disable(exp_id, slot)
elif cmd == 'opcurrent-tune':
all_lane_reg_values: List[LaneRegInfo] = reg_access_tool.read_opt_regs(exp_id, slot_list, lane_list, ['opcurrent'])
for lane_reg_value in all_lane_reg_values:
if lane_reg_value.opcurrent < 140:
logging.info(f'exp_id:{exp_id}, slot: {[lane_reg_value.slot_id]}, lane: {[lane_reg_value.logic_lane]}, opcurrent: {lane_reg_value.opcurrent}, need change to 130')
reg_access_tool.write_opt_regs(exp_id, [lane_reg_value.slot_id], [lane_reg_value.logic_lane], ['opcurrent'], '130')
elif cmd == 'rssi-check':
RssiCheck(reg_access_tool, remote_reg_access_tool, bmc, host, exp_id, slot_list, ibias_rssi_map, route_name)
elif cmd == 'eye-check':
EyeCheck(host, bmc, exp_id, slot_list, lane_list, remote_bmc, route_name, reg_access_tool, remote_reg_access_tool)
elif cmd == 'err-check':
# logging.info(param)
# logging.info(param_list)
if rtmr_list == ['']:
retimers = [1,2,3,4]
else:
retimers = [int(x) for x in rtmr_list]
is_show_all = False
if param == 'show-all':
is_show_all = True
RecvErrCheck(host, remote_host, bmc, exp_id, slot_list, retimers, remote_bmc, route_name, reg_access_tool, remote_reg_access_tool, False, is_show_all)
elif cmd == 'recv-check':
if rtmr_list == ['']:
retimers = [1,2,3,4]
else:
retimers = [int(x) for x in rtmr_list]
RecvErrCheck(host, remote_host, bmc, exp_id, slot_list, retimers, remote_bmc, route_name, reg_access_tool, remote_reg_access_tool, True)
elif cmd == 'inmpd-check':
inmpd_check(host, bmc, exp_id, slot_list, reg_access_tool)
elif cmd == 'tia-peak-tune':
wt_regs = param_list
TiaPeakTune(reg_access_tool, bmc, host, exp_id, slot_list, lane_list, wt_regs)
elif cmd == 'mgc-tune':
MgcTune(reg_access_tool, bmc, host, exp_id, slot_list, lane_list, reg_wt_value)
elif cmd == 'exp-cold-reset':
ExpColdReset(bmc, exp_id)
elif cmd in ['plot-mgc-vpeak', 'mgc-auto-tune', 'mgc-auto-tune2', 'tiapeak-auto-tune', 'highfreq-auto-tune',
'lowfreq-auto-tune', 'opcurrent-auto-tune', 'opcurrent-auto-tune-test', 'rt-ibias', 'rt-mgc', 'mgc-manual-tune', 'mgc-calc-target-vpeak']:
logging.info(f'reg_table_file:{reg_table_file}')
AutoTuneMGC(host, bmc, remote_bmc, reg_access_tool, remote_reg_access_tool,
exp_id, slot_list, lane_list, reg_access_tool.parser, cmd, route_name)
elif cmd == 'ibias-auto-tune':
logging.info(f'------------ param: {param}')
if rtmr_list == ['']:
retimers = [1,2,3,4]
else:
retimers = [int(x) for x in rtmr_list]
if remote_bmc is None:
remote_bmc = bmc
prbs_tool = PrbsTool(bmc, remote_bmc, reg_access_tool, remote_reg_access_tool, route_name)
if param == '':
preset = 9
else:
preset = int(param)
prbs_tool.ResetRetimerAndEnablePrbs(exp_id, retimers, preset)
if remote_bmc == bmc:
# AutoTuneIbias(host, bmc, exp_id, slot_list, lane_list, reg_access_tool.parser, route_name)
AutoTuneIbiasOnet(host, bmc, exp_id, slot_list, lane_list, bmc, reg_table_file, route_name, ibias_rssi_map)
else:
# bmc.TopoConfig(exp_id, '32')
# remote_bmc.TopoConfig(exp_id, '32')
# bmc.TopoConfig(exp_id, '32')
# remote_bmc.TopoConfig(exp_id, '32')
AutoTuneIbiasOnet(host, bmc, exp_id, slot_list, lane_list, remote_bmc, reg_table_file, route_name, ibias_rssi_map)
AutoTuneIbiasOnet(host, remote_bmc, exp_id, slot_list, lane_list, bmc, reg_table_file, route_name, ibias_rssi_map)
# elif cmd == 'lowfreq-auto-tune':
# AutoTuneLowFreq(host, bmc, exp_id, slot_list, reg_table_file, cmd)
elif cmd == "highfreq-tune":
wt_regs = param_list
TuneHighFreq(reg_access_tool, exp_id)
elif cmd == 'swa-auto-tune':
SwaAutoTune(host, bmc, exp_id, slot_list, lane_list, remote_bmc, route_name, reg_access_tool, remote_reg_access_tool)
elif cmd == 'swb-auto-tune':
SwbAutoTune(host, bmc, exp_id, slot_list, lane_list, remote_bmc, route_name, reg_access_tool, remote_reg_access_tool)
elif cmd == 'mzm-auto-tune':
MzmAutoTune(host, bmc, exp_id, slot_list, lane_list, remote_bmc, route_name, reg_access_tool, remote_reg_access_tool)
elif cmd == 'rtmr-prbs':
if remote_host != '':
host_list = f'{host},{remote_host}'
else:
host_list = host
cms_str = ["ocs_link_reset", "-i", f"{host_list}", "-e", f"{exp_id}"]
logging.info(f'---- cmd: {cms_str}')
result = subprocess.run(cms_str, timeout=30)
time.sleep(6)
if result.returncode == 0:
print("ocs link reset success")
else:
print("ocs link reset failed")
logging.info(param)
logging.info(param_list)
if param_list == ['']:
retimers = [1,2,3,4]
else:
retimers = [int(x) for x in param_list]
if remote_bmc is None:
remote_bmc = bmc
remote_reg_access_tool = reg_access_tool
prbs_tool = PrbsTool(bmc, remote_bmc, reg_access_tool, remote_reg_access_tool, route_name)
logging.info('--------step 2')
logging.info(f"------slot_list: {slot_list}")
prbs_tool.ResetRetimerAndEnablePrbs(exp_id, retimers)
elif cmd == 'rtmr-ctle-wt':
logging.info(f'--------- rtmr-ctle-wt, rtmr_list: {rtmr_list}')
WriteRtmrCtle(host, exp_id, bmc, rtmr_list, lane_list, int(param))
CommitRtmrCtle(exp_id, bmc, rtmr_list)
elif cmd == 'rtmr-prbs-test':
if remote_host != '' and host != remote_host:
host_list = f'{host},{remote_host}'
else:
host_list = host
# cms_str = ["ocs_link_reset", "-i", f"{host_list}", "-e", f"{exp_id}"]
# logging.info(f'---- cmd: {cms_str}')
# result = subprocess.run(cms_str, timeout=30)
# time.sleep(6)
# if result.returncode == 0:
# print("ocs link reset success")
# else:
# print("ocs link reset failed")
logging.info(param)
logging.info(param_list)
if param_list == ['']:
retimers = [1,2,3,4]
else:
retimers = [int(x) for x in param_list]
if remote_bmc is None:
remote_bmc = bmc
remote_reg_access_tool = reg_access_tool
prbs_tool = PrbsTool(bmc, remote_bmc, reg_access_tool, remote_reg_access_tool, route_name)
logging.info(f"------slot_list: {slot_list}")
logging.info("----------step 1: reset retimer")
prbs_tool.ResetRetimer(exp_id, retimers)
time.sleep(1)
logging.info("----------step 2: enable prbs")
# all_rtmr_lane_settings: List[RetimerLaneSetting] = load_ctle_config(host, route_name, exp_id)
# for lane_setting in all_rtmr_lane_settings:
# WriteRtmrCtle(host, exp_id, bmc, [lane_setting.rtmr_id], [lane_setting.rtmr_lane], lane_setting.ctle)
# time.sleep(0.05)
# if all_rtmr_lane_settings:
# CommitRtmrCtle(exp_id, bmc, retimers)
# prbs_tool.EnableTxPrbsDebug(exp_id, retimers)
prbs_tool.EnableTxPrbs(exp_id, retimers)
prbs_tool.prbs_check(exp_id, retimers, True)
time.sleep(2)
prbs_tool.prbs_check(exp_id, retimers, False)
elif cmd == 'ctle-auto-tune':
if remote_host != '' and host != remote_host:
host_list = f'{host},{remote_host}'
else:
host_list = host
cms_str = ["ocs_link_reset", "-i", f"{host_list}", "-e", f"{exp_id}"]
logging.info(f'---- cmd: {cms_str}')
result = subprocess.run(cms_str, timeout=30)
time.sleep(6)
if result.returncode == 0:
print("ocs link reset success")
else:
print("ocs link reset failed")
logging.info(param)
logging.info(param_list)
if rtmr_list == ['']:
retimers = [1,2,3,4]
else:
retimers = [int(x) for x in rtmr_list]
if remote_bmc is None:
remote_bmc = bmc
remote_reg_access_tool = reg_access_tool
prbs_tool = PrbsTool(bmc, remote_bmc, reg_access_tool, remote_reg_access_tool, route_name)
logging.info(f"------slot_list: {slot_list}")
logging.info("----------step 1: reset retimer")
prbs_tool.ResetRetimer(exp_id, retimers)
time.sleep(1)
logging.info("----------step 2: enable prbs")
# all_rtmr_lane_settings: List[RetimerLaneSetting] = load_ctle_config(host, route_name, exp_id)
# for lane_setting in all_rtmr_lane_settings:
# # WriteRtmrCtle(host, exp_id, bmc, [lane_setting.rtmr_id], [lane_setting.rtmr_lane], 0)
# WriteRtmrCtle(host, exp_id, bmc, [lane_setting.rtmr_id], [lane_setting.rtmr_lane], lane_setting.ctle)
# time.sleep(0.05)
tune_value_list = [0, 2, 4, 6, 8, 10, 12, 14, 16, 18]
# tune_value_list = [0, 18]
lane_data_list: List[LaneErrInfo] = []
topo_map = TopoMappingParser("/xz/gyou/nexusbench/main_data/topo_mapping.yaml")
topo_map.parse()
for slot_id in [0, 1, 2, 3, 4, 5, 6, 7]:
for lane in [0, 1, 2, 3, 4, 5, 6, 7]:
tmp_err_map = {value: -1 for value in tune_value_list}
result = topo_map.get_phys_rtmr_by_slot(slot_id, lane, route_name)
if result:
success, rt_phys_id, rt_phys_lane = result
if success == False:
logging.error(f'get_phys_rtmr_by_slot failed, result: {success}')
return False
lane_info = LaneErrInfo(
slot_id=slot_id,
logic_lane=lane,
rt_phys_id=rt_phys_id,
rt_phys_lane=rt_phys_lane,
tmp_err_map=tmp_err_map
)
lane_data_list.append(lane_info)
if param == '':
logging.info(f"preset is empty, please set preset by param")
preset_list = [int(param)]
for preset in preset_list:
for ctle in tune_value_list:
for rtmr in retimers:
for rt_lane in range(16):
WriteRtmrCtle(host, exp_id, bmc, [rtmr], [rt_lane], ctle)
time.sleep(0.05)
# if all_rtmr_lane_settings:
CommitRtmrCtle(exp_id, bmc, retimers)
prbs_tool.EnableTxPrbs(exp_id, retimers, preset)
prbs_tool.prbs_check(exp_id, retimers, True)
time.sleep(5)
prbs_results = prbs_tool.prbs_check(exp_id, retimers, False)
# logging.info(f'-------------- prbs_results: {prbs_results}')
for prbs in prbs_results:
logging.info(f'rtmr_id: {prbs.rtmr_id}, lane: {prbs.rtmr_lane}, route: {route_name}')
slot = topo_map.get_local_slot_by_retimer(prbs.rtmr_id, prbs.rtmr_lane, route_name)
if not slot:
logging.error(f'local slot is none!')
return False
slot_id, lane_id = slot
for info in lane_data_list:
if info.slot_id == slot_id and info.logic_lane == lane_id:
info.preset = preset
# logging.info(f'--------- start modify, value: {value}, prbs.locked: {prbs.locked}')
if prbs.locked:
info.tmp_err_map[ctle] = prbs.err_count
else:
info.tmp_err_map[ctle] = 69999
# logging.info(f'------prbs unlock, {value}: {info.tmp_err_map[value]}')
# logging.info(f'info.tmp_err_map: {info.tmp_err_map}')
break
for rtmr in retimers:
bmc.CmdVendorCommand(exp_id, f'rtmr {rtmr} phy full')
time.sleep(1)
rd_regs = ['mgc']
slot_list = [0,1,2,3,4,5,6,7]
all_lane_reg_values: List[LaneRegInfo] = reg_access_tool.read_opt_regs(exp_id, slot_list, [0,1,2,3,4,5,6,7], rd_regs)
if not all_lane_reg_values:
print("No register data read.")
else:
# 提取 slot 和 lane 顺序(只需一次)
slots = [item.slot_id for item in all_lane_reg_values]
lanes = [item.logic_lane for item in all_lane_reg_values]
# 对 rd_regs 中每个寄存器,单独打印
for reg_name in rd_regs:
values = [getattr(item, reg_name) for item in all_lane_reg_values]
logging.info(f"host: {host} exp: {exp_id} reg: {reg_name} slot: {slot_list} lane: {lane_list}")
logging.info(f"value: {values}\n")
print_general_err_matrix(host, exp_id, lane_data_list, tune_value_list)
elif cmd == "rtmr-reset":
if remote_host != '':
host_list = f'{host},{remote_host}'
else:
host_list = host
logging.info(param)
logging.info(param_list)
if param_list == ['']:
retimers = [1,2,3,4]
else:
retimers = [int(x) for x in param_list]
if remote_bmc is None:
remote_bmc = bmc
remote_reg_access_tool = reg_access_tool
prbs_tool = PrbsTool(bmc, remote_bmc, reg_access_tool, remote_reg_access_tool, route_name)
logging.info('--------step 2')
logging.info(f"------slot_list: {slot_list}")
# prbs_tool.ResetRetimer(exp_id, retimers)
# logging.info(f'host: {host_list}')
# with ThreadPoolExecutor(max_workers=len(host_list)) as executor:
# executor.map(process_rtmr_waram_reset, host_list)
rtmr_reset_and_port_reset(bmc, exp_id)
elif cmd == "vcmd":
bmc.CmdVendorCommand(exp_id, param)
elif cmd == "eq-auto-tune":
logging.info(f'------------ param: {param}')
AutoTuneEq(host, bmc, exp_id, slot_list, lane_list, remote_bmc, route_name, reg_access_tool, remote_reg_access_tool)
elif cmd == "calc-ctle-map":
logging.info(f'------------ param: {param}')
CalcCtleMap(host, bmc, exp_id, slot_list, lane_list, remote_bmc, route_name, reg_access_tool, remote_reg_access_tool)
elif cmd == "topo-config":
bmc.TopoConfig(exp_id, param)
elif cmd == "exp-stat":
bmc.GetExpStatus(exp_id)
elif cmd == 'reg-save':
regs = param_list
logging.info(f'--------param_list:{param_list}')
if regs == ['']:
regs = ['mgc', 'vpeak', 'tia_peak', 'ibias', 'ipcurrent', 'opcurrent',
'lowfreq_eq', 'highfreq_eq', 'vgc_set', 'drv_vpeak', 'rssi',
'swa_onoc_h', 'swa_onoc_m', 'swa_onoc_l', 'swa_onet_h', 'swa_onet_m', 'swa_onet_l',
'swb_oneta_h', 'swb_oneta_m', 'swb_oneta_l', 'swb_onetb_h', 'swb_onetb_m', 'swb_onetb_l']
SaveRegsToFile(reg_access_tool, host, exp_id, slot_list, route_name, lane_list, regs, sl_file)
elif cmd == 'reg-load':
regs = param_list
logging.info(f'--------param_list:{param_list}')
# if regs == ['']:
# logging.error('regs is empty')
# regs = ['mgc', 'tia_peak', 'ibias', 'ipcurrent', 'opcurrent',
# 'lowfreq_eq', 'highfreq_eq', 'vgc_set', 'drv_vpeak']
LoadRegsToFile(reg_access_tool, host, exp_id, slot_list, route_name, regs, sl_file)
elif cmd == 'tune-rd':
rtmr_id = int(param_list[0])
rtmr_lane = int(param_list[1])
TuneView(host, bmc, exp_id, slot_list, lane_list, remote_bmc,
route_name, reg_access_tool, remote_reg_access_tool,
rtmr_id, rtmr_lane)
elif cmd == 'tune-wt':
rtmr_id = int(param_list[0])
rtmr_lane = int(param_list[1])
reg_name_value = reg_wt_value.split('=')
TuneWrite(host, bmc, exp_id, slot_list, lane_list, remote_bmc,
route_name, reg_access_tool, remote_reg_access_tool,
rtmr_id, rtmr_lane, reg_name_value[0], int(reg_name_value[1]))
elif cmd == 'set-power':
SetPower(host, exp_id, bmc, param)
else:
logging.error(f"Invalid command: {cmd}")
exp_util.unlock(exp_id)
logging.info(f'----------process_host {host} exp {exp_id} unlock')
if cmd in ['ibias-auto-tune', 'eq-auto-tune', 'tune-rd', 'tune-wt', 'rssi-check', 'err-check', 'rtmr-prbs', 'rtmr-prbs-test', 'ctle-auto-tune', 'mgc-auto-tune',
'mgc-auto-tune2', 'lowfreq-auto-tune', 'highfreq-auto-tune', 'opcurrent-auto-tune', 'opcurrent-auto-tune-test', 'tiapeak-auto-tune'] and remote_ip != '':
if remote_exp_util:
remote_exp_util.unlock(exp_id)
logging.info(f'----------process dst host {remote_host} exp {exp_id} unlock')
def expand_ip(ip: str) -> str:
if '.' in ip:
return ip # 已经是完整 IP,直接返回
try:
last_octet = int(ip)
if 0 <= last_octet <= 255:
return f"10.57.216.{last_octet}"
else:
raise ValueError(f"Invalid IP last octet: {last_octet}")
except ValueError as e:
raise ValueError(f"Invalid IP format: {ip}, must be x.x.x.x or 0-255") from e
if __name__ == "__main__":
Logger.init_logging(log_folder='logs', level=logging.INFO)
parser = argparse.ArgumentParser(description="XZtech OCS Diag Tool (v0.2@20260106)")
parser.add_argument("--host", "-i", type=str, required=False, default='', help="")
parser.add_argument("--remote_host", "-r", type=str, required=False, default='', help="")
parser.add_argument("--os_host", "-o", type=str, required=False, default='', help="")
parser.add_argument("--exp", "-e", type=str, required=True, default='', help="")
parser.add_argument("--slot", "-s", type=str, default='0', help="")
parser.add_argument("--rtmr", "-rt", type=str, default='all', help="")
parser.add_argument("--lane", "-l", type=str, default='all', help="default all lane")
parser.add_argument("--cmd", "-c", required=True, type=str, default='',
help="" )
# parser.add_argument("--cmd", "-c", required=True, type=str, default='',
# help="exp-cold-reset, exp_stat, rtmr-prbs, rtmr-reset, reg-rd, reg-wt, vcmd, \
# topo-config, mgc-auto-tune, mgc-manual-tune, mgc-calc-target-vpeak, \
# ibias-auto-tune, reg-save, reg-load, lowfreq-auto-tune, highfreq-tune, tia-peak-tune, eq-auto-tune, tune-view" )
parser.add_argument("--param", "-p", type=str, default='', help="param for cmd")
parser.add_argument("--value", "-v", type=str, default='', help="value of reg-rd")
parser.add_argument("--reg_table", type=str, default='', help="")
parser.add_argument("--sl_file", type=str, default='',
help="default")
args = parser.parse_args()
# config_file = args.rw_config
reg_table_file = args.reg_table
# logging.info(reg_table_file)
sl_file = args.sl_file
# logging.info(f'-------save load file: {sl_file}')
host_list = [expand_ip(h.strip()) for h in args.host.split(',') if h.strip()]
# logging.info(f'------ host_list: {host_list}')
os_host_list = [expand_ip(h.strip()) for h in args.os_host.split(',') if h.strip()]
# logging.info(f'------ os_host_list: {os_host_list}')
if hasattr(args, 'remote_host') and args.remote_host:
remote_ip = expand_ip(args.remote_host.strip())
logging.info(f'------ remote_ip: {remote_ip}')
else:
remote_ip = ''
exp_list = args.exp.split(',')
cmd = args.cmd
if args.slot == 'all':
slot_list = [0,1,2,3,4,5,6,7]
else:
slot_list = list(map(int, args.slot.split(',')))
if args.rtmr == 'all':
rtmr_list = [1,2,3,4]
else:
rtmr_list = list(map(int, args.rtmr.split(',')))
logging.info(rtmr_list)
if args.lane == 'all':
lane_list = [0,1,2,3,4,5,6,7]
if cmd == 'rtmr-ctle-wt':
lane_list = [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15]
else:
lane_list = list(map(int, args.lane.split(',')))
# logging.info(f'------slot_list:{slot_list}')
param = ''
param_list = args.param.split(',')
if len(param_list) == 1:
param = args.param
reg_wt_value = args.value
if cmd == 'reg-wt' and reg_wt_value == '':
logging.error('reg write value is empty!')
sys.exit(1)
# with ThreadPoolExecutor(max_workers=len(host_list)) as executor:
# executor.map(process_host, host_list)
if cmd == 'link-train':
if param == '':
logging.error('topo name is empty!')
sys.exit()
else:
link_train(host_list, os_host_list, exp_list, f'mesh_{param}.json')
sys.exit()
elif cmd == 'gpu-reset':
gpu_reset(os_host_list)
sys.exit()
elif cmd == 'gpu-cto-disable':
gpu_cto_disable(os_host_list)
sys.exit()
with ThreadPoolExecutor(max_workers=1) as executor:
func_with_params = partial(process_host, reg_table_file=reg_table_file, exp_list=exp_list,
slot_list=slot_list, rtmr_list=rtmr_list, lane_list=lane_list, cmd=cmd, param=param,
reg_wt_value=reg_wt_value, sl_file=sl_file)
executor.map(func_with_params, host_list)