Class: Risc::Sim
- Inherits:
-
Object
- Object
- Risc::Sim
- Defined in:
- lib/risc/Sim.rb
Overview
A generic discrete-event sequential simulator. This class implements a generic discrete-event sequential simulator. Sim maintains and executes a time-ordered schedule of actions (or discrete events).
Constant Summary collapse
- A_Event =
0- A_Timeout =
1- A_Init =
2- A_Stop =
3- @@m_current_time =
Virtual time in the simulated world.
INIT_TIME- @@m_current_process =
Currently running process.
Process::NULL_PROCESSID
- @@m_current_delay =
Duration of the current action.
INIT_TIME- @@m_running =
Is simulation running?
false- @@m_actions =
{}
- @@m_processes =
{}
- @@m_lock =
false
Class Method Summary collapse
-
.advance_delay(delay) ⇒ Object
Advance the execution time of the current process.
-
.clear ⇒ Object
Clears out internal data structures.
-
.clock ⇒ Object
Returns the current virtual time for the current process.
-
.create_process(process, mode = 0) ⇒ Object
Creates a new process with the given Process object.
-
.run_simulation ⇒ Object
Starts execution of the simulation.
- .schedule(action, time) ⇒ Object
- .schedule_now(action) ⇒ Object
-
.set_timeout(time) ⇒ Object
Sets a timeout for the current process.
-
.signal_event(event, pid, delay = 0) ⇒ Object
Signal an event to the given process.
-
.stop_process(pid = @@m_current_process) ⇒ Object
Stops the execution of a given process.
-
.stop_simulation ⇒ Object
Stops execution of the simulation.
-
.this_process ⇒ Object
Returns the current process.
Class Method Details
.advance_delay(delay) ⇒ Object
Advance the execution time of the current process. This method can be used to specify the duration of certain actions, or certain steps within the same action.
146 147 148 149 150 151 |
# File 'lib/risc/Sim.rb', line 146 def Sim.advance_delay(delay) return unless @@m_running pd = @@m_processes[@@m_current_process] pd.total_action_time += delay @@m_current_delay += delay end |
.clear ⇒ Object
Clears out internal data structures. Resets the simulator making it available for a completely new simulation. All scheduled actions are deleted together with the associated events. All process identifiers returned by previoius invocations of link create_process(Process*,char) create_processendlink are invalidated by this operation. Notice however that it is the responsibility of the simulation programmer to delete process objects used in the simulation.
117 118 119 120 121 122 123 |
# File 'lib/risc/Sim.rb', line 117 def Sim.clear @@m_running = false @@m_current_time = INIT_TIME @@m_current_delay = INIT_TIME @@m_processes.clear @@m_actions.clear end |
.clock ⇒ Object
Returns the current virtual time for the current process.
159 160 161 |
# File 'lib/risc/Sim.rb', line 159 def Sim.clock @@m_current_time + @@m_current_delay end |
.create_process(process, mode = 0) ⇒ Object
Creates a new process with the given Process object. mode specifies the execution flags of the process. If the P_SEQUENTIAL flag is set, then the process will process one event at a time with respect to the simulation virtual time, otherwise (default) the actions of this process will be considered reentrant and may be executed in parallel. By default, the simulator discards the events signalled to a P_SEQUENTIAL process while that process is busy executing other actions. The P_QUEUEING flag can be set to instruct the simulator to queue those events. In this case, the simulator will deliver signals to that process as the process is available to respond to them.
94 95 96 97 98 99 |
# File 'lib/risc/Sim.rb', line 94 def Sim.create_process(process,mode = 0) newpid = @@m_processes.size @@m_processes[newpid] = PDescr.new(process,mode & (P_SEQUENTIAL | P_QUEUEING)) schedule_now(Action.new(A_Init,newpid)) newpid end |
.run_simulation ⇒ Object
Starts execution of the simulation.
164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 |
# File 'lib/risc/Sim.rb', line 164 def Sim.run_simulation # Prevents anyone from re-entering the main loop. Note that this # isn't meant to be thread-safe, it works if some process calls # Sim::run_simulation() within their process_event() or # process_timeout() function. return if @@m_lock @@m_lock = true @@m_running = true # While there is at least a scheduled action... while (@@m_running && !@@m_actions.empty?) do # I'm purposely excluding any kind of checks in this version # of the simulator. # I should say something like this: # assert(current_time <= (*a).first); key = @@m_actions.keys.sort.first @@m_current_time = key actions = @@m_actions[key] action = actions.delete_at(0) @@m_actions.delete(key) if actions.empty? @@m_current_process = action.pid @@m_current_delay = 0 # Right now I don't check if current_process is indeed a # valid process. Keep in mind that this is the heart of the # simulator main loop, therefore efficiency is crucial. # Perhaps I should check. This is somehow a design choice. pd = @@m_processes[@@m_current_process] if ((pd.status & P_TERMINATED) > 0) then # ...work in progress... action.event = nil elsif ((pd.status & P_SEQUENTIAL) > 0 && @@m_current_time < pd.available_at) then # This process is sequential and is currently executing # another action (in virtual time of course), so we # reschedule this action to the time the process is # available. schedule(action,pd.available_at) if ((pd.status & P_QUEUEING) > 0) # If the process can not queue actions, this action is simply dropped. else case action.type when A_Event pd.process.process_event(action.event) when A_Timeout pd.process.process_timeout when A_Init pd.process.init when A_Stop pd.process.stop pd.status |= P_TERMINATED else # Add paranoia checks/logging here? end pd.available_at = clock if ((pd.status & P_SEQUENTIAL) > 0) end end @@m_lock = false end |
.schedule(action, time) ⇒ Object
229 230 231 |
# File 'lib/risc/Sim.rb', line 229 def Sim.schedule(action,time) (@@m_actions[clock + time] ||= []) << action end |
.schedule_now(action) ⇒ Object
233 234 235 |
# File 'lib/risc/Sim.rb', line 233 def Sim.schedule_now(action) schedule(action,@@m_current_time) end |
.set_timeout(time) ⇒ Object
Sets a timeout for the current process. Schedules the execution of process_timeout() on the current process after the given amount of (virtual) time.
139 140 141 |
# File 'lib/risc/Sim.rb', line 139 def Sim.set_timeout(time) schedule(Action.new(A_Timeout,@@m_current_process),time) end |
.signal_event(event, pid, delay = 0) ⇒ Object
Signal an event to the given process. Signal an event to the given process. The response is scheduled for the current time.
129 130 131 132 133 134 |
# File 'lib/risc/Sim.rb', line 129 def Sim.signal_event(event,pid,delay = 0) pd = @@m_processes[pid] return -1 if pd.status & P_TERMINATED > 0 schedule(Action.new(A_Event,pid,event),delay) 0 end |
.stop_process(pid = @@m_current_process) ⇒ Object
Stops the execution of a given process.
102 103 104 105 106 107 |
# File 'lib/risc/Sim.rb', line 102 def Sim.stop_process(pid = @@m_current_process) pd = @@m_processes[pid] return -1 if pd.status & P_TERMINATED > 0 schedule_now(Action.new(A_Stop,pid)) 0 end |
.stop_simulation ⇒ Object
Stops execution of the simulation.
225 226 227 |
# File 'lib/risc/Sim.rb', line 225 def Sim.stop_simulation @@m_running = false end |
.this_process ⇒ Object
Returns the current process.
154 155 156 |
# File 'lib/risc/Sim.rb', line 154 def Sim.this_process @@m_current_process end |