summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKevin Lim <ktlim@umich.edu>2006-07-06 16:51:50 -0400
committerKevin Lim <ktlim@umich.edu>2006-07-06 16:51:50 -0400
commitb55cda163ed1a29ee5e08cde36743047923ab475 (patch)
tree3e94908acce5edfa05b76cf87a7d5b1ef012a720
parentec72f6534c2bb6aada305815fb306680508d7a7c (diff)
parenta1d208a65de95ee14c52fdc6ca9401642e07293d (diff)
downloadgem5-b55cda163ed1a29ee5e08cde36743047923ab475.tar.xz
Merge ktlim@zizzer:/bk/newmem
into zamp.eecs.umich.edu:/z/ktlim2/clean/newmem --HG-- extra : convert_revision : 7c7fc8a2f9579d443786e86dbcf906b355de69fc
-rw-r--r--configs/test/fs.py8
-rw-r--r--src/SConscript1
-rw-r--r--src/arch/mips/isa/formats/fp.isa16
-rw-r--r--src/base/traceflags.py14
-rw-r--r--src/cpu/SConscript15
-rw-r--r--src/cpu/base.cc1
-rw-r--r--src/cpu/base.hh1
-rw-r--r--src/cpu/checker/cpu.hh3
-rw-r--r--src/cpu/checker/cpu_impl.hh6
-rw-r--r--src/cpu/cpu_models.py14
-rw-r--r--src/cpu/o3/alpha/cpu_builder.cc9
-rw-r--r--src/cpu/o3/alpha/impl.hh4
-rw-r--r--src/cpu/o3/alpha/params.hh11
-rw-r--r--src/cpu/o3/commit.hh13
-rw-r--r--src/cpu/o3/commit_impl.hh21
-rw-r--r--src/cpu/o3/cpu.cc138
-rw-r--r--src/cpu/o3/cpu.hh26
-rw-r--r--src/cpu/o3/decode.hh8
-rw-r--r--src/cpu/o3/decode_impl.hh6
-rw-r--r--src/cpu/o3/dyn_inst.hh45
-rw-r--r--src/cpu/o3/fetch.hh16
-rw-r--r--src/cpu/o3/fetch_impl.hh24
-rw-r--r--src/cpu/o3/iew.hh66
-rw-r--r--src/cpu/o3/iew_impl.hh31
-rw-r--r--src/cpu/o3/inst_queue_impl.hh2
-rw-r--r--src/cpu/o3/lsq_unit_impl.hh1
-rwxr-xr-xsrc/cpu/o3/params.hh15
-rw-r--r--src/cpu/o3/rename.hh9
-rw-r--r--src/cpu/o3/rename_impl.hh6
-rw-r--r--src/cpu/ozone/cpu.hh5
-rw-r--r--src/cpu/ozone/cpu_impl.hh6
-rw-r--r--src/cpu/simple/base.cc1
-rw-r--r--src/cpu/simple/base.hh6
-rw-r--r--src/cpu/simple/timing.cc29
-rw-r--r--src/cpu/simple/timing.hh6
-rw-r--r--src/cpu/static_inst.hh4
-rw-r--r--src/dev/ide_ctrl.cc232
-rw-r--r--src/dev/ide_ctrl.hh8
-rw-r--r--src/dev/io_device.cc22
-rw-r--r--src/dev/io_device.hh4
-rw-r--r--src/dev/ns_gige.cc30
-rw-r--r--src/dev/ns_gige.hh3
-rw-r--r--src/dev/pciconfigall.cc131
-rw-r--r--src/dev/pciconfigall.hh66
-rw-r--r--src/dev/pcidev.cc347
-rw-r--r--src/dev/pcidev.hh112
-rw-r--r--src/dev/pcireg.h1
-rw-r--r--src/dev/platform.cc16
-rw-r--r--src/dev/platform.hh15
-rw-r--r--src/dev/sinic.cc4
-rw-r--r--src/dev/tsunami.cc7
-rw-r--r--src/dev/tsunami.hh6
-rw-r--r--src/dev/tsunami_pchip.cc11
-rw-r--r--src/dev/tsunami_pchip.hh5
-rw-r--r--src/mem/bus.cc116
-rw-r--r--src/mem/bus.hh12
-rw-r--r--src/mem/cache/base_cache.cc31
-rw-r--r--src/mem/cache/base_cache.hh32
-rw-r--r--src/mem/cache/cache.hh13
-rw-r--r--src/python/m5/__init__.py30
-rw-r--r--src/python/m5/config.py6
-rw-r--r--src/python/m5/objects/Bus.py1
-rw-r--r--src/python/m5/objects/O3CPU.py8
-rw-r--r--src/python/m5/objects/Pci.py10
-rw-r--r--src/sim/main.cc14
-rw-r--r--src/sim/pseudo_inst.cc6
-rw-r--r--src/sim/sim_events.cc4
-rw-r--r--src/sim/sim_events.hh6
-rw-r--r--src/sim/sim_object.cc23
-rw-r--r--src/sim/sim_object.hh10
70 files changed, 1084 insertions, 845 deletions
diff --git a/configs/test/fs.py b/configs/test/fs.py
index aa530dd55..e0dd38e41 100644
--- a/configs/test/fs.py
+++ b/configs/test/fs.py
@@ -1,6 +1,6 @@
import m5
from m5.objects import *
-import os
+import os,optparse,sys
from SysPaths import *
parser = optparse.OptionParser(option_list=m5.standardOptions)
@@ -98,7 +98,7 @@ class SpecwebFilesetDisk(IdeDisk):
class BaseTsunami(Tsunami):
cchip = TsunamiCChip(pio_addr=0x801a0000000)
pchip = TsunamiPChip(pio_addr=0x80180000000)
- pciconfig = PciConfigAll(pio_addr=0x801fe000000)
+ pciconfig = PciConfigAll()
fake_sm_chip = IsaFake(pio_addr=0x801fc000370)
fake_uart1 = IsaFake(pio_addr=0x801fc0002f8)
@@ -151,16 +151,18 @@ class MyLinuxAlphaSystem(LinuxAlphaSystem):
tsunami = LinuxTsunami()
tsunami.cchip.pio = magicbus.port
tsunami.pchip.pio = magicbus.port
- tsunami.pciconfig.pio = magicbus.port
+ tsunami.pciconfig.pio = magicbus.default
tsunami.fake_sm_chip.pio = magicbus.port
tsunami.ethernet.pio = magicbus.port
tsunami.ethernet.dma = magicbus.port
+ tsunami.ethernet.config = magicbus.port
tsunami.fake_uart1.pio = magicbus.port
tsunami.fake_uart2.pio = magicbus.port
tsunami.fake_uart3.pio = magicbus.port
tsunami.fake_uart4.pio = magicbus.port
tsunami.ide.pio = magicbus.port
tsunami.ide.dma = magicbus.port
+ tsunami.ide.config = magicbus.port
tsunami.fake_ppc.pio = magicbus.port
tsunami.fake_OROM.pio = magicbus.port
tsunami.fake_pnp_addr.pio = magicbus.port
diff --git a/src/SConscript b/src/SConscript
index 0d0cb2486..9825cafe7 100644
--- a/src/SConscript
+++ b/src/SConscript
@@ -89,7 +89,6 @@ base_sources = Split('''
cpu/pc_event.cc
cpu/quiesce_event.cc
cpu/static_inst.cc
- cpu/sampler/sampler.cc
cpu/simple_thread.cc
cpu/thread_state.cc
diff --git a/src/arch/mips/isa/formats/fp.isa b/src/arch/mips/isa/formats/fp.isa
index 1e5d62626..cdb892b3f 100644
--- a/src/arch/mips/isa/formats/fp.isa
+++ b/src/arch/mips/isa/formats/fp.isa
@@ -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;
diff --git a/src/base/traceflags.py b/src/base/traceflags.py
index 327ce6075..27c24107c 100644
--- a/src/base/traceflags.py
+++ b/src/base/traceflags.py
@@ -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,13 +119,8 @@ baseFlags = [
'MSHR',
'Mbox',
'MemDepUnit',
- 'BaseCPU'
'O3CPU',
'OzoneCPU',
- 'FE',
- 'IBE',
- 'BE',
- 'O3CPU',
'OzoneLSQ',
'PCEvent',
'PCIA',
@@ -135,6 +134,7 @@ baseFlags = [
'RenameMap',
'SQL',
'Sampler',
+ 'Scoreboard',
'ScsiCtrl',
'ScsiDisk',
'ScsiNone',
@@ -158,8 +158,6 @@ baseFlags = [
'Uart',
'VtoPhys',
'WriteBarrier',
- 'Activity',
- 'Scoreboard',
'Writeback',
]
@@ -178,7 +176,7 @@ compoundFlagMap = {
'EthernetAll' : [ 'Ethernet', 'EthernetPIO', 'EthernetDMA', 'EthernetData' , 'EthernetDesc', 'EthernetIntr', 'EthernetSM', 'EthernetCksum' ],
'EthernetNoData' : [ 'Ethernet', 'EthernetPIO', 'EthernetDesc', 'EthernetIntr', 'EthernetSM', 'EthernetCksum' ],
'IdeAll' : [ 'IdeCtrl', 'IdeDisk' ],
- 'O3CPUAll' : [ 'Fetch', 'Decode', 'Rename', 'IEW', 'Commit', 'IQ', 'ROB', 'FreeList', 'RenameMap', 'LSQ', 'LSQUnit', 'StoreSet', 'MemDepUnit', 'DynInst', 'O3CPU', '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']
}
diff --git a/src/cpu/SConscript b/src/cpu/SConscript
index 3dcc2f1ec..1d0a015b0 100644
--- a/src/cpu/SConscript
+++ b/src/cpu/SConscript
@@ -130,13 +130,13 @@ if need_simple_base:
if 'FastCPU' in env['CPU_MODELS']:
sources += Split('fast/cpu.cc')
+need_bp_unit = False
if 'O3CPU' in env['CPU_MODELS']:
+ need_bp_unit = True
sources += SConscript('o3/SConscript', exports = 'env')
sources += Split('''
- o3/2bit_local_pred.cc
o3/base_dyn_inst.cc
o3/bpred_unit.cc
- o3/btb.cc
o3/commit.cc
o3/decode.cc
o3/fetch.cc
@@ -148,18 +148,17 @@ if 'O3CPU' 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 'OzoneCPU' in env['CPU_MODELS']:
+ need_bp_unit = True
sources += Split('''
ozone/base_dyn_inst.cc
ozone/bpred_unit.cc
@@ -174,6 +173,14 @@ if 'OzoneCPU' in env['CPU_MODELS']:
if env['USE_CHECKER']:
sources += Split('ozone/checker_builder.cc')
+if need_bp_unit:
+ sources += Split('''
+ o3/2bit_local_pred.cc
+ o3/btb.cc
+ o3/ras.cc
+ o3/tournament_pred.cc
+ ''')
+
if env['USE_CHECKER']:
sources += Split('checker/cpu.cc')
checker_supports = False
diff --git a/src/cpu/base.cc b/src/cpu/base.cc
index 40cec416b..0b9c80591 100644
--- a/src/cpu/base.cc
+++ b/src/cpu/base.cc
@@ -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"
diff --git a/src/cpu/base.hh b/src/cpu/base.hh
index 51f3bb905..5256a411f 100644
--- a/src/cpu/base.hh
+++ b/src/cpu/base.hh
@@ -36,7 +36,6 @@
#include "base/statistics.hh"
#include "config/full_system.hh"
-#include "cpu/sampler/sampler.hh"
#include "sim/eventq.hh"
#include "sim/sim_object.hh"
#include "arch/isa_traits.hh"
diff --git a/src/cpu/checker/cpu.hh b/src/cpu/checker/cpu.hh
index 785387e60..b520e1be0 100644
--- a/src/cpu/checker/cpu.hh
+++ b/src/cpu/checker/cpu.hh
@@ -66,7 +66,6 @@ class ThreadContext;
class MemInterface;
class Checkpoint;
class Request;
-class Sampler;
/**
* CheckerCPU class. Dynamically verifies instructions as they are
@@ -374,7 +373,7 @@ class Checker : public CheckerCPU
: CheckerCPU(p)
{ }
- void switchOut(Sampler *s);
+ void switchOut();
void takeOverFrom(BaseCPU *oldCPU);
void verify(DynInstPtr &inst);
diff --git a/src/cpu/checker/cpu_impl.hh b/src/cpu/checker/cpu_impl.hh
index 137e1c46d..81f97726c 100644
--- a/src/cpu/checker/cpu_impl.hh
+++ b/src/cpu/checker/cpu_impl.hh
@@ -236,9 +236,7 @@ Checker<DynInstPtr>::verify(DynInstPtr &completed_inst)
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
+#endif
} else {
#if THE_ISA != MIPS_ISA
// go to the next instruction
@@ -295,7 +293,7 @@ Checker<DynInstPtr>::verify(DynInstPtr &completed_inst)
template <class DynInstPtr>
void
-Checker<DynInstPtr>::switchOut(Sampler *s)
+Checker<DynInstPtr>::switchOut()
{
instList.clear();
}
diff --git a/src/cpu/cpu_models.py b/src/cpu/cpu_models.py
index 1add32745..5b0c6c4da 100644
--- a/src/cpu/cpu_models.py
+++ b/src/cpu/cpu_models.py
@@ -79,18 +79,6 @@ CpuModel('OzoneCPU', 'ozone_exec.cc',
CpuModel('CheckerCPU', 'checker_cpu_exec.cc',
'#include "cpu/checker/cpu.hh"',
{ 'CPU_exec_context': 'CheckerCPU' })
-
-# Maybe there is a more clever way to determine ISA
-# here but since the environment variable isnt passed through
-# here the easiest way is this...
-sub_template = 'not found'
-for argument in sys.argv:
- if 'ALPHA' in argument:
- sub_template = 'AlphaDynInst<AlphaSimpleImpl>'
-
-if sub_template == 'not found':
- sys.exit('NO CPU_exec_context substitution defined for this ISA')
-
CpuModel('O3CPU', 'o3_cpu_exec.cc',
'#include "cpu/o3/isa_specific.hh"',
- { 'CPU_exec_context': sub_template })
+ { 'CPU_exec_context': 'O3DynInst' })
diff --git a/src/cpu/o3/alpha/cpu_builder.cc b/src/cpu/o3/alpha/cpu_builder.cc
index 490305cbf..d61eee4b1 100644
--- a/src/cpu/o3/alpha/cpu_builder.cc
+++ b/src/cpu/o3/alpha/cpu_builder.cc
@@ -91,7 +91,10 @@ Param<unsigned> renameWidth;
Param<unsigned> commitToIEWDelay;
Param<unsigned> renameToIEWDelay;
Param<unsigned> issueToExecuteDelay;
+Param<unsigned> dispatchWidth;
Param<unsigned> issueWidth;
+Param<unsigned> wbWidth;
+Param<unsigned> wbDepth;
SimObjectParam<FUPool *> fuPool;
Param<unsigned> iewToCommitDelay;
@@ -207,7 +210,10 @@ BEGIN_INIT_SIM_OBJECT_PARAMS(DerivO3CPU)
"Issue/Execute/Writeback delay"),
INIT_PARAM(issueToExecuteDelay, "Issue to execute delay (internal"
"to the IEW stage)"),
+ INIT_PARAM(dispatchWidth, "Dispatch width"),
INIT_PARAM(issueWidth, "Issue width"),
+ INIT_PARAM(wbWidth, "Writeback width"),
+ INIT_PARAM(wbDepth, "Writeback depth (number of cycles it can buffer)"),
INIT_PARAM_DFLT(fuPool, "Functional unit pool", NULL),
INIT_PARAM(iewToCommitDelay, "Issue/Execute/Writeback to commit "
@@ -333,7 +339,10 @@ CREATE_SIM_OBJECT(DerivO3CPU)
params->commitToIEWDelay = commitToIEWDelay;
params->renameToIEWDelay = renameToIEWDelay;
params->issueToExecuteDelay = issueToExecuteDelay;
+ params->dispatchWidth = dispatchWidth;
params->issueWidth = issueWidth;
+ params->wbWidth = wbWidth;
+ params->wbDepth = wbDepth;
params->fuPool = fuPool;
params->iewToCommitDelay = iewToCommitDelay;
diff --git a/src/cpu/o3/alpha/impl.hh b/src/cpu/o3/alpha/impl.hh
index 8cd8692c6..b928ae654 100644
--- a/src/cpu/o3/alpha/impl.hh
+++ b/src/cpu/o3/alpha/impl.hh
@@ -36,6 +36,7 @@
#include "cpu/o3/alpha/params.hh"
#include "cpu/o3/cpu_policy.hh"
+
// Forward declarations.
template <class Impl>
class AlphaDynInst;
@@ -88,7 +89,4 @@ struct AlphaSimpleImpl
/** The O3Impl to be used. */
typedef AlphaSimpleImpl O3CPUImpl;
-/** The O3Impl to be used. */
-typedef DynInst O3DynInst;
-
#endif // __CPU_O3_ALPHA_IMPL_HH__
diff --git a/src/cpu/o3/alpha/params.hh b/src/cpu/o3/alpha/params.hh
index b1f2a487d..c618cee08 100644
--- a/src/cpu/o3/alpha/params.hh
+++ b/src/cpu/o3/alpha/params.hh
@@ -54,16 +54,7 @@ class AlphaSimpleParams : public O3Params
#if FULL_SYSTEM
AlphaITB *itb;
AlphaDTB *dtb;
-#else
- std::vector<Process *> workload;
- Process *process;
-#endif // FULL_SYSTEM
-
- MemObject *mem;
-
- BaseCPU *checker;
-
- unsigned decodeToFetchDelay;
+#endif
};
#endif // __CPU_O3_ALPHA_PARAMS_HH__
diff --git a/src/cpu/o3/commit.hh b/src/cpu/o3/commit.hh
index 60b555269..49ff5cdad 100644
--- a/src/cpu/o3/commit.hh
+++ b/src/cpu/o3/commit.hh
@@ -187,11 +187,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. */
+ void 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();
@@ -383,8 +386,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;
diff --git a/src/cpu/o3/commit_impl.hh b/src/cpu/o3/commit_impl.hh
index 06b8e8a95..2eb05afac 100644
--- a/src/cpu/o3/commit_impl.hh
+++ b/src/cpu/o3/commit_impl.hh
@@ -80,7 +80,7 @@ DefaultCommit<Impl>::DefaultCommit(Params *params)
renameWidth(params->renameWidth),
commitWidth(params->commitWidth),
numThreads(params->numberOfThreads),
- switchPending(false),
+ drainPending(false),
switchedOut(false),
trapLatency(params->trapLatency),
fetchTrapLatency(params->fetchTrapLatency)
@@ -351,22 +351,28 @@ DefaultCommit<Impl>::initStage()
template <class Impl>
void
-DefaultCommit<Impl>::switchOut()
+DefaultCommit<Impl>::drain()
{
- switchPending = true;
+ drainPending = true;
}
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()
+{
+}
+
+template <class Impl>
+void
DefaultCommit<Impl>::takeOverFrom()
{
switchedOut = false;
@@ -557,8 +563,9 @@ 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;
}
diff --git a/src/cpu/o3/cpu.cc b/src/cpu/o3/cpu.cc
index feca4cdf2..b182d5ca7 100644
--- a/src/cpu/o3/cpu.cc
+++ b/src/cpu/o3/cpu.cc
@@ -158,7 +158,7 @@ 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)
{
@@ -463,14 +463,13 @@ template <class Impl>
void
FullO3CPU<Impl>::insertThread(unsigned tid)
{
- DPRINTF(O3CPU,"[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
@@ -490,11 +489,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);
@@ -503,16 +505,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(O3CPU,"[tid:%i] Removing thread data");
-#if 0
- //Unbind Int Regs from Rename Map
+ DPRINTF(O3CPU,"[tid:%i] Removing thread from CPU.");
+
+ // 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);
@@ -520,7 +525,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);
@@ -528,27 +533,18 @@ 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);
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
}
@@ -656,7 +652,7 @@ template <class Impl>
void
FullO3CPU<Impl>::suspendContext(int tid)
{
- DPRINTF(O3CPU,"[tid: %i]: Suspended ...\n", tid);
+ DPRINTF(O3CPU,"[tid: %i]: Suspending Thread Context.\n", tid);
unscheduleTickEvent();
_status = Idle;
/*
@@ -676,27 +672,26 @@ template <class Impl>
void
FullO3CPU<Impl>::deallocateContext(int tid)
{
- DPRINTF(O3CPU,"[tid:%i]: Deallocating ...", tid);
-/*
+ DPRINTF(O3CPU,"[tid:%i]: Deallocating Thread Context", tid);
+
//Remove From Active List, if Active
- list<unsigned>::iterator isActive = find(
- activeThreads.begin(), activeThreads.end(), tid);
+ list<unsigned>::iterator thread_it =
+ find(activeThreads.begin(), activeThreads.end(), tid);
- if (isActive != activeThreads.end()) {
+ if (thread_it != activeThreads.end()) {
DPRINTF(O3CPU,"[tid:%i]: Removing from active threads list\n",
tid);
- activeThreads.erase(isActive);
+ activeThreads.erase(thread_it);
removeThread(tid);
}
-*/
}
template <class Impl>
void
FullO3CPU<Impl>::haltContext(int tid)
{
- DPRINTF(O3CPU,"[tid:%i]: Halted ...", tid);
+ DPRINTF(O3CPU,"[tid:%i]: Halting Thread Context", tid);
/*
//Remove From Active List, if Active
list<unsigned>::iterator isActive = find(
@@ -713,47 +708,72 @@ FullO3CPU<Impl>::haltContext(int tid)
}
template <class Impl>
-void
-FullO3CPU<Impl>::switchOut(Sampler *_sampler)
+bool
+FullO3CPU<Impl>::drain(Event *drain_event)
{
- sampler = _sampler;
- switchCount = 0;
- fetch.switchOut();
- decode.switchOut();
- rename.switchOut();
- iew.switchOut();
- commit.switchOut();
+ drainCount = 0;
+ drainEvent = drain_event;
+ fetch.drain();
+ decode.drain();
+ rename.drain();
+ iew.drain();
+ commit.drain();
// Wake the CPU and record activity so everything can drain out if
// the CPU is currently idle.
wakeCPU();
activityRec.activity();
+
+ return false;
}
template <class Impl>
void
-FullO3CPU<Impl>::signalSwitched()
-{
- if (++switchCount == NumStages) {
- fetch.doSwitchOut();
- rename.doSwitchOut();
- commit.doSwitchOut();
- instList.clear();
- while (!removeList.empty()) {
- removeList.pop();
- }
+FullO3CPU<Impl>::resume()
+{
+ if (_status == SwitchedOut)
+ return;
+ fetch.resume();
+ decode.resume();
+ rename.resume();
+ iew.resume();
+ commit.resume();
-#if USE_CHECKER
- if (checker)
- checker->switchOut(sampler);
-#endif
+ if (!tickEvent.scheduled())
+ tickEvent.schedule(curTick);
+ _status = Running;
+}
+template <class Impl>
+void
+FullO3CPU<Impl>::signalDrained()
+{
+ if (++drainCount == NumStages) {
if (tickEvent.scheduled())
tickEvent.squash();
- sampler->signalSwitched();
- _status = SwitchedOut;
+ _status = Drained;
+ drainEvent->process();
}
- 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>
diff --git a/src/cpu/o3/cpu.hh b/src/cpu/o3/cpu.hh
index 1cff6142d..cf3747601 100644
--- a/src/cpu/o3/cpu.hh
+++ b/src/cpu/o3/cpu.hh
@@ -57,6 +57,8 @@ class Checker;
class ThreadContext;
template <class>
class O3ThreadContext;
+
+class Checkpoint;
class MemObject;
class Process;
@@ -109,6 +111,7 @@ class FullO3CPU : public BaseO3CPU
Idle,
Halted,
Blocked,
+ Drained,
SwitchedOut
};
@@ -270,14 +273,21 @@ class FullO3CPU : public BaseO3CPU
*/
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 bool 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()
@@ -550,11 +560,11 @@ class FullO3CPU : public BaseO3CPU
/** 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;
diff --git a/src/cpu/o3/decode.hh b/src/cpu/o3/decode.hh
index 1edf3335d..1e96f1884 100644
--- a/src/cpu/o3/decode.hh
+++ b/src/cpu/o3/decode.hh
@@ -109,8 +109,14 @@ class DefaultDecode
/** Sets pointer to list of active threads. */
void setActiveThreads(std::list<unsigned> *at_ptr);
+ /** Drains the decode stage. */
+ void 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();
diff --git a/src/cpu/o3/decode_impl.hh b/src/cpu/o3/decode_impl.hh
index 16be01784..71637883b 100644
--- a/src/cpu/o3/decode_impl.hh
+++ b/src/cpu/o3/decode_impl.hh
@@ -166,10 +166,10 @@ DefaultDecode<Impl>::setActiveThreads(list<unsigned> *at_ptr)
template <class Impl>
void
-DefaultDecode<Impl>::switchOut()
+DefaultDecode<Impl>::drain()
{
- // Decode can immediately switch out.
- cpu->signalSwitched();
+ // Decode is done draining at any time.
+ cpu->signalDrained();
}
template <class Impl>
diff --git a/src/cpu/o3/dyn_inst.hh b/src/cpu/o3/dyn_inst.hh
new file mode 100644
index 000000000..a2cdf2dba
--- /dev/null
+++ b/src/cpu/o3/dyn_inst.hh
@@ -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__
diff --git a/src/cpu/o3/fetch.hh b/src/cpu/o3/fetch.hh
index 7fcd21b7d..9611f0455 100644
--- a/src/cpu/o3/fetch.hh
+++ b/src/cpu/o3/fetch.hh
@@ -40,8 +40,6 @@
#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
@@ -182,11 +180,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. */
+ void 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();
@@ -423,6 +424,9 @@ class DefaultFetch
*/
bool interruptPending;
+ /** Is there a drain pending. */
+ bool drainPending;
+
/** Records if fetch is switched out. */
bool switchedOut;
diff --git a/src/cpu/o3/fetch_impl.hh b/src/cpu/o3/fetch_impl.hh
index 60eb76d17..500b5304e 100644
--- a/src/cpu/o3/fetch_impl.hh
+++ b/src/cpu/o3/fetch_impl.hh
@@ -109,6 +109,7 @@ DefaultFetch<Impl>::DefaultFetch(Params *params)
numThreads(params->numberOfThreads),
numFetchingThreads(params->smtNumFetchingThreads),
interruptPending(false),
+ drainPending(false),
switchedOut(false)
{
if (numThreads > Impl::MaxThreads)
@@ -353,7 +354,8 @@ DefaultFetch<Impl>::processCacheCompletion(PacketPtr pkt)
// to return.
if (fetchStatus[tid] != IcacheWaitResponse ||
pkt->req != memReq[tid] ||
- isSwitchedOut()) {
+ isSwitchedOut() ||
+ drainPending) {
++fetchIcacheSquashes;
delete pkt->req;
delete pkt;
@@ -384,17 +386,25 @@ DefaultFetch<Impl>::processCacheCompletion(PacketPtr pkt)
template <class Impl>
void
-DefaultFetch<Impl>::switchOut()
+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;
}
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();
}
@@ -498,7 +508,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) || drainPending) {
// 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
diff --git a/src/cpu/o3/iew.hh b/src/cpu/o3/iew.hh
index 2af68d8fc..774b6dcbd 100644
--- a/src/cpu/o3/iew.hh
+++ b/src/cpu/o3/iew.hh
@@ -143,11 +143,14 @@ class DefaultIEW
/** Sets pointer to the scoreboard. */
void setScoreboard(Scoreboard *sb_ptr);
- /** Starts switch out of IEW stage. */
- void switchOut();
+ /** Drains IEW stage. */
+ void 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 +207,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.
@@ -384,11 +426,8 @@ 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;
@@ -403,6 +442,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;
diff --git a/src/cpu/o3/iew_impl.hh b/src/cpu/o3/iew_impl.hh
index 8e6fd46a1..c3aa748ae 100644
--- a/src/cpu/o3/iew_impl.hh
+++ b/src/cpu/o3/iew_impl.hh
@@ -50,8 +50,10 @@ DefaultIEW<Impl>::DefaultIEW(Params *params)
commitToIEWDelay(params->commitToIEWDelay),
renameToIEWDelay(params->renameToIEWDelay),
issueToExecuteDelay(params->issueToExecuteDelay),
- issueReadWidth(params->issueWidth),
+ dispatchWidth(params->dispatchWidth),
issueWidth(params->issueWidth),
+ wbOutstanding(0),
+ wbWidth(params->wbWidth),
numThreads(params->numberOfThreads),
switchedOut(false)
{
@@ -74,8 +76,12 @@ DefaultIEW<Impl>::DefaultIEW(Params *params)
fetchRedirect[i] = false;
}
+ wbMax = wbWidth * params->wbDepth;
+
updateLSQNextCycle = false;
+ ableToIssue = true;
+
skidBufferMax = (3 * (renameToIEWDelay * params->renameWidth)) + issueWidth;
}
@@ -349,15 +355,21 @@ DefaultIEW<Impl>::setScoreboard(Scoreboard *sb_ptr)
template <class Impl>
void
-DefaultIEW<Impl>::switchOut()
+DefaultIEW<Impl>::drain()
+{
+ // IEW is ready to drain at any time.
+ cpu->signalDrained();
+}
+
+template <class Impl>
+void
+DefaultIEW<Impl>::resume()
{
- // IEW is ready to switch out at any time.
- cpu->signalSwitched();
}
template <class Impl>
void
-DefaultIEW<Impl>::doSwitchOut()
+DefaultIEW<Impl>::switchOut()
{
// Clear any state.
switchedOut = true;
@@ -559,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.
@@ -937,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();
@@ -1189,6 +1201,7 @@ DefaultIEW<Impl>::executeInsts()
++iewExecSquashedInsts;
+ decrWb(inst->seqNum);
continue;
}
@@ -1351,6 +1364,8 @@ DefaultIEW<Impl>::writebackInsts()
}
writebackCount[tid]++;
}
+
+ decrWb(inst->seqNum);
}
}
diff --git a/src/cpu/o3/inst_queue_impl.hh b/src/cpu/o3/inst_queue_impl.hh
index b99bd0900..36e0842be 100644
--- a/src/cpu/o3/inst_queue_impl.hh
+++ b/src/cpu/o3/inst_queue_impl.hh
@@ -687,6 +687,7 @@ InstructionQueue<Impl>::scheduleReadyInsts()
int total_issued = 0;
while (total_issued < totalWidth &&
+ iewStage->canIssue() &&
order_it != order_end_it) {
OpClass op_class = (*order_it).queueType;
@@ -784,6 +785,7 @@ InstructionQueue<Impl>::scheduleReadyInsts()
listOrder.erase(order_it++);
statIssuedInstType[tid][op_class]++;
+ iewStage->incrWb(issuing_inst->seqNum);
} else {
statFuBusy[op_class]++;
fuBusy[tid]++;
diff --git a/src/cpu/o3/lsq_unit_impl.hh b/src/cpu/o3/lsq_unit_impl.hh
index 714acb2ef..bb3da7eec 100644
--- a/src/cpu/o3/lsq_unit_impl.hh
+++ b/src/cpu/o3/lsq_unit_impl.hh
@@ -77,6 +77,7 @@ LSQUnit<Impl>::completeDataAccess(PacketPtr pkt)
//iewStage->ldstQueue.removeMSHR(inst->threadNumber,inst->seqNum);
if (isSwitchedOut() || inst->isSquashed()) {
+ iewStage->decrWb(inst->seqNum);
delete state;
delete pkt;
return;
diff --git a/src/cpu/o3/params.hh b/src/cpu/o3/params.hh
index 69a1bb937..ed53fa97a 100755
--- a/src/cpu/o3/params.hh
+++ b/src/cpu/o3/params.hh
@@ -47,6 +47,18 @@ class O3Params : public BaseO3CPU::Params
unsigned activity;
//
+ // Pointers to key objects
+ //
+#if !FULL_SYSTEM
+ std::vector<Process *> workload;
+ Process *process;
+#endif // FULL_SYSTEM
+
+ MemObject *mem;
+
+ BaseCPU *checker;
+
+ //
// Caches
//
// MemInterface *icacheInterface;
@@ -86,7 +98,10 @@ class O3Params : public BaseO3CPU::Params
unsigned commitToIEWDelay;
unsigned renameToIEWDelay;
unsigned issueToExecuteDelay;
+ unsigned dispatchWidth;
unsigned issueWidth;
+ unsigned wbWidth;
+ unsigned wbDepth;
FUPool *fuPool;
//
diff --git a/src/cpu/o3/rename.hh b/src/cpu/o3/rename.hh
index 581fc8f81..538dd9bb4 100644
--- a/src/cpu/o3/rename.hh
+++ b/src/cpu/o3/rename.hh
@@ -157,12 +157,15 @@ class DefaultRename
/** Sets pointer to the scoreboard. */
void setScoreboard(Scoreboard *_scoreboard);
+ /** Drains the rename stage. */
+ void drain();
+
+ /** Resumes execution after a drain. */
+ void resume() { }
+
/** Switches out the rename stage. */
void switchOut();
- /** Completes the switch out. */
- void doSwitchOut();
-
/** Takes over from another CPU's thread. */
void takeOverFrom();
diff --git a/src/cpu/o3/rename_impl.hh b/src/cpu/o3/rename_impl.hh
index df8b7f9da..fddbae3db 100644
--- a/src/cpu/o3/rename_impl.hh
+++ b/src/cpu/o3/rename_impl.hh
@@ -258,15 +258,15 @@ DefaultRename<Impl>::setScoreboard(Scoreboard *_scoreboard)
template <class Impl>
void
-DefaultRename<Impl>::switchOut()
+DefaultRename<Impl>::drain()
{
// Rename is ready to switch out at any time.
- cpu->signalSwitched();
+ cpu->signalDrained();
}
template <class Impl>
void
-DefaultRename<Impl>::doSwitchOut()
+DefaultRename<Impl>::switchOut()
{
// Clear any state, fix up the rename map.
for (int i = 0; i < numThreads; i++) {
diff --git a/src/cpu/ozone/cpu.hh b/src/cpu/ozone/cpu.hh
index f726ac99b..8993781ea 100644
--- a/src/cpu/ozone/cpu.hh
+++ b/src/cpu/ozone/cpu.hh
@@ -55,7 +55,6 @@ class AlphaDTB;
class PhysicalMemory;
class MemoryController;
-class Sampler;
class RemoteGDB;
class GDBListener;
@@ -356,12 +355,10 @@ class OzoneCPU : public BaseCPU
int cpuId;
- void switchOut(Sampler *sampler);
+ void switchOut();
void signalSwitched();
void takeOverFrom(BaseCPU *oldCPU);
- Sampler *sampler;
-
int switchCount;
#if FULL_SYSTEM
diff --git a/src/cpu/ozone/cpu_impl.hh b/src/cpu/ozone/cpu_impl.hh
index 2cdc8a3da..ccb1c8418 100644
--- a/src/cpu/ozone/cpu_impl.hh
+++ b/src/cpu/ozone/cpu_impl.hh
@@ -244,9 +244,8 @@ OzoneCPU<Impl>::~OzoneCPU()
template <class Impl>
void
-OzoneCPU<Impl>::switchOut(Sampler *_sampler)
+OzoneCPU<Impl>::switchOut()
{
- sampler = _sampler;
switchCount = 0;
// Front end needs state from back end, so switch out the back end first.
backEnd->switchOut();
@@ -262,13 +261,12 @@ OzoneCPU<Impl>::signalSwitched()
frontEnd->doSwitchOut();
#if USE_CHECKER
if (checker)
- checker->switchOut(sampler);
+ checker->switchOut();
#endif
_status = SwitchedOut;
if (tickEvent.scheduled())
tickEvent.squash();
- sampler->signalSwitched();
}
assert(switchCount <= 2);
}
diff --git a/src/cpu/simple/base.cc b/src/cpu/simple/base.cc
index db5dd2acf..a50541189 100644
--- a/src/cpu/simple/base.cc
+++ b/src/cpu/simple/base.cc
@@ -41,7 +41,6 @@
#include "cpu/base.hh"
#include "cpu/exetrace.hh"
#include "cpu/profile.hh"
-#include "cpu/sampler/sampler.hh"
#include "cpu/simple/base.hh"
#include "cpu/simple_thread.hh"
#include "cpu/smt.hh"
diff --git a/src/cpu/simple/base.hh b/src/cpu/simple/base.hh
index 39bc86050..57cfa3c2c 100644
--- a/src/cpu/simple/base.hh
+++ b/src/cpu/simple/base.hh
@@ -38,7 +38,6 @@
#include "cpu/base.hh"
#include "cpu/simple_thread.hh"
#include "cpu/pc_event.hh"
-#include "cpu/sampler/sampler.hh"
#include "cpu/static_inst.hh"
#include "mem/packet.hh"
#include "mem/port.hh"
@@ -128,11 +127,6 @@ class BaseSimpleCPU : public BaseCPU
// Static data storage
TheISA::IntReg dataReg;
- // Pointer to the sampler that is telling us to switchover.
- // Used to signal the completion of the pipe drain and schedule
- // the next switchover
- Sampler *sampler;
-
StaticInstPtr curStaticInst;
void checkForInterrupts();
diff --git a/src/cpu/simple/timing.cc b/src/cpu/simple/timing.cc
index d5bdcfa9b..ad04c8d3b 100644
--- a/src/cpu/simple/timing.cc
+++ b/src/cpu/simple/timing.cc
@@ -88,7 +88,7 @@ TimingSimpleCPU::TimingSimpleCPU(Params *p)
{
_status = Idle;
ifetch_pkt = dcache_pkt = NULL;
- quiesceEvent = NULL;
+ drainEvent = NULL;
state = SimObject::Timing;
}
@@ -112,17 +112,16 @@ TimingSimpleCPU::unserialize(Checkpoint *cp, const string &section)
}
bool
-TimingSimpleCPU::quiesce(Event *quiesce_event)
+TimingSimpleCPU::drain(Event *drain_event)
{
- // TimingSimpleCPU is ready to quiesce if it's not waiting for
+ // TimingSimpleCPU is ready to drain if it's not waiting for
// an access to complete.
if (status() == Idle || status() == Running || status() == SwitchedOut) {
- DPRINTF(Config, "Ready to quiesce\n");
+ changeState(SimObject::DrainedTiming);
return false;
} else {
- DPRINTF(Config, "Waiting to quiesce\n");
- changeState(SimObject::Quiescing);
- quiesceEvent = quiesce_event;
+ changeState(SimObject::Draining);
+ drainEvent = drain_event;
return true;
}
}
@@ -422,8 +421,8 @@ TimingSimpleCPU::completeIfetch(Packet *pkt)
delete pkt->req;
delete pkt;
- if (getState() == SimObject::Quiescing) {
- completeQuiesce();
+ if (getState() == SimObject::Draining) {
+ completeDrain();
return;
}
@@ -479,8 +478,8 @@ TimingSimpleCPU::completeDataAccess(Packet *pkt)
assert(_status == DcacheWaitResponse);
_status = Running;
- if (getState() == SimObject::Quiescing) {
- completeQuiesce();
+ if (getState() == SimObject::Draining) {
+ completeDrain();
delete pkt->req;
delete pkt;
@@ -499,11 +498,11 @@ TimingSimpleCPU::completeDataAccess(Packet *pkt)
void
-TimingSimpleCPU::completeQuiesce()
+TimingSimpleCPU::completeDrain()
{
- DPRINTF(Config, "Done quiescing\n");
- changeState(SimObject::QuiescedTiming);
- quiesceEvent->process();
+ DPRINTF(Config, "Done draining\n");
+ changeState(SimObject::DrainedTiming);
+ drainEvent->process();
}
bool
diff --git a/src/cpu/simple/timing.hh b/src/cpu/simple/timing.hh
index d91144e4a..c360e553e 100644
--- a/src/cpu/simple/timing.hh
+++ b/src/cpu/simple/timing.hh
@@ -64,7 +64,7 @@ class TimingSimpleCPU : public BaseSimpleCPU
Status status() const { return _status; }
- Event *quiesceEvent;
+ Event *drainEvent;
private:
@@ -133,7 +133,7 @@ class TimingSimpleCPU : public BaseSimpleCPU
virtual void serialize(std::ostream &os);
virtual void unserialize(Checkpoint *cp, const std::string &section);
- virtual bool quiesce(Event *quiesce_event);
+ virtual bool drain(Event *drain_event);
virtual void resume();
virtual void setMemoryMode(State new_mode);
@@ -154,7 +154,7 @@ class TimingSimpleCPU : public BaseSimpleCPU
void completeDataAccess(Packet *);
void advanceInst(Fault fault);
private:
- void completeQuiesce();
+ void completeDrain();
};
#endif // __CPU_SIMPLE_TIMING_HH__
diff --git a/src/cpu/static_inst.hh b/src/cpu/static_inst.hh
index a98078634..ea1a65148 100644
--- a/src/cpu/static_inst.hh
+++ b/src/cpu/static_inst.hh
@@ -39,6 +39,7 @@
#include "base/misc.hh"
#include "base/refcnt.hh"
#include "cpu/op_class.hh"
+#include "cpu/o3/dyn_inst.hh"
#include "sim/host.hh"
#include "arch/isa_traits.hh"
@@ -51,9 +52,6 @@ class DynInst;
class Packet;
template <class Impl>
-class AlphaDynInst;
-
-template <class Impl>
class OzoneDynInst;
class CheckerCPU;
diff --git a/src/dev/ide_ctrl.cc b/src/dev/ide_ctrl.cc
index 63435e87c..5ffc02d34 100644
--- a/src/dev/ide_ctrl.cc
+++ b/src/dev/ide_ctrl.cc
@@ -227,177 +227,143 @@ IdeController::setDmaComplete(IdeDisk *disk)
// Read and write handling
////
-void
-IdeController::readConfig(int offset, uint8_t *data)
+Tick
+IdeController::readConfig(Packet *pkt)
{
- if (offset < PCI_DEVICE_SPECIFIC) {
- PciDev::readConfig(offset, data);
- } else if (offset >= IDE_CTRL_CONF_START &&
- (offset + 1) <= IDE_CTRL_CONF_END) {
+ int offset = pkt->getAddr() & PCI_CONFIG_SIZE;
+ if (offset < PCI_DEVICE_SPECIFIC)
+ return PciDev::readConfig(pkt);
+ assert(offset >= IDE_CTRL_CONF_START && (offset + 1) <= IDE_CTRL_CONF_END);
+ pkt->allocate();
+
+ switch (pkt->getSize()) {
+ case sizeof(uint8_t):
switch (offset) {
case IDE_CTRL_CONF_DEV_TIMING:
- *data = config_regs.sidetim;
+ pkt->set<uint8_t>(config_regs.sidetim);
break;
case IDE_CTRL_CONF_UDMA_CNTRL:
- *data = config_regs.udmactl;
+ pkt->set<uint8_t>(config_regs.udmactl);
break;
case IDE_CTRL_CONF_PRIM_TIMING+1:
- *data = htole(config_regs.idetim0) >> 8;
+ pkt->set<uint8_t>(htole(config_regs.idetim0) >> 8);
break;
case IDE_CTRL_CONF_SEC_TIMING+1:
- *data = htole(config_regs.idetim1) >> 8;
+ pkt->set<uint8_t>(htole(config_regs.idetim1) >> 8);
break;
case IDE_CTRL_CONF_IDE_CONFIG:
- *data = htole(config_regs.ideconfig) & 0xFF;
+ pkt->set<uint8_t>(htole(config_regs.ideconfig) & 0xFF);
break;
case IDE_CTRL_CONF_IDE_CONFIG+1:
- *data = htole(config_regs.ideconfig) >> 8;
+ pkt->set<uint8_t>(htole(config_regs.ideconfig) >> 8);
break;
default:
panic("Invalid PCI configuration read for size 1 at offset: %#x!\n",
offset);
}
-
- } else {
- panic("Read of unimplemented PCI config. register: %x\n", offset);
- }
- DPRINTF(IdeCtrl, "PCI read offset: %#x size: 1 data: %#x\n",
- offset, (uint32_t)*data);
-}
-
-void
-IdeController::readConfig(int offset, uint16_t *data)
-{
- if (offset < PCI_DEVICE_SPECIFIC) {
- PciDev::readConfig(offset, data);
- } else if (offset >= IDE_CTRL_CONF_START &&
- (offset + 2) <= IDE_CTRL_CONF_END) {
-
+ DPRINTF(IdeCtrl, "PCI read offset: %#x size: 1 data: %#x\n", offset,
+ (uint32_t)pkt->get<uint8_t>());
+ break;
+ case sizeof(uint16_t):
switch (offset) {
case IDE_CTRL_CONF_PRIM_TIMING:
- *data = config_regs.idetim0;
+ pkt->set<uint16_t>(config_regs.idetim0);
break;
case IDE_CTRL_CONF_SEC_TIMING:
- *data = config_regs.idetim1;
+ pkt->set<uint16_t>(config_regs.idetim1);
break;
case IDE_CTRL_CONF_UDMA_TIMING:
- *data = config_regs.udmatim;
+ pkt->set<uint16_t>(config_regs.udmatim);
break;
case IDE_CTRL_CONF_IDE_CONFIG:
- *data = config_regs.ideconfig;
+ pkt->set<uint16_t>(config_regs.ideconfig);
break;
default:
panic("Invalid PCI configuration read for size 2 offset: %#x!\n",
offset);
}
-
- } else {
- panic("Read of unimplemented PCI config. register: %x\n", offset);
+ DPRINTF(IdeCtrl, "PCI read offset: %#x size: 2 data: %#x\n", offset,
+ (uint32_t)pkt->get<uint16_t>());
+ break;
+ case sizeof(uint32_t):
+ panic("No 32bit reads implemented for this device.");
+ DPRINTF(IdeCtrl, "PCI read offset: %#x size: 4 data: %#x\n", offset,
+ (uint32_t)pkt->get<uint32_t>());
+ break;
+ default:
+ panic("invalid access size(?) for PCI configspace!\n");
}
- DPRINTF(IdeCtrl, "PCI read offset: %#x size: 2 data: %#x\n", offset, *data);
-}
+ pkt->result = Packet::Success;
+ return configDelay;
-void
-IdeController::readConfig(int offset, uint32_t *data)
-{
- if (offset < PCI_DEVICE_SPECIFIC) {
- PciDev::readConfig(offset, data);
- } else {
- panic("Read of unimplemented PCI config. register: %x\n", offset);
- }
- DPRINTF(IdeCtrl, "PCI read offset: %#x size: 4 data: %#x\n", offset, *data);
}
-void
-IdeController::writeConfig(int offset, const uint8_t data)
-{
- if (offset < PCI_DEVICE_SPECIFIC) {
- PciDev::writeConfig(offset, data);
- } else if (offset >= IDE_CTRL_CONF_START &&
- (offset + 1) <= IDE_CTRL_CONF_END) {
- switch (offset) {
- case IDE_CTRL_CONF_DEV_TIMING:
- config_regs.sidetim = data;
- break;
- case IDE_CTRL_CONF_UDMA_CNTRL:
- config_regs.udmactl = data;
- break;
- case IDE_CTRL_CONF_IDE_CONFIG:
- config_regs.ideconfig = (config_regs.ideconfig & 0xFF00) | (data);
- break;
- case IDE_CTRL_CONF_IDE_CONFIG+1:
- config_regs.ideconfig = (config_regs.ideconfig & 0x00FF) | data << 8;
- break;
- default:
- panic("Invalid PCI configuration write for size 1 offset: %#x!\n",
- offset);
- }
- } else {
- panic("Read of unimplemented PCI config. register: %x\n", offset);
- }
- DPRINTF(IdeCtrl, "PCI write offset: %#x size: 1 data: %#x\n",
- offset, (uint32_t)data);
-}
-
-void
-IdeController::writeConfig(int offset, const uint16_t data)
+Tick
+IdeController::writeConfig(Packet *pkt)
{
+ int offset = pkt->getAddr() & PCI_CONFIG_SIZE;
if (offset < PCI_DEVICE_SPECIFIC) {
- PciDev::writeConfig(offset, data);
- } else if (offset >= IDE_CTRL_CONF_START &&
- (offset + 2) <= IDE_CTRL_CONF_END) {
+ PciDev::writeConfig(pkt);
+ } else {
+ assert(offset >= IDE_CTRL_CONF_START && (offset + 1) <= IDE_CTRL_CONF_END);
- switch (offset) {
- case IDE_CTRL_CONF_PRIM_TIMING:
- config_regs.idetim0 = data;
- break;
- case IDE_CTRL_CONF_SEC_TIMING:
- config_regs.idetim1 = data;
+ switch (pkt->getSize()) {
+ case sizeof(uint8_t):
+ switch (offset) {
+ case IDE_CTRL_CONF_DEV_TIMING:
+ config_regs.sidetim = pkt->get<uint8_t>();
+ break;
+ case IDE_CTRL_CONF_UDMA_CNTRL:
+ config_regs.udmactl = pkt->get<uint8_t>();
+ break;
+ case IDE_CTRL_CONF_IDE_CONFIG:
+ config_regs.ideconfig = (config_regs.ideconfig & 0xFF00) |
+ (pkt->get<uint8_t>());
+ break;
+ case IDE_CTRL_CONF_IDE_CONFIG+1:
+ config_regs.ideconfig = (config_regs.ideconfig & 0x00FF) |
+ pkt->get<uint8_t>() << 8;
+ break;
+ default:
+ panic("Invalid PCI configuration write for size 1 offset: %#x!\n",
+ offset);
+ }
+ DPRINTF(IdeCtrl, "PCI write offset: %#x size: 1 data: %#x\n",
+ offset, (uint32_t)pkt->get<uint8_t>());
break;
- case IDE_CTRL_CONF_UDMA_TIMING:
- config_regs.udmatim = data;
+ case sizeof(uint16_t):
+ switch (offset) {
+ case IDE_CTRL_CONF_PRIM_TIMING:
+ config_regs.idetim0 = pkt->get<uint16_t>();
+ break;
+ case IDE_CTRL_CONF_SEC_TIMING:
+ config_regs.idetim1 = pkt->get<uint16_t>();
+ break;
+ case IDE_CTRL_CONF_UDMA_TIMING:
+ config_regs.udmatim = pkt->get<uint16_t>();
+ break;
+ case IDE_CTRL_CONF_IDE_CONFIG:
+ config_regs.ideconfig = pkt->get<uint16_t>();
+ break;
+ default:
+ panic("Invalid PCI configuration write for size 2 offset: %#x!\n",
+ offset);
+ }
+ DPRINTF(IdeCtrl, "PCI write offset: %#x size: 2 data: %#x\n",
+ offset, (uint32_t)pkt->get<uint16_t>());
break;
- case IDE_CTRL_CONF_IDE_CONFIG:
- config_regs.ideconfig = data;
+ case sizeof(uint32_t):
+ panic("Write of unimplemented PCI config. register: %x\n", offset);
break;
default:
- panic("Invalid PCI configuration write for size 2 offset: %#x!\n",
- offset);
+ panic("invalid access size(?) for PCI configspace!\n");
}
-
- } else {
- panic("Write of unimplemented PCI config. register: %x\n", offset);
}
- DPRINTF(IdeCtrl, "PCI write offset: %#x size: 2 data: %#x\n", offset, data);
-
- /* Trap command register writes and enable IO/BM as appropriate. */
- if (offset == PCI_COMMAND) {
- if (letoh(config.command) & PCI_CMD_IOSE)
- io_enabled = true;
- else
- io_enabled = false;
-
- if (letoh(config.command) & PCI_CMD_BME)
- bm_enabled = true;
- else
- bm_enabled = false;
- }
-
-}
-
-void
-IdeController::writeConfig(int offset, const uint32_t data)
-{
- if (offset < PCI_DEVICE_SPECIFIC) {
- PciDev::writeConfig(offset, data);
- } else {
- panic("Read of unimplemented PCI config. register: %x\n", offset);
- }
-
- DPRINTF(IdeCtrl, "PCI write offset: %#x size: 4 data: %#x\n", offset, data);
+ /* Trap command register writes and enable IO/BM as appropriate as well as
+ * BARs. */
switch(offset) {
case PCI0_BASE_ADDR0:
if (BARAddrs[0] != 0)
@@ -423,9 +389,24 @@ IdeController::writeConfig(int offset, const uint32_t data)
if (BARAddrs[4] != 0)
bmi_addr = BARAddrs[4];
break;
+
+ case PCI_COMMAND:
+ if (letoh(config.command) & PCI_CMD_IOSE)
+ io_enabled = true;
+ else
+ io_enabled = false;
+
+ if (letoh(config.command) & PCI_CMD_BME)
+ bm_enabled = true;
+ else
+ bm_enabled = false;
+ break;
}
+ pkt->result = Packet::Success;
+ return configDelay;
}
+
Tick
IdeController::read(Packet *pkt)
{
@@ -770,7 +751,6 @@ BEGIN_DECLARE_SIM_OBJECT_PARAMS(IdeController)
SimObjectParam<System *> system;
SimObjectParam<Platform *> platform;
- SimObjectParam<PciConfigAll *> configspace;
SimObjectParam<PciConfigData *> configdata;
Param<uint32_t> pci_bus;
Param<uint32_t> pci_dev;
@@ -784,7 +764,6 @@ BEGIN_INIT_SIM_OBJECT_PARAMS(IdeController)
INIT_PARAM(system, "System pointer"),
INIT_PARAM(platform, "Platform pointer"),
- INIT_PARAM(configspace, "PCI Configspace"),
INIT_PARAM(configdata, "PCI Config data"),
INIT_PARAM(pci_bus, "PCI bus ID"),
INIT_PARAM(pci_dev, "PCI device number"),
@@ -800,7 +779,6 @@ CREATE_SIM_OBJECT(IdeController)
params->name = getInstanceName();
params->platform = platform;
params->system = system;
- params->configSpace = configspace;
params->configData = configdata;
params->busNum = pci_bus;
params->deviceNum = pci_dev;
diff --git a/src/dev/ide_ctrl.hh b/src/dev/ide_ctrl.hh
index 1d30c8b31..5842d322e 100644
--- a/src/dev/ide_ctrl.hh
+++ b/src/dev/ide_ctrl.hh
@@ -204,12 +204,8 @@ class IdeController : public PciDev
IdeController(Params *p);
~IdeController();
- virtual void writeConfig(int offset, const uint8_t data);
- virtual void writeConfig(int offset, const uint16_t data);
- virtual void writeConfig(int offset, const uint32_t data);
- virtual void readConfig(int offset, uint8_t *data);
- virtual void readConfig(int offset, uint16_t *data);
- virtual void readConfig(int offset, uint32_t *data);
+ virtual Tick writeConfig(Packet *pkt);
+ virtual Tick readConfig(Packet *pkt);
void setDmaComplete(IdeDisk *disk);
diff --git a/src/dev/io_device.cc b/src/dev/io_device.cc
index e769ef037..cb4850108 100644
--- a/src/dev/io_device.cc
+++ b/src/dev/io_device.cc
@@ -34,8 +34,8 @@
#include "sim/builder.hh"
-PioPort::PioPort(PioDevice *dev, Platform *p)
- : Port(dev->name() + "-pioport"), device(dev), platform(p)
+PioPort::PioPort(PioDevice *dev, Platform *p, std::string pname)
+ : Port(dev->name() + pname), device(dev), platform(p)
{ }
@@ -79,19 +79,23 @@ PioPort::SendEvent::process()
port->transmitList.push_back(packet);
}
+void
+PioPort::resendNacked(Packet *pkt) {
+ pkt->reinitNacked();
+ if (transmitList.size()) {
+ transmitList.push_front(pkt);
+ } else {
+ if (!Port::sendTiming(pkt))
+ transmitList.push_front(pkt);
+ }
+};
bool
PioPort::recvTiming(Packet *pkt)
{
if (pkt->result == Packet::Nacked) {
- pkt->reinitNacked();
- if (transmitList.size()) {
- transmitList.push_front(pkt);
- } else {
- if (!Port::sendTiming(pkt))
- transmitList.push_front(pkt);
- }
+ resendNacked(pkt);
} else {
Tick latency = device->recvAtomic(pkt);
// turn packet around to go back to requester
diff --git a/src/dev/io_device.hh b/src/dev/io_device.hh
index a2b61c7f4..40edf6875 100644
--- a/src/dev/io_device.hh
+++ b/src/dev/io_device.hh
@@ -82,6 +82,8 @@ class PioPort : public Port
virtual void getDeviceAddressRanges(AddrRangeList &resp, AddrRangeList &snoop);
+ void resendNacked(Packet *pkt);
+
/**
* This class is used to implemented sendTiming() with a delay. When a delay
* is requested a new event is created. When the event time expires it
@@ -113,7 +115,7 @@ class PioPort : public Port
virtual void recvRetry();
public:
- PioPort(PioDevice *dev, Platform *p);
+ PioPort(PioDevice *dev, Platform *p, std::string pname = "-pioport");
friend class PioPort::SendEvent;
};
diff --git a/src/dev/ns_gige.cc b/src/dev/ns_gige.cc
index 360fe8c9b..179a2c62d 100644
--- a/src/dev/ns_gige.cc
+++ b/src/dev/ns_gige.cc
@@ -465,11 +465,12 @@ NSGigE::regStats()
/**
* This is to write to the PCI general configuration registers
*/
-void
-NSGigE::writeConfig(int offset, const uint16_t data)
+Tick
+NSGigE::writeConfig(Packet *pkt)
{
+ int offset = pkt->getAddr() & PCI_CONFIG_SIZE;
if (offset < PCI_DEVICE_SPECIFIC)
- PciDev::writeConfig(offset, data);
+ PciDev::writeConfig(pkt);
else
panic("Device specific PCI config space not implemented!\n");
@@ -484,6 +485,8 @@ NSGigE::writeConfig(int offset, const uint16_t data)
ioEnable = false;
break;
}
+ pkt->result = Packet::Success;
+ return configDelay;
}
/**
@@ -508,14 +511,7 @@ NSGigE::read(Packet *pkt)
if (daddr > LAST && daddr <= RESERVED) {
panic("Accessing reserved register");
} else if (daddr > RESERVED && daddr <= 0x3FC) {
- if (pkt->getSize() == sizeof(uint8_t))
- readConfig(daddr & 0xff, pkt->getPtr<uint8_t>());
- if (pkt->getSize() == sizeof(uint16_t))
- readConfig(daddr & 0xff, pkt->getPtr<uint16_t>());
- if (pkt->getSize() == sizeof(uint32_t))
- readConfig(daddr & 0xff, pkt->getPtr<uint32_t>());
- pkt->result = Packet::Success;
- return pioDelay;
+ return readConfig(pkt);
} else if (daddr >= MIB_START && daddr <= MIB_END) {
// don't implement all the MIB's. hopefully the kernel
// doesn't actually DEPEND upon their values
@@ -733,14 +729,7 @@ NSGigE::write(Packet *pkt)
if (daddr > LAST && daddr <= RESERVED) {
panic("Accessing reserved register");
} else if (daddr > RESERVED && daddr <= 0x3FC) {
- if (pkt->getSize() == sizeof(uint8_t))
- writeConfig(daddr & 0xff, pkt->get<uint8_t>());
- if (pkt->getSize() == sizeof(uint16_t))
- writeConfig(daddr & 0xff, pkt->get<uint16_t>());
- if (pkt->getSize() == sizeof(uint32_t))
- writeConfig(daddr & 0xff, pkt->get<uint32_t>());
- pkt->result = Packet::Success;
- return pioDelay;
+ return writeConfig(pkt);
} else if (daddr > 0x3FC)
panic("Something is messed up!\n");
@@ -2807,7 +2796,6 @@ BEGIN_DECLARE_SIM_OBJECT_PARAMS(NSGigE)
SimObjectParam<System *> system;
SimObjectParam<Platform *> platform;
- SimObjectParam<PciConfigAll *> configspace;
SimObjectParam<PciConfigData *> configdata;
Param<uint32_t> pci_bus;
Param<uint32_t> pci_dev;
@@ -2841,7 +2829,6 @@ BEGIN_INIT_SIM_OBJECT_PARAMS(NSGigE)
INIT_PARAM(system, "System pointer"),
INIT_PARAM(platform, "Platform pointer"),
- INIT_PARAM(configspace, "PCI Configspace"),
INIT_PARAM(configdata, "PCI Config data"),
INIT_PARAM(pci_bus, "PCI bus ID"),
INIT_PARAM(pci_dev, "PCI device number"),
@@ -2879,7 +2866,6 @@ CREATE_SIM_OBJECT(NSGigE)
params->name = getInstanceName();
params->platform = platform;
params->system = system;
- params->configSpace = configspace;
params->configData = configdata;
params->busNum = pci_bus;
params->deviceNum = pci_dev;
diff --git a/src/dev/ns_gige.hh b/src/dev/ns_gige.hh
index 2f47026f3..ea7243777 100644
--- a/src/dev/ns_gige.hh
+++ b/src/dev/ns_gige.hh
@@ -114,7 +114,6 @@ struct dp_rom {
class NSGigEInt;
class Packet;
-class PciConfigAll;
/**
* NS DP83820 Ethernet device model
@@ -376,7 +375,7 @@ class NSGigE : public PciDev
~NSGigE();
const Params *params() const { return (const Params *)_params; }
- virtual void writeConfig(int offset, const uint16_t data);
+ virtual Tick writeConfig(Packet *pkt);
virtual Tick read(Packet *pkt);
virtual Tick write(Packet *pkt);
diff --git a/src/dev/pciconfigall.cc b/src/dev/pciconfigall.cc
index 785774ff4..68013eab8 100644
--- a/src/dev/pciconfigall.cc
+++ b/src/dev/pciconfigall.cc
@@ -33,14 +33,8 @@
* PCI Configspace implementation
*/
-#include <deque>
-#include <string>
-#include <vector>
-#include <bitset>
-
#include "base/trace.hh"
#include "dev/pciconfigall.hh"
-#include "dev/pcidev.hh"
#include "dev/pcireg.h"
#include "dev/platform.hh"
#include "mem/packet.hh"
@@ -50,151 +44,61 @@
using namespace std;
PciConfigAll::PciConfigAll(Params *p)
- : BasicPioDevice(p)
+ : PioDevice(p)
{
- pioSize = 0xffffff;
-
- // Set backpointer for pci config. Really the config stuff should be able to
- // automagically do this
- p->platform->pciconfig = this;
-
- // Make all the pointers to devices null
- for(int x=0; x < MAX_PCI_DEV; x++)
- for(int y=0; y < MAX_PCI_FUNC; y++)
- devices[x][y] = NULL;
+ pioAddr = p->platform->calcConfigAddr(params()->bus,0,0);
}
-// If two interrupts share the same line largely bad things will happen.
-// Since we don't track how many times an interrupt was set and correspondingly
-// cleared two devices on the same interrupt line and assert and deassert each
-// others interrupt "line". Interrupts will not work correctly.
-void
-PciConfigAll::startup()
-{
- bitset<256> intLines;
- PciDev *tempDev;
- uint8_t intline;
-
- for (int x = 0; x < MAX_PCI_DEV; x++) {
- for (int y = 0; y < MAX_PCI_FUNC; y++) {
- if (devices[x][y] != NULL) {
- tempDev = devices[x][y];
- intline = tempDev->interruptLine();
- if (intLines.test(intline))
- warn("Interrupt line %#X is used multiple times"
- "(You probably want to fix this).\n", (uint32_t)intline);
- else
- intLines.set(intline);
- } // devices != NULL
- } // PCI_FUNC
- } // PCI_DEV
-
-}
Tick
PciConfigAll::read(Packet *pkt)
{
assert(pkt->result == Packet::Unknown);
- assert(pkt->getAddr() >= pioAddr && pkt->getAddr() < pioAddr + pioSize);
-
- Addr daddr = pkt->getAddr() - pioAddr;
- int device = (daddr >> 11) & 0x1F;
- int func = (daddr >> 8) & 0x7;
- int reg = daddr & 0xFF;
pkt->allocate();
- DPRINTF(PciConfigAll, "read va=%#x da=%#x size=%d\n", pkt->getAddr(), daddr,
+ DPRINTF(PciConfigAll, "read va=%#x size=%d\n", pkt->getAddr(),
pkt->getSize());
switch (pkt->getSize()) {
case sizeof(uint32_t):
- if (devices[device][func] == NULL)
- pkt->set<uint32_t>(0xFFFFFFFF);
- else
- devices[device][func]->readConfig(reg, pkt->getPtr<uint32_t>());
+ pkt->set<uint32_t>(0xFFFFFFFF);
break;
case sizeof(uint16_t):
- if (devices[device][func] == NULL)
- pkt->set<uint16_t>(0xFFFF);
- else
- devices[device][func]->readConfig(reg, pkt->getPtr<uint16_t>());
+ pkt->set<uint16_t>(0xFFFF);
break;
case sizeof(uint8_t):
- if (devices[device][func] == NULL)
- pkt->set<uint8_t>(0xFF);
- else
- devices[device][func]->readConfig(reg, pkt->getPtr<uint8_t>());
+ pkt->set<uint8_t>(0xFF);
break;
default:
panic("invalid access size(?) for PCI configspace!\n");
}
pkt->result = Packet::Success;
- return pioDelay;
+ return params()->pio_delay;
}
Tick
PciConfigAll::write(Packet *pkt)
{
assert(pkt->result == Packet::Unknown);
- assert(pkt->getAddr() >= pioAddr && pkt->getAddr() < pioAddr + pioSize);
- assert(pkt->getSize() == sizeof(uint8_t) || pkt->getSize() == sizeof(uint16_t) ||
- pkt->getSize() == sizeof(uint32_t));
- Addr daddr = pkt->getAddr() - pioAddr;
-
- int device = (daddr >> 11) & 0x1F;
- int func = (daddr >> 8) & 0x7;
- int reg = daddr & 0xFF;
-
- if (devices[device][func] == NULL)
- panic("Attempting to write to config space on non-existant device\n");
-
- DPRINTF(PciConfigAll, "write - va=%#x size=%d data=%#x\n",
- pkt->getAddr(), pkt->getSize(), pkt->get<uint32_t>());
-
- switch (pkt->getSize()) {
- case sizeof(uint8_t):
- devices[device][func]->writeConfig(reg, pkt->get<uint8_t>());
- break;
- case sizeof(uint16_t):
- devices[device][func]->writeConfig(reg, pkt->get<uint16_t>());
- break;
- case sizeof(uint32_t):
- devices[device][func]->writeConfig(reg, pkt->get<uint32_t>());
- break;
- default:
- panic("invalid pci config write size\n");
- }
- pkt->result = Packet::Success;
- return pioDelay;
+ panic("Attempting to write to config space on non-existant device\n");
}
void
-PciConfigAll::serialize(std::ostream &os)
+PciConfigAll::addressRanges(AddrRangeList &range_list)
{
- /*
- * There is no state associated with this object that requires
- * serialization. The only real state are the device pointers
- * which are all setup by the constructor of the PciDev class
- */
+ range_list.clear();
+ range_list.push_back(RangeSize(pioAddr, params()->size));
}
-void
-PciConfigAll::unserialize(Checkpoint *cp, const std::string &section)
-{
- /*
- * There is no state associated with this object that requires
- * serialization. The only real state are the device pointers
- * which are all setup by the constructor of the PciDev class
- */
-}
#ifndef DOXYGEN_SHOULD_SKIP_THIS
BEGIN_DECLARE_SIM_OBJECT_PARAMS(PciConfigAll)
- Param<Addr> pio_addr;
Param<Tick> pio_latency;
+ Param<int> bus;
+ Param<Addr> size;
SimObjectParam<Platform *> platform;
SimObjectParam<System *> system;
@@ -202,8 +106,9 @@ END_DECLARE_SIM_OBJECT_PARAMS(PciConfigAll)
BEGIN_INIT_SIM_OBJECT_PARAMS(PciConfigAll)
- INIT_PARAM(pio_addr, "Device Address"),
INIT_PARAM(pio_latency, "Programmed IO latency"),
+ INIT_PARAM(bus, "Bus that this object handles config space for"),
+ INIT_PARAM(size, "The size of config space"),
INIT_PARAM(platform, "platform"),
INIT_PARAM(system, "system object")
@@ -211,11 +116,13 @@ END_INIT_SIM_OBJECT_PARAMS(PciConfigAll)
CREATE_SIM_OBJECT(PciConfigAll)
{
- BasicPioDevice::Params *p = new BasicPioDevice::Params;
- p->pio_addr = pio_addr;
+ PciConfigAll::Params *p = new PciConfigAll::Params;
p->pio_delay = pio_latency;
p->platform = platform;
p->system = system;
+ p->bus = bus;
+ p->size = size;
+
return new PciConfigAll(p);
}
diff --git a/src/dev/pciconfigall.hh b/src/dev/pciconfigall.hh
index e60fd949b..07eaf8112 100644
--- a/src/dev/pciconfigall.hh
+++ b/src/dev/pciconfigall.hh
@@ -42,11 +42,6 @@
#include "dev/io_device.hh"
-static const uint32_t MAX_PCI_DEV = 32;
-static const uint32_t MAX_PCI_FUNC = 8;
-
-class PciDev;
-
/**
* PCI Config Space
* All of PCI config space needs to return -1 on Tsunami, except
@@ -54,16 +49,17 @@ class PciDev;
* space and passes the requests on to TsunamiPCIDev devices as
* appropriate.
*/
-class PciConfigAll : public BasicPioDevice
+class PciConfigAll : public PioDevice
{
- private:
- /**
- * Pointers to all the devices that are registered with this
- * particular config space.
- */
- PciDev* devices[MAX_PCI_DEV][MAX_PCI_FUNC];
-
public:
+ struct Params : public PioDevice::Params
+ {
+ Tick pio_delay;
+ Addr size;
+ int bus;
+ };
+ const Params *params() const { return (const Params *)_params; }
+
/**
* Constructor for PCIConfigAll
* @param p parameters structure
@@ -71,28 +67,10 @@ class PciConfigAll : public BasicPioDevice
PciConfigAll(Params *p);
/**
- * Check if a device exists.
- * @param pcidev PCI device to check
- * @param pcifunc PCI function to check
- * @return true if device exists, false otherwise
- */
- bool deviceExists(uint32_t pcidev, uint32_t pcifunc)
- { return devices[pcidev][pcifunc] != NULL ? true : false; }
-
- /**
- * Registers a device with the config space object.
- * @param pcidev PCI device to register
- * @param pcifunc PCI function to register
- * @param device device to register
- */
- void registerDevice(uint8_t pcidev, uint8_t pcifunc, PciDev *device)
- { devices[pcidev][pcifunc] = device; }
-
- /**
* Read something in PCI config space. If the device does not exist
* -1 is returned, if the device does exist its PciDev::ReadConfig (or the
* virtual function that overrides) it is called.
- * @param pkt Contains the address of the field to read.
+ * @param pkt Contains information about the read operation
* @return Amount of time to do the read
*/
virtual Tick read(Packet *pkt);
@@ -101,31 +79,17 @@ class PciConfigAll : public BasicPioDevice
* Write to PCI config spcae. If the device does not exit the simulator
* panics. If it does it is passed on the PciDev::WriteConfig (or the virtual
* function that overrides it).
- * @param req Contains the address to write to.
- * @param data The data to write.
- * @return The fault condition of the access.
+ * @param pkt Contains information about the write operation
+ * @return Amount of time to do the read
*/
virtual Tick write(Packet *pkt);
- /**
- * Start up function to check if more than one person is using an interrupt line
- * and print a warning if such a case exists
- */
- virtual void startup();
+ void addressRanges(AddrRangeList &range_list);
- /**
- * Serialize this object to the given output stream.
- * @param os The stream to serialize to.
- */
- virtual void serialize(std::ostream &os);
+ private:
+ Addr pioAddr;
- /**
- * Reconstruct the state of this object from a checkpoint.
- * @param cp The checkpoint use.
- * @param section The section name of this object
- */
- virtual void unserialize(Checkpoint *cp, const std::string &section);
};
#endif // __PCICONFIGALL_HH__
diff --git a/src/dev/pcidev.cc b/src/dev/pcidev.cc
index f8db2efbc..62a7324ad 100644
--- a/src/dev/pcidev.cc
+++ b/src/dev/pcidev.cc
@@ -53,201 +53,256 @@
using namespace std;
-PciDev::PciDev(Params *p)
- : DmaDevice(p), plat(p->platform), configData(p->configData),
- pioDelay(p->pio_delay)
-{
- // copy the config data from the PciConfigData object
- if (configData) {
- memcpy(config.data, configData->config.data, sizeof(config.data));
- memcpy(BARSize, configData->BARSize, sizeof(BARSize));
- memcpy(BARAddrs, configData->BARAddrs, sizeof(BARAddrs));
- } else
- panic("NULL pointer to configuration data");
- // Setup pointer in config space to point to this entry
- if (p->configSpace->deviceExists(p->deviceNum, p->functionNum))
- panic("Two PCI devices occuping same dev: %#x func: %#x",
- p->deviceNum, p->functionNum);
- else
- p->configSpace->registerDevice(p->deviceNum, p->functionNum, this);
-}
-
-void
-PciDev::readConfig(int offset, uint8_t *data)
+PciDev::PciConfigPort::PciConfigPort(PciDev *dev, int busid, int devid,
+ int funcid, Platform *p)
+ : PioPort(dev,p,"-pciconf"), device(dev), busId(busid), deviceId(devid),
+ functionId(funcid)
{
- if (offset >= PCI_DEVICE_SPECIFIC)
- panic("Device specific PCI config space not implemented!\n");
+ configAddr = platform->calcConfigAddr(busId, deviceId, functionId);
+}
- *data = config.data[offset];
- DPRINTF(PCIDEV,
- "read device: %#x function: %#x register: %#x 1 bytes: data: %#x\n",
- params()->deviceNum, params()->functionNum, offset, *data);
+Tick
+PciDev::PciConfigPort::recvAtomic(Packet *pkt)
+{
+ assert(pkt->result == Packet::Unknown);
+ assert(pkt->getAddr() >= configAddr && pkt->getAddr() < configAddr +
+ PCI_CONFIG_SIZE);
+ return device->recvConfig(pkt);
}
void
-PciDev::addressRanges(AddrRangeList &range_list)
+PciDev::PciConfigPort::recvFunctional(Packet *pkt)
{
- int x = 0;
- range_list.clear();
- for (x = 0; x < 6; x++)
- if (BARAddrs[x] != 0)
- range_list.push_back(RangeSize(BARAddrs[x],BARSize[x]));
+ assert(pkt->result == Packet::Unknown);
+ assert(pkt->getAddr() >= configAddr && pkt->getAddr() < configAddr +
+ PCI_CONFIG_SIZE);
+ device->recvConfig(pkt);
}
void
-PciDev::readConfig(int offset, uint16_t *data)
+PciDev::PciConfigPort::getDeviceAddressRanges(AddrRangeList &resp, AddrRangeList &snoop)
{
- if (offset >= PCI_DEVICE_SPECIFIC)
- panic("Device specific PCI config space not implemented!\n");
+ snoop.clear();
+ resp.push_back(RangeSize(configAddr, PCI_CONFIG_SIZE+1));
+}
- *data = *(uint16_t*)&config.data[offset];
- DPRINTF(PCIDEV,
- "read device: %#x function: %#x register: %#x 2 bytes: data: %#x\n",
- params()->deviceNum, params()->functionNum, offset, *data);
+bool
+PciDev::PciConfigPort::recvTiming(Packet *pkt)
+{
+ if (pkt->result == Packet::Nacked) {
+ resendNacked(pkt);
+ } else {
+ assert(pkt->result == Packet::Unknown);
+ assert(pkt->getAddr() >= configAddr && pkt->getAddr() < configAddr +
+ PCI_CONFIG_SIZE);
+ Tick latency = device->recvConfig(pkt);
+ // turn packet around to go back to requester
+ pkt->makeTimingResponse();
+ sendTiming(pkt, latency);
+ }
+ return true;
}
-void
-PciDev::readConfig(int offset, uint32_t *data)
+PciDev::PciDev(Params *p)
+ : DmaDevice(p), plat(p->platform), configData(p->configData),
+ pioDelay(p->pio_delay), configDelay(p->config_delay),
+ configPort(NULL)
{
- if (offset >= PCI_DEVICE_SPECIFIC)
- panic("Device specific PCI config space not implemented!\n");
-
- *data = *(uint32_t*)&config.data[offset];
+ // copy the config data from the PciConfigData object
+ if (configData) {
+ memcpy(config.data, configData->config.data, sizeof(config.data));
+ memcpy(BARSize, configData->BARSize, sizeof(BARSize));
+ memcpy(BARAddrs, configData->BARAddrs, sizeof(BARAddrs));
+ } else
+ panic("NULL pointer to configuration data");
- DPRINTF(PCIDEV,
- "read device: %#x function: %#x register: %#x 4 bytes: data: %#x\n",
- params()->deviceNum, params()->functionNum, offset, *data);
+ plat->registerPciDevice(0, p->deviceNum, p->functionNum,
+ letoh(configData->config.interruptLine));
}
-
void
-PciDev::writeConfig(int offset, const uint8_t data)
+PciDev::init()
{
+ if (!configPort)
+ panic("pci config port not connected to anything!");
+ configPort->sendStatusChange(Port::RangeChange);
+ PioDevice::init();
+}
+
+Tick
+PciDev::readConfig(Packet *pkt)
+{
+ int offset = pkt->getAddr() & PCI_CONFIG_SIZE;
if (offset >= PCI_DEVICE_SPECIFIC)
panic("Device specific PCI config space not implemented!\n");
- DPRINTF(PCIDEV,
- "write device: %#x function: %#x reg: %#x size: 1 data: %#x\n",
- params()->deviceNum, params()->functionNum, offset, data);
-
- switch (offset) {
- case PCI0_INTERRUPT_LINE:
- config.interruptLine = data;
- case PCI_CACHE_LINE_SIZE:
- config.cacheLineSize = data;
- case PCI_LATENCY_TIMER:
- config.latencyTimer = data;
+ pkt->allocate();
+
+ switch (pkt->getSize()) {
+ case sizeof(uint8_t):
+ pkt->set<uint8_t>(config.data[offset]);
+ DPRINTF(PCIDEV,
+ "read device: %#x function: %#x register: %#x 1 bytes: data: %#x\n",
+ params()->deviceNum, params()->functionNum, offset,
+ (uint32_t)pkt->get<uint8_t>());
break;
- /* Do nothing for these read-only registers */
- case PCI0_INTERRUPT_PIN:
- case PCI0_MINIMUM_GRANT:
- case PCI0_MAXIMUM_LATENCY:
- case PCI_CLASS_CODE:
- case PCI_REVISION_ID:
+ case sizeof(uint16_t):
+ pkt->set<uint16_t>(*(uint16_t*)&config.data[offset]);
+ DPRINTF(PCIDEV,
+ "read device: %#x function: %#x register: %#x 2 bytes: data: %#x\n",
+ params()->deviceNum, params()->functionNum, offset,
+ (uint32_t)pkt->get<uint16_t>());
+ break;
+ case sizeof(uint32_t):
+ pkt->set<uint32_t>(*(uint32_t*)&config.data[offset]);
+ DPRINTF(PCIDEV,
+ "read device: %#x function: %#x register: %#x 4 bytes: data: %#x\n",
+ params()->deviceNum, params()->functionNum, offset,
+ (uint32_t)pkt->get<uint32_t>());
break;
default:
- panic("writing to a read only register");
+ panic("invalid access size(?) for PCI configspace!\n");
}
+ pkt->result = Packet::Success;
+ return configDelay;
+
}
void
-PciDev::writeConfig(int offset, const uint16_t data)
+PciDev::addressRanges(AddrRangeList &range_list)
{
- if (offset >= PCI_DEVICE_SPECIFIC)
- panic("Device specific PCI config space not implemented!\n");
-
- DPRINTF(PCIDEV,
- "write device: %#x function: %#x reg: %#x size: 2 data: %#x\n",
- params()->deviceNum, params()->functionNum, offset, data);
-
- switch (offset) {
- case PCI_COMMAND:
- config.command = data;
- case PCI_STATUS:
- config.status = data;
- case PCI_CACHE_LINE_SIZE:
- config.cacheLineSize = data;
- break;
- default:
- panic("writing to a read only register");
- }
+ int x = 0;
+ range_list.clear();
+ for (x = 0; x < 6; x++)
+ if (BARAddrs[x] != 0)
+ range_list.push_back(RangeSize(BARAddrs[x],BARSize[x]));
}
-
-void
-PciDev::writeConfig(int offset, const uint32_t data)
+Tick
+PciDev::writeConfig(Packet *pkt)
{
+ int offset = pkt->getAddr() & PCI_CONFIG_SIZE;
if (offset >= PCI_DEVICE_SPECIFIC)
panic("Device specific PCI config space not implemented!\n");
- DPRINTF(PCIDEV,
- "write device: %#x function: %#x reg: %#x size: 4 data: %#x\n",
- params()->deviceNum, params()->functionNum, offset, data);
-
- switch (offset) {
- case PCI0_BASE_ADDR0:
- case PCI0_BASE_ADDR1:
- case PCI0_BASE_ADDR2:
- case PCI0_BASE_ADDR3:
- case PCI0_BASE_ADDR4:
- case PCI0_BASE_ADDR5:
-
- uint32_t barnum, bar_mask;
- Addr base_addr, base_size, space_base;
-
- barnum = BAR_NUMBER(offset);
-
- if (BAR_IO_SPACE(letoh(config.baseAddr[barnum]))) {
- bar_mask = BAR_IO_MASK;
- space_base = TSUNAMI_PCI0_IO;
- } else {
- bar_mask = BAR_MEM_MASK;
- space_base = TSUNAMI_PCI0_MEMORY;
+ switch (pkt->getSize()) {
+ case sizeof(uint8_t):
+ switch (offset) {
+ case PCI0_INTERRUPT_LINE:
+ config.interruptLine = pkt->get<uint8_t>();
+ case PCI_CACHE_LINE_SIZE:
+ config.cacheLineSize = pkt->get<uint8_t>();
+ case PCI_LATENCY_TIMER:
+ config.latencyTimer = pkt->get<uint8_t>();
+ break;
+ /* Do nothing for these read-only registers */
+ case PCI0_INTERRUPT_PIN:
+ case PCI0_MINIMUM_GRANT:
+ case PCI0_MAXIMUM_LATENCY:
+ case PCI_CLASS_CODE:
+ case PCI_REVISION_ID:
+ break;
+ default:
+ panic("writing to a read only register");
}
+ DPRINTF(PCIDEV,
+ "write device: %#x function: %#x register: %#x 1 bytes: data: %#x\n",
+ params()->deviceNum, params()->functionNum, offset,
+ (uint32_t)pkt->get<uint8_t>());
+ break;
+ case sizeof(uint16_t):
+ switch (offset) {
+ case PCI_COMMAND:
+ config.command = pkt->get<uint8_t>();
+ case PCI_STATUS:
+ config.status = pkt->get<uint8_t>();
+ case PCI_CACHE_LINE_SIZE:
+ config.cacheLineSize = pkt->get<uint8_t>();
+ break;
+ default:
+ panic("writing to a read only register");
+ }
+ DPRINTF(PCIDEV,
+ "write device: %#x function: %#x register: %#x 2 bytes: data: %#x\n",
+ params()->deviceNum, params()->functionNum, offset,
+ (uint32_t)pkt->get<uint16_t>());
+ break;
+ case sizeof(uint32_t):
+ switch (offset) {
+ case PCI0_BASE_ADDR0:
+ case PCI0_BASE_ADDR1:
+ case PCI0_BASE_ADDR2:
+ case PCI0_BASE_ADDR3:
+ case PCI0_BASE_ADDR4:
+ case PCI0_BASE_ADDR5:
+
+ uint32_t barnum, bar_mask;
+ Addr base_addr, base_size, space_base;
+
+ barnum = BAR_NUMBER(offset);
+
+ if (BAR_IO_SPACE(letoh(config.baseAddr[barnum]))) {
+ bar_mask = BAR_IO_MASK;
+ space_base = TSUNAMI_PCI0_IO;
+ } else {
+ bar_mask = BAR_MEM_MASK;
+ space_base = TSUNAMI_PCI0_MEMORY;
+ }
- // Writing 0xffffffff to a BAR tells the card to set the
- // value of the bar to size of memory it needs
- if (letoh(data) == 0xffffffff) {
- // This is I/O Space, bottom two bits are read only
-
- config.baseAddr[barnum] = letoh(
- (~(BARSize[barnum] - 1) & ~bar_mask) |
+ // Writing 0xffffffff to a BAR tells the card to set the
+ // value of the bar to size of memory it needs
+ if (letoh(pkt->get<uint32_t>()) == 0xffffffff) {
+ // This is I/O Space, bottom two bits are read only
+
+ config.baseAddr[barnum] = letoh(
+ (~(BARSize[barnum] - 1) & ~bar_mask) |
+ (letoh(config.baseAddr[barnum]) & bar_mask));
+ } else {
+ config.baseAddr[barnum] = letoh(
+ (letoh(pkt->get<uint32_t>()) & ~bar_mask) |
(letoh(config.baseAddr[barnum]) & bar_mask));
- } else {
- config.baseAddr[barnum] = letoh(
- (letoh(data) & ~bar_mask) |
- (letoh(config.baseAddr[barnum]) & bar_mask));
- if (letoh(config.baseAddr[barnum]) & ~bar_mask) {
- base_addr = (letoh(data) & ~bar_mask) + space_base;
- base_size = BARSize[barnum];
- BARAddrs[barnum] = base_addr;
+ if (letoh(config.baseAddr[barnum]) & ~bar_mask) {
+ base_addr = (letoh(pkt->get<uint32_t>()) & ~bar_mask) + space_base;
+ base_size = BARSize[barnum];
+ BARAddrs[barnum] = base_addr;
- pioPort->sendStatusChange(Port::RangeChange);
+ pioPort->sendStatusChange(Port::RangeChange);
+ }
}
+ break;
+
+ case PCI0_ROM_BASE_ADDR:
+ if (letoh(pkt->get<uint32_t>()) == 0xfffffffe)
+ config.expansionROM = htole((uint32_t)0xffffffff);
+ else
+ config.expansionROM = pkt->get<uint32_t>();
+ break;
+
+ case PCI_COMMAND:
+ // This could also clear some of the error bits in the Status
+ // register. However they should never get set, so lets ignore
+ // it for now
+ config.command = pkt->get<uint32_t>();
+ break;
+
+ default:
+ DPRINTF(PCIDEV, "Writing to a read only register");
}
+ DPRINTF(PCIDEV,
+ "write device: %#x function: %#x register: %#x 4 bytes: data: %#x\n",
+ params()->deviceNum, params()->functionNum, offset,
+ (uint32_t)pkt->get<uint32_t>());
break;
-
- case PCI0_ROM_BASE_ADDR:
- if (letoh(data) == 0xfffffffe)
- config.expansionROM = htole((uint32_t)0xffffffff);
- else
- config.expansionROM = data;
- break;
-
- case PCI_COMMAND:
- // This could also clear some of the error bits in the Status
- // register. However they should never get set, so lets ignore
- // it for now
- config.command = data;
- break;
-
default:
- DPRINTF(PCIDEV, "Writing to a read only register");
+ panic("invalid access size(?) for PCI configspace!\n");
}
+ pkt->result = Packet::Success;
+ return configDelay;
+
}
void
diff --git a/src/dev/pcidev.hh b/src/dev/pcidev.hh
index 92786427b..20ab9364a 100644
--- a/src/dev/pcidev.hh
+++ b/src/dev/pcidev.hh
@@ -47,8 +47,6 @@
#define BAR_IO_SPACE(x) ((x) & BAR_IO_SPACE_BIT)
#define BAR_NUMBER(x) (((x) - PCI0_BASE_ADDR0) >> 0x2);
-class PciConfigAll;
-
/**
* This class encapulates the first 64 bytes of a singles PCI
@@ -78,24 +76,41 @@ class PciConfigData : public SimObject
Addr BARAddrs[6];
};
+
/**
* PCI device, base implemnation is only config space.
- * Each device is connected to a PCIConfigSpace device
- * which returns -1 for everything but the pcidevs that
- * register with it. This object registers with the PCIConfig space
- * object.
*/
class PciDev : public DmaDevice
{
- public:
- struct Params : public ::PioDevice::Params
+ class PciConfigPort : public PioPort
{
- /**
- * A pointer to the configspace all object that calls us when
- * a read comes to this particular device/function.
- */
- PciConfigAll *configSpace;
+ protected:
+ PciDev *device;
+
+ virtual bool recvTiming(Packet *pkt);
+
+ virtual Tick recvAtomic(Packet *pkt);
+
+ virtual void recvFunctional(Packet *pkt) ;
+
+ virtual void getDeviceAddressRanges(AddrRangeList &resp, AddrRangeList &snoop);
+
+ int busId;
+ int deviceId;
+ int functionId;
+
+ Addr configAddr;
+
+ public:
+ PciConfigPort(PciDev *dev, int busid, int devid, int funcid,
+ Platform *p);
+ friend class PioPort::SendEvent;
+ };
+
+ public:
+ struct Params : public PioDevice::Params
+ {
/**
* A pointer to the object that contains the first 64 bytes of
* config space
@@ -113,6 +128,9 @@ class PciDev : public DmaDevice
/** The latency for pio accesses. */
Tick pio_delay;
+
+ /** The latency for a config access. */
+ Tick config_delay;
};
public:
@@ -164,6 +182,25 @@ class PciDev : public DmaDevice
Platform *plat;
PciConfigData *configData;
Tick pioDelay;
+ Tick configDelay;
+ PciConfigPort *configPort;
+
+ /**
+ * Write to the PCI config space data that is stored locally. This may be
+ * overridden by the device but at some point it will eventually call this
+ * for normal operations that it does not need to override.
+ * @param pkt packet containing the write the offset into config space
+ */
+ virtual Tick writeConfig(Packet *pkt);
+
+
+ /**
+ * Read from the PCI config space data that is stored locally. This may be
+ * overridden by the device but at some point it will eventually call this
+ * for normal operations that it does not need to override.
+ * @param pkt packet containing the write the offset into config space
+ */
+ virtual Tick readConfig(Packet *pkt);
public:
Addr pciToDma(Addr pciAddr) const
@@ -171,21 +208,25 @@ class PciDev : public DmaDevice
void
intrPost()
- { plat->postPciInt(configData->config.interruptLine); }
+ { plat->postPciInt(letoh(configData->config.interruptLine)); }
void
intrClear()
- { plat->clearPciInt(configData->config.interruptLine); }
+ { plat->clearPciInt(letoh(configData->config.interruptLine)); }
uint8_t
interruptLine()
- { return configData->config.interruptLine; }
+ { return letoh(configData->config.interruptLine); }
/** return the address ranges that this device responds to.
* @params range_list range list to populate with ranges
*/
void addressRanges(AddrRangeList &range_list);
+ /** Do a PCI Configspace memory access. */
+ Tick recvConfig(Packet *pkt)
+ { return pkt->isRead() ? readConfig(pkt) : writeConfig(pkt); }
+
/**
* Constructor for PCI Dev. This function copies data from the
* config file object PCIConfigData and registers the device with
@@ -193,30 +234,7 @@ class PciDev : public DmaDevice
*/
PciDev(Params *params);
- /**
- * Write to the PCI config space data that is stored locally. This may be
- * overridden by the device but at some point it will eventually call this
- * for normal operations that it does not need to override.
- * @param offset the offset into config space
- * @param size the size of the write
- * @param data the data to write
- */
- virtual void writeConfig(int offset, const uint8_t data);
- virtual void writeConfig(int offset, const uint16_t data);
- virtual void writeConfig(int offset, const uint32_t data);
-
-
- /**
- * Read from the PCI config space data that is stored locally. This may be
- * overridden by the device but at some point it will eventually call this
- * for normal operations that it does not need to override.
- * @param offset the offset into config space
- * @param size the size of the read
- * @param data pointer to the location where the read value should be stored
- */
- virtual void readConfig(int offset, uint8_t *data);
- virtual void readConfig(int offset, uint16_t *data);
- virtual void readConfig(int offset, uint32_t *data);
+ virtual void init();
/**
* Serialize this object to the given output stream.
@@ -230,5 +248,19 @@ class PciDev : public DmaDevice
* @param section The section name of this object
*/
virtual void unserialize(Checkpoint *cp, const std::string &section);
+
+ virtual Port *getPort(const std::string &if_name, int idx = -1)
+ {
+ if (if_name == "config") {
+ if (configPort != NULL)
+ panic("pciconfig port already connected to.");
+ configPort = new PciConfigPort(this, params()->busNum,
+ params()->deviceNum, params()->functionNum,
+ params()->platform);
+ return configPort;
+ }
+ return DmaDevice::getPort(if_name, idx);
+ }
+
};
#endif // __DEV_PCIDEV_HH__
diff --git a/src/dev/pcireg.h b/src/dev/pcireg.h
index 0aa4ba8ef..a48abd4fa 100644
--- a/src/dev/pcireg.h
+++ b/src/dev/pcireg.h
@@ -142,6 +142,7 @@ union PCIConfig {
// Device specific offsets
#define PCI_DEVICE_SPECIFIC 0x40 // 192 bytes
+#define PCI_CONFIG_SIZE 0xFF
// Some Vendor IDs
#define PCI_VENDOR_DEC 0x1011
diff --git a/src/dev/platform.cc b/src/dev/platform.cc
index ed021e3b6..8546b7805 100644
--- a/src/dev/platform.cc
+++ b/src/dev/platform.cc
@@ -63,5 +63,21 @@ Platform::pciToDma(Addr pciAddr) const
panic("No PCI dma support in platform.");
}
+void
+Platform::registerPciDevice(uint8_t bus, uint8_t dev, uint8_t func, uint8_t intr)
+{
+ uint32_t bdf = bus << 16 | dev << 8 | func << 0;
+ if (pciDevices.find(bdf) != pciDevices.end())
+ fatal("Two PCI devices have same bus:device:function\n");
+
+ if (intLines.test(intr))
+ fatal("Two PCI devices have same interrupt line: %d\n", intr);
+
+ pciDevices.insert(bdf);
+
+ intLines.set(intr);
+}
+
+
DEFINE_SIM_OBJECT_CLASS_NAME("Platform", Platform)
diff --git a/src/dev/platform.hh b/src/dev/platform.hh
index 0e6f4ba4a..1940dcad6 100644
--- a/src/dev/platform.hh
+++ b/src/dev/platform.hh
@@ -37,6 +37,9 @@
#ifndef __DEV_PLATFORM_HH__
#define __DEV_PLATFORM_HH__
+#include <bitset>
+#include <set>
+
#include "sim/sim_object.hh"
#include "arch/isa_traits.hh"
@@ -52,9 +55,6 @@ class Platform : public SimObject
/** Pointer to the interrupt controller */
IntrControl *intrctrl;
- /** Pointer to the PCI configuration space */
- PciConfigAll *pciconfig;
-
/** Pointer to the UART, set by the uart */
Uart *uart;
@@ -64,13 +64,20 @@ class Platform : public SimObject
public:
Platform(const std::string &name, IntrControl *intctrl);
virtual ~Platform();
- virtual void init() { if (pciconfig == NULL) panic("PCI Config not set"); }
virtual void postConsoleInt() = 0;
virtual void clearConsoleInt() = 0;
virtual Tick intrFrequency() = 0;
virtual void postPciInt(int line);
virtual void clearPciInt(int line);
virtual Addr pciToDma(Addr pciAddr) const;
+ virtual Addr calcConfigAddr(int bus, int dev, int func) = 0;
+ virtual void registerPciDevice(uint8_t bus, uint8_t dev, uint8_t func,
+ uint8_t intr);
+
+ private:
+ std::bitset<256> intLines;
+ std::set<uint32_t> pciDevices;
+
};
#endif // __DEV_PLATFORM_HH__
diff --git a/src/dev/sinic.cc b/src/dev/sinic.cc
index a0223733b..dddda1f1c 100644
--- a/src/dev/sinic.cc
+++ b/src/dev/sinic.cc
@@ -37,7 +37,6 @@
#include "cpu/intr_control.hh"
#include "dev/etherlink.hh"
#include "dev/sinic.hh"
-#include "dev/pciconfigall.hh"
#include "mem/packet.hh"
#include "sim/builder.hh"
#include "sim/debug.hh"
@@ -1623,7 +1622,6 @@ BEGIN_DECLARE_SIM_OBJECT_PARAMS(Device)
SimObjectParam<System *> system;
SimObjectParam<Platform *> platform;
- SimObjectParam<PciConfigAll *> configspace;
SimObjectParam<PciConfigData *> configdata;
Param<uint32_t> pci_bus;
Param<uint32_t> pci_dev;
@@ -1666,7 +1664,6 @@ BEGIN_INIT_SIM_OBJECT_PARAMS(Device)
INIT_PARAM(system, "System pointer"),
INIT_PARAM(platform, "Platform pointer"),
- INIT_PARAM(configspace, "PCI Configspace"),
INIT_PARAM(configdata, "PCI Config data"),
INIT_PARAM(pci_bus, "PCI bus ID"),
INIT_PARAM(pci_dev, "PCI device number"),
@@ -1711,7 +1708,6 @@ CREATE_SIM_OBJECT(Device)
params->name = getInstanceName();
params->platform = platform;
params->system = system;
- params->configSpace = configspace;
params->configData = configdata;
params->busNum = pci_bus;
params->deviceNum = pci_dev;
diff --git a/src/dev/tsunami.cc b/src/dev/tsunami.cc
index c9e15581d..8e740a72f 100644
--- a/src/dev/tsunami.cc
+++ b/src/dev/tsunami.cc
@@ -95,6 +95,13 @@ Tsunami::pciToDma(Addr pciAddr) const
return pchip->translatePciToDma(pciAddr);
}
+
+Addr
+Tsunami::calcConfigAddr(int bus, int dev, int func)
+{
+ return pchip->calcConfigAddr(bus, dev, func);
+}
+
void
Tsunami::serialize(std::ostream &os)
{
diff --git a/src/dev/tsunami.hh b/src/dev/tsunami.hh
index 13fc4417c..8bb66e914 100644
--- a/src/dev/tsunami.hh
+++ b/src/dev/tsunami.hh
@@ -113,9 +113,15 @@ class Tsunami : public Platform
*/
virtual void clearPciInt(int line);
+
virtual Addr pciToDma(Addr pciAddr) const;
/**
+ * Calculate the configuration address given a bus/dev/func.
+ */
+ virtual Addr calcConfigAddr(int bus, int dev, int func);
+
+ /**
* Serialize this object to the given output stream.
* @param os The stream to serialize to.
*/
diff --git a/src/dev/tsunami_pchip.cc b/src/dev/tsunami_pchip.cc
index a376b908d..8a542b9b0 100644
--- a/src/dev/tsunami_pchip.cc
+++ b/src/dev/tsunami_pchip.cc
@@ -302,6 +302,17 @@ TsunamiPChip::translatePciToDma(Addr busAddr)
// if no match was found, then return the original address
return busAddr;
}
+Addr
+TsunamiPChip::calcConfigAddr(int bus, int dev, int func)
+{
+ assert(func < 8);
+ assert(dev < 32);
+ assert(bus == 0);
+
+ return TsunamiPciBus0Config | (func << 8) | (dev << 11);
+}
+
+
void
TsunamiPChip::serialize(std::ostream &os)
diff --git a/src/dev/tsunami_pchip.hh b/src/dev/tsunami_pchip.hh
index 9f80f7d68..b9e900526 100644
--- a/src/dev/tsunami_pchip.hh
+++ b/src/dev/tsunami_pchip.hh
@@ -45,6 +45,9 @@
class TsunamiPChip : public BasicPioDevice
{
protected:
+
+ static const Addr TsunamiPciBus0Config = 0x801fe000000;
+
/** Pchip control register */
uint64_t pctl;
@@ -80,6 +83,8 @@ class TsunamiPChip : public BasicPioDevice
*/
Addr translatePciToDma(Addr busAddr);
+ Addr calcConfigAddr(int bus, int dev, int func);
+
virtual Tick read(Packet *pkt);
virtual Tick write(Packet *pkt);
diff --git a/src/mem/bus.cc b/src/mem/bus.cc
index 19a3dc9e4..31271106b 100644
--- a/src/mem/bus.cc
+++ b/src/mem/bus.cc
@@ -33,6 +33,7 @@
*/
+#include "base/misc.hh"
#include "base/trace.hh"
#include "mem/bus.hh"
#include "sim/builder.hh"
@@ -40,6 +41,14 @@
Port *
Bus::getPort(const std::string &if_name, int idx)
{
+ if (if_name == "default")
+ if (defaultPort == NULL) {
+ defaultPort = new BusPort(csprintf("%s-default",name()), this,
+ defaultId);
+ return defaultPort;
+ } else
+ fatal("Default port already set\n");
+
// if_name ignored? forced to be empty?
int id = interfaces.size();
BusPort *bp = new BusPort(csprintf("%s-p%d", name(), id), this, id);
@@ -47,11 +56,12 @@ Bus::getPort(const std::string &if_name, int idx)
return bp;
}
-/** Get the ranges of anyone that we are connected to. */
+/** Get the ranges of anyone other buses that we are connected to. */
void
Bus::init()
{
std::vector<Port*>::iterator intIter;
+
for (intIter = interfaces.begin(); intIter != interfaces.end(); intIter++)
(*intIter)->sendStatusChange(Port::RangeChange);
}
@@ -110,6 +120,7 @@ Bus::findPort(Addr addr, int id)
int dest_id = -1;
int i = 0;
bool found = false;
+ AddrRangeIter iter;
while (i < portList.size() && !found)
{
@@ -120,8 +131,18 @@ Bus::findPort(Addr addr, int id)
}
i++;
}
- if (dest_id == -1)
+
+ // Check if this matches the default range
+ if (dest_id == -1) {
+ for (iter = defaultRange.begin(); iter != defaultRange.end(); iter++) {
+ if (*iter == addr) {
+ DPRINTF(Bus, " found addr 0x%llx on default\n", addr);
+ return defaultPort;
+ }
+ }
panic("Unable to find destination for addr: %llx", addr);
+ }
+
// we shouldn't be sending this back to where it came from
assert(dest_id != id);
@@ -155,39 +176,52 @@ Bus::recvFunctional(Packet *pkt)
void
Bus::recvStatusChange(Port::Status status, int id)
{
+ AddrRangeList ranges;
+ AddrRangeList snoops;
+ int x;
+ AddrRangeIter iter;
+
assert(status == Port::RangeChange &&
"The other statuses need to be implemented.");
DPRINTF(BusAddrRanges, "received RangeChange from device id %d\n", id);
- assert(id < interfaces.size() && id >= 0);
- int x;
- Port *port = interfaces[id];
- AddrRangeList ranges;
- AddrRangeList snoops;
- AddrRangeIter iter;
- std::vector<DevMap>::iterator portIter;
+ if (id == defaultId) {
+ defaultRange.clear();
+ defaultPort->getPeerAddressRanges(ranges, snoops);
+ assert(snoops.size() == 0);
+ for(iter = ranges.begin(); iter != ranges.end(); iter++) {
+ defaultRange.push_back(*iter);
+ DPRINTF(BusAddrRanges, "Adding range %llx - %llx for default\n",
+ iter->start, iter->end);
+ }
+ } else {
- // Clean out any previously existent ids
- for (portIter = portList.begin(); portIter != portList.end(); ) {
- if (portIter->portId == id)
- portIter = portList.erase(portIter);
- else
- portIter++;
- }
+ assert((id < interfaces.size() && id >= 0) || id == -1);
+ Port *port = interfaces[id];
+ std::vector<DevMap>::iterator portIter;
+
+ // Clean out any previously existent ids
+ for (portIter = portList.begin(); portIter != portList.end(); ) {
+ if (portIter->portId == id)
+ portIter = portList.erase(portIter);
+ else
+ portIter++;
+ }
- port->getPeerAddressRanges(ranges, snoops);
+ port->getPeerAddressRanges(ranges, snoops);
- // not dealing with snooping yet either
- assert(snoops.size() == 0);
- for(iter = ranges.begin(); iter != ranges.end(); iter++) {
- DevMap dm;
- dm.portId = id;
- dm.range = *iter;
+ // not dealing with snooping yet either
+ assert(snoops.size() == 0);
+ for(iter = ranges.begin(); iter != ranges.end(); iter++) {
+ DevMap dm;
+ dm.portId = id;
+ dm.range = *iter;
- DPRINTF(BusAddrRanges, "Adding range %llx - %llx for id %d\n",
- dm.range.start, dm.range.end, id);
- portList.push_back(dm);
+ DPRINTF(BusAddrRanges, "Adding range %llx - %llx for id %d\n",
+ dm.range.start, dm.range.end, id);
+ portList.push_back(dm);
+ }
}
DPRINTF(MMU, "port list has %d entries\n", portList.size());
@@ -196,19 +230,47 @@ Bus::recvStatusChange(Port::Status status, int id)
for (x = 0; x < interfaces.size(); x++)
if (x != id)
interfaces[x]->sendStatusChange(Port::RangeChange);
+
+ if (id != defaultId && defaultPort)
+ defaultPort->sendStatusChange(Port::RangeChange);
}
void
Bus::addressRanges(AddrRangeList &resp, AddrRangeList &snoop, int id)
{
std::vector<DevMap>::iterator portIter;
+ AddrRangeIter dflt_iter;
+ bool subset;
resp.clear();
snoop.clear();
DPRINTF(BusAddrRanges, "received address range request, returning:\n");
+
+ for (dflt_iter = defaultRange.begin(); dflt_iter != defaultRange.end();
+ dflt_iter++) {
+ resp.push_back(*dflt_iter);
+ DPRINTF(BusAddrRanges, " -- %#llX : %#llX\n",dflt_iter->start,
+ dflt_iter->end);
+ }
for (portIter = portList.begin(); portIter != portList.end(); portIter++) {
- if (portIter->portId != id) {
+ subset = false;
+ for (dflt_iter = defaultRange.begin(); dflt_iter != defaultRange.end();
+ dflt_iter++) {
+ if ((portIter->range.start < dflt_iter->start &&
+ portIter->range.end >= dflt_iter->start) ||
+ (portIter->range.start < dflt_iter->end &&
+ portIter->range.end >= dflt_iter->end))
+ fatal("Devices can not set ranges that itersect the default set\
+ but are not a subset of the default set.\n");
+ if (portIter->range.start >= dflt_iter->start &&
+ portIter->range.end <= dflt_iter->end) {
+ subset = true;
+ DPRINTF(BusAddrRanges, " -- %#llX : %#llX is a SUBSET\n",
+ portIter->range.start, portIter->range.end);
+ }
+ }
+ if (portIter->portId != id && !subset) {
resp.push_back(portIter->range);
DPRINTF(BusAddrRanges, " -- %#llX : %#llX\n",
portIter->range.start, portIter->range.end);
diff --git a/src/mem/bus.hh b/src/mem/bus.hh
index 9c7054b94..3a2896886 100644
--- a/src/mem/bus.hh
+++ b/src/mem/bus.hh
@@ -51,19 +51,22 @@ class Bus : public MemObject
/** a globally unique id for this bus. */
int busId;
+ static const int defaultId = -1;
+
struct DevMap {
int portId;
Range<Addr> range;
};
std::vector<DevMap> portList;
+ AddrRangeList defaultRange;
/** Function called by the port when the bus is recieving a Timing
- transaction.*/
+ transaction.*/
bool recvTiming(Packet *pkt);
/** Function called by the port when the bus is recieving a Atomic
- transaction.*/
+ transaction.*/
Tick recvAtomic(Packet *pkt);
/** Function called by the port when the bus is recieving a Functional
@@ -159,6 +162,9 @@ class Bus : public MemObject
* original send failed for whatever reason.*/
std::list<Port*> retryList;
+ /** Port that handles requests that don't match any of the interfaces.*/
+ Port *defaultPort;
+
public:
/** A function used to return the port associated with this bus object. */
@@ -167,7 +173,7 @@ class Bus : public MemObject
virtual void init();
Bus(const std::string &n, int bus_id)
- : MemObject(n), busId(bus_id) {}
+ : MemObject(n), busId(bus_id), defaultPort(NULL) {}
};
diff --git a/src/mem/cache/base_cache.cc b/src/mem/cache/base_cache.cc
index aaaf1bdef..15a21efa1 100644
--- a/src/mem/cache/base_cache.cc
+++ b/src/mem/cache/base_cache.cc
@@ -98,6 +98,37 @@ BaseCache::CachePort::clearBlocked()
blocked = false;
}
+BaseCache::CacheEvent::CacheEvent(CachePort *_cachePort)
+ : Event(&mainEventQueue, CPU_Tick_Pri), cachePort(_cachePort)
+{
+ this->setFlags(AutoDelete);
+ pkt = NULL;
+}
+
+BaseCache::CacheEvent::CacheEvent(CachePort *_cachePort, Packet *_pkt)
+ : Event(&mainEventQueue, CPU_Tick_Pri), cachePort(_cachePort), pkt(_pkt)
+{
+ this->setFlags(AutoDelete);
+}
+
+void
+BaseCache::CacheEvent::process()
+{
+ if (!pkt)
+ {
+ if (!cachePort->isCpuSide)
+ pkt = cachePort->cache->getPacket();
+ //Else get coherence req
+ }
+ cachePort->sendTiming(pkt);
+}
+
+const char *
+BaseCache::CacheEvent::description()
+{
+ return "timing event\n";
+}
+
Port*
BaseCache::getPort(const std::string &if_name, int idx)
{
diff --git a/src/mem/cache/base_cache.hh b/src/mem/cache/base_cache.hh
index 2754fab5a..5370a73c8 100644
--- a/src/mem/cache/base_cache.hh
+++ b/src/mem/cache/base_cache.hh
@@ -79,9 +79,9 @@ class BaseCache : public MemObject
{
class CachePort : public Port
{
+ public:
BaseCache *cache;
- public:
CachePort(const std::string &_name, BaseCache *_cache, bool _isCpuSide);
protected:
@@ -110,10 +110,11 @@ class BaseCache : public MemObject
struct CacheEvent : public Event
{
- Packet *pkt;
CachePort *cachePort;
+ Packet *pkt;
- CacheEvent(Packet *pkt, CachePort *cachePort);
+ CacheEvent(CachePort *_cachePort);
+ CacheEvent(CachePort *_cachePort, Packet *_pkt);
void process();
const char *description();
};
@@ -147,6 +148,11 @@ class BaseCache : public MemObject
fatal("No implementation");
}
+ virtual Packet *getPacket()
+ {
+ fatal("No implementation");
+ }
+
/**
* Bit vector of the blocking reasons for the access path.
* @sa #BlockedCause
@@ -388,7 +394,6 @@ class BaseCache : public MemObject
if (!isBlockedForSnoop()) {
memSidePort->clearBlocked();
}
-
}
/**
@@ -407,10 +412,13 @@ class BaseCache : public MemObject
*/
void setMasterRequest(RequestCause cause, Tick time)
{
+ if (!doMasterRequest())
+ {
+ BaseCache::CacheEvent * reqCpu = new BaseCache::CacheEvent(memSidePort);
+ reqCpu->schedule(time);
+ }
uint8_t flag = 1<<cause;
masterRequests |= flag;
- assert("Implement\n" && 0);
-// mi->pktuest(time);
}
/**
@@ -462,8 +470,10 @@ class BaseCache : public MemObject
*/
void respond(Packet *pkt, Tick time)
{
- assert("Implement\n" && 0);
-// si->respond(pkt,time);
+ pkt->makeTimingResponse();
+ pkt->result = Packet::Success;
+ CacheEvent *reqCpu = new CacheEvent(cpuSidePort, pkt);
+ reqCpu->schedule(time);
}
/**
@@ -476,8 +486,10 @@ class BaseCache : public MemObject
if (!pkt->req->isUncacheable()) {
missLatency[pkt->cmdToIndex()][pkt->req->getThreadNum()] += time - pkt->time;
}
- assert("Implement\n" && 0);
-// si->respond(pkt,time);
+ pkt->makeTimingResponse();
+ pkt->result = Packet::Success;
+ CacheEvent *reqCpu = new CacheEvent(cpuSidePort, pkt);
+ reqCpu->schedule(time);
}
/**
diff --git a/src/mem/cache/cache.hh b/src/mem/cache/cache.hh
index 1243c9d9e..2e77444a0 100644
--- a/src/mem/cache/cache.hh
+++ b/src/mem/cache/cache.hh
@@ -168,7 +168,7 @@ class Cache : public BaseCache
* Selects a request to send on the bus.
* @return The memory request to service.
*/
- Packet * getPacket();
+ virtual Packet * getPacket();
/**
* Was the request was sent successfully?
@@ -242,17 +242,6 @@ class Cache : public BaseCache
}
/**
- * Send a response to the slave interface.
- * @param req The request being responded to.
- * @param time The time the response is ready.
- */
- void respond(Packet * &pkt, Tick time)
- {
- //si->respond(pkt,time);
- cpuSidePort->sendAtomic(pkt);
- }
-
- /**
* Perform the access specified in the request and return the estimated
* time of completion. This function can either update the hierarchy state
* or just perform the access wherever the data is found depending on the
diff --git a/src/python/m5/__init__.py b/src/python/m5/__init__.py
index 828165d15..579785a46 100644
--- a/src/python/m5/__init__.py
+++ b/src/python/m5/__init__.py
@@ -213,14 +213,14 @@ atexit.register(cc_main.doExitCleanup)
# matter since most scripts will probably 'from m5.objects import *'.
import objects
-def doQuiesce(root):
- quiesce = cc_main.createCountedQuiesce()
- unready_objects = root.startQuiesce(quiesce, True)
- # If we've got some objects that can't quiesce immediately, then simulate
+def doDrain(root):
+ drain_event = cc_main.createCountedDrain()
+ unready_objects = root.startDrain(drain_event, True)
+ # If we've got some objects that can't drain immediately, then simulate
if unready_objects > 0:
- quiesce.setCount(unready_objects)
+ drain_event.setCount(unready_objects)
simulate()
- cc_main.cleanupCountedQuiesce(quiesce)
+ cc_main.cleanupCountedDrain(drain_event)
def resume(root):
root.resume()
@@ -228,7 +228,7 @@ def resume(root):
def checkpoint(root):
if not isinstance(root, objects.Root):
raise TypeError, "Object is not a root object. Checkpoint must be called on a root object."
- doQuiesce(root)
+ doDrain(root)
print "Writing checkpoint"
cc_main.serializeAll()
resume(root)
@@ -241,7 +241,7 @@ def changeToAtomic(system):
if not isinstance(system, objects.Root) and not isinstance(system, System):
raise TypeError, "Object is not a root or system object. Checkpoint must be "
"called on a root object."
- doQuiesce(system)
+ doDrain(system)
print "Changing memory mode to atomic"
system.changeTiming(cc_main.SimObject.Atomic)
resume(system)
@@ -250,7 +250,7 @@ def changeToTiming(system):
if not isinstance(system, objects.Root) and not isinstance(system, System):
raise TypeError, "Object is not a root or system object. Checkpoint must be "
"called on a root object."
- doQuiesce(system)
+ doDrain(system)
print "Changing memory mode to timing"
system.changeTiming(cc_main.SimObject.Timing)
resume(system)
@@ -271,16 +271,16 @@ def switchCpus(cpuList):
if not isinstance(cpu, objects.BaseCPU):
raise TypeError, "%s is not of type BaseCPU", cpu
- # Quiesce all of the individual CPUs
- quiesce = cc_main.createCountedQuiesce()
+ # Drain all of the individual CPUs
+ drain_event = cc_main.createCountedDrain()
unready_cpus = 0
for old_cpu in old_cpus:
- unready_cpus += old_cpu.startQuiesce(quiesce, False)
- # If we've got some objects that can't quiesce immediately, then simulate
+ unready_cpus += old_cpu.startDrain(drain_event, False)
+ # If we've got some objects that can't drain immediately, then simulate
if unready_cpus > 0:
- quiesce.setCount(unready_cpus)
+ drain_event.setCount(unready_cpus)
simulate()
- cc_main.cleanupCountedQuiesce(quiesce)
+ cc_main.cleanupCountedDrain(drain_event)
# Now all of the CPUs are ready to be switched out
for old_cpu in old_cpus:
old_cpu._ccObject.switchOut()
diff --git a/src/python/m5/config.py b/src/python/m5/config.py
index 6f2873d40..8291e1e1b 100644
--- a/src/python/m5/config.py
+++ b/src/python/m5/config.py
@@ -543,15 +543,15 @@ class SimObject(object):
for child in self._children.itervalues():
child.connectPorts()
- def startQuiesce(self, quiesce_event, recursive):
+ def startDrain(self, drain_event, recursive):
count = 0
# ParamContexts don't serialize
if isinstance(self, SimObject) and not isinstance(self, ParamContext):
- if self._ccObject.quiesce(quiesce_event):
+ if not self._ccObject.drain(drain_event):
count = 1
if recursive:
for child in self._children.itervalues():
- count += child.startQuiesce(quiesce_event, True)
+ count += child.startDrain(drain_event, True)
return count
def resume(self):
diff --git a/src/python/m5/objects/Bus.py b/src/python/m5/objects/Bus.py
index 019e15034..e0278e6c3 100644
--- a/src/python/m5/objects/Bus.py
+++ b/src/python/m5/objects/Bus.py
@@ -4,4 +4,5 @@ from MemObject import MemObject
class Bus(MemObject):
type = 'Bus'
port = VectorPort("vector port for connecting devices")
+ default = Port("Default port for requests that aren't handeled by a device.")
bus_id = Param.Int(0, "blah")
diff --git a/src/python/m5/objects/O3CPU.py b/src/python/m5/objects/O3CPU.py
index 4ecfa8fbd..9ccbdcf53 100644
--- a/src/python/m5/objects/O3CPU.py
+++ b/src/python/m5/objects/O3CPU.py
@@ -37,12 +37,10 @@ class DerivO3CPU(BaseCPU):
"Issue/Execute/Writeback delay")
issueToExecuteDelay = Param.Unsigned("Issue to execute delay (internal "
"to the IEW stage)")
+ dispatchWidth = Param.Unsigned("Dispatch width")
issueWidth = Param.Unsigned("Issue width")
- executeWidth = Param.Unsigned("Execute width")
- executeIntWidth = Param.Unsigned("Integer execute width")
- executeFloatWidth = Param.Unsigned("Floating point execute width")
- executeBranchWidth = Param.Unsigned("Branch execute width")
- executeMemoryWidth = Param.Unsigned("Memory execute width")
+ wbWidth = Param.Unsigned("Writeback width")
+ wbDepth = Param.Unsigned("Writeback depth")
fuPool = Param.FUPool(NULL, "Functional Unit pool")
iewToCommitDelay = Param.Unsigned("Issue/Execute/Writeback to commit "
diff --git a/src/python/m5/objects/Pci.py b/src/python/m5/objects/Pci.py
index 9e1e91b13..29014bb37 100644
--- a/src/python/m5/objects/Pci.py
+++ b/src/python/m5/objects/Pci.py
@@ -1,5 +1,5 @@
from m5.config import *
-from Device import BasicPioDevice, DmaDevice
+from Device import BasicPioDevice, DmaDevice, PioDevice
class PciConfigData(SimObject):
type = 'PciConfigData'
@@ -38,18 +38,22 @@ class PciConfigData(SimObject):
MaximumLatency = Param.UInt8(0x00, "Maximum Latency")
MinimumGrant = Param.UInt8(0x00, "Minimum Grant")
-class PciConfigAll(BasicPioDevice):
+class PciConfigAll(PioDevice):
type = 'PciConfigAll'
+ pio_latency = Param.Tick(1, "Programmed IO latency in simticks")
+ bus = Param.UInt8(0x00, "PCI bus to act as config space for")
+ size = Param.MemorySize32('16MB', "Size of config space")
+
class PciDevice(DmaDevice):
type = 'PciDevice'
abstract = True
+ config = Port("PCI configuration space port")
pci_bus = Param.Int("PCI bus")
pci_dev = Param.Int("PCI device number")
pci_func = Param.Int("PCI function code")
pio_latency = Param.Tick(1, "Programmed IO latency in simticks")
configdata = Param.PciConfigData(Parent.any, "PCI Config data")
- configspace = Param.PciConfigAll(Parent.any, "PCI Configspace")
class PciFake(PciDevice):
type = 'PciFake'
diff --git a/src/sim/main.cc b/src/sim/main.cc
index 3eb7fa95d..e96a44930 100644
--- a/src/sim/main.cc
+++ b/src/sim/main.cc
@@ -523,19 +523,19 @@ simulate(Tick num_cycles = -1)
}
Event *
-createCountedQuiesce()
+createCountedDrain()
{
- return new CountedQuiesceEvent();
+ return new CountedDrainEvent();
}
void
-cleanupCountedQuiesce(Event *counted_quiesce)
+cleanupCountedDrain(Event *counted_drain)
{
- CountedQuiesceEvent *event =
- dynamic_cast<CountedQuiesceEvent *>(counted_quiesce);
+ CountedDrainEvent *event =
+ dynamic_cast<CountedDrainEvent *>(counted_drain);
if (event == NULL) {
- fatal("Called cleanupCountedQuiesce() on an event that was not "
- "a CountedQuiesceEvent.");
+ fatal("Called cleanupCountedDrain() on an event that was not "
+ "a CountedDrainEvent.");
}
assert(event->getCount() == 0);
delete event;
diff --git a/src/sim/pseudo_inst.cc b/src/sim/pseudo_inst.cc
index b2854e491..869805f5c 100644
--- a/src/sim/pseudo_inst.cc
+++ b/src/sim/pseudo_inst.cc
@@ -52,8 +52,6 @@
using namespace std;
-extern Sampler *SampCPU;
-
using namespace Stats;
using namespace TheISA;
@@ -209,6 +207,7 @@ namespace AlphaPseudo
{
if (!doCheckpointInsts)
return;
+ exitSimLoop("checkpoint");
}
uint64_t
@@ -280,7 +279,6 @@ namespace AlphaPseudo
void switchcpu(ThreadContext *tc)
{
- if (SampCPU)
- SampCPU->switchCPUs();
+ exitSimLoop("switchcpu");
}
}
diff --git a/src/sim/sim_events.cc b/src/sim/sim_events.cc
index 97f7ae03c..d9e8bdeaa 100644
--- a/src/sim/sim_events.cc
+++ b/src/sim/sim_events.cc
@@ -79,10 +79,10 @@ exitSimLoop(const std::string &message, int exit_code)
}
void
-CountedQuiesceEvent::process()
+CountedDrainEvent::process()
{
if (--count == 0) {
- exitSimLoop("Finished quiesce");
+ exitSimLoop("Finished drain");
}
}
diff --git a/src/sim/sim_events.hh b/src/sim/sim_events.hh
index 50368f258..3c4a9dd05 100644
--- a/src/sim/sim_events.hh
+++ b/src/sim/sim_events.hh
@@ -67,13 +67,13 @@ class SimLoopExitEvent : public Event
virtual const char *description();
};
-class CountedQuiesceEvent : public SimLoopExitEvent
+class CountedDrainEvent : public SimLoopExitEvent
{
private:
- // Count down to quiescing
+ // Count of how many objects have not yet drained
int count;
public:
- CountedQuiesceEvent()
+ CountedDrainEvent()
: count(0)
{ }
void process();
diff --git a/src/sim/sim_object.cc b/src/sim/sim_object.cc
index 551555b25..a0278dba0 100644
--- a/src/sim/sim_object.cc
+++ b/src/sim/sim_object.cc
@@ -37,7 +37,6 @@
#include "base/misc.hh"
#include "base/trace.hh"
#include "base/stats/events.hh"
-#include "base/serializer.hh"
#include "sim/host.hh"
#include "sim/sim_object.hh"
#include "sim/stats.hh"
@@ -271,22 +270,22 @@ SimObject::recordEvent(const std::string &stat)
}
bool
-SimObject::quiesce(Event *quiesce_event)
+SimObject::drain(Event *drain_event)
{
- if (state != QuiescedAtomic && state != Atomic) {
- panic("Must implement your own quiesce function if it is to be used "
+ if (state != DrainedAtomic && state != Atomic) {
+ panic("Must implement your own drain function if it is to be used "
"in timing mode!");
}
- state = QuiescedAtomic;
- return false;
+ state = DrainedAtomic;
+ return true;
}
void
SimObject::resume()
{
- if (state == QuiescedAtomic) {
+ if (state == DrainedAtomic) {
state = Atomic;
- } else if (state == QuiescedTiming) {
+ } else if (state == DrainedTiming) {
state = Timing;
}
}
@@ -295,10 +294,10 @@ void
SimObject::setMemoryMode(State new_mode)
{
assert(new_mode == Timing || new_mode == Atomic);
- if (state == QuiescedAtomic && new_mode == Timing) {
- state = QuiescedTiming;
- } else if (state == QuiescedTiming && new_mode == Atomic) {
- state = QuiescedAtomic;
+ if (state == DrainedAtomic && new_mode == Timing) {
+ state = DrainedTiming;
+ } else if (state == DrainedTiming && new_mode == Atomic) {
+ state = DrainedAtomic;
} else {
state = new_mode;
}
diff --git a/src/sim/sim_object.hh b/src/sim/sim_object.hh
index e0b21782f..7ecc00958 100644
--- a/src/sim/sim_object.hh
+++ b/src/sim/sim_object.hh
@@ -62,9 +62,9 @@ class SimObject : public Serializable, protected StartupCallback
enum State {
Atomic,
Timing,
- Quiescing,
- QuiescedAtomic,
- QuiescedTiming
+ Draining,
+ DrainedAtomic,
+ DrainedTiming
};
protected:
@@ -116,8 +116,8 @@ class SimObject : public Serializable, protected StartupCallback
// Methods to drain objects in order to take checkpoints
// Or switch from timing -> atomic memory model
- // Quiesce returns true if the SimObject cannot quiesce immediately.
- virtual bool quiesce(Event *quiesce_event);
+ // Drain returns false if the SimObject cannot drain immediately.
+ virtual bool drain(Event *drain_event);
virtual void resume();
virtual void setMemoryMode(State new_mode);
virtual void switchOut();