base.cc revision 5310:4164e6bfcc8a
12SN/A/*
29952Sdam.sunwoo@arm.com * Copyright (c) 2002-2005 The Regents of The University of Michigan
39952Sdam.sunwoo@arm.com * All rights reserved.
49952Sdam.sunwoo@arm.com *
59952Sdam.sunwoo@arm.com * Redistribution and use in source and binary forms, with or without
69952Sdam.sunwoo@arm.com * modification, are permitted provided that the following conditions are
79952Sdam.sunwoo@arm.com * met: redistributions of source code must retain the above copyright
89952Sdam.sunwoo@arm.com * notice, this list of conditions and the following disclaimer;
99952Sdam.sunwoo@arm.com * redistributions in binary form must reproduce the above copyright
109952Sdam.sunwoo@arm.com * notice, this list of conditions and the following disclaimer in the
119952Sdam.sunwoo@arm.com * documentation and/or other materials provided with the distribution;
129952Sdam.sunwoo@arm.com * neither the name of the copyright holders nor the names of its
139952Sdam.sunwoo@arm.com * contributors may be used to endorse or promote products derived from
141762SN/A * this software without specific prior written permission.
159983Sstever@gmail.com *
169983Sstever@gmail.com * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
172SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
182SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
192SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
202SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
212SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
222SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
232SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
242SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
252SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
262SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
272SN/A *
282SN/A * Authors: Steve Reinhardt
292SN/A */
302SN/A
312SN/A#include "arch/utility.hh"
322SN/A#include "arch/faults.hh"
332SN/A#include "base/cprintf.hh"
342SN/A#include "base/inifile.hh"
352SN/A#include "base/loader/symtab.hh"
362SN/A#include "base/misc.hh"
372SN/A#include "base/pollevent.hh"
382SN/A#include "base/range.hh"
392SN/A#include "base/stats/events.hh"
402SN/A#include "base/trace.hh"
412665Ssaidi@eecs.umich.edu#include "cpu/base.hh"
422665Ssaidi@eecs.umich.edu#include "cpu/exetrace.hh"
432SN/A#include "cpu/profile.hh"
442SN/A#include "cpu/simple/base.hh"
451798SN/A#include "cpu/simple_thread.hh"
461798SN/A#include "cpu/smt.hh"
472SN/A#include "cpu/static_inst.hh"
489983Sstever@gmail.com#include "cpu/thread_context.hh"
499952Sdam.sunwoo@arm.com#include "mem/packet.hh"
502SN/A#include "sim/byteswap.hh"
512SN/A#include "sim/debug.hh"
522SN/A#include "sim/host.hh"
532SN/A#include "sim/sim_events.hh"
549983Sstever@gmail.com#include "sim/sim_object.hh"
552SN/A#include "sim/stats.hh"
565606Snate@binkert.org#include "sim/system.hh"
572SN/A
582SN/A#if FULL_SYSTEM
592SN/A#include "arch/kernel_stats.hh"
603144Shsul@eecs.umich.edu#include "arch/stacktrace.hh"
612SN/A#include "arch/tlb.hh"
622SN/A#include "arch/vtophys.hh"
639952Sdam.sunwoo@arm.com#include "base/remote_gdb.hh"
649983Sstever@gmail.com#else // !FULL_SYSTEM
659983Sstever@gmail.com#include "mem/mem_object.hh"
6611070Sandreas.sandberg@arm.com#endif // FULL_SYSTEM
672SN/A
689983Sstever@gmail.comusing namespace std;
699983Sstever@gmail.comusing namespace TheISA;
709983Sstever@gmail.com
719983Sstever@gmail.comBaseSimpleCPU::BaseSimpleCPU(Params *p)
729983Sstever@gmail.com    : BaseCPU(p), traceData(NULL), thread(NULL), predecoder(NULL)
739983Sstever@gmail.com{
749983Sstever@gmail.com#if FULL_SYSTEM
759983Sstever@gmail.com    thread = new SimpleThread(this, 0, p->system, p->itb, p->dtb);
769983Sstever@gmail.com#else
779983Sstever@gmail.com    thread = new SimpleThread(this, /* thread_num */ 0, p->process,
789983Sstever@gmail.com            p->itb, p->dtb, /* asid */ 0);
799983Sstever@gmail.com#endif // !FULL_SYSTEM
809983Sstever@gmail.com
819983Sstever@gmail.com    thread->setStatus(ThreadContext::Unallocated);
829983Sstever@gmail.com
839983Sstever@gmail.com    tc = thread->getTC();
849983Sstever@gmail.com
859983Sstever@gmail.com    numInst = 0;
8611070Sandreas.sandberg@arm.com    startNumInst = 0;
879983Sstever@gmail.com    numLoad = 0;
889983Sstever@gmail.com    startNumLoad = 0;
899983Sstever@gmail.com    lastIcacheStall = 0;
902SN/A    lastDcacheStall = 0;
915543Ssaidi@eecs.umich.edu
922SN/A    threadContexts.push_back(tc);
935336Shines@cs.fsu.edu
949952Sdam.sunwoo@arm.com
9510905Sandreas.sandberg@arm.com    fetchOffset = 0;
9610905Sandreas.sandberg@arm.com    stayAtPC = false;
9710905Sandreas.sandberg@arm.com}
989952Sdam.sunwoo@arm.com
992SN/ABaseSimpleCPU::~BaseSimpleCPU()
1002SN/A{
1017821Ssteve.reinhardt@amd.com}
1022797Sktlim@umich.edu
1032797Sktlim@umich.eduvoid
1042839Sktlim@umich.eduBaseSimpleCPU::deallocateContext(int thread_num)
1052797Sktlim@umich.edu{
1065606Snate@binkert.org    // for now, these are equivalent
1072797Sktlim@umich.edu    suspendContext(thread_num);
1085606Snate@binkert.org}
1095606Snate@binkert.org
1102797Sktlim@umich.edu
1112797Sktlim@umich.eduvoid
1122797Sktlim@umich.eduBaseSimpleCPU::haltContext(int thread_num)
1132797Sktlim@umich.edu{
1149983Sstever@gmail.com    // for now, these are equivalent
1152797Sktlim@umich.edu    suspendContext(thread_num);
1162797Sktlim@umich.edu}
1172SN/A
1182SN/A
1192SN/Avoid
1202SN/ABaseSimpleCPU::regStats()
1212SN/A{
1222SN/A    using namespace Stats;
1232SN/A
1242SN/A    BaseCPU::regStats();
1255543Ssaidi@eecs.umich.edu
1265543Ssaidi@eecs.umich.edu    numInsts
1272SN/A        .name(name() + ".num_insts")
1282SN/A        .desc("Number of instructions executed")
1295606Snate@binkert.org        ;
1302SN/A
1315543Ssaidi@eecs.umich.edu    numMemRefs
1322SN/A        .name(name() + ".num_refs")
1335336Shines@cs.fsu.edu        .desc("Number of memory references")
1342SN/A        ;
1352SN/A
1362SN/A    notIdleFraction
1371798SN/A        .name(name() + ".not_idle_fraction")
138        .desc("Percentage of non-idle cycles")
139        ;
140
141    idleFraction
142        .name(name() + ".idle_fraction")
143        .desc("Percentage of idle cycles")
144        ;
145
146    icacheStallCycles
147        .name(name() + ".icache_stall_cycles")
148        .desc("ICache total stall cycles")
149        .prereq(icacheStallCycles)
150        ;
151
152    dcacheStallCycles
153        .name(name() + ".dcache_stall_cycles")
154        .desc("DCache total stall cycles")
155        .prereq(dcacheStallCycles)
156        ;
157
158    icacheRetryCycles
159        .name(name() + ".icache_retry_cycles")
160        .desc("ICache total retry cycles")
161        .prereq(icacheRetryCycles)
162        ;
163
164    dcacheRetryCycles
165        .name(name() + ".dcache_retry_cycles")
166        .desc("DCache total retry cycles")
167        .prereq(dcacheRetryCycles)
168        ;
169
170    idleFraction = constant(1.0) - notIdleFraction;
171}
172
173void
174BaseSimpleCPU::resetStats()
175{
176//    startNumInst = numInst;
177    // notIdleFraction = (_status != Idle);
178}
179
180void
181BaseSimpleCPU::serialize(ostream &os)
182{
183    BaseCPU::serialize(os);
184//    SERIALIZE_SCALAR(inst);
185    nameOut(os, csprintf("%s.xc.0", name()));
186    thread->serialize(os);
187}
188
189void
190BaseSimpleCPU::unserialize(Checkpoint *cp, const string &section)
191{
192    BaseCPU::unserialize(cp, section);
193//    UNSERIALIZE_SCALAR(inst);
194    thread->unserialize(cp, csprintf("%s.xc.0", section));
195}
196
197void
198change_thread_state(int thread_number, int activate, int priority)
199{
200}
201
202Fault
203BaseSimpleCPU::copySrcTranslate(Addr src)
204{
205#if 0
206    static bool no_warn = true;
207    int blk_size = (dcacheInterface) ? dcacheInterface->getBlockSize() : 64;
208    // Only support block sizes of 64 atm.
209    assert(blk_size == 64);
210    int offset = src & (blk_size - 1);
211
212    // Make sure block doesn't span page
213    if (no_warn &&
214        (src & PageMask) != ((src + blk_size) & PageMask) &&
215        (src >> 40) != 0xfffffc) {
216        warn("Copied block source spans pages %x.", src);
217        no_warn = false;
218    }
219
220    memReq->reset(src & ~(blk_size - 1), blk_size);
221
222    // translate to physical address
223    Fault fault = thread->translateDataReadReq(req);
224
225    if (fault == NoFault) {
226        thread->copySrcAddr = src;
227        thread->copySrcPhysAddr = memReq->paddr + offset;
228    } else {
229        assert(!fault->isAlignmentFault());
230
231        thread->copySrcAddr = 0;
232        thread->copySrcPhysAddr = 0;
233    }
234    return fault;
235#else
236    return NoFault;
237#endif
238}
239
240Fault
241BaseSimpleCPU::copy(Addr dest)
242{
243#if 0
244    static bool no_warn = true;
245    int blk_size = (dcacheInterface) ? dcacheInterface->getBlockSize() : 64;
246    // Only support block sizes of 64 atm.
247    assert(blk_size == 64);
248    uint8_t data[blk_size];
249    //assert(thread->copySrcAddr);
250    int offset = dest & (blk_size - 1);
251
252    // Make sure block doesn't span page
253    if (no_warn &&
254        (dest & PageMask) != ((dest + blk_size) & PageMask) &&
255        (dest >> 40) != 0xfffffc) {
256        no_warn = false;
257        warn("Copied block destination spans pages %x. ", dest);
258    }
259
260    memReq->reset(dest & ~(blk_size -1), blk_size);
261    // translate to physical address
262    Fault fault = thread->translateDataWriteReq(req);
263
264    if (fault == NoFault) {
265        Addr dest_addr = memReq->paddr + offset;
266        // Need to read straight from memory since we have more than 8 bytes.
267        memReq->paddr = thread->copySrcPhysAddr;
268        thread->mem->read(memReq, data);
269        memReq->paddr = dest_addr;
270        thread->mem->write(memReq, data);
271        if (dcacheInterface) {
272            memReq->cmd = Copy;
273            memReq->completionEvent = NULL;
274            memReq->paddr = thread->copySrcPhysAddr;
275            memReq->dest = dest_addr;
276            memReq->size = 64;
277            memReq->time = curTick;
278            memReq->flags &= ~INST_READ;
279            dcacheInterface->access(memReq);
280        }
281    }
282    else
283        assert(!fault->isAlignmentFault());
284
285    return fault;
286#else
287    panic("copy not implemented");
288    return NoFault;
289#endif
290}
291
292#if FULL_SYSTEM
293Addr
294BaseSimpleCPU::dbg_vtophys(Addr addr)
295{
296    return vtophys(tc, addr);
297}
298#endif // FULL_SYSTEM
299
300#if FULL_SYSTEM
301void
302BaseSimpleCPU::post_interrupt(int int_num, int index)
303{
304    BaseCPU::post_interrupt(int_num, index);
305
306    if (thread->status() == ThreadContext::Suspended) {
307                DPRINTF(Quiesce,"Suspended Processor awoke\n");
308        thread->activate();
309    }
310}
311#endif // FULL_SYSTEM
312
313void
314BaseSimpleCPU::checkForInterrupts()
315{
316#if FULL_SYSTEM
317    if (check_interrupts(tc)) {
318        Fault interrupt = interrupts.getInterrupt(tc);
319
320        if (interrupt != NoFault) {
321            interrupts.updateIntrInfo(tc);
322            interrupt->invoke(tc);
323        }
324    }
325#endif
326}
327
328
329Fault
330BaseSimpleCPU::setupFetchRequest(Request *req)
331{
332    Addr threadPC = thread->readPC();
333
334    // set up memory request for instruction fetch
335#if ISA_HAS_DELAY_SLOT
336    DPRINTF(Fetch,"Fetch: PC:%08p NPC:%08p NNPC:%08p\n",threadPC,
337            thread->readNextPC(),thread->readNextNPC());
338#else
339    DPRINTF(Fetch,"Fetch: PC:%08p NPC:%08p\n",threadPC,
340            thread->readNextPC());
341#endif
342
343    Addr fetchPC = (threadPC & PCMask) + fetchOffset;
344    req->setVirt(0, fetchPC, sizeof(MachInst), 0, threadPC);
345
346    Fault fault = thread->translateInstReq(req);
347
348    return fault;
349}
350
351
352void
353BaseSimpleCPU::preExecute()
354{
355    // maintain $r0 semantics
356    thread->setIntReg(ZeroReg, 0);
357#if THE_ISA == ALPHA_ISA
358    thread->setFloatReg(ZeroReg, 0.0);
359#endif // ALPHA_ISA
360
361    // check for instruction-count-based events
362    comInstEventQueue[0]->serviceEvents(numInst);
363
364    // decode the instruction
365    inst = gtoh(inst);
366
367    //If we're not in the middle of a macro instruction
368    if (!curMacroStaticInst) {
369
370        StaticInstPtr instPtr = NULL;
371
372        //Predecode, ie bundle up an ExtMachInst
373        //This should go away once the constructor can be set up properly
374        predecoder.setTC(thread->getTC());
375        //If more fetch data is needed, pass it in.
376        Addr fetchPC = (thread->readPC() & PCMask) + fetchOffset;
377        //if(predecoder.needMoreBytes())
378            predecoder.moreBytes(thread->readPC(), fetchPC, inst);
379        //else
380        //    predecoder.process();
381
382        //If an instruction is ready, decode it. Otherwise, we'll have to
383        //fetch beyond the MachInst at the current pc.
384        if (predecoder.extMachInstReady()) {
385#if THE_ISA == X86_ISA
386            thread->setNextPC(thread->readPC() + predecoder.getInstSize());
387#endif // X86_ISA
388            stayAtPC = false;
389            instPtr = StaticInst::decode(predecoder.getExtMachInst(),
390                                         thread->readPC());
391        } else {
392            stayAtPC = true;
393            fetchOffset += sizeof(MachInst);
394        }
395
396        //If we decoded an instruction and it's microcoded, start pulling
397        //out micro ops
398        if (instPtr && instPtr->isMacroop()) {
399            curMacroStaticInst = instPtr;
400            curStaticInst = curMacroStaticInst->
401                fetchMicroop(thread->readMicroPC());
402        } else {
403            curStaticInst = instPtr;
404        }
405    } else {
406        //Read the next micro op from the macro op
407        curStaticInst = curMacroStaticInst->
408            fetchMicroop(thread->readMicroPC());
409    }
410
411    //If we decoded an instruction this "tick", record information about it.
412    if(curStaticInst)
413    {
414#if TRACING_ON
415        traceData = tracer->getInstRecord(curTick, tc, curStaticInst,
416                                         thread->readPC());
417
418        DPRINTF(Decode,"Decode: Decoded %s instruction: 0x%x\n",
419                curStaticInst->getName(), curStaticInst->machInst);
420#endif // TRACING_ON
421
422#if FULL_SYSTEM
423        thread->setInst(inst);
424#endif // FULL_SYSTEM
425    }
426}
427
428void
429BaseSimpleCPU::postExecute()
430{
431#if FULL_SYSTEM
432    if (thread->profile && curStaticInst) {
433        bool usermode = TheISA::inUserMode(tc);
434        thread->profilePC = usermode ? 1 : thread->readPC();
435        ProfileNode *node = thread->profile->consume(tc, curStaticInst);
436        if (node)
437            thread->profileNode = node;
438    }
439#endif
440
441    if (curStaticInst->isMemRef()) {
442        numMemRefs++;
443    }
444
445    if (curStaticInst->isLoad()) {
446        ++numLoad;
447        comLoadEventQueue[0]->serviceEvents(numLoad);
448    }
449
450    traceFunctions(thread->readPC());
451
452    if (traceData) {
453        traceData->dump();
454        delete traceData;
455        traceData = NULL;
456    }
457}
458
459
460void
461BaseSimpleCPU::advancePC(Fault fault)
462{
463    //Since we're moving to a new pc, zero out the offset
464    fetchOffset = 0;
465    if (fault != NoFault) {
466        curMacroStaticInst = StaticInst::nullStaticInstPtr;
467        predecoder.reset();
468        thread->setMicroPC(0);
469        thread->setNextMicroPC(1);
470        fault->invoke(tc);
471    } else {
472        //If we're at the last micro op for this instruction
473        if (curStaticInst && curStaticInst->isLastMicroop()) {
474            //We should be working with a macro op
475            assert(curMacroStaticInst);
476            //Close out this macro op, and clean up the
477            //microcode state
478            curMacroStaticInst = StaticInst::nullStaticInstPtr;
479            thread->setMicroPC(0);
480            thread->setNextMicroPC(1);
481        }
482        //If we're still in a macro op
483        if (curMacroStaticInst) {
484            //Advance the micro pc
485            thread->setMicroPC(thread->readNextMicroPC());
486            //Advance the "next" micro pc. Note that there are no delay
487            //slots, and micro ops are "word" addressed.
488            thread->setNextMicroPC(thread->readNextMicroPC() + 1);
489        } else {
490            // go to the next instruction
491            thread->setPC(thread->readNextPC());
492            thread->setNextPC(thread->readNextNPC());
493            thread->setNextNPC(thread->readNextNPC() + sizeof(MachInst));
494            assert(thread->readNextPC() != thread->readNextNPC());
495        }
496    }
497
498    Addr oldpc;
499    do {
500        oldpc = thread->readPC();
501        system->pcEventQueue.service(tc);
502    } while (oldpc != thread->readPC());
503}
504
505/*Fault
506BaseSimpleCPU::CacheOp(uint8_t Op, Addr EffAddr)
507{
508    // translate to physical address
509    Fault fault = NoFault;
510    int CacheID = Op & 0x3; // Lower 3 bits identify Cache
511    int CacheOP = Op >> 2; // Upper 3 bits identify Cache Operation
512    if(CacheID > 1)
513      {
514        warn("CacheOps not implemented for secondary/tertiary caches\n");
515      }
516    else
517      {
518        switch(CacheOP)
519          { // Fill Packet Type
520          case 0: warn("Invalidate Cache Op\n");
521            break;
522          case 1: warn("Index Load Tag Cache Op\n");
523            break;
524          case 2: warn("Index Store Tag Cache Op\n");
525            break;
526          case 4: warn("Hit Invalidate Cache Op\n");
527            break;
528          case 5: warn("Fill/Hit Writeback Invalidate Cache Op\n");
529            break;
530          case 6: warn("Hit Writeback\n");
531            break;
532          case 7: warn("Fetch & Lock Cache Op\n");
533            break;
534          default: warn("Unimplemented Cache Op\n");
535          }
536      }
537    return fault;
538}*/
539