@@ -183,27 +183,38 @@ Module GenPromising (IWA : InterfaceWithArch) (TM : TermModelsT IWA).
183183 it generic *)
184184 Structure BasicExecutablePM := {
185185 pModel :> PromisingModel;
186- (** try to compute ALL allowed promises, if that is not possible (not
187- enough fuel) then fail with error message.
188186
189- Soundness and completeness proofs are required to show that when not
190- failing, promise_select effectively computes the allowed_promises
191- set. *)
192- promise_select :
187+ enumerate_promises_and_terminal_states :
193188 (* fuel *) nat → (* tid *) nat →
194189 (* termination condition *) (registerMap → bool) →
195190 memoryMap → pModel.(tState) → PromMemory.t pModel.(mEvent) →
196- Exec.res string pModel.(mEvent);
191+ result string (list pModel.(mEvent) * list pModel.(tState) );
197192
198193 promise_select_sound :
199- ∀ fuel tid term initMem ts mem,
200- ∀ ev ∈ (promise_select fuel tid term initMem ts mem),
201- ev ∈ pModel.(allowed_promises) tid initMem ts mem;
194+ ∀ fuel tid term initMem ts mem promises tstates,
195+ Ok (promises, tstates) =
196+ enumerate_promises_and_terminal_states fuel tid term initMem ts mem →
197+ ∀ ev ∈ promises, ev ∈ pModel.(allowed_promises) tid initMem ts mem;
198+
202199 promise_select_complete :
203- ∀ fuel tid term initMem ts mem,
204- ¬ Exec.has_error (promise_select fuel tid term initMem ts mem) →
205- ∀ ev ∈ pModel.(allowed_promises) tid initMem ts mem,
206- ev ∈ promise_select fuel tid term initMem ts mem
200+ ∀ fuel tid term initMem ts mem promises tstates,
201+ Ok (promises, tstates) =
202+ enumerate_promises_and_terminal_states fuel tid term initMem ts mem →
203+ ∀ ev ∈ pModel.(allowed_promises) tid initMem ts mem, ev ∈ promises;
204+
205+ terminal_state_no_outstanding_promise :
206+ ∀ fuel tid term initMem ts mem promises tstates,
207+ Ok (promises, tstates) =
208+ enumerate_promises_and_terminal_states fuel tid term initMem ts mem →
209+ ∀ tts ∈ tstates, pModel.(tState_nopromises) tts;
210+
211+ terminal_state_is_terminated :
212+ ∀ fuel tid term initMem ts mem promises tstates,
213+ Ok (promises, tstates) =
214+ enumerate_promises_and_terminal_states fuel tid term initMem ts mem →
215+ ∀ tts ∈ tstates, term (pModel.(tState_regs) tts);
216+
217+ (* TODO: add terminal_state_is_reachable *)
207218 }.
208219 Arguments BasicExecutablePM : clear implicits.
209220
@@ -341,10 +352,24 @@ Module GenPromising (IWA : InterfaceWithArch) (TM : TermModelsT IWA).
341352 Local Notation mEvent := (mEvent prom).
342353 Local Notation t := (t tState mEvent n).
343354
355+ (** The type of final promising state return by run *)
356+ Definition final := { x : t | terminated prom term x }.
357+
358+ Definition make_final (p : t) := exist (terminated prom term) p.
359+
360+ (** Convert a final promising state to a generic final state *)
361+ Program Definition to_final_archState (f : final) :
362+ {s & archState.is_terminated term s} :=
363+ existT (to_archState prom f) _.
364+ Solve All Obligations with
365+ hauto unfold:terminated unfold:archState.is_terminated l:on db:vec, brefl.
366+
344367 (** Get a list of possible promises for a thread by tid *)
345368 Definition promise_select_tid (fuel : nat) (st : t)
346369 (tid : fin n) : Exec.res string mEvent :=
347- prom.(promise_select) fuel tid (term tid) (initmem st) (tstate tid st) (events st).
370+ '(promises, _) ← mlift $ prom.(enumerate_promises_and_terminal_states)
371+ fuel tid (term tid) (initmem st) (tstate tid st) (events st);
372+ mchoosel promises.
348373
349374 (** Take any promising step for that tid and promise it *)
350375 Definition cpromise_tid (fuel : nat) (tid : fin n)
@@ -368,45 +393,6 @@ Module GenPromising (IWA : InterfaceWithArch) (TM : TermModelsT IWA).
368393 promise ← mchoosel (enum bool);
369394 if (promise : bool) then cpromise_tid fuel tid else run_tid isem prom tid.
370395
371- (** Run only promise steps. If a thread has reached termination
372- no progress is made in the thread (either instruction running or
373- promises *)
374- Fixpoint run_step_promise_first (fuel : nat) (terminated : fin n -> bool) : Exec.t t string () :=
375- st ← mGet;
376- let all_terminated := ∀ tid ∈ (enum (fin n)), terminated tid in
377- if decide all_terminated then
378- mret ()
379- else
380- if fuel is S fuel then
381- tid ← mchoose n;
382- if decide $ (terminated tid) then
383- run_step_promise_first fuel terminated
384- else
385- let ev_res := promise_select_tid fuel st tid in
386- if decide (Exec.has_error ev_res) then
387- run_step_promise_first fuel (λ t, if decide (t = tid) then true else (terminated t))
388- else
389- let res_st :=
390- ev ← ev_res;
391- mret $ promise_tid prom st tid ev
392- in
393- mlift $ Exec.make ((.,()) <$> res_st.(Exec.results)) ((st,.) <$> res_st.(Exec.errors));;
394- run_step_promise_first fuel terminated
395- else mthrow "Could not finish promise-first within the size of the fuel".
396-
397- (** The type of final promising state return by run *)
398- Definition final := { x : t | terminated prom term x }.
399-
400- Definition make_final (p : t) := exist (terminated prom term) p.
401-
402-
403- (** Convert a final promising state to a generic final state *)
404- Program Definition to_final_archState (f : final) :
405- {s & archState.is_terminated term s} :=
406- existT (to_archState prom f) _.
407- Solve All Obligations with
408- hauto unfold:terminated unfold:archState.is_terminated l:on db:vec, brefl.
409-
410396 (** Computational evaluate all the possible allowed final states according
411397 to the promising model prom starting from st *)
412398 Fixpoint run (fuel : nat) : Exec.t t string final :=
@@ -418,52 +404,77 @@ Module GenPromising (IWA : InterfaceWithArch) (TM : TermModelsT IWA).
418404 run fuel
419405 else mthrow "Could not finish running within the size of the fuel".
420406
421- (** Computational evaluate all the possible allowed final states according
422- to the promising model prom starting from st *)
423- Fixpoint run_promise_first (fuel : nat) : Exec.t t string final :=
424- st ← mGet;
425- if decide $ terminated prom term st is left pt then mret (make_final st pt)
426- else
427- if fuel is S fuel then
428- run_step_promise_first (S fuel);;
429- run_promise_first fuel
407+ (** Explore all possible promise-based executions across all threads. *)
408+ Fixpoint prune_promises_and_states (fuel_per_tid fuel : nat)
409+ (finals : list final) : Exec.t t string (list final) :=
410+ if fuel is S fuel then
411+ st ← mGet;
412+ (* Find out next possible promises or terminating states at the current thread *)
413+ executions ←
414+ for (tid : fin n) in enum (fin n) do
415+ '(promises_per_tid, tstates_per_tid) ←
416+ mlift $ prom.(enumerate_promises_and_terminal_states)
417+ fuel_per_tid tid (term tid) (initmem st) (tstate tid st) (events st);
418+ mret (map (λ ev, (ev, tid)) promises_per_tid, tstates_per_tid)
419+ end ;
420+
421+ (* Compute cartesian products of the possible thread states *)
422+ let tstates_sys :=
423+ fold_left (λ partial_sts tstates_tid,
424+ List.flat_map (λ tstate,
425+ if is_emptyb partial_sts then [[tstate]]
426+ else map (λ partial_st, partial_st ++ [tstate]) partial_sts
427+ ) tstates_tid
428+ ) (map snd executions) [] in
429+ let new_finals :=
430+ omap (λ tstates,
431+ if (list_to_vec_n n tstates) is Some tstates_vec then
432+ let st := Make tstates_vec st.(PState.initmem) st.(PState.events) in
433+ if decide $ terminated prom term st is left pt
434+ then Some (make_final st pt)
435+ else None
436+ else None
437+ ) tstates_sys in
438+
439+ (* Non-deterministically choose the next promise and the tid for pruning *)
440+ let promises_all := List.concat (map fst executions) in
441+ if is_emptyb promises_all then
442+ mret (new_finals ++ finals)
443+ else
444+ '(next_ev, tid) ← mchoosel promises_all;
445+ mSet (λ st, promise_tid prom st tid next_ev);;
446+ prune_promises_and_states fuel_per_tid fuel (new_finals ++ finals)
447+ else mret finals.
430448
431449 (** Computational evaluate all the possible allowed final states according
432450 to the promising model prom starting from st
433451 with promise-first optimization *)
434452 Definition run_promise_first (fuel : nat) : Exec.t t string final :=
435- st ← mGet;
436- (* Execute promise-first *)
437- run_step_promise_first fuel;;
453+ finals ← prune_promises_and_states fuel fuel [];
454+ mchoosel finals.
438455
439- if decide $ terminated prom term st is left pt then mret (make_final st pt)
440- else
441- if fuel is S fuel then
442- run_step (S fuel);;
443- run fuel
444- else mthrow "Could not finish running within the size of the fuel".
445456 End CPS.
446457 Arguments to_final_archState {_ _ _}.
447458 End CPState.
448459
449460 (** Create a computational model from an ISA model and promising model *)
450461 Definition Promising_to_Modelc (isem : iMon ()) (prom : BasicExecutablePM)
451462 (fuel : nat) : archModel.c ∅ :=
452- fun n term (initMs : archState n) =>
463+ λ n term (initMs : archState n),
453464 PState.from_archState prom initMs |>
454465 archModel.Res.from_exec
455466 $ CPState.to_final_archState
456467 <$> CPState.run isem prom term fuel.
457468
458469 (** Create a computational model from an ISA model and promising model
459470 with promise-free optimization *)
460- Definition Promising_to_Modelc_promise_first (isem : iMon ()) (prom : BasicExecutablePM)
471+ Definition Promising_to_Modelc_pf (isem : iMon ()) (prom : BasicExecutablePM)
461472 (fuel : nat) : archModel.c ∅ :=
462- fun n term (initMs : archState n) =>
473+ λ n term (initMs : archState n),
463474 PState.from_archState prom initMs |>
464475 archModel.Res.from_exec
465476 $ CPState.to_final_archState
466- <$> CPState.run_promise_first isem prom term fuel.
477+ <$> CPState.run_promise_first prom term fuel.
467478
468479 (* TODO state some soundness lemma between Promising_to_Modelnc and
469480 Promising_Modelc *)
0 commit comments