(Jun-24-2019, 04:47 PM)ThomasL Wrote: and task is an instance of that class where the method deadline is defined?
what construct is self._task_info?
why is there a self._task_info dot deadline?
1. Yes.
2 & 3. Here is the file where I tried to add the setter. It's at line 184.
# coding=utf-8
from collections import deque
from SimPy.Simulation import Process, Monitor, hold, passivate
from simso.core.Job import Job
from simso.core.Timer import Timer
from simso.core.CSDP import CSDP
import os
import os.path
class TaskInfo(object):
"""
TaskInfo is mainly a container class grouping the data that characterize
a Task. A list of TaskInfo objects are passed to the Model so that
:class:`Task` instances can be created.
"""
def __init__(self, name, identifier, task_type, abort_on_miss, period,
activation_date, n_instr, mix, stack_file, wcet, acet,
et_stddev, deadline, base_cpi, followed_by,
list_activation_dates, preemption_cost, data, my_parameter):
"""
:type name: str
:type identifier: int
:type task_type: str
:type abort_on_miss: bool
:type period: float
:type activation_date: float
:type n_instr: int
:type mix: float
:type stack_file: str
:type wcet: float
:type acet: float
:type et_stddev: float
:type deadline: float
:type base_cpi: float
:type followed_by: int
:type list_activation_dates: list
:type preemption_cost: int
:type data: dict
:type my_parameter: float
"""
self.name = name
self.identifier = identifier
self.task_type = task_type
self.period = period
self.activation_date = activation_date
self.n_instr = n_instr
self.mix = mix
self.wcet = wcet
self.acet = acet
self.et_stddev = et_stddev
self.base_cpi = base_cpi
self._stack = None
self._csdp = None
self._stack_file = ''
self.set_stack_file(*stack_file)
self.deadline = deadline
self.followed_by = followed_by
self.abort_on_miss = abort_on_miss
self.list_activation_dates = list_activation_dates
self.data = data
self.preemption_cost = preemption_cost
self.my_parameter = my_parameter
@property
def csdp(self):
"""
Accumulated Stack Distance Profile. Used by the cache models instead of
the Stack Distance Profile for optimization matters.
"""
return self._csdp
@property
def stack_file(self):
"""
Stack distance profile input file.
"""
return self._stack_file
def set_stack_file(self, stack_file, cur_dir):
"""
Set the stack distance profile.
"""
if stack_file:
try:
self._stack = TaskInfo._parse_stack(stack_file)
self._csdp = CSDP(self._stack)
self._stack_file = os.path.relpath(stack_file, cur_dir)
except Exception as e:
print("set_stack_file failed:", e)
@staticmethod
def _parse_stack(stack_file):
stack = {}
if stack_file and os.path.isfile(stack_file):
for line in open(stack_file):
dist, value = line.split()
stack[int(dist)] = float(value)
else:
stack = None
return stack
class GenericTask(Process):
"""
Abstract class for Tasks. :class:`ATask` and :class:`PTask` inherits from
this class.
These classes simulate the behavior of the simulated task. It controls the
release of the jobs and is able to abort the jobs that exceed their
deadline.
The majority of the task_info attributes are available through this class
too. A set of metrics such as the number of preemptions and migrations are
available for analysis.
"""
fields = []
def __init__(self, sim, task_info):
"""
Args:
- `sim`: :class:`Model <simso.core.Model>` instance.
- `task_info`: A :class:`TaskInfo` representing the Task.
:type sim: Model
:type task_info: TaskInfo
"""
Process.__init__(self, name=task_info.name, sim=sim)
self.name = task_info.name
self._task_info = task_info
self._monitor = Monitor(name="Monitor" + self.name + "_states",
sim=sim)
self._activations_fifo = deque([])
self._sim = sim
self.cpu = None
self._etm = sim.etm
self._job_count = 0
self._last_cpu = None
self._cpi_alone = {}
self._jobs = []
self.job = None
def __lt__(self, other):
return self.identifier < other.identifier
def is_active(self):
return self.job is not None and self.job.is_active()
def set_cpi_alone(self, proc, cpi):
self._cpi_alone[proc] = cpi
def get_cpi_alone(self, proc=None):
if proc is None:
proc = self.cpu
return self._cpi_alone[proc]
@property
def base_cpi(self):
return self._task_info.base_cpi
@property
def data(self):
"""
Extra data to characterize the task. Only used by the scheduler.
"""
return self._task_info.data
@property
def deadline(self):
"""
Deadline in milliseconds.
"""
return self._task_info.deadline
#Added
@deadline.setter
def deadline(self, value):
self._task_info.deadline = value
@property
def n_instr(self):
return self._task_info.n_instr
@property
def mix(self):
return self._task_info.mix
@property
def csdp(self):
return self._task_info.csdp
@property
def preemption_cost(self):
return self._task_info.preemption_cost
@property
def footprint(self):
return int(self._task_info.n_instr * self._task_info.mix *
(1 - self._task_info.csdp.get(-1)))
@property
def wcet(self):
"""Worst-Case Execution Time in milliseconds."""
return self._task_info.wcet
#Added
@wcet.setter
def set_wcet(self, value):
'setting'
self._task_info.wcet = value
@property
def acet(self):
return self._task_info.acet
@property
def my_parameter(self):
return self._task_info.my_parameter
@property
def et_stddev(self):
return self._task_info.et_stddev
@property
def period(self):
"""
Period of the task.
"""
return self._task_info.period
#Added
@period.setter
def period(self,value):
'setting'
self._task_info.period = value
@property
def identifier(self):
"""
Identifier of the task.
"""
return self._task_info.identifier
@property
def monitor(self):
"""
The monitor for this Task. Similar to a log mechanism (see Monitor in
SimPy doc).
"""
return self._monitor
@property
def followed_by(self):
"""
Task that is activated by the end of a job from this task.
"""
if self._task_info.followed_by is not None:
followed = [x for x in self._sim.task_list
if (x.identifier == self._task_info.followed_by)]
if followed:
return followed[0]
return None
@property
def jobs(self):
"""
List of the jobs.
"""
return self._jobs
def end_job(self, job):
self._last_cpu = self.cpu
if self.followed_by:
self.followed_by.create_job(job)
if len(self._activations_fifo) > 0:
self._activations_fifo.popleft()
if len(self._activations_fifo) > 0:
self.job = self._activations_fifo[0]
self.sim.activate(self.job, self.job.activate_job())
def _job_killer(self, job):
if job.end_date is None and job.computation_time < job.wcet:
if self._task_info.abort_on_miss:
self.cancel(job)
job.abort()
def create_job(self, pred=None):
"""
Create a new job from this task. This should probably not be used
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)
if len(self._activations_fifo) == 0:
self.job = job
self.sim.activate(job, job.activate_job())
self._activations_fifo.append(job)
self._jobs.append(job)
timer_deadline = Timer(self.sim, GenericTask._job_killer,
(self, job), self.deadline)
timer_deadline.start()
def _init(self):
if self.cpu is None:
self.cpu = self._sim.processors[0]
class ATask(GenericTask):
"""
Non-periodic Task process. Inherits from :class:`GenericTask`. The job is
created by another task.
"""
fields = ['deadline', 'wcet', 'my_parameter']
def execute(self):
self._init()
yield passivate, self
class PTask(GenericTask):
"""
Periodic Task process. Inherits from :class:`GenericTask`. The jobs are
created periodically.
"""
fields = ['activation_date', 'period', 'deadline', 'wcet', 'my_parameter']
def execute(self):
self._init()
# wait the activation date.
yield hold, self, int(self._task_info.activation_date *
self._sim.cycles_per_ms)
while True:
#print self.sim.now(), "activate", self.name
self.create_job()
yield hold, self, int(self.period * self._sim.cycles_per_ms)
class SporadicTask(GenericTask):
"""
Sporadic Task process. Inherits from :class:`GenericTask`. The jobs are
created using a list of activation dates.
"""
fields = ['list_activation_dates', 'deadline', 'wcet', 'my_parameter']
def execute(self):
self._init()
for ndate in self.list_activation_dates:
yield hold, self, int(ndate * self._sim.cycles_per_ms) \
- self._sim.now()
self.create_job()
@property
def list_activation_dates(self):
return self._task_info.list_activation_dates
task_types = {
"Periodic": PTask,
"APeriodic": ATask,
"Sporadic": SporadicTask
}
task_types_names = ["Periodic", "APeriodic", "Sporadic"]
def Task(sim, task_info):
"""
Task factory. Return and instantiate the correct class according to the
task_info.
"""
return task_types[task_info.task_type](sim, task_info)
(Jun-24-2019, 05:40 PM)nilamo Wrote: https://github.com/MaximeCheramy/simso/b...sk.py#L170 Wrote: @property
def deadline(self):
"""
Deadline in milliseconds.
"""
return self._task_info.deadline
Are you modifying a library or something? Can you share your whole class, and how you're trying to use it?
Yes. I tried to modify a library. At line 184 I added the setter.
And in another file, on an instance of the class PTask, which I called "task", I tried to set its deadline.
# coding=utf-8
from collections import deque
from SimPy.Simulation import Process, Monitor, hold, passivate
from simso.core.Job import Job
from simso.core.Timer import Timer
from simso.core.CSDP import CSDP
import os
import os.path
class TaskInfo(object):
"""
TaskInfo is mainly a container class grouping the data that characterize
a Task. A list of TaskInfo objects are passed to the Model so that
:class:`Task` instances can be created.
"""
def __init__(self, name, identifier, task_type, abort_on_miss, period,
activation_date, n_instr, mix, stack_file, wcet, acet,
et_stddev, deadline, base_cpi, followed_by,
list_activation_dates, preemption_cost, data, my_parameter):
"""
:type name: str
:type identifier: int
:type task_type: str
:type abort_on_miss: bool
:type period: float
:type activation_date: float
:type n_instr: int
:type mix: float
:type stack_file: str
:type wcet: float
:type acet: float
:type et_stddev: float
:type deadline: float
:type base_cpi: float
:type followed_by: int
:type list_activation_dates: list
:type preemption_cost: int
:type data: dict
:type my_parameter: float
"""
self.name = name
self.identifier = identifier
self.task_type = task_type
self.period = period
self.activation_date = activation_date
self.n_instr = n_instr
self.mix = mix
self.wcet = wcet
self.acet = acet
self.et_stddev = et_stddev
self.base_cpi = base_cpi
self._stack = None
self._csdp = None
self._stack_file = ''
self.set_stack_file(*stack_file)
self.deadline = deadline
self.followed_by = followed_by
self.abort_on_miss = abort_on_miss
self.list_activation_dates = list_activation_dates
self.data = data
self.preemption_cost = preemption_cost
self.my_parameter = my_parameter
@property
def csdp(self):
"""
Accumulated Stack Distance Profile. Used by the cache models instead of
the Stack Distance Profile for optimization matters.
"""
return self._csdp
@property
def stack_file(self):
"""
Stack distance profile input file.
"""
return self._stack_file
def set_stack_file(self, stack_file, cur_dir):
"""
Set the stack distance profile.
"""
if stack_file:
try:
self._stack = TaskInfo._parse_stack(stack_file)
self._csdp = CSDP(self._stack)
self._stack_file = os.path.relpath(stack_file, cur_dir)
except Exception as e:
print("set_stack_file failed:", e)
@staticmethod
def _parse_stack(stack_file):
stack = {}
if stack_file and os.path.isfile(stack_file):
for line in open(stack_file):
dist, value = line.split()
stack[int(dist)] = float(value)
else:
stack = None
return stack
class GenericTask(Process):
"""
Abstract class for Tasks. :class:`ATask` and :class:`PTask` inherits from
this class.
These classes simulate the behavior of the simulated task. It controls the
release of the jobs and is able to abort the jobs that exceed their
deadline.
The majority of the task_info attributes are available through this class
too. A set of metrics such as the number of preemptions and migrations are
available for analysis.
"""
fields = []
def __init__(self, sim, task_info):
"""
Args:
- `sim`: :class:`Model <simso.core.Model>` instance.
- `task_info`: A :class:`TaskInfo` representing the Task.
:type sim: Model
:type task_info: TaskInfo
"""
Process.__init__(self, name=task_info.name, sim=sim)
self.name = task_info.name
self._task_info = task_info
self._monitor = Monitor(name="Monitor" + self.name + "_states",
sim=sim)
self._activations_fifo = deque([])
self._sim = sim
self.cpu = None
self._etm = sim.etm
self._job_count = 0
self._last_cpu = None
self._cpi_alone = {}
self._jobs = []
self.job = None
def __lt__(self, other):
return self.identifier < other.identifier
def is_active(self):
return self.job is not None and self.job.is_active()
def set_cpi_alone(self, proc, cpi):
self._cpi_alone[proc] = cpi
def get_cpi_alone(self, proc=None):
if proc is None:
proc = self.cpu
return self._cpi_alone[proc]
@property
def base_cpi(self):
return self._task_info.base_cpi
@property
def data(self):
"""
Extra data to characterize the task. Only used by the scheduler.
"""
return self._task_info.data
@property
def deadline(self):
"""
Deadline in milliseconds.
"""
return self._task_info.deadline
#Added
@deadline.setter
def deadline(self, value):
self._task_info.deadline = value
@property
def n_instr(self):
return self._task_info.n_instr
@property
def mix(self):
return self._task_info.mix
@property
def csdp(self):
return self._task_info.csdp
@property
def preemption_cost(self):
return self._task_info.preemption_cost
@property
def footprint(self):
return int(self._task_info.n_instr * self._task_info.mix *
(1 - self._task_info.csdp.get(-1)))
@property
def wcet(self):
"""Worst-Case Execution Time in milliseconds."""
return self._task_info.wcet
#Added
@wcet.setter
def set_wcet(self, value):
'setting'
self._task_info.wcet = value
@property
def acet(self):
return self._task_info.acet
@property
def my_parameter(self):
return self._task_info.my_parameter
@property
def et_stddev(self):
return self._task_info.et_stddev
@property
def period(self):
"""
Period of the task.
"""
return self._task_info.period
#Added
@period.setter
def period(self,value):
'setting'
self._task_info.period = value
@property
def identifier(self):
"""
Identifier of the task.
"""
return self._task_info.identifier
@property
def monitor(self):
"""
The monitor for this Task. Similar to a log mechanism (see Monitor in
SimPy doc).
"""
return self._monitor
@property
def followed_by(self):
"""
Task that is activated by the end of a job from this task.
"""
if self._task_info.followed_by is not None:
followed = [x for x in self._sim.task_list
if (x.identifier == self._task_info.followed_by)]
if followed:
return followed[0]
return None
@property
def jobs(self):
"""
List of the jobs.
"""
return self._jobs
def end_job(self, job):
self._last_cpu = self.cpu
if self.followed_by:
self.followed_by.create_job(job)
if len(self._activations_fifo) > 0:
self._activations_fifo.popleft()
if len(self._activations_fifo) > 0:
self.job = self._activations_fifo[0]
self.sim.activate(self.job, self.job.activate_job())
def _job_killer(self, job):
if job.end_date is None and job.computation_time < job.wcet:
if self._task_info.abort_on_miss:
self.cancel(job)
job.abort()
def create_job(self, pred=None):
"""
Create a new job from this task. This should probably not be used
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)
if len(self._activations_fifo) == 0:
self.job = job
self.sim.activate(job, job.activate_job())
self._activations_fifo.append(job)
self._jobs.append(job)
timer_deadline = Timer(self.sim, GenericTask._job_killer,
(self, job), self.deadline)
timer_deadline.start()
def _init(self):
if self.cpu is None:
self.cpu = self._sim.processors[0]
class ATask(GenericTask):
"""
Non-periodic Task process. Inherits from :class:`GenericTask`. The job is
created by another task.
"""
fields = ['deadline', 'wcet', 'my_parameter']
def execute(self):
self._init()
yield passivate, self
class PTask(GenericTask):
"""
Periodic Task process. Inherits from :class:`GenericTask`. The jobs are
created periodically.
"""
fields = ['activation_date', 'period', 'deadline', 'wcet', 'my_parameter']
def execute(self):
self._init()
# wait the activation date.
yield hold, self, int(self._task_info.activation_date *
self._sim.cycles_per_ms)
while True:
#print self.sim.now(), "activate", self.name
self.create_job()
yield hold, self, int(self.period * self._sim.cycles_per_ms)
class SporadicTask(GenericTask):
"""
Sporadic Task process. Inherits from :class:`GenericTask`. The jobs are
created using a list of activation dates.
"""
fields = ['list_activation_dates', 'deadline', 'wcet', 'my_parameter']
def execute(self):
self._init()
for ndate in self.list_activation_dates:
yield hold, self, int(ndate * self._sim.cycles_per_ms) \
- self._sim.now()
self.create_job()
@property
def list_activation_dates(self):
return self._task_info.list_activation_dates
task_types = {
"Periodic": PTask,
"APeriodic": ATask,
"Sporadic": SporadicTask
}
task_types_names = ["Periodic", "APeriodic", "Sporadic"]
def Task(sim, task_info):
"""
Task factory. Return and instantiate the correct class according to the
task_info.
"""
return task_types[task_info.task_type](sim, task_info)