Merge zeep.pool:/z/saidi/work/m5.newmem
into zeep.pool:/z/saidi/work/m5.newmem.head --HG-- extra : convert_revision : 1344e6a30073a1091a904593e6d4733baf19d7e2
This commit is contained in:
commit
f456360bbc
41 changed files with 884 additions and 791 deletions
54
SConstruct
54
SConstruct
|
@ -105,9 +105,10 @@ def rfind(l, elt, offs = -1):
|
||||||
# recognize that ALPHA_SE specifies the configuration because it
|
# recognize that ALPHA_SE specifies the configuration because it
|
||||||
# follow 'build' in the bulid path.
|
# follow 'build' in the bulid path.
|
||||||
|
|
||||||
# Generate a list of the unique configs that the collected targets
|
# Generate a list of the unique build roots and configs that the
|
||||||
# reference.
|
# collected targets reference.
|
||||||
build_paths = []
|
build_paths = []
|
||||||
|
build_root = None
|
||||||
for t in abs_targets:
|
for t in abs_targets:
|
||||||
path_dirs = t.split('/')
|
path_dirs = t.split('/')
|
||||||
try:
|
try:
|
||||||
|
@ -115,9 +116,17 @@ for t in abs_targets:
|
||||||
except:
|
except:
|
||||||
print "Error: no non-leaf 'build' dir found on target path", t
|
print "Error: no non-leaf 'build' dir found on target path", t
|
||||||
Exit(1)
|
Exit(1)
|
||||||
config_dir = os.path.join('/',*path_dirs[:build_top+2])
|
this_build_root = os.path.join('/',*path_dirs[:build_top+1])
|
||||||
if config_dir not in build_paths:
|
if not build_root:
|
||||||
build_paths.append(config_dir)
|
build_root = this_build_root
|
||||||
|
else:
|
||||||
|
if this_build_root != build_root:
|
||||||
|
print "Error: build targets not under same build root\n"\
|
||||||
|
" %s\n %s" % (build_root, this_build_root)
|
||||||
|
Exit(1)
|
||||||
|
build_path = os.path.join('/',*path_dirs[:build_top+2])
|
||||||
|
if build_path not in build_paths:
|
||||||
|
build_paths.append(build_path)
|
||||||
|
|
||||||
###################################################
|
###################################################
|
||||||
#
|
#
|
||||||
|
@ -153,8 +162,11 @@ env.Append(CPPPATH=[Dir('ext/dnet')])
|
||||||
# Default libraries
|
# Default libraries
|
||||||
env.Append(LIBS=['z'])
|
env.Append(LIBS=['z'])
|
||||||
|
|
||||||
# Platform-specific configuration
|
# Platform-specific configuration. Note again that we assume that all
|
||||||
conf = Configure(env)
|
# builds under a given build root run on the same host platform.
|
||||||
|
conf = Configure(env,
|
||||||
|
conf_dir = os.path.join(build_root, '.scons_config'),
|
||||||
|
log_file = os.path.join(build_root, 'scons_config.log'))
|
||||||
|
|
||||||
# Check for <fenv.h> (C99 FP environment control)
|
# Check for <fenv.h> (C99 FP environment control)
|
||||||
have_fenv = conf.CheckHeader('fenv.h', '<>')
|
have_fenv = conf.CheckHeader('fenv.h', '<>')
|
||||||
|
@ -195,7 +207,7 @@ env['ALL_ISA_LIST'] = ['alpha', 'sparc', 'mips']
|
||||||
|
|
||||||
# Define the universe of supported CPU models
|
# Define the universe of supported CPU models
|
||||||
env['ALL_CPU_LIST'] = ['AtomicSimpleCPU', 'TimingSimpleCPU',
|
env['ALL_CPU_LIST'] = ['AtomicSimpleCPU', 'TimingSimpleCPU',
|
||||||
'FastCPU', 'FullCPU', 'AlphaFullCPU']
|
'FullCPU', 'AlphaFullCPU']
|
||||||
|
|
||||||
# Sticky options get saved in the options file so they persist from
|
# Sticky options get saved in the options file so they persist from
|
||||||
# one invocation to the next (unless overridden, in which case the new
|
# one invocation to the next (unless overridden, in which case the new
|
||||||
|
@ -208,7 +220,8 @@ sticky_opts.AddOptions(
|
||||||
# values (more than one value) not to be able to be restored from
|
# values (more than one value) not to be able to be restored from
|
||||||
# a saved option file. If this causes trouble then upgrade to
|
# a saved option file. If this causes trouble then upgrade to
|
||||||
# scons 0.96.90 or later.
|
# scons 0.96.90 or later.
|
||||||
ListOption('CPU_MODELS', 'CPU models', 'all', env['ALL_CPU_LIST']),
|
ListOption('CPU_MODELS', 'CPU models', 'AtomicSimpleCPU,TimingSimpleCPU',
|
||||||
|
env['ALL_CPU_LIST']),
|
||||||
BoolOption('ALPHA_TLASER',
|
BoolOption('ALPHA_TLASER',
|
||||||
'Model Alpha TurboLaser platform (vs. Tsunami)', False),
|
'Model Alpha TurboLaser platform (vs. Tsunami)', False),
|
||||||
BoolOption('NO_FAST_ALLOC', 'Disable fast object allocator', False),
|
BoolOption('NO_FAST_ALLOC', 'Disable fast object allocator', False),
|
||||||
|
@ -246,11 +259,6 @@ def no_action(target, source, env):
|
||||||
|
|
||||||
env.NoAction = Action(no_action, None)
|
env.NoAction = Action(no_action, None)
|
||||||
|
|
||||||
# libelf build is described in its own SConscript file.
|
|
||||||
# SConscript-global is the build in build/libelf shared among all
|
|
||||||
# configs.
|
|
||||||
env.SConscript('src/libelf/SConscript-global', exports = 'env')
|
|
||||||
|
|
||||||
###################################################
|
###################################################
|
||||||
#
|
#
|
||||||
# Define a SCons builder for configuration flag headers.
|
# Define a SCons builder for configuration flag headers.
|
||||||
|
@ -292,6 +300,17 @@ config_builder = Builder(emitter = config_emitter, action = config_action)
|
||||||
|
|
||||||
env.Append(BUILDERS = { 'ConfigFile' : config_builder })
|
env.Append(BUILDERS = { 'ConfigFile' : config_builder })
|
||||||
|
|
||||||
|
# base help text
|
||||||
|
help_text = '''
|
||||||
|
Usage: scons [scons options] [build options] [target(s)]
|
||||||
|
|
||||||
|
'''
|
||||||
|
|
||||||
|
# libelf build is shared across all configs in the build root.
|
||||||
|
env.SConscript('ext/libelf/SConscript',
|
||||||
|
build_dir = os.path.join(build_root, 'libelf'),
|
||||||
|
exports = 'env')
|
||||||
|
|
||||||
###################################################
|
###################################################
|
||||||
#
|
#
|
||||||
# Define build environments for selected configurations.
|
# Define build environments for selected configurations.
|
||||||
|
@ -301,17 +320,12 @@ env.Append(BUILDERS = { 'ConfigFile' : config_builder })
|
||||||
# rename base env
|
# rename base env
|
||||||
base_env = env
|
base_env = env
|
||||||
|
|
||||||
help_text = '''
|
|
||||||
Usage: scons [scons options] [build options] [target(s)]
|
|
||||||
|
|
||||||
'''
|
|
||||||
|
|
||||||
for build_path in build_paths:
|
for build_path in build_paths:
|
||||||
print "Building in", build_path
|
print "Building in", build_path
|
||||||
# build_dir is the tail component of build path, and is used to
|
# build_dir is the tail component of build path, and is used to
|
||||||
# determine the build parameters (e.g., 'ALPHA_SE')
|
# determine the build parameters (e.g., 'ALPHA_SE')
|
||||||
(build_root, build_dir) = os.path.split(build_path)
|
(build_root, build_dir) = os.path.split(build_path)
|
||||||
# Make a copy of the default environment to use for this config.
|
# Make a copy of the build-root environment to use for this config.
|
||||||
env = base_env.Copy()
|
env = base_env.Copy()
|
||||||
|
|
||||||
# Set env options according to the build directory config.
|
# Set env options according to the build directory config.
|
||||||
|
|
|
@ -326,10 +326,6 @@ env.Command(Split('base/traceflags.hh base/traceflags.cc'),
|
||||||
'base/traceflags.py',
|
'base/traceflags.py',
|
||||||
'python $SOURCE $TARGET.base')
|
'python $SOURCE $TARGET.base')
|
||||||
|
|
||||||
# libelf build is described in its own SConscript file.
|
|
||||||
# SConscript-local is the per-config build, which just copies some
|
|
||||||
# header files into a place where they can be found.
|
|
||||||
SConscript('libelf/SConscript-local', exports = 'env', duplicate=0)
|
|
||||||
SConscript('python/SConscript', exports = ['env'], duplicate=0)
|
SConscript('python/SConscript', exports = ['env'], duplicate=0)
|
||||||
|
|
||||||
# This function adds the specified sources to the given build
|
# This function adds the specified sources to the given build
|
||||||
|
@ -358,7 +354,6 @@ def make_objs(sources, env):
|
||||||
# the corresponding build directory to pick up generated include
|
# the corresponding build directory to pick up generated include
|
||||||
# files.
|
# files.
|
||||||
env.Append(CPPPATH='.')
|
env.Append(CPPPATH='.')
|
||||||
env.Append(CPPPATH='./libelf')
|
|
||||||
|
|
||||||
# Debug binary
|
# Debug binary
|
||||||
debugEnv = env.Copy(OBJSUFFIX='.do')
|
debugEnv = env.Copy(OBJSUFFIX='.do')
|
||||||
|
|
|
@ -132,7 +132,7 @@ def isa_desc_emitter(target, source, env):
|
||||||
return (isa_desc_gen_files, [isa_parser, cpu_models_file] + source)
|
return (isa_desc_gen_files, [isa_parser, cpu_models_file] + source)
|
||||||
|
|
||||||
# Pieces are in place, so create the builder.
|
# Pieces are in place, so create the builder.
|
||||||
isa_desc_builder = Builder(action='python $SOURCES $TARGET.dir $CPU_MODELS',
|
isa_desc_builder = Builder(action='python2.4 $SOURCES $TARGET.dir $CPU_MODELS',
|
||||||
emitter = isa_desc_emitter)
|
emitter = isa_desc_emitter)
|
||||||
|
|
||||||
env.Append(BUILDERS = { 'ISADesc' : isa_desc_builder })
|
env.Append(BUILDERS = { 'ISADesc' : isa_desc_builder })
|
||||||
|
|
|
@ -32,6 +32,16 @@
|
||||||
// Nop instruction
|
// Nop instruction
|
||||||
//
|
//
|
||||||
|
|
||||||
|
// Per-cpu-model nop execute method.
|
||||||
|
def template NopExec {{
|
||||||
|
|
||||||
|
Fault execute(%(CPU_exec_context)s *xc, Trace::InstRecord *traceData) const
|
||||||
|
{
|
||||||
|
// Nothing to see here, move along
|
||||||
|
return NoFault;
|
||||||
|
}
|
||||||
|
}};
|
||||||
|
|
||||||
output header {{
|
output header {{
|
||||||
/**
|
/**
|
||||||
* Nop class.
|
* Nop class.
|
||||||
|
@ -46,14 +56,11 @@ output header {{
|
||||||
}
|
}
|
||||||
|
|
||||||
// All Nop instructions do the same thing, so this can be
|
// All Nop instructions do the same thing, so this can be
|
||||||
// defined here. Nops can be defined directly, so there needs
|
// defined here. Nops can be defined directly, so there
|
||||||
// to be a default implementation
|
// needs to be a default implementation. Interpolate via
|
||||||
Fault execute(%(CPU_exec_context)s *xc,
|
// template so i gets expanded to a set of
|
||||||
Trace::InstRecord *traceData) const
|
// cpu-model-specific functions.
|
||||||
{
|
%(NopExec)s
|
||||||
//Nothing to see here, move along
|
|
||||||
return NoFault;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string generateDisassembly(Addr pc,
|
std::string generateDisassembly(Addr pc,
|
||||||
const SymbolTable *symtab) const;
|
const SymbolTable *symtab) const;
|
||||||
|
|
|
@ -30,16 +30,10 @@
|
||||||
|
|
||||||
// Because of the -Wundef flag we have to do this
|
// Because of the -Wundef flag we have to do this
|
||||||
#define __LIBELF_INTERNAL__ 0
|
#define __LIBELF_INTERNAL__ 0
|
||||||
// counterintuitive, but the flag below causes libelf to define
|
|
||||||
// 64-bit elf types that apparently didn't exist in some older
|
|
||||||
// versions of Linux. They seem to be there in 2.4.x, so don't
|
|
||||||
// set this now (it causes things to break on 64-bit platforms).
|
|
||||||
#define __LIBELF64_LINUX 0
|
|
||||||
#define __LIBELF_NEED_LINK_H 0
|
#define __LIBELF_NEED_LINK_H 0
|
||||||
#define __LIBELF_SYMBOL_VERSIONS 0
|
#define __LIBELF_SYMBOL_VERSIONS 0
|
||||||
|
|
||||||
#include "libelf/libelf.h"
|
#include "gelf.h"
|
||||||
#include "libelf/gelf.h"
|
|
||||||
|
|
||||||
#include "base/loader/elf_object.hh"
|
#include "base/loader/elf_object.hh"
|
||||||
#include "base/misc.hh"
|
#include "base/misc.hh"
|
||||||
|
|
|
@ -45,105 +45,107 @@ ccfilename = sys.argv[1] + '.cc'
|
||||||
# To define a new flag, simply add it to this list.
|
# To define a new flag, simply add it to this list.
|
||||||
#
|
#
|
||||||
baseFlags = [
|
baseFlags = [
|
||||||
'TCPIP',
|
'AlphaConsole',
|
||||||
'Bus',
|
|
||||||
'ScsiDisk',
|
|
||||||
'ScsiCtrl',
|
|
||||||
'ScsiNone',
|
|
||||||
'DMA',
|
|
||||||
'DMAReadVerbose',
|
|
||||||
'DMAWriteVerbose',
|
|
||||||
'TLB',
|
|
||||||
'SimpleDisk',
|
|
||||||
'SimpleDiskData',
|
|
||||||
'Clock',
|
|
||||||
'Regs',
|
|
||||||
'MC146818',
|
|
||||||
'IPI',
|
|
||||||
'Timer',
|
|
||||||
'Mbox',
|
|
||||||
'PCIA',
|
|
||||||
'PCIDEV',
|
|
||||||
'PciConfigAll',
|
|
||||||
'ISP',
|
|
||||||
'BADADDR',
|
'BADADDR',
|
||||||
|
'BPredRAS',
|
||||||
|
'Bus',
|
||||||
|
'BusAddrRanges',
|
||||||
|
'BusBridge',
|
||||||
|
'Cache',
|
||||||
|
'Chains',
|
||||||
|
'Clock',
|
||||||
|
'Commit',
|
||||||
|
'CommitRate',
|
||||||
|
'Config',
|
||||||
'Console',
|
'Console',
|
||||||
'ConsolePoll',
|
'ConsolePoll',
|
||||||
'ConsoleVerbose',
|
'ConsoleVerbose',
|
||||||
'AlphaConsole',
|
'Context',
|
||||||
'Flow',
|
|
||||||
'Interrupt',
|
|
||||||
'Fault',
|
|
||||||
'Cycle',
|
'Cycle',
|
||||||
'Loader',
|
'DMA',
|
||||||
'MMU',
|
'DMAReadVerbose',
|
||||||
|
'DMAWriteVerbose',
|
||||||
|
'DebugPrintf',
|
||||||
|
'Decode',
|
||||||
|
'DiskImage',
|
||||||
|
'DiskImageRead',
|
||||||
|
'DiskImageWrite',
|
||||||
|
'DynInst',
|
||||||
'Ethernet',
|
'Ethernet',
|
||||||
'EthernetPIO',
|
'EthernetCksum',
|
||||||
'EthernetDMA',
|
'EthernetDMA',
|
||||||
'EthernetData',
|
'EthernetData',
|
||||||
'EthernetDesc',
|
'EthernetDesc',
|
||||||
'EthernetIntr',
|
'EthernetIntr',
|
||||||
|
'EthernetPIO',
|
||||||
'EthernetSM',
|
'EthernetSM',
|
||||||
'EthernetCksum',
|
|
||||||
'GDBMisc',
|
|
||||||
'GDBAcc',
|
|
||||||
'GDBRead',
|
|
||||||
'GDBWrite',
|
|
||||||
'GDBSend',
|
|
||||||
'GDBRecv',
|
|
||||||
'GDBExtra',
|
|
||||||
'VtoPhys',
|
|
||||||
'Printf',
|
|
||||||
'DebugPrintf',
|
|
||||||
'Serialize',
|
|
||||||
'Event',
|
'Event',
|
||||||
'PCEvent',
|
'Fault',
|
||||||
'Syscall',
|
'Fetch',
|
||||||
'SyscallVerbose',
|
'Flow',
|
||||||
'DiskImage',
|
'FreeList',
|
||||||
'DiskImageRead',
|
'FullCPU',
|
||||||
'DiskImageWrite',
|
'GDBAcc',
|
||||||
'InstExec',
|
'GDBExtra',
|
||||||
'BPredRAS',
|
'GDBMisc',
|
||||||
'Cache',
|
'GDBRead',
|
||||||
|
'GDBRecv',
|
||||||
|
'GDBSend',
|
||||||
|
'GDBWrite',
|
||||||
|
'HWPrefetch',
|
||||||
|
'IEW',
|
||||||
'IIC',
|
'IIC',
|
||||||
'IICMore',
|
'IICMore',
|
||||||
'MSHR',
|
'IPI',
|
||||||
'Chains',
|
'IQ',
|
||||||
'Pipeline',
|
'ISP',
|
||||||
'Stats',
|
|
||||||
'StatEvents',
|
|
||||||
'Context',
|
|
||||||
'Config',
|
|
||||||
'Sampler',
|
|
||||||
'WriteBarrier',
|
|
||||||
'IdeCtrl',
|
'IdeCtrl',
|
||||||
'IdeDisk',
|
'IdeDisk',
|
||||||
|
'InstExec',
|
||||||
|
'Interrupt',
|
||||||
|
'LDSTQ',
|
||||||
|
'Loader',
|
||||||
|
'MC146818',
|
||||||
|
'MMU',
|
||||||
|
'MSHR',
|
||||||
|
'Mbox',
|
||||||
|
'MemDepUnit',
|
||||||
|
'OoOCPU',
|
||||||
|
'PCEvent',
|
||||||
|
'PCIA',
|
||||||
|
'PCIDEV',
|
||||||
|
'PciConfigAll',
|
||||||
|
'Pipeline',
|
||||||
|
'Printf',
|
||||||
|
'ROB',
|
||||||
|
'Regs',
|
||||||
|
'Rename',
|
||||||
|
'RenameMap',
|
||||||
|
'SQL',
|
||||||
|
'Sampler',
|
||||||
|
'ScsiCtrl',
|
||||||
|
'ScsiDisk',
|
||||||
|
'ScsiNone',
|
||||||
|
'Serialize',
|
||||||
|
'SimpleCPU',
|
||||||
|
'SimpleDisk',
|
||||||
|
'SimpleDiskData',
|
||||||
|
'Sparc',
|
||||||
|
'Split',
|
||||||
|
'Stack',
|
||||||
|
'StatEvents',
|
||||||
|
'Stats',
|
||||||
|
'StoreSet',
|
||||||
|
'Syscall',
|
||||||
|
'SyscallVerbose',
|
||||||
|
'TCPIP',
|
||||||
|
'TLB',
|
||||||
|
'Thread',
|
||||||
|
'Timer',
|
||||||
'Tsunami',
|
'Tsunami',
|
||||||
'Uart',
|
'Uart',
|
||||||
'Split',
|
'VtoPhys',
|
||||||
'SQL',
|
'WriteBarrier',
|
||||||
'Thread',
|
|
||||||
'Fetch',
|
|
||||||
'Decode',
|
|
||||||
'Rename',
|
|
||||||
'IEW',
|
|
||||||
'Commit',
|
|
||||||
'IQ',
|
|
||||||
'ROB',
|
|
||||||
'FreeList',
|
|
||||||
'RenameMap',
|
|
||||||
'LDSTQ',
|
|
||||||
'StoreSet',
|
|
||||||
'MemDepUnit',
|
|
||||||
'DynInst',
|
|
||||||
'FullCPU',
|
|
||||||
'CommitRate',
|
|
||||||
'OoOCPU',
|
|
||||||
'HWPrefetch',
|
|
||||||
'Stack',
|
|
||||||
'SimpleCPU',
|
|
||||||
'Sparc',
|
|
||||||
]
|
]
|
||||||
|
|
||||||
#
|
#
|
||||||
|
|
|
@ -80,12 +80,14 @@ CPUExecContext::CPUExecContext(BaseCPU *_cpu, int _thread_num, System *_sys,
|
||||||
profilePC = 3;
|
profilePC = 3;
|
||||||
|
|
||||||
Port *mem_port;
|
Port *mem_port;
|
||||||
physPort = new FunctionalPort();
|
physPort = new FunctionalPort(csprintf("%s-%d-funcport",
|
||||||
|
cpu->name(), thread_num));
|
||||||
mem_port = system->physmem->getPort("functional");
|
mem_port = system->physmem->getPort("functional");
|
||||||
mem_port->setPeer(physPort);
|
mem_port->setPeer(physPort);
|
||||||
physPort->setPeer(mem_port);
|
physPort->setPeer(mem_port);
|
||||||
|
|
||||||
virtPort = new VirtualPort();
|
virtPort = new VirtualPort(csprintf("%s-%d-vport",
|
||||||
|
cpu->name(), thread_num));
|
||||||
mem_port = system->physmem->getPort("functional");
|
mem_port = system->physmem->getPort("functional");
|
||||||
mem_port->setPeer(virtPort);
|
mem_port->setPeer(virtPort);
|
||||||
virtPort->setPeer(mem_port);
|
virtPort->setPeer(mem_port);
|
||||||
|
@ -100,7 +102,9 @@ CPUExecContext::CPUExecContext(BaseCPU *_cpu, int _thread_num,
|
||||||
{
|
{
|
||||||
/* Use this port to for syscall emulation writes to memory. */
|
/* Use this port to for syscall emulation writes to memory. */
|
||||||
Port *mem_port;
|
Port *mem_port;
|
||||||
port = new TranslatingPort(process->pTable, false);
|
port = new TranslatingPort(csprintf("%s-%d-funcport",
|
||||||
|
cpu->name(), thread_num),
|
||||||
|
process->pTable, false);
|
||||||
mem_port = memobj->getPort("functional");
|
mem_port = memobj->getPort("functional");
|
||||||
mem_port->setPeer(port);
|
mem_port->setPeer(port);
|
||||||
port->setPeer(mem_port);
|
port->setPeer(mem_port);
|
||||||
|
@ -300,7 +304,7 @@ CPUExecContext::getVirtPort(ExecContext *xc)
|
||||||
VirtualPort *vp;
|
VirtualPort *vp;
|
||||||
Port *mem_port;
|
Port *mem_port;
|
||||||
|
|
||||||
vp = new VirtualPort(xc);
|
vp = new VirtualPort("xc-vport", xc);
|
||||||
mem_port = system->physmem->getPort("functional");
|
mem_port = system->physmem->getPort("functional");
|
||||||
mem_port->setPeer(vp);
|
mem_port->setPeer(vp);
|
||||||
vp->setPeer(mem_port);
|
vp->setPeer(mem_port);
|
||||||
|
|
|
@ -62,9 +62,6 @@ CpuModel('AtomicSimpleCPU', 'atomic_simple_cpu_exec.cc',
|
||||||
CpuModel('TimingSimpleCPU', 'timing_simple_cpu_exec.cc',
|
CpuModel('TimingSimpleCPU', 'timing_simple_cpu_exec.cc',
|
||||||
'#include "cpu/simple/timing.hh"',
|
'#include "cpu/simple/timing.hh"',
|
||||||
{ 'CPU_exec_context': 'TimingSimpleCPU' })
|
{ 'CPU_exec_context': 'TimingSimpleCPU' })
|
||||||
CpuModel('FastCPU', 'fast_cpu_exec.cc',
|
|
||||||
'#include "cpu/fast/cpu.hh"',
|
|
||||||
{ 'CPU_exec_context': 'FastCPU' })
|
|
||||||
CpuModel('FullCPU', 'full_cpu_exec.cc',
|
CpuModel('FullCPU', 'full_cpu_exec.cc',
|
||||||
'#include "encumbered/cpu/full/dyn_inst.hh"',
|
'#include "encumbered/cpu/full/dyn_inst.hh"',
|
||||||
{ 'CPU_exec_context': 'DynInst' })
|
{ 'CPU_exec_context': 'DynInst' })
|
||||||
|
|
|
@ -117,7 +117,7 @@ AtomicSimpleCPU::CpuPort::recvRetry()
|
||||||
AtomicSimpleCPU::AtomicSimpleCPU(Params *p)
|
AtomicSimpleCPU::AtomicSimpleCPU(Params *p)
|
||||||
: BaseSimpleCPU(p), tickEvent(this),
|
: BaseSimpleCPU(p), tickEvent(this),
|
||||||
width(p->width), simulate_stalls(p->simulate_stalls),
|
width(p->width), simulate_stalls(p->simulate_stalls),
|
||||||
icachePort(this), dcachePort(this)
|
icachePort(name() + "-iport", this), dcachePort(name() + "-iport", this)
|
||||||
{
|
{
|
||||||
_status = Idle;
|
_status = Idle;
|
||||||
|
|
||||||
|
@ -126,31 +126,23 @@ AtomicSimpleCPU::AtomicSimpleCPU(Params *p)
|
||||||
// @todo fix me and get the real cpu iD!!!
|
// @todo fix me and get the real cpu iD!!!
|
||||||
ifetch_req->setCpuNum(0);
|
ifetch_req->setCpuNum(0);
|
||||||
ifetch_req->setSize(sizeof(MachInst));
|
ifetch_req->setSize(sizeof(MachInst));
|
||||||
ifetch_pkt = new Packet;
|
ifetch_pkt = new Packet(ifetch_req, Packet::ReadReq, Packet::Broadcast);
|
||||||
ifetch_pkt->cmd = Read;
|
|
||||||
ifetch_pkt->dataStatic(&inst);
|
ifetch_pkt->dataStatic(&inst);
|
||||||
ifetch_pkt->req = ifetch_req;
|
|
||||||
ifetch_pkt->size = sizeof(MachInst);
|
|
||||||
ifetch_pkt->dest = Packet::Broadcast;
|
|
||||||
|
|
||||||
data_read_req = new Request(true);
|
data_read_req = new Request(true);
|
||||||
// @todo fix me and get the real cpu iD!!!
|
// @todo fix me and get the real cpu iD!!!
|
||||||
data_read_req->setCpuNum(0);
|
data_read_req->setCpuNum(0);
|
||||||
data_read_req->setAsid(0);
|
data_read_req->setAsid(0);
|
||||||
data_read_pkt = new Packet;
|
data_read_pkt = new Packet(data_read_req, Packet::ReadReq,
|
||||||
data_read_pkt->cmd = Read;
|
Packet::Broadcast);
|
||||||
data_read_pkt->dataStatic(&dataReg);
|
data_read_pkt->dataStatic(&dataReg);
|
||||||
data_read_pkt->req = data_read_req;
|
|
||||||
data_read_pkt->dest = Packet::Broadcast;
|
|
||||||
|
|
||||||
data_write_req = new Request(true);
|
data_write_req = new Request(true);
|
||||||
// @todo fix me and get the real cpu iD!!!
|
// @todo fix me and get the real cpu iD!!!
|
||||||
data_write_req->setCpuNum(0);
|
data_write_req->setCpuNum(0);
|
||||||
data_write_req->setAsid(0);
|
data_write_req->setAsid(0);
|
||||||
data_write_pkt = new Packet;
|
data_write_pkt = new Packet(data_write_req, Packet::WriteReq,
|
||||||
data_write_pkt->cmd = Write;
|
Packet::Broadcast);
|
||||||
data_write_pkt->req = data_write_req;
|
|
||||||
data_write_pkt->dest = Packet::Broadcast;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -260,13 +252,12 @@ AtomicSimpleCPU::read(Addr addr, T &data, unsigned flags)
|
||||||
// Now do the access.
|
// Now do the access.
|
||||||
if (fault == NoFault) {
|
if (fault == NoFault) {
|
||||||
data_read_pkt->reset();
|
data_read_pkt->reset();
|
||||||
data_read_pkt->addr = data_read_req->getPaddr();
|
data_read_pkt->reinitFromRequest();
|
||||||
data_read_pkt->size = sizeof(T);
|
|
||||||
|
|
||||||
dcache_complete = dcachePort.sendAtomic(data_read_pkt);
|
dcache_complete = dcachePort.sendAtomic(data_read_pkt);
|
||||||
dcache_access = true;
|
dcache_access = true;
|
||||||
|
|
||||||
assert(data_read_pkt->result == Success);
|
assert(data_read_pkt->result == Packet::Success);
|
||||||
data = data_read_pkt->get<T>();
|
data = data_read_pkt->get<T>();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -342,13 +333,12 @@ AtomicSimpleCPU::write(T data, Addr addr, unsigned flags, uint64_t *res)
|
||||||
data_write_pkt->reset();
|
data_write_pkt->reset();
|
||||||
data = htog(data);
|
data = htog(data);
|
||||||
data_write_pkt->dataStatic(&data);
|
data_write_pkt->dataStatic(&data);
|
||||||
data_write_pkt->addr = data_write_req->getPaddr();
|
data_write_pkt->reinitFromRequest();
|
||||||
data_write_pkt->size = sizeof(T);
|
|
||||||
|
|
||||||
dcache_complete = dcachePort.sendAtomic(data_write_pkt);
|
dcache_complete = dcachePort.sendAtomic(data_write_pkt);
|
||||||
dcache_access = true;
|
dcache_access = true;
|
||||||
|
|
||||||
assert(data_write_pkt->result == Success);
|
assert(data_write_pkt->result == Packet::Success);
|
||||||
|
|
||||||
if (res && data_write_req->getFlags() & LOCKED) {
|
if (res && data_write_req->getFlags() & LOCKED) {
|
||||||
*res = data_write_req->getScResult();
|
*res = data_write_req->getScResult();
|
||||||
|
@ -435,10 +425,6 @@ AtomicSimpleCPU::tick()
|
||||||
fault = curStaticInst->execute(this, traceData);
|
fault = curStaticInst->execute(this, traceData);
|
||||||
postExecute();
|
postExecute();
|
||||||
|
|
||||||
if (traceData) {
|
|
||||||
traceData->finalize();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (simulate_stalls) {
|
if (simulate_stalls) {
|
||||||
// This calculation assumes that the icache and dcache
|
// This calculation assumes that the icache and dcache
|
||||||
// access latencies are always a multiple of the CPU's
|
// access latencies are always a multiple of the CPU's
|
||||||
|
|
|
@ -84,8 +84,8 @@ class AtomicSimpleCPU : public BaseSimpleCPU
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
CpuPort(AtomicSimpleCPU *_cpu)
|
CpuPort(const std::string &_name, AtomicSimpleCPU *_cpu)
|
||||||
: cpu(_cpu)
|
: Port(_name), cpu(_cpu)
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
|
@ -372,7 +372,7 @@ BaseSimpleCPU::setupFetchPacket(Packet *ifetch_pkt)
|
||||||
Fault fault = cpuXC->translateInstReq(ifetch_req);
|
Fault fault = cpuXC->translateInstReq(ifetch_req);
|
||||||
|
|
||||||
if (fault == NoFault) {
|
if (fault == NoFault) {
|
||||||
ifetch_pkt->addr = ifetch_req->getPaddr();
|
ifetch_pkt->reinitFromRequest();
|
||||||
}
|
}
|
||||||
|
|
||||||
return fault;
|
return fault;
|
||||||
|
@ -442,6 +442,10 @@ BaseSimpleCPU::postExecute()
|
||||||
}
|
}
|
||||||
|
|
||||||
traceFunctions(cpuXC->readPC());
|
traceFunctions(cpuXC->readPC());
|
||||||
|
|
||||||
|
if (traceData) {
|
||||||
|
traceData->finalize();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -158,10 +158,11 @@ TimingSimpleCPU::suspendContext(int thread_num)
|
||||||
assert(thread_num == 0);
|
assert(thread_num == 0);
|
||||||
assert(cpuXC);
|
assert(cpuXC);
|
||||||
|
|
||||||
panic("TimingSimpleCPU::suspendContext not implemented");
|
|
||||||
|
|
||||||
assert(_status == Running);
|
assert(_status == Running);
|
||||||
|
|
||||||
|
// just change status to Idle... if status != Running,
|
||||||
|
// completeInst() will not initiate fetch of next instruction.
|
||||||
|
|
||||||
notIdleFraction--;
|
notIdleFraction--;
|
||||||
_status = Idle;
|
_status = Idle;
|
||||||
}
|
}
|
||||||
|
@ -187,13 +188,9 @@ TimingSimpleCPU::read(Addr addr, T &data, unsigned flags)
|
||||||
|
|
||||||
// Now do the access.
|
// Now do the access.
|
||||||
if (fault == NoFault) {
|
if (fault == NoFault) {
|
||||||
Packet *data_read_pkt = new Packet;
|
Packet *data_read_pkt =
|
||||||
data_read_pkt->cmd = Read;
|
new Packet(data_read_req, Packet::ReadReq, Packet::Broadcast);
|
||||||
data_read_pkt->req = data_read_req;
|
|
||||||
data_read_pkt->dataDynamic<T>(new T);
|
data_read_pkt->dataDynamic<T>(new T);
|
||||||
data_read_pkt->addr = data_read_req->getPaddr();
|
|
||||||
data_read_pkt->size = sizeof(T);
|
|
||||||
data_read_pkt->dest = Packet::Broadcast;
|
|
||||||
|
|
||||||
if (!dcachePort.sendTiming(data_read_pkt)) {
|
if (!dcachePort.sendTiming(data_read_pkt)) {
|
||||||
_status = DcacheRetry;
|
_status = DcacheRetry;
|
||||||
|
@ -268,14 +265,10 @@ TimingSimpleCPU::write(T data, Addr addr, unsigned flags, uint64_t *res)
|
||||||
Fault fault = cpuXC->translateDataWriteReq(data_write_req);
|
Fault fault = cpuXC->translateDataWriteReq(data_write_req);
|
||||||
// Now do the access.
|
// Now do the access.
|
||||||
if (fault == NoFault) {
|
if (fault == NoFault) {
|
||||||
Packet *data_write_pkt = new Packet;
|
Packet *data_write_pkt =
|
||||||
data_write_pkt->cmd = Write;
|
new Packet(data_write_req, Packet::WriteReq, Packet::Broadcast);
|
||||||
data_write_pkt->req = data_write_req;
|
|
||||||
data_write_pkt->allocate();
|
data_write_pkt->allocate();
|
||||||
data_write_pkt->size = sizeof(T);
|
|
||||||
data_write_pkt->set(data);
|
data_write_pkt->set(data);
|
||||||
data_write_pkt->addr = data_write_req->getPaddr();
|
|
||||||
data_write_pkt->dest = Packet::Broadcast;
|
|
||||||
|
|
||||||
if (!dcachePort.sendTiming(data_write_pkt)) {
|
if (!dcachePort.sendTiming(data_write_pkt)) {
|
||||||
_status = DcacheRetry;
|
_status = DcacheRetry;
|
||||||
|
@ -350,12 +343,8 @@ TimingSimpleCPU::fetch()
|
||||||
Request *ifetch_req = new Request(true);
|
Request *ifetch_req = new Request(true);
|
||||||
ifetch_req->setSize(sizeof(MachInst));
|
ifetch_req->setSize(sizeof(MachInst));
|
||||||
|
|
||||||
ifetch_pkt = new Packet;
|
ifetch_pkt = new Packet(ifetch_req, Packet::ReadReq, Packet::Broadcast);
|
||||||
ifetch_pkt->cmd = Read;
|
|
||||||
ifetch_pkt->dataStatic(&inst);
|
ifetch_pkt->dataStatic(&inst);
|
||||||
ifetch_pkt->req = ifetch_req;
|
|
||||||
ifetch_pkt->size = sizeof(MachInst);
|
|
||||||
ifetch_pkt->dest = Packet::Broadcast;
|
|
||||||
|
|
||||||
Fault fault = setupFetchPacket(ifetch_pkt);
|
Fault fault = setupFetchPacket(ifetch_pkt);
|
||||||
if (fault == NoFault) {
|
if (fault == NoFault) {
|
||||||
|
@ -369,20 +358,15 @@ TimingSimpleCPU::fetch()
|
||||||
ifetch_pkt = NULL;
|
ifetch_pkt = NULL;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
panic("TimingSimpleCPU fetch fault handling not implemented");
|
// fetch fault: advance directly to next instruction (fault handler)
|
||||||
|
advanceInst(fault);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
TimingSimpleCPU::completeInst(Fault fault)
|
TimingSimpleCPU::advanceInst(Fault fault)
|
||||||
{
|
{
|
||||||
postExecute();
|
|
||||||
|
|
||||||
if (traceData) {
|
|
||||||
traceData->finalize();
|
|
||||||
}
|
|
||||||
|
|
||||||
advancePC(fault);
|
advancePC(fault);
|
||||||
|
|
||||||
if (_status == Running) {
|
if (_status == Running) {
|
||||||
|
@ -395,23 +379,35 @@ TimingSimpleCPU::completeInst(Fault fault)
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
TimingSimpleCPU::completeIfetch()
|
TimingSimpleCPU::completeIfetch(Packet *pkt)
|
||||||
{
|
{
|
||||||
// received a response from the icache: execute the received
|
// received a response from the icache: execute the received
|
||||||
// instruction
|
// instruction
|
||||||
|
assert(pkt->result == Packet::Success);
|
||||||
assert(_status == IcacheWaitResponse);
|
assert(_status == IcacheWaitResponse);
|
||||||
_status = Running;
|
_status = Running;
|
||||||
|
|
||||||
|
delete pkt->req;
|
||||||
|
delete pkt;
|
||||||
|
|
||||||
preExecute();
|
preExecute();
|
||||||
if (curStaticInst->isMemRef()) {
|
if (curStaticInst->isMemRef() && !curStaticInst->isDataPrefetch()) {
|
||||||
// load or store: just send to dcache
|
// load or store: just send to dcache
|
||||||
Fault fault = curStaticInst->initiateAcc(this, traceData);
|
Fault fault = curStaticInst->initiateAcc(this, traceData);
|
||||||
assert(fault == NoFault);
|
if (fault == NoFault) {
|
||||||
|
// successfully initiated access: instruction will
|
||||||
|
// complete in dcache response callback
|
||||||
assert(_status == DcacheWaitResponse);
|
assert(_status == DcacheWaitResponse);
|
||||||
// instruction will complete in dcache response callback
|
} else {
|
||||||
|
// fault: complete now to invoke fault handler
|
||||||
|
postExecute();
|
||||||
|
advanceInst(fault);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
// non-memory instruction: execute completely now
|
// non-memory instruction: execute completely now
|
||||||
Fault fault = curStaticInst->execute(this, traceData);
|
Fault fault = curStaticInst->execute(this, traceData);
|
||||||
completeInst(fault);
|
postExecute();
|
||||||
|
advanceInst(fault);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -419,7 +415,7 @@ TimingSimpleCPU::completeIfetch()
|
||||||
bool
|
bool
|
||||||
TimingSimpleCPU::IcachePort::recvTiming(Packet *pkt)
|
TimingSimpleCPU::IcachePort::recvTiming(Packet *pkt)
|
||||||
{
|
{
|
||||||
cpu->completeIfetch();
|
cpu->completeIfetch(pkt);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -441,13 +437,17 @@ TimingSimpleCPU::completeDataAccess(Packet *pkt)
|
||||||
{
|
{
|
||||||
// received a response from the dcache: complete the load or store
|
// received a response from the dcache: complete the load or store
|
||||||
// instruction
|
// instruction
|
||||||
assert(pkt->result == Success);
|
assert(pkt->result == Packet::Success);
|
||||||
assert(_status == DcacheWaitResponse);
|
assert(_status == DcacheWaitResponse);
|
||||||
_status = Running;
|
_status = Running;
|
||||||
|
|
||||||
Fault fault = curStaticInst->completeAcc(pkt, this, traceData);
|
Fault fault = curStaticInst->completeAcc(pkt, this, traceData);
|
||||||
|
|
||||||
completeInst(fault);
|
delete pkt->req;
|
||||||
|
delete pkt;
|
||||||
|
|
||||||
|
postExecute();
|
||||||
|
advanceInst(fault);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -71,8 +71,8 @@ class TimingSimpleCPU : public BaseSimpleCPU
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
CpuPort(TimingSimpleCPU *_cpu)
|
CpuPort(const std::string &_name, TimingSimpleCPU *_cpu)
|
||||||
: cpu(_cpu)
|
: Port(_name), cpu(_cpu)
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
@ -93,7 +93,7 @@ class TimingSimpleCPU : public BaseSimpleCPU
|
||||||
public:
|
public:
|
||||||
|
|
||||||
IcachePort(TimingSimpleCPU *_cpu)
|
IcachePort(TimingSimpleCPU *_cpu)
|
||||||
: CpuPort(_cpu)
|
: CpuPort(_cpu->name() + "-iport", _cpu)
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
@ -108,7 +108,7 @@ class TimingSimpleCPU : public BaseSimpleCPU
|
||||||
public:
|
public:
|
||||||
|
|
||||||
DcachePort(TimingSimpleCPU *_cpu)
|
DcachePort(TimingSimpleCPU *_cpu)
|
||||||
: CpuPort(_cpu)
|
: CpuPort(_cpu->name() + "-dport", _cpu)
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
@ -142,9 +142,9 @@ class TimingSimpleCPU : public BaseSimpleCPU
|
||||||
Fault write(T data, Addr addr, unsigned flags, uint64_t *res);
|
Fault write(T data, Addr addr, unsigned flags, uint64_t *res);
|
||||||
|
|
||||||
void fetch();
|
void fetch();
|
||||||
void completeInst(Fault fault);
|
void completeIfetch(Packet *);
|
||||||
void completeIfetch();
|
|
||||||
void completeDataAccess(Packet *);
|
void completeDataAccess(Packet *);
|
||||||
|
void advanceInst(Fault fault);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // __CPU_SIMPLE_TIMING_HH__
|
#endif // __CPU_SIMPLE_TIMING_HH__
|
||||||
|
|
|
@ -95,15 +95,15 @@ AlphaConsole::read(Packet *pkt)
|
||||||
* machine dependent address swizzle is required?
|
* machine dependent address swizzle is required?
|
||||||
*/
|
*/
|
||||||
|
|
||||||
assert(pkt->result == Unknown);
|
assert(pkt->result == Packet::Unknown);
|
||||||
assert(pkt->addr >= pioAddr && pkt->addr < pioAddr + pioSize);
|
assert(pkt->getAddr() >= pioAddr && pkt->getAddr() < pioAddr + pioSize);
|
||||||
|
|
||||||
pkt->time += pioDelay;
|
pkt->time += pioDelay;
|
||||||
Addr daddr = pkt->addr - pioAddr;
|
Addr daddr = pkt->getAddr() - pioAddr;
|
||||||
|
|
||||||
pkt->allocate();
|
pkt->allocate();
|
||||||
|
|
||||||
switch (pkt->size)
|
switch (pkt->getSize())
|
||||||
{
|
{
|
||||||
case sizeof(uint32_t):
|
case sizeof(uint32_t):
|
||||||
switch (daddr)
|
switch (daddr)
|
||||||
|
@ -124,7 +124,7 @@ AlphaConsole::read(Packet *pkt)
|
||||||
/* Old console code read in everyting as a 32bit int
|
/* Old console code read in everyting as a 32bit int
|
||||||
* we now break that for better error checking.
|
* we now break that for better error checking.
|
||||||
*/
|
*/
|
||||||
pkt->result = BadAddress;
|
pkt->result = Packet::BadAddress;
|
||||||
}
|
}
|
||||||
DPRINTF(AlphaConsole, "read: offset=%#x val=%#x\n", daddr,
|
DPRINTF(AlphaConsole, "read: offset=%#x val=%#x\n", daddr,
|
||||||
pkt->get<uint32_t>());
|
pkt->get<uint32_t>());
|
||||||
|
@ -181,9 +181,10 @@ AlphaConsole::read(Packet *pkt)
|
||||||
pkt->get<uint64_t>());
|
pkt->get<uint64_t>());
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
pkt->result = BadAddress;
|
pkt->result = Packet::BadAddress;
|
||||||
}
|
}
|
||||||
if (pkt->result == Unknown) pkt->result = Success;
|
if (pkt->result == Packet::Unknown)
|
||||||
|
pkt->result = Packet::Success;
|
||||||
return pioDelay;
|
return pioDelay;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -192,12 +193,12 @@ AlphaConsole::write(Packet *pkt)
|
||||||
{
|
{
|
||||||
pkt->time += pioDelay;
|
pkt->time += pioDelay;
|
||||||
|
|
||||||
assert(pkt->result == Unknown);
|
assert(pkt->result == Packet::Unknown);
|
||||||
assert(pkt->addr >= pioAddr && pkt->addr < pioAddr + pioSize);
|
assert(pkt->getAddr() >= pioAddr && pkt->getAddr() < pioAddr + pioSize);
|
||||||
Addr daddr = pkt->addr - pioAddr;
|
Addr daddr = pkt->getAddr() - pioAddr;
|
||||||
|
|
||||||
uint64_t val = pkt->get<uint64_t>();
|
uint64_t val = pkt->get<uint64_t>();
|
||||||
assert(pkt->size == sizeof(uint64_t));
|
assert(pkt->getSize() == sizeof(uint64_t));
|
||||||
|
|
||||||
switch (daddr) {
|
switch (daddr) {
|
||||||
case offsetof(AlphaAccess, diskUnit):
|
case offsetof(AlphaAccess, diskUnit):
|
||||||
|
@ -240,7 +241,7 @@ AlphaConsole::write(Packet *pkt)
|
||||||
panic("Unknown 64bit access, %#x\n", daddr);
|
panic("Unknown 64bit access, %#x\n", daddr);
|
||||||
}
|
}
|
||||||
|
|
||||||
pkt->result = Success;
|
pkt->result = Packet::Success;
|
||||||
|
|
||||||
return pioDelay;
|
return pioDelay;
|
||||||
}
|
}
|
||||||
|
|
|
@ -432,19 +432,19 @@ IdeController::read(Packet *pkt)
|
||||||
|
|
||||||
pkt->time += pioDelay;
|
pkt->time += pioDelay;
|
||||||
pkt->allocate();
|
pkt->allocate();
|
||||||
if (pkt->size != 1 && pkt->size != 2 && pkt->size !=4)
|
if (pkt->getSize() != 1 && pkt->getSize() != 2 && pkt->getSize() !=4)
|
||||||
panic("Bad IDE read size: %d\n", pkt->size);
|
panic("Bad IDE read size: %d\n", pkt->getSize());
|
||||||
|
|
||||||
parseAddr(pkt->addr, offset, channel, reg_type);
|
parseAddr(pkt->getAddr(), offset, channel, reg_type);
|
||||||
|
|
||||||
if (!io_enabled) {
|
if (!io_enabled) {
|
||||||
pkt->result = Success;
|
pkt->result = Packet::Success;
|
||||||
return pioDelay;
|
return pioDelay;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (reg_type) {
|
switch (reg_type) {
|
||||||
case BMI_BLOCK:
|
case BMI_BLOCK:
|
||||||
switch (pkt->size) {
|
switch (pkt->getSize()) {
|
||||||
case sizeof(uint8_t):
|
case sizeof(uint8_t):
|
||||||
pkt->set(bmi_regs.data[offset]);
|
pkt->set(bmi_regs.data[offset]);
|
||||||
break;
|
break;
|
||||||
|
@ -455,7 +455,7 @@ IdeController::read(Packet *pkt)
|
||||||
pkt->set(*(uint32_t*)&bmi_regs.data[offset]);
|
pkt->set(*(uint32_t*)&bmi_regs.data[offset]);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
panic("IDE read of BMI reg invalid size: %#x\n", pkt->size);
|
panic("IDE read of BMI reg invalid size: %#x\n", pkt->getSize());
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -470,7 +470,7 @@ IdeController::read(Packet *pkt)
|
||||||
|
|
||||||
switch (offset) {
|
switch (offset) {
|
||||||
case DATA_OFFSET:
|
case DATA_OFFSET:
|
||||||
switch (pkt->size) {
|
switch (pkt->getSize()) {
|
||||||
case sizeof(uint16_t):
|
case sizeof(uint16_t):
|
||||||
disks[disk]->read(offset, reg_type, pkt->getPtr<uint8_t>());
|
disks[disk]->read(offset, reg_type, pkt->getPtr<uint8_t>());
|
||||||
break;
|
break;
|
||||||
|
@ -482,30 +482,30 @@ IdeController::read(Packet *pkt)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
panic("IDE read of data reg invalid size: %#x\n", pkt->size);
|
panic("IDE read of data reg invalid size: %#x\n", pkt->getSize());
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
if (pkt->size == sizeof(uint8_t)) {
|
if (pkt->getSize() == sizeof(uint8_t)) {
|
||||||
disks[disk]->read(offset, reg_type, pkt->getPtr<uint8_t>());
|
disks[disk]->read(offset, reg_type, pkt->getPtr<uint8_t>());
|
||||||
} else
|
} else
|
||||||
panic("IDE read of command reg of invalid size: %#x\n", pkt->size);
|
panic("IDE read of command reg of invalid size: %#x\n", pkt->getSize());
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
panic("IDE controller read of unknown register block type!\n");
|
panic("IDE controller read of unknown register block type!\n");
|
||||||
}
|
}
|
||||||
if (pkt->size == 1)
|
if (pkt->getSize() == 1)
|
||||||
DPRINTF(IdeCtrl, "read from offset: %#x size: %#x data: %#x\n",
|
DPRINTF(IdeCtrl, "read from offset: %#x size: %#x data: %#x\n",
|
||||||
offset, pkt->size, (uint32_t)pkt->get<uint8_t>());
|
offset, pkt->getSize(), (uint32_t)pkt->get<uint8_t>());
|
||||||
else if (pkt->size == 2)
|
else if (pkt->getSize() == 2)
|
||||||
DPRINTF(IdeCtrl, "read from offset: %#x size: %#x data: %#x\n",
|
DPRINTF(IdeCtrl, "read from offset: %#x size: %#x data: %#x\n",
|
||||||
offset, pkt->size, pkt->get<uint16_t>());
|
offset, pkt->getSize(), pkt->get<uint16_t>());
|
||||||
else
|
else
|
||||||
DPRINTF(IdeCtrl, "read from offset: %#x size: %#x data: %#x\n",
|
DPRINTF(IdeCtrl, "read from offset: %#x size: %#x data: %#x\n",
|
||||||
offset, pkt->size, pkt->get<uint32_t>());
|
offset, pkt->getSize(), pkt->get<uint32_t>());
|
||||||
|
|
||||||
pkt->result = Success;
|
pkt->result = Packet::Success;
|
||||||
return pioDelay;
|
return pioDelay;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -520,10 +520,10 @@ IdeController::write(Packet *pkt)
|
||||||
|
|
||||||
pkt->time += pioDelay;
|
pkt->time += pioDelay;
|
||||||
|
|
||||||
parseAddr(pkt->addr, offset, channel, reg_type);
|
parseAddr(pkt->getAddr(), offset, channel, reg_type);
|
||||||
|
|
||||||
if (!io_enabled) {
|
if (!io_enabled) {
|
||||||
pkt->result = Success;
|
pkt->result = Packet::Success;
|
||||||
DPRINTF(IdeCtrl, "io not enabled\n");
|
DPRINTF(IdeCtrl, "io not enabled\n");
|
||||||
return pioDelay;
|
return pioDelay;
|
||||||
}
|
}
|
||||||
|
@ -531,7 +531,7 @@ IdeController::write(Packet *pkt)
|
||||||
switch (reg_type) {
|
switch (reg_type) {
|
||||||
case BMI_BLOCK:
|
case BMI_BLOCK:
|
||||||
if (!bm_enabled) {
|
if (!bm_enabled) {
|
||||||
pkt->result = Success;
|
pkt->result = Packet::Success;
|
||||||
return pioDelay;
|
return pioDelay;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -539,8 +539,8 @@ IdeController::write(Packet *pkt)
|
||||||
// Bus master IDE command register
|
// Bus master IDE command register
|
||||||
case BMIC1:
|
case BMIC1:
|
||||||
case BMIC0:
|
case BMIC0:
|
||||||
if (pkt->size != sizeof(uint8_t))
|
if (pkt->getSize() != sizeof(uint8_t))
|
||||||
panic("Invalid BMIC write size: %x\n", pkt->size);
|
panic("Invalid BMIC write size: %x\n", pkt->getSize());
|
||||||
|
|
||||||
// select the current disk based on DEV bit
|
// select the current disk based on DEV bit
|
||||||
disk = getDisk(channel);
|
disk = getDisk(channel);
|
||||||
|
@ -595,8 +595,8 @@ IdeController::write(Packet *pkt)
|
||||||
// Bus master IDE status register
|
// Bus master IDE status register
|
||||||
case BMIS0:
|
case BMIS0:
|
||||||
case BMIS1:
|
case BMIS1:
|
||||||
if (pkt->size != sizeof(uint8_t))
|
if (pkt->getSize() != sizeof(uint8_t))
|
||||||
panic("Invalid BMIS write size: %x\n", pkt->size);
|
panic("Invalid BMIS write size: %x\n", pkt->getSize());
|
||||||
|
|
||||||
oldVal = bmi_regs.chan[channel].bmis;
|
oldVal = bmi_regs.chan[channel].bmis;
|
||||||
newVal = pkt->get<uint8_t>();
|
newVal = pkt->get<uint8_t>();
|
||||||
|
@ -622,22 +622,22 @@ IdeController::write(Packet *pkt)
|
||||||
case BMIDTP0:
|
case BMIDTP0:
|
||||||
case BMIDTP1:
|
case BMIDTP1:
|
||||||
{
|
{
|
||||||
if (pkt->size != sizeof(uint32_t))
|
if (pkt->getSize() != sizeof(uint32_t))
|
||||||
panic("Invalid BMIDTP write size: %x\n", pkt->size);
|
panic("Invalid BMIDTP write size: %x\n", pkt->getSize());
|
||||||
|
|
||||||
bmi_regs.chan[channel].bmidtp = htole(pkt->get<uint32_t>() & ~0x3);
|
bmi_regs.chan[channel].bmidtp = htole(pkt->get<uint32_t>() & ~0x3);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
if (pkt->size != sizeof(uint8_t) &&
|
if (pkt->getSize() != sizeof(uint8_t) &&
|
||||||
pkt->size != sizeof(uint16_t) &&
|
pkt->getSize() != sizeof(uint16_t) &&
|
||||||
pkt->size != sizeof(uint32_t))
|
pkt->getSize() != sizeof(uint32_t))
|
||||||
panic("IDE controller write of invalid write size: %x\n",
|
panic("IDE controller write of invalid write size: %x\n",
|
||||||
pkt->size);
|
pkt->getSize());
|
||||||
|
|
||||||
// do a default copy of data into the registers
|
// do a default copy of data into the registers
|
||||||
memcpy(&bmi_regs.data[offset], pkt->getPtr<uint8_t>(), pkt->size);
|
memcpy(&bmi_regs.data[offset], pkt->getPtr<uint8_t>(), pkt->getSize());
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case COMMAND_BLOCK:
|
case COMMAND_BLOCK:
|
||||||
|
@ -654,7 +654,7 @@ IdeController::write(Packet *pkt)
|
||||||
|
|
||||||
switch (offset) {
|
switch (offset) {
|
||||||
case DATA_OFFSET:
|
case DATA_OFFSET:
|
||||||
switch (pkt->size) {
|
switch (pkt->getSize()) {
|
||||||
case sizeof(uint16_t):
|
case sizeof(uint16_t):
|
||||||
disks[disk]->write(offset, reg_type, pkt->getPtr<uint8_t>());
|
disks[disk]->write(offset, reg_type, pkt->getPtr<uint8_t>());
|
||||||
break;
|
break;
|
||||||
|
@ -665,32 +665,32 @@ IdeController::write(Packet *pkt)
|
||||||
sizeof(uint16_t));
|
sizeof(uint16_t));
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
panic("IDE write of data reg invalid size: %#x\n", pkt->size);
|
panic("IDE write of data reg invalid size: %#x\n", pkt->getSize());
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
if (pkt->size == sizeof(uint8_t)) {
|
if (pkt->getSize() == sizeof(uint8_t)) {
|
||||||
disks[disk]->write(offset, reg_type, pkt->getPtr<uint8_t>());
|
disks[disk]->write(offset, reg_type, pkt->getPtr<uint8_t>());
|
||||||
} else
|
} else
|
||||||
panic("IDE write of command reg of invalid size: %#x\n", pkt->size);
|
panic("IDE write of command reg of invalid size: %#x\n", pkt->getSize());
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
panic("IDE controller write of unknown register block type!\n");
|
panic("IDE controller write of unknown register block type!\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pkt->size == 1)
|
if (pkt->getSize() == 1)
|
||||||
DPRINTF(IdeCtrl, "write to offset: %#x size: %#x data: %#x\n",
|
DPRINTF(IdeCtrl, "write to offset: %#x size: %#x data: %#x\n",
|
||||||
offset, pkt->size, (uint32_t)pkt->get<uint8_t>());
|
offset, pkt->getSize(), (uint32_t)pkt->get<uint8_t>());
|
||||||
else if (pkt->size == 2)
|
else if (pkt->getSize() == 2)
|
||||||
DPRINTF(IdeCtrl, "write to offset: %#x size: %#x data: %#x\n",
|
DPRINTF(IdeCtrl, "write to offset: %#x size: %#x data: %#x\n",
|
||||||
offset, pkt->size, pkt->get<uint16_t>());
|
offset, pkt->getSize(), pkt->get<uint16_t>());
|
||||||
else
|
else
|
||||||
DPRINTF(IdeCtrl, "write to offset: %#x size: %#x data: %#x\n",
|
DPRINTF(IdeCtrl, "write to offset: %#x size: %#x data: %#x\n",
|
||||||
offset, pkt->size, pkt->get<uint32_t>());
|
offset, pkt->getSize(), pkt->get<uint32_t>());
|
||||||
|
|
||||||
|
|
||||||
pkt->result = Success;
|
pkt->result = Packet::Success;
|
||||||
return pioDelay;
|
return pioDelay;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -31,7 +31,7 @@
|
||||||
|
|
||||||
|
|
||||||
PioPort::PioPort(PioDevice *dev, Platform *p)
|
PioPort::PioPort(PioDevice *dev, Platform *p)
|
||||||
: device(dev), platform(p)
|
: Port(dev->name() + "-pioport"), device(dev), platform(p)
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
|
|
||||||
|
@ -67,7 +67,7 @@ PioPort::recvRetry()
|
||||||
void
|
void
|
||||||
PioPort::SendEvent::process()
|
PioPort::SendEvent::process()
|
||||||
{
|
{
|
||||||
if (port->Port::sendTiming(packet) == Success)
|
if (port->Port::sendTiming(packet))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
port->transmitList.push_back(packet);
|
port->transmitList.push_back(packet);
|
||||||
|
@ -78,8 +78,10 @@ bool
|
||||||
PioPort::recvTiming(Packet *pkt)
|
PioPort::recvTiming(Packet *pkt)
|
||||||
{
|
{
|
||||||
device->recvAtomic(pkt);
|
device->recvAtomic(pkt);
|
||||||
|
// turn packet around to go back to requester
|
||||||
|
pkt->makeTimingResponse();
|
||||||
sendTiming(pkt, pkt->time - pkt->req->getTime());
|
sendTiming(pkt, pkt->time - pkt->req->getTime());
|
||||||
return Success;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
PioDevice::~PioDevice()
|
PioDevice::~PioDevice()
|
||||||
|
@ -106,7 +108,7 @@ BasicPioDevice::addressRanges(AddrRangeList &range_list)
|
||||||
|
|
||||||
|
|
||||||
DmaPort::DmaPort(DmaDevice *dev, Platform *p)
|
DmaPort::DmaPort(DmaDevice *dev, Platform *p)
|
||||||
: device(dev), platform(p), pendingCount(0)
|
: Port(dev->name() + "-dmaport"), device(dev), platform(p), pendingCount(0)
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
bool
|
bool
|
||||||
|
@ -114,7 +116,7 @@ DmaPort::recvTiming(Packet *pkt)
|
||||||
{
|
{
|
||||||
if (pkt->senderState) {
|
if (pkt->senderState) {
|
||||||
DmaReqState *state;
|
DmaReqState *state;
|
||||||
state = (DmaReqState*)pkt->senderState;
|
state = dynamic_cast<DmaReqState*>(pkt->senderState);
|
||||||
state->completionEvent->schedule(pkt->time - pkt->req->getTime());
|
state->completionEvent->schedule(pkt->time - pkt->req->getTime());
|
||||||
delete pkt->req;
|
delete pkt->req;
|
||||||
delete pkt;
|
delete pkt;
|
||||||
|
@ -123,7 +125,7 @@ DmaPort::recvTiming(Packet *pkt)
|
||||||
delete pkt;
|
delete pkt;
|
||||||
}
|
}
|
||||||
|
|
||||||
return Success;
|
return Packet::Success;
|
||||||
}
|
}
|
||||||
|
|
||||||
DmaDevice::DmaDevice(Params *p)
|
DmaDevice::DmaDevice(Params *p)
|
||||||
|
@ -133,7 +135,7 @@ DmaDevice::DmaDevice(Params *p)
|
||||||
void
|
void
|
||||||
DmaPort::SendEvent::process()
|
DmaPort::SendEvent::process()
|
||||||
{
|
{
|
||||||
if (port->Port::sendTiming(packet) == Success)
|
if (port->Port::sendTiming(packet))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
port->transmitList.push_back(packet);
|
port->transmitList.push_back(packet);
|
||||||
|
@ -146,54 +148,39 @@ DmaPort::recvRetry()
|
||||||
transmitList.pop_front();
|
transmitList.pop_front();
|
||||||
return pkt;
|
return pkt;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
DmaPort::dmaAction(Command cmd, Addr addr, int size, Event *event,
|
DmaPort::dmaAction(Packet::Command cmd, Addr addr, int size, Event *event,
|
||||||
uint8_t *data)
|
uint8_t *data)
|
||||||
{
|
{
|
||||||
|
|
||||||
assert(event);
|
assert(event);
|
||||||
|
|
||||||
int prevSize = 0;
|
int prevSize = 0;
|
||||||
Packet basePkt;
|
|
||||||
Request baseReq(false);
|
|
||||||
|
|
||||||
basePkt.flags = 0;
|
|
||||||
basePkt.coherence = NULL;
|
|
||||||
basePkt.senderState = NULL;
|
|
||||||
basePkt.dest = Packet::Broadcast;
|
|
||||||
basePkt.cmd = cmd;
|
|
||||||
basePkt.result = Unknown;
|
|
||||||
basePkt.req = NULL;
|
|
||||||
// baseReq.nicReq = true;
|
|
||||||
baseReq.setTime(curTick);
|
|
||||||
|
|
||||||
for (ChunkGenerator gen(addr, size, peerBlockSize());
|
for (ChunkGenerator gen(addr, size, peerBlockSize());
|
||||||
!gen.done(); gen.next()) {
|
!gen.done(); gen.next()) {
|
||||||
Packet *pkt = new Packet(basePkt);
|
Request *req = new Request(false);
|
||||||
Request *req = new Request(baseReq);
|
req->setPaddr(gen.addr());
|
||||||
pkt->addr = gen.addr();
|
req->setSize(gen.size());
|
||||||
pkt->size = gen.size();
|
req->setTime(curTick);
|
||||||
pkt->req = req;
|
Packet *pkt = new Packet(req, cmd, Packet::Broadcast);
|
||||||
pkt->req->setPaddr(pkt->addr);
|
|
||||||
pkt->req->setSize(pkt->size);
|
|
||||||
// Increment the data pointer on a write
|
// Increment the data pointer on a write
|
||||||
if (data)
|
if (data)
|
||||||
pkt->dataStatic(data + prevSize) ;
|
pkt->dataStatic(data + prevSize) ;
|
||||||
prevSize += pkt->size;
|
|
||||||
|
prevSize += gen.size();
|
||||||
|
|
||||||
// Set the last bit of the dma as the final packet for this dma
|
// Set the last bit of the dma as the final packet for this dma
|
||||||
// and set it's completion event.
|
// and set it's completion event.
|
||||||
if (prevSize == size) {
|
if (prevSize == size) {
|
||||||
DmaReqState *state = new DmaReqState(event, true);
|
pkt->senderState = new DmaReqState(event, true);
|
||||||
|
|
||||||
pkt->senderState = (void*)state;
|
|
||||||
}
|
}
|
||||||
assert(pendingCount >= 0);
|
assert(pendingCount >= 0);
|
||||||
pendingCount++;
|
pendingCount++;
|
||||||
sendDma(pkt);
|
sendDma(pkt);
|
||||||
}
|
}
|
||||||
// since this isn't getting used and we want a check to make sure that all
|
|
||||||
// packets had data in them at some point.
|
|
||||||
basePkt.dataStatic((uint8_t*)NULL);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -206,12 +193,12 @@ DmaPort::sendDma(Packet *pkt)
|
||||||
/* MemState state = device->platform->system->memState;
|
/* MemState state = device->platform->system->memState;
|
||||||
|
|
||||||
if (state == Timing) {
|
if (state == Timing) {
|
||||||
if (sendTiming(pkt) == Failure)
|
if (!sendTiming(pkt))
|
||||||
transmitList.push_back(&packet);
|
transmitList.push_back(&packet);
|
||||||
} else if (state == Atomic) {*/
|
} else if (state == Atomic) {*/
|
||||||
sendAtomic(pkt);
|
sendAtomic(pkt);
|
||||||
if (pkt->senderState) {
|
if (pkt->senderState) {
|
||||||
DmaReqState *state = (DmaReqState*)pkt->senderState;
|
DmaReqState *state = dynamic_cast<DmaReqState*>(pkt->senderState);
|
||||||
state->completionEvent->schedule(curTick + (pkt->time - pkt->req->getTime()) +1);
|
state->completionEvent->schedule(curTick + (pkt->time - pkt->req->getTime()) +1);
|
||||||
}
|
}
|
||||||
pendingCount--;
|
pendingCount--;
|
||||||
|
|
|
@ -115,7 +115,7 @@ class PioPort : public Port
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
struct DmaReqState
|
struct DmaReqState : public Packet::SenderState
|
||||||
{
|
{
|
||||||
Event *completionEvent;
|
Event *completionEvent;
|
||||||
bool final;
|
bool final;
|
||||||
|
@ -173,7 +173,7 @@ class DmaPort : public Port
|
||||||
public:
|
public:
|
||||||
DmaPort(DmaDevice *dev, Platform *p);
|
DmaPort(DmaDevice *dev, Platform *p);
|
||||||
|
|
||||||
void dmaAction(Command cmd, Addr addr, int size, Event *event,
|
void dmaAction(Packet::Command cmd, Addr addr, int size, Event *event,
|
||||||
uint8_t *data = NULL);
|
uint8_t *data = NULL);
|
||||||
|
|
||||||
bool dmaPending() { return pendingCount > 0; }
|
bool dmaPending() { return pendingCount > 0; }
|
||||||
|
@ -207,7 +207,7 @@ class PioDevice : public MemObject
|
||||||
/** As far as the devices are concerned they only accept atomic transactions
|
/** As far as the devices are concerned they only accept atomic transactions
|
||||||
* which are converted to either a write or a read. */
|
* which are converted to either a write or a read. */
|
||||||
Tick recvAtomic(Packet *pkt)
|
Tick recvAtomic(Packet *pkt)
|
||||||
{ return pkt->cmd == Read ? this->read(pkt) : this->write(pkt); }
|
{ return pkt->isRead() ? this->read(pkt) : this->write(pkt); }
|
||||||
|
|
||||||
/** Pure virtual function that the device must implement. Called when a read
|
/** Pure virtual function that the device must implement. Called when a read
|
||||||
* command is recieved by the port.
|
* command is recieved by the port.
|
||||||
|
@ -305,10 +305,10 @@ class DmaDevice : public PioDevice
|
||||||
virtual ~DmaDevice();
|
virtual ~DmaDevice();
|
||||||
|
|
||||||
void dmaWrite(Addr addr, int size, Event *event, uint8_t *data)
|
void dmaWrite(Addr addr, int size, Event *event, uint8_t *data)
|
||||||
{ dmaPort->dmaAction(Write, addr, size, event, data) ; }
|
{ dmaPort->dmaAction(Packet::WriteReq, addr, size, event, data) ; }
|
||||||
|
|
||||||
void dmaRead(Addr addr, int size, Event *event, uint8_t *data = NULL)
|
void dmaRead(Addr addr, int size, Event *event, uint8_t *data = NULL)
|
||||||
{ dmaPort->dmaAction(Read, addr, size, event, data); }
|
{ dmaPort->dmaAction(Packet::ReadReq, addr, size, event, data); }
|
||||||
|
|
||||||
bool dmaPending() { return dmaPort->dmaPending(); }
|
bool dmaPending() { return dmaPort->dmaPending(); }
|
||||||
|
|
||||||
|
|
|
@ -51,14 +51,14 @@ IsaFake::IsaFake(Params *p)
|
||||||
Tick
|
Tick
|
||||||
IsaFake::read(Packet *pkt)
|
IsaFake::read(Packet *pkt)
|
||||||
{
|
{
|
||||||
assert(pkt->result == Unknown);
|
assert(pkt->result == Packet::Unknown);
|
||||||
assert(pkt->addr >= pioAddr && pkt->addr < pioAddr + pioSize);
|
assert(pkt->getAddr() >= pioAddr && pkt->getAddr() < pioAddr + pioSize);
|
||||||
|
|
||||||
pkt->time += pioDelay;
|
pkt->time += pioDelay;
|
||||||
|
|
||||||
DPRINTF(Tsunami, "read va=%#x size=%d\n", pkt->addr, pkt->size);
|
DPRINTF(Tsunami, "read va=%#x size=%d\n", pkt->getAddr(), pkt->getSize());
|
||||||
|
|
||||||
switch (pkt->size) {
|
switch (pkt->getSize()) {
|
||||||
pkt->set(0xFFFFFFFFFFFFFFFFULL);
|
pkt->set(0xFFFFFFFFFFFFFFFFULL);
|
||||||
break;
|
break;
|
||||||
case sizeof(uint32_t):
|
case sizeof(uint32_t):
|
||||||
|
@ -73,7 +73,7 @@ IsaFake::read(Packet *pkt)
|
||||||
default:
|
default:
|
||||||
panic("invalid access size(?) for PCI configspace!\n");
|
panic("invalid access size(?) for PCI configspace!\n");
|
||||||
}
|
}
|
||||||
pkt->result = Success;
|
pkt->result = Packet::Success;
|
||||||
return pioDelay;
|
return pioDelay;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -81,8 +81,8 @@ Tick
|
||||||
IsaFake::write(Packet *pkt)
|
IsaFake::write(Packet *pkt)
|
||||||
{
|
{
|
||||||
pkt->time += pioDelay;
|
pkt->time += pioDelay;
|
||||||
DPRINTF(Tsunami, "write - va=%#x size=%d \n", pkt->addr, pkt->size);
|
DPRINTF(Tsunami, "write - va=%#x size=%d \n", pkt->getAddr(), pkt->getSize());
|
||||||
pkt->result = Success;
|
pkt->result = Packet::Success;
|
||||||
return pioDelay;
|
return pioDelay;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -496,9 +496,9 @@ NSGigE::read(Packet *pkt)
|
||||||
pkt->allocate();
|
pkt->allocate();
|
||||||
|
|
||||||
//The mask is to give you only the offset into the device register file
|
//The mask is to give you only the offset into the device register file
|
||||||
Addr daddr = pkt->addr & 0xfff;
|
Addr daddr = pkt->getAddr() & 0xfff;
|
||||||
DPRINTF(EthernetPIO, "read da=%#x pa=%#x size=%d\n",
|
DPRINTF(EthernetPIO, "read da=%#x pa=%#x size=%d\n",
|
||||||
daddr, pkt->addr, pkt->size);
|
daddr, pkt->getAddr(), pkt->getSize());
|
||||||
|
|
||||||
|
|
||||||
// there are some reserved registers, you can see ns_gige_reg.h and
|
// there are some reserved registers, you can see ns_gige_reg.h and
|
||||||
|
@ -506,25 +506,25 @@ NSGigE::read(Packet *pkt)
|
||||||
if (daddr > LAST && daddr <= RESERVED) {
|
if (daddr > LAST && daddr <= RESERVED) {
|
||||||
panic("Accessing reserved register");
|
panic("Accessing reserved register");
|
||||||
} else if (daddr > RESERVED && daddr <= 0x3FC) {
|
} else if (daddr > RESERVED && daddr <= 0x3FC) {
|
||||||
if (pkt->size == sizeof(uint8_t))
|
if (pkt->getSize() == sizeof(uint8_t))
|
||||||
readConfig(daddr & 0xff, pkt->getPtr<uint8_t>());
|
readConfig(daddr & 0xff, pkt->getPtr<uint8_t>());
|
||||||
if (pkt->size == sizeof(uint16_t))
|
if (pkt->getSize() == sizeof(uint16_t))
|
||||||
readConfig(daddr & 0xff, pkt->getPtr<uint16_t>());
|
readConfig(daddr & 0xff, pkt->getPtr<uint16_t>());
|
||||||
if (pkt->size == sizeof(uint32_t))
|
if (pkt->getSize() == sizeof(uint32_t))
|
||||||
readConfig(daddr & 0xff, pkt->getPtr<uint32_t>());
|
readConfig(daddr & 0xff, pkt->getPtr<uint32_t>());
|
||||||
pkt->result = Success;
|
pkt->result = Packet::Success;
|
||||||
return pioDelay;
|
return pioDelay;
|
||||||
} else if (daddr >= MIB_START && daddr <= MIB_END) {
|
} else if (daddr >= MIB_START && daddr <= MIB_END) {
|
||||||
// don't implement all the MIB's. hopefully the kernel
|
// don't implement all the MIB's. hopefully the kernel
|
||||||
// doesn't actually DEPEND upon their values
|
// doesn't actually DEPEND upon their values
|
||||||
// MIB are just hardware stats keepers
|
// MIB are just hardware stats keepers
|
||||||
pkt->set<uint32_t>(0);
|
pkt->set<uint32_t>(0);
|
||||||
pkt->result = Success;
|
pkt->result = Packet::Success;
|
||||||
return pioDelay;
|
return pioDelay;
|
||||||
} else if (daddr > 0x3FC)
|
} else if (daddr > 0x3FC)
|
||||||
panic("Something is messed up!\n");
|
panic("Something is messed up!\n");
|
||||||
|
|
||||||
assert(pkt->size == sizeof(uint32_t));
|
assert(pkt->getSize() == sizeof(uint32_t));
|
||||||
uint32_t ® = *pkt->getPtr<uint32_t>();
|
uint32_t ® = *pkt->getPtr<uint32_t>();
|
||||||
uint16_t rfaddr;
|
uint16_t rfaddr;
|
||||||
|
|
||||||
|
@ -715,7 +715,7 @@ NSGigE::read(Packet *pkt)
|
||||||
DPRINTF(EthernetPIO, "read from %#x: data=%d data=%#x\n",
|
DPRINTF(EthernetPIO, "read from %#x: data=%d data=%#x\n",
|
||||||
daddr, reg, reg);
|
daddr, reg, reg);
|
||||||
|
|
||||||
pkt->result = Success;
|
pkt->result = Packet::Success;
|
||||||
return pioDelay;
|
return pioDelay;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -724,27 +724,27 @@ NSGigE::write(Packet *pkt)
|
||||||
{
|
{
|
||||||
assert(ioEnable);
|
assert(ioEnable);
|
||||||
|
|
||||||
Addr daddr = pkt->addr & 0xfff;
|
Addr daddr = pkt->getAddr() & 0xfff;
|
||||||
DPRINTF(EthernetPIO, "write da=%#x pa=%#x size=%d\n",
|
DPRINTF(EthernetPIO, "write da=%#x pa=%#x size=%d\n",
|
||||||
daddr, pkt->addr, pkt->size);
|
daddr, pkt->getAddr(), pkt->getSize());
|
||||||
|
|
||||||
pkt->time += pioDelay;
|
pkt->time += pioDelay;
|
||||||
|
|
||||||
if (daddr > LAST && daddr <= RESERVED) {
|
if (daddr > LAST && daddr <= RESERVED) {
|
||||||
panic("Accessing reserved register");
|
panic("Accessing reserved register");
|
||||||
} else if (daddr > RESERVED && daddr <= 0x3FC) {
|
} else if (daddr > RESERVED && daddr <= 0x3FC) {
|
||||||
if (pkt->size == sizeof(uint8_t))
|
if (pkt->getSize() == sizeof(uint8_t))
|
||||||
writeConfig(daddr & 0xff, pkt->get<uint8_t>());
|
writeConfig(daddr & 0xff, pkt->get<uint8_t>());
|
||||||
if (pkt->size == sizeof(uint16_t))
|
if (pkt->getSize() == sizeof(uint16_t))
|
||||||
writeConfig(daddr & 0xff, pkt->get<uint16_t>());
|
writeConfig(daddr & 0xff, pkt->get<uint16_t>());
|
||||||
if (pkt->size == sizeof(uint32_t))
|
if (pkt->getSize() == sizeof(uint32_t))
|
||||||
writeConfig(daddr & 0xff, pkt->get<uint32_t>());
|
writeConfig(daddr & 0xff, pkt->get<uint32_t>());
|
||||||
pkt->result = Success;
|
pkt->result = Packet::Success;
|
||||||
return pioDelay;
|
return pioDelay;
|
||||||
} else if (daddr > 0x3FC)
|
} else if (daddr > 0x3FC)
|
||||||
panic("Something is messed up!\n");
|
panic("Something is messed up!\n");
|
||||||
|
|
||||||
if (pkt->size == sizeof(uint32_t)) {
|
if (pkt->getSize() == sizeof(uint32_t)) {
|
||||||
uint32_t reg = pkt->get<uint32_t>();
|
uint32_t reg = pkt->get<uint32_t>();
|
||||||
uint16_t rfaddr;
|
uint16_t rfaddr;
|
||||||
|
|
||||||
|
@ -1131,7 +1131,7 @@ NSGigE::write(Packet *pkt)
|
||||||
} else {
|
} else {
|
||||||
panic("Invalid Request Size");
|
panic("Invalid Request Size");
|
||||||
}
|
}
|
||||||
pkt->result = Success;
|
pkt->result = Packet::Success;
|
||||||
return pioDelay;
|
return pioDelay;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -91,10 +91,10 @@ PciConfigAll::startup()
|
||||||
Tick
|
Tick
|
||||||
PciConfigAll::read(Packet *pkt)
|
PciConfigAll::read(Packet *pkt)
|
||||||
{
|
{
|
||||||
assert(pkt->result == Unknown);
|
assert(pkt->result == Packet::Unknown);
|
||||||
assert(pkt->addr >= pioAddr && pkt->addr < pioAddr + pioSize);
|
assert(pkt->getAddr() >= pioAddr && pkt->getAddr() < pioAddr + pioSize);
|
||||||
|
|
||||||
Addr daddr = pkt->addr - pioAddr;
|
Addr daddr = pkt->getAddr() - pioAddr;
|
||||||
int device = (daddr >> 11) & 0x1F;
|
int device = (daddr >> 11) & 0x1F;
|
||||||
int func = (daddr >> 8) & 0x7;
|
int func = (daddr >> 8) & 0x7;
|
||||||
int reg = daddr & 0xFF;
|
int reg = daddr & 0xFF;
|
||||||
|
@ -102,10 +102,10 @@ PciConfigAll::read(Packet *pkt)
|
||||||
pkt->time += pioDelay;
|
pkt->time += pioDelay;
|
||||||
pkt->allocate();
|
pkt->allocate();
|
||||||
|
|
||||||
DPRINTF(PciConfigAll, "read va=%#x da=%#x size=%d\n", pkt->addr, daddr,
|
DPRINTF(PciConfigAll, "read va=%#x da=%#x size=%d\n", pkt->getAddr(), daddr,
|
||||||
pkt->size);
|
pkt->getSize());
|
||||||
|
|
||||||
switch (pkt->size) {
|
switch (pkt->getSize()) {
|
||||||
case sizeof(uint32_t):
|
case sizeof(uint32_t):
|
||||||
if (devices[device][func] == NULL)
|
if (devices[device][func] == NULL)
|
||||||
pkt->set<uint32_t>(0xFFFFFFFF);
|
pkt->set<uint32_t>(0xFFFFFFFF);
|
||||||
|
@ -127,7 +127,7 @@ PciConfigAll::read(Packet *pkt)
|
||||||
default:
|
default:
|
||||||
panic("invalid access size(?) for PCI configspace!\n");
|
panic("invalid access size(?) for PCI configspace!\n");
|
||||||
}
|
}
|
||||||
pkt->result = Success;
|
pkt->result = Packet::Success;
|
||||||
return pioDelay;
|
return pioDelay;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -136,11 +136,11 @@ PciConfigAll::write(Packet *pkt)
|
||||||
{
|
{
|
||||||
pkt->time += pioDelay;
|
pkt->time += pioDelay;
|
||||||
|
|
||||||
assert(pkt->result == Unknown);
|
assert(pkt->result == Packet::Unknown);
|
||||||
assert(pkt->addr >= pioAddr && pkt->addr < pioAddr + pioSize);
|
assert(pkt->getAddr() >= pioAddr && pkt->getAddr() < pioAddr + pioSize);
|
||||||
assert(pkt->size == sizeof(uint8_t) || pkt->size == sizeof(uint16_t) ||
|
assert(pkt->getSize() == sizeof(uint8_t) || pkt->getSize() == sizeof(uint16_t) ||
|
||||||
pkt->size == sizeof(uint32_t));
|
pkt->getSize() == sizeof(uint32_t));
|
||||||
Addr daddr = pkt->addr - pioAddr;
|
Addr daddr = pkt->getAddr() - pioAddr;
|
||||||
|
|
||||||
int device = (daddr >> 11) & 0x1F;
|
int device = (daddr >> 11) & 0x1F;
|
||||||
int func = (daddr >> 8) & 0x7;
|
int func = (daddr >> 8) & 0x7;
|
||||||
|
@ -150,9 +150,9 @@ PciConfigAll::write(Packet *pkt)
|
||||||
panic("Attempting to write to config space on non-existant device\n");
|
panic("Attempting to write to config space on non-existant device\n");
|
||||||
|
|
||||||
DPRINTF(PciConfigAll, "write - va=%#x size=%d data=%#x\n",
|
DPRINTF(PciConfigAll, "write - va=%#x size=%d data=%#x\n",
|
||||||
pkt->addr, pkt->size, pkt->get<uint32_t>());
|
pkt->getAddr(), pkt->getSize(), pkt->get<uint32_t>());
|
||||||
|
|
||||||
switch (pkt->size) {
|
switch (pkt->getSize()) {
|
||||||
case sizeof(uint8_t):
|
case sizeof(uint8_t):
|
||||||
devices[device][func]->writeConfig(reg, pkt->get<uint8_t>());
|
devices[device][func]->writeConfig(reg, pkt->get<uint8_t>());
|
||||||
break;
|
break;
|
||||||
|
@ -165,7 +165,7 @@ PciConfigAll::write(Packet *pkt)
|
||||||
default:
|
default:
|
||||||
panic("invalid pci config write size\n");
|
panic("invalid pci config write size\n");
|
||||||
}
|
}
|
||||||
pkt->result = Success;
|
pkt->result = Packet::Success;
|
||||||
return pioDelay;
|
return pioDelay;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -315,10 +315,10 @@ Tick
|
||||||
Device::read(Packet *pkt)
|
Device::read(Packet *pkt)
|
||||||
{
|
{
|
||||||
assert(config.command & PCI_CMD_MSE);
|
assert(config.command & PCI_CMD_MSE);
|
||||||
assert(pkt->addr >= BARAddrs[0] && pkt->size < BARSize[0]);
|
assert(pkt->getAddr() >= BARAddrs[0] && pkt->getSize() < BARSize[0]);
|
||||||
|
|
||||||
int cpu = pkt->req->getCpuNum();
|
int cpu = pkt->req->getCpuNum();
|
||||||
Addr daddr = pkt->addr - BARAddrs[0];
|
Addr daddr = pkt->getAddr() - BARAddrs[0];
|
||||||
Addr index = daddr >> Regs::VirtualShift;
|
Addr index = daddr >> Regs::VirtualShift;
|
||||||
Addr raddr = daddr & Regs::VirtualMask;
|
Addr raddr = daddr & Regs::VirtualMask;
|
||||||
|
|
||||||
|
@ -327,28 +327,28 @@ Device::read(Packet *pkt)
|
||||||
|
|
||||||
if (!regValid(raddr))
|
if (!regValid(raddr))
|
||||||
panic("invalid register: cpu=%d vnic=%d da=%#x pa=%#x size=%d",
|
panic("invalid register: cpu=%d vnic=%d da=%#x pa=%#x size=%d",
|
||||||
cpu, index, daddr, pkt->addr, pkt->size);
|
cpu, index, daddr, pkt->getAddr(), pkt->getSize());
|
||||||
|
|
||||||
const Regs::Info &info = regInfo(raddr);
|
const Regs::Info &info = regInfo(raddr);
|
||||||
if (!info.read)
|
if (!info.read)
|
||||||
panic("read %s (write only): "
|
panic("read %s (write only): "
|
||||||
"cpu=%d vnic=%d da=%#x pa=%#x size=%d",
|
"cpu=%d vnic=%d da=%#x pa=%#x size=%d",
|
||||||
info.name, cpu, index, daddr, pkt->addr, pkt->size);
|
info.name, cpu, index, daddr, pkt->getAddr(), pkt->getSize());
|
||||||
|
|
||||||
panic("read %s (invalid size): "
|
panic("read %s (invalid size): "
|
||||||
"cpu=%d vnic=%d da=%#x pa=%#x size=%d",
|
"cpu=%d vnic=%d da=%#x pa=%#x size=%d",
|
||||||
info.name, cpu, index, daddr, pkt->addr, pkt->size);
|
info.name, cpu, index, daddr, pkt->getAddr(), pkt->getSize());
|
||||||
|
|
||||||
prepareRead(cpu, index);
|
prepareRead(cpu, index);
|
||||||
|
|
||||||
uint64_t value = 0;
|
uint64_t value = 0;
|
||||||
if (pkt->size == 4) {
|
if (pkt->getSize() == 4) {
|
||||||
uint32_t reg = regData32(raddr);
|
uint32_t reg = regData32(raddr);
|
||||||
pkt->set(reg);
|
pkt->set(reg);
|
||||||
value = reg;
|
value = reg;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pkt->size == 8) {
|
if (pkt->getSize() == 8) {
|
||||||
uint64_t reg = regData64(raddr);
|
uint64_t reg = regData64(raddr);
|
||||||
pkt->set(reg);
|
pkt->set(reg);
|
||||||
value = reg;
|
value = reg;
|
||||||
|
@ -356,7 +356,7 @@ Device::read(Packet *pkt)
|
||||||
|
|
||||||
DPRINTF(EthernetPIO,
|
DPRINTF(EthernetPIO,
|
||||||
"read %s: cpu=%d vnic=%d da=%#x pa=%#x size=%d val=%#x\n",
|
"read %s: cpu=%d vnic=%d da=%#x pa=%#x size=%d val=%#x\n",
|
||||||
info.name, cpu, index, daddr, pkt->addr, pkt->size, value);
|
info.name, cpu, index, daddr, pkt->getAddr(), pkt->getSize(), value);
|
||||||
|
|
||||||
// reading the interrupt status register has the side effect of
|
// reading the interrupt status register has the side effect of
|
||||||
// clearing it
|
// clearing it
|
||||||
|
@ -403,10 +403,10 @@ Tick
|
||||||
Device::write(Packet *pkt)
|
Device::write(Packet *pkt)
|
||||||
{
|
{
|
||||||
assert(config.command & PCI_CMD_MSE);
|
assert(config.command & PCI_CMD_MSE);
|
||||||
assert(pkt->addr >= BARAddrs[0] && pkt->size < BARSize[0]);
|
assert(pkt->getAddr() >= BARAddrs[0] && pkt->getSize() < BARSize[0]);
|
||||||
|
|
||||||
int cpu = pkt->req->getCpuNum();
|
int cpu = pkt->req->getCpuNum();
|
||||||
Addr daddr = pkt->addr - BARAddrs[0];
|
Addr daddr = pkt->getAddr() - BARAddrs[0];
|
||||||
Addr index = daddr >> Regs::VirtualShift;
|
Addr index = daddr >> Regs::VirtualShift;
|
||||||
Addr raddr = daddr & Regs::VirtualMask;
|
Addr raddr = daddr & Regs::VirtualMask;
|
||||||
|
|
||||||
|
@ -414,25 +414,25 @@ Device::write(Packet *pkt)
|
||||||
|
|
||||||
if (!regValid(raddr))
|
if (!regValid(raddr))
|
||||||
panic("invalid register: cpu=%d, da=%#x pa=%#x size=%d",
|
panic("invalid register: cpu=%d, da=%#x pa=%#x size=%d",
|
||||||
cpu, daddr, pkt->addr, pkt->size);
|
cpu, daddr, pkt->getAddr(), pkt->getSize());
|
||||||
|
|
||||||
const Regs::Info &info = regInfo(raddr);
|
const Regs::Info &info = regInfo(raddr);
|
||||||
if (!info.write)
|
if (!info.write)
|
||||||
panic("write %s (read only): "
|
panic("write %s (read only): "
|
||||||
"cpu=%d vnic=%d da=%#x pa=%#x size=%d",
|
"cpu=%d vnic=%d da=%#x pa=%#x size=%d",
|
||||||
info.name, cpu, index, daddr, pkt->addr, pkt->size);
|
info.name, cpu, index, daddr, pkt->getAddr(), pkt->getSize());
|
||||||
|
|
||||||
if (pkt->size != info.size)
|
if (pkt->getSize() != info.size)
|
||||||
panic("write %s (invalid size): "
|
panic("write %s (invalid size): "
|
||||||
"cpu=%d vnic=%d da=%#x pa=%#x size=%d",
|
"cpu=%d vnic=%d da=%#x pa=%#x size=%d",
|
||||||
info.name, cpu, index, daddr, pkt->addr, pkt->size);
|
info.name, cpu, index, daddr, pkt->getAddr(), pkt->getSize());
|
||||||
|
|
||||||
VirtualReg &vnic = virtualRegs[index];
|
VirtualReg &vnic = virtualRegs[index];
|
||||||
|
|
||||||
DPRINTF(EthernetPIO,
|
DPRINTF(EthernetPIO,
|
||||||
"write %s vnic %d: cpu=%d val=%#x da=%#x pa=%#x size=%d\n",
|
"write %s vnic %d: cpu=%d val=%#x da=%#x pa=%#x size=%d\n",
|
||||||
info.name, index, cpu, info.size == 4 ? pkt->get<uint32_t>() :
|
info.name, index, cpu, info.size == 4 ? pkt->get<uint32_t>() :
|
||||||
pkt->get<uint64_t>(), daddr, pkt->addr, pkt->size);
|
pkt->get<uint64_t>(), daddr, pkt->getAddr(), pkt->getSize());
|
||||||
|
|
||||||
prepareWrite(cpu, index);
|
prepareWrite(cpu, index);
|
||||||
|
|
||||||
|
|
|
@ -71,17 +71,17 @@ TsunamiCChip::TsunamiCChip(Params *p)
|
||||||
Tick
|
Tick
|
||||||
TsunamiCChip::read(Packet *pkt)
|
TsunamiCChip::read(Packet *pkt)
|
||||||
{
|
{
|
||||||
DPRINTF(Tsunami, "read va=%#x size=%d\n", pkt->addr, pkt->size);
|
DPRINTF(Tsunami, "read va=%#x size=%d\n", pkt->getAddr(), pkt->getSize());
|
||||||
|
|
||||||
assert(pkt->result == Unknown);
|
assert(pkt->result == Packet::Unknown);
|
||||||
assert(pkt->addr >= pioAddr && pkt->addr < pioAddr + pioSize);
|
assert(pkt->getAddr() >= pioAddr && pkt->getAddr() < pioAddr + pioSize);
|
||||||
|
|
||||||
pkt->time += pioDelay;
|
pkt->time += pioDelay;
|
||||||
Addr regnum = (pkt->addr - pioAddr) >> 6;
|
Addr regnum = (pkt->getAddr() - pioAddr) >> 6;
|
||||||
Addr daddr = (pkt->addr - pioAddr);
|
Addr daddr = (pkt->getAddr() - pioAddr);
|
||||||
|
|
||||||
pkt->allocate();
|
pkt->allocate();
|
||||||
switch (pkt->size) {
|
switch (pkt->getSize()) {
|
||||||
|
|
||||||
case sizeof(uint64_t):
|
case sizeof(uint64_t):
|
||||||
if (daddr & TSDEV_CC_BDIMS)
|
if (daddr & TSDEV_CC_BDIMS)
|
||||||
|
@ -173,9 +173,9 @@ TsunamiCChip::read(Packet *pkt)
|
||||||
panic("invalid access size(?) for tsunami register!\n");
|
panic("invalid access size(?) for tsunami register!\n");
|
||||||
}
|
}
|
||||||
DPRINTF(Tsunami, "Tsunami CChip: read regnum=%#x size=%d data=%lld\n",
|
DPRINTF(Tsunami, "Tsunami CChip: read regnum=%#x size=%d data=%lld\n",
|
||||||
regnum, pkt->size, pkt->get<uint64_t>());
|
regnum, pkt->getSize(), pkt->get<uint64_t>());
|
||||||
|
|
||||||
pkt->result = Success;
|
pkt->result = Packet::Success;
|
||||||
return pioDelay;
|
return pioDelay;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -185,14 +185,14 @@ TsunamiCChip::write(Packet *pkt)
|
||||||
pkt->time += pioDelay;
|
pkt->time += pioDelay;
|
||||||
|
|
||||||
|
|
||||||
assert(pkt->addr >= pioAddr && pkt->addr < pioAddr + pioSize);
|
assert(pkt->getAddr() >= pioAddr && pkt->getAddr() < pioAddr + pioSize);
|
||||||
Addr daddr = pkt->addr - pioAddr;
|
Addr daddr = pkt->getAddr() - pioAddr;
|
||||||
Addr regnum = (pkt->addr - pioAddr) >> 6 ;
|
Addr regnum = (pkt->getAddr() - pioAddr) >> 6 ;
|
||||||
|
|
||||||
|
|
||||||
assert(pkt->size == sizeof(uint64_t));
|
assert(pkt->getSize() == sizeof(uint64_t));
|
||||||
|
|
||||||
DPRINTF(Tsunami, "write - addr=%#x value=%#x\n", pkt->addr, pkt->get<uint64_t>());
|
DPRINTF(Tsunami, "write - addr=%#x value=%#x\n", pkt->getAddr(), pkt->get<uint64_t>());
|
||||||
|
|
||||||
bool supportedWrite = false;
|
bool supportedWrite = false;
|
||||||
|
|
||||||
|
@ -362,7 +362,7 @@ TsunamiCChip::write(Packet *pkt)
|
||||||
panic("default in cchip read reached, accessing 0x%x\n");
|
panic("default in cchip read reached, accessing 0x%x\n");
|
||||||
} // swtich(regnum)
|
} // swtich(regnum)
|
||||||
} // not BIG_TSUNAMI write
|
} // not BIG_TSUNAMI write
|
||||||
pkt->result = Success;
|
pkt->result = Packet::Success;
|
||||||
return pioDelay;
|
return pioDelay;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -438,18 +438,18 @@ TsunamiIO::frequency() const
|
||||||
Tick
|
Tick
|
||||||
TsunamiIO::read(Packet *pkt)
|
TsunamiIO::read(Packet *pkt)
|
||||||
{
|
{
|
||||||
assert(pkt->result == Unknown);
|
assert(pkt->result == Packet::Unknown);
|
||||||
assert(pkt->addr >= pioAddr && pkt->addr < pioAddr + pioSize);
|
assert(pkt->getAddr() >= pioAddr && pkt->getAddr() < pioAddr + pioSize);
|
||||||
|
|
||||||
pkt->time += pioDelay;
|
pkt->time += pioDelay;
|
||||||
Addr daddr = pkt->addr - pioAddr;
|
Addr daddr = pkt->getAddr() - pioAddr;
|
||||||
|
|
||||||
DPRINTF(Tsunami, "io read va=%#x size=%d IOPorrt=%#x\n", pkt->addr,
|
DPRINTF(Tsunami, "io read va=%#x size=%d IOPorrt=%#x\n", pkt->getAddr(),
|
||||||
pkt->size, daddr);
|
pkt->getSize(), daddr);
|
||||||
|
|
||||||
pkt->allocate();
|
pkt->allocate();
|
||||||
|
|
||||||
if (pkt->size == sizeof(uint8_t)) {
|
if (pkt->getSize() == sizeof(uint8_t)) {
|
||||||
switch(daddr) {
|
switch(daddr) {
|
||||||
// PIC1 mask read
|
// PIC1 mask read
|
||||||
case TSDEV_PIC1_MASK:
|
case TSDEV_PIC1_MASK:
|
||||||
|
@ -487,18 +487,18 @@ TsunamiIO::read(Packet *pkt)
|
||||||
pkt->set(0x00);
|
pkt->set(0x00);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
panic("I/O Read - va%#x size %d\n", pkt->addr, pkt->size);
|
panic("I/O Read - va%#x size %d\n", pkt->getAddr(), pkt->getSize());
|
||||||
}
|
}
|
||||||
} else if (pkt->size == sizeof(uint64_t)) {
|
} else if (pkt->getSize() == sizeof(uint64_t)) {
|
||||||
if (daddr == TSDEV_PIC1_ISR)
|
if (daddr == TSDEV_PIC1_ISR)
|
||||||
pkt->set<uint64_t>(picr);
|
pkt->set<uint64_t>(picr);
|
||||||
else
|
else
|
||||||
panic("I/O Read - invalid addr - va %#x size %d\n",
|
panic("I/O Read - invalid addr - va %#x size %d\n",
|
||||||
pkt->addr, pkt->size);
|
pkt->getAddr(), pkt->getSize());
|
||||||
} else {
|
} else {
|
||||||
panic("I/O Read - invalid size - va %#x size %d\n", pkt->addr, pkt->size);
|
panic("I/O Read - invalid size - va %#x size %d\n", pkt->getAddr(), pkt->getSize());
|
||||||
}
|
}
|
||||||
pkt->result = Success;
|
pkt->result = Packet::Success;
|
||||||
return pioDelay;
|
return pioDelay;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -507,14 +507,14 @@ TsunamiIO::write(Packet *pkt)
|
||||||
{
|
{
|
||||||
pkt->time += pioDelay;
|
pkt->time += pioDelay;
|
||||||
|
|
||||||
assert(pkt->result == Unknown);
|
assert(pkt->result == Packet::Unknown);
|
||||||
assert(pkt->addr >= pioAddr && pkt->addr < pioAddr + pioSize);
|
assert(pkt->getAddr() >= pioAddr && pkt->getAddr() < pioAddr + pioSize);
|
||||||
Addr daddr = pkt->addr - pioAddr;
|
Addr daddr = pkt->getAddr() - pioAddr;
|
||||||
|
|
||||||
DPRINTF(Tsunami, "io write - va=%#x size=%d IOPort=%#x Data=%#x\n",
|
DPRINTF(Tsunami, "io write - va=%#x size=%d IOPort=%#x Data=%#x\n",
|
||||||
pkt->addr, pkt->size, pkt->addr & 0xfff, (uint32_t)pkt->get<uint8_t>());
|
pkt->getAddr(), pkt->getSize(), pkt->getAddr() & 0xfff, (uint32_t)pkt->get<uint8_t>());
|
||||||
|
|
||||||
assert(pkt->size == sizeof(uint8_t));
|
assert(pkt->getSize() == sizeof(uint8_t));
|
||||||
|
|
||||||
switch(daddr) {
|
switch(daddr) {
|
||||||
case TSDEV_PIC1_MASK:
|
case TSDEV_PIC1_MASK:
|
||||||
|
@ -577,10 +577,10 @@ TsunamiIO::write(Packet *pkt)
|
||||||
case TSDEV_CTRL_PORTB:
|
case TSDEV_CTRL_PORTB:
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
panic("I/O Write - va%#x size %d data %#x\n", pkt->addr, pkt->size, pkt->get<uint8_t>());
|
panic("I/O Write - va%#x size %d data %#x\n", pkt->getAddr(), pkt->getSize(), pkt->get<uint8_t>());
|
||||||
}
|
}
|
||||||
|
|
||||||
pkt->result = Success;
|
pkt->result = Packet::Success;
|
||||||
return pioDelay;
|
return pioDelay;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -67,17 +67,17 @@ TsunamiPChip::TsunamiPChip(Params *p)
|
||||||
Tick
|
Tick
|
||||||
TsunamiPChip::read(Packet *pkt)
|
TsunamiPChip::read(Packet *pkt)
|
||||||
{
|
{
|
||||||
assert(pkt->result == Unknown);
|
assert(pkt->result == Packet::Unknown);
|
||||||
assert(pkt->addr >= pioAddr && pkt->addr < pioAddr + pioSize);
|
assert(pkt->getAddr() >= pioAddr && pkt->getAddr() < pioAddr + pioSize);
|
||||||
|
|
||||||
|
|
||||||
pkt->time += pioDelay;
|
pkt->time += pioDelay;
|
||||||
pkt->allocate();
|
pkt->allocate();
|
||||||
Addr daddr = (pkt->addr - pioAddr) >> 6;;
|
Addr daddr = (pkt->getAddr() - pioAddr) >> 6;;
|
||||||
assert(pkt->size == sizeof(uint64_t));
|
assert(pkt->getSize() == sizeof(uint64_t));
|
||||||
|
|
||||||
|
|
||||||
DPRINTF(Tsunami, "read va=%#x size=%d\n", pkt->addr, pkt->size);
|
DPRINTF(Tsunami, "read va=%#x size=%d\n", pkt->getAddr(), pkt->getSize());
|
||||||
|
|
||||||
switch(daddr) {
|
switch(daddr) {
|
||||||
case TSDEV_PC_WSBA0:
|
case TSDEV_PC_WSBA0:
|
||||||
|
@ -143,7 +143,7 @@ TsunamiPChip::read(Packet *pkt)
|
||||||
default:
|
default:
|
||||||
panic("Default in PChip Read reached reading 0x%x\n", daddr);
|
panic("Default in PChip Read reached reading 0x%x\n", daddr);
|
||||||
}
|
}
|
||||||
pkt->result = Success;
|
pkt->result = Packet::Success;
|
||||||
return pioDelay;
|
return pioDelay;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -153,13 +153,13 @@ TsunamiPChip::write(Packet *pkt)
|
||||||
{
|
{
|
||||||
pkt->time += pioDelay;
|
pkt->time += pioDelay;
|
||||||
|
|
||||||
assert(pkt->result == Unknown);
|
assert(pkt->result == Packet::Unknown);
|
||||||
assert(pkt->addr >= pioAddr && pkt->addr < pioAddr + pioSize);
|
assert(pkt->getAddr() >= pioAddr && pkt->getAddr() < pioAddr + pioSize);
|
||||||
Addr daddr = (pkt->addr - pioAddr) >> 6;
|
Addr daddr = (pkt->getAddr() - pioAddr) >> 6;
|
||||||
|
|
||||||
assert(pkt->size == sizeof(uint64_t));
|
assert(pkt->getSize() == sizeof(uint64_t));
|
||||||
|
|
||||||
DPRINTF(Tsunami, "write - va=%#x size=%d \n", pkt->addr, pkt->size);
|
DPRINTF(Tsunami, "write - va=%#x size=%d \n", pkt->getAddr(), pkt->getSize());
|
||||||
|
|
||||||
switch(daddr) {
|
switch(daddr) {
|
||||||
case TSDEV_PC_WSBA0:
|
case TSDEV_PC_WSBA0:
|
||||||
|
@ -224,7 +224,7 @@ TsunamiPChip::write(Packet *pkt)
|
||||||
|
|
||||||
} // uint64_t
|
} // uint64_t
|
||||||
|
|
||||||
pkt->result = Success;
|
pkt->result = Packet::Success;
|
||||||
return pioDelay;
|
return pioDelay;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -110,12 +110,12 @@ Uart8250::Uart8250(Params *p)
|
||||||
Tick
|
Tick
|
||||||
Uart8250::read(Packet *pkt)
|
Uart8250::read(Packet *pkt)
|
||||||
{
|
{
|
||||||
assert(pkt->result == Unknown);
|
assert(pkt->result == Packet::Unknown);
|
||||||
assert(pkt->addr >= pioAddr && pkt->addr < pioAddr + pioSize);
|
assert(pkt->getAddr() >= pioAddr && pkt->getAddr() < pioAddr + pioSize);
|
||||||
assert(pkt->size == 1);
|
assert(pkt->getSize() == 1);
|
||||||
|
|
||||||
pkt->time += pioDelay;
|
pkt->time += pioDelay;
|
||||||
Addr daddr = pkt->addr - pioAddr;
|
Addr daddr = pkt->getAddr() - pioAddr;
|
||||||
pkt->allocate();
|
pkt->allocate();
|
||||||
|
|
||||||
DPRINTF(Uart, " read register %#x\n", daddr);
|
DPRINTF(Uart, " read register %#x\n", daddr);
|
||||||
|
@ -186,7 +186,7 @@ Uart8250::read(Packet *pkt)
|
||||||
/* uint32_t d32 = *data;
|
/* uint32_t d32 = *data;
|
||||||
DPRINTF(Uart, "Register read to register %#x returned %#x\n", daddr, d32);
|
DPRINTF(Uart, "Register read to register %#x returned %#x\n", daddr, d32);
|
||||||
*/
|
*/
|
||||||
pkt->result = Success;
|
pkt->result = Packet::Success;
|
||||||
return pioDelay;
|
return pioDelay;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -194,12 +194,12 @@ Tick
|
||||||
Uart8250::write(Packet *pkt)
|
Uart8250::write(Packet *pkt)
|
||||||
{
|
{
|
||||||
|
|
||||||
assert(pkt->result == Unknown);
|
assert(pkt->result == Packet::Unknown);
|
||||||
assert(pkt->addr >= pioAddr && pkt->addr < pioAddr + pioSize);
|
assert(pkt->getAddr() >= pioAddr && pkt->getAddr() < pioAddr + pioSize);
|
||||||
assert(pkt->size == 1);
|
assert(pkt->getSize() == 1);
|
||||||
|
|
||||||
pkt->time += pioDelay;
|
pkt->time += pioDelay;
|
||||||
Addr daddr = pkt->addr - pioAddr;
|
Addr daddr = pkt->getAddr() - pioAddr;
|
||||||
|
|
||||||
DPRINTF(Uart, " write register %#x value %#x\n", daddr, pkt->get<uint8_t>());
|
DPRINTF(Uart, " write register %#x value %#x\n", daddr, pkt->get<uint8_t>());
|
||||||
|
|
||||||
|
@ -264,7 +264,7 @@ Uart8250::write(Packet *pkt)
|
||||||
panic("Tried to access a UART port that doesn't exist\n");
|
panic("Tried to access a UART port that doesn't exist\n");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
pkt->result = Success;
|
pkt->result = Packet::Success;
|
||||||
return pioDelay;
|
return pioDelay;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -31,209 +31,209 @@
|
||||||
* @file Definition of a simple bus bridge without buffering.
|
* @file Definition of a simple bus bridge without buffering.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
#include "base/trace.hh"
|
#include "base/trace.hh"
|
||||||
#include "mem/bridge.hh"
|
#include "mem/bridge.hh"
|
||||||
#include "sim/builder.hh"
|
#include "sim/builder.hh"
|
||||||
|
|
||||||
|
Bridge::BridgePort::BridgePort(const std::string &_name,
|
||||||
|
Bridge *_bridge, BridgePort *_otherPort,
|
||||||
|
int _delay, int _queueLimit)
|
||||||
|
: Port(_name), bridge(_bridge), otherPort(_otherPort),
|
||||||
|
delay(_delay), outstandingResponses(0),
|
||||||
|
queueLimit(_queueLimit), sendEvent(this)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
Bridge::Bridge(const std::string &n, int qsa, int qsb,
|
||||||
|
Tick _delay, int write_ack)
|
||||||
|
: MemObject(n),
|
||||||
|
portA(n + "-portA", this, &portB, _delay, qsa),
|
||||||
|
portB(n + "-portB", this, &portA, _delay, qsa),
|
||||||
|
ackWrites(write_ack)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
Port *
|
||||||
|
Bridge::getPort(const std::string &if_name)
|
||||||
|
{
|
||||||
|
BridgePort *port;
|
||||||
|
|
||||||
|
if (if_name == "side_a")
|
||||||
|
port = &portA;
|
||||||
|
else if (if_name == "side_b")
|
||||||
|
port = &portB;
|
||||||
|
else
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
if (port->getPeer() != NULL)
|
||||||
|
panic("bridge side %s already connected to.", if_name);
|
||||||
|
return port;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
Bridge::init()
|
Bridge::init()
|
||||||
{
|
{
|
||||||
// Make sure that both sides are connected to.
|
// Make sure that both sides are connected to.
|
||||||
if (sideA == NULL || sideB == NULL)
|
if (portA.getPeer() == NULL || portB.getPeer() == NULL)
|
||||||
panic("Both ports of bus bridge are not connected to a bus.\n");
|
panic("Both ports of bus bridge are not connected to a bus.\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/** Function called by the port when the bus is recieving a Timing
|
/** Function called by the port when the bus is receiving a Timing
|
||||||
* transaction.*/
|
* transaction.*/
|
||||||
bool
|
bool
|
||||||
Bridge::recvTiming(Packet *pkt, Side id)
|
Bridge::BridgePort::recvTiming(Packet *pkt)
|
||||||
{
|
{
|
||||||
if (blockedA && id == SideA)
|
DPRINTF(BusBridge, "recvTiming: src %d dest %d addr 0x%x\n",
|
||||||
return false;
|
pkt->getSrc(), pkt->getDest(), pkt->getAddr());
|
||||||
if (blockedB && id == SideB)
|
|
||||||
|
if (pkt->isResponse()) {
|
||||||
|
// This is a response for a request we forwarded earlier. The
|
||||||
|
// corresponding PacketBuffer should be stored in the packet's
|
||||||
|
// senderState field.
|
||||||
|
PacketBuffer *buf = dynamic_cast<PacketBuffer*>(pkt->senderState);
|
||||||
|
assert(buf != NULL);
|
||||||
|
// set up new packet dest & senderState based on values saved
|
||||||
|
// from original request
|
||||||
|
buf->fixResponse(pkt);
|
||||||
|
DPRINTF(BusBridge, " is response, new dest %d\n", pkt->getDest());
|
||||||
|
delete buf;
|
||||||
|
}
|
||||||
|
|
||||||
|
return otherPort->queueForSendTiming(pkt);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool
|
||||||
|
Bridge::BridgePort::queueForSendTiming(Packet *pkt)
|
||||||
|
{
|
||||||
|
if (queueFull())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (delay) {
|
Tick readyTime = curTick + delay;
|
||||||
if (!sendEvent.scheduled())
|
PacketBuffer *buf = new PacketBuffer(pkt, readyTime);
|
||||||
sendEvent.schedule(curTick + delay);
|
|
||||||
if (id == SideA) {
|
// If we're about to put this packet at the head of the queue, we
|
||||||
inboundA.push_back(std::make_pair<Packet*, Tick>(pkt, curTick));
|
// need to schedule an event to do the transmit. Otherwise there
|
||||||
blockCheck(SideA);
|
// should already be an event scheduled for sending the head
|
||||||
} else {
|
// packet.
|
||||||
inboundB.push_back(std::make_pair<Packet*, Tick>(pkt, curTick));
|
if (sendQueue.empty()) {
|
||||||
blockCheck(SideB);
|
sendEvent.schedule(readyTime);
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (id == SideB) {
|
|
||||||
sideA->sendPkt(pkt);
|
|
||||||
blockCheck(SideB);
|
|
||||||
} else {
|
|
||||||
sideB->sendPkt(pkt);
|
|
||||||
blockCheck(SideA);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sendQueue.push_back(buf);
|
||||||
|
|
||||||
|
// Did we just become blocked? If yes, let other side know.
|
||||||
|
if (queueFull())
|
||||||
|
otherPort->sendStatusChange(Port::Blocked);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
Bridge::blockCheck(Side id)
|
Bridge::BridgePort::finishSend(PacketBuffer *buf)
|
||||||
{
|
{
|
||||||
/* Check that we still have buffer space available. */
|
if (buf->expectResponse) {
|
||||||
if (id == SideB) {
|
// Must wait for response. We just need to count outstanding
|
||||||
if (sideA->numQueued() + inboundB.size() >= queueSizeA && !blockedB) {
|
// responses (in case we want to cap them); PacketBuffer
|
||||||
sideB->sendStatusChange(Port::Blocked);
|
// pointer will be recovered on response.
|
||||||
blockedB = true;
|
++outstandingResponses;
|
||||||
} else if (sideA->numQueued() + inboundB.size() < queueSizeA && blockedB) {
|
DPRINTF(BusBridge, " successful: awaiting response (%d)\n",
|
||||||
sideB->sendStatusChange(Port::Unblocked);
|
outstandingResponses);
|
||||||
blockedB = false;
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
if (sideB->numQueued() + inboundA.size() >= queueSizeB && !blockedA) {
|
// no response expected... deallocate packet buffer now.
|
||||||
sideA->sendStatusChange(Port::Blocked);
|
DPRINTF(BusBridge, " successful: no response expected\n");
|
||||||
blockedA = true;
|
delete buf;
|
||||||
} else if (sideB->numQueued() + inboundA.size() < queueSizeB && blockedA) {
|
|
||||||
sideA->sendStatusChange(Port::Unblocked);
|
|
||||||
blockedA = false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If there are more packets to send, schedule event to try again.
|
||||||
|
if (!sendQueue.empty()) {
|
||||||
|
buf = sendQueue.front();
|
||||||
|
sendEvent.schedule(std::max(buf->ready, curTick + 1));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Bridge::timerEvent()
|
|
||||||
{
|
|
||||||
Tick t = 0;
|
|
||||||
|
|
||||||
assert(inboundA.size() || inboundB.size());
|
void
|
||||||
if (inboundA.size()) {
|
Bridge::BridgePort::trySend()
|
||||||
while (inboundA.front().second <= curTick + delay){
|
{
|
||||||
sideB->sendPkt(inboundA.front());
|
assert(!sendQueue.empty());
|
||||||
inboundA.pop_front();
|
|
||||||
}
|
PacketBuffer *buf = sendQueue.front();
|
||||||
if (inboundA.size())
|
|
||||||
t = inboundA.front().second + delay;
|
assert(buf->ready <= curTick);
|
||||||
}
|
|
||||||
if (inboundB.size()) {
|
Packet *pkt = buf->pkt;
|
||||||
while (inboundB.front().second <= curTick + delay){
|
|
||||||
sideB->sendPkt(inboundA.front());
|
DPRINTF(BusBridge, "trySend: origSrc %d dest %d addr 0x%x\n",
|
||||||
inboundB.pop_front();
|
buf->origSrc, pkt->getDest(), pkt->getAddr());
|
||||||
}
|
|
||||||
if (inboundB.size())
|
if (sendTiming(pkt)) {
|
||||||
if (t == 0)
|
// send successful
|
||||||
t = inboundB.front().second + delay;
|
sendQueue.pop_front();
|
||||||
else
|
buf->pkt = NULL; // we no longer own packet, so it's not safe to look at it
|
||||||
t = std::min(t,inboundB.front().second + delay);
|
finishSend(buf);
|
||||||
} else {
|
} else {
|
||||||
panic("timerEvent() called but nothing to do?");
|
DPRINTF(BusBridge, " unsuccessful\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (t != 0)
|
|
||||||
sendEvent.schedule(t);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void
|
|
||||||
Bridge::BridgePort::sendPkt(Packet *pkt)
|
|
||||||
{
|
|
||||||
if (!sendTiming(pkt))
|
|
||||||
outbound.push_back(std::make_pair<Packet*,Tick>(pkt, curTick));
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
Bridge::BridgePort::sendPkt(std::pair<Packet*, Tick> p)
|
|
||||||
{
|
|
||||||
if (!sendTiming(p.first))
|
|
||||||
outbound.push_back(p);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Packet *
|
Packet *
|
||||||
Bridge::BridgePort::recvRetry()
|
Bridge::BridgePort::recvRetry()
|
||||||
{
|
{
|
||||||
Packet *pkt;
|
PacketBuffer *buf = sendQueue.front();
|
||||||
assert(outbound.size() > 0);
|
Packet *pkt = buf->pkt;
|
||||||
assert(outbound.front().second >= curTick + bridge->delay);
|
finishSend(buf);
|
||||||
pkt = outbound.front().first;
|
|
||||||
outbound.pop_front();
|
|
||||||
bridge->blockCheck(side);
|
|
||||||
return pkt;
|
return pkt;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Function called by the port when the bus is recieving a Atomic
|
/** Function called by the port when the bus is receiving a Atomic
|
||||||
* transaction.*/
|
* transaction.*/
|
||||||
Tick
|
Tick
|
||||||
Bridge::recvAtomic(Packet *pkt, Side id)
|
Bridge::BridgePort::recvAtomic(Packet *pkt)
|
||||||
{
|
{
|
||||||
pkt->time += delay;
|
return otherPort->sendAtomic(pkt) + delay;
|
||||||
|
|
||||||
if (id == SideA)
|
|
||||||
return sideB->sendAtomic(pkt);
|
|
||||||
else
|
|
||||||
return sideA->sendAtomic(pkt);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Function called by the port when the bus is recieving a Functional
|
/** Function called by the port when the bus is receiving a Functional
|
||||||
* transaction.*/
|
* transaction.*/
|
||||||
void
|
void
|
||||||
Bridge::recvFunctional(Packet *pkt, Side id)
|
Bridge::BridgePort::recvFunctional(Packet *pkt)
|
||||||
{
|
{
|
||||||
pkt->time += delay;
|
std::list<PacketBuffer*>::iterator i;
|
||||||
std::list<std::pair<Packet*, Tick> >::iterator i;
|
|
||||||
bool pktContinue = true;
|
bool pktContinue = true;
|
||||||
|
|
||||||
for(i = inboundA.begin(); i != inboundA.end(); ++i) {
|
for (i = sendQueue.begin(); i != sendQueue.end(); ++i) {
|
||||||
if (pkt->intersect(i->first)) {
|
if (pkt->intersect((*i)->pkt)) {
|
||||||
pktContinue &= fixPacket(pkt, i->first);
|
pktContinue &= fixPacket(pkt, (*i)->pkt);
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for(i = inboundB.begin(); i != inboundB.end(); ++i) {
|
|
||||||
if (pkt->intersect(i->first)) {
|
|
||||||
pktContinue &= fixPacket(pkt, i->first);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for(i = sideA->outbound.begin(); i != sideA->outbound.end(); ++i) {
|
|
||||||
if (pkt->intersect(i->first)) {
|
|
||||||
pktContinue &= fixPacket(pkt, i->first);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for(i = sideB->outbound.begin(); i != sideB->outbound.end(); ++i) {
|
|
||||||
if (pkt->intersect(i->first)) {
|
|
||||||
pktContinue &= fixPacket(pkt, i->first);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pktContinue) {
|
if (pktContinue) {
|
||||||
if (id == SideA)
|
otherPort->sendFunctional(pkt);
|
||||||
sideB->sendFunctional(pkt);
|
|
||||||
else
|
|
||||||
sideA->sendFunctional(pkt);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Function called by the port when the bus is recieving a status change.*/
|
/** Function called by the port when the bus is receiving a status change.*/
|
||||||
void
|
void
|
||||||
Bridge::recvStatusChange(Port::Status status, Side id)
|
Bridge::BridgePort::recvStatusChange(Port::Status status)
|
||||||
{
|
{
|
||||||
if (status == Port::Blocked || status == Port::Unblocked)
|
if (status == Port::Blocked || status == Port::Unblocked)
|
||||||
return ;
|
return;
|
||||||
|
|
||||||
if (id == SideA)
|
otherPort->sendStatusChange(status);
|
||||||
sideB->sendStatusChange(status);
|
|
||||||
else
|
|
||||||
sideA->sendStatusChange(status);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
Bridge::addressRanges(AddrRangeList &resp, AddrRangeList &snoop, Side id)
|
Bridge::BridgePort::getDeviceAddressRanges(AddrRangeList &resp,
|
||||||
|
AddrRangeList &snoop)
|
||||||
{
|
{
|
||||||
if (id == SideA)
|
otherPort->getPeerAddressRanges(resp, snoop);
|
||||||
sideB->getPeerAddressRanges(resp, snoop);
|
|
||||||
else
|
|
||||||
sideA->getPeerAddressRanges(resp, snoop);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
BEGIN_DECLARE_SIM_OBJECT_PARAMS(Bridge)
|
BEGIN_DECLARE_SIM_OBJECT_PARAMS(Bridge)
|
||||||
|
|
|
@ -46,132 +46,127 @@
|
||||||
|
|
||||||
class Bridge : public MemObject
|
class Bridge : public MemObject
|
||||||
{
|
{
|
||||||
public:
|
|
||||||
enum Side
|
|
||||||
{
|
|
||||||
SideA,
|
|
||||||
SideB
|
|
||||||
};
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
/** Function called by the port when the bus is recieving a Timing
|
|
||||||
transaction.*/
|
|
||||||
bool recvTiming(Packet *pkt, Side id);
|
|
||||||
|
|
||||||
/** Function called by the port when the bus is recieving a Atomic
|
|
||||||
transaction.*/
|
|
||||||
Tick recvAtomic(Packet *pkt, Side id);
|
|
||||||
|
|
||||||
/** Function called by the port when the bus is recieving a Functional
|
|
||||||
transaction.*/
|
|
||||||
void recvFunctional(Packet *pkt, Side id);
|
|
||||||
|
|
||||||
/** Function called by the port when the bus is recieving a status change.*/
|
|
||||||
void recvStatusChange(Port::Status status, Side id);
|
|
||||||
|
|
||||||
/** Process address range request.
|
|
||||||
* @param resp addresses that we can respond to
|
|
||||||
* @param snoop addresses that we would like to snoop
|
|
||||||
* @param id ide of the busport that made the request.
|
|
||||||
*/
|
|
||||||
void addressRanges(AddrRangeList &resp, AddrRangeList &snoop, Side id);
|
|
||||||
|
|
||||||
|
|
||||||
/** Event that the SendEvent calls when it fires. This code must reschedule
|
|
||||||
* the send event as required. */
|
|
||||||
void timerEvent();
|
|
||||||
|
|
||||||
/** Decleration of the buses port type, one will be instantiated for each
|
/** Decleration of the buses port type, one will be instantiated for each
|
||||||
of the interfaces connecting to the bus. */
|
of the interfaces connecting to the bus. */
|
||||||
class BridgePort : public Port
|
class BridgePort : public Port
|
||||||
{
|
{
|
||||||
/** A pointer to the bus to which this port belongs. */
|
/** A pointer to the bridge to which this port belongs. */
|
||||||
Bridge *bridge;
|
Bridge *bridge;
|
||||||
|
|
||||||
/** A id to keep track of the intercafe ID this port is connected to. */
|
/**
|
||||||
Bridge::Side side;
|
* Pointer to the port on the other side of the bridge
|
||||||
|
* (connected to the other bus).
|
||||||
|
*/
|
||||||
|
BridgePort *otherPort;
|
||||||
|
|
||||||
|
/** Minimum delay though this bridge. */
|
||||||
|
Tick delay;
|
||||||
|
|
||||||
|
class PacketBuffer : public Packet::SenderState {
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
Tick ready;
|
||||||
|
Packet *pkt;
|
||||||
|
Packet::SenderState *origSenderState;
|
||||||
|
short origSrc;
|
||||||
|
bool expectResponse;
|
||||||
|
|
||||||
/** Constructor for the BusPort.*/
|
PacketBuffer(Packet *_pkt, Tick t)
|
||||||
BridgePort(Bridge *_bridge, Side _side)
|
: ready(t), pkt(_pkt),
|
||||||
: bridge(_bridge), side(_side)
|
origSenderState(_pkt->senderState), origSrc(_pkt->getSrc()),
|
||||||
{ }
|
expectResponse(_pkt->needsResponse())
|
||||||
|
{
|
||||||
|
pkt->senderState = this;
|
||||||
|
}
|
||||||
|
|
||||||
int numQueued() { return outbound.size(); }
|
void fixResponse(Packet *pkt)
|
||||||
|
{
|
||||||
protected:
|
assert(pkt->senderState == this);
|
||||||
/** Data this is waiting to be transmitted. */
|
pkt->setDest(origSrc);
|
||||||
std::list<std::pair<Packet*, Tick> > outbound;
|
pkt->senderState = origSenderState;
|
||||||
|
}
|
||||||
void sendPkt(Packet *pkt);
|
|
||||||
void sendPkt(std::pair<Packet*, Tick> p);
|
|
||||||
|
|
||||||
/** When reciving a timing request from the peer port,
|
|
||||||
pass it to the bridge. */
|
|
||||||
virtual bool recvTiming(Packet *pkt)
|
|
||||||
{ return bridge->recvTiming(pkt, side); }
|
|
||||||
|
|
||||||
/** When reciving a retry request from the peer port,
|
|
||||||
pass it to the bridge. */
|
|
||||||
virtual Packet* recvRetry();
|
|
||||||
|
|
||||||
/** When reciving a Atomic requestfrom the peer port,
|
|
||||||
pass it to the bridge. */
|
|
||||||
virtual Tick recvAtomic(Packet *pkt)
|
|
||||||
{ return bridge->recvAtomic(pkt, side); }
|
|
||||||
|
|
||||||
/** When reciving a Functional request from the peer port,
|
|
||||||
pass it to the bridge. */
|
|
||||||
virtual void recvFunctional(Packet *pkt)
|
|
||||||
{ bridge->recvFunctional(pkt, side); }
|
|
||||||
|
|
||||||
/** When reciving a status changefrom the peer port,
|
|
||||||
pass it to the bridge. */
|
|
||||||
virtual void recvStatusChange(Status status)
|
|
||||||
{ bridge->recvStatusChange(status, side); }
|
|
||||||
|
|
||||||
/** When reciving a address range request the peer port,
|
|
||||||
pass it to the bridge. */
|
|
||||||
virtual void getDeviceAddressRanges(AddrRangeList &resp, AddrRangeList &snoop)
|
|
||||||
{ bridge->addressRanges(resp, snoop, side); }
|
|
||||||
|
|
||||||
friend class Bridge;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Outbound packet queue. Packets are held in this queue for a
|
||||||
|
* specified delay to model the processing delay of the
|
||||||
|
* bridge.
|
||||||
|
*/
|
||||||
|
std::list<PacketBuffer*> sendQueue;
|
||||||
|
|
||||||
|
int outstandingResponses;
|
||||||
|
|
||||||
|
/** Max queue size for outbound packets */
|
||||||
|
int queueLimit;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Is this side blocked from accepting outbound packets?
|
||||||
|
*/
|
||||||
|
bool queueFull() { return (sendQueue.size() == queueLimit); }
|
||||||
|
|
||||||
|
bool queueForSendTiming(Packet *pkt);
|
||||||
|
|
||||||
|
void finishSend(PacketBuffer *buf);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handle send event, scheduled when the packet at the head of
|
||||||
|
* the outbound queue is ready to transmit (for timing
|
||||||
|
* accesses only).
|
||||||
|
*/
|
||||||
|
void trySend();
|
||||||
|
|
||||||
class SendEvent : public Event
|
class SendEvent : public Event
|
||||||
{
|
{
|
||||||
Bridge *bridge;
|
BridgePort *port;
|
||||||
|
|
||||||
SendEvent(Bridge *b)
|
public:
|
||||||
: Event(&mainEventQueue), bridge(b) {}
|
SendEvent(BridgePort *p)
|
||||||
|
: Event(&mainEventQueue), port(p) {}
|
||||||
|
|
||||||
virtual void process() { bridge->timerEvent(); }
|
virtual void process() { port->trySend(); }
|
||||||
|
|
||||||
virtual const char *description() { return "bridge delay event"; }
|
virtual const char *description() { return "bridge send event"; }
|
||||||
friend class Bridge;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
SendEvent sendEvent;
|
SendEvent sendEvent;
|
||||||
|
|
||||||
/** Sides of the bus bridges. */
|
public:
|
||||||
BridgePort* sideA;
|
|
||||||
BridgePort* sideB;
|
|
||||||
|
|
||||||
/** inbound queues on both sides. */
|
/** Constructor for the BusPort.*/
|
||||||
std::list<std::pair<Packet*, Tick> > inboundA;
|
BridgePort(const std::string &_name,
|
||||||
std::list<std::pair<Packet*, Tick> > inboundB;
|
Bridge *_bridge, BridgePort *_otherPort,
|
||||||
|
int _delay, int _queueLimit);
|
||||||
|
|
||||||
/** The size of the queue for data coming into side a */
|
protected:
|
||||||
int queueSizeA;
|
|
||||||
int queueSizeB;
|
|
||||||
|
|
||||||
/* if the side is blocked or not. */
|
/** When receiving a timing request from the peer port,
|
||||||
bool blockedA;
|
pass it to the bridge. */
|
||||||
bool blockedB;
|
virtual bool recvTiming(Packet *pkt);
|
||||||
|
|
||||||
/** Miminum delay though this bridge. */
|
/** When receiving a retry request from the peer port,
|
||||||
Tick delay;
|
pass it to the bridge. */
|
||||||
|
virtual Packet* recvRetry();
|
||||||
|
|
||||||
|
/** When receiving a Atomic requestfrom the peer port,
|
||||||
|
pass it to the bridge. */
|
||||||
|
virtual Tick recvAtomic(Packet *pkt);
|
||||||
|
|
||||||
|
/** When receiving a Functional request from the peer port,
|
||||||
|
pass it to the bridge. */
|
||||||
|
virtual void recvFunctional(Packet *pkt);
|
||||||
|
|
||||||
|
/** When receiving a status changefrom the peer port,
|
||||||
|
pass it to the bridge. */
|
||||||
|
virtual void recvStatusChange(Status status);
|
||||||
|
|
||||||
|
/** When receiving a address range request the peer port,
|
||||||
|
pass it to the bridge. */
|
||||||
|
virtual void getDeviceAddressRanges(AddrRangeList &resp,
|
||||||
|
AddrRangeList &snoop);
|
||||||
|
};
|
||||||
|
|
||||||
|
BridgePort portA, portB;
|
||||||
|
|
||||||
/** If this bridge should acknowledge writes. */
|
/** If this bridge should acknowledge writes. */
|
||||||
bool ackWrites;
|
bool ackWrites;
|
||||||
|
@ -179,36 +174,11 @@ class Bridge : public MemObject
|
||||||
public:
|
public:
|
||||||
|
|
||||||
/** A function used to return the port associated with this bus object. */
|
/** A function used to return the port associated with this bus object. */
|
||||||
virtual Port *getPort(const std::string &if_name)
|
virtual Port *getPort(const std::string &if_name);
|
||||||
{
|
|
||||||
if (if_name == "side_a") {
|
|
||||||
if (sideA != NULL)
|
|
||||||
panic("bridge side a already connected to.");
|
|
||||||
sideA = new BridgePort(this, SideA);
|
|
||||||
return sideA;
|
|
||||||
} else if (if_name == "side_b") {
|
|
||||||
if (sideB != NULL)
|
|
||||||
panic("bridge side b already connected to.");
|
|
||||||
sideB = new BridgePort(this, SideB);
|
|
||||||
return sideB;
|
|
||||||
} else
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual void init();
|
virtual void init();
|
||||||
|
|
||||||
Bridge(const std::string &n, int qsa, int qsb, Tick _delay, int write_ack)
|
Bridge(const std::string &n, int qsa, int qsb, Tick _delay, int write_ack);
|
||||||
: MemObject(n), sendEvent(this), sideA(NULL), sideB(NULL),
|
|
||||||
queueSizeA(qsa), queueSizeB(qsb), blockedA(false), blockedB(false),
|
|
||||||
delay(_delay), ackWrites(write_ack)
|
|
||||||
{}
|
|
||||||
|
|
||||||
/** Check if the port should block/unblock after recieving/sending a packet.
|
|
||||||
* */
|
|
||||||
void blockCheck(Side id);
|
|
||||||
|
|
||||||
friend class Bridge::SendEvent;
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif //__MEM_BUS_HH__
|
#endif //__MEM_BUS_HH__
|
||||||
|
|
|
@ -35,6 +35,16 @@
|
||||||
#include "mem/bus.hh"
|
#include "mem/bus.hh"
|
||||||
#include "sim/builder.hh"
|
#include "sim/builder.hh"
|
||||||
|
|
||||||
|
Port *
|
||||||
|
Bus::getPort(const std::string &if_name)
|
||||||
|
{
|
||||||
|
// if_name ignored? forced to be empty?
|
||||||
|
int id = interfaces.size();
|
||||||
|
BusPort *bp = new BusPort(csprintf("%s-p%d", name(), id), this, id);
|
||||||
|
interfaces.push_back(bp);
|
||||||
|
return bp;
|
||||||
|
}
|
||||||
|
|
||||||
/** Get the ranges of anyone that we are connected to. */
|
/** Get the ranges of anyone that we are connected to. */
|
||||||
void
|
void
|
||||||
Bus::init()
|
Bus::init()
|
||||||
|
@ -45,17 +55,22 @@ Bus::init()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/** Function called by the port when the bus is recieving a Timing
|
/** Function called by the port when the bus is receiving a Timing
|
||||||
* transaction.*/
|
* transaction.*/
|
||||||
bool
|
bool
|
||||||
Bus::recvTiming(Packet *pkt)
|
Bus::recvTiming(Packet *pkt)
|
||||||
{
|
{
|
||||||
Port *port;
|
Port *port;
|
||||||
if (pkt->dest == Packet::Broadcast) {
|
DPRINTF(Bus, "recvTiming: packet src %d dest %d addr 0x%x cmd %s\n",
|
||||||
port = findPort(pkt->addr, pkt->src);
|
pkt->getSrc(), pkt->getDest(), pkt->getAddr(), pkt->cmdString());
|
||||||
|
|
||||||
|
short dest = pkt->getDest();
|
||||||
|
if (dest == Packet::Broadcast) {
|
||||||
|
port = findPort(pkt->getAddr(), pkt->getSrc());
|
||||||
} else {
|
} else {
|
||||||
assert(pkt->dest > 0 && pkt->dest < interfaces.size());
|
assert(dest >= 0 && dest < interfaces.size());
|
||||||
port = interfaces[pkt->dest];
|
assert(dest != pkt->getSrc()); // catch infinite loops
|
||||||
|
port = interfaces[dest];
|
||||||
}
|
}
|
||||||
return port->sendTiming(pkt);
|
return port->sendTiming(pkt);
|
||||||
}
|
}
|
||||||
|
@ -73,7 +88,7 @@ Bus::findPort(Addr addr, int id)
|
||||||
if (portList[i].range == addr) {
|
if (portList[i].range == addr) {
|
||||||
dest_id = portList[i].portId;
|
dest_id = portList[i].portId;
|
||||||
found = true;
|
found = true;
|
||||||
DPRINTF(Bus, "Found Addr: %llx on device %d\n", addr, dest_id);
|
DPRINTF(Bus, " found addr 0x%llx on device %d\n", addr, dest_id);
|
||||||
}
|
}
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
|
@ -86,33 +101,37 @@ Bus::findPort(Addr addr, int id)
|
||||||
return interfaces[dest_id];
|
return interfaces[dest_id];
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Function called by the port when the bus is recieving a Atomic
|
/** Function called by the port when the bus is receiving a Atomic
|
||||||
* transaction.*/
|
* transaction.*/
|
||||||
Tick
|
Tick
|
||||||
Bus::recvAtomic(Packet *pkt)
|
Bus::recvAtomic(Packet *pkt)
|
||||||
{
|
{
|
||||||
assert(pkt->dest == Packet::Broadcast);
|
DPRINTF(Bus, "recvAtomic: packet src %d dest %d addr 0x%x cmd %s\n",
|
||||||
return findPort(pkt->addr, pkt->src)->sendAtomic(pkt);
|
pkt->getSrc(), pkt->getDest(), pkt->getAddr(), pkt->cmdString());
|
||||||
|
assert(pkt->getDest() == Packet::Broadcast);
|
||||||
|
return findPort(pkt->getAddr(), pkt->getSrc())->sendAtomic(pkt);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Function called by the port when the bus is recieving a Functional
|
/** Function called by the port when the bus is receiving a Functional
|
||||||
* transaction.*/
|
* transaction.*/
|
||||||
void
|
void
|
||||||
Bus::recvFunctional(Packet *pkt)
|
Bus::recvFunctional(Packet *pkt)
|
||||||
{
|
{
|
||||||
assert(pkt->dest == Packet::Broadcast);
|
DPRINTF(Bus, "recvFunctional: packet src %d dest %d addr 0x%x cmd %s\n",
|
||||||
findPort(pkt->addr, pkt->src)->sendFunctional(pkt);
|
pkt->getSrc(), pkt->getDest(), pkt->getAddr(), pkt->cmdString());
|
||||||
|
assert(pkt->getDest() == Packet::Broadcast);
|
||||||
|
findPort(pkt->getAddr(), pkt->getSrc())->sendFunctional(pkt);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Function called by the port when the bus is recieving a status change.*/
|
/** Function called by the port when the bus is receiving a status change.*/
|
||||||
void
|
void
|
||||||
Bus::recvStatusChange(Port::Status status, int id)
|
Bus::recvStatusChange(Port::Status status, int id)
|
||||||
{
|
{
|
||||||
DPRINTF(Bus, "Bus %d recieved status change from device id %d\n",
|
|
||||||
busId, id);
|
|
||||||
assert(status == Port::RangeChange &&
|
assert(status == Port::RangeChange &&
|
||||||
"The other statuses need to be implemented.");
|
"The other statuses need to be implemented.");
|
||||||
|
|
||||||
|
DPRINTF(BusAddrRanges, "received RangeChange from device id %d\n", id);
|
||||||
|
|
||||||
assert(id < interfaces.size() && id >= 0);
|
assert(id < interfaces.size() && id >= 0);
|
||||||
int x;
|
int x;
|
||||||
Port *port = interfaces[id];
|
Port *port = interfaces[id];
|
||||||
|
@ -138,8 +157,8 @@ Bus::recvStatusChange(Port::Status status, int id)
|
||||||
dm.portId = id;
|
dm.portId = id;
|
||||||
dm.range = *iter;
|
dm.range = *iter;
|
||||||
|
|
||||||
DPRINTF(MMU, "Adding range %llx - %llx for id %d\n", dm.range.start,
|
DPRINTF(BusAddrRanges, "Adding range %llx - %llx for id %d\n",
|
||||||
dm.range.end, id);
|
dm.range.start, dm.range.end, id);
|
||||||
portList.push_back(dm);
|
portList.push_back(dm);
|
||||||
}
|
}
|
||||||
DPRINTF(MMU, "port list has %d entries\n", portList.size());
|
DPRINTF(MMU, "port list has %d entries\n", portList.size());
|
||||||
|
@ -159,13 +178,12 @@ Bus::addressRanges(AddrRangeList &resp, AddrRangeList &snoop, int id)
|
||||||
resp.clear();
|
resp.clear();
|
||||||
snoop.clear();
|
snoop.clear();
|
||||||
|
|
||||||
DPRINTF(Bus, "Bus id %d recieved address range request returning\n",
|
DPRINTF(BusAddrRanges, "received address range request, returning:\n");
|
||||||
busId);
|
|
||||||
for (portIter = portList.begin(); portIter != portList.end(); portIter++) {
|
for (portIter = portList.begin(); portIter != portList.end(); portIter++) {
|
||||||
if (portIter->portId != id) {
|
if (portIter->portId != id) {
|
||||||
resp.push_back(portIter->range);
|
resp.push_back(portIter->range);
|
||||||
DPRINTF(Bus, "-- %#llX : %#llX\n", portIter->range.start,
|
DPRINTF(BusAddrRanges, " -- %#llX : %#llX\n",
|
||||||
portIter->range.end);
|
portIter->range.start, portIter->range.end);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -100,8 +100,8 @@ class Bus : public MemObject
|
||||||
public:
|
public:
|
||||||
|
|
||||||
/** Constructor for the BusPort.*/
|
/** Constructor for the BusPort.*/
|
||||||
BusPort(Bus *_bus, int _id)
|
BusPort(const std::string &_name, Bus *_bus, int _id)
|
||||||
: bus(_bus), id(_id)
|
: Port(_name), bus(_bus), id(_id)
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
@ -109,17 +109,17 @@ class Bus : public MemObject
|
||||||
/** When reciving a timing request from the peer port (at id),
|
/** When reciving a timing request from the peer port (at id),
|
||||||
pass it to the bus. */
|
pass it to the bus. */
|
||||||
virtual bool recvTiming(Packet *pkt)
|
virtual bool recvTiming(Packet *pkt)
|
||||||
{ pkt->src = id; return bus->recvTiming(pkt); }
|
{ pkt->setSrc(id); return bus->recvTiming(pkt); }
|
||||||
|
|
||||||
/** When reciving a Atomic requestfrom the peer port (at id),
|
/** When reciving a Atomic requestfrom the peer port (at id),
|
||||||
pass it to the bus. */
|
pass it to the bus. */
|
||||||
virtual Tick recvAtomic(Packet *pkt)
|
virtual Tick recvAtomic(Packet *pkt)
|
||||||
{ pkt->src = id; return bus->recvAtomic(pkt); }
|
{ pkt->setSrc(id); return bus->recvAtomic(pkt); }
|
||||||
|
|
||||||
/** When reciving a Functional requestfrom the peer port (at id),
|
/** When reciving a Functional requestfrom the peer port (at id),
|
||||||
pass it to the bus. */
|
pass it to the bus. */
|
||||||
virtual void recvFunctional(Packet *pkt)
|
virtual void recvFunctional(Packet *pkt)
|
||||||
{ pkt->src = id; bus->recvFunctional(pkt); }
|
{ pkt->setSrc(id); bus->recvFunctional(pkt); }
|
||||||
|
|
||||||
/** When reciving a status changefrom the peer port (at id),
|
/** When reciving a status changefrom the peer port (at id),
|
||||||
pass it to the bus. */
|
pass it to the bus. */
|
||||||
|
@ -146,13 +146,7 @@ class Bus : public MemObject
|
||||||
public:
|
public:
|
||||||
|
|
||||||
/** A function used to return the port associated with this bus object. */
|
/** A function used to return the port associated with this bus object. */
|
||||||
virtual Port *getPort(const std::string &if_name)
|
virtual Port *getPort(const std::string &if_name);
|
||||||
{
|
|
||||||
// if_name ignored? forced to be empty?
|
|
||||||
int id = interfaces.size();
|
|
||||||
interfaces.push_back(new BusPort(this, id));
|
|
||||||
return interfaces.back();
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual void init();
|
virtual void init();
|
||||||
|
|
||||||
|
|
|
@ -34,11 +34,31 @@
|
||||||
#include "base/misc.hh"
|
#include "base/misc.hh"
|
||||||
#include "mem/packet.hh"
|
#include "mem/packet.hh"
|
||||||
|
|
||||||
|
static const std::string ReadReqString("ReadReq");
|
||||||
|
static const std::string WriteReqString("WriteReq");
|
||||||
|
static const std::string WriteReqNoAckString("WriteReqNoAck");
|
||||||
|
static const std::string ReadRespString("ReadResp");
|
||||||
|
static const std::string WriteRespString("WriteResp");
|
||||||
|
static const std::string OtherCmdString("<other>");
|
||||||
|
|
||||||
|
const std::string &
|
||||||
|
Packet::cmdString() const
|
||||||
|
{
|
||||||
|
switch (cmd) {
|
||||||
|
case ReadReq: return ReadReqString;
|
||||||
|
case WriteReq: return WriteReqString;
|
||||||
|
case WriteReqNoAck: return WriteReqNoAckString;
|
||||||
|
case ReadResp: return ReadRespString;
|
||||||
|
case WriteResp: return WriteRespString;
|
||||||
|
default: return OtherCmdString;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/** delete the data pointed to in the data pointer. Ok to call to matter how
|
/** delete the data pointed to in the data pointer. Ok to call to matter how
|
||||||
* data was allocted. */
|
* data was allocted. */
|
||||||
void
|
void
|
||||||
Packet::deleteData() {
|
Packet::deleteData()
|
||||||
|
{
|
||||||
assert(staticData || dynamicData);
|
assert(staticData || dynamicData);
|
||||||
if (staticData)
|
if (staticData)
|
||||||
return;
|
return;
|
||||||
|
@ -51,22 +71,24 @@ Packet::deleteData() {
|
||||||
|
|
||||||
/** If there isn't data in the packet, allocate some. */
|
/** If there isn't data in the packet, allocate some. */
|
||||||
void
|
void
|
||||||
Packet::allocate() {
|
Packet::allocate()
|
||||||
|
{
|
||||||
if (data)
|
if (data)
|
||||||
return;
|
return;
|
||||||
assert(!staticData);
|
assert(!staticData);
|
||||||
dynamicData = true;
|
dynamicData = true;
|
||||||
arrayData = true;
|
arrayData = true;
|
||||||
data = new uint8_t[size];
|
data = new uint8_t[getSize()];
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Do the packet modify the same addresses. */
|
/** Do the packet modify the same addresses. */
|
||||||
bool
|
bool
|
||||||
Packet::intersect(Packet *p) {
|
Packet::intersect(Packet *p)
|
||||||
Addr s1 = addr;
|
{
|
||||||
Addr e1 = addr + size;
|
Addr s1 = getAddr();
|
||||||
Addr s2 = p->addr;
|
Addr e1 = getAddr() + getSize();
|
||||||
Addr e2 = p->addr + p->size;
|
Addr s2 = p->getAddr();
|
||||||
|
Addr e2 = p->getAddr() + p->getSize();
|
||||||
|
|
||||||
if (s1 >= s2 && s1 < e2)
|
if (s1 >= s2 && s1 < e2)
|
||||||
return true;
|
return true;
|
||||||
|
@ -77,7 +99,8 @@ Packet::intersect(Packet *p) {
|
||||||
|
|
||||||
/** Minimally reset a packet so something like simple cpu can reuse it. */
|
/** Minimally reset a packet so something like simple cpu can reuse it. */
|
||||||
void
|
void
|
||||||
Packet::reset() {
|
Packet::reset()
|
||||||
|
{
|
||||||
result = Unknown;
|
result = Unknown;
|
||||||
if (dynamicData) {
|
if (dynamicData) {
|
||||||
deleteData();
|
deleteData();
|
||||||
|
@ -88,7 +111,8 @@ Packet::reset() {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool
|
||||||
|
fixPacket(Packet *func, Packet *timing)
|
||||||
bool fixPacket(Packet *func, Packet *timing)
|
{
|
||||||
{ panic("Need to implement!"); }
|
panic("Need to implement!");
|
||||||
|
}
|
||||||
|
|
|
@ -43,24 +43,6 @@ struct Packet;
|
||||||
typedef Packet* PacketPtr;
|
typedef Packet* PacketPtr;
|
||||||
typedef uint8_t* PacketDataPtr;
|
typedef uint8_t* PacketDataPtr;
|
||||||
|
|
||||||
/** List of all commands associated with a packet. */
|
|
||||||
enum Command
|
|
||||||
{
|
|
||||||
Read,
|
|
||||||
Write
|
|
||||||
};
|
|
||||||
|
|
||||||
/** The result of a particular pakets request. */
|
|
||||||
enum PacketResult
|
|
||||||
{
|
|
||||||
Success,
|
|
||||||
BadAddress,
|
|
||||||
Unknown
|
|
||||||
};
|
|
||||||
|
|
||||||
class SenderState{};
|
|
||||||
class Coherence{};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A Packet is the structure to handle requests between two levels
|
* A Packet is the structure to handle requests between two levels
|
||||||
* of the memory system. The Request is a global object that trancends
|
* of the memory system. The Request is a global object that trancends
|
||||||
|
@ -74,7 +56,7 @@ class Coherence{};
|
||||||
* Packets are assumed to be returned in the case of a single response. If
|
* Packets are assumed to be returned in the case of a single response. If
|
||||||
* the transaction has no response, then the consumer will delete the packet.
|
* the transaction has no response, then the consumer will delete the packet.
|
||||||
*/
|
*/
|
||||||
struct Packet
|
class Packet
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
/** A pointer to the data being transfered. It can be differnt sizes
|
/** A pointer to the data being transfered. It can be differnt sizes
|
||||||
|
@ -95,57 +77,132 @@ struct Packet
|
||||||
bool arrayData;
|
bool arrayData;
|
||||||
|
|
||||||
|
|
||||||
public:
|
|
||||||
/** The address of the request, could be virtual or physical (depending on
|
/** The address of the request, could be virtual or physical (depending on
|
||||||
cache configurations). */
|
cache configurations). */
|
||||||
Addr addr;
|
Addr addr;
|
||||||
|
|
||||||
/** Flag structure to hold flags for this particular packet */
|
|
||||||
uint64_t flags;
|
|
||||||
|
|
||||||
/** A pointer to the overall request. */
|
|
||||||
RequestPtr req;
|
|
||||||
|
|
||||||
/** A virtual base opaque structure used to hold
|
|
||||||
coherence status messages. */
|
|
||||||
Coherence *coherence; // virtual base opaque,
|
|
||||||
// assert(dynamic_cast<Foo>) etc.
|
|
||||||
|
|
||||||
/** A virtual base opaque structure used to hold the senders state. */
|
|
||||||
void *senderState; // virtual base opaque,
|
|
||||||
// assert(dynamic_cast<Foo>) etc.
|
|
||||||
|
|
||||||
/** Indicates the size of the request. */
|
/** Indicates the size of the request. */
|
||||||
int size;
|
int size;
|
||||||
|
|
||||||
/** A index of the source of the transaction. */
|
/** A index of the source of the transaction. */
|
||||||
short src;
|
short src;
|
||||||
|
|
||||||
static const short Broadcast = -1;
|
|
||||||
|
|
||||||
/** A index to the destination of the transaction. */
|
/** A index to the destination of the transaction. */
|
||||||
short dest;
|
short dest;
|
||||||
|
|
||||||
|
bool addrValid;
|
||||||
|
bool sizeValid;
|
||||||
|
bool srcValid;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
static const short Broadcast = -1;
|
||||||
|
|
||||||
|
/** A pointer to the overall request. */
|
||||||
|
RequestPtr req;
|
||||||
|
|
||||||
|
class CoherenceState {
|
||||||
|
public:
|
||||||
|
virtual ~CoherenceState() {}
|
||||||
|
};
|
||||||
|
|
||||||
|
/** A virtual base opaque structure used to hold
|
||||||
|
coherence status messages. */
|
||||||
|
CoherenceState *coherence; // virtual base opaque,
|
||||||
|
// assert(dynamic_cast<Foo>) etc.
|
||||||
|
|
||||||
|
class SenderState {
|
||||||
|
public:
|
||||||
|
virtual ~SenderState() {}
|
||||||
|
};
|
||||||
|
|
||||||
|
/** A virtual base opaque structure used to hold the senders state. */
|
||||||
|
SenderState *senderState; // virtual base opaque,
|
||||||
|
// assert(dynamic_cast<Foo>) etc.
|
||||||
|
|
||||||
|
private:
|
||||||
|
/** List of command attributes. */
|
||||||
|
enum CommandAttribute
|
||||||
|
{
|
||||||
|
IsRead = 1 << 0,
|
||||||
|
IsWrite = 1 << 1,
|
||||||
|
IsPrefetch = 1 << 2,
|
||||||
|
IsInvalidate = 1 << 3,
|
||||||
|
IsRequest = 1 << 4,
|
||||||
|
IsResponse = 1 << 5,
|
||||||
|
NeedsResponse = 1 << 6,
|
||||||
|
};
|
||||||
|
|
||||||
|
public:
|
||||||
|
/** List of all commands associated with a packet. */
|
||||||
|
enum Command
|
||||||
|
{
|
||||||
|
ReadReq = IsRead | IsRequest | NeedsResponse,
|
||||||
|
WriteReq = IsWrite | IsRequest | NeedsResponse,
|
||||||
|
WriteReqNoAck = IsWrite | IsRequest,
|
||||||
|
ReadResp = IsRead | IsResponse,
|
||||||
|
WriteResp = IsWrite | IsResponse
|
||||||
|
};
|
||||||
|
|
||||||
|
const std::string &cmdString() const;
|
||||||
|
|
||||||
/** The command of the transaction. */
|
/** The command of the transaction. */
|
||||||
Command cmd;
|
Command cmd;
|
||||||
|
|
||||||
|
bool isRead() { return (cmd & IsRead) != 0; }
|
||||||
|
bool isRequest() { return (cmd & IsRequest) != 0; }
|
||||||
|
bool isResponse() { return (cmd & IsResponse) != 0; }
|
||||||
|
bool needsResponse() { return (cmd & NeedsResponse) != 0; }
|
||||||
|
|
||||||
|
void makeTimingResponse() {
|
||||||
|
assert(needsResponse());
|
||||||
|
int icmd = (int)cmd;
|
||||||
|
icmd &= ~(IsRequest | NeedsResponse);
|
||||||
|
icmd |= IsResponse;
|
||||||
|
cmd = (Command)icmd;
|
||||||
|
dest = src;
|
||||||
|
srcValid = false;
|
||||||
|
}
|
||||||
|
|
||||||
/** The time this request was responded to. Used to calculate latencies. */
|
/** The time this request was responded to. Used to calculate latencies. */
|
||||||
Tick time;
|
Tick time;
|
||||||
|
|
||||||
|
/** The result of a particular packets request. */
|
||||||
|
enum Result
|
||||||
|
{
|
||||||
|
Success,
|
||||||
|
BadAddress,
|
||||||
|
Unknown
|
||||||
|
};
|
||||||
|
|
||||||
/** The result of the packet transaction. */
|
/** The result of the packet transaction. */
|
||||||
PacketResult result;
|
Result result;
|
||||||
|
|
||||||
/** Accessor function that returns the source index of the packet. */
|
/** Accessor function that returns the source index of the packet. */
|
||||||
short getSrc() const { return src; }
|
short getSrc() const { assert(srcValid); return src; }
|
||||||
|
void setSrc(short _src) { src = _src; srcValid = true; }
|
||||||
|
|
||||||
/** Accessor function that returns the destination index of
|
/** Accessor function that returns the destination index of
|
||||||
the packet. */
|
the packet. */
|
||||||
short getDest() const { return dest; }
|
short getDest() const { return dest; }
|
||||||
|
void setDest(short _dest) { dest = _dest; }
|
||||||
|
|
||||||
Packet()
|
Addr getAddr() const { assert(addrValid); return addr; }
|
||||||
|
void setAddr(Addr _addr) { addr = _addr; addrValid = true; }
|
||||||
|
|
||||||
|
int getSize() const { assert(sizeValid); return size; }
|
||||||
|
void setSize(int _size) { size = _size; sizeValid = true; }
|
||||||
|
|
||||||
|
|
||||||
|
Packet(Request *_req, Command _cmd, short _dest)
|
||||||
: data(NULL), staticData(false), dynamicData(false), arrayData(false),
|
: data(NULL), staticData(false), dynamicData(false), arrayData(false),
|
||||||
|
addr(_req->paddr), size(_req->size), dest(_dest),
|
||||||
|
addrValid(_req->validPaddr), sizeValid(_req->validSize),
|
||||||
|
srcValid(false),
|
||||||
|
req(_req), coherence(NULL), senderState(NULL), cmd(_cmd),
|
||||||
time(curTick), result(Unknown)
|
time(curTick), result(Unknown)
|
||||||
{}
|
{
|
||||||
|
}
|
||||||
|
|
||||||
~Packet()
|
~Packet()
|
||||||
{ deleteData(); }
|
{ deleteData(); }
|
||||||
|
@ -154,6 +211,11 @@ struct Packet
|
||||||
/** Minimally reset a packet so something like simple cpu can reuse it. */
|
/** Minimally reset a packet so something like simple cpu can reuse it. */
|
||||||
void reset();
|
void reset();
|
||||||
|
|
||||||
|
void reinitFromRequest() {
|
||||||
|
if (req->validPaddr) setAddr(req->paddr);
|
||||||
|
if (req->validSize) setSize(req->size);
|
||||||
|
}
|
||||||
|
|
||||||
/** Set the data pointer to the following value that should not be freed. */
|
/** Set the data pointer to the following value that should not be freed. */
|
||||||
template <typename T>
|
template <typename T>
|
||||||
void dataStatic(T *p);
|
void dataStatic(T *p);
|
||||||
|
|
|
@ -127,7 +127,8 @@ PhysicalMemory::doTimingAccess (Packet *pkt, MemoryPort* memoryPort)
|
||||||
{
|
{
|
||||||
doFunctionalAccess(pkt);
|
doFunctionalAccess(pkt);
|
||||||
|
|
||||||
pkt->dest = pkt->src;
|
// turn packet around to go back to requester
|
||||||
|
pkt->makeTimingResponse();
|
||||||
MemResponseEvent* response = new MemResponseEvent(pkt, memoryPort);
|
MemResponseEvent* response = new MemResponseEvent(pkt, memoryPort);
|
||||||
response->schedule(curTick + lat);
|
response->schedule(curTick + lat);
|
||||||
|
|
||||||
|
@ -145,16 +146,18 @@ PhysicalMemory::doAtomicAccess(Packet *pkt)
|
||||||
void
|
void
|
||||||
PhysicalMemory::doFunctionalAccess(Packet *pkt)
|
PhysicalMemory::doFunctionalAccess(Packet *pkt)
|
||||||
{
|
{
|
||||||
assert(pkt->addr + pkt->size < pmem_size);
|
assert(pkt->getAddr() + pkt->getSize() < pmem_size);
|
||||||
|
|
||||||
switch (pkt->cmd) {
|
switch (pkt->cmd) {
|
||||||
case Read:
|
case Packet::ReadReq:
|
||||||
memcpy(pkt->getPtr<uint8_t>(), pmem_addr + pkt->addr - base_addr,
|
memcpy(pkt->getPtr<uint8_t>(),
|
||||||
pkt->size);
|
pmem_addr + pkt->getAddr() - base_addr,
|
||||||
|
pkt->getSize());
|
||||||
break;
|
break;
|
||||||
case Write:
|
case Packet::WriteReq:
|
||||||
memcpy(pmem_addr + pkt->addr - base_addr, pkt->getPtr<uint8_t>(),
|
memcpy(pmem_addr + pkt->getAddr() - base_addr,
|
||||||
pkt->size);
|
pkt->getPtr<uint8_t>(),
|
||||||
|
pkt->getSize());
|
||||||
// temporary hack: will need to add real LL/SC implementation
|
// temporary hack: will need to add real LL/SC implementation
|
||||||
// for cacheless systems later.
|
// for cacheless systems later.
|
||||||
if (pkt->req->getFlags() & LOCKED) {
|
if (pkt->req->getFlags() & LOCKED) {
|
||||||
|
@ -165,7 +168,7 @@ PhysicalMemory::doFunctionalAccess(Packet *pkt)
|
||||||
panic("unimplemented");
|
panic("unimplemented");
|
||||||
}
|
}
|
||||||
|
|
||||||
pkt->result = Success;
|
pkt->result = Packet::Success;
|
||||||
}
|
}
|
||||||
|
|
||||||
Port *
|
Port *
|
||||||
|
@ -174,11 +177,11 @@ PhysicalMemory::getPort(const std::string &if_name)
|
||||||
if (if_name == "") {
|
if (if_name == "") {
|
||||||
if (port != NULL)
|
if (port != NULL)
|
||||||
panic("PhysicalMemory::getPort: additional port requested to memory!");
|
panic("PhysicalMemory::getPort: additional port requested to memory!");
|
||||||
port = new MemoryPort(this);
|
port = new MemoryPort(name() + "-port", this);
|
||||||
return port;
|
return port;
|
||||||
} else if (if_name == "functional") {
|
} else if (if_name == "functional") {
|
||||||
/* special port for functional writes at startup. */
|
/* special port for functional writes at startup. */
|
||||||
return new MemoryPort(this);
|
return new MemoryPort(name() + "-funcport", this);
|
||||||
} else {
|
} else {
|
||||||
panic("PhysicalMemory::getPort: unknown port %s requested", if_name);
|
panic("PhysicalMemory::getPort: unknown port %s requested", if_name);
|
||||||
}
|
}
|
||||||
|
@ -189,8 +192,9 @@ PhysicalMemory::recvStatusChange(Port::Status status)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
PhysicalMemory::MemoryPort::MemoryPort(PhysicalMemory *_memory)
|
PhysicalMemory::MemoryPort::MemoryPort(const std::string &_name,
|
||||||
: memory(_memory)
|
PhysicalMemory *_memory)
|
||||||
|
: Port(_name), memory(_memory)
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
|
@ -51,7 +51,7 @@ class PhysicalMemory : public MemObject
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
MemoryPort(PhysicalMemory *_memory);
|
MemoryPort(const std::string &_name, PhysicalMemory *_memory);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
|
|
|
@ -31,22 +31,28 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "base/chunk_generator.hh"
|
#include "base/chunk_generator.hh"
|
||||||
|
#include "base/trace.hh"
|
||||||
#include "mem/packet_impl.hh"
|
#include "mem/packet_impl.hh"
|
||||||
#include "mem/port.hh"
|
#include "mem/port.hh"
|
||||||
|
|
||||||
void
|
void
|
||||||
Port::blobHelper(Addr addr, uint8_t *p, int size, Command cmd)
|
Port::setPeer(Port *port)
|
||||||
|
{
|
||||||
|
DPRINTF(Config, "setting peer to %s\n", port->name());
|
||||||
|
peer = port;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
Port::blobHelper(Addr addr, uint8_t *p, int size, Packet::Command cmd)
|
||||||
{
|
{
|
||||||
Request req(false);
|
Request req(false);
|
||||||
Packet pkt;
|
Packet pkt(&req, cmd, Packet::Broadcast);
|
||||||
pkt.req = &req;
|
|
||||||
pkt.cmd = cmd;
|
|
||||||
pkt.dest = Packet::Broadcast;
|
|
||||||
|
|
||||||
for (ChunkGenerator gen(addr, size, peerBlockSize());
|
for (ChunkGenerator gen(addr, size, peerBlockSize());
|
||||||
!gen.done(); gen.next()) {
|
!gen.done(); gen.next()) {
|
||||||
req.setPaddr(pkt.addr = gen.addr());
|
req.setPaddr(gen.addr());
|
||||||
req.setSize(pkt.size = gen.size());
|
req.setSize(gen.size());
|
||||||
|
pkt.reinitFromRequest();
|
||||||
pkt.dataStatic(p);
|
pkt.dataStatic(p);
|
||||||
sendFunctional(&pkt);
|
sendFunctional(&pkt);
|
||||||
p += gen.size();
|
p += gen.size();
|
||||||
|
@ -56,13 +62,13 @@ Port::blobHelper(Addr addr, uint8_t *p, int size, Command cmd)
|
||||||
void
|
void
|
||||||
Port::writeBlob(Addr addr, uint8_t *p, int size)
|
Port::writeBlob(Addr addr, uint8_t *p, int size)
|
||||||
{
|
{
|
||||||
blobHelper(addr, p, size, Write);
|
blobHelper(addr, p, size, Packet::WriteReq);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
Port::readBlob(Addr addr, uint8_t *p, int size)
|
Port::readBlob(Addr addr, uint8_t *p, int size)
|
||||||
{
|
{
|
||||||
blobHelper(addr, p, size, Read);
|
blobHelper(addr, p, size, Packet::ReadReq);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -72,7 +78,7 @@ Port::memsetBlob(Addr addr, uint8_t val, int size)
|
||||||
uint8_t *buf = new uint8_t[size];
|
uint8_t *buf = new uint8_t[size];
|
||||||
|
|
||||||
memset(buf, val, size);
|
memset(buf, val, size);
|
||||||
blobHelper(addr, buf, size, Write);
|
blobHelper(addr, buf, size, Packet::WriteReq);
|
||||||
|
|
||||||
delete [] buf;
|
delete [] buf;
|
||||||
}
|
}
|
||||||
|
|
|
@ -69,9 +69,28 @@ typedef std::list<Range<Addr> >::iterator AddrRangeIter;
|
||||||
*/
|
*/
|
||||||
class Port
|
class Port
|
||||||
{
|
{
|
||||||
|
private:
|
||||||
|
|
||||||
|
/** Descriptive name (for DPRINTF output) */
|
||||||
|
const std::string portName;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor.
|
||||||
|
*
|
||||||
|
* @param _name Port name for DPRINTF output. Should include name
|
||||||
|
* of memory system object to which the port belongs.
|
||||||
|
*/
|
||||||
|
Port(const std::string &_name)
|
||||||
|
: portName(_name)
|
||||||
|
{ }
|
||||||
|
|
||||||
|
/** Return port name (for DPRINTF). */
|
||||||
|
const std::string &name() const { return portName; }
|
||||||
|
|
||||||
virtual ~Port() {};
|
virtual ~Port() {};
|
||||||
|
|
||||||
// mey be better to use subclasses & RTTI?
|
// mey be better to use subclasses & RTTI?
|
||||||
/** Holds the ports status. Keeps track if it is blocked, or has
|
/** Holds the ports status. Keeps track if it is blocked, or has
|
||||||
calculated a range change. */
|
calculated a range change. */
|
||||||
|
@ -93,7 +112,7 @@ class Port
|
||||||
/** Function to set the pointer for the peer port.
|
/** Function to set the pointer for the peer port.
|
||||||
@todo should be called by the configuration stuff (python).
|
@todo should be called by the configuration stuff (python).
|
||||||
*/
|
*/
|
||||||
void setPeer(Port *port) { peer = port; }
|
void setPeer(Port *port);
|
||||||
|
|
||||||
/** Function to set the pointer for the peer port.
|
/** Function to set the pointer for the peer port.
|
||||||
@todo should be called by the configuration stuff (python).
|
@todo should be called by the configuration stuff (python).
|
||||||
|
@ -213,7 +232,7 @@ class Port
|
||||||
|
|
||||||
/** Internal helper function for read/writeBlob().
|
/** Internal helper function for read/writeBlob().
|
||||||
*/
|
*/
|
||||||
void blobHelper(Addr addr, uint8_t *p, int size, Command cmd);
|
void blobHelper(Addr addr, uint8_t *p, int size, Packet::Command cmd);
|
||||||
};
|
};
|
||||||
|
|
||||||
/** A simple functional port that is only meant for one way communication to
|
/** A simple functional port that is only meant for one way communication to
|
||||||
|
@ -224,6 +243,10 @@ class Port
|
||||||
class FunctionalPort : public Port
|
class FunctionalPort : public Port
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
FunctionalPort(const std::string &_name)
|
||||||
|
: Port(_name)
|
||||||
|
{}
|
||||||
|
|
||||||
virtual bool recvTiming(Packet *pkt) { panic("FuncPort is UniDir"); }
|
virtual bool recvTiming(Packet *pkt) { panic("FuncPort is UniDir"); }
|
||||||
virtual Tick recvAtomic(Packet *pkt) { panic("FuncPort is UniDir"); }
|
virtual Tick recvAtomic(Packet *pkt) { panic("FuncPort is UniDir"); }
|
||||||
virtual void recvFunctional(Packet *pkt) { panic("FuncPort is UniDir"); }
|
virtual void recvFunctional(Packet *pkt) { panic("FuncPort is UniDir"); }
|
||||||
|
|
|
@ -195,6 +195,7 @@ class Request
|
||||||
/** Accesor function for pc.*/
|
/** Accesor function for pc.*/
|
||||||
void setPC(Addr _pc);
|
void setPC(Addr _pc);
|
||||||
|
|
||||||
|
friend class Packet;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // __MEM_REQUEST_HH__
|
#endif // __MEM_REQUEST_HH__
|
||||||
|
|
|
@ -34,8 +34,9 @@
|
||||||
|
|
||||||
using namespace TheISA;
|
using namespace TheISA;
|
||||||
|
|
||||||
TranslatingPort::TranslatingPort(PageTable *p_table, bool alloc)
|
TranslatingPort::TranslatingPort(const std::string &_name,
|
||||||
: pTable(p_table), allocating(alloc)
|
PageTable *p_table, bool alloc)
|
||||||
|
: FunctionalPort(_name), pTable(p_table), allocating(alloc)
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
TranslatingPort::~TranslatingPort()
|
TranslatingPort::~TranslatingPort()
|
||||||
|
|
|
@ -39,14 +39,11 @@ class TranslatingPort : public FunctionalPort
|
||||||
PageTable *pTable;
|
PageTable *pTable;
|
||||||
bool allocating;
|
bool allocating;
|
||||||
|
|
||||||
TranslatingPort(const TranslatingPort &specmem);
|
|
||||||
const TranslatingPort &operator=(const TranslatingPort &specmem);
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
TranslatingPort(PageTable *p_table, bool alloc = false);
|
TranslatingPort(const std::string &_name,
|
||||||
|
PageTable *p_table, bool alloc = false);
|
||||||
virtual ~TranslatingPort();
|
virtual ~TranslatingPort();
|
||||||
|
|
||||||
public:
|
|
||||||
bool tryReadBlob(Addr addr, uint8_t *p, int size);
|
bool tryReadBlob(Addr addr, uint8_t *p, int size);
|
||||||
bool tryWriteBlob(Addr addr, uint8_t *p, int size);
|
bool tryWriteBlob(Addr addr, uint8_t *p, int size);
|
||||||
bool tryMemsetBlob(Addr addr, uint8_t val, int size);
|
bool tryMemsetBlob(Addr addr, uint8_t val, int size);
|
||||||
|
@ -56,9 +53,9 @@ class TranslatingPort : public FunctionalPort
|
||||||
virtual void readBlob(Addr addr, uint8_t *p, int size);
|
virtual void readBlob(Addr addr, uint8_t *p, int size);
|
||||||
virtual void writeBlob(Addr addr, uint8_t *p, int size);
|
virtual void writeBlob(Addr addr, uint8_t *p, int size);
|
||||||
virtual void memsetBlob(Addr addr, uint8_t val, int size);
|
virtual void memsetBlob(Addr addr, uint8_t val, int size);
|
||||||
|
|
||||||
void writeString(Addr addr, const char *str);
|
void writeString(Addr addr, const char *str);
|
||||||
void readString(std::string &str, Addr addr);
|
void readString(std::string &str, Addr addr);
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -53,8 +53,8 @@ class VirtualPort : public FunctionalPort
|
||||||
ExecContext *xc;
|
ExecContext *xc;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
VirtualPort(ExecContext *_xc = NULL)
|
VirtualPort(const std::string &_name, ExecContext *_xc = NULL)
|
||||||
: xc(_xc)
|
: FunctionalPort(_name), xc(_xc)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
/** Return true if we have an exec context. This is used to prevent someone
|
/** Return true if we have an exec context. This is used to prevent someone
|
||||||
|
|
|
@ -154,7 +154,7 @@ Process::startup()
|
||||||
|
|
||||||
Port *mem_port;
|
Port *mem_port;
|
||||||
mem_port = system->physmem->getPort("functional");
|
mem_port = system->physmem->getPort("functional");
|
||||||
initVirtMem = new TranslatingPort(pTable, true);
|
initVirtMem = new TranslatingPort("process init port", pTable, true);
|
||||||
mem_port->setPeer(initVirtMem);
|
mem_port->setPeer(initVirtMem);
|
||||||
initVirtMem->setPeer(mem_port);
|
initVirtMem->setPeer(mem_port);
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,6 +25,8 @@ System::System(Params *p)
|
||||||
: SimObject(p->name), physmem(p->physmem), numcpus(0),
|
: SimObject(p->name), physmem(p->physmem), numcpus(0),
|
||||||
#if FULL_SYSTEM
|
#if FULL_SYSTEM
|
||||||
init_param(p->init_param),
|
init_param(p->init_param),
|
||||||
|
functionalPort(p->name + "-fport"),
|
||||||
|
virtPort(p->name + "-vport"),
|
||||||
#else
|
#else
|
||||||
page_ptr(0),
|
page_ptr(0),
|
||||||
#endif
|
#endif
|
||||||
|
|
Loading…
Reference in a new issue