Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add probabilistic WCET feature #19

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion misc/script.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import sys
from simso.core import Model
from simso.configuration import Configuration
import numpy as np


def main(argv):
Expand All @@ -21,7 +22,7 @@ def main(argv):

# Add tasks:
configuration.add_task(name="T1", identifier=1, period=7,
activation_date=0, wcet=3, deadline=7)
activation_date=0, wcet=np.array([[1,2,3],[.1,.2,.7]]), deadline=7) # add a task with a probabilistic WCET
configuration.add_task(name="T2", identifier=2, period=12,
activation_date=0, wcet=3, deadline=12)
configuration.add_task(name="T3", identifier=3, period=20,
Expand Down
29 changes: 17 additions & 12 deletions simso/configuration/Configuration.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import os
import re
from xml.dom import minidom
import numpy as np
from simso.core.Scheduler import SchedulerInfo
from simso.core import Scheduler
from simso.core.Task import TaskInfo
Expand Down Expand Up @@ -181,22 +182,33 @@ def check_tasks(self):
"name must begins with a letter and must not contains any "\
"special character."

# Activation date >= 0:
# Activation date >= 0:
assert task.activation_date >= 0, \
"Activation date must be positive."

# Period >= 0:
assert task.period >= 0, "Tasks' periods must be positives."

# Deadline >= 0:
# Deadline >= 0:
assert task.deadline >= 0, "Tasks' deadlines must be positives."

# N_instr >= 0:
assert task.n_instr >= 0, \
"A number of instructions must be positive."

# WCET >= 0:
assert task.wcet >= 0, "WCET must be positive."
# WCET >= 0:
if isinstance(task.wcet, np.ndarray):
assert np.min(task.wcet[0, :]) >= 0, "WCETs must be positive"
assert np.sum(task.wcet[1, :]) == 1, "probabilities sum must be 1"
else:
assert task.wcet >= 0, "WCET must be positive."
if self.etm == "cache":
# stack
assert task.stack_file, "A task needs a stack profile."

# stack ok
assert task.csdp, "Stack not found or empty."


# ACET >= 0:
assert task.acet >= 0, "ACET must be positive."
Expand All @@ -209,13 +221,6 @@ def check_tasks(self):
assert 0.0 <= task.mix <= 2.0, \
"A mix must be positive and less or equal than 2.0"

if self.etm == "cache":
# stack
assert task.stack_file, "A task needs a stack profile."

# stack ok
assert task.csdp, "Stack not found or empty."

def check_caches(self):
for index, cache in enumerate(self._caches_list):
# Id unique :
Expand All @@ -231,7 +236,7 @@ def check_caches(self):
# Taille positive :
assert cache.size >= 0, "A cache size must be positive."

# Access time >= 0:
# Access time >= 0:
assert cache.access_time >= 0, "An access time must be positive."

def get_hyperperiod(self):
Expand Down
9 changes: 6 additions & 3 deletions simso/core/Job.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ class Job(Process):
"""The Job class simulate the behavior of a real Job. This *should* only be
instantiated by a Task."""

def __init__(self, task, name, pred, monitor, etm, sim):
def __init__(self, task, name, pred, monitor, etm, sim, wcet=None):
"""
Args:
- `task`: The parent :class:`task <simso.core.Task.Task>`.
Expand Down Expand Up @@ -44,6 +44,7 @@ def __init__(self, task, name, pred, monitor, etm, sim):
self._monitor = monitor
self._etm = etm
self._was_running_on = task.cpu
self._wcet = wcet

self._on_activate()

Expand Down Expand Up @@ -243,7 +244,9 @@ def wcet(self):
Worst-Case Execution Time in milliseconds.
Equivalent to ``self.task.wcet``.
"""
return self._task.wcet
if (self._wcet is None):
return self._task.wcet
return self._wcet

@property
def activation_date(self):
Expand Down Expand Up @@ -291,7 +294,7 @@ def activate_job(self):
# Wait an execute order.
yield passivate, self

# Execute the job.
# Execute the job.
if not self.interrupted():
self._on_execute()
# ret is a duration lower than the remaining execution time.
Expand Down
12 changes: 10 additions & 2 deletions simso/core/Task.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,10 @@

from collections import deque
from SimPy.Simulation import Process, Monitor, hold, passivate
import numpy as np
from simso.core.Job import Job
from simso.core.Timer import Timer
from simso.utils.probabilistic_calc import random_int_from_distr
from .CSDP import CSDP

import os
Expand Down Expand Up @@ -272,9 +274,15 @@ def create_job(self, pred=None):
directly by a scheduler.
"""
self._job_count += 1
job = Job(self, "{}_{}".format(self.name, self._job_count), pred,
monitor=self._monitor, etm=self._etm, sim=self.sim)

# pick random wcet according to their probabilities
if isinstance(self.wcet, np.ndarray):
wcet_sample = random_int_from_distr(self.wcet, n_sample=1)[0]
else:
wcet_sample = None

job = Job(self, "{}_{}".format(self.name, self._job_count), pred,
monitor=self._monitor, etm=self._etm, sim=self.sim, wcet=wcet_sample)
if len(self._activations_fifo) == 0:
self.job = job
self.sim.activate(job, job.activate_job())
Expand Down
2 changes: 1 addition & 1 deletion simso/core/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,10 @@
The core module include all the classes needed for the simulation.
"""

from simso.core.Scheduler import Scheduler
from simso.core.JobEvent import JobEvent
from simso.core.ProcEvent import ProcEvent
from simso.core.Model import Model
from simso.core.Processor import Processor
from simso.core.Scheduler import Scheduler
from simso.core.Timer import Timer
from simso.core.results import Results
48 changes: 48 additions & 0 deletions simso/utils/probabilistic_calc.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Created on Tue Nov 27 17:23:01 2018

@author: sbenamor
"""

from random import random
import numpy as np


def random_int_from_distr(proba_dist, n_sample=1):
""" function that generate n random value according to a given
discrete probability distribution proba_dist

Args:
- proba_dist (numpy array 2*m): discrete probability distribution with m possible value.
- n_sample (int): number of generated samples.

Returns:
- list: list of n random generated values.

Example:
>>> randon_int_distr(np.array([[5],[1]]),1) #doctest: +ELLIPSIS +NORMALIZE_WHITESPACE
[5]
>>> randon_int_distr(np.array([[2,3,8],[.1, .2, .7]]),1)[0] in [2,3,8] #doctest: \
+ELLIPSIS +NORMALIZE_WHITESPACE
1
>>> np.all(np.isin(randon_int_distr(np.array([[2,3,8],[.1, .2, .7]]),5), [2,3,8])) \
#doctest: +ELLIPSIS +NORMALIZE_WHITESPACE
True
"""
samples = []

cdf = np.cumsum(proba_dist[1, :]) # Cumulative Distribution Function

for _ in range(n_sample):
proba = random() # generate a probability value uniformly between 0 and 1
rand_value_index = np.argmax(cdf > proba) # transform generated probability to a value from the distribution using cdf function
samples.append(int(proba_dist[0, rand_value_index]))

return samples


if __name__ == "__main__":
import doctest
doctest.testmod()