1
2 /*
3 ************************************************************************************************************************
4 *
5 * Copyright (C) 2007-2022 Advanced Micro Devices, Inc. All rights reserved.
6 *
7 * Permission is hereby granted, free of charge, to any person obtaining a
8 * copy of this software and associated documentation files (the "Software"),
9 * to deal in the Software without restriction, including without limitation
10 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
11 * and/or sell copies of the Software, and to permit persons to whom the
12 * Software is furnished to do so, subject to the following conditions:
13 *
14 * The above copyright notice and this permission notice shall be included in
15 * all copies or substantial portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
21 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
22 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
23 * OTHER DEALINGS IN THE SOFTWARE
24 *
25 ***********************************************************************************************************************/
26
27 // Coordinate class implementation
28 #include "addrcommon.h"
29 #include "coord.h"
30
31 namespace Addr
32 {
33 namespace V2
34 {
35
Coordinate()36 Coordinate::Coordinate()
37 {
38 dim = DIM_X;
39 ord = 0;
40 }
41
Coordinate(enum Dim dim,INT_32 n)42 Coordinate::Coordinate(enum Dim dim, INT_32 n)
43 {
44 set(dim, n);
45 }
46
set(enum Dim d,INT_32 n)47 VOID Coordinate::set(enum Dim d, INT_32 n)
48 {
49 dim = d;
50 ord = static_cast<INT_8>(n);
51 }
52
ison(const UINT_32 * coords) const53 UINT_32 Coordinate::ison(const UINT_32 *coords) const
54 {
55 UINT_32 bit = static_cast<UINT_32>(1ull << static_cast<UINT_32>(ord));
56
57 return (coords[dim] & bit) ? 1 : 0;
58 }
59
getdim()60 enum Dim Coordinate::getdim()
61 {
62 return dim;
63 }
64
getord()65 INT_8 Coordinate::getord()
66 {
67 return ord;
68 }
69
operator ==(const Coordinate & b)70 BOOL_32 Coordinate::operator==(const Coordinate& b)
71 {
72 return (dim == b.dim) && (ord == b.ord);
73 }
74
operator <(const Coordinate & b)75 BOOL_32 Coordinate::operator<(const Coordinate& b)
76 {
77 BOOL_32 ret;
78
79 if (dim == b.dim)
80 {
81 ret = ord < b.ord;
82 }
83 else
84 {
85 if (dim == DIM_S || b.dim == DIM_M)
86 {
87 ret = TRUE;
88 }
89 else if (b.dim == DIM_S || dim == DIM_M)
90 {
91 ret = FALSE;
92 }
93 else if (ord == b.ord)
94 {
95 ret = dim < b.dim;
96 }
97 else
98 {
99 ret = ord < b.ord;
100 }
101 }
102
103 return ret;
104 }
105
operator >(const Coordinate & b)106 BOOL_32 Coordinate::operator>(const Coordinate& b)
107 {
108 BOOL_32 lt = *this < b;
109 BOOL_32 eq = *this == b;
110 return !lt && !eq;
111 }
112
operator <=(const Coordinate & b)113 BOOL_32 Coordinate::operator<=(const Coordinate& b)
114 {
115 return (*this < b) || (*this == b);
116 }
117
operator >=(const Coordinate & b)118 BOOL_32 Coordinate::operator>=(const Coordinate& b)
119 {
120 return !(*this < b);
121 }
122
operator !=(const Coordinate & b)123 BOOL_32 Coordinate::operator!=(const Coordinate& b)
124 {
125 return !(*this == b);
126 }
127
operator ++(INT_32)128 Coordinate& Coordinate::operator++(INT_32)
129 {
130 ord++;
131 return *this;
132 }
133
134 // CoordTerm
135
CoordTerm()136 CoordTerm::CoordTerm()
137 {
138 num_coords = 0;
139 }
140
Clear()141 VOID CoordTerm::Clear()
142 {
143 num_coords = 0;
144 }
145
add(Coordinate & co)146 VOID CoordTerm::add(Coordinate& co)
147 {
148 // This function adds a coordinate INT_32o the list
149 // It will prevent the same coordinate from appearing,
150 // and will keep the list ordered from smallest to largest
151 UINT_32 i;
152
153 for (i = 0; i < num_coords; i++)
154 {
155 if (m_coord[i] == co)
156 {
157 break;
158 }
159 if (m_coord[i] > co)
160 {
161 for (UINT_32 j = num_coords; j > i; j--)
162 {
163 m_coord[j] = m_coord[j - 1];
164 }
165 m_coord[i] = co;
166 num_coords++;
167 break;
168 }
169 }
170
171 if (i == num_coords)
172 {
173 m_coord[num_coords] = co;
174 num_coords++;
175 }
176 }
177
add(CoordTerm & cl)178 VOID CoordTerm::add(CoordTerm& cl)
179 {
180 for (UINT_32 i = 0; i < cl.num_coords; i++)
181 {
182 add(cl.m_coord[i]);
183 }
184 }
185
remove(Coordinate & co)186 BOOL_32 CoordTerm::remove(Coordinate& co)
187 {
188 BOOL_32 remove = FALSE;
189 for (UINT_32 i = 0; i < num_coords; i++)
190 {
191 if (m_coord[i] == co)
192 {
193 remove = TRUE;
194 num_coords--;
195 }
196
197 if (remove)
198 {
199 m_coord[i] = m_coord[i + 1];
200 }
201 }
202 return remove;
203 }
204
Exists(Coordinate & co)205 BOOL_32 CoordTerm::Exists(Coordinate& co)
206 {
207 BOOL_32 exists = FALSE;
208 for (UINT_32 i = 0; i < num_coords; i++)
209 {
210 if (m_coord[i] == co)
211 {
212 exists = TRUE;
213 break;
214 }
215 }
216 return exists;
217 }
218
copyto(CoordTerm & cl)219 VOID CoordTerm::copyto(CoordTerm& cl)
220 {
221 cl.num_coords = num_coords;
222 for (UINT_32 i = 0; i < num_coords; i++)
223 {
224 cl.m_coord[i] = m_coord[i];
225 }
226 }
227
getsize()228 UINT_32 CoordTerm::getsize()
229 {
230 return num_coords;
231 }
232
getxor(const UINT_32 * coords) const233 UINT_32 CoordTerm::getxor(const UINT_32 *coords) const
234 {
235 UINT_32 out = 0;
236 for (UINT_32 i = 0; i < num_coords; i++)
237 {
238 out = out ^ m_coord[i].ison(coords);
239 }
240 return out;
241 }
242
getsmallest(Coordinate & co)243 VOID CoordTerm::getsmallest(Coordinate& co)
244 {
245 co = m_coord[0];
246 }
247
Filter(INT_8 f,Coordinate & co,UINT_32 start,enum Dim axis)248 UINT_32 CoordTerm::Filter(INT_8 f, Coordinate& co, UINT_32 start, enum Dim axis)
249 {
250 for (UINT_32 i = start; i < num_coords;)
251 {
252 if (((f == '<' && m_coord[i] < co) ||
253 (f == '>' && m_coord[i] > co) ||
254 (f == '=' && m_coord[i] == co)) &&
255 (axis == NUM_DIMS || axis == m_coord[i].getdim()))
256 {
257 for (UINT_32 j = i; j < num_coords - 1; j++)
258 {
259 m_coord[j] = m_coord[j + 1];
260 }
261 num_coords--;
262 }
263 else
264 {
265 i++;
266 }
267 }
268 return num_coords;
269 }
270
operator [](UINT_32 i)271 Coordinate& CoordTerm::operator[](UINT_32 i)
272 {
273 return m_coord[i];
274 }
275
operator ==(const CoordTerm & b)276 BOOL_32 CoordTerm::operator==(const CoordTerm& b)
277 {
278 BOOL_32 ret = TRUE;
279
280 if (num_coords != b.num_coords)
281 {
282 ret = FALSE;
283 }
284 else
285 {
286 for (UINT_32 i = 0; i < num_coords; i++)
287 {
288 // Note: the lists will always be in order, so we can compare the two lists at time
289 if (m_coord[i] != b.m_coord[i])
290 {
291 ret = FALSE;
292 break;
293 }
294 }
295 }
296 return ret;
297 }
298
operator !=(const CoordTerm & b)299 BOOL_32 CoordTerm::operator!=(const CoordTerm& b)
300 {
301 return !(*this == b);
302 }
303
exceedRange(const UINT_32 * ranges)304 BOOL_32 CoordTerm::exceedRange(const UINT_32 *ranges)
305 {
306 BOOL_32 exceed = FALSE;
307 for (UINT_32 i = 0; (i < num_coords) && (exceed == FALSE); i++)
308 {
309 exceed = ((1u << m_coord[i].getord()) <= ranges[m_coord[i].getdim()]);
310 }
311
312 return exceed;
313 }
314
315 // coordeq
CoordEq()316 CoordEq::CoordEq()
317 {
318 m_numBits = 0;
319 }
320
remove(Coordinate & co)321 VOID CoordEq::remove(Coordinate& co)
322 {
323 for (UINT_32 i = 0; i < m_numBits; i++)
324 {
325 m_eq[i].remove(co);
326 }
327 }
328
Exists(Coordinate & co)329 BOOL_32 CoordEq::Exists(Coordinate& co)
330 {
331 BOOL_32 exists = FALSE;
332
333 for (UINT_32 i = 0; i < m_numBits; i++)
334 {
335 if (m_eq[i].Exists(co))
336 {
337 exists = TRUE;
338 }
339 }
340 return exists;
341 }
342
resize(UINT_32 n)343 VOID CoordEq::resize(UINT_32 n)
344 {
345 if (n > m_numBits)
346 {
347 for (UINT_32 i = m_numBits; i < n; i++)
348 {
349 m_eq[i].Clear();
350 }
351 }
352 m_numBits = n;
353 }
354
getsize()355 UINT_32 CoordEq::getsize()
356 {
357 return m_numBits;
358 }
359
solve(const UINT_32 * coords) const360 UINT_64 CoordEq::solve(const UINT_32 *coords) const
361 {
362 UINT_64 out = 0;
363 for (UINT_32 i = 0; i < m_numBits; i++)
364 {
365 out |= static_cast<UINT_64>(m_eq[i].getxor(coords)) << i;
366 }
367 return out;
368 }
369
solveAddr(UINT_64 addr,UINT_32 sliceInM,UINT_32 * coords) const370 VOID CoordEq::solveAddr(
371 UINT_64 addr, UINT_32 sliceInM,
372 UINT_32 *coords) const
373 {
374 UINT_32 BitsValid[NUM_DIMS] = {0};
375
376 CoordEq temp = *this;
377
378 memset(coords, 0, NUM_DIMS * sizeof(coords[0]));
379
380 UINT_32 bitsLeft = 0;
381
382 for (UINT_32 i = 0; i < temp.m_numBits; i++)
383 {
384 UINT_32 termSize = temp.m_eq[i].getsize();
385
386 if (termSize == 1)
387 {
388 INT_8 bit = (addr >> i) & 1;
389 enum Dim dim = temp.m_eq[i][0].getdim();
390 INT_8 ord = temp.m_eq[i][0].getord();
391
392 ADDR_ASSERT((ord < 32) || (bit == 0));
393
394 BitsValid[dim] |= 1u << ord;
395 coords[dim] |= bit << ord;
396
397 temp.m_eq[i].Clear();
398 }
399 else if (termSize > 1)
400 {
401 bitsLeft++;
402 }
403 }
404
405 if (bitsLeft > 0)
406 {
407 if (sliceInM != 0)
408 {
409 coords[DIM_Z] = coords[DIM_M] / sliceInM;
410 BitsValid[DIM_Z] = 0xffffffff;
411 }
412
413 do
414 {
415 bitsLeft = 0;
416
417 for (UINT_32 i = 0; i < temp.m_numBits; i++)
418 {
419 UINT_32 termSize = temp.m_eq[i].getsize();
420
421 if (termSize == 1)
422 {
423 INT_8 bit = (addr >> i) & 1;
424 enum Dim dim = temp.m_eq[i][0].getdim();
425 INT_8 ord = temp.m_eq[i][0].getord();
426
427 ADDR_ASSERT((ord < 32) || (bit == 0));
428 ADDR_ASSERT(dim < DIM_S);
429
430 BitsValid[dim] |= 1u << ord;
431 coords[dim] |= bit << ord;
432
433 temp.m_eq[i].Clear();
434 }
435 else if (termSize > 1)
436 {
437 CoordTerm tmpTerm = temp.m_eq[i];
438
439 for (UINT_32 j = 0; j < termSize; j++)
440 {
441 enum Dim dim = temp.m_eq[i][j].getdim();
442 INT_8 ord = temp.m_eq[i][j].getord();
443
444 ADDR_ASSERT(dim < DIM_S);
445
446 if (BitsValid[dim] & (1u << ord))
447 {
448 UINT_32 v = (((coords[dim] >> ord) & 1) << i);
449 addr ^= static_cast<UINT_64>(v);
450 tmpTerm.remove(temp.m_eq[i][j]);
451 }
452 }
453
454 temp.m_eq[i] = tmpTerm;
455
456 bitsLeft++;
457 }
458 }
459 } while (bitsLeft > 0);
460 }
461 }
462
copy(CoordEq & o,UINT_32 start,UINT_32 num)463 VOID CoordEq::copy(CoordEq& o, UINT_32 start, UINT_32 num)
464 {
465 o.m_numBits = (num == 0xFFFFFFFF) ? m_numBits : num;
466 for (UINT_32 i = 0; i < o.m_numBits; i++)
467 {
468 m_eq[start + i].copyto(o.m_eq[i]);
469 }
470 }
471
reverse(UINT_32 start,UINT_32 num)472 VOID CoordEq::reverse(UINT_32 start, UINT_32 num)
473 {
474 UINT_32 n = (num == 0xFFFFFFFF) ? m_numBits : num;
475
476 for (UINT_32 i = 0; i < n / 2; i++)
477 {
478 CoordTerm temp;
479 m_eq[start + i].copyto(temp);
480 m_eq[start + n - 1 - i].copyto(m_eq[start + i]);
481 temp.copyto(m_eq[start + n - 1 - i]);
482 }
483 }
484
xorin(CoordEq & x,UINT_32 start)485 VOID CoordEq::xorin(CoordEq& x, UINT_32 start)
486 {
487 UINT_32 n = ((m_numBits - start) < x.m_numBits) ? (m_numBits - start) : x.m_numBits;
488 for (UINT_32 i = 0; i < n; i++)
489 {
490 m_eq[start + i].add(x.m_eq[i]);
491 }
492 }
493
Filter(INT_8 f,Coordinate & co,UINT_32 start,enum Dim axis)494 UINT_32 CoordEq::Filter(INT_8 f, Coordinate& co, UINT_32 start, enum Dim axis)
495 {
496 for (UINT_32 i = start; i < m_numBits;)
497 {
498 UINT_32 m = m_eq[i].Filter(f, co, 0, axis);
499 if (m == 0)
500 {
501 for (UINT_32 j = i; j < m_numBits - 1; j++)
502 {
503 m_eq[j] = m_eq[j + 1];
504 }
505 m_numBits--;
506 }
507 else
508 {
509 i++;
510 }
511 }
512 return m_numBits;
513 }
514
shift(INT_32 amount,INT_32 start)515 VOID CoordEq::shift(INT_32 amount, INT_32 start)
516 {
517 if (amount != 0)
518 {
519 INT_32 numBits = static_cast<INT_32>(m_numBits);
520 amount = -amount;
521 INT_32 inc = (amount < 0) ? -1 : 1;
522 INT_32 i = (amount < 0) ? numBits - 1 : start;
523 INT_32 end = (amount < 0) ? start - 1 : numBits;
524 for (; (inc > 0) ? i < end : i > end; i += inc)
525 {
526 if ((i + amount < start) || (i + amount >= numBits))
527 {
528 m_eq[i].Clear();
529 }
530 else
531 {
532 m_eq[i + amount].copyto(m_eq[i]);
533 }
534 }
535 }
536 }
537
operator [](UINT_32 i)538 CoordTerm& CoordEq::operator[](UINT_32 i)
539 {
540 return m_eq[i];
541 }
542
mort2d(Coordinate & c0,Coordinate & c1,UINT_32 start,UINT_32 end)543 VOID CoordEq::mort2d(Coordinate& c0, Coordinate& c1, UINT_32 start, UINT_32 end)
544 {
545 if (end == 0)
546 {
547 ADDR_ASSERT(m_numBits > 0);
548 end = m_numBits - 1;
549 }
550 for (UINT_32 i = start; i <= end; i++)
551 {
552 UINT_32 select = (i - start) % 2;
553 Coordinate& c = (select == 0) ? c0 : c1;
554 m_eq[i].add(c);
555 c++;
556 }
557 }
558
mort3d(Coordinate & c0,Coordinate & c1,Coordinate & c2,UINT_32 start,UINT_32 end)559 VOID CoordEq::mort3d(Coordinate& c0, Coordinate& c1, Coordinate& c2, UINT_32 start, UINT_32 end)
560 {
561 if (end == 0)
562 {
563 ADDR_ASSERT(m_numBits > 0);
564 end = m_numBits - 1;
565 }
566 for (UINT_32 i = start; i <= end; i++)
567 {
568 UINT_32 select = (i - start) % 3;
569 Coordinate& c = (select == 0) ? c0 : ((select == 1) ? c1 : c2);
570 m_eq[i].add(c);
571 c++;
572 }
573 }
574
operator ==(const CoordEq & b)575 BOOL_32 CoordEq::operator==(const CoordEq& b)
576 {
577 BOOL_32 ret = TRUE;
578
579 if (m_numBits != b.m_numBits)
580 {
581 ret = FALSE;
582 }
583 else
584 {
585 for (UINT_32 i = 0; i < m_numBits; i++)
586 {
587 if (m_eq[i] != b.m_eq[i])
588 {
589 ret = FALSE;
590 break;
591 }
592 }
593 }
594 return ret;
595 }
596
operator !=(const CoordEq & b)597 BOOL_32 CoordEq::operator!=(const CoordEq& b)
598 {
599 return !(*this == b);
600 }
601
602 } // V2
603 } // Addr
604