From Coq Require Import List Permutation.
Import List.ListNotations.
Open Scope list_scope.
From Velus Require Import Common.
From Velus Require Import Environment.
From Velus Require Import FunctionalEnvironment.
From Velus Require Import Operators.
From Velus Require Import Clocks.
From Velus Require Import CommonProgram.
From Velus Require Import Fresh.
From Velus Require Import CoreExpr.CESyntax.
From Velus Require Import Stc.StcSyntax.
Module Type EXT_CC
(
Ids :
IDS)
(
Op :
OPERATORS)
(
OpAux :
OPERATORS_AUX Ids Op)
(
Cks :
CLOCKS Ids Op OpAux)
(
CESyn :
CESYNTAX Ids Op OpAux Cks)
(
Syn :
STCSYNTAX Ids Op OpAux Cks CESyn).
In the returned list a pair (x, y) indicates
that x should be cut in transition constraint y
Parameter cutting_points :
list ident ->
list ident ->
list Syn.trconstr ->
list ident.
End EXT_CC.
Module Type CC
(
Import Ids :
IDS)
(
Import Op :
OPERATORS)
(
OpAux :
OPERATORS_AUX Ids Op)
(
Import Cks :
CLOCKS Ids Op OpAux)
(
Import CESyn :
CESYNTAX Ids Op OpAux Cks)
(
Import Syn :
STCSYNTAX Ids Op OpAux Cks CESyn)
(
ECC :
EXT_CC Ids Op OpAux Cks CESyn Syn).
Module Fresh :=
Fresh.Fresh(
Ids).
Import Fresh Notations Facts Tactics.
Local Open Scope fresh_monad_scope.
Section rename.
Variable x :
var_last.
Variable y :
ident.
Definition rename_var id :=
match x with
|
Var x =>
if id ==
b x then y else id
|
_ =>
id
end.
Fixpoint rename_clock (
ck :
clock) :=
match ck with
|
Cbase =>
Cbase
|
Con ck x (
ty,
k) =>
Con (
rename_clock ck) (
rename_var x) (
ty,
k)
end.
Fixpoint rename_exp (
e :
exp) :=
match e with
|
Econst _ |
Eenum _ _ =>
e
|
Evar x ty =>
Evar (
rename_var x)
ty
|
Elast id ty =>
match x with
|
Last x =>
if id ==
b x then Evar y ty else Elast id ty
|
_ =>
Elast id ty
end
|
Ewhen e (
x,
ty)
k =>
Ewhen (
rename_exp e) (
x,
ty)
k
|
Eunop op e1 ty =>
Eunop op (
rename_exp e1)
ty
|
Ebinop op e1 e2 ty =>
Ebinop op (
rename_exp e1) (
rename_exp e2)
ty
end.
Fixpoint rename_cexp (
e :
cexp) :=
match e with
|
Emerge (
x,
tx)
es ty =>
Emerge (
x,
tx) (
map rename_cexp es)
ty
|
Ecase e es d =>
Ecase (
rename_exp e) (
map (
option_map rename_cexp)
es) (
rename_cexp d)
|
Eexp e =>
Eexp (
rename_exp e)
end.
Definition rename_rhs (
e :
rhs) :=
match e with
|
Eextcall f es ty =>
Eextcall f (
map rename_exp es)
ty
|
Ecexp e =>
Ecexp (
rename_cexp e)
end.
End rename.
Definition rename_trconstr x y (
tc :
trconstr) :=
match tc with
|
TcDef ck i'
rhs =>
TcDef ck i' (
rename_rhs x y rhs)
|
TcReset _ _ =>
tc
|
TcUpdate ck ckrs (
UpdLast i e) =>
if var_last_ident x ==
b i then tc
else TcUpdate ck ckrs (
UpdLast i (
rename_cexp x y e))
|
TcUpdate ck ckrs (
UpdNext i e) =>
if var_last_ident x ==
b i then tc
else TcUpdate ck ckrs (
UpdNext i (
rename_exp x y e))
|
TcUpdate ck ckrs (
UpdInst i'
xs f es) =>
match x with
|
Last _ =>
TcUpdate ck ckrs (
UpdInst i'
xs f (
map (
rename_exp x y)
es))
|
Var _ =>
tc
end
end.
System
Definition FreshAnn A :=
Fresh stc A (
type *
clock).
Definition cut_cycles_tcs (
lasts nexts:
list (
ident * (
const *
type *
clock)))
tcs :
FreshAnn (
list trconstr) :=
do nlasts <-
fresh_idents (
map (
fun '(
x, (
_,
ty,
ck)) => (
x, (
ty,
ck)))
lasts);
let tcs :=
fold_left (
fun tcs '(
x,
lx,
_) =>
map (
rename_trconstr (
Last x)
lx)
tcs)
nlasts tcs in
let eqlasts :=
map (
fun '(
x,
lx, (
ty,
ck)) =>
TcDef ck lx (
Ecexp (
Eexp (
Elast x ty))))
nlasts in
do nnexts <-
fresh_idents (
map (
fun '(
x, (
_,
ty,
ck)) => (
x, (
ty,
ck)))
nexts);
let tcs :=
fold_left (
fun tcs '(
x,
lx,
_) =>
map (
rename_trconstr (
Var x)
lx)
tcs)
nnexts tcs in
let eqnexts :=
map (
fun '(
x,
lx, (
ty,
ck)) =>
TcDef ck lx (
Ecexp (
Eexp (
Evar x ty))))
nnexts in
ret (
eqlasts++
eqnexts++
tcs).
Properties
Lemma map_fold_rename {
A} (
cons:
ident ->
var_last) :
forall (
xs:
list (
ident *
ident *
A))
tcs,
fold_left (
fun tcs '(
x,
lx,
_) =>
map (
rename_trconstr (
cons x)
lx)
tcs)
xs tcs
=
map (
fun tc =>
fold_left (
fun tc '(
x,
lx,
_) =>
rename_trconstr (
cons x)
lx tc)
xs tc)
tcs.
Proof.
Typeof
Section rename_typeof.
Lemma rename_exp_typeof subl subn :
forall e,
typeof (
rename_exp subl subn e) =
typeof e.
Proof.
induction e; simpl; cases; auto.
Qed.
Lemma rename_cexp_typeofc subl subn :
forall ce,
typeofc (
rename_cexp subl subn ce) =
typeofc ce.
Proof.
Lemma rename_rhs_typeofr subl subn :
forall e,
typeofr (
rename_rhs subl subn e) =
typeofr e.
Proof.
End rename_typeof.
Variables, Last, Next Definitions
Lemma fresh_idents_vars_perm :
forall xs xs'
st st',
@
fresh_idents stc (
type *
clock)
xs st = (
xs',
st') ->
Permutation (
st_ids st') (
map (
fun '(
_,
lx,
_) =>
lx)
xs' ++
st_ids st).
Proof.
Lemma cut_cycles_tcs_variables :
forall lasts nexts tcs tcs'
st',
cut_cycles_tcs lasts nexts tcs init_st = (
tcs',
st') ->
Permutation (
variables tcs') (
variables tcs ++
st_ids st').
Proof.
Lemma cut_cycles_tcs_lasts_of :
forall lasts nexts tcs tcs'
st',
cut_cycles_tcs lasts nexts tcs init_st = (
tcs',
st') ->
lasts_of tcs' =
lasts_of tcs.
Proof.
Lemma cut_cycles_tcs_nexts_of :
forall lasts nexts tcs tcs'
st',
cut_cycles_tcs lasts nexts tcs init_st = (
tcs',
st') ->
nexts_of tcs' =
nexts_of tcs.
Proof.
Lemma cut_cycles_tcs_state_resets_of :
forall lasts nexts tcs tcs'
st',
cut_cycles_tcs lasts nexts tcs init_st = (
tcs',
st') ->
state_resets_of tcs' =
state_resets_of tcs.
Proof.
Lemma cut_cycles_tcs_insts_of :
forall lasts nexts tcs tcs'
st',
cut_cycles_tcs lasts nexts tcs init_st = (
tcs',
st') ->
insts_of tcs' =
insts_of tcs.
Proof.
intros *
Cut.
unfold cut_cycles_tcs in *.
repeat inv_bind.
rewrite ?
insts_of_app.
replace (
insts_of (
map _ x))
with (@
nil (
ident *
ident)).
2:{
clear -
x.
induction x as [|];
destruct_conjs;
simpl;
auto. }
replace (
insts_of (
map _ x1))
with (@
nil (
ident *
ident)).
2:{
clear -
x1.
induction x1 as [|];
destruct_conjs;
simpl;
auto. }
simpl.
eapply fold_left_ind2,
fold_left_ind2;
try reflexivity.
1,2:
intros *
Perm;
rewrite <-
Perm;
clear Perm.
1,2:
destruct_conjs.
1,2:
induction acc as [|[| |?? []]];
simpl in *;
try destruct (
_ ==
b _);
cases;
auto.
Qed.
Lemma cut_cycles_tcs_inst_resets_of :
forall lasts nexts tcs tcs'
st',
cut_cycles_tcs lasts nexts tcs init_st = (
tcs',
st') ->
inst_resets_of tcs' =
inst_resets_of tcs.
Proof.
AtomOrGensym / NoDup
Fact AtomOrGensym_add :
forall x,
AtomOrGensym (
PSP.of_list lustre_prefs)
x ->
AtomOrGensym (
PSP.of_list gensym_prefs)
x.
Proof.
intros *
At.
simpl in *.
destruct At as [|(?&
In&
At)]; [
left|
right];
auto.
do 2
esplit;
eauto.
rewrite ?
PS.add_spec in *.
firstorder.
Qed.
Lemma stc_not_in_lustre_prefs :
~
PS.In stc (
PSP.of_list lustre_prefs).
Proof.
Program Definition cut_cycles_system (
b: @
system (
PSP.of_list lustre_prefs)) : @
system (
PSP.of_list gensym_prefs) :=
let tocut :=
ECC.cutting_points (
map fst b.(
s_lasts)) (
map fst b.(
s_nexts))
b.(
s_tcs)
in
let tocut :=
PSP.of_list tocut in
let res :=
cut_cycles_tcs
(
filter (
fun x =>
PS.mem (
fst x)
tocut)
b.(
s_lasts))
(
filter (
fun x =>
PS.mem (
fst x)
tocut)
b.(
s_nexts))
b.(
s_tcs)
init_st in
{|
s_name :=
b.(
s_name);
s_subs :=
b.(
s_subs);
s_in :=
b.(
s_in);
s_vars :=
b.(
s_vars)++
st_anns (
snd res);
s_lasts :=
b.(
s_lasts);
s_nexts :=
b.(
s_nexts);
s_out :=
b.(
s_out);
s_tcs :=
fst res;
s_ingt0 :=
b.(
s_ingt0);
s_nodup_states_subs :=
b.(
s_nodup_states_subs);
|}.
Next Obligation.
Next Obligation.
Next Obligation.
Next Obligation.
destruct (
cut_cycles_tcs _ _ _)
as (
tcs'&
st')
eqn:
Htcs;
simpl.
pose proof (
s_last_consistency b)
as Cons.
unfold cut_cycles_tcs in *.
repeat inv_bind.
intros ??
Ex ?.
unfold last_consistency,
Last_with_reset_in,
Is_reset_state_in in *.
rewrite ?
List.Exists_app in *.
destruct Ex as [
Ex|[
Ex|
Ex]];
simpl_Exists;
try now inv Ex.
rewrite ?
map_fold_rename in *.
simpl_In.
assert (
exists ck e,
x2 =
TcUpdate ck ckrs (
UpdLast s e))
as (?&?&?);
subst.
{
revert Ex.
eapply fold_left_ind2,
fold_left_ind2.
3:
intros *
Ex;
inv Ex;
eauto.
1,2:(
intros;
destruct_conjs;
subst;
destruct acc as [|? []|?? []];
simpl in *;
cases;
inv Ex;
eauto with stcsyntax).
}
rewrite Cons; [|
solve_Exists;
constructor].
clear Ex.
split; [
intros Ex|
intros [
Ex|[
Ex|
Ex]]];
simpl_Exists;
try now inv Ex.
-
do 2
right.
solve_Exists.
inv Ex.
eapply fold_left_ind2,
fold_left_ind2;
try constructor.
1,2:
intros;
destruct_conjs;
inv H1;
simpl;
constructor.
-
revert Ex.
eapply fold_left_ind2,
fold_left_ind2.
3:
intros *
Ex;
inv Ex;
eauto.
1,2:(
intros;
destruct_conjs;
subst;
destruct acc as [|? []|?? []];
simpl in *;
cases;
inv Ex;
eauto with stcsyntax).
solve_Exists.
constructor.
Qed.
Next Obligation.
Next Obligation.
destruct (
cut_cycles_tcs _ _ _)
as (
tcs'&
st')
eqn:
Htcs;
simpl.
pose proof (
s_next_consistency b)
as Cons.
unfold cut_cycles_tcs in *.
repeat inv_bind.
intros ??
Ex ?.
unfold next_consistency,
Next_with_reset_in,
Is_reset_state_in in *.
rewrite ?
List.Exists_app in *.
destruct Ex as [
Ex|[
Ex|
Ex]];
simpl_Exists;
try now inv Ex.
rewrite ?
map_fold_rename in *.
simpl_In.
assert (
exists ck e,
x2 =
TcUpdate ck ckrs (
UpdNext s e))
as (?&?&?);
subst.
{
revert Ex.
eapply fold_left_ind2,
fold_left_ind2.
3:
intros *
Ex;
inv Ex;
eauto.
1,2:(
intros;
destruct_conjs;
subst;
destruct acc as [|? []|?? []];
simpl in *;
cases;
inv Ex;
eauto with stcsyntax).
}
rewrite Cons; [|
solve_Exists;
constructor].
clear Ex.
split; [
intros Ex|
intros [
Ex|[
Ex|
Ex]]];
simpl_Exists;
try now inv Ex.
-
do 2
right.
solve_Exists.
inv Ex.
eapply fold_left_ind2,
fold_left_ind2;
try constructor.
1,2:
intros;
destruct_conjs;
inv H1;
simpl;
constructor.
-
revert Ex.
eapply fold_left_ind2,
fold_left_ind2.
3:
intros *
Ex;
inv Ex;
eauto.
1,2:(
intros;
destruct_conjs;
subst;
destruct acc as [|? []|?? []];
simpl in *;
cases;
inv Ex;
eauto with stcsyntax).
solve_Exists.
constructor.
Qed.
Next Obligation.
Next Obligation.
Next Obligation.
Next Obligation.
destruct (
cut_cycles_tcs _ _ _)
as (
tcs'&
st')
eqn:
Htcs;
simpl.
pose proof (
s_inst_consistency b)
as Cons.
unfold cut_cycles_tcs in *.
repeat inv_bind.
intros ??
Ex ?.
unfold inst_consistency,
Inst_with_reset_in,
Is_reset_inst_in in *.
rewrite ?
List.Exists_app in *.
destruct Ex as [
Ex|[
Ex|
Ex]];
simpl_Exists;
try now inv Ex.
rewrite ?
map_fold_rename in *.
simpl_In.
assert (
exists ck xs f es,
x2 =
TcUpdate ck ckrs (
UpdInst s xs f es))
as (?&?&?&?&?);
subst.
{
revert Ex.
eapply fold_left_ind2,
fold_left_ind2.
3:
intros *
Ex;
inv Ex;
eauto.
1,2:(
intros;
destruct_conjs;
subst;
destruct acc as [|? []|?? []];
simpl in *;
cases;
inv Ex;
eauto with stcsyntax).
}
rewrite Cons; [|
solve_Exists;
constructor].
clear Ex.
split; [
intros Ex|
intros [
Ex|[
Ex|
Ex]]];
simpl_Exists;
try now inv Ex.
-
do 2
right.
solve_Exists.
inv Ex.
eapply fold_left_ind2,
fold_left_ind2;
try constructor.
1,2:
intros;
destruct_conjs;
inv H1;
simpl;
constructor.
-
revert Ex.
eapply fold_left_ind2,
fold_left_ind2.
3:
intros *
Ex;
inv Ex;
eauto.
1,2:(
intros;
destruct_conjs;
subst;
destruct acc as [|? []|?? []];
simpl in *;
cases;
inv Ex;
eauto with stcsyntax).
solve_Exists.
constructor.
Qed.
Next Obligation.
Next Obligation.
Definition cut_cycles P :
program :=
Program P.(
types)
P.(
externs) (
map cut_cycles_system P.(
systems)).
Lemma cut_cycles_map_name :
forall P,
map s_name (
map cut_cycles_system P) =
map s_name P.
Proof.
induction P as [|b]; auto.
destruct b; simpl.
simpl in *; now rewrite IHP.
Qed.
Lemma cut_cycles_find_system :
forall P P'
f s,
find_system f P =
Some (
s,
P') ->
find_system f (
cut_cycles P) =
Some (
cut_cycles_system s,
cut_cycles P').
Proof.
intros [];
induction systems0 as [|
s']; [
now inversion 1|].
intros *
Hfind.
setoid_rewrite find_unit_cons;
simpl;
eauto.
eapply find_unit_cons in Hfind as [[
E Hfind]|[
E Hfind]];
simpl in *;
eauto.
inv Hfind;
auto.
Qed.
Lemma cut_cycles_find_system' :
forall P f s P',
find_system f (
cut_cycles P) =
Some (
s,
P') ->
exists s'
P'',
find_system f P =
Some (
s',
P'')
/\
s =
cut_cycles_system s'
/\
P' =
cut_cycles P''.
Proof.
intros [];
induction systems0 as [|
sys]; [
now inversion 1|].
intros *
Hfind;
unfold find_system,
find_unit in *;
simpl in *.
destruct (
ident_eq_dec sys.(
s_name)
f);
eauto.
inv Hfind;
eauto.
Qed.
Additional properties of fresh_idents
Lemma fresh_idents_In_anns2 {
prefs A} :
forall xs1 xs2 xs1'
xs2'
st0 st1 st2,
@
fresh_idents prefs A xs1 st0 = (
xs1',
st1) ->
@
fresh_idents prefs A xs2 st1 = (
xs2',
st2) ->
Forall (
fun '(
_,
lx,
ann) =>
In (
lx,
ann) (
st_anns st2)) (
xs1' ++
xs2').
Proof.
Lemma fresh_idents_In_anns2' {
prefs A} :
forall xs1 xs2 xs1'
xs2'
st1 st2,
@
fresh_idents prefs A xs1 init_st = (
xs1',
st1) ->
@
fresh_idents prefs A xs2 st1 = (
xs2',
st2) ->
Forall (
fun '(
lx,
ann) =>
exists x,
In (
x,
ann) (
xs1 ++
xs2)) (
st_anns st2).
Proof.
intros *
Fr1 Fr2.
do 2 (
erewrite fresh_idents_anns;
eauto).
rewrite init_st_anns,
app_nil_r.
apply Forall_app;
split;
simpl_Forall.
-
eapply fresh_idents_In'
in Fr2;
eauto with datatypes.
-
eapply fresh_idents_In'
in Fr1;
eauto with datatypes.
Qed.
End CC.
Module CCFun
(
Ids :
IDS)
(
Op :
OPERATORS)
(
OpAux :
OPERATORS_AUX Ids Op)
(
Cks :
CLOCKS Ids Op OpAux)
(
CESyn :
CESYNTAX Ids Op OpAux Cks)
(
Syn :
STCSYNTAX Ids Op OpAux Cks CESyn)
(
ECC :
EXT_CC Ids Op OpAux Cks CESyn Syn)
<:
CC Ids Op OpAux Cks CESyn Syn ECC.
Include CC Ids Op OpAux Cks CESyn Syn ECC.
End CCFun.