diff options
Diffstat (limited to 'src')
153 files changed, 2917 insertions, 1277 deletions
diff --git a/src/arch/alpha/faults.cc b/src/arch/alpha/faults.cc index eef4361fd..7179bf025 100644 --- a/src/arch/alpha/faults.cc +++ b/src/arch/alpha/faults.cc @@ -194,7 +194,8 @@ void PageTableFault::invoke(ThreadContext *tc) // We've accessed the next page if (vaddr > p->stack_min - PageBytes) { - warn("Increasing stack %#x:%#x to %#x:%#x because of access to %#x", + DPRINTF(Stack, + "Increasing stack %#x:%#x to %#x:%#x because of access to %#x", p->stack_min, p->stack_base, p->stack_min - PageBytes, p->stack_base, vaddr); p->stack_min -= PageBytes; @@ -202,6 +203,7 @@ void PageTableFault::invoke(ThreadContext *tc) fatal("Over max stack size for one thread\n"); p->pTable->allocate(p->stack_min, PageBytes); } else { + warn("Page fault on address %#x\n", vaddr); FaultBase::invoke(tc); } } diff --git a/src/arch/alpha/isa/main.isa b/src/arch/alpha/isa/main.isa index 1270bf8d8..2024b1117 100644 --- a/src/arch/alpha/isa/main.isa +++ b/src/arch/alpha/isa/main.isa @@ -45,20 +45,22 @@ output header {{ #include <iostream> #include <iomanip> +#include "arch/alpha/faults.hh" #include "config/ss_compatible_fp.hh" #include "cpu/static_inst.hh" -#include "arch/alpha/faults.hh" #include "mem/request.hh" // some constructors use MemReq flags +#include "mem/packet.hh" }}; output decoder {{ +#include <cmath> + #include "base/cprintf.hh" #include "base/fenv.hh" #include "base/loader/symtab.hh" #include "config/ss_compatible_fp.hh" #include "cpu/thread_context.hh" // for Jump::branchTarget() - -#include <math.h> +#include "mem/packet.hh" using namespace AlphaISA; }}; @@ -73,8 +75,9 @@ output exec {{ #include "config/ss_compatible_fp.hh" #include "cpu/base.hh" #include "cpu/exetrace.hh" +#include "mem/packet.hh" +#include "mem/packet_access.hh" #include "sim/sim_exit.hh" -#include "mem/packet_impl.hh" using namespace AlphaISA; }}; diff --git a/src/arch/alpha/isa/mem.isa b/src/arch/alpha/isa/mem.isa index fe69c36a5..02291ed6b 100644 --- a/src/arch/alpha/isa/mem.isa +++ b/src/arch/alpha/isa/mem.isa @@ -186,7 +186,7 @@ def template InitiateAccDeclare {{ def template CompleteAccDeclare {{ - Fault completeAcc(Packet *, %(CPU_exec_context)s *, + Fault completeAcc(PacketPtr, %(CPU_exec_context)s *, Trace::InstRecord *) const; }}; @@ -313,7 +313,7 @@ def template LoadInitiateAcc {{ def template LoadCompleteAcc {{ - Fault %(class_name)s::completeAcc(Packet *pkt, + Fault %(class_name)s::completeAcc(PacketPtr pkt, %(CPU_exec_context)s *xc, Trace::InstRecord *traceData) const { @@ -437,7 +437,7 @@ def template StoreInitiateAcc {{ def template StoreCompleteAcc {{ - Fault %(class_name)s::completeAcc(Packet *pkt, + Fault %(class_name)s::completeAcc(PacketPtr pkt, %(CPU_exec_context)s *xc, Trace::InstRecord *traceData) const { @@ -460,7 +460,7 @@ def template StoreCompleteAcc {{ def template StoreCondCompleteAcc {{ - Fault %(class_name)s::completeAcc(Packet *pkt, + Fault %(class_name)s::completeAcc(PacketPtr pkt, %(CPU_exec_context)s *xc, Trace::InstRecord *traceData) const { @@ -535,7 +535,7 @@ def template MiscInitiateAcc {{ def template MiscCompleteAcc {{ - Fault %(class_name)s::completeAcc(Packet *pkt, + Fault %(class_name)s::completeAcc(PacketPtr pkt, %(CPU_exec_context)s *xc, Trace::InstRecord *traceData) const { diff --git a/src/arch/alpha/utility.hh b/src/arch/alpha/utility.hh index d3ccc0444..0304d1c3a 100644 --- a/src/arch/alpha/utility.hh +++ b/src/arch/alpha/utility.hh @@ -37,16 +37,17 @@ #include "arch/alpha/isa_traits.hh" #include "arch/alpha/regfile.hh" #include "base/misc.hh" +#include "cpu/thread_context.hh" namespace AlphaISA { static inline ExtMachInst - makeExtMI(MachInst inst, const uint64_t &pc) { + makeExtMI(MachInst inst, ThreadContext * xc) { #if FULL_SYSTEM ExtMachInst ext_inst = inst; - if (pc && 0x1) - return ext_inst|=(static_cast<ExtMachInst>(pc & 0x1) << 32); + if (xc->readPC() && 0x1) + return ext_inst|=(static_cast<ExtMachInst>(xc->readPC() & 0x1) << 32); else return ext_inst; #else diff --git a/src/arch/isa_parser.py b/src/arch/isa_parser.py index 4d522e18a..b235398f1 100755 --- a/src/arch/isa_parser.py +++ b/src/arch/isa_parser.py @@ -1636,7 +1636,7 @@ opClassRE = re.compile(r'.*Op|No_OpClass') class InstObjParams: def __init__(self, mnem, class_name, base_class = '', - code = None, opt_args = [], *extras): + code = None, opt_args = [], extras = {}): self.mnemonic = mnem self.class_name = class_name self.base_class = base_class @@ -1648,13 +1648,23 @@ class InstObjParams: else: origCode = code codeBlock = CodeBlock(code) - compositeCode = '\n'.join([origCode] + - [pair[1] for pair in extras]) + stringExtras = {} + otherExtras = {} + for (k, v) in extras.items(): + if type(v) == str: + stringExtras[k] = v + else: + otherExtras[k] = v + compositeCode = "\n".join([origCode] + stringExtras.values()) + # compositeCode = '\n'.join([origCode] + + # [pair[1] for pair in extras]) compositeBlock = CodeBlock(compositeCode) for code_attr in compositeBlock.__dict__.keys(): setattr(self, code_attr, getattr(compositeBlock, code_attr)) - for (key, snippet) in extras: + for (key, snippet) in stringExtras.items(): setattr(self, key, CodeBlock(snippet).code) + for (key, item) in otherExtras.items(): + setattr(self, key, item) self.code = codeBlock.code self.orig_code = origCode else: diff --git a/src/arch/mips/isa/formats/mem.isa b/src/arch/mips/isa/formats/mem.isa index d6b0c2938..e786cfbe2 100644 --- a/src/arch/mips/isa/formats/mem.isa +++ b/src/arch/mips/isa/formats/mem.isa @@ -162,7 +162,7 @@ def template InitiateAccDeclare {{ def template CompleteAccDeclare {{ - Fault completeAcc(Packet *, %(CPU_exec_context)s *, Trace::InstRecord *) const; + Fault completeAcc(PacketPtr, %(CPU_exec_context)s *, Trace::InstRecord *) const; }}; @@ -288,7 +288,7 @@ def template LoadInitiateAcc {{ def template LoadCompleteAcc {{ - Fault %(class_name)s::completeAcc(Packet *pkt, + Fault %(class_name)s::completeAcc(PacketPtr pkt, %(CPU_exec_context)s *xc, Trace::InstRecord *traceData) const { @@ -412,7 +412,7 @@ def template StoreInitiateAcc {{ def template StoreCompleteAcc {{ - Fault %(class_name)s::completeAcc(Packet *pkt, + Fault %(class_name)s::completeAcc(PacketPtr pkt, %(CPU_exec_context)s *xc, Trace::InstRecord *traceData) const { @@ -434,7 +434,7 @@ def template StoreCompleteAcc {{ }}; def template StoreCondCompleteAcc {{ - Fault %(class_name)s::completeAcc(Packet *pkt, + Fault %(class_name)s::completeAcc(PacketPtr pkt, %(CPU_exec_context)s *xc, Trace::InstRecord *traceData) const { @@ -509,7 +509,7 @@ def template MiscInitiateAcc {{ def template MiscCompleteAcc {{ - Fault %(class_name)s::completeAcc(Packet *pkt, + Fault %(class_name)s::completeAcc(PacketPtr pkt, %(CPU_exec_context)s *xc, Trace::InstRecord *traceData) const { diff --git a/src/arch/mips/isa/includes.isa b/src/arch/mips/isa/includes.isa index f58c8adaa..274fdcaa1 100644 --- a/src/arch/mips/isa/includes.isa +++ b/src/arch/mips/isa/includes.isa @@ -38,23 +38,25 @@ output header {{ #include <iostream> #include <iomanip> -#include "cpu/static_inst.hh" #include "arch/mips/isa_traits.hh" +#include "cpu/static_inst.hh" +#include "mem/packet.hh" }}; output decoder {{ +#include <cmath> +#if defined(linux) +#include <fenv.h> +#endif + +#include "arch/mips/faults.hh" +#include "arch/mips/isa_traits.hh" +#include "arch/mips/isa_traits.hh" #include "arch/mips/isa_traits.hh" +#include "arch/mips/utility.hh" #include "base/cprintf.hh" #include "base/loader/symtab.hh" #include "cpu/thread_context.hh" -#include "arch/mips/faults.hh" -#include "arch/mips/isa_traits.hh" -#include "arch/mips/utility.hh" - -#include <math.h> -#if defined(linux) -#include <fenv.h> -#endif using namespace MipsISA; }}; @@ -74,8 +76,9 @@ output exec {{ #endif #include "cpu/base.hh" #include "cpu/exetrace.hh" +#include "mem/packet.hh" +#include "mem/packet_access.hh" #include "sim/sim_exit.hh" -#include "mem/packet_impl.hh" using namespace MipsISA; }}; diff --git a/src/arch/mips/utility.hh b/src/arch/mips/utility.hh index ae2fe1aea..56689ba4d 100644 --- a/src/arch/mips/utility.hh +++ b/src/arch/mips/utility.hh @@ -35,6 +35,7 @@ #include "arch/mips/types.hh" #include "base/misc.hh" #include "config/full_system.hh" +#include "cpu/thread_context.hh" //XXX This is needed for size_t. We should use something other than size_t //#include "kern/linux/linux.hh" #include "sim/host.hh" @@ -86,11 +87,11 @@ namespace MipsISA { } static inline ExtMachInst - makeExtMI(MachInst inst, const uint64_t &pc) { + makeExtMI(MachInst inst, ThreadContext * xc) { #if FULL_SYSTEM ExtMachInst ext_inst = inst; - if (pc && 0x1) - return ext_inst|=(static_cast<ExtMachInst>(pc & 0x1) << 32); + if (xc->readPC() && 0x1) + return ext_inst|=(static_cast<ExtMachInst>(xc->readPC() & 0x1) << 32); else return ext_inst; #else diff --git a/src/arch/sparc/SConscript b/src/arch/sparc/SConscript index 66f2b57e0..e317502e0 100644 --- a/src/arch/sparc/SConscript +++ b/src/arch/sparc/SConscript @@ -44,6 +44,7 @@ Import('env') # Base sources used by all configurations. base_sources = Split(''' + asi.cc faults.cc floatregfile.cc intregfile.cc diff --git a/src/arch/sparc/asi.cc b/src/arch/sparc/asi.cc new file mode 100644 index 000000000..00c9e041e --- /dev/null +++ b/src/arch/sparc/asi.cc @@ -0,0 +1,279 @@ +/* + * Copyright (c) 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/asi.hh" + +namespace SparcISA +{ + bool AsiIsBlock(ASI asi) + { + return + (asi == ASI_BLK_AIUP) || + (asi == ASI_BLK_AIUS) || + (asi == ASI_BLK_AIUPL) || + (asi == ASI_BLK_AIUSL) || + (asi == ASI_BLK_P) || + (asi == ASI_BLK_S) || + (asi == ASI_BLK_PL) || + (asi == ASI_BLK_SL); + } + + bool AsiIsPrimary(ASI asi) + { + return + (asi == ASI_AIUP) || + (asi == ASI_BLK_AIUP) || + (asi == ASI_AIUPL) || + (asi == ASI_BLK_AIUPL) || + (asi == ASI_LDTX_AIUP) || + (asi == ASI_LDTX_AIUPL) || + (asi == ASI_P) || + (asi == ASI_PNF) || + (asi == ASI_PL) || + (asi == ASI_PNFL) || + (asi == ASI_PST8_P) || + (asi == ASI_PST16_P) || + (asi == ASI_PST32_P) || + (asi == ASI_PST8_PL) || + (asi == ASI_PST16_PL) || + (asi == ASI_PST32_PL) || + (asi == ASI_FL8_P) || + (asi == ASI_FL16_P) || + (asi == ASI_FL8_PL) || + (asi == ASI_FL16_PL) || + (asi == ASI_LDTX_P) || + (asi == ASI_LDTX_PL) || + (asi == ASI_BLK_P) || + (asi == ASI_BLK_PL); + } + + bool AsiIsSecondary(ASI asi) + { + return + (asi == ASI_AIUS) || + (asi == ASI_BLK_AIUS) || + (asi == ASI_AIUSL) || + (asi == ASI_BLK_AIUSL) || + (asi == ASI_LDTX_AIUS) || + (asi == ASI_LDTX_AIUSL) || + (asi == ASI_S) || + (asi == ASI_SNF) || + (asi == ASI_SL) || + (asi == ASI_SNFL) || + (asi == ASI_PST8_S) || + (asi == ASI_PST16_S) || + (asi == ASI_PST32_S) || + (asi == ASI_PST8_SL) || + (asi == ASI_PST16_SL) || + (asi == ASI_PST32_SL) || + (asi == ASI_FL8_S) || + (asi == ASI_FL16_S) || + (asi == ASI_FL8_SL) || + (asi == ASI_FL16_SL) || + (asi == ASI_LDTX_S) || + (asi == ASI_LDTX_SL) || + (asi == ASI_BLK_S) || + (asi == ASI_BLK_SL); + } + + bool AsiNucleus(ASI asi) + { + return + (asi == ASI_N) || + (asi == ASI_NL) || + (asi == ASI_LDTX_N) || + (asi == ASI_LDTX_NL); + } + + bool AsiIsAsIfUser(ASI asi) + { + return + (asi == ASI_AIUP) || + (asi == ASI_AIUS) || + (asi == ASI_BLK_AIUP) || + (asi == ASI_BLK_AIUS) || + (asi == ASI_AIUPL) || + (asi == ASI_AIUSL) || + (asi == ASI_BLK_AIUPL) || + (asi == ASI_BLK_AIUSL) || + (asi == ASI_LDTX_AIUP) || + (asi == ASI_LDTX_AIUS) || + (asi == ASI_LDTX_AIUPL) || + (asi == ASI_LDTX_AIUSL); + } + + bool AsiIsIO(ASI asi) + { + return + (asi == ASI_REAL_IO) || + (asi == ASI_REAL_IO_L); + } + + bool AsiIsReal(ASI asi) + { + return + (asi == ASI_REAL) || + (asi == ASI_REAL_IO) || + (asi == ASI_REAL_L) || + (asi == ASI_REAL_IO_L) || + (asi == ASI_LDTX_REAL) || + (asi == ASI_LDTX_REAL_L) || + (asi == ASI_MMU_REAL); + } + + bool AsiIsLittle(ASI asi) + { + return + (asi == ASI_NL) || + (asi == ASI_AIUPL) || + (asi == ASI_AIUSL) || + (asi == ASI_REAL_L) || + (asi == ASI_REAL_IO_L) || + (asi == ASI_BLK_AIUPL) || + (asi == ASI_BLK_AIUSL) || + (asi == ASI_LDTX_AIUPL) || + (asi == ASI_LDTX_AIUSL) || + (asi == ASI_LDTX_REAL_L) || + (asi == ASI_LDTX_NL) || + (asi == ASI_PL) || + (asi == ASI_SL) || + (asi == ASI_PNFL) || + (asi == ASI_SNFL) || + (asi == ASI_PST8_PL) || + (asi == ASI_PST8_SL) || + (asi == ASI_PST16_PL) || + (asi == ASI_PST16_SL) || + (asi == ASI_PST32_PL) || + (asi == ASI_PST32_SL) || + (asi == ASI_FL8_PL) || + (asi == ASI_FL8_SL) || + (asi == ASI_FL16_PL) || + (asi == ASI_FL16_SL) || + (asi == ASI_LDTX_PL) || + (asi == ASI_LDTX_SL) || + (asi == ASI_BLK_PL) || + (asi == ASI_BLK_SL); + } + + bool AsiIsTwin(ASI asi) + { + return + (asi == ASI_LDTX_AIUP) || + (asi == ASI_LDTX_AIUS) || + (asi == ASI_LDTX_REAL) || + (asi == ASI_LDTX_N) || + (asi == ASI_LDTX_AIUPL) || + (asi == ASI_LDTX_AIUSL) || + (asi == ASI_LDTX_REAL_L) || + (asi == ASI_LDTX_NL) || + (asi == ASI_LDTX_P) || + (asi == ASI_LDTX_S) || + (asi == ASI_LDTX_PL) || + (asi == ASI_LDTX_SL); + } + + bool AsiIsPartialStore(ASI asi) + { + return + (asi == ASI_PST8_P) || + (asi == ASI_PST8_S) || + (asi == ASI_PST16_P) || + (asi == ASI_PST16_S) || + (asi == ASI_PST32_P) || + (asi == ASI_PST32_S) || + (asi == ASI_PST8_PL) || + (asi == ASI_PST8_SL) || + (asi == ASI_PST16_PL) || + (asi == ASI_PST16_SL) || + (asi == ASI_PST32_PL) || + (asi == ASI_PST32_SL); + } + + bool AsiIsFloatingLoad(ASI asi) + { + return + (asi == ASI_FL8_P) || + (asi == ASI_FL8_S) || + (asi == ASI_FL16_P) || + (asi == ASI_FL16_S) || + (asi == ASI_FL8_PL) || + (asi == ASI_FL8_SL) || + (asi == ASI_FL16_PL) || + (asi == ASI_FL16_SL); + } + + bool AsiIsNoFault(ASI asi) + { + return + (asi == ASI_PNF) || + (asi == ASI_SNF) || + (asi == ASI_PNFL) || + (asi == ASI_SNFL); + } + + bool AsiIsScratchPad(ASI asi) + { + return + (asi == ASI_SCRATCHPAD) || + (asi == ASI_HYP_SCRATCHPAD); + } + + bool AsiIsCmt(ASI asi) + { + return + (asi == ASI_CMT_PER_STRAND) || + (asi == ASI_CMT_SHARED); + } + + bool AsiIsQueue(ASI asi) + { + return asi == ASI_QUEUE; + } + + bool AsiIsDtlb(ASI asi) + { + return + (asi == ASI_DTLB_DATA_IN_REG) || + (asi == ASI_DTLB_DATA_ACCESS_REG) || + (asi == ASI_DTLB_TAG_READ_REG); + } + + bool AsiIsMmu(ASI asi) + { + return + (asi == ASI_MMU_CONTEXTID) || + (asi == ASI_IMMU) || + (asi == ASI_MMU_REAL) || + (asi == ASI_MMU) || + (asi == ASI_DMMU) || + (asi == ASI_UMMU) || + (asi == ASI_DMMU_DEMAP); + } +} diff --git a/src/arch/sparc/asi.hh b/src/arch/sparc/asi.hh index 482e077e0..876567225 100644 --- a/src/arch/sparc/asi.hh +++ b/src/arch/sparc/asi.hh @@ -156,23 +156,23 @@ namespace SparcISA ASI_PST32_SL = 0xCD, ASI_PST32_SECONDARY_LITTLE = ASI_PST32_SL, //0xCE-0xCF implementation dependent - ASI_PL8_P = 0xD0, - ASI_PL8_PRIMARY = ASI_PL8_P, - ASI_PL8_S = 0xD1, - ASI_PL8_SECONDARY = ASI_PL8_S, - ASI_PL16_P = 0xD2, - ASI_PL16_PRIMARY = ASI_PL16_P, - ASI_PL16_S = 0xD3, - ASI_PL16_SECONDARY = ASI_PL16_S, + ASI_FL8_P = 0xD0, + ASI_FL8_PRIMARY = ASI_FL8_P, + ASI_FL8_S = 0xD1, + ASI_FL8_SECONDARY = ASI_FL8_S, + ASI_FL16_P = 0xD2, + ASI_FL16_PRIMARY = ASI_FL16_P, + ASI_FL16_S = 0xD3, + ASI_FL16_SECONDARY = ASI_FL16_S, //0xD4-0xD7 implementation dependent - ASI_PL8_PL = 0xD8, - ASI_PL8_PRIMARY_LITTLE = ASI_PL8_PL, - ASI_PL8_SL = 0xD9, - ASI_PL8_SECONDARY_LITTLE = ASI_PL8_SL, - ASI_PL16_PL = 0xDA, - ASI_PL16_PRIMARY_LITTLE = ASI_PL16_PL, - ASI_PL16_SL = 0xDB, - ASI_PL16_SECONDARY_LITTLE = ASI_PL16_SL, + ASI_FL8_PL = 0xD8, + ASI_FL8_PRIMARY_LITTLE = ASI_FL8_PL, + ASI_FL8_SL = 0xD9, + ASI_FL8_SECONDARY_LITTLE = ASI_FL8_SL, + ASI_FL16_PL = 0xDA, + ASI_FL16_PRIMARY_LITTLE = ASI_FL16_PL, + ASI_FL16_SL = 0xDB, + ASI_FL16_SECONDARY_LITTLE = ASI_FL16_SL, //0xDC-0xDF implementation dependent //0xE0-0xE1 reserved ASI_LDTX_P = 0xE2, @@ -193,9 +193,30 @@ namespace SparcISA ASI_BLK_PL = 0xF8, ASI_BLOCK_PRIMARY_LITTLE = ASI_BLK_PL, ASI_BLK_SL = 0xF9, - ASI_BLOCK_SECONDARY_LITTLE = ASI_BLK_SL + ASI_BLOCK_SECONDARY_LITTLE = ASI_BLK_SL, //0xFA-0xFF implementation dependent + MAX_ASI = 0xFF }; + + //Functions that classify an asi + bool AsiIsBlock(ASI); + bool AsiIsPrimary(ASI); + bool AsiIsSecondary(ASI); + bool AsiIsNucleus(ASI); + bool AsiIsAsIfUser(ASI); + bool AsiIsIO(ASI); + bool AsiIsReal(ASI); + bool AsiIsLittle(ASI); + bool AsiIsTwin(ASI); + bool AsiIsPartialStore(ASI); + bool AsiIsFloatingLoad(ASI); + bool AsiIsNoFault(ASI); + bool AsiIsScratchPad(ASI); + bool AsiIsCmt(ASI); + bool AsiIsQueue(ASI); + bool AsiIsDtlb(ASI); + bool AsiIsMmu(ASI); + }; #endif // __ARCH_SPARC_TLB_HH__ diff --git a/src/arch/sparc/isa/base.isa b/src/arch/sparc/isa/base.isa index b518265aa..a4c022411 100644 --- a/src/arch/sparc/isa/base.isa +++ b/src/arch/sparc/isa/base.isa @@ -77,7 +77,7 @@ output header {{ protected: // Constructor. SparcStaticInst(const char *mnem, - MachInst _machInst, OpClass __opClass) + ExtMachInst _machInst, OpClass __opClass) : StaticInst(mnem, _machInst, __opClass) { } diff --git a/src/arch/sparc/isa/bitfields.isa b/src/arch/sparc/isa/bitfields.isa index 27f52fa29..372f5c4ef 100644 --- a/src/arch/sparc/isa/bitfields.isa +++ b/src/arch/sparc/isa/bitfields.isa @@ -76,3 +76,7 @@ def bitfield SIMM11 <10:0>; def bitfield SIMM13 <12:0>; def bitfield SW_TRAP <7:0>; def bitfield X <12>; + +// Extended bitfields which aren't part of the actual instruction. + +def bitfield EXT_ASI <39:32>; diff --git a/src/arch/sparc/isa/decoder.isa b/src/arch/sparc/isa/decoder.isa index 1384b21a0..45d3616d9 100644 --- a/src/arch/sparc/isa/decoder.isa +++ b/src/arch/sparc/isa/decoder.isa @@ -441,7 +441,7 @@ decode OP default Unknown::unknown() 0x34: decode OPF{ format BasicOperate{ 0x01: fmovs({{ - Frd.uw = Frs2.uw; + Frds.uw = Frs2s.uw; //fsr.ftt = fsr.cexc = 0 Fsr &= ~(7 << 14); Fsr &= ~(0x1F); @@ -454,7 +454,7 @@ decode OP default Unknown::unknown() }}); 0x03: Trap::fmovq({{fault = new FpDisabled;}}); 0x05: fnegs({{ - Frd.uw = Frs2.uw ^ (1UL << 31); + Frds.uw = Frs2s.uw ^ (1UL << 31); //fsr.ftt = fsr.cexc = 0 Fsr &= ~(7 << 14); Fsr &= ~(0x1F); @@ -467,7 +467,7 @@ decode OP default Unknown::unknown() }}); 0x07: Trap::fnegq({{fault = new FpDisabled;}}); 0x09: fabss({{ - Frd.uw = ((1UL << 31) - 1) & Frs2.uw; + Frds.uw = ((1UL << 31) - 1) & Frs2s.uw; //fsr.ftt = fsr.cexc = 0 Fsr &= ~(7 << 14); Fsr &= ~(0x1F); @@ -479,55 +479,55 @@ decode OP default Unknown::unknown() Fsr &= ~(0x1F); }}); 0x0B: Trap::fabsq({{fault = new FpDisabled;}}); - 0x29: fsqrts({{Frd.sf = sqrt(Frs2.sf);}}); + 0x29: fsqrts({{Frds.sf = sqrt(Frs2s.sf);}}); 0x2A: fsqrtd({{Frd.df = sqrt(Frs2.df);}}); 0x2B: Trap::fsqrtq({{fault = new FpDisabled;}}); - 0x41: fadds({{Frd.sf = Frs1.sf + Frs2.sf;}}); + 0x41: fadds({{Frds.sf = Frs1s.sf + Frs2s.sf;}}); 0x42: faddd({{Frd.df = Frs1.df + Frs2.df;}}); 0x43: Trap::faddq({{fault = new FpDisabled;}}); - 0x45: fsubs({{Frd.sf = Frs1.sf - Frs2.sf;}}); + 0x45: fsubs({{Frds.sf = Frs1s.sf - Frs2s.sf;}}); 0x46: fsubd({{Frd.df = Frs1.df - Frs2.df;}}); 0x47: Trap::fsubq({{fault = new FpDisabled;}}); - 0x49: fmuls({{Frd.sf = Frs1.sf * Frs2.sf;}}); + 0x49: fmuls({{Frds.sf = Frs1s.sf * Frs2s.sf;}}); 0x4A: fmuld({{Frd.df = Frs1.df * Frs2.df;}}); 0x4B: Trap::fmulq({{fault = new FpDisabled;}}); - 0x4D: fdivs({{Frd.sf = Frs1.sf / Frs2.sf;}}); + 0x4D: fdivs({{Frds.sf = Frs1s.sf / Frs2s.sf;}}); 0x4E: fdivd({{Frd.df = Frs1.df / Frs2.df;}}); 0x4F: Trap::fdivq({{fault = new FpDisabled;}}); - 0x69: fsmuld({{Frd.df = Frs1.sf * Frs2.sf;}}); + 0x69: fsmuld({{Frd.df = Frs1s.sf * Frs2s.sf;}}); 0x6E: Trap::fdmulq({{fault = new FpDisabled;}}); 0x81: fstox({{ - Frd.df = (double)static_cast<int64_t>(Frs2.sf); + Frd.df = (double)static_cast<int64_t>(Frs2s.sf); }}); 0x82: fdtox({{ Frd.df = (double)static_cast<int64_t>(Frs2.df); }}); 0x83: Trap::fqtox({{fault = new FpDisabled;}}); 0x84: fxtos({{ - Frd.sf = static_cast<float>((int64_t)Frs2.df); + Frds.sf = static_cast<float>((int64_t)Frs2.df); }}); 0x88: fxtod({{ Frd.df = static_cast<double>((int64_t)Frs2.df); }}); 0x8C: Trap::fxtoq({{fault = new FpDisabled;}}); 0xC4: fitos({{ - Frd.sf = static_cast<float>((int32_t)Frs2.sf); + Frds.sf = static_cast<float>((int32_t)Frs2s.sf); }}); - 0xC6: fdtos({{Frd.sf = Frs2.df;}}); + 0xC6: fdtos({{Frds.sf = Frs2.df;}}); 0xC7: Trap::fqtos({{fault = new FpDisabled;}}); 0xC8: fitod({{ - Frd.df = static_cast<double>((int32_t)Frs2.sf); + Frd.df = static_cast<double>((int32_t)Frs2s.sf); }}); - 0xC9: fstod({{Frd.df = Frs2.sf;}}); + 0xC9: fstod({{Frd.df = Frs2s.sf;}}); 0xCB: Trap::fqtod({{fault = new FpDisabled;}}); 0xCC: Trap::fitoq({{fault = new FpDisabled;}}); 0xCD: Trap::fstoq({{fault = new FpDisabled;}}); 0xCE: Trap::fdtoq({{fault = new FpDisabled;}}); 0xD1: fstoi({{ - Frd.sf = (float)static_cast<int32_t>(Frs2.sf); + Frds.sf = (float)static_cast<int32_t>(Frs2s.sf); }}); 0xD2: fdtoi({{ - Frd.sf = (float)static_cast<int32_t>(Frs2.df); + Frds.sf = (float)static_cast<int32_t>(Frs2.df); }}); 0xD3: Trap::fqtoi({{fault = new FpDisabled;}}); default: Trap::fpop1({{fault = new FpDisabled;}}); @@ -620,7 +620,7 @@ decode OP default Unknown::unknown() 0x56: Trap::fpsub32({{fault = new IllegalInstruction;}}); 0x57: Trap::fpsub32s({{fault = new IllegalInstruction;}}); 0x60: BasicOperate::fzero({{Frd.df = 0;}}); - 0x61: BasicOperate::fzeros({{Frd.sf = 0;}}); + 0x61: BasicOperate::fzeros({{Frds.sf = 0;}}); 0x62: Trap::fnor({{fault = new IllegalInstruction;}}); 0x63: Trap::fnors({{fault = new IllegalInstruction;}}); 0x64: Trap::fandnot2({{fault = new IllegalInstruction;}}); @@ -629,7 +629,7 @@ decode OP default Unknown::unknown() Frd.df = (double)(~((uint64_t)Frs2.df)); }}); 0x67: BasicOperate::fnot2s({{ - Frd.sf = (float)(~((uint32_t)Frs2.sf)); + Frds.sf = (float)(~((uint32_t)Frs2s.sf)); }}); 0x68: Trap::fandnot1({{fault = new IllegalInstruction;}}); 0x69: Trap::fandnot1s({{fault = new IllegalInstruction;}}); @@ -637,7 +637,7 @@ decode OP default Unknown::unknown() Frd.df = (double)(~((uint64_t)Frs1.df)); }}); 0x6B: BasicOperate::fnot1s({{ - Frd.sf = (float)(~((uint32_t)Frs1.sf)); + Frds.sf = (float)(~((uint32_t)Frs1s.sf)); }}); 0x6C: Trap::fxor({{fault = new IllegalInstruction;}}); 0x6D: Trap::fxors({{fault = new IllegalInstruction;}}); @@ -820,92 +820,248 @@ decode OP default Unknown::unknown() } 0x3: decode OP3 { format Load { - 0x00: lduw({{Rd = Mem;}}, {{32}}); - 0x01: ldub({{Rd = Mem;}}, {{8}}); - 0x02: lduh({{Rd = Mem;}}, {{16}}); + 0x00: lduw({{Rd = Mem.uw;}}); + 0x01: ldub({{Rd = Mem.ub;}}); + 0x02: lduh({{Rd = Mem.uhw;}}); 0x03: ldd({{ - uint64_t val = Mem; + uint64_t val = Mem.udw; RdLow = val<31:0>; RdHigh = val<63:32>; - }}, {{64}}); + }}); } format Store { - 0x04: stw({{Mem = Rd.sw;}}, {{32}}); - 0x05: stb({{Mem = Rd.sb;}}, {{8}}); - 0x06: sth({{Mem = Rd.shw;}}, {{16}}); - 0x07: std({{Mem = RdLow<31:0> | (RdHigh<31:0> << 32);}}, {{64}}); + 0x04: stw({{Mem.uw = Rd.sw;}}); + 0x05: stb({{Mem.ub = Rd.sb;}}); + 0x06: sth({{Mem.uhw = Rd.shw;}}); + 0x07: std({{Mem.udw = RdLow<31:0> | (RdHigh<31:0> << 32);}}); } format Load { - 0x08: ldsw({{Rd = (int32_t)Mem;}}, {{32}}); - 0x09: ldsb({{Rd = (int8_t)Mem;}}, {{8}}); - 0x0A: ldsh({{Rd = (int16_t)Mem;}}, {{16}}); - 0x0B: ldx({{Rd = (int64_t)Mem;}}, {{64}}); + 0x08: ldsw({{Rd = (int32_t)Mem.sw;}}); + 0x09: ldsb({{Rd = (int8_t)Mem.sb;}}); + 0x0A: ldsh({{Rd = (int16_t)Mem.shw;}}); + 0x0B: ldx({{Rd = (int64_t)Mem.sdw;}}); 0x0D: ldstub({{ - Rd = Mem; - Mem = 0xFF; - }}, {{8}}); + Rd = Mem.ub; + Mem.ub = 0xFF; + }}); } - 0x0E: Store::stx({{Mem = Rd}}, {{64}}); - 0x0F: LoadStore::swap({{ - uint32_t temp = Rd; - Rd = Mem; - Mem = temp; - }}, {{32}}); + 0x0E: Store::stx({{Mem.udw = Rd}}); + 0x0F: LoadStore::swap( + {{*temp = Rd.uw; + Rd.uw = Mem.uw;}}, + {{Mem.uw = *temp;}}); format Load { - 0x10: lduwa({{Rd = Mem;}}, {{32}}); - 0x11: lduba({{Rd = Mem;}}, {{8}}); - 0x12: lduha({{Rd = Mem;}}, {{16}}); + 0x10: lduwa({{Rd = Mem.uw;}}); + 0x11: lduba({{Rd = Mem.ub;}}); + 0x12: lduha({{Rd = Mem.uhw;}}); 0x13: ldda({{ - uint64_t val = Mem; + uint64_t val = Mem.udw; RdLow = val<31:0>; RdHigh = val<63:32>; - }}, {{64}}); + }}); } format Store { - 0x14: stwa({{Mem = Rd;}}, {{32}}); - 0x15: stba({{Mem = Rd;}}, {{8}}); - 0x16: stha({{Mem = Rd;}}, {{16}}); - 0x17: stda({{Mem = RdLow<31:0> | RdHigh<31:0> << 32;}}, {{64}}); + 0x14: stwa({{Mem.uw = Rd;}}); + 0x15: stba({{Mem.ub = Rd;}}); + 0x16: stha({{Mem.uhw = Rd;}}); + 0x17: stda({{Mem.udw = RdLow<31:0> | RdHigh<31:0> << 32;}}); } format Load { - 0x18: ldswa({{Rd = (int32_t)Mem;}}, {{32}}); - 0x19: ldsba({{Rd = (int8_t)Mem;}}, {{8}}); - 0x1A: ldsha({{Rd = (int16_t)Mem;}}, {{16}}); - 0x1B: ldxa({{Rd = (int64_t)Mem;}}, {{64}}); + 0x18: ldswa({{Rd = (int32_t)Mem.sw;}}); + 0x19: ldsba({{Rd = (int8_t)Mem.sb;}}); + 0x1A: ldsha({{Rd = (int16_t)Mem.shw;}}); + 0x1B: ldxa({{Rd = (int64_t)Mem.sdw;}}); } - 0x1D: LoadStore::ldstuba({{ - Rd = Mem; - Mem = 0xFF; - }}, {{8}}); - 0x1E: Store::stxa({{Mem = Rd}}, {{64}}); - 0x1F: LoadStore::swapa({{ - uint32_t temp = Rd; - Rd = Mem; - Mem = temp; - }}, {{32}}); + 0x1D: LoadStore::ldstuba( + {{Rd = Mem.ub;}}, + {{Mem.ub = 0xFF}}); + 0x1E: Store::stxa({{Mem.udw = Rd}}); + 0x1F: LoadStore::swapa( + {{*temp = Rd.uw; + Rd.uw = Mem.uw;}}, + {{Mem.uw = *temp;}}); format Trap { - 0x20: Load::ldf({{Frd.uw = Mem;}}, {{32}}); + 0x20: Load::ldf({{Frd.uw = Mem.uw;}}); 0x21: decode X { - 0x0: Load::ldfsr({{Fsr = Mem<31:0> | Fsr<63:32>;}}, {{32}}); - 0x1: Load::ldxfsr({{Fsr = Mem;}}, {{64}}); + 0x0: Load::ldfsr({{Fsr = Mem.uw | Fsr<63:32>;}}); + 0x1: Load::ldxfsr({{Fsr = Mem.udw;}}); } 0x22: ldqf({{fault = new FpDisabled;}}); - 0x23: Load::lddf({{Frd.udw = Mem;}}, {{64}}); - 0x24: Store::stf({{Mem = Frd.uw;}}, {{32}}); + 0x23: Load::lddf({{Frd.udw = Mem.udw;}}); + 0x24: Store::stf({{Mem.uw = Frd.uw;}}); 0x25: decode X { - 0x0: Store::stfsr({{Mem = Fsr<31:0>;}}, {{32}}); - 0x1: Store::stxfsr({{Mem = Fsr;}}, {{64}}); + 0x0: Store::stfsr({{Mem.uw = Fsr<31:0>;}}); + 0x1: Store::stxfsr({{Mem.udw = Fsr;}}); } 0x26: stqf({{fault = new FpDisabled;}}); - 0x27: Store::stdf({{Mem = Frd.udw;}}, {{64}}); + 0x27: Store::stdf({{Mem.udw = Frd.udw;}}); 0x2D: Nop::prefetch({{ }}); - 0x30: Load::ldfa({{Frd.uw = Mem;}}, {{32}}); + 0x30: Load::ldfa({{Frd.uw = Mem.uw;}}); 0x32: ldqfa({{fault = new FpDisabled;}}); - 0x33: Load::lddfa({{Frd.udw = Mem;}}, {{64}}); - 0x34: Store::stfa({{Mem = Frd.uw;}}, {{32}}); + format LoadAlt { + 0x33: decode EXT_ASI { + //ASI_NUCLEUS + 0x04: FailUnimpl::lddfa_n(); + //ASI_NUCLEUS_LITTLE + 0x0C: FailUnimpl::lddfa_nl(); + //ASI_AS_IF_USER_PRIMARY + 0x10: FailUnimpl::lddfa_aiup(); + //ASI_AS_IF_USER_PRIMARY_LITTLE + 0x18: FailUnimpl::lddfa_aiupl(); + //ASI_AS_IF_USER_SECONDARY + 0x11: FailUnimpl::lddfa_aius(); + //ASI_AS_IF_USER_SECONDARY_LITTLE + 0x19: FailUnimpl::lddfa_aiusl(); + //ASI_REAL + 0x14: FailUnimpl::lddfa_real(); + //ASI_REAL_LITTLE + 0x1C: FailUnimpl::lddfa_real_l(); + //ASI_REAL_IO + 0x15: FailUnimpl::lddfa_real_io(); + //ASI_REAL_IO_LITTLE + 0x1D: FailUnimpl::lddfa_real_io_l(); + //ASI_PRIMARY + 0x80: FailUnimpl::lddfa_p(); + //ASI_PRIMARY_LITTLE + 0x88: FailUnimpl::lddfa_pl(); + //ASI_SECONDARY + 0x81: FailUnimpl::lddfa_s(); + //ASI_SECONDARY_LITTLE + 0x89: FailUnimpl::lddfa_sl(); + //ASI_PRIMARY_NO_FAULT + 0x82: FailUnimpl::lddfa_pnf(); + //ASI_PRIMARY_NO_FAULT_LITTLE + 0x8A: FailUnimpl::lddfa_pnfl(); + //ASI_SECONDARY_NO_FAULT + 0x83: FailUnimpl::lddfa_snf(); + //ASI_SECONDARY_NO_FAULT_LITTLE + 0x8B: FailUnimpl::lddfa_snfl(); + + format BlockLoad { + // LDBLOCKF + //ASI_BLOCK_AS_IF_USER_PRIMARY + 0x16: FailUnimpl::ldblockf_aiup(); + //ASI_BLOCK_AS_IF_USER_SECONDARY + 0x17: FailUnimpl::ldblockf_aius(); + //ASI_BLOCK_AS_IF_USER_PRIMARY_LITTLE + 0x1E: FailUnimpl::ldblockf_aiupl(); + //ASI_BLOCK_AS_IF_USER_SECONDARY_LITTLE + 0x1F: FailUnimpl::ldblockf_aiusl(); + //ASI_BLOCK_PRIMARY + 0xF0: ldblockf_p({{Frd_N.udw = Mem.udw;}}); + //ASI_BLOCK_SECONDARY + 0xF1: FailUnimpl::ldblockf_s(); + //ASI_BLOCK_PRIMARY_LITTLE + 0xF8: FailUnimpl::ldblockf_pl(); + //ASI_BLOCK_SECONDARY_LITTLE + 0xF9: FailUnimpl::ldblockf_sl(); + } + + //LDSHORTF + //ASI_FL8_PRIMARY + 0xD0: FailUnimpl::ldshortf_8p(); + //ASI_FL8_SECONDARY + 0xD1: FailUnimpl::ldshortf_8s(); + //ASI_FL8_PRIMARY_LITTLE + 0xD8: FailUnimpl::ldshortf_8pl(); + //ASI_FL8_SECONDARY_LITTLE + 0xD9: FailUnimpl::ldshortf_8sl(); + //ASI_FL16_PRIMARY + 0xD2: FailUnimpl::ldshortf_16p(); + //ASI_FL16_SECONDARY + 0xD3: FailUnimpl::ldshortf_16s(); + //ASI_FL16_PRIMARY_LITTLE + 0xDA: FailUnimpl::ldshortf_16pl(); + //ASI_FL16_SECONDARY_LITTLE + 0xDB: FailUnimpl::ldshortf_16sl(); + //Not an ASI which is legal with lddfa + default: Trap::lddfa_bad_asi( + {{fault = new DataAccessException;}}); + } + } + 0x34: Store::stfa({{Mem.uw = Frd.uw;}}); 0x36: stqfa({{fault = new FpDisabled;}}); - //XXX need to work in the ASI thing - 0x37: Store::stdfa({{Mem = Frd.udw;}}, {{64}}); + format StoreAlt { + 0x37: decode EXT_ASI { + //ASI_NUCLEUS + 0x04: FailUnimpl::stdfa_n(); + //ASI_NUCLEUS_LITTLE + 0x0C: FailUnimpl::stdfa_nl(); + //ASI_AS_IF_USER_PRIMARY + 0x10: FailUnimpl::stdfa_aiup(); + //ASI_AS_IF_USER_PRIMARY_LITTLE + 0x18: FailUnimpl::stdfa_aiupl(); + //ASI_AS_IF_USER_SECONDARY + 0x11: FailUnimpl::stdfa_aius(); + //ASI_AS_IF_USER_SECONDARY_LITTLE + 0x19: FailUnimpl::stdfa_aiusl(); + //ASI_REAL + 0x14: FailUnimpl::stdfa_real(); + //ASI_REAL_LITTLE + 0x1C: FailUnimpl::stdfa_real_l(); + //ASI_REAL_IO + 0x15: FailUnimpl::stdfa_real_io(); + //ASI_REAL_IO_LITTLE + 0x1D: FailUnimpl::stdfa_real_io_l(); + //ASI_PRIMARY + 0x80: FailUnimpl::stdfa_p(); + //ASI_PRIMARY_LITTLE + 0x88: FailUnimpl::stdfa_pl(); + //ASI_SECONDARY + 0x81: FailUnimpl::stdfa_s(); + //ASI_SECONDARY_LITTLE + 0x89: FailUnimpl::stdfa_sl(); + //ASI_PRIMARY_NO_FAULT + 0x82: FailUnimpl::stdfa_pnf(); + //ASI_PRIMARY_NO_FAULT_LITTLE + 0x8A: FailUnimpl::stdfa_pnfl(); + //ASI_SECONDARY_NO_FAULT + 0x83: FailUnimpl::stdfa_snf(); + //ASI_SECONDARY_NO_FAULT_LITTLE + 0x8B: FailUnimpl::stdfa_snfl(); + + format BlockStore { + // STBLOCKF + //ASI_BLOCK_AS_IF_USER_PRIMARY + 0x16: FailUnimpl::stblockf_aiup(); + //ASI_BLOCK_AS_IF_USER_SECONDARY + 0x17: FailUnimpl::stblockf_aius(); + //ASI_BLOCK_AS_IF_USER_PRIMARY_LITTLE + 0x1E: FailUnimpl::stblockf_aiupl(); + //ASI_BLOCK_AS_IF_USER_SECONDARY_LITTLE + 0x1F: FailUnimpl::stblockf_aiusl(); + //ASI_BLOCK_PRIMARY + 0xF0: stblockf_p({{Mem.udw = Frd_N.udw;}}); + //ASI_BLOCK_SECONDARY + 0xF1: FailUnimpl::stblockf_s(); + //ASI_BLOCK_PRIMARY_LITTLE + 0xF8: FailUnimpl::stblockf_pl(); + //ASI_BLOCK_SECONDARY_LITTLE + 0xF9: FailUnimpl::stblockf_sl(); + } + + //STSHORTF + //ASI_FL8_PRIMARY + 0xD0: FailUnimpl::stshortf_8p(); + //ASI_FL8_SECONDARY + 0xD1: FailUnimpl::stshortf_8s(); + //ASI_FL8_PRIMARY_LITTLE + 0xD8: FailUnimpl::stshortf_8pl(); + //ASI_FL8_SECONDARY_LITTLE + 0xD9: FailUnimpl::stshortf_8sl(); + //ASI_FL16_PRIMARY + 0xD2: FailUnimpl::stshortf_16p(); + //ASI_FL16_SECONDARY + 0xD3: FailUnimpl::stshortf_16s(); + //ASI_FL16_PRIMARY_LITTLE + 0xDA: FailUnimpl::stshortf_16pl(); + //ASI_FL16_SECONDARY_LITTLE + 0xDB: FailUnimpl::stshortf_16sl(); + //Not an ASI which is legal with lddfa + default: Trap::stdfa_bad_asi( + {{fault = new DataAccessException;}}); + } + } 0x3C: Cas::casa({{ uint64_t val = Mem.uw; if(Rs2.uw == val) diff --git a/src/arch/sparc/isa/formats.isa b/src/arch/sparc/isa/formats.isa deleted file mode 100644 index 17d68061b..000000000 --- a/src/arch/sparc/isa/formats.isa +++ /dev/null @@ -1,28 +0,0 @@ -//Include the basic format -//Templates from this format are used later -##include "formats/basic.isa" - -//Include the noop format -##include "formats/nop.isa" - -//Include the integerOp and integerOpCc format -##include "formats/integerop.isa" - -//Include the memory format -##include "formats/mem.isa" - -//Include the compare and swap format -##include "formats/cas.isa" - -//Include the trap format -##include "formats/trap.isa" - -//Include the "unknown" format -##include "formats/unknown.isa" - -//Include the priveleged mode format -##include "formats/priv.isa" - -//Include the branch format -##include "formats/branch.isa" - diff --git a/src/arch/sparc/isa/formats/basic.isa b/src/arch/sparc/isa/formats/basic.isa index 0a47a7ffe..a4c05387b 100644 --- a/src/arch/sparc/isa/formats/basic.isa +++ b/src/arch/sparc/isa/formats/basic.isa @@ -33,6 +33,14 @@ def template BasicExecDeclare {{ Fault execute(%(CPU_exec_context)s *, Trace::InstRecord *) const; }}; +// Definitions of execute methods that panic. +def template BasicExecPanic {{ + Fault execute(%(CPU_exec_context)s *, Trace::InstRecord *) const + { + panic("Execute method called when it shouldn't!"); + } +}}; + // Basic instruction class declaration template. def template BasicDeclare {{ /** @@ -42,14 +50,14 @@ def template BasicDeclare {{ { public: // Constructor. - %(class_name)s(MachInst machInst); + %(class_name)s(ExtMachInst machInst); %(BasicExecDeclare)s }; }}; // Basic instruction class constructor template. def template BasicConstructor {{ - inline %(class_name)s::%(class_name)s(MachInst machInst) + inline %(class_name)s::%(class_name)s(ExtMachInst machInst) : %(base_class)s("%(mnemonic)s", machInst, %(op_class)s) { %(constructor)s; @@ -80,6 +88,11 @@ def template BasicDecode {{ return new %(class_name)s(machInst); }}; +// Basic decode template, passing mnemonic in as string arg to constructor. +def template BasicDecodeWithMnemonic {{ + return new %(class_name)s("%(mnemonic)s", machInst); +}}; + // The most basic instruction format... used only for a few misc. insts def format BasicOperate(code, *flags) {{ iop = InstObjParams(name, Name, 'SparcStaticInst', diff --git a/src/arch/sparc/isa/formats/branch.isa b/src/arch/sparc/isa/formats/branch.isa index 2c206354b..5fb7ade2d 100644 --- a/src/arch/sparc/isa/formats/branch.isa +++ b/src/arch/sparc/isa/formats/branch.isa @@ -80,7 +80,7 @@ output header {{ OpClass __opClass) : BranchDisp(mnem, _machInst, __opClass) { - disp = sign_ext(_machInst << 2, bits + 2); + disp = sext<bits + 2>((_machInst & mask(bits)) << 2); } }; @@ -95,7 +95,7 @@ output header {{ OpClass __opClass) : BranchDisp(mnem, _machInst, __opClass) { - disp = sign_ext((D16HI << 16) | (D16LO << 2), 18); + disp = sext<18>((D16HI << 16) | (D16LO << 2)); } }; @@ -108,7 +108,7 @@ output header {{ protected: // Constructor BranchImm13(const char *mnem, MachInst _machInst, OpClass __opClass) : - Branch(mnem, _machInst, __opClass), imm(sign_ext(SIMM13, 13)) + Branch(mnem, _machInst, __opClass), imm(sext<13>(SIMM13)) { } diff --git a/src/arch/sparc/isa/formats/formats.isa b/src/arch/sparc/isa/formats/formats.isa new file mode 100644 index 000000000..5b81a1ab1 --- /dev/null +++ b/src/arch/sparc/isa/formats/formats.isa @@ -0,0 +1,62 @@ +// Copyright (c) 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 the basic format +//Templates from this format are used later +##include "basic.isa" + +//Include base classes for microcoding instructions +##include "micro.isa" + +//Include the noop format +##include "nop.isa" + +//Include the integerOp and integerOpCc format +##include "integerop.isa" + +//Include the memory formats +##include "mem/mem.isa" + +//Include the compare and swap format +##include "cas.isa" + +//Include the trap format +##include "trap.isa" + +//Include the unimplemented format +##include "unimp.isa" + +//Include the "unknown" format +##include "unknown.isa" + +//Include the priveleged mode format +##include "priv.isa" + +//Include the branch format +##include "branch.isa" + diff --git a/src/arch/sparc/isa/formats/integerop.isa b/src/arch/sparc/isa/formats/integerop.isa index 83c7e6958..4f8ebebcc 100644 --- a/src/arch/sparc/isa/formats/integerop.isa +++ b/src/arch/sparc/isa/formats/integerop.isa @@ -87,7 +87,7 @@ output header {{ OpClass __opClass) : IntOpImm(mnem, _machInst, __opClass) { - imm = sign_ext(SIMM10, 10); + imm = sext<10>(SIMM10); } }; @@ -102,7 +102,7 @@ output header {{ OpClass __opClass) : IntOpImm(mnem, _machInst, __opClass) { - imm = sign_ext(SIMM11, 11); + imm = sext<11>(SIMM11); } }; @@ -117,7 +117,7 @@ output header {{ OpClass __opClass) : IntOpImm(mnem, _machInst, __opClass) { - imm = sign_ext(SIMM13, 13); + imm = sext<13>(SIMM13); } }; @@ -264,13 +264,13 @@ let {{ (usesImm, code, immCode, rString, iString) = splitOutImm(code) iop = InstObjParams(name, Name, 'IntOp', code, - opt_flags, ("cc_code", ccCode)) + opt_flags, {"cc_code": ccCode}) header_output = BasicDeclare.subst(iop) decoder_output = BasicConstructor.subst(iop) exec_output = IntOpExecute.subst(iop) if usesImm: imm_iop = InstObjParams(name, Name + 'Imm', 'IntOpImm' + iString, - immCode, opt_flags, ("cc_code", ccCode)) + immCode, opt_flags, {"cc_code": ccCode}) header_output += BasicDeclare.subst(imm_iop) decoder_output += BasicConstructor.subst(imm_iop) exec_output += IntOpExecute.subst(imm_iop) @@ -341,7 +341,7 @@ def format IntOpCcRes(code, *opt_flags) {{ def format SetHi(code, *opt_flags) {{ iop = InstObjParams(name, Name, 'SetHi', - code, opt_flags, ("cc_code", '')) + code, opt_flags, {"cc_code": ''}) header_output = BasicDeclare.subst(iop) decoder_output = BasicConstructor.subst(iop) exec_output = IntOpExecute.subst(iop) diff --git a/src/arch/sparc/isa/formats/mem.isa b/src/arch/sparc/isa/formats/mem/basicmem.isa index 9011c1fc6..c13194d0f 100644 --- a/src/arch/sparc/isa/formats/mem.isa +++ b/src/arch/sparc/isa/formats/mem/basicmem.isa @@ -1,3 +1,32 @@ +// Copyright (c) 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: Ali Saidi +// Gabe Black + //////////////////////////////////////////////////////////////////// // // Mem instructions @@ -30,15 +59,13 @@ output header {{ // Constructor MemImm(const char *mnem, ExtMachInst _machInst, OpClass __opClass) : - Mem(mnem, _machInst, __opClass) - { - imm = sign_ext(SIMM13, 13); - } + Mem(mnem, _machInst, __opClass), imm(sext<13>(SIMM13)) + {} std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const; - int32_t imm; + const int32_t imm; }; }}; @@ -99,73 +126,69 @@ output decoder {{ } }}; -def template MemExecute {{ - Fault %(class_name)s::execute(%(CPU_exec_context)s *xc, - Trace::InstRecord *traceData) const +def template MemDeclare {{ + /** + * Static instruction class for "%(mnemonic)s". + */ + class %(class_name)s : public %(base_class)s { - Fault fault = NoFault; - Addr EA; - %(op_decl)s; - %(op_rd)s; - %(ea_code)s; - DPRINTF(Sparc, "The address is 0x%x\n", EA); - %(load)s; - %(code)s; - - if(fault == NoFault) - { - %(store)s; - //Write the resulting state to the execution context - %(op_wb)s; - } + public: - return fault; - } + /// Constructor. + %(class_name)s(ExtMachInst machInst); + + %(BasicExecDeclare)s + + %(InitiateAccDeclare)s + + %(CompleteAccDeclare)s + }; }}; let {{ - # Leave memAccessFlags at 0 for now - loadString = "xc->read(EA, (uint%(width)s_t&)Mem, 0);" - storeString = "uint64_t write_result = 0; \ - xc->write((uint%(width)s_t)Mem, EA, 0, &write_result);" - - def doMemFormat(code, load, store, name, Name, opt_flags): + def doMemFormat(code, execute, faultCode, name, Name, opt_flags): addrCalcReg = 'EA = Rs1 + Rs2;' addrCalcImm = 'EA = Rs1 + imm;' iop = InstObjParams(name, Name, 'Mem', code, - opt_flags, ("ea_code", addrCalcReg), - ("load", load), ("store", store)) - iop_imm = InstObjParams(name, Name + 'Imm', 'MemImm', code, - opt_flags, ("ea_code", addrCalcImm), - ("load", load), ("store", store)) - header_output = BasicDeclare.subst(iop) + BasicDeclare.subst(iop_imm) + opt_flags, {"fault_check": faultCode, "ea_code": addrCalcReg}) + iop_imm = InstObjParams(name, Name + "Imm", 'MemImm', code, + opt_flags, {"fault_check": faultCode, "ea_code": addrCalcImm}) + header_output = MemDeclare.subst(iop) + MemDeclare.subst(iop_imm) decoder_output = BasicConstructor.subst(iop) + BasicConstructor.subst(iop_imm) decode_block = ROrImmDecode.subst(iop) - exec_output = MemExecute.subst(iop) + MemExecute.subst(iop_imm) + exec_output = doSplitExecute(code, addrCalcReg, addrCalcImm, execute, + faultCode, name, name + "Imm", Name, Name + "Imm", opt_flags) return (header_output, decoder_output, exec_output, decode_block) }}; -def format Load(code, width, *opt_flags) {{ +def format LoadAlt(code, *opt_flags) {{ (header_output, decoder_output, exec_output, - decode_block) = doMemFormat(code, - loadString % {"width":width}, '', name, Name, opt_flags) + decode_block) = doMemFormat(code, LoadExecute, + AlternateAsiPrivFaultCheck, name, Name, opt_flags) }}; -def format Store(code, width, *opt_flags) {{ +def format StoreAlt(code, *opt_flags) {{ (header_output, decoder_output, exec_output, - decode_block) = doMemFormat(code, '', - storeString % {"width":width}, name, Name, opt_flags) + decode_block) = doMemFormat(code, StoreExecute, + AlternateAsiPrivFaultCheck, name, Name, opt_flags) +}}; + +def format Load(code, *opt_flags) {{ + (header_output, + decoder_output, + exec_output, + decode_block) = doMemFormat(code, + LoadExecute, '', name, Name, opt_flags) }}; -def format LoadStore(code, width, *opt_flags) {{ +def format Store(code, *opt_flags) {{ (header_output, decoder_output, exec_output, decode_block) = doMemFormat(code, - loadString % {"width":width}, storeString % {"width":width}, - name, Name, opt_flags) + StoreExecute, '', name, Name, opt_flags) }}; diff --git a/src/arch/sparc/isa/formats/mem/blockmem.isa b/src/arch/sparc/isa/formats/mem/blockmem.isa new file mode 100644 index 000000000..93ad1b2b8 --- /dev/null +++ b/src/arch/sparc/isa/formats/mem/blockmem.isa @@ -0,0 +1,337 @@ +// Copyright (c) 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: Ali Saidi +// Gabe Black + +//////////////////////////////////////////////////////////////////// +// +// Block Memory instructions +// + +output header {{ + + class BlockMem : public SparcMacroInst + { + protected: + + // Constructor + // We make the assumption that all block memory operations + // Will take 8 instructions to execute + BlockMem(const char *mnem, ExtMachInst _machInst) : + SparcMacroInst(mnem, _machInst, No_OpClass, 8) + {} + }; + + class BlockMemImm : public BlockMem + { + protected: + + // Constructor + BlockMemImm(const char *mnem, ExtMachInst _machInst) : + BlockMem(mnem, _machInst) + {} + }; + + class BlockMemMicro : public SparcDelayedMicroInst + { + protected: + + // Constructor + BlockMemMicro(const char *mnem, ExtMachInst _machInst, + OpClass __opClass, int8_t _offset) : + SparcDelayedMicroInst(mnem, _machInst, __opClass), + offset(_offset) + {} + + std::string generateDisassembly(Addr pc, + const SymbolTable *symtab) const; + + const int8_t offset; + }; + + class BlockMemImmMicro : public BlockMemMicro + { + protected: + + // Constructor + BlockMemImmMicro(const char *mnem, ExtMachInst _machInst, + OpClass __opClass, int8_t _offset) : + BlockMemMicro(mnem, _machInst, __opClass, _offset), + imm(sext<13>(SIMM13)) + {} + + std::string generateDisassembly(Addr pc, + const SymbolTable *symtab) const; + + const int32_t imm; + }; +}}; + +output decoder {{ + std::string BlockMemMicro::generateDisassembly(Addr pc, + const SymbolTable *symtab) const + { + std::stringstream response; + bool load = flags[IsLoad]; + bool save = flags[IsStore]; + + printMnemonic(response, mnemonic); + if(save) + { + printReg(response, _srcRegIdx[0]); + ccprintf(response, ", "); + } + ccprintf(response, "[ "); + printReg(response, _srcRegIdx[!save ? 0 : 1]); + ccprintf(response, " + "); + printReg(response, _srcRegIdx[!save ? 1 : 2]); + ccprintf(response, " ]"); + if(load) + { + ccprintf(response, ", "); + printReg(response, _destRegIdx[0]); + } + + return response.str(); + } + + std::string BlockMemImmMicro::generateDisassembly(Addr pc, + const SymbolTable *symtab) const + { + std::stringstream response; + bool load = flags[IsLoad]; + bool save = flags[IsStore]; + + printMnemonic(response, mnemonic); + if(save) + { + printReg(response, _srcRegIdx[1]); + ccprintf(response, ", "); + } + ccprintf(response, "[ "); + printReg(response, _srcRegIdx[0]); + if(imm >= 0) + ccprintf(response, " + 0x%x ]", imm); + else + ccprintf(response, " + -0x%x ]", -imm); + if(load) + { + ccprintf(response, ", "); + printReg(response, _destRegIdx[0]); + } + + return response.str(); + } + +}}; + +def template BlockMemDeclare {{ + /** + * Static instruction class for a block memory operation + */ + class %(class_name)s : public %(base_class)s + { + public: + //Constructor + %(class_name)s(ExtMachInst machInst); + + protected: + class %(class_name)s_0 : public %(base_class)sMicro + { + public: + //Constructor + %(class_name)s_0(ExtMachInst machInst); + %(BasicExecDeclare)s + %(InitiateAccDeclare)s + %(CompleteAccDeclare)s + }; + + class %(class_name)s_1 : public %(base_class)sMicro + { + public: + //Constructor + %(class_name)s_1(ExtMachInst machInst); + %(BasicExecDeclare)s + %(InitiateAccDeclare)s + %(CompleteAccDeclare)s + }; + + class %(class_name)s_2 : public %(base_class)sMicro + { + public: + //Constructor + %(class_name)s_2(ExtMachInst machInst); + %(BasicExecDeclare)s + %(InitiateAccDeclare)s + %(CompleteAccDeclare)s + }; + + class %(class_name)s_3 : public %(base_class)sMicro + { + public: + //Constructor + %(class_name)s_3(ExtMachInst machInst); + %(BasicExecDeclare)s + %(InitiateAccDeclare)s + %(CompleteAccDeclare)s + }; + + class %(class_name)s_4 : public %(base_class)sMicro + { + public: + //Constructor + %(class_name)s_4(ExtMachInst machInst); + %(BasicExecDeclare)s + %(InitiateAccDeclare)s + %(CompleteAccDeclare)s + }; + + class %(class_name)s_5 : public %(base_class)sMicro + { + public: + //Constructor + %(class_name)s_5(ExtMachInst machInst); + %(BasicExecDeclare)s + %(InitiateAccDeclare)s + %(CompleteAccDeclare)s + }; + + class %(class_name)s_6 : public %(base_class)sMicro + { + public: + //Constructor + %(class_name)s_6(ExtMachInst machInst); + %(BasicExecDeclare)s + %(InitiateAccDeclare)s + %(CompleteAccDeclare)s + }; + + class %(class_name)s_7 : public %(base_class)sMicro + { + public: + //Constructor + %(class_name)s_7(ExtMachInst machInst); + %(BasicExecDeclare)s + %(InitiateAccDeclare)s + %(CompleteAccDeclare)s + }; + }; +}}; + +// Basic instruction class constructor template. +def template BlockMemConstructor {{ + inline %(class_name)s::%(class_name)s(ExtMachInst machInst) + : %(base_class)s("%(mnemonic)s", machInst) + { + %(constructor)s; + microOps[0] = new %(class_name)s_0(machInst); + microOps[1] = new %(class_name)s_1(machInst); + microOps[2] = new %(class_name)s_2(machInst); + microOps[3] = new %(class_name)s_3(machInst); + microOps[4] = new %(class_name)s_4(machInst); + microOps[5] = new %(class_name)s_5(machInst); + microOps[6] = new %(class_name)s_6(machInst); + microOps[7] = new %(class_name)s_7(machInst); + } +}}; + +def template BlockMemMicroConstructor {{ + inline %(class_name)s:: + %(class_name)s_%(micro_pc)s:: + %(class_name)s_%(micro_pc)s(ExtMachInst machInst) : + %(base_class)sMicro("%(mnemonic)s[%(micro_pc)s]", + machInst, %(op_class)s, %(micro_pc)s * 8) + { + %(constructor)s; + %(set_flags)s; + } +}}; + +let {{ + + def doBlockMemFormat(code, faultCode, execute, name, Name, opt_flags): + # XXX Need to take care of pstate.hpriv as well. The lower ASIs + # are split into ones that are available in priv and hpriv, and + # those that are only available in hpriv + addrCalcReg = 'EA = Rs1 + Rs2 + offset;' + addrCalcImm = 'EA = Rs1 + imm + offset;' + iop = InstObjParams(name, Name, 'BlockMem', code, opt_flags) + iop_imm = InstObjParams(name, Name + 'Imm', 'BlockMemImm', code, opt_flags) + header_output = BlockMemDeclare.subst(iop) + BlockMemDeclare.subst(iop_imm) + decoder_output = BlockMemConstructor.subst(iop) + BlockMemConstructor.subst(iop_imm) + decode_block = ROrImmDecode.subst(iop) + matcher = re.compile(r'Frd_N') + exec_output = '' + for microPc in range(8): + flag_code = '' + if (microPc == 7): + flag_code = "flags[IsLastMicroOp] = true;" + pcedCode = matcher.sub("Frd_%d" % microPc, code) + iop = InstObjParams(name, Name, 'BlockMem', pcedCode, + opt_flags, {"ea_code": addrCalcReg, + "fault_check": faultCode, "micro_pc": microPc, + "set_flags": flag_code}) + iop_imm = InstObjParams(name, Name + 'Imm', 'BlockMemImm', pcedCode, + opt_flags, {"ea_code": addrCalcImm, + "fault_check": faultCode, "micro_pc": microPc, + "set_flags": flag_code}) + decoder_output += BlockMemMicroConstructor.subst(iop) + decoder_output += BlockMemMicroConstructor.subst(iop_imm) + exec_output += doSplitExecute( + pcedCode, addrCalcReg, addrCalcImm, execute, faultCode, + makeMicroName(name, microPc), + makeMicroName(name + "Imm", microPc), + makeMicroName(Name, microPc), + makeMicroName(Name + "Imm", microPc), + opt_flags); + faultCode = '' + return (header_output, decoder_output, exec_output, decode_block) +}}; + +def format BlockLoad(code, *opt_flags) {{ + # We need to make sure to check the highest priority fault last. + # That way, if other faults have been detected, they'll be overwritten + # rather than the other way around. + faultCode = AlternateASIPrivFaultCheck + BlockAlignmentFaultCheck + (header_output, + decoder_output, + exec_output, + decode_block) = doBlockMemFormat(code, faultCode, + LoadExecute, name, Name, opt_flags) +}}; + +def format BlockStore(code, *opt_flags) {{ + # We need to make sure to check the highest priority fault last. + # That way, if other faults have been detected, they'll be overwritten + # rather than the other way around. + faultCode = AlternateASIPrivFaultCheck + BlockAlignmentFaultCheck + (header_output, + decoder_output, + exec_output, + decode_block) = doBlockMemFormat(code, faultCode, + StoreExecute, name, Name, opt_flags) +}}; diff --git a/src/arch/sparc/isa/formats/mem/mem.isa b/src/arch/sparc/isa/formats/mem/mem.isa new file mode 100644 index 000000000..20a22c45d --- /dev/null +++ b/src/arch/sparc/isa/formats/mem/mem.isa @@ -0,0 +1,45 @@ +// Copyright (c) 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: Ali Saidi +// Gabe Black + +//////////////////////////////////////////////////////////////////// +// +// Mem formats +// + +//Include mem utility templates and functions +##include "util.isa" + +//Include the basic memory format +##include "basicmem.isa" + +//Include the block memory format +##include "blockmem.isa" + +//Include the load/store memory format +##include "loadstore.isa" diff --git a/src/arch/sparc/isa/formats/mem/util.isa b/src/arch/sparc/isa/formats/mem/util.isa new file mode 100644 index 000000000..241a25d17 --- /dev/null +++ b/src/arch/sparc/isa/formats/mem/util.isa @@ -0,0 +1,226 @@ +// Copyright (c) 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: Ali Saidi +// Gabe Black +// Steve Reinhardt + +//////////////////////////////////////////////////////////////////// +// +// Mem utility templates and functions +// + +//This template provides the execute functions for a load +def template LoadExecute {{ + Fault %(class_name)s::execute(%(CPU_exec_context)s *xc, + Trace::InstRecord *traceData) const + { + Fault fault = NoFault; + Addr EA; + %(op_decl)s; + %(op_rd)s; + %(ea_code)s; + DPRINTF(Sparc, "The address is 0x%x\n", EA); + %(fault_check)s; + if(fault == NoFault) + { + fault = xc->read(EA, (uint%(mem_acc_size)s_t&)Mem, 0); + } + if(fault == NoFault) + { + %(code)s; + } + if(fault == NoFault) + { + //Write the resulting state to the execution context + %(op_wb)s; + } + + return fault; + } + + Fault %(class_name)s::initiateAcc(%(CPU_exec_context)s * xc, + Trace::InstRecord * traceData) const + { + Fault fault = NoFault; + Addr EA; + uint%(mem_acc_size)s_t Mem; + %(ea_decl)s; + %(ea_rd)s; + %(ea_code)s; + %(fault_check)s; + if(fault == NoFault) + { + fault = xc->read(EA, (uint%(mem_acc_size)s_t&)Mem, 0); + } + return fault; + } + + Fault %(class_name)s::completeAcc(PacketPtr pkt, %(CPU_exec_context)s * xc, + Trace::InstRecord * traceData) const + { + Fault fault = NoFault; + %(code_decl)s; + %(code_rd)s; + Mem = pkt->get<typeof(Mem)>(); + %(code)s; + if(fault == NoFault) + { + %(code_wb)s; + } + return fault; + } +}}; + +//This template provides the execute functions for a store +def template StoreExecute {{ + Fault %(class_name)s::execute(%(CPU_exec_context)s *xc, + Trace::InstRecord *traceData) const + { + Fault fault = NoFault; + uint64_t write_result = 0; + Addr EA; + %(op_decl)s; + %(op_rd)s; + %(ea_code)s; + DPRINTF(Sparc, "The address is 0x%x\n", EA); + %(fault_check)s; + if(fault == NoFault) + { + %(code)s; + } + if(fault == NoFault) + { + fault = xc->write((uint%(mem_acc_size)s_t)Mem, EA, 0, &write_result); + } + if(fault == NoFault) + { + //Write the resulting state to the execution context + %(op_wb)s; + } + + return fault; + } + + Fault %(class_name)s::initiateAcc(%(CPU_exec_context)s * xc, + Trace::InstRecord * traceData) const + { + Fault fault = NoFault; + uint64_t write_result = 0; + Addr EA; + %(op_decl)s; + %(op_rd)s; + %(ea_code)s; + DPRINTF(Sparc, "The address is 0x%x\n", EA); + %(fault_check)s; + if(fault == NoFault) + { + %(code)s; + } + if(fault == NoFault) + { + fault = xc->write((uint%(mem_acc_size)s_t)Mem, EA, 0, &write_result); + } + if(fault == NoFault) + { + //Write the resulting state to the execution context + %(op_wb)s; + } + return fault; + } + + Fault %(class_name)s::completeAcc(PacketPtr, %(CPU_exec_context)s * xc, + Trace::InstRecord * traceData) const + { + return NoFault; + } +}}; + +//This delcares the initiateAcc function in memory operations +def template InitiateAccDeclare {{ + Fault initiateAcc(%(CPU_exec_context)s *, Trace::InstRecord *) const; +}}; + +//This declares the completeAcc function in memory operations +def template CompleteAccDeclare {{ + Fault completeAcc(PacketPtr, %(CPU_exec_context)s *, Trace::InstRecord *) const; +}}; + +//Here are some code snippets which check for various fault conditions +let {{ + # The LSB can be zero, since it's really the MSB in doubles and quads + # and we're dealing with doubles + BlockAlignmentFaultCheck = ''' + if(RD & 0xe) + fault = new IllegalInstruction; + else if(EA & 0x3f) + fault = new MemAddressNotAligned; + ''' + # XXX Need to take care of pstate.hpriv as well. The lower ASIs + # are split into ones that are available in priv and hpriv, and + # those that are only available in hpriv + AlternateASIPrivFaultCheck = ''' + if(bits(Pstate,2,2) == 0 && (EXT_ASI & 0x80) == 0) + fault = new PrivilegedAction; + else if(AsiIsAsIfUser((ASI)EXT_ASI) && !bits(Pstate,2,2)) + fault = new PrivilegedAction; + ''' + +}}; + +//A simple function to generate the name of the macro op of a certain +//instruction at a certain micropc +let {{ + def makeMicroName(name, microPc): + return name + "::" + name + "_" + str(microPc) +}}; + +//This function properly generates the execute functions for one of the +//templates above. This is needed because in one case, ea computation, +//fault checks and the actual code all occur in the same function, +//and in the other they're distributed across two. Also note that for +//execute functions, the name of the base class doesn't matter. +let {{ + def doSplitExecute(code, eaRegCode, eaImmCode, execute, + faultCode, nameReg, nameImm, NameReg, NameImm, opt_flags): + codeIop = InstObjParams(nameReg, NameReg, '', code, opt_flags) + executeCode = '' + for (eaCode, name, Name) in ( + (eaRegCode, nameReg, NameReg), + (eaImmCode, nameImm, NameImm)): + eaIop = InstObjParams(name, Name, '', eaCode, + opt_flags, {"fault_check": faultCode}) + iop = InstObjParams(name, Name, '', code, opt_flags, + {"fault_check": faultCode, "ea_code" : eaCode}) + (iop.ea_decl, + iop.ea_rd, + iop.ea_wb) = (eaIop.op_decl, eaIop.op_rd, eaIop.op_wb) + (iop.code_decl, + iop.code_rd, + iop.code_wb) = (codeIop.op_decl, codeIop.op_rd, codeIop.op_wb) + executeCode += execute.subst(iop) + return executeCode +}}; diff --git a/src/arch/sparc/isa/formats/micro.isa b/src/arch/sparc/isa/formats/micro.isa new file mode 100644 index 000000000..82d7fb4cb --- /dev/null +++ b/src/arch/sparc/isa/formats/micro.isa @@ -0,0 +1,103 @@ +// Copyright (c) 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 + +output header {{ + + class SparcMacroInst : public SparcStaticInst + { + protected: + const uint32_t numMicroOps; + + //Constructor. + SparcMacroInst(const char *mnem, ExtMachInst _machInst, + OpClass __opClass, uint32_t _numMicroOps) + : SparcStaticInst(mnem, _machInst, __opClass), + numMicroOps(_numMicroOps) + { + assert(numMicroOps); + microOps = new StaticInstPtr[numMicroOps]; + flags[IsMacroOp] = true; + } + + ~SparcMacroInst() + { + delete [] microOps; + } + + std::string generateDisassembly(Addr pc, + const SymbolTable *symtab) const; + + StaticInstPtr * microOps; + + StaticInstPtr fetchMicroOp(MicroPC microPC) + { + assert(microPC < numMicroOps); + return microOps[microPC]; + } + + %(BasicExecPanic)s + }; + + class SparcMicroInst : public SparcStaticInst + { + protected: + //Constructor. + SparcMicroInst(const char *mnem, + ExtMachInst _machInst, OpClass __opClass) + : SparcStaticInst(mnem, _machInst, __opClass) + { + flags[IsMicroOp] = true; + } + }; + + class SparcDelayedMicroInst : public SparcMicroInst + { + protected: + //Constructor. + SparcDelayedMicroInst(const char *mnem, + ExtMachInst _machInst, OpClass __opClass) + : SparcMicroInst(mnem, _machInst, __opClass) + { + flags[IsDelayedCommit] = true; + } + }; +}}; + +output decoder {{ + + std::string SparcMacroInst::generateDisassembly(Addr pc, + const SymbolTable *symtab) const + { + std::stringstream response; + + printMnemonic(response, mnemonic); + + return response.str(); + } + +}}; diff --git a/src/arch/sparc/isa/formats/priv.isa b/src/arch/sparc/isa/formats/priv.isa index d7ee01519..2a38422a7 100644 --- a/src/arch/sparc/isa/formats/priv.isa +++ b/src/arch/sparc/isa/formats/priv.isa @@ -103,13 +103,13 @@ let {{ (usesImm, code, immCode, rString, iString) = splitOutImm(code) iop = InstObjParams(name, Name, 'Priv', code, - opt_flags, ("check", checkCode)) + opt_flags, {"check": checkCode}) header_output = BasicDeclare.subst(iop) decoder_output = BasicConstructor.subst(iop) exec_output = PrivExecute.subst(iop) if usesImm: imm_iop = InstObjParams(name, Name + 'Imm', 'PrivImm', - immCode, opt_flags, ("check", checkCode)) + immCode, opt_flags, {"check": checkCode}) header_output += BasicDeclare.subst(imm_iop) decoder_output += BasicConstructor.subst(imm_iop) exec_output += PrivExecute.subst(imm_iop) diff --git a/src/arch/sparc/isa/formats/unimp.isa b/src/arch/sparc/isa/formats/unimp.isa new file mode 100644 index 000000000..a623507a1 --- /dev/null +++ b/src/arch/sparc/isa/formats/unimp.isa @@ -0,0 +1,147 @@ +// -*- mode:c++ -*- + +// Copyright (c) 2003-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: Steve Reinhardt + +//////////////////////////////////////////////////////////////////// +// +// Unimplemented instructions +// + +output header {{ + /** + * Static instruction class for unimplemented instructions that + * cause simulator termination. Note that these are recognized + * (legal) instructions that the simulator does not support; the + * 'Unknown' class is used for unrecognized/illegal instructions. + * This is a leaf class. + */ + class FailUnimplemented : public SparcStaticInst + { + public: + /// Constructor + FailUnimplemented(const char *_mnemonic, ExtMachInst _machInst) + : SparcStaticInst(_mnemonic, _machInst, No_OpClass) + { + // don't call execute() (which panics) if we're on a + // speculative path + flags[IsNonSpeculative] = true; + } + + %(BasicExecDeclare)s + + std::string + generateDisassembly(Addr pc, const SymbolTable *symtab) const; + }; + + /** + * Base class for unimplemented instructions that cause a warning + * to be printed (but do not terminate simulation). This + * implementation is a little screwy in that it will print a + * warning for each instance of a particular unimplemented machine + * instruction, not just for each unimplemented opcode. Should + * probably make the 'warned' flag a static member of the derived + * class. + */ + class WarnUnimplemented : public SparcStaticInst + { + private: + /// Have we warned on this instruction yet? + mutable bool warned; + + public: + /// Constructor + WarnUnimplemented(const char *_mnemonic, ExtMachInst _machInst) + : SparcStaticInst(_mnemonic, _machInst, No_OpClass), warned(false) + { + // don't call execute() (which panics) if we're on a + // speculative path + flags[IsNonSpeculative] = true; + } + + %(BasicExecDeclare)s + + std::string + generateDisassembly(Addr pc, const SymbolTable *symtab) const; + }; +}}; + +output decoder {{ + std::string + FailUnimplemented::generateDisassembly(Addr pc, + const SymbolTable *symtab) const + { + return csprintf("%-10s (unimplemented)", mnemonic); + } + + std::string + WarnUnimplemented::generateDisassembly(Addr pc, + const SymbolTable *symtab) const + { +#ifdef SS_COMPATIBLE_DISASSEMBLY + return csprintf("%-10s", mnemonic); +#else + return csprintf("%-10s (unimplemented)", mnemonic); +#endif + } +}}; + +output exec {{ + Fault + FailUnimplemented::execute(%(CPU_exec_context)s *xc, + Trace::InstRecord *traceData) const + { + panic("attempt to execute unimplemented instruction '%s' " + "(inst 0x%08x)", mnemonic, machInst); + return NoFault; + } + + Fault + WarnUnimplemented::execute(%(CPU_exec_context)s *xc, + Trace::InstRecord *traceData) const + { + if (!warned) { + warn("instruction '%s' unimplemented\n", mnemonic); + warned = true; + } + + return NoFault; + } +}}; + + +def format FailUnimpl() {{ + iop = InstObjParams(name, 'FailUnimplemented') + decode_block = BasicDecodeWithMnemonic.subst(iop) +}}; + +def format WarnUnimpl() {{ + iop = InstObjParams(name, 'WarnUnimplemented') + decode_block = BasicDecodeWithMnemonic.subst(iop) +}}; + diff --git a/src/arch/sparc/isa/includes.isa b/src/arch/sparc/isa/includes.isa index f1c2bee96..a324756ec 100644 --- a/src/arch/sparc/isa/includes.isa +++ b/src/arch/sparc/isa/includes.isa @@ -40,6 +40,7 @@ output header {{ #include "cpu/static_inst.hh" #include "arch/sparc/faults.hh" #include "mem/request.hh" // some constructors use MemReq flags +#include "mem/packet.hh" #include "arch/sparc/isa_traits.hh" #include "arch/sparc/regfile.hh" }}; @@ -48,6 +49,7 @@ output decoder {{ #include "base/cprintf.hh" #include "base/loader/symtab.hh" #include "cpu/thread_context.hh" // for Jump::branchTarget() +#include "mem/packet.hh" #if defined(linux) #include <fenv.h> @@ -65,6 +67,8 @@ output exec {{ #include "cpu/base.hh" #include "cpu/exetrace.hh" #include "sim/sim_exit.hh" +#include "mem/packet.hh" +#include "mem/packet_access.hh" using namespace SparcISA; }}; diff --git a/src/arch/sparc/isa/main.isa b/src/arch/sparc/isa/main.isa index 14acf54fa..df5ad0c99 100644 --- a/src/arch/sparc/isa/main.isa +++ b/src/arch/sparc/isa/main.isa @@ -26,7 +26,7 @@ // (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: Korey Sewell +// Authors: Gabe Black //////////////////////////////////////////////////////////////////// // @@ -55,7 +55,7 @@ namespace SparcISA; ##include "base.isa" //Include the definitions for the instruction formats -##include "formats.isa" +##include "formats/formats.isa" //Include the decoder definition ##include "decoder.isa" diff --git a/src/arch/sparc/isa/operands.isa b/src/arch/sparc/isa/operands.isa index 605816083..b8b75170b 100644 --- a/src/arch/sparc/isa/operands.isa +++ b/src/arch/sparc/isa/operands.isa @@ -42,6 +42,16 @@ def operand_types {{ 'qf' : ('float', 128) }}; +output header {{ + // A function to "decompress" double and quad floating point + // register numbers stuffed into 5 bit fields. These have their + // MSB put in the LSB position but are otherwise normal. + static inline unsigned int dfpr(unsigned int regNum) + { + return (regNum & (~1)) | ((regNum & 1) << 5); + } +}}; + def operands {{ # Int regs default to unsigned, but code should not count on this. # For clarity, descriptions that depend on unsigned behavior should @@ -51,10 +61,22 @@ def operands {{ 'RdHigh': ('IntReg', 'udw', 'RD | 1', 'IsInteger', 3), 'Rs1': ('IntReg', 'udw', 'RS1', 'IsInteger', 4), 'Rs2': ('IntReg', 'udw', 'RS2', 'IsInteger', 5), - 'Frd': ('FloatReg', 'df', 'RD', 'IsFloating', 10), - 'Frs1': ('FloatReg', 'df', 'RS1', 'IsFloating', 11), - 'Frs2': ('FloatReg', 'df', 'RS2', 'IsFloating', 12), - 'Mem': ('Mem', 'udw', None, ('IsMemRef', 'IsLoad', 'IsStore'), 20), + 'Frds': ('FloatReg', 'sf', 'RD', 'IsFloating', 10), + 'Frd': ('FloatReg', 'df', 'dfpr(RD)', 'IsFloating', 10), + # Each Frd_N refers to the Nth double precision register from Frd. + # Note that this adds twice N to the register number. + 'Frd_0': ('FloatReg', 'df', 'dfpr(RD)', 'IsFloating', 10), + 'Frd_1': ('FloatReg', 'df', 'dfpr(RD) + 2', 'IsFloating', 10), + 'Frd_2': ('FloatReg', 'df', 'dfpr(RD) + 4', 'IsFloating', 10), + 'Frd_3': ('FloatReg', 'df', 'dfpr(RD) + 6', 'IsFloating', 10), + 'Frd_4': ('FloatReg', 'df', 'dfpr(RD) + 8', 'IsFloating', 10), + 'Frd_5': ('FloatReg', 'df', 'dfpr(RD) + 10', 'IsFloating', 10), + 'Frd_6': ('FloatReg', 'df', 'dfpr(RD) + 12', 'IsFloating', 10), + 'Frd_7': ('FloatReg', 'df', 'dfpr(RD) + 14', 'IsFloating', 10), + 'Frs1s': ('FloatReg', 'df', 'RS1', 'IsFloating', 11), + 'Frs1': ('FloatReg', 'df', 'dfpr(RS1)', 'IsFloating', 11), + 'Frs2s': ('FloatReg', 'df', 'RS2', 'IsFloating', 12), + 'Frs2': ('FloatReg', 'df', 'dfpr(RS2)', 'IsFloating', 12), 'NPC': ('NPC', 'udw', None, ( None, None, 'IsControl' ), 31), 'NNPC': ('NNPC', 'udw', None, (None, None, 'IsControl' ), 32), #'Runiq': ('ControlReg', 'uq', 'Uniq', None, 1), @@ -84,6 +106,8 @@ def operands {{ 'Gl': ('ControlReg', 'udw', 'MISCREG_GL', None, 54), 'Fsr': ('ControlReg', 'udw', 'MISCREG_FSR', None, 55), - 'Gsr': ('ControlReg', 'udw', 'MISCREG_GSR', None, 56) + 'Gsr': ('ControlReg', 'udw', 'MISCREG_GSR', None, 56), + # Mem gets a large number so it's always last + 'Mem': ('Mem', 'udw', None, ('IsMemRef', 'IsLoad', 'IsStore'), 100) }}; diff --git a/src/arch/sparc/utility.hh b/src/arch/sparc/utility.hh index f1c071148..23fddf0e9 100644 --- a/src/arch/sparc/utility.hh +++ b/src/arch/sparc/utility.hh @@ -33,12 +33,25 @@ #include "arch/sparc/isa_traits.hh" #include "base/misc.hh" +#include "base/bitfield.hh" +#include "cpu/thread_context.hh" namespace SparcISA { inline ExtMachInst - makeExtMI(MachInst inst, const Addr &pc) { - return ExtMachInst(inst); + makeExtMI(MachInst inst, ThreadContext * xc) { + ExtMachInst emi = (unsigned MachInst) inst; + //The I bit, bit 13, is used to figure out where the ASI + //should come from. Use that in the ExtMachInst. This is + //slightly redundant, but it removes the need to put a condition + //into all the execute functions + if(inst & (1 << 13)) + emi |= (static_cast<ExtMachInst>(xc->readMiscReg(MISCREG_ASI)) + << (sizeof(MachInst) * 8)); + else + emi |= (static_cast<ExtMachInst>(bits(inst, 12, 5)) + << (sizeof(MachInst) * 8)); + return emi; } inline bool isCallerSaveIntegerRegister(unsigned int reg) { diff --git a/src/base/bitfield.hh b/src/base/bitfield.hh index f4e49aa8d..879780d56 100644 --- a/src/base/bitfield.hh +++ b/src/base/bitfield.hh @@ -32,7 +32,7 @@ #ifndef __BASE_BITFIELD_HH__ #define __BASE_BITFIELD_HH__ -#include "sim/host.hh" +#include <inttypes.h> /** * Generate a 64-bit mask of 'nbits' 1s, right justified. diff --git a/src/base/traceflags.py b/src/base/traceflags.py index 757c9e7b7..2402cf361 100644 --- a/src/base/traceflags.py +++ b/src/base/traceflags.py @@ -133,6 +133,7 @@ baseFlags = [ 'PciConfigAll', 'Pipeline', 'Printf', + 'Quiesce', 'ROB', 'Regs', 'Rename', @@ -182,7 +183,8 @@ compoundFlagMap = { 'EthernetNoData' : [ 'Ethernet', 'EthernetPIO', 'EthernetDesc', 'EthernetIntr', 'EthernetSM', 'EthernetCksum' ], 'IdeAll' : [ 'IdeCtrl', 'IdeDisk' ], 'O3CPUAll' : [ 'Fetch', 'Decode', 'Rename', 'IEW', 'Commit', 'IQ', 'ROB', 'FreeList', 'RenameMap', 'LSQ', 'LSQUnit', 'StoreSet', 'MemDepUnit', 'DynInst', 'FullCPU', 'O3CPU', 'Activity','Scoreboard','Writeback'], - 'OzoneCPUAll' : [ 'BE', 'FE', 'IBE', 'OzoneLSQ', 'OzoneCPU'] + 'OzoneCPUAll' : [ 'BE', 'FE', 'IBE', 'OzoneLSQ', 'OzoneCPU'], + 'All' : baseFlags } ############################################################# diff --git a/src/cpu/checker/cpu.cc b/src/cpu/checker/cpu.cc index f6d56eef6..9cb6b032e 100644 --- a/src/cpu/checker/cpu.cc +++ b/src/cpu/checker/cpu.cc @@ -34,10 +34,8 @@ #include "cpu/base.hh" #include "cpu/checker/cpu.hh" #include "cpu/simple_thread.hh" -#include "cpu/thread_context.hh" #include "cpu/static_inst.hh" -#include "mem/packet_impl.hh" -#include "sim/byteswap.hh" +#include "cpu/thread_context.hh" #if FULL_SYSTEM #include "arch/vtophys.hh" @@ -171,7 +169,7 @@ CheckerCPU::read(Addr addr, T &data, unsigned flags) // translate to physical address translateDataReadReq(memReq); - Packet *pkt = new Packet(memReq, Packet::ReadReq, Packet::Broadcast); + PacketPtr pkt = new Packet(memReq, Packet::ReadReq, Packet::Broadcast); pkt->dataStatic(&data); @@ -258,7 +256,7 @@ CheckerCPU::write(T data, Addr addr, unsigned flags, uint64_t *res) T inst_data; /* // This code would work if the LSQ allowed for snooping. - Packet *pkt = new Packet(memReq, Packet::ReadReq, Packet::Broadcast); + PacketPtr pkt = new Packet(memReq, Packet::ReadReq, Packet::Broadcast); pkt.dataStatic(&inst_data); dcachePort->sendFunctional(pkt); diff --git a/src/cpu/checker/cpu_impl.hh b/src/cpu/checker/cpu_impl.hh index 8aec79754..36c7349e6 100644 --- a/src/cpu/checker/cpu_impl.hh +++ b/src/cpu/checker/cpu_impl.hh @@ -37,8 +37,6 @@ #include "cpu/simple_thread.hh" #include "cpu/thread_context.hh" #include "cpu/static_inst.hh" -#include "mem/packet_impl.hh" -#include "sim/byteswap.hh" #include "sim/sim_object.hh" #include "sim/stats.hh" @@ -183,7 +181,7 @@ Checker<DynInstPtr>::verify(DynInstPtr &completed_inst) } if (fault == NoFault) { - Packet *pkt = new Packet(memReq, Packet::ReadReq, + PacketPtr pkt = new Packet(memReq, Packet::ReadReq, Packet::Broadcast); pkt->dataStatic(&machInst); @@ -202,7 +200,7 @@ Checker<DynInstPtr>::verify(DynInstPtr &completed_inst) validateInst(inst); curStaticInst = StaticInst::decode(makeExtMI(machInst, - thread->readPC())); + thread->getTC())); #if FULL_SYSTEM thread->setInst(machInst); diff --git a/src/cpu/exetrace.cc b/src/cpu/exetrace.cc index 8b1e60aea..9d85311bb 100644 --- a/src/cpu/exetrace.cc +++ b/src/cpu/exetrace.cc @@ -60,61 +60,66 @@ Trace::InstRecord::dump(ostream &outs) if (flags[PRINT_REG_DELTA]) { #if THE_ISA == SPARC_ISA - static uint64_t regs[32] = { - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0}; - static uint64_t ccr = 0; - static uint64_t y = 0; - static uint64_t floats[32]; - uint64_t newVal; - static const char * prefixes[4] = {"G", "O", "L", "I"}; - - char buf[256]; - sprintf(buf, "PC = 0x%016llx", thread->readNextPC()); - outs << buf; - sprintf(buf, " NPC = 0x%016llx", thread->readNextNPC()); - outs << buf; - newVal = thread->readMiscReg(SparcISA::MISCREG_CCR); - if(newVal != ccr) + //Don't print what happens for each micro-op, just print out + //once at the last op, and for regular instructions. + if(!staticInst->isMicroOp() || staticInst->isLastMicroOp()) { - sprintf(buf, " CCR = 0x%016llx", newVal); + static uint64_t regs[32] = { + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0}; + static uint64_t ccr = 0; + static uint64_t y = 0; + static uint64_t floats[32]; + uint64_t newVal; + static const char * prefixes[4] = {"G", "O", "L", "I"}; + + char buf[256]; + sprintf(buf, "PC = 0x%016llx", thread->readNextPC()); outs << buf; - ccr = newVal; - } - newVal = thread->readMiscReg(SparcISA::MISCREG_Y); - if(newVal != y) - { - sprintf(buf, " Y = 0x%016llx", newVal); + sprintf(buf, " NPC = 0x%016llx", thread->readNextNPC()); outs << buf; - y = newVal; - } - for(int y = 0; y < 4; y++) - { - for(int x = 0; x < 8; x++) + newVal = thread->readMiscReg(SparcISA::MISCREG_CCR); + if(newVal != ccr) + { + sprintf(buf, " CCR = 0x%016llx", newVal); + outs << buf; + ccr = newVal; + } + newVal = thread->readMiscReg(SparcISA::MISCREG_Y); + if(newVal != y) + { + sprintf(buf, " Y = 0x%016llx", newVal); + outs << buf; + y = newVal; + } + for(int y = 0; y < 4; y++) { - int index = x + 8 * y; - newVal = thread->readIntReg(index); - if(regs[index] != newVal) + for(int x = 0; x < 8; x++) { - sprintf(buf, " %s%d = 0x%016llx", prefixes[y], x, newVal); - outs << buf; - regs[index] = newVal; + int index = x + 8 * y; + newVal = thread->readIntReg(index); + if(regs[index] != newVal) + { + sprintf(buf, " %s%d = 0x%016llx", prefixes[y], x, newVal); + outs << buf; + regs[index] = newVal; + } } } - } - for(int y = 0; y < 32; y++) - { - newVal = thread->readFloatRegBits(2 * y, 64); - if(floats[y] != newVal) + for(int y = 0; y < 32; y++) { - sprintf(buf, " F%d = 0x%016llx", y, newVal); - outs << buf; - floats[y] = newVal; + newVal = thread->readFloatRegBits(2 * y, 64); + if(floats[y] != newVal) + { + sprintf(buf, " F%d = 0x%016llx", 2 * y, newVal); + outs << buf; + floats[y] = newVal; + } } + outs << endl; } - outs << endl; #endif } else if (flags[INTEL_FORMAT]) { diff --git a/src/cpu/memtest/memtest.cc b/src/cpu/memtest/memtest.cc index 024cd7e41..91e073cf0 100644 --- a/src/cpu/memtest/memtest.cc +++ b/src/cpu/memtest/memtest.cc @@ -38,42 +38,42 @@ #include "base/misc.hh" #include "base/statistics.hh" -//#include "cpu/simple_thread.hh" #include "cpu/memtest/memtest.hh" +//#include "cpu/simple_thread.hh" //#include "mem/cache/base_cache.hh" +#include "mem/mem_object.hh" +#include "mem/port.hh" +#include "mem/packet.hh" //#include "mem/physical.hh" +#include "mem/request.hh" #include "sim/builder.hh" #include "sim/sim_events.hh" #include "sim/stats.hh" -#include "mem/packet.hh" -#include "mem/request.hh" -#include "mem/port.hh" -#include "mem/mem_object.hh" using namespace std; int TESTER_ALLOCATOR=0; bool -MemTest::CpuPort::recvTiming(Packet *pkt) +MemTest::CpuPort::recvTiming(PacketPtr pkt) { memtest->completeRequest(pkt); return true; } Tick -MemTest::CpuPort::recvAtomic(Packet *pkt) +MemTest::CpuPort::recvAtomic(PacketPtr pkt) { panic("MemTest doesn't expect recvAtomic callback!"); return curTick; } void -MemTest::CpuPort::recvFunctional(Packet *pkt) +MemTest::CpuPort::recvFunctional(PacketPtr pkt) { //Do nothing if we see one come through - if (curTick != 0)//Supress warning durring initialization - warn("Functional Writes not implemented in MemTester\n"); +// if (curTick != 0)//Supress warning durring initialization +// warn("Functional Writes not implemented in MemTester\n"); //Need to find any response values that intersect and update return; } @@ -94,7 +94,7 @@ MemTest::CpuPort::recvRetry() } void -MemTest::sendPkt(Packet *pkt) { +MemTest::sendPkt(PacketPtr pkt) { if (atomic) { cachePort.sendAtomic(pkt); pkt->makeAtomicResponse(); @@ -113,7 +113,7 @@ MemTest::MemTest(const string &name, // PhysicalMemory *check_mem, unsigned _memorySize, unsigned _percentReads, -// unsigned _percentCopies, + unsigned _percentFunctional, unsigned _percentUncacheable, unsigned _progressInterval, unsigned _percentSourceUnaligned, @@ -130,7 +130,7 @@ MemTest::MemTest(const string &name, // checkMem(check_mem), size(_memorySize), percentReads(_percentReads), -// percentCopies(_percentCopies), + percentFunctional(_percentFunctional), percentUncacheable(_percentUncacheable), progressInterval(_progressInterval), nextProgressMessage(_progressInterval), @@ -204,7 +204,7 @@ printData(ostream &os, uint8_t *data, int nbytes) } void -MemTest::completeRequest(Packet *pkt) +MemTest::completeRequest(PacketPtr pkt) { MemTestSenderState *state = dynamic_cast<MemTestSenderState *>(pkt->senderState); @@ -345,8 +345,8 @@ MemTest::tick() } else { paddr = ((base) ? baseAddr1 : baseAddr2) + offset; } - //bool probe = (random() % 2 == 1) && !req->isUncacheable(); - bool probe = false; + bool probe = (random() % 100 < percentFunctional) && !(flags & UNCACHEABLE); + //bool probe = false; paddr &= ~((1 << access_size) - 1); req->setPhys(paddr, 1 << access_size, flags); @@ -381,13 +381,14 @@ MemTest::tick() << dec << curTick << endl; } - Packet *pkt = new Packet(req, Packet::ReadReq, Packet::Broadcast); + PacketPtr pkt = new Packet(req, Packet::ReadReq, Packet::Broadcast); pkt->dataDynamicArray(new uint8_t[req->getSize()]); MemTestSenderState *state = new MemTestSenderState(result); pkt->senderState = state; if (probe) { cachePort.sendFunctional(pkt); + pkt->makeAtomicResponse(); completeRequest(pkt); } else { // req->completionEvent = new MemCompleteEvent(req, result, this); @@ -420,7 +421,7 @@ MemTest::tick() << dec << curTick << endl; } */ - Packet *pkt = new Packet(req, Packet::WriteReq, Packet::Broadcast); + PacketPtr pkt = new Packet(req, Packet::WriteReq, Packet::Broadcast); uint8_t *pkt_data = new uint8_t[req->getSize()]; pkt->dataDynamicArray(pkt_data); memcpy(pkt_data, &data, req->getSize()); @@ -431,6 +432,7 @@ MemTest::tick() if (probe) { cachePort.sendFunctional(pkt); + pkt->makeAtomicResponse(); completeRequest(pkt); } else { // req->completionEvent = new MemCompleteEvent(req, NULL, this); @@ -499,7 +501,7 @@ BEGIN_DECLARE_SIM_OBJECT_PARAMS(MemTest) // SimObjectParam<PhysicalMemory *> check_mem; Param<unsigned> memory_size; Param<unsigned> percent_reads; -// Param<unsigned> percent_copies; + Param<unsigned> percent_functional; Param<unsigned> percent_uncacheable; Param<unsigned> progress_interval; Param<unsigned> percent_source_unaligned; @@ -518,7 +520,7 @@ BEGIN_INIT_SIM_OBJECT_PARAMS(MemTest) // INIT_PARAM(check_mem, "check memory"), INIT_PARAM(memory_size, "memory size"), INIT_PARAM(percent_reads, "target read percentage"), -// INIT_PARAM(percent_copies, "target copy percentage"), + INIT_PARAM(percent_functional, "percentage of access that are functional"), INIT_PARAM(percent_uncacheable, "target uncacheable percentage"), INIT_PARAM(progress_interval, "progress report interval (in accesses)"), INIT_PARAM(percent_source_unaligned, @@ -535,7 +537,7 @@ END_INIT_SIM_OBJECT_PARAMS(MemTest) CREATE_SIM_OBJECT(MemTest) { return new MemTest(getInstanceName(), /*cache->getInterface(),*/ /*main_mem,*/ - /*check_mem,*/ memory_size, percent_reads, /*percent_copies,*/ + /*check_mem,*/ memory_size, percent_reads, percent_functional, percent_uncacheable, progress_interval, percent_source_unaligned, percent_dest_unaligned, trace_addr, max_loads, atomic); diff --git a/src/cpu/memtest/memtest.hh b/src/cpu/memtest/memtest.hh index 5de41f0d8..edde4a3b2 100644 --- a/src/cpu/memtest/memtest.hh +++ b/src/cpu/memtest/memtest.hh @@ -55,7 +55,7 @@ class MemTest : public MemObject // PhysicalMemory *check_mem, unsigned _memorySize, unsigned _percentReads, -// unsigned _percentCopies, + unsigned _percentFunctional, unsigned _percentUncacheable, unsigned _progressInterval, unsigned _percentSourceUnaligned, @@ -102,11 +102,11 @@ class MemTest : public MemObject protected: - virtual bool recvTiming(Packet *pkt); + virtual bool recvTiming(PacketPtr pkt); - virtual Tick recvAtomic(Packet *pkt); + virtual Tick recvAtomic(PacketPtr pkt); - virtual void recvFunctional(Packet *pkt); + virtual void recvFunctional(PacketPtr pkt); virtual void recvStatusChange(Status status); @@ -133,7 +133,7 @@ class MemTest : public MemObject }; // Request *dataReq; - Packet *retryPkt; + PacketPtr retryPkt; // MemInterface *cacheInterface; // PhysicalMemory *mainMem; // PhysicalMemory *checkMem; @@ -144,7 +144,7 @@ class MemTest : public MemObject unsigned size; // size of testing memory region unsigned percentReads; // target percentage of read accesses -// unsigned percentCopies; // target percentage of copy accesses + unsigned percentFunctional; // target percentage of functional accesses unsigned percentUncacheable; int id; @@ -184,9 +184,9 @@ class MemTest : public MemObject Stats::Scalar<> numCopiesStat; // called by MemCompleteEvent::process() - void completeRequest(Packet *pkt); + void completeRequest(PacketPtr pkt); - void sendPkt(Packet *pkt); + void sendPkt(PacketPtr pkt); void doRetry(); diff --git a/src/cpu/o3/alpha/dyn_inst.hh b/src/cpu/o3/alpha/dyn_inst.hh index 9dee610b6..294aadde8 100644 --- a/src/cpu/o3/alpha/dyn_inst.hh +++ b/src/cpu/o3/alpha/dyn_inst.hh @@ -86,7 +86,7 @@ class AlphaDynInst : public BaseDynInst<Impl> Fault initiateAcc(); /** Completes the access. Only valid for memory operations. */ - Fault completeAcc(Packet *pkt); + Fault completeAcc(PacketPtr pkt); private: /** Initializes variables. */ diff --git a/src/cpu/o3/alpha/dyn_inst_impl.hh b/src/cpu/o3/alpha/dyn_inst_impl.hh index 2d1b4b309..b273a7b9b 100644 --- a/src/cpu/o3/alpha/dyn_inst_impl.hh +++ b/src/cpu/o3/alpha/dyn_inst_impl.hh @@ -100,7 +100,7 @@ AlphaDynInst<Impl>::initiateAcc() template <class Impl> Fault -AlphaDynInst<Impl>::completeAcc(Packet *pkt) +AlphaDynInst<Impl>::completeAcc(PacketPtr pkt) { this->fault = this->staticInst->completeAcc(pkt, this, this->traceData); diff --git a/src/cpu/o3/fetch.hh b/src/cpu/o3/fetch.hh index 280bf0e71..5555bff85 100644 --- a/src/cpu/o3/fetch.hh +++ b/src/cpu/o3/fetch.hh @@ -36,7 +36,7 @@ #include "base/statistics.hh" #include "base/timebuf.hh" #include "cpu/pc_event.hh" -#include "mem/packet_impl.hh" +#include "mem/packet.hh" #include "mem/port.hh" #include "sim/eventq.hh" diff --git a/src/cpu/o3/fetch_impl.hh b/src/cpu/o3/fetch_impl.hh index f261a0a3a..2f7a75129 100644 --- a/src/cpu/o3/fetch_impl.hh +++ b/src/cpu/o3/fetch_impl.hh @@ -78,9 +78,12 @@ DefaultFetch<Impl>::IcachePort::recvStatusChange(Status status) template<class Impl> bool -DefaultFetch<Impl>::IcachePort::recvTiming(Packet *pkt) +DefaultFetch<Impl>::IcachePort::recvTiming(PacketPtr pkt) { - fetch->processCacheCompletion(pkt); + if (pkt->isResponse()) { + fetch->processCacheCompletion(pkt); + } + //else Snooped a coherence request, just return return true; } @@ -1115,7 +1118,7 @@ DefaultFetch<Impl>::fetch(bool &status_change) inst = TheISA::gtoh(*reinterpret_cast<TheISA::MachInst *> (&cacheData[tid][offset])); - ext_inst = TheISA::makeExtMI(inst, fetch_PC); + ext_inst = TheISA::makeExtMI(inst, cpu->tcBase(tid)); // Create a new DynInst from the instruction fetched. DynInstPtr instruction = new DynInst(ext_inst, fetch_PC, diff --git a/src/cpu/o3/lsq_impl.hh b/src/cpu/o3/lsq_impl.hh index 7b7d1eb8e..317e23b14 100644 --- a/src/cpu/o3/lsq_impl.hh +++ b/src/cpu/o3/lsq_impl.hh @@ -63,7 +63,14 @@ template <class Impl> bool LSQ<Impl>::DcachePort::recvTiming(PacketPtr pkt) { - lsq->thread[pkt->req->getThreadNum()].completeDataAccess(pkt); + if (pkt->isResponse()) { + lsq->thread[pkt->req->getThreadNum()].completeDataAccess(pkt); + } + else { + //else it is a coherence request, maybe you need to do something + warn("Recieved a coherence request (Invalidate?), 03CPU doesn't" + "update LSQ for these\n"); + } return true; } diff --git a/src/cpu/o3/lsq_unit.hh b/src/cpu/o3/lsq_unit.hh index 00f24f98c..a2e11173e 100644 --- a/src/cpu/o3/lsq_unit.hh +++ b/src/cpu/o3/lsq_unit.hh @@ -41,7 +41,7 @@ #include "config/full_system.hh" #include "base/hashmap.hh" #include "cpu/inst_seq.hh" -#include "mem/packet_impl.hh" +#include "mem/packet.hh" #include "mem/port.hh" /** @@ -220,7 +220,7 @@ class LSQUnit { void writeback(DynInstPtr &inst, PacketPtr pkt); /** Handles completing the send of a store to memory. */ - void storePostSend(Packet *pkt); + void storePostSend(PacketPtr pkt); /** Completes the store at the specified index. */ void completeStore(int store_idx); diff --git a/src/cpu/o3/lsq_unit_impl.hh b/src/cpu/o3/lsq_unit_impl.hh index 05b784a1b..8a63ff011 100644 --- a/src/cpu/o3/lsq_unit_impl.hh +++ b/src/cpu/o3/lsq_unit_impl.hh @@ -761,7 +761,7 @@ LSQUnit<Impl>::squash(const InstSeqNum &squashed_num) template <class Impl> void -LSQUnit<Impl>::storePostSend(Packet *pkt) +LSQUnit<Impl>::storePostSend(PacketPtr pkt) { if (isStalled() && storeQueue[storeWBIdx].inst->seqNum == stallingStoreIsn) { diff --git a/src/cpu/o3/mips/dyn_inst.hh b/src/cpu/o3/mips/dyn_inst.hh index 06bdfcec4..aa30bfa1e 100755 --- a/src/cpu/o3/mips/dyn_inst.hh +++ b/src/cpu/o3/mips/dyn_inst.hh @@ -87,7 +87,7 @@ class MipsDynInst : public BaseDynInst<Impl> Fault initiateAcc(); /** Completes the access. Only valid for memory operations. */ - Fault completeAcc(Packet *pkt); + Fault completeAcc(PacketPtr pkt); private: /** Initializes variables. */ diff --git a/src/cpu/o3/mips/dyn_inst_impl.hh b/src/cpu/o3/mips/dyn_inst_impl.hh index 57dec1ccf..5bc01b9b3 100755 --- a/src/cpu/o3/mips/dyn_inst_impl.hh +++ b/src/cpu/o3/mips/dyn_inst_impl.hh @@ -100,7 +100,7 @@ MipsDynInst<Impl>::initiateAcc() template <class Impl> Fault -MipsDynInst<Impl>::completeAcc(Packet *pkt) +MipsDynInst<Impl>::completeAcc(PacketPtr pkt) { this->fault = this->staticInst->completeAcc(pkt, this, this->traceData); diff --git a/src/cpu/ozone/dyn_inst.hh b/src/cpu/ozone/dyn_inst.hh index 75ac464ec..e7390626e 100644 --- a/src/cpu/ozone/dyn_inst.hh +++ b/src/cpu/ozone/dyn_inst.hh @@ -133,7 +133,7 @@ class OzoneDynInst : public BaseDynInst<Impl> Fault initiateAcc(); - Fault completeAcc(Packet *pkt); + Fault completeAcc(PacketPtr pkt); // The register accessor methods provide the index of the // instruction's operand (e.g., 0 or 1), not the architectural diff --git a/src/cpu/ozone/dyn_inst_impl.hh b/src/cpu/ozone/dyn_inst_impl.hh index db1460eba..0a1e1c139 100644 --- a/src/cpu/ozone/dyn_inst_impl.hh +++ b/src/cpu/ozone/dyn_inst_impl.hh @@ -108,7 +108,7 @@ OzoneDynInst<Impl>::initiateAcc() template <class Impl> Fault -OzoneDynInst<Impl>::completeAcc(Packet *pkt) +OzoneDynInst<Impl>::completeAcc(PacketPtr pkt) { this->fault = this->staticInst->completeAcc(pkt, this, this->traceData); diff --git a/src/cpu/ozone/front_end.hh b/src/cpu/ozone/front_end.hh index 59cf9785c..2bdca35b9 100644 --- a/src/cpu/ozone/front_end.hh +++ b/src/cpu/ozone/front_end.hh @@ -129,7 +129,7 @@ class FrontEnd const bool is_branch = false, const bool branch_taken = false); DynInstPtr getInst(); - void processCacheCompletion(Packet *pkt); + void processCacheCompletion(PacketPtr pkt); void addFreeRegs(int num_freed); diff --git a/src/cpu/ozone/front_end_impl.hh b/src/cpu/ozone/front_end_impl.hh index c814ff9c7..36e87ec9c 100644 --- a/src/cpu/ozone/front_end_impl.hh +++ b/src/cpu/ozone/front_end_impl.hh @@ -74,7 +74,7 @@ FrontEnd<Impl>::IcachePort::recvStatusChange(Status status) template<class Impl> bool -FrontEnd<Impl>::IcachePort::recvTiming(Packet *pkt) +FrontEnd<Impl>::IcachePort::recvTiming(PacketPtr pkt) { fe->processCacheCompletion(pkt); return true; @@ -883,7 +883,7 @@ FrontEnd<Impl>::getInstFromCacheline() // Get the instruction from the array of the cache line. inst = htog(*reinterpret_cast<MachInst *>(&cacheData[offset])); - ExtMachInst decode_inst = TheISA::makeExtMI(inst, PC); + ExtMachInst decode_inst = TheISA::makeExtMI(inst, tc); // Create a new DynInst from the instruction fetched. DynInstPtr instruction = new DynInst(decode_inst, PC, PC+sizeof(MachInst), diff --git a/src/cpu/ozone/lw_lsq.hh b/src/cpu/ozone/lw_lsq.hh index 9b93ce74f..dc58a8285 100644 --- a/src/cpu/ozone/lw_lsq.hh +++ b/src/cpu/ozone/lw_lsq.hh @@ -222,7 +222,7 @@ class OzoneLWLSQ { void writeback(DynInstPtr &inst, PacketPtr pkt); /** Handles completing the send of a store to memory. */ - void storePostSend(Packet *pkt, DynInstPtr &inst); + void storePostSend(PacketPtr pkt, DynInstPtr &inst); /** Completes the store at the specified index. */ void completeStore(DynInstPtr &inst); @@ -260,7 +260,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,-1)); } virtual bool recvTiming(PacketPtr pkt); diff --git a/src/cpu/ozone/lw_lsq_impl.hh b/src/cpu/ozone/lw_lsq_impl.hh index e523712da..1f3f18502 100644 --- a/src/cpu/ozone/lw_lsq_impl.hh +++ b/src/cpu/ozone/lw_lsq_impl.hh @@ -832,7 +832,7 @@ OzoneLWLSQ<Impl>::dumpInsts() template <class Impl> void -OzoneLWLSQ<Impl>::storePostSend(Packet *pkt, DynInstPtr &inst) +OzoneLWLSQ<Impl>::storePostSend(PacketPtr pkt, DynInstPtr &inst) { if (isStalled() && inst->seqNum == stallingStoreIsn) { diff --git a/src/cpu/quiesce_event.cc b/src/cpu/quiesce_event.cc index 8dd20db02..fa79e6d1e 100644 --- a/src/cpu/quiesce_event.cc +++ b/src/cpu/quiesce_event.cc @@ -28,6 +28,7 @@ * Authors: Kevin Lim */ +#include "cpu/base.hh" #include "cpu/thread_context.hh" #include "cpu/quiesce_event.hh" @@ -39,6 +40,7 @@ EndQuiesceEvent::EndQuiesceEvent(ThreadContext *_tc) void EndQuiesceEvent::process() { + DPRINTF(Quiesce, "activating %s\n", tc->getCpuPtr()->name()); tc->activate(); } diff --git a/src/cpu/simple/atomic.cc b/src/cpu/simple/atomic.cc index fe421ae6c..25c478ae9 100644 --- a/src/cpu/simple/atomic.cc +++ b/src/cpu/simple/atomic.cc @@ -32,7 +32,8 @@ #include "arch/utility.hh" #include "cpu/exetrace.hh" #include "cpu/simple/atomic.hh" -#include "mem/packet_impl.hh" +#include "mem/packet.hh" +#include "mem/packet_access.hh" #include "sim/builder.hh" #include "sim/system.hh" @@ -92,21 +93,21 @@ AtomicSimpleCPU::init() } bool -AtomicSimpleCPU::CpuPort::recvTiming(Packet *pkt) +AtomicSimpleCPU::CpuPort::recvTiming(PacketPtr pkt) { panic("AtomicSimpleCPU doesn't expect recvTiming callback!"); return true; } Tick -AtomicSimpleCPU::CpuPort::recvAtomic(Packet *pkt) +AtomicSimpleCPU::CpuPort::recvAtomic(PacketPtr pkt) { - panic("AtomicSimpleCPU doesn't expect recvAtomic callback!"); + //Snooping a coherence request, just return return curTick; } void -AtomicSimpleCPU::CpuPort::recvFunctional(Packet *pkt) +AtomicSimpleCPU::CpuPort::recvFunctional(PacketPtr pkt) { //No internal storage to update, just return return; @@ -259,7 +260,7 @@ AtomicSimpleCPU::read(Addr addr, T &data, unsigned flags) { // use the CPU's statically allocated read request and packet objects Request *req = data_read_req; - Packet *pkt = data_read_pkt; + PacketPtr pkt = data_read_pkt; req->setVirt(0, addr, sizeof(T), flags, thread->readPC()); @@ -341,7 +342,7 @@ AtomicSimpleCPU::write(T data, Addr addr, unsigned flags, uint64_t *res) { // use the CPU's statically allocated write request and packet objects Request *req = data_write_req; - Packet *pkt = data_write_pkt; + PacketPtr pkt = data_write_pkt; req->setVirt(0, addr, sizeof(T), flags, thread->readPC()); @@ -447,7 +448,8 @@ AtomicSimpleCPU::tick() for (int i = 0; i < width; ++i) { numCycles++; - checkForInterrupts(); + if (!curStaticInst || !curStaticInst->isDelayedCommit()) + checkForInterrupts(); Fault fault = setupFetchRequest(ifetch_req); diff --git a/src/cpu/simple/atomic.hh b/src/cpu/simple/atomic.hh index 52afd76ef..0edca9369 100644 --- a/src/cpu/simple/atomic.hh +++ b/src/cpu/simple/atomic.hh @@ -92,11 +92,11 @@ class AtomicSimpleCPU : public BaseSimpleCPU protected: - virtual bool recvTiming(Packet *pkt); + virtual bool recvTiming(PacketPtr pkt); - virtual Tick recvAtomic(Packet *pkt); + virtual Tick recvAtomic(PacketPtr pkt); - virtual void recvFunctional(Packet *pkt); + virtual void recvFunctional(PacketPtr pkt); virtual void recvStatusChange(Status status); @@ -110,12 +110,12 @@ class AtomicSimpleCPU : public BaseSimpleCPU CpuPort icachePort; CpuPort dcachePort; - Request *ifetch_req; - Packet *ifetch_pkt; - Request *data_read_req; - Packet *data_read_pkt; - Request *data_write_req; - Packet *data_write_pkt; + Request *ifetch_req; + PacketPtr ifetch_pkt; + Request *data_read_req; + PacketPtr data_read_pkt; + Request *data_write_req; + PacketPtr data_write_pkt; bool dcache_access; Tick dcache_latency; diff --git a/src/cpu/simple/base.cc b/src/cpu/simple/base.cc index 522fe79aa..cbb3980cb 100644 --- a/src/cpu/simple/base.cc +++ b/src/cpu/simple/base.cc @@ -47,7 +47,7 @@ #include "cpu/static_inst.hh" #include "cpu/thread_context.hh" #include "kern/kernel_stats.hh" -#include "mem/packet_impl.hh" +#include "mem/packet.hh" #include "sim/builder.hh" #include "sim/byteswap.hh" #include "sim/debug.hh" @@ -396,7 +396,20 @@ BaseSimpleCPU::preExecute() // decode the instruction inst = gtoh(inst); - curStaticInst = StaticInst::decode(makeExtMI(inst, thread->readPC())); + //If we're not in the middle of a macro instruction + if (!curMacroStaticInst) { + StaticInstPtr instPtr = StaticInst::decode(makeExtMI(inst, thread->getTC())); + if (instPtr->isMacroOp()) { + curMacroStaticInst = instPtr; + curStaticInst = curMacroStaticInst->fetchMicroOp(0); + } else { + curStaticInst = instPtr; + } + } else { + //Read the next micro op from the macro op + curStaticInst = curMacroStaticInst->fetchMicroOp(thread->readMicroPC()); + } + traceData = Trace::getInstRecord(curTick, tc, curStaticInst, thread->readPC()); @@ -446,18 +459,35 @@ BaseSimpleCPU::advancePC(Fault fault) { if (fault != NoFault) { fault->invoke(tc); - } - else { - // go to the next instruction - thread->setPC(thread->readNextPC()); + } else { + //If we're at the last micro op for this instruction + if (curStaticInst->isLastMicroOp()) { + //We should be working with a macro op + assert(curMacroStaticInst); + //Close out this macro op, and clean up the + //microcode state + curMacroStaticInst = StaticInst::nullStaticInstPtr; + thread->setMicroPC(0); + thread->setNextMicroPC(1); + } + //If we're still in a macro op + if (curMacroStaticInst) { + //Advance the micro pc + thread->setMicroPC(thread->readNextMicroPC()); + //Advance the "next" micro pc. Note that there are no delay + //slots, and micro ops are "word" addressed. + thread->setNextMicroPC(thread->readNextMicroPC() + 1); + } else { + // go to the next instruction + thread->setPC(thread->readNextPC()); #if ISA_HAS_DELAY_SLOT - thread->setNextPC(thread->readNextNPC()); - thread->setNextNPC(thread->readNextNPC() + sizeof(MachInst)); - assert(thread->readNextPC() != thread->readNextNPC()); + thread->setNextPC(thread->readNextNPC()); + thread->setNextNPC(thread->readNextNPC() + sizeof(MachInst)); + assert(thread->readNextPC() != thread->readNextNPC()); #else - thread->setNextPC(thread->readNextPC() + sizeof(MachInst)); + thread->setNextPC(thread->readNextPC() + sizeof(MachInst)); #endif - + } } #if FULL_SYSTEM diff --git a/src/cpu/simple/base.hh b/src/cpu/simple/base.hh index 57cfa3c2c..af6b6f835 100644 --- a/src/cpu/simple/base.hh +++ b/src/cpu/simple/base.hh @@ -128,6 +128,7 @@ class BaseSimpleCPU : public BaseCPU TheISA::IntReg dataReg; StaticInstPtr curStaticInst; + StaticInstPtr curMacroStaticInst; void checkForInterrupts(); Fault setupFetchRequest(Request *req); diff --git a/src/cpu/simple/timing.cc b/src/cpu/simple/timing.cc index ad5c0e5d6..fe6775ea4 100644 --- a/src/cpu/simple/timing.cc +++ b/src/cpu/simple/timing.cc @@ -32,7 +32,8 @@ #include "arch/utility.hh" #include "cpu/exetrace.hh" #include "cpu/simple/timing.hh" -#include "mem/packet_impl.hh" +#include "mem/packet.hh" +#include "mem/packet_access.hh" #include "sim/builder.hh" #include "sim/system.hh" @@ -65,14 +66,14 @@ TimingSimpleCPU::init() } Tick -TimingSimpleCPU::CpuPort::recvAtomic(Packet *pkt) +TimingSimpleCPU::CpuPort::recvAtomic(PacketPtr pkt) { panic("TimingSimpleCPU doesn't expect recvAtomic callback!"); return curTick; } void -TimingSimpleCPU::CpuPort::recvFunctional(Packet *pkt) +TimingSimpleCPU::CpuPort::recvFunctional(PacketPtr pkt) { //No internal storage to update, jusst return return; @@ -89,7 +90,7 @@ TimingSimpleCPU::CpuPort::recvStatusChange(Status status) void -TimingSimpleCPU::CpuPort::TickEvent::schedule(Packet *_pkt, Tick t) +TimingSimpleCPU::CpuPort::TickEvent::schedule(PacketPtr _pkt, Tick t) { pkt = _pkt; Event::schedule(t); @@ -268,7 +269,7 @@ TimingSimpleCPU::read(Addr addr, T &data, unsigned flags) // Now do the access. if (fault == NoFault) { - Packet *pkt = + PacketPtr pkt = new Packet(req, Packet::ReadReq, Packet::Broadcast); pkt->dataDynamic<T>(new T); @@ -426,7 +427,8 @@ TimingSimpleCPU::write(int32_t data, Addr addr, unsigned flags, uint64_t *res) void TimingSimpleCPU::fetch() { - checkForInterrupts(); + if (!curStaticInst || !curStaticInst->isDelayedCommit()) + checkForInterrupts(); Request *ifetch_req = new Request(); ifetch_req->setThreadContext(cpu_id, /* thread ID */ 0); @@ -470,7 +472,7 @@ TimingSimpleCPU::advanceInst(Fault fault) void -TimingSimpleCPU::completeIfetch(Packet *pkt) +TimingSimpleCPU::completeIfetch(PacketPtr pkt) { // received a response from the icache: execute the received // instruction @@ -526,19 +528,25 @@ TimingSimpleCPU::IcachePort::ITickEvent::process() } bool -TimingSimpleCPU::IcachePort::recvTiming(Packet *pkt) +TimingSimpleCPU::IcachePort::recvTiming(PacketPtr pkt) { - // delay processing of returned data until next CPU clock edge - Tick time = pkt->req->getTime(); - while (time < curTick) - time += lat; + if (pkt->isResponse()) { + // delay processing of returned data until next CPU clock edge + Tick time = pkt->req->getTime(); + while (time < curTick) + time += lat; - if (time == curTick) - cpu->completeIfetch(pkt); - else - tickEvent.schedule(pkt, time); + if (time == curTick) + cpu->completeIfetch(pkt); + else + tickEvent.schedule(pkt, time); - return true; + return true; + } + else { + //Snooping a Coherence Request, do nothing + return true; + } } void @@ -548,7 +556,7 @@ TimingSimpleCPU::IcachePort::recvRetry() // waiting to transmit assert(cpu->ifetch_pkt != NULL); assert(cpu->_status == IcacheRetry); - Packet *tmp = cpu->ifetch_pkt; + PacketPtr tmp = cpu->ifetch_pkt; if (sendTiming(tmp)) { cpu->_status = IcacheWaitResponse; cpu->ifetch_pkt = NULL; @@ -556,7 +564,7 @@ TimingSimpleCPU::IcachePort::recvRetry() } void -TimingSimpleCPU::completeDataAccess(Packet *pkt) +TimingSimpleCPU::completeDataAccess(PacketPtr pkt) { // received a response from the dcache: complete the load or store // instruction @@ -598,19 +606,25 @@ TimingSimpleCPU::completeDrain() } bool -TimingSimpleCPU::DcachePort::recvTiming(Packet *pkt) +TimingSimpleCPU::DcachePort::recvTiming(PacketPtr pkt) { - // delay processing of returned data until next CPU clock edge - Tick time = pkt->req->getTime(); - while (time < curTick) - time += lat; + if (pkt->isResponse()) { + // delay processing of returned data until next CPU clock edge + Tick time = pkt->req->getTime(); + while (time < curTick) + time += lat; - if (time == curTick) - cpu->completeDataAccess(pkt); - else - tickEvent.schedule(pkt, time); + if (time == curTick) + cpu->completeDataAccess(pkt); + else + tickEvent.schedule(pkt, time); - return true; + return true; + } + else { + //Snooping a coherence req, do nothing + return true; + } } void @@ -626,7 +640,7 @@ TimingSimpleCPU::DcachePort::recvRetry() // waiting to transmit assert(cpu->dcache_pkt != NULL); assert(cpu->_status == DcacheRetry); - Packet *tmp = cpu->dcache_pkt; + PacketPtr tmp = cpu->dcache_pkt; if (sendTiming(tmp)) { cpu->_status = DcacheWaitResponse; // memory system takes ownership of packet diff --git a/src/cpu/simple/timing.hh b/src/cpu/simple/timing.hh index 988ddeded..577e13e40 100644 --- a/src/cpu/simple/timing.hh +++ b/src/cpu/simple/timing.hh @@ -84,9 +84,9 @@ class TimingSimpleCPU : public BaseSimpleCPU protected: - virtual Tick recvAtomic(Packet *pkt); + virtual Tick recvAtomic(PacketPtr pkt); - virtual void recvFunctional(Packet *pkt); + virtual void recvFunctional(PacketPtr pkt); virtual void recvStatusChange(Status status); @@ -96,13 +96,13 @@ class TimingSimpleCPU : public BaseSimpleCPU struct TickEvent : public Event { - Packet *pkt; + PacketPtr pkt; TimingSimpleCPU *cpu; TickEvent(TimingSimpleCPU *_cpu) :Event(&mainEventQueue), cpu(_cpu) {} const char *description() { return "Timing CPU clock event"; } - void schedule(Packet *_pkt, Tick t); + void schedule(PacketPtr _pkt, Tick t); }; }; @@ -117,7 +117,7 @@ class TimingSimpleCPU : public BaseSimpleCPU protected: - virtual bool recvTiming(Packet *pkt); + virtual bool recvTiming(PacketPtr pkt); virtual void recvRetry(); @@ -144,7 +144,7 @@ class TimingSimpleCPU : public BaseSimpleCPU protected: - virtual bool recvTiming(Packet *pkt); + virtual bool recvTiming(PacketPtr pkt); virtual void recvRetry(); @@ -163,8 +163,8 @@ class TimingSimpleCPU : public BaseSimpleCPU IcachePort icachePort; DcachePort dcachePort; - Packet *ifetch_pkt; - Packet *dcache_pkt; + PacketPtr ifetch_pkt; + PacketPtr dcache_pkt; int cpu_id; Tick previousTick; @@ -192,8 +192,8 @@ class TimingSimpleCPU : public BaseSimpleCPU Fault write(T data, Addr addr, unsigned flags, uint64_t *res); void fetch(); - void completeIfetch(Packet *); - void completeDataAccess(Packet *); + void completeIfetch(PacketPtr ); + void completeDataAccess(PacketPtr ); void advanceInst(Fault fault); private: void completeDrain(); diff --git a/src/cpu/simple_thread.hh b/src/cpu/simple_thread.hh index 6fa6500bd..fe22e6c43 100644 --- a/src/cpu/simple_thread.hh +++ b/src/cpu/simple_thread.hh @@ -377,6 +377,16 @@ class SimpleThread : public ThreadState regs.setPC(val); } + uint64_t readMicroPC() + { + return microPC; + } + + void setMicroPC(uint64_t val) + { + microPC = val; + } + uint64_t readNextPC() { return regs.readNextPC(); @@ -387,6 +397,16 @@ class SimpleThread : public ThreadState regs.setNextPC(val); } + uint64_t readNextMicroPC() + { + return nextMicroPC; + } + + void setNextMicroPC(uint64_t val) + { + nextMicroPC = val; + } + uint64_t readNextNPC() { return regs.readNextNPC(); diff --git a/src/cpu/static_inst.cc b/src/cpu/static_inst.cc index c311d2282..cb4a7cdf7 100644 --- a/src/cpu/static_inst.cc +++ b/src/cpu/static_inst.cc @@ -75,3 +75,10 @@ StaticInst::hasBranchTarget(Addr pc, ThreadContext *tc, Addr &tgt) const return false; } +StaticInstPtr +StaticInst::fetchMicroOp(MicroPC micropc) +{ + panic("StaticInst::fetchMicroOp() called on instruction " + "that is not microcoded."); +} + diff --git a/src/cpu/static_inst.hh b/src/cpu/static_inst.hh index 578d14191..523cfae40 100644 --- a/src/cpu/static_inst.hh +++ b/src/cpu/static_inst.hh @@ -67,6 +67,8 @@ namespace Trace { class InstRecord; } +typedef uint32_t MicroPC; + /** * Base, ISA-independent static instruction class. * @@ -139,6 +141,14 @@ class StaticInstBase : public RefCounted IsIprAccess, ///< Accesses IPRs IsUnverifiable, ///< Can't be verified by a checker + //Flags for microcode + IsMacroOp, ///< Is a macroop containing microops + IsMicroOp, ///< Is a microop + IsDelayedCommit, ///< This microop doesn't commit right away + IsLastMicroOp, ///< This microop ends a microop sequence + //This flag doesn't do anything yet + IsMicroBranch, ///< This microop branches within the microcode for a macroop + NumFlags }; @@ -230,6 +240,12 @@ class StaticInstBase : public RefCounted bool isQuiesce() const { return flags[IsQuiesce]; } bool isIprAccess() const { return flags[IsIprAccess]; } bool isUnverifiable() const { return flags[IsUnverifiable]; } + bool isMacroOp() const { return flags[IsMacroOp]; } + bool isMicroOp() const { return flags[IsMicroOp]; } + bool isDelayedCommit() const { return flags[IsDelayedCommit]; } + bool isLastMicroOp() const { return flags[IsLastMicroOp]; } + //This flag doesn't do anything yet + bool isMicroBranch() const { return flags[IsMicroBranch]; } //@} /// Operation class. Used to select appropriate function unit in issue. @@ -347,6 +363,12 @@ class StaticInst : public StaticInstBase #include "cpu/static_inst_exec_sigs.hh" /** + * Return the microop that goes with a particular micropc. This should + * only be defined/used in macroops which will contain microops + */ + virtual StaticInstPtr fetchMicroOp(MicroPC micropc); + + /** * Return the target address for a PC-relative branch. * Invalid if not a PC-relative branch (i.e. isDirectCtrl() * should be true). diff --git a/src/cpu/thread_state.cc b/src/cpu/thread_state.cc index 6a96560f1..c644ae8d7 100644 --- a/src/cpu/thread_state.cc +++ b/src/cpu/thread_state.cc @@ -42,13 +42,13 @@ ThreadState::ThreadState(int _cpuId, int _tid) : cpuId(_cpuId), tid(_tid), lastActivate(0), lastSuspend(0), profile(NULL), profileNode(NULL), profilePC(0), quiesceEvent(NULL), - funcExeInst(0), storeCondFailures(0) + microPC(0), nextMicroPC(1), funcExeInst(0), storeCondFailures(0) #else ThreadState::ThreadState(int _cpuId, int _tid, Process *_process, short _asid, MemObject *mem) : cpuId(_cpuId), tid(_tid), lastActivate(0), lastSuspend(0), process(_process), asid(_asid), - funcExeInst(0), storeCondFailures(0) + microPC(0), nextMicroPC(1), funcExeInst(0), storeCondFailures(0) #endif { numInst = 0; diff --git a/src/cpu/thread_state.hh b/src/cpu/thread_state.hh index 14e033b7f..60353760c 100644 --- a/src/cpu/thread_state.hh +++ b/src/cpu/thread_state.hh @@ -200,6 +200,16 @@ struct ThreadState { */ TheISA::MachInst inst; + /** The current microcode pc for the currently executing macro + * operation. + */ + MicroPC microPC; + + /** The next microcode pc for the currently executing macro + * operation. + */ + MicroPC nextMicroPC; + public: /** * Temporary storage to pass the source address from copy_load to diff --git a/src/dev/alpha_console.cc b/src/dev/alpha_console.cc index 181bbf934..40868de51 100644 --- a/src/dev/alpha_console.cc +++ b/src/dev/alpha_console.cc @@ -48,6 +48,8 @@ #include "dev/platform.hh" #include "dev/simconsole.hh" #include "dev/simple_disk.hh" +#include "mem/packet.hh" +#include "mem/packet_access.hh" #include "mem/physical.hh" #include "sim/builder.hh" #include "sim/sim_object.hh" @@ -92,7 +94,7 @@ AlphaConsole::startup() } Tick -AlphaConsole::read(Packet *pkt) +AlphaConsole::read(PacketPtr pkt) { /** XXX Do we want to push the addr munging to a bus brige or something? So @@ -193,7 +195,7 @@ AlphaConsole::read(Packet *pkt) } Tick -AlphaConsole::write(Packet *pkt) +AlphaConsole::write(PacketPtr pkt) { assert(pkt->result == Packet::Unknown); assert(pkt->getAddr() >= pioAddr && pkt->getAddr() < pioAddr + pioSize); diff --git a/src/dev/alpha_console.hh b/src/dev/alpha_console.hh index b6360d40f..7d6d1e679 100644 --- a/src/dev/alpha_console.hh +++ b/src/dev/alpha_console.hh @@ -118,8 +118,8 @@ class AlphaConsole : public BasicPioDevice /** * memory mapped reads and writes */ - virtual Tick read(Packet *pkt); - virtual Tick write(Packet *pkt); + virtual Tick read(PacketPtr pkt); + virtual Tick write(PacketPtr pkt); /** * standard serialization routines for checkpointing diff --git a/src/dev/baddev.cc b/src/dev/baddev.cc index e4297be19..1bab93492 100644 --- a/src/dev/baddev.cc +++ b/src/dev/baddev.cc @@ -53,13 +53,13 @@ BadDevice::BadDevice(Params *p) } Tick -BadDevice::read(Packet *pkt) +BadDevice::read(PacketPtr pkt) { panic("Device %s not imlpmented\n", devname); } Tick -BadDevice::write(Packet *pkt) +BadDevice::write(PacketPtr pkt) { panic("Device %s not imlpmented\n", devname); } diff --git a/src/dev/baddev.hh b/src/dev/baddev.hh index d7d778af4..040fff8e5 100644 --- a/src/dev/baddev.hh +++ b/src/dev/baddev.hh @@ -67,8 +67,8 @@ class BadDevice : public BasicPioDevice */ BadDevice(Params *p); - virtual Tick read(Packet *pkt); - virtual Tick write(Packet *pkt); + virtual Tick read(PacketPtr pkt); + virtual Tick write(PacketPtr pkt); }; #endif // __DEV_BADDEV_HH__ diff --git a/src/dev/i8254xGBe.cc b/src/dev/i8254xGBe.cc index 77c731899..943e6881f 100644 --- a/src/dev/i8254xGBe.cc +++ b/src/dev/i8254xGBe.cc @@ -47,7 +47,7 @@ IGbE::IGbE(Params *p) Tick -IGbE::writeConfig(Packet *pkt) +IGbE::writeConfig(PacketPtr pkt) { int offset = pkt->getAddr() & PCI_CONFIG_SIZE; if (offset < PCI_DEVICE_SPECIFIC) @@ -63,7 +63,7 @@ IGbE::writeConfig(Packet *pkt) } Tick -IGbE::read(Packet *pkt) +IGbE::read(PacketPtr pkt) { int bar; Addr daddr; @@ -88,7 +88,7 @@ IGbE::read(Packet *pkt) } Tick -IGbE::write(Packet *pkt) +IGbE::write(PacketPtr pkt) { int bar; Addr daddr; diff --git a/src/dev/i8254xGBe.hh b/src/dev/i8254xGBe.hh index 88931eb6d..161d8befc 100644 --- a/src/dev/i8254xGBe.hh +++ b/src/dev/i8254xGBe.hh @@ -59,10 +59,10 @@ class IGbE : public PciDev IGbE(Params *params); ~IGbE() {;} - virtual Tick read(Packet *pkt); - virtual Tick write(Packet *pkt); + virtual Tick read(PacketPtr pkt); + virtual Tick write(PacketPtr pkt); - virtual Tick writeConfig(Packet *pkt); + virtual Tick writeConfig(PacketPtr pkt); bool ethRxPkt(EthPacketPtr packet); void ethTxDone(); diff --git a/src/dev/ide_ctrl.cc b/src/dev/ide_ctrl.cc index 8007fda5e..1afad529f 100644 --- a/src/dev/ide_ctrl.cc +++ b/src/dev/ide_ctrl.cc @@ -43,6 +43,7 @@ #include "dev/pcireg.h" #include "dev/platform.hh" #include "mem/packet.hh" +#include "mem/packet_access.hh" #include "sim/builder.hh" #include "sim/sim_object.hh" #include "sim/byteswap.hh" @@ -228,7 +229,7 @@ IdeController::setDmaComplete(IdeDisk *disk) //// Tick -IdeController::readConfig(Packet *pkt) +IdeController::readConfig(PacketPtr pkt) { int offset = pkt->getAddr() & PCI_CONFIG_SIZE; if (offset < PCI_DEVICE_SPECIFIC) @@ -301,7 +302,7 @@ IdeController::readConfig(Packet *pkt) Tick -IdeController::writeConfig(Packet *pkt) +IdeController::writeConfig(PacketPtr pkt) { int offset = pkt->getAddr() & PCI_CONFIG_SIZE; if (offset < PCI_DEVICE_SPECIFIC) { @@ -408,7 +409,7 @@ IdeController::writeConfig(Packet *pkt) Tick -IdeController::read(Packet *pkt) +IdeController::read(PacketPtr pkt) { Addr offset; IdeChannel channel; @@ -494,7 +495,7 @@ IdeController::read(Packet *pkt) } Tick -IdeController::write(Packet *pkt) +IdeController::write(PacketPtr pkt) { Addr offset; IdeChannel channel; diff --git a/src/dev/ide_ctrl.hh b/src/dev/ide_ctrl.hh index 5842d322e..291446d1c 100644 --- a/src/dev/ide_ctrl.hh +++ b/src/dev/ide_ctrl.hh @@ -204,8 +204,8 @@ class IdeController : public PciDev IdeController(Params *p); ~IdeController(); - virtual Tick writeConfig(Packet *pkt); - virtual Tick readConfig(Packet *pkt); + virtual Tick writeConfig(PacketPtr pkt); + virtual Tick readConfig(PacketPtr pkt); void setDmaComplete(IdeDisk *disk); @@ -214,14 +214,14 @@ class IdeController : public PciDev * @param pkt Packet describing what is to be read * @return The amount of time to complete this request */ - virtual Tick read(Packet *pkt); + virtual Tick read(PacketPtr pkt); /** * Write a done field for a given target. * @param pkt Packet describing what is to be written * @return The amount of time to complete this request */ - virtual Tick write(Packet *pkt); + virtual Tick write(PacketPtr pkt); /** * Serialize this object to the given output stream. diff --git a/src/dev/io_device.cc b/src/dev/io_device.cc index 408d8de3e..9671d77cc 100644 --- a/src/dev/io_device.cc +++ b/src/dev/io_device.cc @@ -42,7 +42,7 @@ PioPort::PioPort(PioDevice *dev, System *s, std::string pname) Tick -PioPort::recvAtomic(Packet *pkt) +PioPort::recvAtomic(PacketPtr pkt) { return pkt->isRead() ? device->read(pkt) : device->write(pkt); } @@ -97,7 +97,7 @@ DmaPort::DmaPort(DmaDevice *dev, System *s) { } bool -DmaPort::recvTiming(Packet *pkt) +DmaPort::recvTiming(PacketPtr pkt) { @@ -165,7 +165,7 @@ DmaPort::drain(Event *de) void DmaPort::recvRetry() { - Packet* pkt = transmitList.front(); + PacketPtr pkt = transmitList.front(); bool result = true; while (result && transmitList.size()) { DPRINTF(DMA, "Retry on Packet %#x with senderState: %#x\n", @@ -194,7 +194,7 @@ DmaPort::dmaAction(Packet::Command cmd, Addr addr, int size, Event *event, for (ChunkGenerator gen(addr, size, peerBlockSize()); !gen.done(); gen.next()) { Request *req = new Request(gen.addr(), gen.size(), 0); - Packet *pkt = new Packet(req, cmd, Packet::Broadcast); + PacketPtr pkt = new Packet(req, cmd, Packet::Broadcast); // Increment the data pointer on a write if (data) @@ -211,7 +211,7 @@ DmaPort::dmaAction(Packet::Command cmd, Addr addr, int size, Event *event, void -DmaPort::sendDma(Packet *pkt, bool front) +DmaPort::sendDma(PacketPtr pkt, bool front) { // some kind of selction between access methods // more work is going to have to be done to make diff --git a/src/dev/io_device.hh b/src/dev/io_device.hh index 24e822a40..aa242d170 100644 --- a/src/dev/io_device.hh +++ b/src/dev/io_device.hh @@ -33,9 +33,9 @@ #define __DEV_IO_DEVICE_HH__ #include "mem/mem_object.hh" -#include "mem/packet_impl.hh" -#include "sim/sim_object.hh" +#include "mem/packet.hh" #include "mem/tport.hh" +#include "sim/sim_object.hh" class Event; class Platform; @@ -56,7 +56,7 @@ class PioPort : public SimpleTimingPort /** The device that this port serves. */ PioDevice *device; - virtual Tick recvAtomic(Packet *pkt); + virtual Tick recvAtomic(PacketPtr pkt); virtual void getDeviceAddressRanges(AddrRangeList &resp, AddrRangeList &snoop); @@ -91,7 +91,7 @@ class DmaPort : public Port }; DmaDevice *device; - std::list<Packet*> transmitList; + std::list<PacketPtr> transmitList; /** The system that device/port are in. This is used to select which mode * we are currently operating in. */ @@ -107,10 +107,10 @@ class DmaPort : public Port * here.*/ Event *drainEvent; - virtual bool recvTiming(Packet *pkt); - virtual Tick recvAtomic(Packet *pkt) + virtual bool recvTiming(PacketPtr pkt); + virtual Tick recvAtomic(PacketPtr pkt) { panic("dma port shouldn't be used for pio access."); } - virtual void recvFunctional(Packet *pkt) + virtual void recvFunctional(PacketPtr pkt) { panic("dma port shouldn't be used for pio access."); } virtual void recvStatusChange(Status status) @@ -122,7 +122,7 @@ class DmaPort : public Port AddrRangeList &snoop) { resp.clear(); snoop.clear(); } - void sendDma(Packet *pkt, bool front = false); + void sendDma(PacketPtr pkt, bool front = false); public: DmaPort(DmaDevice *dev, System *s); @@ -163,14 +163,14 @@ class PioDevice : public MemObject * @param pkt Packet describing this request * @return number of ticks it took to complete */ - virtual Tick read(Packet *pkt) = 0; + virtual Tick read(PacketPtr pkt) = 0; /** Pure virtual function that the device must implement. Called when a * write command is recieved by the port. * @param pkt Packet describing this request * @return number of ticks it took to complete */ - virtual Tick write(Packet *pkt) = 0; + virtual Tick write(PacketPtr pkt) = 0; public: /** Params struct which is extended through each device based on diff --git a/src/dev/isa_fake.cc b/src/dev/isa_fake.cc index 9622f015c..23761cd10 100644 --- a/src/dev/isa_fake.cc +++ b/src/dev/isa_fake.cc @@ -40,6 +40,7 @@ #include "base/trace.hh" #include "dev/isa_fake.hh" #include "mem/packet.hh" +#include "mem/packet_access.hh" #include "sim/builder.hh" #include "sim/system.hh" @@ -52,7 +53,7 @@ IsaFake::IsaFake(Params *p) } Tick -IsaFake::read(Packet *pkt) +IsaFake::read(PacketPtr pkt) { assert(pkt->result == Packet::Unknown); assert(pkt->getAddr() >= pioAddr && pkt->getAddr() < pioAddr + pioSize); @@ -60,6 +61,7 @@ IsaFake::read(Packet *pkt) DPRINTF(Tsunami, "read va=%#x size=%d\n", pkt->getAddr(), pkt->getSize()); switch (pkt->getSize()) { + case sizeof(uint64_t): pkt->set(0xFFFFFFFFFFFFFFFFULL); break; case sizeof(uint32_t): @@ -79,7 +81,7 @@ IsaFake::read(Packet *pkt) } Tick -IsaFake::write(Packet *pkt) +IsaFake::write(PacketPtr pkt) { DPRINTF(Tsunami, "write - va=%#x size=%d \n", pkt->getAddr(), pkt->getSize()); pkt->result = Packet::Success; diff --git a/src/dev/isa_fake.hh b/src/dev/isa_fake.hh index 5166882f8..366061c25 100644 --- a/src/dev/isa_fake.hh +++ b/src/dev/isa_fake.hh @@ -36,9 +36,10 @@ #ifndef __ISA_FAKE_HH__ #define __ISA_FAKE_HH__ -#include "dev/tsunami.hh" #include "base/range.hh" #include "dev/io_device.hh" +#include "dev/tsunami.hh" +#include "mem/packet.hh" /** * IsaFake is a device that returns -1 on all reads and @@ -68,14 +69,14 @@ class IsaFake : public BasicPioDevice * @param pkt The memory request. * @param data Where to put the data. */ - virtual Tick read(Packet *pkt); + virtual Tick read(PacketPtr pkt); /** * All writes are simply ignored. * @param pkt The memory request. * @param data the data to not write. */ - virtual Tick write(Packet *pkt); + virtual Tick write(PacketPtr pkt); }; #endif // __TSUNAMI_FAKE_HH__ diff --git a/src/dev/ns_gige.cc b/src/dev/ns_gige.cc index 704afcf7d..19c553d87 100644 --- a/src/dev/ns_gige.cc +++ b/src/dev/ns_gige.cc @@ -43,6 +43,7 @@ #include "dev/ns_gige.hh" #include "dev/pciconfigall.hh" #include "mem/packet.hh" +#include "mem/packet_access.hh" #include "sim/builder.hh" #include "sim/debug.hh" #include "sim/host.hh" @@ -466,7 +467,7 @@ NSGigE::regStats() * This is to write to the PCI general configuration registers */ Tick -NSGigE::writeConfig(Packet *pkt) +NSGigE::writeConfig(PacketPtr pkt) { int offset = pkt->getAddr() & PCI_CONFIG_SIZE; if (offset < PCI_DEVICE_SPECIFIC) @@ -494,7 +495,7 @@ NSGigE::writeConfig(Packet *pkt) * spec sheet */ Tick -NSGigE::read(Packet *pkt) +NSGigE::read(PacketPtr pkt) { assert(ioEnable); @@ -718,7 +719,7 @@ NSGigE::read(Packet *pkt) } Tick -NSGigE::write(Packet *pkt) +NSGigE::write(PacketPtr pkt) { assert(ioEnable); diff --git a/src/dev/ns_gige.hh b/src/dev/ns_gige.hh index 080c0b1f3..a40fe3b29 100644 --- a/src/dev/ns_gige.hh +++ b/src/dev/ns_gige.hh @@ -375,10 +375,10 @@ class NSGigE : public PciDev ~NSGigE(); const Params *params() const { return (const Params *)_params; } - virtual Tick writeConfig(Packet *pkt); + virtual Tick writeConfig(PacketPtr pkt); - virtual Tick read(Packet *pkt); - virtual Tick write(Packet *pkt); + virtual Tick read(PacketPtr pkt); + virtual Tick write(PacketPtr pkt); bool cpuIntrPending() const; void cpuIntrAck() { cpuIntrClear(); } diff --git a/src/dev/pciconfigall.cc b/src/dev/pciconfigall.cc index 68013eab8..39c8f0fa0 100644 --- a/src/dev/pciconfigall.cc +++ b/src/dev/pciconfigall.cc @@ -38,6 +38,7 @@ #include "dev/pcireg.h" #include "dev/platform.hh" #include "mem/packet.hh" +#include "mem/packet_access.hh" #include "sim/builder.hh" #include "sim/system.hh" @@ -51,7 +52,7 @@ PciConfigAll::PciConfigAll(Params *p) Tick -PciConfigAll::read(Packet *pkt) +PciConfigAll::read(PacketPtr pkt) { assert(pkt->result == Packet::Unknown); @@ -78,7 +79,7 @@ PciConfigAll::read(Packet *pkt) } Tick -PciConfigAll::write(Packet *pkt) +PciConfigAll::write(PacketPtr pkt) { assert(pkt->result == Packet::Unknown); panic("Attempting to write to config space on non-existant device\n"); diff --git a/src/dev/pciconfigall.hh b/src/dev/pciconfigall.hh index 07eaf8112..720a2f005 100644 --- a/src/dev/pciconfigall.hh +++ b/src/dev/pciconfigall.hh @@ -73,7 +73,7 @@ class PciConfigAll : public PioDevice * @param pkt Contains information about the read operation * @return Amount of time to do the read */ - virtual Tick read(Packet *pkt); + virtual Tick read(PacketPtr pkt); /** * Write to PCI config spcae. If the device does not exit the simulator @@ -83,7 +83,7 @@ class PciConfigAll : public PioDevice * @return Amount of time to do the read */ - virtual Tick write(Packet *pkt); + virtual Tick write(PacketPtr pkt); void addressRanges(AddrRangeList &range_list); diff --git a/src/dev/pcidev.cc b/src/dev/pcidev.cc index b16ddb31a..8c0d03817 100644 --- a/src/dev/pcidev.cc +++ b/src/dev/pcidev.cc @@ -47,6 +47,7 @@ #include "dev/pcidev.hh" #include "dev/tsunamireg.h" #include "mem/packet.hh" +#include "mem/packet_access.hh" #include "sim/builder.hh" #include "sim/byteswap.hh" #include "sim/param.hh" @@ -65,7 +66,7 @@ PciDev::PciConfigPort::PciConfigPort(PciDev *dev, int busid, int devid, Tick -PciDev::PciConfigPort::recvAtomic(Packet *pkt) +PciDev::PciConfigPort::recvAtomic(PacketPtr pkt) { assert(pkt->result == Packet::Unknown); assert(pkt->getAddr() >= configAddr && @@ -122,7 +123,7 @@ PciDev::drain(Event *de) } Tick -PciDev::readConfig(Packet *pkt) +PciDev::readConfig(PacketPtr pkt) { int offset = pkt->getAddr() & PCI_CONFIG_SIZE; if (offset >= PCI_DEVICE_SPECIFIC) @@ -171,7 +172,7 @@ PciDev::addressRanges(AddrRangeList &range_list) } Tick -PciDev::writeConfig(Packet *pkt) +PciDev::writeConfig(PacketPtr pkt) { int offset = pkt->getAddr() & PCI_CONFIG_SIZE; if (offset >= PCI_DEVICE_SPECIFIC) diff --git a/src/dev/pcidev.hh b/src/dev/pcidev.hh index 22dd6296e..fbfdbb65c 100644 --- a/src/dev/pcidev.hh +++ b/src/dev/pcidev.hh @@ -40,6 +40,7 @@ #include "dev/io_device.hh" #include "dev/pcireg.h" #include "dev/platform.hh" +#include "sim/byteswap.hh" #define BAR_IO_MASK 0x3 #define BAR_MEM_MASK 0xF @@ -83,7 +84,7 @@ class PciDev : public DmaDevice protected: PciDev *device; - virtual Tick recvAtomic(Packet *pkt); + virtual Tick recvAtomic(PacketPtr pkt); virtual void getDeviceAddressRanges(AddrRangeList &resp, AddrRangeList &snoop); @@ -201,7 +202,7 @@ class PciDev : public DmaDevice * for normal operations that it does not need to override. * @param pkt packet containing the write the offset into config space */ - virtual Tick writeConfig(Packet *pkt); + virtual Tick writeConfig(PacketPtr pkt); /** @@ -210,7 +211,7 @@ class PciDev : public DmaDevice * for normal operations that it does not need to override. * @param pkt packet containing the write the offset into config space */ - virtual Tick readConfig(Packet *pkt); + virtual Tick readConfig(PacketPtr pkt); public: Addr pciToDma(Addr pciAddr) const diff --git a/src/dev/sinic.cc b/src/dev/sinic.cc index 61fb3aa24..f61c161aa 100644 --- a/src/dev/sinic.cc +++ b/src/dev/sinic.cc @@ -38,6 +38,7 @@ #include "dev/etherlink.hh" #include "dev/sinic.hh" #include "mem/packet.hh" +#include "mem/packet_access.hh" #include "sim/builder.hh" #include "sim/debug.hh" #include "sim/eventq.hh" @@ -313,7 +314,7 @@ Device::prepareWrite(int cpu, int index) * I/O read of device register */ Tick -Device::read(Packet *pkt) +Device::read(PacketPtr pkt) { assert(config.command & PCI_CMD_MSE); assert(pkt->getAddr() >= BARAddrs[0] && pkt->getSize() < BARSize[0]); @@ -400,7 +401,7 @@ Device::iprRead(Addr daddr, int cpu, uint64_t &result) * I/O write of device register */ Tick -Device::write(Packet *pkt) +Device::write(PacketPtr pkt) { assert(config.command & PCI_CMD_MSE); assert(pkt->getAddr() >= BARAddrs[0] && pkt->getSize() < BARSize[0]); diff --git a/src/dev/sinic.hh b/src/dev/sinic.hh index eece4ba6b..3904c2a8a 100644 --- a/src/dev/sinic.hh +++ b/src/dev/sinic.hh @@ -264,8 +264,8 @@ class Device : public Base * Memory Interface */ public: - virtual Tick read(Packet *pkt); - virtual Tick write(Packet *pkt); + virtual Tick read(PacketPtr pkt); + virtual Tick write(PacketPtr pkt); virtual void resume(); void prepareIO(int cpu, int index); diff --git a/src/dev/tsunami_cchip.cc b/src/dev/tsunami_cchip.cc index 3feb7439f..74a68566c 100644 --- a/src/dev/tsunami_cchip.cc +++ b/src/dev/tsunami_cchip.cc @@ -39,12 +39,14 @@ #include "arch/alpha/ev5.hh" #include "base/trace.hh" +#include "cpu/intr_control.hh" +#include "cpu/thread_context.hh" +#include "dev/tsunami.hh" #include "dev/tsunami_cchip.hh" #include "dev/tsunamireg.h" -#include "dev/tsunami.hh" +#include "mem/packet.hh" +#include "mem/packet_access.hh" #include "mem/port.hh" -#include "cpu/thread_context.hh" -#include "cpu/intr_control.hh" #include "sim/builder.hh" #include "sim/system.hh" @@ -72,7 +74,7 @@ TsunamiCChip::TsunamiCChip(Params *p) } Tick -TsunamiCChip::read(Packet *pkt) +TsunamiCChip::read(PacketPtr pkt) { DPRINTF(Tsunami, "read va=%#x size=%d\n", pkt->getAddr(), pkt->getSize()); @@ -182,7 +184,7 @@ TsunamiCChip::read(Packet *pkt) } Tick -TsunamiCChip::write(Packet *pkt) +TsunamiCChip::write(PacketPtr pkt) { assert(pkt->getAddr() >= pioAddr && pkt->getAddr() < pioAddr + pioSize); Addr daddr = pkt->getAddr() - pioAddr; diff --git a/src/dev/tsunami_cchip.hh b/src/dev/tsunami_cchip.hh index ef43f621f..297a94129 100644 --- a/src/dev/tsunami_cchip.hh +++ b/src/dev/tsunami_cchip.hh @@ -94,9 +94,9 @@ class TsunamiCChip : public BasicPioDevice */ TsunamiCChip(Params *p); - virtual Tick read(Packet *pkt); + virtual Tick read(PacketPtr pkt); - virtual Tick write(Packet *pkt); + virtual Tick write(PacketPtr pkt); /** * post an RTC interrupt to the CPU diff --git a/src/dev/tsunami_io.cc b/src/dev/tsunami_io.cc index e3da10eb5..73af6c2ef 100644 --- a/src/dev/tsunami_io.cc +++ b/src/dev/tsunami_io.cc @@ -47,6 +47,8 @@ #include "dev/tsunami.hh" #include "dev/tsunami_io.hh" #include "dev/tsunamireg.h" +#include "mem/packet.hh" +#include "mem/packet_access.hh" #include "mem/port.hh" #include "sim/builder.hh" #include "sim/system.hh" @@ -446,7 +448,7 @@ TsunamiIO::frequency() const } Tick -TsunamiIO::read(Packet *pkt) +TsunamiIO::read(PacketPtr pkt) { assert(pkt->result == Packet::Unknown); assert(pkt->getAddr() >= pioAddr && pkt->getAddr() < pioAddr + pioSize); @@ -512,7 +514,7 @@ TsunamiIO::read(Packet *pkt) } Tick -TsunamiIO::write(Packet *pkt) +TsunamiIO::write(PacketPtr pkt) { assert(pkt->result == Packet::Unknown); assert(pkt->getAddr() >= pioAddr && pkt->getAddr() < pioAddr + pioSize); diff --git a/src/dev/tsunami_io.hh b/src/dev/tsunami_io.hh index 9084a1be8..5ea3628c1 100644 --- a/src/dev/tsunami_io.hh +++ b/src/dev/tsunami_io.hh @@ -328,8 +328,8 @@ class TsunamiIO : public BasicPioDevice */ TsunamiIO(Params *p); - virtual Tick read(Packet *pkt); - virtual Tick write(Packet *pkt); + virtual Tick read(PacketPtr pkt); + virtual Tick write(PacketPtr pkt); /** * Post an PIC interrupt to the CPU via the CChip diff --git a/src/dev/tsunami_pchip.cc b/src/dev/tsunami_pchip.cc index 8a542b9b0..549db1a50 100644 --- a/src/dev/tsunami_pchip.cc +++ b/src/dev/tsunami_pchip.cc @@ -42,6 +42,7 @@ #include "dev/tsunamireg.h" #include "dev/tsunami.hh" #include "mem/packet.hh" +#include "mem/packet_access.hh" #include "sim/builder.hh" #include "sim/system.hh" @@ -68,7 +69,7 @@ TsunamiPChip::TsunamiPChip(Params *p) } Tick -TsunamiPChip::read(Packet *pkt) +TsunamiPChip::read(PacketPtr pkt) { assert(pkt->result == Packet::Unknown); assert(pkt->getAddr() >= pioAddr && pkt->getAddr() < pioAddr + pioSize); @@ -150,7 +151,7 @@ TsunamiPChip::read(Packet *pkt) } Tick -TsunamiPChip::write(Packet *pkt) +TsunamiPChip::write(PacketPtr pkt) { assert(pkt->result == Packet::Unknown); assert(pkt->getAddr() >= pioAddr && pkt->getAddr() < pioAddr + pioSize); diff --git a/src/dev/tsunami_pchip.hh b/src/dev/tsunami_pchip.hh index 2c97a1fea..d0a9c3157 100644 --- a/src/dev/tsunami_pchip.hh +++ b/src/dev/tsunami_pchip.hh @@ -85,8 +85,8 @@ class TsunamiPChip : public BasicPioDevice Addr calcConfigAddr(int bus, int dev, int func); - virtual Tick read(Packet *pkt); - virtual Tick write(Packet *pkt); + virtual Tick read(PacketPtr pkt); + virtual Tick write(PacketPtr pkt); /** * Serialize this object to the given output stream. diff --git a/src/dev/uart8250.cc b/src/dev/uart8250.cc index b92527b5a..9051a26a2 100644 --- a/src/dev/uart8250.cc +++ b/src/dev/uart8250.cc @@ -42,6 +42,8 @@ #include "dev/simconsole.hh" #include "dev/uart8250.hh" #include "dev/platform.hh" +#include "mem/packet.hh" +#include "mem/packet_access.hh" #include "sim/builder.hh" using namespace std; @@ -110,7 +112,7 @@ Uart8250::Uart8250(Params *p) } Tick -Uart8250::read(Packet *pkt) +Uart8250::read(PacketPtr pkt) { assert(pkt->result == Packet::Unknown); assert(pkt->getAddr() >= pioAddr && pkt->getAddr() < pioAddr + pioSize); @@ -192,7 +194,7 @@ Uart8250::read(Packet *pkt) } Tick -Uart8250::write(Packet *pkt) +Uart8250::write(PacketPtr pkt) { assert(pkt->result == Packet::Unknown); diff --git a/src/dev/uart8250.hh b/src/dev/uart8250.hh index 44e90132f..2e768216a 100644 --- a/src/dev/uart8250.hh +++ b/src/dev/uart8250.hh @@ -82,8 +82,8 @@ class Uart8250 : public Uart public: Uart8250(Params *p); - virtual Tick read(Packet *pkt); - virtual Tick write(Packet *pkt); + virtual Tick read(PacketPtr pkt); + virtual Tick write(PacketPtr pkt); virtual void addressRanges(AddrRangeList &range_list); diff --git a/src/kern/linux/linux.hh b/src/kern/linux/linux.hh index 3a2677642..6e0b37d91 100644 --- a/src/kern/linux/linux.hh +++ b/src/kern/linux/linux.hh @@ -54,11 +54,11 @@ class Linux : public OperatingSystem //@{ /// Basic Linux types. -/* typedef uint64_t size_t; + typedef uint64_t size_t; typedef uint64_t off_t; typedef int64_t time_t; typedef uint32_t uid_t; - typedef uint32_t gid_t;*/ + typedef uint32_t gid_t; //@} /// Stat buffer. Note that we can't call it 'stat' since that diff --git a/src/kern/solaris/solaris.hh b/src/kern/solaris/solaris.hh index a5ca41cdd..ed574fdbf 100644 --- a/src/kern/solaris/solaris.hh +++ b/src/kern/solaris/solaris.hh @@ -56,7 +56,7 @@ class Solaris : public OperatingSystem //@{ /// Basic Solaris types. -/* typedef uint64_t size_t; + typedef uint64_t size_t; typedef uint64_t off_t; typedef int64_t time_t; typedef int32_t uid_t; @@ -65,7 +65,7 @@ class Solaris : public OperatingSystem typedef uint64_t ino_t; typedef uint64_t dev_t; typedef uint32_t mode_t; - typedef uint32_t nlink_t;*/ + typedef uint32_t nlink_t; //@} struct tgt_timespec { diff --git a/src/kern/tru64/tru64.hh b/src/kern/tru64/tru64.hh index 18671c364..6d6d0d96d 100644 --- a/src/kern/tru64/tru64.hh +++ b/src/kern/tru64/tru64.hh @@ -393,34 +393,6 @@ class Tru64 : public OperatingSystem uint64_t pad2[2]; //!< pad2 }; - /*/// Helper function to convert a host stat buffer to a target stat - /// buffer. Also copies the target buffer out to the simulated - /// memory space. Used by stat(), fstat(), and lstat(). - template <class T> - static void - copyOutStatBuf(TranslatingPort *mem, Addr addr, global_stat *host) - { - using namespace TheISA; - - TypedBufferArg<T> tgt(addr); - - tgt->st_dev = htog(host->st_dev); - tgt->st_ino = htog(host->st_ino); - tgt->st_mode = htog(host->st_mode); - tgt->st_nlink = htog(host->st_nlink); - tgt->st_uid = htog(host->st_uid); - tgt->st_gid = htog(host->st_gid); - tgt->st_rdev = htog(host->st_rdev); - tgt->st_size = htog(host->st_size); - tgt->st_atimeX = htog(host->st_atime); - tgt->st_mtimeX = htog(host->st_mtime); - tgt->st_ctimeX = htog(host->st_ctime); - tgt->st_blksize = htog(host->st_blksize); - tgt->st_blocks = htog(host->st_blocks); - - tgt.copyOut(mem); - }*/ - /// Helper function to convert a host statfs buffer to a target statfs /// buffer. Also copies the target buffer out to the simulated /// memory space. Used by statfs() and fstatfs(). @@ -450,34 +422,6 @@ class Tru64 : public OperatingSystem tgt.copyOut(mem); } -/* /// Helper function to convert a host stat buffer to an old pre-F64 - /// (4.x) target stat buffer. Also copies the target buffer out to - /// the simulated memory space. Used by pre_F64_stat(), - /// pre_F64_fstat(), and pre_F64_lstat(). - static void - copyOutPreF64StatBuf(TranslatingPort *mem, Addr addr, struct stat *host) - { - using namespace TheISA; - - TypedBufferArg<Tru64::pre_F64_stat> tgt(addr); - - tgt->st_dev = htog(host->st_dev); - tgt->st_ino = htog(host->st_ino); - tgt->st_mode = htog(host->st_mode); - tgt->st_nlink = htog(host->st_nlink); - tgt->st_uid = htog(host->st_uid); - tgt->st_gid = htog(host->st_gid); - tgt->st_rdev = htog(host->st_rdev); - tgt->st_size = htog(host->st_size); - tgt->st_atimeX = htog(host->st_atime); - tgt->st_mtimeX = htog(host->st_mtime); - tgt->st_ctimeX = htog(host->st_ctime); - tgt->st_blksize = htog(host->st_blksize); - tgt->st_blocks = htog(host->st_blocks); - - tgt.copyOut(mem); - }*/ - /// The target system's hostname. static const char *hostname; @@ -600,12 +544,19 @@ class Tru64 : public OperatingSystem process->next_thread_stack_base -= stack_size; } - stack_base = roundDown(stack_base, VMPageSize); + Addr rounded_stack_base = roundDown(stack_base, VMPageSize); + Addr rounded_stack_size = roundUp(stack_size, VMPageSize); + + DPRINTF(SyscallVerbose, + "stack_create: allocating stack @ %#x size %#x " + "(rounded from %#x, %#x)\n", + rounded_stack_base, rounded_stack_size, + stack_base, stack_size); // map memory - process->pTable->allocate(stack_base, roundUp(stack_size, VMPageSize)); + process->pTable->allocate(rounded_stack_base, rounded_stack_size); - argp->address = gtoh(stack_base); + argp->address = gtoh(rounded_stack_base); argp.copyOut(tc->getMemPort()); return 0; diff --git a/src/mem/bridge.cc b/src/mem/bridge.cc index b181dd583..38dcfd2e8 100644 --- a/src/mem/bridge.cc +++ b/src/mem/bridge.cc @@ -89,7 +89,7 @@ Bridge::init() /** Function called by the port when the bus is receiving a Timing * transaction.*/ bool -Bridge::BridgePort::recvTiming(Packet *pkt) +Bridge::BridgePort::recvTiming(PacketPtr pkt) { DPRINTF(BusBridge, "recvTiming: src %d dest %d addr 0x%x\n", pkt->getSrc(), pkt->getDest(), pkt->getAddr()); @@ -99,7 +99,7 @@ Bridge::BridgePort::recvTiming(Packet *pkt) bool -Bridge::BridgePort::queueForSendTiming(Packet *pkt) +Bridge::BridgePort::queueForSendTiming(PacketPtr pkt) { if (queueFull()) return false; @@ -148,7 +148,7 @@ Bridge::BridgePort::trySend() assert(buf->ready <= curTick); - Packet *pkt = buf->pkt; + PacketPtr pkt = buf->pkt; DPRINTF(BusBridge, "trySend: origSrc %d dest %d addr 0x%x\n", buf->origSrc, pkt->getDest(), pkt->getAddr()); @@ -198,7 +198,7 @@ Bridge::BridgePort::recvRetry() /** Function called by the port when the bus is receiving a Atomic * transaction.*/ Tick -Bridge::BridgePort::recvAtomic(Packet *pkt) +Bridge::BridgePort::recvAtomic(PacketPtr pkt) { return otherPort->sendAtomic(pkt) + delay; } @@ -206,7 +206,7 @@ Bridge::BridgePort::recvAtomic(Packet *pkt) /** Function called by the port when the bus is receiving a Functional * transaction.*/ void -Bridge::BridgePort::recvFunctional(Packet *pkt) +Bridge::BridgePort::recvFunctional(PacketPtr pkt) { std::list<PacketBuffer*>::iterator i; bool pktContinue = true; diff --git a/src/mem/bridge.hh b/src/mem/bridge.hh index 2ab9799c7..f7d0d12d0 100644 --- a/src/mem/bridge.hh +++ b/src/mem/bridge.hh @@ -70,12 +70,12 @@ class Bridge : public MemObject public: Tick ready; - Packet *pkt; + PacketPtr pkt; Packet::SenderState *origSenderState; short origSrc; bool expectResponse; - PacketBuffer(Packet *_pkt, Tick t) + PacketBuffer(PacketPtr _pkt, Tick t) : ready(t), pkt(_pkt), origSenderState(_pkt->senderState), origSrc(_pkt->getSrc()), expectResponse(_pkt->needsResponse()) @@ -84,7 +84,7 @@ class Bridge : public MemObject pkt->senderState = this; } - void fixResponse(Packet *pkt) + void fixResponse(PacketPtr pkt) { assert(pkt->senderState == this); pkt->setDest(origSrc); @@ -109,7 +109,7 @@ class Bridge : public MemObject */ bool queueFull() { return (sendQueue.size() == queueLimit); } - bool queueForSendTiming(Packet *pkt); + bool queueForSendTiming(PacketPtr pkt); void finishSend(PacketBuffer *buf); @@ -146,7 +146,7 @@ class Bridge : public MemObject /** When receiving a timing request from the peer port, pass it to the bridge. */ - virtual bool recvTiming(Packet *pkt); + virtual bool recvTiming(PacketPtr pkt); /** When receiving a retry request from the peer port, pass it to the bridge. */ @@ -154,11 +154,11 @@ class Bridge : public MemObject /** When receiving a Atomic requestfrom the peer port, pass it to the bridge. */ - virtual Tick recvAtomic(Packet *pkt); + virtual Tick recvAtomic(PacketPtr pkt); /** When receiving a Functional request from the peer port, pass it to the bridge. */ - virtual void recvFunctional(Packet *pkt); + virtual void recvFunctional(PacketPtr pkt); /** When receiving a status changefrom the peer port, pass it to the bridge. */ diff --git a/src/mem/bus.cc b/src/mem/bus.cc index b11b6de58..86a148f87 100644 --- a/src/mem/bus.cc +++ b/src/mem/bus.cc @@ -138,7 +138,7 @@ void Bus::occupyBus(PacketPtr pkt) /** Function called by the port when the bus is receiving a Timing * transaction.*/ bool -Bus::recvTiming(Packet *pkt) +Bus::recvTiming(PacketPtr pkt) { Port *port; DPRINTF(Bus, "recvTiming: packet src %d dest %d addr 0x%x cmd %s\n", @@ -160,9 +160,12 @@ Bus::recvTiming(Packet *pkt) short dest = pkt->getDest(); if (dest == Packet::Broadcast) { if (timingSnoop(pkt)) { + bool success; + pkt->flags |= SNOOP_COMMIT; - bool success = timingSnoop(pkt); + success = timingSnoop(pkt); assert(success); + if (pkt->flags & SATISFIED) { //Cache-Cache transfer occuring if (inRetry) { @@ -298,7 +301,7 @@ Bus::findSnoopPorts(Addr addr, int id) } Tick -Bus::atomicSnoop(Packet *pkt) +Bus::atomicSnoop(PacketPtr pkt) { std::vector<int> ports = findSnoopPorts(pkt->getAddr(), pkt->getSrc()); Tick response_time = 0; @@ -316,7 +319,7 @@ Bus::atomicSnoop(Packet *pkt) } void -Bus::functionalSnoop(Packet *pkt) +Bus::functionalSnoop(PacketPtr pkt) { std::vector<int> ports = findSnoopPorts(pkt->getAddr(), pkt->getSrc()); @@ -328,7 +331,7 @@ Bus::functionalSnoop(Packet *pkt) } bool -Bus::timingSnoop(Packet *pkt) +Bus::timingSnoop(PacketPtr pkt) { std::vector<int> ports = findSnoopPorts(pkt->getAddr(), pkt->getSrc()); bool success = true; @@ -346,7 +349,7 @@ Bus::timingSnoop(Packet *pkt) /** Function called by the port when the bus is receiving a Atomic * transaction.*/ Tick -Bus::recvAtomic(Packet *pkt) +Bus::recvAtomic(PacketPtr pkt) { DPRINTF(Bus, "recvAtomic: packet src %d dest %d addr 0x%x cmd %s\n", pkt->getSrc(), pkt->getDest(), pkt->getAddr(), pkt->cmdString()); @@ -361,7 +364,7 @@ Bus::recvAtomic(Packet *pkt) /** Function called by the port when the bus is receiving a Functional * transaction.*/ void -Bus::recvFunctional(Packet *pkt) +Bus::recvFunctional(PacketPtr pkt) { DPRINTF(Bus, "recvFunctional: packet src %d dest %d addr 0x%x cmd %s\n", pkt->getSrc(), pkt->getDest(), pkt->getAddr(), pkt->cmdString()); diff --git a/src/mem/bus.hh b/src/mem/bus.hh index 509b8cf9b..9fb33b7c3 100644 --- a/src/mem/bus.hh +++ b/src/mem/bus.hh @@ -71,15 +71,15 @@ class Bus : public MemObject /** Function called by the port when the bus is recieving a Timing transaction.*/ - bool recvTiming(Packet *pkt); + bool recvTiming(PacketPtr pkt); /** Function called by the port when the bus is recieving a Atomic transaction.*/ - Tick recvAtomic(Packet *pkt); + Tick recvAtomic(PacketPtr pkt); /** Function called by the port when the bus is recieving a Functional transaction.*/ - void recvFunctional(Packet *pkt); + void recvFunctional(PacketPtr pkt); /** Timing function called by port when it is once again able to process * requests. */ @@ -107,16 +107,16 @@ class Bus : public MemObject std::vector<int> findSnoopPorts(Addr addr, int id); /** Snoop all relevant ports atomicly. */ - Tick atomicSnoop(Packet *pkt); + Tick atomicSnoop(PacketPtr pkt); /** Snoop all relevant ports functionally. */ - void functionalSnoop(Packet *pkt); + void functionalSnoop(PacketPtr pkt); /** Call snoop on caches, be sure to set SNOOP_COMMIT bit if you want * the snoop to happen * @return True if succeds. */ - bool timingSnoop(Packet *pkt); + bool timingSnoop(PacketPtr pkt); /** Process address range request. * @param resp addresses that we can respond to @@ -157,17 +157,17 @@ class Bus : public MemObject /** When reciving a timing request from the peer port (at id), pass it to the bus. */ - virtual bool recvTiming(Packet *pkt) + virtual bool recvTiming(PacketPtr pkt) { pkt->setSrc(id); return bus->recvTiming(pkt); } /** When reciving a Atomic requestfrom the peer port (at id), pass it to the bus. */ - virtual Tick recvAtomic(Packet *pkt) + virtual Tick recvAtomic(PacketPtr pkt) { pkt->setSrc(id); return bus->recvAtomic(pkt); } /** When reciving a Functional requestfrom the peer port (at id), pass it to the bus. */ - virtual void recvFunctional(Packet *pkt) + virtual void recvFunctional(PacketPtr pkt) { pkt->setSrc(id); bus->recvFunctional(pkt); } /** When reciving a status changefrom the peer port (at id), diff --git a/src/mem/cache/base_cache.cc b/src/mem/cache/base_cache.cc index 51b4ed55e..0694aae6e 100644 --- a/src/mem/cache/base_cache.cc +++ b/src/mem/cache/base_cache.cc @@ -33,11 +33,10 @@ * Definition of BaseCache functions. */ +#include "cpu/base.hh" +#include "cpu/smt.hh" #include "mem/cache/base_cache.hh" #include "mem/cache/miss/mshr.hh" -#include "mem/packet_impl.hh" -#include "cpu/smt.hh" -#include "cpu/base.hh" using namespace std; @@ -72,7 +71,7 @@ BaseCache::CachePort::deviceBlockSize() } bool -BaseCache::CachePort::recvTiming(Packet *pkt) +BaseCache::CachePort::recvTiming(PacketPtr pkt) { if (isCpuSide && !pkt->req->isUncacheable() @@ -100,48 +99,23 @@ BaseCache::CachePort::recvTiming(Packet *pkt) } Tick -BaseCache::CachePort::recvAtomic(Packet *pkt) +BaseCache::CachePort::recvAtomic(PacketPtr pkt) { return cache->doAtomicAccess(pkt, isCpuSide); } void -BaseCache::CachePort::recvFunctional(Packet *pkt) +BaseCache::CachePort::recvFunctional(PacketPtr pkt) { //Check storage here first - list<Packet *>::iterator i = drainList.begin(); - list<Packet *>::iterator end = drainList.end(); + list<PacketPtr>::iterator i = drainList.begin(); + list<PacketPtr>::iterator end = drainList.end(); for (; i != end; ++i) { - Packet * target = *i; + PacketPtr target = *i; // If the target contains data, and it overlaps the // probed request, need to update data if (target->intersect(pkt)) { - uint8_t* pkt_data; - uint8_t* write_data; - int data_size; - if (target->getAddr() < pkt->getAddr()) { - int offset = pkt->getAddr() - target->getAddr(); - pkt_data = pkt->getPtr<uint8_t>(); - write_data = target->getPtr<uint8_t>() + offset; - data_size = target->getSize() - offset; - assert(data_size > 0); - if (data_size > pkt->getSize()) - data_size = pkt->getSize(); - } else { - int offset = target->getAddr() - pkt->getAddr(); - pkt_data = pkt->getPtr<uint8_t>() + offset; - write_data = target->getPtr<uint8_t>(); - data_size = pkt->getSize() - offset; - assert(data_size > pkt->getSize()); - if (data_size > target->getSize()) - data_size = target->getSize(); - } - - if (pkt->isWrite()) { - memcpy(pkt_data, write_data, data_size); - } else { - memcpy(write_data, pkt_data, data_size); - } + fixPacket(pkt, target); } } cache->doFunctionalAccess(pkt, isCpuSide); @@ -150,7 +124,7 @@ BaseCache::CachePort::recvFunctional(Packet *pkt) void BaseCache::CachePort::recvRetry() { - Packet *pkt; + PacketPtr pkt; assert(waitingOnRetry); if (!drainList.empty()) { DPRINTF(CachePort, "%s attempting to send a retry for response\n", name()); @@ -182,7 +156,7 @@ BaseCache::CachePort::recvRetry() pkt = cache->getPacket(); MSHR* mshr = (MSHR*) pkt->senderState; //Copy the packet, it may be modified/destroyed elsewhere - Packet * copyPkt = new Packet(*pkt); + PacketPtr copyPkt = new Packet(*pkt); copyPkt->dataStatic<uint8_t>(pkt->getPtr<uint8_t>()); mshr->pkt = copyPkt; @@ -258,7 +232,7 @@ BaseCache::CacheEvent::CacheEvent(CachePort *_cachePort) pkt = NULL; } -BaseCache::CacheEvent::CacheEvent(CachePort *_cachePort, Packet *_pkt) +BaseCache::CacheEvent::CacheEvent(CachePort *_cachePort, PacketPtr _pkt) : Event(&mainEventQueue, CPU_Tick_Pri), cachePort(_cachePort), pkt(_pkt) { this->setFlags(AutoDelete); @@ -302,7 +276,7 @@ BaseCache::CacheEvent::process() pkt = cachePort->cache->getPacket(); MSHR* mshr = (MSHR*) pkt->senderState; //Copy the packet, it may be modified/destroyed elsewhere - Packet * copyPkt = new Packet(*pkt); + PacketPtr copyPkt = new Packet(*pkt); copyPkt->dataStatic<uint8_t>(pkt->getPtr<uint8_t>()); mshr->pkt = copyPkt; @@ -332,7 +306,7 @@ BaseCache::CacheEvent::process() pkt = cachePort->cache->getCoherencePacket(); MSHR* cshr = (MSHR*) pkt->senderState; bool success = cachePort->sendTiming(pkt); - cachePort->cache->sendResult(pkt, cshr, success); + cachePort->cache->sendCoherenceResult(pkt, cshr, success); cachePort->waitingOnRetry = !success; if (cachePort->waitingOnRetry) DPRINTF(CachePort, "%s now waiting on a retry\n", cachePort->name()); diff --git a/src/mem/cache/base_cache.hh b/src/mem/cache/base_cache.hh index 93830b04f..565280aef 100644 --- a/src/mem/cache/base_cache.hh +++ b/src/mem/cache/base_cache.hh @@ -85,11 +85,11 @@ class BaseCache : public MemObject CachePort(const std::string &_name, BaseCache *_cache, bool _isCpuSide); protected: - virtual bool recvTiming(Packet *pkt); + virtual bool recvTiming(PacketPtr pkt); - virtual Tick recvAtomic(Packet *pkt); + virtual Tick recvAtomic(PacketPtr pkt); - virtual void recvFunctional(Packet *pkt); + virtual void recvFunctional(PacketPtr pkt); virtual void recvStatusChange(Status status); @@ -113,23 +113,25 @@ class BaseCache : public MemObject bool waitingOnRetry; - std::list<Packet *> drainList; + std::list<PacketPtr> drainList; }; struct CacheEvent : public Event { CachePort *cachePort; - Packet *pkt; + PacketPtr pkt; CacheEvent(CachePort *_cachePort); - CacheEvent(CachePort *_cachePort, Packet *_pkt); + CacheEvent(CachePort *_cachePort, PacketPtr _pkt); void process(); const char *description(); }; - protected: + public: //Made public so coherence can get at it. CachePort *cpuSidePort; + + protected: CachePort *memSidePort; bool snoopRangesSent; @@ -139,17 +141,17 @@ class BaseCache : public MemObject private: //To be defined in cache_impl.hh not in base class - virtual bool doTimingAccess(Packet *pkt, CachePort *cachePort, bool isCpuSide) + virtual bool doTimingAccess(PacketPtr pkt, CachePort *cachePort, bool isCpuSide) { fatal("No implementation"); } - virtual Tick doAtomicAccess(Packet *pkt, bool isCpuSide) + virtual Tick doAtomicAccess(PacketPtr pkt, bool isCpuSide) { fatal("No implementation"); } - virtual void doFunctionalAccess(Packet *pkt, bool isCpuSide) + virtual void doFunctionalAccess(PacketPtr pkt, bool isCpuSide) { fatal("No implementation"); } @@ -170,23 +172,23 @@ class BaseCache : public MemObject } } - virtual Packet *getPacket() + virtual PacketPtr getPacket() { fatal("No implementation"); } - virtual Packet *getCoherencePacket() + virtual PacketPtr getCoherencePacket() { fatal("No implementation"); } - virtual void sendResult(Packet* &pkt, MSHR* mshr, bool success) + virtual void sendResult(PacketPtr &pkt, MSHR* mshr, bool success) { fatal("No implementation"); } - virtual void sendCoherenceResult(Packet* &pkt, MSHR* mshr, bool success) + virtual void sendCoherenceResult(PacketPtr &pkt, MSHR* mshr, bool success) { fatal("No implementation"); @@ -517,7 +519,7 @@ class BaseCache : public MemObject * @param pkt The request being responded to. * @param time The time the response is ready. */ - void respond(Packet *pkt, Tick time) + void respond(PacketPtr pkt, Tick time) { if (pkt->needsResponse()) { CacheEvent *reqCpu = new CacheEvent(cpuSidePort, pkt); @@ -537,7 +539,7 @@ class BaseCache : public MemObject * @param pkt The request to respond to. * @param time The time the response is ready. */ - void respondToMiss(Packet *pkt, Tick time) + void respondToMiss(PacketPtr pkt, Tick time) { if (!pkt->req->isUncacheable()) { missLatency[pkt->cmdToIndex()][0/*pkt->req->getThreadNum()*/] += time - pkt->time; @@ -559,7 +561,7 @@ class BaseCache : public MemObject * Suppliess the data if cache to cache transfers are enabled. * @param pkt The bus transaction to fulfill. */ - void respondToSnoop(Packet *pkt, Tick time) + void respondToSnoop(PacketPtr pkt, Tick time) { assert (pkt->needsResponse()); CacheEvent *reqMem = new CacheEvent(memSidePort, pkt); diff --git a/src/mem/cache/cache.hh b/src/mem/cache/cache.hh index 07d9d6336..1f3b087bb 100644 --- a/src/mem/cache/cache.hh +++ b/src/mem/cache/cache.hh @@ -96,7 +96,7 @@ class Cache : public BaseCache * A permanent mem req to always be used to cause invalidations. * Used to append to target list, to cause an invalidation. */ - Packet * invalidatePkt; + PacketPtr invalidatePkt; Request *invalidateReq; public: @@ -127,12 +127,12 @@ class Cache : public BaseCache /** Instantiates a basic cache object. */ Cache(const std::string &_name, Params ¶ms); - virtual bool doTimingAccess(Packet *pkt, CachePort *cachePort, + virtual bool doTimingAccess(PacketPtr pkt, CachePort *cachePort, bool isCpuSide); - virtual Tick doAtomicAccess(Packet *pkt, bool isCpuSide); + virtual Tick doAtomicAccess(PacketPtr pkt, bool isCpuSide); - virtual void doFunctionalAccess(Packet *pkt, bool isCpuSide); + virtual void doFunctionalAccess(PacketPtr pkt, bool isCpuSide); virtual void recvStatusChange(Port::Status status, bool isCpuSide); @@ -143,47 +143,47 @@ class Cache : public BaseCache * @param pkt The request to perform. * @return The result of the access. */ - bool access(Packet * &pkt); + bool access(PacketPtr &pkt); /** * Selects a request to send on the bus. * @return The memory request to service. */ - virtual Packet * getPacket(); + virtual PacketPtr getPacket(); /** * Was the request was sent successfully? * @param pkt The request. * @param success True if the request was sent successfully. */ - virtual void sendResult(Packet * &pkt, MSHR* mshr, bool success); + virtual void sendResult(PacketPtr &pkt, MSHR* mshr, bool success); /** * Was the CSHR request was sent successfully? * @param pkt The request. * @param success True if the request was sent successfully. */ - virtual void sendCoherenceResult(Packet * &pkt, MSHR* cshr, bool success); + virtual void sendCoherenceResult(PacketPtr &pkt, MSHR* cshr, bool success); /** * Handles a response (cache line fill/write ack) from the bus. * @param pkt The request being responded to. */ - void handleResponse(Packet * &pkt); + void handleResponse(PacketPtr &pkt); /** * Selects a coherence message to forward to lower levels of the hierarchy. * @return The coherence message to forward. */ - virtual Packet * getCoherencePacket(); + virtual PacketPtr getCoherencePacket(); /** * Snoops bus transactions to maintain coherence. * @param pkt The current bus transaction. */ - void snoop(Packet * &pkt); + void snoop(PacketPtr &pkt); - void snoopResponse(Packet * &pkt); + void snoopResponse(PacketPtr &pkt); /** * Invalidates the block containing address if found. @@ -224,7 +224,7 @@ class Cache : public BaseCache * request. * @return The estimated completion time. */ - Tick probe(Packet * &pkt, bool update, CachePort * otherSidePort); + Tick probe(PacketPtr &pkt, bool update, CachePort * otherSidePort); /** * Snoop for the provided request in the cache and return the estimated @@ -235,7 +235,7 @@ class Cache : public BaseCache * request. * @return The estimated completion time. */ - Tick snoopProbe(Packet * &pkt); + Tick snoopProbe(PacketPtr &pkt); }; #endif // __CACHE_HH__ diff --git a/src/mem/cache/cache_blk.hh b/src/mem/cache/cache_blk.hh index 078c82d82..7b999e4b1 100644 --- a/src/mem/cache/cache_blk.hh +++ b/src/mem/cache/cache_blk.hh @@ -35,8 +35,11 @@ #ifndef __CACHE_BLK_HH__ #define __CACHE_BLK_HH__ +#include <list> + #include "sim/root.hh" // for Tick #include "arch/isa_traits.hh" // for Addr +#include "mem/request.hh" /** * Cache block status bit assignments @@ -96,6 +99,35 @@ class CacheBlk /** Number of references to this block since it was brought in. */ int refCount; + protected: + /** + * Represents that the indicated thread context has a "lock" on + * the block, in the LL/SC sense. + */ + class Lock { + public: + int cpuNum; // locking CPU + int threadNum; // locking thread ID within CPU + + // check for matching execution context + bool matchesContext(Request *req) + { + return (cpuNum == req->getCpuNum() && + threadNum == req->getThreadNum()); + } + + Lock(Request *req) + : cpuNum(req->getCpuNum()), threadNum(req->getThreadNum()) + { + } + }; + + /** List of thread contexts that have performed a load-locked (LL) + * on the block since the last store. */ + std::list<Lock> lockList; + + public: + CacheBlk() : asid(-1), tag(0), data(0) ,size(0), status(0), whenReady(0), set(-1), refCount(0) @@ -175,7 +207,58 @@ class CacheBlk return (status & BlkHWPrefetched) != 0; } + /** + * Track the fact that a local locked was issued to the block. If + * multiple LLs get issued from the same context we could have + * redundant records on the list, but that's OK, as they'll all + * get blown away at the next store. + */ + void trackLoadLocked(Request *req) + { + assert(req->isLocked()); + lockList.push_front(Lock(req)); + } + + /** + * Clear the list of valid load locks. Should be called whenever + * block is written to or invalidated. + */ + void clearLoadLocks() { lockList.clear(); } + /** + * Handle interaction of load-locked operations and stores. + * @return True if write should proceed, false otherwise. Returns + * false only in the case of a failed store conditional. + */ + bool checkWrite(Request *req) + { + if (req->isLocked()) { + // it's a store conditional... have to check for matching + // load locked. + bool success = false; + + for (std::list<Lock>::iterator i = lockList.begin(); + i != lockList.end(); ++i) + { + if (i->matchesContext(req)) { + // it's a store conditional, and as far as the memory + // system can tell, the requesting context's lock is + // still valid. + success = true; + break; + } + } + + req->setScResult(success ? 1 : 0); + clearLoadLocks(); + return success; + } else { + // for *all* stores (conditional or otherwise) we have to + // clear the list of load-locks as they're all invalid now. + clearLoadLocks(); + return true; + } + } }; #endif //__CACHE_BLK_HH__ diff --git a/src/mem/cache/cache_impl.hh b/src/mem/cache/cache_impl.hh index 520e5abb5..3c47762f6 100644 --- a/src/mem/cache/cache_impl.hh +++ b/src/mem/cache/cache_impl.hh @@ -56,7 +56,7 @@ template<class TagStore, class Buffering, class Coherence> bool Cache<TagStore,Buffering,Coherence>:: -doTimingAccess(Packet *pkt, CachePort *cachePort, bool isCpuSide) +doTimingAccess(PacketPtr pkt, CachePort *cachePort, bool isCpuSide) { if (isCpuSide) { @@ -82,15 +82,10 @@ doTimingAccess(Packet *pkt, CachePort *cachePort, bool isCpuSide) template<class TagStore, class Buffering, class Coherence> Tick Cache<TagStore,Buffering,Coherence>:: -doAtomicAccess(Packet *pkt, bool isCpuSide) +doAtomicAccess(PacketPtr pkt, bool isCpuSide) { if (isCpuSide) { - //Temporary solution to LL/SC - if (pkt->isWrite() && (pkt->req->isLocked())) { - pkt->req->setScResult(1); - } - probe(pkt, true, NULL); //TEMP ALWAYS SUCCES FOR NOW pkt->result = Packet::Success; @@ -109,18 +104,13 @@ doAtomicAccess(Packet *pkt, bool isCpuSide) template<class TagStore, class Buffering, class Coherence> void Cache<TagStore,Buffering,Coherence>:: -doFunctionalAccess(Packet *pkt, bool isCpuSide) +doFunctionalAccess(PacketPtr pkt, bool isCpuSide) { if (isCpuSide) { //TEMP USE CPU?THREAD 0 0 pkt->req->setThreadContext(0,0); - //Temporary solution to LL/SC - if (pkt->isWrite() && (pkt->req->isLocked())) { - assert("Can't handle LL/SC on functional path\n"); - } - probe(pkt, false, memSidePort); //TEMP ALWAYS SUCCESFUL FOR NOW pkt->result = Packet::Success; @@ -241,18 +231,26 @@ Cache<TagStore,Buffering,Coherence>::access(PacketPtr &pkt) exitSimLoop("A cache reached the maximum miss count"); } } - missQueue->handleMiss(pkt, size, curTick + hitLatency); -// return MA_CACHE_MISS; + + if (pkt->flags & SATISFIED) { + // happens when a store conditional fails because it missed + // the cache completely + if (pkt->needsResponse()) + respond(pkt, curTick+lat); + } else { + missQueue->handleMiss(pkt, size, curTick + hitLatency); + } + return true; } template<class TagStore, class Buffering, class Coherence> -Packet * +PacketPtr Cache<TagStore,Buffering,Coherence>::getPacket() { assert(missQueue->havePending()); - Packet * pkt = missQueue->getPacket(); + PacketPtr pkt = missQueue->getPacket(); if (pkt) { if (!pkt->req->isUncacheable()) { if (pkt->cmd == Packet::HardPFReq) @@ -316,7 +314,7 @@ Cache<TagStore,Buffering,Coherence>::sendResult(PacketPtr &pkt, MSHR* mshr, template<class TagStore, class Buffering, class Coherence> void -Cache<TagStore,Buffering,Coherence>::handleResponse(Packet * &pkt) +Cache<TagStore,Buffering,Coherence>::handleResponse(PacketPtr &pkt) { BlkType *blk = NULL; if (pkt->senderState) { @@ -358,7 +356,7 @@ Cache<TagStore,Buffering,Coherence>::handleResponse(Packet * &pkt) } template<class TagStore, class Buffering, class Coherence> -Packet * +PacketPtr Cache<TagStore,Buffering,Coherence>::getCoherencePacket() { return coherence->getPacket(); @@ -366,7 +364,7 @@ Cache<TagStore,Buffering,Coherence>::getCoherencePacket() template<class TagStore, class Buffering, class Coherence> void -Cache<TagStore,Buffering,Coherence>::sendCoherenceResult(Packet* &pkt, +Cache<TagStore,Buffering,Coherence>::sendCoherenceResult(PacketPtr &pkt, MSHR *cshr, bool success) { @@ -376,17 +374,22 @@ Cache<TagStore,Buffering,Coherence>::sendCoherenceResult(Packet* &pkt, template<class TagStore, class Buffering, class Coherence> void -Cache<TagStore,Buffering,Coherence>::snoop(Packet * &pkt) +Cache<TagStore,Buffering,Coherence>::snoop(PacketPtr &pkt) { if (pkt->req->isUncacheable()) { //Can't get a hit on an uncacheable address //Revisit this for multi level coherence return; } + + //Send a timing (true) invalidate up if the protocol calls for it + coherence->propogateInvalidate(pkt, true); + Addr blk_addr = pkt->getAddr() & ~(Addr(blkSize-1)); BlkType *blk = tags->findBlock(pkt); MSHR *mshr = missQueue->findMSHR(blk_addr); - if (coherence->hasProtocol()) { //@todo Move this into handle bus req + if (coherence->hasProtocol() || pkt->isInvalidate()) { + //@todo Move this into handle bus req //If we find an mshr, and it is in service, we need to NACK or //invalidate if (mshr) { @@ -490,7 +493,7 @@ Cache<TagStore,Buffering,Coherence>::snoop(Packet * &pkt) template<class TagStore, class Buffering, class Coherence> void -Cache<TagStore,Buffering,Coherence>::snoopResponse(Packet * &pkt) +Cache<TagStore,Buffering,Coherence>::snoopResponse(PacketPtr &pkt) { //Need to handle the response, if NACKED if (pkt->flags & NACKED_LINE) { @@ -520,7 +523,7 @@ Cache<TagStore,Buffering,Coherence>::invalidateBlk(Addr addr) */ template<class TagStore, class Buffering, class Coherence> Tick -Cache<TagStore,Buffering,Coherence>::probe(Packet * &pkt, bool update, +Cache<TagStore,Buffering,Coherence>::probe(PacketPtr &pkt, bool update, CachePort* otherSidePort) { // MemDebug::cacheProbe(pkt); @@ -536,6 +539,13 @@ Cache<TagStore,Buffering,Coherence>::probe(Packet * &pkt, bool update, } } + if (!update && (pkt->isWrite() || (otherSidePort == cpuSidePort))) { + // Still need to change data in all locations. + otherSidePort->sendFunctional(pkt); + if (pkt->isRead() && pkt->result == Packet::Success) + return 0; + } + PacketList writebacks; int lat; BlkType *blk = tags->handleAccess(pkt, lat, writebacks, update); @@ -544,179 +554,127 @@ Cache<TagStore,Buffering,Coherence>::probe(Packet * &pkt, bool update, pkt->getAddr() & (((ULL(1))<<48)-1), (blk) ? "hit" : "miss", pkt->getAddr() & ~((Addr)blkSize - 1)); - if (!blk) { - // Need to check for outstanding misses and writes - Addr blk_addr = pkt->getAddr() & ~(blkSize - 1); - - // There can only be one matching outstanding miss. - MSHR* mshr = missQueue->findMSHR(blk_addr); - - // There can be many matching outstanding writes. - std::vector<MSHR*> writes; - missQueue->findWrites(blk_addr, writes); - - if (!update) { - otherSidePort->sendFunctional(pkt); - - // Check for data in MSHR and writebuffer. - if (mshr) { - warn("Found outstanding miss on an non-update probe"); - MSHR::TargetList *targets = mshr->getTargetList(); - MSHR::TargetList::iterator i = targets->begin(); - MSHR::TargetList::iterator end = targets->end(); - for (; i != end; ++i) { - Packet * target = *i; - // If the target contains data, and it overlaps the - // probed request, need to update data - if (target->isWrite() && target->intersect(pkt)) { - uint8_t* pkt_data; - uint8_t* write_data; - int data_size; - if (target->getAddr() < pkt->getAddr()) { - int offset = pkt->getAddr() - target->getAddr(); - pkt_data = pkt->getPtr<uint8_t>(); - write_data = target->getPtr<uint8_t>() + offset; - data_size = target->getSize() - offset; - assert(data_size > 0); - if (data_size > pkt->getSize()) - data_size = pkt->getSize(); - } else { - int offset = target->getAddr() - pkt->getAddr(); - pkt_data = pkt->getPtr<uint8_t>() + offset; - write_data = target->getPtr<uint8_t>(); - data_size = pkt->getSize() - offset; - assert(data_size > pkt->getSize()); - if (data_size > target->getSize()) - data_size = target->getSize(); - } - - if (pkt->isWrite()) { - memcpy(pkt_data, write_data, data_size); - } else { - memcpy(write_data, pkt_data, data_size); - } - } - } - } - for (int i = 0; i < writes.size(); ++i) { - Packet * write = writes[i]->pkt; - if (write->intersect(pkt)) { - warn("Found outstanding write on an non-update probe"); - uint8_t* pkt_data; - uint8_t* write_data; - int data_size; - if (write->getAddr() < pkt->getAddr()) { - int offset = pkt->getAddr() - write->getAddr(); - pkt_data = pkt->getPtr<uint8_t>(); - write_data = write->getPtr<uint8_t>() + offset; - data_size = write->getSize() - offset; - assert(data_size > 0); - if (data_size > pkt->getSize()) - data_size = pkt->getSize(); - } else { - int offset = write->getAddr() - pkt->getAddr(); - pkt_data = pkt->getPtr<uint8_t>() + offset; - write_data = write->getPtr<uint8_t>(); - data_size = pkt->getSize() - offset; - assert(data_size > pkt->getSize()); - if (data_size > write->getSize()) - data_size = write->getSize(); - } - if (pkt->isWrite()) { - memcpy(pkt_data, write_data, data_size); - } else { - memcpy(write_data, pkt_data, data_size); - } + // Need to check for outstanding misses and writes + Addr blk_addr = pkt->getAddr() & ~(blkSize - 1); + // There can only be one matching outstanding miss. + MSHR* mshr = missQueue->findMSHR(blk_addr); + + // There can be many matching outstanding writes. + std::vector<MSHR*> writes; + missQueue->findWrites(blk_addr, writes); + + if (!update) { + // Check for data in MSHR and writebuffer. + if (mshr) { + MSHR::TargetList *targets = mshr->getTargetList(); + MSHR::TargetList::iterator i = targets->begin(); + MSHR::TargetList::iterator end = targets->end(); + for (; i != end; ++i) { + PacketPtr target = *i; + // If the target contains data, and it overlaps the + // probed request, need to update data + if (target->intersect(pkt)) { + fixPacket(pkt, target); } } - return 0; - } else { - // update the cache state and statistics - if (mshr || !writes.empty()){ - // Can't handle it, return pktuest unsatisfied. - panic("Atomic access ran into outstanding MSHR's or WB's!"); + } + for (int i = 0; i < writes.size(); ++i) { + PacketPtr write = writes[i]->pkt; + if (write->intersect(pkt)) { + fixPacket(pkt, write); } - if (!pkt->req->isUncacheable()) { + } + if (pkt->isRead() + && pkt->result != Packet::Success + && otherSidePort == memSidePort) { + otherSidePort->sendFunctional(pkt); + assert(pkt->result == Packet::Success); + } + return 0; + } else if (!blk && !(pkt->flags & SATISFIED)) { + // update the cache state and statistics + if (mshr || !writes.empty()){ + // Can't handle it, return pktuest unsatisfied. + panic("Atomic access ran into outstanding MSHR's or WB's!"); + } + if (!pkt->req->isUncacheable()) { // Fetch the cache block to fill - BlkType *blk = tags->findBlock(pkt); - Packet::Command temp_cmd = coherence->getBusCmd(pkt->cmd, - (blk)? blk->status : 0); + BlkType *blk = tags->findBlock(pkt); + Packet::Command temp_cmd = coherence->getBusCmd(pkt->cmd, + (blk)? blk->status : 0); - Packet * busPkt = new Packet(pkt->req,temp_cmd, -1, blkSize); + PacketPtr busPkt = new Packet(pkt->req,temp_cmd, -1, blkSize); - busPkt->allocate(); + busPkt->allocate(); - busPkt->time = curTick; + busPkt->time = curTick; - DPRINTF(Cache, "Sending a atomic %s for %x blk_addr: %x\n", - busPkt->cmdString(), - busPkt->getAddr() & (((ULL(1))<<48)-1), - busPkt->getAddr() & ~((Addr)blkSize - 1)); + DPRINTF(Cache, "Sending a atomic %s for %x blk_addr: %x\n", + busPkt->cmdString(), + busPkt->getAddr() & (((ULL(1))<<48)-1), + busPkt->getAddr() & ~((Addr)blkSize - 1)); - lat = memSidePort->sendAtomic(busPkt); + lat = memSidePort->sendAtomic(busPkt); - //Be sure to flip the response to a request for coherence - if (busPkt->needsResponse()) { - busPkt->makeAtomicResponse(); - } + //Be sure to flip the response to a request for coherence + if (busPkt->needsResponse()) { + busPkt->makeAtomicResponse(); + } /* if (!(busPkt->flags & SATISFIED)) { - // blocked at a higher level, just return - return 0; - } +// blocked at a higher level, just return +return 0; +} */ misses[pkt->cmdToIndex()][0/*pkt->req->getThreadNum()*/]++; - CacheBlk::State old_state = (blk) ? blk->status : 0; - CacheBlk::State new_state = - coherence->getNewState(busPkt, old_state); - DPRINTF(Cache, + CacheBlk::State old_state = (blk) ? blk->status : 0; + CacheBlk::State new_state = + coherence->getNewState(busPkt, old_state); + DPRINTF(Cache, "Receive response:%s for blk addr %x in state %i\n", - busPkt->cmdString(), - busPkt->getAddr() & (((ULL(1))<<48)-1), old_state); - if (old_state != new_state) + busPkt->cmdString(), + busPkt->getAddr() & (((ULL(1))<<48)-1), old_state); + if (old_state != new_state) DPRINTF(Cache, "Block for blk addr %x moving from " "state %i to %i\n", busPkt->getAddr() & (((ULL(1))<<48)-1), old_state, new_state); - tags->handleFill(blk, busPkt, - new_state, - writebacks, pkt); - //Free the packet - delete busPkt; - - // Handle writebacks if needed - while (!writebacks.empty()){ - Packet *wbPkt = writebacks.front(); - memSidePort->sendAtomic(wbPkt); - writebacks.pop_front(); - delete wbPkt; - } - return lat + hitLatency; - } else { - return memSidePort->sendAtomic(pkt); + tags->handleFill(blk, busPkt, + new_state, + writebacks, pkt); + //Free the packet + delete busPkt; + + // Handle writebacks if needed + while (!writebacks.empty()){ + PacketPtr wbPkt = writebacks.front(); + memSidePort->sendAtomic(wbPkt); + writebacks.pop_front(); + delete wbPkt; } + return lat + hitLatency; + } else { + return memSidePort->sendAtomic(pkt); } } else { - // There was a cache hit. - // Handle writebacks if needed - while (!writebacks.empty()){ - memSidePort->sendAtomic(writebacks.front()); - writebacks.pop_front(); - } + if (blk) { + // There was a cache hit. + // Handle writebacks if needed + while (!writebacks.empty()){ + memSidePort->sendAtomic(writebacks.front()); + writebacks.pop_front(); + } - if (update) { hits[pkt->cmdToIndex()][0/*pkt->req->getThreadNum()*/]++; - } else if (pkt->isWrite()) { - // Still need to change data in all locations. - otherSidePort->sendFunctional(pkt); } + return hitLatency; } - fatal("Probe not handled.\n"); + return 0; } @@ -724,24 +682,27 @@ template<class TagStore, class Buffering, class Coherence> Tick Cache<TagStore,Buffering,Coherence>::snoopProbe(PacketPtr &pkt) { - Addr blk_addr = pkt->getAddr() & ~(Addr(blkSize-1)); - BlkType *blk = tags->findBlock(pkt); - MSHR *mshr = missQueue->findMSHR(blk_addr); - CacheBlk::State new_state = 0; - bool satisfy = coherence->handleBusRequest(pkt,blk,mshr, new_state); - if (satisfy) { - DPRINTF(Cache, "Cache snooped a %s request for addr %x and " - "now supplying data, new state is %i\n", - pkt->cmdString(), blk_addr, new_state); + //Send a atomic (false) invalidate up if the protocol calls for it + coherence->propogateInvalidate(pkt, false); + + Addr blk_addr = pkt->getAddr() & ~(Addr(blkSize-1)); + BlkType *blk = tags->findBlock(pkt); + MSHR *mshr = missQueue->findMSHR(blk_addr); + CacheBlk::State new_state = 0; + bool satisfy = coherence->handleBusRequest(pkt,blk,mshr, new_state); + if (satisfy) { + DPRINTF(Cache, "Cache snooped a %s request for addr %x and " + "now supplying data, new state is %i\n", + pkt->cmdString(), blk_addr, new_state); tags->handleSnoop(blk, new_state, pkt); return hitLatency; - } - if (blk) - DPRINTF(Cache, "Cache snooped a %s request for addr %x, " - "new state is %i\n", + } + if (blk) + DPRINTF(Cache, "Cache snooped a %s request for addr %x, " + "new state is %i\n", pkt->cmdString(), blk_addr, new_state); - tags->handleSnoop(blk, new_state); - return 0; + tags->handleSnoop(blk, new_state); + return 0; } diff --git a/src/mem/cache/coherence/coherence_protocol.cc b/src/mem/cache/coherence/coherence_protocol.cc index e28dda3dc..3d7721805 100644 --- a/src/mem/cache/coherence/coherence_protocol.cc +++ b/src/mem/cache/coherence/coherence_protocol.cc @@ -192,7 +192,7 @@ CoherenceProtocol::regStats() bool -CoherenceProtocol::invalidateTrans(BaseCache *cache, Packet * &pkt, +CoherenceProtocol::invalidateTrans(BaseCache *cache, PacketPtr &pkt, CacheBlk *blk, MSHR *mshr, CacheBlk::State & new_state) { @@ -203,18 +203,17 @@ CoherenceProtocol::invalidateTrans(BaseCache *cache, Packet * &pkt, bool -CoherenceProtocol::supplyTrans(BaseCache *cache, Packet * &pkt, +CoherenceProtocol::supplyTrans(BaseCache *cache, PacketPtr &pkt, CacheBlk *blk, MSHR *mshr, - CacheBlk::State & new_state - ) + CacheBlk::State & new_state) { return true; } bool -CoherenceProtocol::supplyAndGotoSharedTrans(BaseCache *cache, Packet * &pkt, +CoherenceProtocol::supplyAndGotoSharedTrans(BaseCache *cache, PacketPtr &pkt, CacheBlk *blk, MSHR *mshr, CacheBlk::State & new_state) @@ -226,7 +225,7 @@ CoherenceProtocol::supplyAndGotoSharedTrans(BaseCache *cache, Packet * &pkt, bool -CoherenceProtocol::supplyAndGotoOwnedTrans(BaseCache *cache, Packet * &pkt, +CoherenceProtocol::supplyAndGotoOwnedTrans(BaseCache *cache, PacketPtr &pkt, CacheBlk *blk, MSHR *mshr, CacheBlk::State & new_state) @@ -238,7 +237,7 @@ CoherenceProtocol::supplyAndGotoOwnedTrans(BaseCache *cache, Packet * &pkt, bool -CoherenceProtocol::supplyAndInvalidateTrans(BaseCache *cache, Packet * &pkt, +CoherenceProtocol::supplyAndInvalidateTrans(BaseCache *cache, PacketPtr &pkt, CacheBlk *blk, MSHR *mshr, CacheBlk::State & new_state) @@ -248,7 +247,7 @@ CoherenceProtocol::supplyAndInvalidateTrans(BaseCache *cache, Packet * &pkt, } bool -CoherenceProtocol::assertShared(BaseCache *cache, Packet * &pkt, +CoherenceProtocol::assertShared(BaseCache *cache, PacketPtr &pkt, CacheBlk *blk, MSHR *mshr, CacheBlk::State & new_state) @@ -263,182 +262,106 @@ CoherenceProtocol::CoherenceProtocol(const string &name, const bool doUpgrades) : SimObject(name) { - if ((protocol == "mosi" || protocol == "moesi") && !doUpgrades) { - cerr << "CoherenceProtocol: ownership protocols require upgrade transactions" - << "(write miss on owned block generates ReadExcl, which will clobber dirty block)" - << endl; - fatal(""); + // Python should catch this, but in case it doesn't... + if (!(protocol == "msi" || protocol == "mesi" || + protocol == "mosi" || protocol == "moesi")) { + fatal("CoherenceProtocol: unrecognized protocol %s\n", protocol); } - Packet::Command writeToSharedCmd = doUpgrades ? Packet::UpgradeReq : Packet::ReadExReq; - Packet::Command writeToSharedResp = doUpgrades ? Packet::UpgradeReq : Packet::ReadExResp; - -//@todo add in hardware prefetch to this list - if (protocol == "msi") { - // incoming requests: specify outgoing bus request - transitionTable[Invalid][Packet::ReadReq].onRequest(Packet::ReadReq); - transitionTable[Invalid][Packet::WriteReq].onRequest(Packet::ReadExReq); - transitionTable[Shared][Packet::WriteReq].onRequest(writeToSharedCmd); - //Prefetching causes a read - transitionTable[Invalid][Packet::SoftPFReq].onRequest(Packet::ReadReq); - transitionTable[Invalid][Packet::HardPFReq].onRequest(Packet::ReadReq); - - // on response to given request: specify new state - transitionTable[Invalid][Packet::ReadResp].onResponse(Shared); - transitionTable[Invalid][Packet::ReadExResp].onResponse(Modified); - transitionTable[Shared][writeToSharedResp].onResponse(Modified); - - // bus snoop transition functions - transitionTable[Invalid][Packet::ReadReq].onSnoop(nullTransition); - transitionTable[Invalid][Packet::ReadExReq].onSnoop(nullTransition); - transitionTable[Shared][Packet::ReadReq].onSnoop(nullTransition); - transitionTable[Shared][Packet::ReadExReq].onSnoop(invalidateTrans); - transitionTable[Modified][Packet::ReadExReq].onSnoop(supplyAndInvalidateTrans); - transitionTable[Modified][Packet::ReadReq].onSnoop(supplyAndGotoSharedTrans); - //Tansitions on seeing a DMA (writeInv(samelevel) or DMAInv) - transitionTable[Invalid][Packet::InvalidateReq].onSnoop(invalidateTrans); - transitionTable[Shared][Packet::InvalidateReq].onSnoop(invalidateTrans); - transitionTable[Modified][Packet::InvalidateReq].onSnoop(invalidateTrans); - transitionTable[Invalid][Packet::WriteInvalidateReq].onSnoop(invalidateTrans); - transitionTable[Shared][Packet::WriteInvalidateReq].onSnoop(invalidateTrans); - transitionTable[Modified][Packet::WriteInvalidateReq].onSnoop(invalidateTrans); - - if (doUpgrades) { - transitionTable[Invalid][Packet::UpgradeReq].onSnoop(nullTransition); - transitionTable[Shared][Packet::UpgradeReq].onSnoop(invalidateTrans); - } + bool hasOwned = (protocol == "mosi" || protocol == "moesi"); + bool hasExclusive = (protocol == "mesi" || protocol == "moesi"); + + if (hasOwned && !doUpgrades) { + fatal("CoherenceProtocol: ownership protocols require upgrade " + "transactions\n(write miss on owned block generates ReadExcl, " + "which will clobber dirty block)\n"); } - else if(protocol == "mesi") { - // incoming requests: specify outgoing bus request - transitionTable[Invalid][Packet::ReadReq].onRequest(Packet::ReadReq); - transitionTable[Invalid][Packet::WriteReq].onRequest(Packet::ReadExReq); - transitionTable[Shared][Packet::WriteReq].onRequest(writeToSharedCmd); - //Prefetching causes a read - transitionTable[Invalid][Packet::SoftPFReq].onRequest(Packet::ReadReq); - transitionTable[Invalid][Packet::HardPFReq].onRequest(Packet::ReadReq); - - // on response to given request: specify new state - transitionTable[Invalid][Packet::ReadResp].onResponse(Exclusive); - //It will move into shared if the shared line is asserted in the - //getNewState function - transitionTable[Invalid][Packet::ReadExResp].onResponse(Modified); - transitionTable[Shared][writeToSharedResp].onResponse(Modified); - - // bus snoop transition functions - transitionTable[Invalid][Packet::ReadReq].onSnoop(nullTransition); - transitionTable[Invalid][Packet::ReadExReq].onSnoop(nullTransition); - transitionTable[Shared][Packet::ReadReq].onSnoop(assertShared); - transitionTable[Shared][Packet::ReadExReq].onSnoop(invalidateTrans); - transitionTable[Exclusive][Packet::ReadReq].onSnoop(assertShared); - transitionTable[Exclusive][Packet::ReadExReq].onSnoop(invalidateTrans); - transitionTable[Modified][Packet::ReadExReq].onSnoop(supplyAndInvalidateTrans); - transitionTable[Modified][Packet::ReadReq].onSnoop(supplyAndGotoSharedTrans); - //Tansitions on seeing a DMA (writeInv(samelevel) or DMAInv) - transitionTable[Invalid][Packet::InvalidateReq].onSnoop(invalidateTrans); - transitionTable[Shared][Packet::InvalidateReq].onSnoop(invalidateTrans); - transitionTable[Modified][Packet::InvalidateReq].onSnoop(invalidateTrans); - transitionTable[Exclusive][Packet::InvalidateReq].onSnoop(invalidateTrans); - transitionTable[Invalid][Packet::WriteInvalidateReq].onSnoop(invalidateTrans); - transitionTable[Shared][Packet::WriteInvalidateReq].onSnoop(invalidateTrans); - transitionTable[Modified][Packet::WriteInvalidateReq].onSnoop(invalidateTrans); - transitionTable[Exclusive][Packet::WriteInvalidateReq].onSnoop(invalidateTrans); - - if (doUpgrades) { - transitionTable[Invalid][Packet::UpgradeReq].onSnoop(nullTransition); - transitionTable[Shared][Packet::UpgradeReq].onSnoop(invalidateTrans); - } + // set up a few shortcuts to save typing & visual clutter + typedef Packet P; + StateTransition (&tt)[stateMax+1][NUM_MEM_CMDS] = transitionTable; + + P::Command writeToSharedCmd = doUpgrades ? P::UpgradeReq : P::ReadExReq; + P::Command writeToSharedResp = doUpgrades ? P::UpgradeReq : P::ReadExResp; + + // Note that all transitions by default cause a panic. + // Override the valid transitions with the appropriate actions here. + + // + // ----- incoming requests: specify outgoing bus request ----- + // + tt[Invalid][P::ReadReq].onRequest(P::ReadReq); + // we only support write allocate right now + tt[Invalid][P::WriteReq].onRequest(P::ReadExReq); + tt[Shared][P::WriteReq].onRequest(writeToSharedCmd); + if (hasOwned) { + tt[Owned][P::WriteReq].onRequest(writeToSharedCmd); } - else if(protocol == "mosi") { - // incoming requests: specify outgoing bus request - transitionTable[Invalid][Packet::ReadReq].onRequest(Packet::ReadReq); - transitionTable[Invalid][Packet::WriteReq].onRequest(Packet::ReadExReq); - transitionTable[Shared][Packet::WriteReq].onRequest(writeToSharedCmd); - transitionTable[Owned][Packet::WriteReq].onRequest(writeToSharedCmd); - //Prefetching causes a read - transitionTable[Invalid][Packet::SoftPFReq].onRequest(Packet::ReadReq); - transitionTable[Invalid][Packet::HardPFReq].onRequest(Packet::ReadReq); - - // on response to given request: specify new state - transitionTable[Invalid][Packet::ReadResp].onResponse(Shared); - transitionTable[Invalid][Packet::ReadExResp].onResponse(Modified); - transitionTable[Shared][writeToSharedResp].onResponse(Modified); - transitionTable[Owned][writeToSharedResp].onResponse(Modified); - - // bus snoop transition functions - transitionTable[Invalid][Packet::ReadReq].onSnoop(nullTransition); - transitionTable[Invalid][Packet::ReadExReq].onSnoop(nullTransition); - transitionTable[Invalid][Packet::UpgradeReq].onSnoop(nullTransition); - transitionTable[Shared][Packet::ReadReq].onSnoop(assertShared); - transitionTable[Shared][Packet::ReadExReq].onSnoop(invalidateTrans); - transitionTable[Shared][Packet::UpgradeReq].onSnoop(invalidateTrans); - transitionTable[Modified][Packet::ReadExReq].onSnoop(supplyAndInvalidateTrans); - transitionTable[Modified][Packet::ReadReq].onSnoop(supplyAndGotoOwnedTrans); - transitionTable[Owned][Packet::ReadReq].onSnoop(supplyAndGotoOwnedTrans); - transitionTable[Owned][Packet::ReadExReq].onSnoop(supplyAndInvalidateTrans); - transitionTable[Owned][Packet::UpgradeReq].onSnoop(invalidateTrans); - //Tansitions on seeing a DMA (writeInv(samelevel) or DMAInv) - transitionTable[Invalid][Packet::InvalidateReq].onSnoop(invalidateTrans); - transitionTable[Shared][Packet::InvalidateReq].onSnoop(invalidateTrans); - transitionTable[Modified][Packet::InvalidateReq].onSnoop(invalidateTrans); - transitionTable[Owned][Packet::InvalidateReq].onSnoop(invalidateTrans); - transitionTable[Invalid][Packet::WriteInvalidateReq].onSnoop(invalidateTrans); - transitionTable[Shared][Packet::WriteInvalidateReq].onSnoop(invalidateTrans); - transitionTable[Modified][Packet::WriteInvalidateReq].onSnoop(invalidateTrans); - transitionTable[Owned][Packet::WriteInvalidateReq].onSnoop(invalidateTrans); + // Prefetching causes a read + tt[Invalid][P::SoftPFReq].onRequest(P::ReadReq); + tt[Invalid][P::HardPFReq].onRequest(P::ReadReq); + + // + // ----- on response to given request: specify new state ----- + // + tt[Invalid][P::ReadExResp].onResponse(Modified); + tt[Shared][writeToSharedResp].onResponse(Modified); + // Go to Exclusive state on read response if we have one (will + // move into shared if the shared line is asserted in the + // getNewState function) + // + // originally had this as: + // tt[Invalid][P::ReadResp].onResponse(hasExclusive ? Exclusive: Shared); + // ...but for some reason that caused a link error... + if (hasExclusive) { + tt[Invalid][P::ReadResp].onResponse(Exclusive); + } else { + tt[Invalid][P::ReadResp].onResponse(Shared); + } + if (hasOwned) { + tt[Owned][writeToSharedResp].onResponse(Modified); } - else if(protocol == "moesi") { - // incoming requests: specify outgoing bus request - transitionTable[Invalid][Packet::ReadReq].onRequest(Packet::ReadReq); - transitionTable[Invalid][Packet::WriteReq].onRequest(Packet::ReadExReq); - transitionTable[Shared][Packet::WriteReq].onRequest(writeToSharedCmd); - transitionTable[Owned][Packet::WriteReq].onRequest(writeToSharedCmd); - //Prefetching causes a read - transitionTable[Invalid][Packet::SoftPFReq].onRequest(Packet::ReadReq); - transitionTable[Invalid][Packet::HardPFReq].onRequest(Packet::ReadReq); - - // on response to given request: specify new state - transitionTable[Invalid][Packet::ReadResp].onResponse(Exclusive); - //It will move into shared if the shared line is asserted in the - //getNewState function - transitionTable[Invalid][Packet::ReadExResp].onResponse(Modified); - transitionTable[Shared][writeToSharedResp].onResponse(Modified); - transitionTable[Owned][writeToSharedResp].onResponse(Modified); - - // bus snoop transition functions - transitionTable[Invalid][Packet::ReadReq].onSnoop(nullTransition); - transitionTable[Invalid][Packet::ReadExReq].onSnoop(nullTransition); - transitionTable[Invalid][Packet::UpgradeReq].onSnoop(nullTransition); - transitionTable[Shared][Packet::ReadReq].onSnoop(assertShared); - transitionTable[Shared][Packet::ReadExReq].onSnoop(invalidateTrans); - transitionTable[Shared][Packet::UpgradeReq].onSnoop(invalidateTrans); - transitionTable[Exclusive][Packet::ReadReq].onSnoop(assertShared); - transitionTable[Exclusive][Packet::ReadExReq].onSnoop(invalidateTrans); - transitionTable[Modified][Packet::ReadReq].onSnoop(supplyAndGotoOwnedTrans); - transitionTable[Modified][Packet::ReadExReq].onSnoop(supplyAndInvalidateTrans); - transitionTable[Owned][Packet::ReadReq].onSnoop(supplyAndGotoOwnedTrans); - transitionTable[Owned][Packet::ReadExReq].onSnoop(supplyAndInvalidateTrans); - transitionTable[Owned][Packet::UpgradeReq].onSnoop(invalidateTrans); - //Transitions on seeing a DMA (writeInv(samelevel) or DMAInv) - transitionTable[Invalid][Packet::InvalidateReq].onSnoop(invalidateTrans); - transitionTable[Shared][Packet::InvalidateReq].onSnoop(invalidateTrans); - transitionTable[Exclusive][Packet::InvalidateReq].onSnoop(invalidateTrans); - transitionTable[Modified][Packet::InvalidateReq].onSnoop(invalidateTrans); - transitionTable[Owned][Packet::InvalidateReq].onSnoop(invalidateTrans); - transitionTable[Invalid][Packet::WriteInvalidateReq].onSnoop(invalidateTrans); - transitionTable[Shared][Packet::WriteInvalidateReq].onSnoop(invalidateTrans); - transitionTable[Exclusive][Packet::WriteInvalidateReq].onSnoop(invalidateTrans); - transitionTable[Modified][Packet::WriteInvalidateReq].onSnoop(invalidateTrans); - transitionTable[Owned][Packet::WriteInvalidateReq].onSnoop(invalidateTrans); + // + // ----- bus snoop transition functions ----- + // + tt[Invalid][P::ReadReq].onSnoop(nullTransition); + tt[Invalid][P::ReadExReq].onSnoop(nullTransition); + tt[Invalid][P::InvalidateReq].onSnoop(invalidateTrans); + tt[Invalid][P::WriteInvalidateReq].onSnoop(invalidateTrans); + tt[Shared][P::ReadReq].onSnoop(hasExclusive + ? assertShared : nullTransition); + tt[Shared][P::ReadExReq].onSnoop(invalidateTrans); + tt[Shared][P::InvalidateReq].onSnoop(invalidateTrans); + tt[Shared][P::WriteInvalidateReq].onSnoop(invalidateTrans); + if (doUpgrades) { + tt[Invalid][P::UpgradeReq].onSnoop(nullTransition); + tt[Shared][P::UpgradeReq].onSnoop(invalidateTrans); + } + tt[Modified][P::ReadExReq].onSnoop(supplyAndInvalidateTrans); + tt[Modified][P::ReadReq].onSnoop(hasOwned + ? supplyAndGotoOwnedTrans + : supplyAndGotoSharedTrans); + tt[Modified][P::InvalidateReq].onSnoop(invalidateTrans); + tt[Modified][P::WriteInvalidateReq].onSnoop(invalidateTrans); + + if (hasExclusive) { + tt[Exclusive][P::ReadReq].onSnoop(assertShared); + tt[Exclusive][P::ReadExReq].onSnoop(invalidateTrans); + tt[Exclusive][P::InvalidateReq].onSnoop(invalidateTrans); + tt[Exclusive][P::WriteInvalidateReq].onSnoop(invalidateTrans); } - else { - cerr << "CoherenceProtocol: unrecognized protocol " << protocol - << endl; - fatal(""); + if (hasOwned) { + tt[Owned][P::ReadReq].onSnoop(supplyAndGotoOwnedTrans); + tt[Owned][P::ReadExReq].onSnoop(supplyAndInvalidateTrans); + tt[Owned][P::UpgradeReq].onSnoop(invalidateTrans); + tt[Owned][P::InvalidateReq].onSnoop(invalidateTrans); + tt[Owned][P::WriteInvalidateReq].onSnoop(invalidateTrans); } + + // @todo add in hardware prefetch to this list } @@ -463,7 +386,7 @@ CoherenceProtocol::getBusCmd(Packet::Command cmdIn, CacheBlk::State state, CacheBlk::State -CoherenceProtocol::getNewState(Packet * &pkt, CacheBlk::State oldState) +CoherenceProtocol::getNewState(PacketPtr &pkt, CacheBlk::State oldState) { CacheBlk::State state = oldState & stateMask; int cmd_idx = pkt->cmdToIndex(); @@ -488,7 +411,7 @@ CoherenceProtocol::getNewState(Packet * &pkt, CacheBlk::State oldState) bool -CoherenceProtocol::handleBusRequest(BaseCache *cache, Packet * &pkt, +CoherenceProtocol::handleBusRequest(BaseCache *cache, PacketPtr &pkt, CacheBlk *blk, MSHR *mshr, CacheBlk::State & new_state) @@ -518,7 +441,7 @@ CoherenceProtocol::handleBusRequest(BaseCache *cache, Packet * &pkt, } bool -CoherenceProtocol::nullTransition(BaseCache *cache, Packet * &pkt, +CoherenceProtocol::nullTransition(BaseCache *cache, PacketPtr &pkt, CacheBlk *blk, MSHR *mshr, CacheBlk::State & new_state) { @@ -530,7 +453,7 @@ CoherenceProtocol::nullTransition(BaseCache *cache, Packet * &pkt, bool -CoherenceProtocol::invalidTransition(BaseCache *cache, Packet * &pkt, +CoherenceProtocol::invalidTransition(BaseCache *cache, PacketPtr &pkt, CacheBlk *blk, MSHR *mshr, CacheBlk::State & new_state) { diff --git a/src/mem/cache/coherence/coherence_protocol.hh b/src/mem/cache/coherence/coherence_protocol.hh index b5d7d80aa..481277523 100644 --- a/src/mem/cache/coherence/coherence_protocol.hh +++ b/src/mem/cache/coherence/coherence_protocol.hh @@ -89,7 +89,7 @@ class CoherenceProtocol : public SimObject * @param oldState The current block state. * @return The new state. */ - CacheBlk::State getNewState(Packet * &pkt, + CacheBlk::State getNewState(PacketPtr &pkt, CacheBlk::State oldState); /** @@ -101,12 +101,12 @@ class CoherenceProtocol : public SimObject * @param new_state The new coherence state of the block. * @return True if the request should be satisfied locally. */ - bool handleBusRequest(BaseCache *cache, Packet * &pkt, CacheBlk *blk, + bool handleBusRequest(BaseCache *cache, PacketPtr &pkt, CacheBlk *blk, MSHR *mshr, CacheBlk::State &new_state); protected: /** Snoop function type. */ - typedef bool (*SnoopFuncType)(BaseCache *, Packet *&, CacheBlk *, + typedef bool (*SnoopFuncType)(BaseCache *, PacketPtr &, CacheBlk *, MSHR *, CacheBlk::State&); // @@ -116,49 +116,49 @@ class CoherenceProtocol : public SimObject /** * Do nothing transition. */ - static bool nullTransition(BaseCache *, Packet *&, CacheBlk *, + static bool nullTransition(BaseCache *, PacketPtr &, CacheBlk *, MSHR *, CacheBlk::State&); /** * Invalid transition, basically panic. */ - static bool invalidTransition(BaseCache *, Packet *&, CacheBlk *, + static bool invalidTransition(BaseCache *, PacketPtr &, CacheBlk *, MSHR *, CacheBlk::State&); /** * Invalidate block, move to Invalid state. */ - static bool invalidateTrans(BaseCache *, Packet *&, CacheBlk *, + static bool invalidateTrans(BaseCache *, PacketPtr &, CacheBlk *, MSHR *, CacheBlk::State&); /** * Supply data, no state transition. */ - static bool supplyTrans(BaseCache *, Packet *&, CacheBlk *, + static bool supplyTrans(BaseCache *, PacketPtr &, CacheBlk *, MSHR *, CacheBlk::State&); /** * Supply data and go to Shared state. */ - static bool supplyAndGotoSharedTrans(BaseCache *, Packet *&, CacheBlk *, + static bool supplyAndGotoSharedTrans(BaseCache *, PacketPtr &, CacheBlk *, MSHR *, CacheBlk::State&); /** * Supply data and go to Owned state. */ - static bool supplyAndGotoOwnedTrans(BaseCache *, Packet *&, CacheBlk *, + static bool supplyAndGotoOwnedTrans(BaseCache *, PacketPtr &, CacheBlk *, MSHR *, CacheBlk::State&); /** * Invalidate block, supply data, and go to Invalid state. */ - static bool supplyAndInvalidateTrans(BaseCache *, Packet *&, CacheBlk *, + static bool supplyAndInvalidateTrans(BaseCache *, PacketPtr &, CacheBlk *, MSHR *, CacheBlk::State&); /** * Assert the shared line for a block that is shared/exclusive. */ - static bool assertShared(BaseCache *, Packet *&, CacheBlk *, + static bool assertShared(BaseCache *, PacketPtr &, CacheBlk *, MSHR *, CacheBlk::State&); /** @@ -211,31 +211,25 @@ class CoherenceProtocol : public SimObject friend class CoherenceProtocol::StateTransition; /** Mask to select status bits relevant to coherence protocol. */ - const static CacheBlk::State - stateMask = BlkValid | BlkWritable | BlkDirty; + static const int stateMask = BlkValid | BlkWritable | BlkDirty; /** The Modified (M) state. */ - const static CacheBlk::State - Modified = BlkValid | BlkWritable | BlkDirty; + static const int Modified = BlkValid | BlkWritable | BlkDirty; /** The Owned (O) state. */ - const static CacheBlk::State - Owned = BlkValid | BlkDirty; + static const int Owned = BlkValid | BlkDirty; /** The Exclusive (E) state. */ - const static CacheBlk::State - Exclusive = BlkValid | BlkWritable; + static const int Exclusive = BlkValid | BlkWritable; /** The Shared (S) state. */ - const static CacheBlk::State - Shared = BlkValid; + static const int Shared = BlkValid; /** The Invalid (I) state. */ - const static CacheBlk::State - Invalid = 0; + static const int Invalid = 0; /** * Maximum state encoding value (used to size transition lookup * table). Could be more than number of states, depends on * encoding of status bits. */ - const static int stateMax = stateMask; + static const int stateMax = stateMask; /** * The table of all possible transitions, organized by starting state and diff --git a/src/mem/cache/coherence/simple_coherence.hh b/src/mem/cache/coherence/simple_coherence.hh index a356b3ecc..5316e64b9 100644 --- a/src/mem/cache/coherence/simple_coherence.hh +++ b/src/mem/cache/coherence/simple_coherence.hh @@ -89,7 +89,7 @@ class SimpleCoherence * This policy does not forward invalidates, return NULL. * @return NULL. */ - Packet * getPacket() + PacketPtr getPacket() { return NULL; } @@ -99,7 +99,7 @@ class SimpleCoherence * @param pkt The request. * @param success True if the request was sent successfully. */ - void sendResult(Packet * &pkt, MSHR* cshr, bool success) + void sendResult(PacketPtr &pkt, MSHR* cshr, bool success) { //Don't do coherence return; @@ -112,7 +112,7 @@ class SimpleCoherence * @param current The current block state. * @return The new state. */ - CacheBlk::State getNewState(Packet * &pkt, CacheBlk::State current) + CacheBlk::State getNewState(PacketPtr &pkt, CacheBlk::State current) { return protocol->getNewState(pkt, current); } @@ -124,7 +124,7 @@ class SimpleCoherence * @param mshr The MSHR corresponding to the request, if any. * @param new_state Return the new state for the block. */ - bool handleBusRequest(Packet * &pkt, CacheBlk *blk, MSHR *mshr, + bool handleBusRequest(PacketPtr &pkt, CacheBlk *blk, MSHR *mshr, CacheBlk::State &new_state) { // assert(mshr == NULL); @@ -160,6 +160,12 @@ class SimpleCoherence bool allowFastWrites() { return false; } bool hasProtocol() { return true; } + + void propogateInvalidate(PacketPtr pkt, bool isTiming) + { + //For now we do nothing, asssumes simple coherence is top level of cache + return; + } }; #endif //__SIMPLE_COHERENCE_HH__ diff --git a/src/mem/cache/coherence/uni_coherence.cc b/src/mem/cache/coherence/uni_coherence.cc index 751de4801..19230e35b 100644 --- a/src/mem/cache/coherence/uni_coherence.cc +++ b/src/mem/cache/coherence/uni_coherence.cc @@ -40,24 +40,24 @@ UniCoherence::UniCoherence() { } -Packet * +PacketPtr UniCoherence::getPacket() { - Packet* pkt = cshrs.getReq(); + PacketPtr pkt = cshrs.getReq(); return pkt; } void -UniCoherence::sendResult(Packet * &pkt, MSHR* cshr, bool success) +UniCoherence::sendResult(PacketPtr &pkt, MSHR* cshr, bool success) { if (success) { bool unblock = cshrs.isFull(); - cshrs.markInService(cshr); +// cshrs.markInService(cshr); + cshrs.deallocate(cshr); if (!cshrs.havePending()) { cache->clearSlaveRequest(Request_Coherence); } - cshrs.deallocate(cshr); if (unblock) { //since CSHRs are always used as buffers, should always get rid of one assert(!cshrs.isFull()); @@ -71,24 +71,36 @@ UniCoherence::sendResult(Packet * &pkt, MSHR* cshr, bool success) * @todo add support for returning slave requests, not doing them here. */ bool -UniCoherence::handleBusRequest(Packet * &pkt, CacheBlk *blk, MSHR *mshr, +UniCoherence::handleBusRequest(PacketPtr &pkt, CacheBlk *blk, MSHR *mshr, CacheBlk::State &new_state) { new_state = 0; if (pkt->isInvalidate()) { - DPRINTF(Cache, "snoop inval on blk %x (blk ptr %x)\n", - pkt->getAddr(), blk); - // Forward to other caches - Packet * tmp = new Packet(pkt->req, Packet::InvalidateReq, -1); - cshrs.allocate(tmp); - cache->setSlaveRequest(Request_Coherence, curTick); - if (cshrs.isFull()) { - cache->setBlockedForSnoop(Blocked_Coherence); + DPRINTF(Cache, "snoop inval on blk %x (blk ptr %x)\n", + pkt->getAddr(), blk); + } + else if (blk) { + new_state = blk->status; + } + return false; +} + +void +UniCoherence::propogateInvalidate(PacketPtr pkt, bool isTiming) +{ + if (pkt->isInvalidate()) { + if (isTiming) { + // Forward to other caches + PacketPtr tmp = new Packet(pkt->req, Packet::InvalidateReq, -1); + cshrs.allocate(tmp); + cache->setSlaveRequest(Request_Coherence, curTick); + if (cshrs.isFull()) + cache->setBlockedForSnoop(Blocked_Coherence); } - } else { - if (blk) { - new_state = blk->status; + else { + PacketPtr tmp = new Packet(pkt->req, Packet::InvalidateReq, -1); + cache->cpuSidePort->sendAtomic(tmp); + delete tmp; } } - return false; } diff --git a/src/mem/cache/coherence/uni_coherence.hh b/src/mem/cache/coherence/uni_coherence.hh index 60da7a36e..44c752088 100644 --- a/src/mem/cache/coherence/uni_coherence.hh +++ b/src/mem/cache/coherence/uni_coherence.hh @@ -92,7 +92,7 @@ class UniCoherence * @param current The current block state. * @return The new state. */ - CacheBlk::State getNewState(Packet * &pkt, CacheBlk::State current) + CacheBlk::State getNewState(PacketPtr &pkt, CacheBlk::State current) { if (pkt->senderState) //Blocking Buffers don't get mshrs { @@ -113,14 +113,14 @@ class UniCoherence * Return outstanding invalidate to forward. * @return The next invalidate to forward to lower levels of cache. */ - Packet * getPacket(); + PacketPtr getPacket(); /** * Was the CSHR request was sent successfully? * @param pkt The request. * @param success True if the request was sent successfully. */ - void sendResult(Packet * &pkt, MSHR* cshr, bool success); + void sendResult(PacketPtr &pkt, MSHR* cshr, bool success); /** * Handle snooped bus requests. @@ -130,7 +130,7 @@ class UniCoherence * @param new_state The new coherence state of the block. * @return True if the request should be satisfied locally. */ - bool handleBusRequest(Packet * &pkt, CacheBlk *blk, MSHR *mshr, + bool handleBusRequest(PacketPtr &pkt, CacheBlk *blk, MSHR *mshr, CacheBlk::State &new_state); /** @@ -139,6 +139,8 @@ class UniCoherence bool allowFastWrites() { return true; } bool hasProtocol() { return false; } + + void propogateInvalidate(PacketPtr pkt, bool isTiming); }; #endif //__UNI_COHERENCE_HH__ diff --git a/src/mem/cache/miss/blocking_buffer.cc b/src/mem/cache/miss/blocking_buffer.cc index f7aacff89..bf741e547 100644 --- a/src/mem/cache/miss/blocking_buffer.cc +++ b/src/mem/cache/miss/blocking_buffer.cc @@ -68,7 +68,7 @@ BlockingBuffer::setPrefetcher(BasePrefetcher *_prefetcher) prefetcher = _prefetcher; } void -BlockingBuffer::handleMiss(Packet * &pkt, int blk_size, Tick time) +BlockingBuffer::handleMiss(PacketPtr &pkt, int blk_size, Tick time) { Addr blk_addr = pkt->getAddr() & ~(Addr)(blk_size - 1); if (pkt->isWrite() && (pkt->req->isUncacheable() || !writeAllocate || @@ -98,7 +98,7 @@ BlockingBuffer::handleMiss(Packet * &pkt, int blk_size, Tick time) cache->setMasterRequest(Request_MSHR, time); } -Packet * +PacketPtr BlockingBuffer::getPacket() { if (miss.pkt && !miss.inService) { @@ -108,7 +108,7 @@ BlockingBuffer::getPacket() } void -BlockingBuffer::setBusCmd(Packet * &pkt, Packet::Command cmd) +BlockingBuffer::setBusCmd(PacketPtr &pkt, Packet::Command cmd) { MSHR *mshr = (MSHR*) pkt->senderState; mshr->originalCmd = pkt->cmd; @@ -117,13 +117,13 @@ BlockingBuffer::setBusCmd(Packet * &pkt, Packet::Command cmd) } void -BlockingBuffer::restoreOrigCmd(Packet * &pkt) +BlockingBuffer::restoreOrigCmd(PacketPtr &pkt) { pkt->cmdOverride(((MSHR*)(pkt->senderState))->originalCmd); } void -BlockingBuffer::markInService(Packet * &pkt, MSHR* mshr) +BlockingBuffer::markInService(PacketPtr &pkt, MSHR* mshr) { if (!pkt->isCacheFill() && pkt->isWrite()) { // Forwarding a write/ writeback, don't need to change @@ -152,7 +152,7 @@ BlockingBuffer::markInService(Packet * &pkt, MSHR* mshr) } void -BlockingBuffer::handleResponse(Packet * &pkt, Tick time) +BlockingBuffer::handleResponse(PacketPtr &pkt, Tick time) { if (pkt->isCacheFill()) { // targets were handled in the cache tags @@ -163,7 +163,7 @@ BlockingBuffer::handleResponse(Packet * &pkt, Tick time) if (((MSHR*)(pkt->senderState))->hasTargets()) { // Should only have 1 target if we had any assert(((MSHR*)(pkt->senderState))->getNumTargets() == 1); - Packet * target = ((MSHR*)(pkt->senderState))->getTarget(); + PacketPtr target = ((MSHR*)(pkt->senderState))->getTarget(); ((MSHR*)(pkt->senderState))->popTarget(); if (pkt->isRead()) { memcpy(target->getPtr<uint8_t>(), pkt->getPtr<uint8_t>(), target->getSize()); @@ -187,7 +187,7 @@ void BlockingBuffer::squash(int threadNum) { if (miss.threadNum == threadNum) { - Packet * target = miss.getTarget(); + PacketPtr target = miss.getTarget(); miss.popTarget(); assert(0/*target->req->getThreadNum()*/ == threadNum); target = NULL; @@ -207,7 +207,7 @@ BlockingBuffer::doWriteback(Addr addr, { // Generate request Request * req = new Request(addr, size, 0); - Packet * pkt = new Packet(req, Packet::Writeback, -1); + PacketPtr pkt = new Packet(req, Packet::Writeback, -1); pkt->allocate(); if (data) { memcpy(pkt->getPtr<uint8_t>(), data, size); @@ -228,7 +228,7 @@ BlockingBuffer::doWriteback(Addr addr, void -BlockingBuffer::doWriteback(Packet * &pkt) +BlockingBuffer::doWriteback(PacketPtr &pkt) { writebacks[0/*pkt->req->getThreadNum()*/]++; diff --git a/src/mem/cache/miss/blocking_buffer.hh b/src/mem/cache/miss/blocking_buffer.hh index f7069696c..4408cfc4f 100644 --- a/src/mem/cache/miss/blocking_buffer.hh +++ b/src/mem/cache/miss/blocking_buffer.hh @@ -111,7 +111,7 @@ public: * @param blk_size The block size of the cache. * @param time The time the miss is detected. */ - void handleMiss(Packet * &pkt, int blk_size, Tick time); + void handleMiss(PacketPtr &pkt, int blk_size, Tick time); /** * Fetch the block for the given address and buffer the given target. @@ -122,7 +122,7 @@ public: * @param target The target for the fetch. */ MSHR* fetchBlock(Addr addr, int blk_size, Tick time, - Packet * &target) + PacketPtr &target) { fatal("Unimplemented"); } @@ -131,20 +131,20 @@ public: * Selects a outstanding pktuest to service. * @return The pktuest to service, NULL if none found. */ - Packet * getPacket(); + PacketPtr getPacket(); /** * Set the command to the given bus command. * @param pkt The request to update. * @param cmd The bus command to use. */ - void setBusCmd(Packet * &pkt, Packet::Command cmd); + void setBusCmd(PacketPtr &pkt, Packet::Command cmd); /** * Restore the original command in case of a bus transmission error. * @param pkt The request to reset. */ - void restoreOrigCmd(Packet * &pkt); + void restoreOrigCmd(PacketPtr &pkt); /** * Marks a pktuest as in service (sent on the bus). This can have side @@ -152,14 +152,14 @@ public: * are successfully sent. * @param pkt The request that was sent on the bus. */ - void markInService(Packet * &pkt, MSHR* mshr); + void markInService(PacketPtr &pkt, MSHR* mshr); /** * Frees the resources of the pktuest and unblock the cache. * @param pkt The request that has been satisfied. * @param time The time when the pktuest is satisfied. */ - void handleResponse(Packet * &pkt, Tick time); + void handleResponse(PacketPtr &pkt, Tick time); /** * Removes all outstanding pktuests for a given thread number. If a request @@ -223,7 +223,7 @@ public: * Perform a writeback pktuest. * @param pkt The writeback request. */ - void doWriteback(Packet * &pkt); + void doWriteback(PacketPtr &pkt); /** * Returns true if there are outstanding pktuests. @@ -239,7 +239,7 @@ public: * @param mshr The mshr to add a target to. * @param pkt The target to add. */ - void addTarget(MSHR *mshr, Packet * &pkt) + void addTarget(MSHR *mshr, PacketPtr &pkt) { fatal("Shouldn't call this on a blocking buffer."); } diff --git a/src/mem/cache/miss/miss_queue.cc b/src/mem/cache/miss/miss_queue.cc index c23b542f5..fe467a8ea 100644 --- a/src/mem/cache/miss/miss_queue.cc +++ b/src/mem/cache/miss/miss_queue.cc @@ -350,7 +350,7 @@ MissQueue::setPrefetcher(BasePrefetcher *_prefetcher) } MSHR* -MissQueue::allocateMiss(Packet * &pkt, int size, Tick time) +MissQueue::allocateMiss(PacketPtr &pkt, int size, Tick time) { MSHR* mshr = mq.allocate(pkt, size); mshr->order = order++; @@ -370,7 +370,7 @@ MissQueue::allocateMiss(Packet * &pkt, int size, Tick time) MSHR* -MissQueue::allocateWrite(Packet * &pkt, int size, Tick time) +MissQueue::allocateWrite(PacketPtr &pkt, int size, Tick time) { MSHR* mshr = wb.allocate(pkt,size); mshr->order = order++; @@ -401,7 +401,7 @@ MissQueue::allocateWrite(Packet * &pkt, int size, Tick time) * @todo Remove SW prefetches on mshr hits. */ void -MissQueue::handleMiss(Packet * &pkt, int blkSize, Tick time) +MissQueue::handleMiss(PacketPtr &pkt, int blkSize, Tick time) { // if (!cache->isTopLevel()) if (prefetchMiss) prefetcher->handleMiss(pkt, time); @@ -455,7 +455,7 @@ MissQueue::handleMiss(Packet * &pkt, int blkSize, Tick time) MSHR* MissQueue::fetchBlock(Addr addr, int blk_size, Tick time, - Packet * &target) + PacketPtr &target) { Addr blkAddr = addr & ~(Addr)(blk_size - 1); assert(mq.findMatch(addr) == NULL); @@ -469,10 +469,10 @@ MissQueue::fetchBlock(Addr addr, int blk_size, Tick time, return mshr; } -Packet * +PacketPtr MissQueue::getPacket() { - Packet * pkt = mq.getReq(); + PacketPtr pkt = mq.getReq(); if (((wb.isFull() && wb.inServiceMSHRs == 0) || !pkt || pkt->time > curTick) && wb.havePending()) { pkt = wb.getReq(); @@ -510,7 +510,7 @@ MissQueue::getPacket() } void -MissQueue::setBusCmd(Packet * &pkt, Packet::Command cmd) +MissQueue::setBusCmd(PacketPtr &pkt, Packet::Command cmd) { assert(pkt->senderState != 0); MSHR * mshr = (MSHR*)pkt->senderState; @@ -528,13 +528,13 @@ MissQueue::setBusCmd(Packet * &pkt, Packet::Command cmd) } void -MissQueue::restoreOrigCmd(Packet * &pkt) +MissQueue::restoreOrigCmd(PacketPtr &pkt) { pkt->cmd = ((MSHR*)(pkt->senderState))->originalCmd; } void -MissQueue::markInService(Packet * &pkt, MSHR* mshr) +MissQueue::markInService(PacketPtr &pkt, MSHR* mshr) { bool unblock = false; BlockedCause cause = NUM_BLOCKED_CAUSES; @@ -583,7 +583,7 @@ MissQueue::markInService(Packet * &pkt, MSHR* mshr) void -MissQueue::handleResponse(Packet * &pkt, Tick time) +MissQueue::handleResponse(PacketPtr &pkt, Tick time) { MSHR* mshr = (MSHR*)pkt->senderState; if (((MSHR*)(pkt->senderState))->originalCmd == Packet::HardPFReq) { @@ -632,7 +632,7 @@ MissQueue::handleResponse(Packet * &pkt, Tick time) if (mshr->hasTargets() && pkt->req->isUncacheable()) { // Should only have 1 target if we had any assert(num_targets == 1); - Packet * target = mshr->getTarget(); + PacketPtr target = mshr->getTarget(); mshr->popTarget(); if (pkt->isRead()) { memcpy(target->getPtr<uint8_t>(), pkt->getPtr<uint8_t>(), @@ -645,7 +645,7 @@ MissQueue::handleResponse(Packet * &pkt, Tick time) //Must be a no_allocate with possibly more than one target assert(mshr->pkt->isNoAllocate()); while (mshr->hasTargets()) { - Packet * target = mshr->getTarget(); + PacketPtr target = mshr->getTarget(); mshr->popTarget(); if (pkt->isRead()) { memcpy(target->getPtr<uint8_t>(), pkt->getPtr<uint8_t>(), @@ -721,7 +721,7 @@ MissQueue::doWriteback(Addr addr, { // Generate request Request * req = new Request(addr, size, 0); - Packet * pkt = new Packet(req, Packet::Writeback, -1); + PacketPtr pkt = new Packet(req, Packet::Writeback, -1); pkt->allocate(); if (data) { memcpy(pkt->getPtr<uint8_t>(), data, size); @@ -739,7 +739,7 @@ MissQueue::doWriteback(Addr addr, void -MissQueue::doWriteback(Packet * &pkt) +MissQueue::doWriteback(PacketPtr &pkt) { writebacks[0/*pkt->req->getThreadNum()*/]++; allocateWrite(pkt, 0, curTick); diff --git a/src/mem/cache/miss/miss_queue.hh b/src/mem/cache/miss/miss_queue.hh index 179638d2b..2e04802fb 100644 --- a/src/mem/cache/miss/miss_queue.hh +++ b/src/mem/cache/miss/miss_queue.hh @@ -169,7 +169,7 @@ class MissQueue * @param time The time the miss occurs. * @return A pointer to the new MSHR. */ - MSHR* allocateMiss(Packet * &pkt, int size, Tick time); + MSHR* allocateMiss(PacketPtr &pkt, int size, Tick time); /** * Allocate a new WriteBuffer to handle the provided write. @@ -178,7 +178,7 @@ class MissQueue * @param time The time the write occurs. * @return A pointer to the new write buffer. */ - MSHR* allocateWrite(Packet * &pkt, int size, Tick time); + MSHR* allocateWrite(PacketPtr &pkt, int size, Tick time); public: /** @@ -218,7 +218,7 @@ class MissQueue * @param blk_size The block size of the cache. * @param time The time the miss is detected. */ - void handleMiss(Packet * &pkt, int blk_size, Tick time); + void handleMiss(PacketPtr &pkt, int blk_size, Tick time); /** * Fetch the block for the given address and buffer the given target. @@ -229,26 +229,26 @@ class MissQueue * @param target The target for the fetch. */ MSHR* fetchBlock(Addr addr, int blk_size, Tick time, - Packet * &target); + PacketPtr &target); /** * Selects a outstanding pktuest to service. * @return The pktuest to service, NULL if none found. */ - Packet * getPacket(); + PacketPtr getPacket(); /** * Set the command to the given bus command. * @param pkt The request to update. * @param cmd The bus command to use. */ - void setBusCmd(Packet * &pkt, Packet::Command cmd); + void setBusCmd(PacketPtr &pkt, Packet::Command cmd); /** * Restore the original command in case of a bus transmission error. * @param pkt The request to reset. */ - void restoreOrigCmd(Packet * &pkt); + void restoreOrigCmd(PacketPtr &pkt); /** * Marks a pktuest as in service (sent on the bus). This can have side @@ -256,14 +256,14 @@ class MissQueue * are successfully sent. * @param pkt The request that was sent on the bus. */ - void markInService(Packet * &pkt, MSHR* mshr); + void markInService(PacketPtr &pkt, MSHR* mshr); /** * Collect statistics and free resources of a satisfied pktuest. * @param pkt The request that has been satisfied. * @param time The time when the pktuest is satisfied. */ - void handleResponse(Packet * &pkt, Tick time); + void handleResponse(PacketPtr &pkt, Tick time); /** * Removes all outstanding pktuests for a given thread number. If a request @@ -316,7 +316,7 @@ class MissQueue * Perform the given writeback pktuest. * @param pkt The writeback request. */ - void doWriteback(Packet * &pkt); + void doWriteback(PacketPtr &pkt); /** * Returns true if there are outstanding pktuests. @@ -329,7 +329,7 @@ class MissQueue * @param mshr The mshr to add a target to. * @param pkt The target to add. */ - void addTarget(MSHR *mshr, Packet * &pkt) + void addTarget(MSHR *mshr, PacketPtr &pkt) { mq.allocateTarget(mshr, pkt); } diff --git a/src/mem/cache/miss/mshr.cc b/src/mem/cache/miss/mshr.cc index 455798f15..fc520b4b4 100644 --- a/src/mem/cache/miss/mshr.cc +++ b/src/mem/cache/miss/mshr.cc @@ -55,7 +55,7 @@ MSHR::MSHR() void MSHR::allocate(Packet::Command cmd, Addr _addr, int size, - Packet * &target) + PacketPtr &target) { addr = _addr; if (target) @@ -85,7 +85,7 @@ MSHR::allocate(Packet::Command cmd, Addr _addr, int size, * @todo When we have a "global" data flag, might want to copy data here. */ void -MSHR::allocateAsBuffer(Packet * &target) +MSHR::allocateAsBuffer(PacketPtr &target) { addr = target->getAddr(); threadNum = 0/*target->req->getThreadNum()*/; @@ -111,13 +111,13 @@ MSHR::deallocate() * Adds a target to an MSHR */ void -MSHR::allocateTarget(Packet * &target) +MSHR::allocateTarget(PacketPtr &target) { //If we append an invalidate and we issued a read to the bus, //but now have some pending writes, we need to move //the invalidate to before the first non-read if (inService && pkt->isRead() && target->isInvalidate()) { - std::list<Packet *> temp; + std::list<PacketPtr> temp; while (!targets.empty()) { if (!targets.front()->isRead()) break; diff --git a/src/mem/cache/miss/mshr.hh b/src/mem/cache/miss/mshr.hh index 028259b35..d92aa8a85 100644 --- a/src/mem/cache/miss/mshr.hh +++ b/src/mem/cache/miss/mshr.hh @@ -49,9 +49,9 @@ class MSHR; class MSHR { public: /** Defines the Data structure of the MSHR targetlist. */ - typedef std::list<Packet *> TargetList; + typedef std::list<PacketPtr> TargetList; /** Target list iterator. */ - typedef std::list<Packet *>::iterator TargetListIterator; + typedef std::list<PacketPtr>::iterator TargetListIterator; /** A list of MSHRs. */ typedef std::list<MSHR *> List; /** MSHR list iterator. */ @@ -68,7 +68,7 @@ class MSHR { /** Thread number of the miss. */ int threadNum; /** The pktuest that is forwarded to the next level of the hierarchy. */ - Packet * pkt; + PacketPtr pkt; /** The number of currently allocated targets. */ short ntargets; /** The original pktuesting command. */ @@ -101,13 +101,13 @@ public: * @param pkt The original miss. */ void allocate(Packet::Command cmd, Addr addr, int size, - Packet * &pkt); + PacketPtr &pkt); /** * Allocate this MSHR as a buffer for the given pktuest. * @param target The memory pktuest to buffer. */ - void allocateAsBuffer(Packet * &target); + void allocateAsBuffer(PacketPtr &target); /** * Mark this MSHR as free. @@ -118,7 +118,7 @@ public: * Add a pktuest to the list of targets. * @param target The target. */ - void allocateTarget(Packet * &target); + void allocateTarget(PacketPtr &target); /** A simple constructor. */ MSHR(); @@ -147,7 +147,7 @@ public: * Returns a reference to the first target. * @return A pointer to the first target. */ - Packet * getTarget() + PacketPtr getTarget() { return targets.front(); } diff --git a/src/mem/cache/miss/mshr_queue.cc b/src/mem/cache/miss/mshr_queue.cc index 777443e5f..d3a7a7933 100644 --- a/src/mem/cache/miss/mshr_queue.cc +++ b/src/mem/cache/miss/mshr_queue.cc @@ -88,7 +88,7 @@ MSHRQueue::findMatches(Addr addr, vector<MSHR*>& matches) const } MSHR* -MSHRQueue::findPending(Packet * &pkt) const +MSHRQueue::findPending(PacketPtr &pkt) const { MSHR::ConstIterator i = pendingList.begin(); MSHR::ConstIterator end = pendingList.end(); @@ -108,7 +108,7 @@ MSHRQueue::findPending(Packet * &pkt) const } MSHR* -MSHRQueue::allocate(Packet * &pkt, int size) +MSHRQueue::allocate(PacketPtr &pkt, int size) { Addr aligned_addr = pkt->getAddr() & ~((Addr)size - 1); assert(!freeList.empty()); @@ -131,7 +131,7 @@ MSHRQueue::allocate(Packet * &pkt, int size) } MSHR* -MSHRQueue::allocateFetch(Addr addr, int size, Packet * &target) +MSHRQueue::allocateFetch(Addr addr, int size, PacketPtr &target) { MSHR *mshr = freeList.front(); assert(mshr->getNumTargets() == 0); @@ -150,7 +150,7 @@ MSHRQueue::allocateTargetList(Addr addr, int size) MSHR *mshr = freeList.front(); assert(mshr->getNumTargets() == 0); freeList.pop_front(); - Packet * dummy; + PacketPtr dummy; mshr->allocate(Packet::ReadReq, addr, size, dummy); mshr->allocIter = allocatedList.insert(allocatedList.end(), mshr); mshr->inService = true; @@ -237,7 +237,7 @@ MSHRQueue::squash(int threadNum) MSHR *mshr = *i; if (mshr->threadNum == threadNum) { while (mshr->hasTargets()) { - Packet * target = mshr->getTarget(); + PacketPtr target = mshr->getTarget(); mshr->popTarget(); assert(0/*target->req->getThreadNum()*/ == threadNum); diff --git a/src/mem/cache/miss/mshr_queue.hh b/src/mem/cache/miss/mshr_queue.hh index ea5f101b7..30397d9a0 100644 --- a/src/mem/cache/miss/mshr_queue.hh +++ b/src/mem/cache/miss/mshr_queue.hh @@ -107,7 +107,7 @@ class MSHRQueue { * @param pkt The request to find. * @return A pointer to the earliest matching MSHR. */ - MSHR* findPending(Packet * &pkt) const; + MSHR* findPending(PacketPtr &pkt) const; /** * Allocates a new MSHR for the pktuest and size. This places the request @@ -118,7 +118,7 @@ class MSHRQueue { * * @pre There are free MSHRs. */ - MSHR* allocate(Packet * &pkt, int size = 0); + MSHR* allocate(PacketPtr &pkt, int size = 0); /** * Allocate a read pktuest for the given address, and places the given @@ -129,7 +129,7 @@ class MSHRQueue { * @param target The first target for the pktuest. * @return Pointer to the new MSHR. */ - MSHR* allocateFetch(Addr addr, int size, Packet * &target); + MSHR* allocateFetch(Addr addr, int size, PacketPtr &target); /** * Allocate a target list for the given address. @@ -153,7 +153,7 @@ class MSHRQueue { * @param mshr The MSHR to allocate the target to. * @param pkt The target request. */ - void allocateTarget(MSHR* mshr, Packet * &pkt) + void allocateTarget(MSHR* mshr, PacketPtr &pkt) { mshr->allocateTarget(pkt); allocatedTargets += 1; @@ -216,7 +216,7 @@ class MSHRQueue { * Returns the pktuest at the head of the pendingList. * @return The next pktuest to service. */ - Packet * getReq() const + PacketPtr getReq() const { if (pendingList.empty()) { return NULL; diff --git a/src/mem/cache/prefetch/base_prefetcher.cc b/src/mem/cache/prefetch/base_prefetcher.cc index 5e50c48bd..a1388fad6 100644 --- a/src/mem/cache/prefetch/base_prefetcher.cc +++ b/src/mem/cache/prefetch/base_prefetcher.cc @@ -102,7 +102,7 @@ BasePrefetcher::regStats(const std::string &name) ; } -Packet * +PacketPtr BasePrefetcher::getPacket() { DPRINTF(HWPrefetch, "%s:Requesting a hw_pf to issue\n", cache->name()); @@ -112,7 +112,7 @@ BasePrefetcher::getPacket() return NULL; } - Packet * pkt; + PacketPtr pkt; bool keepTrying = false; do { pkt = *pf.begin(); @@ -131,7 +131,7 @@ BasePrefetcher::getPacket() } void -BasePrefetcher::handleMiss(Packet * &pkt, Tick time) +BasePrefetcher::handleMiss(PacketPtr &pkt, Tick time) { if (!pkt->req->isUncacheable() && !(pkt->req->isInstRead() && only_data)) { @@ -139,7 +139,7 @@ BasePrefetcher::handleMiss(Packet * &pkt, Tick time) Addr blkAddr = pkt->getAddr() & ~(Addr)(blkSize-1); //Check if miss is in pfq, if so remove it - std::list<Packet *>::iterator iter = inPrefetch(blkAddr); + std::list<PacketPtr>::iterator iter = inPrefetch(blkAddr); if (iter != pf.end()) { DPRINTF(HWPrefetch, "%s:Saw a miss to a queued prefetch, removing it\n", cache->name()); pfRemovedMSHR++; @@ -179,7 +179,7 @@ BasePrefetcher::handleMiss(Packet * &pkt, Tick time) pfIdentified++; //create a prefetch memreq Request * prefetchReq = new Request(*addr, blkSize, 0); - Packet * prefetch; + PacketPtr prefetch; prefetch = new Packet(prefetchReq, Packet::HardPFReq, -1); prefetch->allocate(); prefetch->req->setThreadContext(pkt->req->getCpuNum(), @@ -233,11 +233,11 @@ BasePrefetcher::handleMiss(Packet * &pkt, Tick time) } } -std::list<Packet *>::iterator +std::list<PacketPtr>::iterator BasePrefetcher::inPrefetch(Addr address) { //Guaranteed to only be one match, we always check before inserting - std::list<Packet *>::iterator iter; + std::list<PacketPtr>::iterator iter; for (iter=pf.begin(); iter != pf.end(); iter++) { if (((*iter)->getAddr() & ~(Addr)(blkSize-1)) == address) { return iter; diff --git a/src/mem/cache/prefetch/base_prefetcher.hh b/src/mem/cache/prefetch/base_prefetcher.hh index d7ea41961..781d3ab09 100644 --- a/src/mem/cache/prefetch/base_prefetcher.hh +++ b/src/mem/cache/prefetch/base_prefetcher.hh @@ -45,7 +45,7 @@ class BasePrefetcher protected: /** The Prefetch Queue. */ - std::list<Packet *> pf; + std::list<PacketPtr> pf; // PARAMETERS @@ -93,24 +93,24 @@ class BasePrefetcher void setCache(BaseCache *_cache); - void handleMiss(Packet * &pkt, Tick time); + void handleMiss(PacketPtr &pkt, Tick time); - Packet * getPacket(); + PacketPtr getPacket(); bool havePending() { return !pf.empty(); } - virtual void calculatePrefetch(Packet * &pkt, + virtual void calculatePrefetch(PacketPtr &pkt, std::list<Addr> &addresses, std::list<Tick> &delays) = 0; - virtual bool inCache(Packet * &pkt) = 0; + virtual bool inCache(PacketPtr &pkt) = 0; virtual bool inMissQueue(Addr address) = 0; - std::list<Packet *>::iterator inPrefetch(Addr address); + std::list<PacketPtr>::iterator inPrefetch(Addr address); }; diff --git a/src/mem/cache/prefetch/ghb_prefetcher.hh b/src/mem/cache/prefetch/ghb_prefetcher.hh index c22b763d1..14f5747df 100644 --- a/src/mem/cache/prefetch/ghb_prefetcher.hh +++ b/src/mem/cache/prefetch/ghb_prefetcher.hh @@ -75,7 +75,7 @@ class GHBPrefetcher : public Prefetcher<TagStore, Buffering> ~GHBPrefetcher() {} - void calculatePrefetch(Packet * &pkt, std::list<Addr> &addresses, + void calculatePrefetch(PacketPtr &pkt, std::list<Addr> &addresses, std::list<Tick> &delays) { Addr blkAddr = pkt->getAddr() & ~(Addr)(this->blkSize-1); diff --git a/src/mem/cache/prefetch/stride_prefetcher.hh b/src/mem/cache/prefetch/stride_prefetcher.hh index 4a8ee7de4..d6fb8ab66 100644 --- a/src/mem/cache/prefetch/stride_prefetcher.hh +++ b/src/mem/cache/prefetch/stride_prefetcher.hh @@ -92,7 +92,7 @@ class StridePrefetcher : public Prefetcher<TagStore, Buffering> ~StridePrefetcher() {} - void calculatePrefetch(Packet * &pkt, std::list<Addr> &addresses, + void calculatePrefetch(PacketPtr &pkt, std::list<Addr> &addresses, std::list<Tick> &delays) { // Addr blkAddr = pkt->paddr & ~(Addr)(this->blkSize-1); diff --git a/src/mem/cache/prefetch/tagged_prefetcher.hh b/src/mem/cache/prefetch/tagged_prefetcher.hh index 17f500dd8..b61e57dcc 100644 --- a/src/mem/cache/prefetch/tagged_prefetcher.hh +++ b/src/mem/cache/prefetch/tagged_prefetcher.hh @@ -64,7 +64,7 @@ class TaggedPrefetcher : public Prefetcher<TagStore, Buffering> ~TaggedPrefetcher() {} - void calculatePrefetch(Packet * &pkt, std::list<Addr> &addresses, + void calculatePrefetch(PacketPtr &pkt, std::list<Addr> &addresses, std::list<Tick> &delays); }; diff --git a/src/mem/cache/prefetch/tagged_prefetcher_impl.hh b/src/mem/cache/prefetch/tagged_prefetcher_impl.hh index e554b3cec..a18de4571 100644 --- a/src/mem/cache/prefetch/tagged_prefetcher_impl.hh +++ b/src/mem/cache/prefetch/tagged_prefetcher_impl.hh @@ -50,7 +50,7 @@ TaggedPrefetcher(int size, bool pageStop, bool serialSquash, template <class TagStore, class Buffering> void TaggedPrefetcher<TagStore, Buffering>:: -calculatePrefetch(Packet * &pkt, std::list<Addr> &addresses, +calculatePrefetch(PacketPtr &pkt, std::list<Addr> &addresses, std::list<Tick> &delays) { Addr blkAddr = pkt->getAddr() & ~(Addr)(this->blkSize-1); diff --git a/src/mem/cache/tags/fa_lru.cc b/src/mem/cache/tags/fa_lru.cc index 784ba1311..a58ddaff8 100644 --- a/src/mem/cache/tags/fa_lru.cc +++ b/src/mem/cache/tags/fa_lru.cc @@ -203,7 +203,7 @@ FALRU::findBlock(Addr addr, int &lat, int *inCache) } FALRUBlk* -FALRU::findBlock(Packet * &pkt, int &lat, int *inCache) +FALRU::findBlock(PacketPtr &pkt, int &lat, int *inCache) { Addr addr = pkt->getAddr(); @@ -256,7 +256,7 @@ FALRU::findBlock(Addr addr) const } FALRUBlk* -FALRU::findReplacement(Packet * &pkt, PacketList &writebacks, +FALRU::findReplacement(PacketPtr &pkt, PacketList &writebacks, BlkList &compress_blocks) { FALRUBlk * blk = tail; diff --git a/src/mem/cache/tags/fa_lru.hh b/src/mem/cache/tags/fa_lru.hh index 0fc54902b..2db89d603 100644 --- a/src/mem/cache/tags/fa_lru.hh +++ b/src/mem/cache/tags/fa_lru.hh @@ -198,7 +198,7 @@ public: * @param inCache The FALRUBlk::inCache flags. * @return Pointer to the cache block. */ - FALRUBlk* findBlock(Packet * &pkt, int &lat, int *inCache = 0); + FALRUBlk* findBlock(PacketPtr &pkt, int &lat, int *inCache = 0); /** * Find the block in the cache, do not update the replacement data. @@ -215,7 +215,7 @@ public: * @param compress_blocks List of blocks to compress, for adaptive comp. * @return The block to place the replacement in. */ - FALRUBlk* findReplacement(Packet * &pkt, PacketList & writebacks, + FALRUBlk* findReplacement(PacketPtr &pkt, PacketList & writebacks, BlkList &compress_blocks); /** diff --git a/src/mem/cache/tags/iic.cc b/src/mem/cache/tags/iic.cc index bf1d9ece4..f4e870659 100644 --- a/src/mem/cache/tags/iic.cc +++ b/src/mem/cache/tags/iic.cc @@ -285,7 +285,7 @@ IIC::findBlock(Addr addr, int &lat) } IICTag* -IIC::findBlock(Packet * &pkt, int &lat) +IIC::findBlock(PacketPtr &pkt, int &lat) { Addr addr = pkt->getAddr(); @@ -362,7 +362,7 @@ IIC::findBlock(Addr addr) const IICTag* -IIC::findReplacement(Packet * &pkt, PacketList &writebacks, +IIC::findReplacement(PacketPtr &pkt, PacketList &writebacks, BlkList &compress_blocks) { DPRINTF(IIC, "Finding Replacement for %x\n", pkt->getAddr()); @@ -423,7 +423,7 @@ IIC::freeReplacementBlock(PacketList & writebacks) tag_ptr->refCount = 0; if (tag_ptr->isModified()) { -/* Packet * writeback = +/* PacketPtr writeback = buildWritebackReq(regenerateBlkAddr(tag_ptr->tag, 0), tag_ptr->req->asid, tag_ptr->xc, blkSize, tag_ptr->data, @@ -431,7 +431,7 @@ IIC::freeReplacementBlock(PacketList & writebacks) */ Request *writebackReq = new Request(regenerateBlkAddr(tag_ptr->tag, 0), blkSize, 0); - Packet *writeback = new Packet(writebackReq, Packet::Writeback, -1); + PacketPtr writeback = new Packet(writebackReq, Packet::Writeback, -1); writeback->allocate(); memcpy(writeback->getPtr<uint8_t>(), tag_ptr->data, blkSize); diff --git a/src/mem/cache/tags/iic.hh b/src/mem/cache/tags/iic.hh index 905d480c5..92bd6da1d 100644 --- a/src/mem/cache/tags/iic.hh +++ b/src/mem/cache/tags/iic.hh @@ -458,7 +458,7 @@ class IIC : public BaseTags * @param lat The access latency. * @return A pointer to the block found, if any. */ - IICTag* findBlock(Packet * &pkt, int &lat); + IICTag* findBlock(PacketPtr &pkt, int &lat); /** * Find the block, do not update the replacement data. @@ -475,7 +475,7 @@ class IIC : public BaseTags * @param compress_blocks List of blocks to compress, for adaptive comp. * @return The block to place the replacement in. */ - IICTag* findReplacement(Packet * &pkt, PacketList &writebacks, + IICTag* findReplacement(PacketPtr &pkt, PacketList &writebacks, BlkList &compress_blocks); /** diff --git a/src/mem/cache/tags/lru.cc b/src/mem/cache/tags/lru.cc index a9ae049c3..31d29aae6 100644 --- a/src/mem/cache/tags/lru.cc +++ b/src/mem/cache/tags/lru.cc @@ -184,7 +184,7 @@ LRU::findBlock(Addr addr, int &lat) } LRUBlk* -LRU::findBlock(Packet * &pkt, int &lat) +LRU::findBlock(PacketPtr &pkt, int &lat) { Addr addr = pkt->getAddr(); @@ -215,7 +215,7 @@ LRU::findBlock(Addr addr) const } LRUBlk* -LRU::findReplacement(Packet * &pkt, PacketList &writebacks, +LRU::findReplacement(PacketPtr &pkt, PacketList &writebacks, BlkList &compress_blocks) { unsigned set = extractSet(pkt->getAddr()); @@ -246,6 +246,7 @@ LRU::invalidateBlk(Addr addr) if (blk) { blk->status = 0; blk->isTouched = false; + blk->clearLoadLocks(); tagsInUse--; } } diff --git a/src/mem/cache/tags/lru.hh b/src/mem/cache/tags/lru.hh index 9f0a05ee8..fed688283 100644 --- a/src/mem/cache/tags/lru.hh +++ b/src/mem/cache/tags/lru.hh @@ -174,7 +174,7 @@ public: * @param lat The access latency. * @return Pointer to the cache block if found. */ - LRUBlk* findBlock(Packet * &pkt, int &lat); + LRUBlk* findBlock(PacketPtr &pkt, int &lat); /** * Finds the given address in the cache and update replacement data. @@ -201,7 +201,7 @@ public: * @param compress_blocks List of blocks to compress, for adaptive comp. * @return The block to place the replacement in. */ - LRUBlk* findReplacement(Packet * &pkt, PacketList &writebacks, + LRUBlk* findReplacement(PacketPtr &pkt, PacketList &writebacks, BlkList &compress_blocks); /** diff --git a/src/mem/cache/tags/split.cc b/src/mem/cache/tags/split.cc index cad18e885..bc74f0e0f 100644 --- a/src/mem/cache/tags/split.cc +++ b/src/mem/cache/tags/split.cc @@ -267,7 +267,7 @@ Split::probe(Addr addr) const } SplitBlk* -Split::findBlock(Packet * &pkt, int &lat) +Split::findBlock(PacketPtr &pkt, int &lat) { Addr aligned = blkAlign(pkt->getAddr()); @@ -350,7 +350,7 @@ Split::findBlock(Addr addr) const } SplitBlk* -Split::findReplacement(Packet * &pkt, PacketList &writebacks, +Split::findReplacement(PacketPtr &pkt, PacketList &writebacks, BlkList &compress_blocks) { SplitBlk *blk; diff --git a/src/mem/cache/tags/split.hh b/src/mem/cache/tags/split.hh index 708058e96..748f6fb25 100644 --- a/src/mem/cache/tags/split.hh +++ b/src/mem/cache/tags/split.hh @@ -207,7 +207,7 @@ class Split : public BaseTags * @param lat The access latency. * @return Pointer to the cache block if found. */ - SplitBlk* findBlock(Packet * &pkt, int &lat); + SplitBlk* findBlock(PacketPtr &pkt, int &lat); /** * Finds the given address in the cache, do not update replacement data. @@ -224,7 +224,7 @@ class Split : public BaseTags * @param compress_blocks List of blocks to compress, for adaptive comp. * @return The block to place the replacement in. */ - SplitBlk* findReplacement(Packet * &pkt, PacketList &writebacks, + SplitBlk* findReplacement(PacketPtr &pkt, PacketList &writebacks, BlkList &compress_blocks); diff --git a/src/mem/cache/tags/split_lifo.cc b/src/mem/cache/tags/split_lifo.cc index 4e9375070..302e2aaeb 100644 --- a/src/mem/cache/tags/split_lifo.cc +++ b/src/mem/cache/tags/split_lifo.cc @@ -255,7 +255,7 @@ SplitLIFO::findBlock(Addr addr, int &lat) } SplitBlk* -SplitLIFO::findBlock(Packet * &pkt, int &lat) +SplitLIFO::findBlock(PacketPtr &pkt, int &lat) { Addr addr = pkt->getAddr(); @@ -291,7 +291,7 @@ SplitLIFO::findBlock(Addr addr) const } SplitBlk* -SplitLIFO::findReplacement(Packet * &pkt, PacketList &writebacks, +SplitLIFO::findReplacement(PacketPtr &pkt, PacketList &writebacks, BlkList &compress_blocks) { unsigned set = extractSet(pkt->getAddr()); diff --git a/src/mem/cache/tags/split_lifo.hh b/src/mem/cache/tags/split_lifo.hh index ddc7fdeec..6c3befe37 100644 --- a/src/mem/cache/tags/split_lifo.hh +++ b/src/mem/cache/tags/split_lifo.hh @@ -207,7 +207,7 @@ public: * @param lat The access latency. * @return Pointer to the cache block if found. */ - SplitBlk* findBlock(Packet * &pkt, int &lat); + SplitBlk* findBlock(PacketPtr &pkt, int &lat); /** * Finds the given address in the cache, do not update replacement data. @@ -224,7 +224,7 @@ public: * @param compress_blocks List of blocks to compress, for adaptive comp. * @return The block to place the replacement in. */ - SplitBlk* findReplacement(Packet * &pkt, PacketList &writebacks, + SplitBlk* findReplacement(PacketPtr &pkt, PacketList &writebacks, BlkList &compress_blocks); /** diff --git a/src/mem/cache/tags/split_lru.cc b/src/mem/cache/tags/split_lru.cc index 4aba1c37f..11c9a5d64 100644 --- a/src/mem/cache/tags/split_lru.cc +++ b/src/mem/cache/tags/split_lru.cc @@ -203,7 +203,7 @@ SplitLRU::findBlock(Addr addr, int &lat) } SplitBlk* -SplitLRU::findBlock(Packet * &pkt, int &lat) +SplitLRU::findBlock(PacketPtr &pkt, int &lat) { Addr addr = pkt->getAddr(); @@ -234,7 +234,7 @@ SplitLRU::findBlock(Addr addr) const } SplitBlk* -SplitLRU::findReplacement(Packet * &pkt, PacketList &writebacks, +SplitLRU::findReplacement(PacketPtr &pkt, PacketList &writebacks, BlkList &compress_blocks) { unsigned set = extractSet(pkt->getAddr()); diff --git a/src/mem/cache/tags/split_lru.hh b/src/mem/cache/tags/split_lru.hh index 71f921177..6160d59e5 100644 --- a/src/mem/cache/tags/split_lru.hh +++ b/src/mem/cache/tags/split_lru.hh @@ -190,7 +190,7 @@ public: * @param lat The access latency. * @return Pointer to the cache block if found. */ - SplitBlk* findBlock(Packet * &pkt, int &lat); + SplitBlk* findBlock(PacketPtr &pkt, int &lat); /** * Finds the given address in the cache, do not update replacement data. @@ -207,7 +207,7 @@ public: * @param compress_blocks List of blocks to compress, for adaptive comp. * @return The block to place the replacement in. */ - SplitBlk* findReplacement(Packet * &pkt, PacketList &writebacks, + SplitBlk* findReplacement(PacketPtr &pkt, PacketList &writebacks, BlkList &compress_blocks); /** diff --git a/src/mem/dram.cc b/src/mem/dram.cc index d7b955975..873ca5b97 100644 --- a/src/mem/dram.cc +++ b/src/mem/dram.cc @@ -359,7 +359,7 @@ DRAMMemory::regStats() static char *mem_access_output=NULL; /* latency of access [CPU cycles]*/ Tick -DRAMMemory::calculateLatency(Packet *pkt) +DRAMMemory::calculateLatency(PacketPtr pkt) { bool cmdIsRead = pkt->isRead(); diff --git a/src/mem/dram.hh b/src/mem/dram.hh index 32d117596..9d2f60ee8 100644 --- a/src/mem/dram.hh +++ b/src/mem/dram.hh @@ -140,7 +140,7 @@ class DRAMMemory : public PhysicalMemory protected: - Tick calculateLatency(Packet *pkt); + Tick calculateLatency(PacketPtr pkt); int prechargeBanksAround(int bank); public: diff --git a/src/mem/packet.cc b/src/mem/packet.cc index 64c65dcca..fa8d82c46 100644 --- a/src/mem/packet.cc +++ b/src/mem/packet.cc @@ -36,9 +36,10 @@ */ #include <iostream> + #include "base/misc.hh" -#include "mem/packet.hh" #include "base/trace.hh" +#include "mem/packet.hh" static const std::string ReadReqString("ReadReq"); static const std::string WriteReqString("WriteReq"); @@ -51,6 +52,7 @@ static const std::string HardPFReqString("HardPFReq"); static const std::string HardPFRespString("HardPFResp"); static const std::string InvalidateReqString("InvalidateReq"); static const std::string WriteInvalidateReqString("WriteInvalidateReq"); +static const std::string WriteInvalidateRespString("WriteInvalidateResp"); static const std::string UpgradeReqString("UpgradeReq"); static const std::string ReadExReqString("ReadExReq"); static const std::string ReadExRespString("ReadExResp"); @@ -71,6 +73,7 @@ Packet::cmdString() const case HardPFResp: return HardPFRespString; case InvalidateReq: return InvalidateReqString; case WriteInvalidateReq:return WriteInvalidateReqString; + case WriteInvalidateResp:return WriteInvalidateRespString; case UpgradeReq: return UpgradeReqString; case ReadExReq: return ReadExReqString; case ReadExResp: return ReadExRespString; @@ -93,6 +96,7 @@ Packet::cmdIdxToString(Packet::Command idx) case HardPFResp: return HardPFRespString; case InvalidateReq: return InvalidateReqString; case WriteInvalidateReq:return WriteInvalidateReqString; + case WriteInvalidateResp:return WriteInvalidateRespString; case UpgradeReq: return UpgradeReqString; case ReadExReq: return ReadExReqString; case ReadExResp: return ReadExRespString; @@ -129,7 +133,7 @@ Packet::allocate() /** Do the packet modify the same addresses. */ bool -Packet::intersect(Packet *p) +Packet::intersect(PacketPtr p) { Addr s1 = getAddr(); Addr e1 = getAddr() + getSize() - 1; @@ -140,14 +144,14 @@ Packet::intersect(Packet *p) } bool -fixPacket(Packet *func, Packet *timing) +fixPacket(PacketPtr func, PacketPtr timing) { Addr funcStart = func->getAddr(); Addr funcEnd = func->getAddr() + func->getSize() - 1; Addr timingStart = timing->getAddr(); Addr timingEnd = timing->getAddr() + timing->getSize() - 1; - assert(!(funcStart > timingEnd || timingStart < funcEnd)); + assert(!(funcStart > timingEnd || timingStart > funcEnd)); if (DTRACE(FunctionalAccess)) { DebugOut() << func; diff --git a/src/mem/packet.hh b/src/mem/packet.hh index 319a4e534..cb97dd036 100644 --- a/src/mem/packet.hh +++ b/src/mem/packet.hh @@ -38,28 +38,29 @@ #ifndef __MEM_PACKET_HH__ #define __MEM_PACKET_HH__ +#include <cassert> +#include <list> + #include "mem/request.hh" #include "sim/host.hh" #include "sim/root.hh" -#include <list> -#include <cassert> struct Packet; -typedef Packet* PacketPtr; +typedef Packet *PacketPtr; typedef uint8_t* PacketDataPtr; typedef std::list<PacketPtr> PacketList; //Coherence Flags -#define NACKED_LINE 1 << 0 -#define SATISFIED 1 << 1 -#define SHARED_LINE 1 << 2 -#define CACHE_LINE_FILL 1 << 3 -#define COMPRESSED 1 << 4 -#define NO_ALLOCATE 1 << 5 -#define SNOOP_COMMIT 1 << 6 +#define NACKED_LINE (1 << 0) +#define SATISFIED (1 << 1) +#define SHARED_LINE (1 << 2) +#define CACHE_LINE_FILL (1 << 3) +#define COMPRESSED (1 << 4) +#define NO_ALLOCATE (1 << 5) +#define SNOOP_COMMIT (1 << 6) //for now. @todo fix later -#define NUM_MEM_CMDS 1 << 11 +#define NUM_MEM_CMDS (1 << 11) /** * A Packet is used to encapsulate a transfer between two objects in * the memory system (e.g., the L1 and L2 cache). (In contrast, a @@ -102,7 +103,7 @@ class Packet /** Device address (e.g., bus ID) of the source of the * transaction. The source is not responsible for setting this * field; it is set implicitly by the interconnect when the - * packet * is first sent. */ + * packet is first sent. */ short src; /** Device address (e.g., bus ID) of the destination of the @@ -171,17 +172,17 @@ class Packet // as well. enum CommandAttribute { - IsRead = 1 << 0, - IsWrite = 1 << 1, - IsPrefetch = 1 << 2, - IsInvalidate = 1 << 3, - IsRequest = 1 << 4, - IsResponse = 1 << 5, - NeedsResponse = 1 << 6, + IsRead = 1 << 0, + IsWrite = 1 << 1, + IsPrefetch = 1 << 2, + IsInvalidate = 1 << 3, + IsRequest = 1 << 4, + IsResponse = 1 << 5, + NeedsResponse = 1 << 6, IsSWPrefetch = 1 << 7, IsHWPrefetch = 1 << 8, IsUpgrade = 1 << 9, - HasData = 1 << 10 + HasData = 1 << 10 }; public: @@ -189,26 +190,27 @@ class Packet enum Command { InvalidCmd = 0, - ReadReq = IsRead | IsRequest | NeedsResponse, + ReadReq = IsRead | IsRequest | NeedsResponse, WriteReq = IsWrite | IsRequest | NeedsResponse | HasData, - WriteReqNoAck = IsWrite | IsRequest | HasData, + WriteReqNoAck = IsWrite | IsRequest | HasData, ReadResp = IsRead | IsResponse | NeedsResponse | HasData, - WriteResp = IsWrite | IsResponse | NeedsResponse, + WriteResp = IsWrite | IsResponse | NeedsResponse, Writeback = IsWrite | IsRequest | HasData, SoftPFReq = IsRead | IsRequest | IsSWPrefetch | NeedsResponse, HardPFReq = IsRead | IsRequest | IsHWPrefetch | NeedsResponse, SoftPFResp = IsRead | IsResponse | IsSWPrefetch - | NeedsResponse | HasData, + | NeedsResponse | HasData, HardPFResp = IsRead | IsResponse | IsHWPrefetch - | NeedsResponse | HasData, + | NeedsResponse | HasData, InvalidateReq = IsInvalidate | IsRequest, - WriteInvalidateReq = IsWrite | IsInvalidate | IsRequest - | HasData | NeedsResponse, - WriteInvalidateResp = IsWrite | IsInvalidate | IsRequest | NeedsResponse, + WriteInvalidateReq = IsWrite | IsInvalidate | IsRequest + | HasData | NeedsResponse, + WriteInvalidateResp = IsWrite | IsInvalidate | IsRequest + | NeedsResponse | IsResponse, UpgradeReq = IsInvalidate | IsRequest | IsUpgrade, ReadExReq = IsRead | IsInvalidate | IsRequest | NeedsResponse, ReadExResp = IsRead | IsInvalidate | IsResponse - | NeedsResponse | HasData + | NeedsResponse | HasData }; /** Return the string name of the cmd field (for debugging and @@ -308,6 +310,7 @@ class Packet * multiple transactions. */ void reinitFromRequest() { assert(req->validPaddr); + flags = 0; addr = req->paddr; size = req->size; time = req->time; @@ -341,10 +344,12 @@ class Packet srcValid = false; } - /** Take a request packet and modify it in place to be suitable - * for returning as a response to that request. + /** + * Take a request packet and modify it in place to be suitable for + * returning as a response to that request. */ - void makeAtomicResponse() { + void makeAtomicResponse() + { assert(needsResponse()); assert(isRequest()); int icmd = (int)cmd; @@ -357,50 +362,90 @@ class Packet cmd = (Command)icmd; } - /** Take a request packet that has been returned as NACKED and modify it so - * that it can be sent out again. Only packets that need a response can be - * NACKED, so verify that that is true. */ - void reinitNacked() { + /** + * Take a request packet that has been returned as NACKED and + * modify it so that it can be sent out again. Only packets that + * need a response can be NACKED, so verify that that is true. + */ + void + reinitNacked() + { assert(needsResponse() && result == Nacked); dest = Broadcast; result = Unknown; } - /** Set the data pointer to the following value that should not be freed. */ + /** + * Set the data pointer to the following value that should not be + * freed. + */ + template <typename T> + void + dataStatic(T *p) + { + if(dynamicData) + dynamicData = false; + data = (PacketDataPtr)p; + staticData = true; + } + + /** + * Set the data pointer to a value that should have delete [] + * called on it. + */ template <typename T> - void dataStatic(T *p); + void + dataDynamicArray(T *p) + { + assert(!staticData && !dynamicData); + data = (PacketDataPtr)p; + dynamicData = true; + arrayData = true; + } - /** Set the data pointer to a value that should have delete [] called on it. + /** + * set the data pointer to a value that should have delete called + * on it. */ template <typename T> - void dataDynamicArray(T *p); + void + dataDynamic(T *p) + { + assert(!staticData && !dynamicData); + data = (PacketDataPtr)p; + dynamicData = true; + arrayData = false; + } - /** set the data pointer to a value that should have delete called on it. */ + /** get a pointer to the data ptr. */ template <typename T> - void dataDynamic(T *p); + T* + getPtr() + { + assert(staticData || dynamicData); + return (T*)data; + } /** return the value of what is pointed to in the packet. */ template <typename T> T get(); - /** get a pointer to the data ptr. */ - template <typename T> - T* getPtr(); - /** set the value in the data pointer to v. */ template <typename T> void set(T v); - /** delete the data pointed to in the data pointer. Ok to call to matter how - * data was allocted. */ + /** + * delete the data pointed to in the data pointer. Ok to call to + * matter how data was allocted. + */ void deleteData(); /** If there isn't data in the packet, allocate some. */ void allocate(); /** Do the packet modify the same addresses. */ - bool intersect(Packet *p); + bool intersect(PacketPtr p); }; @@ -409,7 +454,7 @@ class Packet * in the timing packet. It returns if the functional packet should continue to * traverse the memory hierarchy or not. */ -bool fixPacket(Packet *func, Packet *timing); +bool fixPacket(PacketPtr func, PacketPtr timing); std::ostream & operator<<(std::ostream &o, const Packet &p); diff --git a/src/mem/packet_access.hh b/src/mem/packet_access.hh new file mode 100644 index 000000000..aac0c3ae5 --- /dev/null +++ b/src/mem/packet_access.hh @@ -0,0 +1,62 @@ +/* + * Copyright (c) 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: Ali Saidi + * Nathan Binkert + */ + +#include "arch/isa_traits.hh" +#include "mem/packet.hh" +#include "sim/byteswap.hh" + +#ifndef __MEM_PACKET_ACCESS_HH__ +#define __MEM_PACKET_ACCESS_HH__ +// The memory system needs to have an endianness. This is the easiest +// way to deal with it for now. At some point, we will have to remove +// these functions and make the users do their own byte swapping since +// the memory system does not in fact have an endianness. + +/** return the value of what is pointed to in the packet. */ +template <typename T> +inline T +Packet::get() +{ + assert(staticData || dynamicData); + assert(sizeof(T) <= size); + return TheISA::gtoh(*(T*)data); +} + +/** set the value in the data pointer to v. */ +template <typename T> +inline void +Packet::set(T v) +{ + assert(sizeof(T) <= size); + *(T*)data = TheISA::htog(v); +} + +#endif //__MEM_PACKET_ACCESS_HH__ diff --git a/src/mem/page_table.cc b/src/mem/page_table.cc index fa6d5ddfb..fe8094b88 100644 --- a/src/mem/page_table.cc +++ b/src/mem/page_table.cc @@ -170,11 +170,14 @@ PageTable::serialize(std::ostream &os) int count = 0; - m5::hash_map<Addr,Addr>::iterator iter; - m5::hash_map<Addr,Addr>::iterator end; - for (iter = pTable.begin(); iter != end; ++iter,++count) { - paramOut(os, csprintf("ptable.entry%dvaddr", count),iter->first); - paramOut(os, csprintf("ptable.entry%dpaddr", count),iter->second); + m5::hash_map<Addr,Addr>::iterator iter = pTable.begin(); + m5::hash_map<Addr,Addr>::iterator end = pTable.end(); + while (iter != end) { + paramOut(os, csprintf("ptable.entry%dvaddr", count), iter->first); + paramOut(os, csprintf("ptable.entry%dpaddr", count), iter->second); + + ++iter; + ++count; } assert(count == pTable.size()); } diff --git a/src/mem/physical.cc b/src/mem/physical.cc index f5a0ade15..0302f7351 100644 --- a/src/mem/physical.cc +++ b/src/mem/physical.cc @@ -39,21 +39,17 @@ #include <iostream> #include <string> - +#include "arch/isa_traits.hh" #include "base/misc.hh" #include "config/full_system.hh" -#include "mem/packet_impl.hh" #include "mem/physical.hh" -#include "sim/host.hh" #include "sim/builder.hh" #include "sim/eventq.hh" -#include "arch/isa_traits.hh" - +#include "sim/host.hh" using namespace std; using namespace TheISA; - PhysicalMemory::PhysicalMemory(Params *p) : MemObject(p->name), pmemAddr(NULL), port(NULL), lat(p->latency), _params(p) { @@ -105,7 +101,7 @@ PhysicalMemory::deviceBlockSize() } Tick -PhysicalMemory::calculateLatency(Packet *pkt) +PhysicalMemory::calculateLatency(PacketPtr pkt) { return lat; } @@ -193,7 +189,7 @@ PhysicalMemory::checkLockedAddrList(Request *req) } void -PhysicalMemory::doFunctionalAccess(Packet *pkt) +PhysicalMemory::doFunctionalAccess(PacketPtr pkt) { assert(pkt->getAddr() + pkt->getSize() <= params()->addrRange.size()); @@ -281,14 +277,14 @@ PhysicalMemory::MemoryPort::deviceBlockSize() } Tick -PhysicalMemory::MemoryPort::recvAtomic(Packet *pkt) +PhysicalMemory::MemoryPort::recvAtomic(PacketPtr pkt) { memory->doFunctionalAccess(pkt); return memory->calculateLatency(pkt); } void -PhysicalMemory::MemoryPort::recvFunctional(Packet *pkt) +PhysicalMemory::MemoryPort::recvFunctional(PacketPtr pkt) { // Default implementation of SimpleTimingPort::recvFunctional() // calls recvAtomic() and throws away the latency; we can save a diff --git a/src/mem/physical.hh b/src/mem/physical.hh index 97bea2ec4..045e61612 100644 --- a/src/mem/physical.hh +++ b/src/mem/physical.hh @@ -57,9 +57,9 @@ class PhysicalMemory : public MemObject protected: - virtual Tick recvAtomic(Packet *pkt); + virtual Tick recvAtomic(PacketPtr pkt); - virtual void recvFunctional(Packet *pkt); + virtual void recvFunctional(PacketPtr pkt); virtual void recvStatusChange(Status status); @@ -172,8 +172,8 @@ class PhysicalMemory : public MemObject unsigned int drain(Event *de); protected: - void doFunctionalAccess(Packet *pkt); - virtual Tick calculateLatency(Packet *pkt); + void doFunctionalAccess(PacketPtr pkt); + virtual Tick calculateLatency(PacketPtr pkt); void recvStatusChange(Port::Status status); public: diff --git a/src/mem/port.cc b/src/mem/port.cc index 17924b759..bbc98c160 100644 --- a/src/mem/port.cc +++ b/src/mem/port.cc @@ -35,7 +35,6 @@ #include "base/chunk_generator.hh" #include "base/trace.hh" -#include "mem/packet_impl.hh" #include "mem/port.hh" void diff --git a/src/mem/port.hh b/src/mem/port.hh index bb3bc1b1b..b6eeb9db3 100644 --- a/src/mem/port.hh +++ b/src/mem/port.hh @@ -128,13 +128,13 @@ class Port * called by a peer port, never directly by any outside object. */ /** Called to recive a timing call from the peer port. */ - virtual bool recvTiming(Packet *pkt) = 0; + virtual bool recvTiming(PacketPtr pkt) = 0; /** Called to recive a atomic call from the peer port. */ - virtual Tick recvAtomic(Packet *pkt) = 0; + virtual Tick recvAtomic(PacketPtr pkt) = 0; /** Called to recive a functional call from the peer port. */ - virtual void recvFunctional(Packet *pkt) = 0; + virtual void recvFunctional(PacketPtr pkt) = 0; /** Called to recieve a status change from the peer port. */ virtual void recvStatusChange(Status status) = 0; @@ -172,14 +172,14 @@ class Port case a cache has a higher priority request come in while waiting for the bus to arbitrate. */ - bool sendTiming(Packet *pkt) { return peer->recvTiming(pkt); } + bool sendTiming(PacketPtr pkt) { return peer->recvTiming(pkt); } /** Function called by the associated device to send an atomic * access, an access in which the data is moved and the state is * updated in one cycle, without interleaving with other memory * accesses. Returns estimated latency of access. */ - Tick sendAtomic(Packet *pkt) + Tick sendAtomic(PacketPtr pkt) { return peer->recvAtomic(pkt); } /** Function called by the associated device to send a functional access, @@ -187,7 +187,7 @@ class Port memory system, without affecting the current state of any block or moving the block. */ - void sendFunctional(Packet *pkt) + void sendFunctional(PacketPtr pkt) { return peer->recvFunctional(pkt); } /** Called by the associated device to send a status change to the device @@ -252,9 +252,9 @@ class FunctionalPort : public Port {} protected: - virtual bool recvTiming(Packet *pkt) { panic("FuncPort is UniDir"); } - virtual Tick recvAtomic(Packet *pkt) { panic("FuncPort is UniDir"); } - virtual void recvFunctional(Packet *pkt) { panic("FuncPort is UniDir"); } + virtual bool recvTiming(PacketPtr pkt) { panic("FuncPort is UniDir"); } + virtual Tick recvAtomic(PacketPtr pkt) { panic("FuncPort is UniDir"); } + virtual void recvFunctional(PacketPtr pkt) { panic("FuncPort is UniDir"); } virtual void recvStatusChange(Status status) {} public: diff --git a/src/mem/tport.cc b/src/mem/tport.cc index 2d8e7dba4..55a461a8b 100644 --- a/src/mem/tport.cc +++ b/src/mem/tport.cc @@ -31,28 +31,27 @@ #include "mem/tport.hh" void -SimpleTimingPort::recvFunctional(Packet *pkt) +SimpleTimingPort::recvFunctional(PacketPtr pkt) { - //First check queued events - std::list<Packet *>::iterator i = transmitList.begin(); - std::list<Packet *>::iterator end = transmitList.end(); - bool cont = true; + std::list<PacketPtr>::iterator i = transmitList.begin(); + std::list<PacketPtr>::iterator end = transmitList.end(); - while (i != end && cont) { - Packet * target = *i; + while (i != end) { + PacketPtr target = *i; // If the target contains data, and it overlaps the // probed request, need to update data if (target->intersect(pkt)) fixPacket(pkt, target); } + //Then just do an atomic access and throw away the returned latency - if (cont) + if (pkt->result != Packet::Success) recvAtomic(pkt); } bool -SimpleTimingPort::recvTiming(Packet *pkt) +SimpleTimingPort::recvTiming(PacketPtr pkt) { // If the device is only a slave, it should only be sending // responses, which should never get nacked. There used to be diff --git a/src/mem/tport.hh b/src/mem/tport.hh index df6d48196..fbe81c443 100644 --- a/src/mem/tport.hh +++ b/src/mem/tport.hh @@ -60,7 +60,7 @@ class SimpleTimingPort : public Port protected: /** A list of outgoing timing response packets that haven't been * serviced yet. */ - std::list<Packet*> transmitList; + std::list<PacketPtr> transmitList; /** * This class is used to implemented sendTiming() with a delay. When @@ -71,10 +71,10 @@ class SimpleTimingPort : public Port class SendEvent : public Event { SimpleTimingPort *port; - Packet *packet; + PacketPtr packet; public: - SendEvent(SimpleTimingPort *p, Packet *pkt, Tick t) + SendEvent(SimpleTimingPort *p, PacketPtr pkt, Tick t) : Event(&mainEventQueue), port(p), packet(pkt) { setFlags(AutoDelete); schedule(curTick + t); } @@ -95,7 +95,7 @@ class SimpleTimingPort : public Port Event *drainEvent; /** Schedule a sendTiming() event to be called in the future. */ - void sendTimingLater(Packet *pkt, Tick time) + void sendTimingLater(PacketPtr pkt, Tick time) { outTiming++; new SendEvent(this, pkt, time); } /** This function is notification that the device should attempt to send a @@ -103,10 +103,10 @@ class SimpleTimingPort : public Port virtual void recvRetry(); /** Implemented using recvAtomic(). */ - void recvFunctional(Packet *pkt); + void recvFunctional(PacketPtr pkt); /** Implemented using recvAtomic(). */ - bool recvTiming(Packet *pkt); + bool recvTiming(PacketPtr pkt); /** * Simple ports generally don't care about any status diff --git a/src/python/m5/objects/MemTest.py b/src/python/m5/objects/MemTest.py index 83399be80..1219ddd4d 100644 --- a/src/python/m5/objects/MemTest.py +++ b/src/python/m5/objects/MemTest.py @@ -13,6 +13,7 @@ class MemTest(SimObject): percent_reads = Param.Percent(65, "target read percentage") percent_source_unaligned = Param.Percent(50, "percent of copy source address that are unaligned") + percent_functional = Param.Percent(50, "percent of access that are functional") percent_uncacheable = Param.Percent(10, "target uncacheable percentage") progress_interval = Param.Counter(1000000, diff --git a/src/sim/eventq.hh b/src/sim/eventq.hh index 537bfb918..fa65b08af 100644 --- a/src/sim/eventq.hh +++ b/src/sim/eventq.hh @@ -120,10 +120,22 @@ class Event : public Serializable, public FastAlloc /// priority; these values are used to control events that need to /// be ordered within a cycle. enum Priority { - /// Breakpoints should happen before anything else, so we - /// don't miss any action when debugging. + /// If we enable tracing on a particular cycle, do that as the + /// very first thing so we don't miss any of the events on + /// that cycle (even if we enter the debugger). + Trace_Enable_Pri = -101, + + /// Breakpoints should happen before anything else (except + /// enabling trace output), so we don't miss any action when + /// debugging. Debug_Break_Pri = -100, + /// CPU switches schedule the new CPU's tick event for the + /// same cycle (after unscheduling the old CPU's tick event). + /// The switch needs to come before any tick events to make + /// sure we don't tick both CPUs in the same cycle. + CPU_Switch_Pri = -31, + /// For some reason "delayed" inter-cluster writebacks are /// scheduled before regular writebacks (which have default /// priority). Steve? @@ -132,12 +144,6 @@ class Event : public Serializable, public FastAlloc /// Default is zero for historical reasons. Default_Pri = 0, - /// CPU switches schedule the new CPU's tick event for the - /// same cycle (after unscheduling the old CPU's tick event). - /// The switch needs to come before any tick events to make - /// sure we don't tick both CPUs in the same cycle. - CPU_Switch_Pri = -31, - /// Serailization needs to occur before tick events also, so /// that a serialize/unserialize is identical to an on-line /// CPU switch. diff --git a/src/sim/faults.cc b/src/sim/faults.cc index 650b728f7..cea35482a 100644 --- a/src/sim/faults.cc +++ b/src/sim/faults.cc @@ -37,7 +37,7 @@ #if !FULL_SYSTEM void FaultBase::invoke(ThreadContext * tc) { - fatal("fault (%s) detected @ PC 0x%08p", name(), tc->readPC()); + fatal("fault (%s) detected @ PC %p", name(), tc->readPC()); } #else void FaultBase::invoke(ThreadContext * tc) diff --git a/src/sim/main.cc b/src/sim/main.cc index 8bb0d7aaa..133141e57 100644 --- a/src/sim/main.cc +++ b/src/sim/main.cc @@ -55,6 +55,7 @@ #include "base/statistics.hh" #include "base/str.hh" #include "base/time.hh" +#include "config/pythonhome.hh" #include "cpu/base.hh" #include "cpu/smt.hh" #include "mem/mem_object.hh" @@ -145,6 +146,11 @@ main(int argc, char **argv) if (setenv("PYTHONPATH", pythonpath.c_str(), true) == -1) fatal("setenv: %s\n", strerror(errno)); + char *python_home = getenv("PYTHONHOME"); + if (!python_home) + python_home = PYTHONHOME; + Py_SetPythonHome(python_home); + // initialize embedded Python interpreter Py_Initialize(); PySys_SetArgv(argc, argv); diff --git a/src/sim/pseudo_inst.cc b/src/sim/pseudo_inst.cc index addf897c6..4eb0866a5 100644 --- a/src/sim/pseudo_inst.cc +++ b/src/sim/pseudo_inst.cc @@ -87,10 +87,15 @@ namespace AlphaPseudo EndQuiesceEvent *quiesceEvent = tc->getQuiesceEvent(); + Tick resume = curTick + Clock::Int::ns * ns; + if (quiesceEvent->scheduled()) - quiesceEvent->reschedule(curTick + Clock::Int::ns * ns); + quiesceEvent->reschedule(resume); else - quiesceEvent->schedule(curTick + Clock::Int::ns * ns); + quiesceEvent->schedule(resume); + + DPRINTF(Quiesce, "%s: quiesceNs(%d) until %d\n", + tc->getCpuPtr()->name(), ns, resume); tc->suspend(); if (tc->getKernelStats()) @@ -105,12 +110,15 @@ namespace AlphaPseudo EndQuiesceEvent *quiesceEvent = tc->getQuiesceEvent(); + Tick resume = curTick + tc->getCpuPtr()->cycles(cycles); + if (quiesceEvent->scheduled()) - quiesceEvent->reschedule(curTick + - tc->getCpuPtr()->cycles(cycles)); + quiesceEvent->reschedule(resume); else - quiesceEvent->schedule(curTick + - tc->getCpuPtr()->cycles(cycles)); + quiesceEvent->schedule(resume); + + DPRINTF(Quiesce, "%s: quiesceCycles(%d) until %d\n", + tc->getCpuPtr()->name(), cycles, resume); tc->suspend(); if (tc->getKernelStats()) diff --git a/src/sim/syscall_emul.hh b/src/sim/syscall_emul.hh index edd4e331d..e79712a19 100644 --- a/src/sim/syscall_emul.hh +++ b/src/sim/syscall_emul.hh @@ -356,6 +356,14 @@ convertStatBuf(target_stat &tgt, host_stat *host, bool fakeTTY = false) tgt->st_dev = htog(tgt->st_dev); tgt->st_ino = host->st_ino; tgt->st_ino = htog(tgt->st_ino); + tgt->st_mode = host->st_mode; + tgt->st_mode = htog(tgt->st_mode); + tgt->st_nlink = host->st_nlink; + tgt->st_nlink = htog(tgt->st_nlink); + tgt->st_uid = host->st_uid; + tgt->st_uid = htog(tgt->st_uid); + tgt->st_gid = host->st_gid; + tgt->st_gid = htog(tgt->st_gid); if (fakeTTY) tgt->st_rdev = 0x880d; else |