timing.cc (9433:34971d2e0019) timing.cc (9442:36967173340c)
1/*
2 * Copyright (c) 2010-2012 ARM Limited
3 * All rights reserved
4 *
5 * The license below extends only to copyright in the software and shall
6 * not be construed as granting a license to any other intellectual
7 * property including but not limited to intellectual property relating
8 * to a hardware implementation of the functionality of the software

--- 80 unchanged lines hidden (view full) ---

89{
90 pkt = _pkt;
91 cpu->schedule(this, t);
92}
93
94TimingSimpleCPU::TimingSimpleCPU(TimingSimpleCPUParams *p)
95 : BaseSimpleCPU(p), fetchTranslation(this), icachePort(this),
96 dcachePort(this), ifetch_pkt(NULL), dcache_pkt(NULL), previousCycle(0),
1/*
2 * Copyright (c) 2010-2012 ARM Limited
3 * All rights reserved
4 *
5 * The license below extends only to copyright in the software and shall
6 * not be construed as granting a license to any other intellectual
7 * property including but not limited to intellectual property relating
8 * to a hardware implementation of the functionality of the software

--- 80 unchanged lines hidden (view full) ---

89{
90 pkt = _pkt;
91 cpu->schedule(this, t);
92}
93
94TimingSimpleCPU::TimingSimpleCPU(TimingSimpleCPUParams *p)
95 : BaseSimpleCPU(p), fetchTranslation(this), icachePort(this),
96 dcachePort(this), ifetch_pkt(NULL), dcache_pkt(NULL), previousCycle(0),
97 fetchEvent(this)
97 fetchEvent(this), drainManager(NULL)
98{
99 _status = Idle;
100
98{
99 _status = Idle;
100
101 setDrainState(Drainable::Running);
102 system->totalNumInsts = 0;
103}
104
105
106TimingSimpleCPU::~TimingSimpleCPU()
107{
108}
109
101 system->totalNumInsts = 0;
102}
103
104
105TimingSimpleCPU::~TimingSimpleCPU()
106{
107}
108
110void
111TimingSimpleCPU::serialize(ostream &os)
112{
113 Drainable::State so_state(getDrainState());
114 SERIALIZE_ENUM(so_state);
115 BaseSimpleCPU::serialize(os);
116}
117
118void
119TimingSimpleCPU::unserialize(Checkpoint *cp, const string &section)
120{
121 Drainable::State so_state;
122 UNSERIALIZE_ENUM(so_state);
123 BaseSimpleCPU::unserialize(cp, section);
124}
125
126unsigned int
127TimingSimpleCPU::drain(DrainManager *drain_manager)
128{
109unsigned int
110TimingSimpleCPU::drain(DrainManager *drain_manager)
111{
129 // TimingSimpleCPU is ready to drain if it's not waiting for
130 // an access to complete.
131 if (_status == Idle ||
112 if (_status == Idle ||
132 _status == BaseSimpleCPU::Running ||
113 (_status == BaseSimpleCPU::Running && isDrained()) ||
133 _status == SwitchedOut) {
114 _status == SwitchedOut) {
134 setDrainState(Drainable::Drained);
115 assert(!fetchEvent.scheduled());
116 DPRINTF(Drain, "No need to drain.\n");
135 return 0;
136 } else {
117 return 0;
118 } else {
137 setDrainState(Drainable::Draining);
138 drainManager = drain_manager;
119 drainManager = drain_manager;
139 DPRINTF(Drain, "CPU not drained\n");
120 DPRINTF(Drain, "Requesting drain: %s\n", pcState());
121
122 // The fetch event can become descheduled if a drain didn't
123 // succeed on the first attempt. We need to reschedule it if
124 // the CPU is waiting for a microcode routine to complete.
125 if (_status == BaseSimpleCPU::Running && !isDrained() &&
126 !fetchEvent.scheduled()) {
127 schedule(fetchEvent, nextCycle());
128 }
129
140 return 1;
141 }
142}
143
144void
145TimingSimpleCPU::drainResume()
146{
130 return 1;
131 }
132}
133
134void
135TimingSimpleCPU::drainResume()
136{
137 assert(!fetchEvent.scheduled());
138
147 DPRINTF(SimpleCPU, "Resume\n");
148 if (_status != SwitchedOut && _status != Idle) {
149 if (system->getMemoryMode() != Enums::timing) {
150 fatal("The timing CPU requires the memory system to be in "
151 "'timing' mode.\n");
152 }
153
139 DPRINTF(SimpleCPU, "Resume\n");
140 if (_status != SwitchedOut && _status != Idle) {
141 if (system->getMemoryMode() != Enums::timing) {
142 fatal("The timing CPU requires the memory system to be in "
143 "'timing' mode.\n");
144 }
145
154 if (fetchEvent.scheduled())
155 deschedule(fetchEvent);
156
157 schedule(fetchEvent, nextCycle());
158 }
146 schedule(fetchEvent, nextCycle());
147 }
148}
159
149
160 setDrainState(Drainable::Running);
150bool
151TimingSimpleCPU::tryCompleteDrain()
152{
153 if (!drainManager)
154 return false;
155
156 DPRINTF(Drain, "tryCompleteDrain: %s\n", pcState());
157 if (!isDrained())
158 return false;
159
160 DPRINTF(Drain, "CPU done draining, processing drain event\n");
161 drainManager->signalDrainDone();
162 drainManager = NULL;
163
164 return true;
161}
162
163void
164TimingSimpleCPU::switchOut()
165{
166 BaseSimpleCPU::switchOut();
167
165}
166
167void
168TimingSimpleCPU::switchOut()
169{
170 BaseSimpleCPU::switchOut();
171
172 assert(!fetchEvent.scheduled());
168 assert(_status == BaseSimpleCPU::Running || _status == Idle);
173 assert(_status == BaseSimpleCPU::Running || _status == Idle);
174 assert(!stayAtPC);
175 assert(microPC() == 0);
176
169 _status = SwitchedOut;
170 numCycles += curCycle() - previousCycle;
177 _status = SwitchedOut;
178 numCycles += curCycle() - previousCycle;
171
172 // If we've been scheduled to resume but are then told to switch out,
173 // we'll need to cancel it.
174 if (fetchEvent.scheduled())
175 deschedule(fetchEvent);
176}
177
178
179void
180TimingSimpleCPU::takeOverFrom(BaseCPU *oldCPU)
181{
182 BaseSimpleCPU::takeOverFrom(oldCPU);
183

--- 155 unchanged lines hidden (view full) ---

339 if (traceData) {
340 // Since there was a fault, we shouldn't trace this instruction.
341 delete traceData;
342 traceData = NULL;
343 }
344
345 postExecute();
346
179}
180
181
182void
183TimingSimpleCPU::takeOverFrom(BaseCPU *oldCPU)
184{
185 BaseSimpleCPU::takeOverFrom(oldCPU);
186

--- 155 unchanged lines hidden (view full) ---

342 if (traceData) {
343 // Since there was a fault, we shouldn't trace this instruction.
344 delete traceData;
345 traceData = NULL;
346 }
347
348 postExecute();
349
347 if (getDrainState() == Drainable::Draining) {
348 advancePC(fault);
349 completeDrain();
350 } else {
351 advanceInst(fault);
352 }
350 advanceInst(fault);
353}
354
355void
356TimingSimpleCPU::buildPacket(PacketPtr &pkt, RequestPtr req, bool read)
357{
358 MemCmd cmd;
359 if (read) {
360 cmd = MemCmd::ReadReq;

--- 252 unchanged lines hidden (view full) ---

613 numCycles += curCycle() - previousCycle;
614 previousCycle = curCycle();
615}
616
617
618void
619TimingSimpleCPU::advanceInst(Fault fault)
620{
351}
352
353void
354TimingSimpleCPU::buildPacket(PacketPtr &pkt, RequestPtr req, bool read)
355{
356 MemCmd cmd;
357 if (read) {
358 cmd = MemCmd::ReadReq;

--- 252 unchanged lines hidden (view full) ---

611 numCycles += curCycle() - previousCycle;
612 previousCycle = curCycle();
613}
614
615
616void
617TimingSimpleCPU::advanceInst(Fault fault)
618{
621
622 if (_status == Faulting)
623 return;
624
625 if (fault != NoFault) {
626 advancePC(fault);
627 DPRINTF(SimpleCPU, "Fault occured, scheduling fetch event\n");
628 reschedule(fetchEvent, nextCycle(), true);
629 _status = Faulting;
630 return;
631 }
632
633
634 if (!stayAtPC)
635 advancePC(fault);
636
619 if (_status == Faulting)
620 return;
621
622 if (fault != NoFault) {
623 advancePC(fault);
624 DPRINTF(SimpleCPU, "Fault occured, scheduling fetch event\n");
625 reschedule(fetchEvent, nextCycle(), true);
626 _status = Faulting;
627 return;
628 }
629
630
631 if (!stayAtPC)
632 advancePC(fault);
633
634 if (tryCompleteDrain())
635 return;
636
637 if (_status == BaseSimpleCPU::Running) {
638 // kick off fetch of next instruction... callback from icache
639 // response will cause that instruction to be executed,
640 // keeping the CPU running.
641 fetch();
642 }
643}
644

--- 10 unchanged lines hidden (view full) ---

655 assert(!pkt || !pkt->isError());
656 assert(_status == IcacheWaitResponse);
657
658 _status = BaseSimpleCPU::Running;
659
660 numCycles += curCycle() - previousCycle;
661 previousCycle = curCycle();
662
637 if (_status == BaseSimpleCPU::Running) {
638 // kick off fetch of next instruction... callback from icache
639 // response will cause that instruction to be executed,
640 // keeping the CPU running.
641 fetch();
642 }
643}
644

--- 10 unchanged lines hidden (view full) ---

655 assert(!pkt || !pkt->isError());
656 assert(_status == IcacheWaitResponse);
657
658 _status = BaseSimpleCPU::Running;
659
660 numCycles += curCycle() - previousCycle;
661 previousCycle = curCycle();
662
663 if (getDrainState() == Drainable::Draining) {
664 if (pkt) {
665 delete pkt->req;
666 delete pkt;
667 }
668
669 completeDrain();
670 return;
671 }
672
673 preExecute();
674 if (curStaticInst && curStaticInst->isMemRef()) {
675 // load or store: just send to dcache
676 Fault fault = curStaticInst->initiateAcc(this, traceData);
677
678 // If we're not running now the instruction will complete in a dcache
679 // response callback or the instruction faulted and has started an
680 // ifetch

--- 130 unchanged lines hidden (view full) ---

811 TheISA::handleLockedRead(thread, pkt->req);
812 }
813
814 delete pkt->req;
815 delete pkt;
816
817 postExecute();
818
663 preExecute();
664 if (curStaticInst && curStaticInst->isMemRef()) {
665 // load or store: just send to dcache
666 Fault fault = curStaticInst->initiateAcc(this, traceData);
667
668 // If we're not running now the instruction will complete in a dcache
669 // response callback or the instruction faulted and has started an
670 // ifetch

--- 130 unchanged lines hidden (view full) ---

801 TheISA::handleLockedRead(thread, pkt->req);
802 }
803
804 delete pkt->req;
805 delete pkt;
806
807 postExecute();
808
819 if (getDrainState() == Drainable::Draining) {
820 advancePC(fault);
821 completeDrain();
822
823 return;
824 }
825
826 advanceInst(fault);
827}
828
809 advanceInst(fault);
810}
811
829
830void
831TimingSimpleCPU::completeDrain()
832{
833 DPRINTF(Drain, "CPU done draining, processing drain event\n");
834 setDrainState(Drainable::Drained);
835 drainManager->signalDrainDone();
836}
837
838bool
839TimingSimpleCPU::DcachePort::recvTimingResp(PacketPtr pkt)
840{
841 // delay processing of returned data until next CPU clock edge
842 Tick next_tick = cpu->nextCycle();
843
844 if (next_tick == curTick()) {
845 cpu->completeDataAccess(pkt);

--- 105 unchanged lines hidden ---
812bool
813TimingSimpleCPU::DcachePort::recvTimingResp(PacketPtr pkt)
814{
815 // delay processing of returned data until next CPU clock edge
816 Tick next_tick = cpu->nextCycle();
817
818 if (next_tick == curTick()) {
819 cpu->completeDataAccess(pkt);

--- 105 unchanged lines hidden ---