#include "gemmstone/microkernel/package.hpp"
#include "ngen_decoder.hpp"
GEMMSTONE_NAMESPACE_START
namespace microkernel {
using namespace ngen;
Package::Status Package::finalize() {
using namespace ngen;
auto status = Status::Success;
auto product = npack::decodeHWIPVersion(gmdidCompat);
auto hw = getCore(product.family);
if (hw == HW::Unknown) return Status::UnsupportedHW;
Decoder decoder(hw, binary);
DependencyRegion dstRegion;
std::array<bool, GRF::maxRegs() + 1> clobbered = {false};
for (; !decoder.done(); decoder.advance()) {
auto op = decoder.opcode();
systolic |= (op == Opcode::dpas || op == Opcode::dpasw);
if (decoder.getOperandRegion(dstRegion, -1)) {
if (dstRegion.unspecified) {
status = Status::UncertainClobbers;
} else
for (int j = 0; j < dstRegion.size; j++)
clobbered[dstRegion.base + j] = true;
}
}
clobbers.clear();
int regBytes = GRF::bytes(hw);
int base = 0, len = 0;
for (int j = 0; j < int(clobbered.size()); j++) {
if (clobbered[j]) {
if (len > 0)
len++;
else
base = j, len = 1;
} else if (len > 0) {
clobbers.emplace_back(
RegisterRange(base * regBytes, len * regBytes));
len = 0;
}
}
uint32_t last = 0;
if (!clobbers.empty()) {
auto &final = clobbers.back();
last = final.boffset + final.blen;
}
for (const auto &argument : arguments)
for (auto &range : argument.location)
last = std::max(last, range.boffset + range.blen);
grfMin = (last + regBytes - 1) / regBytes;
uint32_t luid = 0;
uint32_t multiplier = 1357;
auto *u32ptr = (const uint32_t *)binary.data();
for (size_t i = 0; i < (binary.size() >> 2); i++) {
luid ^= u32ptr[i] * multiplier;
multiplier += 2;
luid = (luid << 3) | (luid >> 29);
}
this->luid = luid;
return status;
}
}
GEMMSTONE_NAMESPACE_END