[/] [trunk/] [src/] [maketest/] [transitionflipper.sml] - Blame information for rev 31

Line No. Rev Author Line
1 4 tbourke
(* $Id: transitionflipper.sml 31 2008-03-30 23:16:19Z tbourke $ *)
2
 
3
(*TODO:
4
  * Check whether duplicate selectids can muck things up.
5
  * Remove unused select ids from final transitions (or initial transitions?).
6
    fun removeEarlierDuplicates l = let (* there can be only one *)
7
        fun p s (s', _) = not (s =:= s')
8
        fun f []                  = []
9
          | f ((x as (s, _))::xs) = x :: f (List.filter (p s) xs)
10
      in rev (f (rev l)) end
11
 
12
    fun unusedId used (E.BoundId (s, ty, _)) = if s <- used
13
                                               then SOME (s, ty) else NONE
14
 
15
    val sellist = removeEarlierDuplicates
16
                    (List.mapPartial (unusedId (!usednames)) presellist)
17
 
18
  * What happens if we call negate(negate tr)?
19
    Should this be forbidden by using types?
20
 
21
  * Should check whether any actselect indices are used in guard terms in a way
22
    that will create problems (restrict how actions are selected?).
23
      e.g. select i . (i > 4) / a[i]
24
                  ||negate
25
                  \/
26
           select i . (i <= r) / a[i]
27
     But how would this combine with other transitions? Does it work?
28
     This must first be understood properly.
29
 
30
  * What about action selectids with non-zero lower bounds?
31
        chan c[6];
32
        select i : int[2,5] . true / c[i]
33
 
34
    Either forbid, or the negation set has to include:
35
        select i : int [0,1] . true / c[i]
36
 
37
  * Need a mapping back from scalar sets to their typedef-ed names (possibly via
38
    uniqueid lookup?, or don't expand to begin with (would this break anything
39
    else?). See tests/testflip13, the selectid should come from 'S', not
40
    scalar[5].
41
 
42
 *)
43
 
44
structure TransitionFlipper :> TRANSITION_FLIPPER = let
45
  structure E       = Expression
46
        and Env     = Environment
47
        and ECVT    = ExpressionCvt
48
        and ATrans  = ActionTrans
49
        and ClkE    = ClockExpression
50
        and CETrans = ClkExprTrans
51
in struct
52
  exception FlipFailed of string
53
 
54
  (* shortcuts over Atom and AtomSet *)
55 18 tbourke
  infix <+ <- ++ <\ \ =:= ; open Symbol
56 4 tbourke
 
57
  type t = {selectids:  E.boundid list,
58
            actionsubs: E.expr list,
59
            guard:      E.expr}
60
 
61
  fun toString {selectids, actionsubs, guard} = let
62
      fun showActions []      = ""
63
        | showActions (e::es) = "[" ^ ECVT.Expr.toString e ^"]"^ showActions es
64
 
65
      fun boundToStr (E.BoundId (s, ty, _)) = Atom.toString s ^
66
                                              " : " ^ ECVT.Ty.toString ty
67
      val bindingList = (ListFormat.fmt {init="(", sep=", ",
68
                                         final=")", fmt=boundToStr})
69
    in
70
      "{select "  ^ bindingList selectids    ^ "\n"  ^
71
      " action: " ^ showActions actionsubs   ^ "\n " ^
72
                    ECVT.Expr.toString guard ^ " }"  ^ "\n"
73
    end
74
 
75
  fun andexpr env (e1, e2) = let
76
      val (ce1, ce1fa, used) = ClkE.fromExpr (emptyset, env, e1)
77
      val (ce2, ce2fa, used) = ClkE.fromExpr (used, env, e2)
78 27 tbourke
    in ClkE.toExpr (ClkE.andexpr (ce1, ce2), ce1fa @ ce2fa) end
79 4 tbourke
 
80 31 tbourke
  fun negateInvariant env invExpr = let
81
      val atr = ActionTrans.fromTrans []
82
                  {selectids=[], actionsubs=[], guard=invExpr}
83
      val ctr = (CETrans.fromATrans env) atr
84
      val ctrs' = CETrans.negate ClkE.trueExpr ctr
85
    in map CETrans.toTrans ctrs' end
86
      handle ClkE.NonClockTerm => raise FlipFailed "bad clock terms in invariant"
87
 
88
 
89 4 tbourke
  fun negateTransitions env (subtypes, trans : t list, invariant) = let
90
      val _ = Util.debugSect (Settings.Outline, fn ()=>"negateTransitions:\n"
91
                                                       ::map toString trans)
92
 
93
      (* 1. Group like subscripts; rename subSelectIds; make others unique. *)
94
      val atrans = ATrans.ensureConsistency
95
                     (map (ATrans.fromTrans subtypes) trans)
96
      val otherATrans = ATrans.coverMissingChannels (subtypes, atrans,
97
                                                     invariant)
98 29 tbourke
      val atrans' = map (ATrans.reduceSelectIds env) atrans
99
      val cetrans = map (CETrans.fromATrans env) atrans'
100 4 tbourke
 
101
      val _ = Util.debugSubsect (Settings.Outline,
102
                        fn ()=>"cover missing channels:\n"
103
                               ::map ATrans.toString otherATrans)
104
 
105
      (* 2. Paritition remaining transitions. *)
106
      val partitions = Partitions.makeList cetrans
107
 
108
      (* 3. Form partition expressions: just over freeSubscripts
109
            Grouping back into a single list of transitions. *)
110
      val cetrans = List.concat (List.map CETrans.formPartitionReps partitions)
111
 
112
      val _ = Util.debugSubsect (Settings.Detailed,
113
                fn ()=>"with partition reps:\n"::map CETrans.toString cetrans)
114
 
115
      (* 4. Convert the location invariant into a clock expression
116
       *    (this piece was hacked in later and could be tightened up. *)
117
      val (cinv, cinv_fall, _) = ClkE.fromExpr (CETrans.unionNames cetrans,
118
                                                env, invariant)
119
      val cetrans = if null cinv_fall then cetrans
120
                    else List.map (CETrans.addDisjointForalls cinv_fall)
121
                                  cetrans
122
 
123
      (* 5. Negate each, concatenating results. *)
124
      val ncetrans = List.concat (List.map (CETrans.negate cinv) cetrans)
125
 
126
      val _ = Util.debugSubsect (Settings.Detailed, fn ()=>"after negation:\n"
127
                                              ::map CETrans.toString ncetrans)
128
 
129
    in map ATrans.toTrans otherATrans @ map CETrans.toTrans ncetrans end
130
      handle CETrans.SelectIdConflictsWithForAll (sel, forall) => let
131
                fun showSym n = ListFormat.fmt {init=n ^ "(", final=")",
132
                                                sep=", ", fmt=Atom.toString}
133
              in
134
               raise FlipFailed ("select/forall conflict, " ^
135
                                 showSym "select" sel       ^
136
                                 showSym "forall" forall    )
137
              end
138
 
139
           | ClkE.NonClockTerm => raise FlipFailed "bad clock terms in guard"
140
 
141
           | ATrans.ActSubWithNonSimpleSelect e      => raise FlipFailed (
142
                  "channel subscript contains non-simple bound variable (" ^
143
                  ExpressionCvt.Expr.toString e ^ ")")
144
 
145
           | ATrans.ActSubWithBadType {expr, badty, goodty} => raise FlipFailed
146
                ("channel subscript select variable " ^
147
                 ExpressionCvt.Expr.toString expr  ^ " has type " ^
148
                   ExpressionCvt.Ty.toString badty ^ ", not "     ^
149
                   ExpressionCvt.Ty.toString goodty)
150
 
151
           | ATrans.BadSubscriptCount                =>
152
                raise FlipFailed ("wrong number of channel subscripts")
153
 
154
           | ATrans.MixedSubscriptTypes (e1, e2) => raise FlipFailed
155
                ("non-consistent channel subscript dimensions (" ^
156
                 ExpressionCvt.Expr.toString e1 ^ ", " ^
157
                 ExpressionCvt.Expr.toString e2 ^ ")")
158
 
159
  fun chanToSubRanges (env, s) = let
160
      fun arrToList (E.CHANNEL _, r)              = SOME r
161
        | arrToList (E.ARRAY (ty, E.Type sub), r) = arrToList (ty, sub::r)
162
        | arrToList _                             = NONE
163
    in
164
      Option.composePartial (fn ty=> arrToList (ty, []), Env.findValType env) s
165
    end
166
 
167
end
168
end
169