summaryrefslogtreecommitdiff
path: root/src/cpu/simple/timing.hh
diff options
context:
space:
mode:
authorGabe Black <gblack@eecs.umich.edu>2009-04-06 10:19:36 -0700
committerGabe Black <gblack@eecs.umich.edu>2009-04-06 10:19:36 -0700
commitd080581db1f9ee4e1e6d07d2b01c13c67908a391 (patch)
treecc484b289fa5a30c4631f9faa1d8b456bffeebfc /src/cpu/simple/timing.hh
parent7a7c4c5fca83a8d47c7e71c9c080a882ebe204a9 (diff)
parent639cb0a42d953ee32bc7e96b0cdfa96cd40e9fc1 (diff)
downloadgem5-d080581db1f9ee4e1e6d07d2b01c13c67908a391.tar.xz
Merge ARM into the head. ARM will compile but may not actually work.
Diffstat (limited to 'src/cpu/simple/timing.hh')
-rw-r--r--src/cpu/simple/timing.hh195
1 files changed, 165 insertions, 30 deletions
diff --git a/src/cpu/simple/timing.hh b/src/cpu/simple/timing.hh
index f8b77604a..a02ec48c9 100644
--- a/src/cpu/simple/timing.hh
+++ b/src/cpu/simple/timing.hh
@@ -33,40 +33,181 @@
#include "cpu/simple/base.hh"
+#include "params/TimingSimpleCPU.hh"
+
class TimingSimpleCPU : public BaseSimpleCPU
{
public:
- struct Params : public BaseSimpleCPU::Params {
- };
-
- TimingSimpleCPU(Params *params);
+ TimingSimpleCPU(TimingSimpleCPUParams * params);
virtual ~TimingSimpleCPU();
virtual void init();
public:
- //
- enum Status {
- Idle,
- Running,
- IcacheRetry,
- IcacheWaitResponse,
- IcacheWaitSwitch,
- DcacheRetry,
- DcacheWaitResponse,
- DcacheWaitSwitch,
- SwitchedOut
+ Event *drainEvent;
+
+ private:
+
+ /*
+ * If an access needs to be broken into fragments, currently at most two,
+ * the the following two classes are used as the sender state of the
+ * packets so the CPU can keep track of everything. In the main packet
+ * sender state, there's an array with a spot for each fragment. If a
+ * fragment has already been accepted by the CPU, aka isn't waiting for
+ * a retry, it's pointer is NULL. After each fragment has successfully
+ * been processed, the "outstanding" counter is decremented. Once the
+ * count is zero, the entire larger access is complete.
+ */
+ class SplitMainSenderState : public Packet::SenderState
+ {
+ public:
+ int outstanding;
+ PacketPtr fragments[2];
+
+ int
+ getPendingFragment()
+ {
+ if (fragments[0]) {
+ return 0;
+ } else if (fragments[1]) {
+ return 1;
+ } else {
+ return -1;
+ }
+ }
};
- protected:
- Status _status;
+ class SplitFragmentSenderState : public Packet::SenderState
+ {
+ public:
+ SplitFragmentSenderState(PacketPtr _bigPkt, int _index) :
+ bigPkt(_bigPkt), index(_index)
+ {}
+ PacketPtr bigPkt;
+ int index;
+
+ void
+ clearFromParent()
+ {
+ SplitMainSenderState * main_send_state =
+ dynamic_cast<SplitMainSenderState *>(bigPkt->senderState);
+ main_send_state->fragments[index] = NULL;
+ }
+ };
- Status status() const { return _status; }
+ class FetchTranslation : public BaseTLB::Translation
+ {
+ protected:
+ TimingSimpleCPU *cpu;
- Event *drainEvent;
+ public:
+ FetchTranslation(TimingSimpleCPU *_cpu) : cpu(_cpu)
+ {}
- private:
+ void finish(Fault fault, RequestPtr req,
+ ThreadContext *tc, bool write)
+ {
+ cpu->sendFetch(fault, req, tc);
+ }
+ };
+ FetchTranslation fetchTranslation;
+
+ class DataTranslation : public BaseTLB::Translation
+ {
+ protected:
+ TimingSimpleCPU *cpu;
+ uint8_t *data;
+ uint64_t *res;
+ bool read;
+
+ public:
+ DataTranslation(TimingSimpleCPU *_cpu,
+ uint8_t *_data, uint64_t *_res, bool _read) :
+ cpu(_cpu), data(_data), res(_res), read(_read)
+ {}
+
+ void
+ finish(Fault fault, RequestPtr req,
+ ThreadContext *tc, bool write)
+ {
+ cpu->sendData(fault, req, data, res, read);
+ delete this;
+ }
+ };
+
+ class SplitDataTranslation : public BaseTLB::Translation
+ {
+ public:
+ struct WholeTranslationState
+ {
+ public:
+ int outstanding;
+ RequestPtr requests[2];
+ RequestPtr mainReq;
+ Fault faults[2];
+ uint8_t *data;
+ bool read;
+
+ WholeTranslationState(RequestPtr req1, RequestPtr req2,
+ RequestPtr main, uint8_t *_data, bool _read)
+ {
+ outstanding = 2;
+ requests[0] = req1;
+ requests[1] = req2;
+ mainReq = main;
+ faults[0] = faults[1] = NoFault;
+ data = _data;
+ read = _read;
+ }
+ };
+
+ TimingSimpleCPU *cpu;
+ int index;
+ WholeTranslationState *state;
+
+ SplitDataTranslation(TimingSimpleCPU *_cpu, int _index,
+ WholeTranslationState *_state) :
+ cpu(_cpu), index(_index), state(_state)
+ {}
+
+ void
+ finish(Fault fault, RequestPtr req,
+ ThreadContext *tc, bool write)
+ {
+ assert(state);
+ assert(state->outstanding);
+ state->faults[index] = fault;
+ if (--state->outstanding == 0) {
+ cpu->sendSplitData(state->faults[0],
+ state->faults[1],
+ state->requests[0],
+ state->requests[1],
+ state->mainReq,
+ state->data,
+ state->read);
+ delete state;
+ }
+ delete this;
+ }
+ };
+
+ void sendData(Fault fault, RequestPtr req,
+ uint8_t *data, uint64_t *res, bool read);
+ void sendSplitData(Fault fault1, Fault fault2,
+ RequestPtr req1, RequestPtr req2, RequestPtr req,
+ uint8_t *data, bool read);
+
+ void translationFault(Fault fault);
+
+ void buildPacket(PacketPtr &pkt, RequestPtr req, bool read);
+ void buildSplitPacket(PacketPtr &pkt1, PacketPtr &pkt2,
+ RequestPtr req1, RequestPtr req2, RequestPtr req,
+ uint8_t *data, bool read);
+
+ bool handleReadPacket(PacketPtr pkt);
+ // This function always implicitly uses dcache_pkt.
+ bool handleWritePacket();
class CpuPort : public Port
{
@@ -99,8 +240,7 @@ class TimingSimpleCPU : public BaseSimpleCPU
PacketPtr pkt;
TimingSimpleCPU *cpu;
- TickEvent(TimingSimpleCPU *_cpu)
- :Event(&mainEventQueue), cpu(_cpu) {}
+ TickEvent(TimingSimpleCPU *_cpu) : cpu(_cpu) {}
const char *description() const { return "Timing CPU tick"; }
void schedule(PacketPtr _pkt, Tick t);
};
@@ -189,18 +329,13 @@ class TimingSimpleCPU : public BaseSimpleCPU
template <class T>
Fault read(Addr addr, T &data, unsigned flags);
- Fault translateDataReadAddr(Addr vaddr, Addr &paddr,
- int size, unsigned flags);
-
template <class T>
Fault write(T data, Addr addr, unsigned flags, uint64_t *res);
- Fault translateDataWriteAddr(Addr vaddr, Addr &paddr,
- int size, unsigned flags);
-
void fetch();
+ void sendFetch(Fault fault, RequestPtr req, ThreadContext *tc);
void completeIfetch(PacketPtr );
- void completeDataAccess(PacketPtr );
+ void completeDataAccess(PacketPtr pkt);
void advanceInst(Fault fault);
/**
@@ -212,7 +347,7 @@ class TimingSimpleCPU : public BaseSimpleCPU
private:
typedef EventWrapper<TimingSimpleCPU, &TimingSimpleCPU::fetch> FetchEvent;
- FetchEvent *fetchEvent;
+ FetchEvent fetchEvent;
struct IprEvent : Event {
Packet *pkt;