What is 'cycle' in specman events - specman

I have stumbled upon e code written like that:
event a is cycle #b;
Removing the 'cycle' from this event, made no difference in behavior.
What is the meaning of cycle here?
Thanks

From the e LRM:
"Represents one cycle of an event. With no explicit sampling event specified, this
represents one cycle of the default sampling event. With a sampling event specified,
cycle is equivalent to “#sampling-event #any”. You can use the cycle expression to
override the default sampling event taken from the context."
A use for it is the following:
some_tcm() #clk is {
message(LOW, "This is synced at clock");
wait #rise_async;
message(LOW, "This is synced at the first clk after rise_async");
wait cycle #rise_async;
message(LOW, "This is synced exactly at rise_async");
stop_run();
};
some_tcm() specifies #clk as a sampling event. Say you have another asynchronous event #rise_async which will get triggered in between clock edges. If you do a simple wait #rise_async the TCM will wait until the first trigger of #clk after #rise_async (effectively a #rise_async #clk). If you do a wait cycle #rise_async, then you have overridden the sampling event and the TCM will wait exactly until #rise_async happens.

"event a is cycle #b;" is a trick to respond to event triggering, but do so at the end of the current tick.
For example, the following code would print "hello world", instead of "world hello" if we did "on b".
event b;
event a is cycle #b;
foo() is {
emit b;
message(NONE, "hello");
};
on a {
message(NONE, "world");
};

Related

Is it possible to dynamically update if functions in anylogic?

I'm using a state chart in combination with a schedule in Anylogic (see picture). The output of the schedule is equal to 1 during working hours and 0 otherwise. Now I want the transition from state1 to state2 to happen when the schedule is turning to 1 or is equal to 1(so otherwise wait until the working hours).
I have tried using an if statement
if( main.plannerSchedule()==1 )(<perform action>)
However, by this method, the state transition only happens if the statement is true but doesn't wait for it to become true. Is there a way to constantly update the state transition or is there a "wait until" function that can solve this problem?
Best let the schedule send a message to your statechart when it switches. This assumes that the statechart lives on the same agent type as the schedule. Write this code in the action code box of the schedule:
if (value==1) {
statechart.fireEvent("go to state 2");
}
Obviously, your message transition needs to await the "go to state 2" message.
Note the value keyword. See https://www.benjamin-schumann.com/blog/2016/2/4/the-magic-lightbulb-and-how-it-can-help-your-anylogic-modelling for more info on that

Why won't AnyEvent::child callbacks ever run if interval timer events are always ready?

Update this issue can be resolved using the fixes present in https://github.com/zbentley/AnyEvent-Impl-Perl-Improved/tree/io-starvation
Context:
I am integrating AnyEvent with some otherwise-synchronous code. The synchronous code needs to install some watchers (on timers, child processes, and files), wait for at least one watcher to complete, do some synchronous/blocking/legacy stuff, and repeat.
I am using the pure-perl AnyEvent::Loop-based event loop, which is good enough for my purposes at this point; most of what I need it for is signal/process/timer tracking.
The problem:
If I have a callback that can block the event loop for a moment, child-process-exit events/callbacks never fire. The simplest example I could make watches a child process and runs an interval timer. The interval timer does something blocking before it finishes:
use AnyEvent;
# Start a timer that, every 0.5 seconds, sleeps for 1 second, then prints "timer":
my $w2 = AnyEvent->timer(
after => 0,
interval => 0.5,
cb => sub {
sleep 1; # Simulated blocking operation. If this is removed, everything works.
say "timer";
},
);
# Fork off a pid that waits for 1 second and then exits:
my $pid = fork();
if ( $pid == 0 ) {
sleep 1;
exit;
}
# Print "child" when the child process exits:
my $w1 = AnyEvent->child(
pid => $pid,
cb => sub {
say "child";
},
);
AnyEvent->condvar->recv;
This code leaves the child process zombied, and prints "timer" over and over, for "ever" (I ran it for several minutes). If the sleep 1 call is removed from the callback for the timer, the code works correctly and the child process watcher fires as expected.
I'd expect the child watcher to run eventually (at some point after the child exited, and any interval events in the event queue ran, blocked, and finished), but it does not.
The sleep 1 could be any blocking operation. It can be replaced with a busy-wait or any other thing that takes long enough. It doesn't even need to take a second; it appears to only need to be a) running during the child-exit event/SIGCHLD delivery, and b) result in the interval always being due to run according to the wallclock.
Questions:
Why isn't AnyEvent ever running my child-process watcher callback?
How can I multiplex child-process-exit events with interval events that may block for so long that the next interval becomes due?
What I've tried:
My theory is that timer events which become "ready" due to time spent outside of the event loop can indefinitely pre-empt other types of ready events (like child process watchers) somewhere inside AnyEvent. I've tried a few things:
Using AnyEvent::Strict doesn't surface any errors or change behavior in any way.
Partial solution: Removing the interval event at any point does make the child process watcher fire (as if there's some internal event polling/queue population done inside AnyEvent that only happens if there are no timer events already "ready" according to the wallclock). Drawbacks: in the general case that doesn't work, since I'd have to know when my child process had exited to know when to postpone my intervals, which is tautological.
Partial solution: Unlike child-process watchers, other interval timers seem to be able to multiplex with each other just fine, so I can install a manual call to waitpid in another interval timer to check for and reap children. Drawbacks: child-waiting can be artificially delayed (my use case involves lots of frequent process creation/destruction), any AnyEvent::child watchers that are installed and fire successfully will auto-reap the child and not tell my interval/waitpid timer, requiring orchestration, and it just generally feels like I'm misusing AnyEvent.
The interval is the time between the start of each timer callback, i.e. not the time between the end of a callback and the start of the next callback. You setup a timer with interval 0.5 and the action for the timer is to sleep one second. This means that once the timer is triggered it will be triggered immediately again and again because the interval is always over after the timer returned.
Thus depending on the implementation of the event loop it might happen that no other events will be processed because it is busy running the same timer over and over. I don't know which underlying event loop you are using (check $AnyEvent::MODEL) but if you look at the source code of AnyEvent::Loop (the loop for the pure Perl implementation, i.e. model is AnyEvent::Impl::Perl) you will find the following code:
if (#timer && $timer[0][0] <= $MNOW) {
do {
my $timer = shift #timer;
$timer->[1] && $timer->[1]($timer);
} while #timer && $timer[0][0] <= $MNOW;
As you can see it will be busy executing timers as long as there are timers which need to run. And with your setup of the interval (0.5) and the behavior of the timer (sleep one second) there will always be a timer which needs to be executed.
If you instead change your timer so that there is actual room for the processing of other events by setting the interval to be larger than the blocking time (like 2 seconds instead of 0.5) everything works fine:
...
interval => 2,
cb => sub {
sleep 1; # Simulated blocking operation. Sleep less than the interval!!
say "timer";
...
timer
child
timer
timer
Update this issue can be resolved using the fixes present in https://github.com/zbentley/AnyEvent-Impl-Perl-Improved/tree/io-starvation
#steffen-ulrich's answer is correct, but points out a very flawed behavior in AnyEvent: since there is no underlying event queue, certain kinds of events that always report "ready" can indefinitely pre-empt others.
Here is a workaround:
For interval timers that are always "ready" due to a blocking operation that happens outside of the event loop, it is possible to prevent starvation by chaining interval invocations onto the next run of the event loop, like this:
use AnyEvent;
sub deferred_interval {
my %args = #_;
# Some silly wrangling to emulate AnyEvent's normal
# "watchers are uninstalled when they are destroyed" behavior:
${$args{reference}} = 1;
$args{oldref} //= delete($args{reference});
return unless ${$args{oldref}};
AnyEvent::postpone {
${$args{oldref}} = AnyEvent->timer(
after => delete($args{after}) // $args{interval},
cb => sub {
$args{cb}->(#_);
deferred_interval(%args);
}
);
};
return ${$args{oldref}};
}
# Start a timer that, at most once every 0.5 seconds, sleeps
# for 1 second, and then prints "timer":
my $w1; $w1 = deferred_interval(
after => 0.1,
reference => \$w2,
interval => 0.5,
cb => sub {
sleep 1; # Simulated blocking operation.
say "timer";
},
);
# Fork off a pid that waits for 1 second and then exits:
my $pid = fork();
if ( $pid == 0 ) {
sleep 1;
exit;
}
# Print "child" when the child process exits:
my $w1 = AnyEvent->child(
pid => $pid,
cb => sub {
say "child";
},
);
AnyEvent->condvar->recv;
Using that code, the child process watcher will fire more or less on time, and the interval will keep firing. The tradeoff is that each interval timer will only start after each blocking callback finishes. Given an interval time of I and a blocking-callback runtime of B, this approach will fire an interval event roughly every I + B seconds, and the previous approach from the question will take min(I,B) seconds (at the expense of potential starvation).
I think that a lot of the headaches here could be avoided if AnyEvent had a backing queue (many common event loops take this approach to prevent situations exactly like this one), or if the implementation of AnyEvent::postpone installed a "NextTick"-like event emitter to be fired only after all other emitters had been checked for events.

Confusion regarding usage of event.triggered

I'm trying out some code that is supposed to block until moving to a new simulation time step (similar to waiting for sys.tick_start in e).
I tried writing a function that does this:
task wait_triggered();
event e;
`uvm_info("DBG", "Waiting trig", UVM_NONE)
-> e;
$display("e.triggered = ", e.triggered);
wait (!e.triggered);
`uvm_info("DBG", "Wait trig done", UVM_NONE)
endtask
The idea behind it is that I trigger some event, meaning that its triggered field is going to be 1 when control reaches the line with wait(!e.triggered). This line should unblock in the next time slot, when triggered is going to be cleared.
To test this out I added some other thread that consumes simulation time:
fork
wait_triggered();
begin
`uvm_info("DBG", "Doing stuff", UVM_NONE)
#1;
`uvm_info("DBG", "Did stuff", UVM_NONE)
end
join
#1;
$finish(1);
I see the messages Doing stuff and Did stuff, but Wait trig done never comes. The simulation also stops before reaching the finish(1). One simulator told me that this is because no further events have been scheduled.
All simulators exhibit the same behavior, so there must be something I'm missing. Could anyone explain what's going on?
The problem is with wait (!e.triggered); when e.triggered is changing from 1 to zero. It has to change in a region where nothing can be scheduled, so whether it changes at the end of the current time slot, or the beginning of the next time slot is unobservable. So the wait will hang waiting for the end of the current time slot, which never comes.
I think the closest thing to what you are looking for is #1step. This blocks for the smallest simulation precision time step. But I've got to believe there is a better way to code what you want without having to know if time is advancing.

Using REPEAT a block till an event occurs?

This is my issue:
On triger of a START button i wan to execute one block. And it should stop executing when I
press STOP button.
Eg
on triger of start button:
REPEAT:
message "hai".
END.
and when I press STOP button It should stop. What additional condition should I give to REPEAT block?Preferably I dont want to write the condition in STOP button Triger..Please give suggestion .
Progress is not multi-threaded.
So you have to carefully think through which bits of code need to execute in what context in order to fake it. (More carefully than my initial "it cannot be done" response.)
As "firhang" points out "PROCESS EVENTS" can be used to check for events queued and ready to be acted on.
So you could run your loop inside an event handler and have that event handler listen for additional events.
I believe that the following satisfies the original question and works in both GUI and Character clients:
define variable i as integer no-undo.
define variable bStop as logical no-undo.
define button butStart label "Start".
define button butStop label "Stop".
form butStart butStop with frame but-frame row 1.
on choose of butStop bStop = true.
on choose of butStart do:
bStop = false.
do while bStop = false:
i = i + 1.
process events.
message i.
end.
message "Paused".
end.
enable butStart butStop with frame but-frame.
pause 0 before-hide.
wait-for window-close of current-window.
PROCESS EVENTS statement
Processes all outstanding events without blocking for user input.
Syntax
PROCESS EVENTS
Example
This procedure counts to 1,000 until you choose STOP:
r-proevs.p
DEFINE VARIABLE ix AS INTEGER NO-UNDO.
DEFINE VARIABLE stop-sel AS LOGICAL NO-UNDO.
DEFINE BUTTON stop-it LABEL "STOP".
DISPLAY stop-it.
ON CHOOSE OF stop-it
stop-sel = TRUE.
ENABLE stop-it.
DO ix = 1 TO 1000:
DISPLAY ix VIEW-AS TEXT.
PROCESS EVENTS.
IF stop-sel THEN LEAVE.
END.
On each pass through the loop, the procedure displays the new value of ix and then checks whether any events are waiting to be processed. If no events have occurred, execution continues and the loop iterates. If the STOP button has been chosen, that event is processed changing the value of stop-sel. When execution continues, the program exits the loop.
If the loop does not contain the PROCESS EVENTS statement, the choose event never processes and the loop iterates until ix equals 1,000.
Notes
The WAIT-FOR statement processes all pending events and blocks all other execution until a specified event occurs. The PROCESS EVENTS statement processes all pending events and immediately continues execution with the next statement.
If there are any asynchronous requests for which PROCEDURE-COMPLETE events have been received but not yet processed, this statement processes these events as described for the WAIT-FOR statement.
You cannot call the .NET method system.Windows.Forms.Application:DoEvent( ) in ABL. The PROCESS EVENTS statement performs the function of this method.
.NET can raise exceptions in the context of an ABL session when this statement executes.
DEFINE VARIABLE bStop AS LOGICAL NO-UNDO.
DEFINE BUTTON butStop LABEL "Stop".
FORM butStop WITH FRAME but-frame ROW 1.
ON CHOOSE OF butStop bStop = TRUE.
ENABLE butStop WITH FRAME but-frame.
REPEAT:
PROCESS EVENTS.
MESSAGE "hai".
IF bStop THEN LEAVE.
END.
MESSAGE "stoped".
WAIT-FOR WINDOW-CLOSE OF CURRENT-WINDOW.

numeric updown control c#

I am using numeric updowncontrol. For min and max values changed listening for these events
this.numDownMinLimit.ValueChanged += new System.EventHandler(this.numDownMinLimit_ValueChanged);
this.numDownMaxLimit.ValueChanged += new System.EventHandler(this.numDownMaxLimit_ValueChanged);
step size set is 0.1
The eventhandler takes some time to complete.
If you keep the mouse pressed for a period of time and then release it, the eventhandler still executes with the previous values which were fired.
How do we prevent this scenario from occurring? I would like to discard the remaining events which are still in the queue, waiting to be handled, when the user releases the mouse button.
You need to have a look at the NumericUpDownAcceleration Class which handles this behaviour:
From: http://msdn.microsoft.com/en-us/library/system.windows.forms.numericupdownacceleration.aspx
The NumericUpDownAcceleration object
is used by the NumericUpDown control
to optionally provide acceleration
when incrementing or decrementing the
control through a large quantity of
numbers.
Let us know how you get on.