aboutsummaryrefslogtreecommitdiffstats
path: root/firmware
diff options
context:
space:
mode:
Diffstat (limited to 'firmware')
-rwxr-xr-xfirmware/usrp3/x300/x300_aurora_bist.py108
1 files changed, 101 insertions, 7 deletions
diff --git a/firmware/usrp3/x300/x300_aurora_bist.py b/firmware/usrp3/x300/x300_aurora_bist.py
index 225cd030b..f5e119b66 100755
--- a/firmware/usrp3/x300/x300_aurora_bist.py
+++ b/firmware/usrp3/x300/x300_aurora_bist.py
@@ -1,6 +1,3 @@
-from __future__ import print_function
-from builtins import str
-from builtins import range
#!/usr/bin/env python
#
# Copyright 2016 Ettus Research LLC
@@ -19,12 +16,17 @@ from builtins import range
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
+from __future__ import print_function
+from builtins import str
+from builtins import range
+
import x300_debug
import argparse
import time
import datetime
import math
import tqdm
+import numpy
########################################################################
# constants
@@ -86,9 +88,9 @@ def get_rate_setting(rate):
return (div-1, 8e-6 * BUS_CLK_RATE * (1.0 - 1.0/(div-1)))
return (0, 8e-6 * BUS_CLK_RATE)
-def run_loopback_bist(ctrls, duration, xxx_todo_changeme):
- (rate_sett, rate) = xxx_todo_changeme
- print('[INFO] Running Loopback BIST at %.0fMB/s for %.0fs...'%(rate,duration))
+def run_ber_loopback_bist(ctrls, duration, rate_tuple):
+ (rate_sett, rate) = rate_tuple
+ print('[INFO] Running BER Loopback BIST at %.0fMB/s for %.0fs...'%(rate,duration))
# Determine offsets
(mst_port, link_up) = get_aurora_info(ctrls['master'])
MST_MAC_REG_BASE = SFP0_MAC_REG_BASE if (mst_port == 0) else SFP1_MAC_REG_BASE
@@ -165,6 +167,93 @@ def run_loopback_bist(ctrls, duration, xxx_todo_changeme):
if 'slave' in ctrls:
ctrls['slave'].poke(SLA_MAC_REG_BASE + MAC_REG_CTRL, 0)
+def run_latency_loopback_bist(ctrls, duration, rate_tuple):
+ (rate_sett, rate) = rate_tuple
+ print('[INFO] Running Latency Loopback BIST at %.0fMB/s for %.0fs...'%(rate,duration))
+ # Determine offsets
+ (mst_port, link_up) = get_aurora_info(ctrls['master'])
+ MST_MAC_REG_BASE = SFP0_MAC_REG_BASE if (mst_port == 0) else SFP1_MAC_REG_BASE
+ if 'slave' in ctrls:
+ (sla_port, link_up) = get_aurora_info(ctrls['slave'])
+ SLA_MAC_REG_BASE = SFP0_MAC_REG_BASE if (sla_port == 0) else SFP1_MAC_REG_BASE
+ # Reset both PHYS
+ ctrls['master'].poke(MST_MAC_REG_BASE + MAC_REG_CTRL, MAC_CTRL_PHY_RESET)
+ ctrls['master'].poke(MST_MAC_REG_BASE + MAC_REG_CTRL, 0)
+ if 'slave' in ctrls:
+ ctrls['slave'].poke(SLA_MAC_REG_BASE + MAC_REG_CTRL, MAC_CTRL_PHY_RESET)
+ ctrls['slave'].poke(SLA_MAC_REG_BASE + MAC_REG_CTRL, 0)
+ time.sleep(1.5)
+
+ # Put the slave in loopback mode and the master in BIST mode
+ if 'slave' in ctrls:
+ ctrls['slave'].poke(SLA_MAC_REG_BASE + MAC_REG_CTRL, MAC_CTRL_BIST_LOOPBACK_EN)
+ if rate_sett == 0:
+ master_ctrl = MAC_CTRL_BIST_GEN_EN|MAC_CTRL_BIST_CHECKER_EN
+ else:
+ master_ctrl = ((rate_sett - 1) << MAC_CTRL_BIST_RATE_OFFSET)|MAC_CTRL_BIST_GEN_EN|MAC_CTRL_BIST_CHECKER_EN
+
+ start_time = datetime.datetime.now()
+ latencies = []
+ mst_lock_errors = 0
+ mst_hard_errors = 0
+ mst_overruns = 0
+ try:
+ for i in tqdm.tqdm(list(range(duration*10)), desc='[INFO] Progress'):
+ ctrls['master'].poke(MST_MAC_REG_BASE + MAC_REG_CTRL, master_ctrl)
+ # Wait and check if BIST locked
+ time.sleep(0.05)
+ mst_status = ctrls['master'].peek(MST_MAC_REG_BASE + MAC_REG_STATUS)
+ if (not (mst_status & MAC_STATUS_BIST_LOCKED_MSK)):
+ mst_lock_errors += 1
+ # Turn off the BIST generator
+ ctrls['master'].poke(MST_MAC_REG_BASE + MAC_REG_CTRL, MAC_CTRL_BIST_CHECKER_EN)
+ # Validate status and no overruns
+ mst_status = ctrls['master'].peek(MST_MAC_REG_BASE + MAC_REG_STATUS)
+ mst_overruns += ctrls['master'].peek(MST_MAC_REG_BASE + MAC_REG_OVERRUNS)
+ if (mst_status & MAC_STATUS_HARD_ERR_MSK):
+ mst_hard_errors += 1
+ time.sleep(0.05)
+ ctrls['master'].poke(MST_MAC_REG_BASE + MAC_REG_CTRL, 0)
+ # Compure latency
+ mst_latency_cyc = 16.0*((mst_status & MAC_STATUS_BIST_LATENCY_MSK) >> MAC_STATUS_BIST_LATENCY_OFFSET)
+ mst_latency_us = 1e6*mst_latency_cyc/AURORA_CLK_RATE
+ latencies.append(mst_latency_us)
+ except KeyboardInterrupt:
+ print('[WARNING] Operation cancelled by user.')
+ stop_time = datetime.datetime.now()
+ # Report
+ if (mst_lock_errors > 0):
+ print('[ERROR] BIST engine did not lock onto a PRBS word %d times!'%(mst_lock_errors))
+ if (mst_hard_errors > 0):
+ print('[ERROR] There were %d hard errors in master PHY'%(mst_hard_errors))
+ if (mst_overruns > 0):
+ print('[ERROR] There were %d buffer overruns in master PHY'%(mst_overruns))
+
+ print('[INFO] BIST Complete!')
+ print('- Elapsed Time = ' + str(stop_time - start_time))
+ print('- Roundtrip Latency Mean = %.2fus'%(numpy.mean(latencies)))
+ print('- Roundtrip Latency Stdev = %.2fus'%(numpy.std(latencies)))
+ # Turn off BIST loopback
+ time.sleep(0.5)
+ if 'slave' in ctrls:
+ ctrls['slave'].poke(SLA_MAC_REG_BASE + MAC_REG_CTRL, 0)
+ if 'slave' in ctrls:
+ sla_status = ctrls['slave'].peek(SLA_MAC_REG_BASE + MAC_REG_STATUS)
+ sla_overruns = ctrls['slave'].peek(SLA_MAC_REG_BASE + MAC_REG_OVERRUNS)
+ if (sla_status & MAC_STATUS_HARD_ERR_MSK):
+ print('[ERROR] Hard errors in slave PHY')
+ if (sla_overruns > 0):
+ print('[ERROR] Buffer overruns in slave PHY')
+ # Drain and Cleanup
+ print('[INFO] Cleaning up...')
+ ctrls['master'].poke(MST_MAC_REG_BASE + MAC_REG_CTRL, MAC_CTRL_BIST_CHECKER_EN)
+ if 'slave' in ctrls:
+ ctrls['slave'].poke(SLA_MAC_REG_BASE + MAC_REG_CTRL, MAC_CTRL_BIST_CHECKER_EN)
+ time.sleep(0.5)
+ ctrls['master'].poke(MST_MAC_REG_BASE + MAC_REG_CTRL, 0)
+ if 'slave' in ctrls:
+ ctrls['slave'].poke(SLA_MAC_REG_BASE + MAC_REG_CTRL, 0)
+
########################################################################
# command line options
########################################################################
@@ -172,6 +261,7 @@ def get_options():
parser = argparse.ArgumentParser(description='Controller for the USRP X3X0 Aurora BIST Engine')
parser.add_argument('--master', type=str, default=None, required=True, help='IP Address of master USRP-X3X0 device')
parser.add_argument('--slave', type=str, default=None, help='IP Address of slave USRP-X3X0 device')
+ parser.add_argument('--test', type=str, default='ber', choices=['ber', 'latency'], help='Type of test to run')
parser.add_argument('--duration', type=int, default=10, help='Duration of test in seconds')
parser.add_argument('--rate', type=int, default=1245, help='BIST throughput in MB/s')
return parser.parse_args()
@@ -210,4 +300,8 @@ if __name__=='__main__':
exit(1)
# Run BIST
- run_loopback_bist(ctrls, options.duration, get_rate_setting(options.rate))
+ if options.test == 'ber':
+ run_ber_loopback_bist(ctrls, options.duration, get_rate_setting(options.rate))
+ else:
+ run_latency_loopback_bist(ctrls, options.duration, get_rate_setting(options.rate))
+