{-# OPTIONS --safe --cubical #-}
module SemanticExplanation.Industry.Spartan where
open import Agda.Builtin.Reflection using (Name)
open import Agda.Builtin.List
renaming ([] to []L ; _∷_ to _∷L_)
open import SemanticExplanation
open import Spartan6.Prelude
open import Spartan6.Netlist.Expression
open import Spartan6.Semantics.Design
import Spartan6.Examples.StateDomains as StateDomains
import Spartan6.Semantics.Invariant as Invariant
import Spartan6.Semantics.Simulation as Simulation
guardDoorClosedSignal : Expr 3 2
guardDoorClosedSignal = input fzero
emergencyStopLoopHealthySignal : Expr 3 2
emergencyStopLoopHealthySignal = input (fsuc fzero)
restartCommandSignal : Expr 3 2
restartCommandSignal = input (fsuc (fsuc fzero))
motorPermitNext : Expr 3 2
motorPermitNext =
(guardDoorClosedSignal andE emergencyStopLoopHealthySignal)
andE restartCommandSignal
firstMotorPermit secondMotorPermit : Expr 3 2
firstMotorPermit = register fzero
secondMotorPermit = register (fsuc fzero)
redundantMotorInterlock : Design 3 2 2
redundantMotorInterlock =
mkDesign
(low ∷ low ∷ [])
(firstMotorPermit ∷ secondMotorPermit ∷ [])
(motorPermitNext ∷ motorPermitNext ∷ [])
MotorPermitChannelsSynchronized :
State redundantMotorInterlock → Type₀
MotorPermitChannelsSynchronized (first ∷ second ∷ []) = first ≡ second
motorPermitChannelsInvariant :
Invariant.Invariant
redundantMotorInterlock MotorPermitChannelsSynchronized
Invariant.initially motorPermitChannelsInvariant = refl
Invariant.preserved motorPermitChannelsInvariant idle
(guardClosed ∷ stopLoopHealthy ∷ restartRequested ∷ [])
(first ∷ second ∷ []) synchronized = synchronized
Invariant.preserved motorPermitChannelsInvariant risingEdge
(guardClosed ∷ stopLoopHealthy ∷ restartRequested ∷ [])
(first ∷ second ∷ []) synchronized = refl
record AuditedControlSequence : Type₀ where
constructor audited-control-sequence
field
samples : List (Stimulus 3)
open AuditedControlSequence public
RedundantChannelsRemainSynchronized :
AuditedControlSequence → Type₀
RedundantChannelsRemainSynchronized trace =
MotorPermitChannelsSynchronized
(run redundantMotorInterlock
(initial redundantMotorInterlock) (samples trace))
allAuditedControlSequencesPreserveRedundancy :
(trace : AuditedControlSequence) →
RedundantChannelsRemainSynchronized trace
allAuditedControlSequencesPreserveRedundancy
(audited-control-sequence controlSamples) =
Invariant.initial-run-preserves
motorPermitChannelsInvariant controlSamples
record SafetyPanelInput : Type₀ where
constructor safety-panel-input
field
guardDoorClosed : Bit
emergencyStopLoopHealthy : Bit
restartCommandPresent : Bit
open SafetyPanelInput public
panelBits : SafetyPanelInput → Vec Bit 3
panelBits panel =
guardDoorClosed panel
∷ emergencyStopLoopHealthy panel
∷ restartCommandPresent panel
∷ []
record MotorInterlockState : Type₀ where
constructor motor-interlock-state
field
stateBits : Vec Bit 2
open MotorInterlockState public
record RecordedMotorControlCycle : Type₀ where
constructor recorded-motor-control-cycle
field
panel : SafetyPanelInput
before : MotorInterlockState
after : MotorInterlockState
open RecordedMotorControlCycle public
PerimeterGuardDoorIsClosed : RecordedMotorControlCycle → Type₀
PerimeterGuardDoorIsClosed cycle =
guardDoorClosed (panel cycle) ≡ high
EmergencyStopSafetyLoopIsHealthy : RecordedMotorControlCycle → Type₀
EmergencyStopSafetyLoopIsHealthy cycle =
emergencyStopLoopHealthy (panel cycle) ≡ high
RestartCommandIsPresent : RecordedMotorControlCycle → Type₀
RestartCommandIsPresent cycle =
restartCommandPresent (panel cycle) ≡ high
EmergencyStopSafetyLoopIsTripped : RecordedMotorControlCycle → Type₀
EmergencyStopSafetyLoopIsTripped cycle =
emergencyStopLoopHealthy (panel cycle) ≡ low
RecordedRisingEdgeUpdateIsValid : RecordedMotorControlCycle → Type₀
RecordedRisingEdgeUpdateIsValid cycle =
Transition redundantMotorInterlock risingEdge
(panelBits (panel cycle))
(stateBits (before cycle))
(stateBits (after cycle))
BothMotorPermitChannelsAreEnergized :
RecordedMotorControlCycle → Type₀
BothMotorPermitChannelsAreEnergized cycle =
stateBits (after cycle) ≡ high ∷ high ∷ []
BothMotorPermitChannelsAreDeEnergized :
RecordedMotorControlCycle → Type₀
BothMotorPermitChannelsAreDeEnergized cycle =
stateBits (after cycle) ≡ low ∷ low ∷ []
permitBit : Bit → Bit → Bit → Bit
permitBit guardClosed stopLoopHealthy restartRequested =
(guardClosed and stopLoopHealthy) and restartRequested
healthyPermitIsHigh : ∀ guardClosed stopLoopHealthy restartRequested →
guardClosed ≡ high →
stopLoopHealthy ≡ high →
restartRequested ≡ high →
permitBit guardClosed stopLoopHealthy restartRequested ≡ high
healthyPermitIsHigh guardClosed stopLoopHealthy restartRequested
guardClosedProof stopLoopHealthyProof restartRequestedProof =
cong (λ guard → permitBit guard stopLoopHealthy restartRequested)
guardClosedProof
∙ cong (λ stopLoop → permitBit high stopLoop restartRequested)
stopLoopHealthyProof
∙ cong (permitBit high high) restartRequestedProof
trippedPermitIsLow : ∀ guardClosed stopLoopHealthy restartRequested →
stopLoopHealthy ≡ low →
permitBit guardClosed stopLoopHealthy restartRequested ≡ low
trippedPermitIsLow false stopLoopHealthy restartRequested tripProof =
cong (λ stopLoop → permitBit false stopLoop restartRequested) tripProof
trippedPermitIsLow true stopLoopHealthy restartRequested tripProof =
cong (λ stopLoop → permitBit true stopLoop restartRequested) tripProof
healthyRestartEnergizesBothMotorPermitChannels :
(event : RecordedMotorControlCycle) →
PerimeterGuardDoorIsClosed event →
EmergencyStopSafetyLoopIsHealthy event →
RestartCommandIsPresent event →
RecordedRisingEdgeUpdateIsValid event →
BothMotorPermitChannelsAreEnergized event
healthyRestartEnergizesBothMotorPermitChannels
(recorded-motor-control-cycle
(safety-panel-input guardClosed stopLoopHealthy restartRequested)
(motor-interlock-state stateBefore)
(motor-interlock-state stateAfter))
guardClosedProof stopLoopHealthyProof restartRequestedProof transitionProof =
sym transitionProof
∙ cong (λ permit → permit ∷ permit ∷ [])
(healthyPermitIsHigh
guardClosed stopLoopHealthy restartRequested
guardClosedProof stopLoopHealthyProof restartRequestedProof)
emergencyStopTripDropsBothMotorPermitChannels :
(event : RecordedMotorControlCycle) →
EmergencyStopSafetyLoopIsTripped event →
RecordedRisingEdgeUpdateIsValid event →
BothMotorPermitChannelsAreDeEnergized event
emergencyStopTripDropsBothMotorPermitChannels
(recorded-motor-control-cycle
(safety-panel-input guardClosed stopLoopHealthy restartRequested)
(motor-interlock-state stateBefore)
(motor-interlock-state stateAfter))
stopLoopTripped transitionProof =
sym transitionProof
∙ cong (λ permit → permit ∷ permit ∷ [])
(trippedPermitIsLow
guardClosed stopLoopHealthy restartRequested stopLoopTripped)
spartanIndustrialDomain : DomainSpec
spartanIndustrialDomain =
domain-spec
"ff-spartan6-industrial-motor-interlock-v1"
( entity-rule "spartan.industry.entity.audit-trace"
(quote AuditedControlSequence) []L "audited control sequence"
∷L entity-rule "spartan.industry.entity.motor-cycle"
(quote RecordedMotorControlCycle) []L "recorded motor-control cycle"
∷L []L )
( predicate-rule "spartan.industry.predicate.redundancy-preserved"
(quote RedundantChannelsRemainSynchronized)
(semanticExpression ∷L []L)
(unarySuffix
"leaves the two motor-permit register channels synchronized in the final state reached after its sampled control sequence")
∷L predicate-rule "spartan.industry.predicate.guard-closed"
(quote PerimeterGuardDoorIsClosed)
(semanticExpression ∷L []L)
(unarySuffix "reports the perimeter guard door closed")
∷L predicate-rule "spartan.industry.predicate.estop-healthy"
(quote EmergencyStopSafetyLoopIsHealthy)
(semanticExpression ∷L []L)
(unarySuffix "reports the emergency-stop safety loop healthy")
∷L predicate-rule "spartan.industry.predicate.restart-present"
(quote RestartCommandIsPresent)
(semanticExpression ∷L []L)
(unarySuffix "contains an operator restart command")
∷L predicate-rule "spartan.industry.predicate.estop-tripped"
(quote EmergencyStopSafetyLoopIsTripped)
(semanticExpression ∷L []L)
(unarySuffix "reports the emergency-stop safety loop tripped")
∷L predicate-rule "spartan.industry.predicate.valid-rising-update"
(quote RecordedRisingEdgeUpdateIsValid)
(semanticExpression ∷L []L)
(unarySuffix
"is a valid rising-edge update of the redundant motor interlock")
∷L predicate-rule "spartan.industry.predicate.both-permits-high"
(quote BothMotorPermitChannelsAreEnergized)
(semanticExpression ∷L []L)
(unarySuffix "leaves both redundant motor-permit channels energized")
∷L predicate-rule "spartan.industry.predicate.both-permits-low"
(quote BothMotorPermitChannelsAreDeEnergized)
(semanticExpression ∷L []L)
(unarySuffix "leaves both redundant motor-permit channels de-energized")
∷L []L )
[]L []L []L 512
liveInitialRunInvariantTheorem : Name
liveInitialRunInvariantTheorem = quote Invariant.initial-run-preserves
liveSimulationRunTheorem : Name
liveSimulationRunTheorem = quote Simulation.initial-runs-related
liveSimultaneousDomainExample : Name
liveSimultaneousDomainExample = quote StateDomains.two-domain-simultaneous-update
finiteRunExplanation : Explanation
finiteRunExplanation =
explainNameCompact spartanIndustrialDomain
allAuditedControlSequencesPreserveRedundancy
finiteRunExplanationText :
Explanation.text finiteRunExplanation ≡
"For every audited control sequence trace, trace leaves the two motor-permit register channels synchronized in the final state reached after its sampled control sequence."
finiteRunExplanationText = refl
healthyRestartExplanation : Explanation
healthyRestartExplanation =
explainNameCompact spartanIndustrialDomain
healthyRestartEnergizesBothMotorPermitChannels
healthyRestartExplanationText :
Explanation.text healthyRestartExplanation ≡
"For every recorded motor-control cycle event, if event reports the perimeter guard door closed, event reports the emergency-stop safety loop healthy, event contains an operator restart command, and event is a valid rising-edge update of the redundant motor interlock, then event leaves both redundant motor-permit channels energized."
healthyRestartExplanationText = refl
emergencyStopTripExplanation : Explanation
emergencyStopTripExplanation =
explainNameCompact spartanIndustrialDomain
emergencyStopTripDropsBothMotorPermitChannels
emergencyStopTripExplanationText :
Explanation.text emergencyStopTripExplanation ≡
"For every recorded motor-control cycle event, if event reports the emergency-stop safety loop tripped and event is a valid rising-edge update of the redundant motor interlock, then event leaves both redundant motor-permit channels de-energized."
emergencyStopTripExplanationText = refl
finiteRunExplanationProvenance :
Explanation.provenance finiteRunExplanation ≡
( ruleUsed "spartan.industry.entity.audit-trace"
∷L ruleUsed "spartan.industry.predicate.redundancy-preserved"
∷L []L )
finiteRunExplanationProvenance = refl
healthyRestartExplanationProvenance :
Explanation.provenance healthyRestartExplanation ≡
( ruleUsed "spartan.industry.entity.motor-cycle"
∷L ruleUsed "spartan.industry.predicate.guard-closed"
∷L ruleUsed "spartan.industry.predicate.estop-healthy"
∷L ruleUsed "spartan.industry.predicate.restart-present"
∷L ruleUsed "spartan.industry.predicate.valid-rising-update"
∷L ruleUsed "spartan.industry.predicate.both-permits-high"
∷L []L )
healthyRestartExplanationProvenance = refl
emergencyStopTripExplanationProvenance :
Explanation.provenance emergencyStopTripExplanation ≡
( ruleUsed "spartan.industry.entity.motor-cycle"
∷L ruleUsed "spartan.industry.predicate.estop-tripped"
∷L ruleUsed "spartan.industry.predicate.valid-rising-update"
∷L ruleUsed "spartan.industry.predicate.both-permits-low"
∷L []L )
emergencyStopTripExplanationProvenance = refl