Made RT interrupt changes
This commit is contained in:
parent
770af49c87
commit
68a247654d
10 changed files with 47 additions and 20 deletions
6
build.sh
6
build.sh
|
|
@ -9,7 +9,7 @@ cp install_mpi4py.sh pypdevs/install_mpi4py.sh
|
||||||
cd doc/sphinx
|
cd doc/sphinx
|
||||||
rm -r _build/html
|
rm -r _build/html
|
||||||
make html
|
make html
|
||||||
./rewrite_documentation.sh
|
#./rewrite_documentation.sh
|
||||||
cd ../..
|
cd ../..
|
||||||
cp -R doc/sphinx/_build/html/ pypdevs/doc
|
cp -R doc/sphinx/_build/html/ pypdevs/doc
|
||||||
cp -R src/ pypdevs/
|
cp -R src/ pypdevs/
|
||||||
|
|
@ -18,7 +18,7 @@ rm test/output/*
|
||||||
cp -R test/ pypdevs/
|
cp -R test/ pypdevs/
|
||||||
cp LICENSE pypdevs/
|
cp LICENSE pypdevs/
|
||||||
cp NOTICE pypdevs/
|
cp NOTICE pypdevs/
|
||||||
mkdir pypdevs/tests/output
|
mkdir -p pypdevs/tests/output
|
||||||
rm pypdevs/src/pypdevs/*.pyc
|
rm pypdevs/src/pypdevs/*.pyc
|
||||||
rm pypdevs/examples/*/*.pyc
|
rm pypdevs/examples/*/*.pyc
|
||||||
rm pypdevs/examples/*/*.pyo
|
rm pypdevs/examples/*/*.pyo
|
||||||
|
|
@ -37,3 +37,5 @@ rm -R pypdevs/src/pypdevs/__pycache__
|
||||||
|
|
||||||
tar -czf pypdevs.tgz pypdevs
|
tar -czf pypdevs.tgz pypdevs
|
||||||
rm -R pypdevs
|
rm -R pypdevs
|
||||||
|
|
||||||
|
read -p "Press [Enter] key to continue..."
|
||||||
|
|
|
||||||
|
|
@ -17,5 +17,5 @@
|
||||||
Changelog
|
Changelog
|
||||||
=========
|
=========
|
||||||
|
|
||||||
.. literalinclude:: ../notes.txt
|
.. literalinclude:: ../../notes.txt
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -24,7 +24,7 @@ Dependencies
|
||||||
|
|
||||||
The following dependencies are mandatory:
|
The following dependencies are mandatory:
|
||||||
|
|
||||||
* python 2.7
|
* Python 2.7 **or** Python 3.6+
|
||||||
|
|
||||||
For parallel and distributed simulation, the following additional dependencies are required:
|
For parallel and distributed simulation, the following additional dependencies are required:
|
||||||
|
|
||||||
|
|
@ -35,6 +35,16 @@ Installation instructions are given for these two dependencies further in this s
|
||||||
|
|
||||||
Realtime simulation using the Tk backend, obviously requires Tk.
|
Realtime simulation using the Tk backend, obviously requires Tk.
|
||||||
|
|
||||||
|
Download
|
||||||
|
--------
|
||||||
|
|
||||||
|
The most up-to-date version of PyPDEVS can be obtained from the git repository::
|
||||||
|
|
||||||
|
git clone https://msdl.uantwerpen.be/git/yentl/PythonPDEVS.git
|
||||||
|
|
||||||
|
Alternatively, the latest release can be downloaded via:
|
||||||
|
https://msdl.uantwerpen.be/git/yentl/PythonPDEVS/archive/master.zip
|
||||||
|
|
||||||
PyPDEVS Installation
|
PyPDEVS Installation
|
||||||
--------------------
|
--------------------
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -41,9 +41,9 @@ While examples could be given purely in their formal description, they would not
|
||||||
To specify this model, we first define the event exchanged between different examples: the Job.
|
To specify this model, we first define the event exchanged between different examples: the Job.
|
||||||
A job is coded as a class ``Job``.
|
A job is coded as a class ``Job``.
|
||||||
It has the attributes ``size`` (i.e., indicative of processing time) and ``creation time`` (i.e., time the event was created, for statistic gathering).
|
It has the attributes ``size`` (i.e., indicative of processing time) and ``creation time`` (i.e., time the event was created, for statistic gathering).
|
||||||
The ``Job`` class definition is shown next and can de downloaded: :download:`job.py <../examples/queueing/job.py>`.
|
The ``Job`` class definition is shown next and can de downloaded: :download:`job.py <../../examples/queueing/job.py>`.
|
||||||
|
|
||||||
.. literalinclude:: ../examples/queueing/job.py
|
.. literalinclude:: ../../examples/queueing/job.py
|
||||||
|
|
||||||
We now focus on each atomic model seperately, starting at the event generator.
|
We now focus on each atomic model seperately, starting at the event generator.
|
||||||
|
|
||||||
|
|
@ -59,9 +59,9 @@ Finally, the output function returns a new customer event with a randomly define
|
||||||
The job has an attribute containing the time at which it was generated.
|
The job has an attribute containing the time at which it was generated.
|
||||||
Recall, however, that the output function was invoked before the internal transition, so the current time has not yet been updated by the internal transition.
|
Recall, however, that the output function was invoked before the internal transition, so the current time has not yet been updated by the internal transition.
|
||||||
Therefore, the output function also has to do this addition, without storing the result in the state (as it cannot write to the state).
|
Therefore, the output function also has to do this addition, without storing the result in the state (as it cannot write to the state).
|
||||||
The ``Generator`` class definition is shown next and can de downloaded: :download:`generator.py <../examples/queueing/generator.py>`.
|
The ``Generator`` class definition is shown next and can de downloaded: :download:`generator.py <../../examples/queueing/generator.py>`.
|
||||||
|
|
||||||
.. literalinclude:: ../examples/queueing/generator.py
|
.. literalinclude:: ../../examples/queueing/generator.py
|
||||||
|
|
||||||
Next up is the queue, which is the most interesting component of the simulation, as it is the part we wish to analyze.
|
Next up is the queue, which is the most interesting component of the simulation, as it is the part we wish to analyze.
|
||||||
The ``Queue`` implementation is similar in structure to the ``Generator``.
|
The ``Queue`` implementation is similar in structure to the ``Generator``.
|
||||||
|
|
@ -83,9 +83,9 @@ An important consideration in this model is the ``remaining\_time`` counter, whi
|
||||||
We can't simply put the processing time of events in the time advance, as interrupts could happen during this time.
|
We can't simply put the processing time of events in the time advance, as interrupts could happen during this time.
|
||||||
When an interrupt happens (e.g., another event arrives), the time advance is invoked again, and would return the total processing time, instead of the remaining time to process the event.
|
When an interrupt happens (e.g., another event arrives), the time advance is invoked again, and would return the total processing time, instead of the remaining time to process the event.
|
||||||
To solve this problem, we maintain a counter that explicitly gets decremented when an external interrupt happens.
|
To solve this problem, we maintain a counter that explicitly gets decremented when an external interrupt happens.
|
||||||
The ``Queue`` class definition is shown next and can de downloaded: :download:`queue.py <../examples/queueing/queue.py>`.
|
The ``Queue`` class definition is shown next and can de downloaded: :download:`queue.py <../../examples/queueing/queue.py>`.
|
||||||
|
|
||||||
.. literalinclude:: ../examples/queueing/queue.py
|
.. literalinclude:: ../../examples/queueing/queue.py
|
||||||
|
|
||||||
The next atomic model is the ``Processor`` class.
|
The next atomic model is the ``Processor`` class.
|
||||||
It merely receives an incoming event and starts processing it.
|
It merely receives an incoming event and starts processing it.
|
||||||
|
|
@ -95,32 +95,32 @@ We need to send out two events: one containing the job that was processed, and o
|
||||||
For this, two different ports are used.
|
For this, two different ports are used.
|
||||||
Note that the definition of the processor would not be this simple in case there was no queue before it.
|
Note that the definition of the processor would not be this simple in case there was no queue before it.
|
||||||
We can now make the assumption that when we get an event, we are already idle and therefore don't need to queue new incoming events first.
|
We can now make the assumption that when we get an event, we are already idle and therefore don't need to queue new incoming events first.
|
||||||
The ``Processor`` class definition is shown next and can de downloaded: :download:`processor.py <../examples/queueing/processor.py>`.
|
The ``Processor`` class definition is shown next and can de downloaded: :download:`processor.py <../../examples/queueing/processor.py>`.
|
||||||
|
|
||||||
.. literalinclude:: ../examples/queueing/processor.py
|
.. literalinclude:: ../../examples/queueing/processor.py
|
||||||
|
|
||||||
The processor finally sends the task to the ``Collector`` class.
|
The processor finally sends the task to the ``Collector`` class.
|
||||||
The collector is an artificial component that is not present in the system being modeled; it is only used for statistics gathering.
|
The collector is an artificial component that is not present in the system being modeled; it is only used for statistics gathering.
|
||||||
For each job, it stores the time in the queue.
|
For each job, it stores the time in the queue.
|
||||||
The ``Collector`` class definition is shown next and can de downloaded: :download:`collector.py <../examples/queueing/collector.py>`.
|
The ``Collector`` class definition is shown next and can de downloaded: :download:`collector.py <../../examples/queueing/collector.py>`.
|
||||||
|
|
||||||
.. literalinclude:: ../examples/queueing/collector.py
|
.. literalinclude:: ../../examples/queueing/collector.py
|
||||||
|
|
||||||
With all atomic examples defined, we only have to couple them together in a coupled model: the ``System``.
|
With all atomic examples defined, we only have to couple them together in a coupled model: the ``System``.
|
||||||
In this system, we instantiate a generator, queue, and collector, as well as a variable number of processors.
|
In this system, we instantiate a generator, queue, and collector, as well as a variable number of processors.
|
||||||
The number of processors is variable, but is still static during simulation.
|
The number of processors is variable, but is still static during simulation.
|
||||||
The couplings also depend on the number of processors, as each processor is connected to the queue and the collector.
|
The couplings also depend on the number of processors, as each processor is connected to the queue and the collector.
|
||||||
The ``System`` class definition is shown next and can de downloaded: :download:`system.py <../examples/queueing/system.py>`.
|
The ``System`` class definition is shown next and can de downloaded: :download:`system.py <../../examples/queueing/system.py>`.
|
||||||
|
|
||||||
.. literalinclude:: ../examples/queueing/system.py
|
.. literalinclude:: ../../examples/queueing/system.py
|
||||||
|
|
||||||
Now that our DEVS model is completely specified, we can start running simulations on it.
|
Now that our DEVS model is completely specified, we can start running simulations on it.
|
||||||
Simulation requires an *experiment* file though, which initializes the model with parameters and defines the simulation configuration.
|
Simulation requires an *experiment* file though, which initializes the model with parameters and defines the simulation configuration.
|
||||||
The experiment writes out the raw queueing times to a Comma Seperated Value (CSV) file.
|
The experiment writes out the raw queueing times to a Comma Seperated Value (CSV) file.
|
||||||
An experiment file often contains some configuration of the simulation tool, which differs for each tool.
|
An experiment file often contains some configuration of the simulation tool, which differs for each tool.
|
||||||
The experiment file is shown next and can de downloaded: :download:`experiment.py <../examples/queueing/experiment.py>`.
|
The experiment file is shown next and can de downloaded: :download:`experiment.py <../../examples/queueing/experiment.py>`.
|
||||||
|
|
||||||
.. literalinclude:: ../examples/queueing/experiment.py
|
.. literalinclude:: ../../examples/queueing/experiment.py
|
||||||
|
|
||||||
Performance Analysis
|
Performance Analysis
|
||||||
--------------------
|
--------------------
|
||||||
|
|
|
||||||
BIN
pypdevs.tgz
BIN
pypdevs.tgz
Binary file not shown.
|
|
@ -1092,7 +1092,10 @@ class BaseSimulator(Solver):
|
||||||
interrupt = self.threading_backend.getInterrupt()
|
interrupt = self.threading_backend.getInterrupt()
|
||||||
if interrupt is None:
|
if interrupt is None:
|
||||||
self.realtime_counter = 100
|
self.realtime_counter = 100
|
||||||
self.threading_backend.wait(wait_time, self.runsim)
|
if wait_time == float('inf') and getattr(self, "accept_external_input", False):
|
||||||
|
self.threading_backend.wait(0.01, self.runsim)
|
||||||
|
else:
|
||||||
|
self.threading_backend.wait(wait_time, self.runsim)
|
||||||
return True
|
return True
|
||||||
try:
|
try:
|
||||||
info = interrupt.split(" ")
|
info = interrupt.split(" ")
|
||||||
|
|
|
||||||
|
|
@ -51,6 +51,7 @@ class Controller(BaseSimulator):
|
||||||
self.running_irreversible = None
|
self.running_irreversible = None
|
||||||
self.initial_allocator = None
|
self.initial_allocator = None
|
||||||
self.prev_termination_time = 0.0
|
self.prev_termination_time = 0.0
|
||||||
|
self.accept_external_input = False
|
||||||
|
|
||||||
def __setstate__(self, retdict):
|
def __setstate__(self, retdict):
|
||||||
"""
|
"""
|
||||||
|
|
@ -317,6 +318,14 @@ class Controller(BaseSimulator):
|
||||||
self.termination_condition = termination_condition
|
self.termination_condition = termination_condition
|
||||||
self.termination_time_check = False
|
self.termination_time_check = False
|
||||||
|
|
||||||
|
def setAcceptExternalInputs(self, aei):
|
||||||
|
"""
|
||||||
|
Sets the controller to accept external inputs.
|
||||||
|
When enabled, the "early-return" of the simulator when all components have an infinite
|
||||||
|
time-advance is ignored.
|
||||||
|
"""
|
||||||
|
self.accept_external_input = aei
|
||||||
|
|
||||||
def findAndPerformRelocations(self, gvt, activities, horizon):
|
def findAndPerformRelocations(self, gvt, activities, horizon):
|
||||||
"""
|
"""
|
||||||
First requests the relocator for relocations to perform, and afterwards actually perform them.
|
First requests the relocator for relocations to perform, and afterwards actually perform them.
|
||||||
|
|
|
||||||
|
|
@ -51,7 +51,7 @@ class ThreadingBackend(object):
|
||||||
|
|
||||||
def interrupt(self, value):
|
def interrupt(self, value):
|
||||||
"""
|
"""
|
||||||
Interrupt a running wait call.
|
Interrupt a running wait call, overwriting any previous interrupts.
|
||||||
|
|
||||||
:param value: the value that interrupts
|
:param value: the value that interrupts
|
||||||
"""
|
"""
|
||||||
|
|
|
||||||
|
|
@ -623,6 +623,7 @@ class SimulatorConfiguration(object):
|
||||||
if not isinstance(ports, dict):
|
if not isinstance(ports, dict):
|
||||||
raise DEVSException("Realtime input port references should be a dictionary")
|
raise DEVSException("Realtime input port references should be a dictionary")
|
||||||
self.simulator.realtime_port_references = ports
|
self.simulator.realtime_port_references = ports
|
||||||
|
self.simulator.accept_external_input = True
|
||||||
|
|
||||||
def setModelState(self, model, new_state):
|
def setModelState(self, model, new_state):
|
||||||
"""
|
"""
|
||||||
|
|
|
||||||
|
|
@ -210,6 +210,7 @@ class Simulator(object):
|
||||||
self.setSchedulerActivityHeap()
|
self.setSchedulerActivityHeap()
|
||||||
self.locations_file = None
|
self.locations_file = None
|
||||||
self.allocator = None
|
self.allocator = None
|
||||||
|
self.accept_external_input = False
|
||||||
self.realtime_extra = []
|
self.realtime_extra = []
|
||||||
|
|
||||||
self.model_ids = []
|
self.model_ids = []
|
||||||
|
|
@ -584,6 +585,7 @@ class Simulator(object):
|
||||||
self.controller.setDSDEVS(self.dsdevs)
|
self.controller.setDSDEVS(self.dsdevs)
|
||||||
self.controller.setActivityTracking(self.activity_tracking)
|
self.controller.setActivityTracking(self.activity_tracking)
|
||||||
self.controller.setClassicDEVS(self.classicDEVS)
|
self.controller.setClassicDEVS(self.classicDEVS)
|
||||||
|
self.controller.setAcceptExternalInputs(self.accept_external_input)
|
||||||
self.controller.setCellLocationTracer(self.x_size,
|
self.controller.setCellLocationTracer(self.x_size,
|
||||||
self.y_size,
|
self.y_size,
|
||||||
self.location_cell_view)
|
self.location_cell_view)
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue