/* * 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 <array> #include <cstdint> #include <functional> struct AtomicOpFunctor { virtual void operator()(uint8_t *p) = 0; virtual AtomicOpFunctor* clone() = 0; virtual ~AtomicOpFunctor() {} }; template <class T> struct TypedAtomicOpFunctor : public AtomicOpFunctor { void operator()(uint8_t *p) { execute((T *)p); } virtual AtomicOpFunctor* clone() = 0; virtual void execute(T * p) = 0; }; template<typename T> class AtomicGeneric2Op : public TypedAtomicOpFunctor<T> { public: AtomicGeneric2Op(T _a, std::function<void(T*,T)> _op) : a(_a), op(_op) {} AtomicOpFunctor* clone() override { return new AtomicGeneric2Op<T>(*this); } void execute(T *b) override { op(b, a); } private: T a; std::function<void(T*,T)> op; }; template<typename T> class AtomicGeneric3Op : public TypedAtomicOpFunctor<T> { public: AtomicGeneric3Op(T _a, T _c, std::function<void(T*, T, T)> _op) : a(_a), c(_c), op(_op) {} AtomicOpFunctor* clone() override { return new AtomicGeneric3Op<T>(*this); } void execute(T *b) override { op(b, a, c); } private: T a; T c; std::function<void(T*, T, T)> op; }; template<typename T> class AtomicGenericPair3Op : public TypedAtomicOpFunctor<T> { public: AtomicGenericPair3Op(std::array<T, 2>& _a, std::array<T, 2> _c, std::function<void(T*, std::array<T, 2>&, std::array<T, 2>)> _op) : a(_a), c(_c), op(_op) {} AtomicOpFunctor* clone() override { return new AtomicGenericPair3Op<T>(*this); } void execute(T* b) override { op(b, a, c); } private: std::array<T, 2> a; std::array<T, 2> c; std::function<void(T*, std::array<T, 2>&, std::array<T, 2>)> op; }; template<typename T> class AtomicOpAnd : public TypedAtomicOpFunctor<T> { public: T a; AtomicOpAnd(T _a) : a(_a) { } void execute(T *b) { *b &= a; } AtomicOpFunctor* clone () { return new AtomicOpAnd(a); } }; template<typename T> class AtomicOpOr : public TypedAtomicOpFunctor<T> { public: T a; AtomicOpOr(T _a) : a(_a) { } void execute(T *b) { *b |= a; } AtomicOpFunctor* clone () { return new AtomicOpOr(a); } }; template<typename T> class AtomicOpXor : public TypedAtomicOpFunctor<T> { public: T a; AtomicOpXor(T _a) : a(_a) {} void execute(T *b) { *b ^= a; } AtomicOpFunctor* clone () { return new AtomicOpXor(a); } }; template<typename T> class AtomicOpExch : public TypedAtomicOpFunctor<T> { public: T a; AtomicOpExch(T _a) : a(_a) { } void execute(T *b) { *b = a; } AtomicOpFunctor* clone () { return new AtomicOpExch(a); } }; template<typename T> class AtomicOpAdd : public TypedAtomicOpFunctor<T> { public: T a; AtomicOpAdd(T _a) : a(_a) { } void execute(T *b) { *b += a; } AtomicOpFunctor* clone () { return new AtomicOpAdd(a); } }; template<typename T> class AtomicOpSub : public TypedAtomicOpFunctor<T> { public: T a; AtomicOpSub(T _a) : a(_a) { } void execute(T *b) { *b -= a; } AtomicOpFunctor* clone () { return new AtomicOpSub(a); } }; template<typename T> class AtomicOpInc : public TypedAtomicOpFunctor<T> { public: AtomicOpInc() { } void execute(T *b) { *b += 1; } AtomicOpFunctor* clone () { return new AtomicOpInc(); } }; template<typename T> class AtomicOpDec : public TypedAtomicOpFunctor<T> { public: AtomicOpDec() {} void execute(T *b) { *b -= 1; } AtomicOpFunctor* clone () { return new AtomicOpDec(); } }; template<typename T> class AtomicOpMax : public TypedAtomicOpFunctor<T> { public: T a; AtomicOpMax(T _a) : a(_a) { } void execute(T *b) { if (a > *b) *b = a; } AtomicOpFunctor* clone () { return new AtomicOpMax(a); } }; template<typename T> class AtomicOpMin : public TypedAtomicOpFunctor<T> { 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<AtomicOpFunctor> AtomicOpFunctorPtr; #endif // __BASE_AMO_HH__