base,mem: Support AtomicOpFunctor in the classic memory system

AtomicOpFunctor can be used to implement atomic memory operations.
AtomicOpFunctor is captured inside a memory request and executed directly
in the memory hierarchy in a single step.

This patch enables AtomicOpFunctor pointers to be included in a memory
request and executed in a single step in the classic cache system.

This patch also makes the copy constructor of Request class do a deep
copy of AtomicOpFunctor object. This prevents a copy of a Request object
from accessing a deleted AtomicOpFunctor object.

Change-Id: I6649532b37f711e55f4552ad26893efeb300dd37
Reviewed-on: https://gem5-review.googlesource.com/8185
Reviewed-by: Nikos Nikoleris <nikos.nikoleris@arm.com>
Maintainer: Nikos Nikoleris <nikos.nikoleris@arm.com>
diff --git a/src/base/types.hh b/src/base/types.hh
index 05a29f8..d07c370 100644
--- a/src/base/types.hh
+++ b/src/base/types.hh
@@ -191,6 +191,7 @@
 struct AtomicOpFunctor
 {
     virtual void operator()(uint8_t *p) = 0;
+    virtual AtomicOpFunctor* clone() = 0;
     virtual ~AtomicOpFunctor() {}
 };
 
@@ -198,6 +199,7 @@
 struct TypedAtomicOpFunctor : public AtomicOpFunctor
 {
     void operator()(uint8_t *p) { execute((T *)p); }
+    virtual AtomicOpFunctor* clone() = 0;
     virtual void execute(T * p) = 0;
 };