From 1b6355c89574c42c5b5f8014b994cf26dae4737d Mon Sep 17 00:00:00 2001 From: Steve Reinhardt Date: Sun, 17 Jan 2016 18:27:46 -0800 Subject: [PATCH] cpu. arch: add initiateMemRead() to ExecContext interface For historical reasons, the ExecContext interface had a single function, readMem(), that did two different things depending on whether the ExecContext supported atomic memory mode (i.e., AtomicSimpleCPU) or timing memory mode (all the other models). In the former case, it actually performed a memory read; in the latter case, it merely initiated a read access, and the read completion did not happen until later when a response packet arrived from the memory system. This led to some confusing things, including timing accesses being required to provide a pointer for the return data even though that pointer was only used in atomic mode. This patch splits this interface, adding a new initiateMemRead() function to the ExecContext interface to replace the timing-mode use of readMem(). For consistency and clarity, the readMemTiming() helper function in the ISA definitions is renamed to initiateMemRead() as well. For x86, where the access size is passed in explicitly, we can also get rid of the data parameter at this level. For other ISAs, where the access size is determined from the type of the data parameter, we have to keep the parameter for that purpose. --- src/arch/alpha/isa/mem.isa | 2 +- src/arch/arm/isa/templates/mem.isa | 8 +++--- src/arch/arm/isa/templates/mem64.isa | 2 +- src/arch/arm/isa/templates/neon64.isa | 5 +--- src/arch/generic/memhelpers.hh | 10 +++++--- src/arch/mips/isa/formats/mem.isa | 2 +- src/arch/power/isa/formats/mem.isa | 2 +- src/arch/sparc/isa/formats/mem/util.isa | 2 +- src/arch/x86/isa/formats/monitor_mwait.isa | 3 +-- src/arch/x86/isa/microops/ldstop.isa | 2 +- src/arch/x86/memhelpers.hh | 7 ++--- src/cpu/base_dyn_inst.hh | 12 ++------- src/cpu/exec_context.hh | 30 +++++++++++++++++++++- src/cpu/minor/exec_context.hh | 5 ++-- src/cpu/simple/atomic.cc | 6 +++++ src/cpu/simple/atomic.hh | 2 ++ src/cpu/simple/base.hh | 2 ++ src/cpu/simple/exec_context.hh | 6 +++++ src/cpu/simple/timing.cc | 7 +++++ src/cpu/simple/timing.hh | 2 ++ 20 files changed, 79 insertions(+), 38 deletions(-) diff --git a/src/arch/alpha/isa/mem.isa b/src/arch/alpha/isa/mem.isa index 71b1343404..6ba8ee5d08 100644 --- a/src/arch/alpha/isa/mem.isa +++ b/src/arch/alpha/isa/mem.isa @@ -223,7 +223,7 @@ def template LoadInitiateAcc {{ %(ea_code)s; if (fault == NoFault) { - fault = readMemTiming(xc, traceData, EA, Mem, memAccessFlags); + fault = initiateMemRead(xc, traceData, EA, Mem, memAccessFlags); } return fault; diff --git a/src/arch/arm/isa/templates/mem.isa b/src/arch/arm/isa/templates/mem.isa index bac1cd2114..51f598f504 100644 --- a/src/arch/arm/isa/templates/mem.isa +++ b/src/arch/arm/isa/templates/mem.isa @@ -438,7 +438,8 @@ def template LoadInitiateAcc {{ if (%(predicate_test)s) { if (fault == NoFault) { - fault = readMemTiming(xc, traceData, EA, Mem, memAccessFlags); + fault = initiateMemRead(xc, traceData, EA, Mem, + memAccessFlags); } } else { xc->setPredicate(false); @@ -461,13 +462,10 @@ def template NeonLoadInitiateAcc {{ %(op_rd)s; %(ea_code)s; - MemUnion memUnion; - uint8_t *dataPtr = memUnion.bytes; - if (%(predicate_test)s) { if (fault == NoFault) { - fault = xc->readMem(EA, dataPtr, %(size)d, memAccessFlags); + fault = xc->initiateMemRead(EA, %(size)d, memAccessFlags); } } else { xc->setPredicate(false); diff --git a/src/arch/arm/isa/templates/mem64.isa b/src/arch/arm/isa/templates/mem64.isa index 72ee882a76..e831f17a58 100644 --- a/src/arch/arm/isa/templates/mem64.isa +++ b/src/arch/arm/isa/templates/mem64.isa @@ -191,7 +191,7 @@ def template Load64InitiateAcc {{ %(ea_code)s; if (fault == NoFault) { - fault = readMemTiming(xc, traceData, EA, Mem, memAccessFlags); + fault = initiateMemRead(xc, traceData, EA, Mem, memAccessFlags); } return fault; diff --git a/src/arch/arm/isa/templates/neon64.isa b/src/arch/arm/isa/templates/neon64.isa index 19dd50910b..6356073c5b 100644 --- a/src/arch/arm/isa/templates/neon64.isa +++ b/src/arch/arm/isa/templates/neon64.isa @@ -313,11 +313,8 @@ def template NeonLoadInitiateAcc64 {{ %(op_rd)s; %(ea_code)s; - MemUnion memUnion; - uint8_t *dataPtr = memUnion.bytes; - if (fault == NoFault) { - fault = xc->readMem(EA, dataPtr, accSize, memAccessFlags); + fault = xc->initiateMemRead(EA, accSize, memAccessFlags); } return fault; diff --git a/src/arch/generic/memhelpers.hh b/src/arch/generic/memhelpers.hh index aa082553ab..b12e7b0b16 100644 --- a/src/arch/generic/memhelpers.hh +++ b/src/arch/generic/memhelpers.hh @@ -48,13 +48,15 @@ #include "sim/byteswap.hh" #include "sim/insttracer.hh" -/// Read from memory in timing mode. +/// Initiate a read from memory in timing mode. Note that the 'mem' +/// parameter is unused; only the type of that parameter is used +/// to determine the size of the access. template Fault -readMemTiming(XC *xc, Trace::InstRecord *traceData, Addr addr, - MemT &mem, unsigned flags) +initiateMemRead(XC *xc, Trace::InstRecord *traceData, Addr addr, + MemT &mem, unsigned flags) { - return xc->readMem(addr, (uint8_t *)&mem, sizeof(MemT), flags); + return xc->initiateMemRead(addr, sizeof(MemT), flags); } /// Extract the data returned from a timing mode read. diff --git a/src/arch/mips/isa/formats/mem.isa b/src/arch/mips/isa/formats/mem.isa index 80107be8b9..052ead82c3 100644 --- a/src/arch/mips/isa/formats/mem.isa +++ b/src/arch/mips/isa/formats/mem.isa @@ -253,7 +253,7 @@ def template LoadInitiateAcc {{ %(ea_code)s; if (fault == NoFault) { - fault = readMemTiming(xc, traceData, EA, Mem, memAccessFlags); + fault = initiateMemRead(xc, traceData, EA, Mem, memAccessFlags); } return fault; diff --git a/src/arch/power/isa/formats/mem.isa b/src/arch/power/isa/formats/mem.isa index 0c0dff6ca3..eafd6aea73 100644 --- a/src/arch/power/isa/formats/mem.isa +++ b/src/arch/power/isa/formats/mem.isa @@ -109,7 +109,7 @@ def template LoadInitiateAcc {{ %(ea_code)s; if (fault == NoFault) { - fault = readMemTiming(xc, traceData, EA, Mem, memAccessFlags); + fault = initiateMemRead(xc, traceData, EA, Mem, memAccessFlags); xc->setEA(EA); } diff --git a/src/arch/sparc/isa/formats/mem/util.isa b/src/arch/sparc/isa/formats/mem/util.isa index 53559e4931..a5c64dda54 100644 --- a/src/arch/sparc/isa/formats/mem/util.isa +++ b/src/arch/sparc/isa/formats/mem/util.isa @@ -171,7 +171,7 @@ def template LoadInitiateAcc {{ %(fault_check)s; if (fault == NoFault) { %(EA_trunc)s - fault = readMemTiming(xc, traceData, EA, Mem, %(asi_val)s); + fault = initiateMemRead(xc, traceData, EA, Mem, %(asi_val)s); } return fault; } diff --git a/src/arch/x86/isa/formats/monitor_mwait.isa b/src/arch/x86/isa/formats/monitor_mwait.isa index b26c1f2670..c901cedede 100644 --- a/src/arch/x86/isa/formats/monitor_mwait.isa +++ b/src/arch/x86/isa/formats/monitor_mwait.isa @@ -67,10 +67,9 @@ def template MwaitInitiateAcc {{ Fault %(class_name)s::initiateAcc(CPU_EXEC_CONTEXT * xc, Trace::InstRecord * traceData) const { - uint64_t m = 0; //mem unsigned s = 0x8; //size unsigned f = 0; //flags - readMemTiming(xc, traceData, xc->getAddrMonitor()->vAddr, m, s, f); + initiateMemRead(xc, traceData, xc->getAddrMonitor()->vAddr, s, f); return NoFault; } }}; diff --git a/src/arch/x86/isa/microops/ldstop.isa b/src/arch/x86/isa/microops/ldstop.isa index a7c201f441..fa8bc6f2b2 100644 --- a/src/arch/x86/isa/microops/ldstop.isa +++ b/src/arch/x86/isa/microops/ldstop.isa @@ -127,7 +127,7 @@ def template MicroLoadInitiateAcc {{ %(ea_code)s; DPRINTF(X86, "%s : %s: The address is %#x\n", instMnem, mnemonic, EA); - fault = readMemTiming(xc, traceData, EA, Mem, dataSize, memFlags); + fault = initiateMemRead(xc, traceData, EA, dataSize, memFlags); return fault; } diff --git a/src/arch/x86/memhelpers.hh b/src/arch/x86/memhelpers.hh index 6403273258..705457d675 100644 --- a/src/arch/x86/memhelpers.hh +++ b/src/arch/x86/memhelpers.hh @@ -38,12 +38,13 @@ namespace X86ISA { +/// Initiate a read from memory in timing mode. template Fault -readMemTiming(XC *xc, Trace::InstRecord *traceData, Addr addr, - uint64_t &mem, unsigned dataSize, unsigned flags) +initiateMemRead(XC *xc, Trace::InstRecord *traceData, Addr addr, + unsigned dataSize, unsigned flags) { - return xc->readMem(addr, (uint8_t *)&mem, dataSize, flags); + return xc->initiateMemRead(addr, dataSize, flags); } static inline uint64_t diff --git a/src/cpu/base_dyn_inst.hh b/src/cpu/base_dyn_inst.hh index b6b8c045ae..031337aec3 100644 --- a/src/cpu/base_dyn_inst.hh +++ b/src/cpu/base_dyn_inst.hh @@ -313,7 +313,7 @@ class BaseDynInst : public ExecContext, public RefCounted cpu->demapPage(vaddr, asn); } - Fault readMem(Addr addr, uint8_t *data, unsigned size, unsigned flags); + Fault initiateMemRead(Addr addr, unsigned size, unsigned flags); Fault writeMem(uint8_t *data, unsigned size, Addr addr, unsigned flags, uint64_t *res); @@ -873,8 +873,7 @@ class BaseDynInst : public ExecContext, public RefCounted template Fault -BaseDynInst::readMem(Addr addr, uint8_t *data, - unsigned size, unsigned flags) +BaseDynInst::initiateMemRead(Addr addr, unsigned size, unsigned flags) { instFlags[ReqMade] = true; Request *req = NULL; @@ -916,13 +915,6 @@ BaseDynInst::readMem(Addr addr, uint8_t *data, // instruction as executed. this->setExecuted(); } - - if (fault != NoFault) { - // Return a fixed value to keep simulation deterministic even - // along misspeculated paths. - if (data) - bzero(data, size); - } } if (traceData) diff --git a/src/cpu/exec_context.hh b/src/cpu/exec_context.hh index c65841db21..951c9c2b3e 100644 --- a/src/cpu/exec_context.hh +++ b/src/cpu/exec_context.hh @@ -12,6 +12,7 @@ * modified or unmodified, in source code or in binary form. * * Copyright (c) 2002-2005 The Regents of The University of Michigan + * Copyright (c) 2015 Advanced Micro Devices, Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -173,9 +174,36 @@ class ExecContext { */ virtual Addr getEA() const = 0; + /** + * Perform an atomic memory read operation. Must be overridden + * for exec contexts that support atomic memory mode. Not pure + * virtual since exec contexts that only support timing memory + * mode need not override (though in that case this function + * should never be called). + */ virtual Fault readMem(Addr addr, uint8_t *data, unsigned int size, - unsigned int flags) = 0; + unsigned int flags) + { + panic("ExecContext::readMem() should be overridden\n"); + } + /** + * Initiate a timing memory read operation. Must be overridden + * for exec contexts that support timing memory mode. Not pure + * virtual since exec contexts that only support atomic memory + * mode need not override (though in that case this function + * should never be called). + */ + virtual Fault initiateMemRead(Addr addr, unsigned int size, + unsigned int flags) + { + panic("ExecContext::initiateMemRead() should be overridden\n"); + } + + /** + * For atomic-mode contexts, perform an atomic memory write operation. + * For timing-mode contexts, initiate a timing memory write operation. + */ virtual Fault writeMem(uint8_t *data, unsigned int size, Addr addr, unsigned int flags, uint64_t *res) = 0; diff --git a/src/cpu/minor/exec_context.hh b/src/cpu/minor/exec_context.hh index 625d2b8776..092ad5a2dc 100644 --- a/src/cpu/minor/exec_context.hh +++ b/src/cpu/minor/exec_context.hh @@ -103,10 +103,9 @@ class ExecContext : public ::ExecContext } Fault - readMem(Addr addr, uint8_t *data, unsigned int size, - unsigned int flags) + initiateMemRead(Addr addr, unsigned int size, unsigned int flags) { - execute.getLSQ().pushRequest(inst, true /* load */, data, + execute.getLSQ().pushRequest(inst, true /* load */, nullptr, size, addr, flags, NULL); return NoFault; } diff --git a/src/cpu/simple/atomic.cc b/src/cpu/simple/atomic.cc index 77706966bc..4afd019d0b 100644 --- a/src/cpu/simple/atomic.cc +++ b/src/cpu/simple/atomic.cc @@ -415,6 +415,12 @@ AtomicSimpleCPU::readMem(Addr addr, uint8_t * data, } } +Fault +AtomicSimpleCPU::initiateMemRead(Addr addr, unsigned size, unsigned flags) +{ + panic("initiateMemRead() is for timing accesses, and should " + "never be called on AtomicSimpleCPU.\n"); +} Fault AtomicSimpleCPU::writeMem(uint8_t *data, unsigned size, diff --git a/src/cpu/simple/atomic.hh b/src/cpu/simple/atomic.hh index 1a2f19949e..c643bfe581 100644 --- a/src/cpu/simple/atomic.hh +++ b/src/cpu/simple/atomic.hh @@ -205,6 +205,8 @@ class AtomicSimpleCPU : public BaseSimpleCPU Fault readMem(Addr addr, uint8_t *data, unsigned size, unsigned flags) override; + Fault initiateMemRead(Addr addr, unsigned size, unsigned flags) override; + Fault writeMem(uint8_t *data, unsigned size, Addr addr, unsigned flags, uint64_t *res) override; diff --git a/src/cpu/simple/base.hh b/src/cpu/simple/base.hh index 0ec9e502bf..9164a2960b 100644 --- a/src/cpu/simple/base.hh +++ b/src/cpu/simple/base.hh @@ -145,6 +145,8 @@ class BaseSimpleCPU : public BaseCPU virtual Fault readMem(Addr addr, uint8_t* data, unsigned size, unsigned flags) = 0; + virtual Fault initiateMemRead(Addr addr, unsigned size, unsigned flags) = 0; + virtual Fault writeMem(uint8_t* data, unsigned size, Addr addr, unsigned flags, uint64_t* res) = 0; diff --git a/src/cpu/simple/exec_context.hh b/src/cpu/simple/exec_context.hh index 43a0124049..f9d80d0d51 100644 --- a/src/cpu/simple/exec_context.hh +++ b/src/cpu/simple/exec_context.hh @@ -291,6 +291,12 @@ class SimpleExecContext : public ExecContext { return cpu->readMem(addr, data, size, flags); } + Fault initiateMemRead(Addr addr, unsigned int size, + unsigned int flags) override + { + return cpu->initiateMemRead(addr, size, flags); + } + Fault writeMem(uint8_t *data, unsigned int size, Addr addr, unsigned int flags, uint64_t *res) override { diff --git a/src/cpu/simple/timing.cc b/src/cpu/simple/timing.cc index 6d67f610b5..441d5f8961 100644 --- a/src/cpu/simple/timing.cc +++ b/src/cpu/simple/timing.cc @@ -406,6 +406,13 @@ TimingSimpleCPU::buildSplitPacket(PacketPtr &pkt1, PacketPtr &pkt2, Fault TimingSimpleCPU::readMem(Addr addr, uint8_t *data, unsigned size, unsigned flags) +{ + panic("readMem() is for atomic accesses, and should " + "never be called on TimingSimpleCPU.\n"); +} + +Fault +TimingSimpleCPU::initiateMemRead(Addr addr, unsigned size, unsigned flags) { SimpleExecContext &t_info = *threadInfo[curThread]; SimpleThread* thread = t_info.thread; diff --git a/src/cpu/simple/timing.hh b/src/cpu/simple/timing.hh index 36e01e9be2..da83207931 100644 --- a/src/cpu/simple/timing.hh +++ b/src/cpu/simple/timing.hh @@ -286,6 +286,8 @@ class TimingSimpleCPU : public BaseSimpleCPU Fault readMem(Addr addr, uint8_t *data, unsigned size, unsigned flags) override; + Fault initiateMemRead(Addr addr, unsigned size, unsigned flags) override; + Fault writeMem(uint8_t *data, unsigned size, Addr addr, unsigned flags, uint64_t *res) override;