/***************************************************************************** * * Copyright 2018 Green Hills Software, Inc. * All Rights Reserved * * This program is the property of Green Hills Software, Inc, * its contents are proprietary information and no part of it * is to be disclosed to anyone except employees of Green Hills * Software, Inc., or as agreed in writing signed by the President * of Green Hills Software, Inc. * * * hsst_debug.rc revision 6, 2020-03-23 * * This file documents some of the features of the Green Hills high-speed * serial SuperTrace probe pertaining to bringing up an Aurora link. * * Contents: * 1. Example generic mbs script for Aurora trace * 2. Basic 'tracereg' reference * 3. Advanced 'tracereg' reference * 4. Utility functions for mbs/rc scripts * ***************************************************************************** =========================================================================== 1. Example script for Aurora link bringup =========================================================================== The following is an example script that outlines the basics of Aurora link bringup. This defines a setup_trace() function that can be called elsewhere to initialize the Aurora link between the target and the probe. For this example we'll assume the following target configuration. You will need to modify the configuration and register access to match your target. * 2 lanes * 6.0 Gbps per lane * ARM HSSTP IP accessible in the core's APB space at +0x80008000, with register map: * +0x0 -- STPSR; STP status register * +0x4 -- STPCR; STP control register * +0x8 -- LLIR; Link initialization register Note that for PowerPC targets with Nexus Aurora interfaces, the retry loop portion of the script is not needed because mpserv natively handles link bringup as part of "trace on". ----------- // Include utility functions from this file (hsst_debug.rc). // Alternatively, copy needed functions here. < C:\full\path\to\hsst_debug.rc define setup_trace() { // Optionally return if the link is already up // if (get_probe_rx_up()) { // return // } // Disable TimeMachine trace, since we'll be resetting the underlying // physical capture layers. trace off -no_retrieve // Define some register addresses eval $STPSR_APB_ADDR = 0x80008000 eval $STPCR_APB_ADDR = 0x80008004 eval $LLIR_APB_ADDR = 0x80008008 // Configure the probe's Aurora line rate and number of lanes. target set hsst_rx_lanes 2 // this is a non-volatile option target tracereg aurora_linerate=6000 // this is volatile // Configure the target's trace-related clocks, serial trace PHY, and // other target-specific features. This often includes a series of // register writes dictated by the SOC design. For ARM HSSTP, this will // include writing LLIR -- which we will populate with a maximum // ALIGN_LEN field value. ... ... ... G_write_apb($LLIR_APB_ADDR, 0x3fdfffff) // Retry loop wrapper for Aurora channel initialization. // // Aurora trace runs over a simplex link that relies on timers on the // probe side to step through the initialzation process. Because // resetting the target side of the link is asynchronous to the probe, // initialization may occasionally fail. We use a retry loop to ensure // we end up with a good link. eval $retries = 10 for (eval $attempt=0; $attempt<$retries; eval $attempt++) { // Reset the probe's side of the link target tracereg aurora_rx_reset=1 // Hold the HSSTP block in reset G_set_apb_bits($STPCR_APB_ADDR, 3, 0, 0x0) // Optional: short delay (in milliseconds) wait -time 10 // Release the HSSTP block to begin Aurora training G_set_apb_bits($STPCR_APB_ADDR, 3, 0, 0xd) // Optional: short delay (in milliseconds) wait -time 10 // Optional: ensure STPSR reports channel up if (G_read_apb($STPSR_APB_ADDR) & (1<<6) == 0) { mprintf("STPSR[CHANNEL_UP] is not high. Aborting.\n"); break -fail } // Check for channel up on the probe side if (get_probe_rx_up() == 0) { // see definition in hsst_debug.rc mprintf("Aurora init failed, iteration %d. Retrying...\n", \ $attempt) print_hsst_debug() continue } // Enable data transmission from the HSSTP block G_set_apb_bits($STPCR_APB_ADDR, 3, 0, 0xf) // Done break } if ($attempt >= $retries) { mprintf("Exceeded max retries. Aborting. \n") break -fail } // Enable TimeMachine trace. Some architectures (Nexus) will report an // error here if the Aurora link bringup was unsuccessful. trace on } =========================================================================== 2. Basic 'tracereg' reference =========================================================================== The 'target tracereg' command allows access to named registers that control or provide status of various aspects of the SuperTrace Probe's trace subsystem. Use the following syntax to access trace registers from the MULTI cmd pane: target tracereg (register)[=(value)] For example: target tracereg aurora_linerate=6000 Some registers related to Aurora serial trace are listed below. Values written to these registers are *not stored in the SuperTrace probe's non-volatile memory, and therefore should be set each time the trace link is brought up (e.g., as part of the .mbs setup script). == aurora_rx_up == A bit indicating that all lanes in the Aurora channel are up, and the link is aligned, bonded, and verified. == aurora_rx_reset == A write-only register that resets the RX interface in the SuperTrace probe, preparing it to receive training sequences from the target. The only valid write value is 1. == aurora_linerate == Sets the line rate for the Aurora link. Specified in Mbps. Supported values include (but are not necessarily limited to) 2500, 3000, 3125, 5000, 6000, and 6250. == aurora_rxpackets == A 16-bit count of the raw packets received by the probe over the Aurora link. == aurora_lanes_up == A bitfield with a bit for each Aurora lane. The least-significant bit corresponds to lane 0 being up, and so on. == aurora_(soft|hard|frame)_error_count == A 8-bit count of the number of errors that have been detected since the link was last reset (via aurora_rx_reset). If more than 255 errors occur, this register reads as 255. UG198 p64. The types of errors are as follows: soft - invalid code, or disparity error. hard - rx overflow/underflow, bad control character, or soft error limit. frame - truncated frame, invalid control character, or no data in frame. == aurora_hard_error == Single bit that indicates an active hard error condition in the Aurora block. Automatically cleared when the error is resolved, or with aurora_rx_reset. =========================================================================== 3. Advanced 'tracereg' reference =========================================================================== The following registers provide adjustment of low-level receive termination and transmit drive characteristics of the Aurora serial interface. Further technical detail is available in the following Xilinx documentation: STPv3: UG198 - Virtex-5 FPGA RocketIO GTX Transceiver User Guide GHPv4: UG476 - 7 Series FPGAs GTX/GTX Transceviers RX termination adjustment ------------------------- == aurora_rxeqmix (STPv3 Only) == This parameter controls the mode of the rx linear equalization circuit. High frequency gain may need to be increased when using high bitrates (5+Gbps) and/or when running over traces with significant high-frequency loss. UG198 p166. The values for this 2-bit register are as follows: 0 - Large high-frequency boost 1 - Small high-frequency boost 2 - Moderate high-frequency boost 3 - Bypass with gain == aurora_dfe == On STPv3, this parameter controls TAP1 weight value for the Decision Feedback Equalizer in the Virtex5 FPGA. This is a 5-bit field. The default value of 0 is appropriate for most circumstances, but may need to be increased for long traces. See UG198 p171. On GHPv4, this parameter takes a binary value of 0 or 1, and controls whether LPM or DFE mode is used for rx equalization. LPM uses less power, but DFE is more effective at higher line rates. For further detail, see "RX Equalizer (DFE and LPM)" in Xilinx UG476. TX drive adjustment ------------------- For serial trace interfaces that require the probe to provide a reference clock (such as Freescale MPC57xx), the following registers are available to control the drive characteristics of the reference clock. In most cases these should be left at their default values. == aurora_drive (STPv3 Only) == This controls the amplitude of the driver's differential swing. Values for this three-bit register are as follows: 0 - 500mV (default) 1 - 700mV 2 - 800mV 3 - 900mV 4 - 1000mV 5 - 1100mV 6 - 1200mV 7 - 1300mV == aurora_preemphasis (STPv3 Only) == This controls the relative amount of pre-emphasis of the driver. See UG198 p152 for more details. Values for this three-bit register are as follows: 0 - 0% (default) 1 - 8% 2 - 17% 3 - 25% 4 - 33% 5 - 42% 6 - 50% 7 - 58% =========================================================================== 4. Utility functions for mbs/rc scripts =========================================================================== The following are utility functions for use in MBS or RC scripts: */ /* Read from an apb address */ define G_read_apb(addr) { substitute target a=rr apb[%EVAL{p/x addr}] substitute eval $a = %EVAL{target print 0x$$a} target undef a return $a } /* Write to an apb address */ define G_write_apb(addr, val) { substitute target rw apb[%EVAL{p/x addr}] %EVAL{p/x val} } /* Read, modify, write to apb address, ORing the value */ define G_ori_apb(addr, val) { G_write_apb(addr, G_read_apb(addr) | val) } /* Read, modify, write to apb address, ANDing the value */ define G_andi_apb(addr, val) { G_write_apb(addr, G_read_apb(addr) & val) } /* Read, modify, write to apb address, setting the bits specified in val between the upper limit of hi and the lower limit of lo */ define G_set_apb_bits(addr, hi, lo, val) { eval $pr_tmp = G_read_apb(addr) eval $pr_width = (hi - lo) + 1 eval $pr_mask = (((1 << $pr_width)-1) << lo) eval $pr_tmp &= ~($pr_mask) eval $pr_tmp |= ((val << lo) & $pr_mask) G_write_apb(addr, $pr_tmp) eval G_read_apb(addr) } /* Read from an ahb address */ define G_read_ahb(addr) { substitute target a=rr ahb[%EVAL{p/x addr}] substitute eval $a = %EVAL{target print 0x$$a} target undef a return $a } /* Writes to an ahb address */ define G_write_ahb(addr, val) { substitute target rw ahb[%EVAL{p/x addr}] %EVAL{p/x val} } /* Read, modify, write to ahb address, ORing the value */ define G_ori_ahb(addr, val) { G_write_ahb(addr, G_read_ahb(addr) | val) } /* Read, modify, write to ahb address, ANDing the value */ define G_andi_ahb(addr, val) { G_write_ahb(addr, G_read_ahb(addr) & val) } /* Read, modify, write to ahb address, setting the bits specified in val between the upper limit of hi and the lower limit of lo */ define G_set_ahb_bits(addr, hi, lo, val) { eval $pr_tmp = G_read_ahb(addr) eval $pr_width = (hi - lo) + 1 eval $pr_mask = (((1 << $pr_width)-1) << lo) eval $pr_tmp &= ~($pr_mask) eval $pr_tmp |= ((val << lo) & $pr_mask) G_write_ahb(addr, $pr_tmp) eval G_read_ahb(addr) } /* Determine whether 12G is supported on this probe. */ define get_probe_12G_support() { py -b -s "d=debugger\nif not (d and d.IsAlive()):d=GHS_Debugger()" py -b -s "def m(cmd):\n _=d.RunCmd(cmd,block=True,printOutput=False)\n return d.cmdExecOutput" py -b -s "_=m('$G_result=%d'%('SPOD' in m('target infoqry adapter.class')))" return $G_result } define G_get_probe_12G_support() { return get_probe_12G_support() } /* Returns the configured linerate in Gbps. */ define get_probe_linerate_gbps() { substitute eval $p_%EVAL{target tracereg aurora_linerate} return $p_aurora_linerate/1000.0 } /* Tests for channel up. Returns 0 or 1. */ define get_probe_rx_up() { substitute eval $probe_%EVAL{target tracereg aurora_rx_up} return $probe_aurora_rx_up } define G_get_probe_rx_up() { return get_probe_rx_up() } /* Ensures the channel is up. If the channel is up, print a message and return. If the channel is not up, print some debugging information and break out of script execution. */ define ensure_channel_up() { if (get_probe_rx_up()) { mprintf("---\n") mprintf("Aurora channel is up at %0.3f Gbps.\n", get_probe_linerate_gbps()) mprintf("---\n") } else { mprintf("---\n") mprintf("ERROR: Aurora channel is NOT up. Debug info:\n") mprintf("---\n") print_hsst_debug(); break -fail; } } /* Prints debugging information about the HSST link. */ define print_hsst_debug() { mprintf("--- Aurora debug ---\n") mprintf("[Config]\n") substitute eval $p_%EVAL{target set hsst_rx_lanes} mprintf(" Lanes: %d\n", $p_hsst_rx_lanes); eval $p_linerate_gbps = get_probe_linerate_gbps() mprintf(" Line rate: %0.3f Gbps\n", $p_linerate_gbps); substitute eval $p_%EVAL{target tracereg aurora_rxeqmix} substitute eval $p_%EVAL{target tracereg aurora_dfe} mprintf(" rxeqmix/dfe: 0x%x/0x%x\n", $p_aurora_rxeqmix, $p_aurora_dfe); substitute eval $p_%EVAL{target tracereg aurora_align_count} substitute eval $p_%EVAL{target tracereg aurora_bond_count} substitute eval $p_%EVAL{target tracereg aurora_verify_count} mprintf("[Link init/status]\n") if ($p_aurora_align_count != 0xcc10 && $p_aurora_bond_count != 0xc1a && $p_aurora_verify_count != 0xcc10) { mprintf(" align/bond/verify counts: 0x%x/0x%x/0x%x\n", $p_aurora_align_count, $p_aurora_bond_count, $p_aurora_verify_count) } substitute eval $p_%EVAL{target tracereg aurora_lanes_up} mprintf(" lanes up (bitfield): 0x%x\n", $p_aurora_lanes_up) substitute eval $p_%EVAL{target tracereg aurora_rx_up} mprintf(" channel status: ") if ($p_aurora_rx_up) { mprintf("UP\n") } else { mprintf("DOWN\n") } substitute eval $p_%EVAL{target tracereg aurora_linkup_count} substitute eval $p_%EVAL{target tracereg aurora_linkdown_count} if ($p_aurora_linkup_count != 0xc1a && $p_aurora_linkdown_count != 0xcc10) { mprintf(" channel up/down counts: 0x%x/0x%x\n", $p_aurora_linkup_count, $p_aurora_linkdown_count) } substitute eval $p_%EVAL{target tracereg aurora_soft_error_count} substitute eval $p_%EVAL{target tracereg aurora_hard_error_count} substitute eval $p_%EVAL{target tracereg aurora_frame_error_count} mprintf(" soft/hard/frame errors: 0x%x/0x%x/0x%x\n", $p_aurora_soft_error_count, $p_aurora_hard_error_count, $p_aurora_frame_error_count) target quiet on target a=tracereg aurora_crc_error_count target quiet off substitute eval $p_aurora_crc_error_count = %EVAL{target print 0x$$a} mprintf(" crc errors: ") if ($p_aurora_crc == 0) { mprintf("(none)\n") } else { mprintf("0x%x\n", $p_aurora_crc_error_count) } if ($p_aurora_rx_up) { mprintf("[Datapath]\n") eval $p_delay = 100 substitute eval $p_%EVAL{target tracereg aurora_rxpackets } eval $p_tmp = $p_aurora_rxpackets substitute wait -time %EVAL{p/d $p_delay} substitute eval $p_%EVAL{target tracereg aurora_rxpackets } eval $p_receiving_data=0; if ($p_tmp == $p_aurora_rxpackets) { eval $p_tmp = $p_aurora_rxpackets substitute wait -time %EVAL{p/d $p_delay} if ($p_tmp == $p_aurora_rxpackets) { mprintf(" receiving data: NO\n") } else { mprintf(" receiving data: YES\n") eval $p_receiving_data=1; } } else { mprintf(" receiving data: YES\n") eval $p_receiving_data=1; if (($p_tmp & 0xffff0000) == 0 && ($p_aurora_rxpackets & 0xffff0000) == 0) { // null } else { eval $p_data_rate = ((float)($p_aurora_rxpackets - $p_tmp))*((1000./$p_delay)*32*$p_hsst_rx_lanes)/1E9 mprintf(" approx data rate: %0.3f Gbps\n", $p_data_rate) } } if ($p_receiving_data) { target quiet on target tracereg aurora_pb_ctrl=0x0000fff0 target a=0 target a=tracereg aurora_pb_ctrl substitute eval $pb_supported = %EVAL{target print 0x$$a} target undef a target quiet off if ($pb_supported) { target tracereg aurora_pb_ctrl=1 wait -time 10 substitute eval $p_%EVAL{target tracereg aurora_pb_ctrl} if ($p_aurora_pb_ctrl & 1) { mprintf("pb: timed out waiting for data. Aborting.\n") return } mprintf(" Data sample:\n") eval $p_sample_lines = 4; for (eval $p_i=1; $p_i<=$p_sample_lines; eval $p_i++) { substitute target tracereg aurora_pb_ctrl=%EVAL{p/x $p_i << 4} substitute eval $p_%EVAL{target tracereg aurora_pb_data0} mprintf(" 0x%08x", $p_aurora_pb_data0) if ($p_hsst_rx_lanes>1) { substitute eval $p_%EVAL{target tracereg aurora_pb_data1} mprintf(" 0x%08x", $p_aurora_pb_data1) } if ($p_hsst_rx_lanes>2) { substitute eval $p_%EVAL{target tracereg aurora_pb_data2} mprintf(" 0x%08x", $p_aurora_pb_data2) } if ($p_hsst_rx_lanes>3) { substitute eval $p_%EVAL{target tracereg aurora_pb_data3} mprintf(" 0x%08x", $p_aurora_pb_data3) } mprintf("\n") } } } mprintf("[CoreSight]\n") // mprintf(" (only applicable after TPIU setup via \"trace off; trace on\")\n") mprintf(" trace enabled in MULTI: ") substitute eval $p_trace_state = %EVAL{target trace_state} if ($p_trace_state & 1) { mprintf("YES\n") } else { mprintf("NO\n") } substitute eval $p_%EVAL{target tracereg aurora_targetreg } mprintf(" frame sync: ") if ($p_aurora_targetreg & 1) { mprintf("YES\n") } else { mprintf("NO\n") } target quiet on target a=0 target a=tracereg link_util_ctrl substitute eval $lut_supported = %EVAL{target print 0x$$a} target undef a target quiet off if ($lut_supported) { substitute eval $p_%EVAL{target tracereg link_util_ctrl} eval $lut_scale = (($p_link_util_ctrl & 0x3ff) + 1) * 256 substitute eval $p_%EVAL{target tracereg link_util_cur} eval $lut_cur_gbps = ($p_link_util_cur*0.8*$p_linerate_gbps/(lut_scale)) mprintf(" frame throughput: %0.3f Gbps\n", $lut_cur_gbps) } // TODO: add TPIU diagnostics } } /* TPIU test pattern verification for GHPv4. Arguments: core_num -- TPIU probe core number. See "target tl" for a core listing. This function will enable the walking-ones test pattern in the TPIU and verify the data as received over the Aurora interface. The Aurora link is expected to already be properly trained. Status and error counts are printed to the MULTI command pane every second. Press ESC to abort the script. When aborted, the TPIU will still be sending the test pattern -- issuing a "trace clear" will clean this up. */ define v4_tpiu_test_pattern(core_num) { if (!get_probe_rx_up()) { print "ERROR: Aurora link is not up." break -fail } trace on trace clear target quiet on target tracereg tpiu_test_csr=2 target a=0 target a=tracereg tpiu_test_csr substitute eval $tpiu_test_supported = %EVAL{target print 0x$$a} target quiet off if (!$tpiu_test_supported) { print "ERROR: v4 tpiu test not supported by this firmware/target configuration." break -fail } target quiet on substitute target a=t %EVAL{p/d core_num} rr tpiu_supp_test_pat substitute eval $supp = %EVAL{target print 0x$$a} target quiet off if (!($supp & 1)) { mprintf("ERROR: Core %d is not a TPIU, or does not support test patterns.\n", core_num) print "'target tl' output listed below:" target tl break -fail } print "Enabling walking-ones test pattern..." print "Note: 'trace clear' suggested after aborting this script" substitute target t %EVAL{p/d core_num} rw tpiu_curr_test_pat 0x00010001 target tracereg tpiu_test_csr=1 target tracereg tpiu_test_csr=2 eval $cumulative = 0ULL eval $last = 0 while (1) { substitute eval $probe_%EVAL{target tracereg tpiu_test_csr} substitute eval $probe_%EVAL{target tracereg tpiu_test_vc} eval $errors = ($probe_tpiu_test_csr >> 4) & 0xff eval $cumulative += ($probe_tpiu_test_vc - $last) eval $last = $probe_tpiu_test_vc substitute eval $p_%EVAL{target tracereg aurora_soft_error_count} substitute eval $p_%EVAL{target tracereg aurora_hard_error_count} substitute eval $p_%EVAL{target tracereg aurora_frame_error_count} mprintf("TPIU (walking ones). Valid words: 0x%llx. ", $cumulative) if ($errors == 255) { mprintf("error counter wrapped. FAIL.\n") break -fail } else { mprintf("Errors: %d.", $errors) } mprintf(" Aurora soft/hard/frame errors: 0x%x/0x%x/0x%x", $p_aurora_soft_error_count, $p_aurora_hard_error_count, $p_aurora_frame_error_count) mprintf(" (ESC to cancel)\n") wait -time 100 } } /* v3_tpiu_test_pattern() CoreSight-only TPIU test pattern verification for STPv3. Set up your target and bring up the trace link before running this test. It will enable a certain type of TPIU pattern generation and verify the values real-time on the SuperTrace probe. Results including the number of errors will be printed at the end of the test. Note that a full TPIU is required for this test to function. == pattern == This specifies the type of test pattern to run. There are currently two supported values: 4 - Enables the 55555555/aaaaaaaa pattern 8 - Enables the 00000000/ffffffff pattern == num_seconds == This specifies how long to run. */ define v3_tpiu_test_pattern(pattern, num_seconds) { trace on trace clear eval $sanity_check = 1; if ($sanity_check) { target tracereg aurora_tp_enable=0 target tracereg aurora_tp_reset=1 substitute target tracereg aurora_tp_pattern=2 substitute target rw tpiu_curr_test_pat 8 target tracereg aurora_tp_enable=1 substitute eval $probe_%EVAL{target tracereg aurora_tp_enable} if ($probe_aurora_tp_enable == 0) { print "Test patterns not supported with this target/firmware." break -fail } substitute eval $probe_%EVAL{target tracereg aurora_tp_errors} if ($probe_aurora_tp_errors != 255) { mprintf("ERROR: Not catching tpiu errors (%d). Is the target set up?\n", $probe_aurora_tp_errors) break -fail } else { mprintf("(smoketest - %d - SUCCESS)\n", $probe_aurora_tp_errors) } } if ($pattern == 4) { mprintf("Running TPIU test pattern 5/A...\n"); eval $probe_pattern = 2; } else if ($pattern == 8) { mprintf("Running TPIU test pattern 0/F...\n"); eval $probe_pattern = 3; } else { mprintf("ERROR: Unsupported pattern: %d\n", $pattern) break -fail } target tracereg aurora_tp_enable=0 target tracereg aurora_tp_reset=1 substitute target tracereg aurora_tp_pattern=%EVAL{p/x $probe_pattern} substitute target rw tpiu_curr_test_pat %EVAL{p/x 0x00020000 | $pattern} target tracereg aurora_tp_enable=1 eval $delay_ms = $num_seconds / 0.010; eval $pct = 0 while ($pct < 100) { substitute wait -time %EVAL{p/d $delay_ms} eval $pct += 10 mprintf("%d%% ", $pct) } mprintf("Done!\n") target tracereg aurora_tp_enable=0 target rw tpiu_curr_test_pat 0 trace off -no_retrieve trace clear substitute eval $p_%EVAL{target tracereg aurora_tp_errors} mprintf("Test results: %d errors in %d second(s)\n", $p_aurora_tp_errors, $num_seconds) }