typed: model checking improvements

This commit is contained in:
Sam Caldwell 2022-06-17 15:59:20 -04:00
parent 798e66dc8c
commit 43cc25ea1b
2 changed files with 98 additions and 40 deletions

View File

@ -19,12 +19,22 @@
;; a SpinProgram is a
;; (sprog Assignment [Listof SpinProcess] MessageTable SpinLTL NameEnvironment)
(struct sprog [assignment procs spec msg-tabe name-env] #:transparent)
;; (sprog Assignment
;; [Listof SpinProcess]
;; MessageTable
;; SpinLTL
;; [Setof SName]
;; NameEnvironment)
(struct sprog [assignment procs spec msg-tabe assertion-tys name-env] #:transparent)
;; a SpinProcess is a
;; (sproc SName [Setof SName] Assignment [Listof SAction] [Setof SpinState])
(struct sproc [name state-names locals init-actions states] #:transparent)
;; (sproc SName
;; [Setof SName]
;; SName
;; Assignment
;; [Listof SAction]
;; [Setof SpinState])
(struct sproc [name state-names st0 locals init-actions states] #:transparent)
;; an Assignment is a [Hashof SVar SValue]
@ -59,6 +69,7 @@
;; a SAction is one of
;; - (assert ?)
;; - (retract ?)
;; - (unlearn ?)
;; - (send ?)
;; - (incorporate D+)
;; - (add-message-interest ?)
@ -66,6 +77,7 @@
;; - (transition-to SName)
(struct assert [ty] #:prefab)
(struct retract [ty] #:prefab)
(struct unlearn [ty] #:prefab)
(struct add-message-interest [ty] #:prefab)
(struct remove-message-interest [ty] #:prefab)
;; send defined in proto.rkt
@ -101,12 +113,13 @@
(define name-env (make-name-env all-mentioned-tys))
(define procs (for/list ([rg rgs]) (rg->spin rg event-subty# name-env)))
(define assertion-vars (initial-assertion-vars-for all-assertion-tys name-env))
(define assertion-nms (for/set ([τ (in-set all-assertion-tys)]) (hash-ref name-env τ)))
(define messages-vars (initial-message-vars-for msg-bodies name-env))
(define mailbox-vars (initial-mailbox-vars msg-bodies (map sproc-name procs) name-env))
(define msg-table (make-message-table message-tys msg-event-tys name-env))
(define globals (hash-union assertion-vars messages-vars mailbox-vars))
(define spec-spin (rename-ltl spec name-env))
(sprog globals procs spec-spin msg-table name-env))
(sprog globals procs spec-spin msg-table assertion-nms name-env))
;; [Setof τ] [Setof τ] NameEnvironment -> MessageTable
(define (make-message-table message-tys msg-event-tys name-env)
@ -132,19 +145,22 @@
(define all-events (all-event-types (in-hash-values states)))
(define state-renaming (make-state-rename (hash-keys states)))
(define states- (for/list ([st (in-hash-values states)])
(state->spin st states event-subty# name-env state-renaming)))
(state->spin st states all-events event-subty# name-env state-renaming)))
(define st0- (hash-ref state-renaming st0))
;; ergh the invariant for when I tack on _assertions to a name is getting tricksy
(define st0-asserts (state-assertions (hash-ref states st0)))
(define st0-msg-interests (message-transitions (state-transitions (hash-ref states st0))))
(define initial-asserts (transition-assertions (set) st0-asserts event-subty# name-env))
(define initial-asserts (transition-assertions (set) st0-asserts all-events event-subty# name-env))
(define initial-msg-interests (transition-msg-interests (set) st0-msg-interests event-subty# name-env))
(define init-acts (append initial-asserts initial-msg-interests))
(define assignment (local-variables-for st0- all-events name-env))
(sproc name (hash-values-set state-renaming) assignment init-acts (list->set states-)))
(define relevant-assertions (for/set ([evt (in-set all-events)]
#:unless (Message? evt))
(hash-ref name-env evt)))
(sproc name (hash-values-set state-renaming) st0- relevant-assertions init-acts (list->set states-)))
;; State [Sequenceof State] [Hashof τ [Setof τ]] NameEnvironment [Hashof StateName SName] -> SpinState
(define (state->spin st states event-subty# name-env state-env)
;; State [Sequenceof State] [Setof [U τ (Message τ)]] [Hashof τ [Setof τ]] NameEnvironment [Hashof StateName SName] -> SpinState
(define (state->spin st states all-events event-subty# name-env state-env)
(match-define (state name transitions assertions) st)
(define name- (hash-ref state-env name))
(define msg-txns (message-transitions transitions))
@ -154,7 +170,7 @@
(match-define (state _ dest-txns dest-assertions) (hash-ref states dest))
(define dest- (hash-ref state-env dest))
(define dest-msg-txns (message-transitions dest-txns))
(branch-on D+ assertions msg-txns dest- dest-assertions dest-msg-txns effs event-subty# name-env)))
(branch-on D+ assertions msg-txns dest- dest-assertions dest-msg-txns effs all-events event-subty# name-env)))
(sstate name- branches))
;; (Hashof D+ _) -> (Setof τ)
@ -183,6 +199,10 @@
(define (assertions-var-name s)
(string->symbol (format "~a_assertions" s)))
;; SName -> SName
(define (assertions-update-var-name s)
(string->symbol (format "~a_update" s)))
;; SName -> SName
(define (active-var-name s)
(string->symbol (format "know_~a" s)))
@ -221,8 +241,10 @@
;; [Setof τ] NameEnvironment -> Assignment
(define (initial-assertion-vars-for assertion-tys name-env)
(for/hash ([τ (in-set assertion-tys)])
(values (svar (assertions-var-name (hash-ref name-env τ)) SInt)
(for*/hash ([τ (in-set assertion-tys)]
[bucket? (in-list '(#t #f))])
(define namer (if bucket? assertions-var-name assertions-update-var-name))
(values (svar (namer (hash-ref name-env τ)) SInt)
0)))
;; [Setof τ] NameEnvironment -> Assignment
@ -282,7 +304,7 @@
(set-union as (all-events-of rg)))
)
;; [Sequenceof State] -> ?
;; [Sequenceof State] -> [Setof [U τ (Message τ)]]
(define (all-event-types states)
(for*/set ([st states]
[D+ (in-hash-keys (state-transitions st))])
@ -330,11 +352,18 @@
(values (svar (active-var-name (hash-ref name-env evt))
SBool)
#f)))
(hash-set assign CURRENT-STATE st0))
assign
#;(hash-set assign CURRENT-STATE st0))
;; D+ [Setof τ] [Setof τ] SName [Setof τ] [Setof τ] [Listof TransitionEffect] [Hashof τ [Setof τ]] NameEnvironment -> SBranch
(define (branch-on D+ curr-assertions curr-msg-txns dest dest-assertions dest-msg-txns effs event-subty# name-env)
(define assertion-updates (transition-assertions curr-assertions dest-assertions event-subty# name-env))
;; [Setof SName] -> Void
(define (update-knowledge relevant-assertions)
(for ([assert-nm (in-set relevant-assertions)])
(define know-nm (active-var-name assert-nm))
(indent) (printf "~a = (~a -> ASSERTED(~a) : ~a);\n" know-nm know-nm assert-nm know-nm)))
;; D+ [Setof τ] [Setof τ] SName [Setof τ] [Setof τ] [Listof TransitionEffect] [Setof [U τ (Message τ)]] [Hashof τ [Setof τ]] NameEnvironment -> SBranch
(define (branch-on D+ curr-assertions curr-msg-txns dest dest-assertions dest-msg-txns effs all-events event-subty# name-env)
(define assertion-updates (transition-assertions curr-assertions dest-assertions all-events event-subty# name-env))
(define msg-interest-updates (transition-msg-interests curr-msg-txns dest-msg-txns event-subty# name-env))
(define effs- (rename-effects effs name-env))
(define renamed-evt (rename-event D+ name-env))
@ -344,14 +373,18 @@
msg-interest-updates
effs-))))
;; [Setof τ] [Setof τ] [Hashof τ [Setof τ]] NameEnvironment -> [Listof SAction]
(define (transition-assertions curr-assertions dest-assertions event-subty# name-env)
;; [Setof τ] [Setof τ] [Setof [U τ (Message τ)]] [Hashof τ [Setof τ]] NameEnvironment -> [Listof SAction]
(define (transition-assertions curr-assertions dest-assertions all-events event-subty# name-env)
(define new-assertions (super-type-closure (set-subtract dest-assertions curr-assertions) event-subty#))
(define retractions (super-type-closure (set-subtract curr-assertions dest-assertions) event-subty#))
(define (lookup ty) (hash-ref name-env ty))
(define asserts (set-map new-assertions (compose assert lookup)))
(define retracts (set-map retractions (compose retract lookup)))
(append asserts retracts))
(define unlearns (for/list ([τ (in-set retractions)]
#:when (and (Observe? τ)
(set-member? all-events (Observe-ty τ))))
(unlearn (lookup (Observe-ty τ)))))
(append asserts retracts unlearns))
;; [Setof τ] [Setof τ] [Hashof τ [Setof τ]] NameEnvironment -> [Listof SAction]
(define (transition-msg-interests curr-msg-txns dest-msg-txns event-subty# name-env)
@ -557,7 +590,7 @@
;; SpinProgram -> Void
(define (gen-spin prog)
(match prog
[(sprog assignment procs spec msg-table name-env)
[(sprog assignment procs spec msg-table assertion-tys name-env)
(display SPIN-PRELUDE)
(gen-assignment assignment)
(newline)
@ -565,7 +598,7 @@
(for ([p procs])
(gen-spin-proc p name-env)
(newline))
(gen-clock-ticker (map sproc-name procs) msg-table)
(gen-clock-ticker (map sproc-name procs) msg-table assertion-tys)
(newline)
(gen-spec "spec" (lambda () (gen-ltl spec)))
(newline)
@ -622,16 +655,24 @@
(define (gen-spin-break)
(indent) (displayln "break;"))
(define (gen-spin-skip)
(indent) (displayln "skip;"))
;; SpinProcess NameEnvironment -> Void
(define (gen-spin-proc proc name-env)
(match-define (sproc name state-names locals init-actions states) proc)
(match-define (sproc name state-names st0 relevant-assertions init-actions states) proc)
(define my-clock (proc-clock-var name))
(define locals (for/hash ([evt (in-set relevant-assertions)])
(values (svar (active-var-name evt)
SBool)
#f)))
(indent) (declare-mtype state-names)
(indent) (gen-assign my-clock GLOBAL-CLOCK-INIT-VAL #:declare #t)
(indent) (printf "active proctype ~a() {\n" name)
(with-indent
(gen-assign CURRENT-STATE st0 #:declare #t)
(gen-assignment locals)
(with-spin-dstep
(with-spin-atomic
(for ([a init-actions])
(gen-spin-form a name-env name)))
(indent) (printf "~a: do\n" (format-end-label name))
@ -639,10 +680,11 @@
(with-spin-branch "true"
(indent) (printf "~a;\n" (clock-predicate my-clock))
(with-spin-atomic
(indent) (update-clock my-clock)
(with-spin-if
(for ([st states])
(gen-spin-form st name-env name))))))
(indent) (update-clock my-clock)
(with-spin-do
(for ([st states])
(gen-spin-form st name-env name)))
(update-knowledge relevant-assertions))))
(indent) (displayln "od;"))
(indent) (displayln "}"))
@ -654,14 +696,14 @@
(cond
[(empty? branches)
;; no transitions out of this state
(gen-spin-break)
#;(gen-spin-skip) (gen-spin-break)
]
[else
(with-indent
(with-spin-do
(with-spin-if
(for ([branch branches])
(gen-spin-form branch name-env proc-name))
(gen-spin-branch "else" gen-spin-break)))])]
(gen-spin-branch "else" #;gen-spin-skip gen-spin-break)))])]
[(sbranch event dest actions)
(indent) (printf ":: ~a -> ~a\n" (predicate-for event proc-name) (embed-event-as-comment event name-env))
(with-indent
@ -672,6 +714,8 @@
(indent) (printf "ASSERT(~a); ~a\n" x (embed-value-as-comment assert x name-env))]
[(retract x)
(indent) (printf "RETRACT(~a); ~a\n" x (embed-value-as-comment retract x name-env))]
[(unlearn x)
(indent) (printf "~a = false;\n" (active-var-name x))]
[(send x)
(indent) (printf "SEND(~a); ~a\n" x (embed-value-as-comment send x name-env))]
[(add-message-interest x)
@ -686,7 +730,7 @@
(indent) (printf "~a = ~a;\n" (svar-name CURRENT-STATE) dest)]))
;; [Listof SName] MessageTable -> Void
(define (gen-clock-ticker proc-names msg-table)
(define (gen-clock-ticker proc-names msg-table assertion-tys)
(define clock-names (for/list ([pn (in-list proc-names)])
(svar-name (proc-clock-var pn))))
(indent) (displayln "active proctype __clock_ticker__() {")
@ -696,6 +740,7 @@
(with-spin-branch (all-procs-ready-predicate clock-names)
(with-spin-dstep
(indent) (update-clock GLOBAL-CLOCK-VAR (format-as-comment TURN-BEGIN-EVENT))
(update-all-assertion-vars assertion-tys)
(unless (hash-empty? msg-table)
(with-spin-do
(gen-spin-branch "else" gen-spin-break)
@ -703,6 +748,15 @@
(gen-msg-dispatch sent-msg matching-evts proc-names))))))))
(indent) (displayln "}"))
;; (Setof SName) -> Void
;; update the assertion bucket variables based on the update variables
(define (update-all-assertion-vars assertion-nms)
(for ([assertion (in-set assertion-nms)])
(define bucket (assertions-var-name assertion))
(define update (assertions-update-var-name assertion))
(indent) (printf "~a = ~a + ~a;\n" bucket bucket update)
(indent) (printf "~a = 0;\n" update)))
;; SName (Setof SName) [Listof SName] -> Void
(define (gen-msg-dispatch sent-msg matching-evts proc-names)
(define mailbox-nm (messages-var-name sent-msg))
@ -758,7 +812,7 @@
;; SType -> String
(define (spin-type->string ty)
(match ty
[(== SInt) "int"]
[(== SInt) "short"]
[(== SBool) "bool"]
[(== mtype) "mtype"]))
@ -982,11 +1036,15 @@ Examples:
(define (analyze-spin-trail spin-file)
(define-values (_ out __) (run-script REPLAY-TRAIL.EXE (list spin-file)))
#;(pretty-display out)
(define pid/line-trace (regexp-match* TRAIL-LINE-RX out #:match-select cdr))
(define model-lines (file->vector spin-file))
(define trace (interpret-spin-trace pid/line-trace model-lines))
(define trace (spin-trace->syndicate-trace out spin-file))
(print-trace trace)
(log-trace-msd trace))
#;(log-trace-msd trace))
;; String Path -> (Listof TraceStep)
(define (spin-trace->syndicate-trace spin-out spin-file)
(define pid/line-trace (regexp-match* TRAIL-LINE-RX spin-out #:match-select cdr))
(define model-lines (file->vector spin-file))
(interpret-spin-trace pid/line-trace model-lines))
;; String (Listof String) -> (Values Bool String String)
(define (run-script cmd args)

View File

@ -2,8 +2,8 @@
#define ASSERTED(x) (x##_assertions > 0)
#define RETRACTED(x) (x##_assertions == 0)
#define ASSERT(x) x##_assertions = x##_assertions + 1
#define RETRACT(x) x##_assertions = x##_assertions - 1
#define ASSERT(x) x##_update = x##_update + 1
#define RETRACT(x) x##_update = x##_update - 1
#define SEND(x) x##_messages = x##_messages + 1
/* Rest of Program */