SE/FS: Expose the same methods on the CPUs in SE and FS modes.
authorGabe Black <gblack@eecs.umich.edu>
Tue, 1 Nov 2011 11:01:13 +0000 (04:01 -0700)
committerGabe Black <gblack@eecs.umich.edu>
Tue, 1 Nov 2011 11:01:13 +0000 (04:01 -0700)
15 files changed:
src/cpu/base.cc
src/cpu/base.hh
src/cpu/exec_context.hh
src/cpu/inorder/cpu.cc
src/cpu/inorder/cpu.hh
src/cpu/inorder/inorder_dyn_inst.cc
src/cpu/inorder/inorder_dyn_inst.hh
src/cpu/o3/cpu.cc
src/cpu/o3/cpu.hh
src/cpu/o3/dyn_inst.hh
src/cpu/o3/dyn_inst_impl.hh
src/cpu/simple/atomic.cc
src/cpu/simple/base.cc
src/cpu/simple/base.hh
src/cpu/simple/timing.cc

index d5343aa640a56ede9b69a999c93c49b8eab205aa..f20618698dd3fe9045b64aebd2ddba68e4a16c19 100644 (file)
@@ -47,6 +47,7 @@
 #include "cpu/thread_context.hh"
 #include "debug/SyscallVerbose.hh"
 #include "params/BaseCPU.hh"
+#include "sim/full_system.hh"
 #include "sim/process.hh"
 #include "sim/sim_events.hh"
 #include "sim/sim_exit.hh"
@@ -197,11 +198,13 @@ BaseCPU::BaseCPU(Params *p)
     }
     interrupts->setCPU(this);
 
+    if (FullSystem) {
 #if FULL_SYSTEM
-    profileEvent = NULL;
-    if (params()->profile)
-        profileEvent = new ProfileEvent(this, params()->profile);
+        profileEvent = NULL;
+        if (params()->profile)
+            profileEvent = new ProfileEvent(this, params()->profile);
 #endif
+    }
     tracer = params()->tracer;
 }
 
@@ -225,10 +228,10 @@ BaseCPU::init()
 void
 BaseCPU::startup()
 {
-#if FULL_SYSTEM
-    if (!params()->defer_registration && profileEvent)
-        schedule(profileEvent, curTick());
-#endif
+    if (FullSystem) {
+        if (!params()->defer_registration && profileEvent)
+            schedule(profileEvent, curTick());
+    }
 
     if (params()->progress_interval) {
         Tick num_ticks = ticks(params()->progress_interval);
@@ -268,9 +271,6 @@ BaseCPU::regStats()
         }
     } else if (size == 1)
         threadContexts[0]->regStats(name());
-
-#if FULL_SYSTEM
-#endif
 }
 
 Tick
@@ -312,9 +312,9 @@ BaseCPU::registerThreadContexts()
             tc->setContextId(system->registerThreadContext(tc, _cpuId));
         else
             tc->setContextId(system->registerThreadContext(tc));
-#if !FULL_SYSTEM
-        tc->getProcessPtr()->assignThreadContext(tc->contextId());
-#endif
+
+        if (!FullSystem)
+            tc->getProcessPtr()->assignThreadContext(tc->contextId());
     }
 }
 
@@ -333,11 +333,8 @@ BaseCPU::findContext(ThreadContext *tc)
 void
 BaseCPU::switchOut()
 {
-//    panic("This CPU doesn't support sampling!");
-#if FULL_SYSTEM
     if (profileEvent && profileEvent->scheduled())
         deschedule(profileEvent);
-#endif
 }
 
 void
@@ -391,13 +388,13 @@ BaseCPU::takeOverFrom(BaseCPU *oldCPU, Port *ic, Port *dc)
     interrupts = oldCPU->interrupts;
     interrupts->setCPU(this);
 
-#if FULL_SYSTEM
-    for (ThreadID i = 0; i < size; ++i)
-        threadContexts[i]->profileClear();
+    if (FullSystem) {
+        for (ThreadID i = 0; i < size; ++i)
+            threadContexts[i]->profileClear();
 
-    if (profileEvent)
-        schedule(profileEvent, curTick());
-#endif
+        if (profileEvent)
+            schedule(profileEvent, curTick());
+    }
 
     // Connect new CPU to old CPU's memory only if new CPU isn't
     // connected to anything.  Also connect old CPU's memory to new
@@ -416,7 +413,6 @@ BaseCPU::takeOverFrom(BaseCPU *oldCPU, Port *ic, Port *dc)
 }
 
 
-#if FULL_SYSTEM
 BaseCPU::ProfileEvent::ProfileEvent(BaseCPU *_cpu, Tick _interval)
     : cpu(_cpu), interval(_interval)
 { }
@@ -433,8 +429,6 @@ BaseCPU::ProfileEvent::process()
     cpu->schedule(this, curTick() + interval);
 }
 
-#endif // FULL_SYSTEM
-
 void
 BaseCPU::serialize(std::ostream &os)
 {
index 9c75539b1cdedc5b5119f618031ea98208a63d20..c15186e84e6913dff6779b393c8de7b2ccf3e7ee 100644 (file)
@@ -44,6 +44,7 @@
 #include "config/the_isa.hh"
 #include "mem/mem_object.hh"
 #include "sim/eventq.hh"
+#include "sim/full_system.hh"
 #include "sim/insttracer.hh"
 
 class BaseCPUParams;
@@ -132,17 +133,14 @@ class BaseCPU : public MemObject
         return interrupts;
     }
 
-#if FULL_SYSTEM
     virtual void wakeup() = 0;
-#endif
 
     void
     postInterrupt(int int_num, int index)
     {
         interrupts->post(int_num, index);
-#if FULL_SYSTEM
-        wakeup();
-#endif
+        if (FullSystem)
+            wakeup();
     }
 
     void
index 61c9b24a98e2ee02dcbc71fb6767e2eee54c639c..2f4d26976914c2b12e6ff8e84f565db9f6edcc33 100644 (file)
@@ -111,7 +111,6 @@ class ExecContext {
     Fault writeMem(uint8_t *data, unsigned size,
                    Addr addr, unsigned flags, uint64_t *res);
 
-#if FULL_SYSTEM
     /** Somewhat Alpha-specific function that handles returning from
      * an error or interrupt. */
     Fault hwrei();
@@ -121,10 +120,9 @@ class ExecContext {
      * return value is false, actual PAL call will be suppressed.
      */
     bool simPalCheck(int palFunc);
-#else
+
     /** Executes a syscall specified by the callnum. */
     void syscall(int64_t callnum);
-#endif
 
     /** Finish a DTB address translation. */
     void finishTranslation(WholeTranslationState *state);
index 97fbe737e3d00d50d6ed2003accf04ba8334aa44..226b2d8ea0aaa91a75233f0b89f68b66565135e5 100644 (file)
@@ -1688,7 +1688,6 @@ InOrderCPU::wakeCPU()
     schedule(&tickEvent, nextCycle(curTick()));
 }
 
-#if FULL_SYSTEM
 // Lots of copied full system code...place into BaseCPU class?
 void
 InOrderCPU::wakeup()
@@ -1701,7 +1700,6 @@ InOrderCPU::wakeup()
     DPRINTF(Quiesce, "Suspended Processor woken\n");
     threadContexts[0]->activate();
 }
-#endif
 
 void
 InOrderCPU::syscallContext(Fault fault, ThreadID tid, DynInstPtr inst, int delay)
index dd53f3ce5f7cd69a8020ccb3698c9082acb17dd3..8e915c08c7dcd1c47bcee3f5761d09d4581f9d55 100644 (file)
@@ -751,9 +751,7 @@ class InOrderCPU : public BaseCPU
     /** Wakes the CPU, rescheduling the CPU if it's not already active. */
     void wakeCPU();
 
-#if FULL_SYSTEM
     virtual void wakeup();
-#endif
 
     /* LL/SC debug functionality
     unsigned stCondFails;
index ff178f6d3ee56cc60119c8b0951737aa6892ca83..043b211343553105b3c4022624915ee97ab10519 100644 (file)
@@ -45,6 +45,7 @@
 #include "cpu/exetrace.hh"
 #include "debug/InOrderDynInst.hh"
 #include "mem/request.hh"
+#include "sim/full_system.hh"
 
 using namespace std;
 using namespace TheISA;
@@ -269,8 +270,6 @@ InOrderDynInst::memAccess()
 }
 
 
-#if FULL_SYSTEM
-
 Fault
 InOrderDynInst::hwrei()
 {
@@ -311,17 +310,16 @@ InOrderDynInst::simPalCheck(int palFunc)
 #endif
     return this->cpu->simPalCheck(palFunc, this->threadNumber);
 }
-#endif
 
 void
 InOrderDynInst::syscall(int64_t callnum)
 {
-#if FULL_SYSTEM
-    panic("Syscall emulation isn't available in FS mode.\n");
-#else
-    syscallNum = callnum;
-    cpu->syscallContext(NoFault, this->threadNumber, this);
-#endif
+    if (FullSystem) {
+        panic("Syscall emulation isn't available in FS mode.\n");
+    } else {
+        syscallNum = callnum;
+        cpu->syscallContext(NoFault, this->threadNumber, this);
+    }
 }
 
 void
index f49476ec595c5d4763176918279bd8bdb12a4b5a..4dd5f3fda9db186aeaa4d556a51f185f2ff5d21d 100644 (file)
@@ -517,15 +517,12 @@ class InOrderDynInst : public FastAlloc, public RefCounted
     void setCurResSlot(unsigned slot_num) { curResSlot = slot_num; }
 
     /** Calls a syscall. */
-#if FULL_SYSTEM
     /** Calls hardware return from error interrupt. */
     Fault hwrei();
     /** Traps to handle specified fault. */
     void trap(Fault fault);
     bool simPalCheck(int palFunc);
-#else
     short syscallNum;
-#endif
 
     /** Emulates a syscall. */
     void syscall(int64_t callnum);
index 1ffd014cdf4c45f11437481f6308fbfa6b5920a6..08cf0a692a4f38ea6f00ce0604ae453301ce2b6d 100644 (file)
@@ -31,6 +31,7 @@
  *          Rick Strong
  */
 
+#include "arch/kernel_stats.hh"
 #include "config/full_system.hh"
 #include "config/the_isa.hh"
 #include "config/use_checker.hh"
@@ -38,6 +39,7 @@
 #include "cpu/o3/isa_specific.hh"
 #include "cpu/o3/thread_context.hh"
 #include "cpu/activity.hh"
+#include "cpu/quiesce_event.hh"
 #include "cpu/simple_thread.hh"
 #include "cpu/thread_context.hh"
 #include "debug/Activity.hh"
 #include "debug/Quiesce.hh"
 #include "enums/MemoryMode.hh"
 #include "sim/core.hh"
+#include "sim/process.hh"
 #include "sim/stat_control.hh"
 #include "sim/system.hh"
 
-#if FULL_SYSTEM
-#include "cpu/quiesce_event.hh"
-#else
-#include "sim/process.hh"
-#endif
-
 #if USE_CHECKER
 #include "cpu/checker/cpu.hh"
 #endif
@@ -896,7 +893,6 @@ FullO3CPU<Impl>::activateWhenReady(ThreadID tid)
     }
 }
 
-#if FULL_SYSTEM
 template <class Impl>
 Fault
 FullO3CPU<Impl>::hwrei(ThreadID tid)
@@ -973,7 +969,6 @@ FullO3CPU<Impl>::updateMemPorts()
     for (ThreadID i = 0; i < size; ++i)
         thread[i]->connectMemPorts(thread[i]->getTC());
 }
-#endif
 
 template <class Impl>
 void
@@ -1594,7 +1589,6 @@ FullO3CPU<Impl>::wakeCPU()
     schedule(tickEvent, nextCycle());
 }
 
-#if FULL_SYSTEM
 template <class Impl>
 void
 FullO3CPU<Impl>::wakeup()
@@ -1607,7 +1601,6 @@ FullO3CPU<Impl>::wakeup()
     DPRINTF(Quiesce, "Suspended Processor woken\n");
     this->threadContexts[0]->activate();
 }
-#endif
 
 template <class Impl>
 ThreadID
index 8eb32fae68b2422b3469de0dde63ad4c92637a8d..6de6ea6efb8af97b944b0569a0c11657aae117b3 100644 (file)
@@ -378,7 +378,6 @@ class FullO3CPU : public BaseO3CPU
     /** Traps to handle given fault. */
     void trap(Fault fault, ThreadID tid, StaticInstPtr inst);
 
-#if FULL_SYSTEM
     /** HW return from error interrupt. */
     Fault hwrei(ThreadID tid);
 
@@ -402,7 +401,6 @@ class FullO3CPU : public BaseO3CPU
 
     /** Check if this address is a valid data address. */
     bool validDataAddr(Addr addr) { return true; }
-#endif
 
     /** Register accessors.  Index refers to the physical register index. */
 
@@ -631,9 +629,7 @@ class FullO3CPU : public BaseO3CPU
     /** Wakes the CPU, rescheduling the CPU if it's not already active. */
     void wakeCPU();
 
-#if FULL_SYSTEM
     virtual void wakeup();
-#endif
 
     /** Gets a free thread id. Use if thread ids change across system. */
     ThreadID getFreeTid();
index e58eb99c5f3a9a393ca9128bca897f7ff4cb6199..1b101ede930a0cb6bbb737cb352a3945d56ed19c 100644 (file)
@@ -199,13 +199,11 @@ class BaseO3DynInst : public BaseDynInst<Impl>
                 this->setFloatRegOperandBits(this->staticInst.get(), idx, this->cpu->readFloatRegBits(prev_phys_reg));
         }
     }
-#if FULL_SYSTEM
     /** Calls hardware return from error interrupt. */
     Fault hwrei();
     /** Traps to handle specified fault. */
     void trap(Fault fault);
     bool simPalCheck(int palFunc);
-#endif
 
     /** Emulates a syscall. */
     void syscall(int64_t callnum);
index 500d63de88ba0d547301a34062ebdb3e2c928044..93ae834416518e6530f38c5bc6dd16f5fdeb3b95 100644 (file)
@@ -42,6 +42,7 @@
 
 #include "base/cp_annotate.hh"
 #include "cpu/o3/dyn_inst.hh"
+#include "sim/full_system.hh"
 
 template <class Impl>
 BaseO3DynInst<Impl>::BaseO3DynInst(StaticInstPtr staticInst,
@@ -143,7 +144,6 @@ BaseO3DynInst<Impl>::completeAcc(PacketPtr pkt)
     return this->fault;
 }
 
-#if FULL_SYSTEM
 template <class Impl>
 Fault
 BaseO3DynInst<Impl>::hwrei()
@@ -188,24 +188,23 @@ BaseO3DynInst<Impl>::simPalCheck(int palFunc)
 #endif
     return this->cpu->simPalCheck(palFunc, this->threadNumber);
 }
-#endif
 
 template <class Impl>
 void
 BaseO3DynInst<Impl>::syscall(int64_t callnum)
 {
-#if FULL_SYSTEM
-    panic("Syscall emulation isn't available in FS mode.\n");
-#else
-    // HACK: check CPU's nextPC before and after syscall. If it
-    // changes, update this instruction's nextPC because the syscall
-    // must have changed the nextPC.
-    TheISA::PCState curPC = this->cpu->pcState(this->threadNumber);
-    this->cpu->syscall(callnum, this->threadNumber);
-    TheISA::PCState newPC = this->cpu->pcState(this->threadNumber);
-    if (!(curPC == newPC)) {
-        this->pcState(newPC);
+    if (FullSystem) {
+        panic("Syscall emulation isn't available in FS mode.\n");
+    } else {
+        // HACK: check CPU's nextPC before and after syscall. If it
+        // changes, update this instruction's nextPC because the syscall
+        // must have changed the nextPC.
+        TheISA::PCState curPC = this->cpu->pcState(this->threadNumber);
+        this->cpu->syscall(callnum, this->threadNumber);
+        TheISA::PCState newPC = this->cpu->pcState(this->threadNumber);
+        if (!(curPC == newPC)) {
+            this->pcState(newPC);
+        }
     }
-#endif
 }
 
index 5376519d4311af797b9c6cd2ae236c453216d18a..9995ed55e8b7aedbdcda73e8d2395492c2c19bb3 100644 (file)
@@ -42,6 +42,7 @@
 #include "params/AtomicSimpleCPU.hh"
 #include "sim/faults.hh"
 #include "sim/system.hh"
+#include "sim/full_system.hh"
 
 using namespace std;
 using namespace TheISA;
@@ -83,15 +84,16 @@ void
 AtomicSimpleCPU::init()
 {
     BaseCPU::init();
+    if (FullSystem) {
+        ThreadID size = threadContexts.size();
+        for (ThreadID i = 0; i < size; ++i) {
 #if FULL_SYSTEM
-    ThreadID size = threadContexts.size();
-    for (ThreadID i = 0; i < size; ++i) {
-        ThreadContext *tc = threadContexts[i];
-
-        // initialize CPU, including PC
-        TheISA::initCPU(tc, tc->contextId());
-    }
+            ThreadContext *tc = threadContexts[i];
+            // initialize CPU, including PC
+            TheISA::initCPU(tc, tc->contextId());
 #endif
+        }
+    }
     if (hasPhysMemPort) {
         bool snoop = false;
         AddrRangeList pmAddrList;
@@ -150,11 +152,11 @@ AtomicSimpleCPU::DcachePort::setPeer(Port *port)
 {
     Port::setPeer(port);
 
-#if FULL_SYSTEM
-    // Update the ThreadContext's memory ports (Functional/Virtual
-    // Ports)
-    cpu->tcBase()->connectMemPorts(cpu->tcBase());
-#endif
+    if (FullSystem) {
+        // Update the ThreadContext's memory ports (Functional/Virtual
+        // Ports)
+        cpu->tcBase()->connectMemPorts(cpu->tcBase());
+    }
 }
 
 AtomicSimpleCPU::AtomicSimpleCPU(AtomicSimpleCPUParams *p)
@@ -617,7 +619,7 @@ AtomicSimpleCPUParams::create()
 {
     numThreads = 1;
 #if !FULL_SYSTEM
-    if (workload.size() != 1)
+    if (!FullSystem && workload.size() != 1)
         panic("only one workload allowed");
 #endif
     return new AtomicSimpleCPU(this);
index 70e2c39e65d213a607d6aa8853daaae6da59768a..d0e15eee91e9646e4ccbd957971e3829b72de0ee 100644 (file)
  */
 
 #include "arch/faults.hh"
+#include "arch/kernel_stats.hh"
+#include "arch/stacktrace.hh"
+#include "arch/tlb.hh"
 #include "arch/utility.hh"
+#include "arch/vtophys.hh"
 #include "base/loader/symtab.hh"
 #include "base/cp_annotate.hh"
 #include "base/cprintf.hh"
@@ -63,6 +67,7 @@
 #include "debug/Decode.hh"
 #include "debug/Fetch.hh"
 #include "debug/Quiesce.hh"
+#include "mem/mem_object.hh"
 #include "mem/packet.hh"
 #include "mem/request.hh"
 #include "params/BaseSimpleCPU.hh"
 #include "sim/stats.hh"
 #include "sim/system.hh"
 
-#if FULL_SYSTEM
-#include "arch/kernel_stats.hh"
-#include "arch/stacktrace.hh"
-#include "arch/tlb.hh"
-#include "arch/vtophys.hh"
-#else // !FULL_SYSTEM
-#include "mem/mem_object.hh"
-#endif // FULL_SYSTEM
-
 using namespace std;
 using namespace TheISA;
 
@@ -290,15 +286,12 @@ change_thread_state(ThreadID tid, int activate, int priority)
 {
 }
 
-#if FULL_SYSTEM
 Addr
 BaseSimpleCPU::dbg_vtophys(Addr addr)
 {
     return vtophys(tc, addr);
 }
-#endif // FULL_SYSTEM
 
-#if FULL_SYSTEM
 void
 BaseSimpleCPU::wakeup()
 {
@@ -308,12 +301,10 @@ BaseSimpleCPU::wakeup()
     DPRINTF(Quiesce,"Suspended Processor awoke\n");
     thread->activate();
 }
-#endif // FULL_SYSTEM
 
 void
 BaseSimpleCPU::checkForInterrupts()
 {
-#if FULL_SYSTEM
     if (checkInterrupts(tc)) {
         Fault interrupt = interrupts->getInterrupt(tc);
 
@@ -324,7 +315,6 @@ BaseSimpleCPU::checkForInterrupts()
             predecoder.reset();
         }
     }
-#endif
 }
 
 
@@ -422,7 +412,6 @@ BaseSimpleCPU::postExecute()
 
     TheISA::PCState pc = tc->pcState();
     Addr instAddr = pc.instAddr();
-#if FULL_SYSTEM
     if (thread->profile) {
         bool usermode = TheISA::inUserMode(tc);
         thread->profilePC = usermode ? 1 : instAddr;
@@ -430,7 +419,6 @@ BaseSimpleCPU::postExecute()
         if (node)
             thread->profileNode = node;
     }
-#endif
 
     if (curStaticInst->isMemRef()) {
         numMemRefs++;
index ad281aa2b88b45ee7a91246fd0d021b48b677383..6272560a185948aec705cc8ef71e09ec51ba8b09 100644 (file)
@@ -35,7 +35,6 @@
 
 #include "arch/predecoder.hh"
 #include "base/statistics.hh"
-#include "config/full_system.hh"
 #include "config/the_isa.hh"
 #include "cpu/base.hh"
 #include "cpu/decode.hh"
 #include "mem/port.hh"
 #include "mem/request.hh"
 #include "sim/eventq.hh"
+#include "sim/full_system.hh"
 #include "sim/system.hh"
 
 // forward declarations
-#if FULL_SYSTEM
-class Processor;
-namespace TheISA
-{
-    class ITB;
-    class DTB;
-}
+class Checkpoint;
 class MemObject;
-
-#else
-
 class Process;
-
-#endif // FULL_SYSTEM
+class Processor;
+class ThreadContext;
 
 namespace TheISA
 {
+    class DTB;
+    class ITB;
     class Predecoder;
 }
-class ThreadContext;
-class Checkpoint;
 
 namespace Trace {
     class InstRecord;
@@ -141,11 +132,9 @@ class BaseSimpleCPU : public BaseCPU
 
   public:
 
-#if FULL_SYSTEM
     Addr dbg_vtophys(Addr addr);
 
     bool interval_stats;
-#endif
 
     // current instruction
     TheISA::MachInst inst;
@@ -399,19 +388,16 @@ class BaseSimpleCPU : public BaseCPU
 
     //Fault CacheOp(uint8_t Op, Addr EA);
 
-#if FULL_SYSTEM
     Fault hwrei() { return thread->hwrei(); }
     bool simPalCheck(int palFunc) { return thread->simPalCheck(palFunc); }
-#endif
 
     void
     syscall(int64_t callnum)
     {
-#if FULL_SYSTEM
-        panic("Syscall emulation isn't available in FS mode.\n");
-#else
-        thread->syscall(callnum);
-#endif
+        if (FullSystem)
+            panic("Syscall emulation isn't available in FS mode.\n");
+        else
+            thread->syscall(callnum);
     }
 
     bool misspeculating() { return thread->misspeculating(); }
index e2151d974993b7423537f4ed3f10249c7f4c0e8c..cd640da3196ff5de4db43d072506748fa6246ba0 100644 (file)
@@ -54,6 +54,7 @@
 #include "mem/packet_access.hh"
 #include "params/TimingSimpleCPU.hh"
 #include "sim/faults.hh"
+#include "sim/full_system.hh"
 #include "sim/system.hh"
 
 using namespace std;
@@ -74,14 +75,15 @@ void
 TimingSimpleCPU::init()
 {
     BaseCPU::init();
+    if (FullSystem) {
+        for (int i = 0; i < threadContexts.size(); ++i) {
 #if FULL_SYSTEM
-    for (int i = 0; i < threadContexts.size(); ++i) {
-        ThreadContext *tc = threadContexts[i];
-
-        // initialize CPU, including PC
-        TheISA::initCPU(tc, _cpuId);
-    }
+            ThreadContext *tc = threadContexts[i];
+            // initialize CPU, including PC
+            TheISA::initCPU(tc, _cpuId);
 #endif
+        }
+    }
 }
 
 Tick
@@ -879,11 +881,11 @@ TimingSimpleCPU::DcachePort::setPeer(Port *port)
 {
     Port::setPeer(port);
 
-#if FULL_SYSTEM
-    // Update the ThreadContext's memory ports (Functional/Virtual
-    // Ports)
-    cpu->tcBase()->connectMemPorts(cpu->tcBase());
-#endif
+    if (FullSystem) {
+        // Update the ThreadContext's memory ports (Functional/Virtual
+        // Ports)
+        cpu->tcBase()->connectMemPorts(cpu->tcBase());
+    }
 }
 
 bool
@@ -1008,7 +1010,7 @@ TimingSimpleCPUParams::create()
 {
     numThreads = 1;
 #if !FULL_SYSTEM
-    if (workload.size() != 1)
+    if (!FullSystem && workload.size() != 1)
         panic("only one workload allowed");
 #endif
     return new TimingSimpleCPU(this);