SCL allows the user to inject external values into the simulated PIC environment while the simultor is executing the user's project code. For example, SCL can be used to toggle the INT0 pin to cause an interrupt to occur.
Given that the Simulator is, well, a simulation, timing of injection can be tricky. Events that happen simultaneously on the real hardware necessarily happen sequentially in the simulation. It is necessary to understand how the Simulator works to know when to inject.
The Simulator's fundamental process is to execute an instruction from the user's software image. For example, when "running", the Simulator is actually just executing one instruction after another. Of course the Simulator also simulates peripherals and handles SCL injections too. Here is the basic single-step flow:
singleStepexecute user instructionfor each Tcyc needed by instruction // might be more than 1 Tcyc!increment stopwatchprocess each peripheralrun SCL processes
What is important here is to note that SCL injection won't occur until after the instruction has been executed. Usually the SCL author doesn't have to worry about cycle accuracy to such a fine level. But when injections absolutely have to occur at a specific instruction cycle, remembering the above process flow can be invaluable.
The run SCL processes step in the above singleStep flow was a bit vague. What exactly happens when the Simulator runs SCL processes?
(If you are new to SCL and the next part is confusing, skip it for now. It will make more sense after you've played with SCL for a bit!)
SCL maintains two process queues, active and inactive. When SCL runs it's processes, each process on the inactive queue is checked to see if that process can be moved to the active queue. (This is usually determined by the arguments to the wait statment that put the process on the inactive queue.) Then each process on the active queue is executed until another wait statement is encountered, putting the process back on the inactive queue.
This sequence is repeated until no SCL processes remain on the
active queue. In particular note that a process can encounter a wait
condition that will immediately move it back to the active queue. For
example assume the wait statement is "
wait until STATUS.Z == 1".
If the STATUS.Z register field is currently 1, then the process will
move to the inactive queue and immediately move back to the active queue
and continue executing. All within the same simulation Tcyc!