diff options
Diffstat (limited to 'src/cpu')
-rw-r--r-- | src/cpu/base.cc | 2 | ||||
-rw-r--r-- | src/cpu/base.hh | 4 | ||||
-rw-r--r-- | src/cpu/exetrace.cc | 307 | ||||
-rw-r--r-- | src/cpu/m5legion_interface.h | 4 | ||||
-rw-r--r-- | src/cpu/memtest/memtest.hh | 2 | ||||
-rw-r--r-- | src/cpu/o3/fetch.hh | 2 | ||||
-rwxr-xr-x | src/cpu/o3/isa_specific.hh | 5 | ||||
-rw-r--r-- | src/cpu/o3/lsq.hh | 2 | ||||
-rw-r--r-- | src/cpu/o3/sparc/cpu.cc | 38 | ||||
-rw-r--r-- | src/cpu/o3/sparc/cpu.hh | 207 | ||||
-rw-r--r-- | src/cpu/o3/sparc/cpu_builder.cc | 433 | ||||
-rw-r--r-- | src/cpu/o3/sparc/cpu_impl.hh | 319 | ||||
-rw-r--r-- | src/cpu/o3/sparc/dyn_inst.cc | 36 | ||||
-rw-r--r-- | src/cpu/o3/sparc/dyn_inst.hh | 273 | ||||
-rw-r--r-- | src/cpu/o3/sparc/dyn_inst_impl.hh | 139 | ||||
-rw-r--r-- | src/cpu/o3/sparc/impl.hh | 92 | ||||
-rw-r--r-- | src/cpu/o3/sparc/params.hh | 63 | ||||
-rwxr-xr-x | src/cpu/o3/sparc/thread_context.cc | 35 | ||||
-rw-r--r-- | src/cpu/o3/sparc/thread_context.hh | 84 | ||||
-rw-r--r-- | src/cpu/ozone/front_end.hh | 2 | ||||
-rw-r--r-- | src/cpu/ozone/lw_lsq.hh | 2 | ||||
-rw-r--r-- | src/cpu/simple/atomic.cc | 33 | ||||
-rw-r--r-- | src/cpu/simple/atomic.hh | 2 | ||||
-rw-r--r-- | src/cpu/simple/timing.hh | 2 |
24 files changed, 2057 insertions, 31 deletions
diff --git a/src/cpu/base.cc b/src/cpu/base.cc index 7cbbb0b96..31604ad58 100644 --- a/src/cpu/base.cc +++ b/src/cpu/base.cc @@ -96,7 +96,7 @@ CPUProgressEvent::description() #if FULL_SYSTEM BaseCPU::BaseCPU(Params *p) - : MemObject(p->name), clock(p->clock), checkInterrupts(true), + : MemObject(p->name), clock(p->clock), instCnt(0), checkInterrupts(true), params(p), number_of_threads(p->numberOfThreads), system(p->system), phase(p->phase) #else diff --git a/src/cpu/base.hh b/src/cpu/base.hh index 1d9b6a93b..8c6b079da 100644 --- a/src/cpu/base.hh +++ b/src/cpu/base.hh @@ -70,12 +70,16 @@ class BaseCPU : public MemObject protected: // CPU's clock period in terms of the number of ticks of curTime. Tick clock; + // @todo remove me after debugging with legion done + Tick instCnt; public: // Tick currentTick; inline Tick frequency() const { return Clock::Frequency / clock; } inline Tick cycles(int numCycles) const { return clock * numCycles; } inline Tick curCycle() const { return curTick / clock; } + // @todo remove me after debugging with legion done + Tick instCount() { return instCnt; } /** The next cycle the CPU should be scheduled, given a cache * access or quiesce event returning on this cycle. This function diff --git a/src/cpu/exetrace.cc b/src/cpu/exetrace.cc index 113f0fe74..3fe40b4c1 100644 --- a/src/cpu/exetrace.cc +++ b/src/cpu/exetrace.cc @@ -57,6 +57,10 @@ using namespace std; using namespace TheISA; +#if THE_ISA == SPARC_ISA && FULL_SYSTEM +static int diffcount = 0; +#endif + namespace Trace { SharedData *shared_data = NULL; } @@ -66,6 +70,56 @@ SharedData *shared_data = NULL; // Methods for the InstRecord object // +#if THE_ISA == SPARC_ISA + +inline char * genCenteredLabel(int length, char * buffer, char * label) +{ + int labelLength = strlen(label); + assert(labelLength <= length); + int leftPad = (length - labelLength) / 2; + int rightPad = length - leftPad - labelLength; + char format[64]; + sprintf(format, "%%%ds%%s%%%ds", leftPad, rightPad); + sprintf(buffer, format, "", label, ""); + return buffer; +} + +inline void printRegPair(ostream & os, char const * title, uint64_t a, uint64_t b) +{ + ccprintf(os, " %16s | %#018x %s %#-018x \n", + title, a, (a == b) ? "|" : "X", b); +} + +inline void printColumnLabels(ostream & os) +{ + static char * regLabel = genCenteredLabel(16, new char[17], "Register"); + static char * m5Label = genCenteredLabel(18, new char[18], "M5"); + static char * legionLabel = genCenteredLabel(18, new char[18], "Legion"); + ccprintf(os, " %s | %s | %s \n", regLabel, m5Label, legionLabel); + ccprintf(os, "--------------------+-----------------------+-----------------------\n"); +} + +inline void printSectionHeader(ostream & os, char * name) +{ + char sectionString[70]; + genCenteredLabel(69, sectionString, name); + ccprintf(os, "====================================================================\n"); + ccprintf(os, "%69s\n", sectionString); + ccprintf(os, "====================================================================\n"); +} + +inline void printLevelHeader(ostream & os, int level) +{ + char sectionString[70]; + char levelName[70]; + sprintf(levelName, "Trap stack level %d", level); + genCenteredLabel(69, sectionString, levelName); + ccprintf(os, "====================================================================\n"); + ccprintf(os, "%69s\n", sectionString); + ccprintf(os, "====================================================================\n"); +} + +#endif void Trace::InstRecord::dump(ostream &outs) @@ -229,40 +283,172 @@ Trace::InstRecord::dump(ostream &outs) // outs << endl; } -#if THE_ISA == SPARC_ISA +#if THE_ISA == SPARC_ISA && FULL_SYSTEM // Compare if (flags[LEGION_LOCKSTEP]) { bool compared = false; bool diffPC = false; + bool diffCC = false; bool diffInst = false; bool diffRegs = false; + bool diffTpc = false; + bool diffTnpc = false; + bool diffTstate = false; + bool diffTt = false; + bool diffTba = false; + bool diffHpstate = false; + bool diffHtstate = false; + bool diffHtba = false; + bool diffPstate = false; + bool diffY = false; + bool diffCcr = false; + bool diffTl = false; + bool diffGl = false; + bool diffAsi = false; + bool diffPil = false; + bool diffCwp = false; + bool diffCansave = false; + bool diffCanrestore = false; + bool diffOtherwin = false; + bool diffCleanwin = false; Addr m5Pc, lgnPc; if(!staticInst->isMicroOp() || staticInst->isLastMicroOp()) { while (!compared) { - m5Pc = PC & TheISA::PAddrImplMask; - lgnPc = shared_data->pc & TheISA::PAddrImplMask; if (shared_data->flags == OWN_M5) { + m5Pc = PC & TheISA::PAddrImplMask; + lgnPc = shared_data->pc & TheISA::PAddrImplMask; if (lgnPc != m5Pc) diffPC = true; - if (shared_data->instruction != staticInst->machInst) + + if (shared_data->cycle_count != + thread->getCpuPtr()->instCount()) + diffCC = true; + + if (shared_data->instruction != + (SparcISA::MachInst)staticInst->machInst) { diffInst = true; - for (int i = 0; i < TheISA::NumRegularIntRegs; i++) { + } + for (int i = 0; i < TheISA::NumIntArchRegs; i++) { if (thread->readIntReg(i) != shared_data->intregs[i]) { diffRegs = true; } } - - if (diffPC || diffInst || diffRegs ) { + uint64_t oldTl = thread->readMiscReg(MISCREG_TL); + if (oldTl != shared_data->tl) + diffTl = true; + for (int i = 1; i <= MaxTL; i++) { + thread->setMiscReg(MISCREG_TL, i); + if (thread->readMiscReg(MISCREG_TPC) != + shared_data->tpc[i-1]) + diffTpc = true; + if (thread->readMiscReg(MISCREG_TNPC) != + shared_data->tnpc[i-1]) + diffTnpc = true; + if (thread->readMiscReg(MISCREG_TSTATE) != + shared_data->tstate[i-1]) + diffTstate = true; + if (thread->readMiscReg(MISCREG_TT) != + shared_data->tt[i-1]) + diffTt = true; + if (thread->readMiscReg(MISCREG_HTSTATE) != + shared_data->htstate[i-1]) + diffHtstate = true; + } + thread->setMiscReg(MISCREG_TL, oldTl); + + if(shared_data->tba != thread->readMiscReg(MISCREG_TBA)) + diffTba = true; + //When the hpstate register is read by an instruction, + //legion has bit 11 set. When it's in storage, it doesn't. + //Since we don't directly support seperate interpretations + //of the registers like that, the bit is always set to 1 and + //we just don't compare it. It's not supposed to matter + //anyway. + if((shared_data->hpstate | (1 << 11)) != thread->readMiscReg(MISCREG_HPSTATE)) + diffHpstate = true; + if(shared_data->htba != thread->readMiscReg(MISCREG_HTBA)) + diffHtba = true; + if(shared_data->pstate != thread->readMiscReg(MISCREG_PSTATE)) + diffPstate = true; + if(shared_data->y != thread->readMiscReg(MISCREG_Y)) + diffY = true; + if(shared_data->ccr != thread->readMiscReg(MISCREG_CCR)) + diffCcr = true; + if(shared_data->gl != thread->readMiscReg(MISCREG_GL)) + diffGl = true; + if(shared_data->asi != thread->readMiscReg(MISCREG_ASI)) + diffAsi = true; + if(shared_data->pil != thread->readMiscReg(MISCREG_PIL)) + diffPil = true; + if(shared_data->cwp != thread->readMiscReg(MISCREG_CWP)) + diffCwp = true; + if(shared_data->cansave != thread->readMiscReg(MISCREG_CANSAVE)) + diffCansave = true; + if(shared_data->canrestore != + thread->readMiscReg(MISCREG_CANRESTORE)) + diffCanrestore = true; + if(shared_data->otherwin != thread->readMiscReg(MISCREG_OTHERWIN)) + diffOtherwin = true; + if(shared_data->cleanwin != thread->readMiscReg(MISCREG_CLEANWIN)) + diffCleanwin = true; + + if ((diffPC || diffCC || diffInst || diffRegs || diffTpc || + diffTnpc || diffTstate || diffTt || diffHpstate || + diffHtstate || diffHtba || diffPstate || diffY || + diffCcr || diffTl || diffGl || diffAsi || diffPil || + diffCwp || diffCansave || diffCanrestore || + diffOtherwin || diffCleanwin) + && !((staticInst->machInst & 0xC1F80000) == 0x81D00000)) { outs << "Differences found between M5 and Legion:"; if (diffPC) outs << " [PC]"; + if (diffCC) + outs << " [CC]"; if (diffInst) outs << " [Instruction]"; if (diffRegs) outs << " [IntRegs]"; + if (diffTpc) + outs << " [Tpc]"; + if (diffTnpc) + outs << " [Tnpc]"; + if (diffTstate) + outs << " [Tstate]"; + if (diffTt) + outs << " [Tt]"; + if (diffHpstate) + outs << " [Hpstate]"; + if (diffHtstate) + outs << " [Htstate]"; + if (diffHtba) + outs << " [Htba]"; + if (diffPstate) + outs << " [Pstate]"; + if (diffY) + outs << " [Y]"; + if (diffCcr) + outs << " [Ccr]"; + if (diffTl) + outs << " [Tl]"; + if (diffGl) + outs << " [Gl]"; + if (diffAsi) + outs << " [Asi]"; + if (diffPil) + outs << " [Pil]"; + if (diffCwp) + outs << " [Cwp]"; + if (diffCansave) + outs << " [Cansave]"; + if (diffCanrestore) + outs << " [Canrestore]"; + if (diffOtherwin) + outs << " [Otherwin]"; + if (diffCleanwin) + outs << " [Cleanwin]"; outs << endl << endl; outs << right << setfill(' ') << setw(15) @@ -272,38 +458,127 @@ Trace::InstRecord::dump(ostream &outs) << "Legion PC: " << "0x"<< setw(16) << setfill('0') << hex << lgnPc << endl << endl; + outs << right << setfill(' ') << setw(15) + << "M5 CC: " << "0x"<< setw(16) << setfill('0') + << hex << thread->getCpuPtr()->instCount() << endl; + outs << setfill(' ') << setw(15) + << "Legion CC: " << "0x"<< setw(16) << setfill('0') << hex + << shared_data->cycle_count << endl << endl; + outs << setfill(' ') << setw(15) << "M5 Inst: " << "0x"<< setw(8) << setfill('0') << hex << staticInst->machInst << staticInst->disassemble(m5Pc, debugSymbolTable) << endl; - StaticInstPtr legionInst = StaticInst::decode(makeExtMI(shared_data->instruction, thread)); + StaticInstPtr legionInst = + StaticInst::decode(makeExtMI(shared_data->instruction, + thread)); outs << setfill(' ') << setw(15) << " Legion Inst: " << "0x" << setw(8) << setfill('0') << hex << shared_data->instruction << legionInst->disassemble(lgnPc, debugSymbolTable) - << endl; - + << endl << endl; + + printSectionHeader(outs, "General State"); + printColumnLabels(outs); + printRegPair(outs, "HPstate", + thread->readMiscReg(MISCREG_HPSTATE), + shared_data->hpstate | (1 << 11)); + printRegPair(outs, "Htba", + thread->readMiscReg(MISCREG_HTBA), + shared_data->htba); + printRegPair(outs, "Pstate", + thread->readMiscReg(MISCREG_PSTATE), + shared_data->pstate); + printRegPair(outs, "Y", + thread->readMiscReg(MISCREG_Y), + shared_data->y); + printRegPair(outs, "Ccr", + thread->readMiscReg(MISCREG_CCR), + shared_data->ccr); + printRegPair(outs, "Tl", + thread->readMiscReg(MISCREG_TL), + shared_data->tl); + printRegPair(outs, "Gl", + thread->readMiscReg(MISCREG_GL), + shared_data->gl); + printRegPair(outs, "Asi", + thread->readMiscReg(MISCREG_ASI), + shared_data->asi); + printRegPair(outs, "Pil", + thread->readMiscReg(MISCREG_PIL), + shared_data->pil); + printRegPair(outs, "Cwp", + thread->readMiscReg(MISCREG_CWP), + shared_data->cwp); + printRegPair(outs, "Cansave", + thread->readMiscReg(MISCREG_CANSAVE), + shared_data->cansave); + printRegPair(outs, "Canrestore", + thread->readMiscReg(MISCREG_CANRESTORE), + shared_data->canrestore); + printRegPair(outs, "Otherwin", + thread->readMiscReg(MISCREG_OTHERWIN), + shared_data->otherwin); + printRegPair(outs, "Cleanwin", + thread->readMiscReg(MISCREG_CLEANWIN), + shared_data->cleanwin); + outs << endl; + for (int i = 1; i <= MaxTL; i++) { + printLevelHeader(outs, i); + printColumnLabels(outs); + thread->setMiscReg(MISCREG_TL, i); + printRegPair(outs, "Tpc", + thread->readMiscReg(MISCREG_TPC), + shared_data->tpc[i-1]); + printRegPair(outs, "Tnpc", + thread->readMiscReg(MISCREG_TNPC), + shared_data->tnpc[i-1]); + printRegPair(outs, "Tstate", + thread->readMiscReg(MISCREG_TSTATE), + shared_data->tstate[i-1]); + printRegPair(outs, "Tt", + thread->readMiscReg(MISCREG_TT), + shared_data->tt[i-1]); + printRegPair(outs, "Htstate", + thread->readMiscReg(MISCREG_HTSTATE), + shared_data->htstate[i-1]); + } + thread->setMiscReg(MISCREG_TL, oldTl); outs << endl; + printSectionHeader(outs, "General Purpose Registers"); static const char * regtypes[4] = {"%g", "%o", "%l", "%i"}; for(int y = 0; y < 4; y++) { for(int x = 0; x < 8; x++) { - outs << regtypes[y] << x << " " ; - outs << "0x" << hex << setw(16) << thread->readIntReg(y*8+x); - if (thread->readIntReg(y*8 + x) != shared_data->intregs[y*8+x]) + char label[8]; + sprintf(label, "%s%d", regtypes[y], x); + printRegPair(outs, label, + thread->readIntReg(y*8+x), + shared_data->intregs[y*8+x]); + /*outs << regtypes[y] << x << " " ; + outs << "0x" << hex << setw(16) + << thread->readIntReg(y*8+x); + if (thread->readIntReg(y*8 + x) + != shared_data->intregs[y*8+x]) outs << " X "; else outs << " | "; - outs << "0x" << setw(16) << hex << shared_data->intregs[y*8+x] - << endl; + outs << "0x" << setw(16) << hex + << shared_data->intregs[y*8+x] + << endl;*/ } } - fatal("Differences found between Legion and M5\n"); + thread->getITBPtr()->dumpAll(); + thread->getDTBPtr()->dumpAll(); + + diffcount++; + if (diffcount > 2) + fatal("Differences found between Legion and M5\n"); } compared = true; diff --git a/src/cpu/m5legion_interface.h b/src/cpu/m5legion_interface.h index 373fbeb11..bfb88485a 100644 --- a/src/cpu/m5legion_interface.h +++ b/src/cpu/m5legion_interface.h @@ -30,7 +30,7 @@ #include <unistd.h> -#define VERSION 0xA1000005 +#define VERSION 0xA1000006 #define OWN_M5 0x000000AA #define OWN_LEGION 0x00000055 @@ -42,6 +42,8 @@ typedef struct { uint64_t pc; uint64_t new_pc; + uint64_t cycle_count; + uint64_t new_cycle_count; uint32_t instruction; uint32_t new_instruction; uint64_t intregs[32]; diff --git a/src/cpu/memtest/memtest.hh b/src/cpu/memtest/memtest.hh index 7bf34d827..264309fd7 100644 --- a/src/cpu/memtest/memtest.hh +++ b/src/cpu/memtest/memtest.hh @@ -116,7 +116,7 @@ class MemTest : public MemObject virtual void getDeviceAddressRanges(AddrRangeList &resp, AddrRangeList &snoop) - { resp.clear(); snoop.clear(); snoop.push_back(RangeSize(0,-1)); } + { resp.clear(); snoop.clear(); snoop.push_back(RangeSize(0,0)); } }; CpuPort cachePort; diff --git a/src/cpu/o3/fetch.hh b/src/cpu/o3/fetch.hh index 04016347a..e880e14e4 100644 --- a/src/cpu/o3/fetch.hh +++ b/src/cpu/o3/fetch.hh @@ -98,7 +98,7 @@ class DefaultFetch /** Returns the address ranges of this device. */ virtual void getDeviceAddressRanges(AddrRangeList &resp, AddrRangeList &snoop) - { resp.clear(); snoop.clear(); snoop.push_back(RangeSize(0,-1)); } + { resp.clear(); snoop.clear(); snoop.push_back(RangeSize(0,0)); } /** Timing version of receive. Handles setting fetch to the * proper status to start fetching. */ diff --git a/src/cpu/o3/isa_specific.hh b/src/cpu/o3/isa_specific.hh index 4937589e3..72a8d4021 100755 --- a/src/cpu/o3/isa_specific.hh +++ b/src/cpu/o3/isa_specific.hh @@ -40,6 +40,11 @@ #include "cpu/o3/mips/impl.hh" #include "cpu/o3/mips/params.hh" #include "cpu/o3/mips/dyn_inst.hh" +#elif THE_ISA == SPARC_ISA + #include "cpu/o3/sparc/cpu.hh" + #include "cpu/o3/sparc/impl.hh" + #include "cpu/o3/sparc/params.hh" + #include "cpu/o3/sparc/dyn_inst.hh" #else #error "ISA-specific header files O3CPU not defined ISA" #endif diff --git a/src/cpu/o3/lsq.hh b/src/cpu/o3/lsq.hh index 7559a36d5..e68085cfd 100644 --- a/src/cpu/o3/lsq.hh +++ b/src/cpu/o3/lsq.hh @@ -313,7 +313,7 @@ class LSQ { /** Returns the address ranges of this device. */ virtual void getDeviceAddressRanges(AddrRangeList &resp, AddrRangeList &snoop) - { resp.clear(); snoop.clear(); snoop.push_back(RangeSize(0,-1)); } + { resp.clear(); snoop.clear(); snoop.push_back(RangeSize(0,0)); } /** Timing version of receive. Handles writing back and * completing the load or store that has returned from diff --git a/src/cpu/o3/sparc/cpu.cc b/src/cpu/o3/sparc/cpu.cc new file mode 100644 index 000000000..1546a2b88 --- /dev/null +++ b/src/cpu/o3/sparc/cpu.cc @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2004-2005 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Gabe Black + */ + +#include "cpu/o3/sparc/impl.hh" +#include "cpu/o3/sparc/cpu_impl.hh" +#include "cpu/o3/sparc/dyn_inst.hh" + +// Force instantiation of SparcO3CPU for all the implementations that are +// needed. Consider merging this and sparc_dyn_inst.cc, and maybe all +// classes that depend on a certain impl, into one file (sparc_impl.cc?). +template class SparcO3CPU<SparcSimpleImpl>; diff --git a/src/cpu/o3/sparc/cpu.hh b/src/cpu/o3/sparc/cpu.hh new file mode 100644 index 000000000..c4df79832 --- /dev/null +++ b/src/cpu/o3/sparc/cpu.hh @@ -0,0 +1,207 @@ +/* + * Copyright (c) 2004-2006 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Kevin Lim + */ + +#ifndef __CPU_O3_SPARC_CPU_HH__ +#define __CPU_O3_SPARC_CPU_HH__ + +#include "arch/sparc/regfile.hh" +#include "arch/sparc/types.hh" +#include "cpu/thread_context.hh" +#include "cpu/o3/cpu.hh" +#include "sim/byteswap.hh" + +namespace TheISA +{ + class ITB; + class DTB; +} + +class EndQuiesceEvent; +namespace Kernel { + class Statistics; +}; + +class TranslatingPort; + +/** + * SparcO3CPU class. Derives from the FullO3CPU class, and + * implements all ISA and implementation specific functions of the + * CPU. This is the CPU class that is used for the SimObjects, and is + * what is given to the DynInsts. Most of its state exists in the + * FullO3CPU; the state is has is mainly for ISA specific + * functionality. + */ +template <class Impl> +class SparcO3CPU : public FullO3CPU<Impl> +{ + protected: + typedef TheISA::IntReg IntReg; + typedef TheISA::FloatReg FloatReg; + typedef TheISA::FloatRegBits FloatRegBits; + typedef TheISA::MiscReg MiscReg; + typedef TheISA::RegFile RegFile; + typedef TheISA::MiscRegFile MiscRegFile; + + public: + typedef O3ThreadState<Impl> ImplState; + typedef O3ThreadState<Impl> Thread; + typedef typename Impl::Params Params; + + /** Constructs an AlphaO3CPU with the given parameters. */ + SparcO3CPU(Params *params); + +#if FULL_SYSTEM + /** ITB pointer. */ + SparcISA::ITB *itb; + /** DTB pointer. */ + SparcISA::DTB *dtb; +#endif + + /** Registers statistics. */ + void regStats(); + +#if FULL_SYSTEM + /** Translates instruction requestion. */ + Fault translateInstReq(RequestPtr &req, Thread *thread) + { + return itb->translate(req, thread->getTC()); + } + + /** Translates data read request. */ + Fault translateDataReadReq(RequestPtr &req, Thread *thread) + { + return dtb->translate(req, thread->getTC(), false); + } + + /** Translates data write request. */ + Fault translateDataWriteReq(RequestPtr &req, Thread *thread) + { + return dtb->translate(req, thread->getTC(), true); + } + +#else + /** Translates instruction requestion in syscall emulation mode. */ + Fault translateInstReq(RequestPtr &req, Thread *thread) + { + return thread->getProcessPtr()->pTable->translate(req); + } + + /** Translates data read request in syscall emulation mode. */ + Fault translateDataReadReq(RequestPtr &req, Thread *thread) + { + return thread->getProcessPtr()->pTable->translate(req); + } + + /** Translates data write request in syscall emulation mode. */ + Fault translateDataWriteReq(RequestPtr &req, Thread *thread) + { + return thread->getProcessPtr()->pTable->translate(req); + } + +#endif + /** Reads a miscellaneous register. */ + MiscReg readMiscReg(int misc_reg, unsigned tid); + + /** Reads a misc. register, including any side effects the read + * might have as defined by the architecture. + */ + MiscReg readMiscRegWithEffect(int misc_reg, unsigned tid); + + /** Sets a miscellaneous register. */ + void setMiscReg(int misc_reg, const MiscReg &val, unsigned tid); + + /** Sets a misc. register, including any side effects the write + * might have as defined by the architecture. + */ + void setMiscRegWithEffect(int misc_reg, const MiscReg &val, unsigned tid); + + /** Initiates a squash of all in-flight instructions for a given + * thread. The source of the squash is an external update of + * state through the TC. + */ + void squashFromTC(unsigned tid); + +#if FULL_SYSTEM + /** Posts an interrupt. */ + void post_interrupt(int int_num, int index); + /** HW return from error interrupt. */ + Fault hwrei(unsigned tid); + + bool simPalCheck(int palFunc, unsigned tid); + + /** Returns the Fault for any valid interrupt. */ + Fault getInterrupts(); + + /** Processes any an interrupt fault. */ + void processInterrupts(Fault interrupt); + + /** Halts the CPU. */ + void halt() { panic("Halt not implemented!\n"); } +#endif + + /** Traps to handle given fault. */ + void trap(Fault fault, unsigned tid); + +#if !FULL_SYSTEM + /** Executes a syscall. + * @todo: Determine if this needs to be virtual. + */ + void syscall(int64_t callnum, int tid); + /** Gets a syscall argument. */ + IntReg getSyscallArg(int i, int tid); + + /** Used to shift args for indirect syscall. */ + void setSyscallArg(int i, IntReg val, int tid); + + /** Sets the return value of a syscall. */ + void setSyscallReturn(SyscallReturn return_value, int tid); +#endif + + /** CPU read function, forwards read to LSQ. */ + template <class T> + Fault read(RequestPtr &req, T &data, int load_idx) + { + return this->iew.ldstQueue.read(req, data, load_idx); + } + + /** CPU write function, forwards write to LSQ. */ + template <class T> + Fault write(RequestPtr &req, T &data, int store_idx) + { + return this->iew.ldstQueue.write(req, data, store_idx); + } + + Addr lockAddr; + + /** Temporary fix for the lock flag, works in the UP case. */ + bool lockFlag; +}; + +#endif // __CPU_O3_ALPHA_CPU_HH__ diff --git a/src/cpu/o3/sparc/cpu_builder.cc b/src/cpu/o3/sparc/cpu_builder.cc new file mode 100644 index 000000000..81f419ee0 --- /dev/null +++ b/src/cpu/o3/sparc/cpu_builder.cc @@ -0,0 +1,433 @@ +/* + * Copyright (c) 2004-2006 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Gabe Black + */ + +#include <string> + +#include "cpu/base.hh" +#include "cpu/o3/sparc/cpu.hh" +#include "cpu/o3/sparc/impl.hh" +#include "cpu/o3/sparc/params.hh" +#include "cpu/o3/fu_pool.hh" +#include "sim/builder.hh" + +class DerivO3CPU : public SparcO3CPU<SparcSimpleImpl> +{ + public: + DerivO3CPU(SparcSimpleParams *p) + : SparcO3CPU<SparcSimpleImpl>(p) + { } +}; + +BEGIN_DECLARE_SIM_OBJECT_PARAMS(DerivO3CPU) + + Param<int> clock; + Param<int> phase; + Param<int> numThreads; + Param<int> activity; + +#if FULL_SYSTEM + SimObjectParam<System *> system; + Param<int> cpu_id; + SimObjectParam<AlphaISA::ITB *> itb; + SimObjectParam<AlphaISA::DTB *> dtb; + Param<Tick> profile; + + Param<bool> do_quiesce; + Param<bool> do_checkpoint_insts; + Param<bool> do_statistics_insts; +#else + SimObjectVectorParam<Process *> workload; +#endif // FULL_SYSTEM + + SimObjectParam<BaseCPU *> checker; + + Param<Counter> max_insts_any_thread; + Param<Counter> max_insts_all_threads; + Param<Counter> max_loads_any_thread; + Param<Counter> max_loads_all_threads; + Param<Tick> progress_interval; + + Param<unsigned> cachePorts; + + Param<unsigned> decodeToFetchDelay; + Param<unsigned> renameToFetchDelay; + Param<unsigned> iewToFetchDelay; + Param<unsigned> commitToFetchDelay; + Param<unsigned> fetchWidth; + + Param<unsigned> renameToDecodeDelay; + Param<unsigned> iewToDecodeDelay; + Param<unsigned> commitToDecodeDelay; + Param<unsigned> fetchToDecodeDelay; + Param<unsigned> decodeWidth; + + Param<unsigned> iewToRenameDelay; + Param<unsigned> commitToRenameDelay; + Param<unsigned> decodeToRenameDelay; + Param<unsigned> renameWidth; + + Param<unsigned> commitToIEWDelay; + Param<unsigned> renameToIEWDelay; + Param<unsigned> issueToExecuteDelay; + Param<unsigned> dispatchWidth; + Param<unsigned> issueWidth; + Param<unsigned> wbWidth; + Param<unsigned> wbDepth; + SimObjectParam<FUPool *> fuPool; + + Param<unsigned> iewToCommitDelay; + Param<unsigned> renameToROBDelay; + Param<unsigned> commitWidth; + Param<unsigned> squashWidth; + Param<Tick> trapLatency; + + Param<unsigned> backComSize; + Param<unsigned> forwardComSize; + + Param<std::string> predType; + Param<unsigned> localPredictorSize; + Param<unsigned> localCtrBits; + Param<unsigned> localHistoryTableSize; + Param<unsigned> localHistoryBits; + Param<unsigned> globalPredictorSize; + Param<unsigned> globalCtrBits; + Param<unsigned> globalHistoryBits; + Param<unsigned> choicePredictorSize; + Param<unsigned> choiceCtrBits; + + Param<unsigned> BTBEntries; + Param<unsigned> BTBTagSize; + + Param<unsigned> RASSize; + + Param<unsigned> LQEntries; + Param<unsigned> SQEntries; + Param<unsigned> LFSTSize; + Param<unsigned> SSITSize; + + Param<unsigned> numPhysIntRegs; + Param<unsigned> numPhysFloatRegs; + Param<unsigned> numIQEntries; + Param<unsigned> numROBEntries; + + Param<unsigned> smtNumFetchingThreads; + Param<std::string> smtFetchPolicy; + Param<std::string> smtLSQPolicy; + Param<unsigned> smtLSQThreshold; + Param<std::string> smtIQPolicy; + Param<unsigned> smtIQThreshold; + Param<std::string> smtROBPolicy; + Param<unsigned> smtROBThreshold; + Param<std::string> smtCommitPolicy; + + Param<unsigned> instShiftAmt; + + Param<bool> defer_registration; + + Param<bool> function_trace; + Param<Tick> function_trace_start; + +END_DECLARE_SIM_OBJECT_PARAMS(DerivO3CPU) + +BEGIN_INIT_SIM_OBJECT_PARAMS(DerivO3CPU) + + INIT_PARAM(clock, "clock speed"), + INIT_PARAM_DFLT(phase, "clock phase", 0), + INIT_PARAM(numThreads, "number of HW thread contexts"), + INIT_PARAM_DFLT(activity, "Initial activity count", 0), + +#if FULL_SYSTEM + INIT_PARAM(system, "System object"), + INIT_PARAM(cpu_id, "processor ID"), + INIT_PARAM(itb, "Instruction translation buffer"), + INIT_PARAM(dtb, "Data translation buffer"), + INIT_PARAM(profile, ""), + + INIT_PARAM(do_quiesce, ""), + INIT_PARAM(do_checkpoint_insts, ""), + INIT_PARAM(do_statistics_insts, ""), +#else + INIT_PARAM(workload, "Processes to run"), +#endif // FULL_SYSTEM + + INIT_PARAM_DFLT(checker, "Checker CPU", NULL), + + INIT_PARAM_DFLT(max_insts_any_thread, + "Terminate when any thread reaches this inst count", + 0), + INIT_PARAM_DFLT(max_insts_all_threads, + "Terminate when all threads have reached" + "this inst count", + 0), + INIT_PARAM_DFLT(max_loads_any_thread, + "Terminate when any thread reaches this load count", + 0), + INIT_PARAM_DFLT(max_loads_all_threads, + "Terminate when all threads have reached this load" + "count", + 0), + INIT_PARAM_DFLT(progress_interval, "Progress interval", 0), + + INIT_PARAM_DFLT(cachePorts, "Cache Ports", 200), + + INIT_PARAM(decodeToFetchDelay, "Decode to fetch delay"), + INIT_PARAM(renameToFetchDelay, "Rename to fetch delay"), + INIT_PARAM(iewToFetchDelay, "Issue/Execute/Writeback to fetch" + "delay"), + INIT_PARAM(commitToFetchDelay, "Commit to fetch delay"), + INIT_PARAM(fetchWidth, "Fetch width"), + INIT_PARAM(renameToDecodeDelay, "Rename to decode delay"), + INIT_PARAM(iewToDecodeDelay, "Issue/Execute/Writeback to decode" + "delay"), + INIT_PARAM(commitToDecodeDelay, "Commit to decode delay"), + INIT_PARAM(fetchToDecodeDelay, "Fetch to decode delay"), + INIT_PARAM(decodeWidth, "Decode width"), + + INIT_PARAM(iewToRenameDelay, "Issue/Execute/Writeback to rename" + "delay"), + INIT_PARAM(commitToRenameDelay, "Commit to rename delay"), + INIT_PARAM(decodeToRenameDelay, "Decode to rename delay"), + INIT_PARAM(renameWidth, "Rename width"), + + INIT_PARAM(commitToIEWDelay, "Commit to " + "Issue/Execute/Writeback delay"), + INIT_PARAM(renameToIEWDelay, "Rename to " + "Issue/Execute/Writeback delay"), + INIT_PARAM(issueToExecuteDelay, "Issue to execute delay (internal" + "to the IEW stage)"), + INIT_PARAM(dispatchWidth, "Dispatch width"), + INIT_PARAM(issueWidth, "Issue width"), + INIT_PARAM(wbWidth, "Writeback width"), + INIT_PARAM(wbDepth, "Writeback depth (number of cycles it can buffer)"), + INIT_PARAM_DFLT(fuPool, "Functional unit pool", NULL), + + INIT_PARAM(iewToCommitDelay, "Issue/Execute/Writeback to commit " + "delay"), + INIT_PARAM(renameToROBDelay, "Rename to reorder buffer delay"), + INIT_PARAM(commitWidth, "Commit width"), + INIT_PARAM(squashWidth, "Squash width"), + INIT_PARAM_DFLT(trapLatency, "Number of cycles before the trap is handled", 6), + + INIT_PARAM(backComSize, "Time buffer size for backwards communication"), + INIT_PARAM(forwardComSize, "Time buffer size for forward communication"), + + INIT_PARAM(predType, "Type of branch predictor ('local', 'tournament')"), + INIT_PARAM(localPredictorSize, "Size of local predictor"), + INIT_PARAM(localCtrBits, "Bits per counter"), + INIT_PARAM(localHistoryTableSize, "Size of local history table"), + INIT_PARAM(localHistoryBits, "Bits for the local history"), + INIT_PARAM(globalPredictorSize, "Size of global predictor"), + INIT_PARAM(globalCtrBits, "Bits per counter"), + INIT_PARAM(globalHistoryBits, "Bits of history"), + INIT_PARAM(choicePredictorSize, "Size of choice predictor"), + INIT_PARAM(choiceCtrBits, "Bits of choice counters"), + + INIT_PARAM(BTBEntries, "Number of BTB entries"), + INIT_PARAM(BTBTagSize, "Size of the BTB tags, in bits"), + + INIT_PARAM(RASSize, "RAS size"), + + INIT_PARAM(LQEntries, "Number of load queue entries"), + INIT_PARAM(SQEntries, "Number of store queue entries"), + INIT_PARAM(LFSTSize, "Last fetched store table size"), + INIT_PARAM(SSITSize, "Store set ID table size"), + + INIT_PARAM(numPhysIntRegs, "Number of physical integer registers"), + INIT_PARAM(numPhysFloatRegs, "Number of physical floating point " + "registers"), + INIT_PARAM(numIQEntries, "Number of instruction queue entries"), + INIT_PARAM(numROBEntries, "Number of reorder buffer entries"), + + INIT_PARAM_DFLT(smtNumFetchingThreads, "SMT Number of Fetching Threads", 1), + INIT_PARAM_DFLT(smtFetchPolicy, "SMT Fetch Policy", "SingleThread"), + INIT_PARAM_DFLT(smtLSQPolicy, "SMT LSQ Sharing Policy", "Partitioned"), + INIT_PARAM_DFLT(smtLSQThreshold,"SMT LSQ Threshold", 100), + INIT_PARAM_DFLT(smtIQPolicy, "SMT IQ Policy", "Partitioned"), + INIT_PARAM_DFLT(smtIQThreshold, "SMT IQ Threshold", 100), + INIT_PARAM_DFLT(smtROBPolicy, "SMT ROB Sharing Policy", "Partitioned"), + INIT_PARAM_DFLT(smtROBThreshold,"SMT ROB Threshold", 100), + INIT_PARAM_DFLT(smtCommitPolicy,"SMT Commit Fetch Policy", "RoundRobin"), + + INIT_PARAM(instShiftAmt, "Number of bits to shift instructions by"), + INIT_PARAM(defer_registration, "defer system registration (for sampling)"), + + INIT_PARAM(function_trace, "Enable function trace"), + INIT_PARAM(function_trace_start, "Cycle to start function trace") + +END_INIT_SIM_OBJECT_PARAMS(DerivO3CPU) + +CREATE_SIM_OBJECT(DerivO3CPU) +{ + DerivO3CPU *cpu; + +#if FULL_SYSTEM + // Full-system only supports a single thread for the moment. + int actual_num_threads = 1; +#else + // In non-full-system mode, we infer the number of threads from + // the workload if it's not explicitly specified. + int actual_num_threads = + (numThreads.isValid() && numThreads >= workload.size()) ? + numThreads : workload.size(); + + if (workload.size() == 0) { + fatal("Must specify at least one workload!"); + } +#endif + + SparcSimpleParams *params = new SparcSimpleParams; + + params->clock = clock; + + params->name = getInstanceName(); + params->numberOfThreads = actual_num_threads; + params->activity = activity; + +#if FULL_SYSTEM + params->system = system; + params->cpu_id = cpu_id; + params->itb = itb; + params->dtb = dtb; + params->profile = profile; + + params->do_quiesce = do_quiesce; + params->do_checkpoint_insts = do_checkpoint_insts; + params->do_statistics_insts = do_statistics_insts; +#else + params->workload = workload; +#endif // FULL_SYSTEM + + params->checker = checker; + + params->max_insts_any_thread = max_insts_any_thread; + params->max_insts_all_threads = max_insts_all_threads; + params->max_loads_any_thread = max_loads_any_thread; + params->max_loads_all_threads = max_loads_all_threads; + params->progress_interval = progress_interval; + + // + // Caches + // + params->cachePorts = cachePorts; + + params->decodeToFetchDelay = decodeToFetchDelay; + params->renameToFetchDelay = renameToFetchDelay; + params->iewToFetchDelay = iewToFetchDelay; + params->commitToFetchDelay = commitToFetchDelay; + params->fetchWidth = fetchWidth; + + params->renameToDecodeDelay = renameToDecodeDelay; + params->iewToDecodeDelay = iewToDecodeDelay; + params->commitToDecodeDelay = commitToDecodeDelay; + params->fetchToDecodeDelay = fetchToDecodeDelay; + params->decodeWidth = decodeWidth; + + params->iewToRenameDelay = iewToRenameDelay; + params->commitToRenameDelay = commitToRenameDelay; + params->decodeToRenameDelay = decodeToRenameDelay; + params->renameWidth = renameWidth; + + params->commitToIEWDelay = commitToIEWDelay; + params->renameToIEWDelay = renameToIEWDelay; + params->issueToExecuteDelay = issueToExecuteDelay; + params->dispatchWidth = dispatchWidth; + params->issueWidth = issueWidth; + params->wbWidth = wbWidth; + params->wbDepth = wbDepth; + params->fuPool = fuPool; + + params->iewToCommitDelay = iewToCommitDelay; + params->renameToROBDelay = renameToROBDelay; + params->commitWidth = commitWidth; + params->squashWidth = squashWidth; + params->trapLatency = trapLatency; + + params->backComSize = backComSize; + params->forwardComSize = forwardComSize; + + params->predType = predType; + params->localPredictorSize = localPredictorSize; + params->localCtrBits = localCtrBits; + params->localHistoryTableSize = localHistoryTableSize; + params->localHistoryBits = localHistoryBits; + params->globalPredictorSize = globalPredictorSize; + params->globalCtrBits = globalCtrBits; + params->globalHistoryBits = globalHistoryBits; + params->choicePredictorSize = choicePredictorSize; + params->choiceCtrBits = choiceCtrBits; + + params->BTBEntries = BTBEntries; + params->BTBTagSize = BTBTagSize; + + params->RASSize = RASSize; + + params->LQEntries = LQEntries; + params->SQEntries = SQEntries; + + params->SSITSize = SSITSize; + params->LFSTSize = LFSTSize; + + params->numPhysIntRegs = numPhysIntRegs; + params->numPhysFloatRegs = numPhysFloatRegs; + params->numIQEntries = numIQEntries; + params->numROBEntries = numROBEntries; + + params->smtNumFetchingThreads = smtNumFetchingThreads; + + // Default smtFetchPolicy to "RoundRobin", if necessary. + std::string round_robin_policy = "RoundRobin"; + std::string single_thread = "SingleThread"; + + if (actual_num_threads > 1 && single_thread.compare(smtFetchPolicy) == 0) + params->smtFetchPolicy = round_robin_policy; + else + params->smtFetchPolicy = smtFetchPolicy; + + params->smtIQPolicy = smtIQPolicy; + params->smtLSQPolicy = smtLSQPolicy; + params->smtLSQThreshold = smtLSQThreshold; + params->smtROBPolicy = smtROBPolicy; + params->smtROBThreshold = smtROBThreshold; + params->smtCommitPolicy = smtCommitPolicy; + + params->instShiftAmt = 2; + + params->deferRegistration = defer_registration; + + params->functionTrace = function_trace; + params->functionTraceStart = function_trace_start; + + cpu = new DerivO3CPU(params); + + return cpu; +} + +REGISTER_SIM_OBJECT("DerivO3CPU", DerivO3CPU) + diff --git a/src/cpu/o3/sparc/cpu_impl.hh b/src/cpu/o3/sparc/cpu_impl.hh new file mode 100644 index 000000000..536a620bf --- /dev/null +++ b/src/cpu/o3/sparc/cpu_impl.hh @@ -0,0 +1,319 @@ +/* + * Copyright (c) 2004-2006 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Gabe Black + */ + +#include "config/use_checker.hh" + +#include "arch/sparc/faults.hh" +#include "arch/sparc/isa_traits.hh" +#include "arch/sparc/miscregfile.hh" +#include "base/cprintf.hh" +#include "base/statistics.hh" +#include "base/timebuf.hh" +#include "cpu/checker/thread_context.hh" +#include "sim/sim_events.hh" +#include "sim/stats.hh" + +#include "cpu/o3/sparc/cpu.hh" +#include "cpu/o3/sparc/params.hh" +#include "cpu/o3/sparc/thread_context.hh" +#include "cpu/o3/comm.hh" +#include "cpu/o3/thread_state.hh" + +#if FULL_SYSTEM +#include "arch/sparc/isa_traits.hh" +#include "arch/sparc/kernel_stats.hh" +#include "cpu/quiesce_event.hh" +#include "sim/sim_exit.hh" +#include "sim/system.hh" +#endif + +template <class Impl> +SparcO3CPU<Impl>::SparcO3CPU(Params *params) +#if FULL_SYSTEM + : FullO3CPU<Impl>(params), itb(params->itb), dtb(params->dtb) +#else + : FullO3CPU<Impl>(params) +#endif +{ + DPRINTF(O3CPU, "Creating SparcO3CPU object.\n"); + + // Setup any thread state. + this->thread.resize(this->numThreads); + + for (int i = 0; i < this->numThreads; ++i) { +#if FULL_SYSTEM + // SMT is not supported in FS mode yet. + assert(this->numThreads == 1); + this->thread[i] = new Thread(this, 0); + this->thread[i]->setStatus(ThreadContext::Suspended); +#else + if (i < params->workload.size()) { + DPRINTF(O3CPU, "Workload[%i] process is %#x", + i, this->thread[i]); + this->thread[i] = new Thread(this, i, params->workload[i], i); + + this->thread[i]->setStatus(ThreadContext::Suspended); + + //usedTids[i] = true; + //threadMap[i] = i; + } else { + //Allocate Empty thread so M5 can use later + //when scheduling threads to CPU + Process* dummy_proc = NULL; + + this->thread[i] = new Thread(this, i, dummy_proc, i); + //usedTids[i] = false; + } +#endif // !FULL_SYSTEM + + ThreadContext *tc; + + // Setup the TC that will serve as the interface to the threads/CPU. + SparcTC<Impl> *sparc_tc = new SparcTC<Impl>; + + tc = sparc_tc; + + // If we're using a checker, then the TC should be the + // CheckerThreadContext. +#if USE_CHECKER + if (params->checker) { + tc = new CheckerThreadContext<SparcTC<Impl> >( + sparc_tc, this->checker); + } +#endif + + sparc_tc->cpu = this; + sparc_tc->thread = this->thread[i]; + +#if FULL_SYSTEM + // Setup quiesce event. + this->thread[i]->quiesceEvent = new EndQuiesceEvent(tc); +#endif + // Give the thread the TC. + this->thread[i]->tc = tc; + + // Add the TC to the CPU's list of TC's. + this->threadContexts.push_back(tc); + } + + for (int i=0; i < this->numThreads; i++) { + this->thread[i]->setFuncExeInst(0); + } + + // Sets CPU pointers. These must be set at this level because the CPU + // pointers are defined to be the highest level of CPU class. + this->fetch.setCPU(this); + this->decode.setCPU(this); + this->rename.setCPU(this); + this->iew.setCPU(this); + this->commit.setCPU(this); + + this->rob.setCPU(this); + this->regFile.setCPU(this); + + lockAddr = 0; + lockFlag = false; +} + +template <class Impl> +void +SparcO3CPU<Impl>::regStats() +{ + // Register stats for everything that has stats. + this->fullCPURegStats(); + this->fetch.regStats(); + this->decode.regStats(); + this->rename.regStats(); + this->iew.regStats(); + this->commit.regStats(); +} + + +template <class Impl> +TheISA::MiscReg +SparcO3CPU<Impl>::readMiscReg(int misc_reg, unsigned tid) +{ + return this->regFile.readMiscReg(misc_reg, tid); +} + +template <class Impl> +TheISA::MiscReg +SparcO3CPU<Impl>::readMiscRegWithEffect(int misc_reg, unsigned tid) +{ + return this->regFile.readMiscRegWithEffect(misc_reg, tid); +} + +template <class Impl> +void +SparcO3CPU<Impl>::setMiscReg(int misc_reg, const MiscReg &val, unsigned tid) +{ + this->regFile.setMiscReg(misc_reg, val, tid); +} + +template <class Impl> +void +SparcO3CPU<Impl>::setMiscRegWithEffect(int misc_reg, const MiscReg &val, + unsigned tid) +{ + this->regFile.setMiscRegWithEffect(misc_reg, val, tid); +} + +template <class Impl> +void +SparcO3CPU<Impl>::squashFromTC(unsigned tid) +{ + this->thread[tid]->inSyscall = true; + this->commit.generateTCEvent(tid); +} + +#if FULL_SYSTEM + +template <class Impl> +void +SparcO3CPU<Impl>::post_interrupt(int int_num, int index) +{ + BaseCPU::post_interrupt(int_num, index); + + if (this->thread[0]->status() == ThreadContext::Suspended) { + DPRINTF(IPI,"Suspended Processor awoke\n"); + this->threadContexts[0]->activate(); + } +} + +template <class Impl> +Fault +SparcO3CPU<Impl>::hwrei(unsigned tid) +{ + panic("This doesn't make sense for SPARC\n"); + return NoFault; +} + +template <class Impl> +bool +SparcO3CPU<Impl>::simPalCheck(int palFunc, unsigned tid) +{ + panic("This doesn't make sense for SPARC\n"); + return true; +} + +template <class Impl> +Fault +SparcO3CPU<Impl>::getInterrupts() +{ + // Check if there are any outstanding interrupts + return this->interrupts.getInterrupt(this->threadContexts[0]); +} + +template <class Impl> +void +SparcO3CPU<Impl>::processInterrupts(Fault interrupt) +{ + // Check for interrupts here. For now can copy the code that + // exists within isa_fullsys_traits.hh. Also assume that thread 0 + // is the one that handles the interrupts. + // @todo: Possibly consolidate the interrupt checking code. + // @todo: Allow other threads to handle interrupts. + + assert(interrupt != NoFault); + this->interrupts.updateIntrInfo(this->threadContexts[0]); + + DPRINTF(O3CPU, "Interrupt %s being handled\n", interrupt->name()); + this->checkInterrupts = false; + this->trap(interrupt, 0); +} + +#endif // FULL_SYSTEM + +template <class Impl> +void +SparcO3CPU<Impl>::trap(Fault fault, unsigned tid) +{ + // Pass the thread's TC into the invoke method. + fault->invoke(this->threadContexts[tid]); +} + +#if !FULL_SYSTEM + +template <class Impl> +void +SparcO3CPU<Impl>::syscall(int64_t callnum, int tid) +{ + DPRINTF(O3CPU, "[tid:%i] Executing syscall().\n\n", tid); + + DPRINTF(Activity,"Activity: syscall() called.\n"); + + // Temporarily increase this by one to account for the syscall + // instruction. + ++(this->thread[tid]->funcExeInst); + + // Execute the actual syscall. + this->thread[tid]->syscall(callnum); + + // Decrease funcExeInst by one as the normal commit will handle + // incrementing it. + --(this->thread[tid]->funcExeInst); +} + +template <class Impl> +TheISA::IntReg +SparcO3CPU<Impl>::getSyscallArg(int i, int tid) +{ + return this->readArchIntReg(SparcISA::ArgumentReg0 + i, tid); +} + +template <class Impl> +void +SparcO3CPU<Impl>::setSyscallArg(int i, IntReg val, int tid) +{ + this->setArchIntReg(SparcISA::ArgumentReg0 + i, val, tid); +} + +template <class Impl> +void +SparcO3CPU<Impl>::setSyscallReturn(SyscallReturn return_value, int tid) +{ + // check for error condition. SPARC syscall convention is to + // indicate success/failure in reg the carry bit of the ccr + // and put the return value itself in the standard return value reg (). + if (return_value.successful()) { + // no error, clear XCC.C + this->setMiscReg(SparcISA::MISCREG_CCR, + this->readMiscReg(SparcISA::MISCREG_CCR, tid) & 0xEE, tid); + this->setArchIntReg(SparcISA::ReturnValueReg, + return_value.value(), tid); + } else { + // got an error, set XCC.C + this->setMiscReg(SparcISA::MISCREG_CCR, + this->readMiscReg(SparcISA::MISCREG_CCR, tid) | 0x11, tid); + this->setArchIntReg(SparcISA::ReturnValueReg, + return_value.value(), tid); + } +} +#endif diff --git a/src/cpu/o3/sparc/dyn_inst.cc b/src/cpu/o3/sparc/dyn_inst.cc new file mode 100644 index 000000000..984b58f4b --- /dev/null +++ b/src/cpu/o3/sparc/dyn_inst.cc @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2004-2005 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Gabe Black + */ + +#include "cpu/o3/sparc/dyn_inst_impl.hh" +#include "cpu/o3/sparc/impl.hh" + +// Force instantiation of SparcDynInst for all the implementations that +// are needed. +template class SparcDynInst<SparcSimpleImpl>; diff --git a/src/cpu/o3/sparc/dyn_inst.hh b/src/cpu/o3/sparc/dyn_inst.hh new file mode 100644 index 000000000..f8d6bb63f --- /dev/null +++ b/src/cpu/o3/sparc/dyn_inst.hh @@ -0,0 +1,273 @@ +/* + * Copyright (c) 2004-2006 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Gabe Black + */ + +#ifndef __CPU_O3_SPARC_DYN_INST_HH__ +#define __CPU_O3_SPARC_DYN_INST_HH__ + +#include "arch/sparc/isa_traits.hh" +#include "cpu/base_dyn_inst.hh" +#include "cpu/inst_seq.hh" +#include "cpu/o3/sparc/cpu.hh" +#include "cpu/o3/sparc/impl.hh" + +class Packet; + +/** + * Mostly implementation & ISA specific SparcDynInst. As with most + * other classes in the new CPU model, it is templated on the Impl to + * allow for passing in of all types, such as the CPU type and the ISA + * type. The SparcDynInst serves as the primary interface to the CPU + * for instructions that are executing. + */ +template <class Impl> +class SparcDynInst : public BaseDynInst<Impl> +{ + public: + /** Typedef for the CPU. */ + typedef typename Impl::O3CPU O3CPU; + + public: + /** BaseDynInst constructor given a binary instruction. */ + SparcDynInst(TheISA::ExtMachInst inst, Addr PC, + Addr Pred_PC, InstSeqNum seq_num, O3CPU *cpu); + + /** BaseDynInst constructor given a static inst pointer. */ + SparcDynInst(StaticInstPtr &_staticInst); + + /** Executes the instruction.*/ + Fault execute(); + + /** Initiates the access. Only valid for memory operations. */ + Fault initiateAcc(); + + /** Completes the access. Only valid for memory operations. */ + Fault completeAcc(PacketPtr pkt); + + private: + /** Initializes variables. */ + void initVars(); + + public: + /** Reads a miscellaneous register. */ + TheISA::MiscReg readMiscReg(int misc_reg) + { + return this->cpu->readMiscReg(misc_reg, this->threadNumber); + } + + /** Reads a misc. register, including any side-effects the read + * might have as defined by the architecture. + */ + TheISA::MiscReg readMiscRegWithEffect(int misc_reg) + { + return this->cpu->readMiscRegWithEffect(misc_reg, this->threadNumber); + } + + /** Sets a misc. register. */ + void setMiscReg(int misc_reg, const TheISA::MiscReg &val) + { + this->instResult.integer = val; + return this->cpu->setMiscReg(misc_reg, val, this->threadNumber); + } + + /** Sets a misc. register, including any side-effects the write + * might have as defined by the architecture. + */ + void setMiscRegWithEffect(int misc_reg, const TheISA::MiscReg &val) + { + return this->cpu->setMiscRegWithEffect(misc_reg, val, + this->threadNumber); + } + +#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 + /** Calls a syscall. */ + void syscall(int64_t callnum); +#endif + + private: + /** Physical register index of the destination registers of this + * instruction. + */ + PhysRegIndex _destRegIdx[TheISA::MaxInstDestRegs]; + + /** Physical register index of the source registers of this + * instruction. + */ + PhysRegIndex _srcRegIdx[TheISA::MaxInstSrcRegs]; + + /** Physical register index of the previous producers of the + * architected destinations. + */ + PhysRegIndex _prevDestRegIdx[TheISA::MaxInstDestRegs]; + + public: + + // The register accessor methods provide the index of the + // instruction's operand (e.g., 0 or 1), not the architectural + // register index, to simplify the implementation of register + // renaming. We find the architectural register index by indexing + // into the instruction's own operand index table. Note that a + // raw pointer to the StaticInst is provided instead of a + // ref-counted StaticInstPtr to redice overhead. This is fine as + // long as these methods don't copy the pointer into any long-term + // storage (which is pretty hard to imagine they would have reason + // to do). + + uint64_t readIntReg(const StaticInst *si, int idx) + { + return this->cpu->readIntReg(_srcRegIdx[idx]); + } + + TheISA::FloatReg readFloatReg(const StaticInst *si, int idx, int width) + { + return this->cpu->readFloatReg(_srcRegIdx[idx], width); + } + + TheISA::FloatReg readFloatReg(const StaticInst *si, int idx) + { + return this->cpu->readFloatReg(_srcRegIdx[idx]); + } + + TheISA::FloatRegBits readFloatRegBits(const StaticInst *si, + int idx, int width) + { + return this->cpu->readFloatRegBits(_srcRegIdx[idx], width); + } + + TheISA::FloatRegBits readFloatRegBits(const StaticInst *si, int idx) + { + return this->cpu->readFloatRegBits(_srcRegIdx[idx]); + } + + /** @todo: Make results into arrays so they can handle multiple dest + * registers. + */ + void setIntReg(const StaticInst *si, int idx, uint64_t val) + { + this->cpu->setIntReg(_destRegIdx[idx], val); + BaseDynInst<Impl>::setIntReg(si, idx, val); + } + + void setFloatReg(const StaticInst *si, int idx, + TheISA::FloatReg val, int width) + { + this->cpu->setFloatReg(_destRegIdx[idx], val, width); + BaseDynInst<Impl>::setFloatReg(si, idx, val, width); + } + + void setFloatReg(const StaticInst *si, int idx, TheISA::FloatReg val) + { + this->cpu->setFloatReg(_destRegIdx[idx], val); + BaseDynInst<Impl>::setFloatReg(si, idx, val); + } + + void setFloatRegBits(const StaticInst *si, int idx, + TheISA::FloatRegBits val, int width) + { + this->cpu->setFloatRegBits(_destRegIdx[idx], val, width); + BaseDynInst<Impl>::setFloatRegBits(si, idx, val); + } + + void setFloatRegBits(const StaticInst *si, + int idx, TheISA::FloatRegBits val) + { + this->cpu->setFloatRegBits(_destRegIdx[idx], val); + BaseDynInst<Impl>::setFloatRegBits(si, idx, val); + } + + /** Returns the physical register index of the i'th destination + * register. + */ + PhysRegIndex renamedDestRegIdx(int idx) const + { + return _destRegIdx[idx]; + } + + /** Returns the physical register index of the i'th source register. */ + PhysRegIndex renamedSrcRegIdx(int idx) const + { + return _srcRegIdx[idx]; + } + + /** Returns the physical register index of the previous physical register + * that remapped to the same logical register index. + */ + PhysRegIndex prevDestRegIdx(int idx) const + { + return _prevDestRegIdx[idx]; + } + + /** Renames a destination register to a physical register. Also records + * the previous physical register that the logical register mapped to. + */ + void renameDestReg(int idx, + PhysRegIndex renamed_dest, + PhysRegIndex previous_rename) + { + _destRegIdx[idx] = renamed_dest; + _prevDestRegIdx[idx] = previous_rename; + } + + /** Renames a source logical register to the physical register which + * has/will produce that logical register's result. + * @todo: add in whether or not the source register is ready. + */ + void renameSrcReg(int idx, PhysRegIndex renamed_src) + { + _srcRegIdx[idx] = renamed_src; + } + + public: + /** Calculates EA part of a memory instruction. Currently unused, + * though it may be useful in the future if we want to split + * memory operations into EA calculation and memory access parts. + */ + Fault calcEA() + { + return this->staticInst->eaCompInst()->execute(this, this->traceData); + } + + /** Does the memory access part of a memory instruction. Currently unused, + * though it may be useful in the future if we want to split + * memory operations into EA calculation and memory access parts. + */ + Fault memAccess() + { + return this->staticInst->memAccInst()->execute(this, this->traceData); + } +}; + +#endif // __CPU_O3_SPARC_DYN_INST_HH__ + diff --git a/src/cpu/o3/sparc/dyn_inst_impl.hh b/src/cpu/o3/sparc/dyn_inst_impl.hh new file mode 100644 index 000000000..210daace2 --- /dev/null +++ b/src/cpu/o3/sparc/dyn_inst_impl.hh @@ -0,0 +1,139 @@ +/* + * Copyright (c) 2004-2006 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Gabe Black + */ + +#include "cpu/o3/sparc/dyn_inst.hh" + +template <class Impl> +SparcDynInst<Impl>::SparcDynInst(TheISA::ExtMachInst inst, Addr PC, + Addr Pred_PC, InstSeqNum seq_num, O3CPU *cpu) + : BaseDynInst<Impl>(inst, PC, Pred_PC, seq_num, cpu) +{ + initVars(); +} + +template <class Impl> +SparcDynInst<Impl>::SparcDynInst(StaticInstPtr &_staticInst) + : BaseDynInst<Impl>(_staticInst) +{ + initVars(); +} + +template <class Impl> +void +SparcDynInst<Impl>::initVars() +{ + // Make sure to have the renamed register entries set to the same + // as the normal register entries. It will allow the IQ to work + // without any modifications. + for (int i = 0; i < this->staticInst->numDestRegs(); i++) { + _destRegIdx[i] = this->staticInst->destRegIdx(i); + } + + for (int i = 0; i < this->staticInst->numSrcRegs(); i++) { + _srcRegIdx[i] = this->staticInst->srcRegIdx(i); + this->_readySrcRegIdx[i] = 0; + } +} + +template <class Impl> +Fault +SparcDynInst<Impl>::execute() +{ + // @todo: Pretty convoluted way to avoid squashing from happening + // when using the TC during an instruction's execution + // (specifically for instructions that have side-effects that use + // the TC). Fix this. + bool in_syscall = this->thread->inSyscall; + this->thread->inSyscall = true; + + this->fault = this->staticInst->execute(this, this->traceData); + + this->thread->inSyscall = in_syscall; + + return this->fault; +} + +template <class Impl> +Fault +SparcDynInst<Impl>::initiateAcc() +{ + // @todo: Pretty convoluted way to avoid squashing from happening + // when using the TC during an instruction's execution + // (specifically for instructions that have side-effects that use + // the TC). Fix this. + bool in_syscall = this->thread->inSyscall; + this->thread->inSyscall = true; + + this->fault = this->staticInst->initiateAcc(this, this->traceData); + + this->thread->inSyscall = in_syscall; + + return this->fault; +} + +template <class Impl> +Fault +SparcDynInst<Impl>::completeAcc(PacketPtr pkt) +{ + this->fault = this->staticInst->completeAcc(pkt, this, this->traceData); + + return this->fault; +} + +#if FULL_SYSTEM +template <class Impl> +Fault +SparcDynInst<Impl>::hwrei() +{ + return NoFault; +} + +template <class Impl> +void +SparcDynInst<Impl>::trap(Fault fault) +{ + this->cpu->trap(fault, this->threadNumber); +} + +template <class Impl> +bool +SparcDynInst<Impl>::simPalCheck(int palFunc) +{ + return this->cpu->simPalCheck(palFunc, this->threadNumber); +} +#else +template <class Impl> +void +SparcDynInst<Impl>::syscall(int64_t callnum) +{ + this->cpu->syscall(callnum, this->threadNumber); +} +#endif + diff --git a/src/cpu/o3/sparc/impl.hh b/src/cpu/o3/sparc/impl.hh new file mode 100644 index 000000000..0a970c2f0 --- /dev/null +++ b/src/cpu/o3/sparc/impl.hh @@ -0,0 +1,92 @@ +/* + * Copyright (c) 2004-2005 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Gabe Black + */ + +#ifndef __CPU_O3_SPARC_IMPL_HH__ +#define __CPU_O3_SPARC_IMPL_HH__ + +#include "arch/sparc/isa_traits.hh" + +#include "cpu/o3/sparc/params.hh" +#include "cpu/o3/cpu_policy.hh" + + +// Forward declarations. +template <class Impl> +class SparcDynInst; + +template <class Impl> +class SparcO3CPU; + +/** Implementation specific struct that defines several key types to the + * CPU, the stages within the CPU, the time buffers, and the DynInst. + * The struct defines the ISA, the CPU policy, the specific DynInst, the + * specific O3CPU, and all of the structs from the time buffers to do + * communication. + * This is one of the key things that must be defined for each hardware + * specific CPU implementation. + */ +struct SparcSimpleImpl +{ + /** The type of MachInst. */ + typedef TheISA::MachInst MachInst; + + /** The CPU policy to be used, which defines all of the CPU stages. */ + typedef SimpleCPUPolicy<SparcSimpleImpl> CPUPol; + + /** The DynInst type to be used. */ + typedef SparcDynInst<SparcSimpleImpl> DynInst; + + /** The refcounted DynInst pointer to be used. In most cases this is + * what should be used, and not DynInst *. + */ + typedef RefCountingPtr<DynInst> DynInstPtr; + + /** The O3CPU type to be used. */ + typedef SparcO3CPU<SparcSimpleImpl> O3CPU; + + /** Same typedef, but for CPUType. BaseDynInst may not always use + * an O3 CPU, so it's clearer to call it CPUType instead in that + * case. + */ + typedef O3CPU CPUType; + + /** The Params to be passed to each stage. */ + typedef SparcSimpleParams Params; + + enum { + MaxWidth = 8, + MaxThreads = 4 + }; +}; + +/** The O3Impl to be used. */ +typedef SparcSimpleImpl O3CPUImpl; + +#endif // __CPU_O3_SPARC_IMPL_HH__ diff --git a/src/cpu/o3/sparc/params.hh b/src/cpu/o3/sparc/params.hh new file mode 100644 index 000000000..d399d64c4 --- /dev/null +++ b/src/cpu/o3/sparc/params.hh @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2004-2006 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Gabe Black + */ + +#ifndef __CPU_O3_SPARC_PARAMS_HH__ +#define __CPU_O3_SPARC_PARAMS_HH__ + +#include "cpu/o3/cpu.hh" +#include "cpu/o3/params.hh" + +//Forward declarations +namespace SparcISA +{ + class DTB; + class ITB; +} +class MemObject; +class Process; +class System; + +/** + * This file defines the parameters that will be used for the AlphaO3CPU. + * This must be defined externally so that the Impl can have a params class + * defined that it can pass to all of the individual stages. + */ + +class SparcSimpleParams : public O3Params +{ + public: + +#if FULL_SYSTEM + SparcISA::ITB *itb; + SparcISA::DTB *dtb; +#endif +}; + +#endif // __CPU_O3_SPARC_PARAMS_HH__ diff --git a/src/cpu/o3/sparc/thread_context.cc b/src/cpu/o3/sparc/thread_context.cc new file mode 100755 index 000000000..d85aff502 --- /dev/null +++ b/src/cpu/o3/sparc/thread_context.cc @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2004-2006 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Gabe Black + */ + +#include "cpu/o3/thread_context.hh" +#include "cpu/o3/thread_context_impl.hh" + +template class O3ThreadContext<SparcSimpleImpl>; + diff --git a/src/cpu/o3/sparc/thread_context.hh b/src/cpu/o3/sparc/thread_context.hh new file mode 100644 index 000000000..69d1e2d04 --- /dev/null +++ b/src/cpu/o3/sparc/thread_context.hh @@ -0,0 +1,84 @@ +/* + * Copyright (c) 2004-2006 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Gabe Black + */ + +#include "arch/sparc/types.hh" +#include "cpu/o3/thread_context.hh" + +template <class Impl> +class SparcTC : public O3ThreadContext<Impl> +{ + public: +#if FULL_SYSTEM + /** Returns a pointer to the ITB. */ + virtual SparcISA::ITB *getITBPtr() { return this->cpu->itb; } + + /** Returns a pointer to the DTB. */ + virtual SparcISA::DTB *getDTBPtr() { return this->cpu->dtb; } + + /** Returns pointer to the quiesce event. */ + virtual EndQuiesceEvent *getQuiesceEvent() + { + return this->thread->quiesceEvent; + } +#endif + + virtual uint64_t readNextNPC() + { + return this->cpu->readNextNPC(this->thread->readTid()); + } + + virtual void setNextNPC(uint64_t val) + { + this->cpu->setNextNPC(val, this->thread->readTid()); + } + + virtual void changeRegFileContext(TheISA::RegContextParam param, + TheISA::RegContextVal val) + { + panic("This doesn't make sense!\n"); + } + + + /** This function exits the thread context in the CPU and returns + * 1 if the CPU has no more active threads (meaning it's OK to exit); + * Used in syscall-emulation mode when a thread executes the 'exit' + * syscall. + */ + virtual int exit() + { + this->deallocate(); + + // If there are still threads executing in the system + if (this->cpu->numActiveThreads()) + return 0; // don't exit simulation + else + return 1; // exit simulation + } +}; diff --git a/src/cpu/ozone/front_end.hh b/src/cpu/ozone/front_end.hh index e09e4de9c..0acf99ead 100644 --- a/src/cpu/ozone/front_end.hh +++ b/src/cpu/ozone/front_end.hh @@ -92,7 +92,7 @@ class FrontEnd /** Returns the address ranges of this device. */ virtual void getDeviceAddressRanges(AddrRangeList &resp, AddrRangeList &snoop) - { resp.clear(); snoop.clear(); snoop.push_back(RangeSize(0,-1)); } + { resp.clear(); snoop.clear(); snoop.push_back(RangeSize(0,0)); } /** Timing version of receive. Handles setting fetch to the * proper status to start fetching. */ diff --git a/src/cpu/ozone/lw_lsq.hh b/src/cpu/ozone/lw_lsq.hh index 7e6849668..c981b8e63 100644 --- a/src/cpu/ozone/lw_lsq.hh +++ b/src/cpu/ozone/lw_lsq.hh @@ -258,7 +258,7 @@ class OzoneLWLSQ { virtual void getDeviceAddressRanges(AddrRangeList &resp, AddrRangeList &snoop) - { resp.clear(); snoop.clear(); snoop.push_back(RangeSize(0,-1)); } + { resp.clear(); snoop.clear(); snoop.push_back(RangeSize(0,0)); } virtual bool recvTiming(PacketPtr pkt); diff --git a/src/cpu/simple/atomic.cc b/src/cpu/simple/atomic.cc index 8cfe2ee83..8db864153 100644 --- a/src/cpu/simple/atomic.cc +++ b/src/cpu/simple/atomic.cc @@ -29,6 +29,7 @@ */ #include "arch/locked_mem.hh" +#include "arch/mmaped_ipr.hh" #include "arch/utility.hh" #include "cpu/exetrace.hh" #include "cpu/simple/atomic.hh" @@ -289,10 +290,16 @@ AtomicSimpleCPU::read(Addr addr, T &data, unsigned flags) if (fault == NoFault) { pkt->reinitFromRequest(); - dcache_latency = dcachePort.sendAtomic(pkt); + if (req->isMmapedIpr()) + dcache_latency = TheISA::handleIprRead(thread->getTC(),pkt); + else + dcache_latency = dcachePort.sendAtomic(pkt); dcache_access = true; - - assert(pkt->result == Packet::Success); +#if !defined(NDEBUG) + if (pkt->result != Packet::Success) + panic("Unable to find responder for address pa = %#X va = %#X\n", + pkt->req->getPaddr(), pkt->req->getVaddr()); +#endif data = pkt->get<T>(); if (req->isLocked()) { @@ -376,14 +383,22 @@ AtomicSimpleCPU::write(T data, Addr addr, unsigned flags, uint64_t *res) } if (do_access) { - data = htog(data); pkt->reinitFromRequest(); pkt->dataStatic(&data); - dcache_latency = dcachePort.sendAtomic(pkt); + if (req->isMmapedIpr()) { + dcache_latency = TheISA::handleIprWrite(thread->getTC(), pkt); + } else { + data = htog(data); + dcache_latency = dcachePort.sendAtomic(pkt); + } dcache_access = true; - assert(pkt->result == Packet::Success); +#if !defined(NDEBUG) + if (pkt->result != Packet::Success) + panic("Unable to find responder for address pa = %#X va = %#X\n", + pkt->req->getPaddr(), pkt->req->getVaddr()); +#endif } if (req->isLocked()) { @@ -476,9 +491,15 @@ AtomicSimpleCPU::tick() dcache_access = false; // assume no dcache access preExecute(); + fault = curStaticInst->execute(this, traceData); postExecute(); + // @todo remove me after debugging with legion done + if (curStaticInst && (!curStaticInst->isMicroOp() || + curStaticInst->isLastMicroOp())) + instCnt++; + if (simulate_stalls) { Tick icache_stall = icache_latency - cycles(1); Tick dcache_stall = diff --git a/src/cpu/simple/atomic.hh b/src/cpu/simple/atomic.hh index 0df6fe079..42c7bf23a 100644 --- a/src/cpu/simple/atomic.hh +++ b/src/cpu/simple/atomic.hh @@ -106,7 +106,7 @@ class AtomicSimpleCPU : public BaseSimpleCPU virtual void getDeviceAddressRanges(AddrRangeList &resp, AddrRangeList &snoop) - { resp.clear(); snoop.clear(); snoop.push_back(RangeSize(0,-1)); } + { resp.clear(); snoop.clear(); snoop.push_back(RangeSize(0,0)); } }; CpuPort icachePort; diff --git a/src/cpu/simple/timing.hh b/src/cpu/simple/timing.hh index fe5d03666..abcb224bf 100644 --- a/src/cpu/simple/timing.hh +++ b/src/cpu/simple/timing.hh @@ -94,7 +94,7 @@ class TimingSimpleCPU : public BaseSimpleCPU virtual void getDeviceAddressRanges(AddrRangeList &resp, AddrRangeList &snoop) - { resp.clear(); snoop.clear(); snoop.push_back(RangeSize(0,-1)); } + { resp.clear(); snoop.clear(); snoop.push_back(RangeSize(0,0)); } struct TickEvent : public Event { |