1 : |
jhr |
280 |
(* high-to-mid.sml
|
2 : |
|
|
*
|
3 : |
|
|
* COPYRIGHT (c) 2010 The Diderot Project (http://diderot.cs.uchicago.edu)
|
4 : |
|
|
* All rights reserved.
|
5 : |
|
|
*
|
6 : |
|
|
* Translation from HighIL to MidIL representations.
|
7 : |
|
|
*)
|
8 : |
|
|
|
9 : |
|
|
structure HighToMid : sig
|
10 : |
|
|
|
11 : |
|
|
val translate : HighIL.program -> MidIL.program
|
12 : |
|
|
|
13 : |
|
|
end = struct
|
14 : |
|
|
|
15 : |
|
|
structure SrcIL = HighIL
|
16 : |
|
|
structure SrcOp = SrcIL.Op
|
17 : |
|
|
structure DstIL = MidIL
|
18 : |
|
|
structure DstOp = DstIL.Op
|
19 : |
|
|
structure VMap = SrcIL.Var.Map
|
20 : |
|
|
|
21 : |
jhr |
323 |
(* a tree representation of nested iterations over the image space, where the
|
22 : |
|
|
* height of the tree corresponds to the number of dimensions and at each node
|
23 : |
|
|
* we have as many children as there are iterations.
|
24 : |
|
|
*)
|
25 : |
|
|
structure IT =
|
26 : |
|
|
struct
|
27 : |
|
|
datatype ('nd, 'lf) iter_tree
|
28 : |
|
|
= LF of 'lf
|
29 : |
|
|
| ND of ('nd * ('nd, 'lf) iter_tree list)
|
30 : |
|
|
|
31 : |
|
|
fun create (depth, width, ndAttr, f, lfAttr, init) = let
|
32 : |
|
|
fun mk (d, i, arg) = if (d < depth)
|
33 : |
|
|
then ND(ndAttr arg, List.tabulate(width, fn j => mk(d+1, j, f(j, arg))))
|
34 : |
|
|
else LF(lfAttr arg)
|
35 : |
|
|
in
|
36 : |
|
|
mk (0, 0, init)
|
37 : |
|
|
end
|
38 : |
|
|
|
39 : |
|
|
fun map (nd, lf) t = let
|
40 : |
|
|
fun mapf (LF x) = LF(lf x)
|
41 : |
|
|
| mapf (ND(i, kids)) = ND(nd i, List.map mapf kids)
|
42 : |
|
|
in
|
43 : |
|
|
mapf t
|
44 : |
|
|
end
|
45 : |
|
|
|
46 : |
|
|
fun foldr f init t = let
|
47 : |
|
|
fun fold (LF x, acc) = f(x, acc)
|
48 : |
|
|
| fold (ND(_, kids), acc) = List.foldr fold acc kids
|
49 : |
|
|
in
|
50 : |
|
|
fold t
|
51 : |
|
|
end
|
52 : |
|
|
|
53 : |
|
|
end
|
54 : |
|
|
|
55 : |
jhr |
280 |
(* expand the field Inside operator into a image-space test *)
|
56 : |
|
|
fun expandInside (env, result, pos, fld) = let
|
57 : |
|
|
val pos' = lookupVar (env, pos)
|
58 : |
|
|
val fld = (case valueOf fld
|
59 : |
|
|
of SrcIL.OP(SrcOp.Field fld, []) => fld
|
60 : |
|
|
| _ => raise Fail "bogus field binding"
|
61 : |
|
|
(* end case *))
|
62 : |
|
|
fun expand (FieldDef.CONV(_, img, _)) => let
|
63 : |
|
|
val imgPos = newVar ??
|
64 : |
|
|
in [
|
65 : |
|
|
(imgPos, DstIL.OP(DstOp.Transform img, [pos'])),
|
66 : |
|
|
(result, DstIL.OP(DstOp.Inside img, [imgPos]))
|
67 : |
|
|
] end
|
68 : |
|
|
| expand (FieldDef.NEG fld) => expand fld
|
69 : |
|
|
| expand (FieldDef.SUM(fld1, dlf2)) => raise Fail "expandInside: SUM"
|
70 : |
|
|
in
|
71 : |
|
|
expand fld
|
72 : |
|
|
end
|
73 : |
|
|
|
74 : |
jhr |
314 |
(* generate a new variable indexed by dimension *)
|
75 : |
|
|
local
|
76 : |
|
|
val dimNames = Vector.fromList[ "x", "y", "z" ];
|
77 : |
|
|
in
|
78 : |
|
|
fun newVar_dim (prefix, d) =
|
79 : |
|
|
DstIL.Var.new (prefix ^ Vector.sub(dimNames, d))
|
80 : |
|
|
|
81 : |
|
|
fun assign (x, rator, args) = (x, DstIL.OP(rator, args))
|
82 : |
jhr |
323 |
fun cons (x, args) = (x, DstIL.CONS args)
|
83 : |
jhr |
314 |
fun intLit (x, i) = (x, DstIL.LIT(Literal.Int(IntInf.fromInt i)))
|
84 : |
|
|
|
85 : |
|
|
fun generate (n, f) = List.concat(List.tabulate(n, f))
|
86 : |
|
|
|
87 : |
|
|
(* generate code for probing the field (D^k (v * h)) at pos *)
|
88 : |
|
|
fun probe (result, (k, v, h), pos) = let
|
89 : |
|
|
val ImageInfo.ImgInfo{dim, ty=([], ty), ...} = v
|
90 : |
|
|
val dimTy = DstOp.VecTy dim
|
91 : |
|
|
val s = Kernel.support h
|
92 : |
|
|
val sTy = DstOp.VecTy(2*s)
|
93 : |
|
|
(* generate the transform code *)
|
94 : |
|
|
val x = DstIL.Var.new "x" (* image-space position *)
|
95 : |
|
|
val f = DstIL.Var.new "f"
|
96 : |
|
|
val nd = DstIL.Var.new "nd"
|
97 : |
|
|
val n = DstIL.Var.new "n"
|
98 : |
|
|
val transformCode = [
|
99 : |
|
|
assign(x, DstIL.Transform v, [pos]),
|
100 : |
|
|
assign(nd, DstIL.Floor dim, [x]),
|
101 : |
|
|
assign(f, DstIL.Sub dimTy, [x, nd]),
|
102 : |
|
|
assign(n, DstOp.TruncToInt dim, [nd])
|
103 : |
|
|
]
|
104 : |
|
|
(* generate code to load the voxel data *)
|
105 : |
jhr |
323 |
val voxIter = let
|
106 : |
|
|
fun f (i, (offsets, id)) = (i - (s - 1) :: offsets, i::id)
|
107 : |
|
|
fun g (offsets, id) = {
|
108 : |
|
|
offsets = offsets,
|
109 : |
|
|
vox = DstIL.Var.new(String.concat("v" :: List.map Int.toString id))
|
110 : |
|
|
}
|
111 : |
|
|
in
|
112 : |
|
|
IT.create (depth, width, fn _ => (), f, g, ([], []))
|
113 : |
|
|
end
|
114 : |
|
|
val loadCode = let
|
115 : |
|
|
fun genCode ({offsets, vox}, code) = let
|
116 : |
|
|
fun computeIndices (_, []) = ([], [])
|
117 : |
|
|
| computeIndices (i, offset::offsets) = let
|
118 : |
|
|
val index = newVar_dim("i", i)
|
119 : |
|
|
val t1 = newVar "t1"
|
120 : |
|
|
val t2 = newVar "t2"
|
121 : |
|
|
val (indices, code) = computeIndices (i+1, offsets)
|
122 : |
|
|
val code =
|
123 : |
|
|
intLit(t1, offset) ::
|
124 : |
|
|
assign(t2, DstOp.Select i, [n]) ::
|
125 : |
|
|
assign(index, DstOp.Add(DstOp.IntTy), [t1, t2]) ::
|
126 : |
|
|
code
|
127 : |
|
|
val indices = index::indices
|
128 : |
|
|
in
|
129 : |
|
|
(indices, code)
|
130 : |
|
|
end
|
131 : |
|
|
val (indices, indicesCode) = computeIndices (0, ~(s-1) :: offsets)
|
132 : |
|
|
val a = DstIL.Var.new "a"
|
133 : |
|
|
in
|
134 : |
|
|
indicesCode :: [
|
135 : |
|
|
assign(a, VoxelAddress v, indices),
|
136 : |
|
|
assign(vox, LoadVoxels(ty, 2*s))
|
137 : |
|
|
] @ code
|
138 : |
|
|
end
|
139 : |
|
|
in
|
140 : |
|
|
IT.foldr genCode [] voxIter
|
141 : |
|
|
end
|
142 : |
|
|
val voxVars = IT.foldr (fn ({vox, ...}, vs) => vox::vs) [] voxIter
|
143 : |
|
|
(* generate the code for computing the convolution coefficients *)
|
144 : |
|
|
(* SOMETHING *)
|
145 : |
|
|
(* generate the reduction code *)
|
146 : |
|
|
fun genReduce (d, IT.ND(kids), code) =
|
147 : |
|
|
if (d < dim)
|
148 : |
|
|
then List.foldr (fn (nd, code) => genReduce(d+1, nd, code)) code kids
|
149 : |
|
|
else let (* the kids will all be leaves *)
|
150 : |
|
|
val vv = newVar "vv"
|
151 : |
|
|
fun getVox (IT.LF{vox, offsets}) = vox
|
152 : |
jhr |
314 |
in
|
153 : |
jhr |
323 |
cons (vv, List.map getVox kids) ::
|
154 : |
|
|
assign (t, DstIL.Dot, [h, vv]) :: code
|
155 : |
|
|
end
|
156 : |
|
|
val reduceCode = genReduce (1, voxIter, [])
|
157 : |
jhr |
314 |
in
|
158 : |
jhr |
323 |
transformCode @ loadCode @ reduceCode
|
159 : |
jhr |
314 |
end
|
160 : |
|
|
|
161 : |
|
|
end
|
162 : |
|
|
|
163 : |
jhr |
280 |
fun expandProbe (env, result, fld, pos) = let
|
164 : |
|
|
val pos' = lookupVar (env, pos)
|
165 : |
|
|
val fld = (case valueOf fld
|
166 : |
|
|
of SrcIL.OP(SrcOp.Field fld, []) => fld
|
167 : |
|
|
| _ => raise Fail "bogus field binding"
|
168 : |
|
|
(* end case *))
|
169 : |
|
|
fun expand (result, FieldDef.CONV(0, img, h)) => let
|
170 : |
|
|
val imgPos = newVar ??
|
171 : |
|
|
val xformStm = (imgPos, DstIL.OP(DstOp.Transform img, [pos']))
|
172 : |
|
|
(* generate samples based on kernel support and dimensionality of image *)
|
173 : |
|
|
in
|
174 : |
|
|
xformStm :: probeStms
|
175 : |
|
|
end
|
176 : |
|
|
| expand (FieldDef.CONV(k, img, h)) => ??
|
177 : |
|
|
| expand (FieldDef.NEG fld) => let
|
178 : |
|
|
val r = newVar ??
|
179 : |
|
|
val stms = expand (r, fld)
|
180 : |
|
|
in
|
181 : |
|
|
(r, DstIL.OP(DstOp.Neg ty, [r])) :: stms
|
182 : |
|
|
end
|
183 : |
|
|
| expand (FieldDef.SUM(fld1, dlf2)) => raise Fail "expandInside: SUM"
|
184 : |
|
|
in
|
185 : |
|
|
List.rev (expand (result, fld))
|
186 : |
|
|
end
|
187 : |
|
|
|
188 : |
|
|
end
|