Commit d7ec2fb6 by Michael Schmid

intermediate commit, not working

parent b7a117cf
{
// Use IntelliSense to learn about possible attributes.
// Hover to view descriptions of existing attributes.
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"name": "simso",
"type": "python",
"request": "launch",
"program": "${workspaceFolder}/script.py",
"console": "internalConsole",
"justMyCode": false
}
]
}
\ No newline at end of file
{
"python.pythonPath": "/usr/bin/python",
"editor.tokenColorCustomizations": {
"textMateRules": [
{
"scope": "googletest.failed",
"settings": {
"foreground": "#f00"
}
},
{
"scope": "googletest.passed",
"settings": {
"foreground": "#0f0"
}
},
{
"scope": "googletest.run",
"settings": {
"foreground": "#0f0"
}
}
]
},
"python.linting.pylintEnabled": true,
"python.linting.enabled": true
}
\ No newline at end of file
# coding=utf-8
from SimPy.Simulation import Process, hold, passivate
# from SimPy.Simulation import Process, hold, passivate
from simpy import Process, Interrupt
from simso.core.JobEvent import JobEvent
from math import ceil
......@@ -27,7 +28,7 @@ class Job(Process):
:type etm: AbstractExecutionTimeModel
:type sim: Model
"""
Process.__init__(self, name=name, sim=sim)
Process.__init__(self, env=sim, generator=self.activate_job()) # TODO: what to pass as generator?
self._task = task
self._pred = pred
self.instr_count = 0 # Updated by the cache model.
......@@ -37,14 +38,15 @@ class Job(Process):
self._start_date = None
self._end_date = None
self._is_preempted = False
self._activation_date = self.sim.now_ms()
self._absolute_deadline = self.sim.now_ms() + task.deadline
self._aborted = False
self._sim = sim
self._activation_date = self._sim.now_ms()
self._absolute_deadline = self._sim.now_ms() + task.deadline
self._monitor = monitor
self._etm = etm
self._was_running_on = task.cpu
self._wcet = task.wcet
self.name = name
self._on_activate()
......@@ -62,7 +64,7 @@ class Job(Process):
self._etm.on_activate(self)
def _on_execute(self):
self._last_exec = self.sim.now()
self._last_exec = self._sim.now()
self._etm.on_execute(self)
if self._is_preempted:
......@@ -76,7 +78,7 @@ class Job(Process):
def _on_stop_exec(self):
if self._last_exec is not None:
self._computation_time += self.sim.now() - self._last_exec
self._computation_time += self._sim.now() - self._last_exec
self._last_exec = None
def _on_preempted(self):
......@@ -87,13 +89,13 @@ class Job(Process):
self._monitor.observe(JobEvent(self, JobEvent.PREEMPTED))
self._sim.logger.log(self.name + " Preempted! ret: " +
str(self.interruptLeft), kernel=True)
str("Don't know what to pass else?"), kernel=True) # TODO: what to pass as interrupted?
def _on_terminated(self):
self._on_stop_exec()
self._etm.on_terminated(self)
self._end_date = self.sim.now()
self._end_date = self._sim.now()
self._monitor.observe(JobEvent(self, JobEvent.TERMINATED))
self._task.end_job(self)
self._task.cpu.terminate(self)
......@@ -102,7 +104,7 @@ class Job(Process):
def _on_abort(self):
self._on_stop_exec()
self._etm.on_abort(self)
self._end_date = self.sim.now()
self._end_date = self._sim.now()
self._aborted = True
self._monitor.observe(JobEvent(self, JobEvent.ABORTED))
self._task.end_job(self)
......@@ -181,7 +183,7 @@ class Job(Process):
Dynamic laxity of the job in ms.
"""
return (self.absolute_deadline - self.ret
) * self.sim.cycles_per_ms - self.sim.now()
) * self._sim.cycles_per_ms - self._sim.now()
@property
def computation_time(self):
......@@ -199,7 +201,7 @@ class Job(Process):
return int(self._computation_time)
else:
return (int(self._computation_time) +
self.sim.now() - self._last_exec)
self._sim.now() - self._last_exec)
@property
def actual_computation_time(self):
......@@ -288,39 +290,35 @@ class Job(Process):
return self._pred
def activate_job(self):
self._start_date = self.sim.now()
self._start_date = self._sim.now()
# Notify the OS.
self._task.cpu.activate(self)
# While the job's execution is not finished.
while self._end_date is None:
# Wait an execute order.
yield passivate, self
# Execute the job.
if not self.interrupted():
try:
yield self._sim.event()
except Interrupt:
pass
else:
self._on_execute()
# ret is a duration lower than the remaining execution time.
ret = self._etm.get_ret(self)
while ret > 0:
yield hold, self, int(ceil(ret))
if not self.interrupted():
# If executed without interruption for ret cycles.
ret = self._etm.get_ret(self)
else:
try:
yield self._sim.timeout(int(ceil(ret)))
except Interrupt:
self._on_preempted()
self.interruptReset()
break
else:
ret = self._etm.get_ret(self)
if ret <= 0:
# End of job.
self._on_terminated()
else:
self.interruptReset()
class SequentialJob(Job):
pass
......
# coding=utf-8
from SimPy.Simulation import Monitor
from simso.core.Monitor import Monitor
class Logger(object):
"""
......@@ -13,7 +12,7 @@ class Logger(object):
- `sim`: The :class:`model <simso.core.Model.Model>` object.
"""
self.sim = sim
self._logs = Monitor(name="Logs", sim=sim)
self._logs = Monitor(name="Logs", env=sim)
def log(self, msg, kernel=False):
"""
......
# coding=utf-8
from SimPy.Simulation import Simulation
# from simpy.Simulation import Simulation
from simpy import Environment
from simso.core.Processor import Processor
from simso.core.Task import Task
from simso.core.Timer import Timer
from simso.core.etm import execution_time_models
from simso.core.Logger import Logger
from simso.core.results import Results
import SimPy as SPPc
class Model(Simulation):
class Model(Environment):
"""
Main class for the simulation. It instantiate the various components
required by the simulation and run it.
......@@ -27,8 +27,7 @@ class Model(Simulation):
Methods:
"""
print(SPPc.__version__)
Simulation.__init__(self)
Environment.__init__(self)
self._logger = Logger(self)
task_info_list = configuration.task_info_list
proc_info_list = configuration.proc_info_list
......@@ -76,7 +75,7 @@ class Model(Simulation):
self.results = None
def now_ms(self):
return float(self.now()) / self._cycles_per_ms
return float(self.now) / self._cycles_per_ms
@property
def logs(self):
......@@ -127,25 +126,25 @@ class Model(Simulation):
def _on_tick(self):
if self._callback:
self._callback(self.now())
self._callback(self.now)
def run_model(self):
""" Execute the simulation."""
self.initialize()
# self.initialize()
self.scheduler.init()
self.progress.start()
for cpu in self._processors:
self.activate(cpu, cpu.run())
self.process(cpu.run())
for task in self._task_list:
self.activate(task, task.execute())
self.process(task.execute())
try:
self.simulate(until=self._duration)
self.run(until=self._duration)
finally:
self._etm.update()
if self.now() > 0:
if self.now > 0:
self.results = Results(self)
self.results.end()
class Monitor(list):
""" Monitored variables
A Class for monitored variables, that is, variables that allow one
to gather simple statistics. A Monitor is a subclass of list and
list operations can be performed on it. An object is established
using m = Monitor(name = '..'). It can be given a
unique name for use in debugging and in tracing and ylab and tlab
strings for labelling graphs.
"""
def __init__(self, env , name = 'a_Monitor', ylab = 'y', tlab = 't'):
list.__init__(self)
self.env = env
self.startTime = 0.0
self.name = name
self.ylab = ylab
self.tlab = tlab
def observe(self, y,t = None):
"""record y and t"""
if t is None: t = self.env.now()
self.append([t, y])
def tally(self, y):
""" deprecated: tally for backward compatibility"""
self.observe(y, 0)
def accum(self, y,t = None):
""" deprecated: accum for backward compatibility"""
self.observe(y, t)
def reset(self, t = None):
"""reset the sums and counts for the monitored variable """
self[:] = []
if t is None: t = self.env.now()
self.startTime = t
def tseries(self):
""" the series of measured times"""
return list(zip(*self))[0]
def yseries(self):
""" the series of measured values"""
return list(zip(*self))[1]
def count(self):
""" deprecated: the number of observations made """
return self.__len__()
def total(self):
""" the sum of the y"""
if self.__len__() == 0: return 0
else:
sum = 0.0
for i in range(self.__len__()):
sum += self[i][1]
return sum # replace by sum() later
def mean(self):
""" the simple average of the monitored variable"""
try:
return 1.0 * self.total() / self.__len__()
except ZeroDivisionError:
raise ZeroDivisionError('SimPy: No observations for mean')
def var(self):
""" the sample variance of the monitored variable """
n = len(self)
tot = self.total()
ssq = 0.0
for i in range(self.__len__()):
ssq += self[i][1] ** 2 # replace by sum() eventually
try:
return (ssq - float(tot * tot) / n) / n
except:
raise ZeroDivisionError(
'SimPy: No observations for sample variance')
def timeAverage(self, t = None):
"""
The time-weighted average of the monitored variable.
If t is used it is assumed to be the current time,
otherwise t = self.sim.now()
"""
N = self.__len__()
if N == 0:
return None
if t is None: t = self.env.now()
sum = 0.0
tlast = self[0][0]
ylast = self[0][1]
for i in range(N):
ti, yi = self[i]
sum += ylast * (ti - tlast)
tlast = ti
ylast = yi
sum += ylast * (t - tlast)
T = t - self[0][0]
if T == 0:
return None
return sum / float(T)
def timeVariance(self, t = None):
""" the time - weighted Variance of the monitored variable.
If t is used it is assumed to be the current time,
otherwise t = self.sim.now()
"""
N = self.__len__()
if N == 0:
return None
if t is None: t = self.env.now()
sm = 0.0
ssq = 0.0
tlast = self[0][0]
# print 'DEBUG: 1 twVar ', t, tlast
ylast = self[0][1]
for i in range(N):
ti, yi = self[i]
sm += ylast * (ti - tlast)
ssq += ylast * ylast * (ti - tlast)
tlast = ti
ylast = yi
sm += ylast * (t - tlast)
ssq += ylast * ylast * (t - tlast)
T = t - self[0][0]
if T == 0:
return None
mn = sm / float(T)
return ssq / float(T) - mn * mn
# coding=utf-8
from collections import deque
from SimPy.Simulation import Process, Monitor, hold, waituntil
from simpy import Process
# from SimPy.Simulation import Process, Monitor, hold, waituntil
from simso.core.ProcEvent import ProcRunEvent, ProcIdleEvent, \
ProcOverheadEvent, ProcCxtSaveEvent, ProcCxtLoadEvent
from simso.core.Monitor import Monitor
RESCHED = 1
ACTIVATE = 2
......@@ -53,7 +54,7 @@ class Processor(Process):
cls._identifier = 0
def __init__(self, model, proc_info):
Process.__init__(self, name=proc_info.name, sim=model)
Process.__init__(self, env=model, generator=self.run()) # TODO: what to pass as generator?
self._model = model
self._internal_id = Processor._identifier
Processor._identifier += 1
......@@ -62,15 +63,14 @@ class Processor(Process):
self.was_running = None
self._evts = deque([])
self.sched = model.scheduler
self.monitor = Monitor(name="Monitor" + proc_info.name, sim=model)
self.monitor = Monitor(env=model, name="Monitor" + proc_info.name)
self._caches = []
self._penalty = proc_info.penalty
self._cs_overhead = proc_info.cs_overhead
self._cl_overhead = proc_info.cl_overhead
self._migration_overhead = proc_info.migration_overhead
self.set_caches(proc_info.caches)
self.timer_monitor = Monitor(name="Monitor Timer" + proc_info.name,
sim=model)
self.timer_monitor = Monitor(env=model, name="Monitor Timer" + proc_info.name)
self._speed = proc_info.speed
def resched(self):
......@@ -143,28 +143,32 @@ class Processor(Process):
"""
return self._running
def waituntil(self, cond_func, delay=1):
while not cond_func():
yield self.env.timeout(delay)
def run(self):
while True:
if not self._evts:
job = self._running
if job:
yield waituntil, self, lambda: job.context_ok
yield self.waituntil(lambda: job.context_ok)
self.monitor.observe(ProcCxtLoadEvent())
yield hold, self, self.cl_overhead # overhead load context
yield self._model.timeout(self.cl_overhead) # overhead load context
self.monitor.observe(ProcCxtLoadEvent(terminated=True))
job.interruptReset()
self.sim.reactivate(job)
self.env.reactivate(job)
self.monitor.observe(ProcRunEvent(job))
job.context_ok = False
else:
self.monitor.observe(ProcIdleEvent())
# Wait event.
yield waituntil, self, lambda: self._evts
yield self.waituntil(lambda: self._evts)
if job:
self.interrupt(job)
self.monitor.observe(ProcCxtSaveEvent())
yield hold, self, self.cs_overhead # overhead save context
yield self._model.timeout(self.cs_overhead) # overhead save context
self.monitor.observe(ProcCxtSaveEvent(terminated=True))
job.context_ok = True
......@@ -178,28 +182,28 @@ class Processor(Process):
self.sched.on_activate(evt[1])
self.monitor.observe(ProcOverheadEvent("JobActivation"))
self.sched.monitor_begin_activate(self)
yield hold, self, self.sched.overhead_activate
yield self._model.timeout(self.sched.overhead_activate)
self.sched.monitor_end_activate(self)
elif evt[0] == TERMINATE:
self.sched.on_terminated(evt[1])
self.monitor.observe(ProcOverheadEvent("JobTermination"))
self.sched.monitor_begin_terminate(self)
yield hold, self, self.sched.overhead_terminate
yield self._model.timeout(self.sched.overhead_terminate)
self.sched.monitor_end_terminate(self)
elif evt[0] == TIMER:
self.timer_monitor.observe(None)
if evt[1].overhead > 0:
print(self.sim.now(), "hold", evt[1].overhead)
yield hold, self, evt[1].overhead
print(self.env.now(), "hold", evt[1].overhead)
yield self._model.timeout(evt[1].overhead)
evt[1].call_handler()
elif evt[0] == SPEED:
self._speed = evt[1]
elif evt[0] == RESCHED:
self.monitor.observe(ProcOverheadEvent("Scheduling"))
self.sched.monitor_begin_schedule(self)
yield waituntil, self, self.sched.get_lock
yield self.waituntil(self.sched.get_lock)
decisions = self.sched.schedule(self)
yield hold, self, self.sched.overhead # overhead scheduling
yield self._model.timeout(self.sched.overhead) # overhead scheduling
if type(decisions) is not list:
decisions = [decisions]
decisions = [d for d in decisions if d is not None]
......
......@@ -6,11 +6,12 @@ import importlib
import pkgutil
import inspect
from simso.core.Monitor import Monitor
from simso.core.SchedulerEvent import SchedulerBeginScheduleEvent, \
SchedulerEndScheduleEvent, SchedulerBeginActivateEvent, \
SchedulerEndActivateEvent, SchedulerBeginTerminateEvent, \
SchedulerEndTerminateEvent
from SimPy.Simulation import Monitor
class SchedulerInfo(object):
......@@ -145,7 +146,7 @@ class Scheduler(object):
self.overhead_activate = scheduler_info.overhead_activate
self.overhead_terminate = scheduler_info.overhead_terminate
self.data = scheduler_info.data
self.monitor = Monitor(name="MonitorScheduler", sim=sim)
self.monitor = Monitor(name="MonitorScheduler", env=sim)
def init(self):
"""
......
# coding=utf-8
import simpy
from simpy import Process
from collections import deque
from SimPy.Simulation import Process, Monitor, hold, passivate
# from SimPy.Simulation import Process, Monitor, hold, passivate
from simso.core.Job import Job
from simso.core.Timer import Timer
from simso.core.Monitor import Monitor
from .CSDP import CSDP
import os
......@@ -129,11 +132,11 @@ class GenericTask(Process):
:type sim: Model
:type task_info: TaskInfo
"""
Process.__init__(self, name=task_info.name, sim=sim)
Process.__init__(self, env=sim, generator=self.execute())
self.name = task_info.name
self._task_info = task_info
self._monitor = Monitor(name="Monitor" + self.name + "_states",
sim=sim)
env=sim)
self._activations_fifo = deque([])
self._sim = sim
self.cpu = None
......@@ -144,6 +147,9 @@ class GenericTask(Process):
self._jobs = []
self.job = None
def execute(self):
pass
def __lt__(self, other):
return self.identifier < other.identifier
......@@ -260,12 +266,12 @@ class GenericTask(Process):
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())
self.env.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)
# self.cancel(job) TODO: How to cancel Job?
job.abort()
def create_job(self, pred=None):
......@@ -275,15 +281,15 @@ class GenericTask(Process):
"""
self._job_count += 1
job = Job(self, "{}_{}".format(self.name, self._job_count), pred,
monitor=self._monitor, etm=self._etm, sim=self.sim)
monitor=self._monitor, etm=self._etm, sim=self.env)
if len(self._activations_fifo) == 0:
self.job = job
self.sim.activate(job, job.activate_job())
self.env.process(job.activate_job())
self._activations_fifo.append(job)
self._jobs.append(job)
timer_deadline = Timer(self.sim, GenericTask._job_killer,
timer_deadline = Timer(self.env, GenericTask._job_killer,
(self, job), self.deadline)
timer_deadline.start()
......@@ -301,7 +307,7 @@ class ATask(GenericTask):
def execute(self):
self._init()
yield passivate, self
yield self.env.event()
class PTask(GenericTask):
......@@ -314,13 +320,13 @@ class PTask(GenericTask):
def execute(self):
self._init()
# wait the activation date.
yield hold, self, int(self._task_info.activation_date *
self._sim.cycles_per_ms)
yield self.env.timeout(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)
yield self.env.timeout(int(self.period * self._sim.cycles_per_ms))
class SporadicTask(GenericTask):
......@@ -334,8 +340,8 @@ class SporadicTask(GenericTask):
self._init()
for ndate in self.list_activation_dates:
yield hold, self, int(ndate * self._sim.cycles_per_ms) \
- self._sim.now()
yield self.env.timeout(int(ndate * self._sim.cycles_per_ms) \
- self._sim.now())
self.create_job()
@property
......@@ -354,8 +360,8 @@ class ProbabilisticTask(GenericTask):
self._init()
for ndate in self.list_activation_dates:
yield hold, self, int(ndate * self._sim.cycles_per_ms) \
- self._sim.now()
yield self.env.timeout(int(ndate * self._sim.cycles_per_ms) \
- self._sim.now())
self.create_job()
@property
......
# coding=utf-8
from SimPy.Simulation import Process, hold
# from SimPy.Simulation import Process, hold
from simpy import Environment, Process, Interrupt
# TODO: allow the user to specify an overhead.
class InstanceTimer(Process):
def __init__(self, timer):
Process.__init__(self, name="Timer", sim=timer.sim)
Process.__init__(self, env=timer.env, generator=self.run())
self.function = timer.function
self.args = timer.args
self.delay = timer.delay
......@@ -23,9 +24,13 @@ class InstanceTimer(Process):
def run(self):
self.running = True
while self.running:
yield hold, self, self.delay
if self.interrupted() or not self.running:
try:
yield self.env.timeout(self.delay)
except Interrupt:
break
else:
if not self.running:
break;
if self.cpu:
self.cpu.timer(self)
else:
......@@ -67,7 +72,7 @@ class Timer(object):
Methods:
"""
self.sim = sim
self.env = sim
self.function = function
self.args = args
if in_ms:
......@@ -89,7 +94,7 @@ class Timer(object):
Start the timer.
"""
self.instance = InstanceTimer(self)
self.sim.activate(self.instance, self.instance.run(), self.prior)
self.env.process(self.instance.run()) # TODO: , self.prior what's with this?
def stop(self):
"""
......
......@@ -9,3 +9,4 @@ from simso.core.Processor import Processor
from simso.core.Scheduler import Scheduler
from simso.core.Timer import Timer
from simso.core.results import Results
from simso.core.Monitor import Monitor
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or sign in to comment