Using SimSo in script mode¶
SimSo can be used as a library in order to automatize wide experimentations and have a maximum of flexibility on the analysis of the results. In this tutorial, a few examples are provided.
Table of Contents
Loading a configuration using a simulation file¶
A Configuration
can be initialized with a file passed to its constructor:
configuration = Configuration(argv[1])
The configuration could also be partial and completed by the script. Finally, the configuration can be checked for correctness using the check_all
method:
configuration.check_all()
This method will raise an exception if something is not correct.
Creating a configuration from scratch¶
It is also possible to create a new configuration from an empty configuration. This is done by instantiating a Configuration
object without argument. Then, its attributes can be changed:
configuration = Configuration()
configuration.duration = 100 * configuration.cycles_per_ms
It is also possible to add tasks:
configuration.add_task(name="T1", identifier=1, period=7,
activation_date=0, wcet=3, deadline=7)
And of course processors:
configuration.add_processor(name="CPU 1", identifier=1)
Finally, a scheduler is also required. For that, it’s possible to use a custom scheduler:
configuration.scheduler_info.filename = "examples/RM.py"
Or one of the schedulers embedded with SimSo:
configuration.scheduler_info.clas = "simso.schedulers.RM"
Creating the Model¶
A configuration
is an object grouping every characteristics of the system (tasks, processors, schedulers, etc). Such a configuration can be passed to the Model
constructor in order to create the simulation:
model = Model(configuration)
And the simulation can be run with the run_model
method:
model.run_model()
Some basic logs can be get through the logs
attribute:
for log in model.logs:
print(log)
First Example¶
The following script simulate a system loading from a simulation file or configured from scratch:
import sys
from simso.core import Model
from simso.configuration import Configuration
def main(argv):
if len(argv) == 2:
# Configuration load from a file.
configuration = Configuration(argv[1])
else:
# Manual configuration:
configuration = Configuration()
configuration.duration = 420 * configuration.cycles_per_ms
# Add tasks:
configuration.add_task(name="T1", identifier=1, period=7,
activation_date=0, wcet=3, deadline=7)
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,
activation_date=0, wcet=5, deadline=20)
# Add a processor:
configuration.add_processor(name="CPU 1", identifier=1)
# Add a scheduler:
#configuration.scheduler_info.filename = "examples/RM.py"
configuration.scheduler_info.clas = "simso.schedulers.RM"
# Check the config before trying to run it.
configuration.check_all()
# Init a model from the configuration.
model = Model(configuration)
# Execute the simulation.
model.run_model()
# Print logs.
for log in model.logs:
print(log)
main(sys.argv)
More details¶
It is possible to get more information from the tasks using Results
class. For example we could get the computation time of the jobs:
for task in model.results.tasks:
print(task.name + ":")
for job in task.jobs:
print("%s %.3f ms" % (job.name, job.computation_time))
Or the number of preemptions per task:
for task in model.results.tasks.values():
print("%s %s" % (task.name, task.preemption_count))
You can get all the metrics provided in the TaskR
and JobR
objects. Read the documentation of these classes to know exactly what is directly accessible.
It is also possible to get the monitor object from each processors. This is a very detail history of the system. For example, you can count the number of context switches, where a context switch is something that happen when the previous task running on the same processor is different:
cxt = 0
for processor in model.processors:
prev = None
for evt in processor.monitor:
if evt[1].event == ProcEvent.RUN:
if prev is not None and prev != evt[1].args.task:
cxt += 1
prev = evt[1].args.task
print("Number of context switches (without counting the OS): " + str(cxt))