Files
RTOS/tools/analysis/timing_analyzer.py
T
root ca13734bf0 Add full automotive RTOS project
Add kernel (Cortex-M0/M3/M4, Tricore, S32K, RISC-V ports), drivers,
middleware (CAN stack, diagnostics, safety), applications, board
support, build/test tooling, and documentation.
2026-08-23 03:35:29 -04:00

216 lines
7.2 KiB
Python
Executable File

#!/usr/bin/env python3
"""
@file timing_analyzer.py
@brief Timing analyzer for Automotive RTOS
"""
import os
import re
import sys
import argparse
import json
from collections import defaultdict
from pathlib import Path
class TimingAnalyzer:
"""Analyze timing requirements and performance"""
def __init__(self, project_root):
self.project_root = Path(project_root)
self.tasks = {}
self.timing_data = defaultdict(list)
self.violations = []
def analyze_task_configuration(self):
"""Analyze task timing configuration"""
print("Analyzing task configuration...")
task_config_file = self.project_root / 'config' / 'task_config.h'
if not task_config_file.exists():
print("Task configuration file not found")
return
with open(task_config_file, 'r') as f:
content = f.read()
# Parse task priorities and periods
task_pattern = re.compile(
r'\{"([^"]+)",\s*(\d+),\s*(\d+),\s*(\d+),\s*(\d+),\s*(true|false),\s*(true|false)\}'
)
print("\nTask Configuration:")
print("-" * 80)
print(f"{'Task Name':25s} {'Priority':>8s} {'Period':>8s} {'Deadline':>8s}")
print("-" * 80)
for match in task_pattern.finditer(content):
task_name = match.group(1)
priority = int(match.group(2))
period = int(match.group(3))
deadline = int(match.group(5))
self.tasks[task_name] = {
'priority': priority,
'period': period,
'deadline': deadline
}
print(f"{task_name:25s} {priority:8d} {period:8d} {deadline:8d}")
print("-" * 80)
def analyze_schedulability(self):
"""Analyze task schedulability"""
print("\nSchedulability Analysis:")
print("-" * 60)
# Calculate CPU utilization
total_utilization = 0
for task_name, config in self.tasks.items():
if config['period'] > 0:
utilization = config['deadline'] / config['period']
total_utilization += utilization
print(f"{task_name:25s} {utilization*100:6.2f}%")
print("-" * 60)
print(f"Total CPU Utilization: {total_utilization*100:.2f}%")
# Check schedulability
if total_utilization < 0.69: # Liu & Layland bound for RM
print("✓ System is schedulable (Rate Monotonic)")
else:
print("⚠ System may not be schedulable")
self.violations.append("High CPU utilization")
def analyze_timing_logs(self, log_file):
"""Analyze timing logs"""
if not os.path.exists(log_file):
print(f"Timing log not found: {log_file}")
return
print(f"\nAnalyzing timing log: {log_file}")
with open(log_file, 'r') as f:
for line in f:
# Parse timing data
match = re.match(
r'\[(\d+)\]\s+(\w+):\s+start=(\d+)\s+end=(\d+)\s+duration=(\d+)'
, line)
if match:
timestamp = int(match.group(1))
task_name = match.group(2)
duration = int(match.group(5))
self.timing_data[task_name].append({
'timestamp': timestamp,
'duration': duration
})
# Calculate statistics
print("\nTiming Statistics:")
print("-" * 80)
print(f"{'Task Name':25s} {'Count':>6s} {'Min':>8s} {'Max':>8s} {'Avg':>8s} {'Jitter':>8s}")
print("-" * 80)
for task_name, measurements in self.timing_data.items():
if measurements:
durations = [m['duration'] for m in measurements]
count = len(durations)
min_duration = min(durations)
max_duration = max(durations)
avg_duration = sum(durations) / count
jitter = max_duration - min_duration
print(f"{task_name:25s} {count:6d} {min_duration:8d} "
f"{max_duration:8d} {avg_duration:8.1f} {jitter:8d}")
# Check for violations
if task_name in self.tasks:
deadline = self.tasks[task_name]['deadline']
if max_duration > deadline:
self.violations.append(
f"{task_name} exceeds deadline: {max_duration} > {deadline}"
)
def analyze_interrupt_timing(self):
"""Analyze interrupt timing"""
print("\nInterrupt Timing Analysis:")
print("-" * 40)
# Common interrupt latencies
interrupts = {
'SysTick': {'priority': 15, 'typical_latency': 1},
'CAN': {'priority': 5, 'typical_latency': 2},
'UART': {'priority': 6, 'typical_latency': 1},
'SPI': {'priority': 7, 'typical_latency': 1},
'I2C': {'priority': 7, 'typical_latency': 2},
'ADC': {'priority': 8, 'typical_latency': 3},
'Timer': {'priority': 8, 'typical_latency': 1},
}
for irq_name, config in interrupts.items():
print(f"{irq_name:15s} Priority: {config['priority']:2d} "
f"Latency: {config['typical_latency']}ms")
def generate_report(self, output_file):
"""Generate timing analysis report"""
print(f"\nGenerating report: {output_file}")
with open(output_file, 'w') as f:
f.write("=" * 80 + "\n")
f.write("Timing Analysis Report\n")
f.write("=" * 80 + "\n\n")
# Task configuration
f.write("Task Configuration:\n")
f.write("-" * 40 + "\n")
for task_name, config in self.tasks.items():
f.write(f"{task_name}: Priority={config['priority']}, "
f"Period={config['period']}ms, Deadline={config['deadline']}ms\n")
f.write("\n")
# Violations
if self.violations:
f.write("Timing Violations:\n")
f.write("-" * 40 + "\n")
for violation in self.violations:
f.write(f"{violation}\n")
else:
f.write("No timing violations detected.\n")
def analyze(self, timing_log=None):
"""Run complete analysis"""
print("=" * 60)
print("Timing Analyzer")
print("=" * 60)
self.analyze_task_configuration()
self.analyze_schedulability()
self.analyze_interrupt_timing()
if timing_log:
self.analyze_timing_logs(timing_log)
# Generate report
report_file = self.project_root / 'build' / 'timing_report.txt'
report_file.parent.mkdir(parents=True, exist_ok=True)
self.generate_report(report_file)
print(f"\nReport saved to: {report_file}")
def main():
parser = argparse.ArgumentParser(description='Timing analyzer')
parser.add_argument('--project', default='.', help='Project root directory')
parser.add_argument('--timing-log', help='Timing log file')
args = parser.parse_args()
analyzer = TimingAnalyzer(args.project)
analyzer.analyze(args.timing_log)
if __name__ == '__main__':
main()