@@ -170,27 +170,38 @@ Module GenPromising (IWA : InterfaceWithArch) (TM : TermModelsT IWA).
170170 it generic *)
171171 Structure BasicExecutablePM := {
172172 pModel :> PromisingModel;
173- (** try to compute ALL allowed promises, if that is not possible (not
174- enough fuel) then fail with error message.
175173
176- Soundness and completeness proofs are required to show that when not
177- failing, promise_select effectively computes the allowed_promises
178- set. *)
179- promise_select :
174+ enumerate_promises_and_terminal_states :
180175 (* fuel *) nat → (* tid *) nat →
181176 (* termination condition *) (registerMap → bool) →
182177 memoryMap → pModel.(tState) → PromMemory.t pModel.(mEvent) →
183- Exec.res string pModel.(mEvent);
178+ result string (list pModel.(mEvent) * list pModel.(tState) );
184179
185180 promise_select_sound :
186- ∀ fuel tid term initMem ts mem,
187- ∀ ev ∈ (promise_select fuel tid term initMem ts mem),
188- ev ∈ pModel.(allowed_promises) tid initMem ts mem;
181+ ∀ fuel tid term initMem ts mem promises tstates,
182+ Ok (promises, tstates) =
183+ enumerate_promises_and_terminal_states fuel tid term initMem ts mem →
184+ ∀ ev ∈ promises, ev ∈ pModel.(allowed_promises) tid initMem ts mem;
185+
189186 promise_select_complete :
190- ∀ fuel tid term initMem ts mem,
191- ¬ Exec.has_error (promise_select fuel tid term initMem ts mem) →
192- ∀ ev ∈ pModel.(allowed_promises) tid initMem ts mem,
193- ev ∈ promise_select fuel tid term initMem ts mem
187+ ∀ fuel tid term initMem ts mem promises tstates,
188+ Ok (promises, tstates) =
189+ enumerate_promises_and_terminal_states fuel tid term initMem ts mem →
190+ ∀ ev ∈ pModel.(allowed_promises) tid initMem ts mem, ev ∈ promises;
191+
192+ terminal_state_no_outstanding_promise :
193+ ∀ fuel tid term initMem ts mem promises tstates,
194+ Ok (promises, tstates) =
195+ enumerate_promises_and_terminal_states fuel tid term initMem ts mem →
196+ ∀ tts ∈ tstates, pModel.(tState_nopromises) tts;
197+
198+ terminal_state_is_terminated :
199+ ∀ fuel tid term initMem ts mem promises tstates,
200+ Ok (promises, tstates) =
201+ enumerate_promises_and_terminal_states fuel tid term initMem ts mem →
202+ ∀ tts ∈ tstates, term (pModel.(tState_regs) tts);
203+
204+ (* TODO: add terminal_state_is_reachable *)
194205 }.
195206 Arguments BasicExecutablePM : clear implicits.
196207
@@ -328,10 +339,24 @@ Module GenPromising (IWA : InterfaceWithArch) (TM : TermModelsT IWA).
328339 Local Notation mEvent := (mEvent prom).
329340 Local Notation t := (t tState mEvent n).
330341
342+ (** The type of final promising state return by run *)
343+ Definition final := { x : t | terminated prom term x }.
344+
345+ Definition make_final (p : t) := exist (terminated prom term) p.
346+
347+ (** Convert a final promising state to a generic final state *)
348+ Program Definition to_final_archState (f : final) :
349+ {s & archState.is_terminated term s} :=
350+ existT (to_archState prom f) _.
351+ Solve All Obligations with
352+ hauto unfold:terminated unfold:archState.is_terminated l:on db:vec, brefl.
353+
331354 (** Get a list of possible promises for a thread by tid *)
332355 Definition promise_select_tid (fuel : nat) (st : t)
333356 (tid : fin n) : Exec.res string mEvent :=
334- prom.(promise_select) fuel tid (term tid) (initmem st) (tstate tid st) (events st).
357+ '(promises, _) ← mlift $ prom.(enumerate_promises_and_terminal_states)
358+ fuel tid (term tid) (initmem st) (tstate tid st) (events st);
359+ mchoosel promises.
335360
336361 (** Take any promising step for that tid and promise it *)
337362 Definition cpromise_tid (fuel : nat) (tid : fin n)
@@ -355,19 +380,6 @@ Module GenPromising (IWA : InterfaceWithArch) (TM : TermModelsT IWA).
355380 promise ← mchoosel (enum bool);
356381 if (promise : bool) then cpromise_tid fuel tid else run_tid isem prom tid.
357382
358- (** The type of final promising state return by run *)
359- Definition final := { x : t | terminated prom term x }.
360-
361- Definition make_final (p : t) := exist (terminated prom term) p.
362-
363-
364- (** Convert a final promising state to a generic final state *)
365- Program Definition to_final_archState (f : final) :
366- {s & archState.is_terminated term s} :=
367- existT (to_archState prom f) _.
368- Solve All Obligations with
369- hauto unfold:terminated unfold:archState.is_terminated l:on db:vec, brefl.
370-
371383 (** Computational evaluate all the possible allowed final states according
372384 to the promising model prom starting from st *)
373385 Fixpoint run (fuel : nat) : Exec.t t string final :=
@@ -378,19 +390,79 @@ Module GenPromising (IWA : InterfaceWithArch) (TM : TermModelsT IWA).
378390 run_step (S fuel);;
379391 run fuel
380392 else mthrow "Could not finish running within the size of the fuel".
393+
394+ (** Explore all possible promise-based executions across all threads. *)
395+ Fixpoint prune_promises_and_states (fuel_per_tid fuel : nat)
396+ (finals : list final) : Exec.t t string (list final) :=
397+ if fuel is S fuel then
398+ st ← mGet;
399+ (* Find out next possible promises or terminating states at the current thread *)
400+ executions ←
401+ for (tid : fin n) in enum (fin n) do
402+ '(promises_per_tid, tstates_per_tid) ←
403+ mlift $ prom.(enumerate_promises_and_terminal_states)
404+ fuel_per_tid tid (term tid) (initmem st) (tstate tid st) (events st);
405+ mret (map (λ ev, (ev, tid)) promises_per_tid, tstates_per_tid)
406+ end ;
407+
408+ (* Compute cartesian products of the possible thread states *)
409+ let tstates_sys :=
410+ fold_left (λ partial_sts tstates_tid,
411+ List.flat_map (λ tstate,
412+ if is_emptyb partial_sts then [[tstate]]
413+ else map (λ partial_st, partial_st ++ [tstate]) partial_sts
414+ ) tstates_tid
415+ ) (map snd executions) [] in
416+ let new_finals :=
417+ omap (λ tstates,
418+ if (list_to_vec_n n tstates) is Some tstates_vec then
419+ let st := Make tstates_vec st.(PState.initmem) st.(PState.events) in
420+ if decide $ terminated prom term st is left pt
421+ then Some (make_final st pt)
422+ else None
423+ else None
424+ ) tstates_sys in
425+
426+ (* Non-deterministically choose the next promise and the tid for pruning *)
427+ let promises_all := List.concat (map fst executions) in
428+ if is_emptyb promises_all then
429+ mret (new_finals ++ finals)
430+ else
431+ '(next_ev, tid) ← mchoosel promises_all;
432+ mSet (λ st, promise_tid prom st tid next_ev);;
433+ prune_promises_and_states fuel_per_tid fuel (new_finals ++ finals)
434+ else mret finals.
435+
436+ (** Computational evaluate all the possible allowed final states according
437+ to the promising model prom starting from st
438+ with promise-first optimization *)
439+ Definition run_promise_first (fuel : nat) : Exec.t t string final :=
440+ finals ← prune_promises_and_states fuel fuel [];
441+ mchoosel finals.
442+
381443 End CPS.
382444 Arguments to_final_archState {_ _ _}.
383445 End CPState.
384446
385447 (** Create a computational model from an ISA model and promising model *)
386448 Definition Promising_to_Modelc (isem : iMon ()) (prom : BasicExecutablePM)
387449 (fuel : nat) : archModel.c ∅ :=
388- fun n term (initMs : archState n) =>
450+ λ n term (initMs : archState n),
389451 PState.from_archState prom initMs |>
390452 archModel.Res.from_exec
391453 $ CPState.to_final_archState
392454 <$> CPState.run isem prom term fuel.
393455
456+ (** Create a computational model from an ISA model and promising model
457+ with promise-free optimization *)
458+ Definition Promising_to_Modelc_pf (isem : iMon ()) (prom : BasicExecutablePM)
459+ (fuel : nat) : archModel.c ∅ :=
460+ λ n term (initMs : archState n),
461+ PState.from_archState prom initMs |>
462+ archModel.Res.from_exec
463+ $ CPState.to_final_archState
464+ <$> CPState.run_promise_first prom term fuel.
465+
394466 (* TODO state some soundness lemma between Promising_to_Modelnc and
395467 Promising_Modelc *)
396468
0 commit comments