NOTICE: The Processors Wiki will End-of-Life in December of 2020. It is recommended to download any files or other content you may need that are hosted on The site is now set to read only.

System Analyzer Tutorial 4B

From Texas Instruments Wiki
Jump to: navigation, search

System Analyzer Tutorial 4B:

How to Enable Multicore Event Correlation When Using JTAG Transports

In Tutorial 3A, we worked with an example program called 'stairstep' that illustrated how to work with the built-in software instrumentation that ships with SysBIOS. In this tutorial, we'll extend that example so that it:

  • Uploads events via JTAG on a multicore emulation target while the target is running
  • Logs a sync point event in main() after the program starts running
  • Has a background idle loop that checks to see if a sync point needs to be logged due to the target halting and, if required, logs one

We'll be running this example program on all of the cores on the emulation target. (Note that currently, simulation targets do not support multicore event correlation). For the sake of simplicity, we'll ignore the complexity of resource managing the Timers on the board, and let each CPU think that it can use whatever timer it wants. Since they will all be configuring the timer in the same way, it doesn't affect the operation of the demo. Also, since all cores are running the same program and data is on the stack, we leave details such as how to partition the memory to accommodate different program images to Tutorial 4C.

If you are starting with the Tutorial 3A project built for the simulator, you will need to make the following changes:

  • Change the RTSC platform to an appropriate multicore emulation target (e.g. evm6472, evm6474, evm6678...)
  • Right click on the project in the CCS Project Explorer, select Build Options / General / RTSC and select the platform from the drop-down list near the bottom of the dialog page.
  • Edit the .cfg file and replace the following line:
  • LoggingSetup.eventUploadMode = LoggingSetup.UploadMode_SIMULATOR;
  • with this line:
  • LoggingSetup.eventUploadMode = LoggingSetup.UploadMode_JTAGRUNMODE;

Clean and build the project.

If you run the project right now on all cores and start System Analyzer, you will notice that there are a lot of dropped events!

  • Since we are running this on multiple cores, but still only have a single JTAG connection to upload all of the event data, the bandwidth available to upload events is sometimes not sufficient to allow the host to upload events faster than they are being logged.

We'll be covering ways to manage data throughput to minimize data loss in a future tutorial. For now, let's turn off the SysBios task switching events so that we can focus on the task load and CPU load events. To do that, add the following line to your .cfg file

  • LoggingSetup.sysbiosTaskLogging = false;

To get better resolution in the Task Load graph (at the cost of uploading more events per second), you can also add the following lines to the .cfg file:

  • var Load = xdc.useModule('ti.sysbios.utils.Load');
  • Load.windowInMs = 50;

Also, if you are running on a C6XXX target, in order to make it easier to see the various CPU cores all doing different things, please make the following changes to the stairstep.c file:

  • Add the following include statement:
  • #include <c6x.h> // for DNUM
  • And in the timerFunc function, replace the following statements:
  • /* change load values every 5 seconds */
  • if (++tickCount >= (5 * NUMPERSEC)) {
  • with
  • /* change load values every (1+DNUM)/2 seconds */
  • if (++tickCount >= (((1 + DNUM) * NUMPERSEC))>>1) {

You should be able to run the project on all cores with less data loss than before.

At this point, we still haven't correlated the events from the various cores with each other. If you start one core much later than the other, its local CPU timestamps will be misaligned with those of the other CPU cores, so you won't really have any idea of how the events from the various CPUs 'line up' with each other. Each CPU effectively has its own 'timeline'.

Enabling Multicore Event Correlation: C code and Configuration Script

In order to enable multicore event correlation, please either make the following changes to your code or replace the .c and .cfg files in your project with those in

C code:

/* Add include file for LogSync module: */ 
#include <ti/uia/runtime/LogSync.h>
#include <xdc/cfg/global.h>

/* Function prototype for the idle function */
Void myIdleFunc();

 Void main()
	/* The LogSync_writeSyncPoint API call should NOT be the first thing executed in main(), since
	   the compiler may reorder the execution of the associated opcodes in a way that causes it to be
	   executed before the CPU actually halts when running to main after program load. */ 
    Log_print0(Diags_USER1, "stairstep example started.");    
    /* Fall into BIOS idle loop */
Void myIdleFunc(){
	if (LogSync_isSyncEventRequired()){

.cfg configuration script

/* Bring in the LogSync module, and configure it so that 
 * event correlation is enabled even though we are using
 * JTAG as a transport. */
var LogSync = xdc.useModule('ti.uia.runtime.LogSync');
LogSync.enableEventCorrelationForJTAG = true;

/* Register the idle function hook */
var Idle = xdc.useModule('ti.sysbios.knl.Idle');

When you start one of the cores, you will see a 'Warning: Waiting UIA SyncPoint data.' message displayed in the lower left corner of the Log view:
System Analyzer waits for sync point events to be logged from all CPUs before it will display any events, in order to order the events properly in the view and the associated graphs and timelines.

Here's a screenshot showing the stairstep program running on a 6 core C6472 EVM, with Task Load graphs for cores 0,1 and 6 displayed. The Sync point events that were logged at program startup are displayed in the Log view.
Tutorial4B screenshot.gif
Note that the EnableGroupingButton.gif (Enable Grouping) button has been clicked so that the views will scroll together. Clicking the EnableGroupingButton.gif button on the Log view will allow you to click on an event in the log view and have the other grouped views show where that event is on their graphs.

Once you halt a CPU, that CPU's timestamp will typically also be stopped and a new sync point will need to be logged by that CPU in order to re-establish the correlation between the local CPU timestamp and the global timestamp.

Note 1: The target is halted momentarily whenever the CPU writes to the console (CIO) e.g. using stdio . This will cause loss of correlation from that point onwards. e.g. if you rework the MCSDK ImageProcessing Example to use JTAG as a transport, event correlation will lose synchronization whenever the master uses platform_write() statements, which are routed to CIO in the default case. To overcome this, you should log another sync point event after the CIO operation, either by adding the LogSync_writeSyncPoint() API call to your code after the CIO operation, or by following the steps described in 'Note 2' below. (Thanks to Alois Hahn for this note!)

Note 2: Each time you halt the cores to read the events, you will need to stop your current System Analyzer session (by clicking the StopSystemAnalyzer.gif button in the Logs view toolbar), and then re-start it again(by clicking the StartSystemAnalyzer.gif button that the stop button turns into after System Analyzer has been stopped). (Note that this feature was added fairly recently - if you are using a version of CCS earlier than CCSv5.4, you will need to close System Analyzer and then re-open it).

When you start up System Analyzer, you will see the 'Warning: Waiting UIA SyncPoint data.' message in the Log view. To get the CPUs to log a new Sync Point event that this System Analyzer session can work with:

  • right click on the CPU in the debug view and select "Open GEL Files View"
  • For each core on the device:
  • click on the core in the debug view to bring it into focus
  • right click on the GEL Files view table, select "Load GEL file" and load the systemAnalyzerLogSync.gel file
  • From the Scripts menu, select System Analyzer LogSync ->LogSyncPointEvent

What this does:

  • The LogSync module's LogSync_isSyncEventRequired() API checks to see if the ti_uia_runtime_LogSync_gNumTimesHalted global variable has changed since the last time it checked, and returns true if it has.
  • The systemAnalyzerLogSync.gel file's LogSyncPointEvent function increments this global variable, so that the Idle callback function will log a sync point the next time it runs.

While this won't cope with single stepping or hitting frequent breakpoints, it is sufficient to enable you to do some debugging without having to restart your program every time in order to reestablish synchronization between cores.

Next: Tutorial 4C: How to communicate with multicore devices via Ethernet, with IPC communication between cores