User Guide Topics

Processor-in-the-Loop (PIL) testing verifies that code generated from your Simulink model produces correct results when executed on actual target hardware. PIL runs your algorithm on the real microcontroller and compares the output with a reference simulation, providing both numerical verification and performance analysis.

What is PIL Testing?

PIL testing bridges the gap between simulation and real-world deployment by:

  1. Generating embedded C code from your Simulink model or subsystem
  2. Compiling the code with the target compiler (XC16/XC-DSC/XC32)
  3. Programming the code to target hardware (dsPIC, PIC32, SAM)
  4. Executing the algorithm on real hardware with test inputs
  5. Comparing hardware results with simulation reference
  6. Measuring execution time and resource usage (CPU cycles, stack, memory)

๐Ÿ’ก Why PIL is Critical: PIL catches errors that simulation alone cannot detect:

        **Fixed-point quantization errors**: Hardware arithmetic vs. simulation floating-point
        **Compiler optimization side effects**: Code may behave differently when optimized
        **Hardware-specific behavior**: Peripheral timing, interrupt latency, memory access
        **Performance bottlenecks**: Actual execution time vs. theoretical analysis

PIL vs External Mode

FeaturePIL TestingExternal Mode
PurposeVerification & performance analysisReal-time tuning & debugging
When to UseBefore production releaseDuring development & commissioning
Code ModificationNo modification (tests production code)Adds communication overhead
Performance ImpactNone (measured without overhead)5-15% CPU overhead
Hardware ConnectionProgrammer (ICD/PICkit) during testSerial/Ethernet required during runtime
Test AutomationFully automatedManual interaction
OutputsPass/fail verification, timing dataReal-time plots, tuned parameters

PIL Test Results

PIL testing provides two types of critical verification:

1. Numerical Verification

Compares hardware execution results with simulation reference to detect:

  • Code generation errors: Verify code generator produces correct logic
  • Fixed-point quantization: Check if integer arithmetic matches floating-point simulation
  • Compiler optimization artifacts: Ensure optimizations don’t change behavior
  • Hardware arithmetic differences: Detect rounding or overflow issues

Pass Criteria:

Data TypeAcceptable ErrorNotes
double (64-bit float)< 1e-14Rounding errors only
@@PROT_9@@ (32-bit float)< 1e-6Rounding errors only
@@PROT_10@@ / @@PROT_11@@0 (exact match)Must match exactly
@@PROT_12@@ / @@PROT_13@@0 or ยฑ1 LSBCheck for acceptable quantization
Fixed-pointApplication-dependentVerify against requirements

2. Timing Analysis

Measures actual execution time on target hardware:

  • Minimum execution time: Best-case code path (fastest input combination)
  • Maximum execution time: Worst-case code path (critical for real-time deadlines)
  • Average execution time: Typical performance (for CPU load estimation)
  • Stack usage: Peak stack depth (verify no stack overflow)
  • Code size: Flash memory used (verify fits in device)

Example Timing Report:

@@PROT_1@@

Requirements for PIL Testing

Hardware Requirements

  1. Target board with supported microcontroller (dsPIC, PIC32, SAM)
  2. Programmer/debugger (ICD4/5, PICkit4/5, PKOB4, Snap, ICE4)
  3. USB cable to connect programmer to PC

Model Requirements

  1. Master Block in your model for target configuration
  2. Timer PIL Profiling Block to measure execution time
  3. Algorithm under test as a subsystem or referenced model
  4. Reference model (same algorithm) for comparison
  5. Test inputs (signal sources: sine waves, steps, ramps)
  6. Comparison logic (subtract outputs, check error threshold)
๐Ÿ’ก Timer PIL Profiling Block: The Timer PIL Profiling Block uses hardware timer peripherals to measure execution time with cycle-accurate precision. Add this block to any subsystem you want to profile.

PIL Test Model Structure

A typical PIL test model includes:

[Test Inputs] โ†’ [PIL Block (Hardware)] โ†’ [Output]
                       โ†“                      โ†“
                  [Timing Data]          [Compare]
                                             โ†“
              [Reference Model] โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ†’ [Error]
                                             โ†“
                                        [Assertion]
                                        (Fail if error > threshold)

Model Components:

  • Test Inputs: Signal sources (sine, step, ramp, chirp) covering operating range
  • PIL Block: Subsystem configured to run on hardware
  • Reference Model: Same algorithm running in Simulink simulation
  • Comparison: Subtract outputs to calculate error
  • Assertion: Stop simulation and report failure if error exceeds threshold
  • Timing Analysis: Timer PIL Profiling block measures execution cycles

Configuring a Subsystem for PIL

Step 1: Create Test Model

  1. Create a new Simulink model
  2. Add test signal sources (Sine Wave, Step, Ramp, etc.)
  3. Add your algorithm as a Subsystem or Model Reference block
  4. Add a duplicate reference implementation for comparison
  5. Add comparison logic (Subtract block + Assertion block)

Step 2: Configure Subsystem for PIL

  1. Right-click the subsystem (or Model Reference block)
  2. Select C/C++ Code โ†’ Build
  3. In the build dialog:
    • Set Build action to “Processor-in-the-Loop (PIL)”
    • Select your programmer (ICD4/5, PICkit4/5, etc.)
    • Choose communication interface (typically Simulator or Serial)
  4. Click Build

Step 3: Add Timer PIL Profiling Block

  1. Open the subsystem you want to profile
  2. Add Timer PIL Profiling block from MCHP Blockset
  3. Configure the timer peripheral (usually Timer 1)
  4. Connect timing output to model output for logging

Step 4: Run PIL Test

  1. Click Run (or press Ctrl+T) in the test model
  2. Code is automatically:
    • Generated from subsystem
    • Compiled with target compiler
    • Programmed to hardware via programmer
    • Executed with test inputs
  3. Results are collected and compared with reference
  4. Timing report is generated

Interpreting PIL Results

Numerical Verification

PASS: Hardware output matches simulation within tolerance

Max error: 3.2e-15  (double precision rounding)
Status: โœ… PASS - Code generation verified correct

FAIL: Hardware output differs significantly from simulation

Max error: 0.045  (45 LSB in 16-bit fixed-point)
Status: โŒ FAIL - Investigate:
  โ€ข Fixed-point word length
  โ€ข Overflow protection
  โ€ข Scaling factors
  โ€ข Integer division rounding

Timing Analysis

PASS: Maximum execution time is less than sample period

Sample period: 1000 ฮผs (1 kHz)
Max execution:  650 ฮผs
Margin:        350 ฮผs (35%)
Status: โœ… PASS - Meets real-time deadline

FAIL: Execution time exceeds deadline

Sample period: 1000 ฮผs (1 kHz)
Max execution: 1200 ฮผs
Status: โŒ FAIL - Deadline missed by 200 ฮผs

Solutions:
  โ€ข Enable compiler optimization (-O2 or -O3)
  โ€ข Simplify algorithm or reduce computation
  โ€ข Increase sample period (reduce execution rate)
  โ€ข Use faster microcontroller

Optimization After Failed PIL Timing

If PIL timing fails (execution time exceeds deadline):

1. Enable Compiler Optimization

Use the Compiler Options Block to enable -O2 optimization (free license) or -O3 (PRO license).

2. Profile to Find Bottlenecks

Use Timer PIL Profiling blocks on individual subsections to identify slow code paths.

3. Algorithm Optimization

  • Replace divisions with multiplications where possible
  • Use lookup tables instead of transcendental functions (sin, cos, sqrt)
  • Pre-compute constants outside loops
  • Reduce loop iterations

4. Code Replacement Library

Enable assembly-optimized math functions in model configuration (Code Generation โ†’ Interface โ†’ Code replacement library).

5. Upgrade Hardware

Consider a faster microcontroller (e.g., dsPIC33E โ†’ dsPIC33C โ†’ dsPIC33A).

Best Practices

Development Workflow

Phase 1: Algorithm Development
  1. Develop algorithm in Simulink (pure simulation)
  2. Verify functionality with simulation tests

Phase 2: PIL Verification
  3. Create PIL test model with reference comparison
  4. Run PIL test for numerical verification
  5. If FAIL: debug fixed-point, scaling, overflow issues

Phase 3: Performance Validation
  6. Add Timer PIL Profiling blocks
  7. Measure execution time
  8. If timing FAIL: optimize (see above)

Phase 4: Hardware Deployment
  9. Deploy to hardware with External Mode for tuning
  10. Final PIL test with tuned parameters
  11. Disable External Mode and build production code

Testing Recommendations

  • Test early: Run PIL after each major algorithm change
  • Use realistic inputs: Cover full operating range, edge cases
  • Test worst-case timing: Find maximum execution time path
  • Automate tests: Integrate PIL into CI/CD pipeline
  • Document results: Keep timing reports and numerical verification logs

Detailed PIL Guide

For comprehensive information including External Mode comparison, timing analysis strategies, and advanced PIL workflows, see:

๐Ÿ“š External Mode & PIL Testing Guide

This detailed guide covers:

  • PIL test model structure and design
  • Numerical verification pass criteria
  • Timing analysis interpretation
  • External Mode vs PIL comparison
  • Best practices for production deployment

Home | User Guide | Code Generation | External Mode | Compiler Setup | Video Demos | Block Reference