diff options
Diffstat (limited to 'firmware/usrp3/x300')
-rwxr-xr-x | firmware/usrp3/x300/x300_aurora_bist.py | 307 | ||||
-rwxr-xr-x | firmware/usrp3/x300/x300_debug.py | 130 | ||||
-rw-r--r-- | firmware/usrp3/x300/x300_defs.h | 24 | ||||
-rw-r--r-- | firmware/usrp3/x300/x300_init.c | 36 | ||||
-rw-r--r-- | firmware/usrp3/x300/x300_main.c | 31 |
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 |