Skip to main content
emobility.academy
M.TechCode generation & HILAdvanced About 8 weeksMATLAB & Simulink

SIL Back-to-Back Testing and Code Coverage for an EV Function

Set up software-in-the-loop (SIL) back-to-back testing for an EV regenerative-braking blending function: run the same Simulink Test cases on the model and on its generated C code, compare outputs with tolerances, and measure model and code coverage with Simulink Coverage to find untested logic.

Tools: Embedded Coder · Simulink Test · Simulink Coverage

SIL Back-to-Back Testing and Code Coverage for an EV Function: STM32 board, LCD and laptop running firmware on a DIYguru lab desk
Representative photo from DIYguru's EV lab, not of this specific project.

The problem

Automotive software standards expect evidence that generated code behaves like the model it came from and that tests exercise the code thoroughly. Back-to-back testing provides the first, coverage analysis the second. Setting these up well, with meaningful tolerances, coverage targets and an explanation for every coverage gap, is a practical skill that is rarely taught.

Objectives

  • Model a regenerative-braking blending function with SOC, speed and temperature limits.
  • Write requirement-based tests in Simulink Test.
  • Run back-to-back MIL versus SIL comparisons with defined tolerances.
  • Measure decision, condition and MC/DC coverage on the model and the code.
  • Close or justify every coverage gap.

What you need

Tools and toolboxes

  • Simulink — Regenerative-braking blending model and test harnesses.
  • Embedded Coder — C code generation and SIL execution.
  • Simulink Test — Test Manager, test harnesses, equivalence tests between MIL and SIL, and reports.
  • Simulink Coverage — Model coverage and generated-code coverage (decision, condition, MC/DC).
  • Stateflow (optional) — Mode logic for regeneration enable and fade-out.

Software

  • MATLAB R2023b or later
  • Simulink
  • Embedded Coder
  • Simulink Test
  • Simulink Coverage
  • A C compiler supported by MATLAB

Extra parts and data

None beyond the software above.

Key concepts

Back-to-back testing
Running identical inputs through the model and the generated code and comparing outputs, so any behavioural difference introduced by code generation is caught.
Equivalence tolerance
The allowed difference between model and code outputs. It should be zero for logic and integer signals and justified by data type for floating-point or fixed-point signals.
MC/DC
Modified condition/decision coverage requires showing that each condition in a decision independently affects its outcome; it is demanded for higher integrity levels.
Coverage gap analysis
Each uncovered decision or condition is either covered with a new test, shown to be unreachable, or justified, so the gap is understood rather than ignored.

Step-by-step guide

  1. 1

    Define the function and requirements

    Model a regenerative-braking blending function: given brake pedal demand, vehicle speed, battery SOC and battery temperature, split braking torque into regenerative and friction parts. Write requirements with example values: no regeneration above 95 per cent SOC, linear derating from 90 to 95 per cent, fade-out below 8 km/h, limit at low temperature, and total torque always equal to demand. Number them.

    Checkpoint: A requirement table of about ten items with clear pass criteria.

  2. 2

    Build the model

    Use lookup tables for regeneration limits against speed, SOC and temperature, a Min block to take the most restrictive limit, and the friction share as demand minus regeneration. Use fixed-step discrete at 10 ms. Choose data types early, for example single for torque, to keep MIL and SIL comparable. Keep the function in an atomic subsystem or referenced model for code generation.

    Checkpoint: Simulation shows regenerative torque falling to zero as SOC rises from 90 to 95 per cent while total torque matches demand.

  3. 3

    Write requirement-based tests

    Create a harness and test cases in the Test Manager: one or more per requirement, with boundary values (SOC exactly 90 and 95 per cent, speed exactly 8 km/h) and combined conditions. Use Test Sequence blocks for multi-step scenarios and verify() statements for pass criteria. Run the suite in normal (MIL) mode and fix any model defects. Link each test case to its requirement number in its name or description, so the evidence chain is clear later.

    Checkpoint: All requirement-based tests pass in MIL.

  4. 4

    Measure model coverage

    Enable coverage collection in the Test Manager with decision, condition and MC/DC metrics, and rerun the suite. Open the coverage report and highlight the model. List every uncovered decision or condition. Typical gaps are saturation limits not reached and lookup-table extrapolation regions. Save the coverage data with the test results, so later runs can be compared and any drop in coverage after a model change is noticed quickly. Also note which tests contribute most coverage.

    Checkpoint: A coverage report with percentages and a list of uncovered items.

  5. 5

    Close coverage gaps

    For each gap, either add a test that exercises it, show that it cannot be reached with valid inputs (and consider removing it), or write a justification. Add the new tests to the suite, linked to the requirement they exercise. Rerun coverage. Avoid writing tests purely to hit coverage without checking a requirement-based expected result. Record the decision for every gap in a table with columns for item, action and reason, which becomes part of the evidence package.

    Checkpoint: Model coverage at the target, for example 100 per cent decision and MC/DC, or each remaining gap justified in writing.

  6. 6

    Generate code and set up SIL

    Configure the referenced model for Embedded Coder (ert.tlc) and generate code. In the Test Manager, create an equivalence test that runs the same harness in Normal mode and in Software-in-the-Loop mode, or set the simulation mode per test iteration. Define tolerances per signal: zero for Boolean flags, a small absolute tolerance for single-precision torque. Keep code-generation settings in a configuration reference so MIL and SIL use exactly the same configuration.

    Checkpoint: The equivalence test runs both modes and reports a comparison for each signal.

  7. 7

    Run back-to-back tests

    Run every requirement-based test as an equivalence test. Investigate any difference outside tolerance: common causes are different rounding, data-type settings that differ between simulation and code, or optimisation settings. Document each difference and its resolution. A clean result means the code behaves like the model for every test. Keep the tolerances in a single file referenced by every test, so they can be reviewed in one place and changed consistently if a justification changes. Record the compiler used for SIL.

    Checkpoint: All equivalence tests pass with the declared tolerances.

  8. 8

    Measure code coverage

    Enable code coverage for SIL in the coverage settings and rerun the suite. Compare model coverage with code coverage. Code can contain branches the model does not show, such as saturation or division protection, so code coverage may be lower. Explain each extra code branch and add tests or justifications. Make sure the coverage tool records code coverage only for the generated function under test, not for harness code, so the percentages are meaningful.

    Checkpoint: A side-by-side table of model and code coverage with every difference explained.

  9. 9

    Inject defects

    Introduce small deliberate defects in the model, such as a wrong threshold or an inverted condition, regenerate code and rerun. Check which tests fail. If a defect goes undetected, your tests have a weakness; add a test. This is a simple form of mutation testing and shows the suite's real strength beyond coverage numbers. Keep each mutant in a separate copy of the model so the original stays clean and every mutant can be rerun later.

    Checkpoint: A table of injected defects and the tests that detected them, with none undetected after improvements.

  10. 10

    Generate reports

    Produce test results, equivalence comparison and coverage reports from the Test Manager and the coverage tool. Organise them as evidence: requirement → test → MIL result → SIL result → coverage. Keep report generation scripted so it can be rerun after changes. Store the reports alongside the model version they belong to, so evidence always refers to a known design. Include the MATLAB and compiler versions in each report, as tool versions can affect both behaviour and coverage.

    Checkpoint: A scripted evidence package that regenerates in one command.

  11. 11

    Write up

    Present the function, requirements, test design, coverage strategy, SIL setup, tolerances and their justification, gap analysis, defect-injection results and limits. Discuss how this would fit an ISO 26262-style process, without claiming compliance. Note what SIL cannot show, such as target-specific numerics, which PIL addresses. Include the gap-analysis table and the mutation results as the central evidence, since they show the quality of the testing rather than only its quantity.

    Checkpoint: A thesis chapter with an evidence table and a discussion of limits.

Testing & validation

  • All requirement-based tests pass in MIL.
  • Model coverage at target or every gap justified.
  • MIL versus SIL equivalence tests pass with justified tolerances.
  • Code coverage measured and differences from model coverage explained.
  • Injected defects detected by the test suite.

Expected results

A complete MIL–SIL back-to-back test setup for an EV regenerative-braking function, with requirement-based tests, justified tolerances, model and code coverage evidence, gap analysis and a defect-injection study.

Research angle for your M.Tech thesis

Research questions: how well do coverage metrics predict a test suite's ability to detect defects in generated EV control code, and how should equivalence tolerances be set for floating- and fixed-point implementations? Metrics: model and code coverage, defect-detection rate under systematic mutation, number of equivalence failures and their causes. Baselines: requirement-based tests only, coverage-driven tests, and automatically generated tests. A systematic mutation study across several EV functions, with released models and test suites, would make a solid conference contribution on verification practice.

Take it further

  • Add PIL on an STM32 target and compare with SIL.
  • Generate tests automatically with Simulink Design Verifier and compare their coverage with hand-written tests.
  • Run the suite in a continuous integration job with the MATLAB command line.
  • Convert to fixed-point and repeat the equivalence tests.

Viva and review questions

Why is 100 per cent coverage not proof of correctness?

Coverage shows that code was executed by tests, not that the expected results were right; a test can execute a branch without checking its output.

Why can code coverage be lower than model coverage?

Generated code can contain branches that have no visible block in the model, such as saturation handling or protection against division by zero, which need their own tests or justification.

How did you choose tolerances?

Zero for logical and integer outputs, and a small absolute tolerance for single-precision signals based on the expected rounding difference, justified per signal.

Learn it at DIYguru

These DIYguru courses and programmes teach what this project needs.

Related EV projects

All 100 MATLAB & Simulink EV projects