/* * Copyright (c) 2015-2017 Advanced Micro Devices, Inc. * All rights reserved. * * Copyright (c) 2003-2005 The Regents of The University of Michigan * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer; * redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution; * neither the name of the copyright holders nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * Authors: Nathan Binkert * Anthony Gutierrez */ #ifndef __BASE_AMO_HH__ #define __BASE_AMO_HH__ #include #include #include struct AtomicOpFunctor { virtual void operator()(uint8_t *p) = 0; virtual AtomicOpFunctor* clone() = 0; virtual ~AtomicOpFunctor() {} }; template struct TypedAtomicOpFunctor : public AtomicOpFunctor { void operator()(uint8_t *p) { execute((T *)p); } virtual AtomicOpFunctor* clone() = 0; virtual void execute(T * p) = 0; }; template class AtomicGeneric2Op : public TypedAtomicOpFunctor { public: AtomicGeneric2Op(T _a, std::function _op) : a(_a), op(_op) {} AtomicOpFunctor* clone() override { return new AtomicGeneric2Op(*this); } void execute(T *b) override { op(b, a); } private: T a; std::function op; }; template class AtomicGeneric3Op : public TypedAtomicOpFunctor { public: AtomicGeneric3Op(T _a, T _c, std::function _op) : a(_a), c(_c), op(_op) {} AtomicOpFunctor* clone() override { return new AtomicGeneric3Op(*this); } void execute(T *b) override { op(b, a, c); } private: T a; T c; std::function op; }; template class AtomicGenericPair3Op : public TypedAtomicOpFunctor { public: AtomicGenericPair3Op(std::array& _a, std::array _c, std::function&, std::array)> _op) : a(_a), c(_c), op(_op) {} AtomicOpFunctor* clone() override { return new AtomicGenericPair3Op(*this); } void execute(T* b) override { op(b, a, c); } private: std::array a; std::array c; std::function&, std::array)> op; }; template class AtomicOpAnd : public TypedAtomicOpFunctor { public: T a; AtomicOpAnd(T _a) : a(_a) { } void execute(T *b) { *b &= a; } AtomicOpFunctor* clone () { return new AtomicOpAnd(a); } }; template class AtomicOpOr : public TypedAtomicOpFunctor { public: T a; AtomicOpOr(T _a) : a(_a) { } void execute(T *b) { *b |= a; } AtomicOpFunctor* clone () { return new AtomicOpOr(a); } }; template class AtomicOpXor : public TypedAtomicOpFunctor { public: T a; AtomicOpXor(T _a) : a(_a) {} void execute(T *b) { *b ^= a; } AtomicOpFunctor* clone () { return new AtomicOpXor(a); } }; template class AtomicOpExch : public TypedAtomicOpFunctor { public: T a; AtomicOpExch(T _a) : a(_a) { } void execute(T *b) { *b = a; } AtomicOpFunctor* clone () { return new AtomicOpExch(a); } }; template class AtomicOpAdd : public TypedAtomicOpFunctor { public: T a; AtomicOpAdd(T _a) : a(_a) { } void execute(T *b) { *b += a; } AtomicOpFunctor* clone () { return new AtomicOpAdd(a); } }; template class AtomicOpSub : public TypedAtomicOpFunctor { public: T a; AtomicOpSub(T _a) : a(_a) { } void execute(T *b) { *b -= a; } AtomicOpFunctor* clone () { return new AtomicOpSub(a); } }; template class AtomicOpInc : public TypedAtomicOpFunctor { public: AtomicOpInc() { } void execute(T *b) { *b += 1; } AtomicOpFunctor* clone () { return new AtomicOpInc(); } }; template class AtomicOpDec : public TypedAtomicOpFunctor { public: AtomicOpDec() {} void execute(T *b) { *b -= 1; } AtomicOpFunctor* clone () { return new AtomicOpDec(); } }; template class AtomicOpMax : public TypedAtomicOpFunctor { public: T a; AtomicOpMax(T _a) : a(_a) { } void execute(T *b) { if (a > *b) *b = a; } AtomicOpFunctor* clone () { return new AtomicOpMax(a); } }; template class AtomicOpMin : public TypedAtomicOpFunctor { public: T a; AtomicOpMin(T _a) : a(_a) {} void execute(T *b) { if (a < *b) *b = a; } AtomicOpFunctor* clone () { return new AtomicOpMin(a); } }; typedef std::unique_ptr AtomicOpFunctorPtr; #endif // __BASE_AMO_HH__