1 /* ************************************************************************
2  * Copyright 2013 Advanced Micro Devices, Inc.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  * ************************************************************************/
16 
17 #include <errno.h>
18 #include <assert.h>
19 #include "tile_iter.h"
20 
21 // Translate coordiates in physical memory block
22 // into logical tile coordinates
23 static int
iterCalcLogCoords(PhysTileIterator * iter)24 iterCalcLogCoords( PhysTileIterator* iter){
25 
26     if( NULL == iter ){
27         return -EINVAL;
28     }
29 
30     if ( iter->isLogRowMaj ) {
31 
32         iter->row = iter->line;
33         iter->col = iter->vec*iter->vecLen;
34 
35     }
36     else {
37 
38         iter->col = iter->line;
39         iter->row = iter->vec*iter->vecLen;
40     }
41 
42     return 0;
43 }
44 
45 //-----------------------------------------------------------------------------
46 
47 int
iterInit(PhysTileIterator * iter,const Tile * tile,int vecLen,unsigned int tileIterFlags)48 iterInit(PhysTileIterator *iter,
49     const Tile *tile,
50     int vecLen,
51     unsigned int tileIterFlags)
52 {
53     if( NULL == iter ||
54         NULL == tile ){
55 
56         return -EINVAL;
57     }
58 
59     memset(iter, 0, sizeof(PhysTileIterator));
60     iter->isLogRowMaj = tile->trans ? 0 : 1;
61     iter->vecLen = vecLen;
62 
63     if ( iter->isLogRowMaj ) {
64 
65         if ( tile->nrCols % vecLen ) {
66             return -EINVAL;
67         }
68 
69         if ( tileIterFlags & TILE_ITER_BACKWARD_ROWS ) {
70             iter->phyIterFlags |= PHY_ITER_BACKWARD_LINES;
71         }
72         if ( tileIterFlags & TILE_ITER_BACKWARD_COLS ) {
73             iter->phyIterFlags |= PHY_ITER_BACKWARD_VECS;
74         }
75 
76         iter->nrLines = tile->nrRows;
77         iter->nrVecs = tile->nrCols/vecLen;
78 
79     }
80     else {
81 
82         if ( tile->nrRows % vecLen ) {
83             return -EINVAL;
84         }
85 
86         if ( tileIterFlags & TILE_ITER_BACKWARD_ROWS ) {
87             iter->phyIterFlags |= PHY_ITER_BACKWARD_VECS;
88         }
89         if ( tileIterFlags & TILE_ITER_BACKWARD_COLS ) {
90             iter->phyIterFlags |= PHY_ITER_BACKWARD_LINES;
91         }
92 
93         iter->nrLines = tile->nrCols;
94         iter->nrVecs = tile->nrRows/vecLen;
95     }
96 
97     switch( iter->phyIterFlags & (  PHY_ITER_BACKWARD_VECS |
98                                     PHY_ITER_BACKWARD_LINES ) ){
99 
100         // lines - forward, vectors - forward
101         case !( PHY_ITER_BACKWARD_LINES | PHY_ITER_BACKWARD_VECS ):
102 
103             iter->vec = 0;
104             iter->line = 0;
105             break;
106 
107         // lines - forward, vectors - backward
108         case PHY_ITER_BACKWARD_VECS:
109 
110             iter->vec = iter->nrVecs-1;
111             iter->line = 0;
112             break;
113 
114         // lines - backward, vectors - forward
115         case PHY_ITER_BACKWARD_LINES:
116 
117             iter->vec = 0;
118             iter->line = iter->nrLines-1;
119             break;
120 
121         // lines - backward, vectors - backward
122         case PHY_ITER_BACKWARD_LINES | PHY_ITER_BACKWARD_VECS:
123 
124             iter->vec = iter->nrVecs-1;
125             iter->line = iter->nrLines-1;
126             break;
127 
128     }
129 
130     iterCalcLogCoords(iter);
131 
132     return 0;
133 }
134 
135 //-----------------------------------------------------------------------------
136 
iterIterate(PhysTileIterator * iter)137 int iterIterate(PhysTileIterator *iter)
138 {
139     if( NULL == iter ){
140         return -EINVAL;
141     }
142 
143     //tile end
144     if( iterIsEnd(iter) ){
145         return 1;
146     }
147 
148     switch( iter->phyIterFlags & (  PHY_ITER_BACKWARD_LINES |
149                                     PHY_ITER_BACKWARD_VECS) ){
150 
151         // lines - forward, vectors - forward
152         case !( PHY_ITER_BACKWARD_LINES | PHY_ITER_BACKWARD_VECS ):
153 
154             if( iter->nrVecs-1 == iter->vec ){
155 
156                 iter->vec = 0;
157                 iter->line++;
158             }
159             else{
160                 iter->vec++;
161             }
162             break;
163 
164         // lines - forward, vectors - backward
165         case PHY_ITER_BACKWARD_VECS:
166 
167             if( 0 == iter->vec ){
168 
169                 iter->vec = iter->nrVecs-1;
170                 iter->line++;
171             }
172             else{
173                 iter->vec--;
174             }
175             break;
176 
177         // lines - backward, vectors - forward
178         case PHY_ITER_BACKWARD_LINES:
179 
180             if( iter->nrVecs-1 == iter->vec ){
181 
182                 iter->vec = 0;
183                 iter->line--;
184             }
185             else{
186                 iter->vec++;
187             }
188             break;
189 
190         // lines - backward, vectors - backward
191         case ( PHY_ITER_BACKWARD_LINES | PHY_ITER_BACKWARD_VECS ):
192 
193             if(  0 == iter->vec ){
194 
195                 iter->vec = iter->nrVecs-1;
196                 iter->line--;
197             }
198             else{
199                 iter->vec--;
200             }
201             break;
202     }
203 
204     iterCalcLogCoords(iter);
205 
206     return 0;
207 }
208 
209 //-----------------------------------------------------------------------------
210 
211 int
iterSeek(PhysTileIterator * iter,int row,int col)212 iterSeek( PhysTileIterator *iter,
213     int row,
214     int col )
215 {
216     if ( NULL == iter ) {
217         return -EINVAL;
218     }
219 
220     iter->row = row;
221     iter->col = col;
222 
223     if ( iter->isLogRowMaj ) {
224 
225         iter->line = row;
226         iter->vec = col/iter->vecLen;
227     }
228     else {
229 
230         iter->line = col;
231         iter->vec = row/iter->vecLen;
232     }
233 
234     assert( iter->line < iter->nrLines );
235     assert( iter->vec < iter->nrVecs );
236     return 0;
237 }
238 
239 //-----------------------------------------------------------------------------
240 
241 int
iterSeekPhys(PhysTileIterator * iter,int line,int vec)242 iterSeekPhys( PhysTileIterator *iter,
243     int line,
244     int vec )
245 {
246     if ( NULL == iter ) {
247         return -EINVAL;
248     }
249 
250     iter->line = line;
251     iter->vec = vec;
252 
253     if ( iter->isLogRowMaj ) {
254 
255         iter->row = line;
256         iter->col = vec * iter->vecLen;
257     }
258     else {
259 
260         iter->row = vec * iter->vecLen;
261         iter->col = line;
262     }
263 
264     assert( iter->line < iter->nrLines );
265     assert( iter->vec < iter->nrVecs );
266     return 0;
267 }
268 
269 //-----------------------------------------------------------------------------
270 
271 /*
272  * Check if the entire tile has been iterated. Return true if the iterator is
273  * at the next element beyond the last.
274  */
iterIsEnd(const PhysTileIterator * iter)275 int iterIsEnd(const PhysTileIterator *iter)
276 {
277     int isEnd = false;
278 
279     if( NULL == iter ){
280         return -EINVAL;
281     }
282 
283     if( iter->phyIterFlags & PHY_ITER_BACKWARD_LINES ){
284         if( iter->line < 0 ){
285             isEnd = true;
286         }
287     }
288     else{
289         if( iter->line >= iter->nrLines ){
290             isEnd = true;
291         }
292     }
293 
294     return isEnd;
295 
296 }
297