Merge m5.eecs.umich.edu:/bk/newmem

into  ewok.(none):/home/gblack/m5/newmem

--HG--
extra : convert_revision : 516c357f98c7a571c70362babd3fa162fbc2ed5a
This commit is contained in:
Gabe Black
2006-07-18 18:23:23 -04:00
290 changed files with 22098 additions and 5816 deletions

View File

@@ -62,7 +62,6 @@ base_sources = Split('''
base/range.cc
base/random.cc
base/sat_counter.cc
base/serializer.cc
base/socket.cc
base/statistics.cc
base/str.cc
@@ -85,33 +84,54 @@ base_sources = Split('''
cpu/base.cc
cpu/cpuevent.cc
cpu/exetrace.cc
cpu/func_unit.cc
cpu/op_class.cc
cpu/pc_event.cc
cpu/quiesce_event.cc
cpu/static_inst.cc
cpu/sampler/sampler.cc
cpu/simple_thread.cc
cpu/thread_state.cc
encumbered/cpu/full/fu_pool.cc
mem/bridge.cc
mem/bus.cc
mem/connector.cc
mem/mem_object.cc
mem/packet.cc
mem/physical.cc
mem/port.cc
mem/cache/base_cache.cc
mem/cache/cache.cc
mem/cache/coherence/coherence_protocol.cc
mem/cache/coherence/uni_coherence.cc
mem/cache/miss/blocking_buffer.cc
mem/cache/miss/miss_queue.cc
mem/cache/miss/mshr.cc
mem/cache/miss/mshr_queue.cc
mem/cache/prefetch/base_prefetcher.cc
mem/cache/prefetch/ghb_prefetcher.cc
mem/cache/prefetch/prefetcher.cc
mem/cache/prefetch/stride_prefetcher.cc
mem/cache/prefetch/tagged_prefetcher.cc
mem/cache/tags/base_tags.cc
mem/cache/tags/cache_tags.cc
mem/cache/tags/fa_lru.cc
mem/cache/tags/iic.cc
mem/cache/tags/lru.cc
mem/cache/tags/repl/gen.cc
mem/cache/tags/repl/repl.cc
mem/cache/tags/split.cc
mem/cache/tags/split_lifo.cc
mem/cache/tags/split_lru.cc
mem/cache/cache_builder.cc
sim/builder.cc
sim/configfile.cc
sim/debug.cc
sim/eventq.cc
sim/faults.cc
sim/main.cc
python/swig/main_wrap.cc
python/swig/cc_main_wrap.cc
sim/param.cc
sim/profile.cc
sim/root.cc
sim/serialize.cc
sim/sim_events.cc

View File

@@ -28,7 +28,7 @@
#
# Authors: Steve Reinhardt
import os.path
import os.path, sys
# Import build environment variable from SConstruct.
Import('env')
@@ -128,13 +128,19 @@ isa_desc_gen_files = Split('decoder.cc decoder.hh')
isa_desc_gen_files += [CpuModel.dict[cpu].filename
for cpu in env['CPU_MODELS']]
# Also include the CheckerCPU as one of the models if it is being
# enabled via command line.
if env['USE_CHECKER']:
isa_desc_gen_files += [CpuModel.dict['CheckerCPU'].filename]
# The emitter patches up the sources & targets to include the
# autogenerated files as targets and isa parser itself as a source.
def isa_desc_emitter(target, source, env):
return (isa_desc_gen_files, [isa_parser, cpu_models_file] + source)
# Pieces are in place, so create the builder.
isa_desc_builder = Builder(action='python2.4 $SOURCES $TARGET.dir $CPU_MODELS',
python = sys.executable # use same Python binary used to run scons
isa_desc_builder = Builder(action=python + ' $SOURCES $TARGET.dir $CPU_MODELS',
emitter = isa_desc_emitter)
env.Append(BUILDERS = { 'ISADesc' : isa_desc_builder })

View File

@@ -59,8 +59,12 @@ AlphaISA::initCPU(ThreadContext *tc, int cpuId)
tc->setIntReg(16, cpuId);
tc->setIntReg(0, cpuId);
tc->setPC(tc->readMiscReg(IPR_PAL_BASE) + (new ResetFault)->vect());
AlphaFault *reset = new ResetFault;
tc->setPC(tc->readMiscReg(IPR_PAL_BASE) + reset->vect());
tc->setNextPC(tc->readPC() + sizeof(MachInst));
delete reset;
}
////////////////////////////////////////////////////////////////////////

View File

@@ -35,6 +35,9 @@
#include "base/trace.hh"
#if FULL_SYSTEM
#include "arch/alpha/ev5.hh"
#else
#include "sim/process.hh"
#include "mem/page_table.hh"
#endif
namespace AlphaISA
@@ -56,6 +59,12 @@ FaultName ArithmeticFault::_name = "arith";
FaultVect ArithmeticFault::_vect = 0x0501;
FaultStat ArithmeticFault::_count;
#if !FULL_SYSTEM
FaultName PageTableFault::_name = "page_table_fault";
FaultVect PageTableFault::_vect = 0x0000;
FaultStat PageTableFault::_count;
#endif
FaultName InterruptFault::_name = "interrupt";
FaultVect InterruptFault::_vect = 0x0101;
FaultStat InterruptFault::_count;
@@ -173,6 +182,30 @@ void ItbFault::invoke(ThreadContext * tc)
AlphaFault::invoke(tc);
}
#else //!FULL_SYSTEM
void PageTableFault::invoke(ThreadContext *tc)
{
Process *p = tc->getProcessPtr();
// address is higher than the stack region or in the current stack region
if (vaddr > p->stack_base || vaddr > p->stack_min)
FaultBase::invoke(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",
p->stack_min, p->stack_base, p->stack_min - PageBytes,
p->stack_base, vaddr);
p->stack_min -= PageBytes;
if (p->stack_base - p->stack_min > 8*1024*1024)
fatal("Over max stack size for one thread\n");
p->pTable->allocate(p->stack_min, PageBytes);
} else {
FaultBase::invoke(tc);
}
}
#endif
} // namespace AlphaISA

View File

@@ -81,6 +81,29 @@ class AlignmentFault : public AlphaFault
bool isAlignmentFault() {return true;}
};
#if !FULL_SYSTEM
class PageTableFault : public AlphaFault
{
private:
Addr vaddr;
static FaultName _name;
static FaultVect _vect;
static FaultStat _count;
public:
PageTableFault(Addr va)
: vaddr(va) {}
FaultName name() {return _name;}
FaultVect vect() {return _vect;}
FaultStat & countStat() {return _count;}
void invoke(ThreadContext * tc);
};
static inline Fault genPageTableFault(Addr va)
{
return new PageTableFault(va);
}
#endif
static inline Fault genMachineCheckFault()
{
return new MachineCheckFault;

View File

@@ -97,6 +97,7 @@ BEGIN_DECLARE_SIM_OBJECT_PARAMS(FreebsdAlphaSystem)
Param<Tick> boot_cpu_frequency;
SimObjectParam<PhysicalMemory *> physmem;
SimpleEnumParam<System::MemoryMode> mem_mode;
Param<string> kernel;
Param<string> console;
@@ -115,6 +116,8 @@ BEGIN_INIT_SIM_OBJECT_PARAMS(FreebsdAlphaSystem)
INIT_PARAM(boot_cpu_frequency, "Frequency of the boot CPU"),
INIT_PARAM(physmem, "phsyical memory"),
INIT_ENUM_PARAM(mem_mode, "Memory Mode, (1=atomic, 2=timing)",
System::MemoryModeStrings),
INIT_PARAM(kernel, "file that contains the kernel code"),
INIT_PARAM(console, "file that contains the console code"),
INIT_PARAM(pal, "file that contains palcode"),
@@ -133,6 +136,7 @@ CREATE_SIM_OBJECT(FreebsdAlphaSystem)
p->name = getInstanceName();
p->boot_cpu_frequency = boot_cpu_frequency;
p->physmem = physmem;
p->mem_mode = mem_mode;
p->kernel_path = kernel;
p->console_path = console;
p->palcode = pal;

View File

@@ -47,9 +47,11 @@ decode OPCODE default Unknown::unknown() {
0x23: ldt({{ Fa = Mem.df; }});
0x2a: ldl_l({{ Ra.sl = Mem.sl; }}, mem_flags = LOCKED);
0x2b: ldq_l({{ Ra.uq = Mem.uq; }}, mem_flags = LOCKED);
#ifdef USE_COPY
0x20: MiscPrefetch::copy_load({{ EA = Ra; }},
{{ fault = xc->copySrcTranslate(EA); }},
inst_flags = [IsMemRef, IsLoad, IsCopy]);
#endif
}
format LoadOrPrefetch {
@@ -69,9 +71,11 @@ decode OPCODE default Unknown::unknown() {
0x0f: stq_u({{ Mem.uq = Ra.uq; }}, {{ EA = (Rb + disp) & ~7; }});
0x26: sts({{ Mem.ul = t_to_s(Fa.uq); }});
0x27: stt({{ Mem.df = Fa; }});
#ifdef USE_COPY
0x24: MiscPrefetch::copy_store({{ EA = Rb; }},
{{ fault = xc->copy(EA); }},
inst_flags = [IsMemRef, IsStore, IsCopy]);
#endif
}
format StoreCond {
@@ -659,11 +663,11 @@ decode OPCODE default Unknown::unknown() {
0xe000: rc({{
Ra = xc->readIntrFlag();
xc->setIntrFlag(0);
}}, IsNonSpeculative);
}}, IsNonSpeculative, IsUnverifiable);
0xf000: rs({{
Ra = xc->readIntrFlag();
xc->setIntrFlag(1);
}}, IsNonSpeculative);
}}, IsNonSpeculative, IsUnverifiable);
}
#else
format FailUnimpl {
@@ -701,7 +705,7 @@ decode OPCODE default Unknown::unknown() {
}}, IsNonSpeculative);
0x83: callsys({{
xc->syscall(R0);
}}, IsNonSpeculative);
}}, IsSerializeAfter, IsNonSpeculative);
// Read uniq reg into ABI return value register (r0)
0x9e: rduniq({{ R0 = Runiq; }}, IsIprAccess);
// Write uniq reg with value from ABI arg register (r16)

View File

@@ -150,9 +150,6 @@ LinuxAlphaSystem::~LinuxAlphaSystem()
delete debugPrintkEvent;
delete idleStartEvent;
delete printThreadEvent;
delete intStartEvent;
delete intEndEvent;
delete intEndEvent2;
}
@@ -194,6 +191,7 @@ BEGIN_DECLARE_SIM_OBJECT_PARAMS(LinuxAlphaSystem)
Param<Tick> boot_cpu_frequency;
SimObjectParam<PhysicalMemory *> physmem;
SimpleEnumParam<System::MemoryMode> mem_mode;
Param<string> kernel;
Param<string> console;
@@ -212,6 +210,8 @@ BEGIN_INIT_SIM_OBJECT_PARAMS(LinuxAlphaSystem)
INIT_PARAM(boot_cpu_frequency, "Frequency of the boot CPU"),
INIT_PARAM(physmem, "phsyical memory"),
INIT_ENUM_PARAM(mem_mode, "Memory Mode, (1=atomic, 2=timing)",
System::MemoryModeStrings),
INIT_PARAM(kernel, "file that contains the kernel code"),
INIT_PARAM(console, "file that contains the console code"),
INIT_PARAM(pal, "file that contains palcode"),
@@ -230,6 +230,7 @@ CREATE_SIM_OBJECT(LinuxAlphaSystem)
p->name = getInstanceName();
p->boot_cpu_frequency = boot_cpu_frequency;
p->physmem = physmem;
p->mem_mode = mem_mode;
p->kernel_path = kernel;
p->console_path = console;
p->palcode = pal;

View File

@@ -112,6 +112,10 @@ namespace AlphaISA
lock_flag = 0;
lock_addr = 0;
}
void serialize(std::ostream &os);
void unserialize(Checkpoint *cp, const std::string &section);
#if FULL_SYSTEM
protected:
typedef uint64_t InternalProcReg;

View File

@@ -26,6 +26,7 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Authors: Ali Saidi
* Nathan Binkert
*/
#include "arch/alpha/ev5.hh"
@@ -220,6 +221,7 @@ BEGIN_DECLARE_SIM_OBJECT_PARAMS(AlphaSystem)
Param<Tick> boot_cpu_frequency;
SimObjectParam<PhysicalMemory *> physmem;
SimpleEnumParam<System::MemoryMode> mem_mode;
Param<std::string> kernel;
Param<std::string> console;
@@ -238,6 +240,8 @@ BEGIN_INIT_SIM_OBJECT_PARAMS(AlphaSystem)
INIT_PARAM(boot_cpu_frequency, "Frequency of the boot CPU"),
INIT_PARAM(physmem, "phsyical memory"),
INIT_ENUM_PARAM(mem_mode, "Memory Mode, (1=atomic, 2=timing)",
System::MemoryModeStrings),
INIT_PARAM(kernel, "file that contains the kernel code"),
INIT_PARAM(console, "file that contains the console code"),
INIT_PARAM(pal, "file that contains palcode"),
@@ -256,6 +260,7 @@ CREATE_SIM_OBJECT(AlphaSystem)
p->name = getInstanceName();
p->boot_cpu_frequency = boot_cpu_frequency;
p->physmem = physmem;
p->mem_mode = mem_mode;
p->kernel_path = kernel;
p->console_path = console;
p->palcode = pal;

View File

@@ -26,6 +26,7 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Authors: Ali Saidi
* Nathan Binkert
*/
#ifndef __ARCH_ALPHA_SYSTEM_HH__

View File

@@ -95,6 +95,7 @@ BEGIN_DECLARE_SIM_OBJECT_PARAMS(Tru64AlphaSystem)
Param<Tick> boot_cpu_frequency;
SimObjectParam<PhysicalMemory *> physmem;
SimpleEnumParam<System::MemoryMode> mem_mode;
Param<string> kernel;
Param<string> console;
@@ -113,6 +114,8 @@ BEGIN_INIT_SIM_OBJECT_PARAMS(Tru64AlphaSystem)
INIT_PARAM(boot_cpu_frequency, "frequency of the boot cpu"),
INIT_PARAM(physmem, "phsyical memory"),
INIT_ENUM_PARAM(mem_mode, "Memory Mode, (1=atomic, 2=timing)",
System::MemoryModeStrings),
INIT_PARAM(kernel, "file that contains the kernel code"),
INIT_PARAM(console, "file that contains the console code"),
INIT_PARAM(pal, "file that contains palcode"),
@@ -131,6 +134,7 @@ CREATE_SIM_OBJECT(Tru64AlphaSystem)
p->name = getInstanceName();
p->boot_cpu_frequency = boot_cpu_frequency;
p->physmem = physmem;
p->mem_mode = mem_mode;
p->kernel_path = kernel;
p->console_path = console;
p->palcode = pal;

View File

@@ -52,8 +52,7 @@ base_sources = Split('''
# Full-system sources
full_system_sources = Split('''
memory.cc
mips34k.cc
#Insert Full-System Files Here
''')
# Syscall emulation (non-full-system) sources

View File

@@ -32,6 +32,10 @@
#include "cpu/thread_context.hh"
#include "cpu/base.hh"
#include "base/trace.hh"
#if !FULL_SYSTEM
#include "sim/process.hh"
#include "mem/page_table.hh"
#endif
namespace MipsISA
{
@@ -52,6 +56,12 @@ FaultName ArithmeticFault::_name = "arith";
FaultVect ArithmeticFault::_vect = 0x0501;
FaultStat ArithmeticFault::_count;
#if !FULL_SYSTEM
FaultName PageTableFault::_name = "page_table_fault";
FaultVect PageTableFault::_vect = 0x0000;
FaultStat PageTableFault::_count;
#endif
FaultName InterruptFault::_name = "interrupt";
FaultVect InterruptFault::_vect = 0x0101;
FaultStat InterruptFault::_count;
@@ -127,7 +137,28 @@ void ArithmeticFault::invoke(ThreadContext * tc)
panic("Arithmetic traps are unimplemented!");
}
#endif
#else //!FULL_SYSTEM
void PageTableFault::invoke(ThreadContext *tc)
{
Process *p = tc->getProcessPtr();
// address is higher than the stack region or in the current stack region
if (vaddr > p->stack_base || vaddr > p->stack_min)
FaultBase::invoke(tc);
// We've accessed the next page
if (vaddr > p->stack_min - PageBytes) {
p->stack_min -= PageBytes;
if (p->stack_base - p->stack_min > 8*1024*1024)
fatal("Over max stack size for one thread\n");
p->pTable->allocate(p->stack_min, PageBytes);
warn("Increasing stack size by one page.");
} else {
FaultBase::invoke(tc);
}
}
#endif
} // namespace MipsISA

View File

@@ -79,6 +79,30 @@ class AlignmentFault : public MipsFault
bool isAlignmentFault() {return true;}
};
#if !FULL_SYSTEM
class PageTableFault : public MipsFault
{
private:
Addr vaddr;
static FaultName _name;
static FaultVect _vect;
static FaultStat _count;
public:
PageTableFault(Addr va)
: vaddr(va) {}
FaultName name() {return _name;}
FaultVect vect() {return _vect;}
FaultStat & countStat() {return _count;}
void invoke(ThreadContext * tc);
};
static inline Fault genPageTableFault(Addr va)
{
return new PageTableFault(va);
}
#endif
static inline Fault genMachineCheckFault()
{
return new MachineCheckFault;

View File

@@ -1,6 +1,6 @@
// -*- mode:c++ -*-
// Copyright (c) 2003-2006 The Regents of The University of Michigan
// Copyright (c) 2006 The Regents of The University of Michigan
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
@@ -38,7 +38,6 @@ output header {{
using namespace MipsISA;
/**
* Base class for all MIPS static instructions.
*/

View File

@@ -1,6 +1,6 @@
// -*- mode:c++ -*-
// Copyright (c) 2003-2006 The Regents of The University of Michigan
// Copyright (c) 2006 The Regents of The University of Michigan
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without

View File

@@ -1,6 +1,6 @@
// -*- mode:c++ -*-
// Copyright (c) 2003-2006 The Regents of The University of Michigan
// Copyright (c) 2006 The Regents of The University of Michigan
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
@@ -158,14 +158,16 @@ decode OPCODE_HI default Unknown::unknown() {
}
format HiLoMiscOp {
0x2: div({{
HI = Rs.sd % Rt.sd;
LO = Rs.sd / Rt.sd;
}});
0x3: divu({{
HI = Rs.ud % Rt.ud;
LO = Rs.ud / Rt.ud;
}});
0x2: div({{ if (Rt.sd != 0) {
HI = Rs.sd % Rt.sd;
LO = Rs.sd / Rt.sd;
}
}});
0x3: divu({{ if (Rt.ud != 0) {
HI = Rs.ud % Rt.ud;
LO = Rs.ud / Rt.ud;
}
}});
}
}
@@ -333,7 +335,7 @@ decode OPCODE_HI default Unknown::unknown() {
0x0: decode RS_HI {
0x0: decode RS_LO {
format CP1Control {
0x0: mfc1 ({{ Rt.uw = Fs.uw<31:0>; }});
0x0: mfc1 ({{ Rt.uw = Fs.uw; }});
0x2: cfc1({{
switch (FS)
@@ -438,9 +440,10 @@ decode OPCODE_HI default Unknown::unknown() {
0x3: div_s({{ Fd.sf = Fs.sf / Ft.sf;}});
0x4: sqrt_s({{ Fd.sf = sqrt(Fs.sf);}});
0x5: abs_s({{ Fd.sf = fabs(Fs.sf);}});
0x6: mov_s({{ Fd.sf = Fs.sf;}});
0x7: neg_s({{ Fd.sf = -Fs.sf;}});
}
0x6: BasicOp::mov_s({{ Fd.sf = Fs.sf;}});
}
0x1: decode FUNCTION_LO {
@@ -549,9 +552,10 @@ decode OPCODE_HI default Unknown::unknown() {
0x3: div_d({{ Fd.df = Fs.df / Ft.df; }});
0x4: sqrt_d({{ Fd.df = sqrt(Fs.df); }});
0x5: abs_d({{ Fd.df = fabs(Fs.df); }});
0x6: mov_d({{ Fd.df = Fs.df; }});
0x7: neg_d({{ Fd.df = -1 * Fs.df; }});
}
0x6: BasicOp::mov_d({{ Fd.df = Fs.df; }});
}
0x1: decode FUNCTION_LO {
@@ -853,17 +857,19 @@ decode OPCODE_HI default Unknown::unknown() {
0x3: decode FUNCTION_HI {
0x0: decode FUNCTION_LO {
format LoadIndexedMemory {
0x0: lwxc1({{ Ft.uw = Mem.uw;}});
0x1: ldxc1({{ Ft.ud = Mem.ud;}});
0x5: luxc1({{ Ft.uw = Mem.ud;}});
0x0: lwxc1({{ Fd.uw = Mem.uw;}});
0x1: ldxc1({{ Fd.ud = Mem.ud;}});
0x5: luxc1({{ Fd.ud = Mem.ud;}},
{{ EA = (Rs + Rt) & ~7; }});
}
}
0x1: decode FUNCTION_LO {
format StoreIndexedMemory {
0x0: swxc1({{ Mem.uw = Ft.uw;}});
0x1: sdxc1({{ Mem.ud = Ft.ud;}});
0x5: suxc1({{ Mem.ud = Ft.ud;}});
0x0: swxc1({{ Mem.uw = Fs.uw;}});
0x1: sdxc1({{ Mem.ud = Fs.ud;}});
0x5: suxc1({{ Mem.ud = Fs.ud;}},
{{ EA = (Rs + Rt) & ~7; }});
}
0x7: Prefetch::prefx({{ EA = Rs + Rt; }});
@@ -991,7 +997,7 @@ decode OPCODE_HI default Unknown::unknown() {
0x7: decode FUNCTION_HI {
0x0: decode FUNCTION_LO {
format BasicOp {
0x1: ext({{ Rt.uw = bits(Rs.uw, MSB+LSB, LSB); }});
0x0: ext({{ Rt.uw = bits(Rs.uw, MSB+LSB, LSB); }});
0x4: ins({{ Rt.uw = bits(Rt.uw, 31, MSB+1) << (MSB+1) |
bits(Rs.uw, MSB-LSB, 0) << LSB |
bits(Rt.uw, LSB-1, 0);
@@ -1014,8 +1020,8 @@ decode OPCODE_HI default Unknown::unknown() {
Rt.uw<7:0> << 8 |
Rt.uw<15:8>;
}});
0x10: seb({{ Rd.sw = Rt.sw<7:0>}});
0x18: seh({{ Rd.sw = Rt.sw<15:0>}});
0x10: seb({{ Rd.sw = Rt.sb; }});
0x18: seh({{ Rd.sw = Rt.sh; }});
}
}

View File

@@ -1,6 +1,6 @@
// -*- mode:c++ -*-
// Copyright (c) 2003-2006 The Regents of The University of Michigan
// Copyright (c) 2006 The Regents of The University of Michigan
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without

View File

@@ -1,6 +1,6 @@
// -*- mode:c++ -*-
// Copyright (c) 2003-2006 The Regents of The University of Michigan
// Copyright (c) 2006 The Regents of The University of Michigan
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without

View File

@@ -1,6 +1,6 @@
// -*- mode:c++ -*-
// Copyright (c) 2003-2006 The Regents of The University of Michigan
// Copyright (c) 2006 The Regents of The University of Michigan
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without

View File

@@ -1,6 +1,6 @@
// -*- mode:c++ -*-
// Copyright (c) 2003-2006 The Regents of The University of Michigan
// Copyright (c) 2006 The Regents of The University of Michigan
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
@@ -142,10 +142,10 @@ output exec {{
cpu->setFloatRegBits(inst, 0, mips_nan, size);
//Read FCSR from FloatRegFile
uint32_t fcsr_bits = cpu->tc->readFloatRegBits(FCSR);
uint32_t fcsr_bits = cpu->tcBase()->readFloatRegBits(FCSR);
//Write FCSR from FloatRegFile
cpu->tc->setFloatRegBits(FCSR, genInvalidVector(fcsr_bits));
cpu->tcBase()->setFloatRegBits(FCSR, genInvalidVector(fcsr_bits));
if (traceData) { traceData->setData(mips_nan); }
return true;
@@ -158,12 +158,12 @@ output exec {{
fpResetCauseBits(%(CPU_exec_context)s *cpu)
{
//Read FCSR from FloatRegFile
uint32_t fcsr = cpu->tc->readFloatRegBits(FCSR);
uint32_t fcsr = cpu->tcBase()->readFloatRegBits(FCSR);
fcsr = bits(fcsr, 31, 18) << 18 | bits(fcsr, 11, 0);
//Write FCSR from FloatRegFile
cpu->tc->setFloatRegBits(FCSR, fcsr);
cpu->tcBase()->setFloatRegBits(FCSR, fcsr);
}
}};
@@ -176,8 +176,9 @@ def template FloatingPointExecute {{
//When is the right time to reset cause bits?
//start of every instruction or every cycle?
#if FULL_SYSTEM
fpResetCauseBits(xc);
#endif
%(op_decl)s;
%(op_rd)s;
@@ -192,7 +193,10 @@ def template FloatingPointExecute {{
//----
//Check for IEEE 754 FP Exceptions
//fault = fpNanOperands((FPOp*)this, xc, Fd, traceData);
if (!fpInvalidOp((FPOp*)this, xc, Fd, traceData) &&
if (
#if FULL_SYSTEM
!fpInvalidOp((FPOp*)this, xc, Fd, traceData) &&
#endif
fault == NoFault)
{
%(op_wb)s;

View File

@@ -1,6 +1,6 @@
// -*- mode:c++ -*-
// Copyright (c) 2003-2006 The Regents of The University of Michigan
// Copyright (c) 2006 The Regents of The University of Michigan
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
@@ -228,7 +228,7 @@ def format IntOp(code, *opt_flags) {{
iop = InstObjParams(name, Name, 'IntOp', CodeBlock(code), opt_flags)
header_output = BasicDeclare.subst(iop)
decoder_output = BasicConstructor.subst(iop)
decode_block = OperateNopCheckDecode.subst(iop)
decode_block = RegNopCheckDecode.subst(iop)
exec_output = BasicExecute.subst(iop)
}};
@@ -236,7 +236,7 @@ def format IntImmOp(code, *opt_flags) {{
iop = InstObjParams(name, Name, 'IntImmOp', CodeBlock(code), opt_flags)
header_output = BasicDeclare.subst(iop)
decoder_output = BasicConstructor.subst(iop)
decode_block = OperateNopCheckDecode.subst(iop)
decode_block = ImmNopCheckDecode.subst(iop)
exec_output = BasicExecute.subst(iop)
}};
@@ -252,7 +252,7 @@ def format HiLoOp(code, *opt_flags) {{
iop = InstObjParams(name, Name, 'HiLoOp', CodeBlock(code), opt_flags)
header_output = BasicDeclare.subst(iop)
decoder_output = BasicConstructor.subst(iop)
decode_block = OperateNopCheckDecode.subst(iop)
decode_block = BasicDecode.subst(iop)
exec_output = HiLoExecute.subst(iop)
}};
@@ -260,7 +260,7 @@ def format HiLoMiscOp(code, *opt_flags) {{
iop = InstObjParams(name, Name, 'HiLoMiscOp', CodeBlock(code), opt_flags)
header_output = BasicDeclare.subst(iop)
decoder_output = BasicConstructor.subst(iop)
decode_block = OperateNopCheckDecode.subst(iop)
decode_block = BasicDecode.subst(iop)
exec_output = HiLoExecute.subst(iop)
}};

View File

@@ -1,6 +1,6 @@
// -*- mode:c++ -*-
// Copyright (c) 2003-2005 The Regents of The University of Michigan
// Copyright (c) 2006 The Regents of The University of Michigan
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
@@ -58,14 +58,8 @@ output header {{
StaticInstPtr _memAccPtr = nullStaticInstPtr)
: MipsStaticInst(mnem, _machInst, __opClass),
memAccessFlags(0), eaCompPtr(_eaCompPtr), memAccPtr(_memAccPtr),
disp(OFFSET)
disp(sext<16>(OFFSET))
{
//If Bit 15 is 1 then Sign Extend
int32_t temp = disp & 0x00008000;
if (temp > 0) {
disp |= 0xFFFF0000;
}
}
std::string
@@ -77,6 +71,24 @@ output header {{
const StaticInstPtr &memAccInst() const { return memAccPtr; }
};
/**
* Base class for a few miscellaneous memory-format insts
* that don't interpret the disp field
*/
class MemoryNoDisp : public Memory
{
protected:
/// Constructor
MemoryNoDisp(const char *mnem, ExtMachInst _machInst, OpClass __opClass,
StaticInstPtr _eaCompPtr = nullStaticInstPtr,
StaticInstPtr _memAccPtr = nullStaticInstPtr)
: Memory(mnem, _machInst, __opClass, _eaCompPtr, _memAccPtr)
{
}
std::string
generateDisassembly(Addr pc, const SymbolTable *symtab) const;
};
}};
@@ -84,10 +96,18 @@ output decoder {{
std::string
Memory::generateDisassembly(Addr pc, const SymbolTable *symtab) const
{
return csprintf("%-10s %c%d,%d(r%d)", mnemonic,
return csprintf("%-10s %c%d, %d(r%d)", mnemonic,
flags[IsFloating] ? 'f' : 'r', RT, disp, RS);
}
std::string
MemoryNoDisp::generateDisassembly(Addr pc, const SymbolTable *symtab) const
{
return csprintf("%-10s %c%d, r%d(r%d)", mnemonic,
flags[IsFloating] ? 'f' : 'r',
flags[IsFloating] ? FD : RD,
RS, RT);
}
}};
def template LoadStoreDeclare {{
@@ -479,23 +499,11 @@ def template MiscCompleteAcc {{
}
}};
// load instructions use Rt as dest, so check for
// Rt == 0 to detect nops
def template LoadNopCheckDecode {{
{
MipsStaticInst *i = new %(class_name)s(machInst);
if (RT == 0) {
i = makeNop(i);
}
return i;
}
}};
def format LoadMemory(memacc_code, ea_code = {{ EA = Rs + disp; }},
mem_flags = [], inst_flags = []) {{
(header_output, decoder_output, decode_block, exec_output) = \
LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags,
decode_template = LoadNopCheckDecode,
decode_template = ImmNopCheckDecode,
exec_template_base = 'Load')
}};
@@ -510,7 +518,7 @@ def format LoadIndexedMemory(memacc_code, ea_code = {{ EA = Rs + Rt; }},
mem_flags = [], inst_flags = []) {{
(header_output, decoder_output, decode_block, exec_output) = \
LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags,
decode_template = LoadNopCheckDecode,
decode_template = ImmNopCheckDecode,
exec_template_base = 'Load')
}};
@@ -534,7 +542,7 @@ def format LoadUnalignedMemory(memacc_code, ea_code = {{ EA = (Rs + disp) & ~3;
(header_output, decoder_output, decode_block, exec_output) = \
LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags,
decode_template = LoadNopCheckDecode,
decode_template = ImmNopCheckDecode,
exec_template_base = 'Load')
}};
@@ -551,7 +559,6 @@ def format StoreUnalignedMemory(memacc_code, ea_code = {{ EA = (Rs + disp) & ~3;
(header_output, decoder_output, decode_block, exec_output) = \
LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags,
decode_template = LoadNopCheckDecode,
exec_template_base = 'Store')
}};

View File

@@ -1,6 +1,6 @@
// -*- mode:c++ -*-
// Copyright (c) 2003-2006 The Regents of The University of Michigan
// Copyright (c) 2006 The Regents of The University of Michigan
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
@@ -35,14 +35,15 @@
output header {{
/**
* Base class for integer operations.
* Base class for MIPS MT ASE operations.
*/
class MT : public MipsStaticInst
{
protected:
/// Constructor
MT(const char *mnem, MachInst _machInst, OpClass __opClass) : MipsStaticInst(mnem, _machInst, __opClass)
MT(const char *mnem, MachInst _machInst, OpClass __opClass) :
MipsStaticInst(mnem, _machInst, __opClass)
{
}

View File

@@ -1,6 +1,6 @@
// -*- mode:c++ -*-
// Copyright (c) 2003-2006 The Regents of The University of Michigan
// Copyright (c) 2006 The Regents of The University of Michigan
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
@@ -73,7 +73,8 @@ output decoder {{
MipsStaticInst *
makeNop(MipsStaticInst *inst)
{
MipsStaticInst *nop = new Nop(inst->disassemble(0), inst->machInst);
std::string nop_str = "(" + inst->disassemble(0) + ")";
MipsStaticInst *nop = new Nop(nop_str, inst->machInst);
delete inst;
return nop;
}
@@ -87,16 +88,36 @@ output exec {{
}
}};
// integer & FP operate instructions use RT as dest, so check for
// RT == 0 to detect nops
// Int & FP operate instructions use RD as dest, so check for
// RD == 0 to detect nops
def template RegNopCheckDecode {{
{
MipsStaticInst *i = new %(class_name)s(machInst);
//if (RD == 0) {
//i = makeNop(i);
//}
return i;
}
}};
def template OperateNopCheckDecode {{
{
MipsStaticInst *i = new %(class_name)s(machInst);
//if (RD == 0) {
// i = makeNop(i);
// i = makeNop(i);
//}
return i;
}
}};
// IntImm & Memory instructions use Rt as dest, so check for
// Rt == 0 to detect nops
def template ImmNopCheckDecode {{
{
MipsStaticInst *i = new %(class_name)s(machInst);
//if (RT == 0) {
// i = makeNop(i);
// }
return i;
}
}};

View File

@@ -1,6 +1,6 @@
// -*- mode:c++ -*-
// Copyright (c) 2003-2006 The Regents of The University of Michigan
// Copyright (c) 2006 The Regents of The University of Michigan
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without

View File

@@ -1,6 +1,6 @@
// -*- mode:c++ -*-
// Copyright (c) 2003-2006 The Regents of The University of Michigan
// Copyright (c) 2006 The Regents of The University of Michigan
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
@@ -70,7 +70,7 @@ def template TrapExecute {{
}};
def format Trap(code, *flags) {{
code = 'panic(\"'
code = 'warn(\"'
code += 'Trap Exception Handler Is Currently Not Implemented.'
code += '\");'
iop = InstObjParams(name, Name, 'MipsStaticInst', CodeBlock(code), flags)

View File

@@ -1,7 +1,7 @@
// -*- mode:c++ -*-
// Copyright (c) 2003-2005 The Regents of The University of Michigan
// Copyright (c) 2006 The Regents of The University of Michigan
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without

View File

@@ -1,6 +1,6 @@
// -*- mode:c++ -*-
// Copyright (c) 2003-2006 The Regents of The University of Michigan
// Copyright (c) 2006 The Regents of The University of Michigan
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without

View File

@@ -1,6 +1,6 @@
// -*- mode:c++ -*-
// Copyright (c) 2003-2006 The Regents of The University of Michigan
// Copyright (c) 2006 The Regents of The University of Michigan
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without

View File

@@ -1,6 +1,6 @@
// -*- mode:c++ -*-
// Copyright (c) 2003-2006 The Regents of The University of Michigan
// Copyright (c) 2006 The Regents of The University of Michigan
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without

View File

@@ -1,6 +1,6 @@
// -*- mode:c++ -*-
// Copyright (c) 2003-2005 The Regents of The University of Michigan
// Copyright (c) 2006 The Regents of The University of Michigan
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without

View File

@@ -1,6 +1,6 @@
// -*- mode:c++ -*-
// Copyright (c) 2003-2006 The Regents of The University of Michigan
// Copyright (c) 2006 The Regents of The University of Michigan
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
@@ -53,8 +53,8 @@ def operands {{
'R2': ('IntReg', 'uw','2', 'IsInteger', 5),
#Special Integer Reg operands
'HI': ('IntReg', 'uw','32', 'IsInteger', 6),
'LO': ('IntReg', 'uw','33', 'IsInteger', 7),
'HI': ('IntReg', 'uw','MipsISA::HI', 'IsInteger', 6),
'LO': ('IntReg', 'uw','MipsISA::LO', 'IsInteger', 7),
#Immediate Value operand
'IntImm': ('IntReg', 'uw', 'INTIMM', 'IsInteger', 3),
@@ -66,11 +66,11 @@ def operands {{
'Fr': ('FloatReg', 'sf', 'FR', 'IsFloating', 3),
#Special Floating Point Control Reg Operands
'FIR': ('FloatReg', 'uw', '32', 'IsFloating', 1),
'FCCR': ('FloatReg', 'uw', '33', 'IsFloating', 2),
'FEXR': ('FloatReg', 'uw', '34', 'IsFloating', 3),
'FENR': ('FloatReg', 'uw', '35', 'IsFloating', 3),
'FCSR': ('FloatReg', 'uw', '36', 'IsFloating', 3),
'FIR': ('FloatReg', 'uw', 'MipsISA::FIR', 'IsFloating', 1),
'FCCR': ('FloatReg', 'uw', 'MipsISA::FCCR', 'IsFloating', 2),
'FEXR': ('FloatReg', 'uw', 'MipsISA::FEXR', 'IsFloating', 3),
'FENR': ('FloatReg', 'uw', 'MipsISA::FENR', 'IsFloating', 3),
'FCSR': ('FloatReg', 'uw', 'MipsISA::FCSR', 'IsFloating', 3),
#Operands For Paired Singles FP Operations
'Fd1': ('FloatReg', 'sf', 'FD', 'IsFloating', 4),

View File

@@ -30,7 +30,7 @@
*/
#include "arch/mips/isa_traits.hh"
#include "config/full_system.hh"
//#include "config/full_system.hh"
#include "cpu/static_inst.hh"
#include "sim/serialize.hh"
#include "base/bitfield.hh"
@@ -43,39 +43,20 @@ void
MipsISA::copyRegs(ThreadContext *src, ThreadContext *dest)
{
panic("Copy Regs Not Implemented Yet\n");
/*fpcr = xc->readMiscReg(MipsISA::Fpcr_DepTag);
uniq = xc->readMiscReg(MipsISA::Uniq_DepTag);
lock_flag = xc->readMiscReg(MipsISA::Lock_Flag_DepTag);
lock_addr = xc->readMiscReg(MipsISA::Lock_Addr_DepTag);
}
#if FULL_SYSTEM
copyIprs(xc);
#endif*/
void
MipsISA::copyMiscRegs(ThreadContext *src, ThreadContext *dest)
{
panic("Copy Misc. Regs Not Implemented Yet\n");
}
void
MipsISA::MiscRegFile::copyMiscRegs(ThreadContext *tc)
{
panic("Copy Misc. Regs Not Implemented Yet\n");
/*fpcr = xc->readMiscReg(MipsISA::Fpcr_DepTag);
uniq = xc->readMiscReg(MipsISA::Uniq_DepTag);
lock_flag = xc->readMiscReg(MipsISA::Lock_Flag_DepTag);
lock_addr = xc->readMiscReg(MipsISA::Lock_Addr_DepTag);
#endif*/
}
#if FULL_SYSTEM
static inline Addr
TruncPage(Addr addr)
{ return addr & ~(MipsISA::PageBytes - 1); }
static inline Addr
RoundPage(Addr addr)
{ return (addr + MipsISA::PageBytes - 1) & ~(MipsISA::PageBytes - 1); }
#endif
void
IntRegFile::serialize(std::ostream &os)
{
@@ -100,12 +81,6 @@ RegFile::serialize(std::ostream &os)
SERIALIZE_SCALAR(pc);
SERIALIZE_SCALAR(npc);
SERIALIZE_SCALAR(nnpc);
#if FULL_SYSTEM
SERIALIZE_ARRAY(palregs, NumIntRegs);
SERIALIZE_ARRAY(ipr, NumInternalProcRegs);
SERIALIZE_SCALAR(intrflag);
SERIALIZE_SCALAR(pal_shadow);
#endif
}
@@ -121,43 +96,5 @@ RegFile::unserialize(Checkpoint *cp, const std::string &section)
UNSERIALIZE_SCALAR(pc);
UNSERIALIZE_SCALAR(npc);
UNSERIALIZE_SCALAR(nnpc);
#if FULL_SYSTEM
UNSERIALIZE_ARRAY(palregs, NumIntRegs);
UNSERIALIZE_ARRAY(ipr, NumInternalProcRegs);
UNSERIALIZE_SCALAR(intrflag);
UNSERIALIZE_SCALAR(pal_shadow);
#endif
}
#if FULL_SYSTEM
void
PTE::serialize(std::ostream &os)
{
SERIALIZE_SCALAR(tag);
SERIALIZE_SCALAR(ppn);
SERIALIZE_SCALAR(xre);
SERIALIZE_SCALAR(xwe);
SERIALIZE_SCALAR(asn);
SERIALIZE_SCALAR(asma);
SERIALIZE_SCALAR(fonr);
SERIALIZE_SCALAR(fonw);
SERIALIZE_SCALAR(valid);
}
void
PTE::unserialize(Checkpoint *cp, const std::string &section)
{
UNSERIALIZE_SCALAR(tag);
UNSERIALIZE_SCALAR(ppn);
UNSERIALIZE_SCALAR(xre);
UNSERIALIZE_SCALAR(xwe);
UNSERIALIZE_SCALAR(asn);
UNSERIALIZE_SCALAR(asma);
UNSERIALIZE_SCALAR(fonr);
UNSERIALIZE_SCALAR(fonw);
UNSERIALIZE_SCALAR(valid);
}
#endif //FULL_SYSTEM

View File

@@ -57,12 +57,6 @@ namespace LittleEndianGuest {};
class StaticInst;
class StaticInstPtr;
namespace MIPS34K {
int DTB_ASN_ASN(uint64_t reg);
int ITB_ASN_ASN(uint64_t reg);
};
#if !FULL_SYSTEM
class SyscallReturn {
public:
template <class T>
@@ -95,7 +89,6 @@ class SyscallReturn {
uint64_t retval;
bool success;
};
#endif
namespace MipsISA
{
@@ -136,16 +129,10 @@ namespace MipsISA
template <class TC>
void zeroRegisters(TC *tc);
const Addr MaxAddr = (Addr)-1;
// const Addr MaxAddr = (Addr)-1;
void copyRegs(ThreadContext *src, ThreadContext *dest);
uint64_t fpConvert(double fp_val, ConvertType cvt_type);
double roundFP(double val, int digits);
double truncFP(double val);
bool getFPConditionCode(uint32_t fcsr_reg, int cc);
uint32_t makeCCVector(uint32_t fcsr, int num, bool val);
// Machine operations
void saveMachineReg(AnyReg &savereg, const RegFile &reg_file,
@@ -191,12 +178,6 @@ namespace MipsISA
};
#if FULL_SYSTEM
#include "arch/mips/mips34k.hh"
#endif
using namespace MipsISA;
#endif // __ARCH_MIPS_ISA_TRAITS_HH__

View File

@@ -1,3 +1,4 @@
/*
* Copyright (c) 2003-2004 The Regents of The University of Michigan
* All rights reserved.
@@ -40,6 +41,8 @@
using namespace std;
using namespace MipsISA;
Addr MipsLiveProcess::stack_start = 0x7FFFFFFF;
MipsLiveProcess::MipsLiveProcess(const std::string &nm, ObjectFile *objFile,
System *_system, int stdin_fd, int stdout_fd, int stderr_fd,
std::vector<std::string> &argv, std::vector<std::string> &envp)
@@ -48,10 +51,11 @@ MipsLiveProcess::MipsLiveProcess(const std::string &nm, ObjectFile *objFile,
{
// Set up stack. On MIPS, stack starts at the top of kuseg
// user address space. MIPS stack grows down from here
stack_base = 0x7FFFFFFF;
stack_base = stack_start;
// Set pointer for next thread stack. Reserve 8M for main stack.
next_thread_stack_base = stack_base - (8 * 1024 * 1024);
stack_start = next_thread_stack_base;
// Set up break point (Top of Heap)
brk_point = objFile->dataBase() + objFile->dataSize() + objFile->bssSize();

View File

@@ -50,6 +50,9 @@ class MipsLiveProcess : public LiveProcess
std::vector<std::string> &envp);
void startup();
static Addr stack_start;
};

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2003-2005 The Regents of The University of Michigan
* Copyright (c) 2006 The Regents of The University of Michigan
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -24,8 +24,6 @@
* 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: Korey Sewell
*/
#ifndef __ARCH_MIPS_FLOAT_REGFILE_HH__
@@ -34,13 +32,14 @@
#include "arch/mips/types.hh"
#include "arch/mips/constants.hh"
#include "base/misc.hh"
#include "base/bitfield.hh"
#include "config/full_system.hh"
#include "sim/byteswap.hh"
#include "sim/faults.hh"
#include "sim/host.hh"
class Checkpoint;
class ThreadContext;
class ExecContext;
class Regfile;
namespace MipsISA
@@ -101,8 +100,9 @@ namespace MipsISA
}
}
Fault setReg(int floatReg, const FloatReg &val, int width)
Fault setReg(int floatReg, const FloatRegVal &val, int width)
{
using namespace std;
switch(width)
{
case SingleWidth:
@@ -117,8 +117,8 @@ namespace MipsISA
{
const void *double_ptr = &val;
FloatReg64 temp_double = *(FloatReg64 *) double_ptr;
regs[floatReg + 1] = temp_double >> 32;
regs[floatReg] = 0x0000FFFF & temp_double;
regs[floatReg + 1] = bits(temp_double, 63, 32);
regs[floatReg] = bits(temp_double, 31, 0);
break;
}
@@ -140,8 +140,8 @@ namespace MipsISA
break;
case DoubleWidth:
regs[floatReg + 1] = val >> 32;
regs[floatReg] = val;
regs[floatReg + 1] = bits(val, 63, 32);
regs[floatReg] = bits(val, 31, 0);
break;
default:

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2003-2005 The Regents of The University of Michigan
* Copyright (c) 2006 The Regents of The University of Michigan
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -65,11 +65,6 @@ namespace MipsISA
};
enum MiscIntRegNums {
HI = NumIntArchRegs,
LO
};
} // namespace MipsISA
#endif

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2003-2005 The Regents of The University of Michigan
* Copyright (c) 2006 The Regents of The University of Michigan
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -45,18 +45,12 @@ namespace MipsISA
protected:
uint64_t fpcr; // floating point condition codes
uint64_t uniq; // process-unique register
bool lock_flag; // lock flag for LL/SC
Addr lock_addr; // lock address for LL/SC
MiscReg miscRegFile[NumMiscRegs];
public:
//These functions should be removed once the simplescalar cpu model
//has been replaced.
int getInstAsid();
int getDataAsid();
void copyMiscRegs(ThreadContext *tc);
MiscReg readReg(int misc_reg)
@@ -80,17 +74,6 @@ namespace MipsISA
miscRegFile[misc_reg] = val; return NoFault;
}
#if FULL_SYSTEM
void clearIprs() { }
protected:
InternalProcReg ipr[NumInternalProcRegs]; // Internal processor regs
private:
MiscReg readIpr(int idx, Fault &fault, ThreadContext *tc) { }
Fault setIpr(int idx, uint64_t val, ThreadContext *tc) { }
#endif
friend class RegFile;
};
} // namespace MipsISA

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2003-2005 The Regents of The University of Michigan
* Copyright (c) 2006 The Regents of The University of Michigan
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -81,12 +81,12 @@ namespace MipsISA
return miscRegFile.setRegWithEffect(miscReg, val, tc);
}
FloatReg readFloatReg(int floatReg)
FloatRegVal readFloatReg(int floatReg)
{
return floatRegFile.readReg(floatReg,SingleWidth);
}
FloatReg readFloatReg(int floatReg, int width)
FloatRegVal readFloatReg(int floatReg, int width)
{
return floatRegFile.readReg(floatReg,width);
}
@@ -101,12 +101,12 @@ namespace MipsISA
return floatRegFile.readRegBits(floatReg,width);
}
Fault setFloatReg(int floatReg, const FloatReg &val)
Fault setFloatReg(int floatReg, const FloatRegVal &val)
{
return floatRegFile.setReg(floatReg, val, SingleWidth);
}
Fault setFloatReg(int floatReg, const FloatReg &val, int width)
Fault setFloatReg(int floatReg, const FloatRegVal &val, int width)
{
return floatRegFile.setReg(floatReg, val, width);
}
@@ -168,16 +168,6 @@ namespace MipsISA
nnpc = val;
}
#if FULL_SYSTEM
IntReg palregs[NumIntRegs]; // PAL shadow registers
InternalProcReg ipr[NumInternalProcRegs]; // internal processor regs
int intrflag; // interrupt flag
bool pal_shadow; // using pal_shadow registers
inline int instAsid() { return MIPS34K::ITB_ASN_ASN(ipr[IPR_ITB_ASN]); }
inline int dataAsid() { return MIPS34K::DTB_ASN_ASN(ipr[IPR_DTB_ASN]); }
#endif // FULL_SYSTEM
void serialize(std::ostream &os);
void unserialize(Checkpoint *cp, const std::string &section);
@@ -193,9 +183,6 @@ namespace MipsISA
void copyMiscRegs(ThreadContext *src, ThreadContext *dest);
#if FULL_SYSTEM
void copyIprs(ThreadContext *src, ThreadContext *dest);
#endif
} // namespace MipsISA
#endif

View File

@@ -25,11 +25,11 @@
* (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: Ali Saidi
*/
#ifndef __ARCH_ALPHA_STACKTRACE_HH__
#define __ARCH_ALPHA_STACKTRACE_HH__
#ifndef __ARCH_MIPS_STACKTRACE_HH__
#define __ARCH_MIPS_STACKTRACE_HH__
#include "base/trace.hh"
#include "cpu/static_inst.hh"
@@ -118,4 +118,4 @@ StackTrace::trace(ThreadContext *tc, StaticInstPtr inst)
return true;
}
#endif // __ARCH_ALPHA_STACKTRACE_HH__
#endif // __ARCH_MIPS_STACKTRACE_HH__

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2003-2005 The Regents of The University of Michigan
* Copyright (c) 2006 The Regents of The University of Michigan
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -42,14 +42,15 @@ namespace MipsISA
typedef uint32_t IntReg;
// floating point register file entry type
typedef double FloatReg;
typedef uint32_t FloatReg32;
typedef uint64_t FloatReg64;
typedef uint64_t FloatRegBits;
typedef double FloatRegVal;
typedef double FloatReg;
// cop-0/cop-1 system control register
typedef uint64_t MiscReg;
typedef uint64_t InternalProcReg;
typedef union {
IntReg intreg;

View File

@@ -33,6 +33,10 @@
#include "cpu/thread_context.hh"
#include "cpu/base.hh"
#include "base/trace.hh"
#if !FULL_SYSTEM
#include "sim/process.hh"
#include "mem/page_table.hh"
#endif
namespace SparcISA
{
@@ -218,6 +222,13 @@ TrapType TrapInstruction::_baseTrapType = 0x100;
FaultPriority TrapInstruction::_priority = 16;
FaultStat TrapInstruction::_count;
#if !FULL_SYSTEM
FaultName PageTableFault::_name = "page_table_fault";
TrapType PageTableFault::_trapType = 0x0000;
FaultPriority PageTableFault::_priority = 0;
FaultStat PageTableFault::_count;
#endif
#if FULL_SYSTEM
void SparcFault::invoke(ThreadContext * tc)
@@ -249,9 +260,28 @@ void SparcFault::invoke(ThreadContext * tc)
void TrapInstruction::invoke(ThreadContext * tc)
{
tc->syscall(syscall_num);
// Should be handled in ISA.
}
void PageTableFault::invoke(ThreadContext *tc)
{
Process *p = tc->getProcessPtr();
// address is higher than the stack region or in the current stack region
if (vaddr > p->stack_base || vaddr > p->stack_min)
FaultBase::invoke(tc);
// We've accessed the next page
if (vaddr > p->stack_min - PageBytes) {
p->stack_min -= PageBytes;
if (p->stack_base - p->stack_min > 8*1024*1024)
fatal("Over max stack size for one thread\n");
p->pTable->allocate(p->stack_min, PageBytes);
warn("Increasing stack size by one page.");
} else {
FaultBase::invoke(tc);
}
}
#endif
} // namespace SparcISA

View File

@@ -83,6 +83,31 @@ class MemAddressNotAligned : public SparcFault
bool isAlignmentFault() {return true;}
};
#if !FULL_SYSTEM
class PageTableFault : public SparcFault
{
private:
Addr vaddr;
static FaultName _name;
static TrapType _trapType;
static FaultPriority _priority;
static FaultStat _count;
public:
PageTableFault(Addr va)
: vaddr(va) {}
FaultName name() {return _name;}
TrapType trapType() {return _trapType;}
FaultPriority priority() {return _priority;}
FaultStat & countStat() {return _count;}
void invoke(ThreadContext * tc);
};
static inline Fault genPageTableFault(Addr va)
{
return new PageTableFault(va);
}
#endif
static inline Fault genMachineCheckFault()
{
return new InternalProcessorError;
@@ -589,6 +614,7 @@ class TrapInstruction : public EnumeratedFault
#endif
};
} // SparcISA namespace
#endif // __FAULTS_HH__

View File

@@ -141,6 +141,7 @@ SparcSystem::unserialize(Checkpoint *cp, const std::string &section)
BEGIN_DECLARE_SIM_OBJECT_PARAMS(SparcSystem)
SimObjectParam<PhysicalMemory *> physmem;
SimpleEnumParam<System::MemoryMode> mem_mode;
Param<std::string> kernel;
Param<std::string> reset_bin;
@@ -161,6 +162,8 @@ BEGIN_INIT_SIM_OBJECT_PARAMS(SparcSystem)
INIT_PARAM(boot_cpu_frequency, "Frequency of the boot CPU"),
INIT_PARAM(physmem, "phsyical memory"),
INIT_ENUM_PARAM(mem_mode, "Memory Mode, (1=atomic, 2=timing)",
System::MemoryModeStrings),
INIT_PARAM(kernel, "file that contains the kernel code"),
INIT_PARAM(reset_bin, "file that contains the reset code"),
INIT_PARAM(hypervisor_bin, "file that contains the hypervisor code"),
@@ -183,6 +186,7 @@ CREATE_SIM_OBJECT(SparcSystem)
p->name = getInstanceName();
p->boot_cpu_frequency = boot_cpu_frequency;
p->physmem = physmem;
p->mem_mode = mem_mode;
p->kernel_path = kernel;
p->reset_bin = reset_bin;
p->hypervisor_bin = hypervisor_bin;

View File

@@ -180,13 +180,11 @@ FastAlloc::dump_oldest(int n)
// C interfaces to FastAlloc::dump_summary() and FastAlloc::dump_oldest().
// gdb seems to have trouble with calling C++ functions directly.
//
extern "C" void
fast_alloc_summary()
{
FastAlloc::dump_summary();
}
extern "C" void
fast_alloc_oldest(int n)
{
FastAlloc::dump_oldest(n);

View File

@@ -25,7 +25,8 @@
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Authors: Kevin Lim
* Authors: Nathan Binkert
* Kevin Lim
*/
#ifndef __BASE_TIMEBUF_HH__
@@ -214,6 +215,11 @@ class TimeBuffer
{
return wire(this, 0);
}
int getSize()
{
return size;
}
};
#endif // __BASE_TIMEBUF_HH__

View File

@@ -247,7 +247,6 @@ DebugOut()
//
// Dump trace buffer to specified file (cout if NULL)
//
extern "C"
void
dumpTrace(const char *filename)
{
@@ -269,7 +268,6 @@ dumpTrace(const char *filename)
// same facility as the "trace to file" feature, and will print error
// messages rather than clobbering an existing ostream pointer.
//
extern "C"
void
echoTrace(bool on)
{
@@ -289,7 +287,6 @@ echoTrace(bool on)
}
}
extern "C"
void
printTraceFlags()
{
@@ -338,14 +335,12 @@ tweakTraceFlag(const char *string, bool value)
cprintf("could not find flag %s\n", string);
}
extern "C"
void
setTraceFlag(const char *string)
{
tweakTraceFlag(string, true);
}
extern "C"
void
clearTraceFlag(const char *string)
{

View File

@@ -48,8 +48,10 @@ ccfilename = sys.argv[1] + '.cc'
# To define a new flag, simply add it to this list.
#
baseFlags = [
'Activity',
'AlphaConsole',
'BADADDR',
'BE',
'BPredRAS',
'Bus',
'BusAddrRanges',
@@ -84,6 +86,7 @@ baseFlags = [
'EthernetPIO',
'EthernetSM',
'Event',
'FE',
'Fault',
'Fetch',
'Flow',
@@ -97,6 +100,7 @@ baseFlags = [
'GDBSend',
'GDBWrite',
'HWPrefetch',
'IBE',
'IEW',
'IIC',
'IICMore',
@@ -115,10 +119,8 @@ baseFlags = [
'MSHR',
'Mbox',
'MemDepUnit',
'O3CPU',
'OzoneCPU',
'FE',
'IBE',
'BE',
'OzoneLSQ',
'PCEvent',
'PCIA',
@@ -132,6 +134,7 @@ baseFlags = [
'RenameMap',
'SQL',
'Sampler',
'Scoreboard',
'ScsiCtrl',
'ScsiDisk',
'ScsiNone',
@@ -155,8 +158,6 @@ baseFlags = [
'Uart',
'VtoPhys',
'WriteBarrier',
'Activity',
'Scoreboard',
'Writeback',
]
@@ -175,7 +176,7 @@ compoundFlagMap = {
'EthernetAll' : [ 'Ethernet', 'EthernetPIO', 'EthernetDMA', 'EthernetData' , 'EthernetDesc', 'EthernetIntr', 'EthernetSM', 'EthernetCksum' ],
'EthernetNoData' : [ 'Ethernet', 'EthernetPIO', 'EthernetDesc', 'EthernetIntr', 'EthernetSM', 'EthernetCksum' ],
'IdeAll' : [ 'IdeCtrl', 'IdeDisk' ],
'FullCPUAll' : [ 'Fetch', 'Decode', 'Rename', 'IEW', 'Commit', 'IQ', 'ROB', 'FreeList', 'RenameMap', 'LSQ', 'LSQUnit', 'StoreSet', 'MemDepUnit', 'DynInst', 'FullCPU', 'Activity','Scoreboard','Writeback'],
'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']
}

View File

@@ -68,6 +68,13 @@ mem_comp_sig_template = '''
virtual Fault completeAcc(uint8_t *data, %s *xc, Trace::InstRecord *traceData) const { panic("Not defined!"); return NoFault; };
'''
# Generate a temporary CPU list, including the CheckerCPU if
# it's enabled. This isn't used for anything else other than StaticInst
# headers.
temp_cpu_list = env['CPU_MODELS']
if env['USE_CHECKER']:
temp_cpu_list.append('CheckerCPU')
# Generate header.
def gen_cpu_exec_signatures(target, source, env):
f = open(str(target[0]), 'w')
@@ -75,7 +82,7 @@ def gen_cpu_exec_signatures(target, source, env):
#ifndef __CPU_STATIC_INST_EXEC_SIGS_HH__
#define __CPU_STATIC_INST_EXEC_SIGS_HH__
'''
for cpu in env['CPU_MODELS']:
for cpu in temp_cpu_list:
xc_type = CpuModel.dict[cpu].strings['CPU_exec_context']
print >> f, exec_sig_template % (xc_type, xc_type, xc_type)
print >> f, '''
@@ -85,12 +92,19 @@ def gen_cpu_exec_signatures(target, source, env):
# Generate string that gets printed when header is rebuilt
def gen_sigs_string(target, source, env):
return "Generating static_inst_exec_sigs.hh: " \
+ ', '.join(env['CPU_MODELS'])
+ ', '.join(temp_cpu_list)
# Add command to generate header to environment.
env.Command('static_inst_exec_sigs.hh', models_db,
Action(gen_cpu_exec_signatures, gen_sigs_string,
varlist = ['CPU_MODELS']))
varlist = temp_cpu_list))
env.Depends('static_inst_exec_sigs.hh', Value(env['USE_CHECKER']))
env.Depends('static_inst_exec_sigs.hh', Value(env['CPU_MODELS']))
# List of suppported CPUs by the Checker. Errors out if USE_CHECKER=True
# and one of these are not being used.
CheckerSupportedCPUList = ['O3CPU', 'OzoneCPU']
#################################################################
#
@@ -116,15 +130,13 @@ if need_simple_base:
if 'FastCPU' in env['CPU_MODELS']:
sources += Split('fast/cpu.cc')
if 'AlphaFullCPU' in env['CPU_MODELS']:
need_bp_unit = False
if 'O3CPU' in env['CPU_MODELS']:
need_bp_unit = True
sources += SConscript('o3/SConscript', exports = 'env')
sources += Split('''
base_dyn_inst.cc
o3/2bit_local_pred.cc
o3/alpha_dyn_inst.cc
o3/alpha_cpu.cc
o3/alpha_cpu_builder.cc
o3/base_dyn_inst.cc
o3/bpred_unit.cc
o3/btb.cc
o3/commit.cc
o3/decode.cc
o3/fetch.cc
@@ -136,40 +148,54 @@ if 'AlphaFullCPU' in env['CPU_MODELS']:
o3/lsq_unit.cc
o3/lsq.cc
o3/mem_dep_unit.cc
o3/ras.cc
o3/rename.cc
o3/rename_map.cc
o3/rob.cc
o3/scoreboard.cc
o3/store_set.cc
o3/tournament_pred.cc
''')
if env['USE_CHECKER']:
sources += Split('o3/checker_builder.cc')
if 'OzoneSimpleCPU' in env['CPU_MODELS']:
if 'OzoneCPU' in env['CPU_MODELS']:
need_bp_unit = True
sources += Split('''
ozone/base_dyn_inst.cc
ozone/bpred_unit.cc
ozone/cpu.cc
ozone/cpu_builder.cc
ozone/dyn_inst.cc
ozone/front_end.cc
ozone/inorder_back_end.cc
ozone/inst_queue.cc
ozone/rename_table.cc
''')
if 'OzoneCPU' in env['CPU_MODELS']:
sources += Split('''
ozone/lsq_unit.cc
ozone/lw_back_end.cc
ozone/lw_lsq.cc
ozone/rename_table.cc
''')
if env['USE_CHECKER']:
sources += Split('ozone/checker_builder.cc')
if 'CheckerCPU' in env['CPU_MODELS']:
if need_bp_unit:
sources += Split('''
checker/cpu.cc
checker/o3_cpu_builder.cc
o3/2bit_local_pred.cc
o3/btb.cc
o3/ras.cc
o3/tournament_pred.cc
''')
# FullCPU sources are included from m5/SConscript since they're not
if env['USE_CHECKER']:
sources += Split('checker/cpu.cc')
checker_supports = False
for i in CheckerSupportedCPUList:
if i in env['CPU_MODELS']:
checker_supports = True
if not checker_supports:
print "Checker only supports CPU models",
for i in CheckerSupportedCPUList:
print i,
print ", please set USE_CHECKER=False or use one of those CPU models"
Exit(1)
# FullCPU sources are included from src/SConscript since they're not
# below this point in the file hierarchy.
# Convert file names to SCons File objects. This takes care of the

View File

@@ -41,7 +41,6 @@
#include "cpu/cpuevent.hh"
#include "cpu/thread_context.hh"
#include "cpu/profile.hh"
#include "cpu/sampler/sampler.hh"
#include "sim/param.hh"
#include "sim/process.hh"
#include "sim/sim_events.hh"
@@ -60,11 +59,11 @@ int maxThreadsPerCPU = 1;
#if FULL_SYSTEM
BaseCPU::BaseCPU(Params *p)
: SimObject(p->name), clock(p->clock), checkInterrupts(true),
: MemObject(p->name), clock(p->clock), checkInterrupts(true),
params(p), number_of_threads(p->numberOfThreads), system(p->system)
#else
BaseCPU::BaseCPU(Params *p)
: SimObject(p->name), clock(p->clock), params(p),
: MemObject(p->name), clock(p->clock), params(p),
number_of_threads(p->numberOfThreads), system(p->system)
#endif
{
@@ -237,7 +236,7 @@ BaseCPU::registerThreadContexts()
void
BaseCPU::switchOut(Sampler *sampler)
BaseCPU::switchOut()
{
panic("This CPU doesn't support sampling!");
}

View File

@@ -36,17 +36,17 @@
#include "base/statistics.hh"
#include "config/full_system.hh"
#include "cpu/sampler/sampler.hh"
#include "sim/eventq.hh"
#include "sim/sim_object.hh"
#include "mem/mem_object.hh"
#include "arch/isa_traits.hh"
class BranchPred;
class CheckerCPU;
class ThreadContext;
class System;
class Port;
class BaseCPU : public SimObject
class BaseCPU : public MemObject
{
protected:
// CPU's clock period in terms of the number of ticks of curTime.
@@ -148,7 +148,7 @@ class BaseCPU : public SimObject
/// Prepare for another CPU to take over execution. When it is
/// is ready (drained pipe) it signals the sampler.
virtual void switchOut(Sampler *);
virtual void switchOut();
/// Take over execution from the given CPU. Used for warm-up and
/// sampling.

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2004-2005 The Regents of The University of Michigan
* Copyright (c) 2004-2006 The Regents of The University of Michigan
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -31,6 +31,7 @@
#ifndef __CPU_BASE_DYN_INST_HH__
#define __CPU_BASE_DYN_INST_HH__
#include <bitset>
#include <list>
#include <string>
@@ -44,12 +45,6 @@
#include "cpu/static_inst.hh"
#include "mem/packet.hh"
#include "sim/system.hh"
/*
#include "encumbered/cpu/full/bpred_update.hh"
#include "encumbered/cpu/full/spec_memory.hh"
#include "encumbered/cpu/full/spec_state.hh"
#include "encumbered/mem/functional/main.hh"
*/
/**
* @file
@@ -64,8 +59,8 @@ class BaseDynInst : public FastAlloc, public RefCounted
{
public:
// Typedef for the CPU.
typedef typename Impl::FullCPU FullCPU;
typedef typename FullCPU::ImplState ImplState;
typedef typename Impl::CPUType ImplCPU;
typedef typename ImplCPU::ImplState ImplState;
// Binary machine instruction type.
typedef TheISA::MachInst MachInst;
@@ -132,56 +127,34 @@ class BaseDynInst : public FastAlloc, public RefCounted
/** The sequence number of the instruction. */
InstSeqNum seqNum;
/** Is the instruction in the IQ */
bool iqEntry;
enum Status {
IqEntry, /// Instruction is in the IQ
RobEntry, /// Instruction is in the ROB
LsqEntry, /// Instruction is in the LSQ
Completed, /// Instruction has completed
ResultReady, /// Instruction has its result
CanIssue, /// Instruction can issue and execute
Issued, /// Instruction has issued
Executed, /// Instruction has executed
CanCommit, /// Instruction can commit
AtCommit, /// Instruction has reached commit
Committed, /// Instruction has committed
Squashed, /// Instruction is squashed
SquashedInIQ, /// Instruction is squashed in the IQ
SquashedInLSQ, /// Instruction is squashed in the LSQ
SquashedInROB, /// Instruction is squashed in the ROB
RecoverInst, /// Is a recover instruction
BlockingInst, /// Is a blocking instruction
ThreadsyncWait, /// Is a thread synchronization instruction
SerializeBefore, /// Needs to serialize on
/// instructions ahead of it
SerializeAfter, /// Needs to serialize instructions behind it
SerializeHandled, /// Serialization has been handled
NumStatus
};
/** Is the instruction in the ROB */
bool robEntry;
/** Is the instruction in the LSQ */
bool lsqEntry;
/** Is the instruction completed. */
bool completed;
/** Is the instruction's result ready. */
bool resultReady;
/** Can this instruction issue. */
bool canIssue;
/** Has this instruction issued. */
bool issued;
/** Has this instruction executed (or made it through execute) yet. */
bool executed;
/** Can this instruction commit. */
bool canCommit;
/** Is this instruction committed. */
bool committed;
/** Is this instruction squashed. */
bool squashed;
/** Is this instruction squashed in the instruction queue. */
bool squashedInIQ;
/** Is this instruction squashed in the instruction queue. */
bool squashedInLSQ;
/** Is this instruction squashed in the instruction queue. */
bool squashedInROB;
/** Is this a recover instruction. */
bool recoverInst;
/** Is this a thread blocking instruction. */
bool blockingInst; /* this inst has called thread_block() */
/** Is this a thread syncrhonization instruction. */
bool threadsyncWait;
/** The status of this BaseDynInst. Several bits can be set. */
std::bitset<NumStatus> status;
/** The thread this instruction is from. */
short threadNumber;
@@ -192,8 +165,8 @@ class BaseDynInst : public FastAlloc, public RefCounted
/** How many source registers are ready. */
unsigned readyRegs;
/** Pointer to the FullCPU object. */
FullCPU *cpu;
/** Pointer to the Impl's CPU object. */
ImplCPU *cpu;
/** Pointer to the thread state. */
ImplState *thread;
@@ -202,10 +175,9 @@ class BaseDynInst : public FastAlloc, public RefCounted
Fault fault;
/** The memory request. */
// MemReqPtr req;
Request *req;
// Packet pkt;
/** Pointer to the data for the memory access. */
uint8_t *memData;
/** The effective virtual address (lds & stores only). */
@@ -223,12 +195,6 @@ class BaseDynInst : public FastAlloc, public RefCounted
/** The memory request flags (from translation). */
unsigned memReqFlags;
/** The size of the data to be stored. */
int storeSize;
/** The data to be stored. */
IntReg storeData;
union Result {
uint64_t integer;
float fp;
@@ -273,7 +239,7 @@ class BaseDynInst : public FastAlloc, public RefCounted
* @param cpu Pointer to the instruction's CPU.
*/
BaseDynInst(ExtMachInst inst, Addr PC, Addr pred_PC, InstSeqNum seq_num,
FullCPU *cpu);
ImplCPU *cpu);
/** BaseDynInst constructor given a StaticInst pointer.
* @param _staticInst The StaticInst for this BaseDynInst.
@@ -288,21 +254,6 @@ class BaseDynInst : public FastAlloc, public RefCounted
void initVars();
public:
/**
* @todo: Make this function work; currently it is a dummy function.
* @param fault Last fault.
* @param cmd Last command.
* @param addr Virtual address of access.
* @param p Memory accessed.
* @param nbytes Access size.
*/
// void
// trace_mem(Fault fault,
// MemCmd cmd,
// Addr addr,
// void *p,
// int nbytes);
/** Dumps out contents of this BaseDynInst. */
void dump();
@@ -360,9 +311,9 @@ class BaseDynInst : public FastAlloc, public RefCounted
bool isThreadSync() const { return staticInst->isThreadSync(); }
bool isSerializing() const { return staticInst->isSerializing(); }
bool isSerializeBefore() const
{ return staticInst->isSerializeBefore() || serializeBefore; }
{ return staticInst->isSerializeBefore() || status[SerializeBefore]; }
bool isSerializeAfter() const
{ return staticInst->isSerializeAfter() || serializeAfter; }
{ return staticInst->isSerializeAfter() || status[SerializeAfter]; }
bool isMemBarrier() const { return staticInst->isMemBarrier(); }
bool isWriteBarrier() const { return staticInst->isWriteBarrier(); }
bool isNonSpeculative() const { return staticInst->isNonSpeculative(); }
@@ -371,41 +322,32 @@ class BaseDynInst : public FastAlloc, public RefCounted
bool isUnverifiable() const { return staticInst->isUnverifiable(); }
/** Temporarily sets this instruction as a serialize before instruction. */
void setSerializeBefore() { serializeBefore = true; }
void setSerializeBefore() { status.set(SerializeBefore); }
/** Clears the serializeBefore part of this instruction. */
void clearSerializeBefore() { serializeBefore = false; }
void clearSerializeBefore() { status.reset(SerializeBefore); }
/** Checks if this serializeBefore is only temporarily set. */
bool isTempSerializeBefore() { return serializeBefore; }
/** Tracks if instruction has been externally set as serializeBefore. */
bool serializeBefore;
bool isTempSerializeBefore() { return status[SerializeBefore]; }
/** Temporarily sets this instruction as a serialize after instruction. */
void setSerializeAfter() { serializeAfter = true; }
void setSerializeAfter() { status.set(SerializeAfter); }
/** Clears the serializeAfter part of this instruction.*/
void clearSerializeAfter() { serializeAfter = false; }
void clearSerializeAfter() { status.reset(SerializeAfter); }
/** Checks if this serializeAfter is only temporarily set. */
bool isTempSerializeAfter() { return serializeAfter; }
bool isTempSerializeAfter() { return status[SerializeAfter]; }
/** Tracks if instruction has been externally set as serializeAfter. */
bool serializeAfter;
/** Sets the serialization part of this instruction as handled. */
void setSerializeHandled() { status.set(SerializeHandled); }
/** Checks if the serialization part of this instruction has been
* handled. This does not apply to the temporary serializing
* state; it only applies to this instruction's own permanent
* serializing state.
*/
bool isSerializeHandled() { return serializeHandled; }
/** Sets the serialization part of this instruction as handled. */
void setSerializeHandled() { serializeHandled = true; }
/** Whether or not the serialization of this instruction has been handled. */
bool serializeHandled;
bool isSerializeHandled() { return status[SerializeHandled]; }
/** Returns the opclass of this instruction. */
OpClass opClass() const { return staticInst->opClass(); }
@@ -439,11 +381,13 @@ class BaseDynInst : public FastAlloc, public RefCounted
/** Returns the result of a floating point (double) instruction. */
double readDoubleResult() { return instResult.dbl; }
/** Records an integer register being set to a value. */
void setIntReg(const StaticInst *si, int idx, uint64_t val)
{
instResult.integer = val;
}
/** Records an fp register being set to a value. */
void setFloatReg(const StaticInst *si, int idx, FloatReg val, int width)
{
if (width == 32)
@@ -454,16 +398,19 @@ class BaseDynInst : public FastAlloc, public RefCounted
panic("Unsupported width!");
}
/** Records an fp register being set to a value. */
void setFloatReg(const StaticInst *si, int idx, FloatReg val)
{
instResult.fp = val;
}
/** Records an fp register being set to an integer value. */
void setFloatRegBits(const StaticInst *si, int idx, uint64_t val, int width)
{
instResult.integer = val;
}
/** Records an fp register being set to an integer value. */
void setFloatRegBits(const StaticInst *si, int idx, uint64_t val)
{
instResult.integer = val;
@@ -482,106 +429,112 @@ class BaseDynInst : public FastAlloc, public RefCounted
}
/** Sets this instruction as completed. */
void setCompleted() { completed = true; }
void setCompleted() { status.set(Completed); }
/** Returns whether or not this instruction is completed. */
bool isCompleted() const { return completed; }
bool isCompleted() const { return status[Completed]; }
void setResultReady() { resultReady = true; }
/** Marks the result as ready. */
void setResultReady() { status.set(ResultReady); }
bool isResultReady() const { return resultReady; }
/** Returns whether or not the result is ready. */
bool isResultReady() const { return status[ResultReady]; }
/** Sets this instruction as ready to issue. */
void setCanIssue() { canIssue = true; }
void setCanIssue() { status.set(CanIssue); }
/** Returns whether or not this instruction is ready to issue. */
bool readyToIssue() const { return canIssue; }
bool readyToIssue() const { return status[CanIssue]; }
/** Sets this instruction as issued from the IQ. */
void setIssued() { issued = true; }
void setIssued() { status.set(Issued); }
/** Returns whether or not this instruction has issued. */
bool isIssued() const { return issued; }
bool isIssued() const { return status[Issued]; }
/** Sets this instruction as executed. */
void setExecuted() { executed = true; }
void setExecuted() { status.set(Executed); }
/** Returns whether or not this instruction has executed. */
bool isExecuted() const { return executed; }
bool isExecuted() const { return status[Executed]; }
/** Sets this instruction as ready to commit. */
void setCanCommit() { canCommit = true; }
void setCanCommit() { status.set(CanCommit); }
/** Clears this instruction as being ready to commit. */
void clearCanCommit() { canCommit = false; }
void clearCanCommit() { status.reset(CanCommit); }
/** Returns whether or not this instruction is ready to commit. */
bool readyToCommit() const { return canCommit; }
bool readyToCommit() const { return status[CanCommit]; }
void setAtCommit() { status.set(AtCommit); }
bool isAtCommit() { return status[AtCommit]; }
/** Sets this instruction as committed. */
void setCommitted() { committed = true; }
void setCommitted() { status.set(Committed); }
/** Returns whether or not this instruction is committed. */
bool isCommitted() const { return committed; }
bool isCommitted() const { return status[Committed]; }
/** Sets this instruction as squashed. */
void setSquashed() { squashed = true; }
void setSquashed() { status.set(Squashed); }
/** Returns whether or not this instruction is squashed. */
bool isSquashed() const { return squashed; }
bool isSquashed() const { return status[Squashed]; }
//Instruction Queue Entry
//-----------------------
/** Sets this instruction as a entry the IQ. */
void setInIQ() { iqEntry = true; }
void setInIQ() { status.set(IqEntry); }
/** Sets this instruction as a entry the IQ. */
void removeInIQ() { iqEntry = false; }
/** Sets this instruction as squashed in the IQ. */
void setSquashedInIQ() { squashedInIQ = true; squashed = true;}
/** Returns whether or not this instruction is squashed in the IQ. */
bool isSquashedInIQ() const { return squashedInIQ; }
void clearInIQ() { status.reset(IqEntry); }
/** Returns whether or not this instruction has issued. */
bool isInIQ() const { return iqEntry; }
bool isInIQ() const { return status[IqEntry]; }
/** Sets this instruction as squashed in the IQ. */
void setSquashedInIQ() { status.set(SquashedInIQ); status.set(Squashed);}
/** Returns whether or not this instruction is squashed in the IQ. */
bool isSquashedInIQ() const { return status[SquashedInIQ]; }
//Load / Store Queue Functions
//-----------------------
/** Sets this instruction as a entry the LSQ. */
void setInLSQ() { lsqEntry = true; }
void setInLSQ() { status.set(LsqEntry); }
/** Sets this instruction as a entry the LSQ. */
void removeInLSQ() { lsqEntry = false; }
/** Sets this instruction as squashed in the LSQ. */
void setSquashedInLSQ() { squashedInLSQ = true;}
/** Returns whether or not this instruction is squashed in the LSQ. */
bool isSquashedInLSQ() const { return squashedInLSQ; }
void removeInLSQ() { status.reset(LsqEntry); }
/** Returns whether or not this instruction is in the LSQ. */
bool isInLSQ() const { return lsqEntry; }
bool isInLSQ() const { return status[LsqEntry]; }
/** Sets this instruction as squashed in the LSQ. */
void setSquashedInLSQ() { status.set(SquashedInLSQ);}
/** Returns whether or not this instruction is squashed in the LSQ. */
bool isSquashedInLSQ() const { return status[SquashedInLSQ]; }
//Reorder Buffer Functions
//-----------------------
/** Sets this instruction as a entry the ROB. */
void setInROB() { robEntry = true; }
void setInROB() { status.set(RobEntry); }
/** Sets this instruction as a entry the ROB. */
void removeInROB() { robEntry = false; }
/** Sets this instruction as squashed in the ROB. */
void setSquashedInROB() { squashedInROB = true; }
/** Returns whether or not this instruction is squashed in the ROB. */
bool isSquashedInROB() const { return squashedInROB; }
void clearInROB() { status.reset(RobEntry); }
/** Returns whether or not this instruction is in the ROB. */
bool isInROB() const { return robEntry; }
bool isInROB() const { return status[RobEntry]; }
/** Sets this instruction as squashed in the ROB. */
void setSquashedInROB() { status.set(SquashedInROB); }
/** Returns whether or not this instruction is squashed in the ROB. */
bool isSquashedInROB() const { return status[SquashedInROB]; }
/** Read the PC of this instruction. */
const Addr readPC() const { return PC; }
@@ -590,17 +543,18 @@ class BaseDynInst : public FastAlloc, public RefCounted
void setNextPC(uint64_t val)
{
nextPC = val;
// instResult.integer = val;
}
/** Sets the ASID. */
void setASID(short addr_space_id) { asid = addr_space_id; }
void setThread(unsigned tid) { threadNumber = tid; }
/** Sets the thread id. */
void setTid(unsigned tid) { threadNumber = tid; }
void setState(ImplState *state) { thread = state; }
/** Sets the pointer to the thread state. */
void setThreadState(ImplState *state) { thread = state; }
/** Returns the thread context.
*/
/** Returns the thread context. */
ThreadContext *tcBase() { return thread->getTC(); }
private:
@@ -637,8 +591,6 @@ class BaseDynInst : public FastAlloc, public RefCounted
/** Store queue index. */
int16_t sqIdx;
bool reachedCommit;
/** Iterator pointing to this BaseDynInst in the list of all insts. */
ListIt instListIt;

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2004-2005 The Regents of The University of Michigan
* Copyright (c) 2004-2006 The Regents of The University of Michigan
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -41,10 +41,6 @@
#include "mem/request.hh"
#include "cpu/base_dyn_inst.hh"
#include "cpu/o3/alpha_impl.hh"
#include "cpu/o3/alpha_cpu.hh"
//#include "cpu/ozone/simple_impl.hh"
//#include "cpu/ozone/ozone_impl.hh"
using namespace std;
using namespace TheISA;
@@ -71,8 +67,8 @@ my_hash_t thishash;
template <class Impl>
BaseDynInst<Impl>::BaseDynInst(ExtMachInst machInst, Addr inst_PC,
Addr pred_PC, InstSeqNum seq_num,
FullCPU *cpu)
: staticInst(machInst), traceData(NULL), cpu(cpu)/*, xc(cpu->xcBase())*/
ImplCPU *cpu)
: staticInst(machInst), traceData(NULL), cpu(cpu)
{
seqNum = seq_num;
@@ -99,37 +95,18 @@ BaseDynInst<Impl>::initVars()
memData = NULL;
effAddr = 0;
physEffAddr = 0;
storeSize = 0;
readyRegs = 0;
// May want to turn this into a bit vector or something.
completed = false;
resultReady = false;
canIssue = false;
issued = false;
executed = false;
canCommit = false;
committed = false;
squashed = false;
squashedInIQ = false;
squashedInLSQ = false;
squashedInROB = false;
instResult.integer = 0;
status.reset();
eaCalcDone = false;
memOpDone = false;
lqIdx = -1;
sqIdx = -1;
reachedCommit = false;
blockingInst = false;
recoverInst = false;
iqEntry = false;
robEntry = false;
serializeBefore = false;
serializeAfter = false;
serializeHandled = false;
// Eventually make this a parameter.
threadNumber = 0;
@@ -242,31 +219,7 @@ template <class Impl>
void
BaseDynInst<Impl>::writeHint(Addr addr, int size, unsigned flags)
{
// Need to create a MemReq here so we can do a translation. This
// will casue a TLB miss trap if necessary... not sure whether
// that's the best thing to do or not. We don't really need the
// MemReq otherwise, since wh64 has no functional effect.
/*
MemReqPtr req = new MemReq(addr, thread->getXCProxy(), size, flags);
req->asid = asid;
fault = cpu->translateDataWriteReq(req);
if (fault == NoFault && !(req->flags & UNCACHEABLE)) {
// Record key MemReq parameters so we can generate another one
// just like it for the timing access without calling translate()
// again (which might mess up the TLB).
effAddr = req->vaddr;
physEffAddr = req->paddr;
memReqFlags = req->flags;
} else {
// ignore faults & accesses to uncacheable space... treat as no-op
effAddr = physEffAddr = MemReq::inval_addr;
}
storeSize = size;
storeData = 0;
*/
// Not currently supported.
}
/**
@@ -276,22 +229,7 @@ template <class Impl>
Fault
BaseDynInst<Impl>::copySrcTranslate(Addr src)
{
/*
MemReqPtr req = new MemReq(src, thread->getXCProxy(), 64);
req->asid = asid;
// translate to physical address
Fault fault = cpu->translateDataReadReq(req);
if (fault == NoFault) {
thread->copySrcAddr = src;
thread->copySrcPhysAddr = req->paddr;
} else {
thread->copySrcAddr = 0;
thread->copySrcPhysAddr = 0;
}
return fault;
*/
// Not currently supported.
return NoFault;
}
@@ -302,26 +240,7 @@ template <class Impl>
Fault
BaseDynInst<Impl>::copy(Addr dest)
{
/*
uint8_t data[64];
FunctionalMemory *mem = thread->mem;
assert(thread->copySrcPhysAddr);
MemReqPtr req = new MemReq(dest, thread->getXCProxy(), 64);
req->asid = asid;
// translate to physical address
Fault fault = cpu->translateDataWriteReq(req);
if (fault == NoFault) {
Addr dest_addr = req->paddr;
// Need to read straight from memory since we have more than 8 bytes.
req->paddr = thread->copySrcPhysAddr;
mem->read(req, data);
req->paddr = dest_addr;
mem->write(req, data);
}
return fault;
*/
// Not currently supported.
return NoFault;
}
@@ -350,7 +269,7 @@ void
BaseDynInst<Impl>::markSrcRegReady()
{
if (++readyRegs == numSrcRegs()) {
canIssue = true;
status.set(CanIssue);
}
}
@@ -358,13 +277,9 @@ template <class Impl>
void
BaseDynInst<Impl>::markSrcRegReady(RegIndex src_idx)
{
++readyRegs;
_readySrcRegIdx[src_idx] = true;
if (readyRegs == numSrcRegs()) {
canIssue = true;
}
markSrcRegReady();
}
template <class Impl>
@@ -382,25 +297,3 @@ BaseDynInst<Impl>::eaSrcsReady()
return true;
}
// Forward declaration
template class BaseDynInst<AlphaSimpleImpl>;
template <>
int
BaseDynInst<AlphaSimpleImpl>::instcount = 0;
/*
// Forward declaration
template class BaseDynInst<SimpleImpl>;
template <>
int
BaseDynInst<SimpleImpl>::instcount = 0;
// Forward declaration
template class BaseDynInst<OzoneImpl>;
template <>
int
BaseDynInst<OzoneImpl>::instcount = 0;
*/

View File

@@ -31,27 +31,17 @@
#include <list>
#include <string>
#include "base/refcnt.hh"
#include "cpu/base.hh"
#include "cpu/base_dyn_inst.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 "sim/sim_object.hh"
#include "sim/stats.hh"
#include "cpu/o3/alpha_dyn_inst.hh"
#include "cpu/o3/alpha_impl.hh"
//#include "cpu/ozone/dyn_inst.hh"
//#include "cpu/ozone/ozone_impl.hh"
//#include "cpu/ozone/simple_impl.hh"
#if FULL_SYSTEM
#include "sim/system.hh"
#include "arch/vtophys.hh"
#include "kern/kernel_stats.hh"
#endif // FULL_SYSTEM
using namespace std;
@@ -77,6 +67,7 @@ CheckerCPU::CheckerCPU(Params *p)
changedPC = willChangePC = changedNextPC = false;
exitOnError = p->exitOnError;
warnOnlyOnLoadError = p->warnOnlyOnLoadError;
#if FULL_SYSTEM
itb = p->itb;
dtb = p->dtb;
@@ -84,6 +75,8 @@ CheckerCPU::CheckerCPU(Params *p)
#else
process = p->process;
#endif
result.integer = 0;
}
CheckerCPU::~CheckerCPU()
@@ -406,379 +399,10 @@ CheckerCPU::checkFlags(Request *req)
}
}
template <class DynInstPtr>
void
Checker<DynInstPtr>::tick(DynInstPtr &completed_inst)
CheckerCPU::dumpAndExit()
{
DynInstPtr inst;
// Either check this instruction, or add it to a list of
// instructions waiting to be checked. Instructions must be
// checked in program order, so if a store has committed yet not
// completed, there may be some instructions that are waiting
// behind it that have completed and must be checked.
if (!instList.empty()) {
if (youngestSN < completed_inst->seqNum) {
DPRINTF(Checker, "Adding instruction [sn:%lli] PC:%#x to list.\n",
completed_inst->seqNum, completed_inst->readPC());
instList.push_back(completed_inst);
youngestSN = completed_inst->seqNum;
}
if (!instList.front()->isCompleted()) {
return;
} else {
inst = instList.front();
instList.pop_front();
}
} else {
if (!completed_inst->isCompleted()) {
if (youngestSN < completed_inst->seqNum) {
DPRINTF(Checker, "Adding instruction [sn:%lli] PC:%#x to list.\n",
completed_inst->seqNum, completed_inst->readPC());
instList.push_back(completed_inst);
youngestSN = completed_inst->seqNum;
}
return;
} else {
if (youngestSN < completed_inst->seqNum) {
inst = completed_inst;
youngestSN = completed_inst->seqNum;
} else {
return;
}
}
}
// Try to check all instructions that are completed, ending if we
// run out of instructions to check or if an instruction is not
// yet completed.
while (1) {
DPRINTF(Checker, "Processing instruction [sn:%lli] PC:%#x.\n",
inst->seqNum, inst->readPC());
unverifiedResult.integer = inst->readIntResult();
unverifiedReq = inst->req;
unverifiedMemData = inst->memData;
numCycles++;
Fault fault = NoFault;
// maintain $r0 semantics
thread->setIntReg(ZeroReg, 0);
#ifdef TARGET_ALPHA
thread->setFloatRegDouble(ZeroReg, 0.0);
#endif // TARGET_ALPHA
// Check if any recent PC changes match up with anything we
// expect to happen. This is mostly to check if traps or
// PC-based events have occurred in both the checker and CPU.
if (changedPC) {
DPRINTF(Checker, "Changed PC recently to %#x\n",
thread->readPC());
if (willChangePC) {
if (newPC == thread->readPC()) {
DPRINTF(Checker, "Changed PC matches expected PC\n");
} else {
warn("%lli: Changed PC does not match expected PC, "
"changed: %#x, expected: %#x",
curTick, thread->readPC(), newPC);
handleError();
}
willChangePC = false;
}
changedPC = false;
}
if (changedNextPC) {
DPRINTF(Checker, "Changed NextPC recently to %#x\n",
thread->readNextPC());
changedNextPC = false;
}
// Try to fetch the instruction
#if FULL_SYSTEM
#define IFETCH_FLAGS(pc) ((pc) & 1) ? PHYSICAL : 0
#else
#define IFETCH_FLAGS(pc) 0
#endif
uint64_t fetch_PC = thread->readPC() & ~3;
// set up memory request for instruction fetch
memReq = new Request(inst->threadNumber, fetch_PC,
sizeof(uint32_t),
IFETCH_FLAGS(thread->readPC()),
fetch_PC, thread->readCpuId(), inst->threadNumber);
bool succeeded = translateInstReq(memReq);
if (!succeeded) {
if (inst->getFault() == NoFault) {
// In this case the instruction was not a dummy
// instruction carrying an ITB fault. In the single
// threaded case the ITB should still be able to
// translate this instruction; in the SMT case it's
// possible that its ITB entry was kicked out.
warn("%lli: Instruction PC %#x was not found in the ITB!",
curTick, thread->readPC());
handleError();
// go to the next instruction
thread->setPC(thread->readNextPC());
thread->setNextPC(thread->readNextPC() + sizeof(MachInst));
return;
} else {
// The instruction is carrying an ITB fault. Handle
// the fault and see if our results match the CPU on
// the next tick().
fault = inst->getFault();
}
}
if (fault == NoFault) {
Packet *pkt = new Packet(memReq, Packet::ReadReq,
Packet::Broadcast);
pkt->dataStatic(&machInst);
icachePort->sendFunctional(pkt);
delete pkt;
// keep an instruction count
numInst++;
// decode the instruction
machInst = gtoh(machInst);
// Checks that the instruction matches what we expected it to be.
// Checks both the machine instruction and the PC.
validateInst(inst);
curStaticInst = StaticInst::decode(makeExtMI(machInst,
thread->readPC()));
#if FULL_SYSTEM
thread->setInst(machInst);
#endif // FULL_SYSTEM
fault = inst->getFault();
}
// Discard fetch's memReq.
delete memReq;
memReq = NULL;
// Either the instruction was a fault and we should process the fault,
// or we should just go ahead execute the instruction. This assumes
// that the instruction is properly marked as a fault.
if (fault == NoFault) {
thread->funcExeInst++;
fault = curStaticInst->execute(this, NULL);
// Checks to make sure instrution results are correct.
validateExecution(inst);
if (curStaticInst->isLoad()) {
++numLoad;
}
}
if (fault != NoFault) {
#if FULL_SYSTEM
fault->invoke(tc);
willChangePC = true;
newPC = thread->readPC();
DPRINTF(Checker, "Fault, PC is now %#x\n", newPC);
#else // !FULL_SYSTEM
fatal("fault (%d) detected @ PC 0x%08p", fault, thread->readPC());
#endif // FULL_SYSTEM
} else {
#if THE_ISA != MIPS_ISA
// go to the next instruction
thread->setPC(thread->readNextPC());
thread->setNextPC(thread->readNextPC() + sizeof(MachInst));
#else
// go to the next instruction
thread->setPC(thread->readNextPC());
thread->setNextPC(thread->readNextNPC());
thread->setNextNPC(thread->readNextNPC() + sizeof(MachInst));
#endif
}
#if FULL_SYSTEM
// @todo: Determine if these should happen only if the
// instruction hasn't faulted. In the SimpleCPU case this may
// not be true, but in the O3 or Ozone case this may be true.
Addr oldpc;
int count = 0;
do {
oldpc = thread->readPC();
system->pcEventQueue.service(tc);
count++;
} while (oldpc != thread->readPC());
if (count > 1) {
willChangePC = true;
newPC = thread->readPC();
DPRINTF(Checker, "PC Event, PC is now %#x\n", newPC);
}
#endif
// @todo: Optionally can check all registers. (Or just those
// that have been modified).
validateState();
if (memReq) {
delete memReq;
memReq = NULL;
}
// Continue verifying instructions if there's another completed
// instruction waiting to be verified.
if (instList.empty()) {
break;
} else if (instList.front()->isCompleted()) {
inst = instList.front();
instList.pop_front();
} else {
break;
}
}
warn("%lli: Checker PC:%#x, next PC:%#x",
curTick, thread->readPC(), thread->readNextPC());
panic("Checker found an error!");
}
template <class DynInstPtr>
void
Checker<DynInstPtr>::switchOut(Sampler *s)
{
instList.clear();
}
template <class DynInstPtr>
void
Checker<DynInstPtr>::takeOverFrom(BaseCPU *oldCPU)
{
}
template <class DynInstPtr>
void
Checker<DynInstPtr>::validateInst(DynInstPtr &inst)
{
if (inst->readPC() != thread->readPC()) {
warn("%lli: PCs do not match! Inst: %#x, checker: %#x",
curTick, inst->readPC(), thread->readPC());
if (changedPC) {
warn("%lli: Changed PCs recently, may not be an error",
curTick);
} else {
handleError();
}
}
MachInst mi = static_cast<MachInst>(inst->staticInst->machInst);
if (mi != machInst) {
warn("%lli: Binary instructions do not match! Inst: %#x, "
"checker: %#x",
curTick, mi, machInst);
handleError();
}
}
template <class DynInstPtr>
void
Checker<DynInstPtr>::validateExecution(DynInstPtr &inst)
{
if (inst->numDestRegs()) {
// @todo: Support more destination registers.
if (inst->isUnverifiable()) {
// Unverifiable instructions assume they were executed
// properly by the CPU. Grab the result from the
// instruction and write it to the register.
RegIndex idx = inst->destRegIdx(0);
if (idx < TheISA::FP_Base_DepTag) {
thread->setIntReg(idx, inst->readIntResult());
} else if (idx < TheISA::Fpcr_DepTag) {
thread->setFloatRegBits(idx, inst->readIntResult());
} else {
thread->setMiscReg(idx, inst->readIntResult());
}
} else if (result.integer != inst->readIntResult()) {
warn("%lli: Instruction results do not match! (Values may not "
"actually be integers) Inst: %#x, checker: %#x",
curTick, inst->readIntResult(), result.integer);
handleError();
}
}
if (inst->readNextPC() != thread->readNextPC()) {
warn("%lli: Instruction next PCs do not match! Inst: %#x, "
"checker: %#x",
curTick, inst->readNextPC(), thread->readNextPC());
handleError();
}
// Checking side effect registers can be difficult if they are not
// checked simultaneously with the execution of the instruction.
// This is because other valid instructions may have modified
// these registers in the meantime, and their values are not
// stored within the DynInst.
while (!miscRegIdxs.empty()) {
int misc_reg_idx = miscRegIdxs.front();
miscRegIdxs.pop();
if (inst->tcBase()->readMiscReg(misc_reg_idx) !=
thread->readMiscReg(misc_reg_idx)) {
warn("%lli: Misc reg idx %i (side effect) does not match! "
"Inst: %#x, checker: %#x",
curTick, misc_reg_idx,
inst->tcBase()->readMiscReg(misc_reg_idx),
thread->readMiscReg(misc_reg_idx));
handleError();
}
}
}
template <class DynInstPtr>
void
Checker<DynInstPtr>::validateState()
{
}
template <class DynInstPtr>
void
Checker<DynInstPtr>::dumpInsts()
{
int num = 0;
InstListIt inst_list_it = --(instList.end());
cprintf("Inst list size: %i\n", instList.size());
while (inst_list_it != instList.end())
{
cprintf("Instruction:%i\n",
num);
cprintf("PC:%#x\n[sn:%lli]\n[tid:%i]\n"
"Completed:%i\n",
(*inst_list_it)->readPC(),
(*inst_list_it)->seqNum,
(*inst_list_it)->threadNumber,
(*inst_list_it)->isCompleted());
cprintf("\n");
inst_list_it--;
++num;
}
}
//template
//class Checker<RefCountingPtr<OzoneDynInst<OzoneImpl> > >;
template
class Checker<RefCountingPtr<AlphaDynInst<AlphaSimpleImpl> > >;

View File

@@ -66,7 +66,6 @@ class ThreadContext;
class MemInterface;
class Checkpoint;
class Request;
class Sampler;
/**
* CheckerCPU class. Dynamically verifies instructions as they are
@@ -103,6 +102,7 @@ class CheckerCPU : public BaseCPU
Process *process;
#endif
bool exitOnError;
bool warnOnlyOnLoadError;
};
public:
@@ -127,6 +127,12 @@ class CheckerCPU : public BaseCPU
Port *dcachePort;
virtual Port *getPort(const std::string &name, int idx)
{
panic("Not supported on checker!");
return NULL;
}
public:
// Primary thread being run.
SimpleThread *thread;
@@ -335,10 +341,13 @@ class CheckerCPU : public BaseCPU
void handleError()
{
if (exitOnError)
panic("Checker found error!");
dumpAndExit();
}
bool checkFlags(Request *req);
void dumpAndExit();
ThreadContext *tcBase() { return tc; }
SimpleThread *threadBase() { return thread; }
@@ -351,6 +360,7 @@ class CheckerCPU : public BaseCPU
uint64_t newPC;
bool changedNextPC;
bool exitOnError;
bool warnOnlyOnLoadError;
InstSeqNum youngestSN;
};
@@ -369,15 +379,26 @@ class Checker : public CheckerCPU
: CheckerCPU(p)
{ }
void switchOut(Sampler *s);
void switchOut();
void takeOverFrom(BaseCPU *oldCPU);
void tick(DynInstPtr &inst);
void verify(DynInstPtr &inst);
void validateInst(DynInstPtr &inst);
void validateExecution(DynInstPtr &inst);
void validateState();
void copyResult(DynInstPtr &inst);
private:
void handleError(DynInstPtr &inst)
{
if (exitOnError)
dumpAndExit(inst);
}
void dumpAndExit(DynInstPtr &inst);
std::list<DynInstPtr> instList;
typedef typename std::list<DynInstPtr>::iterator InstListIt;
void dumpInsts();

458
src/cpu/checker/cpu_impl.hh Normal file
View File

@@ -0,0 +1,458 @@
/*
* 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: Kevin Lim
*/
#include <list>
#include <string>
#include "base/refcnt.hh"
#include "cpu/base_dyn_inst.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 "sim/sim_object.hh"
#include "sim/stats.hh"
#if FULL_SYSTEM
#include "arch/vtophys.hh"
#endif // FULL_SYSTEM
using namespace std;
//The CheckerCPU does alpha only
using namespace AlphaISA;
template <class DynInstPtr>
void
Checker<DynInstPtr>::verify(DynInstPtr &completed_inst)
{
DynInstPtr inst;
// Either check this instruction, or add it to a list of
// instructions waiting to be checked. Instructions must be
// checked in program order, so if a store has committed yet not
// completed, there may be some instructions that are waiting
// behind it that have completed and must be checked.
if (!instList.empty()) {
if (youngestSN < completed_inst->seqNum) {
DPRINTF(Checker, "Adding instruction [sn:%lli] PC:%#x to list.\n",
completed_inst->seqNum, completed_inst->readPC());
instList.push_back(completed_inst);
youngestSN = completed_inst->seqNum;
}
if (!instList.front()->isCompleted()) {
return;
} else {
inst = instList.front();
instList.pop_front();
}
} else {
if (!completed_inst->isCompleted()) {
if (youngestSN < completed_inst->seqNum) {
DPRINTF(Checker, "Adding instruction [sn:%lli] PC:%#x to list.\n",
completed_inst->seqNum, completed_inst->readPC());
instList.push_back(completed_inst);
youngestSN = completed_inst->seqNum;
}
return;
} else {
if (youngestSN < completed_inst->seqNum) {
inst = completed_inst;
youngestSN = completed_inst->seqNum;
} else {
return;
}
}
}
// Try to check all instructions that are completed, ending if we
// run out of instructions to check or if an instruction is not
// yet completed.
while (1) {
DPRINTF(Checker, "Processing instruction [sn:%lli] PC:%#x.\n",
inst->seqNum, inst->readPC());
unverifiedResult.integer = inst->readIntResult();
unverifiedReq = inst->req;
unverifiedMemData = inst->memData;
numCycles++;
Fault fault = NoFault;
// maintain $r0 semantics
thread->setIntReg(ZeroReg, 0);
#ifdef TARGET_ALPHA
thread->setFloatRegDouble(ZeroReg, 0.0);
#endif // TARGET_ALPHA
// Check if any recent PC changes match up with anything we
// expect to happen. This is mostly to check if traps or
// PC-based events have occurred in both the checker and CPU.
if (changedPC) {
DPRINTF(Checker, "Changed PC recently to %#x\n",
thread->readPC());
if (willChangePC) {
if (newPC == thread->readPC()) {
DPRINTF(Checker, "Changed PC matches expected PC\n");
} else {
warn("%lli: Changed PC does not match expected PC, "
"changed: %#x, expected: %#x",
curTick, thread->readPC(), newPC);
CheckerCPU::handleError();
}
willChangePC = false;
}
changedPC = false;
}
if (changedNextPC) {
DPRINTF(Checker, "Changed NextPC recently to %#x\n",
thread->readNextPC());
changedNextPC = false;
}
// Try to fetch the instruction
#if FULL_SYSTEM
#define IFETCH_FLAGS(pc) ((pc) & 1) ? PHYSICAL : 0
#else
#define IFETCH_FLAGS(pc) 0
#endif
uint64_t fetch_PC = thread->readPC() & ~3;
// set up memory request for instruction fetch
memReq = new Request(inst->threadNumber, fetch_PC,
sizeof(uint32_t),
IFETCH_FLAGS(thread->readPC()),
fetch_PC, thread->readCpuId(), inst->threadNumber);
bool succeeded = translateInstReq(memReq);
if (!succeeded) {
if (inst->getFault() == NoFault) {
// In this case the instruction was not a dummy
// instruction carrying an ITB fault. In the single
// threaded case the ITB should still be able to
// translate this instruction; in the SMT case it's
// possible that its ITB entry was kicked out.
warn("%lli: Instruction PC %#x was not found in the ITB!",
curTick, thread->readPC());
handleError(inst);
// go to the next instruction
thread->setPC(thread->readNextPC());
thread->setNextPC(thread->readNextPC() + sizeof(MachInst));
return;
} else {
// The instruction is carrying an ITB fault. Handle
// the fault and see if our results match the CPU on
// the next tick().
fault = inst->getFault();
}
}
if (fault == NoFault) {
Packet *pkt = new Packet(memReq, Packet::ReadReq,
Packet::Broadcast);
pkt->dataStatic(&machInst);
icachePort->sendFunctional(pkt);
delete pkt;
// keep an instruction count
numInst++;
// decode the instruction
machInst = gtoh(machInst);
// Checks that the instruction matches what we expected it to be.
// Checks both the machine instruction and the PC.
validateInst(inst);
curStaticInst = StaticInst::decode(makeExtMI(machInst,
thread->readPC()));
#if FULL_SYSTEM
thread->setInst(machInst);
#endif // FULL_SYSTEM
fault = inst->getFault();
}
// Discard fetch's memReq.
delete memReq;
memReq = NULL;
// Either the instruction was a fault and we should process the fault,
// or we should just go ahead execute the instruction. This assumes
// that the instruction is properly marked as a fault.
if (fault == NoFault) {
thread->funcExeInst++;
fault = curStaticInst->execute(this, NULL);
// Checks to make sure instrution results are correct.
validateExecution(inst);
if (curStaticInst->isLoad()) {
++numLoad;
}
}
if (fault != NoFault) {
#if FULL_SYSTEM
fault->invoke(tc);
willChangePC = true;
newPC = thread->readPC();
DPRINTF(Checker, "Fault, PC is now %#x\n", newPC);
#endif
} else {
#if THE_ISA != MIPS_ISA
// go to the next instruction
thread->setPC(thread->readNextPC());
thread->setNextPC(thread->readNextPC() + sizeof(MachInst));
#else
// go to the next instruction
thread->setPC(thread->readNextPC());
thread->setNextPC(thread->readNextNPC());
thread->setNextNPC(thread->readNextNPC() + sizeof(MachInst));
#endif
}
#if FULL_SYSTEM
// @todo: Determine if these should happen only if the
// instruction hasn't faulted. In the SimpleCPU case this may
// not be true, but in the O3 or Ozone case this may be true.
Addr oldpc;
int count = 0;
do {
oldpc = thread->readPC();
system->pcEventQueue.service(tc);
count++;
} while (oldpc != thread->readPC());
if (count > 1) {
willChangePC = true;
newPC = thread->readPC();
DPRINTF(Checker, "PC Event, PC is now %#x\n", newPC);
}
#endif
// @todo: Optionally can check all registers. (Or just those
// that have been modified).
validateState();
if (memReq) {
delete memReq;
memReq = NULL;
}
// Continue verifying instructions if there's another completed
// instruction waiting to be verified.
if (instList.empty()) {
break;
} else if (instList.front()->isCompleted()) {
inst = instList.front();
instList.pop_front();
} else {
break;
}
}
}
template <class DynInstPtr>
void
Checker<DynInstPtr>::switchOut()
{
instList.clear();
}
template <class DynInstPtr>
void
Checker<DynInstPtr>::takeOverFrom(BaseCPU *oldCPU)
{
}
template <class DynInstPtr>
void
Checker<DynInstPtr>::validateInst(DynInstPtr &inst)
{
if (inst->readPC() != thread->readPC()) {
warn("%lli: PCs do not match! Inst: %#x, checker: %#x",
curTick, inst->readPC(), thread->readPC());
if (changedPC) {
warn("%lli: Changed PCs recently, may not be an error",
curTick);
} else {
handleError(inst);
}
}
MachInst mi = static_cast<MachInst>(inst->staticInst->machInst);
if (mi != machInst) {
warn("%lli: Binary instructions do not match! Inst: %#x, "
"checker: %#x",
curTick, mi, machInst);
handleError(inst);
}
}
template <class DynInstPtr>
void
Checker<DynInstPtr>::validateExecution(DynInstPtr &inst)
{
bool result_mismatch = false;
if (inst->numDestRegs()) {
// @todo: Support more destination registers.
if (inst->isUnverifiable()) {
// Unverifiable instructions assume they were executed
// properly by the CPU. Grab the result from the
// instruction and write it to the register.
copyResult(inst);
} else if (result.integer != inst->readIntResult()) {
result_mismatch = true;
}
}
if (result_mismatch) {
warn("%lli: Instruction results do not match! (Values may not "
"actually be integers) Inst: %#x, checker: %#x",
curTick, inst->readIntResult(), result.integer);
// It's useful to verify load values from memory, but in MP
// systems the value obtained at execute may be different than
// the value obtained at completion. Similarly DMA can
// present the same problem on even UP systems. Thus there is
// the option to only warn on loads having a result error.
if (inst->isLoad() && warnOnlyOnLoadError) {
copyResult(inst);
} else {
handleError(inst);
}
}
if (inst->readNextPC() != thread->readNextPC()) {
warn("%lli: Instruction next PCs do not match! Inst: %#x, "
"checker: %#x",
curTick, inst->readNextPC(), thread->readNextPC());
handleError(inst);
}
// Checking side effect registers can be difficult if they are not
// checked simultaneously with the execution of the instruction.
// This is because other valid instructions may have modified
// these registers in the meantime, and their values are not
// stored within the DynInst.
while (!miscRegIdxs.empty()) {
int misc_reg_idx = miscRegIdxs.front();
miscRegIdxs.pop();
if (inst->tcBase()->readMiscReg(misc_reg_idx) !=
thread->readMiscReg(misc_reg_idx)) {
warn("%lli: Misc reg idx %i (side effect) does not match! "
"Inst: %#x, checker: %#x",
curTick, misc_reg_idx,
inst->tcBase()->readMiscReg(misc_reg_idx),
thread->readMiscReg(misc_reg_idx));
handleError(inst);
}
}
}
template <class DynInstPtr>
void
Checker<DynInstPtr>::validateState()
{
}
template <class DynInstPtr>
void
Checker<DynInstPtr>::copyResult(DynInstPtr &inst)
{
RegIndex idx = inst->destRegIdx(0);
if (idx < TheISA::FP_Base_DepTag) {
thread->setIntReg(idx, inst->readIntResult());
} else if (idx < TheISA::Fpcr_DepTag) {
thread->setFloatRegBits(idx, inst->readIntResult());
} else {
thread->setMiscReg(idx, inst->readIntResult());
}
}
template <class DynInstPtr>
void
Checker<DynInstPtr>::dumpAndExit(DynInstPtr &inst)
{
cprintf("Error detected, instruction information:\n");
cprintf("PC:%#x, nextPC:%#x\n[sn:%lli]\n[tid:%i]\n"
"Completed:%i\n",
inst->readPC(),
inst->readNextPC(),
inst->seqNum,
inst->threadNumber,
inst->isCompleted());
inst->dump();
CheckerCPU::dumpAndExit();
}
template <class DynInstPtr>
void
Checker<DynInstPtr>::dumpInsts()
{
int num = 0;
InstListIt inst_list_it = --(instList.end());
cprintf("Inst list size: %i\n", instList.size());
while (inst_list_it != instList.end())
{
cprintf("Instruction:%i\n",
num);
cprintf("PC:%#x\n[sn:%lli]\n[tid:%i]\n"
"Completed:%i\n",
(*inst_list_it)->readPC(),
(*inst_list_it)->seqNum,
(*inst_list_it)->threadNumber,
(*inst_list_it)->isCompleted());
cprintf("\n");
inst_list_it--;
++num;
}
}

View File

@@ -120,7 +120,7 @@ class CheckerThreadContext : public ThreadContext
void suspend() { actualTC->suspend(); }
/// Set the status to Unallocated.
void deallocate() { actualTC->deallocate(); }
void deallocate(int delay = 0) { actualTC->deallocate(delay); }
/// Set the status to Halted.
void halt() { actualTC->halt(); }

View File

@@ -26,6 +26,10 @@
#
# Authors: Steve Reinhardt
import os
import os.path
import sys
################
# CpuModel class
#
@@ -47,7 +51,6 @@ class CpuModel:
# Add self to dict
CpuModel.dict[name] = self
#
# Define CPU models.
#
@@ -67,9 +70,6 @@ CpuModel('TimingSimpleCPU', 'timing_simple_cpu_exec.cc',
CpuModel('FullCPU', 'full_cpu_exec.cc',
'#include "encumbered/cpu/full/dyn_inst.hh"',
{ 'CPU_exec_context': 'DynInst' })
CpuModel('AlphaFullCPU', 'alpha_o3_exec.cc',
'#include "cpu/o3/alpha_dyn_inst.hh"',
{ 'CPU_exec_context': 'AlphaDynInst<AlphaSimpleImpl>' })
CpuModel('OzoneSimpleCPU', 'ozone_simple_exec.cc',
'#include "cpu/ozone/dyn_inst.hh"',
{ 'CPU_exec_context': 'OzoneDynInst<SimpleImpl>' })
@@ -79,4 +79,6 @@ CpuModel('OzoneCPU', 'ozone_exec.cc',
CpuModel('CheckerCPU', 'checker_cpu_exec.cc',
'#include "cpu/checker/cpu.hh"',
{ 'CPU_exec_context': 'CheckerCPU' })
CpuModel('O3CPU', 'o3_cpu_exec.cc',
'#include "cpu/o3/isa_specific.hh"',
{ 'CPU_exec_context': 'O3DynInst' })

View File

@@ -36,7 +36,7 @@
class ThreadContext;
/** This class creates a global list of events than need a pointer to an
/** This class creates a global list of events that need a pointer to a
* thread context. When a switchover takes place the events can be migrated
* to the new thread context, otherwise you could have a wake timer interrupt
* go off on a switched out cpu or other unfortunate events. This object MUST be

161
src/cpu/exec_context.hh Normal file
View File

@@ -0,0 +1,161 @@
/*
* Copyright (c) 2002-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: Kevin Lim
*/
#error "Cannot include this file"
/**
* The ExecContext is not a usable class. It is simply here for
* documentation purposes. It shows the interface that is used by the
* ISA to access and change CPU state.
*/
class ExecContext {
// The register accessor methods provide the index of the
// instruction's operand (e.g., 0 or 1), not the architectural
// register index, to simplify the implementation of register
// renaming. We find the architectural register index by indexing
// into the instruction's own operand index table. Note that a
// raw pointer to the StaticInst is provided instead of a
// ref-counted StaticInstPtr to reduce overhead. This is fine as
// long as these methods don't copy the pointer into any long-term
// storage (which is pretty hard to imagine they would have reason
// to do).
/** Reads an integer register. */
uint64_t readIntReg(const StaticInst *si, int idx);
/** Reads a floating point register of a specific width. */
FloatReg readFloatReg(const StaticInst *si, int idx, int width);
/** Reads a floating point register of single register width. */
FloatReg readFloatReg(const StaticInst *si, int idx);
/** Reads a floating point register of a specific width in its
* binary format, instead of by value. */
FloatRegBits readFloatRegBits(const StaticInst *si, int idx, int width);
/** Reads a floating point register in its binary format, instead
* of by value. */
FloatRegBits readFloatRegBits(const StaticInst *si, int idx);
/** Sets an integer register to a value. */
void setIntReg(const StaticInst *si, int idx, uint64_t val);
/** Sets a floating point register of a specific width to a value. */
void setFloatReg(const StaticInst *si, int idx, FloatReg val, int width);
/** Sets a floating point register of single width to a value. */
void setFloatReg(const StaticInst *si, int idx, FloatReg val);
/** Sets the bits of a floating point register of a specific width
* to a binary value. */
void setFloatRegBits(const StaticInst *si, int idx,
FloatRegBits val, int width);
/** Sets the bits of a floating point register of single width
* to a binary value. */
void setFloatRegBits(const StaticInst *si, int idx, FloatRegBits val);
/** Reads the PC. */
uint64_t readPC();
/** Reads the NextPC. */
uint64_t readNextPC();
/** Reads the Next-NextPC. Only for architectures like SPARC or MIPS. */
uint64_t readNextNPC();
/** Sets the PC. */
void setPC(uint64_t val);
/** Sets the NextPC. */
void setNextPC(uint64_t val);
/** Sets the Next-NextPC. Only for architectures like SPARC or MIPS. */
void setNextNPC(uint64_t val);
/** Reads a miscellaneous register. */
MiscReg readMiscReg(int misc_reg);
/** Reads a miscellaneous register, handling any architectural
* side effects due to reading that register. */
MiscReg readMiscRegWithEffect(int misc_reg, Fault &fault);
/** Sets a miscellaneous register. */
Fault setMiscReg(int misc_reg, const MiscReg &val);
/** Sets a miscellaneous register, handling any architectural
* side effects due to writing that register. */
Fault setMiscRegWithEffect(int misc_reg, const MiscReg &val);
/** Records the effective address of the instruction. Only valid
* for memory ops. */
void setEA(Addr EA);
/** Returns the effective address of the instruction. Only valid
* for memory ops. */
Addr getEA();
/** Returns a pointer to the ThreadContext. */
ThreadContext *tcBase();
/** Reads an address, creating a memory request with the given
* flags. Stores result of read in data. */
template <class T>
Fault read(Addr addr, T &data, unsigned flags);
/** Writes to an address, creating a memory request with the given
* flags. Writes data to memory. For store conditionals, returns
* the result of the store in res. */
template <class T>
Fault write(T data, Addr addr, unsigned flags, uint64_t *res);
/** Prefetches an address, creating a memory request with the
* given flags. */
void prefetch(Addr addr, unsigned flags);
/** Hints to the memory system that an address will be written to
* soon, with the given size. Creates a memory request with the
* given flags. */
void writeHint(Addr addr, int size, unsigned flags);
#if FULL_SYSTEM
/** Somewhat Alpha-specific function that handles returning from
* an error or interrupt. */
Fault hwrei();
/** Reads the interrupt flags. */
int readIntrFlag();
/** Sets the interrupt flags to a value. */
void setIntrFlag(int val);
/**
* Check for special simulator handling of specific PAL calls. If
* return value is false, actual PAL call will be suppressed.
*/
bool simPalCheck(int palFunc);
#else
/** Executes a syscall specified by the callnum. */
void syscall(int64_t callnum);
#endif
};

171
src/cpu/func_unit.cc Normal file
View File

@@ -0,0 +1,171 @@
/*
* Copyright (c) 2002-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: Steve Raasch
*/
#include <sstream>
#include "base/misc.hh"
#include "cpu/func_unit.hh"
#include "sim/builder.hh"
using namespace std;
////////////////////////////////////////////////////////////////////////////
//
// The funciton unit
//
FuncUnit::FuncUnit()
{
capabilityList.reset();
}
// Copy constructor
FuncUnit::FuncUnit(const FuncUnit &fu)
{
for (int i = 0; i < Num_OpClasses; ++i) {
opLatencies[i] = fu.opLatencies[i];
issueLatencies[i] = fu.issueLatencies[i];
}
capabilityList = fu.capabilityList;
}
void
FuncUnit::addCapability(OpClass cap, unsigned oplat, unsigned issuelat)
{
if (issuelat == 0 || oplat == 0)
panic("FuncUnit: you don't really want a zero-cycle latency do you?");
capabilityList.set(cap);
opLatencies[cap] = oplat;
issueLatencies[cap] = issuelat;
}
bool
FuncUnit::provides(OpClass capability)
{
return capabilityList[capability];
}
bitset<Num_OpClasses>
FuncUnit::capabilities()
{
return capabilityList;
}
unsigned &
FuncUnit::opLatency(OpClass cap)
{
return opLatencies[cap];
}
unsigned
FuncUnit::issueLatency(OpClass capability)
{
return issueLatencies[capability];
}
////////////////////////////////////////////////////////////////////////////
//
// The SimObjects we use to get the FU information into the simulator
//
////////////////////////////////////////////////////////////////////////////
//
// We use 2 objects to specify this data in the INI file:
// (1) OpDesc - Describes the operation class & latencies
// (multiple OpDesc objects can refer to the same
// operation classes)
// (2) FUDesc - Describes the operations available in the unit &
// the number of these units
//
//
//
// The operation-class description object
//
BEGIN_DECLARE_SIM_OBJECT_PARAMS(OpDesc)
SimpleEnumParam<OpClass> opClass;
Param<unsigned> opLat;
Param<unsigned> issueLat;
END_DECLARE_SIM_OBJECT_PARAMS(OpDesc)
BEGIN_INIT_SIM_OBJECT_PARAMS(OpDesc)
INIT_ENUM_PARAM(opClass, "type of operation", opClassStrings),
INIT_PARAM(opLat, "cycles until result is available"),
INIT_PARAM(issueLat, "cycles until another can be issued")
END_INIT_SIM_OBJECT_PARAMS(OpDesc)
CREATE_SIM_OBJECT(OpDesc)
{
return new OpDesc(getInstanceName(), opClass, opLat, issueLat);
}
REGISTER_SIM_OBJECT("OpDesc", OpDesc)
//
// The FuDesc object
//
BEGIN_DECLARE_SIM_OBJECT_PARAMS(FUDesc)
SimObjectVectorParam<OpDesc *> opList;
Param<unsigned> count;
END_DECLARE_SIM_OBJECT_PARAMS(FUDesc)
BEGIN_INIT_SIM_OBJECT_PARAMS(FUDesc)
INIT_PARAM(opList, "list of operation classes for this FU type"),
INIT_PARAM(count, "number of these FU's available")
END_INIT_SIM_OBJECT_PARAMS(FUDesc)
CREATE_SIM_OBJECT(FUDesc)
{
return new FUDesc(getInstanceName(), opList, count);
}
REGISTER_SIM_OBJECT("FUDesc", FUDesc)

101
src/cpu/func_unit.hh Normal file
View File

@@ -0,0 +1,101 @@
/*
* Copyright (c) 2002-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: Steve Raasch
*/
#ifndef __CPU_FUNC_UNIT_HH__
#define __CPU_FUNC_UNIT_HH__
#include <bitset>
#include <string>
#include <vector>
#include "cpu/op_class.hh"
#include "sim/sim_object.hh"
////////////////////////////////////////////////////////////////////////////
//
// Structures used ONLY during the initialization phase...
//
//
//
struct OpDesc : public SimObject
{
OpClass opClass;
unsigned opLat;
unsigned issueLat;
OpDesc(std::string name, OpClass c, unsigned o, unsigned i)
: SimObject(name), opClass(c), opLat(o), issueLat(i) {};
};
struct FUDesc : public SimObject
{
std::vector<OpDesc *> opDescList;
unsigned number;
FUDesc(std::string name, std::vector<OpDesc *> l, unsigned n)
: SimObject(name), opDescList(l), number(n) {};
};
typedef std::vector<OpDesc *>::iterator OPDDiterator;
typedef std::vector<FUDesc *>::iterator FUDDiterator;
////////////////////////////////////////////////////////////////////////////
//
// The actual FU object
//
//
//
class FuncUnit
{
private:
unsigned opLatencies[Num_OpClasses];
unsigned issueLatencies[Num_OpClasses];
std::bitset<Num_OpClasses> capabilityList;
public:
FuncUnit();
FuncUnit(const FuncUnit &fu);
std::string name;
void addCapability(OpClass cap, unsigned oplat, unsigned issuelat);
bool provides(OpClass capability);
std::bitset<Num_OpClasses> capabilities();
unsigned &opLatency(OpClass capability);
unsigned issueLatency(OpClass capability);
};
#endif // __FU_POOL_HH__

79
src/cpu/o3/SConscript Executable file
View File

@@ -0,0 +1,79 @@
# -*- mode:python -*-
# 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: Korey Sewell
import os
import os.path
import sys
# Import build environment variable from SConstruct.
Import('env')
#################################################################
#
# Include ISA-specific files for the O3 CPU-model
#
#################################################################
sources = []
if env['TARGET_ISA'] == 'alpha':
sources += Split('''
alpha/dyn_inst.cc
alpha/cpu.cc
alpha/thread_context.cc
alpha/cpu_builder.cc
''')
elif env['TARGET_ISA'] == 'mips':
sys.exit('O3 CPU does not support MIPS')
#sources += Split('''
# mips/dyn_inst.cc
# mips/cpu.cc
# mips/thread_context.cc
# mips/cpu_builder.cc
# ''')
elif env['TARGET_ISA'] == 'sparc':
sys.exit('O3 CPU does not support MIPS')
#sources += Split('''
# sparc/dyn_inst.cc
# sparc/cpu.cc
# sparc/thread_context.cc
# sparc/cpu_builder.cc
# ''')
else:
sys.exit('O3 CPU does not support the \'%s\' ISA' % env['TARGET_ISA'])
# Convert file names to SCons File objects. This takes care of the
# path relative to the top of the directory tree.
sources = [File(s) for s in sources]
Return('sources')

View File

@@ -28,11 +28,11 @@
* Authors: Kevin Lim
*/
#include "cpu/o3/alpha_impl.hh"
#include "cpu/o3/alpha_cpu_impl.hh"
#include "cpu/o3/alpha_dyn_inst.hh"
#include "cpu/o3/alpha/impl.hh"
#include "cpu/o3/alpha/cpu_impl.hh"
#include "cpu/o3/alpha/dyn_inst.hh"
// Force instantiation of AlphaFullCPU for all the implemntations that are
// Force instantiation of AlphaO3CPU for all the implemntations that are
// needed. Consider merging this and alpha_dyn_inst.cc, and maybe all
// classes that depend on a certain impl, into one file (alpha_impl.cc?).
template class AlphaFullCPU<AlphaSimpleImpl>;
template class AlphaO3CPU<AlphaSimpleImpl>;

204
src/cpu/o3/alpha/cpu.hh Normal file
View File

@@ -0,0 +1,204 @@
/*
* Copyright (c) 2004-2006 The Regents of The University of Michigan
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met: redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer;
* redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution;
* neither the name of the copyright holders nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Authors: Kevin Lim
*/
#ifndef __CPU_O3_ALPHA_CPU_HH__
#define __CPU_O3_ALPHA_CPU_HH__
#include "arch/isa_traits.hh"
#include "cpu/thread_context.hh"
#include "cpu/o3/cpu.hh"
#include "sim/byteswap.hh"
class EndQuiesceEvent;
namespace Kernel {
class Statistics;
};
class TranslatingPort;
/**
* AlphaO3CPU class. Derives from the FullO3CPU class, and
* implements all ISA and implementation specific functions of the
* CPU. This is the CPU class that is used for the SimObjects, and is
* what is given to the DynInsts. Most of its state exists in the
* FullO3CPU; the state is has is mainly for ISA specific
* functionality.
*/
template <class Impl>
class AlphaO3CPU : public FullO3CPU<Impl>
{
protected:
typedef TheISA::IntReg IntReg;
typedef TheISA::FloatReg FloatReg;
typedef TheISA::FloatRegBits FloatRegBits;
typedef TheISA::MiscReg MiscReg;
typedef TheISA::RegFile RegFile;
typedef TheISA::MiscRegFile MiscRegFile;
public:
typedef O3ThreadState<Impl> ImplState;
typedef O3ThreadState<Impl> Thread;
typedef typename Impl::Params Params;
/** Constructs an AlphaO3CPU with the given parameters. */
AlphaO3CPU(Params *params);
#if FULL_SYSTEM
/** ITB pointer. */
AlphaITB *itb;
/** DTB pointer. */
AlphaDTB *dtb;
#endif
/** Registers statistics. */
void regStats();
#if FULL_SYSTEM
/** Translates instruction requestion. */
Fault translateInstReq(RequestPtr &req, Thread *thread)
{
return itb->translate(req, thread->getTC());
}
/** Translates data read request. */
Fault translateDataReadReq(RequestPtr &req, Thread *thread)
{
return dtb->translate(req, thread->getTC(), false);
}
/** Translates data write request. */
Fault translateDataWriteReq(RequestPtr &req, Thread *thread)
{
return dtb->translate(req, thread->getTC(), true);
}
#else
/** Translates instruction requestion in syscall emulation mode. */
Fault translateInstReq(RequestPtr &req, Thread *thread)
{
return thread->getProcessPtr()->pTable->translate(req);
}
/** Translates data read request in syscall emulation mode. */
Fault translateDataReadReq(RequestPtr &req, Thread *thread)
{
return thread->getProcessPtr()->pTable->translate(req);
}
/** Translates data write request in syscall emulation mode. */
Fault translateDataWriteReq(RequestPtr &req, Thread *thread)
{
return thread->getProcessPtr()->pTable->translate(req);
}
#endif
/** Reads a miscellaneous register. */
MiscReg readMiscReg(int misc_reg, unsigned tid);
/** Reads a misc. register, including any side effects the read
* might have as defined by the architecture.
*/
MiscReg readMiscRegWithEffect(int misc_reg, Fault &fault, unsigned tid);
/** Sets a miscellaneous register. */
Fault setMiscReg(int misc_reg, const MiscReg &val, unsigned tid);
/** Sets a misc. register, including any side effects the write
* might have as defined by the architecture.
*/
Fault setMiscRegWithEffect(int misc_reg, const MiscReg &val, unsigned tid);
/** Initiates a squash of all in-flight instructions for a given
* thread. The source of the squash is an external update of
* state through the TC.
*/
void squashFromTC(unsigned tid);
#if FULL_SYSTEM
/** Posts an interrupt. */
void post_interrupt(int int_num, int index);
/** Reads the interrupt flag. */
int readIntrFlag();
/** Sets the interrupt flags. */
void setIntrFlag(int val);
/** HW return from error interrupt. */
Fault hwrei(unsigned tid);
/** Returns if a specific PC is a PAL mode PC. */
bool inPalMode(uint64_t PC)
{ return AlphaISA::PcPAL(PC); }
bool simPalCheck(int palFunc, unsigned tid);
/** Processes any interrupts. */
void processInterrupts();
/** Halts the CPU. */
void halt() { panic("Halt not implemented!\n"); }
#endif
/** Traps to handle given fault. */
void trap(Fault fault, unsigned tid);
#if !FULL_SYSTEM
/** Executes a syscall.
* @todo: Determine if this needs to be virtual.
*/
void syscall(int64_t callnum, int tid);
/** Gets a syscall argument. */
IntReg getSyscallArg(int i, int tid);
/** Used to shift args for indirect syscall. */
void setSyscallArg(int i, IntReg val, int tid);
/** Sets the return value of a syscall. */
void setSyscallReturn(SyscallReturn return_value, int tid);
#endif
/** CPU read function, forwards read to LSQ. */
template <class T>
Fault read(RequestPtr &req, T &data, int load_idx)
{
return this->iew.ldstQueue.read(req, data, load_idx);
}
/** CPU write function, forwards write to LSQ. */
template <class T>
Fault write(RequestPtr &req, T &data, int store_idx)
{
return this->iew.ldstQueue.write(req, data, store_idx);
}
Addr lockAddr;
/** Temporary fix for the lock flag, works in the UP case. */
bool lockFlag;
};
#endif // __CPU_O3_ALPHA_CPU_HH__

View File

@@ -31,21 +31,21 @@
#include <string>
#include "cpu/base.hh"
#include "cpu/o3/alpha_cpu.hh"
#include "cpu/o3/alpha_impl.hh"
#include "cpu/o3/alpha_params.hh"
#include "cpu/o3/alpha/cpu.hh"
#include "cpu/o3/alpha/impl.hh"
#include "cpu/o3/alpha/params.hh"
#include "cpu/o3/fu_pool.hh"
#include "sim/builder.hh"
class DerivAlphaFullCPU : public AlphaFullCPU<AlphaSimpleImpl>
class DerivO3CPU : public AlphaO3CPU<AlphaSimpleImpl>
{
public:
DerivAlphaFullCPU(AlphaSimpleParams *p)
: AlphaFullCPU<AlphaSimpleImpl>(p)
DerivO3CPU(AlphaSimpleParams *p)
: AlphaO3CPU<AlphaSimpleImpl>(p)
{ }
};
BEGIN_DECLARE_SIM_OBJECT_PARAMS(DerivAlphaFullCPU)
BEGIN_DECLARE_SIM_OBJECT_PARAMS(DerivO3CPU)
Param<int> clock;
Param<int> numThreads;
@@ -91,12 +91,10 @@ Param<unsigned> renameWidth;
Param<unsigned> commitToIEWDelay;
Param<unsigned> renameToIEWDelay;
Param<unsigned> issueToExecuteDelay;
Param<unsigned> dispatchWidth;
Param<unsigned> issueWidth;
Param<unsigned> executeWidth;
Param<unsigned> executeIntWidth;
Param<unsigned> executeFloatWidth;
Param<unsigned> executeBranchWidth;
Param<unsigned> executeMemoryWidth;
Param<unsigned> wbWidth;
Param<unsigned> wbDepth;
SimObjectParam<FUPool *> fuPool;
Param<unsigned> iewToCommitDelay;
@@ -104,7 +102,9 @@ Param<unsigned> renameToROBDelay;
Param<unsigned> commitWidth;
Param<unsigned> squashWidth;
Param<Tick> trapLatency;
Param<Tick> fetchTrapLatency;
Param<unsigned> backComSize;
Param<unsigned> forwardComSize;
Param<std::string> predType;
Param<unsigned> localPredictorSize;
@@ -149,9 +149,9 @@ Param<bool> defer_registration;
Param<bool> function_trace;
Param<Tick> function_trace_start;
END_DECLARE_SIM_OBJECT_PARAMS(DerivAlphaFullCPU)
END_DECLARE_SIM_OBJECT_PARAMS(DerivO3CPU)
BEGIN_INIT_SIM_OBJECT_PARAMS(DerivAlphaFullCPU)
BEGIN_INIT_SIM_OBJECT_PARAMS(DerivO3CPU)
INIT_PARAM(clock, "clock speed"),
INIT_PARAM(numThreads, "number of HW thread contexts"),
@@ -212,12 +212,10 @@ BEGIN_INIT_SIM_OBJECT_PARAMS(DerivAlphaFullCPU)
"Issue/Execute/Writeback delay"),
INIT_PARAM(issueToExecuteDelay, "Issue to execute delay (internal"
"to the IEW stage)"),
INIT_PARAM(dispatchWidth, "Dispatch width"),
INIT_PARAM(issueWidth, "Issue width"),
INIT_PARAM(executeWidth, "Execute width"),
INIT_PARAM(executeIntWidth, "Integer execute width"),
INIT_PARAM(executeFloatWidth, "Floating point execute width"),
INIT_PARAM(executeBranchWidth, "Branch execute width"),
INIT_PARAM(executeMemoryWidth, "Memory execute width"),
INIT_PARAM(wbWidth, "Writeback width"),
INIT_PARAM(wbDepth, "Writeback depth (number of cycles it can buffer)"),
INIT_PARAM_DFLT(fuPool, "Functional unit pool", NULL),
INIT_PARAM(iewToCommitDelay, "Issue/Execute/Writeback to commit "
@@ -226,7 +224,9 @@ BEGIN_INIT_SIM_OBJECT_PARAMS(DerivAlphaFullCPU)
INIT_PARAM(commitWidth, "Commit width"),
INIT_PARAM(squashWidth, "Squash width"),
INIT_PARAM_DFLT(trapLatency, "Number of cycles before the trap is handled", 6),
INIT_PARAM_DFLT(fetchTrapLatency, "Number of cycles before the fetch trap is handled", 12),
INIT_PARAM(backComSize, "Time buffer size for backwards communication"),
INIT_PARAM(forwardComSize, "Time buffer size for forward communication"),
INIT_PARAM(predType, "Type of branch predictor ('local', 'tournament')"),
INIT_PARAM(localPredictorSize, "Size of local predictor"),
@@ -271,11 +271,11 @@ BEGIN_INIT_SIM_OBJECT_PARAMS(DerivAlphaFullCPU)
INIT_PARAM(function_trace, "Enable function trace"),
INIT_PARAM(function_trace_start, "Cycle to start function trace")
END_INIT_SIM_OBJECT_PARAMS(DerivAlphaFullCPU)
END_INIT_SIM_OBJECT_PARAMS(DerivO3CPU)
CREATE_SIM_OBJECT(DerivAlphaFullCPU)
CREATE_SIM_OBJECT(DerivO3CPU)
{
DerivAlphaFullCPU *cpu;
DerivO3CPU *cpu;
#if FULL_SYSTEM
// Full-system only supports a single thread for the moment.
@@ -284,12 +284,12 @@ CREATE_SIM_OBJECT(DerivAlphaFullCPU)
// In non-full-system mode, we infer the number of threads from
// the workload if it's not explicitly specified.
int actual_num_threads =
numThreads.isValid() ? numThreads : workload.size();
(numThreads.isValid() && numThreads >= workload.size()) ?
numThreads : workload.size();
if (workload.size() == 0) {
fatal("Must specify at least one workload!");
}
#endif
AlphaSimpleParams *params = new AlphaSimpleParams;
@@ -343,12 +343,10 @@ CREATE_SIM_OBJECT(DerivAlphaFullCPU)
params->commitToIEWDelay = commitToIEWDelay;
params->renameToIEWDelay = renameToIEWDelay;
params->issueToExecuteDelay = issueToExecuteDelay;
params->dispatchWidth = dispatchWidth;
params->issueWidth = issueWidth;
params->executeWidth = executeWidth;
params->executeIntWidth = executeIntWidth;
params->executeFloatWidth = executeFloatWidth;
params->executeBranchWidth = executeBranchWidth;
params->executeMemoryWidth = executeMemoryWidth;
params->wbWidth = wbWidth;
params->wbDepth = wbDepth;
params->fuPool = fuPool;
params->iewToCommitDelay = iewToCommitDelay;
@@ -356,7 +354,9 @@ CREATE_SIM_OBJECT(DerivAlphaFullCPU)
params->commitWidth = commitWidth;
params->squashWidth = squashWidth;
params->trapLatency = trapLatency;
params->fetchTrapLatency = fetchTrapLatency;
params->backComSize = backComSize;
params->forwardComSize = forwardComSize;
params->predType = predType;
params->localPredictorSize = localPredictorSize;
@@ -386,7 +386,16 @@ CREATE_SIM_OBJECT(DerivAlphaFullCPU)
params->numROBEntries = numROBEntries;
params->smtNumFetchingThreads = smtNumFetchingThreads;
params->smtFetchPolicy = smtFetchPolicy;
// Default smtFetchPolicy to "RoundRobin", if necessary.
std::string round_robin_policy = "RoundRobin";
std::string single_thread = "SingleThread";
if (actual_num_threads > 1 && single_thread.compare(smtFetchPolicy) == 0)
params->smtFetchPolicy = round_robin_policy;
else
params->smtFetchPolicy = smtFetchPolicy;
params->smtIQPolicy = smtIQPolicy;
params->smtLSQPolicy = smtLSQPolicy;
params->smtLSQThreshold = smtLSQThreshold;
@@ -401,10 +410,10 @@ CREATE_SIM_OBJECT(DerivAlphaFullCPU)
params->functionTrace = function_trace;
params->functionTraceStart = function_trace_start;
cpu = new DerivAlphaFullCPU(params);
cpu = new DerivO3CPU(params);
return cpu;
}
REGISTER_SIM_OBJECT("DerivAlphaFullCPU", DerivAlphaFullCPU)
REGISTER_SIM_OBJECT("DerivO3CPU", DerivO3CPU)

View File

@@ -0,0 +1,422 @@
/*
* Copyright (c) 2004-2006 The Regents of The University of Michigan
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met: redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer;
* redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution;
* neither the name of the copyright holders nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Authors: Kevin Lim
*/
#include "config/use_checker.hh"
#include "arch/alpha/faults.hh"
#include "base/cprintf.hh"
#include "base/statistics.hh"
#include "base/timebuf.hh"
#include "cpu/checker/thread_context.hh"
#include "sim/sim_events.hh"
#include "sim/stats.hh"
#include "cpu/o3/alpha/cpu.hh"
#include "cpu/o3/alpha/params.hh"
#include "cpu/o3/alpha/thread_context.hh"
#include "cpu/o3/comm.hh"
#include "cpu/o3/thread_state.hh"
#if FULL_SYSTEM
#include "arch/alpha/osfpal.hh"
#include "arch/isa_traits.hh"
#include "cpu/quiesce_event.hh"
#include "kern/kernel_stats.hh"
#include "sim/sim_exit.hh"
#include "sim/system.hh"
#endif
using namespace TheISA;
template <class Impl>
AlphaO3CPU<Impl>::AlphaO3CPU(Params *params)
#if FULL_SYSTEM
: FullO3CPU<Impl>(params), itb(params->itb), dtb(params->dtb)
#else
: FullO3CPU<Impl>(params)
#endif
{
DPRINTF(O3CPU, "Creating AlphaO3CPU object.\n");
// Setup any thread state.
this->thread.resize(this->numThreads);
for (int i = 0; i < this->numThreads; ++i) {
#if FULL_SYSTEM
// SMT is not supported in FS mode yet.
assert(this->numThreads == 1);
this->thread[i] = new Thread(this, 0);
this->thread[i]->setStatus(ThreadContext::Suspended);
#else
if (i < params->workload.size()) {
DPRINTF(O3CPU, "Workload[%i] process is %#x",
i, this->thread[i]);
this->thread[i] = new Thread(this, i, params->workload[i],
i, params->mem);
this->thread[i]->setStatus(ThreadContext::Suspended);
#if !FULL_SYSTEM
/* Use this port to for syscall emulation writes to memory. */
Port *mem_port;
TranslatingPort *trans_port;
trans_port = new TranslatingPort(csprintf("%s-%d-funcport",
name(), i),
params->workload[i]->pTable,
false);
mem_port = params->mem->getPort("functional");
mem_port->setPeer(trans_port);
trans_port->setPeer(mem_port);
this->thread[i]->setMemPort(trans_port);
#endif
//usedTids[i] = true;
//threadMap[i] = i;
} else {
//Allocate Empty thread so M5 can use later
//when scheduling threads to CPU
Process* dummy_proc = NULL;
this->thread[i] = new Thread(this, i, dummy_proc, i, params->mem);
//usedTids[i] = false;
}
#endif // !FULL_SYSTEM
ThreadContext *tc;
// Setup the TC that will serve as the interface to the threads/CPU.
AlphaTC<Impl> *alpha_tc =
new AlphaTC<Impl>;
tc = alpha_tc;
// If we're using a checker, then the TC should be the
// CheckerThreadContext.
#if USE_CHECKER
if (params->checker) {
tc = new CheckerThreadContext<AlphaTC<Impl> >(
alpha_tc, this->checker);
}
#endif
alpha_tc->cpu = this;
alpha_tc->thread = this->thread[i];
#if FULL_SYSTEM
// Setup quiesce event.
this->thread[i]->quiesceEvent = new EndQuiesceEvent(tc);
Port *mem_port;
FunctionalPort *phys_port;
VirtualPort *virt_port;
phys_port = new FunctionalPort(csprintf("%s-%d-funcport",
name(), i));
mem_port = this->system->physmem->getPort("functional");
mem_port->setPeer(phys_port);
phys_port->setPeer(mem_port);
virt_port = new VirtualPort(csprintf("%s-%d-vport",
name(), i));
mem_port = this->system->physmem->getPort("functional");
mem_port->setPeer(virt_port);
virt_port->setPeer(mem_port);
this->thread[i]->setPhysPort(phys_port);
this->thread[i]->setVirtPort(virt_port);
#endif
// Give the thread the TC.
this->thread[i]->tc = tc;
// Add the TC to the CPU's list of TC's.
this->threadContexts.push_back(tc);
}
for (int i=0; i < this->numThreads; i++) {
this->thread[i]->setFuncExeInst(0);
}
// Sets CPU pointers. These must be set at this level because the CPU
// pointers are defined to be the highest level of CPU class.
this->fetch.setCPU(this);
this->decode.setCPU(this);
this->rename.setCPU(this);
this->iew.setCPU(this);
this->commit.setCPU(this);
this->rob.setCPU(this);
this->regFile.setCPU(this);
lockAddr = 0;
lockFlag = false;
}
template <class Impl>
void
AlphaO3CPU<Impl>::regStats()
{
// Register stats for everything that has stats.
this->fullCPURegStats();
this->fetch.regStats();
this->decode.regStats();
this->rename.regStats();
this->iew.regStats();
this->commit.regStats();
}
template <class Impl>
MiscReg
AlphaO3CPU<Impl>::readMiscReg(int misc_reg, unsigned tid)
{
return this->regFile.readMiscReg(misc_reg, tid);
}
template <class Impl>
MiscReg
AlphaO3CPU<Impl>::readMiscRegWithEffect(int misc_reg, Fault &fault,
unsigned tid)
{
return this->regFile.readMiscRegWithEffect(misc_reg, fault, tid);
}
template <class Impl>
Fault
AlphaO3CPU<Impl>::setMiscReg(int misc_reg, const MiscReg &val, unsigned tid)
{
return this->regFile.setMiscReg(misc_reg, val, tid);
}
template <class Impl>
Fault
AlphaO3CPU<Impl>::setMiscRegWithEffect(int misc_reg, const MiscReg &val,
unsigned tid)
{
return this->regFile.setMiscRegWithEffect(misc_reg, val, tid);
}
template <class Impl>
void
AlphaO3CPU<Impl>::squashFromTC(unsigned tid)
{
this->thread[tid]->inSyscall = true;
this->commit.generateTCEvent(tid);
}
#if FULL_SYSTEM
template <class Impl>
void
AlphaO3CPU<Impl>::post_interrupt(int int_num, int index)
{
BaseCPU::post_interrupt(int_num, index);
if (this->thread[0]->status() == ThreadContext::Suspended) {
DPRINTF(IPI,"Suspended Processor awoke\n");
this->threadContexts[0]->activate();
}
}
template <class Impl>
int
AlphaO3CPU<Impl>::readIntrFlag()
{
return this->regFile.readIntrFlag();
}
template <class Impl>
void
AlphaO3CPU<Impl>::setIntrFlag(int val)
{
this->regFile.setIntrFlag(val);
}
template <class Impl>
Fault
AlphaO3CPU<Impl>::hwrei(unsigned tid)
{
// Need to clear the lock flag upon returning from an interrupt.
this->lockFlag = false;
this->thread[tid]->kernelStats->hwrei();
this->checkInterrupts = true;
// FIXME: XXX check for interrupts? XXX
return NoFault;
}
template <class Impl>
bool
AlphaO3CPU<Impl>::simPalCheck(int palFunc, unsigned tid)
{
if (this->thread[tid]->kernelStats)
this->thread[tid]->kernelStats->callpal(palFunc,
this->threadContexts[tid]);
switch (palFunc) {
case PAL::halt:
halt();
if (--System::numSystemsRunning == 0)
exitSimLoop("all cpus halted");
break;
case PAL::bpt:
case PAL::bugchk:
if (this->system->breakpoint())
return false;
break;
}
return true;
}
template <class Impl>
void
AlphaO3CPU<Impl>::processInterrupts()
{
// Check for interrupts here. For now can copy the code that
// exists within isa_fullsys_traits.hh. Also assume that thread 0
// is the one that handles the interrupts.
// @todo: Possibly consolidate the interrupt checking code.
// @todo: Allow other threads to handle interrupts.
// Check if there are any outstanding interrupts
//Handle the interrupts
int ipl = 0;
int summary = 0;
this->checkInterrupts = false;
if (this->readMiscReg(IPR_ASTRR, 0))
panic("asynchronous traps not implemented\n");
if (this->readMiscReg(IPR_SIRR, 0)) {
for (int i = INTLEVEL_SOFTWARE_MIN;
i < INTLEVEL_SOFTWARE_MAX; i++) {
if (this->readMiscReg(IPR_SIRR, 0) & (ULL(1) << i)) {
// See table 4-19 of the 21164 hardware reference
ipl = (i - INTLEVEL_SOFTWARE_MIN) + 1;
summary |= (ULL(1) << i);
}
}
}
uint64_t interrupts = this->intr_status();
if (interrupts) {
for (int i = INTLEVEL_EXTERNAL_MIN;
i < INTLEVEL_EXTERNAL_MAX; i++) {
if (interrupts & (ULL(1) << i)) {
// See table 4-19 of the 21164 hardware reference
ipl = i;
summary |= (ULL(1) << i);
}
}
}
if (ipl && ipl > this->readMiscReg(IPR_IPLR, 0)) {
this->setMiscReg(IPR_ISR, summary, 0);
this->setMiscReg(IPR_INTID, ipl, 0);
// Checker needs to know these two registers were updated.
#if USE_CHECKER
if (this->checker) {
this->checker->threadBase()->setMiscReg(IPR_ISR, summary);
this->checker->threadBase()->setMiscReg(IPR_INTID, ipl);
}
#endif
this->trap(Fault(new InterruptFault), 0);
DPRINTF(Flow, "Interrupt! IPLR=%d ipl=%d summary=%x\n",
this->readMiscReg(IPR_IPLR, 0), ipl, summary);
}
}
#endif // FULL_SYSTEM
template <class Impl>
void
AlphaO3CPU<Impl>::trap(Fault fault, unsigned tid)
{
// Pass the thread's TC into the invoke method.
fault->invoke(this->threadContexts[tid]);
}
#if !FULL_SYSTEM
template <class Impl>
void
AlphaO3CPU<Impl>::syscall(int64_t callnum, int tid)
{
DPRINTF(O3CPU, "[tid:%i] Executing syscall().\n\n", tid);
DPRINTF(Activity,"Activity: syscall() called.\n");
// Temporarily increase this by one to account for the syscall
// instruction.
++(this->thread[tid]->funcExeInst);
// Execute the actual syscall.
this->thread[tid]->syscall(callnum);
// Decrease funcExeInst by one as the normal commit will handle
// incrementing it.
--(this->thread[tid]->funcExeInst);
}
template <class Impl>
TheISA::IntReg
AlphaO3CPU<Impl>::getSyscallArg(int i, int tid)
{
return this->readArchIntReg(AlphaISA::ArgumentReg0 + i, tid);
}
template <class Impl>
void
AlphaO3CPU<Impl>::setSyscallArg(int i, IntReg val, int tid)
{
this->setArchIntReg(AlphaISA::ArgumentReg0 + i, val, tid);
}
template <class Impl>
void
AlphaO3CPU<Impl>::setSyscallReturn(SyscallReturn return_value, int tid)
{
// check for error condition. Alpha syscall convention is to
// indicate success/failure in reg a3 (r19) and put the
// return value itself in the standard return value reg (v0).
if (return_value.successful()) {
// no error
this->setArchIntReg(SyscallSuccessReg, 0, tid);
this->setArchIntReg(ReturnValueReg, return_value.value(), tid);
} else {
// got an error, return details
this->setArchIntReg(SyscallSuccessReg, (IntReg) -1, tid);
this->setArchIntReg(ReturnValueReg, -return_value.value(), tid);
}
}
#endif

View File

@@ -28,8 +28,8 @@
* Authors: Kevin Lim
*/
#include "cpu/o3/alpha_dyn_inst_impl.hh"
#include "cpu/o3/alpha_impl.hh"
#include "cpu/o3/alpha/dyn_inst_impl.hh"
#include "cpu/o3/alpha/impl.hh"
// Force instantiation of AlphaDynInst for all the implementations that
// are needed.

View File

@@ -34,8 +34,8 @@
#include "arch/isa_traits.hh"
#include "cpu/base_dyn_inst.hh"
#include "cpu/inst_seq.hh"
#include "cpu/o3/alpha_cpu.hh"
#include "cpu/o3/alpha_impl.hh"
#include "cpu/o3/alpha/cpu.hh"
#include "cpu/o3/alpha/impl.hh"
class Packet;
@@ -51,7 +51,7 @@ class AlphaDynInst : public BaseDynInst<Impl>
{
public:
/** Typedef for the CPU. */
typedef typename Impl::FullCPU FullCPU;
typedef typename Impl::O3CPU O3CPU;
/** Binary machine instruction type. */
typedef TheISA::MachInst MachInst;
@@ -74,7 +74,7 @@ class AlphaDynInst : public BaseDynInst<Impl>
public:
/** BaseDynInst constructor given a binary instruction. */
AlphaDynInst(ExtMachInst inst, Addr PC, Addr Pred_PC, InstSeqNum seq_num,
FullCPU *cpu);
O3CPU *cpu);
/** BaseDynInst constructor given a static inst pointer. */
AlphaDynInst(StaticInstPtr &_staticInst);

View File

@@ -28,11 +28,11 @@
* Authors: Kevin Lim
*/
#include "cpu/o3/alpha_dyn_inst.hh"
#include "cpu/o3/alpha/dyn_inst.hh"
template <class Impl>
AlphaDynInst<Impl>::AlphaDynInst(ExtMachInst inst, Addr PC, Addr Pred_PC,
InstSeqNum seq_num, FullCPU *cpu)
InstSeqNum seq_num, O3CPU *cpu)
: BaseDynInst<Impl>(inst, PC, Pred_PC, seq_num, cpu)
{
initVars();
@@ -102,15 +102,7 @@ template <class Impl>
Fault
AlphaDynInst<Impl>::completeAcc(Packet *pkt)
{
if (this->isLoad()) {
this->fault = this->staticInst->completeAcc(pkt, this,
this->traceData);
} else if (this->isStore()) {
this->fault = this->staticInst->completeAcc(pkt, this,
this->traceData);
} else {
panic("Unknown type!");
}
this->fault = this->staticInst->completeAcc(pkt, this, this->traceData);
return this->fault;
}

View File

@@ -33,20 +33,21 @@
#include "arch/alpha/isa_traits.hh"
#include "cpu/o3/alpha_params.hh"
#include "cpu/o3/alpha/params.hh"
#include "cpu/o3/cpu_policy.hh"
// Forward declarations.
template <class Impl>
class AlphaDynInst;
template <class Impl>
class AlphaFullCPU;
class AlphaO3CPU;
/** Implementation specific struct that defines several key types to the
* CPU, the stages within the CPU, the time buffers, and the DynInst.
* The struct defines the ISA, the CPU policy, the specific DynInst, the
* specific FullCPU, and all of the structs from the time buffers to do
* specific O3CPU, and all of the structs from the time buffers to do
* communication.
* This is one of the key things that must be defined for each hardware
* specific CPU implementation.
@@ -67,8 +68,14 @@ struct AlphaSimpleImpl
*/
typedef RefCountingPtr<DynInst> DynInstPtr;
/** The FullCPU type to be used. */
typedef AlphaFullCPU<AlphaSimpleImpl> FullCPU;
/** The O3CPU type to be used. */
typedef AlphaO3CPU<AlphaSimpleImpl> O3CPU;
/** Same typedef, but for CPUType. BaseDynInst may not always use
* an O3 CPU, so it's clearer to call it CPUType instead in that
* case.
*/
typedef O3CPU CPUType;
/** The Params to be passed to each stage. */
typedef AlphaSimpleParams Params;
@@ -79,4 +86,7 @@ struct AlphaSimpleImpl
};
};
/** The O3Impl to be used. */
typedef AlphaSimpleImpl O3CPUImpl;
#endif // __CPU_O3_ALPHA_IMPL_HH__

View File

@@ -0,0 +1,60 @@
/*
* Copyright (c) 2004-2006 The Regents of The University of Michigan
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met: redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer;
* redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution;
* neither the name of the copyright holders nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Authors: Kevin Lim
*/
#ifndef __CPU_O3_ALPHA_PARAMS_HH__
#define __CPU_O3_ALPHA_PARAMS_HH__
#include "cpu/o3/cpu.hh"
#include "cpu/o3/params.hh"
//Forward declarations
class AlphaDTB;
class AlphaITB;
class MemObject;
class Process;
class System;
/**
* This file defines the parameters that will be used for the AlphaO3CPU.
* This must be defined externally so that the Impl can have a params class
* defined that it can pass to all of the individual stages.
*/
class AlphaSimpleParams : public O3Params
{
public:
#if FULL_SYSTEM
AlphaITB *itb;
AlphaDTB *dtb;
#endif
};
#endif // __CPU_O3_ALPHA_PARAMS_HH__

View File

@@ -0,0 +1,36 @@
/*
* Copyright (c) 2004-2006 The Regents of The University of Michigan
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met: redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer;
* redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution;
* neither the name of the copyright holders nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Authors: Kevin Lim
* Korey Sewell
*/
#include "cpu/o3/thread_context.hh"
#include "cpu/o3/thread_context_impl.hh"
template class O3ThreadContext<AlphaSimpleImpl>;

View File

@@ -0,0 +1,88 @@
/*
* Copyright (c) 2004-2006 The Regents of The University of Michigan
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met: redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer;
* redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution;
* neither the name of the copyright holders nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Authors: Kevin Lim
* Korey Sewell
*/
#include "cpu/o3/thread_context.hh"
template <class Impl>
class AlphaTC : public O3ThreadContext<Impl>
{
public:
#if FULL_SYSTEM
/** Returns a pointer to the ITB. */
virtual AlphaITB *getITBPtr() { return this->cpu->itb; }
/** Returns a pointer to the DTB. */
virtual AlphaDTB *getDTBPtr() { return this->cpu->dtb; }
/** Returns pointer to the quiesce event. */
virtual EndQuiesceEvent *getQuiesceEvent()
{
return this->thread->quiesceEvent;
}
/** Returns if the thread is currently in PAL mode, based on
* the PC's value. */
virtual bool inPalMode()
{ return TheISA::PcPAL(this->cpu->readPC(this->thread->readTid())); }
#endif
virtual uint64_t readNextNPC()
{
panic("Alpha has no NextNPC!");
return 0;
}
virtual void setNextNPC(uint64_t val)
{
panic("Alpha has no NextNPC!");
}
virtual void changeRegFileContext(TheISA::RegFile::ContextParam param,
TheISA::RegFile::ContextVal val)
{ panic("Not supported on Alpha!"); }
/** This function exits the thread context in the CPU and returns
* 1 if the CPU has no more active threads (meaning it's OK to exit);
* Used in syscall-emulation mode when a thread executes the 'exit'
* syscall.
*/
virtual int exit()
{
this->deallocate();
// If there are still threads executing in the system
if (this->cpu->numActiveThreads())
return 0; // don't exit simulation
else
return 1; // exit simulation
}
};

View File

@@ -1,434 +0,0 @@
/*
* Copyright (c) 2004-2006 The Regents of The University of Michigan
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met: redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer;
* redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution;
* neither the name of the copyright holders nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Authors: Kevin Lim
*/
#ifndef __CPU_O3_ALPHA_FULL_CPU_HH__
#define __CPU_O3_ALPHA_FULL_CPU_HH__
#include "arch/isa_traits.hh"
#include "cpu/thread_context.hh"
#include "cpu/o3/cpu.hh"
#include "sim/byteswap.hh"
class EndQuiesceEvent;
namespace Kernel {
class Statistics;
};
class TranslatingPort;
/**
* AlphaFullCPU class. Derives from the FullO3CPU class, and
* implements all ISA and implementation specific functions of the
* CPU. This is the CPU class that is used for the SimObjects, and is
* what is given to the DynInsts. Most of its state exists in the
* FullO3CPU; the state is has is mainly for ISA specific
* functionality.
*/
template <class Impl>
class AlphaFullCPU : public FullO3CPU<Impl>
{
protected:
typedef TheISA::IntReg IntReg;
typedef TheISA::FloatReg FloatReg;
typedef TheISA::FloatRegBits FloatRegBits;
typedef TheISA::MiscReg MiscReg;
typedef TheISA::RegFile RegFile;
typedef TheISA::MiscRegFile MiscRegFile;
public:
typedef O3ThreadState<Impl> ImplState;
typedef O3ThreadState<Impl> Thread;
typedef typename Impl::Params Params;
/** Constructs an AlphaFullCPU with the given parameters. */
AlphaFullCPU(Params *params);
/**
* Derived ThreadContext class for use with the AlphaFullCPU. It
* provides the interface for any external objects to access a
* single thread's state and some general CPU state. Any time
* external objects try to update state through this interface,
* the CPU will create an event to squash all in-flight
* instructions in order to ensure state is maintained correctly.
* It must be defined specifically for the AlphaFullCPU because
* not all architectural state is located within the O3ThreadState
* (such as the commit PC, and registers), and specific actions
* must be taken when using this interface (such as squashing all
* in-flight instructions when doing a write to this interface).
*/
class AlphaTC : public ThreadContext
{
public:
/** Pointer to the CPU. */
AlphaFullCPU<Impl> *cpu;
/** Pointer to the thread state that this TC corrseponds to. */
O3ThreadState<Impl> *thread;
/** Returns a pointer to this CPU. */
virtual BaseCPU *getCpuPtr() { return cpu; }
/** Sets this CPU's ID. */
virtual void setCpuId(int id) { cpu->cpu_id = id; }
/** Reads this CPU's ID. */
virtual int readCpuId() { return cpu->cpu_id; }
#if FULL_SYSTEM
/** Returns a pointer to the system. */
virtual System *getSystemPtr() { return cpu->system; }
/** Returns a pointer to physical memory. */
virtual PhysicalMemory *getPhysMemPtr() { return cpu->physmem; }
/** Returns a pointer to the ITB. */
virtual AlphaITB *getITBPtr() { return cpu->itb; }
/** Returns a pointer to the DTB. */
virtual AlphaDTB *getDTBPtr() { return cpu->dtb; }
/** Returns a pointer to this thread's kernel statistics. */
virtual Kernel::Statistics *getKernelStats()
{ return thread->kernelStats; }
virtual FunctionalPort *getPhysPort() { return thread->getPhysPort(); }
virtual VirtualPort *getVirtPort(ThreadContext *src_tc = NULL);
void delVirtPort(VirtualPort *vp);
#else
virtual TranslatingPort *getMemPort() { return thread->getMemPort(); }
/** Returns a pointer to this thread's process. */
virtual Process *getProcessPtr() { return thread->getProcessPtr(); }
#endif
/** Returns this thread's status. */
virtual Status status() const { return thread->status(); }
/** Sets this thread's status. */
virtual void setStatus(Status new_status)
{ thread->setStatus(new_status); }
/** Set the status to Active. Optional delay indicates number of
* cycles to wait before beginning execution. */
virtual void activate(int delay = 1);
/** Set the status to Suspended. */
virtual void suspend();
/** Set the status to Unallocated. */
virtual void deallocate();
/** Set the status to Halted. */
virtual void halt();
#if FULL_SYSTEM
/** Dumps the function profiling information.
* @todo: Implement.
*/
virtual void dumpFuncProfile();
#endif
/** Takes over execution of a thread from another CPU. */
virtual void takeOverFrom(ThreadContext *old_context);
/** Registers statistics associated with this TC. */
virtual void regStats(const std::string &name);
/** Serializes state. */
virtual void serialize(std::ostream &os);
/** Unserializes state. */
virtual void unserialize(Checkpoint *cp, const std::string &section);
#if FULL_SYSTEM
/** Returns pointer to the quiesce event. */
virtual EndQuiesceEvent *getQuiesceEvent();
/** Reads the last tick that this thread was activated on. */
virtual Tick readLastActivate();
/** Reads the last tick that this thread was suspended on. */
virtual Tick readLastSuspend();
/** Clears the function profiling information. */
virtual void profileClear();
/** Samples the function profiling information. */
virtual void profileSample();
#endif
/** Returns this thread's ID number. */
virtual int getThreadNum() { return thread->readTid(); }
/** Returns the instruction this thread is currently committing.
* Only used when an instruction faults.
*/
virtual TheISA::MachInst getInst();
/** Copies the architectural registers from another TC into this TC. */
virtual void copyArchRegs(ThreadContext *tc);
/** Resets all architectural registers to 0. */
virtual void clearArchRegs();
/** Reads an integer register. */
virtual uint64_t readIntReg(int reg_idx);
virtual FloatReg readFloatReg(int reg_idx, int width);
virtual FloatReg readFloatReg(int reg_idx);
virtual FloatRegBits readFloatRegBits(int reg_idx, int width);
virtual FloatRegBits readFloatRegBits(int reg_idx);
/** Sets an integer register to a value. */
virtual void setIntReg(int reg_idx, uint64_t val);
virtual void setFloatReg(int reg_idx, FloatReg val, int width);
virtual void setFloatReg(int reg_idx, FloatReg val);
virtual void setFloatRegBits(int reg_idx, FloatRegBits val, int width);
virtual void setFloatRegBits(int reg_idx, FloatRegBits val);
/** Reads this thread's PC. */
virtual uint64_t readPC()
{ return cpu->readPC(thread->readTid()); }
/** Sets this thread's PC. */
virtual void setPC(uint64_t val);
/** Reads this thread's next PC. */
virtual uint64_t readNextPC()
{ return cpu->readNextPC(thread->readTid()); }
/** Sets this thread's next PC. */
virtual void setNextPC(uint64_t val);
virtual uint64_t readNextNPC()
{
panic("Alpha has no NextNPC!");
return 0;
}
virtual void setNextNPC(uint64_t val)
{ }
/** Reads a miscellaneous register. */
virtual MiscReg readMiscReg(int misc_reg)
{ return cpu->readMiscReg(misc_reg, thread->readTid()); }
/** Reads a misc. register, including any side-effects the
* read might have as defined by the architecture. */
virtual MiscReg readMiscRegWithEffect(int misc_reg, Fault &fault)
{ return cpu->readMiscRegWithEffect(misc_reg, fault, thread->readTid()); }
/** Sets a misc. register. */
virtual Fault setMiscReg(int misc_reg, const MiscReg &val);
/** Sets a misc. register, including any side-effects the
* write might have as defined by the architecture. */
virtual Fault setMiscRegWithEffect(int misc_reg, const MiscReg &val);
/** Returns the number of consecutive store conditional failures. */
// @todo: Figure out where these store cond failures should go.
virtual unsigned readStCondFailures()
{ return thread->storeCondFailures; }
/** Sets the number of consecutive store conditional failures. */
virtual void setStCondFailures(unsigned sc_failures)
{ thread->storeCondFailures = sc_failures; }
#if FULL_SYSTEM
/** Returns if the thread is currently in PAL mode, based on
* the PC's value. */
virtual bool inPalMode()
{ return TheISA::PcPAL(cpu->readPC(thread->readTid())); }
#endif
// Only really makes sense for old CPU model. Lots of code
// outside the CPU still checks this function, so it will
// always return false to keep everything working.
/** Checks if the thread is misspeculating. Because it is
* very difficult to determine if the thread is
* misspeculating, this is set as false. */
virtual bool misspeculating() { return false; }
#if !FULL_SYSTEM
/** Gets a syscall argument by index. */
virtual IntReg getSyscallArg(int i);
/** Sets a syscall argument. */
virtual void setSyscallArg(int i, IntReg val);
/** Sets the syscall return value. */
virtual void setSyscallReturn(SyscallReturn return_value);
/** Executes a syscall in SE mode. */
virtual void syscall(int64_t callnum)
{ return cpu->syscall(callnum, thread->readTid()); }
/** Reads the funcExeInst counter. */
virtual Counter readFuncExeInst() { return thread->funcExeInst; }
#endif
virtual void changeRegFileContext(TheISA::RegFile::ContextParam param,
TheISA::RegFile::ContextVal val)
{ panic("Not supported on Alpha!"); }
};
#if FULL_SYSTEM
/** ITB pointer. */
AlphaITB *itb;
/** DTB pointer. */
AlphaDTB *dtb;
#endif
/** Registers statistics. */
void regStats();
#if FULL_SYSTEM
/** Translates instruction requestion. */
Fault translateInstReq(RequestPtr &req, Thread *thread)
{
return itb->translate(req, thread->getTC());
}
/** Translates data read request. */
Fault translateDataReadReq(RequestPtr &req, Thread *thread)
{
return dtb->translate(req, thread->getTC(), false);
}
/** Translates data write request. */
Fault translateDataWriteReq(RequestPtr &req, Thread *thread)
{
return dtb->translate(req, thread->getTC(), true);
}
#else
/** Translates instruction requestion in syscall emulation mode. */
Fault translateInstReq(RequestPtr &req, Thread *thread)
{
return thread->getProcessPtr()->pTable->translate(req);
}
/** Translates data read request in syscall emulation mode. */
Fault translateDataReadReq(RequestPtr &req, Thread *thread)
{
return thread->getProcessPtr()->pTable->translate(req);
}
/** Translates data write request in syscall emulation mode. */
Fault translateDataWriteReq(RequestPtr &req, Thread *thread)
{
return thread->getProcessPtr()->pTable->translate(req);
}
#endif
/** Reads a miscellaneous register. */
MiscReg readMiscReg(int misc_reg, unsigned tid);
/** Reads a misc. register, including any side effects the read
* might have as defined by the architecture.
*/
MiscReg readMiscRegWithEffect(int misc_reg, Fault &fault, unsigned tid);
/** Sets a miscellaneous register. */
Fault setMiscReg(int misc_reg, const MiscReg &val, unsigned tid);
/** Sets a misc. register, including any side effects the write
* might have as defined by the architecture.
*/
Fault setMiscRegWithEffect(int misc_reg, const MiscReg &val, unsigned tid);
/** Initiates a squash of all in-flight instructions for a given
* thread. The source of the squash is an external update of
* state through the TC.
*/
void squashFromTC(unsigned tid);
#if FULL_SYSTEM
/** Posts an interrupt. */
void post_interrupt(int int_num, int index);
/** Reads the interrupt flag. */
int readIntrFlag();
/** Sets the interrupt flags. */
void setIntrFlag(int val);
/** HW return from error interrupt. */
Fault hwrei(unsigned tid);
/** Returns if a specific PC is a PAL mode PC. */
bool inPalMode(uint64_t PC)
{ return AlphaISA::PcPAL(PC); }
/** Traps to handle given fault. */
void trap(Fault fault, unsigned tid);
bool simPalCheck(int palFunc, unsigned tid);
/** Processes any interrupts. */
void processInterrupts();
/** Halts the CPU. */
void halt() { panic("Halt not implemented!\n"); }
#endif
#if !FULL_SYSTEM
/** Executes a syscall.
* @todo: Determine if this needs to be virtual.
*/
void syscall(int64_t callnum, int tid);
/** Gets a syscall argument. */
IntReg getSyscallArg(int i, int tid);
/** Used to shift args for indirect syscall. */
void setSyscallArg(int i, IntReg val, int tid);
/** Sets the return value of a syscall. */
void setSyscallReturn(SyscallReturn return_value, int tid);
#endif
/** CPU read function, forwards read to LSQ. */
template <class T>
Fault read(RequestPtr &req, T &data, int load_idx)
{
return this->iew.ldstQueue.read(req, data, load_idx);
}
/** CPU write function, forwards write to LSQ. */
template <class T>
Fault write(RequestPtr &req, T &data, int store_idx)
{
return this->iew.ldstQueue.write(req, data, store_idx);
}
Addr lockAddr;
/** Temporary fix for the lock flag, works in the UP case. */
bool lockFlag;
};
#endif // __CPU_O3_ALPHA_FULL_CPU_HH__

View File

@@ -1,872 +0,0 @@
/*
* Copyright (c) 2004-2006 The Regents of The University of Michigan
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met: redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer;
* redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution;
* neither the name of the copyright holders nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Authors: Kevin Lim
*/
#include "arch/alpha/faults.hh"
#include "base/cprintf.hh"
#include "base/statistics.hh"
#include "base/timebuf.hh"
#include "cpu/checker/thread_context.hh"
#include "sim/sim_events.hh"
#include "sim/stats.hh"
#include "cpu/o3/alpha_cpu.hh"
#include "cpu/o3/alpha_params.hh"
#include "cpu/o3/comm.hh"
#include "cpu/o3/thread_state.hh"
#if FULL_SYSTEM
#include "arch/alpha/osfpal.hh"
#include "arch/isa_traits.hh"
#include "cpu/quiesce_event.hh"
#include "kern/kernel_stats.hh"
#include "sim/system.hh"
#endif
using namespace TheISA;
template <class Impl>
AlphaFullCPU<Impl>::AlphaFullCPU(Params *params)
#if FULL_SYSTEM
: FullO3CPU<Impl>(params), itb(params->itb), dtb(params->dtb)
#else
: FullO3CPU<Impl>(params)
#endif
{
DPRINTF(FullCPU, "AlphaFullCPU: Creating AlphaFullCPU object.\n");
// Setup any thread state.
this->thread.resize(this->numThreads);
for (int i = 0; i < this->numThreads; ++i) {
#if FULL_SYSTEM
// SMT is not supported in FS mode yet.
assert(this->numThreads == 1);
this->thread[i] = new Thread(this, 0);
this->thread[i]->setStatus(ThreadContext::Suspended);
#else
if (i < params->workload.size()) {
DPRINTF(FullCPU, "FullCPU: Workload[%i] process is %#x",
i, this->thread[i]);
this->thread[i] = new Thread(this, i, params->workload[i],
i, params->mem);
this->thread[i]->setStatus(ThreadContext::Suspended);
#if !FULL_SYSTEM
/* Use this port to for syscall emulation writes to memory. */
Port *mem_port;
TranslatingPort *trans_port;
trans_port = new TranslatingPort(csprintf("%s-%d-funcport",
name(), i),
params->workload[i]->pTable,
false);
mem_port = params->mem->getPort("functional");
mem_port->setPeer(trans_port);
trans_port->setPeer(mem_port);
this->thread[i]->setMemPort(trans_port);
#endif
//usedTids[i] = true;
//threadMap[i] = i;
} else {
//Allocate Empty thread so M5 can use later
//when scheduling threads to CPU
Process* dummy_proc = NULL;
this->thread[i] = new Thread(this, i, dummy_proc, i, params->mem);
//usedTids[i] = false;
}
#endif // !FULL_SYSTEM
ThreadContext *tc;
// Setup the TC that will serve as the interface to the threads/CPU.
AlphaTC *alpha_tc = new AlphaTC;
// If we're using a checker, then the TC should be the
// CheckerThreadContext.
if (params->checker) {
tc = new CheckerThreadContext<AlphaTC>(
alpha_tc, this->checker);
} else {
tc = alpha_tc;
}
alpha_tc->cpu = this;
alpha_tc->thread = this->thread[i];
#if FULL_SYSTEM
// Setup quiesce event.
this->thread[i]->quiesceEvent = new EndQuiesceEvent(tc);
Port *mem_port;
FunctionalPort *phys_port;
VirtualPort *virt_port;
phys_port = new FunctionalPort(csprintf("%s-%d-funcport",
name(), i));
mem_port = this->system->physmem->getPort("functional");
mem_port->setPeer(phys_port);
phys_port->setPeer(mem_port);
virt_port = new VirtualPort(csprintf("%s-%d-vport",
name(), i));
mem_port = this->system->physmem->getPort("functional");
mem_port->setPeer(virt_port);
virt_port->setPeer(mem_port);
this->thread[i]->setPhysPort(phys_port);
this->thread[i]->setVirtPort(virt_port);
#endif
// Give the thread the TC.
this->thread[i]->tc = tc;
// Add the TC to the CPU's list of TC's.
this->threadContexts.push_back(tc);
}
for (int i=0; i < this->numThreads; i++) {
this->thread[i]->setFuncExeInst(0);
}
// Sets CPU pointers. These must be set at this level because the CPU
// pointers are defined to be the highest level of CPU class.
this->fetch.setCPU(this);
this->decode.setCPU(this);
this->rename.setCPU(this);
this->iew.setCPU(this);
this->commit.setCPU(this);
this->rob.setCPU(this);
this->regFile.setCPU(this);
lockAddr = 0;
lockFlag = false;
}
template <class Impl>
void
AlphaFullCPU<Impl>::regStats()
{
// Register stats for everything that has stats.
this->fullCPURegStats();
this->fetch.regStats();
this->decode.regStats();
this->rename.regStats();
this->iew.regStats();
this->commit.regStats();
}
#if FULL_SYSTEM
template <class Impl>
VirtualPort *
AlphaFullCPU<Impl>::AlphaTC::getVirtPort(ThreadContext *src_tc)
{
if (!src_tc)
return thread->getVirtPort();
VirtualPort *vp;
Port *mem_port;
vp = new VirtualPort("tc-vport", src_tc);
mem_port = cpu->system->physmem->getPort("functional");
mem_port->setPeer(vp);
vp->setPeer(mem_port);
return vp;
}
template <class Impl>
void
AlphaFullCPU<Impl>::AlphaTC::dumpFuncProfile()
{
// Currently not supported
}
#endif
template <class Impl>
void
AlphaFullCPU<Impl>::AlphaTC::takeOverFrom(ThreadContext *old_context)
{
// some things should already be set up
#if FULL_SYSTEM
assert(getSystemPtr() == old_context->getSystemPtr());
#else
assert(getProcessPtr() == old_context->getProcessPtr());
#endif
// copy over functional state
setStatus(old_context->status());
copyArchRegs(old_context);
setCpuId(old_context->readCpuId());
#if !FULL_SYSTEM
thread->funcExeInst = old_context->readFuncExeInst();
#else
EndQuiesceEvent *other_quiesce = old_context->getQuiesceEvent();
if (other_quiesce) {
// Point the quiesce event's TC at this TC so that it wakes up
// the proper CPU.
other_quiesce->tc = this;
}
if (thread->quiesceEvent) {
thread->quiesceEvent->tc = this;
}
// Transfer kernel stats from one CPU to the other.
thread->kernelStats = old_context->getKernelStats();
// storeCondFailures = 0;
cpu->lockFlag = false;
#endif
old_context->setStatus(ThreadContext::Unallocated);
thread->inSyscall = false;
thread->trapPending = false;
}
#if FULL_SYSTEM
template <class Impl>
void
AlphaFullCPU<Impl>::AlphaTC::delVirtPort(VirtualPort *vp)
{
delete vp->getPeer();
delete vp;
}
#endif
template <class Impl>
void
AlphaFullCPU<Impl>::AlphaTC::activate(int delay)
{
DPRINTF(FullCPU, "Calling activate on AlphaTC\n");
if (thread->status() == ThreadContext::Active)
return;
#if FULL_SYSTEM
thread->lastActivate = curTick;
#endif
if (thread->status() == ThreadContext::Unallocated) {
cpu->activateWhenReady(thread->readTid());
return;
}
thread->setStatus(ThreadContext::Active);
// status() == Suspended
cpu->activateContext(thread->readTid(), delay);
}
template <class Impl>
void
AlphaFullCPU<Impl>::AlphaTC::suspend()
{
DPRINTF(FullCPU, "Calling suspend on AlphaTC\n");
if (thread->status() == ThreadContext::Suspended)
return;
#if FULL_SYSTEM
thread->lastActivate = curTick;
thread->lastSuspend = curTick;
#endif
/*
#if FULL_SYSTEM
// Don't change the status from active if there are pending interrupts
if (cpu->check_interrupts()) {
assert(status() == ThreadContext::Active);
return;
}
#endif
*/
thread->setStatus(ThreadContext::Suspended);
cpu->suspendContext(thread->readTid());
}
template <class Impl>
void
AlphaFullCPU<Impl>::AlphaTC::deallocate()
{
DPRINTF(FullCPU, "Calling deallocate on AlphaTC\n");
if (thread->status() == ThreadContext::Unallocated)
return;
thread->setStatus(ThreadContext::Unallocated);
cpu->deallocateContext(thread->readTid());
}
template <class Impl>
void
AlphaFullCPU<Impl>::AlphaTC::halt()
{
DPRINTF(FullCPU, "Calling halt on AlphaTC\n");
if (thread->status() == ThreadContext::Halted)
return;
thread->setStatus(ThreadContext::Halted);
cpu->haltContext(thread->readTid());
}
template <class Impl>
void
AlphaFullCPU<Impl>::AlphaTC::regStats(const std::string &name)
{
#if FULL_SYSTEM
thread->kernelStats = new Kernel::Statistics(cpu->system);
thread->kernelStats->regStats(name + ".kern");
#endif
}
template <class Impl>
void
AlphaFullCPU<Impl>::AlphaTC::serialize(std::ostream &os)
{
#if FULL_SYSTEM
if (thread->kernelStats)
thread->kernelStats->serialize(os);
#endif
}
template <class Impl>
void
AlphaFullCPU<Impl>::AlphaTC::unserialize(Checkpoint *cp, const std::string &section)
{
#if FULL_SYSTEM
if (thread->kernelStats)
thread->kernelStats->unserialize(cp, section);
#endif
}
#if FULL_SYSTEM
template <class Impl>
EndQuiesceEvent *
AlphaFullCPU<Impl>::AlphaTC::getQuiesceEvent()
{
return thread->quiesceEvent;
}
template <class Impl>
Tick
AlphaFullCPU<Impl>::AlphaTC::readLastActivate()
{
return thread->lastActivate;
}
template <class Impl>
Tick
AlphaFullCPU<Impl>::AlphaTC::readLastSuspend()
{
return thread->lastSuspend;
}
template <class Impl>
void
AlphaFullCPU<Impl>::AlphaTC::profileClear()
{}
template <class Impl>
void
AlphaFullCPU<Impl>::AlphaTC::profileSample()
{}
#endif
template <class Impl>
TheISA::MachInst
AlphaFullCPU<Impl>::AlphaTC:: getInst()
{
return thread->getInst();
}
template <class Impl>
void
AlphaFullCPU<Impl>::AlphaTC::copyArchRegs(ThreadContext *tc)
{
// This function will mess things up unless the ROB is empty and
// there are no instructions in the pipeline.
unsigned tid = thread->readTid();
PhysRegIndex renamed_reg;
// First loop through the integer registers.
for (int i = 0; i < AlphaISA::NumIntRegs; ++i) {
renamed_reg = cpu->renameMap[tid].lookup(i);
DPRINTF(FullCPU, "FullCPU: Copying over register %i, had data %lli, "
"now has data %lli.\n",
renamed_reg, cpu->readIntReg(renamed_reg),
tc->readIntReg(i));
cpu->setIntReg(renamed_reg, tc->readIntReg(i));
}
// Then loop through the floating point registers.
for (int i = 0; i < AlphaISA::NumFloatRegs; ++i) {
renamed_reg = cpu->renameMap[tid].lookup(i + AlphaISA::FP_Base_DepTag);
cpu->setFloatRegBits(renamed_reg,
tc->readFloatRegBits(i));
}
// Copy the misc regs.
copyMiscRegs(tc, this);
// Then finally set the PC and the next PC.
cpu->setPC(tc->readPC(), tid);
cpu->setNextPC(tc->readNextPC(), tid);
#if !FULL_SYSTEM
this->thread->funcExeInst = tc->readFuncExeInst();
#endif
}
template <class Impl>
void
AlphaFullCPU<Impl>::AlphaTC::clearArchRegs()
{}
template <class Impl>
uint64_t
AlphaFullCPU<Impl>::AlphaTC::readIntReg(int reg_idx)
{
return cpu->readArchIntReg(reg_idx, thread->readTid());
}
template <class Impl>
FloatReg
AlphaFullCPU<Impl>::AlphaTC::readFloatReg(int reg_idx, int width)
{
switch(width) {
case 32:
return cpu->readArchFloatRegSingle(reg_idx, thread->readTid());
case 64:
return cpu->readArchFloatRegDouble(reg_idx, thread->readTid());
default:
panic("Unsupported width!");
return 0;
}
}
template <class Impl>
FloatReg
AlphaFullCPU<Impl>::AlphaTC::readFloatReg(int reg_idx)
{
return cpu->readArchFloatRegSingle(reg_idx, thread->readTid());
}
template <class Impl>
FloatRegBits
AlphaFullCPU<Impl>::AlphaTC::readFloatRegBits(int reg_idx, int width)
{
DPRINTF(Fault, "Reading floatint register through the TC!\n");
return cpu->readArchFloatRegInt(reg_idx, thread->readTid());
}
template <class Impl>
FloatRegBits
AlphaFullCPU<Impl>::AlphaTC::readFloatRegBits(int reg_idx)
{
return cpu->readArchFloatRegInt(reg_idx, thread->readTid());
}
template <class Impl>
void
AlphaFullCPU<Impl>::AlphaTC::setIntReg(int reg_idx, uint64_t val)
{
cpu->setArchIntReg(reg_idx, val, thread->readTid());
// Squash if we're not already in a state update mode.
if (!thread->trapPending && !thread->inSyscall) {
cpu->squashFromTC(thread->readTid());
}
}
template <class Impl>
void
AlphaFullCPU<Impl>::AlphaTC::setFloatReg(int reg_idx, FloatReg val, int width)
{
switch(width) {
case 32:
cpu->setArchFloatRegSingle(reg_idx, val, thread->readTid());
break;
case 64:
cpu->setArchFloatRegDouble(reg_idx, val, thread->readTid());
break;
}
// Squash if we're not already in a state update mode.
if (!thread->trapPending && !thread->inSyscall) {
cpu->squashFromTC(thread->readTid());
}
}
template <class Impl>
void
AlphaFullCPU<Impl>::AlphaTC::setFloatReg(int reg_idx, FloatReg val)
{
cpu->setArchFloatRegSingle(reg_idx, val, thread->readTid());
if (!thread->trapPending && !thread->inSyscall) {
cpu->squashFromTC(thread->readTid());
}
}
template <class Impl>
void
AlphaFullCPU<Impl>::AlphaTC::setFloatRegBits(int reg_idx, FloatRegBits val,
int width)
{
DPRINTF(Fault, "Setting floatint register through the TC!\n");
cpu->setArchFloatRegInt(reg_idx, val, thread->readTid());
// Squash if we're not already in a state update mode.
if (!thread->trapPending && !thread->inSyscall) {
cpu->squashFromTC(thread->readTid());
}
}
template <class Impl>
void
AlphaFullCPU<Impl>::AlphaTC::setFloatRegBits(int reg_idx, FloatRegBits val)
{
cpu->setArchFloatRegInt(reg_idx, val, thread->readTid());
// Squash if we're not already in a state update mode.
if (!thread->trapPending && !thread->inSyscall) {
cpu->squashFromTC(thread->readTid());
}
}
template <class Impl>
void
AlphaFullCPU<Impl>::AlphaTC::setPC(uint64_t val)
{
cpu->setPC(val, thread->readTid());
// Squash if we're not already in a state update mode.
if (!thread->trapPending && !thread->inSyscall) {
cpu->squashFromTC(thread->readTid());
}
}
template <class Impl>
void
AlphaFullCPU<Impl>::AlphaTC::setNextPC(uint64_t val)
{
cpu->setNextPC(val, thread->readTid());
// Squash if we're not already in a state update mode.
if (!thread->trapPending && !thread->inSyscall) {
cpu->squashFromTC(thread->readTid());
}
}
template <class Impl>
Fault
AlphaFullCPU<Impl>::AlphaTC::setMiscReg(int misc_reg, const MiscReg &val)
{
Fault ret_fault = cpu->setMiscReg(misc_reg, val, thread->readTid());
// Squash if we're not already in a state update mode.
if (!thread->trapPending && !thread->inSyscall) {
cpu->squashFromTC(thread->readTid());
}
return ret_fault;
}
template <class Impl>
Fault
AlphaFullCPU<Impl>::AlphaTC::setMiscRegWithEffect(int misc_reg,
const MiscReg &val)
{
Fault ret_fault = cpu->setMiscRegWithEffect(misc_reg, val,
thread->readTid());
// Squash if we're not already in a state update mode.
if (!thread->trapPending && !thread->inSyscall) {
cpu->squashFromTC(thread->readTid());
}
return ret_fault;
}
#if !FULL_SYSTEM
template <class Impl>
TheISA::IntReg
AlphaFullCPU<Impl>::AlphaTC::getSyscallArg(int i)
{
return cpu->getSyscallArg(i, thread->readTid());
}
template <class Impl>
void
AlphaFullCPU<Impl>::AlphaTC::setSyscallArg(int i, IntReg val)
{
cpu->setSyscallArg(i, val, thread->readTid());
}
template <class Impl>
void
AlphaFullCPU<Impl>::AlphaTC::setSyscallReturn(SyscallReturn return_value)
{
cpu->setSyscallReturn(return_value, thread->readTid());
}
#endif // FULL_SYSTEM
template <class Impl>
MiscReg
AlphaFullCPU<Impl>::readMiscReg(int misc_reg, unsigned tid)
{
return this->regFile.readMiscReg(misc_reg, tid);
}
template <class Impl>
MiscReg
AlphaFullCPU<Impl>::readMiscRegWithEffect(int misc_reg, Fault &fault,
unsigned tid)
{
return this->regFile.readMiscRegWithEffect(misc_reg, fault, tid);
}
template <class Impl>
Fault
AlphaFullCPU<Impl>::setMiscReg(int misc_reg, const MiscReg &val, unsigned tid)
{
return this->regFile.setMiscReg(misc_reg, val, tid);
}
template <class Impl>
Fault
AlphaFullCPU<Impl>::setMiscRegWithEffect(int misc_reg, const MiscReg &val,
unsigned tid)
{
return this->regFile.setMiscRegWithEffect(misc_reg, val, tid);
}
template <class Impl>
void
AlphaFullCPU<Impl>::squashFromTC(unsigned tid)
{
this->thread[tid]->inSyscall = true;
this->commit.generateTCEvent(tid);
}
#if FULL_SYSTEM
template <class Impl>
void
AlphaFullCPU<Impl>::post_interrupt(int int_num, int index)
{
BaseCPU::post_interrupt(int_num, index);
if (this->thread[0]->status() == ThreadContext::Suspended) {
DPRINTF(IPI,"Suspended Processor awoke\n");
this->threadContexts[0]->activate();
}
}
template <class Impl>
int
AlphaFullCPU<Impl>::readIntrFlag()
{
return this->regFile.readIntrFlag();
}
template <class Impl>
void
AlphaFullCPU<Impl>::setIntrFlag(int val)
{
this->regFile.setIntrFlag(val);
}
template <class Impl>
Fault
AlphaFullCPU<Impl>::hwrei(unsigned tid)
{
// Need to clear the lock flag upon returning from an interrupt.
this->lockFlag = false;
this->thread[tid]->kernelStats->hwrei();
this->checkInterrupts = true;
// FIXME: XXX check for interrupts? XXX
return NoFault;
}
template <class Impl>
bool
AlphaFullCPU<Impl>::simPalCheck(int palFunc, unsigned tid)
{
if (this->thread[tid]->kernelStats)
this->thread[tid]->kernelStats->callpal(palFunc,
this->threadContexts[tid]);
switch (palFunc) {
case PAL::halt:
halt();
if (--System::numSystemsRunning == 0)
exitSimLoop("all cpus halted");
break;
case PAL::bpt:
case PAL::bugchk:
if (this->system->breakpoint())
return false;
break;
}
return true;
}
template <class Impl>
void
AlphaFullCPU<Impl>::trap(Fault fault, unsigned tid)
{
// Pass the thread's TC into the invoke method.
fault->invoke(this->threadContexts[tid]);
}
template <class Impl>
void
AlphaFullCPU<Impl>::processInterrupts()
{
// Check for interrupts here. For now can copy the code that
// exists within isa_fullsys_traits.hh. Also assume that thread 0
// is the one that handles the interrupts.
// @todo: Possibly consolidate the interrupt checking code.
// @todo: Allow other threads to handle interrupts.
// Check if there are any outstanding interrupts
//Handle the interrupts
int ipl = 0;
int summary = 0;
this->checkInterrupts = false;
if (this->readMiscReg(IPR_ASTRR, 0))
panic("asynchronous traps not implemented\n");
if (this->readMiscReg(IPR_SIRR, 0)) {
for (int i = INTLEVEL_SOFTWARE_MIN;
i < INTLEVEL_SOFTWARE_MAX; i++) {
if (this->readMiscReg(IPR_SIRR, 0) & (ULL(1) << i)) {
// See table 4-19 of the 21164 hardware reference
ipl = (i - INTLEVEL_SOFTWARE_MIN) + 1;
summary |= (ULL(1) << i);
}
}
}
uint64_t interrupts = this->intr_status();
if (interrupts) {
for (int i = INTLEVEL_EXTERNAL_MIN;
i < INTLEVEL_EXTERNAL_MAX; i++) {
if (interrupts & (ULL(1) << i)) {
// See table 4-19 of the 21164 hardware reference
ipl = i;
summary |= (ULL(1) << i);
}
}
}
if (ipl && ipl > this->readMiscReg(IPR_IPLR, 0)) {
this->setMiscReg(IPR_ISR, summary, 0);
this->setMiscReg(IPR_INTID, ipl, 0);
// Checker needs to know these two registers were updated.
if (this->checker) {
this->checker->threadBase()->setMiscReg(IPR_ISR, summary);
this->checker->threadBase()->setMiscReg(IPR_INTID, ipl);
}
this->trap(Fault(new InterruptFault), 0);
DPRINTF(Flow, "Interrupt! IPLR=%d ipl=%d summary=%x\n",
this->readMiscReg(IPR_IPLR, 0), ipl, summary);
}
}
#endif // FULL_SYSTEM
#if !FULL_SYSTEM
template <class Impl>
void
AlphaFullCPU<Impl>::syscall(int64_t callnum, int tid)
{
DPRINTF(FullCPU, "AlphaFullCPU: [tid:%i] Executing syscall().\n\n", tid);
DPRINTF(Activity,"Activity: syscall() called.\n");
// Temporarily increase this by one to account for the syscall
// instruction.
++(this->thread[tid]->funcExeInst);
// Execute the actual syscall.
this->thread[tid]->syscall(callnum);
// Decrease funcExeInst by one as the normal commit will handle
// incrementing it.
--(this->thread[tid]->funcExeInst);
}
template <class Impl>
TheISA::IntReg
AlphaFullCPU<Impl>::getSyscallArg(int i, int tid)
{
return this->readArchIntReg(AlphaISA::ArgumentReg0 + i, tid);
}
template <class Impl>
void
AlphaFullCPU<Impl>::setSyscallArg(int i, IntReg val, int tid)
{
this->setArchIntReg(AlphaISA::ArgumentReg0 + i, val, tid);
}
template <class Impl>
void
AlphaFullCPU<Impl>::setSyscallReturn(SyscallReturn return_value, int tid)
{
// check for error condition. Alpha syscall convention is to
// indicate success/failure in reg a3 (r19) and put the
// return value itself in the standard return value reg (v0).
if (return_value.successful()) {
// no error
this->setArchIntReg(SyscallSuccessReg, 0, tid);
this->setArchIntReg(ReturnValueReg, return_value.value(), tid);
} else {
// got an error, return details
this->setArchIntReg(SyscallSuccessReg, (IntReg) -1, tid);
this->setArchIntReg(ReturnValueReg, -return_value.value(), tid);
}
}
#endif

View File

@@ -0,0 +1,39 @@
/*
* 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: Kevin Lim
*/
#include "cpu/base_dyn_inst_impl.hh"
#include "cpu/o3/isa_specific.hh"
// Explicit instantiation
template class BaseDynInst<O3CPUImpl>;
template <>
int
BaseDynInst<O3CPUImpl>::instcount = 0;

View File

@@ -29,11 +29,6 @@
*/
#include "cpu/o3/bpred_unit_impl.hh"
#include "cpu/o3/alpha_impl.hh"
#include "cpu/o3/alpha_dyn_inst.hh"
#include "cpu/ozone/ozone_impl.hh"
//#include "cpu/ozone/simple_impl.hh"
#include "cpu/o3/isa_specific.hh"
template class BPredUnit<AlphaSimpleImpl>;
template class BPredUnit<OzoneImpl>;
//template class BPredUnit<SimpleImpl>;
template class BPredUnit<O3CPUImpl>;

View File

@@ -30,16 +30,19 @@
#include <string>
#include "cpu/checker/cpu.hh"
#include "cpu/checker/cpu_impl.hh"
#include "cpu/inst_seq.hh"
#include "cpu/o3/alpha_dyn_inst.hh"
#include "cpu/o3/alpha_impl.hh"
#include "cpu/o3/alpha/dyn_inst.hh"
#include "cpu/o3/alpha/impl.hh"
#include "sim/builder.hh"
#include "sim/process.hh"
#include "sim/sim_object.hh"
class MemObject;
template
class Checker<RefCountingPtr<AlphaDynInst<AlphaSimpleImpl> > >;
/**
* Specific non-templated derived class used for SimObject configuration.
*/
@@ -75,6 +78,7 @@ BEGIN_DECLARE_SIM_OBJECT_PARAMS(O3Checker)
Param<bool> defer_registration;
Param<bool> exitOnError;
Param<bool> warnOnlyOnLoadError;
Param<bool> function_trace;
Param<Tick> function_trace_start;
@@ -105,6 +109,8 @@ BEGIN_INIT_SIM_OBJECT_PARAMS(O3Checker)
INIT_PARAM(defer_registration, "defer system registration (for sampling)"),
INIT_PARAM(exitOnError, "exit on error"),
INIT_PARAM_DFLT(warnOnlyOnLoadError, "warn, but don't exit, if a load "
"result errors", false),
INIT_PARAM(function_trace, "Enable function trace"),
INIT_PARAM(function_trace_start, "Cycle to start function trace")
@@ -121,6 +127,7 @@ CREATE_SIM_OBJECT(O3Checker)
params->max_loads_any_thread = 0;
params->max_loads_all_threads = 0;
params->exitOnError = exitOnError;
params->warnOnlyOnLoadError = warnOnlyOnLoadError;
params->deferRegistration = defer_registration;
params->functionTrace = function_trace;
params->functionTraceStart = function_trace_start;

View File

@@ -28,8 +28,7 @@
* Authors: Kevin Lim
*/
#include "cpu/o3/alpha_dyn_inst.hh"
#include "cpu/o3/alpha_impl.hh"
#include "cpu/o3/isa_specific.hh"
#include "cpu/o3/commit_impl.hh"
template class DefaultCommit<AlphaSimpleImpl>;
template class DefaultCommit<O3CPUImpl>;

View File

@@ -26,6 +26,7 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Authors: Kevin Lim
* Korey Sewell
*/
#ifndef __CPU_O3_COMMIT_HH__
@@ -67,7 +68,7 @@ class DefaultCommit
{
public:
// Typedefs from the Impl.
typedef typename Impl::FullCPU FullCPU;
typedef typename Impl::O3CPU O3CPU;
typedef typename Impl::DynInstPtr DynInstPtr;
typedef typename Impl::Params Params;
typedef typename Impl::CPUPol CPUPol;
@@ -145,7 +146,7 @@ class DefaultCommit
void regStats();
/** Sets the CPU pointer. */
void setCPU(FullCPU *cpu_ptr);
void setCPU(O3CPU *cpu_ptr);
/** Sets the list of threads. */
void setThreads(std::vector<Thread *> &threads);
@@ -161,10 +162,6 @@ class DefaultCommit
/** Sets the pointer to the queue coming from IEW. */
void setIEWQueue(TimeBuffer<IEWStruct> *iq_ptr);
void setFetchStage(Fetch *fetch_stage);
Fetch *fetchStage;
/** Sets the pointer to the IEW stage. */
void setIEWStage(IEW *iew_stage);
@@ -186,11 +183,14 @@ class DefaultCommit
/** Initializes stage by sending back the number of free entries. */
void initStage();
/** Initializes the switching out of commit. */
void switchOut();
/** Initializes the draining of commit. */
bool drain();
/** Resumes execution after draining. */
void resume();
/** Completes the switch out of commit. */
void doSwitchOut();
void switchOut();
/** Takes over from another CPU's thread. */
void takeOverFrom();
@@ -280,12 +280,20 @@ class DefaultCommit
/** Sets the PC of a specific thread. */
void setPC(uint64_t val, unsigned tid) { PC[tid] = val; }
/** Reads the PC of a specific thread. */
/** Reads the next PC of a specific thread. */
uint64_t readNextPC(unsigned tid) { return nextPC[tid]; }
/** Sets the next PC of a specific thread. */
void setNextPC(uint64_t val, unsigned tid) { nextPC[tid] = val; }
#if THE_ISA != ALPHA_ISA
/** Reads the next NPC of a specific thread. */
uint64_t readNextPC(unsigned tid) { return nextNPC[tid]; }
/** Sets the next NPC of a specific thread. */
void setNextPC(uint64_t val, unsigned tid) { nextNPC[tid] = val; }
#endif
private:
/** Time buffer interface. */
TimeBuffer<TimeStruct> *timeBuffer;
@@ -317,16 +325,12 @@ class DefaultCommit
ROB *rob;
private:
/** Pointer to FullCPU. */
FullCPU *cpu;
/** Pointer to O3CPU. */
O3CPU *cpu;
/** Vector of all of the threads. */
std::vector<Thread *> thread;
Fault fetchFault;
int fetchTrapWait;
/** Records that commit has written to the time buffer this cycle. Used for
* the CPU to determine if it can deschedule itself if there is no activity.
*/
@@ -365,11 +369,6 @@ class DefaultCommit
*/
unsigned renameWidth;
/** IEW width, in instructions. Used so ROB knows how many
* instructions to get from the IEW instruction queue.
*/
unsigned iewWidth;
/** Commit width, in instructions. */
unsigned commitWidth;
@@ -379,8 +378,8 @@ class DefaultCommit
/** Number of Active Threads */
unsigned numThreads;
/** Is a switch out pending. */
bool switchPending;
/** Is a drain pending. */
bool drainPending;
/** Is commit switched out. */
bool switchedOut;
@@ -390,10 +389,6 @@ class DefaultCommit
*/
Tick trapLatency;
Tick fetchTrapLatency;
Tick fetchFaultTick;
/** The commit PC of each thread. Refers to the instruction that
* is currently being processed/committed.
*/
@@ -402,6 +397,11 @@ class DefaultCommit
/** The next PC of each thread. */
Addr nextPC[Impl::MaxThreads];
#if THE_ISA != ALPHA_ISA
/** The next NPC of each thread. */
Addr nextNPC[Impl::MaxThreads];
#endif
/** The sequence number of the youngest valid instruction in the ROB. */
InstSeqNum youngestSeqNum[Impl::MaxThreads];

View File

@@ -28,16 +28,22 @@
* Authors: Kevin Lim
*/
#include "config/full_system.hh"
#include "config/use_checker.hh"
#include <algorithm>
#include <string>
#include "base/loader/symtab.hh"
#include "base/timebuf.hh"
#include "cpu/checker/cpu.hh"
#include "cpu/exetrace.hh"
#include "cpu/o3/commit.hh"
#include "cpu/o3/thread_state.hh"
#if USE_CHECKER
#include "cpu/checker/cpu.hh"
#endif
using namespace std;
template <class Impl>
@@ -72,13 +78,11 @@ DefaultCommit<Impl>::DefaultCommit(Params *params)
renameToROBDelay(params->renameToROBDelay),
fetchToCommitDelay(params->commitToFetchDelay),
renameWidth(params->renameWidth),
iewWidth(params->executeWidth),
commitWidth(params->commitWidth),
numThreads(params->numberOfThreads),
switchPending(false),
drainPending(false),
switchedOut(false),
trapLatency(params->trapLatency),
fetchTrapLatency(params->fetchTrapLatency)
trapLatency(params->trapLatency)
{
_status = Active;
_nextStatus = Inactive;
@@ -118,9 +122,6 @@ DefaultCommit<Impl>::DefaultCommit(Params *params)
tcSquash[i] = false;
PC[i] = nextPC[i] = 0;
}
fetchFaultTick = 0;
fetchTrapWait = 0;
}
template <class Impl>
@@ -205,19 +206,6 @@ DefaultCommit<Impl>::regStats()
.flags(total)
;
//
// Commit-Eligible instructions...
//
// -> The number of instructions eligible to commit in those
// cycles where we reached our commit BW limit (less the number
// actually committed)
//
// -> The average value is computed over ALL CYCLES... not just
// the BW limited cycles
//
// -> The standard deviation is computed only over cycles where
// we reached the BW limit
//
commitEligible
.init(cpu->number_of_threads)
.name(name() + ".COM:bw_limited")
@@ -233,17 +221,16 @@ DefaultCommit<Impl>::regStats()
template <class Impl>
void
DefaultCommit<Impl>::setCPU(FullCPU *cpu_ptr)
DefaultCommit<Impl>::setCPU(O3CPU *cpu_ptr)
{
DPRINTF(Commit, "Commit: Setting CPU pointer.\n");
cpu = cpu_ptr;
// Commit must broadcast the number of free entries it has at the start of
// the simulation, so it starts as active.
cpu->activateStage(FullCPU::CommitIdx);
cpu->activateStage(O3CPU::CommitIdx);
trapLatency = cpu->cycles(trapLatency);
fetchTrapLatency = cpu->cycles(fetchTrapLatency);
}
template <class Impl>
@@ -300,13 +287,6 @@ DefaultCommit<Impl>::setIEWQueue(TimeBuffer<IEWStruct> *iq_ptr)
fromIEW = iewQueue->getWire(-iewToCommitDelay);
}
template <class Impl>
void
DefaultCommit<Impl>::setFetchStage(Fetch *fetch_stage)
{
fetchStage = fetch_stage;
}
template <class Impl>
void
DefaultCommit<Impl>::setIEWStage(IEW *iew_stage)
@@ -358,21 +338,36 @@ DefaultCommit<Impl>::initStage()
}
template <class Impl>
void
DefaultCommit<Impl>::switchOut()
bool
DefaultCommit<Impl>::drain()
{
switchPending = true;
drainPending = true;
// If it's already drained, return true.
if (rob->isEmpty() && !iewStage->hasStoresToWB()) {
cpu->signalDrained();
return true;
}
return false;
}
template <class Impl>
void
DefaultCommit<Impl>::doSwitchOut()
DefaultCommit<Impl>::switchOut()
{
switchedOut = true;
switchPending = false;
drainPending = false;
rob->switchOut();
}
template <class Impl>
void
DefaultCommit<Impl>::resume()
{
drainPending = false;
}
template <class Impl>
void
DefaultCommit<Impl>::takeOverFrom()
@@ -409,10 +404,10 @@ DefaultCommit<Impl>::updateStatus()
if (_nextStatus == Inactive && _status == Active) {
DPRINTF(Activity, "Deactivating stage.\n");
cpu->deactivateStage(FullCPU::CommitIdx);
cpu->deactivateStage(O3CPU::CommitIdx);
} else if (_nextStatus == Active && _status == Inactive) {
DPRINTF(Activity, "Activating stage.\n");
cpu->activateStage(FullCPU::CommitIdx);
cpu->activateStage(O3CPU::CommitIdx);
}
_status = _nextStatus;
@@ -434,7 +429,7 @@ DefaultCommit<Impl>::setNextStatus()
}
}
assert(squashes == squashCounter);
squashCounter = squashes;
// If commit is currently squashing, then it will have activity for the
// next cycle. Set its next status as active.
@@ -539,8 +534,6 @@ DefaultCommit<Impl>::squashFromTrap(unsigned tid)
commitStatus[tid] = ROBSquashing;
cpu->activityThisCycle();
++squashCounter;
}
template <class Impl>
@@ -558,8 +551,6 @@ DefaultCommit<Impl>::squashFromTC(unsigned tid)
cpu->activityThisCycle();
tcSquash[tid] = false;
++squashCounter;
}
template <class Impl>
@@ -569,11 +560,15 @@ DefaultCommit<Impl>::tick()
wroteToTimeBuffer = false;
_nextStatus = Inactive;
if (switchPending && rob->isEmpty() && !iewStage->hasStoresToWB()) {
cpu->signalSwitched();
if (drainPending && rob->isEmpty() && !iewStage->hasStoresToWB()) {
cpu->signalDrained();
drainPending = false;
return;
}
if ((*activeThreads).size() <= 0)
return;
list<unsigned>::iterator threads = (*activeThreads).begin();
// Check if any of the threads are done squashing. Change the
@@ -585,10 +580,12 @@ DefaultCommit<Impl>::tick()
if (rob->isDoneSquashing(tid)) {
commitStatus[tid] = Running;
--squashCounter;
} else {
DPRINTF(Commit,"[tid:%u]: Still Squashing, cannot commit any"
"insts this cycle.\n", tid);
" insts this cycle.\n", tid);
rob->doSquash(tid);
toIEW->commitInfo[tid].robSquashing = true;
wroteToTimeBuffer = true;
}
}
}
@@ -694,29 +691,7 @@ DefaultCommit<Impl>::commit()
while (threads != (*activeThreads).end()) {
unsigned tid = *threads++;
/*
if (fromFetch->fetchFault && commitStatus[0] != TrapPending) {
// Record the fault. Wait until it's empty in the ROB.
// Then handle the trap. Ignore it if there's already a
// trap pending as fetch will be redirected.
fetchFault = fromFetch->fetchFault;
fetchFaultTick = curTick + fetchTrapLatency;
commitStatus[0] = FetchTrapPending;
DPRINTF(Commit, "Fault from fetch recorded. Will trap if the "
"ROB empties without squashing the fault.\n");
fetchTrapWait = 0;
}
// Fetch may tell commit to clear the trap if it's been squashed.
if (fromFetch->clearFetchFault) {
DPRINTF(Commit, "Received clear fetch fault signal\n");
fetchTrapWait = 0;
if (commitStatus[0] == FetchTrapPending) {
DPRINTF(Commit, "Clearing fault from fetch\n");
commitStatus[0] = Running;
}
}
*/
// Not sure which one takes priority. I think if we have
// both, that's a bad sign.
if (trapSquash[tid] == true) {
@@ -744,8 +719,6 @@ DefaultCommit<Impl>::commit()
commitStatus[tid] = ROBSquashing;
++squashCounter;
// If we want to include the squashing instruction in the squash,
// then use one older sequence number.
InstSeqNum squashed_inst = fromIEW->squashedSeqNum[tid];
@@ -947,7 +920,7 @@ DefaultCommit<Impl>::commitHead(DynInstPtr &head_inst, unsigned inst_num)
// and committed this instruction.
thread[tid]->funcExeInst--;
head_inst->reachedCommit = true;
head_inst->setAtCommit();
if (head_inst->isNonSpeculative() ||
head_inst->isStoreConditional() ||
@@ -1012,18 +985,19 @@ DefaultCommit<Impl>::commitHead(DynInstPtr &head_inst, unsigned inst_num)
head_inst->setCompleted();
}
#if USE_CHECKER
// Use checker prior to updating anything due to traps or PC
// based events.
if (cpu->checker) {
cpu->checker->tick(head_inst);
cpu->checker->verify(head_inst);
}
#endif
// Check if the instruction caused a fault. If so, trap.
Fault inst_fault = head_inst->getFault();
if (inst_fault != NoFault) {
head_inst->setCompleted();
#if FULL_SYSTEM
DPRINTF(Commit, "Inst [sn:%lli] PC %#x has a fault\n",
head_inst->seqNum, head_inst->readPC());
@@ -1032,9 +1006,11 @@ DefaultCommit<Impl>::commitHead(DynInstPtr &head_inst, unsigned inst_num)
return false;
}
#if USE_CHECKER
if (cpu->checker && head_inst->isStore()) {
cpu->checker->tick(head_inst);
cpu->checker->verify(head_inst);
}
#endif
assert(!thread[tid]->inSyscall);
@@ -1065,10 +1041,6 @@ DefaultCommit<Impl>::commitHead(DynInstPtr &head_inst, unsigned inst_num)
generateTrapEvent(tid);
return false;
#else // !FULL_SYSTEM
panic("fault (%d) detected @ PC %08p", inst_fault,
head_inst->PC);
#endif // FULL_SYSTEM
}
updateComInstStats(head_inst);
@@ -1256,7 +1228,8 @@ DefaultCommit<Impl>::roundRobin()
unsigned tid = *pri_iter;
if (commitStatus[tid] == Running ||
commitStatus[tid] == Idle) {
commitStatus[tid] == Idle ||
commitStatus[tid] == FetchTrapPending) {
if (rob->isHeadReady(tid)) {
priority_list.erase(pri_iter);

View File

@@ -26,9 +26,11 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Authors: Kevin Lim
* Korey Sewell
*/
#include "config/full_system.hh"
#include "config/use_checker.hh"
#if FULL_SYSTEM
#include "sim/system.hh"
@@ -37,26 +39,28 @@
#endif
#include "cpu/activity.hh"
#include "cpu/checker/cpu.hh"
#include "cpu/simple_thread.hh"
#include "cpu/thread_context.hh"
#include "cpu/o3/alpha_dyn_inst.hh"
#include "cpu/o3/alpha_impl.hh"
#include "cpu/o3/isa_specific.hh"
#include "cpu/o3/cpu.hh"
#include "sim/root.hh"
#include "sim/stat_control.hh"
#if USE_CHECKER
#include "cpu/checker/cpu.hh"
#endif
using namespace std;
using namespace TheISA;
BaseFullCPU::BaseFullCPU(Params *params)
BaseO3CPU::BaseO3CPU(Params *params)
: BaseCPU(params), cpu_id(0)
{
}
void
BaseFullCPU::regStats()
BaseO3CPU::regStats()
{
BaseCPU::regStats();
}
@@ -81,9 +85,68 @@ FullO3CPU<Impl>::TickEvent::description()
return "FullO3CPU tick event";
}
template <class Impl>
FullO3CPU<Impl>::ActivateThreadEvent::ActivateThreadEvent()
: Event(&mainEventQueue, CPU_Tick_Pri)
{
}
template <class Impl>
void
FullO3CPU<Impl>::ActivateThreadEvent::init(int thread_num,
FullO3CPU<Impl> *thread_cpu)
{
tid = thread_num;
cpu = thread_cpu;
}
template <class Impl>
void
FullO3CPU<Impl>::ActivateThreadEvent::process()
{
cpu->activateThread(tid);
}
template <class Impl>
const char *
FullO3CPU<Impl>::ActivateThreadEvent::description()
{
return "FullO3CPU \"Activate Thread\" event";
}
template <class Impl>
FullO3CPU<Impl>::DeallocateContextEvent::DeallocateContextEvent()
: Event(&mainEventQueue, CPU_Tick_Pri)
{
}
template <class Impl>
void
FullO3CPU<Impl>::DeallocateContextEvent::init(int thread_num,
FullO3CPU<Impl> *thread_cpu)
{
tid = thread_num;
cpu = thread_cpu;
}
template <class Impl>
void
FullO3CPU<Impl>::DeallocateContextEvent::process()
{
cpu->deactivateThread(tid);
cpu->removeThread(tid);
}
template <class Impl>
const char *
FullO3CPU<Impl>::DeallocateContextEvent::description()
{
return "FullO3CPU \"Deallocate Context\" event";
}
template <class Impl>
FullO3CPU<Impl>::FullO3CPU(Params *params)
: BaseFullCPU(params),
: BaseO3CPU(params),
tickEvent(this),
removeInstsThisCycle(false),
fetch(params),
@@ -94,7 +157,7 @@ FullO3CPU<Impl>::FullO3CPU(Params *params)
regFile(params->numPhysIntRegs, params->numPhysFloatRegs),
freeList(params->numberOfThreads,//number of activeThreads
freeList(params->numberOfThreads,
TheISA::NumIntRegs, params->numPhysIntRegs,
TheISA::NumFloatRegs, params->numPhysFloatRegs),
@@ -102,21 +165,20 @@ FullO3CPU<Impl>::FullO3CPU(Params *params)
params->smtROBPolicy, params->smtROBThreshold,
params->numberOfThreads),
scoreboard(params->numberOfThreads,//number of activeThreads
scoreboard(params->numberOfThreads,
TheISA::NumIntRegs, params->numPhysIntRegs,
TheISA::NumFloatRegs, params->numPhysFloatRegs,
TheISA::NumMiscRegs * number_of_threads,
TheISA::ZeroReg),
// For now just have these time buffers be pretty big.
// @todo: Make these time buffer sizes parameters or derived
// from latencies
timeBuffer(5, 5),
fetchQueue(5, 5),
decodeQueue(5, 5),
renameQueue(5, 5),
iewQueue(5, 5),
activityRec(NumStages, 10, params->activity),
timeBuffer(params->backComSize, params->forwardComSize),
fetchQueue(params->backComSize, params->forwardComSize),
decodeQueue(params->backComSize, params->forwardComSize),
renameQueue(params->backComSize, params->forwardComSize),
iewQueue(params->backComSize, params->forwardComSize),
activityRec(NumStages,
params->backComSize + params->forwardComSize,
params->activity),
globalSeqNum(1),
@@ -125,21 +187,25 @@ FullO3CPU<Impl>::FullO3CPU(Params *params)
physmem(system->physmem),
#endif // FULL_SYSTEM
mem(params->mem),
switchCount(0),
drainCount(0),
deferRegistration(params->deferRegistration),
numThreads(number_of_threads)
{
_status = Idle;
checker = NULL;
if (params->checker) {
#if USE_CHECKER
BaseCPU *temp_checker = params->checker;
checker = dynamic_cast<Checker<DynInstPtr> *>(temp_checker);
checker->setMemory(mem);
#if FULL_SYSTEM
checker->setSystem(params->system);
#endif
} else {
checker = NULL;
#else
panic("Checker enabled but not compiled in!");
#endif // USE_CHECKER
}
#if !FULL_SYSTEM
@@ -177,13 +243,18 @@ FullO3CPU<Impl>::FullO3CPU(Params *params)
commit.setIEWQueue(&iewQueue);
commit.setRenameQueue(&renameQueue);
commit.setFetchStage(&fetch);
commit.setIEWStage(&iew);
rename.setIEWStage(&iew);
rename.setCommitStage(&commit);
#if !FULL_SYSTEM
int active_threads = params->workload.size();
if (active_threads > Impl::MaxThreads) {
panic("Workload Size too large. Increase the 'MaxThreads'"
"constant in your O3CPU impl. file (e.g. o3/alpha/impl.hh) or "
"edit your workload size.");
}
#else
int active_threads = 1;
#endif
@@ -249,6 +320,8 @@ FullO3CPU<Impl>::FullO3CPU(Params *params)
lastRunningCycle = curTick;
lastActivatedCycle = -1;
contextSwitch = false;
}
@@ -261,9 +334,9 @@ template <class Impl>
void
FullO3CPU<Impl>::fullCPURegStats()
{
BaseFullCPU::regStats();
BaseO3CPU::regStats();
// Register any of the FullCPU's stats here.
// Register any of the O3CPU's stats here.
timesIdled
.name(name() + ".timesIdled")
.desc("Number of times that the entire CPU went into an idle state and"
@@ -315,11 +388,23 @@ FullO3CPU<Impl>::fullCPURegStats()
}
template <class Impl>
Port *
FullO3CPU<Impl>::getPort(const std::string &if_name, int idx)
{
if (if_name == "dcache_port")
return iew.getDcachePort();
else if (if_name == "icache_port")
return fetch.getIcachePort();
else
panic("No Such Port\n");
}
template <class Impl>
void
FullO3CPU<Impl>::tick()
{
DPRINTF(FullCPU, "\n\nFullCPU: Ticking main, FullO3CPU.\n");
DPRINTF(O3CPU, "\n\nFullO3CPU: Ticking main, FullO3CPU.\n");
++numCycles;
@@ -355,7 +440,8 @@ FullO3CPU<Impl>::tick()
}
if (!tickEvent.scheduled()) {
if (_status == SwitchedOut) {
if (_status == SwitchedOut ||
getState() == SimObject::Drained) {
// increment stat
lastRunningCycle = curTick;
} else if (!activityRec.active()) {
@@ -414,18 +500,109 @@ FullO3CPU<Impl>::init()
commit.setThreads(thread);
}
template <class Impl>
void
FullO3CPU<Impl>::activateThread(unsigned tid)
{
list<unsigned>::iterator isActive = find(
activeThreads.begin(), activeThreads.end(), tid);
if (isActive == activeThreads.end()) {
DPRINTF(O3CPU, "[tid:%i]: Adding to active threads list\n",
tid);
activeThreads.push_back(tid);
}
}
template <class Impl>
void
FullO3CPU<Impl>::deactivateThread(unsigned tid)
{
//Remove From Active List, if Active
list<unsigned>::iterator thread_it =
find(activeThreads.begin(), activeThreads.end(), tid);
if (thread_it != activeThreads.end()) {
DPRINTF(O3CPU,"[tid:%i]: Removing from active threads list\n",
tid);
activeThreads.erase(thread_it);
}
}
template <class Impl>
void
FullO3CPU<Impl>::activateContext(int tid, int delay)
{
// Needs to set each stage to running as well.
if (delay){
DPRINTF(O3CPU, "[tid:%i]: Scheduling thread context to activate "
"on cycle %d\n", tid, curTick + cycles(delay));
scheduleActivateThreadEvent(tid, delay);
} else {
activateThread(tid);
}
if(lastActivatedCycle < curTick) {
scheduleTickEvent(delay);
// Be sure to signal that there's some activity so the CPU doesn't
// deschedule itself.
activityRec.activity();
fetch.wakeFromQuiesce();
lastActivatedCycle = curTick;
_status = Running;
}
}
template <class Impl>
void
FullO3CPU<Impl>::deallocateContext(int tid, int delay)
{
// Schedule removal of thread data from CPU
if (delay){
DPRINTF(O3CPU, "[tid:%i]: Scheduling thread context to deallocate "
"on cycle %d\n", tid, curTick + cycles(delay));
scheduleDeallocateContextEvent(tid, delay);
} else {
deactivateThread(tid);
removeThread(tid);
}
}
template <class Impl>
void
FullO3CPU<Impl>::suspendContext(int tid)
{
DPRINTF(O3CPU,"[tid: %i]: Suspending Thread Context.\n", tid);
deactivateThread(tid);
if (activeThreads.size() == 0)
unscheduleTickEvent();
_status = Idle;
}
template <class Impl>
void
FullO3CPU<Impl>::haltContext(int tid)
{
//For now, this is the same as deallocate
DPRINTF(O3CPU,"[tid:%i]: Halt Context called. Deallocating", tid);
deallocateContext(tid, 1);
}
template <class Impl>
void
FullO3CPU<Impl>::insertThread(unsigned tid)
{
DPRINTF(FullCPU,"[tid:%i] Initializing thread data");
DPRINTF(O3CPU,"[tid:%i] Initializing thread into CPU");
// Will change now that the PC and thread state is internal to the CPU
// and not in the ThreadContext.
#if 0
#if FULL_SYSTEM
ThreadContext *src_tc = system->threadContexts[tid];
#else
ThreadContext *src_tc = thread[tid];
ThreadContext *src_tc = tcBase(tid);
#endif
//Bind Int Regs to Rename Map
@@ -445,11 +622,14 @@ FullO3CPU<Impl>::insertThread(unsigned tid)
}
//Copy Thread Data Into RegFile
this->copyFromTC(tid);
//this->copyFromTC(tid);
//Set PC/NPC
regFile.pc[tid] = src_tc->readPC();
regFile.npc[tid] = src_tc->readNextPC();
//Set PC/NPC/NNPC
setPC(src_tc->readPC(), tid);
setNextPC(src_tc->readNextPC(), tid);
#if THE_ISA != ALPHA_ISA
setNextNPC(src_tc->readNextNPC(), tid);
#endif
src_tc->setStatus(ThreadContext::Active);
@@ -458,16 +638,19 @@ FullO3CPU<Impl>::insertThread(unsigned tid)
//Reset ROB/IQ/LSQ Entries
commit.rob->resetEntries();
iew.resetEntries();
#endif
}
template <class Impl>
void
FullO3CPU<Impl>::removeThread(unsigned tid)
{
DPRINTF(FullCPU,"[tid:%i] Removing thread data");
#if 0
//Unbind Int Regs from Rename Map
DPRINTF(O3CPU,"[tid:%i] Removing thread context from CPU.\n", tid);
// Copy Thread Data From RegFile
// If thread is suspended, it might be re-allocated
//this->copyToTC(tid);
// Unbind Int Regs from Rename Map
for (int ireg = 0; ireg < TheISA::NumIntRegs; ireg++) {
PhysRegIndex phys_reg = renameMap[tid].lookup(ireg);
@@ -475,7 +658,7 @@ FullO3CPU<Impl>::removeThread(unsigned tid)
freeList.addReg(phys_reg);
}
//Unbind Float Regs from Rename Map
// Unbind Float Regs from Rename Map
for (int freg = 0; freg < TheISA::NumFloatRegs; freg++) {
PhysRegIndex phys_reg = renameMap[tid].lookup(freg);
@@ -483,27 +666,20 @@ FullO3CPU<Impl>::removeThread(unsigned tid)
freeList.addReg(phys_reg);
}
//Copy Thread Data From RegFile
/* Fix Me:
* Do we really need to do this if we are removing a thread
* in the sense that it's finished (exiting)? If the thread is just
* being suspended we might...
*/
// this->copyToTC(tid);
//Squash Throughout Pipeline
// Squash Throughout Pipeline
fetch.squash(0,tid);
decode.squash(tid);
rename.squash(tid);
iew.squash(tid);
commit.rob->squash(commit.rob->readHeadInst(tid)->seqNum, tid);
assert(iew.ldstQueue.getCount(tid) == 0);
//Reset ROB/IQ/LSQ Entries
// Reset ROB/IQ/LSQ Entries
if (activeThreads.size() >= 1) {
commit.rob->resetEntries();
iew.resetEntries();
}
#endif
}
@@ -511,37 +687,37 @@ template <class Impl>
void
FullO3CPU<Impl>::activateWhenReady(int tid)
{
DPRINTF(FullCPU,"[tid:%i]: Checking if resources are available for incoming"
DPRINTF(O3CPU,"[tid:%i]: Checking if resources are available for incoming"
"(e.g. PhysRegs/ROB/IQ/LSQ) \n",
tid);
bool ready = true;
if (freeList.numFreeIntRegs() >= TheISA::NumIntRegs) {
DPRINTF(FullCPU,"[tid:%i] Suspending thread due to not enough "
DPRINTF(O3CPU,"[tid:%i] Suspending thread due to not enough "
"Phys. Int. Regs.\n",
tid);
ready = false;
} else if (freeList.numFreeFloatRegs() >= TheISA::NumFloatRegs) {
DPRINTF(FullCPU,"[tid:%i] Suspending thread due to not enough "
DPRINTF(O3CPU,"[tid:%i] Suspending thread due to not enough "
"Phys. Float. Regs.\n",
tid);
ready = false;
} else if (commit.rob->numFreeEntries() >=
commit.rob->entryAmount(activeThreads.size() + 1)) {
DPRINTF(FullCPU,"[tid:%i] Suspending thread due to not enough "
DPRINTF(O3CPU,"[tid:%i] Suspending thread due to not enough "
"ROB entries.\n",
tid);
ready = false;
} else if (iew.instQueue.numFreeEntries() >=
iew.instQueue.entryAmount(activeThreads.size() + 1)) {
DPRINTF(FullCPU,"[tid:%i] Suspending thread due to not enough "
DPRINTF(O3CPU,"[tid:%i] Suspending thread due to not enough "
"IQ entries.\n",
tid);
ready = false;
} else if (iew.ldstQueue.numFreeEntries() >=
iew.ldstQueue.entryAmount(activeThreads.size() + 1)) {
DPRINTF(FullCPU,"[tid:%i] Suspending thread due to not enough "
DPRINTF(O3CPU,"[tid:%i] Suspending thread due to not enough "
"LSQ entries.\n",
tid);
ready = false;
@@ -559,6 +735,7 @@ FullO3CPU<Impl>::activateWhenReady(int tid)
//blocks fetch
contextSwitch = true;
//@todo: dont always add to waitlist
//do waitlist
cpuWaitList.push_back(tid);
}
@@ -566,133 +743,130 @@ FullO3CPU<Impl>::activateWhenReady(int tid)
template <class Impl>
void
FullO3CPU<Impl>::activateContext(int tid, int delay)
FullO3CPU<Impl>::serialize(std::ostream &os)
{
// Needs to set each stage to running as well.
list<unsigned>::iterator isActive = find(
activeThreads.begin(), activeThreads.end(), tid);
SERIALIZE_ENUM(_status);
BaseCPU::serialize(os);
nameOut(os, csprintf("%s.tickEvent", name()));
tickEvent.serialize(os);
if (isActive == activeThreads.end()) {
//May Need to Re-code this if the delay variable is the
//delay needed for thread to activate
DPRINTF(FullCPU, "Adding Thread %i to active threads list\n",
tid);
// Use SimpleThread's ability to checkpoint to make it easier to
// write out the registers. Also make this static so it doesn't
// get instantiated multiple times (causes a panic in statistics).
static SimpleThread temp;
activeThreads.push_back(tid);
for (int i = 0; i < thread.size(); i++) {
nameOut(os, csprintf("%s.xc.%i", name(), i));
temp.copyTC(thread[i]->getTC());
temp.serialize(os);
}
}
assert(_status == Idle || _status == SwitchedOut);
template <class Impl>
void
FullO3CPU<Impl>::unserialize(Checkpoint *cp, const std::string &section)
{
UNSERIALIZE_ENUM(_status);
BaseCPU::unserialize(cp, section);
tickEvent.unserialize(cp, csprintf("%s.tickEvent", section));
scheduleTickEvent(delay);
// Use SimpleThread's ability to checkpoint to make it easier to
// read in the registers. Also make this static so it doesn't
// get instantiated multiple times (causes a panic in statistics).
static SimpleThread temp;
// Be sure to signal that there's some activity so the CPU doesn't
// deschedule itself.
activityRec.activity();
fetch.wakeFromQuiesce();
for (int i = 0; i < thread.size(); i++) {
temp.copyTC(thread[i]->getTC());
temp.unserialize(cp, csprintf("%s.xc.%i", section, i));
thread[i]->getTC()->copyArchRegs(temp.getTC());
}
}
template <class Impl>
unsigned int
FullO3CPU<Impl>::drain(Event *drain_event)
{
drainCount = 0;
fetch.drain();
decode.drain();
rename.drain();
iew.drain();
commit.drain();
// Wake the CPU and record activity so everything can drain out if
// the CPU was not able to immediately drain.
if (getState() != SimObject::Drained) {
// A bit of a hack...set the drainEvent after all the drain()
// calls have been made, that way if all of the stages drain
// immediately, the signalDrained() function knows not to call
// process on the drain event.
drainEvent = drain_event;
wakeCPU();
activityRec.activity();
return 1;
} else {
return 0;
}
}
template <class Impl>
void
FullO3CPU<Impl>::resume()
{
assert(system->getMemoryMode() == System::Timing);
fetch.resume();
decode.resume();
rename.resume();
iew.resume();
commit.resume();
changeState(SimObject::Running);
if (_status == SwitchedOut || _status == Idle)
return;
if (!tickEvent.scheduled())
tickEvent.schedule(curTick);
_status = Running;
}
template <class Impl>
void
FullO3CPU<Impl>::suspendContext(int tid)
FullO3CPU<Impl>::signalDrained()
{
DPRINTF(FullCPU,"[tid: %i]: Suspended ...\n", tid);
unscheduleTickEvent();
_status = Idle;
/*
//Remove From Active List, if Active
list<unsigned>::iterator isActive = find(
activeThreads.begin(), activeThreads.end(), tid);
if (isActive != activeThreads.end()) {
DPRINTF(FullCPU,"[tid:%i]: Removing from active threads list\n",
tid);
activeThreads.erase(isActive);
}
*/
}
template <class Impl>
void
FullO3CPU<Impl>::deallocateContext(int tid)
{
DPRINTF(FullCPU,"[tid:%i]: Deallocating ...", tid);
/*
//Remove From Active List, if Active
list<unsigned>::iterator isActive = find(
activeThreads.begin(), activeThreads.end(), tid);
if (isActive != activeThreads.end()) {
DPRINTF(FullCPU,"[tid:%i]: Removing from active threads list\n",
tid);
activeThreads.erase(isActive);
removeThread(tid);
}
*/
}
template <class Impl>
void
FullO3CPU<Impl>::haltContext(int tid)
{
DPRINTF(FullCPU,"[tid:%i]: Halted ...", tid);
/*
//Remove From Active List, if Active
list<unsigned>::iterator isActive = find(
activeThreads.begin(), activeThreads.end(), tid);
if (isActive != activeThreads.end()) {
DPRINTF(FullCPU,"[tid:%i]: Removing from active threads list\n",
tid);
activeThreads.erase(isActive);
removeThread(tid);
}
*/
}
template <class Impl>
void
FullO3CPU<Impl>::switchOut(Sampler *_sampler)
{
sampler = _sampler;
switchCount = 0;
fetch.switchOut();
decode.switchOut();
rename.switchOut();
iew.switchOut();
commit.switchOut();
// Wake the CPU and record activity so everything can drain out if
// the CPU is currently idle.
wakeCPU();
activityRec.activity();
}
template <class Impl>
void
FullO3CPU<Impl>::signalSwitched()
{
if (++switchCount == NumStages) {
fetch.doSwitchOut();
rename.doSwitchOut();
commit.doSwitchOut();
instList.clear();
while (!removeList.empty()) {
removeList.pop();
}
if (checker)
checker->switchOut(sampler);
if (++drainCount == NumStages) {
if (tickEvent.scheduled())
tickEvent.squash();
sampler->signalSwitched();
_status = SwitchedOut;
changeState(SimObject::Drained);
if (drainEvent) {
drainEvent->process();
drainEvent = NULL;
}
}
assert(switchCount <= 5);
assert(drainCount <= 5);
}
template <class Impl>
void
FullO3CPU<Impl>::switchOut()
{
fetch.switchOut();
rename.switchOut();
commit.switchOut();
instList.clear();
while (!removeList.empty()) {
removeList.pop();
}
_status = SwitchedOut;
#if USE_CHECKER
if (checker)
checker->switchOut();
#endif
}
template <class Impl>
@@ -700,7 +874,7 @@ void
FullO3CPU<Impl>::takeOverFrom(BaseCPU *oldCPU)
{
// Flush out any old data from the time buffers.
for (int i = 0; i < 10; ++i) {
for (int i = 0; i < timeBuffer.getSize(); ++i) {
timeBuffer.advance();
fetchQueue.advance();
decodeQueue.advance();
@@ -730,7 +904,7 @@ FullO3CPU<Impl>::takeOverFrom(BaseCPU *oldCPU)
if (isActive == activeThreads.end()) {
//May Need to Re-code this if the delay variable is the delay
//needed for thread to activate
DPRINTF(FullCPU, "Adding Thread %i to active threads list\n",
DPRINTF(O3CPU, "Adding Thread %i to active threads list\n",
tid);
activeThreads.push_back(tid);
@@ -922,6 +1096,22 @@ FullO3CPU<Impl>::setNextPC(uint64_t val,unsigned tid)
commit.setNextPC(val, tid);
}
#if THE_ISA != ALPHA_ISA
template <class Impl>
uint64_t
FullO3CPU<Impl>::readNextNPC(unsigned tid)
{
return commit.readNextNPC(tid);
}
template <class Impl>
void
FullO3CPU<Impl>::setNextNNPC(uint64_t val,unsigned tid)
{
commit.setNextNPC(val, tid);
}
#endif
template <class Impl>
typename FullO3CPU<Impl>::ListIt
FullO3CPU<Impl>::addInst(DynInstPtr &inst)
@@ -958,7 +1148,7 @@ template <class Impl>
void
FullO3CPU<Impl>::removeFrontInst(DynInstPtr &inst)
{
DPRINTF(FullCPU, "FullCPU: Removing committed instruction [tid:%i] PC %#x "
DPRINTF(O3CPU, "Removing committed instruction [tid:%i] PC %#x "
"[sn:%lli]\n",
inst->threadNumber, inst->readPC(), inst->seqNum);
@@ -972,7 +1162,7 @@ template <class Impl>
void
FullO3CPU<Impl>::removeInstsNotInROB(unsigned tid)
{
DPRINTF(FullCPU, "FullCPU: Thread %i: Deleting instructions from instruction"
DPRINTF(O3CPU, "Thread %i: Deleting instructions from instruction"
" list.\n", tid);
ListIt end_it;
@@ -982,12 +1172,12 @@ FullO3CPU<Impl>::removeInstsNotInROB(unsigned tid)
if (instList.empty()) {
return;
} else if (rob.isEmpty(/*tid*/)) {
DPRINTF(FullCPU, "FullCPU: ROB is empty, squashing all insts.\n");
DPRINTF(O3CPU, "ROB is empty, squashing all insts.\n");
end_it = instList.begin();
rob_empty = true;
} else {
end_it = (rob.readTailInst(tid))->getInstListIt();
DPRINTF(FullCPU, "FullCPU: ROB is not empty, squashing insts not in ROB.\n");
DPRINTF(O3CPU, "ROB is not empty, squashing insts not in ROB.\n");
}
removeInstsThisCycle = true;
@@ -1026,7 +1216,7 @@ FullO3CPU<Impl>::removeInstsUntil(const InstSeqNum &seq_num,
inst_iter--;
DPRINTF(FullCPU, "FullCPU: Deleting instructions from instruction "
DPRINTF(O3CPU, "Deleting instructions from instruction "
"list that are from [tid:%i] and above [sn:%lli] (end=%lli).\n",
tid, seq_num, (*inst_iter)->seqNum);
@@ -1048,7 +1238,7 @@ inline void
FullO3CPU<Impl>::squashInstIt(const ListIt &instIt, const unsigned &tid)
{
if ((*instIt)->threadNumber == tid) {
DPRINTF(FullCPU, "FullCPU: Squashing instruction, "
DPRINTF(O3CPU, "Squashing instruction, "
"[tid:%i] [sn:%lli] PC %#x\n",
(*instIt)->threadNumber,
(*instIt)->seqNum,
@@ -1069,7 +1259,7 @@ void
FullO3CPU<Impl>::cleanUpRemovedInsts()
{
while (!removeList.empty()) {
DPRINTF(FullCPU, "FullCPU: Removing instruction, "
DPRINTF(O3CPU, "Removing instruction, "
"[tid:%i] [sn:%lli] PC %#x\n",
(*removeList.front())->threadNumber,
(*removeList.front())->seqNum,
@@ -1185,4 +1375,4 @@ FullO3CPU<Impl>::updateThreadPriority()
}
// Forward declaration of FullO3CPU.
template class FullO3CPU<AlphaSimpleImpl>;
template class FullO3CPU<O3CPUImpl>;

View File

@@ -26,6 +26,7 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Authors: Kevin Lim
* Korey Sewell
*/
#ifndef __CPU_O3_CPU_HH__
@@ -48,24 +49,33 @@
#include "cpu/o3/cpu_policy.hh"
#include "cpu/o3/scoreboard.hh"
#include "cpu/o3/thread_state.hh"
//#include "cpu/o3/thread_context.hh"
#include "sim/process.hh"
template <class>
class Checker;
class ThreadContext;
template <class>
class O3ThreadContext;
class Checkpoint;
class MemObject;
class Process;
class BaseFullCPU : public BaseCPU
class BaseO3CPU : public BaseCPU
{
//Stuff that's pretty ISA independent will go here.
public:
typedef BaseCPU::Params Params;
BaseFullCPU(Params *params);
BaseO3CPU(Params *params);
void regStats();
/** Sets this CPU's ID. */
void setCpuId(int id) { cpu_id = id; }
/** Reads this CPU's ID. */
int readCpuId() { return cpu_id; }
protected:
@@ -78,7 +88,7 @@ class BaseFullCPU : public BaseCPU
* tick() function for the CPU is defined here.
*/
template <class Impl>
class FullO3CPU : public BaseFullCPU
class FullO3CPU : public BaseO3CPU
{
public:
typedef TheISA::FloatReg FloatReg;
@@ -93,6 +103,8 @@ class FullO3CPU : public BaseFullCPU
typedef typename std::list<DynInstPtr>::iterator ListIt;
friend class O3ThreadContext<Impl>;
public:
enum Status {
Running,
@@ -105,6 +117,9 @@ class FullO3CPU : public BaseFullCPU
/** Overall CPU status. */
Status _status;
/** Per-thread status in CPU, used for SMT. */
Status _threadStatus[Impl::MaxThreads];
private:
class TickEvent : public Event
{
@@ -141,6 +156,92 @@ class FullO3CPU : public BaseFullCPU
tickEvent.squash();
}
class ActivateThreadEvent : public Event
{
private:
/** Number of Thread to Activate */
int tid;
/** Pointer to the CPU. */
FullO3CPU<Impl> *cpu;
public:
/** Constructs the event. */
ActivateThreadEvent();
/** Initialize Event */
void init(int thread_num, FullO3CPU<Impl> *thread_cpu);
/** Processes the event, calling activateThread() on the CPU. */
void process();
/** Returns the description of the event. */
const char *description();
};
/** Schedule thread to activate , regardless of its current state. */
void scheduleActivateThreadEvent(int tid, int delay)
{
// Schedule thread to activate, regardless of its current state.
if (activateThreadEvent[tid].squashed())
activateThreadEvent[tid].reschedule(curTick + cycles(delay));
else if (!activateThreadEvent[tid].scheduled())
activateThreadEvent[tid].schedule(curTick + cycles(delay));
}
/** Unschedule actiavte thread event, regardless of its current state. */
void unscheduleActivateThreadEvent(int tid)
{
if (activateThreadEvent[tid].scheduled())
activateThreadEvent[tid].squash();
}
/** The tick event used for scheduling CPU ticks. */
ActivateThreadEvent activateThreadEvent[Impl::MaxThreads];
class DeallocateContextEvent : public Event
{
private:
/** Number of Thread to Activate */
int tid;
/** Pointer to the CPU. */
FullO3CPU<Impl> *cpu;
public:
/** Constructs the event. */
DeallocateContextEvent();
/** Initialize Event */
void init(int thread_num, FullO3CPU<Impl> *thread_cpu);
/** Processes the event, calling activateThread() on the CPU. */
void process();
/** Returns the description of the event. */
const char *description();
};
/** Schedule cpu to deallocate thread context.*/
void scheduleDeallocateContextEvent(int tid, int delay)
{
// Schedule thread to activate, regardless of its current state.
if (deallocateContextEvent[tid].squashed())
deallocateContextEvent[tid].reschedule(curTick + cycles(delay));
else if (!deallocateContextEvent[tid].scheduled())
deallocateContextEvent[tid].schedule(curTick + cycles(delay));
}
/** Unschedule thread deallocation in CPU */
void unscheduleDeallocateContextEvent(int tid)
{
if (deallocateContextEvent[tid].scheduled())
deallocateContextEvent[tid].squash();
}
/** The tick event used for scheduling CPU ticks. */
DeallocateContextEvent deallocateContextEvent[Impl::MaxThreads];
public:
/** Constructs a CPU with the given parameters. */
FullO3CPU(Params *params);
@@ -150,6 +251,9 @@ class FullO3CPU : public BaseFullCPU
/** Registers statistics. */
void fullCPURegStats();
/** Returns a specific port. */
Port *getPort(const std::string &if_name, int idx);
/** Ticks CPU, calling tick() on each stage, and checking the overall
* activity to see if the CPU should deschedule itself.
*/
@@ -158,6 +262,16 @@ class FullO3CPU : public BaseFullCPU
/** Initialize the CPU */
void init();
/** Returns the Number of Active Threads in the CPU */
int numActiveThreads()
{ return activeThreads.size(); }
/** Add Thread to Active Threads List */
void activateThread(unsigned tid);
/** Remove Thread from Active Threads List */
void deactivateThread(unsigned tid);
/** Setup CPU to insert a thread's context */
void insertThread(unsigned tid);
@@ -184,7 +298,7 @@ class FullO3CPU : public BaseFullCPU
/** Remove Thread from Active Threads List &&
* Remove Thread Context from CPU.
*/
void deallocateContext(int tid);
void deallocateContext(int tid, int delay = 1);
/** Remove Thread from Active Threads List &&
* Remove Thread Context from CPU.
@@ -200,6 +314,13 @@ class FullO3CPU : public BaseFullCPU
/** Update The Order In Which We Process Threads. */
void updateThreadPriority();
/** Serialize state. */
virtual void serialize(std::ostream &os);
/** Unserialize from a checkpoint. */
virtual void unserialize(Checkpoint *cp, const std::string &section);
public:
/** Executes a syscall on this cycle.
* ---------------------------------------
* Note: this is a virtual function. CPU-Specific
@@ -207,14 +328,21 @@ class FullO3CPU : public BaseFullCPU
*/
virtual void syscall(int tid) { panic("Unimplemented!"); }
/** Switches out this CPU. */
void switchOut(Sampler *sampler);
/** Starts draining the CPU's pipeline of all instructions in
* order to stop all memory accesses. */
virtual unsigned int drain(Event *drain_event);
/** Resumes execution after a drain. */
virtual void resume();
/** Signals to this CPU that a stage has completed switching out. */
void signalSwitched();
void signalDrained();
/** Switches out this CPU. */
virtual void switchOut();
/** Takes over from another CPU. */
void takeOverFrom(BaseCPU *oldCPU);
virtual void takeOverFrom(BaseCPU *oldCPU);
/** Get the current instruction sequence number, and increment it. */
InstSeqNum getAndIncrementInstSeq()
@@ -299,6 +427,12 @@ class FullO3CPU : public BaseFullCPU
/** Sets the next PC of a specific thread. */
void setNextPC(uint64_t val, unsigned tid);
/** Reads the next NPC of a specific thread. */
uint64_t readNextNPC(unsigned tid);
/** Sets the next NPC of a specific thread. */
void setNextNPC(uint64_t val, unsigned tid);
/** Function to add instruction onto the head of the list of the
* instructions. Used when new instructions are fetched.
*/
@@ -481,11 +615,11 @@ class FullO3CPU : public BaseFullCPU
/** Pointer to memory. */
MemObject *mem;
/** Pointer to the sampler */
Sampler *sampler;
/** Event to call process() on once draining has completed. */
Event *drainEvent;
/** Counter of how many stages have completed switching out. */
int switchCount;
/** Counter of how many stages have completed draining. */
int drainCount;
/** Pointers to all of the threads in the CPU. */
std::vector<Thread *> thread;
@@ -507,6 +641,9 @@ class FullO3CPU : public BaseFullCPU
/** The cycle that the CPU was last running, used for statistics. */
Tick lastRunningCycle;
/** The cycle that the CPU was last activated by a new thread*/
Tick lastActivatedCycle;
/** Number of Threads CPU can process */
unsigned numThreads;

View File

@@ -28,8 +28,7 @@
* Authors: Kevin Lim
*/
#include "cpu/o3/alpha_dyn_inst.hh"
#include "cpu/o3/alpha_impl.hh"
#include "cpu/o3/isa_specific.hh"
#include "cpu/o3/decode_impl.hh"
template class DefaultDecode<AlphaSimpleImpl>;
template class DefaultDecode<O3CPUImpl>;

View File

@@ -48,7 +48,7 @@ class DefaultDecode
{
private:
// Typedefs from the Impl.
typedef typename Impl::FullCPU FullCPU;
typedef typename Impl::O3CPU O3CPU;
typedef typename Impl::DynInstPtr DynInstPtr;
typedef typename Impl::Params Params;
typedef typename Impl::CPUPol CPUPol;
@@ -95,7 +95,7 @@ class DefaultDecode
void regStats();
/** Sets CPU pointer. */
void setCPU(FullCPU *cpu_ptr);
void setCPU(O3CPU *cpu_ptr);
/** Sets the main backwards communication time buffer pointer. */
void setTimeBuffer(TimeBuffer<TimeStruct> *tb_ptr);
@@ -109,8 +109,14 @@ class DefaultDecode
/** Sets pointer to list of active threads. */
void setActiveThreads(std::list<unsigned> *at_ptr);
/** Drains the decode stage. */
bool drain();
/** Resumes execution after a drain. */
void resume() { }
/** Switches out the decode stage. */
void switchOut();
void switchOut() { }
/** Takes over from another CPU's thread. */
void takeOverFrom();
@@ -189,7 +195,7 @@ class DefaultDecode
private:
// Interfaces to objects outside of decode.
/** CPU interface. */
FullCPU *cpu;
O3CPU *cpu;
/** Time buffer interface. */
TimeBuffer<TimeStruct> *timeBuffer;

View File

@@ -112,7 +112,7 @@ DefaultDecode<Impl>::regStats()
template<class Impl>
void
DefaultDecode<Impl>::setCPU(FullCPU *cpu_ptr)
DefaultDecode<Impl>::setCPU(O3CPU *cpu_ptr)
{
DPRINTF(Decode, "Setting CPU pointer.\n");
cpu = cpu_ptr;
@@ -165,11 +165,12 @@ DefaultDecode<Impl>::setActiveThreads(list<unsigned> *at_ptr)
}
template <class Impl>
void
DefaultDecode<Impl>::switchOut()
bool
DefaultDecode<Impl>::drain()
{
// Decode can immediately switch out.
cpu->signalSwitched();
// Decode is done draining at any time.
cpu->signalDrained();
return true;
}
template <class Impl>
@@ -296,7 +297,7 @@ DefaultDecode<Impl>::squash(DynInstPtr &inst, unsigned tid)
for (int i=0; i<fromFetch->size; i++) {
if (fromFetch->insts[i]->threadNumber == tid &&
fromFetch->insts[i]->seqNum > inst->seqNum) {
fromFetch->insts[i]->squashed = true;
fromFetch->insts[i]->setSquashed();
}
}
@@ -345,7 +346,7 @@ DefaultDecode<Impl>::squash(unsigned tid)
for (int i=0; i<fromFetch->size; i++) {
if (fromFetch->insts[i]->threadNumber == tid) {
fromFetch->insts[i]->squashed = true;
fromFetch->insts[i]->setSquashed();
squash_count++;
}
}
@@ -427,7 +428,7 @@ DefaultDecode<Impl>::updateStatus()
DPRINTF(Activity, "Activating stage.\n");
cpu->activateStage(FullCPU::DecodeIdx);
cpu->activateStage(O3CPU::DecodeIdx);
}
} else {
// If it's not unblocking, then decode will not have any internal
@@ -436,7 +437,7 @@ DefaultDecode<Impl>::updateStatus()
_status = Inactive;
DPRINTF(Activity, "Deactivating stage.\n");
cpu->deactivateStage(FullCPU::DecodeIdx);
cpu->deactivateStage(O3CPU::DecodeIdx);
}
}
}
@@ -515,7 +516,7 @@ DefaultDecode<Impl>::checkSignalsAndUpdate(unsigned tid)
// Check ROB squash signals from commit.
if (fromCommit->commitInfo[tid].robSquashing) {
DPRINTF(Decode, "[tid:%]: ROB is still squashing.\n",tid);
DPRINTF(Decode, "[tid:%u]: ROB is still squashing.\n", tid);
// Continue to squash.
decodeStatus[tid] = Squashing;

View File

@@ -68,6 +68,8 @@ class DependencyGraph
: numEntries(0), memAllocCounter(0), nodesTraversed(0), nodesRemoved(0)
{ }
~DependencyGraph();
/** Resize the dependency graph to have num_entries registers. */
void resize(int num_entries);
@@ -120,6 +122,12 @@ class DependencyGraph
uint64_t nodesRemoved;
};
template <class DynInstPtr>
DependencyGraph<DynInstPtr>::~DependencyGraph()
{
delete [] dependGraph;
}
template <class DynInstPtr>
void
DependencyGraph<DynInstPtr>::resize(int num_entries)

45
src/cpu/o3/dyn_inst.hh Normal file
View File

@@ -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: Korey Sewell
*/
#ifndef __CPU_O3_DYN_INST_HH__
#define __CPU_O3_DYN_INST_HH__
#include "arch/isa_specific.hh"
#if THE_ISA == ALPHA_ISA
template <class Impl>
class AlphaDynInst;
struct AlphaSimpleImpl;
typedef AlphaDynInst<AlphaSimpleImpl> O3DynInst;
#endif
#endif // __CPU_O3_DYN_INST_HH__

View File

@@ -28,8 +28,7 @@
* Authors: Kevin Lim
*/
#include "cpu/o3/alpha_dyn_inst.hh"
#include "cpu/o3/alpha_impl.hh"
#include "cpu/o3/isa_specific.hh"
#include "cpu/o3/fetch_impl.hh"
template class DefaultFetch<AlphaSimpleImpl>;
template class DefaultFetch<O3CPUImpl>;

View File

@@ -26,6 +26,7 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Authors: Kevin Lim
* Korey Sewell
*/
#ifndef __CPU_O3_FETCH_HH__
@@ -35,12 +36,10 @@
#include "base/statistics.hh"
#include "base/timebuf.hh"
#include "cpu/pc_event.hh"
#include "mem/packet.hh"
#include "mem/packet_impl.hh"
#include "mem/port.hh"
#include "sim/eventq.hh"
class Sampler;
/**
* DefaultFetch class handles both single threaded and SMT fetch. Its
* width is specified by the parameters; each cycle it tries to fetch
@@ -57,7 +56,7 @@ class DefaultFetch
typedef typename Impl::CPUPol CPUPol;
typedef typename Impl::DynInst DynInst;
typedef typename Impl::DynInstPtr DynInstPtr;
typedef typename Impl::FullCPU FullCPU;
typedef typename Impl::O3CPU O3CPU;
typedef typename Impl::Params Params;
/** Typedefs from the CPU policy. */
@@ -163,8 +162,11 @@ class DefaultFetch
/** Registers statistics. */
void regStats();
/** Returns the icache port. */
Port *getIcachePort() { return icachePort; }
/** Sets CPU pointer. */
void setCPU(FullCPU *cpu_ptr);
void setCPU(O3CPU *cpu_ptr);
/** Sets the main backwards communication time buffer pointer. */
void setTimeBuffer(TimeBuffer<TimeStruct> *time_buffer);
@@ -181,11 +183,14 @@ class DefaultFetch
/** Processes cache completion event. */
void processCacheCompletion(PacketPtr pkt);
/** Begins the switch out of the fetch stage. */
void switchOut();
/** Begins the drain of the fetch stage. */
bool drain();
/** Completes the switch out of the fetch stage. */
void doSwitchOut();
/** Resumes execution after a drain. */
void resume();
/** Tells fetch stage to prepare to be switched out. */
void switchOut();
/** Takes over from another CPU's thread. */
void takeOverFrom();
@@ -296,8 +301,8 @@ class DefaultFetch
int branchCount();
private:
/** Pointer to the FullCPU. */
FullCPU *cpu;
/** Pointer to the O3CPU. */
O3CPU *cpu;
/** Time buffer interface. */
TimeBuffer<TimeStruct> *timeBuffer;
@@ -335,6 +340,15 @@ class DefaultFetch
/** Per-thread next PC. */
Addr nextPC[Impl::MaxThreads];
#if THE_ISA != ALPHA_ISA
/** Per-thread next Next PC.
* This is not a real register but is used for
* architectures that use a branch-delay slot.
* (such as MIPS or Sparc)
*/
Addr nextNPC[Impl::MaxThreads];
#endif
/** Memory request used to access cache. */
RequestPtr memReq[Impl::MaxThreads];
@@ -390,6 +404,12 @@ class DefaultFetch
/** The cache line being fetched. */
uint8_t *cacheData[Impl::MaxThreads];
/** The PC of the cacheline that has been loaded. */
Addr cacheDataPC[Impl::MaxThreads];
/** Whether or not the cache data is valid. */
bool cacheDataValid[Impl::MaxThreads];
/** Size of instructions. */
int instSize;
@@ -413,6 +433,9 @@ class DefaultFetch
*/
bool interruptPending;
/** Is there a drain pending. */
bool drainPending;
/** Records if fetch is switched out. */
bool switchedOut;
@@ -421,6 +444,7 @@ class DefaultFetch
Stats::Scalar<> icacheStallCycles;
/** Stat for total number of fetched instructions. */
Stats::Scalar<> fetchedInsts;
/** Total number of fetched branches. */
Stats::Scalar<> fetchedBranches;
/** Stat for total number of predicted branches. */
Stats::Scalar<> predictedBranches;

View File

@@ -26,8 +26,11 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Authors: Kevin Lim
* Korey Sewell
*/
#include "config/use_checker.hh"
#include "arch/isa_traits.hh"
#include "arch/utility.hh"
#include "cpu/checker/cpu.hh"
@@ -106,13 +109,12 @@ DefaultFetch<Impl>::DefaultFetch(Params *params)
numThreads(params->numberOfThreads),
numFetchingThreads(params->smtNumFetchingThreads),
interruptPending(false),
drainPending(false),
switchedOut(false)
{
if (numThreads > Impl::MaxThreads)
fatal("numThreads is not a valid value\n");
DPRINTF(Fetch, "Fetch constructor called\n");
// Set fetch stage's status to inactive.
_status = Inactive;
@@ -125,6 +127,8 @@ DefaultFetch<Impl>::DefaultFetch(Params *params)
// Figure out fetch policy
if (policy == "singlethread") {
fetchPolicy = SingleThread;
if (numThreads > 1)
panic("Invalid Fetch Policy for a SMT workload.");
} else if (policy == "roundrobin") {
fetchPolicy = RoundRobin;
DPRINTF(Fetch, "Fetch policy set to Round Robin\n");
@@ -158,6 +162,8 @@ DefaultFetch<Impl>::DefaultFetch(Params *params)
// Create space to store a cache line.
cacheData[tid] = new uint8_t[cacheBlkSize];
cacheDataPC[tid] = 0;
cacheDataValid[tid] = false;
stalls[tid].decode = 0;
stalls[tid].rename = 0;
@@ -268,7 +274,7 @@ DefaultFetch<Impl>::regStats()
template<class Impl>
void
DefaultFetch<Impl>::setCPU(FullCPU *cpu_ptr)
DefaultFetch<Impl>::setCPU(O3CPU *cpu_ptr)
{
DPRINTF(Fetch, "Setting the CPU pointer.\n");
cpu = cpu_ptr;
@@ -276,13 +282,11 @@ DefaultFetch<Impl>::setCPU(FullCPU *cpu_ptr)
// Name is finally available, so create the port.
icachePort = new IcachePort(this);
Port *mem_dport = mem->getPort("");
icachePort->setPeer(mem_dport);
mem_dport->setPeer(icachePort);
#if USE_CHECKER
if (cpu->checker) {
cpu->checker->setIcachePort(icachePort);
}
#endif
// Fetch needs to start fetching instructions at the very beginning,
// so it must start up in active state.
@@ -330,6 +334,9 @@ DefaultFetch<Impl>::initStage()
for (int tid = 0; tid < numThreads; tid++) {
PC[tid] = cpu->readPC(tid);
nextPC[tid] = cpu->readNextPC(tid);
#if THE_ISA != ALPHA_ISA
nextNPC[tid] = cpu->readNextNPC(tid);
#endif
}
}
@@ -349,18 +356,22 @@ DefaultFetch<Impl>::processCacheCompletion(PacketPtr pkt)
++fetchIcacheSquashes;
delete pkt->req;
delete pkt;
memReq[tid] = NULL;
return;
}
// Wake up the CPU (if it went to sleep and was waiting on this completion
// event).
cpu->wakeCPU();
memcpy(cacheData[tid], pkt->getPtr<uint8_t *>(), cacheBlkSize);
cacheDataValid[tid] = true;
DPRINTF(Activity, "[tid:%u] Activating fetch due to cache completion\n",
tid);
if (!drainPending) {
// Wake up the CPU (if it went to sleep and was waiting on
// this completion event).
cpu->wakeCPU();
switchToActive();
DPRINTF(Activity, "[tid:%u] Activating fetch due to cache completion\n",
tid);
switchToActive();
}
// Only switch to IcacheAccessComplete if we're not stalled as well.
if (checkStall(tid)) {
@@ -376,18 +387,27 @@ DefaultFetch<Impl>::processCacheCompletion(PacketPtr pkt)
}
template <class Impl>
void
DefaultFetch<Impl>::switchOut()
bool
DefaultFetch<Impl>::drain()
{
// Fetch is ready to switch out at any time.
switchedOut = true;
cpu->signalSwitched();
// Fetch is ready to drain at any time.
cpu->signalDrained();
drainPending = true;
return true;
}
template <class Impl>
void
DefaultFetch<Impl>::doSwitchOut()
DefaultFetch<Impl>::resume()
{
drainPending = false;
}
template <class Impl>
void
DefaultFetch<Impl>::switchOut()
{
switchedOut = true;
// Branch predictor needs to have its state cleared.
branchPred.switchOut();
}
@@ -404,6 +424,9 @@ DefaultFetch<Impl>::takeOverFrom()
stalls[i].commit = 0;
PC[i] = cpu->readPC(i);
nextPC[i] = cpu->readNextPC(i);
#if THE_ISA != ALPHA_ISA
nextNPC[i] = cpu->readNextNPC(i);
#endif
fetchStatus[i] = Running;
}
numInst = 0;
@@ -430,7 +453,7 @@ DefaultFetch<Impl>::switchToActive()
if (_status == Inactive) {
DPRINTF(Activity, "Activating stage.\n");
cpu->activateStage(FullCPU::FetchIdx);
cpu->activateStage(O3CPU::FetchIdx);
_status = Active;
}
@@ -443,7 +466,7 @@ DefaultFetch<Impl>::switchToInactive()
if (_status == Active) {
DPRINTF(Activity, "Deactivating stage.\n");
cpu->deactivateStage(FullCPU::FetchIdx);
cpu->deactivateStage(O3CPU::FetchIdx);
_status = Inactive;
}
@@ -488,7 +511,7 @@ DefaultFetch<Impl>::fetchCacheLine(Addr fetch_PC, Fault &ret_fault, unsigned tid
unsigned flags = 0;
#endif // FULL_SYSTEM
if (cacheBlocked || (interruptPending && flags == 0) || switchedOut) {
if (cacheBlocked || (interruptPending && flags == 0)) {
// Hold off fetch from getting new instructions when:
// Cache is blocked, or
// while an interrupt is pending and we're not in PAL mode, or
@@ -499,6 +522,11 @@ DefaultFetch<Impl>::fetchCacheLine(Addr fetch_PC, Fault &ret_fault, unsigned tid
// Align the fetch PC so it's at the start of a cache block.
fetch_PC = icacheBlockAlignPC(fetch_PC);
// If we've already got the block, no need to try to fetch it again.
if (cacheDataValid[tid] && fetch_PC == cacheDataPC[tid]) {
return true;
}
// Setup the memReq to do a read of the first instruction's address.
// Set the appropriate read size and flags as well.
// Build request here.
@@ -530,7 +558,10 @@ DefaultFetch<Impl>::fetchCacheLine(Addr fetch_PC, Fault &ret_fault, unsigned tid
// Build packet here.
PacketPtr data_pkt = new Packet(mem_req,
Packet::ReadReq, Packet::Broadcast);
data_pkt->dataStatic(cacheData[tid]);
data_pkt->dataDynamicArray(new uint8_t[cacheBlkSize]);
cacheDataPC[tid] = fetch_PC;
cacheDataValid[tid] = false;
DPRINTF(Fetch, "Fetch: Doing instruction read.\n");
@@ -549,7 +580,7 @@ DefaultFetch<Impl>::fetchCacheLine(Addr fetch_PC, Fault &ret_fault, unsigned tid
return false;
}
DPRINTF(Fetch, "Doing cache access.\n");
DPRINTF(Fetch, "[tid:%i]: Doing cache access.\n", tid);
lastIcacheStall[tid] = curTick;
@@ -662,7 +693,7 @@ DefaultFetch<Impl>::updateFetchStatus()
"completion\n",tid);
}
cpu->activateStage(FullCPU::FetchIdx);
cpu->activateStage(O3CPU::FetchIdx);
}
return Active;
@@ -673,7 +704,7 @@ DefaultFetch<Impl>::updateFetchStatus()
if (_status == Active) {
DPRINTF(Activity, "Deactivating stage.\n");
cpu->deactivateStage(FullCPU::FetchIdx);
cpu->deactivateStage(O3CPU::FetchIdx);
}
return Inactive;
@@ -714,12 +745,15 @@ DefaultFetch<Impl>::tick()
// Reset the number of the instruction we're fetching.
numInst = 0;
#if FULL_SYSTEM
if (fromCommit->commitInfo[0].interruptPending) {
interruptPending = true;
}
if (fromCommit->commitInfo[0].clearInterrupt) {
interruptPending = false;
}
#endif
for (threadFetched = 0; threadFetched < numFetchingThreads;
threadFetched++) {
@@ -817,7 +851,7 @@ DefaultFetch<Impl>::checkSignalsAndUpdate(unsigned tid)
// Check ROB squash signals from commit.
if (fromCommit->commitInfo[tid].robSquashing) {
DPRINTF(Fetch, "[tid:%u]: ROB is still squashing Thread %u.\n", tid);
DPRINTF(Fetch, "[tid:%u]: ROB is still squashing.\n", tid);
// Continue to squash.
fetchStatus[tid] = Squashing;
@@ -885,7 +919,7 @@ DefaultFetch<Impl>::fetch(bool &status_change)
//////////////////////////////////////////
int tid = getFetchingThread(fetchPolicy);
if (tid == -1) {
if (tid == -1 || drainPending) {
DPRINTF(Fetch,"There are no more threads available to fetch from.\n");
// Breaks looping condition in tick()
@@ -893,6 +927,8 @@ DefaultFetch<Impl>::fetch(bool &status_change)
return;
}
DPRINTF(Fetch, "Attempting to fetch from [tid:%i]\n", tid);
// The current PC.
Addr &fetch_PC = PC[tid];
@@ -915,7 +951,11 @@ DefaultFetch<Impl>::fetch(bool &status_change)
bool fetch_success = fetchCacheLine(fetch_PC, fault, tid);
if (!fetch_success) {
++fetchMiscStallCycles;
if (cacheBlocked) {
++icacheStallCycles;
} else {
++fetchMiscStallCycles;
}
return;
}
} else {
@@ -984,11 +1024,11 @@ DefaultFetch<Impl>::fetch(bool &status_change)
DynInstPtr instruction = new DynInst(ext_inst, fetch_PC,
next_PC,
inst_seq, cpu);
instruction->setThread(tid);
instruction->setTid(tid);
instruction->setASID(tid);
instruction->setState(cpu->thread[tid]);
instruction->setThreadState(cpu->thread[tid]);
DPRINTF(Fetch, "[tid:%i]: Instruction PC %#x created "
"[sn:%lli]\n",
@@ -1020,7 +1060,7 @@ DefaultFetch<Impl>::fetch(bool &status_change)
fetch_PC = next_PC;
if (instruction->isQuiesce()) {
warn("%lli: Quiesce instruction encountered, halting fetch!",
warn("cycle %lli: Quiesce instruction encountered, halting fetch!",
curTick);
fetchStatus[tid] = QuiescePending;
++numInst;
@@ -1041,8 +1081,17 @@ DefaultFetch<Impl>::fetch(bool &status_change)
if (fault == NoFault) {
DPRINTF(Fetch, "[tid:%i]: Setting PC to %08p.\n",tid, next_PC);
#if THE_ISA == ALPHA_ISA
PC[tid] = next_PC;
nextPC[tid] = next_PC + instSize;
#else
PC[tid] = next_PC;
nextPC[tid] = next_PC + instSize;
nextPC[tid] = next_PC + instSize;
thread->setNextPC(thread->readNextNPC());
thread->setNextNPC(thread->readNextNPC() + sizeof(MachInst));
#endif
} else {
// We shouldn't be in an icache miss and also have a fault (an ITB
// miss)
@@ -1065,11 +1114,11 @@ DefaultFetch<Impl>::fetch(bool &status_change)
next_PC,
inst_seq, cpu);
instruction->setPredTarg(next_PC + instSize);
instruction->setThread(tid);
instruction->setTid(tid);
instruction->setASID(tid);
instruction->setState(cpu->thread[tid]);
instruction->setThreadState(cpu->thread[tid]);
instruction->traceData = NULL;
@@ -1085,9 +1134,9 @@ DefaultFetch<Impl>::fetch(bool &status_change)
fetchStatus[tid] = TrapPending;
status_change = true;
warn("%lli fault (%d) detected @ PC %08p", curTick, fault, PC[tid]);
warn("cycle %lli: fault (%d) detected @ PC %08p", curTick, fault, PC[tid]);
#else // !FULL_SYSTEM
warn("%lli fault (%d) detected @ PC %08p", curTick, fault, PC[tid]);
warn("cycle %lli: fault (%d) detected @ PC %08p", curTick, fault, PC[tid]);
#endif // FULL_SYSTEM
}
}
@@ -1256,6 +1305,6 @@ int
DefaultFetch<Impl>::branchCount()
{
list<unsigned>::iterator threads = (*activeThreads).begin();
panic("Branch Count Fetch policy unimplemented\n");
return *threads;
}

View File

@@ -31,7 +31,7 @@
#include <sstream>
#include "cpu/o3/fu_pool.hh"
#include "encumbered/cpu/full/fu_pool.hh"
#include "cpu/func_unit.hh"
#include "sim/builder.hh"
using namespace std;

View File

@@ -28,9 +28,8 @@
* Authors: Kevin Lim
*/
#include "cpu/o3/alpha_dyn_inst.hh"
#include "cpu/o3/alpha_impl.hh"
#include "cpu/o3/isa_specific.hh"
#include "cpu/o3/iew_impl.hh"
#include "cpu/o3/inst_queue.hh"
template class DefaultIEW<AlphaSimpleImpl>;
template class DefaultIEW<O3CPUImpl>;

View File

@@ -68,7 +68,7 @@ class DefaultIEW
//Typedefs from Impl
typedef typename Impl::CPUPol CPUPol;
typedef typename Impl::DynInstPtr DynInstPtr;
typedef typename Impl::FullCPU FullCPU;
typedef typename Impl::O3CPU O3CPU;
typedef typename Impl::Params Params;
typedef typename CPUPol::IQ IQ;
@@ -80,7 +80,7 @@ class DefaultIEW
typedef typename CPUPol::RenameStruct RenameStruct;
typedef typename CPUPol::IssueStruct IssueStruct;
friend class Impl::FullCPU;
friend class Impl::O3CPU;
friend class CPUPol::IQ;
public:
@@ -125,8 +125,11 @@ class DefaultIEW
/** Initializes stage; sends back the number of free IQ and LSQ entries. */
void initStage();
/** Returns the dcache port. */
Port *getDcachePort() { return ldstQueue.getDcachePort(); }
/** Sets CPU pointer for IEW, IQ, and LSQ. */
void setCPU(FullCPU *cpu_ptr);
void setCPU(O3CPU *cpu_ptr);
/** Sets main time buffer used for backwards communication. */
void setTimeBuffer(TimeBuffer<TimeStruct> *tb_ptr);
@@ -143,11 +146,14 @@ class DefaultIEW
/** Sets pointer to the scoreboard. */
void setScoreboard(Scoreboard *sb_ptr);
/** Starts switch out of IEW stage. */
void switchOut();
/** Drains IEW stage. */
bool drain();
/** Resumes execution after a drain. */
void resume();
/** Completes switch out of IEW stage. */
void doSwitchOut();
void switchOut();
/** Takes over from another CPU's thread. */
void takeOverFrom();
@@ -204,6 +210,45 @@ class DefaultIEW
/** Returns if the LSQ has any stores to writeback. */
bool hasStoresToWB() { return ldstQueue.hasStoresToWB(); }
void incrWb(InstSeqNum &sn)
{
if (++wbOutstanding == wbMax)
ableToIssue = false;
DPRINTF(IEW, "wbOutstanding: %i\n", wbOutstanding);
#if DEBUG
wbList.insert(sn);
#endif
}
void decrWb(InstSeqNum &sn)
{
if (wbOutstanding-- == wbMax)
ableToIssue = true;
DPRINTF(IEW, "wbOutstanding: %i\n", wbOutstanding);
#if DEBUG
assert(wbList.find(sn) != wbList.end());
wbList.erase(sn);
#endif
}
#if DEBUG
std::set<InstSeqNum> wbList;
void dumpWb()
{
std::set<InstSeqNum>::iterator wb_it = wbList.begin();
while (wb_it != wbList.end()) {
cprintf("[sn:%lli]\n",
(*wb_it));
wb_it++;
}
}
#endif
bool canIssue() { return ableToIssue; }
bool ableToIssue;
private:
/** Sends commit proper information for a squash due to a branch
* mispredict.
@@ -261,6 +306,9 @@ class DefaultIEW
/** Processes inputs and changes state accordingly. */
void checkSignalsAndUpdate(unsigned tid);
/** Removes instructions from rename from a thread's instruction list. */
void emptyRenameInsts(unsigned tid);
/** Sorts instructions coming from rename into lists separated by thread. */
void sortInsts();
@@ -328,7 +376,7 @@ class DefaultIEW
private:
/** CPU pointer. */
FullCPU *cpu;
O3CPU *cpu;
/** Records if IEW has written to the time buffer this cycle, so that the
* CPU can deschedule itself if there is no activity.
@@ -381,20 +429,12 @@ class DefaultIEW
*/
unsigned issueToExecuteDelay;
/** Width of issue's read path, in instructions. The read path is both
* the skid buffer and the rename instruction queue.
* Note to self: is this really different than issueWidth?
*/
unsigned issueReadWidth;
/** Width of dispatch, in instructions. */
unsigned dispatchWidth;
/** Width of issue, in instructions. */
unsigned issueWidth;
/** Width of execute, in instructions. Might make more sense to break
* down into FP vs int.
*/
unsigned executeWidth;
/** Index into queue of instructions being written back. */
unsigned wbNumInst;
@@ -405,6 +445,17 @@ class DefaultIEW
*/
unsigned wbCycle;
/** Number of instructions in flight that will writeback. */
unsigned wbOutstanding;
/** Writeback width. */
unsigned wbWidth;
/** Writeback width * writeback depth, where writeback depth is
* the number of cycles of writing back instructions that can be
* buffered. */
unsigned wbMax;
/** Number of active threads. */
unsigned numThreads;
@@ -439,14 +490,6 @@ class DefaultIEW
Stats::Scalar<> iewIQFullEvents;
/** Stat for number of times the LSQ becomes full. */
Stats::Scalar<> iewLSQFullEvents;
/** Stat for total number of executed instructions. */
Stats::Scalar<> iewExecutedInsts;
/** Stat for total number of executed load instructions. */
Stats::Vector<> iewExecLoadInsts;
/** Stat for total number of executed store instructions. */
// Stats::Scalar<> iewExecStoreInsts;
/** Stat for total number of squashed instructions skipped at execute. */
Stats::Scalar<> iewExecSquashedInsts;
/** Stat for total number of memory ordering violation events. */
Stats::Scalar<> memOrderViolationEvents;
/** Stat for total number of incorrect predicted taken branches. */
@@ -456,28 +499,25 @@ class DefaultIEW
/** Stat for total number of mispredicted branches detected at execute. */
Stats::Formula branchMispredicts;
/** Stat for total number of executed instructions. */
Stats::Scalar<> iewExecutedInsts;
/** Stat for total number of executed load instructions. */
Stats::Vector<> iewExecLoadInsts;
/** Stat for total number of squashed instructions skipped at execute. */
Stats::Scalar<> iewExecSquashedInsts;
/** Number of executed software prefetches. */
Stats::Vector<> exeSwp;
Stats::Vector<> iewExecutedSwp;
/** Number of executed nops. */
Stats::Vector<> exeNop;
Stats::Vector<> iewExecutedNop;
/** Number of executed meomory references. */
Stats::Vector<> exeRefs;
Stats::Vector<> iewExecutedRefs;
/** Number of executed branches. */
Stats::Vector<> exeBranches;
// Stats::Vector<> issued_ops;
/*
Stats::Vector<> stat_fu_busy;
Stats::Vector2d<> stat_fuBusy;
Stats::Vector<> dist_unissued;
Stats::Vector2d<> stat_issued_inst_type;
*/
/** Number of instructions issued per cycle. */
Stats::Formula issueRate;
Stats::Vector<> iewExecutedBranches;
/** Number of executed store instructions. */
Stats::Formula iewExecStoreInsts;
// Stats::Formula issue_op_rate;
// Stats::Formula fu_busy_rate;
/** Number of instructions executed per cycle. */
Stats::Formula iewExecRate;
/** Number of instructions sent to commit. */
Stats::Vector<> iewInstsToCommit;
/** Number of instructions that writeback. */
@@ -490,7 +530,6 @@ class DefaultIEW
* to resource contention.
*/
Stats::Vector<> wbPenalized;
/** Number of instructions per cycle written back. */
Stats::Formula wbRate;
/** Average number of woken instructions per writeback. */

View File

@@ -42,17 +42,17 @@ using namespace std;
template<class Impl>
DefaultIEW<Impl>::DefaultIEW(Params *params)
: // @todo: Make this into a parameter.
issueToExecQueue(5, 5),
: issueToExecQueue(params->backComSize, params->forwardComSize),
instQueue(params),
ldstQueue(params),
fuPool(params->fuPool),
commitToIEWDelay(params->commitToIEWDelay),
renameToIEWDelay(params->renameToIEWDelay),
issueToExecuteDelay(params->issueToExecuteDelay),
issueReadWidth(params->issueWidth),
dispatchWidth(params->dispatchWidth),
issueWidth(params->issueWidth),
executeWidth(params->executeWidth),
wbOutstanding(0),
wbWidth(params->wbWidth),
numThreads(params->numberOfThreads),
switchedOut(false)
{
@@ -75,8 +75,12 @@ DefaultIEW<Impl>::DefaultIEW(Params *params)
fetchRedirect[i] = false;
}
wbMax = wbWidth * params->wbDepth;
updateLSQNextCycle = false;
ableToIssue = true;
skidBufferMax = (3 * (renameToIEWDelay * params->renameWidth)) + issueWidth;
}
@@ -94,6 +98,7 @@ DefaultIEW<Impl>::regStats()
using namespace Stats;
instQueue.regStats();
ldstQueue.regStats();
iewIdleCycles
.name(name() + ".iewIdleCycles")
@@ -139,20 +144,6 @@ DefaultIEW<Impl>::regStats()
.name(name() + ".iewLSQFullEvents")
.desc("Number of times the LSQ has become full, causing a stall");
iewExecutedInsts
.name(name() + ".iewExecutedInsts")
.desc("Number of executed instructions");
iewExecLoadInsts
.init(cpu->number_of_threads)
.name(name() + ".iewExecLoadInsts")
.desc("Number of load instructions executed")
.flags(total);
iewExecSquashedInsts
.name(name() + ".iewExecSquashedInsts")
.desc("Number of squashed instructions skipped in execute");
memOrderViolationEvents
.name(name() + ".memOrderViolationEvents")
.desc("Number of memory order violations");
@@ -171,114 +162,105 @@ DefaultIEW<Impl>::regStats()
branchMispredicts = predictedTakenIncorrect + predictedNotTakenIncorrect;
exeSwp
iewExecutedInsts
.name(name() + ".EXEC:insts")
.desc("Number of executed instructions");
iewExecLoadInsts
.init(cpu->number_of_threads)
.name(name() + ".EXEC:loads")
.desc("Number of load instructions executed")
.flags(total);
iewExecSquashedInsts
.name(name() + ".EXEC:squashedInsts")
.desc("Number of squashed instructions skipped in execute");
iewExecutedSwp
.init(cpu->number_of_threads)
.name(name() + ".EXEC:swp")
.desc("number of swp insts executed")
.flags(total)
;
.flags(total);
exeNop
iewExecutedNop
.init(cpu->number_of_threads)
.name(name() + ".EXEC:nop")
.desc("number of nop insts executed")
.flags(total)
;
.flags(total);
exeRefs
iewExecutedRefs
.init(cpu->number_of_threads)
.name(name() + ".EXEC:refs")
.desc("number of memory reference insts executed")
.flags(total)
;
.flags(total);
exeBranches
iewExecutedBranches
.init(cpu->number_of_threads)
.name(name() + ".EXEC:branches")
.desc("Number of branches executed")
.flags(total)
;
issueRate
.name(name() + ".EXEC:rate")
.desc("Inst execution rate")
.flags(total)
;
issueRate = iewExecutedInsts / cpu->numCycles;
.flags(total);
iewExecStoreInsts
.name(name() + ".EXEC:stores")
.desc("Number of stores executed")
.flags(total)
;
iewExecStoreInsts = exeRefs - iewExecLoadInsts;
/*
for (int i=0; i<Num_OpClasses; ++i) {
stringstream subname;
subname << opClassStrings[i] << "_delay";
issue_delay_dist.subname(i, subname.str());
}
*/
//
// Other stats
//
.flags(total);
iewExecStoreInsts = iewExecutedRefs - iewExecLoadInsts;
iewExecRate
.name(name() + ".EXEC:rate")
.desc("Inst execution rate")
.flags(total);
iewExecRate = iewExecutedInsts / cpu->numCycles;
iewInstsToCommit
.init(cpu->number_of_threads)
.name(name() + ".WB:sent")
.desc("cumulative count of insts sent to commit")
.flags(total)
;
.flags(total);
writebackCount
.init(cpu->number_of_threads)
.name(name() + ".WB:count")
.desc("cumulative count of insts written-back")
.flags(total)
;
.flags(total);
producerInst
.init(cpu->number_of_threads)
.name(name() + ".WB:producers")
.desc("num instructions producing a value")
.flags(total)
;
.flags(total);
consumerInst
.init(cpu->number_of_threads)
.name(name() + ".WB:consumers")
.desc("num instructions consuming a value")
.flags(total)
;
.flags(total);
wbPenalized
.init(cpu->number_of_threads)
.name(name() + ".WB:penalized")
.desc("number of instrctions required to write to 'other' IQ")
.flags(total)
;
.flags(total);
wbPenalizedRate
.name(name() + ".WB:penalized_rate")
.desc ("fraction of instructions written-back that wrote to 'other' IQ")
.flags(total)
;
.flags(total);
wbPenalizedRate = wbPenalized / writebackCount;
wbFanout
.name(name() + ".WB:fanout")
.desc("average fanout of values written-back")
.flags(total)
;
.flags(total);
wbFanout = producerInst / consumerInst;
wbRate
.name(name() + ".WB:rate")
.desc("insts written-back per cycle")
.flags(total)
;
.flags(total);
wbRate = writebackCount / cpu->numCycles;
}
@@ -299,7 +281,7 @@ DefaultIEW<Impl>::initStage()
template<class Impl>
void
DefaultIEW<Impl>::setCPU(FullCPU *cpu_ptr)
DefaultIEW<Impl>::setCPU(O3CPU *cpu_ptr)
{
DPRINTF(IEW, "Setting CPU pointer.\n");
cpu = cpu_ptr;
@@ -307,7 +289,7 @@ DefaultIEW<Impl>::setCPU(FullCPU *cpu_ptr)
instQueue.setCPU(cpu_ptr);
ldstQueue.setCPU(cpu_ptr);
cpu->activateStage(FullCPU::IEWIdx);
cpu->activateStage(O3CPU::IEWIdx);
}
template<class Impl>
@@ -371,16 +353,23 @@ DefaultIEW<Impl>::setScoreboard(Scoreboard *sb_ptr)
}
template <class Impl>
void
DefaultIEW<Impl>::switchOut()
bool
DefaultIEW<Impl>::drain()
{
// IEW is ready to switch out at any time.
cpu->signalSwitched();
// IEW is ready to drain at any time.
cpu->signalDrained();
return true;
}
template <class Impl>
void
DefaultIEW<Impl>::doSwitchOut()
DefaultIEW<Impl>::resume()
{
}
template <class Impl>
void
DefaultIEW<Impl>::switchOut()
{
// Clear any state.
switchedOut = true;
@@ -423,7 +412,7 @@ DefaultIEW<Impl>::takeOverFrom()
updateLSQNextCycle = false;
// @todo: Fix hardcoded number
for (int i = 0; i < 6; ++i) {
for (int i = 0; i < issueToExecQueue.getSize(); ++i) {
issueToExecQueue.advance();
}
}
@@ -456,16 +445,7 @@ DefaultIEW<Impl>::squash(unsigned tid)
skidBuffer[tid].pop();
}
while (!insts[tid].empty()) {
if (insts[tid].front()->isLoad() ||
insts[tid].front()->isStore() ) {
toRename->iewInfo[tid].dispatchedToLSQ++;
}
toRename->iewInfo[tid].dispatched++;
insts[tid].pop();
}
emptyRenameInsts(tid);
}
template<class Impl>
@@ -591,12 +571,12 @@ DefaultIEW<Impl>::instToCommit(DynInstPtr &inst)
// free slot.
while ((*iewQueue)[wbCycle].insts[wbNumInst]) {
++wbNumInst;
if (wbNumInst == issueWidth) {
if (wbNumInst == wbWidth) {
++wbCycle;
wbNumInst = 0;
}
assert(wbCycle < 5);
assert((wbCycle * wbWidth + wbNumInst) < wbMax);
}
// Add finished instruction to queue to commit.
@@ -611,7 +591,7 @@ DefaultIEW<Impl>::validInstsFromRename()
unsigned inst_count = 0;
for (int i=0; i<fromRename->size; i++) {
if (!fromRename->insts[i]->squashed)
if (!fromRename->insts[i]->isSquashed())
inst_count++;
}
@@ -799,10 +779,12 @@ DefaultIEW<Impl>::checkSignalsAndUpdate(unsigned tid)
}
if (fromCommit->commitInfo[tid].robSquashing) {
DPRINTF(IEW, "[tid:%i]: ROB is still squashing.\n");
DPRINTF(IEW, "[tid:%i]: ROB is still squashing.\n", tid);
dispatchStatus[tid] = Squashing;
emptyRenameInsts(tid);
wroteToTimeBuffer = true;
return;
}
@@ -851,6 +833,22 @@ DefaultIEW<Impl>::sortInsts()
}
}
template <class Impl>
void
DefaultIEW<Impl>::emptyRenameInsts(unsigned tid)
{
while (!insts[tid].empty()) {
if (insts[tid].front()->isLoad() ||
insts[tid].front()->isStore() ) {
toRename->iewInfo[tid].dispatchedToLSQ++;
}
toRename->iewInfo[tid].dispatched++;
insts[tid].pop();
}
}
template <class Impl>
void
DefaultIEW<Impl>::wakeCPU()
@@ -871,7 +869,7 @@ inline void
DefaultIEW<Impl>::activateStage()
{
DPRINTF(Activity, "Activating stage.\n");
cpu->activateStage(FullCPU::IEWIdx);
cpu->activateStage(O3CPU::IEWIdx);
}
template <class Impl>
@@ -879,7 +877,7 @@ inline void
DefaultIEW<Impl>::deactivateStage()
{
DPRINTF(Activity, "Deactivating stage.\n");
cpu->deactivateStage(FullCPU::IEWIdx);
cpu->deactivateStage(O3CPU::IEWIdx);
}
template<class Impl>
@@ -951,7 +949,7 @@ DefaultIEW<Impl>::dispatchInsts(unsigned tid)
// Loop through the instructions, putting them in the instruction
// queue.
for ( ; dis_num_inst < insts_to_add &&
dis_num_inst < issueReadWidth;
dis_num_inst < dispatchWidth;
++dis_num_inst)
{
inst = insts_to_dispatch.front();
@@ -1090,7 +1088,7 @@ DefaultIEW<Impl>::dispatchInsts(unsigned tid)
instQueue.recordProducer(inst);
exeNop[tid]++;
iewExecutedNop[tid]++;
add_to_iq = false;
} else if (inst->isExecuted()) {
@@ -1203,6 +1201,7 @@ DefaultIEW<Impl>::executeInsts()
++iewExecSquashedInsts;
decrWb(inst->seqNum);
continue;
}
@@ -1365,6 +1364,8 @@ DefaultIEW<Impl>::writebackInsts()
}
writebackCount[tid]++;
}
decrWb(inst->seqNum);
}
}
@@ -1501,9 +1502,9 @@ DefaultIEW<Impl>::updateExeInstStats(DynInstPtr &inst)
//
#ifdef TARGET_ALPHA
if (inst->isDataPrefetch())
exeSwp[thread_number]++;
iewExecutedSwp[thread_number]++;
else
iewExecutedInsts++;
iewIewExecutedcutedInsts++;
#else
iewExecutedInsts++;
#endif
@@ -1512,13 +1513,13 @@ DefaultIEW<Impl>::updateExeInstStats(DynInstPtr &inst)
// Control operations
//
if (inst->isControl())
exeBranches[thread_number]++;
iewExecutedBranches[thread_number]++;
//
// Memory operations
//
if (inst->isMemRef()) {
exeRefs[thread_number]++;
iewExecutedRefs[thread_number]++;
if (inst->isLoad()) {
iewExecLoadInsts[thread_number]++;

View File

@@ -28,9 +28,8 @@
* Authors: Kevin Lim
*/
#include "cpu/o3/alpha_dyn_inst.hh"
#include "cpu/o3/alpha_impl.hh"
#include "cpu/o3/isa_specific.hh"
#include "cpu/o3/inst_queue_impl.hh"
// Force instantiation of InstructionQueue.
template class InstructionQueue<AlphaSimpleImpl>;
template class InstructionQueue<O3CPUImpl>;

Some files were not shown because too many files have changed in this diff Show More