/*
+ * Copyright (c) 2012-2013,2015 ARM Limited
+ * All rights reserved.
+ *
+ * The license below extends only to copyright in the software and shall
+ * not be construed as granting a license to any other intellectual
+ * property including but not limited to intellectual property relating
+ * to a hardware implementation of the functionality of the software
+ * licensed hereunder. You may use the software subject to the license
+ * terms below provided that you ensure that this notice is replicated
+ * unmodified and in its entirety in all distributions of the software,
+ * modified or unmodified, in source code or in binary form.
+ *
* Copyright (c) 2002-2005 The Regents of The University of Michigan
* All rights reserved.
*
#define __CPU_SIMPLE_ATOMIC_HH__
#include "cpu/simple/base.hh"
+#include "cpu/simple/exec_context.hh"
+#include "mem/request.hh"
#include "params/AtomicSimpleCPU.hh"
+#include "sim/probe/probe.hh"
class AtomicSimpleCPU : public BaseSimpleCPU
{
AtomicSimpleCPU(AtomicSimpleCPUParams *params);
virtual ~AtomicSimpleCPU();
- virtual void init();
+ void init() override;
private:
- struct TickEvent : public Event
- {
- AtomicSimpleCPU *cpu;
-
- TickEvent(AtomicSimpleCPU *c);
- void process();
- const char *description() const;
- };
-
- TickEvent tickEvent;
+ EventFunctionWrapper tickEvent;
const int width;
bool locked;
// main simulation loop (one cycle)
void tick();
+ /**
+ * Check if a system is in a drained state.
+ *
+ * We need to drain if:
+ * <ul>
+ * <li>We are in the middle of a microcode sequence as some CPUs
+ * (e.g., HW accelerated CPUs) can't be started in the middle
+ * of a gem5 microcode sequence.
+ *
+ * <li>The CPU is in a LLSC region. This shouldn't normally happen
+ * as these are executed atomically within a single tick()
+ * call. The only way this can happen at the moment is if
+ * there is an event in the PC event queue that affects the
+ * CPU state while it is in an LLSC region.
+ *
+ * <li>Stay at PC is true.
+ * </ul>
+ */
+ bool isDrained() {
+ SimpleExecContext &t_info = *threadInfo[curThread];
+
+ return t_info.thread->microPC() == 0 &&
+ !locked &&
+ !t_info.stayAtPC;
+ }
+
+ /**
+ * Try to complete a drain request.
+ *
+ * @returns true if the CPU is drained, false otherwise.
+ */
+ bool tryCompleteDrain();
+
/**
* An AtomicCPUPort overrides the default behaviour of the
- * recvAtomic and ignores the packet instead of panicking.
+ * recvAtomicSnoop and ignores the packet instead of panicking. It
+ * also provides an implementation for the purely virtual timing
+ * functions and panics on either of these.
*/
- class AtomicCPUPort : public CpuPort
+ class AtomicCPUPort : public MasterPort
{
public:
- AtomicCPUPort(const std::string &_name, BaseCPU* _cpu)
- : CpuPort(_name, _cpu)
+ AtomicCPUPort(const std::string &_name, BaseSimpleCPU* _cpu)
+ : MasterPort(_name, _cpu)
{ }
protected:
- virtual Tick recvAtomic(PacketPtr pkt)
+ bool recvTimingResp(PacketPtr pkt)
+ {
+ panic("Atomic CPU doesn't expect recvTimingResp!\n");
+ return true;
+ }
+
+ void recvReqRetry()
+ {
+ panic("Atomic CPU doesn't expect recvRetry!\n");
+ }
+
+ };
+
+ class AtomicCPUDPort : public AtomicCPUPort
+ {
+
+ public:
+
+ AtomicCPUDPort(const std::string &_name, BaseSimpleCPU* _cpu)
+ : AtomicCPUPort(_name, _cpu), cpu(_cpu)
{
- // Snooping a coherence request, just return
- return 0;
+ cacheBlockMask = ~(cpu->cacheLineSize() - 1);
}
+ bool isSnooping() const { return true; }
+
+ Addr cacheBlockMask;
+ protected:
+ BaseSimpleCPU *cpu;
+
+ virtual Tick recvAtomicSnoop(PacketPtr pkt);
+ virtual void recvFunctionalSnoop(PacketPtr pkt);
};
+
AtomicCPUPort icachePort;
- AtomicCPUPort dcachePort;
+ AtomicCPUDPort dcachePort;
- CpuPort physmemPort;
- bool hasPhysMemPort;
+ bool fastmem;
Request ifetch_req;
Request data_read_req;
Request data_write_req;
bool dcache_access;
Tick dcache_latency;
- Range<Addr> physMemAddr;
+ /** Probe Points. */
+ ProbePointArg<std::pair<SimpleThread*, const StaticInstPtr>> *ppCommit;
+
+ protected:
+
+ /** Return a reference to the data port. */
+ MasterPort &getDataPort() override { return dcachePort; }
+
+ /** Return a reference to the instruction port. */
+ MasterPort &getInstPort() override { return icachePort; }
+
+ /** Perform snoop for other cpu-local thread contexts. */
+ void threadSnoop(PacketPtr pkt, ThreadID sender);
public:
- virtual Port *getPort(const std::string &if_name, int idx = -1);
+ DrainState drain() override;
+ void drainResume() override;
- virtual void serialize(std::ostream &os);
- virtual void unserialize(Checkpoint *cp, const std::string §ion);
- virtual void resume();
+ void switchOut() override;
+ void takeOverFrom(BaseCPU *oldCPU) override;
- void switchOut();
- void takeOverFrom(BaseCPU *oldCPU);
+ void verifyMemoryMode() const override;
- virtual void activateContext(ThreadID thread_num, int delay);
- virtual void suspendContext(ThreadID thread_num);
+ void activateContext(ThreadID thread_num) override;
+ void suspendContext(ThreadID thread_num) override;
- Fault readMem(Addr addr, uint8_t *data, unsigned size, unsigned flags);
+ Fault readMem(Addr addr, uint8_t *data, unsigned size,
+ Request::Flags flags) override;
+
+ Fault initiateMemRead(Addr addr, unsigned size,
+ Request::Flags flags) override;
Fault writeMem(uint8_t *data, unsigned size,
- Addr addr, unsigned flags, uint64_t *res);
+ Addr addr, Request::Flags flags, uint64_t *res) override;
+
+ void regProbePoints() override;
/**
* Print state of address in memory system via PrintReq (for