diff options
41 files changed, 868 insertions, 775 deletions
diff --git a/SConstruct b/SConstruct index f29d10cef..3fac9eb2e 100644 --- a/SConstruct +++ b/SConstruct @@ -105,9 +105,10 @@ def rfind(l, elt, offs = -1): # recognize that ALPHA_SE specifies the configuration because it # follow 'build' in the bulid path. -# Generate a list of the unique configs that the collected targets -# reference. +# Generate a list of the unique build roots and configs that the +# collected targets reference. build_paths = [] +build_root = None for t in abs_targets: path_dirs = t.split('/') try: @@ -115,9 +116,17 @@ for t in abs_targets: except: print "Error: no non-leaf 'build' dir found on target path", t Exit(1) - config_dir = os.path.join('/',*path_dirs[:build_top+2]) - if config_dir not in build_paths: - build_paths.append(config_dir) + this_build_root = os.path.join('/',*path_dirs[:build_top+1]) + if not build_root: + 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 env.Append(LIBS=['z']) -# Platform-specific configuration -conf = Configure(env) +# Platform-specific configuration. Note again that we assume that all +# 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) have_fenv = conf.CheckHeader('fenv.h', '<>') @@ -195,7 +207,7 @@ env['ALL_ISA_LIST'] = ['alpha', 'sparc', 'mips'] # Define the universe of supported CPU models env['ALL_CPU_LIST'] = ['AtomicSimpleCPU', 'TimingSimpleCPU', - 'FastCPU', 'FullCPU', 'AlphaFullCPU'] + 'FullCPU', 'AlphaFullCPU'] # Sticky options get saved in the options file so they persist from # 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 # a saved option file. If this causes trouble then upgrade to # 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', 'Model Alpha TurboLaser platform (vs. Tsunami)', 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) -# 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. @@ -292,6 +300,17 @@ config_builder = Builder(emitter = config_emitter, action = config_action) 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. @@ -301,17 +320,12 @@ env.Append(BUILDERS = { 'ConfigFile' : config_builder }) # rename base env base_env = env -help_text = ''' -Usage: scons [scons options] [build options] [target(s)] - -''' - for build_path in build_paths: print "Building in", build_path # build_dir is the tail component of build path, and is used to # determine the build parameters (e.g., 'ALPHA_SE') (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() # Set env options according to the build directory config. diff --git a/src/SConscript b/src/SConscript index a2d5de279..558c447e9 100644 --- a/src/SConscript +++ b/src/SConscript @@ -326,10 +326,6 @@ env.Command(Split('base/traceflags.hh base/traceflags.cc'), 'base/traceflags.py', '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) # 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 # files. env.Append(CPPPATH='.') -env.Append(CPPPATH='./libelf') # Debug binary debugEnv = env.Copy(OBJSUFFIX='.do') diff --git a/src/arch/SConscript b/src/arch/SConscript index 06b8e8dde..9c193207f 100644 --- a/src/arch/SConscript +++ b/src/arch/SConscript @@ -132,7 +132,7 @@ def isa_desc_emitter(target, source, env): return (isa_desc_gen_files, [isa_parser, cpu_models_file] + source) # Pieces are in place, so create the builder. -isa_desc_builder = Builder(action='python $SOURCES $TARGET.dir $CPU_MODELS', +isa_desc_builder = Builder(action='python2.4 $SOURCES $TARGET.dir $CPU_MODELS', emitter = isa_desc_emitter) env.Append(BUILDERS = { 'ISADesc' : isa_desc_builder }) diff --git a/src/arch/sparc/isa/formats/nop.isa b/src/arch/sparc/isa/formats/nop.isa index 7fd1a3b21..37ef2e8d0 100644 --- a/src/arch/sparc/isa/formats/nop.isa +++ b/src/arch/sparc/isa/formats/nop.isa @@ -32,6 +32,16 @@ // 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 {{ /** * Nop class. @@ -46,14 +56,11 @@ output header {{ } // All Nop instructions do the same thing, so this can be - // defined here. Nops can be defined directly, so there needs - // to be a default implementation - Fault execute(%(CPU_exec_context)s *xc, - Trace::InstRecord *traceData) const - { - //Nothing to see here, move along - return NoFault; - } + // defined here. Nops can be defined directly, so there + // needs to be a default implementation. Interpolate via + // template so i gets expanded to a set of + // cpu-model-specific functions. + %(NopExec)s std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const; diff --git a/src/base/loader/elf_object.cc b/src/base/loader/elf_object.cc index 165501e1c..79601e9d1 100644 --- a/src/base/loader/elf_object.cc +++ b/src/base/loader/elf_object.cc @@ -30,16 +30,10 @@ // Because of the -Wundef flag we have to do this #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_SYMBOL_VERSIONS 0 -#include "libelf/libelf.h" -#include "libelf/gelf.h" +#include "gelf.h" #include "base/loader/elf_object.hh" #include "base/misc.hh" diff --git a/src/base/traceflags.py b/src/base/traceflags.py index 7dbaac60e..3b7dd0f81 100644 --- a/src/base/traceflags.py +++ b/src/base/traceflags.py @@ -45,105 +45,107 @@ ccfilename = sys.argv[1] + '.cc' # To define a new flag, simply add it to this list. # baseFlags = [ - 'TCPIP', + 'AlphaConsole', + 'BADADDR', + 'BPredRAS', 'Bus', - 'ScsiDisk', - 'ScsiCtrl', - 'ScsiNone', - 'DMA', - 'DMAReadVerbose', - 'DMAWriteVerbose', - 'TLB', - 'SimpleDisk', - 'SimpleDiskData', + 'BusAddrRanges', + 'BusBridge', + 'Cache', + 'Chains', 'Clock', - 'Regs', - 'MC146818', - 'IPI', - 'Timer', - 'Mbox', - 'PCIA', - 'PCIDEV', - 'PciConfigAll', - 'ISP', - 'BADADDR', + 'Commit', + 'CommitRate', + 'Config', 'Console', 'ConsolePoll', 'ConsoleVerbose', - 'AlphaConsole', - 'Flow', - 'Interrupt', - 'Fault', + 'Context', 'Cycle', - 'Loader', - 'MMU', + 'DMA', + 'DMAReadVerbose', + 'DMAWriteVerbose', + 'DebugPrintf', + 'Decode', + 'DiskImage', + 'DiskImageRead', + 'DiskImageWrite', + 'DynInst', 'Ethernet', - 'EthernetPIO', + 'EthernetCksum', 'EthernetDMA', 'EthernetData', 'EthernetDesc', 'EthernetIntr', + 'EthernetPIO', 'EthernetSM', - 'EthernetCksum', - 'GDBMisc', + 'Event', + 'Fault', + 'Fetch', + 'Flow', + 'FreeList', + 'FullCPU', 'GDBAcc', + 'GDBExtra', + 'GDBMisc', 'GDBRead', - 'GDBWrite', - 'GDBSend', 'GDBRecv', - 'GDBExtra', - 'VtoPhys', - 'Printf', - 'DebugPrintf', - 'Serialize', - 'Event', - 'PCEvent', - 'Syscall', - 'SyscallVerbose', - 'DiskImage', - 'DiskImageRead', - 'DiskImageWrite', - 'InstExec', - 'BPredRAS', - 'Cache', + 'GDBSend', + 'GDBWrite', + 'HWPrefetch', + 'IEW', 'IIC', 'IICMore', - 'MSHR', - 'Chains', - 'Pipeline', - 'Stats', - 'StatEvents', - 'Context', - 'Config', - 'Sampler', - 'WriteBarrier', + 'IPI', + 'IQ', + 'ISP', 'IdeCtrl', 'IdeDisk', - 'Tsunami', - 'Uart', - 'Split', - 'SQL', - 'Thread', - 'Fetch', - 'Decode', - 'Rename', - 'IEW', - 'Commit', - 'IQ', - 'ROB', - 'FreeList', - 'RenameMap', + 'InstExec', + 'Interrupt', 'LDSTQ', - 'StoreSet', + 'Loader', + 'MC146818', + 'MMU', + 'MSHR', + 'Mbox', 'MemDepUnit', - 'DynInst', - 'FullCPU', - 'CommitRate', 'OoOCPU', - 'HWPrefetch', - 'Stack', + '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', + 'Uart', + 'VtoPhys', + 'WriteBarrier', ] # diff --git a/src/cpu/cpu_exec_context.cc b/src/cpu/cpu_exec_context.cc index ec1e94561..b8aa9a67e 100644 --- a/src/cpu/cpu_exec_context.cc +++ b/src/cpu/cpu_exec_context.cc @@ -80,12 +80,14 @@ CPUExecContext::CPUExecContext(BaseCPU *_cpu, int _thread_num, System *_sys, profilePC = 3; 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->setPeer(physPort); 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->setPeer(virtPort); 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. */ 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->setPeer(port); port->setPeer(mem_port); @@ -300,7 +304,7 @@ CPUExecContext::getVirtPort(ExecContext *xc) VirtualPort *vp; Port *mem_port; - vp = new VirtualPort(xc); + vp = new VirtualPort("xc-vport", xc); mem_port = system->physmem->getPort("functional"); mem_port->setPeer(vp); vp->setPeer(mem_port); diff --git a/src/cpu/cpu_models.py b/src/cpu/cpu_models.py index 30cbabde1..8d0a15f61 100644 --- a/src/cpu/cpu_models.py +++ b/src/cpu/cpu_models.py @@ -62,9 +62,6 @@ CpuModel('AtomicSimpleCPU', 'atomic_simple_cpu_exec.cc', CpuModel('TimingSimpleCPU', 'timing_simple_cpu_exec.cc', '#include "cpu/simple/timing.hh"', { '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', '#include "encumbered/cpu/full/dyn_inst.hh"', { 'CPU_exec_context': 'DynInst' }) diff --git a/src/cpu/simple/atomic.cc b/src/cpu/simple/atomic.cc index e9422b9c0..3cad6e43f 100644 --- a/src/cpu/simple/atomic.cc +++ b/src/cpu/simple/atomic.cc @@ -117,7 +117,7 @@ AtomicSimpleCPU::CpuPort::recvRetry() AtomicSimpleCPU::AtomicSimpleCPU(Params *p) : BaseSimpleCPU(p), tickEvent(this), width(p->width), simulate_stalls(p->simulate_stalls), - icachePort(this), dcachePort(this) + icachePort(name() + "-iport", this), dcachePort(name() + "-iport", this) { _status = Idle; @@ -126,31 +126,23 @@ AtomicSimpleCPU::AtomicSimpleCPU(Params *p) // @todo fix me and get the real cpu iD!!! ifetch_req->setCpuNum(0); ifetch_req->setSize(sizeof(MachInst)); - ifetch_pkt = new Packet; - ifetch_pkt->cmd = Read; + ifetch_pkt = new Packet(ifetch_req, Packet::ReadReq, Packet::Broadcast); 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); // @todo fix me and get the real cpu iD!!! data_read_req->setCpuNum(0); data_read_req->setAsid(0); - data_read_pkt = new Packet; - data_read_pkt->cmd = Read; + data_read_pkt = new Packet(data_read_req, Packet::ReadReq, + Packet::Broadcast); data_read_pkt->dataStatic(&dataReg); - data_read_pkt->req = data_read_req; - data_read_pkt->dest = Packet::Broadcast; data_write_req = new Request(true); // @todo fix me and get the real cpu iD!!! data_write_req->setCpuNum(0); data_write_req->setAsid(0); - data_write_pkt = new Packet; - data_write_pkt->cmd = Write; - data_write_pkt->req = data_write_req; - data_write_pkt->dest = Packet::Broadcast; + data_write_pkt = new Packet(data_write_req, Packet::WriteReq, + Packet::Broadcast); } @@ -260,13 +252,12 @@ AtomicSimpleCPU::read(Addr addr, T &data, unsigned flags) // Now do the access. if (fault == NoFault) { data_read_pkt->reset(); - data_read_pkt->addr = data_read_req->getPaddr(); - data_read_pkt->size = sizeof(T); + data_read_pkt->reinitFromRequest(); dcache_complete = dcachePort.sendAtomic(data_read_pkt); dcache_access = true; - assert(data_read_pkt->result == Success); + assert(data_read_pkt->result == Packet::Success); 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 = htog(data); data_write_pkt->dataStatic(&data); - data_write_pkt->addr = data_write_req->getPaddr(); - data_write_pkt->size = sizeof(T); + data_write_pkt->reinitFromRequest(); dcache_complete = dcachePort.sendAtomic(data_write_pkt); dcache_access = true; - assert(data_write_pkt->result == Success); + assert(data_write_pkt->result == Packet::Success); if (res && data_write_req->getFlags() & LOCKED) { *res = data_write_req->getScResult(); @@ -435,10 +425,6 @@ AtomicSimpleCPU::tick() fault = curStaticInst->execute(this, traceData); postExecute(); - if (traceData) { - traceData->finalize(); - } - if (simulate_stalls) { // This calculation assumes that the icache and dcache // access latencies are always a multiple of the CPU's diff --git a/src/cpu/simple/atomic.hh b/src/cpu/simple/atomic.hh index d0ba085f0..ab3a3e8ef 100644 --- a/src/cpu/simple/atomic.hh +++ b/src/cpu/simple/atomic.hh @@ -84,8 +84,8 @@ class AtomicSimpleCPU : public BaseSimpleCPU public: - CpuPort(AtomicSimpleCPU *_cpu) - : cpu(_cpu) + CpuPort(const std::string &_name, AtomicSimpleCPU *_cpu) + : Port(_name), cpu(_cpu) { } protected: diff --git a/src/cpu/simple/base.cc b/src/cpu/simple/base.cc index 30c002ed5..18f170449 100644 --- a/src/cpu/simple/base.cc +++ b/src/cpu/simple/base.cc @@ -372,7 +372,7 @@ BaseSimpleCPU::setupFetchPacket(Packet *ifetch_pkt) Fault fault = cpuXC->translateInstReq(ifetch_req); if (fault == NoFault) { - ifetch_pkt->addr = ifetch_req->getPaddr(); + ifetch_pkt->reinitFromRequest(); } return fault; @@ -442,6 +442,10 @@ BaseSimpleCPU::postExecute() } traceFunctions(cpuXC->readPC()); + + if (traceData) { + traceData->finalize(); + } } diff --git a/src/cpu/simple/timing.cc b/src/cpu/simple/timing.cc index 70b88c4b1..7cdcdafa1 100644 --- a/src/cpu/simple/timing.cc +++ b/src/cpu/simple/timing.cc @@ -158,10 +158,11 @@ TimingSimpleCPU::suspendContext(int thread_num) assert(thread_num == 0); assert(cpuXC); - panic("TimingSimpleCPU::suspendContext not implemented"); - assert(_status == Running); + // just change status to Idle... if status != Running, + // completeInst() will not initiate fetch of next instruction. + notIdleFraction--; _status = Idle; } @@ -187,13 +188,9 @@ TimingSimpleCPU::read(Addr addr, T &data, unsigned flags) // Now do the access. if (fault == NoFault) { - Packet *data_read_pkt = new Packet; - data_read_pkt->cmd = Read; - data_read_pkt->req = data_read_req; + Packet *data_read_pkt = + new Packet(data_read_req, Packet::ReadReq, Packet::Broadcast); 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)) { _status = DcacheRetry; @@ -268,14 +265,10 @@ TimingSimpleCPU::write(T data, Addr addr, unsigned flags, uint64_t *res) Fault fault = cpuXC->translateDataWriteReq(data_write_req); // Now do the access. if (fault == NoFault) { - Packet *data_write_pkt = new Packet; - data_write_pkt->cmd = Write; - data_write_pkt->req = data_write_req; + Packet *data_write_pkt = + new Packet(data_write_req, Packet::WriteReq, Packet::Broadcast); data_write_pkt->allocate(); - data_write_pkt->size = sizeof(T); 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)) { _status = DcacheRetry; @@ -350,12 +343,8 @@ TimingSimpleCPU::fetch() Request *ifetch_req = new Request(true); ifetch_req->setSize(sizeof(MachInst)); - ifetch_pkt = new Packet; - ifetch_pkt->cmd = Read; + ifetch_pkt = new Packet(ifetch_req, Packet::ReadReq, Packet::Broadcast); ifetch_pkt->dataStatic(&inst); - ifetch_pkt->req = ifetch_req; - ifetch_pkt->size = sizeof(MachInst); - ifetch_pkt->dest = Packet::Broadcast; Fault fault = setupFetchPacket(ifetch_pkt); if (fault == NoFault) { @@ -369,20 +358,15 @@ TimingSimpleCPU::fetch() ifetch_pkt = NULL; } } else { - panic("TimingSimpleCPU fetch fault handling not implemented"); + // fetch fault: advance directly to next instruction (fault handler) + advanceInst(fault); } } void -TimingSimpleCPU::completeInst(Fault fault) +TimingSimpleCPU::advanceInst(Fault fault) { - postExecute(); - - if (traceData) { - traceData->finalize(); - } - advancePC(fault); if (_status == Running) { @@ -395,23 +379,35 @@ TimingSimpleCPU::completeInst(Fault fault) void -TimingSimpleCPU::completeIfetch() +TimingSimpleCPU::completeIfetch(Packet *pkt) { // received a response from the icache: execute the received // instruction + assert(pkt->result == Packet::Success); assert(_status == IcacheWaitResponse); _status = Running; + + delete pkt->req; + delete pkt; + preExecute(); - if (curStaticInst->isMemRef()) { + if (curStaticInst->isMemRef() && !curStaticInst->isDataPrefetch()) { // load or store: just send to dcache Fault fault = curStaticInst->initiateAcc(this, traceData); - assert(fault == NoFault); - assert(_status == DcacheWaitResponse); - // instruction will complete in dcache response callback + if (fault == NoFault) { + // successfully initiated access: instruction will + // complete in dcache response callback + assert(_status == DcacheWaitResponse); + } else { + // fault: complete now to invoke fault handler + postExecute(); + advanceInst(fault); + } } else { // non-memory instruction: execute completely now Fault fault = curStaticInst->execute(this, traceData); - completeInst(fault); + postExecute(); + advanceInst(fault); } } @@ -419,7 +415,7 @@ TimingSimpleCPU::completeIfetch() bool TimingSimpleCPU::IcachePort::recvTiming(Packet *pkt) { - cpu->completeIfetch(); + cpu->completeIfetch(pkt); return true; } @@ -441,13 +437,17 @@ TimingSimpleCPU::completeDataAccess(Packet *pkt) { // received a response from the dcache: complete the load or store // instruction - assert(pkt->result == Success); + assert(pkt->result == Packet::Success); assert(_status == DcacheWaitResponse); _status = Running; Fault fault = curStaticInst->completeAcc(pkt, this, traceData); - completeInst(fault); + delete pkt->req; + delete pkt; + + postExecute(); + advanceInst(fault); } diff --git a/src/cpu/simple/timing.hh b/src/cpu/simple/timing.hh index 83be025d9..b46631d5a 100644 --- a/src/cpu/simple/timing.hh +++ b/src/cpu/simple/timing.hh @@ -71,8 +71,8 @@ class TimingSimpleCPU : public BaseSimpleCPU public: - CpuPort(TimingSimpleCPU *_cpu) - : cpu(_cpu) + CpuPort(const std::string &_name, TimingSimpleCPU *_cpu) + : Port(_name), cpu(_cpu) { } protected: @@ -93,7 +93,7 @@ class TimingSimpleCPU : public BaseSimpleCPU public: IcachePort(TimingSimpleCPU *_cpu) - : CpuPort(_cpu) + : CpuPort(_cpu->name() + "-iport", _cpu) { } protected: @@ -108,7 +108,7 @@ class TimingSimpleCPU : public BaseSimpleCPU public: DcachePort(TimingSimpleCPU *_cpu) - : CpuPort(_cpu) + : CpuPort(_cpu->name() + "-dport", _cpu) { } protected: @@ -142,9 +142,9 @@ class TimingSimpleCPU : public BaseSimpleCPU Fault write(T data, Addr addr, unsigned flags, uint64_t *res); void fetch(); - void completeInst(Fault fault); - void completeIfetch(); + void completeIfetch(Packet *); void completeDataAccess(Packet *); + void advanceInst(Fault fault); }; #endif // __CPU_SIMPLE_TIMING_HH__ diff --git a/src/dev/alpha_console.cc b/src/dev/alpha_console.cc index f24c09844..0b4bb048c 100644 --- a/src/dev/alpha_console.cc +++ b/src/dev/alpha_console.cc @@ -95,15 +95,15 @@ AlphaConsole::read(Packet *pkt) * machine dependent address swizzle is required? */ - assert(pkt->result == Unknown); - assert(pkt->addr >= pioAddr && pkt->addr < pioAddr + pioSize); + assert(pkt->result == Packet::Unknown); + assert(pkt->getAddr() >= pioAddr && pkt->getAddr() < pioAddr + pioSize); pkt->time += pioDelay; - Addr daddr = pkt->addr - pioAddr; + Addr daddr = pkt->getAddr() - pioAddr; pkt->allocate(); - switch (pkt->size) + switch (pkt->getSize()) { case sizeof(uint32_t): switch (daddr) @@ -124,7 +124,7 @@ AlphaConsole::read(Packet *pkt) /* Old console code read in everyting as a 32bit int * we now break that for better error checking. */ - pkt->result = BadAddress; + pkt->result = Packet::BadAddress; } DPRINTF(AlphaConsole, "read: offset=%#x val=%#x\n", daddr, pkt->get<uint32_t>()); @@ -181,9 +181,10 @@ AlphaConsole::read(Packet *pkt) pkt->get<uint64_t>()); break; 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; } @@ -192,12 +193,12 @@ AlphaConsole::write(Packet *pkt) { pkt->time += pioDelay; - assert(pkt->result == Unknown); - assert(pkt->addr >= pioAddr && pkt->addr < pioAddr + pioSize); - Addr daddr = pkt->addr - pioAddr; + assert(pkt->result == Packet::Unknown); + assert(pkt->getAddr() >= pioAddr && pkt->getAddr() < pioAddr + pioSize); + Addr daddr = pkt->getAddr() - pioAddr; uint64_t val = pkt->get<uint64_t>(); - assert(pkt->size == sizeof(uint64_t)); + assert(pkt->getSize() == sizeof(uint64_t)); switch (daddr) { case offsetof(AlphaAccess, diskUnit): @@ -240,7 +241,7 @@ AlphaConsole::write(Packet *pkt) panic("Unknown 64bit access, %#x\n", daddr); } - pkt->result = Success; + pkt->result = Packet::Success; return pioDelay; } diff --git a/src/dev/ide_ctrl.cc b/src/dev/ide_ctrl.cc index cedd5c53e..eb03d5db8 100644 --- a/src/dev/ide_ctrl.cc +++ b/src/dev/ide_ctrl.cc @@ -432,19 +432,19 @@ IdeController::read(Packet *pkt) pkt->time += pioDelay; pkt->allocate(); - if (pkt->size != 1 && pkt->size != 2 && pkt->size !=4) - panic("Bad IDE read size: %d\n", pkt->size); + if (pkt->getSize() != 1 && pkt->getSize() != 2 && pkt->getSize() !=4) + 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) { - pkt->result = Success; + pkt->result = Packet::Success; return pioDelay; } switch (reg_type) { case BMI_BLOCK: - switch (pkt->size) { + switch (pkt->getSize()) { case sizeof(uint8_t): pkt->set(bmi_regs.data[offset]); break; @@ -455,7 +455,7 @@ IdeController::read(Packet *pkt) pkt->set(*(uint32_t*)&bmi_regs.data[offset]); break; 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; @@ -470,7 +470,7 @@ IdeController::read(Packet *pkt) switch (offset) { case DATA_OFFSET: - switch (pkt->size) { + switch (pkt->getSize()) { case sizeof(uint16_t): disks[disk]->read(offset, reg_type, pkt->getPtr<uint8_t>()); break; @@ -482,30 +482,30 @@ IdeController::read(Packet *pkt) break; 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; default: - if (pkt->size == sizeof(uint8_t)) { + if (pkt->getSize() == sizeof(uint8_t)) { disks[disk]->read(offset, reg_type, pkt->getPtr<uint8_t>()); } 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; default: 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", - offset, pkt->size, (uint32_t)pkt->get<uint8_t>()); - else if (pkt->size == 2) + offset, pkt->getSize(), (uint32_t)pkt->get<uint8_t>()); + else if (pkt->getSize() == 2) 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 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; } @@ -520,10 +520,10 @@ IdeController::write(Packet *pkt) pkt->time += pioDelay; - parseAddr(pkt->addr, offset, channel, reg_type); + parseAddr(pkt->getAddr(), offset, channel, reg_type); if (!io_enabled) { - pkt->result = Success; + pkt->result = Packet::Success; DPRINTF(IdeCtrl, "io not enabled\n"); return pioDelay; } @@ -531,7 +531,7 @@ IdeController::write(Packet *pkt) switch (reg_type) { case BMI_BLOCK: if (!bm_enabled) { - pkt->result = Success; + pkt->result = Packet::Success; return pioDelay; } @@ -539,8 +539,8 @@ IdeController::write(Packet *pkt) // Bus master IDE command register case BMIC1: case BMIC0: - if (pkt->size != sizeof(uint8_t)) - panic("Invalid BMIC write size: %x\n", pkt->size); + if (pkt->getSize() != sizeof(uint8_t)) + panic("Invalid BMIC write size: %x\n", pkt->getSize()); // select the current disk based on DEV bit disk = getDisk(channel); @@ -595,8 +595,8 @@ IdeController::write(Packet *pkt) // Bus master IDE status register case BMIS0: case BMIS1: - if (pkt->size != sizeof(uint8_t)) - panic("Invalid BMIS write size: %x\n", pkt->size); + if (pkt->getSize() != sizeof(uint8_t)) + panic("Invalid BMIS write size: %x\n", pkt->getSize()); oldVal = bmi_regs.chan[channel].bmis; newVal = pkt->get<uint8_t>(); @@ -622,22 +622,22 @@ IdeController::write(Packet *pkt) case BMIDTP0: case BMIDTP1: { - if (pkt->size != sizeof(uint32_t)) - panic("Invalid BMIDTP write size: %x\n", pkt->size); + if (pkt->getSize() != sizeof(uint32_t)) + panic("Invalid BMIDTP write size: %x\n", pkt->getSize()); bmi_regs.chan[channel].bmidtp = htole(pkt->get<uint32_t>() & ~0x3); } break; default: - if (pkt->size != sizeof(uint8_t) && - pkt->size != sizeof(uint16_t) && - pkt->size != sizeof(uint32_t)) + if (pkt->getSize() != sizeof(uint8_t) && + pkt->getSize() != sizeof(uint16_t) && + pkt->getSize() != sizeof(uint32_t)) panic("IDE controller write of invalid write size: %x\n", - pkt->size); + pkt->getSize()); // 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; case COMMAND_BLOCK: @@ -654,7 +654,7 @@ IdeController::write(Packet *pkt) switch (offset) { case DATA_OFFSET: - switch (pkt->size) { + switch (pkt->getSize()) { case sizeof(uint16_t): disks[disk]->write(offset, reg_type, pkt->getPtr<uint8_t>()); break; @@ -665,32 +665,32 @@ IdeController::write(Packet *pkt) sizeof(uint16_t)); break; 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; default: - if (pkt->size == sizeof(uint8_t)) { + if (pkt->getSize() == sizeof(uint8_t)) { disks[disk]->write(offset, reg_type, pkt->getPtr<uint8_t>()); } 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; default: 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", - offset, pkt->size, (uint32_t)pkt->get<uint8_t>()); - else if (pkt->size == 2) + offset, pkt->getSize(), (uint32_t)pkt->get<uint8_t>()); + else if (pkt->getSize() == 2) 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 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; } diff --git a/src/dev/io_device.cc b/src/dev/io_device.cc index 634b11b7e..87fdbb765 100644 --- a/src/dev/io_device.cc +++ b/src/dev/io_device.cc @@ -31,7 +31,7 @@ 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 PioPort::SendEvent::process() { - if (port->Port::sendTiming(packet) == Success) + if (port->Port::sendTiming(packet)) return; port->transmitList.push_back(packet); @@ -78,8 +78,10 @@ bool PioPort::recvTiming(Packet *pkt) { device->recvAtomic(pkt); + // turn packet around to go back to requester + pkt->makeTimingResponse(); sendTiming(pkt, pkt->time - pkt->req->getTime()); - return Success; + return true; } PioDevice::~PioDevice() @@ -106,7 +108,7 @@ BasicPioDevice::addressRanges(AddrRangeList &range_list) DmaPort::DmaPort(DmaDevice *dev, Platform *p) - : device(dev), platform(p), pendingCount(0) + : Port(dev->name() + "-dmaport"), device(dev), platform(p), pendingCount(0) { } bool @@ -114,7 +116,7 @@ DmaPort::recvTiming(Packet *pkt) { if (pkt->senderState) { DmaReqState *state; - state = (DmaReqState*)pkt->senderState; + state = dynamic_cast<DmaReqState*>(pkt->senderState); state->completionEvent->schedule(pkt->time - pkt->req->getTime()); delete pkt->req; delete pkt; @@ -123,7 +125,7 @@ DmaPort::recvTiming(Packet *pkt) delete pkt; } - return Success; + return Packet::Success; } DmaDevice::DmaDevice(Params *p) @@ -133,7 +135,7 @@ DmaDevice::DmaDevice(Params *p) void DmaPort::SendEvent::process() { - if (port->Port::sendTiming(packet) == Success) + if (port->Port::sendTiming(packet)) return; port->transmitList.push_back(packet); @@ -146,54 +148,39 @@ DmaPort::recvRetry() transmitList.pop_front(); return pkt; } + + void -DmaPort::dmaAction(Command cmd, Addr addr, int size, Event *event, - uint8_t *data) +DmaPort::dmaAction(Packet::Command cmd, Addr addr, int size, Event *event, + uint8_t *data) { - assert(event); 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()); !gen.done(); gen.next()) { - Packet *pkt = new Packet(basePkt); - Request *req = new Request(baseReq); - pkt->addr = gen.addr(); - pkt->size = gen.size(); - pkt->req = req; - pkt->req->setPaddr(pkt->addr); - pkt->req->setSize(pkt->size); + Request *req = new Request(false); + req->setPaddr(gen.addr()); + req->setSize(gen.size()); + req->setTime(curTick); + Packet *pkt = new Packet(req, cmd, Packet::Broadcast); + // Increment the data pointer on a write if (data) pkt->dataStatic(data + prevSize) ; - prevSize += pkt->size; + + prevSize += gen.size(); + // Set the last bit of the dma as the final packet for this dma // and set it's completion event. if (prevSize == size) { - DmaReqState *state = new DmaReqState(event, true); - - pkt->senderState = (void*)state; + pkt->senderState = new DmaReqState(event, true); } assert(pendingCount >= 0); pendingCount++; 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; if (state == Timing) { - if (sendTiming(pkt) == Failure) + if (!sendTiming(pkt)) transmitList.push_back(&packet); } else if (state == Atomic) {*/ sendAtomic(pkt); 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); } pendingCount--; diff --git a/src/dev/io_device.hh b/src/dev/io_device.hh index 6efa9ef63..74730ad92 100644 --- a/src/dev/io_device.hh +++ b/src/dev/io_device.hh @@ -115,7 +115,7 @@ class PioPort : public Port }; -struct DmaReqState +struct DmaReqState : public Packet::SenderState { Event *completionEvent; bool final; @@ -173,8 +173,8 @@ class DmaPort : public Port public: DmaPort(DmaDevice *dev, Platform *p); - void dmaAction(Command cmd, Addr addr, int size, Event *event, - uint8_t *data = NULL); + void dmaAction(Packet::Command cmd, Addr addr, int size, Event *event, + uint8_t *data = NULL); 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 * which are converted to either a write or a read. */ 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 * command is recieved by the port. @@ -305,10 +305,10 @@ class DmaDevice : public PioDevice virtual ~DmaDevice(); 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) - { dmaPort->dmaAction(Read, addr, size, event, data); } + { dmaPort->dmaAction(Packet::ReadReq, addr, size, event, data); } bool dmaPending() { return dmaPort->dmaPending(); } diff --git a/src/dev/isa_fake.cc b/src/dev/isa_fake.cc index 9717226b7..c303ffc30 100644 --- a/src/dev/isa_fake.cc +++ b/src/dev/isa_fake.cc @@ -51,14 +51,14 @@ IsaFake::IsaFake(Params *p) Tick IsaFake::read(Packet *pkt) { - assert(pkt->result == Unknown); - assert(pkt->addr >= pioAddr && pkt->addr < pioAddr + pioSize); + assert(pkt->result == Packet::Unknown); + assert(pkt->getAddr() >= pioAddr && pkt->getAddr() < pioAddr + pioSize); 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); break; case sizeof(uint32_t): @@ -73,7 +73,7 @@ IsaFake::read(Packet *pkt) default: panic("invalid access size(?) for PCI configspace!\n"); } - pkt->result = Success; + pkt->result = Packet::Success; return pioDelay; } @@ -81,8 +81,8 @@ Tick IsaFake::write(Packet *pkt) { pkt->time += pioDelay; - DPRINTF(Tsunami, "write - va=%#x size=%d \n", pkt->addr, pkt->size); - pkt->result = Success; + DPRINTF(Tsunami, "write - va=%#x size=%d \n", pkt->getAddr(), pkt->getSize()); + pkt->result = Packet::Success; return pioDelay; } diff --git a/src/dev/ns_gige.cc b/src/dev/ns_gige.cc index 5e27db58d..963675847 100644 --- a/src/dev/ns_gige.cc +++ b/src/dev/ns_gige.cc @@ -496,9 +496,9 @@ NSGigE::read(Packet *pkt) pkt->allocate(); //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", - daddr, pkt->addr, pkt->size); + daddr, pkt->getAddr(), pkt->getSize()); // 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) { panic("Accessing reserved register"); } 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>()); - if (pkt->size == sizeof(uint16_t)) + if (pkt->getSize() == sizeof(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>()); - pkt->result = Success; + pkt->result = Packet::Success; return pioDelay; } else if (daddr >= MIB_START && daddr <= MIB_END) { // don't implement all the MIB's. hopefully the kernel // doesn't actually DEPEND upon their values // MIB are just hardware stats keepers pkt->set<uint32_t>(0); - pkt->result = Success; + pkt->result = Packet::Success; return pioDelay; } else if (daddr > 0x3FC) panic("Something is messed up!\n"); - assert(pkt->size == sizeof(uint32_t)); + assert(pkt->getSize() == sizeof(uint32_t)); uint32_t ® = *pkt->getPtr<uint32_t>(); uint16_t rfaddr; @@ -715,7 +715,7 @@ NSGigE::read(Packet *pkt) DPRINTF(EthernetPIO, "read from %#x: data=%d data=%#x\n", daddr, reg, reg); - pkt->result = Success; + pkt->result = Packet::Success; return pioDelay; } @@ -724,27 +724,27 @@ NSGigE::write(Packet *pkt) { assert(ioEnable); - Addr daddr = pkt->addr & 0xfff; + Addr daddr = pkt->getAddr() & 0xfff; DPRINTF(EthernetPIO, "write da=%#x pa=%#x size=%d\n", - daddr, pkt->addr, pkt->size); + daddr, pkt->getAddr(), pkt->getSize()); pkt->time += pioDelay; if (daddr > LAST && daddr <= RESERVED) { panic("Accessing reserved register"); } 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>()); - if (pkt->size == sizeof(uint16_t)) + if (pkt->getSize() == sizeof(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>()); - pkt->result = Success; + pkt->result = Packet::Success; return pioDelay; } else if (daddr > 0x3FC) 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>(); uint16_t rfaddr; @@ -1131,7 +1131,7 @@ NSGigE::write(Packet *pkt) } else { panic("Invalid Request Size"); } - pkt->result = Success; + pkt->result = Packet::Success; return pioDelay; } diff --git a/src/dev/pciconfigall.cc b/src/dev/pciconfigall.cc index f278a67cf..14a28e86d 100644 --- a/src/dev/pciconfigall.cc +++ b/src/dev/pciconfigall.cc @@ -91,10 +91,10 @@ PciConfigAll::startup() Tick PciConfigAll::read(Packet *pkt) { - assert(pkt->result == Unknown); - assert(pkt->addr >= pioAddr && pkt->addr < pioAddr + pioSize); + assert(pkt->result == Packet::Unknown); + assert(pkt->getAddr() >= pioAddr && pkt->getAddr() < pioAddr + pioSize); - Addr daddr = pkt->addr - pioAddr; + Addr daddr = pkt->getAddr() - pioAddr; int device = (daddr >> 11) & 0x1F; int func = (daddr >> 8) & 0x7; int reg = daddr & 0xFF; @@ -102,10 +102,10 @@ PciConfigAll::read(Packet *pkt) pkt->time += pioDelay; pkt->allocate(); - DPRINTF(PciConfigAll, "read va=%#x da=%#x size=%d\n", pkt->addr, daddr, - pkt->size); + DPRINTF(PciConfigAll, "read va=%#x da=%#x size=%d\n", pkt->getAddr(), daddr, + pkt->getSize()); - switch (pkt->size) { + switch (pkt->getSize()) { case sizeof(uint32_t): if (devices[device][func] == NULL) pkt->set<uint32_t>(0xFFFFFFFF); @@ -127,7 +127,7 @@ PciConfigAll::read(Packet *pkt) default: panic("invalid access size(?) for PCI configspace!\n"); } - pkt->result = Success; + pkt->result = Packet::Success; return pioDelay; } @@ -136,11 +136,11 @@ PciConfigAll::write(Packet *pkt) { pkt->time += pioDelay; - assert(pkt->result == Unknown); - assert(pkt->addr >= pioAddr && pkt->addr < pioAddr + pioSize); - assert(pkt->size == sizeof(uint8_t) || pkt->size == sizeof(uint16_t) || - pkt->size == sizeof(uint32_t)); - Addr daddr = pkt->addr - pioAddr; + assert(pkt->result == Packet::Unknown); + assert(pkt->getAddr() >= pioAddr && pkt->getAddr() < pioAddr + pioSize); + assert(pkt->getSize() == sizeof(uint8_t) || pkt->getSize() == sizeof(uint16_t) || + pkt->getSize() == sizeof(uint32_t)); + Addr daddr = pkt->getAddr() - pioAddr; int device = (daddr >> 11) & 0x1F; int func = (daddr >> 8) & 0x7; @@ -150,9 +150,9 @@ PciConfigAll::write(Packet *pkt) panic("Attempting to write to config space on non-existant device\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): devices[device][func]->writeConfig(reg, pkt->get<uint8_t>()); break; @@ -165,7 +165,7 @@ PciConfigAll::write(Packet *pkt) default: panic("invalid pci config write size\n"); } - pkt->result = Success; + pkt->result = Packet::Success; return pioDelay; } diff --git a/src/dev/sinic.cc b/src/dev/sinic.cc index df7e4d167..31fbc49aa 100644 --- a/src/dev/sinic.cc +++ b/src/dev/sinic.cc @@ -315,10 +315,10 @@ Tick Device::read(Packet *pkt) { 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(); - Addr daddr = pkt->addr - BARAddrs[0]; + Addr daddr = pkt->getAddr() - BARAddrs[0]; Addr index = daddr >> Regs::VirtualShift; Addr raddr = daddr & Regs::VirtualMask; @@ -327,28 +327,28 @@ Device::read(Packet *pkt) if (!regValid(raddr)) 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); if (!info.read) panic("read %s (write only): " "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): " "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); uint64_t value = 0; - if (pkt->size == 4) { + if (pkt->getSize() == 4) { uint32_t reg = regData32(raddr); pkt->set(reg); value = reg; } - if (pkt->size == 8) { + if (pkt->getSize() == 8) { uint64_t reg = regData64(raddr); pkt->set(reg); value = reg; @@ -356,7 +356,7 @@ Device::read(Packet *pkt) DPRINTF(EthernetPIO, "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 // clearing it @@ -403,10 +403,10 @@ Tick Device::write(Packet *pkt) { 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(); - Addr daddr = pkt->addr - BARAddrs[0]; + Addr daddr = pkt->getAddr() - BARAddrs[0]; Addr index = daddr >> Regs::VirtualShift; Addr raddr = daddr & Regs::VirtualMask; @@ -414,25 +414,25 @@ Device::write(Packet *pkt) if (!regValid(raddr)) 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); if (!info.write) panic("write %s (read only): " "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): " "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]; DPRINTF(EthernetPIO, "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>() : - pkt->get<uint64_t>(), daddr, pkt->addr, pkt->size); + pkt->get<uint64_t>(), daddr, pkt->getAddr(), pkt->getSize()); prepareWrite(cpu, index); diff --git a/src/dev/tsunami_cchip.cc b/src/dev/tsunami_cchip.cc index 7206a61bb..146321b9f 100644 --- a/src/dev/tsunami_cchip.cc +++ b/src/dev/tsunami_cchip.cc @@ -71,17 +71,17 @@ TsunamiCChip::TsunamiCChip(Params *p) Tick 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->addr >= pioAddr && pkt->addr < pioAddr + pioSize); + assert(pkt->result == Packet::Unknown); + assert(pkt->getAddr() >= pioAddr && pkt->getAddr() < pioAddr + pioSize); pkt->time += pioDelay; - Addr regnum = (pkt->addr - pioAddr) >> 6; - Addr daddr = (pkt->addr - pioAddr); + Addr regnum = (pkt->getAddr() - pioAddr) >> 6; + Addr daddr = (pkt->getAddr() - pioAddr); pkt->allocate(); - switch (pkt->size) { + switch (pkt->getSize()) { case sizeof(uint64_t): if (daddr & TSDEV_CC_BDIMS) @@ -173,9 +173,9 @@ TsunamiCChip::read(Packet *pkt) panic("invalid access size(?) for tsunami register!\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; } @@ -185,14 +185,14 @@ TsunamiCChip::write(Packet *pkt) pkt->time += pioDelay; - assert(pkt->addr >= pioAddr && pkt->addr < pioAddr + pioSize); - Addr daddr = pkt->addr - pioAddr; - Addr regnum = (pkt->addr - pioAddr) >> 6 ; + assert(pkt->getAddr() >= pioAddr && pkt->getAddr() < pioAddr + pioSize); + Addr daddr = pkt->getAddr() - pioAddr; + 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; @@ -362,7 +362,7 @@ TsunamiCChip::write(Packet *pkt) panic("default in cchip read reached, accessing 0x%x\n"); } // swtich(regnum) } // not BIG_TSUNAMI write - pkt->result = Success; + pkt->result = Packet::Success; return pioDelay; } diff --git a/src/dev/tsunami_io.cc b/src/dev/tsunami_io.cc index dd9feae99..7c649a84a 100644 --- a/src/dev/tsunami_io.cc +++ b/src/dev/tsunami_io.cc @@ -438,18 +438,18 @@ TsunamiIO::frequency() const Tick TsunamiIO::read(Packet *pkt) { - assert(pkt->result == Unknown); - assert(pkt->addr >= pioAddr && pkt->addr < pioAddr + pioSize); + assert(pkt->result == Packet::Unknown); + assert(pkt->getAddr() >= pioAddr && pkt->getAddr() < pioAddr + pioSize); 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, - pkt->size, daddr); + DPRINTF(Tsunami, "io read va=%#x size=%d IOPorrt=%#x\n", pkt->getAddr(), + pkt->getSize(), daddr); pkt->allocate(); - if (pkt->size == sizeof(uint8_t)) { + if (pkt->getSize() == sizeof(uint8_t)) { switch(daddr) { // PIC1 mask read case TSDEV_PIC1_MASK: @@ -487,18 +487,18 @@ TsunamiIO::read(Packet *pkt) pkt->set(0x00); break; 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) pkt->set<uint64_t>(picr); else panic("I/O Read - invalid addr - va %#x size %d\n", - pkt->addr, pkt->size); + pkt->getAddr(), pkt->getSize()); } 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; } @@ -507,14 +507,14 @@ TsunamiIO::write(Packet *pkt) { pkt->time += pioDelay; - assert(pkt->result == Unknown); - assert(pkt->addr >= pioAddr && pkt->addr < pioAddr + pioSize); - Addr daddr = pkt->addr - pioAddr; + assert(pkt->result == Packet::Unknown); + assert(pkt->getAddr() >= pioAddr && pkt->getAddr() < pioAddr + pioSize); + Addr daddr = pkt->getAddr() - pioAddr; 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) { case TSDEV_PIC1_MASK: @@ -577,10 +577,10 @@ TsunamiIO::write(Packet *pkt) case TSDEV_CTRL_PORTB: break; 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; } diff --git a/src/dev/tsunami_pchip.cc b/src/dev/tsunami_pchip.cc index 999278e37..c430ca0a0 100644 --- a/src/dev/tsunami_pchip.cc +++ b/src/dev/tsunami_pchip.cc @@ -67,17 +67,17 @@ TsunamiPChip::TsunamiPChip(Params *p) Tick TsunamiPChip::read(Packet *pkt) { - assert(pkt->result == Unknown); - assert(pkt->addr >= pioAddr && pkt->addr < pioAddr + pioSize); + assert(pkt->result == Packet::Unknown); + assert(pkt->getAddr() >= pioAddr && pkt->getAddr() < pioAddr + pioSize); pkt->time += pioDelay; pkt->allocate(); - Addr daddr = (pkt->addr - pioAddr) >> 6;; - assert(pkt->size == sizeof(uint64_t)); + Addr daddr = (pkt->getAddr() - pioAddr) >> 6;; + 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) { case TSDEV_PC_WSBA0: @@ -143,7 +143,7 @@ TsunamiPChip::read(Packet *pkt) default: panic("Default in PChip Read reached reading 0x%x\n", daddr); } - pkt->result = Success; + pkt->result = Packet::Success; return pioDelay; } @@ -153,13 +153,13 @@ TsunamiPChip::write(Packet *pkt) { pkt->time += pioDelay; - assert(pkt->result == Unknown); - assert(pkt->addr >= pioAddr && pkt->addr < pioAddr + pioSize); - Addr daddr = (pkt->addr - pioAddr) >> 6; + assert(pkt->result == Packet::Unknown); + assert(pkt->getAddr() >= pioAddr && pkt->getAddr() < pioAddr + pioSize); + 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) { case TSDEV_PC_WSBA0: @@ -224,7 +224,7 @@ TsunamiPChip::write(Packet *pkt) } // uint64_t - pkt->result = Success; + pkt->result = Packet::Success; return pioDelay; } diff --git a/src/dev/uart8250.cc b/src/dev/uart8250.cc index a4b30cf25..8e6843841 100644 --- a/src/dev/uart8250.cc +++ b/src/dev/uart8250.cc @@ -110,12 +110,12 @@ Uart8250::Uart8250(Params *p) Tick Uart8250::read(Packet *pkt) { - assert(pkt->result == Unknown); - assert(pkt->addr >= pioAddr && pkt->addr < pioAddr + pioSize); - assert(pkt->size == 1); + assert(pkt->result == Packet::Unknown); + assert(pkt->getAddr() >= pioAddr && pkt->getAddr() < pioAddr + pioSize); + assert(pkt->getSize() == 1); pkt->time += pioDelay; - Addr daddr = pkt->addr - pioAddr; + Addr daddr = pkt->getAddr() - pioAddr; pkt->allocate(); DPRINTF(Uart, " read register %#x\n", daddr); @@ -186,7 +186,7 @@ Uart8250::read(Packet *pkt) /* uint32_t d32 = *data; DPRINTF(Uart, "Register read to register %#x returned %#x\n", daddr, d32); */ - pkt->result = Success; + pkt->result = Packet::Success; return pioDelay; } @@ -194,12 +194,12 @@ Tick Uart8250::write(Packet *pkt) { - assert(pkt->result == Unknown); - assert(pkt->addr >= pioAddr && pkt->addr < pioAddr + pioSize); - assert(pkt->size == 1); + assert(pkt->result == Packet::Unknown); + assert(pkt->getAddr() >= pioAddr && pkt->getAddr() < pioAddr + pioSize); + assert(pkt->getSize() == 1); 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>()); @@ -264,7 +264,7 @@ Uart8250::write(Packet *pkt) panic("Tried to access a UART port that doesn't exist\n"); break; } - pkt->result = Success; + pkt->result = Packet::Success; return pioDelay; } diff --git a/src/mem/bridge.cc b/src/mem/bridge.cc index c4b137869..736e8dc81 100644 --- a/src/mem/bridge.cc +++ b/src/mem/bridge.cc @@ -31,209 +31,209 @@ * @file Definition of a simple bus bridge without buffering. */ +#include <algorithm> #include "base/trace.hh" #include "mem/bridge.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 Bridge::init() { // 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"); } -/** 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.*/ bool -Bridge::recvTiming(Packet *pkt, Side id) +Bridge::BridgePort::recvTiming(Packet *pkt) { - if (blockedA && id == SideA) - return false; - if (blockedB && id == SideB) - return false; - - if (delay) { - if (!sendEvent.scheduled()) - sendEvent.schedule(curTick + delay); - if (id == SideA) { - inboundA.push_back(std::make_pair<Packet*, Tick>(pkt, curTick)); - blockCheck(SideA); - } else { - inboundB.push_back(std::make_pair<Packet*, Tick>(pkt, curTick)); - blockCheck(SideB); - } - } else { - if (id == SideB) { - sideA->sendPkt(pkt); - blockCheck(SideB); - } else { - sideB->sendPkt(pkt); - blockCheck(SideA); - } + DPRINTF(BusBridge, "recvTiming: src %d dest %d addr 0x%x\n", + pkt->getSrc(), pkt->getDest(), pkt->getAddr()); + + 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 true; + return otherPort->queueForSendTiming(pkt); } -void -Bridge::blockCheck(Side id) -{ - /* Check that we still have buffer space available. */ - if (id == SideB) { - if (sideA->numQueued() + inboundB.size() >= queueSizeA && !blockedB) { - sideB->sendStatusChange(Port::Blocked); - blockedB = true; - } else if (sideA->numQueued() + inboundB.size() < queueSizeA && blockedB) { - sideB->sendStatusChange(Port::Unblocked); - blockedB = false; - } - } else { - if (sideB->numQueued() + inboundA.size() >= queueSizeB && !blockedA) { - sideA->sendStatusChange(Port::Blocked); - blockedA = true; - } else if (sideB->numQueued() + inboundA.size() < queueSizeB && blockedA) { - sideA->sendStatusChange(Port::Unblocked); - blockedA = false; - } - } -} -void Bridge::timerEvent() +bool +Bridge::BridgePort::queueForSendTiming(Packet *pkt) { - Tick t = 0; + if (queueFull()) + return false; - assert(inboundA.size() || inboundB.size()); - if (inboundA.size()) { - while (inboundA.front().second <= curTick + delay){ - sideB->sendPkt(inboundA.front()); - inboundA.pop_front(); - } - if (inboundA.size()) - t = inboundA.front().second + delay; - } - if (inboundB.size()) { - while (inboundB.front().second <= curTick + delay){ - sideB->sendPkt(inboundA.front()); - inboundB.pop_front(); - } - if (inboundB.size()) - if (t == 0) - t = inboundB.front().second + delay; - else - t = std::min(t,inboundB.front().second + delay); - } else { - panic("timerEvent() called but nothing to do?"); + Tick readyTime = curTick + delay; + PacketBuffer *buf = new PacketBuffer(pkt, readyTime); + + // If we're about to put this packet at the head of the queue, we + // need to schedule an event to do the transmit. Otherwise there + // should already be an event scheduled for sending the head + // packet. + if (sendQueue.empty()) { + sendEvent.schedule(readyTime); } - if (t != 0) - sendEvent.schedule(t); + sendQueue.push_back(buf); + + // Did we just become blocked? If yes, let other side know. + if (queueFull()) + otherPort->sendStatusChange(Port::Blocked); + + return true; } void -Bridge::BridgePort::sendPkt(Packet *pkt) +Bridge::BridgePort::finishSend(PacketBuffer *buf) { - if (!sendTiming(pkt)) - outbound.push_back(std::make_pair<Packet*,Tick>(pkt, curTick)); + if (buf->expectResponse) { + // Must wait for response. We just need to count outstanding + // responses (in case we want to cap them); PacketBuffer + // pointer will be recovered on response. + ++outstandingResponses; + DPRINTF(BusBridge, " successful: awaiting response (%d)\n", + outstandingResponses); + } else { + // no response expected... deallocate packet buffer now. + DPRINTF(BusBridge, " successful: no response expected\n"); + delete buf; + } + + // 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::BridgePort::sendPkt(std::pair<Packet*, Tick> p) +Bridge::BridgePort::trySend() { - if (!sendTiming(p.first)) - outbound.push_back(p); + assert(!sendQueue.empty()); + + PacketBuffer *buf = sendQueue.front(); + + assert(buf->ready <= curTick); + + Packet *pkt = buf->pkt; + + DPRINTF(BusBridge, "trySend: origSrc %d dest %d addr 0x%x\n", + buf->origSrc, pkt->getDest(), pkt->getAddr()); + + if (sendTiming(pkt)) { + // send successful + sendQueue.pop_front(); + buf->pkt = NULL; // we no longer own packet, so it's not safe to look at it + finishSend(buf); + } else { + DPRINTF(BusBridge, " unsuccessful\n"); + } } Packet * Bridge::BridgePort::recvRetry() { - Packet *pkt; - assert(outbound.size() > 0); - assert(outbound.front().second >= curTick + bridge->delay); - pkt = outbound.front().first; - outbound.pop_front(); - bridge->blockCheck(side); + PacketBuffer *buf = sendQueue.front(); + Packet *pkt = buf->pkt; + finishSend(buf); 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.*/ Tick -Bridge::recvAtomic(Packet *pkt, Side id) +Bridge::BridgePort::recvAtomic(Packet *pkt) { - pkt->time += delay; - - if (id == SideA) - return sideB->sendAtomic(pkt); - else - return sideA->sendAtomic(pkt); + return otherPort->sendAtomic(pkt) + delay; } -/** 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.*/ void -Bridge::recvFunctional(Packet *pkt, Side id) +Bridge::BridgePort::recvFunctional(Packet *pkt) { - pkt->time += delay; - std::list<std::pair<Packet*, Tick> >::iterator i; + std::list<PacketBuffer*>::iterator i; bool pktContinue = true; - for(i = inboundA.begin(); i != inboundA.end(); ++i) { - if (pkt->intersect(i->first)) { - pktContinue &= fixPacket(pkt, i->first); - } - } - - 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); + for (i = sendQueue.begin(); i != sendQueue.end(); ++i) { + if (pkt->intersect((*i)->pkt)) { + pktContinue &= fixPacket(pkt, (*i)->pkt); } } if (pktContinue) { - if (id == SideA) - sideB->sendFunctional(pkt); - else - sideA->sendFunctional(pkt); + otherPort->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 -Bridge::recvStatusChange(Port::Status status, Side id) +Bridge::BridgePort::recvStatusChange(Port::Status status) { if (status == Port::Blocked || status == Port::Unblocked) - return ; + return; - if (id == SideA) - sideB->sendStatusChange(status); - else - sideA->sendStatusChange(status); + otherPort->sendStatusChange(status); } void -Bridge::addressRanges(AddrRangeList &resp, AddrRangeList &snoop, Side id) +Bridge::BridgePort::getDeviceAddressRanges(AddrRangeList &resp, + AddrRangeList &snoop) { - if (id == SideA) - sideB->getPeerAddressRanges(resp, snoop); - else - sideA->getPeerAddressRanges(resp, snoop); + otherPort->getPeerAddressRanges(resp, snoop); } BEGIN_DECLARE_SIM_OBJECT_PARAMS(Bridge) diff --git a/src/mem/bridge.hh b/src/mem/bridge.hh index 5f19ded40..8a5cbf92a 100644 --- a/src/mem/bridge.hh +++ b/src/mem/bridge.hh @@ -46,132 +46,127 @@ class Bridge : public MemObject { - public: - enum Side + protected: + /** Decleration of the buses port type, one will be instantiated for each + of the interfaces connecting to the bus. */ + class BridgePort : public Port { - SideA, - SideB - }; + /** A pointer to the bridge to which this port belongs. */ + Bridge *bridge; - protected: - /** Function called by the port when the bus is recieving a Timing - transaction.*/ - bool recvTiming(Packet *pkt, Side id); + /** + * Pointer to the port on the other side of the bridge + * (connected to the other bus). + */ + BridgePort *otherPort; - /** Function called by the port when the bus is recieving a Atomic - transaction.*/ - Tick recvAtomic(Packet *pkt, Side id); + /** Minimum delay though this bridge. */ + Tick delay; - /** Function called by the port when the bus is recieving a Functional - transaction.*/ - void recvFunctional(Packet *pkt, Side id); + class PacketBuffer : public Packet::SenderState { - /** Function called by the port when the bus is recieving a status change.*/ - void recvStatusChange(Port::Status status, Side id); + public: + Tick ready; + Packet *pkt; + Packet::SenderState *origSenderState; + short origSrc; + bool expectResponse; - /** 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); + PacketBuffer(Packet *_pkt, Tick t) + : ready(t), pkt(_pkt), + origSenderState(_pkt->senderState), origSrc(_pkt->getSrc()), + expectResponse(_pkt->needsResponse()) + { + pkt->senderState = this; + } + void fixResponse(Packet *pkt) + { + assert(pkt->senderState == this); + pkt->setDest(origSrc); + pkt->senderState = origSenderState; + } + }; - /** Event that the SendEvent calls when it fires. This code must reschedule - * the send event as required. */ - void timerEvent(); + /** + * 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; - /** Decleration of the buses port type, one will be instantiated for each - of the interfaces connecting to the bus. */ - class BridgePort : public Port - { - /** A pointer to the bus to which this port belongs. */ - Bridge *bridge; + 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 + { + BridgePort *port; + + public: + SendEvent(BridgePort *p) + : Event(&mainEventQueue), port(p) {} + + virtual void process() { port->trySend(); } - /** A id to keep track of the intercafe ID this port is connected to. */ - Bridge::Side side; + virtual const char *description() { return "bridge send event"; } + }; + + SendEvent sendEvent; public: /** Constructor for the BusPort.*/ - BridgePort(Bridge *_bridge, Side _side) - : bridge(_bridge), side(_side) - { } - - int numQueued() { return outbound.size(); } + BridgePort(const std::string &_name, + Bridge *_bridge, BridgePort *_otherPort, + int _delay, int _queueLimit); protected: - /** Data this is waiting to be transmitted. */ - std::list<std::pair<Packet*, Tick> > outbound; - - void sendPkt(Packet *pkt); - void sendPkt(std::pair<Packet*, Tick> p); - /** When reciving a timing request from the peer port, + /** When receiving a timing request from the peer port, pass it to the bridge. */ - virtual bool recvTiming(Packet *pkt) - { return bridge->recvTiming(pkt, side); } + virtual bool recvTiming(Packet *pkt); - /** When reciving a retry request from the peer port, + /** When receiving a retry request from the peer port, pass it to the bridge. */ virtual Packet* recvRetry(); - /** When reciving a Atomic requestfrom the peer port, + /** When receiving a Atomic requestfrom the peer port, pass it to the bridge. */ - virtual Tick recvAtomic(Packet *pkt) - { return bridge->recvAtomic(pkt, side); } + virtual Tick recvAtomic(Packet *pkt); - /** When reciving a Functional request from the peer port, + /** When receiving a Functional request from the peer port, pass it to the bridge. */ - virtual void recvFunctional(Packet *pkt) - { bridge->recvFunctional(pkt, side); } + virtual void recvFunctional(Packet *pkt); - /** When reciving a status changefrom the peer port, + /** When receiving a status changefrom the peer port, pass it to the bridge. */ - virtual void recvStatusChange(Status status) - { bridge->recvStatusChange(status, side); } + virtual void recvStatusChange(Status status); - /** When reciving a address range request the peer port, + /** When receiving 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; - }; - - class SendEvent : public Event - { - Bridge *bridge; - - SendEvent(Bridge *b) - : Event(&mainEventQueue), bridge(b) {} - - virtual void process() { bridge->timerEvent(); } - - virtual const char *description() { return "bridge delay event"; } - friend class Bridge; + virtual void getDeviceAddressRanges(AddrRangeList &resp, + AddrRangeList &snoop); }; - SendEvent sendEvent; - - /** Sides of the bus bridges. */ - BridgePort* sideA; - BridgePort* sideB; - - /** inbound queues on both sides. */ - std::list<std::pair<Packet*, Tick> > inboundA; - std::list<std::pair<Packet*, Tick> > inboundB; - - /** The size of the queue for data coming into side a */ - int queueSizeA; - int queueSizeB; - - /* if the side is blocked or not. */ - bool blockedA; - bool blockedB; - - /** Miminum delay though this bridge. */ - Tick delay; + BridgePort portA, portB; /** If this bridge should acknowledge writes. */ bool ackWrites; @@ -179,36 +174,11 @@ class Bridge : public MemObject public: /** A function used to return the port associated with this bus object. */ - 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 Port *getPort(const std::string &if_name); virtual void init(); - 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; - + Bridge(const std::string &n, int qsa, int qsb, Tick _delay, int write_ack); }; #endif //__MEM_BUS_HH__ diff --git a/src/mem/bus.cc b/src/mem/bus.cc index f7c2b874a..cfc99a64f 100644 --- a/src/mem/bus.cc +++ b/src/mem/bus.cc @@ -35,6 +35,16 @@ #include "mem/bus.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. */ void 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.*/ bool Bus::recvTiming(Packet *pkt) { Port *port; - if (pkt->dest == Packet::Broadcast) { - port = findPort(pkt->addr, pkt->src); + DPRINTF(Bus, "recvTiming: packet src %d dest %d addr 0x%x cmd %s\n", + pkt->getSrc(), pkt->getDest(), pkt->getAddr(), pkt->cmdString()); + + short dest = pkt->getDest(); + if (dest == Packet::Broadcast) { + port = findPort(pkt->getAddr(), pkt->getSrc()); } else { - assert(pkt->dest > 0 && pkt->dest < interfaces.size()); - port = interfaces[pkt->dest]; + assert(dest >= 0 && dest < interfaces.size()); + assert(dest != pkt->getSrc()); // catch infinite loops + port = interfaces[dest]; } return port->sendTiming(pkt); } @@ -73,7 +88,7 @@ Bus::findPort(Addr addr, int id) if (portList[i].range == addr) { dest_id = portList[i].portId; 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++; } @@ -86,33 +101,37 @@ Bus::findPort(Addr addr, int 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.*/ Tick Bus::recvAtomic(Packet *pkt) { - assert(pkt->dest == Packet::Broadcast); - return findPort(pkt->addr, pkt->src)->sendAtomic(pkt); + DPRINTF(Bus, "recvAtomic: packet src %d dest %d addr 0x%x cmd %s\n", + 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.*/ void Bus::recvFunctional(Packet *pkt) { - assert(pkt->dest == Packet::Broadcast); - findPort(pkt->addr, pkt->src)->sendFunctional(pkt); + DPRINTF(Bus, "recvFunctional: packet src %d dest %d addr 0x%x cmd %s\n", + 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 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 && "The other statuses need to be implemented."); + DPRINTF(BusAddrRanges, "received RangeChange from device id %d\n", id); + assert(id < interfaces.size() && id >= 0); int x; Port *port = interfaces[id]; @@ -138,8 +157,8 @@ Bus::recvStatusChange(Port::Status status, int id) dm.portId = id; dm.range = *iter; - DPRINTF(MMU, "Adding range %llx - %llx for id %d\n", dm.range.start, - dm.range.end, id); + DPRINTF(BusAddrRanges, "Adding range %llx - %llx for id %d\n", + dm.range.start, dm.range.end, id); portList.push_back(dm); } DPRINTF(MMU, "port list has %d entries\n", portList.size()); @@ -159,13 +178,12 @@ Bus::addressRanges(AddrRangeList &resp, AddrRangeList &snoop, int id) resp.clear(); snoop.clear(); - DPRINTF(Bus, "Bus id %d recieved address range request returning\n", - busId); + DPRINTF(BusAddrRanges, "received address range request, returning:\n"); for (portIter = portList.begin(); portIter != portList.end(); portIter++) { if (portIter->portId != id) { resp.push_back(portIter->range); - DPRINTF(Bus, "-- %#llX : %#llX\n", portIter->range.start, - portIter->range.end); + DPRINTF(BusAddrRanges, " -- %#llX : %#llX\n", + portIter->range.start, portIter->range.end); } } } diff --git a/src/mem/bus.hh b/src/mem/bus.hh index 38573e514..5eeb07904 100644 --- a/src/mem/bus.hh +++ b/src/mem/bus.hh @@ -100,8 +100,8 @@ class Bus : public MemObject public: /** Constructor for the BusPort.*/ - BusPort(Bus *_bus, int _id) - : bus(_bus), id(_id) + BusPort(const std::string &_name, Bus *_bus, int _id) + : Port(_name), bus(_bus), id(_id) { } protected: @@ -109,17 +109,17 @@ class Bus : public MemObject /** When reciving a timing request from the peer port (at id), pass it to the bus. */ virtual bool recvTiming(Packet *pkt) - { pkt->src = id; return bus->recvTiming(pkt); } + { pkt->setSrc(id); return bus->recvTiming(pkt); } /** When reciving a Atomic requestfrom the peer port (at id), pass it to the bus. */ virtual Tick recvAtomic(Packet *pkt) - { pkt->src = id; return bus->recvAtomic(pkt); } + { pkt->setSrc(id); return bus->recvAtomic(pkt); } /** When reciving a Functional requestfrom the peer port (at id), pass it to the bus. */ virtual void recvFunctional(Packet *pkt) - { pkt->src = id; bus->recvFunctional(pkt); } + { pkt->setSrc(id); bus->recvFunctional(pkt); } /** When reciving a status changefrom the peer port (at id), pass it to the bus. */ @@ -146,13 +146,7 @@ class Bus : public MemObject public: /** A function used to return the port associated with this bus object. */ - 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 Port *getPort(const std::string &if_name); virtual void init(); diff --git a/src/mem/packet.cc b/src/mem/packet.cc index a9be7ac51..3b415d77f 100644 --- a/src/mem/packet.cc +++ b/src/mem/packet.cc @@ -34,11 +34,31 @@ #include "base/misc.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 * data was allocted. */ void -Packet::deleteData() { +Packet::deleteData() +{ assert(staticData || dynamicData); if (staticData) return; @@ -51,22 +71,24 @@ Packet::deleteData() { /** If there isn't data in the packet, allocate some. */ void -Packet::allocate() { +Packet::allocate() +{ if (data) return; assert(!staticData); dynamicData = true; arrayData = true; - data = new uint8_t[size]; + data = new uint8_t[getSize()]; } /** Do the packet modify the same addresses. */ bool -Packet::intersect(Packet *p) { - Addr s1 = addr; - Addr e1 = addr + size; - Addr s2 = p->addr; - Addr e2 = p->addr + p->size; +Packet::intersect(Packet *p) +{ + Addr s1 = getAddr(); + Addr e1 = getAddr() + getSize(); + Addr s2 = p->getAddr(); + Addr e2 = p->getAddr() + p->getSize(); if (s1 >= s2 && s1 < e2) return true; @@ -77,7 +99,8 @@ Packet::intersect(Packet *p) { /** Minimally reset a packet so something like simple cpu can reuse it. */ void -Packet::reset() { +Packet::reset() +{ result = Unknown; if (dynamicData) { deleteData(); @@ -88,7 +111,8 @@ Packet::reset() { } - - -bool fixPacket(Packet *func, Packet *timing) -{ panic("Need to implement!"); } +bool +fixPacket(Packet *func, Packet *timing) +{ + panic("Need to implement!"); +} diff --git a/src/mem/packet.hh b/src/mem/packet.hh index e8a7b0c73..83f52ede5 100644 --- a/src/mem/packet.hh +++ b/src/mem/packet.hh @@ -43,24 +43,6 @@ struct Packet; typedef Packet* PacketPtr; 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 * 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 * the transaction has no response, then the consumer will delete the packet. */ -struct Packet +class Packet { private: /** A pointer to the data being transfered. It can be differnt sizes @@ -95,57 +77,132 @@ struct Packet bool arrayData; - public: /** The address of the request, could be virtual or physical (depending on cache configurations). */ Addr addr; - /** Flag structure to hold flags for this particular packet */ - uint64_t flags; + /** Indicates the size of the request. */ + int size; + + /** A index of the source of the transaction. */ + short src; + + /** A index to the destination of the transaction. */ + 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. */ - Coherence *coherence; // virtual base opaque, + CoherenceState *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. */ - int size; + class SenderState { + public: + virtual ~SenderState() {} + }; - /** A index of the source of the transaction. */ - short src; + /** A virtual base opaque structure used to hold the senders state. */ + SenderState *senderState; // virtual base opaque, + // assert(dynamic_cast<Foo>) etc. - static const short Broadcast = -1; + 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, + }; - /** A index to the destination of the transaction. */ - short dest; + 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. */ 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. */ Tick time; + /** The result of a particular packets request. */ + enum Result + { + Success, + BadAddress, + Unknown + }; + /** The result of the packet transaction. */ - PacketResult result; + Result result; /** 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 the packet. */ short getDest() const { return dest; } + void setDest(short _dest) { dest = _dest; } + + 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() + + Packet(Request *_req, Command _cmd, short _dest) : 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) - {} + { + } ~Packet() { deleteData(); } @@ -154,6 +211,11 @@ struct Packet /** Minimally reset a packet so something like simple cpu can reuse it. */ 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. */ template <typename T> void dataStatic(T *p); diff --git a/src/mem/physical.cc b/src/mem/physical.cc index bc2500678..26dbef0cd 100644 --- a/src/mem/physical.cc +++ b/src/mem/physical.cc @@ -127,7 +127,8 @@ PhysicalMemory::doTimingAccess (Packet *pkt, MemoryPort* memoryPort) { doFunctionalAccess(pkt); - pkt->dest = pkt->src; + // turn packet around to go back to requester + pkt->makeTimingResponse(); MemResponseEvent* response = new MemResponseEvent(pkt, memoryPort); response->schedule(curTick + lat); @@ -145,16 +146,18 @@ PhysicalMemory::doAtomicAccess(Packet *pkt) void PhysicalMemory::doFunctionalAccess(Packet *pkt) { - assert(pkt->addr + pkt->size < pmem_size); + assert(pkt->getAddr() + pkt->getSize() < pmem_size); switch (pkt->cmd) { - case Read: - memcpy(pkt->getPtr<uint8_t>(), pmem_addr + pkt->addr - base_addr, - pkt->size); + case Packet::ReadReq: + memcpy(pkt->getPtr<uint8_t>(), + pmem_addr + pkt->getAddr() - base_addr, + pkt->getSize()); break; - case Write: - memcpy(pmem_addr + pkt->addr - base_addr, pkt->getPtr<uint8_t>(), - pkt->size); + case Packet::WriteReq: + memcpy(pmem_addr + pkt->getAddr() - base_addr, + pkt->getPtr<uint8_t>(), + pkt->getSize()); // temporary hack: will need to add real LL/SC implementation // for cacheless systems later. if (pkt->req->getFlags() & LOCKED) { @@ -165,7 +168,7 @@ PhysicalMemory::doFunctionalAccess(Packet *pkt) panic("unimplemented"); } - pkt->result = Success; + pkt->result = Packet::Success; } Port * @@ -174,11 +177,11 @@ PhysicalMemory::getPort(const std::string &if_name) if (if_name == "") { if (port != NULL) panic("PhysicalMemory::getPort: additional port requested to memory!"); - port = new MemoryPort(this); + port = new MemoryPort(name() + "-port", this); return port; } else if (if_name == "functional") { /* special port for functional writes at startup. */ - return new MemoryPort(this); + return new MemoryPort(name() + "-funcport", this); } else { panic("PhysicalMemory::getPort: unknown port %s requested", if_name); } @@ -189,8 +192,9 @@ PhysicalMemory::recvStatusChange(Port::Status status) { } -PhysicalMemory::MemoryPort::MemoryPort(PhysicalMemory *_memory) - : memory(_memory) +PhysicalMemory::MemoryPort::MemoryPort(const std::string &_name, + PhysicalMemory *_memory) + : Port(_name), memory(_memory) { } void diff --git a/src/mem/physical.hh b/src/mem/physical.hh index 1cf5444ab..2ced79045 100644 --- a/src/mem/physical.hh +++ b/src/mem/physical.hh @@ -51,7 +51,7 @@ class PhysicalMemory : public MemObject public: - MemoryPort(PhysicalMemory *_memory); + MemoryPort(const std::string &_name, PhysicalMemory *_memory); protected: diff --git a/src/mem/port.cc b/src/mem/port.cc index fb3103ed1..651cb739a 100644 --- a/src/mem/port.cc +++ b/src/mem/port.cc @@ -31,22 +31,28 @@ */ #include "base/chunk_generator.hh" +#include "base/trace.hh" #include "mem/packet_impl.hh" #include "mem/port.hh" 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); - Packet pkt; - pkt.req = &req; - pkt.cmd = cmd; - pkt.dest = Packet::Broadcast; + Packet pkt(&req, cmd, Packet::Broadcast); for (ChunkGenerator gen(addr, size, peerBlockSize()); !gen.done(); gen.next()) { - req.setPaddr(pkt.addr = gen.addr()); - req.setSize(pkt.size = gen.size()); + req.setPaddr(gen.addr()); + req.setSize(gen.size()); + pkt.reinitFromRequest(); pkt.dataStatic(p); sendFunctional(&pkt); p += gen.size(); @@ -56,13 +62,13 @@ Port::blobHelper(Addr addr, uint8_t *p, int size, Command cmd) void Port::writeBlob(Addr addr, uint8_t *p, int size) { - blobHelper(addr, p, size, Write); + blobHelper(addr, p, size, Packet::WriteReq); } void Port::readBlob(Addr addr, uint8_t *p, int size) { - blobHelper(addr, p, size, Read); + blobHelper(addr, p, size, Packet::ReadReq); } void @@ -72,7 +78,7 @@ Port::memsetBlob(Addr addr, uint8_t val, int size) uint8_t *buf = new uint8_t[size]; memset(buf, val, size); - blobHelper(addr, buf, size, Write); + blobHelper(addr, buf, size, Packet::WriteReq); delete [] buf; } diff --git a/src/mem/port.hh b/src/mem/port.hh index 1b1920c03..f9103865e 100644 --- a/src/mem/port.hh +++ b/src/mem/port.hh @@ -69,9 +69,28 @@ typedef std::list<Range<Addr> >::iterator AddrRangeIter; */ class Port { + private: + + /** Descriptive name (for DPRINTF output) */ + const std::string portName; + 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() {}; + // mey be better to use subclasses & RTTI? /** Holds the ports status. Keeps track if it is blocked, or has calculated a range change. */ @@ -93,9 +112,9 @@ class Port /** Function to set the pointer for the peer port. @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). */ Port *getPeer() { return peer; } @@ -213,7 +232,7 @@ class Port /** 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 @@ -224,6 +243,10 @@ class Port class FunctionalPort : public Port { public: + FunctionalPort(const std::string &_name) + : Port(_name) + {} + virtual bool recvTiming(Packet *pkt) { panic("FuncPort is UniDir"); } virtual Tick recvAtomic(Packet *pkt) { panic("FuncPort is UniDir"); } virtual void recvFunctional(Packet *pkt) { panic("FuncPort is UniDir"); } diff --git a/src/mem/request.hh b/src/mem/request.hh index 2db7b7779..10550e859 100644 --- a/src/mem/request.hh +++ b/src/mem/request.hh @@ -195,6 +195,7 @@ class Request /** Accesor function for pc.*/ void setPC(Addr _pc); + friend class Packet; }; #endif // __MEM_REQUEST_HH__ diff --git a/src/mem/translating_port.cc b/src/mem/translating_port.cc index 5dfeaff31..ee4d277b6 100644 --- a/src/mem/translating_port.cc +++ b/src/mem/translating_port.cc @@ -34,8 +34,9 @@ using namespace TheISA; -TranslatingPort::TranslatingPort(PageTable *p_table, bool alloc) - : pTable(p_table), allocating(alloc) +TranslatingPort::TranslatingPort(const std::string &_name, + PageTable *p_table, bool alloc) + : FunctionalPort(_name), pTable(p_table), allocating(alloc) { } TranslatingPort::~TranslatingPort() diff --git a/src/mem/translating_port.hh b/src/mem/translating_port.hh index 7611ac3c7..d078158a3 100644 --- a/src/mem/translating_port.hh +++ b/src/mem/translating_port.hh @@ -39,14 +39,11 @@ class TranslatingPort : public FunctionalPort PageTable *pTable; bool allocating; - TranslatingPort(const TranslatingPort &specmem); - const TranslatingPort &operator=(const TranslatingPort &specmem); - public: - TranslatingPort(PageTable *p_table, bool alloc = false); + TranslatingPort(const std::string &_name, + PageTable *p_table, bool alloc = false); virtual ~TranslatingPort(); - public: bool tryReadBlob(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); @@ -56,9 +53,9 @@ class TranslatingPort : public FunctionalPort virtual void readBlob(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); + void writeString(Addr addr, const char *str); void readString(std::string &str, Addr addr); - }; #endif diff --git a/src/mem/vport.hh b/src/mem/vport.hh index fbc230ba3..0f3b1f09e 100644 --- a/src/mem/vport.hh +++ b/src/mem/vport.hh @@ -53,8 +53,8 @@ class VirtualPort : public FunctionalPort ExecContext *xc; public: - VirtualPort(ExecContext *_xc = NULL) - : xc(_xc) + VirtualPort(const std::string &_name, ExecContext *_xc = NULL) + : FunctionalPort(_name), xc(_xc) {} /** Return true if we have an exec context. This is used to prevent someone diff --git a/src/sim/process.cc b/src/sim/process.cc index 1261b8436..1da525093 100644 --- a/src/sim/process.cc +++ b/src/sim/process.cc @@ -154,7 +154,7 @@ Process::startup() Port *mem_port; mem_port = system->physmem->getPort("functional"); - initVirtMem = new TranslatingPort(pTable, true); + initVirtMem = new TranslatingPort("process init port", pTable, true); mem_port->setPeer(initVirtMem); initVirtMem->setPeer(mem_port); } diff --git a/src/sim/system.cc b/src/sim/system.cc index ca9d68d77..89f39491e 100644 --- a/src/sim/system.cc +++ b/src/sim/system.cc @@ -25,6 +25,8 @@ System::System(Params *p) : SimObject(p->name), physmem(p->physmem), numcpus(0), #if FULL_SYSTEM init_param(p->init_param), + functionalPort(p->name + "-fport"), + virtPort(p->name + "-vport"), #else page_ptr(0), #endif |