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

Line No. Rev Author Line
1 4 tbourke
(* $Id: transitionflipper.sml 27 2008-03-28 05:50:05Z 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
  fun negateTransitions env (subtypes, trans : t list, invariant) = let
81
      val _ = Util.debugSect (Settings.Outline, fn ()=>"negateTransitions:\n"
82
                                                       ::map toString trans)
83
 
84
      (* 1. Group like subscripts; rename subSelectIds; make others unique. *)
85
      val atrans = ATrans.ensureConsistency
86
                     (map (ATrans.fromTrans subtypes) trans)
87
      val otherATrans = ATrans.coverMissingChannels (subtypes, atrans,
88
                                                     invariant)
89
      val cetrans = map (CETrans.fromATrans env) atrans
90
 
91
      val _ = Util.debugSubsect (Settings.Outline,
92
                        fn ()=>"cover missing channels:\n"
93
                               ::map ATrans.toString otherATrans)
94
 
95
      (* 2. Paritition remaining transitions. *)
96
      val partitions = Partitions.makeList cetrans
97
 
98
      (* 3. Form partition expressions: just over freeSubscripts
99
            Grouping back into a single list of transitions. *)
100
      val cetrans = List.concat (List.map CETrans.formPartitionReps partitions)
101
 
102
      val _ = Util.debugSubsect (Settings.Detailed,
103
                fn ()=>"with partition reps:\n"::map CETrans.toString cetrans)
104
 
105
      (* 4. Convert the location invariant into a clock expression
106
       *    (this piece was hacked in later and could be tightened up. *)
107
      val (cinv, cinv_fall, _) = ClkE.fromExpr (CETrans.unionNames cetrans,
108
                                                env, invariant)
109
      val cetrans = if null cinv_fall then cetrans
110
                    else List.map (CETrans.addDisjointForalls cinv_fall)
111
                                  cetrans
112
 
113
      (* 5. Negate each, concatenating results. *)
114
      val ncetrans = List.concat (List.map (CETrans.negate cinv) cetrans)
115
 
116
      val _ = Util.debugSubsect (Settings.Detailed, fn ()=>"after negation:\n"
117
                                              ::map CETrans.toString ncetrans)
118
 
119
    in map ATrans.toTrans otherATrans @ map CETrans.toTrans ncetrans end
120
      handle CETrans.SelectIdConflictsWithForAll (sel, forall) => let
121
                fun showSym n = ListFormat.fmt {init=n ^ "(", final=")",
122
                                                sep=", ", fmt=Atom.toString}
123
              in
124
               raise FlipFailed ("select/forall conflict, " ^
125
                                 showSym "select" sel       ^
126
                                 showSym "forall" forall    )
127
              end
128
 
129
           | ClkE.NonClockTerm => raise FlipFailed "bad clock terms in guard"
130
 
131
           | ATrans.ActSubWithNonSimpleSelect e      => raise FlipFailed (
132
                  "channel subscript contains non-simple bound variable (" ^
133
                  ExpressionCvt.Expr.toString e ^ ")")
134
 
135
           | ATrans.ActSubWithBadType {expr, badty, goodty} => raise FlipFailed
136
                ("channel subscript select variable " ^
137
                 ExpressionCvt.Expr.toString expr  ^ " has type " ^
138
                   ExpressionCvt.Ty.toString badty ^ ", not "     ^
139
                   ExpressionCvt.Ty.toString goodty)
140
 
141
           | ATrans.BadSubscriptCount                =>
142
                raise FlipFailed ("wrong number of channel subscripts")
143
 
144
           | ATrans.MixedSubscriptTypes (e1, e2) => raise FlipFailed
145
                ("non-consistent channel subscript dimensions (" ^
146
                 ExpressionCvt.Expr.toString e1 ^ ", " ^
147
                 ExpressionCvt.Expr.toString e2 ^ ")")
148
 
149
  fun chanToSubRanges (env, s) = let
150
      fun arrToList (E.CHANNEL _, r)              = SOME r
151
        | arrToList (E.ARRAY (ty, E.Type sub), r) = arrToList (ty, sub::r)
152
        | arrToList _                             = NONE
153
    in
154
      Option.composePartial (fn ty=> arrToList (ty, []), Env.findValType env) s
155
    end
156
 
157
end
158
end
159