## Explore Variable Names and Loop Rolling

### `timesN` Looping Tutorial Overview

Objective: This example shows how you can influence looping behavior of generated code.

Open the Example:

```openExample('simulinkcoder/AdviceAboutTLCTutorialsExample') cd(tlctutorial/timesN)```

Work with the model `sfun_xN` in `tlctutorial/timesN`. It has one source (a Sine Wave generator block), a times N gain block, an Out block, and a Scope block.

The tutorial guides you through following steps:

1. Getting Started — Set up the exercise and run the model

2. Modify the Model — Change the input width and see the results

3. Change the Loop Rolling Threshold — Change the threshold and see the results

4. More About TLC Loop Rolling — Parameterize loop behavior

### Getting Started

1. Make `tlctutorial/timesN` your current folder, so that you can use the files provided.

2. In the MATLAB® Command Window, create a MEX-file for the S-function:

`mex timesN.c`

This avoids picking up the version shipped with Simulink®.

Note

An error might occur if you have not previously run ```mex -setup```.

3. Open the model file `sfun_xN`.

4. View the previously generated code in `sfun_xN_grt_rtw/sfun_xN.c`. Note that no loops exist in the code. This is because the input and output signals are scalar.

### Modify the Model

1. Replace the Sine Wave block with a Constant block.

2. Set the parameter for the Constant block to 1:4, and change the top label, `model: sfun_xN`, to `model: sfun_vec`.

3. Save the edited model as `sfun_vec` (in `tlctutorial/timesN`). The model now looks like this.

4. Because the Constant block generates a vector of values, this is a vectorized model. Generate code for the model and view the ```/*Model output function */``` section of `sfun_vec.c` in your editor to observe how variables and `for` loops are handled. This function appears as follows:

```/* Model output function */ static void sfun_vec_output(int_T tid) { /* S-Function Block: <Root>/S-Function */ /* Multiply input by 3.0 */ sfun_vec_B.timesN_output[0] = sfun_vec_P.Constant_Value[0] * 3.0; sfun_vec_B.timesN_output[1] = sfun_vec_P.Constant_Value[1] * 3.0; sfun_vec_B.timesN_output[2] = sfun_vec_P.Constant_Value[2] * 3.0; sfun_vec_B.timesN_output[3] = sfun_vec_P.Constant_Value[3] * 3.0; /* Outport: '<Root>/Out' */ sfun_vec_Y.Out[0] = sfun_vec_B.timesN_output[0]; sfun_vec_Y.Out[1] = sfun_vec_B.timesN_output[1]; sfun_vec_Y.Out[2] = sfun_vec_B.timesN_output[2]; sfun_vec_Y.Out[3] = sfun_vec_B.timesN_output[3]; UNUSED_PARAMETER(tid); }```

Notice that there are four instances of the code that generates model outputs, corresponding to four iterations.

5. Set the parameter for the Constant block to 1:10, and save the model.

6. Generate code for the model and view the ```/*Model output function */``` section of `sfun_vec.c` in your editor to observe how variables and `for` loops are handled. This function appears as follows:

```/* Model output function */ static void sfun_vec_output(int_T tid) { /* S-Function Block: <Root>/S-Function */ /* Multiply input by 3.0 */ { int_T i1; const real_T *u0 = &sfun_vec_P.Constant_Value[0]; real_T *y0 = sfun_vec_B.timesN_output; for (i1=0; i1 < 10; i1++) { y0[i1] = u0[i1] * 3.0; } } { int32_T i; for (i = 0; i < 10; i++) { /* Outport: '<Root>/Out' */ sfun_vec_Y.Out[i] = sfun_vec_B.timesN_output[i]; } } UNUSED_PARAMETER(tid); }```

Notice that:

• The code that generates model outputs gets “rolled” into a loop. This occurs by default when the number of iterations exceeds 5.

• Loop index `i1` runs from 0 to 9.

• Pointer `*y0` is used and initialized to the output signal array.

### Change the Loop Rolling Threshold

The code generator creates iterations or loops depending on the current value of the Loop unrolling threshold parameter.

The default value of Loop unrolling threshold is `5`. To change looping behavior for blocks in a model:

1. On the Optimization pane of the Configuration Parameters dialog box, set Loop unrolling threshold to `12` and click `Apply`.

The parameter `RollThreshold` is now `12`. Loops will be generated only when the width of signals passing through a block exceeds 12.

Note

You cannot modify `RollThreshold` for specific blocks from the Configuration Parameters dialog box.

2. Press Ctrl+B to regenerate the output.

3. Inspect `sfun_vec.c`. It will look like this:

```/* Model output function */ static void sfun_vec_output(int_T tid) { /* S-Function Block: <Root>/S-Function */ /* Multiply input by 3.0 */ sfun_vec_B.timesN_output[0] = sfun_vec_P.Constant_Value[0] * 3.0; sfun_vec_B.timesN_output[1] = sfun_vec_P.Constant_Value[1] * 3.0; sfun_vec_B.timesN_output[2] = sfun_vec_P.Constant_Value[2] * 3.0; sfun_vec_B.timesN_output[3] = sfun_vec_P.Constant_Value[3] * 3.0; sfun_vec_B.timesN_output[4] = sfun_vec_P.Constant_Value[4] * 3.0; sfun_vec_B.timesN_output[5] = sfun_vec_P.Constant_Value[5] * 3.0; sfun_vec_B.timesN_output[6] = sfun_vec_P.Constant_Value[6] * 3.0; sfun_vec_B.timesN_output[7] = sfun_vec_P.Constant_Value[7] * 3.0; sfun_vec_B.timesN_output[8] = sfun_vec_P.Constant_Value[8] * 3.0; sfun_vec_B.timesN_output[9] = sfun_vec_P.Constant_Value[9] * 3.0; /* Outport: '<Root>/Out' */ sfun_vec_Y.Out[0] = sfun_vec_B.timesN_output[0]; sfun_vec_Y.Out[1] = sfun_vec_B.timesN_output[1]; sfun_vec_Y.Out[2] = sfun_vec_B.timesN_output[2]; sfun_vec_Y.Out[3] = sfun_vec_B.timesN_output[3]; sfun_vec_Y.Out[4] = sfun_vec_B.timesN_output[4]; sfun_vec_Y.Out[5] = sfun_vec_B.timesN_output[5]; sfun_vec_Y.Out[6] = sfun_vec_B.timesN_output[6]; sfun_vec_Y.Out[7] = sfun_vec_B.timesN_output[7]; sfun_vec_Y.Out[8] = sfun_vec_B.timesN_output[8]; sfun_vec_Y.Out[9] = sfun_vec_B.timesN_output[9]; UNUSED_PARAMETER(tid); }```
4. To activate loop rolling again, change the Loop unrolling threshold to 10 (or less) on the Optimization pane.

Loop rolling is an important TLC capability for optimizing generated code. Take some time to study and explore its implications before generating code for production requirements.

### More About TLC Loop Rolling

The following TLC `%roll` code is the `Outputs` function of `timesN.tlc`:

```%function Outputs(block, system) Output /* %<Type> Block: %<Name> */ %% /* Multiply input by %<gain> */ %assign rollVars = ["U", "Y"] %roll idx = RollRegions, lcv = RollThreshold, block, "Roller", rollVars %<LibBlockOutputSignal(0, "", lcv, idx)> = \ %<LibBlockInputSignal(0, "", lcv, idx)> * %<gain>; %endroll %endfunction %% Outputs```

#### Arguments for `%roll`

The lines between `%roll` and %`endroll` may be either repeated or looped. The key to understanding the `%roll` directive is in its arguments:

`%roll sigIdx = RollRegions, lcv = RollThreshold, block, "Roller", rollVars`
ArgumentDescription
`sigIdx`

Specify the index into a (signal) vector that is used in the generated code. If the signal is scalar, when analyzing that block of the `model.rtw` file, TLC determines that only a single line of code is required. In this case, it sets `sigIdx` to `0` so as to access only the first element of a vector, and no loop is constructed.

`lcv`

A control variable generally specified in the `%roll` directive as `lcv = RollThreshold`. `RollThreshold` is a global (model-wide) threshold with the default value of 5. Therefore, whenever a block contains more than five contiguous and rollable variables, TLC collapses the lines nested between `%roll` and `%endroll` into a loop. If fewer than five contiguous rollable variables exist, `%roll` does not create a loop and instead produces individual lines of code.

`block`

This tells TLC that it is operating on block objects. TLC code for S-functions use this argument.

`"Roller"`

This, specified in `rtw/c/tlc/roller.tlc`, formats the loop. Normally you pass this as is, but other loop control constructs are possible for advanced uses (see `LibBlockInputSignal` in Input Signal Functions).

`rollVars`

Tells TLC what types of items should be rolled: input signals, output signals, and/or parameters. You do not have to use all of them. In a previous line, `rollVars` is defined using `%assign`.

`%assign rollVars = ["U", "Y"]`
This list tells TLC that it is rolling through input signals (`U`) and output signals (`Y`). In cases where blocks specify an array of parameters instead of a scalar parameter, `rollvars` is specified as
`%assign rollVars = ["U", "Y", "P"]`

#### Input Signals, Output Signals, and Parameters

Look at the lines that appear between `%roll` and `%endroll`:

```%<LibBlockOutputSignal(0, "", lcv, idx)> = \ %<LibBlockInputSignal (0, "", lcv, idx)> * 2.0;```

The TLC library functions `LibBlockInputSignal` and `LibBlockOutputSignal` expand to produce scalar or vector identifiers that are named and indexed. `LibBlockInputSignal`, `LibBlockOutputSignal`, and a number of related TLC functions are passed four canonical arguments:

ArgumentDescription

first argument — `0`

Corresponds to the input port index for a given block. The first input port has index 0. The second input port has index 1, and so on.

second argument — `" "`

An index variable reserved for advanced use. For now, specify the second argument as an empty string. In advanced applications, you may define your own variable name to be used as an index with `%roll`. In such a case, TLC declares this variable as an integer in a location in the generated code.

third argument — `lcv`

As described previously, `lcv = RollThreshold` is set in `%roll` to indicate that a loop be constructed whenever `RollThreshold` (default value of 5) is exceeded.

fourth argument — `sigIdx`

Enables TLC to handle special cases. In the event that the `RollThreshold` is not exceeded (for example, if the block is only connected to a scalar input signal) TLC does not roll it into a loop. Instead, TLC provides an integer value for the index variable in a corresponding line of “inline” code. Whenever the `RollThreshold` is exceeded, TLC creates a `for` loop and uses an index variable to access inputs, outputs and parameters within the loop.