diff options
Diffstat (limited to 'src/amd/addrlib/gfx9/coord.cpp')
-rw-r--r-- | src/amd/addrlib/gfx9/coord.cpp | 707 |
1 files changed, 707 insertions, 0 deletions
diff --git a/src/amd/addrlib/gfx9/coord.cpp b/src/amd/addrlib/gfx9/coord.cpp new file mode 100644 index 00000000000..effdc90017e --- /dev/null +++ b/src/amd/addrlib/gfx9/coord.cpp @@ -0,0 +1,707 @@ +/* + * Copyright © 2017 Advanced Micro Devices, Inc. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NON-INFRINGEMENT. IN NO EVENT SHALL THE COPYRIGHT HOLDERS, AUTHORS + * AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE + * USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + */ + +// Coordinate class implementation +#include "addrcommon.h" +#include "coord.h" + +Coordinate::Coordinate() +{ + dim = 'x'; + ord = 0; +} + +Coordinate::Coordinate(INT_8 c, UINT_32 n) +{ + set(c,n); +} + +VOID Coordinate::set(INT_8 c, UINT_32 n) +{ + dim = c; + ord = static_cast<INT_8>(n); +} + +UINT_32 Coordinate::ison(UINT_32 x, UINT_32 y, UINT_32 z, UINT_32 s, UINT_32 m) +{ + UINT_32 bit = 1 << (UINT_32)ord; + UINT_32 out = 0; + + switch (dim) + { + case 'm': out = m & bit; break; + case 's': out = s & bit; break; + case 'x': out = x & bit; break; + case 'y': out = y & bit; break; + case 'z': out = z & bit; break; + } + return (out != 0) ? 1 : 0; +} + +INT_8 Coordinate::getdim() +{ + return dim; +} + +INT_8 Coordinate::getord() +{ + return ord; +} + +BOOL_32 Coordinate::operator==(const Coordinate& b) +{ + return (dim == b.dim) && (ord == b.ord); +} + +BOOL_32 Coordinate::operator<(const Coordinate& b) +{ + BOOL_32 ret; + + if (dim == b.dim) + { + ret = ord < b.ord; + } + else + { + if (dim == 's' || b.dim == 'm') + { + ret = TRUE; + } + else if (b.dim == 's' || dim == 'm') + { + ret = FALSE; + } + else if (ord == b.ord) + { + ret = dim < b.dim; + } + else + { + ret = ord < b.ord; + } + } + + return ret; +} + +BOOL_32 Coordinate::operator>(const Coordinate& b) +{ + BOOL_32 lt = *this < b; + BOOL_32 eq = *this == b; + return !lt && !eq; +} + +BOOL_32 Coordinate::operator<=(const Coordinate& b) +{ + return (*this < b) || (*this == b); +} + +BOOL_32 Coordinate::operator>=(const Coordinate& b) +{ + return !(*this < b); +} + +BOOL_32 Coordinate::operator!=(const Coordinate& b) +{ + return !(*this == b); +} + +Coordinate& Coordinate::operator++(INT_32) +{ + ord++; + return *this; +} + +// CoordTerm + +CoordTerm::CoordTerm() +{ + num_coords = 0; +} + +VOID CoordTerm::Clear() +{ + num_coords = 0; +} + +VOID CoordTerm::add(Coordinate& co) +{ + // This function adds a coordinate INT_32o the list + // It will prevent the same coordinate from appearing, + // and will keep the list ordered from smallest to largest + UINT_32 i; + + for (i = 0; i < num_coords; i++) + { + if (m_coord[i] == co) + { + break; + } + if (m_coord[i] > co) + { + for (UINT_32 j = num_coords; j > i; j--) + { + m_coord[j] = m_coord[j - 1]; + } + m_coord[i] = co; + num_coords++; + break; + } + } + + if (i == num_coords) + { + m_coord[num_coords] = co; + num_coords++; + } +} + +VOID CoordTerm::add(CoordTerm& cl) +{ + for (UINT_32 i = 0; i < cl.num_coords; i++) + { + add(cl.m_coord[i]); + } +} + +BOOL_32 CoordTerm::remove(Coordinate& co) +{ + BOOL_32 remove = FALSE; + for (UINT_32 i = 0; i < num_coords; i++) + { + if (m_coord[i] == co) + { + remove = TRUE; + num_coords--; + } + + if (remove) + { + m_coord[i] = m_coord[i + 1]; + } + } + return remove; +} + +BOOL_32 CoordTerm::Exists(Coordinate& co) +{ + BOOL_32 exists = FALSE; + for (UINT_32 i = 0; i < num_coords; i++) + { + if (m_coord[i] == co) + { + exists = TRUE; + break; + } + } + return exists; +} + +VOID CoordTerm::copyto(CoordTerm& cl) +{ + cl.num_coords = num_coords; + for (UINT_32 i = 0; i < num_coords; i++) + { + cl.m_coord[i] = m_coord[i]; + } +} + +UINT_32 CoordTerm::getsize() +{ + return num_coords; +} + +UINT_32 CoordTerm::getxor(UINT_32 x, UINT_32 y, UINT_32 z, UINT_32 s, UINT_32 m) +{ + UINT_32 out = 0; + for (UINT_32 i = 0; i < num_coords; i++) + { + out = out ^ m_coord[i].ison(x, y, z, s, m); + } + return out; +} + +VOID CoordTerm::getsmallest(Coordinate& co) +{ + co = m_coord[0]; +} + +UINT_32 CoordTerm::Filter(INT_8 f, Coordinate& co, UINT_32 start, INT_8 axis) +{ + for (UINT_32 i = start; i < num_coords;) + { + if (((f == '<' && m_coord[i] < co) || + (f == '>' && m_coord[i] > co) || + (f == '=' && m_coord[i] == co)) && + (axis == '\0' || axis == m_coord[i].getdim())) + { + for (UINT_32 j = i; j < num_coords - 1; j++) + { + m_coord[j] = m_coord[j + 1]; + } + num_coords--; + } + else + { + i++; + } + } + return num_coords; +} + +Coordinate& CoordTerm::operator[](UINT_32 i) +{ + return m_coord[i]; +} + +BOOL_32 CoordTerm::operator==(const CoordTerm& b) +{ + BOOL_32 ret = TRUE; + + if (num_coords != b.num_coords) + { + ret = FALSE; + } + else + { + for (UINT_32 i = 0; i < num_coords; i++) + { + // Note: the lists will always be in order, so we can compare the two lists at time + if (m_coord[i] != b.m_coord[i]) + { + ret = FALSE; + break; + } + } + } + return ret; +} + +BOOL_32 CoordTerm::operator!=(const CoordTerm& b) +{ + return !(*this == b); +} + +BOOL_32 CoordTerm::exceedRange(UINT_32 xRange, UINT_32 yRange, UINT_32 zRange, UINT_32 sRange) +{ + BOOL_32 exceed = FALSE; + for (UINT_32 i = 0; (i < num_coords) && (exceed == FALSE); i++) + { + UINT_32 subject; + switch (m_coord[i].getdim()) + { + case 'x': + subject = xRange; + break; + case 'y': + subject = yRange; + break; + case 'z': + subject = zRange; + break; + case 's': + subject = sRange; + break; + case 'm': + subject = 0; + break; + default: + // Invalid input! + ADDR_ASSERT_ALWAYS(); + subject = 0; + break; + } + + exceed = ((1u << m_coord[i].getord()) <= subject); + } + + return exceed; +} + +// coordeq +CoordEq::CoordEq() +{ + m_numBits = 0; +} + +VOID CoordEq::remove(Coordinate& co) +{ + for (UINT_32 i = 0; i < m_numBits; i++) + { + m_eq[i].remove(co); + } +} + +BOOL_32 CoordEq::Exists(Coordinate& co) +{ + BOOL_32 exists = FALSE; + + for (UINT_32 i = 0; i < m_numBits; i++) + { + if (m_eq[i].Exists(co)) + { + exists = TRUE; + } + } + return exists; +} + +VOID CoordEq::resize(UINT_32 n) +{ + if (n > m_numBits) + { + for (UINT_32 i = m_numBits; i < n; i++) + { + m_eq[i].Clear(); + } + } + m_numBits = n; +} + +UINT_32 CoordEq::getsize() +{ + return m_numBits; +} + +UINT_64 CoordEq::solve(UINT_32 x, UINT_32 y, UINT_32 z, UINT_32 s, UINT_32 m) +{ + UINT_64 out = 0; + for (UINT_32 i = 0; i < m_numBits; i++) + { + if (m_eq[i].getxor(x, y, z, s, m) != 0) + { + out |= (1ULL << i); + } + } + return out; +} + +VOID CoordEq::solveAddr( + UINT_64 addr, UINT_32 sliceInM, + UINT_32& x, UINT_32& y, UINT_32& z, UINT_32& s, UINT_32& m) +{ + UINT_32 xBitsValid = 0; + UINT_32 yBitsValid = 0; + UINT_32 zBitsValid = 0; + UINT_32 sBitsValid = 0; + UINT_32 mBitsValid = 0; + + CoordEq temp = *this; + + x = y = z = s = m = 0; + + UINT_32 bitsLeft = 0; + + for (UINT_32 i = 0; i < temp.m_numBits; i++) + { + UINT_32 termSize = temp.m_eq[i].getsize(); + + if (termSize == 1) + { + INT_8 bit = (addr >> i) & 1; + INT_8 dim = temp.m_eq[i][0].getdim(); + INT_8 ord = temp.m_eq[i][0].getord(); + + ADDR_ASSERT((ord < 32) || (bit == 0)); + + switch (dim) + { + case 'x': + xBitsValid |= (1 << ord); + x |= (bit << ord); + break; + case 'y': + yBitsValid |= (1 << ord); + y |= (bit << ord); + break; + case 'z': + zBitsValid |= (1 << ord); + z |= (bit << ord); + break; + case 's': + sBitsValid |= (1 << ord); + s |= (bit << ord); + break; + case 'm': + mBitsValid |= (1 << ord); + m |= (bit << ord); + break; + default: + break; + } + + temp.m_eq[i].Clear(); + } + else if (termSize > 1) + { + bitsLeft++; + } + } + + if (bitsLeft > 0) + { + if (sliceInM != 0) + { + z = m / sliceInM; + zBitsValid = 0xffffffff; + } + + do + { + bitsLeft = 0; + + for (UINT_32 i = 0; i < temp.m_numBits; i++) + { + UINT_32 termSize = temp.m_eq[i].getsize(); + + if (termSize == 1) + { + INT_8 bit = (addr >> i) & 1; + INT_8 dim = temp.m_eq[i][0].getdim(); + INT_8 ord = temp.m_eq[i][0].getord(); + + ADDR_ASSERT((ord < 32) || (bit == 0)); + + switch (dim) + { + case 'x': + xBitsValid |= (1 << ord); + x |= (bit << ord); + break; + case 'y': + yBitsValid |= (1 << ord); + y |= (bit << ord); + break; + case 'z': + zBitsValid |= (1 << ord); + z |= (bit << ord); + break; + case 's': + ADDR_ASSERT_ALWAYS(); + break; + case 'm': + ADDR_ASSERT_ALWAYS(); + break; + default: + break; + } + + temp.m_eq[i].Clear(); + } + else if (termSize > 1) + { + CoordTerm tmpTerm = temp.m_eq[i]; + + for (UINT_32 j = 0; j < termSize; j++) + { + INT_8 dim = temp.m_eq[i][j].getdim(); + INT_8 ord = temp.m_eq[i][j].getord(); + + switch (dim) + { + case 'x': + if (xBitsValid & (1 << ord)) + { + UINT_32 v = (((x >> ord) & 1) << i); + addr ^= static_cast<UINT_64>(v); + tmpTerm.remove(temp.m_eq[i][j]); + } + break; + case 'y': + if (yBitsValid & (1 << ord)) + { + UINT_32 v = (((y >> ord) & 1) << i); + addr ^= static_cast<UINT_64>(v); + tmpTerm.remove(temp.m_eq[i][j]); + } + break; + case 'z': + if (zBitsValid & (1 << ord)) + { + UINT_32 v = (((z >> ord) & 1) << i); + addr ^= static_cast<UINT_64>(v); + tmpTerm.remove(temp.m_eq[i][j]); + } + break; + case 's': + ADDR_ASSERT_ALWAYS(); + break; + case 'm': + ADDR_ASSERT_ALWAYS(); + break; + default: + break; + } + } + + temp.m_eq[i] = tmpTerm; + + bitsLeft++; + } + } + } while (bitsLeft > 0); + } +} + +VOID CoordEq::copy(CoordEq& o, UINT_32 start, UINT_32 num) +{ + o.m_numBits = (num == 0xFFFFFFFF) ? m_numBits : num; + for (UINT_32 i = 0; i < o.m_numBits; i++) + { + m_eq[start + i].copyto(o.m_eq[i]); + } +} + +VOID CoordEq::reverse(UINT_32 start, UINT_32 num) +{ + UINT_32 n = (num == 0xFFFFFFFF) ? m_numBits : num; + + for (UINT_32 i = 0; i < n / 2; i++) + { + CoordTerm temp; + m_eq[start + i].copyto(temp); + m_eq[start + n - 1 - i].copyto(m_eq[start + i]); + temp.copyto(m_eq[start + n - 1 - i]); + } +} + +VOID CoordEq::xorin(CoordEq& x, UINT_32 start) +{ + UINT_32 n = ((m_numBits - start) < x.m_numBits) ? (m_numBits - start) : x.m_numBits; + for (UINT_32 i = 0; i < n; i++) + { + m_eq[start + i].add(x.m_eq[i]); + } +} + +UINT_32 CoordEq::Filter(INT_8 f, Coordinate& co, UINT_32 start, INT_8 axis) +{ + for (UINT_32 i = start; i < m_numBits;) + { + UINT_32 m = m_eq[i].Filter(f, co, 0, axis); + if (m == 0) + { + for (UINT_32 j = i; j < m_numBits - 1; j++) + { + m_eq[j] = m_eq[j + 1]; + } + m_numBits--; + } + else + { + i++; + } + } + return m_numBits; +} + +VOID CoordEq::shift(INT_32 amount, INT_32 start) +{ + if (amount != 0) + { + INT_32 numBits = static_cast<INT_32>(m_numBits); + amount = -amount; + INT_32 inc = (amount < 0) ? -1 : 1; + INT_32 i = (amount < 0) ? numBits - 1 : start; + INT_32 end = (amount < 0) ? start - 1 : numBits; + for (; (inc > 0) ? i < end : i > end; i += inc) + { + if ((i + amount < start) || (i + amount >= numBits)) + { + m_eq[i].Clear(); + } + else + { + m_eq[i + amount].copyto(m_eq[i]); + } + } + } +} + +CoordTerm& CoordEq::operator[](UINT_32 i) +{ + return m_eq[i]; +} + +VOID CoordEq::mort2d(Coordinate& c0, Coordinate& c1, UINT_32 start, UINT_32 end) +{ + if (end == 0) + { + ADDR_ASSERT(m_numBits > 0); + end = m_numBits - 1; + } + for (UINT_32 i = start; i <= end; i++) + { + UINT_32 select = (i - start) % 2; + Coordinate& c = (select == 0) ? c0 : c1; + m_eq[i].add(c); + c++; + } +} + +VOID CoordEq::mort3d(Coordinate& c0, Coordinate& c1, Coordinate& c2, UINT_32 start, UINT_32 end) +{ + if (end == 0) + { + ADDR_ASSERT(m_numBits > 0); + end = m_numBits - 1; + } + for (UINT_32 i = start; i <= end; i++) + { + UINT_32 select = (i - start) % 3; + Coordinate& c = (select == 0) ? c0 : ((select == 1) ? c1 : c2); + m_eq[i].add(c); + c++; + } +} + +BOOL_32 CoordEq::operator==(const CoordEq& b) +{ + BOOL_32 ret = TRUE; + + if (m_numBits != b.m_numBits) + { + ret = FALSE; + } + else + { + for (UINT_32 i = 0; i < m_numBits; i++) + { + if (m_eq[i] != b.m_eq[i]) + { + ret = FALSE; + break; + } + } + } + return ret; +} + +BOOL_32 CoordEq::operator!=(const CoordEq& b) +{ + return !(*this == b); +} + |