Commit 0d1c7bcc authored by Marco Maida's avatar Marco Maida 🌱
Browse files

Basic trace generation, one periodic task+jitter

parent 35855c5b
Pipeline #57974 failed with stages
in 40 seconds
......@@ -4,4 +4,5 @@
__pycache__/*
*.py[cod]
*$py.class
_local/*
\ No newline at end of file
_local/*
debug/output
\ No newline at end of file
all:
python3 trace_generator.py -o debug/output/1-periodic_one_perfect.yaml -u 1000 debug/1-periodic_one_perfect.yaml
python3 trace_generator.py -o debug/output/2-periodic_one_jitter.yaml -u 2000 debug/2-periodic_one_jitter.yaml
python3 trace_generator.py -o debug/output/3-periodic_one_variable_job_cost.yaml -u 3000 debug/3-periodic_one_variable_job_cost.yaml
python3 trace_generator.py -o debug/output/4-periodic_one_variable_job_cost_jitter -u 4000 debug/4-periodic_one_variable_job_cost_jitter.yaml
\ No newline at end of file
......@@ -3,13 +3,7 @@ task set:
- id: 1
period: 100
best-case execution time: 50
worst-case execution time: 50
priority: 1
- id: 2
period: 200
jitter: 0
burst: 1
worst-case execution time: 20
priority: 2
...
\ No newline at end of file
---
task set:
- id: 1
period: 100
best-case execution time: 50
worst-case execution time: 50
jitter: 20
priority: 1
...
\ No newline at end of file
---
task set:
- id: 1
period: 100
worst-case execution time: 50
jitter: 20
priority: 1
...
\ No newline at end of file
......@@ -19,13 +19,14 @@ TASK_SET_TAG = "task set"
TASK_ID_TAG = "id"
TASK_WCET_TAG = "worst-case execution time"
TASK_BCET_TAG = "best-case execution time"
TASK_PRIORITY_TAG = "priority"
TASK_PERIOD_TAG = "period"
TASK_JITTER_TAG = "jitter"
TASK_BURST_TAG = "burst"
allowed_tags_at_root_level = [TASK_SET_TAG]
allowed_tags_at_task_level = [TASK_ID_TAG, TASK_WCET_TAG, TASK_PRIORITY_TAG, TASK_PERIOD_TAG, TASK_JITTER_TAG, TASK_BURST_TAG]
allowed_tags_at_task_level = [TASK_ID_TAG, TASK_WCET_TAG, TASK_PRIORITY_TAG, TASK_PERIOD_TAG, TASK_JITTER_TAG, TASK_BURST_TAG, TASK_BCET_TAG]
# ****************************************
......@@ -79,9 +80,12 @@ def parse_natural_number (father, tag, default = None):
else:
value = parse_required (father, tag)
assert value >= 0
try: return int(value)
except: raise Exception(f"'{tag}' has value '{value}', which is not a positive number.")
try:
n = int(value)
assert n >= 0
return n
except:
raise Exception(f"'{tag}' has value '{value}', which is not a positive number.")
def parse_task (task):
# Given a dictionary, it parses a task.
......@@ -95,8 +99,9 @@ def parse_task (task):
period = parse_natural_number(task, TASK_PERIOD_TAG)
jitter = parse_natural_number(task, TASK_JITTER_TAG, 0)
burst = parse_natural_number(task, TASK_BURST_TAG, 1)
bcet = parse_natural_number(task, TASK_BCET_TAG, 1)
check_for_allowed_tags(task, allowed_tags_at_task_level)
t = Task(id = id, wcet = wcet, priority=priority, period=period, jitter=jitter, burst=burst)
t = Task(id = id, wcet = wcet, bcet=bcet, priority=priority, period=period, jitter=jitter, burst=burst)
return t
\ No newline at end of file
......@@ -8,10 +8,8 @@ class ProblemInstance:
def __str__ (self):
res = "\n------- Problem instance -------\n"
res += f"Tasks:\n"
for t in self.task_set:
res += f"{str(t)}\n"
res += "\n"
return res
__repr__ = __str__
......
......@@ -2,17 +2,20 @@
This module contains the specification of task and a task set.
"""
class Task:
def __init__(self, id, wcet, priority, period, jitter, burst):
def __init__(self, id, wcet, bcet, priority, period, jitter, burst):
self.id = id
self.wcet = wcet
self.bcet = bcet
self.priority = priority
self.period = period
self.jitter = jitter
self.burst = burst
assert bcet <= wcet
def __str__(self):
task = f"(T{self.id}: wcet={self.wcet}, priority={self.priority},"
task += f"period={self.period}, jitter={self.jitter}, burst={self.burst})"
task = f"T{self.id}: exctime=({self.bcet}->{self.wcet}) | priority={self.priority} | "
task += f"period={self.period} | jitter={self.jitter} | burst={self.burst}"
return task
__repr__ = __str__
......
import random as rnd
class TraceEvent:
def __init__(self, instant, etype, pid):
self.etype = etype
self.pid = pid
self.instant = instant
def __str__(self):
return (f"(t={self.instant}, {self.etype}, PID={self.pid})")
__repr__ = __str__
def generate_trace(problem_instance, horizon):
ts = problem_instance.task_set
t = ts[0]
assert len(ts) == 1, "Currently, only single-task task sets are supported"
assert t.burst == 1, "No jitter or bursts are supported"
assert t.wcet < t.period, "WCET must be less than period (otherwise, the trace will be of only one job)"
assert t.jitter + t.wcet < t.period, "Self-interference not supported"
trace = []
time = 0
while time < horizon:
arrival = time+rnd.randint(0,t.jitter)
trace += [TraceEvent(arrival, "Activation", t.id)]
trace += [TraceEvent(arrival+rnd.randint(t.bcet,t.wcet), "Deactivation", t.id)]
assert trace[-1].instant > trace[-2].instant
time += t.period
return trace
\ No newline at end of file
import os, argparse, sys
import os, argparse, sys, yaml
from types import TracebackType
import parser
from trace import TraceEvent
import trace as tgen
def run():
### Parsing and checking input
opts = parse_args()
input_path = opts.input
output_path = opts.output
horizon = opts.until
check_condition(os.path.exists(input_path), "Input file not found")
check_condition(os.path.exists(input_path)
and os.path.isfile(input_path),
f"File not found: {input_path}")
check_condition(output_path is not None, "Please specify an output file.")
check_condition(horizon is not None, "Please specify an horizon ('-u') for the trace.")
check_condition(horizon > 0, "The horizon ('-u') should be positive.")
### Generating trace
problem_instance = parser.parse_file(input_path)
assert problem_instance is not None
print(input_path)
print(problem_instance)
print(output_path)
print(f"*** Writing file... {output_path}\n")
trace = tgen.generate_trace(problem_instance, horizon)
print(f"{trace[:3]} ... ({len(trace)} total events)\n")
save_file(output_path,trace)
def parse_args():
parser = argparse.ArgumentParser(description="The Trace Generation Tool")
......@@ -29,6 +36,9 @@ def parse_args():
parser.add_argument('-o', '--output', default=None, action='store',
help='Path of the file in which the trace will be generated.')
parser.add_argument('-u', '--until', default=None, action='store', type=int,
help='The task set will be traced from 0 to u.')
return parser.parse_args()
def check_condition(condition, error_message):
......@@ -36,12 +46,25 @@ def check_condition(condition, error_message):
print(error_message)
sys.exit(1)
def save_file(path, text):
def init_yaml():
def yaml_equivalent_of_default(dumper, data):
dict_representation = data.__dict__
node = dumper.represent_dict(dict_representation)
return node
yaml.add_representer(TraceEvent, yaml_equivalent_of_default)
def save_file(path, trace):
folder = os.path.dirname(path)
if folder != '' and not os.path.exists(folder):
os.makedirs(folder)
try:
with open(path, "w") as f:
f.write(text)
yaml.dump(trace, f, explicit_start=True, explicit_end=True, sort_keys=False)
except Exception as e:
print("Error while saving certificate to '{path}'")
print("Error while saving trace to '{path}'")
print(e)
init_yaml()
run()
\ No newline at end of file
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment