aboutsummaryrefslogtreecommitdiffstats
path: root/firmware/usrp3/x300
diff options
context:
space:
mode:
Diffstat (limited to 'firmware/usrp3/x300')
-rwxr-xr-xfirmware/usrp3/x300/x300_aurora_bist.py307
-rwxr-xr-xfirmware/usrp3/x300/x300_debug.py130
-rw-r--r--firmware/usrp3/x300/x300_defs.h24
-rw-r--r--firmware/usrp3/x300/x300_init.c36
-rw-r--r--firmware/usrp3/x300/x300_main.c31
5 files changed, 438 insertions, 90 deletions
diff --git a/firmware/usrp3/x300/x300_aurora_bist.py b/firmware/usrp3/x300/x300_aurora_bist.py
new file mode 100755
index 000000000..f5e119b66
--- /dev/null
+++ b/firmware/usrp3/x300/x300_aurora_bist.py
@@ -0,0 +1,307 @@
+#!/usr/bin/env python
+#
+# Copyright 2016 Ettus Research LLC
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# 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
+########################################################################
+SFP0_MAC_REG_BASE = 0xC000
+SFP1_MAC_REG_BASE = 0xD000
+SFP0_TYPE_REG_OFFSET = 0xA000 + 16
+SFP1_TYPE_REG_OFFSET = 0xA000 + 20
+SFP0_STATUS_REG_OFFSET = 0xA000 + 32
+SFP1_STATUS_REG_OFFSET = 0xA000 + 36
+
+SFP_TYPE_AURORA = 2
+
+MAC_REG_CTRL = 0
+MAC_REG_STATUS = 0
+MAC_REG_OVERRUNS = 4
+MAC_REG_BIST_SAMPS = 8
+MAC_REG_BIST_ERRORS = 12
+
+MAC_STATUS_LINK_UP_MSK = 0x00000001
+MAC_STATUS_HARD_ERR_MSK = 0x00000002
+MAC_STATUS_SOFT_ERR_MSK = 0x00000004
+MAC_STATUS_BIST_LOCKED_MSK = 0x00000008
+MAC_STATUS_BIST_LATENCY_MSK = 0x000FFFF0
+MAC_STATUS_BIST_LATENCY_OFFSET = 4
+MAC_STATUS_CHECKSUM_ERRS_MSK = 0xFFF00000
+MAC_STATUS_CHECKSUM_ERRS_OFFSET = 20
+
+MAC_CTRL_BIST_CHECKER_EN = 0x00000001
+MAC_CTRL_BIST_GEN_EN = 0x00000002
+MAC_CTRL_BIST_LOOPBACK_EN = 0x00000004
+MAC_CTRL_PHY_RESET = 0x00000100
+MAC_CTRL_BIST_RATE_MSK = 0x000000F8
+MAC_CTRL_BIST_RATE_OFFSET = 3
+
+AURORA_CLK_RATE = 156.25e6
+BUS_CLK_RATE = 166.66e6
+BIST_MAX_TIME_LIMIT = math.floor(pow(2,48)/AURORA_CLK_RATE)-1
+
+########################################################################
+# utils
+########################################################################
+def get_aurora_info(ctrl):
+ if (ctrl.peek(SFP0_TYPE_REG_OFFSET) == SFP_TYPE_AURORA):
+ aur_port = 0
+ elif (ctrl.peek(SFP1_TYPE_REG_OFFSET) == SFP_TYPE_AURORA):
+ aur_port = 1
+ else:
+ aur_port = -1
+ link_up = False
+ if aur_port != -1:
+ mac_base = SFP0_MAC_REG_BASE if aur_port == 0 else SFP1_MAC_REG_BASE
+ link_up = ((ctrl.peek(mac_base + MAC_REG_STATUS) & MAC_STATUS_LINK_UP_MSK) != 0)
+ return (aur_port, link_up)
+
+def get_rate_setting(rate):
+ for div in range(2,32):
+ if (rate < 8e-6 * BUS_CLK_RATE * (1.0 - 1.0/div)):
+ return (div-1, 8e-6 * BUS_CLK_RATE * (1.0 - 1.0/(div-1)))
+ return (0, 8e-6 * BUS_CLK_RATE)
+
+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
+ 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
+ ctrls['master'].poke(MST_MAC_REG_BASE + MAC_REG_CTRL, master_ctrl)
+ start_time = datetime.datetime.now()
+ # Wait and check if BIST locked
+ time.sleep(0.5)
+ mst_status = ctrls['master'].peek(MST_MAC_REG_BASE + MAC_REG_STATUS)
+ if (not (mst_status & MAC_STATUS_BIST_LOCKED_MSK)):
+ print('[ERROR] BIST engine did not lock onto a PRBS word!')
+ # Wait for requested time
+ try:
+ for i in tqdm.tqdm(list(range(duration)), desc='[INFO] Progress'):
+ time.sleep(1.0)
+ except KeyboardInterrupt:
+ print('[WARNING] Operation cancelled by user.')
+ # Turn off the BIST generator and loopback
+ ctrls['master'].poke(MST_MAC_REG_BASE + MAC_REG_CTRL, MAC_CTRL_BIST_CHECKER_EN)
+ stop_time = datetime.datetime.now()
+ time.sleep(0.5)
+ if 'slave' in ctrls:
+ ctrls['slave'].poke(SLA_MAC_REG_BASE + MAC_REG_CTRL, 0)
+ # 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):
+ print('[ERROR] Hard errors in master PHY')
+ if (mst_overruns > 0):
+ print('[ERROR] Buffer overruns in master PHY')
+ 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')
+ # Compure latency
+ mst_samps = 65536.0*ctrls['master'].peek(MST_MAC_REG_BASE + MAC_REG_BIST_SAMPS)
+ mst_errors = 1.0*ctrls['master'].peek(MST_MAC_REG_BASE + MAC_REG_BIST_ERRORS)
+ if (mst_samps != 0):
+ mst_latency_cyc = 16.0*((mst_status & MAC_STATUS_BIST_LATENCY_MSK) >> MAC_STATUS_BIST_LATENCY_OFFSET)
+ time_diff = stop_time - start_time
+ print('[INFO] BIST Complete!')
+ print('- Elapsed Time = ' + str(time_diff))
+ print('- Max BER (Bit Error Ratio) = %.4g (%d errors out of %d)'%((mst_errors+1)/mst_samps,mst_errors,mst_samps))
+ print('- Max Roundtrip Latency = %.1fus'%(1e6*mst_latency_cyc/AURORA_CLK_RATE))
+ print('- Approx Throughput = %.0fMB/s'%((8e-6*mst_samps)/time_diff.total_seconds()))
+ else:
+ print('[ERROR] BIST Failed!')
+ # 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)
+
+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
+########################################################################
+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()
+
+########################################################################
+# main
+########################################################################
+if __name__=='__main__':
+ options = get_options()
+
+ if (options.duration < 0 or options.duration > BIST_MAX_TIME_LIMIT):
+ raise Exception('Invalid duration. Min = 0s and Max = %ds'%(BIST_MAX_TIME_LIMIT))
+
+ ctrls = dict()
+ ctrls['master'] = x300_debug.ctrl_socket(addr=options.master)
+ if options.slave:
+ ctrls['slave'] = x300_debug.ctrl_socket(addr=options.slave)
+
+ # Report device and core info
+ links_up = True
+ for node in ctrls:
+ print('[INFO] ' + node.upper() + ':')
+ ctrl = ctrls[node]
+ (aur_port, link_up) = get_aurora_info(ctrl)
+ if aur_port >= 0:
+ status_str = str(aur_port) + (' UP' if link_up else ' DOWN')
+ else:
+ status_str = 'Not Detected!'
+ print('- Mgmt IP Addr : ' + (options.master if node == 'master' else options.slave))
+ print('- Aurora Status : Port ' + status_str)
+ links_up = links_up & link_up
+
+ # Sanity check
+ if not links_up:
+ print('[ERROR] At least one of the links is down. Cannot proceed.')
+ exit(1)
+
+ # Run BIST
+ 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))
+
diff --git a/firmware/usrp3/x300/x300_debug.py b/firmware/usrp3/x300/x300_debug.py
index c9bcbb138..e134a7275 100755
--- a/firmware/usrp3/x300/x300_debug.py
+++ b/firmware/usrp3/x300/x300_debug.py
@@ -1,6 +1,6 @@
#!/usr/bin/env python
#
-# Copyright 2010-2011 Ettus Research LLC
+# Copyright 2010-2014 Ettus Research LLC
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
@@ -21,27 +21,36 @@ import math
import socket
import struct
-
########################################################################
# constants
########################################################################
-B250_FW_COMMS_UDP_PORT = 49152
+X300_FW_COMMS_UDP_PORT = 49152
+
+X300_FW_COMMS_FLAGS_ACK = 1
+X300_FW_COMMS_FLAGS_ERROR = 2
+X300_FW_COMMS_FLAGS_POKE32 = 4
+X300_FW_COMMS_FLAGS_PEEK32 = 8
+
+X300_FIXED_PORTS = 5
-B250_FW_COMMS_FLAGS_ACK = 1
-B250_FW_COMMS_FLAGS_ERROR = 2
-B250_FW_COMMS_FLAGS_POKE32 = 4
-B250_FW_COMMS_FLAGS_PEEK32 = 8
+X300_ZPU_MISC_SR_BUS_OFFSET = 0xA000
+X300_ZPU_XBAR_SR_BUS_OFFSET = 0xB000
+
+# Settings register bus addresses (hangs off ZPU wishbone bus)
+# Multiple by 4 as ZPU wishbone bus is word aligned
+X300_SR_NUM_CE = X300_ZPU_MISC_SR_BUS_OFFSET + 4*7
+X300_SR_RB_ADDR_XBAR = X300_ZPU_MISC_SR_BUS_OFFSET + 4*128
+# Readback addresses
+X300_RB_CROSSBAR = X300_ZPU_MISC_SR_BUS_OFFSET + 4*128
#UDP_CTRL_PORT = 49183
UDP_MAX_XFER_BYTES = 1024
UDP_TIMEOUT = 3
-#USRP2_FW_PROTO_VERSION = 11 #should be unused after r6
#REG_ARGS_FMT = '!LLLLLB15x'
#REG_IP_FMT = '!LLLL20x'
REG_PEEK_POKE_FMT = '!LLLL'
-
_seq = -1
def seq():
global _seq
@@ -66,7 +75,7 @@ class ctrl_socket(object):
def __init__(self, addr):
self._sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
self._sock.settimeout(UDP_TIMEOUT)
- self._sock.connect((addr, B250_FW_COMMS_UDP_PORT))
+ self._sock.connect((addr, X300_FW_COMMS_UDP_PORT))
self.set_callbacks(lambda *a: None, lambda *a: None)
#self.init_update() #check that the device is there
@@ -78,47 +87,71 @@ class ctrl_socket(object):
self._sock.send(pkt)
return self._sock.recv(UDP_MAX_XFER_BYTES)
- def read_router_stats(self):
+ def read_router_stats(self, blocks=None, ignore=None):
+ # Readback number of CEs
+ num_ports = self.peek(X300_SR_NUM_CE) + X300_FIXED_PORTS
+ ports = ['eth0', 'eth1', 'pcie', 'radio0', 'radio1'] + ["Block{num}".format(num=x) for x in range(num_ports-X300_FIXED_PORTS)]
+ if blocks is None:
+ print("\nNote: Using default CE port names (use --blocks to specify)\n")
+ else:
+ user_ports = [x.strip() for x in blocks.split(",") if len(x.strip())]
+ for idx, user_port in enumerate(user_ports):
+ ports[idx + X300_FIXED_PORTS] = user_port
+ if ignore is None:
+ ignore = []
+ else:
+ ignore = [int(x.strip()) for x in ignore.split(",") if len(x.strip())]
+ print("Egress Port "),
+ # Write out xbar ports
+ PORT_MAX_LEN = 12
+ for idx, in_prt in enumerate(ports):
+ if idx in ignore:
+ continue
+ print "{spaces}{name}".format(spaces=(" "*max(0, PORT_MAX_LEN-len(in_prt))), name=in_prt),
print
- print(" "),
- ports = [' eth0',' eth1',' radio0',' radio1',' compute0',' compute1',' compute2',' pcie']
- for in_prt in ports:
- print("%s" % in_prt),
- print(" Egress Port")
- print(" "),
- for in_prt in range (0, 8):
- print("____________"),
+ print(" "*(PORT_MAX_LEN+1)),
+ for in_prt in range(num_ports-len(ignore)):
+ print("_" * (PORT_MAX_LEN-1) + " "),
print
- for in_prt in range (0, 8):
- print("%s |" % ports[in_prt]),
- for out_prt in range (0, 8):
- out_pkt = pack_reg_peek_poke_fmt(B250_FW_COMMS_FLAGS_PEEK32|B250_FW_COMMS_FLAGS_ACK, seq(), 0xA000+256+((in_prt*8+out_prt)*4), 0)
- in_pkt = self.send_and_recv(out_pkt)
- (flags, rxseq, addr, data) = unpack_reg_peek_poke_fmt(in_pkt)
- if flags & B250_FW_COMMS_FLAGS_ERROR == B250_FW_COMMS_FLAGS_ERROR:
- raise Exception("B250 peek returns error code")
+ for in_prt, port_name in enumerate(ports):
+ if in_prt in ignore:
+ continue
+ print "{spaces}{name} |".format(spaces=(" "*max(0, PORT_MAX_LEN-len(port_name))), name=port_name),
+ for out_prt in range(num_ports):
+ if out_prt in ignore:
+ continue
+ self.poke(X300_SR_RB_ADDR_XBAR,(in_prt*num_ports+out_prt))
+ data = self.peek(X300_RB_CROSSBAR)
print("%10d " % (data)),
print
print
print("Ingress Port")
print
+ def peek_print(self,peek_addr):
+ peek_data = self.peek(peek_addr)
+ print("PEEK of address %d(0x%x) reads %d(0x%x)" % (peek_addr,peek_addr,peek_data,peek_data))
+ return peek_data
def peek(self,peek_addr):
- out_pkt = pack_reg_peek_poke_fmt(B250_FW_COMMS_FLAGS_PEEK32|B250_FW_COMMS_FLAGS_ACK, seq(), peek_addr, 0)
+ out_pkt = pack_reg_peek_poke_fmt(X300_FW_COMMS_FLAGS_PEEK32|X300_FW_COMMS_FLAGS_ACK, seq(), peek_addr, 0)
in_pkt = self.send_and_recv(out_pkt)
(flags, rxseq, addr, data) = unpack_reg_peek_poke_fmt(in_pkt)
- if flags & B250_FW_COMMS_FLAGS_ERROR == B250_FW_COMMS_FLAGS_ERROR:
- raise Exception("B250 peek of address %d returns error code" % (addr))
- print("PEEK of address %d(0x%x) reads %d(0x%x)" % (addr,addr,data,data))
+ if flags & X300_FW_COMMS_FLAGS_ERROR == X300_FW_COMMS_FLAGS_ERROR:
+ raise Exception("X300 peek of address %d returns error code" % (addr))
+ return data
+
+ def poke_print(self,poke_addr,poke_data):
+ print("POKE of address %d(0x%x) with %d(0x%x)" % (poke_addr,poke_addr,poke_data,poke_data))
+ return(self.poke(poke_addr,poke_data))
def poke(self,poke_addr,poke_data):
- out_pkt = pack_reg_peek_poke_fmt(B250_FW_COMMS_FLAGS_POKE32|B250_FW_COMMS_FLAGS_ACK, seq(), poke_addr, poke_data)
+ out_pkt = pack_reg_peek_poke_fmt(X300_FW_COMMS_FLAGS_POKE32|X300_FW_COMMS_FLAGS_ACK, seq(), poke_addr, poke_data)
in_pkt = self.send_and_recv(out_pkt)
(flags, rxseq, addr, data) = unpack_reg_peek_poke_fmt(in_pkt)
- if flags & B250_FW_COMMS_FLAGS_ERROR == B250_FW_COMMS_FLAGS_ERROR:
- raise Exception("B250 peek of address %d returns error code" % (addr))
- print("POKE of address %d(0x%x) with %d(0x%x)" % (poke_addr,poke_addr,poke_data,poke_data) )
+ if flags & X300_FW_COMMS_FLAGS_ERROR == X300_FW_COMMS_FLAGS_ERROR:
+ raise Exception("X300 peek of address %d returns error code" % (addr))
+ return data
########################################################################
@@ -126,14 +159,14 @@ class ctrl_socket(object):
########################################################################
def get_options():
parser = optparse.OptionParser()
- parser.add_option("--addr", type="string", help="USRP-N2XX device address", default='')
- parser.add_option("--list", action="store_true", help="list possible network devices", default=False)
- parser.add_option("--peek", type="int", help="Read from memory map", default=None)
- parser.add_option("--poke", type="int", help="Write to memory map", default=None)
- parser.add_option("--data", type="int", help="Data for poke", default=None)
- parser.add_option("--stats", action="store_true", help="Display SuperMIMO Network Stats", default=False)
+ parser.add_option("--addr", type="string", help="USRP-X300 device address", default='')
+ parser.add_option("--stats", action="store_true", help="Display RFNoC Crossbar Stats", default=False)
+ parser.add_option("--peek", type="int", help="Read from memory map", default=None)
+ parser.add_option("--poke", type="int", help="Write to memory map", default=None)
+ parser.add_option("--data", type="int", help="Data for poke", default=None)
+ parser.add_option("--blocks", help="List names of blocks (post-radio)", default=None)
+ parser.add_option("--ignore", help="List of ports to ignore", default=None)
(options, args) = parser.parse_args()
-
return options
@@ -143,25 +176,18 @@ def get_options():
if __name__=='__main__':
options = get_options()
-
- if options.list:
- print('Possible network devices:')
- print(' ' + '\n '.join(enumerate_devices()))
- exit()
-
if not options.addr: raise Exception('no address specified')
status = ctrl_socket(addr=options.addr)
if options.stats:
- status.read_router_stats()
-
+ status.read_router_stats(options.blocks, options.ignore)
if options.peek is not None:
addr = options.peek
- status.peek(addr)
+ status.peek_print(addr)
if options.poke is not None and options.data is not None:
addr = options.poke
data = options.data
- status.poke(addr,data)
+ status.poke_print(addr,data)
diff --git a/firmware/usrp3/x300/x300_defs.h b/firmware/usrp3/x300/x300_defs.h
index c4011bd12..e9e9f34fa 100644
--- a/firmware/usrp3/x300/x300_defs.h
+++ b/firmware/usrp3/x300/x300_defs.h
@@ -4,11 +4,11 @@
#ifndef INCLUDED_X300_DEFS_H
#define INCLUDED_X300_DEFS_H
-#define CPU_CLOCK 166666667
+#define CPU_CLOCK 83333333
#define MAIN_RAM_BASE 0x0000
#define PKT_RAM0_BASE 0x8000
-#define XGE0_BASE 0xC000
-#define XGE1_BASE 0xD000
+#define SFP0_MAC_BASE 0xC000
+#define SFP1_MAC_BASE 0xD000
#define BOOT_LDR_BASE 0xFC00
#define UART0_BASE 0xfd00
#define UART0_BAUD 115200
@@ -21,9 +21,6 @@
#define RB0_BASE 0xa000 //same as set
#define SETXB_BASE 0xb000
-#define ETH1G
-//#define ETH10G
-
//eeprom map for mboard addrs
#define MBOARD_EEPROM_ADDR 0x50
@@ -36,6 +33,7 @@ static const int SR_SFPP_CTRL = 4;
static const int SR_SPI = 32;
static const int SR_ETHINT0 = 40;
static const int SR_ETHINT1 = 56;
+static const int SR_RB_ADDR = 128;
//led shifts for SR_LEDS
static const int LED_ACT1 = (1 << 5);
@@ -49,11 +47,12 @@ static const int LED_LINKACT = (1 << 0);
static const int RB_COUNTER = 0;
static const int RB_SPI_RDY = 1;
static const int RB_SPI_DATA = 2;
-static const int RB_ETH_TYPE0 = 4;
-static const int RB_ETH_TYPE1 = 5;
+static const int RB_SFP0_TYPE = 4;
+static const int RB_SFP1_TYPE = 5;
static const int RB_FPGA_COMPAT = 6;
-static const int RB_SFPP_STATUS0 = 8;
-static const int RB_SFPP_STATUS1 = 9;
+static const int RB_SFP0_STATUS = 8;
+static const int RB_SFP1_STATUS = 9;
+static const int RB_XBAR = 128;
// Bootloader Memory Map
static const int BL_ADDRESS = 0;
@@ -73,4 +72,9 @@ static const int BL_DATA = 1;
#define ETH_FRAMER_DST_UDP_MAC 6
#define ETH_FRAMER_DST_MAC_LO 7
+// SFP type constants
+#define RB_SFP_1G_ETH 0
+#define RB_SFP_10G_ETH 1
+#define RB_SFP_AURORA 2
+
#endif /* INCLUDED_X300_DEFS_H */
diff --git a/firmware/usrp3/x300/x300_init.c b/firmware/usrp3/x300/x300_init.c
index ef97412a2..57c1faa2c 100644
--- a/firmware/usrp3/x300/x300_init.c
+++ b/firmware/usrp3/x300/x300_init.c
@@ -1,7 +1,7 @@
#include "x300_init.h"
#include "x300_defs.h"
#include "ethernet.h"
-#include "mdelay.h"
+#include "cron.h"
#include <wb_utils.h>
#include <wb_uart.h>
#include <wb_i2c.h>
@@ -84,8 +84,8 @@ static void init_network(void)
wb_i2c_read(I2C1_BASE, MBOARD_EEPROM_ADDR, (uint8_t *)(&eeprom_map), sizeof(eeprom_map));
//determine interface number
- const size_t eth0no = wb_peek32(SR_ADDR(RB0_BASE, RB_ETH_TYPE0))? 2 : 0;
- const size_t eth1no = wb_peek32(SR_ADDR(RB0_BASE, RB_ETH_TYPE1))? 3 : 1;
+ const size_t eth0no = wb_peek32(SR_ADDR(RB0_BASE, RB_SFP0_TYPE))? 2 : 0;
+ const size_t eth1no = wb_peek32(SR_ADDR(RB0_BASE, RB_SFP1_TYPE))? 3 : 1;
//pick the address from eeprom or default
const eth_mac_addr_t *my_mac0 = (const eth_mac_addr_t *)pick_inited_field(&eeprom_map.mac_addr0, &default_map.mac_addr0, 6);
@@ -121,6 +121,11 @@ static void putc(void *p, char c)
#endif
}
+static uint32_t get_counter_val()
+{
+ return wb_peek32(SR_ADDR(RB0_BASE, RB_COUNTER));
+}
+
void x300_init(void)
{
//first - uart
@@ -136,6 +141,9 @@ void x300_init(void)
UHD_FW_TRACE_FSTR(INFO, "-- FPGA Compat Number: %u.%u", (fpga_compat>>16), (fpga_compat&0xFFFF));
UHD_FW_TRACE_FSTR(INFO, "-- Clock Frequency: %u MHz", (CPU_CLOCK/1000000));
+ //Initialize cron
+ cron_init(get_counter_val, CPU_CLOCK);
+
//i2c rate init
wb_i2c_init(I2C0_BASE, CPU_CLOCK);
wb_i2c_init(I2C1_BASE, CPU_CLOCK);
@@ -151,19 +159,23 @@ void x300_init(void)
wb_poke32(SR_ADDR(SET0_BASE, SR_SW_RST), 0);
//print network summary
- for (uint8_t e = 0; e < ethernet_ninterfaces(); e++)
+ for (uint8_t sfp = 0; sfp < ethernet_ninterfaces(); sfp++)
{
- uint32_t offset = SR_ADDR(RB0_BASE, ((e==1)?RB_ETH_TYPE1:RB_ETH_TYPE0));
- UHD_FW_TRACE_FSTR(INFO, "Ethernet Port %u:", (int)e);
- UHD_FW_TRACE_FSTR(INFO, "-- PHY: %s", ((wb_peek32(offset)==1) ? "10Gbps" : "1Gbps"));
- UHD_FW_TRACE_FSTR(INFO, "-- MAC: %s", mac_addr_to_str(u3_net_stack_get_mac_addr(e)));
- UHD_FW_TRACE_FSTR(INFO, "-- IP: %s", ip_addr_to_str(u3_net_stack_get_ip_addr(e)));
- UHD_FW_TRACE_FSTR(INFO, "-- SUBNET: %s", ip_addr_to_str(u3_net_stack_get_subnet(e)));
- UHD_FW_TRACE_FSTR(INFO, "-- BCAST: %s", ip_addr_to_str(u3_net_stack_get_bcast(e)));
+ uint32_t sfp_type = wb_peek32(SR_ADDR(RB0_BASE, ((sfp==1) ? RB_SFP1_TYPE : RB_SFP0_TYPE)));
+ UHD_FW_TRACE_FSTR(INFO, "SFP+ Port %u:", (int)sfp);
+ if (sfp_type == RB_SFP_AURORA) {
+ UHD_FW_TRACE (INFO, "-- PHY: 10Gbps Aurora");
+ } else {
+ UHD_FW_TRACE_FSTR(INFO, "-- PHY: %s", (sfp_type == RB_SFP_10G_ETH) ? "10Gbps Ethernet" : "1Gbps Ethernet");
+ UHD_FW_TRACE_FSTR(INFO, "-- MAC: %s", mac_addr_to_str(u3_net_stack_get_mac_addr(sfp)));
+ UHD_FW_TRACE_FSTR(INFO, "-- IP: %s", ip_addr_to_str(u3_net_stack_get_ip_addr(sfp)));
+ UHD_FW_TRACE_FSTR(INFO, "-- SUBNET: %s", ip_addr_to_str(u3_net_stack_get_subnet(sfp)));
+ UHD_FW_TRACE_FSTR(INFO, "-- BCAST: %s", ip_addr_to_str(u3_net_stack_get_bcast(sfp)));
+ }
}
// For eth interfaces, initialize the PHY's
- mdelay(100);
+ sleep_ms(100);
ethernet_init(0);
ethernet_init(1);
}
diff --git a/firmware/usrp3/x300/x300_main.c b/firmware/usrp3/x300/x300_main.c
index 3b812a2c4..42ee3248b 100644
--- a/firmware/usrp3/x300/x300_main.c
+++ b/firmware/usrp3/x300/x300_main.c
@@ -6,7 +6,6 @@
#include "xge_phy.h"
#include "ethernet.h"
#include "chinch.h"
-#include "mdelay.h"
#include <wb_utils.h>
#include <wb_uart.h>
@@ -247,18 +246,16 @@ static void handle_claim(void)
/***********************************************************************
* LED blinky logic and support utilities
**********************************************************************/
-static uint32_t get_xbar_total(const uint8_t port)
+static uint32_t get_xbar_total(const uint32_t port)
{
- #define get_xbar_stat(in_prt, out_prt) \
- wb_peek32(RB0_BASE+256+(((in_prt)*8+(out_prt))*4))
+ static const uint32_t NUM_PORTS = 16;
uint32_t total = 0;
- for (size_t i = 0; i < 8; i++)
+ for (uint32_t i = 0; i < NUM_PORTS; i++)
{
- total += get_xbar_stat(port, i);
- }
- for (size_t i = 0; i < 8; i++)
- {
- total += get_xbar_stat(i, port);
+ wb_poke32(SET0_BASE + SR_RB_ADDR*4, (NUM_PORTS*port + i));
+ total += wb_peek32(RB0_BASE + RB_XBAR*4);
+ wb_poke32(SET0_BASE + SR_RB_ADDR*4, (NUM_PORTS*i + port));
+ total += wb_peek32(RB0_BASE + RB_XBAR*4);
}
if (port < 2) //also netstack if applicable
{
@@ -280,10 +277,10 @@ static size_t popcntll(uint64_t num)
static void update_leds(void)
{
//update activity status for all ports
- uint64_t activity_shreg[8];
- for (size_t i = 0; i < 8; i++)
+ uint64_t activity_shreg[16];
+ for (uint32_t i = 0; i < 16; i++)
{
- static uint32_t last_total[8];
+ static uint32_t last_total[16];
const uint32_t total = get_xbar_total(i);
activity_shreg[i] <<= 1;
activity_shreg[i] |= (total == last_total[i])? 0 : 1;
@@ -321,8 +318,10 @@ static void garp(void)
count = 0;
for (size_t e = 0; e < ethernet_ninterfaces(); e++)
{
- if (!ethernet_get_link_up(e)) continue;
- u3_net_stack_send_arp_request(e, u3_net_stack_get_ip_addr(e));
+ if (wb_peek32(SR_ADDR(RB0_BASE, e == 0 ? RB_SFP0_TYPE : RB_SFP1_TYPE)) != RB_SFP_AURORA) {
+ if (!ethernet_get_link_up(e)) continue;
+ u3_net_stack_send_arp_request(e, u3_net_stack_get_ip_addr(e));
+ }
}
}
@@ -447,7 +446,7 @@ int main(void)
{
poll_sfpp_status(0); // Every so often poll XGE Phy to look for SFP+ hotplug events.
poll_sfpp_status(1); // Every so often poll XGE Phy to look for SFP+ hotplug events.
- handle_link_state(); //deal with router table update
+ //handle_link_state(); //deal with router table update
handle_claim(); //deal with the host claim register
update_leds(); //run the link and activity leds
garp(); //send periodic garps