/******************************************************************************* * * MIT License * * Copyright (C) 2019-2022 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, sublicense, 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 above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * 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 NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS 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. * *******************************************************************************/ #include #include #include namespace Tensile { std::ostream& operator<<(std::ostream& stream, const KernelArguments& t) { size_t prevOffset = 0; for(auto const& name : t.m_names) { auto const& iter = t.m_argRecords.find(name); if(iter == t.m_argRecords.end()) throw std::runtime_error("Argument " + name + " not found in record."); auto const& record = iter->second; size_t offset = std::get(record); size_t size = std::get(record); if(prevOffset != offset) { stream << "[" << prevOffset << ".." << offset - 1 << "] " << std::endl; } stream << "[" << offset << ".." << offset + size - 1 << "] " << name << ":"; if(std::get(record)) { auto oldFill = stream.fill(); auto oldWidth = stream.width(); stream << std::hex; for(size_t i = offset; i < offset + size; i++) stream << " " << std::setfill('0') << std::setw(2) << static_cast(t.m_data[i]); stream << std::dec; stream.fill(oldFill); stream.width(oldWidth); if(t.m_log) { stream << " (" << std::get(record) << ")"; } } else { stream << " "; } stream << std::endl; prevOffset = offset + size; } return stream; } KernelArguments::KernelArguments(bool log) : m_log(log) { } KernelArguments::~KernelArguments() {} void KernelArguments::reserve(size_t bytes, size_t count) { m_data.reserve(bytes); m_names.reserve(count); if(m_log) m_argRecords.reserve(count); } bool KernelArguments::isFullyBound() const { if(!m_log) return true; for(auto const& record : m_argRecords) { if(!std::get(record.second)) return false; } return true; } void const* KernelArguments::data() const { if(!isFullyBound()) throw std::runtime_error("Arguments not fully bound."); return reinterpret_cast(m_data.data()); } size_t KernelArguments::size() const { return m_data.size(); } KernelArguments::const_iterator::const_iterator(KernelArguments const& args) : m_args(args) , m_currentArg(args.m_names.begin()) { if(!args.m_log) { throw std::runtime_error("KernelArguments::const_iterator requires m_log=true"); } assignCurrentArg(); } KernelArguments::const_iterator::const_iterator(KernelArguments const& args, std::string const& name) : m_args(args) , m_currentArg(args.m_names.begin()) { if(!args.m_log) { throw std::runtime_error("KernelArguments::const_iterator requires m_log=true"); } if(name.empty()) { m_currentArg = m_args.m_names.end(); } else { while(m_currentArg != args.m_names.end() && *m_currentArg != name) { m_currentArg++; } } assignCurrentArg(); } auto KernelArguments::const_iterator::operator++() -> const_iterator& { if(m_currentArg != m_args.m_names.end()) { ++m_currentArg; assignCurrentArg(); } return *this; } auto KernelArguments::const_iterator::operator++(int) -> const_iterator { if(m_currentArg != m_args.m_names.end()) { auto ret = *this; ++m_currentArg; assignCurrentArg(); return ret; } return *this; } bool KernelArguments::const_iterator::operator==(const const_iterator& rhs) const { return m_value == rhs.m_value; } bool KernelArguments::const_iterator::operator!=(const const_iterator& rhs) const { return m_value != rhs.m_value; } auto KernelArguments::const_iterator::operator*() const -> decltype(const_iterator::m_value) const& { return m_value; } auto KernelArguments::const_iterator::operator->() const -> decltype(const_iterator::m_value) const* { return &m_value; } void KernelArguments::const_iterator::reset() { m_currentArg = m_args.m_names.begin(); assignCurrentArg(); } void KernelArguments::const_iterator::assignCurrentArg() { if(m_currentArg != m_args.m_names.end()) { auto const& iter = m_args.m_argRecords.find(*m_currentArg); if(iter == m_args.m_argRecords.end()) { throw std::runtime_error("Argument " + *m_currentArg + " not found in record."); } auto const& record = iter->second; if(!m_args.isFullyBound()) { throw std::runtime_error("Arguments not fully bound."); } m_value = std::make_pair( static_cast(m_args.m_data.data() + std::get(record)), (size_t)std::get(record)); } else { m_value = std::make_pair((void const*)nullptr, (size_t)0); } } auto KernelArguments::begin() const -> const_iterator { return const_iterator(*this); } auto KernelArguments::end() const -> const_iterator { return const_iterator(*this, ""); } } // namespace Tensile