ca13734bf0
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.
206 lines
6.6 KiB
Python
Executable File
206 lines
6.6 KiB
Python
Executable File
#!/usr/bin/env python3
|
|
"""
|
|
@file task_priority_calculator.py
|
|
@brief Task priority calculator for Rate Monotonic Scheduling
|
|
"""
|
|
|
|
import sys
|
|
import argparse
|
|
from collections import defaultdict
|
|
from math import ceil
|
|
|
|
class TaskPriorityCalculator:
|
|
"""Calculate task priorities using RMS/DMS algorithms"""
|
|
|
|
def __init__(self):
|
|
self.tasks = []
|
|
|
|
def add_task(self, name, period_ms, execution_time_ms, deadline_ms=None):
|
|
"""Add task for analysis"""
|
|
if deadline_ms is None:
|
|
deadline_ms = period_ms
|
|
|
|
self.tasks.append({
|
|
'name': name,
|
|
'period': period_ms,
|
|
'execution_time': execution_time_ms,
|
|
'deadline': deadline_ms
|
|
})
|
|
|
|
def calculate_utilization(self):
|
|
"""Calculate CPU utilization"""
|
|
total_utilization = 0
|
|
|
|
for task in self.tasks:
|
|
utilization = task['execution_time'] / task['period']
|
|
task['utilization'] = utilization
|
|
total_utilization += utilization
|
|
|
|
return total_utilization
|
|
|
|
def rate_monotonic_priority(self):
|
|
"""Assign priorities using Rate Monotonic Scheduling"""
|
|
# Sort by period (shortest period = highest priority)
|
|
sorted_tasks = sorted(self.tasks, key=lambda x: x['period'])
|
|
|
|
for i, task in enumerate(sorted_tasks):
|
|
task['rms_priority'] = i
|
|
|
|
return sorted_tasks
|
|
|
|
def deadline_monotonic_priority(self):
|
|
"""Assign priorities using Deadline Monotonic Scheduling"""
|
|
# Sort by deadline (shortest deadline = highest priority)
|
|
sorted_tasks = sorted(self.tasks, key=lambda x: x['deadline'])
|
|
|
|
for i, task in enumerate(sorted_tasks):
|
|
task['dms_priority'] = i
|
|
|
|
return sorted_tasks
|
|
|
|
def check_schedulability(self):
|
|
"""Check if task set is schedulable"""
|
|
n = len(self.tasks)
|
|
total_utilization = self.calculate_utilization()
|
|
|
|
# Liu & Layland bound for RMS
|
|
rms_bound = n * (2 ** (1/n) - 1)
|
|
|
|
# Exact schedulability test
|
|
schedulable = True
|
|
|
|
for i, task in enumerate(sorted(self.tasks, key=lambda x: x['priority'])):
|
|
# Calculate response time
|
|
response_time = task['execution_time']
|
|
|
|
while True:
|
|
interference = 0
|
|
for j in range(i):
|
|
higher_task = self.tasks[j]
|
|
interference += ceil(response_time / higher_task['period']) * \
|
|
higher_task['execution_time']
|
|
|
|
new_response = task['execution_time'] + interference
|
|
|
|
if new_response == response_time:
|
|
break
|
|
|
|
response_time = new_response
|
|
|
|
if response_time > task['deadline']:
|
|
schedulable = False
|
|
break
|
|
|
|
task['response_time'] = response_time
|
|
|
|
if not schedulable:
|
|
break
|
|
|
|
return schedulable, total_utilization, rms_bound
|
|
|
|
def generate_report(self):
|
|
"""Generate priority assignment report"""
|
|
print("=" * 80)
|
|
print("Task Priority Calculation Report")
|
|
print("=" * 80)
|
|
print()
|
|
|
|
# Calculate utilization
|
|
total_utilization = self.calculate_utilization()
|
|
|
|
print("Task Set:")
|
|
print("-" * 80)
|
|
print(f"{'Task':20s} {'Period':>8s} {'Exec Time':>10s} {'Deadline':>8s} {'Util':>8s}")
|
|
print("-" * 80)
|
|
|
|
for task in self.tasks:
|
|
print(f"{task['name']:20s} {task['period']:8d} "
|
|
f"{task['execution_time']:10d} {task['deadline']:8d} "
|
|
f"{task['utilization']*100:7.2f}%")
|
|
|
|
print("-" * 80)
|
|
print(f"{'Total':20s} {'':>8s} {'':>10s} {'':>8s} {total_utilization*100:7.2f}%")
|
|
print()
|
|
|
|
# Rate Monotonic
|
|
print("Rate Monotonic Priority Assignment:")
|
|
print("-" * 40)
|
|
rms_tasks = self.rate_monotonic_priority()
|
|
for task in rms_tasks:
|
|
print(f" Priority {task['rms_priority']}: {task['name']}")
|
|
print()
|
|
|
|
# Deadline Monotonic
|
|
print("Deadline Monotonic Priority Assignment:")
|
|
print("-" * 40)
|
|
dms_tasks = self.deadline_monotonic_priority()
|
|
for task in dms_tasks:
|
|
print(f" Priority {task['dms_priority']}: {task['name']}")
|
|
print()
|
|
|
|
# Schedulability
|
|
schedulable, utilization, bound = self.check_schedulability()
|
|
|
|
print("Schedulability Analysis:")
|
|
print("-" * 40)
|
|
print(f"CPU Utilization: {utilization*100:.2f}%")
|
|
print(f"Theoretical Bound: {bound*100:.2f}%")
|
|
|
|
if schedulable:
|
|
print("✓ Task set is schedulable")
|
|
else:
|
|
print("✗ Task set is NOT schedulable")
|
|
|
|
print()
|
|
print("Response Times:")
|
|
print("-" * 40)
|
|
for task in self.tasks:
|
|
if 'response_time' in task:
|
|
print(f" {task['name']}: {task['response_time']}ms "
|
|
f"(deadline: {task['deadline']}ms)")
|
|
|
|
def main():
|
|
parser = argparse.ArgumentParser(description='Task priority calculator')
|
|
parser.add_argument('--tasks', nargs='+', help='Task definitions: name:period:exec[:deadline]')
|
|
parser.add_argument('--file', help='Task definition file')
|
|
|
|
args = parser.parse_args()
|
|
|
|
calculator = TaskPriorityCalculator()
|
|
|
|
# Load tasks from file or command line
|
|
if args.file:
|
|
with open(args.file, 'r') as f:
|
|
for line in f:
|
|
line = line.strip()
|
|
if line and not line.startswith('#'):
|
|
parts = line.split(':')
|
|
if len(parts) >= 3:
|
|
name = parts[0]
|
|
period = int(parts[1])
|
|
exec_time = int(parts[2])
|
|
deadline = int(parts[3]) if len(parts) > 3 else period
|
|
calculator.add_task(name, period, exec_time, deadline)
|
|
elif args.tasks:
|
|
for task_def in args.tasks:
|
|
parts = task_def.split(':')
|
|
if len(parts) >= 3:
|
|
name = parts[0]
|
|
period = int(parts[1])
|
|
exec_time = int(parts[2])
|
|
deadline = int(parts[3]) if len(parts) > 3 else period
|
|
calculator.add_task(name, period, exec_time, deadline)
|
|
else:
|
|
# Example tasks
|
|
print("Using example task set:")
|
|
calculator.add_task("Engine Control", 1, 0.5)
|
|
calculator.add_task("Brake Control", 5, 1)
|
|
calculator.add_task("CAN Communication", 10, 2)
|
|
calculator.add_task("Sensor Reading", 2, 0.3)
|
|
calculator.add_task("Display Update", 50, 10)
|
|
|
|
calculator.generate_report()
|
|
|
|
if __name__ == '__main__':
|
|
main()
|