In any system, changes in untimed state are caused by significant events that occur in the system. Many times it is useful to keep track of these significant events. These can either be used as auxiliary model elements to define safety properties during model checking, or they can be part of the system implementation itself (e.g. black-box recording). Events of interest differ based on where they are used. Therefore, an event stream is parametrized by the set of events that the system handles. This can be captured by the following parameterized module EVENT-LOG (note that the sort Mt-Log (empty log) is added to ensure that the empty log nil will have a least sort when there are multiple distinct instances of EVENT-LOG):
(fmod EVENT-LOG{X :: TRIV} is pr RT-COMP . sorts NoEventType{X} EventType{X} Event{X} . sorts Mt-Log Stopped-Event-Log{X} Event-Log{X} . subsorts X$Elt NoEventType{X} < EventType{X} .
subsort Mt-Log < Stopped-Event-Log{X} < Event-Log{X} < RT-Comp .
op none : -> NoEventType{X} [ctor] . op E : X$Elt Clock -> Event{X} [ctor] . op type : Event{X} -> X$Elt .
op elapsed : Event{X} -> Time . op stop : Event{X} -> Event{X} . op stopped? : Event{X} -> Bool .
op tick : Event{X} Time -> Event{X} . op mte : Event{X} -> Time .
var C : Clock . var L L’ : Event-Log{X} . var SL : Stopped-Event-Log{X} .
var T T’ : Time .
eq type(E(ET, C)) = ET .
eq elapsed(E(ET, C)) = value(C) . eq stop(E(ET, C)) = E(ET, stop(C)) . eq stopped?(E(ET, C)) = stopped?(C) .
eq tick(E(ET, C), T) = E(ET, tick(C, T)) . eq mte(E(ET, C)) = mte(C) .
op nil : -> Mt-Log [ctor] .
op __ : Event{X} Stopped-Event-Log{X} -> Event-Log{X} [ctor] . op stop : Mt-Log -> Mt-Log .
op stop : Event-Log{X} -> Stopped-Event-Log{X} . op append : Mt-Log Mt-Log -> Mt-Log .
op append : Event-Log{X} Stopped-Event-Log{X} -> Event-Log{X} .
cmb EV SL : Stopped-Event-Log{X} if stopped?(EV) .
op log : Mt-Log NoEventType{X} -> Mt-Log .
op log : Event-Log{X} EventType{X} -> Event-Log{X} .
op tick : Mt-Log Time -> Mt-Log .
op tick : Event-Log{X} Time -> Event-Log{X} . op mte : Event-Log{X} -> Time .
eq stop(nil) = nil .
eq stop(EV L) = stop(EV) stop(L) . eq append(nil, L) = L .
Figure 4.2: Event Example
eq log(L, none) = L .
eq log(L, ET) = E(ET, clock0) stop(L) [owise] .
eq tick(nil, T) = nil .
--- only the latest event needs to be ticked --- remaining event clocks are stopped eq tick(EV L, T) = tick(EV, T) L . eq mte(nil) = INF .
eq mte(EV L) = mte(EV) . endfm)
To understand event logs it is helpful to provide an example of how one such log is represented. Figure 4.2 shows a stream of events (with event names A!, B!, C!, D!) and the time durations between them. Also, there is a reference point to the current time the system is at. To represent this set of events, we first need to instantiate the set of event names with an appropriate module and view:
(fmod ABCD-EVENT is sort EventName .
ops A! B! C! D! : -> EventName . endfm)
(view ABCD-Event from TRIV to ABCD-EVENT is sort Elt to EventName .
endv)
(fmod ABCD-EVENT-LOG is pr EVENT-LOG{ABCD-Event} .
pr POSRAT-TIME-DOMAIN-WITH-INF .
op events : -> Event-Log{ABCD-Event} . eq events =
E(D!, c(4, run)) E(C!, c(6, stop)) E(B!, c(4, stop)) E(A!, c(5, stop)) nil .
endfm)
The constant events corresponds exactly to the graphical representation of the events in Figure 4.2. Furthermore, ticking events increases the time elapsed for the latest event:
reduce in ABCD-EVENT-LOG : tick(events,10)
result Event-Log{ABCD-Event} :
E(D!,c(14,run))E(C!,c(6,stop))E(B!,c(4,stop))E(A!,c(5,stop))nil
Finally, adding an event to the log locks (stops all the clocks for) the time elapsed of all previous events and starts a clock for the newest event:
reduce in ABCD-EVENT-LOG : log(tick(events,10),A!) result Event-Log{ABCD-Event} :
E(A!,c(0,run))E(D!,c(14,stop))E(C!,c(6,stop))E(B!,c(4,stop))E(A!,c(5, stop))nil
We would also like to highlight a particularly important type of event log for the medical device wrapper, namely, the stress-relax log. An example of a stress-relax log is shown in Figure 4.3. Given a critical threshold for a value that changes over time, a !stress event is recorded whenever the value crosses above the threshold, and a !relax event is recorded whenever the value crosses below the threshold. Also, we assume that the system starts at a value below the threshold. Notice that a stress-relax log imposes additional structure on top of event logs:
1. The first event logged must be a !stress event
2. Events must alternate between !stress and !relax events over time
These constraints, and the notion of a stress-relax log, are both captured by the following parameterized instantiation (plus additional constraints) on event logs:
Figure 4.3: Stress Relax Event Log
(fmod STRESS-RELAX-EVENT is sort SREvent .
ops !stress !relax : -> SREvent [ctor] . endfm)
(view SREvent from TRIV to STRESS-RELAX-EVENT is sort Elt to SREvent .
endv)
(fmod STRESS-RELAX-LOG is inc EVENT-LOG{SREvent} .
sorts Stopped-Stress-Relax-Log Stress-Relax-Log . subsorts Mt-Log
< Stopped-Stress-Relax-Log < Stopped-Event-Log{SREvent} .
subsorts Stopped-Stress-Relax-Log
< Stress-Relax-Log < Event-Log{SREvent} .
op tick : Stress-Relax-Log Time -> Stress-Relax-Log .
var C C’ : Clock .
var SL : Stopped-Stress-Relax-Log . var L : Stress-Relax-Log .
cmb E(!stress, C) nil : Stopped-Stress-Relax-Log if stopped?(C) .
cmb E(!stress, C) E(!relax, C’) SL : Stopped-Stress-Relax-Log if E(!relax, C’) SL : Stopped-Stress-Relax-Log
/\ stopped?(C) .
cmb E(!relax, C) E(!stress, C’) SL : Stopped-Stress-Relax-Log if E(!stress, C’) SL : Stopped-Stress-Relax-Log
/\ stopped?(C) .
mb E(!stress, C) nil : Stress-Relax-Log .
cmb E(!stress, C) E(!relax, C’) SL : Stress-Relax-Log if E(!relax, C’) SL : Stopped-Stress-Relax-Log . cmb E(!relax, C) E(!stress, C’) SL : Stress-Relax-Log
if E(!stress, C’) SL : Stopped-Stress-Relax-Log . endfm)