3.6.2. Controlling the execution mode

To provide fully controlled debugging of the target, the attached debugger must be able to control the execution of the target. This capability is provided in CADI by a set of method calls that can determine the current state of the target and initiate state changes such as stopping or running. This target execution control is closely coupled to CADICallbackObj.

The mode, that is, the state of the target, can be explicitly requested by CADIExecGetMode(). This might be useful to, for example, connect to an existing simulation.

Polling of the target state is not, however, the recommended general solution. The modeChange() callback of CADICallbackObj must be implemented by the caller to eliminate the requirement for such polling calls and prevent blocking the interface. The returned mode is of type CADI_EXECMODE_t. The returned state is either CADI_EXECMODE_Run, CADI_EXECMODE_Stop, CADI_EXECMODE_Error, or CADI_EXECMODE_ResetDone.

Note

CADI_EXECMODE_Bpt cannot be returned as the target state from CADIExecGetMode().

CADIExecSetMode() is the counterpart to CADIExecGetMode(). It receives a 32-bit unsigned integer as parameter. The provided value is typically of type CADI_EXECMODE_t which is a 32-bit unsigned integer. The intended use is to pass either CADI_EXECMODE_Run or CADI_EXECMODE_Stop to the target.

Note

CADIExecSetMode() cannot be used to set the target state to CADI_EXECMODE_Bpt.

An example of modifying the target mode is shown in Example 3.9:

Example 3.9. Accessing registers in the target

// very basic example of debugger accessing registers in connected target
// cadi is a connected simulation object of type CADI

cout << "Client: Invoking target->CADIExecSetMode(3)" << endl;
cadi->CADIExecSetMode(3);

cout << "Client: Invoking target->CADIExecGetMode()" << endl;
uint32_t execMode;
cadi->CADIExecGetMode(&execMode);
cout << "Client: Target's current mode is: " << execMode << endl;

Starting and stopping the target

For a subset of execution modes, the following dedicated methods are preferable:

  • CADIExecContinue() instead of CADIExecSetMode(CADI_EXECMODE_Run)

  • CADIExecStop() instead of CADIExecSetMode(CADI_EXECMODE_Stop).

Call CADIExecContinue() to start or continue the execution of a target component. This asynchronous call immediately returns after triggering the target, so the execution might not start immediately. The registered callback object (from the caller) is responsible for indicating the actual beginning of the target execution by issuing a modeChange() callback.

If CADIExecContinue() is called and the target is running (CADI_EXECMODE_Run), the target must ignore the call and return CADI_STATUS_TargetBusy.

Call CADIExecStop() to stop a running simulation. This method returns immediately and the target is not typically stopped when the call returns. The caller must wait for a modeChange() callback that indicates CADI_EXECMODE_Stop.

If CADIExecStop() is called and the target is already stopped (CADI_EXECMODE_Stop), the call must be ignored by the target and return CADI_STATUS_TargetBusy.

Note

In general, clients must expect that mode changes can occur asynchronously. If for example an asynchronous mode change occurred during the execution of:

if (t->CADIExecGetMode()==CADI_EXECMODE_Stop) t->CADIExecContinue()

the second call might return CADI_STATUS_TargetBusy while the client receives a modeChange message on the callback thread. The client must handle all possible outcomes of this race condition.

Stepping the target

In addition to the ability to run the target until the next breakpoint or the end of simulation, you can use CADIExecSingleStep() to step the target component for one or more steps.

Target steps can be specified as either cycle steps or instruction steps. That is, the target is either stepped for a specific number of clock cycles or stepped until the corresponding instructions are completely finished.

The stepOver parameter of CADIExecSingleStep() enables stepping over call instructions. This is primarily intended for use with source level debugging where some methods or function calls must not be stepped through.

The method is asynchronous and the call returns immediately and typically before the instructions have been finished. A sequence of modeChanges() to CADI_EXECMODE_Run and CADI_EXECMODE_Stop are issued to inform the caller about the progress of the execution.

If CADIExecSingleStep() is called and the target is running, the call must be ignored and CADI_STATUS_TargetBusy returned.

Using CADI resets

A CADI reset is intended to bring a simulation platform, or one of its components, back into a specific state. This simulation reset must be distinguished from a real hardware reset because it might perform, for example, certain initialization steps that real hardware does not do.

CADI resets are identified by their reset level and a name. The corresponding reset level numbers must be used uniquely within a target. There must not be two different resets defined to be of the same reset level.

CADI permits free definition of its simulation reset levels. Each associated reset can differ in the addressed components or resources. One reset might, for example, only initialize the core registers in a processor, but another reset might modify both the core registers and memory in the target.

CADI reserves reset 0 as a Hard Reset and explicitly specifies the semantics of this reset. All other reset levels, however, can be customized and might differ from model to model. Reset level numbers can be chosen arbitrarily and have no other meaning than representing a certain simulation reset. There is, for example, no ordering of reset levels by their severity.

Because CADI reset 0, the Hard Reset, has fixed semantics, it must be implemented by every model providing a CADI implementation. This Hard Reset resets all state variables of a model including those that would not be modified by a real hardware reset. After the reset, the simulation platform must be in the same state as it was immediately after instantiating it. The corresponding initialization values must be well-defined and must not be chosen randomly. This guarantees that a simulation run with the same loaded application is reproducible after a hard reset.

Caution

Calling CADIExecReset() for any reset level must not touch any set breakpoint or unregister any registered callback object.

A call to CADIExecReset(0) must trigger the following behavior of the target:

  • setting all registers and state variables to their initial values

  • clearing all memories of the target and bring them into their initial state.

  • clearing the internal list of loaded applications (because the memory is cleared). See Application loading.

After calling CADIExecReset(0), it is the responsibility of the calling debugger to reload applications if that is required.

To determine the supported resets for a target, call the CADIExecGetResetLevels() method which provides a list with the corresponding identifiers. The contained reset level number must be forwarded to CADIExecReset() to trigger the required reset.

Using CADIExecReset()

CADIExecReset() is an asynchronous call and can therefore return before the actual reset of the target has finished. After the target has ended all required actions, the simulation thread sends out a modeChange(CADI_EXECMODE_ResetDone) callback to all registered debuggers. Because a target can only accept one CADI reset at a time, the calling debugger can depend on the receiving the end notification for its CADIExecReset() call and then proceed with other required functionality such as loading applications to the target.

Note

The modeChange(CADI_EXECMODE_ResetDone) callback is identical to the legacy CADICallbackObj::reset() callback.

Targets must support both callbacks to maintain backwards compatibility.

ARM recommends using modeChange(CADI_EXECMODE_ResetDone) in client code because the reset() callback is deprecated in a future version of CADI. See CADICallbackObj::modeChange().

Callback behavior

The CADICallbackObj class is an important part of the mechanism for controlling target execution. Unlike the interface calls of the CADI class that initiates behavior changes in the target, the callback mechanism reports changes in the target state back to the caller.

Some callback calls are optional and are not required for the execution control. These include:

  • semihosting (see Using the semihosting API)

  • methods provided for convenience that are not used for control, but instead enable notifying the caller to perform actions on the GUI side such as refreshing views.

Callbacks in CADI are asynchronous and can be received even if a debugger has not triggered any behavior. This is required to enable connection of multiple debuggers to a single target. If for example one debugger requests a running target to stop, all connected debuggers receive a modeChange(CADI_EXECMODE_Stop) callback that instructs the debuggers to change their state and to update the target views.

Note

Callbacks of class CADICallbackObj must only be called from the simulation thread. The associated debugger thread must not, either directly or indirectly, call a callback of this class.

The most important, and almost mandatory, callback for execution control is the modeChange() method. It reports any change of the state of the target state or if a breakpoint is hit. modeChange() receives the execution mode and, if required, the breakpoint ID. The typical execution modes are CADI_EXECMODE_Run, CADI_EXECMODE_Stop, CADI_EXECMODE_Bpt, CADI_EXECMODE_ResetDone, and CADI_EXECMODE_Error.

Issuing a modeChange() callback is only permitted if the state changed and the new state has been reached. For example, a change to CADI_EXECMODE_Stop can only be issued if the target was previously in another state, typically CADI_EXECMODE_Run, and the target is now in the stopped state and has finished ALL implied updates of target resources.

A change to CADI_EXECMODE_Bpt requires an additional breakpoint ID to inform the caller that the breakpoint has been hit. In all other cases, this parameter has to be set to zero which indicates an invalid breakpoint ID.

A mode change to CADI_EXECMODE_Bpt must be issued for every hit breakpoint. If multiple breakpoints triggered at the time, each of them must be reported by dedicated calls. This might be the case if, for example, a register breakpoint and a program breakpoint are hit simultaneously. Both must be reported to enable the caller to react properly to the two events.

A mode change to CADI_EXECMODE_ResetDone indicates the end of a CADI reset and the debugger must update all its views. The debugger might also take additional actions if the debugger was responsible for the reset. See Controlling the execution mode. The caller might expect characteristic sequences of modeChange() callbacks in response to a specific requested functionality. Table 3.2 lists typical schemes:

Table 3.2. Typical modeChange() callback responses

Target stateCalled interface methodExpected modeChange() sequence
StoppedDebugger calls CADIExecContinue().
modeChange(CADI_EXECMODE_Run, 0)
RunningDebugger calls CADIExecStop().
modeChange(CADI_EXECMODE_Stop, 0)
StoppedDebugger calls CADIExecSingleStep().
modeChange(CADI_EXECMODE_Run, 0)
modeChange(CADI_EXECMODE_Stop, 0)
RunningDebugger calls CADIExecContinue() or CADIExecSingleStep().No modeChange() is issued and the corresponding call returns with CADI_STATUS_TargetBusy.
StoppedDebugger calls CADIExecStop().

No modeChange() is issued. The call returns with CADI_STATUS_OK because nothing unexpected or incorrect occurred.

Stopped

Debugger has set a program breakpoint (ID=1) to be hit.

Debugger calls CADIExecContinue().

modeChange(CADI_EXECMODE_Run, 0)
modeChange(CADI_EXECMODE_Bpt, 1)
modeChange(CADI_EXECMODE_Stop, 0)
Stopped

Debugger has set a program breakpoint (ID=1) on the next instruction and a memory breakpoint (ID =2) on an address is modified after finishing the current instruction.

Debugger calls CADIExecSingleStep() for an instruction step.

modeChange(CADI_EXECMODE_Run, 0)
modeChange(CADI_EXECMODE_Bpt, 1)
modeChange(CADI_EXECMODE_Bpt, 2)
modeChange(CADI_EXECMODE_Stop, 0)
Stopped

Debugger has set a breakpoint (ID=1) with property continueExecution set to true. The breakpoint is hit if execution resumes.

Debugger calls CADIExecContinue().

modeChange(CADI_EXECMODE_Run, 0)
modeChange(CADI_EXECMODE_Bpt, 1)

Target continues.

Stopped

Debugger calls CADIExecReset().

modeChange(CADI_EXECMODE_ResetDone, 0)
Running

Debugger calls CADIExecReset().

modeChange(CADI_EXECMODE_Stop, 0) if it is required that the model stop before reset.

modeChange(CADI_EXECMODE_ResetDone, 0)

Copyright © 2008-2014 ARM. All rights reserved.ARM DUI 0444M
Non-ConfidentialID051314