diff options
Diffstat (limited to 'src')
593 files changed, 23165 insertions, 18493 deletions
diff --git a/src/SConscript b/src/SConscript index d96922b49..d02d2a6e7 100644 --- a/src/SConscript +++ b/src/SConscript @@ -49,7 +49,7 @@ Import('*') # Children need to see the environment Export('env') -build_env = dict([(opt, env[opt]) for opt in export_vars]) +build_env = [(opt, env[opt]) for opt in export_vars] ######################################################################## # Code for adding source files of various types @@ -132,15 +132,15 @@ class PySource(SourceFile): modpath = '.'.join(modpath) arcpath = path + [ self.basename ] - debugname = self.snode.abspath - if not exists(debugname): - debugname = self.tnode.abspath + abspath = self.snode.abspath + if not exists(abspath): + abspath = self.tnode.abspath self.package = package self.modname = modname self.modpath = modpath self.arcname = joinpath(*arcpath) - self.debugname = debugname + self.abspath = abspath self.compiled = File(self.filename + 'c') self.assembly = File(self.filename + '.s') self.symname = "PyEMB_" + PySource.invalid_sym_char.sub('_', modpath) @@ -228,9 +228,6 @@ env.Append(CPPPATH=Dir('.')) for extra_dir in extras_dir_list: env.Append(CPPPATH=Dir(extra_dir)) -# Add a flag defining what THE_ISA should be for all compilation -env.Append(CPPDEFINES=[('THE_ISA','%s_ISA' % env['TARGET_ISA'].upper())]) - # Workaround for bug in SCons version > 0.97d20071212 # Scons bug id: 2006 M5 Bug id: 308 for root, dirs, files in os.walk(base_dir, topdown=True): @@ -261,11 +258,38 @@ for extra_dir in extras_dir_list: for opt in export_vars: env.ConfigFile(opt) +def makeTheISA(source, target, env): + f = file(str(target[0]), 'w') + + isas = [ src.get_contents() for src in source ] + target = env['TARGET_ISA'] + def define(isa): + return isa.upper() + '_ISA' + + def namespace(isa): + return isa[0].upper() + isa[1:].lower() + 'ISA' + + + print >>f, '#ifndef __CONFIG_THE_ISA_HH__' + print >>f, '#define __CONFIG_THE_ISA_HH__' + print >>f + for i,isa in enumerate(isas): + print >>f, '#define %s %d' % (define(isa), i + 1) + print >>f + print >>f, '#define THE_ISA %s' % (define(target)) + print >>f, '#define TheISA %s' % (namespace(target)) + print >>f + print >>f, '#endif // __CONFIG_THE_ISA_HH__' + +env.Command('config/the_isa.hh', map(Value, all_isa_list), makeTheISA) + ######################################################################## # # Prevent any SimObjects from being added after this point, they # should all have been added in the SConscripts above # +SimObject.fixed = True + class DictImporter(object): '''This importer takes a dictionary of arbitrary module names that map to arbitrary filenames.''' @@ -283,7 +307,7 @@ class DictImporter(object): self.installed = set() def find_module(self, fullname, path): - if fullname == 'defines': + if fullname == 'm5.defines': return self if fullname == 'm5.objects': @@ -293,7 +317,7 @@ class DictImporter(object): return None source = self.modules.get(fullname, None) - if source is not None and exists(source.snode.abspath): + if source is not None and fullname.startswith('m5.objects'): return self return None @@ -308,28 +332,31 @@ class DictImporter(object): mod.__path__ = fullname.split('.') return mod - if fullname == 'defines': - mod.__dict__['buildEnv'] = build_env + if fullname == 'm5.defines': + mod.__dict__['buildEnv'] = m5.util.SmartDict(build_env) return mod source = self.modules[fullname] if source.modname == '__init__': mod.__path__ = source.modpath - mod.__file__ = source.snode.abspath + mod.__file__ = source.abspath - exec file(source.snode.abspath, 'r') in mod.__dict__ + exec file(source.abspath, 'r') in mod.__dict__ return mod +import m5.SimObject +import m5.params + +m5.SimObject.clear() +m5.params.clear() + # install the python importer so we can grab stuff from the source # tree itself. We can't have SimObjects added after this point or # else we won't know about them for the rest of the stuff. -SimObject.fixed = True importer = DictImporter(PySource.modules) sys.meta_path[0:0] = [ importer ] -import m5 - # import all sim objects so we can populate the all_objects list # make sure that we're working with a list, then let's sort it for modname in SimObject.modnames: @@ -346,6 +373,12 @@ all_enums = m5.params.allEnums all_params = {} for name,obj in sorted(sim_objects.iteritems()): for param in obj._params.local.values(): + # load the ptype attribute now because it depends on the + # current version of SimObject.allClasses, but when scons + # actually uses the value, all versions of + # SimObject.allClasses will have been loaded + param.ptype + if not hasattr(param, 'swig_decl'): continue pname = param.ptype_str @@ -365,13 +398,27 @@ depends = [ PySource.modules[dep].tnode for dep in module_depends ] # # Generate Python file containing a dict specifying the current -# build_env flags. +# buildEnv flags. def makeDefinesPyFile(target, source, env): - f = file(str(target[0]), 'w') build_env, hg_info = [ x.get_contents() for x in source ] - print >>f, "buildEnv = %s" % build_env - print >>f, "hgRev = '%s'" % hg_info - f.close() + + code = m5.util.code_formatter() + code(""" +import m5.internal +import m5.util + +buildEnv = m5.util.SmartDict($build_env) +hgRev = '$hg_info' + +compileDate = m5.internal.core.compileDate +_globals = globals() +for key,val in m5.internal.core.__dict__.iteritems(): + if key.startswith('flag_'): + flag = key[5:] + _globals[flag] = val +del _globals +""") + code.write(str(target[0])) defines_info = [ Value(build_env), Value(env['HG_INFO']) ] # Generate a file with all of the compile options in it @@ -467,12 +514,7 @@ for name,simobj in sorted(sim_objects.iteritems()): # Generate any parameter header files needed params_i_files = [] for name,param in all_params.iteritems(): - if isinstance(param, m5.params.VectorParamDesc): - ext = 'vptype' - else: - ext = 'ptype' - - i_file = File('params/%s_%s.i' % (name, ext)) + i_file = File('params/%s_%s.i' % (name, param.file_ext)) params_i_files.append(i_file) env.Command(i_file, Value(name), createSwigParam) env.Depends(i_file, depends) @@ -850,7 +892,7 @@ def objectifyPyFile(target, source, env): dst = file(str(target[0]), 'w') pysource = PySource.tnodes[source[0]] - compiled = compile(src, pysource.debugname, 'exec') + compiled = compile(src, pysource.abspath, 'exec') marshalled = marshal.dumps(compiled) compressed = zlib.compress(marshalled) data = compressed diff --git a/src/arch/alpha/faults.cc b/src/arch/alpha/faults.cc index e93e16711..ff6de8d03 100644 --- a/src/arch/alpha/faults.cc +++ b/src/arch/alpha/faults.cc @@ -144,7 +144,7 @@ DtbFault::invoke(ThreadContext *tc) // read, like the EV5). The EV6 approach is cleaner and seems to // work with EV5 PAL code, but not the other way around. if (!tc->misspeculating() && - reqFlags.noneSet(Request::VPTE|Request::NO_FAULT)) { + reqFlags.noneSet(Request::VPTE | Request::PREFETCH)) { // set VA register with faulting address tc->setMiscRegNoEffect(IPR_VA, vaddr); diff --git a/src/arch/alpha/isa.cc b/src/arch/alpha/isa.cc index eee391a0d..8b6da3649 100644 --- a/src/arch/alpha/isa.cc +++ b/src/arch/alpha/isa.cc @@ -36,7 +36,7 @@ namespace AlphaISA { void -ISA::serialize(std::ostream &os) +ISA::serialize(EventManager *em, std::ostream &os) { SERIALIZE_SCALAR(fpcr); SERIALIZE_SCALAR(uniq); @@ -46,7 +46,7 @@ ISA::serialize(std::ostream &os) } void -ISA::unserialize(Checkpoint *cp, const std::string §ion) +ISA::unserialize(EventManager *em, Checkpoint *cp, const std::string §ion) { UNSERIALIZE_SCALAR(fpcr); UNSERIALIZE_SCALAR(uniq); diff --git a/src/arch/alpha/isa.hh b/src/arch/alpha/isa.hh index 622d1da4c..574b50841 100644 --- a/src/arch/alpha/isa.hh +++ b/src/arch/alpha/isa.hh @@ -83,8 +83,9 @@ namespace AlphaISA intr_flag = 0; } - void serialize(std::ostream &os); - void unserialize(Checkpoint *cp, const std::string §ion); + void serialize(EventManager *em, std::ostream &os); + void unserialize(EventManager *em, Checkpoint *cp, + const std::string §ion); void reset(std::string core_name, ThreadID num_threads, unsigned num_vpes, BaseCPU *_cpu) diff --git a/src/arch/alpha/isa/decoder.isa b/src/arch/alpha/isa/decoder.isa index cb43fcb74..52e124ad5 100644 --- a/src/arch/alpha/isa/decoder.isa +++ b/src/arch/alpha/isa/decoder.isa @@ -627,7 +627,7 @@ decode OPCODE default Unknown::unknown() { format MiscPrefetch { 0xf800: wh64({{ EA = Rb & ~ULL(63); }}, {{ xc->writeHint(EA, 64, memAccessFlags); }}, - mem_flags = NO_FAULT, + mem_flags = PREFETCH, inst_flags = [IsMemRef, IsDataPrefetch, IsStore, MemWriteOp]); } diff --git a/src/arch/alpha/isa/mem.isa b/src/arch/alpha/isa/mem.isa index fedfbf55d..b1703221f 100644 --- a/src/arch/alpha/isa/mem.isa +++ b/src/arch/alpha/isa/mem.isa @@ -548,7 +548,7 @@ def format LoadOrPrefetch(memacc_code, ea_code = {{ EA = Rb + disp; }}, pf_flags = makeList(pf_flags) inst_flags = makeList(inst_flags) - pf_mem_flags = mem_flags + pf_flags + ['NO_FAULT'] + pf_mem_flags = mem_flags + pf_flags + ['PREFETCH'] pf_inst_flags = inst_flags + ['IsMemRef', 'IsLoad', 'IsDataPrefetch', 'MemReadOp'] diff --git a/src/arch/alpha/linux/linux.hh b/src/arch/alpha/linux/linux.hh index c622c5ef1..c728ce1fb 100644 --- a/src/arch/alpha/linux/linux.hh +++ b/src/arch/alpha/linux/linux.hh @@ -105,6 +105,7 @@ class AlphaLinux : public Linux static const unsigned TIOCISATTY_ = 0x2000745e; static const unsigned TIOCGETS_ = 0x402c7413; static const unsigned TIOCGETA_ = 0x40127417; + static const unsigned TCSETAW_ = 0x80147419; // 2.6.15 kernel //@} /// For table(). @@ -125,6 +126,21 @@ class AlphaLinux : public Linux TGT_RLIMIT_MEMLOCK = 9, TGT_RLIMIT_LOCKS = 10 }; + + typedef struct { + int64_t uptime; /* Seconds since boot */ + uint64_t loads[3]; /* 1, 5, and 15 minute load averages */ + uint64_t totalram; /* Total usable main memory size */ + uint64_t freeram; /* Available memory size */ + uint64_t sharedram; /* Amount of shared memory */ + uint64_t bufferram; /* Memory used by buffers */ + uint64_t totalswap; /* Total swap space size */ + uint64_t freeswap; /* swap space still available */ + uint16_t procs; /* Number of current processes */ + uint64_t totalhigh; /* Total high memory size */ + uint64_t freehigh; /* Available high memory size */ + uint64_t mem_unit; /* Memory unit size in bytes */ + } tgt_sysinfo; }; #endif // __ALPHA_ALPHA_LINUX_LINUX_HH__ diff --git a/src/arch/alpha/linux/process.cc b/src/arch/alpha/linux/process.cc index 9886c7ea7..a653d7845 100644 --- a/src/arch/alpha/linux/process.cc +++ b/src/arch/alpha/linux/process.cc @@ -48,7 +48,8 @@ static SyscallReturn unameFunc(SyscallDesc *desc, int callnum, LiveProcess *process, ThreadContext *tc) { - TypedBufferArg<Linux::utsname> name(process->getSyscallArg(tc, 0)); + int index = 0; + TypedBufferArg<Linux::utsname> name(process->getSyscallArg(tc, index)); strcpy(name->sysname, "Linux"); strcpy(name->nodename, "m5.eecs.umich.edu"); @@ -67,13 +68,15 @@ static SyscallReturn osf_getsysinfoFunc(SyscallDesc *desc, int callnum, LiveProcess *process, ThreadContext *tc) { - unsigned op = process->getSyscallArg(tc, 0); + int index = 0; + unsigned op = process->getSyscallArg(tc, index); + Addr bufPtr = process->getSyscallArg(tc, index); // unsigned nbytes = process->getSyscallArg(tc, 2); switch (op) { case 45: { // GSI_IEEE_FP_CONTROL - TypedBufferArg<uint64_t> fpcr(process->getSyscallArg(tc, 1)); + TypedBufferArg<uint64_t> fpcr(bufPtr); // I don't think this exactly matches the HW FPCR *fpcr = 0; fpcr.copyOut(tc->getMemPort()); @@ -94,13 +97,15 @@ static SyscallReturn osf_setsysinfoFunc(SyscallDesc *desc, int callnum, LiveProcess *process, ThreadContext *tc) { - unsigned op = process->getSyscallArg(tc, 0); + int index = 0; + unsigned op = process->getSyscallArg(tc, index); + Addr bufPtr = process->getSyscallArg(tc, index); // unsigned nbytes = process->getSyscallArg(tc, 2); switch (op) { case 14: { // SSI_IEEE_FP_CONTROL - TypedBufferArg<uint64_t> fpcr(process->getSyscallArg(tc, 1)); + TypedBufferArg<uint64_t> fpcr(bufPtr); // I don't think this exactly matches the HW FPCR fpcr.copyIn(tc->getMemPort()); DPRINTFR(SyscallVerbose, "osf_setsysinfo(SSI_IEEE_FP_CONTROL): " @@ -440,7 +445,7 @@ SyscallDesc AlphaLinuxProcess::syscallDescs[] = { /* 315 */ SyscallDesc("munlock", unimplementedFunc), /* 316 */ SyscallDesc("mlockall", unimplementedFunc), /* 317 */ SyscallDesc("munlockall", unimplementedFunc), - /* 318 */ SyscallDesc("sysinfo", unimplementedFunc), + /* 318 */ SyscallDesc("sysinfo", sysinfoFunc<AlphaLinux>), /* 319 */ SyscallDesc("_sysctl", unimplementedFunc), /* 320 */ SyscallDesc("was sys_idle", unimplementedFunc), /* 321 */ SyscallDesc("oldumount", unimplementedFunc), diff --git a/src/arch/alpha/process.cc b/src/arch/alpha/process.cc index 6aad45da8..9d75d5fa1 100644 --- a/src/arch/alpha/process.cc +++ b/src/arch/alpha/process.cc @@ -193,10 +193,10 @@ AlphaLiveProcess::startup() } AlphaISA::IntReg -AlphaLiveProcess::getSyscallArg(ThreadContext *tc, int i) +AlphaLiveProcess::getSyscallArg(ThreadContext *tc, int &i) { assert(i < 6); - return tc->readIntReg(FirstArgumentReg + i); + return tc->readIntReg(FirstArgumentReg + i++); } void diff --git a/src/arch/alpha/process.hh b/src/arch/alpha/process.hh index 6d083c5ac..36b25a48e 100644 --- a/src/arch/alpha/process.hh +++ b/src/arch/alpha/process.hh @@ -44,7 +44,7 @@ class AlphaLiveProcess : public LiveProcess void argsInit(int intSize, int pageSize); public: - AlphaISA::IntReg getSyscallArg(ThreadContext *tc, int i); + AlphaISA::IntReg getSyscallArg(ThreadContext *tc, int &i); void setSyscallArg(ThreadContext *tc, int i, AlphaISA::IntReg val); void setSyscallReturn(ThreadContext *tc, SyscallReturn return_value); }; diff --git a/src/arch/alpha/tru64/process.cc b/src/arch/alpha/tru64/process.cc index 8fa3cdeda..b039fbe19 100644 --- a/src/arch/alpha/tru64/process.cc +++ b/src/arch/alpha/tru64/process.cc @@ -45,7 +45,8 @@ static SyscallReturn unameFunc(SyscallDesc *desc, int callnum, LiveProcess *process, ThreadContext *tc) { - TypedBufferArg<AlphaTru64::utsname> name(process->getSyscallArg(tc, 0)); + int index = 0; + TypedBufferArg<AlphaTru64::utsname> name(process->getSyscallArg(tc, index)); strcpy(name->sysname, "OSF1"); strcpy(name->nodename, "m5.eecs.umich.edu"); @@ -62,35 +63,36 @@ static SyscallReturn getsysinfoFunc(SyscallDesc *desc, int callnum, LiveProcess *process, ThreadContext *tc) { - unsigned op = process->getSyscallArg(tc, 0); - unsigned nbytes = process->getSyscallArg(tc, 2); + int index = 0; + unsigned op = process->getSyscallArg(tc, index); + Addr bufPtr = process->getSyscallArg(tc, index); + unsigned nbytes = process->getSyscallArg(tc, index); switch (op) { case AlphaTru64::GSI_MAX_CPU: { - TypedBufferArg<uint32_t> max_cpu(process->getSyscallArg(tc, 1)); + TypedBufferArg<uint32_t> max_cpu(bufPtr); *max_cpu = htog((uint32_t)process->numCpus()); max_cpu.copyOut(tc->getMemPort()); return 1; } case AlphaTru64::GSI_CPUS_IN_BOX: { - TypedBufferArg<uint32_t> cpus_in_box(process->getSyscallArg(tc, 1)); + TypedBufferArg<uint32_t> cpus_in_box(bufPtr); *cpus_in_box = htog((uint32_t)process->numCpus()); cpus_in_box.copyOut(tc->getMemPort()); return 1; } case AlphaTru64::GSI_PHYSMEM: { - TypedBufferArg<uint64_t> physmem(process->getSyscallArg(tc, 1)); + TypedBufferArg<uint64_t> physmem(bufPtr); *physmem = htog((uint64_t)1024 * 1024); // physical memory in KB physmem.copyOut(tc->getMemPort()); return 1; } case AlphaTru64::GSI_CPU_INFO: { - TypedBufferArg<AlphaTru64::cpu_info> - infop(process->getSyscallArg(tc, 1)); + TypedBufferArg<AlphaTru64::cpu_info> infop(bufPtr); infop->current_cpu = htog(0); infop->cpus_in_box = htog(process->numCpus()); @@ -107,14 +109,14 @@ getsysinfoFunc(SyscallDesc *desc, int callnum, LiveProcess *process, } case AlphaTru64::GSI_PROC_TYPE: { - TypedBufferArg<uint64_t> proc_type(process->getSyscallArg(tc, 1)); + TypedBufferArg<uint64_t> proc_type(bufPtr); *proc_type = htog((uint64_t)11); proc_type.copyOut(tc->getMemPort()); return 1; } case AlphaTru64::GSI_PLATFORM_NAME: { - BufferArg bufArg(process->getSyscallArg(tc, 1), nbytes); + BufferArg bufArg(bufPtr, nbytes); strncpy((char *)bufArg.bufferPtr(), "COMPAQ Professional Workstation XP1000", nbytes); @@ -123,7 +125,7 @@ getsysinfoFunc(SyscallDesc *desc, int callnum, LiveProcess *process, } case AlphaTru64::GSI_CLK_TCK: { - TypedBufferArg<uint64_t> clk_hz(process->getSyscallArg(tc, 1)); + TypedBufferArg<uint64_t> clk_hz(bufPtr); *clk_hz = htog((uint64_t)1024); clk_hz.copyOut(tc->getMemPort()); return 1; @@ -142,12 +144,13 @@ static SyscallReturn setsysinfoFunc(SyscallDesc *desc, int callnum, LiveProcess *process, ThreadContext *tc) { - unsigned op = process->getSyscallArg(tc, 0); + int index = 0; + unsigned op = process->getSyscallArg(tc, index); switch (op) { case AlphaTru64::SSI_IEEE_FP_CONTROL: warn("setsysinfo: ignoring ieee_set_fp_control() arg 0x%x\n", - process->getSyscallArg(tc, 1)); + process->getSyscallArg(tc, index)); break; default: @@ -165,17 +168,19 @@ tableFunc(SyscallDesc *desc, int callnum, LiveProcess *process, { using namespace std; - int id = process->getSyscallArg(tc, 0); // table ID - int index = process->getSyscallArg(tc, 1); // index into table + int argIndex = 0; + int id = process->getSyscallArg(tc, argIndex); // table ID + int index = process->getSyscallArg(tc, argIndex); // index into table + Addr bufPtr = process->getSyscallArg(tc, argIndex); // arg 2 is buffer pointer; type depends on table ID - int nel = process->getSyscallArg(tc, 3); // number of elements - int lel = process->getSyscallArg(tc, 4); // expected element size + int nel = process->getSyscallArg(tc, argIndex); // number of elements + int lel = process->getSyscallArg(tc, argIndex); // expected element size switch (id) { case AlphaTru64::TBL_SYSINFO: { if (index != 0 || nel != 1 || lel != sizeof(Tru64::tbl_sysinfo)) return -EINVAL; - TypedBufferArg<Tru64::tbl_sysinfo> elp(process->getSyscallArg(tc, 2)); + TypedBufferArg<Tru64::tbl_sysinfo> elp(bufPtr); const int clk_hz = one_million; elp->si_user = htog(curTick / (Clock::Frequency / clk_hz)); diff --git a/src/arch/alpha/tru64/tru64.hh b/src/arch/alpha/tru64/tru64.hh index 4ba35fc50..0ee12973c 100644 --- a/src/arch/alpha/tru64/tru64.hh +++ b/src/arch/alpha/tru64/tru64.hh @@ -99,6 +99,7 @@ class AlphaTru64 : public Tru64 static const unsigned TIOCISATTY_ = 0x2000745e; static const unsigned TIOCGETS_ = 0x402c7413; static const unsigned TIOCGETA_ = 0x40127417; + static const unsigned TCSETAW_ = 0x80147419; //@} //@{ diff --git a/src/arch/arm/ArmInterrupts.py b/src/arch/arm/ArmInterrupts.py new file mode 100644 index 000000000..f21d49e95 --- /dev/null +++ b/src/arch/arm/ArmInterrupts.py @@ -0,0 +1,33 @@ +# Copyright (c) 2009 ARM Limited +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer; +# redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution; +# neither the name of the copyright holders nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# Authors: Ali Saidi + +from m5.SimObject import SimObject + +class ArmInterrupts(SimObject): + type = 'ArmInterrupts' + cxx_class = 'ArmISA::Interrupts' diff --git a/src/python/m5/environment.py b/src/arch/arm/ArmSystem.py index bea0bc1d0..872776c69 100644 --- a/src/python/m5/environment.py +++ b/src/arch/arm/ArmSystem.py @@ -1,4 +1,4 @@ -# Copyright (c) 2005 The Regents of The University of Michigan +# Copyright (c) 2009 ARM Limited # All rights reserved. # # Redistribution and use in source and binary forms, with or without @@ -24,20 +24,12 @@ # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # -# Authors: Nathan Binkert -# Steve Reinhardt +# Authors: Ali Saidi -import os +from m5.params import * -# import the m5 compile options -import defines +from System import System -# make a SmartDict out of the build options for our local use -import smartdict -build_env = smartdict.SmartDict() -build_env.update(defines.m5_build_env) - -# make a SmartDict out of the OS environment too -env = smartdict.SmartDict() -env.update(os.environ) +class ArmSystem(System): + type = 'ArmSystem' diff --git a/src/arch/arm/SConscript b/src/arch/arm/SConscript index 55ecabdc3..92a4193f1 100644 --- a/src/arch/arm/SConscript +++ b/src/arch/arm/SConscript @@ -1,6 +1,7 @@ # -*- mode:python -*- # Copyright (c) 2007-2008 The Florida State University +# Copyright (c) 2009 ARM Limited # All rights reserved. # # Redistribution and use in source and binary forms, with or without @@ -27,6 +28,7 @@ # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # # Authors: Stephen Hines +# Ali Saidi Import('*') @@ -43,15 +45,20 @@ if env['TARGET_ISA'] == 'arm': Source('pagetable.cc') Source('tlb.cc') Source('vtophys.cc') + Source('utility.cc') SimObject('ArmNativeTrace.py') SimObject('ArmTLB.py') TraceFlag('Arm') - + TraceFlag('Faults', "Trace Exceptions, interrupts, svc/swi") if env['FULL_SYSTEM']: - #Insert Full-System Files Here - pass + Source('interrupts.cc') + Source('stacktrace.cc') + Source('system.cc') + + SimObject('ArmInterrupts.py') + SimObject('ArmSystem.py') else: Source('process.cc') Source('linux/linux.cc') diff --git a/src/arch/arm/faults.cc b/src/arch/arm/faults.cc index 3d882c97f..b7dd2d503 100644 --- a/src/arch/arm/faults.cc +++ b/src/arch/arm/faults.cc @@ -26,488 +26,114 @@ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * - * Authors: Gabe Black - * Stephen Hines + * Authors: Ali Saidi + * Gabe Black */ #include "arch/arm/faults.hh" #include "cpu/thread_context.hh" #include "cpu/base.hh" #include "base/trace.hh" -#if !FULL_SYSTEM -#include "sim/process.hh" -#include "mem/page_table.hh" -#endif namespace ArmISA { -FaultName MachineCheckFault::_name = "Machine Check"; -FaultVect MachineCheckFault::_vect = 0x0401; -FaultStat MachineCheckFault::_count; +template<> ArmFaultBase::FaultVals ArmFault<Reset>::vals = + {"reset", 0x00, MODE_SVC, 0, 0, true, true}; -FaultName AlignmentFault::_name = "Alignment"; -FaultVect AlignmentFault::_vect = 0x0301; -FaultStat AlignmentFault::_count; +template<> ArmFaultBase::FaultVals ArmFault<UndefinedInstruction>::vals = + {"Undefined Instruction", 0x04, MODE_UNDEFINED, 4 ,2, false, false} ; -FaultName ResetFault::_name = "Reset Fault"; -#if FULL_SYSTEM -FaultVect ResetFault::_vect = 0xBFC00000; -#else -FaultVect ResetFault::_vect = 0x001; -#endif -FaultStat ResetFault::_count; +template<> ArmFaultBase::FaultVals ArmFault<SupervisorCall>::vals = + {"Supervisor Call", 0x08, MODE_SVC, 4, 2, false, false}; -FaultName AddressErrorFault::_name = "Address Error"; -FaultVect AddressErrorFault::_vect = 0x0180; -FaultStat AddressErrorFault::_count; +template<> ArmFaultBase::FaultVals ArmFault<PrefetchAbort>::vals = + {"Prefetch Abort", 0x0C, MODE_ABORT, 4, 4, true, false}; -FaultName StoreAddressErrorFault::_name = "Store Address Error"; -FaultVect StoreAddressErrorFault::_vect = 0x0180; -FaultStat StoreAddressErrorFault::_count; +template<> ArmFaultBase::FaultVals ArmFault<DataAbort>::vals = + {"Data Abort", 0x10, MODE_ABORT, 8, 8, true, false}; +template<> ArmFaultBase::FaultVals ArmFault<Interrupt>::vals = + {"IRQ", 0x18, MODE_IRQ, 4, 4, true, false}; -FaultName SystemCallFault::_name = "Syscall"; -FaultVect SystemCallFault::_vect = 0x0180; -FaultStat SystemCallFault::_count; +template<> ArmFaultBase::FaultVals ArmFault<FastInterrupt>::vals = + {"FIQ", 0x1C, MODE_FIQ, 4, 4, true, true}; -FaultName CoprocessorUnusableFault::_name = "Coprocessor Unusable Fault"; -FaultVect CoprocessorUnusableFault::_vect = 0x180; -FaultStat CoprocessorUnusableFault::_count; - -FaultName ReservedInstructionFault::_name = "Reserved Instruction Fault"; -FaultVect ReservedInstructionFault::_vect = 0x0180; -FaultStat ReservedInstructionFault::_count; - -FaultName ThreadFault::_name = "Thread Fault"; -FaultVect ThreadFault::_vect = 0x00F1; -FaultStat ThreadFault::_count; - - -FaultName ArithmeticFault::_name = "Arithmetic Overflow Exception"; -FaultVect ArithmeticFault::_vect = 0x180; -FaultStat ArithmeticFault::_count; - -FaultName UnimplementedOpcodeFault::_name = "opdec"; -FaultVect UnimplementedOpcodeFault::_vect = 0x0481; -FaultStat UnimplementedOpcodeFault::_count; - -FaultName InterruptFault::_name = "interrupt"; -FaultVect InterruptFault::_vect = 0x0180; -FaultStat InterruptFault::_count; - -FaultName TrapFault::_name = "Trap"; -FaultVect TrapFault::_vect = 0x0180; -FaultStat TrapFault::_count; - -FaultName BreakpointFault::_name = "Breakpoint"; -FaultVect BreakpointFault::_vect = 0x0180; -FaultStat BreakpointFault::_count; - - -FaultName ItbInvalidFault::_name = "Invalid TLB Entry Exception (I-Fetch/LW)"; -FaultVect ItbInvalidFault::_vect = 0x0180; -FaultStat ItbInvalidFault::_count; - -FaultName ItbPageFault::_name = "itbmiss"; -FaultVect ItbPageFault::_vect = 0x0181; -FaultStat ItbPageFault::_count; - -FaultName ItbMissFault::_name = "itbmiss"; -FaultVect ItbMissFault::_vect = 0x0181; -FaultStat ItbMissFault::_count; - -FaultName ItbAcvFault::_name = "iaccvio"; -FaultVect ItbAcvFault::_vect = 0x0081; -FaultStat ItbAcvFault::_count; - -FaultName ItbRefillFault::_name = "TLB Refill Exception (I-Fetch/LW)"; -FaultVect ItbRefillFault::_vect = 0x0180; -FaultStat ItbRefillFault::_count; - -FaultName NDtbMissFault::_name = "dtb_miss_single"; -FaultVect NDtbMissFault::_vect = 0x0201; -FaultStat NDtbMissFault::_count; - -FaultName PDtbMissFault::_name = "dtb_miss_double"; -FaultVect PDtbMissFault::_vect = 0x0281; -FaultStat PDtbMissFault::_count; - -FaultName DtbPageFault::_name = "dfault"; -FaultVect DtbPageFault::_vect = 0x0381; -FaultStat DtbPageFault::_count; - -FaultName DtbAcvFault::_name = "dfault"; -FaultVect DtbAcvFault::_vect = 0x0381; -FaultStat DtbAcvFault::_count; - -FaultName DtbInvalidFault::_name = "Invalid TLB Entry Exception (Store)"; -FaultVect DtbInvalidFault::_vect = 0x0180; -FaultStat DtbInvalidFault::_count; - -FaultName DtbRefillFault::_name = "TLB Refill Exception (Store)"; -FaultVect DtbRefillFault::_vect = 0x0180; -FaultStat DtbRefillFault::_count; - -FaultName TLBModifiedFault::_name = "TLB Modified Exception"; -FaultVect TLBModifiedFault::_vect = 0x0180; -FaultStat TLBModifiedFault::_count; - -FaultName FloatEnableFault::_name = "float_enable_fault"; -FaultVect FloatEnableFault::_vect = 0x0581; -FaultStat FloatEnableFault::_count; - -FaultName IntegerOverflowFault::_name = "Integer Overflow Fault"; -FaultVect IntegerOverflowFault::_vect = 0x0501; -FaultStat IntegerOverflowFault::_count; - -FaultName DspStateDisabledFault::_name = "DSP Disabled Fault"; -FaultVect DspStateDisabledFault::_vect = 0x001a; -FaultStat DspStateDisabledFault::_count; - -#if FULL_SYSTEM -void ArmFault::setHandlerPC(Addr HandlerBase, ThreadContext *tc) -{ - tc->setPC(HandlerBase); - tc->setNextPC(HandlerBase+sizeof(MachInst)); - tc->setNextNPC(HandlerBase+2*sizeof(MachInst)); -} - -void ArmFault::setExceptionState(ThreadContext *tc,uint8_t ExcCode) -{ - // modify SRS Ctl - Save CSS, put ESS into CSS - MiscReg stat = tc->readMiscReg(ArmISA::Status); - if(bits(stat,Status_EXL) != 1 && bits(stat,Status_BEV) != 1) - { - // SRS Ctl is modified only if Status_EXL and Status_BEV are not set - MiscReg srs = tc->readMiscReg(ArmISA::SRSCtl); - uint8_t CSS,ESS; - CSS = bits(srs,SRSCtl_CSS_HI,SRSCtl_CSS_LO); - ESS = bits(srs,SRSCtl_ESS_HI,SRSCtl_ESS_LO); - // Move CSS to PSS - replaceBits(srs,SRSCtl_PSS_HI,SRSCtl_PSS_LO,CSS); - // Move ESS to CSS - replaceBits(srs,SRSCtl_CSS_HI,SRSCtl_CSS_LO,ESS); - tc->setMiscRegNoEffect(ArmISA::SRSCtl,srs); - //tc->setShadowSet(ESS); - } - - // set EXL bit (don't care if it is already set!) - replaceBits(stat,Status_EXL_HI,Status_EXL_LO,1); - tc->setMiscRegNoEffect(ArmISA::Status,stat); - - // write EPC - // warn("Set EPC to %x\n",tc->readPC()); - // CHECK ME or FIXME or FIX ME or POSSIBLE HACK - // Check to see if the exception occurred in the branch delay slot - DPRINTF(Arm,"PC: %x, NextPC: %x, NNPC: %x\n",tc->readPC(),tc->readNextPC(),tc->readNextNPC()); - int C_BD=0; - if(tc->readPC() + sizeof(MachInst) != tc->readNextPC()){ - tc->setMiscRegNoEffect(ArmISA::EPC,tc->readPC()-sizeof(MachInst)); - // In the branch delay slot? set CAUSE_31 - C_BD = 1; - } else { - tc->setMiscRegNoEffect(ArmISA::EPC,tc->readPC()); - // In the branch delay slot? reset CAUSE_31 - C_BD = 0; - } - - // Set Cause_EXCCODE field - MiscReg cause = tc->readMiscReg(ArmISA::Cause); - replaceBits(cause,Cause_EXCCODE_HI,Cause_EXCCODE_LO,ExcCode); - replaceBits(cause,Cause_BD_HI,Cause_BD_LO,C_BD); - replaceBits(cause,Cause_CE_HI,Cause_CE_LO,0); - tc->setMiscRegNoEffect(ArmISA::Cause,cause); - -} - -void ArithmeticFault::invoke(ThreadContext *tc) -{ - DPRINTF(Arm,"%s encountered.\n", name()); - setExceptionState(tc,0xC); - - // Set new PC - Addr HandlerBase; - MiscReg stat = tc->readMiscReg(ArmISA::Status); - // Here, the handler is dependent on BEV, which is not modified by setExceptionState() - if(bits(stat,Status_BEV)==0){ // See MIPS ARM Vol 3, Revision 2, Page 38 - HandlerBase= vect() + tc->readMiscReg(ArmISA::EBase); - }else{ - HandlerBase = 0xBFC00200; - } - setHandlerPC(HandlerBase,tc); - // warn("Exception Handler At: %x \n",HandlerBase); -} - -void StoreAddressErrorFault::invoke(ThreadContext *tc) -{ - DPRINTF(Arm,"%s encountered.\n", name()); - setExceptionState(tc,0x5); - tc->setMiscRegNoEffect(ArmISA::BadVAddr,BadVAddr); - - // Set new PC - Addr HandlerBase; - HandlerBase= vect() + tc->readMiscReg(ArmISA::EBase); // Offset 0x180 - General Exception Vector - setHandlerPC(HandlerBase,tc); - // warn("Exception Handler At: %x \n",HandlerBase); - // warn("Exception Handler At: %x , EPC set to %x\n",HandlerBase,tc->readMiscReg(ArmISA::EPC)); - -} - -void TrapFault::invoke(ThreadContext *tc) -{ - DPRINTF(Arm,"%s encountered.\n", name()); - // warn("%s encountered.\n", name()); - setExceptionState(tc,0xD); - - // Set new PC - Addr HandlerBase; - HandlerBase= vect() + tc->readMiscReg(ArmISA::EBase); // Offset 0x180 - General Exception Vector - setHandlerPC(HandlerBase,tc); - // warn("Exception Handler At: %x \n",HandlerBase); - // warn("Exception Handler At: %x , EPC set to %x\n",HandlerBase,tc->readMiscReg(ArmISA::EPC)); -} - -void BreakpointFault::invoke(ThreadContext *tc) -{ - setExceptionState(tc,0x9); - - // Set new PC - Addr HandlerBase; - HandlerBase= vect() + tc->readMiscReg(ArmISA::EBase); // Offset 0x180 - General Exception Vector - setHandlerPC(HandlerBase,tc); - // warn("Exception Handler At: %x \n",HandlerBase); - // warn("Exception Handler At: %x , EPC set to %x\n",HandlerBase,tc->readMiscReg(ArmISA::EPC)); - -} - -void DtbInvalidFault::invoke(ThreadContext *tc) +Addr +ArmFaultBase::getVector(ThreadContext *tc) { - DPRINTF(Arm,"%s encountered.\n", name()); - // warn("%s encountered.\n", name()); - tc->setMiscRegNoEffect(ArmISA::BadVAddr,BadVAddr); - MiscReg eh = tc->readMiscReg(ArmISA::EntryHi); - replaceBits(eh,EntryHi_ASID_HI,EntryHi_ASID_LO,EntryHi_Asid); - replaceBits(eh,EntryHi_VPN2_HI,EntryHi_VPN2_LO,EntryHi_VPN2); - replaceBits(eh,EntryHi_VPN2X_HI,EntryHi_VPN2X_LO,EntryHi_VPN2X); - tc->setMiscRegNoEffect(ArmISA::EntryHi,eh); - MiscReg ctxt = tc->readMiscReg(ArmISA::Context); - replaceBits(ctxt,Context_BadVPN2_HI,Context_BadVPN2_LO,Context_BadVPN2); - tc->setMiscRegNoEffect(ArmISA::Context,ctxt); - setExceptionState(tc,0x3); + // ARM ARM B1-3 + SCTLR sctlr = tc->readMiscReg(MISCREG_SCTLR); + + // panic if SCTLR.VE because I have no idea what to do with vectored + // interrupts + assert(!sctlr.ve); + + if (!sctlr.v) + return offset(); + return offset() + HighVecs; - // Set new PC - Addr HandlerBase; - HandlerBase= vect() + tc->readMiscReg(ArmISA::EBase); // Offset 0x180 - General Exception Vector - setHandlerPC(HandlerBase,tc); - // warn("Exception Handler At: %x , EPC set to %x\n",HandlerBase,tc->readMiscReg(ArmISA::EPC)); } -void AddressErrorFault::invoke(ThreadContext *tc) -{ - DPRINTF(Arm,"%s encountered.\n", name()); - setExceptionState(tc,0x4); - tc->setMiscRegNoEffect(ArmISA::BadVAddr,BadVAddr); - - // Set new PC - Addr HandlerBase; - HandlerBase= vect() + tc->readMiscReg(ArmISA::EBase); // Offset 0x180 - General Exception Vector - setHandlerPC(HandlerBase,tc); -} - -void ItbInvalidFault::invoke(ThreadContext *tc) -{ - DPRINTF(Arm,"%s encountered.\n", name()); - setExceptionState(tc,0x2); - tc->setMiscRegNoEffect(ArmISA::BadVAddr,BadVAddr); - MiscReg eh = tc->readMiscReg(ArmISA::EntryHi); - replaceBits(eh,EntryHi_ASID_HI,EntryHi_ASID_LO,EntryHi_Asid); - replaceBits(eh,EntryHi_VPN2_HI,EntryHi_VPN2_LO,EntryHi_VPN2); - replaceBits(eh,EntryHi_VPN2X_HI,EntryHi_VPN2X_LO,EntryHi_VPN2X); - tc->setMiscRegNoEffect(ArmISA::EntryHi,eh); - MiscReg ctxt = tc->readMiscReg(ArmISA::Context); - replaceBits(ctxt,Context_BadVPN2_HI,Context_BadVPN2_LO,Context_BadVPN2); - tc->setMiscRegNoEffect(ArmISA::Context,ctxt); - - - // Set new PC - Addr HandlerBase; - HandlerBase= vect() + tc->readMiscReg(ArmISA::EBase); // Offset 0x180 - General Exception Vector - setHandlerPC(HandlerBase,tc); - DPRINTF(Arm,"Exception Handler At: %x , EPC set to %x\n",HandlerBase,tc->readMiscReg(ArmISA::EPC)); -} - -void ItbRefillFault::invoke(ThreadContext *tc) -{ - DPRINTF(Arm,"%s encountered (%x).\n", name(),BadVAddr); - Addr HandlerBase; - tc->setMiscRegNoEffect(ArmISA::BadVAddr,BadVAddr); - MiscReg eh = tc->readMiscReg(ArmISA::EntryHi); - replaceBits(eh,EntryHi_ASID_HI,EntryHi_ASID_LO,EntryHi_Asid); - replaceBits(eh,EntryHi_VPN2_HI,EntryHi_VPN2_LO,EntryHi_VPN2); - replaceBits(eh,EntryHi_VPN2X_HI,EntryHi_VPN2X_LO,EntryHi_VPN2X); - tc->setMiscRegNoEffect(ArmISA::EntryHi,eh); - MiscReg ctxt = tc->readMiscReg(ArmISA::Context); - replaceBits(ctxt,Context_BadVPN2_HI,Context_BadVPN2_LO,Context_BadVPN2); - tc->setMiscRegNoEffect(ArmISA::Context,ctxt); - - MiscReg stat = tc->readMiscReg(ArmISA::Status); - // Since handler depends on EXL bit, must check EXL bit before setting it!! - if(bits(stat,Status_EXL)==1){ // See MIPS ARM Vol 3, Revision 2, Page 38 - HandlerBase= vect() + tc->readMiscReg(ArmISA::EBase); // Offset 0x180 - General Exception Vector - }else{ - HandlerBase = tc->readMiscReg(ArmISA::EBase); // Offset 0x000 - } - - setExceptionState(tc,0x2); - setHandlerPC(HandlerBase,tc); -} - -void DtbRefillFault::invoke(ThreadContext *tc) -{ - // Set new PC - DPRINTF(Arm,"%s encountered.\n", name()); - Addr HandlerBase; - tc->setMiscRegNoEffect(ArmISA::BadVAddr,BadVAddr); - MiscReg eh = tc->readMiscReg(ArmISA::EntryHi); - replaceBits(eh,EntryHi_ASID_HI,EntryHi_ASID_LO,EntryHi_Asid); - replaceBits(eh,EntryHi_VPN2_HI,EntryHi_VPN2_LO,EntryHi_VPN2); - replaceBits(eh,EntryHi_VPN2X_HI,EntryHi_VPN2X_LO,EntryHi_VPN2X); - tc->setMiscRegNoEffect(ArmISA::EntryHi,eh); - MiscReg ctxt = tc->readMiscReg(ArmISA::Context); - replaceBits(ctxt,Context_BadVPN2_HI,Context_BadVPN2_LO,Context_BadVPN2); - tc->setMiscRegNoEffect(ArmISA::Context,ctxt); - - MiscReg stat = tc->readMiscReg(ArmISA::Status); - // Since handler depends on EXL bit, must check EXL bit before setting it!! - if(bits(stat,Status_EXL)==1){ // See MIPS ARM Vol 3, Revision 2, Page 38 - HandlerBase= vect() + tc->readMiscReg(ArmISA::EBase); // Offset 0x180 - General Exception Vector - }else{ - HandlerBase = tc->readMiscReg(ArmISA::EBase); // Offset 0x000 - } - - - setExceptionState(tc,0x3); - - setHandlerPC(HandlerBase,tc); -} - -void TLBModifiedFault::invoke(ThreadContext *tc) -{ - DPRINTF(Arm,"%s encountered.\n", name()); - tc->setMiscRegNoEffect(ArmISA::BadVAddr,BadVAddr); - MiscReg eh = tc->readMiscReg(ArmISA::EntryHi); - replaceBits(eh,EntryHi_ASID_HI,EntryHi_ASID_LO,EntryHi_Asid); - replaceBits(eh,EntryHi_VPN2_HI,EntryHi_VPN2_LO,EntryHi_VPN2); - replaceBits(eh,EntryHi_VPN2X_HI,EntryHi_VPN2X_LO,EntryHi_VPN2X); - tc->setMiscRegNoEffect(ArmISA::EntryHi,eh); - MiscReg ctxt = tc->readMiscReg(ArmISA::Context); - replaceBits(ctxt,Context_BadVPN2_HI,Context_BadVPN2_LO,Context_BadVPN2); - tc->setMiscRegNoEffect(ArmISA::Context,ctxt); - - // Set new PC - Addr HandlerBase; - HandlerBase= vect() + tc->readMiscReg(ArmISA::EBase); // Offset 0x180 - General Exception Vector - setExceptionState(tc,0x1); - setHandlerPC(HandlerBase,tc); - // warn("Exception Handler At: %x , EPC set to %x\n",HandlerBase,tc->readMiscReg(ArmISA::EPC)); - -} - -void SystemCallFault::invoke(ThreadContext *tc) -{ - DPRINTF(Arm,"%s encountered.\n", name()); - setExceptionState(tc,0x8); - - // Set new PC - Addr HandlerBase; - HandlerBase= vect() + tc->readMiscReg(ArmISA::EBase); // Offset 0x180 - General Exception Vector - setHandlerPC(HandlerBase,tc); - // warn("Exception Handler At: %x \n",HandlerBase); - // warn("Exception Handler At: %x , EPC set to %x\n",HandlerBase,tc->readMiscReg(ArmISA::EPC)); - -} - -void InterruptFault::invoke(ThreadContext *tc) -{ -#if FULL_SYSTEM - DPRINTF(Arm,"%s encountered.\n", name()); - setExceptionState(tc,0x0A); - Addr HandlerBase; - - - uint8_t IV = bits(tc->readMiscRegNoEffect(ArmISA::Cause),Cause_IV); - if (IV)// Offset 200 for release 2 - HandlerBase= 0x20 + vect() + tc->readMiscRegNoEffect(ArmISA::EBase); - else//Ofset at 180 for release 1 - HandlerBase= vect() + tc->readMiscRegNoEffect(ArmISA::EBase); - - setHandlerPC(HandlerBase,tc); -#endif -} - -#endif // FULL_SYSTEM - -void ResetFault::invoke(ThreadContext *tc) -{ #if FULL_SYSTEM - DPRINTF(Arm,"%s encountered.\n", name()); - /* All reset activity must be invoked from here */ - tc->setPC(vect()); - tc->setNextPC(vect()+sizeof(MachInst)); - tc->setNextNPC(vect()+sizeof(MachInst)+sizeof(MachInst)); - DPRINTF(Arm,"(%x) - ResetFault::invoke : PC set to %x",(unsigned)tc,(unsigned)tc->readPC()); -#endif - // Set Coprocessor 1 (Floating Point) To Usable - //tc->setMiscReg(ArmISA::Status, ArmISA::Status | 0x20000000); -} - -void ReservedInstructionFault::invoke(ThreadContext *tc) -{ -#if FULL_SYSTEM - DPRINTF(Arm,"%s encountered.\n", name()); - setExceptionState(tc,0x0A); - Addr HandlerBase; - HandlerBase= vect() + tc->readMiscRegNoEffect(ArmISA::EBase); // Offset 0x180 - General Exception Vector - setHandlerPC(HandlerBase,tc); -#else - panic("%s encountered.\n", name()); -#endif -} - -void ThreadFault::invoke(ThreadContext *tc) -{ - DPRINTF(Arm,"%s encountered.\n", name()); - panic("%s encountered.\n", name()); -} - -void DspStateDisabledFault::invoke(ThreadContext *tc) -{ - DPRINTF(Arm,"%s encountered.\n", name()); - panic("%s encountered.\n", name()); +void +ArmFaultBase::invoke(ThreadContext *tc) +{ + // ARM ARM B1.6.3 + FaultBase::invoke(tc); + countStat()++; + + SCTLR sctlr = tc->readMiscReg(MISCREG_SCTLR); + CPSR cpsr = tc->readMiscReg(MISCREG_CPSR); + CPSR saved_cpsr = tc->readMiscReg(MISCREG_CPSR) | + tc->readIntReg(INTREG_CONDCODES); + + + cpsr.mode = nextMode(); + cpsr.it1 = cpsr.it2 = 0; + cpsr.j = 0; + + if (sctlr.te) + cpsr.t = 1; + cpsr.a = cpsr.a | abortDisable(); + cpsr.f = cpsr.f | fiqDisable(); + cpsr.i = 1; + tc->setMiscReg(MISCREG_CPSR, cpsr); + tc->setIntReg(INTREG_LR, tc->readPC() + + (saved_cpsr.t ? thumbPcOffset() : armPcOffset())); + + switch (nextMode()) { + case MODE_FIQ: + tc->setMiscReg(MISCREG_SPSR_FIQ, saved_cpsr); + break; + case MODE_IRQ: + tc->setMiscReg(MISCREG_SPSR_IRQ, saved_cpsr); + break; + case MODE_SVC: + tc->setMiscReg(MISCREG_SPSR_SVC, saved_cpsr); + break; + case MODE_UNDEFINED: + tc->setMiscReg(MISCREG_SPSR_UND, saved_cpsr); + break; + case MODE_ABORT: + tc->setMiscReg(MISCREG_SPSR_ABT, saved_cpsr); + break; + default: + panic("unknown Mode\n"); + } + + DPRINTF(Faults, "Invoking Fault: %s cpsr: %#x PC: %#x lr: %#x\n", name(), cpsr, + tc->readPC(), tc->readIntReg(INTREG_LR)); + tc->setPC(getVector(tc)); + tc->setNextPC(getVector(tc) + cpsr.t ? 2 : 4 ); } +#endif // FULL_SYSTEM -void CoprocessorUnusableFault::invoke(ThreadContext *tc) -{ -#if FULL_SYSTEM - DPRINTF(Arm,"%s encountered.\n", name()); - setExceptionState(tc,0xb); - /* The ID of the coprocessor causing the exception is stored in CoprocessorUnusableFault::coProcID */ - MiscReg cause = tc->readMiscReg(ArmISA::Cause); - replaceBits(cause,Cause_CE_HI,Cause_CE_LO,coProcID); - tc->setMiscRegNoEffect(ArmISA::Cause,cause); +// return via SUBS pc, lr, xxx; rfe, movs, ldm - Addr HandlerBase; - HandlerBase= vect() + tc->readMiscReg(ArmISA::EBase); // Offset 0x180 - General Exception Vector - setHandlerPC(HandlerBase,tc); - // warn("Status: %x, Cause: %x\n",tc->readMiscReg(ArmISA::Status),tc->readMiscReg(ArmISA::Cause)); -#else - warn("%s (CP%d) encountered.\n", name(), coProcID); -#endif -} } // namespace ArmISA diff --git a/src/arch/arm/faults.hh b/src/arch/arm/faults.hh index 28ecd7591..7f8aa66b6 100644 --- a/src/arch/arm/faults.hh +++ b/src/arch/arm/faults.hh @@ -26,548 +26,79 @@ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * - * Authors: Gabe Black - * Stephen Hines + * Authors: Ali Saidi + * Gabe Black */ #ifndef __ARM_FAULTS_HH__ #define __ARM_FAULTS_HH__ +#include "arch/arm/types.hh" +#include "config/full_system.hh" #include "sim/faults.hh" // The design of the "name" and "vect" functions is in sim/faults.hh namespace ArmISA { -typedef const Addr FaultVect; +typedef const Addr FaultOffset; -class ArmFault : public FaultBase +class ArmFaultBase : public FaultBase { protected: - virtual bool skipFaultingInstruction() {return false;} - virtual bool setRestartAddress() {return true;} - public: - Addr BadVAddr; - Addr EntryHi_Asid; - Addr EntryHi_VPN2; - Addr EntryHi_VPN2X; - Addr Context_BadVPN2; -#if FULL_SYSTEM - void invoke(ThreadContext * tc) {}; - void setExceptionState(ThreadContext *,uint8_t); - void setHandlerPC(Addr,ThreadContext *); -#endif - virtual FaultVect vect() = 0; - virtual FaultStat & countStat() = 0; -}; - -class MachineCheckFault : public ArmFault -{ - private: - static FaultName _name; - static FaultVect _vect; - static FaultStat _count; - public: - FaultName name() const {return _name;} - FaultVect vect() {return _vect;} - FaultStat & countStat() {return _count;} - bool isMachineCheckFault() {return true;} -}; - -class NonMaskableInterrupt : public ArmFault -{ - private: - static FaultName _name; - static FaultVect _vect; - static FaultStat _count; - public: - FaultName name() const {return _name;} - FaultVect vect() {return _vect;} - FaultStat & countStat() {return _count;} - bool isNonMaskableInterrupt() {return true;} -}; - -class AlignmentFault : public ArmFault -{ - private: - static FaultName _name; - static FaultVect _vect; - static FaultStat _count; - public: - FaultName name() const {return _name;} - FaultVect vect() {return _vect;} - FaultStat & countStat() {return _count;} - bool isAlignmentFault() {return true;} -}; - -class AddressErrorFault : public ArmFault -{ - private: - static FaultName _name; - static FaultVect _vect; - static FaultStat _count; - public: - FaultName name() const {return _name;} - FaultVect vect() {return _vect;} - FaultStat & countStat() {return _count;} -#if FULL_SYSTEM - void invoke(ThreadContext * tc); -#endif - -}; -class StoreAddressErrorFault : public ArmFault -{ - private: - static FaultName _name; - static FaultVect _vect; - static FaultStat _count; - public: - FaultName name() const {return _name;} - FaultVect vect() {return _vect;} - FaultStat & countStat() {return _count;} -#if FULL_SYSTEM - void invoke(ThreadContext * tc); -#endif - -}; -class UnimplementedOpcodeFault : public ArmFault -{ - private: - static FaultName _name; - static FaultVect _vect; - static FaultStat _count; - public: - FaultName name() const {return _name;} - FaultVect vect() {return _vect;} - FaultStat & countStat() {return _count;} -}; - - -class TLBRefillIFetchFault : public ArmFault -{ - private: - Addr vaddr; - static FaultName _name; - static FaultVect _vect; - static FaultStat _count; - public: - FaultName name() const {return _name;} - FaultVect vect() {return _vect;} - FaultStat & countStat() {return _count;} - void invoke(ThreadContext * tc); -}; -class TLBInvalidIFetchFault : public ArmFault -{ - private: - Addr vaddr; - static FaultName _name; - static FaultVect _vect; - static FaultStat _count; - public: - FaultName name() const {return _name;} - FaultVect vect() {return _vect;} - FaultStat & countStat() {return _count;} - void invoke(ThreadContext * tc); -}; - -class NDtbMissFault : public ArmFault -{ - private: - static FaultName _name; - static FaultVect _vect; - static FaultStat _count; - public: - FaultName name() const {return _name;} - FaultVect vect() {return _vect;} - FaultStat & countStat() {return _count;} -}; - -class PDtbMissFault : public ArmFault -{ - private: - static FaultName _name; - static FaultVect _vect; - static FaultStat _count; - public: - FaultName name() const {return _name;} - FaultVect vect() {return _vect;} - FaultStat & countStat() {return _count;} -}; - -class DtbPageFault : public ArmFault -{ - private: - static FaultName _name; - static FaultVect _vect; - static FaultStat _count; - public: - FaultName name() const {return _name;} - FaultVect vect() {return _vect;} - FaultStat & countStat() {return _count;} -}; - -class DtbAcvFault : public ArmFault -{ - private: - static FaultName _name; - static FaultVect _vect; - static FaultStat _count; - public: - FaultName name() const {return _name;} - FaultVect vect() {return _vect;} - FaultStat & countStat() {return _count;} -}; - -class CacheErrorFault : public ArmFault -{ - private: - Addr vaddr; - static FaultName _name; - static FaultVect _vect; - static FaultStat _count; - public: - FaultName name() const {return _name;} - FaultVect vect() {return _vect;} - FaultStat & countStat() {return _count;} - void invoke(ThreadContext * tc); -}; - - - - -static inline Fault genMachineCheckFault() -{ - return new MachineCheckFault; -} - -static inline Fault genAlignmentFault() -{ - return new AlignmentFault; -} - -class ResetFault : public ArmFault -{ - private: - static FaultName _name; - static FaultVect _vect; - static FaultStat _count; - public: - FaultName name() const {return _name;} - FaultVect vect() {return _vect;} - FaultStat & countStat() {return _count;} - void invoke(ThreadContext * tc); - -}; -class SystemCallFault : public ArmFault -{ - private: - static FaultName _name; - static FaultVect _vect; - static FaultStat _count; - public: - FaultName name() const {return _name;} - FaultVect vect() {return _vect;} - FaultStat & countStat() {return _count;} - void invoke(ThreadContext * tc); -}; - -class SoftResetFault : public ArmFault -{ - private: - static FaultName _name; - static FaultVect _vect; - static FaultStat _count; - public: - FaultName name() const {return _name;} - FaultVect vect() {return _vect;} - FaultStat & countStat() {return _count;} - void invoke(ThreadContext * tc); -}; -class DebugSingleStep : public ArmFault -{ - private: - static FaultName _name; - static FaultVect _vect; - static FaultStat _count; - public: - FaultName name() const {return _name;} - FaultVect vect() {return _vect;} - FaultStat & countStat() {return _count;} - void invoke(ThreadContext * tc); -}; -class DebugInterrupt : public ArmFault -{ - private: - static FaultName _name; - static FaultVect _vect; - static FaultStat _count; - public: - FaultName name() const {return _name;} - FaultVect vect() {return _vect;} - FaultStat & countStat() {return _count;} - void invoke(ThreadContext * tc); -}; - -class CoprocessorUnusableFault : public ArmFault -{ - private: - static FaultName _name; - static FaultVect _vect; - static FaultStat _count; - int coProcID; - public: - FaultName name() const {return _name;} - FaultVect vect() {return _vect;} - FaultStat & countStat() {return _count;} - void invoke(ThreadContext * tc); - CoprocessorUnusableFault(int _procid){ coProcID = _procid;} -}; + Addr getVector(ThreadContext *tc); -class ReservedInstructionFault : public ArmFault -{ - private: - static FaultName _name; - static FaultVect _vect; - static FaultStat _count; public: - FaultName name() const {return _name;} - FaultVect vect() {return _vect;} - FaultStat & countStat() {return _count;} - void invoke(ThreadContext * tc); -}; - -class ThreadFault : public ArmFault -{ - private: - static FaultName _name; - static FaultVect _vect; - static FaultStat _count; - public: - FaultName name() const {return _name;} - FaultVect vect() {return _vect;} - FaultStat & countStat() {return _count;} - void invoke(ThreadContext * tc); -}; + struct FaultVals + { + const FaultName name; + const FaultOffset offset; + const OperatingMode nextMode; + const uint8_t armPcOffset; + const uint8_t thumbPcOffset; + const bool abortDisable; + const bool fiqDisable; + FaultStat count; + }; - -class ArithmeticFault : public ArmFault -{ - protected: - bool skipFaultingInstruction() {return true;} - private: - static FaultName _name; - static FaultVect _vect; - static FaultStat _count; - public: - FaultName name() const {return _name;} - FaultVect vect() {return _vect;} - FaultStat & countStat() {return _count;} #if FULL_SYSTEM - void invoke(ThreadContext * tc); + void invoke(ThreadContext *tc); #endif + virtual FaultStat& countStat() = 0; + virtual FaultOffset offset() = 0; + virtual OperatingMode nextMode() = 0; + virtual uint8_t armPcOffset() = 0; + virtual uint8_t thumbPcOffset() = 0; + virtual bool abortDisable() = 0; + virtual bool fiqDisable() = 0; }; -class InterruptFault : public ArmFault +template<typename T> +class ArmFault : public ArmFaultBase { protected: - bool setRestartAddress() {return false;} - private: - static FaultName _name; - static FaultVect _vect; - static FaultStat _count; - public: - FaultName name() const {return _name;} - FaultVect vect() {return _vect;} - FaultStat & countStat() {return _count;} - -#if FULL_SYSTEM - void invoke(ThreadContext * tc); -#endif - - //void invoke(ThreadContext * tc); -}; - -class TrapFault : public ArmFault -{ - private: - static FaultName _name; - static FaultVect _vect; - static FaultStat _count; - public: - FaultName name() const {return _name;} - FaultVect vect() {return _vect;} - FaultStat & countStat() {return _count;} -#if FULL_SYSTEM - void invoke(ThreadContext * tc); -#endif -}; - -class BreakpointFault : public ArmFault -{ - private: - static FaultName _name; - static FaultVect _vect; - static FaultStat _count; - public: - FaultName name() const {return _name;} - FaultVect vect() {return _vect;} - FaultStat & countStat() {return _count;} -#if FULL_SYSTEM - void invoke(ThreadContext * tc); -#endif -}; - -class ItbRefillFault : public ArmFault -{ - private: - static FaultName _name; - static FaultVect _vect; - static FaultStat _count; - public: - FaultName name() const {return _name;} - FaultVect vect() {return _vect;} - FaultStat & countStat() {return _count;} -#if FULL_SYSTEM - void invoke(ThreadContext * tc); -#endif -}; -class DtbRefillFault : public ArmFault -{ - private: - static FaultName _name; - static FaultVect _vect; - static FaultStat _count; - public: - FaultName name() const {return _name;} - FaultVect vect() {return _vect;} - FaultStat & countStat() {return _count;} -#if FULL_SYSTEM - void invoke(ThreadContext * tc); -#endif -}; - -class ItbPageFault : public ArmFault -{ - private: - static FaultName _name; - static FaultVect _vect; - static FaultStat _count; - public: - FaultName name() const {return _name;} - FaultVect vect() {return _vect;} - FaultStat & countStat() {return _count;} -#if FULL_SYSTEM - void invoke(ThreadContext * tc); -#endif -}; - -class ItbInvalidFault : public ArmFault -{ - private: - static FaultName _name; - static FaultVect _vect; - static FaultStat _count; - public: - FaultName name() const {return _name;} - FaultVect vect() {return _vect;} - FaultStat & countStat() {return _count;} -#if FULL_SYSTEM - void invoke(ThreadContext * tc); -#endif - -}; -class TLBModifiedFault : public ArmFault -{ - private: - static FaultName _name; - static FaultVect _vect; - static FaultStat _count; - public: - FaultName name() const {return _name;} - FaultVect vect() {return _vect;} - FaultStat & countStat() {return _count;} -#if FULL_SYSTEM - void invoke(ThreadContext * tc); -#endif - -}; + static FaultVals vals; -class DtbInvalidFault : public ArmFault -{ - private: - static FaultName _name; - static FaultVect _vect; - static FaultStat _count; public: - FaultName name() const {return _name;} - FaultVect vect() {return _vect;} - FaultStat & countStat() {return _count;} -#if FULL_SYSTEM - void invoke(ThreadContext * tc); -#endif - + FaultName name() const { return vals.name; } + FaultStat & countStat() {return vals.count;} + FaultOffset offset() { return vals.offset; } + OperatingMode nextMode() { return vals.nextMode; } + uint8_t armPcOffset() { return vals.armPcOffset; } + uint8_t thumbPcOffset() { return vals.thumbPcOffset; } + bool abortDisable() { return vals.abortDisable; } + bool fiqDisable() { return vals.fiqDisable; } }; -class FloatEnableFault : public ArmFault -{ - private: - static FaultName _name; - static FaultVect _vect; - static FaultStat _count; - public: - FaultName name() const {return _name;} - FaultVect vect() {return _vect;} - FaultStat & countStat() {return _count;} -}; -class ItbMissFault : public ArmFault -{ - private: - static FaultName _name; - static FaultVect _vect; - static FaultStat _count; - public: - FaultName name() const {return _name;} - FaultVect vect() {return _vect;} - FaultStat & countStat() {return _count;} -}; +class Reset : public ArmFault<Reset> {}; +class UndefinedInstruction : public ArmFault<UndefinedInstruction> {}; +class SupervisorCall : public ArmFault<SupervisorCall> {}; +class PrefetchAbort : public ArmFault<PrefetchAbort> {}; +class DataAbort : public ArmFault<DataAbort> {}; +class Interrupt : public ArmFault<Interrupt> {}; +class FastInterrupt : public ArmFault<FastInterrupt> {}; -class ItbAcvFault : public ArmFault -{ - private: - static FaultName _name; - static FaultVect _vect; - static FaultStat _count; - public: - FaultName name() const {return _name;} - FaultVect vect() {return _vect;} - FaultStat & countStat() {return _count;} -}; - -class IntegerOverflowFault : public ArmFault -{ - private: - static FaultName _name; - static FaultVect _vect; - static FaultStat _count; - public: - FaultName name() const {return _name;} - FaultVect vect() {return _vect;} - FaultStat & countStat() {return _count;} -}; - -class DspStateDisabledFault : public ArmFault -{ - private: - static FaultName _name; - static FaultVect _vect; - static FaultStat _count; - public: - FaultName name() const {return _name;} - FaultVect vect() {return _vect;} - FaultStat & countStat() {return _count;} - void invoke(ThreadContext * tc); -}; } // ArmISA namespace diff --git a/src/arch/arm/insts/macromem.hh b/src/arch/arm/insts/macromem.hh index 541c9e3f5..714b8bb7e 100644 --- a/src/arch/arm/insts/macromem.hh +++ b/src/arch/arm/insts/macromem.hh @@ -84,33 +84,20 @@ class MicroMemOp : public MicroIntOp */ class ArmMacroMemoryOp : public PredMacroOp { - protected: + protected: /// Memory request flags. See mem_req_base.hh. unsigned memAccessFlags; uint32_t reglist; uint32_t ones; - uint32_t puswl, - prepost, - up, - psruser, - writeback, - loadop; ArmMacroMemoryOp(const char *mnem, ExtMachInst _machInst, OpClass __opClass) - : PredMacroOp(mnem, _machInst, __opClass), - memAccessFlags(0), - reglist(machInst.regList), ones(0), - puswl(machInst.puswl), - prepost(machInst.puswl.prepost), - up(machInst.puswl.up), - psruser(machInst.puswl.psruser), - writeback(machInst.puswl.writeback), - loadop(machInst.puswl.loadOp) + : PredMacroOp(mnem, _machInst, __opClass), memAccessFlags(0), + reglist(machInst.regList), ones(0) { ones = number_of_ones(reglist); - numMicroops = ones + writeback + 1; + numMicroops = ones + machInst.puswl.writeback + 1; // Remember that writeback adds a uop microOps = new StaticInstPtr[numMicroops]; } @@ -121,7 +108,7 @@ class ArmMacroMemoryOp : public PredMacroOp */ class ArmMacroFPAOp : public PredMacroOp { - protected: + protected: uint32_t puswl, prepost, up, @@ -150,7 +137,7 @@ class ArmMacroFPAOp : public PredMacroOp */ class ArmMacroFMOp : public PredMacroOp { - protected: + protected: uint32_t punwl, prepost, up, diff --git a/src/arch/arm/insts/static_inst.cc b/src/arch/arm/insts/static_inst.cc index df2d5de25..bf7a38c58 100644 --- a/src/arch/arm/insts/static_inst.cc +++ b/src/arch/arm/insts/static_inst.cc @@ -27,8 +27,10 @@ * Authors: Stephen Hines */ +#include "arch/arm/faults.hh" #include "arch/arm/insts/static_inst.hh" #include "base/condcodes.hh" +#include "base/cprintf.hh" #include "base/loader/symtab.hh" namespace ArmISA @@ -62,7 +64,7 @@ ArmStaticInst::shift_rm_imm(uint32_t base, uint32_t shamt, else return (base << (32 - shamt)) | (base >> shamt); default: - fprintf(stderr, "Unhandled shift type\n"); + ccprintf(std::cerr, "Unhandled shift type\n"); exit(1); break; } @@ -101,7 +103,7 @@ ArmStaticInst::shift_rm_rs(uint32_t base, uint32_t shamt, else return (base << (32 - shamt)) | (base >> shamt); default: - fprintf(stderr, "Unhandled shift type\n"); + ccprintf(std::cerr, "Unhandled shift type\n"); exit(1); break; } @@ -141,7 +143,7 @@ ArmStaticInst::shift_carry_imm(uint32_t base, uint32_t shamt, else return (base >> (shamt - 1)) & 1; default: - fprintf(stderr, "Unhandled shift type\n"); + ccprintf(std::cerr, "Unhandled shift type\n"); exit(1); break; } @@ -182,7 +184,7 @@ ArmStaticInst::shift_carry_rs(uint32_t base, uint32_t shamt, shamt = 32; return (base >> (shamt - 1)) & 1; default: - fprintf(stderr, "Unhandled shift type\n"); + ccprintf(std::cerr, "Unhandled shift type\n"); exit(1); break; } diff --git a/src/arch/arm/insts/static_inst.hh b/src/arch/arm/insts/static_inst.hh index c963c1827..f2881c3b6 100644 --- a/src/arch/arm/insts/static_inst.hh +++ b/src/arch/arm/insts/static_inst.hh @@ -74,6 +74,56 @@ class ArmStaticInst : public StaticInst void printDataInst(std::ostream &os, bool withImm) const; std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const; + + static uint32_t + cpsrWriteByInstr(CPSR cpsr, uint32_t val, + uint8_t byteMask, bool affectState) + { + bool privileged = (cpsr.mode != MODE_USER); + + uint32_t bitMask = 0; + + if (bits(byteMask, 3)) { + unsigned lowIdx = affectState ? 24 : 27; + bitMask = bitMask | mask(31, lowIdx); + } + if (bits(byteMask, 2)) { + bitMask = bitMask | mask(19, 16); + } + if (bits(byteMask, 1)) { + unsigned highIdx = affectState ? 15 : 9; + unsigned lowIdx = privileged ? 8 : 9; + bitMask = bitMask | mask(highIdx, lowIdx); + } + if (bits(byteMask, 0)) { + if (privileged) { + bitMask = bitMask | mask(7, 6); + bitMask = bitMask | mask(5); + } + if (affectState) + bitMask = bitMask | (1 << 5); + } + + return ((uint32_t)cpsr & ~bitMask) | (val & bitMask); + } + + static uint32_t + spsrWriteByInstr(uint32_t spsr, uint32_t val, + uint8_t byteMask, bool affectState) + { + uint32_t bitMask = 0; + + if (bits(byteMask, 3)) + bitMask = bitMask | mask(31, 24); + if (bits(byteMask, 2)) + bitMask = bitMask | mask(19, 16); + if (bits(byteMask, 1)) + bitMask = bitMask | mask(15, 8); + if (bits(byteMask, 0)) + bitMask = bitMask | mask(7, 0); + + return ((spsr & ~bitMask) | (val & bitMask)); + } }; } diff --git a/src/mem/slicc/ast/AST.cc b/src/arch/arm/interrupts.cc index e893c453a..a47ebc75d 100644 --- a/src/mem/slicc/ast/AST.cc +++ b/src/arch/arm/interrupts.cc @@ -1,6 +1,5 @@ - /* - * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood + * Copyright (c) 2009 ARM Limited * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -25,15 +24,14 @@ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/* - * AST.C - * - * Description: See AST.hh - * - * $Id$ * + * Authors: Ali Saidi */ -#include "mem/slicc/ast/AST.hh" +#include "arch/arm/interrupts.hh" + +ArmISA::Interrupts * +ArmInterruptsParams::create() +{ + return new ArmISA::Interrupts(this); +} diff --git a/src/mem/slicc/ast/LiteralExprAST.hh b/src/arch/arm/interrupts.hh index c895fa9ae..189341d6b 100644 --- a/src/mem/slicc/ast/LiteralExprAST.hh +++ b/src/arch/arm/interrupts.hh @@ -1,6 +1,6 @@ - /* - * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood + * Copyright (c) 2006 The Regents of The University of Michigan + * Copyright (c) 2009 ARM Limited * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -25,59 +25,97 @@ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/* - * LiteralExprAST.hh - * - * Description: - * - * $Id: LiteralExprAST.hh,v 3.1 2001/12/12 01:00:20 milo Exp $ * + * Authors: Ali Saidi */ -#ifndef LITERALEXPRAST_H -#define LITERALEXPRAST_H +#ifndef __ARCH_ARM_INTERRUPT_HH__ +#define __ARCH_ARM_INTERRUPT_HH__ -#include "mem/slicc/slicc_global.hh" -#include "mem/slicc/ast/ExprAST.hh" +#include "arch/arm/faults.hh" +#include "arch/arm/isa_traits.hh" +#include "arch/arm/registers.hh" +#include "cpu/thread_context.hh" +#include "params/ArmInterrupts.hh" +#include "sim/sim_object.hh" +namespace ArmISA +{ -class LiteralExprAST : public ExprAST { -public: - // Constructors - LiteralExprAST(string* lit_ptr, string type) : ExprAST() { m_lit_ptr = lit_ptr; m_type = type; } +class Interrupts : public SimObject +{ + private: + BaseCPU * cpu; - // Destructor - ~LiteralExprAST() { delete m_lit_ptr; } + uint64_t intStatus; - // Public Methods - Type* generate(string& code) const; - void print(ostream& out) const { out << "[Literal: " << *m_lit_ptr << "]"; } -private: - // Private Methods + public: - // Private copy constructor and assignment operator - LiteralExprAST(const LiteralExprAST& obj); - LiteralExprAST& operator=(const LiteralExprAST& obj); + void + setCPU(BaseCPU * _cpu) + { + cpu = _cpu; + } - // Data Members (m_ prefix) - string* m_lit_ptr; - string m_type; -}; + typedef ArmInterruptsParams Params; -// Output operator declaration -ostream& operator<<(ostream& out, const LiteralExprAST& obj); + const Params * + params() const + { + return dynamic_cast<const Params *>(_params); + } -// ******************* Definitions ******************* + Interrupts(Params * p) : SimObject(p), cpu(NULL) + { + clearAll(); + } -// Output operator definition -extern inline -ostream& operator<<(ostream& out, const LiteralExprAST& obj) -{ - obj.print(out); - out << flush; - return out; -} -#endif //LITERALEXPRAST_H + void + post(int int_num, int index) + { + } + + void + clear(int int_num, int index) + { + } + + void + clearAll() + { + intStatus = 0; + } + + bool + checkInterrupts(ThreadContext *tc) const + { + return intStatus; + } + + Fault + getInterrupt(ThreadContext *tc) + { + warn_once("ARM Interrupts not handled\n"); + return NoFault; + } + + void + updateIntrInfo(ThreadContext *tc) + { + + } + + void + serialize(std::ostream &os) + { + } + + void + unserialize(Checkpoint *cp, const std::string §ion) + { + } +}; +} // namespace ARM_ISA + +#endif // __ARCH_ARM_INTERRUPT_HH__ diff --git a/src/arch/arm/intregs.hh b/src/arch/arm/intregs.hh new file mode 100644 index 000000000..15499601a --- /dev/null +++ b/src/arch/arm/intregs.hh @@ -0,0 +1,337 @@ +/* + * Copyright (c) 2009 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Gabe Black + */ + +#include <assert.h> + +#ifndef __ARCH_ARM_INTREGS_HH__ +#define __ARCH_ARM_INTREGS_HH__ + +namespace ArmISA +{ + +enum IntRegIndex +{ + /* All the unique register indices. */ + INTREG_R0, + INTREG_R1, + INTREG_R2, + INTREG_R3, + INTREG_R4, + INTREG_R5, + INTREG_R6, + INTREG_R7, + INTREG_R8, + INTREG_R9, + INTREG_R10, + INTREG_R11, + INTREG_R12, + INTREG_R13, + INTREG_SP = INTREG_R13, + INTREG_R14, + INTREG_LR = INTREG_R14, + INTREG_R15, + INTREG_PC = INTREG_R15, + + INTREG_R13_SVC, + INTREG_SP_SVC = INTREG_R13_SVC, + INTREG_R14_SVC, + INTREG_LR_SVC = INTREG_R14_SVC, + + INTREG_R13_MON, + INTREG_SP_MON = INTREG_R13_MON, + INTREG_R14_MON, + INTREG_LR_MON = INTREG_R14_MON, + + INTREG_R13_ABT, + INTREG_SP_ABT = INTREG_R13_ABT, + INTREG_R14_ABT, + INTREG_LR_ABT = INTREG_R14_ABT, + + INTREG_R13_UND, + INTREG_SP_UND = INTREG_R13_UND, + INTREG_R14_UND, + INTREG_LR_UND = INTREG_R14_UND, + + INTREG_R13_IRQ, + INTREG_SP_IRQ = INTREG_R13_IRQ, + INTREG_R14_IRQ, + INTREG_LR_IRQ = INTREG_R14_IRQ, + + INTREG_R8_FIQ, + INTREG_R9_FIQ, + INTREG_R10_FIQ, + INTREG_R11_FIQ, + INTREG_R12_FIQ, + INTREG_R13_FIQ, + INTREG_SP_FIQ = INTREG_R13_FIQ, + INTREG_R14_FIQ, + INTREG_LR_FIQ = INTREG_R14_FIQ, + + INTREG_ZERO, // Dummy zero reg since there has to be one. + INTREG_UREG0, + INTREG_RHI, + INTREG_RLO, + INTREG_CONDCODES, + + NUM_INTREGS, + NUM_ARCH_INTREGS = INTREG_PC + 1, + + /* All the aliased indexes. */ + + /* USR mode */ + INTREG_R0_USR = INTREG_R0, + INTREG_R1_USR = INTREG_R1, + INTREG_R2_USR = INTREG_R2, + INTREG_R3_USR = INTREG_R3, + INTREG_R4_USR = INTREG_R4, + INTREG_R5_USR = INTREG_R5, + INTREG_R6_USR = INTREG_R6, + INTREG_R7_USR = INTREG_R7, + INTREG_R8_USR = INTREG_R8, + INTREG_R9_USR = INTREG_R9, + INTREG_R10_USR = INTREG_R10, + INTREG_R11_USR = INTREG_R11, + INTREG_R12_USR = INTREG_R12, + INTREG_R13_USR = INTREG_R13, + INTREG_SP_USR = INTREG_SP, + INTREG_R14_USR = INTREG_R14, + INTREG_LR_USR = INTREG_LR, + INTREG_R15_USR = INTREG_R15, + INTREG_PC_USR = INTREG_PC, + + /* SVC mode */ + INTREG_R0_SVC = INTREG_R0, + INTREG_R1_SVC = INTREG_R1, + INTREG_R2_SVC = INTREG_R2, + INTREG_R3_SVC = INTREG_R3, + INTREG_R4_SVC = INTREG_R4, + INTREG_R5_SVC = INTREG_R5, + INTREG_R6_SVC = INTREG_R6, + INTREG_R7_SVC = INTREG_R7, + INTREG_R8_SVC = INTREG_R8, + INTREG_R9_SVC = INTREG_R9, + INTREG_R10_SVC = INTREG_R10, + INTREG_R11_SVC = INTREG_R11, + INTREG_R12_SVC = INTREG_R12, + INTREG_PC_SVC = INTREG_PC, + INTREG_R15_SVC = INTREG_R15, + + /* MON mode */ + INTREG_R0_MON = INTREG_R0, + INTREG_R1_MON = INTREG_R1, + INTREG_R2_MON = INTREG_R2, + INTREG_R3_MON = INTREG_R3, + INTREG_R4_MON = INTREG_R4, + INTREG_R5_MON = INTREG_R5, + INTREG_R6_MON = INTREG_R6, + INTREG_R7_MON = INTREG_R7, + INTREG_R8_MON = INTREG_R8, + INTREG_R9_MON = INTREG_R9, + INTREG_R10_MON = INTREG_R10, + INTREG_R11_MON = INTREG_R11, + INTREG_R12_MON = INTREG_R12, + INTREG_PC_MON = INTREG_PC, + INTREG_R15_MON = INTREG_R15, + + /* ABT mode */ + INTREG_R0_ABT = INTREG_R0, + INTREG_R1_ABT = INTREG_R1, + INTREG_R2_ABT = INTREG_R2, + INTREG_R3_ABT = INTREG_R3, + INTREG_R4_ABT = INTREG_R4, + INTREG_R5_ABT = INTREG_R5, + INTREG_R6_ABT = INTREG_R6, + INTREG_R7_ABT = INTREG_R7, + INTREG_R8_ABT = INTREG_R8, + INTREG_R9_ABT = INTREG_R9, + INTREG_R10_ABT = INTREG_R10, + INTREG_R11_ABT = INTREG_R11, + INTREG_R12_ABT = INTREG_R12, + INTREG_PC_ABT = INTREG_PC, + INTREG_R15_ABT = INTREG_R15, + + /* UND mode */ + INTREG_R0_UND = INTREG_R0, + INTREG_R1_UND = INTREG_R1, + INTREG_R2_UND = INTREG_R2, + INTREG_R3_UND = INTREG_R3, + INTREG_R4_UND = INTREG_R4, + INTREG_R5_UND = INTREG_R5, + INTREG_R6_UND = INTREG_R6, + INTREG_R7_UND = INTREG_R7, + INTREG_R8_UND = INTREG_R8, + INTREG_R9_UND = INTREG_R9, + INTREG_R10_UND = INTREG_R10, + INTREG_R11_UND = INTREG_R11, + INTREG_R12_UND = INTREG_R12, + INTREG_PC_UND = INTREG_PC, + INTREG_R15_UND = INTREG_R15, + + /* IRQ mode */ + INTREG_R0_IRQ = INTREG_R0, + INTREG_R1_IRQ = INTREG_R1, + INTREG_R2_IRQ = INTREG_R2, + INTREG_R3_IRQ = INTREG_R3, + INTREG_R4_IRQ = INTREG_R4, + INTREG_R5_IRQ = INTREG_R5, + INTREG_R6_IRQ = INTREG_R6, + INTREG_R7_IRQ = INTREG_R7, + INTREG_R8_IRQ = INTREG_R8, + INTREG_R9_IRQ = INTREG_R9, + INTREG_R10_IRQ = INTREG_R10, + INTREG_R11_IRQ = INTREG_R11, + INTREG_R12_IRQ = INTREG_R12, + INTREG_PC_IRQ = INTREG_PC, + INTREG_R15_IRQ = INTREG_R15, + + /* FIQ mode */ + INTREG_R0_FIQ = INTREG_R0, + INTREG_R1_FIQ = INTREG_R1, + INTREG_R2_FIQ = INTREG_R2, + INTREG_R3_FIQ = INTREG_R3, + INTREG_R4_FIQ = INTREG_R4, + INTREG_R5_FIQ = INTREG_R5, + INTREG_R6_FIQ = INTREG_R6, + INTREG_R7_FIQ = INTREG_R7, + INTREG_PC_FIQ = INTREG_PC, + INTREG_R15_FIQ = INTREG_R15, +}; + +typedef IntRegIndex IntRegMap[NUM_ARCH_INTREGS]; + +const IntRegMap IntRegUsrMap = { + INTREG_R0_USR, INTREG_R1_USR, INTREG_R2_USR, INTREG_R3_USR, + INTREG_R4_USR, INTREG_R5_USR, INTREG_R6_USR, INTREG_R7_USR, + INTREG_R8_USR, INTREG_R9_USR, INTREG_R10_USR, INTREG_R11_USR, + INTREG_R12_USR, INTREG_R13_USR, INTREG_R14_USR, INTREG_R15_USR +}; + +static inline IntRegIndex +INTREG_USR(unsigned index) +{ + assert(index < NUM_ARCH_INTREGS); + return IntRegUsrMap[index]; +} + +const IntRegMap IntRegSvcMap = { + INTREG_R0_SVC, INTREG_R1_SVC, INTREG_R2_SVC, INTREG_R3_SVC, + INTREG_R4_SVC, INTREG_R5_SVC, INTREG_R6_SVC, INTREG_R7_SVC, + INTREG_R8_SVC, INTREG_R9_SVC, INTREG_R10_SVC, INTREG_R11_SVC, + INTREG_R12_SVC, INTREG_R13_SVC, INTREG_R14_SVC, INTREG_R15_SVC +}; + +static inline IntRegIndex +INTREG_SVC(unsigned index) +{ + assert(index < NUM_ARCH_INTREGS); + return IntRegSvcMap[index]; +} + +const IntRegMap IntRegMonMap = { + INTREG_R0_MON, INTREG_R1_MON, INTREG_R2_MON, INTREG_R3_MON, + INTREG_R4_MON, INTREG_R5_MON, INTREG_R6_MON, INTREG_R7_MON, + INTREG_R8_MON, INTREG_R9_MON, INTREG_R10_MON, INTREG_R11_MON, + INTREG_R12_MON, INTREG_R13_MON, INTREG_R14_MON, INTREG_R15_MON +}; + +static inline IntRegIndex +INTREG_MON(unsigned index) +{ + assert(index < NUM_ARCH_INTREGS); + return IntRegMonMap[index]; +} + +const IntRegMap IntRegAbtMap = { + INTREG_R0_ABT, INTREG_R1_ABT, INTREG_R2_ABT, INTREG_R3_ABT, + INTREG_R4_ABT, INTREG_R5_ABT, INTREG_R6_ABT, INTREG_R7_ABT, + INTREG_R8_ABT, INTREG_R9_ABT, INTREG_R10_ABT, INTREG_R11_ABT, + INTREG_R12_ABT, INTREG_R13_ABT, INTREG_R14_ABT, INTREG_R15_ABT +}; + +static inline IntRegIndex +INTREG_ABT(unsigned index) +{ + assert(index < NUM_ARCH_INTREGS); + return IntRegAbtMap[index]; +} + +const IntRegMap IntRegUndMap = { + INTREG_R0_UND, INTREG_R1_UND, INTREG_R2_UND, INTREG_R3_UND, + INTREG_R4_UND, INTREG_R5_UND, INTREG_R6_UND, INTREG_R7_UND, + INTREG_R8_UND, INTREG_R9_UND, INTREG_R10_UND, INTREG_R11_UND, + INTREG_R12_UND, INTREG_R13_UND, INTREG_R14_UND, INTREG_R15_UND +}; + +static inline IntRegIndex +INTREG_UND(unsigned index) +{ + assert(index < NUM_ARCH_INTREGS); + return IntRegUndMap[index]; +} + +const IntRegMap IntRegIrqMap = { + INTREG_R0_IRQ, INTREG_R1_IRQ, INTREG_R2_IRQ, INTREG_R3_IRQ, + INTREG_R4_IRQ, INTREG_R5_IRQ, INTREG_R6_IRQ, INTREG_R7_IRQ, + INTREG_R8_IRQ, INTREG_R9_IRQ, INTREG_R10_IRQ, INTREG_R11_IRQ, + INTREG_R12_IRQ, INTREG_R13_IRQ, INTREG_R14_IRQ, INTREG_R15_IRQ +}; + +static inline IntRegIndex +INTREG_IRQ(unsigned index) +{ + assert(index < NUM_ARCH_INTREGS); + return IntRegIrqMap[index]; +} + +const IntRegMap IntRegFiqMap = { + INTREG_R0_FIQ, INTREG_R1_FIQ, INTREG_R2_FIQ, INTREG_R3_FIQ, + INTREG_R4_FIQ, INTREG_R5_FIQ, INTREG_R6_FIQ, INTREG_R7_FIQ, + INTREG_R8_FIQ, INTREG_R9_FIQ, INTREG_R10_FIQ, INTREG_R11_FIQ, + INTREG_R12_FIQ, INTREG_R13_FIQ, INTREG_R14_FIQ, INTREG_R15_FIQ +}; + +static inline IntRegIndex +INTREG_FIQ(unsigned index) +{ + assert(index < NUM_ARCH_INTREGS); + return IntRegFiqMap[index]; +} + +static inline IntRegIndex +intRegForceUser(unsigned index) +{ + assert(index < NUM_ARCH_INTREGS); + + return index == 15 ? (IntRegIndex)15 : (IntRegIndex)(index + NUM_INTREGS); +} + +} + +#endif diff --git a/src/arch/arm/isa.hh b/src/arch/arm/isa.hh index 2315afa9e..905eb0183 100644 --- a/src/arch/arm/isa.hh +++ b/src/arch/arm/isa.hh @@ -44,6 +44,38 @@ namespace ArmISA { protected: MiscReg miscRegs[NumMiscRegs]; + const IntRegIndex *intRegMap; + + void + updateRegMap(CPSR cpsr) + { + switch (cpsr.mode) { + case MODE_USER: + case MODE_SYSTEM: + intRegMap = IntRegUsrMap; + break; + case MODE_FIQ: + intRegMap = IntRegFiqMap; + break; + case MODE_IRQ: + intRegMap = IntRegIrqMap; + break; + case MODE_SVC: + intRegMap = IntRegSvcMap; + break; + case MODE_MON: + intRegMap = IntRegMonMap; + break; + case MODE_ABORT: + intRegMap = IntRegAbtMap; + break; + case MODE_UNDEFINED: + intRegMap = IntRegUndMap; + break; + default: + panic("Unrecognized mode setting in CPSR.\n"); + } + } public: void clear() @@ -52,6 +84,15 @@ namespace ArmISA CPSR cpsr = 0; cpsr.mode = MODE_USER; miscRegs[MISCREG_CPSR] = cpsr; + updateRegMap(cpsr); + + SCTLR sctlr = 0; + sctlr.nmfi = 1; + sctlr.rao1 = 1; + sctlr.rao2 = 1; + sctlr.rao3 = 1; + sctlr.rao4 = 1; + //XXX We need to initialize the rest of the state. } @@ -59,34 +100,94 @@ namespace ArmISA readMiscRegNoEffect(int misc_reg) { assert(misc_reg < NumMiscRegs); + if (misc_reg == MISCREG_SPSR) { + CPSR cpsr = miscRegs[MISCREG_CPSR]; + switch (cpsr.mode) { + case MODE_USER: + return miscRegs[MISCREG_SPSR]; + case MODE_FIQ: + return miscRegs[MISCREG_SPSR_FIQ]; + case MODE_IRQ: + return miscRegs[MISCREG_SPSR_IRQ]; + case MODE_SVC: + return miscRegs[MISCREG_SPSR_SVC]; + case MODE_MON: + return miscRegs[MISCREG_SPSR_MON]; + case MODE_ABORT: + return miscRegs[MISCREG_SPSR_ABT]; + case MODE_UNDEFINED: + return miscRegs[MISCREG_SPSR_UND]; + default: + return miscRegs[MISCREG_SPSR]; + } + } return miscRegs[misc_reg]; } MiscReg readMiscReg(int misc_reg, ThreadContext *tc) { - assert(misc_reg < NumMiscRegs); - return miscRegs[misc_reg]; + return readMiscRegNoEffect(misc_reg); } void setMiscRegNoEffect(int misc_reg, const MiscReg &val) { assert(misc_reg < NumMiscRegs); + if (misc_reg == MISCREG_SPSR) { + CPSR cpsr = miscRegs[MISCREG_CPSR]; + switch (cpsr.mode) { + case MODE_USER: + miscRegs[MISCREG_SPSR] = val; + return; + case MODE_FIQ: + miscRegs[MISCREG_SPSR_FIQ] = val; + return; + case MODE_IRQ: + miscRegs[MISCREG_SPSR_IRQ] = val; + return; + case MODE_SVC: + miscRegs[MISCREG_SPSR_SVC] = val; + return; + case MODE_MON: + miscRegs[MISCREG_SPSR_MON] = val; + return; + case MODE_ABORT: + miscRegs[MISCREG_SPSR_ABT] = val; + return; + case MODE_UNDEFINED: + miscRegs[MISCREG_SPSR_UND] = val; + return; + default: + miscRegs[MISCREG_SPSR] = val; + return; + } + } miscRegs[misc_reg] = val; } void setMiscReg(int misc_reg, const MiscReg &val, ThreadContext *tc) { - assert(misc_reg < NumMiscRegs); - miscRegs[misc_reg] = val; + if (misc_reg == MISCREG_CPSR) { + updateRegMap(val); + } + return setMiscRegNoEffect(misc_reg, val); } int flattenIntIndex(int reg) { - return reg; + assert(reg >= 0); + if (reg < NUM_ARCH_INTREGS) { + return intRegMap[reg]; + } else if (reg < NUM_INTREGS) { + return reg; + } else { + reg -= NUM_INTREGS; + assert(reg < NUM_ARCH_INTREGS); + return reg; + } } int @@ -95,9 +196,10 @@ namespace ArmISA return reg; } - void serialize(std::ostream &os) + void serialize(EventManager *em, std::ostream &os) {} - void unserialize(Checkpoint *cp, const std::string §ion) + void unserialize(EventManager *em, Checkpoint *cp, + const std::string §ion) {} ISA() diff --git a/src/arch/arm/isa/bitfields.isa b/src/arch/arm/isa/bitfields.isa index 5785939cc..8ff819983 100644 --- a/src/arch/arm/isa/bitfields.isa +++ b/src/arch/arm/isa/bitfields.isa @@ -38,14 +38,18 @@ def bitfield ENCODING encoding; def bitfield OPCODE opcode; def bitfield MEDIA_OPCODE mediaOpcode; def bitfield MEDIA_OPCODE2 mediaOpcode2; +def bitfield USEIMM useImm; def bitfield OPCODE_24 opcode24; def bitfield OPCODE_23_20 opcode23_20; def bitfield OPCODE_23_21 opcode23_21; def bitfield OPCODE_22 opcode22; +def bitfield OPCODE_20 opcode20; def bitfield OPCODE_19 opcode19; +def bitfield OPCODE_18 opcode18; def bitfield OPCODE_15_12 opcode15_12; def bitfield OPCODE_15 opcode15; def bitfield MISC_OPCODE miscOpcode; +def bitfield OPC2 opc2; def bitfield OPCODE_7 opcode7; def bitfield OPCODE_4 opcode4; diff --git a/src/arch/arm/isa/decoder.isa b/src/arch/arm/isa/decoder.isa index a999b52e9..ff20c6107 100644 --- a/src/arch/arm/isa/decoder.isa +++ b/src/arch/arm/isa/decoder.isa @@ -51,20 +51,25 @@ format DataOp { resTemp = ((uint64_t)Rm)*((uint64_t)Rs); Rd = (uint32_t)(resTemp & 0xffffffff); Rn = (uint32_t)(resTemp >> 32); - }}); - 0x5: WarnUnimpl::smlal(); + }}, llbit); + 0x5: smlal({{ + resTemp = ((int64_t)Rm) * ((int64_t)Rs); + resTemp += (((uint64_t)Rn) << 32) | ((uint64_t)Rd); + Rd = (uint32_t)(resTemp & 0xffffffff); + Rn = (uint32_t)(resTemp >> 32); + }}, llbit); 0x6: smull({{ resTemp = ((int64_t)(int32_t)Rm)* ((int64_t)(int32_t)Rs); Rd = (int32_t)(resTemp & 0xffffffff); Rn = (int32_t)(resTemp >> 32); - }}); + }}, llbit); 0x7: umlal({{ resTemp = ((uint64_t)Rm)*((uint64_t)Rs); resTemp += ((uint64_t)Rn << 32)+((uint64_t)Rd); Rd = (uint32_t)(resTemp & 0xffffffff); Rn = (uint32_t)(resTemp >> 32); - }}); + }}, llbit); } 1: decode PUBWL { 0x10: WarnUnimpl::swp(); @@ -91,9 +96,9 @@ format DataOp { 0x2: sub({{ Rd = resTemp = Rn - op2; }}, sub); 0x3: rsb({{ Rd = resTemp = op2 - Rn; }}, rsb); 0x4: add({{ Rd = resTemp = Rn + op2; }}, add); - 0x5: adc({{ Rd = resTemp = Rn + op2 + Cpsr<29:>; }}, add); - 0x6: sbc({{ Rd = resTemp = Rn - op2 - !Cpsr<29:>; }}, sub); - 0x7: rsc({{ Rd = resTemp = op2 - Rn - !Cpsr<29:>; }}, rsb); + 0x5: adc({{ Rd = resTemp = Rn + op2 + CondCodes<29:>; }}, add); + 0x6: sbc({{ Rd = resTemp = Rn - op2 - !CondCodes<29:>; }}, sub); + 0x7: rsc({{ Rd = resTemp = op2 - Rn - !CondCodes<29:>; }}, rsb); 0x8: tst({{ resTemp = Rn & op2; }}); 0x9: teq({{ resTemp = Rn ^ op2; }}); 0xa: cmp({{ resTemp = Rn - op2; }}, sub); @@ -105,10 +110,37 @@ format DataOp { } 1: decode MISC_OPCODE { 0x0: decode OPCODE { - 0x8: WarnUnimpl::mrs_cpsr(); - 0x9: WarnUnimpl::msr_cpsr(); - 0xa: WarnUnimpl::mrs_spsr(); - 0xb: WarnUnimpl::msr_spsr(); + 0x8: PredOp::mrs_cpsr({{ + Rd = (Cpsr | CondCodes) & 0xF8FF03DF; + }}); + 0x9: decode USEIMM { + // The mask field is the same as the RN index. + 0: PredOp::msr_cpsr_reg({{ + uint32_t newCpsr = + cpsrWriteByInstr(Cpsr | CondCodes, + Rm, RN, false); + Cpsr = ~CondCodesMask & newCpsr; + CondCodes = CondCodesMask & newCpsr; + }}); + 1: PredImmOp::msr_cpsr_imm({{ + uint32_t newCpsr = + cpsrWriteByInstr(Cpsr | CondCodes, + rotated_imm, RN, false); + Cpsr = ~CondCodesMask & newCpsr; + CondCodes = CondCodesMask & newCpsr; + }}); + } + 0xa: PredOp::mrs_spsr({{ Rd = Spsr; }}); + 0xb: decode USEIMM { + // The mask field is the same as the RN index. + 0: PredOp::msr_spsr_reg({{ + Spsr = spsrWriteByInstr(Spsr, Rm, RN, false); + }}); + 1: PredImmOp::msr_spsr_imm({{ + Spsr = spsrWriteByInstr(Spsr, rotated_imm, + RN, false); + }}); + } } 0x1: decode OPCODE { 0x9: BranchExchange::bx({{ }}); @@ -129,28 +161,32 @@ format DataOp { 0xb: WarnUnimpl::qdsub(); } 0x8: decode OPCODE { - 0x8: WarnUnimpl::smlabb(); + 0x8: smlabb({{ Rn = resTemp = sext<16>(Rm<15:0>) * sext<16>(Rs<15:0>) + Rd; }}, overflow); 0x9: WarnUnimpl::smlalbb(); 0xa: WarnUnimpl::smlawb(); - 0xb: WarnUnimpl::smulbb(); + 0xb: smulbb({{ Rn = resTemp = sext<16>(Rm<15:0>) * sext<16>(Rs<15:0>); }}, none); } 0xa: decode OPCODE { - 0x8: WarnUnimpl::smlatb(); - 0x9: WarnUnimpl::smulwb(); + 0x8: smlatb({{ Rn = resTemp = sext<16>(Rm<31:16>) * sext<16>(Rs<15:0>) + Rd; }}, overflow); + 0x9: smulwb({{ + Rn = resTemp = bits(sext<32>(Rm) * sext<16>(Rs<15:0>), 47, 16); + }}, none); 0xa: WarnUnimpl::smlaltb(); - 0xb: WarnUnimpl::smultb(); + 0xb: smultb({{ Rn = resTemp = sext<16>(Rm<31:16>) * sext<16>(Rs<15:0>); }}, none); } 0xc: decode OPCODE { - 0x8: WarnUnimpl::smlabt(); + 0x8: smlabt({{ Rn = resTemp = sext<16>(Rm<15:0>) * sext<16>(Rs<31:16>) + Rd; }}, overflow); 0x9: WarnUnimpl::smlawt(); 0xa: WarnUnimpl::smlalbt(); - 0xb: WarnUnimpl::smulbt(); + 0xb: smulbt({{ Rn = resTemp = sext<16>(Rm<15:0>) * sext<16>(Rs<31:16>); }}, none); } 0xe: decode OPCODE { - 0x8: WarnUnimpl::smlatt(); - 0x9: WarnUnimpl::smulwt(); + 0x8: smlatt({{ Rn = resTemp = sext<16>(Rm<31:16>) * sext<16>(Rs<31:16>) + Rd; }}, overflow); + 0x9: smulwt({{ + Rn = resTemp = bits(sext<32>(Rm) * sext<16>(Rs<31:16>), 47, 16); + }}, none); 0xa: WarnUnimpl::smlaltt(); - 0xb: WarnUnimpl::smultt(); + 0xb: smultt({{ Rn = resTemp = sext<16>(Rm<31:16>) * sext<16>(Rs<31:16>); }}, none); } } } @@ -163,9 +199,15 @@ format DataOp { 0x2: subi({{ Rd = resTemp = Rn - rotated_imm; }}, sub); 0x3: rsbi({{ Rd = resTemp = rotated_imm - Rn; }}, rsb); 0x4: addi({{ Rd = resTemp = Rn + rotated_imm; }}, add); - 0x5: adci({{ Rd = resTemp = Rn + rotated_imm + Cpsr<29:>; }}, add); - 0x6: sbci({{ Rd = resTemp = Rn -rotated_imm - !Cpsr<29:>; }}, sub); - 0x7: rsci({{ Rd = resTemp = rotated_imm - Rn - !Cpsr<29:>;}}, rsb); + 0x5: adci({{ + Rd = resTemp = Rn + rotated_imm + CondCodes<29:>; + }}, add); + 0x6: sbci({{ + Rd = resTemp = Rn -rotated_imm - !CondCodes<29:>; + }}, sub); + 0x7: rsci({{ + Rd = resTemp = rotated_imm - Rn - !CondCodes<29:>; + }}, rsb); 0x8: tsti({{ resTemp = Rn & rotated_imm; }}); 0x9: teqi({{ resTemp = Rn ^ rotated_imm; }}); 0xa: cmpi({{ resTemp = Rn - rotated_imm; }}, sub); @@ -178,11 +220,27 @@ format DataOp { } 1: decode OPCODE { // The following two instructions aren't supposed to be defined - 0x8: WarnUnimpl::undefined_instruction(); - 0x9: WarnUnimpl::undefined_instruction(); - - 0xa: WarnUnimpl::mrs_i_cpsr(); - 0xb: WarnUnimpl::mrs_i_spsr(); + 0x8: DataOp::movw({{ Rd = IMMED_11_0 | (RN << 12) ; }}); + 0x9: decode RN { + 0: decode IMM { + 0: PredImmOp::nop({{ ; }}); + 1: WarnUnimpl::yield(); + 2: WarnUnimpl::wfe(); + 3: WarnUnimpl::wfi(); + 4: WarnUnimpl::sev(); + } + default: PredImmOp::msr_i_cpsr({{ + uint32_t newCpsr = + cpsrWriteByInstr(Cpsr | CondCodes, + rotated_imm, RN, false); + Cpsr = ~CondCodesMask & newCpsr; + CondCodes = CondCodesMask & newCpsr; + }}); + } + 0xa: PredOp::movt({{ Rd = IMMED_11_0 << 16 | RN << 28 | Rd<15:0>; }}); + 0xb: PredImmOp::msr_i_spsr({{ + Spsr = spsrWriteByInstr(Spsr, rotated_imm, RN, false); + }}); } } 0x2: AddrMode2::addrMode2(Disp, disp); @@ -324,77 +382,79 @@ format DataOp { } } 0x7: decode OPCODE_24 { - 0: decode CPNUM { - // Coprocessor Instructions - 0x1: decode OPCODE_4 { + 0: decode OPCODE_4 { + 0: decode CPNUM { format FloatOp { - // Basic FPA Instructions - 0: decode OPCODE_23_20 { - 0x0: decode OPCODE_15 { - 0: adf({{ Fd.sf = Fn.sf + Fm.sf; }}); - 1: mvf({{ Fd.sf = Fm.sf; }}); - } - 0x1: decode OPCODE_15 { - 0: muf({{ Fd.sf = Fn.sf * Fm.sf; }}); - 1: mnf({{ Fd.sf = -Fm.sf; }}); - } - 0x2: decode OPCODE_15 { - 0: suf({{ Fd.sf = Fn.sf - Fm.sf; }}); - 1: abs({{ Fd.sf = fabs(Fm.sf); }}); - } - 0x3: decode OPCODE_15 { - 0: rsf({{ Fd.sf = Fm.sf - Fn.sf; }}); - 1: rnd({{ Fd.sf = rint(Fm.sf); }}); - } - 0x4: decode OPCODE_15 { - 0: dvf({{ Fd.sf = Fn.sf / Fm.sf; }}); - 1: sqt({{ Fd.sf = sqrt(Fm.sf); }}); - } - 0x5: decode OPCODE_15 { - 0: rdf({{ Fd.sf = Fm.sf / Fn.sf; }}); - 1: log({{ Fd.sf = log10(Fm.sf); }}); - } - 0x6: decode OPCODE_15 { - 0: pow({{ Fd.sf = pow(Fm.sf, Fn.sf); }}); - 1: lgn({{ Fd.sf = log(Fm.sf); }}); - } - 0x7: decode OPCODE_15 { - 0: rpw({{ Fd.sf = pow(Fn.sf, Fm.sf); }}); - 1: exp({{ Fd.sf = exp(Fm.sf); }}); - } - 0x8: decode OPCODE_15 { - 0: rmf({{ Fd.sf = drem(Fn.sf, Fm.sf); }}); - 1: sin({{ Fd.sf = sin(Fm.sf); }}); - } - 0x9: decode OPCODE_15 { - 0: fml({{ Fd.sf = Fn.sf * Fm.sf; }}); - 1: cos({{ Fd.sf = cos(Fm.sf); }}); - } - 0xa: decode OPCODE_15 { - 0: fdv({{ Fd.sf = Fn.sf / Fm.sf; }}); - 1: tan({{ Fd.sf = tan(Fm.sf); }}); - } - 0xb: decode OPCODE_15 { - 0: frd({{ Fd.sf = Fm.sf / Fn.sf; }}); - 1: asn({{ Fd.sf = asin(Fm.sf); }}); - } - 0xc: decode OPCODE_15 { - 0: pol({{ Fd.sf = atan2(Fn.sf, Fm.sf); }}); - 1: acs({{ Fd.sf = acos(Fm.sf); }}); - } - 0xd: decode OPCODE_15 { - 1: atn({{ Fd.sf = atan(Fm.sf); }}); - } - 0xe: decode OPCODE_15 { - // Unnormalised Round - 1: FailUnimpl::urd(); - } - 0xf: decode OPCODE_15 { - // Normalise - 1: FailUnimpl::nrm(); - } - } - 1: decode OPCODE_15_12 { + 0x1: decode OPCODE_23_20 { + 0x0: decode OPCODE_15 { + 0: adf({{ Fd.sf = Fn.sf + Fm.sf; }}); + 1: mvf({{ Fd.sf = Fm.sf; }}); + } + 0x1: decode OPCODE_15 { + 0: muf({{ Fd.sf = Fn.sf * Fm.sf; }}); + 1: mnf({{ Fd.sf = -Fm.sf; }}); + } + 0x2: decode OPCODE_15 { + 0: suf({{ Fd.sf = Fn.sf - Fm.sf; }}); + 1: abs({{ Fd.sf = fabs(Fm.sf); }}); + } + 0x3: decode OPCODE_15 { + 0: rsf({{ Fd.sf = Fm.sf - Fn.sf; }}); + 1: rnd({{ Fd.sf = rint(Fm.sf); }}); + } + 0x4: decode OPCODE_15 { + 0: dvf({{ Fd.sf = Fn.sf / Fm.sf; }}); + 1: sqt({{ Fd.sf = sqrt(Fm.sf); }}); + } + 0x5: decode OPCODE_15 { + 0: rdf({{ Fd.sf = Fm.sf / Fn.sf; }}); + 1: log({{ Fd.sf = log10(Fm.sf); }}); + } + 0x6: decode OPCODE_15 { + 0: pow({{ Fd.sf = pow(Fm.sf, Fn.sf); }}); + 1: lgn({{ Fd.sf = log(Fm.sf); }}); + } + 0x7: decode OPCODE_15 { + 0: rpw({{ Fd.sf = pow(Fn.sf, Fm.sf); }}); + 1: exp({{ Fd.sf = exp(Fm.sf); }}); + } + 0x8: decode OPCODE_15 { + 0: rmf({{ Fd.sf = drem(Fn.sf, Fm.sf); }}); + 1: sin({{ Fd.sf = sin(Fm.sf); }}); + } + 0x9: decode OPCODE_15 { + 0: fml({{ Fd.sf = Fn.sf * Fm.sf; }}); + 1: cos({{ Fd.sf = cos(Fm.sf); }}); + } + 0xa: decode OPCODE_15 { + 0: fdv({{ Fd.sf = Fn.sf / Fm.sf; }}); + 1: tan({{ Fd.sf = tan(Fm.sf); }}); + } + 0xb: decode OPCODE_15 { + 0: frd({{ Fd.sf = Fm.sf / Fn.sf; }}); + 1: asn({{ Fd.sf = asin(Fm.sf); }}); + } + 0xc: decode OPCODE_15 { + 0: pol({{ Fd.sf = atan2(Fn.sf, Fm.sf); }}); + 1: acs({{ Fd.sf = acos(Fm.sf); }}); + } + 0xd: decode OPCODE_15 { + 1: atn({{ Fd.sf = atan(Fm.sf); }}); + } + 0xe: decode OPCODE_15 { + // Unnormalised Round + 1: FailUnimpl::urd(); + } + 0xf: decode OPCODE_15 { + // Normalise + 1: FailUnimpl::nrm(); + } + } // OPCODE_23_20 + } // format FloatOp + } // CPNUM + 1: decode CPNUM { // 27-24=1110,4 ==1 + 1: decode OPCODE_15_12 { + format FloatOp { 0xf: decode OPCODE_23_21 { format FloatCmp { 0x4: cmf({{ Fn.df }}, {{ Fm.df }}); @@ -417,36 +477,86 @@ format DataOp { 0x4: FailUnimpl::wfc(); 0x5: FailUnimpl::rfc(); } - } + } // format FloatOp } - } - 0xa: decode MISC_OPCODE { - 0x1: decode MEDIA_OPCODE { - 0xf: decode RN { - 0x0: FloatOp::fmrx_fpsid({{ Rd = Fpsid; }}); - 0x1: FloatOp::fmrx_fpscr({{ Rd = Fpscr; }}); - 0x8: FloatOp::fmrx_fpexc({{ Rd = Fpexc; }}); - } - 0xe: decode RN { - 0x0: FloatOp::fmxr_fpsid({{ Fpsid = Rd; }}); - 0x1: FloatOp::fmxr_fpscr({{ Fpscr = Rd; }}); - 0x8: FloatOp::fmxr_fpexc({{ Fpexc = Rd; }}); + 0xa: decode MISC_OPCODE { + 0x1: decode MEDIA_OPCODE { + 0xf: decode RN { + 0x0: FloatOp::fmrx_fpsid({{ Rd = Fpsid; }}); + 0x1: FloatOp::fmrx_fpscr({{ Rd = Fpscr; }}); + 0x8: FloatOp::fmrx_fpexc({{ Rd = Fpexc; }}); + } + 0xe: decode RN { + 0x0: FloatOp::fmxr_fpsid({{ Fpsid = Rd; }}); + 0x1: FloatOp::fmxr_fpscr({{ Fpscr = Rd; }}); + 0x8: FloatOp::fmxr_fpexc({{ Fpexc = Rd; }}); + } + } // MEDIA_OPCODE (MISC_OPCODE 0x1) + } // MISC_OPCODE (CPNUM 0xA) + 0xf: decode RN { + // Barrriers, Cache Maintence, NOPS + 7: decode OPCODE_23_21 { + 0: decode RM { + 0: decode OPC2 { + 4: decode OPCODE_20 { + 0: PredOp::mcr_cp15_nop1({{ }}); // was wfi + } + } + 1: WarnUnimpl::cp15_cache_maint(); + 4: WarnUnimpl::cp15_par(); + 5: decode OPC2 { + 0,1: WarnUnimpl::cp15_cache_maint2(); + 4: PredOp::cp15_isb({{ ; }}, IsMemBarrier, IsSerializeBefore); + 6,7: WarnUnimpl::cp15_bp_maint(); + } + 6: WarnUnimpl::cp15_cache_maint3(); + 8: WarnUnimpl::cp15_va_to_pa(); + 10: decode OPC2 { + 1,2: WarnUnimpl::cp15_cache_maint3(); + 4: PredOp::cp15_dsb({{ ; }}, IsMemBarrier, IsSerializeBefore); + 5: PredOp::cp15_dmb({{ ; }}, IsMemBarrier, IsSerializeBefore); + } + 11: WarnUnimpl::cp15_cache_maint4(); + 13: decode OPC2 { + 1: decode OPCODE_20 { + 0: PredOp::mcr_cp15_nop2({{ }}); // was prefetch + } + } + 14: WarnUnimpl::cp15_cache_maint5(); + } // RM + } // OPCODE_23_21 CR + + // Thread ID and context ID registers + // Thread ID register needs cheaper access than miscreg + 13: WarnUnimpl::mcr_mrc_cp15_c7(); + + // All the rest + default: decode OPCODE_20 { + 0: PredOp::mcr_cp15({{ + fault = setCp15Register(Rd, RN, OPCODE_23_21, RM, OPC2); + }}); + 1: PredOp::mrc_cp15({{ + fault = readCp15Register(Rd, RN, OPCODE_23_21, RM, OPC2); + }}); } - } + } // RN + } // CPNUM (OP4 == 1) + } //OPCODE_4 + +#if FULL_SYSTEM + 1: PredOp::swi({{ fault = new SupervisorCall; }}, IsSerializeAfter, IsNonSpeculative, IsSyscall); +#else + 1: PredOp::swi({{ if (testPredicate(CondCodes, condCode)) + { + if (IMMED_23_0) + xc->syscall(IMMED_23_0); + else + xc->syscall(R7); } - } - format PredOp { - // ARM System Call (SoftWare Interrupt) - 1: swi({{ if (testPredicate(Cpsr, condCode)) - { - if (IMMED_23_0) - xc->syscall(IMMED_23_0); - else - xc->syscall(R7); - } - }}); - } - } + }}); +#endif // FULL_SYSTEM + } // OPCODE_24 + } } diff --git a/src/arch/arm/isa/formats/branch.isa b/src/arch/arm/isa/formats/branch.isa index 95f4f14e1..5f1b541ff 100644 --- a/src/arch/arm/isa/formats/branch.isa +++ b/src/arch/arm/isa/formats/branch.isa @@ -52,7 +52,7 @@ def format Branch(code,*opt_flags) {{ else: inst_flags += ('IsCondControl', ) - icode = 'if (testPredicate(Cpsr, condCode)) {\n' + icode = 'if (testPredicate(CondCodes, condCode)) {\n' icode += code icode += ' NPC = NPC + 4 + disp;\n' icode += '} else {\n' @@ -90,7 +90,7 @@ def format BranchExchange(code,*opt_flags) {{ #Condition code - icode = 'if (testPredicate(Cpsr, condCode)) {\n' + icode = 'if (testPredicate(CondCodes, condCode)) {\n' icode += code icode += ' NPC = Rm & 0xfffffffe; // Masks off bottom bit\n' icode += '} else {\n' diff --git a/src/arch/arm/isa/formats/fp.isa b/src/arch/arm/isa/formats/fp.isa index e88531580..e79529615 100644 --- a/src/arch/arm/isa/formats/fp.isa +++ b/src/arch/arm/isa/formats/fp.isa @@ -119,8 +119,8 @@ let {{ _ic = %(fReg1)s >= %(fReg2)s; _iv = (isnan(%(fReg1)s) || isnan(%(fReg2)s)) & 1; - Cpsr = _in << 31 | _iz << 30 | _ic << 29 | _iv << 28 | - (Cpsr & 0x0FFFFFFF); + CondCodes = _in << 31 | _iz << 30 | _ic << 29 | _iv << 28 | + (CondCodes & 0x0FFFFFFF); ''' }}; diff --git a/src/arch/arm/isa/formats/macromem.isa b/src/arch/arm/isa/formats/macromem.isa index 355a67ea9..c834c22cb 100644 --- a/src/arch/arm/isa/formats/macromem.isa +++ b/src/arch/arm/isa/formats/macromem.isa @@ -72,6 +72,18 @@ let {{ 'predicate_test': predicateTest}, ['IsMicroop']) + microLdrRetUopCode = ''' + Ra = Mem; + Cpsr = cpsrWriteByInstr(Cpsr, Spsr, 0xF, true); + ''' + microLdrRetUopIop = InstObjParams('ldr_ret_uop', 'MicroLdrRetUop', + 'MicroMemOp', + {'memacc_code': microLdrRetUopCode, + 'ea_code': + 'EA = Rb + (UP ? imm : -imm);', + 'predicate_test': predicateTest}, + ['IsMicroop']) + microStrUopIop = InstObjParams('str_uop', 'MicroStrUop', 'MicroMemOp', {'memacc_code': 'Mem = Ra;', @@ -80,14 +92,19 @@ let {{ ['IsMicroop']) header_output = MicroMemDeclare.subst(microLdrUopIop) + \ + MicroMemDeclare.subst(microLdrRetUopIop) + \ MicroMemDeclare.subst(microStrUopIop) decoder_output = MicroConstructor.subst(microLdrUopIop) + \ + MicroConstructor.subst(microLdrRetUopIop) + \ MicroConstructor.subst(microStrUopIop) exec_output = LoadExecute.subst(microLdrUopIop) + \ + LoadExecute.subst(microLdrRetUopIop) + \ StoreExecute.subst(microStrUopIop) + \ LoadInitiateAcc.subst(microLdrUopIop) + \ + LoadInitiateAcc.subst(microLdrRetUopIop) + \ StoreInitiateAcc.subst(microStrUopIop) + \ LoadCompleteAcc.subst(microLdrUopIop) + \ + LoadCompleteAcc.subst(microLdrRetUopIop) + \ StoreCompleteAcc.subst(microStrUopIop) }}; @@ -178,73 +195,64 @@ inline %(class_name)s::%(class_name)s(ExtMachInst machInst) : %(base_class)s("%(mnemonic)s", machInst, %(op_class)s) { %(constructor)s; - uint32_t regs_to_handle = reglist; - uint32_t start_addr = 0; + uint32_t regs = reglist; + uint32_t addr = 0; + bool up = machInst.puswl.up; - switch (puswl) - { - case 0x00: // stmda - case 0x01: // L ldmda_l - case 0x02: // W stmda_w - case 0x03: // WL ldmda_wl - start_addr = (ones << 2) - 4; - break; - case 0x08: // U stmia_u - case 0x09: // U L ldmia_ul - case 0x0a: // U W stmia - case 0x0b: // U WL ldmia - start_addr = 0; - break; - case 0x10: // P stmdb - case 0x11: // P L ldmdb - case 0x12: // P W stmdb - case 0x13: // P WL ldmdb - start_addr = (ones << 2); // U-bit is already 0 for subtract - break; - case 0x18: // PU stmib - case 0x19: // PU L ldmib - case 0x1a: // PU W stmib - case 0x1b: // PU WL ldmib - start_addr = 4; - break; - default: - panic("Unhandled Load/Store Multiple Instruction, " - "puswl = 0x%x", (unsigned) puswl); - break; - } + if (!up) + addr = (ones << 2) - 4; + + if (machInst.puswl.prepost) + addr += 4; - // Add 0 to Rn and stick it in Raddr (register 17). + // Add 0 to Rn and stick it in ureg0. // This is equivalent to a move. - microOps[0] = new MicroAddiUop(machInst, 17, RN, 0); + microOps[0] = new MicroAddiUop(machInst, INTREG_UREG0, RN, 0); - unsigned j = 0; - for (int i = 1; i < ones+1; i++) { - // Get next available bit for transfer - while (! ( regs_to_handle & (1<<j))) - j++; - regs_to_handle &= ~(1<<j); + unsigned reg = 0; + bool force_user = machInst.puswl.psruser & !OPCODE_15; + bool exception_ret = machInst.puswl.psruser & OPCODE_15; - if (loadop) - microOps[i] = new MicroLdrUop(machInst, j, 17, start_addr); - else - microOps[i] = new MicroStrUop(machInst, j, 17, start_addr); + for (int i = 1; i < ones + 1; i++) { + // Find the next register. + while (!bits(regs, reg)) + reg++; + replaceBits(regs, reg, 0); + + unsigned regIdx = reg; + if (force_user) { + regIdx = intRegForceUser(regIdx); + } + + if (machInst.puswl.loadOp) { + if (reg == INTREG_PC && exception_ret) { + // This must be the exception return form of ldm. + microOps[i] = + new MicroLdrRetUop(machInst, regIdx, INTREG_UREG0, addr); + } else { + microOps[i] = + new MicroLdrUop(machInst, regIdx, INTREG_UREG0, addr); + } + } else { + microOps[i] = + new MicroStrUop(machInst, regIdx, INTREG_UREG0, addr); + } if (up) - start_addr += 4; + addr += 4; else - start_addr -= 4; + addr -= 4; } - if (writeback) { + StaticInstPtr &lastUop = microOps[numMicroops - 1]; + if (machInst.puswl.writeback) { if (up) { - microOps[numMicroops-1] = - new MicroAddiUop(machInst, RN, RN, ones * 4); + lastUop = new MicroAddiUop(machInst, RN, RN, ones * 4); } else { - microOps[numMicroops-1] = - new MicroSubiUop(machInst, RN, RN, ones * 4); + lastUop = new MicroSubiUop(machInst, RN, RN, ones * 4); } } - microOps[numMicroops-1]->setLastMicroop(); + lastUop->setLastMicroop(); } }}; @@ -285,14 +293,14 @@ inline %(class_name)s::%(class_name)s(ExtMachInst machInst) if (writeback) { if (up) { - microOps[numMicroops-1] = + microOps[numMicroops - 1] = new MicroAddiUop(machInst, RN, RN, disp8); } else { - microOps[numMicroops-1] = + microOps[numMicroops - 1] = new MicroSubiUop(machInst, RN, RN, disp8); } } - microOps[numMicroops-1]->setLastMicroop(); + microOps[numMicroops - 1]->setLastMicroop(); } }}; @@ -316,14 +324,14 @@ inline %(class_name)s::%(class_name)s(ExtMachInst machInst) if (writeback) { if (up) { - microOps[numMicroops-1] = + microOps[numMicroops - 1] = new MicroAddiUop(machInst, RN, RN, disp8); } else { - microOps[numMicroops-1] = + microOps[numMicroops - 1] = new MicroSubiUop(machInst, RN, RN, disp8); } } - microOps[numMicroops-1]->setLastMicroop(); + microOps[numMicroops - 1]->setLastMicroop(); } }}; diff --git a/src/arch/arm/isa/formats/pred.isa b/src/arch/arm/isa/formats/pred.isa index e90788c91..0d6ee32f7 100644 --- a/src/arch/arm/isa/formats/pred.isa +++ b/src/arch/arm/isa/formats/pred.isa @@ -34,7 +34,7 @@ // let {{ - predicateTest = 'testPredicate(Cpsr, condCode)' + predicateTest = 'testPredicate(CondCodes, condCode)' }}; def template PredOpExecute {{ @@ -81,32 +81,45 @@ def template DataImmDecode {{ }}; let {{ + + calcCcCode = ''' + if (%(canOverflow)s){ + cprintf("canOverflow: %%d\\n", Rd < resTemp); + replaceBits(CondCodes, 27, Rd < resTemp); + } else { + uint16_t _ic, _iv, _iz, _in; + _in = (resTemp >> %(negBit)d) & 1; + _iz = (resTemp == 0); + _iv = %(ivValue)s & 1; + _ic = %(icValue)s & 1; + + CondCodes = _in << 31 | _iz << 30 | _ic << 29 | _iv << 28 | + (CondCodes & 0x0FFFFFFF); - calcCcCode = ''' - uint16_t _ic, _iv, _iz, _in; - - _in = (resTemp >> 31) & 1; - _iz = (resTemp == 0); - _iv = %(ivValue)s & 1; - _ic = %(icValue)s & 1; - - Cpsr = _in << 31 | _iz << 30 | _ic << 29 | _iv << 28 | - (Cpsr & 0x0FFFFFFF); - - DPRINTF(Arm, "in = %%d\\n", _in); - DPRINTF(Arm, "iz = %%d\\n", _iz); - DPRINTF(Arm, "ic = %%d\\n", _ic); - DPRINTF(Arm, "iv = %%d\\n", _iv); + DPRINTF(Arm, "in = %%d\\n", _in); + DPRINTF(Arm, "iz = %%d\\n", _iz); + DPRINTF(Arm, "ic = %%d\\n", _ic); + DPRINTF(Arm, "iv = %%d\\n", _iv); + } ''' - }}; let {{ def getCcCode(flagtype): icReg = icImm = iv = '' + negBit = 31 + canOverflow = 'false' + if flagtype == "none": - icReg = icImm = 'Cpsr<29:>' - iv = 'Cpsr<28:>' + icReg = icImm = 'CondCodes<29:>' + iv = 'CondCodes<28:>' + elif flagtype == "llbit": + icReg = icImm = 'CondCodes<29:>' + iv = 'CondCodes<28:>' + negBit = 63 + elif flagtype == "overflow": + canOverflow = "true" + icReg = icImm = iv = '0' elif flagtype == "add": icReg = icImm = 'findCarry(32, resTemp, Rn, op2)' iv = 'findOverflow(32, resTemp, Rn, op2)' @@ -117,17 +130,32 @@ let {{ icReg = icImm = 'findCarry(32, resTemp, op2, ~Rn)' iv = 'findOverflow(32, resTemp, op2, ~Rn)' else: - icReg = 'shift_carry_rs(Rm, Rs, shift, Cpsr<29:>)' - icImm = 'shift_carry_imm(Rm, shift_size, shift, Cpsr<29:>)' - iv = 'Cpsr<28:>' - return (calcCcCode % {"icValue" : icReg, "ivValue" : iv}, - calcCcCode % {"icValue" : icImm, "ivValue" : iv}) + icReg = 'shift_carry_rs(Rm, Rs<7:0>, shift, CondCodes<29:>)' + icImm = 'shift_carry_imm(Rm, shift_size, shift, CondCodes<29:>)' + iv = 'CondCodes<28:>' + return (calcCcCode % {"icValue" : icReg, + "ivValue" : iv, + "negBit" : negBit, + "canOverflow" : canOverflow }, + calcCcCode % {"icValue" : icImm, + "ivValue" : iv, + "negBit" : negBit, + "canOverflow" : canOverflow }) def getImmCcCode(flagtype): ivValue = icValue = '' + negBit = 31 + canOverflow = 'false' if flagtype == "none": - icValue = 'Cpsr<29:>' - ivValue = 'Cpsr<28:>' + icValue = 'CondCodes<29:>' + ivValue = 'CondCodes<28:>' + elif flagtype == "llbit": + icValue = 'CondCodes<29:>' + ivValue = 'CondCodes<28:>' + negBit = 63 + elif flagtype == "overflow": + icVaule = ivValue = '0' + canOverflow = "true" elif flagtype == "add": icValue = 'findCarry(32, resTemp, Rn, rotated_imm)' ivValue = 'findOverflow(32, resTemp, Rn, rotated_imm)' @@ -138,18 +166,18 @@ let {{ icValue = 'findCarry(32, resTemp, rotated_imm, ~Rn)' ivValue = 'findOverflow(32, resTemp, rotated_imm, ~Rn)' else: - icValue = '(rotate ? rotated_carry:Cpsr<29:>)' - ivValue = 'Cpsr<28:>' + icValue = '(rotate ? rotated_carry:CondCodes<29:>)' + ivValue = 'CondCodes<28:>' return calcCcCode % vars() }}; def format DataOp(code, flagtype = logic) {{ (regCcCode, immCcCode) = getCcCode(flagtype) - regCode = '''uint32_t op2 = shift_rm_rs(Rm, Rs, - shift, Cpsr<29:0>); + regCode = '''uint32_t op2 = shift_rm_rs(Rm, Rs<7:0>, + shift, CondCodes<29:>); op2 = op2;''' + code immCode = '''uint32_t op2 = shift_rm_imm(Rm, shift_size, - shift, Cpsr<29:0>); + shift, CondCodes<29:>); op2 = op2;''' + code regIop = InstObjParams(name, Name, 'PredIntOp', {"code": regCode, diff --git a/src/arch/arm/isa/formats/unimp.isa b/src/arch/arm/isa/formats/unimp.isa index c82bb41c6..6909c3f85 100644 --- a/src/arch/arm/isa/formats/unimp.isa +++ b/src/arch/arm/isa/formats/unimp.isa @@ -115,7 +115,7 @@ output exec {{ panic("attempt to execute unimplemented instruction '%s' " "(inst 0x%08x, opcode 0x%x, binary:%s)", mnemonic, machInst, OPCODE, inst2string(machInst)); - return new UnimplementedOpcodeFault; + return new UnimpFault("Unimplemented Instruction"); } Fault diff --git a/src/arch/arm/isa/formats/unknown.isa b/src/arch/arm/isa/formats/unknown.isa index 2ad7a2506..97a0caa6b 100644 --- a/src/arch/arm/isa/formats/unknown.isa +++ b/src/arch/arm/isa/formats/unknown.isa @@ -74,7 +74,7 @@ output exec {{ { panic("attempt to execute unknown instruction " "(inst 0x%08x, opcode 0x%x, binary: %s)", machInst, OPCODE, inst2string(machInst)); - return new UnimplementedOpcodeFault; + return new UnimpFault("Unimplemented Instruction"); } }}; diff --git a/src/arch/arm/isa/formats/util.isa b/src/arch/arm/isa/formats/util.isa index b5efec568..d42ffb147 100644 --- a/src/arch/arm/isa/formats/util.isa +++ b/src/arch/arm/isa/formats/util.isa @@ -33,8 +33,10 @@ let {{ # Generic substitutions for Arm instructions def ArmGenericCodeSubs(code): # Substitute in the shifted portion of operations - new_code = re.sub(r'Rm_Imm', 'shift_rm_imm(Rm, shift_size, shift, Cpsr<29:>)', code) - new_code = re.sub(r'Rm_Rs', 'shift_rm_rs(Rm, Rs, shift, Cpsr<29:>)', new_code) + new_code = re.sub(r'Rm_Imm', + 'shift_rm_imm(Rm, shift_size, shift, CondCodes<29:>)', code) + new_code = re.sub(r'Rm_Rs', + 'shift_rm_rs(Rm, Rs, shift, CondCodes<29:>)', new_code) return new_code def LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags, diff --git a/src/arch/arm/isa/operands.isa b/src/arch/arm/isa/operands.isa index ac7427dad..aadefc79c 100644 --- a/src/arch/arm/isa/operands.isa +++ b/src/arch/arm/isa/operands.isa @@ -58,15 +58,16 @@ def operands {{ 'Rs': ('IntReg', 'uw', 'RS', 'IsInteger', 3, maybePCRead, maybePCWrite), 'Rn': ('IntReg', 'uw', 'RN', 'IsInteger', 4, maybePCRead, maybePCWrite), 'R7': ('IntReg', 'uw', '7', 'IsInteger', 5), + 'R0': ('IntReg', 'uw', '0', 'IsInteger', 0), #Destination register for load/store double instructions 'Rdo': ('IntReg', 'uw', '(RD & ~1)', 'IsInteger', 4, maybePCRead, maybePCWrite), 'Rde': ('IntReg', 'uw', '(RD | 1)', 'IsInteger', 5, maybePCRead, maybePCWrite), - 'Raddr': ('IntReg', 'uw', '17', 'IsInteger', 6), - 'Rhi': ('IntReg', 'uw', '18', 'IsInteger', 7), - 'Rlo': ('IntReg', 'uw', '19', 'IsInteger', 8), - 'LR': ('IntReg', 'uw', '14', 'IsInteger', 9), + 'Rhi': ('IntReg', 'uw', 'INTREG_RHI', 'IsInteger', 7), + 'Rlo': ('IntReg', 'uw', 'INTREG_RLO', 'IsInteger', 8), + 'LR': ('IntReg', 'uw', 'INTREG_LR', 'IsInteger', 9), + 'CondCodes': ('IntReg', 'uw', 'INTREG_CONDCODES', 'IsInteger', 10), #Register fields for microops 'Ra' : ('IntReg', 'uw', 'ura', 'IsInteger', 11, maybePCRead, maybePCWrite), @@ -80,12 +81,13 @@ def operands {{ #Memory Operand 'Mem': ('Mem', 'uw', None, ('IsMemRef', 'IsLoad', 'IsStore'), 30), - 'Cpsr': ('ControlReg', 'uw', 'MISCREG_CPSR', 'IsInteger', 40), - 'Fpsr': ('ControlReg', 'uw', 'MISCREG_FPSR', 'IsInteger', 41), - 'Fpsid': ('ControlReg', 'uw', 'MISCREG_FPSID', 'IsInteger', 42), - 'Fpscr': ('ControlReg', 'uw', 'MISCREG_FPSCR', 'IsInteger', 43), - 'Fpexc': ('ControlReg', 'uw', 'MISCREG_FPEXC', 'IsInteger', 44), - 'NPC': ('NPC', 'uw', None, (None, None, 'IsControl'), 45), - 'NNPC': ('NNPC', 'uw', None, (None, None, 'IsControl'), 46) + 'Cpsr': ('ControlReg', 'uw', 'MISCREG_CPSR', (None, None, 'IsControl'), 40), + 'Spsr': ('ControlReg', 'uw', 'MISCREG_SPSR', (None, None, 'IsControl'), 41), + 'Fpsr': ('ControlReg', 'uw', 'MISCREG_FPSR', (None, None, 'IsControl'), 42), + 'Fpsid': ('ControlReg', 'uw', 'MISCREG_FPSID', (None, None, 'IsControl'), 43), + 'Fpscr': ('ControlReg', 'uw', 'MISCREG_FPSCR', (None, None, 'IsControl'), 44), + 'Fpexc': ('ControlReg', 'uw', 'MISCREG_FPEXC', (None, None, 'IsControl'), 45), + 'NPC': ('NPC', 'uw', None, (None, None, 'IsControl'), 50), + 'NNPC': ('NNPC', 'uw', None, (None, None, 'IsControl'), 51) }}; diff --git a/src/arch/arm/isa_traits.hh b/src/arch/arm/isa_traits.hh index 542174b6b..91c51c46b 100644 --- a/src/arch/arm/isa_traits.hh +++ b/src/arch/arm/isa_traits.hh @@ -104,6 +104,8 @@ namespace ArmISA const int WordBytes = 4; const int HalfwordBytes = 2; const int ByteBytes = 1; + + const uint32_t HighVecs = 0xFFFF0000; }; using namespace ArmISA; diff --git a/src/mem/slicc/ast/TypeAST.cc b/src/arch/arm/kernel_stats.hh index 7590b4e7c..18bdc500d 100644 --- a/src/mem/slicc/ast/TypeAST.cc +++ b/src/arch/arm/kernel_stats.hh @@ -1,6 +1,5 @@ - /* - * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood + * Copyright (c) 2004-2005 The Regents of The University of Michigan * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -25,43 +24,34 @@ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/* - * TypeAST.C - * - * Description: See TypeAST.hh - * - * $Id: TypeAST.C,v 3.1 2003/03/22 15:15:16 xu Exp $ * + * Authors: Gabe Black */ -#include "mem/slicc/ast/TypeAST.hh" +#ifndef __ARCH_ARM_KERNEL_STATS_HH__ +#define __ARCH_ARM_KERNEL_STATS_HH__ -TypeAST::TypeAST(string* ident_ptr) - : AST() -{ - m_ident_ptr = ident_ptr; -} +#include <map> +#include <stack> +#include <string> +#include <vector> -TypeAST::~TypeAST() -{ - delete m_ident_ptr; +#include "kern/kernel_stats.hh" -} +namespace ArmISA { +namespace Kernel { -string TypeAST::toString() const -{ - return *m_ident_ptr; -} +enum cpu_mode { hypervisor, kernel, user, idle, cpu_mode_num }; +extern const char *modestr[]; -Type* TypeAST::lookupType() const +class Statistics : public ::Kernel::Statistics { - Type* type_ptr = g_sym_table.getType(*m_ident_ptr); - if (type_ptr != NULL) { - return type_ptr; - } else { - error("Type '" + *m_ident_ptr + "' not declared."); - } - return NULL; // Not reached -} + public: + Statistics(System *system) : ::Kernel::Statistics(system) + {} +}; + +} /* end namespace ArmISA::Kernel */ +} /* end namespace ArmISA */ + +#endif // __ARCH_ARM_KERNEL_STATS_HH__ diff --git a/src/arch/arm/linux/linux.hh b/src/arch/arm/linux/linux.hh index d99fa8e49..f829dd7c6 100644 --- a/src/arch/arm/linux/linux.hh +++ b/src/arch/arm/linux/linux.hh @@ -86,6 +86,7 @@ class ArmLinux : public Linux static const unsigned TIOCISATTY_ = 0x2000745e; static const unsigned TIOCGETS_ = 0x402c7413; static const unsigned TIOCGETA_ = 0x40127417; + static const unsigned TCSETAW_ = 0x5407; // 2.6.15 kernel //@} /// For table(). @@ -147,6 +148,21 @@ class ArmLinux : public Linux uint64_t st_ino; } tgt_stat64; + typedef struct { + int32_t uptime; /* Seconds since boot */ + uint32_t loads[3]; /* 1, 5, and 15 minute load averages */ + uint32_t totalram; /* Total usable main memory size */ + uint32_t freeram; /* Available memory size */ + uint32_t sharedram; /* Amount of shared memory */ + uint32_t bufferram; /* Memory used by buffers */ + uint32_t totalswap; /* Total swap space size */ + uint32_t freeswap; /* swap space still available */ + uint16_t procs; /* Number of current processes */ + uint32_t totalhigh; /* Total high memory size */ + uint32_t freehigh; /* Available high memory size */ + uint32_t mem_unit; /* Memory unit size in bytes */ + } tgt_sysinfo; + }; diff --git a/src/arch/arm/linux/process.cc b/src/arch/arm/linux/process.cc index 56e3588a7..f909d871a 100644 --- a/src/arch/arm/linux/process.cc +++ b/src/arch/arm/linux/process.cc @@ -50,7 +50,8 @@ static SyscallReturn unameFunc(SyscallDesc *desc, int callnum, LiveProcess *process, ThreadContext *tc) { - TypedBufferArg<Linux::utsname> name(process->getSyscallArg(tc, 0)); + int index = 0; + TypedBufferArg<Linux::utsname> name(process->getSyscallArg(tc, index)); strcpy(name->sysname, "Linux"); strcpy(name->nodename, "m5.eecs.umich.edu"); @@ -179,7 +180,7 @@ SyscallDesc ArmLinuxProcess::syscallDescs[] = { /* 113 */ SyscallDesc("vm86", unimplementedFunc), /* 114 */ SyscallDesc("wait4", unimplementedFunc), /* 115 */ SyscallDesc("swapoff", unimplementedFunc), - /* 116 */ SyscallDesc("sysinfo", unimplementedFunc), + /* 116 */ SyscallDesc("sysinfo", sysinfoFunc<ArmLinux>), /* 117 */ SyscallDesc("ipc", unimplementedFunc), /* 118 */ SyscallDesc("fsync", unimplementedFunc), /* 119 */ SyscallDesc("sigreturn", unimplementedFunc), @@ -417,7 +418,8 @@ static SyscallReturn setTLSFunc(SyscallDesc *desc, int callnum, LiveProcess *process, ThreadContext *tc) { - uint32_t tlsPtr = process->getSyscallArg(tc, 0); + int index = 0; + uint32_t tlsPtr = process->getSyscallArg(tc, index); tc->getMemPort()->writeBlob(ArmLinuxProcess::commPage + 0x0ff0, (uint8_t *)&tlsPtr, sizeof(tlsPtr)); @@ -511,12 +513,12 @@ ArmLinuxProcess::startup() } ArmISA::IntReg -ArmLinuxProcess::getSyscallArg(ThreadContext *tc, int i) +ArmLinuxProcess::getSyscallArg(ThreadContext *tc, int &i) { // Linux apparently allows more parameter than the ABI says it should. // This limit may need to be increased even further. assert(i < 6); - return tc->readIntReg(ArgumentReg0 + i); + return tc->readIntReg(ArgumentReg0 + i++); } void diff --git a/src/arch/arm/linux/process.hh b/src/arch/arm/linux/process.hh index 53b3781d2..ab836fab2 100644 --- a/src/arch/arm/linux/process.hh +++ b/src/arch/arm/linux/process.hh @@ -44,7 +44,7 @@ class ArmLinuxProcess : public ArmLiveProcess void startup(); - ArmISA::IntReg getSyscallArg(ThreadContext *tc, int i); + ArmISA::IntReg getSyscallArg(ThreadContext *tc, int &i); void setSyscallArg(ThreadContext *tc, int i, ArmISA::IntReg val); /// The target system's hostname. diff --git a/src/arch/arm/miscregs.hh b/src/arch/arm/miscregs.hh index 3180669de..d100efb8e 100644 --- a/src/arch/arm/miscregs.hh +++ b/src/arch/arm/miscregs.hh @@ -55,23 +55,24 @@ namespace ArmISA enum MiscRegIndex { MISCREG_CPSR = 0, - MISCREG_SPSR, + MISCREG_SPSR, MISCREG_SPSR_FIQ, MISCREG_SPSR_IRQ, MISCREG_SPSR_SVC, + MISCREG_SPSR_MON, MISCREG_SPSR_UND, MISCREG_SPSR_ABT, MISCREG_FPSR, MISCREG_FPSID, MISCREG_FPSCR, MISCREG_FPEXC, - NUM_MISCREGS + MISCREG_SCTLR, + NUM_MISCREGS }; const char * const miscRegName[NUM_MISCREGS] = { - "cpsr", - "spsr", "spsr_fiq", "spsr_irq", "spsr_svc", "spsr_und", "spsr_abt", - "fpsr" + "cpsr", "spsr", "spsr_fiq", "spsr_irq", "spsr_svc", "spsr_und", + "spsr_abt", "fpsr", "fpsid", "fpscr", "fpexc", "sctlr" }; BitUnion32(CPSR) @@ -80,8 +81,10 @@ namespace ArmISA Bitfield<29> c; Bitfield<28> v; Bitfield<27> q; + Bitfield<26,25> it1; Bitfield<24> j; Bitfield<19, 16> ge; + Bitfield<15,10> it2; Bitfield<9> e; Bitfield<8> a; Bitfield<7> i; @@ -89,6 +92,35 @@ namespace ArmISA Bitfield<5> t; Bitfield<4, 0> mode; EndBitUnion(CPSR) + + // This mask selects bits of the CPSR that actually go in the CondCodes + // integer register to allow renaming. + static const uint32_t CondCodesMask = 0xF80F0000; + + BitUnion32(SCTLR) + Bitfield<30> te; // Thumb Exception Enable + Bitfield<29> afe; // Access flag enable + Bitfield<28> tre; // TEX Remap bit + Bitfield<27> nmfi;// Non-maskable fast interrupts enable + Bitfield<25> ee; // Exception Endianness bit + Bitfield<24> ve; // Interrupt vectors enable + Bitfield<23> rao1;// Read as one + Bitfield<22> u; // Alignment (now unused) + Bitfield<21> fi; // Fast interrupts configuration enable + Bitfield<18> rao2;// Read as one + Bitfield<17> ha; // Hardware access flag enable + Bitfield<16> rao3;// Read as one + Bitfield<14> rr; // Round robin cache replacement + Bitfield<13> v; // Base address for exception vectors + Bitfield<12> i; // instruction cache enable + Bitfield<11> z; // branch prediction enable bit + Bitfield<10> sw; // Enable swp/swpb + Bitfield<6,3> rao4;// Read as one + Bitfield<7> b; // Endianness support (unused) + Bitfield<2> c; // Cache enable bit + Bitfield<1> a; // Alignment fault checking + Bitfield<0> m; // MMU enable bit + EndBitUnion(SCTLR) }; #endif // __ARCH_ARM_MISCREGS_HH__ diff --git a/src/arch/arm/nativetrace.cc b/src/arch/arm/nativetrace.cc index 1ad9e1a19..01f3205eb 100644 --- a/src/arch/arm/nativetrace.cc +++ b/src/arch/arm/nativetrace.cc @@ -97,7 +97,8 @@ Trace::ArmNativeTrace::ThreadState::update(ThreadContext *tc) changed[STATE_PC] = (newState[STATE_PC] != oldState[STATE_PC]); //CPSR - newState[STATE_CPSR] = tc->readMiscReg(MISCREG_CPSR); + newState[STATE_CPSR] = tc->readMiscReg(MISCREG_CPSR) | + tc->readIntReg(INTREG_CONDCODES); changed[STATE_CPSR] = (newState[STATE_CPSR] != oldState[STATE_CPSR]); } diff --git a/src/arch/arm/process.cc b/src/arch/arm/process.cc index cd7cc9736..702922a43 100644 --- a/src/arch/arm/process.cc +++ b/src/arch/arm/process.cc @@ -324,10 +324,10 @@ ArmLiveProcess::argsInit(int intSize, int pageSize) } ArmISA::IntReg -ArmLiveProcess::getSyscallArg(ThreadContext *tc, int i) +ArmLiveProcess::getSyscallArg(ThreadContext *tc, int &i) { assert(i < 4); - return tc->readIntReg(ArgumentReg0 + i); + return tc->readIntReg(ArgumentReg0 + i++); } void diff --git a/src/arch/arm/process.hh b/src/arch/arm/process.hh index 8954d3719..f793892d0 100644 --- a/src/arch/arm/process.hh +++ b/src/arch/arm/process.hh @@ -53,7 +53,7 @@ class ArmLiveProcess : public LiveProcess public: void argsInit(int intSize, int pageSize); - ArmISA::IntReg getSyscallArg(ThreadContext *tc, int i); + ArmISA::IntReg getSyscallArg(ThreadContext *tc, int &i); void setSyscallArg(ThreadContext *tc, int i, ArmISA::IntReg val); void setSyscallReturn(ThreadContext *tc, SyscallReturn return_value); }; diff --git a/src/arch/arm/registers.hh b/src/arch/arm/registers.hh index 7f9b6b828..41bbf4e7f 100644 --- a/src/arch/arm/registers.hh +++ b/src/arch/arm/registers.hh @@ -32,6 +32,7 @@ #define __ARCH_ARM_REGISTERS_HH__ #include "arch/arm/max_inst_regs.hh" +#include "arch/arm/intregs.hh" #include "arch/arm/miscregs.hh" namespace ArmISA { @@ -51,13 +52,11 @@ typedef float FloatReg; typedef uint64_t MiscReg; // Constants Related to the number of registers -const int NumIntArchRegs = 16; -const int NumIntSpecialRegs = 19; +const int NumIntArchRegs = NUM_ARCH_INTREGS; const int NumFloatArchRegs = 16; const int NumFloatSpecialRegs = 5; -const int NumInternalProcRegs = 0; -const int NumIntRegs = NumIntArchRegs + NumIntSpecialRegs; +const int NumIntRegs = NUM_INTREGS; const int NumFloatRegs = NumFloatArchRegs + NumFloatSpecialRegs; const int NumMiscRegs = NUM_MISCREGS; @@ -72,12 +71,11 @@ const int ArgumentReg1 = 1; const int ArgumentReg2 = 2; const int ArgumentReg3 = 3; const int FramePointerReg = 11; -const int StackPointerReg = 13; -const int ReturnAddressReg = 14; -const int PCReg = 15; +const int StackPointerReg = INTREG_SP; +const int ReturnAddressReg = INTREG_LR; +const int PCReg = INTREG_PC; -const int ZeroReg = NumIntArchRegs; -const int AddrReg = ZeroReg + 1; // Used to generate address for uops +const int ZeroReg = INTREG_ZERO; const int SyscallNumReg = ReturnValueReg; const int SyscallPseudoReturnReg = ReturnValueReg; @@ -116,35 +114,6 @@ enum FCSRFields { Cause_Field = 11 }; -enum MiscIntRegNums { - zero_reg = NumIntArchRegs, - addr_reg, - - rhi, - rlo, - - r8_fiq, /* FIQ mode register bank */ - r9_fiq, - r10_fiq, - r11_fiq, - r12_fiq, - - r13_fiq, /* FIQ mode SP and LR */ - r14_fiq, - - r13_irq, /* IRQ mode SP and LR */ - r14_irq, - - r13_svc, /* SVC mode SP and LR */ - r14_svc, - - r13_undef, /* UNDEF mode SP and LR */ - r14_undef, - - r13_abt, /* ABT mode SP and LR */ - r14_abt -}; - } // namespace ArmISA #endif diff --git a/src/arch/arm/stacktrace.cc b/src/arch/arm/stacktrace.cc new file mode 100644 index 000000000..6b346b0ab --- /dev/null +++ b/src/arch/arm/stacktrace.cc @@ -0,0 +1,151 @@ +/* + * Copyright (c) 2005 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Nathan Binkert + */ + +#include <string> + +#include "arch/arm/isa_traits.hh" +#include "arch/arm/stacktrace.hh" +#include "arch/arm/vtophys.hh" +#include "base/bitfield.hh" +#include "base/trace.hh" +#include "cpu/base.hh" +#include "cpu/thread_context.hh" +#include "sim/system.hh" + +using namespace std; +namespace ArmISA +{ + ProcessInfo::ProcessInfo(ThreadContext *_tc) + : tc(_tc) + { + Addr addr = 0; + + VirtualPort *vp; + + vp = tc->getVirtPort(); + + if (!tc->getSystemPtr()->kernelSymtab->findAddress("thread_info_size", addr)) + panic("thread info not compiled into kernel\n"); + thread_info_size = vp->readGtoH<int32_t>(addr); + + if (!tc->getSystemPtr()->kernelSymtab->findAddress("task_struct_size", addr)) + panic("thread info not compiled into kernel\n"); + task_struct_size = vp->readGtoH<int32_t>(addr); + + if (!tc->getSystemPtr()->kernelSymtab->findAddress("thread_info_task", addr)) + panic("thread info not compiled into kernel\n"); + task_off = vp->readGtoH<int32_t>(addr); + + if (!tc->getSystemPtr()->kernelSymtab->findAddress("task_struct_pid", addr)) + panic("thread info not compiled into kernel\n"); + pid_off = vp->readGtoH<int32_t>(addr); + + if (!tc->getSystemPtr()->kernelSymtab->findAddress("task_struct_comm", addr)) + panic("thread info not compiled into kernel\n"); + name_off = vp->readGtoH<int32_t>(addr); + } + + Addr + ProcessInfo::task(Addr ksp) const + { + return 0; + } + + int + ProcessInfo::pid(Addr ksp) const + { + return -1; + } + + string + ProcessInfo::name(Addr ksp) const + { + return "Implement me"; + } + + StackTrace::StackTrace() + : tc(0), stack(64) + { + } + + StackTrace::StackTrace(ThreadContext *_tc, StaticInstPtr inst) + : tc(0), stack(64) + { + trace(_tc, inst); + } + + StackTrace::~StackTrace() + { + } + + void + StackTrace::trace(ThreadContext *_tc, bool is_call) + { + } + + bool + StackTrace::isEntry(Addr addr) + { + return false; + } + + bool + StackTrace::decodeStack(MachInst inst, int &disp) + { + return false; + } + + bool + StackTrace::decodeSave(MachInst inst, int ®, int &disp) + { + return false; + } + + /* + * Decode the function prologue for the function we're in, and note + * which registers are stored where, and how large the stack frame is. + */ + bool + StackTrace::decodePrologue(Addr sp, Addr callpc, Addr func, + int &size, Addr &ra) + { + return false; + } + +#if TRACING_ON + void + StackTrace::dump() + { + DPRINTFN("------ Stack ------\n"); + + DPRINTFN(" Not implemented\n"); + } +#endif +} diff --git a/src/arch/arm/stacktrace.hh b/src/arch/arm/stacktrace.hh index 3f9c91096..05fdb9e78 100644 --- a/src/arch/arm/stacktrace.hh +++ b/src/arch/arm/stacktrace.hh @@ -1,6 +1,5 @@ /* * Copyright (c) 2005 The Regents of The University of Michigan - * Copyright (c) 2007-2008 The Florida State University * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -26,8 +25,7 @@ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * - * Authors: Ali Saidi - * Stephen Hines + * Authors: Nathan Binkert */ #ifndef __ARCH_ARM_STACKTRACE_HH__ @@ -37,11 +35,11 @@ #include "cpu/static_inst.hh" class ThreadContext; -class StackTrace; - namespace ArmISA { +class StackTrace; + class ProcessInfo { private: @@ -64,7 +62,7 @@ class ProcessInfo class StackTrace { protected: - typedef TheISA::MachInst MachInst; + typedef ArmISA::MachInst MachInst; private: ThreadContext *tc; std::vector<Addr> stack; @@ -94,10 +92,6 @@ class StackTrace public: const std::vector<Addr> &getstack() const { return stack; } - static const int user = 1; - static const int console = 2; - static const int unknown = 3; - #if TRACING_ON private: void dump(); @@ -123,6 +117,6 @@ StackTrace::trace(ThreadContext *tc, StaticInstPtr inst) return true; } -} +} // Namespace ArmISA #endif // __ARCH_ARM_STACKTRACE_HH__ diff --git a/src/mem/slicc/ast/TypeFieldAST.cc b/src/arch/arm/system.cc index 5657d023c..e7470f89a 100644 --- a/src/mem/slicc/ast/TypeFieldAST.cc +++ b/src/arch/arm/system.cc @@ -1,6 +1,5 @@ - /* - * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood + * Copyright (c) 2002-2006 The Regents of The University of Michigan * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -25,20 +24,28 @@ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/* - * TypeFieldAST.C - * - * Description: See TypeFieldAST.hh - * - * $Id$ * + * Authors: Ali Saidi */ -#include "mem/slicc/ast/TypeFieldAST.hh" +#include "arch/arm/system.hh" + -TypeFieldAST::TypeFieldAST(PairListAST* pairs_ptr) - : AST(pairs_ptr->getPairs()) { +using namespace LittleEndianGuest; + +ArmSystem::ArmSystem(Params *p) + : System(p) +{ + +} + +ArmSystem::~ArmSystem() +{ } + +ArmSystem * +ArmSystemParams::create() +{ + return new ArmSystem(this); +} diff --git a/src/mem/slicc/ast/StatementAST.cc b/src/arch/arm/system.hh index 35627722a..9dfb66fb7 100644 --- a/src/mem/slicc/ast/StatementAST.cc +++ b/src/arch/arm/system.hh @@ -1,6 +1,5 @@ - /* - * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood + * Copyright (c) 2002-2005 The Regents of The University of Michigan * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -25,36 +24,33 @@ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/* - * StatementAST.C - * - * Description: See StatementAST.hh - * - * $Id$ * + * Authors: Ali Saidi */ -#include "mem/slicc/ast/StatementAST.hh" +#ifndef __ARCH_ARM_SYSTEM_HH__ +#define __ARCH_ARM_SYSTEM_HH__ -static int indentation_depth = 1; +#include <string> +#include <vector> -void inc_indent() -{ - indentation_depth++; -} +#include "params/ArmSystem.hh" +#include "sim/sim_object.hh" +#include "sim/system.hh" -void dec_indent() +class ArmSystem : public System { - indentation_depth--; -} + public: + typedef ArmSystemParams Params; + ArmSystem(Params *p); + ~ArmSystem(); + + virtual Addr fixFuncEventAddr(Addr addr) + { + //XXX This may eventually have to do something useful. + return addr; + } +}; + +#endif -string indent_str() -{ - string temp; - for(int i=0; i<indentation_depth; i++) { - temp += " "; - } - return temp; -} diff --git a/src/arch/arm/tlb.cc b/src/arch/arm/tlb.cc index febc6d081..864c061a2 100644 --- a/src/arch/arm/tlb.cc +++ b/src/arch/arm/tlb.cc @@ -287,7 +287,15 @@ TLB::translateAtomic(RequestPtr req, ThreadContext *tc, Mode mode) return NoFault; #else - fatal("translate atomic not yet implemented\n"); + SCTLR sctlr = tc->readMiscReg(MISCREG_SCTLR); + if (!sctlr.m) { + req->setPaddr(req->getVaddr()); + return NoFault; + } + panic("MMU translation not implemented\n"); + return NoFault; + + #endif } diff --git a/src/arch/arm/types.hh b/src/arch/arm/types.hh index 2c4e1291c..e0b3951b9 100644 --- a/src/arch/arm/types.hh +++ b/src/arch/arm/types.hh @@ -45,16 +45,20 @@ namespace ArmISA // All the different types of opcode fields. Bitfield<27, 25> encoding; + Bitfield<25> useImm; Bitfield<24, 21> opcode; Bitfield<24, 20> mediaOpcode; Bitfield<24> opcode24; Bitfield<23, 20> opcode23_20; Bitfield<23, 21> opcode23_21; + Bitfield<20> opcode20; Bitfield<22> opcode22; Bitfield<19> opcode19; + Bitfield<18> opcode18; Bitfield<15, 12> opcode15_12; Bitfield<15> opcode15; Bitfield<7, 4> miscOpcode; + Bitfield<7,5> opc2; Bitfield<7> opcode7; Bitfield<4> opcode4; @@ -156,6 +160,7 @@ namespace ArmISA MODE_FIQ = 17, MODE_IRQ = 18, MODE_SVC = 19, + MODE_MON = 22, MODE_ABORT = 23, MODE_UNDEFINED = 27, MODE_SYSTEM = 31 diff --git a/src/mem/slicc/ast/ExprStatementAST.cc b/src/arch/arm/utility.cc index f4bffaab3..5ce32542b 100644 --- a/src/mem/slicc/ast/ExprStatementAST.cc +++ b/src/arch/arm/utility.cc @@ -1,6 +1,5 @@ - /* - * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood + * Copyright (c) 2009 ARM Limited * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -25,49 +24,53 @@ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/* - * ExprStatementAST.C - * - * Description: See ExprStatementAST.hh - * - * $Id$ * + * Authors: Ali Saidi */ -#include "mem/slicc/ast/ExprStatementAST.hh" -ExprStatementAST::ExprStatementAST(ExprAST* expr_ptr) - : StatementAST() +#include "arch/arm/faults.hh" +#include "arch/arm/utility.hh" +#include "cpu/thread_context.hh" + + +namespace ArmISA { + +void +initCPU(ThreadContext *tc, int cpuId) { - m_expr_ptr = expr_ptr; + // Reset CP15?? What does that mean -- ali + + // FPEXC.EN = 0 + + static Fault reset = new Reset; + if (cpuId == 0) + reset->invoke(tc); } -ExprStatementAST::~ExprStatementAST() -{ - delete m_expr_ptr; +uint64_t getArgument(ThreadContext *tc, int number, bool fp) { +#if FULL_SYSTEM + panic("getArgument() not implemented for ARM!\n"); +#else + panic("getArgument() only implemented for FULL_SYSTEM\n"); + M5_DUMMY_RETURN +#endif } -void ExprStatementAST::generate(string& code, Type* return_type_ptr) const +Fault +setCp15Register(uint32_t &Rd, int CRn, int opc1, int CRm, int opc2) { - code += indent_str(); - Type* actual_type_ptr = m_expr_ptr->generate(code); - code += ";\n"; - - // The return type must be void - Type* expected_type_ptr = g_sym_table.getType("void"); - if (expected_type_ptr != actual_type_ptr) { - m_expr_ptr->error("Non-void return must not be ignored, return type is '" + actual_type_ptr->toString() + "'"); - } + return new UnimpFault(csprintf("MCR CP15: CRn: %d opc1: %d CRm: %d opc1: %d\n", + CRn, opc1, CRm, opc2)); } -void ExprStatementAST::findResources(Map<Var*, string>& resource_list) const +Fault +readCp15Register(uint32_t &Rd, int CRn, int opc1, int CRm, int opc2) { - m_expr_ptr->findResources(resource_list); + return new UnimpFault(csprintf("MRC CP15: CRn: %d opc1: %d CRm: %d opc1: %d\n", + CRn, opc1, CRm, opc2)); + } -void ExprStatementAST::print(ostream& out) const -{ - out << "[ExprStatementAST: " << *m_expr_ptr << "]"; + } diff --git a/src/arch/arm/utility.hh b/src/arch/arm/utility.hh index a2f0ef170..3ddfd12dd 100644 --- a/src/arch/arm/utility.hh +++ b/src/arch/arm/utility.hh @@ -125,6 +125,20 @@ namespace ArmISA { { panic("Copy Misc. Regs Not Implemented Yet\n"); } + + void initCPU(ThreadContext *tc, int cpuId); + + static inline bool + inUserMode(ThreadContext *tc) + { + return (tc->readMiscRegNoEffect(MISCREG_CPSR) & 0x1f) == MODE_USER; + } + +uint64_t getArgument(ThreadContext *tc, int number, bool fp); + +Fault setCp15Register(uint32_t &Rd, int CRn, int opc1, int CRm, int opc2); +Fault readCp15Register(uint32_t &Rd, int CRn, int opc1, int CRm, int opc2); + }; diff --git a/src/arch/isa_parser.py b/src/arch/isa_parser.py index d5b5bbe4f..2db7c6aa6 100755 --- a/src/arch/isa_parser.py +++ b/src/arch/isa_parser.py @@ -34,702 +34,704 @@ import traceback # get type names from types import * -# Prepend the directory where the PLY lex & yacc modules are found -# to the search path. Assumes we're compiling in a subdirectory -# of 'build' in the current tree. -sys.path[0:0] = [os.environ['M5_PLY']] - -from ply import lex -from ply import yacc - -##################################################################### -# -# Lexer -# -# The PLY lexer module takes two things as input: -# - A list of token names (the string list 'tokens') -# - A regular expression describing a match for each token. The -# regexp for token FOO can be provided in two ways: -# - as a string variable named t_FOO -# - as the doc string for a function named t_FOO. In this case, -# the function is also executed, allowing an action to be -# associated with each token match. -# -##################################################################### - -# Reserved words. These are listed separately as they are matched -# using the same regexp as generic IDs, but distinguished in the -# t_ID() function. The PLY documentation suggests this approach. -reserved = ( - 'BITFIELD', 'DECODE', 'DECODER', 'DEFAULT', 'DEF', 'EXEC', 'FORMAT', - 'HEADER', 'LET', 'NAMESPACE', 'OPERAND_TYPES', 'OPERANDS', - 'OUTPUT', 'SIGNED', 'TEMPLATE' +from m5.util.grammar import Grammar + +class ISAParser(Grammar): + def __init__(self, *args, **kwargs): + super(ISAParser, self).__init__(*args, **kwargs) + self.templateMap = {} + + ##################################################################### + # + # Lexer + # + # The PLY lexer module takes two things as input: + # - A list of token names (the string list 'tokens') + # - A regular expression describing a match for each token. The + # regexp for token FOO can be provided in two ways: + # - as a string variable named t_FOO + # - as the doc string for a function named t_FOO. In this case, + # the function is also executed, allowing an action to be + # associated with each token match. + # + ##################################################################### + + # Reserved words. These are listed separately as they are matched + # using the same regexp as generic IDs, but distinguished in the + # t_ID() function. The PLY documentation suggests this approach. + reserved = ( + 'BITFIELD', 'DECODE', 'DECODER', 'DEFAULT', 'DEF', 'EXEC', 'FORMAT', + 'HEADER', 'LET', 'NAMESPACE', 'OPERAND_TYPES', 'OPERANDS', + 'OUTPUT', 'SIGNED', 'TEMPLATE' + ) + + # List of tokens. The lex module requires this. + tokens = reserved + ( + # identifier + 'ID', + + # integer literal + 'INTLIT', + + # string literal + 'STRLIT', + + # code literal + 'CODELIT', + + # ( ) [ ] { } < > , ; . : :: * + 'LPAREN', 'RPAREN', + 'LBRACKET', 'RBRACKET', + 'LBRACE', 'RBRACE', + 'LESS', 'GREATER', 'EQUALS', + 'COMMA', 'SEMI', 'DOT', 'COLON', 'DBLCOLON', + 'ASTERISK', + + # C preprocessor directives + 'CPPDIRECTIVE' + + # The following are matched but never returned. commented out to + # suppress PLY warning + # newfile directive + # 'NEWFILE', + + # endfile directive + # 'ENDFILE' ) -# List of tokens. The lex module requires this. -tokens = reserved + ( - # identifier - 'ID', - - # integer literal - 'INTLIT', - - # string literal - 'STRLIT', - - # code literal - 'CODELIT', - - # ( ) [ ] { } < > , ; . : :: * - 'LPAREN', 'RPAREN', - 'LBRACKET', 'RBRACKET', - 'LBRACE', 'RBRACE', - 'LESS', 'GREATER', 'EQUALS', - 'COMMA', 'SEMI', 'DOT', 'COLON', 'DBLCOLON', - 'ASTERISK', - - # C preprocessor directives - 'CPPDIRECTIVE' - -# The following are matched but never returned. commented out to -# suppress PLY warning - # newfile directive -# 'NEWFILE', - - # endfile directive -# 'ENDFILE' -) - -# Regular expressions for token matching -t_LPAREN = r'\(' -t_RPAREN = r'\)' -t_LBRACKET = r'\[' -t_RBRACKET = r'\]' -t_LBRACE = r'\{' -t_RBRACE = r'\}' -t_LESS = r'\<' -t_GREATER = r'\>' -t_EQUALS = r'=' -t_COMMA = r',' -t_SEMI = r';' -t_DOT = r'\.' -t_COLON = r':' -t_DBLCOLON = r'::' -t_ASTERISK = r'\*' - -# Identifiers and reserved words -reserved_map = { } -for r in reserved: - reserved_map[r.lower()] = r - -def t_ID(t): - r'[A-Za-z_]\w*' - t.type = reserved_map.get(t.value,'ID') - return t - -# Integer literal -def t_INTLIT(t): - r'(0x[\da-fA-F]+)|\d+' - try: - t.value = int(t.value,0) - except ValueError: - error(t.lexer.lineno, 'Integer value "%s" too large' % t.value) - t.value = 0 - return t - -# String literal. Note that these use only single quotes, and -# can span multiple lines. -def t_STRLIT(t): - r"(?m)'([^'])+'" - # strip off quotes - t.value = t.value[1:-1] - t.lexer.lineno += t.value.count('\n') - return t - - -# "Code literal"... like a string literal, but delimiters are -# '{{' and '}}' so they get formatted nicely under emacs c-mode -def t_CODELIT(t): - r"(?m)\{\{([^\}]|}(?!\}))+\}\}" - # strip off {{ & }} - t.value = t.value[2:-2] - t.lexer.lineno += t.value.count('\n') - return t - -def t_CPPDIRECTIVE(t): - r'^\#[^\#].*\n' - t.lexer.lineno += t.value.count('\n') - return t - -def t_NEWFILE(t): - r'^\#\#newfile\s+"[\w/.-]*"' - fileNameStack.push((t.value[11:-1], t.lexer.lineno)) - t.lexer.lineno = 0 - -def t_ENDFILE(t): - r'^\#\#endfile' - (old_filename, t.lexer.lineno) = fileNameStack.pop() - -# -# The functions t_NEWLINE, t_ignore, and t_error are -# special for the lex module. -# - -# Newlines -def t_NEWLINE(t): - r'\n+' - t.lexer.lineno += t.value.count('\n') - -# Comments -def t_comment(t): - r'//.*' - -# Completely ignored characters -t_ignore = ' \t\x0c' - -# Error handler -def t_error(t): - error(t.lexer.lineno, "illegal character '%s'" % t.value[0]) - t.skip(1) - -# Build the lexer -lexer = lex.lex() - -##################################################################### -# -# Parser -# -# Every function whose name starts with 'p_' defines a grammar rule. -# The rule is encoded in the function's doc string, while the -# function body provides the action taken when the rule is matched. -# The argument to each function is a list of the values of the -# rule's symbols: t[0] for the LHS, and t[1..n] for the symbols -# on the RHS. For tokens, the value is copied from the t.value -# attribute provided by the lexer. For non-terminals, the value -# is assigned by the producing rule; i.e., the job of the grammar -# rule function is to set the value for the non-terminal on the LHS -# (by assigning to t[0]). -##################################################################### - -# The LHS of the first grammar rule is used as the start symbol -# (in this case, 'specification'). Note that this rule enforces -# that there will be exactly one namespace declaration, with 0 or more -# global defs/decls before and after it. The defs & decls before -# the namespace decl will be outside the namespace; those after -# will be inside. The decoder function is always inside the namespace. -def p_specification(t): - 'specification : opt_defs_and_outputs name_decl opt_defs_and_outputs decode_block' - global_code = t[1] - isa_name = t[2] - namespace = isa_name + "Inst" - # wrap the decode block as a function definition - t[4].wrap_decode_block(''' + # Regular expressions for token matching + t_LPAREN = r'\(' + t_RPAREN = r'\)' + t_LBRACKET = r'\[' + t_RBRACKET = r'\]' + t_LBRACE = r'\{' + t_RBRACE = r'\}' + t_LESS = r'\<' + t_GREATER = r'\>' + t_EQUALS = r'=' + t_COMMA = r',' + t_SEMI = r';' + t_DOT = r'\.' + t_COLON = r':' + t_DBLCOLON = r'::' + t_ASTERISK = r'\*' + + # Identifiers and reserved words + reserved_map = { } + for r in reserved: + reserved_map[r.lower()] = r + + def t_ID(self, t): + r'[A-Za-z_]\w*' + t.type = self.reserved_map.get(t.value, 'ID') + return t + + # Integer literal + def t_INTLIT(self, t): + r'(0x[\da-fA-F]+)|\d+' + try: + t.value = int(t.value,0) + except ValueError: + error(t.lexer.lineno, 'Integer value "%s" too large' % t.value) + t.value = 0 + return t + + # String literal. Note that these use only single quotes, and + # can span multiple lines. + def t_STRLIT(self, t): + r"(?m)'([^'])+'" + # strip off quotes + t.value = t.value[1:-1] + t.lexer.lineno += t.value.count('\n') + return t + + + # "Code literal"... like a string literal, but delimiters are + # '{{' and '}}' so they get formatted nicely under emacs c-mode + def t_CODELIT(self, t): + r"(?m)\{\{([^\}]|}(?!\}))+\}\}" + # strip off {{ & }} + t.value = t.value[2:-2] + t.lexer.lineno += t.value.count('\n') + return t + + def t_CPPDIRECTIVE(self, t): + r'^\#[^\#].*\n' + t.lexer.lineno += t.value.count('\n') + return t + + def t_NEWFILE(self, t): + r'^\#\#newfile\s+"[\w/.-]*"' + fileNameStack.push((t.value[11:-1], t.lexer.lineno)) + t.lexer.lineno = 0 + + def t_ENDFILE(self, t): + r'^\#\#endfile' + (old_filename, t.lexer.lineno) = fileNameStack.pop() + + # + # The functions t_NEWLINE, t_ignore, and t_error are + # special for the lex module. + # + + # Newlines + def t_NEWLINE(self, t): + r'\n+' + t.lexer.lineno += t.value.count('\n') + + # Comments + def t_comment(self, t): + r'//.*' + + # Completely ignored characters + t_ignore = ' \t\x0c' + + # Error handler + def t_error(self, t): + error(t.lexer.lineno, "illegal character '%s'" % t.value[0]) + t.skip(1) + + ##################################################################### + # + # Parser + # + # Every function whose name starts with 'p_' defines a grammar + # rule. The rule is encoded in the function's doc string, while + # the function body provides the action taken when the rule is + # matched. The argument to each function is a list of the values + # of the rule's symbols: t[0] for the LHS, and t[1..n] for the + # symbols on the RHS. For tokens, the value is copied from the + # t.value attribute provided by the lexer. For non-terminals, the + # value is assigned by the producing rule; i.e., the job of the + # grammar rule function is to set the value for the non-terminal + # on the LHS (by assigning to t[0]). + ##################################################################### + + # The LHS of the first grammar rule is used as the start symbol + # (in this case, 'specification'). Note that this rule enforces + # that there will be exactly one namespace declaration, with 0 or + # more global defs/decls before and after it. The defs & decls + # before the namespace decl will be outside the namespace; those + # after will be inside. The decoder function is always inside the + # namespace. + def p_specification(self, t): + 'specification : opt_defs_and_outputs name_decl opt_defs_and_outputs decode_block' + global_code = t[1] + isa_name = t[2] + namespace = isa_name + "Inst" + # wrap the decode block as a function definition + t[4].wrap_decode_block(''' StaticInstPtr %(isa_name)s::decodeInst(%(isa_name)s::ExtMachInst machInst) { using namespace %(namespace)s; ''' % vars(), '}') - # both the latter output blocks and the decode block are in the namespace - namespace_code = t[3] + t[4] - # pass it all back to the caller of yacc.parse() - t[0] = (isa_name, namespace, global_code, namespace_code) - -# ISA name declaration looks like "namespace <foo>;" -def p_name_decl(t): - 'name_decl : NAMESPACE ID SEMI' - t[0] = t[2] - -# 'opt_defs_and_outputs' is a possibly empty sequence of -# def and/or output statements. -def p_opt_defs_and_outputs_0(t): - 'opt_defs_and_outputs : empty' - t[0] = GenCode() - -def p_opt_defs_and_outputs_1(t): - 'opt_defs_and_outputs : defs_and_outputs' - t[0] = t[1] - -def p_defs_and_outputs_0(t): - 'defs_and_outputs : def_or_output' - t[0] = t[1] - -def p_defs_and_outputs_1(t): - 'defs_and_outputs : defs_and_outputs def_or_output' - t[0] = t[1] + t[2] - -# The list of possible definition/output statements. -def p_def_or_output(t): - '''def_or_output : def_format - | def_bitfield - | def_bitfield_struct - | def_template - | def_operand_types - | def_operands - | output_header - | output_decoder - | output_exec - | global_let''' - t[0] = t[1] - -# Output blocks 'output <foo> {{...}}' (C++ code blocks) are copied -# directly to the appropriate output section. - - -# Protect any non-dict-substitution '%'s in a format string -# (i.e. those not followed by '(') -def protect_non_subst_percents(s): - return re.sub(r'%(?!\()', '%%', s) - -# Massage output block by substituting in template definitions and bit -# operators. We handle '%'s embedded in the string that don't -# indicate template substitutions (or CPU-specific symbols, which get -# handled in GenCode) by doubling them first so that the format -# operation will reduce them back to single '%'s. -def process_output(s): - s = protect_non_subst_percents(s) - # protects cpu-specific symbols too - s = protect_cpu_symbols(s) - return substBitOps(s % templateMap) - -def p_output_header(t): - 'output_header : OUTPUT HEADER CODELIT SEMI' - t[0] = GenCode(header_output = process_output(t[3])) - -def p_output_decoder(t): - 'output_decoder : OUTPUT DECODER CODELIT SEMI' - t[0] = GenCode(decoder_output = process_output(t[3])) - -def p_output_exec(t): - 'output_exec : OUTPUT EXEC CODELIT SEMI' - t[0] = GenCode(exec_output = process_output(t[3])) - -# global let blocks 'let {{...}}' (Python code blocks) are executed -# directly when seen. Note that these execute in a special variable -# context 'exportContext' to prevent the code from polluting this -# script's namespace. -def p_global_let(t): - 'global_let : LET CODELIT SEMI' - updateExportContext() - exportContext["header_output"] = '' - exportContext["decoder_output"] = '' - exportContext["exec_output"] = '' - exportContext["decode_block"] = '' - try: - exec fixPythonIndentation(t[2]) in exportContext - except Exception, exc: - error(t.lexer.lineno, - 'error: %s in global let block "%s".' % (exc, t[2])) - t[0] = GenCode(header_output = exportContext["header_output"], - decoder_output = exportContext["decoder_output"], - exec_output = exportContext["exec_output"], - decode_block = exportContext["decode_block"]) - -# Define the mapping from operand type extensions to C++ types and bit -# widths (stored in operandTypeMap). -def p_def_operand_types(t): - 'def_operand_types : DEF OPERAND_TYPES CODELIT SEMI' - try: - userDict = eval('{' + t[3] + '}') - except Exception, exc: - error(t.lexer.lineno, - 'error: %s in def operand_types block "%s".' % (exc, t[3])) - buildOperandTypeMap(userDict, t.lexer.lineno) - t[0] = GenCode() # contributes nothing to the output C++ file - -# Define the mapping from operand names to operand classes and other -# traits. Stored in operandNameMap. -def p_def_operands(t): - 'def_operands : DEF OPERANDS CODELIT SEMI' - if not globals().has_key('operandTypeMap'): - error(t.lexer.lineno, - 'error: operand types must be defined before operands') - try: - userDict = eval('{' + t[3] + '}', exportContext) - except Exception, exc: - error(t.lexer.lineno, - 'error: %s in def operands block "%s".' % (exc, t[3])) - buildOperandNameMap(userDict, t.lexer.lineno) - t[0] = GenCode() # contributes nothing to the output C++ file - -# A bitfield definition looks like: -# 'def [signed] bitfield <ID> [<first>:<last>]' -# This generates a preprocessor macro in the output file. -def p_def_bitfield_0(t): - 'def_bitfield : DEF opt_signed BITFIELD ID LESS INTLIT COLON INTLIT GREATER SEMI' - expr = 'bits(machInst, %2d, %2d)' % (t[6], t[8]) - if (t[2] == 'signed'): - expr = 'sext<%d>(%s)' % (t[6] - t[8] + 1, expr) - hash_define = '#undef %s\n#define %s\t%s\n' % (t[4], t[4], expr) - t[0] = GenCode(header_output = hash_define) - -# alternate form for single bit: 'def [signed] bitfield <ID> [<bit>]' -def p_def_bitfield_1(t): - 'def_bitfield : DEF opt_signed BITFIELD ID LESS INTLIT GREATER SEMI' - expr = 'bits(machInst, %2d, %2d)' % (t[6], t[6]) - if (t[2] == 'signed'): - expr = 'sext<%d>(%s)' % (1, expr) - hash_define = '#undef %s\n#define %s\t%s\n' % (t[4], t[4], expr) - t[0] = GenCode(header_output = hash_define) - -# alternate form for structure member: 'def bitfield <ID> <ID>' -def p_def_bitfield_struct(t): - 'def_bitfield_struct : DEF opt_signed BITFIELD ID id_with_dot SEMI' - if (t[2] != ''): - error(t.lexer.lineno, 'error: structure bitfields are always unsigned.') - expr = 'machInst.%s' % t[5] - hash_define = '#undef %s\n#define %s\t%s\n' % (t[4], t[4], expr) - t[0] = GenCode(header_output = hash_define) - -def p_id_with_dot_0(t): - 'id_with_dot : ID' - t[0] = t[1] - -def p_id_with_dot_1(t): - 'id_with_dot : ID DOT id_with_dot' - t[0] = t[1] + t[2] + t[3] - -def p_opt_signed_0(t): - 'opt_signed : SIGNED' - t[0] = t[1] - -def p_opt_signed_1(t): - 'opt_signed : empty' - t[0] = '' - -# Global map variable to hold templates -templateMap = {} - -def p_def_template(t): - 'def_template : DEF TEMPLATE ID CODELIT SEMI' - templateMap[t[3]] = Template(t[4]) - t[0] = GenCode() - -# An instruction format definition looks like -# "def format <fmt>(<params>) {{...}};" -def p_def_format(t): - 'def_format : DEF FORMAT ID LPAREN param_list RPAREN CODELIT SEMI' - (id, params, code) = (t[3], t[5], t[7]) - defFormat(id, params, code, t.lexer.lineno) - t[0] = GenCode() - -# The formal parameter list for an instruction format is a possibly -# empty list of comma-separated parameters. Positional (standard, -# non-keyword) parameters must come first, followed by keyword -# parameters, followed by a '*foo' parameter that gets excess -# positional arguments (as in Python). Each of these three parameter -# categories is optional. -# -# Note that we do not support the '**foo' parameter for collecting -# otherwise undefined keyword args. Otherwise the parameter list is -# (I believe) identical to what is supported in Python. -# -# The param list generates a tuple, where the first element is a list of -# the positional params and the second element is a dict containing the -# keyword params. -def p_param_list_0(t): - 'param_list : positional_param_list COMMA nonpositional_param_list' - t[0] = t[1] + t[3] - -def p_param_list_1(t): - '''param_list : positional_param_list - | nonpositional_param_list''' - t[0] = t[1] - -def p_positional_param_list_0(t): - 'positional_param_list : empty' - t[0] = [] - -def p_positional_param_list_1(t): - 'positional_param_list : ID' - t[0] = [t[1]] - -def p_positional_param_list_2(t): - 'positional_param_list : positional_param_list COMMA ID' - t[0] = t[1] + [t[3]] - -def p_nonpositional_param_list_0(t): - 'nonpositional_param_list : keyword_param_list COMMA excess_args_param' - t[0] = t[1] + t[3] - -def p_nonpositional_param_list_1(t): - '''nonpositional_param_list : keyword_param_list - | excess_args_param''' - t[0] = t[1] - -def p_keyword_param_list_0(t): - 'keyword_param_list : keyword_param' - t[0] = [t[1]] - -def p_keyword_param_list_1(t): - 'keyword_param_list : keyword_param_list COMMA keyword_param' - t[0] = t[1] + [t[3]] - -def p_keyword_param(t): - 'keyword_param : ID EQUALS expr' - t[0] = t[1] + ' = ' + t[3].__repr__() - -def p_excess_args_param(t): - 'excess_args_param : ASTERISK ID' - # Just concatenate them: '*ID'. Wrap in list to be consistent - # with positional_param_list and keyword_param_list. - t[0] = [t[1] + t[2]] - -# End of format definition-related rules. -############## - -# -# A decode block looks like: -# decode <field1> [, <field2>]* [default <inst>] { ... } -# -def p_decode_block(t): - 'decode_block : DECODE ID opt_default LBRACE decode_stmt_list RBRACE' - default_defaults = defaultStack.pop() - codeObj = t[5] - # use the "default defaults" only if there was no explicit - # default statement in decode_stmt_list - if not codeObj.has_decode_default: - codeObj += default_defaults - codeObj.wrap_decode_block('switch (%s) {\n' % t[2], '}\n') - t[0] = codeObj - -# The opt_default statement serves only to push the "default defaults" -# onto defaultStack. This value will be used by nested decode blocks, -# and used and popped off when the current decode_block is processed -# (in p_decode_block() above). -def p_opt_default_0(t): - 'opt_default : empty' - # no default specified: reuse the one currently at the top of the stack - defaultStack.push(defaultStack.top()) - # no meaningful value returned - t[0] = None - -def p_opt_default_1(t): - 'opt_default : DEFAULT inst' - # push the new default - codeObj = t[2] - codeObj.wrap_decode_block('\ndefault:\n', 'break;\n') - defaultStack.push(codeObj) - # no meaningful value returned - t[0] = None - -def p_decode_stmt_list_0(t): - 'decode_stmt_list : decode_stmt' - t[0] = t[1] - -def p_decode_stmt_list_1(t): - 'decode_stmt_list : decode_stmt decode_stmt_list' - if (t[1].has_decode_default and t[2].has_decode_default): - error(t.lexer.lineno, 'Two default cases in decode block') - t[0] = t[1] + t[2] - -# -# Decode statement rules -# -# There are four types of statements allowed in a decode block: -# 1. Format blocks 'format <foo> { ... }' -# 2. Nested decode blocks -# 3. Instruction definitions. -# 4. C preprocessor directives. - - -# Preprocessor directives found in a decode statement list are passed -# through to the output, replicated to all of the output code -# streams. This works well for ifdefs, so we can ifdef out both the -# declarations and the decode cases generated by an instruction -# definition. Handling them as part of the grammar makes it easy to -# keep them in the right place with respect to the code generated by -# the other statements. -def p_decode_stmt_cpp(t): - 'decode_stmt : CPPDIRECTIVE' - t[0] = GenCode(t[1], t[1], t[1], t[1]) - -# A format block 'format <foo> { ... }' sets the default instruction -# format used to handle instruction definitions inside the block. -# This format can be overridden by using an explicit format on the -# instruction definition or with a nested format block. -def p_decode_stmt_format(t): - 'decode_stmt : FORMAT push_format_id LBRACE decode_stmt_list RBRACE' - # The format will be pushed on the stack when 'push_format_id' is - # processed (see below). Once the parser has recognized the full - # production (though the right brace), we're done with the format, - # so now we can pop it. - formatStack.pop() - t[0] = t[4] - -# This rule exists so we can set the current format (& push the stack) -# when we recognize the format name part of the format block. -def p_push_format_id(t): - 'push_format_id : ID' - try: - formatStack.push(formatMap[t[1]]) - t[0] = ('', '// format %s' % t[1]) - except KeyError: - error(t.lexer.lineno, 'instruction format "%s" not defined.' % t[1]) - -# Nested decode block: if the value of the current field matches the -# specified constant, do a nested decode on some other field. -def p_decode_stmt_decode(t): - 'decode_stmt : case_label COLON decode_block' - label = t[1] - codeObj = t[3] - # just wrap the decoding code from the block as a case in the - # outer switch statement. - codeObj.wrap_decode_block('\n%s:\n' % label) - codeObj.has_decode_default = (label == 'default') - t[0] = codeObj - -# Instruction definition (finally!). -def p_decode_stmt_inst(t): - 'decode_stmt : case_label COLON inst SEMI' - label = t[1] - codeObj = t[3] - codeObj.wrap_decode_block('\n%s:' % label, 'break;\n') - codeObj.has_decode_default = (label == 'default') - t[0] = codeObj - -# The case label is either a list of one or more constants or 'default' -def p_case_label_0(t): - 'case_label : intlit_list' - t[0] = ': '.join(map(lambda a: 'case %#x' % a, t[1])) - -def p_case_label_1(t): - 'case_label : DEFAULT' - t[0] = 'default' - -# -# The constant list for a decode case label must be non-empty, but may have -# one or more comma-separated integer literals in it. -# -def p_intlit_list_0(t): - 'intlit_list : INTLIT' - t[0] = [t[1]] - -def p_intlit_list_1(t): - 'intlit_list : intlit_list COMMA INTLIT' - t[0] = t[1] - t[0].append(t[3]) - -# Define an instruction using the current instruction format (specified -# by an enclosing format block). -# "<mnemonic>(<args>)" -def p_inst_0(t): - 'inst : ID LPAREN arg_list RPAREN' - # Pass the ID and arg list to the current format class to deal with. - currentFormat = formatStack.top() - codeObj = currentFormat.defineInst(t[1], t[3], t.lexer.lineno) - args = ','.join(map(str, t[3])) - args = re.sub('(?m)^', '//', args) - args = re.sub('^//', '', args) - comment = '\n// %s::%s(%s)\n' % (currentFormat.id, t[1], args) - codeObj.prepend_all(comment) - t[0] = codeObj - -# Define an instruction using an explicitly specified format: -# "<fmt>::<mnemonic>(<args>)" -def p_inst_1(t): - 'inst : ID DBLCOLON ID LPAREN arg_list RPAREN' - try: - format = formatMap[t[1]] - except KeyError: - error(t.lexer.lineno, 'instruction format "%s" not defined.' % t[1]) - codeObj = format.defineInst(t[3], t[5], t.lexer.lineno) - comment = '\n// %s::%s(%s)\n' % (t[1], t[3], t[5]) - codeObj.prepend_all(comment) - t[0] = codeObj - -# The arg list generates a tuple, where the first element is a list of -# the positional args and the second element is a dict containing the -# keyword args. -def p_arg_list_0(t): - 'arg_list : positional_arg_list COMMA keyword_arg_list' - t[0] = ( t[1], t[3] ) - -def p_arg_list_1(t): - 'arg_list : positional_arg_list' - t[0] = ( t[1], {} ) - -def p_arg_list_2(t): - 'arg_list : keyword_arg_list' - t[0] = ( [], t[1] ) - -def p_positional_arg_list_0(t): - 'positional_arg_list : empty' - t[0] = [] - -def p_positional_arg_list_1(t): - 'positional_arg_list : expr' - t[0] = [t[1]] - -def p_positional_arg_list_2(t): - 'positional_arg_list : positional_arg_list COMMA expr' - t[0] = t[1] + [t[3]] - -def p_keyword_arg_list_0(t): - 'keyword_arg_list : keyword_arg' - t[0] = t[1] - -def p_keyword_arg_list_1(t): - 'keyword_arg_list : keyword_arg_list COMMA keyword_arg' - t[0] = t[1] - t[0].update(t[3]) - -def p_keyword_arg(t): - 'keyword_arg : ID EQUALS expr' - t[0] = { t[1] : t[3] } - -# -# Basic expressions. These constitute the argument values of -# "function calls" (i.e. instruction definitions in the decode block) -# and default values for formal parameters of format functions. -# -# Right now, these are either strings, integers, or (recursively) -# lists of exprs (using Python square-bracket list syntax). Note that -# bare identifiers are trated as string constants here (since there -# isn't really a variable namespace to refer to). -# -def p_expr_0(t): - '''expr : ID - | INTLIT - | STRLIT - | CODELIT''' - t[0] = t[1] - -def p_expr_1(t): - '''expr : LBRACKET list_expr RBRACKET''' - t[0] = t[2] - -def p_list_expr_0(t): - 'list_expr : expr' - t[0] = [t[1]] - -def p_list_expr_1(t): - 'list_expr : list_expr COMMA expr' - t[0] = t[1] + [t[3]] - -def p_list_expr_2(t): - 'list_expr : empty' - t[0] = [] + # both the latter output blocks and the decode block are in + # the namespace + namespace_code = t[3] + t[4] + # pass it all back to the caller of yacc.parse() + t[0] = (isa_name, namespace, global_code, namespace_code) + + # ISA name declaration looks like "namespace <foo>;" + def p_name_decl(self, t): + 'name_decl : NAMESPACE ID SEMI' + t[0] = t[2] + + # 'opt_defs_and_outputs' is a possibly empty sequence of + # def and/or output statements. + def p_opt_defs_and_outputs_0(self, t): + 'opt_defs_and_outputs : empty' + t[0] = GenCode() + + def p_opt_defs_and_outputs_1(self, t): + 'opt_defs_and_outputs : defs_and_outputs' + t[0] = t[1] + + def p_defs_and_outputs_0(self, t): + 'defs_and_outputs : def_or_output' + t[0] = t[1] + + def p_defs_and_outputs_1(self, t): + 'defs_and_outputs : defs_and_outputs def_or_output' + t[0] = t[1] + t[2] + + # The list of possible definition/output statements. + def p_def_or_output(self, t): + '''def_or_output : def_format + | def_bitfield + | def_bitfield_struct + | def_template + | def_operand_types + | def_operands + | output_header + | output_decoder + | output_exec + | global_let''' + t[0] = t[1] + + # Output blocks 'output <foo> {{...}}' (C++ code blocks) are copied + # directly to the appropriate output section. + + # Massage output block by substituting in template definitions and + # bit operators. We handle '%'s embedded in the string that don't + # indicate template substitutions (or CPU-specific symbols, which + # get handled in GenCode) by doubling them first so that the + # format operation will reduce them back to single '%'s. + def process_output(self, s): + s = protect_non_subst_percents(s) + # protects cpu-specific symbols too + s = protect_cpu_symbols(s) + return substBitOps(s % self.templateMap) + + def p_output_header(self, t): + 'output_header : OUTPUT HEADER CODELIT SEMI' + t[0] = GenCode(header_output = self.process_output(t[3])) + + def p_output_decoder(self, t): + 'output_decoder : OUTPUT DECODER CODELIT SEMI' + t[0] = GenCode(decoder_output = self.process_output(t[3])) + + def p_output_exec(self, t): + 'output_exec : OUTPUT EXEC CODELIT SEMI' + t[0] = GenCode(exec_output = self.process_output(t[3])) + + # global let blocks 'let {{...}}' (Python code blocks) are + # executed directly when seen. Note that these execute in a + # special variable context 'exportContext' to prevent the code + # from polluting this script's namespace. + def p_global_let(self, t): + 'global_let : LET CODELIT SEMI' + updateExportContext() + exportContext["header_output"] = '' + exportContext["decoder_output"] = '' + exportContext["exec_output"] = '' + exportContext["decode_block"] = '' + try: + exec fixPythonIndentation(t[2]) in exportContext + except Exception, exc: + error(t.lexer.lineno, + 'error: %s in global let block "%s".' % (exc, t[2])) + t[0] = GenCode(header_output = exportContext["header_output"], + decoder_output = exportContext["decoder_output"], + exec_output = exportContext["exec_output"], + decode_block = exportContext["decode_block"]) + + # Define the mapping from operand type extensions to C++ types and + # bit widths (stored in operandTypeMap). + def p_def_operand_types(self, t): + 'def_operand_types : DEF OPERAND_TYPES CODELIT SEMI' + try: + userDict = eval('{' + t[3] + '}') + except Exception, exc: + error(t.lexer.lineno, + 'error: %s in def operand_types block "%s".' % (exc, t[3])) + buildOperandTypeMap(userDict, t.lexer.lineno) + t[0] = GenCode() # contributes nothing to the output C++ file + + # Define the mapping from operand names to operand classes and + # other traits. Stored in operandNameMap. + def p_def_operands(self, t): + 'def_operands : DEF OPERANDS CODELIT SEMI' + if not globals().has_key('operandTypeMap'): + error(t.lexer.lineno, + 'error: operand types must be defined before operands') + try: + userDict = eval('{' + t[3] + '}', exportContext) + except Exception, exc: + error(t.lexer.lineno, + 'error: %s in def operands block "%s".' % (exc, t[3])) + buildOperandNameMap(userDict, t.lexer.lineno) + t[0] = GenCode() # contributes nothing to the output C++ file + + # A bitfield definition looks like: + # 'def [signed] bitfield <ID> [<first>:<last>]' + # This generates a preprocessor macro in the output file. + def p_def_bitfield_0(self, t): + 'def_bitfield : DEF opt_signed BITFIELD ID LESS INTLIT COLON INTLIT GREATER SEMI' + expr = 'bits(machInst, %2d, %2d)' % (t[6], t[8]) + if (t[2] == 'signed'): + expr = 'sext<%d>(%s)' % (t[6] - t[8] + 1, expr) + hash_define = '#undef %s\n#define %s\t%s\n' % (t[4], t[4], expr) + t[0] = GenCode(header_output = hash_define) + + # alternate form for single bit: 'def [signed] bitfield <ID> [<bit>]' + def p_def_bitfield_1(self, t): + 'def_bitfield : DEF opt_signed BITFIELD ID LESS INTLIT GREATER SEMI' + expr = 'bits(machInst, %2d, %2d)' % (t[6], t[6]) + if (t[2] == 'signed'): + expr = 'sext<%d>(%s)' % (1, expr) + hash_define = '#undef %s\n#define %s\t%s\n' % (t[4], t[4], expr) + t[0] = GenCode(header_output = hash_define) + + # alternate form for structure member: 'def bitfield <ID> <ID>' + def p_def_bitfield_struct(self, t): + 'def_bitfield_struct : DEF opt_signed BITFIELD ID id_with_dot SEMI' + if (t[2] != ''): + error(t.lexer.lineno, + 'error: structure bitfields are always unsigned.') + expr = 'machInst.%s' % t[5] + hash_define = '#undef %s\n#define %s\t%s\n' % (t[4], t[4], expr) + t[0] = GenCode(header_output = hash_define) + + def p_id_with_dot_0(self, t): + 'id_with_dot : ID' + t[0] = t[1] + + def p_id_with_dot_1(self, t): + 'id_with_dot : ID DOT id_with_dot' + t[0] = t[1] + t[2] + t[3] + + def p_opt_signed_0(self, t): + 'opt_signed : SIGNED' + t[0] = t[1] + + def p_opt_signed_1(self, t): + 'opt_signed : empty' + t[0] = '' + + def p_def_template(self, t): + 'def_template : DEF TEMPLATE ID CODELIT SEMI' + self.templateMap[t[3]] = Template(t[4]) + t[0] = GenCode() + + # An instruction format definition looks like + # "def format <fmt>(<params>) {{...}};" + def p_def_format(self, t): + 'def_format : DEF FORMAT ID LPAREN param_list RPAREN CODELIT SEMI' + (id, params, code) = (t[3], t[5], t[7]) + defFormat(id, params, code, t.lexer.lineno) + t[0] = GenCode() + + # The formal parameter list for an instruction format is a + # possibly empty list of comma-separated parameters. Positional + # (standard, non-keyword) parameters must come first, followed by + # keyword parameters, followed by a '*foo' parameter that gets + # excess positional arguments (as in Python). Each of these three + # parameter categories is optional. + # + # Note that we do not support the '**foo' parameter for collecting + # otherwise undefined keyword args. Otherwise the parameter list + # is (I believe) identical to what is supported in Python. + # + # The param list generates a tuple, where the first element is a + # list of the positional params and the second element is a dict + # containing the keyword params. + def p_param_list_0(self, t): + 'param_list : positional_param_list COMMA nonpositional_param_list' + t[0] = t[1] + t[3] + + def p_param_list_1(self, t): + '''param_list : positional_param_list + | nonpositional_param_list''' + t[0] = t[1] + + def p_positional_param_list_0(self, t): + 'positional_param_list : empty' + t[0] = [] + + def p_positional_param_list_1(self, t): + 'positional_param_list : ID' + t[0] = [t[1]] + + def p_positional_param_list_2(self, t): + 'positional_param_list : positional_param_list COMMA ID' + t[0] = t[1] + [t[3]] + + def p_nonpositional_param_list_0(self, t): + 'nonpositional_param_list : keyword_param_list COMMA excess_args_param' + t[0] = t[1] + t[3] + + def p_nonpositional_param_list_1(self, t): + '''nonpositional_param_list : keyword_param_list + | excess_args_param''' + t[0] = t[1] + + def p_keyword_param_list_0(self, t): + 'keyword_param_list : keyword_param' + t[0] = [t[1]] + + def p_keyword_param_list_1(self, t): + 'keyword_param_list : keyword_param_list COMMA keyword_param' + t[0] = t[1] + [t[3]] + + def p_keyword_param(self, t): + 'keyword_param : ID EQUALS expr' + t[0] = t[1] + ' = ' + t[3].__repr__() + + def p_excess_args_param(self, t): + 'excess_args_param : ASTERISK ID' + # Just concatenate them: '*ID'. Wrap in list to be consistent + # with positional_param_list and keyword_param_list. + t[0] = [t[1] + t[2]] + + # End of format definition-related rules. + ############## + + # + # A decode block looks like: + # decode <field1> [, <field2>]* [default <inst>] { ... } + # + def p_decode_block(self, t): + 'decode_block : DECODE ID opt_default LBRACE decode_stmt_list RBRACE' + default_defaults = defaultStack.pop() + codeObj = t[5] + # use the "default defaults" only if there was no explicit + # default statement in decode_stmt_list + if not codeObj.has_decode_default: + codeObj += default_defaults + codeObj.wrap_decode_block('switch (%s) {\n' % t[2], '}\n') + t[0] = codeObj + + # The opt_default statement serves only to push the "default + # defaults" onto defaultStack. This value will be used by nested + # decode blocks, and used and popped off when the current + # decode_block is processed (in p_decode_block() above). + def p_opt_default_0(self, t): + 'opt_default : empty' + # no default specified: reuse the one currently at the top of + # the stack + defaultStack.push(defaultStack.top()) + # no meaningful value returned + t[0] = None + + def p_opt_default_1(self, t): + 'opt_default : DEFAULT inst' + # push the new default + codeObj = t[2] + codeObj.wrap_decode_block('\ndefault:\n', 'break;\n') + defaultStack.push(codeObj) + # no meaningful value returned + t[0] = None + + def p_decode_stmt_list_0(self, t): + 'decode_stmt_list : decode_stmt' + t[0] = t[1] + + def p_decode_stmt_list_1(self, t): + 'decode_stmt_list : decode_stmt decode_stmt_list' + if (t[1].has_decode_default and t[2].has_decode_default): + error(t.lexer.lineno, 'Two default cases in decode block') + t[0] = t[1] + t[2] + + # + # Decode statement rules + # + # There are four types of statements allowed in a decode block: + # 1. Format blocks 'format <foo> { ... }' + # 2. Nested decode blocks + # 3. Instruction definitions. + # 4. C preprocessor directives. + + + # Preprocessor directives found in a decode statement list are + # passed through to the output, replicated to all of the output + # code streams. This works well for ifdefs, so we can ifdef out + # both the declarations and the decode cases generated by an + # instruction definition. Handling them as part of the grammar + # makes it easy to keep them in the right place with respect to + # the code generated by the other statements. + def p_decode_stmt_cpp(self, t): + 'decode_stmt : CPPDIRECTIVE' + t[0] = GenCode(t[1], t[1], t[1], t[1]) + + # A format block 'format <foo> { ... }' sets the default + # instruction format used to handle instruction definitions inside + # the block. This format can be overridden by using an explicit + # format on the instruction definition or with a nested format + # block. + def p_decode_stmt_format(self, t): + 'decode_stmt : FORMAT push_format_id LBRACE decode_stmt_list RBRACE' + # The format will be pushed on the stack when 'push_format_id' + # is processed (see below). Once the parser has recognized + # the full production (though the right brace), we're done + # with the format, so now we can pop it. + formatStack.pop() + t[0] = t[4] + + # This rule exists so we can set the current format (& push the + # stack) when we recognize the format name part of the format + # block. + def p_push_format_id(self, t): + 'push_format_id : ID' + try: + formatStack.push(formatMap[t[1]]) + t[0] = ('', '// format %s' % t[1]) + except KeyError: + error(t.lexer.lineno, + 'instruction format "%s" not defined.' % t[1]) + + # Nested decode block: if the value of the current field matches + # the specified constant, do a nested decode on some other field. + def p_decode_stmt_decode(self, t): + 'decode_stmt : case_label COLON decode_block' + label = t[1] + codeObj = t[3] + # just wrap the decoding code from the block as a case in the + # outer switch statement. + codeObj.wrap_decode_block('\n%s:\n' % label) + codeObj.has_decode_default = (label == 'default') + t[0] = codeObj + + # Instruction definition (finally!). + def p_decode_stmt_inst(self, t): + 'decode_stmt : case_label COLON inst SEMI' + label = t[1] + codeObj = t[3] + codeObj.wrap_decode_block('\n%s:' % label, 'break;\n') + codeObj.has_decode_default = (label == 'default') + t[0] = codeObj + + # The case label is either a list of one or more constants or + # 'default' + def p_case_label_0(self, t): + 'case_label : intlit_list' + def make_case(intlit): + if intlit >= 2**32: + return 'case ULL(%#x)' % intlit + else: + return 'case %#x' % intlit + t[0] = ': '.join(map(make_case, t[1])) + + def p_case_label_1(self, t): + 'case_label : DEFAULT' + t[0] = 'default' + + # + # The constant list for a decode case label must be non-empty, but + # may have one or more comma-separated integer literals in it. + # + def p_intlit_list_0(self, t): + 'intlit_list : INTLIT' + t[0] = [t[1]] + + def p_intlit_list_1(self, t): + 'intlit_list : intlit_list COMMA INTLIT' + t[0] = t[1] + t[0].append(t[3]) + + # Define an instruction using the current instruction format + # (specified by an enclosing format block). + # "<mnemonic>(<args>)" + def p_inst_0(self, t): + 'inst : ID LPAREN arg_list RPAREN' + # Pass the ID and arg list to the current format class to deal with. + currentFormat = formatStack.top() + codeObj = currentFormat.defineInst(t[1], t[3], t.lexer.lineno) + args = ','.join(map(str, t[3])) + args = re.sub('(?m)^', '//', args) + args = re.sub('^//', '', args) + comment = '\n// %s::%s(%s)\n' % (currentFormat.id, t[1], args) + codeObj.prepend_all(comment) + t[0] = codeObj + + # Define an instruction using an explicitly specified format: + # "<fmt>::<mnemonic>(<args>)" + def p_inst_1(self, t): + 'inst : ID DBLCOLON ID LPAREN arg_list RPAREN' + try: + format = formatMap[t[1]] + except KeyError: + error(t.lexer.lineno, + 'instruction format "%s" not defined.' % t[1]) + codeObj = format.defineInst(t[3], t[5], t.lexer.lineno) + comment = '\n// %s::%s(%s)\n' % (t[1], t[3], t[5]) + codeObj.prepend_all(comment) + t[0] = codeObj + + # The arg list generates a tuple, where the first element is a + # list of the positional args and the second element is a dict + # containing the keyword args. + def p_arg_list_0(self, t): + 'arg_list : positional_arg_list COMMA keyword_arg_list' + t[0] = ( t[1], t[3] ) + + def p_arg_list_1(self, t): + 'arg_list : positional_arg_list' + t[0] = ( t[1], {} ) + + def p_arg_list_2(self, t): + 'arg_list : keyword_arg_list' + t[0] = ( [], t[1] ) + + def p_positional_arg_list_0(self, t): + 'positional_arg_list : empty' + t[0] = [] + + def p_positional_arg_list_1(self, t): + 'positional_arg_list : expr' + t[0] = [t[1]] + + def p_positional_arg_list_2(self, t): + 'positional_arg_list : positional_arg_list COMMA expr' + t[0] = t[1] + [t[3]] + + def p_keyword_arg_list_0(self, t): + 'keyword_arg_list : keyword_arg' + t[0] = t[1] + + def p_keyword_arg_list_1(self, t): + 'keyword_arg_list : keyword_arg_list COMMA keyword_arg' + t[0] = t[1] + t[0].update(t[3]) + + def p_keyword_arg(self, t): + 'keyword_arg : ID EQUALS expr' + t[0] = { t[1] : t[3] } + + # + # Basic expressions. These constitute the argument values of + # "function calls" (i.e. instruction definitions in the decode + # block) and default values for formal parameters of format + # functions. + # + # Right now, these are either strings, integers, or (recursively) + # lists of exprs (using Python square-bracket list syntax). Note + # that bare identifiers are trated as string constants here (since + # there isn't really a variable namespace to refer to). + # + def p_expr_0(self, t): + '''expr : ID + | INTLIT + | STRLIT + | CODELIT''' + t[0] = t[1] + + def p_expr_1(self, t): + '''expr : LBRACKET list_expr RBRACKET''' + t[0] = t[2] + + def p_list_expr_0(self, t): + 'list_expr : expr' + t[0] = [t[1]] + + def p_list_expr_1(self, t): + 'list_expr : list_expr COMMA expr' + t[0] = t[1] + [t[3]] + + def p_list_expr_2(self, t): + 'list_expr : empty' + t[0] = [] + + # + # Empty production... use in other rules for readability. + # + def p_empty(self, t): + 'empty :' + pass + + # Parse error handler. Note that the argument here is the + # offending *token*, not a grammar symbol (hence the need to use + # t.value) + def p_error(self, t): + if t: + error(t.lexer.lineno, "syntax error at '%s'" % t.value) + else: + error(0, "unknown syntax error", True) -# -# Empty production... use in other rules for readability. -# -def p_empty(t): - 'empty :' - pass - -# Parse error handler. Note that the argument here is the offending -# *token*, not a grammar symbol (hence the need to use t.value) -def p_error(t): - if t: - error(t.lexer.lineno, "syntax error at '%s'" % t.value) - else: - error(0, "unknown syntax error", True) + # END OF GRAMMAR RULES -# END OF GRAMMAR RULES -# # Now build the parser. -parser = yacc.yacc() - +parser = ISAParser() ##################################################################### # @@ -766,6 +768,11 @@ def expand_cpu_symbols_to_string(template): def protect_cpu_symbols(template): return re.sub(r'%(?=\(CPU_)', '%%', template) +# Protect any non-dict-substitution '%'s in a format string +# (i.e. those not followed by '(') +def protect_non_subst_percents(s): + return re.sub(r'%(?!\()', '%%', s) + ############### # GenCode class # @@ -839,7 +846,7 @@ exportContext = {} def updateExportContext(): exportContext.update(exportDict(*exportContextSymbols)) - exportContext.update(templateMap) + exportContext.update(parser.templateMap) def exportDict(*symNames): return dict([(s, eval(s)) for s in symNames]) @@ -1049,7 +1056,7 @@ class Template: # Build a dict ('myDict') to use for the template substitution. # Start with the template namespace. Make a copy since we're # going to modify it. - myDict = templateMap.copy() + myDict = parser.templateMap.copy() if isinstance(d, InstObjParams): # If we're dealing with an InstObjParams object, we need @@ -1463,6 +1470,16 @@ class MemOperand(Operand): def makeAccSize(self): return self.size +class PCOperand(Operand): + def makeConstructor(self): + return '' + + def makeRead(self): + return '%s = xc->readPC();\n' % self.base_name + + def makeWrite(self): + return 'xc->setPC(%s);\n' % self.base_name + class UPCOperand(Operand): def makeConstructor(self): return '' @@ -1975,8 +1992,7 @@ def parse_isa_desc(isa_desc_file, output_dir): fileNameStack.push((isa_desc_file, 0)) # Parse it. - (isa_name, namespace, global_code, namespace_code) = \ - parser.parse(isa_desc, lexer=lexer) + (isa_name, namespace, global_code, namespace_code) = parser.parse(isa_desc) # grab the last three path components of isa_desc_file to put in # the output diff --git a/src/arch/micro_asm.py b/src/arch/micro_asm.py index 3433a8076..4e5400cef 100644 --- a/src/arch/micro_asm.py +++ b/src/arch/micro_asm.py @@ -34,10 +34,6 @@ import traceback # get type names from types import * -# Prepend the directory where the PLY lex & yacc modules are found -# to the search path. -sys.path[0:0] = [os.environ['M5_PLY']] - from ply import lex from ply import yacc diff --git a/src/arch/mips/BISystem.py b/src/arch/mips/BISystem.py index dd4e4fe25..a6e4091f2 100755 --- a/src/arch/mips/BISystem.py +++ b/src/arch/mips/BISystem.py @@ -28,10 +28,11 @@ # # Authors: Jaidev Patwardhan -from m5 import build_env +from m5.defines import buildEnv + from System import * -if build_env['FULL_SYSTEM']: +if buildEnv['FULL_SYSTEM']: class BareIronMipsSystem(MipsSystem): type = 'BareIronMipsSystem' system_type = 34 diff --git a/src/arch/mips/MipsCPU.py b/src/arch/mips/MipsCPU.py index 81c6bdacf..48ee4171c 100644 --- a/src/arch/mips/MipsCPU.py +++ b/src/arch/mips/MipsCPU.py @@ -29,12 +29,13 @@ # Authors: Jaidev Patwardhan # Korey Sewell -from m5.SimObject import SimObject +from m5.defines import buildEnv from m5.params import * + from BaseCPU import BaseCPU class BaseMipsCPU(BaseCPU) - if build_env['TARGET_ISA'] == 'mips': + if buildEnv['TARGET_ISA'] == 'mips': CP0_IntCtl_IPTI = Param.Unsigned(0,"No Description") CP0_IntCtl_IPPCI = Param.Unsigned(0,"No Description") CP0_SrsCtl_HSS = Param.Unsigned(0,"No Description") diff --git a/src/arch/mips/MipsSystem.py b/src/arch/mips/MipsSystem.py index c3dcf4e0b..d271bd387 100644 --- a/src/arch/mips/MipsSystem.py +++ b/src/arch/mips/MipsSystem.py @@ -28,10 +28,10 @@ # # Authors: Jaidev Patwardhan -from m5.SimObject import SimObject +from m5.defines import buildEnv from m5.params import * from m5.proxy import * -from m5 import build_env + from System import System class MipsSystem(System): @@ -42,7 +42,7 @@ class MipsSystem(System): system_type = Param.UInt64("Type of system we are emulating") system_rev = Param.UInt64("Revision of system we are emulating") -if build_env['FULL_SYSTEM']: +if buildEnv['FULL_SYSTEM']: class LinuxMipsSystem(MipsSystem): type = 'LinuxMipsSystem' system_type = 34 diff --git a/src/arch/mips/dsp.cc b/src/arch/mips/dsp.cc index 6e4f7afea..b8b02ae9e 100755 --- a/src/arch/mips/dsp.cc +++ b/src/arch/mips/dsp.cc @@ -463,6 +463,8 @@ MipsISA::dspMuleq(int32_t a, int32_t b, int32_t mode, uint32_t *dspctl) uint64_t b_values[SIMD_MAX_VALS]; uint64_t c_values[SIMD_MAX_VALS]; + memset(c_values, 0, sizeof(c_values)); + simdUnpack(a, a_values, SIMD_FMT_PH, SIGNED); simdUnpack(b, b_values, SIMD_FMT_PH, SIGNED); @@ -743,7 +745,7 @@ MipsISA::dspMulsaq(int64_t dspac, int32_t a, int32_t b, int32_t ac, int nvals = SIMD_NVALS[fmt]; uint64_t a_values[SIMD_MAX_VALS]; uint64_t b_values[SIMD_MAX_VALS]; - int64_t temp[2]; + int64_t temp[2] = {0, 0}; uint32_t ouflag = 0; simdUnpack(a, a_values, fmt, SIGNED); diff --git a/src/arch/mips/isa.hh b/src/arch/mips/isa.hh index 15c043dc0..165adff83 100644 --- a/src/arch/mips/isa.hh +++ b/src/arch/mips/isa.hh @@ -172,8 +172,11 @@ namespace MipsISA return reg; } - void serialize(std::ostream &os); - void unserialize(Checkpoint *cp, const std::string §ion); + void serialize(EventManager *em, std::ostream &os) + {} + void unserialize(EventManager *em, Checkpoint *cp, + const std::string §ion) + {} }; } diff --git a/src/arch/mips/isa/formats/mem.isa b/src/arch/mips/isa/formats/mem.isa index adcb16137..161a52b06 100644 --- a/src/arch/mips/isa/formats/mem.isa +++ b/src/arch/mips/isa/formats/mem.isa @@ -619,7 +619,7 @@ def format StoreUnalignedMemory(memacc_code, ea_code = {{ EA = (Rs + disp) & ~3; def format Prefetch(ea_code = {{ EA = Rs + disp; }}, mem_flags = [], pf_flags = [], inst_flags = []) {{ - pf_mem_flags = mem_flags + pf_flags + ['NO_FAULT'] + pf_mem_flags = mem_flags + pf_flags + ['PREFETCH'] pf_inst_flags = inst_flags + ['IsMemRef', 'IsLoad', 'IsDataPrefetch', 'MemReadOp'] diff --git a/src/arch/mips/linux/linux.hh b/src/arch/mips/linux/linux.hh index ee81fa18f..a2418cfb6 100644 --- a/src/arch/mips/linux/linux.hh +++ b/src/arch/mips/linux/linux.hh @@ -100,6 +100,7 @@ class MipsLinux : public Linux static const unsigned TIOCISATTY_ = 0x5480; static const unsigned TIOCGETS_ = 0x540d; static const unsigned TIOCGETA_ = 0x7417; + static const unsigned TCSETAW_ = 0x5403; // 2.6.15 kernel //@} /// For table(). @@ -126,6 +127,22 @@ class MipsLinux : public Linux /// assign themselves to process IDs reserved for /// the root users. static const int NUM_ROOT_PROCS = 2; + + typedef struct { + int32_t uptime; /* Seconds since boot */ + uint32_t loads[3]; /* 1, 5, and 15 minute load averages */ + uint32_t totalram; /* Total usable main memory size */ + uint32_t freeram; /* Available memory size */ + uint32_t sharedram; /* Amount of shared memory */ + uint32_t bufferram; /* Memory used by buffers */ + uint32_t totalswap; /* Total swap space size */ + uint32_t freeswap; /* swap space still available */ + uint16_t procs; /* Number of current processes */ + uint32_t totalhigh; /* Total high memory size */ + uint32_t freehigh; /* Available high memory size */ + uint32_t mem_unit; /* Memory unit size in bytes */ + } tgt_sysinfo; + }; #endif diff --git a/src/arch/mips/linux/process.cc b/src/arch/mips/linux/process.cc index 53a24487f..c2a05b73b 100644 --- a/src/arch/mips/linux/process.cc +++ b/src/arch/mips/linux/process.cc @@ -51,7 +51,8 @@ static SyscallReturn unameFunc(SyscallDesc *desc, int callnum, LiveProcess *process, ThreadContext *tc) { - TypedBufferArg<Linux::utsname> name(process->getSyscallArg(tc, 0)); + int index = 0; + TypedBufferArg<Linux::utsname> name(process->getSyscallArg(tc, index)); strcpy(name->sysname, "Linux"); strcpy(name->nodename,"m5.eecs.umich.edu"); @@ -70,14 +71,16 @@ static SyscallReturn sys_getsysinfoFunc(SyscallDesc *desc, int callnum, LiveProcess *process, ThreadContext *tc) { - unsigned op = process->getSyscallArg(tc, 0); - // unsigned nbytes = process->getSyscallArg(tc, 2); + int index = 0; + unsigned op = process->getSyscallArg(tc, index); + unsigned bufPtr = process->getSyscallArg(tc, index); + // unsigned nbytes = process->getSyscallArg(tc, index); switch (op) { case 45: { // GSI_IEEE_FP_CONTROL - TypedBufferArg<uint64_t> fpcr(process->getSyscallArg(tc, 1)); + TypedBufferArg<uint64_t> fpcr(bufPtr); // I don't think this exactly matches the HW FPCR *fpcr = 0; fpcr.copyOut(tc->getMemPort()); @@ -97,15 +100,17 @@ static SyscallReturn sys_setsysinfoFunc(SyscallDesc *desc, int callnum, LiveProcess *process, ThreadContext *tc) { - unsigned op = process->getSyscallArg(tc, 0); - // unsigned nbytes = process->getSyscallArg(tc, 2); + int index = 0; + unsigned op = process->getSyscallArg(tc, index); + Addr bufPtr = process->getSyscallArg(tc, index); + // unsigned nbytes = process->getSyscallArg(tc, index); switch (op) { case 14: { // SSI_IEEE_FP_CONTROL - TypedBufferArg<uint64_t> fpcr(process->getSyscallArg(tc, 1)); + TypedBufferArg<uint64_t> fpcr(bufPtr); // I don't think this exactly matches the HW FPCR fpcr.copyIn(tc->getMemPort()); DPRINTFR(SyscallVerbose, "sys_setsysinfo(SSI_IEEE_FP_CONTROL): " @@ -238,7 +243,7 @@ SyscallDesc MipsLinuxProcess::syscallDescs[] = { /* 113 */ SyscallDesc("vm86", unimplementedFunc), /* 114 */ SyscallDesc("wait4", unimplementedFunc), /* 115 */ SyscallDesc("swapoff", unimplementedFunc), - /* 116 */ SyscallDesc("sysinfo", unimplementedFunc), + /* 116 */ SyscallDesc("sysinfo", sysinfoFunc<MipsLinux>), /* 117 */ SyscallDesc("ipc", unimplementedFunc), /* 118 */ SyscallDesc("fsync", unimplementedFunc), /* 119 */ SyscallDesc("sigreturn", unimplementedFunc), @@ -413,12 +418,6 @@ MipsLinuxProcess::MipsLinuxProcess(LiveProcessParams * params, Num_Syscall_Descs(sizeof(syscallDescs) / sizeof(SyscallDesc)) { } -void -MipsLinuxProcess::startup() -{ - MipsLiveProcess::argsInit(MachineBytes, VMPageSize); -} - SyscallDesc* MipsLinuxProcess::getDesc(int callnum) { diff --git a/src/arch/mips/linux/process.hh b/src/arch/mips/linux/process.hh index 5afde2be1..8c45014e0 100644 --- a/src/arch/mips/linux/process.hh +++ b/src/arch/mips/linux/process.hh @@ -43,8 +43,6 @@ class MipsLinuxProcess : public MipsLiveProcess /// Constructor. MipsLinuxProcess(LiveProcessParams * params, ObjectFile *objFile); - void startup(); - virtual SyscallDesc* getDesc(int callnum); /// The target system's hostname. diff --git a/src/arch/mips/process.cc b/src/arch/mips/process.cc index 3e9fb7c20..d96b0c81c 100644 --- a/src/arch/mips/process.cc +++ b/src/arch/mips/process.cc @@ -32,9 +32,15 @@ #include "arch/mips/isa_traits.hh" #include "arch/mips/process.hh" + #include "base/loader/object_file.hh" #include "base/misc.hh" #include "cpu/thread_context.hh" + +#include "mem/page_table.hh" + +#include "sim/process.hh" +#include "sim/process_impl.hh" #include "sim/system.hh" using namespace std; @@ -62,14 +68,89 @@ MipsLiveProcess::MipsLiveProcess(LiveProcessParams * params, void MipsLiveProcess::startup() { + Process::startup(); + argsInit(MachineBytes, VMPageSize); } +void +MipsLiveProcess::argsInit(int intSize, int pageSize) +{ + // load object file into target memory + objFile->loadSections(initVirtMem); + + // Calculate how much space we need for arg & env arrays. + int argv_array_size = intSize * (argv.size() + 1); + int envp_array_size = intSize * (envp.size() + 1); + int arg_data_size = 0; + for (vector<string>::size_type i = 0; i < argv.size(); ++i) { + arg_data_size += argv[i].size() + 1; + } + int env_data_size = 0; + for (vector<string>::size_type i = 0; i < envp.size(); ++i) { + env_data_size += envp[i].size() + 1; + } + + int space_needed = + argv_array_size + envp_array_size + arg_data_size + env_data_size; + if (space_needed < 32*1024) + space_needed = 32*1024; + + // set bottom of stack + stack_min = stack_base - space_needed; + // align it + stack_min = roundDown(stack_min, pageSize); + stack_size = stack_base - stack_min; + // map memory + pTable->allocate(stack_min, roundUp(stack_size, pageSize)); + + // map out initial stack contents + // ======== + // NOTE: Using uint32_t hardcodes MIPS32 and not MIPS64 + // even if MIPS64 was intended. This is because the + // copyStringArray function templates on the parameters. + // Elegant way to check intSize and vary between 32/64? + // ======== + uint32_t argv_array_base = stack_min + intSize; // room for argc + uint32_t envp_array_base = argv_array_base + argv_array_size; + uint32_t arg_data_base = envp_array_base + envp_array_size; + uint32_t env_data_base = arg_data_base + arg_data_size; + + // write contents to stack + uint32_t argc = argv.size(); + + if (intSize == 8) + argc = htog((uint64_t)argc); + else if (intSize == 4) + argc = htog((uint32_t)argc); + else + panic("Unknown int size"); + + + initVirtMem->writeBlob(stack_min, (uint8_t*)&argc, intSize); + + copyStringArray(argv, argv_array_base, arg_data_base, initVirtMem); + + copyStringArray(envp, envp_array_base, env_data_base, initVirtMem); + + ThreadContext *tc = system->getThreadContext(contextIds[0]); + + setSyscallArg(tc, 0, argc); + setSyscallArg(tc, 1, argv_array_base); + tc->setIntReg(StackPointerReg, stack_min); + + Addr prog_entry = objFile->entryPoint(); + tc->setPC(prog_entry); + tc->setNextPC(prog_entry + sizeof(MachInst)); + tc->setNextNPC(prog_entry + (2 * sizeof(MachInst))); +} + + MipsISA::IntReg -MipsLiveProcess::getSyscallArg(ThreadContext *tc, int i) +MipsLiveProcess::getSyscallArg(ThreadContext *tc, int &i) { assert(i < 6); - return tc->readIntReg(FirstArgumentReg + i); + return tc->readIntReg(FirstArgumentReg + i++); } void diff --git a/src/arch/mips/process.hh b/src/arch/mips/process.hh index 87c62330f..f35ec8554 100644 --- a/src/arch/mips/process.hh +++ b/src/arch/mips/process.hh @@ -45,10 +45,12 @@ class MipsLiveProcess : public LiveProcess protected: MipsLiveProcess(LiveProcessParams * params, ObjectFile *objFile); - virtual void startup(); + void startup(); + + void argsInit(int intSize, int pageSize); public: - MipsISA::IntReg getSyscallArg(ThreadContext *tc, int i); + MipsISA::IntReg getSyscallArg(ThreadContext *tc, int &i); void setSyscallArg(ThreadContext *tc, int i, MipsISA::IntReg val); void setSyscallReturn(ThreadContext *tc, SyscallReturn return_value); }; diff --git a/src/arch/power/PowerTLB.py b/src/arch/power/PowerTLB.py new file mode 100644 index 000000000..36dff5333 --- /dev/null +++ b/src/arch/power/PowerTLB.py @@ -0,0 +1,37 @@ +# -*- mode:python -*- + +# Copyright (c) 2009 The University of Edinburgh +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer; +# redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution; +# neither the name of the copyright holders nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# Authors: Timothy M. Jones + +from m5.SimObject import SimObject +from m5.params import * + +class PowerTLB(SimObject): + type = 'PowerTLB' + cxx_class = 'PowerISA::TLB' + size = Param.Int(64, "TLB size") diff --git a/src/arch/power/SConscript b/src/arch/power/SConscript new file mode 100644 index 000000000..1fb36eaab --- /dev/null +++ b/src/arch/power/SConscript @@ -0,0 +1,61 @@ +# -*- mode:python -*- + +# Copyright (c) 2009 The University of Edinburgh +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer; +# redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution; +# neither the name of the copyright holders nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# Authors: Timothy M. Jones + +Import('*') + +if env['TARGET_ISA'] == 'power': +# Workaround for bug in SCons version > 0.97d20071212 +# Scons bug id: 2006 M5 Bug id: 308 + Dir('isa/formats') + Source('insts/branch.cc') + Source('insts/mem.cc') + Source('insts/integer.cc') + Source('insts/floating.cc') + Source('insts/condition.cc') + Source('insts/static_inst.cc') + Source('pagetable.cc') + Source('tlb.cc') + + SimObject('PowerTLB.py') + TraceFlag('Power') + + if not env['FULL_SYSTEM']: + Source('process.cc') + Source('linux/linux.cc') + Source('linux/process.cc') + + # Add in files generated by the ISA description. + isa_desc_files = env.ISADesc('isa/main.isa') + + # Only non-header files need to be compiled. + for f in isa_desc_files: + if not f.path.endswith('.hh'): + Source(f) + diff --git a/src/arch/power/SConsopts b/src/arch/power/SConsopts new file mode 100644 index 000000000..d762c2d58 --- /dev/null +++ b/src/arch/power/SConsopts @@ -0,0 +1,33 @@ +# -*- mode:python -*- + +# Copyright (c) 2009 The University of Edinburgh +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer; +# redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution; +# neither the name of the copyright holders nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# Authors: Timothy M. Jones + +Import('*') + +all_isa_list.append('power') diff --git a/src/mem/slicc/symbols/Symbol.cc b/src/arch/power/faults.hh index 25af5ad47..eadcb7900 100644 --- a/src/mem/slicc/symbols/Symbol.cc +++ b/src/arch/power/faults.hh @@ -1,6 +1,6 @@ - /* - * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood + * Copyright (c) 2003-2005 The Regents of The University of Michigan + * Copyright (c) 2009 The University of Edinburgh * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -25,48 +25,63 @@ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/* - * $Id$ * + * Authors: Gabe Black + * Timothy M. Jones */ -#include "mem/slicc/symbols/Symbol.hh" +#ifndef __ARCH_POWER_FAULTS_HH__ +#define __ARCH_POWER_FAULTS_HH__ + +#include "sim/faults.hh" -Symbol::Symbol(string id, const Location& location, const Map<string, string>& pairs) +namespace PowerISA { - m_id = id; - m_location = location; - m_pairs = pairs; - if (!existPair("short")) { - addPair("short", m_id); - } - m_used = false; -} -Symbol::Symbol(string id, const Location& location) +class PowerFault : public FaultBase { - m_id = id; - m_location = location; - if (!existPair("short")) { - addPair("short", m_id); - } - m_used = false; -} + protected: + FaultName _name; + + PowerFault(FaultName name) + : _name(name) + { + } + + FaultName + name() const + { + return _name; + } +}; -const string& Symbol::lookupPair(const string& key) const + +class UnimplementedOpcodeFault : public PowerFault { - if (!existPair(key)) { - error("Value for pair '" + key + "' missing."); - } - return m_pairs.lookup(key); -} + public: + UnimplementedOpcodeFault() + : PowerFault("Unimplemented Opcode") + { + } +}; + + +class MachineCheckFault : public PowerFault +{ + public: + MachineCheckFault() + : PowerFault("Machine Check") + { + } +}; + -void Symbol::addPair(const string& key, const string& value) +static inline Fault +genMachineCheckFault() { - if (existPair(key)) { - warning("Pair key '" + key + "' re-defined. new: '" + value + "' old: '" + lookupPair(key) + "'"); - } - m_pairs.add(key, value); + return new MachineCheckFault(); } + +} // PowerISA namespace + +#endif // __ARCH_POWER_FAULTS_HH__ diff --git a/src/arch/power/insts/branch.cc b/src/arch/power/insts/branch.cc new file mode 100644 index 000000000..3f4346c97 --- /dev/null +++ b/src/arch/power/insts/branch.cc @@ -0,0 +1,169 @@ +/* + * Copyright (c) 2009 The University of Edinburgh + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Timothy M. Jones + */ + +#include "arch/power/insts/branch.hh" +#include "base/loader/symtab.hh" + +using namespace PowerISA; + +const std::string & +PCDependentDisassembly::disassemble(Addr pc, const SymbolTable *symtab) const +{ + if (!cachedDisassembly || + pc != cachedPC || symtab != cachedSymtab) + { + if (cachedDisassembly) + delete cachedDisassembly; + + cachedDisassembly = + new std::string(generateDisassembly(pc, symtab)); + cachedPC = pc; + cachedSymtab = symtab; + } + + return *cachedDisassembly; +} + +Addr +BranchPCRel::branchTarget(Addr pc) const +{ + return (uint32_t)(pc + disp); +} + +std::string +BranchPCRel::generateDisassembly(Addr pc, const SymbolTable *symtab) const +{ + std::stringstream ss; + + ccprintf(ss, "%-10s ", mnemonic); + + Addr target = pc + disp; + + std::string str; + if (symtab && symtab->findSymbol(target, str)) + ss << str; + else + ccprintf(ss, "0x%x", target); + + return ss.str(); +} + +Addr +BranchNonPCRel::branchTarget(Addr pc) const +{ + return targetAddr; +} + +std::string +BranchNonPCRel::generateDisassembly(Addr pc, const SymbolTable *symtab) const +{ + std::stringstream ss; + + ccprintf(ss, "%-10s ", mnemonic); + + std::string str; + if (symtab && symtab->findSymbol(targetAddr, str)) + ss << str; + else + ccprintf(ss, "0x%x", targetAddr); + + return ss.str(); +} + +Addr +BranchPCRelCond::branchTarget(Addr pc) const +{ + return (uint32_t)(pc + disp); +} + +std::string +BranchPCRelCond::generateDisassembly(Addr pc, const SymbolTable *symtab) const +{ + std::stringstream ss; + + ccprintf(ss, "%-10s ", mnemonic); + + ss << bo << ", " << bi << ", "; + + Addr target = pc + disp; + + std::string str; + if (symtab && symtab->findSymbol(target, str)) + ss << str; + else + ccprintf(ss, "0x%x", target); + + return ss.str(); +} + +Addr +BranchNonPCRelCond::branchTarget(Addr pc) const +{ + return targetAddr; +} + +std::string +BranchNonPCRelCond::generateDisassembly(Addr pc, + const SymbolTable *symtab) const +{ + std::stringstream ss; + + ccprintf(ss, "%-10s ", mnemonic); + + ss << bo << ", " << bi << ", "; + + std::string str; + if (symtab && symtab->findSymbol(targetAddr, str)) + ss << str; + else + ccprintf(ss, "0x%x", targetAddr); + + return ss.str(); +} + +Addr +BranchRegCond::branchTarget(ThreadContext *tc) const +{ + uint32_t regVal = tc->readIntReg(_srcRegIdx[_numSrcRegs - 1]); + return (regVal & 0xfffffffc); +} + +std::string +BranchRegCond::generateDisassembly(Addr pc, + const SymbolTable *symtab) const +{ + std::stringstream ss; + + ccprintf(ss, "%-10s ", mnemonic); + + ss << bo << ", " << bi << ", "; + + return ss.str(); +} diff --git a/src/arch/power/insts/branch.hh b/src/arch/power/insts/branch.hh new file mode 100644 index 000000000..dd00e42c3 --- /dev/null +++ b/src/arch/power/insts/branch.hh @@ -0,0 +1,241 @@ +/* Copyright (c) 2007-2008 The Florida State University + * Copyright (c) 2009 The University of Edinburgh + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Timothy M. Jones + */ + +#ifndef __ARCH_POWER_INSTS_BRANCH_HH__ +#define __ARCH_POWER_INSTS_BRANCH_HH__ + +#include "arch/power/insts/static_inst.hh" + +namespace PowerISA +{ + +/** + * Base class for instructions whose disassembly is not purely a + * function of the machine instruction (i.e., it depends on the + * PC). This class overrides the disassemble() method to check + * the PC and symbol table values before re-using a cached + * disassembly string. This is necessary for branches and jumps, + * where the disassembly string includes the target address (which + * may depend on the PC and/or symbol table). + */ +class PCDependentDisassembly : public PowerStaticInst +{ + protected: + /// Cached program counter from last disassembly + mutable Addr cachedPC; + /// Cached symbol table pointer from last disassembly + mutable const SymbolTable *cachedSymtab; + + /// Constructor + PCDependentDisassembly(const char *mnem, ExtMachInst _machInst, + OpClass __opClass) + : PowerStaticInst(mnem, _machInst, __opClass), + cachedPC(0), cachedSymtab(0) + { + } + + const std::string & + disassemble(Addr pc, const SymbolTable *symtab) const; +}; + +/** + * Base class for unconditional, PC-relative branches. + */ +class BranchPCRel : public PCDependentDisassembly +{ + protected: + + /// Displacement + uint32_t disp; + + /// Constructor. + BranchPCRel(const char *mnem, MachInst _machInst, OpClass __opClass) + : PCDependentDisassembly(mnem, _machInst, __opClass), + disp(machInst.li << 2) + { + // If bit 26 is 1 then sign extend + if (disp & 0x2000000) { + disp |= 0xfc000000; + } + } + + Addr branchTarget(Addr pc) const; + + std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const; +}; + +/** + * Base class for unconditional, non PC-relative branches. + */ +class BranchNonPCRel : public PCDependentDisassembly +{ + protected: + + /// Target address + uint32_t targetAddr; + + /// Constructor. + BranchNonPCRel(const char *mnem, MachInst _machInst, OpClass __opClass) + : PCDependentDisassembly(mnem, _machInst, __opClass), + targetAddr(machInst.li << 2) + { + // If bit 26 is 1 then sign extend + if (targetAddr & 0x2000000) { + targetAddr |= 0xfc000000; + } + } + + Addr branchTarget(Addr pc) const; + + std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const; +}; + +/** + * Base class for conditional branches. + */ +class BranchCond : public PCDependentDisassembly +{ + protected: + + /// Fields needed for conditions + uint32_t bo; + uint32_t bi; + + /// Constructor. + BranchCond(const char *mnem, MachInst _machInst, OpClass __opClass) + : PCDependentDisassembly(mnem, _machInst, __opClass), + bo(machInst.bo), + bi(machInst.bi) + { + } + + inline bool + ctrOk(uint32_t& ctr) const + { + bool ctr_ok; + if (bo & 4) { + ctr_ok = true; + } else { + ctr--; + if (ctr != 0) { + ctr_ok = ((bo & 2) == 0); + } else { + ctr_ok = ((bo & 2) != 0); + } + } + return ctr_ok; + } + + inline bool + condOk(uint32_t cr) const + { + bool cond_ok; + if (bo & 16) { + cond_ok = true; + } else { + cond_ok = (((cr >> (31 - bi)) & 1) == ((bo >> 3) & 1)); + } + return cond_ok; + } +}; + +/** + * Base class for conditional, PC-relative branches. + */ +class BranchPCRelCond : public BranchCond +{ + protected: + + /// Displacement + uint32_t disp; + + /// Constructor. + BranchPCRelCond(const char *mnem, MachInst _machInst, OpClass __opClass) + : BranchCond(mnem, _machInst, __opClass), + disp(machInst.bd << 2) + { + // If bit 16 is 1 then sign extend + if (disp & 0x8000) { + disp |= 0xffff0000; + } + } + + Addr branchTarget(Addr pc) const; + + std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const; +}; + +/** + * Base class for conditional, non PC-relative branches. + */ +class BranchNonPCRelCond : public BranchCond +{ + protected: + + /// Target address + uint32_t targetAddr; + + /// Constructor. + BranchNonPCRelCond(const char *mnem, MachInst _machInst, OpClass __opClass) + : BranchCond(mnem, _machInst, __opClass), + targetAddr(machInst.bd << 2) + { + // If bit 16 is 1 then sign extend + if (targetAddr & 0x8000) { + targetAddr |= 0xffff0000; + } + } + + Addr branchTarget(Addr pc) const; + + std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const; +}; + +/** + * Base class for conditional, register-based branches + */ +class BranchRegCond : public BranchCond +{ + protected: + + /// Constructor. + BranchRegCond(const char *mnem, MachInst _machInst, OpClass __opClass) + : BranchCond(mnem, _machInst, __opClass) + { + } + + Addr branchTarget(ThreadContext *tc) const; + + std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const; +}; + +} // PowerISA namespace + +#endif //__ARCH_POWER_INSTS_BRANCH_HH__ diff --git a/src/mem/slicc/symbols/Var.cc b/src/arch/power/insts/condition.cc index a6e8dfd55..0a942a982 100644 --- a/src/mem/slicc/symbols/Var.cc +++ b/src/arch/power/insts/condition.cc @@ -1,6 +1,5 @@ - /* - * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood + * Copyright (c) 2009 The University of Edinburgh * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -25,33 +24,36 @@ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Timothy M. Jones */ -/* - * $Id$ - * - * */ +#include "arch/power/insts/condition.hh" -#include "mem/slicc/symbols/Var.hh" -#include "mem/slicc/symbols/StateMachine.hh" +using namespace PowerISA; -Var::Var(string id, const Location& location, - Type* type_ptr, string code, - const Map<string, string>& pairs, - StateMachine* machine_ptr) : Symbol(id, location, pairs) +std::string +CondLogicOp::generateDisassembly(Addr pc, const SymbolTable *symtab) const { - if (machine_ptr == NULL) { - m_c_id = id; - } else { - m_c_id = machine_ptr->toString() + "_" + id; // Append with machine name - } - - m_machine_ptr = machine_ptr; - m_type_ptr = type_ptr; - m_code = code; + std::stringstream ss; + + ccprintf(ss, "%-10s ", mnemonic); + + // Format is <mnemonic> bt, ba, bb + ss << bt << ", " << ba << ", " << bb; + + return ss.str(); } -void Var::print(ostream& out) const +std::string +CondMoveOp::generateDisassembly(Addr pc, const SymbolTable *symtab) const { - out << "[Var id: " << m_c_id << "]" << endl; + std::stringstream ss; + + ccprintf(ss, "%-10s ", mnemonic); + + // Format is <mnemonic> bf, bfa + ss << bf << ", " << bfa; + + return ss.str(); } diff --git a/src/mem/slicc/ast/DeclAST.hh b/src/arch/power/insts/condition.hh index d9e4555b4..a23667d9e 100644 --- a/src/mem/slicc/ast/DeclAST.hh +++ b/src/arch/power/insts/condition.hh @@ -1,6 +1,5 @@ - /* - * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood + * Copyright (c) 2009 The University of Edinburgh * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -25,61 +24,63 @@ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/* - * DeclAST.hh - * - * Description: - * - * $Id$ * + * Authors: Timothy M. Jones */ -#ifndef DECLAST_H -#define DECLAST_H +#ifndef __ARCH_POWER_INSTS_CONDITION_HH__ +#define __ARCH_POWER_INSTS_CONDITION_HH__ -#include "mem/slicc/slicc_global.hh" -#include "mem/slicc/ast/AST.hh" -#include "mem/slicc/ast/PairListAST.hh" -#include "mem/slicc/symbols/StateMachine.hh" -#include "mem/slicc/ast/TypeAST.hh" +#include "arch/power/insts/static_inst.hh" +#include "base/cprintf.hh" -class DeclAST : public AST { -public: - // Constructors - DeclAST(PairListAST* pairs_ptr) : AST(pairs_ptr->getPairs()) {} - - // Destructor - virtual ~DeclAST() {} +namespace PowerISA +{ - // Public Methods - virtual void generate() = 0; - virtual void findMachines() {}; +/** + * Class for condition register logical operations. + */ +class CondLogicOp : public PowerStaticInst +{ + protected: - // void print(ostream& out) const; -private: - // Private Methods + uint32_t ba; + uint32_t bb; + uint32_t bt; - // Private copy constructor and assignment operator - // DeclAST(const DeclAST& obj); - // DeclAST& operator=(const DeclAST& obj); + /// Constructor + CondLogicOp(const char *mnem, MachInst _machInst, OpClass __opClass) + : PowerStaticInst(mnem, _machInst, __opClass), + ba(machInst.ba), + bb(machInst.bb), + bt(machInst.bt) + { + } - // Data Members (m_ prefix) + std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const; }; -// Output operator declaration -ostream& operator<<(ostream& out, const DeclAST& obj); +/** + * Class for condition register move operations. + */ +class CondMoveOp : public PowerStaticInst +{ + protected: + + uint32_t bf; + uint32_t bfa; -// ******************* Definitions ******************* + /// Constructor + CondMoveOp(const char *mnem, MachInst _machInst, OpClass __opClass) + : PowerStaticInst(mnem, _machInst, __opClass), + bf(machInst.bf), + bfa(machInst.bfa) + { + } -// Output operator definition -extern inline -ostream& operator<<(ostream& out, const DeclAST& obj) -{ - obj.print(out); - out << flush; - return out; -} + std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const; +}; + +} // PowerISA namespace -#endif //DECLAST_H +#endif //__ARCH_POWER_INSTS_CONDITION_HH__ diff --git a/src/arch/power/insts/floating.cc b/src/arch/power/insts/floating.cc new file mode 100644 index 000000000..f5c34ee2a --- /dev/null +++ b/src/arch/power/insts/floating.cc @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2009 The University of Edinburgh + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Timothy M. Jones + */ + +#include "arch/power/insts/floating.hh" + +using namespace PowerISA; + +std::string +FloatOp::generateDisassembly(Addr pc, const SymbolTable *symtab) const +{ + std::stringstream ss; + + ccprintf(ss, "%-10s ", mnemonic); + + // Print the first destination only + if (_numDestRegs > 0) { + printReg(ss, _destRegIdx[0]); + } + + // Print the (possibly) two source registers + if (_numSrcRegs > 0) { + if (_numDestRegs > 0) { + ss << ", "; + } + printReg(ss, _srcRegIdx[0]); + if (_numSrcRegs > 1) { + ss << ", "; + printReg(ss, _srcRegIdx[1]); + } + } + + return ss.str(); +} diff --git a/src/arch/power/insts/floating.hh b/src/arch/power/insts/floating.hh new file mode 100644 index 000000000..2b2668409 --- /dev/null +++ b/src/arch/power/insts/floating.hh @@ -0,0 +1,153 @@ +/* + * Copyright (c) 2009 The University of Edinburgh + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Timothy M. Jones + * Korey Sewell + */ + +#ifndef __ARCH_POWER_INSTS_FLOATING_HH__ +#define __ARCH_POWER_INSTS_FLOATING_HH__ + +#include "arch/power/insts/static_inst.hh" +#include "base/cprintf.hh" +#include "base/bitfield.hh" + +namespace PowerISA +{ + +/** + * Base class for floating point operations. + */ +class FloatOp : public PowerStaticInst +{ + protected: + + bool rcSet; + + /// Constructor + FloatOp(const char *mnem, MachInst _machInst, OpClass __opClass) + : PowerStaticInst(mnem, _machInst, __opClass) + { + } + + // Test for NaN (maximum biased exponent & non-zero fraction) + inline bool + isNan(uint32_t val_bits) const + { + return ((bits(val_bits, 30, 23) == 0xFF) && bits(val_bits, 22, 0)); + } + + inline bool + isNan(uint64_t val_bits) const + { + return ((bits(val_bits, 62, 52) == 0x7FF) && bits(val_bits, 51, 0)); + } + + inline bool + isNan(float val) const + { + void *val_ptr = &val; + uint32_t val_bits = *(uint32_t *) val_ptr; + return isNan(val_bits); + } + + inline bool + isNan(double val) const + { + void *val_ptr = &val; + uint64_t val_bits = *(uint64_t *) val_ptr; + return isNan(val_bits); + } + + // Test for SNaN (NaN with high order bit of fraction set to 0) + inline bool + isSnan(uint32_t val_bits) const + { + return ((bits(val_bits, 30, 22) == 0x1FE) && bits(val_bits, 22, 0)); + } + + // Test for QNaN (NaN with high order bit of fraction set to 1) + inline bool + isQnan(uint32_t val_bits) const + { + return (bits(val_bits, 30, 22) == 0x1FF); + } + + // Test for infinity (maximum biased exponent and zero fraction) + inline bool + isInfinity(uint32_t val_bits) const + { + return ((bits(val_bits, 30, 23) == 0xFF) && !bits(val_bits, 22, 0)); + } + + // Test for normalized numbers (biased exponent in the range 1 to 254) + inline bool + isNormalized(uint32_t val_bits) const + { + return ((bits(val_bits, 30, 23) != 0xFF) && bits(val_bits, 22, 0)); + } + + // Test for denormalized numbers (biased exponent of zero and + // non-zero fraction) + inline bool + isDenormalized(uint32_t val_bits) const + { + return (!bits(val_bits, 30, 23) && bits(val_bits, 22, 0)); + } + + // Test for zero (biased exponent of zero and fraction of zero) + inline bool + isZero(uint32_t val_bits) const + { + return (!bits(val_bits, 30, 23) && !bits(val_bits, 22, 0)); + } + + // Test for negative + inline bool + isNegative(uint32_t val_bits) const + { + return (bits(val_bits, 31)); + } + + // Compute the CR field + inline uint32_t + makeCRField(double a, double b) const + { + uint32_t c = 0; + if (isNan(a) || isNan(b)) { c = 0x1; } + else if (a < b) { c = 0x8; } + else if (a > b) { c = 0x4; } + else { c = 0x2; } + return c; + } + + std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const; +}; + +} // PowerISA namespace + +#endif //__ARCH_POWER_INSTS_FLOATING_HH__ diff --git a/src/arch/power/insts/integer.cc b/src/arch/power/insts/integer.cc new file mode 100644 index 000000000..1f81a15dc --- /dev/null +++ b/src/arch/power/insts/integer.cc @@ -0,0 +1,170 @@ +/* + * Copyright (c) 2009 The University of Edinburgh + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Timothy M. Jones + */ + +#include "arch/power/insts/integer.hh" + +using namespace std; +using namespace PowerISA; + +string +IntOp::generateDisassembly(Addr pc, const SymbolTable *symtab) const +{ + stringstream ss; + bool printDest = true; + bool printSrcs = true; + bool printSecondSrc = true; + + // Generate the correct mnemonic + string myMnemonic(mnemonic); + + // Special cases + if (!myMnemonic.compare("or") && _srcRegIdx[0] == _srcRegIdx[1]) { + myMnemonic = "mr"; + printSecondSrc = false; + } else if (!myMnemonic.compare("mtlr") || !myMnemonic.compare("cmpi")) { + printDest = false; + } else if (!myMnemonic.compare("mflr")) { + printSrcs = false; + } + + // Additional characters depending on isa bits being set + if (oeSet) myMnemonic = myMnemonic + "o"; + if (rcSet) myMnemonic = myMnemonic + "."; + ccprintf(ss, "%-10s ", myMnemonic); + + // Print the first destination only + if (_numDestRegs > 0 && printDest) { + printReg(ss, _destRegIdx[0]); + } + + // Print the (possibly) two source registers + if (_numSrcRegs > 0 && printSrcs) { + if (_numDestRegs > 0 && printDest) { + ss << ", "; + } + printReg(ss, _srcRegIdx[0]); + if (_numSrcRegs > 1 && printSecondSrc) { + ss << ", "; + printReg(ss, _srcRegIdx[1]); + } + } + + return ss.str(); +} + + +string +IntImmOp::generateDisassembly(Addr pc, const SymbolTable *symtab) const +{ + stringstream ss; + + // Generate the correct mnemonic + string myMnemonic(mnemonic); + + // Special cases + if (!myMnemonic.compare("addi") && _numSrcRegs == 0) { + myMnemonic = "li"; + } else if (!myMnemonic.compare("addis") && _numSrcRegs == 0) { + myMnemonic = "lis"; + } + ccprintf(ss, "%-10s ", myMnemonic); + + // Print the first destination only + if (_numDestRegs > 0) { + printReg(ss, _destRegIdx[0]); + } + + // Print the source register + if (_numSrcRegs > 0) { + if (_numDestRegs > 0) { + ss << ", "; + } + printReg(ss, _srcRegIdx[0]); + } + + // Print the immediate value last + ss << ", " << (int32_t)imm; + + return ss.str(); +} + + +string +IntShiftOp::generateDisassembly(Addr pc, const SymbolTable *symtab) const +{ + stringstream ss; + + ccprintf(ss, "%-10s ", mnemonic); + + // Print the first destination only + if (_numDestRegs > 0) { + printReg(ss, _destRegIdx[0]); + } + + // Print the first source register + if (_numSrcRegs > 0) { + if (_numDestRegs > 0) { + ss << ", "; + } + printReg(ss, _srcRegIdx[0]); + } + + // Print the shift + ss << ", " << sh; + + return ss.str(); +} + + +string +IntRotateOp::generateDisassembly(Addr pc, const SymbolTable *symtab) const +{ + stringstream ss; + + ccprintf(ss, "%-10s ", mnemonic); + + // Print the first destination only + if (_numDestRegs > 0) { + printReg(ss, _destRegIdx[0]); + } + + // Print the first source register + if (_numSrcRegs > 0) { + if (_numDestRegs > 0) { + ss << ", "; + } + printReg(ss, _srcRegIdx[0]); + } + + // Print the shift, mask begin and mask end + ss << ", " << sh << ", " << mb << ", " << me; + + return ss.str(); +} diff --git a/src/arch/power/insts/integer.hh b/src/arch/power/insts/integer.hh new file mode 100644 index 000000000..b4b96d5dc --- /dev/null +++ b/src/arch/power/insts/integer.hh @@ -0,0 +1,176 @@ +/* + * Copyright (c) 2009 The University of Edinburgh + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Timothy M. Jones + */ + +#ifndef __ARCH_POWER_INSTS_INTEGER_HH__ +#define __ARCH_POWER_INSTS_INTEGER_HH__ + +#include "arch/power/insts/static_inst.hh" +#include "base/cprintf.hh" +#include "base/bitfield.hh" + +namespace PowerISA +{ + +/** + * We provide a base class for integer operations and then inherit for + * several other classes. These specialise for instructions using immediate + * values and also rotate instructions. We also need to have versions that + * consider the Rc and OE bits. + */ + +/** + * Base class for integer operations. + */ +class IntOp : public PowerStaticInst +{ + protected: + + bool rcSet; + bool oeSet; + + // Needed for srawi only + uint32_t sh; + + /// Constructor + IntOp(const char *mnem, MachInst _machInst, OpClass __opClass) + : PowerStaticInst(mnem, _machInst, __opClass), + rcSet(false), oeSet(false) + { + } + + /* Compute the CR (condition register) field using signed comparison */ + inline uint32_t + makeCRField(int32_t a, int32_t b, uint32_t xerSO) const + { + uint32_t c = xerSO; + + /* We've pre-shifted the immediate values here */ + if (a < b) { c += 0x8; } + else if (a > b) { c += 0x4; } + else { c += 0x2; } + return c; + } + + /* Compute the CR (condition register) field using unsigned comparison */ + inline uint32_t + makeCRField(uint32_t a, uint32_t b, uint32_t xerSO) const + { + uint32_t c = xerSO; + + /* We've pre-shifted the immediate values here */ + if (a < b) { c += 0x8; } + else if (a > b) { c += 0x4; } + else { c += 0x2; } + return c; + } + + std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const; +}; + + +/** + * Class for integer immediate (signed and unsigned) operations. + */ +class IntImmOp : public IntOp +{ + protected: + + int32_t imm; + uint32_t uimm; + + /// Constructor + IntImmOp(const char *mnem, MachInst _machInst, OpClass __opClass) + : IntOp(mnem, _machInst, __opClass), + imm(sext<16>(machInst.si)), + uimm(machInst.si) + { + } + + std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const; +}; + + +/** + * Class for integer operations with a shift. + */ +class IntShiftOp : public IntOp +{ + protected: + + uint32_t sh; + + /// Constructor + IntShiftOp(const char *mnem, MachInst _machInst, OpClass __opClass) + : IntOp(mnem, _machInst, __opClass), + sh(machInst.sh) + { + } + + std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const; +}; + + +/** + * Class for integer rotate operations. + */ +class IntRotateOp : public IntShiftOp +{ + protected: + + uint32_t mb; + uint32_t me; + uint32_t fullMask; + + /// Constructor + IntRotateOp(const char *mnem, MachInst _machInst, OpClass __opClass) + : IntShiftOp(mnem, _machInst, __opClass), + mb(machInst.mb), + me(machInst.me) + { + if (me >= mb) { + fullMask = mask(31 - mb, 31 - me); + } else { + fullMask = ~mask(31 - (me + 1), 31 - (mb - 1)); + } + } + + uint32_t + rotateValue(uint32_t rs, uint32_t shift) const + { + uint32_t n = shift & 31; + return (rs << n) | (rs >> (32 - n)); + } + + std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const; +}; + +} // PowerISA namespace + +#endif //__ARCH_POWER_INSTS_INTEGER_HH__ diff --git a/src/mem/slicc/ast/DeclListAST.cc b/src/arch/power/insts/mem.cc index 8337d714b..447efa2f4 100644 --- a/src/mem/slicc/ast/DeclListAST.cc +++ b/src/arch/power/insts/mem.cc @@ -1,6 +1,5 @@ - /* - * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood + * Copyright (c) 2009 The University of Edinburgh * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -25,62 +24,51 @@ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/* - * DeclListAST.C - * - * Description: See DeclListAST.hh - * - * $Id$ * + * Authors: Timothy M. Jones */ -#include "mem/slicc/ast/DeclListAST.hh" +#include "arch/power/insts/mem.hh" +#include "base/loader/symtab.hh" -DeclListAST::DeclListAST(Vector<DeclAST*>* vec_ptr) - : AST() -{ - assert(vec_ptr != NULL); - m_vec_ptr = vec_ptr; -} +using namespace PowerISA; -// Singleton constructor. -DeclListAST::DeclListAST(DeclAST* Decl_ptr) - : AST() +std::string +MemOp::generateDisassembly(Addr pc, const SymbolTable *symtab) const { - assert(Decl_ptr != NULL); - m_vec_ptr = new Vector<DeclAST*>; - m_vec_ptr->insertAtTop(Decl_ptr); + return csprintf("%-10s", mnemonic); } -DeclListAST::~DeclListAST() +std::string +MemDispOp::generateDisassembly(Addr pc, const SymbolTable *symtab) const { - int size = m_vec_ptr->size(); - for(int i=0; i<size; i++) { - delete (*m_vec_ptr)[i]; - } - delete m_vec_ptr; -} + std::stringstream ss; -void DeclListAST::generate() const -{ - int size = m_vec_ptr->size(); - for(int i=0; i<size; i++) { - (*m_vec_ptr)[i]->generate(); - } -} + ccprintf(ss, "%-10s ", mnemonic); -void DeclListAST::findMachines() const -{ - int size = m_vec_ptr->size(); - for(int i=0; i<size; i++) { - (*m_vec_ptr)[i]->findMachines(); - } -} + // Print the destination only for a load + if (!flags[IsStore]) { + if (_numDestRegs > 0) { -void DeclListAST::print(ostream& out) const -{ - assert(m_vec_ptr != NULL); - out << "[DeclListAST: " << *m_vec_ptr << "]"; + // If the instruction updates the source register with the + // EA, then this source register is placed in position 0, + // therefore we print the last destination register. + printReg(ss, _destRegIdx[_numDestRegs-1]); + } + } + + // Print the data register for a store + else { + printReg(ss, _srcRegIdx[1]); + } + + // Print the displacement + ss << ", " << (int32_t)disp; + + // Print the address register + ss << "("; + printReg(ss, _srcRegIdx[0]); + ss << ")"; + + return ss.str(); } diff --git a/src/mem/slicc/ast/TypeDeclAST.cc b/src/arch/power/insts/mem.hh index bbf2f8491..329dafe57 100644 --- a/src/mem/slicc/ast/TypeDeclAST.cc +++ b/src/arch/power/insts/mem.hh @@ -1,6 +1,5 @@ - /* - * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood + * Copyright (c) 2009 The University of Edinburgh * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -25,62 +24,68 @@ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/* - * TypeDeclAST.C - * - * Description: See TypeDeclAST.hh - * - * $Id: TypeDeclAST.C,v 3.1 2003/03/22 15:15:17 xu Exp $ * + * Authors: Timothy M. Jones */ -#include "mem/slicc/ast/TypeDeclAST.hh" -#include "mem/slicc/main.hh" -#include "mem/slicc/symbols/SymbolTable.hh" +#ifndef __ARCH_POWER_MEM_HH__ +#define __ARCH_POWER_MEM_HH__ -TypeDeclAST::TypeDeclAST(TypeAST* type_ast_ptr, - PairListAST* pairs_ptr, - Vector<TypeFieldAST*>* field_vec_ptr) - : DeclAST(pairs_ptr) +#include "arch/power/insts/static_inst.hh" + +namespace PowerISA { - m_type_ast_ptr = type_ast_ptr; - m_field_vec_ptr = field_vec_ptr; -} -TypeDeclAST::~TypeDeclAST() +/** + * Base class for memory operations. + */ +class MemOp : public PowerStaticInst { - delete m_type_ast_ptr; - if (m_field_vec_ptr != NULL) { - int size = m_field_vec_ptr->size(); - for(int i=0; i<size; i++) { - delete (*m_field_vec_ptr)[i]; + protected: + + /// Memory request flags. See mem_req_base.hh. + unsigned memAccessFlags; + /// Pointer to EAComp object. + const StaticInstPtr eaCompPtr; + /// Pointer to MemAcc object. + const StaticInstPtr memAccPtr; + + /// Constructor + MemOp(const char *mnem, MachInst _machInst, OpClass __opClass, + StaticInstPtr _eaCompPtr = nullStaticInstPtr, + StaticInstPtr _memAccPtr = nullStaticInstPtr) + : PowerStaticInst(mnem, _machInst, __opClass), + memAccessFlags(0), + eaCompPtr(_eaCompPtr), + memAccPtr(_memAccPtr) + { } - delete m_field_vec_ptr; - } -} -void TypeDeclAST::generate() + std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const; +}; + + +/** + * Class for memory operations with displacement. + */ +class MemDispOp : public MemOp { - string machine_name; - string id = m_type_ast_ptr->toString(); + protected: - // Make the new type - Type* new_type_ptr = new Type(id, getLocation(), getPairs(), - g_sym_table.getStateMachine()); - g_sym_table.newSym(new_type_ptr); + int16_t disp; - // Add all of the fields of the type to it - if (m_field_vec_ptr != NULL) { - int size = m_field_vec_ptr->size(); - for(int i=0; i<size; i++) { - (*m_field_vec_ptr)[i]->generate(new_type_ptr); + /// Constructor + MemDispOp(const char *mnem, MachInst _machInst, OpClass __opClass, + StaticInstPtr _eaCompPtr = nullStaticInstPtr, + StaticInstPtr _memAccPtr = nullStaticInstPtr) + : MemOp(mnem, _machInst, __opClass, _eaCompPtr, _memAccPtr), + disp(machInst.d) + { } - } -} -void TypeDeclAST::print(ostream& out) const -{ - out << "[TypeDecl: " << m_type_ast_ptr->toString() << "]"; -} + std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const; +}; + +} // PowerISA namespace + +#endif //__ARCH_POWER_INSTS_MEM_HH__ diff --git a/src/arch/power/insts/misc.cc b/src/arch/power/insts/misc.cc new file mode 100644 index 000000000..913030b61 --- /dev/null +++ b/src/arch/power/insts/misc.cc @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2009 The University of Edinburgh + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Timothy M. Jones + */ + +#include "arch/power/insts/misc.hh" + +using namespace PowerISA; + +std::string +MiscOp::generateDisassembly(Addr pc, const SymbolTable *symtab) const +{ + std::stringstream ss; + + ccprintf(ss, "%-10s ", mnemonic); + + // Print the first destination only + if (_numDestRegs > 0) { + printReg(ss, _destRegIdx[0]); + } + + // Print the (possibly) two source registers + if (_numSrcRegs > 0) { + if (_numDestRegs > 0) { + ss << ", "; + } + printReg(ss, _srcRegIdx[0]); + if (_numSrcRegs > 1) { + ss << ", "; + printReg(ss, _srcRegIdx[1]); + } + } + + return ss.str(); +} diff --git a/src/mem/slicc/ast/LiteralExprAST.cc b/src/arch/power/insts/misc.hh index 4e384a3b3..dd4941b93 100644 --- a/src/mem/slicc/ast/LiteralExprAST.cc +++ b/src/arch/power/insts/misc.hh @@ -1,6 +1,5 @@ - /* - * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood + * Copyright (c) 2009 The University of Edinburgh * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -25,31 +24,34 @@ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/* - * LiteralExprAST.C - * - * Description: See LiteralExprAST.hh - * - * $Id: LiteralExprAST.C,v 3.1 2002/10/22 21:27:52 milo Exp $ * + * Authors: Timothy M. Jones */ -#include "mem/slicc/ast/LiteralExprAST.hh" +#ifndef __ARCH_POWER_INSTS_MISC_HH__ +#define __ARCH_POWER_INSTS_MISC_HH__ + +#include "arch/power/insts/static_inst.hh" -Type* LiteralExprAST::generate(string& code) const +namespace PowerISA { - if (m_type == "string") { - code += "(\"" + *m_lit_ptr + "\")"; - } else { - code += "(" + *m_lit_ptr + ")"; - } - - Type* type_ptr = g_sym_table.getType(m_type); - if (type_ptr == NULL) { - // Can't find the type - error("Internal: can't primitive type '" + m_type + "'"); - } - return type_ptr; -} + +/** + * Class for misc operations. + */ +class MiscOp : public PowerStaticInst +{ + protected: + + /// Constructor + MiscOp(const char *mnem, MachInst _machInst, OpClass __opClass) + : PowerStaticInst(mnem, _machInst, __opClass) + { + } + + std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const; +}; + +} // PowerISA namespace + +#endif //__ARCH_POWER_INSTS_MISC_HH__ diff --git a/src/arch/power/insts/static_inst.cc b/src/arch/power/insts/static_inst.cc new file mode 100644 index 000000000..1982744bf --- /dev/null +++ b/src/arch/power/insts/static_inst.cc @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2009 The University of Edinburgh + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Timothy M. Jones + */ + +#include "arch/power/insts/static_inst.hh" + +using namespace PowerISA; + +void +PowerStaticInst::printReg(std::ostream &os, int reg) const +{ + if (reg < FP_Base_DepTag) { + ccprintf(os, "r%d", reg); + } else if (reg < Ctrl_Base_DepTag) { + ccprintf(os, "f%d", reg - FP_Base_DepTag); + } else { + switch (reg - Ctrl_Base_DepTag) { + case 0: ccprintf(os, "cr"); break; + case 1: ccprintf(os, "xer"); break; + case 2: ccprintf(os, "lr"); break; + case 3: ccprintf(os, "ctr"); break; + default: ccprintf(os, "unknown_reg"); + } + } +} + +std::string +PowerStaticInst::generateDisassembly(Addr pc, + const SymbolTable *symtab) const +{ + std::stringstream ss; + + ccprintf(ss, "%-10s ", mnemonic); + + return ss.str(); +} diff --git a/src/mem/slicc/ast/PairListAST.hh b/src/arch/power/insts/static_inst.hh index 7edcdc1e7..399e75371 100644 --- a/src/mem/slicc/ast/PairListAST.hh +++ b/src/arch/power/insts/static_inst.hh @@ -1,6 +1,5 @@ - /* - * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood + * Copyright (c) 2009 The University of Edinburgh * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -25,58 +24,47 @@ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/* - * PairListAST.hh - * - * Description: - * - * $Id$ * + * Authors: Timothy M. Jones */ -#ifndef PairListAST_H -#define PairListAST_H +#ifndef __ARCH_POWER_INSTS_STATICINST_HH__ +#define __ARCH_POWER_INSTS_STATICINST_HH__ -#include "mem/slicc/slicc_global.hh" -#include "mem/slicc/ast/AST.hh" -#include "mem/slicc/ast/PairAST.hh" +#include "base/trace.hh" +#include "cpu/static_inst.hh" +namespace PowerISA +{ -class PairListAST : public AST { -public: - // Constructors - PairListAST() : AST() {} +class PowerStaticInst : public StaticInst +{ + protected: - // Destructor - //~PairListAST(); + // Constructor + PowerStaticInst(const char *mnem, MachInst _machInst, OpClass __opClass) + : StaticInst(mnem, _machInst, __opClass) + { + } - // Public Methods - void addPair(PairAST* pair_ptr); - void print(ostream& out) const; -private: - // Private Methods + // Insert a condition value into a CR (condition register) field + inline uint32_t + insertCRField(uint32_t cr, uint32_t bf, uint32_t value) const + { + uint32_t bits = value << ((7 - bf) * 4); + uint32_t mask = ~(0xf << ((7 - bf) * 4)); + return (cr & mask) | bits; + } - // Private copy constructor and assignment operator - PairListAST(const PairListAST& obj); - PairListAST& operator=(const PairListAST& obj); + /// Print a register name for disassembly given the unique + /// dependence tag number (FP or int). + void + printReg(std::ostream &os, int reg) const; - // Data Members (m_ prefix) + std::string + generateDisassembly(Addr pc, const SymbolTable *symtab) const; }; -// Output operator declaration -ostream& operator<<(ostream& out, const PairListAST& obj); - -// ******************* Definitions ******************* - -// Output operator definition -extern inline -ostream& operator<<(ostream& out, const PairListAST& obj) -{ - obj.print(out); - out << flush; - return out; -} +} // PowerISA namespace -#endif //PairListAST_H +#endif //__ARCH_POWER_INSTS_STATICINST_HH__ diff --git a/src/arch/power/isa.hh b/src/arch/power/isa.hh new file mode 100644 index 000000000..ba1b5018d --- /dev/null +++ b/src/arch/power/isa.hh @@ -0,0 +1,115 @@ +/* + * Copyright (c) 2009 The Regents of The University of Michigan + * Copyright (c) 2009 The University of Edinburgh + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Gabe Black + * Timothy M. Jones + */ + +#ifndef __ARCH_POWER_ISA_HH__ +#define __ARCH_POWER_ISA_HH__ + +#include "arch/power/registers.hh" +#include "arch/power/types.hh" +#include "base/misc.hh" + +class ThreadContext; +class Checkpoint; +class EventManager; + +namespace PowerISA +{ + +class ISA +{ + protected: + MiscReg dummy; + MiscReg miscRegs[NumMiscRegs]; + + public: + void + clear() + { + } + + MiscReg + readMiscRegNoEffect(int misc_reg) + { + fatal("Power does not currently have any misc regs defined\n"); + return dummy; + } + + MiscReg + readMiscReg(int misc_reg, ThreadContext *tc) + { + fatal("Power does not currently have any misc regs defined\n"); + return dummy; + } + + void + setMiscRegNoEffect(int misc_reg, const MiscReg &val) + { + fatal("Power does not currently have any misc regs defined\n"); + } + + void + setMiscReg(int misc_reg, const MiscReg &val, ThreadContext *tc) + { + fatal("Power does not currently have any misc regs defined\n"); + } + + int + flattenIntIndex(int reg) + { + return reg; + } + + int + flattenFloatIndex(int reg) + { + return reg; + } + + void + serialize(EventManager *em, std::ostream &os) + { + } + + void + unserialize(EventManager *em, Checkpoint *cp, const std::string §ion) + { + } + + ISA() + { + clear(); + } +}; + +} // PowerISA namespace + +#endif // __ARCH_POWER_ISA_HH__ diff --git a/src/arch/power/isa/bitfields.isa b/src/arch/power/isa/bitfields.isa new file mode 100644 index 000000000..8cd323ad5 --- /dev/null +++ b/src/arch/power/isa/bitfields.isa @@ -0,0 +1,84 @@ +// -*- mode:c++ -*- + +// Copyright (c) 2009 The University of Edinburgh +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer; +// redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution; +// neither the name of the copyright holders nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Authors: Timothy M. Jones + +//////////////////////////////////////////////////////////////////// +// +// Bitfield definitions. +// +// The endianness is the opposite to what's used here, so things +// are reversed sometimes. Not sure of a fix to this though... + +// Opcode fields +def bitfield OPCODE <31:26>; +def bitfield X_XO <10:0>; +def bitfield XO_XO <10:1>; +def bitfield A_XO <5:1>; + +// Register fields +def bitfield RA <20:16>; +def bitfield RB <15:11>; +def bitfield RS <25:21>; +def bitfield RT <25:21>; +def bitfield FRA <20:16>; +def bitfield FRB <15:11>; +def bitfield FRC <10:6>; +def bitfield FRS <25:21>; +def bitfield FRT <25:21>; + +// The record bit can be in two positions +// Used to enable setting of the condition register +def bitfield RC31 <0>; +def bitfield RC21 <10>; + +// Used to enable setting of the overflow flags +def bitfield OE <10>; + +// SPR field for mtspr instruction +def bitfield SPR <20:11>; + +// FXM field for mtcrf instruction +def bitfield FXM <19:12>; + +// Branch fields +def bitfield LK <0>; +def bitfield AA <1>; + +// Specifies a CR or FPSCR field +def bitfield BF <25:23>; + +// Fields for FPSCR manipulation instructions +def bitfield FLM <24:17>; +def bitfield L <25>; +def bitfield W <16>; +// Named so to avoid conflicts with range.hh +def bitfield U_FIELD <15:12>; + +// Field for specifying a bit in CR or FPSCR +def bitfield BT <25:21>; diff --git a/src/arch/power/isa/decoder.isa b/src/arch/power/isa/decoder.isa new file mode 100644 index 000000000..3252ff14a --- /dev/null +++ b/src/arch/power/isa/decoder.isa @@ -0,0 +1,593 @@ +// -*- mode:c++ -*- + +// Copyright (c) 2009 The University of Edinburgh +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer; +// redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution; +// neither the name of the copyright holders nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Authors: Timothy M. Jones + +//////////////////////////////////////////////////////////////////// +// +// The actual Power ISA decoder +// ------------------------------ +// +// I've used the Power ISA Book I v2.06 for instruction formats, +// opcode numbers, register names, etc. +// +decode OPCODE default Unknown::unknown() { + + format IntImmOp { + 10: cmpli({{ + Xer xer = XER; + uint32_t cr = makeCRField(Ra, (uint32_t)uimm, xer.so); + CR = insertCRField(CR, BF, cr); + }}); + 11: cmpi({{ + Xer xer = XER; + uint32_t cr = makeCRField(Ra.sw, (int32_t)imm, xer.so); + CR = insertCRField(CR, BF, cr); + }}); + } + + // Some instructions use bits 21 - 30, others 22 - 30. We have to use + // the larger size to account for all opcodes. For those that use the + // smaller value, the OE bit is bit 21. Therefore, we have two versions + // of each instruction: 1 with OE set, the other without. For an + // example see 'add' and 'addo'. + 31: decode XO_XO { + + // These instructions can all be reduced to the form + // Rt = src1 + src2 [+ CA], therefore we just give src1 and src2 + // (and, if necessary, CA) definitions and let the python script + // deal with setting things up correctly. We also give flags to + // say which control registers to set. + format IntSumOp { + 266: add({{ Ra }}, {{ Rb }}); + 40: subf({{ ~Ra }}, {{ Rb }}, {{ 1 }}); + 10: addc({{ Ra }}, {{ Rb }}, + computeCA = true); + 8: subfc({{ ~Ra }}, {{ Rb }}, {{ 1 }}, + true); + 104: neg({{ ~Ra }}, {{ 1 }}); + 138: adde({{ Ra }}, {{ Rb }}, {{ xer.ca }}, + true); + 234: addme({{ Ra }}, {{ (uint32_t)-1 }}, {{ xer.ca }}, + true); + 136: subfe({{ ~Ra }}, {{ Rb }}, {{ xer.ca }}, + true); + 232: subfme({{ ~Ra }}, {{ (uint32_t)-1 }}, {{ xer.ca }}, + true); + 202: addze({{ Ra }}, {{ xer.ca }}, + computeCA = true); + 200: subfze({{ ~Ra }}, {{ xer.ca }}, + computeCA = true); + } + + // Arithmetic instructions all use source registers Ra and Rb, + // with destination register Rt. + format IntArithOp { + 75: mulhw({{ int64_t prod = Ra.sq * Rb.sq; Rt = prod >> 32; }}); + 11: mulhwu({{ uint64_t prod = Ra.uq * Rb.uq; Rt = prod >> 32; }}); + 235: mullw({{ int64_t prod = Ra.sq * Rb.sq; Rt = prod; }}); + 747: mullwo({{ int64_t src1 = Ra.sq; int64_t src2 = Rb; int64_t prod = src1 * src2; Rt = prod; }}, + true); + + 491: divw({{ + int32_t src1 = Ra.sw; + int32_t src2 = Rb.sw; + if ((src1 != 0x80000000 || src2 != 0xffffffff) + && src2 != 0) { + Rt = src1 / src2; + } else { + Rt = 0; + } + }}); + + 1003: divwo({{ + int32_t src1 = Ra.sw; + int32_t src2 = Rb.sw; + if ((src1 != 0x80000000 || src2 != 0xffffffff) + && src2 != 0) { + Rt = src1 / src2; + } else { + Rt = 0; + divSetOV = true; + } + }}, + true); + + 459: divwu({{ + uint32_t src1 = Ra.sw; + uint32_t src2 = Rb.sw; + if (src2 != 0) { + Rt = src1 / src2; + } else { + Rt = 0; + } + }}); + + 971: divwuo({{ + uint32_t src1 = Ra.sw; + uint32_t src2 = Rb.sw; + if (src2 != 0) { + Rt = src1 / src2; + } else { + Rt = 0; + divSetOV = true; + } + }}, + true); + } + + // Integer logic instructions use source registers Rs and Rb, + // with destination register Ra. + format IntLogicOp { + 28: and({{ Ra = Rs & Rb; }}); + 316: xor({{ Ra = Rs ^ Rb; }}); + 476: nand({{ Ra = ~(Rs & Rb); }}); + 444: or({{ Ra = Rs | Rb; }}); + 124: nor({{ Ra = ~(Rs | Rb); }}); + 60: andc({{ Ra = Rs & ~Rb; }}); + 954: extsb({{ Ra = sext<8>(Rs); }}); + 284: eqv({{ Ra = ~(Rs ^ Rb); }}); + 412: orc({{ Ra = Rs | ~Rb; }}); + 922: extsh({{ Ra = sext<16>(Rs); }}); + 26: cntlzw({{ Ra = Rs == 0 ? 32 : 31 - findMsbSet(Rs); }}); + 508: cmpb({{ + uint32_t val = 0; + for (int n = 0; n < 32; n += 8) { + if(bits(Rs, n, n+7) == bits(Rb, n, n+7)) { + val = insertBits(val, n, n+7, 0xff); + } + } + Ra = val; + }}); + + 24: slw({{ + if (Rb & 0x20) { + Ra = 0; + } else { + Ra = Rs << (Rb & 0x1f); + } + }}); + + 536: srw({{ + if (Rb & 0x20) { + Ra = 0; + } else { + Ra = Rs >> (Rb & 0x1f); + } + }}); + + 792: sraw({{ + bool shiftSetCA = false; + int32_t s = Rs; + if (Rb == 0) { + Ra = Rs; + shiftSetCA = true; + } else if (Rb & 0x20) { + if (s < 0) { + Ra = (uint32_t)-1; + if (s & 0x7fffffff) { + shiftSetCA = true; + } else { + shiftSetCA = false; + } + } else { + Ra = 0; + shiftSetCA = false; + } + } else { + Ra = s >> (Rb & 0x1f); + if (s < 0 && (s << (32 - (Rb & 0x1f))) != 0) { + shiftSetCA = true; + } else { + shiftSetCA = false; + } + } + Xer xer1 = XER; + if (shiftSetCA) { + xer1.ca = 1; + } else { + xer1.ca = 0; + } + XER = xer1; + }}); + } + + // Integer logic instructions with a shift value. + format IntShiftOp { + 824: srawi({{ + bool shiftSetCA = false; + if (sh == 0) { + Ra = Rs; + shiftSetCA = false; + } else { + int32_t s = Rs; + Ra = s >> sh; + if (s < 0 && (s << (32 - sh)) != 0) { + shiftSetCA = true; + } else { + shiftSetCA = false; + } + } + Xer xer1 = XER; + if (shiftSetCA) { + xer1.ca = 1; + } else { + xer1.ca = 0; + } + XER = xer1; + }}); + } + + // Generic integer format instructions. + format IntOp { + 0: cmp({{ + Xer xer = XER; + uint32_t cr = makeCRField(Ra.sw, Rb.sw, xer.so); + CR = insertCRField(CR, BF, cr); + }}); + 32: cmpl({{ + Xer xer = XER; + uint32_t cr = makeCRField(Ra, Rb, xer.so); + CR = insertCRField(CR, BF, cr); + }}); + 144: mtcrf({{ + uint32_t mask = 0; + for (int i = 0; i < 8; ++i) { + if (((FXM >> i) & 0x1) == 0x1) { + mask |= 0xf << (4 * i); + } + } + CR = (Rs & mask) | (CR & ~mask); + }}); + 19: mfcr({{ Rt = CR; }}); + 339: decode SPR { + 0x20: mfxer({{ Rt = XER; }}); + 0x100: mflr({{ Rt = LR; }}); + 0x120: mfctr({{ Rt = CTR; }}); + } + 467: decode SPR { + 0x20: mtxer({{ XER = Rs; }}); + 0x100: mtlr({{ LR = Rs; }}); + 0x120: mtctr({{ CTR = Rs; }}); + } + } + + // All loads with an index register. The non-update versions + // all use the value 0 if Ra == R0, not the value contained in + // R0. Others update Ra with the effective address. In all cases, + // Ra and Rb are source registers, Rt is the destintation. + format LoadIndexOp { + 87: lbzx({{ Rt = Mem.ub; }}); + 279: lhzx({{ Rt = Mem.uh; }}); + 343: lhax({{ Rt = Mem.sh; }}); + 23: lwzx({{ Rt = Mem; }}); + 341: lwax({{ Rt = Mem.sw; }}); + 20: lwarx({{ Rt = Mem.sw; Rsv = 1; RsvLen = 4; RsvAddr = EA; }}); + 535: lfsx({{ Ft.sf = Mem.sf; }}); + 599: lfdx({{ Ft = Mem.df; }}); + 855: lfiwax({{ Ft.uw = Mem; }}); + } + + format LoadIndexUpdateOp { + 119: lbzux({{ Rt = Mem.ub; }}); + 311: lhzux({{ Rt = Mem.uh; }}); + 375: lhaux({{ Rt = Mem.sh; }}); + 55: lwzux({{ Rt = Mem; }}); + 373: lwaux({{ Rt = Mem.sw; }}); + 567: lfsux({{ Ft.sf = Mem.sf; }}); + 631: lfdux({{ Ft = Mem.df; }}); + } + + format StoreIndexOp { + 215: stbx({{ Mem.ub = Rs.ub; }}); + 407: sthx({{ Mem.uh = Rs.uh; }}); + 151: stwx({{ Mem = Rs; }}); + 150: stwcx({{ + bool store_performed = false; + if (Rsv) { + if (RsvLen == 4) { + if (RsvAddr == EA) { + Mem = Rs; + store_performed = true; + } + } + } + Xer xer = XER; + Cr cr = CR; + cr.cr0 = ((store_performed ? 0x2 : 0x0) | xer.so); + CR = cr; + Rsv = 0; + }}); + 663: stfsx({{ Mem.sf = Fs.sf; }}); + 727: stfdx({{ Mem.df = Fs; }}); + 983: stfiwx({{ Mem = Fs.uw; }}); + } + + format StoreIndexUpdateOp { + 247: stbux({{ Mem.ub = Rs.ub; }}); + 439: sthux({{ Mem.uh = Rs.uh; }}); + 183: stwux({{ Mem = Rs; }}); + 695: stfsux({{ Mem.sf = Fs.sf; }}); + 759: stfdux({{ Mem.df = Fs; }}); + } + + // These instructions all provide data cache hints + format MiscOp { + 278: dcbt({{ }}); + 246: dcbtst({{ }}); + 598: sync({{ }}, [ IsMemBarrier ]); + 854: eieio({{ }}, [ IsMemBarrier ]); + } + } + + format IntImmArithCheckRaOp { + 14: addi({{ Rt = Ra + imm; }}, + {{ Rt = imm }}); + 15: addis({{ Rt = Ra + (imm << 16); }}, + {{ Rt = imm << 16; }}); + } + + format IntImmArithOp { + 12: addic({{ uint32_t src = Ra; Rt = src + imm; }}, + [computeCA]); + 13: addic_({{ uint32_t src = Ra; Rt = src + imm; }}, + [computeCA, computeCR0]); + 8: subfic({{ int32_t src = ~Ra; Rt = src + imm + 1; }}, + [computeCA]); + 7: mulli({{ + int32_t src = Ra.sw; + int64_t prod = src * imm; + Rt = (uint32_t)prod; + }}); + } + + format IntImmLogicOp { + 24: ori({{ Ra = Rs | uimm; }}); + 25: oris({{ Ra = Rs | (uimm << 16); }}); + 26: xori({{ Ra = Rs ^ uimm; }}); + 27: xoris({{ Ra = Rs ^ (uimm << 16); }}); + 28: andi_({{ Ra = Rs & uimm; }}, + true); + 29: andis_({{ Ra = Rs & (uimm << 16); }}, + true); + } + + 16: decode AA { + + // Conditionally branch relative to PC based on CR and CTR. + format BranchPCRelCondCtr { + 0: bc({{ NPC = PC + disp; }}); + } + + // Conditionally branch to fixed address based on CR and CTR. + format BranchNonPCRelCondCtr { + 1: bca({{ NPC = targetAddr; }}); + } + } + + 18: decode AA { + + // Unconditionally branch relative to PC. + format BranchPCRel { + 0: b({{ NPC = PC + disp; }}); + } + + // Unconditionally branch to fixed address. + format BranchNonPCRel { + 1: ba({{ NPC = targetAddr; }}); + } + } + + 19: decode XO_XO { + + // Conditionally branch to address in LR based on CR and CTR. + format BranchLrCondCtr { + 16: bclr({{ NPC = LR & 0xfffffffc; }}); + } + + // Conditionally branch to address in CTR based on CR. + format BranchCtrCond { + 528: bcctr({{ NPC = CTR & 0xfffffffc; }}); + } + + // Condition register manipulation instructions. + format CondLogicOp { + 257: crand({{ + uint32_t crBa = bits(CR, 31 - ba); + uint32_t crBb = bits(CR, 31 - bb); + CR = insertBits(CR, 31 - bt, crBa & crBb); + }}); + 449: cror({{ + uint32_t crBa = bits(CR, 31 - ba); + uint32_t crBb = bits(CR, 31 - bb); + CR = insertBits(CR, 31 - bt, crBa | crBb); + }}); + 255: crnand({{ + uint32_t crBa = bits(CR, 31 - ba); + uint32_t crBb = bits(CR, 31 - bb); + CR = insertBits(CR, 31 - bt, !(crBa & crBb)); + }}); + 193: crxor({{ + uint32_t crBa = bits(CR, 31 - ba); + uint32_t crBb = bits(CR, 31 - bb); + CR = insertBits(CR, 31 - bt, crBa ^ crBb); + }}); + 33: crnor({{ + uint32_t crBa = bits(CR, 31 - ba); + uint32_t crBb = bits(CR, 31 - bb); + CR = insertBits(CR, 31 - bt, !(crBa | crBb)); + }}); + 289: creqv({{ + uint32_t crBa = bits(CR, 31 - ba); + uint32_t crBb = bits(CR, 31 - bb); + CR = insertBits(CR, 31 - bt, crBa == crBb); + }}); + 129: crandc({{ + uint32_t crBa = bits(CR, 31 - ba); + uint32_t crBb = bits(CR, 31 - bb); + CR = insertBits(CR, 31 - bt, crBa & !crBb); + }}); + 417: crorc({{ + uint32_t crBa = bits(CR, 31 - ba); + uint32_t crBb = bits(CR, 31 - bb); + CR = insertBits(CR, 31 - bt, crBa | !crBb); + }}); + } + format CondMoveOp { + 0: mcrf({{ + uint32_t crBfa = bits(CR, 31 - bfa*4, 28 - bfa*4); + CR = insertBits(CR, 31 - bf*4, 28 - bf*4, crBfa); + }}); + } + format MiscOp { + 150: isync({{ }}, [ IsSerializeAfter ]); + } + } + + format IntRotateOp { + 21: rlwinm({{ Ra = rotateValue(Rs, sh) & fullMask; }}); + 23: rlwnm({{ Ra = rotateValue(Rs, Rb) & fullMask; }}); + 20: rlwimi({{ Ra = (rotateValue(Rs, sh) & fullMask) | (Ra & ~fullMask); }}); + } + + format LoadDispOp { + 34: lbz({{ Rt = Mem.ub; }}); + 40: lhz({{ Rt = Mem.uh; }}); + 42: lha({{ Rt = Mem.sh; }}); + 32: lwz({{ Rt = Mem; }}); + 58: lwa({{ Rt = Mem.sw; }}, + {{ EA = Ra + (disp & 0xfffffffc); }}, + {{ EA = disp & 0xfffffffc; }}); + 48: lfs({{ Ft.sf = Mem.sf; }}); + 50: lfd({{ Ft = Mem.df; }}); + } + + format LoadDispUpdateOp { + 35: lbzu({{ Rt = Mem.ub; }}); + 41: lhzu({{ Rt = Mem.uh; }}); + 43: lhau({{ Rt = Mem.sh; }}); + 33: lwzu({{ Rt = Mem; }}); + 49: lfsu({{ Ft.sf = Mem.sf; }}); + 51: lfdu({{ Ft = Mem.df; }}); + } + + format StoreDispOp { + 38: stb({{ Mem.ub = Rs.ub; }}); + 44: sth({{ Mem.uh = Rs.uh; }}); + 36: stw({{ Mem = Rs; }}); + 52: stfs({{ Mem.sf = Fs.sf; }}); + 54: stfd({{ Mem.df = Fs; }}); + } + + format StoreDispUpdateOp { + 39: stbu({{ Mem.ub = Rs.ub; }}); + 45: sthu({{ Mem.uh = Rs.uh; }}); + 37: stwu({{ Mem = Rs; }}); + 53: stfsu({{ Mem.sf = Fs.sf; }}); + 55: stfdu({{ Mem.df = Fs; }}); + } + + 17: IntOp::sc({{ xc->syscall(R0); }}, + [ IsSyscall, IsNonSpeculative, IsSerializeAfter ]); + + format FloatArithOp { + 59: decode A_XO { + 21: fadds({{ Ft = Fa + Fb; }}); + 20: fsubs({{ Ft = Fa - Fb; }}); + 25: fmuls({{ Ft = Fa * Fc; }}); + 18: fdivs({{ Ft = Fa / Fb; }}); + 29: fmadds({{ Ft = (Fa * Fc) + Fb; }}); + 28: fmsubs({{ Ft = (Fa * Fc) - Fb; }}); + 31: fnmadds({{ Ft = -((Fa * Fc) + Fb); }}); + 30: fnmsubs({{ Ft = -((Fa * Fc) - Fb); }}); + } + } + + 63: decode A_XO { + format FloatArithOp { + 21: fadd({{ Ft = Fa + Fb; }}); + 20: fsub({{ Ft = Fa - Fb; }}); + 25: fmul({{ Ft = Fa * Fc; }}); + 18: fdiv({{ Ft = Fa / Fb; }}); + 29: fmadd({{ Ft = (Fa * Fc) + Fb; }}); + 28: fmsub({{ Ft = (Fa * Fc) - Fb; }}); + 31: fnmadd({{ Ft = -((Fa * Fc) + Fb); }}); + 30: fnmsub({{ Ft = -((Fa * Fc) - Fb); }}); + } + + default: decode XO_XO { + format FloatConvertOp { + 12: frsp({{ Ft.sf = Fb; }}); + 15: fctiwz({{ Ft.sw = (int32_t)trunc(Fb); }}); + } + + format FloatOp { + 0: fcmpu({{ + uint32_t c = makeCRField(Fa, Fb); + Fpscr fpscr = FPSCR; + fpscr.fprf.fpcc = c; + FPSCR = fpscr; + CR = insertCRField(CR, BF, c); + }}); + } + + format FloatRCCheckOp { + 72: fmr({{ Ft = Fb; }}); + 264: fabs({{ + Ft.uq = Fb.uq; + Ft.uq = insertBits(Ft.uq, 63, 0); }}); + 136: fnabs({{ + Ft.uq = Fb.uq; + Ft.uq = insertBits(Ft.uq, 63, 1); }}); + 40: fneg({{ Ft = -Fb; }}); + 8: fcpsgn({{ + Ft.uq = Fb.uq; + Ft.uq = insertBits(Ft.uq, 63, Fa.uq<63:63>); + }}); + 583: mffs({{ Ft.uq = FPSCR; }}); + 134: mtfsfi({{ + FPSCR = insertCRField(FPSCR, BF + (8 * (1 - W)), U_FIELD); + }}); + 711: mtfsf({{ + if (L == 1) { FPSCR = Fb.uq; } + else { + for (int i = 0; i < 8; ++i) { + if (bits(FLM, i) == 1) { + int k = 4 * (i + (8 * (1 - W))); + FPSCR = insertBits(FPSCR, k, k + 3, + bits(Fb.uq, k, k + 3)); + } + } + } + }}); + 70: mtfsb0({{ FPSCR = insertBits(FPSCR, 31 - BT, 0); }}); + 38: mtfsb1({{ FPSCR = insertBits(FPSCR, 31 - BT, 1); }}); + } + } + } +} diff --git a/src/arch/power/isa/formats/basic.isa b/src/arch/power/isa/formats/basic.isa new file mode 100644 index 000000000..adb5e7ef8 --- /dev/null +++ b/src/arch/power/isa/formats/basic.isa @@ -0,0 +1,103 @@ +// -*- mode:c++ -*- + +// Copyright (c) 2009 The University of Edinburgh +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer; +// redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution; +// neither the name of the copyright holders nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Authors: Timothy M. Jones + +// Declarations for execute() methods. +def template BasicExecDeclare {{ + Fault execute(%(CPU_exec_context)s *, Trace::InstRecord *) const; +}}; + +// Basic instruction class declaration template. +def template BasicDeclare {{ + /** + * Static instruction class for "%(mnemonic)s". + */ + class %(class_name)s : public %(base_class)s + { + public: + /// Constructor. + %(class_name)s(ExtMachInst machInst); + %(BasicExecDeclare)s + }; +}}; + +// Basic instruction class constructor template. +def template BasicConstructor {{ + inline %(class_name)s::%(class_name)s(ExtMachInst machInst) : %(base_class)s("%(mnemonic)s", machInst, %(op_class)s) + { + %(constructor)s; + } +}}; + + +// Basic instruction class execute method template. +def template BasicExecute {{ + Fault %(class_name)s::execute(%(CPU_exec_context)s *xc, Trace::InstRecord *traceData) const + { + Fault fault = NoFault; + + %(op_decl)s; + %(op_rd)s; + %(code)s; + + if (fault == NoFault) + { + %(op_wb)s; + } + + return fault; + } +}}; + +// Basic decode template. +def template BasicDecode {{ + return new %(class_name)s(machInst); +}}; + +// Basic decode template, passing mnemonic in as string arg to constructor. +def template BasicDecodeWithMnemonic {{ + return new %(class_name)s("%(mnemonic)s", machInst); +}}; + +// Definitions of execute methods that panic. +def template BasicExecPanic {{ +Fault execute(%(CPU_exec_context)s *, Trace::InstRecord *) const +{ + panic("Execute method called when it shouldn't!"); +} +}}; + +// The most basic instruction format... +def format BasicOp(code, *flags) {{ + iop = InstObjParams(name, Name, 'PowerStaticInst', code, flags) + header_output = BasicDeclare.subst(iop) + decoder_output = BasicConstructor.subst(iop) + decode_block = BasicDecode.subst(iop) + exec_output = BasicExecute.subst(iop) +}}; diff --git a/src/arch/power/isa/formats/branch.isa b/src/arch/power/isa/formats/branch.isa new file mode 100644 index 000000000..d51ed5c25 --- /dev/null +++ b/src/arch/power/isa/formats/branch.isa @@ -0,0 +1,222 @@ +// -*- mode:c++ -*- + +// Copyright (c) 2009 The University of Edinburgh +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer; +// redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution; +// neither the name of the copyright holders nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Authors: Timothy M. Jones + +//////////////////////////////////////////////////////////////////// +// +// Control transfer instructions +// +// From the Power ISA Book I v2.06, page 33, the following rules should +// be obeyed by programmers: +// +// - Use branch instructions where LK == 1 only as subroutine calls. +// - Pair each subroutine call with a bclr instruction with BH == 00 +// that returns from the subroutine. +// - Do not use bclrl as a subroutine call. +// +// Therefore, I've flagged all versions that update the link register (LR) +// as calls, except bclrl (BranchLrCtrCond format) which is flagged as +// a return. + + +let {{ + +# Simple code to update link register (LR). +updateLrCode = 'LR = PC + 4;' + +}}; + +// Instructions that unconditionally branch relative to the current PC. +def format BranchPCRel(br_code, inst_flags = []) {{ + inst_flags += ('IsUncondControl', 'IsDirectControl') + basic_code = br_code + + # The version that does not update LR + (header_output, decoder_output, decode_block, exec_output) = \ + GenAluOp(name, Name, 'BranchPCRel', basic_code, inst_flags, + CheckLkDecode, BasicConstructor) + + # The version that does the update + update_code = basic_code + updateLrCode + update_flags = inst_flags + [ 'IsCall' ] + (header_output_up, decoder_output_up, _, exec_output_up) = \ + GenAluOp(name, Name + 'UpdateLr', 'BranchPCRel', update_code, + update_flags, CheckLkDecode, BasicConstructor) + + # Add the outputs together + header_output += header_output_up + decoder_output += decoder_output_up + exec_output += exec_output_up +}}; + +// Instructions that unconditionally branch to a specific address. +def format BranchNonPCRel(br_code, inst_flags = []) {{ + inst_flags += ('IsUncondControl', 'IsDirectControl') + basic_code = br_code + + # The version that does not update LR + (header_output, decoder_output, decode_block, exec_output) = \ + GenAluOp(name, Name, 'BranchNonPCRel', basic_code, inst_flags, + CheckLkDecode, BasicConstructor) + + # The version that does the update + update_code = basic_code + updateLrCode + update_flags = inst_flags + [ 'IsCall' ] + (header_output_up, decoder_output_up, _, exec_output_up) = \ + GenAluOp(name, Name + 'UpdateLr', 'BranchNonPCRel', update_code, + update_flags, CheckLkDecode, BasicConstructor) + + # Add the outputs together + header_output += header_output_up + decoder_output += decoder_output_up + exec_output += exec_output_up +}}; + +let {{ + +# Check the condition register (CR) allows the branch to be taken. +def GetCondCode(br_code): + cond_code = 'if(condOk(CR)) {\n' + cond_code += ' ' + br_code + '\n' + cond_code += '} else {\n' + cond_code += ' NPC = NPC;\n' + cond_code += '}\n' + return cond_code + +# Check the condition register (CR) and count register (CTR) allow the +# branch to be taken. Also, in certain situations, decrement the count +# register too. This takes place in ctrOk within BranchCond classes. +def GetCtrCondCode(br_code): + cond_code = 'uint32_t ctr = CTR;\n' + cond_code += 'bool ctr_ok = ctrOk(ctr);\n' + cond_code += 'bool cond_ok = condOk(CR);\n' + cond_code += 'if(ctr_ok && cond_ok) {\n' + cond_code += ' ' + br_code + '\n' + cond_code += '} else {\n' + cond_code += ' NPC = NPC;\n' + cond_code += '}\n' + cond_code += 'CTR = ctr;\n' + return cond_code + +}}; + +// Instructions that conditionally branch relative to the current PC based on +// the condition register (CR) and count register (CTR). +def format BranchPCRelCondCtr(br_code, inst_flags = []) {{ + inst_flags += ('IsCondControl', 'IsDirectControl') + basic_code = GetCtrCondCode(br_code) + + # The version that does not update LR + (header_output, decoder_output, decode_block, exec_output) = \ + GenAluOp(name, Name, 'BranchPCRelCond', basic_code, inst_flags, + CheckLkDecode, BasicConstructor) + + # The version that does the update + update_code = basic_code + updateLrCode + update_flags = inst_flags + [ 'IsCall' ] + (header_output_up, decoder_output_up, _, exec_output_up) = \ + GenAluOp(name, Name + 'UpdateLr', 'BranchPCRelCond', update_code, + update_flags, CheckLkDecode, BasicConstructor) + + # Add the outputs together + header_output += header_output_up + decoder_output += decoder_output_up + exec_output += exec_output_up +}}; + +// Instructions that conditionally branch to a specific address based on the +// condition register (CR) and count register (CTR). +def format BranchNonPCRelCondCtr(br_code, inst_flags = []) {{ + inst_flags += ('IsCondControl', 'IsDirectControl') + basic_code = GetCtrCondCode(br_code) + + # The version that does not update LR + (header_output, decoder_output, decode_block, exec_output) = \ + GenAluOp(name, Name, 'BranchNonPCRelCond', basic_code, inst_flags, + CheckLkDecode, BasicConstructor) + + # The version that does the update + update_code = basic_code + updateLrCode + update_flags = inst_flags + [ 'IsCall' ] + (header_output_up, decoder_output_up, _, exec_output_up) = \ + GenAluOp(name, Name + 'UpdateLr', 'BranchNonPCRelCond', update_code, + update_flags, CheckLkDecode, BasicConstructor) + + # Add the outputs together + header_output += header_output_up + decoder_output += decoder_output_up + exec_output += exec_output_up +}}; + +// Instructions that conditionally branch to the address in the link register +// (LR) based on the condition register (CR) and count register (CTR). +def format BranchLrCondCtr(br_code, inst_flags = []) {{ + inst_flags += ('IsCondControl', 'IsIndirectControl', 'IsReturn') + basic_code = GetCtrCondCode(br_code) + + # The version that does not update LR + (header_output, decoder_output, decode_block, exec_output) = \ + GenAluOp(name, Name, 'BranchRegCond', basic_code, inst_flags, + CheckLkDecode, BasicConstructor) + + # The version that does the update + update_code = basic_code + updateLrCode + (header_output_up, decoder_output_up, _, exec_output_up) = \ + GenAluOp(name, Name + 'UpdateLr', 'BranchRegCond', update_code, + inst_flags, CheckLkDecode, BasicConstructor) + + # Add the outputs together + header_output += header_output_up + decoder_output += decoder_output_up + exec_output += exec_output_up +}}; + +// Instructions that conditionally branch to the address in the count register +// (CTR) based on the condition register (CR). +def format BranchCtrCond(br_code, inst_flags = []) {{ + inst_flags += ('IsCondControl', 'IsIndirectControl') + basic_code = GetCondCode(br_code) + + # The version that does not update LR + (header_output, decoder_output, decode_block, exec_output) = \ + GenAluOp(name, Name, 'BranchRegCond', basic_code, inst_flags, + CheckLkDecode, BasicConstructor) + + # The version that does the update + update_code = basic_code + updateLrCode + update_flags = inst_flags + [ 'IsCall' ] + (header_output_up, decoder_output_up, _, exec_output_up) = \ + GenAluOp(name, Name + 'UpdateLr', 'BranchRegCond', update_code, + update_flags, CheckLkDecode, BasicConstructor) + + # Add the outputs together + header_output += header_output_up + decoder_output += decoder_output_up + exec_output += exec_output_up +}}; diff --git a/src/arch/power/isa/formats/condition.isa b/src/arch/power/isa/formats/condition.isa new file mode 100644 index 000000000..12ee7ae7d --- /dev/null +++ b/src/arch/power/isa/formats/condition.isa @@ -0,0 +1,47 @@ +// -*- mode:c++ -*- + +// Copyright (c) 2009 The University of Edinburgh +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer; +// redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution; +// neither the name of the copyright holders nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Authors: Timothy M. Jones + +// Logical instructions that manipulate the condition register +def format CondLogicOp(code, *flags) {{ + iop = InstObjParams(name, Name, 'CondLogicOp', code, flags) + header_output = BasicDeclare.subst(iop) + decoder_output = BasicConstructor.subst(iop) + decode_block = BasicDecode.subst(iop) + exec_output = BasicExecute.subst(iop) +}}; + +// Instructions that condition register fields +def format CondMoveOp(code, *flags) {{ + iop = InstObjParams(name, Name, 'CondMoveOp', code, flags) + header_output = BasicDeclare.subst(iop) + decoder_output = BasicConstructor.subst(iop) + decode_block = BasicDecode.subst(iop) + exec_output = BasicExecute.subst(iop) +}}; diff --git a/src/arch/power/isa/formats/formats.isa b/src/arch/power/isa/formats/formats.isa new file mode 100644 index 000000000..ec2575196 --- /dev/null +++ b/src/arch/power/isa/formats/formats.isa @@ -0,0 +1,60 @@ +// -*- mode:c++ -*- + +// Copyright (c) 2009 The University of Edinburgh +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer; +// redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution; +// neither the name of the copyright holders nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Authors: Timothy M. Jones + +//Templates from this format are used later +//Include the basic format +##include "basic.isa" + +//Include integer instructions +##include "integer.isa" + +//Include condition register instructions +##include "condition.isa" + +//Include utility functions +##include "util.isa" + +//Include the float formats +##include "fp.isa" + +//Include the mem format +##include "mem.isa" + +//Include the branch format +##include "branch.isa" + +//Include the misc format +##include "misc.isa" + +//Include the unimplemented format +##include "unimp.isa" + +//Include the unknown format +##include "unknown.isa" diff --git a/src/arch/power/isa/formats/fp.isa b/src/arch/power/isa/formats/fp.isa new file mode 100644 index 000000000..db917476e --- /dev/null +++ b/src/arch/power/isa/formats/fp.isa @@ -0,0 +1,132 @@ +// -*- mode:c++ -*- + +// Copyright (c) 2009 The University of Edinburgh +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer; +// redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution; +// neither the name of the copyright holders nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Authors: Timothy M. Jones + +//////////////////////////////////////////////////////////////////// +// +// Floating Point operate instructions +// + + +let {{ + + readFPSCRCode = 'Fpscr fpscr = FPSCR;' + + computeCR1Code = ''' + Cr cr = CR; + cr.cr1 = (fpscr.fx << 3) | (fpscr.fex << 2) | + (fpscr.vx << 1) | fpscr.ox; + CR = cr; + ''' + +}}; + +// Primary format for floating point operate instructions: +def format FloatOp(code, inst_flags = []) {{ + iop = InstObjParams(name, Name, 'FloatOp', + {"code": code}, + inst_flags) + header_output = BasicDeclare.subst(iop) + decoder_output = BasicConstructor.subst(iop) + decode_block = BasicDecode.subst(iop) + exec_output = BasicExecute.subst(iop) +}}; + +// Floating point operations that compute the CR1 code if RC is set. No other +// special registers are touched using these operations. +def format FloatRCCheckOp(code, inst_flags = []) {{ + + # Code when Rc is set + code_rc1 = code + readFPSCRCode + computeCR1Code + + # Generate the first class + (header_output, decoder_output, decode_block, exec_output) = \ + GenAluOp(name, Name, 'FloatOp', code, inst_flags, + CheckRcDecode, BasicConstructor) + + # Generate the second class + (header_output_rc1, decoder_output_rc1, _, exec_output_rc1) = \ + GenAluOp(name, Name + 'RcSet', 'FloatOp', code_rc1, inst_flags, + CheckRcDecode, IntRcConstructor) + + # Finally, add to the other outputs + header_output += header_output_rc1 + decoder_output += decoder_output_rc1 + exec_output += exec_output_rc1 +}}; + +// Floating point elementary arithmetic operations. Besides having two +// versions of each instruction for when Rc is set or not, we also have +// to alter lots of special registers depending on the result of the +// operation. The result is always in Ft.sf. +def format FloatArithOp(code, inst_flags = []) {{ + + # Code when Rc is set + code_rc1 = code + readFPSCRCode + computeCR1Code + + # Generate the first class + (header_output, decoder_output, decode_block, exec_output) = \ + GenAluOp(name, Name, 'FloatOp', code, inst_flags, + CheckRcDecode, BasicConstructor) + + # Generate the second class + (header_output_rc1, decoder_output_rc1, _, exec_output_rc1) = \ + GenAluOp(name, Name + 'RcSet', 'FloatOp', code_rc1, inst_flags, + CheckRcDecode, IntRcConstructor) + + # Finally, add to the other outputs + header_output += header_output_rc1 + decoder_output += decoder_output_rc1 + exec_output += exec_output_rc1 +}}; + +// Floating point rounding and conversion operations. Besides having two +// versions of each instruction for when Rc is set or not, we also have +// to alter lots of special registers depending on the result of the +// operation. The result is always in Ft.sf. +def format FloatConvertOp(code, inst_flags = []) {{ + + # Code when Rc is set + code_rc1 = code + readFPSCRCode + computeCR1Code + + # Generate the first class + (header_output, decoder_output, decode_block, exec_output) = \ + GenAluOp(name, Name, 'FloatOp', code, inst_flags, + CheckRcDecode, BasicConstructor) + + # Generate the second class + (header_output_rc1, decoder_output_rc1, _, exec_output_rc1) = \ + GenAluOp(name, Name + 'RcSet', 'FloatOp', code_rc1, inst_flags, + CheckRcDecode, IntRcConstructor) + + # Finally, add to the other outputs + header_output += header_output_rc1 + decoder_output += decoder_output_rc1 + exec_output += exec_output_rc1 +}}; diff --git a/src/arch/power/isa/formats/integer.isa b/src/arch/power/isa/formats/integer.isa new file mode 100644 index 000000000..0766826ec --- /dev/null +++ b/src/arch/power/isa/formats/integer.isa @@ -0,0 +1,369 @@ +// -*- mode:c++ -*- + +// Copyright (c) 2009 The University of Edinburgh +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer; +// redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution; +// neither the name of the copyright holders nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Authors: Timothy M. Jones + +//////////////////////////////////////////////////////////////////// +// +// Integer ALU instructions +// + + +// Instruction class constructor template when Rc is set. +def template IntRcConstructor {{ + inline %(class_name)s::%(class_name)s(ExtMachInst machInst) : %(base_class)s("%(mnemonic)s", machInst, %(op_class)s) + { + %(constructor)s; + rcSet = true; + } +}}; + + +// Instruction class constructor template when OE is set. +def template IntOeConstructor {{ + inline %(class_name)s::%(class_name)s(ExtMachInst machInst) : %(base_class)s("%(mnemonic)s", machInst, %(op_class)s) + { + %(constructor)s; + oeSet = true; + } +}}; + + +// Instruction class constructor template when both Rc and OE are set. +def template IntRcOeConstructor {{ + inline %(class_name)s::%(class_name)s(ExtMachInst machInst) : %(base_class)s("%(mnemonic)s", machInst, %(op_class)s) + { + %(constructor)s; + rcSet = true; + oeSet = true; + } +}}; + + +let {{ + +readXERCode = 'Xer xer = XER;' + +setXERCode = 'XER = xer;' + +computeCR0Code = ''' + Cr cr = CR; + cr.cr0 = makeCRField((int32_t)%(result)s, (int32_t)0, xer.so); + CR = cr; +''' + +computeCACode = ''' + if (findCarry(32, %(result)s, %(inputa)s, %(inputb)s)) { + xer.ca = 1; + } else { + xer.ca = 0; + } +''' + +computeOVCode = ''' + if (findOverflow(32, %(result)s, %(inputa)s, %(inputb)s)) { + xer.ov = 1; + xer.so = 1; + } else { + xer.ov = 0; + } +''' + +computeDivOVCode = ''' + if (divSetOV) { + xer.ov = 1; + xer.so = 1; + } else { + if (findOverflow(32, %(result)s, %(inputa)s, %(inputb)s)) { + xer.ov = 1; + xer.so = 1; + } else { + xer.ov = 0; + } + } +''' + +}}; + + +// A basic integer instruction. +def format IntOp(code, inst_flags = []) {{ + (header_output, decoder_output, decode_block, exec_output) = \ + GenAluOp(name, Name, 'IntOp', code, inst_flags, BasicDecode, + BasicConstructor) +}}; + + +// Integer instructions with immediate (signed or unsigned). +def format IntImmOp(code, inst_flags = []) {{ + (header_output, decoder_output, decode_block, exec_output) = \ + GenAluOp(name, Name, 'IntImmOp', code, inst_flags, BasicDecode, + BasicConstructor) +}}; + + +// Integer instructions with immediate that perform arithmetic. +// These instructions all write to Rt and use an altered form of the +// value in source register Ra, hence the use of src to hold the actual +// value. The control flags include the use of code to compute the +// carry bit or the CR0 code. +def format IntImmArithOp(code, ctrl_flags = [], inst_flags = []) {{ + + # Set up the dictionary and deal with control flags + dict = {'result':'Rt', 'inputa':'src', 'inputb':'imm'} + if ctrl_flags: + code += readXERCode + for val in ctrl_flags: + if val == 'computeCA': + code += computeCACode % dict + setXERCode + elif val == 'computeCR0': + code += computeCR0Code % dict + + # Generate the class + (header_output, decoder_output, decode_block, exec_output) = \ + GenAluOp(name, Name, 'IntImmOp', code, inst_flags, BasicDecode, + BasicConstructor) +}}; + + +// Integer instructions with immediate that perform arithmetic but use +// the value 0 when Ra == 0. We generate two versions of each instruction +// corresponding to these two different scenarios. The correct version is +// determined at decode (see the CheckRaDecode template). +def format IntImmArithCheckRaOp(code, code_ra0, inst_flags = []) {{ + + # First the version where Ra is non-zero + (header_output, decoder_output, decode_block, exec_output) = \ + GenAluOp(name, Name, 'IntImmOp', code, inst_flags, + CheckRaDecode, BasicConstructor) + + # Now another version where Ra == 0 + (header_output_ra0, decoder_output_ra0, _, exec_output_ra0) = \ + GenAluOp(name, Name + 'RaZero', 'IntImmOp', code_ra0, inst_flags, + CheckRaDecode, BasicConstructor) + + # Finally, add to the other outputs + header_output += header_output_ra0 + decoder_output += decoder_output_ra0 + exec_output += exec_output_ra0 +}}; + + +// Integer instructions with immediate that perform logic operations. +// All instructions write to Ra and use Rs as a source register. Some +// also compute the CR0 code too. +def format IntImmLogicOp(code, computeCR0 = 0, inst_flags = []) {{ + + # Set up the dictionary and deal with computing CR0 + dict = {'result':'Ra'} + if computeCR0: + code += readXERCode + computeCR0Code % dict + + # Generate the class + (header_output, decoder_output, decode_block, exec_output) = \ + GenAluOp(name, Name, 'IntImmOp', code, inst_flags, BasicDecode, + BasicConstructor) +}}; + + +// Integer instructions that perform logic operations. The result is +// always written into Ra. All instructions have 2 versions depending on +// whether the Rc bit is set to compute the CR0 code. This is determined +// at decode as before. +def format IntLogicOp(code, inst_flags = []) {{ + dict = {'result':'Ra'} + + # Code when Rc is set + code_rc1 = code + readXERCode + computeCR0Code % dict + + # Generate the first class + (header_output, decoder_output, decode_block, exec_output) = \ + GenAluOp(name, Name, 'IntOp', code, inst_flags, + CheckRcDecode, BasicConstructor) + + # Generate the second class + (header_output_rc1, decoder_output_rc1, _, exec_output_rc1) = \ + GenAluOp(name, Name + 'RcSet', 'IntOp', code_rc1, inst_flags, + CheckRcDecode, IntRcConstructor) + + # Finally, add to the other outputs + header_output += header_output_rc1 + decoder_output += decoder_output_rc1 + exec_output += exec_output_rc1 +}}; + + +// Integer instructions with a shift amount. As above, except inheriting +// from the IntShiftOp class. +def format IntShiftOp(code, inst_flags = []) {{ + dict = {'result':'Ra'} + + # Code when Rc is set + code_rc1 = code + readXERCode + computeCR0Code % dict + + # Generate the first class + (header_output, decoder_output, decode_block, exec_output) = \ + GenAluOp(name, Name, 'IntShiftOp', code, inst_flags, + CheckRcDecode, BasicConstructor) + + # Generate the second class + (header_output_rc1, decoder_output_rc1, _, exec_output_rc1) = \ + GenAluOp(name, Name + 'RcSet', 'IntShiftOp', code_rc1, inst_flags, + CheckRcDecode, IntRcConstructor) + + # Finally, add to the other outputs + header_output += header_output_rc1 + decoder_output += decoder_output_rc1 + exec_output += exec_output_rc1 +}}; + + +// Instructions in this format are all reduced to the form Rt = src1 + src2, +// therefore we just give src1 and src2 definitions. In working out the +// template we first put in the definitions of the variables and then +// the code for the addition. We also deal with computing the carry flag +// if required. +// +// We generate 4 versions of each instruction. This correspond to the +// different combinations of having the OE bit set or unset (which controls +// whether the overflow flag is computed) and the Rc bit set or unset too +// (which controls whether the CR0 code is computed). +def format IntSumOp(src1, src2, ca = {{ 0 }}, computeCA = 0, + inst_flags = []) {{ + + # The result is always in Rt, but the source values vary + dict = {'result':'Rt', 'inputa':'src1', 'inputb':'src2'} + + # Add code to set up variables and do the sum + code = 'uint32_t src1 = ' + src1 + ';\n' + code += 'uint32_t src2 = ' + src2 + ';\n' + code += 'uint32_t ca = ' + ca + ';\n' + code += 'Rt = src1 + src2 + ca;\n' + + # Add code for calculating the carry, if needed + if computeCA: + code += computeCACode % dict + setXERCode + + # Setup the 4 code versions and add code to access XER if necessary + code_rc1 = readXERCode + code + code_oe1 = readXERCode + code + computeOVCode % dict + setXERCode + code_rc1_oe1 = readXERCode + code + computeOVCode % dict + setXERCode + if (computeCA or ca == 'xer.ca'): + code = readXERCode + code + code_rc1 += computeCR0Code % dict + code_rc1_oe1 += computeCR0Code % dict + + # Generate the classes + (header_output, decoder_output, decode_block, exec_output) = \ + GenAluOp(name, Name, 'IntOp', code, inst_flags, + CheckRcOeDecode, BasicConstructor) + (header_output_rc1, decoder_output_rc1, _, exec_output_rc1) = \ + GenAluOp(name, Name + 'RcSet', 'IntOp', code_rc1, inst_flags, + CheckRcOeDecode, IntRcConstructor) + (header_output_oe1, decoder_output_oe1, _, exec_output_oe1) = \ + GenAluOp(name, Name + 'OeSet', 'IntOp', code_oe1, inst_flags, + CheckRcOeDecode, IntOeConstructor) + (header_output_rc1_oe1, decoder_output_rc1_oe1, _, exec_output_rc1_oe1) = \ + GenAluOp(name, Name + 'RcSetOeSet', 'IntOp', code_rc1_oe1, + inst_flags, CheckRcOeDecode, IntRcOeConstructor) + + # Finally, add to the other outputs + header_output += \ + header_output_rc1 + header_output_oe1 + header_output_rc1_oe1 + decoder_output += \ + decoder_output_rc1 + decoder_output_oe1 + decoder_output_rc1_oe1 + exec_output += \ + exec_output_rc1 + exec_output_oe1 + exec_output_rc1_oe1 + +}}; + + +// Instructions that use source registers Ra and Rb, with the result +// placed into Rt. Basically multiply and divide instructions. The +// carry bit is never set, but overflow can be calculated. Division +// explicitly sets the overflow bit in certain situations and this is +// dealt with using the 'divSetOV' boolean in decoder.isa. We generate +// two versions of each instruction to deal with the Rc bit. +def format IntArithOp(code, computeOV = 0, inst_flags = []) {{ + + # The result is always in Rt, but the source values vary + dict = {'result':'Rt', 'inputa':'src1', 'inputb':'src2'} + + # Deal with setting the overflow flag + if computeOV: + code = 'bool divSetOV = false;\n' + code + code += computeDivOVCode % dict + setXERCode + + # Setup the 2 code versions and add code to access XER if necessary + code_rc1 = readXERCode + code + computeCR0Code % dict + if computeOV: + code = readXERCode + code + + # Generate the classes + (header_output, decoder_output, decode_block, exec_output) = \ + GenAluOp(name, Name, 'IntOp', code, inst_flags, + CheckRcDecode, BasicConstructor) + + # Generate the second class + (header_output_rc1, decoder_output_rc1, _, exec_output_rc1) = \ + GenAluOp(name, Name + 'RcSet', 'IntOp', code_rc1, inst_flags, + CheckRcDecode, IntRcConstructor) + + # Finally, add to the other outputs + header_output += header_output_rc1 + decoder_output += decoder_output_rc1 + exec_output += exec_output_rc1 +}}; + + +// A special format for rotate instructions which use certain fields +// from the instruction's binary encoding. We need two versions for each +// instruction to deal with the Rc bit. +def format IntRotateOp(code, inst_flags = []) {{ + + # The result is always in Ra + dict = {'result':'Ra'} + + # Setup the code for when Rc is set + code_rc1 = readXERCode + code + computeCR0Code % dict + + # Generate the first class + (header_output, decoder_output, decode_block, exec_output) = \ + GenAluOp(name, Name, 'IntRotateOp', code, inst_flags, + CheckRcDecode, BasicConstructor) + + # Generate the second class + (header_output_rc1, decoder_output_rc1, _, exec_output_rc1) = \ + GenAluOp(name, Name + 'RcSet', 'IntRotateOp', code_rc1, inst_flags, + CheckRcDecode, IntRcConstructor) + + # Finally, add to the other outputs + header_output += header_output_rc1 + decoder_output += decoder_output_rc1 + exec_output += exec_output_rc1 +}}; diff --git a/src/arch/power/isa/formats/mem.isa b/src/arch/power/isa/formats/mem.isa new file mode 100644 index 000000000..1be49c2f7 --- /dev/null +++ b/src/arch/power/isa/formats/mem.isa @@ -0,0 +1,351 @@ +// -*- mode:c++ -*- + +// Copyright (c) 2009 The University of Edinburgh +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer; +// redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution; +// neither the name of the copyright holders nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Authors: Timothy M. Jones + +//////////////////////////////////////////////////////////////////// +// +// Memory-format instructions +// + +def template LoadStoreDeclare {{ + /** + * Static instruction class for "%(mnemonic)s". + */ + class %(class_name)s : public %(base_class)s + { + public: + + /// Constructor. + %(class_name)s(ExtMachInst machInst); + + %(BasicExecDeclare)s + + %(InitiateAccDeclare)s + + %(CompleteAccDeclare)s + }; +}}; + + +def template InitiateAccDeclare {{ + Fault initiateAcc(%(CPU_exec_context)s *, Trace::InstRecord *) const; +}}; + + +def template CompleteAccDeclare {{ + Fault completeAcc(PacketPtr, %(CPU_exec_context)s *, Trace::InstRecord *) const; +}}; + + +def template LoadStoreConstructor {{ + inline %(class_name)s::%(class_name)s(ExtMachInst machInst) + : %(base_class)s("%(mnemonic)s", machInst, %(op_class)s) + { + %(constructor)s; + } +}}; + + +def template LoadExecute {{ + Fault %(class_name)s::execute(%(CPU_exec_context)s *xc, + Trace::InstRecord *traceData) const + { + Addr EA; + Fault fault = NoFault; + + %(op_decl)s; + %(op_rd)s; + %(ea_code)s; + + if (fault == NoFault) { + fault = xc->read(EA, (uint%(mem_acc_size)d_t&)Mem, memAccessFlags); + %(memacc_code)s; + } + + if (fault == NoFault) { + %(op_wb)s; + } + + return fault; + } +}}; + + +def template LoadInitiateAcc {{ + Fault %(class_name)s::initiateAcc(%(CPU_exec_context)s *xc, + Trace::InstRecord *traceData) const + { + Addr EA; + Fault fault = NoFault; + + %(op_src_decl)s; + %(op_rd)s; + %(ea_code)s; + + if (fault == NoFault) { + fault = xc->read(EA, (uint%(mem_acc_size)d_t &)Mem, memAccessFlags); + xc->setEA(EA); + } + + return fault; + } +}}; + + +def template LoadCompleteAcc {{ + Fault %(class_name)s::completeAcc(PacketPtr pkt, + %(CPU_exec_context)s *xc, + Trace::InstRecord *traceData) const + { + Addr EA; + Fault fault = NoFault; + uint%(mem_acc_size)d_t val; + + %(op_decl)s; + %(op_rd)s; + + EA = xc->getEA(); + + val = pkt->get<uint%(mem_acc_size)d_t>(); + *((uint%(mem_acc_size)d_t*)&Mem) = val; + + if (fault == NoFault) { + %(memacc_code)s; + } + + if (fault == NoFault) { + %(op_wb)s; + } + + return fault; + } +}}; + + +def template StoreExecute {{ + Fault %(class_name)s::execute(%(CPU_exec_context)s *xc, + Trace::InstRecord *traceData) const + { + Addr EA; + Fault fault = NoFault; + + %(op_decl)s; + %(op_rd)s; + %(ea_code)s; + + if (fault == NoFault) { + %(memacc_code)s; + } + + if (fault == NoFault) { + fault = xc->write((uint%(mem_acc_size)d_t&)Mem, EA, + memAccessFlags, NULL); + if (traceData) { traceData->setData(Mem); } + } + + if (fault == NoFault) { + %(op_wb)s; + } + + return fault; + } +}}; + + +def template StoreInitiateAcc {{ + Fault %(class_name)s::initiateAcc(%(CPU_exec_context)s *xc, + Trace::InstRecord *traceData) const + { + Addr EA; + Fault fault = NoFault; + + %(op_decl)s; + %(op_rd)s; + %(ea_code)s; + + if (fault == NoFault) { + %(memacc_code)s; + } + + if (fault == NoFault) { + fault = xc->write((uint%(mem_acc_size)d_t&)Mem, EA, + memAccessFlags, NULL); + if (traceData) { traceData->setData(Mem); } + } + + // Need to write back any potential address register update + if (fault == NoFault) { + %(op_wb)s; + } + + return fault; + } +}}; + + +def template StoreCompleteAcc {{ + Fault %(class_name)s::completeAcc(PacketPtr pkt, + %(CPU_exec_context)s *xc, + Trace::InstRecord *traceData) const + { + Fault fault = NoFault; + + %(op_dest_decl)s; + + if (fault == NoFault) { + %(op_wb)s; + } + + return fault; + } +}}; + + +// The generic memory operation generator. This is called when two versions +// of an instruction are needed - when Ra == 0 and otherwise. This is so +// that instructions can use the value 0 when Ra == 0 but avoid having a +// dependence on Ra. +let {{ + +def GenMemOp(name, Name, memacc_code, ea_code, ea_code_ra0, base, + load_or_store, mem_flags = [], inst_flags = []): + + # First the version where Ra is non-zero + (header_output, decoder_output, decode_block, exec_output) = \ + LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags, + base_class = base, + decode_template = CheckRaDecode, + exec_template_base = load_or_store) + + # Now another version where Ra == 0 + (header_output_ra0, decoder_output_ra0, _, exec_output_ra0) = \ + LoadStoreBase(name, Name + 'RaZero', ea_code_ra0, memacc_code, + mem_flags, inst_flags, + base_class = base, + exec_template_base = load_or_store) + + # Finally, add to the other outputs + header_output += header_output_ra0 + decoder_output += decoder_output_ra0 + exec_output += exec_output_ra0 + return (header_output, decoder_output, decode_block, exec_output) + +}}; + + +def format LoadIndexOp(memacc_code, ea_code = {{ EA = Ra + Rb; }}, + ea_code_ra0 = {{ EA = Rb; }}, + mem_flags = [], inst_flags = []) {{ + (header_output, decoder_output, decode_block, exec_output) = \ + GenMemOp(name, Name, memacc_code, ea_code, ea_code_ra0, + 'MemOp', 'Load', mem_flags, inst_flags) +}}; + + +def format StoreIndexOp(memacc_code, ea_code = {{ EA = Ra + Rb; }}, + ea_code_ra0 = {{ EA = Rb; }}, + mem_flags = [], inst_flags = []) {{ + (header_output, decoder_output, decode_block, exec_output) = \ + GenMemOp(name, Name, memacc_code, ea_code, ea_code_ra0, + 'MemOp', 'Store', mem_flags, inst_flags) +}}; + + +def format LoadIndexUpdateOp(memacc_code, ea_code = {{ EA = Ra + Rb; }}, + mem_flags = [], inst_flags = []) {{ + + # Add in the update code + memacc_code += 'Ra = EA;' + + # Generate the class + (header_output, decoder_output, decode_block, exec_output) = \ + LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags, + base_class = 'MemOp', + exec_template_base = 'Load') +}}; + + +def format StoreIndexUpdateOp(memacc_code, ea_code = {{ EA = Ra + Rb; }}, + mem_flags = [], inst_flags = []) {{ + + # Add in the update code + memacc_code += 'Ra = EA;' + + # Generate the class + (header_output, decoder_output, decode_block, exec_output) = \ + LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags, + base_class = 'MemOp', + exec_template_base = 'Store') +}}; + + +def format LoadDispOp(memacc_code, ea_code = {{ EA = Ra + disp; }}, + ea_code_ra0 = {{ EA = disp; }}, + mem_flags = [], inst_flags = []) {{ + (header_output, decoder_output, decode_block, exec_output) = \ + GenMemOp(name, Name, memacc_code, ea_code, ea_code_ra0, + 'MemDispOp', 'Load', mem_flags, inst_flags) +}}; + + +def format StoreDispOp(memacc_code, ea_code = {{ EA = Ra + disp; }}, + ea_code_ra0 = {{ EA = disp; }}, + mem_flags = [], inst_flags = []) {{ + (header_output, decoder_output, decode_block, exec_output) = \ + GenMemOp(name, Name, memacc_code, ea_code, ea_code_ra0, + 'MemDispOp', 'Store', mem_flags, inst_flags) +}}; + + +def format LoadDispUpdateOp(memacc_code, ea_code = {{ EA = Ra + disp; }}, + mem_flags = [], inst_flags = []) {{ + + # Add in the update code + memacc_code += 'Ra = EA;' + + # Generate the class + (header_output, decoder_output, decode_block, exec_output) = \ + LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags, + base_class = 'MemDispOp', + exec_template_base = 'Load') +}}; + + +def format StoreDispUpdateOp(memacc_code, ea_code = {{ EA = Ra + disp; }}, + mem_flags = [], inst_flags = []) {{ + + # Add in the update code + memacc_code += 'Ra = EA;' + + # Generate the class + (header_output, decoder_output, decode_block, exec_output) = \ + LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags, + base_class = 'MemDispOp', + exec_template_base = 'Store') +}}; diff --git a/src/arch/power/isa/formats/misc.isa b/src/arch/power/isa/formats/misc.isa new file mode 100644 index 000000000..93536aa18 --- /dev/null +++ b/src/arch/power/isa/formats/misc.isa @@ -0,0 +1,61 @@ +// -*- mode:c++ -*- + +// Copyright (c) 2009 The University of Edinburgh +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer; +// redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution; +// neither the name of the copyright holders nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Authors: Timothy M. Jones + +//////////////////////////////////////////////////////////////////// +// +// Misc instructions +// + +def template MiscOpExecute {{ + Fault %(class_name)s::execute(%(CPU_exec_context)s *xc, Trace::InstRecord *traceData) const + { + Fault fault = NoFault; + %(op_decl)s; + %(op_rd)s; + + %(code)s; + if (fault == NoFault) + { + %(op_wb)s; + } + + return fault; + } +}}; + +def format MiscOp(code, opt_flags = []) {{ + iop = InstObjParams(name, Name, 'IntOp', + {"code": code}, + opt_flags) + header_output = BasicDeclare.subst(iop) + decoder_output = BasicConstructor.subst(iop) + decode_block = BasicDecode.subst(iop) + exec_output = MiscOpExecute.subst(iop) +}}; diff --git a/src/arch/power/isa/formats/unimp.isa b/src/arch/power/isa/formats/unimp.isa new file mode 100644 index 000000000..60a7c469d --- /dev/null +++ b/src/arch/power/isa/formats/unimp.isa @@ -0,0 +1,146 @@ +// -*- mode:c++ -*- + +// Copyright (c) 2007-2008 The Florida State University +// Copyright (c) 2009 The University of Edinburgh +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer; +// redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution; +// neither the name of the copyright holders nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Authors: Stephen Hines +// Timothy M. Jones + +//////////////////////////////////////////////////////////////////// +// +// Unimplemented instructions +// + +output header {{ + /** + * Static instruction class for unimplemented instructions that + * cause simulator termination. Note that these are recognized + * (legal) instructions that the simulator does not support; the + * 'Unknown' class is used for unrecognized/illegal instructions. + * This is a leaf class. + */ + class FailUnimplemented : public PowerStaticInst + { + public: + /// Constructor + FailUnimplemented(const char *_mnemonic, MachInst _machInst) + : PowerStaticInst(_mnemonic, _machInst, No_OpClass) + { + // don't call execute() (which panics) if we're on a + // speculative path + flags[IsNonSpeculative] = true; + } + + %(BasicExecDeclare)s + + std::string + generateDisassembly(Addr pc, const SymbolTable *symtab) const; + }; + + /** + * Base class for unimplemented instructions that cause a warning + * to be printed (but do not terminate simulation). This + * implementation is a little screwy in that it will print a + * warning for each instance of a particular unimplemented machine + * instruction, not just for each unimplemented opcode. Should + * probably make the 'warned' flag a static member of the derived + * class. + */ + class WarnUnimplemented : public PowerStaticInst + { + private: + /// Have we warned on this instruction yet? + mutable bool warned; + + public: + /// Constructor + WarnUnimplemented(const char *_mnemonic, MachInst _machInst) + : PowerStaticInst(_mnemonic, _machInst, No_OpClass), warned(false) + { + // don't call execute() (which panics) if we're on a + // speculative path + flags[IsNonSpeculative] = true; + } + + %(BasicExecDeclare)s + + std::string + generateDisassembly(Addr pc, const SymbolTable *symtab) const; + }; +}}; + +output decoder {{ + std::string + FailUnimplemented::generateDisassembly(Addr pc, + const SymbolTable *symtab) const + { + return csprintf("%-10s (unimplemented)", mnemonic); + } + + std::string + WarnUnimplemented::generateDisassembly(Addr pc, + const SymbolTable *symtab) const + { + return csprintf("%-10s (unimplemented)", mnemonic); + } +}}; + +output exec {{ + Fault + FailUnimplemented::execute(%(CPU_exec_context)s *xc, + Trace::InstRecord *traceData) const + { + panic("attempt to execute unimplemented instruction '%s' " + "(inst 0x%08x, opcode 0x%x, binary:%s)", mnemonic, machInst, OPCODE, + inst2string(machInst)); + return new UnimplementedOpcodeFault; + } + + Fault + WarnUnimplemented::execute(%(CPU_exec_context)s *xc, + Trace::InstRecord *traceData) const + { + if (!warned) { + warn("\tinstruction '%s' unimplemented\n", mnemonic); + warned = true; + } + + return NoFault; + } +}}; + + +def format FailUnimpl() {{ + iop = InstObjParams(name, 'FailUnimplemented') + decode_block = BasicDecodeWithMnemonic.subst(iop) +}}; + +def format WarnUnimpl() {{ + iop = InstObjParams(name, 'WarnUnimplemented') + decode_block = BasicDecodeWithMnemonic.subst(iop) +}}; + diff --git a/src/arch/power/isa/formats/unknown.isa b/src/arch/power/isa/formats/unknown.isa new file mode 100644 index 000000000..06e6ece26 --- /dev/null +++ b/src/arch/power/isa/formats/unknown.isa @@ -0,0 +1,87 @@ +// -*- mode:c++ -*- + +// Copyright (c) 2007-2008 The Florida State University +// Copyright (c) 2009 The University of Edinburgh +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer; +// redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution; +// neither the name of the copyright holders nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Authors: Stephen Hines +// Timothy M. Jones + +//////////////////////////////////////////////////////////////////// +// +// Unknown instructions +// + +output header {{ + /** + * Static instruction class for unknown (illegal) instructions. + * These cause simulator termination if they are executed in a + * non-speculative mode. This is a leaf class. + */ + class Unknown : public PowerStaticInst + { + public: + /// Constructor + Unknown(ExtMachInst _machInst) + : PowerStaticInst("unknown", _machInst, No_OpClass) + { + // don't call execute() (which panics) if we're on a + // speculative path + flags[IsNonSpeculative] = true; + } + + %(BasicExecDeclare)s + + std::string + generateDisassembly(Addr pc, const SymbolTable *symtab) const; + }; +}}; + +output decoder {{ + std::string + Unknown::generateDisassembly(Addr pc, const SymbolTable *symtab) const + { + return csprintf("%-10s (inst 0x%x, opcode 0x%x, binary:%s)", + "unknown", machInst, OPCODE, inst2string(machInst)); + } +}}; + +output exec {{ + Fault + Unknown::execute(%(CPU_exec_context)s *xc, + Trace::InstRecord *traceData) const + { + panic("attempt to execute unknown instruction at %#x" + "(inst 0x%08x, opcode 0x%x, binary: %s)", + xc->readPC(), machInst, OPCODE, inst2string(machInst)); + return new UnimplementedOpcodeFault; + } +}}; + +def format Unknown() {{ + decode_block = 'return new Unknown(machInst);\n' +}}; + diff --git a/src/arch/power/isa/formats/util.isa b/src/arch/power/isa/formats/util.isa new file mode 100644 index 000000000..ab1e530b2 --- /dev/null +++ b/src/arch/power/isa/formats/util.isa @@ -0,0 +1,174 @@ +// -*- mode:c++ -*- + +// Copyright (c) 2003-2005 The Regents of The University of Michigan +// Copyright (c) 2009 The University of Edinburgh +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer; +// redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution; +// neither the name of the copyright holders nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Authors: Steve Reinhardt +// Korey Sewell +// Timothy M. Jones + +// Some instructions ignore the contents of Ra if Ra == 0, +// so check for this. +def template CheckRaDecode {{ + { + if (RA == 0) { + return new %(class_name)sRaZero(machInst); + } else { + return new %(class_name)s(machInst); + } + } +}}; + + +// Some instructions have extra behaviour if Rc is set. +def template CheckRcDecode {{ + { + if (RC31 == 0) { + return new %(class_name)s(machInst); + } else { + return new %(class_name)sRcSet(machInst); + } + } +}}; + + +// Some instructions have extra behaviour if Rc and OE are set. +def template CheckRcOeDecode {{ + { + if (RC31 == 0) { + if (OE == 0) { + return new %(class_name)s(machInst); + } else { + return new %(class_name)sOeSet(machInst); + } + } else { + if (OE == 0) { + return new %(class_name)sRcSet(machInst); + } else { + return new %(class_name)sRcSetOeSet(machInst); + } + } + } +}}; + +// Branch instructions always have two versions, one which sets the link +// register (LR). +def template CheckLkDecode {{ + { + if (LK == 0) { + return new %(class_name)s(machInst); + } else { + return new %(class_name)sUpdateLr(machInst); + } + } +}}; + + +let {{ + +def LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags, + base_class = 'MemOp', + decode_template = BasicDecode, exec_template_base = ''): + # Make sure flags are in lists (convert to lists if not). + mem_flags = makeList(mem_flags) + inst_flags = makeList(inst_flags) + + # add hook to get effective addresses into execution trace output. + ea_code += '\nif (traceData) { traceData->setAddr(EA); }\n' + + # Generate InstObjParams for the memory access. + iop = InstObjParams(name, Name, base_class, + {'ea_code': ea_code, + 'memacc_code': memacc_code}, + inst_flags) + + if mem_flags: + s = '\n\tmemAccessFlags = ' + string.join(mem_flags, '|') + ';' + iop.constructor += s + + fullExecTemplate = eval(exec_template_base + 'Execute') + initiateAccTemplate = eval(exec_template_base + 'InitiateAcc') + completeAccTemplate = eval(exec_template_base + 'CompleteAcc') + + # (header_output, decoder_output, decode_block, exec_output) + return (LoadStoreDeclare.subst(iop), + LoadStoreConstructor.subst(iop), + decode_template.subst(iop), + fullExecTemplate.subst(iop) + + initiateAccTemplate.subst(iop) + + completeAccTemplate.subst(iop)) + + +# The generic ALU instruction generator. Integer and fp formats calls this +# to generate the different output sections. +def GenAluOp(name, Name, base_class, code, inst_flags, decode_template, + constructor_template): + iop = InstObjParams(name, Name, base_class, + {"code": code}, + inst_flags) + header_output = BasicDeclare.subst(iop) + exec_output = BasicExecute.subst(iop) + + # We use constructors dependent on the Rc and OE bits being set + decoder_output = constructor_template.subst(iop) + + # The decode block defines which version to use + decode_block = decode_template.subst(iop) + return (header_output, decoder_output, decode_block, exec_output) + +}}; + + +output header {{ + std::string + inst2string(MachInst machInst); +}}; + +output decoder {{ + + std::string + inst2string(MachInst machInst) + { + std::string str = ""; + uint32_t mask = 0x80000000; + + for(int i=0; i < 32; i++) { + if ((machInst & mask) == 0) { + str += "0"; + } else { + str += "1"; + } + + mask = mask >> 1; + } + + return str; + } + +}}; + + diff --git a/src/arch/power/isa/includes.isa b/src/arch/power/isa/includes.isa new file mode 100644 index 000000000..47e8c1411 --- /dev/null +++ b/src/arch/power/isa/includes.isa @@ -0,0 +1,92 @@ +// -*- mode:c++ -*- + +// Copyright (c) 2009 The University of Edinburgh +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer; +// redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution; +// neither the name of the copyright holders nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Authors: Timothy M. Jones + +//////////////////////////////////////////////////////////////////// +// +// Output include file directives. +// + +output header {{ +#include <sstream> +#include <iostream> +#include <iomanip> + +#include "arch/power/insts/branch.hh" +#include "arch/power/insts/mem.hh" +#include "arch/power/insts/integer.hh" +#include "arch/power/insts/floating.hh" +#include "arch/power/insts/condition.hh" +#include "arch/power/insts/misc.hh" +#include "arch/power/insts/static_inst.hh" +#include "arch/power/isa_traits.hh" +#include "cpu/static_inst.hh" +#include "mem/packet.hh" + +using namespace PowerISA; +}}; + +output decoder {{ +#include <cmath> +#if defined(linux) +#include <fenv.h> +#endif + +#include "arch/power/faults.hh" +#include "arch/power/isa_traits.hh" +#include "arch/power/utility.hh" +#include "base/cprintf.hh" +#include "base/loader/symtab.hh" +#include "cpu/thread_context.hh" + +using namespace PowerISA; +using std::isnan; +}}; + +output exec {{ +#include "arch/power/faults.hh" +#include "arch/power/isa_traits.hh" +#include "arch/power/utility.hh" + +#include <cmath> +#if defined(linux) +#include <fenv.h> +#endif + +#include "base/condcodes.hh" +#include "cpu/base.hh" +#include "cpu/exetrace.hh" +#include "mem/packet.hh" +#include "mem/packet_access.hh" +#include "sim/sim_exit.hh" + +using namespace PowerISA; +using std::isnan; +}}; + diff --git a/src/arch/power/isa/main.isa b/src/arch/power/isa/main.isa new file mode 100644 index 000000000..cce7e39ee --- /dev/null +++ b/src/arch/power/isa/main.isa @@ -0,0 +1,57 @@ +// -*- mode:c++ -*- + +// Copyright (c) 2009 The University of Edinburgh +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer; +// redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution; +// neither the name of the copyright holders nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Authors: Timothy M. Jones + +//////////////////////////////////////////////////////////////////// +// +// Power ISA description file. +// +//////////////////////////////////////////////////////////////////// + +//Include the C++ include directives +##include "includes.isa" + +//////////////////////////////////////////////////////////////////// +// +// Namespace statement. Everything below this line will be in the +// PowerISAInst namespace. +// +namespace PowerISA; + +//Include the bitfield definitions +##include "bitfields.isa" + +//Include the operand_types and operand definitions +##include "operands.isa" + +//Include the definitions for the instruction formats +##include "formats/formats.isa" + +//Include the decoder definition +##include "decoder.isa" diff --git a/src/arch/power/isa/operands.isa b/src/arch/power/isa/operands.isa new file mode 100644 index 000000000..fc6c32685 --- /dev/null +++ b/src/arch/power/isa/operands.isa @@ -0,0 +1,81 @@ +// -*- mode:c++ -*- + +// Copyright (c) 2009 The University of Edinburgh +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer; +// redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution; +// neither the name of the copyright holders nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Authors: Timothy M. Jones + +def operand_types {{ + 'sb' : ('signed int', 8), + 'ub' : ('unsigned int', 8), + 'sh' : ('signed int', 16), + 'uh' : ('unsigned int', 16), + 'sw' : ('signed int', 32), + 'uw' : ('unsigned int', 32), + 'sq' : ('signed int', 64), + 'uq' : ('unsigned int', 64), + 'sf' : ('float', 32), + 'df' : ('float', 64) +}}; + +def operands {{ + # General Purpose Integer Reg Operands + 'Ra': ('IntReg', 'uw', 'RA', 'IsInteger', 1), + 'Rb': ('IntReg', 'uw', 'RB', 'IsInteger', 2), + 'Rs': ('IntReg', 'uw', 'RS', 'IsInteger', 3), + 'Rt': ('IntReg', 'uw', 'RT', 'IsInteger', 4), + + # General Purpose Floating Point Reg Operands + 'Fa': ('FloatReg', 'df', 'FRA', 'IsFloating', 1), + 'Fb': ('FloatReg', 'df', 'FRB', 'IsFloating', 2), + 'Fc': ('FloatReg', 'df', 'FRC', 'IsFloating', 3), + 'Fs': ('FloatReg', 'df', 'FRS', 'IsFloating', 4), + 'Ft': ('FloatReg', 'df', 'FRT', 'IsFloating', 5), + + # Memory Operand + 'Mem': ('Mem', 'uw', None, ('IsMemRef', 'IsLoad', 'IsStore'), 8), + + # Program counter and next + 'PC': ('PC', 'uw', None, (None, None, 'IsControl'), 9), + 'NPC': ('NPC', 'uw', None, (None, None, 'IsControl'), 9), + + # Control registers + 'CR': ('IntReg', 'uw', 'INTREG_CR', 'IsInteger', 9), + 'LR': ('IntReg', 'uw', 'INTREG_LR', 'IsInteger', 9), + 'CTR': ('IntReg', 'uw', 'INTREG_CTR', 'IsInteger', 9), + 'XER': ('IntReg', 'uw', 'INTREG_XER', 'IsInteger', 9), + + # Setting as IntReg so things are stored as an integer, not double + 'FPSCR': ('IntReg', 'uw', 'INTREG_FPSCR', 'IsFloating', 9), + + # Registers for linked loads and stores + 'Rsv': ('IntReg', 'uw', 'INTREG_RSV', 'IsInteger', 9), + 'RsvLen': ('IntReg', 'uw', 'INTREG_RSV_LEN', 'IsInteger', 9), + 'RsvAddr': ('IntReg', 'uw', 'INTREG_RSV_ADDR', 'IsInteger', 9), + + # Hack for non-full-system syscall emulation + 'R0': ('IntReg', 'uw', '0', None, 1), +}}; diff --git a/src/arch/isa_specific.hh b/src/arch/power/isa_traits.hh index de070bbf9..886c2cb0b 100644 --- a/src/arch/isa_specific.hh +++ b/src/arch/power/isa_traits.hh @@ -1,5 +1,7 @@ /* * Copyright (c) 2003-2005 The Regents of The University of Michigan + * Copyright (c) 2007-2008 The Florida State University + * Copyright (c) 2009 The University of Edinburgh * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -25,46 +27,49 @@ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * - * Authors: Gabe Black + * Authors: Timothy M. Jones + * Gabe Black + * Stephen Hines */ -#ifndef __ARCH_ISA_SPECIFIC_HH__ -#define __ARCH_ISA_SPECIFIC_HH__ +#ifndef __ARCH_POWER_ISA_TRAITS_HH__ +#define __ARCH_POWER_ISA_TRAITS_HH__ -//This file provides a mechanism for other source code to bring in -//files from the ISA being compiled in. +#include "arch/power/types.hh" +#include "base/types.hh" -//These are constants so you can selectively compile code based on the isa. -//To use them, do something like: -// -//#if THE_ISA == YOUR_FAVORITE_ISA -// conditional_code -//#endif -// -//Note that this is how this file sets up the TheISA macro. +namespace BigEndianGuest {}; -//These macros have numerical values because otherwise the preprocessor -//would treat them as 0 in comparisons. -#define ALPHA_ISA 21064 -#define SPARC_ISA 42 -#define MIPS_ISA 34000 -#define X86_ISA 8086 -#define ARM_ISA 6 +class StaticInstPtr; -//These tell the preprocessor where to find the files of a particular -//ISA, and set the "TheISA" macro for use elsewhere. -#if THE_ISA == ALPHA_ISA - #define TheISA AlphaISA -#elif THE_ISA == SPARC_ISA - #define TheISA SparcISA -#elif THE_ISA == MIPS_ISA - #define TheISA MipsISA -#elif THE_ISA == X86_ISA - #define TheISA X86ISA -#elif THE_ISA == ARM_ISA - #define TheISA ArmISA -#else - #error "THE_ISA not set" -#endif +namespace PowerISA +{ -#endif +using namespace BigEndianGuest; + +StaticInstPtr decodeInst(ExtMachInst); + +// POWER DOES NOT have a delay slot +#define ISA_HAS_DELAY_SLOT 0 + +const Addr PageShift = 12; +const Addr PageBytes = ULL(1) << PageShift; +const Addr Page_Mask = ~(PageBytes - 1); +const Addr PageOffset = PageBytes - 1; + +const Addr PteShift = 3; +const Addr NPtePageShift = PageShift - PteShift; +const Addr NPtePage = ULL(1) << NPtePageShift; +const Addr PteMask = NPtePage - 1; + +const int LogVMPageSize = 12; // 4K bytes +const int VMPageSize = (1 << LogVMPageSize); + +const int MachineBytes = 4; + +// This is ori 0, 0, 0 +const ExtMachInst NoopMachInst = 0x60000000; + +} // PowerISA namespace + +#endif // __ARCH_POWER_ISA_TRAITS_HH__ diff --git a/src/arch/power/linux/linux.cc b/src/arch/power/linux/linux.cc new file mode 100644 index 000000000..113f3e48e --- /dev/null +++ b/src/arch/power/linux/linux.cc @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2003-2005 The Regents of The University of Michigan + * Copyright (c) 2009 The University of Edinburgh + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Timothy M. Jones + */ + +#include "arch/power/linux/linux.hh" + +#include <fcntl.h> + +// open(2) flags translation table +OpenFlagTransTable PowerLinux::openFlagTable[] = { +#ifdef _MSC_VER + { PowerLinux::TGT_O_RDONLY, _O_RDONLY }, + { PowerLinux::TGT_O_WRONLY, _O_WRONLY }, + { PowerLinux::TGT_O_RDWR, _O_RDWR }, + { PowerLinux::TGT_O_APPEND, _O_APPEND }, + { PowerLinux::TGT_O_CREAT, _O_CREAT }, + { PowerLinux::TGT_O_TRUNC, _O_TRUNC }, + { PowerLinux::TGT_O_EXCL, _O_EXCL }, +#ifdef _O_NONBLOCK + { PowerLinux::TGT_O_NONBLOCK, _O_NONBLOCK }, +#endif +#ifdef _O_NOCTTY + { PowerLinux::TGT_O_NOCTTY, _O_NOCTTY }, +#endif +#ifdef _O_SYNC + { PowerLinux::TGT_O_SYNC, _O_SYNC }, +#endif +#ifdef _O_LARGEFILE + { PowerLinux::TGT_O_LARGEFILE, _O_LARGEFILE }, +#endif +#else /* !_MSC_VER */ + { PowerLinux::TGT_O_RDONLY, O_RDONLY }, + { PowerLinux::TGT_O_WRONLY, O_WRONLY }, + { PowerLinux::TGT_O_RDWR, O_RDWR }, + { PowerLinux::TGT_O_APPEND, O_APPEND }, + { PowerLinux::TGT_O_CREAT, O_CREAT }, + { PowerLinux::TGT_O_TRUNC, O_TRUNC }, + { PowerLinux::TGT_O_EXCL, O_EXCL }, + { PowerLinux::TGT_O_NONBLOCK, O_NONBLOCK }, + { PowerLinux::TGT_O_NOCTTY, O_NOCTTY }, +#ifdef O_SYNC + { PowerLinux::TGT_O_SYNC, O_SYNC }, +#endif +#ifdef O_LARGEFILE + { PowerLinux::TGT_O_LARGEFILE, O_LARGEFILE }, +#endif +#endif /* _MSC_VER */ +}; + +const int PowerLinux::NUM_OPEN_FLAGS = + (sizeof(PowerLinux::openFlagTable)/sizeof(PowerLinux::openFlagTable[0])); + diff --git a/src/arch/power/linux/linux.hh b/src/arch/power/linux/linux.hh new file mode 100644 index 000000000..c681c8baf --- /dev/null +++ b/src/arch/power/linux/linux.hh @@ -0,0 +1,148 @@ +/* + * Copyright (c) 2003-2005 The Regents of The University of Michigan + * Copyright (c) 2009 The University of Edinburgh + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Timothy M. Jones + */ + +#ifndef __ARCH_POWER_LINUX_LINUX_HH__ +#define __ARCH_POWER_LINUX_LINUX_HH__ + +#include "kern/linux/linux.hh" + +/* + * This works for a 2.6.15 kernel. + */ + +class PowerLinux : public Linux +{ + public: + + typedef int32_t time_t; + + typedef struct { + uint64_t st_dev; + uint32_t __pad1; + uint32_t st_ino; + uint32_t st_mode; + uint32_t st_nlink; + uint32_t st_uid; + uint32_t st_gid; + uint64_t st_rdev; + uint32_t __pad2; + uint32_t st_size; + uint32_t st_blksize; + uint32_t st_blocks; + uint32_t st_atimeX; + uint32_t st_atime_nsec; + uint32_t st_mtimeX; + uint32_t st_mtime_nsec; + uint32_t st_ctimeX; + uint32_t st_ctime_nsec; + uint32_t __unused4; + uint32_t __unused5; + } tgt_stat; + + typedef struct { + uint64_t st_dev; + uint64_t st_ino; + uint32_t st_mode; + uint32_t st_nlink; + uint32_t st_uid; + uint32_t st_gid; + uint64_t st_rdev; + uint64_t __pad2; + uint64_t st_size; + uint32_t st_blksize; + uint32_t __blksize_pad; + uint64_t st_blocks; + uint32_t st_atimeX; + uint32_t st_atime_nsec; + uint32_t st_mtimeX; + uint32_t st_mtime_nsec; + uint32_t st_ctimeX; + uint32_t st_ctime_nsec; + uint32_t __unused4; + uint32_t __unused5; + } tgt_stat64; + + /// For times(). + struct tms { + int32_t tms_utime; //!< user time + int32_t tms_stime; //!< system time + int32_t tms_cutime; //!< user time of children + int32_t tms_cstime; //!< system time of children + }; + + /// This table maps the target open() flags to the corresponding + /// host open() flags. + static OpenFlagTransTable openFlagTable[]; + + /// Number of entries in openFlagTable[]. + static const int NUM_OPEN_FLAGS; + + //@{ + /// open(2) flag values. + static const int TGT_O_RDONLY = 00000000; //!< O_RDONLY + static const int TGT_O_WRONLY = 00000001; //!< O_WRONLY + static const int TGT_O_RDWR = 00000002; //!< O_RDWR + static const int TGT_O_CREAT = 00000100; //!< O_CREAT + static const int TGT_O_EXCL = 00000200; //!< O_EXCL + static const int TGT_O_NOCTTY = 00000400; //!< O_NOCTTY + static const int TGT_O_TRUNC = 00001000; //!< O_TRUNC + static const int TGT_O_APPEND = 00002000; //!< O_APPEND + static const int TGT_O_NONBLOCK = 00004000; //!< O_NONBLOCK + static const int TGT_O_SYNC = 00010000; //!< O_SYNC + static const int TGT_FASYNC = 00020000; //!< FASYNC + static const int TGT_O_DIRECTORY = 00040000; //!< O_DIRECTORY + static const int TGT_O_NOFOLLOW = 00100000; //!< O_NOFOLLOW + static const int TGT_O_LARGEFILE = 00200000; //!< O_LARGEFILE + static const int TGT_O_DIRECT = 00400000; //!< O_DIRECT + static const int TGT_O_NOATIME = 01000000; //!< O_NOATIME + //@} + + /// For mmap(). + static const unsigned TGT_MAP_ANONYMOUS = 0x800; + + //@{ + /// ioctl() command codes. + /// These are for the 2.6.15 kernel. Some have changed for + /// later versions. + static const unsigned TIOCGETP_ = 0x40067408; + static const unsigned TIOCSETP_ = 0x80067409; + static const unsigned TIOCSETN_ = 0x8006740a; + static const unsigned TIOCSETC_ = 0x80067411; + static const unsigned TIOCGETC_ = 0x40067412; + static const unsigned FIONREAD_ = 0x4004667f; + static const unsigned TIOCISATTY_ = 0x2000745e; + static const unsigned TIOCGETS_ = 0x402c7413; + static const unsigned TIOCGETA_ = 0x40147417; + static const unsigned TCSETAW_ = 0x80147419; + //@} +}; + +#endif // __ARCH_POWER_LINUX_LINUX_HH__ diff --git a/src/arch/power/linux/process.cc b/src/arch/power/linux/process.cc new file mode 100644 index 000000000..504d0e334 --- /dev/null +++ b/src/arch/power/linux/process.cc @@ -0,0 +1,456 @@ +/* + * Copyright (c) 2003-2005 The Regents of The University of Michigan + * Copyright (c) 2007-2008 The Florida State University + * Copyright (c) 2009 The University of Edinburgh + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Korey Sewell + * Stephen Hines + * Timothy M. Jones + */ + +#include "arch/power/linux/linux.hh" +#include "arch/power/linux/process.hh" +#include "arch/power/isa_traits.hh" + +#include "base/trace.hh" +#include "cpu/thread_context.hh" +#include "kern/linux/linux.hh" + +#include "sim/process.hh" +#include "sim/syscall_emul.hh" +#include "sim/system.hh" + +using namespace std; +using namespace PowerISA; + +/// Target uname() handler. +static SyscallReturn +unameFunc(SyscallDesc *desc, int callnum, LiveProcess *process, + ThreadContext *tc) +{ + int index = 0; + TypedBufferArg<Linux::utsname> name(process->getSyscallArg(tc, index)); + + strcpy(name->sysname, "Linux"); + strcpy(name->nodename, "m5.eecs.umich.edu"); + strcpy(name->release, "2.6.16.19"); + strcpy(name->version, "#1 Mon Aug 18 11:32:15 EDT 2003"); + strcpy(name->machine, "power"); + + name.copyOut(tc->getMemPort()); + return 0; +} + +SyscallDesc PowerLinuxProcess::syscallDescs[] = { + /* 0 */ SyscallDesc("syscall", unimplementedFunc), + /* 1 */ SyscallDesc("exit", exitFunc), + /* 2 */ SyscallDesc("fork", unimplementedFunc), + /* 3 */ SyscallDesc("read", readFunc), + /* 4 */ SyscallDesc("write", writeFunc), + /* 5 */ SyscallDesc("open", openFunc<PowerLinux>), + /* 6 */ SyscallDesc("close", closeFunc), + /* 7 */ SyscallDesc("waitpid", unimplementedFunc), //??? + /* 8 */ SyscallDesc("creat", unimplementedFunc), + /* 9 */ SyscallDesc("link", unimplementedFunc), + /* 10 */ SyscallDesc("unlink", unlinkFunc), + /* 11 */ SyscallDesc("execve", unimplementedFunc), + /* 12 */ SyscallDesc("chdir", unimplementedFunc), + /* 13 */ SyscallDesc("time", timeFunc<PowerLinux>), + /* 14 */ SyscallDesc("mknod", unimplementedFunc), + /* 15 */ SyscallDesc("chmod", chmodFunc<PowerLinux>), + /* 16 */ SyscallDesc("lchown", chownFunc), + /* 17 */ SyscallDesc("break", brkFunc), //??? + /* 18 */ SyscallDesc("unused#18", unimplementedFunc), //??? + /* 19 */ SyscallDesc("lseek", lseekFunc), + /* 20 */ SyscallDesc("getpid", getpidFunc), + /* 21 */ SyscallDesc("mount", unimplementedFunc), + /* 22 */ SyscallDesc("umount", unimplementedFunc), + /* 23 */ SyscallDesc("setuid", setuidFunc), + /* 24 */ SyscallDesc("getuid", getuidFunc), + /* 25 */ SyscallDesc("stime", unimplementedFunc), + /* 26 */ SyscallDesc("ptrace", unimplementedFunc), + /* 27 */ SyscallDesc("alarm", unimplementedFunc), + /* 28 */ SyscallDesc("unused#28", unimplementedFunc), + /* 29 */ SyscallDesc("pause", unimplementedFunc), + /* 30 */ SyscallDesc("utime", unimplementedFunc), + /* 31 */ SyscallDesc("stty", unimplementedFunc), + /* 32 */ SyscallDesc("gtty", unimplementedFunc), + /* 33 */ SyscallDesc("access", unimplementedFunc), + /* 34 */ SyscallDesc("nice", unimplementedFunc), + /* 35 */ SyscallDesc("ftime", unimplementedFunc), + /* 36 */ SyscallDesc("sync", unimplementedFunc), + /* 37 */ SyscallDesc("kill", ignoreFunc), + /* 38 */ SyscallDesc("rename", renameFunc), + /* 39 */ SyscallDesc("mkdir", unimplementedFunc), + /* 40 */ SyscallDesc("rmdir", unimplementedFunc), + /* 41 */ SyscallDesc("dup", dupFunc), + /* 42 */ SyscallDesc("pipe", unimplementedFunc), + /* 43 */ SyscallDesc("times", timesFunc<PowerLinux>), + /* 44 */ SyscallDesc("prof", unimplementedFunc), + /* 45 */ SyscallDesc("brk", brkFunc), + /* 46 */ SyscallDesc("setgid", unimplementedFunc), + /* 47 */ SyscallDesc("getgid", getgidFunc), + /* 48 */ SyscallDesc("signal", ignoreFunc), + /* 49 */ SyscallDesc("geteuid", geteuidFunc), + /* 50 */ SyscallDesc("getegid", getegidFunc), + /* 51 */ SyscallDesc("acct", unimplementedFunc), + /* 52 */ SyscallDesc("umount2", unimplementedFunc), + /* 53 */ SyscallDesc("lock", unimplementedFunc), + /* 54 */ SyscallDesc("ioctl", ioctlFunc<PowerLinux>), + /* 55 */ SyscallDesc("fcntl", fcntlFunc), + /* 56 */ SyscallDesc("mpx", unimplementedFunc), + /* 57 */ SyscallDesc("setpgid", unimplementedFunc), + /* 58 */ SyscallDesc("ulimit", unimplementedFunc), + /* 59 */ SyscallDesc("unused#59", unimplementedFunc), + /* 60 */ SyscallDesc("umask", umaskFunc), + /* 61 */ SyscallDesc("chroot", unimplementedFunc), + /* 62 */ SyscallDesc("ustat", unimplementedFunc), + /* 63 */ SyscallDesc("dup2", unimplementedFunc), + /* 64 */ SyscallDesc("getppid", getpagesizeFunc), + /* 65 */ SyscallDesc("getpgrp", unimplementedFunc), + /* 66 */ SyscallDesc("setsid", unimplementedFunc), + /* 67 */ SyscallDesc("sigaction",unimplementedFunc), + /* 68 */ SyscallDesc("sgetmask", unimplementedFunc), + /* 69 */ SyscallDesc("ssetmask", unimplementedFunc), + /* 70 */ SyscallDesc("setreuid", unimplementedFunc), + /* 71 */ SyscallDesc("setregid", unimplementedFunc), + /* 72 */ SyscallDesc("sigsuspend", unimplementedFunc), + /* 73 */ SyscallDesc("sigpending", unimplementedFunc), + /* 74 */ SyscallDesc("sethostname", ignoreFunc), + /* 75 */ SyscallDesc("setrlimit", ignoreFunc), + /* 76 */ SyscallDesc("getrlimit", unimplementedFunc), + /* 77 */ SyscallDesc("getrusage", ignoreFunc), + /* 78 */ SyscallDesc("gettimeofday", unimplementedFunc), + /* 79 */ SyscallDesc("settimeofday", unimplementedFunc), + /* 80 */ SyscallDesc("getgroups", unimplementedFunc), + /* 81 */ SyscallDesc("setgroups", unimplementedFunc), + /* 82 */ SyscallDesc("reserved#82", unimplementedFunc), + /* 83 */ SyscallDesc("symlink", unimplementedFunc), + /* 84 */ SyscallDesc("unused#84", unimplementedFunc), + /* 85 */ SyscallDesc("readlink", unimplementedFunc), + /* 86 */ SyscallDesc("uselib", unimplementedFunc), + /* 87 */ SyscallDesc("swapon", gethostnameFunc), + /* 88 */ SyscallDesc("reboot", unimplementedFunc), + /* 89 */ SyscallDesc("readdir", unimplementedFunc), + /* 90 */ SyscallDesc("mmap", mmapFunc<PowerLinux>), + /* 91 */ SyscallDesc("munmap",munmapFunc), + /* 92 */ SyscallDesc("truncate", truncateFunc), + /* 93 */ SyscallDesc("ftruncate", ftruncateFunc), + /* 94 */ SyscallDesc("fchmod", unimplementedFunc), + /* 95 */ SyscallDesc("fchown", unimplementedFunc), + /* 96 */ SyscallDesc("getpriority", unimplementedFunc), + /* 97 */ SyscallDesc("setpriority", unimplementedFunc), + /* 98 */ SyscallDesc("profil", unimplementedFunc), + /* 99 */ SyscallDesc("statfs", unimplementedFunc), + /* 100 */ SyscallDesc("fstatfs", unimplementedFunc), + /* 101 */ SyscallDesc("ioperm", unimplementedFunc), + /* 102 */ SyscallDesc("socketcall", unimplementedFunc), + /* 103 */ SyscallDesc("syslog", unimplementedFunc), + /* 104 */ SyscallDesc("setitimer", unimplementedFunc), + /* 105 */ SyscallDesc("getitimer", unimplementedFunc), + /* 106 */ SyscallDesc("stat", statFunc<PowerLinux>), + /* 107 */ SyscallDesc("lstat", unimplementedFunc), + /* 108 */ SyscallDesc("fstat", fstatFunc<PowerLinux>), + /* 109 */ SyscallDesc("unused#109", unimplementedFunc), + /* 110 */ SyscallDesc("iopl", unimplementedFunc), + /* 111 */ SyscallDesc("vhangup", unimplementedFunc), + /* 112 */ SyscallDesc("idle", ignoreFunc), + /* 113 */ SyscallDesc("vm86", unimplementedFunc), + /* 114 */ SyscallDesc("wait4", unimplementedFunc), + /* 115 */ SyscallDesc("swapoff", unimplementedFunc), + /* 116 */ SyscallDesc("sysinfo", unimplementedFunc), + /* 117 */ SyscallDesc("ipc", unimplementedFunc), + /* 118 */ SyscallDesc("fsync", unimplementedFunc), + /* 119 */ SyscallDesc("sigreturn", unimplementedFunc), + /* 120 */ SyscallDesc("clone", unimplementedFunc), + /* 121 */ SyscallDesc("setdomainname", unimplementedFunc), + /* 122 */ SyscallDesc("uname", unameFunc), + /* 123 */ SyscallDesc("modify_ldt", unimplementedFunc), + /* 124 */ SyscallDesc("adjtimex", unimplementedFunc), + /* 125 */ SyscallDesc("mprotect", ignoreFunc), + /* 126 */ SyscallDesc("sigprocmask", unimplementedFunc), + /* 127 */ SyscallDesc("create_module", unimplementedFunc), + /* 128 */ SyscallDesc("init_module", unimplementedFunc), + /* 129 */ SyscallDesc("delete_module", unimplementedFunc), + /* 130 */ SyscallDesc("get_kernel_syms", unimplementedFunc), + /* 131 */ SyscallDesc("quotactl", unimplementedFunc), + /* 132 */ SyscallDesc("getpgid", unimplementedFunc), + /* 133 */ SyscallDesc("fchdir", unimplementedFunc), + /* 134 */ SyscallDesc("bdflush", unimplementedFunc), + /* 135 */ SyscallDesc("sysfs", unimplementedFunc), + /* 136 */ SyscallDesc("personality", unimplementedFunc), + /* 137 */ SyscallDesc("afs_syscall", unimplementedFunc), + /* 138 */ SyscallDesc("setfsuid", unimplementedFunc), + /* 139 */ SyscallDesc("setfsgid", unimplementedFunc), + /* 140 */ SyscallDesc("llseek", _llseekFunc), + /* 141 */ SyscallDesc("getdents", unimplementedFunc), + /* 142 */ SyscallDesc("newselect", unimplementedFunc), + /* 143 */ SyscallDesc("flock", unimplementedFunc), + /* 144 */ SyscallDesc("msync", unimplementedFunc), + /* 145 */ SyscallDesc("readv", unimplementedFunc), + /* 146 */ SyscallDesc("writev", writevFunc<PowerLinux>), + /* 147 */ SyscallDesc("getsid", unimplementedFunc), + /* 148 */ SyscallDesc("fdatasync", unimplementedFunc), + /* 149 */ SyscallDesc("sysctl", unimplementedFunc), + /* 150 */ SyscallDesc("mlock", unimplementedFunc), + /* 151 */ SyscallDesc("munlock", unimplementedFunc), + /* 152 */ SyscallDesc("mlockall", unimplementedFunc), + /* 153 */ SyscallDesc("munlockall", unimplementedFunc), + /* 154 */ SyscallDesc("sched_setparam", unimplementedFunc), + /* 155 */ SyscallDesc("sched_getparam", unimplementedFunc), + /* 156 */ SyscallDesc("sched_setscheduler", unimplementedFunc), + /* 157 */ SyscallDesc("sched_getscheduler", unimplementedFunc), + /* 158 */ SyscallDesc("sched_yield", unimplementedFunc), + /* 159 */ SyscallDesc("sched_get_priority_max", unimplementedFunc), + /* 160 */ SyscallDesc("sched_get_priority_min", unimplementedFunc), + /* 161 */ SyscallDesc("sched_rr_get_interval", unimplementedFunc), + /* 162 */ SyscallDesc("nanosleep", unimplementedFunc), + /* 163 */ SyscallDesc("mremap", unimplementedFunc), + /* 164 */ SyscallDesc("setresuid", unimplementedFunc), + /* 165 */ SyscallDesc("getresuid", unimplementedFunc), + /* 166 */ SyscallDesc("vm862", unimplementedFunc), + /* 167 */ SyscallDesc("query_module", unimplementedFunc), + /* 168 */ SyscallDesc("poll", unimplementedFunc), + /* 169 */ SyscallDesc("nfsservctl", unimplementedFunc), + /* 170 */ SyscallDesc("setresgid", unimplementedFunc), + /* 171 */ SyscallDesc("getresgid", unimplementedFunc), + /* 172 */ SyscallDesc("prctl", unimplementedFunc), + /* 173 */ SyscallDesc("rt_sigaction", ignoreFunc), + /* 174 */ SyscallDesc("rt_sigprocmask", unimplementedFunc), + /* 175 */ SyscallDesc("unknown#175", unimplementedFunc), + /* 176 */ SyscallDesc("rt_sigpending", unimplementedFunc), + /* 177 */ SyscallDesc("rt_sigtimedwait", unimplementedFunc), + /* 178 */ SyscallDesc("rt_sigqueueinfo", ignoreFunc), + /* 179 */ SyscallDesc("rt_sigsuspend", unimplementedFunc), + /* 180 */ SyscallDesc("pread64", unimplementedFunc), + /* 181 */ SyscallDesc("pwrite64", unimplementedFunc), + /* 182 */ SyscallDesc("chown", unimplementedFunc), + /* 183 */ SyscallDesc("getcwd", unimplementedFunc), + /* 184 */ SyscallDesc("capget", unimplementedFunc), + /* 185 */ SyscallDesc("capset", unimplementedFunc), + /* 186 */ SyscallDesc("sigaltstack", unimplementedFunc), + /* 187 */ SyscallDesc("sendfile", unimplementedFunc), + /* 188 */ SyscallDesc("getpmsg", unimplementedFunc), + /* 189 */ SyscallDesc("putpmsg", unimplementedFunc), + /* 190 */ SyscallDesc("ugetrlimit", ignoreFunc), + /* 191 */ SyscallDesc("getrlimit", unimplementedFunc), + /* 192 */ SyscallDesc("mmap2", mmapFunc<PowerLinux>), + /* 193 */ SyscallDesc("truncate64", unimplementedFunc), + /* 194 */ SyscallDesc("ftruncate64", ftruncate64Func), + /* 195 */ SyscallDesc("stat64", stat64Func<PowerLinux>), + /* 196 */ SyscallDesc("lstat64", lstat64Func<PowerLinux>), + /* 197 */ SyscallDesc("fstat64", fstat64Func<PowerLinux>), + /* 198 */ SyscallDesc("lchown", unimplementedFunc), + /* 199 */ SyscallDesc("getuid", getuidFunc), + /* 200 */ SyscallDesc("getgid", getgidFunc), + /* 201 */ SyscallDesc("geteuid", geteuidFunc), + /* 202 */ SyscallDesc("getegid", getegidFunc), + /* 203 */ SyscallDesc("setreuid", unimplementedFunc), + /* 204 */ SyscallDesc("fcntl64", fcntl64Func), + /* 205 */ SyscallDesc("getgroups", unimplementedFunc), + /* 206 */ SyscallDesc("setgroups", unimplementedFunc), + /* 207 */ SyscallDesc("fchown", unimplementedFunc), + /* 208 */ SyscallDesc("setresuid", unimplementedFunc), + /* 209 */ SyscallDesc("getresuid", unimplementedFunc), + /* 210 */ SyscallDesc("setresgid", unimplementedFunc), + /* 211 */ SyscallDesc("getresgid", unimplementedFunc), + /* 212 */ SyscallDesc("chown", unimplementedFunc), + /* 213 */ SyscallDesc("setuid", unimplementedFunc), + /* 214 */ SyscallDesc("setgid", unimplementedFunc), + /* 215 */ SyscallDesc("setfsuid", unimplementedFunc), + /* 216 */ SyscallDesc("setfsgid", unimplementedFunc), + /* 217 */ SyscallDesc("getdents64", unimplementedFunc), + /* 218 */ SyscallDesc("pivot_root", unimplementedFunc), + /* 219 */ SyscallDesc("mincore", unimplementedFunc), + /* 220 */ SyscallDesc("madvise", unimplementedFunc), + /* 221 */ SyscallDesc("unknown#221", unimplementedFunc), + /* 222 */ SyscallDesc("tux", unimplementedFunc), + /* 223 */ SyscallDesc("unknown#223", unimplementedFunc), + /* 224 */ SyscallDesc("gettid", unimplementedFunc), + /* 225 */ SyscallDesc("readahead", unimplementedFunc), + /* 226 */ SyscallDesc("setxattr", unimplementedFunc), + /* 227 */ SyscallDesc("lsetxattr", unimplementedFunc), + /* 228 */ SyscallDesc("fsetxattr", unimplementedFunc), + /* 229 */ SyscallDesc("getxattr", unimplementedFunc), + /* 230 */ SyscallDesc("lgetxattr", unimplementedFunc), + /* 231 */ SyscallDesc("fgetxattr", unimplementedFunc), + /* 232 */ SyscallDesc("listxattr", unimplementedFunc), + /* 233 */ SyscallDesc("llistxattr", unimplementedFunc), + /* 234 */ SyscallDesc("exit_group", exitGroupFunc), + /* 235 */ SyscallDesc("removexattr", unimplementedFunc), + /* 236 */ SyscallDesc("lremovexattr", unimplementedFunc), + /* 237 */ SyscallDesc("fremovexattr", unimplementedFunc), + /* 238 */ SyscallDesc("tkill", unimplementedFunc), + /* 239 */ SyscallDesc("sendfile64", unimplementedFunc), + /* 240 */ SyscallDesc("futex", unimplementedFunc), + /* 241 */ SyscallDesc("sched_setaffinity", unimplementedFunc), + /* 242 */ SyscallDesc("sched_getaffinity", unimplementedFunc), + /* 243 */ SyscallDesc("io_setup", unimplementedFunc), + /* 244 */ SyscallDesc("io_destory", unimplementedFunc), + /* 245 */ SyscallDesc("io_getevents", unimplementedFunc), + /* 246 */ SyscallDesc("io_submit", unimplementedFunc), + /* 247 */ SyscallDesc("io_cancel", unimplementedFunc), + /* 248 */ SyscallDesc("unknown#248", unimplementedFunc), + /* 249 */ SyscallDesc("lookup_dcookie", unimplementedFunc), + /* 250 */ SyscallDesc("epoll_create", unimplementedFunc), + /* 251 */ SyscallDesc("epoll_ctl", unimplementedFunc), + /* 252 */ SyscallDesc("epoll_wait", unimplementedFunc), + /* 253 */ SyscallDesc("remap_file_pages", unimplementedFunc), + /* 254 */ SyscallDesc("set_thread_area", unimplementedFunc), + /* 255 */ SyscallDesc("get_thread_area", unimplementedFunc), + /* 256 */ SyscallDesc("set_tid_address", unimplementedFunc), + /* 257 */ SyscallDesc("timer_create", unimplementedFunc), + /* 258 */ SyscallDesc("timer_settime", unimplementedFunc), + /* 259 */ SyscallDesc("timer_gettime", unimplementedFunc), + /* 260 */ SyscallDesc("timer_getoverrun", unimplementedFunc), + /* 261 */ SyscallDesc("timer_delete", unimplementedFunc), + /* 262 */ SyscallDesc("clock_settime", unimplementedFunc), + /* 263 */ SyscallDesc("clock_gettime", unimplementedFunc), + /* 264 */ SyscallDesc("clock_getres", unimplementedFunc), + /* 265 */ SyscallDesc("clock_nanosleep", unimplementedFunc), + /* 266 */ SyscallDesc("statfs64", unimplementedFunc), + /* 267 */ SyscallDesc("fstatfs64", unimplementedFunc), + /* 268 */ SyscallDesc("tgkill", unimplementedFunc), + /* 269 */ SyscallDesc("utimes", unimplementedFunc), + /* 270 */ SyscallDesc("arm_fadvise64_64", unimplementedFunc), + /* 271 */ SyscallDesc("pciconfig_iobase", unimplementedFunc), + /* 272 */ SyscallDesc("pciconfig_read", unimplementedFunc), + /* 273 */ SyscallDesc("pciconfig_write", unimplementedFunc), + /* 274 */ SyscallDesc("mq_open", unimplementedFunc), + /* 275 */ SyscallDesc("mq_unlink", unimplementedFunc), + /* 276 */ SyscallDesc("mq_timedsend", unimplementedFunc), + /* 277 */ SyscallDesc("mq_timedreceive", unimplementedFunc), + /* 278 */ SyscallDesc("mq_notify", unimplementedFunc), + /* 279 */ SyscallDesc("mq_getsetattr", unimplementedFunc), + /* 280 */ SyscallDesc("waitid", unimplementedFunc), + /* 281 */ SyscallDesc("socket", unimplementedFunc), + /* 282 */ SyscallDesc("bind", unimplementedFunc), + /* 283 */ SyscallDesc("connect", unimplementedFunc), + /* 284 */ SyscallDesc("listen", unimplementedFunc), + /* 285 */ SyscallDesc("accept", unimplementedFunc), + /* 286 */ SyscallDesc("getsockname", unimplementedFunc), + /* 287 */ SyscallDesc("getpeername", unimplementedFunc), + /* 288 */ SyscallDesc("socketpair", unimplementedFunc), + /* 289 */ SyscallDesc("send", unimplementedFunc), + /* 290 */ SyscallDesc("sendto", unimplementedFunc), + /* 291 */ SyscallDesc("recv", unimplementedFunc), + /* 292 */ SyscallDesc("recvfrom", unimplementedFunc), + /* 293 */ SyscallDesc("shutdown", unimplementedFunc), + /* 294 */ SyscallDesc("setsockopt", unimplementedFunc), + /* 295 */ SyscallDesc("getsockopt", unimplementedFunc), + /* 296 */ SyscallDesc("sendmsg", unimplementedFunc), + /* 297 */ SyscallDesc("rcvmsg", unimplementedFunc), + /* 298 */ SyscallDesc("semop", unimplementedFunc), + /* 299 */ SyscallDesc("semget", unimplementedFunc), + /* 300 */ SyscallDesc("semctl", unimplementedFunc), + /* 301 */ SyscallDesc("msgsend", unimplementedFunc), + /* 302 */ SyscallDesc("msgrcv", unimplementedFunc), + /* 303 */ SyscallDesc("msgget", unimplementedFunc), + /* 304 */ SyscallDesc("msgctl", unimplementedFunc), + /* 305 */ SyscallDesc("shmat", unimplementedFunc), + /* 306 */ SyscallDesc("shmdt", unimplementedFunc), + /* 307 */ SyscallDesc("shmget", unimplementedFunc), + /* 308 */ SyscallDesc("shmctl", unimplementedFunc), + /* 309 */ SyscallDesc("add_key", unimplementedFunc), + /* 310 */ SyscallDesc("request_key", unimplementedFunc), + /* 311 */ SyscallDesc("keyctl", unimplementedFunc), + /* 312 */ SyscallDesc("semtimedop", unimplementedFunc), + /* 313 */ SyscallDesc("vserver", unimplementedFunc), + /* 314 */ SyscallDesc("ioprio_set", unimplementedFunc), + /* 315 */ SyscallDesc("ioprio_get", unimplementedFunc), + /* 316 */ SyscallDesc("inotify_init", unimplementedFunc), + /* 317 */ SyscallDesc("inotify_add_watch", unimplementedFunc), + /* 318 */ SyscallDesc("inotify_rm_watch", unimplementedFunc), + /* 319 */ SyscallDesc("mbind", unimplementedFunc), + /* 320 */ SyscallDesc("get_mempolicy", unimplementedFunc), + /* 321 */ SyscallDesc("set_mempolicy", unimplementedFunc), + /* 322 */ SyscallDesc("openat", unimplementedFunc), + /* 323 */ SyscallDesc("mkdirat", unimplementedFunc), + /* 324 */ SyscallDesc("mknodat", unimplementedFunc), + /* 325 */ SyscallDesc("fchownat", unimplementedFunc), + /* 326 */ SyscallDesc("futimesat", unimplementedFunc), + /* 327 */ SyscallDesc("fstatat64", unimplementedFunc), + /* 328 */ SyscallDesc("unlinkat", unimplementedFunc), + /* 329 */ SyscallDesc("renameat", unimplementedFunc), + /* 330 */ SyscallDesc("linkat", unimplementedFunc), + /* 331 */ SyscallDesc("symlinkat", unimplementedFunc), + /* 332 */ SyscallDesc("readlinkat", unimplementedFunc), + /* 333 */ SyscallDesc("fchmodat", unimplementedFunc), + /* 334 */ SyscallDesc("faccessat", unimplementedFunc), + /* 335 */ SyscallDesc("pselect6", unimplementedFunc), + /* 336 */ SyscallDesc("ppoll", unimplementedFunc), + /* 337 */ SyscallDesc("unshare", unimplementedFunc), + /* 338 */ SyscallDesc("set_robust_list", unimplementedFunc), + /* 339 */ SyscallDesc("get_robust_list", unimplementedFunc), + /* 340 */ SyscallDesc("splice", unimplementedFunc), + /* 341 */ SyscallDesc("arm_sync_file_range", unimplementedFunc), + /* 342 */ SyscallDesc("tee", unimplementedFunc), + /* 343 */ SyscallDesc("vmsplice", unimplementedFunc), + /* 344 */ SyscallDesc("move_pages", unimplementedFunc), + /* 345 */ SyscallDesc("getcpu", unimplementedFunc), + /* 346 */ SyscallDesc("epoll_pwait", unimplementedFunc), +}; + +PowerLinuxProcess::PowerLinuxProcess(LiveProcessParams * params, + ObjectFile *objFile) + : PowerLiveProcess(params, objFile), + Num_Syscall_Descs(sizeof(syscallDescs) / sizeof(SyscallDesc)) +{ +} + +SyscallDesc* +PowerLinuxProcess::getDesc(int callnum) +{ + if (callnum < 0 || callnum > Num_Syscall_Descs) + return NULL; + + return &syscallDescs[callnum]; +} + +void +PowerLinuxProcess::startup() +{ + PowerLiveProcess::startup(); +} + +PowerISA::IntReg +PowerLinuxProcess::getSyscallArg(ThreadContext *tc, int &i) +{ + // Linux apparently allows more parameter than the ABI says it should. + // This limit may need to be increased even further. + assert(i < 6); + return tc->readIntReg(ArgumentReg0 + i++); +} + +void +PowerLinuxProcess::setSyscallArg(ThreadContext *tc, int i, PowerISA::IntReg val) +{ + // Linux apparently allows more parameter than the ABI says it should. + // This limit may need to be increased even further. + assert(i < 6); + tc->setIntReg(ArgumentReg0 + i, val); +} diff --git a/src/mem/slicc/generator/fileio.cc b/src/arch/power/linux/process.hh index 15eccd3ca..db6759a77 100644 --- a/src/mem/slicc/generator/fileio.cc +++ b/src/arch/power/linux/process.hh @@ -1,6 +1,6 @@ - /* - * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood + * Copyright (c) 2007-2008 The Florida State University + * Copyright (c) 2009 The University of Edinburgh * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -25,42 +25,34 @@ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Stephen Hines + * Timothy M. Jones */ -/* - * fileio.C - * - * Description: See fileio.hh - * - * $Id: fileio.C,v 3.3 2003/07/10 18:08:08 milo Exp $ - * - * */ +#ifndef __POWER_LINUX_PROCESS_HH__ +#define __POWER_LINUX_PROCESS_HH__ + +#include "arch/power/process.hh" -#include "mem/slicc/generator/fileio.hh" -void conditionally_write_file(string filename, ostringstream& sstr) +/// A process with emulated PPC/Linux syscalls. +class PowerLinuxProcess : public PowerLiveProcess { - ofstream out; - ifstream in; - string input_file; + public: + PowerLinuxProcess(LiveProcessParams * params, ObjectFile *objFile); + + virtual SyscallDesc* getDesc(int callnum); + + void startup(); + + PowerISA::IntReg getSyscallArg(ThreadContext *tc, int &i); + void setSyscallArg(ThreadContext *tc, int i, PowerISA::IntReg val); - // Read in the file if it exists - in.open(filename.c_str()); - char c; - while (in.get(c)) { - input_file += c; - } - in.close(); + /// Array of syscall descriptors, indexed by call number. + static SyscallDesc syscallDescs[]; - // Check to see if the file is the same as what we want to write - if (input_file != sstr.str()) { - cout << " Overwriting file: " << filename << endl; - // Overwrite the old file with the new file - out.open(filename.c_str()); - out << sstr.str(); - out.close(); - } else { - //cout << " Keeping old file: " << filename << endl; - } -} + const int Num_Syscall_Descs; +}; +#endif // __POWER_LINUX_PROCESS_HH__ diff --git a/src/mem/slicc/ast/PairAST.cc b/src/arch/power/locked_mem.hh index c42843cce..56ab1d4a0 100644 --- a/src/mem/slicc/ast/PairAST.cc +++ b/src/arch/power/locked_mem.hh @@ -1,6 +1,7 @@ - /* - * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood + * Copyright (c) 2006 The Regents of The University of Michigan + * Copyright (c) 2007-2008 The Florida State University + * Copyright (c) 2009 The University of Edinburgh * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -25,48 +26,39 @@ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Steve Reinhardt + * Stephen Hines + * Timothy M. Jones */ -/* - * PairAST.C - * - * Description: See PairAST.hh - * - * $Id$ +#ifndef __ARCH_POWER_LOCKED_MEM_HH__ +#define __ARCH_POWER_LOCKED_MEM_HH__ + +/** + * @file * + * ISA-specific helper functions for locked memory accesses. */ -#include "mem/slicc/ast/PairAST.hh" +#include "mem/request.hh" -PairAST::PairAST(string* key_ptr, string* value_ptr) - : AST() +namespace PowerISA { - m_key_ptr = key_ptr; - m_value_ptr = value_ptr; -} - -PairAST::PairAST(string key, string* value_ptr) - : AST() -{ - m_key_ptr = new string(key); - m_value_ptr = value_ptr; -} -PairAST::PairAST(string key, string value) - : AST() +template <class XC> +inline void +handleLockedRead(XC *xc, Request *req) { - m_key_ptr = new string(key); - m_value_ptr = new string(value); } -PairAST::~PairAST() +template <class XC> +inline bool +handleLockedWrite(XC *xc, Request *req) { - delete m_key_ptr; - delete m_value_ptr; + return true; } -void PairAST::print(ostream& out) const -{ - out << "[" << *m_key_ptr << "=" << *m_value_ptr << "]" << endl; -} +} // PowerISA namespace +#endif // __ARCH_POWER_LOCKED_MEM_HH__ diff --git a/src/mem/slicc/ast/PairListAST.cc b/src/arch/power/microcode_rom.hh index 76892d437..e35db5112 100644 --- a/src/mem/slicc/ast/PairListAST.cc +++ b/src/arch/power/microcode_rom.hh @@ -1,6 +1,6 @@ - /* - * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood + * Copyright (c) 2008 The Regents of The University of Michigan + * Copyright (c) 2009 The University of Edinburgh * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -25,25 +25,21 @@ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/* - * PairListAST.C - * - * Description: See PairListAST.hh - * - * $Id$ * + * Authors: Gabe Black + * Timothy M. Jones */ -#include "mem/slicc/ast/PairListAST.hh" +#ifndef __ARCH_POWER_MICROCODE_ROM_HH__ +#define __ARCH_POWER_MICROCODE_ROM_HH__ -void PairListAST::addPair(PairAST* pair_ptr) -{ - getPairs().add(pair_ptr->key(), pair_ptr->value()); -} +#include "sim/microcode_rom.hh" -void PairListAST::print(ostream& out) const +namespace PowerISA { - out << "[PairListAST] " << getPairs(); -} + +using ::MicrocodeRom; + +} // PowerISA namespace + +#endif // __ARCH_POWER_MICROCODE_ROM_HH__ diff --git a/src/mem/slicc/ast/CheckAllocateStatementAST.hh b/src/arch/power/miscregs.hh index 1df853514..cd9815b2a 100644 --- a/src/mem/slicc/ast/CheckAllocateStatementAST.hh +++ b/src/arch/power/miscregs.hh @@ -1,6 +1,5 @@ - /* - * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood + * Copyright (c) 2009 The University of Edinburgh * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -25,58 +24,72 @@ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/* - * $Id$ * + * Authors: Timothy M. Jones */ -#ifndef CHECKALLOCATESTATEMENTAST_H -#define CHECKALLOCATESTATEMENTAST_H - -#include "mem/slicc/slicc_global.hh" -#include "mem/slicc/ast/StatementAST.hh" -#include "mem/slicc/ast/TypeAST.hh" - -class VarExprAST; -class Var; +#ifndef __ARCH_POWER_MISCREGS_HH__ +#define __ARCH_POWER_MISCREGS_HH__ -class CheckAllocateStatementAST : public StatementAST { -public: - // Constructors - CheckAllocateStatementAST(VarExprAST* variable); +#include "base/bitunion.hh" - // Destructor - ~CheckAllocateStatementAST(); - - // Public Methods - void generate(string& code, Type* return_type_ptr) const; - void findResources(Map<Var*, string>& resource_list) const; - void print(ostream& out) const; -private: - // Private Methods +namespace PowerISA +{ - // Private copy constructor and assignment operator - CheckAllocateStatementAST(const CheckAllocateStatementAST& obj); - CheckAllocateStatementAST& operator=(const CheckAllocateStatementAST& obj); +enum MiscRegIndex { + NUM_MISCREGS = 0 +}; - // Data Members (m_ prefix) - VarExprAST* m_variable; +const char * const miscRegName[NUM_MISCREGS] = { }; -// Output operator declaration -ostream& operator<<(ostream& out, const CheckAllocateStatementAST& obj); +BitUnion32(Cr) + Bitfield<31,28> cr0; + Bitfield<27,24> cr1; +EndBitUnion(Cr) -// ******************* Definitions ******************* +BitUnion32(Xer) + Bitfield<31> so; + Bitfield<30> ov; + Bitfield<29> ca; +EndBitUnion(Xer) -// Output operator definition -extern inline -ostream& operator<<(ostream& out, const CheckAllocateStatementAST& obj) -{ - obj.print(out); - out << flush; - return out; -} +BitUnion32(Fpscr) + Bitfield<31> fx; + Bitfield<30> fex; + Bitfield<29> vx; + Bitfield<28> ox; + Bitfield<27> ux; + Bitfield<26> zx; + Bitfield<25> xx; + Bitfield<24> vxsnan; + Bitfield<23> vxisi; + Bitfield<22> vxidi; + Bitfield<21> vxzdz; + Bitfield<20> vximz; + Bitfield<19> vxvc; + Bitfield<18> fr; + Bitfield<17> fi; + SubBitUnion(fprf, 16, 12) + Bitfield<16> c; + SubBitUnion(fpcc, 15, 12) + Bitfield<15> fl; + Bitfield<14> fg; + Bitfield<13> fe; + Bitfield<12> fu; + EndSubBitUnion(fpcc) + EndSubBitUnion(fprf) + Bitfield<10> vxsqrt; + Bitfield<9> vxcvi; + Bitfield<8> ve; + Bitfield<7> oe; + Bitfield<6> ue; + Bitfield<5> ze; + Bitfield<4> xe; + Bitfield<3> ni; + Bitfield<2,1> rn; +EndBitUnion(Fpscr) + +}; // PowerISA namespace -#endif //CHECKALLOCATESTATEMENTAST_H +#endif // __ARCH_POWER_MISCREGS_HH__ diff --git a/src/arch/power/mmaped_ipr.hh b/src/arch/power/mmaped_ipr.hh new file mode 100644 index 000000000..bd1ea10b3 --- /dev/null +++ b/src/arch/power/mmaped_ipr.hh @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2006 The Regents of The University of Michigan + * Copyright (c) 2007-2008 The Florida State University + * Copyright (c) 2009 The University of Edinburgh + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Ali Saidi + * Stephen Hines + * Timothy M. Jones + */ + +#ifndef __ARCH_POWER_MMAPED_IPR_HH__ +#define __ARCH_POWER_MMAPED_IPR_HH__ + +/** + * @file + * + * ISA-specific helper functions for memory mapped IPR accesses. + */ + +#include "base/misc.hh" +#include "mem/packet.hh" + +class ThreadContext; + +namespace PowerISA +{ + +inline Tick +handleIprRead(ThreadContext *xc, Packet *pkt) +{ + panic("No implementation for handleIprRead in POWER\n"); +} + +inline Tick +handleIprWrite(ThreadContext *xc, Packet *pkt) +{ + panic("No implementation for handleIprWrite in POWER\n"); +} + +} // PowerISA namespace + +#endif // __ARCH_POWER_MMAPED_IPR_HH__ diff --git a/src/mem/slicc/ast/EnumExprAST.cc b/src/arch/power/pagetable.cc index 0d8af0e9f..862404578 100644 --- a/src/mem/slicc/ast/EnumExprAST.cc +++ b/src/arch/power/pagetable.cc @@ -1,6 +1,8 @@ - /* - * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood + * Copyright (c) 2002-2005 The Regents of The University of Michigan + * Copyright (c) 2007 MIPS Technologies, Inc. + * Copyright (c) 2007-2008 The Florida State University + * Copyright (c) 2009 The University of Edinburgh * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -25,52 +27,56 @@ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/* - * EnumExprAST.C - * - * Description: See EnumExprAST.hh - * - * $Id: EnumExprAST.C,v 3.1 2003/07/10 18:08:06 milo Exp $ * + * Authors: Nathan Binkert + * Steve Reinhardt + * Jaidev Patwardhan + * Stephen Hines + * Timothy M. Jones */ -#include "mem/slicc/ast/EnumExprAST.hh" +#include "arch/power/pagetable.hh" +#include "sim/serialize.hh" -EnumExprAST::EnumExprAST(TypeAST* type_ast_ptr, - string* value_ptr) - : ExprAST() +namespace PowerISA { - assert(value_ptr != NULL); - assert(type_ast_ptr != NULL); - m_type_ast_ptr = type_ast_ptr; - m_value_ptr = value_ptr; -} -EnumExprAST::~EnumExprAST() +void +PTE::serialize(std::ostream &os) { - delete m_type_ast_ptr; - delete m_value_ptr; + SERIALIZE_SCALAR(Mask); + SERIALIZE_SCALAR(VPN); + SERIALIZE_SCALAR(asid); + SERIALIZE_SCALAR(G); + SERIALIZE_SCALAR(PFN0); + SERIALIZE_SCALAR(D0); + SERIALIZE_SCALAR(V0); + SERIALIZE_SCALAR(C0); + SERIALIZE_SCALAR(PFN1); + SERIALIZE_SCALAR(D1); + SERIALIZE_SCALAR(V1); + SERIALIZE_SCALAR(C1); + SERIALIZE_SCALAR(AddrShiftAmount); + SERIALIZE_SCALAR(OffsetMask); } -Type* EnumExprAST::generate(string& code) const +void +PTE::unserialize(Checkpoint *cp, const std::string §ion) { - Type* type_ptr = m_type_ast_ptr->lookupType(); - code += type_ptr->cIdent() + "_" + (*m_value_ptr); - - // Make sure the enumeration value exists - if (!type_ptr->enumExist(*m_value_ptr)) { - error("Type '" + m_type_ast_ptr->toString() + "' does not have enumeration '" + *m_value_ptr + "'"); - } - - // Return the proper type - return type_ptr; + UNSERIALIZE_SCALAR(Mask); + UNSERIALIZE_SCALAR(VPN); + UNSERIALIZE_SCALAR(asid); + UNSERIALIZE_SCALAR(G); + UNSERIALIZE_SCALAR(PFN0); + UNSERIALIZE_SCALAR(D0); + UNSERIALIZE_SCALAR(V0); + UNSERIALIZE_SCALAR(C0); + UNSERIALIZE_SCALAR(PFN1); + UNSERIALIZE_SCALAR(D1); + UNSERIALIZE_SCALAR(V1); + UNSERIALIZE_SCALAR(C1); + UNSERIALIZE_SCALAR(AddrShiftAmount); + UNSERIALIZE_SCALAR(OffsetMask); } -void EnumExprAST::print(ostream& out) const -{ - string str; - str += m_type_ast_ptr->toString()+":"+(*m_value_ptr); - out << "[EnumExpr: " << str << "]"; -} +} // PowerISA namespace diff --git a/src/arch/power/pagetable.hh b/src/arch/power/pagetable.hh new file mode 100644 index 000000000..bd2b9d397 --- /dev/null +++ b/src/arch/power/pagetable.hh @@ -0,0 +1,158 @@ +/* + * Copyright (c) 2002-2005 The Regents of The University of Michigan + * Copyright (c) 2007 MIPS Technologies, Inc. + * Copyright (c) 2007-2008 The Florida State University + * Copyright (c) 2009 The University of Edinburgh + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Nathan Binkert + * Steve Reinhardt + * Jaidev Patwardhan + * Stephen Hines + * Timothy M. Jones + */ + +#ifndef __ARCH_POWER_PAGETABLE_H__ +#define __ARCH_POWER_PAGETABLE_H__ + +#include "arch/power/isa_traits.hh" +#include "arch/power/utility.hh" +#include "arch/power/vtophys.hh" +#include "config/full_system.hh" + +namespace PowerISA { + +struct VAddr +{ + static const int ImplBits = 43; + static const Addr ImplMask = (ULL(1) << ImplBits) - 1; + static const Addr UnImplMask = ~ImplMask; + + Addr addr; + + VAddr(Addr a) + : addr(a) + {} + + operator Addr() const + { + return addr; + } + + const VAddr + &operator=(Addr a) + { + addr = a; + return *this; + } + + Addr + vpn() const + { + return (addr & ImplMask) >> PageShift; + } + + Addr + page() const + { + return addr & Page_Mask; + } + + Addr + offset() const + { + return addr & PageOffset; + } + + Addr + level3() const + { + return PowerISA::PteAddr(addr >> PageShift); + } + + Addr + level2() const + { + return PowerISA::PteAddr(addr >> (NPtePageShift + PageShift)); + } + + Addr + level1() const + { + return PowerISA::PteAddr(addr >> (2 * NPtePageShift + PageShift)); + } +}; + +// ITB/DTB page table entry +struct PTE +{ + // What parts of the VAddr (from bits 28..11) should be used in + // translation (includes Mask and MaskX from PageMask) + Addr Mask; + + // Virtual Page Number (/2) (Includes VPN2 + VPN2X .. bits 31..11 + // from EntryHi) + Addr VPN; + + // Address Space ID (8 bits) // Lower 8 bits of EntryHi + uint8_t asid; + + // Global Bit - Obtained by an *AND* of EntryLo0 and EntryLo1 G bit + bool G; + + /* Contents of Entry Lo0 */ + Addr PFN0; // Physical Frame Number - Even + bool D0; // Even entry Dirty Bit + bool V0; // Even entry Valid Bit + uint8_t C0; // Cache Coherency Bits - Even + + /* Contents of Entry Lo1 */ + Addr PFN1; // Physical Frame Number - Odd + bool D1; // Odd entry Dirty Bit + bool V1; // Odd entry Valid Bit + uint8_t C1; // Cache Coherency Bits (3 bits) + + // The next few variables are put in as optimizations to reduce TLB + // lookup overheads. For a given Mask, what is the address shift amount + // and what is the OffsetMask + int AddrShiftAmount; + int OffsetMask; + + bool + Valid() + { + return (V0 | V1); + }; + + void serialize(std::ostream &os); + + void unserialize(Checkpoint *cp, const std::string §ion); +}; + +} // PowerISA namespace + +#endif // __ARCH_POWER_PAGETABLE_H__ + diff --git a/src/arch/power/predecoder.hh b/src/arch/power/predecoder.hh new file mode 100644 index 000000000..1f3ac41cb --- /dev/null +++ b/src/arch/power/predecoder.hh @@ -0,0 +1,121 @@ +/* + * Copyright (c) 2006 The Regents of The University of Michigan + * Copyright (c) 2007-2008 The Florida State University + * Copyright (c) 2009 The University of Edinburgh + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Gabe Black + * Stephen Hines + * Timothy M. Jones + */ + +#ifndef __ARCH_ARM_PREDECODER_HH__ +#define __ARCH_ARM_PREDECODER_HH__ + +#include "arch/power/types.hh" +#include "base/misc.hh" +#include "base/types.hh" + +class ThreadContext; + +namespace PowerISA +{ + +class Predecoder +{ + protected: + ThreadContext * tc; + + // The extended machine instruction being generated + ExtMachInst emi; + + public: + Predecoder(ThreadContext * _tc) + : tc(_tc) + { + } + + ThreadContext * + getTC() + { + return tc; + } + + void + setTC(ThreadContext * _tc) + { + tc = _tc; + } + + void + process() + { + } + + void + reset() + { + } + + // Use this to give data to the predecoder. This should be used + // when there is control flow. + void + moreBytes(Addr pc, Addr fetchPC, MachInst inst) + { + emi = inst; + } + + // Use this to give data to the predecoder. This should be used + // when instructions are executed in order. + void + moreBytes(MachInst machInst) + { + moreBytes(0, 0, machInst); + } + + bool + needMoreBytes() + { + return true; + } + + bool + extMachInstReady() + { + return true; + } + + // This returns a constant reference to the ExtMachInst to avoid a copy + const ExtMachInst & + getExtMachInst() + { + return emi; + } +}; + +} // PowerISA namespace + +#endif // __ARCH_POWER_PREDECODER_HH__ diff --git a/src/arch/power/process.cc b/src/arch/power/process.cc new file mode 100644 index 000000000..92f993e4c --- /dev/null +++ b/src/arch/power/process.cc @@ -0,0 +1,288 @@ +/* + * Copyright (c) 2007-2008 The Florida State University + * Copyright (c) 2009 The University of Edinburgh + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Stephen Hines + * Timothy M. Jones + */ + +#include "arch/power/isa_traits.hh" +#include "arch/power/process.hh" +#include "arch/power/types.hh" +#include "base/loader/elf_object.hh" +#include "base/loader/object_file.hh" +#include "base/misc.hh" +#include "cpu/thread_context.hh" +#include "mem/page_table.hh" +#include "mem/translating_port.hh" +#include "sim/process_impl.hh" +#include "sim/system.hh" + +using namespace std; +using namespace PowerISA; + +PowerLiveProcess::PowerLiveProcess(LiveProcessParams *params, + ObjectFile *objFile) + : LiveProcess(params, objFile) +{ + stack_base = 0xbf000000L; + + // Set pointer for next thread stack. Reserve 8M for main stack. + next_thread_stack_base = stack_base - (8 * 1024 * 1024); + + // Set up break point (Top of Heap) + brk_point = objFile->dataBase() + objFile->dataSize() + objFile->bssSize(); + brk_point = roundUp(brk_point, VMPageSize); + + // Set up region for mmaps. For now, start at bottom of kuseg space. + mmap_start = mmap_end = 0x70000000L; +} + +void +PowerLiveProcess::startup() +{ + argsInit(MachineBytes, VMPageSize); +} + +void +PowerLiveProcess::argsInit(int intSize, int pageSize) +{ + typedef AuxVector<uint32_t> auxv_t; + std::vector<auxv_t> auxv; + + string filename; + if (argv.size() < 1) + filename = ""; + else + filename = argv[0]; + + //We want 16 byte alignment + uint64_t align = 16; + + // Overloaded argsInit so that we can fine-tune for POWER architecture + Process::startup(); + + // load object file into target memory + objFile->loadSections(initVirtMem); + + //Setup the auxilliary vectors. These will already have endian conversion. + //Auxilliary vectors are loaded only for elf formatted executables. + ElfObject * elfObject = dynamic_cast<ElfObject *>(objFile); + if (elfObject) { + uint32_t features = 0; + + //Bits which describe the system hardware capabilities + //XXX Figure out what these should be + auxv.push_back(auxv_t(M5_AT_HWCAP, features)); + //The system page size + auxv.push_back(auxv_t(M5_AT_PAGESZ, PowerISA::VMPageSize)); + //Frequency at which times() increments + auxv.push_back(auxv_t(M5_AT_CLKTCK, 0x64)); + // For statically linked executables, this is the virtual address of the + // program header tables if they appear in the executable image + auxv.push_back(auxv_t(M5_AT_PHDR, elfObject->programHeaderTable())); + // This is the size of a program header entry from the elf file. + auxv.push_back(auxv_t(M5_AT_PHENT, elfObject->programHeaderSize())); + // This is the number of program headers from the original elf file. + auxv.push_back(auxv_t(M5_AT_PHNUM, elfObject->programHeaderCount())); + //This is the address of the elf "interpreter", It should be set + //to 0 for regular executables. It should be something else + //(not sure what) for dynamic libraries. + auxv.push_back(auxv_t(M5_AT_BASE, 0)); + + //XXX Figure out what this should be. + auxv.push_back(auxv_t(M5_AT_FLAGS, 0)); + //The entry point to the program + auxv.push_back(auxv_t(M5_AT_ENTRY, objFile->entryPoint())); + //Different user and group IDs + auxv.push_back(auxv_t(M5_AT_UID, uid())); + auxv.push_back(auxv_t(M5_AT_EUID, euid())); + auxv.push_back(auxv_t(M5_AT_GID, gid())); + auxv.push_back(auxv_t(M5_AT_EGID, egid())); + //Whether to enable "secure mode" in the executable + auxv.push_back(auxv_t(M5_AT_SECURE, 0)); + //The filename of the program + auxv.push_back(auxv_t(M5_AT_EXECFN, 0)); + //The string "v51" with unknown meaning + auxv.push_back(auxv_t(M5_AT_PLATFORM, 0)); + } + + //Figure out how big the initial stack nedes to be + + // A sentry NULL void pointer at the top of the stack. + int sentry_size = intSize; + + string platform = "v51"; + int platform_size = platform.size() + 1; + + // The aux vectors are put on the stack in two groups. The first group are + // the vectors that are generated as the elf is loaded. The second group + // are the ones that were computed ahead of time and include the platform + // string. + int aux_data_size = filename.size() + 1; + + int env_data_size = 0; + for (int i = 0; i < envp.size(); ++i) { + env_data_size += envp[i].size() + 1; + } + int arg_data_size = 0; + for (int i = 0; i < argv.size(); ++i) { + arg_data_size += argv[i].size() + 1; + } + + int info_block_size = + sentry_size + env_data_size + arg_data_size + + aux_data_size + platform_size; + + //Each auxilliary vector is two 4 byte words + int aux_array_size = intSize * 2 * (auxv.size() + 1); + + int envp_array_size = intSize * (envp.size() + 1); + int argv_array_size = intSize * (argv.size() + 1); + + int argc_size = intSize; + + //Figure out the size of the contents of the actual initial frame + int frame_size = + info_block_size + + aux_array_size + + envp_array_size + + argv_array_size + + argc_size; + + //There needs to be padding after the auxiliary vector data so that the + //very bottom of the stack is aligned properly. + int partial_size = frame_size; + int aligned_partial_size = roundUp(partial_size, align); + int aux_padding = aligned_partial_size - partial_size; + + int space_needed = frame_size + aux_padding; + + stack_min = stack_base - space_needed; + stack_min = roundDown(stack_min, align); + stack_size = stack_base - stack_min; + + // map memory + pTable->allocate(roundDown(stack_min, pageSize), + roundUp(stack_size, pageSize)); + + // map out initial stack contents + uint32_t sentry_base = stack_base - sentry_size; + uint32_t aux_data_base = sentry_base - aux_data_size; + uint32_t env_data_base = aux_data_base - env_data_size; + uint32_t arg_data_base = env_data_base - arg_data_size; + uint32_t platform_base = arg_data_base - platform_size; + uint32_t auxv_array_base = platform_base - aux_array_size - aux_padding; + uint32_t envp_array_base = auxv_array_base - envp_array_size; + uint32_t argv_array_base = envp_array_base - argv_array_size; + uint32_t argc_base = argv_array_base - argc_size; + + DPRINTF(Stack, "The addresses of items on the initial stack:\n"); + DPRINTF(Stack, "0x%x - aux data\n", aux_data_base); + DPRINTF(Stack, "0x%x - env data\n", env_data_base); + DPRINTF(Stack, "0x%x - arg data\n", arg_data_base); + DPRINTF(Stack, "0x%x - platform base\n", platform_base); + DPRINTF(Stack, "0x%x - auxv array\n", auxv_array_base); + DPRINTF(Stack, "0x%x - envp array\n", envp_array_base); + DPRINTF(Stack, "0x%x - argv array\n", argv_array_base); + DPRINTF(Stack, "0x%x - argc \n", argc_base); + DPRINTF(Stack, "0x%x - stack min\n", stack_min); + + // write contents to stack + + // figure out argc + uint32_t argc = argv.size(); + uint32_t guestArgc = PowerISA::htog(argc); + + //Write out the sentry void * + uint32_t sentry_NULL = 0; + initVirtMem->writeBlob(sentry_base, + (uint8_t*)&sentry_NULL, sentry_size); + + //Fix up the aux vectors which point to other data + for (int i = auxv.size() - 1; i >= 0; i--) { + if (auxv[i].a_type == M5_AT_PLATFORM) { + auxv[i].a_val = platform_base; + initVirtMem->writeString(platform_base, platform.c_str()); + } else if (auxv[i].a_type == M5_AT_EXECFN) { + auxv[i].a_val = aux_data_base; + initVirtMem->writeString(aux_data_base, filename.c_str()); + } + } + + //Copy the aux stuff + for (int x = 0; x < auxv.size(); x++) + { + initVirtMem->writeBlob(auxv_array_base + x * 2 * intSize, + (uint8_t*)&(auxv[x].a_type), intSize); + initVirtMem->writeBlob(auxv_array_base + (x * 2 + 1) * intSize, + (uint8_t*)&(auxv[x].a_val), intSize); + } + //Write out the terminating zeroed auxilliary vector + const uint64_t zero = 0; + initVirtMem->writeBlob(auxv_array_base + 2 * intSize * auxv.size(), + (uint8_t*)&zero, 2 * intSize); + + copyStringArray(envp, envp_array_base, env_data_base, initVirtMem); + copyStringArray(argv, argv_array_base, arg_data_base, initVirtMem); + + initVirtMem->writeBlob(argc_base, (uint8_t*)&guestArgc, intSize); + + ThreadContext *tc = system->getThreadContext(contextIds[0]); + + //Set the stack pointer register + tc->setIntReg(StackPointerReg, stack_min); + + Addr prog_entry = objFile->entryPoint(); + tc->setPC(prog_entry); + tc->setNextPC(prog_entry + sizeof(MachInst)); + + //Align the "stack_min" to a page boundary. + stack_min = roundDown(stack_min, pageSize); +} + +PowerISA::IntReg +PowerLiveProcess::getSyscallArg(ThreadContext *tc, int &i) +{ + assert(i < 5); + return tc->readIntReg(ArgumentReg0 + i++); +} + +void +PowerLiveProcess::setSyscallArg(ThreadContext *tc, + int i, PowerISA::IntReg val) +{ + assert(i < 5); + tc->setIntReg(ArgumentReg0 + i, val); +} + +void +PowerLiveProcess::setSyscallReturn(ThreadContext *tc, + SyscallReturn return_value) +{ + tc->setIntReg(ReturnValueReg, return_value.value()); +} diff --git a/src/arch/power/process.hh b/src/arch/power/process.hh new file mode 100644 index 000000000..ede75f05f --- /dev/null +++ b/src/arch/power/process.hh @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2007-2008 The Florida State University + * Copyright (c) 2009 The University of Edinburgh + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Stephen Hines + * Timothy M. Jones + */ + +#ifndef __POWER_PROCESS_HH__ +#define __POWER_PROCESS_HH__ + +#include <string> +#include <vector> +#include "sim/process.hh" + +class LiveProcess; +class ObjectFile; +class System; + +class PowerLiveProcess : public LiveProcess +{ + protected: + PowerLiveProcess(LiveProcessParams * params, ObjectFile *objFile); + + void startup(); + + public: + void argsInit(int intSize, int pageSize); + PowerISA::IntReg getSyscallArg(ThreadContext *tc, int &i); + void setSyscallArg(ThreadContext *tc, int i, PowerISA::IntReg val); + void setSyscallReturn(ThreadContext *tc, SyscallReturn return_value); +}; + +#endif // __POWER_PROCESS_HH__ + diff --git a/src/arch/power/registers.hh b/src/arch/power/registers.hh new file mode 100644 index 000000000..5bcca3641 --- /dev/null +++ b/src/arch/power/registers.hh @@ -0,0 +1,105 @@ +/* + * Copyright (c) 2009 The University of Edinburgh + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Timothy M. Jones + */ + +#ifndef __ARCH_POWER_REGISTERS_HH__ +#define __ARCH_POWER_REGISTERS_HH__ + +#include "arch/power/max_inst_regs.hh" +#include "arch/power/miscregs.hh" + +namespace PowerISA { + +using PowerISAInst::MaxInstSrcRegs; +using PowerISAInst::MaxInstDestRegs; + +typedef uint8_t RegIndex; + +typedef uint64_t IntReg; + +// Floating point register file entry type +typedef uint64_t FloatRegBits; +typedef double FloatReg; +typedef uint64_t MiscReg; + +// Constants Related to the number of registers +const int NumIntArchRegs = 32; + +// CR, XER, LR, CTR, FPSCR, RSV, RSV-LEN, RSV-ADDR +// and zero register, which doesn't actually exist but needs a number +const int NumIntSpecialRegs = 9; +const int NumFloatArchRegs = 32; +const int NumFloatSpecialRegs = 0; +const int NumInternalProcRegs = 0; + +const int NumIntRegs = NumIntArchRegs + NumIntSpecialRegs; +const int NumFloatRegs = NumFloatArchRegs + NumFloatSpecialRegs; +const int NumMiscRegs = NUM_MISCREGS; + +// Semantically meaningful register indices +const int ReturnValueReg = 3; +const int ArgumentReg0 = 3; +const int ArgumentReg1 = 4; +const int ArgumentReg2 = 5; +const int ArgumentReg3 = 6; +const int ArgumentReg4 = 7; +const int FramePointerReg = 31; +const int StackPointerReg = 1; + +// There isn't one in Power, but we need to define one somewhere +const int ZeroReg = NumIntRegs - 1; + +const int SyscallNumReg = 0; +const int SyscallPseudoReturnReg = 3; +const int SyscallSuccessReg = 3; + +// These help enumerate all the registers for dependence tracking. +const int FP_Base_DepTag = NumIntRegs; +const int Ctrl_Base_DepTag = FP_Base_DepTag + NumFloatRegs; + +typedef union { + IntReg intreg; + FloatReg fpreg; + MiscReg ctrlreg; +} AnyReg; + +enum MiscIntRegNums { + INTREG_CR = NumIntArchRegs, + INTREG_XER, + INTREG_LR, + INTREG_CTR, + INTREG_FPSCR, + INTREG_RSV, + INTREG_RSV_LEN, + INTREG_RSV_ADDR +}; + +} // PowerISA namespace + +#endif // __ARCH_POWER_REGISTERS_HH__ diff --git a/src/mem/slicc/ast/TypeAST.hh b/src/arch/power/remote_gdb.hh index f8e1fdc24..34bb4bd1f 100644 --- a/src/mem/slicc/ast/TypeAST.hh +++ b/src/arch/power/remote_gdb.hh @@ -1,6 +1,7 @@ - /* - * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood + * Copyright (c) 2002-2005 The Regents of The University of Michigan + * Copyright (c) 2007-2008 The Florida State University + * Copyright (c) 2009 The University of Edinburgh * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -25,59 +26,59 @@ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/* - * TypeAST.hh - * - * Description: - * - * $Id: TypeAST.hh,v 3.2 2003/03/22 15:15:17 xu Exp $ * + * Authors: Nathan Binkert + * Stephen Hines + * Timothy M. Jones */ -#ifndef TYPEAST_H -#define TYPEAST_H +#ifndef __ARCH_ARM_REMOTE_GDB_HH__ +#define __ARCH_ARM_REMOTE_GDB_HH__ -#include "mem/slicc/slicc_global.hh" -#include "mem/slicc/ast/AST.hh" +#include "base/remote_gdb.hh" -class TypeAST : public AST { -public: - // Constructors - TypeAST(string* ident_ptr); - - // Destructor - ~TypeAST(); +namespace PowerISA +{ - // Public Methods - string toString() const; - Type* lookupType() const; +class RemoteGDB : public BaseRemoteGDB +{ + public: + RemoteGDB(System *system, ThreadContext *context) + : BaseRemoteGDB(system, context, 1) + { + } - virtual void print(ostream& out) const {} -private: - // Private Methods + bool + acc(Addr, size_t) + { + panic("acc not implemented for POWER!"); + } - // Private copy constructor and assignment operator - TypeAST(const TypeAST& obj); - TypeAST& operator=(const TypeAST& obj); + void + getregs() + { + panic("getregs not implemented for POWER!"); + } - // Data Members (m_ prefix) - string* m_ident_ptr; -}; + void + setregs() + { + panic("setregs not implemented for POWER!"); + } -// Output operator declaration -ostream& operator<<(ostream& out, const TypeAST& obj); + void + clearSingleStep() + { + panic("clearSingleStep not implemented for POWER!"); + } -// ******************* Definitions ******************* + void + setSingleStep() + { + panic("setSingleStep not implemented for POWER!"); + } +}; -// Output operator definition -extern inline -ostream& operator<<(ostream& out, const TypeAST& obj) -{ - obj.print(out); - out << flush; - return out; -} +} // PowerISA namespace -#endif //TYPEAST_H +#endif /* __ARCH_POWER_REMOTE_GDB_H__ */ diff --git a/src/arch/power/stacktrace.hh b/src/arch/power/stacktrace.hh new file mode 100644 index 000000000..49d687a6e --- /dev/null +++ b/src/arch/power/stacktrace.hh @@ -0,0 +1,148 @@ +/* + * Copyright (c) 2005 The Regents of The University of Michigan + * Copyright (c) 2007-2008 The Florida State University + * Copyright (c) 2009 The University of Edinburgh + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Ali Saidi + * Stephen Hines + * Timothy M. Jones + */ + +#ifndef __ARCH_POWER_STACKTRACE_HH__ +#define __ARCH_POWER_STACKTRACE_HH__ + +#include "base/trace.hh" +#include "cpu/static_inst.hh" + +class ThreadContext; +class StackTrace; + +namespace PowerISA +{ + +class ProcessInfo +{ + private: + ThreadContext *tc; + + int thread_info_size; + int task_struct_size; + int task_off; + int pid_off; + int name_off; + + public: + ProcessInfo(ThreadContext *_tc); + + Addr task(Addr ksp) const; + int pid(Addr ksp) const; + std::string name(Addr ksp) const; +}; + +class StackTrace +{ + protected: + typedef TheISA::MachInst MachInst; + private: + ThreadContext *tc; + std::vector<Addr> stack; + + private: + bool isEntry(Addr addr); + bool decodePrologue(Addr sp, Addr callpc, Addr func, int &size, Addr &ra); + bool decodeSave(MachInst inst, int ®, int &disp); + bool decodeStack(MachInst inst, int &disp); + + void trace(ThreadContext *tc, bool is_call); + + public: + StackTrace(); + StackTrace(ThreadContext *tc, StaticInstPtr inst); + ~StackTrace(); + + void + clear() + { + tc = 0; + stack.clear(); + } + + bool + valid() const + { + return tc != NULL; + } + + bool trace(ThreadContext *tc, StaticInstPtr inst); + + public: + const std::vector<Addr> & + getstack() const + { + return stack; + } + + static const int user = 1; + static const int console = 2; + static const int unknown = 3; + +#if TRACING_ON + private: + void dump(); + + public: + void + dprintf() + { + if (DTRACE(Stack)) + dump(); + } +#else + public: + void + dprintf() + { + } +#endif +}; + +inline bool +StackTrace::trace(ThreadContext *tc, StaticInstPtr inst) +{ + if (!inst->isCall() && !inst->isReturn()) + return false; + + if (valid()) + clear(); + + trace(tc, !inst->isReturn()); + return true; +} + +} // PowerISA namespace + +#endif // __ARCH_POWER_STACKTRACE_HH__ diff --git a/src/arch/power/tlb.cc b/src/arch/power/tlb.cc new file mode 100644 index 000000000..125c92a1a --- /dev/null +++ b/src/arch/power/tlb.cc @@ -0,0 +1,322 @@ +/* + * Copyright (c) 2001-2005 The Regents of The University of Michigan + * Copyright (c) 2007 MIPS Technologies, Inc. + * Copyright (c) 2007-2008 The Florida State University + * Copyright (c) 2009 The University of Edinburgh + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Nathan Binkert + * Steve Reinhardt + * Jaidev Patwardhan + * Stephen Hines + * Timothy M. Jones + */ + +#include <string> +#include <vector> + +#include "arch/power/faults.hh" +#include "arch/power/pagetable.hh" +#include "arch/power/tlb.hh" +#include "arch/power/utility.hh" +#include "base/inifile.hh" +#include "base/str.hh" +#include "base/trace.hh" +#include "cpu/thread_context.hh" +#include "mem/page_table.hh" +#include "params/PowerTLB.hh" +#include "sim/process.hh" + + +using namespace std; +using namespace PowerISA; + +/////////////////////////////////////////////////////////////////////// +// +// POWER TLB +// + +#define MODE2MASK(X) (1 << (X)) + +TLB::TLB(const Params *p) + : BaseTLB(p), size(p->size), nlu(0) +{ + table = new PowerISA::PTE[size]; + memset(table, 0, sizeof(PowerISA::PTE[size])); + smallPages = 0; +} + +TLB::~TLB() +{ + if (table) + delete [] table; +} + +// look up an entry in the TLB +PowerISA::PTE * +TLB::lookup(Addr vpn, uint8_t asn) const +{ + // assume not found... + PowerISA::PTE *retval = NULL; + PageTable::const_iterator i = lookupTable.find(vpn); + if (i != lookupTable.end()) { + while (i->first == vpn) { + int index = i->second; + PowerISA::PTE *pte = &table[index]; + Addr Mask = pte->Mask; + Addr InvMask = ~Mask; + Addr VPN = pte->VPN; + if (((vpn & InvMask) == (VPN & InvMask)) + && (pte->G || (asn == pte->asid))) { + + // We have a VPN + ASID Match + retval = pte; + break; + } + ++i; + } + } + + DPRINTF(TLB, "lookup %#x, asn %#x -> %s ppn %#x\n", vpn, (int)asn, + retval ? "hit" : "miss", retval ? retval->PFN1 : 0); + return retval; +} + +PowerISA::PTE* +TLB::getEntry(unsigned Index) const +{ + // Make sure that Index is valid + assert(Index<size); + return &table[Index]; +} + +int +TLB::probeEntry(Addr vpn,uint8_t asn) const +{ + // assume not found... + PowerISA::PTE *retval = NULL; + int Ind = -1; + PageTable::const_iterator i = lookupTable.find(vpn); + if (i != lookupTable.end()) { + while (i->first == vpn) { + int index = i->second; + PowerISA::PTE *pte = &table[index]; + Addr Mask = pte->Mask; + Addr InvMask = ~Mask; + Addr VPN = pte->VPN; + if (((vpn & InvMask) == (VPN & InvMask)) + && (pte->G || (asn == pte->asid))) { + + // We have a VPN + ASID Match + retval = pte; + Ind = index; + break; + } + ++i; + } + } + + DPRINTF(Power, "VPN: %x, asid: %d, Result of TLBP: %d\n", vpn, asn, Ind); + return Ind; +} + +inline Fault +TLB::checkCacheability(RequestPtr &req) +{ + Addr VAddrUncacheable = 0xA0000000; + if ((req->getVaddr() & VAddrUncacheable) == VAddrUncacheable) { + + // mark request as uncacheable + req->setFlags(Request::UNCACHEABLE); + } + return NoFault; +} + +void +TLB::insertAt(PowerISA::PTE &pte, unsigned Index, int _smallPages) +{ + smallPages=_smallPages; + if (Index > size){ + warn("Attempted to write at index (%d) beyond TLB size (%d)", + Index, size); + } else { + + // Update TLB + if (table[Index].V0 == true || table[Index].V1 == true) { + + // Previous entry is valid + PageTable::iterator i = lookupTable.find(table[Index].VPN); + lookupTable.erase(i); + } + table[Index]=pte; + + // Update fast lookup table + lookupTable.insert(make_pair(table[Index].VPN, Index)); + } +} + +// insert a new TLB entry +void +TLB::insert(Addr addr, PowerISA::PTE &pte) +{ + fatal("TLB Insert not yet implemented\n"); +} + +void +TLB::flushAll() +{ + DPRINTF(TLB, "flushAll\n"); + memset(table, 0, sizeof(PowerISA::PTE[size])); + lookupTable.clear(); + nlu = 0; +} + +void +TLB::serialize(ostream &os) +{ + SERIALIZE_SCALAR(size); + SERIALIZE_SCALAR(nlu); + + for (int i = 0; i < size; i++) { + nameOut(os, csprintf("%s.PTE%d", name(), i)); + table[i].serialize(os); + } +} + +void +TLB::unserialize(Checkpoint *cp, const string §ion) +{ + UNSERIALIZE_SCALAR(size); + UNSERIALIZE_SCALAR(nlu); + + for (int i = 0; i < size; i++) { + table[i].unserialize(cp, csprintf("%s.PTE%d", section, i)); + if (table[i].V0 || table[i].V1) { + lookupTable.insert(make_pair(table[i].VPN, i)); + } + } +} + +void +TLB::regStats() +{ + read_hits + .name(name() + ".read_hits") + .desc("DTB read hits") + ; + + read_misses + .name(name() + ".read_misses") + .desc("DTB read misses") + ; + + + read_accesses + .name(name() + ".read_accesses") + .desc("DTB read accesses") + ; + + write_hits + .name(name() + ".write_hits") + .desc("DTB write hits") + ; + + write_misses + .name(name() + ".write_misses") + .desc("DTB write misses") + ; + + + write_accesses + .name(name() + ".write_accesses") + .desc("DTB write accesses") + ; + + hits + .name(name() + ".hits") + .desc("DTB hits") + ; + + misses + .name(name() + ".misses") + .desc("DTB misses") + ; + + invalids + .name(name() + ".invalids") + .desc("DTB access violations") + ; + + accesses + .name(name() + ".accesses") + .desc("DTB accesses") + ; + + hits = read_hits + write_hits; + misses = read_misses + write_misses; + accesses = read_accesses + write_accesses; +} + +Fault +TLB::translateAtomic(RequestPtr req, ThreadContext *tc, Mode mode) +{ +#if !FULL_SYSTEM + Process * p = tc->getProcessPtr(); + + Fault fault = p->pTable->translate(req); + if (fault != NoFault) + return fault; + + return NoFault; +#else + fatal("translate atomic not yet implemented\n"); +#endif +} + +void +TLB::translateTiming(RequestPtr req, ThreadContext *tc, + Translation *translation, Mode mode) +{ + assert(translation); + translation->finish(translateAtomic(req, tc, mode), req, tc, mode); +} + +PowerISA::PTE & +TLB::index(bool advance) +{ + PowerISA::PTE *pte = &table[nlu]; + + if (advance) + nextnlu(); + + return *pte; +} + +PowerISA::TLB * +PowerTLBParams::create() +{ + return new PowerISA::TLB(this); +} diff --git a/src/arch/power/tlb.hh b/src/arch/power/tlb.hh new file mode 100644 index 000000000..8b6c7233d --- /dev/null +++ b/src/arch/power/tlb.hh @@ -0,0 +1,171 @@ +/* + * Copyright (c) 2001-2005 The Regents of The University of Michigan + * Copyright (c) 2007 MIPS Technologies, Inc. + * Copyright (c) 2007-2008 The Florida State University + * Copyright (c) 2009 The University of Edinburgh + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Nathan Binkert + * Steve Reinhardt + * Stephen Hines + * Timothy M. Jones + */ + +#ifndef __ARCH_POWER_TLB_HH__ +#define __ARCH_POWER_TLB_HH__ + +#include <map> + +#include "arch/power/isa_traits.hh" +#include "arch/power/utility.hh" +#include "arch/power/vtophys.hh" +#include "arch/power/pagetable.hh" +#include "base/statistics.hh" +#include "mem/request.hh" +#include "params/PowerTLB.hh" +#include "sim/faults.hh" +#include "sim/tlb.hh" + +class ThreadContext; + +namespace PowerISA { + +// This is copied from the ARM ISA and has not been checked against the +// Power at all. +struct TlbEntry +{ + Addr _pageStart; + + TlbEntry() + { + } + + TlbEntry(Addr asn, Addr vaddr, Addr paddr) + : _pageStart(paddr) + { + } + + void + updateVaddr(Addr new_vaddr) + { + panic("unimplemented"); + } + + Addr + pageStart() + { + return _pageStart; + } + + void + serialize(std::ostream &os) + { + SERIALIZE_SCALAR(_pageStart); + } + + void + unserialize(Checkpoint *cp, const std::string §ion) + { + UNSERIALIZE_SCALAR(_pageStart); + } +}; + +class TLB : public BaseTLB +{ + protected: + typedef std::multimap<Addr, int> PageTable; + PageTable lookupTable; // Quick lookup into page table + + PowerISA::PTE *table; // the Page Table + int size; // TLB Size + int nlu; // not last used entry (for replacement) + + void + nextnlu() + { + if (++nlu >= size) { + nlu = 0; + } + } + + PowerISA::PTE *lookup(Addr vpn, uint8_t asn) const; + + mutable Stats::Scalar read_hits; + mutable Stats::Scalar read_misses; + mutable Stats::Scalar read_acv; + mutable Stats::Scalar read_accesses; + mutable Stats::Scalar write_hits; + mutable Stats::Scalar write_misses; + mutable Stats::Scalar write_acv; + mutable Stats::Scalar write_accesses; + Stats::Formula hits; + Stats::Formula misses; + Stats::Formula invalids; + Stats::Formula accesses; + + public: + typedef PowerTLBParams Params; + TLB(const Params *p); + virtual ~TLB(); + + int probeEntry(Addr vpn,uint8_t) const; + PowerISA::PTE *getEntry(unsigned) const; + + int smallPages; + + int + getsize() const + { + return size; + } + + PowerISA::PTE &index(bool advance = true); + void insert(Addr vaddr, PowerISA::PTE &pte); + void insertAt(PowerISA::PTE &pte, unsigned Index, int _smallPages); + void flushAll(); + + void + demapPage(Addr vaddr, uint64_t asn) + { + panic("demapPage unimplemented.\n"); + } + + // static helper functions... really + static bool validVirtualAddress(Addr vaddr); + static Fault checkCacheability(RequestPtr &req); + Fault translateAtomic(RequestPtr req, ThreadContext *tc, Mode mode); + void translateTiming(RequestPtr req, ThreadContext *tc, + Translation *translation, Mode mode); + + // Checkpointing + void serialize(std::ostream &os); + void unserialize(Checkpoint *cp, const std::string §ion); + void regStats(); +}; + +} // PowerISA namespace + +#endif // __ARCH_POWER_TLB_HH__ diff --git a/src/mem/slicc/ast/ExprAST.hh b/src/arch/power/types.hh index 9566541da..7b994adc9 100644 --- a/src/mem/slicc/ast/ExprAST.hh +++ b/src/arch/power/types.hh @@ -1,6 +1,5 @@ - /* - * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood + * Copyright (c) 2009 The University of Edinburgh * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -25,60 +24,68 @@ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/* - * ExprAST.hh - * - * Description: - * - * $Id$ * + * Authors: Timothy M. Jones */ -#ifndef EXPRAST_H -#define EXPRAST_H +#ifndef __ARCH_POWER_TYPES_HH__ +#define __ARCH_POWER_TYPES_HH__ -#include "mem/slicc/slicc_global.hh" -#include "mem/slicc/ast/AST.hh" +#include "base/bitunion.hh" +#include "base/types.hh" +namespace PowerISA +{ -class ExprAST : public AST { -public: - // Constructors - ExprAST() : AST() { } +typedef uint32_t MachInst; - // Destructor - virtual ~ExprAST() { } +BitUnion32(ExtMachInst) - // Public Methods - virtual Type* generate(string& code) const = 0; - virtual void findResources(Map<Var*, string>& resource_list) const {} // The default is no resources + // Registers + Bitfield<25, 21> rs; + Bitfield<20, 16> ra; - // void print(ostream& out) const; -private: - // Private Methods + // Shifts and masks + Bitfield<15, 11> sh; + Bitfield<10, 6> mb; + Bitfield< 5, 1> me; - // Private copy constructor and assignment operator - // ExprAST(const ExprAST& obj); - // ExprAST& operator=(const ExprAST& obj); + // Immediate fields + Bitfield<15, 0> si; + Bitfield<15, 0> d; - // Data Members (m_ prefix) + // Special purpose register identifier + Bitfield<20, 11> spr; + Bitfield<25, 2> li; + Bitfield<1> aa; + Bitfield<25, 23> bf; + Bitfield<15, 2> bd; + Bitfield<25, 21> bo; + Bitfield<20, 16> bi; + Bitfield<20, 18> bfa; -}; + // Record bits + Bitfield<0> rc31; + Bitfield<10> oe; -// Output operator declaration -ostream& operator<<(ostream& out, const ExprAST& obj); + // Condition register fields + Bitfield<25, 21> bt; + Bitfield<20, 16> ba; + Bitfield<15, 11> bb; -// ******************* Definitions ******************* + // FXM field for mtcrf instruction + Bitfield<19, 12> fxm; +EndBitUnion(ExtMachInst) -// Output operator definition -extern inline -ostream& operator<<(ostream& out, const ExprAST& obj) -{ - obj.print(out); - out << flush; - return out; -} +// typedef uint64_t LargestRead; +// // Need to use 64 bits to make sure that read requests get handled properly + +// typedef int RegContextParam; +// typedef int RegContextVal; + +struct CoreSpecific { +}; + +} // PowerISA namspace -#endif //EXPRAST_H +#endif // __ARCH_POWER_TYPES_HH__ diff --git a/src/arch/power/utility.hh b/src/arch/power/utility.hh new file mode 100644 index 000000000..442075aa2 --- /dev/null +++ b/src/arch/power/utility.hh @@ -0,0 +1,118 @@ +/* + * Copyright (c) 2003-2005 The Regents of The University of Michigan + * Copyright (c) 2007-2008 The Florida State University + * Copyright (c) 2009 The University of Edinburgh + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Korey Sewell + * Stephen Hines + * Timothy M. Jones + */ + +#ifndef __ARCH_POWER_UTILITY_HH__ +#define __ARCH_POWER_UTILITY_HH__ + +#include "arch/power/miscregs.hh" +#include "arch/power/types.hh" +#include "base/hashmap.hh" +#include "base/types.hh" +#include "cpu/thread_context.hh" + +namespace __hash_namespace { + +template<> +struct hash<PowerISA::ExtMachInst> : public hash<uint32_t> { + size_t operator()(const PowerISA::ExtMachInst &emi) const { + return hash<uint32_t>::operator()((uint32_t)emi); + }; +}; + +} // __hash_namespace namespace + +namespace PowerISA { + +/** + * Function to ensure ISA semantics about 0 registers. + * @param tc The thread context. + */ +template <class TC> +void zeroRegisters(TC *tc); + +// Instruction address compression hooks +static inline Addr +realPCToFetchPC(const Addr &addr) +{ + return addr; +} + +static inline Addr +fetchPCToRealPC(const Addr &addr) +{ + return addr; +} + +// the size of "fetched" instructions +static inline size_t +fetchInstSize() +{ + return sizeof(MachInst); +} + +static inline MachInst +makeRegisterCopy(int dest, int src) +{ + panic("makeRegisterCopy not implemented"); + return 0; +} + +inline void +startupCPU(ThreadContext *tc, int cpuId) +{ + tc->activate(0); +} + +template <class XC> +Fault +checkFpEnableFault(XC *xc) +{ + return NoFault; +} + +static inline void +copyRegs(ThreadContext *src, ThreadContext *dest) +{ + panic("Copy Regs Not Implemented Yet\n"); +} + +static inline void +copyMiscRegs(ThreadContext *src, ThreadContext *dest) +{ + panic("Copy Misc. Regs Not Implemented Yet\n"); +} + +} // PowerISA namespace + +#endif // __ARCH_POWER_UTILITY_HH__ diff --git a/src/arch/power/vtophys.hh b/src/arch/power/vtophys.hh new file mode 100644 index 000000000..3cfebcfc7 --- /dev/null +++ b/src/arch/power/vtophys.hh @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2002-2005 The Regents of The University of Michigan + * Copyright (c) 2007-2008 The Florida State University + * Copyright (c) 2009 The University of Edinburgh + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Ali Saidi + * Nathan Binkert + * Stephen Hines + * Timothy M. Jones + */ + +#ifndef __ARCH_POWER_VTOPHYS_HH__ +#define __ARCH_POWER_VTOPHYS_HH__ + +#include "arch/power/isa_traits.hh" +#include "arch/power/utility.hh" + + +class ThreadContext; +class FunctionalPort; + +namespace PowerISA { + +inline Addr +PteAddr(Addr a) +{ + return (a & PteMask) << PteShift; +} + +} // PowerISA namespace + +#endif // __ARCH_POWER_VTOPHYS_HH__ + diff --git a/src/arch/sparc/isa/decoder.isa b/src/arch/sparc/isa/decoder.isa index e34ca033f..ce5e34ff0 100644 --- a/src/arch/sparc/isa/decoder.isa +++ b/src/arch/sparc/isa/decoder.isa @@ -226,7 +226,8 @@ decode OP default Unknown::unknown() if(Rs2_or_imm13.udw == 0) fault = new DivisionByZero; else Rd = Rs1.udw / Rs2_or_imm13.udw;}}); 0x1E: IntOpCcRes::udivcc({{ - uint32_t resTemp, val2 = Rs2_or_imm13.udw; + uint64_t resTemp; + uint32_t val2 = Rs2_or_imm13.udw; int32_t overflow = 0; if(val2 == 0) fault = new DivisionByZero; else diff --git a/src/arch/sparc/linux/linux.hh b/src/arch/sparc/linux/linux.hh index b1dc691ce..1f7567d43 100644 --- a/src/arch/sparc/linux/linux.hh +++ b/src/arch/sparc/linux/linux.hh @@ -77,6 +77,22 @@ class SparcLinux : public Linux static const int NUM_OPEN_FLAGS; static const unsigned TGT_MAP_ANONYMOUS = 0x20; + + typedef struct { + int64_t uptime; /* Seconds since boot */ + uint64_t loads[3]; /* 1, 5, and 15 minute load averages */ + uint64_t totalram; /* Total usable main memory size */ + uint64_t freeram; /* Available memory size */ + uint64_t sharedram; /* Amount of shared memory */ + uint64_t bufferram; /* Memory used by buffers */ + uint64_t totalswap; /* Total swap space size */ + uint64_t freeswap; /* swap space still available */ + uint16_t procs; /* Number of current processes */ + uint64_t totalhigh; /* Total high memory size */ + uint64_t freehigh; /* Available high memory size */ + uint64_t mem_unit; /* Memory unit size in bytes */ + } tgt_sysinfo; + }; class Sparc32Linux : public SparcLinux @@ -105,6 +121,22 @@ class Sparc32Linux : public SparcLinux uint32_t __unused4; uint32_t __unused5; } tgt_stat64; + + typedef struct { + int32_t uptime; /* Seconds since boot */ + uint32_t loads[3]; /* 1, 5, and 15 minute load averages */ + uint32_t totalram; /* Total usable main memory size */ + uint32_t freeram; /* Available memory size */ + uint32_t sharedram; /* Amount of shared memory */ + uint32_t bufferram; /* Memory used by buffers */ + uint32_t totalswap; /* Total swap space size */ + uint32_t freeswap; /* swap space still available */ + uint16_t procs; /* Number of current processes */ + uint32_t totalhigh; /* Total high memory size */ + uint32_t freehigh; /* Available high memory size */ + uint32_t mem_unit; /* Memory unit size in bytes */ + } tgt_sysinfo; + }; #endif diff --git a/src/arch/sparc/linux/syscalls.cc b/src/arch/sparc/linux/syscalls.cc index f4781d886..874ddc005 100644 --- a/src/arch/sparc/linux/syscalls.cc +++ b/src/arch/sparc/linux/syscalls.cc @@ -41,7 +41,8 @@ static SyscallReturn unameFunc(SyscallDesc *desc, int callnum, LiveProcess *process, ThreadContext *tc) { - TypedBufferArg<Linux::utsname> name(process->getSyscallArg(tc, 0)); + int index = 0; + TypedBufferArg<Linux::utsname> name(process->getSyscallArg(tc, index)); strcpy(name->sysname, "Linux"); strcpy(name->nodename, "m5.eecs.umich.edu"); @@ -59,9 +60,10 @@ SyscallReturn getresuidFunc(SyscallDesc *desc, int num, LiveProcess *p, ThreadContext *tc) { const IntReg id = htog(100); - Addr ruid = p->getSyscallArg(tc, 0); - Addr euid = p->getSyscallArg(tc, 1); - Addr suid = p->getSyscallArg(tc, 2); + int index = 0; + Addr ruid = p->getSyscallArg(tc, index); + Addr euid = p->getSyscallArg(tc, index); + Addr suid = p->getSyscallArg(tc, index); //Handle the EFAULT case //Set the ruid if(ruid) @@ -302,7 +304,7 @@ SyscallDesc SparcLinuxProcess::syscall32Descs[] = { /* 211 */ SyscallDesc("tgkill", unimplementedFunc), //32 bit /* 212 */ SyscallDesc("waitpid", unimplementedFunc), //32 bit /* 213 */ SyscallDesc("swapoff", unimplementedFunc), - /* 214 */ SyscallDesc("sysinfo", unimplementedFunc), //32 bit + /* 214 */ SyscallDesc("sysinfo", sysinfoFunc<Sparc32Linux>), //32 bit /* 215 */ SyscallDesc("ipc", unimplementedFunc), //32 bit /* 216 */ SyscallDesc("sigreturn", unimplementedFunc), //32 bit /* 217 */ SyscallDesc("clone", cloneFunc), @@ -608,7 +610,7 @@ SyscallDesc SparcLinuxProcess::syscallDescs[] = { /* 211 */ SyscallDesc("tgkill", unimplementedFunc), /* 212 */ SyscallDesc("waitpid", unimplementedFunc), /* 213 */ SyscallDesc("swapoff", unimplementedFunc), - /* 214 */ SyscallDesc("sysinfo", unimplementedFunc), + /* 214 */ SyscallDesc("sysinfo", sysinfoFunc<SparcLinux>), /* 215 */ SyscallDesc("ipc", unimplementedFunc), /* 216 */ SyscallDesc("sigreturn", unimplementedFunc), /* 217 */ SyscallDesc("clone", cloneFunc), diff --git a/src/arch/sparc/process.cc b/src/arch/sparc/process.cc index 89e853573..7e01f6b07 100644 --- a/src/arch/sparc/process.cc +++ b/src/arch/sparc/process.cc @@ -514,10 +514,10 @@ void Sparc64LiveProcess::flushWindows(ThreadContext *tc) } IntReg -Sparc32LiveProcess::getSyscallArg(ThreadContext *tc, int i) +Sparc32LiveProcess::getSyscallArg(ThreadContext *tc, int &i) { assert(i < 6); - return bits(tc->readIntReg(FirstArgumentReg + i), 31, 0); + return bits(tc->readIntReg(FirstArgumentReg + i++), 31, 0); } void @@ -528,10 +528,10 @@ Sparc32LiveProcess::setSyscallArg(ThreadContext *tc, int i, IntReg val) } IntReg -Sparc64LiveProcess::getSyscallArg(ThreadContext *tc, int i) +Sparc64LiveProcess::getSyscallArg(ThreadContext *tc, int &i) { assert(i < 6); - return tc->readIntReg(FirstArgumentReg + i); + return tc->readIntReg(FirstArgumentReg + i++); } void diff --git a/src/arch/sparc/process.hh b/src/arch/sparc/process.hh index fdb9734ba..cca312e0a 100644 --- a/src/arch/sparc/process.hh +++ b/src/arch/sparc/process.hh @@ -95,7 +95,7 @@ class Sparc32LiveProcess : public SparcLiveProcess void flushWindows(ThreadContext *tc); - SparcISA::IntReg getSyscallArg(ThreadContext *tc, int i); + SparcISA::IntReg getSyscallArg(ThreadContext *tc, int &i); void setSyscallArg(ThreadContext *tc, int i, SparcISA::IntReg val); }; @@ -123,7 +123,7 @@ class Sparc64LiveProcess : public SparcLiveProcess void flushWindows(ThreadContext *tc); - SparcISA::IntReg getSyscallArg(ThreadContext *tc, int i); + SparcISA::IntReg getSyscallArg(ThreadContext *tc, int &i); void setSyscallArg(ThreadContext *tc, int i, SparcISA::IntReg val); }; diff --git a/src/arch/sparc/solaris/process.cc b/src/arch/sparc/solaris/process.cc index eafb488df..24abd8687 100644 --- a/src/arch/sparc/solaris/process.cc +++ b/src/arch/sparc/solaris/process.cc @@ -48,7 +48,8 @@ static SyscallReturn unameFunc(SyscallDesc *desc, int callnum, LiveProcess *process, ThreadContext *tc) { - TypedBufferArg<Solaris::utsname> name(process->getSyscallArg(tc, 0)); + int index = 0; + TypedBufferArg<Solaris::utsname> name(process->getSyscallArg(tc, index)); strcpy(name->sysname, "SunOS"); strcpy(name->nodename, "m5.eecs.umich.edu"); diff --git a/src/arch/x86/X86TLB.py b/src/arch/x86/X86TLB.py index 15b03fd33..9f7dc43b3 100644 --- a/src/arch/x86/X86TLB.py +++ b/src/arch/x86/X86TLB.py @@ -53,13 +53,14 @@ # # Authors: Gabe Black -from MemObject import MemObject +from m5.defines import buildEnv from m5.params import * from m5.proxy import * -from m5 import build_env + from BaseTLB import BaseTLB +from MemObject import MemObject -if build_env['FULL_SYSTEM']: +if buildEnv['FULL_SYSTEM']: class X86PagetableWalker(MemObject): type = 'X86PagetableWalker' cxx_class = 'X86ISA::Walker' @@ -70,6 +71,6 @@ class X86TLB(BaseTLB): type = 'X86TLB' cxx_class = 'X86ISA::TLB' size = Param.Int(64, "TLB size") - if build_env['FULL_SYSTEM']: + if buildEnv['FULL_SYSTEM']: walker = Param.X86PagetableWalker(\ X86PagetableWalker(), "page table walker") diff --git a/src/arch/x86/interrupts.cc b/src/arch/x86/interrupts.cc index 1b7933036..1b83c6649 100644 --- a/src/arch/x86/interrupts.cc +++ b/src/arch/x86/interrupts.cc @@ -500,7 +500,7 @@ X86ISA::Interrupts::setReg(ApicRegIndex reg, uint32_t val) InterruptCommandRegHigh high = regs[APIC_INTERRUPT_COMMAND_HIGH]; // Record that an IPI is being sent. low.deliveryStatus = 1; - TriggerIntMessage message; + TriggerIntMessage message = 0; message.destination = high.destination; message.vector = low.vector; message.deliveryMode = low.deliveryMode; diff --git a/src/arch/x86/isa.cc b/src/arch/x86/isa.cc index 06a656efc..47d24ed1e 100644 --- a/src/arch/x86/isa.cc +++ b/src/arch/x86/isa.cc @@ -41,7 +41,7 @@ void ISA::updateHandyM5Reg(Efer efer, CR0 cr0, SegAttr csAttr, SegAttr ssAttr, RFLAGS rflags) { - HandyM5Reg m5reg; + HandyM5Reg m5reg = 0; if (efer.lma) { m5reg.mode = LongMode; if (csAttr.longMode) diff --git a/src/arch/x86/isa/decoder/two_byte_opcodes.isa b/src/arch/x86/isa/decoder/two_byte_opcodes.isa index c23eeccab..288c5e5a8 100644 --- a/src/arch/x86/isa/decoder/two_byte_opcodes.isa +++ b/src/arch/x86/isa/decoder/two_byte_opcodes.isa @@ -604,7 +604,7 @@ } // repe (0xF3) 0x4: decode OPCODE_OP_BOTTOM3 { - 0x7: WarnUnimpl::movdqu_Vo_Wo(); + 0x7: MOVDQU(Vo,Wo); default: UD2(); } // operand size (0x66) @@ -615,8 +615,8 @@ 0x3: PACKSSDW(Vo,Wo); 0x4: PUNPCKLQDQ(Vo,Wq); 0x5: PUNPCKHQDQ(Vo,Wq); - 0x6: WarnUnimpl::movd_Vo_Ed(); - 0x7: WarnUnimpl::movdqa_Vo_Wo(); + 0x6: MOVD(Vo,Edp); + 0x7: MOVDQA(Vo,Wo); } default: UD2(); } @@ -673,9 +673,9 @@ //0x3: group14_pshimq(); 0x3: decode MODRM_REG { 0x2: PSRLQ(VRo,Ib); - 0x3: WarnUnimpl::psrldq_VRo_Ib(); + 0x3: PSRLDQ(VRo,Ib); 0x6: PSLLQ(VRo,Ib); - 0x7: WarnUnimpl::pslldq_VRo_Ib(); + 0x7: PSLLDQ(VRo,Ib); default: UD2(); } 0x4: PCMPEQB(Vo,Wo); @@ -702,15 +702,15 @@ // repe (0xF3) 0x4: decode OPCODE_OP_BOTTOM3 { 0x6: MOVQ(Vq,Wq); - 0x7: WarnUnimpl::movdqu_Wo_Vo(); + 0x7: MOVDQU(Wo,Vo); default: UD2(); } // operand size (0x66) 0x1: decode OPCODE_OP_BOTTOM3 { - 0x4: WarnUnimpl::haddpd_Vo_Wo(); + 0x4: HADDPD(Vo,Wo); 0x5: WarnUnimpl::hsubpd_Vo_Wo(); - 0x6: WarnUnimpl::movd_Ed_Vd(); - 0x7: WarnUnimpl::movdqa_Wo_Vo(); + 0x6: MOVD(Edp,Vd); + 0x7: MOVDQA(Wo,Vo); default: UD2(); } // repne (0xF2) diff --git a/src/arch/x86/isa/insts/general_purpose/control_transfer/interrupts_and_exceptions.py b/src/arch/x86/isa/insts/general_purpose/control_transfer/interrupts_and_exceptions.py index a9ad611b7..1c0650683 100644 --- a/src/arch/x86/isa/insts/general_purpose/control_transfer/interrupts_and_exceptions.py +++ b/src/arch/x86/isa/insts/general_purpose/control_transfer/interrupts_and_exceptions.py @@ -62,7 +62,7 @@ def macroop IRET_PROT { .adjust_env oszIn64Override # Check for a nested task. This isn't supported at the moment. - rflag t1, NT + rflag t1, 14; #NT bit panic "Task switching with iret is unimplemented!", flags=(nCEZF,) #t1 = temp_RIP diff --git a/src/arch/x86/isa/insts/general_purpose/data_transfer/move.py b/src/arch/x86/isa/insts/general_purpose/data_transfer/move.py index 7ccdca6c3..51f5ad23b 100644 --- a/src/arch/x86/isa/insts/general_purpose/data_transfer/move.py +++ b/src/arch/x86/isa/insts/general_purpose/data_transfer/move.py @@ -355,6 +355,36 @@ def macroop MOVNTI_P_R { rdip t7 st reg, seg, riprel, disp }; + +def macroop MOVD_XMM_R { + mov2fp xmml, regm, srcSize=dsz, destSize=8 + lfpimm xmmh, 0 +}; + +def macroop MOVD_XMM_M { + ldfp xmml, seg, sib, disp, dataSize=dsz + lfpimm xmmh, 0 +}; + +def macroop MOVD_XMM_P { + rdip t7 + ldfp xmml, seg, riprel, disp, dataSize=dsz + lfpimm xmmh, 0 +}; + +def macroop MOVD_R_XMM { + mov2int reg, xmmlm, size=dsz +}; + +def macroop MOVD_M_XMM { + stfp xmml, seg, sib, disp, dataSize=dsz +}; + +def macroop MOVD_P_XMM { + rdip t7 + stfp xmml, seg, riprel, disp, dataSize=dsz +}; + ''' #let {{ # class MOVD(Inst): diff --git a/src/arch/x86/isa/insts/simd128/floating_point/arithmetic/horizontal_addition.py b/src/arch/x86/isa/insts/simd128/floating_point/arithmetic/horizontal_addition.py index 8b307d3da..adf7650b9 100644 --- a/src/arch/x86/isa/insts/simd128/floating_point/arithmetic/horizontal_addition.py +++ b/src/arch/x86/isa/insts/simd128/floating_point/arithmetic/horizontal_addition.py @@ -55,5 +55,25 @@ microcode = ''' # HADDPS -# HADDPD + +def macroop HADDPD_XMM_XMM { + maddf ufp1, xmmh , xmml, size=8, ext=1 + maddf xmmh, xmmlm, xmmhm, size=8, ext=1 + movfp xmml, ufp1 +}; + +def macroop HADDPD_XMM_M { + ldfp ufp1, seg, sib, disp, dataSize=8 + ldfp ufp2, seg, sib, "DISPLACEMENT+8", dataSize=8 + maddf xmml, xmmh, xmml, size=8, ext=1 + maddf xmmh, ufp1, ufp2, size=8, ext=1 +}; + +def macroop HADDPD_XMM_P { + rdip t7 + ldfp ufp1, seg, riprel, disp, dataSize=8 + ldfp ufp2, seg, riprel, "DISPLACEMENT+8", dataSize=8 + maddf xmml, xmmh, xmml, size=8, ext=1 + maddf xmmh, ufp1, ufp2, size=8, ext=1 +}; ''' diff --git a/src/arch/x86/isa/insts/simd128/floating_point/data_transfer/move.py b/src/arch/x86/isa/insts/simd128/floating_point/data_transfer/move.py index 1f4044bde..86ac89ade 100644 --- a/src/arch/x86/isa/insts/simd128/floating_point/data_transfer/move.py +++ b/src/arch/x86/isa/insts/simd128/floating_point/data_transfer/move.py @@ -168,41 +168,39 @@ def macroop MOVUPD_P_XMM { }; def macroop MOVHPS_XMM_M { - ldfp xmmh, seg, sib, "DISPLACEMENT + 8", dataSize=8 + ldfp xmmh, seg, sib, disp, dataSize=8 }; def macroop MOVHPS_XMM_P { rdip t7 - ldfp xmmh, seg, riprel, "DISPLACEMENT + 8", dataSize=8 + ldfp xmmh, seg, riprel, disp, dataSize=8 }; def macroop MOVHPS_M_XMM { - stfp xmmh, seg, sib, "DISPLACEMENT + 8", dataSize=8 + stfp xmmh, seg, sib, disp, dataSize=8 }; def macroop MOVHPS_P_XMM { rdip t7 - stfp xmml, seg, riprel, "DISPLACEMENT", dataSize=8 - stfp xmmh, seg, riprel, "DISPLACEMENT + 8", dataSize=8 + stfp xmmh, seg, riprel, disp, dataSize=8 }; def macroop MOVHPD_XMM_M { - ldfp xmmh, seg, sib, "DISPLACEMENT + 8", dataSize=8 + ldfp xmmh, seg, sib, disp, dataSize=8 }; def macroop MOVHPD_XMM_P { rdip t7 - ldfp xmmh, seg, riprel, "DISPLACEMENT + 8", dataSize=8 + ldfp xmmh, seg, riprel, disp, dataSize=8 }; def macroop MOVHPD_M_XMM { - stfp xmmh, seg, sib, "DISPLACEMENT + 8", dataSize=8 + stfp xmmh, seg, sib, disp, dataSize=8 }; def macroop MOVHPD_P_XMM { rdip t7 - stfp xmml, seg, riprel, "DISPLACEMENT", dataSize=8 - stfp xmmh, seg, riprel, "DISPLACEMENT + 8", dataSize=8 + stfp xmmh, seg, riprel, disp, dataSize=8 }; def macroop MOVLPS_XMM_M { diff --git a/src/arch/x86/isa/insts/simd128/integer/data_transfer/move.py b/src/arch/x86/isa/insts/simd128/integer/data_transfer/move.py index c34bd42bb..ec80ffe73 100644 --- a/src/arch/x86/isa/insts/simd128/integer/data_transfer/move.py +++ b/src/arch/x86/isa/insts/simd128/integer/data_transfer/move.py @@ -87,7 +87,59 @@ def macroop MOVQ2DQ_XMM_MMX { movfp xmml, mmxm, dataSize=8 lfpimm xmmh, 0 }; + +def macroop MOVDQA_XMM_XMM { + movfp xmml, xmmlm + movfp xmmh, xmmhm +}; + +def macroop MOVDQA_XMM_M { + ldfp xmml, seg, sib, "DISPLACEMENT", dataSize=8 + ldfp xmmh, seg, sib, "DISPLACEMENT + 8", dataSize=8 +}; + +def macroop MOVDQA_XMM_P { + rdip t7 + ldfp xmml, seg, riprel, "DISPLACEMENT", dataSize=8 + ldfp xmmh, seg, riprel, "DISPLACEMENT + 8", dataSize=8 +}; + +def macroop MOVDQA_M_XMM { + stfp xmml, seg, sib, "DISPLACEMENT", dataSize=8 + stfp xmmh, seg, sib, "DISPLACEMENT + 8", dataSize=8 +}; + +def macroop MOVDQA_P_XMM { + rdip t7 + stfp xmml, seg, riprel, "DISPLACEMENT", dataSize=8 + stfp xmmh, seg, riprel, "DISPLACEMENT + 8", dataSize=8 +}; + +def macroop MOVDQU_XMM_XMM { + movfp xmml, xmmlm + movfp xmmh, xmmhm +}; + +def macroop MOVDQU_XMM_M { + ldfp xmml, seg, sib, "DISPLACEMENT", dataSize=8 + ldfp xmmh, seg, sib, "DISPLACEMENT + 8", dataSize=8 +}; + +def macroop MOVDQU_XMM_P { + rdip t7 + ldfp xmml, seg, riprel, "DISPLACEMENT", dataSize=8 + ldfp xmmh, seg, riprel, "DISPLACEMENT + 8", dataSize=8 +}; + +def macroop MOVDQU_M_XMM { + stfp xmml, seg, sib, "DISPLACEMENT", dataSize=8 + stfp xmmh, seg, sib, "DISPLACEMENT + 8", dataSize=8 +}; + +def macroop MOVDQU_P_XMM { + rdip t7 + stfp xmml, seg, riprel, "DISPLACEMENT", dataSize=8 + stfp xmmh, seg, riprel, "DISPLACEMENT + 8", dataSize=8 +}; ''' -# MOVDQA -# MOVDQU # LDDQU diff --git a/src/arch/x86/isa/insts/simd128/integer/shift/left_logical_shift.py b/src/arch/x86/isa/insts/simd128/integer/shift/left_logical_shift.py index 617033bc0..c13c7064c 100644 --- a/src/arch/x86/isa/insts/simd128/integer/shift/left_logical_shift.py +++ b/src/arch/x86/isa/insts/simd128/integer/shift/left_logical_shift.py @@ -122,5 +122,43 @@ def macroop PSLLQ_XMM_I { mslli xmml, xmml, imm, size=8, ext=0 mslli xmmh, xmmh, imm, size=8, ext=0 }; + +def macroop PSLLDQ_XMM_I { + + limm t2, 8 + subi t1, t2, imm, flags=(ECF,), dataSize=1 + br label("pslldq_less_8"), flags=(nCECF,) + + # Greater than 8 + + limm t2, 16 + subi t1, t2, imm, flags=(ECF,), dataSize=1 + br label("pslldq_less_16"), flags=(nCECF,) + + # Greater than 16 + + lfpimm xmml, 0 + lfpimm xmmh, 0 + br label("pslldq_end") + +pslldq_less_16: + + # Between 8 and 16 + + mslli xmmh, xmml, "(IMMEDIATE-8)<<3", size=8, ext=0 + lfpimm xmml, 0 + br label("pslldq_end") + +pslldq_less_8: + + # Less than 8 + + msrli ufp1, xmml, "(8-IMMEDIATE) << 3", size=8, ext=0 + mslli xmmh, xmmh, "IMMEDIATE << 3", size=8, ext=0 + mslli xmml, xmml, "IMMEDIATE << 3", size=8, ext=0 + mor xmmh, xmmh, ufp1 + +pslldq_end: + fault "NoFault" +}; ''' -# PSLLDQ diff --git a/src/arch/x86/isa/insts/simd128/integer/shift/right_logical_shift.py b/src/arch/x86/isa/insts/simd128/integer/shift/right_logical_shift.py index c904eaf50..61efe1a5d 100644 --- a/src/arch/x86/isa/insts/simd128/integer/shift/right_logical_shift.py +++ b/src/arch/x86/isa/insts/simd128/integer/shift/right_logical_shift.py @@ -122,5 +122,41 @@ def macroop PSRLQ_XMM_I { msrli xmml, xmml, imm, size=8, ext=0 msrli xmmh, xmmh, imm, size=8, ext=0 }; + +def macroop PSRLDQ_XMM_I { + limm t2, 8 + subi t1, t2, imm, flags=(ECF,), dataSize=1 + br label("psrldq_less_8"), flags=(nCECF,) + # Greater than 8 + + limm t2, 16 + subi t1, t2, imm, flags=(ECF,), dataSize=1 + br label("psrldq_less_16"), flags=(nCECF,) + + # Greater than 16 + + lfpimm xmml, 0 + lfpimm xmmh, 0 + br label("psrldq_end") + +psrldq_less_16: + + # Between 8 and 16 + + msrli xmml, xmmh, "(IMMEDIATE-8)<<3", size=8, ext=0 + lfpimm xmmh, 0 + br label("psrldq_end") + +psrldq_less_8: + + # Less than 8 + + mslli ufp1, xmmh, "(8-IMMEDIATE) << 3", size=8, ext=0 + msrli xmml, xmml, "IMMEDIATE << 3", size=8, ext=0 + msrli xmmh, xmmh, "IMMEDIATE << 3", size=8, ext=0 + mor xmml, xmml, ufp1 + +psrldq_end: + fault "NoFault" +}; ''' -# PSRLDQ diff --git a/src/arch/x86/isa/insts/system/segmentation.py b/src/arch/x86/isa/insts/system/segmentation.py index b83fcba95..c97f2f152 100644 --- a/src/arch/x86/isa/insts/system/segmentation.py +++ b/src/arch/x86/isa/insts/system/segmentation.py @@ -179,7 +179,8 @@ def macroop LTR_R wrdh t3, t1, t2 wrdl tr, t1, reg wrbase tr, t3, dataSize=8 - ori t1, t1, (1 << 9) + limm t5, (1 << 9) + or t1, t1, t5 st t1, tsg, [8, t4, t0], dataSize=8 }; @@ -195,7 +196,8 @@ def macroop LTR_M wrdh t3, t1, t2 wrdl tr, t1, t5 wrbase tr, t3, dataSize=8 - ori t1, t1, (1 << 9) + limm t5, (1 << 9) + or t1, t1, t5 st t1, tsg, [8, t4, t0], dataSize=8 }; @@ -212,7 +214,8 @@ def macroop LTR_P wrdh t3, t1, t2 wrdl tr, t1, t5 wrbase tr, t3, dataSize=8 - ori t1, t1, (1 << 9) + limm t5, (1 << 9) + or t1, t1, t5 st t1, tsg, [8, t4, t0], dataSize=8 }; diff --git a/src/arch/x86/isa/microops/ldstop.isa b/src/arch/x86/isa/microops/ldstop.isa index 912aa3511..afe1ead59 100644 --- a/src/arch/x86/isa/microops/ldstop.isa +++ b/src/arch/x86/isa/microops/ldstop.isa @@ -157,7 +157,7 @@ def template MicroLoadExecute {{ if (fault == NoFault) { %(code)s; - } else if (memFlags & Request::PF_EXCLUSIVE) { + } else if (memFlags & Request::PREFETCH) { // For prefetches, ignore any faults/exceptions. return NoFault; } @@ -374,7 +374,7 @@ let {{ if atCPL0: self.memFlags += " | (CPL0FlagBit << FlagShift)" if prefetch: - self.memFlags += " | Request::PF_EXCLUSIVE" + self.memFlags += " | Request::PREFETCH" self.memFlags += " | (machInst.legacy.addr ? " + \ "(AddrSizeFlagBit << FlagShift) : 0)" diff --git a/src/arch/x86/isa/microops/mediaop.isa b/src/arch/x86/isa/microops/mediaop.isa index 9c53fa0fb..4052f254d 100644 --- a/src/arch/x86/isa/microops/mediaop.isa +++ b/src/arch/x86/isa/microops/mediaop.isa @@ -452,7 +452,7 @@ let {{ if (signBit) { if (overflow != mask(destBits - srcBits + 1)) { if (ext & 0x1) - picked = (1 << (destBits - 1)); + picked = (ULL(1) << (destBits - 1)); else picked = 0; } @@ -480,7 +480,7 @@ let {{ if (signBit) { if (overflow != mask(destBits - srcBits + 1)) { if (ext & 0x1) - picked = (1 << (destBits - 1)); + picked = (ULL(1) << (destBits - 1)); else picked = 0; } @@ -642,10 +642,10 @@ let {{ int loIndex = (i + 0) * sizeBits; uint64_t arg1Bits = bits(FpSrcReg1.uqw, hiIndex, loIndex); int64_t arg1 = arg1Bits | - (0 - (arg1Bits & (1 << (sizeBits - 1)))); + (0 - (arg1Bits & (ULL(1) << (sizeBits - 1)))); uint64_t arg2Bits = bits(FpSrcReg2.uqw, hiIndex, loIndex); int64_t arg2 = arg2Bits | - (0 - (arg2Bits & (1 << (sizeBits - 1)))); + (0 - (arg2Bits & (ULL(1) << (sizeBits - 1)))); uint64_t resBits; if (ext & 0x2) { @@ -680,10 +680,10 @@ let {{ int loIndex = (i + 0) * sizeBits; uint64_t arg1Bits = bits(FpSrcReg1.uqw, hiIndex, loIndex); int64_t arg1 = arg1Bits | - (0 - (arg1Bits & (1 << (sizeBits - 1)))); + (0 - (arg1Bits & (ULL(1) << (sizeBits - 1)))); uint64_t arg2Bits = bits(FpSrcReg2.uqw, hiIndex, loIndex); int64_t arg2 = arg2Bits | - (0 - (arg2Bits & (1 << (sizeBits - 1)))); + (0 - (arg2Bits & (ULL(1) << (sizeBits - 1)))); uint64_t resBits; if (ext & 0x2) { @@ -957,7 +957,7 @@ let {{ int resSign = bits(resBits, sizeBits - 1); if ((arg1Sign == arg2Sign) && (arg1Sign != resSign)) { if (resSign == 0) - resBits = (1 << (sizeBits - 1)); + resBits = (ULL(1) << (sizeBits - 1)); else resBits = mask(sizeBits - 1); } @@ -996,7 +996,7 @@ let {{ int resSign = bits(resBits, sizeBits - 1); if ((arg1Sign == arg2Sign) && (arg1Sign != resSign)) { if (resSign == 0) - resBits = (1 << (sizeBits - 1)); + resBits = (ULL(1) << (sizeBits - 1)); else resBits = mask(sizeBits - 1); } @@ -1032,16 +1032,16 @@ let {{ if (ext & 0x2) { int64_t arg1 = arg1Bits | - (0 - (arg1Bits & (1 << (srcBits - 1)))); + (0 - (arg1Bits & (ULL(1) << (srcBits - 1)))); int64_t arg2 = arg2Bits | - (0 - (arg2Bits & (1 << (srcBits - 1)))); + (0 - (arg2Bits & (ULL(1) << (srcBits - 1)))); resBits = (uint64_t)(arg1 * arg2); } else { resBits = arg1Bits * arg2Bits; } if (ext & 0x4) - resBits += (1 << (destBits - 1)); + resBits += (ULL(1) << (destBits - 1)); if (ext & 0x8) resBits >>= destBits; @@ -1142,7 +1142,7 @@ let {{ } else { resBits = (arg1Bits >> shiftAmt); resBits = resBits | - (0 - (resBits & (1 << (sizeBits - 1 - shiftAmt)))); + (0 - (resBits & (ULL(1) << (sizeBits - 1 - shiftAmt)))); } result = insertBits(result, hiIndex, loIndex, resBits); @@ -1237,7 +1237,7 @@ let {{ } if (destSize == 4) { - argBits = (uint32_t)(float)arg; + argBits = (uint32_t)arg; } else { argBits = (uint64_t)arg; } @@ -1289,7 +1289,8 @@ let {{ int srcHiIndex = srcStart + (i + 1) * srcSizeBits - 1; int srcLoIndex = srcStart + (i + 0) * srcSizeBits; uint64_t argBits = bits(FpSrcReg1.uqw, srcHiIndex, srcLoIndex); - int64_t sArg = argBits | (0 - (argBits & (1 << srcHiIndex))); + + int64_t sArg = argBits | (0 - (argBits & (ULL(1) << srcHiIndex))); double arg = sArg; if (destSize == 4) { @@ -1400,10 +1401,10 @@ let {{ int loIndex = (i + 0) * sizeBits; uint64_t arg1Bits = bits(FpSrcReg1.uqw, hiIndex, loIndex); int64_t arg1 = arg1Bits | - (0 - (arg1Bits & (1 << (sizeBits - 1)))); + (0 - (arg1Bits & (ULL(1) << (sizeBits - 1)))); uint64_t arg2Bits = bits(FpSrcReg2.uqw, hiIndex, loIndex); int64_t arg2 = arg2Bits | - (0 - (arg2Bits & (1 << (sizeBits - 1)))); + (0 - (arg2Bits & (ULL(1) << (sizeBits - 1)))); uint64_t resBits = 0; if (((ext & 0x2) == 0 && arg1 == arg2) || diff --git a/src/arch/x86/isa/microops/regop.isa b/src/arch/x86/isa/microops/regop.isa index a4cb6f4cc..0b1f9a96a 100644 --- a/src/arch/x86/isa/microops/regop.isa +++ b/src/arch/x86/isa/microops/regop.isa @@ -149,12 +149,12 @@ def template MicroRegOpImmDeclare {{ %(class_name)s(ExtMachInst _machInst, const char * instMnem, bool isMicro, bool isDelayed, bool isFirst, bool isLast, - InstRegIndex _src1, uint16_t _imm8, InstRegIndex _dest, + InstRegIndex _src1, uint8_t _imm8, InstRegIndex _dest, uint8_t _dataSize, uint16_t _ext); %(class_name)s(ExtMachInst _machInst, const char * instMnem, - InstRegIndex _src1, uint16_t _imm8, InstRegIndex _dest, + InstRegIndex _src1, uint8_t _imm8, InstRegIndex _dest, uint8_t _dataSize, uint16_t _ext); %(BasicExecDeclare)s @@ -203,7 +203,7 @@ def template MicroRegOpImmConstructor {{ inline %(class_name)s::%(class_name)s( ExtMachInst machInst, const char * instMnem, - InstRegIndex _src1, uint16_t _imm8, InstRegIndex _dest, + InstRegIndex _src1, uint8_t _imm8, InstRegIndex _dest, uint8_t _dataSize, uint16_t _ext) : %(base_class)s(machInst, "%(mnemonic)s", instMnem, false, false, false, false, @@ -216,7 +216,7 @@ def template MicroRegOpImmConstructor {{ inline %(class_name)s::%(class_name)s( ExtMachInst machInst, const char * instMnem, bool isMicro, bool isDelayed, bool isFirst, bool isLast, - InstRegIndex _src1, uint16_t _imm8, InstRegIndex _dest, + InstRegIndex _src1, uint8_t _imm8, InstRegIndex _dest, uint8_t _dataSize, uint16_t _ext) : %(base_class)s(machInst, "%(mnemonic)s", instMnem, isMicro, isDelayed, isFirst, isLast, @@ -324,11 +324,12 @@ let {{ matcher.sub(src2_name, flag_code), matcher.sub(src2_name, cond_check), matcher.sub(src2_name, else_code)) + imm_name = "%simm8" % match.group("prefix") self.buildCppClasses(name + "i", Name, suffix + "Imm", - matcher.sub("imm8", code), - matcher.sub("imm8", flag_code), - matcher.sub("imm8", cond_check), - matcher.sub("imm8", else_code)) + matcher.sub(imm_name, code), + matcher.sub(imm_name, flag_code), + matcher.sub(imm_name, cond_check), + matcher.sub(imm_name, else_code)) return # If there's something optional to do with flags, generate @@ -353,13 +354,16 @@ let {{ matcher = re.compile("(?<!\w)spsrc2(?!\w)") if matcher.search(allCode): code = "int64_t spsrc2 = signedPick(SrcReg2, 1, dataSize);" + code + matcher = re.compile("(?<!\w)simm8(?!\w)") + if matcher.search(allCode): + code = "int8_t simm8 = imm8;" + code base = "X86ISA::RegOp" # If imm8 shows up in the code, use the immediate templates, if # not, hopefully the register ones will be correct. templates = regTemplates - matcher = re.compile("(?<!\w)imm8(?!\w)") + matcher = re.compile("(?<!\w)s?imm8(?!\w)") if matcher.search(allCode): base += "Imm" templates = immTemplates @@ -521,7 +525,7 @@ let {{ code = ''' ProdLow = psrc1 * op2; int halfSize = (dataSize * 8) / 2; - uint64_t shifter = (1ULL << halfSize); + uint64_t shifter = (ULL(1) << halfSize); uint64_t hiResult; uint64_t psrc1_h = psrc1 / shifter; uint64_t psrc1_l = psrc1 & mask(halfSize); @@ -549,7 +553,7 @@ let {{ code = ''' ProdLow = psrc1 * op2; int halfSize = (dataSize * 8) / 2; - uint64_t shifter = (1ULL << halfSize); + uint64_t shifter = (ULL(1) << halfSize); uint64_t psrc1_h = psrc1 / shifter; uint64_t psrc1_l = psrc1 & mask(halfSize); uint64_t psrc2_h = (op2 / shifter) & mask(halfSize); diff --git a/src/arch/x86/linux/linux.hh b/src/arch/x86/linux/linux.hh index c2941c769..238b5e683 100644 --- a/src/arch/x86/linux/linux.hh +++ b/src/arch/x86/linux/linux.hh @@ -111,6 +111,22 @@ class X86Linux64 : public Linux uint64_t iov_base; // void * uint64_t iov_len; // size_t } tgt_iovec; + + typedef struct { + int64_t uptime; /* Seconds since boot */ + uint64_t loads[3]; /* 1, 5, and 15 minute load averages */ + uint64_t totalram; /* Total usable main memory size */ + uint64_t freeram; /* Available memory size */ + uint64_t sharedram; /* Amount of shared memory */ + uint64_t bufferram; /* Memory used by buffers */ + uint64_t totalswap; /* Total swap space size */ + uint64_t freeswap; /* swap space still available */ + uint16_t procs; /* Number of current processes */ + uint64_t totalhigh; /* Total high memory size */ + uint64_t freehigh; /* Available high memory size */ + uint64_t mem_unit; /* Memory unit size in bytes */ + } tgt_sysinfo; + }; class X86Linux32 : public Linux @@ -126,8 +142,8 @@ class X86Linux32 : public Linux uint32_t st_uid; uint32_t st_gid; uint64_t st_rdev; - int64_t st_size; uint8_t __pad3[4]; + int64_t st_size; uint32_t st_blksize; uint64_t st_blocks; uint32_t st_atimeX; @@ -137,7 +153,7 @@ class X86Linux32 : public Linux uint32_t st_ctimeX; uint32_t st_ctime_nsec; uint64_t st_ino; - } tgt_stat64; + } __attribute__((__packed__)) tgt_stat64; static OpenFlagTransTable openFlagTable[]; @@ -160,6 +176,23 @@ class X86Linux32 : public Linux static const int NUM_OPEN_FLAGS; static const unsigned TGT_MAP_ANONYMOUS = 0x20; + + typedef struct { + int32_t uptime; /* Seconds since boot */ + uint32_t loads[3]; /* 1, 5, and 15 minute load averages */ + uint32_t totalram; /* Total usable main memory size */ + uint32_t freeram; /* Available memory size */ + uint32_t sharedram; /* Amount of shared memory */ + uint32_t bufferram; /* Memory used by buffers */ + uint32_t totalswap; /* Total swap space size */ + uint32_t freeswap; /* swap space still available */ + uint16_t procs; /* Number of current processes */ + uint32_t totalhigh; /* Total high memory size */ + uint32_t freehigh; /* Available high memory size */ + uint32_t mem_unit; /* Memory unit size in bytes */ + } tgt_sysinfo; + + static bool mmapGrowsDown() { return true; } }; #endif diff --git a/src/arch/x86/linux/syscalls.cc b/src/arch/x86/linux/syscalls.cc index 4d7bca95c..6a659108f 100644 --- a/src/arch/x86/linux/syscalls.cc +++ b/src/arch/x86/linux/syscalls.cc @@ -68,7 +68,8 @@ static SyscallReturn unameFunc(SyscallDesc *desc, int callnum, LiveProcess *process, ThreadContext *tc) { - TypedBufferArg<Linux::utsname> name(process->getSyscallArg(tc, 0)); + int index = 0; + TypedBufferArg<Linux::utsname> name(process->getSyscallArg(tc, index)); strcpy(name->sysname, "Linux"); strcpy(name->nodename, "m5.eecs.umich.edu"); @@ -94,8 +95,9 @@ archPrctlFunc(SyscallDesc *desc, int callnum, LiveProcess *process, }; //First argument is the code, second is the address - int code = process->getSyscallArg(tc, 0); - uint64_t addr = process->getSyscallArg(tc, 1); + int index = 0; + int code = process->getSyscallArg(tc, index); + uint64_t addr = process->getSyscallArg(tc, index); uint64_t fsBase, gsBase; TranslatingPort *p = tc->getMemPort(); switch(code) @@ -159,7 +161,8 @@ setThreadArea32Func(SyscallDesc *desc, int callnum, assert((maxTLSEntry + 1) * sizeof(uint64_t) <= x86lp->gdtSize()); - TypedBufferArg<UserDesc32> userDesc(process->getSyscallArg(tc, 0)); + int argIndex = 0; + TypedBufferArg<UserDesc32> userDesc(process->getSyscallArg(tc, argIndex)); TypedBufferArg<uint64_t> gdt(x86lp->gdtStart() + minTLSEntry * sizeof(uint64_t), numTLSEntries * sizeof(uint64_t)); @@ -232,7 +235,7 @@ SyscallDesc X86_64LinuxProcess::syscallDescs[] = { /* 1 */ SyscallDesc("write", writeFunc), /* 2 */ SyscallDesc("open", openFunc<X86Linux64>), /* 3 */ SyscallDesc("close", closeFunc), - /* 4 */ SyscallDesc("stat", unimplementedFunc), + /* 4 */ SyscallDesc("stat", stat64Func<X86Linux64>), /* 5 */ SyscallDesc("fstat", fstat64Func<X86Linux64>), /* 6 */ SyscallDesc("lstat", unimplementedFunc), /* 7 */ SyscallDesc("poll", unimplementedFunc), @@ -241,7 +244,7 @@ SyscallDesc X86_64LinuxProcess::syscallDescs[] = { /* 10 */ SyscallDesc("mprotect", unimplementedFunc), /* 11 */ SyscallDesc("munmap", munmapFunc), /* 12 */ SyscallDesc("brk", brkFunc), - /* 13 */ SyscallDesc("rt_sigaction", unimplementedFunc), + /* 13 */ SyscallDesc("rt_sigaction", ignoreFunc), /* 14 */ SyscallDesc("rt_sigprocmask", unimplementedFunc), /* 15 */ SyscallDesc("rt_sigreturn", unimplementedFunc), /* 16 */ SyscallDesc("ioctl", unimplementedFunc), @@ -304,8 +307,8 @@ SyscallDesc X86_64LinuxProcess::syscallDescs[] = { /* 73 */ SyscallDesc("flock", unimplementedFunc), /* 74 */ SyscallDesc("fsync", unimplementedFunc), /* 75 */ SyscallDesc("fdatasync", unimplementedFunc), - /* 76 */ SyscallDesc("truncate", unimplementedFunc), - /* 77 */ SyscallDesc("ftruncate", unimplementedFunc), + /* 76 */ SyscallDesc("truncate", truncateFunc), + /* 77 */ SyscallDesc("ftruncate", ftruncateFunc), /* 78 */ SyscallDesc("getdents", unimplementedFunc), /* 79 */ SyscallDesc("getcwd", unimplementedFunc), /* 80 */ SyscallDesc("chdir", unimplementedFunc), @@ -327,7 +330,7 @@ SyscallDesc X86_64LinuxProcess::syscallDescs[] = { /* 96 */ SyscallDesc("gettimeofday", unimplementedFunc), /* 97 */ SyscallDesc("getrlimit", unimplementedFunc), /* 98 */ SyscallDesc("getrusage", unimplementedFunc), - /* 99 */ SyscallDesc("sysinfo", unimplementedFunc), + /* 99 */ SyscallDesc("sysinfo", sysinfoFunc<X86Linux64>), /* 100 */ SyscallDesc("times", unimplementedFunc), /* 101 */ SyscallDesc("ptrace", unimplementedFunc), /* 102 */ SyscallDesc("getuid", getuidFunc), @@ -429,7 +432,7 @@ SyscallDesc X86_64LinuxProcess::syscallDescs[] = { /* 198 */ SyscallDesc("lremovexattr", unimplementedFunc), /* 199 */ SyscallDesc("fremovexattr", unimplementedFunc), /* 200 */ SyscallDesc("tkill", unimplementedFunc), - /* 201 */ SyscallDesc("time", unimplementedFunc), + /* 201 */ SyscallDesc("time", timeFunc<X86Linux64>), /* 202 */ SyscallDesc("futex", ignoreFunc), /* 203 */ SyscallDesc("sched_setaffinity", unimplementedFunc), /* 204 */ SyscallDesc("sched_getaffinity", unimplementedFunc), @@ -508,19 +511,19 @@ const int X86_64LinuxProcess::numSyscalls = SyscallDesc I386LinuxProcess::syscallDescs[] = { /* 0 */ SyscallDesc("restart_syscall", unimplementedFunc), - /* 1 */ SyscallDesc("exit", unimplementedFunc), + /* 1 */ SyscallDesc("exit", exitFunc), /* 2 */ SyscallDesc("fork", unimplementedFunc), - /* 3 */ SyscallDesc("read", unimplementedFunc), + /* 3 */ SyscallDesc("read", readFunc), /* 4 */ SyscallDesc("write", writeFunc), - /* 5 */ SyscallDesc("open", openFunc<X86Linux64>), - /* 6 */ SyscallDesc("close", unimplementedFunc), + /* 5 */ SyscallDesc("open", openFunc<X86Linux32>), + /* 6 */ SyscallDesc("close", closeFunc), /* 7 */ SyscallDesc("waitpid", unimplementedFunc), /* 8 */ SyscallDesc("creat", unimplementedFunc), /* 9 */ SyscallDesc("link", unimplementedFunc), /* 10 */ SyscallDesc("unlink", unimplementedFunc), /* 11 */ SyscallDesc("execve", unimplementedFunc), /* 12 */ SyscallDesc("chdir", unimplementedFunc), - /* 13 */ SyscallDesc("time", unimplementedFunc), + /* 13 */ SyscallDesc("time", timeFunc<X86Linux32>), /* 14 */ SyscallDesc("mknod", unimplementedFunc), /* 15 */ SyscallDesc("chmod", unimplementedFunc), /* 16 */ SyscallDesc("lchown", unimplementedFunc), @@ -531,7 +534,7 @@ SyscallDesc I386LinuxProcess::syscallDescs[] = { /* 21 */ SyscallDesc("mount", unimplementedFunc), /* 22 */ SyscallDesc("umount", unimplementedFunc), /* 23 */ SyscallDesc("setuid", unimplementedFunc), - /* 24 */ SyscallDesc("getuid", unimplementedFunc), + /* 24 */ SyscallDesc("getuid", getuidFunc), /* 25 */ SyscallDesc("stime", unimplementedFunc), /* 26 */ SyscallDesc("ptrace", unimplementedFunc), /* 27 */ SyscallDesc("alarm", unimplementedFunc), @@ -554,10 +557,10 @@ SyscallDesc I386LinuxProcess::syscallDescs[] = { /* 44 */ SyscallDesc("prof", unimplementedFunc), /* 45 */ SyscallDesc("brk", brkFunc), /* 46 */ SyscallDesc("setgid", unimplementedFunc), - /* 47 */ SyscallDesc("getgid", unimplementedFunc), + /* 47 */ SyscallDesc("getgid", getgidFunc), /* 48 */ SyscallDesc("signal", unimplementedFunc), - /* 49 */ SyscallDesc("geteuid", unimplementedFunc), - /* 50 */ SyscallDesc("getegid", unimplementedFunc), + /* 49 */ SyscallDesc("geteuid", geteuidFunc), + /* 50 */ SyscallDesc("getegid", getegidFunc), /* 51 */ SyscallDesc("acct", unimplementedFunc), /* 52 */ SyscallDesc("umount2", unimplementedFunc), /* 53 */ SyscallDesc("lock", unimplementedFunc), @@ -598,9 +601,9 @@ SyscallDesc I386LinuxProcess::syscallDescs[] = { /* 88 */ SyscallDesc("reboot", unimplementedFunc), /* 89 */ SyscallDesc("readdir", unimplementedFunc), /* 90 */ SyscallDesc("mmap", unimplementedFunc), - /* 91 */ SyscallDesc("munmap", unimplementedFunc), - /* 92 */ SyscallDesc("truncate", unimplementedFunc), - /* 93 */ SyscallDesc("ftruncate", unimplementedFunc), + /* 91 */ SyscallDesc("munmap", munmapFunc), + /* 92 */ SyscallDesc("truncate", truncateFunc), + /* 93 */ SyscallDesc("ftruncate", ftruncateFunc), /* 94 */ SyscallDesc("fchmod", unimplementedFunc), /* 95 */ SyscallDesc("fchown", unimplementedFunc), /* 96 */ SyscallDesc("getpriority", unimplementedFunc), @@ -623,7 +626,7 @@ SyscallDesc I386LinuxProcess::syscallDescs[] = { /* 113 */ SyscallDesc("vm86old", unimplementedFunc), /* 114 */ SyscallDesc("wait4", unimplementedFunc), /* 115 */ SyscallDesc("swapoff", unimplementedFunc), - /* 116 */ SyscallDesc("sysinfo", unimplementedFunc), + /* 116 */ SyscallDesc("sysinfo", sysinfoFunc<X86Linux32>), /* 117 */ SyscallDesc("ipc", unimplementedFunc), /* 118 */ SyscallDesc("fsync", unimplementedFunc), /* 119 */ SyscallDesc("sigreturn", unimplementedFunc), @@ -681,7 +684,7 @@ SyscallDesc I386LinuxProcess::syscallDescs[] = { /* 171 */ SyscallDesc("getresgid", unimplementedFunc), /* 172 */ SyscallDesc("prctl", unimplementedFunc), /* 173 */ SyscallDesc("rt_sigreturn", unimplementedFunc), - /* 174 */ SyscallDesc("rt_sigaction", unimplementedFunc), + /* 174 */ SyscallDesc("rt_sigaction", ignoreFunc), /* 175 */ SyscallDesc("rt_sigprocmask", unimplementedFunc), /* 176 */ SyscallDesc("rt_sigpending", unimplementedFunc), /* 177 */ SyscallDesc("rt_sigtimedwait", unimplementedFunc), @@ -700,16 +703,16 @@ SyscallDesc I386LinuxProcess::syscallDescs[] = { /* 190 */ SyscallDesc("vfork", unimplementedFunc), /* 191 */ SyscallDesc("ugetrlimit", unimplementedFunc), /* 192 */ SyscallDesc("mmap2", mmapFunc<X86Linux32>), - /* 193 */ SyscallDesc("truncate64", unimplementedFunc), - /* 194 */ SyscallDesc("ftruncate64", unimplementedFunc), - /* 195 */ SyscallDesc("stat64", unimplementedFunc), + /* 193 */ SyscallDesc("truncate64", truncate64Func), + /* 194 */ SyscallDesc("ftruncate64", ftruncate64Func), + /* 195 */ SyscallDesc("stat64", stat64Func<X86Linux32>), /* 196 */ SyscallDesc("lstat64", unimplementedFunc), /* 197 */ SyscallDesc("fstat64", fstat64Func<X86Linux32>), /* 198 */ SyscallDesc("lchown32", unimplementedFunc), - /* 199 */ SyscallDesc("getuid32", unimplementedFunc), - /* 200 */ SyscallDesc("getgid32", unimplementedFunc), - /* 201 */ SyscallDesc("geteuid32", unimplementedFunc), - /* 202 */ SyscallDesc("getegid32", unimplementedFunc), + /* 199 */ SyscallDesc("getuid32", getuidFunc), + /* 200 */ SyscallDesc("getgid32", getgidFunc), + /* 201 */ SyscallDesc("geteuid32", geteuidFunc), + /* 202 */ SyscallDesc("getegid32", getegidFunc), /* 203 */ SyscallDesc("setreuid32", unimplementedFunc), /* 204 */ SyscallDesc("setregid32", unimplementedFunc), /* 205 */ SyscallDesc("getgroups32", unimplementedFunc), diff --git a/src/arch/x86/predecoder_tables.cc b/src/arch/x86/predecoder_tables.cc index 5f2b5c421..e8c838dfb 100644 --- a/src/arch/x86/predecoder_tables.cc +++ b/src/arch/x86/predecoder_tables.cc @@ -191,7 +191,7 @@ namespace X86ISA /* 7 */ BY, BY, BY, BY, BY, BY, BY, BY, BY, BY, BY, BY, BY, BY, BY, BY, /* 8 */ BY, ZW, BY, BY, 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , /* 9 */ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , -/* A */ BY, VW, BY, VW, 0 , 0 , 0 , 0 , BY, ZW, 0 , 0 , 0 , 0 , 0 , 0 , +/* A */ VW, VW, VW, VW, 0 , 0 , 0 , 0 , BY, ZW, 0 , 0 , 0 , 0 , 0 , 0 , /* B */ BY, BY, BY, BY, BY, BY, BY, BY, VW, VW, VW, VW, VW, VW, VW, VW, /* C */ BY, BY, WO, 0 , 0 , 0 , BY, ZW, EN, 0 , WO, 0 , 0 , BY, 0 , 0 , /* D */ 0 , 0 , 0 , 0 , BY, BY, 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , diff --git a/src/arch/x86/process.cc b/src/arch/x86/process.cc index 4082e568c..42ca7b27d 100644 --- a/src/arch/x86/process.cc +++ b/src/arch/x86/process.cc @@ -139,6 +139,12 @@ X86_64LiveProcess::X86_64LiveProcess(LiveProcessParams *params, int _numSyscallDescs) : X86LiveProcess(params, objFile, _syscallDescs, _numSyscallDescs) { + + vsyscallPage.base = 0xffffffffff600000ULL; + vsyscallPage.size = VMPageSize; + vsyscallPage.vtimeOffset = 0x400; + vsyscallPage.vgettimeofdayOffset = 0x410; + // Set up stack. On X86_64 Linux, stack goes from the top of memory // downward, less the hole for the kernel address space plus one page // for undertermined purposes. @@ -169,7 +175,7 @@ I386LiveProcess::I386LiveProcess(LiveProcessParams *params, int _numSyscallDescs) : X86LiveProcess(params, objFile, _syscallDescs, _numSyscallDescs) { - _gdtStart = 0x100000000; + _gdtStart = ULL(0x100000000); _gdtSize = VMPageSize; vsyscallPage.base = 0xffffe000ULL; @@ -184,7 +190,7 @@ I386LiveProcess::I386LiveProcess(LiveProcessParams *params, // Set up region for mmaps. This was determined empirically and may not // always be correct. - mmap_start = mmap_end = (Addr)0xf7ffd000ULL; + mmap_start = mmap_end = (Addr)0xf7ffe000ULL; } SyscallDesc* @@ -205,6 +211,24 @@ X86_64LiveProcess::startup() argsInit(sizeof(uint64_t), VMPageSize); + // Set up the vsyscall page for this process. + pTable->allocate(vsyscallPage.base, vsyscallPage.size); + uint8_t vtimeBlob[] = { + 0x48,0xc7,0xc0,0xc9,0x00,0x00,0x00, // mov $0xc9,%rax + 0x0f,0x05, // syscall + 0xc3 // retq + }; + initVirtMem->writeBlob(vsyscallPage.base + vsyscallPage.vtimeOffset, + vtimeBlob, sizeof(vtimeBlob)); + + uint8_t vgettimeofdayBlob[] = { + 0x48,0xc7,0xc0,0x60,0x00,0x00,0x00, // mov $0x60,%rax + 0x0f,0x05, // syscall + 0xc3 // retq + }; + initVirtMem->writeBlob(vsyscallPage.base + vsyscallPage.vgettimeofdayOffset, + vgettimeofdayBlob, sizeof(vgettimeofdayBlob)); + for (int i = 0; i < contextIds.size(); i++) { ThreadContext * tc = system->getThreadContext(contextIds[i]); @@ -698,10 +722,10 @@ X86LiveProcess::setSyscallReturn(ThreadContext *tc, SyscallReturn return_value) } X86ISA::IntReg -X86_64LiveProcess::getSyscallArg(ThreadContext *tc, int i) +X86_64LiveProcess::getSyscallArg(ThreadContext *tc, int &i) { assert(i < NumArgumentRegs); - return tc->readIntReg(ArgumentReg[i]); + return tc->readIntReg(ArgumentReg[i++]); } void @@ -712,10 +736,21 @@ X86_64LiveProcess::setSyscallArg(ThreadContext *tc, int i, X86ISA::IntReg val) } X86ISA::IntReg -I386LiveProcess::getSyscallArg(ThreadContext *tc, int i) +I386LiveProcess::getSyscallArg(ThreadContext *tc, int &i) { assert(i < NumArgumentRegs32); - return tc->readIntReg(ArgumentReg32[i]); + return tc->readIntReg(ArgumentReg32[i++]); +} + +X86ISA::IntReg +I386LiveProcess::getSyscallArg(ThreadContext *tc, int &i, int width) +{ + assert(width == 32 || width == 64); + assert(i < NumArgumentRegs); + uint64_t retVal = tc->readIntReg(ArgumentReg32[i++]) & mask(32); + if (width == 64) + retVal |= ((uint64_t)tc->readIntReg(ArgumentReg[i++]) << 32); + return retVal; } void diff --git a/src/arch/x86/process.hh b/src/arch/x86/process.hh index cd6d99e66..3ad2abe08 100644 --- a/src/arch/x86/process.hh +++ b/src/arch/x86/process.hh @@ -101,11 +101,21 @@ namespace X86ISA X86_64LiveProcess(LiveProcessParams *params, ObjectFile *objFile, SyscallDesc *_syscallDescs, int _numSyscallDescs); + class VSyscallPage + { + public: + Addr base; + Addr size; + Addr vtimeOffset; + Addr vgettimeofdayOffset; + }; + VSyscallPage vsyscallPage; + public: void argsInit(int intSize, int pageSize); void startup(); - X86ISA::IntReg getSyscallArg(ThreadContext *tc, int i); + X86ISA::IntReg getSyscallArg(ThreadContext *tc, int &i); void setSyscallArg(ThreadContext *tc, int i, X86ISA::IntReg val); }; @@ -130,7 +140,8 @@ namespace X86ISA void startup(); void syscall(int64_t callnum, ThreadContext *tc); - X86ISA::IntReg getSyscallArg(ThreadContext *tc, int i); + X86ISA::IntReg getSyscallArg(ThreadContext *tc, int &i); + X86ISA::IntReg getSyscallArg(ThreadContext *tc, int &i, int width); void setSyscallArg(ThreadContext *tc, int i, X86ISA::IntReg val); }; } diff --git a/src/arch/x86/system.cc b/src/arch/x86/system.cc index 1594cc375..31183f2f9 100644 --- a/src/arch/x86/system.cc +++ b/src/arch/x86/system.cc @@ -211,7 +211,7 @@ X86System::startup() numGDTEntries++; - SegSelector ds; + SegSelector ds = 0; ds.si = numGDTEntries - 1; tc->setMiscReg(MISCREG_DS, (MiscReg)ds); diff --git a/src/arch/x86/tlb.cc b/src/arch/x86/tlb.cc index 5280b9ba8..d7959da2c 100644 --- a/src/arch/x86/tlb.cc +++ b/src/arch/x86/tlb.cc @@ -632,12 +632,26 @@ TLB::translate(RequestPtr req, ThreadContext *tc, Translation *translation, Process *p = tc->getProcessPtr(); TlbEntry newEntry; bool success = p->pTable->lookup(vaddr, newEntry); - if(!success && mode != Execute) { + if (!success && mode != Execute) { p->checkAndAllocNextPage(vaddr); success = p->pTable->lookup(vaddr, newEntry); } - if(!success) { - panic("Tried to execute unmapped address %#x.\n", vaddr); + if (!success) { + if (req->isPrefetch()) { + return new PageFault(vaddr, true, mode, true, false); + } else { + const char *modeStr = ""; + if (mode == Execute) + modeStr = "execute"; + else if (mode == Read) + modeStr = "read"; + else if (mode == Write) + modeStr = "write"; + else + modeStr = "?"; + panic("Tried to %s unmapped address %#x.\n", + modeStr, vaddr); + } } else { Addr alignedVaddr = p->pTable->pageAlign(vaddr); DPRINTF(TLB, "Mapping %#x to %#x\n", alignedVaddr, diff --git a/src/base/bigint.cc b/src/base/bigint.cc index ce9942c9c..d741e1f7b 100644 --- a/src/base/bigint.cc +++ b/src/base/bigint.cc @@ -28,10 +28,10 @@ * Authors: Gabe Black */ -#include "base/bigint.hh" - #include <iostream> +#include "base/bigint.hh" + using namespace std; ostream & operator << (ostream & os, const Twin64_t & t) diff --git a/src/base/bigint.hh b/src/base/bigint.hh index d60684231..a4e8738d3 100644 --- a/src/base/bigint.hh +++ b/src/base/bigint.hh @@ -28,10 +28,11 @@ * Authors: Ali Saidi */ -#include "base/misc.hh" - #include <iostream> +#include "base/misc.hh" +#include "base/types.hh" + #ifndef __BASE_BIGINT_HH__ #define __BASE_BIGINT_HH__ // Create a couple of large int types for atomic reads diff --git a/src/base/cp_annotate.cc b/src/base/cp_annotate.cc index 0aba2d999..4e138a6dd 100644 --- a/src/base/cp_annotate.cc +++ b/src/base/cp_annotate.cc @@ -35,6 +35,7 @@ #include "base/loader/object_file.hh" #include "base/output.hh" #include "base/trace.hh" +#include "config/the_isa.hh" #include "cpu/thread_context.hh" #include "sim/arguments.hh" #include "sim/core.hh" diff --git a/src/base/cp_annotate.hh b/src/base/cp_annotate.hh index 05d8129d0..4248c070a 100644 --- a/src/base/cp_annotate.hh +++ b/src/base/cp_annotate.hh @@ -41,6 +41,7 @@ #include "base/trace.hh" #include "base/types.hh" #include "config/cp_annotate.hh" +#include "config/the_isa.hh" #include "sim/serialize.hh" #include "sim/startup.hh" #include "sim/system.hh" diff --git a/src/base/inet.cc b/src/base/inet.cc index 898a189ef..1a280e993 100644 --- a/src/base/inet.cc +++ b/src/base/inet.cc @@ -28,6 +28,7 @@ * Authors: Nathan Binkert */ +#include <cstdio> #include <sstream> #include <string> diff --git a/src/base/loader/elf_object.cc b/src/base/loader/elf_object.cc index 15ad88f76..60f0f99b4 100644 --- a/src/base/loader/elf_object.cc +++ b/src/base/loader/elf_object.cc @@ -97,6 +97,19 @@ ElfObject::tryFile(const string &fname, int fd, size_t len, uint8_t *data) arch = ObjectFile::Alpha; } else if (ehdr.e_machine == EM_ARM) { arch = ObjectFile::Arm; + } else if (ehdr.e_machine == EM_PPC && + ehdr.e_ident[EI_CLASS] == ELFCLASS32) { + if (ehdr.e_ident[EI_DATA] == ELFDATA2MSB) { + arch = ObjectFile::Power; + } else { + fatal("The binary you're trying to load is compiled for " + "little endian Power.\nM5 only supports big " + "endian Power. Please recompile your binary.\n"); + } + } else if (ehdr.e_machine == EM_PPC64) { + fatal("The binary you're trying to load is compiled for 64-bit " + "Power. M5\n only supports 32-bit Power. Please " + "recompile your binary.\n"); } else { warn("Unknown architecture: %d\n", ehdr.e_machine); arch = ObjectFile::UnknownArch; diff --git a/src/base/loader/object_file.hh b/src/base/loader/object_file.hh index e511451b7..b08f1c633 100644 --- a/src/base/loader/object_file.hh +++ b/src/base/loader/object_file.hh @@ -52,7 +52,8 @@ class ObjectFile Mips, X86_64, I386, - Arm + Arm, + Power }; enum OpSys { diff --git a/src/base/remote_gdb.cc b/src/base/remote_gdb.cc index 6c301b10e..68747b3d1 100644 --- a/src/base/remote_gdb.cc +++ b/src/base/remote_gdb.cc @@ -118,6 +118,7 @@ #include <sys/signal.h> +#include <cstdio> #include <string> #include <unistd.h> @@ -131,9 +132,9 @@ #include "base/remote_gdb.hh" #include "base/socket.hh" #include "base/trace.hh" +#include "config/the_isa.hh" #include "cpu/thread_context.hh" #include "cpu/static_inst.hh" -//#include "mem/physical.hh" #include "mem/port.hh" #include "mem/translating_port.hh" #include "sim/system.hh" diff --git a/src/base/types.hh b/src/base/types.hh index 1a6db9fbb..0c10fac64 100644 --- a/src/base/types.hh +++ b/src/base/types.hh @@ -55,6 +55,7 @@ typedef int64_t Counter; * @note using an unsigned breaks the cache. */ typedef int64_t Tick; +typedef uint64_t UTick; const Tick MaxTick = LL(0x7fffffffffffffff); diff --git a/src/cpu/BaseCPU.py b/src/cpu/BaseCPU.py index 4661375ba..ac734e5ac 100644 --- a/src/cpu/BaseCPU.py +++ b/src/cpu/BaseCPU.py @@ -26,37 +26,43 @@ # # Authors: Nathan Binkert -from MemObject import MemObject +import sys + +from m5.defines import buildEnv from m5.params import * from m5.proxy import * -from m5 import build_env + from Bus import Bus from InstTracer import InstTracer from ExeTracer import ExeTracer -import sys +from MemObject import MemObject default_tracer = ExeTracer() -if build_env['TARGET_ISA'] == 'alpha': +if buildEnv['TARGET_ISA'] == 'alpha': from AlphaTLB import AlphaDTB, AlphaITB - if build_env['FULL_SYSTEM']: + if buildEnv['FULL_SYSTEM']: from AlphaInterrupts import AlphaInterrupts -elif build_env['TARGET_ISA'] == 'sparc': +elif buildEnv['TARGET_ISA'] == 'sparc': from SparcTLB import SparcTLB - if build_env['FULL_SYSTEM']: + if buildEnv['FULL_SYSTEM']: from SparcInterrupts import SparcInterrupts -elif build_env['TARGET_ISA'] == 'x86': +elif buildEnv['TARGET_ISA'] == 'x86': from X86TLB import X86TLB - if build_env['FULL_SYSTEM']: + if buildEnv['FULL_SYSTEM']: from X86LocalApic import X86LocalApic -elif build_env['TARGET_ISA'] == 'mips': +elif buildEnv['TARGET_ISA'] == 'mips': from MipsTLB import MipsTLB - if build_env['FULL_SYSTEM']: + if buildEnv['FULL_SYSTEM']: from MipsInterrupts import MipsInterrupts -elif build_env['TARGET_ISA'] == 'arm': +elif buildEnv['TARGET_ISA'] == 'arm': from ArmTLB import ArmTLB - if build_env['FULL_SYSTEM']: + if buildEnv['FULL_SYSTEM']: from ArmInterrupts import ArmInterrupts +elif buildEnv['TARGET_ISA'] == 'power': + from PowerTLB import PowerTLB + if buildEnv['FULL_SYSTEM']: + from PowerInterrupts import PowerInterrupts class BaseCPU(MemObject): type = 'BaseCPU' @@ -76,47 +82,54 @@ class BaseCPU(MemObject): do_statistics_insts = Param.Bool(True, "enable statistics pseudo instructions") - if build_env['FULL_SYSTEM']: + if buildEnv['FULL_SYSTEM']: profile = Param.Latency('0ns', "trace the kernel stack") do_quiesce = Param.Bool(True, "enable quiesce instructions") else: workload = VectorParam.Process("processes to run") - if build_env['TARGET_ISA'] == 'sparc': + if buildEnv['TARGET_ISA'] == 'sparc': dtb = Param.SparcTLB(SparcTLB(), "Data TLB") itb = Param.SparcTLB(SparcTLB(), "Instruction TLB") - if build_env['FULL_SYSTEM']: + if buildEnv['FULL_SYSTEM']: interrupts = Param.SparcInterrupts( SparcInterrupts(), "Interrupt Controller") - elif build_env['TARGET_ISA'] == 'alpha': + elif buildEnv['TARGET_ISA'] == 'alpha': dtb = Param.AlphaTLB(AlphaDTB(), "Data TLB") itb = Param.AlphaTLB(AlphaITB(), "Instruction TLB") - if build_env['FULL_SYSTEM']: + if buildEnv['FULL_SYSTEM']: interrupts = Param.AlphaInterrupts( AlphaInterrupts(), "Interrupt Controller") - elif build_env['TARGET_ISA'] == 'x86': + elif buildEnv['TARGET_ISA'] == 'x86': dtb = Param.X86TLB(X86TLB(), "Data TLB") itb = Param.X86TLB(X86TLB(), "Instruction TLB") - if build_env['FULL_SYSTEM']: + if buildEnv['FULL_SYSTEM']: _localApic = X86LocalApic(pio_addr=0x2000000000000000) interrupts = \ Param.X86LocalApic(_localApic, "Interrupt Controller") - elif build_env['TARGET_ISA'] == 'mips': + elif buildEnv['TARGET_ISA'] == 'mips': dtb = Param.MipsTLB(MipsTLB(), "Data TLB") itb = Param.MipsTLB(MipsTLB(), "Instruction TLB") - if build_env['FULL_SYSTEM']: + if buildEnv['FULL_SYSTEM']: interrupts = Param.MipsInterrupts( MipsInterrupts(), "Interrupt Controller") - elif build_env['TARGET_ISA'] == 'arm': + elif buildEnv['TARGET_ISA'] == 'arm': UnifiedTLB = Param.Bool(True, "Is this a Unified TLB?") dtb = Param.ArmTLB(ArmTLB(), "Data TLB") itb = Param.ArmTLB(ArmTLB(), "Instruction TLB") - if build_env['FULL_SYSTEM']: + if buildEnv['FULL_SYSTEM']: interrupts = Param.ArmInterrupts( ArmInterrupts(), "Interrupt Controller") + elif buildEnv['TARGET_ISA'] == 'power': + UnifiedTLB = Param.Bool(True, "Is this a Unified TLB?") + dtb = Param.PowerTLB(PowerTLB(), "Data TLB") + itb = Param.PowerTLB(PowerTLB(), "Instruction TLB") + if buildEnv['FULL_SYSTEM']: + interrupts = Param.PowerInterrupts( + PowerInterrupts(), "Interrupt Controller") else: print "Don't know what TLB to use for ISA %s" % \ - build_env['TARGET_ISA'] + buildEnv['TARGET_ISA'] sys.exit(1) max_insts_all_threads = Param.Counter(0, @@ -139,7 +152,7 @@ class BaseCPU(MemObject): tracer = Param.InstTracer(default_tracer, "Instruction tracer") _mem_ports = [] - if build_env['TARGET_ISA'] == 'x86' and build_env['FULL_SYSTEM']: + if buildEnv['TARGET_ISA'] == 'x86' and buildEnv['FULL_SYSTEM']: _mem_ports = ["itb.walker.port", "dtb.walker.port", "interrupts.pio", @@ -157,7 +170,7 @@ class BaseCPU(MemObject): self.icache_port = ic.cpu_side self.dcache_port = dc.cpu_side self._mem_ports = ['icache.mem_side', 'dcache.mem_side'] - if build_env['TARGET_ISA'] == 'x86' and build_env['FULL_SYSTEM']: + if buildEnv['TARGET_ISA'] == 'x86' and buildEnv['FULL_SYSTEM']: self._mem_ports += ["itb.walker_port", "dtb.walker_port"] def addTwoLevelCacheHierarchy(self, ic, dc, l2c): @@ -168,7 +181,7 @@ class BaseCPU(MemObject): self.l2cache.cpu_side = self.toL2Bus.port self._mem_ports = ['l2cache.mem_side'] - if build_env['TARGET_ISA'] == 'mips': + if buildEnv['TARGET_ISA'] == 'mips': CP0_IntCtl_IPTI = Param.Unsigned(0,"No Description") CP0_IntCtl_IPPCI = Param.Unsigned(0,"No Description") CP0_SrsCtl_HSS = Param.Unsigned(0,"No Description") diff --git a/src/cpu/CheckerCPU.py b/src/cpu/CheckerCPU.py index bff9af62d..132254413 100644 --- a/src/cpu/CheckerCPU.py +++ b/src/cpu/CheckerCPU.py @@ -27,7 +27,6 @@ # Authors: Nathan Binkert from m5.params import * -from m5 import build_env from BaseCPU import BaseCPU class CheckerCPU(BaseCPU): diff --git a/src/cpu/SConscript b/src/cpu/SConscript index ea79b622c..b89a589c6 100644 --- a/src/cpu/SConscript +++ b/src/cpu/SConscript @@ -160,6 +160,7 @@ TraceFlag('DynInst') TraceFlag('ExecEnable') TraceFlag('ExecCPSeq') TraceFlag('ExecEffAddr') +TraceFlag('ExecFaulting', 'Trace faulting instructions') TraceFlag('ExecFetchSeq') TraceFlag('ExecOpClass') TraceFlag('ExecRegDelta') @@ -176,6 +177,6 @@ TraceFlag('PCEvent') TraceFlag('Quiesce') CompoundFlag('Exec', [ 'ExecEnable', 'ExecTicks', 'ExecOpClass', 'ExecThread', - 'ExecEffAddr', 'ExecResult', 'ExecSymbol', 'ExecMicro' ]) + 'ExecEffAddr', 'ExecResult', 'ExecSymbol', 'ExecMicro', 'ExecFaulting' ]) CompoundFlag('ExecNoTicks', [ 'ExecEnable', 'ExecOpClass', 'ExecThread', - 'ExecEffAddr', 'ExecResult', 'ExecMicro' ]) + 'ExecEffAddr', 'ExecResult', 'ExecMicro', 'ExecFaulting' ]) diff --git a/src/cpu/base.cc b/src/cpu/base.cc index e4cb79344..556e7ec6f 100644 --- a/src/cpu/base.cc +++ b/src/cpu/base.cc @@ -151,7 +151,7 @@ BaseCPU::BaseCPU(Params *p) *counter = numThreads; for (ThreadID tid = 0; tid < numThreads; ++tid) { Event *event = new CountedExitEvent(cause, *counter); - comInstEventQueue[tid]->schedule(event, p->max_insts_any_thread); + comInstEventQueue[tid]->schedule(event, p->max_insts_all_threads); } } diff --git a/src/cpu/base.hh b/src/cpu/base.hh index 441d9b5dd..bfeec0870 100644 --- a/src/cpu/base.hh +++ b/src/cpu/base.hh @@ -38,6 +38,7 @@ #include "arch/microcode_rom.hh" #include "base/statistics.hh" #include "config/full_system.hh" +#include "config/the_isa.hh" #include "sim/eventq.hh" #include "sim/insttracer.hh" #include "mem/mem_object.hh" diff --git a/src/cpu/base_dyn_inst.hh b/src/cpu/base_dyn_inst.hh index f4ff88209..31206c81e 100644 --- a/src/cpu/base_dyn_inst.hh +++ b/src/cpu/base_dyn_inst.hh @@ -39,6 +39,7 @@ #include "base/fast_alloc.hh" #include "base/trace.hh" #include "config/full_system.hh" +#include "config/the_isa.hh" #include "cpu/o3/comm.hh" #include "cpu/exetrace.hh" #include "cpu/inst_seq.hh" diff --git a/src/cpu/base_dyn_inst_impl.hh b/src/cpu/base_dyn_inst_impl.hh index 4ee7d2f2c..70c91ceda 100644 --- a/src/cpu/base_dyn_inst_impl.hh +++ b/src/cpu/base_dyn_inst_impl.hh @@ -35,12 +35,11 @@ #include "base/cprintf.hh" #include "base/trace.hh" - -#include "sim/faults.hh" +#include "config/the_isa.hh" +#include "cpu/base_dyn_inst.hh" #include "cpu/exetrace.hh" #include "mem/request.hh" - -#include "cpu/base_dyn_inst.hh" +#include "sim/faults.hh" #define NOHASH #ifndef NOHASH diff --git a/src/cpu/checker/cpu.cc b/src/cpu/checker/cpu.cc index 7dacc58ff..16b779e06 100644 --- a/src/cpu/checker/cpu.cc +++ b/src/cpu/checker/cpu.cc @@ -326,7 +326,7 @@ CheckerCPU::checkFlags(Request *req) { // Remove any dynamic flags that don't have to do with the request itself. unsigned flags = unverifiedReq->getFlags(); - unsigned mask = LOCKED | PHYSICAL | VPTE | ALTMODE | UNCACHEABLE | NO_FAULT; + unsigned mask = LOCKED | PHYSICAL | VPTE | ALTMODE | UNCACHEABLE | PREFETCH; flags = flags & (mask); if (flags == req->getFlags()) { return false; diff --git a/src/cpu/checker/cpu_impl.hh b/src/cpu/checker/cpu_impl.hh index 26571ed68..81f494630 100644 --- a/src/cpu/checker/cpu_impl.hh +++ b/src/cpu/checker/cpu_impl.hh @@ -32,6 +32,7 @@ #include <string> #include "base/refcnt.hh" +#include "config/the_isa.hh" #include "cpu/base_dyn_inst.hh" #include "cpu/checker/cpu.hh" #include "cpu/simple_thread.hh" diff --git a/src/cpu/checker/thread_context.hh b/src/cpu/checker/thread_context.hh index d38bd2915..ef7d4c643 100644 --- a/src/cpu/checker/thread_context.hh +++ b/src/cpu/checker/thread_context.hh @@ -32,6 +32,7 @@ #define __CPU_CHECKER_THREAD_CONTEXT_HH__ #include "arch/types.hh" +#include "config/the_isa.hh" #include "cpu/checker/cpu.hh" #include "cpu/simple_thread.hh" #include "cpu/thread_context.hh" diff --git a/src/cpu/exetrace.cc b/src/cpu/exetrace.cc index ea53fb6f5..07be700bb 100644 --- a/src/cpu/exetrace.cc +++ b/src/cpu/exetrace.cc @@ -38,6 +38,7 @@ #include "cpu/exetrace.hh" #include "cpu/static_inst.hh" #include "cpu/thread_context.hh" +#include "config/the_isa.hh" #include "enums/OpClass.hh" using namespace std; diff --git a/src/cpu/inorder/InOrderCPU.py b/src/cpu/inorder/InOrderCPU.py index 9faadc68c..a0b0466a7 100644 --- a/src/cpu/inorder/InOrderCPU.py +++ b/src/cpu/inorder/InOrderCPU.py @@ -28,7 +28,6 @@ from m5.params import * from m5.proxy import * -from m5 import build_env from BaseCPU import BaseCPU class InOrderCPU(BaseCPU): diff --git a/src/cpu/inorder/SConscript b/src/cpu/inorder/SConscript index 64f1b5481..82a1028c2 100644 --- a/src/cpu/inorder/SConscript +++ b/src/cpu/inorder/SConscript @@ -79,6 +79,7 @@ if 'InOrderCPU' in env['CPU_MODELS']: Source('resources/mult_div_unit.cc') Source('resource_pool.cc') Source('reg_dep_map.cc') + Source('thread_state.cc') Source('thread_context.cc') Source('cpu.cc') diff --git a/src/cpu/inorder/cpu.cc b/src/cpu/inorder/cpu.cc index a2367db63..1e3fdc40e 100644 --- a/src/cpu/inorder/cpu.cc +++ b/src/cpu/inorder/cpu.cc @@ -33,24 +33,34 @@ #include "arch/utility.hh" #include "config/full_system.hh" -#include "cpu/exetrace.hh" +#include "config/the_isa.hh" #include "cpu/activity.hh" -#include "cpu/simple_thread.hh" -#include "cpu/thread_context.hh" #include "cpu/base.hh" -#include "cpu/inorder/inorder_dyn_inst.hh" -#include "cpu/inorder/thread_context.hh" -#include "cpu/inorder/thread_state.hh" +#include "cpu/exetrace.hh" #include "cpu/inorder/cpu.hh" -#include "params/InOrderCPU.hh" -#include "cpu/inorder/pipeline_traits.hh" #include "cpu/inorder/first_stage.hh" -#include "cpu/inorder/resources/resource_list.hh" +#include "cpu/inorder/inorder_dyn_inst.hh" +#include "cpu/inorder/pipeline_traits.hh" #include "cpu/inorder/resource_pool.hh" +#include "cpu/inorder/resources/resource_list.hh" +#include "cpu/inorder/thread_context.hh" +#include "cpu/inorder/thread_state.hh" +#include "cpu/simple_thread.hh" +#include "cpu/thread_context.hh" #include "mem/translating_port.hh" +#include "params/InOrderCPU.hh" #include "sim/process.hh" #include "sim/stat_control.hh" +#if FULL_SYSTEM +#include "cpu/quiesce_event.hh" +#include "sim/system.hh" +#endif + +#if THE_ISA == ALPHA_ISA +#include "arch/alpha/osfpal.hh" +#endif + using namespace std; using namespace TheISA; using namespace ThePipeline; @@ -171,11 +181,16 @@ InOrderCPU::InOrderCPU(Params *params) timeBuffer(2 , 2), removeInstsThisCycle(false), activityRec(params->name, NumStages, 10, params->activity), +#if FULL_SYSTEM + system(params->system), + physmem(system->physmem), +#endif // FULL_SYSTEM switchCount(0), deferRegistration(false/*params->deferRegistration*/), stageTracing(params->stageTracing), numVirtProcs(1) { + ThreadID active_threads; cpu_params = params; resPool = new ResourcePool(this, params); @@ -183,13 +198,17 @@ InOrderCPU::InOrderCPU(Params *params) // Resize for Multithreading CPUs thread.resize(numThreads); - ThreadID active_threads = params->workload.size(); +#if FULL_SYSTEM + active_threads = 1; +#else + active_threads = params->workload.size(); if (active_threads > MaxThreads) { panic("Workload Size too large. Increase the 'MaxThreads'" "in your InOrder implementation or " "edit your workload size."); } +#endif // Bind the fetch & data ports from the resource pool. fetchPortIdx = resPool->getPortIdx(params->fetchMemPort); @@ -203,17 +222,23 @@ InOrderCPU::InOrderCPU(Params *params) } for (ThreadID tid = 0; tid < numThreads; ++tid) { +#if FULL_SYSTEM + // SMT is not supported in FS mode yet. + assert(numThreads == 1); + thread[tid] = new Thread(this, 0); +#else if (tid < (ThreadID)params->workload.size()) { DPRINTF(InOrderCPU, "Workload[%i] process is %#x\n", - tid, this->thread[tid]); - this->thread[tid] = + tid, params->workload[tid]->prog_fname); + thread[tid] = new Thread(this, tid, params->workload[tid]); } else { //Allocate Empty thread so M5 can use later //when scheduling threads to CPU Process* dummy_proc = params->workload[0]; - this->thread[tid] = new Thread(this, tid, dummy_proc); + thread[tid] = new Thread(this, tid, dummy_proc); } +#endif // Setup the TC that will serve as the interface to the threads/CPU. InOrderThreadContext *tc = new InOrderThreadContext; @@ -410,7 +435,7 @@ InOrderCPU::tick() //Tick next_tick = curTick + cycles(1); //tickEvent.schedule(next_tick); mainEventQueue.schedule(&tickEvent, nextCycle(curTick + 1)); - DPRINTF(InOrderCPU, "Scheduled CPU for next tick @ %i.\n", nextCycle() + curTick); + DPRINTF(InOrderCPU, "Scheduled CPU for next tick @ %i.\n", nextCycle(curTick + 1)); } } @@ -447,13 +472,6 @@ InOrderCPU::init() } void -InOrderCPU::readFunctional(Addr addr, uint32_t &buffer) -{ - tcBase()->getMemPort()->readBlob(addr, (uint8_t*)&buffer, sizeof(uint32_t)); - buffer = gtoh(buffer); -} - -void InOrderCPU::reset() { for (int i = 0; i < numThreads; i++) { @@ -468,6 +486,61 @@ InOrderCPU::getPort(const std::string &if_name, int idx) return resPool->getPort(if_name, idx); } +#if FULL_SYSTEM +Fault +InOrderCPU::hwrei(ThreadID tid) +{ + panic("hwrei: Unimplemented"); + + return NoFault; +} + + +bool +InOrderCPU::simPalCheck(int palFunc, ThreadID tid) +{ + panic("simPalCheck: Unimplemented"); + + return true; +} + + +Fault +InOrderCPU::getInterrupts() +{ + // Check if there are any outstanding interrupts + return this->interrupts->getInterrupt(this->threadContexts[0]); +} + + +void +InOrderCPU::processInterrupts(Fault interrupt) +{ + // Check for interrupts here. For now can copy the code that + // exists within isa_fullsys_traits.hh. Also assume that thread 0 + // is the one that handles the interrupts. + // @todo: Possibly consolidate the interrupt checking code. + // @todo: Allow other threads to handle interrupts. + + assert(interrupt != NoFault); + this->interrupts->updateIntrInfo(this->threadContexts[0]); + + DPRINTF(InOrderCPU, "Interrupt %s being handled\n", interrupt->name()); + this->trap(interrupt, 0); +} + + +void +InOrderCPU::updateMemPorts() +{ + // Update all ThreadContext's memory ports (Functional/Virtual + // Ports) + ThreadID size = thread.size(); + for (ThreadID i = 0; i < size; ++i) + thread[i]->connectMemPorts(thread[i]->getTC()); +} +#endif + void InOrderCPU::trap(Fault fault, ThreadID tid, int delay) { @@ -1230,6 +1303,22 @@ InOrderCPU::wakeCPU() mainEventQueue.schedule(&tickEvent, curTick); } +#if FULL_SYSTEM + +void +InOrderCPU::wakeup() +{ + if (this->thread[0]->status() != ThreadContext::Suspended) + return; + + this->wakeCPU(); + + DPRINTF(Quiesce, "Suspended Processor woken\n"); + this->threadContexts[0]->activate(); +} +#endif + +#if !FULL_SYSTEM void InOrderCPU::syscall(int64_t callnum, ThreadID tid) { @@ -1251,6 +1340,7 @@ InOrderCPU::syscall(int64_t callnum, ThreadID tid) // Clear Non-Speculative Block Variable nonSpecInstActive[tid] = false; } +#endif void InOrderCPU::prefetch(DynInstPtr inst) diff --git a/src/cpu/inorder/cpu.hh b/src/cpu/inorder/cpu.hh index 75d77c818..3320532ba 100644 --- a/src/cpu/inorder/cpu.hh +++ b/src/cpu/inorder/cpu.hh @@ -40,10 +40,12 @@ #include "arch/isa_traits.hh" #include "arch/types.hh" +#include "arch/registers.hh" #include "base/statistics.hh" #include "base/timebuf.hh" #include "base/types.hh" #include "config/full_system.hh" +#include "config/the_isa.hh" #include "cpu/activity.hh" #include "cpu/base.hh" #include "cpu/simple_thread.hh" @@ -297,6 +299,32 @@ class InOrderCPU : public BaseCPU /** Get a Memory Port */ Port* getPort(const std::string &if_name, int idx = 0); +#if FULL_SYSTEM + /** HW return from error interrupt. */ + Fault hwrei(ThreadID tid); + + bool simPalCheck(int palFunc, ThreadID tid); + + /** Returns the Fault for any valid interrupt. */ + Fault getInterrupts(); + + /** Processes any an interrupt fault. */ + void processInterrupts(Fault interrupt); + + /** Halts the CPU. */ + void halt() { panic("Halt not implemented!\n"); } + + /** Update the Virt and Phys ports of all ThreadContexts to + * reflect change in memory connections. */ + void updateMemPorts(); + + /** Check if this address is a valid instruction address. */ + bool validInstAddr(Addr addr) { return true; } + + /** Check if this address is a valid data address. */ + bool validDataAddr(Addr addr) { return true; } +#endif + /** trap() - sets up a trap event on the cpuTraps to handle given fault. * trapCPU() - Traps to handle given fault */ @@ -578,8 +606,6 @@ class InOrderCPU : public BaseCPU ActivityRecorder activityRec; public: - void readFunctional(Addr addr, uint32_t &buffer); - /** Number of Active Threads in the CPU */ ThreadID numActiveThreads() { return activeThreads.size(); } @@ -597,6 +623,10 @@ class InOrderCPU : public BaseCPU /** Wakes the CPU, rescheduling the CPU if it's not already active. */ void wakeCPU(); +#if FULL_SYSTEM + virtual void wakeup(); +#endif + /** Gets a free thread id. Use if thread ids change across system. */ ThreadID getFreeTid(); @@ -622,6 +652,14 @@ class InOrderCPU : public BaseCPU return total; } +#if FULL_SYSTEM + /** Pointer to the system. */ + System *system; + + /** Pointer to physical memory. */ + PhysicalMemory *physmem; +#endif + /** The global sequence number counter. */ InstSeqNum globalSeqNum[ThePipeline::MaxThreads]; diff --git a/src/cpu/inorder/inorder_cpu_builder.cc b/src/cpu/inorder/inorder_cpu_builder.cc index 5ee7b31db..a19137dd8 100644 --- a/src/cpu/inorder/inorder_cpu_builder.cc +++ b/src/cpu/inorder/inorder_cpu_builder.cc @@ -42,12 +42,17 @@ InOrderCPU * InOrderCPUParams::create() { +#if FULL_SYSTEM + // Full-system only supports a single thread for the moment. + ThreadID actual_num_threads = 1; +#else ThreadID actual_num_threads = (numThreads >= workload.size()) ? numThreads : workload.size(); if (workload.size() == 0) { fatal("Must specify at least one workload!"); } +#endif numThreads = actual_num_threads; diff --git a/src/cpu/inorder/inorder_dyn_inst.cc b/src/cpu/inorder/inorder_dyn_inst.cc index a6abb28b2..5ab839615 100644 --- a/src/cpu/inorder/inorder_dyn_inst.cc +++ b/src/cpu/inorder/inorder_dyn_inst.cc @@ -34,15 +34,14 @@ #include <string> #include <sstream> +#include "arch/faults.hh" #include "base/cprintf.hh" #include "base/trace.hh" - -#include "arch/faults.hh" +#include "config/the_isa.hh" #include "cpu/exetrace.hh" -#include "mem/request.hh" - -#include "cpu/inorder/inorder_dyn_inst.hh" #include "cpu/inorder/cpu.hh" +#include "cpu/inorder/inorder_dyn_inst.hh" +#include "mem/request.hh" using namespace std; using namespace TheISA; @@ -297,11 +296,39 @@ InOrderDynInst::memAccess() return initiateAcc(); } + +#if FULL_SYSTEM + +Fault +InOrderDynInst::hwrei() +{ + panic("InOrderDynInst: hwrei: unimplemented\n"); + return NoFault; +} + + +void +InOrderDynInst::trap(Fault fault) +{ + this->cpu->trap(fault, this->threadNumber); +} + + +bool +InOrderDynInst::simPalCheck(int palFunc) +{ +#if THE_ISA != ALPHA_ISA + panic("simPalCheck called, but PAL only exists in Alpha!\n"); +#endif + return this->cpu->simPalCheck(palFunc, this->threadNumber); +} +#else void InOrderDynInst::syscall(int64_t callnum) { cpu->syscall(callnum, this->threadNumber); } +#endif void InOrderDynInst::prefetch(Addr addr, unsigned flags) diff --git a/src/cpu/inorder/inorder_dyn_inst.hh b/src/cpu/inorder/inorder_dyn_inst.hh index e95a6d039..522b4e8d7 100644 --- a/src/cpu/inorder/inorder_dyn_inst.hh +++ b/src/cpu/inorder/inorder_dyn_inst.hh @@ -37,25 +37,31 @@ #include <list> #include <string> -#include "arch/isa_traits.hh" #include "arch/faults.hh" -#include "arch/types.hh" +#include "arch/isa_traits.hh" #include "arch/mt.hh" +#include "arch/types.hh" #include "base/fast_alloc.hh" #include "base/trace.hh" -#include "cpu/inorder/inorder_trace.hh" +#include "base/types.hh" #include "config/full_system.hh" -#include "cpu/thread_context.hh" +#include "config/the_isa.hh" #include "cpu/exetrace.hh" +#include "cpu/inorder/inorder_trace.hh" +#include "cpu/inorder/pipeline_traits.hh" +#include "cpu/inorder/resource.hh" +#include "cpu/inorder/thread_state.hh" #include "cpu/inst_seq.hh" #include "cpu/op_class.hh" #include "cpu/static_inst.hh" -#include "cpu/inorder/thread_state.hh" -#include "cpu/inorder/resource.hh" -#include "cpu/inorder/pipeline_traits.hh" +#include "cpu/thread_context.hh" #include "mem/packet.hh" #include "sim/system.hh" +#if THE_ISA == ALPHA_ISA +#include "arch/alpha/ev5.hh" +#endif + /** * @file * Defines a dynamic instruction context for a inorder CPU model. @@ -64,6 +70,7 @@ // Forward declaration. class StaticInstPtr; class ResourceRequest; +class Packet; class InOrderDynInst : public FastAlloc, public RefCounted { @@ -486,7 +493,16 @@ class InOrderDynInst : public FastAlloc, public RefCounted void setCurResSlot(unsigned slot_num) { curResSlot = slot_num; } /** Calls a syscall. */ +#if FULL_SYSTEM + /** Calls hardware return from error interrupt. */ + Fault hwrei(); + /** Traps to handle specified fault. */ + void trap(Fault fault); + bool simPalCheck(int palFunc); +#else + /** Calls a syscall. */ void syscall(int64_t callnum); +#endif void prefetch(Addr addr, unsigned flags); void writeHint(Addr addr, int size, unsigned flags); Fault copySrcTranslate(Addr src); diff --git a/src/cpu/inorder/inorder_trace.cc b/src/cpu/inorder/inorder_trace.cc index f12a1b7a9..90c94a4f5 100644 --- a/src/cpu/inorder/inorder_trace.cc +++ b/src/cpu/inorder/inorder_trace.cc @@ -31,6 +31,7 @@ #include <iomanip> +#include "config/the_isa.hh" #include "cpu/exetrace.hh" #include "cpu/inorder/inorder_trace.hh" #include "cpu/static_inst.hh" diff --git a/src/cpu/inorder/pipeline_stage.cc b/src/cpu/inorder/pipeline_stage.cc index 46b1cbad0..dc0378bf3 100644 --- a/src/cpu/inorder/pipeline_stage.cc +++ b/src/cpu/inorder/pipeline_stage.cc @@ -30,6 +30,7 @@ */ #include "base/str.hh" +#include "config/the_isa.hh" #include "cpu/inorder/pipeline_stage.hh" #include "cpu/inorder/resource_pool.hh" #include "cpu/inorder/cpu.hh" diff --git a/src/cpu/inorder/reg_dep_map.cc b/src/cpu/inorder/reg_dep_map.cc index a405b1fb9..51782a588 100644 --- a/src/cpu/inorder/reg_dep_map.cc +++ b/src/cpu/inorder/reg_dep_map.cc @@ -30,6 +30,7 @@ */ #include "arch/isa_traits.hh" +#include "config/the_isa.hh" #include "cpu/inorder/pipeline_traits.hh" #include "cpu/inorder/reg_dep_map.hh" #include "cpu/inorder/inorder_dyn_inst.hh" diff --git a/src/cpu/inorder/reg_dep_map.hh b/src/cpu/inorder/reg_dep_map.hh index ba2a8c8a3..b78e211bb 100644 --- a/src/cpu/inorder/reg_dep_map.hh +++ b/src/cpu/inorder/reg_dep_map.hh @@ -36,6 +36,7 @@ #include <vector> #include "arch/isa_traits.hh" +#include "config/the_isa.hh" #include "cpu/inorder/pipeline_traits.hh" class InOrderCPU; diff --git a/src/cpu/inorder/resource.hh b/src/cpu/inorder/resource.hh index 7935e5517..605b7f690 100644 --- a/src/cpu/inorder/resource.hh +++ b/src/cpu/inorder/resource.hh @@ -36,6 +36,7 @@ #include <list> #include <string> +#include "base/types.hh" #include "cpu/inst_seq.hh" #include "cpu/inorder/inorder_dyn_inst.hh" #include "cpu/inorder/pipeline_traits.hh" diff --git a/src/cpu/inorder/resources/bpred_unit.cc b/src/cpu/inorder/resources/bpred_unit.cc index 2ed8586aa..0e8526fa1 100644 --- a/src/cpu/inorder/resources/bpred_unit.cc +++ b/src/cpu/inorder/resources/bpred_unit.cc @@ -33,6 +33,7 @@ #include "base/trace.hh" #include "base/traceflags.hh" +#include "config/the_isa.hh" #include "cpu/inorder/resources/bpred_unit.hh" using namespace std; diff --git a/src/cpu/inorder/resources/branch_predictor.cc b/src/cpu/inorder/resources/branch_predictor.cc index 905de0794..ecac5fff0 100644 --- a/src/cpu/inorder/resources/branch_predictor.cc +++ b/src/cpu/inorder/resources/branch_predictor.cc @@ -29,6 +29,7 @@ * */ +#include "config/the_isa.hh" #include "cpu/inorder/resources/branch_predictor.hh" using namespace std; diff --git a/src/cpu/inorder/resources/cache_unit.cc b/src/cpu/inorder/resources/cache_unit.cc index 5677810f6..eb66e10f8 100644 --- a/src/cpu/inorder/resources/cache_unit.cc +++ b/src/cpu/inorder/resources/cache_unit.cc @@ -31,10 +31,12 @@ #include <vector> #include <list> + #include "arch/isa_traits.hh" #include "arch/locked_mem.hh" #include "arch/utility.hh" #include "arch/predecoder.hh" +#include "config/the_isa.hh" #include "cpu/inorder/resources/cache_unit.hh" #include "cpu/inorder/pipeline_traits.hh" #include "cpu/inorder/cpu.hh" diff --git a/src/cpu/inorder/resources/cache_unit.hh b/src/cpu/inorder/resources/cache_unit.hh index 8946ad5d3..c467e9771 100644 --- a/src/cpu/inorder/resources/cache_unit.hh +++ b/src/cpu/inorder/resources/cache_unit.hh @@ -36,17 +36,17 @@ #include <list> #include <string> -#include "arch/tlb.hh" #include "arch/predecoder.hh" -#include "cpu/inorder/resource.hh" +#include "arch/tlb.hh" +#include "config/the_isa.hh" #include "cpu/inorder/inorder_dyn_inst.hh" +#include "cpu/inorder/pipeline_traits.hh" +#include "cpu/inorder/resource.hh" #include "mem/packet.hh" #include "mem/packet_access.hh" #include "mem/port.hh" -#include "cpu/inorder/pipeline_traits.hh" -#include "sim/sim_object.hh" - #include "params/InOrderCPU.hh" +#include "sim/sim_object.hh" class CacheRequest; typedef CacheRequest* CacheReqPtr; diff --git a/src/cpu/inorder/resources/decode_unit.cc b/src/cpu/inorder/resources/decode_unit.cc index 033c318f2..33f5aba1a 100644 --- a/src/cpu/inorder/resources/decode_unit.cc +++ b/src/cpu/inorder/resources/decode_unit.cc @@ -29,6 +29,7 @@ * */ +#include "config/the_isa.hh" #include "cpu/inorder/resources/decode_unit.hh" using namespace TheISA; diff --git a/src/cpu/inorder/resources/fetch_seq_unit.cc b/src/cpu/inorder/resources/fetch_seq_unit.cc index bc809b040..1d0b92075 100644 --- a/src/cpu/inorder/resources/fetch_seq_unit.cc +++ b/src/cpu/inorder/resources/fetch_seq_unit.cc @@ -29,6 +29,7 @@ * */ +#include "config/the_isa.hh" #include "cpu/inorder/resources/fetch_seq_unit.hh" #include "cpu/inorder/resource_pool.hh" diff --git a/src/cpu/inorder/resources/fetch_seq_unit.hh b/src/cpu/inorder/resources/fetch_seq_unit.hh index 3e18d47cb..a4495564b 100644 --- a/src/cpu/inorder/resources/fetch_seq_unit.hh +++ b/src/cpu/inorder/resources/fetch_seq_unit.hh @@ -36,6 +36,7 @@ #include <list> #include <string> +#include "config/the_isa.hh" #include "cpu/inorder/resource.hh" #include "cpu/inorder/inorder_dyn_inst.hh" #include "cpu/inorder/pipeline_traits.hh" diff --git a/src/cpu/inorder/resources/inst_buffer.cc b/src/cpu/inorder/resources/inst_buffer.cc index 21df1d053..bb308b0ea 100644 --- a/src/cpu/inorder/resources/inst_buffer.cc +++ b/src/cpu/inorder/resources/inst_buffer.cc @@ -31,7 +31,9 @@ #include <vector> #include <list> + #include "arch/isa_traits.hh" +#include "config/the_isa.hh" #include "cpu/inorder/pipeline_traits.hh" #include "cpu/inorder/resources/inst_buffer.hh" #include "cpu/inorder/cpu.hh" diff --git a/src/cpu/inorder/resources/inst_buffer_new.cc b/src/cpu/inorder/resources/inst_buffer_new.cc index cc534ef3e..2e5a9666a 100644 --- a/src/cpu/inorder/resources/inst_buffer_new.cc +++ b/src/cpu/inorder/resources/inst_buffer_new.cc @@ -31,7 +31,9 @@ #include <vector> #include <list> + #include "arch/isa_traits.hh" +#include "config/the_isa.hh" #include "cpu/inorder/pipeline_traits.hh" #include "cpu/inorder/resources/inst_buffer.hh" #include "cpu/inorder/cpu.hh" diff --git a/src/cpu/inorder/resources/mult_div_unit.cc b/src/cpu/inorder/resources/mult_div_unit.cc index 7592c0260..e7bd6750f 100644 --- a/src/cpu/inorder/resources/mult_div_unit.cc +++ b/src/cpu/inorder/resources/mult_div_unit.cc @@ -91,7 +91,32 @@ MultDivUnit::freeSlot(int slot_idx) Resource::freeSlot(slot_idx); } - +//@TODO: Should we push this behavior into base-class to generically +// accomodate all multicyle resources? +void +MultDivUnit::requestAgain(DynInstPtr inst, bool &service_request) +{ + ResReqPtr mult_div_req = findRequest(inst); + assert(mult_div_req); + + service_request = true; + + // Check to see if this instruction is requesting the same command + // or a different one + if (mult_div_req->cmd != inst->resSched.top()->cmd) { + // If different, then update command in the request + mult_div_req->cmd = inst->resSched.top()->cmd; + DPRINTF(InOrderMDU, + "[tid:%i]: [sn:%i]: Updating the command for this instruction\n", + inst->readTid(), inst->seqNum); + } else { + // If same command, just check to see if memory access was completed + // but dont try to re-execute + DPRINTF(InOrderMDU, + "[tid:%i]: [sn:%i]: requesting this resource again\n", + inst->readTid(), inst->seqNum); + } +} int MultDivUnit::getSlot(DynInstPtr inst) { @@ -232,8 +257,13 @@ MultDivUnit::execute(int slot_num) // counting down the time { DPRINTF(InOrderMDU, "End MDU called ...\n"); - if (mult_div_req->getInst()->isExecuted()) + if (mult_div_req->getInst()->isExecuted()) { + DPRINTF(InOrderMDU, "Mult/Div finished.\n"); mult_div_req->done(); + } else { + mult_div_req->setCompleted(false); + } + } break; diff --git a/src/cpu/inorder/resources/mult_div_unit.hh b/src/cpu/inorder/resources/mult_div_unit.hh index 76180714c..d3dd0260d 100644 --- a/src/cpu/inorder/resources/mult_div_unit.hh +++ b/src/cpu/inorder/resources/mult_div_unit.hh @@ -82,6 +82,8 @@ class MultDivUnit : public Resource { /** Register extra resource stats */ virtual void regStats(); + void requestAgain(DynInstPtr inst, bool &try_request); + protected: /** Latency & Repeat Rate for Multiply Insts */ unsigned multRepeatRate; diff --git a/src/cpu/inorder/resources/tlb_unit.cc b/src/cpu/inorder/resources/tlb_unit.cc index 95bade36a..0410d6b24 100644 --- a/src/cpu/inorder/resources/tlb_unit.cc +++ b/src/cpu/inorder/resources/tlb_unit.cc @@ -31,7 +31,9 @@ #include <vector> #include <list> + #include "arch/isa_traits.hh" +#include "config/the_isa.hh" #include "cpu/inorder/pipeline_traits.hh" #include "cpu/inorder/first_stage.hh" #include "cpu/inorder/resources/tlb_unit.hh" diff --git a/src/cpu/inorder/resources/tlb_unit.hh b/src/cpu/inorder/resources/tlb_unit.hh index 1c08bd822..5c62c7751 100644 --- a/src/cpu/inorder/resources/tlb_unit.hh +++ b/src/cpu/inorder/resources/tlb_unit.hh @@ -36,6 +36,7 @@ #include <list> #include <string> +#include "config/the_isa.hh" #include "cpu/inorder/resources/inst_buffer.hh" #include "cpu/inorder/inorder_dyn_inst.hh" #include "cpu/inorder/pipeline_traits.hh" diff --git a/src/cpu/inorder/resources/use_def.cc b/src/cpu/inorder/resources/use_def.cc index 2f1652c08..36392d054 100644 --- a/src/cpu/inorder/resources/use_def.cc +++ b/src/cpu/inorder/resources/use_def.cc @@ -31,7 +31,9 @@ #include <vector> #include <list> + #include "arch/isa_traits.hh" +#include "config/the_isa.hh" #include "cpu/inorder/pipeline_traits.hh" #include "cpu/inorder/resources/use_def.hh" #include "cpu/inorder/cpu.hh" diff --git a/src/cpu/inorder/thread_context.cc b/src/cpu/inorder/thread_context.cc index fe1a0faa1..41d16b633 100644 --- a/src/cpu/inorder/thread_context.cc +++ b/src/cpu/inorder/thread_context.cc @@ -30,23 +30,77 @@ */ #include "arch/isa_traits.hh" +#include "config/the_isa.hh" #include "cpu/exetrace.hh" #include "cpu/inorder/thread_context.hh" using namespace TheISA; +#if FULL_SYSTEM + +VirtualPort * +InOrderThreadContext::getVirtPort() +{ + return thread->getVirtPort(); +} + + +void +InOrderThreadContext::dumpFuncProfile() +{ + thread->dumpFuncProfile(); +} + + +Tick +InOrderThreadContext::readLastActivate() +{ + return thread->lastActivate; +} + + +Tick +InOrderThreadContext::readLastSuspend() +{ + return thread->lastSuspend; +} + + +void +InOrderThreadContext::profileClear() +{ + thread->profileClear(); +} + + +void +InOrderThreadContext::profileSample() +{ + thread->profileSample(); +} +#endif + void InOrderThreadContext::takeOverFrom(ThreadContext *old_context) { // some things should already be set up + assert(getSystemPtr() == old_context->getSystemPtr()); +#if !FULL_SYSTEM assert(getProcessPtr() == old_context->getProcessPtr()); +#endif + + // copy over functional state setStatus(old_context->status()); copyArchRegs(old_context); +#if !FULL_SYSTEM thread->funcExeInst = old_context->readFuncExeInst(); +#endif + old_context->setStatus(ThreadContext::Halted); + thread->inSyscall = false; thread->trapPending = false; } @@ -97,8 +151,8 @@ void InOrderThreadContext::regStats(const std::string &name) { #if FULL_SYSTEM - thread->kernelStats = new Kernel::Statistics(cpu->system); - thread->kernelStats->regStats(name + ".kern"); + //thread->kernelStats = new Kernel::Statistics(cpu->system); + //thread->kernelStats->regStats(name + ".kern"); #endif ; } @@ -107,22 +161,14 @@ InOrderThreadContext::regStats(const std::string &name) void InOrderThreadContext::serialize(std::ostream &os) { -#if FULL_SYSTEM - if (thread->kernelStats) - thread->kernelStats->serialize(os); -#endif - ; + panic("serialize unimplemented"); } void InOrderThreadContext::unserialize(Checkpoint *cp, const std::string §ion) { -#if FULL_SYSTEM - if (thread->kernelStats) - thread->kernelStats->unserialize(cp, section); -#endif - ; + panic("unserialize unimplemented"); } TheISA::MachInst diff --git a/src/cpu/inorder/thread_context.hh b/src/cpu/inorder/thread_context.hh index 327f8ac71..820f3077f 100644 --- a/src/cpu/inorder/thread_context.hh +++ b/src/cpu/inorder/thread_context.hh @@ -32,6 +32,7 @@ #ifndef __CPU_INORDER_THREAD_CONTEXT_HH__ #define __CPU_INORDER_THREAD_CONTEXT_HH__ +#include "config/the_isa.hh" #include "cpu/exetrace.hh" #include "cpu/thread_context.hh" #include "cpu/inorder/thread_state.hh" @@ -101,10 +102,48 @@ class InOrderThreadContext : public ThreadContext virtual void setNextMicroPC(uint64_t val) { }; +#if FULL_SYSTEM + /** Returns a pointer to physical memory. */ + virtual PhysicalMemory *getPhysMemPtr() + { assert(0); return 0; /*return cpu->physmem;*/ } + + /** Returns a pointer to this thread's kernel statistics. */ + virtual TheISA::Kernel::Statistics *getKernelStats() + { return thread->kernelStats; } + + virtual FunctionalPort *getPhysPort() { return thread->getPhysPort(); } + + virtual VirtualPort *getVirtPort(); + + virtual void connectMemPorts(ThreadContext *tc) { thread->connectMemPorts(tc); } + + /** Dumps the function profiling information. + * @todo: Implement. + */ + virtual void dumpFuncProfile(); + + /** Reads the last tick that this thread was activated on. */ + virtual Tick readLastActivate(); + /** Reads the last tick that this thread was suspended on. */ + virtual Tick readLastSuspend(); + + /** Clears the function profiling information. */ + virtual void profileClear(); + + /** Samples the function profiling information. */ + virtual void profileSample(); + + /** Returns pointer to the quiesce event. */ + virtual EndQuiesceEvent *getQuiesceEvent() + { + return this->thread->quiesceEvent; + } +#else virtual TranslatingPort *getMemPort() { return thread->getMemPort(); } /** Returns a pointer to this thread's process. */ virtual Process *getProcessPtr() { return thread->getProcessPtr(); } +#endif /** Returns this thread's status. */ virtual Status status() const { return thread->status(); } @@ -232,9 +271,11 @@ class InOrderThreadContext : public ThreadContext * misspeculating, this is set as false. */ virtual bool misspeculating() { return false; } +#if !FULL_SYSTEM /** Executes a syscall in SE mode. */ virtual void syscall(int64_t callnum) { return cpu->syscall(callnum, thread->readTid()); } +#endif /** Reads the funcExeInst counter. */ virtual Counter readFuncExeInst() { return thread->funcExeInst; } diff --git a/src/mem/slicc/generator/fileio.hh b/src/cpu/inorder/thread_state.cc index 81b7306bc..b3a54efb1 100644 --- a/src/mem/slicc/generator/fileio.hh +++ b/src/cpu/inorder/thread_state.cc @@ -1,6 +1,5 @@ - /* - * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood + * Copyright (c) 2007 MIPS Technologies, Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -25,22 +24,24 @@ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/* - * fileio.hh - * - * Description: * - * $Id: fileio.hh,v 3.2 2003/02/24 20:54:25 xu Exp $ + * Authors: Korey Sewell * - * */ + */ -#ifndef FILEIO_H -#define FILEIO_H +#include "arch/isa_traits.hh" +#include "cpu/exetrace.hh" +#include "cpu/inorder/thread_state.hh" +#include "cpu/inorder/cpu.hh" -#include "mem/slicc/slicc_global.hh" +using namespace TheISA; -void conditionally_write_file(string filename, ostringstream& sstr); +#if FULL_SYSTEM +void +InOrderThreadState::dumpFuncProfile() +{ + std::ostream *os = simout.create(csprintf("profile.%s.dat", cpu->name())); + profile->dump(tc, *os); +} +#endif -#endif //FILEIO_H diff --git a/src/cpu/inorder/thread_state.hh b/src/cpu/inorder/thread_state.hh index 9b3b39fcb..422df30aa 100644 --- a/src/cpu/inorder/thread_state.hh +++ b/src/cpu/inorder/thread_state.hh @@ -33,13 +33,23 @@ #include "arch/faults.hh" #include "arch/isa_traits.hh" +#include "base/callback.hh" +#include "base/output.hh" #include "cpu/thread_context.hh" #include "cpu/thread_state.hh" +#include "sim/sim_exit.hh" class Event; +class InOrderCPU; + +#if FULL_SYSTEM +class EndQuiesceEvent; +class FunctionProfile; +class ProfileNode; +#else class FunctionalMemory; class Process; -class InOrderCPU; +#endif /** * Class that has various thread state, such as the status, the @@ -66,16 +76,28 @@ class InOrderThreadState : public ThreadState { */ bool trapPending; - +#if FULL_SYSTEM + InOrderThreadState(InOrderCPU *_cpu, ThreadID _thread_num) + : ThreadState(reinterpret_cast<BaseCPU*>(_cpu), _thread_num), + cpu(_cpu), inSyscall(0), trapPending(0) + { } +#else InOrderThreadState(InOrderCPU *_cpu, ThreadID _thread_num, Process *_process) - : ThreadState(reinterpret_cast<BaseCPU*>(_cpu), 0/*_thread_num*/, + : ThreadState(reinterpret_cast<BaseCPU*>(_cpu), _thread_num, _process), cpu(_cpu), inSyscall(0), trapPending(0) { } +#endif +#if !FULL_SYSTEM /** Handles the syscall. */ void syscall(int64_t callnum) { process->syscall(callnum, tc); } +#endif + +#if FULL_SYSTEM + void dumpFuncProfile(); +#endif /** Pointer to the ThreadContext of this thread. */ ThreadContext *tc; @@ -83,7 +105,7 @@ class InOrderThreadState : public ThreadState { /** Returns a pointer to the TC of this thread. */ ThreadContext *getTC() { return tc; } - int readTid() { return 0; } + int readTid() { return threadId(); } /** Pointer to the last graduated instruction in the thread */ //DynInstPtr lastGradInst; diff --git a/src/cpu/inst_seq.hh b/src/cpu/inst_seq.hh index 21e04ed25..b5feaf584 100644 --- a/src/cpu/inst_seq.hh +++ b/src/cpu/inst_seq.hh @@ -32,6 +32,8 @@ #ifndef __STD_TYPES_HH__ #define __STD_TYPES_HH__ +#include "base/types.hh" + // inst sequence type, used to order instructions in the ready list, // if this rolls over the ready list order temporarily will get messed // up, but execution will continue and complete correctly diff --git a/src/cpu/inteltrace.cc b/src/cpu/inteltrace.cc index 145075dc1..ec51b80e7 100644 --- a/src/cpu/inteltrace.cc +++ b/src/cpu/inteltrace.cc @@ -33,6 +33,7 @@ #include <iomanip> +#include "config/the_isa.hh" #include "cpu/exetrace.hh" #include "cpu/inteltrace.hh" #include "cpu/static_inst.hh" diff --git a/src/cpu/legiontrace.cc b/src/cpu/legiontrace.cc index 5face4391..1390d0807 100644 --- a/src/cpu/legiontrace.cc +++ b/src/cpu/legiontrace.cc @@ -31,7 +31,7 @@ * Steve Raasch */ -#include "arch/isa_specific.hh" +#include "config/the_isa.hh" #if THE_ISA != SPARC_ISA #error Legion tracing only works with SPARC simulations! #endif @@ -41,10 +41,12 @@ #error Legion tracing only works in full system! #endif -#include <iomanip> #include <sys/ipc.h> #include <sys/shm.h> +#include <cstdio> +#include <iomanip> + #include "arch/sparc/predecoder.hh" #include "arch/sparc/registers.hh" #include "arch/sparc/utility.hh" diff --git a/src/cpu/memtest/MemTest.py b/src/cpu/memtest/MemTest.py index 629fd4877..8e1b3a8d0 100644 --- a/src/cpu/memtest/MemTest.py +++ b/src/cpu/memtest/MemTest.py @@ -29,7 +29,6 @@ from MemObject import MemObject from m5.params import * from m5.proxy import * -from m5 import build_env class MemTest(MemObject): type = 'MemTest' diff --git a/src/cpu/o3/O3CPU.py b/src/cpu/o3/O3CPU.py index 56e537ad2..3f2210e44 100644 --- a/src/cpu/o3/O3CPU.py +++ b/src/cpu/o3/O3CPU.py @@ -26,21 +26,21 @@ # # Authors: Kevin Lim +from m5.defines import buildEnv from m5.params import * from m5.proxy import * -from m5 import build_env from BaseCPU import BaseCPU from FUPool import * -if build_env['USE_CHECKER']: +if buildEnv['USE_CHECKER']: from O3Checker import O3Checker class DerivO3CPU(BaseCPU): type = 'DerivO3CPU' activity = Param.Unsigned(0, "Initial count") - if build_env['USE_CHECKER']: - if not build_env['FULL_SYSTEM']: + if buildEnv['USE_CHECKER']: + if not buildEnv['FULL_SYSTEM']: checker = Param.BaseCPU(O3Checker(workload=Parent.workload, exitOnError=False, updateOnError=True, diff --git a/src/cpu/o3/O3Checker.py b/src/cpu/o3/O3Checker.py index edc6dc9b6..d0c4ce537 100644 --- a/src/cpu/o3/O3Checker.py +++ b/src/cpu/o3/O3Checker.py @@ -27,7 +27,6 @@ # Authors: Nathan Binkert from m5.params import * -from m5 import build_env from BaseCPU import BaseCPU class O3Checker(BaseCPU): diff --git a/src/cpu/o3/bpred_unit_impl.hh b/src/cpu/o3/bpred_unit_impl.hh index 1378ac135..ed3471761 100644 --- a/src/cpu/o3/bpred_unit_impl.hh +++ b/src/cpu/o3/bpred_unit_impl.hh @@ -28,16 +28,16 @@ * Authors: Kevin Lim */ +#include <algorithm> + #include "arch/types.hh" #include "arch/isa_traits.hh" #include "base/trace.hh" #include "base/traceflags.hh" +#include "config/the_isa.hh" #include "cpu/o3/bpred_unit.hh" - #include "params/DerivO3CPU.hh" -#include <algorithm> - template<class Impl> BPredUnit<Impl>::BPredUnit(DerivO3CPUParams *params) : _name(params->name + ".BPredUnit"), diff --git a/src/cpu/o3/commit_impl.hh b/src/cpu/o3/commit_impl.hh index 7286f1b6f..cb5f23814 100644 --- a/src/cpu/o3/commit_impl.hh +++ b/src/cpu/o3/commit_impl.hh @@ -37,6 +37,7 @@ #include "base/loader/symtab.hh" #include "base/timebuf.hh" #include "config/full_system.hh" +#include "config/the_isa.hh" #include "config/use_checker.hh" #include "cpu/exetrace.hh" #include "cpu/o3/commit.hh" @@ -1075,9 +1076,11 @@ DefaultCommit<Impl>::commitHead(DynInstPtr &head_inst, unsigned inst_num) commitStatus[tid] = TrapPending; if (head_inst->traceData) { - head_inst->traceData->setFetchSeq(head_inst->seqNum); - head_inst->traceData->setCPSeq(thread[tid]->numInst); - head_inst->traceData->dump(); + if (DTRACE(ExecFaulting)) { + head_inst->traceData->setFetchSeq(head_inst->seqNum); + head_inst->traceData->setCPSeq(thread[tid]->numInst); + head_inst->traceData->dump(); + } delete head_inst->traceData; head_inst->traceData = NULL; } diff --git a/src/cpu/o3/cpu.cc b/src/cpu/o3/cpu.cc index 6722941e4..2a4e0176a 100644 --- a/src/cpu/o3/cpu.cc +++ b/src/cpu/o3/cpu.cc @@ -30,8 +30,8 @@ */ #include "config/full_system.hh" +#include "config/the_isa.hh" #include "config/use_checker.hh" - #include "cpu/activity.hh" #include "cpu/simple_thread.hh" #include "cpu/thread_context.hh" @@ -200,7 +200,6 @@ FullO3CPU<Impl>::FullO3CPU(DerivO3CPUParams *params) globalSeqNum(1), #if FULL_SYSTEM system(params->system), - physmem(system->physmem), #endif // FULL_SYSTEM drainCount(0), deferRegistration(params->defer_registration) diff --git a/src/cpu/o3/cpu.hh b/src/cpu/o3/cpu.hh index 0cc8eab78..2ea918983 100644 --- a/src/cpu/o3/cpu.hh +++ b/src/cpu/o3/cpu.hh @@ -42,6 +42,7 @@ #include "base/statistics.hh" #include "base/timebuf.hh" #include "config/full_system.hh" +#include "config/the_isa.hh" #include "config/use_checker.hh" #include "cpu/activity.hh" #include "cpu/base.hh" @@ -668,9 +669,6 @@ class FullO3CPU : public BaseO3CPU #if FULL_SYSTEM /** Pointer to the system. */ System *system; - - /** Pointer to physical memory. */ - PhysicalMemory *physmem; #endif /** Event to call process() on once draining has completed. */ diff --git a/src/cpu/o3/decode_impl.hh b/src/cpu/o3/decode_impl.hh index 86f87991c..1b76de132 100644 --- a/src/cpu/o3/decode_impl.hh +++ b/src/cpu/o3/decode_impl.hh @@ -28,6 +28,7 @@ * Authors: Kevin Lim */ +#include "config/the_isa.hh" #include "cpu/o3/decode.hh" #include "params/DerivO3CPU.hh" diff --git a/src/cpu/o3/dyn_inst.hh b/src/cpu/o3/dyn_inst.hh index 3ef42e91f..e1279f82b 100644 --- a/src/cpu/o3/dyn_inst.hh +++ b/src/cpu/o3/dyn_inst.hh @@ -32,6 +32,7 @@ #define __CPU_O3_DYN_INST_HH__ #include "arch/isa_traits.hh" +#include "config/the_isa.hh" #include "cpu/base_dyn_inst.hh" #include "cpu/inst_seq.hh" #include "cpu/o3/cpu.hh" diff --git a/src/cpu/o3/fetch.hh b/src/cpu/o3/fetch.hh index 9cbc50899..425c34428 100644 --- a/src/cpu/o3/fetch.hh +++ b/src/cpu/o3/fetch.hh @@ -36,6 +36,7 @@ #include "arch/predecoder.hh" #include "base/statistics.hh" #include "base/timebuf.hh" +#include "config/the_isa.hh" #include "cpu/pc_event.hh" #include "mem/packet.hh" #include "mem/port.hh" diff --git a/src/cpu/o3/fetch_impl.hh b/src/cpu/o3/fetch_impl.hh index 3781113bd..e6815ef8a 100644 --- a/src/cpu/o3/fetch_impl.hh +++ b/src/cpu/o3/fetch_impl.hh @@ -35,6 +35,7 @@ #include "arch/isa_traits.hh" #include "arch/utility.hh" #include "base/types.hh" +#include "config/the_isa.hh" #include "config/use_checker.hh" #include "cpu/checker/cpu.hh" #include "cpu/exetrace.hh" @@ -1263,6 +1264,8 @@ DefaultFetch<Impl>::fetch(bool &status_change) toDecode->insts[numInst] = instruction; toDecode->size++; + wroteToTimeBuffer = true; + DPRINTF(Fetch, "[tid:%i]: Blocked, need to handle the trap.\n",tid); fetchStatus[tid] = TrapPending; diff --git a/src/cpu/o3/free_list.hh b/src/cpu/o3/free_list.hh index e28c4910e..96289f641 100644 --- a/src/cpu/o3/free_list.hh +++ b/src/cpu/o3/free_list.hh @@ -38,6 +38,7 @@ #include "base/misc.hh" #include "base/trace.hh" #include "base/traceflags.hh" +#include "config/the_isa.hh" #include "cpu/o3/comm.hh" /** diff --git a/src/cpu/o3/iew_impl.hh b/src/cpu/o3/iew_impl.hh index ba29df196..751a26afd 100644 --- a/src/cpu/o3/iew_impl.hh +++ b/src/cpu/o3/iew_impl.hh @@ -35,6 +35,7 @@ #include <queue> #include "base/timebuf.hh" +#include "config/the_isa.hh" #include "cpu/o3/fu_pool.hh" #include "cpu/o3/iew.hh" #include "params/DerivO3CPU.hh" diff --git a/src/cpu/o3/impl.hh b/src/cpu/o3/impl.hh index 4b29b4daa..ffccd4a84 100644 --- a/src/cpu/o3/impl.hh +++ b/src/cpu/o3/impl.hh @@ -32,7 +32,7 @@ #define __CPU_O3_IMPL_HH__ #include "arch/isa_traits.hh" - +#include "config/the_isa.hh" #include "cpu/o3/cpu_policy.hh" diff --git a/src/cpu/o3/lsq_unit.hh b/src/cpu/o3/lsq_unit.hh index a917caef3..6ff36d929 100644 --- a/src/cpu/o3/lsq_unit.hh +++ b/src/cpu/o3/lsq_unit.hh @@ -40,6 +40,7 @@ #include "arch/faults.hh" #include "arch/locked_mem.hh" #include "config/full_system.hh" +#include "config/the_isa.hh" #include "base/fast_alloc.hh" #include "base/hashmap.hh" #include "cpu/inst_seq.hh" diff --git a/src/cpu/o3/lsq_unit_impl.hh b/src/cpu/o3/lsq_unit_impl.hh index edc8c9b3f..9ee1de45a 100644 --- a/src/cpu/o3/lsq_unit_impl.hh +++ b/src/cpu/o3/lsq_unit_impl.hh @@ -30,8 +30,8 @@ */ #include "arch/locked_mem.hh" +#include "config/the_isa.hh" #include "config/use_checker.hh" - #include "cpu/o3/lsq.hh" #include "cpu/o3/lsq_unit.hh" #include "base/str.hh" diff --git a/src/cpu/o3/regfile.hh b/src/cpu/o3/regfile.hh index d6beecdc5..e252fa362 100644 --- a/src/cpu/o3/regfile.hh +++ b/src/cpu/o3/regfile.hh @@ -32,18 +32,19 @@ #ifndef __CPU_O3_REGFILE_HH__ #define __CPU_O3_REGFILE_HH__ +#include <vector> + #include "arch/isa_traits.hh" #include "arch/types.hh" #include "base/trace.hh" #include "config/full_system.hh" +#include "config/the_isa.hh" #include "cpu/o3/comm.hh" #if FULL_SYSTEM #include "arch/kernel_stats.hh" #endif -#include <vector> - /** * Simple physical register file class. * Right now this is specific to Alpha until we decide if/how to make things diff --git a/src/cpu/o3/rename.hh b/src/cpu/o3/rename.hh index 734b63105..8c21dda0a 100644 --- a/src/cpu/o3/rename.hh +++ b/src/cpu/o3/rename.hh @@ -35,6 +35,7 @@ #include "base/statistics.hh" #include "base/timebuf.hh" +#include "config/the_isa.hh" class DerivO3CPUParams; diff --git a/src/cpu/o3/rename_impl.hh b/src/cpu/o3/rename_impl.hh index e4cc2674b..ce206435c 100644 --- a/src/cpu/o3/rename_impl.hh +++ b/src/cpu/o3/rename_impl.hh @@ -34,6 +34,7 @@ #include "arch/isa_traits.hh" #include "arch/registers.hh" #include "config/full_system.hh" +#include "config/the_isa.hh" #include "cpu/o3/rename.hh" #include "params/DerivO3CPU.hh" diff --git a/src/cpu/o3/rename_map.hh b/src/cpu/o3/rename_map.hh index 896c66f3e..51d8db4d8 100644 --- a/src/cpu/o3/rename_map.hh +++ b/src/cpu/o3/rename_map.hh @@ -39,8 +39,9 @@ #include <utility> #include <vector> -#include "cpu/o3/free_list.hh" #include "arch/types.hh" +#include "config/the_isa.hh" +#include "cpu/o3/free_list.hh" class SimpleRenameMap { diff --git a/src/cpu/o3/rob.hh b/src/cpu/o3/rob.hh index 657bc8d06..bdea07d1a 100644 --- a/src/cpu/o3/rob.hh +++ b/src/cpu/o3/rob.hh @@ -36,6 +36,8 @@ #include <utility> #include <vector> +#include "config/the_isa.hh" + /** * ROB class. The ROB is largely what drives squashing. */ diff --git a/src/cpu/o3/scoreboard.cc b/src/cpu/o3/scoreboard.cc index e7f8b7949..ae1e13717 100644 --- a/src/cpu/o3/scoreboard.cc +++ b/src/cpu/o3/scoreboard.cc @@ -29,7 +29,7 @@ * Kevin Lim */ -#include "arch/isa_specific.hh" +#include "config/the_isa.hh" #include "cpu/o3/scoreboard.hh" Scoreboard::Scoreboard(unsigned activeThreads, diff --git a/src/cpu/o3/thread_context.hh b/src/cpu/o3/thread_context.hh index ed5c6ac20..78b266014 100755 --- a/src/cpu/o3/thread_context.hh +++ b/src/cpu/o3/thread_context.hh @@ -31,6 +31,7 @@ #ifndef __CPU_O3_THREAD_CONTEXT_HH__ #define __CPU_O3_THREAD_CONTEXT_HH__ +#include "config/the_isa.hh" #include "cpu/thread_context.hh" #include "cpu/o3/isa_specific.hh" @@ -90,9 +91,6 @@ class O3ThreadContext : public ThreadContext virtual System *getSystemPtr() { return cpu->system; } #if FULL_SYSTEM - /** Returns a pointer to physical memory. */ - virtual PhysicalMemory *getPhysMemPtr() { return cpu->physmem; } - /** Returns a pointer to this thread's kernel statistics. */ virtual TheISA::Kernel::Statistics *getKernelStats() { return thread->kernelStats; } diff --git a/src/cpu/o3/thread_context_impl.hh b/src/cpu/o3/thread_context_impl.hh index e631c9244..940d460ce 100755 --- a/src/cpu/o3/thread_context_impl.hh +++ b/src/cpu/o3/thread_context_impl.hh @@ -30,6 +30,7 @@ */ #include "arch/registers.hh" +#include "config/the_isa.hh" #include "cpu/o3/thread_context.hh" #include "cpu/quiesce_event.hh" diff --git a/src/cpu/ozone/OzoneCPU.py b/src/cpu/ozone/OzoneCPU.py index 37386898d..2c7b8475f 100644 --- a/src/cpu/ozone/OzoneCPU.py +++ b/src/cpu/ozone/OzoneCPU.py @@ -26,11 +26,11 @@ # # Authors: Kevin Lim +from m5.defines import buildEnv from m5.params import * -from m5 import build_env from BaseCPU import BaseCPU -if build_env['USE_CHECKER']: +if buildEnv['USE_CHECKER']: from OzoneChecker import OzoneChecker class DerivOzoneCPU(BaseCPU): @@ -38,7 +38,7 @@ class DerivOzoneCPU(BaseCPU): numThreads = Param.Unsigned("number of HW thread contexts") - if build_env['USE_CHECKER']: + if buildEnv['USE_CHECKER']: checker = Param.BaseCPU("Checker CPU") icache_port = Port("Instruction Port") diff --git a/src/cpu/ozone/OzoneChecker.py b/src/cpu/ozone/OzoneChecker.py index bfa39ead9..bbe46db18 100644 --- a/src/cpu/ozone/OzoneChecker.py +++ b/src/cpu/ozone/OzoneChecker.py @@ -27,7 +27,6 @@ # Authors: Nathan Binkert from m5.params import * -from m5 import build_env from BaseCPU import BaseCPU class OzoneChecker(BaseCPU): diff --git a/src/cpu/ozone/SimpleOzoneCPU.py b/src/cpu/ozone/SimpleOzoneCPU.py index 93603092b..d4620cd8e 100644 --- a/src/cpu/ozone/SimpleOzoneCPU.py +++ b/src/cpu/ozone/SimpleOzoneCPU.py @@ -26,8 +26,8 @@ # # Authors: Kevin Lim +from m5.defines import buildEnv from m5.params import * -from m5 import build_env from BaseCPU import BaseCPU class SimpleOzoneCPU(BaseCPU): @@ -35,7 +35,7 @@ class SimpleOzoneCPU(BaseCPU): numThreads = Param.Unsigned("number of HW thread contexts") - if not build_env['FULL_SYSTEM']: + if not buildEnv['FULL_SYSTEM']: mem = Param.FunctionalMemory(NULL, "memory") width = Param.Unsigned("Width") diff --git a/src/cpu/ozone/cpu.hh b/src/cpu/ozone/cpu.hh index 5e36332af..a16986c99 100644 --- a/src/cpu/ozone/cpu.hh +++ b/src/cpu/ozone/cpu.hh @@ -36,6 +36,7 @@ #include "base/statistics.hh" #include "base/timebuf.hh" #include "config/full_system.hh" +#include "config/the_isa.hh" #include "cpu/base.hh" #include "cpu/thread_context.hh" #include "cpu/inst_seq.hh" diff --git a/src/cpu/ozone/cpu_impl.hh b/src/cpu/ozone/cpu_impl.hh index f86b882d1..c09dd9046 100644 --- a/src/cpu/ozone/cpu_impl.hh +++ b/src/cpu/ozone/cpu_impl.hh @@ -34,6 +34,7 @@ #include "arch/isa_traits.hh" // For MachInst #include "base/trace.hh" +#include "config/the_isa.hh" #include "cpu/base.hh" #include "cpu/simple_thread.hh" #include "cpu/thread_context.hh" diff --git a/src/cpu/ozone/dyn_inst.hh b/src/cpu/ozone/dyn_inst.hh index a39f383ba..cca72ef18 100644 --- a/src/cpu/ozone/dyn_inst.hh +++ b/src/cpu/ozone/dyn_inst.hh @@ -34,6 +34,7 @@ #include "arch/isa_traits.hh" #include "arch/types.hh" #include "config/full_system.hh" +#include "config/the_isa.hh" #include "cpu/base_dyn_inst.hh" #include "cpu/inst_seq.hh" #include "cpu/ozone/cpu.hh" // MUST include this diff --git a/src/cpu/ozone/dyn_inst_impl.hh b/src/cpu/ozone/dyn_inst_impl.hh index 8519917f5..bfefb9428 100644 --- a/src/cpu/ozone/dyn_inst_impl.hh +++ b/src/cpu/ozone/dyn_inst_impl.hh @@ -30,6 +30,7 @@ #include "sim/faults.hh" #include "config/full_system.hh" +#include "config/the_isa.hh" #include "cpu/ozone/dyn_inst.hh" #if FULL_SYSTEM diff --git a/src/cpu/ozone/front_end.hh b/src/cpu/ozone/front_end.hh index 38fc89e3f..3809db00d 100644 --- a/src/cpu/ozone/front_end.hh +++ b/src/cpu/ozone/front_end.hh @@ -35,6 +35,7 @@ #include "arch/utility.hh" #include "base/timebuf.hh" +#include "config/the_isa.hh" #include "cpu/inst_seq.hh" #include "cpu/o3/bpred_unit.hh" #include "cpu/ozone/rename_table.hh" diff --git a/src/cpu/ozone/front_end_impl.hh b/src/cpu/ozone/front_end_impl.hh index 516823b47..884136927 100644 --- a/src/cpu/ozone/front_end_impl.hh +++ b/src/cpu/ozone/front_end_impl.hh @@ -28,12 +28,12 @@ * Authors: Kevin Lim */ -#include "config/use_checker.hh" - #include "sim/faults.hh" #include "arch/isa_traits.hh" #include "arch/utility.hh" #include "base/statistics.hh" +#include "config/the_isa.hh" +#include "config/use_checker.hh" #include "cpu/thread_context.hh" #include "cpu/exetrace.hh" #include "cpu/ozone/front_end.hh" diff --git a/src/cpu/ozone/inorder_back_end_impl.hh b/src/cpu/ozone/inorder_back_end_impl.hh index 798b628d6..2d4d225c7 100644 --- a/src/cpu/ozone/inorder_back_end_impl.hh +++ b/src/cpu/ozone/inorder_back_end_impl.hh @@ -30,6 +30,7 @@ #include "sim/faults.hh" #include "arch/types.hh" +#include "config/the_isa.hh" #include "cpu/ozone/inorder_back_end.hh" #include "cpu/ozone/thread_state.hh" diff --git a/src/cpu/ozone/lsq_unit.hh b/src/cpu/ozone/lsq_unit.hh index 47be245e5..d8e402b65 100644 --- a/src/cpu/ozone/lsq_unit.hh +++ b/src/cpu/ozone/lsq_unit.hh @@ -38,6 +38,7 @@ #include "arch/faults.hh" #include "arch/types.hh" #include "config/full_system.hh" +#include "config/the_isa.hh" #include "base/hashmap.hh" #include "cpu/inst_seq.hh" #include "mem/mem_interface.hh" diff --git a/src/cpu/ozone/lsq_unit_impl.hh b/src/cpu/ozone/lsq_unit_impl.hh index 833aa0581..dd44adf6e 100644 --- a/src/cpu/ozone/lsq_unit_impl.hh +++ b/src/cpu/ozone/lsq_unit_impl.hh @@ -30,6 +30,7 @@ #include "arch/faults.hh" #include "base/str.hh" +#include "config/the_isa.hh" #include "cpu/ozone/lsq_unit.hh" template <class Impl> diff --git a/src/cpu/ozone/lw_back_end_impl.hh b/src/cpu/ozone/lw_back_end_impl.hh index 86d4531a0..cbc386cb0 100644 --- a/src/cpu/ozone/lw_back_end_impl.hh +++ b/src/cpu/ozone/lw_back_end_impl.hh @@ -28,8 +28,8 @@ * Authors: Kevin Lim */ +#include "config/the_isa.hh" #include "config/use_checker.hh" - #include "cpu/ozone/lw_back_end.hh" #include "cpu/op_class.hh" diff --git a/src/cpu/ozone/lw_lsq.hh b/src/cpu/ozone/lw_lsq.hh index 6e9bb77af..ee0312969 100644 --- a/src/cpu/ozone/lw_lsq.hh +++ b/src/cpu/ozone/lw_lsq.hh @@ -39,6 +39,7 @@ #include "arch/faults.hh" #include "arch/types.hh" #include "config/full_system.hh" +#include "config/the_isa.hh" #include "base/fast_alloc.hh" #include "base/hashmap.hh" #include "cpu/inst_seq.hh" diff --git a/src/cpu/ozone/lw_lsq_impl.hh b/src/cpu/ozone/lw_lsq_impl.hh index 4d290a1e9..c714c5d38 100644 --- a/src/cpu/ozone/lw_lsq_impl.hh +++ b/src/cpu/ozone/lw_lsq_impl.hh @@ -28,10 +28,10 @@ * Authors: Kevin Lim */ -#include "config/use_checker.hh" - #include "arch/faults.hh" #include "base/str.hh" +#include "config/the_isa.hh" +#include "config/use_checker.hh" #include "cpu/ozone/lw_lsq.hh" #include "cpu/checker/cpu.hh" diff --git a/src/cpu/ozone/rename_table.hh b/src/cpu/ozone/rename_table.hh index 0b67d9635..9a5579158 100644 --- a/src/cpu/ozone/rename_table.hh +++ b/src/cpu/ozone/rename_table.hh @@ -32,6 +32,7 @@ #define __CPU_OZONE_RENAME_TABLE_HH__ #include "arch/isa_traits.hh" +#include "config/the_isa.hh" /** Rename table that holds the rename of each architectural register to * producing DynInst. Needs to support copying from one table to another. diff --git a/src/cpu/ozone/rename_table_impl.hh b/src/cpu/ozone/rename_table_impl.hh index 67bab7337..e8071e2b3 100644 --- a/src/cpu/ozone/rename_table_impl.hh +++ b/src/cpu/ozone/rename_table_impl.hh @@ -29,6 +29,8 @@ */ #include <cstdlib> // Not really sure what to include to get NULL + +#include "config/the_isa.hh" #include "cpu/ozone/rename_table.hh" template <class Impl> diff --git a/src/cpu/ozone/simple_params.hh b/src/cpu/ozone/simple_params.hh index 7687fdf60..b241dea73 100644 --- a/src/cpu/ozone/simple_params.hh +++ b/src/cpu/ozone/simple_params.hh @@ -31,6 +31,7 @@ #ifndef __CPU_OZONE_SIMPLE_PARAMS_HH__ #define __CPU_OZONE_SIMPLE_PARAMS_HH__ +#include "config/the_isa.hh" #include "cpu/ozone/cpu.hh" //Forward declarations diff --git a/src/cpu/ozone/thread_state.hh b/src/cpu/ozone/thread_state.hh index 971fba886..638b9d86c 100644 --- a/src/cpu/ozone/thread_state.hh +++ b/src/cpu/ozone/thread_state.hh @@ -31,13 +31,14 @@ #ifndef __CPU_OZONE_THREAD_STATE_HH__ #define __CPU_OZONE_THREAD_STATE_HH__ -#include "sim/faults.hh" -#include "arch/types.hh" #include "arch/regfile.hh" +#include "arch/types.hh" #include "base/callback.hh" #include "base/output.hh" +#include "config/the_isa.hh" #include "cpu/thread_context.hh" #include "cpu/thread_state.hh" +#include "sim/faults.hh" #include "sim/process.hh" #include "sim/sim_exit.hh" diff --git a/src/cpu/profile.hh b/src/cpu/profile.hh index 9606ed24d..dd856b5a7 100644 --- a/src/cpu/profile.hh +++ b/src/cpu/profile.hh @@ -34,6 +34,7 @@ #include <map> #include "arch/stacktrace.hh" +#include "config/the_isa.hh" #include "cpu/static_inst.hh" #include "base/types.hh" diff --git a/src/cpu/simple/AtomicSimpleCPU.py b/src/cpu/simple/AtomicSimpleCPU.py index b7174bb43..3d72f4098 100644 --- a/src/cpu/simple/AtomicSimpleCPU.py +++ b/src/cpu/simple/AtomicSimpleCPU.py @@ -27,7 +27,6 @@ # Authors: Nathan Binkert from m5.params import * -from m5 import build_env from BaseSimpleCPU import BaseSimpleCPU class AtomicSimpleCPU(BaseSimpleCPU): diff --git a/src/cpu/simple/TimingSimpleCPU.py b/src/cpu/simple/TimingSimpleCPU.py index ce6839241..6b83c41aa 100644 --- a/src/cpu/simple/TimingSimpleCPU.py +++ b/src/cpu/simple/TimingSimpleCPU.py @@ -27,7 +27,6 @@ # Authors: Nathan Binkert from m5.params import * -from m5 import build_env from BaseSimpleCPU import BaseSimpleCPU class TimingSimpleCPU(BaseSimpleCPU): diff --git a/src/cpu/simple/atomic.cc b/src/cpu/simple/atomic.cc index 83da618f8..05b4ca3e2 100644 --- a/src/cpu/simple/atomic.cc +++ b/src/cpu/simple/atomic.cc @@ -32,6 +32,7 @@ #include "arch/mmaped_ipr.hh" #include "arch/utility.hh" #include "base/bigint.hh" +#include "config/the_isa.hh" #include "cpu/exetrace.hh" #include "cpu/simple/atomic.hh" #include "mem/packet.hh" @@ -170,6 +171,9 @@ AtomicSimpleCPU::AtomicSimpleCPU(AtomicSimpleCPUParams *p) AtomicSimpleCPU::~AtomicSimpleCPU() { + if (tickEvent.scheduled()) { + deschedule(tickEvent); + } } void @@ -352,8 +356,14 @@ AtomicSimpleCPU::read(Addr addr, T &data, unsigned flags) recordEvent("Uncached Read"); //If there's a fault, return it - if (fault != NoFault) - return fault; + if (fault != NoFault) { + if (req->isPrefetch()) { + return NoFault; + } else { + return fault; + } + } + //If we don't need to access a second cache line, stop now. if (secondAddr <= addr) { @@ -530,7 +540,11 @@ AtomicSimpleCPU::write(T data, Addr addr, unsigned flags, uint64_t *res) assert(locked); locked = false; } - return fault; + if (fault != NoFault && req->isPrefetch()) { + return NoFault; + } else { + return fault; + } } /* diff --git a/src/cpu/simple/base.cc b/src/cpu/simple/base.cc index 732bb637b..0104e1b1f 100644 --- a/src/cpu/simple/base.cc +++ b/src/cpu/simple/base.cc @@ -40,6 +40,7 @@ #include "base/stats/events.hh" #include "base/trace.hh" #include "base/types.hh" +#include "config/the_isa.hh" #include "cpu/base.hh" #include "cpu/exetrace.hh" #include "cpu/profile.hh" diff --git a/src/cpu/simple/base.hh b/src/cpu/simple/base.hh index 466d0d1c9..39961fb88 100644 --- a/src/cpu/simple/base.hh +++ b/src/cpu/simple/base.hh @@ -36,6 +36,7 @@ #include "arch/predecoder.hh" #include "base/statistics.hh" #include "config/full_system.hh" +#include "config/the_isa.hh" #include "cpu/base.hh" #include "cpu/simple_thread.hh" #include "cpu/pc_event.hh" diff --git a/src/cpu/simple/timing.cc b/src/cpu/simple/timing.cc index 672fd9414..6b22d2fcf 100644 --- a/src/cpu/simple/timing.cc +++ b/src/cpu/simple/timing.cc @@ -32,6 +32,7 @@ #include "arch/mmaped_ipr.hh" #include "arch/utility.hh" #include "base/bigint.hh" +#include "config/the_isa.hh" #include "cpu/exetrace.hh" #include "cpu/simple/timing.hh" #include "mem/packet.hh" @@ -272,6 +273,8 @@ TimingSimpleCPU::sendData(Fault fault, RequestPtr req, { _status = Running; if (fault != NoFault) { + if (req->isPrefetch()) + fault = NoFault; delete data; delete req; @@ -314,6 +317,10 @@ TimingSimpleCPU::sendSplitData(Fault fault1, Fault fault2, { _status = Running; if (fault1 != NoFault || fault2 != NoFault) { + if (req1->isPrefetch()) + fault1 = NoFault; + if (req2->isPrefetch()) + fault2 = NoFault; delete data; delete req1; delete req2; @@ -359,6 +366,8 @@ TimingSimpleCPU::sendSplitData(Fault fault1, Fault fault2, void TimingSimpleCPU::translationFault(Fault fault) { + // fault may be NoFault in cases where a fault is suppressed, + // for instance prefetches. numCycles += tickToCycles(curTick - previousTick); previousTick = curTick; diff --git a/src/cpu/simple_thread.cc b/src/cpu/simple_thread.cc index 22bc283a3..ad69719ee 100644 --- a/src/cpu/simple_thread.cc +++ b/src/cpu/simple_thread.cc @@ -34,6 +34,7 @@ #include <string> #include "arch/isa_traits.hh" +#include "config/the_isa.hh" #include "cpu/base.hh" #include "cpu/simple_thread.hh" #include "cpu/thread_context.hh" @@ -198,6 +199,11 @@ SimpleThread::serialize(ostream &os) SERIALIZE_SCALAR(nextPC); SERIALIZE_SCALAR(nextNPC); // thread_num and cpu_id are deterministic from the config + + // + // Now must serialize all the ISA dependent state + // + isa.serialize(cpu, os); } @@ -213,6 +219,11 @@ SimpleThread::unserialize(Checkpoint *cp, const std::string §ion) UNSERIALIZE_SCALAR(nextPC); UNSERIALIZE_SCALAR(nextNPC); // thread_num and cpu_id are deterministic from the config + + // + // Now must unserialize all the ISA dependent state + // + isa.unserialize(cpu, cp, section); } #if FULL_SYSTEM diff --git a/src/cpu/simple_thread.hh b/src/cpu/simple_thread.hh index 8a44eba37..2d28607b4 100644 --- a/src/cpu/simple_thread.hh +++ b/src/cpu/simple_thread.hh @@ -39,6 +39,7 @@ #include "arch/types.hh" #include "base/types.hh" #include "config/full_system.hh" +#include "config/the_isa.hh" #include "cpu/thread_context.hh" #include "cpu/thread_state.hh" #include "mem/request.hh" diff --git a/src/cpu/static_inst.hh b/src/cpu/static_inst.hh index b1298e0e9..fdec09756 100644 --- a/src/cpu/static_inst.hh +++ b/src/cpu/static_inst.hh @@ -36,6 +36,7 @@ #include "arch/isa_traits.hh" #include "arch/utility.hh" +#include "config/the_isa.hh" #include "base/bitfield.hh" #include "base/hashmap.hh" #include "base/misc.hh" diff --git a/src/cpu/thread_context.cc b/src/cpu/thread_context.cc index ab105a435..f2083ef08 100644 --- a/src/cpu/thread_context.cc +++ b/src/cpu/thread_context.cc @@ -30,6 +30,7 @@ #include "base/misc.hh" #include "base/trace.hh" +#include "config/the_isa.hh" #include "cpu/thread_context.hh" void diff --git a/src/cpu/thread_context.hh b/src/cpu/thread_context.hh index 9e34204ef..78ecdacf2 100644 --- a/src/cpu/thread_context.hh +++ b/src/cpu/thread_context.hh @@ -35,6 +35,7 @@ #include "arch/types.hh" #include "base/types.hh" #include "config/full_system.hh" +#include "config/the_isa.hh" #include "mem/request.hh" #include "sim/byteswap.hh" #include "sim/faults.hh" diff --git a/src/cpu/thread_state.hh b/src/cpu/thread_state.hh index 5c7c0ea56..cf637aeda 100644 --- a/src/cpu/thread_state.hh +++ b/src/cpu/thread_state.hh @@ -32,6 +32,7 @@ #define __CPU_THREAD_STATE_HH__ #include "arch/types.hh" +#include "config/the_isa.hh" #include "cpu/profile.hh" #include "cpu/thread_context.hh" #include "cpu/base.hh" diff --git a/src/dev/Uart.py b/src/dev/Uart.py index 5135a064d..9254dc695 100644 --- a/src/dev/Uart.py +++ b/src/dev/Uart.py @@ -28,7 +28,6 @@ from m5.params import * from m5.proxy import * -from m5 import build_env from Device import BasicPioDevice class Uart(BasicPioDevice): diff --git a/src/dev/alpha/tsunami.cc b/src/dev/alpha/tsunami.cc index b6478fe22..b36b5977d 100644 --- a/src/dev/alpha/tsunami.cc +++ b/src/dev/alpha/tsunami.cc @@ -36,6 +36,7 @@ #include <string> #include <vector> +#include "config/the_isa.hh" #include "cpu/intr_control.hh" #include "dev/alpha/tsunami_cchip.hh" #include "dev/alpha/tsunami_pchip.hh" diff --git a/src/dev/alpha/tsunami_cchip.cc b/src/dev/alpha/tsunami_cchip.cc index 52a2aea14..fd76fd93e 100644 --- a/src/dev/alpha/tsunami_cchip.cc +++ b/src/dev/alpha/tsunami_cchip.cc @@ -39,6 +39,7 @@ #include "arch/alpha/ev5.hh" #include "base/trace.hh" +#include "config/the_isa.hh" #include "cpu/intr_control.hh" #include "cpu/thread_context.hh" #include "dev/alpha/tsunami.hh" diff --git a/src/dev/alpha/tsunami_io.cc b/src/dev/alpha/tsunami_io.cc index 9c88904e3..8b06f5170 100644 --- a/src/dev/alpha/tsunami_io.cc +++ b/src/dev/alpha/tsunami_io.cc @@ -42,6 +42,7 @@ #include "base/time.hh" #include "base/trace.hh" +#include "config/the_isa.hh" #include "dev/rtcreg.h" #include "dev/alpha/tsunami_cchip.hh" #include "dev/alpha/tsunami.hh" diff --git a/src/dev/alpha/tsunami_pchip.cc b/src/dev/alpha/tsunami_pchip.cc index 4df7d1150..df980cf79 100644 --- a/src/dev/alpha/tsunami_pchip.cc +++ b/src/dev/alpha/tsunami_pchip.cc @@ -38,6 +38,7 @@ #include <vector> #include "base/trace.hh" +#include "config/the_isa.hh" #include "dev/alpha/tsunami_pchip.hh" #include "dev/alpha/tsunamireg.h" #include "dev/alpha/tsunami.hh" diff --git a/src/dev/arm/SConscript b/src/dev/arm/SConscript new file mode 100644 index 000000000..dd1d73e1a --- /dev/null +++ b/src/dev/arm/SConscript @@ -0,0 +1,36 @@ +# -*- mode:python -*- + +# Copyright (c) 2009 ARM Limited +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer; +# redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution; +# neither the name of the copyright holders nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# Authors: Ali Saidi + +Import('*') + +if env['FULL_SYSTEM'] and env['TARGET_ISA'] == 'arm': + SimObject('Versatile.py') + + Source('versatile.cc') diff --git a/src/dev/arm/Versatile.py b/src/dev/arm/Versatile.py new file mode 100644 index 000000000..7f36bbcf3 --- /dev/null +++ b/src/dev/arm/Versatile.py @@ -0,0 +1,51 @@ +# Copyright (c) 2006-2007 The Regents of The University of Michigan +# Copyright (c) 2009 ARM Limited +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer; +# redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution; +# neither the name of the copyright holders nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# Authors: Gabe Black + +from m5.params import * +from m5.proxy import * +from Device import BasicPioDevice, PioDevice, IsaFake, BadAddr +from Platform import Platform +from Terminal import Terminal +from Uart import Uart8250 + + +class Versatile(Platform): + type = 'Versatile' + system = Param.System(Parent.any, "system") + + # Attach I/O devices that are on chip + def attachOnChipIO(self, bus): + pass + + + # Attach I/O devices to specified bus object. Can't do this + # earlier, since the bus object itself is typically defined at the + # System level. + def attachIO(self, bus): + pass diff --git a/src/dev/arm/versatile.cc b/src/dev/arm/versatile.cc new file mode 100644 index 000000000..7d571db99 --- /dev/null +++ b/src/dev/arm/versatile.cc @@ -0,0 +1,122 @@ +/* + * Copyright (c) 2004-2005 The Regents of The University of Michigan + * Copyright (c) 2009 ARM Limited + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Ali Saidi + */ + +/** @file + * Implementation of Versatile platform. + */ + +#include <deque> +#include <string> +#include <vector> + +#include "config/the_isa.hh" +#include "cpu/intr_control.hh" +#include "dev/arm/versatile.hh" +#include "dev/terminal.hh" +#include "sim/system.hh" + +using namespace std; +using namespace TheISA; + +Versatile::Versatile(const Params *p) + : Platform(p), system(p->system) +{ + // set the back pointer from the system to myself + system->platform = this; +} + +Tick +Versatile::intrFrequency() +{ + panic("Need implementation\n"); + M5_DUMMY_RETURN +} + +void +Versatile::postConsoleInt() +{ + warn_once("Don't know what interrupt to post for console.\n"); + //panic("Need implementation\n"); +} + +void +Versatile::clearConsoleInt() +{ + warn_once("Don't know what interrupt to clear for console.\n"); + //panic("Need implementation\n"); +} + +void +Versatile::postPciInt(int line) +{ + panic("Need implementation\n"); +} + +void +Versatile::clearPciInt(int line) +{ + panic("Need implementation\n"); +} + +Addr +Versatile::pciToDma(Addr pciAddr) const +{ + panic("Need implementation\n"); + M5_DUMMY_RETURN +} + + +Addr +Versatile::calcPciConfigAddr(int bus, int dev, int func) +{ + panic("Need implementation\n"); + M5_DUMMY_RETURN +} + +Addr +Versatile::calcPciIOAddr(Addr addr) +{ + panic("Need implementation\n"); + M5_DUMMY_RETURN +} + +Addr +Versatile::calcPciMemAddr(Addr addr) +{ + panic("Need implementation\n"); + M5_DUMMY_RETURN +} + +Versatile * +VersatileParams::create() +{ + return new Versatile(this); +} diff --git a/src/dev/arm/versatile.hh b/src/dev/arm/versatile.hh new file mode 100644 index 000000000..edec3631c --- /dev/null +++ b/src/dev/arm/versatile.hh @@ -0,0 +1,108 @@ +/* + * Copyright (c) 2004-2005 The Regents of The University of Michigan + * Copyright (c) 2009 ARM Limited + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Ali Saidi + */ + +/** + * @file + * Declaration of top level class for the Versatile platform chips. This class just + * retains pointers to all its children so the children can communicate. + */ + +#ifndef __DEV_ARM_VERSATILE_HH__ +#define __DEV_ARM_VERSATILE_HH__ + +#include "dev/platform.hh" +#include "params/Versatile.hh" + +class IdeController; +class System; + +class Versatile : public Platform +{ + public: + /** Pointer to the system */ + System *system; + + public: + typedef VersatileParams Params; + /** + * Constructor for the Tsunami Class. + * @param name name of the object + * @param s system the object belongs to + * @param intctrl pointer to the interrupt controller + */ + Versatile(const Params *p); + + /** + * Return the interrupting frequency to AlphaAccess + * @return frequency of RTC interrupts + */ + virtual Tick intrFrequency(); + + /** + * Cause the cpu to post a serial interrupt to the CPU. + */ + virtual void postConsoleInt(); + + /** + * Clear a posted CPU interrupt + */ + virtual void clearConsoleInt(); + + /** + * Cause the chipset to post a cpi interrupt to the CPU. + */ + virtual void postPciInt(int line); + + /** + * Clear a posted PCI->CPU interrupt + */ + virtual void clearPciInt(int line); + + + virtual Addr pciToDma(Addr pciAddr) const; + + /** + * Calculate the configuration address given a bus/dev/func. + */ + virtual Addr calcPciConfigAddr(int bus, int dev, int func); + + /** + * Calculate the address for an IO location on the PCI bus. + */ + virtual Addr calcPciIOAddr(Addr addr); + + /** + * Calculate the address for a memory location on the PCI bus. + */ + virtual Addr calcPciMemAddr(Addr addr); +}; + +#endif // __DEV_ARM_VERSATILE_HH__ diff --git a/src/dev/baddev.cc b/src/dev/baddev.cc index 6cdee0310..356574c71 100644 --- a/src/dev/baddev.cc +++ b/src/dev/baddev.cc @@ -37,6 +37,7 @@ #include <vector> #include "base/trace.hh" +#include "config/the_isa.hh" #include "dev/baddev.hh" #include "dev/platform.hh" #include "mem/port.hh" diff --git a/src/dev/ide_ctrl.cc b/src/dev/ide_ctrl.cc index a8cceda1f..87dc0b2aa 100644 --- a/src/dev/ide_ctrl.cc +++ b/src/dev/ide_ctrl.cc @@ -75,8 +75,6 @@ IdeController::Channel::Channel( IdeController::Channel::~Channel() { - delete master; - delete slave; } IdeController::IdeController(Params *p) diff --git a/src/dev/ide_disk.cc b/src/dev/ide_disk.cc index 83faf508e..fe93924f9 100644 --- a/src/dev/ide_disk.cc +++ b/src/dev/ide_disk.cc @@ -39,6 +39,7 @@ #include <string> #include "arch/isa_traits.hh" +#include "config/the_isa.hh" #include "base/chunk_generator.hh" #include "base/cprintf.hh" // csprintf #include "base/trace.hh" diff --git a/src/dev/mc146818.cc b/src/dev/mc146818.cc index b25b015d2..2e6ed2a4b 100644 --- a/src/dev/mc146818.cc +++ b/src/dev/mc146818.cc @@ -105,6 +105,8 @@ MC146818::MC146818(EventManager *em, const string &n, const struct tm time, MC146818::~MC146818() { + deschedule(tickEvent); + deschedule(event); } void @@ -207,6 +209,15 @@ MC146818::serialize(const string &base, ostream &os) arrayParamOut(os, base + ".clock_data", clock_data, sizeof(clock_data)); paramOut(os, base + ".stat_regA", stat_regA); paramOut(os, base + ".stat_regB", stat_regB); + + // + // save the timer tick and rtc clock tick values to correctly reschedule + // them during unserialize + // + Tick rtcTimerInterruptTickOffset = event.when() - curTick; + SERIALIZE_SCALAR(rtcTimerInterruptTickOffset); + Tick rtcClockTickOffset = event.when() - curTick; + SERIALIZE_SCALAR(rtcClockTickOffset); } void @@ -218,10 +229,15 @@ MC146818::unserialize(const string &base, Checkpoint *cp, paramIn(cp, section, base + ".stat_regA", stat_regA); paramIn(cp, section, base + ".stat_regB", stat_regB); - // We're not unserializing the event here, but we need to - // rescehedule the event since curTick was moved forward by the - // checkpoint - reschedule(event, curTick + event.interval); + // + // properly schedule the timer and rtc clock events + // + Tick rtcTimerInterruptTickOffset; + UNSERIALIZE_SCALAR(rtcTimerInterruptTickOffset); + reschedule(event, curTick + rtcTimerInterruptTickOffset); + Tick rtcClockTickOffset; + UNSERIALIZE_SCALAR(rtcClockTickOffset); + reschedule(tickEvent, curTick + rtcClockTickOffset); } MC146818::RTCEvent::RTCEvent(MC146818 * _parent, Tick i) diff --git a/src/dev/mips/malta.cc b/src/dev/mips/malta.cc index 1401fe9ee..73dc9f116 100755 --- a/src/dev/mips/malta.cc +++ b/src/dev/mips/malta.cc @@ -37,6 +37,7 @@ #include <string> #include <vector> +#include "config/the_isa.hh" #include "cpu/intr_control.hh" #include "dev/mips/malta_cchip.hh" #include "dev/mips/malta_pchip.hh" @@ -46,7 +47,6 @@ #include "params/Malta.hh" #include "sim/system.hh" - using namespace std; using namespace TheISA; diff --git a/src/dev/mips/malta_cchip.cc b/src/dev/mips/malta_cchip.cc index 265977665..b2d5069c5 100755 --- a/src/dev/mips/malta_cchip.cc +++ b/src/dev/mips/malta_cchip.cc @@ -39,6 +39,7 @@ #include "arch/mips/mips_core_specific.hh" #include "base/trace.hh" +#include "config/the_isa.hh" #include "cpu/intr_control.hh" #include "cpu/thread_context.hh" #include "dev/mips/malta.hh" @@ -56,7 +57,7 @@ using namespace TheISA; MaltaCChip::MaltaCChip(Params *p) : BasicPioDevice(p), malta(p->malta) { - warn("MaltaCCHIP::MaltaCChip() not implemented."); + warn("MaltaCCHIP::MaltaCChip() not implemented."); pioSize = 0xfffffff; //Put back pointer in malta diff --git a/src/dev/mips/malta_io.cc b/src/dev/mips/malta_io.cc index 7f04789db..5a738a9b4 100755 --- a/src/dev/mips/malta_io.cc +++ b/src/dev/mips/malta_io.cc @@ -42,6 +42,7 @@ #include "base/time.hh" #include "base/trace.hh" +#include "config/the_isa.hh" #include "dev/rtcreg.h" #include "dev/mips/malta_cchip.hh" #include "dev/mips/malta.hh" diff --git a/src/dev/mips/malta_pchip.cc b/src/dev/mips/malta_pchip.cc index b357e3b61..035433021 100755 --- a/src/dev/mips/malta_pchip.cc +++ b/src/dev/mips/malta_pchip.cc @@ -38,6 +38,7 @@ #include <vector> #include "base/trace.hh" +#include "config/the_isa.hh" #include "dev/mips/malta_pchip.hh" #include "dev/mips/maltareg.h" #include "dev/mips/malta.hh" diff --git a/src/dev/ns_gige.cc b/src/dev/ns_gige.cc index 912ca7f0f..86f081ec5 100644 --- a/src/dev/ns_gige.cc +++ b/src/dev/ns_gige.cc @@ -39,6 +39,7 @@ #include "base/debug.hh" #include "base/inet.hh" #include "base/types.hh" +#include "config/the_isa.hh" #include "cpu/thread_context.hh" #include "dev/etherlink.hh" #include "dev/ns_gige.hh" diff --git a/src/dev/platform.cc b/src/dev/platform.cc index 2b51a6245..a91a5abf9 100644 --- a/src/dev/platform.cc +++ b/src/dev/platform.cc @@ -30,6 +30,7 @@ */ #include "base/misc.hh" +#include "config/the_isa.hh" #include "dev/platform.hh" #include "sim/sim_exit.hh" diff --git a/src/dev/sinic.cc b/src/dev/sinic.cc index 133f70b0b..86090e048 100644 --- a/src/dev/sinic.cc +++ b/src/dev/sinic.cc @@ -36,6 +36,7 @@ #include "base/debug.hh" #include "base/inet.hh" #include "base/types.hh" +#include "config/the_isa.hh" #include "cpu/intr_control.hh" #include "cpu/thread_context.hh" #include "dev/etherlink.hh" diff --git a/src/dev/sparc/dtod.cc b/src/dev/sparc/dtod.cc index 81132ac65..c7243cfb8 100644 --- a/src/dev/sparc/dtod.cc +++ b/src/dev/sparc/dtod.cc @@ -39,6 +39,7 @@ #include "base/time.hh" #include "base/trace.hh" +#include "config/the_isa.hh" #include "dev/sparc/dtod.hh" #include "dev/platform.hh" #include "mem/packet_access.hh" diff --git a/src/dev/sparc/iob.cc b/src/dev/sparc/iob.cc index 4543dd07b..40f856d8a 100644 --- a/src/dev/sparc/iob.cc +++ b/src/dev/sparc/iob.cc @@ -90,20 +90,18 @@ void Iob::readIob(PacketPtr pkt) { Addr accessAddr = pkt->getAddr() - iobManAddr; - int index; - uint64_t data; if (accessAddr >= IntManAddr && accessAddr < IntManAddr + IntManSize) { - index = (accessAddr - IntManAddr) >> 3; - data = intMan[index].cpu << 8 | intMan[index].vector << 0; + int index = (accessAddr - IntManAddr) >> 3; + uint64_t data = intMan[index].cpu << 8 | intMan[index].vector << 0; pkt->set(data); return; } if (accessAddr >= IntCtlAddr && accessAddr < IntCtlAddr + IntCtlSize) { - index = (accessAddr - IntManAddr) >> 3; - data = intCtl[index].mask ? 1 << 2 : 0 | - intCtl[index].pend ? 1 << 0 : 0; + int index = (accessAddr - IntCtlAddr) >> 3; + uint64_t data = intCtl[index].mask ? 1 << 2 : 0 | + intCtl[index].pend ? 1 << 0 : 0; pkt->set(data); return; } @@ -199,7 +197,7 @@ Iob::writeIob(PacketPtr pkt) } if (accessAddr >= IntCtlAddr && accessAddr < IntCtlAddr + IntCtlSize) { - index = (accessAddr - IntManAddr) >> 3; + index = (accessAddr - IntCtlAddr) >> 3; data = pkt->get<uint64_t>(); intCtl[index].mask = bits(data,2,2); if (bits(data,1,1)) diff --git a/src/dev/sparc/t1000.cc b/src/dev/sparc/t1000.cc index 88fb358ef..c00d942c9 100644 --- a/src/dev/sparc/t1000.cc +++ b/src/dev/sparc/t1000.cc @@ -36,6 +36,7 @@ #include <string> #include <vector> +#include "config/the_isa.hh" #include "cpu/intr_control.hh" #include "dev/sparc/t1000.hh" #include "dev/terminal.hh" diff --git a/src/dev/uart8250.cc b/src/dev/uart8250.cc index 93f71f49b..e3eacaaa2 100644 --- a/src/dev/uart8250.cc +++ b/src/dev/uart8250.cc @@ -38,6 +38,7 @@ #include "base/inifile.hh" #include "base/str.hh" // for to_number #include "base/trace.hh" +#include "config/the_isa.hh" #include "dev/platform.hh" #include "dev/terminal.hh" #include "dev/uart8250.hh" diff --git a/src/dev/x86/i82094aa.cc b/src/dev/x86/i82094aa.cc index ed936d0cb..591fee6a4 100644 --- a/src/dev/x86/i82094aa.cc +++ b/src/dev/x86/i82094aa.cc @@ -151,7 +151,7 @@ X86ISA::I82094AA::signalInterrupt(int line) DPRINTF(I82094AA, "Entry was masked.\n"); return; } else { - TriggerIntMessage message; + TriggerIntMessage message = 0; message.destination = entry.dest; if (entry.deliveryMode == DeliveryMode::ExtInt) { assert(extIntPic); diff --git a/src/dev/x86/pc.cc b/src/dev/x86/pc.cc index 7dc1d8711..e3449abf6 100644 --- a/src/dev/x86/pc.cc +++ b/src/dev/x86/pc.cc @@ -38,6 +38,7 @@ #include "arch/x86/intmessage.hh" #include "arch/x86/x86_traits.hh" +#include "config/the_isa.hh" #include "cpu/intr_control.hh" #include "dev/terminal.hh" #include "dev/x86/i82094aa.hh" diff --git a/src/kern/linux/linux.cc b/src/kern/linux/linux.cc index abe7c0b75..72f1832b8 100644 --- a/src/kern/linux/linux.cc +++ b/src/kern/linux/linux.cc @@ -28,6 +28,7 @@ * Authors: Ali Saidi */ +#include <cstdio> #include <string> #include "cpu/thread_context.hh" diff --git a/src/kern/linux/linux.hh b/src/kern/linux/linux.hh index 7c16228ea..7fe107139 100644 --- a/src/kern/linux/linux.hh +++ b/src/kern/linux/linux.hh @@ -62,6 +62,7 @@ class Linux : public OperatingSystem typedef uint64_t size_t; typedef uint64_t off_t; typedef int64_t time_t; + typedef int64_t clock_t; typedef uint32_t uid_t; typedef uint32_t gid_t; //@} @@ -136,6 +137,17 @@ class Linux : public OperatingSystem int64_t tv_usec; //!< microseconds }; + /// Clock ticks per second, for times(). + static const int M5_SC_CLK_TCK = 100; + + /// For times(). + struct tms { + int64_t tms_utime; //!< user time + int64_t tms_stime; //!< system time + int64_t tms_cutime; //!< user time of children + int64_t tms_cstime; //!< system time of children + }; + // For writev/readv struct tgt_iovec { uint64_t iov_base; // void * diff --git a/src/kern/linux/printk.hh b/src/kern/linux/printk.hh index da9564b7e..5c6ee073d 100644 --- a/src/kern/linux/printk.hh +++ b/src/kern/linux/printk.hh @@ -32,8 +32,6 @@ #ifndef __PRINTK_HH__ #define __PRINTK_HH__ -#include "arch/isa_specific.hh" - #include <sstream> class Arguments; diff --git a/src/kern/operatingsystem.hh b/src/kern/operatingsystem.hh index 47e64ffd9..6574e3c6b 100644 --- a/src/kern/operatingsystem.hh +++ b/src/kern/operatingsystem.hh @@ -122,6 +122,10 @@ class OperatingSystem { static int openSpecialFile(std::string path, LiveProcess *process, ThreadContext *tc); + static const bool mmapGrowsUp = true; + + static bool mmapGrowsDown() { return false; } + }; // class OperatingSystem diff --git a/src/kern/system_events.cc b/src/kern/system_events.cc index 6fd9e1563..bd01ed9ed 100644 --- a/src/kern/system_events.cc +++ b/src/kern/system_events.cc @@ -29,9 +29,9 @@ * Nathan Binkert */ -//For ISA_HAS_DELAY_SLOT #include "arch/isa_traits.hh" #include "base/trace.hh" +#include "config/the_isa.hh" #include "cpu/thread_context.hh" #include "kern/system_events.hh" diff --git a/src/kern/tru64/dump_mbuf.cc b/src/kern/tru64/dump_mbuf.cc index 517aad6fa..207d30792 100644 --- a/src/kern/tru64/dump_mbuf.cc +++ b/src/kern/tru64/dump_mbuf.cc @@ -37,6 +37,7 @@ #include "base/loader/symtab.hh" #include "base/trace.hh" #include "base/types.hh" +#include "config/the_isa.hh" #include "cpu/thread_context.hh" #include "kern/tru64/mbuf.hh" #include "sim/arguments.hh" diff --git a/src/kern/tru64/tru64.hh b/src/kern/tru64/tru64.hh index bf46e0de4..033f30946 100644 --- a/src/kern/tru64/tru64.hh +++ b/src/kern/tru64/tru64.hh @@ -31,6 +31,7 @@ #ifndef __TRU64_HH__ #define __TRU64_HH__ + #include "config/full_system.hh" #include "kern/operatingsystem.hh" @@ -55,6 +56,7 @@ class Tru64 {}; #include <string.h> // for memset() #include <unistd.h> +#include "config/the_isa.hh" #include "arch/alpha/registers.hh" #include "cpu/base.hh" #include "sim/core.hh" @@ -438,10 +440,11 @@ class Tru64 : public OperatingSystem #ifdef __CYGWIN__ panic("getdirent not implemented on cygwin!"); #else - int fd = process->sim_fd(process->getSyscallArg(tc, 0)); - Addr tgt_buf = process->getSyscallArg(tc, 1); - int tgt_nbytes = process->getSyscallArg(tc, 2); - Addr tgt_basep = process->getSyscallArg(tc, 3); + int index = 0; + int fd = process->sim_fd(process->getSyscallArg(tc, index)); + Addr tgt_buf = process->getSyscallArg(tc, index); + int tgt_nbytes = process->getSyscallArg(tc, index); + Addr tgt_basep = process->getSyscallArg(tc, index); char * const host_buf = new char[tgt_nbytes]; @@ -496,7 +499,8 @@ class Tru64 : public OperatingSystem { using namespace TheISA; - TypedBufferArg<Tru64::sigcontext> sc(process->getSyscallArg(tc, 0)); + int index = 0; + TypedBufferArg<Tru64::sigcontext> sc(process->getSyscallArg(tc, index)); sc.copyIn(tc->getMemPort()); @@ -528,7 +532,8 @@ class Tru64 : public OperatingSystem { using namespace TheISA; - TypedBufferArg<Tru64::vm_stack> argp(process->getSyscallArg(tc, 0)); + int index = 0; + TypedBufferArg<Tru64::vm_stack> argp(process->getSyscallArg(tc, index)); argp.copyIn(tc->getMemPort()); @@ -576,9 +581,10 @@ class Tru64 : public OperatingSystem using namespace std; using namespace TheISA; + int index = 0; TypedBufferArg<Tru64::nxm_task_attr> - attrp(process->getSyscallArg(tc, 0)); - TypedBufferArg<Addr> configptr_ptr(process->getSyscallArg(tc, 1)); + attrp(process->getSyscallArg(tc, index)); + TypedBufferArg<Addr> configptr_ptr(process->getSyscallArg(tc, index)); attrp.copyIn(tc->getMemPort()); @@ -710,10 +716,11 @@ class Tru64 : public OperatingSystem using namespace std; using namespace TheISA; + int index = 0; TypedBufferArg<Tru64::nxm_thread_attr> - attrp(process->getSyscallArg(tc, 0)); - TypedBufferArg<uint64_t> kidp(process->getSyscallArg(tc, 1)); - int thread_index = process->getSyscallArg(tc, 2); + attrp(process->getSyscallArg(tc, index)); + TypedBufferArg<uint64_t> kidp(process->getSyscallArg(tc, index)); + int thread_index = process->getSyscallArg(tc, index); // get attribute args attrp.copyIn(tc->getMemPort()); @@ -832,11 +839,12 @@ class Tru64 : public OperatingSystem { using namespace std; - uint64_t tid = process->getSyscallArg(tc, 0); - uint64_t secs = process->getSyscallArg(tc, 1); - uint64_t flags = process->getSyscallArg(tc, 2); - uint64_t action = process->getSyscallArg(tc, 3); - uint64_t usecs = process->getSyscallArg(tc, 4); + int index = 0; + uint64_t tid = process->getSyscallArg(tc, index); + uint64_t secs = process->getSyscallArg(tc, index); + uint64_t flags = process->getSyscallArg(tc, index); + uint64_t action = process->getSyscallArg(tc, index); + uint64_t usecs = process->getSyscallArg(tc, index); cout << tc->getCpuPtr()->name() << ": nxm_thread_block " << tid << " " << secs << " " << flags << " " << action << " " << usecs << endl; @@ -851,11 +859,12 @@ class Tru64 : public OperatingSystem { using namespace std; - Addr uaddr = process->getSyscallArg(tc, 0); - uint64_t val = process->getSyscallArg(tc, 1); - uint64_t secs = process->getSyscallArg(tc, 2); - uint64_t usecs = process->getSyscallArg(tc, 3); - uint64_t flags = process->getSyscallArg(tc, 4); + int index = 0; + Addr uaddr = process->getSyscallArg(tc, index); + uint64_t val = process->getSyscallArg(tc, index); + uint64_t secs = process->getSyscallArg(tc, index); + uint64_t usecs = process->getSyscallArg(tc, index); + uint64_t flags = process->getSyscallArg(tc, index); BaseCPU *cpu = tc->getCpuPtr(); @@ -874,7 +883,8 @@ class Tru64 : public OperatingSystem { using namespace std; - Addr uaddr = process->getSyscallArg(tc, 0); + int index = 0; + Addr uaddr = process->getSyscallArg(tc, index); cout << tc->getCpuPtr()->name() << ": nxm_unblock " << hex << uaddr << dec << endl; @@ -975,7 +985,8 @@ class Tru64 : public OperatingSystem m5_mutex_lockFunc(SyscallDesc *desc, int callnum, LiveProcess *process, ThreadContext *tc) { - Addr uaddr = process->getSyscallArg(tc, 0); + int index = 0; + Addr uaddr = process->getSyscallArg(tc, index); m5_lock_mutex(uaddr, process, tc); @@ -992,7 +1003,8 @@ class Tru64 : public OperatingSystem { using namespace TheISA; - Addr uaddr = process->getSyscallArg(tc, 0); + int index = 0; + Addr uaddr = process->getSyscallArg(tc, index); TypedBufferArg<uint64_t> lockp(uaddr); lockp.copyIn(tc->getMemPort()); @@ -1012,7 +1024,8 @@ class Tru64 : public OperatingSystem m5_mutex_unlockFunc(SyscallDesc *desc, int callnum, LiveProcess *process, ThreadContext *tc) { - Addr uaddr = process->getSyscallArg(tc, 0); + int index = 0; + Addr uaddr = process->getSyscallArg(tc, index); m5_unlock_mutex(uaddr, process, tc); @@ -1024,7 +1037,8 @@ class Tru64 : public OperatingSystem m5_cond_signalFunc(SyscallDesc *desc, int callnum, LiveProcess *process, ThreadContext *tc) { - Addr cond_addr = process->getSyscallArg(tc, 0); + int index = 0; + Addr cond_addr = process->getSyscallArg(tc, index); // Wake up one process waiting on the condition variable. activate_waiting_context(cond_addr, process); @@ -1037,7 +1051,8 @@ class Tru64 : public OperatingSystem m5_cond_broadcastFunc(SyscallDesc *desc, int callnum, LiveProcess *process, ThreadContext *tc) { - Addr cond_addr = process->getSyscallArg(tc, 0); + int index = 0; + Addr cond_addr = process->getSyscallArg(tc, index); activate_waiting_context(cond_addr, process, true); @@ -1051,8 +1066,9 @@ class Tru64 : public OperatingSystem { using namespace TheISA; - Addr cond_addr = process->getSyscallArg(tc, 0); - Addr lock_addr = process->getSyscallArg(tc, 1); + int index = 0; + Addr cond_addr = process->getSyscallArg(tc, index); + Addr lock_addr = process->getSyscallArg(tc, index); TypedBufferArg<uint64_t> condp(cond_addr); TypedBufferArg<uint64_t> lockp(lock_addr); @@ -1084,10 +1100,11 @@ class Tru64 : public OperatingSystem indirectSyscallFunc(SyscallDesc *desc, int callnum, LiveProcess *process, ThreadContext *tc) { - int new_callnum = process->getSyscallArg(tc, 0); + int index = 0; + int new_callnum = process->getSyscallArg(tc, index); for (int i = 0; i < 5; ++i) - process->setSyscallArg(tc, i, process->getSyscallArg(tc, i+1)); + process->setSyscallArg(tc, i, process->getSyscallArg(tc, index)); SyscallDesc *new_desc = process->getDesc(new_callnum); diff --git a/src/kern/tru64/tru64_events.cc b/src/kern/tru64/tru64_events.cc index 4867df559..460f75dea 100644 --- a/src/kern/tru64/tru64_events.cc +++ b/src/kern/tru64/tru64_events.cc @@ -31,6 +31,7 @@ #include "arch/alpha/ev5.hh" #include "arch/isa_traits.hh" +#include "config/the_isa.hh" #include "cpu/thread_context.hh" #include "cpu/base.hh" #include "kern/system_events.hh" diff --git a/src/mem/Bus.py b/src/mem/Bus.py index 0f113cc09..b3f6b2946 100644 --- a/src/mem/Bus.py +++ b/src/mem/Bus.py @@ -26,12 +26,12 @@ # # Authors: Nathan Binkert -from m5 import build_env +from m5.defines import buildEnv from m5.params import * from m5.proxy import * from MemObject import MemObject -if build_env['FULL_SYSTEM']: +if buildEnv['FULL_SYSTEM']: from Device import BadAddr class Bus(MemObject): diff --git a/src/mem/RubyMemory.py b/src/mem/RubyMemory.py index fbbbeebe4..2ad794a3f 100644 --- a/src/mem/RubyMemory.py +++ b/src/mem/RubyMemory.py @@ -42,4 +42,7 @@ class RubyMemory(PhysicalMemory): debug = Param.Bool(False, "Use ruby debug") debug_file = Param.String("ruby.debug", "path to the Ruby debug output file (stdout if blank)") - + num_dmas = Param.Int(0, "Number of DMA ports connected to the Ruby memory") + dma_port = VectorPort("Ruby_dma_ports") + pio_port = Port("Ruby_pio_port") + ports_per_core = Param.Int(2, "Number of per core. Typical two: icache + dcache") diff --git a/src/mem/SConscript b/src/mem/SConscript index 21335a709..2188850e0 100644 --- a/src/mem/SConscript +++ b/src/mem/SConscript @@ -63,3 +63,4 @@ TraceFlag('BusBridge') TraceFlag('LLSC') TraceFlag('MMU') TraceFlag('MemoryAccess') +TraceFlag('Ruby') diff --git a/src/mem/bridge.cc b/src/mem/bridge.cc index cc9b83d3e..d0135fc9d 100644 --- a/src/mem/bridge.cc +++ b/src/mem/bridge.cc @@ -93,7 +93,9 @@ Bridge::init() fatal("Both ports of bus bridge are not connected to a bus.\n"); if (portA.peerBlockSize() != portB.peerBlockSize()) - fatal("Busses don't have the same block size... Not supported.\n"); + fatal("port A size %d, port B size %d \n " \ + "Busses don't have the same block size... Not supported.\n", + portA.peerBlockSize(), portB.peerBlockSize()); } bool diff --git a/src/mem/bus.cc b/src/mem/bus.cc index 001c37a24..cac08d1a8 100644 --- a/src/mem/bus.cc +++ b/src/mem/bus.cc @@ -244,6 +244,9 @@ Bus::recvTiming(PacketPtr pkt) // Packet not successfully sent. Leave or put it on the retry list. // illegal to block responses... can lead to deadlock assert(!pkt->isResponse()); + // It's also illegal to force a transaction to retry after + // someone else has committed to respond. + assert(!pkt->memInhibitAsserted()); DPRINTF(Bus, "recvTiming: src %d dst %d %s 0x%x TGT RETRY\n", src, pkt->getDest(), pkt->cmdString(), pkt->getAddr()); addToRetryList(src_port); diff --git a/src/mem/cache/BaseCache.py b/src/mem/cache/BaseCache.py index bdef07cb4..5ded05400 100644 --- a/src/mem/cache/BaseCache.py +++ b/src/mem/cache/BaseCache.py @@ -68,8 +68,6 @@ class BaseCache(MemObject): "Latency of the prefetcher") prefetch_policy = Param.Prefetch('none', "Type of prefetcher to use") - prefetch_cache_check_push = Param.Bool(True, - "Check if in cache on push or pop of prefetch queue") prefetch_use_cpu_id = Param.Bool(True, "Use the CPU ID to separate calculations of prefetches") prefetch_data_accesses_only = Param.Bool(False, diff --git a/src/mem/cache/base.hh b/src/mem/cache/base.hh index 24f993383..c245fecd2 100644 --- a/src/mem/cache/base.hh +++ b/src/mem/cache/base.hh @@ -379,7 +379,7 @@ class BaseCache : public MemObject } - Addr blockAlign(Addr addr) const { return (addr & ~(blkSize - 1)); } + Addr blockAlign(Addr addr) const { return (addr & ~(Addr(blkSize - 1))); } const Range<Addr> &getAddrRange() const { return addrRange; } diff --git a/src/mem/cache/builder.cc b/src/mem/cache/builder.cc index 599353b88..bd9eb9acc 100644 --- a/src/mem/cache/builder.cc +++ b/src/mem/cache/builder.cc @@ -33,9 +33,10 @@ * @file * Simobject instatiation of caches. */ +#include <list> #include <vector> -// Must be included first to determine which caches we want +#include "config/the_isa.hh" #include "enums/Prefetch.hh" #include "mem/config/cache.hh" #include "mem/cache/base.hh" diff --git a/src/mem/cache/cache_impl.hh b/src/mem/cache/cache_impl.hh index 80b7c545c..429928c79 100644 --- a/src/mem/cache/cache_impl.hh +++ b/src/mem/cache/cache_impl.hh @@ -449,7 +449,7 @@ Cache<TagStore>::timingAccess(PacketPtr pkt) } else { // miss - Addr blk_addr = pkt->getAddr() & ~(Addr(blkSize-1)); + Addr blk_addr = blockAlign(pkt->getAddr()); MSHR *mshr = mshrQueue.findMatch(blk_addr); if (mshr) { @@ -692,7 +692,7 @@ Cache<TagStore>::functionalAccess(PacketPtr pkt, CachePort *incomingPort, CachePort *otherSidePort) { - Addr blk_addr = pkt->getAddr() & ~(blkSize - 1); + Addr blk_addr = blockAlign(pkt->getAddr()); BlkType *blk = tags->findBlock(pkt->getAddr()); pkt->pushLabel(name()); @@ -1162,7 +1162,7 @@ Cache<TagStore>::snoopTiming(PacketPtr pkt) BlkType *blk = tags->findBlock(pkt->getAddr()); - Addr blk_addr = pkt->getAddr() & ~(Addr(blkSize-1)); + Addr blk_addr = blockAlign(pkt->getAddr()); MSHR *mshr = mshrQueue.findMatch(blk_addr); // Let the MSHR itself track the snoop and decide whether we want @@ -1301,11 +1301,14 @@ Cache<TagStore>::getNextMSHR() // If we have a miss queue slot, we can try a prefetch PacketPtr pkt = prefetcher->getPacket(); if (pkt) { - // Update statistic on number of prefetches issued - // (hwpf_mshr_misses) - mshr_misses[pkt->cmdToIndex()][0/*pkt->req->threadId()*/]++; - // Don't request bus, since we already have it - return allocateMissBuffer(pkt, curTick, false); + Addr pf_addr = blockAlign(pkt->getAddr()); + if (!tags->findBlock(pf_addr) && !mshrQueue.findMatch(pf_addr)) { + // Update statistic on number of prefetches issued + // (hwpf_mshr_misses) + mshr_misses[pkt->cmdToIndex()][0/*pkt->req->threadId()*/]++; + // Don't request bus, since we already have it + return allocateMissBuffer(pkt, curTick, false); + } } } diff --git a/src/mem/cache/prefetch/base.cc b/src/mem/cache/prefetch/base.cc index f20a306cb..ad7a0c882 100644 --- a/src/mem/cache/prefetch/base.cc +++ b/src/mem/cache/prefetch/base.cc @@ -33,17 +33,18 @@ * Hardware Prefetcher Definition. */ +#include <list> + #include "arch/isa_traits.hh" #include "base/trace.hh" +#include "config/the_isa.hh" #include "mem/cache/base.hh" #include "mem/cache/prefetch/base.hh" #include "mem/request.hh" -#include <list> BasePrefetcher::BasePrefetcher(const BaseCacheParams *p) : size(p->prefetcher_size), pageStop(!p->prefetch_past_page), serialSquash(p->prefetch_serial_squash), - cacheCheckPush(p->prefetch_cache_check_push), onlyData(p->prefetch_data_accesses_only) { } @@ -141,9 +142,6 @@ BasePrefetcher::getPacket() do { pkt = *pf.begin(); pf.pop_front(); - if (!cacheCheckPush) { - keep_trying = cache->inCache(pkt->getAddr()); - } if (keep_trying) { DPRINTF(HWPrefetch, "addr 0x%x in cache, skipping\n", @@ -224,18 +222,6 @@ BasePrefetcher::notify(PacketPtr &pkt, Tick time) "inserting into prefetch queue with delay %d time %d\n", addr, *delayIter, time); - // Check if it is already in the cache - if (cacheCheckPush && cache->inCache(addr)) { - DPRINTF(HWPrefetch, "Prefetch addr already in cache\n"); - continue; - } - - // Check if it is already in the miss_queue - if (cache->inMissQueue(addr)) { - DPRINTF(HWPrefetch, "Prefetch addr already in miss queue\n"); - continue; - } - // Check if it is already in the pf buffer if (inPrefetch(addr) != pf.end()) { pfBufferHit++; diff --git a/src/mem/cache/prefetch/base.hh b/src/mem/cache/prefetch/base.hh index b5f33a455..e3c0cbf16 100644 --- a/src/mem/cache/prefetch/base.hh +++ b/src/mem/cache/prefetch/base.hh @@ -68,10 +68,6 @@ class BasePrefetcher /** Do we remove prefetches with later times than a new miss.*/ bool serialSquash; - /** Do we check if it is in the cache when inserting into buffer, - or removing.*/ - bool cacheCheckPush; - /** Do we prefetch on only data reads, or on inst reads as well. */ bool onlyData; diff --git a/src/mem/packet.hh b/src/mem/packet.hh index 07c086cd5..c58862270 100644 --- a/src/mem/packet.hh +++ b/src/mem/packet.hh @@ -437,6 +437,7 @@ class Packet : public FastAlloc, public Printable bool hadBadAddress() const { return cmd == MemCmd::BadAddressError; } void copyError(Packet *pkt) { assert(pkt->isError()); cmd = pkt->cmd; } + bool isSrcValid() { return flags.isSet(VALID_SRC); } /// Accessor function to get the source index of the packet. NodeID getSrc() const { assert(flags.isSet(VALID_SRC)); return src; } /// Accessor function to set the source index of the packet. @@ -444,6 +445,7 @@ class Packet : public FastAlloc, public Printable /// Reset source field, e.g. to retransmit packet on different bus. void clearSrc() { flags.clear(VALID_SRC); } + bool isDestValid() { return flags.isSet(VALID_DST); } /// Accessor function for the destination index of the packet. NodeID getDest() const { assert(flags.isSet(VALID_DST)); return dest; } /// Accessor function to set the destination index of the packet. diff --git a/src/mem/packet_access.hh b/src/mem/packet_access.hh index f70d508b2..fca9606fc 100644 --- a/src/mem/packet_access.hh +++ b/src/mem/packet_access.hh @@ -31,6 +31,7 @@ #include "arch/isa_traits.hh" #include "base/bigint.hh" +#include "config/the_isa.hh" #include "mem/packet.hh" #include "sim/byteswap.hh" diff --git a/src/mem/page_table.cc b/src/mem/page_table.cc index bf35932a6..4bc3a4434 100644 --- a/src/mem/page_table.cc +++ b/src/mem/page_table.cc @@ -42,6 +42,7 @@ #include "base/bitfield.hh" #include "base/intmath.hh" #include "base/trace.hh" +#include "config/the_isa.hh" #include "mem/page_table.hh" #include "sim/process.hh" #include "sim/sim_object.hh" diff --git a/src/mem/page_table.hh b/src/mem/page_table.hh index 3ce720ad4..0d93d37c7 100644 --- a/src/mem/page_table.hh +++ b/src/mem/page_table.hh @@ -42,6 +42,7 @@ #include "arch/tlb.hh" #include "base/hashmap.hh" #include "base/types.hh" +#include "config/the_isa.hh" #include "mem/request.hh" #include "sim/faults.hh" #include "sim/serialize.hh" diff --git a/src/mem/physical.cc b/src/mem/physical.cc index d87ad3b22..121a6e447 100644 --- a/src/mem/physical.cc +++ b/src/mem/physical.cc @@ -36,6 +36,7 @@ #include <unistd.h> #include <zlib.h> +#include <cstdio> #include <iostream> #include <string> @@ -44,6 +45,7 @@ #include "base/random.hh" #include "base/types.hh" #include "config/full_system.hh" +#include "config/the_isa.hh" #include "mem/packet_access.hh" #include "mem/physical.hh" #include "sim/eventq.hh" diff --git a/src/mem/port_impl.hh b/src/mem/port_impl.hh index 989cfd338..bc9592164 100644 --- a/src/mem/port_impl.hh +++ b/src/mem/port_impl.hh @@ -28,9 +28,8 @@ * Authors: Ali Saidi */ -//To get endianness #include "arch/isa_traits.hh" - +#include "config/the_isa.hh" #include "mem/port.hh" #include "sim/byteswap.hh" diff --git a/src/mem/protocol/MI_example-dir.sm b/src/mem/protocol/MI_example-dir.sm index 17f39af5b..1f64d25df 100644 --- a/src/mem/protocol/MI_example-dir.sm +++ b/src/mem/protocol/MI_example-dir.sm @@ -1,8 +1,6 @@ machine(Directory, "Directory protocol") -: int directory_latency, - int dma_select_low_bit, - int dma_select_num_bits +: int directory_latency { MessageBuffer forwardFromDir, network="To", virtual_network="2", ordered="false"; @@ -74,6 +72,7 @@ machine(Directory, "Directory protocol") State TBEState, desc="Transient State"; DataBlock DataBlk, desc="Data to be written (DMA write only)"; int Len, desc="..."; + MachineID DmaRequestor, desc="DMA requestor"; } external_type(TBETable) { @@ -243,8 +242,7 @@ machine(Directory, "Directory protocol") out_msg.LineAddress := address; out_msg.Type := DMAResponseType:DATA; out_msg.DataBlk := in_msg.DataBlk; // we send the entire data block and rely on the dma controller to split it up if need be - out_msg.Destination.add(mapAddressToRange(address, MachineType:DMA, - dma_select_low_bit, dma_select_num_bits)); + out_msg.Destination.add(TBEs[address].DmaRequestor); out_msg.MessageSize := MessageSizeType:Response_Data; } } @@ -259,8 +257,7 @@ machine(Directory, "Directory protocol") out_msg.LineAddress := address; out_msg.Type := DMAResponseType:DATA; out_msg.DataBlk := in_msg.DataBlk; // we send the entire data block and rely on the dma controller to split it up if need be - out_msg.Destination.add(mapAddressToRange(address, MachineType:DMA, - dma_select_low_bit, dma_select_num_bits)); + out_msg.Destination.add(TBEs[address].DmaRequestor); out_msg.MessageSize := MessageSizeType:Response_Data; } } @@ -271,8 +268,7 @@ machine(Directory, "Directory protocol") out_msg.PhysicalAddress := address; out_msg.LineAddress := address; out_msg.Type := DMAResponseType:ACK; - out_msg.Destination.add(mapAddressToRange(address, MachineType:DMA, - dma_select_low_bit, dma_select_num_bits)); + out_msg.Destination.add(TBEs[address].DmaRequestor); out_msg.MessageSize := MessageSizeType:Writeback_Control; } } @@ -343,6 +339,14 @@ machine(Directory, "Directory protocol") TBEs[address].DataBlk := in_msg.DataBlk; TBEs[address].PhysicalAddress := in_msg.PhysicalAddress; TBEs[address].Len := in_msg.Len; + TBEs[address].DmaRequestor := in_msg.Requestor; + } + } + + action(r_allocateTbeForDmaRead, "\r", desc="Allocate TBE for DMA Read") { + peek(dmaRequestQueue_in, DMARequestMsg) { + TBEs.allocate(address); + TBEs[address].DmaRequestor := in_msg.Requestor; } } @@ -485,6 +489,7 @@ machine(Directory, "Directory protocol") transition(I, DMA_READ, ID) { //dr_sendDMAData; + r_allocateTbeForDmaRead; qf_queueMemoryFetchRequestDMA; p_popIncomingDMARequestQueue; } @@ -492,6 +497,7 @@ machine(Directory, "Directory protocol") transition(ID, Memory_Data, I) { dr_sendDMAData; //p_popIncomingDMARequestQueue; + w_deallocateTBE; l_popMemQueue; } diff --git a/src/mem/protocol/MI_example-dma.sm b/src/mem/protocol/MI_example-dma.sm index e883288df..79c42e719 100644 --- a/src/mem/protocol/MI_example-dma.sm +++ b/src/mem/protocol/MI_example-dma.sm @@ -71,6 +71,7 @@ machine(DMA, "DMA Controller") out_msg.PhysicalAddress := in_msg.PhysicalAddress; out_msg.LineAddress := in_msg.LineAddress; out_msg.Type := DMARequestType:READ; + out_msg.Requestor := machineID; out_msg.DataBlk := in_msg.DataBlk; out_msg.Len := in_msg.Len; out_msg.Destination.add(map_Address_to_Directory(address)); @@ -85,6 +86,7 @@ machine(DMA, "DMA Controller") out_msg.PhysicalAddress := in_msg.PhysicalAddress; out_msg.LineAddress := in_msg.LineAddress; out_msg.Type := DMARequestType:WRITE; + out_msg.Requestor := machineID; out_msg.DataBlk := in_msg.DataBlk; out_msg.Len := in_msg.Len; out_msg.Destination.add(map_Address_to_Directory(address)); @@ -113,10 +115,6 @@ machine(DMA, "DMA Controller") dmaResponseQueue_in.dequeue(); } - action(z_stall, "z", desc="dma is busy..stall") { - // do nothing - } - transition(READY, ReadRequest, BUSY_RD) { s_sendReadRequest; p_popRequestQueue; diff --git a/src/mem/protocol/MI_example-msg.sm b/src/mem/protocol/MI_example-msg.sm index d4d557200..3cdb74e49 100644 --- a/src/mem/protocol/MI_example-msg.sm +++ b/src/mem/protocol/MI_example-msg.sm @@ -105,6 +105,7 @@ structure(DMARequestMsg, desc="...", interface="NetworkMessage") { DMARequestType Type, desc="Request type (read/write)"; Address PhysicalAddress, desc="Physical address for this request"; Address LineAddress, desc="Line address for this request"; + MachineID Requestor, desc="Node who initiated the request"; NetDest Destination, desc="Destination"; DataBlock DataBlk, desc="DataBlk attached to this request"; int Len, desc="The length of the request"; diff --git a/src/mem/protocol/MOESI_CMP_token-L1cache.sm b/src/mem/protocol/MOESI_CMP_token-L1cache.sm index ab58c5c00..3fb4a8862 100644 --- a/src/mem/protocol/MOESI_CMP_token-L1cache.sm +++ b/src/mem/protocol/MOESI_CMP_token-L1cache.sm @@ -32,21 +32,32 @@ * */ -machine(L1Cache, "Token protocol") { +machine(L1Cache, "Token protocol") + : int l1_request_latency, + int l1_response_latency, + int l2_select_low_bit, + int l2_select_num_bits, + int N_tokens, + int retry_threshold, + int fixed_timeout_latency, + bool dynamic_timeout_enabled +{ // From this node's L1 cache TO the network - // a local L1 -> this L2 bank, currently ordered with directory forwarded requests - MessageBuffer requestFromL1Cache, network="To", virtual_network="0", ordered="false"; + // a local L1 -> this L2 bank - MessageBuffer responseFromL1Cache, network="To", virtual_network="2", ordered="false"; - MessageBuffer persistentFromL1Cache, network="To", virtual_network="3", ordered="true"; + MessageBuffer responseFromL1Cache, network="To", virtual_network="1", ordered="false"; + MessageBuffer persistentFromL1Cache, network="To", virtual_network="2", ordered="true"; + // a local L1 -> this L2 bank, currently ordered with directory forwarded requests + MessageBuffer requestFromL1Cache, network="To", virtual_network="4", ordered="false"; + // To this node's L1 cache FROM the network // a L2 bank -> this L1 - MessageBuffer requestToL1Cache, network="From", virtual_network="0", ordered="false"; + MessageBuffer responseToL1Cache, network="From", virtual_network="1", ordered="false"; + MessageBuffer persistentToL1Cache, network="From", virtual_network="2", ordered="true"; // a L2 bank -> this L1 - MessageBuffer responseToL1Cache, network="From", virtual_network="2", ordered="false"; - MessageBuffer persistentToL1Cache, network="From", virtual_network="3", ordered="true"; + MessageBuffer requestToL1Cache, network="From", virtual_network="4", ordered="false"; // STATES enumeration(State, desc="Cache states", default="L1Cache_State_I") { @@ -111,10 +122,6 @@ machine(L1Cache, "Token protocol") { // TYPES - int getRetryThreshold(); - int getFixedTimeoutLatency(); - bool getDynamicTimeoutEnabled(); - // CacheEntry structure(Entry, desc="...", interface="AbstractCacheEntry") { State CacheState, desc="cache state"; @@ -143,7 +150,7 @@ machine(L1Cache, "Token protocol") { external_type(CacheMemory) { bool cacheAvail(Address); Address cacheProbe(Address); - void allocate(Address); + void allocate(Address, Entry); void deallocate(Address); Entry lookup(Address); void changePermission(Address, AccessPermission); @@ -157,17 +164,28 @@ machine(L1Cache, "Token protocol") { bool isPresent(Address); } + external_type(PersistentTable) { + void persistentRequestLock(Address, MachineID, AccessType); + void persistentRequestUnlock(Address, MachineID); + bool okToIssueStarving(Address, MachineID); + MachineID findSmallest(Address); + AccessType typeOfSmallest(Address); + void markEntries(Address); + bool isLocked(Address); + int countStarvingForAddress(Address); + int countReadStarvingForAddress(Address); + } TBETable L1_TBEs, template_hack="<L1Cache_TBE>"; - CacheMemory L1IcacheMemory, template_hack="<L1Cache_Entry>", constructor_hack='L1_CACHE_NUM_SETS_BITS,L1_CACHE_ASSOC,MachineType_L1Cache,int_to_string(i)+"_L1I"', abstract_chip_ptr="true"; - CacheMemory L1DcacheMemory, template_hack="<L1Cache_Entry>", constructor_hack='L1_CACHE_NUM_SETS_BITS,L1_CACHE_ASSOC,MachineType_L1Cache,int_to_string(i)+"_L1D"', abstract_chip_ptr="true"; + CacheMemory L1IcacheMemory, factory='RubySystem::getCache(m_cfg["icache"])'; + CacheMemory L1DcacheMemory, factory='RubySystem::getCache(m_cfg["dcache"])'; MessageBuffer mandatoryQueue, ordered="false", abstract_chip_ptr="true"; - Sequencer sequencer, abstract_chip_ptr="true", constructor_hack="i"; + Sequencer sequencer, factory='RubySystem::getSequencer(m_cfg["sequencer"])'; bool starving, default="false"; - PersistentTable persistentTable, constructor_hack="i"; + PersistentTable persistentTable; TimerTable useTimerTable; TimerTable reissueTimerTable; @@ -175,11 +193,11 @@ machine(L1Cache, "Token protocol") { int outstandingPersistentRequests, default="0"; int averageLatencyHysteresis, default="(8)"; // Constant that provides hysteresis for calculated the estimated average - int averageLatencyCounter, default="(500 << (*m_L1Cache_averageLatencyHysteresis_vec[i]))"; + int averageLatencyCounter, default="(500 << (*m_L1Cache_averageLatencyHysteresis_ptr))"; int averageLatencyEstimate() { DEBUG_EXPR( (averageLatencyCounter >> averageLatencyHysteresis) ); - profile_average_latency_estimate( (averageLatencyCounter >> averageLatencyHysteresis) ); + //profile_average_latency_estimate( (averageLatencyCounter >> averageLatencyHysteresis) ); return averageLatencyCounter >> averageLatencyHysteresis; } @@ -366,30 +384,33 @@ machine(L1Cache, "Token protocol") { } } - GenericMachineType getNondirectHitMachType(Address addr, MachineID sender) { - if (machineIDToMachineType(sender) == MachineType:L1Cache) { - return GenericMachineType:L1Cache_wCC; // NOTE direct L1 hits should not call this - } else if (machineIDToMachineType(sender) == MachineType:L2Cache) { - if ( sender == (map_L1CacheMachId_to_L2Cache(addr,machineID))) { - return GenericMachineType:L2Cache; - } else { - return GenericMachineType:L2Cache_wCC; - } - } else { - return ConvertMachToGenericMach(machineIDToMachineType(sender)); - } - } - - bool okToIssueStarving(Address addr) { - return persistentTable.okToIssueStarving(addr); +// GenericMachineType getNondirectHitMachType(Address addr, MachineID sender) { +// if (machineIDToMachineType(sender) == MachineType:L1Cache) { +// return GenericMachineType:L1Cache_wCC; // NOTE direct L1 hits should not call this +// } else if (machineIDToMachineType(sender) == MachineType:L2Cache) { +// +// if (sender == (mapAddressToRange(addr, +// MachineType:L2Cache, +// l2_select_low_bit, +// l2_select_num_bits))) { +// +// return GenericMachineType:L2Cache; +// } else { +// return GenericMachineType:L2Cache_wCC; +// } +// } else { +// return ConvertMachToGenericMach(machineIDToMachineType(sender)); +// } +// } + + bool okToIssueStarving(Address addr, MachineID machinID) { + return persistentTable.okToIssueStarving(addr, machineID); } void markPersistentEntries(Address addr) { persistentTable.markEntries(addr); } - MessageBuffer triggerQueue, ordered="false", random="false"; - // ** OUT_PORTS ** out_port(persistentNetwork_out, PersistentMsg, persistentFromL1Cache); out_port(requestNetwork_out, RequestMsg, requestFromL1Cache); @@ -507,7 +528,11 @@ machine(L1Cache, "Token protocol") { // Mark TBE flag if response received off-chip. Use this to update average latency estimate if ( in_msg.SenderMachine == MachineType:L2Cache ) { - if (in_msg.Sender == map_L1CacheMachId_to_L2Cache(in_msg.Address, machineID)) { + if (in_msg.Sender == mapAddressToRange(in_msg.Address, + MachineType:L2Cache, + l2_select_low_bit, + l2_select_num_bits)) { + // came from an off-chip L2 cache if (L1_TBEs.isPresent(in_msg.Address)) { // L1_TBEs[in_msg.Address].ExternalResponse := true; @@ -523,15 +548,15 @@ machine(L1Cache, "Token protocol") { // profile_memory_response( in_msg.Address); } } else if ( in_msg.SenderMachine == MachineType:L1Cache) { - if (isLocalProcessor(machineID, in_msg.Sender) == false) { - if (L1_TBEs.isPresent(in_msg.Address)) { + //if (isLocalProcessor(machineID, in_msg.Sender) == false) { + //if (L1_TBEs.isPresent(in_msg.Address)) { // L1_TBEs[in_msg.Address].ExternalResponse := true; // profile_offchipL1_response(in_msg.Address ); - } - } - else { + //} + //} + //else { // profile_onchipL1_response(in_msg.Address ); - } + //} } else { error("unexpected SenderMachine"); } @@ -570,42 +595,42 @@ machine(L1Cache, "Token protocol") { // ** INSTRUCTION ACCESS *** // Check to see if it is in the OTHER L1 - if (L1DcacheMemory.isTagPresent(in_msg.Address)) { + if (L1DcacheMemory.isTagPresent(in_msg.LineAddress)) { // The block is in the wrong L1, try to write it to the L2 - trigger(Event:L1_Replacement, in_msg.Address); + trigger(Event:L1_Replacement, in_msg.LineAddress); } - if (L1IcacheMemory.isTagPresent(in_msg.Address)) { + if (L1IcacheMemory.isTagPresent(in_msg.LineAddress)) { // The tag matches for the L1, so the L1 fetches the line. We know it can't be in the L2 due to exclusion - trigger(mandatory_request_type_to_event(in_msg.Type), in_msg.Address); + trigger(mandatory_request_type_to_event(in_msg.Type), in_msg.LineAddress); } else { - if (L1IcacheMemory.cacheAvail(in_msg.Address)) { + if (L1IcacheMemory.cacheAvail(in_msg.LineAddress)) { // L1 does't have the line, but we have space for it in the L1 - trigger(mandatory_request_type_to_event(in_msg.Type), in_msg.Address); + trigger(mandatory_request_type_to_event(in_msg.Type), in_msg.LineAddress); } else { // No room in the L1, so we need to make room - trigger(Event:L1_Replacement, L1IcacheMemory.cacheProbe(in_msg.Address)); + trigger(Event:L1_Replacement, L1IcacheMemory.cacheProbe(in_msg.LineAddress)); } } } else { // *** DATA ACCESS *** // Check to see if it is in the OTHER L1 - if (L1IcacheMemory.isTagPresent(in_msg.Address)) { + if (L1IcacheMemory.isTagPresent(in_msg.LineAddress)) { // The block is in the wrong L1, try to write it to the L2 - trigger(Event:L1_Replacement, in_msg.Address); + trigger(Event:L1_Replacement, in_msg.LineAddress); } - if (L1DcacheMemory.isTagPresent(in_msg.Address)) { + if (L1DcacheMemory.isTagPresent(in_msg.LineAddress)) { // The tag matches for the L1, so the L1 fetches the line. We know it can't be in the L2 due to exclusion - trigger(mandatory_request_type_to_event(in_msg.Type), in_msg.Address); + trigger(mandatory_request_type_to_event(in_msg.Type), in_msg.LineAddress); } else { - if (L1DcacheMemory.cacheAvail(in_msg.Address)) { + if (L1DcacheMemory.cacheAvail(in_msg.LineAddress)) { // L1 does't have the line, but we have space for it in the L1 - trigger(mandatory_request_type_to_event(in_msg.Type), in_msg.Address); + trigger(mandatory_request_type_to_event(in_msg.Type), in_msg.LineAddress); } else { // No room in the L1, so we need to make room - trigger(Event:L1_Replacement, L1DcacheMemory.cacheProbe(in_msg.Address)); + trigger(Event:L1_Replacement, L1DcacheMemory.cacheProbe(in_msg.LineAddress)); } } } @@ -618,19 +643,31 @@ machine(L1Cache, "Token protocol") { action(a_issueReadRequest, "a", desc="Issue GETS") { if (L1_TBEs[address].IssueCount == 0) { // Update outstanding requests - profile_outstanding_request(outstandingRequests); + //profile_outstanding_request(outstandingRequests); outstandingRequests := outstandingRequests + 1; } - if (L1_TBEs[address].IssueCount >= getRetryThreshold() ) { + if (L1_TBEs[address].IssueCount >= retry_threshold) { // Issue a persistent request if possible - if (okToIssueStarving(address) && (starving == false)) { - enqueue(persistentNetwork_out, PersistentMsg, latency="L1_REQUEST_LATENCY") { + if (okToIssueStarving(address, machineID) && (starving == false)) { + enqueue(persistentNetwork_out, PersistentMsg, latency = l1_request_latency) { out_msg.Address := address; out_msg.Type := PersistentRequestType:GETS_PERSISTENT; out_msg.Requestor := machineID; out_msg.Destination.broadcast(MachineType:L1Cache); - out_msg.Destination.addNetDest(getAllPertinentL2Banks(address)); + + // + // Currently the configuration system limits the system to only one + // chip. Therefore, if we assume one shared L2 cache, then only one + // pertinent L2 cache exist. + // + //out_msg.Destination.addNetDest(getAllPertinentL2Banks(address)); + + out_msg.Destination.add(mapAddressToRange(address, + MachineType:L2Cache, + l2_select_low_bit, + l2_select_num_bits)); + out_msg.Destination.add(map_Address_to_Directory(address)); out_msg.MessageSize := MessageSizeType:Persistent_Control; out_msg.Prefetch := L1_TBEs[address].Prefetch; @@ -640,11 +677,11 @@ machine(L1Cache, "Token protocol") { starving := true; if (L1_TBEs[address].IssueCount == 0) { - profile_persistent_prediction(address, L1_TBEs[address].AccessType); + //profile_persistent_prediction(address, L1_TBEs[address].AccessType); } // Update outstanding requests - profile_outstanding_persistent_request(outstandingPersistentRequests); + //profile_outstanding_persistent_request(outstandingPersistentRequests); outstandingPersistentRequests := outstandingPersistentRequests + 1; // Increment IssueCount @@ -666,11 +703,16 @@ machine(L1Cache, "Token protocol") { } } else { // Make a normal request - enqueue(requestNetwork_out, RequestMsg, latency="L1_REQUEST_LATENCY") { + enqueue(requestNetwork_out, RequestMsg, latency = l1_request_latency) { out_msg.Address := address; out_msg.Type := CoherenceRequestType:GETS; out_msg.Requestor := machineID; - out_msg.Destination.add(map_L1CacheMachId_to_L2Cache(address,machineID)); + + out_msg.Destination.add(mapAddressToRange(address, + MachineType:L2Cache, + l2_select_low_bit, + l2_select_num_bits)); + out_msg.RetryNum := L1_TBEs[address].IssueCount; if (L1_TBEs[address].IssueCount == 0) { out_msg.MessageSize := MessageSizeType:Request_Control; @@ -682,11 +724,18 @@ machine(L1Cache, "Token protocol") { } // send to other local L1s, with local bit set - enqueue(requestNetwork_out, RequestMsg, latency="L1_REQUEST_LATENCY") { + enqueue(requestNetwork_out, RequestMsg, latency = l1_request_latency) { out_msg.Address := address; out_msg.Type := CoherenceRequestType:GETS; out_msg.Requestor := machineID; - out_msg.Destination := getOtherLocalL1IDs(machineID); + + // + // Since only one chip, assuming all L1 caches are local + // + //out_msg.Destination := getOtherLocalL1IDs(machineID); + out_msg.Destination.broadcast(MachineType:L1Cache); + out_msg.Destination.remove(machineID); + out_msg.RetryNum := L1_TBEs[address].IssueCount; out_msg.isLocal := true; if (L1_TBEs[address].IssueCount == 0) { @@ -703,10 +752,10 @@ machine(L1Cache, "Token protocol") { // Set a wakeup timer - if (getDynamicTimeoutEnabled()) { + if (dynamic_timeout_enabled) { reissueTimerTable.set(address, 1.25 * averageLatencyEstimate()); } else { - reissueTimerTable.set(address, getFixedTimeoutLatency()); + reissueTimerTable.set(address, fixed_timeout_latency); } } @@ -716,20 +765,32 @@ machine(L1Cache, "Token protocol") { if (L1_TBEs[address].IssueCount == 0) { // Update outstanding requests - profile_outstanding_request(outstandingRequests); + //profile_outstanding_request(outstandingRequests); outstandingRequests := outstandingRequests + 1; } - if (L1_TBEs[address].IssueCount >= getRetryThreshold() ) { + if (L1_TBEs[address].IssueCount >= retry_threshold) { // Issue a persistent request if possible - if ( okToIssueStarving(address) && (starving == false)) { - enqueue(persistentNetwork_out, PersistentMsg, latency="L1_REQUEST_LATENCY") { + if ( okToIssueStarving(address, machineID) && (starving == false)) { + enqueue(persistentNetwork_out, PersistentMsg, latency = l1_request_latency) { out_msg.Address := address; out_msg.Type := PersistentRequestType:GETX_PERSISTENT; out_msg.Requestor := machineID; out_msg.RequestorMachine := MachineType:L1Cache; out_msg.Destination.broadcast(MachineType:L1Cache); - out_msg.Destination.addNetDest(getAllPertinentL2Banks(address)); + + // + // Currently the configuration system limits the system to only one + // chip. Therefore, if we assume one shared L2 cache, then only one + // pertinent L2 cache exist. + // + //out_msg.Destination.addNetDest(getAllPertinentL2Banks(address)); + + out_msg.Destination.add(mapAddressToRange(address, + MachineType:L2Cache, + l2_select_low_bit, + l2_select_num_bits)); + out_msg.Destination.add(map_Address_to_Directory(address)); out_msg.MessageSize := MessageSizeType:Persistent_Control; out_msg.Prefetch := L1_TBEs[address].Prefetch; @@ -739,11 +800,11 @@ machine(L1Cache, "Token protocol") { starving := true; // Update outstanding requests - profile_outstanding_persistent_request(outstandingPersistentRequests); + //profile_outstanding_persistent_request(outstandingPersistentRequests); outstandingPersistentRequests := outstandingPersistentRequests + 1; if (L1_TBEs[address].IssueCount == 0) { - profile_persistent_prediction(address, L1_TBEs[address].AccessType); + //profile_persistent_prediction(address, L1_TBEs[address].AccessType); } // Increment IssueCount @@ -766,12 +827,17 @@ machine(L1Cache, "Token protocol") { } else { // Make a normal request - enqueue(requestNetwork_out, RequestMsg, latency="L1_REQUEST_LATENCY") { + enqueue(requestNetwork_out, RequestMsg, latency = l1_request_latency) { out_msg.Address := address; out_msg.Type := CoherenceRequestType:GETX; out_msg.Requestor := machineID; out_msg.RequestorMachine := MachineType:L1Cache; - out_msg.Destination.add(map_L1CacheMachId_to_L2Cache(address,machineID)); + + out_msg.Destination.add(mapAddressToRange(address, + MachineType:L2Cache, + l2_select_low_bit, + l2_select_num_bits)); + out_msg.RetryNum := L1_TBEs[address].IssueCount; if (L1_TBEs[address].IssueCount == 0) { @@ -784,12 +850,19 @@ machine(L1Cache, "Token protocol") { } // send to other local L1s too - enqueue(requestNetwork_out, RequestMsg, latency="L1_REQUEST_LATENCY") { + enqueue(requestNetwork_out, RequestMsg, latency = l1_request_latency) { out_msg.Address := address; out_msg.Type := CoherenceRequestType:GETX; out_msg.Requestor := machineID; out_msg.isLocal := true; - out_msg.Destination := getOtherLocalL1IDs(machineID); + + // + // Since only one chip, assuming all L1 caches are local + // + //out_msg.Destination := getOtherLocalL1IDs(machineID); + out_msg.Destination.broadcast(MachineType:L1Cache); + out_msg.Destination.remove(machineID); + out_msg.RetryNum := L1_TBEs[address].IssueCount; if (L1_TBEs[address].IssueCount == 0) { out_msg.MessageSize := MessageSizeType:Request_Control; @@ -807,10 +880,10 @@ machine(L1Cache, "Token protocol") { DEBUG_EXPR(L1_TBEs[address].IssueCount); // Set a wakeup timer - if (getDynamicTimeoutEnabled()) { + if (dynamic_timeout_enabled) { reissueTimerTable.set(address, 1.25 * averageLatencyEstimate()); } else { - reissueTimerTable.set(address, getFixedTimeoutLatency()); + reissueTimerTable.set(address, fixed_timeout_latency); } } } @@ -818,7 +891,7 @@ machine(L1Cache, "Token protocol") { action(bb_bounceResponse, "\b", desc="Bounce tokens and data to memory") { peek(responseNetwork_in, ResponseMsg) { // FIXME, should use a 3rd vnet - enqueue(responseNetwork_out, ResponseMsg, latency="NULL_LATENCY") { + enqueue(responseNetwork_out, ResponseMsg, latency="1") { out_msg.Address := address; out_msg.Type := in_msg.Type; out_msg.Sender := machineID; @@ -833,11 +906,16 @@ machine(L1Cache, "Token protocol") { } action(c_ownedReplacement, "c", desc="Issue writeback") { - enqueue(responseNetwork_out, ResponseMsg, latency="L1_RESPONSE_LATENCY") { + enqueue(responseNetwork_out, ResponseMsg, latency = l1_response_latency) { out_msg.Address := address; out_msg.Sender := machineID; out_msg.SenderMachine := MachineType:L1Cache; - out_msg.Destination.add(map_L1CacheMachId_to_L2Cache(address,machineID)); + + out_msg.Destination.add(mapAddressToRange(address, + MachineType:L2Cache, + l2_select_low_bit, + l2_select_num_bits)); + out_msg.Tokens := getCacheEntry(address).Tokens; out_msg.DataBlk := getCacheEntry(address).DataBlk; out_msg.Dirty := getCacheEntry(address).Dirty; @@ -853,11 +931,16 @@ machine(L1Cache, "Token protocol") { // don't send writeback if replacing block with no tokens if (getCacheEntry(address).Tokens != 0) { - enqueue(responseNetwork_out, ResponseMsg, latency="L1_RESPONSE_LATENCY") { + enqueue(responseNetwork_out, ResponseMsg, latency = l1_response_latency) { out_msg.Address := address; out_msg.Sender := machineID; out_msg.SenderMachine := MachineType:L1Cache; - out_msg.Destination.add(map_L1CacheMachId_to_L2Cache(address,machineID)); + + out_msg.Destination.add(mapAddressToRange(address, + MachineType:L2Cache, + l2_select_low_bit, + l2_select_num_bits)); + out_msg.Tokens := getCacheEntry(address).Tokens; out_msg.DataBlk := getCacheEntry(address).DataBlk; // assert(getCacheEntry(address).Dirty == false); @@ -879,7 +962,7 @@ machine(L1Cache, "Token protocol") { action(d_sendDataWithToken, "d", desc="Send data and a token from cache to requestor") { peek(requestNetwork_in, RequestMsg) { - enqueue(responseNetwork_out, ResponseMsg, latency="L1_RESPONSE_LATENCY") { + enqueue(responseNetwork_out, ResponseMsg, latency = l1_response_latency) { out_msg.Address := address; out_msg.Type := CoherenceResponseType:DATA_SHARED; out_msg.Sender := machineID; @@ -902,14 +985,14 @@ machine(L1Cache, "Token protocol") { action(d_sendDataWithNTokenIfAvail, "\dd", desc="Send data and a token from cache to requestor") { peek(requestNetwork_in, RequestMsg) { - if (getCacheEntry(address).Tokens > N_tokens()) { - enqueue(responseNetwork_out, ResponseMsg, latency="L1_RESPONSE_LATENCY") { + if (getCacheEntry(address).Tokens > N_tokens) { + enqueue(responseNetwork_out, ResponseMsg, latency = l1_response_latency) { out_msg.Address := address; out_msg.Type := CoherenceResponseType:DATA_SHARED; out_msg.Sender := machineID; out_msg.SenderMachine := MachineType:L1Cache; out_msg.Destination.add(in_msg.Requestor); - out_msg.Tokens := N_tokens(); + out_msg.Tokens := N_tokens; out_msg.DataBlk := getCacheEntry(address).DataBlk; // out_msg.Dirty := getCacheEntry(address).Dirty; out_msg.Dirty := false; @@ -919,10 +1002,10 @@ machine(L1Cache, "Token protocol") { out_msg.MessageSize := MessageSizeType:Response_Data; } } - getCacheEntry(address).Tokens := getCacheEntry(address).Tokens - N_tokens(); + getCacheEntry(address).Tokens := getCacheEntry(address).Tokens - N_tokens; } else if (getCacheEntry(address).Tokens > 1) { - enqueue(responseNetwork_out, ResponseMsg, latency="L1_RESPONSE_LATENCY") { + enqueue(responseNetwork_out, ResponseMsg, latency = l1_response_latency) { out_msg.Address := address; out_msg.Type := CoherenceResponseType:DATA_SHARED; out_msg.Sender := machineID; @@ -946,7 +1029,7 @@ machine(L1Cache, "Token protocol") { action(dd_sendDataWithAllTokens, "\d", desc="Send data and all tokens from cache to requestor") { peek(requestNetwork_in, RequestMsg) { - enqueue(responseNetwork_out, ResponseMsg, latency="L1_RESPONSE_LATENCY") { + enqueue(responseNetwork_out, ResponseMsg, latency = l1_response_latency) { out_msg.Address := address; out_msg.Type := CoherenceResponseType:DATA_OWNER; out_msg.Sender := machineID; @@ -969,7 +1052,7 @@ machine(L1Cache, "Token protocol") { action(e_sendAckWithCollectedTokens, "e", desc="Send ack with the tokens we've collected thus far.") { // assert(persistentTable.findSmallest(address) != id); // Make sure we never bounce tokens to ourself if (getCacheEntry(address).Tokens > 0) { - enqueue(responseNetwork_out, ResponseMsg, latency="L1_RESPONSE_LATENCY") { + enqueue(responseNetwork_out, ResponseMsg, latency = l1_response_latency) { out_msg.Address := address; out_msg.Type := CoherenceResponseType:ACK; out_msg.Sender := machineID; @@ -986,7 +1069,7 @@ machine(L1Cache, "Token protocol") { action(ee_sendDataWithAllTokens, "\e", desc="Send data and all tokens from cache to starver") { //assert(persistentTable.findSmallest(address) != id); // Make sure we never bounce tokens to ourself assert(getCacheEntry(address).Tokens > 0); - enqueue(responseNetwork_out, ResponseMsg, latency="L1_RESPONSE_LATENCY") { + enqueue(responseNetwork_out, ResponseMsg, latency = l1_response_latency) { out_msg.Address := address; out_msg.Type := CoherenceResponseType:DATA_OWNER; out_msg.Sender := machineID; @@ -1005,23 +1088,23 @@ machine(L1Cache, "Token protocol") { //assert(persistentTable.findSmallest(address) != id); // Make sure we never bounce tokens to ourself assert(getCacheEntry(address).Tokens > 0); if (getCacheEntry(address).Tokens > 1) { - enqueue(responseNetwork_out, ResponseMsg, latency="L1_RESPONSE_LATENCY") { + enqueue(responseNetwork_out, ResponseMsg, latency = l1_response_latency) { out_msg.Address := address; out_msg.Type := CoherenceResponseType:ACK; out_msg.Sender := machineID; out_msg.SenderMachine := MachineType:L1Cache; out_msg.Destination.add(persistentTable.findSmallest(address)); assert(getCacheEntry(address).Tokens >= 1); - if (getCacheEntry(address).Tokens > N_tokens()) { - out_msg.Tokens := getCacheEntry(address).Tokens - N_tokens(); + if (getCacheEntry(address).Tokens > N_tokens) { + out_msg.Tokens := getCacheEntry(address).Tokens - N_tokens; } else { out_msg.Tokens := getCacheEntry(address).Tokens - 1; } out_msg.MessageSize := MessageSizeType:Response_Control; } } - if (getCacheEntry(address).Tokens > N_tokens()) { - getCacheEntry(address).Tokens := N_tokens(); + if (getCacheEntry(address).Tokens > N_tokens) { + getCacheEntry(address).Tokens := N_tokens; } else { getCacheEntry(address).Tokens := 1; } @@ -1031,15 +1114,15 @@ machine(L1Cache, "Token protocol") { //assert(persistentTable.findSmallest(address) != id); // Make sure we never bounce tokens to ourself assert(getCacheEntry(address).Tokens > 0); if (getCacheEntry(address).Tokens > 1) { - enqueue(responseNetwork_out, ResponseMsg, latency="L1_RESPONSE_LATENCY") { + enqueue(responseNetwork_out, ResponseMsg, latency = l1_response_latency) { out_msg.Address := address; out_msg.Type := CoherenceResponseType:DATA_OWNER; out_msg.Sender := machineID; out_msg.SenderMachine := MachineType:L1Cache; out_msg.Destination.add(persistentTable.findSmallest(address)); assert(getCacheEntry(address).Tokens >= 1); - if (getCacheEntry(address).Tokens > N_tokens()) { - out_msg.Tokens := getCacheEntry(address).Tokens - N_tokens(); + if (getCacheEntry(address).Tokens > N_tokens) { + out_msg.Tokens := getCacheEntry(address).Tokens - N_tokens; } else { out_msg.Tokens := getCacheEntry(address).Tokens - 1; } @@ -1047,8 +1130,8 @@ machine(L1Cache, "Token protocol") { out_msg.Dirty := getCacheEntry(address).Dirty; out_msg.MessageSize := MessageSizeType:Response_Data; } - if (getCacheEntry(address).Tokens > N_tokens()) { - getCacheEntry(address).Tokens := N_tokens(); + if (getCacheEntry(address).Tokens > N_tokens) { + getCacheEntry(address).Tokens := N_tokens; } else { getCacheEntry(address).Tokens := 1; } @@ -1061,7 +1144,7 @@ machine(L1Cache, "Token protocol") { peek(responseNetwork_in, ResponseMsg) { // assert(persistentTable.findSmallest(address) != id); // Make sure we never bounce tokens to ourself // FIXME, should use a 3rd vnet in some cases - enqueue(responseNetwork_out, ResponseMsg, latency="NULL_LATENCY") { + enqueue(responseNetwork_out, ResponseMsg, latency="1") { out_msg.Address := address; out_msg.Type := in_msg.Type; out_msg.Sender := machineID; @@ -1079,7 +1162,8 @@ machine(L1Cache, "Token protocol") { action(h_load_hit, "h", desc="Notify sequencer the load completed.") { DEBUG_EXPR(address); DEBUG_EXPR(getCacheEntry(address).DataBlk); - sequencer.readCallback(address, getCacheEntry(address).DataBlk, GenericMachineType:L1Cache, PrefetchBit:No); + //sequencer.readCallback(address, getCacheEntry(address).DataBlk, GenericMachineType:L1Cache, PrefetchBit:No); + sequencer.readCallback(address, getCacheEntry(address).DataBlk); } action(x_external_load_hit, "x", desc="Notify sequencer the load completed.") { @@ -1087,14 +1171,16 @@ machine(L1Cache, "Token protocol") { DEBUG_EXPR(getCacheEntry(address).DataBlk); peek(responseNetwork_in, ResponseMsg) { - sequencer.readCallback(address, getCacheEntry(address).DataBlk, getNondirectHitMachType(in_msg.Address, in_msg.Sender), PrefetchBit:No); + //sequencer.readCallback(address, getCacheEntry(address).DataBlk, getNondirectHitMachType(in_msg.Address, in_msg.Sender), PrefetchBit:No); + sequencer.readCallback(address, getCacheEntry(address).DataBlk); } } action(hh_store_hit, "\h", desc="Notify sequencer that store completed.") { DEBUG_EXPR(address); DEBUG_EXPR(getCacheEntry(address).DataBlk); - sequencer.writeCallback(address, getCacheEntry(address).DataBlk, GenericMachineType:L1Cache, PrefetchBit:No); + //sequencer.writeCallback(address, getCacheEntry(address).DataBlk, GenericMachineType:L1Cache, PrefetchBit:No); + sequencer.writeCallback(address, getCacheEntry(address).DataBlk); getCacheEntry(address).Dirty := true; DEBUG_EXPR(getCacheEntry(address).DataBlk); } @@ -1103,7 +1189,8 @@ machine(L1Cache, "Token protocol") { DEBUG_EXPR(address); DEBUG_EXPR(getCacheEntry(address).DataBlk); peek(responseNetwork_in, ResponseMsg) { - sequencer.writeCallback(address, getCacheEntry(address).DataBlk, getNondirectHitMachType(in_msg.Address, in_msg.Sender), PrefetchBit:No); + //sequencer.writeCallback(address, getCacheEntry(address).DataBlk, getNondirectHitMachType(in_msg.Address, in_msg.Sender), PrefetchBit:No); + sequencer.writeCallback(address, getCacheEntry(address).DataBlk); } getCacheEntry(address).Dirty := true; DEBUG_EXPR(getCacheEntry(address).DataBlk); @@ -1133,8 +1220,6 @@ machine(L1Cache, "Token protocol") { useTimerTable.unset(address); } - - action(k_popMandatoryQueue, "k", desc="Pop mandatory queue.") { mandatoryQueue_in.dequeue(); } @@ -1156,14 +1241,19 @@ machine(L1Cache, "Token protocol") { } action(p_informL2AboutTokenLoss, "p", desc="Inform L2 about loss of all tokens") { - enqueue(responseNetwork_out, ResponseMsg, latency="L1_RESPONSE_LATENCY") { + enqueue(responseNetwork_out, ResponseMsg, latency = l1_response_latency) { out_msg.Address := address; out_msg.Type := CoherenceResponseType:INV; out_msg.Tokens := 0; out_msg.Sender := machineID; out_msg.SenderMachine := MachineType:L1Cache; out_msg.DestMachine := MachineType:L2Cache; - out_msg.Destination.add(map_L1CacheMachId_to_L2Cache(address,machineID)); + + out_msg.Destination.add(mapAddressToRange(address, + MachineType:L2Cache, + l2_select_low_bit, + l2_select_num_bits)); + out_msg.MessageSize := MessageSizeType:Response_Control; } } @@ -1189,13 +1279,25 @@ machine(L1Cache, "Token protocol") { if (L1_TBEs[address].WentPersistent) { // assert(starving == true); outstandingRequests := outstandingRequests - 1; - enqueue(persistentNetwork_out, PersistentMsg, latency="L1_REQUEST_LATENCY") { + enqueue(persistentNetwork_out, PersistentMsg, latency = l1_request_latency) { out_msg.Address := address; out_msg.Type := PersistentRequestType:DEACTIVATE_PERSISTENT; out_msg.Requestor := machineID; out_msg.RequestorMachine := MachineType:L1Cache; out_msg.Destination.broadcast(MachineType:L1Cache); - out_msg.Destination.addNetDest(getAllPertinentL2Banks(address)); + + // + // Currently the configuration system limits the system to only one + // chip. Therefore, if we assume one shared L2 cache, then only one + // pertinent L2 cache exist. + // + //out_msg.Destination.addNetDest(getAllPertinentL2Banks(address)); + + out_msg.Destination.add(mapAddressToRange(address, + MachineType:L2Cache, + l2_select_low_bit, + l2_select_num_bits)); + out_msg.Destination.add(map_Address_to_Directory(address)); out_msg.MessageSize := MessageSizeType:Persistent_Control; } @@ -1217,14 +1319,14 @@ machine(L1Cache, "Token protocol") { // profile_token_retry(address, L1_TBEs[address].AccessType, 1); //} - profile_token_retry(address, L1_TBEs[address].AccessType, L1_TBEs[address].IssueCount); + //profile_token_retry(address, L1_TBEs[address].AccessType, L1_TBEs[address].IssueCount); L1_TBEs.deallocate(address); } action(t_sendAckWithCollectedTokens, "t", desc="Send ack with the tokens we've collected thus far.") { if (getCacheEntry(address).Tokens > 0) { peek(requestNetwork_in, RequestMsg) { - enqueue(responseNetwork_out, ResponseMsg, latency="L1_RESPONSE_LATENCY") { + enqueue(responseNetwork_out, ResponseMsg, latency = l1_response_latency) { out_msg.Address := address; out_msg.Type := CoherenceResponseType:ACK; out_msg.Sender := machineID; @@ -1259,13 +1361,13 @@ machine(L1Cache, "Token protocol") { action(ii_allocateL1DCacheBlock, "\i", desc="Set L1 D-cache tag equal to tag of block B.") { if (L1DcacheMemory.isTagPresent(address) == false) { - L1DcacheMemory.allocate(address); + L1DcacheMemory.allocate(address, new Entry); } } action(pp_allocateL1ICacheBlock, "\p", desc="Set L1 I-cache tag equal to tag of block B.") { if (L1IcacheMemory.isTagPresent(address) == false) { - L1IcacheMemory.allocate(address); + L1IcacheMemory.allocate(address, new Entry); } } @@ -1281,11 +1383,6 @@ machine(L1Cache, "Token protocol") { } } - - action(z_stall, "z", desc="Stall") { - - } - action(zz_recycleMandatoryQueue, "\z", desc="Send the head of the mandatory queue to the back of the queue.") { mandatoryQueue_in.recycle(); } diff --git a/src/mem/protocol/MOESI_CMP_token-L2cache.sm b/src/mem/protocol/MOESI_CMP_token-L2cache.sm index 0a58ed5cf..9a5c400f2 100644 --- a/src/mem/protocol/MOESI_CMP_token-L2cache.sm +++ b/src/mem/protocol/MOESI_CMP_token-L2cache.sm @@ -32,20 +32,33 @@ * */ -machine(L2Cache, "Token protocol") { +machine(L2Cache, "Token protocol") + : int l2_request_latency, + int l2_response_latency, + int N_tokens, + bool filtering_enabled +{ // L2 BANK QUEUES // From local bank of L2 cache TO the network - MessageBuffer L1RequestFromL2Cache, network="To", virtual_network="0", ordered="false"; // this L2 bank -> a local L1 - MessageBuffer GlobalRequestFromL2Cache, network="To", virtual_network="1", ordered="false"; // this L2 bank -> mod-directory - MessageBuffer responseFromL2Cache, network="To", virtual_network="2", ordered="false"; // this L2 bank -> a local L1 || mod-directory + + // this L2 bank -> a local L1 || mod-directory + MessageBuffer responseFromL2Cache, network="To", virtual_network="1", ordered="false"; + // this L2 bank -> mod-directory + MessageBuffer GlobalRequestFromL2Cache, network="To", virtual_network="3", ordered="false"; + // this L2 bank -> a local L1 + MessageBuffer L1RequestFromL2Cache, network="To", virtual_network="4", ordered="false"; // FROM the network to this local bank of L2 cache - MessageBuffer L1RequestToL2Cache, network="From", virtual_network="0", ordered="false"; // a local L1 -> this L2 bank - MessageBuffer GlobalRequestToL2Cache, network="From", virtual_network="1", ordered="false"; // mod-directory -> this L2 bank - MessageBuffer responseToL2Cache, network="From", virtual_network="2", ordered="false"; // a local L1 || mod-directory -> this L2 bank - MessageBuffer persistentToL2Cache, network="From", virtual_network="3", ordered="true"; + + // a local L1 || mod-directory -> this L2 bank + MessageBuffer responseToL2Cache, network="From", virtual_network="1", ordered="false"; + MessageBuffer persistentToL2Cache, network="From", virtual_network="2", ordered="true"; + // mod-directory -> this L2 bank + MessageBuffer GlobalRequestToL2Cache, network="From", virtual_network="3", ordered="false"; + // a local L1 -> this L2 bank + MessageBuffer L1RequestToL2Cache, network="From", virtual_network="4", ordered="false"; // STATES enumeration(State, desc="L2 Cache states", default="L2Cache_State_I") { @@ -107,8 +120,6 @@ machine(L2Cache, "Token protocol") { DataBlock DataBlk, desc="data for the block"; } - - structure(DirEntry, desc="...") { Set Sharers, desc="Set of the internal processors that want the block in shared state"; bool exclusive, default="false", desc="if local exclusive is likely"; @@ -117,7 +128,7 @@ machine(L2Cache, "Token protocol") { external_type(CacheMemory) { bool cacheAvail(Address); Address cacheProbe(Address); - void allocate(Address); + void allocate(Address, Entry); void deallocate(Address); Entry lookup(Address); void changePermission(Address, AccessPermission); @@ -132,19 +143,28 @@ machine(L2Cache, "Token protocol") { bool isTagPresent(Address); } + external_type(PersistentTable) { + void persistentRequestLock(Address, MachineID, AccessType); + void persistentRequestUnlock(Address, MachineID); + MachineID findSmallest(Address); + AccessType typeOfSmallest(Address); + void markEntries(Address); + bool isLocked(Address); + int countStarvingForAddress(Address); + int countReadStarvingForAddress(Address); + } - CacheMemory L2cacheMemory, template_hack="<L2Cache_Entry>", constructor_hack='L2_CACHE_NUM_SETS_BITS,L2_CACHE_ASSOC,MachineType_L2Cache,int_to_string(i)+"_L2"'; + CacheMemory L2cacheMemory, factory='RubySystem::getCache(m_cfg["cache"])'; - PersistentTable persistentTable, constructor_hack="i"; + PersistentTable persistentTable; PerfectCacheMemory localDirectory, template_hack="<L2Cache_DirEntry>"; - - bool getFilteringEnabled(); - Entry getL2CacheEntry(Address addr), return_by_ref="yes" { if (L2cacheMemory.isTagPresent(addr)) { return L2cacheMemory[addr]; } + assert(false); + return L2cacheMemory[addr]; } int getTokens(Address addr) { @@ -465,15 +485,21 @@ machine(L2Cache, "Token protocol") { // if this is a retry or no local sharers, broadcast normally // if (in_msg.RetryNum > 0 || (in_msg.Type == CoherenceRequestType:GETX && exclusiveExists(in_msg.Address) == false) || (in_msg.Type == CoherenceRequestType:GETS && sharersExist(in_msg.Address) == false)) { - enqueue(globalRequestNetwork_out, RequestMsg, latency="L2_REQUEST_LATENCY") { + enqueue(globalRequestNetwork_out, RequestMsg, latency=l2_request_latency) { out_msg.Address := in_msg.Address; out_msg.Type := in_msg.Type; out_msg.Requestor := in_msg.Requestor; out_msg.RequestorMachine := in_msg.RequestorMachine; - //out_msg.Destination.broadcast(MachineType:L2Cache); out_msg.RetryNum := in_msg.RetryNum; - out_msg.Destination.addNetDest(getAllPertinentL2Banks(address)); - out_msg.Destination.remove(map_L1CacheMachId_to_L2Cache(address, in_msg.Requestor)); + + // + // If a statically shared L2 cache, then no other L2 caches can + // store the block + // + //out_msg.Destination.broadcast(MachineType:L2Cache); + //out_msg.Destination.addNetDest(getAllPertinentL2Banks(address)); + //out_msg.Destination.remove(map_L1CacheMachId_to_L2Cache(address, in_msg.Requestor)); + out_msg.Destination.add(map_Address_to_Directory(address)); out_msg.MessageSize := MessageSizeType:Request_Control; out_msg.AccessMode := in_msg.AccessMode; @@ -489,7 +515,7 @@ machine(L2Cache, "Token protocol") { action(bb_bounceResponse, "\b", desc="Bounce tokens and data to memory") { peek(responseNetwork_in, ResponseMsg) { // FIXME, should use a 3rd vnet - enqueue(responseNetwork_out, ResponseMsg, latency="NULL_LATENCY") { + enqueue(responseNetwork_out, ResponseMsg, latency="1") { out_msg.Address := address; out_msg.Type := in_msg.Type; out_msg.Sender := machineID; @@ -505,7 +531,7 @@ machine(L2Cache, "Token protocol") { action(c_cleanReplacement, "c", desc="Issue clean writeback") { if (getL2CacheEntry(address).Tokens > 0) { - enqueue(responseNetwork_out, ResponseMsg, latency="L2_RESPONSE_LATENCY") { + enqueue(responseNetwork_out, ResponseMsg, latency=l2_response_latency) { out_msg.Address := address; out_msg.Type := CoherenceResponseType:ACK; out_msg.Sender := machineID; @@ -519,7 +545,7 @@ machine(L2Cache, "Token protocol") { } action(cc_dirtyReplacement, "\c", desc="Issue dirty writeback") { - enqueue(responseNetwork_out, ResponseMsg, latency="L2_RESPONSE_LATENCY") { + enqueue(responseNetwork_out, ResponseMsg, latency=l2_response_latency) { out_msg.Address := address; out_msg.Sender := machineID; out_msg.SenderMachine := MachineType:L2Cache; @@ -541,22 +567,22 @@ machine(L2Cache, "Token protocol") { action(d_sendDataWithTokens, "d", desc="Send data and a token from cache to requestor") { peek(requestNetwork_in, RequestMsg) { - if (getL2CacheEntry(address).Tokens > N_tokens()) { - enqueue(responseNetwork_out, ResponseMsg, latency="L2_RESPONSE_LATENCY") { + if (getL2CacheEntry(address).Tokens > N_tokens) { + enqueue(responseNetwork_out, ResponseMsg, latency=l2_response_latency) { out_msg.Address := address; out_msg.Type := CoherenceResponseType:DATA_SHARED; out_msg.Sender := machineID; out_msg.SenderMachine := MachineType:L2Cache; out_msg.Destination.add(in_msg.Requestor); - out_msg.Tokens := N_tokens(); + out_msg.Tokens := N_tokens; out_msg.DataBlk := getL2CacheEntry(address).DataBlk; out_msg.Dirty := false; out_msg.MessageSize := MessageSizeType:Response_Data; } - getL2CacheEntry(address).Tokens := getL2CacheEntry(address).Tokens - N_tokens(); + getL2CacheEntry(address).Tokens := getL2CacheEntry(address).Tokens - N_tokens; } else { - enqueue(responseNetwork_out, ResponseMsg, latency="L2_RESPONSE_LATENCY") { + enqueue(responseNetwork_out, ResponseMsg, latency=l2_response_latency) { out_msg.Address := address; out_msg.Type := CoherenceResponseType:DATA_SHARED; out_msg.Sender := machineID; @@ -574,7 +600,7 @@ machine(L2Cache, "Token protocol") { action(dd_sendDataWithAllTokens, "\d", desc="Send data and all tokens from cache to requestor") { peek(requestNetwork_in, RequestMsg) { - enqueue(responseNetwork_out, ResponseMsg, latency="L2_RESPONSE_LATENCY") { + enqueue(responseNetwork_out, ResponseMsg, latency=l2_response_latency) { out_msg.Address := address; out_msg.Type := CoherenceResponseType:DATA_OWNER; out_msg.Sender := machineID; @@ -592,7 +618,7 @@ machine(L2Cache, "Token protocol") { action(e_sendAckWithCollectedTokens, "e", desc="Send ack with the tokens we've collected thus far.") { if (getL2CacheEntry(address).Tokens > 0) { - enqueue(responseNetwork_out, ResponseMsg, latency="L2_RESPONSE_LATENCY") { + enqueue(responseNetwork_out, ResponseMsg, latency=l2_response_latency) { out_msg.Address := address; out_msg.Type := CoherenceResponseType:ACK; out_msg.Sender := machineID; @@ -607,7 +633,7 @@ machine(L2Cache, "Token protocol") { } action(ee_sendDataWithAllTokens, "\e", desc="Send data and all tokens from cache to starver") { - enqueue(responseNetwork_out, ResponseMsg, latency="L2_RESPONSE_LATENCY") { + enqueue(responseNetwork_out, ResponseMsg, latency=l2_response_latency) { out_msg.Address := address; out_msg.Type := CoherenceResponseType:DATA_OWNER; out_msg.Sender := machineID; @@ -626,7 +652,7 @@ machine(L2Cache, "Token protocol") { //assert(persistentTable.findSmallest(address) != id); // Make sure we never bounce tokens to ourself assert(getL2CacheEntry(address).Tokens > 0); if (getL2CacheEntry(address).Tokens > 1) { - enqueue(responseNetwork_out, ResponseMsg, latency="L2_RESPONSE_LATENCY") { + enqueue(responseNetwork_out, ResponseMsg, latency=l2_response_latency) { out_msg.Address := address; out_msg.Type := CoherenceResponseType:ACK; out_msg.Sender := machineID; @@ -644,7 +670,7 @@ machine(L2Cache, "Token protocol") { //assert(persistentTable.findSmallest(address) != id); // Make sure we never bounce tokens to ourself assert(getL2CacheEntry(address).Tokens > 0); if (getL2CacheEntry(address).Tokens > 1) { - enqueue(responseNetwork_out, ResponseMsg, latency="L2_RESPONSE_LATENCY") { + enqueue(responseNetwork_out, ResponseMsg, latency=l2_response_latency) { out_msg.Address := address; out_msg.Type := CoherenceResponseType:DATA_OWNER; out_msg.Sender := machineID; @@ -666,7 +692,7 @@ machine(L2Cache, "Token protocol") { // assert(persistentTable.isLocked(address)); peek(responseNetwork_in, ResponseMsg) { // FIXME, should use a 3rd vnet in some cases - enqueue(responseNetwork_out, ResponseMsg, latency="NULL_LATENCY") { + enqueue(responseNetwork_out, ResponseMsg, latency="1") { out_msg.Address := address; out_msg.Type := in_msg.Type; out_msg.Sender := machineID; @@ -684,7 +710,7 @@ machine(L2Cache, "Token protocol") { //assert(persistentTable.isLocked(address)); peek(responseNetwork_in, ResponseMsg) { // FIXME, should use a 3rd vnet in some cases - enqueue(responseNetwork_out, ResponseMsg, latency="NULL_LATENCY") { + enqueue(responseNetwork_out, ResponseMsg, latency="1") { out_msg.Address := address; if (in_msg.Type == CoherenceResponseType:WB_SHARED_DATA) { out_msg.Type := CoherenceResponseType:DATA_SHARED; @@ -706,7 +732,7 @@ machine(L2Cache, "Token protocol") { // assert(persistentTable.isLocked(address)); peek(responseNetwork_in, ResponseMsg) { // FIXME, should use a 3rd vnet in some cases - enqueue(responseNetwork_out, ResponseMsg, latency="NULL_LATENCY") { + enqueue(responseNetwork_out, ResponseMsg, latency="1") { out_msg.Address := address; out_msg.Type := CoherenceResponseType:DATA_OWNER; out_msg.Sender := machineID; @@ -729,24 +755,31 @@ machine(L2Cache, "Token protocol") { action(j_forwardTransientRequestToLocalSharers, "j", desc="Forward external transient request to local sharers") { peek(requestNetwork_in, RequestMsg) { - if (getFilteringEnabled() == true && in_msg.RetryNum == 0 && sharersExist(in_msg.Address) == false) { - profile_filter_action(1); + if (filtering_enabled == true && in_msg.RetryNum == 0 && sharersExist(in_msg.Address) == false) { + //profile_filter_action(1); DEBUG_EXPR("filtered message"); DEBUG_EXPR(in_msg.RetryNum); } else { - enqueue( localRequestNetwork_out, RequestMsg, latency="L2_RESPONSE_LATENCY" ) { + enqueue(localRequestNetwork_out, RequestMsg, latency=l2_response_latency ) { out_msg.Address := in_msg.Address; out_msg.Requestor := in_msg.Requestor; out_msg.RequestorMachine := in_msg.RequestorMachine; - out_msg.Destination := getLocalL1IDs(machineID); + + // + // Currently assuming only one chip so all L1s are local + // + //out_msg.Destination := getLocalL1IDs(machineID); + out_msg.Destination.broadcast(MachineType:L1Cache); + out_msg.Destination.remove(in_msg.Requestor); + out_msg.Type := in_msg.Type; out_msg.isLocal := false; out_msg.MessageSize := MessageSizeType:Request_Control; out_msg.AccessMode := in_msg.AccessMode; out_msg.Prefetch := in_msg.Prefetch; } - profile_filter_action(0); + //profile_filter_action(0); } } } @@ -756,7 +789,7 @@ machine(L2Cache, "Token protocol") { peek(L1requestNetwork_in, RequestMsg) { assert(getL2CacheEntry(address).Tokens > 0); //enqueue(responseIntraChipL2Network_out, ResponseMsg, latency="L2_to_L1_RESPONSE_LATENCY") { - enqueue(responseNetwork_out, ResponseMsg, latency="L2_RESPONSE_LATENCY") { + enqueue(responseNetwork_out, ResponseMsg, latency=l2_response_latency) { out_msg.Address := address; out_msg.Type := CoherenceResponseType:DATA_SHARED; out_msg.Sender := machineID; @@ -774,7 +807,7 @@ machine(L2Cache, "Token protocol") { action(k_dataOwnerFromL2CacheToL1Requestor, "\k", desc="Send data and a token from cache to L1 requestor") { peek(L1requestNetwork_in, RequestMsg) { assert(getL2CacheEntry(address).Tokens > 0); - enqueue(responseNetwork_out, ResponseMsg, latency="L2_RESPONSE_LATENCY") { + enqueue(responseNetwork_out, ResponseMsg, latency=l2_response_latency) { out_msg.Address := address; out_msg.Type := CoherenceResponseType:DATA_OWNER; out_msg.Sender := machineID; @@ -793,7 +826,7 @@ machine(L2Cache, "Token protocol") { peek(L1requestNetwork_in, RequestMsg) { // assert(getL2CacheEntry(address).Tokens == max_tokens()); //enqueue(responseIntraChipL2Network_out, ResponseMsg, latency="L2_to_L1_RESPONSE_LATENCY") { - enqueue(responseNetwork_out, ResponseMsg, latency="L2_RESPONSE_LATENCY") { + enqueue(responseNetwork_out, ResponseMsg, latency=l2_response_latency) { out_msg.Address := address; out_msg.Type := CoherenceResponseType:DATA_OWNER; out_msg.Sender := machineID; @@ -840,12 +873,13 @@ machine(L2Cache, "Token protocol") { } action(r_markNewSharer, "r", desc="Mark the new local sharer from local request message") { - peek(L1requestNetwork_in, RequestMsg) { - if (in_msg.Type == CoherenceRequestType:GETX) { - setNewWriter(in_msg.Address, machineIDToNodeID(in_msg.Requestor)); - } else if (in_msg.Type == CoherenceRequestType:GETS) { - addNewSharer(in_msg.Address, machineIDToNodeID(in_msg.Requestor)); + if (machineIDToMachineType(in_msg.Requestor) == MachineType:L1Cache) { + if (in_msg.Type == CoherenceRequestType:GETX) { + setNewWriter(in_msg.Address, machineIDToNodeID(in_msg.Requestor)); + } else if (in_msg.Type == CoherenceRequestType:GETS) { + addNewSharer(in_msg.Address, machineIDToNodeID(in_msg.Requestor)); + } } } } @@ -854,16 +888,19 @@ machine(L2Cache, "Token protocol") { clearExclusiveBitIfExists(address); } - action( r_setMRU, "\rr", desc="manually set the MRU bit for cache line" ) { - if(isCacheTagPresent(address)) { - L2cacheMemory.setMRU(address); + action(r_setMRU, "\rr", desc="manually set the MRU bit for cache line" ) { + peek(L1requestNetwork_in, RequestMsg) { + if ((machineIDToMachineType(in_msg.Requestor) == MachineType:L1Cache) && + (isCacheTagPresent(address))) { + L2cacheMemory.setMRU(address); + } } } action(t_sendAckWithCollectedTokens, "t", desc="Send ack with the tokens we've collected thus far.") { if (getL2CacheEntry(address).Tokens > 0) { peek(requestNetwork_in, RequestMsg) { - enqueue(responseNetwork_out, ResponseMsg, latency="L2_RESPONSE_LATENCY") { + enqueue(responseNetwork_out, ResponseMsg, latency=l2_response_latency) { out_msg.Address := address; out_msg.Type := CoherenceResponseType:ACK; out_msg.Sender := machineID; @@ -881,7 +918,7 @@ machine(L2Cache, "Token protocol") { action(tt_sendLocalAckWithCollectedTokens, "tt", desc="Send ack with the tokens we've collected thus far.") { if (getL2CacheEntry(address).Tokens > 0) { peek(L1requestNetwork_in, RequestMsg) { - enqueue(responseNetwork_out, ResponseMsg, latency="L2_RESPONSE_LATENCY") { + enqueue(responseNetwork_out, ResponseMsg, latency=l2_response_latency) { out_msg.Address := address; out_msg.Type := CoherenceResponseType:ACK; out_msg.Sender := machineID; @@ -906,19 +943,19 @@ machine(L2Cache, "Token protocol") { } action(vv_allocateL2CacheBlock, "\v", desc="Set L2 cache tag equal to tag of block B.") { - L2cacheMemory.allocate(address); + L2cacheMemory.allocate(address, new Entry); } action(rr_deallocateL2CacheBlock, "\r", desc="Deallocate L2 cache block. Sets the cache to not present, allowing a replacement in parallel with a fetch.") { L2cacheMemory.deallocate(address); } - action(uu_profileMiss, "\u", desc="Profile the demand miss") { - peek(L1requestNetwork_in, RequestMsg) { + //action(uu_profileMiss, "\u", desc="Profile the demand miss") { + // peek(L1requestNetwork_in, RequestMsg) { // AccessModeType not implemented //profile_L2Cache_miss(convertToGenericType(in_msg.Type), in_msg.AccessMode, MessageSizeTypeToInt(in_msg.MessageSize), in_msg.Prefetch, machineIDToNodeID(in_msg.Requestor)); - } - } + // } + //} action(w_assertIncomingDataAndCacheDataMatch, "w", desc="Assert that the incoming data and the data in the cache match") { @@ -927,11 +964,6 @@ machine(L2Cache, "Token protocol") { } } - action(z_stall, "z", desc="Stall") { - } - - - //***************************************************** // TRANSITIONS @@ -961,7 +993,7 @@ machine(L2Cache, "Token protocol") { transition(NP, {L1_GETS, L1_GETX}) { a_broadcastLocalRequest; r_markNewSharer; - uu_profileMiss; + //uu_profileMiss; o_popL1RequestQueue; } @@ -1012,7 +1044,7 @@ machine(L2Cache, "Token protocol") { a_broadcastLocalRequest; tt_sendLocalAckWithCollectedTokens; // send any tokens we have collected r_markNewSharer; - uu_profileMiss; + //uu_profileMiss; o_popL1RequestQueue; } @@ -1020,7 +1052,7 @@ machine(L2Cache, "Token protocol") { a_broadcastLocalRequest; tt_sendLocalAckWithCollectedTokens; // send any tokens we have collected r_markNewSharer; - uu_profileMiss; + //uu_profileMiss; o_popL1RequestQueue; } @@ -1181,7 +1213,7 @@ machine(L2Cache, "Token protocol") { tt_sendLocalAckWithCollectedTokens; r_markNewSharer; r_setMRU; - uu_profileMiss; + //uu_profileMiss; o_popL1RequestQueue; } @@ -1294,7 +1326,7 @@ machine(L2Cache, "Token protocol") { k_dataAndAllTokensFromL2CacheToL1Requestor; r_markNewSharer; r_setMRU; - uu_profileMiss; + //uu_profileMiss; o_popL1RequestQueue; } @@ -1382,7 +1414,7 @@ machine(L2Cache, "Token protocol") { transition(I_L, {L1_GETX, L1_GETS}) { a_broadcastLocalRequest; r_markNewSharer; - uu_profileMiss; + //uu_profileMiss; o_popL1RequestQueue; } @@ -1391,7 +1423,7 @@ machine(L2Cache, "Token protocol") { tt_sendLocalAckWithCollectedTokens; r_markNewSharer; r_setMRU; - uu_profileMiss; + //uu_profileMiss; o_popL1RequestQueue; } diff --git a/src/mem/protocol/MOESI_CMP_token-dir.sm b/src/mem/protocol/MOESI_CMP_token-dir.sm index 1592fd123..7925a8fe0 100644 --- a/src/mem/protocol/MOESI_CMP_token-dir.sm +++ b/src/mem/protocol/MOESI_CMP_token-dir.sm @@ -32,14 +32,23 @@ */ -machine(Directory, "Token protocol") { - - MessageBuffer requestFromDir, network="To", virtual_network="1", ordered="false"; - MessageBuffer responseFromDir, network="To", virtual_network="2", ordered="false"; - - MessageBuffer persistentToDir, network="From", virtual_network="3", ordered="true"; - MessageBuffer requestToDir, network="From", virtual_network="1", ordered="false"; - MessageBuffer responseToDir, network="From", virtual_network="2", ordered="false"; +machine(Directory, "Token protocol") + : int directory_latency, + int l2_select_low_bit, + int l2_select_num_bits, + bool distributed_persistent, + int fixed_timeout_latency +{ + + MessageBuffer dmaResponseFromDir, network="To", virtual_network="0", ordered="true"; + MessageBuffer responseFromDir, network="To", virtual_network="1", ordered="false"; + MessageBuffer persistentFromDir, network="To", virtual_network="2", ordered="true"; + MessageBuffer requestFromDir, network="To", virtual_network="4", ordered="false"; + + MessageBuffer responseToDir, network="From", virtual_network="1", ordered="false"; + MessageBuffer persistentToDir, network="From", virtual_network="2", ordered="true"; + MessageBuffer requestToDir, network="From", virtual_network="3", ordered="false"; + MessageBuffer dmaRequestToDir, network="From", virtual_network="5", ordered="true"; // STATES enumeration(State, desc="Directory states", default="Directory_State_O") { @@ -47,6 +56,24 @@ machine(Directory, "Token protocol") { O, desc="Owner"; NO, desc="Not Owner"; L, desc="Locked"; + + // Memory wait states - can block all messages including persistent requests + O_W, desc="transitioning to Owner, waiting for memory write"; + L_W, desc="transitioning to Locked, waiting for memory read"; + DR_L_W, desc="transitioning to Locked underneath a DMA read, waiting for memory data"; + NO_W, desc="transitioning to Not Owner, waiting for memory read"; + O_DW_W, desc="transitioning to Owner, waiting for memory before DMA ack"; + O_DR_W, desc="transitioning to Owner, waiting for memory before DMA data"; + + // DMA request transient states - must respond to persistent requests + O_DW, desc="issued GETX for DMA write, waiting for all tokens"; + NO_DW, desc="issued GETX for DMA write, waiting for all tokens"; + NO_DR, desc="issued GETS for DMA read, waiting for data"; + + // DMA request in progress - competing with a CPU persistent request + DW_L, desc="issued GETX for DMA write, CPU persistent request must complete first"; + DR_L, desc="issued GETS for DMA read, CPU persistent request must complete first"; + } // Events @@ -55,9 +82,23 @@ machine(Directory, "Token protocol") { GETS, desc="A GETS arrives"; Lockdown, desc="A lockdown request arrives"; Unlockdown, desc="An un-lockdown request arrives"; + Own_Lock_or_Unlock, desc="own lock or unlock"; Data_Owner, desc="Data arrive"; + Data_All_Tokens, desc="Data and all tokens"; Ack_Owner, desc="Owner token arrived without data because it was clean"; + Ack_Owner_All_Tokens, desc="All tokens including owner arrived without data because it was clean"; Tokens, desc="Tokens arrive"; + Ack_All_Tokens, desc="All_Tokens arrive"; + Request_Timeout, desc="A DMA request has timed out"; + + // Memory Controller + Memory_Data, desc="Fetched data from memory arrives"; + Memory_Ack, desc="Writeback Ack from memory arrives"; + + // DMA requests + DMA_READ, desc="A DMA Read memory request"; + DMA_WRITE, desc="A DMA Write memory request"; + DMA_WRITE_All_Tokens, desc="A DMA Write memory request, directory has all tokens"; } // TYPES @@ -73,7 +114,7 @@ machine(Directory, "Token protocol") { // is 'soft state' that does not need to be correct (as long as // you're eventually willing to resort to broadcast.) - Set Owner, desc="Probable Owner of the line. More accurately, the set of processors who need to see a GetS or GetO. We use a Set for convenience, but only one bit is set at a time."; + Set Owner, desc="Probable Owner of the line. More accurately, the set of processors who need to see a GetS or GetO. We use a Set for convenience, but only one bit is set at a time."; Set Sharers, desc="Probable sharers of the line. More accurately, the set of processors who need to see a GetX"; } @@ -82,23 +123,70 @@ machine(Directory, "Token protocol") { bool isPresent(Address); } + external_type(MemoryControl, inport="yes", outport="yes") { + + } + + external_type(PersistentTable) { + void persistentRequestLock(Address, MachineID, AccessType); + void persistentRequestUnlock(Address, MachineID); + bool okToIssueStarving(Address, MachineID); + MachineID findSmallest(Address); + AccessType typeOfSmallest(Address); + void markEntries(Address); + bool isLocked(Address); + int countStarvingForAddress(Address); + int countReadStarvingForAddress(Address); + } + + // TBE entries for DMA requests + structure(TBE, desc="TBE entries for outstanding DMA requests") { + Address PhysicalAddress, desc="physical address"; + State TBEState, desc="Transient State"; + DataBlock DmaDataBlk, desc="DMA Data to be written. Partial blocks need to merged with system memory"; + DataBlock DataBlk, desc="The current view of system memory"; + int Len, desc="..."; + MachineID DmaRequestor, desc="DMA requestor"; + bool WentPersistent, desc="Did the DMA request require a persistent request"; + } + + external_type(TBETable) { + TBE lookup(Address); + void allocate(Address); + void deallocate(Address); + bool isPresent(Address); + } // ** OBJECTS ** - DirectoryMemory directory, constructor_hack="i"; + DirectoryMemory directory, factory='RubySystem::getDirectory(m_cfg["directory_name"])'; + + MemoryControl memBuffer, factory='RubySystem::getMemoryControl(m_cfg["memory_controller_name"])'; - PersistentTable persistentTable, constructor_hack="i"; + PersistentTable persistentTable; + TimerTable reissueTimerTable; + + TBETable TBEs, template_hack="<Directory_TBE>"; + + bool starving, default="false"; State getState(Address addr) { - return directory[addr].DirectoryState; + if (TBEs.isPresent(addr)) { + return TBEs[addr].TBEState; + } else { + return directory[addr].DirectoryState; + } } void setState(Address addr, State state) { + if (TBEs.isPresent(addr)) { + TBEs[addr].TBEState := state; + } directory[addr].DirectoryState := state; if (state == State:L) { assert(directory[addr].Tokens == 0); - } + } // We have one or zero owners assert((directory[addr].Owner.count() == 0) || (directory[addr].Owner.count() == 1)); @@ -112,19 +200,90 @@ machine(Directory, "Token protocol") { // assert(directory[addr].Tokens >= (max_tokens() / 2)); // Only mostly true; this might not always hold } } + + bool okToIssueStarving(Address addr, MachineID machinID) { + return persistentTable.okToIssueStarving(addr, machineID); + } + + void markPersistentEntries(Address addr) { + persistentTable.markEntries(addr); + } // ** OUT_PORTS ** out_port(responseNetwork_out, ResponseMsg, responseFromDir); + out_port(persistentNetwork_out, PersistentMsg, persistentFromDir); out_port(requestNetwork_out, RequestMsg, requestFromDir); + out_port(dmaResponseNetwork_out, DMAResponseMsg, dmaResponseFromDir); + + // + // Memory buffer for memory controller to DIMM communication + // + out_port(memQueue_out, MemoryMsg, memBuffer); // ** IN_PORTS ** + + // off-chip memory request/response is done + in_port(memQueue_in, MemoryMsg, memBuffer) { + if (memQueue_in.isReady()) { + peek(memQueue_in, MemoryMsg) { + if (in_msg.Type == MemoryRequestType:MEMORY_READ) { + trigger(Event:Memory_Data, in_msg.Address); + } else if (in_msg.Type == MemoryRequestType:MEMORY_WB) { + trigger(Event:Memory_Ack, in_msg.Address); + } else { + DEBUG_EXPR(in_msg.Type); + error("Invalid message"); + } + } + } + } + + // Reissue Timer + in_port(reissueTimerTable_in, Address, reissueTimerTable) { + if (reissueTimerTable_in.isReady()) { + trigger(Event:Request_Timeout, reissueTimerTable.readyAddress()); + } + } + + in_port(responseNetwork_in, ResponseMsg, responseToDir) { + if (responseNetwork_in.isReady()) { + peek(responseNetwork_in, ResponseMsg) { + assert(in_msg.Destination.isElement(machineID)); + if (directory[in_msg.Address].Tokens + in_msg.Tokens == max_tokens()) { + if ((in_msg.Type == CoherenceResponseType:DATA_OWNER) || + (in_msg.Type == CoherenceResponseType:DATA_SHARED)) { + trigger(Event:Data_All_Tokens, in_msg.Address); + } else if (in_msg.Type == CoherenceResponseType:ACK_OWNER) { + trigger(Event:Ack_Owner_All_Tokens, in_msg.Address); + } else if (in_msg.Type == CoherenceResponseType:ACK) { + trigger(Event:Ack_All_Tokens, in_msg.Address); + } else { + DEBUG_EXPR(in_msg.Type); + error("Invalid message"); + } + } else { + if (in_msg.Type == CoherenceResponseType:DATA_OWNER) { + trigger(Event:Data_Owner, in_msg.Address); + } else if ((in_msg.Type == CoherenceResponseType:ACK) || + (in_msg.Type == CoherenceResponseType:DATA_SHARED)) { + trigger(Event:Tokens, in_msg.Address); + } else if (in_msg.Type == CoherenceResponseType:ACK_OWNER) { + trigger(Event:Ack_Owner, in_msg.Address); + } else { + DEBUG_EXPR(in_msg.Type); + error("Invalid message"); + } + } + } + } + } in_port(persistentNetwork_in, PersistentMsg, persistentToDir) { if (persistentNetwork_in.isReady()) { peek(persistentNetwork_in, PersistentMsg) { assert(in_msg.Destination.isElement(machineID)); - if (distributedPersistentEnabled()) { + if (distributed_persistent) { // Apply the lockdown or unlockdown message to the table if (in_msg.Type == PersistentRequestType:GETX_PERSISTENT) { persistentTable.persistentRequestLock(in_msg.Address, in_msg.Requestor, AccessType:Write); @@ -173,19 +332,18 @@ machine(Directory, "Token protocol") { } } - in_port(responseNetwork_in, ResponseMsg, responseToDir) { - if (responseNetwork_in.isReady()) { - peek(responseNetwork_in, ResponseMsg) { - assert(in_msg.Destination.isElement(machineID)); - if (in_msg.Type == CoherenceResponseType:DATA_OWNER) { - trigger(Event:Data_Owner, in_msg.Address); - } else if ((in_msg.Type == CoherenceResponseType:ACK) || - (in_msg.Type == CoherenceResponseType:DATA_SHARED)) { - trigger(Event:Tokens, in_msg.Address); - } else if (in_msg.Type == CoherenceResponseType:ACK_OWNER) { - trigger(Event:Ack_Owner, in_msg.Address); + in_port(dmaRequestQueue_in, DMARequestMsg, dmaRequestToDir) { + if (dmaRequestQueue_in.isReady()) { + peek(dmaRequestQueue_in, DMARequestMsg) { + if (in_msg.Type == DMARequestType:READ) { + trigger(Event:DMA_READ, in_msg.LineAddress); + } else if (in_msg.Type == DMARequestType:WRITE) { + if (directory[in_msg.LineAddress].Tokens == max_tokens()) { + trigger(Event:DMA_WRITE_All_Tokens, in_msg.LineAddress); + } else { + trigger(Event:DMA_WRITE, in_msg.LineAddress); + } } else { - DEBUG_EXPR(in_msg.Type); error("Invalid message"); } } @@ -199,7 +357,7 @@ machine(Directory, "Token protocol") { if (directory[address].Tokens > 0) { peek(requestNetwork_in, RequestMsg) { // enqueue(responseNetwork_out, ResponseMsg, latency="DIRECTORY_CACHE_LATENCY") {// FIXME? - enqueue(responseNetwork_out, ResponseMsg, latency="DIRECTORY_LATENCY") {// FIXME? + enqueue(responseNetwork_out, ResponseMsg, latency=directory_latency) {// FIXME? out_msg.Address := address; out_msg.Type := CoherenceResponseType:ACK; out_msg.Sender := machineID; @@ -213,11 +371,151 @@ machine(Directory, "Token protocol") { } } + action(px_tryIssuingPersistentGETXRequest, "px", desc="...") { + if (okToIssueStarving(address, machineID) && (starving == false)) { + enqueue(persistentNetwork_out, PersistentMsg, latency = "1") { + out_msg.Address := address; + out_msg.Type := PersistentRequestType:GETX_PERSISTENT; + out_msg.Requestor := machineID; + out_msg.RequestorMachine := MachineType:Directory; + out_msg.Destination.broadcast(MachineType:L1Cache); + + // + // Currently the configuration system limits the system to only one + // chip. Therefore, if we assume one shared L2 cache, then only one + // pertinent L2 cache exist. + // + //out_msg.Destination.addNetDest(getAllPertinentL2Banks(address)); + + out_msg.Destination.add(mapAddressToRange(address, + MachineType:L2Cache, + l2_select_low_bit, + l2_select_num_bits)); + + out_msg.Destination.add(map_Address_to_Directory(address)); + out_msg.MessageSize := MessageSizeType:Persistent_Control; + out_msg.Prefetch := PrefetchBit:No; + out_msg.AccessMode := AccessModeType:SupervisorMode; + } + markPersistentEntries(address); + starving := true; + + TBEs[address].WentPersistent := true; + + // Do not schedule a wakeup, a persistent requests will always complete + } else { + + // We'd like to issue a persistent request, but are not allowed + // to issue a P.R. right now. This, we do not increment the + // IssueCount. + + // Set a wakeup timer + reissueTimerTable.set(address, 10); + } + } + + action(bw_broadcastWrite, "bw", desc="Broadcast GETX if we need tokens") { + peek(dmaRequestQueue_in, DMARequestMsg) { + // + // Assser that we only send message if we don't already have all the tokens + // + assert(directory[address].Tokens != max_tokens()); + enqueue(requestNetwork_out, RequestMsg, latency = "1") { + out_msg.Address := address; + out_msg.Type := CoherenceRequestType:GETX; + out_msg.Requestor := machineID; + out_msg.RequestorMachine := MachineType:Directory; + + // + // Since only one chip, assuming all L1 caches are local + // + out_msg.Destination.broadcast(MachineType:L1Cache); + out_msg.Destination.add(mapAddressToRange(address, + MachineType:L2Cache, + l2_select_low_bit, + l2_select_num_bits)); + + out_msg.RetryNum := 0; + out_msg.MessageSize := MessageSizeType:Request_Control; + out_msg.Prefetch := PrefetchBit:No; + out_msg.AccessMode := AccessModeType:SupervisorMode; + } + } + } + + action(ps_tryIssuingPersistentGETSRequest, "ps", desc="...") { + if (okToIssueStarving(address, machineID) && (starving == false)) { + enqueue(persistentNetwork_out, PersistentMsg, latency = "1") { + out_msg.Address := address; + out_msg.Type := PersistentRequestType:GETS_PERSISTENT; + out_msg.Requestor := machineID; + out_msg.RequestorMachine := MachineType:Directory; + out_msg.Destination.broadcast(MachineType:L1Cache); + + // + // Currently the configuration system limits the system to only one + // chip. Therefore, if we assume one shared L2 cache, then only one + // pertinent L2 cache exist. + // + //out_msg.Destination.addNetDest(getAllPertinentL2Banks(address)); + + out_msg.Destination.add(mapAddressToRange(address, + MachineType:L2Cache, + l2_select_low_bit, + l2_select_num_bits)); + + out_msg.Destination.add(map_Address_to_Directory(address)); + out_msg.MessageSize := MessageSizeType:Persistent_Control; + out_msg.Prefetch := PrefetchBit:No; + out_msg.AccessMode := AccessModeType:SupervisorMode; + } + markPersistentEntries(address); + starving := true; + + TBEs[address].WentPersistent := true; + + // Do not schedule a wakeup, a persistent requests will always complete + } else { + + // We'd like to issue a persistent request, but are not allowed + // to issue a P.R. right now. This, we do not increment the + // IssueCount. + + // Set a wakeup timer + reissueTimerTable.set(address, 10); + } + } + + action(br_broadcastRead, "br", desc="Broadcast GETS for data") { + peek(dmaRequestQueue_in, DMARequestMsg) { + enqueue(requestNetwork_out, RequestMsg, latency = "1") { + out_msg.Address := address; + out_msg.Type := CoherenceRequestType:GETS; + out_msg.Requestor := machineID; + out_msg.RequestorMachine := MachineType:Directory; + + // + // Since only one chip, assuming all L1 caches are local + // + out_msg.Destination.broadcast(MachineType:L1Cache); + out_msg.Destination.add(mapAddressToRange(address, + MachineType:L2Cache, + l2_select_low_bit, + l2_select_num_bits)); + + out_msg.RetryNum := 0; + out_msg.MessageSize := MessageSizeType:Request_Control; + out_msg.Prefetch := PrefetchBit:No; + out_msg.AccessMode := AccessModeType:SupervisorMode; + } + } + } + action(aa_sendTokensToStarver, "\a", desc="Send tokens to starver") { // Only send a message if we have tokens to send if (directory[address].Tokens > 0) { // enqueue(responseNetwork_out, ResponseMsg, latency="DIRECTORY_CACHE_LATENCY") {// FIXME? - enqueue(responseNetwork_out, ResponseMsg, latency="DIRECTORY_LATENCY") {// FIXME? + enqueue(responseNetwork_out, ResponseMsg, latency=directory_latency) {// FIXME? out_msg.Address := address; out_msg.Type := CoherenceResponseType:ACK; out_msg.Sender := machineID; @@ -230,14 +528,14 @@ machine(Directory, "Token protocol") { } } - action(d_sendDataWithAllTokens, "d", desc="Send data and tokens to requestor") { - peek(requestNetwork_in, RequestMsg) { - enqueue(responseNetwork_out, ResponseMsg, latency="MEMORY_LATENCY") { + action(d_sendMemoryDataWithAllTokens, "d", desc="Send data and tokens to requestor") { + peek(memQueue_in, MemoryMsg) { + enqueue(responseNetwork_out, ResponseMsg, latency="1") { out_msg.Address := address; out_msg.Type := CoherenceResponseType:DATA_OWNER; out_msg.Sender := machineID; out_msg.SenderMachine := MachineType:Directory; - out_msg.Destination.add(in_msg.Requestor); + out_msg.Destination.add(in_msg.OriginalRequestorMachId); assert(directory[address].Tokens > 0); out_msg.Tokens := directory[in_msg.Address].Tokens; out_msg.DataBlk := directory[in_msg.Address].DataBlk; @@ -249,21 +547,140 @@ machine(Directory, "Token protocol") { } action(dd_sendDataWithAllTokensToStarver, "\d", desc="Send data and tokens to starver") { - enqueue(responseNetwork_out, ResponseMsg, latency="MEMORY_LATENCY") { - out_msg.Address := address; - out_msg.Type := CoherenceResponseType:DATA_OWNER; - out_msg.Sender := machineID; - out_msg.SenderMachine := MachineType:Directory; - out_msg.Destination.add(persistentTable.findSmallest(address)); - assert(directory[address].Tokens > 0); - out_msg.Tokens := directory[address].Tokens; - out_msg.DataBlk := directory[address].DataBlk; - out_msg.Dirty := false; - out_msg.MessageSize := MessageSizeType:Response_Data; + peek(memQueue_in, MemoryMsg) { + enqueue(responseNetwork_out, ResponseMsg, latency="1") { + out_msg.Address := address; + out_msg.Type := CoherenceResponseType:DATA_OWNER; + out_msg.Sender := machineID; + out_msg.SenderMachine := MachineType:Directory; + out_msg.Destination.add(persistentTable.findSmallest(address)); + assert(directory[address].Tokens > 0); + out_msg.Tokens := directory[address].Tokens; + out_msg.DataBlk := directory[address].DataBlk; + out_msg.Dirty := false; + out_msg.MessageSize := MessageSizeType:Response_Data; + } } directory[address].Tokens := 0; } + action(qf_queueMemoryFetchRequest, "qf", desc="Queue off-chip fetch request") { + peek(requestNetwork_in, RequestMsg) { + enqueue(memQueue_out, MemoryMsg, latency="1") { + out_msg.Address := address; + out_msg.Type := MemoryRequestType:MEMORY_READ; + out_msg.Sender := machineID; + out_msg.OriginalRequestorMachId := in_msg.Requestor; + out_msg.MessageSize := in_msg.MessageSize; + out_msg.DataBlk := directory[address].DataBlk; + DEBUG_EXPR(out_msg); + } + } + } + + action(fd_memoryDma, "fd", desc="Queue off-chip fetch request") { + peek(dmaRequestQueue_in, DMARequestMsg) { + enqueue(memQueue_out, MemoryMsg, latency="1") { + out_msg.Address := address; + out_msg.Type := MemoryRequestType:MEMORY_READ; + out_msg.Sender := machineID; + out_msg.OriginalRequestorMachId := in_msg.Requestor; + out_msg.MessageSize := in_msg.MessageSize; + out_msg.DataBlk := directory[address].DataBlk; + DEBUG_EXPR(out_msg); + } + } + } + + action(lq_queueMemoryWbRequest, "lq", desc="Write data to memory") { + enqueue(memQueue_out, MemoryMsg, latency="1") { + out_msg.Address := address; + out_msg.Type := MemoryRequestType:MEMORY_WB; + DEBUG_EXPR(out_msg); + } + } + + action(ld_queueMemoryDmaWriteFromTbe, "ld", desc="Write DMA data to memory") { + enqueue(memQueue_out, MemoryMsg, latency="1") { + out_msg.Address := address; + out_msg.Type := MemoryRequestType:MEMORY_WB; + // first, initialize the data blk to the current version of system memory + out_msg.DataBlk := TBEs[address].DataBlk; + // then add the dma write data + out_msg.DataBlk.copyPartial(TBEs[address].DmaDataBlk, addressOffset(TBEs[address].PhysicalAddress), TBEs[address].Len); + DEBUG_EXPR(out_msg); + } + } + + action(lr_queueMemoryDmaReadWriteback, "lr", desc="Write DMA data from read to memory") { + enqueue(memQueue_out, MemoryMsg, latency="1") { + out_msg.Address := address; + out_msg.Type := MemoryRequestType:MEMORY_WB; + // first, initialize the data blk to the current version of system memory + out_msg.DataBlk := TBEs[address].DataBlk; + DEBUG_EXPR(out_msg); + } + } + + action(vd_allocateDmaRequestInTBE, "vd", desc="Record Data in TBE") { + peek(dmaRequestQueue_in, DMARequestMsg) { + TBEs.allocate(address); + TBEs[address].DmaDataBlk := in_msg.DataBlk; + TBEs[address].PhysicalAddress := in_msg.PhysicalAddress; + TBEs[address].Len := in_msg.Len; + TBEs[address].DmaRequestor := in_msg.Requestor; + TBEs[address].WentPersistent := false; + } + } + + action(s_deallocateTBE, "s", desc="Deallocate TBE") { + + if (TBEs[address].WentPersistent) { + assert(starving == true); + + enqueue(persistentNetwork_out, PersistentMsg, latency = "1") { + out_msg.Address := address; + out_msg.Type := PersistentRequestType:DEACTIVATE_PERSISTENT; + out_msg.Requestor := machineID; + out_msg.RequestorMachine := MachineType:Directory; + out_msg.Destination.broadcast(MachineType:L1Cache); + + // + // Currently the configuration system limits the system to only one + // chip. Therefore, if we assume one shared L2 cache, then only one + // pertinent L2 cache exist. + // + //out_msg.Destination.addNetDest(getAllPertinentL2Banks(address)); + + out_msg.Destination.add(mapAddressToRange(address, + MachineType:L2Cache, + l2_select_low_bit, + l2_select_num_bits)); + + out_msg.Destination.add(map_Address_to_Directory(address)); + out_msg.MessageSize := MessageSizeType:Persistent_Control; + } + starving := false; + } + + TBEs.deallocate(address); + } + + action(rd_recordDataInTbe, "rd", desc="Record data in TBE") { + peek(responseNetwork_in, ResponseMsg) { + TBEs[address].DataBlk := in_msg.DataBlk; + } + } + + action(cd_writeCleanDataToTbe, "cd", desc="Write clean memory data to TBE") { + TBEs[address].DataBlk := directory[address].DataBlk; + } + + action(dwt_writeDmaDataFromTBE, "dwt", desc="DMA Write data to memory from TBE") { + directory[address].DataBlk := TBEs[address].DataBlk; + directory[address].DataBlk.copyPartial(TBEs[address].DmaDataBlk, addressOffset(TBEs[address].PhysicalAddress), TBEs[address].Len); + } + action(f_incrementTokens, "f", desc="Increment the number of tokens we're tracking") { peek(responseNetwork_in, ResponseMsg) { assert(in_msg.Tokens >= 1); @@ -275,14 +692,34 @@ machine(Directory, "Token protocol") { requestNetwork_in.dequeue(); } + action(z_recycleRequest, "z", desc="Recycle the request queue") { + requestNetwork_in.recycle(); + } + action(k_popIncomingResponseQueue, "k", desc="Pop incoming response queue") { responseNetwork_in.dequeue(); } + action(kz_recycleResponse, "kz", desc="Recycle incoming response queue") { + responseNetwork_in.recycle(); + } + action(l_popIncomingPersistentQueue, "l", desc="Pop incoming persistent queue") { persistentNetwork_in.dequeue(); } + action(p_popDmaRequestQueue, "pd", desc="pop dma request queue") { + dmaRequestQueue_in.dequeue(); + } + + action(y_recycleDmaRequestQueue, "y", desc="recycle dma request queue") { + dmaRequestQueue_in.recycle(); + } + + action(l_popMemQueue, "q", desc="Pop off-chip request queue") { + memQueue_in.dequeue(); + } + action(m_writeDataToMemory, "m", desc="Write dirty writeback to memory") { peek(responseNetwork_in, ResponseMsg) { directory[in_msg.Address].DataBlk := in_msg.DataBlk; @@ -291,18 +728,15 @@ machine(Directory, "Token protocol") { } } - action(n_checkIncomingMsg, "n", desc="Check incoming token message") { + action(n_checkData, "n", desc="Check incoming clean data message") { peek(responseNetwork_in, ResponseMsg) { - assert(in_msg.Type == CoherenceResponseType:ACK_OWNER); - assert(in_msg.Dirty == false); - assert(in_msg.MessageSize == MessageSizeType:Writeback_Control); assert(directory[in_msg.Address].DataBlk == in_msg.DataBlk); } } action(r_bounceResponse, "r", desc="Bounce response to starving processor") { peek(responseNetwork_in, ResponseMsg) { - enqueue(responseNetwork_out, ResponseMsg, latency="NULL_LATENCY") { + enqueue(responseNetwork_out, ResponseMsg, latency="1") { out_msg.Address := address; out_msg.Type := in_msg.Type; out_msg.Sender := machineID; @@ -316,7 +750,20 @@ machine(Directory, "Token protocol") { } } - action(s_bounceDatalessOwnerToken, "s", desc="Bounce clean owner token to starving processor") { + action(st_scheduleTimeout, "st", desc="Schedule Timeout") { + // + // currently only support a fixed timeout latency + // + reissueTimerTable.set(address, fixed_timeout_latency); + } + + action(ut_unsetReissueTimer, "ut", desc="Unset reissue timer.") { + if (reissueTimerTable.isSet(address)) { + reissueTimerTable.unset(address); + } + } + + action(bd_bounceDatalessOwnerToken, "bd", desc="Bounce clean owner token to starving processor") { peek(responseNetwork_in, ResponseMsg) { assert(in_msg.Type == CoherenceResponseType:ACK_OWNER); assert(in_msg.Dirty == false); @@ -331,7 +778,7 @@ machine(Directory, "Token protocol") { // Bounce the message, but "re-associate" the data and the owner // token. In essence we're converting an ACK_OWNER message to a // DATA_OWNER message, keeping the number of tokens the same. - enqueue(responseNetwork_out, ResponseMsg, latency="NULL_LATENCY") { + enqueue(responseNetwork_out, ResponseMsg, latency="1") { out_msg.Address := address; out_msg.Type := CoherenceResponseType:DATA_OWNER; out_msg.Sender := machineID; @@ -346,53 +793,212 @@ machine(Directory, "Token protocol") { } } + action(da_sendDmaAck, "da", desc="Send Ack to DMA controller") { + enqueue(dmaResponseNetwork_out, DMAResponseMsg, latency="1") { + out_msg.PhysicalAddress := address; + out_msg.LineAddress := address; + out_msg.Type := DMAResponseType:ACK; + out_msg.Destination.add(TBEs[address].DmaRequestor); + out_msg.MessageSize := MessageSizeType:Writeback_Control; + } + } + + action(dm_sendMemoryDataToDma, "dm", desc="Send Data to DMA controller from memory") { + peek(memQueue_in, MemoryMsg) { + enqueue(dmaResponseNetwork_out, DMAResponseMsg, latency="1") { + out_msg.PhysicalAddress := address; + out_msg.LineAddress := address; + out_msg.Type := DMAResponseType:DATA; + // + // we send the entire data block and rely on the dma controller to + // split it up if need be + // + out_msg.DataBlk := in_msg.DataBlk; + out_msg.Destination.add(TBEs[address].DmaRequestor); + out_msg.MessageSize := MessageSizeType:Response_Data; + } + } + } + + action(dd_sendDmaData, "dd", desc="Send Data to DMA controller") { + peek(responseNetwork_in, ResponseMsg) { + enqueue(dmaResponseNetwork_out, DMAResponseMsg, latency="1") { + out_msg.PhysicalAddress := address; + out_msg.LineAddress := address; + out_msg.Type := DMAResponseType:DATA; + // + // we send the entire data block and rely on the dma controller to + // split it up if need be + // + out_msg.DataBlk := in_msg.DataBlk; + out_msg.Destination.add(TBEs[address].DmaRequestor); + out_msg.MessageSize := MessageSizeType:Response_Data; + } + } + } // TRANSITIONS - // Trans. from O - transition(O, GETX, NO) { - d_sendDataWithAllTokens; + // + // Trans. from base state O + // the directory has valid data + // + transition(O, GETX, NO_W) { + qf_queueMemoryFetchRequest; j_popIncomingRequestQueue; } - transition(O, GETS, NO) { - d_sendDataWithAllTokens; + transition(O, DMA_WRITE, O_DW) { + vd_allocateDmaRequestInTBE; + bw_broadcastWrite; + st_scheduleTimeout; + p_popDmaRequestQueue; + } + + transition(O, DMA_WRITE_All_Tokens, O_DW_W) { + vd_allocateDmaRequestInTBE; + cd_writeCleanDataToTbe; + dwt_writeDmaDataFromTBE; + ld_queueMemoryDmaWriteFromTbe; + p_popDmaRequestQueue; + } + + transition(O, GETS, NO_W) { + qf_queueMemoryFetchRequest; j_popIncomingRequestQueue; } - transition(O, Lockdown, L) { - dd_sendDataWithAllTokensToStarver; + transition(O, DMA_READ, O_DR_W) { + vd_allocateDmaRequestInTBE; + fd_memoryDma; + st_scheduleTimeout; + p_popDmaRequestQueue; + } + + transition(O, Lockdown, L_W) { + qf_queueMemoryFetchRequest; + l_popIncomingPersistentQueue; + } + + transition(O, {Tokens, Ack_All_Tokens}) { + f_incrementTokens; + k_popIncomingResponseQueue; + } + + transition(O, {Data_Owner, Data_All_Tokens}) { + n_checkData; + f_incrementTokens; + k_popIncomingResponseQueue; + } + + // + // transitioning to Owner, waiting for memory before DMA ack + // All other events should recycle/stall + // + transition(O_DR_W, Memory_Data, O) { + dm_sendMemoryDataToDma; + ut_unsetReissueTimer; + s_deallocateTBE; + l_popMemQueue; + } + + // + // issued GETX for DMA write, waiting for all tokens + // + transition(O_DW, Tokens) { + f_incrementTokens; + k_popIncomingResponseQueue; + } + + transition(O_DW, Data_Owner) { + f_incrementTokens; + rd_recordDataInTbe; + k_popIncomingResponseQueue; + } + + transition(O_DW, Ack_Owner) { + f_incrementTokens; + cd_writeCleanDataToTbe; + k_popIncomingResponseQueue; + } + + transition(O_DW, Lockdown, DW_L) { l_popIncomingPersistentQueue; } - transition(O, Tokens) { + transition({NO_DW, O_DW}, Data_All_Tokens, O_DW_W) { f_incrementTokens; + rd_recordDataInTbe; + dwt_writeDmaDataFromTBE; + ld_queueMemoryDmaWriteFromTbe; + ut_unsetReissueTimer; k_popIncomingResponseQueue; } + transition(O_DW, Ack_All_Tokens, O_DW_W) { + f_incrementTokens; + dwt_writeDmaDataFromTBE; + ld_queueMemoryDmaWriteFromTbe; + ut_unsetReissueTimer; + k_popIncomingResponseQueue; + } + + transition(O_DW, Ack_Owner_All_Tokens, O_DW_W) { + f_incrementTokens; + cd_writeCleanDataToTbe; + dwt_writeDmaDataFromTBE; + ld_queueMemoryDmaWriteFromTbe; + ut_unsetReissueTimer; + k_popIncomingResponseQueue; + } + + transition(O_DW_W, Memory_Ack, O) { + da_sendDmaAck; + s_deallocateTBE; + l_popMemQueue; + } + + // // Trans. from NO + // The direcotry does not have valid data, but may have some tokens + // transition(NO, GETX) { a_sendTokens; j_popIncomingRequestQueue; } + transition(NO, DMA_WRITE, NO_DW) { + vd_allocateDmaRequestInTBE; + bw_broadcastWrite; + st_scheduleTimeout; + p_popDmaRequestQueue; + } + transition(NO, GETS) { j_popIncomingRequestQueue; } + transition(NO, DMA_READ, NO_DR) { + vd_allocateDmaRequestInTBE; + br_broadcastRead; + st_scheduleTimeout; + p_popDmaRequestQueue; + } + transition(NO, Lockdown, L) { aa_sendTokensToStarver; l_popIncomingPersistentQueue; } - transition(NO, Data_Owner, O) { + transition(NO, {Data_Owner, Data_All_Tokens}, O_W) { m_writeDataToMemory; f_incrementTokens; + lq_queueMemoryWbRequest; k_popIncomingResponseQueue; } - transition(NO, Ack_Owner, O) { - n_checkIncomingMsg; + transition(NO, {Ack_Owner, Ack_Owner_All_Tokens}, O) { + n_checkData; f_incrementTokens; k_popIncomingResponseQueue; } @@ -402,34 +1008,156 @@ machine(Directory, "Token protocol") { k_popIncomingResponseQueue; } + transition(NO_W, Memory_Data, NO) { + d_sendMemoryDataWithAllTokens; + l_popMemQueue; + } + + // Trans. from NO_DW + transition(NO_DW, Request_Timeout) { + ut_unsetReissueTimer; + px_tryIssuingPersistentGETXRequest; + } + + transition(NO_DW, Lockdown, DW_L) { + aa_sendTokensToStarver; + l_popIncomingPersistentQueue; + } + + // Note: NO_DW, Data_All_Tokens transition is combined with O_DW + // Note: NO_DW should not receive the action Ack_All_Tokens because the + // directory does not have valid data + + transition(NO_DW, Data_Owner, O_DW) { + f_incrementTokens; + rd_recordDataInTbe; + lq_queueMemoryWbRequest; + k_popIncomingResponseQueue; + } + + transition({NO_DW, NO_DR}, Tokens) { + f_incrementTokens; + k_popIncomingResponseQueue; + } + + // Trans. from NO_DR + transition(NO_DR, Request_Timeout) { + ut_unsetReissueTimer; + ps_tryIssuingPersistentGETSRequest; + } + + transition(NO_DR, Lockdown, DR_L) { + aa_sendTokensToStarver; + l_popIncomingPersistentQueue; + } + + transition(NO_DR, {Data_Owner, Data_All_Tokens}, O_W) { + m_writeDataToMemory; + f_incrementTokens; + dd_sendDmaData; + lr_queueMemoryDmaReadWriteback; + ut_unsetReissueTimer; + s_deallocateTBE; + k_popIncomingResponseQueue; + } + // Trans. from L - transition(L, {GETX, GETS}) { + transition({L, DW_L, DR_L}, {GETX, GETS}) { j_popIncomingRequestQueue; } - transition(L, Lockdown) { + transition({L, DW_L, DR_L, L_W, DR_L_W}, Lockdown) { l_popIncomingPersistentQueue; } - // we could change this to write the data to memory and send it cleanly - transition(L, Data_Owner) { + // + // Received data for lockdown blocks + // For blocks with outstanding dma requests to them + // ...we could change this to write the data to memory and send it cleanly + // ...we could also proactively complete our DMA requests + // However, to keep my mind from spinning out-of-control, we won't for now :) + // + transition({DW_L, DR_L, L}, {Data_Owner, Data_All_Tokens}) { r_bounceResponse; k_popIncomingResponseQueue; } - transition(L, Tokens) { + transition({DW_L, DR_L, L}, Tokens) { r_bounceResponse; k_popIncomingResponseQueue; } - transition(L, Ack_Owner) { - s_bounceDatalessOwnerToken; + transition({DW_L, DR_L, L}, {Ack_Owner_All_Tokens, Ack_Owner}) { + bd_bounceDatalessOwnerToken; k_popIncomingResponseQueue; } - transition(L, Unlockdown, NO) { l_popIncomingPersistentQueue; } + transition(L_W, Memory_Data, L) { + dd_sendDataWithAllTokensToStarver; + l_popMemQueue; + } + + transition(DR_L_W, Memory_Data, DR_L) { + dd_sendDataWithAllTokensToStarver; + l_popMemQueue; + } + + transition(DW_L, {Unlockdown, Own_Lock_or_Unlock}, NO_DW) { + l_popIncomingPersistentQueue; + } + + transition(DR_L_W, {Unlockdown, Own_Lock_or_Unlock}, O_DR_W) { + l_popIncomingPersistentQueue; + } + + transition({DW_L, DR_L_W}, Request_Timeout) { + ut_unsetReissueTimer; + px_tryIssuingPersistentGETXRequest; + } + + transition(DR_L, {Unlockdown, Own_Lock_or_Unlock}, NO_DR) { + l_popIncomingPersistentQueue; + } + + transition(DR_L, Request_Timeout) { + ut_unsetReissueTimer; + ps_tryIssuingPersistentGETSRequest; + } + + transition(O_W, Memory_Ack, O) { + l_popMemQueue; + } + + transition({O, NO, L, O_DW, NO_DW, NO_DR}, Own_Lock_or_Unlock) { + l_popIncomingPersistentQueue; + } + + // Blocked states + transition({NO_W, O_W, L_W, DR_L_W, O_DW_W, O_DR_W, O_DW, NO_DW, NO_DR}, {GETX, GETS}) { + z_recycleRequest; + } + + transition({NO_W, O_W, L_W, DR_L_W, O_DW_W, O_DR_W, O_DW, NO_DW, NO_DR, L, DW_L, DR_L}, {DMA_READ, DMA_WRITE}) { + y_recycleDmaRequestQueue; + } + + transition({NO_W, O_W, L_W, DR_L_W, O_DW_W, O_DR_W}, {Data_Owner, Ack_Owner, Tokens}) { + kz_recycleResponse; + } + + transition({NO_W, O_W}, Lockdown, L_W) { + l_popIncomingPersistentQueue; + } + + transition(O_DR_W, Lockdown, DR_L_W) { + l_popIncomingPersistentQueue; + } + + transition({NO_W, O_W, O_DR_W}, {Unlockdown, Own_Lock_or_Unlock}) { + l_popIncomingPersistentQueue; + } } diff --git a/src/mem/protocol/MOESI_CMP_token-dma.sm b/src/mem/protocol/MOESI_CMP_token-dma.sm new file mode 100644 index 000000000..550a36ae0 --- /dev/null +++ b/src/mem/protocol/MOESI_CMP_token-dma.sm @@ -0,0 +1,165 @@ +/* + * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +machine(DMA, "DMA Controller") +: int request_latency +{ + + MessageBuffer responseFromDir, network="From", virtual_network="0", ordered="true", no_vector="true"; + MessageBuffer reqToDirectory, network="To", virtual_network="5", ordered="false", no_vector="true"; + + enumeration(State, desc="DMA states", default="DMA_State_READY") { + READY, desc="Ready to accept a new request"; + BUSY_RD, desc="Busy: currently processing a request"; + BUSY_WR, desc="Busy: currently processing a request"; + } + + enumeration(Event, desc="DMA events") { + ReadRequest, desc="A new read request"; + WriteRequest, desc="A new write request"; + Data, desc="Data from a DMA memory read"; + Ack, desc="DMA write to memory completed"; + } + + external_type(DMASequencer) { + void ackCallback(); + void dataCallback(DataBlock); + } + + MessageBuffer mandatoryQueue, ordered="false", no_vector="true"; + DMASequencer dma_sequencer, factory='RubySystem::getDMASequencer(m_cfg["dma_sequencer"])', no_vector="true"; + State cur_state, no_vector="true"; + + State getState(Address addr) { + return cur_state; + } + void setState(Address addr, State state) { + cur_state := state; + } + + out_port(reqToDirectory_out, DMARequestMsg, reqToDirectory, desc="..."); + + in_port(dmaRequestQueue_in, SequencerMsg, mandatoryQueue, desc="...") { + if (dmaRequestQueue_in.isReady()) { + peek(dmaRequestQueue_in, SequencerMsg) { + if (in_msg.Type == SequencerRequestType:LD ) { + trigger(Event:ReadRequest, in_msg.LineAddress); + } else if (in_msg.Type == SequencerRequestType:ST) { + trigger(Event:WriteRequest, in_msg.LineAddress); + } else { + error("Invalid request type"); + } + } + } + } + + in_port(dmaResponseQueue_in, DMAResponseMsg, responseFromDir, desc="...") { + if (dmaResponseQueue_in.isReady()) { + peek( dmaResponseQueue_in, DMAResponseMsg) { + if (in_msg.Type == DMAResponseType:ACK) { + trigger(Event:Ack, in_msg.LineAddress); + } else if (in_msg.Type == DMAResponseType:DATA) { + trigger(Event:Data, in_msg.LineAddress); + } else { + error("Invalid response type"); + } + } + } + } + + action(s_sendReadRequest, "s", desc="Send a DMA read request to memory") { + peek(dmaRequestQueue_in, SequencerMsg) { + enqueue(reqToDirectory_out, DMARequestMsg, latency=request_latency) { + out_msg.PhysicalAddress := in_msg.PhysicalAddress; + out_msg.LineAddress := in_msg.LineAddress; + out_msg.Type := DMARequestType:READ; + out_msg.Requestor := machineID; + out_msg.DataBlk := in_msg.DataBlk; + out_msg.Len := in_msg.Len; + out_msg.Destination.add(map_Address_to_Directory(address)); + out_msg.MessageSize := MessageSizeType:Writeback_Control; + } + } + } + + action(s_sendWriteRequest, "\s", desc="Send a DMA write request to memory") { + peek(dmaRequestQueue_in, SequencerMsg) { + enqueue(reqToDirectory_out, DMARequestMsg, latency=request_latency) { + out_msg.PhysicalAddress := in_msg.PhysicalAddress; + out_msg.LineAddress := in_msg.LineAddress; + out_msg.Type := DMARequestType:WRITE; + out_msg.Requestor := machineID; + out_msg.DataBlk := in_msg.DataBlk; + out_msg.Len := in_msg.Len; + out_msg.Destination.add(map_Address_to_Directory(address)); + out_msg.MessageSize := MessageSizeType:Writeback_Control; + } + } + } + + action(a_ackCallback, "a", desc="Notify dma controller that write request completed") { + peek (dmaResponseQueue_in, DMAResponseMsg) { + dma_sequencer.ackCallback(); + } + } + + action(d_dataCallback, "d", desc="Write data to dma sequencer") { + peek (dmaResponseQueue_in, DMAResponseMsg) { + dma_sequencer.dataCallback(in_msg.DataBlk); + } + } + + action(p_popRequestQueue, "p", desc="Pop request queue") { + dmaRequestQueue_in.dequeue(); + } + + action(p_popResponseQueue, "\p", desc="Pop request queue") { + dmaResponseQueue_in.dequeue(); + } + + transition(READY, ReadRequest, BUSY_RD) { + s_sendReadRequest; + p_popRequestQueue; + } + + transition(READY, WriteRequest, BUSY_WR) { + s_sendWriteRequest; + p_popRequestQueue; + } + + transition(BUSY_RD, Data, READY) { + d_dataCallback; + p_popResponseQueue; + } + + transition(BUSY_WR, Ack, READY) { + a_ackCallback; + p_popResponseQueue; + } +} diff --git a/src/mem/protocol/MOESI_CMP_token-msg.sm b/src/mem/protocol/MOESI_CMP_token-msg.sm index 2a75ce644..40c16b5e1 100644 --- a/src/mem/protocol/MOESI_CMP_token-msg.sm +++ b/src/mem/protocol/MOESI_CMP_token-msg.sm @@ -59,8 +59,10 @@ enumeration(CoherenceResponseType, desc="...") { // TriggerType enumeration(TriggerType, desc="...") { - REQUEST_TIMEOUT, desc="See corresponding event"; + REQUEST_TIMEOUT, desc="See corresponding event"; USE_TIMEOUT, desc="See corresponding event"; + DATA, desc="data for dma read response"; + DATA_ALL_TOKENS, desc="data and all tokens for dma write response"; } // TriggerMsg @@ -111,13 +113,45 @@ structure(ResponseMsg, desc="...", interface="NetworkMessage") { MessageSizeType MessageSize, desc="size category of the message"; } -GenericRequestType convertToGenericType(CoherenceRequestType type) { - if(type == CoherenceRequestType:GETS) { - return GenericRequestType:GETS; - } else if(type == CoherenceRequestType:GETX) { - return GenericRequestType:GETX; - } else { - DEBUG_EXPR(type); - error("invalid CoherenceRequestType"); - } +enumeration(DMARequestType, desc="...", default="DMARequestType_NULL") { + READ, desc="Memory Read"; + WRITE, desc="Memory Write"; + NULL, desc="Invalid"; } + +enumeration(DMAResponseType, desc="...", default="DMAResponseType_NULL") { + DATA, desc="DATA read"; + ACK, desc="ACK write"; + NULL, desc="Invalid"; +} + +structure(DMARequestMsg, desc="...", interface="NetworkMessage") { + DMARequestType Type, desc="Request type (read/write)"; + Address PhysicalAddress, desc="Physical address for this request"; + Address LineAddress, desc="Line address for this request"; + MachineID Requestor, desc="Node who initiated the request"; + NetDest Destination, desc="Destination"; + DataBlock DataBlk, desc="DataBlk attached to this request"; + int Len, desc="The length of the request"; + MessageSizeType MessageSize, desc="size category of the message"; +} + +structure(DMAResponseMsg, desc="...", interface="NetworkMessage") { + DMAResponseType Type, desc="Response type (DATA/ACK)"; + Address PhysicalAddress, desc="Physical address for this request"; + Address LineAddress, desc="Line address for this request"; + NetDest Destination, desc="Destination"; + DataBlock DataBlk, desc="DataBlk attached to this request"; + MessageSizeType MessageSize, desc="size category of the message"; +} + +//GenericRequestType convertToGenericType(CoherenceRequestType type) { +// if(type == CoherenceRequestType:GETS) { +// return GenericRequestType:GETS; +// } else if(type == CoherenceRequestType:GETX) { +// return GenericRequestType:GETX; +// } else { +// DEBUG_EXPR(type); +// error("invalid CoherenceRequestType"); +// } +//} diff --git a/src/mem/protocol/MOESI_CMP_token.slicc b/src/mem/protocol/MOESI_CMP_token.slicc index ae4a6d6ec..a41226f90 100644 --- a/src/mem/protocol/MOESI_CMP_token.slicc +++ b/src/mem/protocol/MOESI_CMP_token.slicc @@ -2,4 +2,5 @@ MOESI_CMP_token-msg.sm MOESI_CMP_token-L1cache.sm MOESI_CMP_token-L2cache.sm MOESI_CMP_token-dir.sm +MOESI_CMP_token-dma.sm standard_CMP-protocol.sm diff --git a/src/mem/protocol/MOESI_hammer-cache.sm b/src/mem/protocol/MOESI_hammer-cache.sm new file mode 100644 index 000000000..3b2240800 --- /dev/null +++ b/src/mem/protocol/MOESI_hammer-cache.sm @@ -0,0 +1,1132 @@ +/* + * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood + * Copyright (c) 2009 Advanced Micro Devices, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * AMD's contributions to the MOESI hammer protocol do not constitute an + * endorsement of its similarity to any AMD products. + * + * Authors: Milo Martin + * Brad Beckmann + */ + +machine(L1Cache, "AMD Hammer-like protocol") +: int cache_response_latency, + int issue_latency +{ + + // NETWORK BUFFERS + MessageBuffer requestFromCache, network="To", virtual_network="3", ordered="false"; + MessageBuffer responseFromCache, network="To", virtual_network="1", ordered="false"; + MessageBuffer unblockFromCache, network="To", virtual_network="0", ordered="false"; + + MessageBuffer forwardToCache, network="From", virtual_network="2", ordered="false"; + MessageBuffer responseToCache, network="From", virtual_network="1", ordered="false"; + + + // STATES + enumeration(State, desc="Cache states", default="L1Cache_State_I") { + // Base states + I, desc="Idle"; + S, desc="Shared"; + O, desc="Owned"; + M, desc="Modified (dirty)"; + MM, desc="Modified (dirty and locally modified)"; + + // Transient States + IM, "IM", desc="Issued GetX"; + SM, "SM", desc="Issued GetX, we still have an old copy of the line"; + OM, "OM", desc="Issued GetX, received data"; + ISM, "ISM", desc="Issued GetX, received data, waiting for all acks"; + M_W, "M^W", desc="Issued GetS, received exclusive data"; + MM_W, "MM^W", desc="Issued GetX, received exclusive data"; + IS, "IS", desc="Issued GetS"; + SS, "SS", desc="Issued GetS, received data, waiting for all acks"; + OI, "OI", desc="Issued PutO, waiting for ack"; + MI, "MI", desc="Issued PutX, waiting for ack"; + II, "II", desc="Issued PutX/O, saw Other_GETS or Other_GETX, waiting for ack"; + } + + // EVENTS + enumeration(Event, desc="Cache events") { + Load, desc="Load request from the processor"; + Ifetch, desc="I-fetch request from the processor"; + Store, desc="Store request from the processor"; + L2_Replacement, desc="L2 Replacement"; + L1_to_L2, desc="L1 to L2 transfer"; + L2_to_L1D, desc="L2 to L1-Data transfer"; + L2_to_L1I, desc="L2 to L1-Instruction transfer"; + + // Requests + Other_GETX, desc="A GetX from another processor"; + Other_GETS, desc="A GetS from another processor"; + + // Responses + Ack, desc="Received an ack message"; + Shared_Ack, desc="Received an ack message, responder has a shared copy"; + Data, desc="Received a data message"; + Shared_Data, desc="Received a data message, responder has a shared copy"; + Exclusive_Data, desc="Received a data message, responder had an exclusive copy, they gave it to us"; + + Writeback_Ack, desc="Writeback O.K. from directory"; + Writeback_Nack, desc="Writeback not O.K. from directory"; + + // Triggers + All_acks, desc="Received all required data and message acks"; + All_acks_no_sharers, desc="Received all acks and no other processor has a shared copy"; + } + + // TYPES + + // STRUCTURE DEFINITIONS + + MessageBuffer mandatoryQueue, ordered="false"; + Sequencer sequencer, factory='RubySystem::getSequencer(m_cfg["sequencer"])'; + + // CacheEntry + structure(Entry, desc="...", interface="AbstractCacheEntry") { + State CacheState, desc="cache state"; + bool Dirty, desc="Is the data dirty (different than memory)?"; + DataBlock DataBlk, desc="data for the block"; + } + + // TBE fields + structure(TBE, desc="...") { + State TBEState, desc="Transient state"; + DataBlock DataBlk, desc="data for the block, required for concurrent writebacks"; + bool Dirty, desc="Is the data dirty (different than memory)?"; + int NumPendingMsgs, desc="Number of acks/data messages that this processor is waiting for"; + bool Sharers, desc="On a GetS, did we find any other sharers in the system"; + } + + external_type(CacheMemory) { + bool cacheAvail(Address); + Address cacheProbe(Address); + void allocate(Address, Entry); + void deallocate(Address); + Entry lookup(Address); + void changePermission(Address, AccessPermission); + bool isTagPresent(Address); + void profileMiss(CacheMsg); + } + + external_type(TBETable) { + TBE lookup(Address); + void allocate(Address); + void deallocate(Address); + bool isPresent(Address); + } + + TBETable TBEs, template_hack="<L1Cache_TBE>"; + CacheMemory L1IcacheMemory, factory='RubySystem::getCache(m_cfg["icache"])'; + CacheMemory L1DcacheMemory, factory='RubySystem::getCache(m_cfg["dcache"])'; + CacheMemory L2cacheMemory, factory='RubySystem::getCache(m_cfg["l2cache"])'; + + Entry getCacheEntry(Address addr), return_by_ref="yes" { + if (L2cacheMemory.isTagPresent(addr)) { + return L2cacheMemory[addr]; + } else if (L1DcacheMemory.isTagPresent(addr)) { + return L1DcacheMemory[addr]; + } else { + return L1IcacheMemory[addr]; + } + } + + void changePermission(Address addr, AccessPermission permission) { + if (L2cacheMemory.isTagPresent(addr)) { + return L2cacheMemory.changePermission(addr, permission); + } else if (L1DcacheMemory.isTagPresent(addr)) { + return L1DcacheMemory.changePermission(addr, permission); + } else { + return L1IcacheMemory.changePermission(addr, permission); + } + } + + bool isCacheTagPresent(Address addr) { + return (L2cacheMemory.isTagPresent(addr) || L1DcacheMemory.isTagPresent(addr) || L1IcacheMemory.isTagPresent(addr)); + } + + State getState(Address addr) { + assert((L1DcacheMemory.isTagPresent(addr) && L1IcacheMemory.isTagPresent(addr)) == false); + assert((L1IcacheMemory.isTagPresent(addr) && L2cacheMemory.isTagPresent(addr)) == false); + assert((L1DcacheMemory.isTagPresent(addr) && L2cacheMemory.isTagPresent(addr)) == false); + + if(TBEs.isPresent(addr)) { + return TBEs[addr].TBEState; + } else if (isCacheTagPresent(addr)) { + return getCacheEntry(addr).CacheState; + } + return State:I; + } + + void setState(Address addr, State state) { + assert((L1DcacheMemory.isTagPresent(addr) && L1IcacheMemory.isTagPresent(addr)) == false); + assert((L1IcacheMemory.isTagPresent(addr) && L2cacheMemory.isTagPresent(addr)) == false); + assert((L1DcacheMemory.isTagPresent(addr) && L2cacheMemory.isTagPresent(addr)) == false); + + if (TBEs.isPresent(addr)) { + TBEs[addr].TBEState := state; + } + + if (isCacheTagPresent(addr)) { + getCacheEntry(addr).CacheState := state; + + // Set permission + if ((state == State:MM) || + (state == State:MM_W)) { + changePermission(addr, AccessPermission:Read_Write); + } else if (state == State:S || + state == State:O || + state == State:M || + state == State:M_W || + state == State:SM || + state == State:ISM || + state == State:OM || + state == State:SS) { + changePermission(addr, AccessPermission:Read_Only); + } else { + changePermission(addr, AccessPermission:Invalid); + } + } + } + + Event mandatory_request_type_to_event(CacheRequestType type) { + if (type == CacheRequestType:LD) { + return Event:Load; + } else if (type == CacheRequestType:IFETCH) { + return Event:Ifetch; + } else if ((type == CacheRequestType:ST) || (type == CacheRequestType:ATOMIC)) { + return Event:Store; + } else { + error("Invalid CacheRequestType"); + } + } + + MessageBuffer triggerQueue, ordered="true"; + + // ** OUT_PORTS ** + + out_port(requestNetwork_out, RequestMsg, requestFromCache); + out_port(responseNetwork_out, ResponseMsg, responseFromCache); + out_port(unblockNetwork_out, ResponseMsg, unblockFromCache); + out_port(triggerQueue_out, TriggerMsg, triggerQueue); + + // ** IN_PORTS ** + + // Trigger Queue + in_port(triggerQueue_in, TriggerMsg, triggerQueue) { + if (triggerQueue_in.isReady()) { + peek(triggerQueue_in, TriggerMsg) { + if (in_msg.Type == TriggerType:ALL_ACKS) { + trigger(Event:All_acks, in_msg.Address); + } else if (in_msg.Type == TriggerType:ALL_ACKS_NO_SHARERS) { + trigger(Event:All_acks_no_sharers, in_msg.Address); + } else { + error("Unexpected message"); + } + } + } + } + + // Nothing from the request network + + // Forward Network + in_port(forwardToCache_in, RequestMsg, forwardToCache) { + if (forwardToCache_in.isReady()) { + peek(forwardToCache_in, RequestMsg) { + if (in_msg.Type == CoherenceRequestType:GETX) { + trigger(Event:Other_GETX, in_msg.Address); + } else if (in_msg.Type == CoherenceRequestType:GETS) { + trigger(Event:Other_GETS, in_msg.Address); + } else if (in_msg.Type == CoherenceRequestType:WB_ACK) { + trigger(Event:Writeback_Ack, in_msg.Address); + } else if (in_msg.Type == CoherenceRequestType:WB_NACK) { + trigger(Event:Writeback_Nack, in_msg.Address); + } else { + error("Unexpected message"); + } + } + } + } + + // Response Network + in_port(responseToCache_in, ResponseMsg, responseToCache) { + if (responseToCache_in.isReady()) { + peek(responseToCache_in, ResponseMsg) { + if (in_msg.Type == CoherenceResponseType:ACK) { + trigger(Event:Ack, in_msg.Address); + } else if (in_msg.Type == CoherenceResponseType:ACK_SHARED) { + trigger(Event:Shared_Ack, in_msg.Address); + } else if (in_msg.Type == CoherenceResponseType:DATA) { + trigger(Event:Data, in_msg.Address); + } else if (in_msg.Type == CoherenceResponseType:DATA_SHARED) { + trigger(Event:Shared_Data, in_msg.Address); + } else if (in_msg.Type == CoherenceResponseType:DATA_EXCLUSIVE) { + trigger(Event:Exclusive_Data, in_msg.Address); + } else { + error("Unexpected message"); + } + } + } + } + + // Nothing from the unblock network + + // Mandatory Queue + in_port(mandatoryQueue_in, CacheMsg, mandatoryQueue, desc="...") { + if (mandatoryQueue_in.isReady()) { + peek(mandatoryQueue_in, CacheMsg) { + + // Check for data access to blocks in I-cache and ifetchs to blocks in D-cache + + if (in_msg.Type == CacheRequestType:IFETCH) { + // ** INSTRUCTION ACCESS *** + + // Check to see if it is in the OTHER L1 + if (L1DcacheMemory.isTagPresent(in_msg.LineAddress)) { + // The block is in the wrong L1, try to write it to the L2 + if (L2cacheMemory.cacheAvail(in_msg.LineAddress)) { + trigger(Event:L1_to_L2, in_msg.LineAddress); + } else { + trigger(Event:L2_Replacement, L2cacheMemory.cacheProbe(in_msg.LineAddress)); + } + } + + if (L1IcacheMemory.isTagPresent(in_msg.LineAddress)) { + // The tag matches for the L1, so the L1 fetches the line. We know it can't be in the L2 due to exclusion + trigger(mandatory_request_type_to_event(in_msg.Type), in_msg.LineAddress); + } else { + if (L1IcacheMemory.cacheAvail(in_msg.LineAddress)) { + // L1 does't have the line, but we have space for it in the L1 + if (L2cacheMemory.isTagPresent(in_msg.LineAddress)) { + // L2 has it (maybe not with the right permissions) + trigger(Event:L2_to_L1I, in_msg.LineAddress); + } else { + // We have room, the L2 doesn't have it, so the L1 fetches the line + trigger(mandatory_request_type_to_event(in_msg.Type), in_msg.LineAddress); + } + } else { + // No room in the L1, so we need to make room + if (L2cacheMemory.cacheAvail(L1IcacheMemory.cacheProbe(in_msg.LineAddress))) { + // The L2 has room, so we move the line from the L1 to the L2 + trigger(Event:L1_to_L2, L1IcacheMemory.cacheProbe(in_msg.LineAddress)); + } else { + // The L2 does not have room, so we replace a line from the L2 + trigger(Event:L2_Replacement, L2cacheMemory.cacheProbe(L1IcacheMemory.cacheProbe(in_msg.LineAddress))); + } + } + } + } else { + // *** DATA ACCESS *** + + // Check to see if it is in the OTHER L1 + if (L1IcacheMemory.isTagPresent(in_msg.LineAddress)) { + // The block is in the wrong L1, try to write it to the L2 + if (L2cacheMemory.cacheAvail(in_msg.LineAddress)) { + trigger(Event:L1_to_L2, in_msg.LineAddress); + } else { + trigger(Event:L2_Replacement, L2cacheMemory.cacheProbe(in_msg.LineAddress)); + } + } + + if (L1DcacheMemory.isTagPresent(in_msg.LineAddress)) { + // The tag matches for the L1, so the L1 fetches the line. We know it can't be in the L2 due to exclusion + trigger(mandatory_request_type_to_event(in_msg.Type), in_msg.LineAddress); + } else { + if (L1DcacheMemory.cacheAvail(in_msg.LineAddress)) { + // L1 does't have the line, but we have space for it in the L1 + if (L2cacheMemory.isTagPresent(in_msg.LineAddress)) { + // L2 has it (maybe not with the right permissions) + trigger(Event:L2_to_L1D, in_msg.LineAddress); + } else { + // We have room, the L2 doesn't have it, so the L1 fetches the line + trigger(mandatory_request_type_to_event(in_msg.Type), in_msg.LineAddress); + } + } else { + // No room in the L1, so we need to make room + if (L2cacheMemory.cacheAvail(L1DcacheMemory.cacheProbe(in_msg.LineAddress))) { + // The L2 has room, so we move the line from the L1 to the L2 + trigger(Event:L1_to_L2, L1DcacheMemory.cacheProbe(in_msg.LineAddress)); + } else { + // The L2 does not have room, so we replace a line from the L2 + trigger(Event:L2_Replacement, L2cacheMemory.cacheProbe(L1DcacheMemory.cacheProbe(in_msg.LineAddress))); + } + } + } + } + } + } + } + + // ACTIONS + + action(a_issueGETS, "a", desc="Issue GETS") { + enqueue(requestNetwork_out, RequestMsg, latency=issue_latency) { + out_msg.Address := address; + out_msg.Type := CoherenceRequestType:GETS; + out_msg.Requestor := machineID; + out_msg.Destination.add(map_Address_to_Directory(address)); + out_msg.MessageSize := MessageSizeType:Request_Control; + TBEs[address].NumPendingMsgs := getNumberOfLastLevelCaches(); // One from each other cache (n-1) plus the memory (+1) + } + } + + action(b_issueGETX, "b", desc="Issue GETX") { + enqueue(requestNetwork_out, RequestMsg, latency=issue_latency) { + out_msg.Address := address; + out_msg.Type := CoherenceRequestType:GETX; + out_msg.Requestor := machineID; + out_msg.Destination.add(map_Address_to_Directory(address)); + out_msg.MessageSize := MessageSizeType:Request_Control; + TBEs[address].NumPendingMsgs := getNumberOfLastLevelCaches(); // One from each other cache (n-1) plus the memory (+1) + } + } + + action(c_sendExclusiveData, "c", desc="Send exclusive data from cache to requestor") { + peek(forwardToCache_in, RequestMsg) { + enqueue(responseNetwork_out, ResponseMsg, latency=cache_response_latency) { + out_msg.Address := address; + out_msg.Type := CoherenceResponseType:DATA_EXCLUSIVE; + out_msg.Sender := machineID; + out_msg.Destination.add(in_msg.Requestor); + out_msg.DataBlk := getCacheEntry(address).DataBlk; + out_msg.Dirty := getCacheEntry(address).Dirty; + out_msg.Acks := 2; + out_msg.MessageSize := MessageSizeType:Response_Data; + } + } + } + + action(d_issuePUT, "d", desc="Issue PUT") { + enqueue(requestNetwork_out, RequestMsg, latency=issue_latency) { + out_msg.Address := address; + out_msg.Type := CoherenceRequestType:PUT; + out_msg.Requestor := machineID; + out_msg.Destination.add(map_Address_to_Directory(address)); + out_msg.MessageSize := MessageSizeType:Writeback_Control; + } + } + + action(e_sendData, "e", desc="Send data from cache to requestor") { + peek(forwardToCache_in, RequestMsg) { + enqueue(responseNetwork_out, ResponseMsg, latency=cache_response_latency) { + out_msg.Address := address; + out_msg.Type := CoherenceResponseType:DATA; + out_msg.Sender := machineID; + out_msg.Destination.add(in_msg.Requestor); + out_msg.DataBlk := getCacheEntry(address).DataBlk; + out_msg.Dirty := getCacheEntry(address).Dirty; + out_msg.Acks := 2; + out_msg.MessageSize := MessageSizeType:Response_Data; + } + } + } + + action(ee_sendDataShared, "\e", desc="Send data from cache to requestor, keep a shared copy") { + peek(forwardToCache_in, RequestMsg) { + enqueue(responseNetwork_out, ResponseMsg, latency=cache_response_latency) { + out_msg.Address := address; + out_msg.Type := CoherenceResponseType:DATA_SHARED; + out_msg.Sender := machineID; + out_msg.Destination.add(in_msg.Requestor); + out_msg.DataBlk := getCacheEntry(address).DataBlk; + out_msg.Dirty := getCacheEntry(address).Dirty; + out_msg.Acks := 2; + out_msg.MessageSize := MessageSizeType:Response_Data; + } + } + } + + action(f_sendAck, "f", desc="Send ack from cache to requestor") { + peek(forwardToCache_in, RequestMsg) { + enqueue(responseNetwork_out, ResponseMsg, latency=cache_response_latency) { + out_msg.Address := address; + out_msg.Type := CoherenceResponseType:ACK; + out_msg.Sender := machineID; + out_msg.Destination.add(in_msg.Requestor); + out_msg.Acks := 1; + out_msg.MessageSize := MessageSizeType:Response_Control; + } + } + } + + action(ff_sendAckShared, "\f", desc="Send shared ack from cache to requestor") { + peek(forwardToCache_in, RequestMsg) { + enqueue(responseNetwork_out, ResponseMsg, latency=cache_response_latency) { + out_msg.Address := address; + out_msg.Type := CoherenceResponseType:ACK_SHARED; + out_msg.Sender := machineID; + out_msg.Destination.add(in_msg.Requestor); + out_msg.Acks := 1; + out_msg.MessageSize := MessageSizeType:Response_Control; + } + } + } + + action(g_sendUnblock, "g", desc="Send unblock to memory") { + enqueue(unblockNetwork_out, ResponseMsg, latency=cache_response_latency) { + out_msg.Address := address; + out_msg.Type := CoherenceResponseType:UNBLOCK; + out_msg.Sender := machineID; + out_msg.Destination.add(map_Address_to_Directory(address)); + out_msg.MessageSize := MessageSizeType:Unblock_Control; + } + } + + action(h_load_hit, "h", desc="Notify sequencer the load completed.") { + DEBUG_EXPR(getCacheEntry(address).DataBlk); + sequencer.readCallback(address, getCacheEntry(address).DataBlk); + } + + action(hh_store_hit, "\h", desc="Notify sequencer that store completed.") { + DEBUG_EXPR(getCacheEntry(address).DataBlk); + sequencer.writeCallback(address, getCacheEntry(address).DataBlk); + getCacheEntry(address).Dirty := true; + } + + action(i_allocateTBE, "i", desc="Allocate TBE") { + check_allocate(TBEs); + TBEs.allocate(address); + TBEs[address].DataBlk := getCacheEntry(address).DataBlk; // Data only used for writebacks + TBEs[address].Dirty := getCacheEntry(address).Dirty; + TBEs[address].Sharers := false; + } + + action(j_popTriggerQueue, "j", desc="Pop trigger queue.") { + triggerQueue_in.dequeue(); + } + + action(k_popMandatoryQueue, "k", desc="Pop mandatory queue.") { + mandatoryQueue_in.dequeue(); + } + + action(l_popForwardQueue, "l", desc="Pop forwareded request queue.") { + forwardToCache_in.dequeue(); + } + + action(m_decrementNumberOfMessages, "m", desc="Decrement the number of messages for which we're waiting") { + peek(responseToCache_in, ResponseMsg) { + assert(in_msg.Acks > 0); + DEBUG_EXPR(TBEs[address].NumPendingMsgs); + TBEs[address].NumPendingMsgs := TBEs[address].NumPendingMsgs - in_msg.Acks; + DEBUG_EXPR(TBEs[address].NumPendingMsgs); + } + } + + action(n_popResponseQueue, "n", desc="Pop response queue") { + responseToCache_in.dequeue(); + } + + action(o_checkForCompletion, "o", desc="Check if we have received all the messages required for completion") { + if (TBEs[address].NumPendingMsgs == 0) { + enqueue(triggerQueue_out, TriggerMsg) { + out_msg.Address := address; + if (TBEs[address].Sharers) { + out_msg.Type := TriggerType:ALL_ACKS; + } else { + out_msg.Type := TriggerType:ALL_ACKS_NO_SHARERS; + } + } + } + } + + action(p_decrementNumberOfMessagesByOne, "p", desc="Decrement the number of messages for which we're waiting by one") { + TBEs[address].NumPendingMsgs := TBEs[address].NumPendingMsgs - 1; + } + + action(pp_incrementNumberOfMessagesByOne, "\p", desc="Increment the number of messages for which we're waiting by one") { + TBEs[address].NumPendingMsgs := TBEs[address].NumPendingMsgs + 1; + } + + action(q_sendDataFromTBEToCache, "q", desc="Send data from TBE to cache") { + peek(forwardToCache_in, RequestMsg) { + enqueue(responseNetwork_out, ResponseMsg, latency=cache_response_latency) { + out_msg.Address := address; + out_msg.Type := CoherenceResponseType:DATA; + out_msg.Sender := machineID; + out_msg.Destination.add(in_msg.Requestor); + out_msg.DataBlk := TBEs[address].DataBlk; + out_msg.Dirty := TBEs[address].Dirty; + out_msg.Acks := 2; + out_msg.MessageSize := MessageSizeType:Response_Data; + } + } + } + + action(qq_sendDataFromTBEToMemory, "\q", desc="Send data from TBE to memory") { + enqueue(unblockNetwork_out, ResponseMsg, latency=cache_response_latency) { + out_msg.Address := address; + out_msg.Sender := machineID; + out_msg.Destination.add(map_Address_to_Directory(address)); + out_msg.Dirty := TBEs[address].Dirty; + if (TBEs[address].Dirty) { + out_msg.Type := CoherenceResponseType:WB_DIRTY; + out_msg.DataBlk := TBEs[address].DataBlk; + out_msg.MessageSize := MessageSizeType:Writeback_Data; + } else { + out_msg.Type := CoherenceResponseType:WB_CLEAN; + // NOTE: in a real system this would not send data. We send + // data here only so we can check it at the memory + out_msg.DataBlk := TBEs[address].DataBlk; + out_msg.MessageSize := MessageSizeType:Writeback_Control; + } + } + } + + action(r_setSharerBit, "r", desc="We saw other sharers") { + TBEs[address].Sharers := true; + } + + action(s_deallocateTBE, "s", desc="Deallocate TBE") { + TBEs.deallocate(address); + } + + action(t_sendExclusiveDataFromTBEToMemory, "t", desc="Send exclusive data from TBE to memory") { + enqueue(unblockNetwork_out, ResponseMsg, latency=cache_response_latency) { + out_msg.Address := address; + out_msg.Sender := machineID; + out_msg.Destination.add(map_Address_to_Directory(address)); + out_msg.DataBlk := TBEs[address].DataBlk; + out_msg.Dirty := TBEs[address].Dirty; + if (TBEs[address].Dirty) { + out_msg.Type := CoherenceResponseType:WB_EXCLUSIVE_DIRTY; + out_msg.DataBlk := TBEs[address].DataBlk; + out_msg.MessageSize := MessageSizeType:Writeback_Data; + } else { + out_msg.Type := CoherenceResponseType:WB_EXCLUSIVE_CLEAN; + // NOTE: in a real system this would not send data. We send + // data here only so we can check it at the memory + out_msg.DataBlk := TBEs[address].DataBlk; + out_msg.MessageSize := MessageSizeType:Writeback_Control; + } + } + } + + action(u_writeDataToCache, "u", desc="Write data to cache") { + peek(responseToCache_in, ResponseMsg) { + getCacheEntry(address).DataBlk := in_msg.DataBlk; + getCacheEntry(address).Dirty := in_msg.Dirty; + } + } + + action(v_writeDataToCacheVerify, "v", desc="Write data to cache, assert it was same as before") { + peek(responseToCache_in, ResponseMsg) { + assert(getCacheEntry(address).DataBlk == in_msg.DataBlk); + getCacheEntry(address).DataBlk := in_msg.DataBlk; + getCacheEntry(address).Dirty := in_msg.Dirty; + } + } + + action(gg_deallocateL1CacheBlock, "\g", desc="Deallocate cache block. Sets the cache to invalid, allowing a replacement in parallel with a fetch.") { + if (L1DcacheMemory.isTagPresent(address)) { + L1DcacheMemory.deallocate(address); + } else { + L1IcacheMemory.deallocate(address); + } + } + + action(ii_allocateL1DCacheBlock, "\i", desc="Set L1 D-cache tag equal to tag of block B.") { + if (L1DcacheMemory.isTagPresent(address) == false) { + L1DcacheMemory.allocate(address, new Entry); + } + } + + action(jj_allocateL1ICacheBlock, "\j", desc="Set L1 I-cache tag equal to tag of block B.") { + if (L1IcacheMemory.isTagPresent(address) == false) { + L1IcacheMemory.allocate(address, new Entry); + } + } + + action(vv_allocateL2CacheBlock, "\v", desc="Set L2 cache tag equal to tag of block B.") { + L2cacheMemory.allocate(address, new Entry); + } + + action(rr_deallocateL2CacheBlock, "\r", desc="Deallocate L2 cache block. Sets the cache to not present, allowing a replacement in parallel with a fetch.") { + L2cacheMemory.deallocate(address); + } + + action(ss_copyFromL1toL2, "\s", desc="Copy data block from L1 (I or D) to L2") { + if (L1DcacheMemory.isTagPresent(address)) { + L2cacheMemory[address] := L1DcacheMemory[address]; + } else { + L2cacheMemory[address] := L1IcacheMemory[address]; + } + } + + action(tt_copyFromL2toL1, "\t", desc="Copy data block from L2 to L1 (I or D)") { + if (L1DcacheMemory.isTagPresent(address)) { + L1DcacheMemory[address] := L2cacheMemory[address]; + } else { + L1IcacheMemory[address] := L2cacheMemory[address]; + } + } + + action(uu_profileMiss, "\u", desc="Profile the demand miss") { + peek(mandatoryQueue_in, CacheMsg) { + if (L1IcacheMemory.isTagPresent(address)) { + L1IcacheMemory.profileMiss(in_msg); + } else if (L1DcacheMemory.isTagPresent(address)) { + L1DcacheMemory.profileMiss(in_msg); + } else { + L2cacheMemory.profileMiss(in_msg); + } + } + } + + action(zz_recycleMandatoryQueue, "\z", desc="Send the head of the mandatory queue to the back of the queue.") { + mandatoryQueue_in.recycle(); + } + + //***************************************************** + // TRANSITIONS + //***************************************************** + + // Transitions for Load/Store/L2_Replacement from transient states + transition({IM, SM, ISM, OM, IS, SS, OI, MI, II}, {Store, L2_Replacement}) { + zz_recycleMandatoryQueue; + } + + transition({M_W, MM_W}, {L2_Replacement}) { + zz_recycleMandatoryQueue; + } + + transition({IM, IS, OI, MI, II}, {Load, Ifetch}) { + zz_recycleMandatoryQueue; + } + + transition({IM, SM, ISM, OM, IS, SS, MM_W, M_W, OI, MI, II}, L1_to_L2) { + zz_recycleMandatoryQueue; + } + + // Transitions moving data between the L1 and L2 caches + transition({I, S, O, M, MM}, L1_to_L2) { + vv_allocateL2CacheBlock; + ss_copyFromL1toL2; // Not really needed for state I + gg_deallocateL1CacheBlock; + } + + transition({I, S, O, M, MM}, L2_to_L1D) { + ii_allocateL1DCacheBlock; + tt_copyFromL2toL1; // Not really needed for state I + rr_deallocateL2CacheBlock; + } + + transition({I, S, O, M, MM}, L2_to_L1I) { + jj_allocateL1ICacheBlock; + tt_copyFromL2toL1; // Not really needed for state I + rr_deallocateL2CacheBlock; + } + + // Transitions from Idle + transition(I, Load, IS) { + ii_allocateL1DCacheBlock; + i_allocateTBE; + a_issueGETS; + uu_profileMiss; + k_popMandatoryQueue; + } + + transition(I, Ifetch, IS) { + jj_allocateL1ICacheBlock; + i_allocateTBE; + a_issueGETS; + uu_profileMiss; + k_popMandatoryQueue; + } + + transition(I, Store, IM) { + ii_allocateL1DCacheBlock; + i_allocateTBE; + b_issueGETX; + uu_profileMiss; + k_popMandatoryQueue; + } + + transition(I, L2_Replacement) { + rr_deallocateL2CacheBlock; + } + + transition(I, {Other_GETX, Other_GETS}) { + f_sendAck; + l_popForwardQueue; + } + + // Transitions from Shared + transition({S, SM, ISM}, {Load, Ifetch}) { + h_load_hit; + k_popMandatoryQueue; + } + + transition(S, Store, SM) { + i_allocateTBE; + b_issueGETX; + uu_profileMiss; + k_popMandatoryQueue; + } + + transition(S, L2_Replacement, I) { + rr_deallocateL2CacheBlock; + } + + transition(S, Other_GETX, I) { + f_sendAck; + l_popForwardQueue; + } + + transition(S, Other_GETS) { + ff_sendAckShared; + l_popForwardQueue; + } + + // Transitions from Owned + transition({O, OM, SS, MM_W, M_W}, {Load, Ifetch}) { + h_load_hit; + k_popMandatoryQueue; + } + + transition(O, Store, OM) { + i_allocateTBE; + b_issueGETX; + p_decrementNumberOfMessagesByOne; + uu_profileMiss; + k_popMandatoryQueue; + } + + transition(O, L2_Replacement, OI) { + i_allocateTBE; + d_issuePUT; + rr_deallocateL2CacheBlock; + } + + transition(O, Other_GETX, I) { + e_sendData; + l_popForwardQueue; + } + + transition(O, Other_GETS) { + ee_sendDataShared; + l_popForwardQueue; + } + + // Transitions from Modified + transition(MM, {Load, Ifetch}) { + h_load_hit; + k_popMandatoryQueue; + } + + transition(MM, Store) { + hh_store_hit; + k_popMandatoryQueue; + } + + transition(MM, L2_Replacement, MI) { + i_allocateTBE; + d_issuePUT; + rr_deallocateL2CacheBlock; + } + + transition(MM, Other_GETX, I) { + c_sendExclusiveData; + l_popForwardQueue; + } + + transition(MM, Other_GETS, I) { + c_sendExclusiveData; + l_popForwardQueue; + } + + // Transitions from Dirty Exclusive + transition(M, {Load, Ifetch}) { + h_load_hit; + k_popMandatoryQueue; + } + + transition(M, Store, MM) { + hh_store_hit; + k_popMandatoryQueue; + } + + transition(M, L2_Replacement, MI) { + i_allocateTBE; + d_issuePUT; + rr_deallocateL2CacheBlock; + } + + transition(M, Other_GETX, I) { + c_sendExclusiveData; + l_popForwardQueue; + } + + transition(M, Other_GETS, O) { + ee_sendDataShared; + l_popForwardQueue; + } + + // Transitions from IM + + transition(IM, {Other_GETX, Other_GETS}) { + f_sendAck; + l_popForwardQueue; + } + + transition(IM, Ack) { + m_decrementNumberOfMessages; + o_checkForCompletion; + n_popResponseQueue; + } + + transition(IM, Data, ISM) { + u_writeDataToCache; + m_decrementNumberOfMessages; + o_checkForCompletion; + n_popResponseQueue; + } + + transition(IM, Exclusive_Data, MM_W) { + u_writeDataToCache; + m_decrementNumberOfMessages; + o_checkForCompletion; + hh_store_hit; + n_popResponseQueue; + } + + // Transitions from SM + transition(SM, Other_GETS) { + ff_sendAckShared; + l_popForwardQueue; + } + + transition(SM, Other_GETX, IM) { + f_sendAck; + l_popForwardQueue; + } + + transition(SM, Ack) { + m_decrementNumberOfMessages; + o_checkForCompletion; + n_popResponseQueue; + } + + transition(SM, Data, ISM) { + v_writeDataToCacheVerify; + m_decrementNumberOfMessages; + o_checkForCompletion; + n_popResponseQueue; + } + + // Transitions from ISM + transition(ISM, Ack) { + m_decrementNumberOfMessages; + o_checkForCompletion; + n_popResponseQueue; + } + + transition(ISM, All_acks_no_sharers, MM) { + hh_store_hit; + g_sendUnblock; + s_deallocateTBE; + j_popTriggerQueue; + } + + // Transitions from OM + + transition(OM, Other_GETX, IM) { + e_sendData; + pp_incrementNumberOfMessagesByOne; + l_popForwardQueue; + } + + transition(OM, Other_GETS) { + ee_sendDataShared; + l_popForwardQueue; + } + + transition(OM, Ack) { + m_decrementNumberOfMessages; + o_checkForCompletion; + n_popResponseQueue; + } + + transition(OM, {All_acks, All_acks_no_sharers}, MM) { + hh_store_hit; + g_sendUnblock; + s_deallocateTBE; + j_popTriggerQueue; + } + + // Transitions from IS + + transition(IS, {Other_GETX, Other_GETS}) { + f_sendAck; + l_popForwardQueue; + } + + transition(IS, Ack) { + m_decrementNumberOfMessages; + o_checkForCompletion; + n_popResponseQueue; + } + + transition(IS, Shared_Ack) { + m_decrementNumberOfMessages; + r_setSharerBit; + o_checkForCompletion; + n_popResponseQueue; + } + + transition(IS, Data, SS) { + u_writeDataToCache; + m_decrementNumberOfMessages; + o_checkForCompletion; + h_load_hit; + n_popResponseQueue; + } + + transition(IS, Exclusive_Data, M_W) { + u_writeDataToCache; + m_decrementNumberOfMessages; + o_checkForCompletion; + h_load_hit; + n_popResponseQueue; + } + + transition(IS, Shared_Data, SS) { + u_writeDataToCache; + r_setSharerBit; + m_decrementNumberOfMessages; + o_checkForCompletion; + h_load_hit; + n_popResponseQueue; + } + + // Transitions from SS + + transition(SS, Ack) { + m_decrementNumberOfMessages; + o_checkForCompletion; + n_popResponseQueue; + } + + transition(SS, Shared_Ack) { + m_decrementNumberOfMessages; + r_setSharerBit; + o_checkForCompletion; + n_popResponseQueue; + } + + transition(SS, All_acks, S) { + g_sendUnblock; + s_deallocateTBE; + j_popTriggerQueue; + } + + transition(SS, All_acks_no_sharers, S) { + // Note: The directory might still be the owner, so that is why we go to S + g_sendUnblock; + s_deallocateTBE; + j_popTriggerQueue; + } + + // Transitions from MM_W + + transition(MM_W, Store) { + hh_store_hit; + k_popMandatoryQueue; + } + + transition(MM_W, Ack) { + m_decrementNumberOfMessages; + o_checkForCompletion; + n_popResponseQueue; + } + + transition(MM_W, All_acks_no_sharers, MM) { + g_sendUnblock; + s_deallocateTBE; + j_popTriggerQueue; + } + + // Transitions from M_W + + transition(M_W, Store, MM_W) { + hh_store_hit; + k_popMandatoryQueue; + } + + transition(M_W, Ack) { + m_decrementNumberOfMessages; + o_checkForCompletion; + n_popResponseQueue; + } + + transition(M_W, All_acks_no_sharers, M) { + g_sendUnblock; + s_deallocateTBE; + j_popTriggerQueue; + } + + // Transitions from OI/MI + + transition({OI, MI}, Other_GETX, II) { + q_sendDataFromTBEToCache; + l_popForwardQueue; + } + + transition({OI, MI}, Other_GETS, OI) { + q_sendDataFromTBEToCache; + l_popForwardQueue; + } + + transition(MI, Writeback_Ack, I) { + t_sendExclusiveDataFromTBEToMemory; + s_deallocateTBE; + l_popForwardQueue; + } + + transition(OI, Writeback_Ack, I) { + qq_sendDataFromTBEToMemory; + s_deallocateTBE; + l_popForwardQueue; + } + + // Transitions from II + transition(II, {Other_GETS, Other_GETX}, II) { + f_sendAck; + l_popForwardQueue; + } + + transition(II, Writeback_Ack, I) { + g_sendUnblock; + s_deallocateTBE; + l_popForwardQueue; + } + + transition(II, Writeback_Nack, I) { + s_deallocateTBE; + l_popForwardQueue; + } +} + diff --git a/src/mem/protocol/MOESI_hammer-dir.sm b/src/mem/protocol/MOESI_hammer-dir.sm new file mode 100644 index 000000000..b9b001e40 --- /dev/null +++ b/src/mem/protocol/MOESI_hammer-dir.sm @@ -0,0 +1,920 @@ +/* + * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood + * Copyright (c) 2009 Advanced Micro Devices, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * AMD's contributions to the MOESI hammer protocol do not constitute an + * endorsement of its similarity to any AMD products. + * + * Authors: Milo Martin + * Brad Beckmann + */ + +machine(Directory, "AMD Hammer-like protocol") +: int memory_controller_latency +{ + + MessageBuffer forwardFromDir, network="To", virtual_network="2", ordered="false"; + MessageBuffer responseFromDir, network="To", virtual_network="1", ordered="false"; + // + // For a finite buffered network, note that the DMA response network only + // works at this relatively higher numbered (lower priority) virtual network + // because the trigger queue decouples cache responses from DMA responses. + // + MessageBuffer dmaResponseFromDir, network="To", virtual_network="4", ordered="true"; + + MessageBuffer unblockToDir, network="From", virtual_network="0", ordered="false"; + MessageBuffer responseToDir, network="From", virtual_network="1", ordered="false"; + MessageBuffer requestToDir, network="From", virtual_network="3", ordered="false"; + MessageBuffer dmaRequestToDir, network="From", virtual_network="5", ordered="true"; + + // STATES + enumeration(State, desc="Directory states", default="Directory_State_E") { + // Base states + NO, desc="Not Owner"; + O, desc="Owner"; + E, desc="Exclusive Owner (we can provide the data in exclusive)"; + NO_B, "NO^B", desc="Not Owner, Blocked"; + O_B, "O^B", desc="Owner, Blocked"; + NO_B_W, desc="Not Owner, Blocked, waiting for Dram"; + O_B_W, desc="Owner, Blocked, waiting for Dram"; + NO_W, desc="Not Owner, waiting for Dram"; + O_W, desc="Owner, waiting for Dram"; + NO_DW_B_W, desc="Not Owner, Dma Write waiting for Dram and cache responses"; + NO_DR_B_W, desc="Not Owner, Dma Read waiting for Dram and cache responses"; + NO_DR_B_D, desc="Not Owner, Dma Read waiting for cache responses including dirty data"; + NO_DR_B, desc="Not Owner, Dma Read waiting for cache responses"; + NO_DW_W, desc="Not Owner, Dma Write waiting for Dram"; + O_DR_B_W, desc="Owner, Dma Read waiting for Dram and cache responses"; + O_DR_B, desc="Owner, Dma Read waiting for cache responses"; + WB, desc="Blocked on a writeback"; + WB_O_W, desc="Blocked on memory write, will go to O"; + WB_E_W, desc="Blocked on memory write, will go to E"; + } + + // Events + enumeration(Event, desc="Directory events") { + GETX, desc="A GETX arrives"; + GETS, desc="A GETS arrives"; + PUT, desc="A PUT arrives"; + Unblock, desc="An unblock message arrives"; + Writeback_Clean, desc="The final part of a PutX (no data)"; + Writeback_Dirty, desc="The final part of a PutX (data)"; + Writeback_Exclusive_Clean, desc="The final part of a PutX (no data, exclusive)"; + Writeback_Exclusive_Dirty, desc="The final part of a PutX (data, exclusive)"; + + // DMA requests + DMA_READ, desc="A DMA Read memory request"; + DMA_WRITE, desc="A DMA Write memory request"; + + // Memory Controller + Memory_Data, desc="Fetched data from memory arrives"; + Memory_Ack, desc="Writeback Ack from memory arrives"; + + // Cache responses required to handle DMA + Ack, desc="Received an ack message"; + Shared_Ack, desc="Received an ack message, responder has a shared copy"; + Shared_Data, desc="Received a data message, responder has a shared copy"; + Exclusive_Data, desc="Received a data message, responder had an exclusive copy, they gave it to us"; + + // Triggers + All_acks_and_data, desc="Received all required data and message acks"; + All_acks_and_data_no_sharers, desc="Received all acks and no other processor has a shared copy"; + } + + // TYPES + + // DirectoryEntry + structure(Entry, desc="...") { + State DirectoryState, desc="Directory state"; + DataBlock DataBlk, desc="data for the block"; + } + + external_type(DirectoryMemory) { + Entry lookup(Address); + bool isPresent(Address); + } + + external_type(MemoryControl, inport="yes", outport="yes") { + + } + + // TBE entries for DMA requests + structure(TBE, desc="TBE entries for outstanding DMA requests") { + Address PhysicalAddress, desc="physical address"; + State TBEState, desc="Transient State"; + CoherenceResponseType ResponseType, desc="The type for the subsequent response message"; + DataBlock DmaDataBlk, desc="DMA Data to be written. Partial blocks need to merged with system memory"; + DataBlock DataBlk, desc="The current view of system memory"; + int Len, desc="..."; + MachineID DmaRequestor, desc="DMA requestor"; + int NumPendingMsgs, desc="Number of pending acks/messages"; + bool CacheDirty, desc="Indicates whether a cache has responded with dirty data"; + bool Sharers, desc="Indicates whether a cache has indicated it is currently a sharer"; + } + + external_type(TBETable) { + TBE lookup(Address); + void allocate(Address); + void deallocate(Address); + bool isPresent(Address); + } + + // ** OBJECTS ** + + DirectoryMemory directory, factory='RubySystem::getDirectory(m_cfg["directory_name"])'; + + MemoryControl memBuffer, factory='RubySystem::getMemoryControl(m_cfg["memory_controller_name"])'; + + TBETable TBEs, template_hack="<Directory_TBE>"; + + State getState(Address addr) { + if (TBEs.isPresent(addr)) { + return TBEs[addr].TBEState; + } else { + return directory[addr].DirectoryState; + } + } + + void setState(Address addr, State state) { + if (TBEs.isPresent(addr)) { + TBEs[addr].TBEState := state; + } + directory[addr].DirectoryState := state; + } + + MessageBuffer triggerQueue, ordered="true"; + + // ** OUT_PORTS ** + out_port(requestQueue_out, ResponseMsg, requestToDir); // For recycling requests + out_port(forwardNetwork_out, RequestMsg, forwardFromDir); + out_port(responseNetwork_out, ResponseMsg, responseFromDir); + out_port(dmaResponseNetwork_out, DMAResponseMsg, dmaResponseFromDir); + out_port(triggerQueue_out, TriggerMsg, triggerQueue); + + // + // Memory buffer for memory controller to DIMM communication + // + out_port(memQueue_out, MemoryMsg, memBuffer); + + // ** IN_PORTS ** + + // Trigger Queue + in_port(triggerQueue_in, TriggerMsg, triggerQueue) { + if (triggerQueue_in.isReady()) { + peek(triggerQueue_in, TriggerMsg) { + if (in_msg.Type == TriggerType:ALL_ACKS) { + trigger(Event:All_acks_and_data, in_msg.Address); + } else if (in_msg.Type == TriggerType:ALL_ACKS_NO_SHARERS) { + trigger(Event:All_acks_and_data_no_sharers, in_msg.Address); + } else { + error("Unexpected message"); + } + } + } + } + + in_port(unblockNetwork_in, ResponseMsg, unblockToDir) { + if (unblockNetwork_in.isReady()) { + peek(unblockNetwork_in, ResponseMsg) { + if (in_msg.Type == CoherenceResponseType:UNBLOCK) { + trigger(Event:Unblock, in_msg.Address); + } else if (in_msg.Type == CoherenceResponseType:WB_CLEAN) { + trigger(Event:Writeback_Clean, in_msg.Address); + } else if (in_msg.Type == CoherenceResponseType:WB_DIRTY) { + trigger(Event:Writeback_Dirty, in_msg.Address); + } else if (in_msg.Type == CoherenceResponseType:WB_EXCLUSIVE_CLEAN) { + trigger(Event:Writeback_Exclusive_Clean, in_msg.Address); + } else if (in_msg.Type == CoherenceResponseType:WB_EXCLUSIVE_DIRTY) { + trigger(Event:Writeback_Exclusive_Dirty, in_msg.Address); + } else { + error("Invalid message"); + } + } + } + } + + // Response Network + in_port(responseToDir_in, ResponseMsg, responseToDir) { + if (responseToDir_in.isReady()) { + peek(responseToDir_in, ResponseMsg) { + if (in_msg.Type == CoherenceResponseType:ACK) { + trigger(Event:Ack, in_msg.Address); + } else if (in_msg.Type == CoherenceResponseType:ACK_SHARED) { + trigger(Event:Shared_Ack, in_msg.Address); + } else if (in_msg.Type == CoherenceResponseType:DATA_SHARED) { + trigger(Event:Shared_Data, in_msg.Address); + } else if (in_msg.Type == CoherenceResponseType:DATA_EXCLUSIVE) { + trigger(Event:Exclusive_Data, in_msg.Address); + } else { + error("Unexpected message"); + } + } + } + } + + in_port(dmaRequestQueue_in, DMARequestMsg, dmaRequestToDir) { + if (dmaRequestQueue_in.isReady()) { + peek(dmaRequestQueue_in, DMARequestMsg) { + if (in_msg.Type == DMARequestType:READ) { + trigger(Event:DMA_READ, in_msg.LineAddress); + } else if (in_msg.Type == DMARequestType:WRITE) { + trigger(Event:DMA_WRITE, in_msg.LineAddress); + } else { + error("Invalid message"); + } + } + } + } + + in_port(requestQueue_in, RequestMsg, requestToDir) { + if (requestQueue_in.isReady()) { + peek(requestQueue_in, RequestMsg) { + if (in_msg.Type == CoherenceRequestType:GETS) { + trigger(Event:GETS, in_msg.Address); + } else if (in_msg.Type == CoherenceRequestType:GETX) { + trigger(Event:GETX, in_msg.Address); + } else if (in_msg.Type == CoherenceRequestType:PUT) { + trigger(Event:PUT, in_msg.Address); + } else { + error("Invalid message"); + } + } + } + } + + // off-chip memory request/response is done + in_port(memQueue_in, MemoryMsg, memBuffer) { + if (memQueue_in.isReady()) { + peek(memQueue_in, MemoryMsg) { + if (in_msg.Type == MemoryRequestType:MEMORY_READ) { + trigger(Event:Memory_Data, in_msg.Address); + } else if (in_msg.Type == MemoryRequestType:MEMORY_WB) { + trigger(Event:Memory_Ack, in_msg.Address); + } else { + DEBUG_EXPR(in_msg.Type); + error("Invalid message"); + } + } + } + } + + // Actions + + action(a_sendWriteBackAck, "a", desc="Send writeback ack to requestor") { + peek(requestQueue_in, RequestMsg) { + enqueue(forwardNetwork_out, RequestMsg, latency=memory_controller_latency) { + out_msg.Address := address; + out_msg.Type := CoherenceRequestType:WB_ACK; + out_msg.Requestor := in_msg.Requestor; + out_msg.Destination.add(in_msg.Requestor); + out_msg.MessageSize := MessageSizeType:Writeback_Control; + } + } + } + + action(b_sendWriteBackNack, "b", desc="Send writeback nack to requestor") { + peek(requestQueue_in, RequestMsg) { + enqueue(forwardNetwork_out, RequestMsg, latency=memory_controller_latency) { + out_msg.Address := address; + out_msg.Type := CoherenceRequestType:WB_NACK; + out_msg.Requestor := in_msg.Requestor; + out_msg.Destination.add(in_msg.Requestor); + out_msg.MessageSize := MessageSizeType:Writeback_Control; + } + } + } + + action(v_allocateTBE, "v", desc="Allocate TBE") { + peek(requestQueue_in, RequestMsg) { + TBEs.allocate(address); + TBEs[address].PhysicalAddress := address; + TBEs[address].ResponseType := CoherenceResponseType:NULL; + } + } + + action(vd_allocateDmaRequestInTBE, "vd", desc="Record Data in TBE") { + peek(dmaRequestQueue_in, DMARequestMsg) { + TBEs.allocate(address); + TBEs[address].DmaDataBlk := in_msg.DataBlk; + TBEs[address].PhysicalAddress := in_msg.PhysicalAddress; + TBEs[address].Len := in_msg.Len; + TBEs[address].DmaRequestor := in_msg.Requestor; + TBEs[address].ResponseType := CoherenceResponseType:DATA_EXCLUSIVE; + // + // One ack for each last-level cache + // + TBEs[address].NumPendingMsgs := getNumberOfLastLevelCaches(); + // + // Assume initially that the caches store a clean copy and that memory + // will provide the data + // + TBEs[address].CacheDirty := false; + } + } + + action(w_deallocateTBE, "w", desc="Deallocate TBE") { + TBEs.deallocate(address); + } + + action(m_decrementNumberOfMessages, "m", desc="Decrement the number of messages for which we're waiting") { + peek(responseToDir_in, ResponseMsg) { + assert(in_msg.Acks > 0); + DEBUG_EXPR(TBEs[address].NumPendingMsgs); + // + // Note that cache data responses will have an ack count of 2. However, + // directory DMA requests must wait for acks from all LLC caches, so + // only decrement by 1. + // + TBEs[address].NumPendingMsgs := TBEs[address].NumPendingMsgs - 1; + DEBUG_EXPR(TBEs[address].NumPendingMsgs); + } + } + + action(n_popResponseQueue, "n", desc="Pop response queue") { + responseToDir_in.dequeue(); + } + + action(o_checkForCompletion, "o", desc="Check if we have received all the messages required for completion") { + if (TBEs[address].NumPendingMsgs == 0) { + enqueue(triggerQueue_out, TriggerMsg) { + out_msg.Address := address; + if (TBEs[address].Sharers) { + out_msg.Type := TriggerType:ALL_ACKS; + } else { + out_msg.Type := TriggerType:ALL_ACKS_NO_SHARERS; + } + } + } + } + + action(d_sendData, "d", desc="Send data to requestor") { + peek(memQueue_in, MemoryMsg) { + enqueue(responseNetwork_out, ResponseMsg, latency="1") { + out_msg.Address := address; + out_msg.Type := TBEs[address].ResponseType; + out_msg.Sender := machineID; + out_msg.Destination.add(in_msg.OriginalRequestorMachId); + out_msg.DataBlk := in_msg.DataBlk; + out_msg.Dirty := false; // By definition, the block is now clean + out_msg.Acks := 1; + out_msg.MessageSize := MessageSizeType:Response_Data; + } + } + } + + action(dr_sendDmaData, "dr", desc="Send Data to DMA controller from memory") { + peek(memQueue_in, MemoryMsg) { + enqueue(dmaResponseNetwork_out, DMAResponseMsg, latency="1") { + out_msg.PhysicalAddress := address; + out_msg.LineAddress := address; + out_msg.Type := DMAResponseType:DATA; + // + // we send the entire data block and rely on the dma controller to + // split it up if need be + // + out_msg.DataBlk := in_msg.DataBlk; + out_msg.Destination.add(TBEs[address].DmaRequestor); + out_msg.MessageSize := MessageSizeType:Response_Data; + } + } + } + + action(dt_sendDmaDataFromTbe, "dt", desc="Send Data to DMA controller from tbe") { + peek(triggerQueue_in, TriggerMsg) { + enqueue(dmaResponseNetwork_out, DMAResponseMsg, latency="1") { + out_msg.PhysicalAddress := address; + out_msg.LineAddress := address; + out_msg.Type := DMAResponseType:DATA; + // + // we send the entire data block and rely on the dma controller to + // split it up if need be + // + out_msg.DataBlk := TBEs[address].DataBlk; + out_msg.Destination.add(TBEs[address].DmaRequestor); + out_msg.MessageSize := MessageSizeType:Response_Data; + } + } + } + + action(da_sendDmaAck, "da", desc="Send Ack to DMA controller") { + enqueue(dmaResponseNetwork_out, DMAResponseMsg, latency="1") { + out_msg.PhysicalAddress := address; + out_msg.LineAddress := address; + out_msg.Type := DMAResponseType:ACK; + out_msg.Destination.add(TBEs[address].DmaRequestor); + out_msg.MessageSize := MessageSizeType:Writeback_Control; + } + } + + action(rx_recordExclusiveInTBE, "rx", desc="Record Exclusive in TBE") { + peek(requestQueue_in, RequestMsg) { + TBEs[address].ResponseType := CoherenceResponseType:DATA_EXCLUSIVE; + } + } + + action(r_recordDataInTBE, "rt", desc="Record Data in TBE") { + peek(requestQueue_in, RequestMsg) { + TBEs[address].ResponseType := CoherenceResponseType:DATA; + } + } + + action(r_setSharerBit, "r", desc="We saw other sharers") { + TBEs[address].Sharers := true; + } + + action(qf_queueMemoryFetchRequest, "qf", desc="Queue off-chip fetch request") { + peek(requestQueue_in, RequestMsg) { + enqueue(memQueue_out, MemoryMsg, latency="1") { + out_msg.Address := address; + out_msg.Type := MemoryRequestType:MEMORY_READ; + out_msg.Sender := machineID; + out_msg.OriginalRequestorMachId := in_msg.Requestor; + out_msg.MessageSize := in_msg.MessageSize; + out_msg.DataBlk := directory[address].DataBlk; + DEBUG_EXPR(out_msg); + } + } + } + + action(qd_queueMemoryRequestFromDmaRead, "qd", desc="Queue off-chip fetch request") { + peek(dmaRequestQueue_in, DMARequestMsg) { + enqueue(memQueue_out, MemoryMsg, latency="1") { + out_msg.Address := address; + out_msg.Type := MemoryRequestType:MEMORY_READ; + out_msg.Sender := machineID; + out_msg.OriginalRequestorMachId := in_msg.Requestor; + out_msg.MessageSize := in_msg.MessageSize; + out_msg.DataBlk := directory[address].DataBlk; + DEBUG_EXPR(out_msg); + } + } + } + + action(f_forwardRequest, "f", desc="Forward requests") { + if (getNumberOfLastLevelCaches() > 1) { + peek(requestQueue_in, RequestMsg) { + enqueue(forwardNetwork_out, RequestMsg, latency=memory_controller_latency) { + out_msg.Address := address; + out_msg.Type := in_msg.Type; + out_msg.Requestor := in_msg.Requestor; + out_msg.Destination.broadcast(MachineType:L1Cache); // Send to all L1 caches + out_msg.Destination.remove(in_msg.Requestor); // Don't include the original requestor + out_msg.MessageSize := MessageSizeType:Forwarded_Control; + } + } + } + } + + action(f_forwardWriteFromDma, "fw", desc="Forward requests") { + peek(dmaRequestQueue_in, DMARequestMsg) { + enqueue(forwardNetwork_out, RequestMsg, latency=memory_controller_latency) { + out_msg.Address := address; + out_msg.Type := CoherenceRequestType:GETX; + // + // Send to all L1 caches, since the requestor is the memory controller + // itself + // + out_msg.Requestor := machineID; + out_msg.Destination.broadcast(MachineType:L1Cache); + out_msg.MessageSize := MessageSizeType:Forwarded_Control; + } + } + } + + action(f_forwardReadFromDma, "fr", desc="Forward requests") { + peek(dmaRequestQueue_in, DMARequestMsg) { + enqueue(forwardNetwork_out, RequestMsg, latency=memory_controller_latency) { + out_msg.Address := address; + out_msg.Type := CoherenceRequestType:GETS; + // + // Send to all L1 caches, since the requestor is the memory controller + // itself + // + out_msg.Requestor := machineID; + out_msg.Destination.broadcast(MachineType:L1Cache); + out_msg.MessageSize := MessageSizeType:Forwarded_Control; + } + } + } + + action(i_popIncomingRequestQueue, "i", desc="Pop incoming request queue") { + requestQueue_in.dequeue(); + } + + action(j_popIncomingUnblockQueue, "j", desc="Pop incoming unblock queue") { + unblockNetwork_in.dequeue(); + } + + action(l_popMemQueue, "q", desc="Pop off-chip request queue") { + memQueue_in.dequeue(); + } + + action(g_popTriggerQueue, "g", desc="Pop trigger queue") { + triggerQueue_in.dequeue(); + } + + action(p_popDmaRequestQueue, "pd", desc="pop dma request queue") { + dmaRequestQueue_in.dequeue(); + } + + action(y_recycleDmaRequestQueue, "y", desc="recycle dma request queue") { + dmaRequestQueue_in.recycle(); + } + + action(r_recordMemoryData, "rd", desc="record data from memory to TBE") { + peek(memQueue_in, MemoryMsg) { + if (TBEs[address].CacheDirty == false) { + TBEs[address].DataBlk := in_msg.DataBlk; + } + } + } + + action(r_recordCacheData, "rc", desc="record data from cache response to TBE") { + peek(responseToDir_in, ResponseMsg) { + TBEs[address].CacheDirty := true; + TBEs[address].DataBlk := in_msg.DataBlk; + } + } + + action(l_writeDataToMemory, "l", desc="Write PUTX/PUTO data to memory") { + peek(unblockNetwork_in, ResponseMsg) { + assert(in_msg.Dirty); + assert(in_msg.MessageSize == MessageSizeType:Writeback_Data); + directory[address].DataBlk := in_msg.DataBlk; + DEBUG_EXPR(in_msg.Address); + DEBUG_EXPR(in_msg.DataBlk); + } + } + + action(dwt_writeDmaDataFromTBE, "dwt", desc="DMA Write data to memory from TBE") { + directory[address].DataBlk := TBEs[address].DataBlk; + directory[address].DataBlk.copyPartial(TBEs[address].DmaDataBlk, addressOffset(TBEs[address].PhysicalAddress), TBEs[address].Len); + } + + action(a_assertCacheData, "ac", desc="Assert that a cache provided the data") { + assert(TBEs[address].CacheDirty); + } + + action(l_queueMemoryWBRequest, "lq", desc="Write PUTX data to memory") { + peek(unblockNetwork_in, ResponseMsg) { + enqueue(memQueue_out, MemoryMsg, latency="1") { + out_msg.Address := address; + out_msg.Type := MemoryRequestType:MEMORY_WB; + DEBUG_EXPR(out_msg); + } + } + } + + action(ld_queueMemoryDmaWrite, "ld", desc="Write DMA data to memory") { + enqueue(memQueue_out, MemoryMsg, latency="1") { + out_msg.Address := address; + out_msg.Type := MemoryRequestType:MEMORY_WB; + // first, initialize the data blk to the current version of system memory + out_msg.DataBlk := TBEs[address].DataBlk; + // then add the dma write data + out_msg.DataBlk.copyPartial(TBEs[address].DmaDataBlk, addressOffset(TBEs[address].PhysicalAddress), TBEs[address].Len); + DEBUG_EXPR(out_msg); + } + } + + action(ll_checkIncomingWriteback, "\l", desc="Check PUTX/PUTO response message") { + peek(unblockNetwork_in, ResponseMsg) { + assert(in_msg.Dirty == false); + assert(in_msg.MessageSize == MessageSizeType:Writeback_Control); + + // NOTE: The following check would not be valid in a real + // implementation. We include the data in the "dataless" + // message so we can assert the clean data matches the datablock + // in memory + assert(directory[address].DataBlk == in_msg.DataBlk); + } + } + + action(zz_recycleRequest, "\z", desc="Recycle the request queue") { + requestQueue_in.recycle(); + } + + // TRANSITIONS + + // Transitions out of E state + transition(E, GETX, NO_B_W) { + v_allocateTBE; + rx_recordExclusiveInTBE; + qf_queueMemoryFetchRequest; + f_forwardRequest; + i_popIncomingRequestQueue; + } + + transition(E, GETS, NO_B_W) { + v_allocateTBE; + rx_recordExclusiveInTBE; + qf_queueMemoryFetchRequest; + f_forwardRequest; + i_popIncomingRequestQueue; + } + + transition(E, DMA_READ, NO_DR_B_W) { + vd_allocateDmaRequestInTBE; + qd_queueMemoryRequestFromDmaRead; + f_forwardReadFromDma; + p_popDmaRequestQueue; + } + + // Transitions out of O state + transition(O, GETX, NO_B_W) { + v_allocateTBE; + r_recordDataInTBE; + qf_queueMemoryFetchRequest; + f_forwardRequest; + i_popIncomingRequestQueue; + } + + transition(O, GETS, O_B_W) { + v_allocateTBE; + r_recordDataInTBE; + qf_queueMemoryFetchRequest; + f_forwardRequest; + i_popIncomingRequestQueue; + } + + transition(O, DMA_READ, O_DR_B_W) { + vd_allocateDmaRequestInTBE; + qd_queueMemoryRequestFromDmaRead; + f_forwardReadFromDma; + p_popDmaRequestQueue; + } + + transition({E, O, NO}, DMA_WRITE, NO_DW_B_W) { + vd_allocateDmaRequestInTBE; + f_forwardWriteFromDma; + p_popDmaRequestQueue; + } + + // Transitions out of NO state + transition(NO, GETX, NO_B) { + f_forwardRequest; + i_popIncomingRequestQueue; + } + + transition(NO, GETS, NO_B) { + f_forwardRequest; + i_popIncomingRequestQueue; + } + + transition(NO, PUT, WB) { + a_sendWriteBackAck; + i_popIncomingRequestQueue; + } + + transition(NO, DMA_READ, NO_DR_B_D) { + vd_allocateDmaRequestInTBE; + f_forwardReadFromDma; + p_popDmaRequestQueue; + } + + // Nack PUT requests when races cause us to believe we own the data + transition({O, E}, PUT) { + b_sendWriteBackNack; + i_popIncomingRequestQueue; + } + + // Blocked transient states + transition({NO_B, O_B, NO_DR_B_W, NO_DW_B_W, NO_B_W, NO_DR_B_D, + NO_DR_B, O_DR_B, O_B_W, O_DR_B_W, NO_DW_W, + NO_W, O_W, WB, WB_E_W, WB_O_W}, + {GETS, GETX, PUT}) { + zz_recycleRequest; + } + + transition({NO_B, O_B, NO_DR_B_W, NO_DW_B_W, NO_B_W, NO_DR_B_D, + NO_DR_B, O_DR_B, O_B_W, O_DR_B_W, NO_DW_W, + NO_W, O_W, WB, WB_E_W, WB_O_W}, + {DMA_READ, DMA_WRITE}) { + y_recycleDmaRequestQueue; + } + + transition(NO_B, Unblock, NO) { + j_popIncomingUnblockQueue; + } + + transition(O_B, Unblock, O) { + j_popIncomingUnblockQueue; + } + + transition(NO_B_W, Memory_Data, NO_B) { + d_sendData; + w_deallocateTBE; + l_popMemQueue; + } + + transition(NO_DR_B_W, Memory_Data, NO_DR_B) { + r_recordMemoryData; + o_checkForCompletion; + l_popMemQueue; + } + + transition(O_DR_B_W, Memory_Data, O_DR_B) { + r_recordMemoryData; + dr_sendDmaData; + o_checkForCompletion; + l_popMemQueue; + } + + transition({NO_DR_B, O_DR_B, NO_DR_B_D, NO_DW_B_W}, Ack) { + m_decrementNumberOfMessages; + o_checkForCompletion; + n_popResponseQueue; + } + + transition(NO_DR_B_W, Ack) { + m_decrementNumberOfMessages; + n_popResponseQueue; + } + + transition(NO_DR_B_W, Shared_Ack) { + m_decrementNumberOfMessages; + r_setSharerBit; + n_popResponseQueue; + } + + transition({NO_DR_B, NO_DR_B_D}, Shared_Ack) { + m_decrementNumberOfMessages; + r_setSharerBit; + o_checkForCompletion; + n_popResponseQueue; + } + + transition(NO_DR_B_W, Shared_Data) { + r_recordCacheData; + m_decrementNumberOfMessages; + r_setSharerBit; + o_checkForCompletion; + n_popResponseQueue; + } + + transition({NO_DR_B, NO_DR_B_D}, Shared_Data) { + r_recordCacheData; + m_decrementNumberOfMessages; + r_setSharerBit; + o_checkForCompletion; + n_popResponseQueue; + } + + transition(NO_DR_B_W, Exclusive_Data) { + r_recordCacheData; + m_decrementNumberOfMessages; + n_popResponseQueue; + } + + transition({NO_DR_B, NO_DR_B_D, NO_DW_B_W}, Exclusive_Data) { + r_recordCacheData; + m_decrementNumberOfMessages; + o_checkForCompletion; + n_popResponseQueue; + } + + transition(NO_DR_B, All_acks_and_data, O) { + // + // Note that the DMA consistency model allows us to send the DMA device + // a response as soon as we receive valid data and prior to receiving + // all acks. However, to simplify the protocol we wait for all acks. + // + dt_sendDmaDataFromTbe; + w_deallocateTBE; + g_popTriggerQueue; + } + + transition(NO_DR_B_D, All_acks_and_data, O) { + // + // Note that the DMA consistency model allows us to send the DMA device + // a response as soon as we receive valid data and prior to receiving + // all acks. However, to simplify the protocol we wait for all acks. + // + dt_sendDmaDataFromTbe; + w_deallocateTBE; + g_popTriggerQueue; + } + + transition(O_DR_B, All_acks_and_data_no_sharers, O) { + w_deallocateTBE; + g_popTriggerQueue; + } + + transition(NO_DR_B, All_acks_and_data_no_sharers, E) { + // + // Note that the DMA consistency model allows us to send the DMA device + // a response as soon as we receive valid data and prior to receiving + // all acks. However, to simplify the protocol we wait for all acks. + // + dt_sendDmaDataFromTbe; + w_deallocateTBE; + g_popTriggerQueue; + } + + transition(NO_DR_B_D, All_acks_and_data_no_sharers, E) { + a_assertCacheData; + // + // Note that the DMA consistency model allows us to send the DMA device + // a response as soon as we receive valid data and prior to receiving + // all acks. However, to simplify the protocol we wait for all acks. + // + dt_sendDmaDataFromTbe; + w_deallocateTBE; + g_popTriggerQueue; + } + + transition(NO_DW_B_W, All_acks_and_data_no_sharers, NO_DW_W) { + dwt_writeDmaDataFromTBE; + ld_queueMemoryDmaWrite; + g_popTriggerQueue; + } + + transition(NO_DW_W, Memory_Ack, E) { + da_sendDmaAck; + w_deallocateTBE; + l_popMemQueue; + } + + transition(O_B_W, Memory_Data, O_B) { + d_sendData; + w_deallocateTBE; + l_popMemQueue; + } + + transition(NO_B_W, Unblock, NO_W) { + j_popIncomingUnblockQueue; + } + + transition(O_B_W, Unblock, O_W) { + j_popIncomingUnblockQueue; + } + + transition(NO_W, Memory_Data, NO) { + w_deallocateTBE; + l_popMemQueue; + } + + transition(O_W, Memory_Data, O) { + w_deallocateTBE; + l_popMemQueue; + } + + // WB State Transistions + transition(WB, Writeback_Dirty, WB_E_W) { + l_writeDataToMemory; + l_queueMemoryWBRequest; + j_popIncomingUnblockQueue; + } + + transition(WB, Writeback_Exclusive_Dirty, WB_O_W) { + l_writeDataToMemory; + l_queueMemoryWBRequest; + j_popIncomingUnblockQueue; + } + + transition(WB_E_W, Memory_Ack, E) { + l_popMemQueue; + } + + transition(WB_O_W, Memory_Ack, O) { + l_popMemQueue; + } + + transition(WB, Writeback_Clean, O) { + ll_checkIncomingWriteback; + j_popIncomingUnblockQueue; + } + + transition(WB, Writeback_Exclusive_Clean, E) { + ll_checkIncomingWriteback; + j_popIncomingUnblockQueue; + } + + transition(WB, Unblock, NO) { + j_popIncomingUnblockQueue; + } +} diff --git a/src/mem/protocol/MOESI_hammer-dma.sm b/src/mem/protocol/MOESI_hammer-dma.sm new file mode 100644 index 000000000..b217923a4 --- /dev/null +++ b/src/mem/protocol/MOESI_hammer-dma.sm @@ -0,0 +1,165 @@ +/* + * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +machine(DMA, "DMA Controller") +: int request_latency +{ + + MessageBuffer responseFromDir, network="From", virtual_network="4", ordered="true", no_vector="true"; + MessageBuffer reqToDirectory, network="To", virtual_network="5", ordered="false", no_vector="true"; + + enumeration(State, desc="DMA states", default="DMA_State_READY") { + READY, desc="Ready to accept a new request"; + BUSY_RD, desc="Busy: currently processing a request"; + BUSY_WR, desc="Busy: currently processing a request"; + } + + enumeration(Event, desc="DMA events") { + ReadRequest, desc="A new read request"; + WriteRequest, desc="A new write request"; + Data, desc="Data from a DMA memory read"; + Ack, desc="DMA write to memory completed"; + } + + external_type(DMASequencer) { + void ackCallback(); + void dataCallback(DataBlock); + } + + MessageBuffer mandatoryQueue, ordered="false", no_vector="true"; + DMASequencer dma_sequencer, factory='RubySystem::getDMASequencer(m_cfg["dma_sequencer"])', no_vector="true"; + State cur_state, no_vector="true"; + + State getState(Address addr) { + return cur_state; + } + void setState(Address addr, State state) { + cur_state := state; + } + + out_port(reqToDirectory_out, DMARequestMsg, reqToDirectory, desc="..."); + + in_port(dmaRequestQueue_in, SequencerMsg, mandatoryQueue, desc="...") { + if (dmaRequestQueue_in.isReady()) { + peek(dmaRequestQueue_in, SequencerMsg) { + if (in_msg.Type == SequencerRequestType:LD ) { + trigger(Event:ReadRequest, in_msg.LineAddress); + } else if (in_msg.Type == SequencerRequestType:ST) { + trigger(Event:WriteRequest, in_msg.LineAddress); + } else { + error("Invalid request type"); + } + } + } + } + + in_port(dmaResponseQueue_in, DMAResponseMsg, responseFromDir, desc="...") { + if (dmaResponseQueue_in.isReady()) { + peek( dmaResponseQueue_in, DMAResponseMsg) { + if (in_msg.Type == DMAResponseType:ACK) { + trigger(Event:Ack, in_msg.LineAddress); + } else if (in_msg.Type == DMAResponseType:DATA) { + trigger(Event:Data, in_msg.LineAddress); + } else { + error("Invalid response type"); + } + } + } + } + + action(s_sendReadRequest, "s", desc="Send a DMA read request to memory") { + peek(dmaRequestQueue_in, SequencerMsg) { + enqueue(reqToDirectory_out, DMARequestMsg, latency=request_latency) { + out_msg.PhysicalAddress := in_msg.PhysicalAddress; + out_msg.LineAddress := in_msg.LineAddress; + out_msg.Type := DMARequestType:READ; + out_msg.Requestor := machineID; + out_msg.DataBlk := in_msg.DataBlk; + out_msg.Len := in_msg.Len; + out_msg.Destination.add(map_Address_to_Directory(address)); + out_msg.MessageSize := MessageSizeType:Writeback_Control; + } + } + } + + action(s_sendWriteRequest, "\s", desc="Send a DMA write request to memory") { + peek(dmaRequestQueue_in, SequencerMsg) { + enqueue(reqToDirectory_out, DMARequestMsg, latency=request_latency) { + out_msg.PhysicalAddress := in_msg.PhysicalAddress; + out_msg.LineAddress := in_msg.LineAddress; + out_msg.Type := DMARequestType:WRITE; + out_msg.Requestor := machineID; + out_msg.DataBlk := in_msg.DataBlk; + out_msg.Len := in_msg.Len; + out_msg.Destination.add(map_Address_to_Directory(address)); + out_msg.MessageSize := MessageSizeType:Writeback_Control; + } + } + } + + action(a_ackCallback, "a", desc="Notify dma controller that write request completed") { + peek (dmaResponseQueue_in, DMAResponseMsg) { + dma_sequencer.ackCallback(); + } + } + + action(d_dataCallback, "d", desc="Write data to dma sequencer") { + peek (dmaResponseQueue_in, DMAResponseMsg) { + dma_sequencer.dataCallback(in_msg.DataBlk); + } + } + + action(p_popRequestQueue, "p", desc="Pop request queue") { + dmaRequestQueue_in.dequeue(); + } + + action(p_popResponseQueue, "\p", desc="Pop request queue") { + dmaResponseQueue_in.dequeue(); + } + + transition(READY, ReadRequest, BUSY_RD) { + s_sendReadRequest; + p_popRequestQueue; + } + + transition(READY, WriteRequest, BUSY_WR) { + s_sendWriteRequest; + p_popRequestQueue; + } + + transition(BUSY_RD, Data, READY) { + d_dataCallback; + p_popResponseQueue; + } + + transition(BUSY_WR, Ack, READY) { + a_ackCallback; + p_popResponseQueue; + } +} diff --git a/src/mem/protocol/MOESI_hammer-msg.sm b/src/mem/protocol/MOESI_hammer-msg.sm new file mode 100644 index 000000000..5d8226eb6 --- /dev/null +++ b/src/mem/protocol/MOESI_hammer-msg.sm @@ -0,0 +1,119 @@ +/* + * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * AMD's contributions to the MOESI hammer protocol do not constitute an + * endorsement of its similarity to any AMD products. + */ + +// CoherenceRequestType +enumeration(CoherenceRequestType, desc="...") { + GETX, desc="Get eXclusive"; + GETS, desc="Get Shared"; + PUT, desc="Put Ownership"; + WB_ACK, desc="Writeback ack"; + WB_NACK, desc="Writeback neg. ack"; +} + +// CoherenceResponseType +enumeration(CoherenceResponseType, desc="...") { + ACK, desc="ACKnowledgment, responder does not have a copy"; + ACK_SHARED, desc="ACKnowledgment, responder has a shared copy"; + DATA, desc="Data, responder does not have a copy"; + DATA_SHARED, desc="Data, responder has a shared copy"; + DATA_EXCLUSIVE, desc="Data, responder was exclusive, gave us a copy, and they went to invalid"; + WB_CLEAN, desc="Clean writeback"; + WB_DIRTY, desc="Dirty writeback"; + WB_EXCLUSIVE_CLEAN, desc="Clean writeback of exclusive data"; + WB_EXCLUSIVE_DIRTY, desc="Dirty writeback of exclusive data"; + UNBLOCK, desc="Unblock"; + NULL, desc="Null value"; +} + +// TriggerType +enumeration(TriggerType, desc="...") { + ALL_ACKS, desc="See corresponding event"; + ALL_ACKS_NO_SHARERS, desc="See corresponding event"; +} + +// TriggerMsg +structure(TriggerMsg, desc="...", interface="Message") { + Address Address, desc="Physical address for this request"; + TriggerType Type, desc="Type of trigger"; +} + +// RequestMsg (and also forwarded requests) +structure(RequestMsg, desc="...", interface="NetworkMessage") { + Address Address, desc="Physical address for this request"; + CoherenceRequestType Type, desc="Type of request (GetS, GetX, PutX, etc)"; + MachineID Requestor, desc="Node who initiated the request"; + NetDest Destination, desc="Multicast destination mask"; + MessageSizeType MessageSize, desc="size category of the message"; +} + +// ResponseMsg (and also unblock requests) +structure(ResponseMsg, desc="...", interface="NetworkMessage") { + Address Address, desc="Physical address for this request"; + CoherenceResponseType Type, desc="Type of response (Ack, Data, etc)"; + MachineID Sender, desc="Node who sent the data"; + NetDest Destination, desc="Node to whom the data is sent"; + DataBlock DataBlk, desc="data for the cache line"; + bool Dirty, desc="Is the data dirty (different than memory)?"; + int Acks, desc="How many messages this counts as"; + MessageSizeType MessageSize, desc="size category of the message"; +} + +enumeration(DMARequestType, desc="...", default="DMARequestType_NULL") { + READ, desc="Memory Read"; + WRITE, desc="Memory Write"; + NULL, desc="Invalid"; +} + +enumeration(DMAResponseType, desc="...", default="DMAResponseType_NULL") { + DATA, desc="DATA read"; + ACK, desc="ACK write"; + NULL, desc="Invalid"; +} + +structure(DMARequestMsg, desc="...", interface="NetworkMessage") { + DMARequestType Type, desc="Request type (read/write)"; + Address PhysicalAddress, desc="Physical address for this request"; + Address LineAddress, desc="Line address for this request"; + MachineID Requestor, desc="Node who initiated the request"; + NetDest Destination, desc="Destination"; + DataBlock DataBlk, desc="DataBlk attached to this request"; + int Len, desc="The length of the request"; + MessageSizeType MessageSize, desc="size category of the message"; +} + +structure(DMAResponseMsg, desc="...", interface="NetworkMessage") { + DMAResponseType Type, desc="Response type (DATA/ACK)"; + Address PhysicalAddress, desc="Physical address for this request"; + Address LineAddress, desc="Line address for this request"; + NetDest Destination, desc="Destination"; + DataBlock DataBlk, desc="DataBlk attached to this request"; + MessageSizeType MessageSize, desc="size category of the message"; +} diff --git a/src/mem/protocol/MOESI_hammer.slicc b/src/mem/protocol/MOESI_hammer.slicc new file mode 100644 index 000000000..31ad47c2e --- /dev/null +++ b/src/mem/protocol/MOESI_hammer.slicc @@ -0,0 +1,5 @@ +MOESI_hammer-msg.sm +MOESI_hammer-cache.sm +MOESI_hammer-dir.sm +MOESI_hammer-dma.sm +standard_1level_CMP-protocol.sm diff --git a/src/mem/protocol/RubySlicc_ComponentMapping.sm b/src/mem/protocol/RubySlicc_ComponentMapping.sm index 0da1a05e2..891820c46 100644 --- a/src/mem/protocol/RubySlicc_ComponentMapping.sm +++ b/src/mem/protocol/RubySlicc_ComponentMapping.sm @@ -29,6 +29,8 @@ // Mapping functions +int getNumberOfLastLevelCaches(); + // NodeID map_address_to_node(Address addr); MachineID mapAddressToRange(Address addr, MachineType type, int low, int high); NetDest broadcast(MachineType type); diff --git a/src/mem/protocol/RubySlicc_Util.sm b/src/mem/protocol/RubySlicc_Util.sm index 312682bd7..e1771448f 100644 --- a/src/mem/protocol/RubySlicc_Util.sm +++ b/src/mem/protocol/RubySlicc_Util.sm @@ -52,7 +52,6 @@ void dirProfileCoherenceRequest(NodeID node, bool needCLB); bool isPerfectProtocol(); bool L1trainsPrefetcher(); int max_tokens(); -int N_tokens(); bool distributedPersistentEnabled(); Address setOffset(Address addr, int offset); Address makeLineAddress(Address addr); diff --git a/src/mem/protocol/SConscript b/src/mem/protocol/SConscript index 293346f13..cd9920d22 100644 --- a/src/mem/protocol/SConscript +++ b/src/mem/protocol/SConscript @@ -29,30 +29,51 @@ # Authors: Nathan Binkert import os -import re -import string import sys -from os.path import basename, dirname, exists, expanduser, isdir, isfile -from os.path import join as joinpath - -import SCons +from os.path import isdir, isfile, join as joinpath Import('*') if not env['RUBY']: Return() -slicc_dir = Dir('../slicc') protocol_dir = Dir('.') html_dir = Dir('html') +slicc_dir = Dir('../slicc') + +sys.path[1:1] = [ Dir('..').srcnode().abspath ] +from slicc.parser import SLICC + +slicc_depends = [] +for root,dirs,files in os.walk(slicc_dir.srcnode().abspath): + for f in files: + if f.endswith('.py'): + slicc_depends.append(File(joinpath(root, f))) # # Use SLICC # -def slicc_generator(target, source, env, for_signature): - slicc_bin = str(source[0]) - protocol = source[1].get_contents() + +def slicc_scanner(node, env, path): + contents = node.get_contents() + files = [ line.strip() for line in contents.splitlines() ] + return files + +env.Append(SCANNERS=Scanner(function=slicc_scanner,skeys=['.slicc'])) + +def slicc_emitter(target, source, env): + files = [s.srcnode().abspath for s in source[1:]] + slicc = SLICC(debug=True) + print "SLICC parsing..." + for name in slicc.load(files, verbose=True): + print " %s" % name + + target.extend(sorted(slicc.files())) + return target, source + +def slicc_action(target, source, env): + protocol = source[0].get_contents() pdir = str(protocol_dir) hdir = str(html_dir) @@ -61,32 +82,31 @@ def slicc_generator(target, source, env, for_signature): if not isdir(hdir): os.mkdir(hdir) - do_html = "html" - cmdline = [ slicc_bin, pdir, hdir, protocol, do_html ] - cmdline += [ str(s) for s in source[2:] ] - cmdline = ' '.join(cmdline) - return cmdline + slicc = SLICC(debug=True) + files = [str(s) for s in source[1:]] + slicc.load(files, verbose=False) -slicc_builder = Builder(generator=slicc_generator) + print "SLICC Generator pass 1..." + slicc.findMachines() -protocol = env['PROTOCOL'] -sources = [ protocol_dir.File("RubySlicc_interfaces.slicc"), - protocol_dir.File("%s.slicc" % protocol) ] + print "SLICC Generator pass 2..." + slicc.generate() -sys.path[0:0] = [env['ENV']['M5_PLY']] -execfile(slicc_dir.File('parser/parser.py').srcnode().abspath) + print "SLICC writing C++ files..." + slicc.writeCodeFiles(pdir) -sm_files = read_slicc([s.srcnode().abspath for s in sources]) -sm_files = [ protocol_dir.File(f) for f in sm_files ] + print "SLICC writing HTML files..." + slicc.writeHTMLFiles(hdir) -hh, cc = scan([s.srcnode().abspath for s in sm_files]) -hh = [ protocol_dir.File(f) for f in hh ] -cc = [ protocol_dir.File(f) for f in cc ] +slicc_builder = Builder(action=slicc_action, emitter=slicc_emitter) -slicc_bin = slicc_dir.File("slicc") +protocol = env['PROTOCOL'] +sources = [ protocol_dir.File("RubySlicc_interfaces.slicc"), + protocol_dir.File("%s.slicc" % protocol) ] env.Append(BUILDERS={'SLICC' : slicc_builder}) -env.SLICC(hh + cc, [ slicc_bin, Value(protocol) ] + sm_files) +nodes = env.SLICC([], [ Value(protocol) ] + sources) +env.Depends(nodes, slicc_depends) -for f in cc: +for f in sorted(s for s in nodes if str(s).endswith('.cc')): Source(f) diff --git a/src/mem/protocol/SConsopts b/src/mem/protocol/SConsopts index ded0814d2..10a303681 100644 --- a/src/mem/protocol/SConsopts +++ b/src/mem/protocol/SConsopts @@ -47,9 +47,10 @@ all_protocols = [ 'MOSI_SMP_bcast_m', 'MOSI_SMP_directory_1level', 'MSI_MOSI_CMP_directory', + 'MOESI_hammer', ] -opt = EnumVariable('PROTOCOL', 'Coherence Protocol for Ruby', 'MI_example', +opt = EnumVariable('PROTOCOL', 'Coherence Protocol for Ruby', 'MOESI_CMP_directory', all_protocols) sticky_vars.AddVariables(opt) diff --git a/src/mem/request.hh b/src/mem/request.hh index c8c31ffcd..f2cc4647c 100644 --- a/src/mem/request.hh +++ b/src/mem/request.hh @@ -72,8 +72,6 @@ class Request : public FastAlloc /** This request is to a memory mapped register. */ static const FlagsType MMAPED_IPR = 0x00002000; - /** The request should not cause a page fault. */ - static const FlagsType NO_FAULT = 0x00010000; /** The request should ignore unaligned access faults */ static const FlagsType NO_ALIGN_FAULT = 0x00020000; /** The request should ignore unaligned access faults */ diff --git a/src/mem/ruby/SConscript b/src/mem/ruby/SConscript index 0c8423c85..3559f042f 100644 --- a/src/mem/ruby/SConscript +++ b/src/mem/ruby/SConscript @@ -114,6 +114,7 @@ MakeInclude('system/MachineID.hh') MakeInclude('system/MemoryControl.hh') MakeInclude('system/NodeID.hh') MakeInclude('system/PerfectCacheMemory.hh') +MakeInclude('system/PersistentTable.hh') MakeInclude('system/Sequencer.hh') MakeInclude('system/TBETable.hh') MakeInclude('system/TimerTable.hh') diff --git a/src/mem/ruby/buffers/MessageBuffer.cc b/src/mem/ruby/buffers/MessageBuffer.cc index 3928e94e6..d157e2a94 100644 --- a/src/mem/ruby/buffers/MessageBuffer.cc +++ b/src/mem/ruby/buffers/MessageBuffer.cc @@ -34,27 +34,7 @@ #include "mem/ruby/buffers/MessageBuffer.hh" #include "mem/ruby/system/System.hh" -MessageBuffer::MessageBuffer() -{ - m_msg_counter = 0; - m_consumer_ptr = NULL; - m_ordering_set = false; - m_strict_fifo = true; - m_size = 0; - m_max_size = -1; - m_last_arrival_time = 0; - m_randomization = true; - m_size_last_time_size_checked = 0; - m_time_last_time_size_checked = 0; - m_time_last_time_enqueue = 0; - m_time_last_time_pop = 0; - m_size_at_cycle_start = 0; - m_msgs_this_cycle = 0; - m_not_avail_count = 0; - m_priority_rank = 0; -} - -MessageBuffer::MessageBuffer(const Chip* chip_ptr) // The chip_ptr is ignored, but could be used for extra debugging +MessageBuffer::MessageBuffer(const string &name) { m_msg_counter = 0; m_consumer_ptr = NULL; @@ -72,6 +52,7 @@ MessageBuffer::MessageBuffer(const Chip* chip_ptr) // The chip_ptr is ignored, m_msgs_this_cycle = 0; m_not_avail_count = 0; m_priority_rank = 0; + m_name = name; } int MessageBuffer::getSize() diff --git a/src/mem/ruby/buffers/MessageBuffer.hh b/src/mem/ruby/buffers/MessageBuffer.hh index 3ca6790d0..8440c3335 100644 --- a/src/mem/ruby/buffers/MessageBuffer.hh +++ b/src/mem/ruby/buffers/MessageBuffer.hh @@ -46,15 +46,11 @@ #include "mem/gems_common/PrioHeap.hh" #include "mem/gems_common/util.hh" -class Chip; - class MessageBuffer { public: // Constructors - MessageBuffer(); - MessageBuffer(const Chip* chip_ptr); // The chip_ptr is ignored, but could be used for extra debugging + MessageBuffer(const string &name = ""); - // Use Default Destructor // ~MessageBuffer() // Public Methods diff --git a/src/mem/ruby/common/Address.hh b/src/mem/ruby/common/Address.hh index c48152354..88cd2668a 100644 --- a/src/mem/ruby/common/Address.hh +++ b/src/mem/ruby/common/Address.hh @@ -148,7 +148,7 @@ inline physical_address_t Address::bitSelect(int small, int big) const // rips bits inclusive { physical_address_t mask; - assert(big >= small); + assert((unsigned)big >= (unsigned)small); if (big >= ADDRESS_WIDTH - 1) { return (m_address >> small); diff --git a/src/mem/ruby/common/DataBlock.hh b/src/mem/ruby/common/DataBlock.hh index 3c8ef56f4..1d399753e 100644 --- a/src/mem/ruby/common/DataBlock.hh +++ b/src/mem/ruby/common/DataBlock.hh @@ -45,7 +45,11 @@ class DataBlock { } // Destructor - ~DataBlock() { if(m_alloc) delete [] m_data;} + ~DataBlock() { + if(m_alloc) { + delete [] m_data; + } + } DataBlock& operator=(const DataBlock& obj); diff --git a/src/mem/ruby/common/Debug.cc b/src/mem/ruby/common/Debug.cc index 1115152f4..cb9fdf082 100644 --- a/src/mem/ruby/common/Debug.cc +++ b/src/mem/ruby/common/Debug.cc @@ -39,6 +39,7 @@ #include "mem/ruby/common/Debug.hh" #include "mem/ruby/eventqueue/RubyEventQueue.hh" #include "mem/gems_common/util.hh" +#include "base/misc.hh" class Debug; extern Debug* g_debug_ptr; @@ -70,6 +71,7 @@ DebugComponentData debugComponents[] = {"Cache", 'c' }, {"Predictor", 'p' }, {"Allocator", 'a' }, + {"Memory", 'M' }, }; extern "C" void changeDebugVerbosity(VerbosityLevel vb); @@ -95,19 +97,27 @@ Debug::Debug() Debug::Debug( const string & name, const vector<string> & argv ) { - for (size_t i=0;i<argv.size();i+=2){ - if (argv[i] == "filter_string") - setFilterString( argv[i+1].c_str() ); - else if (argv[i] == "verbosity_string") + // + // must clear the filter before adding filter strings + // + clearFilter(); + + for (size_t i=0;i<argv.size();i+=2) { + if (argv[i] == "filter_string") { + if (setFilterString(argv[i+1].c_str())) { + fatal("could not set filter string to %s\n", argv[i+1].c_str()); + } + } else if (argv[i] == "verbosity_string") { setVerbosityString( argv[i+1].c_str() ); - else if (argv[i] == "start_time") + } else if (argv[i] == "start_time") { m_starting_cycle = atoi( argv[i+1].c_str() ); - else if (argv[i] == "output_filename") + } else if (argv[i] == "output_filename") { setDebugOutputFile( argv[i+1].c_str() ); - else if (argv[i] == "protocol_trace") + } else if (argv[i] == "protocol_trace") { m_protocol_trace = string_to_bool(argv[i+1]); - else - assert(0); + } else { + fatal("invalid argument %s\n"); + } } } @@ -119,7 +129,8 @@ Debug::Debug( const char *filterString, const char *verboseString, debug_cout_ptr = &cout; m_starting_cycle = filterStartTime; - setFilterString( filterString ); + if (setFilterString(filterString)) + fatal("could not set filter string to %s\n", filterString); setVerbosityString( verboseString ); setDebugOutputFile( filename ); } diff --git a/src/mem/ruby/common/Debug.hh b/src/mem/ruby/common/Debug.hh index c038d57c2..03e123866 100644 --- a/src/mem/ruby/common/Debug.hh +++ b/src/mem/ruby/common/Debug.hh @@ -63,6 +63,7 @@ enum DebugComponents CACHE_COMP, PREDICTOR_COMP, ALLOCATOR_COMP, + MEMORY_COMP, NUMBER_OF_COMPS }; diff --git a/src/mem/ruby/common/NetDest.cc b/src/mem/ruby/common/NetDest.cc index 32771235f..35bb4ec43 100644 --- a/src/mem/ruby/common/NetDest.cc +++ b/src/mem/ruby/common/NetDest.cc @@ -133,13 +133,14 @@ NodeID NetDest::elementAt(MachineID index) { return m_bits[vecIndex(index)].elementAt(bitIndex(index.num)); } -NodeID NetDest::smallestElement() const +MachineID NetDest::smallestElement() const { assert(count() > 0); for (int i=0; i<m_bits.size(); i++) { for (int j=0; j<m_bits[i].getSize(); j++) { if (m_bits[i].isElement(j)) { - return j; + MachineID mach = {MachineType_from_base_level(i), j}; + return mach; } } } diff --git a/src/mem/ruby/common/NetDest.hh b/src/mem/ruby/common/NetDest.hh index 1dcee7b7a..071106623 100644 --- a/src/mem/ruby/common/NetDest.hh +++ b/src/mem/ruby/common/NetDest.hh @@ -63,7 +63,7 @@ public: NetDest& operator=(const Set& obj); // Destructor - // ~NetDest(); + ~NetDest() { DEBUG_MSG(MEMORY_COMP, LowPrio, "NetDest Destructor"); } // Public Methods void add(MachineID newElement); @@ -96,7 +96,7 @@ public: //For Princeton Network Vector<NodeID> getAllDest(); - NodeID smallestElement() const; + MachineID smallestElement() const; MachineID smallestElement(MachineType machine) const; void setSize(); diff --git a/src/mem/ruby/config/MI_example-homogeneous.rb b/src/mem/ruby/config/MI_example-homogeneous.rb index 409d0fe3a..71e20c318 100644 --- a/src/mem/ruby/config/MI_example-homogeneous.rb +++ b/src/mem/ruby/config/MI_example-homogeneous.rb @@ -13,7 +13,7 @@ RubySystem.reset # default values num_cores = 2 -l1_cache_size_kb = 32 +l1_cache_size_kb = 32768 l1_cache_assoc = 8 l1_cache_latency = 1 num_memories = 2 @@ -44,6 +44,15 @@ for i in 0..$*.size-1 do elsif $*[i] == "-s" memory_size_mb = $*[i+1].to_i i = i + 1 + elsif $*[i] == "-C" + l1_cache_size_bytes = $*[i+1].to_i + i = i + 1 + elsif $*[i] == "-A" + l1_cache_assoc = $*[i+1].to_i + i = i + 1 + elsif $*[i] == "-D" + num_dma = $*[i+1].to_i + i = i + 1 end end @@ -55,7 +64,7 @@ assert(protocol == "MI_example", __FILE__ + " cannot be used with protocol " + p require protocol+".rb" num_cores.times { |n| - cache = SetAssociativeCache.new("l1u_"+n.to_s, l1_cache_size_kb, l1_cache_latency, l1_cache_assoc, "PSEUDO_LRU") + cache = SetAssociativeCache.new("l1u_"+n.to_s, l1_cache_size_bytes, l1_cache_latency, l1_cache_assoc, "PSEUDO_LRU") sequencer = Sequencer.new("Sequencer_"+n.to_s, cache, cache) iface_ports << sequencer net_ports << MI_example_CacheController.new("L1CacheController_"+n.to_s, diff --git a/src/mem/ruby/config/MI_example.rb b/src/mem/ruby/config/MI_example.rb index 187dc7a68..8113087aa 100644 --- a/src/mem/ruby/config/MI_example.rb +++ b/src/mem/ruby/config/MI_example.rb @@ -23,8 +23,6 @@ class MI_example_DirectoryController < DirectoryController def argv() vec = super() vec += " directory_latency "+directory_latency.to_s - vec += " dma_select_low_bit "+log_int(RubySystem.block_size_bytes).to_s - vec += " dma_select_num_bits "+log_int(NetPort.totalOfType("DMA")).to_s end end diff --git a/src/mem/ruby/config/MOESI_CMP_token.rb b/src/mem/ruby/config/MOESI_CMP_token.rb new file mode 100644 index 000000000..ba963dc06 --- /dev/null +++ b/src/mem/ruby/config/MOESI_CMP_token.rb @@ -0,0 +1,92 @@ + +require "cfg.rb" +require "util.rb" + + +class MOESI_CMP_token_L1CacheController < L1CacheController + attr :icache, :dcache + attr :num_l2_controllers + attr :n_tokens + def initialize(obj_name, mach_type, icache, dcache, sequencer, num_l2_controllers, n_tokens) + super(obj_name, mach_type, [icache, dcache], sequencer) + @icache = icache + @dcache = dcache + @num_l2_controllers = num_l2_controllers + @n_tokens = n_tokens + end + def argv() + num_select_bits = log_int(num_l2_controllers) + num_block_bits = log_int(RubySystem.block_size_bytes) + + l2_select_low_bit = num_block_bits + + vec = super() + vec += " icache " + @icache.obj_name + vec += " dcache " + @dcache.obj_name + vec += " l1_request_latency " + l1_request_latency.to_s + vec += " l1_response_latency " + l1_response_latency.to_s + vec += " l2_select_low_bit " + l2_select_low_bit.to_s + vec += " l2_select_num_bits " + num_select_bits.to_s + vec += " N_tokens " + n_tokens.to_s + vec += " retry_threshold " + retry_threshold.to_s + vec += " fixed_timeout_latency " + fixed_timeout_latency.to_s + vec += " dynamic_timeout_enabled " + dynamic_timeout_enabled.to_s + + return vec + end +end + +class MOESI_CMP_token_L2CacheController < CacheController + attr :cache + attr :n_tokens + def initialize(obj_name, mach_type, cache, n_tokens) + super(obj_name, mach_type, [cache]) + @cache = cache + @n_tokens = n_tokens + end + def argv() + vec = super() + vec += " cache " + @cache.obj_name + vec += " l2_request_latency " + l2_request_latency.to_s + vec += " l2_response_latency " + l2_response_latency.to_s + vec += " N_tokens " + n_tokens.to_s + vec += " filtering_enabled " + filtering_enabled.to_s + return vec + end +end + + +class MOESI_CMP_token_DirectoryController < DirectoryController + attr :num_l2_controllers + def initialize(obj_name, mach_type, directory, memory_control, num_l2_controllers) + super(obj_name, mach_type, directory, memory_control) + @num_l2_controllers = num_l2_controllers + end + def argv() + num_select_bits = log_int(num_l2_controllers) + num_block_bits = log_int(RubySystem.block_size_bytes) + + l2_select_low_bit = num_block_bits + + vec = super() + vec += " directory_latency "+directory_latency.to_s + vec += " l2_select_low_bit " + l2_select_low_bit.to_s + vec += " l2_select_num_bits " + num_select_bits.to_s + vec += " distributed_persistent "+distributed_persistent.to_s + vec += " fixed_timeout_latency " + fixed_timeout_latency.to_s + return vec + end + +end + +class MOESI_CMP_token_DMAController < DMAController + def initialize(obj_name, mach_type, dma_sequencer) + super(obj_name, mach_type, dma_sequencer) + end + def argv() + vec = super + vec += " request_latency "+request_latency.to_s + vec += " response_latency "+response_latency.to_s + return vec + end +end diff --git a/src/mem/ruby/config/MOESI_hammer-homogeneous.rb b/src/mem/ruby/config/MOESI_hammer-homogeneous.rb new file mode 100644 index 000000000..02af0ec27 --- /dev/null +++ b/src/mem/ruby/config/MOESI_hammer-homogeneous.rb @@ -0,0 +1,109 @@ +#!/usr/bin/ruby +# +# Creates multiple on-chip nodes with three level of cache. +# + +require "cfg.rb" + +RubySystem.reset + +# default values + +num_cores = 2 +l1_cache_size_bytes = 32768 +l1_cache_assoc = 2 +l1_cache_latency = 3 +l2_cache_size_bytes = 1048576 +l2_cache_assoc = 16 +l2_cache_latency = 15 +num_memories = 2 +memory_size_mb = 1024 +num_dma = 0 +use_map = false +map_levels = 4 +protocol = "MOESI_hammer" + +# check for overrides + + +for i in 0..$*.size-1 do + if $*[i] == "-c" + protocol = $*[i+1] + i = i+1 + elsif $*[i] == "-p" + num_cores = $*[i+1].to_i + i = i+1 + elsif $*[i] == "-m" + num_memories = $*[i+1].to_i + i = i+1 + elsif $*[i] == "-s" + memory_size_mb = $*[i+1].to_i + i = i + 1 + elsif $*[i] == "-U" + use_map = $*[i+1] + i = i + 1 + elsif $*[i] == "-C" + l1_cache_size_bytes = $*[i+1].to_i + i = i + 1 + elsif $*[i] == "-A" + l1_cache_assoc = $*[i+1].to_i + i = i + 1 + elsif $*[i] == "-M" + map_levels = $*[i+1].to_i + i = i + 1 + elsif $*[i] == "-D" + num_dma = $*[i+1].to_i + i = i + 1 + end +end + +net_ports = Array.new +iface_ports = Array.new + +assert(protocol == "MOESI_hammer", __FILE__ + " cannot be used with protocol " + protocol) + +require protocol+".rb" + +num_cores.times { |n| + icache = SetAssociativeCache.new("l1i_"+n.to_s, + l1_cache_size_bytes, + l1_cache_latency, + l1_cache_assoc, + "PSEUDO_LRU") + dcache = SetAssociativeCache.new("l1d_"+n.to_s, + l1_cache_size_bytes, + l1_cache_latency, + l1_cache_assoc, + "PSEUDO_LRU") + l2cache = SetAssociativeCache.new("l2u_"+n.to_s, + l2_cache_size_bytes, + l2_cache_latency, + l2_cache_assoc, + "PSEUDO_LRU") + sequencer = Sequencer.new("Sequencer_"+n.to_s, icache, dcache) + iface_ports << sequencer + net_ports << MOESI_hammer_CacheController.new("L1CacheController_"+n.to_s, + "L1Cache", + icache, + dcache, + l2cache, + sequencer) +} +num_memories.times { |n| + directory = DirectoryMemory.new("DirectoryMemory_"+n.to_s, memory_size_mb/num_memories) + memory_control = MemoryControl.new("MemoryControl_"+n.to_s) + net_ports << MOESI_hammer_DirectoryController.new("DirectoryController_"+n.to_s, + "Directory", + directory, + memory_control) +} +num_dma.times { |n| + dma_sequencer = DMASequencer.new("DMASequencer_"+n.to_s) + iface_ports << dma_sequencer + net_ports << MOESI_hammer_DMAController.new("DMAController_"+n.to_s, "DMA", dma_sequencer) +} + +topology = CrossbarTopology.new("theTopology", net_ports) +on_chip_net = Network.new("theNetwork", topology) + +RubySystem.init(iface_ports, on_chip_net) diff --git a/src/mem/ruby/config/MOESI_hammer.rb b/src/mem/ruby/config/MOESI_hammer.rb new file mode 100644 index 000000000..d3735028b --- /dev/null +++ b/src/mem/ruby/config/MOESI_hammer.rb @@ -0,0 +1,41 @@ + +require "util.rb" + +class MOESI_hammer_CacheController < L1CacheController + attr :cache + def initialize(obj_name, mach_type, icache, dcache, l2cache, sequencer) + super(obj_name, mach_type, [icache, dcache, l2cache], sequencer) + @icache = icache + @dcache = dcache + @l2cache = l2cache + end + def argv() + vec = super() + vec += " icache " + @icache.obj_name + vec += " dcache " + @dcache.obj_name + vec += " l2cache " + @l2cache.obj_name + vec += " issue_latency "+issue_latency.to_s + vec += " cache_response_latency "+cache_response_latency.to_s + end + +end + +class MOESI_hammer_DirectoryController < DirectoryController + def initialize(obj_name, mach_type, directory, memory_control) + super(obj_name, mach_type, directory, memory_control) + end + def argv() + vec = super() + vec += " memory_controller_latency "+memory_controller_latency.to_s + end +end + +class MOESI_hammer_DMAController < DMAController + def initialize(obj_name, mach_type, dma_sequencer) + super(obj_name, mach_type, dma_sequencer) + end + def argv() + vec = super + vec += " request_latency "+request_latency.to_s + end +end diff --git a/src/mem/ruby/config/TwoLevel_SplitL1UnifiedL2.rb b/src/mem/ruby/config/TwoLevel_SplitL1UnifiedL2.rb index a4a1982f4..a8ef1eceb 100644 --- a/src/mem/ruby/config/TwoLevel_SplitL1UnifiedL2.rb +++ b/src/mem/ruby/config/TwoLevel_SplitL1UnifiedL2.rb @@ -27,7 +27,7 @@ memory_size_mb = 1024 num_dma = 1 #default protocol -protocol = ""#"MESI_CMP_directory" +protocol = "MOESI_CMP_directory" # check for overrides diff --git a/src/mem/ruby/libruby.cc b/src/mem/ruby/libruby.cc index e4e302eba..b9a72d071 100644 --- a/src/mem/ruby/libruby.cc +++ b/src/mem/ruby/libruby.cc @@ -66,6 +66,12 @@ ostream& operator<<(ostream& out, const RubyRequestType& obj) return out; } +ostream& operator<<(std::ostream& out, const RubyRequest& obj) +{ + out << hex << "0x" << obj.paddr << flush; + return out; +} + vector<string> tokenizeString(string str, string delims) { vector<string> tokens; diff --git a/src/mem/ruby/libruby.hh b/src/mem/ruby/libruby.hh index 8f1aa8098..4c50611c1 100644 --- a/src/mem/ruby/libruby.hh +++ b/src/mem/ruby/libruby.hh @@ -39,6 +39,8 @@ struct RubyRequest { {} }; +std::ostream& operator<<(std::ostream& out, const RubyRequest& obj); + /** * Initialize the system. cfg_file is a Ruby-lang configuration script */ diff --git a/src/mem/ruby/network/Network.cc b/src/mem/ruby/network/Network.cc index 984ec7ca8..ac785f632 100644 --- a/src/mem/ruby/network/Network.cc +++ b/src/mem/ruby/network/Network.cc @@ -1,3 +1,30 @@ +/* + * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ #include "mem/protocol/MachineType.hh" #include "mem/ruby/network/Network.hh" diff --git a/src/mem/ruby/network/garnet-fixed-pipeline/CreditLink_d.hh b/src/mem/ruby/network/garnet-fixed-pipeline/CreditLink_d.hh index 387ed0bc1..c554d7216 100644 --- a/src/mem/ruby/network/garnet-fixed-pipeline/CreditLink_d.hh +++ b/src/mem/ruby/network/garnet-fixed-pipeline/CreditLink_d.hh @@ -1,9 +1,33 @@ /* - * CreditLink_d.hh + * Copyright (c) 2008 Princeton University + * All rights reserved. * - * Niket Agarwal, Princeton University + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. * - * */ + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Niket Agarwal + */ + #ifndef CREDIT_LINK_D_H #define CREDIT_LINK_D_H diff --git a/src/mem/ruby/network/garnet-fixed-pipeline/GarnetNetwork_d.cc b/src/mem/ruby/network/garnet-fixed-pipeline/GarnetNetwork_d.cc index 51393b576..df643e800 100644 --- a/src/mem/ruby/network/garnet-fixed-pipeline/GarnetNetwork_d.cc +++ b/src/mem/ruby/network/garnet-fixed-pipeline/GarnetNetwork_d.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood + * Copyright (c) 2008 Princeton University * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -24,14 +24,9 @@ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/* - * GarnetNetwork_d.cc * - * Niket Agarwal, Princeton University - * - * */ + * Authors: Niket Agarwal + */ #include "mem/ruby/network/garnet-fixed-pipeline/GarnetNetwork_d.hh" #include "mem/protocol/MachineType.hh" diff --git a/src/mem/ruby/network/garnet-fixed-pipeline/GarnetNetwork_d.hh b/src/mem/ruby/network/garnet-fixed-pipeline/GarnetNetwork_d.hh index f4b809443..997f5e374 100644 --- a/src/mem/ruby/network/garnet-fixed-pipeline/GarnetNetwork_d.hh +++ b/src/mem/ruby/network/garnet-fixed-pipeline/GarnetNetwork_d.hh @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood + * Copyright (c) 2008 Princeton University * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -24,14 +24,9 @@ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/* - * GarnetNetwork_d.hh * - * Niket Agarwal, Princeton University - * - * */ + * Authors: Niket Agarwal + */ #ifndef GARNETNETWORK_D_H #define GARNETNETWORK_D_H diff --git a/src/mem/ruby/network/garnet-fixed-pipeline/InputUnit_d.cc b/src/mem/ruby/network/garnet-fixed-pipeline/InputUnit_d.cc index 0ae32de13..7f344b0b7 100644 --- a/src/mem/ruby/network/garnet-fixed-pipeline/InputUnit_d.cc +++ b/src/mem/ruby/network/garnet-fixed-pipeline/InputUnit_d.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood + * Copyright (c) 2008 Princeton University * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -24,14 +24,9 @@ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/* - * InputUnit_d.C * - * Niket Agarwal, Princeton University - * - * */ + * Authors: Niket Agarwal + */ #include "mem/ruby/network/garnet-fixed-pipeline/InputUnit_d.hh" #include "mem/ruby/network/garnet-fixed-pipeline/Router_d.hh" diff --git a/src/mem/ruby/network/garnet-fixed-pipeline/InputUnit_d.hh b/src/mem/ruby/network/garnet-fixed-pipeline/InputUnit_d.hh index a59ac89d8..beee79b3e 100644 --- a/src/mem/ruby/network/garnet-fixed-pipeline/InputUnit_d.hh +++ b/src/mem/ruby/network/garnet-fixed-pipeline/InputUnit_d.hh @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood + * Copyright (c) 2008 Princeton University * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -24,14 +24,9 @@ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/* - * InputUnit_d.hh * - * Niket Agarwal, Princeton University - * - * */ + * Authors: Niket Agarwal + */ #ifndef INPUT_UNIT_D_H #define INPUT_UNIT_D_H diff --git a/src/mem/ruby/network/garnet-fixed-pipeline/NetworkHeader.hh b/src/mem/ruby/network/garnet-fixed-pipeline/NetworkHeader.hh index a69dbf107..62ed9a12c 100644 --- a/src/mem/ruby/network/garnet-fixed-pipeline/NetworkHeader.hh +++ b/src/mem/ruby/network/garnet-fixed-pipeline/NetworkHeader.hh @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood + * Copyright (c) 2008 Princeton University * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -24,14 +24,9 @@ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/* - * NetworkHeader.hh * - * Niket Agarwal, Princeton University - * - * */ + * Authors: Niket Agarwal + */ #ifndef NETWORK_HEADER_H #define NETWORK_HEADER_H diff --git a/src/mem/ruby/network/garnet-fixed-pipeline/NetworkInterface_d.cc b/src/mem/ruby/network/garnet-fixed-pipeline/NetworkInterface_d.cc index 3377ffd1d..c31b76d62 100644 --- a/src/mem/ruby/network/garnet-fixed-pipeline/NetworkInterface_d.cc +++ b/src/mem/ruby/network/garnet-fixed-pipeline/NetworkInterface_d.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood + * Copyright (c) 2008 Princeton University * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -24,14 +24,9 @@ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/* - * NetworkInterface_d.cc * - * Niket Agarwal, Princeton University - * - * */ + * Authors: Niket Agarwal + */ #include "mem/ruby/network/garnet-fixed-pipeline/NetworkInterface_d.hh" #include "mem/ruby/buffers/MessageBuffer.hh" diff --git a/src/mem/ruby/network/garnet-fixed-pipeline/NetworkInterface_d.hh b/src/mem/ruby/network/garnet-fixed-pipeline/NetworkInterface_d.hh index 625226254..12b8d57e1 100644 --- a/src/mem/ruby/network/garnet-fixed-pipeline/NetworkInterface_d.hh +++ b/src/mem/ruby/network/garnet-fixed-pipeline/NetworkInterface_d.hh @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood + * Copyright (c) 2008 Princeton University * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -24,14 +24,9 @@ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/* - * NetworkInterface_d.hh * - * Niket Agarwal, Princeton University - * - * */ + * Authors: Niket Agarwal + */ #ifndef NET_INTERFACE_D_H #define NET_INTERFACE_D_H diff --git a/src/mem/ruby/network/garnet-fixed-pipeline/NetworkLink_d.cc b/src/mem/ruby/network/garnet-fixed-pipeline/NetworkLink_d.cc index 8382d331f..dc3c73b0c 100644 --- a/src/mem/ruby/network/garnet-fixed-pipeline/NetworkLink_d.cc +++ b/src/mem/ruby/network/garnet-fixed-pipeline/NetworkLink_d.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood + * Copyright (c) 2008 Princeton University * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -24,14 +24,9 @@ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/* - * NetworkLink_d.cc * - * Niket Agarwal, Princeton University - * - * */ + * Authors: Niket Agarwal + */ #include "mem/ruby/network/garnet-fixed-pipeline/NetworkLink_d.hh" #include "mem/ruby/network/garnet-flexible-pipeline/NetworkConfig.hh" diff --git a/src/mem/ruby/network/garnet-fixed-pipeline/NetworkLink_d.hh b/src/mem/ruby/network/garnet-fixed-pipeline/NetworkLink_d.hh index 90fb9f6dc..fed8afbd3 100644 --- a/src/mem/ruby/network/garnet-fixed-pipeline/NetworkLink_d.hh +++ b/src/mem/ruby/network/garnet-fixed-pipeline/NetworkLink_d.hh @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood + * Copyright (c) 2008 Princeton University * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -24,14 +24,9 @@ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/* - * NetworkLink_d.hh * - * Niket Agarwal, Princeton University - * - * */ + * Authors: Niket Agarwal + */ #ifndef NETWORK_LINK_D_H #define NETWORK_LINK_D_H diff --git a/src/mem/ruby/network/garnet-fixed-pipeline/OutVcState_d.cc b/src/mem/ruby/network/garnet-fixed-pipeline/OutVcState_d.cc index 69e3ae377..42d9af861 100644 --- a/src/mem/ruby/network/garnet-fixed-pipeline/OutVcState_d.cc +++ b/src/mem/ruby/network/garnet-fixed-pipeline/OutVcState_d.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood + * Copyright (c) 2008 Princeton University * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -24,14 +24,9 @@ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/* - * OutVCState_d.cc * - * Niket Agarwal, Princeton University - * - * */ + * Authors: Niket Agarwal + */ #include "mem/ruby/network/garnet-fixed-pipeline/OutVcState_d.hh" #include "mem/ruby/network/garnet-flexible-pipeline/NetworkConfig.hh" diff --git a/src/mem/ruby/network/garnet-fixed-pipeline/OutVcState_d.hh b/src/mem/ruby/network/garnet-fixed-pipeline/OutVcState_d.hh index dc64b8504..fe6b5fc79 100644 --- a/src/mem/ruby/network/garnet-fixed-pipeline/OutVcState_d.hh +++ b/src/mem/ruby/network/garnet-fixed-pipeline/OutVcState_d.hh @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood + * Copyright (c) 2008 Princeton University * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -24,14 +24,9 @@ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/* - * OutVCState_d.hh * - * Niket Agarwal, Princeton University - * - * */ + * Authors: Niket Agarwal + */ #ifndef OUT_VC_STATE_D_H #define OUT_VC_STATE_D_H diff --git a/src/mem/ruby/network/garnet-fixed-pipeline/OutputUnit_d.cc b/src/mem/ruby/network/garnet-fixed-pipeline/OutputUnit_d.cc index eb2450897..e672009c9 100644 --- a/src/mem/ruby/network/garnet-fixed-pipeline/OutputUnit_d.cc +++ b/src/mem/ruby/network/garnet-fixed-pipeline/OutputUnit_d.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood + * Copyright (c) 2008 Princeton University * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -24,14 +24,9 @@ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/* - * OutputUnit_d.cc * - * Niket Agarwal, Princeton University - * - * */ + * Authors: Niket Agarwal + */ #include "mem/ruby/network/garnet-fixed-pipeline/OutputUnit_d.hh" #include "mem/ruby/network/garnet-fixed-pipeline/Router_d.hh" diff --git a/src/mem/ruby/network/garnet-fixed-pipeline/OutputUnit_d.hh b/src/mem/ruby/network/garnet-fixed-pipeline/OutputUnit_d.hh index 78f46d1b5..beeab8c7f 100644 --- a/src/mem/ruby/network/garnet-fixed-pipeline/OutputUnit_d.hh +++ b/src/mem/ruby/network/garnet-fixed-pipeline/OutputUnit_d.hh @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood + * Copyright (c) 2008 Princeton University * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -24,14 +24,9 @@ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/* - * OutputUnit_d.hh * - * Niket Agarwal, Princeton University - * - * */ + * Authors: Niket Agarwal + */ #ifndef OUTPUT_UNIT_D_H #define OUTPUT_UNIT_D_H diff --git a/src/mem/ruby/network/garnet-fixed-pipeline/Router_d.cc b/src/mem/ruby/network/garnet-fixed-pipeline/Router_d.cc index 161e6ecff..5334de7b9 100644 --- a/src/mem/ruby/network/garnet-fixed-pipeline/Router_d.cc +++ b/src/mem/ruby/network/garnet-fixed-pipeline/Router_d.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood + * Copyright (c) 2008 Princeton University * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -24,14 +24,9 @@ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/* - * Router_d.cc * - * Niket Agarwal, Princeton University - * - * */ + * Authors: Niket Agarwal + */ #include "mem/ruby/network/garnet-fixed-pipeline/Router_d.hh" #include "mem/ruby/network/garnet-fixed-pipeline/GarnetNetwork_d.hh" diff --git a/src/mem/ruby/network/garnet-fixed-pipeline/Router_d.hh b/src/mem/ruby/network/garnet-fixed-pipeline/Router_d.hh index 23a8681d9..f9af1abfb 100644 --- a/src/mem/ruby/network/garnet-fixed-pipeline/Router_d.hh +++ b/src/mem/ruby/network/garnet-fixed-pipeline/Router_d.hh @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood + * Copyright (c) 2008 Princeton University * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -24,14 +24,10 @@ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Niket Agarwal */ -/* - * Router_d.hh - * - * Niket Agarwal, Princeton University - * - * */ #ifndef ROUTER_D_H #define ROUTER_D_H diff --git a/src/mem/ruby/network/garnet-fixed-pipeline/RoutingUnit_d.cc b/src/mem/ruby/network/garnet-fixed-pipeline/RoutingUnit_d.cc index 488741055..9f12ac9cc 100644 --- a/src/mem/ruby/network/garnet-fixed-pipeline/RoutingUnit_d.cc +++ b/src/mem/ruby/network/garnet-fixed-pipeline/RoutingUnit_d.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood + * Copyright (c) 2008 Princeton University * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -24,14 +24,9 @@ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/* - * Routingunit_d.C * - * Niket Agarwal, Princeton University - * - * */ + * Authors: Niket Agarwal + */ #include "mem/ruby/network/garnet-fixed-pipeline/RoutingUnit_d.hh" #include "mem/ruby/network/garnet-fixed-pipeline/Router_d.hh" diff --git a/src/mem/ruby/network/garnet-fixed-pipeline/RoutingUnit_d.hh b/src/mem/ruby/network/garnet-fixed-pipeline/RoutingUnit_d.hh index 091ee90ef..33c9f3cc4 100644 --- a/src/mem/ruby/network/garnet-fixed-pipeline/RoutingUnit_d.hh +++ b/src/mem/ruby/network/garnet-fixed-pipeline/RoutingUnit_d.hh @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood + * Copyright (c) 2008 Princeton University * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -24,14 +24,9 @@ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/* - * Routerunit_d.hh * - * Niket Agarwal, Princeton University - * - * */ + * Authors: Niket Agarwal + */ #ifndef ROUTING_UNIT_D_H #define ROUTING_UNIT_D_H diff --git a/src/mem/ruby/network/garnet-fixed-pipeline/SWallocator_d.cc b/src/mem/ruby/network/garnet-fixed-pipeline/SWallocator_d.cc index dd0378305..c7308597a 100644 --- a/src/mem/ruby/network/garnet-fixed-pipeline/SWallocator_d.cc +++ b/src/mem/ruby/network/garnet-fixed-pipeline/SWallocator_d.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood + * Copyright (c) 2008 Princeton University * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -24,14 +24,9 @@ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/* - * SWallocator_d.cc * - * Niket Agarwal, Princeton University - * - * */ + * Authors: Niket Agarwal + */ #include "mem/ruby/network/garnet-fixed-pipeline/SWallocator_d.hh" #include "mem/ruby/network/garnet-fixed-pipeline/Router_d.hh" diff --git a/src/mem/ruby/network/garnet-fixed-pipeline/SWallocator_d.hh b/src/mem/ruby/network/garnet-fixed-pipeline/SWallocator_d.hh index b1867df7f..f0ec5d77e 100644 --- a/src/mem/ruby/network/garnet-fixed-pipeline/SWallocator_d.hh +++ b/src/mem/ruby/network/garnet-fixed-pipeline/SWallocator_d.hh @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood + * Copyright (c) 2008 Princeton University * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -24,14 +24,9 @@ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/* - * SWallocator_d.hh * - * Niket Agarwal, Princeton University - * - * */ + * Authors: Niket Agarwal + */ #ifndef SW_ALLOCATOR_D_H #define SW_ALLOCATOR_D_H diff --git a/src/mem/ruby/network/garnet-fixed-pipeline/Switch_d.cc b/src/mem/ruby/network/garnet-fixed-pipeline/Switch_d.cc index e1ca64864..11a196906 100644 --- a/src/mem/ruby/network/garnet-fixed-pipeline/Switch_d.cc +++ b/src/mem/ruby/network/garnet-fixed-pipeline/Switch_d.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood + * Copyright (c) 2008 Princeton University * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -24,14 +24,9 @@ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/* - * Switch_d.C * - * Niket Agarwal, Princeton University - * - * */ + * Authors: Niket Agarwal + */ #include "mem/ruby/network/garnet-fixed-pipeline/Switch_d.hh" #include "mem/ruby/network/garnet-fixed-pipeline/Router_d.hh" diff --git a/src/mem/ruby/network/garnet-fixed-pipeline/Switch_d.hh b/src/mem/ruby/network/garnet-fixed-pipeline/Switch_d.hh index 2e2f524a0..936972714 100644 --- a/src/mem/ruby/network/garnet-fixed-pipeline/Switch_d.hh +++ b/src/mem/ruby/network/garnet-fixed-pipeline/Switch_d.hh @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood + * Copyright (c) 2008 Princeton University * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -24,14 +24,9 @@ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/* - * Switch_d.hh * - * Niket Agarwal, Princeton University - * - * */ + * Authors: Niket Agarwal + */ #ifndef SWITCH_D_H #define SWITCH_D_H diff --git a/src/mem/ruby/network/garnet-fixed-pipeline/VCallocator_d.cc b/src/mem/ruby/network/garnet-fixed-pipeline/VCallocator_d.cc index 810aea175..4150907d1 100644 --- a/src/mem/ruby/network/garnet-fixed-pipeline/VCallocator_d.cc +++ b/src/mem/ruby/network/garnet-fixed-pipeline/VCallocator_d.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood + * Copyright (c) 2008 Princeton University * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -24,14 +24,9 @@ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/* - * VCallocator_d.cc * - * Niket Agarwal, Princeton University - * - * */ + * Authors: Niket Agarwal + */ #include "mem/ruby/network/garnet-flexible-pipeline/NetworkConfig.hh" #include "mem/ruby/network/garnet-fixed-pipeline/VCallocator_d.hh" diff --git a/src/mem/ruby/network/garnet-fixed-pipeline/VCallocator_d.hh b/src/mem/ruby/network/garnet-fixed-pipeline/VCallocator_d.hh index 41e317bff..ad3c2c95f 100644 --- a/src/mem/ruby/network/garnet-fixed-pipeline/VCallocator_d.hh +++ b/src/mem/ruby/network/garnet-fixed-pipeline/VCallocator_d.hh @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood + * Copyright (c) 2008 Princeton University * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -24,14 +24,9 @@ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/* - * VCallocator_d.hh * - * Niket Agarwal, Princeton University - * - * */ + * Authors: Niket Agarwal + */ #ifndef VC_ALLOCATOR_D_H #define VC_ALLOCATOR_D_H diff --git a/src/mem/ruby/network/garnet-fixed-pipeline/VirtualChannel_d.cc b/src/mem/ruby/network/garnet-fixed-pipeline/VirtualChannel_d.cc index 2e4473a29..5ce3ca4e5 100644 --- a/src/mem/ruby/network/garnet-fixed-pipeline/VirtualChannel_d.cc +++ b/src/mem/ruby/network/garnet-fixed-pipeline/VirtualChannel_d.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood + * Copyright (c) 2008 Princeton University * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -24,14 +24,9 @@ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/* - * VirtualChannel_d.C * - * Niket Agarwal, Princeton University - * - * */ + * Authors: Niket Agarwal + */ #include "mem/ruby/network/garnet-fixed-pipeline/VirtualChannel_d.hh" diff --git a/src/mem/ruby/network/garnet-fixed-pipeline/VirtualChannel_d.hh b/src/mem/ruby/network/garnet-fixed-pipeline/VirtualChannel_d.hh index 4ac1898e2..2d81cb7e3 100644 --- a/src/mem/ruby/network/garnet-fixed-pipeline/VirtualChannel_d.hh +++ b/src/mem/ruby/network/garnet-fixed-pipeline/VirtualChannel_d.hh @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood + * Copyright (c) 2008 Princeton University * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -24,14 +24,9 @@ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/* - * VirtualChannel_d.hh * - * Niket Agarwal, Princeton University - * - * */ + * Authors: Niket Agarwal + */ #ifndef VIRTUAL_CHANNEL_D_H #define VIRTUAL_CHANNEL_D_H diff --git a/src/mem/ruby/network/garnet-fixed-pipeline/flitBuffer_d.cc b/src/mem/ruby/network/garnet-fixed-pipeline/flitBuffer_d.cc index f3ddca0f2..fa189a8cc 100644 --- a/src/mem/ruby/network/garnet-fixed-pipeline/flitBuffer_d.cc +++ b/src/mem/ruby/network/garnet-fixed-pipeline/flitBuffer_d.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood + * Copyright (c) 2008 Princeton University * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -24,14 +24,9 @@ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/* - * flitBuffer_d.C * - * Niket Agarwal, Princeton University - * - * */ + * Authors: Niket Agarwal + */ #include "mem/ruby/network/garnet-fixed-pipeline/flitBuffer_d.hh" diff --git a/src/mem/ruby/network/garnet-fixed-pipeline/flitBuffer_d.hh b/src/mem/ruby/network/garnet-fixed-pipeline/flitBuffer_d.hh index 70a47d5f6..2edea9d76 100644 --- a/src/mem/ruby/network/garnet-fixed-pipeline/flitBuffer_d.hh +++ b/src/mem/ruby/network/garnet-fixed-pipeline/flitBuffer_d.hh @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood + * Copyright (c) 2008 Princeton University * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -24,14 +24,9 @@ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/* - * flitBuffer_d.hh * - * Niket Agarwal, Princeton University - * - * */ + * Authors: Niket Agarwal + */ #ifndef FLIT_BUFFER_D_H #define FLIT_BUFFER_D_H diff --git a/src/mem/ruby/network/garnet-fixed-pipeline/flit_d.cc b/src/mem/ruby/network/garnet-fixed-pipeline/flit_d.cc index 3defb8029..15e0b0394 100644 --- a/src/mem/ruby/network/garnet-fixed-pipeline/flit_d.cc +++ b/src/mem/ruby/network/garnet-fixed-pipeline/flit_d.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood + * Copyright (c) 2008 Princeton University * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -24,14 +24,9 @@ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/* - * flit_d.C * - * Niket Agarwal, Princeton University - * - * */ + * Authors: Niket Agarwal + */ #include "mem/ruby/network/garnet-fixed-pipeline/flit_d.hh" diff --git a/src/mem/ruby/network/garnet-fixed-pipeline/flit_d.hh b/src/mem/ruby/network/garnet-fixed-pipeline/flit_d.hh index 6f64f4940..39f04052d 100644 --- a/src/mem/ruby/network/garnet-fixed-pipeline/flit_d.hh +++ b/src/mem/ruby/network/garnet-fixed-pipeline/flit_d.hh @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood + * Copyright (c) 2008 Princeton University * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -24,15 +24,9 @@ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/* - * flit_d.hh * - * Niket Agarwal, Princeton University - * - * */ - + * Authors: Niket Agarwal + */ #ifndef FLIT_D_H #define FLIT_D_H diff --git a/src/mem/ruby/network/garnet-flexible-pipeline/FlexibleConsumer.hh b/src/mem/ruby/network/garnet-flexible-pipeline/FlexibleConsumer.hh index f8bf6b949..82179ec21 100644 --- a/src/mem/ruby/network/garnet-flexible-pipeline/FlexibleConsumer.hh +++ b/src/mem/ruby/network/garnet-flexible-pipeline/FlexibleConsumer.hh @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood + * Copyright (c) 2008 Princeton University * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -24,14 +24,10 @@ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Niket Agarwal */ -/* - * FlexibleConsumer.hh - * - * Niket Agarwal, Princeton University - * - * */ #ifndef FLEXIBLE_CONSUMER_H #define FLEXIBLE_CONSUMER_H diff --git a/src/mem/ruby/network/garnet-flexible-pipeline/GarnetNetwork.cc b/src/mem/ruby/network/garnet-flexible-pipeline/GarnetNetwork.cc index e56f5b5e8..5a6b610f9 100644 --- a/src/mem/ruby/network/garnet-flexible-pipeline/GarnetNetwork.cc +++ b/src/mem/ruby/network/garnet-flexible-pipeline/GarnetNetwork.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood + * Copyright (c) 2008 Princeton University * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -24,14 +24,9 @@ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/* - * GarnetNetwork.cc * - * Niket Agarwal, Princeton University - * - * */ + * Authors: Niket Agarwal + */ #include "mem/ruby/network/garnet-flexible-pipeline/GarnetNetwork.hh" #include "mem/protocol/MachineType.hh" diff --git a/src/mem/ruby/network/garnet-flexible-pipeline/GarnetNetwork.hh b/src/mem/ruby/network/garnet-flexible-pipeline/GarnetNetwork.hh index 194fef778..c0e4ac6e4 100644 --- a/src/mem/ruby/network/garnet-flexible-pipeline/GarnetNetwork.hh +++ b/src/mem/ruby/network/garnet-flexible-pipeline/GarnetNetwork.hh @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood + * Copyright (c) 2008 Princeton University * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -24,14 +24,9 @@ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/* - * GarnetNetwork.hh * - * Niket Agarwal, Princeton University - * - * */ + * Authors: Niket Agarwal + */ #ifndef GARNET_NETWORK_H #define GARNET_NETWORK_H diff --git a/src/mem/ruby/network/garnet-flexible-pipeline/InVcState.cc b/src/mem/ruby/network/garnet-flexible-pipeline/InVcState.cc index cecaf867e..7fdff46b9 100644 --- a/src/mem/ruby/network/garnet-flexible-pipeline/InVcState.cc +++ b/src/mem/ruby/network/garnet-flexible-pipeline/InVcState.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood + * Copyright (c) 2008 Princeton University * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -24,14 +24,9 @@ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/* - * InVCState.C * - * Niket Agarwal, Princeton University - * - * */ + * Authors: Niket Agarwal + */ #include "mem/ruby/network/garnet-flexible-pipeline/InVcState.hh" diff --git a/src/mem/ruby/network/garnet-flexible-pipeline/InVcState.hh b/src/mem/ruby/network/garnet-flexible-pipeline/InVcState.hh index b7005efea..67ff6b459 100644 --- a/src/mem/ruby/network/garnet-flexible-pipeline/InVcState.hh +++ b/src/mem/ruby/network/garnet-flexible-pipeline/InVcState.hh @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood + * Copyright (c) 2008 Princeton University * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -24,15 +24,9 @@ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/* * - * InVCState.hh - * - * Niket Agarwal, Princeton University - * - * */ + * Authors: Niket Agarwal + */ #ifndef IN_VC_STATE_H #define IN_VC_STATE_H diff --git a/src/mem/ruby/network/garnet-flexible-pipeline/NetworkConfig.hh b/src/mem/ruby/network/garnet-flexible-pipeline/NetworkConfig.hh index 0a450c002..2080ef022 100644 --- a/src/mem/ruby/network/garnet-flexible-pipeline/NetworkConfig.hh +++ b/src/mem/ruby/network/garnet-flexible-pipeline/NetworkConfig.hh @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood + * Copyright (c) 2008 Princeton University * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -24,16 +24,14 @@ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Niket Agarwal */ /* - * NetworkConfig.hh - * - * Description: This header file is used to define all configuration parameters required by the interconnection network. - * - * Niket Agarwal, Princeton University - * - * */ + * This header file is used to define all configuration parameters + * required by the interconnection network. + */ #ifndef NETWORKCONFIG_H #define NETWORKCONFIG_H diff --git a/src/mem/ruby/network/garnet-flexible-pipeline/NetworkInterface.cc b/src/mem/ruby/network/garnet-flexible-pipeline/NetworkInterface.cc index 597c942b7..4af5b296f 100644 --- a/src/mem/ruby/network/garnet-flexible-pipeline/NetworkInterface.cc +++ b/src/mem/ruby/network/garnet-flexible-pipeline/NetworkInterface.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood + * Copyright (c) 2008 Princeton University * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -24,14 +24,9 @@ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/* - * NetworkInterface.cc * - * Niket Agarwal, Princeton University - * - * */ + * Authors: Niket Agarwal + */ #include "mem/ruby/network/garnet-flexible-pipeline/NetworkInterface.hh" #include "mem/ruby/buffers/MessageBuffer.hh" diff --git a/src/mem/ruby/network/garnet-flexible-pipeline/NetworkInterface.hh b/src/mem/ruby/network/garnet-flexible-pipeline/NetworkInterface.hh index af4b1d4eb..8444658ea 100644 --- a/src/mem/ruby/network/garnet-flexible-pipeline/NetworkInterface.hh +++ b/src/mem/ruby/network/garnet-flexible-pipeline/NetworkInterface.hh @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood + * Copyright (c) 2008 Princeton University * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -24,14 +24,10 @@ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Niket Agarwal */ -/* - * NetworkInterface.hh - * - * Niket Agarwal, Princeton University - * - * */ #ifndef NET_INTERFACE_H #define NET_INTERFACE_H diff --git a/src/mem/ruby/network/garnet-flexible-pipeline/NetworkLink.cc b/src/mem/ruby/network/garnet-flexible-pipeline/NetworkLink.cc index ddc92d44c..598c9e2a4 100644 --- a/src/mem/ruby/network/garnet-flexible-pipeline/NetworkLink.cc +++ b/src/mem/ruby/network/garnet-flexible-pipeline/NetworkLink.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood + * Copyright (c) 2008 Princeton University * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -24,14 +24,9 @@ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/* - * NetworkLink.cc * - * Niket Agarwal, Princeton University - * - * */ + * Authors: Niket Agarwal + */ #include "mem/ruby/network/garnet-flexible-pipeline/NetworkLink.hh" #include "mem/ruby/network/garnet-flexible-pipeline/NetworkConfig.hh" diff --git a/src/mem/ruby/network/garnet-flexible-pipeline/NetworkLink.hh b/src/mem/ruby/network/garnet-flexible-pipeline/NetworkLink.hh index 6cc35b39d..9f5640a2e 100644 --- a/src/mem/ruby/network/garnet-flexible-pipeline/NetworkLink.hh +++ b/src/mem/ruby/network/garnet-flexible-pipeline/NetworkLink.hh @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood + * Copyright (c) 2008 Princeton University * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -24,14 +24,10 @@ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Niket Agarwal */ -/* - * NetworkLink.hh - * - * Niket Agarwal, Princeton University - * - * */ #ifndef NETWORK_LINK_H #define NETWORK_LINK_H diff --git a/src/mem/ruby/network/garnet-flexible-pipeline/OutVcState.cc b/src/mem/ruby/network/garnet-flexible-pipeline/OutVcState.cc index 9a95971eb..a00dd19c1 100644 --- a/src/mem/ruby/network/garnet-flexible-pipeline/OutVcState.cc +++ b/src/mem/ruby/network/garnet-flexible-pipeline/OutVcState.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood + * Copyright (c) 2008 Princeton University * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -24,14 +24,9 @@ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/* - * OutVCState.C * - * Niket Agarwal, Princeton University - * - * */ + * Authors: Niket Agarwal + */ #include "mem/ruby/network/garnet-flexible-pipeline/OutVcState.hh" diff --git a/src/mem/ruby/network/garnet-flexible-pipeline/OutVcState.hh b/src/mem/ruby/network/garnet-flexible-pipeline/OutVcState.hh index cb05826dc..ba68bf2db 100644 --- a/src/mem/ruby/network/garnet-flexible-pipeline/OutVcState.hh +++ b/src/mem/ruby/network/garnet-flexible-pipeline/OutVcState.hh @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood + * Copyright (c) 2008 Princeton University * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -24,14 +24,9 @@ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/* - * OutVCState.hh * - * Niket Agarwal, Princeton University - * - * */ + * Authors: Niket Agarwal + */ #ifndef OUT_VC_STATE_H #define OUT_VC_STATE_H diff --git a/src/mem/ruby/network/garnet-flexible-pipeline/Router.cc b/src/mem/ruby/network/garnet-flexible-pipeline/Router.cc index ea32e938d..628f19349 100644 --- a/src/mem/ruby/network/garnet-flexible-pipeline/Router.cc +++ b/src/mem/ruby/network/garnet-flexible-pipeline/Router.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood + * Copyright (c) 2008 Princeton University * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -24,14 +24,9 @@ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/* - * Router.cc * - * Niket Agarwal, Princeton University - * - * */ + * Authors: Niket Agarwal + */ #include "mem/ruby/network/garnet-flexible-pipeline/Router.hh" #include "mem/ruby/slicc_interface/NetworkMessage.hh" diff --git a/src/mem/ruby/network/garnet-flexible-pipeline/Router.hh b/src/mem/ruby/network/garnet-flexible-pipeline/Router.hh index f3cf0036d..69d405ad4 100644 --- a/src/mem/ruby/network/garnet-flexible-pipeline/Router.hh +++ b/src/mem/ruby/network/garnet-flexible-pipeline/Router.hh @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood + * Copyright (c) 2008 Princeton University * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -24,14 +24,9 @@ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/* - * Router.hh * - * Niket Agarwal, Princeton University - * - * */ + * Authors: Niket Agarwal + */ #ifndef ROUTER_H #define ROUTER_H diff --git a/src/mem/ruby/network/garnet-flexible-pipeline/VCarbiter.cc b/src/mem/ruby/network/garnet-flexible-pipeline/VCarbiter.cc index 271d6dd38..9064cc4a2 100644 --- a/src/mem/ruby/network/garnet-flexible-pipeline/VCarbiter.cc +++ b/src/mem/ruby/network/garnet-flexible-pipeline/VCarbiter.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood + * Copyright (c) 2008 Princeton University * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -24,14 +24,9 @@ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/* - * VCarbiter.C * - * Niket Agarwal, Princeton University - * - * */ + * Authors: Niket Agarwal + */ #include "mem/ruby/network/garnet-flexible-pipeline/VCarbiter.hh" #include "mem/ruby/network/garnet-flexible-pipeline/Router.hh" diff --git a/src/mem/ruby/network/garnet-flexible-pipeline/VCarbiter.hh b/src/mem/ruby/network/garnet-flexible-pipeline/VCarbiter.hh index 96a03b8dc..7f7e5e814 100644 --- a/src/mem/ruby/network/garnet-flexible-pipeline/VCarbiter.hh +++ b/src/mem/ruby/network/garnet-flexible-pipeline/VCarbiter.hh @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood + * Copyright (c) 2008 Princeton University * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -24,14 +24,9 @@ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/* - * VCarbiter.hh * - * Niket Agarwal, Princeton University - * - * */ + * Authors: Niket Agarwal + */ #ifndef VC_ARBITER_H #define VC_ARBITER_H diff --git a/src/mem/ruby/network/garnet-flexible-pipeline/flit.cc b/src/mem/ruby/network/garnet-flexible-pipeline/flit.cc index 51b8af6c6..549726348 100644 --- a/src/mem/ruby/network/garnet-flexible-pipeline/flit.cc +++ b/src/mem/ruby/network/garnet-flexible-pipeline/flit.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood + * Copyright (c) 2008 Princeton University * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -24,14 +24,9 @@ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/* - * flit.C * - * Niket Agarwal, Princeton University - * - * */ + * Authors: Niket Agarwal + */ #include "mem/ruby/network/garnet-flexible-pipeline/flit.hh" diff --git a/src/mem/ruby/network/garnet-flexible-pipeline/flit.hh b/src/mem/ruby/network/garnet-flexible-pipeline/flit.hh index aeac2e63b..a2e628443 100644 --- a/src/mem/ruby/network/garnet-flexible-pipeline/flit.hh +++ b/src/mem/ruby/network/garnet-flexible-pipeline/flit.hh @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood + * Copyright (c) 2008 Princeton University * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -24,14 +24,9 @@ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/* - * flit.hh * - * Niket Agarwal, Princeton University - * - * */ + * Authors: Niket Agarwal + */ #include "mem/ruby/network/garnet-fixed-pipeline/NetworkHeader.hh" #include "mem/ruby/slicc_interface/Message.hh" diff --git a/src/mem/ruby/network/garnet-flexible-pipeline/flitBuffer.cc b/src/mem/ruby/network/garnet-flexible-pipeline/flitBuffer.cc index a0bb71c9d..c68f8c78b 100644 --- a/src/mem/ruby/network/garnet-flexible-pipeline/flitBuffer.cc +++ b/src/mem/ruby/network/garnet-flexible-pipeline/flitBuffer.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood + * Copyright (c) 2008 Princeton University * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -24,14 +24,9 @@ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/* - * flitBuffer.C * - * Niket Agarwal, Princeton University - * - * */ + * Authors: Niket Agarwal + */ #include "mem/ruby/network/garnet-flexible-pipeline/flitBuffer.hh" diff --git a/src/mem/ruby/network/garnet-flexible-pipeline/flitBuffer.hh b/src/mem/ruby/network/garnet-flexible-pipeline/flitBuffer.hh index 006ba60bd..c722e161c 100644 --- a/src/mem/ruby/network/garnet-flexible-pipeline/flitBuffer.hh +++ b/src/mem/ruby/network/garnet-flexible-pipeline/flitBuffer.hh @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood + * Copyright (c) 2008 Princeton University * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -24,14 +24,9 @@ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/* - * flitBuffer.hh * - * Niket Agarwal, Princeton University - * - * */ + * Authors: Niket Agarwal + */ #ifndef FLIT_BUFFER_H #define FLIT_BUFFER_H diff --git a/src/mem/ruby/network/orion/power_utils.cc b/src/mem/ruby/network/orion/power_utils.cc index bc69c3cc7..358e13c6f 100644 --- a/src/mem/ruby/network/orion/power_utils.cc +++ b/src/mem/ruby/network/orion/power_utils.cc @@ -30,6 +30,7 @@ #include <cmath> #include <cstdio> +#include "base/types.hh" #include "mem/ruby/network/orion/parm_technology.hh" #include "mem/ruby/network/orion/power_utils.hh" @@ -39,11 +40,11 @@ static char h_tab[256] = {0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4, 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8}; -static unsigned SIM_power_Hamming_slow( unsigned long int old_val, unsigned long int new_val, unsigned long int mask ) +static uint32_t SIM_power_Hamming_slow( uint64_t old_val, uint64_t new_val, uint64_t mask ) { /* old slow code, I don't understand the new fast code though */ - /* unsigned long int dist; - unsigned Hamming = 0; + /* uint64_t dist; + uint32_t Hamming = 0; dist = ( old_val ^ new_val ) & mask; mask = (mask >> 1) + 1; @@ -58,7 +59,7 @@ static unsigned SIM_power_Hamming_slow( unsigned long int old_val, unsigned long #define TWO(k) (BIGONE << (k)) #define CYCL(k) (BIGNONE/(1 + (TWO(TWO(k))))) #define BSUM(x,k) ((x)+=(x) >> TWO(k), (x) &= CYCL(k)) - unsigned long int x; + uint64_t x; x = (old_val ^ new_val) & mask; x = (x & CYCL(0)) + ((x>>TWO(0)) & CYCL(0)); @@ -74,7 +75,7 @@ static unsigned SIM_power_Hamming_slow( unsigned long int old_val, unsigned long int SIM_power_init(void) { - unsigned i; + uint32_t i; /* initialize Hamming distance table */ for (i = 0; i < 256; i++) @@ -84,14 +85,16 @@ int SIM_power_init(void) } -/* assume unsigned long int is unsigned64_t */ -unsigned SIM_power_Hamming(unsigned long int old_val, unsigned long int new_val, unsigned long int mask) + +uint32_t +SIM_power_Hamming(uint64_t old_val, uint64_t new_val, uint64_t mask) { - union { - unsigned long int x; - char id[8]; - } u; - unsigned rval; + union { + uint64_t x; + uint64_t id[8]; + } u; + + uint32_t rval; u.x = (old_val ^ new_val) & mask; @@ -108,10 +111,12 @@ unsigned SIM_power_Hamming(unsigned long int old_val, unsigned long int new_val, } -unsigned SIM_power_Hamming_group(unsigned long int d1_new, unsigned long int d1_old, unsigned long int d2_new, unsigned long int d2_old, unsigned width, unsigned n_grp) +uint32_t +SIM_power_Hamming_group(uint64_t d1_new, uint64_t d1_old, uint64_t d2_new, + uint64_t d2_old, uint32_t width, uint32_t n_grp) { - unsigned rval = 0; - unsigned long int g1_new, g1_old, g2_new, g2_old, mask; + uint32_t rval = 0; + uint64_t g1_new, g1_old, g2_new, g2_old, mask; mask = HAMM_MASK(width); @@ -146,11 +151,12 @@ double logtwo(double x) return log10(x)/log10(2); } -unsigned SIM_power_logtwo(unsigned long int x) +uint32_t +SIM_power_logtwo(uint64_t x) { - unsigned rval = 0; + uint32_t rval = 0; - while (x >> rval && rval < sizeof(unsigned long int) << 3) rval++; + while (x >> rval && rval < sizeof(uint64_t) << 3) rval++; if (x == (BIGONE << rval - 1)) rval--; return rval; diff --git a/src/mem/ruby/network/simple/SimpleNetwork.cc b/src/mem/ruby/network/simple/SimpleNetwork.cc index 497c602d1..adf7ee21e 100644 --- a/src/mem/ruby/network/simple/SimpleNetwork.cc +++ b/src/mem/ruby/network/simple/SimpleNetwork.cc @@ -87,8 +87,10 @@ void SimpleNetwork::init(const vector<string> & argv) m_toNetQueues[node].setSize(m_virtual_networks); m_fromNetQueues[node].setSize(m_virtual_networks); for (int j = 0; j < m_virtual_networks; j++) { - m_toNetQueues[node][j] = new MessageBuffer; - m_fromNetQueues[node][j] = new MessageBuffer; + m_toNetQueues[node][j] = new MessageBuffer( + "toNet node "+int_to_string(node)+" j "+int_to_string(j)); + m_fromNetQueues[node][j] = new MessageBuffer( + "fromNet node "+int_to_string(node)+" j "+int_to_string(j)); } } @@ -124,7 +126,7 @@ SimpleNetwork::~SimpleNetwork() } m_switch_ptr_vector.deletePointers(); m_buffers_to_free.deletePointers(); - delete m_topology_ptr; + // delete m_topology_ptr; } // From a switch to an endpoint node diff --git a/src/mem/slicc/ast/DeclAST.cc b/src/mem/ruby/slicc_interface/RubySlicc_ComponentMapping.cc index 6ccf9a9d6..4d37b0007 100644 --- a/src/mem/slicc/ast/DeclAST.cc +++ b/src/mem/ruby/slicc_interface/RubySlicc_ComponentMapping.cc @@ -27,13 +27,12 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -/* - * DeclAST.C - * - * Description: See DeclAST.hh - * - * $Id$ - * - */ -#include "mem/slicc/ast/DeclAST.hh" +#include "mem/ruby/slicc_interface/RubySlicc_ComponentMapping.hh" +#include "mem/ruby/system/CacheMemory.hh" + +int getNumberOfLastLevelCaches() +{ + return CacheMemory::numberOfLastLevelCaches(); +} + diff --git a/src/mem/ruby/slicc_interface/RubySlicc_ComponentMapping.hh b/src/mem/ruby/slicc_interface/RubySlicc_ComponentMapping.hh index 159c33815..69424c414 100644 --- a/src/mem/ruby/slicc_interface/RubySlicc_ComponentMapping.hh +++ b/src/mem/ruby/slicc_interface/RubySlicc_ComponentMapping.hh @@ -61,6 +61,15 @@ #define MACHINETYPE_L3CACHE_ENUM MachineType_NUM #endif +#ifdef MACHINETYPE_DMA +#define MACHINETYPE_DMA_ENUM MachineType_DMA +#else +#define MACHINETYPE_DMA_ENUM MachineType_NUM +#endif + +// used to determine the number of acks to wait for +int getNumberOfLastLevelCaches(); + // used to determine the home directory // returns a value between 0 and total_directories_within_the_system inline @@ -81,7 +90,7 @@ MachineID map_Address_to_Directory(const Address &addr) inline MachineID map_Address_to_DMA(const Address & addr) { - MachineID dma = {MachineType_DMA, 0}; + MachineID dma = {MACHINETYPE_DMA_ENUM, 0}; return dma; } diff --git a/src/mem/ruby/slicc_interface/SConscript b/src/mem/ruby/slicc_interface/SConscript index 2b20892ba..6ba614fa9 100644 --- a/src/mem/ruby/slicc_interface/SConscript +++ b/src/mem/ruby/slicc_interface/SConscript @@ -35,3 +35,4 @@ if not env['RUBY']: Source('AbstractCacheEntry.cc') Source('RubySlicc_Profiler_interface.cc') +Source('RubySlicc_ComponentMapping.cc') diff --git a/src/mem/ruby/system/CacheMemory.cc b/src/mem/ruby/system/CacheMemory.cc new file mode 100644 index 000000000..cf3e094ad --- /dev/null +++ b/src/mem/ruby/system/CacheMemory.cc @@ -0,0 +1,483 @@ +/* + * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "mem/ruby/system/CacheMemory.hh" + +int CacheMemory::m_num_last_level_caches = 0; +MachineType CacheMemory::m_last_level_machine_type = MachineType_FIRST; + +// Output operator declaration +//ostream& operator<<(ostream& out, const CacheMemory<ENTRY>& obj); + +// ******************* Definitions ******************* + +// Output operator definition +ostream& operator<<(ostream& out, const CacheMemory& obj) +{ + obj.print(out); + out << flush; + return out; +} + + +// **************************************************************** + +CacheMemory::CacheMemory(const string & name) + : m_cache_name(name) +{ + m_profiler_ptr = new CacheProfiler(name); +} + +void CacheMemory::init(const vector<string> & argv) +{ + int cache_size = -1; + string policy; + + m_num_last_level_caches = + MachineType_base_count(MachineType_FIRST); + m_controller = NULL; + for (uint32 i=0; i<argv.size(); i+=2) { + if (argv[i] == "size") { + cache_size = atoi(argv[i+1].c_str()); + } else if (argv[i] == "latency") { + m_latency = atoi(argv[i+1].c_str()); + } else if (argv[i] == "assoc") { + m_cache_assoc = atoi(argv[i+1].c_str()); + } else if (argv[i] == "replacement_policy") { + policy = argv[i+1]; + } else if (argv[i] == "controller") { + m_controller = RubySystem::getController(argv[i+1]); + if (m_last_level_machine_type < m_controller->getMachineType()) { + m_num_last_level_caches = + MachineType_base_count(m_controller->getMachineType()); + m_last_level_machine_type = + m_controller->getMachineType(); + } + } else { + cerr << "WARNING: CacheMemory: Unknown configuration parameter: " << argv[i] << endl; + } + } + + int num_lines = cache_size/RubySystem::getBlockSizeBytes(); + m_cache_num_sets = num_lines / m_cache_assoc; + m_cache_num_set_bits = log_int(m_cache_num_sets); + assert(m_cache_num_set_bits > 0); + + if(policy == "PSEUDO_LRU") + m_replacementPolicy_ptr = new PseudoLRUPolicy(m_cache_num_sets, m_cache_assoc); + else if (policy == "LRU") + m_replacementPolicy_ptr = new LRUPolicy(m_cache_num_sets, m_cache_assoc); + else + assert(false); + + m_cache.setSize(m_cache_num_sets); + m_locked.setSize(m_cache_num_sets); + for (int i = 0; i < m_cache_num_sets; i++) { + m_cache[i].setSize(m_cache_assoc); + m_locked[i].setSize(m_cache_assoc); + for (int j = 0; j < m_cache_assoc; j++) { + m_cache[i][j] = NULL; + m_locked[i][j] = -1; + } + } +} + +CacheMemory::~CacheMemory() +{ + if(m_replacementPolicy_ptr != NULL) + delete m_replacementPolicy_ptr; + delete m_profiler_ptr; + for (int i = 0; i < m_cache_num_sets; i++) { + for (int j = 0; j < m_cache_assoc; j++) { + delete m_cache[i][j]; + } + } +} + +int +CacheMemory::numberOfLastLevelCaches() +{ + return m_num_last_level_caches; +} + + +void CacheMemory::printConfig(ostream& out) +{ + out << "Cache config: " << m_cache_name << endl; + if (m_controller != NULL) + out << " controller: " << m_controller->getName() << endl; + out << " cache_associativity: " << m_cache_assoc << endl; + out << " num_cache_sets_bits: " << m_cache_num_set_bits << endl; + const int cache_num_sets = 1 << m_cache_num_set_bits; + out << " num_cache_sets: " << cache_num_sets << endl; + out << " cache_set_size_bytes: " << cache_num_sets * RubySystem::getBlockSizeBytes() << endl; + out << " cache_set_size_Kbytes: " + << double(cache_num_sets * RubySystem::getBlockSizeBytes()) / (1<<10) << endl; + out << " cache_set_size_Mbytes: " + << double(cache_num_sets * RubySystem::getBlockSizeBytes()) / (1<<20) << endl; + out << " cache_size_bytes: " + << cache_num_sets * RubySystem::getBlockSizeBytes() * m_cache_assoc << endl; + out << " cache_size_Kbytes: " + << double(cache_num_sets * RubySystem::getBlockSizeBytes() * m_cache_assoc) / (1<<10) << endl; + out << " cache_size_Mbytes: " + << double(cache_num_sets * RubySystem::getBlockSizeBytes() * m_cache_assoc) / (1<<20) << endl; +} + +// PRIVATE METHODS + +// convert a Address to its location in the cache +Index CacheMemory::addressToCacheSet(const Address& address) const +{ + assert(address == line_address(address)); + return address.bitSelect(RubySystem::getBlockSizeBits(), RubySystem::getBlockSizeBits() + m_cache_num_set_bits-1); +} + +// Given a cache index: returns the index of the tag in a set. +// returns -1 if the tag is not found. +int CacheMemory::findTagInSet(Index cacheSet, const Address& tag) const +{ + assert(tag == line_address(tag)); + // search the set for the tags + m5::hash_map<Address, int>::const_iterator it = m_tag_index.find(tag); + if (it != m_tag_index.end()) + if (m_cache[cacheSet][it->second]->m_Permission != AccessPermission_NotPresent) + return it->second; + return -1; // Not found +} + +// Given a cache index: returns the index of the tag in a set. +// returns -1 if the tag is not found. +int CacheMemory::findTagInSetIgnorePermissions(Index cacheSet, const Address& tag) const +{ + assert(tag == line_address(tag)); + // search the set for the tags + m5::hash_map<Address, int>::const_iterator it = m_tag_index.find(tag); + if (it != m_tag_index.end()) + return it->second; + return -1; // Not found +} + +// PUBLIC METHODS +bool CacheMemory::tryCacheAccess(const Address& address, + CacheRequestType type, + DataBlock*& data_ptr) +{ + assert(address == line_address(address)); + DEBUG_EXPR(CACHE_COMP, HighPrio, address); + Index cacheSet = addressToCacheSet(address); + int loc = findTagInSet(cacheSet, address); + if(loc != -1){ // Do we even have a tag match? + AbstractCacheEntry* entry = m_cache[cacheSet][loc]; + m_replacementPolicy_ptr->touch(cacheSet, loc, g_eventQueue_ptr->getTime()); + data_ptr = &(entry->getDataBlk()); + + if(entry->m_Permission == AccessPermission_Read_Write) { + return true; + } + if ((entry->m_Permission == AccessPermission_Read_Only) && + (type == CacheRequestType_LD || type == CacheRequestType_IFETCH)) { + return true; + } + // The line must not be accessible + } + data_ptr = NULL; + return false; +} + +bool CacheMemory::testCacheAccess(const Address& address, + CacheRequestType type, + DataBlock*& data_ptr) +{ + assert(address == line_address(address)); + DEBUG_EXPR(CACHE_COMP, HighPrio, address); + Index cacheSet = addressToCacheSet(address); + int loc = findTagInSet(cacheSet, address); + if(loc != -1){ // Do we even have a tag match? + AbstractCacheEntry* entry = m_cache[cacheSet][loc]; + m_replacementPolicy_ptr->touch(cacheSet, loc, g_eventQueue_ptr->getTime()); + data_ptr = &(entry->getDataBlk()); + + return (m_cache[cacheSet][loc]->m_Permission != AccessPermission_NotPresent); + } + data_ptr = NULL; + return false; +} + +// tests to see if an address is present in the cache +bool CacheMemory::isTagPresent(const Address& address) const +{ + assert(address == line_address(address)); + Index cacheSet = addressToCacheSet(address); + int location = findTagInSet(cacheSet, address); + + if (location == -1) { + // We didn't find the tag + DEBUG_EXPR(CACHE_COMP, LowPrio, address); + DEBUG_MSG(CACHE_COMP, LowPrio, "No tag match"); + return false; + } + DEBUG_EXPR(CACHE_COMP, LowPrio, address); + DEBUG_MSG(CACHE_COMP, LowPrio, "found"); + return true; +} + +// Returns true if there is: +// a) a tag match on this address or there is +// b) an unused line in the same cache "way" +bool CacheMemory::cacheAvail(const Address& address) const +{ + assert(address == line_address(address)); + + Index cacheSet = addressToCacheSet(address); + + for (int i=0; i < m_cache_assoc; i++) { + AbstractCacheEntry* entry = m_cache[cacheSet][i]; + if (entry != NULL) { + if (entry->m_Address == address || // Already in the cache + entry->m_Permission == AccessPermission_NotPresent) { // We found an empty entry + return true; + } + } else { + return true; + } + } + return false; +} + +void CacheMemory::allocate(const Address& address, AbstractCacheEntry* entry) +{ + assert(address == line_address(address)); + assert(!isTagPresent(address)); + assert(cacheAvail(address)); + DEBUG_EXPR(CACHE_COMP, HighPrio, address); + + // Find the first open slot + Index cacheSet = addressToCacheSet(address); + for (int i=0; i < m_cache_assoc; i++) { + if (m_cache[cacheSet][i] == NULL || + m_cache[cacheSet][i]->m_Permission == AccessPermission_NotPresent) { + m_cache[cacheSet][i] = entry; // Init entry + m_cache[cacheSet][i]->m_Address = address; + m_cache[cacheSet][i]->m_Permission = AccessPermission_Invalid; + m_locked[cacheSet][i] = -1; + m_tag_index[address] = i; + + m_replacementPolicy_ptr->touch(cacheSet, i, g_eventQueue_ptr->getTime()); + + return; + } + } + ERROR_MSG("Allocate didn't find an available entry"); +} + +void CacheMemory::deallocate(const Address& address) +{ + assert(address == line_address(address)); + assert(isTagPresent(address)); + DEBUG_EXPR(CACHE_COMP, HighPrio, address); + Index cacheSet = addressToCacheSet(address); + int location = findTagInSet(cacheSet, address); + if (location != -1){ + delete m_cache[cacheSet][location]; + m_cache[cacheSet][location] = NULL; + m_locked[cacheSet][location] = -1; + m_tag_index.erase(address); + } +} + +// Returns with the physical address of the conflicting cache line +Address CacheMemory::cacheProbe(const Address& address) const +{ + assert(address == line_address(address)); + assert(!cacheAvail(address)); + + Index cacheSet = addressToCacheSet(address); + return m_cache[cacheSet][m_replacementPolicy_ptr->getVictim(cacheSet)]->m_Address; +} + +// looks an address up in the cache +AbstractCacheEntry& CacheMemory::lookup(const Address& address) +{ + assert(address == line_address(address)); + Index cacheSet = addressToCacheSet(address); + int loc = findTagInSet(cacheSet, address); + assert(loc != -1); + return *m_cache[cacheSet][loc]; +} + +// looks an address up in the cache +const AbstractCacheEntry& CacheMemory::lookup(const Address& address) const +{ + assert(address == line_address(address)); + Index cacheSet = addressToCacheSet(address); + int loc = findTagInSet(cacheSet, address); + assert(loc != -1); + return *m_cache[cacheSet][loc]; +} + +AccessPermission CacheMemory::getPermission(const Address& address) const +{ + assert(address == line_address(address)); + return lookup(address).m_Permission; +} + +void CacheMemory::changePermission(const Address& address, AccessPermission new_perm) +{ + assert(address == line_address(address)); + lookup(address).m_Permission = new_perm; + Index cacheSet = addressToCacheSet(address); + int loc = findTagInSet(cacheSet, address); + m_locked[cacheSet][loc] = -1; + assert(getPermission(address) == new_perm); +} + +// Sets the most recently used bit for a cache block +void CacheMemory::setMRU(const Address& address) +{ + Index cacheSet; + + cacheSet = addressToCacheSet(address); + m_replacementPolicy_ptr->touch(cacheSet, + findTagInSet(cacheSet, address), + g_eventQueue_ptr->getTime()); +} + +void CacheMemory::profileMiss(const CacheMsg & msg) +{ + m_profiler_ptr->addStatSample(msg.getType(), msg.getAccessMode(), + msg.getSize(), msg.getPrefetch()); +} + +void CacheMemory::recordCacheContents(CacheRecorder& tr) const +{ + for (int i = 0; i < m_cache_num_sets; i++) { + for (int j = 0; j < m_cache_assoc; j++) { + AccessPermission perm = m_cache[i][j]->m_Permission; + CacheRequestType request_type = CacheRequestType_NULL; + if (perm == AccessPermission_Read_Only) { + if (m_is_instruction_only_cache) { + request_type = CacheRequestType_IFETCH; + } else { + request_type = CacheRequestType_LD; + } + } else if (perm == AccessPermission_Read_Write) { + request_type = CacheRequestType_ST; + } + + if (request_type != CacheRequestType_NULL) { + // tr.addRecord(m_chip_ptr->getID(), m_cache[i][j].m_Address, + // Address(0), request_type, m_replacementPolicy_ptr->getLastAccess(i, j)); + } + } + } +} + +void CacheMemory::print(ostream& out) const +{ + out << "Cache dump: " << m_cache_name << endl; + for (int i = 0; i < m_cache_num_sets; i++) { + for (int j = 0; j < m_cache_assoc; j++) { + if (m_cache[i][j] != NULL) { + out << " Index: " << i + << " way: " << j + << " entry: " << *m_cache[i][j] << endl; + } else { + out << " Index: " << i + << " way: " << j + << " entry: NULL" << endl; + } + } + } +} + +void CacheMemory::printData(ostream& out) const +{ + out << "printData() not supported" << endl; +} + +void CacheMemory::clearStats() const +{ + m_profiler_ptr->clearStats(); +} + +void CacheMemory::printStats(ostream& out) const +{ + m_profiler_ptr->printStats(out); +} + +void CacheMemory::getMemoryValue(const Address& addr, char* value, + unsigned int size_in_bytes ){ + AbstractCacheEntry& entry = lookup(line_address(addr)); + unsigned int startByte = addr.getAddress() - line_address(addr).getAddress(); + for(unsigned int i=0; i<size_in_bytes; ++i){ + value[i] = entry.getDataBlk().getByte(i + startByte); + } +} + +void CacheMemory::setMemoryValue(const Address& addr, char* value, + unsigned int size_in_bytes ){ + AbstractCacheEntry& entry = lookup(line_address(addr)); + unsigned int startByte = addr.getAddress() - line_address(addr).getAddress(); + assert(size_in_bytes > 0); + for(unsigned int i=0; i<size_in_bytes; ++i){ + entry.getDataBlk().setByte(i + startByte, value[i]); + } + + // entry = lookup(line_address(addr)); +} + +void +CacheMemory::setLocked(const Address& address, int context) +{ + assert(address == line_address(address)); + Index cacheSet = addressToCacheSet(address); + int loc = findTagInSet(cacheSet, address); + assert(loc != -1); + m_locked[cacheSet][loc] = context; +} + +void +CacheMemory::clearLocked(const Address& address) +{ + assert(address == line_address(address)); + Index cacheSet = addressToCacheSet(address); + int loc = findTagInSet(cacheSet, address); + assert(loc != -1); + m_locked[cacheSet][loc] = -1; +} + +bool +CacheMemory::isLocked(const Address& address, int context) +{ + assert(address == line_address(address)); + Index cacheSet = addressToCacheSet(address); + int loc = findTagInSet(cacheSet, address); + assert(loc != -1); + return m_locked[cacheSet][loc] == context; +} + diff --git a/src/mem/ruby/system/CacheMemory.hh b/src/mem/ruby/system/CacheMemory.hh index 7268189ea..8b84f33ec 100644 --- a/src/mem/ruby/system/CacheMemory.hh +++ b/src/mem/ruby/system/CacheMemory.hh @@ -54,6 +54,7 @@ #include "mem/ruby/slicc_interface/AbstractController.hh" #include "mem/ruby/profiler/CacheProfiler.hh" #include "mem/protocol/CacheMsg.hh" +#include "base/hashmap.hh" #include <vector> class CacheMemory { @@ -104,6 +105,8 @@ public: AccessPermission getPermission(const Address& address) const; void changePermission(const Address& address, AccessPermission new_perm); + static int numberOfLastLevelCaches(); + int getLatency() const { return m_latency; } // Hook for checkpointing the contents of the cache @@ -169,465 +172,11 @@ private: int m_cache_assoc; static Vector< CacheMemory* > m_all_caches; -}; + + static int m_num_last_level_caches; + static MachineType m_last_level_machine_type; -// Output operator declaration -//ostream& operator<<(ostream& out, const CacheMemory<ENTRY>& obj); - -// ******************* Definitions ******************* - -// Output operator definition -inline -ostream& operator<<(ostream& out, const CacheMemory& obj) -{ - obj.print(out); - out << flush; - return out; -} - - -// **************************************************************** - -inline -CacheMemory::CacheMemory(const string & name) - : m_cache_name(name) -{ - m_profiler_ptr = new CacheProfiler(name); -} - -inline -void CacheMemory::init(const vector<string> & argv) -{ - int cache_size = 0; - string policy; - - m_controller = NULL; - for (uint32 i=0; i<argv.size(); i+=2) { - if (argv[i] == "size_kb") { - cache_size = atoi(argv[i+1].c_str()); - } else if (argv[i] == "latency") { - m_latency = atoi(argv[i+1].c_str()); - } else if (argv[i] == "assoc") { - m_cache_assoc = atoi(argv[i+1].c_str()); - } else if (argv[i] == "replacement_policy") { - policy = argv[i+1]; - } else if (argv[i] == "controller") { - m_controller = RubySystem::getController(argv[i+1]); - } else { - cerr << "WARNING: CacheMemory: Unknown configuration parameter: " << argv[i] << endl; - } - } - - int num_lines = (cache_size*1024)/RubySystem::getBlockSizeBytes(); - m_cache_num_sets = num_lines / m_cache_assoc; - m_cache_num_set_bits = log_int(m_cache_num_sets); - - if(policy == "PSEUDO_LRU") - m_replacementPolicy_ptr = new PseudoLRUPolicy(m_cache_num_sets, m_cache_assoc); - else if (policy == "LRU") - m_replacementPolicy_ptr = new LRUPolicy(m_cache_num_sets, m_cache_assoc); - else - assert(false); - - m_cache.setSize(m_cache_num_sets); - m_locked.setSize(m_cache_num_sets); - for (int i = 0; i < m_cache_num_sets; i++) { - m_cache[i].setSize(m_cache_assoc); - m_locked[i].setSize(m_cache_assoc); - for (int j = 0; j < m_cache_assoc; j++) { - m_cache[i][j] = NULL; - m_locked[i][j] = -1; - } - } -} - -inline -CacheMemory::~CacheMemory() -{ - if(m_replacementPolicy_ptr != NULL) - delete m_replacementPolicy_ptr; -} - -inline -void CacheMemory::printConfig(ostream& out) -{ - out << "Cache config: " << m_cache_name << endl; - if (m_controller != NULL) - out << " controller: " << m_controller->getName() << endl; - out << " cache_associativity: " << m_cache_assoc << endl; - out << " num_cache_sets_bits: " << m_cache_num_set_bits << endl; - const int cache_num_sets = 1 << m_cache_num_set_bits; - out << " num_cache_sets: " << cache_num_sets << endl; - out << " cache_set_size_bytes: " << cache_num_sets * RubySystem::getBlockSizeBytes() << endl; - out << " cache_set_size_Kbytes: " - << double(cache_num_sets * RubySystem::getBlockSizeBytes()) / (1<<10) << endl; - out << " cache_set_size_Mbytes: " - << double(cache_num_sets * RubySystem::getBlockSizeBytes()) / (1<<20) << endl; - out << " cache_size_bytes: " - << cache_num_sets * RubySystem::getBlockSizeBytes() * m_cache_assoc << endl; - out << " cache_size_Kbytes: " - << double(cache_num_sets * RubySystem::getBlockSizeBytes() * m_cache_assoc) / (1<<10) << endl; - out << " cache_size_Mbytes: " - << double(cache_num_sets * RubySystem::getBlockSizeBytes() * m_cache_assoc) / (1<<20) << endl; -} - -// PRIVATE METHODS - -// convert a Address to its location in the cache -inline -Index CacheMemory::addressToCacheSet(const Address& address) const -{ - assert(address == line_address(address)); - return address.bitSelect(RubySystem::getBlockSizeBits(), RubySystem::getBlockSizeBits() + m_cache_num_set_bits-1); -} - -// Given a cache index: returns the index of the tag in a set. -// returns -1 if the tag is not found. -inline -int CacheMemory::findTagInSet(Index cacheSet, const Address& tag) const -{ - assert(tag == line_address(tag)); - // search the set for the tags - m5::hash_map<Address, int>::const_iterator it = m_tag_index.find(tag); - if (it != m_tag_index.end()) - if (m_cache[cacheSet][it->second]->m_Permission != AccessPermission_NotPresent) - return it->second; - return -1; // Not found -} - -// Given a cache index: returns the index of the tag in a set. -// returns -1 if the tag is not found. -inline -int CacheMemory::findTagInSetIgnorePermissions(Index cacheSet, const Address& tag) const -{ - assert(tag == line_address(tag)); - // search the set for the tags - m5::hash_map<Address, int>::const_iterator it = m_tag_index.find(tag); - if (it != m_tag_index.end()) - return it->second; - return -1; // Not found -} - -// PUBLIC METHODS -inline -bool CacheMemory::tryCacheAccess(const Address& address, - CacheRequestType type, - DataBlock*& data_ptr) -{ - assert(address == line_address(address)); - DEBUG_EXPR(CACHE_COMP, HighPrio, address); - Index cacheSet = addressToCacheSet(address); - int loc = findTagInSet(cacheSet, address); - if(loc != -1){ // Do we even have a tag match? - AbstractCacheEntry* entry = m_cache[cacheSet][loc]; - m_replacementPolicy_ptr->touch(cacheSet, loc, g_eventQueue_ptr->getTime()); - data_ptr = &(entry->getDataBlk()); - - if(entry->m_Permission == AccessPermission_Read_Write) { - return true; - } - if ((entry->m_Permission == AccessPermission_Read_Only) && - (type == CacheRequestType_LD || type == CacheRequestType_IFETCH)) { - return true; - } - // The line must not be accessible - } - data_ptr = NULL; - return false; -} - -inline -bool CacheMemory::testCacheAccess(const Address& address, - CacheRequestType type, - DataBlock*& data_ptr) -{ - assert(address == line_address(address)); - DEBUG_EXPR(CACHE_COMP, HighPrio, address); - Index cacheSet = addressToCacheSet(address); - int loc = findTagInSet(cacheSet, address); - if(loc != -1){ // Do we even have a tag match? - AbstractCacheEntry* entry = m_cache[cacheSet][loc]; - m_replacementPolicy_ptr->touch(cacheSet, loc, g_eventQueue_ptr->getTime()); - data_ptr = &(entry->getDataBlk()); - - return (m_cache[cacheSet][loc]->m_Permission != AccessPermission_NotPresent); - } - data_ptr = NULL; - return false; -} - -// tests to see if an address is present in the cache -inline -bool CacheMemory::isTagPresent(const Address& address) const -{ - assert(address == line_address(address)); - Index cacheSet = addressToCacheSet(address); - int location = findTagInSet(cacheSet, address); - - if (location == -1) { - // We didn't find the tag - DEBUG_EXPR(CACHE_COMP, LowPrio, address); - DEBUG_MSG(CACHE_COMP, LowPrio, "No tag match"); - return false; - } - DEBUG_EXPR(CACHE_COMP, LowPrio, address); - DEBUG_MSG(CACHE_COMP, LowPrio, "found"); - return true; -} - -// Returns true if there is: -// a) a tag match on this address or there is -// b) an unused line in the same cache "way" -inline -bool CacheMemory::cacheAvail(const Address& address) const -{ - assert(address == line_address(address)); - - Index cacheSet = addressToCacheSet(address); - - for (int i=0; i < m_cache_assoc; i++) { - AbstractCacheEntry* entry = m_cache[cacheSet][i]; - if (entry != NULL) { - if (entry->m_Address == address || // Already in the cache - entry->m_Permission == AccessPermission_NotPresent) { // We found an empty entry - return true; - } - } else { - return true; - } - } - return false; -} - -inline -void CacheMemory::allocate(const Address& address, AbstractCacheEntry* entry) -{ - assert(address == line_address(address)); - assert(!isTagPresent(address)); - assert(cacheAvail(address)); - DEBUG_EXPR(CACHE_COMP, HighPrio, address); - - // Find the first open slot - Index cacheSet = addressToCacheSet(address); - for (int i=0; i < m_cache_assoc; i++) { - if (m_cache[cacheSet][i] == NULL || - m_cache[cacheSet][i]->m_Permission == AccessPermission_NotPresent) { - m_cache[cacheSet][i] = entry; // Init entry - m_cache[cacheSet][i]->m_Address = address; - m_cache[cacheSet][i]->m_Permission = AccessPermission_Invalid; - m_locked[cacheSet][i] = -1; - m_tag_index[address] = i; - - m_replacementPolicy_ptr->touch(cacheSet, i, g_eventQueue_ptr->getTime()); - - return; - } - } - ERROR_MSG("Allocate didn't find an available entry"); -} - -inline -void CacheMemory::deallocate(const Address& address) -{ - assert(address == line_address(address)); - assert(isTagPresent(address)); - DEBUG_EXPR(CACHE_COMP, HighPrio, address); - Index cacheSet = addressToCacheSet(address); - int location = findTagInSet(cacheSet, address); - if (location != -1){ - delete m_cache[cacheSet][location]; - m_cache[cacheSet][location] = NULL; - m_locked[cacheSet][location] = -1; - m_tag_index.erase(address); - } -} - -// Returns with the physical address of the conflicting cache line -inline -Address CacheMemory::cacheProbe(const Address& address) const -{ - assert(address == line_address(address)); - assert(!cacheAvail(address)); - - Index cacheSet = addressToCacheSet(address); - return m_cache[cacheSet][m_replacementPolicy_ptr->getVictim(cacheSet)]->m_Address; -} - -// looks an address up in the cache -inline -AbstractCacheEntry& CacheMemory::lookup(const Address& address) -{ - assert(address == line_address(address)); - Index cacheSet = addressToCacheSet(address); - int loc = findTagInSet(cacheSet, address); - assert(loc != -1); - return *m_cache[cacheSet][loc]; -} - -// looks an address up in the cache -inline -const AbstractCacheEntry& CacheMemory::lookup(const Address& address) const -{ - assert(address == line_address(address)); - Index cacheSet = addressToCacheSet(address); - int loc = findTagInSet(cacheSet, address); - assert(loc != -1); - return *m_cache[cacheSet][loc]; -} - -inline -AccessPermission CacheMemory::getPermission(const Address& address) const -{ - assert(address == line_address(address)); - return lookup(address).m_Permission; -} - -inline -void CacheMemory::changePermission(const Address& address, AccessPermission new_perm) -{ - assert(address == line_address(address)); - lookup(address).m_Permission = new_perm; - Index cacheSet = addressToCacheSet(address); - int loc = findTagInSet(cacheSet, address); - m_locked[cacheSet][loc] = -1; - assert(getPermission(address) == new_perm); -} - -// Sets the most recently used bit for a cache block -inline -void CacheMemory::setMRU(const Address& address) -{ - Index cacheSet; - - cacheSet = addressToCacheSet(address); - m_replacementPolicy_ptr->touch(cacheSet, - findTagInSet(cacheSet, address), - g_eventQueue_ptr->getTime()); -} - -inline -void CacheMemory::profileMiss(const CacheMsg & msg) -{ - m_profiler_ptr->addStatSample(msg.getType(), msg.getAccessMode(), - msg.getSize(), msg.getPrefetch()); -} - -inline -void CacheMemory::recordCacheContents(CacheRecorder& tr) const -{ - for (int i = 0; i < m_cache_num_sets; i++) { - for (int j = 0; j < m_cache_assoc; j++) { - AccessPermission perm = m_cache[i][j]->m_Permission; - CacheRequestType request_type = CacheRequestType_NULL; - if (perm == AccessPermission_Read_Only) { - if (m_is_instruction_only_cache) { - request_type = CacheRequestType_IFETCH; - } else { - request_type = CacheRequestType_LD; - } - } else if (perm == AccessPermission_Read_Write) { - request_type = CacheRequestType_ST; - } - - if (request_type != CacheRequestType_NULL) { - // tr.addRecord(m_chip_ptr->getID(), m_cache[i][j].m_Address, - // Address(0), request_type, m_replacementPolicy_ptr->getLastAccess(i, j)); - } - } - } -} - -inline -void CacheMemory::print(ostream& out) const -{ - out << "Cache dump: " << m_cache_name << endl; - for (int i = 0; i < m_cache_num_sets; i++) { - for (int j = 0; j < m_cache_assoc; j++) { - if (m_cache[i][j] != NULL) { - out << " Index: " << i - << " way: " << j - << " entry: " << *m_cache[i][j] << endl; - } else { - out << " Index: " << i - << " way: " << j - << " entry: NULL" << endl; - } - } - } -} - -inline -void CacheMemory::printData(ostream& out) const -{ - out << "printData() not supported" << endl; -} - -inline void CacheMemory::clearStats() const -{ - m_profiler_ptr->clearStats(); -} - -inline -void CacheMemory::printStats(ostream& out) const -{ - m_profiler_ptr->printStats(out); -} - -inline -void CacheMemory::getMemoryValue(const Address& addr, char* value, - unsigned int size_in_bytes ){ - AbstractCacheEntry& entry = lookup(line_address(addr)); - unsigned int startByte = addr.getAddress() - line_address(addr).getAddress(); - for(unsigned int i=0; i<size_in_bytes; ++i){ - value[i] = entry.getDataBlk().getByte(i + startByte); - } -} - -inline -void CacheMemory::setMemoryValue(const Address& addr, char* value, - unsigned int size_in_bytes ){ - AbstractCacheEntry& entry = lookup(line_address(addr)); - unsigned int startByte = addr.getAddress() - line_address(addr).getAddress(); - assert(size_in_bytes > 0); - for(unsigned int i=0; i<size_in_bytes; ++i){ - entry.getDataBlk().setByte(i + startByte, value[i]); - } - - // entry = lookup(line_address(addr)); -} - -inline -void -CacheMemory::setLocked(const Address& address, int context) -{ - assert(address == line_address(address)); - Index cacheSet = addressToCacheSet(address); - int loc = findTagInSet(cacheSet, address); - assert(loc != -1); - m_locked[cacheSet][loc] = context; -} - -inline -void -CacheMemory::clearLocked(const Address& address) -{ - assert(address == line_address(address)); - Index cacheSet = addressToCacheSet(address); - int loc = findTagInSet(cacheSet, address); - assert(loc != -1); - m_locked[cacheSet][loc] = -1; -} - -inline -bool -CacheMemory::isLocked(const Address& address, int context) -{ - assert(address == line_address(address)); - Index cacheSet = addressToCacheSet(address); - int loc = findTagInSet(cacheSet, address); - assert(loc != -1); - return m_locked[cacheSet][loc] == context; -} +}; #endif //CACHEMEMORY_H diff --git a/src/mem/ruby/system/DirectoryMemory.cc b/src/mem/ruby/system/DirectoryMemory.cc index 46ebdbab4..9b2a3873c 100644 --- a/src/mem/ruby/system/DirectoryMemory.cc +++ b/src/mem/ruby/system/DirectoryMemory.cc @@ -84,11 +84,14 @@ void DirectoryMemory::init(const vector<string> & argv) DirectoryMemory::~DirectoryMemory() { // free up all the directory entries - for (int i=0;i<m_num_entries;i++) - if (m_entries[i] != NULL) - delete m_entries; - if (m_entries != NULL) + for (uint64 i=0;i<m_num_entries;i++) { + if (m_entries[i] != NULL) { + delete m_entries[i]; + } + } + if (m_entries != NULL) { delete [] m_entries; + } } void DirectoryMemory::printConfig(ostream& out) const diff --git a/src/mem/ruby/system/PersistentTable.cc b/src/mem/ruby/system/PersistentTable.cc new file mode 100644 index 000000000..58b67ea60 --- /dev/null +++ b/src/mem/ruby/system/PersistentTable.cc @@ -0,0 +1,204 @@ + +/* + * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "mem/ruby/system/PersistentTable.hh" +#include "mem/gems_common/util.hh" + +// randomize so that handoffs are not locality-aware +// int persistent_randomize[] = {0, 4, 8, 12, 1, 5, 9, 13, 2, 6, 10, 14, 3, 7, 11, 15}; +// int persistent_randomize[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}; + + +PersistentTable::PersistentTable() +{ + m_map_ptr = new Map<Address, PersistentTableEntry>; +} + +PersistentTable::~PersistentTable() +{ + delete m_map_ptr; + m_map_ptr = NULL; +} + +void PersistentTable::persistentRequestLock(const Address& address, + MachineID locker, + AccessType type) +{ + + // if (locker == m_chip_ptr->getID() ) + // cout << "Chip " << m_chip_ptr->getID() << ": " << llocker + // << " requesting lock for " << address << endl; + + // MachineID locker = (MachineID) persistent_randomize[llocker]; + + assert(address == line_address(address)); + if (!m_map_ptr->exist(address)) { + // Allocate if not present + PersistentTableEntry entry; + entry.m_starving.add(locker); + if (type == AccessType_Write) { + entry.m_request_to_write.add(locker); + } + m_map_ptr->add(address, entry); + } else { + PersistentTableEntry& entry = m_map_ptr->lookup(address); + + // + // Make sure we're not already in the locked set + // + assert(!(entry.m_starving.isElement(locker))); + + entry.m_starving.add(locker); + if (type == AccessType_Write) { + entry.m_request_to_write.add(locker); + } + assert(entry.m_marked.isSubset(entry.m_starving)); + } +} + +void PersistentTable::persistentRequestUnlock(const Address& address, + MachineID unlocker) +{ + // if (unlocker == m_chip_ptr->getID() ) + // cout << "Chip " << m_chip_ptr->getID() << ": " << uunlocker + // << " requesting unlock for " << address << endl; + + // MachineID unlocker = (MachineID) persistent_randomize[uunlocker]; + + assert(address == line_address(address)); + assert(m_map_ptr->exist(address)); + PersistentTableEntry& entry = m_map_ptr->lookup(address); + + // + // Make sure we're in the locked set + // + assert(entry.m_starving.isElement(unlocker)); + assert(entry.m_marked.isSubset(entry.m_starving)); + entry.m_starving.remove(unlocker); + entry.m_marked.remove(unlocker); + entry.m_request_to_write.remove(unlocker); + assert(entry.m_marked.isSubset(entry.m_starving)); + + // Deallocate if empty + if (entry.m_starving.isEmpty()) { + assert(entry.m_marked.isEmpty()); + m_map_ptr->erase(address); + } +} + +bool PersistentTable::okToIssueStarving(const Address& address, + MachineID machId) const +{ + assert(address == line_address(address)); + if (!m_map_ptr->exist(address)) { + // + // No entry present + // + return true; + } else if (m_map_ptr->lookup(address).m_starving.isElement(machId)) { + // + // We can't issue another lockdown until are previous unlock has occurred + // + return false; + } else { + return (m_map_ptr->lookup(address).m_marked.isEmpty()); + } +} + +MachineID PersistentTable::findSmallest(const Address& address) const +{ + assert(address == line_address(address)); + assert(m_map_ptr->exist(address)); + const PersistentTableEntry& entry = m_map_ptr->lookup(address); + return entry.m_starving.smallestElement(); +} + +AccessType PersistentTable::typeOfSmallest(const Address& address) const +{ + assert(address == line_address(address)); + assert(m_map_ptr->exist(address)); + const PersistentTableEntry& entry = m_map_ptr->lookup(address); + if (entry.m_request_to_write.isElement(entry.m_starving.smallestElement())) { + return AccessType_Write; + } else { + return AccessType_Read; + } +} + +void PersistentTable::markEntries(const Address& address) +{ + assert(address == line_address(address)); + if (m_map_ptr->exist(address)) { + PersistentTableEntry& entry = m_map_ptr->lookup(address); + + // + // None should be marked + // + assert(entry.m_marked.isEmpty()); + + // + // Mark all the nodes currently in the table + // + entry.m_marked = entry.m_starving; + } +} + +bool PersistentTable::isLocked(const Address& address) const +{ + assert(address == line_address(address)); + // If an entry is present, it must be locked + return (m_map_ptr->exist(address)); +} + +int PersistentTable::countStarvingForAddress(const Address& address) const +{ + if (m_map_ptr->exist(address)) { + PersistentTableEntry& entry = m_map_ptr->lookup(address); + return (entry.m_starving.count()); + } + else { + return 0; + } +} + +int PersistentTable::countReadStarvingForAddress(const Address& address) const +{ + if (m_map_ptr->exist(address)) { + PersistentTableEntry& entry = m_map_ptr->lookup(address); + return (entry.m_starving.count() - entry.m_request_to_write.count()); + } + else { + return 0; + } +} + +void PersistentTable::print(ostream& out) const +{ +} + diff --git a/src/mem/slicc/ast/InfixOperatorExprAST.hh b/src/mem/ruby/system/PersistentTable.hh index f97ab8805..8cbb48817 100644 --- a/src/mem/slicc/ast/InfixOperatorExprAST.hh +++ b/src/mem/ruby/system/PersistentTable.hh @@ -27,59 +27,76 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -/* - * InfixOperatorExprAST.hh - * - * Description: - * - * $Id: InfixOperatorExprAST.hh,v 3.1 2001/12/12 01:00:19 milo Exp $ - * - */ +#ifndef PersistentTable_H +#define PersistentTable_H -#ifndef INFIXOPERATOREXPRAST_H -#define INFIXOPERATOREXPRAST_H +#include "mem/ruby/common/Global.hh" +#include "mem/gems_common/Map.hh" +#include "mem/ruby/common/Address.hh" +#include "mem/ruby/system/MachineID.hh" +#include "mem/protocol/AccessType.hh" +#include "mem/ruby/common/NetDest.hh" -#include "mem/slicc/slicc_global.hh" -#include "mem/slicc/ast/ExprAST.hh" +class PersistentTableEntry { +public: + void print(ostream& out) const {} + NetDest m_starving; + NetDest m_marked; + NetDest m_request_to_write; +}; -class InfixOperatorExprAST : public ExprAST { +class PersistentTable { public: // Constructors - InfixOperatorExprAST(ExprAST* left_ptr, string* op_ptr, ExprAST* right_ptr); + PersistentTable(); // Destructor - ~InfixOperatorExprAST(); - + ~PersistentTable(); + // Public Methods - Type* generate(string& code) const; + void persistentRequestLock(const Address& address, MachineID locker, AccessType type); + void persistentRequestUnlock(const Address& address, MachineID unlocker); + bool okToIssueStarving(const Address& address, MachineID machID) const; + MachineID findSmallest(const Address& address) const; + AccessType typeOfSmallest(const Address& address) const; + void markEntries(const Address& address); + bool isLocked(const Address& addr) const; + int countStarvingForAddress(const Address& addr) const; + int countReadStarvingForAddress(const Address& addr) const; + + static void printConfig(ostream& out) {} + void print(ostream& out) const; private: // Private Methods // Private copy constructor and assignment operator - InfixOperatorExprAST(const InfixOperatorExprAST& obj); - InfixOperatorExprAST& operator=(const InfixOperatorExprAST& obj); - - // Data Members (m_ prefix) - ExprAST* m_left_ptr; - string* m_op_ptr; - ExprAST* m_right_ptr; + PersistentTable(const PersistentTable& obj); + PersistentTable& operator=(const PersistentTable& obj); + // Data Members (m_prefix) + Map<Address, PersistentTableEntry>* m_map_ptr; }; -// Output operator declaration -ostream& operator<<(ostream& out, const InfixOperatorExprAST& obj); - // ******************* Definitions ******************* // Output operator definition extern inline -ostream& operator<<(ostream& out, const InfixOperatorExprAST& obj) +ostream& operator<<(ostream& out, const PersistentTable& obj) +{ + obj.print(out); + out << flush; + return out; +} + +// Output operator definition +extern inline +ostream& operator<<(ostream& out, const PersistentTableEntry& obj) { obj.print(out); out << flush; return out; } -#endif //INFIXOPERATOREXPRAST_H +#endif //PersistentTable_H diff --git a/src/mem/ruby/system/SConscript b/src/mem/ruby/system/SConscript index 1d8b1e2df..4ca1af114 100644 --- a/src/mem/ruby/system/SConscript +++ b/src/mem/ruby/system/SConscript @@ -35,8 +35,10 @@ if not env['RUBY']: Source('DMASequencer.cc') Source('DirectoryMemory.cc') +Source('CacheMemory.cc') Source('MemoryControl.cc') Source('MemoryNode.cc') +Source('PersistentTable.cc') Source('RubyPort.cc') Source('Sequencer.cc', Werror=False) Source('System.cc') diff --git a/src/mem/ruby/system/Sequencer.hh b/src/mem/ruby/system/Sequencer.hh index 231df01bb..ce53dd8d7 100644 --- a/src/mem/ruby/system/Sequencer.hh +++ b/src/mem/ruby/system/Sequencer.hh @@ -63,6 +63,8 @@ struct SequencerRequest { {} }; +std::ostream& operator<<(std::ostream& out, const SequencerRequest& obj); + class Sequencer : public Consumer, public RubyPort { public: // Constructors diff --git a/src/mem/ruby/system/System.hh b/src/mem/ruby/system/System.hh index 38ef09177..1d36de878 100644 --- a/src/mem/ruby/system/System.hh +++ b/src/mem/ruby/system/System.hh @@ -107,7 +107,10 @@ public: if (m_ports.count(name) != 1){ cerr << "Port " << name << " has " << m_ports.count(name) << " instances" << endl; } - assert(m_ports.count(name) == 1); m_ports[name]->registerHitCallback(hit_callback); return m_ports[name]; } + assert(m_ports.count(name) == 1); + m_ports[name]->registerHitCallback(hit_callback); + return m_ports[name]; + } static Network* getNetwork() { assert(m_network_ptr != NULL); return m_network_ptr; } static Topology* getTopology(const string & name) { assert(m_topologies.count(name) == 1); return m_topologies[name]; } static CacheMemory* getCache(const string & name) { assert(m_caches.count(name) == 1); return m_caches[name]; } diff --git a/src/mem/rubymem.cc b/src/mem/rubymem.cc index 4d9f8051f..74a6e390e 100644 --- a/src/mem/rubymem.cc +++ b/src/mem/rubymem.cc @@ -1,5 +1,6 @@ /* * Copyright (c) 2001-2005 The Regents of The University of Michigan + * Copyright (c) 2009 Advanced Micro Devices, Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -26,6 +27,7 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * Authors: Daniel Sanchez + * Brad Beckmann */ #include <iostream> @@ -35,6 +37,7 @@ #include "base/output.hh" #include "base/str.hh" #include "base/types.hh" +#include "config/the_isa.hh" #include "mem/ruby/common/Debug.hh" #include "mem/ruby/libruby.hh" #include "mem/ruby/system/RubyPort.hh" @@ -55,13 +58,23 @@ RubyMemory::RubyMemory(const Params *p) ruby_clock = p->clock; ruby_phase = p->phase; + ports_per_cpu = p->ports_per_core; + + DPRINTF(Ruby, "creating Ruby Memory from file %s\n", + p->config_file.c_str()); + ifstream config(p->config_file.c_str()); + if (config.good() == false) { + fatal("Did not successfully open %s.\n", p->config_file.c_str()); + } + vector<RubyObjConf> sys_conf; while (!config.eof()) { - char buffer[4096]; + char buffer[65536]; config.getline(buffer, sizeof(buffer)); string line = buffer; + DPRINTF(Ruby, "%s %d\n", line, line.empty()); if (line.empty()) continue; vector<string> tokens; @@ -80,11 +93,27 @@ RubyMemory::RubyMemory(const Params *p) RubySystem::create(sys_conf); + // + // Create the necessary ruby_ports to connect to the sequencers. + // This code should be fixed when the configuration systems are unified + // and the ruby configuration text files no longer exist. Also, + // it would be great to remove the single ruby_hit_callback func with + // separate pointers to particular ports to rubymem. However, functional + // access currently prevent the improvement. + // for (int i = 0; i < params()->num_cpus; i++) { RubyPort *p = RubySystem::getPort(csprintf("Sequencer_%d", i), ruby_hit_callback); ruby_ports.push_back(p); } + + for (int i = 0; i < params()->num_dmas; i++) { + RubyPort *p = RubySystem::getPort(csprintf("DMASequencer_%d", i), + ruby_hit_callback); + ruby_dma_ports.push_back(p); + } + + pio_port = NULL; } void @@ -105,7 +134,6 @@ RubyMemory::init() //g_debug_ptr->setDebugTime(1); //g_debug_ptr->setDebugOutputFile("ruby.debug"); - g_system_ptr->clearStats(); if (ports.size() == 0) { @@ -117,9 +145,18 @@ RubyMemory::init() (*pi)->sendStatusChange(Port::RangeChange); } + for (PortIterator pi = dma_ports.begin(); pi != dma_ports.end(); ++pi) { + if (*pi) + (*pi)->sendStatusChange(Port::RangeChange); + } + + if (pio_port != NULL) { + pio_port->sendStatusChange(Port::RangeChange); + } + //Print stats at exit - RubyExitCallback* rc = new RubyExitCallback(this); - registerExitCallback(rc); + rubyExitCB = new RubyExitCallback(this); + registerExitCallback(rubyExitCB); //Sched RubyEvent, automatically reschedules to advance ruby cycles rubyTickEvent = new RubyEvent(this); @@ -137,37 +174,57 @@ RubyMemory::tick() RubyMemory::~RubyMemory() { -} - -void -RubyMemory::hitCallback(PacketPtr pkt, Port *port) -{ - DPRINTF(MemoryAccess, "Hit callback\n"); - - bool needsResponse = pkt->needsResponse(); - doAtomicAccess(pkt); - - // turn packet around to go back to requester if response expected - if (needsResponse) { - // recvAtomic() should already have turned packet into - // atomic response - assert(pkt->isResponse()); - DPRINTF(MemoryAccess, "Sending packet back over port\n"); - port->sendTiming(pkt); - } else { - delete pkt; - } - DPRINTF(MemoryAccess, "Hit callback done!\n"); + delete g_system_ptr; } Port * RubyMemory::getPort(const std::string &if_name, int idx) { + DPRINTF(Ruby, "getting port %d %s\n", idx, if_name); + DPRINTF(Ruby, + "number of ruby ports %d and dma ports %d\n", + ruby_ports.size(), + ruby_dma_ports.size()); + + // + // By default, getPort will be passed an idx of -1. Of course this is an + // invalid ruby port index and must be a modified + // + if (idx == -1) { + idx = 0; + } + // Accept request for "functional" port for backwards compatibility // with places where this function is called from C++. I'd prefer // to move all these into Python someday. if (if_name == "functional") { - return new Port(csprintf("%s-functional", name()), this); + assert(idx < ruby_ports.size()); + return new Port(csprintf("%s-functional", name()), + this, + ruby_ports[idx]); + } + + // + // if dma port request, allocate the appropriate prot + // + if (if_name == "dma_port") { + assert(idx < ruby_dma_ports.size()); + RubyMemory::Port* dma_port = + new Port(csprintf("%s-dma_port%d", name(), idx), + this, + ruby_dma_ports[idx]); + dma_ports.push_back(dma_port); + return dma_port; + } + + // + // if pio port, ensure that there is only one + // + if (if_name == "pio_port") { + assert(pio_port == NULL); + pio_port = + new RubyMemory::Port("ruby_pio_port", this, NULL); + return pio_port; } if (if_name != "port") { @@ -182,30 +239,68 @@ RubyMemory::getPort(const std::string &if_name, int idx) panic("RubyMemory::getPort: port %d already assigned", idx); } - Port *port = new Port(csprintf("%s-port%d", name(), idx), this); + // + // Currently this code assumes that each cpu has both a + // icache and dcache port and therefore divides by ports per cpu. This will + // be fixed once we unify the configuration systems and Ruby sequencers + // directly support M5 ports. + // + assert(idx/ports_per_cpu < ruby_ports.size()); + Port *port = new Port(csprintf("%s-port%d", name(), idx), + this, + ruby_ports[idx/ports_per_cpu]); ports[idx] = port; return port; } -RubyMemory::Port::Port(const std::string &_name, RubyMemory *_memory) +RubyMemory::Port::Port(const std::string &_name, + RubyMemory *_memory, + RubyPort *_port) : PhysicalMemory::MemoryPort::MemoryPort(_name, _memory) { + DPRINTF(Ruby, "creating port to ruby memory %s\n", _name); ruby_mem = _memory; + ruby_port = _port; } bool RubyMemory::Port::recvTiming(PacketPtr pkt) { - DPRINTF(MemoryAccess, "Timing access caught\n"); + DPRINTF(MemoryAccess, + "Timing access caught for address %#x\n", + pkt->getAddr()); //dsm: based on SimpleTimingPort::recvTiming(pkt); - // If the device is only a slave, it should only be sending - // responses, which should never get nacked. There used to be - // code to hanldle nacks here, but I'm pretty sure it didn't work - // correctly with the drain code, so that would need to be fixed - // if we ever added it back. + // + // In FS mode, ruby memory will receive pio responses from devices and + // it must forward these responses back to the particular CPU. + // + if (pkt->isResponse() != false && isPioAddress(pkt->getAddr()) != false) { + DPRINTF(MemoryAccess, + "Pio Response callback %#x\n", + pkt->getAddr()); + RubyMemory::SenderState *senderState = + safe_cast<RubyMemory::SenderState *>(pkt->senderState); + RubyMemory::Port *port = senderState->port; + + // pop the sender state from the packet + pkt->senderState = senderState->saved; + delete senderState; + + port->sendTiming(pkt); + + return true; + } + + // + // After checking for pio responses, the remainder of packets + // received by ruby should only be M5 requests, which should never + // get nacked. There used to be code to hanldle nacks here, but + // I'm pretty sure it didn't work correctly with the drain code, + // so that would need to be fixed if we ever added it back. + // assert(pkt->isRequest()); if (pkt->memInhibitAsserted()) { @@ -219,6 +314,18 @@ RubyMemory::Port::recvTiming(PacketPtr pkt) // Save the port in the sender state object pkt->senderState = new SenderState(this, pkt->senderState); + // + // Check for pio requests and directly send them to the dedicated + // pio_port. + // + if (isPioAddress(pkt->getAddr()) != false) { + return ruby_mem->pio_port->sendTiming(pkt); + } + + // + // For DMA and CPU requests, translate them to ruby requests before + // sending them to our assigned ruby port. + // RubyRequestType type = RubyRequestType_NULL; Addr pc = 0; if (pkt->isRead()) { @@ -239,7 +346,6 @@ RubyMemory::Port::recvTiming(PacketPtr pkt) RubyAccessMode_Supervisor); // Submit the ruby request - RubyPort *ruby_port = ruby_mem->ruby_ports[pkt->req->contextId()]; int64_t req_id = ruby_port->makeRequest(ruby_request); if (req_id == -1) { RubyMemory::SenderState *senderState = @@ -260,6 +366,12 @@ RubyMemory::Port::recvTiming(PacketPtr pkt) void ruby_hit_callback(int64_t req_id) { + // + // Note: This single fuction can be called by cpu and dma ports, + // as well as the functional port. The functional port prevents + // us from replacing this single function with separate port + // functions. + // typedef map<int64_t, PacketPtr> map_t; map_t &prm = RubyMemory::pending_requests; @@ -278,13 +390,58 @@ ruby_hit_callback(int64_t req_id) pkt->senderState = senderState->saved; delete senderState; - port->ruby_mem->hitCallback(pkt, port); + port->hitCallback(pkt); } void +RubyMemory::Port::hitCallback(PacketPtr pkt) +{ + + bool needsResponse = pkt->needsResponse(); + + DPRINTF(MemoryAccess, "Hit callback needs response %d\n", + needsResponse); + + ruby_mem->doAtomicAccess(pkt); + + // turn packet around to go back to requester if response expected + if (needsResponse) { + // recvAtomic() should already have turned packet into + // atomic response + assert(pkt->isResponse()); + DPRINTF(MemoryAccess, "Sending packet back over port\n"); + sendTiming(pkt); + } else { + delete pkt; + } + DPRINTF(MemoryAccess, "Hit callback done!\n"); +} + +bool RubyMemory::Port::sendTiming(PacketPtr pkt) { schedSendTiming(pkt, curTick + 1); //minimum latency, must be > 0 + return true; +} + +bool +RubyMemory::Port::isPioAddress(Addr addr) +{ + AddrRangeList pioAddrList; + bool snoop = false; + if (ruby_mem->pio_port == NULL) { + return false; + } + + ruby_mem->pio_port->getPeerAddressRanges(pioAddrList, snoop); + for(AddrRangeIter iter = pioAddrList.begin(); iter != pioAddrList.end(); iter++) { + if (addr >= iter->start && addr <= iter->end) { + DPRINTF(MemoryAccess, "Pio request found in %#llx - %#llx range\n", + iter->start, iter->end); + return true; + } + } + return false; } void RubyMemory::printConfigStats() @@ -311,6 +468,17 @@ void RubyMemory::printConfig(std::ostream & out) const { //g_system_ptr->printConfig(out); } +void RubyMemory::serialize(ostream &os) +{ + PhysicalMemory::serialize(os); +} + +void RubyMemory::unserialize(Checkpoint *cp, const string §ion) +{ + DPRINTF(Config, "Ruby memory being restored\n"); + reschedule(rubyTickEvent, curTick + ruby_clock + ruby_phase); + PhysicalMemory::unserialize(cp, section); +} //Python-interface code RubyMemory * diff --git a/src/mem/rubymem.hh b/src/mem/rubymem.hh index e33418a42..2672dcb77 100644 --- a/src/mem/rubymem.hh +++ b/src/mem/rubymem.hh @@ -1,5 +1,6 @@ /* * Copyright (c) 2001-2005 The Regents of The University of Michigan + * Copyright (c) 2009 Advanced Micro Devices, Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -39,23 +40,34 @@ #include "mem/physical.hh" #include "mem/ruby/system/RubyPort.hh" #include "params/RubyMemory.hh" +#include "mem/port.hh" + +class RubyExitCallback; class RubyMemory : public PhysicalMemory { public: std::vector<RubyPort *> ruby_ports; + std::vector<RubyPort *> ruby_dma_ports; class Port : public MemoryPort { friend void ruby_hit_callback(int64_t req_id); RubyMemory *ruby_mem; + RubyPort *ruby_port; public: - Port(const std::string &_name, RubyMemory *_memory); - void sendTiming(PacketPtr pkt); + Port(const std::string &_name, + RubyMemory *_memory, + RubyPort *_port); + bool sendTiming(PacketPtr pkt); + void hitCallback(PacketPtr pkt); protected: virtual bool recvTiming(PacketPtr pkt); + + private: + bool isPioAddress(Addr addr); }; class RubyEvent : public Event @@ -108,8 +120,6 @@ class RubyMemory : public PhysicalMemory //options change & M5 determines the //stats file to use - void hitCallback(PacketPtr pkt, Port *port); - void printStats(std::ostream & out) const; void clearStats(); void printConfig(std::ostream & out) const; @@ -119,9 +129,19 @@ class RubyMemory : public PhysicalMemory private: Tick ruby_clock; Tick ruby_phase; + RubyExitCallback* rubyExitCB; + int ports_per_cpu; public: static std::map<int64_t, PacketPtr> pending_requests; + RubyMemory::Port* pio_port; + + protected: + std::vector<MemoryPort*> dma_ports; + + public: + virtual void serialize(std::ostream &os); + virtual void unserialize(Checkpoint *cp, const std::string §ion); }; void ruby_hit_callback(int64_t); diff --git a/src/mem/slicc/SConscript b/src/mem/slicc/SConscript deleted file mode 100644 index e26ceb979..000000000 --- a/src/mem/slicc/SConscript +++ /dev/null @@ -1,129 +0,0 @@ -# -*- mode:python -*- - -# Copyright (c) 2009 The Hewlett-Packard Development Company -# All rights reserved. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions are -# met: redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer; -# redistributions in binary form must reproduce the above copyright -# notice, this list of conditions and the following disclaimer in the -# documentation and/or other materials provided with the distribution; -# neither the name of the copyright holders nor the names of its -# contributors may be used to endorse or promote products derived from -# this software without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -# -# Authors: Nathan Binkert - -import os -import re -import string -import sys - -from os.path import basename, dirname, exists, expanduser, isdir, isfile -from os.path import join as joinpath - -import SCons - -Import('*') - -if not env['RUBY']: - Return() - -common_dir = Dir('../gems_common') - -# -# Build SLICC -# -slicc_env = env.Clone() -slicc_env['CPPDEFINES'] = '' -slicc_env['CPPPATH'] = Dir('../..') -slicc_env.Append(CCFLAGS=['-g', '-O0']) -slicc_env.Append(CPPDEFINES=['DEBUG', 'TRACING_ON=1']) -slicc_env['LIBS'] = '' -slicc_env['LIBPATH'] = '' -all_slicc_sources = [] -def SliccSource(filename): - if filename.endswith('.ll') or filename.endswith('.yy'): - slicc_env.CXXFile(filename) - filename = filename[:-2] + "cc" - x = slicc_env.StaticObject(filename) - all_slicc_sources.append(x) - return x - -# BE CAREFUL WITH THE ORDER OF FILENAMES HERE. SLICC IS VERY FRAGILE -# BECAUSE IT VIOLATES ESTABLISHED RULES ABOUT HOW YOU'RE ALLOWED TO -# CREATE STATIC OBJECTS. (SLICC HAS DEPENDENCIES DURING STATIC OBJECT -# CONSTRUCTION ACROSS FILES. THAT'S A NO-NO.) WITH THIS FILE ORDER, -# WE GET LUCKY AND OBJECTS GET CONSTRUCTED IN THE RIGHT ORDER. -SliccSource('parser/parser.yy') -SliccSource('parser/lexer.ll') -SliccSource('main.cc') -SliccSource('symbols/Func.cc') -SliccSource('symbols/StateMachine.cc') -SliccSource('symbols/Symbol.cc') -SliccSource('symbols/SymbolTable.cc') -SliccSource('symbols/Transition.cc') -SliccSource('symbols/Type.cc') -SliccSource('symbols/Var.cc') -SliccSource('generator/fileio.cc') -SliccSource('generator/html_gen.cc') -SliccSource('generator/mif_gen.cc') -SliccSource('ast/AST.cc') -SliccSource('ast/ActionDeclAST.cc') -SliccSource('ast/AssignStatementAST.cc') -SliccSource('ast/CheckAllocateStatementAST.cc') -SliccSource('ast/CheckStopSlotsStatementAST.cc') -SliccSource('ast/ChipComponentAccessAST.cc') -SliccSource('ast/CopyHeadStatementAST.cc') -SliccSource('ast/DeclAST.cc') -SliccSource('ast/DeclListAST.cc') -SliccSource('ast/EnqueueStatementAST.cc') -SliccSource('ast/EnumDeclAST.cc') -SliccSource('ast/EnumExprAST.cc') -SliccSource('ast/ExprAST.cc') -SliccSource('ast/ExprStatementAST.cc') -SliccSource('ast/FormalParamAST.cc') -SliccSource('ast/FuncCallExprAST.cc') -SliccSource('ast/FuncDeclAST.cc') -SliccSource('ast/IfStatementAST.cc') -SliccSource('ast/InPortDeclAST.cc') -SliccSource('ast/InfixOperatorExprAST.cc') -SliccSource('ast/LiteralExprAST.cc') -SliccSource('ast/Location.cc') -SliccSource('ast/MachineAST.cc') -SliccSource('ast/MemberExprAST.cc') -SliccSource('ast/MethodCallExprAST.cc') -SliccSource('ast/NewExprAST.cc') -SliccSource('ast/ObjDeclAST.cc') -SliccSource('ast/OutPortDeclAST.cc') -SliccSource('ast/PairAST.cc') -SliccSource('ast/PairListAST.cc') -SliccSource('ast/PeekStatementAST.cc') -SliccSource('ast/ReturnStatementAST.cc') -SliccSource('ast/StatementAST.cc') -SliccSource('ast/StatementListAST.cc') -SliccSource('ast/TransitionDeclAST.cc') -SliccSource('ast/TypeAST.cc') -SliccSource('ast/TypeDeclAST.cc') -SliccSource('ast/TypeFieldAST.cc') -SliccSource('ast/TypeFieldEnumAST.cc') -SliccSource('ast/TypeFieldMemberAST.cc') -SliccSource('ast/TypeFieldMethodAST.cc') -SliccSource('ast/VarExprAST.cc') - -slicc_bin = File('slicc') -slicc_env.Program(slicc_bin, all_slicc_sources + [ common_dir.File('util.o') ]) diff --git a/src/mem/slicc/__init__.py b/src/mem/slicc/__init__.py new file mode 100644 index 000000000..8ce04e77d --- /dev/null +++ b/src/mem/slicc/__init__.py @@ -0,0 +1,25 @@ +# Copyright (c) 2009 The Hewlett-Packard Development Company +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer; +# redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution; +# neither the name of the copyright holders nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/src/mem/slicc/ast/AST.hh b/src/mem/slicc/ast/AST.hh deleted file mode 100644 index 33c9b84ed..000000000 --- a/src/mem/slicc/ast/AST.hh +++ /dev/null @@ -1,94 +0,0 @@ - -/* - * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer; - * redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution; - * neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/* - * AST.hh - * - * Description: - * - * $Id$ - * - */ - -#ifndef AST_H -#define AST_H - -#include "mem/slicc/slicc_global.hh" -#include "mem/gems_common/Vector.hh" -#include "mem/gems_common/Map.hh" -#include "mem/slicc/ast/Location.hh" -#include "mem/slicc/symbols/SymbolTable.hh" - -class AST { -public: - // Constructors - AST(Map<string, string> pairs) { m_pairs = pairs; }; - AST() {}; - - // Destructor - virtual ~AST() {}; - - // Public Methods - virtual void print(ostream& out) const = 0; - void error(string err_msg) const { m_location.error(err_msg); }; - string embedError(string err_msg) const { return m_location.embedError(err_msg); }; - void warning(string err_msg) const { m_location.warning(err_msg); }; - - const Location& getLocation() const { return m_location; }; - - const Map<string, string>& getPairs() const { return m_pairs; }; - Map<string, string>& getPairs() { return m_pairs; }; - -private: - // Private Methods - - // Private copy constructor and assignment operator - // AST(const AST& obj); - // AST& operator=(const AST& obj); - - // Data Members (m_ prefix) - Location m_location; - Map<string, string> m_pairs; -}; - -// Output operator declaration -ostream& operator<<(ostream& out, const AST& obj); - -// ******************* Definitions ******************* - -// Output operator definition -extern inline -ostream& operator<<(ostream& out, const AST& obj) -{ - obj.print(out); - out << flush; - return out; -} - -#endif //AST_H diff --git a/src/mem/slicc/ast/AST.py b/src/mem/slicc/ast/AST.py new file mode 100644 index 000000000..5b1b124cd --- /dev/null +++ b/src/mem/slicc/ast/AST.py @@ -0,0 +1,63 @@ +# Copyright (c) 1999-2008 Mark D. Hill and David A. Wood +# Copyright (c) 2009 The Hewlett-Packard Development Company +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer; +# redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution; +# neither the name of the copyright holders nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +from m5.util import code_formatter + +from slicc.util import PairContainer, Location + +class AST(PairContainer): + def __init__(self, slicc, pairs=None): + self.slicc = slicc + self.location = Location(slicc.current_file, slicc.lexer.lineno) + self.pairs = {} + if pairs: + self.pairs.update(getattr(pairs, "pairs", pairs)) + + @property + def symtab(self): + return self.slicc.symtab + + @property + def state_machine(self): + return self.slicc.symtab.state_machine + + def warning(self, message, *args): + self.location.warning(message, *args) + + def error(self, message, *args): + self.location.error(message, *args) + + def embedError(self, message, *args): + if args: + message = message % args + code = code_formatter() + code(''' +cerr << "Runtime Error at ${{self.location}}, Ruby Time: " << g_eventQueue_ptr->getTime() << ": "<< $message << ", PID: " << getpid() << endl; +char c; cerr << "press return to continue." << endl; cin.get(c); abort(); +''') + + return code diff --git a/src/mem/slicc/ast/ASTs.hh b/src/mem/slicc/ast/ASTs.hh deleted file mode 100644 index 3363fbb09..000000000 --- a/src/mem/slicc/ast/ASTs.hh +++ /dev/null @@ -1,91 +0,0 @@ - -/* - * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer; - * redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution; - * neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/* - * $Id$ - * - */ - -#ifndef ASTs_H -#define ASTs_H - -#include "mem/slicc/slicc_global.hh" -#include "mem/slicc/main.hh" -#include "mem/slicc/symbols/StateMachine.hh" -#include "mem/slicc/ast/AST.hh" - -#include "mem/slicc/ast/MachineAST.hh" - -#include "mem/slicc/ast/TypeAST.hh" -#include "mem/slicc/ast/FormalParamAST.hh" - -#include "mem/slicc/ast/DeclListAST.hh" -#include "mem/slicc/ast/DeclAST.hh" -#include "mem/slicc/ast/ActionDeclAST.hh" -#include "mem/slicc/ast/InPortDeclAST.hh" -#include "mem/slicc/ast/OutPortDeclAST.hh" -#include "mem/slicc/ast/TransitionDeclAST.hh" -#include "mem/slicc/ast/EnumDeclAST.hh" -#include "mem/slicc/ast/TypeDeclAST.hh" -#include "mem/slicc/ast/ObjDeclAST.hh" -#include "mem/slicc/ast/FuncDeclAST.hh" - -#include "mem/slicc/ast/TypeFieldAST.hh" -#include "mem/slicc/ast/TypeFieldMethodAST.hh" -#include "mem/slicc/ast/TypeFieldMemberAST.hh" -#include "mem/slicc/ast/TypeFieldEnumAST.hh" - -#include "mem/slicc/ast/PairAST.hh" -#include "mem/slicc/ast/PairListAST.hh" - -#include "mem/slicc/ast/ExprAST.hh" -#include "mem/slicc/ast/VarExprAST.hh" -#include "mem/slicc/ast/EnumExprAST.hh" -#include "mem/slicc/ast/LiteralExprAST.hh" -#include "mem/slicc/ast/MemberExprAST.hh" -#include "mem/slicc/ast/InfixOperatorExprAST.hh" -#include "mem/slicc/ast/FuncCallExprAST.hh" -#include "mem/slicc/ast/MethodCallExprAST.hh" -#include "mem/slicc/ast/NewExprAST.hh" - -#include "mem/slicc/ast/ChipComponentAccessAST.hh" - -#include "mem/slicc/ast/StatementListAST.hh" -#include "mem/slicc/ast/StatementAST.hh" -#include "mem/slicc/ast/ExprStatementAST.hh" -#include "mem/slicc/ast/AssignStatementAST.hh" -#include "mem/slicc/ast/EnqueueStatementAST.hh" -#include "mem/slicc/ast/IfStatementAST.hh" -#include "mem/slicc/ast/PeekStatementAST.hh" -#include "mem/slicc/ast/CopyHeadStatementAST.hh" -#include "mem/slicc/ast/CheckAllocateStatementAST.hh" -#include "mem/slicc/ast/CheckStopSlotsStatementAST.hh" -#include "mem/slicc/ast/ReturnStatementAST.hh" - -#endif //ASTs_H diff --git a/src/mem/slicc/ast/ActionDeclAST.cc b/src/mem/slicc/ast/ActionDeclAST.cc deleted file mode 100644 index e46412ff7..000000000 --- a/src/mem/slicc/ast/ActionDeclAST.cc +++ /dev/null @@ -1,98 +0,0 @@ - -/* - * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer; - * redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution; - * neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/* - * ActionDeclAST.C - * - * Description: See ActionDeclAST.hh - * - * $Id$ - * - */ - - -#include "mem/slicc/ast/ActionDeclAST.hh" -#include "mem/slicc/symbols/Action.hh" -#include "mem/slicc/ast/StatementListAST.hh" - -ActionDeclAST::ActionDeclAST(string* ident_ptr, - PairListAST* pairs_ptr, - StatementListAST* statement_list_ptr) - : DeclAST(pairs_ptr) -{ - m_ident_ptr = ident_ptr; - m_statement_list_ptr = statement_list_ptr; -} - -ActionDeclAST::~ActionDeclAST() -{ - delete m_ident_ptr; - delete m_statement_list_ptr; -} - -void ActionDeclAST::generate() -{ - Map<Var*, string> resource_list; - if (m_statement_list_ptr != NULL) { - string code; - - // Add new local vars - g_sym_table.pushFrame(); - - Type* type_ptr = g_sym_table.getType("Address"); - - if (type_ptr == NULL) { - error("Type 'Address' not declared."); - } - - g_sym_table.newSym(new Var("address", getLocation(), type_ptr, "addr", getPairs())); - - // Don't allows returns in actions - m_statement_list_ptr->generate(code, NULL); - - getPairs().add("c_code", code); - - m_statement_list_ptr->findResources(resource_list); - - g_sym_table.popFrame(); - } - - StateMachine* machine_ptr = g_sym_table.getStateMachine(); - if (machine_ptr == NULL) { - error("Action declaration not part of a machine."); - } else { - machine_ptr->addAction(new Action(*m_ident_ptr, resource_list, getLocation(), getPairs())); - } - -} - -void ActionDeclAST::print(ostream& out) const -{ - out << "[ActionDecl: " << *m_ident_ptr << "]"; -} diff --git a/src/mem/slicc/ast/ActionDeclAST.hh b/src/mem/slicc/ast/ActionDeclAST.hh deleted file mode 100644 index 4970ee254..000000000 --- a/src/mem/slicc/ast/ActionDeclAST.hh +++ /dev/null @@ -1,86 +0,0 @@ - -/* - * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer; - * redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution; - * neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/* - * ActionDeclAST.hh - * - * Description: - * - * $Id: ActionDeclAST.hh,v 3.2 2003/07/10 18:08:06 milo Exp $ - * - */ - -#ifndef ActionDeclAST_H -#define ActionDeclAST_H - -#include "mem/slicc/slicc_global.hh" -#include "mem/slicc/ast/DeclAST.hh" - -class StatementListAST; - -class ActionDeclAST : public DeclAST { -public: - // Constructors - ActionDeclAST(string* ident_ptr, - PairListAST* pairs_ptr, - StatementListAST* statement_list_ptr); - - // Destructor - ~ActionDeclAST(); - - // Public Methods - void generate(); - void print(ostream& out) const; -private: - // Private Methods - - // Private copy constructor and assignment operator - ActionDeclAST(const ActionDeclAST& obj); - ActionDeclAST& operator=(const ActionDeclAST& obj); - - // Data Members (m_ prefix) - string* m_ident_ptr; - StatementListAST* m_statement_list_ptr; -}; - -// Output operator declaration -ostream& operator<<(ostream& out, const ActionDeclAST& obj); - -// ******************* Definitions ******************* - -// Output operator definition -extern inline -ostream& operator<<(ostream& out, const ActionDeclAST& obj) -{ - obj.print(out); - out << flush; - return out; -} - -#endif //ActionDeclAST_H diff --git a/src/mem/slicc/ast/ActionDeclAST.py b/src/mem/slicc/ast/ActionDeclAST.py new file mode 100644 index 000000000..18bf443b9 --- /dev/null +++ b/src/mem/slicc/ast/ActionDeclAST.py @@ -0,0 +1,72 @@ +# Copyright (c) 1999-2008 Mark D. Hill and David A. Wood +# Copyright (c) 2009 The Hewlett-Packard Development Company +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer; +# redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution; +# neither the name of the copyright holders nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +from m5.util import code_formatter + +from slicc.ast.DeclAST import DeclAST +from slicc.symbols import Action, Type, Var + +class ActionDeclAST(DeclAST): + def __init__(self, slicc, ident, pairs, statement_list): + super(ActionDeclAST, self).__init__(slicc, pairs) + self.ident = ident + self.statement_list = statement_list + + def __repr__(self): + return "[ActionDecl: %r]" % (self.ident) + + def generate(self): + resources = {} + if self.statement_list: + # Add new local vars + self.symtab.pushFrame() + + addr_type = self.symtab.find("Address", Type) + + if addr_type is None: + self.error("Type 'Address' not declared.") + + var = Var(self.symtab, "address", self.location, addr_type, + "addr", self.pairs) + self.symtab.newSymbol(var) + + # Do not allows returns in actions + code = code_formatter() + self.statement_list.generate(code, None) + self.pairs["c_code"] = str(code) + + self.statement_list.findResources(resources) + + self.symtab.popFrame() + + machine = self.symtab.state_machine + if machine is None: + self.error("Action declaration not part of a machine.") + + action = Action(self.symtab, self.ident, resources, self.location, + self.pairs) + machine.addAction(action) diff --git a/src/mem/slicc/ast/AssignStatementAST.cc b/src/mem/slicc/ast/AssignStatementAST.cc deleted file mode 100644 index 8cf42aa63..000000000 --- a/src/mem/slicc/ast/AssignStatementAST.cc +++ /dev/null @@ -1,76 +0,0 @@ - -/* - * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer; - * redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution; - * neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/* - * AssignStatementAST.C - * - * Description: See AssignStatementAST.hh - * - * $Id: AssignStatementAST.C,v 3.2 2003/08/01 18:38:19 beckmann Exp $ - * - */ - -#include "mem/slicc/ast/AssignStatementAST.hh" - -AssignStatementAST::AssignStatementAST(ExprAST* lvalue_ptr, ExprAST* rvalue_ptr) - : StatementAST() -{ - m_lvalue_ptr = lvalue_ptr; - m_rvalue_ptr = rvalue_ptr; -} - -AssignStatementAST::~AssignStatementAST() -{ - delete m_lvalue_ptr; - delete m_rvalue_ptr; -} - -void AssignStatementAST::generate(string& code, Type* return_type_ptr) const -{ - code += indent_str(); - Type* lvalue_type_ptr = m_lvalue_ptr->generate(code); - code += " = "; - Type* rvalue_type_ptr = m_rvalue_ptr->generate(code); - code += ";\n"; - - if (lvalue_type_ptr != rvalue_type_ptr) { - // FIXME - beckmann - // the following if statement is a hack to allow NetDest objects to be assigned to Sets - // this allows for the previous NetworkMessage Destiantion 'Set class' to migrate to the - // new NetworkMessage Destiantion 'NetDest class' - if (lvalue_type_ptr->toString() != "NetDest" && rvalue_type_ptr->toString() != "Set") { - error("Assignment type mismatch '" + lvalue_type_ptr->toString() + "' and '" + rvalue_type_ptr->toString() + "'"); - } - } -} - -void AssignStatementAST::print(ostream& out) const -{ - out << "[AssignStatementAST: " << *m_lvalue_ptr << " := " << *m_rvalue_ptr << "]"; -} diff --git a/src/mem/slicc/ast/AssignStatementAST.hh b/src/mem/slicc/ast/AssignStatementAST.hh deleted file mode 100644 index 2c19da831..000000000 --- a/src/mem/slicc/ast/AssignStatementAST.hh +++ /dev/null @@ -1,85 +0,0 @@ - -/* - * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer; - * redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution; - * neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/* - * AssignStatementAST.hh - * - * Description: - * - * $Id: AssignStatementAST.hh,v 3.2 2001/12/12 01:00:09 milo Exp $ - * - */ - -#ifndef ASSIGNSTATEMENTAST_H -#define ASSIGNSTATEMENTAST_H - -#include "mem/slicc/slicc_global.hh" -#include "mem/slicc/ast/StatementAST.hh" -#include "mem/slicc/ast/ExprAST.hh" - - - -class AssignStatementAST : public StatementAST { -public: - // Constructors - AssignStatementAST(ExprAST* lvalue_ptr, ExprAST* rvalue_ptr); - - // Destructor - ~AssignStatementAST(); - - // Public Methods - void generate(string& code, Type* return_type_ptr) const; - void print(ostream& out) const; -private: - // Private Methods - - // Private copy constructor and assignment operator - AssignStatementAST(const AssignStatementAST& obj); - AssignStatementAST& operator=(const AssignStatementAST& obj); - - // Data Members (m_ prefix) - ExprAST* m_lvalue_ptr; - ExprAST* m_rvalue_ptr; -}; - -// Output operator declaration -ostream& operator<<(ostream& out, const AssignStatementAST& obj); - -// ******************* Definitions ******************* - -// Output operator definition -extern inline -ostream& operator<<(ostream& out, const AssignStatementAST& obj) -{ - obj.print(out); - out << flush; - return out; -} - -#endif //ASSIGNSTATEMENTAST_H diff --git a/src/mem/slicc/ast/AssignStatementAST.py b/src/mem/slicc/ast/AssignStatementAST.py new file mode 100644 index 000000000..f8e77b03b --- /dev/null +++ b/src/mem/slicc/ast/AssignStatementAST.py @@ -0,0 +1,59 @@ +# Copyright (c) 1999-2008 Mark D. Hill and David A. Wood +# Copyright (c) 2009 The Hewlett-Packard Development Company +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer; +# redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution; +# neither the name of the copyright holders nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +from m5.util import code_formatter + +from slicc.ast.StatementAST import StatementAST + +class AssignStatementAST(StatementAST): + def __init__(self, slicc, lvalue, rvalue): + super(AssignStatementAST, self).__init__(slicc) + self.lvalue = lvalue + self.rvalue = rvalue + + def __repr__(self): + return "[AssignStatementAST: %r := %r]" % (self.lvalue, self.rvalue) + + def generate(self, code, return_type): + lcode = code_formatter() + rcode = code_formatter() + + ltype = self.lvalue.generate(lcode) + rtype = self.rvalue.generate(rcode) + + code("$lcode = $rcode;") + + if ltype != rtype: + # FIXME - beckmann + # the following if statement is a hack to allow NetDest + # objects to be assigned to Sets this allows for the + # previous NetworkMessage Destiantion 'Set class' to + # migrate to the new NetworkMessage Destiantion 'NetDest + # class' + if str(ltype) != "NetDest" and str(rtype) != "Set": + self.error("Assignment type mismatch '%s' and '%s'", + ltype, rtype) diff --git a/src/mem/slicc/ast/CheckAllocateStatementAST.cc b/src/mem/slicc/ast/CheckAllocateStatementAST.cc deleted file mode 100644 index 1f498efe2..000000000 --- a/src/mem/slicc/ast/CheckAllocateStatementAST.cc +++ /dev/null @@ -1,72 +0,0 @@ - -/* - * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer; - * redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution; - * neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/* - * $Id$ - * - */ - -#include "mem/slicc/ast/CheckAllocateStatementAST.hh" -#include "mem/slicc/symbols/SymbolTable.hh" -#include "mem/slicc/ast/VarExprAST.hh" -#include "mem/gems_common/util.hh" - -CheckAllocateStatementAST::CheckAllocateStatementAST(VarExprAST* variable) - : StatementAST() -{ - m_variable = variable; -} - -CheckAllocateStatementAST::~CheckAllocateStatementAST() -{ - delete m_variable; -} - -void CheckAllocateStatementAST::generate(string& code, Type* return_type_ptr) const -{ - // FIXME - check the type of the variable - - // Make sure the variable is valid - m_variable->getVar(); -} - -void CheckAllocateStatementAST::findResources(Map<Var*, string>& resource_list) const -{ - Var* var_ptr = m_variable->getVar(); - int res_count = 0; - if (resource_list.exist(var_ptr)) { - res_count = atoi((resource_list.lookup(var_ptr)).c_str()); - } - resource_list.add(var_ptr, int_to_string(res_count+1)); -} - -void CheckAllocateStatementAST::print(ostream& out) const -{ - out << "[CheckAllocateStatementAst: " << *m_variable << "]"; -} diff --git a/src/mem/slicc/ast/CheckAllocateStatementAST.py b/src/mem/slicc/ast/CheckAllocateStatementAST.py new file mode 100644 index 000000000..b96153b0a --- /dev/null +++ b/src/mem/slicc/ast/CheckAllocateStatementAST.py @@ -0,0 +1,47 @@ +# Copyright (c) 1999-2008 Mark D. Hill and David A. Wood +# Copyright (c) 2009 The Hewlett-Packard Development Company +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer; +# redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution; +# neither the name of the copyright holders nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +from slicc.ast.StatementAST import StatementAST + +class CheckAllocateStatementAST(StatementAST): + def __init__(self, slicc, variable): + super(StatementAST, self).__init__(slicc) + self.variable = variable + + def __repr__(self): + return "[CheckAllocateStatementAst: %r]" % self.variable + + def generate(self, code, return_type): + # FIXME - check the type of the variable + + # Make sure the variable is valid + self.variable.var + + def findResources(self, resources): + var = self.variable.var + res_count = int(resources.get(var, 0)) + resources[var] = str(res_count + 1) diff --git a/src/mem/slicc/ast/CheckStopSlotsStatementAST.cc b/src/mem/slicc/ast/CheckStopSlotsStatementAST.cc deleted file mode 100644 index 38dc449d6..000000000 --- a/src/mem/slicc/ast/CheckStopSlotsStatementAST.cc +++ /dev/null @@ -1,115 +0,0 @@ - -/* - * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer; - * redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution; - * neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/* - * $Id$ - * - */ - -#include "mem/slicc/ast/CheckStopSlotsStatementAST.hh" -#include "mem/slicc/symbols/SymbolTable.hh" -#include "mem/slicc/ast/VarExprAST.hh" -#include "mem/slicc/ast/PairListAST.hh" - -CheckStopSlotsStatementAST::CheckStopSlotsStatementAST(VarExprAST* variable, string* condStr, string* bankStr) - : StatementAST() -{ - m_variable = variable; - m_condStr_ptr = condStr; - m_bankStr_ptr = bankStr; -} - -CheckStopSlotsStatementAST::~CheckStopSlotsStatementAST() -{ - delete m_variable; - delete m_condStr_ptr; - delete m_bankStr_ptr; -} - -void CheckStopSlotsStatementAST::generate(string& code, Type* return_type_ptr) const -{ - - // Make sure the variable is valid - m_variable->getVar(); - -} - -void CheckStopSlotsStatementAST::findResources(Map<Var*, string>& resource_list) const -{ - Type* type_ptr; - - Var* var_ptr = m_variable->getVar(); - string check_code; - - if (*m_condStr_ptr == "((*in_msg_ptr)).m_isOnChipSearch") { - check_code += " const Response9Msg* in_msg_ptr;\n"; - check_code += " in_msg_ptr = dynamic_cast<const Response9Msg*>(((*(m_chip_ptr->m_L2Cache_responseToL2Cache9_vec[m_version]))).peek());\n"; - check_code += " assert(in_msg_ptr != NULL);\n"; - } - - check_code += " if ("; - check_code += *m_condStr_ptr; - check_code += ") {\n"; - - check_code += " if (!"; - type_ptr = m_variable->generate(check_code); - check_code += ".isDisableSPossible((((*(m_chip_ptr->m_DNUCAmover_ptr))).getBankPos("; - check_code += *m_bankStr_ptr; - check_code += ")))) {\n"; - if(CHECK_INVALID_RESOURCE_STALLS) { - check_code += " assert(priority >= "; - type_ptr = m_variable->generate(check_code); - check_code += ".getPriority());\n"; - } - check_code += " return TransitionResult_ResourceStall;\n"; - check_code += " }\n"; - check_code += " } else {\n"; - check_code += " if (!"; - type_ptr = m_variable->generate(check_code); - check_code += ".isDisableFPossible((((*(m_chip_ptr->m_DNUCAmover_ptr))).getBankPos("; - check_code += *m_bankStr_ptr; - check_code += ")))) {\n"; - if(CHECK_INVALID_RESOURCE_STALLS) { - check_code += " assert(priority >= "; - type_ptr = m_variable->generate(check_code); - check_code += ".getPriority());\n"; - } - check_code += " return TransitionResult_ResourceStall;\n"; - check_code += " }\n"; - check_code += " }\n"; - - assert(!resource_list.exist(var_ptr)); - resource_list.add(var_ptr, check_code); - -} - -void CheckStopSlotsStatementAST::print(ostream& out) const -{ - out << "[CheckStopSlotsStatementAst: " << *m_variable << "]"; -} diff --git a/src/mem/slicc/ast/CheckStopSlotsStatementAST.hh b/src/mem/slicc/ast/CheckStopSlotsStatementAST.hh deleted file mode 100644 index 6de068caa..000000000 --- a/src/mem/slicc/ast/CheckStopSlotsStatementAST.hh +++ /dev/null @@ -1,85 +0,0 @@ - -/* - * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer; - * redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution; - * neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/* - * $Id$ - * - */ - -#ifndef CHECKSTOPSLOTSSTATEMENTAST_H -#define CHECKSTOPSLOTSSTATEMENTAST_H - -#include "mem/slicc/slicc_global.hh" -#include "mem/slicc/ast/ExprAST.hh" -#include "mem/slicc/ast/StatementAST.hh" -#include "mem/slicc/ast/TypeAST.hh" - -class VarExprAST; -class Var; - -class CheckStopSlotsStatementAST : public StatementAST { -public: - // Constructors - CheckStopSlotsStatementAST(VarExprAST* variable, string* condStr, string* bankStr); - - // Destructor - ~CheckStopSlotsStatementAST(); - - // Public Methods - void generate(string& code, Type* return_type_ptr) const; - void findResources(Map<Var*, string>& resource_list) const; - void print(ostream& out) const; -private: - // Private Methods - - // Private copy constructor and assignment operator - CheckStopSlotsStatementAST(const CheckStopSlotsStatementAST& obj); - CheckStopSlotsStatementAST& operator=(const CheckStopSlotsStatementAST& obj); - - // Data Members (m_ prefix) - VarExprAST* m_variable; - string* m_condStr_ptr; - string* m_bankStr_ptr; -}; - -// Output operator declaration -ostream& operator<<(ostream& out, const CheckStopSlotsStatementAST& obj); - -// ******************* Definitions ******************* - -// Output operator definition -extern inline -ostream& operator<<(ostream& out, const CheckStopSlotsStatementAST& obj) -{ - obj.print(out); - out << flush; - return out; -} - -#endif //CHECKSTOPSLOTSSTATEMENTAST_H diff --git a/src/mem/slicc/ast/CheckStopSlotsStatementAST.py b/src/mem/slicc/ast/CheckStopSlotsStatementAST.py new file mode 100644 index 000000000..307fbd6a1 --- /dev/null +++ b/src/mem/slicc/ast/CheckStopSlotsStatementAST.py @@ -0,0 +1,74 @@ +# Copyright (c) 1999-2008 Mark D. Hill and David A. Wood +# Copyright (c) 2009 The Hewlett-Packard Development Company +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer; +# redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution; +# neither the name of the copyright holders nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +from slicc.ast.StatementAST import StatementAST + +class CheckStopSlotsStatementAST(StatementAST): + def __init__(self, slicc, variable, condStr, bankStr): + super(StatementAST, self).__init__(slicc) + self.variable = variable + self.condStr = condStr + self.bankStr = bankStr + + def __repr__(self): + return "[CheckStopSlotsStatementAst: %r]" % self.variable + + def generate(self, code, return_type): + # Make sure the variable is valid + self.variable.var + + def findResources(self, resources): + var = self.variable.var + assert var not in self.resources + + check_code = code_formatter() + if self.condStr == "((*in_msg_ptr)).m_isOnChipSearch": + check_code(''' +const Response9Msg* in_msg_ptr = + dynamic_cast<const Response9Msg*>(((*(m_chip_ptr.m_L2Cache_responseToL2Cache9_vec[m_version]))).peek()); +assert(in_msg_ptr != NULL); +''') + + vcode = self.variable.inline() + bank = self.bankStr + cond = self.condStr + + check_code(''' +if ($cond) { + auto pos = m_chip_ptr.m_DNUCAmover_ptr->getBankPos($bank) + + if (!$vcode.isDisableSPossible(pos)) { + return TransitionResult_ResourceStall; + } +} else { + if (!$vcode.isDisableFPossible(pos)) { + return TransitionResult_ResourceStall; + } +} +''') + + resources[var] = str(check_code) diff --git a/src/mem/slicc/ast/ChipComponentAccessAST.cc b/src/mem/slicc/ast/ChipComponentAccessAST.cc deleted file mode 100644 index 61dccf2c0..000000000 --- a/src/mem/slicc/ast/ChipComponentAccessAST.cc +++ /dev/null @@ -1,244 +0,0 @@ - -/* - * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer; - * redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution; - * neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/* - * ChipComponentAccessAST.C - * - * Description: See ChipComponentAccessAST.hh - * - * $Id: ChipComponentAccessAST.C 1.9 04/06/18 21:00:08-00:00 beckmann@cottons.cs.wisc.edu $ - * - */ - -#include "mem/slicc/ast/ChipComponentAccessAST.hh" - -ChipComponentAccessAST::ChipComponentAccessAST(VarExprAST* machine, ExprAST* mach_version, VarExprAST* component, string* proc_name, Vector<ExprAST*>* expr_vec_ptr) - - : ExprAST() -{ - m_chip_ver_expr_ptr = NULL; - m_mach_var_ptr = machine; - m_comp_var_ptr = component; - m_mach_ver_expr_ptr = mach_version; - m_expr_vec_ptr = expr_vec_ptr; - m_proc_name_ptr = proc_name; - m_field_name_ptr = NULL; -} - -ChipComponentAccessAST::ChipComponentAccessAST(VarExprAST* machine, ExprAST* mach_version, VarExprAST* component, string* field_name) - - : ExprAST() -{ - m_chip_ver_expr_ptr = NULL; - m_mach_var_ptr = machine; - m_comp_var_ptr = component; - m_mach_ver_expr_ptr = mach_version; - m_expr_vec_ptr = NULL; - m_proc_name_ptr = NULL; - m_field_name_ptr = field_name; -} - -ChipComponentAccessAST::ChipComponentAccessAST(ExprAST* chip_version, VarExprAST* machine, ExprAST* mach_version, VarExprAST* component, string* proc_name, Vector<ExprAST*>* expr_vec_ptr) - - : ExprAST() -{ - m_chip_ver_expr_ptr = chip_version; - m_mach_var_ptr = machine; - m_comp_var_ptr = component; - m_mach_ver_expr_ptr = mach_version; - m_expr_vec_ptr = expr_vec_ptr; - m_proc_name_ptr = proc_name; - m_field_name_ptr = NULL; -} - -ChipComponentAccessAST::ChipComponentAccessAST(ExprAST* chip_version, VarExprAST* machine, ExprAST* mach_version, VarExprAST* component, string* field_name) - - : ExprAST() -{ - m_chip_ver_expr_ptr = chip_version; - m_mach_var_ptr = machine; - m_comp_var_ptr = component; - m_mach_ver_expr_ptr = mach_version; - m_expr_vec_ptr = NULL; - m_proc_name_ptr = NULL; - m_field_name_ptr = field_name; -} - - - -ChipComponentAccessAST::~ChipComponentAccessAST() -{ - if (m_expr_vec_ptr != NULL) { - int size = m_expr_vec_ptr->size(); - for(int i=0; i<size; i++) { - delete (*m_expr_vec_ptr)[i]; - } - } - - delete m_mach_var_ptr; - delete m_comp_var_ptr; - delete m_mach_ver_expr_ptr; - - if (m_proc_name_ptr != NULL) { - delete m_proc_name_ptr; - } - - if (m_field_name_ptr != NULL) { - delete m_field_name_ptr; - } - - if (m_chip_ver_expr_ptr != NULL) { - delete m_chip_ver_expr_ptr; - } -} - -Type* ChipComponentAccessAST::generate(string& code) const -{ - Type* void_type_ptr = g_sym_table.getType("void"); - Type* ret_type_ptr; - - - code += "("; - - Var* v = g_sym_table.getMachComponentVar(m_mach_var_ptr->getName(), m_comp_var_ptr->getName()); - - string orig_code = v->getCode(); - string working_code; - - if (m_chip_ver_expr_ptr != NULL) { - // replace m_chip_ptr with specified chip - - unsigned int t = orig_code.find("m_chip_ptr"); - assert(t != string::npos); - string code_temp0 = orig_code.substr(0, t); - string code_temp1 = orig_code.substr(t+10); - - working_code += code_temp0; - working_code += "g_system_ptr->getChip("; - m_chip_ver_expr_ptr->generate(working_code); - working_code += ")"; - working_code += code_temp1; - } - else { - working_code += orig_code; - } - - // replace default "m_version" with the version we really want - unsigned int tmp_uint = working_code.find("m_version"); - assert(tmp_uint != string::npos); - string code_temp2 = working_code.substr(0, tmp_uint); - string code_temp3 = working_code.substr(tmp_uint+9); - - code += code_temp2; - code += "("; - m_mach_ver_expr_ptr->generate(code); - code += ")"; - code += code_temp3; - code += ")"; - - if (m_proc_name_ptr != NULL) { - // method call - code += "."; - - Vector <Type*> paramTypes; - - // generate code - int actual_size = m_expr_vec_ptr->size(); - code += (*m_proc_name_ptr) + "("; - for(int i=0; i<actual_size; i++) { - if (i != 0) { - code += ", "; - } - // Check the types of the parameter - Type* actual_type_ptr = (*m_expr_vec_ptr)[i]->generate(code); - paramTypes.insertAtBottom(actual_type_ptr); - } - code += ")"; - - Type* obj_type_ptr = v->getType(); - string methodId = obj_type_ptr->methodId(*m_proc_name_ptr, paramTypes); - - // Verify that this is a method of the object - if (!obj_type_ptr->methodExist(methodId)) { - error("Invalid method call: Type '" + obj_type_ptr->toString() + "' does not have a method '" + methodId + "'"); - } - - int expected_size = obj_type_ptr->methodParamType(methodId).size(); - if (actual_size != expected_size) { - // Right number of parameters - ostringstream err; - err << "Wrong number of parameters for function name: '" << *m_proc_name_ptr << "'"; - err << ", expected: "; - err << expected_size; - err << ", actual: "; - err << actual_size; - error(err.str()); - } - - for(int i=0; i<actual_size; i++) { - // Check the types of the parameter - Type* actual_type_ptr = paramTypes[i]; - Type* expected_type_ptr = obj_type_ptr->methodParamType(methodId)[i]; - if (actual_type_ptr != expected_type_ptr) { - (*m_expr_vec_ptr)[i]->error("Type mismatch: expected: " + expected_type_ptr->toString() + - " actual: " + actual_type_ptr->toString()); - } - } - - // Return the return type of the method - ret_type_ptr = obj_type_ptr->methodReturnType(methodId); - } - else if (m_field_name_ptr != NULL) { - Type* obj_type_ptr = v->getType(); - code += ").m_" + (*m_field_name_ptr); - - // Verify that this is a valid field name for this type - if (!obj_type_ptr->dataMemberExist(*m_field_name_ptr)) { - error("Invalid object field: Type '" + obj_type_ptr->toString() + "' does not have data member " + *m_field_name_ptr); - } - - // Return the type of the field - ret_type_ptr = obj_type_ptr->dataMemberType(*m_field_name_ptr); - } - else { - assert(0); - } - - return ret_type_ptr; -} - -void ChipComponentAccessAST::findResources(Map<Var*, string>& resource_list) const -{ - -} - -void ChipComponentAccessAST::print(ostream& out) const -{ - out << "[ChipAccessExpr: " << *m_expr_vec_ptr << "]"; -} diff --git a/src/mem/slicc/ast/ChipComponentAccessAST.hh b/src/mem/slicc/ast/ChipComponentAccessAST.hh deleted file mode 100644 index 1f22a79e4..000000000 --- a/src/mem/slicc/ast/ChipComponentAccessAST.hh +++ /dev/null @@ -1,101 +0,0 @@ - -/* - * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer; - * redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution; - * neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/* - * - * - * Description: - * - * $Id: ChipComponentAccessAST.hh 1.8 04/06/18 21:00:08-00:00 beckmann@cottons.cs.wisc.edu $ - * - */ - -#ifndef ChipComponentAccessAST_H -#define ChipComponentAccessAST_H - -#include "mem/slicc/slicc_global.hh" -#include "mem/slicc/ast/StatementAST.hh" -#include "mem/slicc/ast/ExprAST.hh" -#include "mem/slicc/ast/VarExprAST.hh" -#include "mem/slicc/ast/TypeAST.hh" - -class ChipComponentAccessAST : public ExprAST { -public: - // Constructors - - // method call from local chip - ChipComponentAccessAST(VarExprAST* machine, ExprAST* mach_version, VarExprAST* component, string* proc_name, Vector<ExprAST*>* expr_vec_ptr); - // member access from local chip - ChipComponentAccessAST(VarExprAST* machine, ExprAST* mach_version, VarExprAST* component, string* field_name); - - // method call from specified chip - ChipComponentAccessAST(ExprAST* chip_version, VarExprAST* machine, ExprAST* mach_version, VarExprAST* component, string* proc_name, Vector<ExprAST*>* expr_vec_ptr); - - // member access from specified chip - ChipComponentAccessAST(ExprAST* chip_version, VarExprAST* machine, ExprAST* mach_version, VarExprAST* component, string* field_name); - - // Destructor - ~ChipComponentAccessAST(); - - // Public Methods - Type* generate(string& code) const; - void findResources(Map<Var*, string>& resource_list) const; - void print(ostream& out) const; -private: - // Private Methods - - // Private copy constructor and assignment operator - ChipComponentAccessAST(const ChipComponentAccessAST& obj); - ChipComponentAccessAST& operator=(const ChipComponentAccessAST& obj); - - // Data Members (m_ prefix) - VarExprAST* m_mach_var_ptr; - VarExprAST* m_comp_var_ptr; - ExprAST* m_mach_ver_expr_ptr; - ExprAST* m_chip_ver_expr_ptr; - Vector<ExprAST*>* m_expr_vec_ptr; - string* m_proc_name_ptr; - string* m_field_name_ptr; -}; - -// Output operator declaration -ostream& operator<<(ostream& out, const ChipComponentAccessAST& obj); - -// ******************* Definitions ******************* - -// Output operator definition -extern inline -ostream& operator<<(ostream& out, const ChipComponentAccessAST& obj) -{ - obj.print(out); - out << flush; - return out; -} - -#endif // ChipComponentAccessAST_H diff --git a/src/mem/slicc/ast/ChipComponentAccessAST.py b/src/mem/slicc/ast/ChipComponentAccessAST.py new file mode 100644 index 000000000..bbb1b61e9 --- /dev/null +++ b/src/mem/slicc/ast/ChipComponentAccessAST.py @@ -0,0 +1,161 @@ +# Copyright (c) 1999-2008 Mark D. Hill and David A. Wood +# Copyright (c) 2009 The Hewlett-Packard Development Company +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer; +# redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution; +# neither the name of the copyright holders nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +import re + +from slicc.ast.ExprAST import ExprAST +from slicc.symbols import Type + +class ChipComponentAccessAST(ExprAST): + def __init__(self, slicc, machine, mach_version, component): + super(ChipComponentAccessAST, self).__init__(slicc) + self.mach_var = machine + self.comp_var = component + self.mach_ver_expr = mach_version + + def __repr__(self): + return "[ChipAccessExpr: %r]" % self.expr_vec + + def generate(self, code): + void_type = self.symtab.find("void", Type) + + mname = self.mach_var.name + cname = self.comp_var.name + var = self.symtab.machine_components[mname][cname] + + vcode = str(var.code) + + if self.chip_ver_expr is not None: + # replace self.chip with specified chip + gcode = "g_system.getChip(%s)" % self.chip_ver_expr.inline() + vcode = re.sub("m_chip", gcode, vcode) + + # replace default "m_version" with the version we really want + gcode = "(%s)" % self.mach_ver_expr.inline() + vcode = re.sub("m_version", gcode, vcode) + + return_type, gcode = self.generate_access(var) + code("($vcode)$gcode") + return return_type + +class ChipMethodAccessAST(ChipComponentAccessAST): + def __init__(self, slicc, chip_version, machine, mach_version, component, + proc_name, expr_vec): + s = super(ChipMethodAccessAST, self) + s.__init__(slicc, machine, mach_version, component) + + self.chip_ver_expr = chip_version + self.expr_vec = expr_vec + self.proc_name = proc_name + + def generate_access(self, var): + # generate code + paramTypes = [] + gcode = [] + for expr in self.expr_vec: + t,c = expr.generate() + paramTypes.append(t) + gcode.append(c) + + methodId = var.type.methodId(self.proc_name, paramTypes) + + # Verify that this is a method of the object + if not var.type.methodExist(methodId): + self.error("%s: Type '%s' does not have a method '%s'" % \ + ("Invalid method call", var.type, methodId)) + + expected_size = len(var.type.methodParamType(methodId)) + if len(self.expr_vec) != expected_size: + # Right number of parameters + self.error("Wrong number of parameters for function name: " +\ + "'%s', expected: %d, actual: %d", + self.proc_name, expected_size, len(self.expr_vec)) + + for expr,expected,actual in zip(self.expr_vec, + var.type.methodParamType(methodId), + paramTypes): + # Check the types of the parameter + if actual != expected: + expr.error("Type mismatch: expected: %s actual: %s", + expected, actual) + + # method call + code = ".%s(%s)" % (self.proc_name, ', '.join(gcode)) + + # Return the return type of the method + return var.type.methodReturnType(methodId), code + +class LocalChipMethodAST(ChipMethodAccessAST): + # method call from local chip + def __init__(self, slicc, machine, mach_version, component, proc_name, + expr_vec): + s = super(LocalChipMethodAST, self) + s.__init__(slicc, None, machine, mach_version, component, proc_name, + expr_vec) + +class SpecifiedChipMethodAST(ChipMethodAccessAST): + # method call from specified chip + def __init__(self, slicc, chip_version, machine, mach_version, component, + proc_name, expr_vec): + s = super(SpecifiedChipMethodAST, self) + s.__init__(slicc, chip_version, machine, mach_version, component, + proc_name, expr_vec) + +class ChipMemberAccessAST(ChipComponentAccessAST): + # member access from specified chip + def __init__(self, chip_version, machine, mach_version, component, + field_name): + s = super(ChipMemberAccessAST, self) + s.__init__(slicc, machine, mach_version, component) + + self.chip_ver_expr = chip_version + self.field_name = field_name + + def generate_access(self, var): + # Verify that this is a valid field name for this type + if not var.type.dataMemberExist(self.field_name): + self.error("Invalid object field: " +\ + "Type '%s' does not have data member %s", + var.type, self.field_name) + + code += ").m_%s" % self.field_name + + return var.type.dataMemberType(self.field_name), code + +class LocalChipMemberAST(ChipMemberAccessAST): + # member access from local chip + def __init__(self, slicc, machine, mach_version, component, field_name): + s = super(LocalChipMemberAST, self) + s.__init__(slicc, None, machine, mach_version, component, field_name) + +class SpecifiedChipMemberAST(ChipMemberAccessAST): + # member access from specified chip + def __init__(self, chip_version, machine, mach_version, component, + field_name): + s = super(SpecifiedChipMemberAST, self) + s.__init__(slicc, chip_version, machine, mach_version, component, + field_name) diff --git a/src/mem/slicc/ast/CopyHeadStatementAST.cc b/src/mem/slicc/ast/CopyHeadStatementAST.cc deleted file mode 100644 index 8d455eb9d..000000000 --- a/src/mem/slicc/ast/CopyHeadStatementAST.cc +++ /dev/null @@ -1,85 +0,0 @@ - -/* - * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer; - * redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution; - * neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/* - * $Id$ - * - */ - -#include "mem/slicc/ast/CopyHeadStatementAST.hh" -#include "mem/slicc/symbols/SymbolTable.hh" -#include "mem/slicc/ast/VarExprAST.hh" -#include "mem/gems_common/util.hh" - -CopyHeadStatementAST::CopyHeadStatementAST(VarExprAST* in_queue_ptr, - VarExprAST* out_queue_ptr, - PairListAST* pairs_ptr) - : StatementAST(pairs_ptr->getPairs()) -{ - m_in_queue_ptr = in_queue_ptr; - m_out_queue_ptr = out_queue_ptr; -} - -CopyHeadStatementAST::~CopyHeadStatementAST() -{ - delete m_in_queue_ptr; - delete m_out_queue_ptr; -} - -void CopyHeadStatementAST::generate(string& code, Type* return_type_ptr) const -{ - m_in_queue_ptr->assertType("InPort"); - m_out_queue_ptr->assertType("OutPort"); - - code += indent_str(); - code += m_out_queue_ptr->getVar()->getCode() + ".enqueue(" + m_in_queue_ptr->getVar()->getCode() + ".getMsgPtrCopy()"; - - if (getPairs().exist("latency")) { - code += ", " + getPairs().lookup("latency"); - } else { - code += ", COPY_HEAD_LATENCY"; - } - - code += ");\n"; -} - -void CopyHeadStatementAST::findResources(Map<Var*, string>& resource_list) const -{ - Var* var_ptr = m_out_queue_ptr->getVar(); - int res_count = 0; - if (resource_list.exist(var_ptr)) { - res_count = atoi((resource_list.lookup(var_ptr)).c_str()); - } - resource_list.add(var_ptr, int_to_string(res_count+1)); -} - -void CopyHeadStatementAST::print(ostream& out) const -{ - out << "[CopyHeadStatementAst: " << *m_in_queue_ptr << " " << *m_out_queue_ptr << "]"; -} diff --git a/src/mem/slicc/ast/CopyHeadStatementAST.hh b/src/mem/slicc/ast/CopyHeadStatementAST.hh deleted file mode 100644 index 53d479136..000000000 --- a/src/mem/slicc/ast/CopyHeadStatementAST.hh +++ /dev/null @@ -1,87 +0,0 @@ - -/* - * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer; - * redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution; - * neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/* - * $Id$ - * - */ - -#ifndef COPYHEADSTATEMENTAST_H -#define COPYHEADTATEMENTAST_H - -#include "mem/slicc/slicc_global.hh" -#include "mem/slicc/ast/StatementAST.hh" -#include "mem/slicc/ast/StatementListAST.hh" -#include "mem/slicc/ast/TypeAST.hh" -#include "mem/slicc/ast/PairListAST.hh" - -class VarExprAST; -class Var; - -class CopyHeadStatementAST : public StatementAST { -public: - // Constructors - CopyHeadStatementAST(VarExprAST* in_queue_ptr, - VarExprAST* out_queue_ptr, - PairListAST* pairs_ptr); - - // Destructor - ~CopyHeadStatementAST(); - - // Public Methods - void generate(string& code, Type* return_type_ptr) const; - void findResources(Map<Var*, string>& resource_list) const; - void print(ostream& out) const; -private: - // Private Methods - - // Private copy constructor and assignment operator - CopyHeadStatementAST(const CopyHeadStatementAST& obj); - CopyHeadStatementAST& operator=(const CopyHeadStatementAST& obj); - - // Data Members (m_ prefix) - VarExprAST* m_in_queue_ptr; - VarExprAST* m_out_queue_ptr; -}; - -// Output operator declaration -ostream& operator<<(ostream& out, const CopyHeadStatementAST& obj); - -// ******************* Definitions ******************* - -// Output operator definition -extern inline -ostream& operator<<(ostream& out, const CopyHeadStatementAST& obj) -{ - obj.print(out); - out << flush; - return out; -} - -#endif //COPYHEADSTATEMENTAST_H diff --git a/src/mem/slicc/ast/CopyHeadStatementAST.py b/src/mem/slicc/ast/CopyHeadStatementAST.py new file mode 100644 index 000000000..ba9970975 --- /dev/null +++ b/src/mem/slicc/ast/CopyHeadStatementAST.py @@ -0,0 +1,52 @@ +# Copyright (c) 1999-2008 Mark D. Hill and David A. Wood +# Copyright (c) 2009 The Hewlett-Packard Development Company +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer; +# redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution; +# neither the name of the copyright holders nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +from slicc.ast.StatementAST import StatementAST + +class CopyHeadStatementAST(StatementAST): + def __init__(self, slicc, in_queue, out_queue, pairs): + super(CopyHeadStatementAST, self).__init__(slicc, pairs) + + self.in_queue = in_queue + self.out_queue_ptr = out_queue + + def __repr__(self): + return "[CopyHeadStatementAst: %r %r]" % (self.in_queue, + self.out_queue) + + def generate(self, code, return_type): + self.in_queue.assertType("InPort") + self.out_queue.assertType("OutPort") + + out_code = self.out_queue.var.code + in_code = self.in_queue.var.code + latency = self.get("latency", "COPY_HEAD_LATENCY") + code("$out_code.enqueue($in_code.getMsgPtrCopy(), $latency);") + + def findResources(self, resources): + var = self.out_queue.var + resources[var] = str(int(resources.get(var, "0")) + 1) diff --git a/src/mem/slicc/ast/DeclAST.py b/src/mem/slicc/ast/DeclAST.py new file mode 100644 index 000000000..1adb31321 --- /dev/null +++ b/src/mem/slicc/ast/DeclAST.py @@ -0,0 +1,38 @@ +# Copyright (c) 1999-2008 Mark D. Hill and David A. Wood +# Copyright (c) 2009 The Hewlett-Packard Development Company +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer; +# redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution; +# neither the name of the copyright holders nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +from slicc.ast.AST import AST + +class DeclAST(AST): + def __init__(self, slicc, pairs): + super(DeclAST, self).__init__(slicc, pairs) + + def files(self, parent=None): + return set() + + def findMachines(self): + return diff --git a/src/mem/slicc/ast/DeclListAST.hh b/src/mem/slicc/ast/DeclListAST.hh deleted file mode 100644 index 1c2bc3c05..000000000 --- a/src/mem/slicc/ast/DeclListAST.hh +++ /dev/null @@ -1,84 +0,0 @@ - -/* - * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer; - * redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution; - * neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/* - * DeclListAST.hh - * - * Description: - * - * $Id: DeclListAST.hh,v 3.1 2001/12/12 01:00:12 milo Exp $ - * - */ - -#ifndef DeclListAST_H -#define DeclListAST_H - -#include "mem/slicc/slicc_global.hh" -#include "mem/slicc/ast/AST.hh" -#include "mem/slicc/ast/DeclAST.hh" - -class DeclListAST : public AST { -public: - // Constructors - DeclListAST(Vector<DeclAST*>* vec_ptr); - DeclListAST(DeclAST* statement_ptr); - - // Destructor - ~DeclListAST(); - - // Public Methods - void generate() const; - void findMachines() const; - void print(ostream& out) const; -private: - // Private Methods - - // Private copy constructor and assignment operator - DeclListAST(const DeclListAST& obj); - DeclListAST& operator=(const DeclListAST& obj); - - // Data Members (m_ prefix) - Vector<DeclAST*>* m_vec_ptr; -}; - -// Output operator declaration -ostream& operator<<(ostream& out, const DeclListAST& obj); - -// ******************* Definitions ******************* - -// Output operator definition -extern inline -ostream& operator<<(ostream& out, const DeclListAST& obj) -{ - obj.print(out); - out << flush; - return out; -} - -#endif //DeclListAST_H diff --git a/src/mem/slicc/ast/DeclListAST.py b/src/mem/slicc/ast/DeclListAST.py new file mode 100644 index 000000000..36c520070 --- /dev/null +++ b/src/mem/slicc/ast/DeclListAST.py @@ -0,0 +1,53 @@ +# Copyright (c) 1999-2008 Mark D. Hill and David A. Wood +# Copyright (c) 2009 The Hewlett-Packard Development Company +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer; +# redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution; +# neither the name of the copyright holders nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +from slicc.ast.AST import AST + +class DeclListAST(AST): + def __init__(self, slicc, decls): + super(DeclListAST, self).__init__(slicc) + + if not isinstance(decls, (list, tuple)): + decls = [ decls ] + self.decls = decls + + def __repr__(self): + return "[DeclListAST: %s]" % (', '.join(repr(d) for d in self.decls)) + + def files(self, parent=None): + s = set() + for decl in self.decls: + s |= decl.files(parent) + return s + + def generate(self): + for decl in self.decls: + decl.generate() + + def findMachines(self): + for decl in self.decls: + decl.findMachines() diff --git a/src/mem/slicc/ast/EnqueueStatementAST.cc b/src/mem/slicc/ast/EnqueueStatementAST.cc deleted file mode 100644 index a422d8a28..000000000 --- a/src/mem/slicc/ast/EnqueueStatementAST.cc +++ /dev/null @@ -1,111 +0,0 @@ - -/* - * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer; - * redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution; - * neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/* - * $Id$ - * - */ - -#include "mem/slicc/ast/EnqueueStatementAST.hh" -#include "mem/slicc/symbols/SymbolTable.hh" -#include "mem/slicc/ast/VarExprAST.hh" -#include "mem/slicc/ast/PairListAST.hh" -#include "mem/gems_common/util.hh" - -EnqueueStatementAST::EnqueueStatementAST(VarExprAST* queue_name_ptr, - TypeAST* type_name_ptr, - PairListAST* pairs_ptr, - StatementListAST* statement_list_ast_ptr) - : StatementAST(pairs_ptr->getPairs()) -{ - m_queue_name_ptr = queue_name_ptr; - m_type_name_ptr = type_name_ptr; - m_statement_list_ast_ptr = statement_list_ast_ptr; -} - -EnqueueStatementAST::~EnqueueStatementAST() -{ - delete m_queue_name_ptr; - delete m_type_name_ptr; - delete m_statement_list_ast_ptr; -} - -void EnqueueStatementAST::generate(string& code, Type* return_type_ptr) const -{ - code += indent_str() + "{\n"; // Start scope - inc_indent(); - g_sym_table.pushFrame(); - - Type* msg_type_ptr = m_type_name_ptr->lookupType(); - - // Add new local var to symbol table - g_sym_table.newSym(new Var("out_msg", getLocation(), msg_type_ptr, "out_msg", getPairs())); - - code += indent_str() + msg_type_ptr->cIdent() + " out_msg;\n"; // Declare message - m_statement_list_ast_ptr->generate(code, NULL); // The other statements - - code += indent_str(); - - m_queue_name_ptr->assertType("OutPort"); - code += "(" + m_queue_name_ptr->getVar()->getCode() + ")"; - code += ".enqueue(out_msg"; - - if (getPairs().exist("latency")) { - bool is_number = true; - string val = getPairs().lookup("latency"); - for (int i=0; i<val.size(); i++) - if (!isdigit(val[i])) is_number = false; - if (is_number) - code += ", " + getPairs().lookup("latency"); - else - code += ", m_" + getPairs().lookup("latency"); - } - - code += ");\n"; - - dec_indent(); - g_sym_table.popFrame(); - code += indent_str() + "}\n"; // End scope -} - -void EnqueueStatementAST::findResources(Map<Var*, string>& resource_list) const -{ - Var* var_ptr = m_queue_name_ptr->getVar(); - int res_count = 0; - if (resource_list.exist(var_ptr)) { - res_count = atoi((resource_list.lookup(var_ptr)).c_str()); - } - resource_list.add(var_ptr, int_to_string(res_count+1)); -} - -void EnqueueStatementAST::print(ostream& out) const -{ - out << "[EnqueueStatementAst: " << *m_queue_name_ptr << " " - << m_type_name_ptr->toString() << " " << *m_statement_list_ast_ptr << "]"; -} diff --git a/src/mem/slicc/ast/EnqueueStatementAST.hh b/src/mem/slicc/ast/EnqueueStatementAST.hh deleted file mode 100644 index fc2776ed7..000000000 --- a/src/mem/slicc/ast/EnqueueStatementAST.hh +++ /dev/null @@ -1,93 +0,0 @@ - -/* - * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer; - * redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution; - * neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/* - * EnqueueStatementAST.hh - * - * Description: - * - * $Id$ - * - */ - -#ifndef ENQUEUESTATEMENTAST_H -#define ENQUEUESTATEMENTAST_H - -#include "mem/slicc/slicc_global.hh" -#include "mem/slicc/ast/StatementAST.hh" -#include "mem/slicc/ast/StatementListAST.hh" -#include "mem/slicc/ast/TypeAST.hh" - -class VarExprAST; -class Var; -class PairListAST; - -class EnqueueStatementAST : public StatementAST { -public: - // Constructors - EnqueueStatementAST(VarExprAST* queue_name_ptr, - TypeAST* type_name_ptr, - PairListAST* pairs_ptr, - StatementListAST* statement_list_ast_ptr); - - // Destructor - ~EnqueueStatementAST(); - - // Public Methods - void generate(string& code, Type* return_type_ptr) const; - void findResources(Map<Var*, string>& resource_list) const; - void print(ostream& out) const; -private: - // Private Methods - - // Private copy constructor and assignment operator - EnqueueStatementAST(const EnqueueStatementAST& obj); - EnqueueStatementAST& operator=(const EnqueueStatementAST& obj); - - // Data Members (m_ prefix) - VarExprAST* m_queue_name_ptr; - TypeAST* m_type_name_ptr; - StatementListAST* m_statement_list_ast_ptr; -}; - -// Output operator declaration -ostream& operator<<(ostream& out, const EnqueueStatementAST& obj); - -// ******************* Definitions ******************* - -// Output operator definition -extern inline -ostream& operator<<(ostream& out, const EnqueueStatementAST& obj) -{ - obj.print(out); - out << flush; - return out; -} - -#endif //ENQUEUESTATEMENTAST_H diff --git a/src/mem/slicc/ast/EnqueueStatementAST.py b/src/mem/slicc/ast/EnqueueStatementAST.py new file mode 100644 index 000000000..faf966460 --- /dev/null +++ b/src/mem/slicc/ast/EnqueueStatementAST.py @@ -0,0 +1,86 @@ +# Copyright (c) 1999-2008 Mark D. Hill and David A. Wood +# Copyright (c) 2009 The Hewlett-Packard Development Company +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer; +# redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution; +# neither the name of the copyright holders nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +from slicc.ast.StatementAST import StatementAST +from slicc.symbols import Var + +class EnqueueStatementAST(StatementAST): + def __init__(self, slicc, queue_name, type_ast, pairs, statements): + super(EnqueueStatementAST, self).__init__(slicc, pairs) + + self.queue_name = queue_name + self.type_ast = type_ast + self.statements = statements + + def __repr__(self): + return "[EnqueueStatementAst: %s %s %s]" % \ + (self.queue_name, self.type_ast.ident, self.statements) + + def generate(self, code, return_type): + code("{") + code.indent() + self.symtab.pushFrame() + + msg_type = self.type_ast.type + + # Add new local var to symbol table + v = Var(self.symtab, "out_msg", self.location, msg_type, "out_msg", + self.pairs) + self.symtab.newSymbol(v) + + # Declare message + code("${{msg_type.ident}} out_msg;") + + # The other statements + t = self.statements.generate(code, None) + + self.queue_name.assertType("OutPort") + + args = [ "out_msg" ] + if "latency" in self: + latency = self["latency"] + try: + # see if this is an integer + latency = int(latency) + args.append("%s" % latency) + except ValueError: + # if not, it should be a member + args.append("m_%s" % latency) + + args = ", ".join(args) + code('(${{self.queue_name.var.code}}).enqueue($args);') + + + # End scope + self.symtab.popFrame() + code.dedent() + code("}") + + def findResources(self, resources): + var = self.queue_name.var + res_count = int(resources.get(var, 0)) + resources[var] = str(res_count + 1) diff --git a/src/mem/slicc/ast/EnumDeclAST.cc b/src/mem/slicc/ast/EnumDeclAST.cc deleted file mode 100644 index b051f3c8f..000000000 --- a/src/mem/slicc/ast/EnumDeclAST.cc +++ /dev/null @@ -1,98 +0,0 @@ - -/* - * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer; - * redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution; - * neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/* - * EnumDeclAST.C - * - * Description: See EnumDeclAST.hh - * - * $Id$ - * - */ - -#include "mem/slicc/ast/EnumDeclAST.hh" -#include "mem/slicc/main.hh" -#include "mem/slicc/symbols/SymbolTable.hh" - -EnumDeclAST::EnumDeclAST(TypeAST* type_ast_ptr, - PairListAST* pairs_ptr, - Vector<TypeFieldAST*>* field_vec_ptr) - : DeclAST(pairs_ptr) -{ - m_type_ast_ptr = type_ast_ptr; - m_field_vec_ptr = field_vec_ptr; -} - -EnumDeclAST::~EnumDeclAST() -{ - delete m_type_ast_ptr; - if (m_field_vec_ptr != NULL) { - int size = m_field_vec_ptr->size(); - for(int i=0; i<size; i++) { - delete (*m_field_vec_ptr)[i]; - } - delete m_field_vec_ptr; - } -} - -void EnumDeclAST::generate() -{ - string machine_name; - string id = m_type_ast_ptr->toString(); - - Vector<Type*> param_type_vec; // used by to_string func call - - // Make the new type - Type* new_type_ptr = new Type(id, getLocation(), getPairs(), - g_sym_table.getStateMachine()); - g_sym_table.newSym(new_type_ptr); - - // Add all of the fields of the type to it - if (m_field_vec_ptr != NULL) { - int size = m_field_vec_ptr->size(); - for(int i=0; i<size; i++) { - (*m_field_vec_ptr)[i]->generate(new_type_ptr); - } - } - - // Add the implicit State_to_string method - FIXME, this is a bit dirty - param_type_vec.insertAtBottom(new_type_ptr); // add state to param vector - string func_id = new_type_ptr->cIdent()+"_to_string"; - - Map<string, string> pairs; - pairs.add("external", "yes"); - Vector<string> string_vec; - g_sym_table.newSym(new Func(func_id, getLocation(), g_sym_table.getType("string"), param_type_vec, string_vec, string(""), pairs, NULL)); -} - -void EnumDeclAST::print(ostream& out) const -{ - out << "[EnumDecl: " << m_type_ast_ptr->toString() << "]"; -} - diff --git a/src/mem/slicc/ast/EnumDeclAST.hh b/src/mem/slicc/ast/EnumDeclAST.hh deleted file mode 100644 index 2af650e83..000000000 --- a/src/mem/slicc/ast/EnumDeclAST.hh +++ /dev/null @@ -1,86 +0,0 @@ - -/* - * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer; - * redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution; - * neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/* - * EnummDeclAST.hh - * - * Description: - * - * $Id$ - * - */ - -#ifndef EnumDeclAST_H -#define EnumDeclAST_H - -#include "mem/slicc/slicc_global.hh" -#include "mem/slicc/ast/DeclAST.hh" -#include "mem/slicc/ast/TypeAST.hh" -#include "mem/slicc/ast/TypeFieldAST.hh" - -class EnumDeclAST : public DeclAST { -public: - // Constructors - EnumDeclAST(TypeAST* type_ast_ptr, - PairListAST* pairs_ptr, - Vector<TypeFieldAST*>* field_vec_ptr); - - // Destructor - ~EnumDeclAST(); - - // Public Methods - virtual void generate(); - void print(ostream& out) const; -private: - // Private Methods - - // Private copy constructor and assignment operator - EnumDeclAST(const EnumDeclAST& obj); - EnumDeclAST& operator=(const EnumDeclAST& obj); - - // Data Members (m_ prefix) - TypeAST* m_type_ast_ptr; - Vector<TypeFieldAST*>* m_field_vec_ptr; -}; - -// Output operator declaration -ostream& operator<<(ostream& out, const EnumDeclAST& obj); - -// ******************* Definitions ******************* - -// Output operator definition -extern inline -ostream& operator<<(ostream& out, const EnumDeclAST& obj) -{ - obj.print(out); - out << flush; - return out; -} - -#endif //EnumDeclAST_H diff --git a/src/mem/slicc/ast/EnumDeclAST.py b/src/mem/slicc/ast/EnumDeclAST.py new file mode 100644 index 000000000..a20f4b749 --- /dev/null +++ b/src/mem/slicc/ast/EnumDeclAST.py @@ -0,0 +1,71 @@ +# Copyright (c) 1999-2008 Mark D. Hill and David A. Wood +# Copyright (c) 2009 The Hewlett-Packard Development Company +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer; +# redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution; +# neither the name of the copyright holders nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +from slicc.ast.DeclAST import DeclAST +from slicc.symbols import Func, Type + +class EnumDeclAST(DeclAST): + def __init__(self, slicc, type_ast, pairs, fields): + super(EnumDeclAST, self).__init__(slicc, pairs) + + self.type_ast = type_ast + self.fields = fields + + def __repr__(self): + return "[EnumDecl: %s]" % (self.type_ast) + + def files(self, parent=None): + if "external" in self: + return set() + + if parent: + ident = "%s_%s" % (parent, self.type_ast.ident) + else: + ident = self.type_ast.ident + s = set(("%s.hh" % ident, "%s.cc" % ident)) + return s + + def generate(self): + ident = str(self.type_ast) + + # Make the new type + t = Type(self.symtab, ident, self.location, self.pairs, + self.state_machine) + self.symtab.newSymbol(t) + + # Add all of the fields of the type to it + for field in self.fields: + field.generate(t) + + # Add the implicit State_to_string method - FIXME, this is a bit dirty + func_id = "%s_to_string" % t.c_ident + + pairs = { "external" : "yes" } + func = Func(self.symtab, func_id, self.location, + self.symtab.find("string", Type), [ t ], [], "", + pairs, None) + self.symtab.newSymbol(func) diff --git a/src/mem/slicc/ast/EnumExprAST.hh b/src/mem/slicc/ast/EnumExprAST.hh deleted file mode 100644 index 8af1c8891..000000000 --- a/src/mem/slicc/ast/EnumExprAST.hh +++ /dev/null @@ -1,85 +0,0 @@ - -/* - * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer; - * redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution; - * neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/* - * EnumExprAST.hh - * - * Description: - * - * $Id: EnumExprAST.hh,v 3.2 2003/07/10 18:08:06 milo Exp $ - * - */ - -#ifndef EnumExprAST_H -#define EnumExprAST_H - -#include "mem/slicc/slicc_global.hh" -#include "mem/slicc/ast/ExprAST.hh" -#include "mem/slicc/ast/TypeAST.hh" - - -class EnumExprAST : public ExprAST { -public: - // Constructors - EnumExprAST(TypeAST* type_ast_ptr, - string* value_ptr); - - // Destructor - ~EnumExprAST(); - - // Public Methods - Type* generate(string& code) const; - void print(ostream& out) const; -private: - // Private Methods - - // Private copy constructor and assignment operator - EnumExprAST(const EnumExprAST& obj); - EnumExprAST& operator=(const EnumExprAST& obj); - - // Data Members (m_ prefix) - TypeAST* m_type_ast_ptr; - string* m_value_ptr; -}; - -// Output operator declaration -ostream& operator<<(ostream& out, const EnumExprAST& obj); - -// ******************* Definitions ******************* - -// Output operator definition -extern inline -ostream& operator<<(ostream& out, const EnumExprAST& obj) -{ - obj.print(out); - out << flush; - return out; -} - -#endif //EnumExprAST_H diff --git a/src/mem/slicc/ast/EnumExprAST.py b/src/mem/slicc/ast/EnumExprAST.py new file mode 100644 index 000000000..9cb76a8a1 --- /dev/null +++ b/src/mem/slicc/ast/EnumExprAST.py @@ -0,0 +1,53 @@ +# Copyright (c) 1999-2008 Mark D. Hill and David A. Wood +# Copyright (c) 2009 The Hewlett-Packard Development Company +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer; +# redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution; +# neither the name of the copyright holders nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +from slicc.ast.ExprAST import ExprAST + +class EnumExprAST(ExprAST): + def __init__(self, slicc, type_ast, value): + super(EnumExprAST, self).__init__(slicc) + + assert type_ast + assert value + + self.type_ast = type_ast + self.value = value + + def __repr__(self): + return "[EnumExpr: %s:%s]" % (self.type_ast, self.value) + + def generate(self, code): + fix = code.nofix() + code('${{self.type_ast.type.c_ident}}_${{self.value}}') + code.fix(fix) + + # Make sure the enumeration value exists + if self.value not in self.type_ast.type.enums: + self.error("Type '%s' does not have enumeration '%s'", + self.type_ast, self.value) + + return self.type_ast.type diff --git a/src/mem/slicc/ast/ExprAST.cc b/src/mem/slicc/ast/ExprAST.cc deleted file mode 100644 index 3427d4dd9..000000000 --- a/src/mem/slicc/ast/ExprAST.cc +++ /dev/null @@ -1,39 +0,0 @@ - -/* - * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer; - * redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution; - * neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/* - * ExprAST.C - * - * Description: See ExprAST.hh - * - * $Id$ - * - */ - -#include "mem/slicc/ast/ExprAST.hh" diff --git a/src/mem/slicc/ast/ExprAST.py b/src/mem/slicc/ast/ExprAST.py new file mode 100644 index 000000000..70a0aa0b5 --- /dev/null +++ b/src/mem/slicc/ast/ExprAST.py @@ -0,0 +1,45 @@ +# Copyright (c) 2009 The Hewlett-Packard Development Company +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer; +# redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution; +# neither the name of the copyright holders nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +from m5.util import code_formatter + +from slicc.ast.AST import AST + +class ExprAST(AST): + def __init__(self, slicc): + super(ExprAST, self).__init__(slicc) + + def findResources(self, resources): + # The default is no resources + pass + + def inline(self, get_type=False): + code = code_formatter(fix_newlines=False) + return_type = self.generate(code) + if get_type: + return return_type, code + else: + return code diff --git a/src/mem/slicc/ast/ExprStatementAST.hh b/src/mem/slicc/ast/ExprStatementAST.hh deleted file mode 100644 index a47e86af5..000000000 --- a/src/mem/slicc/ast/ExprStatementAST.hh +++ /dev/null @@ -1,83 +0,0 @@ - -/* - * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer; - * redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution; - * neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/* - * ExprStatementAST.hh - * - * Description: - * - * $Id$ - * - */ - -#ifndef ExprStatementAST_H -#define ExprStatementAST_H - -#include "mem/slicc/slicc_global.hh" -#include "mem/slicc/ast/StatementAST.hh" -#include "mem/slicc/ast/ExprAST.hh" - -class ExprStatementAST : public StatementAST { -public: - // Constructors - ExprStatementAST(ExprAST* expr_ptr); - - // Destructor - ~ExprStatementAST(); - - // Public Methods - void generate(string& code, Type* return_type_ptr) const; - void findResources(Map<Var*, string>& resource_list) const; - void print(ostream& out) const; -private: - // Private Methods - - // Private copy constructor and assignment operator - ExprStatementAST(const ExprStatementAST& obj); - ExprStatementAST& operator=(const ExprStatementAST& obj); - - // Data Members (m_ prefix) - ExprAST* m_expr_ptr; -}; - -// Output operator declaration -ostream& operator<<(ostream& out, const ExprStatementAST& obj); - -// ******************* Definitions ******************* - -// Output operator definition -extern inline -ostream& operator<<(ostream& out, const ExprStatementAST& obj) -{ - obj.print(out); - out << flush; - return out; -} - -#endif //ExprStatementAST_H diff --git a/src/mem/slicc/ast/ExprStatementAST.py b/src/mem/slicc/ast/ExprStatementAST.py new file mode 100644 index 000000000..b16d1d072 --- /dev/null +++ b/src/mem/slicc/ast/ExprStatementAST.py @@ -0,0 +1,52 @@ +# Copyright (c) 1999-2008 Mark D. Hill and David A. Wood +# Copyright (c) 2009 The Hewlett-Packard Development Company +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer; +# redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution; +# neither the name of the copyright holders nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +from m5.util import code_formatter + +from slicc.ast.StatementAST import StatementAST +from slicc.symbols import Type + +class ExprStatementAST(StatementAST): + def __init__(self, slicc, expr): + super(ExprStatementAST, self).__init__(slicc) + self.expr = expr + + def __repr__(self): + return "[ExprStatementAST: %s]" % (self.expr) + + def generate(self, code, return_type): + actual_type,rcode = self.expr.inline(True) + code("$rcode;") + + # The return type must be void + if actual_type != self.symtab.find("void", Type): + self.expr.error("Non-void return must not be ignored, " + \ + "return type is '%s'", actual_type.ident) + + def findResources(self, resources): + self.expr.findResources(resources) + diff --git a/src/mem/slicc/ast/FormalParamAST.cc b/src/mem/slicc/ast/FormalParamAST.cc deleted file mode 100644 index 529811f25..000000000 --- a/src/mem/slicc/ast/FormalParamAST.cc +++ /dev/null @@ -1,72 +0,0 @@ - -/* - * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer; - * redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution; - * neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/* - * FormalParamAST.C - * - * Description: See FormalParamAST.hh - * - * $Id: FormalParamAST.C,v 3.1 2000/10/05 21:22:20 milo Exp $ - * - */ - -#include "mem/slicc/ast/FormalParamAST.hh" -#include "mem/slicc/ast/StatementAST.hh" -#include "mem/slicc/ast/TypeAST.hh" -#include "mem/slicc/symbols/SymbolTable.hh" - -FormalParamAST::~FormalParamAST() -{ - delete m_ident_ptr; - delete m_type_ast_ptr; -} - -string FormalParamAST::getTypeName() const -{ - return m_type_ast_ptr->toString(); -} - -Type* FormalParamAST::getType() const -{ - return m_type_ast_ptr->lookupType(); -} - -Type* FormalParamAST::generate(string& code) const -{ - string param = "param_" + *m_ident_ptr; - - Type* type_ptr = m_type_ast_ptr->lookupType(); - code += type_ptr->cIdent(); - code += " "; - code += param; - - // Add to symbol table - g_sym_table.newSym(new Var(*m_ident_ptr, getLocation(), type_ptr, param, getPairs())); - return type_ptr; -} diff --git a/src/mem/slicc/ast/FormalParamAST.hh b/src/mem/slicc/ast/FormalParamAST.hh deleted file mode 100644 index ca27948b7..000000000 --- a/src/mem/slicc/ast/FormalParamAST.hh +++ /dev/null @@ -1,88 +0,0 @@ - -/* - * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer; - * redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution; - * neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/* - * FormalParamAST.hh - * - * Description: - * - * $Id: FormalParamAST.hh,v 3.1 2001/12/12 01:00:15 milo Exp $ - * - */ - -#ifndef FORMALPARAMAST_H -#define FORMALPARAMAST_H - -#include "mem/slicc/slicc_global.hh" -#include "mem/slicc/ast/AST.hh" - -class TypeAST; - - -class FormalParamAST : public AST { -public: - // Constructors - FormalParamAST(TypeAST* type_ast_ptr, string* ident_ptr) : AST() { m_type_ast_ptr = type_ast_ptr; m_ident_ptr = ident_ptr; } - - // Destructor - ~FormalParamAST(); - - // Public Methods - Type* generate(string& code) const; - void print(ostream& out) const { out << "[FormalParamAST: " << *m_ident_ptr << "]"; } - string getName() const { return *m_ident_ptr; } - string getTypeName() const; - Type* getType() const; -private: - // Private Methods - - // Private copy constructor and assignment operator - FormalParamAST(const FormalParamAST& obj); - FormalParamAST& operator=(const FormalParamAST& obj); - - // Data Members (m_ prefix) - string* m_ident_ptr; - TypeAST* m_type_ast_ptr; -}; - -// Output operator declaration -ostream& operator<<(ostream& out, const FormalParamAST& obj); - -// ******************* Definitions ******************* - -// Output operator definition -extern inline -ostream& operator<<(ostream& out, const FormalParamAST& obj) -{ - obj.print(out); - out << flush; - return out; -} - -#endif //FORMALPARAMAST_H diff --git a/src/mem/slicc/ast/FormalParamAST.py b/src/mem/slicc/ast/FormalParamAST.py new file mode 100644 index 000000000..b169cbb1c --- /dev/null +++ b/src/mem/slicc/ast/FormalParamAST.py @@ -0,0 +1,52 @@ +# Copyright (c) 1999-2008 Mark D. Hill and David A. Wood +# Copyright (c) 2009 The Hewlett-Packard Development Company +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer; +# redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution; +# neither the name of the copyright holders nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +from slicc.ast.AST import AST +from slicc.symbols import Var + +class FormalParamAST(AST): + def __init__(self, slicc, type_ast, ident): + super(FormalParamAST, self).__init__(slicc) + self.type_ast = type_ast + self.ident = ident + + def __repr__(self): + return "[FormalParamAST: %s]" % self.ident + + @property + def name(self): + return self.ident + + def generate(self): + type = self.type_ast.type + param = "param_%s" % self.ident + + # Add to symbol table + v = Var(self.symtab, self.ident, self.location, type, param, + self.pairs) + self.symtab.newSymbol(v) + return type, "%s %s" % (type.c_ident, param) diff --git a/src/mem/slicc/ast/FuncCallExprAST.cc b/src/mem/slicc/ast/FuncCallExprAST.cc deleted file mode 100644 index 5b19017e9..000000000 --- a/src/mem/slicc/ast/FuncCallExprAST.cc +++ /dev/null @@ -1,224 +0,0 @@ - -/* - * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer; - * redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution; - * neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/* - * FuncCallExprAST.C - * - * Description: See FuncCallExprAST.hh - * - * $Id$ - * - */ - -#include "mem/slicc/ast/FuncCallExprAST.hh" -#include "mem/slicc/symbols/SymbolTable.hh" - -FuncCallExprAST::FuncCallExprAST(string* proc_name_ptr, - Vector<ExprAST*>* expr_vec_ptr) - : ExprAST() -{ - m_proc_name_ptr = proc_name_ptr; - m_expr_vec_ptr = expr_vec_ptr; -} - -FuncCallExprAST::~FuncCallExprAST() -{ - delete m_proc_name_ptr; - int size = m_expr_vec_ptr->size(); - for(int i=0; i<size; i++) { - delete (*m_expr_vec_ptr)[i]; - } - delete m_expr_vec_ptr; -} - -Type* FuncCallExprAST::generate(string& code) const -{ - // DEBUG_EXPR is strange since it takes parameters of multiple types - if (*m_proc_name_ptr == "DEBUG_EXPR") { - // FIXME - check for number of parameters - code += "DEBUG_SLICC(MedPrio, \""; - code += (*m_expr_vec_ptr)[0]->getLocation().toString(); - code += ": \", "; - (*m_expr_vec_ptr)[0]->generate(code); - code += ");\n"; - Type* void_type_ptr = g_sym_table.getType("void"); - assert(void_type_ptr != NULL); - return void_type_ptr; - } - - // hack for adding comments to profileTransition - if (*m_proc_name_ptr == "APPEND_TRANSITION_COMMENT") { - // FIXME - check for number of parameters - code += "APPEND_TRANSITION_COMMENT("; - //code += (*m_expr_vec_ptr)[0]->getLocation().toString(); - //code += ": \", "; - (*m_expr_vec_ptr)[0]->generate(code); - code += ");\n"; - Type* void_type_ptr = g_sym_table.getType("void"); - assert(void_type_ptr != NULL); - return void_type_ptr; - } - - // Look up the function in the symbol table - Vector<string> code_vec; - Func* func_ptr = g_sym_table.getFunc(*m_proc_name_ptr); - - // Check the types and get the code for the parameters - if (func_ptr == NULL) { - error("Unrecognized function name: '" + *m_proc_name_ptr + "'"); - } else { - int size = m_expr_vec_ptr->size(); - - Vector<Type*> f = func_ptr->getParamTypes(); - - if (size != f.size() ) { - error("Wrong number of arguments passed to function : '" + *m_proc_name_ptr + "'"); - } - else { - for(int i=0; i<size; i++) { - - // Check the types of the parameter - string param_code; - Type* actual_type_ptr = (*m_expr_vec_ptr)[i]->generate(param_code); - Type* expected_type_ptr = func_ptr->getParamTypes()[i]; - if (actual_type_ptr != expected_type_ptr) { - (*m_expr_vec_ptr)[i]->error("Type mismatch: expected: " + expected_type_ptr->toString() + - " actual: " + actual_type_ptr->toString()); - } - code_vec.insertAtBottom(param_code); - } - } - } - - /* OK, the semantics of "trigger" here is that, ports in the machine have - * different priorities. We always check the first port for doable - * transitions. If nothing/stalled, we pick one from the next port. - * - * One thing we have to be careful as the SLICC protocol writter is : - * If a port have two or more transitions can be picked from in one cycle, - * they must be independent. Otherwise, if transition A and B mean to be - * executed in sequential, and A get stalled, transition B can be issued - * erroneously. In practice, in most case, there is only one transition - * should be executed in one cycle for a given port. So as most of current - * protocols. - */ - - if (*m_proc_name_ptr == "trigger") { - code += indent_str() + "{\n"; - code += indent_str() + " Address addr = "; - code += code_vec[1]; - code += ";\n"; - code += indent_str() + " TransitionResult result = doTransition("; - code += code_vec[0]; - code += ", " + g_sym_table.getStateMachine()->toString() + "_getState(addr), addr"; - if(CHECK_INVALID_RESOURCE_STALLS) { - // FIXME - the current assumption is that in_buffer_rank is declared in the msg buffer peek statement - code += ", in_buffer_rank"; - } - code += ");\n"; - code += indent_str() + " if (result == TransitionResult_Valid) {\n"; - code += indent_str() + " counter++;\n"; - code += indent_str() + " continue; // Check the first port again\n"; - code += indent_str() + " }\n"; - code += indent_str() + " if (result == TransitionResult_ResourceStall) {\n"; - code += indent_str() + " g_eventQueue_ptr->scheduleEvent(this, 1);\n"; - code += indent_str() + " // Cannot do anything with this transition, go check next doable transition (mostly likely of next port)\n"; - code += indent_str() + " }\n"; - code += indent_str() + "}\n"; - } else if (*m_proc_name_ptr == "doubleTrigger") { - // NOTE: Use the doubleTrigger call with extreme caution - // the key to double trigger is the second event triggered cannot fail becuase the first event cannot be undone - assert(code_vec.size() == 4); - code += indent_str() + "{\n"; - code += indent_str() + " Address addr1 = "; - code += code_vec[1]; - code += ";\n"; - code += indent_str() + " TransitionResult result1 = doTransition("; - code += code_vec[0]; - code += ", " + g_sym_table.getStateMachine()->toString() + "_getState(addr1), addr1"; - if(CHECK_INVALID_RESOURCE_STALLS) { - // FIXME - the current assumption is that in_buffer_rank is declared in the msg buffer peek statement - code += ", in_buffer_rank"; - } - code += ");\n"; - code += indent_str() + " if (result1 == TransitionResult_Valid) {\n"; - code += indent_str() + " //this second event cannont fail because the first event already took effect\n"; - code += indent_str() + " Address addr2 = "; - code += code_vec[3]; - code += ";\n"; - code += indent_str() + " TransitionResult result2 = doTransition("; - code += code_vec[2]; - code += ", " + g_sym_table.getStateMachine()->toString() + "_getState(addr2), addr2"; - if(CHECK_INVALID_RESOURCE_STALLS) { - // FIXME - the current assumption is that in_buffer_rank is declared in the msg buffer peek statement - code += ", in_buffer_rank"; - } - code += ");\n"; - code += indent_str() + " assert(result2 == TransitionResult_Valid); // ensure the event suceeded\n"; - code += indent_str() + " counter++;\n"; - code += indent_str() + " continue; // Check the first port again\n"; - code += indent_str() + " }\n"; - code += indent_str() + " if (result1 == TransitionResult_ResourceStall) {\n"; - code += indent_str() + " g_eventQueue_ptr->scheduleEvent(this, 1);\n"; - code += indent_str() + " // Cannot do anything with this transition, go check next doable transition (mostly likely of next port)\n"; - code += indent_str() + " }\n"; - code += indent_str() + "}\n"; - } else if (*m_proc_name_ptr == "error") { - code += indent_str() + (*m_expr_vec_ptr)[0]->embedError(code_vec[0]) + "\n"; - } else if (*m_proc_name_ptr == "assert") { - code += indent_str() + "if (ASSERT_FLAG && !(" + code_vec[0] + ")) {\n"; - code += indent_str() + " " + (*m_expr_vec_ptr)[0]->embedError("\"assert failure\"") + "\n"; - code += indent_str() + "}\n"; - } else if (*m_proc_name_ptr == "continueProcessing") { - code += "counter++; continue; // Check the first port again"; - } else { - // Normal function - code += "("; - // if the func is internal to the chip but not the machine then it can only be - // accessed through the chip pointer - if (!func_ptr->existPair("external") && !func_ptr->isInternalMachineFunc()) { - code += "m_chip_ptr->"; - } - code += func_ptr->cIdent() + "("; - int size = code_vec.size(); - for(int i=0; i<size; i++) { - if (i != 0) { - code += ", "; - } - code += code_vec[i]; - } - code += "))"; - } - return func_ptr->getReturnType(); -} - -void FuncCallExprAST::print(ostream& out) const -{ - out << "[FuncCallExpr: " << *m_proc_name_ptr << " " << *m_expr_vec_ptr << "]"; -} diff --git a/src/mem/slicc/ast/FuncCallExprAST.hh b/src/mem/slicc/ast/FuncCallExprAST.hh deleted file mode 100644 index 6c02122ee..000000000 --- a/src/mem/slicc/ast/FuncCallExprAST.hh +++ /dev/null @@ -1,89 +0,0 @@ - -/* - * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer; - * redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution; - * neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/* - * FuncCallExprAST.hh - * - * Description: - * - * $Id$ - * - */ - -#ifndef FUNCCALLEXPRAST_H -#define FUNCCALLEXPRAST_H - -#include "mem/slicc/slicc_global.hh" -#include "mem/slicc/ast/StatementAST.hh" -#include "mem/slicc/ast/ExprAST.hh" - - -// ProcGen decl -class FuncGen; - -class FuncCallExprAST : public ExprAST { -public: - // Constructors - FuncCallExprAST(string* proc_name_ptr, - Vector<ExprAST*>* expr_vec_ptr); - - // Destructor - ~FuncCallExprAST(); - - // Public Methods - Type* generate(string& code) const; - void print(ostream& out) const; - -private: - // Private Methods - - // Private copy constructor and assignment operator - FuncCallExprAST(const FuncCallExprAST& obj); - FuncCallExprAST& operator=(const FuncCallExprAST& obj); - - // Data Members (m_ prefix) - string* m_proc_name_ptr; - Vector<ExprAST*>* m_expr_vec_ptr; -}; - -// Output operator declaration -ostream& operator<<(ostream& out, const FuncCallExprAST& obj); - -// ******************* Definitions ******************* - -// Output operator definition -extern inline -ostream& operator<<(ostream& out, const FuncCallExprAST& obj) -{ - obj.print(out); - out << flush; - return out; -} - -#endif //FUNCCALLEXPRAST_H diff --git a/src/mem/slicc/ast/FuncCallExprAST.py b/src/mem/slicc/ast/FuncCallExprAST.py new file mode 100644 index 000000000..abf7eec7b --- /dev/null +++ b/src/mem/slicc/ast/FuncCallExprAST.py @@ -0,0 +1,168 @@ +# Copyright (c) 1999-2008 Mark D. Hill and David A. Wood +# Copyright (c) 2009 The Hewlett-Packard Development Company +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer; +# redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution; +# neither the name of the copyright holders nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +from slicc.ast.ExprAST import ExprAST +from slicc.symbols import Func, Type + +class FuncCallExprAST(ExprAST): + def __init__(self, slicc, proc_name, exprs): + super(FuncCallExprAST, self).__init__(slicc) + self.proc_name = proc_name + self.exprs = exprs + + def __repr__(self): + return "[FuncCallExpr: %s %s]" % (self.proc_name, self.exprs) + + def generate(self, code): + machine = self.state_machine + + # DEBUG_EXPR is strange since it takes parameters of multiple types + if self.proc_name == "DEBUG_EXPR": + # FIXME - check for number of parameters + code('DEBUG_SLICC(MedPrio, "$0: ", $1)', + self.exprs[0].location, self.exprs[0].inline()) + + return self.symtab.find("void", Type) + + # hack for adding comments to profileTransition + if self.proc_name == "APPEND_TRANSITION_COMMENT": + # FIXME - check for number of parameters + code("APPEND_TRANSITION_COMMENT($0)", self.exprs[0].inline()) + return self.symtab.find("void", Type) + + # Look up the function in the symbol table + func = self.symtab.find(self.proc_name, Func) + + # Check the types and get the code for the parameters + if func is None: + self.error("Unrecognized function name: '%s'", self.proc_name) + + if len(self.exprs) != len(func.param_types): + self.error("Wrong number of arguments passed to function : '%s'" +\ + " Expected %d, got %d", self.proc_name, + len(func.param_types), len(self.exprs)) + + cvec = [] + for expr,expected_type in zip(self.exprs, func.param_types): + # Check the types of the parameter + actual_type,param_code = expr.inline(True) + if actual_type != expected_type: + expr.error("Type mismatch: expected: %s actual: %s" % \ + (expected_type, actual_type)) + cvec.append(param_code) + + # OK, the semantics of "trigger" here is that, ports in the + # machine have different priorities. We always check the first + # port for doable transitions. If nothing/stalled, we pick one + # from the next port. + # + # One thing we have to be careful as the SLICC protocol + # writter is : If a port have two or more transitions can be + # picked from in one cycle, they must be independent. + # Otherwise, if transition A and B mean to be executed in + # sequential, and A get stalled, transition B can be issued + # erroneously. In practice, in most case, there is only one + # transition should be executed in one cycle for a given + # port. So as most of current protocols. + + if self.proc_name == "trigger": + code(''' +{ + Address addr = ${{cvec[1]}}; + TransitionResult result = doTransition(${{cvec[0]}}, ${machine}_getState(addr), addr); + + if (result == TransitionResult_Valid) { + counter++; + continue; // Check the first port again + } + + if (result == TransitionResult_ResourceStall) { + g_eventQueue_ptr->scheduleEvent(this, 1); + + // Cannot do anything with this transition, go check next doable transition (mostly likely of next port) + } +} +''') + elif self.proc_name == "doubleTrigger": + # NOTE: Use the doubleTrigger call with extreme caution + # the key to double trigger is the second event triggered + # cannot fail becuase the first event cannot be undone + assert len(cvec) == 4 + code(''' +{ + Address addr1 = ${{cvec[1]}}; + TransitionResult result1 = + doTransition(${{cvec[0]}}, ${machine}_getState(addr1), addr1); + + if (result1 == TransitionResult_Valid) { + //this second event cannont fail because the first event + // already took effect + Address addr2 = ${{cvec[3]}}; + TransitionResult result2 = doTransition(${{cvec[2]}}, ${machine}_getState(addr2), addr2); + + // ensure the event suceeded + assert(result2 == TransitionResult_Valid); + + counter++; + continue; // Check the first port again + } + + if (result1 == TransitionResult_ResourceStall) { + g_eventQueue_ptr->scheduleEvent(this, 1); + // Cannot do anything with this transition, go check next + // doable transition (mostly likely of next port) + } +} +''') + elif self.proc_name == "error": + code("$0", self.exprs[0].embedError(cvec[0])) + elif self.proc_name == "assert": + error = self.exprs[0].embedError('"assert failure"') + code(''' +if (ASSERT_FLAG && !(${{cvec[0]}})) { + $error +} +''') + + elif self.proc_name == "continueProcessing": + code("counter++;") + code("continue; // Check the first port again") + else: + # Normal function + + # if the func is internal to the chip but not the machine + # then it can only be accessed through the chip pointer + internal = "" + if "external" not in func and not func.isInternalMachineFunc: + internal = "m_chip_ptr->" + + params = ', '.join(str(c) for c in cvec) + fix = code.nofix() + code('(${internal}${{func.c_ident}}($params))') + code.fix(fix) + + return func.return_type diff --git a/src/mem/slicc/ast/FuncDeclAST.cc b/src/mem/slicc/ast/FuncDeclAST.cc deleted file mode 100644 index 2a0905f06..000000000 --- a/src/mem/slicc/ast/FuncDeclAST.cc +++ /dev/null @@ -1,112 +0,0 @@ - -/* - * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer; - * redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution; - * neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/* - * FuncDeclAST.C - * - * Description: See FuncDeclAST.hh - * - * $Id: FuncDeclAST.C,v 3.4 2003/08/22 18:19:34 beckmann Exp $ - * - */ - -#include "mem/slicc/ast/FuncDeclAST.hh" -#include "mem/slicc/ast/FormalParamAST.hh" -#include "mem/slicc/symbols/SymbolTable.hh" -#include "mem/slicc/main.hh" - -FuncDeclAST::FuncDeclAST(TypeAST* return_type_ast_ptr, - string* ident_ptr, - Vector<FormalParamAST*>* formal_vec_ptr, - PairListAST* pairs_ptr, - StatementListAST* statement_list_ptr) - : DeclAST(pairs_ptr) -{ - m_return_type_ast_ptr = return_type_ast_ptr; - m_ident_ptr = ident_ptr; - m_formal_vec_ptr = formal_vec_ptr; - m_statement_list_ptr = statement_list_ptr; -} - -FuncDeclAST::~FuncDeclAST() -{ - delete m_return_type_ast_ptr; - delete m_ident_ptr; - - int size = m_formal_vec_ptr->size(); - for(int i=0; i<size; i++) { - delete (*m_formal_vec_ptr)[i]; - } - delete m_formal_vec_ptr; - delete m_statement_list_ptr; -} - -void FuncDeclAST::generate() -{ - Vector<Type*> type_vec; - Vector<string> param_vec; - Type* void_type_ptr = g_sym_table.getType("void"); - - // Generate definition code - g_sym_table.pushFrame(); - - // Lookup return type - Type* return_type_ptr = m_return_type_ast_ptr->lookupType(); - - // Generate function header - int size = m_formal_vec_ptr->size(); - for(int i=0; i<size; i++) { - // Lookup parameter types - string ident; - Type* type_ptr = (*m_formal_vec_ptr)[i]->generate(ident); - type_vec.insertAtBottom(type_ptr); - param_vec.insertAtBottom(ident); - } - - string body; - if (m_statement_list_ptr == NULL) { - getPairs().add("external", "yes"); - } else { - m_statement_list_ptr->generate(body, return_type_ptr); - } - g_sym_table.popFrame(); - - StateMachine* machine_ptr = g_sym_table.getStateMachine(); - if (machine_ptr != NULL) { - machine_ptr->addFunc(new Func(*m_ident_ptr, getLocation(), return_type_ptr, type_vec, param_vec, body, getPairs(), machine_ptr)); - } else { - g_sym_table.newSym(new Func(*m_ident_ptr, getLocation(), return_type_ptr, type_vec, param_vec, body, getPairs(), machine_ptr)); - } - -} - -void FuncDeclAST::print(ostream& out) const -{ - out << "[FuncDecl: " << *m_ident_ptr << "]"; -} diff --git a/src/mem/slicc/ast/FuncDeclAST.hh b/src/mem/slicc/ast/FuncDeclAST.hh deleted file mode 100644 index 205e71a85..000000000 --- a/src/mem/slicc/ast/FuncDeclAST.hh +++ /dev/null @@ -1,91 +0,0 @@ - -/* - * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer; - * redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution; - * neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/* - * FuncDeclAST.hh - * - * Description: - * - * $Id: FuncDeclAST.hh,v 3.2 2003/07/10 18:08:06 milo Exp $ - * - */ - -#ifndef FuncDeclAST_H -#define FuncDeclAST_H - -#include "mem/slicc/slicc_global.hh" -#include "mem/slicc/ast/DeclAST.hh" -#include "mem/slicc/ast/TypeFieldAST.hh" -#include "mem/slicc/ast/TypeAST.hh" - -class FormalParamsAST; - -class FuncDeclAST : public DeclAST { -public: - // Constructors - FuncDeclAST(TypeAST* return_type_ptr, - string* ident_ptr, - Vector<FormalParamAST*>* formal_vec_ptr, - PairListAST* pairs_ptr, - StatementListAST* statement_list_ptr); - // Destructor - ~FuncDeclAST(); - - // Public Methods - void generate(); - void print(ostream& out) const; -private: - // Private Methods - - // Private copy constructor and assignment operator - FuncDeclAST(const FuncDeclAST& obj); - FuncDeclAST& operator=(const FuncDeclAST& obj); - - // Data Members (m_ prefix) - string* m_ident_ptr; - TypeAST* m_return_type_ast_ptr; - Vector<FormalParamAST*>* m_formal_vec_ptr; - StatementListAST* m_statement_list_ptr; -}; - -// Output operator declaration -ostream& operator<<(ostream& out, const FuncDeclAST& obj); - -// ******************* Definitions ******************* - -// Output operator definition -extern inline -ostream& operator<<(ostream& out, const FuncDeclAST& obj) -{ - obj.print(out); - out << flush; - return out; -} - -#endif //FuncDeclAST_H diff --git a/src/mem/slicc/ast/FuncDeclAST.py b/src/mem/slicc/ast/FuncDeclAST.py new file mode 100644 index 000000000..980804c2a --- /dev/null +++ b/src/mem/slicc/ast/FuncDeclAST.py @@ -0,0 +1,88 @@ +# Copyright (c) 1999-2008 Mark D. Hill and David A. Wood +# Copyright (c) 2009 The Hewlett-Packard Development Company +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer; +# redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution; +# neither the name of the copyright holders nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +from m5.util.code_formatter import code_formatter + +from slicc.ast.DeclAST import DeclAST +from slicc.symbols import Func, Type + +class FuncDeclAST(DeclAST): + def __init__(self, slicc, return_type, ident, formals, pairs, statements): + super(FuncDeclAST, self).__init__(slicc, pairs) + + self.return_type = return_type + self.ident = ident + self.formals = formals + self.statements = statements + + def __repr__(self): + return "[FuncDecl: %s]" % self.ident + + def files(self, parent=None): + if "external" in self or self.statements is None: + return set() + + if parent: + ident = "%s_%s" % (parent, self.ident) + else: + ident = self.ident + return set(("%s.cc" % ident,)) + + def generate(self): + types = [] + params = [] + void_type = self.symtab.find("void", Type) + + # Generate definition code + self.symtab.pushFrame() + + # Lookup return type + return_type = self.return_type.type + + # Generate function header + for formal in self.formals: + # Lookup parameter types + type, ident = formal.generate() + types.append(type) + params.append(ident) + + body = code_formatter() + if self.statements is None: + self["external"] = "yes" + else: + rtype = self.statements.generate(body, return_type) + + self.symtab.popFrame() + + machine = self.state_machine + func = Func(self.symtab, self.ident, self.location, return_type, + types, params, str(body), self.pairs, machine) + + if machine is not None: + machine.addFunc(func) + else: + self.symtab.newSymbol(func) diff --git a/src/mem/slicc/ast/IfStatementAST.cc b/src/mem/slicc/ast/IfStatementAST.cc deleted file mode 100644 index 40942a58d..000000000 --- a/src/mem/slicc/ast/IfStatementAST.cc +++ /dev/null @@ -1,98 +0,0 @@ - -/* - * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer; - * redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution; - * neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/* - * IfStatementAST.C - * - * Description: See IfStatementAST.hh - * - * $Id$ - * - */ - -#include "mem/slicc/ast/IfStatementAST.hh" - -IfStatementAST::IfStatementAST(ExprAST* cond_ptr, - StatementListAST* then_ptr, - StatementListAST* else_ptr) - : StatementAST() -{ - assert(cond_ptr != NULL); - assert(then_ptr != NULL); - m_cond_ptr = cond_ptr; - m_then_ptr = then_ptr; - m_else_ptr = else_ptr; -} - -IfStatementAST::~IfStatementAST() -{ - delete m_cond_ptr; - delete m_then_ptr; - delete m_else_ptr; -} - - -void IfStatementAST::generate(string& code, Type* return_type_ptr) const -{ - Type* type_ptr; - - // Conditional - code += indent_str() + "if ("; - type_ptr = m_cond_ptr->generate(code); - if (type_ptr != g_sym_table.getType("bool")) { - m_cond_ptr->error("Condition of if statement must be boolean, type was '" + type_ptr->toString() + "'"); - } - code += ") {\n"; - // Then part - inc_indent(); - m_then_ptr->generate(code, return_type_ptr); - dec_indent(); - // Else part - if (m_else_ptr != NULL) { - code += indent_str() + "} else {\n"; - inc_indent(); - m_else_ptr->generate(code, return_type_ptr); - dec_indent(); - } - code += indent_str() + "}\n"; // End scope -} - -void IfStatementAST::findResources(Map<Var*, string>& resource_list) const -{ - // Take a worse case look at both paths - m_then_ptr->findResources(resource_list); - if (m_else_ptr != NULL) { - m_else_ptr->findResources(resource_list); - } -} - -void IfStatementAST::print(ostream& out) const -{ - out << "[IfStatement: " << *m_cond_ptr << *m_then_ptr << *m_else_ptr << "]"; -} diff --git a/src/mem/slicc/ast/IfStatementAST.hh b/src/mem/slicc/ast/IfStatementAST.hh deleted file mode 100644 index 2c168913a..000000000 --- a/src/mem/slicc/ast/IfStatementAST.hh +++ /dev/null @@ -1,89 +0,0 @@ - -/* - * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer; - * redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution; - * neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/* - * IfStatementAST.hh - * - * Description: - * - * $Id$ - * - */ - -#ifndef IFSTATEMENTAST_H -#define IFSTATEMENTAST_H - -#include "mem/slicc/slicc_global.hh" -#include "mem/slicc/ast/ExprAST.hh" -#include "mem/slicc/ast/StatementAST.hh" -#include "mem/slicc/ast/StatementListAST.hh" - - -class IfStatementAST : public StatementAST { -public: - // Constructors - IfStatementAST(ExprAST* cond_ptr, - StatementListAST* then_ptr, - StatementListAST* else_ptr); - - // Destructor - ~IfStatementAST(); - - // Public Methods - void generate(string& code, Type* return_type_ptr) const; - void findResources(Map<Var*, string>& resource_list) const; - void print(ostream& out) const; -private: - // Private Methods - - // Private copy constructor and assignment operator - IfStatementAST(const IfStatementAST& obj); - IfStatementAST& operator=(const IfStatementAST& obj); - - // Data Members (m_ prefix) - ExprAST* m_cond_ptr; - StatementListAST* m_then_ptr; - StatementListAST* m_else_ptr; -}; - -// Output operator declaration -ostream& operator<<(ostream& out, const IfStatementAST& obj); - -// ******************* Definitions ******************* - -// Output operator definition -extern inline -ostream& operator<<(ostream& out, const IfStatementAST& obj) -{ - obj.print(out); - out << flush; - return out; -} - -#endif //IFSTATEMENTAST_H diff --git a/src/mem/slicc/ast/IfStatementAST.py b/src/mem/slicc/ast/IfStatementAST.py new file mode 100644 index 000000000..788876fd1 --- /dev/null +++ b/src/mem/slicc/ast/IfStatementAST.py @@ -0,0 +1,74 @@ +# Copyright (c) 1999-2008 Mark D. Hill and David A. Wood +# Copyright (c) 2009 The Hewlett-Packard Development Company +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer; +# redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution; +# neither the name of the copyright holders nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +from m5.util import code_formatter + +from slicc.ast.StatementAST import StatementAST +from slicc.symbols import Type + +class IfStatementAST(StatementAST): + def __init__(self, slicc, cond, then, else_): + super(IfStatementAST, self).__init__(slicc) + + assert cond is not None + assert then is not None + + self.cond = cond + self.then = then + self.else_ = else_ + + def __repr__(self): + return "[IfStatement: %r%r%r]" % (self.cond, self.then, self.else_) + + def generate(self, code, return_type): + cond_code = code_formatter() + cond_type = self.cond.generate(cond_code) + + if cond_type != self.symtab.find("bool", Type): + self.cond.error("Condition of if stmt must be bool, type was '%s'", + ctype) + + # Conditional + code.indent() + code('if ($cond_code) {') + # Then part + code.indent() + self.then.generate(code, return_type) + code.dedent() + # Else part + if self.else_: + code('} else {') + code.indent() + self.else_.generate(code, return_type) + code.dedent() + code('}') # End scope + + def findResources(self, resources): + # Take a worse case look at both paths + self.then.findResources(resources) + if self.else_ is not None: + self.else_.findResources(resources) diff --git a/src/mem/slicc/ast/InPortDeclAST.cc b/src/mem/slicc/ast/InPortDeclAST.cc deleted file mode 100644 index f62af9921..000000000 --- a/src/mem/slicc/ast/InPortDeclAST.cc +++ /dev/null @@ -1,149 +0,0 @@ - -/* - * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer; - * redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution; - * neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/* - * InPortDeclAST.C - * - * Description: See InPortDeclAST.hh - * - * $Id$ - * - */ - -#include "mem/slicc/ast/InPortDeclAST.hh" -#include "mem/slicc/symbols/SymbolTable.hh" -#include "mem/slicc/symbols/Var.hh" - -InPortDeclAST::InPortDeclAST(string* ident_ptr, - TypeAST* msg_type_ptr, - ExprAST* var_expr_ptr, - PairListAST* pairs_ptr, - StatementListAST* statement_list_ptr) - : DeclAST(pairs_ptr) -{ - m_ident_ptr = ident_ptr; - m_msg_type_ptr = msg_type_ptr; - m_var_expr_ptr = var_expr_ptr; - m_statement_list_ptr = statement_list_ptr; - m_queue_type_ptr = new TypeAST(new string("InPort")); -} - -InPortDeclAST::~InPortDeclAST() -{ - delete m_ident_ptr; - delete m_msg_type_ptr; - delete m_var_expr_ptr; - delete m_statement_list_ptr; - delete m_queue_type_ptr; -} - -void InPortDeclAST::generate() -{ - string code; - Type* queue_type_ptr = m_var_expr_ptr->generate(code); - if (!queue_type_ptr->isInPort()) { - error("Inport queues must be of a type that has the 'inport' attribute. The type '" + - queue_type_ptr->toString() + "' does not have this attribute."); - } - - Type* type_ptr = m_queue_type_ptr->lookupType(); - Var* in_port_ptr = new Var(*m_ident_ptr, getLocation(), type_ptr, code, getPairs()); - g_sym_table.newSym(in_port_ptr); - - g_sym_table.pushFrame(); - Vector<Type*> param_type_vec; - - // Check for Event - type_ptr = g_sym_table.getType("Event"); - if (type_ptr == NULL) { - error("in_port declarations require 'Event' enumeration to be defined"); - } - param_type_vec.insertAtBottom(type_ptr); - - // Check for Address - type_ptr = g_sym_table.getType("Address"); - if (type_ptr == NULL) { - error("in_port declarations require 'Address' type to be defined"); - } - param_type_vec.insertAtBottom(type_ptr); - - // Add the trigger method - FIXME, this is a bit dirty - Map<string, string> pairs; - pairs.add("external", "yes"); - Vector<string> string_vec; - g_sym_table.newSym(new Func("trigger", getLocation(), g_sym_table.getType("void"), param_type_vec, string_vec, string(""), pairs, NULL)); - - // Check for Event2 - type_ptr = g_sym_table.getType("Event"); - if (type_ptr == NULL) { - error("in_port declarations require 'Event' enumeration to be defined"); - } - param_type_vec.insertAtBottom(type_ptr); - - // Check for Address2 - type_ptr = g_sym_table.getType("Address"); - if (type_ptr == NULL) { - error("in_port declarations require 'Address' type to be defined"); - } - param_type_vec.insertAtBottom(type_ptr); - - // Add the doubleTrigger method - this hack supports tiggering two simulateous events - // The key is that the second transistion cannot fail because the first event cannot be undone - // therefore you must do some checks before calling double trigger to ensure that won't happen - g_sym_table.newSym(new Func("doubleTrigger", getLocation(), g_sym_table.getType("void"), param_type_vec, string_vec, string(""), pairs, NULL)); - - // Add the continueProcessing method - this hack supports messages that don't trigger events - Vector<Type*> empty_param_type_vec; - Vector<string> empty_string_vec; - g_sym_table.newSym(new Func("continueProcessing", getLocation(), g_sym_table.getType("void"), empty_param_type_vec, empty_string_vec, string(""), pairs, NULL)); - - if (m_statement_list_ptr != NULL) { - inc_indent(); - inc_indent(); - string code; - m_statement_list_ptr->generate(code, NULL); - in_port_ptr->addPair("c_code_in_port", code); - dec_indent(); - dec_indent(); - } - g_sym_table.popFrame(); - - // Add port to state machine - StateMachine* machine_ptr = g_sym_table.getStateMachine(); - if (machine_ptr == NULL) { - error("InPort declaration not part of a machine."); - } - machine_ptr->addInPort(in_port_ptr); -} - - -void InPortDeclAST::print(ostream& out) const -{ - out << "[InPortDecl: " << *m_ident_ptr << "]"; -} diff --git a/src/mem/slicc/ast/InPortDeclAST.hh b/src/mem/slicc/ast/InPortDeclAST.hh deleted file mode 100644 index e6295a6e2..000000000 --- a/src/mem/slicc/ast/InPortDeclAST.hh +++ /dev/null @@ -1,91 +0,0 @@ - -/* - * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer; - * redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution; - * neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/* - * InPortDeclAST.hh - * - * Description: - * - * $Id: InPortDeclAST.hh,v 3.2 2003/07/10 18:08:06 milo Exp $ - * - */ - -#ifndef InPortDeclAST_H -#define InPortDeclAST_H - -#include "mem/slicc/slicc_global.hh" -#include "mem/slicc/ast/DeclAST.hh" -#include "mem/slicc/ast/StatementListAST.hh" -#include "mem/slicc/ast/VarExprAST.hh" - -class InPortDeclAST : public DeclAST { -public: - // Constructors - InPortDeclAST(string* ident_ptr, - TypeAST* msg_type_ptr, - ExprAST* var_expr_ptr, - PairListAST* pairs_ptr, - StatementListAST* statement_list_ptr); - - // Destructor - ~InPortDeclAST(); - - // Public Methods - void generate(); - void print(ostream& out) const; -private: - // Private Methods - - // Private copy constructor and assignment operator - InPortDeclAST(const InPortDeclAST& obj); - InPortDeclAST& operator=(const InPortDeclAST& obj); - - // Data Members (m_ prefix) - string* m_ident_ptr; - TypeAST* m_msg_type_ptr; - ExprAST* m_var_expr_ptr; - StatementListAST* m_statement_list_ptr; - TypeAST* m_queue_type_ptr; -}; - -// Output operator declaration -ostream& operator<<(ostream& out, const InPortDeclAST& obj); - -// ******************* Definitions ******************* - -// Output operator definition -extern inline -ostream& operator<<(ostream& out, const InPortDeclAST& obj) -{ - obj.print(out); - out << flush; - return out; -} - -#endif //InPortDeclAST_H diff --git a/src/mem/slicc/ast/InPortDeclAST.py b/src/mem/slicc/ast/InPortDeclAST.py new file mode 100644 index 000000000..3dde24557 --- /dev/null +++ b/src/mem/slicc/ast/InPortDeclAST.py @@ -0,0 +1,130 @@ +# Copyright (c) 1999-2008 Mark D. Hill and David A. Wood +# Copyright (c) 2009 The Hewlett-Packard Development Company +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer; +# redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution; +# neither the name of the copyright holders nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +from m5.util import code_formatter + +from slicc.ast.DeclAST import DeclAST +from slicc.ast.TypeAST import TypeAST +from slicc.symbols import Func, Type, Var + +class InPortDeclAST(DeclAST): + def __init__(self, slicc, ident, msg_type, var_expr, pairs, statements): + super(InPortDeclAST, self).__init__(slicc, pairs) + + self.ident = ident + self.msg_type = msg_type + self.var_expr = var_expr + self.statements = statements + self.queue_type = TypeAST(slicc, "InPort") + + def __repr__(self): + return "[InPortDecl: %s]" % self.ident + + def generate(self): + symtab = self.symtab + void_type = symtab.find("void", Type) + + code = code_formatter() + queue_type = self.var_expr.generate(code) + if not queue_type.isInPort: + self.error("The inport queue's type must have the 'inport' " + \ + "attribute. Type '%s' does not have this attribute.", + queue_type) + + type = self.queue_type.type + in_port = Var(self.symtab, self.ident, self.location, type, str(code), + self.pairs) + symtab.newSymbol(in_port) + + symtab.pushFrame() + param_types = [] + + # Check for Event + type = symtab.find("Event", Type) + if type is None: + self.error("in_port decls require 'Event' enumeration defined") + param_types.append(type) + + # Check for Address + type = symtab.find("Address", Type) + if type is None: + self.error("in_port decls require 'Address' type to be defined") + + param_types.append(type) + + # Add the trigger method - FIXME, this is a bit dirty + pairs = { "external" : "yes" } + func = Func(self.symtab, "trigger", self.location, void_type, + param_types, [], "", pairs, None) + symtab.newSymbol(func) + + param_types = [] + # Check for Event2 + type = symtab.find("Event", Type) + if type is None: + self.error("in_port decls require 'Event' enumeration") + + param_types.append(type) + + # Check for Address2 + type = symtab.find("Address", Type) + if type is None: + self.error("in_port decls require 'Address' type to be defined") + + param_types.append(type) + + # Add the doubleTrigger method - this hack supports tiggering + # two simulateous events + # + # The key is that the second transistion cannot fail because + # the first event cannot be undone therefore you must do some + # checks before calling double trigger to ensure that won't + # happen + func = Func(self.symtab, "doubleTrigger", self.location, void_type, + param_types, [], "", pairs, None) + symtab.newSymbol(func) + + # Add the continueProcessing method - this hack supports + # messages that don't trigger events + func = Func(self.symtab, "continueProcessing", self.location, + void_type, [], [], "", pairs, None) + symtab.newSymbol(func) + + if self.statements is not None: + rcode = code_formatter() + rcode.indent() + rcode.indent() + self.statements.generate(rcode, None) + in_port["c_code_in_port"] = str(rcode) + symtab.popFrame() + + # Add port to state machine + machine = symtab.state_machine + if machine is None: + self.error("InPort declaration not part of a machine.") + + machine.addInPort(in_port) diff --git a/src/mem/slicc/ast/InfixOperatorExprAST.cc b/src/mem/slicc/ast/InfixOperatorExprAST.cc deleted file mode 100644 index 40719fc66..000000000 --- a/src/mem/slicc/ast/InfixOperatorExprAST.cc +++ /dev/null @@ -1,121 +0,0 @@ - -/* - * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer; - * redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution; - * neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/* - * InfixOperatorExprAST.C - * - * Description: See InfixOperatorExprAST.hh - * - * $Id: InfixOperatorExprAST.C,v 3.2 2004/01/31 20:46:15 milo Exp $ - * - */ - -#include "mem/slicc/ast/InfixOperatorExprAST.hh" - -InfixOperatorExprAST::InfixOperatorExprAST(ExprAST* left_ptr, - string* op_ptr, - ExprAST* right_ptr) - : ExprAST() -{ - m_left_ptr = left_ptr; - m_op_ptr = op_ptr; - m_right_ptr = right_ptr; -} - -InfixOperatorExprAST::~InfixOperatorExprAST() -{ - delete m_left_ptr; - delete m_op_ptr; - delete m_right_ptr; -} - -Type* InfixOperatorExprAST::generate(string& code) const -{ - code += "("; - Type* left_type_ptr = m_left_ptr->generate(code); - code += " " + *m_op_ptr + " "; - Type* right_type_ptr = m_right_ptr->generate(code); - code += ")"; - - string inputs, output; - // Figure out what the input and output types should be - if ((*m_op_ptr == "==" || - *m_op_ptr == "!=")) { - output = "bool"; - if (left_type_ptr != right_type_ptr) { - error("Type mismatch: left & right operand of operator '" + *m_op_ptr + - "' must be the same type." + - "left: '" + left_type_ptr->toString() + - "', right: '" + right_type_ptr->toString() + "'"); - } - } else { - if ((*m_op_ptr == "&&" || - *m_op_ptr == "||")) { - // boolean inputs and output - inputs = "bool"; - output = "bool"; - } else if ((*m_op_ptr == "==" || - *m_op_ptr == "!=" || - *m_op_ptr == ">=" || - *m_op_ptr == "<=" || - *m_op_ptr == ">" || - *m_op_ptr == "<")) { - // Integer inputs, boolean output - inputs = "int"; - output = "bool"; - } else { - // integer inputs and output - inputs = "int"; - output = "int"; - } - - Type* inputs_type = g_sym_table.getType(inputs); - - if (inputs_type != left_type_ptr) { - m_left_ptr->error("Type mismatch: left operand of operator '" + *m_op_ptr + - "' expects input type '" + inputs + "', actual was " + left_type_ptr->toString() + "'"); - } - - if (inputs_type != right_type_ptr) { - m_right_ptr->error("Type mismatch: right operand of operator '" + *m_op_ptr + - "' expects input type '" + inputs + "', actual was '" + right_type_ptr->toString() + "'"); - } - } - - // All is well - Type* output_type = g_sym_table.getType(output); - return output_type; -} - - -void InfixOperatorExprAST::print(ostream& out) const -{ - out << "[InfixExpr: " << *m_left_ptr - << *m_op_ptr << *m_right_ptr << "]"; -} diff --git a/src/mem/slicc/ast/InfixOperatorExprAST.py b/src/mem/slicc/ast/InfixOperatorExprAST.py new file mode 100644 index 000000000..c4fb4a4db --- /dev/null +++ b/src/mem/slicc/ast/InfixOperatorExprAST.py @@ -0,0 +1,89 @@ +# Copyright (c) 1999-2008 Mark D. Hill and David A. Wood +# Copyright (c) 2009 The Hewlett-Packard Development Company +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer; +# redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution; +# neither the name of the copyright holders nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +from m5.util import code_formatter + +from slicc.ast.ExprAST import ExprAST +from slicc.symbols import Type + +class InfixOperatorExprAST(ExprAST): + def __init__(self, slicc, left, op, right): + super(InfixOperatorExprAST, self).__init__(slicc) + + self.left = left + self.op = op + self.right = right + + def __repr__(self): + return "[InfixExpr: %r %s %r]" % (self.left, self.op, self.right) + + def generate(self, code): + lcode = code_formatter() + rcode = code_formatter() + + ltype = self.left.generate(lcode) + rtype = self.right.generate(rcode) + + # Figure out what the input and output types should be + if self.op in ("==", "!="): + output = "bool" + if (ltype != rtype): + self.error("Type mismatch: left and right operands of " + + "operator '%s' must be the same type. " + + "left: '%s', right: '%s'", + self.op, ltype, rtype) + else: + if self.op in ("&&", "||"): + # boolean inputs and output + inputs = "bool" + output = "bool" + elif self.op in ("==", "!=", ">=", "<=", ">", "<"): + # Integer inputs, boolean output + inputs = "int" + output = "bool" + else: + # integer inputs and output + inputs = "int" + output = "int" + + inputs_type = self.symtab.find(inputs, Type) + + if inputs_type != ltype: + self.left.error("Type mismatch: left operand of operator " + + "'%s' expects type '%s', actual was '%s'", + self.op, inputs, ltype) + + if inputs_type != rtype: + self.right.error("Type mismatch: right operand of operator " + + "'%s' expects type '%s', actual was '%s'", + self.op, inputs, rtype) + + # All is well + fix = code.nofix() + code("($lcode ${{self.op}} $rcode)") + code.fix(fix) + return self.symtab.find(output, Type) diff --git a/src/mem/slicc/ast/LiteralExprAST.py b/src/mem/slicc/ast/LiteralExprAST.py new file mode 100644 index 000000000..773e8f35c --- /dev/null +++ b/src/mem/slicc/ast/LiteralExprAST.py @@ -0,0 +1,55 @@ +# Copyright (c) 1999-2008 Mark D. Hill and David A. Wood +# Copyright (c) 2009 The Hewlett-Packard Development Company +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer; +# redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution; +# neither the name of the copyright holders nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +from slicc.ast.ExprAST import ExprAST +from slicc.symbols import Type + +class LiteralExprAST(ExprAST): + def __init__(self, slicc, literal, type): + super(LiteralExprAST, self).__init__(slicc) + self.literal = literal + self.type = type + + def __repr__(self): + return "[Literal: %s]" % self.literal + + def generate(self, code): + fix = code.nofix() + if self.type == "string": + code('("${{self.literal}}")') + elif self.type == "bool": + code('(${{str(self.literal).lower()}})') + else: + code('(${{self.literal}})') + code.fix(fix) + + type = self.symtab.find(self.type, Type) + if type is None: + # Can't find the type + self.error("Internal: can't primitive type '%s'" % self.type) + + return type diff --git a/src/mem/slicc/ast/Location.cc b/src/mem/slicc/ast/Location.cc deleted file mode 100644 index fd224fe2f..000000000 --- a/src/mem/slicc/ast/Location.cc +++ /dev/null @@ -1,87 +0,0 @@ - -/* - * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer; - * redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution; - * neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/* - * Location.C - * - * Description: See Location.hh - * - * $Id: Location.C,v 3.3 2004/05/30 22:19:02 kmoore Exp $ - * - */ - -#include "mem/slicc/ast/Location.hh" - -int g_line_number = 0; -string &g_file_name() -{ - static string the_string; - return the_string; -} - -Location::Location() -{ - m_file_name = g_file_name(); - m_line_number = g_line_number; - - ostringstream sstr; - sstr << getLineNumber(); - m_line_number_str = sstr.str(); -} - -void Location::error(string err_msg) const -{ - cerr << endl; - cerr << toString() << ": Error: " << err_msg << endl; - exit(1); -} - -string Location::embedError(string err_msg) const -{ - string code; - code += "cerr << \"Runtime Error at "; - code += toString() + ", Ruby Time: \" << "; - code += "g_eventQueue_ptr->getTime() << \": \" << "; - code += err_msg; - code += " << \", PID: \" << getpid() << endl;\n"; - code += "char c; cerr << \"press return to continue.\" << endl; cin.get(c); abort();\n"; - - return code; -} - -void Location::warning(string err_msg) const -{ - cerr << toString() << ": Warning: " - << err_msg << endl; -} - -string Location::toString() const -{ - return m_file_name + ":" + m_line_number_str; -} diff --git a/src/mem/slicc/ast/Location.hh b/src/mem/slicc/ast/Location.hh deleted file mode 100644 index c9e20418e..000000000 --- a/src/mem/slicc/ast/Location.hh +++ /dev/null @@ -1,93 +0,0 @@ - -/* - * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer; - * redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution; - * neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/* - * Location.hh - * - * Description: - * - * $Id: Location.hh,v 3.1 2001/12/12 01:00:20 milo Exp $ - * - */ - -#ifndef LOCATION_H -#define LOCATION_H - -#include "mem/slicc/slicc_global.hh" - -extern int g_line_number; -extern string &g_file_name(); - -class Location { -public: - // Constructors - Location(); - - // Destructor - //~Location(); - - // Public Methods - - void print(ostream& out) const; - void error(string err_msg) const; - string embedError(string err_msg) const; - void warning(string err_msg) const; - string toString() const; - -private: - // Private Methods - const string& getFileName() const { return m_file_name; } - int getLineNumber() const { return m_line_number; } - string getLineNumberStr() const { return m_line_number_str; } - - // Private copy constructor and assignment operator - //Location(const Location& obj); - //Location& operator=(const Location& obj); - - // Data Members (m_ prefix) - string m_file_name; - int m_line_number; - string m_line_number_str; -}; - -// Output operator declaration -ostream& operator<<(ostream& out, const Location& obj); - -// ******************* Definitions ******************* - -// Output operator definition -extern inline -ostream& operator<<(ostream& out, const Location& obj) -{ - obj.print(out); - out << flush; - return out; -} - -#endif //LOCATION_H diff --git a/src/mem/slicc/ast/MachineAST.cc b/src/mem/slicc/ast/MachineAST.cc deleted file mode 100644 index ae8026458..000000000 --- a/src/mem/slicc/ast/MachineAST.cc +++ /dev/null @@ -1,99 +0,0 @@ - -/* - * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer; - * redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution; - * neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/* - * MachineAST.cc - * - * Description: See MachineAST.hh - * - * $Id: MachineAST.cc,v 3.1 2003/03/17 01:54:25 xu Exp $ - * - */ - -#include "mem/slicc/ast/MachineAST.hh" -#include "mem/slicc/ast/FormalParamAST.hh" -#include "mem/slicc/symbols/SymbolTable.hh" - -MachineAST::MachineAST(string* ident_ptr, - PairListAST* pairs_ptr, - Vector<FormalParamAST*>* config_parameters, - DeclListAST* decl_list_ptr) - - : DeclAST(pairs_ptr) -{ - m_ident_ptr = ident_ptr; - m_pairs_ptr = pairs_ptr; - m_config_parameters = config_parameters; - m_decl_list_ptr = decl_list_ptr; -} - -MachineAST::~MachineAST() -{ - delete m_ident_ptr; - delete m_pairs_ptr; - delete m_decl_list_ptr; -} - -void MachineAST::generate() -{ - StateMachine* machine_ptr; - - // Make a new frame - g_sym_table.pushFrame(); - - // Create a new machine - machine_ptr = new StateMachine(*m_ident_ptr, getLocation(), getPairs(), m_config_parameters); - g_sym_table.newCurrentMachine(machine_ptr); - - // Generate code for all the internal decls - m_decl_list_ptr->generate(); - - // Build the transition table - machine_ptr->buildTable(); - - // Pop the frame - g_sym_table.popFrame(); -} - -void MachineAST::findMachines() -{ - // Add to MachineType enumeration - Type* type_ptr = g_sym_table.getType("MachineType"); - if (!type_ptr->enumAdd(*m_ident_ptr, m_pairs_ptr->getPairs())) { - error("Duplicate machine name: " + type_ptr->toString() + ":" + *m_ident_ptr); - } - - // Generate code for all the internal decls - m_decl_list_ptr->findMachines(); -} - -void MachineAST::print(ostream& out) const -{ - out << "[Machine: " << *m_ident_ptr << "]"; -} diff --git a/src/mem/slicc/ast/MachineAST.hh b/src/mem/slicc/ast/MachineAST.hh deleted file mode 100644 index 5d1bc2a1c..000000000 --- a/src/mem/slicc/ast/MachineAST.hh +++ /dev/null @@ -1,93 +0,0 @@ - -/* - * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer; - * redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution; - * neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/* - * ActionDeclAST.hh - * - * Description: - * - * $Id: MachineAST.hh,v 3.2 2003/07/10 18:08:06 milo Exp $ - * - */ - -#ifndef MachineAST_H -#define MachineAST_H - -#include "mem/slicc/slicc_global.hh" -#include "mem/slicc/ast/DeclAST.hh" -#include "mem/slicc/ast/DeclListAST.hh" -#include "mem/slicc/ast/TypeFieldAST.hh" -#include "mem/slicc/symbols/StateMachine.hh" - -class FormalParamAST; - -class MachineAST : public DeclAST { -public: - // Constructors - MachineAST(string* ident_ptr, - PairListAST* pairs_ptr, - Vector<FormalParamAST*>* config_parameters, - DeclListAST* decl_list_ptr); - - // Destructor - ~MachineAST(); - - // Public Methods - void print(ostream& out) const; - void generate(); - void findMachines(); -private: - // Private Methods - - // Private copy constructor and assignment operator - MachineAST(const MachineAST& obj); - MachineAST& operator=(const MachineAST& obj); - - // Data Members (m_ prefix) - Vector<FormalParamAST*>* m_config_parameters; - string* m_ident_ptr; - DeclListAST* m_decl_list_ptr; - PairListAST* m_pairs_ptr; -}; - -// Output operator declaration -ostream& operator<<(ostream& out, const MachineAST& obj); - -// ******************* Definitions ******************* - -// Output operator definition -extern inline -ostream& operator<<(ostream& out, const MachineAST& obj) -{ - obj.print(out); - out << flush; - return out; -} - -#endif //MachineAST_H diff --git a/src/mem/slicc/ast/MachineAST.py b/src/mem/slicc/ast/MachineAST.py new file mode 100644 index 000000000..ee75b6d6a --- /dev/null +++ b/src/mem/slicc/ast/MachineAST.py @@ -0,0 +1,81 @@ +# Copyright (c) 1999-2008 Mark D. Hill and David A. Wood +# Copyright (c) 2009 The Hewlett-Packard Development Company +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer; +# redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution; +# neither the name of the copyright holders nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +from slicc.ast.DeclAST import DeclAST +from slicc.symbols import StateMachine, Type + +class MachineAST(DeclAST): + def __init__(self, slicc, ident, pairs_ast, config_parameters, decls): + super(MachineAST, self).__init__(slicc, pairs_ast) + + self.ident = ident + self.pairs_ast = pairs_ast + self.config_parameters = config_parameters + self.decls = decls + + def __repr__(self): + return "[Machine: %r]" % self.ident + + def files(self, parent=None): + s = set(('%s_Controller.cc' % self.ident, + '%s_Controller.hh' % self.ident, + '%s_Profiler.cc' % self.ident, + '%s_Profiler.hh' % self.ident, + '%s_Transitions.cc' % self.ident, + '%s_Wakeup.cc' % self.ident)) + + s |= self.decls.files(self.ident) + return s + + def generate(self): + # Make a new frame + self.symtab.pushFrame() + + # Create a new machine + machine = StateMachine(self.symtab, self.ident, self.location, + self.pairs, self.config_parameters) + + self.symtab.newCurrentMachine(machine) + + # Generate code for all the internal decls + self.decls.generate() + + # Build the transition table + machine.buildTable() + + # Pop the frame + self.symtab.popFrame() + + def findMachines(self): + # Add to MachineType enumeration + machine_type = self.symtab.find("MachineType", Type) + if not machine_type.enumAdd(self.ident, self.pairs_ast.pairs): + self.error("Duplicate machine name: %s:%s" % (machine_type, + self.ident)) + + # Generate code for all the internal decls + self.decls.findMachines() diff --git a/src/mem/slicc/ast/MemberExprAST.cc b/src/mem/slicc/ast/MemberExprAST.cc deleted file mode 100644 index 1bcfdc7f1..000000000 --- a/src/mem/slicc/ast/MemberExprAST.cc +++ /dev/null @@ -1,72 +0,0 @@ - -/* - * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer; - * redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution; - * neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/* - * FieldExprAST.C - * - * Description: See FieldExprAST.hh - * - * $Id$ - * - */ - -#include "mem/slicc/ast/MemberExprAST.hh" - -MemberExprAST::MemberExprAST(ExprAST* expr_ast_ptr, string* field_ptr) - : ExprAST() -{ - m_expr_ast_ptr = expr_ast_ptr; - m_field_ptr = field_ptr; -} - -MemberExprAST::~MemberExprAST() -{ - delete m_expr_ast_ptr; - delete m_field_ptr; -} - -Type* MemberExprAST::generate(string& code) const -{ - code += "("; - Type* type_ptr = m_expr_ast_ptr->generate(code); - code += ").m_" + (*m_field_ptr); - - // Verify that this is a valid field name for this type - if (!type_ptr->dataMemberExist(*m_field_ptr)) { - error("Invalid object field: Type '" + type_ptr->toString() + "' does not have data member " + *m_field_ptr); - } - - // Return the type of the field - return type_ptr->dataMemberType(*m_field_ptr); -} - -void MemberExprAST::print(ostream& out) const -{ - out << "[MemberExprAST: " << *m_expr_ast_ptr << "." << *m_field_ptr << "]"; -} diff --git a/src/mem/slicc/ast/MemberExprAST.hh b/src/mem/slicc/ast/MemberExprAST.hh deleted file mode 100644 index 34b694882..000000000 --- a/src/mem/slicc/ast/MemberExprAST.hh +++ /dev/null @@ -1,83 +0,0 @@ - -/* - * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer; - * redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution; - * neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/* - * MemberExprAST.hh - * - * Description: - * - * $Id: MemberExprAST.hh,v 3.1 2001/12/12 01:00:21 milo Exp $ - * - */ - -#ifndef MemberExprAST_H -#define MemberExprAST_H - -#include "mem/slicc/slicc_global.hh" -#include "mem/slicc/ast/ExprAST.hh" - - -class MemberExprAST : public ExprAST { -public: - // Constructors - MemberExprAST(ExprAST* expr_ast_ptr, string* field_ptr); - - // Destructor - ~MemberExprAST(); - - // Public Methods - Type* generate(string& code) const; - void print(ostream& out) const; -private: - // Private Methods - - // Private copy constructor and assignment operator - MemberExprAST(const MemberExprAST& obj); - MemberExprAST& operator=(const MemberExprAST& obj); - - // Data Members (m_ prefix) - ExprAST* m_expr_ast_ptr; - string* m_field_ptr; -}; - -// Output operator declaration -ostream& operator<<(ostream& out, const MemberExprAST& obj); - -// ******************* Definitions ******************* - -// Output operator definition -extern inline -ostream& operator<<(ostream& out, const MemberExprAST& obj) -{ - obj.print(out); - out << flush; - return out; -} - -#endif //MemberExprAST_H diff --git a/src/mem/slicc/ast/MemberExprAST.py b/src/mem/slicc/ast/MemberExprAST.py new file mode 100644 index 000000000..c62e28741 --- /dev/null +++ b/src/mem/slicc/ast/MemberExprAST.py @@ -0,0 +1,55 @@ +# Copyright (c) 1999-2008 Mark D. Hill and David A. Wood +# Copyright (c) 2009 The Hewlett-Packard Development Company +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer; +# redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution; +# neither the name of the copyright holders nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +from m5.util import code_formatter + +from slicc.ast.ExprAST import ExprAST + +class MemberExprAST(ExprAST): + def __init__(self, slicc, expr_ast, field): + super(MemberExprAST, self).__init__(slicc) + + self.expr_ast = expr_ast + self.field = field + + def __repr__(self): + return "[MemberExprAST: %r.%r]" % (self.expr_ast, self.field) + + def generate(self, code): + return_type, gcode = self.expr_ast.inline(True) + fix = code.nofix() + code("($gcode).m_${{self.field}}") + code.fix(fix) + + # Verify that this is a valid field name for this type + if self.field not in return_type.data_members: + self.error("Invalid object field: " + + "Type '%s' does not have data member %s" % \ + (return_type, self.field)) + + # Return the type of the field + return return_type.data_members[self.field].type diff --git a/src/mem/slicc/ast/MethodCallExprAST.cc b/src/mem/slicc/ast/MethodCallExprAST.cc deleted file mode 100644 index 1bfe312ff..000000000 --- a/src/mem/slicc/ast/MethodCallExprAST.cc +++ /dev/null @@ -1,160 +0,0 @@ - -/* - * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer; - * redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution; - * neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/* - * MethodCallExprAST.cc - * - * Description: See MethodCallExprAST.hh - * - * $Id$ - * - */ - -#include "mem/slicc/ast/MethodCallExprAST.hh" - -MethodCallExprAST::MethodCallExprAST(ExprAST* obj_expr_ptr, - string* proc_name_ptr, - Vector<ExprAST*>* expr_vec_ptr) - : ExprAST() -{ - m_obj_expr_ptr = obj_expr_ptr; - m_type_ptr = NULL; - m_proc_name_ptr = proc_name_ptr; - m_expr_vec_ptr = expr_vec_ptr; -} - -MethodCallExprAST::MethodCallExprAST(TypeAST* type_ptr, - string* proc_name_ptr, - Vector<ExprAST*>* expr_vec_ptr) - : ExprAST() -{ - m_obj_expr_ptr = NULL; - m_type_ptr = type_ptr; - m_proc_name_ptr = proc_name_ptr; - m_expr_vec_ptr = expr_vec_ptr; -} - -MethodCallExprAST::~MethodCallExprAST() -{ - delete m_obj_expr_ptr; - delete m_type_ptr; - delete m_proc_name_ptr; - int size = m_expr_vec_ptr->size(); - for(int i=0; i<size; i++) { - delete (*m_expr_vec_ptr)[i]; - } - delete m_expr_vec_ptr; -} - -Type* MethodCallExprAST::generate(string& code) const -{ - Type* obj_type_ptr = NULL; - - string methodId; - Vector <Type*> paramTypes; - - int actual_size = m_expr_vec_ptr->size(); - for(int i=0; i<actual_size; i++) { - string tmp; - Type* actual_type_ptr = (*m_expr_vec_ptr)[i]->generate(tmp); - paramTypes.insertAtBottom(actual_type_ptr); - } - - if(m_obj_expr_ptr) { - // member method call - string tmp; - obj_type_ptr = m_obj_expr_ptr->generate(tmp); - methodId = obj_type_ptr->methodId(*m_proc_name_ptr, paramTypes); - if (obj_type_ptr->methodReturnType(methodId)->isInterface()) - code += "static_cast<" + obj_type_ptr->methodReturnType(methodId)->cIdent() + "&>"; - code += "(("; - code += tmp; - code += ")."; - } else if (m_type_ptr) { - // class method call - code += "(" + m_type_ptr->toString() + "::"; - obj_type_ptr = m_type_ptr->lookupType(); - methodId = obj_type_ptr->methodId(*m_proc_name_ptr, paramTypes); - } else { - // impossible - assert(0); - } - - // generate code - actual_size = m_expr_vec_ptr->size(); - code += (*m_proc_name_ptr) + "("; - for(int i=0; i<actual_size; i++) { - if (i != 0) { - code += ", "; - } - // Check the types of the parameter - Type* actual_type_ptr = (*m_expr_vec_ptr)[i]->generate(code); - } - code += "))"; - - // Verify that this is a method of the object - if (!obj_type_ptr->methodExist(methodId)) { - error("Invalid method call: Type '" + obj_type_ptr->toString() + "' does not have a method '" + methodId + "'"); - } - - int expected_size = obj_type_ptr->methodParamType(methodId).size(); - if (actual_size != expected_size) { - // Right number of parameters - ostringstream err; - err << "Wrong number of parameters for function name: '" << *m_proc_name_ptr << "'"; - err << ", expected: "; - err << expected_size; - err << ", actual: "; - err << actual_size; - error(err.str()); - } - - for(int i=0; i<actual_size; i++) { - // Check the types of the parameter - Type* actual_type_ptr = paramTypes[i]; - Type* expected_type_ptr = obj_type_ptr->methodParamType(methodId)[i]; - if (actual_type_ptr != expected_type_ptr) { - (*m_expr_vec_ptr)[i]->error("Type mismatch: expected: " + expected_type_ptr->toString() + - " actual: " + actual_type_ptr->toString()); - } - } - - // Return the return type of the method - return obj_type_ptr->methodReturnType(methodId); -} - -void MethodCallExprAST::findResources(Map<Var*, string>& resource_list) const -{ - -} - -void MethodCallExprAST::print(ostream& out) const -{ - out << "[MethodCallExpr: " << *m_proc_name_ptr << *m_obj_expr_ptr << " " << *m_expr_vec_ptr << "]"; -} diff --git a/src/mem/slicc/ast/MethodCallExprAST.hh b/src/mem/slicc/ast/MethodCallExprAST.hh deleted file mode 100644 index d248e6ba4..000000000 --- a/src/mem/slicc/ast/MethodCallExprAST.hh +++ /dev/null @@ -1,93 +0,0 @@ - -/* - * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer; - * redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution; - * neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/* - * MethodCallExprAST.hh - * - * Description: - * - * $Id$ - * - */ - -#ifndef MethodCallExprAST_H -#define MethodCallExprAST_H - -#include "mem/slicc/slicc_global.hh" -#include "mem/slicc/ast/StatementAST.hh" -#include "mem/slicc/ast/ExprAST.hh" -#include "mem/slicc/ast/TypeAST.hh" - -class MethodCallExprAST : public ExprAST { -public: - // Constructors - MethodCallExprAST(ExprAST* m_obj_expr_ptr, - string* proc_name_ptr, - Vector<ExprAST*>* expr_vec_ptr); - - MethodCallExprAST(TypeAST* type_ptr, - string* proc_name_ptr, - Vector<ExprAST*>* expr_vec_ptr); - - // Destructor - ~MethodCallExprAST(); - - // Public Methods - Type* generate(string& code) const; - void findResources(Map<Var*, string>& resource_list) const; - void print(ostream& out) const; -private: - // Private Methods - - // Private copy constructor and assignment operator - MethodCallExprAST(const MethodCallExprAST& obj); - MethodCallExprAST& operator=(const MethodCallExprAST& obj); - - // Data Members (m_ prefix) - ExprAST* m_obj_expr_ptr; - TypeAST* m_type_ptr; - string* m_proc_name_ptr; - Vector<ExprAST*>* m_expr_vec_ptr; -}; - -// Output operator declaration -ostream& operator<<(ostream& out, const MethodCallExprAST& obj); - -// ******************* Definitions ******************* - -// Output operator definition -extern inline -ostream& operator<<(ostream& out, const MethodCallExprAST& obj) -{ - obj.print(out); - out << flush; - return out; -} - -#endif // MethodCallExprAST_H diff --git a/src/mem/slicc/ast/MethodCallExprAST.py b/src/mem/slicc/ast/MethodCallExprAST.py new file mode 100644 index 000000000..3f9b250c1 --- /dev/null +++ b/src/mem/slicc/ast/MethodCallExprAST.py @@ -0,0 +1,130 @@ +# Copyright (c) 1999-2008 Mark D. Hill and David A. Wood +# Copyright (c) 2009 The Hewlett-Packard Development Company +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer; +# redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution; +# neither the name of the copyright holders nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +from m5.util import code_formatter + +from slicc.ast.ExprAST import ExprAST + +class MethodCallExprAST(ExprAST): + def __init__(self, slicc, proc_name, expr_ast_vec): + super(MethodCallExprAST, self).__init__(slicc) + self.proc_name = proc_name + self.expr_ast_vec = expr_ast_vec + + def generate(self, code): + tmp = code_formatter() + paramTypes = [] + for expr_ast in self.expr_ast_vec: + return_type = expr_ast.generate(tmp) + paramTypes.append(return_type) + + obj_type, methodId, prefix = self.generate_prefix(paramTypes) + + # generate code + params = [] + for expr_ast in self.expr_ast_vec: + return_type,tcode = expr_ast.inline(True) + params.append(str(tcode)) + fix = code.nofix() + code("$prefix${{self.proc_name}}(${{', '.join(params)}}))") + code.fix(fix) + + # Verify that this is a method of the object + if methodId not in obj_type.methods: + self.error("Invalid method call: Type '%s' does not have a method '%s'", + obj_type, methodId) + + if len(self.expr_ast_vec) != \ + len(obj_type.methods[methodId].param_types): + # Right number of parameters + self.error("Wrong number of parameters for function name: '%s', " + \ + "expected: , actual: ", proc_name, + len(obj_type.methods[methodId].param_types), + len(self.expr_ast_vec)) + + for actual_type, expected_type in \ + zip(paramTypes, obj_type.methods[methodId].param_types): + if actual_type != expected_type: + self.error("Type mismatch: expected: %s actual: %s", + expected_type, actual_type) + + # Return the return type of the method + return obj_type.methods[methodId].return_type + + def findResources(self, resources): + pass + +class MemberMethodCallExprAST(MethodCallExprAST): + def __init__(self, slicc, obj_expr_ast, proc_name, expr_ast_vec): + s = super(MemberMethodCallExprAST, self) + s.__init__(slicc, proc_name, expr_ast_vec) + + self.obj_expr_ast = obj_expr_ast + + def __repr__(self): + return "[MethodCallExpr: %r%r %r]" % (self.proc_name, + self.obj_expr_ast, + self.expr_ast_vec) + def generate_prefix(self, paramTypes): + code = code_formatter() + + # member method call + obj_type = self.obj_expr_ast.generate(code) + methodId = obj_type.methodId(self.proc_name, paramTypes) + + prefix = "" + if methodId not in obj_type.methods: + self.error("Invalid method call: Type '%s' does not have a method '%s'", + obj_type, methodId) + return_type = obj_type.methods[methodId].return_type + if return_type.isInterface: + prefix = "static_cast<%s &>" % return_type.c_ident + prefix = "%s((%s)." % (prefix, code) + + return obj_type, methodId, prefix + + +class ClassMethodCallExprAST(MethodCallExprAST): + def __init__(self, slicc, type_ast, proc_name, expr_ast_vec): + s = super(ClassMethodCallExprAST, self) + s.__init__(slicc, proc_name, expr_ast_vec) + + self.type_ast = type_ast + + def __repr__(self): + return "[MethodCallExpr: %r %r]" % (self.proc_name, self.expr_ast_vec) + + def generate_prefix(self, paramTypes): + + # class method call + prefix = "(%s::" % self.type_ast + obj_type = self.type_ast.type + methodId = obj_type.methodId(self.proc_name, paramTypes) + + return obj_type, methodId, prefix + +__all__ = [ "MemberMethodCallExprAST", "ClassMethodCallExprAST" ] diff --git a/src/mem/slicc/ast/NewExprAST.cc b/src/mem/slicc/ast/NewExprAST.cc deleted file mode 100644 index 95e57192f..000000000 --- a/src/mem/slicc/ast/NewExprAST.cc +++ /dev/null @@ -1,9 +0,0 @@ - -#include "mem/slicc/ast/NewExprAST.hh" - -Type* NewExprAST::generate(string & code) const -{ - Type* type = m_type_ptr->lookupType(); - code += "new " + type->cIdent(); - return type; -} diff --git a/src/mem/slicc/ast/NewExprAST.hh b/src/mem/slicc/ast/NewExprAST.hh deleted file mode 100644 index 375f130d6..000000000 --- a/src/mem/slicc/ast/NewExprAST.hh +++ /dev/null @@ -1,20 +0,0 @@ -#ifndef NEWEXPRAST_H -#define NEWEXPRAST_H - -#include "mem/slicc/ast/ExprAST.hh" -#include "mem/slicc/ast/TypeAST.hh" -#include "mem/slicc/symbols/Type.hh" - -class NewExprAST : public ExprAST -{ -public: - NewExprAST(TypeAST* type_ptr) : ExprAST() { m_type_ptr = type_ptr; } - Type* generate(string & code) const; - void print(ostream & out) const { out << "[NewExprAST: " << *m_type_ptr << "]"; } - string getName() const { return m_type_ptr->toString(); } - -private: - TypeAST* m_type_ptr; -}; - -#endif diff --git a/src/mem/slicc/ast/NewExprAST.py b/src/mem/slicc/ast/NewExprAST.py new file mode 100644 index 000000000..a42350768 --- /dev/null +++ b/src/mem/slicc/ast/NewExprAST.py @@ -0,0 +1,47 @@ +# Copyright (c) 1999-2008 Mark D. Hill and David A. Wood +# Copyright (c) 2009 The Hewlett-Packard Development Company +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer; +# redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution; +# neither the name of the copyright holders nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +from slicc.ast.ExprAST import ExprAST + +class NewExprAST(ExprAST): + def __init__(self, slicc, type_ast): + super(NewExprAST, self).__init__(slicc) + self.type_ast = type_ast + + def __repr__(self): + return "[NewExprAST: %r]" % self.type_ast + + @property + def name(self): + return str(self.type_ast) + + def generate(self, code): + type = self.type_ast.type + fix = code.nofix() + code("new ${{type.c_ident}}") + code.fix(fix) + return type diff --git a/src/mem/slicc/ast/ObjDeclAST.cc b/src/mem/slicc/ast/ObjDeclAST.cc deleted file mode 100644 index 3569395db..000000000 --- a/src/mem/slicc/ast/ObjDeclAST.cc +++ /dev/null @@ -1,137 +0,0 @@ - -/* - * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer; - * redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution; - * neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/* - * ObjDeclAST.cc - * - * Description: See ObjDeclAST.hh - * - * $Id: ObjDeclAST.cc,v 3.13 2004/06/24 15:56:14 beckmann Exp $ - * - */ - -#include "mem/slicc/ast/ObjDeclAST.hh" -#include "mem/slicc/symbols/SymbolTable.hh" -#include "mem/slicc/main.hh" - -ObjDeclAST::ObjDeclAST(TypeAST* type_ptr, - string* ident_ptr, - PairListAST* pairs_ptr) - : DeclAST(pairs_ptr) -{ - m_type_ptr = type_ptr; - m_ident_ptr = ident_ptr; -} - -ObjDeclAST::~ObjDeclAST() -{ - delete m_type_ptr; - delete m_ident_ptr; -} - -void ObjDeclAST::generate() -{ - - bool machineComponentSym = false; - - getPairs().add("chip_object", "yes"); - - string c_code; - - - if (getPairs().exist("hack")) { - warning("'hack=' is now deprecated"); - } - - if (getPairs().exist("network")) { - if (!getPairs().exist("virtual_network")) { - error("Network queues require a 'virtual_network' attribute."); - } - } - - Type* type_ptr = m_type_ptr->lookupType(); - if (type_ptr->isBuffer()) { - if (!getPairs().exist("ordered")) { - error("Buffer object declarations require an 'ordered' attribute."); - } - } - - if (getPairs().exist("ordered")) { - string value = getPairs().lookup("ordered"); - if (value != "true" && value != "false") { - error("The 'ordered' attribute must be 'true' or 'false'."); - } - } - - if (getPairs().exist("random")) { - string value = getPairs().lookup("random"); - if (value != "true" && value != "false") { - error("The 'random' attribute must be 'true' or 'false'."); - } - } - - string machine; - if (g_sym_table.getStateMachine() != NULL) { - machine = g_sym_table.getStateMachine()->getIdent() + "_"; - } - - // FIXME : should all use accessors here to avoid public member variables - if (*m_ident_ptr == "id") { - c_code = "m_chip_ptr->getID()"; - } else if (*m_ident_ptr == "version") { - c_code = "m_version"; - } else if (*m_ident_ptr == "machineID") { - c_code = "m_machineID"; - } else { - c_code = "(*m_" + machine + *m_ident_ptr + "_ptr)"; - // c_code = "(*(m_chip_ptr->m_" + machine + *m_ident_ptr + "_ptr))"; - // machineComponentSym = true; - } - - Var* v = new Var(*m_ident_ptr, getLocation(), type_ptr, c_code, - getPairs(), g_sym_table.getStateMachine()); - - StateMachine* machine_ptr = g_sym_table.getStateMachine(); - if (machine_ptr != NULL) { - machine_ptr->addObj(v); - }// else { - g_sym_table.newSym(v); - //} - - // used to cheat-- that is, access components in other machines - if (machineComponentSym) { - g_sym_table.newMachComponentSym(v); - } - -} - -void ObjDeclAST::print(ostream& out) const -{ - out << "[ObjDecl: " << *m_ident_ptr << "]"; -} diff --git a/src/mem/slicc/ast/ObjDeclAST.hh b/src/mem/slicc/ast/ObjDeclAST.hh deleted file mode 100644 index 0b808f472..000000000 --- a/src/mem/slicc/ast/ObjDeclAST.hh +++ /dev/null @@ -1,86 +0,0 @@ - -/* - * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer; - * redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution; - * neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/* - * ObjDeclAST.hh - * - * Description: - * - * $Id: ObjDeclAST.hh,v 3.2 2003/07/10 18:08:06 milo Exp $ - * - */ - -#ifndef ObjDeclAST_H -#define ObjDeclAST_H - -#include "mem/slicc/slicc_global.hh" -#include "mem/slicc/ast/DeclAST.hh" -#include "mem/slicc/ast/TypeFieldAST.hh" -#include "mem/slicc/ast/TypeAST.hh" - -class ObjDeclAST : public DeclAST { -public: - // Constructors - ObjDeclAST(TypeAST* type_ptr, - string* ident_ptr, - PairListAST* pairs_ptr); - - // Destructor - ~ObjDeclAST(); - - // Public Methods - void generate(); - void print(ostream& out) const; -private: - // Private Methods - - // Private copy constructor and assignment operator - ObjDeclAST(const ObjDeclAST& obj); - ObjDeclAST& operator=(const ObjDeclAST& obj); - - // Data Members (m_ prefix) - string* m_ident_ptr; - TypeAST* m_type_ptr; -}; - -// Output operator declaration -ostream& operator<<(ostream& out, const ObjDeclAST& obj); - -// ******************* Definitions ******************* - -// Output operator definition -extern inline -ostream& operator<<(ostream& out, const ObjDeclAST& obj) -{ - obj.print(out); - out << flush; - return out; -} - -#endif //ObjDeclAST_H diff --git a/src/mem/slicc/ast/ObjDeclAST.py b/src/mem/slicc/ast/ObjDeclAST.py new file mode 100644 index 000000000..8a967f7b8 --- /dev/null +++ b/src/mem/slicc/ast/ObjDeclAST.py @@ -0,0 +1,94 @@ +# Copyright (c) 1999-2008 Mark D. Hill and David A. Wood +# Copyright (c) 2009 The Hewlett-Packard Development Company +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer; +# redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution; +# neither the name of the copyright holders nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +from slicc.ast.DeclAST import DeclAST +from slicc.symbols import Var + +class ObjDeclAST(DeclAST): + def __init__(self, slicc, type_ast, ident, pairs): + super(ObjDeclAST, self).__init__(slicc, pairs) + + self.type_ast = type_ast + self.ident = ident + + def __repr__(self): + return "[ObjDecl: %r]" % self.ident + + def generate(self): + machineComponentSym = False + + self["chip_object"] = "yes" + + if "hack" in self: + warning("'hack=' is now deprecated") + + if "network" in self and "virtual_network" not in self: + self.error("Network queues require a 'virtual_network' attribute") + + type = self.type_ast.type + if type.isBuffer and "ordered" not in self: + self.error("Buffer object decls require an 'ordered' attribute") + + if "ordered" in self: + value = self["ordered"] + + if value not in ("true", "false"): + self.error("The 'ordered' attribute is '%s' " + \ + "must be 'true' or 'false'.", value) + + if "random" in self: + value = self["random"] + if value not in ("true", "false"): + self.error("The 'random' attribute is '%s' " + \ + "must be 'true' or 'false'.", value) + + machine = self.symtab.state_machine + + # FIXME : should all use accessors here to avoid public member + # variables + if self.ident == "id": + c_code = "m_chip_ptr.getID()" + elif self.ident == "version": + c_code = "m_version" + elif self.ident == "machineID": + c_code = "m_machineID" + elif machine: + c_code = "(*m_%s_%s_ptr)" % (machine.ident, self.ident) + else: + c_code = "(*m_%s_ptr)" % (self.ident) + + v = Var(self.symtab, self.ident, self.location, type, c_code, + self.pairs, machine) + + if machine: + machine.addObject(v) + + self.symtab.newSymbol(v) + + # used to cheat-- that is, access components in other machines + if machineComponentSym: + self.symtab.newMachComponentSym(v) diff --git a/src/mem/slicc/ast/OutPortDeclAST.cc b/src/mem/slicc/ast/OutPortDeclAST.cc deleted file mode 100644 index 56a377f23..000000000 --- a/src/mem/slicc/ast/OutPortDeclAST.cc +++ /dev/null @@ -1,79 +0,0 @@ - -/* - * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer; - * redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution; - * neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/* - * OutPortDeclAST.C - * - * Description: See OutPortDeclAST.hh - * - * $Id: OutPortDeclAST.C,v 3.3 2004/02/02 22:37:51 milo Exp $ - * - */ - -#include "mem/slicc/ast/OutPortDeclAST.hh" -#include "mem/slicc/symbols/SymbolTable.hh" - -OutPortDeclAST::OutPortDeclAST(string* ident_ptr, - TypeAST* msg_type_ptr, - ExprAST* var_expr_ptr, - PairListAST* pairs_ptr) - : DeclAST(pairs_ptr) -{ - m_ident_ptr = ident_ptr; - m_msg_type_ptr = msg_type_ptr; - m_var_expr_ptr = var_expr_ptr; - m_queue_type_ptr = new TypeAST(new string("OutPort")); -} - -OutPortDeclAST::~OutPortDeclAST() -{ - delete m_ident_ptr; - delete m_msg_type_ptr; - delete m_var_expr_ptr; - delete m_queue_type_ptr; -} - -void OutPortDeclAST::generate() -{ - string code; - Type* queue_type_ptr = m_var_expr_ptr->generate(code); - if (!queue_type_ptr->isOutPort()) { - error("Outport queues must be of a type that has the 'outport' attribute. The type '" + - queue_type_ptr->toString() + "' does not have this attribute."); - } - - Type* type_ptr = m_queue_type_ptr->lookupType(); - g_sym_table.newSym(new Var(*m_ident_ptr, getLocation(), type_ptr, code, getPairs())); -} - - -void OutPortDeclAST::print(ostream& out) const -{ - out << "[OutPortDecl: " << *m_ident_ptr << "]"; -} diff --git a/src/mem/slicc/ast/OutPortDeclAST.hh b/src/mem/slicc/ast/OutPortDeclAST.hh deleted file mode 100644 index 0aa0172d3..000000000 --- a/src/mem/slicc/ast/OutPortDeclAST.hh +++ /dev/null @@ -1,89 +0,0 @@ - -/* - * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer; - * redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution; - * neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/* - * OutPortDeclAST.hh - * - * Description: - * - * $Id: OutPortDeclAST.hh,v 3.2 2003/07/10 18:08:06 milo Exp $ - * - */ - -#ifndef OutPortDeclAST_H -#define OutPortDeclAST_H - -#include "mem/slicc/slicc_global.hh" -#include "mem/slicc/ast/DeclAST.hh" -#include "mem/slicc/ast/StatementListAST.hh" -#include "mem/slicc/ast/VarExprAST.hh" - -class OutPortDeclAST : public DeclAST { -public: - // Constructors - OutPortDeclAST(string* ident_ptr, - TypeAST* msg_type_ptr, - ExprAST* var_expr_ptr, - PairListAST* pairs_ptr); - - // Destructor - ~OutPortDeclAST(); - - // Public Methods - void generate(); - void print(ostream& out) const; -private: - // Private Methods - - // Private copy constructor and assignment operator - OutPortDeclAST(const OutPortDeclAST& obj); - OutPortDeclAST& operator=(const OutPortDeclAST& obj); - - // Data Members (m_ prefix) - string* m_ident_ptr; - TypeAST* m_msg_type_ptr; - TypeAST* m_queue_type_ptr; - ExprAST* m_var_expr_ptr; -}; - -// Output operator declaration -ostream& operator<<(ostream& out, const OutPortDeclAST& obj); - -// ******************* Definitions ******************* - -// Output operator definition -extern inline -ostream& operator<<(ostream& out, const OutPortDeclAST& obj) -{ - obj.print(out); - out << flush; - return out; -} - -#endif //OutPortDeclAST_H diff --git a/src/mem/slicc/ast/OutPortDeclAST.py b/src/mem/slicc/ast/OutPortDeclAST.py new file mode 100644 index 000000000..e6ef31928 --- /dev/null +++ b/src/mem/slicc/ast/OutPortDeclAST.py @@ -0,0 +1,57 @@ +# Copyright (c) 1999-2008 Mark D. Hill and David A. Wood +# Copyright (c) 2009 The Hewlett-Packard Development Company +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer; +# redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution; +# neither the name of the copyright holders nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +from m5.util import code_formatter + +from slicc.ast.DeclAST import DeclAST +from slicc.ast.TypeAST import TypeAST +from slicc.symbols import Var + +class OutPortDeclAST(DeclAST): + def __init__(self, slicc, ident, msg_type, var_expr, pairs): + super(OutPortDeclAST, self).__init__(slicc, pairs) + + self.ident = ident + self.msg_type = msg_type + self.var_expr = var_expr + self.queue_type = TypeAST(slicc, "OutPort") + + def __repr__(self): + return "[OutPortDecl: %r]" % self.ident + + def generate(self): + code = code_formatter(newlines=False) + + queue_type = self.var_expr.generate(code) + if not queue_type.isOutPort: + self.error("The outport queue's type must have the 'outport' " + + "attribute. Type '%s' does not have this attribute.", + (queue_type)) + + var = Var(self.symtab, self.ident, self.location, self.queue_type.type, + str(code), self.pairs) + self.symtab.newSymbol(var) diff --git a/src/mem/slicc/ast/PairAST.hh b/src/mem/slicc/ast/PairAST.hh deleted file mode 100644 index d1bb99b93..000000000 --- a/src/mem/slicc/ast/PairAST.hh +++ /dev/null @@ -1,86 +0,0 @@ - -/* - * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer; - * redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution; - * neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/* - * PairAST.hh - * - * Description: - * - * $Id: PairAST.hh,v 3.1 2001/12/12 01:00:24 milo Exp $ - * - */ - -#ifndef PAIRAST_H -#define PAIRAST_H - -#include "mem/slicc/slicc_global.hh" -#include "mem/slicc/ast/AST.hh" - -class PairAST : public AST { -public: - // Constructors - PairAST(string* key_ptr, string* value_ptr); - PairAST(string key, string* value_ptr); - PairAST(string key, string value); - - // Destructor - ~PairAST(); - - // Public Methods - string key() const { return *m_key_ptr; } - string value() const { return *m_value_ptr; } - - virtual void print(ostream& out) const; -private: - // Private Methods - - // Private copy constructor and assignment operator - // PairAST(const PairAST& obj); - // PairAST& operator=(const PairAST& obj); - - // Data Members (m_ prefix) - string* m_key_ptr; - string* m_value_ptr; -}; - -// Output operator declaration -ostream& operator<<(ostream& out, const PairAST& obj); - -// ******************* Definitions ******************* - -// Output operator definition -extern inline -ostream& operator<<(ostream& out, const PairAST& obj) -{ - obj.print(out); - out << flush; - return out; -} - -#endif //PAIRAST_H diff --git a/src/mem/slicc/ast/PairAST.py b/src/mem/slicc/ast/PairAST.py new file mode 100644 index 000000000..347f4d361 --- /dev/null +++ b/src/mem/slicc/ast/PairAST.py @@ -0,0 +1,36 @@ +# Copyright (c) 2009 The Hewlett-Packard Development Company +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer; +# redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution; +# neither the name of the copyright holders nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +from slicc.ast.AST import AST + +class PairAST(AST): + def __init__(self, slicc, key, value): + super(PairAST, self).__init__(slicc) + self.key = key + self.value = value + + def __repr__(self): + return '[%s=%s]' % (self.key, self.value) diff --git a/src/mem/slicc/ast/PairListAST.py b/src/mem/slicc/ast/PairListAST.py new file mode 100644 index 000000000..6afe3f4fa --- /dev/null +++ b/src/mem/slicc/ast/PairListAST.py @@ -0,0 +1,37 @@ +# Copyright (c) 2009 The Hewlett-Packard Development Company +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer; +# redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution; +# neither the name of the copyright holders nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +from slicc.ast.AST import AST + +class PairListAST(AST): + def __init__(self, slicc): + super(PairListAST, self).__init__(slicc) + + def __repr__(self): + return "[PairListAST] %r" % self.pairs + + def addPair(self, pair_ast): + self[pair_ast.key] = pair_ast.value diff --git a/src/mem/slicc/ast/PeekStatementAST.cc b/src/mem/slicc/ast/PeekStatementAST.cc deleted file mode 100644 index 3e92446dd..000000000 --- a/src/mem/slicc/ast/PeekStatementAST.cc +++ /dev/null @@ -1,115 +0,0 @@ - -/* - * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer; - * redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution; - * neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/* - * PeekStatementAST.C - * - * Description: See PeekStatementAST.hh - * - * $Id$ - * - */ - -#include "mem/slicc/ast/PeekStatementAST.hh" -#include "mem/slicc/symbols/SymbolTable.hh" -#include "mem/slicc/ast/StatementListAST.hh" -#include "mem/slicc/ast/TypeAST.hh" -#include "mem/slicc/ast/VarExprAST.hh" - -PeekStatementAST::PeekStatementAST(VarExprAST* queue_name_ptr, - TypeAST* type_ptr, - StatementListAST* statementlist_ptr, - string method) - : StatementAST() -{ - m_queue_name_ptr = queue_name_ptr; - m_type_ptr = type_ptr; - m_statementlist_ptr = statementlist_ptr; - m_method = method; -} - -PeekStatementAST::~PeekStatementAST() -{ - delete m_queue_name_ptr; - delete m_type_ptr; - delete m_statementlist_ptr; -} - -void PeekStatementAST::generate(string& code, Type* return_type_ptr) const -{ - code += indent_str() + "{\n"; // Start scope - inc_indent(); - g_sym_table.pushFrame(); - - Type* msg_type_ptr = m_type_ptr->lookupType(); - - // Add new local var to symbol table - g_sym_table.newSym(new Var("in_msg", getLocation(), msg_type_ptr, "(*in_msg_ptr)", getPairs())); - - // Check the queue type - m_queue_name_ptr->assertType("InPort"); - - // Declare the new "in_msg_ptr" variable - code += indent_str() + "const " + msg_type_ptr->cIdent() + "* in_msg_ptr;\n"; // Declare message - // code += indent_str() + "in_msg_ptr = static_cast<const "; - code += indent_str() + "in_msg_ptr = dynamic_cast<const "; - code += msg_type_ptr->cIdent() + "*>("; - code += "(" + m_queue_name_ptr->getVar()->getCode() + ")"; - code += "."; - code += m_method; - code += "());\n"; - - code += indent_str() + "assert(in_msg_ptr != NULL);\n"; // Check the cast result - - if(CHECK_INVALID_RESOURCE_STALLS) { - // Declare the "in_buffer_rank" variable - code += indent_str() + "int in_buffer_rank = "; // Declare message - code += "(" + m_queue_name_ptr->getVar()->getCode() + ")"; - code += ".getPriority();\n"; - } - - m_statementlist_ptr->generate(code, return_type_ptr); // The other statements - dec_indent(); - g_sym_table.popFrame(); - code += indent_str() + "}\n"; // End scope -} - -void PeekStatementAST::findResources(Map<Var*, string>& resource_list) const -{ - m_statementlist_ptr->findResources(resource_list); -} - -void PeekStatementAST::print(ostream& out) const -{ - out << "[PeekStatementAST: " << m_method - << " queue_name: " << *m_queue_name_ptr - << " type: " << m_type_ptr->toString() - << " " << *m_statementlist_ptr - << "]"; -} diff --git a/src/mem/slicc/ast/PeekStatementAST.hh b/src/mem/slicc/ast/PeekStatementAST.hh deleted file mode 100644 index e8c65ce4f..000000000 --- a/src/mem/slicc/ast/PeekStatementAST.hh +++ /dev/null @@ -1,91 +0,0 @@ - -/* - * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer; - * redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution; - * neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/* - * PeekStatementAST.hh - * - * Description: - * - * $Id$ - * - */ - -#ifndef PEEKSTATEMENTAST_H -#define PEEKSTATEMENTAST_H - -#include "mem/slicc/slicc_global.hh" -#include "mem/slicc/ast/StatementAST.hh" - -class StatementListAST; -class TypeAST; -class VarExprAST; - -class PeekStatementAST : public StatementAST { -public: - // Constructors - PeekStatementAST(VarExprAST* queue_name_ptr, - TypeAST* type_ptr, - StatementListAST* statementlist_ptr, - string method); - // Destructor - ~PeekStatementAST(); - - // Public Methods - void generate(string& code, Type* return_type_ptr) const; - void findResources(Map<Var*, string>& resource_list) const; - void print(ostream& out) const; -private: - // Private Methods - - // Private copy constructor and assignment operator - PeekStatementAST(const PeekStatementAST& obj); - PeekStatementAST& operator=(const PeekStatementAST& obj); - - // Data Members (m_ prefix) - VarExprAST* m_queue_name_ptr; - TypeAST* m_type_ptr; - StatementListAST* m_statementlist_ptr; - string m_method; -}; - -// Output operator declaration -ostream& operator<<(ostream& out, const PeekStatementAST& obj); - -// ******************* Definitions ******************* - -// Output operator definition -extern inline -ostream& operator<<(ostream& out, const PeekStatementAST& obj) -{ - obj.print(out); - out << flush; - return out; -} - -#endif //PEEKSTATEMENTAST_H diff --git a/src/mem/slicc/ast/PeekStatementAST.py b/src/mem/slicc/ast/PeekStatementAST.py new file mode 100644 index 000000000..5186bf0d5 --- /dev/null +++ b/src/mem/slicc/ast/PeekStatementAST.py @@ -0,0 +1,73 @@ +# Copyright (c) 1999-2008 Mark D. Hill and David A. Wood +# Copyright (c) 2009 The Hewlett-Packard Development Company +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer; +# redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution; +# neither the name of the copyright holders nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +from slicc.ast.StatementAST import StatementAST +from slicc.symbols import Var + +class PeekStatementAST(StatementAST): + def __init__(self, slicc, queue_name, type_ast, statements, method): + super(PeekStatementAST, self).__init__(slicc) + + self.queue_name = queue_name + self.type_ast = type_ast + self.statements = statements + self.method = method + + def __repr__(self): + return "[PeekStatementAST: %r queue_name: %r type: %r %r]" % \ + (self.method, self.queue_name, self.type_ast, self.statements) + + def generate(self, code, return_type): + self.symtab.pushFrame() + + msg_type = self.type_ast.type + + # Add new local var to symbol table + var = Var(self.symtab, "in_msg", self.location, msg_type, "(*in_msg_ptr)", + self.pairs) + self.symtab.newSymbol(var) + + # Check the queue type + self.queue_name.assertType("InPort") + + # Declare the new "in_msg_ptr" variable + mtid = msg_type.ident + qcode = self.queue_name.var.code + code(''' +{ + const $mtid* in_msg_ptr; + in_msg_ptr = dynamic_cast<const $mtid *>(($qcode).${{self.method}}()); + assert(in_msg_ptr != NULL); +''') + + # The other statements + self.statements.generate(code, return_type) + self.symtab.popFrame() + code("}") + + def findResources(self, resources): + self.statements.findResources(resources) diff --git a/src/mem/slicc/ast/ReturnStatementAST.cc b/src/mem/slicc/ast/ReturnStatementAST.cc deleted file mode 100644 index 8ec937c87..000000000 --- a/src/mem/slicc/ast/ReturnStatementAST.cc +++ /dev/null @@ -1,79 +0,0 @@ - -/* - * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer; - * redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution; - * neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/* - * ReturnStatementAST.C - * - * Description: See ReturnStatementAST.hh - * - * $Id$ - * - */ - -#include "mem/slicc/ast/ReturnStatementAST.hh" - -ReturnStatementAST::ReturnStatementAST(ExprAST* expr_ptr) - : StatementAST() -{ - m_expr_ptr = expr_ptr; -} - -ReturnStatementAST::~ReturnStatementAST() -{ - delete m_expr_ptr; -} - -void ReturnStatementAST::generate(string& code, Type* return_type_ptr) const -{ - code += indent_str(); - code += "return "; - Type* actual_type_ptr = m_expr_ptr->generate(code); - code += ";\n"; - - // Is return valid here? - if (return_type_ptr == NULL) { - error("Invalid 'return' statement"); - } - - // The return type must match the return_type_ptr - if (return_type_ptr != actual_type_ptr) { - m_expr_ptr->error("Return type miss-match, expected return type is '" + return_type_ptr->toString() + - "', actual is '" + actual_type_ptr->toString() + "'"); - } -} - -void ReturnStatementAST::findResources(Map<Var*, string>& resource_list) const -{ - m_expr_ptr->findResources(resource_list); -} - -void ReturnStatementAST::print(ostream& out) const -{ - out << "[ReturnStatementAST: " << *m_expr_ptr << "]"; -} diff --git a/src/mem/slicc/ast/ReturnStatementAST.hh b/src/mem/slicc/ast/ReturnStatementAST.hh deleted file mode 100644 index 1fa1b36d6..000000000 --- a/src/mem/slicc/ast/ReturnStatementAST.hh +++ /dev/null @@ -1,83 +0,0 @@ - -/* - * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer; - * redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution; - * neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/* - * ReturnStatementAST.hh - * - * Description: - * - * $Id$ - * - */ - -#ifndef ReturnStatementAST_H -#define ReturnStatementAST_H - -#include "mem/slicc/slicc_global.hh" -#include "mem/slicc/ast/StatementAST.hh" -#include "mem/slicc/ast/ExprAST.hh" - -class ReturnStatementAST : public StatementAST { -public: - // Constructors - ReturnStatementAST(ExprAST* expr_ptr); - - // Destructor - ~ReturnStatementAST(); - - // Public Methods - void generate(string& code, Type* return_type_ptr) const; - void findResources(Map<Var*, string>& resource_list) const; - void print(ostream& out) const; -private: - // Private Methods - - // Private copy constructor and assignment operator - ReturnStatementAST(const ReturnStatementAST& obj); - ReturnStatementAST& operator=(const ReturnStatementAST& obj); - - // Data Members (m_ prefix) - ExprAST* m_expr_ptr; -}; - -// Output operator declaration -ostream& operator<<(ostream& out, const ReturnStatementAST& obj); - -// ******************* Definitions ******************* - -// Output operator definition -extern inline -ostream& operator<<(ostream& out, const ReturnStatementAST& obj) -{ - obj.print(out); - out << flush; - return out; -} - -#endif //ReturnStatementAST_H diff --git a/src/mem/slicc/ast/ReturnStatementAST.py b/src/mem/slicc/ast/ReturnStatementAST.py new file mode 100644 index 000000000..f1aff1c32 --- /dev/null +++ b/src/mem/slicc/ast/ReturnStatementAST.py @@ -0,0 +1,54 @@ +# Copyright (c) 1999-2008 Mark D. Hill and David A. Wood +# Copyright (c) 2009 The Hewlett-Packard Development Company +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer; +# redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution; +# neither the name of the copyright holders nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +from slicc.ast.StatementAST import StatementAST + +class ReturnStatementAST(StatementAST): + def __init__(self, slicc, expr_ast): + super(ReturnStatementAST, self).__init__(slicc) + + self.expr_ast = expr_ast + + def __repr__(self): + return "[ReturnStatementAST: %r]" % self.expr_ast + + def generate(self, code, return_type): + actual_type, ecode = self.expr_ast.inline(True) + code('return $ecode;') + + # Is return valid here? + if return_type is None: + self.error("Invalid 'return' statement") + + # The return type must match + if return_type != actual_type: + self.expr_ast.error("Return type miss-match, expected return " + + "type is '%s', actual is '%s'", + return_type, actual_type) + + def findResources(self, resources): + self.expr_ast.findResources(resources) diff --git a/src/mem/slicc/ast/StatementAST.hh b/src/mem/slicc/ast/StatementAST.hh deleted file mode 100644 index 9946541d3..000000000 --- a/src/mem/slicc/ast/StatementAST.hh +++ /dev/null @@ -1,88 +0,0 @@ - -/* - * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer; - * redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution; - * neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/* - * StatementAST.hh - * - * Description: - * - * $Id$ - * - */ - -#ifndef STATEMENTAST_H -#define STATEMENTAST_H - -#include "mem/slicc/slicc_global.hh" -#include "mem/slicc/ast/AST.hh" - -void inc_indent(); -void dec_indent(); -string indent_str(); - -class StatementAST : public AST { -public: - // Constructors - StatementAST() : AST() {} - StatementAST(Map<string, string> pairs) : AST(pairs) {} - - // Destructor - //~StatementAST(); - - // Public Methods - virtual void generate(string& code, Type* return_type_ptr) const = 0; - virtual void findResources(Map<Var*, string>& resource_list) const { } - - //void print(ostream& out) const; -private: - // Private Methods - - // Private copy constructor and assignment operator - //StatementAST(const StatementAST& obj); - //StatementAST& operator=(const StatementAST& obj); - - // Data Members (m_ prefix) - -}; - -// Output operator declaration -ostream& operator<<(ostream& out, const StatementAST& obj); - -// ******************* Definitions ******************* - -// Output operator definition -extern inline -ostream& operator<<(ostream& out, const StatementAST& obj) -{ - obj.print(out); - out << flush; - return out; -} - -#endif //STATEMENTAST_H diff --git a/src/mem/slicc/ast/StatementAST.py b/src/mem/slicc/ast/StatementAST.py new file mode 100644 index 000000000..017b2b1ed --- /dev/null +++ b/src/mem/slicc/ast/StatementAST.py @@ -0,0 +1,34 @@ +# Copyright (c) 2009 The Hewlett-Packard Development Company +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer; +# redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution; +# neither the name of the copyright holders nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +from slicc.ast.AST import AST + +class StatementAST(AST): + def __init__(self, slicc, pairs=None): + super(StatementAST, self).__init__(slicc, pairs) + + def findResources(self, resources): + pass diff --git a/src/mem/slicc/ast/StatementListAST.cc b/src/mem/slicc/ast/StatementListAST.cc deleted file mode 100644 index 0f5817f7c..000000000 --- a/src/mem/slicc/ast/StatementListAST.cc +++ /dev/null @@ -1,86 +0,0 @@ - -/* - * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer; - * redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution; - * neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/* - * StatementListAST.C - * - * Description: See StatementListAST.hh - * - * $Id$ - * - */ - -#include "mem/slicc/ast/StatementListAST.hh" - -StatementListAST::StatementListAST(Vector<StatementAST*>* vec_ptr) - : AST() -{ - assert(vec_ptr != NULL); - m_vec_ptr = vec_ptr; -} - -// Singleton constructor. -StatementListAST::StatementListAST(StatementAST* statement_ptr) - : AST() -{ - assert(statement_ptr != NULL); - m_vec_ptr = new Vector<StatementAST*>; - m_vec_ptr->insertAtTop(statement_ptr); -} - -StatementListAST::~StatementListAST() -{ - int size = m_vec_ptr->size(); - for(int i=0; i<size; i++) { - delete (*m_vec_ptr)[i]; - } - delete m_vec_ptr; -} - -void StatementListAST::generate(string& code, Type* return_type_ptr) const -{ - int size = m_vec_ptr->size(); - for(int i=0; i<size; i++) { - (*m_vec_ptr)[i]->generate(code, return_type_ptr); - } -} - -void StatementListAST::findResources(Map<Var*, string>& resource_list) const -{ - int size = m_vec_ptr->size(); - for(int i=0; i<size; i++) { - (*m_vec_ptr)[i]->findResources(resource_list); - } -} - -void StatementListAST::print(ostream& out) const -{ - assert(m_vec_ptr != NULL); - out << "[StatementListAST: " << *m_vec_ptr << "]"; -} diff --git a/src/mem/slicc/ast/StatementListAST.hh b/src/mem/slicc/ast/StatementListAST.hh deleted file mode 100644 index 831e2481a..000000000 --- a/src/mem/slicc/ast/StatementListAST.hh +++ /dev/null @@ -1,85 +0,0 @@ - -/* - * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer; - * redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution; - * neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/* - * StatementListAST.hh - * - * Description: - * - * $Id$ - * - */ - -#ifndef STATEMENTLISTAST_H -#define STATEMENTLISTAST_H - -#include "mem/slicc/slicc_global.hh" -#include "mem/slicc/ast/AST.hh" -#include "mem/slicc/ast/StatementAST.hh" -class Var; - -class StatementListAST : public AST { -public: - // Constructors - StatementListAST(Vector<StatementAST*>* vec_ptr); - StatementListAST(StatementAST* statement_ptr); - - // Destructor - ~StatementListAST(); - - // Public Methods - void generate(string& code, Type* return_type_ptr) const; - void findResources(Map<Var*, string>& resource_list) const; - void print(ostream& out) const; -private: - // Private Methods - - // Private copy constructor and assignment operator - StatementListAST(const StatementListAST& obj); - StatementListAST& operator=(const StatementListAST& obj); - - // Data Members (m_ prefix) - Vector<StatementAST*>* m_vec_ptr; -}; - -// Output operator declaration -ostream& operator<<(ostream& out, const StatementListAST& obj); - -// ******************* Definitions ******************* - -// Output operator definition -extern inline -ostream& operator<<(ostream& out, const StatementListAST& obj) -{ - obj.print(out); - out << flush; - return out; -} - -#endif //STATEMENTLISTAST_H diff --git a/src/mem/slicc/ast/StatementListAST.py b/src/mem/slicc/ast/StatementListAST.py new file mode 100644 index 000000000..1475c5c97 --- /dev/null +++ b/src/mem/slicc/ast/StatementListAST.py @@ -0,0 +1,46 @@ +# Copyright (c) 1999-2008 Mark D. Hill and David A. Wood +# Copyright (c) 2009 The Hewlett-Packard Development Company +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer; +# redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution; +# neither the name of the copyright holders nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +from slicc.ast.AST import AST + +class StatementListAST(AST): + def __init__(self, slicc, statements): + super(StatementListAST, self).__init__(slicc) + if not isinstance(statements, (list, tuple)): + statements = [ statements ] + self.statements = statements + + def __repr__(self): + return "[StatementListAST: %r]" % self.statements + + def generate(self, code, return_type): + for statement in self.statements: + statement.generate(code, return_type) + + def findResources(self, resources): + for statement in self.statements: + statement.findResources(resources) diff --git a/src/mem/slicc/ast/TransitionDeclAST.cc b/src/mem/slicc/ast/TransitionDeclAST.cc deleted file mode 100644 index 66b7ca132..000000000 --- a/src/mem/slicc/ast/TransitionDeclAST.cc +++ /dev/null @@ -1,89 +0,0 @@ - -/* - * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer; - * redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution; - * neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/* - * TransitionDeclAST.C - * - * Description: See TransitionDeclAST.hh - * - * $Id$ - * - */ - -#include "mem/slicc/ast/TransitionDeclAST.hh" -#include "mem/slicc/symbols/Transition.hh" - -TransitionDeclAST::TransitionDeclAST(Vector<string>* state_list_ptr, - Vector<string>* event_list_ptr, - string* next_state_ptr, - PairListAST* pairs_ptr, - Vector<string>* action_list_ptr) - : DeclAST(pairs_ptr) -{ - m_state_list_ptr = state_list_ptr; - m_event_list_ptr = event_list_ptr; - m_next_state_ptr = next_state_ptr; - m_action_list_ptr = action_list_ptr; -} - -TransitionDeclAST::~TransitionDeclAST() -{ - delete m_state_list_ptr; - delete m_event_list_ptr; - delete m_next_state_ptr; - delete m_action_list_ptr; -} - -void TransitionDeclAST::generate() -{ - Vector<string>& states = *m_state_list_ptr; - Vector<string>& events = *m_event_list_ptr; - - StateMachine* machine_ptr = g_sym_table.getStateMachine(); - if (machine_ptr == NULL) { - error("Transition declaration not part of a machine."); - } else if (m_next_state_ptr == NULL) { - for (int i=0; i<states.size(); i++) { - for (int j=0; j<events.size(); j++) { - machine_ptr->addTransition(new Transition(states[i], events[j], states[i], *m_action_list_ptr, getLocation(), getPairs())); - } - } - } else { - for (int i=0; i<states.size(); i++) { - for (int j=0; j<events.size(); j++) { - machine_ptr->addTransition(new Transition(states[i], events[j], *m_next_state_ptr, *m_action_list_ptr, getLocation(), getPairs())); - } - } - } -} - -void TransitionDeclAST::print(ostream& out) const -{ - out << "[TransitionDecl: ]"; -} diff --git a/src/mem/slicc/ast/TransitionDeclAST.hh b/src/mem/slicc/ast/TransitionDeclAST.hh deleted file mode 100644 index f07f0a3c2..000000000 --- a/src/mem/slicc/ast/TransitionDeclAST.hh +++ /dev/null @@ -1,89 +0,0 @@ - -/* - * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer; - * redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution; - * neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/* - * TransistionDeclAST.hh - * - * Description: - * - * $Id: TransitionDeclAST.hh,v 3.2 2003/07/10 18:08:07 milo Exp $ - * - */ - -#ifndef TransitionDeclAST_H -#define TransitionDeclAST_H - -#include "mem/slicc/slicc_global.hh" -#include "mem/slicc/ast/DeclAST.hh" -#include "mem/slicc/ast/StatementListAST.hh" - -class TransitionDeclAST : public DeclAST { -public: - // Constructors - TransitionDeclAST(Vector<string>* state_list_ptr, - Vector<string>* event_list_ptr, - string* next_state_ptr, - PairListAST* pairs_ptr, - Vector<string>* action_list_ptr); - - // Destructor - ~TransitionDeclAST(); - - // Public Methods - void generate(); - void print(ostream& out) const; -private: - // Private Methods - - // Private copy constructor and assignment operator - TransitionDeclAST(const TransitionDeclAST& obj); - TransitionDeclAST& operator=(const TransitionDeclAST& obj); - - // Data Members (m_ prefix) - Vector<string>* m_state_list_ptr; - Vector<string>* m_event_list_ptr; - string* m_next_state_ptr; - Vector<string>* m_action_list_ptr; -}; - -// Output operator declaration -ostream& operator<<(ostream& out, const TransitionDeclAST& obj); - -// ******************* Definitions ******************* - -// Output operator definition -extern inline -ostream& operator<<(ostream& out, const TransitionDeclAST& obj) -{ - obj.print(out); - out << flush; - return out; -} - -#endif //TransitionDeclAST_H diff --git a/src/mem/slicc/ast/TransitionDeclAST.py b/src/mem/slicc/ast/TransitionDeclAST.py new file mode 100644 index 000000000..a941d7b0c --- /dev/null +++ b/src/mem/slicc/ast/TransitionDeclAST.py @@ -0,0 +1,65 @@ +# Copyright (c) 1999-2008 Mark D. Hill and David A. Wood +# Copyright (c) 2009 The Hewlett-Packard Development Company +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer; +# redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution; +# neither the name of the copyright holders nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +from slicc.ast.DeclAST import DeclAST +from slicc.symbols import Transition + +class TransitionDeclAST(DeclAST): + def __init__(self, slicc, states, events, next_state, pairs, actions): + super(TransitionDeclAST, self).__init__(slicc, pairs) + + self.states = states + self.events = events + self.next_state = next_state + self.actions = actions + + def __repr__(self): + return "[TransitionDecl: ]" + + def generate(self): + machine = self.symtab.state_machine + + if machine is None: + self.error("Transition declaration not part of a machine.") + + for action in self.actions: + if action not in machine.actions: + self.error("Invalid action: %s is not part of machine: %s" % \ + (action, machine)) + + for state in self.states: + if state not in machine.states: + self.error("Invalid state: %s is not part of machine: %s" % \ + (state, machine)) + next_state = self.next_state or state + for event in self.events: + if event not in machine.events: + self.error("Invalid event: %s is not part of machine: %s" % \ + (event, machine)) + t = Transition(self.symtab, machine, state, event, next_state, + self.actions, self.location, self.pairs) + machine.addTransition(t) diff --git a/src/mem/slicc/ast/TypeAST.py b/src/mem/slicc/ast/TypeAST.py new file mode 100644 index 000000000..209859b8d --- /dev/null +++ b/src/mem/slicc/ast/TypeAST.py @@ -0,0 +1,53 @@ +# Copyright (c) 1999-2008 Mark D. Hill and David A. Wood +# Copyright (c) 2009 The Hewlett-Packard Development Company +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer; +# redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution; +# neither the name of the copyright holders nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +from slicc.ast.AST import AST + +from slicc.symbols import Type + +class TypeAST(AST): + def __init__(self, slicc, ident): + super(TypeAST, self).__init__(slicc) + + self.ident = ident + + def __repr__(self): + return self.ident + + def __str__(self): + return self.ident + + @property + def type(self, assert_type=None): + type = self.symtab.find(self.ident, Type) + if not type: + self.error("Type '%s' not declared.", self) + + if assert_type is not None and type != assert_type: + self.error("Type '%s' is should be type '%s'", self, assert_type) + + return type diff --git a/src/mem/slicc/ast/TypeDeclAST.hh b/src/mem/slicc/ast/TypeDeclAST.hh deleted file mode 100644 index 8a72c0406..000000000 --- a/src/mem/slicc/ast/TypeDeclAST.hh +++ /dev/null @@ -1,86 +0,0 @@ - -/* - * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer; - * redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution; - * neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/* - * TypeDeclAST.hh - * - * Description: - * - * $Id: TypeDeclAST.hh,v 3.2 2003/03/17 01:55:28 xu Exp $ - * - */ - -#ifndef TypeDeclAST_H -#define TypeDeclAST_H - -#include "mem/slicc/slicc_global.hh" -#include "mem/slicc/ast/DeclAST.hh" -#include "mem/slicc/ast/TypeAST.hh" -#include "mem/slicc/ast/TypeFieldAST.hh" - -class TypeDeclAST : public DeclAST { -public: - // Constructors - TypeDeclAST(TypeAST* type_ast_ptr, - PairListAST* pairs_ptr, - Vector<TypeFieldAST*>* field_vec_ptr); - - // Destructor - ~TypeDeclAST(); - - // Public Methods - virtual void generate(); - void print(ostream& out) const; -private: - // Private Methods - - // Private copy constructor and assignment operator - TypeDeclAST(const TypeDeclAST& obj); - TypeDeclAST& operator=(const TypeDeclAST& obj); - - // Data Members (m_ prefix) - TypeAST* m_type_ast_ptr; - Vector<TypeFieldAST*>* m_field_vec_ptr; -}; - -// Output operator declaration -ostream& operator<<(ostream& out, const TypeDeclAST& obj); - -// ******************* Definitions ******************* - -// Output operator definition -extern inline -ostream& operator<<(ostream& out, const TypeDeclAST& obj) -{ - obj.print(out); - out << flush; - return out; -} - -#endif //TypeDeclAST_H diff --git a/src/mem/slicc/ast/TypeDeclAST.py b/src/mem/slicc/ast/TypeDeclAST.py new file mode 100644 index 000000000..ecdb5949b --- /dev/null +++ b/src/mem/slicc/ast/TypeDeclAST.py @@ -0,0 +1,61 @@ +# Copyright (c) 1999-2008 Mark D. Hill and David A. Wood +# Copyright (c) 2009 The Hewlett-Packard Development Company +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer; +# redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution; +# neither the name of the copyright holders nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +from slicc.ast.DeclAST import DeclAST +from slicc.symbols.Type import Type + +class TypeDeclAST(DeclAST): + def __init__(self, slicc, type_ast, pairs, field_asts): + super(TypeDeclAST, self).__init__(slicc, pairs) + + self.type_ast = type_ast + self.field_asts = field_asts + + def __repr__(self): + return "[TypeDecl: %r]" % (self.type_ast) + + def files(self, parent=None): + if "external" in self: + return set() + + if parent: + ident = "%s_%s" % (parent, self.type_ast.ident) + else: + ident = self.type_ast.ident + return set(("%s.hh" % ident, "%s.cc" % ident)) + + def generate(self): + ident = str(self.type_ast) + + # Make the new type + new_type = Type(self.symtab, ident, self.location, self.pairs, + self.state_machine) + self.symtab.newSymbol(new_type) + + # Add all of the fields of the type to it + for field in self.field_asts: + field.generate(new_type) diff --git a/src/mem/slicc/ast/TypeFieldAST.hh b/src/mem/slicc/ast/TypeFieldAST.hh deleted file mode 100644 index 144372047..000000000 --- a/src/mem/slicc/ast/TypeFieldAST.hh +++ /dev/null @@ -1,83 +0,0 @@ - -/* - * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer; - * redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution; - * neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/* - * TypeFieldAST.hh - * - * Description: - * - * $Id$ - * - */ - -#ifndef TypeFieldAST_H -#define TypeFieldAST_H - -#include "mem/slicc/slicc_global.hh" -#include "mem/slicc/symbols/StateMachine.hh" -#include "mem/slicc/ast/StatementListAST.hh" -#include "mem/slicc/ast/PairListAST.hh" -#include "mem/slicc/ast/ExprAST.hh" - -class TypeFieldAST : public AST { -public: - // Constructors - TypeFieldAST(PairListAST* pairs_ptr); - - // Destructor - virtual ~TypeFieldAST() {} - - // Public Methods - virtual void generate(Type *type_ptr) = 0; - virtual void print(ostream& out) const = 0; -private: - // Private Methods - - // Private copy constructor and assignment operator - // TypeFieldAST(const TypeFieldAST& obj); - // TypeFieldAST& operator=(const TypeFieldAST& obj); - - // Data Members (m_ prefix) -}; - -// Output operator declaration -ostream& operator<<(ostream& out, const TypeFieldAST& obj); - -// ******************* Definitions ******************* - -// Output operator definition -extern inline -ostream& operator<<(ostream& out, const TypeFieldAST& obj) -{ - obj.print(out); - out << flush; - return out; -} - -#endif //TypeFieldAST_H diff --git a/src/mem/slicc/ast/TypeFieldAST.py b/src/mem/slicc/ast/TypeFieldAST.py new file mode 100644 index 000000000..7dd4c74aa --- /dev/null +++ b/src/mem/slicc/ast/TypeFieldAST.py @@ -0,0 +1,32 @@ +# Copyright (c) 1999-2008 Mark D. Hill and David A. Wood +# Copyright (c) 2009 The Hewlett-Packard Development Company +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer; +# redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution; +# neither the name of the copyright holders nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +from slicc.ast.AST import AST + +class TypeFieldAST(AST): + def __init__(self, slicc, pairs): + super(TypeFieldAST, self).__init__(slicc, pairs) diff --git a/src/mem/slicc/ast/TypeFieldEnumAST.cc b/src/mem/slicc/ast/TypeFieldEnumAST.cc deleted file mode 100644 index 1a02f7edd..000000000 --- a/src/mem/slicc/ast/TypeFieldEnumAST.cc +++ /dev/null @@ -1,82 +0,0 @@ - -/* - * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer; - * redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution; - * neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/* - * TypeFieldEnumAST.C - * - * Description: See TypeFieldEnumAST.hh - * - * $Id$ - * - */ - -#include "mem/slicc/ast/TypeFieldEnumAST.hh" -#include "mem/slicc/symbols/State.hh" -#include "mem/slicc/symbols/Event.hh" - -TypeFieldEnumAST::TypeFieldEnumAST(string* field_id_ptr, - PairListAST* pairs_ptr) - : TypeFieldAST(pairs_ptr) -{ - m_field_id_ptr = field_id_ptr; - m_pairs_ptr = pairs_ptr; -} - -TypeFieldEnumAST::~TypeFieldEnumAST() -{ - delete m_field_id_ptr; -} - -void TypeFieldEnumAST::generate(Type *type_ptr) -{ - // Add enumeration - if (!type_ptr->enumAdd(*m_field_id_ptr, m_pairs_ptr->getPairs())) { - error("Duplicate enumeration: " + type_ptr->toString() + ":" + *m_field_id_ptr); - } - - // Fill machine info - StateMachine* machine_ptr = g_sym_table.getStateMachine(); - if (type_ptr->toString() == "State") { - if (machine_ptr == NULL) { - error("State declaration not part of a machine."); - } - machine_ptr->addState(new State(*m_field_id_ptr, getLocation(), getPairs())); - } - if (type_ptr->toString() == "Event") { - if (machine_ptr == NULL) { - error("Event declaration not part of a machine."); - } - machine_ptr->addEvent(new Event(*m_field_id_ptr, getLocation(), getPairs())); - } -} - -void TypeFieldEnumAST::print(ostream& out) const -{ - out << "[TypeFieldEnum: " << *m_field_id_ptr << "]"; -} diff --git a/src/mem/slicc/ast/TypeFieldEnumAST.hh b/src/mem/slicc/ast/TypeFieldEnumAST.hh deleted file mode 100644 index cd02f03bb..000000000 --- a/src/mem/slicc/ast/TypeFieldEnumAST.hh +++ /dev/null @@ -1,86 +0,0 @@ - -/* - * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer; - * redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution; - * neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/* - * TypeFieldEnumAST.hh - * - * Description: - * - * $Id: TypeFieldEnumAST.hh,v 3.2 2003/07/10 18:08:07 milo Exp $ - * - */ - -#ifndef TypeFieldEnumAST_H -#define TypeFieldEnumAST_H - -#include "mem/slicc/slicc_global.hh" -#include "mem/slicc/symbols/StateMachine.hh" -#include "mem/slicc/ast/TypeFieldAST.hh" -#include "mem/slicc/ast/StatementListAST.hh" -#include "mem/slicc/ast/PairListAST.hh" - -class TypeFieldEnumAST : public TypeFieldAST { -public: - // Constructors - TypeFieldEnumAST(string* field_id_ptr, - PairListAST* pairs_ptr); - - // Destructor - ~TypeFieldEnumAST(); - - // Public Methods - void generate(Type *type_ptr); - void print(ostream& out) const; -private: - // Private Methods - - // Private copy constructor and assignment operator - TypeFieldEnumAST(const TypeFieldEnumAST& obj); - TypeFieldEnumAST& operator=(const TypeFieldEnumAST& obj); - - // Data Members (m_ prefix) - string* m_field_id_ptr; - PairListAST* m_pairs_ptr; -}; - -// Output operator declaration -ostream& operator<<(ostream& out, const TypeFieldEnumAST& obj); - -// ******************* Definitions ******************* - -// Output operator definition -extern inline -ostream& operator<<(ostream& out, const TypeFieldEnumAST& obj) -{ - obj.print(out); - out << flush; - return out; -} - -#endif //TypeFieldEnumAST_H diff --git a/src/mem/slicc/ast/TypeFieldEnumAST.py b/src/mem/slicc/ast/TypeFieldEnumAST.py new file mode 100644 index 000000000..138fff793 --- /dev/null +++ b/src/mem/slicc/ast/TypeFieldEnumAST.py @@ -0,0 +1,59 @@ +# Copyright (c) 1999-2008 Mark D. Hill and David A. Wood +# Copyright (c) 2009 The Hewlett-Packard Development Company +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer; +# redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution; +# neither the name of the copyright holders nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +from slicc.ast.TypeFieldAST import TypeFieldAST +from slicc.symbols import Event, State + +class TypeFieldEnumAST(TypeFieldAST): + def __init__(self, slicc, field_id, pairs_ast): + super(TypeFieldEnumAST, self).__init__(slicc, pairs_ast) + + self.field_id = field_id + self.pairs_ast = pairs_ast + + def __repr__(self): + return "[TypeFieldEnum: %r]" % self.field_id + + def generate(self, type): + # Add enumeration + if not type.enumAdd(self.field_id, self.pairs_ast.pairs): + self.error("Duplicate enumeration: %s:%s" % (type, self.field_id)) + + # Fill machine info + machine = self.symtab.state_machine + + if str(type) == "State": + if not machine: + self.error("State declaration not part of a machine.") + s = State(self.symtab, self.field_id, self.location, self.pairs) + machine.addState(s) + + if str(type) == "Event": + if not machine: + self.error("Event declaration not part of a machine.") + e = Event(self.symtab, self.field_id, self.location, self.pairs) + machine.addEvent(e) diff --git a/src/mem/slicc/ast/TypeFieldMemberAST.cc b/src/mem/slicc/ast/TypeFieldMemberAST.cc deleted file mode 100644 index 1fe0f6d4b..000000000 --- a/src/mem/slicc/ast/TypeFieldMemberAST.cc +++ /dev/null @@ -1,84 +0,0 @@ - -/* - * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer; - * redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution; - * neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/* - * TypeFieldMemberAST.C - * - * Description: See TypeFieldMemberAST.hh - * - * $Id: TypeFieldMemberAST.C,v 3.1 2003/03/27 22:58:54 xu Exp $ - * - */ - -#include "mem/slicc/ast/TypeFieldMemberAST.hh" - -TypeFieldMemberAST::TypeFieldMemberAST(TypeAST* type_ast_ptr, - string* field_id_ptr, - PairListAST* pairs_ptr, - ExprAST* rvalue_ptr) - : TypeFieldAST(pairs_ptr) -{ - m_type_ast_ptr = type_ast_ptr; - m_field_id_ptr = field_id_ptr; - m_rvalue_ptr = rvalue_ptr; -} - -TypeFieldMemberAST::~TypeFieldMemberAST() -{ - delete m_type_ast_ptr; - delete m_field_id_ptr; - if(m_rvalue_ptr) delete m_rvalue_ptr; -} - -void TypeFieldMemberAST::generate(Type *type_ptr) -{ - // Lookup type - Type* field_type_ptr = m_type_ast_ptr->lookupType(); - - // check type if this is a initialization - string* init_code = NULL; - if(m_rvalue_ptr) { - init_code = new string(); - Type* rvalue_type_ptr = m_rvalue_ptr->generate(*init_code); - if(field_type_ptr != rvalue_type_ptr) { - error("Initialization type mismatch '" + field_type_ptr->toString() + "' and '" + rvalue_type_ptr->toString() + "'"); - } - } - - // Add data member to the parent type - if (!type_ptr->dataMemberAdd(*m_field_id_ptr, field_type_ptr, getPairs(), - init_code)) { - error("Duplicate data member: " + type_ptr->toString() + ":" + *m_field_id_ptr); - } -} - -void TypeFieldMemberAST::print(ostream& out) const -{ - out << "[TypeFieldMember: " << *m_field_id_ptr << "]"; -} diff --git a/src/mem/slicc/ast/TypeFieldMemberAST.hh b/src/mem/slicc/ast/TypeFieldMemberAST.hh deleted file mode 100644 index 47355f3ac..000000000 --- a/src/mem/slicc/ast/TypeFieldMemberAST.hh +++ /dev/null @@ -1,91 +0,0 @@ - -/* - * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer; - * redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution; - * neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/* - * TypeFieldMemberAST.hh - * - * Description: - * - * $Id$ - * - */ - -#ifndef TypeFieldMemberAST_H -#define TypeFieldMemberAST_H - -#include "mem/slicc/slicc_global.hh" -#include "mem/slicc/ast/TypeFieldAST.hh" -#include "mem/slicc/symbols/StateMachine.hh" -#include "mem/slicc/ast/StatementListAST.hh" -#include "mem/slicc/ast/PairListAST.hh" -#include "mem/slicc/ast/ExprAST.hh" -#include "mem/slicc/ast/TypeAST.hh" - -class TypeFieldMemberAST : public TypeFieldAST { -public: - // Constructors - TypeFieldMemberAST(TypeAST* type_ast_ptr, - string* field_id_ptr, - PairListAST* pairs_ptr, - ExprAST* rvalue_ptr); - - // Destructor - ~TypeFieldMemberAST(); - - // Public Methods - void generate(Type *type_ptr); - void print(ostream& out) const; -private: - // Private Methods - - // Private copy constructor and assignment operator - TypeFieldMemberAST(const TypeFieldMemberAST& obj); - TypeFieldMemberAST& operator=(const TypeFieldMemberAST& obj); - - // Data Members (m_ prefix) - TypeAST* m_type_ast_ptr; - string* m_field_id_ptr; - ExprAST* m_rvalue_ptr; -}; - -// Output operator declaration -ostream& operator<<(ostream& out, const TypeFieldMemberAST& obj); - -// ******************* Definitions ******************* - -// Output operator definition -extern inline -ostream& operator<<(ostream& out, const TypeFieldMemberAST& obj) -{ - obj.print(out); - out << flush; - return out; -} - -#endif //TypeFieldMemberAST_H diff --git a/src/mem/slicc/ast/TypeFieldMemberAST.py b/src/mem/slicc/ast/TypeFieldMemberAST.py new file mode 100644 index 000000000..a60153664 --- /dev/null +++ b/src/mem/slicc/ast/TypeFieldMemberAST.py @@ -0,0 +1,57 @@ +# Copyright (c) 1999-2008 Mark D. Hill and David A. Wood +# Copyright (c) 2009 The Hewlett-Packard Development Company +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer; +# redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution; +# neither the name of the copyright holders nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +from slicc.ast.TypeFieldAST import TypeFieldAST + +class TypeFieldMemberAST(TypeFieldAST): + def __init__(self, slicc, type_ast, field_id, pairs, rvalue): + super(TypeFieldMemberAST, self).__init__(slicc, pairs) + + self.type_ast = type_ast + self.field_id = field_id + self.rvalue = rvalue + + def __repr__(self): + return "[TypeFieldMember: %r]" % self.field_id + + def generate(self, type): + # Lookup type + field_type = self.type_ast.type + + # check type if this is a initialization + init_code = "" + if self.rvalue: + rvalue_type,init_code = self.rvalue.inline(True) + if field_type != rvalue_type: + self.error("Initialization type mismatch '%s' and '%s'" % \ + (field_type, rvalue_type)) + + # Add data member to the parent type + if not type.dataMemberAdd(self.field_id, field_type, self.pairs, + init_code): + + self.error("Duplicate data member: %s:%s" % (type_ptr, field_id)) diff --git a/src/mem/slicc/ast/TypeFieldMethodAST.cc b/src/mem/slicc/ast/TypeFieldMethodAST.cc deleted file mode 100644 index 03c528f87..000000000 --- a/src/mem/slicc/ast/TypeFieldMethodAST.cc +++ /dev/null @@ -1,81 +0,0 @@ - -/* - * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer; - * redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution; - * neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/* - * TypeFieldMethodAST.C - * - * Description: See TypeFieldMethodAST.hh - * - * $Id: TypeFieldMethodAST.C,v 3.1 2003/07/10 18:08:07 milo Exp $ - * - */ - -#include "mem/slicc/ast/TypeFieldMethodAST.hh" - -TypeFieldMethodAST::TypeFieldMethodAST(TypeAST* return_type_ast_ptr, - string* ident_ptr, - Vector<TypeAST*>* type_ast_vec_ptr, - PairListAST* pairs_ptr) - : TypeFieldAST(pairs_ptr) -{ - m_return_type_ast_ptr = return_type_ast_ptr; - m_ident_ptr = ident_ptr; - m_type_ast_vec_ptr = type_ast_vec_ptr; -} - -TypeFieldMethodAST::~TypeFieldMethodAST() -{ - delete m_return_type_ast_ptr; - delete m_ident_ptr; - - int size = m_type_ast_vec_ptr->size(); - for(int i=0; i<size; i++) { - delete (*m_type_ast_vec_ptr)[i]; - } - delete m_type_ast_vec_ptr; -} - -void TypeFieldMethodAST::generate(Type *type_ptr) -{ - // Lookup return type - Type* return_type_ptr = m_return_type_ast_ptr->lookupType(); - - // Lookup parameter types - Vector<Type*> type_vec; - int size = m_type_ast_vec_ptr->size(); - for(int i=0; i<size; i++) { - Type* type_ptr = (*m_type_ast_vec_ptr)[i]->lookupType(); - type_vec.insertAtBottom(type_ptr); - } - - // Add method - if (!type_ptr->methodAdd(*m_ident_ptr, return_type_ptr, type_vec)) { // Return false on error - error("Duplicate method: " + type_ptr->toString() + ":" + *m_ident_ptr + "()"); - } -} diff --git a/src/mem/slicc/ast/TypeFieldMethodAST.hh b/src/mem/slicc/ast/TypeFieldMethodAST.hh deleted file mode 100644 index 10d53ef80..000000000 --- a/src/mem/slicc/ast/TypeFieldMethodAST.hh +++ /dev/null @@ -1,87 +0,0 @@ - -/* - * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer; - * redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution; - * neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/* - * TypeFieldMethodAST.hh - * - * Description: - * - * $Id: TypeFieldMethodAST.hh,v 3.2 2003/07/10 18:08:07 milo Exp $ - * - */ - -#ifndef TYPEFIELDMETHODAST_H -#define TYPEFIELDMETHODAST_H - -#include "mem/slicc/slicc_global.hh" -#include "mem/slicc/ast/TypeFieldAST.hh" -#include "mem/slicc/ast/TypeAST.hh" - -class TypeFieldMethodAST : public TypeFieldAST { -public: - // Constructors - TypeFieldMethodAST(TypeAST* return_type_ast_ptr, - string* ident_ptr, - Vector<TypeAST*>* type_ast_vec_ptr, - PairListAST* pairs_ptr); - // Destructor - ~TypeFieldMethodAST(); - - // Public Methods - - void generate(Type *type_ptr); - void print(ostream& out) const {} -private: - // Private Methods - - // Private copy constructor and assignment operator - TypeFieldMethodAST(const TypeFieldMethodAST& obj); - TypeFieldMethodAST& operator=(const TypeFieldMethodAST& obj); - - // Data Members (m_ prefix) - TypeAST* m_return_type_ast_ptr; - string* m_ident_ptr; - Vector<TypeAST*>* m_type_ast_vec_ptr; -}; - -// Output operator declaration -ostream& operator<<(ostream& out, const TypeFieldMethodAST& obj); - -// ******************* Definitions ******************* - -// Output operator definition -extern inline -ostream& operator<<(ostream& out, const TypeFieldMethodAST& obj) -{ - obj.print(out); - out << flush; - return out; -} - -#endif //TYPEFIELDMETHODAST_H diff --git a/src/mem/slicc/ast/TypeFieldMethodAST.py b/src/mem/slicc/ast/TypeFieldMethodAST.py new file mode 100644 index 000000000..2c8cf3f7b --- /dev/null +++ b/src/mem/slicc/ast/TypeFieldMethodAST.py @@ -0,0 +1,50 @@ +# Copyright (c) 1999-2008 Mark D. Hill and David A. Wood +# Copyright (c) 2009 The Hewlett-Packard Development Company +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer; +# redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution; +# neither the name of the copyright holders nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +from slicc.ast.TypeFieldAST import TypeFieldAST + +class TypeFieldMethodAST(TypeFieldAST): + def __init__(self, slicc, return_type_ast, ident, type_asts, pairs): + super(TypeFieldMethodAST, self).__init__(slicc, pairs) + + self.return_type_ast = return_type_ast + self.ident = ident + self.type_asts = type_asts + + def __repr__(self): + return "" + + def generate(self, type): + # Lookup return type + return_type = self.return_type_ast.type + + # Lookup parameter types + types = [ t.type for t in self.type_asts ] + + # Add method + if not type.methodAdd(self.ident, return_type, types): + self.error("Duplicate method: %s:%s()" % (type, self.ident)) diff --git a/src/mem/slicc/ast/VarExprAST.cc b/src/mem/slicc/ast/VarExprAST.cc deleted file mode 100644 index 13e265540..000000000 --- a/src/mem/slicc/ast/VarExprAST.cc +++ /dev/null @@ -1,76 +0,0 @@ - -/* - * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer; - * redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution; - * neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/* - * VarExprAST.C - * - * Description: See VarExprAST.hh - * - * $Id$ - * - */ - -#include "mem/slicc/ast/VarExprAST.hh" -#include "mem/slicc/ast/StatementAST.hh" -#include "mem/slicc/symbols/SymbolTable.hh" - -VarExprAST::~VarExprAST() -{ - delete m_var_ptr; -} - - -Var* VarExprAST::getVar() const -{ - string var = *m_var_ptr; - Var* var_ptr = g_sym_table.getVar(var); - if (var_ptr == NULL) { - error("Unrecognized variable: " + var); - } - return var_ptr; -} - -void VarExprAST::assertType(string type_ident) const -{ - Type* expected_type_ptr = g_sym_table.getType(type_ident); - if (expected_type_ptr == NULL) { - error("There must be a type '" + type_ident + "' declared in this scope"); - } - - if (getVar()->getType() != expected_type_ptr) { - error("Incorrect type: '" + getVar()->getIdent() + "' is expected to be type '" + expected_type_ptr->toString() + "'"); - } -} - -Type* VarExprAST::generate(string& code) const -{ - Var* var_ptr = getVar(); - code += var_ptr->getCode(); - return var_ptr->getType(); -} diff --git a/src/mem/slicc/ast/VarExprAST.hh b/src/mem/slicc/ast/VarExprAST.hh deleted file mode 100644 index ea32582a2..000000000 --- a/src/mem/slicc/ast/VarExprAST.hh +++ /dev/null @@ -1,86 +0,0 @@ - -/* - * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer; - * redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution; - * neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/* - * VarExprAST.hh - * - * Description: - * - * $Id$ - * - */ - -#ifndef VAREXPRAST_H -#define VAREXPRAST_H - -#include "mem/slicc/slicc_global.hh" -#include "mem/slicc/ast/ExprAST.hh" -class Var; - -class VarExprAST : public ExprAST { -public: - // Constructors - VarExprAST(string* var_ptr) : ExprAST() { m_var_ptr = var_ptr; } - - // Destructor - ~VarExprAST(); - - // Public Methods - Type* generate(string& code) const; - void print(ostream& out) const { out << "[VarExprAST: " << *m_var_ptr << "]"; } - string getName() const { return *m_var_ptr; } - Var* getVar() const; - void assertType(string type_ident) const; -private: - // Private Methods - - // Private copy constructor and assignment operator - VarExprAST(const VarExprAST& obj); - VarExprAST& operator=(const VarExprAST& obj); - - // Data Members (m_ prefix) - string* m_var_ptr; - -}; - -// Output operator declaration -ostream& operator<<(ostream& out, const VarExprAST& obj); - -// ******************* Definitions ******************* - -// Output operator definition -extern inline -ostream& operator<<(ostream& out, const VarExprAST& obj) -{ - obj.print(out); - out << flush; - return out; -} - -#endif //VAREXPRAST_H diff --git a/src/mem/slicc/ast/VarExprAST.py b/src/mem/slicc/ast/VarExprAST.py new file mode 100644 index 000000000..ac440bb68 --- /dev/null +++ b/src/mem/slicc/ast/VarExprAST.py @@ -0,0 +1,66 @@ +# Copyright (c) 1999-2008 Mark D. Hill and David A. Wood +# Copyright (c) 2009 The Hewlett-Packard Development Company +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer; +# redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution; +# neither the name of the copyright holders nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +from slicc.ast.ExprAST import ExprAST +from slicc.symbols import Type, Var + +class VarExprAST(ExprAST): + def __init__(self, slicc, var): + super(VarExprAST, self).__init__(slicc) + self._var = var + + def __repr__(self): + return "[VarExprAST: %r]" % self._var + + @property + def name(self): + return str(self._var) + + @property + def var(self): + var = self.symtab.find(self._var, Var) + if not var: + self.error("Unrecognized variable: %s", self._var) + return var + + def assertType(self, type_ident): + expected_type = self.symtab.find(type_ident, Type) + + if not expected_type: + self.error("There must be a type '%s' declared in this scope", + type_ident) + + if self.var.type != expected_type: + self.error("Incorrect type: " + \ + "'%s' is expected to be type '%s' not '%s'", + self.var.ident, expected_type, self.var.type) + + def generate(self, code): + fix = code.nofix() + code("${{self.var.code}}") + code.fix(fix) + return self.var.type diff --git a/src/mem/slicc/ast/__init__.py b/src/mem/slicc/ast/__init__.py new file mode 100644 index 000000000..de50cbd49 --- /dev/null +++ b/src/mem/slicc/ast/__init__.py @@ -0,0 +1,69 @@ +# Copyright (c) 2009 The Hewlett-Packard Development Company +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer; +# redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution; +# neither the name of the copyright holders nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +from slicc.ast.AST import * + +# actual ASTs +from slicc.ast.ActionDeclAST import * +from slicc.ast.AssignStatementAST import * +from slicc.ast.CheckAllocateStatementAST import * +from slicc.ast.CheckStopSlotsStatementAST import * +from slicc.ast.ChipComponentAccessAST import * +from slicc.ast.CopyHeadStatementAST import * +from slicc.ast.DeclAST import * +from slicc.ast.DeclListAST import * +from slicc.ast.EnqueueStatementAST import * +from slicc.ast.EnumDeclAST import * +from slicc.ast.EnumExprAST import * +from slicc.ast.ExprAST import * +from slicc.ast.ExprStatementAST import * +from slicc.ast.FormalParamAST import * +from slicc.ast.FuncCallExprAST import * +from slicc.ast.FuncDeclAST import * +from slicc.ast.IfStatementAST import * +from slicc.ast.InPortDeclAST import * +from slicc.ast.InfixOperatorExprAST import * +from slicc.ast.LiteralExprAST import * +from slicc.ast.MachineAST import * +from slicc.ast.MemberExprAST import * +from slicc.ast.MethodCallExprAST import * +from slicc.ast.NewExprAST import * +from slicc.ast.ObjDeclAST import * +from slicc.ast.OutPortDeclAST import * +from slicc.ast.PairAST import * +from slicc.ast.PairListAST import * +from slicc.ast.PeekStatementAST import * +from slicc.ast.ReturnStatementAST import * +from slicc.ast.StatementAST import * +from slicc.ast.StatementListAST import * +from slicc.ast.TransitionDeclAST import * +from slicc.ast.TypeAST import * +from slicc.ast.TypeDeclAST import * +from slicc.ast.TypeFieldAST import * +from slicc.ast.TypeFieldEnumAST import * +from slicc.ast.TypeFieldMemberAST import * +from slicc.ast.TypeFieldMethodAST import * +from slicc.ast.VarExprAST import * diff --git a/src/mem/slicc/generate/__init__.py b/src/mem/slicc/generate/__init__.py new file mode 100644 index 000000000..e69de29bb --- /dev/null +++ b/src/mem/slicc/generate/__init__.py diff --git a/src/mem/slicc/generate/dot.py b/src/mem/slicc/generate/dot.py new file mode 100644 index 000000000..762658983 --- /dev/null +++ b/src/mem/slicc/generate/dot.py @@ -0,0 +1,42 @@ +# Copyright (c) 1999-2008 Mark D. Hill and David A. Wood +# Copyright (c) 2009 The Hewlett-Packard Development Company +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer; +# redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution; +# neither the name of the copyright holders nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +from m5.util.code_formatter import code_formatter + +def printDotty(sm, code): + code('digraph ${{sm.getIdent()}} {') + code.indent() + for t in sm.transitions: + # Don't print ignored transitions + if t.getActionShorthands() in ("--", "z"): + continue + + code('${{t.getStateShorthand()}} -> ${{t.getNextStateShorthand()}') + code(' [label="${{t.getEventShorthand()}}/${{t.getActionShorthands()}}"') + code.dedent() + code('}') + diff --git a/src/mem/slicc/generate/html.py b/src/mem/slicc/generate/html.py new file mode 100644 index 000000000..53252ce3c --- /dev/null +++ b/src/mem/slicc/generate/html.py @@ -0,0 +1,80 @@ +# Copyright (c) 1999-2008 Mark D. Hill and David A. Wood +# Copyright (c) 2009 The Hewlett-Packard Development Company +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer; +# redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution; +# neither the name of the copyright holders nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +from m5.util.code_formatter import code_formatter + +def createSymbol(symbol, title): + code = code_formatter() + code('''<HTML><BODY><BIG> +$title: +${{formatShorthand(symbol.short)}} - ${{symbol.desc}}</BIG></BODY></HTML>''') + return code + +def formatShorthand(short): + munged_shorthand = "" + mode_is_normal = True + + # -- Walk over the string, processing superscript directives + gen = enumerate(short) + for i,c in gen: + if c == '!': + # -- Reached logical end of shorthand name + break + elif c == '_': + munged_shorthand += " " + elif c == '^': + # -- Process super/subscript formatting + mode_is_normal = not mode_is_normal + if mode_is_normal: + # -- Back to normal mode + munged_shorthand += "</SUP>" + else: + # -- Going to superscript mode + munged_shorthand += "<SUP>" + elif c == '\\': + # -- Process Symbol character set + if i + 1 < len(short): + # -- Proceed to next char. Yes I know that changing + # the loop var is ugly! + i,c = gen.next() + munged_shorthand += "<B><FONT size=+1>" + munged_shorthand += c + munged_shorthand += "</FONT></B>" + else: + # -- FIXME: Add line number info later + panic("Encountered a `\\` without anything following it!") + else: + # -- Pass on un-munged + munged_shorthand += c + + # -- Do any other munging + if not mode_is_normal: + # -- Back to normal mode + munged_shorthand += "</SUP>" + + return munged_shorthand + diff --git a/src/mem/slicc/generate/tex.py b/src/mem/slicc/generate/tex.py new file mode 100644 index 000000000..97c63ebc6 --- /dev/null +++ b/src/mem/slicc/generate/tex.py @@ -0,0 +1,71 @@ +# Copyright (c) 1999-2008 Mark D. Hill and David A. Wood +# Copyright (c) 2009 The Hewlett-Packard Development Company +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer; +# redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution; +# neither the name of the copyright holders nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +from m5.util.code_formatter import code_formatter + +class tex_formatter(code_formatter): + braced = "<>" + double_braced = "<<>>" + +def printTexTable(sm, code): + tex = tex_formatter() + tex(r''' +%& latex +\documentclass[12pt]{article} +\usepackage{graphics} +\begin{document} +\begin{tabular}{|l||$<<"l" * len(sm.events)>>|} \hline +''') + + for event in sm.events: + code(r" & \rotatebox{90}{$<<event.short>>}") + tex(r'\\ \hline \hline') + + for state in sm.states: + state_str = state.short + for event in sm.events: + state_str += ' & ' + trans = sm.get_transition(state, event) + if trans: + actions = trans.getActionShorthands() + # FIXME: should compare index, not the string + if trans.getNextStateShorthand() != state.short: + nextState = trans.getNextStateShorthand() + else: + nextState = "" + state_str += actions + if nextState and actions: + state_str += '/' + state_str += nextState + tex(r'$0 \\', state_str) + tex(r''' +\hline +\end{tabular} +\end{document} +''') + + code.append(tex) diff --git a/src/mem/slicc/generator/html_gen.cc b/src/mem/slicc/generator/html_gen.cc deleted file mode 100644 index 2d35dccb6..000000000 --- a/src/mem/slicc/generator/html_gen.cc +++ /dev/null @@ -1,125 +0,0 @@ - -/* - * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer; - * redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution; - * neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/* - * html_gen.C - * - * Description: See html_gen.hh - * - * $Id: html_gen.C,v 3.4 2004/01/31 20:46:50 milo Exp $ - * - * */ - -#include "mem/slicc/generator/html_gen.hh" -#include "mem/slicc/generator/fileio.hh" -#include "mem/slicc/symbols/SymbolTable.hh" - -string formatHTMLShorthand(const string shorthand); - - -void createHTMLSymbol(const Symbol& sym, string title, ostream& out) -{ - out << "<HTML><BODY><BIG>" << endl; - out << title << ": " << endl; - out << formatHTMLShorthand(sym.getShorthand()) << " - "; - out << sym.getDescription(); - out << "</BIG></BODY></HTML>" << endl; -} - -void createHTMLindex(string title, ostream& out) -{ - out << "<html>" << endl; - out << "<head>" << endl; - out << "<title>" << title << "</title>" << endl; - out << "</head>" << endl; - out << "<frameset rows=\"*,30\">" << endl; - Vector<StateMachine*> machine_vec = g_sym_table.getStateMachines(); - if (machine_vec.size() > 1) { - string machine = machine_vec[0]->getIdent(); - out << " <frame name=\"Table\" src=\"" << machine << "_table.html\">" << endl; - } else { - out << " <frame name=\"Table\" src=\"empty.html\">" << endl; - } - - out << " <frame name=\"Status\" src=\"empty.html\">" << endl; - out << "</frameset>" << endl; - out << "</html>" << endl; -} - -string formatHTMLShorthand(const string shorthand) -{ - string munged_shorthand = ""; - bool mode_is_normal = true; - - // -- Walk over the string, processing superscript directives - for(unsigned int i = 0; i < shorthand.length(); i++) { - if(shorthand[i] == '!') { - // -- Reached logical end of shorthand name - break; - } else if( shorthand[i] == '_') { - munged_shorthand += " "; - } else if( shorthand[i] == '^') { - // -- Process super/subscript formatting - mode_is_normal = !mode_is_normal; - if(mode_is_normal) { - // -- Back to normal mode - munged_shorthand += "</SUP>"; - } else { - // -- Going to superscript mode - munged_shorthand += "<SUP>"; - } - } else if(shorthand[i] == '\\') { - // -- Process Symbol character set - if((i + 1) < shorthand.length()) { - i++; // -- Proceed to next char. Yes I know that changing the loop var is ugly! - munged_shorthand += "<B><FONT size=+1>"; - munged_shorthand += shorthand[i]; - munged_shorthand += "</FONT></B>"; - } else { - // -- FIXME: Add line number info later - cerr << "Encountered a `\\` without anything following it!" << endl; - exit( -1 ); - } - } else { - // -- Pass on un-munged - munged_shorthand += shorthand[i]; - } - } // -- end for all characters in shorthand - - // -- Do any other munging - if(!mode_is_normal) { - // -- Back to normal mode - munged_shorthand += "</SUP>"; - } - - // -- Return the formatted shorthand name - return munged_shorthand; -} - - diff --git a/src/mem/slicc/generator/html_gen.hh b/src/mem/slicc/generator/html_gen.hh deleted file mode 100644 index 6b1f8ea92..000000000 --- a/src/mem/slicc/generator/html_gen.hh +++ /dev/null @@ -1,49 +0,0 @@ - -/* - * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer; - * redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution; - * neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/* - * html_gen.hh - * - * Description: - * - * $Id: html_gen.hh,v 3.1 2001/12/12 01:00:35 milo Exp $ - * - * */ - -#ifndef HTML_GEN_H -#define HTML_GEN_H - -#include "mem/slicc/slicc_global.hh" -#include "mem/slicc/symbols/StateMachine.hh" - -string formatHTMLShorthand(const string shorthand); -void createHTMLindex(string title, ostream& out); -void createHTMLSymbol(const Symbol& sym, string title, ostream& out); - -#endif //HTML_GEN_H diff --git a/src/mem/slicc/generator/mif_gen.cc b/src/mem/slicc/generator/mif_gen.cc deleted file mode 100644 index 2dca149b4..000000000 --- a/src/mem/slicc/generator/mif_gen.cc +++ /dev/null @@ -1,1718 +0,0 @@ - -/* - * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer; - * redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution; - * neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/* - * $Id$ - * - */ - -#include "mem/slicc/generator/mif_gen.hh" -#include "mem/slicc/symbols/State.hh" -#include "mem/slicc/symbols/Event.hh" -#include "mem/slicc/symbols/Action.hh" -#include "mem/slicc/symbols/Transition.hh" - -// -- Helper functions -string formatShorthand(const string shorthand); -string formatCellRuling(const string shorthand); - -void printStateTableMIF(const StateMachine& sm, ostream& out) -{ - const string mif_prolog1 = -"<MIFFile 5.50> # Generated by Multifacet MIF Mungers Inc\n\ -<Tbls\n\ - <Tbl\n\ - <TblID 1>\n\ - <TblTag `Format A'>\n\ - <TblFormat\n\ -\n\ - <TblAlignment Center>\n\ -\n\ - # <TblXColumnNum 0>\n\ - <TblXColumnRuling `Medium'>\n\ -\n\ - <TblLRuling `Medium'>\n\ - <TblRRuling `Medium'>\n\ - <TblTRuling `Medium'>\n\ - <TblBRuling `Medium'>\n\ -\n\ - <TblColumn\n\ - <TblColumnNum 0>\n\ - <TblColumnWidth 0.51\">\n\ - <TblColumnH\n\ - <PgfTag `CellHeading'>\n\ - > # end of TblColumnH\n\ - <TblColumnBody\n\ - <PgfTag `CellBody'>\n\ - > # end of TblColumnBody\n\ - <TblColumnF\n\ - <PgfTag `CellHeading'>\n\ - > # end of TblColumnF\n\ - > # end of TblColumn\n\ - <TblColumn\n\ - <TblColumnNum 1>\n\ - <TblColumnWidth 0.51\">\n\ - <TblColumnH\n\ - <PgfTag `CellHeading'>\n\ - > # end of TblColumnH\n\ - <TblColumnBody\n\ - <PgfTag `CellBody'>\n\ - > # end of TblColumnBody\n\ - <TblColumnF\n\ - <PgfTag `CellHeading'>\n\ - > # end of TblColumnF\n\ - > # end of TblColumn\n\ - > # end of TblFormat\n\ -\n\ - <TblNumColumns 2>\n\ - <TblColumnWidth 0.51\">\n\ - <TblColumnWidth 6.00\">\n\ - <TblTitle\n\ - <TblTitleContent\n\ - <Para\n\ - <PgfTag `TableTitle'>\n\ - <Pgf\n\ - <PgfAlignment Center>\n\ - <PgfFont \n\ - <FTag `'>\n\ - <FFamily `Times'>\n\ - <FVar `Regular'>\n\ - <FWeight `Regular'>\n\ - <FAngle `Regular'>\n\ - <FPostScriptName `Times-Roman'>\n\ - <FEncoding `FrameRoman'>\n\ - <FSize 11.0 pt>\n\ - <FUnderlining FNoUnderlining>\n\ - <FOverline No>\n\ - <FStrike No>\n\ - <FChangeBar No>\n\ - <FOutline No>\n\ - <FShadow No>\n\ - <FPairKern Yes>\n\ - <FTsume No>\n\ - <FCase FAsTyped>\n\ - <FPosition FNormal>\n\ - <FDX 0.0%>\n\ - <FDY 0.0%>\n\ - <FDW 0.0%>\n\ - <FStretch 100.0%>\n\ - <FLanguage USEnglish>\n\ - <FLocked No>\n\ - <FSeparation 0>\n\ - <FColor `Black'>\n\ - > # end of PgfFont\n\ - > # end of Pgf\n\ - <PgfNumString `TABLE 1. '>\n\ - <ParaLine\n\ - <Marker\n\ - <MType 9>\n\ - <MTypeName `Cross-Ref'>\n\ - <MCurrPage `1'>\n\ - > # end of Marker\n\ - <String `"; - - const string mif_prolog2 = - "'>\n\ - > # end of ParaLine\n\ - > # end of Para\n\ - > # end of TblTitleContent\n\ - > # end of TblTitle\n\ -\n\ - <TblH\n\ - <Row\n\ - <RowMaxHeight 14.0\">\n\ - <RowHeight 0.44444\">\n\ - <Cell\n\ - <CellLRuling `Medium'>\n\ - <CellBRuling `Medium'>\n\ - <CellRRuling `Medium'>\n\ - <CellTRuling `Medium'>\n\ - <CellContent\n\ - <Para\n\ - <PgfTag `CellHeading'>\n\ - <Pgf\n\ - <PgfAlignment Center>\n\ - <PgfFont \n\ - <FTag `'>\n\ - <FFamily `Times'>\n\ - <FVar `Regular'>\n\ - <FWeight `Regular'>\n\ - <FAngle `Regular'>\n\ - <FPostScriptName `Times-Roman'>\n\ - <FEncoding `FrameRoman'>\n\ - <FSize 11.0 pt>\n\ - <FUnderlining FNoUnderlining>\n\ - <FOverline No>\n\ - <FStrike No>\n\ - <FChangeBar No>\n\ - <FOutline No>\n\ - <FShadow No>\n\ - <FPairKern Yes>\n\ - <FTsume No>\n\ - <FCase FAsTyped>\n\ - <FPosition FNormal>\n\ - <FDX 0.0%>\n\ - <FDY 0.0%>\n\ - <FDW 0.0%>\n\ - <FStretch 100.0%>\n\ - <FLanguage USEnglish>\n\ - <FLocked No>\n\ - <FSeparation 0>\n\ - <FColor `Black'>\n\ - > # end of PgfFont\n\ - >\n\ - <ParaLine\n\ - <String `State'>\n\ - > # end of ParaLine\n\ - > # end of Para\n\ - > # end of CellContent\n\ - > # end of Cell\n\ - <Cell\n\ - <CellLRuling `Medium'>\n\ - <CellBRuling `Medium'>\n\ - <CellRRuling `Medium'>\n\ - <CellTRuling `Medium'>\n\ - <CellContent\n\ - <Para\n\ - <PgfTag `CellHeading'>\n\ - <PgfFont \n\ - <FTag `'>\n\ - <FFamily `Times'>\n\ - <FVar `Regular'>\n\ - <FWeight `Regular'>\n\ - <FAngle `Regular'>\n\ - <FPostScriptName `Times-Roman'>\n\ - <FEncoding `FrameRoman'>\n\ - <FSize 11.0 pt>\n\ - <FUnderlining FNoUnderlining>\n\ - <FOverline No>\n\ - <FStrike No>\n\ - <FChangeBar No>\n\ - <FOutline No>\n\ - <FShadow No>\n\ - <FPairKern Yes>\n\ - <FTsume No>\n\ - <FCase FAsTyped>\n\ - <FPosition FNormal>\n\ - <FDX 0.0%>\n\ - <FDY 0.0%>\n\ - <FDW 0.0%>\n\ - <FStretch 100.0%>\n\ - <FLanguage USEnglish>\n\ - <FLocked No>\n\ - <FSeparation 0>\n\ - <FColor `Black'>\n\ - > # end of PgfFont\n\ - <ParaLine\n\ - <String `Description'>\n\ - > # end of ParaLine\n\ - > # end of Para\n\ - > # end of CellContent\n\ - > # end of Cell\n\ - > # end of Row\n\ - > # end of TblH\n\ -\n\ - <TblBody\n\ -"; - - const string row_before_state = -" <Row\n\ - <RowMaxHeight 14.0\">\n\ - <RowHeight 0.22222\">\n\ - <Cell\n\ - <CellContent\n\ - <Para\n\ - <PgfTag `CellBody'>\n\ - <Pgf\n\ - <PgfAlignment Center>\n\ - <PgfFont \n\ - <FTag `'>\n\ - <FFamily `Times'>\n\ - <FVar `Regular'>\n\ - <FWeight `Regular'>\n\ - <FAngle `Regular'>\n\ - <FPostScriptName `Times-Roman'>\n\ - <FEncoding `FrameRoman'>\n\ - <FSize 11.0 pt>\n\ - <FUnderlining FNoUnderlining>\n\ - <FOverline No>\n\ - <FStrike No>\n\ - <FChangeBar No>\n\ - <FOutline No>\n\ - <FShadow No>\n\ - <FPairKern Yes>\n\ - <FTsume No>\n\ - <FCase FAsTyped>\n\ - <FPosition FNormal>\n\ - <FDX 0.0%>\n\ - <FDY 0.0%>\n\ - <FDW 0.0%>\n\ - <FStretch 100.0%>\n\ - <FLanguage USEnglish>\n\ - <FLocked No>\n\ - <FSeparation 0>\n\ - <FColor `Black'>\n\ - > # end of PgfFont\n\ - >\n\ - <ParaLine\n\ - <String `"; - - const string row_between_state_desc = - "'>\n\ - > # end of ParaLine\n\ - > # end of Para\n\ - > # end of CellContent\n\ - > # end of Cell\n\ - <Cell\n\ - <CellContent\n\ - <Para\n\ - <PgfTag `CellBody'>\n\ - <ParaLine\n\ - <String `"; - - const string row_after_desc = - "'>\n\ - > # end of ParaLine\n\ - > # end of Para\n\ - > # end of CellContent\n\ - > # end of Cell\n\ - > # end of Row\n\ -"; - - const string mif_epilog = -" > # end of TblBody\n\ - > # end of Tbl\n\ -> # end of Tbls\n\ -\n\ - <Para\n\ - <ParaLine\n\ - <ATbl 1>\n\ - > # end of ParaLine\n\ - > # end of Para\n\ -\n\ -# End of MIFFile\n\ -"; - - out << mif_prolog1; - out << formatShorthand( sm.getShorthand() ); - out << " states"; - out << mif_prolog2; - - for( int i = 0; i < sm.numStates(); i++ ) - { - out << row_before_state; - out << formatShorthand( sm.getState( i ).getShorthand() ); - out << row_between_state_desc; - out << sm.getState( i ).getDescription(); - out << row_after_desc; - } - - out << mif_epilog; -} - - -void printEventTableMIF(const StateMachine& sm, ostream& out) -{ - const string mif_prolog1 = -"<MIFFile 5.50> # Generated by Multifacet MIF Mungers Inc\n\ -<Tbls\n\ - <Tbl\n\ - <TblID 1>\n\ - <TblTag `Format A'>\n\ - <TblFormat\n\ -\n\ - <TblAlignment Center>\n\ -\n\ - # <TblXColumnNum 0>\n\ - <TblXColumnRuling `Medium'>\n\ -\n\ - <TblLRuling `Medium'>\n\ - <TblRRuling `Medium'>\n\ - <TblTRuling `Medium'>\n\ - <TblBRuling `Medium'>\n\ -\n\ - <TblColumn\n\ - <TblColumnNum 0>\n\ - <TblColumnWidth 0.51\">\n\ - <TblColumnH\n\ - <PgfTag `CellHeading'>\n\ - > # end of TblColumnH\n\ - <TblColumnBody\n\ - <PgfTag `CellBody'>\n\ - > # end of TblColumnBody\n\ - <TblColumnF\n\ - <PgfTag `CellHeading'>\n\ - > # end of TblColumnF\n\ - > # end of TblColumn\n\ - <TblColumn\n\ - <TblColumnNum 1>\n\ - <TblColumnWidth 0.51\">\n\ - <TblColumnH\n\ - <PgfTag `CellHeading'>\n\ - > # end of TblColumnH\n\ - <TblColumnBody\n\ - <PgfTag `CellBody'>\n\ - > # end of TblColumnBody\n\ - <TblColumnF\n\ - <PgfTag `CellHeading'>\n\ - > # end of TblColumnF\n\ - > # end of TblColumn\n\ - > # end of TblFormat\n\ -\n\ - <TblNumColumns 2>\n\ - <TblColumnWidth 0.51\">\n\ - <TblColumnWidth 6.00\">\n\ - <TblTitle\n\ - <TblTitleContent\n\ - <Para\n\ - <PgfTag `TableTitle'>\n\ - <Pgf\n\ - <PgfAlignment Center>\n\ - <PgfFont \n\ - <FTag `'>\n\ - <FFamily `Times'>\n\ - <FVar `Regular'>\n\ - <FWeight `Regular'>\n\ - <FAngle `Regular'>\n\ - <FPostScriptName `Times-Roman'>\n\ - <FEncoding `FrameRoman'>\n\ - <FSize 11.0 pt>\n\ - <FUnderlining FNoUnderlining>\n\ - <FOverline No>\n\ - <FStrike No>\n\ - <FChangeBar No>\n\ - <FOutline No>\n\ - <FShadow No>\n\ - <FPairKern Yes>\n\ - <FTsume No>\n\ - <FCase FAsTyped>\n\ - <FPosition FNormal>\n\ - <FDX 0.0%>\n\ - <FDY 0.0%>\n\ - <FDW 0.0%>\n\ - <FStretch 100.0%>\n\ - <FLanguage USEnglish>\n\ - <FLocked No>\n\ - <FSeparation 0>\n\ - <FColor `Black'>\n\ - > # end of PgfFont\n\ - > # end of Pgf\n\ - <PgfNumString `TABLE 1. '>\n\ - <ParaLine\n\ - <Marker\n\ - <MType 9>\n\ - <MTypeName `Cross-Ref'>\n\ - <MCurrPage `1'>\n\ - > # end of Marker\n\ - <String `"; - const string mif_prolog2 = -"'>\n\ - > # end of ParaLine\n\ - > # end of Para\n\ - > # end of TblTitleContent\n\ - > # end of TblTitle\n\ -\n\ - <TblH\n\ - <Row\n\ - <RowMaxHeight 14.0\">\n\ - <RowHeight 0.44444\">\n\ - <Cell\n\ - <CellLRuling `Medium'>\n\ - <CellBRuling `Medium'>\n\ - <CellRRuling `Medium'>\n\ - <CellTRuling `Medium'>\n\ - <CellContent\n\ - <Para\n\ - <PgfTag `CellHeading'>\n\ - <PgfFont \n\ - <FTag `'>\n\ - <FFamily `Times'>\n\ - <FVar `Regular'>\n\ - <FWeight `Regular'>\n\ - <FAngle `Regular'>\n\ - <FPostScriptName `Times-Roman'>\n\ - <FEncoding `FrameRoman'>\n\ - <FSize 11.0 pt>\n\ - <FUnderlining FNoUnderlining>\n\ - <FOverline No>\n\ - <FStrike No>\n\ - <FChangeBar No>\n\ - <FOutline No>\n\ - <FShadow No>\n\ - <FPairKern Yes>\n\ - <FTsume No>\n\ - <FCase FAsTyped>\n\ - <FPosition FNormal>\n\ - <FDX 0.0%>\n\ - <FDY 0.0%>\n\ - <FDW 0.0%>\n\ - <FStretch 100.0%>\n\ - <FLanguage USEnglish>\n\ - <FLocked No>\n\ - <FSeparation 0>\n\ - <FColor `Black'>\n\ - > # end of PgfFont\n\ - <Pgf\n\ - <PgfAlignment Center>\n\ - <PgfFont \n\ - <FTag `'>\n\ - <FFamily `Times'>\n\ - <FVar `Regular'>\n\ - <FWeight `Regular'>\n\ - <FAngle `Regular'>\n\ - <FPostScriptName `Times-Roman'>\n\ - <FEncoding `FrameRoman'>\n\ - <FSize 11.0 pt>\n\ - <FUnderlining FNoUnderlining>\n\ - <FOverline No>\n\ - <FStrike No>\n\ - <FChangeBar No>\n\ - <FOutline No>\n\ - <FShadow No>\n\ - <FPairKern Yes>\n\ - <FTsume No>\n\ - <FCase FAsTyped>\n\ - <FPosition FNormal>\n\ - <FDX 0.0%>\n\ - <FDY 0.0%>\n\ - <FDW 0.0%>\n\ - <FStretch 100.0%>\n\ - <FLanguage USEnglish>\n\ - <FLocked No>\n\ - <FSeparation 0>\n\ - <FColor `Black'>\n\ - > # end of PgfFont\n\ - >\n\ - <ParaLine\n\ - <String `Event'>\n\ - > # end of ParaLine\n\ - > # end of Para\n\ - > # end of CellContent\n\ - > # end of Cell\n\ - <Cell\n\ - <CellLRuling `Medium'>\n\ - <CellBRuling `Medium'>\n\ - <CellRRuling `Medium'>\n\ - <CellTRuling `Medium'>\n\ - <CellContent\n\ - <Para\n\ - <PgfTag `CellHeading'>\n\ - <ParaLine\n\ - <String `Description'>\n\ - > # end of ParaLine\n\ - > # end of Para\n\ - > # end of CellContent\n\ - > # end of Cell\n\ - > # end of Row\n\ - > # end of TblH\n\ -\n\ - <TblBody\n\ -"; - - const string row_before_event = -" <Row\n\ - <RowMaxHeight 14.0\">\n\ - <RowHeight 0.22222\">\n\ - <Cell\n\ - <CellContent\n\ - <Para\n\ - <PgfTag `CellBody'>\n\ - <Pgf\n\ - <PgfAlignment Center>\n\ - <PgfFont \n\ - <FTag `'>\n\ - <FFamily `Times'>\n\ - <FVar `Regular'>\n\ - <FWeight `Regular'>\n\ - <FAngle `Regular'>\n\ - <FPostScriptName `Times-Roman'>\n\ - <FEncoding `FrameRoman'>\n\ - <FSize 11.0 pt>\n\ - <FUnderlining FNoUnderlining>\n\ - <FOverline No>\n\ - <FStrike No>\n\ - <FChangeBar No>\n\ - <FOutline No>\n\ - <FShadow No>\n\ - <FPairKern Yes>\n\ - <FTsume No>\n\ - <FCase FAsTyped>\n\ - <FPosition FNormal>\n\ - <FDX 0.0%>\n\ - <FDY 0.0%>\n\ - <FDW 0.0%>\n\ - <FStretch 100.0%>\n\ - <FLanguage USEnglish>\n\ - <FLocked No>\n\ - <FSeparation 0>\n\ - <FColor `Black'>\n\ - > # end of PgfFont\n\ - >\n\ - <ParaLine\n\ - <String `"; - - const string row_between_event_desc = - "'>\n\ - > # end of ParaLine\n\ - > # end of Para\n\ - > # end of CellContent\n\ - > # end of Cell\n\ - <Cell\n\ - <CellContent\n\ - <Para\n\ - <PgfTag `CellBody'>\n\ - <ParaLine\n\ - <String `"; - - const string row_after_desc = - "'>\n\ - > # end of ParaLine\n\ - > # end of Para\n\ - > # end of CellContent\n\ - > # end of Cell\n\ - > # end of Row\n\ -"; - - const string mif_epilog = -" > # end of TblBody\n\ - > # end of Tbl\n\ -> # end of Tbls\n\ -\n\ - <Para\n\ - <ParaLine\n\ - <ATbl 1>\n\ - > # end of ParaLine\n\ - > # end of Para\n\ -\n\ -# End of MIFFile\n\ -"; - - out << mif_prolog1; - out << formatShorthand( sm.getShorthand() ); - out << " events"; - out << mif_prolog2; - - for( int i = 0; i < sm.numEvents(); i++ ) - { - out << row_before_event; - out << formatShorthand( sm.getEvent( i ).getShorthand() ); - out << row_between_event_desc; - out << sm.getEvent( i ).getDescription(); - out << row_after_desc; - } - - out << mif_epilog; -} - - -void printActionTableMIF(const StateMachine& sm, ostream& out) -{ - const string mif_prolog1 = -"<MIFFile 5.50> # Generated by Multifacet MIF Mungers Inc\n\ -<Tbls\n\ - <Tbl\n\ - <TblID 1>\n\ - <TblTag `Format A'>\n\ - <TblFormat\n\ -\n\ - <TblAlignment Center>\n\ -\n\ - # <TblXColumnNum 0>\n\ - <TblXColumnRuling `Medium'>\n\ -\n\ - <TblLRuling `Medium'>\n\ - <TblRRuling `Medium'>\n\ - <TblTRuling `Medium'>\n\ - <TblBRuling `Medium'>\n\ -\n\ - <TblColumn\n\ - <TblColumnNum 0>\n\ - <TblColumnWidth 0.51\">\n\ - <TblColumnH\n\ - <PgfTag `CellHeading'>\n\ - > # end of TblColumnH\n\ - <TblColumnBody\n\ - <PgfTag `CellBody'>\n\ - > # end of TblColumnBody\n\ - <TblColumnF\n\ - <PgfTag `CellHeading'>\n\ - > # end of TblColumnF\n\ - > # end of TblColumn\n\ - <TblColumn\n\ - <TblColumnNum 1>\n\ - <TblColumnWidth 0.51\">\n\ - <TblColumnH\n\ - <PgfTag `CellHeading'>\n\ - > # end of TblColumnH\n\ - <TblColumnBody\n\ - <PgfTag `CellBody'>\n\ - > # end of TblColumnBody\n\ - <TblColumnF\n\ - <PgfTag `CellHeading'>\n\ - > # end of TblColumnF\n\ - > # end of TblColumn\n\ - > # end of TblFormat\n\ -\n\ - <TblNumColumns 2>\n\ - <TblColumnWidth 0.51\">\n\ - <TblColumnWidth 6.00\">\n\ - <TblTitle\n\ - <TblTitleContent\n\ - <Para\n\ - <PgfTag `TableTitle'>\n\ - <Pgf\n\ - <PgfAlignment Center>\n\ - <PgfFont \n\ - <FTag `'>\n\ - <FFamily `Times'>\n\ - <FVar `Regular'>\n\ - <FWeight `Regular'>\n\ - <FAngle `Regular'>\n\ - <FPostScriptName `Times-Roman'>\n\ - <FEncoding `FrameRoman'>\n\ - <FSize 11.0 pt>\n\ - <FUnderlining FNoUnderlining>\n\ - <FOverline No>\n\ - <FStrike No>\n\ - <FChangeBar No>\n\ - <FOutline No>\n\ - <FShadow No>\n\ - <FPairKern Yes>\n\ - <FTsume No>\n\ - <FCase FAsTyped>\n\ - <FPosition FNormal>\n\ - <FDX 0.0%>\n\ - <FDY 0.0%>\n\ - <FDW 0.0%>\n\ - <FStretch 100.0%>\n\ - <FLanguage USEnglish>\n\ - <FLocked No>\n\ - <FSeparation 0>\n\ - <FColor `Black'>\n\ - > # end of PgfFont\n\ - > # end of Pgf\n\ - <PgfNumString `TABLE 1. '>\n\ - <ParaLine\n\ - <Marker\n\ - <MType 9>\n\ - <MTypeName `Cross-Ref'>\n\ - <MCurrPage `1'>\n\ - > # end of Marker\n\ - <String `"; - const string mif_prolog2 = -"'>\n\ - > # end of ParaLine\n\ - > # end of Para\n\ - > # end of TblTitleContent\n\ - > # end of TblTitle\n\ -\n\ - <TblH\n\ - <Row\n\ - <RowMaxHeight 14.0\">\n\ - <RowHeight 0.44444\">\n\ - <Cell\n\ - <CellLRuling `Medium'>\n\ - <CellBRuling `Medium'>\n\ - <CellRRuling `Medium'>\n\ - <CellTRuling `Medium'>\n\ - <CellContent\n\ - <Para\n\ - <PgfTag `CellHeading'>\n\ - <Pgf\n\ - <PgfAlignment Center>\n\ - <PgfFont \n\ - <FTag `'>\n\ - <FFamily `Times'>\n\ - <FVar `Regular'>\n\ - <FWeight `Regular'>\n\ - <FAngle `Regular'>\n\ - <FPostScriptName `Times-Roman'>\n\ - <FEncoding `FrameRoman'>\n\ - <FSize 11.0 pt>\n\ - <FUnderlining FNoUnderlining>\n\ - <FOverline No>\n\ - <FStrike No>\n\ - <FChangeBar No>\n\ - <FOutline No>\n\ - <FShadow No>\n\ - <FPairKern Yes>\n\ - <FTsume No>\n\ - <FCase FAsTyped>\n\ - <FPosition FNormal>\n\ - <FDX 0.0%>\n\ - <FDY 0.0%>\n\ - <FDW 0.0%>\n\ - <FStretch 100.0%>\n\ - <FLanguage USEnglish>\n\ - <FLocked No>\n\ - <FSeparation 0>\n\ - <FColor `Black'>\n\ - > # end of PgfFont\n\ - >\n\ - <ParaLine\n\ - <String `Action'>\n\ - > # end of ParaLine\n\ - > # end of Para\n\ - > # end of CellContent\n\ - > # end of Cell\n\ - <Cell\n\ - <CellLRuling `Medium'>\n\ - <CellBRuling `Medium'>\n\ - <CellRRuling `Medium'>\n\ - <CellTRuling `Medium'>\n\ - <CellContent\n\ - <Para\n\ - <PgfTag `CellHeading'>\n\ - <ParaLine\n\ - <String `Description'>\n\ - > # end of ParaLine\n\ - > # end of Para\n\ - > # end of CellContent\n\ - > # end of Cell\n\ - > # end of Row\n\ - > # end of TblH\n\ -\n\ - <TblBody\n\ -"; - - const string row_before_action = -" <Row\n\ - <RowMaxHeight 14.0\">\n\ - <RowHeight 0.22222\">\n\ - <Cell\n\ - <CellContent\n\ - <Para\n\ - <PgfTag `CellBody'>\n\ - <Pgf\n\ - <PgfAlignment Center>\n\ - <PgfFont \n\ - <FTag `'>\n\ - <FFamily `Times'>\n\ - <FVar `Regular'>\n\ - <FWeight `Regular'>\n\ - <FAngle `Regular'>\n\ - <FPostScriptName `Times-Roman'>\n\ - <FEncoding `FrameRoman'>\n\ - <FSize 11.0 pt>\n\ - <FUnderlining FNoUnderlining>\n\ - <FOverline No>\n\ - <FStrike No>\n\ - <FChangeBar No>\n\ - <FOutline No>\n\ - <FShadow No>\n\ - <FPairKern Yes>\n\ - <FTsume No>\n\ - <FCase FAsTyped>\n\ - <FPosition FNormal>\n\ - <FDX 0.0%>\n\ - <FDY 0.0%>\n\ - <FDW 0.0%>\n\ - <FStretch 100.0%>\n\ - <FLanguage USEnglish>\n\ - <FLocked No>\n\ - <FSeparation 0>\n\ - <FColor `Black'>\n\ - > # end of PgfFont\n\ - >\n\ - <ParaLine\n\ - <String `"; - - const string row_between_action_desc = - "'>\n\ - > # end of ParaLine\n\ - > # end of Para\n\ - > # end of CellContent\n\ - > # end of Cell\n\ - <Cell\n\ - <CellContent\n\ - <Para\n\ - <PgfTag `CellBody'>\n\ - <ParaLine\n\ - <String `"; - - const string row_after_desc = - "'>\n\ - > # end of ParaLine\n\ - > # end of Para\n\ - > # end of CellContent\n\ - > # end of Cell\n\ - > # end of Row\n\ -"; - - const string mif_epilog = -" > # end of TblBody\n\ - > # end of Tbl\n\ -> # end of Tbls\n\ -\n\ - <Para\n\ - <ParaLine\n\ - <ATbl 1>\n\ - > # end of ParaLine\n\ - > # end of Para\n\ -\n\ -# End of MIFFile\n\ -"; - - out << mif_prolog1; - out << formatShorthand( sm.getShorthand() ); - out << " actions"; - out << mif_prolog2; - - for( int i = 0; i < sm.numActions(); i++ ) - { - out << row_before_action; - out << formatShorthand( sm.getAction( i ).getShorthand() ); - out << row_between_action_desc; - out << sm.getAction( i ).getDescription(); - out << row_after_desc; - } - - out << mif_epilog; -} - - -void printTransitionTableMIF(const StateMachine& sm, ostream& out) -{ - const string mif_prolog = -"<MIFFile 5.50> # Generated by Multifacet MIF Mungers Inc\n\ -<Tbls\n\ - <Tbl\n\ - <TblID 1>\n\ - <TblTag `Format A'>\n\ - <TblFormat\n\ -\n\ - <TblAlignment Center>\n\ -\n\ - # <TblXColumnNum 0>\n\ - <TblXColumnRuling `Medium'>\n\ -\n\ - <TblLRuling `Medium'>\n\ - <TblRRuling `Medium'>\n\ - <TblTRuling `Medium'>\n\ - <TblBRuling `Medium'>\n\ - \n\ -"; - - const string tbl_fmt_before_col_num = -" <TblColumn\n\ - <TblColumnNum "; - - const string tbl_fmt_after_col_num = - ">\n\ - <TblColumnWidth 0.51\">\n\ - <TblColumnH\n\ - <PgfTag `CellHeading'>\n\ - > # end of TblColumnH\n\ - <TblColumnBody\n\ - <PgfTag `CellBody'>\n\ - > # end of TblColumnBody\n\ - <TblColumnF\n\ - <PgfTag `CellHeading'>\n\ - > # end of TblColumnF\n\ - > # end of TblColumn\n\ -"; - - const string tbl_fmt_before_num_cols = -" > # end of TblFormat\n\ -\n\ - <TblNumColumns "; - - const string tbl_fmt_each_col_width_begin = - ">\n\ - <TblColumnWidth "; - - const string tbl_fmt_each_col_width_end = "\""; - - const string tbl_before_first_header1 = - ">\n\ - <TblTitle\n\ - <TblTitleContent\n\ - <Para\n\ - <PgfTag `TableTitle'>\n\ - <Pgf\n\ - <PgfAlignment Center>\n\ - <PgfFont \n\ - <FTag `'>\n\ - <FFamily `Times'>\n\ - <FVar `Regular'>\n\ - <FWeight `Regular'>\n\ - <FAngle `Regular'>\n\ - <FPostScriptName `Times-Roman'>\n\ - <FEncoding `FrameRoman'>\n\ - <FSize 11.0 pt>\n\ - <FUnderlining FNoUnderlining>\n\ - <FOverline No>\n\ - <FStrike No>\n\ - <FChangeBar No>\n\ - <FOutline No>\n\ - <FShadow No>\n\ - <FPairKern Yes>\n\ - <FTsume No>\n\ - <FCase FAsTyped>\n\ - <FPosition FNormal>\n\ - <FDX 0.0%>\n\ - <FDY 0.0%>\n\ - <FDW 0.0%>\n\ - <FStretch 100.0%>\n\ - <FLanguage USEnglish>\n\ - <FLocked No>\n\ - <FSeparation 0>\n\ - <FColor `Black'>\n\ - > # end of PgfFont\n\ - > # end of Pgf\n\ - <PgfNumString `TABLE 1. '>\n\ - <ParaLine\n\ - <Marker\n\ - <MType 9>\n\ - <MTypeName `Cross-Ref'>\n\ - <MCurrPage `1'>\n\ - > # end of Marker\n\ - <String `"; - - const string tbl_before_first_header2 = - "'>\n\ - > # end of ParaLine\n\ - > # end of Para\n\ - > # end of TblTitleContent\n\ - > # end of TblTitle\n\ -\n\ - <TblH\n\ - <Row\n\ - <RowMaxHeight 14.0\">\n\ - <RowHeight 0.44444\">"; - - const string tbl_before_each_header = -" <Cell\n\ - <CellLRuling `Medium'>\n\ - <CellBRuling `Medium'>\n\ - <CellRRuling `Medium'>\n\ - <CellTRuling `Medium'>\n\ - <CellContent\n\ - <Para\n\ - <PgfTag `CellHeading'>\n\ - <Pgf\n\ - <PgfAlignment Center>\n\ - <PgfFont \n\ - <FTag `'>\n\ - <FFamily `Times'>\n\ - <FVar `Regular'>\n\ - <FWeight `Regular'>\n\ - <FAngle `Regular'>\n\ - <FPostScriptName `Times-Roman'>\n\ - <FEncoding `FrameRoman'>\n\ - <FSize 11.0 pt>\n\ - <FUnderlining FNoUnderlining>\n\ - <FOverline No>\n\ - <FStrike No>\n\ - <FChangeBar No>\n\ - <FOutline No>\n\ - <FShadow No>\n\ - <FPairKern Yes>\n\ - <FTsume No>\n\ - <FCase FAsTyped>\n\ - <FPosition FNormal>\n\ - <FDX 0.0%>\n\ - <FDY 0.0%>\n\ - <FDW 0.0%>\n\ - <FStretch 100.0%>\n\ - <FLanguage USEnglish>\n\ - <FLocked No>\n\ - <FSeparation 0>\n\ - <FColor `Black'>\n\ - > # end of PgfFont\n\ - >\n\ - <ParaLine\n\ - <String `"; - - const string tbl_before_each_rot_header = -" <Cell\n\ - <CellLRuling `Medium'>\n\ - <CellBRuling `Medium'>\n\ - <CellRRuling `Medium'>\n\ - <CellTRuling `Medium'>\n\ - <CellAngle 270>\n\ - <CellContent\n\ - <Para\n\ - <PgfTag `CellHeading'>\n\ - <ParaLine\n\ - <String `"; - - const string tbl_after_each_header = - "'>\n\ - > # end of ParaLine\n\ - > # end of Para\n\ - > # end of CellContent\n\ - > # end of Cell\n\ -"; - - const string before_first_row = -" > # end of Row\n\ - > # end of TblH\n\ -\n\ - <TblBody\n\ -"; - - const string row_before_first_cell = -" <Row\n\ - <RowMaxHeight 14.0\">\n\ - <RowHeight 0.22222\">"; - - const string row_cell_before_ruling = -" <Cell\n\ -"; - - const string row_cell_before_contents = -" <CellContent\n\ - <Para\n\ - <PgfTag `CellBody'>\n\ - <Pgf\n\ - <PgfAlignment Center>\n\ - <PgfFont \n\ - <FTag `'>\n\ - <FFamily `Times'>\n\ - <FVar `Regular'>\n\ - <FWeight `Regular'>\n\ - <FAngle `Regular'>\n\ - <FPostScriptName `Times-Roman'>\n\ - <FEncoding `FrameRoman'>\n\ - <FSize 11.0 pt>\n\ - <FUnderlining FNoUnderlining>\n\ - <FOverline No>\n\ - <FStrike No>\n\ - <FChangeBar No>\n\ - <FOutline No>\n\ - <FShadow No>\n\ - <FPairKern Yes>\n\ - <FTsume No>\n\ - <FCase FAsTyped>\n\ - <FPosition FNormal>\n\ - <FDX 0.0%>\n\ - <FDY 0.0%>\n\ - <FDW 0.0%>\n\ - <FStretch 100.0%>\n\ - <FLanguage USEnglish>\n\ - <FLocked No>\n\ - <FSeparation 0>\n\ - <FColor `Black'>\n\ - > # end of PgfFont\n\ - >\n\ - <ParaLine\n\ - <String `"; - - const string row_cell_after_contents = - "'>\n\ - > # end of ParaLine\n\ - > # end of Para\n\ - > # end of CellContent\n\ - > # end of Cell\n\ -"; - - const string row_empty_cell = -" <CellFill 5>\n\ - <CellColor `Cyan'>\n\ - <CellContent\n\ - <Para\n\ - <PgfTag `CellBody'>\n\ - <ParaLine\n\ - <String `'>\n\ - > # end of ParaLine\n\ - > # end of Para\n\ - > # end of CellContent\n\ - > # end of Cell\n\ -"; - - const string row_after_last_cell = -" > # end of Row\n\ -"; - - - const string mif_epilog = -" > # end of TblBody\n\ - > # end of Tbl\n\ -> # end of Tbls\n\ -\n\ - <Para\n\ - <ParaLine\n\ - <ATbl 1>\n\ - > # end of ParaLine\n\ - > # end of Para\n\ -\n\ -# End of MIFFile\n\ -"; - - int i, j, num_rows, num_cols; - string row_ruling; - string col_ruling; - - num_rows = sm.numStates(); - num_cols = sm.numEvents() + 1; - - // -- Prolog - out << mif_prolog; - - // -- Table format (for each column) - for( i = 0; i < num_cols; i++ ) - { - out << tbl_fmt_before_col_num; - out << i; - out << tbl_fmt_after_col_num; - } - - // -- Spell out width of each column - - // -- FIXME: make following constants into parameters - const float total_table_width = 7.5; // -- Total page width = 7.5" (portrait mode) - const float min_col_width = 0.35; // -- Min col width (for legibility) - const float max_col_width = 0.75; // -- Max col width (for aesthetics) - float column_width; - - // -- Calculate column width and clamp it within a range - column_width = total_table_width / num_cols; - column_width = ((column_width < min_col_width) - ? min_col_width - : ((column_width > max_col_width) - ? max_col_width - : column_width)); - - out << tbl_fmt_before_num_cols; - out << num_cols; - for( i = 0; i < num_cols; i++ ) - { - out << tbl_fmt_each_col_width_begin << column_width << tbl_fmt_each_col_width_end; - } - - // -- Column headers - out << tbl_before_first_header1; - out << formatShorthand( sm.getShorthand() ); - out << " transitions"; - out << tbl_before_first_header2; - - out << tbl_before_each_header; - out << "State"; - out << tbl_after_each_header; - - for( i = 0; i < sm.numEvents(); i++ ) - { - out << tbl_before_each_rot_header; - out << formatShorthand( sm.getEvent(i).getShorthand() ); - out << tbl_after_each_header; - } - out << before_first_row; - - - // -- Body of table - for( i = 0; i < num_rows; i++ ) - { - // -- Each row - out << row_before_first_cell; - - // -- Figure out ruling - if (sm.getState(i).existPair("format")) { - row_ruling = formatCellRuling( sm.getState(i).lookupPair("format")); - } else { - row_ruling = ""; - } - - // -- First column = state - out << row_cell_before_ruling; - out << row_ruling; - out << row_cell_before_contents; - out << formatShorthand( sm.getState(i).getShorthand() ); - out << row_cell_after_contents; - - // -- One column for each event - for( j = 0; j < sm.numEvents(); j++ ) - { - const Transition* trans_ptr = sm.getTransPtr( i, j ); - - // -- Figure out ruling - if (sm.getEvent(j).existPair("format")) { - col_ruling = formatCellRuling(sm.getEvent(j).lookupPair("format")); - } else { - col_ruling = ""; - } - - out << row_cell_before_ruling; - out << row_ruling; - out << col_ruling; - - if( trans_ptr != NULL ) - { - string actions; - string nextState; - - // -- Get the actions - actions = formatShorthand( trans_ptr->getActionShorthands() ); - - // -- Get the next state - // FIXME: should compare index, not the string - if (trans_ptr->getNextStateShorthand() != - sm.getState(i).getShorthand() ) - { - nextState = formatShorthand( trans_ptr->getNextStateShorthand() ); - } else - { - nextState = ""; - } - - // -- Print out "actions/next-state" - out << row_cell_before_contents; - out << actions; - if ((nextState.length() != 0) && (actions.length() != 0)) { - out << "/"; - } - out << nextState; - out << row_cell_after_contents; - } - else - { - out << row_empty_cell; - } - - } - - out << row_after_last_cell; - } - - // -- Epilog - out << mif_epilog; - -} -/* -void printTBETableMIF(const StateMachine& sm, const Vector<Field>& fields, ostream& out) -{ - const string mif_prolog1 = -"<MIFFile 5.50> # Generated by Multifacet MIF Mungers Inc\n\ -<Tbls\n\ - <Tbl\n\ - <TblID 1>\n\ - <TblTag `Format A'>\n\ - <TblFormat\n\ -\n\ - <TblAlignment Center>\n\ -\n\ - # # <TblXColumnNum 0>\n\ - <TblXColumnRuling `Medium'>\n\ -\n\ - <TblLRuling `Medium'>\n\ - <TblRRuling `Medium'>\n\ - <TblTRuling `Medium'>\n\ - <TblBRuling `Medium'>\n\ -\n\ - <TblColumn\n\ - <TblColumnNum 0>\n\ - <TblColumnWidth 0.51\">\n\ - <TblColumnH\n\ - <PgfTag `CellHeading'>\n\ - > # end of TblColumnH\n\ - <TblColumnBody\n\ - <PgfTag `CellBody'>\n\ - > # end of TblColumnBody\n\ - <TblColumnF\n\ - <PgfTag `CellHeading'>\n\ - > # end of TblColumnF\n\ - > # end of TblColumn\n\ - <TblColumn\n\ - <TblColumnNum 1>\n\ - <TblColumnWidth 0.51\">\n\ - <TblColumnH\n\ - <PgfTag `CellHeading'>\n\ - > # end of TblColumnH\n\ - <TblColumnBody\n\ - <PgfTag `CellBody'>\n\ - > # end of TblColumnBody\n\ - <TblColumnF\n\ - <PgfTag `CellHeading'>\n\ - > # end of TblColumnF\n\ - > # end of TblColumn\n\ - > # end of TblFormat\n\ -\n\ - <TblNumColumns 2>\n\ - <TblColumnWidth 0.51\">\n\ - <TblColumnWidth 6.00\">\n\ - <TblTitle\n\ - <TblTitleContent\n\ - <Para\n\ - <PgfTag `TableTitle'>\n\ - <Pgf\n\ - <PgfAlignment Center>\n\ - <PgfFont \n\ - <FTag `'>\n\ - <FFamily `Times'>\n\ - <FVar `Regular'>\n\ - <FWeight `Regular'>\n\ - <FAngle `Regular'>\n\ - <FPostScriptName `Times-Roman'>\n\ - <FEncoding `FrameRoman'>\n\ - <FSize 11.0 pt>\n\ - <FUnderlining FNoUnderlining>\n\ - <FOverline No>\n\ - <FStrike No>\n\ - <FChangeBar No>\n\ - <FOutline No>\n\ - <FShadow No>\n\ - <FPairKern Yes>\n\ - <FTsume No>\n\ - <FCase FAsTyped>\n\ - <FPosition FNormal>\n\ - <FDX 0.0%>\n\ - <FDY 0.0%>\n\ - <FDW 0.0%>\n\ - <FStretch 100.0%>\n\ - <FLanguage USEnglish>\n\ - <FLocked No>\n\ - <FSeparation 0>\n\ - <FColor `Black'>\n\ - > # end of PgfFont\n\ - > # end of Pgf\n\ - <PgfNumString `TABLE 1. '>\n\ - <ParaLine\n\ - <Marker\n\ - <MType 9>\n\ - <MTypeName `Cross-Ref'>\n\ - <MCurrPage `1'>\n\ - > # end of Marker\n\ - <String `"; - - const string mif_prolog2 = - "'>\n\ - > # end of ParaLine\n\ - > # end of Para\n\ - > # end of TblTitleContent\n\ - > # end of TblTitle\n\ -\n\ - <TblH\n\ - <Row\n\ - <RowMaxHeight 14.0\">\n\ - <RowHeight 0.44444\">\n\ - <Cell\n\ - <CellLRuling `Medium'>\n\ - <CellBRuling `Medium'>\n\ - <CellRRuling `Medium'>\n\ - <CellTRuling `Medium'>\n\ - <CellContent\n\ - <Para\n\ - <PgfTag `CellHeading'>\n\ - <Pgf\n\ - <PgfAlignment Center>\n\ - <PgfFont \n\ - <FTag `'>\n\ - <FFamily `Times'>\n\ - <FVar `Regular'>\n\ - <FWeight `Regular'>\n\ - <FAngle `Regular'>\n\ - <FPostScriptName `Times-Roman'>\n\ - <FEncoding `FrameRoman'>\n\ - <FSize 11.0 pt>\n\ - <FUnderlining FNoUnderlining>\n\ - <FOverline No>\n\ - <FStrike No>\n\ - <FChangeBar No>\n\ - <FOutline No>\n\ - <FShadow No>\n\ - <FPairKern Yes>\n\ - <FTsume No>\n\ - <FCase FAsTyped>\n\ - <FPosition FNormal>\n\ - <FDX 0.0%>\n\ - <FDY 0.0%>\n\ - <FDW 0.0%>\n\ - <FStretch 100.0%>\n\ - <FLanguage USEnglish>\n\ - <FLocked No>\n\ - <FSeparation 0>\n\ - <FColor `Black'>\n\ - > # end of PgfFont\n\ - >\n\ - <ParaLine\n\ - <String `Field'>\n\ - > # end of ParaLine\n\ - > # end of Para\n\ - > # end of CellContent\n\ - > # end of Cell\n\ - <Cell\n\ - <CellLRuling `Medium'>\n\ - <CellBRuling `Medium'>\n\ - <CellRRuling `Medium'>\n\ - <CellTRuling `Medium'>\n\ - <CellContent\n\ - <Para\n\ - <PgfTag `CellHeading'>\n\ - <PgfFont \n\ - <FTag `'>\n\ - <FFamily `Times'>\n\ - <FVar `Regular'>\n\ - <FWeight `Regular'>\n\ - <FAngle `Regular'>\n\ - <FPostScriptName `Times-Roman'>\n\ - <FEncoding `FrameRoman'>\n\ - <FSize 11.0 pt>\n\ - <FUnderlining FNoUnderlining>\n\ - <FOverline No>\n\ - <FStrike No>\n\ - <FChangeBar No>\n\ - <FOutline No>\n\ - <FShadow No>\n\ - <FPairKern Yes>\n\ - <FTsume No>\n\ - <FCase FAsTyped>\n\ - <FPosition FNormal>\n\ - <FDX 0.0%>\n\ - <FDY 0.0%>\n\ - <FDW 0.0%>\n\ - <FStretch 100.0%>\n\ - <FLanguage USEnglish>\n\ - <FLocked No>\n\ - <FSeparation 0>\n\ - <FColor `Black'>\n\ - > # end of PgfFont\n\ - <ParaLine\n\ - <String `Description'>\n\ - > # end of ParaLine\n\ - > # end of Para\n\ - > # end of CellContent\n\ - > # end of Cell\n\ - > # end of Row\n\ - > # end of TblH\n\ -\n\ - <TblBody\n\ -"; - - const string row_before_state = -" <Row\n\ - <RowMaxHeight 14.0\">\n\ - <RowHeight 0.22222\">\n\ - <Cell\n\ - <CellContent\n\ - <Para\n\ - <PgfTag `CellBody'>\n\ - <Pgf\n\ - <PgfAlignment Center>\n\ - <PgfFont \n\ - <FTag `'>\n\ - <FFamily `Times'>\n\ - <FVar `Regular'>\n\ - <FWeight `Regular'>\n\ - <FAngle `Regular'>\n\ - <FPostScriptName `Times-Roman'>\n\ - <FEncoding `FrameRoman'>\n\ - <FSize 11.0 pt>\n\ - <FUnderlining FNoUnderlining>\n\ - <FOverline No>\n\ - <FStrike No>\n\ - <FChangeBar No>\n\ - <FOutline No>\n\ - <FShadow No>\n\ - <FPairKern Yes>\n\ - <FTsume No>\n\ - <FCase FAsTyped>\n\ - <FPosition FNormal>\n\ - <FDX 0.0%>\n\ - <FDY 0.0%>\n\ - <FDW 0.0%>\n\ - <FStretch 100.0%>\n\ - <FLanguage USEnglish>\n\ - <FLocked No>\n\ - <FSeparation 0>\n\ - <FColor `Black'>\n\ - > # end of PgfFont\n\ - >\n\ - <ParaLine\n\ - <String `"; - - const string row_between_state_desc = - "'>\n\ - > # end of ParaLine\n\ - > # end of Para\n\ - > # end of CellContent\n\ - > # end of Cell\n\ - <Cell\n\ - <CellContent\n\ - <Para\n\ - <PgfTag `CellBody'>\n\ - <ParaLine\n\ - <String `"; - - const string row_after_desc = - "'>\n\ - > # end of ParaLine\n\ - > # end of Para\n\ - > # end of CellContent\n\ - > # end of Cell\n\ - > # end of Row\n\ -"; - - const string mif_epilog = -" > # end of TblBody\n\ - > # end of Tbl\n\ -> # end of Tbls\n\ -\n\ - <Para\n\ - <ParaLine\n\ - <ATbl 1>\n\ - > # end of ParaLine\n\ - > # end of Para\n\ -\n\ -# End of MIFFile\n\ -"; - - out << mif_prolog1; - out << sm.getShorthand(); - out << " TBE"; - out << mif_prolog2; - - for( int i = 0; i < fields.size(); i++ ) { - out << row_before_state; - out << formatShorthand(fields[i].getShorthand()); - out << row_between_state_desc; - out << fields[i].getDescription(); - out << row_after_desc; - } - - out << mif_epilog; -} -*/ -// -- -// -- Helper function to do some shorthand formatting (kludge before we -// -- get the tuple attributes into the state machine language. -// -- Current convention: -// -- - each `_' indicates a toggle between normal mode and superscript -// -- - each escaped (using `\') character indicates a letter formatted -// -- using the Symbol character set. \a = alpha, \b = beta, \c = chi etc. -// -- See the FrameMaker character sets manual in the Online Manuals. -// -- - a `!' indicates extra stuff at the end which can be ignored (used -// -- for determining cell ruling and so on) -// -- -string formatShorthand(const string shorthand) -{ - string munged_shorthand = ""; - bool mode_is_normal = true; - const string mif_superscript = "'> <Font <FPosition FSuperscript> <FLocked No> > <String `"; - const string mif_normal = "'> <Font <FPosition FNormal> <FLocked No> > <String `"; - const string mif_symbol = "'> <Font <FFamily `Symbol'> <FPostScriptName `Symbol'> <FEncoding `FrameRoman'> <FLocked No> > <String `"; - const string mif_times = "'> <Font <FFamily `Times'> <FPostScriptName `Times-Roman'> <FEncoding `FrameRoman'> <FLocked No> > <String `"; - - - // -- Walk over the string, processing superscript directives - for( unsigned int i = 0; i < shorthand.length(); i++ ) - { - if( shorthand[i] == '!' ) - { - // -- Reached logical end of shorthand name - break; - } - else if( shorthand[i] == '^' ) - { - // -- Process super/subscript formatting - - mode_is_normal = !mode_is_normal; - if( mode_is_normal ) - { - // -- Back to normal mode - munged_shorthand += mif_normal; - } - else - { - // -- Going to superscript mode - munged_shorthand += mif_superscript; - } - - } - else if( shorthand[i] == '\\' ) - { - // -- Process Symbol character set - if( (i + 1) < shorthand.length() ) - { - i++; // -- Proceed to next char. Yes I know that changing the loop var is ugly! - munged_shorthand += mif_symbol; - munged_shorthand += shorthand[i]; - munged_shorthand += mif_times; - } - else - { - // -- FIXME: Add line number info later - cerr << "Encountered a `\\` without anything following it!" << endl; - exit( -1 ); - } - - } - else - { - // -- Pass on un-munged - munged_shorthand += shorthand[i]; - } - - } // -- end for all characters in shorthand - - // -- Do any other munging - - // -- Return the formatted shorthand name - return munged_shorthand; -} - - -// -- -// -- Helper function to figure out where to put rules in the table (kludge before we -// -- get the tuple attributes into the shorthand machine language. -// -- Current convention: -// -- - a `!' in the shorthand indicates the beginning of ruling information -// -- - `b' => bottom of this row is ruled -// -- - `r' => right of this column is ruled -// -- -string formatCellRuling( const string shorthand) -{ - for( unsigned int i = 0; i < shorthand.length(); i++ ) - { - if( shorthand[i] == '!' ) - { - // -- OK, found beginning of ruling information - for( unsigned int j = i+1; j < shorthand.length(); j++ ) - { - if( shorthand[j] == 'b') - { - // -- Rule the bottom - return "<CellBRuling `Medium'>\n"; - } - else if( shorthand[j] == 'r') - { - // -- Rule the bottom - return "<CellRRuling `Medium'>\n"; - } - - } - - // -- No ruling directives recognized, return default ruling - return ""; - } - - } - - // -- No ruling information found, return default ruling - return ""; -} diff --git a/src/mem/slicc/generator/mif_gen.hh b/src/mem/slicc/generator/mif_gen.hh deleted file mode 100644 index 6da75f748..000000000 --- a/src/mem/slicc/generator/mif_gen.hh +++ /dev/null @@ -1,45 +0,0 @@ - -/* - * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer; - * redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution; - * neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/* - * $Id: mif_gen.hh,v 3.1 2001/12/12 01:00:35 milo Exp $ - * - */ - -#ifndef MIF_GEN_H -#define MIF_GEN_H - -#include "mem/slicc/symbols/StateMachine.hh" - -void printStateTableMIF(const StateMachine& sm, ostream& out); -void printEventTableMIF(const StateMachine& sm, ostream& out); -void printActionTableMIF(const StateMachine& sm, ostream& out); -void printTransitionTableMIF(const StateMachine& sm, ostream& out); - -#endif //MIF_GEN_H diff --git a/src/mem/slicc/main.cc b/src/mem/slicc/main.cc deleted file mode 100644 index 294925ee1..000000000 --- a/src/mem/slicc/main.cc +++ /dev/null @@ -1,246 +0,0 @@ - -/* - * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer; - * redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution; - * neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/* - * $Id$ - * - * */ - -#include "mem/slicc/main.hh" -#include "mem/slicc/symbols/StateMachine.hh" -#include "mem/slicc/generator/mif_gen.hh" -#include "mem/slicc/generator/html_gen.hh" -#include "mem/slicc/generator/fileio.hh" -#include "mem/slicc/ast/DeclListAST.hh" -#include "mem/slicc/symbols/Type.hh" -#include "mem/slicc/symbols/SymbolTable.hh" -#include "mem/slicc/symbols/Event.hh" -#include "mem/slicc/symbols/State.hh" -#include "mem/slicc/symbols/Action.hh" -#include "mem/slicc/symbols/Transition.hh" - -// -- Main conversion functions - -void printDotty(const StateMachine& sm, ostream& out); -void printTexTable(const StateMachine& sm, ostream& out); - -DeclListAST* g_decl_list_ptr; -DeclListAST* parse(string filename); - -int main(int argc, char *argv[]) -{ - cerr << "SLICC v0.3" << endl; - - if (argc < 5) { - cerr << " Usage: generator.exec <code path> <html path> <ident> <html direction> files ... " << endl; - exit(1); - } - - // The path we should place the generated code - string code_path(argv[1]); - code_path += "/"; - - // The path we should place the generated html - string html_path(argv[2]); - html_path += "/"; - - string ident(argv[3]); - - string html_generate(argv[4]); - - Vector<DeclListAST*> decl_list_vec; - - // Parse - cerr << "Parsing..." << endl; - for(int i=5; i<argc; i++) { - cerr << " " << argv[i] << endl; - DeclListAST* decl_list_ptr = parse(argv[i]); - decl_list_vec.insertAtBottom(decl_list_ptr); - } - - // Find machines - cerr << "Generator pass 1..." << endl; - int size = decl_list_vec.size(); - for(int i=0; i<size; i++) { - DeclListAST* decl_list_ptr = decl_list_vec[i]; - decl_list_ptr->findMachines(); - } - - // Generate Code - cerr << "Generator pass 2..." << endl; - for(int i=0; i<size; i++) { - DeclListAST* decl_list_ptr = decl_list_vec[i]; - decl_list_ptr->generate(); - delete decl_list_ptr; - } - - // Generate C/C++ files - cerr << "Writing C files..." << endl; - - { - // Generate the name of the protocol - ostringstream sstr; - sstr << "// Auto generated C++ code started by "<<__FILE__<<":"<<__LINE__<<endl; - sstr << endl; - sstr << "#ifndef PROTOCOL_NAME_H" << endl; - sstr << "#define PROTOCOL_NAME_H" << endl; - sstr << endl; - sstr << "const char CURRENT_PROTOCOL[] = \""; - sstr << ident << "\";\n"; - sstr << "#endif // PROTOCOL_NAME_H" << endl; - conditionally_write_file(code_path + "/protocol_name.hh", sstr); - } - - g_sym_table.writeCFiles(code_path); - - // Generate HTML files - if (html_generate == "html") { - cerr << "Writing HTML files..." << endl; - g_sym_table.writeHTMLFiles(html_path); - } else if (html_generate == "no_html") { - cerr << "No HTML files generated" << endl; - } else { - cerr << "ERROR, unidentified html direction" << endl; - } - - cerr << "Done..." << endl; - - // Generate MIF files - cerr << "Writing MIF files..." << endl; - g_sym_table.writeMIFFiles(html_path); - - cerr << "Done..." << endl; - -} - /* - if(!strcmp(argv[2], "parse")) { - // Parse only - } else if(!strcmp(argv[2], "state")) { - printStateTableMIF(s, cout); - } else if(!strcmp( argv[2], "event")) { - printEventTableMIF(s, cout); - } else if(!strcmp( argv[2], "action")) { - printActionTableMIF(s, cout); - } else if(!strcmp( argv[2], "transition")) { - printTransitionTableMIF(s, cout); - } else if(!strcmp( argv[2], "tbe")) { - for(int i=0; i<s.numTypes(); i++) { - if (s.getType(i).getIdent() == "TBE") { - printTBETableMIF(s, s.getTypeFields(i), cout); - } - } - } else if(!strcmp( argv[2], "dot")) { - printDotty(s, cout); - } else if(!strcmp( argv[2], "latex")) { - printTexTable(s, cout); - } else if (!strcmp( argv[2], "murphi")) { - printMurphi(s, cout); - } else if (!strcmp( argv[2], "html")) { - printHTML(s); - } else if(!strcmp( argv[2], "code")) { - if (argc < 4) { - cerr << "Error: Wrong number of command line parameters!" << endl; - exit(1); - } - */ - - -void printDotty(const StateMachine& sm, ostream& out) -{ - out << "digraph " << sm.getIdent() << " {" << endl; - for(int i=0; i<sm.numTransitions(); i++) { - const Transition& t = sm.getTransition(i); - // Don't print ignored transitions - if ((t.getActionShorthands() != "--") && (t.getActionShorthands() != "z")) { - // if (t.getStateShorthand() != t.getNextStateShorthand()) { - out << " " << t.getStateShorthand() << " -> "; - out << t.getNextStateShorthand() << "[label=\""; - out << t.getEventShorthand() << "/" - << t.getActionShorthands() << "\"]" << endl; - } - } - out << "}" << endl; -} - -void printTexTable(const StateMachine& sm, ostream& out) -{ - const Transition* trans_ptr; - int stateIndex, eventIndex; - string actions; - string nextState; - - out << "%& latex" << endl; - out << "\\documentclass[12pt]{article}" << endl; - out << "\\usepackage{graphics}" << endl; - out << "\\begin{document}" << endl; - // out << "{\\large" << endl; - out << "\\begin{tabular}{|l||"; - for(eventIndex=0; eventIndex < sm.numEvents(); eventIndex++) { - out << "l"; - } - out << "|} \\hline" << endl; - - for(eventIndex=0; eventIndex < sm.numEvents(); eventIndex++) { - out << " & \\rotatebox{90}{"; - out << sm.getEvent(eventIndex).getShorthand(); - out << "}"; - } - out << "\\\\ \\hline \\hline" << endl; - - for(stateIndex=0; stateIndex < sm.numStates(); stateIndex++) { - out << sm.getState(stateIndex).getShorthand(); - for(eventIndex=0; eventIndex < sm.numEvents(); eventIndex++) { - out << " & "; - trans_ptr = sm.getTransPtr(stateIndex, eventIndex); - if (trans_ptr == NULL) { - } else { - actions = trans_ptr->getActionShorthands(); - // FIXME: should compare index, not the string - if (trans_ptr->getNextStateShorthand() != - sm.getState(stateIndex).getShorthand() ) { - nextState = trans_ptr->getNextStateShorthand(); - } else { - nextState = ""; - } - - out << actions; - if ((nextState.length() != 0) && (actions.length() != 0)) { - out << "/"; - } - out << nextState; - } - } - out << "\\\\" << endl; - } - out << "\\hline" << endl; - out << "\\end{tabular}" << endl; - // out << "}" << endl; - out << "\\end{document}" << endl; -} - diff --git a/src/mem/slicc/main.hh b/src/mem/slicc/main.hh deleted file mode 100644 index a10dcca53..000000000 --- a/src/mem/slicc/main.hh +++ /dev/null @@ -1,48 +0,0 @@ - -/* - * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer; - * redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution; - * neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/* - * main.hh - * - * Description: - * - * $Id: main.hh,v 3.2 2003/03/17 01:50:01 xu Exp $ - * - * */ - -#ifndef MAIN_H -#define MAIN_H - -#include "mem/slicc/slicc_global.hh" -#include "mem/slicc/ast/DeclListAST.hh" -#include "mem/gems_common/Map.hh" - -extern DeclListAST* g_decl_list_ptr; - -#endif //MAIN_H diff --git a/src/mem/slicc/main.py b/src/mem/slicc/main.py new file mode 100644 index 000000000..f8efcc323 --- /dev/null +++ b/src/mem/slicc/main.py @@ -0,0 +1,100 @@ +# Copyright (c) 1999-2008 Mark D. Hill and David A. Wood +# Copyright (c) 2009 The Hewlett-Packard Development Company +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer; +# redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution; +# neither the name of the copyright holders nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +import os +import sys + +from slicc.parser import SLICC + +usage="%prog [options] <files> ... " +version="%prog v0.4" +brief_copyright=''' +Copyright (c) 1999-2008 Mark D. Hill and David A. Wood +Copyright (c) 2009 The Hewlett-Packard Development Company +All Rights Reserved. +''' + +def nprint(format, *args): + pass + +def eprint(format, *args): + if args: + format = format % args + + print >>sys.stderr, format + +def main(args=None): + import optparse + + parser = optparse.OptionParser(usage=usage, version=version, + description=brief_copyright) + parser.add_option("-d", "--debug", default=False, action="store_true", + help="Turn on PLY debugging") + parser.add_option("-C", "--code-path", default="generated", + help="Path where C++ code output code goes") + parser.add_option("-H", "--html-path", + help="Path where html output goes") + parser.add_option("-F", "--print-files", + help="Print files that SLICC will generate") + parser.add_option("-q", "--quiet", + help="don't print messages") + opts,files = parser.parse_args(args=args) + + if len(files) < 1: + parser.print_help() + sys.exit(2) + + output = nprint if opts.quiet else eprint + + output("SLICC v0.4") + slicc = SLICC(debug=opts.debug) + + output("Parsing...") + for filename in slicc.load(files, verbose=True): + output(" %s", filename) + + if opts.print_files: + for i in sorted(slicc.files()): + print ' %s' % i + else: + output("Generator pass 1...") + slicc.findMachines() + + output("Generator pass 2...") + slicc.generate() + + output("Generating C++ files...") + slicc.writeCodeFiles(opts.code_path) + + if opts.html_path: + nprint("Writing HTML files...") + slicc.writeHTMLFiles(opts.html_path) + + eprint("SLICC is Done.") + +if __name__ == "__main__": + main() diff --git a/src/mem/slicc/parser.py b/src/mem/slicc/parser.py new file mode 100644 index 000000000..6c3f45629 --- /dev/null +++ b/src/mem/slicc/parser.py @@ -0,0 +1,667 @@ +# Copyright (c) 2009 The Hewlett-Packard Development Company +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer; +# redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution; +# neither the name of the copyright holders nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# Authors: Nathan Binkert + +import os.path +import re +import sys + +from m5.util.grammar import Grammar, TokenError, ParseError + +import slicc.ast as ast +import slicc.util as util +from slicc.symbols import SymbolTable + +def read_slicc(sources): + if not isinstance(sources, (list,tuple)): + sources = [ sources ] + + for source in sources: + for sm_file in file(source, "r"): + sm_file = sm_file.strip() + if not sm_file: + continue + if sm_file.startswith("#"): + continue + yield sm_file + +class SLICC(Grammar): + def __init__(self, **kwargs): + super(SLICC, self).__init__(**kwargs) + self.decl_list_vec = [] + self.current_file = None + self.symtab = SymbolTable() + + def parse(self, filename): + self.current_file = filename + f = file(filename, 'r') + text = f.read() + try: + decl_list = super(SLICC, self).parse(text) + except (TokenError, ParseError), e: + sys.exit("%s: %s:%d" % (e, filename, e.token.lineno)) + self.decl_list_vec.append(decl_list) + self.current_file = None + + def _load(self, *filenames): + filenames = list(filenames) + while filenames: + f = filenames.pop(0) + if isinstance(f, (list, tuple)): + filenames[0:0] = list(f) + continue + + yield f + if f.endswith(".slicc"): + dirname,basename = os.path.split(f) + filenames[0:0] = [ os.path.join(dirname, x) \ + for x in read_slicc(f)] + else: + assert f.endswith(".sm") + self.parse(f) + + def load(self, *filenames, **kwargs): + verbose = kwargs.pop("verbose", False) + if kwargs: + raise TypeError + + gen = self._load(*filenames) + if verbose: + return gen + else: + # Run out the generator if we don't want the verbosity + for foo in gen: + pass + + def findMachines(self): + for decl_list in self.decl_list_vec: + decl_list.findMachines() + + def generate(self): + for decl_list in self.decl_list_vec: + decl_list.generate() + + def writeCodeFiles(self, code_path): + util.makeDir(code_path) + self.symtab.writeCodeFiles(code_path) + + def writeHTMLFiles(self, code_path): + util.makeDir(code_path) + self.symtab.writeHTMLFiles(code_path) + + def files(self): + f = set([ + 'ControllerFactory.cc', + 'ControllerFactory.hh', + 'MachineType.cc', + 'MachineType.hh', + 'Types.hh' ]) + + for decl_list in self.decl_list_vec: + f |= decl_list.files() + + return f + + t_ignore = '\t ' + + # C or C++ comment (ignore) + def t_c_comment(self, t): + r'/\*(.|\n)*?\*/' + t.lexer.lineno += t.value.count('\n') + + def t_cpp_comment(self, t): + r'//.*' + + # Define a rule so we can track line numbers + def t_newline(self, t): + r'\n+' + t.lexer.lineno += len(t.value) + + reserved = { + 'global' : 'GLOBAL', + 'machine' : 'MACHINE', + 'in_port' : 'IN_PORT', + 'out_port' : 'OUT_PORT', + 'action' : 'ACTION', + 'transition' : 'TRANS', + 'structure' : 'STRUCT', + 'external_type' : 'EXTERN_TYPE', + 'enumeration' : 'ENUM', + 'peek' : 'PEEK', + 'enqueue' : 'ENQUEUE', + 'copy_head' : 'COPY_HEAD', + 'check_allocate' : 'CHECK_ALLOCATE', + 'check_stop_slots' : 'CHECK_STOP_SLOTS', + 'if' : 'IF', + 'else' : 'ELSE', + 'return' : 'RETURN', + 'THIS' : 'THIS', + 'CHIP' : 'CHIP', + 'void' : 'VOID', + 'new' : 'NEW', + } + + literals = ':[]{}(),=' + + tokens = [ 'EQ', 'NE', 'LT', 'GT', 'LE', 'GE', + 'LEFTSHIFT', 'RIGHTSHIFT', + 'NOT', 'AND', 'OR', + 'PLUS', 'DASH', 'STAR', 'SLASH', + 'DOUBLE_COLON', 'SEMI', + 'ASSIGN', 'DOT', + 'IDENT', 'LIT_BOOL', 'FLOATNUMBER', 'NUMBER', 'STRING' ] + tokens += reserved.values() + + t_EQ = r'==' + t_NE = r'!=' + t_LT = r'<' + t_GT = r'>' + t_LE = r'<=' + t_GE = r'>=' + t_LEFTSHIFT = r'<<' + t_RIGHTSHIFT = r'>>' + t_NOT = r'!' + t_AND = r'&&' + t_OR = r'\|\|' + t_PLUS = r'\+' + t_DASH = r'-' + t_STAR = r'\*' + t_SLASH = r'/' + t_DOUBLE_COLON = r'::' + t_SEMI = r';' + t_ASSIGN = r':=' + t_DOT = r'\.' + + precedence = ( + ('left', 'AND', 'OR'), + ('left', 'EQ', 'NE'), + ('left', 'LT', 'GT', 'LE', 'GE'), + ('left', 'RIGHTSHIFT', 'LEFTSHIFT'), + ('left', 'PLUS', 'DASH'), + ('left', 'STAR', 'SLASH'), + ('right', 'NOT', 'UMINUS'), + ) + + def t_IDENT(self, t): + r'[a-zA-Z_][a-zA-Z_0-9]*' + if t.value == 'true': + t.type = 'LIT_BOOL' + t.value = True + return t + + if t.value == 'false': + t.type = 'LIT_BOOL' + t.value = False + return t + + # Check for reserved words + t.type = self.reserved.get(t.value, 'IDENT') + return t + + def t_FLOATNUMBER(self, t): + '[0-9]+[.][0-9]+' + try: + t.value = float(t.value) + except ValueError: + raise TokenError("Illegal float", t) + return t + + def t_NUMBER(self, t): + r'[0-9]+' + try: + t.value = int(t.value) + except ValueError: + raise TokenError("Illegal number", t) + return t + + def t_STRING1(self, t): + r'\"[^"\n]*\"' + t.type = 'STRING' + t.value = t.value[1:-1] + return t + + def t_STRING2(self, t): + r"\'[^'\n]*\'" + t.type = 'STRING' + t.value = t.value[1:-1] + return t + + def p_file(self, p): + "file : decls" + p[0] = p[1] + + def p_empty(self, p): + "empty :" + + def p_decls(self, p): + "decls : declsx" + p[0] = ast.DeclListAST(self, p[1]) + + def p_declsx__list(self, p): + "declsx : decl declsx" + p[0] = [ p[1] ] + p[2] + + def p_declsx__none(self, p): + "declsx : empty" + p[0] = [] + + def p_decl__machine(self, p): + "decl : MACHINE '(' ident pairs ')' ':' params '{' decls '}'" + p[0] = ast.MachineAST(self, p[3], p[4], p[7], p[9]) + + def p_decl__action(self, p): + "decl : ACTION '(' ident pairs ')' statements" + p[0] = ast.ActionDeclAST(self, p[3], p[4], p[6]) + + def p_decl__in_port(self, p): + "decl : IN_PORT '(' ident ',' type ',' var pairs ')' statements" + p[0] = ast.InPortDeclAST(self, p[3], p[5], p[7], p[8], p[10]) + + def p_decl__out_port(self, p): + "decl : OUT_PORT '(' ident ',' type ',' var pairs ')' SEMI" + p[0] = ast.OutPortDeclAST(self, p[3], p[5], p[7], p[8]) + + def p_decl__trans0(self, p): + "decl : TRANS '(' idents ',' idents ',' ident pairs ')' idents" + p[0] = ast.TransitionDeclAST(self, p[3], p[5], p[7], p[8], p[10]) + + def p_decl__trans1(self, p): + "decl : TRANS '(' idents ',' idents pairs ')' idents" + p[0] = ast.TransitionDeclAST(self, p[3], p[5], None, p[6], p[8]) + + def p_decl__extern0(self, p): + "decl : EXTERN_TYPE '(' type pairs ')' SEMI" + p[4]["external"] = "yes" + p[0] = ast.TypeDeclAST(self, p[3], p[4], []) + + def p_decl__extern1(self, p): + "decl : EXTERN_TYPE '(' type pairs ')' '{' type_methods '}'" + p[4]["external"] = "yes" + p[0] = ast.TypeDeclAST(self, p[3], p[4], p[7]) + + def p_decl__global(self, p): + "decl : GLOBAL '(' type pairs ')' '{' type_members '}'" + p[4]["global"] = "yes" + p[0] = ast.TypeDeclAST(self, p[3], p[4], p[7]) + + def p_decl__struct(self, p): + "decl : STRUCT '(' type pairs ')' '{' type_members '}'" + p[0] = ast.TypeDeclAST(self, p[3], p[4], p[7]) + + def p_decl__enum(self, p): + "decl : ENUM '(' type pairs ')' '{' type_enums '}'" + p[4]["enumeration"] = "yes" + p[0] = ast.EnumDeclAST(self, p[3], p[4], p[7]) + + def p_decl__object(self, p): + "decl : type ident pairs SEMI" + p[0] = ast.ObjDeclAST(self, p[1], p[2], p[3]) + + def p_decl__func_decl(self, p): + """decl : void ident '(' params ')' pairs SEMI + | type ident '(' params ')' pairs SEMI""" + p[0] = ast.FuncDeclAST(self, p[1], p[2], p[4], p[6], None) + + def p_decl__func_def(self, p): + """decl : void ident '(' params ')' pairs statements + | type ident '(' params ')' pairs statements""" + p[0] = ast.FuncDeclAST(self, p[1], p[2], p[4], p[6], p[7]) + + # Type fields + def p_type_members__list(self, p): + "type_members : type_member type_members" + p[0] = [ p[1] ] + p[2] + + def p_type_members__empty(self, p): + "type_members : empty" + p[0] = [] + + def p_type_member__1(self, p): + "type_member : type ident pairs SEMI" + p[0] = ast.TypeFieldMemberAST(self, p[1], p[2], p[3], None) + + def p_type_member__2(self, p): + "type_member : type ident ASSIGN expr SEMI" + p[0] = ast.TypeFieldMemberAST(self, p[1], p[2], + ast.PairListAST(self), p[4]) + + # Methods + def p_type_methods__list(self, p): + "type_methods : type_method type_methods" + p[0] = [ p[1] ] + p[2] + + def p_type_methods(self, p): + "type_methods : empty" + p[0] = [] + + def p_type_method(self, p): + "type_method : type_or_void ident '(' types ')' pairs SEMI" + p[0] = ast.TypeFieldMethodAST(self, p[1], p[2], p[4], p[6]) + + # Enum fields + def p_type_enums__list(self, p): + "type_enums : type_enum type_enums" + p[0] = [ p[1] ] + p[2] + + def p_type_enums__empty(self, p): + "type_enums : empty" + p[0] = [] + + def p_type_enum(self, p): + "type_enum : ident pairs SEMI" + p[0] = ast.TypeFieldEnumAST(self, p[1], p[2]) + + # Type + def p_types__multiple(self, p): + "types : type ',' types" + p[0] = [ p[1] ] + p[3] + + def p_types__one(self, p): + "types : type" + p[0] = [ p[1] ] + + def p_types__empty(self, p): + "types : empty" + p[0] = [] + + def p_type(self, p): + "type : ident" + p[0] = ast.TypeAST(self, p[1]) + + def p_void(self, p): + "void : VOID" + p[0] = ast.TypeAST(self, p[1]) + + def p_type_or_void(self, p): + """type_or_void : type + | void""" + p[0] = p[1] + + # Formal Param + def p_params__many(self, p): + "params : param ',' params" + p[0] = [ p[1] ] + p[3] + + def p_params__one(self, p): + "params : param" + p[0] = [ p[1] ] + + def p_params__none(self, p): + "params : empty" + p[0] = [] + + def p_param(self, p): + "param : type ident" + p[0] = ast.FormalParamAST(self, p[1], p[2]) + + # Idents and lists + def p_idents__braced(self, p): + "idents : '{' identx '}'" + p[0] = p[2] + + def p_idents__bare(self, p): + "idents : ident" + p[0] = [ p[1] ] + + def p_identx__multiple_1(self, p): + """identx : ident SEMI identx + | ident ',' identx""" + p[0] = [ p[1] ] + p[3] + + def p_identx__multiple_2(self, p): + "identx : ident identx" + p[0] = [ p[1] ] + p[2] + + def p_identx__single(self, p): + "identx : empty" + p[0] = [ ] + + def p_ident(self, p): + "ident : IDENT" + p[0] = p[1] + + # Pair and pair lists + def p_pairs__list(self, p): + "pairs : ',' pairsx" + p[0] = p[2] + + def p_pairs__empty(self, p): + "pairs : empty" + p[0] = ast.PairListAST(self) + + def p_pairsx__many(self, p): + "pairsx : pair ',' pairsx" + p[0] = p[3] + p[0].addPair(p[1]) + + def p_pairsx__one(self, p): + "pairsx : pair" + p[0] = ast.PairListAST(self) + p[0].addPair(p[1]) + + def p_pair__assign(self, p): + """pair : ident '=' STRING + | ident '=' ident""" + p[0] = ast.PairAST(self, p[1], p[3]) + + def p_pair__literal(self, p): + "pair : STRING" + p[0] = ast.PairAST(self, "short", p[1]) + + # Below are the rules for action descriptions + def p_statements__inner(self, p): + "statements : '{' statements_inner '}'" + p[0] = ast.StatementListAST(self, p[2]) + + def p_statements__none(self, p): + "statements : '{' '}'" + p[0] = ast.StatementListAST(self, []) + + def p_statements_inner__many(self, p): + "statements_inner : statement statements_inner" + p[0] = [ p[1] ] + p[2] + + def p_statements_inner__one(self, p): + "statements_inner : statement" + p[0] = [ p[1] ] + + def p_exprs__multiple(self, p): + "exprs : expr ',' exprs" + p[0] = [ p[1] ] + p[3] + + def p_exprs__one(self, p): + "exprs : expr" + p[0] = [ p[1] ] + + def p_exprs__empty(self, p): + "exprs : empty""" + p[0] = [] + + def p_statement__expression(self, p): + "statement : expr SEMI" + p[0] = ast.ExprStatementAST(self, p[1]) + + def p_statement__assign(self, p): + "statement : expr ASSIGN expr SEMI" + p[0] = ast.AssignStatementAST(self, p[1], p[3]) + + def p_statement__enqueue(self, p): + "statement : ENQUEUE '(' var ',' type pairs ')' statements" + p[0] = ast.EnqueueStatementAST(self, p[3], p[5], p[6], p[8]) + + def p_statement__peek(self, p): + "statement : PEEK '(' var ',' type ')' statements" + p[0] = ast.PeekStatementAST(self, p[3], p[5], p[7], "peek") + + def p_statement__copy_head(self, p): + "statement : COPY_HEAD '(' var ',' var pairs ')' SEMI" + p[0] = ast.CopyHeadStatementAST(self, p[3], p[5], p[6]) + + def p_statement__check_allocate(self, p): + "statement : CHECK_ALLOCATE '(' var ')' SEMI" + p[0] = ast.CheckAllocateStatementAST(self, p[3]) + + def p_statement__check_stop(self, p): + "statement : CHECK_STOP_SLOTS '(' var ',' STRING ',' STRING ')' SEMI" + p[0] = ast.CheckStopStatementAST(self, p[3], p[5], p[7]) + + def p_statement__return(self, p): + "statement : RETURN expr SEMI" + p[0] = ast.ReturnStatementAST(self, p[2]) + + def p_statement__if(self, p): + "statement : if_statement" + p[0] = p[1] + + def p_if_statement__if(self, p): + "if_statement : IF '(' expr ')' statements" + p[0] = ast.IfStatementAST(self, p[3], p[5], None) + + def p_if_statement__if_else(self, p): + "if_statement : IF '(' expr ')' statements ELSE statements" + p[0] = ast.IfStatementAST(self, p[3], p[5], p[7]) + + def p_statement__if_else_if(self, p): + "if_statement : IF '(' expr ')' statements ELSE if_statement" + p[0] = ast.IfStatementAST(self, p[3], p[5], + ast.StatementListAST(self, p[7])) + + def p_expr__var(self, p): + "aexpr : var" + p[0] = p[1] + + def p_expr__literal(self, p): + "aexpr : literal" + p[0] = p[1] + + def p_expr__enumeration(self, p): + "aexpr : enumeration" + p[0] = p[1] + + def p_expr__func_call(self, p): + "aexpr : ident '(' exprs ')'" + p[0] = ast.FuncCallExprAST(self, p[1], p[3]) + + def p_expr__new(self, p): + "aexpr : NEW type" + p[0] = ast.NewExprAST(self, p[2]) + + # globally access a local chip component and call a method + def p_expr__local_chip_method(self, p): + "aexpr : THIS DOT var '[' expr ']' DOT var DOT ident '(' exprs ')'" + p[0] = ast.LocalChipMethodAST(self, p[3], p[5], p[8], p[10], p[12]) + + # globally access a local chip component and access a data member + def p_expr__local_chip_member(self, p): + "aexpr : THIS DOT var '[' expr ']' DOT var DOT field" + p[0] = ast.LocalChipMemberAST(self, p[3], p[5], p[8], p[10]) + + # globally access a specified chip component and call a method + def p_expr__specified_chip_method(self, p): + "aexpr : CHIP '[' expr ']' DOT var '[' expr ']' DOT var DOT ident '(' exprs ')'" + p[0] = ast.SpecifiedChipMethodAST(self, p[3], p[6], p[8], p[11], p[13], + p[15]) + + # globally access a specified chip component and access a data member + def p_expr__specified_chip_member(self, p): + "aexpr : CHIP '[' expr ']' DOT var '[' expr ']' DOT var DOT field" + p[0] = ast.SpecifiedChipMemberAST(self, p[3], p[6], p[8], p[11], p[13]) + + def p_expr__member(self, p): + "aexpr : aexpr DOT ident" + p[0] = ast.MemberExprAST(self, p[1], p[3]) + + def p_expr__member_method_call(self, p): + "aexpr : aexpr DOT ident '(' exprs ')'" + p[0] = ast.MemberMethodCallExprAST(self, p[1], p[3], p[5]) + + def p_expr__member_method_call_lookup(self, p): + "aexpr : aexpr '[' exprs ']'" + p[0] = ast.MemberMethodCallExprAST(self, p[1], "lookup", p[3]) + + def p_expr__class_method_call(self, p): + "aexpr : type DOUBLE_COLON ident '(' exprs ')'" + p[0] = ast.ClassMethodCallExprAST(self, p[1], p[3], p[5]) + + def p_expr__aexpr(self, p): + "expr : aexpr" + p[0] = p[1] + + def p_expr__binary_op(self, p): + """expr : expr STAR expr + | expr SLASH expr + | expr PLUS expr + | expr DASH expr + | expr LT expr + | expr GT expr + | expr LE expr + | expr GE expr + | expr EQ expr + | expr NE expr + | expr AND expr + | expr OR expr + | expr RIGHTSHIFT expr + | expr LEFTSHIFT expr""" + p[0] = ast.InfixOperatorExprAST(self, p[1], p[2], p[3]) + + # FIXME - unary not + def p_expr__unary_op(self, p): + """expr : NOT expr + | DASH expr %prec UMINUS""" + p[0] = PrefixOperatorExpr(p[1], p[2]) + + def p_expr__parens(self, p): + "aexpr : '(' expr ')'" + p[0] = p[2] + + def p_literal__string(self, p): + "literal : STRING" + p[0] = ast.LiteralExprAST(self, p[1], "string") + + def p_literal__number(self, p): + "literal : NUMBER" + p[0] = ast.LiteralExprAST(self, p[1], "int") + + def p_literal__float(self, p): + "literal : FLOATNUMBER" + p[0] = ast.LiteralExprAST(self, p[1], "int") + + def p_literal__bool(self, p): + "literal : LIT_BOOL" + p[0] = ast.LiteralExprAST(self, p[1], "bool") + + def p_enumeration(self, p): + "enumeration : ident ':' ident" + p[0] = ast.EnumExprAST(self, ast.TypeAST(self, p[1]), p[3]) + + def p_var(self, p): + "var : ident" + p[0] = ast.VarExprAST(self, p[1]) + + def p_field(self, p): + "field : ident" + p[0] = p[1] diff --git a/src/mem/slicc/parser/lexer.ll b/src/mem/slicc/parser/lexer.ll deleted file mode 100644 index b2d36855b..000000000 --- a/src/mem/slicc/parser/lexer.ll +++ /dev/null @@ -1,125 +0,0 @@ - -/* - * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer; - * redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution; - * neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/* - * $Id$ - */ - -%{ - -#include <assert.h> -#include "mem/slicc/ast/ASTs.hh" -#include "parser.hh" -#include <string> - -extern "C" int yylex(); -extern "C" void yyerror(); -extern "C" int yywrap() -{ - return 1; -} - -%} -%x CMNT -%x IMBEDED -%% - -[\t ]+ /* Ignore whitespace */ -[\n] { g_line_number++; } -"//".*[\n] { g_line_number++; } /* C++ style comments */ - -"/*" BEGIN CMNT; -<CMNT>. ; -<CMNT>\n { g_line_number++; } -<CMNT>"*/" { BEGIN INITIAL; } - -true { yylval.str_ptr = new string(yytext); return LIT_BOOL; } -false { yylval.str_ptr = new string(yytext); return LIT_BOOL; } -global { return GLOBAL_DECL; } -machine { return MACHINE_DECL; } -in_port { return IN_PORT_DECL; } -out_port { return OUT_PORT_DECL; } -action { return ACTION_DECL; } -transition { return TRANSITION_DECL; } -structure { return STRUCT_DECL; } -external_type { return EXTERN_TYPE_DECL; } -enumeration { return ENUM_DECL; } -peek { return PEEK; } -enqueue { return ENQUEUE; } -copy_head { return COPY_HEAD; } -check_allocate { return CHECK_ALLOCATE; } -check_stop_slots { return CHECK_STOP_SLOTS; } -if { return IF; } -else { return ELSE; } -return { return RETURN; } -THIS { return THIS; } -CHIP { return CHIP; } -void { yylval.str_ptr = new string(yytext); return VOID; } -new { return NEW; } - -== { yylval.str_ptr = new string(yytext); return EQ; } -!= { yylval.str_ptr = new string(yytext); return NE; } -[<] { yylval.str_ptr = new string(yytext); return '<'; } -[>] { yylval.str_ptr = new string(yytext); return '>'; } -[<][<] { yylval.str_ptr = new string(yytext); return LEFTSHIFT; } -[>][>] { yylval.str_ptr = new string(yytext); return RIGHTSHIFT; } -[<][=] { yylval.str_ptr = new string(yytext); return LE; } -[>][=] { yylval.str_ptr = new string(yytext); return GE; } -[!] { yylval.str_ptr = new string(yytext); return NOT; } -[&][&] { yylval.str_ptr = new string(yytext); return AND; } -[|][|] { yylval.str_ptr = new string(yytext); return OR; } -[+] { yylval.str_ptr = new string(yytext); return PLUS; } -[-] { yylval.str_ptr = new string(yytext); return DASH; } -[*] { yylval.str_ptr = new string(yytext); return STAR; } -[/] { yylval.str_ptr = new string(yytext); return SLASH; } -:: { return DOUBLE_COLON; } -[:] { return ':'; } -[;] { return SEMICOLON; } -[[] { return '['; } -[]] { return ']'; } -[{] { return '{'; } -[}] { return '}'; } -[(] { return '('; } -[)] { return ')'; } -[,] { return ','; } -[=] { return '='; } -:= { return ASSIGN; } -[.] { return DOT; } - -[0-9]*[.][0-9]* { yylval.str_ptr = new string(yytext); return FLOATNUMBER; } -[0-9]* { yylval.str_ptr = new string(yytext); return NUMBER; } - -[a-zA-Z_][a-zA-Z_0-9]{0,50} { yylval.str_ptr = new string(yytext); return IDENT; } -\"[^"\n]*\" { yytext[strlen(yytext)-1] = '\0'; yylval.str_ptr = new string(yytext+1); return STRING; } -\'[^'\n]*\' { yytext[strlen(yytext)-1] = '\0'; yylval.str_ptr = new string(yytext+1); return STRING; } - -. { return OTHER; } /* Need so that we handle all characters */ - -%% - diff --git a/src/mem/slicc/parser/parser.py b/src/mem/slicc/parser/parser.py deleted file mode 100644 index 7fecfd273..000000000 --- a/src/mem/slicc/parser/parser.py +++ /dev/null @@ -1,563 +0,0 @@ -# Copyright (c) 2009 The Hewlett-Packard Development Company -# All rights reserved. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions are -# met: redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer; -# redistributions in binary form must reproduce the above copyright -# notice, this list of conditions and the following disclaimer in the -# documentation and/or other materials provided with the distribution; -# neither the name of the copyright holders nor the names of its -# contributors may be used to endorse or promote products derived from -# this software without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -# -# Authors: Nathan Binkert - -from ply import lex, yacc -import re - -t_ignore = '\t ' - -# C or C++ comment (ignore) -def t_c_comment(t): - r'/\*(.|\n)*?\*/' - t.lexer.lineno += t.value.count('\n') - -def t_cpp_comment(t): - r'//.*' - pass - -# Define a rule so we can track line numbers -def t_newline(t): - r'\n+' - t.lexer.lineno += len(t.value) - -reserved = { - 'global' : 'GLOBAL', - 'machine' : 'MACHINE', - 'in_port' : 'IN_PORT', - 'out_port' : 'OUT_PORT', - 'action' : 'ACTION', - 'transition' : 'TRANS', - 'structure' : 'STRUCT', - 'external_type' : 'EXTERN_TYPE', - 'enumeration' : 'ENUM', - 'peek' : 'PEEK', - 'enqueue' : 'ENQUEUE', - 'copy_head' : 'COPY_HEAD', - 'check_allocate' : 'CHECK_ALLOCATE', - 'check_stop_slots' : 'CHECK_STOP_SLOTS', - 'if' : 'IF', - 'else' : 'ELSE', - 'return' : 'RETURN', - 'THIS' : 'THIS', - 'CHIP' : 'CHIP', - 'void' : 'VOID', - 'new' : 'NEW', -} - -literals = ':[]{}(),=' - -tokens = [ 'EQ', 'NE', 'LT', 'GT', 'LE', 'GE', - 'LEFTSHIFT', 'RIGHTSHIFT', - 'NOT', 'AND', 'OR', - 'PLUS', 'DASH', 'STAR', 'SLASH', - 'DOUBLE_COLON', 'SEMICOLON', - 'ASSIGN', 'DOT', - 'IDENT', 'LIT_BOOL', 'FLOATNUMBER', 'NUMBER', 'STRING' ] -tokens += reserved.values() - -t_EQ = r'==' -t_NE = r'!=' -t_LT = r'<' -t_GT = r'>' -t_LE = r'<=' -t_GE = r'>=' -t_LEFTSHIFT = r'<<' -t_RIGHTSHIFT = r'>>' -t_NOT = r'!' -t_AND = r'&&' -t_OR = r'\|\|' -t_PLUS = r'\+' -t_DASH = r'-' -t_STAR = r'\*' -t_SLASH = r'/' -t_DOUBLE_COLON = r'::' -t_SEMICOLON = r';' -t_ASSIGN = r':=' -t_DOT = r'\.' - -class TokenError(Exception): - def __init__(self, msg, t): - super(TokenError, self).__init__(msg) - self.token = t - -class ParseError(Exception): - def __init__(self, msg, t): - super(ParseError, self).__init__(msg) - self.token = t - -def t_error(t): - raise TokenError("Illegal character", t) - -def t_IDENT(t): - r'[a-zA-Z_][a-zA-Z_0-9]*' - if t.value == 'true': - t.type = 'LIT_BOOL' - t.value = True - return t - - if t.value == 'false': - t.type = 'LIT_BOOL' - t.value = False - return t - - if t.value.startswith('LATENCY_'): - t.type = 'LATENCY' - return t - - t.type = reserved.get(t.value, 'IDENT') # Check for reserved words - return t - -def t_FLOATNUMBER(t): - '[0-9]+[.][0-9]+' - try: - t.value = float(t.value) - except ValueError: - raise TokenError("Illegal float", t) - return t - -def t_NUMBER(t): - r'[0-9]+' - try: - t.value = int(t.value) - except ValueError: - raise TokenError("Illegal number", t) - return t - -def t_STRING1(t): - r'\"[^"\n]*\"' - t.type = 'STRING' - return t - -def t_STRING2(t): - r"\'[^'\n]*\'" - t.type = 'STRING' - return t - - -def p_file(p): - "file : decl_l" - p[0] = [ x for x in p[1] if x is not None ] - -def p_error(t): - raise ParseError("Syntax error", t) - -def p_empty(p): - "empty :" - pass - -def p_decl_l(p): - "decl_l : decls" - p[0] = p[1] - -def p_decls(p): - """decls : decl decls - | empty""" - if len(p) == 3: - p[0] = [ p[1] ] + p[2] - elif len(p) == 2: - p[0] = [] - -def p_decl(p): - """decl : d_machine - | d_action - | d_in_port - | d_out_port - | t_trans - | d_extern - | d_global - | d_struct - | d_enum - | d_object - | d_func_decl - | d_func_def""" - p[0] = p[1] - -def p_d_machine(p): - """d_machine : MACHINE '(' ident pair_l ')' ':' param_l '{' decl_l '}'""" - - if len(p) == 9: - decl_l = p[7] - elif len(p) == 11: - decl_l = p[9] - decls = [ x for x in decl_l if x is not None ] - p[0] = Machine(p[3], decls) - -def p_d_action(p): - "d_action : ACTION '(' ident pair_l ')' statement_l" - p[0] = Action(p[3]) - -def p_d_in_port(p): - "d_in_port : IN_PORT '(' ident ',' type ',' var pair_l ')' statement_l" - p[0] = InPort(p[3]) - -def p_d_out_port(p): - "d_out_port : OUT_PORT '(' ident ',' type ',' var pair_l ')' SEMICOLON" - p[0] = OutPort(p[3]) - -def p_t_trans(p): - """t_trans : TRANS '(' ident_l ',' ident_l ',' ident pair_l ')' ident_l - | TRANS '(' ident_l ',' ident_l pair_l ')' ident_l""" - p[0] = Transition("transition") - -def p_d_extern(p): - """d_extern : EXTERN_TYPE '(' type pair_l ')' SEMICOLON - | EXTERN_TYPE '(' type pair_l ')' '{' type_methods '}'""" - p[0] = Extern(p[3]) - -def p_d_global(p): - "d_global : GLOBAL '(' type pair_l ')' '{' type_members '}'" - p[0] = Global(p[3]) - -def p_d_struct(p): - "d_struct : STRUCT '(' type pair_l ')' '{' type_members '}'" - p[0] = Struct(p[3]) - -def p_d_enum(p): - "d_enum : ENUM '(' type pair_l ')' '{' type_enums '}'" - p[0] = Enum(p[3]) - -def p_d_object(p): - "d_object : type ident pair_l SEMICOLON" - p[0] = Object(p[2]) - -def p_d_func_decl(p): - """d_func_decl : void ident '(' param_l ')' pair_l SEMICOLON - | type ident '(' param_l ')' pair_l SEMICOLON""" - pass - -def p_d_func_def(p): - """d_func_def : void ident '(' param_l ')' pair_l statement_l - | type ident '(' param_l ')' pair_l statement_l""" - p[0] = Function(p[2]) - -# Type fields -def p_type_members(p): - """type_members : type_member type_members - | empty""" - pass - -def p_type_member(p): - """type_member : type ident pair_l SEMICOLON - | type ident ASSIGN expr SEMICOLON""" - pass - -# Methods -def p_type_methods(p): - """type_methods : type_method type_methods - | empty""" - pass - -def p_type_method(p): - "type_method : type_or_void ident '(' type_l ')' pair_l SEMICOLON" - pass - -# Enum fields -def p_type_enums(p): - """type_enums : type_enum type_enums - | empty""" - pass - -def p_type_enum(p): - "type_enum : ident pair_l SEMICOLON" - pass - -# Type -def p_type_l(p): - """type_l : types - | empty""" - pass - -def p_types(p): - """types : type ',' types - | type""" - pass - -def p_type(p): - "type : ident" - p[0] = p[1] - -def p_void(p): - "void : VOID" - p[0] = None - -def p_type_or_void(p): - """type_or_void : type - | void""" - p[0] = p[1] - -# Formal Param -def p_param_l(p): - """param_l : params - | empty""" - pass - -def p_params(p): - """params : param ',' params - | param""" - pass - -def p_param(p): - "param : type ident" - pass - -# Idents and lists -def p_ident(p): - "ident : IDENT" - p[0] = p[1] - -def p_ident_l(p): - """ident_l : '{' idents '}' - | ident""" - p[0] = p[1] - -def p_idents(p): - """idents : ident SEMICOLON idents - | ident ',' idents - | ident idents - | empty""" - pass - -# Pair and pair lists -def p_pair_l(p): - """pair_l : ',' pairs - | empty""" - if len(p) == 3: - p[0] = p[2] - elif len(p) == 2: - p[0] = None - -def p_pairs(p): - """pairs : pair ',' pairs - | pair""" - if len(p) == 4: - p[3].append(p[1]) - p[0] = p[3] - elif len(p) == 2: - p[0] = [ p[1] ] - -def p_pair(p): - """pair : ident '=' STRING - | ident '=' ident - | STRING""" - if len(p) == 4: - p[0] = p[1], p[3] - elif len(p) == 2: - p[0] = "short", p[1] - -# Below are the rules for action descriptions -def p_statement_l(p): - "statement_l : '{' statements '}'" - pass - -def p_statements(p): - """statements : statement statements - | empty""" - pass - -def p_expr_l(p): - """expr_l : expr ',' expr_l - | expr - | empty""" - pass - -def p_statement(p): - """statement : expr SEMICOLON - | expr ASSIGN expr SEMICOLON - | ENQUEUE '(' var ',' type pair_l ')' statement_l - | PEEK '(' var ',' type ')' statement_l - | COPY_HEAD '(' var ',' var pair_l ')' SEMICOLON - | CHECK_ALLOCATE '(' var ')' SEMICOLON - | CHECK_STOP_SLOTS '(' var ',' STRING ',' STRING ')' SEMICOLON - | if_statement - | RETURN expr SEMICOLON""" - pass - -def p_if_statement(p): - """if_statement : IF '(' expr ')' statement_l ELSE statement_l - | IF '(' expr ')' statement_l - | IF '(' expr ')' statement_l ELSE if_statement""" - pass - -def p_expr(p): - """expr : var - | literal - | enumeration - | ident '(' expr_l ')' - | NEW type - | THIS DOT var '[' expr ']' DOT var DOT ident '(' expr_l ')' - | THIS DOT var '[' expr ']' DOT var DOT ident - | CHIP '[' expr ']' DOT var '[' expr ']' DOT var DOT ident '(' expr_l ')' - | CHIP '[' expr ']' DOT var '[' expr ']' DOT var DOT ident - | expr DOT ident - | expr DOT ident '(' expr_l ')' - | type DOUBLE_COLON ident '(' expr_l ')' - | expr '[' expr_l ']' - | expr STAR expr - | expr SLASH expr - | expr PLUS expr - | expr DASH expr - | expr LT expr - | expr GT expr - | expr LE expr - | expr GE expr - | expr EQ expr - | expr NE expr - | expr AND expr - | expr OR expr - | NOT expr - | expr RIGHTSHIFT expr - | expr LEFTSHIFT expr - | '(' expr ')'""" - pass - -def p_literal(p): - """literal : STRING - | NUMBER - | FLOATNUMBER - | LIT_BOOL""" - pass - -def p_enumeration(p): - "enumeration : ident ':' ident" - pass - -def p_var(p): - "var : ident" - pass - -lex.lex() -yacc.yacc(write_tables=0) - -slicc_generated_cc = set([ - 'ControllerFactory.cc', - 'MachineType.cc']) - -slicc_generated_hh = set([ - 'ControllerFactory.hh', - 'MachineType.hh', - 'Types.hh', - 'protocol_name.hh' ]) - -class Machine(object): - def __init__(self, name, decls): - self.name = name - self.decls = decls - - def add(self, hh, cc): - hh.add('%s_Controller.hh' % self.name) - hh.add('%s_Profiler.hh' % self.name) - - cc.add('%s_Controller.cc' % self.name) - cc.add('%s_Profiler.cc' % self.name) - cc.add('%s_Transitions.cc' % self.name) - cc.add('%s_Wakeup.cc' % self.name) - - for decl in self.decls: - decl.add(hh, cc, self.name) - -class Declaration(object): - hh = False - cc = False - def __init__(self, name): - self.name = name - - def add(self, hh, cc, name=None): - #print '>>>', type(self).__name__, self.name - if name: - name += '_' - else: - name = "" - if self.hh: - hh.add('%s%s.hh' % (name, self.name)) - if self.cc: - cc.add('%s%s.cc' % (name, self.name)) - -class Action(Declaration): pass -class InPort(Declaration): pass -class OutPort(Declaration): pass -class Transition(Declaration): pass -class Extern(Declaration): pass -class Global(Declaration): - hh = True - cc = True -class Struct(Declaration): - hh = True - cc = True -class Enum(Declaration): - hh = True - cc = True -class Object(Declaration): pass -class Function(Declaration): - cc = True - -def read_slicc(sources): - if not isinstance(sources, (list,tuple)): - sources = [ sources ] - - sm_files = [] - for source in sources: - for sm_file in file(source, "r"): - sm_file = sm_file.strip() - if not sm_file: - continue - if sm_file.startswith("#"): - continue - sm_files.append(sm_file) - - return sm_files - -def scan(filenames): - hh = slicc_generated_hh.copy() - cc = slicc_generated_cc.copy() - - for filename in filenames: - lex.lexer.lineno = 1 - try: - print "parsing ",filename - results = yacc.parse(file(filename, 'r').read()) - except (TokenError, ParseError), e: - sys.exit("%s: %s:%d" % (e, filename, e.token.lineno)) - - for result in results: - result.add(hh, cc) - - return list(hh), list(cc) - -if __name__ == '__main__': - import sys - - hh, cc = scan(read_slicc(sys.argv[1:])) - hh.sort() - cc.sort() - print 'Headers:' - for i in hh: - print ' %s' % i - - print 'Sources:' - for i in cc: - print ' %s' % i diff --git a/src/mem/slicc/parser/parser.yy b/src/mem/slicc/parser/parser.yy deleted file mode 100644 index c8cef3b21..000000000 --- a/src/mem/slicc/parser/parser.yy +++ /dev/null @@ -1,360 +0,0 @@ - -/* - * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer; - * redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution; - * neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/* - * $Id$ - * - * */ - -%{ -#include <string> -#include <stdio.h> -#include <assert.h> -#include "mem/slicc/ast/ASTs.hh" -#include <vector> - -#define YYMAXDEPTH 100000 -#define YYERROR_VERBOSE - -extern char* yytext; - -extern "C" void yyerror(char*); -extern "C" int yylex(); - -%} - -%union { - string* str_ptr; - Vector<string>* string_vector_ptr; - std::vector<string*>* stdstring_vector_ptr; - - // Decls - DeclAST* decl_ptr; - DeclListAST* decl_list_ptr; - Vector<DeclAST*>* decl_vector_ptr; - - // TypeField - TypeFieldAST* type_field_ptr; - Vector<TypeFieldAST*>* type_field_vector_ptr; - - // Type - TypeAST* type_ptr; - Vector<TypeAST*>* type_vector_ptr; - - // Formal Params - FormalParamAST* formal_param_ptr; - Vector<FormalParamAST*>* formal_param_vector_ptr; - - // Statements - StatementAST* statement_ptr; - StatementListAST* statement_list_ptr; - Vector<StatementAST*>* statement_vector_ptr; - - // Pairs - PairAST* pair_ptr; - PairListAST* pair_list_ptr; - - // Expressions - VarExprAST* var_expr_ptr; - ExprAST* expr_ptr; - Vector<ExprAST*>* expr_vector_ptr; -} - -%type <type_ptr> type void type_or_void -%type <type_vector_ptr> types type_list - - // Formal Params -%type <formal_param_ptr> formal_param -%type <formal_param_vector_ptr> formal_params formal_param_list - -%type <str_ptr> ident field -%type <string_vector_ptr> ident_list idents - -%type <statement_ptr> statement if_statement -%type <statement_list_ptr> statement_list -%type <statement_vector_ptr> statements - -%type <decl_ptr> decl -%type <decl_list_ptr> decl_list -%type <decl_vector_ptr> decls - -%type <type_field_vector_ptr> type_members type_enums type_methods -%type <type_field_ptr> type_member type_enum type_method - -%type <var_expr_ptr> var -%type <expr_ptr> expr literal enumeration -%type <expr_vector_ptr> expr_list - -%type <pair_ptr> pair -%type <pair_list_ptr> pair_list pairs - -%token <str_ptr> IDENT STRING NUMBER FLOATNUMBER LIT_BOOL VOID -%token <str_ptr> IMBED IMBED_TYPE -%token CHIP THIS -%token ASSIGN DOUBLE_COLON DOT SEMICOLON COLON -%token GLOBAL_DECL MACHINE_DECL IN_PORT_DECL OUT_PORT_DECL -%token PEEK ENQUEUE COPY_HEAD CHECK_ALLOCATE CHECK_STOP_SLOTS -//%token DEQUEUE REMOVE_EARLY SKIP_EARLY PEEK_EARLY -%token DEBUG_EXPR_TOKEN DEBUG_MSG_TOKEN -%token ACTION_DECL TRANSITION_DECL TYPE_DECL STRUCT_DECL EXTERN_TYPE_DECL ENUM_DECL -%token TYPE_FIELD OTHER IF ELSE RETURN NEW - -%token <str_ptr> EQ NE '<' '>' LE GE NOT AND OR PLUS DASH STAR SLASH RIGHTSHIFT LEFTSHIFT - -%left OR -%left AND -%nonassoc EQ NE -%nonassoc '<' '>' GE LE -%left PLUS DASH -%left STAR SLASH -%nonassoc NOT -%nonassoc DOUBLE_COLON DOT '[' - -%% - -file: decl_list { g_decl_list_ptr = $1; } - -decl_list: decls { $$ = new DeclListAST($1); } - -decls: decl decls { $2->insertAtTop($1); $$ = $2; } - | { $$ = new Vector<DeclAST*>; } - ; - -decl: MACHINE_DECL '(' ident pair_list ')' ':' formal_param_list '{' decl_list '}' { $$ = new MachineAST($3, $4, $7, $9); } - | ACTION_DECL '(' ident pair_list ')' statement_list { $$ = new ActionDeclAST($3, $4, $6); } - | IN_PORT_DECL '(' ident ',' type ',' var pair_list ')' statement_list { $$ = new InPortDeclAST($3, $5, $7, $8, $10); } - | OUT_PORT_DECL '(' ident ',' type ',' var pair_list ')' SEMICOLON { $$ = new OutPortDeclAST($3, $5, $7, $8); } - | TRANSITION_DECL '(' ident_list ',' ident_list ',' ident pair_list ')' ident_list { $$ = new TransitionDeclAST($3, $5, $7, $8, $10); } - | TRANSITION_DECL '(' ident_list ',' ident_list pair_list ')' ident_list { $$ = new TransitionDeclAST($3, $5, NULL, $6, $8); } - | EXTERN_TYPE_DECL '(' type pair_list ')' SEMICOLON { $4->addPair(new PairAST("external", "yes")); $$ = new TypeDeclAST($3, $4, NULL); } - | EXTERN_TYPE_DECL '(' type pair_list ')' '{' type_methods '}' { $4->addPair(new PairAST("external", "yes")); $$ = new TypeDeclAST($3, $4, $7); } - | GLOBAL_DECL '(' type pair_list ')' '{' type_members '}' { $4->addPair(new PairAST("global", "yes"));$$ = new TypeDeclAST($3, $4, $7); } - | STRUCT_DECL '(' type pair_list ')' '{' type_members '}' { $$ = new TypeDeclAST($3, $4, $7); } - | ENUM_DECL '(' type pair_list ')' '{' type_enums '}' { $4->addPair(new PairAST("enumeration", "yes")); $$ = new EnumDeclAST($3, $4, $7); } - | type ident pair_list SEMICOLON { $$ = new ObjDeclAST($1, $2, $3); } - | type ident '(' formal_param_list ')' pair_list SEMICOLON { $$ = new FuncDeclAST($1, $2, $4, $6, NULL); } // non-void function - | void ident '(' formal_param_list ')' pair_list SEMICOLON { $$ = new FuncDeclAST($1, $2, $4, $6, NULL); } // void function - | type ident '(' formal_param_list ')' pair_list statement_list { $$ = new FuncDeclAST($1, $2, $4, $6, $7); } // non-void function - | void ident '(' formal_param_list ')' pair_list statement_list { $$ = new FuncDeclAST($1, $2, $4, $6, $7); } // void function - ; - -// Type fields - -type_members: type_member type_members { $2->insertAtTop($1); $$ = $2; } - | { $$ = new Vector<TypeFieldAST*>; } - ; - -type_member: type ident pair_list SEMICOLON { $$ = new TypeFieldMemberAST($1, $2, $3, NULL); } - | type ident ASSIGN expr SEMICOLON { $$ = new TypeFieldMemberAST($1, $2, new PairListAST(), $4); } - ; - -// Methods -type_methods: type_method type_methods { $2->insertAtTop($1); $$ = $2; } - | { $$ = new Vector<TypeFieldAST*>; } - ; - -type_method: type_or_void ident '(' type_list ')' pair_list SEMICOLON { $$ = new TypeFieldMethodAST($1, $2, $4, $6); } - ; - -// Enum fields -type_enums: type_enum type_enums { $2->insertAtTop($1); $$ = $2; } - | { $$ = new Vector<TypeFieldAST*>; } - ; - -type_enum: ident pair_list SEMICOLON { $$ = new TypeFieldEnumAST($1, $2); } - ; - -// Type -type_list : types { $$ = $1; } - | { $$ = new Vector<TypeAST*>; } - ; - -types : type ',' types { $3->insertAtTop($1); $$ = $3; } - | type { $$ = new Vector<TypeAST*>; $$->insertAtTop($1); } - ; - -type: ident { $$ = new TypeAST($1); } - ; - -void: VOID { $$ = new TypeAST($1); } - ; - -type_or_void: type { $$ = $1; } - | void { $$ = $1; } - ; - -// Formal Param -formal_param_list : formal_params { $$ = $1; } - | { $$ = new Vector<FormalParamAST*>; } - ; - -formal_params : formal_param ',' formal_params { $3->insertAtTop($1); $$ = $3; } - | formal_param { $$ = new Vector<FormalParamAST*>; $$->insertAtTop($1); } - ; - -formal_param : type ident { $$ = new FormalParamAST($1, $2); } - ; - -// Idents and lists -ident: IDENT { $$ = $1; }; - -ident_list: '{' idents '}' { $$ = $2; } - | ident { $$ = new Vector<string>; $$->insertAtTop(*($1)); delete $1; } - ; - -idents: ident SEMICOLON idents { $3->insertAtTop(*($1)); $$ = $3; delete $1; } - | ident ',' idents { $3->insertAtTop(*($1)); $$ = $3; delete $1; } - | ident idents { $2->insertAtTop(*($1)); $$ = $2; delete $1; } - | { $$ = new Vector<string>; } - ; - -// Pair and pair lists -pair_list: ',' pairs { $$ = $2; } - | { $$ = new PairListAST(); } - -pairs : pair ',' pairs { $3->addPair($1); $$ = $3; } - | pair { $$ = new PairListAST(); $$->addPair($1); } - ; - -pair : ident '=' STRING { $$ = new PairAST($1, $3); } - | ident '=' ident { $$ = new PairAST($1, $3); } - | STRING { $$ = new PairAST(new string("short"), $1); } - ; - -// Below are the rules for action descriptions - -statement_list: '{' statements '}' { $$ = new StatementListAST($2); } - ; - -statements: statement statements { $2->insertAtTop($1); $$ = $2; } - | { $$ = new Vector<StatementAST*>; } - ; - -expr_list: expr ',' expr_list { $3->insertAtTop($1); $$ = $3; } - | expr { $$ = new Vector<ExprAST*>; $$->insertAtTop($1); } - | { $$ = new Vector<ExprAST*>; } - ; - -statement: expr SEMICOLON { $$ = new ExprStatementAST($1); } - | expr ASSIGN expr SEMICOLON { $$ = new AssignStatementAST($1, $3); } - | ENQUEUE '(' var ',' type pair_list ')' statement_list { $$ = new EnqueueStatementAST($3, $5, $6, $8); } - | PEEK '(' var ',' type ')' statement_list { $$ = new PeekStatementAST($3, $5, $7, "peek"); } -// | PEEK_EARLY '(' var ',' type ')' statement_list { $$ = new PeekStatementAST($3, $5, $7, "peekEarly"); } - | COPY_HEAD '(' var ',' var pair_list ')' SEMICOLON { $$ = new CopyHeadStatementAST($3, $5, $6); } - | CHECK_ALLOCATE '(' var ')' SEMICOLON { $$ = new CheckAllocateStatementAST($3); } - | CHECK_STOP_SLOTS '(' var ',' STRING ',' STRING ')' SEMICOLON { $$ = new CheckStopSlotsStatementAST($3, $5, $7); } - | if_statement { $$ = $1; } - | RETURN expr SEMICOLON { $$ = new ReturnStatementAST($2); } - ; - -if_statement: IF '(' expr ')' statement_list ELSE statement_list { $$ = new IfStatementAST($3, $5, $7); } - | IF '(' expr ')' statement_list { $$ = new IfStatementAST($3, $5, NULL); } - | IF '(' expr ')' statement_list ELSE if_statement { $$ = new IfStatementAST($3, $5, new StatementListAST($7)); } - ; - -expr: var { $$ = $1; } - | literal { $$ = $1; } - | enumeration { $$ = $1; } - | ident '(' expr_list ')' { $$ = new FuncCallExprAST($1, $3); } - | NEW type { $$ = new NewExprAST($2); } - -// globally access a local chip component and call a method - | THIS DOT var '[' expr ']' DOT var DOT ident '(' expr_list ')' { $$ = new ChipComponentAccessAST($3, $5, $8, $10, $12 ); } -// globally access a local chip component and access a data member - | THIS DOT var '[' expr ']' DOT var DOT field { $$ = new ChipComponentAccessAST($3, $5, $8, $10 ); } -// globally access a specified chip component and call a method - | CHIP '[' expr ']' DOT var '[' expr ']' DOT var DOT ident '(' expr_list ')' { $$ = new ChipComponentAccessAST($3, $6, $8, $11, $13, $15 ); } -// globally access a specified chip component and access a data member - | CHIP '[' expr ']' DOT var '[' expr ']' DOT var DOT field { $$ = new ChipComponentAccessAST($3, $6, $8, $11, $13 ); } - - - | expr DOT field { $$ = new MemberExprAST($1, $3); } - | expr DOT ident '(' expr_list ')' { $$ = new MethodCallExprAST($1, $3, $5); } - | type DOUBLE_COLON ident '(' expr_list ')' { $$ = new MethodCallExprAST($1, $3, $5); } - | expr '[' expr_list ']' { $$ = new MethodCallExprAST($1, new string("lookup"), $3); } - | expr STAR expr { $$ = new InfixOperatorExprAST($1, $2, $3); } - | expr SLASH expr { $$ = new InfixOperatorExprAST($1, $2, $3); } - | expr PLUS expr { $$ = new InfixOperatorExprAST($1, $2, $3); } - | expr DASH expr { $$ = new InfixOperatorExprAST($1, $2, $3); } - | expr '<' expr { $$ = new InfixOperatorExprAST($1, $2, $3); } - | expr '>' expr { $$ = new InfixOperatorExprAST($1, $2, $3); } - | expr LE expr { $$ = new InfixOperatorExprAST($1, $2, $3); } - | expr GE expr { $$ = new InfixOperatorExprAST($1, $2, $3); } - | expr EQ expr { $$ = new InfixOperatorExprAST($1, $2, $3); } - | expr NE expr { $$ = new InfixOperatorExprAST($1, $2, $3); } - | expr AND expr { $$ = new InfixOperatorExprAST($1, $2, $3); } - | expr OR expr { $$ = new InfixOperatorExprAST($1, $2, $3); } - | expr RIGHTSHIFT expr { $$ = new InfixOperatorExprAST($1, $2, $3); } - | expr LEFTSHIFT expr { $$ = new InfixOperatorExprAST($1, $2, $3); } -// | NOT expr { $$ = NULL; } // FIXME - unary not -// | DASH expr %prec NOT { $$ = NULL; } // FIXME - unary minus - | '(' expr ')' { $$ = $2; } - ; - -literal: STRING { $$ = new LiteralExprAST($1, "string"); } - | NUMBER { $$ = new LiteralExprAST($1, "int"); } - | FLOATNUMBER { $$ = new LiteralExprAST($1, "int"); } - | LIT_BOOL { $$ = new LiteralExprAST($1, "bool"); } - ; - -enumeration: ident ':' ident { $$ = new EnumExprAST(new TypeAST($1), $3); } - ; - -var: ident { $$ = new VarExprAST($1); } - ; - -field: ident { $$ = $1; } - ; - -%% - -extern FILE *yyin; - -DeclListAST* parse(string filename) -{ - FILE *file; - file = fopen(filename.c_str(), "r"); - if (!file) { - cerr << "Error: Could not open file: " << filename << endl; - exit(1); - } - g_line_number = 1; - g_file_name() = filename; - yyin = file; - g_decl_list_ptr = NULL; - yyparse(); - return g_decl_list_ptr; -} - -extern "C" void yyerror(char* s) -{ - fprintf(stderr, "%s:%d: %s at %s\n", g_file_name().c_str(), g_line_number, s, yytext); - exit(1); -} - diff --git a/src/mem/slicc/slicc_global.hh b/src/mem/slicc/slicc_global.hh deleted file mode 100644 index 40a00c9d2..000000000 --- a/src/mem/slicc/slicc_global.hh +++ /dev/null @@ -1,125 +0,0 @@ - -/* - * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer; - * redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution; - * neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef SLICC_GLOBAL_H -#define SLICC_GLOBAL_H - -#include <cassert> - -#include "mem/gems_common/std-includes.hh" -#include "mem/gems_common/Map.hh" - -typedef unsigned char uint8; -typedef unsigned int uint32; -typedef unsigned long long uint64; - -typedef signed char int8; -typedef int int32; -typedef long long int64; - -typedef long long integer_t; -typedef unsigned long long uinteger_t; - -const bool ASSERT_FLAG = true; - -// when CHECK_RESOURCE_DEADLOCK is enabled, slicc will generate additional code -// that works in conjuction with the resources rank value specified in the protocol -// to detect invalid resource stalls as soon as they occur. -const bool CHECK_INVALID_RESOURCE_STALLS = false; - -#undef assert -#define assert(EXPR) ASSERT(EXPR) - -#define ASSERT(EXPR)\ -{\ - if (ASSERT_FLAG) {\ - if (!(EXPR)) {\ - cerr << "failed assertion '"\ - << #EXPR << "' at fn "\ - << __PRETTY_FUNCTION__ << " in "\ - << __FILE__ << ":"\ - << __LINE__ << endl;\ - if(isatty(STDERR_FILENO)) {\ - cerr << "At this point you might want to attach a debug to ";\ - cerr << "the running and get to the" << endl;\ - cerr << "crash site; otherwise press enter to continue" << endl;\ - cerr << "PID: " << getpid();\ - cerr << endl << flush; \ - char c; \ - cin.get(c); \ - }\ - abort();\ - }\ - }\ -} - -class State; -class Event; -class Symbol; -class Var; - -namespace __gnu_cxx { - template <> struct hash<State*> - { - size_t operator()(State* s) const { return (size_t) s; } - }; - template <> struct hash<Event*> - { - size_t operator()(Event* s) const { return (size_t) s; } - }; - template <> struct hash<Symbol*> - { - size_t operator()(Symbol* s) const { return (size_t) s; } - }; - template <> struct hash<Var*> - { - size_t operator()(Var* s) const { return (size_t) s; } - }; -} // namespace __gnu_cxx - -namespace std { - template <> struct equal_to<Event*> - { - bool operator()(Event* s1, Event* s2) const { return s1 == s2; } - }; - template <> struct equal_to<State*> - { - bool operator()(State* s1, State* s2) const { return s1 == s2; } - }; - template <> struct equal_to<Symbol*> - { - bool operator()(Symbol* s1, Symbol* s2) const { return s1 == s2; } - }; - template <> struct equal_to<Var*> - { - bool operator()(Var* s1, Var* s2) const { return s1 == s2; } - }; -} // namespace std - -#endif //SLICC_GLOBAL_H diff --git a/src/mem/slicc/symbols/Action.hh b/src/mem/slicc/symbols/Action.hh deleted file mode 100644 index dbb0c836a..000000000 --- a/src/mem/slicc/symbols/Action.hh +++ /dev/null @@ -1,52 +0,0 @@ - -/* - * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer; - * redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution; - * neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/* - * $Id$ - */ - -#ifndef ACTION_H -#define ACTION_H - -#include "mem/slicc/symbols/Symbol.hh" - -class Action : public Symbol { -public: - Action(string id, - const Map<Var*, string>& resources, - const Location& location, - const Map<string, string>& pairs) : Symbol(id, location, pairs) { m_resources = resources; } - const Map<Var*, string>& getResources() const { return m_resources; } - void print(ostream& out) const { out << "[Action: " << getIdent() << "]"; } - -private: - Map<Var*, string> m_resources; -}; - -#endif //ACTION_H diff --git a/src/mem/slicc/symbols/Action.py b/src/mem/slicc/symbols/Action.py new file mode 100644 index 000000000..880fab15a --- /dev/null +++ b/src/mem/slicc/symbols/Action.py @@ -0,0 +1,38 @@ +# Copyright (c) 1999-2008 Mark D. Hill and David A. Wood +# Copyright (c) 2009 The Hewlett-Packard Development Company +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer; +# redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution; +# neither the name of the copyright holders nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +from slicc.symbols.Symbol import Symbol + +class Action(Symbol): + def __init__(self, table, ident, resources, location, pairs): + super(Action, self).__init__(table, ident, location, pairs) + self.resources = resources + + def __repr__(self): + return "[Action: %s]" % self.ident + +__all__ = [ "Action" ] diff --git a/src/mem/slicc/symbols/Event.hh b/src/mem/slicc/symbols/Event.hh deleted file mode 100644 index 40cefc982..000000000 --- a/src/mem/slicc/symbols/Event.hh +++ /dev/null @@ -1,45 +0,0 @@ - -/* - * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer; - * redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution; - * neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/* - * $Id$ - */ - -#ifndef EVENT_H -#define EVENT_H - -#include "mem/slicc/symbols/Symbol.hh" - -class Event : public Symbol { -public: - Event(string id, const Location& location, const Map<string, string>& pairs) : Symbol(id, location, pairs) {} - void print(ostream& out) const { out << "[Event: " << getIdent() << "]"; } -}; - -#endif //EVENT_H diff --git a/src/mem/slicc/symbols/Event.py b/src/mem/slicc/symbols/Event.py new file mode 100644 index 000000000..9ff4d8ba7 --- /dev/null +++ b/src/mem/slicc/symbols/Event.py @@ -0,0 +1,34 @@ +# Copyright (c) 1999-2008 Mark D. Hill and David A. Wood +# Copyright (c) 2009 The Hewlett-Packard Development Company +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer; +# redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution; +# neither the name of the copyright holders nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +from slicc.symbols.Symbol import Symbol + +class Event(Symbol): + def __repr__(self): + return "[Event: %s]" % self.ident + +__all__ = [ "Event" ] diff --git a/src/mem/slicc/symbols/Func.cc b/src/mem/slicc/symbols/Func.cc deleted file mode 100644 index d29138b38..000000000 --- a/src/mem/slicc/symbols/Func.cc +++ /dev/null @@ -1,143 +0,0 @@ - -/* - * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer; - * redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution; - * neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/* - * Func.cc - * - * Description: See Func.hh - * - * $Id$ - * - */ - -#include "mem/slicc/symbols/Func.hh" -#include "mem/slicc/symbols/SymbolTable.hh" -#include "mem/slicc/generator/fileio.hh" -#include "mem/slicc/symbols/StateMachine.hh" - -Func::Func(string id, const Location& location, - Type* type_ptr, const Vector<Type*>& param_type_vec, - const Vector<string>& param_string_vec, string body, - const Map<string, string>& pairs, StateMachine* machine_ptr) - : Symbol(id, location, pairs) -{ - m_type_ptr = type_ptr; - m_param_type_vec = param_type_vec; - m_param_string_vec = param_string_vec; - m_body = body; - m_isInternalMachineFunc = false; - - if (machine_ptr == NULL) { - m_c_ident = id; - } else if (existPair("external") || existPair("primitive")) { - m_c_ident = id; - } else { - m_machineStr = machine_ptr->toString(); - m_c_ident = m_machineStr + "_" + id; // Append with machine name - m_isInternalMachineFunc = true; - } -} - -void Func::funcPrototype(string& code) const -{ - if (isExternal()) { - // Do nothing - } else { - string return_type = m_type_ptr->cIdent(); - Type* void_type_ptr = g_sym_table.getType("void"); - if (existPair("return_by_ref") && (m_type_ptr != void_type_ptr)) { - return_type += "&"; - } - code += return_type + " " + cIdent() + "("; - int size = m_param_string_vec.size(); - for(int i=0; i<size; i++) { - // Generate code - if (i != 0) { - code += ", "; - } - code += m_param_string_vec[i]; - } - code += ");\n"; - } -} - -// This write a function of object Chip -void Func::writeCFiles(string path) -{ - if (isExternal()) { - // Do nothing - } else { - ostringstream out; - - // Header - out << "/** Auto generated C++ code started by "<<__FILE__<<":"<<__LINE__<< " */" << endl; - out << endl; - out << "#include \"mem/protocol/Types.hh\"" << endl; - if (m_isInternalMachineFunc) { - out << "#include \"mem/protocol/" << m_machineStr << "_Controller.hh\"" << endl; - } - out << endl; - - // Generate function header - string code; - Type* void_type_ptr = g_sym_table.getType("void"); - string return_type = m_type_ptr->cIdent(); - code += return_type; - if (existPair("return_by_ref") && m_type_ptr != void_type_ptr) { - code += "&"; - } - if (!m_isInternalMachineFunc) { - code += " Chip::" + cIdent() + "("; - } else { - code += " " + m_machineStr + "_Controller::" + cIdent() + "("; - } - int size = m_param_type_vec.size(); - for(int i=0; i<size; i++) { - // Generate code - if (i != 0) { - code += ", "; - } - code += m_param_string_vec[i]; - } - code += ")"; - - // Function body - code += "\n{\n"; - code += m_body; - code += "}\n"; - out << code << endl; - - // Write it out - conditionally_write_file(path + cIdent() + ".cc", out); - } -} - -void Func::print(ostream& out) const -{ -} diff --git a/src/mem/slicc/symbols/Func.hh b/src/mem/slicc/symbols/Func.hh deleted file mode 100644 index 8f8548bb0..000000000 --- a/src/mem/slicc/symbols/Func.hh +++ /dev/null @@ -1,96 +0,0 @@ - -/* - * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer; - * redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution; - * neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/* - * Func.hh - * - * Description: - * - * $Id$ - * - */ - -#ifndef FUNC_H -#define FUNC_H - -#include "mem/slicc/slicc_global.hh" -#include "mem/slicc/symbols/Type.hh" -class StateMachine; - -class Func : public Symbol { -public: - // Constructors - Func(string id, const Location& location, - Type* type_ptr, const Vector<Type*>& param_type_vec, const Vector<string>& param_string_vec, - string body, const Map<string, string>& pairs, StateMachine* machine_ptr); - - // Destructor - ~Func() {} - - // Public Methods - string cIdent() const { return m_c_ident; } - const Vector<Type*>& getParamTypes() const { return m_param_type_vec; } - Type* getReturnType() const { return m_type_ptr; } - void writeCFiles(string path) ; - void funcPrototype(string& code) const; - bool isExternal() const { return existPair("external"); } - bool isInternalMachineFunc() const { return m_isInternalMachineFunc; } - void print(ostream& out) const; -private: - // Private Methods - - // Private copy constructor and assignment operator - Func(const Func& obj); - Func& operator=(const Func& obj); - - // Data Members (m_ prefix) - Type* m_type_ptr; - Vector<Type*> m_param_type_vec; - Vector<string> m_param_string_vec; - string m_body; - string m_c_ident; - string m_machineStr; - bool m_isInternalMachineFunc; -}; - -// Output operator declaration -ostream& operator<<(ostream& out, const Func& obj); - -// ******************* Definitions ******************* - -// Output operator definition -extern inline -ostream& operator<<(ostream& out, const Func& obj) -{ - obj.print(out); - out << flush; - return out; -} - -#endif //FUNC_H diff --git a/src/mem/slicc/symbols/Func.py b/src/mem/slicc/symbols/Func.py new file mode 100644 index 000000000..5c812a96f --- /dev/null +++ b/src/mem/slicc/symbols/Func.py @@ -0,0 +1,107 @@ +# Copyright (c) 1999-2008 Mark D. Hill and David A. Wood +# Copyright (c) 2009 The Hewlett-Packard Development Company +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer; +# redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution; +# neither the name of the copyright holders nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +from m5.util import code_formatter + +from slicc.symbols.Symbol import Symbol +from slicc.symbols.Type import Type + +class Func(Symbol): + def __init__(self, table, ident, location, return_type, param_types, + param_strings, body, pairs, machine): + super(Func, self).__init__(table, ident, location, pairs) + self.return_type = return_type + self.param_types = param_types + self.param_strings = param_strings + self.body = body + self.isInternalMachineFunc = False + + if machine is None: + self.c_ident = ident + elif "external" in self or "primitive" in self: + self.c_ident = ident + else: + self.machineStr = str(machine) + # Append with machine name + self.c_ident = "%s_%s" % (self.machineStr, ident) + self.isInternalMachineFunc = True + + def __repr__(self): + return "" + + @property + def prototype(self): + if "external" in self: + return "" + + return_type = self.return_type.c_ident + void_type = self.symtab.find("void", Type) + if "return_by_ref" in self and self.return_type != void_type: + return_type += "&" + + return "%s %s(%s);" % (return_type, self.c_ident, + ", ".join(self.param_strings)) + + def writeCodeFiles(self, path): + '''This write a function of object Chip''' + if "external" in self: + return + + code = code_formatter() + + # Header + code(''' +/** Auto generated C++ code started by $__file__:$__line__ */ + +#include "mem/protocol/Types.hh" +''') + + if self.isInternalMachineFunc: + code('#include "mem/protocol/${{self.machineStr}}_Controller.hh"') + + # Generate function header + void_type = self.symtab.find("void", Type) + return_type = self.return_type.c_ident + if "return_by_ref" in self and self.return_type != void_type: + return_type += "&" + + if self.isInternalMachineFunc: + klass = "%s_Controller" % self.machineStr + else: + klass = "Chip" + + params = ', '.join(self.param_strings) + + code(''' +$return_type ${klass}::${{self.c_ident}}($params) +{ +${{self.body}} +} +''') + code.write(path, "%s.cc" % self.c_ident) + +__all__ = [ "Func" ] diff --git a/src/mem/slicc/symbols/State.hh b/src/mem/slicc/symbols/State.hh deleted file mode 100644 index 39900d506..000000000 --- a/src/mem/slicc/symbols/State.hh +++ /dev/null @@ -1,45 +0,0 @@ - -/* - * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer; - * redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution; - * neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/* - * $Id$ - */ - -#ifndef STATE_H -#define STATE_H - -#include "mem/slicc/symbols/Symbol.hh" - -class State : public Symbol { -public: - State(string id, const Location& location, const Map<string, string>& pairs) : Symbol(id, location, pairs) {} - void print(ostream& out) const { out << "[State: " << getIdent() << "]"; } -}; - -#endif //STATE_H diff --git a/src/mem/slicc/symbols/State.py b/src/mem/slicc/symbols/State.py new file mode 100644 index 000000000..123693256 --- /dev/null +++ b/src/mem/slicc/symbols/State.py @@ -0,0 +1,34 @@ +# Copyright (c) 1999-2008 Mark D. Hill and David A. Wood +# Copyright (c) 2009 The Hewlett-Packard Development Company +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer; +# redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution; +# neither the name of the copyright holders nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +from slicc.symbols.Symbol import Symbol + +class State(Symbol): + def __repr__(self): + return "[State: %s]" % self.ident + +__all__ = [ "State" ] diff --git a/src/mem/slicc/symbols/StateMachine.cc b/src/mem/slicc/symbols/StateMachine.cc deleted file mode 100644 index 0edfedc43..000000000 --- a/src/mem/slicc/symbols/StateMachine.cc +++ /dev/null @@ -1,1481 +0,0 @@ - -/* - * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer; - * redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution; - * neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/* - * $Id$ - * - * */ - -#include "mem/slicc/symbols/StateMachine.hh" -#include "mem/slicc/generator/fileio.hh" -#include "mem/slicc/generator/html_gen.hh" -#include "mem/slicc/symbols/Action.hh" -#include "mem/slicc/symbols/Event.hh" -#include "mem/slicc/symbols/State.hh" -#include "mem/slicc/symbols/Transition.hh" -#include "mem/slicc/symbols/Var.hh" -#include "mem/slicc/symbols/SymbolTable.hh" -#include "mem/gems_common/util.hh" -#include "mem/gems_common/Vector.hh" -#include "mem/slicc/ast/FormalParamAST.hh" - -#include <set> - -StateMachine::StateMachine(string ident, const Location& location, const Map<string, string>& pairs, Vector<FormalParamAST*>* config_parameters) - : Symbol(ident, location, pairs) -{ - m_table_built = false; - m_config_parameters = config_parameters; - - for (int i=0; i< m_config_parameters->size(); i++) { - Var* var = new Var(m_config_parameters->ref(i)->getName(), - location, - m_config_parameters->ref(i)->getType(), - "m_"+m_config_parameters->ref(i)->getName(), - Map<string, string>(), - this); - g_sym_table.registerSym(m_config_parameters->ref(i)->getName(), var); - } -} - -StateMachine::~StateMachine() -{ - // FIXME - // assert(0); -} - -void StateMachine::addState(State* state_ptr) -{ - assert(m_table_built == false); - m_state_map.add(state_ptr, m_states.size()); - m_states.insertAtBottom(state_ptr); -} - -void StateMachine::addEvent(Event* event_ptr) -{ - assert(m_table_built == false); - m_event_map.add(event_ptr, m_events.size()); - m_events.insertAtBottom(event_ptr); -} - -void StateMachine::addAction(Action* action_ptr) -{ - assert(m_table_built == false); - - // Check for duplicate action - int size = m_actions.size(); - for(int i=0; i<size; i++) { - if (m_actions[i]->getIdent() == action_ptr->getIdent()) { - m_actions[i]->warning("Duplicate action definition: " + m_actions[i]->getIdent()); - action_ptr->error("Duplicate action definition: " + action_ptr->getIdent()); - } - if (m_actions[i]->getShorthand() == action_ptr->getShorthand()) { - m_actions[i]->warning("Duplicate action shorthand: " + m_actions[i]->getIdent()); - m_actions[i]->warning(" shorthand = " + m_actions[i]->getShorthand()); - action_ptr->warning("Duplicate action shorthand: " + action_ptr->getIdent()); - action_ptr->error(" shorthand = " + action_ptr->getShorthand()); - } - } - - m_actions.insertAtBottom(action_ptr); -} - -void StateMachine::addTransition(Transition* trans_ptr) -{ - assert(m_table_built == false); - trans_ptr->checkIdents(m_states, m_events, m_actions); - m_transitions.insertAtBottom(trans_ptr); -} - -void StateMachine::addFunc(Func* func_ptr) -{ - // register func in the symbol table - g_sym_table.registerSym(func_ptr->toString(), func_ptr); - m_internal_func_vec.insertAtBottom(func_ptr); -} - -void StateMachine::buildTable() -{ - assert(m_table_built == false); - int numStates = m_states.size(); - int numEvents = m_events.size(); - int numTransitions = m_transitions.size(); - int stateIndex, eventIndex; - - for(stateIndex=0; stateIndex < numStates; stateIndex++) { - m_table.insertAtBottom(Vector<Transition*>()); - for(eventIndex=0; eventIndex < numEvents; eventIndex++) { - m_table[stateIndex].insertAtBottom(NULL); - } - } - - for(int i=0; i<numTransitions; i++) { - Transition* trans_ptr = m_transitions[i]; - - // Track which actions we touch so we know if we use them all -- - // really this should be done for all symbols as part of the - // symbol table, then only trigger it for Actions, States, Events, - // etc. - - Vector<Action*> actions = trans_ptr->getActions(); - for(int actionIndex=0; actionIndex < actions.size(); actionIndex++) { - actions[actionIndex]->markUsed(); - } - - stateIndex = getStateIndex(trans_ptr->getStatePtr()); - eventIndex = getEventIndex(trans_ptr->getEventPtr()); - if (m_table[stateIndex][eventIndex] != NULL) { - m_table[stateIndex][eventIndex]->warning("Duplicate transition: " + m_table[stateIndex][eventIndex]->toString()); - trans_ptr->error("Duplicate transition: " + trans_ptr->toString()); - } - m_table[stateIndex][eventIndex] = trans_ptr; - } - - // Look at all actions to make sure we used them all - for(int actionIndex=0; actionIndex < m_actions.size(); actionIndex++) { - Action* action_ptr = m_actions[actionIndex]; - if (!action_ptr->wasUsed()) { - string error_msg = "Unused action: " + action_ptr->getIdent(); - if (action_ptr->existPair("desc")) { - error_msg += ", " + action_ptr->getDescription(); - } - action_ptr->warning(error_msg); - } - } - - m_table_built = true; -} - -const Transition* StateMachine::getTransPtr(int stateIndex, int eventIndex) const -{ - return m_table[stateIndex][eventIndex]; -} - -// *********************** // -// ******* C Files ******* // -// *********************** // - -void StateMachine::writeCFiles(string path) -{ - string comp = getIdent(); - string filename; - - // Output the method declarations for the class declaration - { - ostringstream sstr; - printControllerH(sstr, comp); - conditionally_write_file(path + comp + "_Controller.hh", sstr); - } - - // Output switch statement for transition table - { - ostringstream sstr; - printCSwitch(sstr, comp); - conditionally_write_file(path + comp + "_Transitions.cc", sstr); - } - - // Output the actions for performing the actions - { - ostringstream sstr; - printControllerC(sstr, comp); - conditionally_write_file(path + comp + "_Controller.cc", sstr); - } - - // Output the wakeup loop for the events - { - ostringstream sstr; - printCWakeup(sstr, comp); - conditionally_write_file(path + comp + "_Wakeup.cc", sstr); - } - - // Profiling - { - ostringstream sstr; - printProfilerC(sstr, comp); - conditionally_write_file(path + comp + "_Profiler.cc", sstr); - } - { - ostringstream sstr; - printProfilerH(sstr, comp); - conditionally_write_file(path + comp + "_Profiler.hh", sstr); - } - - // Write internal func files - for(int i=0; i<m_internal_func_vec.size(); i++) { - m_internal_func_vec[i]->writeCFiles(path); - } - -} - -void StateMachine::printControllerH(ostream& out, string component) -{ - - m_message_buffer_names.clear(); - - out << "/** \\file " << getIdent() << ".hh" << endl; - out << " * " << endl; - out << " * Auto generated C++ code started by "<<__FILE__<<":"<<__LINE__<< endl; - out << " * Created by slicc definition of Module \"" << getShorthand() << "\"" << endl; - out << " */" << endl; - out << endl; - out << "#ifndef " << component << "_CONTROLLER_H" << endl; - out << "#define " << component << "_CONTROLLER_H" << endl; - out << endl; - out << "#include \"mem/ruby/common/Global.hh\"" << endl; - out << "#include \"mem/ruby/common/Consumer.hh\"" << endl; - out << "#include \"mem/ruby/slicc_interface/AbstractController.hh\"" << endl; - out << "#include \"mem/protocol/TransitionResult.hh\"" << endl; - out << "#include \"mem/protocol/Types.hh\"" << endl; - out << "#include \"mem/protocol/" << component << "_Profiler.hh\"" << endl; - - // include object classes - std::set<string> seen_types; - for(int i=0; i<numObjects(); i++) { - Var* var = m_objs[i]; - if (seen_types.count(var->getType()->cIdent()) == 0) { - out << "#include \"mem/protocol/" << var->getType()->cIdent() << ".hh\"" << endl; - // out << "class " << var->getType()->cIdent() << ";" << endl; - seen_types.insert(var->getType()->cIdent()); - } - } - - out << endl; - - // for adding information to the protocol debug trace - out << "extern stringstream " << component << "_" << "transitionComment;" << endl; - - out << "class " << component << "_Controller : public AbstractController {" << endl; - - /* the coherence checker needs to call isBlockExclusive() and isBlockShared() - making the Chip a friend class is an easy way to do this for now */ - out << "#ifdef CHECK_COHERENCE" << endl; - out << "#endif /* CHECK_COHERENCE */" << endl; - - out << "public:" << endl; - // out << " " << component << "_Controller(int version, Network* net_ptr);" << endl; - out << " " << component << "_Controller(const string & name);" << endl; - out << " static int getNumControllers();" << endl; - out << " void init(Network* net_ptr, const vector<string> & argv);" << endl; - out << " MessageBuffer* getMandatoryQueue() const;" << endl; - out << " const int & getVersion() const;" << endl; - out << " const string toString() const;" << endl; - out << " const string getName() const;" << endl; - out << " const MachineType getMachineType() const;" << endl; - out << " void print(ostream& out) const;" << endl; - out << " void printConfig(ostream& out) const;" << endl; - out << " void wakeup();" << endl; - out << " void set_atomic(Address addr);" << endl; - out << " void clear_atomic(Address addr);" << endl; - out << " void reset_atomics();" << endl; - out << " void printStats(ostream& out) const { s_profiler.dumpStats(out); }" << endl; - out << " void clearStats() { s_profiler.clearStats(); }" << endl; - out << "private:" << endl; -//added by SS -// found_to_mem = 0; - for(int i=0;i<m_config_parameters->size();i++){ - out << " int m_" << m_config_parameters->ref(i)->getName() << ";" << endl; - } - if (strncmp(component.c_str(), "L1Cache", 7) == 0) { - out << " int servicing_atomic;" << endl; - out << " bool started_receiving_writes;" << endl; - out << " Address locked_read_request1;" << endl; - out << " Address locked_read_request2;" << endl; - out << " Address locked_read_request3;" << endl; - out << " Address locked_read_request4;" << endl; - out << " int read_counter;" << endl; - } - out << " int m_number_of_TBEs;" << endl; - - out << " TransitionResult doTransition(" << component << "_Event event, " << component - << "_State state, const Address& addr"; - if(CHECK_INVALID_RESOURCE_STALLS) { - out << ", int priority"; - } - out << "); // in " << component << "_Transitions.cc" << endl; - out << " TransitionResult doTransitionWorker(" << component << "_Event event, " << component - << "_State state, " << component << "_State& next_state, const Address& addr"; - if(CHECK_INVALID_RESOURCE_STALLS) { - out << ", int priority"; - } - out << "); // in " << component << "_Transitions.cc" << endl; - out << " string m_name;" << endl; - out << " int m_transitions_per_cycle;" << endl; - out << " int m_buffer_size;" << endl; - out << " int m_recycle_latency;" << endl; - out << " map< string, string > m_cfg;" << endl; - out << " NodeID m_version;" << endl; - out << " Network* m_net_ptr;" << endl; - out << " MachineID m_machineID;" << endl; - out << " " << component << "_Profiler s_profiler;" << endl; - out << " static int m_num_controllers;" << endl; - - // internal function protypes - out << " // Internal functions" << endl; - for(int i=0; i<m_internal_func_vec.size(); i++) { - Func* func = m_internal_func_vec[i]; - string proto; - func->funcPrototype(proto); - if (proto != "") { - out << " " << proto; - } - } - - out << " // Actions" << endl; - for(int i=0; i < numActions(); i++) { - const Action& action = getAction(i); - out << "/** \\brief " << action.getDescription() << "*/" << endl; - out << " void " << action.getIdent() << "(const Address& addr);" << endl; - } - - // the controller internal variables - out << " // Object" << endl; - for(int i=0; i < numObjects(); i++) { - const Var* var = m_objs[i]; - string template_hack = ""; - if (var->existPair("template_hack")) { - template_hack = var->lookupPair("template_hack"); - } - out << " " << var->getType()->cIdent() << template_hack << "* m_" - << var->cIdent() << "_ptr;" << endl; - - string str = "m_"+ var->cIdent() + "_ptr"; - if (var->getType()->cIdent() == "MessageBuffer") - m_message_buffer_names.push_back(str); - - } - - - out << "};" << endl; - out << "#endif // " << component << "_CONTROLLER_H" << endl; -} - -void StateMachine::printControllerC(ostream& out, string component) -{ - out << "/** \\file " << getIdent() << ".cc" << endl; - out << " * " << endl; - out << " * Auto generated C++ code started by "<<__FILE__<<":"<<__LINE__<< endl; - out << " * Created by slicc definition of Module \"" << getShorthand() << "\"" << endl; - out << " */" << endl; - out << endl; - out << "#include \"mem/ruby/common/Global.hh\"" << endl; - out << "#include \"mem/ruby/slicc_interface/RubySlicc_includes.hh\"" << endl; - out << "#include \"mem/protocol/" << component << "_Controller.hh\"" << endl; - out << "#include \"mem/protocol/" << component << "_State.hh\"" << endl; - out << "#include \"mem/protocol/" << component << "_Event.hh\"" << endl; - out << "#include \"mem/protocol/Types.hh\"" << endl; - out << "#include \"mem/ruby/system/System.hh\"" << endl; - - // include object classes - std::set<string> seen_types; - for(int i=0; i<numObjects(); i++) { - Var* var = m_objs[i]; - if (seen_types.count(var->getType()->cIdent()) == 0) { - out << "#include \"mem/protocol/" << var->getType()->cIdent() << ".hh\"" << endl; - seen_types.insert(var->getType()->cIdent()); - } - - } - - out << endl; - - out << "int " << component << "_Controller::m_num_controllers = 0;" << endl; - - // for adding information to the protocol debug trace - out << "stringstream " << component << "_" << "transitionComment;" << endl; - out << "#define APPEND_TRANSITION_COMMENT(str) (" << component << "_" << "transitionComment << str)" << endl; - - out << "/** \\brief constructor */" << endl; - out << component << "_Controller::" << component - // << "_Controller(int version, Network* net_ptr)" << endl; - << "_Controller(const string & name)" << endl; - out << " : m_name(name)" << endl; - out << "{ " << endl; - if (strncmp(component.c_str(), "L1Cache", 7) == 0) { - out << " servicing_atomic = 0;" << endl; - out << " started_receiving_writes = false;" << endl; - out << " locked_read_request1 = Address(-1);" << endl; - out << " locked_read_request2 = Address(-1);" << endl; - out << " locked_read_request3 = Address(-1);" << endl; - out << " locked_read_request4 = Address(-1);" << endl; - out << " read_counter = 0;" << endl; - } - out << " m_num_controllers++; " << endl; - for(int i=0; i < numObjects(); i++) { - const Var* var = m_objs[i]; - if ( var->cIdent().find("mandatoryQueue") != string::npos) - out << " m_" << var->cIdent() << "_ptr = new " << var->getType()->cIdent() << "();" << endl; - } - out << "}" << endl << endl; - - out << "void " << component << "_Controller::init(Network * net_ptr, const vector<string> & argv)" << endl; - out << "{" << endl; - out << " for (size_t i=0; i < argv.size(); i+=2) {" << endl; -// out << " printf (\"ARG: %s = %s \\n \", argv[i].c_str(), argv[i+1].c_str());"<< endl; - - out << " if (argv[i] == \"version\") " << endl; - out << " m_version = atoi(argv[i+1].c_str());" << endl; - out << " else if (argv[i] == \"transitions_per_cycle\") " << endl; - out << " m_transitions_per_cycle = atoi(argv[i+1].c_str());" << endl; - out << " else if (argv[i] == \"buffer_size\") " << endl; - out << " m_buffer_size = atoi(argv[i+1].c_str());" << endl; -//added by SS - out << " else if (argv[i] == \"recycle_latency\") " << endl; - out << " m_recycle_latency = atoi(argv[i+1].c_str());" << endl; -//added by SS --> for latency -//for loop on latency_vector to check with argv[i] and assign the value to the related m_latency ... - out << " else if (argv[i] == \"number_of_TBEs\") " << endl; - out << " m_number_of_TBEs = atoi(argv[i+1].c_str());" << endl; - - if (m_config_parameters->size()) { - for(int i= 0 ; i < m_config_parameters->size(); i++) { - out << " else if (argv[i] == \"" << m_config_parameters->ref(i)->getName() << "\")" << endl; - if (m_config_parameters->ref(i)->getTypeName() == "int") - out << " m_" << m_config_parameters->ref(i)->getName() << "=" << "atoi(argv[i+1].c_str());" << endl; - else - assert(0); // only int parameters are supported right now - // if (str == "to_mem_ctrl_latency") - // out << " m_" << (*it)->c_str() << "=" << "atoi(argv[i+1].c_str())+(random() % 5);" << endl; - } - } - out << " }" << endl; - out << " m_net_ptr = net_ptr;" << endl; - out << " m_machineID.type = MachineType_" << component << ";" << endl; - out << " m_machineID.num = m_version;" << endl; - - // make configuration array - out << " for (size_t i=0; i < argv.size(); i+=2) {" << endl; - out << " if (argv[i] != \"version\") " << endl; - out << " m_cfg[argv[i]] = argv[i+1];" << endl; - out << " }" << endl; - - out << endl; - - // initialize objects - out << " // Objects" << endl; - out << " s_profiler.setVersion(m_version);" << endl; - for(int i=0; i < numObjects(); i++) { - const Var* var = m_objs[i]; - if (!var->existPair("network")) { - // Not a network port object - if (var->getType()->existPair("primitive")) { - out << " m_" << var->cIdent() << "_ptr = new " << var->getType()->cIdent() << ";\n"; - if (var->existPair("default")) { - out << " (*m_" << var->cIdent() << "_ptr) = " << var->lookupPair("default") << ";\n"; - } - out << " }\n"; - - } else { - // Normal Object - string template_hack = ""; - if (var->existPair("template_hack")) { - template_hack = var->lookupPair("template_hack"); - } -//added by SS - string str = ""; - int found = 0; - if (var->existPair("factory")) { - out << " m_" << var->cIdent() << "_ptr = " << var->lookupPair("factory"); - } else { - if ( var->cIdent().find("mandatoryQueue") == string::npos) { - - str = " m_" + var->cIdent() + "_ptr = new " + var->getType()->cIdent() + template_hack; - out << str; - if (str.find("TBETable")!=string::npos){ - found = 1; - } - - if (!var->getType()->existPair("non_obj") && (!var->getType()->isEnumeration())) { - str = ""; - if (var->existPair("constructor_hack")) { - string constructor_hack = var->lookupPair("constructor_hack"); - str = "(" + constructor_hack + ")"; - } else { - str = "()"; - } - if (found) - str = "(m_number_of_TBEs)"; - out << str; - } - } - } - - out << ";\n"; - out << " assert(m_" << var->cIdent() << "_ptr != NULL);" << endl; - - if (var->existPair("default")) { - out << " (*m_" << var->cIdent() << "_ptr) = " << var->lookupPair("default") - << "; // Object default" << endl; - } else if (var->getType()->hasDefault()) { - out << " (*m_" << var->cIdent() << "_ptr) = " << var->getType()->getDefault() - << "; // Type " << var->getType()->getIdent() << " default" << endl; - } - - // Set ordering - if (var->existPair("ordered") && !var->existPair("trigger_queue")) { - // A buffer - string ordered = var->lookupPair("ordered"); - out << " m_" << var->cIdent() << "_ptr->setOrdering(" << ordered << ");\n"; - } - - // Set randomization - if (var->existPair("random")) { - // A buffer - string value = var->lookupPair("random"); - out << " m_" << var->cIdent() << "_ptr->setRandomization(" << value << ");\n"; - } - - // Set Priority - if (var->getType()->isBuffer() && var->existPair("rank") && !var->existPair("trigger_queue")) { - string rank = var->lookupPair("rank"); - out << " m_" << var->cIdent() << "_ptr->setPriority(" << rank << ");\n"; - } - } - } else { - // Network port object - string network = var->lookupPair("network"); - string ordered = var->lookupPair("ordered"); - string vnet = var->lookupPair("virtual_network"); - - assert (var->getMachine() != NULL); - out << " m_" << var->cIdent() << "_ptr = m_net_ptr->get" - << network << "NetQueue(m_version+MachineType_base_number(string_to_MachineType(\"" - << var->getMachine()->getIdent() << "\")), " - << ordered << ", " << vnet << ");\n"; - out << " assert(m_" << var->cIdent() << "_ptr != NULL);" << endl; - - // Set ordering - if (var->existPair("ordered")) { - // A buffer - string ordered = var->lookupPair("ordered"); - out << " m_" << var->cIdent() << "_ptr->setOrdering(" << ordered << ");\n"; - } - - // Set randomization - if (var->existPair("random")) { - // A buffer - string value = var->lookupPair("random"); - out << " m_" << var->cIdent() << "_ptr->setRandomization(" << value << ");\n"; - } - - // Set Priority - if (var->existPair("rank")) { - string rank = var->lookupPair("rank"); - out << " m_" << var->cIdent() << "_ptr->setPriority(" << rank << ");\n"; - } - - // Set buffer size - if (var->getType()->isBuffer()) { - out << " if (m_buffer_size > 0) {\n"; - out << " m_" << var->cIdent() << "_ptr->setSize(m_buffer_size);\n"; - out << " }\n"; - } - - // set description (may be overriden later by port def) - out << " m_" << var->cIdent() - << "_ptr->setDescription(\"[Version \" + int_to_string(m_version) + \", " - << component << ", name=" << var->cIdent() << "]\");" << endl; - out << endl; - } - } - - // Set the queue consumers - out << endl; - for(int i=0; i < m_in_ports.size(); i++) { - const Var* port = m_in_ports[i]; - out << " " << port->getCode() << ".setConsumer(this);" << endl; - } - - // Set the queue descriptions - out << endl; - for(int i=0; i < m_in_ports.size(); i++) { - const Var* port = m_in_ports[i]; - out << " " << port->getCode() - << ".setDescription(\"[Version \" + int_to_string(m_version) + \", " - << component << ", " << port->toString() << "]\");" << endl; - } - - // Initialize the transition profiling - out << endl; - for(int i=0; i<numTransitions(); i++) { - const Transition& t = getTransition(i); - const Vector<Action*>& action_vec = t.getActions(); - int numActions = action_vec.size(); - - // Figure out if we stall - bool stall = false; - for (int i=0; i<numActions; i++) { - if(action_vec[i]->getIdent() == "z_stall") { - stall = true; - } - } - - // Only possible if it is not a 'z' case - if (!stall) { - out << " s_profiler.possibleTransition(" << component << "_State_" - << t.getStatePtr()->getIdent() << ", " << component << "_Event_" - << t.getEventPtr()->getIdent() << ");" << endl; - } - } - - //added by SS to initialize recycle_latency of message buffers - std::vector<std::string>::const_iterator it; - for ( it=m_message_buffer_names.begin() ; it != m_message_buffer_names.end(); it++ ){ - out << " "<< (*it).c_str() << "->setRecycleLatency(m_recycle_latency);" << endl; - } - - - out << "}" << endl; - - out << endl; - - bool has_mandatory_q = false; - for(int i=0; i < m_in_ports.size(); i++) { - if (m_in_ports[i]->getCode().find("mandatoryQueue_ptr")!= string::npos) - has_mandatory_q = true; - } - - out << "int " << component << "_Controller::getNumControllers() {" << endl; - out << " return m_num_controllers;" << endl; - out << "}" << endl; - - out << endl; - - out << "MessageBuffer* " << component << "_Controller::getMandatoryQueue() const {" << endl; - if (has_mandatory_q) - out << " return m_" << component << "_mandatoryQueue_ptr;" << endl; - else - out << " return NULL;" << endl; - out << "}" << endl; - - out << endl; - - out << "const int & "<<component<<"_Controller::getVersion() const{" << endl; - out << " return m_version;" << endl; - out << "}"; - - out << endl; - - out << "const string "<<component<<"_Controller::toString() const{" << endl; - out << " return \"" << component<< "_Controller\";" << endl; - out << "}"; - - out << endl; - - out << "const string "<<component<<"_Controller::getName() const{" << endl; - out << " return m_name;" << endl; - out << "}"; - - out << endl; - - out << "const MachineType "<<component<<"_Controller::getMachineType() const{" << endl; - out << " return MachineType_" << component<< ";" << endl; - out << "}"; - - out << endl; - - out << "void " << component << "_Controller::print(ostream& out) const { out << \"[" << component - << "_Controller \" << m_version << \"]\"; }" << endl; - - out << "void " << component << "_Controller::printConfig(ostream& out) const {" << endl; - out << " out << \"" << component << "_Controller config: \" << m_name << endl;" << endl; - out << " out << \" version: \" << m_version << endl;" << endl; - out << " for(map< string, string >::const_iterator it = m_cfg.begin(); it != m_cfg.end(); it++) {" << endl; - out << " out << \" \" << (*it).first << \": \" << (*it).second << endl;" << endl; - out << " }" << endl; - out << "}" << endl; - - out << endl; - out << "// Actions" << endl; - out << endl; - - for(int i=0; i < numActions(); i++) { - const Action& action = getAction(i); - if (action.existPair("c_code")) { - out << "/** \\brief " << action.getDescription() << "*/" << endl; - out << "void " << component << "_Controller::" - << action.getIdent() << "(const Address& addr)" << endl; - out << "{" << endl; - out << " DEBUG_MSG(GENERATED_COMP, HighPrio,\"executing\");" << endl; -//added by SS -//it should point to m_latency... -//so I should change the string output of this lookup - - - string c_code_string = action.lookupPair("c_code"); - - out << c_code_string; - - out << "}" << endl; - } - out << endl; - } -} - -void StateMachine::printCWakeup(ostream& out, string component) -{ - out << "// Auto generated C++ code started by "<<__FILE__<<":"<<__LINE__<< endl; - out << "// " << getIdent() << ": " << getShorthand() << endl; - out << endl; - out << "#include \"mem/ruby/common/Global.hh\"" << endl; - out << "#include \"mem/ruby/slicc_interface/RubySlicc_includes.hh\"" << endl; - out << "#include \"mem/protocol/" << component << "_Controller.hh\"" << endl; - out << "#include \"mem/protocol/" << component << "_State.hh\"" << endl; - out << "#include \"mem/protocol/" << component << "_Event.hh\"" << endl; - out << "#include \"mem/protocol/Types.hh\"" << endl; - out << "#include \"mem/ruby/system/System.hh\"" << endl; - out << endl; - out << "void " << component << "_Controller::wakeup()" << endl; - out << "{" << endl; - // out << " DEBUG_EXPR(GENERATED_COMP, MedPrio,*this);" << endl; - // out << " DEBUG_EXPR(GENERATED_COMP, MedPrio,g_eventQueue_ptr->getTime());" << endl; - out << endl; - out << "int counter = 0;" << endl; - out << " while (true) {" << endl; - out << " // Some cases will put us into an infinite loop without this limit" << endl; - out << " assert(counter <= m_transitions_per_cycle);" << endl; - out << " if (counter == m_transitions_per_cycle) {" << endl; - out << " g_system_ptr->getProfiler()->controllerBusy(m_machineID); // Count how often we're fully utilized" << endl; - out << " g_eventQueue_ptr->scheduleEvent(this, 1); // Wakeup in another cycle and try again" << endl; - out << " break;" << endl; - out << " }" << endl; - - // InPorts - // - // Find the position of the mandatory queue in the vector so that we can print it out first - int j = -1; - if (strncmp(component.c_str(), "L1Cache", 7) == 0) { - for(int i=0; i < m_in_ports.size(); i++) { - const Var* port = m_in_ports[i]; - assert(port->existPair("c_code_in_port")); - if (port->toString().find("mandatoryQueue_in") != string::npos) { - assert (j == -1); - j = i; - } - else { - cout << port->toString() << endl << flush; - } - } - - assert(j != -1); - - // print out the mandatory queue here - const Var* port = m_in_ports[j]; - assert(port->existPair("c_code_in_port")); - out << " // " - << component << "InPort " << port->toString() - << endl; - string output = port->lookupPair("c_code_in_port"); - - out << output; - out << endl; - } - for(int i=0; i < m_in_ports.size(); i++) { - const Var* port = m_in_ports[i]; - // don't print out mandatory queue twice - if (i != j) { - if (strncmp(component.c_str(), "L1Cache", 7) == 0) { - if (port->toString().find("forwardRequestNetwork_in") != string::npos) { - out << " bool postpone = false;" << endl; - out << " if ((((*m_L1Cache_forwardToCache_ptr)).isReady())) {" << endl; - out << " const RequestMsg* in_msg_ptr;" << endl; - out << " in_msg_ptr = dynamic_cast<const RequestMsg*>(((*m_L1Cache_forwardToCache_ptr)).peek());" << endl; - out << " if ((((servicing_atomic > 0) && (locked_read_request1 == ((*in_msg_ptr)).m_Address || locked_read_request2 == ((*in_msg_ptr)).m_Address || locked_read_request3 == ((*in_msg_ptr)).m_Address || locked_read_request1 == ((*in_msg_ptr)).m_Address)))) {" << endl; - out << " postpone = true;" << endl; - out << " }" << endl; - - out << " }" << endl; - out << " if (!postpone) {" << endl; - } - else if (port->toString().find("requestNetwork_in") != string::npos || port->toString().find("requestIntraChipL1Network_in") != string::npos) { - out << " bool postpone = false;" << endl; - out << " if ((((*m_L1Cache_requestToL1Cache_ptr)).isReady())) {" << endl; - out << " const RequestMsg* in_msg_ptr;" << endl; - out << " in_msg_ptr = dynamic_cast<const RequestMsg*>(((*m_L1Cache_requestToL1Cache_ptr)).peek());" << endl; - out << " if ((((servicing_atomic > 0) && (locked_read_request1 == ((*in_msg_ptr)).m_Address || locked_read_request2 == ((*in_msg_ptr)).m_Address || locked_read_request3 == ((*in_msg_ptr)).m_Address || locked_read_request1 == ((*in_msg_ptr)).m_Address)))) {" << endl; - out << " postpone = true;" << endl; - out << " }" << endl; - - out << " }" << endl; - out << " if (!postpone) {" << endl; - } - } - assert(port->existPair("c_code_in_port")); - out << " // " - << component << "InPort " << port->toString() - << endl; - out << port->lookupPair("c_code_in_port"); - if (strncmp(component.c_str(), "L1Cache", 7) == 0) { - if (port->toString().find("forwardRequestNetwork_in") != string::npos) { - out << "}" << endl; - } - else if (port->toString().find("requestIntraChipL1Network_in") != string::npos) { - out << "}" << endl; - } - else if (port->toString().find("requestNetwork_in") != string::npos) { - out << "}" << endl; - } - } - out << endl; - } - } - - out << " break; // If we got this far, we have nothing left todo" << endl; - out << " }" << endl; - // out << " g_eventQueue_ptr->scheduleEvent(this, 1);" << endl; - // out << " DEBUG_NEWLINE(GENERATED_COMP, MedPrio);" << endl; - out << "}" << endl; - out << endl; - - - // tack on two more functions - if (strncmp(component.c_str(), "L1Cache", 7) == 0) { - out << "void " << component << "_Controller::set_atomic(Address addr)" << endl; - out << "{" << endl; - out << " servicing_atomic++; " << endl; - out << " switch (servicing_atomic) { " << endl; - out << " case(1): " << endl; - out << " assert(locked_read_request1 == Address(-1)); " << endl; - out << " locked_read_request1 = addr; " << endl; - out << " break; " << endl; - out << " case(2): " << endl; - out << " assert(locked_read_request2 == Address(-1)); " << endl; - out << " locked_read_request2 = addr; " << endl; - out << " break; " << endl; - out << " case(3): " << endl; - out << " assert(locked_read_request3 == Address(-1)); " << endl; - out << " locked_read_request3 = addr; " << endl; - out << " break; " << endl; - out << " case(4): " << endl; - out << " assert(locked_read_request4 == Address(-1)); " << endl; - out << " locked_read_request4 = addr; " << endl; - out << " break; " << endl; - out << " default: " << endl; - out << " assert(0);" << endl; - out << " }" << endl; - out << "}" << endl; - - out << "void " << component << "_Controller::clear_atomic(Address addr)" << endl; - out << "{" << endl; - out << " assert(servicing_atomic > 0); " << endl; - out << " if (addr == locked_read_request1) " << endl; - out << " locked_read_request1 = Address(-1);" << endl; - out << " else if (addr == locked_read_request2)" << endl; - out << " locked_read_request2 = Address(-1);" << endl; - out << " else if (addr == locked_read_request3)" << endl; - out << " locked_read_request3 = Address(-1);" << endl; - out << " else if (addr == locked_read_request4)" << endl; - out << " locked_read_request4 = Address(-1);" << endl; - out << " else " << endl; - out << " assert(0); " << endl; - out << " servicing_atomic--; " << endl; - out << "}" << endl; - - out << "void " << component << "_Controller::reset_atomics()" << endl; - out << "{" << endl; - out << " servicing_atomic = 0; " << endl; - out << " locked_read_request1 = Address(-1);" << endl; - out << " locked_read_request2 = Address(-1);" << endl; - out << " locked_read_request3 = Address(-1);" << endl; - out << " locked_read_request4 = Address(-1);" << endl; - out << "}" << endl; - } - else { - out << "void " << component << "_Controller::set_atomic(Address addr)" << endl; - out << "{" << endl; - out << " assert(0); " << endl; - out << "}" << endl; - - out << "void " << component << "_Controller::clear_atomic(Address addr)" << endl; - out << "{" << endl; - out << " assert(0); " << endl; - out << "}" << endl; - - out << "void " << component << "_Controller::reset_atomics()" << endl; - out << "{" << endl; - out << " assert(0); " << endl; - out << "}" << endl; - } - -} - -void StateMachine::printCSwitch(ostream& out, string component) -{ - out << "// Auto generated C++ code started by "<<__FILE__<<":"<<__LINE__<< endl; - out << "// " << getIdent() << ": " << getShorthand() << endl; - out << endl; - out << "#include \"mem/ruby/common/Global.hh\"" << endl; - out << "#include \"mem/protocol/" << component << "_Controller.hh\"" << endl; - out << "#include \"mem/protocol/" << component << "_State.hh\"" << endl; - out << "#include \"mem/protocol/" << component << "_Event.hh\"" << endl; - out << "#include \"mem/protocol/Types.hh\"" << endl; - out << "#include \"mem/ruby/system/System.hh\"" << endl; - out << endl; - out << "#define HASH_FUN(state, event) ((int(state)*" << component - << "_Event_NUM)+int(event))" << endl; - out << endl; - out << "#define GET_TRANSITION_COMMENT() (" << component << "_" << "transitionComment.str())" << endl; - out << "#define CLEAR_TRANSITION_COMMENT() (" << component << "_" << "transitionComment.str(\"\"))" << endl; - out << endl; - out << "TransitionResult " << component << "_Controller::doTransition(" - << component << "_Event event, " - << component << "_State state, " - << "const Address& addr" << endl; - if(CHECK_INVALID_RESOURCE_STALLS) { - out << ", int priority"; - } - out << ")" << endl; - - out << "{" << endl; - out << " " << component << "_State next_state = state;" << endl; - out << endl; - out << " DEBUG_NEWLINE(GENERATED_COMP, MedPrio);" << endl; - out << " DEBUG_MSG(GENERATED_COMP, MedPrio,*this);" << endl; - out << " DEBUG_EXPR(GENERATED_COMP, MedPrio,g_eventQueue_ptr->getTime());" << endl; - out << " DEBUG_EXPR(GENERATED_COMP, MedPrio,state);" << endl; - out << " DEBUG_EXPR(GENERATED_COMP, MedPrio,event);" << endl; - out << " DEBUG_EXPR(GENERATED_COMP, MedPrio,addr);" << endl; - out << endl; - out << " TransitionResult result = doTransitionWorker(event, state, next_state, addr"; - if(CHECK_INVALID_RESOURCE_STALLS) { - out << ", priority"; - } - out << ");" << endl; - out << endl; - out << " if (result == TransitionResult_Valid) {" << endl; - out << " DEBUG_EXPR(GENERATED_COMP, MedPrio, next_state);" << endl; - out << " DEBUG_NEWLINE(GENERATED_COMP, MedPrio);" << endl; - out << " s_profiler.countTransition(state, event);" << endl; - out << " if (Debug::getProtocolTrace()) {" << endl - << " g_system_ptr->getProfiler()->profileTransition(\"" << component - << "\", m_version, addr, " << endl - << " " << component << "_State_to_string(state), " << endl - << " " << component << "_Event_to_string(event), " << endl - << " " << component << "_State_to_string(next_state), GET_TRANSITION_COMMENT());" << endl - << " }" << endl; - out << " CLEAR_TRANSITION_COMMENT();" << endl; - out << " " << component << "_setState(addr, next_state);" << endl; - out << " " << endl; - out << " } else if (result == TransitionResult_ResourceStall) {" << endl; - out << " if (Debug::getProtocolTrace()) {" << endl - << " g_system_ptr->getProfiler()->profileTransition(\"" << component - << "\", m_version, addr, " << endl - << " " << component << "_State_to_string(state), " << endl - << " " << component << "_Event_to_string(event), " << endl - << " " << component << "_State_to_string(next_state), " << endl - << " \"Resource Stall\");" << endl - << " }" << endl; - out << " } else if (result == TransitionResult_ProtocolStall) {" << endl; - out << " DEBUG_MSG(GENERATED_COMP,HighPrio,\"stalling\");" << endl - << " DEBUG_NEWLINE(GENERATED_COMP, MedPrio);" << endl; - out << " if (Debug::getProtocolTrace()) {" << endl - << " g_system_ptr->getProfiler()->profileTransition(\"" << component - << "\", m_version, addr, " << endl - << " " << component << "_State_to_string(state), " << endl - << " " << component << "_Event_to_string(event), " << endl - << " " << component << "_State_to_string(next_state), " << endl - << " \"Protocol Stall\");" << endl - << " }" << endl - << " }" << endl; - out << " return result;" << endl; - out << "}" << endl; - out << endl; - out << "TransitionResult " << component << "_Controller::doTransitionWorker(" - << component << "_Event event, " - << component << "_State state, " - << component << "_State& next_state, " - << "const Address& addr" << endl; - if(CHECK_INVALID_RESOURCE_STALLS) { - out << ", int priority" << endl; - } - out << ")" << endl; - - out << "{" << endl; - out << "" << endl; - - out << " switch(HASH_FUN(state, event)) {" << endl; - - Map<string, Vector<string> > code_map; // This map will allow suppress generating duplicate code - Vector<string> code_vec; - - for(int i=0; i<numTransitions(); i++) { - const Transition& t = getTransition(i); - string case_string = component + "_State_" + t.getStatePtr()->getIdent() - + ", " + component + "_Event_" + t.getEventPtr()->getIdent(); - - string code; - - code += " {\n"; - // Only set next_state if it changes - if (t.getStatePtr() != t.getNextStatePtr()) { - code += " next_state = " + component + "_State_" + t.getNextStatePtr()->getIdent() + ";\n"; - } - - const Vector<Action*>& action_vec = t.getActions(); - int numActions = action_vec.size(); - - // Check for resources - Vector<string> code_sorter; - const Map<Var*, string>& res = t.getResources(); - Vector<Var*> res_keys = res.keys(); - for (int i=0; i<res_keys.size(); i++) { - string temp_code; - if (res_keys[i]->getType()->cIdent() == "DNUCAStopTable") { - temp_code += res.lookup(res_keys[i]); - } else { - temp_code += " if (!" + (res_keys[i]->getCode()) + ".areNSlotsAvailable(" + res.lookup(res_keys[i]) + ")) {\n"; - if(CHECK_INVALID_RESOURCE_STALLS) { - // assert that the resource stall is for a resource of equal or greater priority - temp_code += " assert(priority >= "+ (res_keys[i]->getCode()) + ".getPriority());\n"; - } - temp_code += " return TransitionResult_ResourceStall;\n"; - temp_code += " }\n"; - } - code_sorter.insertAtBottom(temp_code); - } - - // Emit the code sequences in a sorted order. This makes the - // output deterministic (without this the output order can vary - // since Map's keys() on a vector of pointers is not deterministic - code_sorter.sortVector(); - for (int i=0; i<code_sorter.size(); i++) { - code += code_sorter[i]; - } - - // Figure out if we stall - bool stall = false; - for (int i=0; i<numActions; i++) { - if(action_vec[i]->getIdent() == "z_stall") { - stall = true; - } - } - - if (stall) { - code += " return TransitionResult_ProtocolStall;\n"; - } else { - for (int i=0; i<numActions; i++) { - code += " " + action_vec[i]->getIdent() + "(addr);\n"; - } - code += " return TransitionResult_Valid;\n"; - } - code += " }\n"; - - - // Look to see if this transition code is unique. - if (code_map.exist(code)) { - code_map.lookup(code).insertAtBottom(case_string); - } else { - Vector<string> vec; - vec.insertAtBottom(case_string); - code_map.add(code, vec); - code_vec.insertAtBottom(code); - } - } - - // Walk through all of the unique code blocks and spit out the - // corresponding case statement elements - for (int i=0; i<code_vec.size(); i++) { - string code = code_vec[i]; - - // Iterative over all the multiple transitions that share the same code - for (int case_num=0; case_num<code_map.lookup(code).size(); case_num++) { - string case_string = code_map.lookup(code)[case_num]; - out << " case HASH_FUN(" << case_string << "):" << endl; - } - out << code; - } - - out << " default:" << endl; - out << " WARN_EXPR(m_version);" << endl; - out << " WARN_EXPR(g_eventQueue_ptr->getTime());" << endl; - out << " WARN_EXPR(addr);" << endl; - out << " WARN_EXPR(event);" << endl; - out << " WARN_EXPR(state);" << endl; - out << " ERROR_MSG(\"Invalid transition\");" << endl; - out << " }" << endl; - out << " return TransitionResult_Valid;" << endl; - out << "}" << endl; -} - -void StateMachine::printProfilerH(ostream& out, string component) -{ - out << "// Auto generated C++ code started by "<<__FILE__<<":"<<__LINE__<< endl; - out << "// " << getIdent() << ": " << getShorthand() << endl; - out << endl; - out << "#ifndef " << component << "_PROFILER_H" << endl; - out << "#define " << component << "_PROFILER_H" << endl; - out << endl; - out << "#include \"mem/ruby/common/Global.hh\"" << endl; - out << "#include \"mem/protocol/" << component << "_State.hh\"" << endl; - out << "#include \"mem/protocol/" << component << "_Event.hh\"" << endl; - out << endl; - out << "class " << component << "_Profiler {" << endl; - out << "public:" << endl; - out << " " << component << "_Profiler();" << endl; - out << " void setVersion(int version);" << endl; - out << " void countTransition(" << component << "_State state, " << component << "_Event event);" << endl; - out << " void possibleTransition(" << component << "_State state, " << component << "_Event event);" << endl; - out << " void dumpStats(ostream& out) const;" << endl; - out << " void clearStats();" << endl; - out << "private:" << endl; - out << " int m_counters[" << component << "_State_NUM][" << component << "_Event_NUM];" << endl; - out << " int m_event_counters[" << component << "_Event_NUM];" << endl; - out << " bool m_possible[" << component << "_State_NUM][" << component << "_Event_NUM];" << endl; - out << " int m_version;" << endl; - out << "};" << endl; - out << "#endif // " << component << "_PROFILER_H" << endl; -} - -void StateMachine::printProfilerC(ostream& out, string component) -{ - out << "// Auto generated C++ code started by "<<__FILE__<<":"<<__LINE__<< endl; - out << "// " << getIdent() << ": " << getShorthand() << endl; - out << endl; - out << "#include \"mem/protocol/" << component << "_Profiler.hh\"" << endl; - out << endl; - - // Constructor - out << component << "_Profiler::" << component << "_Profiler()" << endl; - out << "{" << endl; - out << " for (int state = 0; state < " << component << "_State_NUM; state++) {" << endl; - out << " for (int event = 0; event < " << component << "_Event_NUM; event++) {" << endl; - out << " m_possible[state][event] = false;" << endl; - out << " m_counters[state][event] = 0;" << endl; - out << " }" << endl; - out << " }" << endl; - out << " for (int event = 0; event < " << component << "_Event_NUM; event++) {" << endl; - out << " m_event_counters[event] = 0;" << endl; - out << " }" << endl; - out << "}" << endl; - - // setVersion - out << "void " << component << "_Profiler::setVersion(int version)" << endl; - out << "{" << endl; - out << " m_version = version;" << endl; - out << "}" << endl; - - // Clearstats - out << "void " << component << "_Profiler::clearStats()" << endl; - out << "{" << endl; - out << " for (int state = 0; state < " << component << "_State_NUM; state++) {" << endl; - out << " for (int event = 0; event < " << component << "_Event_NUM; event++) {" << endl; - out << " m_counters[state][event] = 0;" << endl; - out << " }" << endl; - out << " }" << endl; - out << " for (int event = 0; event < " << component << "_Event_NUM; event++) {" << endl; - out << " m_event_counters[event] = 0;" << endl; - out << " }" << endl; - out << "}" << endl; - - // Count Transition - out << "void " << component << "_Profiler::countTransition(" << component << "_State state, " << component << "_Event event)" << endl; - out << "{" << endl; - out << " assert(m_possible[state][event]);" << endl; - out << " m_counters[state][event]++;" << endl; - out << " m_event_counters[event]++;" << endl; - out << "}" << endl; - - // Possible Transition - out << "void " << component << "_Profiler::possibleTransition(" << component << "_State state, " << component << "_Event event)" << endl; - out << "{" << endl; - out << " m_possible[state][event] = true;" << endl; - out << "}" << endl; - - // dumpStats - out << "void " << component << "_Profiler::dumpStats(ostream& out) const" << endl; - out << "{" << endl; - out << " out << \" --- " << component << " \" << m_version << \" ---\" << endl;" << endl; - out << " out << \" - Event Counts -\" << endl;" << endl; - out << " for (int event = 0; event < " << component << "_Event_NUM; event++) {" << endl; - out << " int count = m_event_counters[event];" << endl; - out << " out << (" << component << "_Event) event << \" \" << count << endl;" << endl; - out << " }" << endl; - out << " out << endl;" << endl; - out << " out << \" - Transitions -\" << endl;" << endl; - out << " for (int state = 0; state < " << component << "_State_NUM; state++) {" << endl; - out << " for (int event = 0; event < " << component << "_Event_NUM; event++) {" << endl; - out << " if (m_possible[state][event]) {" << endl; - out << " int count = m_counters[state][event];" << endl; - out << " out << (" << component << "_State) state << \" \" << (" << component << "_Event) event << \" \" << count;" << endl; - out << " if (count == 0) {" << endl; - out << " out << \" <-- \";" << endl; - out << " }" << endl; - out << " out << endl;" << endl; - out << " }" << endl; - out << " }" << endl; - out << " out << endl;" << endl; - out << " }" << endl; - out << "}" << endl; -} - - - -// ************************** // -// ******* HTML Files ******* // -// ************************** // - -string frameRef(string click_href, string click_target, string over_href, string over_target_num, string text) -{ - string temp; - temp += "<A href=\"" + click_href + "\" "; - temp += "target=\"" + click_target + "\" "; - string javascript = "if (parent.frames[" + over_target_num + "].location != parent.location + '" + over_href + "') { parent.frames[" + over_target_num + "].location='" + over_href + "' }"; - // string javascript = "parent." + target + ".location='" + href + "'"; - temp += "onMouseOver=\"" + javascript + "\" "; - temp += ">" + text + "</A>"; - return temp; -} - -string frameRef(string href, string target, string target_num, string text) -{ - return frameRef(href, target, href, target_num, text); -} - - -void StateMachine::writeHTMLFiles(string path) -{ - string filename; - string component = getIdent(); - - /* - { - ostringstream out; - out << "<html>" << endl; - out << "<head>" << endl; - out << "<title>" << component << "</title>" << endl; - out << "</head>" << endl; - out << "<frameset rows=\"30,30,*\" frameborder=\"1\">" << endl; - out << " <frame name=\"Status\" src=\"empty.html\" marginheight=\"1\">" << endl; - out << " <frame name=\"Table\" src=\"" << component << "_table.html\" marginheight=\"1\">" << endl; - out << "</frameset>" << endl; - out << "</html>" << endl; - conditionally_write_file(path + component + ".html", out); - } - */ - - // Create table with no row hilighted - { - ostringstream out; - printHTMLTransitions(out, numStates()+1); - - // -- Write file - filename = component + "_table.html"; - conditionally_write_file(path + filename, out); - } - - // Generate transition tables - for(int i=0; i<numStates(); i++) { - ostringstream out; - printHTMLTransitions(out, i); - - // -- Write file - filename = component + "_table_" + getState(i).getIdent() + ".html"; - conditionally_write_file(path + filename, out); - } - - // Generate action descriptions - for(int i=0; i<numActions(); i++) { - ostringstream out; - createHTMLSymbol(getAction(i), "Action", out); - - // -- Write file - filename = component + "_action_" + getAction(i).getIdent() + ".html"; - conditionally_write_file(path + filename, out); - } - - // Generate state descriptions - for(int i=0; i<numStates(); i++) { - ostringstream out; - createHTMLSymbol(getState(i), "State", out); - - // -- Write file - filename = component + "_State_" + getState(i).getIdent() + ".html"; - conditionally_write_file(path + filename, out); - } - - // Generate event descriptions - for(int i=0; i<numEvents(); i++) { - ostringstream out; - createHTMLSymbol(getEvent(i), "Event", out); - - // -- Write file - filename = component + "_Event_" + getEvent(i).getIdent() + ".html"; - conditionally_write_file(path + filename, out); - } -} - -void StateMachine::printHTMLTransitions(ostream& out, int active_state) -{ - // -- Prolog - out << "<HTML><BODY link=\"blue\" vlink=\"blue\">" << endl; - - // -- Header - out << "<H1 align=\"center\">" << formatHTMLShorthand(getShorthand()) << ": " << endl; - Vector<StateMachine*> machine_vec = g_sym_table.getStateMachines(); - for (int i=0; i<machine_vec.size(); i++) { - StateMachine* type = machine_vec[i]; - if (i != 0) { - out << " - "; - } - if (type == this) { - out << type->getIdent() << endl; - } else { - out << "<A target=\"Table\"href=\"" + type->getIdent() + "_table.html\">" + type->getIdent() + "</A> " << endl; - } - } - out << "</H1>" << endl; - - // -- Table header - out << "<TABLE border=1>" << endl; - - // -- Column headers - out << "<TR>" << endl; - - // -- First column header - out << " <TH> </TH>" << endl; - - for(int event = 0; event < numEvents(); event++ ) { - out << " <TH bgcolor=white>"; - out << frameRef(getIdent() + "_Event_" + getEvent(event).getIdent() + ".html", "Status", "1", formatHTMLShorthand(getEvent(event).getShorthand())); - out << "</TH>" << endl; - } - - out << "</TR>" << endl; - - // -- Body of table - for(int state = 0; state < numStates(); state++ ) { - out << "<TR>" << endl; - - // -- Each row - if (state == active_state) { - out << " <TH bgcolor=yellow>"; - } else { - out << " <TH bgcolor=white>"; - } - - string click_href = getIdent() + "_table_" + getState(state).getIdent() + ".html"; - string text = formatHTMLShorthand(getState(state).getShorthand()); - - out << frameRef(click_href, "Table", getIdent() + "_State_" + getState(state).getIdent() + ".html", "1", formatHTMLShorthand(getState(state).getShorthand())); - out << "</TH>" << endl; - - // -- One column for each event - for(int event = 0; event < numEvents(); event++ ) { - const Transition* trans_ptr = getTransPtr(state, event); - - if( trans_ptr != NULL ) { - bool stall_action = false; - string nextState; - string actions_str; - - // -- Get the actions - // actions = trans_ptr->getActionShorthands(); - const Vector<Action*> actions = trans_ptr->getActions(); - for (int action=0; action < actions.size(); action++) { - if ((actions[action]->getIdent() == "z_stall") || - (actions[action]->getIdent() == "zz_recycleMandatoryQueue")) { - stall_action = true; - } - actions_str += " "; - actions_str += frameRef(getIdent() + "_action_" + actions[action]->getIdent() + ".html", "Status", "1", - formatHTMLShorthand(actions[action]->getShorthand())); - actions_str += "\n"; - } - - // -- Get the next state - if (trans_ptr->getNextStatePtr()->getIdent() != getState(state).getIdent()) { - string click_href = getIdent() + "_table_" + trans_ptr->getNextStatePtr()->getIdent() + ".html"; - nextState = frameRef(click_href, "Table", getIdent() + "_State_" + trans_ptr->getNextStatePtr()->getIdent() + ".html", "1", - formatHTMLShorthand(trans_ptr->getNextStateShorthand())); - } else { - nextState = ""; - } - - // -- Print out "actions/next-state" - if (stall_action) { - if (state == active_state) { - out << " <TD bgcolor=#C0C000>"; - } else { - out << " <TD bgcolor=lightgrey>"; - } - } else if (active_state < numStates() && (trans_ptr->getNextStatePtr()->getIdent() == getState(active_state).getIdent())) { - out << " <TD bgcolor=aqua>"; - } else if (state == active_state) { - out << " <TD bgcolor=yellow>"; - } else { - out << " <TD bgcolor=white>"; - } - - out << actions_str; - if ((nextState.length() != 0) && (actions_str.length() != 0)) { - out << "/"; - } - out << nextState; - out << "</TD>" << endl; - } else { - // This is the no transition case - if (state == active_state) { - out << " <TD bgcolor=#C0C000> </TD>" << endl; - } else { - out << " <TD bgcolor=lightgrey> </TD>" << endl; - } - } - } - // -- Each row - if (state == active_state) { - out << " <TH bgcolor=yellow>"; - } else { - out << " <TH bgcolor=white>"; - } - - click_href = getIdent() + "_table_" + getState(state).getIdent() + ".html"; - text = formatHTMLShorthand(getState(state).getShorthand()); - - out << frameRef(click_href, "Table", getIdent() + "_State_" + getState(state).getIdent() + ".html", "1", formatHTMLShorthand(getState(state).getShorthand())); - out << "</TH>" << endl; - - out << "</TR>" << endl; - } - - // -- Column footer - out << "<TR>" << endl; - out << " <TH> </TH>" << endl; - - for(int i = 0; i < numEvents(); i++ ) { - out << " <TH bgcolor=white>"; - out << frameRef(getIdent() + "_Event_" + getEvent(i).getIdent() + ".html", "Status", "1", formatHTMLShorthand(getEvent(i).getShorthand())); - out << "</TH>" << endl; - } - out << "</TR>" << endl; - - // -- Epilog - out << "</TABLE>" << endl; - out << "</BODY></HTML>" << endl; -} - - diff --git a/src/mem/slicc/symbols/StateMachine.hh b/src/mem/slicc/symbols/StateMachine.hh deleted file mode 100644 index f5f3ab073..000000000 --- a/src/mem/slicc/symbols/StateMachine.hh +++ /dev/null @@ -1,156 +0,0 @@ - -/* - * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer; - * redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution; - * neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/* - * $Id$ - * - * */ - -#ifndef STATEMACHINE_H -#define STATEMACHINE_H - -#include "mem/slicc/slicc_global.hh" -#include "mem/gems_common/Vector.hh" -#include "mem/gems_common/Map.hh" -#include "mem/slicc/symbols/Symbol.hh" -#include <list> - -using namespace std; - -class Transition; -class Event; -class State; -class Action; -class Var; -class Func; -class FormalParamAST; - -class StateMachine : public Symbol { -public: - // Constructors - StateMachine(string ident, const Location& location, const Map<string, string>& pairs, Vector<FormalParamAST*>* config_parameters); - - // Destructor - ~StateMachine(); - - // Public Methods - - // Add items to the state machine - // void setMachine(string ident, const Map<string, string>& pairs); - void addState(State* state_ptr); - void addEvent(Event* event_ptr); - void addAction(Action* action_ptr); - void addTransition(Transition* trans_ptr); - void addInPort(Var* var) { m_in_ports.insertAtBottom(var); } - void addFunc(Func* func); - void addObj(Var* obj) { m_objs.insertAtBottom(obj); } - - // Accessors to vectors - const State& getState(int index) const { return *m_states[index]; } - const Event& getEvent(int index) const { return *m_events[index]; } - const Action& getAction(int index) const { return *m_actions[index]; } - const Transition& getTransition(int index) const { return *m_transitions[index]; } - const Transition* getTransPtr(int stateIndex, int eventIndex) const; - const Var& getObject(int index) const { return *m_objs[index]; } - - // Accessors for size of vectors - int numStates() const { return m_states.size(); } - int numEvents() const { return m_events.size(); } - int numActions() const { return m_actions.size(); } - int numTransitions() const { return m_transitions.size(); } - int numObjects() const { return m_objs.size(); } - - void buildTable(); // Needs to be called before accessing the table - - // Code generator methods - void writeCFiles(string path) ; - void writeHTMLFiles(string path) ; - - void print(ostream& out) const { out << "[StateMachine: " << toString() << "]" << endl; } -private: - - Vector<FormalParamAST*>* m_config_parameters; - - // Private Methods - void checkForDuplicate(const Symbol& sym) const; - - int getStateIndex(State* state_ptr) const { return m_state_map.lookup(state_ptr); } - int getEventIndex(Event* event_ptr) const { return m_event_map.lookup(event_ptr); } - - // Private copy constructor and assignment operator - // StateMachine(const StateMachine& obj); - // StateMachine& operator=(const StateMachine& obj); - - void printControllerH(ostream& out, string component) ; - void printControllerC(ostream& out, string component) ; - void printCWakeup(ostream& out, string component) ; - void printCSwitch(ostream& out, string component) ; - void printProfilerH(ostream& out, string component) ; - void printProfilerC(ostream& out, string component) ; - - void printHTMLTransitions(ostream& out, int active_state) ; - - // Data Members (m_ prefix) - Vector<State*> m_states; - Vector<Event*> m_events; - Vector<Action*> m_actions; - Vector<Transition*> m_transitions; - Vector<Func*> m_internal_func_vec; - - Map<State*, int> m_state_map; - Map<Event*, int> m_event_map; - - Vector<Var*> m_in_ports; - - Vector<Var*> m_objs; - - // Table variables - bool m_table_built; - Vector<Vector<Transition*> > m_table; - - //added by SS - std::vector<std::string> m_message_buffer_names; - -}; - -// Output operator declaration -ostream& operator<<(ostream& out, const StateMachine& obj); - -// ******************* Definitions ******************* - -// Output operator definition -extern inline -ostream& operator<<(ostream& out, const StateMachine& obj) -{ - obj.print(out); - out << flush; - return out; -} - -#endif //STATEMACHINE_H diff --git a/src/mem/slicc/symbols/StateMachine.py b/src/mem/slicc/symbols/StateMachine.py new file mode 100644 index 000000000..af9850896 --- /dev/null +++ b/src/mem/slicc/symbols/StateMachine.py @@ -0,0 +1,1164 @@ +# Copyright (c) 1999-2008 Mark D. Hill and David A. Wood +# Copyright (c) 2009 The Hewlett-Packard Development Company +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer; +# redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution; +# neither the name of the copyright holders nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +from m5.util import code_formatter, orderdict + +from slicc.symbols.Symbol import Symbol +from slicc.symbols.Var import Var +import slicc.generate.html as html + +class StateMachine(Symbol): + def __init__(self, symtab, ident, location, pairs, config_parameters): + super(StateMachine, self).__init__(symtab, ident, location, pairs) + self.table = None + self.config_parameters = config_parameters + for param in config_parameters: + var = Var(symtab, param.name, location, param.type_ast.type, + "m_%s" % param.name, {}, self) + self.symtab.registerSym(param.name, var) + + self.states = orderdict() + self.events = orderdict() + self.actions = orderdict() + self.transitions = [] + self.in_ports = [] + self.functions = [] + self.objects = [] + + self.message_buffer_names = [] + + def __repr__(self): + return "[StateMachine: %s]" % self.ident + + def addState(self, state): + assert self.table is None + self.states[state.ident] = state + + def addEvent(self, event): + assert self.table is None + self.events[event.ident] = event + + def addAction(self, action): + assert self.table is None + + # Check for duplicate action + for other in self.actions.itervalues(): + if action.ident == other.ident: + action.warning("Duplicate action definition: %s" % action.ident) + action.error("Duplicate action definition: %s" % action.ident) + if action.short == other.short: + other.warning("Duplicate action shorthand: %s" % other.ident) + other.warning(" shorthand = %s" % other.short) + action.warning("Duplicate action shorthand: %s" % action.ident) + action.error(" shorthand = %s" % action.short) + + self.actions[action.ident] = action + + def addTransition(self, trans): + assert self.table is None + self.transitions.append(trans) + + def addInPort(self, var): + self.in_ports.append(var) + + def addFunc(self, func): + # register func in the symbol table + self.symtab.registerSym(str(func), func) + self.functions.append(func) + + def addObject(self, obj): + self.objects.append(obj) + + # Needs to be called before accessing the table + def buildTable(self): + assert self.table is None + + table = {} + + for trans in self.transitions: + # Track which actions we touch so we know if we use them + # all -- really this should be done for all symbols as + # part of the symbol table, then only trigger it for + # Actions, States, Events, etc. + + for action in trans.actions: + action.used = True + + index = (trans.state, trans.event) + if index in table: + table[index].warning("Duplicate transition: %s" % table[index]) + trans.error("Duplicate transition: %s" % trans) + table[index] = trans + + # Look at all actions to make sure we used them all + for action in self.actions.itervalues(): + if not action.used: + error_msg = "Unused action: %s" % action.ident + if "desc" in action: + error_msg += ", " + action.desc + action.warning(error_msg) + self.table = table + + def writeCodeFiles(self, path): + self.printControllerHH(path) + self.printControllerCC(path) + self.printCSwitch(path) + self.printCWakeup(path) + self.printProfilerCC(path) + self.printProfilerHH(path) + + for func in self.functions: + func.writeCodeFiles(path) + + def printControllerHH(self, path): + '''Output the method declarations for the class declaration''' + code = code_formatter() + ident = self.ident + c_ident = "%s_Controller" % self.ident + + self.message_buffer_names = [] + + code(''' +/** \\file $ident.hh + * + * Auto generated C++ code started by $__file__:$__line__ + * Created by slicc definition of Module "${{self.short}}" + */ + +#ifndef ${ident}_CONTROLLER_H +#define ${ident}_CONTROLLER_H + +#include "mem/ruby/common/Global.hh" +#include "mem/ruby/common/Consumer.hh" +#include "mem/ruby/slicc_interface/AbstractController.hh" +#include "mem/protocol/TransitionResult.hh" +#include "mem/protocol/Types.hh" +#include "mem/protocol/${ident}_Profiler.hh" +''') + + seen_types = set() + for var in self.objects: + if var.type.ident not in seen_types and not var.type.isPrimitive: + code('#include "mem/protocol/${{var.type.c_ident}}.hh"') + seen_types.add(var.type.ident) + + # for adding information to the protocol debug trace + code(''' +extern stringstream ${ident}_transitionComment; + +class $c_ident : public AbstractController { +#ifdef CHECK_COHERENCE +#endif /* CHECK_COHERENCE */ +public: + $c_ident(const string & name); + static int getNumControllers(); + void init(Network* net_ptr, const vector<string> & argv); + MessageBuffer* getMandatoryQueue() const; + const int & getVersion() const; + const string toString() const; + const string getName() const; + const MachineType getMachineType() const; + void print(ostream& out) const; + void printConfig(ostream& out) const; + void wakeup(); + void set_atomic(Address addr); + void clear_atomic(Address addr); + void reset_atomics(); + void printStats(ostream& out) const { s_profiler.dumpStats(out); } + void clearStats() { s_profiler.clearStats(); } +private: +''') + + code.indent() + # added by SS + for param in self.config_parameters: + code('int m_${{param.ident}};') + + if self.ident == "L1Cache": + code(''' +int servicing_atomic; +Address locked_read_request1; +Address locked_read_request2; +Address locked_read_request3; +Address locked_read_request4; +int read_counter; +''') + + code(''' +int m_number_of_TBEs; + +TransitionResult doTransition(${ident}_Event event, ${ident}_State state, const Address& addr); // in ${ident}_Transitions.cc +TransitionResult doTransitionWorker(${ident}_Event event, ${ident}_State state, ${ident}_State& next_state, const Address& addr); // in ${ident}_Transitions.cc +string m_name; +int m_transitions_per_cycle; +int m_buffer_size; +int m_recycle_latency; +map< string, string > m_cfg; +NodeID m_version; +Network* m_net_ptr; +MachineID m_machineID; +${ident}_Profiler s_profiler; +static int m_num_controllers; +// Internal functions +''') + + for func in self.functions: + proto = func.prototype + if proto: + code('$proto') + + code(''' + +// Actions +''') + for action in self.actions.itervalues(): + code('/** \\brief ${{action.desc}} */') + code('void ${{action.ident}}(const Address& addr);') + + # the controller internal variables + code(''' + +// Object +''') + for var in self.objects: + th = var.get("template_hack", "") + code('${{var.type.c_ident}}$th* m_${{var.c_ident}}_ptr;') + + if var.type.ident == "MessageBuffer": + self.message_buffer_names.append("m_%s_ptr" % var.c_ident) + + code.dedent() + code('};') + code('#endif // ${ident}_CONTROLLER_H') + code.write(path, '%s.hh' % c_ident) + + def printControllerCC(self, path): + '''Output the actions for performing the actions''' + + code = code_formatter() + ident = self.ident + c_ident = "%s_Controller" % self.ident + + code(''' +/** \\file $ident.cc + * + * Auto generated C++ code started by $__file__:$__line__ + * Created by slicc definition of Module "${{self.short}}" + */ + +#include "mem/ruby/common/Global.hh" +#include "mem/ruby/slicc_interface/RubySlicc_includes.hh" +#include "mem/protocol/${ident}_Controller.hh" +#include "mem/protocol/${ident}_State.hh" +#include "mem/protocol/${ident}_Event.hh" +#include "mem/protocol/Types.hh" +#include "mem/ruby/system/System.hh" +''') + + # include object classes + seen_types = set() + for var in self.objects: + if var.type.ident not in seen_types and not var.type.isPrimitive: + code('#include "mem/protocol/${{var.type.c_ident}}.hh"') + seen_types.add(var.type.ident) + + code(''' +int $c_ident::m_num_controllers = 0; + +stringstream ${ident}_transitionComment; +#define APPEND_TRANSITION_COMMENT(str) (${ident}_transitionComment << str) +/** \\brief constructor */ +$c_ident::$c_ident(const string &name) + : m_name(name) +{ +''') + code.indent() + if self.ident == "L1Cache": + code(''' +servicing_atomic = 0; +locked_read_request1 = Address(-1); +locked_read_request2 = Address(-1); +locked_read_request3 = Address(-1); +locked_read_request4 = Address(-1); +read_counter = 0; +''') + + code('m_num_controllers++;') + for var in self.objects: + if var.ident.find("mandatoryQueue") >= 0: + code('m_${{var.c_ident}}_ptr = new ${{var.type.c_ident}}();') + + code.dedent() + code(''' +} + +void $c_ident::init(Network *net_ptr, const vector<string> &argv) +{ + for (size_t i = 0; i < argv.size(); i += 2) { + if (argv[i] == "version") + m_version = atoi(argv[i+1].c_str()); + else if (argv[i] == "transitions_per_cycle") + m_transitions_per_cycle = atoi(argv[i+1].c_str()); + else if (argv[i] == "buffer_size") + m_buffer_size = atoi(argv[i+1].c_str()); + else if (argv[i] == "recycle_latency") + m_recycle_latency = atoi(argv[i+1].c_str()); + else if (argv[i] == "number_of_TBEs") + m_number_of_TBEs = atoi(argv[i+1].c_str()); +''') + + code.indent() + code.indent() + for param in self.config_parameters: + code('else if (argv[i] == "${{param.name}}")') + if param.type_ast.type.ident == "int": + code(' m_${{param.name}} = atoi(argv[i+1].c_str());') + elif param.type_ast.type.ident == "bool": + code(' m_${{param.name}} = string_to_bool(argv[i+1]);') + else: + self.error("only int and bool parameters are "\ + "currently supported") + code.dedent() + code.dedent() + code(''' + } + + m_net_ptr = net_ptr; + m_machineID.type = MachineType_${ident}; + m_machineID.num = m_version; + for (size_t i = 0; i < argv.size(); i += 2) { + if (argv[i] != "version") + m_cfg[argv[i]] = argv[i+1]; + } + + // Objects + s_profiler.setVersion(m_version); +''') + + code.indent() + for var in self.objects: + vtype = var.type + vid = "m_%s_ptr" % var.c_ident + if "network" not in var: + # Not a network port object + if "primitive" in vtype: + code('$vid = new ${{vtype.c_ident}};') + if "default" in var: + code('(*$vid) = ${{var["default"]}};') + else: + # Normal Object + # added by SS + if "factory" in var: + code('$vid = ${{var["factory"]}};') + elif var.ident.find("mandatoryQueue") < 0: + th = var.get("template_hack", "") + expr = "%s = new %s%s" % (vid, vtype.c_ident, th) + + args = "" + if "non_obj" not in vtype and not vtype.isEnumeration: + if expr.find("TBETable") >= 0: + args = "m_number_of_TBEs" + else: + args = var.get("constructor_hack", "") + args = "(%s)" % args + + code('$expr$args;') + else: + code(';') + + code('assert($vid != NULL);') + + if "default" in var: + code('(*$vid) = ${{var["default"]}}; // Object default') + elif "default" in vtype: + code('(*$vid) = ${{vtype["default"]}}; // Type ${{vtype.ident}} default') + + # Set ordering + if "ordered" in var and "trigger_queue" not in var: + # A buffer + code('$vid->setOrdering(${{var["ordered"]}});') + + # Set randomization + if "random" in var: + # A buffer + code('$vid->setRandomization(${{var["random"]}});') + + # Set Priority + if vtype.isBuffer and \ + "rank" in var and "trigger_queue" not in var: + code('$vid->setPriority(${{var["rank"]}});') + else: + # Network port object + network = var["network"] + ordered = var["ordered"] + vnet = var["virtual_network"] + + assert var.machine is not None + code(''' +$vid = m_net_ptr->get${network}NetQueue(m_version+MachineType_base_number(string_to_MachineType("${{var.machine.ident}}")), $ordered, $vnet); +''') + + code('assert($vid != NULL);') + + # Set ordering + if "ordered" in var: + # A buffer + code('$vid->setOrdering(${{var["ordered"]}});') + + # Set randomization + if "random" in var: + # A buffer + code('$vid->setRandomization(${{var["random"]}})') + + # Set Priority + if "rank" in var: + code('$vid->setPriority(${{var["rank"]}})') + + # Set buffer size + if vtype.isBuffer: + code(''' +if (m_buffer_size > 0) { + $vid->setSize(m_buffer_size); +} +''') + + # set description (may be overriden later by port def) + code('$vid->setDescription("[Version " + int_to_string(m_version) + ", ${ident}, name=${{var.c_ident}}]");') + + # Set the queue consumers + code.insert_newline() + for port in self.in_ports: + code('${{port.code}}.setConsumer(this);') + + # Set the queue descriptions + code.insert_newline() + for port in self.in_ports: + code('${{port.code}}.setDescription("[Version " + int_to_string(m_version) + ", $ident, $port]");') + + # Initialize the transition profiling + code.insert_newline() + for trans in self.transitions: + # Figure out if we stall + stall = False + for action in trans.actions: + if action.ident == "z_stall": + stall = True + + # Only possible if it is not a 'z' case + if not stall: + state = "%s_State_%s" % (self.ident, trans.state.ident) + event = "%s_Event_%s" % (self.ident, trans.event.ident) + code('s_profiler.possibleTransition($state, $event);') + + # added by SS to initialize recycle_latency of message buffers + for buf in self.message_buffer_names: + code("$buf->setRecycleLatency(m_recycle_latency);") + + code.dedent() + code('}') + + has_mandatory_q = False + for port in self.in_ports: + if port.code.find("mandatoryQueue_ptr") >= 0: + has_mandatory_q = True + + if has_mandatory_q: + mq_ident = "m_%s_mandatoryQueue_ptr" % self.ident + else: + mq_ident = "NULL" + + code(''' +int $c_ident::getNumControllers() { + return m_num_controllers; +} + +MessageBuffer* $c_ident::getMandatoryQueue() const { + return $mq_ident; +} + +const int & $c_ident::getVersion() const{ + return m_version; +} + +const string $c_ident::toString() const{ + return "$c_ident"; +} + +const string $c_ident::getName() const{ + return m_name; +} +const MachineType $c_ident::getMachineType() const{ + return MachineType_${ident}; +} + +void $c_ident::print(ostream& out) const { out << "[$c_ident " << m_version << "]"; } + +void $c_ident::printConfig(ostream& out) const { + out << "$c_ident config: " << m_name << endl; + out << " version: " << m_version << endl; + for (map<string, string>::const_iterator it = m_cfg.begin(); it != m_cfg.end(); it++) { + out << " " << (*it).first << ": " << (*it).second << endl; + } +} + +// Actions +''') + + for action in self.actions.itervalues(): + if "c_code" not in action: + continue + + code(''' +/** \\brief ${{action.desc}} */ +void $c_ident::${{action.ident}}(const Address& addr) +{ + DEBUG_MSG(GENERATED_COMP, HighPrio, "executing"); + ${{action["c_code"]}} +} + +''') + code.write(path, "%s.cc" % c_ident) + + def printCWakeup(self, path): + '''Output the wakeup loop for the events''' + + code = code_formatter() + ident = self.ident + + code(''' +// Auto generated C++ code started by $__file__:$__line__ +// ${ident}: ${{self.short}} + +#include "mem/ruby/common/Global.hh" +#include "mem/ruby/slicc_interface/RubySlicc_includes.hh" +#include "mem/protocol/${ident}_Controller.hh" +#include "mem/protocol/${ident}_State.hh" +#include "mem/protocol/${ident}_Event.hh" +#include "mem/protocol/Types.hh" +#include "mem/ruby/system/System.hh" + +void ${ident}_Controller::wakeup() +{ + + int counter = 0; + while (true) { + // Some cases will put us into an infinite loop without this limit + assert(counter <= m_transitions_per_cycle); + if (counter == m_transitions_per_cycle) { + g_system_ptr->getProfiler()->controllerBusy(m_machineID); // Count how often we\'re fully utilized + g_eventQueue_ptr->scheduleEvent(this, 1); // Wakeup in another cycle and try again + break; + } +''') + + code.indent() + code.indent() + + # InPorts + # + # Find the position of the mandatory queue in the vector so + # that we can print it out first + + mandatory_q = None + if self.ident == "L1Cache": + for i,port in enumerate(self.in_ports): + assert "c_code_in_port" in port + if str(port).find("mandatoryQueue_in") >= 0: + assert mandatory_q is None + mandatory_q = port + + assert mandatory_q is not None + + # print out the mandatory queue here + port = mandatory_q + code('// ${ident}InPort $port') + output = port["c_code_in_port"] + + code('$output') + + for port in self.in_ports: + # don't print out mandatory queue twice + if port == mandatory_q: + continue + + if ident == "L1Cache": + if (str(port).find("forwardRequestNetwork_in") >= 0 or str(port).find("requestNetwork_in") >= 0 or str(port).find("requestIntraChipL1Network_in") >= 0): + code(''' +bool postpone = false; +if ((((*m_L1Cache_forwardToCache_ptr)).isReady())) { + const RequestMsg* in_msg_ptr; + in_msg_ptr = dynamic_cast<const RequestMsg*>(((*m_L1Cache_forwardToCache_ptr)).peek()); + if ((((servicing_atomic > 0) && (locked_read_request1 == ((*in_msg_ptr)).m_Address || locked_read_request2 == ((*in_msg_ptr)).m_Address || locked_read_request3 == ((*in_msg_ptr)).m_Address || locked_read_request1 == ((*in_msg_ptr)).m_Address)))) { + postpone = true; + } +} +if (!postpone) { +''') + code.indent() + code('// ${ident}InPort $port') + code('${{port["c_code_in_port"]}}') + code.dedent() + + if ident == "L1Cache": + if (str(port).find("forwardRequestNetwork_in") >= 0 or str(port).find("requestNetwork_in") >= 0 or str(port).find("requestIntraChipL1Network_in") >= 0): + code.dedent() + code('}') + code.indent() + code('') + + code.dedent() + code.dedent() + code(''' + break; // If we got this far, we have nothing left todo + } +} +''') + + if self.ident == "L1Cache": + code(''' +void ${ident}_Controller::set_atomic(Address addr) +{ + servicing_atomic++; + switch (servicing_atomic) { + case(1): + assert(locked_read_request1 == Address(-1)); + locked_read_request1 = addr; + break; + case(2): + assert(locked_read_request2 == Address(-1)); + locked_read_request2 = addr; + break; + case(3): + assert(locked_read_request3 == Address(-1)); + locked_read_request3 = addr; + break; + case(4): + assert(locked_read_request4 == Address(-1)); + locked_read_request4 = addr; + break; + default: + assert(0); + + } +} + +void ${ident}_Controller::clear_atomic(Address addr) +{ + + assert(servicing_atomic > 0); + if (addr == locked_read_request1) + locked_read_request1 = Address(-1); + else if (addr == locked_read_request2) + locked_read_request2 = Address(-1); + else if (addr == locked_read_request3) + locked_read_request3 = Address(-1); + else if (addr == locked_read_request4) + locked_read_request4 = Address(-1); + else + assert(0); + servicing_atomic--; + +} + +void ${ident}_Controller::reset_atomics() +{ + + servicing_atomic = 0; + locked_read_request1 = Address(-1); + locked_read_request2 = Address(-1); + locked_read_request3 = Address(-1); + locked_read_request4 = Address(-1); + +} + +''') + else: + code(''' +void ${ident}_Controller::reset_atomics() +{ + assert(0); +} + +void ${ident}_Controller::set_atomic(Address addr) +{ + assert(0); +} + +void ${ident}_Controller::clear_atomic(Address addr) +{ + assert(0); +} +''') + + + code.write(path, "%s_Wakeup.cc" % self.ident) + + def printCSwitch(self, path): + '''Output switch statement for transition table''' + + code = code_formatter() + ident = self.ident + + code(''' +// Auto generated C++ code started by $__file__:$__line__ +// ${ident}: ${{self.short}} + +#include "mem/ruby/common/Global.hh" +#include "mem/protocol/${ident}_Controller.hh" +#include "mem/protocol/${ident}_State.hh" +#include "mem/protocol/${ident}_Event.hh" +#include "mem/protocol/Types.hh" +#include "mem/ruby/system/System.hh" + +#define HASH_FUN(state, event) ((int(state)*${ident}_Event_NUM)+int(event)) + +#define GET_TRANSITION_COMMENT() (${ident}_transitionComment.str()) +#define CLEAR_TRANSITION_COMMENT() (${ident}_transitionComment.str("")) + +TransitionResult ${ident}_Controller::doTransition(${ident}_Event event, ${ident}_State state, const Address& addr +) +{ + ${ident}_State next_state = state; + + DEBUG_NEWLINE(GENERATED_COMP, MedPrio); + DEBUG_MSG(GENERATED_COMP, MedPrio, *this); + DEBUG_EXPR(GENERATED_COMP, MedPrio, g_eventQueue_ptr->getTime()); + DEBUG_EXPR(GENERATED_COMP, MedPrio,state); + DEBUG_EXPR(GENERATED_COMP, MedPrio,event); + DEBUG_EXPR(GENERATED_COMP, MedPrio,addr); + + TransitionResult result = doTransitionWorker(event, state, next_state, addr); + + if (result == TransitionResult_Valid) { + DEBUG_EXPR(GENERATED_COMP, MedPrio, next_state); + DEBUG_NEWLINE(GENERATED_COMP, MedPrio); + s_profiler.countTransition(state, event); + if (Debug::getProtocolTrace()) { + g_system_ptr->getProfiler()->profileTransition("${ident}", m_version, addr, + ${ident}_State_to_string(state), + ${ident}_Event_to_string(event), + ${ident}_State_to_string(next_state), GET_TRANSITION_COMMENT()); + } + CLEAR_TRANSITION_COMMENT(); + ${ident}_setState(addr, next_state); + + } else if (result == TransitionResult_ResourceStall) { + if (Debug::getProtocolTrace()) { + g_system_ptr->getProfiler()->profileTransition("${ident}", m_version, addr, + ${ident}_State_to_string(state), + ${ident}_Event_to_string(event), + ${ident}_State_to_string(next_state), + "Resource Stall"); + } + } else if (result == TransitionResult_ProtocolStall) { + DEBUG_MSG(GENERATED_COMP, HighPrio, "stalling"); + DEBUG_NEWLINE(GENERATED_COMP, MedPrio); + if (Debug::getProtocolTrace()) { + g_system_ptr->getProfiler()->profileTransition("${ident}", m_version, addr, + ${ident}_State_to_string(state), + ${ident}_Event_to_string(event), + ${ident}_State_to_string(next_state), + "Protocol Stall"); + } + } + + return result; +} + +TransitionResult ${ident}_Controller::doTransitionWorker(${ident}_Event event, ${ident}_State state, ${ident}_State& next_state, const Address& addr +) +{ + switch(HASH_FUN(state, event)) { +''') + + # This map will allow suppress generating duplicate code + cases = orderdict() + + for trans in self.transitions: + case_string = "%s_State_%s, %s_Event_%s" % \ + (self.ident, trans.state.ident, self.ident, trans.event.ident) + + case = code_formatter() + # Only set next_state if it changes + if trans.state != trans.nextState: + ns_ident = trans.nextState.ident + case('next_state = ${ident}_State_${ns_ident};') + + actions = trans.actions + + # Check for resources + case_sorter = [] + res = trans.resources + for key,val in res.iteritems(): + if key.type.ident != "DNUCAStopTable": + val = ''' +if (!%s.areNSlotsAvailable(%s)) { + return TransitionResult_ResourceStall; +} +''' % (key.code, val) + case_sorter.append(val) + + + # Emit the code sequences in a sorted order. This makes the + # output deterministic (without this the output order can vary + # since Map's keys() on a vector of pointers is not deterministic + for c in sorted(case_sorter): + case("$c") + + # Figure out if we stall + stall = False + for action in actions: + if action.ident == "z_stall": + stall = True + break + + if stall: + case('return TransitionResult_ProtocolStall;') + else: + for action in actions: + case('${{action.ident}}(addr);') + case('return TransitionResult_Valid;') + + case = str(case) + + # Look to see if this transition code is unique. + if case not in cases: + cases[case] = [] + + cases[case].append(case_string) + + # Walk through all of the unique code blocks and spit out the + # corresponding case statement elements + for case,transitions in cases.iteritems(): + # Iterative over all the multiple transitions that share + # the same code + for trans in transitions: + code(' case HASH_FUN($trans):') + code(' {') + code(' $case') + code(' }') + + code(''' + default: + WARN_EXPR(m_version); + WARN_EXPR(g_eventQueue_ptr->getTime()); + WARN_EXPR(addr); + WARN_EXPR(event); + WARN_EXPR(state); + ERROR_MSG(\"Invalid transition\"); + } + return TransitionResult_Valid; +} +''') + code.write(path, "%s_Transitions.cc" % self.ident) + + def printProfilerHH(self, path): + code = code_formatter() + ident = self.ident + + code(''' +// Auto generated C++ code started by $__file__:$__line__ +// ${ident}: ${{self.short}} + +#ifndef ${ident}_PROFILER_H +#define ${ident}_PROFILER_H + +#include "mem/ruby/common/Global.hh" +#include "mem/protocol/${ident}_State.hh" +#include "mem/protocol/${ident}_Event.hh" + +class ${ident}_Profiler { + public: + ${ident}_Profiler(); + void setVersion(int version); + void countTransition(${ident}_State state, ${ident}_Event event); + void possibleTransition(${ident}_State state, ${ident}_Event event); + void dumpStats(ostream& out) const; + void clearStats(); + + private: + int m_counters[${ident}_State_NUM][${ident}_Event_NUM]; + int m_event_counters[${ident}_Event_NUM]; + bool m_possible[${ident}_State_NUM][${ident}_Event_NUM]; + int m_version; +}; + +#endif // ${ident}_PROFILER_H +''') + code.write(path, "%s_Profiler.hh" % self.ident) + + def printProfilerCC(self, path): + code = code_formatter() + ident = self.ident + + code(''' +// Auto generated C++ code started by $__file__:$__line__ +// ${ident}: ${{self.short}} + +#include "mem/protocol/${ident}_Profiler.hh" + +${ident}_Profiler::${ident}_Profiler() +{ + for (int state = 0; state < ${ident}_State_NUM; state++) { + for (int event = 0; event < ${ident}_Event_NUM; event++) { + m_possible[state][event] = false; + m_counters[state][event] = 0; + } + } + for (int event = 0; event < ${ident}_Event_NUM; event++) { + m_event_counters[event] = 0; + } +} +void ${ident}_Profiler::setVersion(int version) +{ + m_version = version; +} +void ${ident}_Profiler::clearStats() +{ + for (int state = 0; state < ${ident}_State_NUM; state++) { + for (int event = 0; event < ${ident}_Event_NUM; event++) { + m_counters[state][event] = 0; + } + } + + for (int event = 0; event < ${ident}_Event_NUM; event++) { + m_event_counters[event] = 0; + } +} +void ${ident}_Profiler::countTransition(${ident}_State state, ${ident}_Event event) +{ + assert(m_possible[state][event]); + m_counters[state][event]++; + m_event_counters[event]++; +} +void ${ident}_Profiler::possibleTransition(${ident}_State state, ${ident}_Event event) +{ + m_possible[state][event] = true; +} +void ${ident}_Profiler::dumpStats(ostream& out) const +{ + out << " --- ${ident} " << m_version << " ---" << endl; + out << " - Event Counts -" << endl; + for (int event = 0; event < ${ident}_Event_NUM; event++) { + int count = m_event_counters[event]; + out << (${ident}_Event) event << " " << count << endl; + } + out << endl; + out << " - Transitions -" << endl; + for (int state = 0; state < ${ident}_State_NUM; state++) { + for (int event = 0; event < ${ident}_Event_NUM; event++) { + if (m_possible[state][event]) { + int count = m_counters[state][event]; + out << (${ident}_State) state << " " << (${ident}_Event) event << " " << count; + if (count == 0) { + out << " <-- "; + } + out << endl; + } + } + out << endl; + } +} +''') + code.write(path, "%s_Profiler.cc" % self.ident) + + # ************************** + # ******* HTML Files ******* + # ************************** + def frameRef(self, click_href, click_target, over_href, over_target_num, + text): + code = code_formatter(fix_newlines=False) + code("""<A href=\"$click_href\" target=\"$click_target\" onMouseOver=\"if (parent.frames[$over_target_num].location != parent.location + '$over_href') { parent.frames[$over_target_num].location='$over_href' }\" >${{html.formatShorthand(text)}}</A>""") + return str(code) + + def writeHTMLFiles(self, path): + # Create table with no row hilighted + self.printHTMLTransitions(path, None) + + # Generate transition tables + for state in self.states.itervalues(): + self.printHTMLTransitions(path, state) + + # Generate action descriptions + for action in self.actions.itervalues(): + name = "%s_action_%s.html" % (self.ident, action.ident) + code = html.createSymbol(action, "Action") + code.write(path, name) + + # Generate state descriptions + for state in self.states.itervalues(): + name = "%s_State_%s.html" % (self.ident, state.ident) + code = html.createSymbol(state, "State") + code.write(path, name) + + # Generate event descriptions + for event in self.events.itervalues(): + name = "%s_Event_%s.html" % (self.ident, event.ident) + code = html.createSymbol(event, "Event") + code.write(path, name) + + def printHTMLTransitions(self, path, active_state): + code = code_formatter() + + code(''' +<HTML><BODY link="blue" vlink="blue"> + +<H1 align="center">${{html.formatShorthand(self.short)}}: +''') + code.indent() + for i,machine in enumerate(self.symtab.getAllType(StateMachine)): + mid = machine.ident + if i != 0: + extra = " - " + else: + extra = "" + if machine == self: + code('$extra$mid') + else: + code('$extra<A target="Table" href="${mid}_table.html">$mid</A>') + code.dedent() + + code(""" +</H1> + +<TABLE border=1> +<TR> + <TH> </TH> +""") + + for event in self.events.itervalues(): + href = "%s_Event_%s.html" % (self.ident, event.ident) + ref = self.frameRef(href, "Status", href, "1", event.short) + code('<TH bgcolor=white>$ref</TH>') + + code('</TR>') + # -- Body of table + for state in self.states.itervalues(): + # -- Each row + if state == active_state: + color = "yellow" + else: + color = "white" + + click = "%s_table_%s.html" % (self.ident, state.ident) + over = "%s_State_%s.html" % (self.ident, state.ident) + text = html.formatShorthand(state.short) + ref = self.frameRef(click, "Table", over, "1", state.short) + code(''' +<TR> + <TH bgcolor=$color>$ref</TH> +''') + + # -- One column for each event + for event in self.events.itervalues(): + trans = self.table.get((state,event), None) + if trans is None: + # This is the no transition case + if state == active_state: + color = "#C0C000" + else: + color = "lightgrey" + + code('<TD bgcolor=$color> </TD>') + continue + + next = trans.nextState + stall_action = False + + # -- Get the actions + for action in trans.actions: + if action.ident == "z_stall" or \ + action.ident == "zz_recycleMandatoryQueue": + stall_action = True + + # -- Print out "actions/next-state" + if stall_action: + if state == active_state: + color = "#C0C000" + else: + color = "lightgrey" + + elif active_state and next.ident == active_state.ident: + color = "aqua" + elif state == active_state: + color = "yellow" + else: + color = "white" + + fix = code.nofix() + code('<TD bgcolor=$color>') + for action in trans.actions: + href = "%s_action_%s.html" % (self.ident, action.ident) + ref = self.frameRef(href, "Status", href, "1", + action.short) + code(' $ref\n') + if next != state: + if trans.actions: + code('/') + click = "%s_table_%s.html" % (self.ident, next.ident) + over = "%s_State_%s.html" % (self.ident, next.ident) + ref = self.frameRef(click, "Table", over, "1", next.short) + code("$ref") + code("</TD>\n") + code.fix(fix) + + # -- Each row + if state == active_state: + color = "yellow" + else: + color = "white" + + click = "%s_table_%s.html" % (self.ident, state.ident) + over = "%s_State_%s.html" % (self.ident, state.ident) + ref = self.frameRef(click, "Table", over, "1", state.short) + code(''' + <TH bgcolor=$color>$ref</TH> +</TR> +''') + code(''' +<TR> + <TH> </TH> +''') + + for event in self.events.itervalues(): + href = "%s_Event_%s.html" % (self.ident, event.ident) + ref = self.frameRef(href, "Status", href, "1", event.short) + code('<TH bgcolor=white>$ref</TH>') + code(''' +</TR> +</TABLE> +</BODY></HTML> +''') + + + if active_state: + name = "%s_table_%s.html" % (self.ident, active_state.ident) + else: + name = "%s_table.html" % self.ident + code.write(path, name) + +__all__ = [ "StateMachine" ] diff --git a/src/mem/slicc/symbols/Symbol.hh b/src/mem/slicc/symbols/Symbol.hh deleted file mode 100644 index 4a1c5e44e..000000000 --- a/src/mem/slicc/symbols/Symbol.hh +++ /dev/null @@ -1,100 +0,0 @@ - -/* - * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer; - * redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution; - * neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/* - * $Id$ - */ - -#ifndef SYMBOL_H -#define SYMBOL_H - -#include "mem/slicc/slicc_global.hh" -#include "mem/gems_common/Map.hh" -#include "mem/slicc/ast/Location.hh" - -class Symbol { -public: - // Constructors - Symbol(string id, const Location& location, const Map<string, string>& pairs); - Symbol(string id, const Location& location); - // Destructor - virtual ~Symbol() { } - - // Public Methods - void error(string err_msg) const { m_location.error(err_msg); } - void warning(string err_msg) const { m_location.warning(err_msg); } - const Location& getLocation() const { return m_location; } - - const string& toString() const { return m_id; } - - const string& getIdent() const { return m_id; } - const string& getShorthand() const { return lookupPair("short"); } - const string& getDescription() const { return lookupPair("desc"); } - - void markUsed() { m_used = true; } - bool wasUsed() { return m_used; } - - bool existPair(const string& key) const { return m_pairs.exist(key); } - const string& lookupPair(const string& key) const; - void addPair(const string& key, const string& value); - - // virtual string getCode() const = 0; - virtual void writeCFiles(string path) {} - virtual void writeHTMLFiles(string path) {} - virtual void print(ostream& out) const { out << "[Symbol: " << getIdent() << "]"; } - -private: - // Private Methods - - // Private copy constructor and assignment operator - // Symbol(const Symbol& obj); - // Symbol& operator=(const Symbol& obj); - - // Data Members (m_ prefix) - string m_id; - Map<string, string> m_pairs; - Location m_location; - bool m_used; -}; - -// Output operator declaration -ostream& operator<<(ostream& out, const Symbol& obj); - -// ******************* Definitions ******************* - -// Output operator definition -extern inline -ostream& operator<<(ostream& out, const Symbol& obj) -{ - obj.print(out); - out << flush; - return out; -} - -#endif //SYMBOL_H diff --git a/src/mem/slicc/symbols/Symbol.py b/src/mem/slicc/symbols/Symbol.py new file mode 100644 index 000000000..b394fda44 --- /dev/null +++ b/src/mem/slicc/symbols/Symbol.py @@ -0,0 +1,78 @@ +# Copyright (c) 1999-2008 Mark D. Hill and David A. Wood +# Copyright (c) 2009 The Hewlett-Packard Development Company +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer; +# redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution; +# neither the name of the copyright holders nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +from slicc.util import PairContainer + +class Symbol(PairContainer): + def __init__(self, symtab, ident, location, pairs=None): + super(Symbol, self).__init__() + + from slicc.util import Location + from slicc.symbols import SymbolTable + if not isinstance(symtab, SymbolTable): raise AttributeError + if not isinstance(ident, str): raise AttributeError + if not isinstance(location, Location): raise AttributeError + + self.symtab = symtab + self.ident = ident + self.location = location + if pairs: + self.pairs.update(getattr(pairs, "pairs", pairs)) + if "short" not in self: + self["short"] = self.ident + self.used = False + + def __repr__(self): + return "[Symbol: %s]" % self.ident + + def __str__(self): + return str(self.ident) + + def __setitem__(self, key, value): + if key in self.pairs: + self.warning("Pair key '%s' re-defined. new: '%s' old: '%s'", + key, value, self.pairs[key]) + super(Symbol, self).__setitem__(key, value) + + @property + def short(self): + return self["short"] + + @property + def desc(self): + return self["desc"] + + def error(self, message, *args): + self.location.error(message, *args) + + def warning(self, message, *args): + self.location.warning(message, *args) + + def writeHTMLFiles(self, path): + pass + +__all__ = [ "Symbol" ] diff --git a/src/mem/slicc/symbols/SymbolTable.cc b/src/mem/slicc/symbols/SymbolTable.cc deleted file mode 100644 index 8af3685f8..000000000 --- a/src/mem/slicc/symbols/SymbolTable.cc +++ /dev/null @@ -1,327 +0,0 @@ - -/* - * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer; - * redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution; - * neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/* - * SymbolTable.cc - * - * Description: See SymbolTable.hh - * - * $Id$ - * - * */ - -#include "mem/slicc/symbols/SymbolTable.hh" -#include "mem/slicc/generator/fileio.hh" -#include "mem/slicc/generator/html_gen.hh" -#include "mem/slicc/generator/mif_gen.hh" -#include "mem/slicc/symbols/Action.hh" - -SymbolTable g_sym_table; - -SymbolTable::SymbolTable() -{ - m_sym_map_vec.setSize(1); - m_depth = 0; - - { - Map<string, string> pairs; - pairs.add("enumeration", "yes"); - newSym(new Type("MachineType", Location(), pairs)); - } - - { - Map<string, string> pairs; - pairs.add("primitive", "yes"); - pairs.add("external", "yes"); - newSym(new Type("void", Location(), pairs)); - } -} - -SymbolTable::~SymbolTable() -{ - int size = m_sym_vec.size(); - for(int i=0; i<size; i++) { - delete m_sym_vec[i]; - } -} - -void SymbolTable::newSym(Symbol* sym_ptr) -{ - registerSym(sym_ptr->toString(), sym_ptr); - m_sym_vec.insertAtBottom(sym_ptr); // Holder for the allocated Sym objects. -} - -void SymbolTable::newMachComponentSym(Symbol* sym_ptr) -{ - // used to cheat-- that is, access components in other machines - StateMachine* mach_ptr = getStateMachine("current_machine"); - if (mach_ptr != NULL) { - m_machine_component_map_vec.lookup(mach_ptr->toString()).add(sym_ptr->toString(), sym_ptr); - } -} - -Var* SymbolTable::getMachComponentVar(string mach, string ident) -{ - Symbol* s = m_machine_component_map_vec.lookup(mach).lookup(ident); - return dynamic_cast<Var*>(s); -} - - -void SymbolTable::registerSym(string id, Symbol* sym_ptr) -{ - - // Check for redeclaration (in the current frame only) - if (m_sym_map_vec[m_depth].exist(id)) { - sym_ptr->error("Symbol '" + id + "' redeclared in same scope."); - } - // FIXME - warn on masking of a declaration in a previous frame - m_sym_map_vec[m_depth].add(id, sym_ptr); -} - -void SymbolTable::registerGlobalSym(string id, Symbol* sym_ptr) -{ - // Check for redeclaration (global frame only) - if (m_sym_map_vec[0].exist(id)) { - sym_ptr->error("Global symbol '" + id + "' redeclared in global scope."); - } - m_sym_map_vec[0].add(id, sym_ptr); -} - -Symbol* SymbolTable::getSym(string ident) const -{ - for (int i=m_depth; i>=0; i--) { - if (m_sym_map_vec[i].exist(ident)) { - return m_sym_map_vec[i].lookup(ident); - } - } - return NULL; -} - -void SymbolTable::newCurrentMachine(StateMachine* sym_ptr) -{ - registerGlobalSym(sym_ptr->toString(), sym_ptr); - registerSym("current_machine", sym_ptr); - m_sym_vec.insertAtBottom(sym_ptr); // Holder for the allocated Sym objects. - - Map<string, Symbol*> m; - m_machine_component_map_vec.add(sym_ptr->toString(),m); - -} - -Type* SymbolTable::getType(string ident) const -{ - return dynamic_cast<Type*>(getSym(ident)); -} - -Var* SymbolTable::getVar(string ident) const -{ - return dynamic_cast<Var*>(getSym(ident)); -} - -Func* SymbolTable::getFunc(string ident) const -{ - return dynamic_cast<Func*>(getSym(ident)); -} - -StateMachine* SymbolTable::getStateMachine(string ident) const -{ - return dynamic_cast<StateMachine*>(getSym(ident)); -} - -void SymbolTable::pushFrame() -{ - m_depth++; - m_sym_map_vec.expand(1); - m_sym_map_vec[m_depth].clear(); -} - -void SymbolTable::popFrame() -{ - m_depth--; - assert(m_depth >= 0); - m_sym_map_vec.expand(-1); -} - -void SymbolTable::writeCFiles(string path) const -{ - int size = m_sym_vec.size(); - { - // Write the Types.hh include file for the types - ostringstream sstr; - sstr << "/** Auto generated C++ code started by "<<__FILE__<<":"<<__LINE__<< " */" << endl; - sstr << endl; - sstr << "#include \"mem/ruby/slicc_interface/RubySlicc_includes.hh\"" << endl; - for(int i=0; i<size; i++) { - Type* type = dynamic_cast<Type*>(m_sym_vec[i]); - if (type != NULL && !type->isPrimitive()) { - sstr << "#include \"mem/protocol/" << type->cIdent() << ".hh" << "\"" << endl; - } - } - conditionally_write_file(path + "/Types.hh", sstr); - } - - // Write all the symbols - for(int i=0; i<size; i++) { - m_sym_vec[i]->writeCFiles(path + '/'); - } - - writeControllerFactory(path); -} - -void SymbolTable::writeControllerFactory(string path) const -{ - ostringstream sstr; - int size = m_sym_vec.size(); - - sstr << "/** \\file ControllerFactory.hh " << endl; - sstr << " * Auto generatred C++ code started by " << __FILE__ << ":" << __LINE__ << endl; - sstr << " */" << endl << endl; - - sstr << "#ifndef CONTROLLERFACTORY_H" << endl; - sstr << "#define CONTROLLERFACTORY_H" << endl; - sstr << endl; - - Vector< string > controller_types; - - // includes - sstr << "#include <string>" << endl; - sstr << "class Network;" << endl; - sstr << "class AbstractController;" << endl; - sstr << endl; - - sstr << "class ControllerFactory {" << endl; - sstr << "public:" << endl; - sstr << " static AbstractController* createController(const std::string & controller_type, const std::string & name);" << endl; - sstr << "};" << endl; - sstr << endl; - - sstr << "#endif // CONTROLLERFACTORY_H" << endl; - conditionally_write_file(path + "/ControllerFactory.hh", sstr); - - // ControllerFactory.cc file - - sstr.str(""); - - sstr << "/** \\file ControllerFactory.cc " << endl; - sstr << " * Auto generatred C++ code started by " << __FILE__ << ":" << __LINE__ << endl; - sstr << " */" << endl << endl; - - // includes - sstr << "#include \"mem/protocol/ControllerFactory.hh\"" << endl; - sstr << "#include \"mem/ruby/slicc_interface/AbstractController.hh\"" << endl; - sstr << "#include \"mem/protocol/MachineType.hh\"" << endl; - for(int i=0; i<size; i++) { - StateMachine* machine = dynamic_cast<StateMachine*>(m_sym_vec[i]); - if (machine != NULL) { - sstr << "#include \"mem/protocol/" << machine->getIdent() << "_Controller.hh\"" << endl; - controller_types.insertAtBottom(machine->getIdent()); - } - } - sstr << endl; - - sstr << "AbstractController* ControllerFactory::createController(const std::string & controller_type, const std::string & name) {" << endl; - for (int i=0;i<controller_types.size();i++) { - sstr << " if (controller_type == \"" << controller_types[i] << "\")" << endl; - sstr << " return new " << controller_types[i] << "_Controller(name);" << endl; - } - sstr << " assert(0); // invalid controller type" << endl; - sstr << " return NULL;" << endl; - sstr << "}" << endl; - conditionally_write_file(path + "/ControllerFactory.cc", sstr); -} - -Vector<StateMachine*> SymbolTable::getStateMachines() const -{ - Vector<StateMachine*> machine_vec; - int size = m_sym_vec.size(); - for(int i=0; i<size; i++) { - StateMachine* type = dynamic_cast<StateMachine*>(m_sym_vec[i]); - if (type != NULL) { - machine_vec.insertAtBottom(type); - } - } - return machine_vec; -} - -void SymbolTable::writeHTMLFiles(string path) const -{ - // Create index.html - { - ostringstream out; - createHTMLindex(path, out); - conditionally_write_file(path + "index.html", out); - } - - // Create empty.html - { - ostringstream out; - out << "<HTML></HTML>"; - conditionally_write_file(path + "empty.html", out); - } - - // Write all the symbols - int size = m_sym_vec.size(); - for(int i=0; i<size; i++) { - m_sym_vec[i]->writeHTMLFiles(path); - } -} - -void write_file(string filename, ostringstream& sstr) -{ - ofstream out; - - out.open(filename.c_str()); - out << sstr.str(); - out.close(); -} - -void SymbolTable::writeMIFFiles(string path) const -{ - int size = m_sym_vec.size(); - for(int i=0; i<size; i++) { - ostringstream states, events, actions, transitions; - StateMachine* machine = dynamic_cast<StateMachine*>(m_sym_vec[i]); - if (machine != NULL) { - printStateTableMIF(*machine, states); - write_file(path + machine->getIdent() + "_states.mif", states); - printEventTableMIF(*machine, events); - write_file(path + machine->getIdent() + "_events.mif", events); - printActionTableMIF(*machine, actions); - write_file(path + machine->getIdent() + "_actions.mif", actions); - printTransitionTableMIF(*machine, transitions); - write_file(path + machine->getIdent() + "_transitions.mif", transitions); - } - } -} - - -void SymbolTable::print(ostream& out) const -{ - out << "[SymbolTable]"; // FIXME -} diff --git a/src/mem/slicc/symbols/SymbolTable.hh b/src/mem/slicc/symbols/SymbolTable.hh deleted file mode 100644 index 90d3f48c3..000000000 --- a/src/mem/slicc/symbols/SymbolTable.hh +++ /dev/null @@ -1,121 +0,0 @@ - -/* - * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer; - * redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution; - * neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/* - * SymbolTable.hh - * - * Description: - * - * $Id$ - * - * */ - -#ifndef SYMBOLTABLE_H -#define SYMBOLTABLE_H - -#include "mem/slicc/slicc_global.hh" -#include "mem/gems_common/Map.hh" -#include "mem/gems_common/Vector.hh" - -#include "mem/slicc/symbols/Symbol.hh" -#include "mem/slicc/symbols/Type.hh" -#include "mem/slicc/symbols/Var.hh" -#include "mem/slicc/symbols/Func.hh" -#include "mem/slicc/symbols/StateMachine.hh" - -class SymbolTable; - -extern SymbolTable g_sym_table; - -class SymbolTable { -public: - // Constructors - SymbolTable(); - - // Destructor - ~SymbolTable(); - - // Public Methods - void newSym(Symbol* sym_ptr); - void registerSym(string id, Symbol* sym_ptr); - Symbol* getSym(string id) const; - - // used to cheat-- that is, access components in other machines - void newMachComponentSym(Symbol* sym_ptr); - Var* getMachComponentVar(string mach, string ident); - - void newCurrentMachine(StateMachine* machine_ptr); - StateMachine* getStateMachine(string ident) const; - StateMachine* getStateMachine() const { return getStateMachine("current_machine"); } - Type* getType(string ident) const; - - Var* getVar(string ident) const; - Func* getFunc(string ident) const; - - void pushFrame(); - void popFrame(); - - Vector<StateMachine*> getStateMachines() const; - - void writeCFiles(string path) const; - void writeHTMLFiles(string path) const; - void writeMIFFiles(string path) const; - - void print(ostream& out) const; -private: - // Private Methods - void registerGlobalSym(string id, Symbol* sym_ptr); - void writeControllerFactory(string path) const; - - // Private copy constructor and assignment operator - SymbolTable(const SymbolTable& obj); - SymbolTable& operator=(const SymbolTable& obj); - - // Data Members (m_ prefix) - Vector<Symbol*> m_sym_vec; - Vector<Map<string, Symbol*> > m_sym_map_vec; - Map<string, Map<string, Symbol*> > m_machine_component_map_vec; - int m_depth; -}; - -// Output operator declaration -ostream& operator<<(ostream& out, const SymbolTable& obj); - -// ******************* Definitions ******************* - -// Output operator definition -extern inline -ostream& operator<<(ostream& out, const SymbolTable& obj) -{ - obj.print(out); - out << flush; - return out; -} - -#endif //SYMBOLTABLE_H diff --git a/src/mem/slicc/symbols/SymbolTable.py b/src/mem/slicc/symbols/SymbolTable.py new file mode 100644 index 000000000..6b1bf13e6 --- /dev/null +++ b/src/mem/slicc/symbols/SymbolTable.py @@ -0,0 +1,221 @@ +# Copyright (c) 1999-2008 Mark D. Hill and David A. Wood +# Copyright (c) 2009 The Hewlett-Packard Development Company +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer; +# redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution; +# neither the name of the copyright holders nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +from m5.util import code_formatter + +from slicc.generate import html +from slicc.symbols.StateMachine import StateMachine +from slicc.symbols.Type import Type +from slicc.util import Location + +class SymbolTable(object): + def __init__(self): + self.sym_vec = [] + self.sym_map_vec = [ {} ] + self.machine_components = {} + + pairs = {} + pairs["enumeration"] = "yes" + MachineType = Type(self, "MachineType", Location("init", 0), pairs) + self.newSymbol(MachineType) + + pairs = {} + pairs["primitive"] = "yes" + pairs["external"] = "yes" + void = Type(self, "void", Location("init", 0), pairs) + self.newSymbol(void) + + def __repr__(self): + return "[SymbolTable]" # FIXME + + def newSymbol(self, sym): + self.registerSym(str(sym), sym) + self.sym_vec.append(sym) + + def registerSym(self, id, sym): + # Check for redeclaration (in the current frame only) + if id in self.sym_map_vec[-1]: + sym.error("Symbol '%s' redeclared in same scope.", id) + + # FIXME - warn on masking of a declaration in a previous frame + self.sym_map_vec[-1][id] = sym + + def find(self, ident, types=None): + for sym_map in reversed(self.sym_map_vec): + try: + symbol = sym_map[ident] + except KeyError: + continue + + if types is not None: + if not isinstance(symbol, types): + symbol.error("Symbol '%s' is not of types '%s'.", + symbol, + types) + + return symbol + + return None + + def newMachComponentSym(self, symbol): + # used to cheat-- that is, access components in other machines + machine = self.find("current_machine", StateMachine) + if machine: + self.machine_components[str(machine)][str(symbol)] = symbol + + def newCurrentMachine(self, sym): + self.registerGlobalSym(str(sym), sym) + self.registerSym("current_machine", sym) + self.sym_vec.append(sym) + + self.machine_components[str(sym)] = {} + + @property + def state_machine(self): + return self.find("current_machine", StateMachine) + + def pushFrame(self): + self.sym_map_vec.append({}) + + def popFrame(self): + assert len(self.sym_map_vec) > 0 + self.sym_map_vec.pop() + + def registerGlobalSym(self, ident, symbol): + # Check for redeclaration (global frame only) + if ident in self.sym_map_vec[0]: + symbol.error("Symbol '%s' redeclared in global scope." % ident) + + self.sym_map_vec[0][ident] = symbol + + def getAllType(self, type): + for symbol in self.sym_vec: + if isinstance(symbol, type): + yield symbol + + def writeCodeFiles(self, path): + code = code_formatter() + code(''' +/** Auto generated C++ code started by $__file__:$__line__ */ + +#include "mem/ruby/slicc_interface/RubySlicc_includes.hh" +''') + for symbol in self.sym_vec: + if isinstance(symbol, Type) and not symbol.isPrimitive: + code('#include "mem/protocol/${{symbol.c_ident}}.hh"') + + code.write(path, "Types.hh") + + for symbol in self.sym_vec: + symbol.writeCodeFiles(path) + + self.writeControllerFactory(path) + + def writeControllerFactory(self, path): + code = code_formatter() + + code(''' +/** \\file ControllerFactory.hh + * Auto generatred C++ code started by $__file__:$__line__ + */ + +#ifndef CONTROLLERFACTORY_H +#define CONTROLLERFACTORY_H + +#include <string> +class Network; +class AbstractController; + +class ControllerFactory { + public: + static AbstractController *createController(const std::string &controller_type, const std::string &name); +}; +#endif // CONTROLLERFACTORY_H''') + code.write(path, "ControllerFactory.hh") + + code = code_formatter() + code(''' +/** \\file ControllerFactory.cc + * Auto generatred C++ code started by $__file__:$__line__ + */ + +#include "mem/protocol/ControllerFactory.hh" +#include "mem/ruby/slicc_interface/AbstractController.hh" +#include "mem/protocol/MachineType.hh" +''') + + controller_types = [] + for symbol in self.getAllType(StateMachine): + code('#include "mem/protocol/${{symbol.ident}}_Controller.hh"') + controller_types.append(symbol.ident) + + code(''' +AbstractController *ControllerFactory::createController(const std::string &controller_type, const std::string &name) { +''') + + for ct in controller_types: + code(''' + if (controller_type == "$ct") + return new ${ct}_Controller(name); +''') + + code(''' + assert(0); // invalid controller type + return NULL; +} +''') + code.write(path, "ControllerFactory.cc") + + def writeHTMLFiles(self, path): + machines = list(self.getAllType(StateMachine)) + if len(machines) > 1: + name = "%s_table.html" % machines[0].ident + else: + name = "empty.html" + + code = code_formatter() + code(''' +<html> +<head> +<title>$path</title> +</head> +<frameset rows="*,30"> + <frame name="Table" src="$name"> + <frame name="Status" src="empty.html"> +</frameset> +</html> +''') + code.write(path, "index.html") + + code = code_formatter() + code("<HTML></HTML>") + code.write(path, "empty.html") + + for symbol in self.sym_vec: + symbol.writeHTMLFiles(path) + +__all__ = [ "SymbolTable" ] diff --git a/src/mem/slicc/symbols/Transition.cc b/src/mem/slicc/symbols/Transition.cc deleted file mode 100644 index d6d348166..000000000 --- a/src/mem/slicc/symbols/Transition.cc +++ /dev/null @@ -1,173 +0,0 @@ - -/* - * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer; - * redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution; - * neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/* - * $Id$ - * - * */ - -#include "mem/slicc/symbols/Transition.hh" -#include "mem/slicc/symbols/State.hh" -#include "mem/slicc/symbols/Event.hh" -#include "mem/slicc/symbols/Action.hh" -#include "mem/gems_common/util.hh" -#include "mem/slicc/symbols/Var.hh" - -Transition::Transition(string state, string event, string nextState, - const Vector<string>& actionList, - const Location& location, - const Map<string, string>& pairMap) - : Symbol(state + "|" + event, location, pairMap) -{ - m_state = state; - m_event = event; - m_nextState = nextState; - m_actionList = actionList; - - // Ptrs are undefined at this point - m_statePtr = NULL; - m_eventPtr = NULL; - m_nextStatePtr = NULL; - m_actionPtrsValid = false; -} - -void Transition::checkIdents(const Vector<State*>& states, - const Vector<Event*>& events, - const Vector<Action*>& actions) -{ - m_statePtr = findIndex(states, m_state); - m_eventPtr = findIndex(events, m_event); - m_nextStatePtr = findIndex(states, m_nextState); - - for(int i=0; i < m_actionList.size(); i++) { - Action* action_ptr = findIndex(actions, m_actionList[i]); - int size = action_ptr->getResources().keys().size(); - for (int j=0; j < size; j++) { - Var* var_ptr = action_ptr->getResources().keys()[j]; - if (var_ptr->getType()->cIdent() != "DNUCAStopTable") { - int num = atoi((action_ptr->getResources().lookup(var_ptr)).c_str()); - if (m_resources.exist(var_ptr)) { - num += atoi((m_resources.lookup(var_ptr)).c_str()); - } - m_resources.add(var_ptr, int_to_string(num)); - } else { - m_resources.add(var_ptr, action_ptr->getResources().lookup(var_ptr)); - } - } - m_actionPtrs.insertAtBottom(action_ptr); - } - m_actionPtrsValid = true; -} - -const string& Transition::getStateShorthand() const -{ - assert(m_statePtr != NULL); - return m_statePtr->getShorthand(); -} - -const string& Transition::getEventShorthand() const -{ - assert(m_eventPtr != NULL); - return m_eventPtr->getShorthand(); -} - -const string& Transition::getNextStateShorthand() const -{ - assert(m_nextStatePtr != NULL); - return m_nextStatePtr->getShorthand(); -} - -string Transition::getActionShorthands() const -{ - assert(m_actionPtrsValid); - string str; - int numActions = m_actionPtrs.size(); - for (int i=0; i<numActions; i++) { - str += m_actionPtrs[i]->getShorthand(); - } - return str; -} - -void Transition::print(ostream& out) const -{ - out << "[Transition: "; - out << "(" << m_state; - if (m_statePtr != NULL) { - out << ":" << *m_statePtr; - } - out << ", " << m_event; - if (m_eventPtr != NULL) { - out << ":" << *m_eventPtr; - } - out << ") -> "; - out << m_nextState; - if (m_nextStatePtr != NULL) { - out << ":" << *m_nextStatePtr; - } - out << ", "; - out << m_actionList; - out << "]"; -} - -Event* Transition::findIndex(const Vector<Event*>& vec, string ident) -{ - int size = vec.size(); - for(int i=0; i<size; i++) { - if (ident == vec[i]->getIdent()) { - return vec[i]; - } - } - error("Event not found: " + ident); - return NULL; -} - -State* Transition::findIndex(const Vector<State*>& vec, string ident) -{ - int size = vec.size(); - for(int i=0; i<size; i++) { - if (ident == vec[i]->getIdent()) { - return vec[i]; - } - } - error("State not found: " + ident); - return NULL; -} - -Action* Transition::findIndex(const Vector<Action*>& vec, string ident) -{ - int size = vec.size(); - for(int i=0; i<size; i++) { - if (ident == vec[i]->getIdent()) { - return vec[i]; - } - } - error("Action not found: " + ident); - return NULL; -} - diff --git a/src/mem/slicc/symbols/Transition.hh b/src/mem/slicc/symbols/Transition.hh deleted file mode 100644 index 75d6da4e9..000000000 --- a/src/mem/slicc/symbols/Transition.hh +++ /dev/null @@ -1,120 +0,0 @@ - -/* - * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer; - * redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution; - * neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/* - * Transition.hh - * - * Description: - * - * $Id$ - * - * */ - -#ifndef TRANSITION_H -#define TRANSITION_H - -#include "mem/slicc/slicc_global.hh" -#include "mem/gems_common/Vector.hh" -#include "mem/slicc/symbols/Symbol.hh" - -class State; -class Event; -class Action; -class Var; - -class Transition : public Symbol { -public: - // Constructors - Transition(string state, string event, string nextState, - const Vector<string>& actionList, - const Location& location, - const Map<string, string>& pairMap); - // Destructor - ~Transition() { } - - // Public Methods - State* getStatePtr() const { assert(m_statePtr != NULL); return m_statePtr; } - Event* getEventPtr() const { assert(m_eventPtr != NULL); return m_eventPtr; } - State* getNextStatePtr() const { assert(m_nextStatePtr != NULL); return m_nextStatePtr; } - - // int getStateIndex() const { assert(m_statePtr != NULL); return m_statePtr->getIndex(); } - // int getEventIndex() const { assert(m_eventPtr != NULL); return m_eventPtr->getIndex(); } - // int getNextStateIndex() const { assert(m_nextStatePtr != NULL); return m_nextStatePtr->getIndex(); } - void checkIdents(const Vector<State*>& states, - const Vector<Event*>& events, - const Vector<Action*>& actions); - - const string& getStateShorthand() const; - const string& getEventShorthand() const; - const string& getNextStateShorthand() const; - string getActionShorthands() const; - const Vector<Action*>& getActions() const { assert(m_actionPtrsValid); return m_actionPtrs; } - const Map<Var*, string>& getResources() const { assert(m_actionPtrsValid); return m_resources; } - - void print(ostream& out) const; - - // Default copy constructor and assignment operator - // Transition(const Transition& obj); - // Transition& operator=(const Transition& obj); -private: - // Private Methods - Event* findIndex(const Vector<Event*>& vec, string ident); - State* findIndex(const Vector<State*>& vec, string ident); - Action* findIndex(const Vector<Action*>& vec, string ident); - - // Data Members (m_ prefix) - string m_state; - string m_event; - string m_nextState; - - State* m_statePtr; - Event* m_eventPtr; - State* m_nextStatePtr; - - Vector<string> m_actionList; - Vector<Action*> m_actionPtrs; - Map<Var*, string> m_resources; - bool m_actionPtrsValid; -}; - -// Output operator declaration -ostream& operator<<(ostream& out, const Transition& obj); - -// ******************* Definitions ******************* - -// Output operator definition -extern inline -ostream& operator<<(ostream& out, const Transition& obj) -{ - obj.print(out); - out << flush; - return out; -} - -#endif //TRANSITION_H diff --git a/src/mem/slicc/symbols/Transition.py b/src/mem/slicc/symbols/Transition.py new file mode 100644 index 000000000..1bf09048a --- /dev/null +++ b/src/mem/slicc/symbols/Transition.py @@ -0,0 +1,61 @@ +# Copyright (c) 1999-2008 Mark D. Hill and David A. Wood +# Copyright (c) 2009 The Hewlett-Packard Development Company +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer; +# redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution; +# neither the name of the copyright holders nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +from slicc.symbols.Symbol import Symbol + +class Transition(Symbol): + def __init__(self, table, machine, state, event, nextState, actions, + location, pairs): + ident = "%s|%s" % (state, event) + super(Transition, self).__init__(table, ident, location, pairs) + + self.state = machine.states[state] + self.event = machine.events[event] + self.nextState = machine.states[nextState] + self.actions = [ machine.actions[a] for a in actions ] + self.resources = {} + + for action in self.actions: + for var,value in action.resources.iteritems(): + if var.type.ident != "DNUCAStopTable": + num = int(value) + if var in self.resources: + num += int(value) + self.resources[var] = str(num) + else: + self.resources[var] = value + + def __repr__(self): + return "[Transition: (%r, %r) -> %r, %r]" % \ + (self.state, self.event, self.nextState, self.actions) + + def getActionShorthands(self): + assert self.actions + + return ''.join(a.short for a in self.actions) + +__all__ = [ "Transition" ] diff --git a/src/mem/slicc/symbols/Type.cc b/src/mem/slicc/symbols/Type.cc deleted file mode 100644 index 5afe53423..000000000 --- a/src/mem/slicc/symbols/Type.cc +++ /dev/null @@ -1,779 +0,0 @@ - -/* - * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer; - * redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution; - * neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/* - * Type.cc - * - * Description: See Type.hh - * - * $Id$ - * */ - -#include "mem/slicc/symbols/Type.hh" -#include "mem/slicc/generator/fileio.hh" -#include "mem/gems_common/Map.hh" -#include "mem/slicc/symbols/StateMachine.hh" - -Type::Type(string id, const Location& location, - const Map<string, string>& pairs, - StateMachine* machine_ptr) - : Symbol(id, location, pairs) -{ - if (machine_ptr == NULL) { - m_c_id = id; - } else if (isExternal() || isPrimitive()) { - if (existPair("external_name")) { - m_c_id = lookupPair("external_name"); - } else { - m_c_id = id; - } - } else { - m_c_id = machine_ptr->toString() + "_" + id; // Append with machine name - } - - if(existPair("desc")){ - m_desc = lookupPair("desc"); - } else { - m_desc = "No description avaliable"; - } - - // check for interface that this Type implements - if(existPair("interface")) { - string interface = lookupPair("interface"); - if(interface == "Message" || interface == "NetworkMessage") { - addPair("message", "yes"); - } - if(interface == "NetworkMessage") { - addPair("networkmessage", "yes"); - } - } - - // FIXME - all of the following id comparisons are fragile hacks - if ((getIdent() == "CacheMemory") || (getIdent() == "NewCacheMemory") || - (getIdent() == "TLCCacheMemory") || (getIdent() == "DNUCACacheMemory") || - (getIdent() == "DNUCABankCacheMemory") || (getIdent() == "L2BankCacheMemory") || - (getIdent() == "CompressedCacheMemory") || (getIdent() == "PrefetchCacheMemory")) { - addPair("cache", "yes"); - } - - if ((getIdent() == "TBETable") || (getIdent() == "DNUCATBETable") || (getIdent() == "DNUCAStopTable")) { - addPair("tbe", "yes"); - } - - if ((getIdent() == "NewTBETable")) { - addPair("newtbe", "yes"); - } - - if ((getIdent() == "TimerTable")) { - addPair("timer", "yes"); - } - - if ((getIdent() == "DirectoryMemory")) { - addPair("dir", "yes"); - } - - if ((getIdent() == "PersistentTable")) { - addPair("persistent", "yes"); - } - - if ((getIdent() == "Prefetcher")) { - addPair("prefetcher", "yes"); - } - - if ((getIdent() == "DNUCA_Movement")) { - addPair("mover", "yes"); - } - - if (id == "MachineType") { - m_isMachineType = true; - } else { - m_isMachineType = false; - } -} - -// Return false on error -bool Type::dataMemberAdd(string id, Type* type_ptr, Map<string, string>& pairs, - string* init_code) -{ - if (dataMemberExist(id)) { - return false; // Error - } else { - m_data_member_map.add(id, type_ptr); - m_data_member_ident_vec.insertAtBottom(id); - m_data_member_type_vec.insertAtBottom(type_ptr); - m_data_member_pairs_vec.insertAtBottom(pairs); - m_data_member_init_code_vec.insertAtBottom(init_code); - } - - return true; -} - -string Type::methodId(string name, - const Vector<Type*>& param_type_vec) -{ - string paramStr = ""; - for (int i = 0; i < param_type_vec.size(); i++) { - paramStr += "_"+param_type_vec[i]->cIdent(); - } - return name+paramStr; -} - -bool Type::methodAdd(string name, - Type* return_type_ptr, - const Vector<Type*>& param_type_vec) -{ - string id = methodId(name, param_type_vec); - if (methodExist(id)) { - return false; // Error - } else { - m_method_return_type_map.add(id, return_type_ptr); - m_method_param_type_map.add(id, param_type_vec); - return true; - } -} - -bool Type::enumAdd(string id, Map<string, string> pairs_map) -{ - if (enumExist(id)) { - return false; - } else { - m_enum_map.add(id, true); - m_enum_vec.insertAtBottom(id); - m_enum_pairs.insertAtBottom(pairs_map); - - // Add default - if (!existPair("default")) { - addPair("default", cIdent()+"_NUM"); - } - - return true; - } -} - -void Type::writeCFiles(string path) -{ - if (isExternal()) { - // Do nothing - } else if (isEnumeration()) { - printEnumH(path); - printEnumC(path); - } else { // User defined structs and messages - printTypeH(path); - printTypeC(path); - } -} - -void Type::printTypeH(string path) const -{ - ostringstream out; - int size = m_data_member_type_vec.size(); - string type_name = cIdent(); // Identifier for the type in C - - // Header - out << "/** \\file " << type_name << ".hh" << endl; - out << " * " << endl; - out << " * Auto generated C++ code started by "<<__FILE__<<":"<<__LINE__<< endl; - out << " */" << endl; - out << endl; - out << "#ifndef " << type_name << "_H" << endl; - out << "#define " << type_name << "_H" << endl; - out << endl; - - // Include all of the #includes needed - out << "#include \"mem/ruby/common/Global.hh\"" << endl; - out << "#include \"mem/gems_common/Allocator.hh\"" << endl; - for (int i=0; i < size; i++) { - Type* type = m_data_member_type_vec[i]; - if (!type->isPrimitive()) { - out << "#include \"mem/protocol/" << type->cIdent() << ".hh" << "\"" << endl; - } - } - string interface = ""; - if(existPair("interface")) { - interface = lookupPair("interface"); - out << "#include \"mem/protocol/" << interface << ".hh\"" << endl; - } - - // Class definition - out << "class " << type_name; - - if(interface != "") { - out << " : public " << interface ; - } - - out << " {" << endl; - out << "public:" << endl; - - // ******** Default constructor ******** - - out << " " << type_name << "() " << endl; - - // Call superclass constructor - if (interface != "") { - out << " : " << interface << "()" << endl; - } - - out << " {" << endl; - - if(!isGlobal()) { - for (int i=0; i < size; i++) { - - Type* type_ptr = m_data_member_type_vec[i]; - string id = m_data_member_ident_vec[i]; - if (m_data_member_pairs_vec[i].exist("default")) { - // look for default value - string default_value = m_data_member_pairs_vec[i].lookup("default"); - out << " m_" << id << " = " << default_value << "; // default for this field " << endl; - } else if (type_ptr->hasDefault()) { - // Look for the type default - string default_value = type_ptr->getDefault(); - out << " m_" << id << " = " << default_value << "; // default value of " << type_ptr->cIdent() << endl; - } else { - out << " // m_" << id << " has no default" << endl; - } - } - } // end of if(!isGlobal()) - out << " }" << endl; - - // ******** Default destructor ******** - out << " "; - out << "~" << type_name << "() { };" << endl; - - // ******** Full init constructor ******** - if(! isGlobal()) { - out << " " << type_name << "("; - - for (int i=0; i < size; i++) { - if (i != 0) { - out << ", "; - } - Type* type = m_data_member_type_vec[i]; - string id = m_data_member_ident_vec[i]; - out << "const " << type->cIdent() << "& local_" << id; - } - - if (isMessage()) { - out << ", const unsigned local_proc_id" << flush; - } - - out << ")" << endl; - - // Call superclass constructor - if (interface != "") { - out << " : " << interface << "()" << endl; - } - - out << " {" << endl; - for (int i=0; i < size; i++) { - Type* type_ptr = m_data_member_type_vec[i]; - string id = m_data_member_ident_vec[i]; - out << " m_" << id << " = local_" << id << ";" << endl; - if (m_data_member_pairs_vec[i].exist("nextLineCallHack")) { - string next_line_value = m_data_member_pairs_vec[i].lookup("nextLineCallHack"); - out << " m_" << id << next_line_value << ";" << endl; - } - } - if (isMessage()) { - out << " proc_id = local_proc_id;" << endl << flush; - } - out << " }" << endl; - } // end of if(!isGlobal()) - - // create a static factory method - if (interface != "") { - out << " static " << interface << "* create() {" << endl; - out << " return new " << type_name << "(); " << endl; - out << " }" << endl; - } - - // bobba - - //******** Partial init constructor ******** - //** Constructor needs only the first n-1 data members for init - //** HACK to create objects with partially specified data members - //** Need to get rid of this and use hierarchy instead -// if(! isGlobal()) { -// out << " " << type_name << "("; - -// for (int i=0; i < size-1; i++) { -// if (i != 0) { -// out << ", "; -// } -// Type* type = m_data_member_type_vec[i]; -// string id = m_data_member_ident_vec[i]; -// out << "const " << type->cIdent() << "& local_" << id; -// } -// out << ")" << endl; - -// // Call superclass constructor -// if (interface != "") { -// out << " : " << interface << "()" << endl; -// } - -// out << " {" << endl; -// for (int i=0; i < size-1; i++) { -// Type* type_ptr = m_data_member_type_vec[i]; -// string id = m_data_member_ident_vec[i]; -// out << " m_" << id << " = local_" << id << ";" << endl; -// if (m_data_member_pairs_vec[i].exist("nextLineCallHack")) { -// string next_line_value = m_data_member_pairs_vec[i].lookup("nextLineCallHack"); -// out << " m_" << id << next_line_value << ";" << endl; -// } - -// } -// out << " }" << endl; -// } // end of if(!isGlobal()) - - // ******** Message member functions ******** - // FIXME: those should be moved into slicc file, slicc should support more of - // the c++ class inheritance - - if (isMessage()) { - out << " Message* clone() const { checkAllocator(); return s_allocator_ptr->allocate(*this); }" << endl; - out << " void destroy() { checkAllocator(); s_allocator_ptr->deallocate(this); }" << endl; - out << " static Allocator<" << type_name << ">* s_allocator_ptr;" << endl; - out << " static void checkAllocator() { if (s_allocator_ptr == NULL) { s_allocator_ptr = new Allocator<" << type_name << ">; }}" << endl; - } - - if(!isGlobal()) { - // const Get methods for each field - out << " // Const accessors methods for each field" << endl; - for (int i=0; i < size; i++) { - Type* type_ptr = m_data_member_type_vec[i]; - string type = type_ptr->cIdent(); - string id = m_data_member_ident_vec[i]; - out << "/** \\brief Const accessor method for " << id << " field." << endl; - out << " * \\return " << id << " field" << endl; - out << " */" << endl; - out << " const " << type << "& get" << id - << "() const { return m_" << id << "; }" << endl; - } - - out << endl; - - // Non-const Get methods for each field - out << " // Non const Accessors methods for each field" << endl; - for (int i=0; i < size; i++) { - Type* type_ptr = m_data_member_type_vec[i]; - string type = type_ptr->cIdent(); - string id = m_data_member_ident_vec[i]; - out << "/** \\brief Non-const accessor method for " << id << " field." << endl; - out << " * \\return " << id << " field" << endl; - out << " */" << endl; - out << " " << type << "& get" << id - << "() { return m_" << id << "; }" << endl; - } - - out << endl; - - // Set methods for each field - out << " // Mutator methods for each field" << endl; - for (int i=0; i < size; i++) { - Type* type_ptr = m_data_member_type_vec[i]; - string type = type_ptr->cIdent(); - string id = m_data_member_ident_vec[i]; - out << "/** \\brief Mutator method for " << id << " field */" << endl; - out << " void set" << id << "(const " << type << "& local_" - << id << ") { m_" << id << " = local_" << id << "; }" << endl; - } - - out << endl; - } // end of if(!isGlobal()) - - out << " void print(ostream& out) const;" << endl; - out << "//private:" << endl; - - // Data members for each field - for (int i=0; i < size; i++) { - if (!m_data_member_pairs_vec[i].exist("abstract")) { - out << " "; - // global structure - if(isGlobal()) out << "static const "; - - Type* type = m_data_member_type_vec[i]; - string id = m_data_member_ident_vec[i]; - out << type->cIdent() << " m_" << id; - - // init value - string* init_code = m_data_member_init_code_vec[i]; - if(init_code) { - // only global structure can have init value here - assert(isGlobal()); - out << " = " << *init_code << " "; - } - out << ";"; - if (m_data_member_pairs_vec[i].exist("desc")) { - string desc = m_data_member_pairs_vec[i].lookup("desc"); - out << " /**< " << desc << "*/"; - } - out << endl; - } - } - - if (isMessage()) { - out << " unsigned proc_id;" << endl << flush; - } - - out << "};" << endl; // End class - - out << "// Output operator declaration" << endl; - out << "ostream& operator<<(ostream& out, const " << type_name << "& obj);" << endl; - out << endl; - out << "// Output operator definition" << endl; - out << "extern inline" << endl; - out << "ostream& operator<<(ostream& out, const " << type_name << "& obj)" << endl; - out << "{" << endl; - out << " obj.print(out);" << endl; - out << " out << flush;" << endl; - out << " return out;" << endl; - out << "}" << endl; - out << endl; - out << "#endif // " << type_name << "_H" << endl; - - // Write it out - conditionally_write_file(path + type_name + ".hh", out); -} - -void Type::printTypeC(string path) const -{ - ostringstream out; - int size = m_data_member_type_vec.size(); - string type_name = cIdent(); // Identifier for the type in C - - // Header - out << "/** \\file " << type_name << ".cc" << endl; - out << " * " << endl; - out << " * Auto generated C++ code started by "<<__FILE__<<":"<<__LINE__<< endl; - out << " */" << endl; - out << endl; - out << "#include \"mem/protocol/" << type_name << ".hh\"" << endl; - out << endl; - if (isMessage()) { - out << "Allocator<" << type_name << ">* " << type_name << "::s_allocator_ptr = NULL;" << endl; - } - out << "/** \\brief Print the state of this object */" << endl; - out << "void " << type_name << "::print(ostream& out) const" << endl; - out << "{" << endl; - out << " out << \"[" << type_name << ": \";" << endl; - - // For each field - for (int i=0; i < size; i++) { - string id = m_data_member_ident_vec[i]; - out << " out << \"" << id << "=\" << m_" << id << " << \" \";" << endl; - } - - if (isMessage()) { - out << " out << \"" << "Time" << "=\" << getTime()" << " << \" \";" << endl; - } - - // Trailer - out << " out << \"]\";" << endl; - out << "}" << endl; - - // Write it out - conditionally_write_file(path + type_name + ".cc", out); -} - -void Type::printEnumH(string path) const -{ - ostringstream out; - int size = m_enum_vec.size(); - string type_name = cIdent(); // Identifier for the type in C - string type_desc = desc(); - - // Header - out << "/** \\file " << type_name << ".hh" << endl; - out << " * " << endl; - out << " * Auto generated C++ code started by "<<__FILE__<<":"<<__LINE__<< endl; - out << " */" << endl; - - out << "#ifndef " << type_name << "_H" << endl; - out << "#define " << type_name << "_H" << endl; - out << endl; - // Include all of the #includes needed - out << "#include \"mem/ruby/common/Global.hh\"" << endl; - out << endl; - - // Class definition - out << "/** \\enum " << type_name << endl; - out << " * \\brief " << type_desc << endl; - out << " */" << endl; - out << "enum " << type_name << " {" << endl; - - out << " " << type_name << "_FIRST," << endl; - - // For each field - for(int i = 0; i < size; i++ ) { - string id = m_enum_vec[i]; - string description; - if(m_enum_pairs[i].exist("desc")){ - description = m_enum_pairs[i].lookup("desc"); - } else { - description = "No description avaliable"; - } - if (i == 0) { - out << " " << type_name << "_" << id << " = " << type_name << "_FIRST, /**< " << description << " */" << endl; - } - else { - out << " " << type_name << "_" << id << ", /**< " << description << " */" << endl; - } - } - out << " " << type_name << "_NUM" << endl; - out << "};" << endl; - - // Code to convert from a string to the enumeration - out << type_name << " string_to_" << type_name << "(const string& str);" << endl; - - // Code to convert state to a string - out << "string " << type_name << "_to_string(const " << type_name << "& obj);" << endl; - - // Code to increment an enumeration type - out << type_name << " &operator++( " << type_name << " &e);" << endl; - - // MachineType hack used to set the base component id for each Machine - if (m_isMachineType) { - out << "int " << type_name << "_base_level(const " << type_name << "& obj);" << endl; - out << "MachineType " << type_name << "_from_base_level(int);" << endl; - out << "int " << type_name << "_base_number(const " << type_name << "& obj);" << endl; - out << "int " << type_name << "_base_count(const " << type_name << "& obj);" << endl; - // out << "int " << type_name << "_chip_count(const " << type_name << "& obj, int chipID);" << endl; - - for(int i = 0; i < size; i++ ) { - string id = m_enum_vec[i]; - out << "#define MACHINETYPE_" << id << " 1" << endl; - } - cout << endl; - } - - // Trailer - out << "ostream& operator<<(ostream& out, const " << type_name << "& obj);" << endl; - out << endl; - out << "#endif // " << type_name << "_H" << endl; - - // Write the file - conditionally_write_file(path + type_name + ".hh", out); -} - -void Type::printEnumC(string path) const -{ - ostringstream out; - int size = m_enum_vec.size(); - string type_name = cIdent(); // Identifier for the type in C - - // Header - out << "/** \\file " << type_name << ".hh" << endl; - out << " * " << endl; - out << " * Auto generated C++ code started by "<<__FILE__<<":"<<__LINE__<< endl; - out << " */" << endl; - - out << endl; - out << "#include \"mem/protocol/" << type_name << ".hh\"" << endl; - if (m_isMachineType) { - out << "#include \"mem/protocol/ControllerFactory.hh\"" << endl; - for( int i = 0; i<size; i++ ) { - out << "#include \"mem/protocol/" << m_enum_vec[i] << "_Controller.hh\"" << endl; - } - out << endl; - } - out << endl; - - // Code for output operator - out << "ostream& operator<<(ostream& out, const " << type_name << "& obj)" << endl; - out << "{" << endl; - out << " out << " << type_name << "_to_string(obj);" << endl; - out << " out << flush;" << endl; - out << " return out;" << endl; - out << "}" << endl; - - // Code to convert state to a string - out << endl; - out << "string " << type_name << "_to_string(const " << type_name << "& obj)" << endl; - out << "{" << endl; - out << " switch(obj) {" << endl; - - // For each field - for( int i = 0; i<size; i++ ) { - out << " case " << type_name << "_" << m_enum_vec[i] << ":" << endl; - out << " return \"" << m_enum_vec[i] << "\";" << endl; - } - - // Trailer - out << " default:" << endl; - out << " ERROR_MSG(\"Invalid range for type " << type_name << "\");" << endl; - out << " return \"\";" << endl; - out << " }" << endl; - out << "}" << endl; - - // Code to convert from a string to the enumeration - out << endl; - out << type_name << " string_to_" << type_name << "(const string& str)" << endl; - out << "{" << endl; - out << " if (false) {" << endl; - - // For each field - for( int i = 0; i<size; i++ ) { - out << " } else if (str == \"" << m_enum_vec[i] << "\") {" << endl; - out << " return " << type_name << "_" << m_enum_vec[i] << ";" << endl; - } - - out << " } else {" << endl; - out << " WARN_EXPR(str);" << endl; - out << " ERROR_MSG(\"Invalid string conversion for type " << type_name << "\");" << endl; - out << " }" << endl; - out << "}" << endl; - - // Code to increment an enumeration type - out << endl; - out << type_name << "& operator++( " << type_name << "& e) {" << endl; - out << " assert(e < " << type_name << "_NUM);" << endl; - out << " return e = " << type_name << "(e+1);" << endl; - out << "}" << endl; - - // MachineType hack used to set the base level and number of components for each Machine - if (m_isMachineType) { - out << endl; - out << "/** \\brief returns the base vector index for each machine type to be used by NetDest " << endl; - out << " * " << endl; - out << " * \\return the base vector index for each machine type to be used by NetDest" << endl; - out << " * \\see NetDest.hh" << endl; - out << " */" << endl; - out << "int " << type_name << "_base_level(const " << type_name << "& obj)" << endl; - out << "{" << endl; - out << " switch(obj) {" << endl; - - // For each field - Vector < string > MachineNames; - for( int i = 0; i<size; i++ ) { - out << " case " << type_name << "_" << m_enum_vec[i] << ":" << endl; - out << " return " << MachineNames.size() << ";" << endl; - MachineNames.insertAtBottom(m_enum_vec[i]); - } - - // total num - out << " case " << type_name << "_NUM:" << endl; - out << " return " << MachineNames.size() << ";" << endl; - - // Trailer - out << " default:" << endl; - out << " ERROR_MSG(\"Invalid range for type " << type_name << "\");" << endl; - out << " return -1;" << endl; - out << " }" << endl; - out << "}" << endl; - - out << "/** \\brief returns the machine type for each base vector index used by NetDest" << endl; - out << " * " << endl; - out << " * \\return the MachineTYpe" << endl; - out << " */" << endl; - out << "MachineType " << type_name << "_from_base_level(int type)" << endl; - out << "{" << endl; - out << " switch(type) {" << endl; - - // For each field - MachineNames.clear(); - for( int i = 0; i<size; i++ ) { - out << " case " << MachineNames.size() << ":" << endl; - out << " return " << type_name << "_" << m_enum_vec[i] << ";" << endl; - MachineNames.insertAtBottom(m_enum_vec[i]); - } - - // Trailer - out << " default:" << endl; - out << " ERROR_MSG(\"Invalid range for type " << type_name << "\");" << endl; - out << " return MachineType_NUM;" << endl; - out << " }" << endl; - out << "}" << endl; - - - out << endl; - out << "/** \\brief The return value indicates the number of components created" << endl; - out << " * before a particular machine's components" << endl; - out << " * " << endl; - out << " * \\return the base number of components for each machine" << endl; - out << " */" << endl; - out << "int " << type_name << "_base_number(const " << type_name << "& obj)" << endl; - out << "{" << endl; - out << " switch(obj) {" << endl; - - // For each field - MachineNames.clear(); - for( int i = 0; i<size; i++ ) { - out << " case " << type_name << "_" << m_enum_vec[i] << ":" << endl; - out << " return 0"; - for ( int m = 0; m<MachineNames.size(); m++) { - out << "+ " << MachineNames[m] << "_Controller::getNumControllers()"; - } - out << ";" << endl; - MachineNames.insertAtBottom(m_enum_vec[i]); - } - - // total num - out << " case " << type_name << "_NUM:" << endl; - out << " return 0"; - for ( int m = 0; m<MachineNames.size(); m++) { - out << "+ " << MachineNames[m] << "_Controller::getNumControllers()"; - } - out << ";" << endl; - - // Trailer - out << " default:" << endl; - out << " ERROR_MSG(\"Invalid range for type " << type_name << "\");" << endl; - out << " return -1;" << endl; - out << " }" << endl; - out << "}" << endl; - - - out << endl; - out << "/** \\brief returns the total number of components for each machine" << endl; - out << " * \\return the total number of components for each machine" << endl; - out << " */" << endl; - out << "int " << type_name << "_base_count(const " << type_name << "& obj)" << endl; - out << "{" << endl; - out << " switch(obj) {" << endl; - - // For each field - for( int i = 0; i<size; i++ ) { - out << " case " << type_name << "_" << m_enum_vec[i] << ":" << endl; - out << " return " << m_enum_vec[i] << "_Controller::getNumControllers();" << endl; - } - - // total num - out << " case " << type_name << "_NUM:" << endl; - // Trailer - out << " default:" << endl; - out << " ERROR_MSG(\"Invalid range for type " << type_name << "\");" << endl; - out << " return -1;" << endl; - out << " }" << endl; - out << "}" << endl; - - out << endl; - - } - - // Write the file - conditionally_write_file(path + type_name + ".cc", out); -} diff --git a/src/mem/slicc/symbols/Type.hh b/src/mem/slicc/symbols/Type.hh deleted file mode 100644 index 07d661d3c..000000000 --- a/src/mem/slicc/symbols/Type.hh +++ /dev/null @@ -1,155 +0,0 @@ - -/* - * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer; - * redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution; - * neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/* - * Type.hh - * - * Description: - * - * $Id$ - * - * */ - -#ifndef TYPE_H -#define TYPE_H - -#include "mem/slicc/slicc_global.hh" -#include "mem/gems_common/Map.hh" -#include "mem/slicc/symbols/Symbol.hh" - -class StateMachine; - -class Type : public Symbol { -public: - // Constructors - Type(string id, const Location& location, - const Map<string, string>& pairs, - StateMachine* machine_ptr = NULL); - - // Destructor - ~Type() {} - - // Public Methods - string cIdent() const { return m_c_id; } - string desc() const { return m_desc; } - - bool isPrimitive() const { return existPair("primitive"); } - bool isNetworkMessage() const { return existPair("networkmessage"); } - bool isMessage() const { return existPair("message"); } - bool isBuffer() const { return existPair("buffer"); } - bool isInPort() const { return existPair("inport"); } - bool isOutPort() const { return existPair("outport"); } - bool isEnumeration() const { return existPair("enumeration"); } - bool isExternal() const { return existPair("external"); } - bool isGlobal() const { return existPair("global"); } - bool isInterface() const { return existPair("interface"); } - - // The data members of this type - only valid for messages and SLICC - // declared structures - // Return false on error - bool dataMemberAdd(string id, Type* type_ptr, Map<string, string>& pairs, - string* init_code); - bool dataMemberExist(string id) const { return m_data_member_map.exist(id); } - Type* dataMemberType(string id) const { return m_data_member_map.lookup(id); } - - // The methods of this type - only valid for external types - // Return false on error - bool methodAdd(string name, Type* return_type_ptr, const Vector<Type*>& param_type_vec); - bool methodExist(string id) const { return m_method_return_type_map.exist(id); } - - string methodId(string name, const Vector<Type*>& param_type_vec); - Type* methodReturnType(string id) const { return m_method_return_type_map.lookup(id); } - const Vector<Type*>& methodParamType(string id) const { return m_method_param_type_map.lookup(id); } - - // The enumeration idents of this type - only valid for enums - // Return false on error - bool enumAdd(string id, Map<string, string> pairs); - bool enumExist(string id) const { return m_enum_map.exist(id); } - - // Write the C output files - void writeCFiles(string path) ; - - bool hasDefault() const { return existPair("default"); } - string getDefault() const { return lookupPair("default"); } - - void print(ostream& out) const {} -private: - // Private Methods - - void printTypeH(string path) const; - void printTypeC(string path) const; - void printEnumC(string path) const; - void printEnumH(string path) const; - - // Private copy constructor and assignment operator - Type(const Type& obj); - Type& operator=(const Type& obj); - - // Data Members (m_ prefix) - string m_c_id; - string m_desc; - - // Data Members - Map<string, Type*> m_data_member_map; - Vector<string> m_data_member_ident_vec; - Vector<Type*> m_data_member_type_vec; - Vector<Map<string, string> > m_data_member_pairs_vec; - Vector<string*> m_data_member_init_code_vec; - // Needs pairs here - - // Methods - Map<string, Type*> m_method_return_type_map; - Map<string, Vector<Type*> > m_method_param_type_map; - // Needs pairs here - - // Enum - Map<string, bool> m_enum_map; - Vector<string> m_enum_vec; - Vector< Map < string, string > > m_enum_pairs; - - // MachineType Hack - bool m_isMachineType; - -}; - -// Output operator declaration -ostream& operator<<(ostream& out, const Type& obj); - -// ******************* Definitions ******************* - -// Output operator definition -extern inline -ostream& operator<<(ostream& out, const Type& obj) -{ - obj.print(out); - out << flush; - return out; -} - -#endif //TYPE_H diff --git a/src/mem/slicc/symbols/Type.py b/src/mem/slicc/symbols/Type.py new file mode 100644 index 000000000..bafc6ea9e --- /dev/null +++ b/src/mem/slicc/symbols/Type.py @@ -0,0 +1,652 @@ +# Copyright (c) 1999-2008 Mark D. Hill and David A. Wood +# Copyright (c) 2009 The Hewlett-Packard Development Company +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer; +# redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution; +# neither the name of the copyright holders nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +from m5.util import code_formatter, orderdict + +from slicc.util import PairContainer +from slicc.symbols.Symbol import Symbol + +class DataMember(PairContainer): + def __init__(self, ident, type, pairs, init_code): + super(DataMember, self).__init__(pairs) + self.ident = ident + self.type = type + self.init_code = init_code + +class Enumeration(PairContainer): + def __init__(self, ident, pairs): + super(Enumeration, self).__init__(pairs) + self.ident = ident + +class Method(object): + def __init__(self, return_type, param_types): + self.return_type = return_type + self.param_types = param_types + +class Type(Symbol): + def __init__(self, table, ident, location, pairs, machine=None): + super(Type, self).__init__(table, ident, location, pairs) + self.c_ident = ident + if machine: + if self.isExternal or self.isPrimitive: + if "external_name" in self: + self.c_ident = self["external_name"] + else: + # Append with machine name + self.c_ident = "%s_%s" % (machine, ident) + + self.pairs.setdefault("desc", "No description avaliable") + + # check for interface that this Type implements + if "interface" in self: + interface = self["interface"] + if interface in ("Message", "NetworkMessage"): + self["message"] = "yes" + if interface == "NetworkMessage": + self["networkmessage"] = "yes" + + # FIXME - all of the following id comparisons are fragile hacks + if self.ident in ("CacheMemory", "NewCacheMemory", + "TLCCacheMemory", "DNUCACacheMemory", + "DNUCABankCacheMemory", "L2BankCacheMemory", + "CompressedCacheMemory", "PrefetchCacheMemory"): + self["cache"] = "yes" + + if self.ident in ("TBETable", "DNUCATBETable", "DNUCAStopTable"): + self["tbe"] = "yes" + + if self.ident == "NewTBETable": + self["newtbe"] = "yes" + + if self.ident == "TimerTable": + self["timer"] = "yes" + + if self.ident == "DirectoryMemory": + self["dir"] = "yes" + + if self.ident == "PersistentTable": + self["persistent"] = "yes" + + if self.ident == "Prefetcher": + self["prefetcher"] = "yes" + + if self.ident == "DNUCA_Movement": + self["mover"] = "yes" + + self.isMachineType = (ident == "MachineType") + + self.data_members = orderdict() + + # Methods + self.methods = {} + + # Enums + self.enums = orderdict() + + @property + def isPrimitive(self): + return "primitive" in self + @property + def isNetworkMessage(self): + return "networkmessage" in self + @property + def isMessage(self): + return "message" in self + @property + def isBuffer(self): + return "buffer" in self + @property + def isInPort(self): + return "inport" in self + @property + def isOutPort(self): + return "outport" in self + @property + def isEnumeration(self): + return "enumeration" in self + @property + def isExternal(self): + return "external" in self + @property + def isGlobal(self): + return "global" in self + @property + def isInterface(self): + return "interface" in self + + # Return false on error + def dataMemberAdd(self, ident, type, pairs, init_code): + if ident in self.data_members: + return False + + member = DataMember(ident, type, pairs, init_code) + self.data_members[ident] = member + + return True + + def dataMemberType(self, ident): + return self.data_members[ident].type + + def methodId(self, name, param_type_vec): + return '_'.join([name] + [ pt.c_ident for pt in param_type_vec ]) + + def methodAdd(self, name, return_type, param_type_vec): + ident = self.methodId(name, param_type_vec) + if ident in self.methods: + return False + + self.methods[ident] = Method(return_type, param_type_vec) + return True + + def enumAdd(self, ident, pairs): + if ident in self.enums: + return False + + self.enums[ident] = Enumeration(ident, pairs) + + # Add default + if "default" not in self: + self["default"] = "%s_NUM" % self.c_ident + + return True + + def writeCodeFiles(self, path): + if self.isExternal: + # Do nothing + pass + elif self.isEnumeration: + self.printEnumHH(path) + self.printEnumCC(path) + else: + # User defined structs and messages + self.printTypeHH(path) + self.printTypeCC(path) + + def printTypeHH(self, path): + code = code_formatter() + code(''' +/** \\file ${{self.c_ident}}.hh + * + * + * Auto generated C++ code started by $__file__:$__line__ + */ + +#ifndef ${{self.c_ident}}_H +#define ${{self.c_ident}}_H + +#include "mem/ruby/common/Global.hh" +#include "mem/gems_common/Allocator.hh" +''') + + for dm in self.data_members.values(): + if not dm.type.isPrimitive: + code('#include "mem/protocol/$0.hh"', dm.type.c_ident) + + parent = "" + if "interface" in self: + code('#include "mem/protocol/$0.hh"', self["interface"]) + parent = " : public %s" % self["interface"] + + code(''' +$klass ${{self.c_ident}}$parent { + public: + ${{self.c_ident}}() +''', klass="class") + + # Call superclass constructor + if "interface" in self: + code(' : ${{self["interface"]}}()') + + code.indent() + code("{") + if not self.isGlobal: + code.indent() + for dm in self.data_members.values(): + ident = dm.ident + if "default" in dm: + # look for default value + code('m_$ident = ${{dm["default"]}}; // default for this field') + elif "default" in dm.type: + # Look for the type default + tid = dm.type.c_ident + code('m_$ident = ${{dm.type["default"]}}; // default value of $tid') + else: + code('// m_$ident has no default') + code.dedent() + code('}') + + # ******** Default destructor ******** + code('~${{self.c_ident}}() { };') + + # ******** Full init constructor ******** + if not self.isGlobal: + params = [ 'const %s& local_%s' % (dm.type.c_ident, dm.ident) \ + for dm in self.data_members.itervalues() ] + + if self.isMessage: + params.append('const unsigned local_proc_id') + + params = ', '.join(params) + code('${{self.c_ident}}($params)') + + # Call superclass constructor + if "interface" in self: + code(' : ${{self["interface"]}}()') + + code('{') + code.indent() + for dm in self.data_members.values(): + code('m_${{dm.ident}} = local_${{dm.ident}};') + if "nextLineCallHack" in dm: + code('m_${{dm.ident}}${{dm["nextLineCallHack"]}};') + + if self.isMessage: + code('proc_id = local_proc_id;') + + code.dedent() + code('}') + + # create a static factory method + if "interface" in self: + code(''' +static ${{self["interface"]}}* create() { + return new ${{self.c_ident}}(); +} +''') + + # ******** Message member functions ******** + # FIXME: those should be moved into slicc file, slicc should + # support more of the c++ class inheritance + + if self.isMessage: + code(''' +Message* clone() const { checkAllocator(); return s_allocator_ptr->allocate(*this); } +void destroy() { checkAllocator(); s_allocator_ptr->deallocate(this); } +static Allocator<${{self.c_ident}}>* s_allocator_ptr; +static void checkAllocator() { if (s_allocator_ptr == NULL) { s_allocator_ptr = new Allocator<${{self.c_ident}}>; }} +''') + + if not self.isGlobal: + # const Get methods for each field + code('// Const accessors methods for each field') + for dm in self.data_members.values(): + code(''' +/** \\brief Const accessor method for ${{dm.ident}} field. + * \\return ${{dm.ident}} field + */ +const ${{dm.type.c_ident}}& get${{dm.ident}}() const { return m_${{dm.ident}}; } +''') + + # Non-const Get methods for each field + code('// Non const Accessors methods for each field') + for dm in self.data_members.values(): + code(''' +/** \\brief Non-const accessor method for ${{dm.ident}} field. + * \\return ${{dm.ident}} field + */ +${{dm.type.c_ident}}& get${{dm.ident}}() { return m_${{dm.ident}}; } +''') + + #Set methods for each field + code('// Mutator methods for each field') + for dm in self.data_members.values(): + code(''' +/** \\brief Mutator method for ${{dm.ident}} field */ +void set${{dm.ident}}(const ${{dm.type.c_ident}}& local_${{dm.ident}}) { m_${{dm.ident}} = local_${{dm.ident}}; } +''') + + code('void print(ostream& out) const;') + code.dedent() + code(' //private:') + code.indent() + + # Data members for each field + for dm in self.data_members.values(): + if "abstract" not in dm: + const = "" + init = "" + + # global structure + if self.isGlobal: + const = "static const " + + # init value + if dm.init_code: + # only global structure can have init value here + assert self.isGlobal + init = " = %s" % (dm.init_code) + + desc = "" + if "desc" in dm: + desc = '/**< %s */' % dm["desc"] + + code('$const${{dm.type.c_ident}} m_${{dm.ident}}$init; $desc') + + if self.isMessage: + code('unsigned proc_id;') + + code.dedent() + code('};') + + code(''' +// Output operator declaration +ostream& operator<<(ostream& out, const ${{self.c_ident}}& obj); + +// Output operator definition +extern inline +ostream& operator<<(ostream& out, const ${{self.c_ident}}& obj) +{ + obj.print(out); + out << flush; + return out; +} + +#endif // ${{self.c_ident}}_H +''') + + code.write(path, "%s.hh" % self.c_ident) + + def printTypeCC(self, path): + code = code_formatter() + + code(''' +/** \\file ${{self.c_ident}}.cc + * + * Auto generated C++ code started by $__file__:$__line__ + */ + +#include "mem/protocol/${{self.c_ident}}.hh" +''') + + if self.isMessage: + code('Allocator<${{self.c_ident}}>* ${{self.c_ident}}::s_allocator_ptr = NULL;') + code(''' +/** \\brief Print the state of this object */ +void ${{self.c_ident}}::print(ostream& out) const +{ + out << "[${{self.c_ident}}: "; +''') + + # For each field + code.indent() + for dm in self.data_members.values(): + code('out << "${{dm.ident}} = " << m_${{dm.ident}} << " ";''') + + if self.isMessage: + code('out << "Time = " << getTime() << " ";') + code.dedent() + + # Trailer + code(''' + out << "]"; +}''') + + code.write(path, "%s.cc" % self.c_ident) + + def printEnumHH(self, path): + code = code_formatter() + code(''' +/** \\file ${{self.c_ident}}.hh + * + * Auto generated C++ code started by $__file__:$__line__ + */ +#ifndef ${{self.c_ident}}_H +#define ${{self.c_ident}}_H + +#include "mem/ruby/common/Global.hh" + +/** \\enum ${{self.c_ident}} + * \\brief ${{self.desc}} + */ +enum ${{self.c_ident}} { + ${{self.c_ident}}_FIRST, +''') + + code.indent() + # For each field + for i,(ident,enum) in enumerate(self.enums.iteritems()): + desc = enum.get("desc", "No description avaliable") + if i == 0: + init = ' = %s_FIRST' % self.c_ident + else: + init = '' + code('${{self.c_ident}}_${{enum.ident}}$init, /**< $desc */') + code.dedent() + code(''' + ${{self.c_ident}}_NUM +}; +${{self.c_ident}} string_to_${{self.c_ident}}(const string& str); +string ${{self.c_ident}}_to_string(const ${{self.c_ident}}& obj); +${{self.c_ident}} &operator++(${{self.c_ident}} &e); +''') + + # MachineType hack used to set the base component id for each Machine + if self.isMachineType: + code(''' +int ${{self.c_ident}}_base_level(const ${{self.c_ident}}& obj); +MachineType ${{self.c_ident}}_from_base_level(int); +int ${{self.c_ident}}_base_number(const ${{self.c_ident}}& obj); +int ${{self.c_ident}}_base_count(const ${{self.c_ident}}& obj); +''') + + for enum in self.enums.itervalues(): + code('#define MACHINETYPE_${{enum.ident}} 1') + + # Trailer + code(''' +ostream& operator<<(ostream& out, const ${{self.c_ident}}& obj); + +#endif // ${{self.c_ident}}_H +''') + + code.write(path, "%s.hh" % self.c_ident) + + def printEnumCC(self, path): + code = code_formatter() + code(''' +/** \\file ${{self.c_ident}}.hh + * + * Auto generated C++ code started by $__file__:$__line__ + */ + +#include "mem/protocol/${{self.c_ident}}.hh" + +''') + + if self.isMachineType: + code('#include "mem/protocol/ControllerFactory.hh"') + for enum in self.enums.itervalues(): + code('#include "mem/protocol/${{enum.ident}}_Controller.hh"') + + code(''' +ostream& operator<<(ostream& out, const ${{self.c_ident}}& obj) +{ + out << ${{self.c_ident}}_to_string(obj); + out << flush; + return out; +} + +string ${{self.c_ident}}_to_string(const ${{self.c_ident}}& obj) +{ + switch(obj) { +''') + + # For each field + code.indent() + for enum in self.enums.itervalues(): + code(' case ${{self.c_ident}}_${{enum.ident}}:') + code(' return "${{enum.ident}}";') + code.dedent() + + # Trailer + code(''' + default: + ERROR_MSG("Invalid range for type ${{self.c_ident}}"); + return ""; + } +} + +${{self.c_ident}} string_to_${{self.c_ident}}(const string& str) +{ +''') + + # For each field + code.indent() + code("if (false) {") + start = "} else " + for enum in self.enums.itervalues(): + code('${start}if (str == "${{enum.ident}}") {') + code(' return ${{self.c_ident}}_${{enum.ident}};') + code.dedent() + + code(''' + } else { + WARN_EXPR(str); + ERROR_MSG("Invalid string conversion for type ${{self.c_ident}}"); + } +} + +${{self.c_ident}}& operator++(${{self.c_ident}}& e) { + assert(e < ${{self.c_ident}}_NUM); + return e = ${{self.c_ident}}(e+1); +} +''') + + # MachineType hack used to set the base level and number of + # components for each Machine + if self.isMachineType: + code(''' +/** \\brief returns the base vector index for each machine type to be used by NetDest + * + * \\return the base vector index for each machine type to be used by NetDest + * \\see NetDest.hh + */ +int ${{self.c_ident}}_base_level(const ${{self.c_ident}}& obj) +{ + switch(obj) { +''') + + # For each field + code.indent() + for i,enum in enumerate(self.enums.itervalues()): + code(' case ${{self.c_ident}}_${{enum.ident}}:') + code(' return $i;') + code.dedent() + + # total num + code(''' + case ${{self.c_ident}}_NUM: + return ${{len(self.enums)}}; + + default: + ERROR_MSG("Invalid range for type ${{self.c_ident}}"); + return -1; + } +} + +/** \\brief returns the machine type for each base vector index used by NetDest + * + * \\return the MachineTYpe + */ +MachineType ${{self.c_ident}}_from_base_level(int type) +{ + switch(type) { +''') + + # For each field + code.indent() + for i,enum in enumerate(self.enums.itervalues()): + code(' case $i:') + code(' return ${{self.c_ident}}_${{enum.ident}};') + code.dedent() + + # Trailer + code(''' + default: + ERROR_MSG("Invalid range for type ${{self.c_ident}}"); + return MachineType_NUM; + } +} + +/** \\brief The return value indicates the number of components created + * before a particular machine\'s components + * + * \\return the base number of components for each machine + */ +int ${{self.c_ident}}_base_number(const ${{self.c_ident}}& obj) +{ + int base = 0; + switch(obj) { +''') + + # For each field + code.indent() + code(' case ${{self.c_ident}}_NUM:') + for enum in reversed(self.enums.values()): + code(' base += ${{enum.ident}}_Controller::getNumControllers();') + code(' case ${{self.c_ident}}_${{enum.ident}}:') + code(' break;') + code.dedent() + + code(''' + default: + ERROR_MSG("Invalid range for type ${{self.c_ident}}"); + return -1; + } + + return base; +} + +/** \\brief returns the total number of components for each machine + * \\return the total number of components for each machine + */ +int ${{self.c_ident}}_base_count(const ${{self.c_ident}}& obj) +{ + switch(obj) { +''') + + # For each field + for enum in self.enums.itervalues(): + code(''' + case ${{self.c_ident}}_${{enum.ident}}: + return ${{enum.ident}}_Controller::getNumControllers(); +''') + + # total num + code(''' + case ${{self.c_ident}}_NUM: + default: + ERROR_MSG("Invalid range for type ${{self.c_ident}}"); + return -1; + } +} +''') + + # Write the file + code.write(path, "%s.cc" % self.c_ident) + +__all__ = [ "Type" ] diff --git a/src/mem/slicc/symbols/Var.hh b/src/mem/slicc/symbols/Var.hh deleted file mode 100644 index 4cb504296..000000000 --- a/src/mem/slicc/symbols/Var.hh +++ /dev/null @@ -1,98 +0,0 @@ - -/* - * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer; - * redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution; - * neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/* - * Var.hh - * - * Description: - * - * $Id$ - * - * */ - -#ifndef VAR_H -#define VAR_H - -#include "mem/slicc/slicc_global.hh" -#include "mem/slicc/symbols/Symbol.hh" -#include "mem/slicc/symbols/Type.hh" - -class StateMachine; - -class Var : public Symbol { -public: - // Constructors - Var(string id, const Location& location, - Type* type_ptr, string code, - const Map<string, string>& pairs, - StateMachine* machine_ptr = NULL); - - // Var(string id, const Location& location, - // Type* type_ptr, string code) : Symbol(id, location) { m_type_ptr = type_ptr; m_code = code; } - - // Destructor - ~Var() {} - - // Public Methods - string cIdent() const { return m_c_id; } - void writeCFiles(string path) {} - string getCode() const { return m_code; } - Type* getType() const { return m_type_ptr; } - StateMachine* getMachine() const { return m_machine_ptr; } - - void print(ostream& out) const; -private: - // Private Methods - - // Private copy constructor and assignment operator - Var(const Var& obj); - Var& operator=(const Var& obj); - - // Data Members (m_ prefix) - string m_c_id; - Type* m_type_ptr; - string m_code; - StateMachine* m_machine_ptr; -}; - -// Output operator declaration -ostream& operator<<(ostream& out, const Var& obj); - -// ******************* Definitions ******************* - -// Output operator definition -extern inline -ostream& operator<<(ostream& out, const Var& obj) -{ - obj.print(out); - out << flush; - return out; -} - -#endif //VAR_H diff --git a/src/mem/slicc/symbols/Var.py b/src/mem/slicc/symbols/Var.py new file mode 100644 index 000000000..87a101f65 --- /dev/null +++ b/src/mem/slicc/symbols/Var.py @@ -0,0 +1,50 @@ +# Copyright (c) 1999-2008 Mark D. Hill and David A. Wood +# Copyright (c) 2009 The Hewlett-Packard Development Company +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer; +# redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution; +# neither the name of the copyright holders nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +from slicc.symbols.Symbol import Symbol + +class Var(Symbol): + def __init__(self, symtab, ident, location, type, code, pairs, + machine=None): + super(Var, self).__init__(symtab, ident, location, pairs) + + if machine: + self.c_ident = "%s_%s" % (machine, ident) + else: + self.c_ident = ident + + self.machine = machine + self.type = type + self.code = code + + def __repr__(self): + return "[Var id: %s]" % (self.c_ident) + + def writeCodeFiles(self, path): + pass + +__all__ = [ "Var" ] diff --git a/src/mem/slicc/symbols/__init__.py b/src/mem/slicc/symbols/__init__.py new file mode 100644 index 000000000..43388a5fe --- /dev/null +++ b/src/mem/slicc/symbols/__init__.py @@ -0,0 +1,38 @@ +# Copyright (c) 2009 The Hewlett-Packard Development Company +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer; +# redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution; +# neither the name of the copyright holders nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# Authors: Nathan Binkert + +from slicc.symbols.Action import Action +from slicc.symbols.Event import Event +from slicc.symbols.Func import Func +from slicc.symbols.State import State +from slicc.symbols.StateMachine import StateMachine +from slicc.symbols.Symbol import Symbol +from slicc.symbols.SymbolTable import SymbolTable +from slicc.symbols.Transition import Transition +from slicc.symbols.Type import Type +from slicc.symbols.Var import Var diff --git a/src/mem/slicc/util.py b/src/mem/slicc/util.py new file mode 100644 index 000000000..abadc3e30 --- /dev/null +++ b/src/mem/slicc/util.py @@ -0,0 +1,75 @@ +# Copyright (c) 2009 The Hewlett-Packard Development Company +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer; +# redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution; +# neither the name of the copyright holders nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +import os +import sys + +def makeDir(path): + if os.path.exists(path): + if not os.path.isdir(path): + raise AttributeError, "%s exists but is not directory" % path + else: + os.mkdir(path) + +class PairContainer(object): + def __init__(self, pairs=None): + self.pairs = {} + if pairs: + self.pairs.update(pairs) + + def __contains__(self, item): + return item in self.pairs + + def __getitem__(self, item): + return self.pairs[item] + + def __setitem__(self, item, value): + self.pairs[item] = value + + def get(self, item, failobj=None): + return self.pairs.get(item, failobj) + +class Location(object): + def __init__(self, filename, lineno): + self.filename = filename + self.lineno = lineno + + def __str__(self): + return '%s:%d' % (os.path.basename(self.filename), self.lineno) + + def warning(self, message, *args): + if args: + message = message % args + #raise Exception, "%s: Warning: %s" % (self, message) + print >>sys.stderr, "%s: Warning: %s" % (self, message) + + def error(self, message, *args): + if args: + message = message % args + raise Exception, "%s: Error: %s" % (self, message) + sys.exit("\n%s: Error: %s" % (self, message)) + +__all__ = [ 'makeDir', 'PairContainer', 'Location' ] diff --git a/src/mem/translating_port.cc b/src/mem/translating_port.cc index 54de6625e..700229b23 100644 --- a/src/mem/translating_port.cc +++ b/src/mem/translating_port.cc @@ -30,7 +30,9 @@ */ #include <string> + #include "base/chunk_generator.hh" +#include "config/the_isa.hh" #include "mem/port.hh" #include "mem/translating_port.hh" #include "mem/page_table.hh" diff --git a/src/mem/vport.cc b/src/mem/vport.cc index 15be45c2a..ab061c019 100644 --- a/src/mem/vport.cc +++ b/src/mem/vport.cc @@ -34,6 +34,7 @@ */ #include "base/chunk_generator.hh" +#include "config/the_isa.hh" #include "cpu/thread_context.hh" #include "mem/vport.hh" diff --git a/src/python/SConscript b/src/python/SConscript index bb892f376..935986a12 100644 --- a/src/python/SConscript +++ b/src/python/SConscript @@ -38,7 +38,6 @@ PySource('', 'importer.py') PySource('m5', 'm5/__init__.py') PySource('m5', 'm5/SimObject.py') PySource('m5', 'm5/config.py') -PySource('m5', 'm5/convert.py') PySource('m5', 'm5/core.py') PySource('m5', 'm5/debug.py') PySource('m5', 'm5/event.py') @@ -47,18 +46,18 @@ PySource('m5', 'm5/options.py') PySource('m5', 'm5/params.py') PySource('m5', 'm5/proxy.py') PySource('m5', 'm5/simulate.py') -PySource('m5', 'm5/smartdict.py') PySource('m5', 'm5/stats.py') PySource('m5', 'm5/ticks.py') PySource('m5', 'm5/trace.py') PySource('m5.util', 'm5/util/__init__.py') PySource('m5.util', 'm5/util/attrdict.py') PySource('m5.util', 'm5/util/code_formatter.py') +PySource('m5.util', 'm5/util/convert.py') PySource('m5.util', 'm5/util/grammar.py') PySource('m5.util', 'm5/util/jobfile.py') -PySource('m5.util', 'm5/util/misc.py') PySource('m5.util', 'm5/util/multidict.py') PySource('m5.util', 'm5/util/orderdict.py') +PySource('m5.util', 'm5/util/smartdict.py') SwigSource('m5.internal', 'swig/core.i') SwigSource('m5.internal', 'swig/debug.i') diff --git a/src/python/m5/SimObject.py b/src/python/m5/SimObject.py index 8ef22be4e..0e0ffaea9 100644 --- a/src/python/m5/SimObject.py +++ b/src/python/m5/SimObject.py @@ -31,47 +31,24 @@ import math import sys import types -import proxy -import m5 -from util import * - -# These utility functions have to come first because they're -# referenced in params.py... otherwise they won't be defined when we -# import params below, and the recursive import of this file from -# params.py will not find these names. -def isSimObject(value): - return isinstance(value, SimObject) - -def isSimObjectClass(value): - return issubclass(value, SimObject) - -def isSimObjectSequence(value): - if not isinstance(value, (list, tuple)) or len(value) == 0: - return False - - for val in value: - if not isNullPointer(val) and not isSimObject(val): - return False - - return True +try: + import pydot +except: + pydot = False -def isSimObjectOrSequence(value): - return isSimObject(value) or isSimObjectSequence(value) +import m5 +from m5.util import * # Have to import params up top since Param is referenced on initial # load (when SimObject class references Param to create a class # variable, the 'name' param)... -from params import * +from m5.params import * # There are a few things we need that aren't in params.__all__ since # normal users don't need them -from params import ParamDesc, VectorParamDesc, isNullPointer, SimObjVector -from proxy import * +from m5.params import ParamDesc, VectorParamDesc, isNullPointer, SimObjVector -noDot = False -try: - import pydot -except: - noDot = True +from m5.proxy import * +from m5.proxy import isproxy ##################################################################### # @@ -141,7 +118,7 @@ class MetaSimObject(type): # and only allow "private" attributes to be passed to the base # __new__ (starting with underscore). def __new__(mcls, name, bases, dict): - assert name not in allClasses + assert name not in allClasses, "SimObject %s already present" % name # Copy "private" attributes, functions, and classes to the # official dict. Everything else goes in _init_dict to be @@ -678,7 +655,7 @@ class SimObject(object): def unproxy_all(self): for param in self._params.iterkeys(): value = self._values.get(param) - if value != None and proxy.isproxy(value): + if value != None and isproxy(value): try: value = value.unproxy(self) except: @@ -749,8 +726,8 @@ class SimObject(object): for param in param_names: value = self._values.get(param) if value is None: - m5.fatal("%s.%s without default or user set value", - self.path(), param) + fatal("%s.%s without default or user set value", + self.path(), param) value = value.getValue() if isinstance(self._params[param], VectorParamDesc): @@ -886,6 +863,34 @@ def resolveSimObject(name): obj = instanceDict[name] return obj.getCCObject() +def isSimObject(value): + return isinstance(value, SimObject) + +def isSimObjectClass(value): + return issubclass(value, SimObject) + +def isSimObjectSequence(value): + if not isinstance(value, (list, tuple)) or len(value) == 0: + return False + + for val in value: + if not isNullPointer(val) and not isSimObject(val): + return False + + return True + +def isSimObjectOrSequence(value): + return isSimObject(value) or isSimObjectSequence(value) + +baseClasses = allClasses.copy() +baseInstances = instanceDict.copy() + +def clear(): + global allClasses, instanceDict + + allClasses = baseClasses.copy() + instanceDict = baseInstances.copy() + # __all__ defines the list of symbols that get exported when # 'from config import *' is invoked. Try to keep this reasonably # short to avoid polluting other namespaces. diff --git a/src/python/m5/__init__.py b/src/python/m5/__init__.py index c3512cd0d..9f9459ae8 100644 --- a/src/python/m5/__init__.py +++ b/src/python/m5/__init__.py @@ -25,106 +25,24 @@ # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # # Authors: Nathan Binkert -# Steve Reinhardt -import os -import sys +# Import useful subpackages of M5, but *only* when run as an m5 +# script. This is mostly to keep backward compatibility with existing +# scripts while allowing new SCons code to operate properly. -import smartdict - -# define a MaxTick parameter -MaxTick = 2**63 - 1 - -# define this here so we can use it right away if necessary - -def errorURL(prefix, s): - try: - import zlib - hashstr = "%x" % zlib.crc32(s) - except: - hashstr = "UnableToHash" - return "For more information see: http://www.m5sim.org/%s/%s" % \ - (prefix, hashstr) - - -# panic() should be called when something happens that should never -# ever happen regardless of what the user does (i.e., an acutal m5 -# bug). -def panic(fmt, *args): - print >>sys.stderr, 'panic:', fmt % args - print >>sys.stderr, errorURL('panic',fmt) - sys.exit(1) - -# fatal() should be called when the simulation cannot continue due to -# some condition that is the user's fault (bad configuration, invalid -# arguments, etc.) and not a simulator bug. -def fatal(fmt, *args): - print >>sys.stderr, 'fatal:', fmt % args - print >>sys.stderr, errorURL('fatal',fmt) - sys.exit(1) - -# force scalars to one-element lists for uniformity -def makeList(objOrList): - if isinstance(objOrList, list): - return objOrList - return [objOrList] - -# Prepend given directory to system module search path. We may not -# need this anymore if we can structure our config library more like a -# Python package. -def AddToPath(path): - # if it's a relative path and we know what directory the current - # python script is in, make the path relative to that directory. - if not os.path.isabs(path) and sys.path[0]: - path = os.path.join(sys.path[0], path) - path = os.path.realpath(path) - # sys.path[0] should always refer to the current script's directory, - # so place the new dir right after that. - sys.path.insert(1, path) - -# make a SmartDict out of the build options for our local use -build_env = smartdict.SmartDict() - -# make a SmartDict out of the OS environment too -env = smartdict.SmartDict() -env.update(os.environ) - -# Since we have so many mutual imports in this package, we should: -# 1. Put all intra-package imports at the *bottom* of the file, unless -# they're absolutely needed before that (for top-level statements -# or class attributes). Imports of "trivial" packages that don't -# import other packages (e.g., 'smartdict') can be at the top. -# 2. Never use 'from foo import *' on an intra-package import since -# you can get the wrong result if foo is only partially imported -# at the point you do that (i.e., because foo is in the middle of -# importing *you*). try: import internal except ImportError: internal = None -try: - import defines - build_env.update(defines.buildEnv) -except ImportError: - defines = None - if internal: - defines.compileDate = internal.core.compileDate - for k,v in internal.core.__dict__.iteritems(): - if k.startswith('flag_'): - setattr(defines, k[5:], v) + import SimObject + import core + import objects + import params + import stats + import util from event import * - from simulate import * from main import options, main - import stats - import core - -import SimObject -import params - -try: - import objects -except ImportError: - objects = None + from simulate import * diff --git a/src/python/m5/main.py b/src/python/m5/main.py index 2a308ff09..29f8cc976 100644 --- a/src/python/m5/main.py +++ b/src/python/m5/main.py @@ -32,7 +32,7 @@ import os import socket import sys -from util import attrdict +from util import attrdict, fatal import config from options import OptionParser diff --git a/src/python/m5/params.py b/src/python/m5/params.py index edd78fa28..cf64070c5 100644 --- a/src/python/m5/params.py +++ b/src/python/m5/params.py @@ -50,13 +50,10 @@ import re import sys import time -import convert import proxy import ticks from util import * -import SimObject - def isSimObject(*args, **kwargs): return SimObject.isSimObject(*args, **kwargs) @@ -96,6 +93,8 @@ class ParamValue(object): # Regular parameter description. class ParamDesc(object): + file_ext = 'ptype' + def __init__(self, ptype_str, ptype, *args, **kwargs): self.ptype_str = ptype_str # remember ptype only if it is provided @@ -130,7 +129,7 @@ class ParamDesc(object): def __getattr__(self, attr): if attr == 'ptype': ptype = SimObject.allClasses[self.ptype_str] - assert issubclass(ptype, SimObject.SimObject) + assert isSimObjectClass(ptype) self.ptype = ptype return ptype @@ -185,6 +184,8 @@ class SimObjVector(VectorParamValue): v.print_ini(ini_file) class VectorParamDesc(ParamDesc): + file_ext = 'vptype' + # Convert assigned value to appropriate type. If the RHS is not a # list or tuple, it generates a single-element list. def convert(self, value): @@ -711,32 +712,31 @@ class MetaEnum(MetaParamValue): super(MetaEnum, cls).__init__(name, bases, init_dict) - def __str__(cls): - return cls.__name__ - # Generate C++ class declaration for this enum type. # Note that we wrap the enum in a class/struct to act as a namespace, # so that the enum strings can be brief w/o worrying about collisions. def cxx_decl(cls): - code = "#ifndef __ENUM__%s\n" % cls - code += '#define __ENUM__%s\n' % cls + name = cls.__name__ + code = "#ifndef __ENUM__%s\n" % name + code += '#define __ENUM__%s\n' % name code += '\n' code += 'namespace Enums {\n' - code += ' enum %s {\n' % cls + code += ' enum %s {\n' % name for val in cls.vals: code += ' %s = %d,\n' % (val, cls.map[val]) - code += ' Num_%s = %d,\n' % (cls, len(cls.vals)) + code += ' Num_%s = %d,\n' % (name, len(cls.vals)) code += ' };\n' - code += ' extern const char *%sStrings[Num_%s];\n' % (cls, cls) + code += ' extern const char *%sStrings[Num_%s];\n' % (name, name) code += '}\n' code += '\n' code += '#endif\n' return code def cxx_def(cls): - code = '#include "enums/%s.hh"\n' % cls + name = cls.__name__ + code = '#include "enums/%s.hh"\n' % name code += 'namespace Enums {\n' - code += ' const char *%sStrings[Num_%s] =\n' % (cls, cls) + code += ' const char *%sStrings[Num_%s] =\n' % (name, name) code += ' {\n' for val in cls.vals: code += ' "%s",\n' % val @@ -1170,6 +1170,15 @@ class PortParamDesc(object): ptype_str = 'Port' ptype = Port +baseEnums = allEnums.copy() +baseParams = allParams.copy() + +def clear(): + global allEnums, allParams + + allEnums = baseEnums.copy() + allParams = baseParams.copy() + __all__ = ['Param', 'VectorParam', 'Enum', 'Bool', 'String', 'Float', 'Int', 'Unsigned', 'Int8', 'UInt8', 'Int16', 'UInt16', @@ -1184,3 +1193,5 @@ __all__ = ['Param', 'VectorParam', 'Time', 'NextEthernetAddr', 'NULL', 'Port', 'VectorPort'] + +import SimObject diff --git a/src/python/m5/simulate.py b/src/python/m5/simulate.py index 45992fe85..092bd0339 100644 --- a/src/python/m5/simulate.py +++ b/src/python/m5/simulate.py @@ -40,6 +40,9 @@ import SimObject import ticks import objects +# define a MaxTick parameter +MaxTick = 2**63 - 1 + # The final hook to generate .ini files. Called from the user script # once the config is built. def instantiate(root): diff --git a/src/python/m5/ticks.py b/src/python/m5/ticks.py index 91834c9c8..181a65eba 100644 --- a/src/python/m5/ticks.py +++ b/src/python/m5/ticks.py @@ -41,7 +41,7 @@ def fixGlobalFrequency(): print "Global frequency set at %d ticks per second" % int(tps) def setGlobalFrequency(ticksPerSecond): - import convert + from m5.util import convert global tps, tps_fixed diff --git a/src/python/m5/trace.py b/src/python/m5/trace.py index 17aa6196c..db239040a 100644 --- a/src/python/m5/trace.py +++ b/src/python/m5/trace.py @@ -48,5 +48,5 @@ def help(): if flag == 'All': continue print " %s: %s" % (flag, flags.descriptions[flag]) - util.print_list(flags.compoundMap[flag], indent=8) + util.printList(flags.compoundMap[flag], indent=8) print diff --git a/src/python/m5/util/__init__.py b/src/python/m5/util/__init__.py index 3930c8b6f..7a674dd2d 100644 --- a/src/python/m5/util/__init__.py +++ b/src/python/m5/util/__init__.py @@ -1,4 +1,5 @@ -# Copyright (c) 2008 The Hewlett-Packard Development Company +# Copyright (c) 2008-2009 The Hewlett-Packard Development Company +# Copyright (c) 2004-2006 The Regents of The University of Michigan # All rights reserved. # # Redistribution and use in source and binary forms, with or without @@ -26,14 +27,130 @@ # # Authors: Nathan Binkert +import os +import re +import sys + +import convert +import jobfile + from attrdict import attrdict, optiondict from code_formatter import code_formatter -from misc import * from multidict import multidict from orderdict import orderdict -import jobfile +from smartdict import SmartDict + +# define this here so we can use it right away if necessary +def errorURL(prefix, s): + try: + import zlib + hashstr = "%x" % zlib.crc32(s) + except: + hashstr = "UnableToHash" + return "For more information see: http://www.m5sim.org/%s/%s" % \ + (prefix, hashstr) + +# panic() should be called when something happens that should never +# ever happen regardless of what the user does (i.e., an acutal m5 +# bug). +def panic(fmt, *args): + print >>sys.stderr, 'panic:', fmt % args + print >>sys.stderr, errorURL('panic',fmt) + sys.exit(1) + +# fatal() should be called when the simulation cannot continue due to +# some condition that is the user's fault (bad configuration, invalid +# arguments, etc.) and not a simulator bug. +def fatal(fmt, *args): + print >>sys.stderr, 'fatal:', fmt % args + print >>sys.stderr, errorURL('fatal',fmt) + sys.exit(1) + +class Singleton(type): + def __call__(cls, *args, **kwargs): + if hasattr(cls, '_instance'): + return cls._instance + + cls._instance = super(Singleton, cls).__call__(*args, **kwargs) + return cls._instance + +def addToPath(path): + """Prepend given directory to system module search path. We may not + need this anymore if we can structure our config library more like a + Python package.""" + + # if it's a relative path and we know what directory the current + # python script is in, make the path relative to that directory. + if not os.path.isabs(path) and sys.path[0]: + path = os.path.join(sys.path[0], path) + path = os.path.realpath(path) + # sys.path[0] should always refer to the current script's directory, + # so place the new dir right after that. + sys.path.insert(1, path) + +# Apply method to object. +# applyMethod(obj, 'meth', <args>) is equivalent to obj.meth(<args>) +def applyMethod(obj, meth, *args, **kwargs): + return getattr(obj, meth)(*args, **kwargs) -def print_list(items, indent=4): +# If the first argument is an (non-sequence) object, apply the named +# method with the given arguments. If the first argument is a +# sequence, apply the method to each element of the sequence (a la +# 'map'). +def applyOrMap(objOrSeq, meth, *args, **kwargs): + if not isinstance(objOrSeq, (list, tuple)): + return applyMethod(objOrSeq, meth, *args, **kwargs) + else: + return [applyMethod(o, meth, *args, **kwargs) for o in objOrSeq] + +def compareVersions(v1, v2): + """helper function: compare arrays or strings of version numbers. + E.g., compare_version((1,3,25), (1,4,1)') + returns -1, 0, 1 if v1 is <, ==, > v2 + """ + def make_version_list(v): + if isinstance(v, (list,tuple)): + return v + elif isinstance(v, str): + return map(lambda x: int(re.match('\d+', x).group()), v.split('.')) + else: + raise TypeError + + v1 = make_version_list(v1) + v2 = make_version_list(v2) + # Compare corresponding elements of lists + for n1,n2 in zip(v1, v2): + if n1 < n2: return -1 + if n1 > n2: return 1 + # all corresponding values are equal... see if one has extra values + if len(v1) < len(v2): return -1 + if len(v1) > len(v2): return 1 + return 0 + +def crossproduct(items): + if len(items) == 1: + for i in items[0]: + yield (i,) + else: + for i in items[0]: + for j in crossproduct(items[1:]): + yield (i,) + j + +def flatten(items): + while items: + item = items.pop(0) + if isinstance(item, (list, tuple)): + items[0:0] = item + else: + yield item + +# force scalars to one-element lists for uniformity +def makeList(objOrList): + if isinstance(objOrList, list): + return objOrList + return [objOrList] + +def printList(items, indent=4): line = ' ' * indent for i,item in enumerate(items): if len(line) + len(item) > 76: @@ -45,3 +162,27 @@ def print_list(items, indent=4): else: line += item print line + +def readCommand(cmd, **kwargs): + """run the command cmd, read the results and return them + this is sorta like `cmd` in shell""" + from subprocess import Popen, PIPE, STDOUT + + if isinstance(cmd, str): + cmd = cmd.split() + + no_exception = 'exception' in kwargs + exception = kwargs.pop('exception', None) + + kwargs.setdefault('shell', False) + kwargs.setdefault('stdout', PIPE) + kwargs.setdefault('stderr', STDOUT) + kwargs.setdefault('close_fds', True) + try: + subp = Popen(cmd, **kwargs) + except Exception, e: + if no_exception: + return exception + raise + + return subp.communicate()[0] diff --git a/src/python/m5/util/attrdict.py b/src/python/m5/util/attrdict.py index 0b30258b9..8f7d59698 100644 --- a/src/python/m5/util/attrdict.py +++ b/src/python/m5/util/attrdict.py @@ -45,6 +45,12 @@ class attrdict(dict): return self.__delitem__(attr) return super(attrdict, self).__delattr__(attr) + def __getstate__(self): + return dict(self) + + def __setstate__(self, state): + self.update(state) + class multiattrdict(attrdict): """Wrap attrdict so that nested attribute accesses automatically create nested dictionaries.""" @@ -52,7 +58,7 @@ class multiattrdict(attrdict): try: return super(multiattrdict, self).__getattr__(attr) except AttributeError: - d = optiondict() + d = multiattrdict() setattr(self, attr, d) return d @@ -80,8 +86,12 @@ if __name__ == '__main__': print dir(x) print(x) + print + print "multiattrdict" x = multiattrdict() + x.x.x.x = 9 x.y.z = 9 print x print x.y print x.y.z + print x.z.z diff --git a/src/python/m5/util/code_formatter.py b/src/python/m5/util/code_formatter.py index 919a6423b..396fe0e52 100644 --- a/src/python/m5/util/code_formatter.py +++ b/src/python/m5/util/code_formatter.py @@ -24,6 +24,7 @@ # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +import __builtin__ import inspect import os import re @@ -64,8 +65,8 @@ class lookup(object): if self.formatter.globals and item in self.frame.f_globals: return self.frame.f_globals[item] - if item in __builtins__: - return __builtins__[item] + if item in __builtin__.__dict__: + return __builtin__.__dict__[item] try: item = int(item) diff --git a/src/python/m5/convert.py b/src/python/m5/util/convert.py index bb9e3e1f1..bb9e3e1f1 100644 --- a/src/python/m5/convert.py +++ b/src/python/m5/util/convert.py diff --git a/src/python/m5/util/grammar.py b/src/python/m5/util/grammar.py index 93c2c84c4..ab5f35868 100644 --- a/src/python/m5/util/grammar.py +++ b/src/python/m5/util/grammar.py @@ -55,6 +55,7 @@ class Tokenizer(object): break yield tok self.input = _input() + self.lexer = lexer def next(self): return self.input.next() @@ -68,6 +69,9 @@ class Tokenizer(object): except StopIteration: return None + def __getattr__(self, attr): + return getattr(self.lexer, attr) + class Grammar(object): def __init__(self, output=None, debug=False): self.yacc_args = {} diff --git a/src/python/m5/util/jobfile.py b/src/python/m5/util/jobfile.py index c830895f6..9c59778e5 100644 --- a/src/python/m5/util/jobfile.py +++ b/src/python/m5/util/jobfile.py @@ -28,9 +28,6 @@ import sys -from attrdict import optiondict -from misc import crossproduct - class Data(object): def __init__(self, name, desc, **kwargs): self.name = name @@ -108,7 +105,8 @@ class Data(object): yield key def optiondict(self): - result = optiondict() + import m5.util + result = m5.util.optiondict() for key in self: result[key] = self[key] return result @@ -328,7 +326,9 @@ class Configuration(Data): optgroups = [ g.subopts() for g in groups ] if not optgroups: return - for options in crossproduct(optgroups): + + import m5.util + for options in m5.util.crossproduct(optgroups): for opt in options: cpt = opt._group._checkpoint if not isinstance(cpt, bool) and cpt != opt: diff --git a/src/python/m5/util/misc.py b/src/python/m5/util/misc.py deleted file mode 100644 index 094e3ed9a..000000000 --- a/src/python/m5/util/misc.py +++ /dev/null @@ -1,87 +0,0 @@ -# Copyright (c) 2004-2006 The Regents of The University of Michigan -# All rights reserved. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions are -# met: redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer; -# redistributions in binary form must reproduce the above copyright -# notice, this list of conditions and the following disclaimer in the -# documentation and/or other materials provided with the distribution; -# neither the name of the copyright holders nor the names of its -# contributors may be used to endorse or promote products derived from -# this software without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -# -# Authors: Steve Reinhardt -# Nathan Binkert - -############################# -# -# Utility classes & methods -# -############################# - -class Singleton(type): - def __call__(cls, *args, **kwargs): - if hasattr(cls, '_instance'): - return cls._instance - - cls._instance = super(Singleton, cls).__call__(*args, **kwargs) - return cls._instance - -# Apply method to object. -# applyMethod(obj, 'meth', <args>) is equivalent to obj.meth(<args>) -def applyMethod(obj, meth, *args, **kwargs): - return getattr(obj, meth)(*args, **kwargs) - -# If the first argument is an (non-sequence) object, apply the named -# method with the given arguments. If the first argument is a -# sequence, apply the method to each element of the sequence (a la -# 'map'). -def applyOrMap(objOrSeq, meth, *args, **kwargs): - if not isinstance(objOrSeq, (list, tuple)): - return applyMethod(objOrSeq, meth, *args, **kwargs) - else: - return [applyMethod(o, meth, *args, **kwargs) for o in objOrSeq] - -def crossproduct(items): - if not isinstance(items, (list, tuple)): - raise AttributeError, 'crossproduct works only on sequences' - - if not items: - yield None - return - - current = items[0] - remainder = items[1:] - - if not hasattr(current, '__iter__'): - current = [ current ] - - for item in current: - for rem in crossproduct(remainder): - data = [ item ] - if rem: - data += rem - yield data - -def flatten(items): - if not isinstance(items, (list, tuple)): - yield items - return - - for item in items: - for flat in flatten(item): - yield flat diff --git a/src/python/m5/smartdict.py b/src/python/m5/util/smartdict.py index d85dbd517..d85dbd517 100644 --- a/src/python/m5/smartdict.py +++ b/src/python/m5/util/smartdict.py diff --git a/src/sim/System.py b/src/sim/System.py index 3b0bc1e46..06a54a78d 100644 --- a/src/sim/System.py +++ b/src/sim/System.py @@ -27,9 +27,10 @@ # Authors: Nathan Binkert from m5.SimObject import SimObject +from m5.defines import buildEnv from m5.params import * from m5.proxy import * -from m5 import build_env + from PhysicalMemory import * class MemoryMode(Enum): vals = ['invalid', 'atomic', 'timing'] @@ -40,7 +41,7 @@ class System(SimObject): physmem = Param.PhysicalMemory(Parent.any, "physical memory") mem_mode = Param.MemoryMode('atomic', "The mode the memory system is in") - if build_env['FULL_SYSTEM']: + if buildEnv['FULL_SYSTEM']: abstract = True boot_cpu_frequency = Param.Frequency(Self.cpu[0].clock.frequency, "boot processor frequency") diff --git a/src/sim/arguments.cc b/src/sim/arguments.cc index 5aa57755a..339a57f90 100644 --- a/src/sim/arguments.cc +++ b/src/sim/arguments.cc @@ -28,11 +28,10 @@ * Authors: Nathan Binkert */ -#include "sim/arguments.hh" #include "arch/utility.hh" +#include "config/the_isa.hh" #include "cpu/thread_context.hh" - -using namespace TheISA; +#include "sim/arguments.hh" Arguments::Data::~Data() { diff --git a/src/sim/eventq.hh b/src/sim/eventq.hh index 29efdeb6f..92c38142c 100644 --- a/src/sim/eventq.hh +++ b/src/sim/eventq.hh @@ -471,7 +471,7 @@ class EventWrapper : public Event inline void EventQueue::schedule(Event *event, Tick when) { - assert(when >= curTick); + assert((UTick)when >= (UTick)curTick); assert(!event->scheduled()); #ifdef EVENTQ_DEBUG assert((event->flags & Event::Initialized) == Event::Initialized); diff --git a/src/sim/process.cc b/src/sim/process.cc index 55bd2f209..343d2ad5a 100644 --- a/src/sim/process.cc +++ b/src/sim/process.cc @@ -32,6 +32,8 @@ #include <unistd.h> #include <fcntl.h> + +#include <cstdio> #include <string> #include "arch/remote_gdb.hh" @@ -40,6 +42,7 @@ #include "base/loader/symtab.hh" #include "base/statistics.hh" #include "config/full_system.hh" +#include "config/the_isa.hh" #include "cpu/thread_context.hh" #include "mem/page_table.hh" #include "mem/physical.hh" @@ -53,7 +56,6 @@ #include "sim/syscall_emul.hh" #include "sim/system.hh" -#include "arch/isa_specific.hh" #if THE_ISA == ALPHA_ISA #include "arch/alpha/linux/process.hh" #include "arch/alpha/tru64/process.hh" @@ -66,6 +68,8 @@ #include "arch/arm/linux/process.hh" #elif THE_ISA == X86_ISA #include "arch/x86/linux/process.hh" +#elif THE_ISA == POWER_ISA +#include "arch/power/linux/process.hh" #else #error "THE_ISA not set" #endif @@ -626,7 +630,7 @@ LiveProcess::argsInit(int intSize, int pageSize) tc->setPC(prog_entry); tc->setNextPC(prog_entry + sizeof(MachInst)); -#if THE_ISA != ALPHA_ISA //e.g. MIPS or Sparc +#if THE_ISA != ALPHA_ISA && THE_ISA != POWER_ISA //e.g. MIPS or Sparc tc->setNextNPC(prog_entry + (2 * sizeof(MachInst))); #endif @@ -645,6 +649,12 @@ LiveProcess::syscall(int64_t callnum, ThreadContext *tc) desc->doSyscall(callnum, this, tc); } +IntReg +LiveProcess::getSyscallArg(ThreadContext *tc, int &i, int width) +{ + return getSyscallArg(tc, i); +} + LiveProcess * LiveProcess::create(LiveProcessParams * params) { @@ -754,6 +764,20 @@ LiveProcess::create(LiveProcessParams * params) default: fatal("Unknown/unsupported operating system."); } +#elif THE_ISA == POWER_ISA + if (objFile->getArch() != ObjectFile::Power) + fatal("Object file architecture does not match compiled ISA (Power)."); + switch (objFile->getOpSys()) { + case ObjectFile::UnknownOpSys: + warn("Unknown operating system; assuming Linux."); + // fall through + case ObjectFile::Linux: + process = new PowerLinuxProcess(params, objFile); + break; + + default: + fatal("Unknown/unsupported operating system."); + } #else #error "THE_ISA not set" #endif diff --git a/src/sim/process.hh b/src/sim/process.hh index 05a48071a..ab9d64cf3 100644 --- a/src/sim/process.hh +++ b/src/sim/process.hh @@ -47,9 +47,11 @@ #include "arch/registers.hh" #include "base/statistics.hh" #include "base/types.hh" +#include "config/the_isa.hh" #include "sim/sim_object.hh" #include "sim/syscallreturn.hh" +class BaseRemoteGDB; class GDBListener; class PageTable; class ProcessParams; @@ -58,10 +60,6 @@ class SyscallDesc; class System; class ThreadContext; class TranslatingPort; -namespace TheISA -{ - class RemoteGDB; -} template<class IntType> struct AuxVector @@ -94,7 +92,7 @@ class Process : public SimObject std::vector<int> contextIds; // remote gdb objects - std::vector<TheISA::RemoteGDB *> remoteGDB; + std::vector<BaseRemoteGDB *> remoteGDB; std::vector<GDBListener *> gdbListen; bool breakpoint(); @@ -327,7 +325,9 @@ class LiveProcess : public Process std::string getcwd() const { return cwd; } virtual void syscall(int64_t callnum, ThreadContext *tc); - virtual TheISA::IntReg getSyscallArg(ThreadContext *tc, int i) = 0; + + virtual TheISA::IntReg getSyscallArg(ThreadContext *tc, int &i) = 0; + virtual TheISA::IntReg getSyscallArg(ThreadContext *tc, int &i, int width); virtual void setSyscallArg(ThreadContext *tc, int i, TheISA::IntReg val) = 0; virtual void setSyscallReturn(ThreadContext *tc, diff --git a/src/sim/pseudo_inst.cc b/src/sim/pseudo_inst.cc index 6182150d4..cf063818b 100644 --- a/src/sim/pseudo_inst.cc +++ b/src/sim/pseudo_inst.cc @@ -35,10 +35,10 @@ #include <fstream> #include <string> -#include "config/full_system.hh" - #include "arch/vtophys.hh" #include "base/debug.hh" +#include "config/full_system.hh" +#include "config/the_isa.hh" #include "cpu/base.hh" #include "cpu/thread_context.hh" #include "cpu/quiesce_event.hh" diff --git a/src/sim/syscall_emul.cc b/src/sim/syscall_emul.cc index 811bdb73a..4726decc5 100644 --- a/src/sim/syscall_emul.cc +++ b/src/sim/syscall_emul.cc @@ -32,18 +32,19 @@ #include <fcntl.h> #include <unistd.h> -#include <string> +#include <cstdio> #include <iostream> +#include <string> #include "sim/syscall_emul.hh" #include "base/chunk_generator.hh" #include "base/trace.hh" +#include "config/the_isa.hh" #include "cpu/thread_context.hh" #include "cpu/base.hh" #include "mem/page_table.hh" #include "sim/process.hh" #include "sim/system.hh" - #include "sim/sim_exit.hh" using namespace std; @@ -52,11 +53,16 @@ using namespace TheISA; void SyscallDesc::doSyscall(int callnum, LiveProcess *process, ThreadContext *tc) { +#if TRACING_ON + int index = 0; +#endif DPRINTFR(SyscallVerbose, "%d: %s: syscall %s called w/arguments %d,%d,%d,%d\n", curTick, tc->getCpuPtr()->name(), name, - process->getSyscallArg(tc, 0), process->getSyscallArg(tc, 1), - process->getSyscallArg(tc, 2), process->getSyscallArg(tc, 3)); + process->getSyscallArg(tc, index), + process->getSyscallArg(tc, index), + process->getSyscallArg(tc, index), + process->getSyscallArg(tc, index)); SyscallReturn retval = (*funcPtr)(this, callnum, process, tc); @@ -82,8 +88,9 @@ SyscallReturn ignoreFunc(SyscallDesc *desc, int callnum, LiveProcess *process, ThreadContext *tc) { + int index = 0; warn("ignoring syscall %s(%d, %d, ...)", desc->name, - process->getSyscallArg(tc, 0), process->getSyscallArg(tc, 1)); + process->getSyscallArg(tc, index), process->getSyscallArg(tc, index)); return 0; } @@ -95,8 +102,9 @@ exitFunc(SyscallDesc *desc, int callnum, LiveProcess *process, { if (process->system->numRunningContexts() == 1) { // Last running context... exit simulator + int index = 0; exitSimLoop("target called exit()", - process->getSyscallArg(tc, 0) & 0xff); + process->getSyscallArg(tc, index) & 0xff); } else { // other running threads... just halt this one tc->halt(); @@ -112,8 +120,9 @@ exitGroupFunc(SyscallDesc *desc, int callnum, LiveProcess *process, { // really should just halt all thread contexts belonging to this // process in case there's another process running... + int index = 0; exitSimLoop("target called exit()", - process->getSyscallArg(tc, 0) & 0xff); + process->getSyscallArg(tc, index) & 0xff); return 1; } @@ -130,7 +139,8 @@ SyscallReturn brkFunc(SyscallDesc *desc, int num, LiveProcess *p, ThreadContext *tc) { // change brk addr to first arg - Addr new_brk = p->getSyscallArg(tc, 0); + int index = 0; + Addr new_brk = p->getSyscallArg(tc, index); // in Linux at least, brk(0) returns the current break value // (note that the syscall and the glibc function have different behavior) @@ -144,6 +154,24 @@ brkFunc(SyscallDesc *desc, int num, LiveProcess *p, ThreadContext *tc) if (!p->pTable->translate(gen.addr())) p->pTable->allocate(roundDown(gen.addr(), VMPageSize), VMPageSize); + + // if the address is already there, zero it out + else { + uint8_t zero = 0; + TranslatingPort *tp = tc->getMemPort(); + + // split non-page aligned accesses + Addr next_page = roundUp(gen.addr(), VMPageSize); + uint32_t size_needed = next_page - gen.addr(); + tp->memsetBlob(gen.addr(), zero, size_needed); + if (gen.addr() + VMPageSize > next_page && + next_page < new_brk && + p->pTable->translate(next_page)) + { + size_needed = VMPageSize - size_needed; + tp->memsetBlob(next_page, zero, size_needed); + } + } } } @@ -156,7 +184,8 @@ brkFunc(SyscallDesc *desc, int num, LiveProcess *p, ThreadContext *tc) SyscallReturn closeFunc(SyscallDesc *desc, int num, LiveProcess *p, ThreadContext *tc) { - int target_fd = p->getSyscallArg(tc, 0); + int index = 0; + int target_fd = p->getSyscallArg(tc, index); int status = close(p->sim_fd(target_fd)); if (status >= 0) p->free_fd(target_fd); @@ -167,9 +196,11 @@ closeFunc(SyscallDesc *desc, int num, LiveProcess *p, ThreadContext *tc) SyscallReturn readFunc(SyscallDesc *desc, int num, LiveProcess *p, ThreadContext *tc) { - int fd = p->sim_fd(p->getSyscallArg(tc, 0)); - int nbytes = p->getSyscallArg(tc, 2); - BufferArg bufArg(p->getSyscallArg(tc, 1), nbytes); + int index = 0; + int fd = p->sim_fd(p->getSyscallArg(tc, index)); + Addr bufPtr = p->getSyscallArg(tc, index); + int nbytes = p->getSyscallArg(tc, index); + BufferArg bufArg(bufPtr, nbytes); int bytes_read = read(fd, bufArg.bufferPtr(), nbytes); @@ -182,9 +213,11 @@ readFunc(SyscallDesc *desc, int num, LiveProcess *p, ThreadContext *tc) SyscallReturn writeFunc(SyscallDesc *desc, int num, LiveProcess *p, ThreadContext *tc) { - int fd = p->sim_fd(p->getSyscallArg(tc, 0)); - int nbytes = p->getSyscallArg(tc, 2); - BufferArg bufArg(p->getSyscallArg(tc, 1), nbytes); + int index = 0; + int fd = p->sim_fd(p->getSyscallArg(tc, index)); + Addr bufPtr = p->getSyscallArg(tc, index); + int nbytes = p->getSyscallArg(tc, index); + BufferArg bufArg(bufPtr, nbytes); bufArg.copyIn(tc->getMemPort()); @@ -199,9 +232,10 @@ writeFunc(SyscallDesc *desc, int num, LiveProcess *p, ThreadContext *tc) SyscallReturn lseekFunc(SyscallDesc *desc, int num, LiveProcess *p, ThreadContext *tc) { - int fd = p->sim_fd(p->getSyscallArg(tc, 0)); - uint64_t offs = p->getSyscallArg(tc, 1); - int whence = p->getSyscallArg(tc, 2); + int index = 0; + int fd = p->sim_fd(p->getSyscallArg(tc, index)); + uint64_t offs = p->getSyscallArg(tc, index); + int whence = p->getSyscallArg(tc, index); off_t result = lseek(fd, offs, whence); @@ -212,11 +246,12 @@ lseekFunc(SyscallDesc *desc, int num, LiveProcess *p, ThreadContext *tc) SyscallReturn _llseekFunc(SyscallDesc *desc, int num, LiveProcess *p, ThreadContext *tc) { - int fd = p->sim_fd(p->getSyscallArg(tc, 0)); - uint64_t offset_high = p->getSyscallArg(tc, 1); - uint32_t offset_low = p->getSyscallArg(tc, 2); - Addr result_ptr = p->getSyscallArg(tc, 3); - int whence = p->getSyscallArg(tc, 4); + int index = 0; + int fd = p->sim_fd(p->getSyscallArg(tc, index)); + uint64_t offset_high = p->getSyscallArg(tc, index); + uint32_t offset_low = p->getSyscallArg(tc, index); + Addr result_ptr = p->getSyscallArg(tc, index); + int whence = p->getSyscallArg(tc, index); uint64_t offset = (offset_high << 32) | offset_low; @@ -255,8 +290,10 @@ const char *hostname = "m5.eecs.umich.edu"; SyscallReturn gethostnameFunc(SyscallDesc *desc, int num, LiveProcess *p, ThreadContext *tc) { - int name_len = p->getSyscallArg(tc, 1); - BufferArg name(p->getSyscallArg(tc, 0), name_len); + int index = 0; + Addr bufPtr = p->getSyscallArg(tc, index); + int name_len = p->getSyscallArg(tc, index); + BufferArg name(bufPtr, name_len); strncpy((char *)name.bufferPtr(), hostname, name_len); @@ -269,8 +306,10 @@ SyscallReturn getcwdFunc(SyscallDesc *desc, int num, LiveProcess *p, ThreadContext *tc) { int result = 0; - unsigned long size = p->getSyscallArg(tc, 1); - BufferArg buf(p->getSyscallArg(tc, 0), size); + int index = 0; + Addr bufPtr = p->getSyscallArg(tc, index); + unsigned long size = p->getSyscallArg(tc, index); + BufferArg buf(bufPtr, size); // Is current working directory defined? string cwd = p->getcwd(); @@ -302,14 +341,17 @@ readlinkFunc(SyscallDesc *desc, int num, LiveProcess *p, ThreadContext *tc) { string path; - if (!tc->getMemPort()->tryReadString(path, p->getSyscallArg(tc, 0))) + int index = 0; + if (!tc->getMemPort()->tryReadString(path, p->getSyscallArg(tc, index))) return (TheISA::IntReg)-EFAULT; // Adjust path for current working directory path = p->fullPath(path); - size_t bufsiz = p->getSyscallArg(tc, 2); - BufferArg buf(p->getSyscallArg(tc, 1), bufsiz); + Addr bufPtr = p->getSyscallArg(tc, index); + size_t bufsiz = p->getSyscallArg(tc, index); + + BufferArg buf(bufPtr, bufsiz); int result = readlink(path.c_str(), (char *)buf.bufferPtr(), bufsiz); @@ -323,7 +365,8 @@ unlinkFunc(SyscallDesc *desc, int num, LiveProcess *p, ThreadContext *tc) { string path; - if (!tc->getMemPort()->tryReadString(path, p->getSyscallArg(tc, 0))) + int index = 0; + if (!tc->getMemPort()->tryReadString(path, p->getSyscallArg(tc, index))) return (TheISA::IntReg)-EFAULT; // Adjust path for current working directory @@ -339,13 +382,14 @@ mkdirFunc(SyscallDesc *desc, int num, LiveProcess *p, ThreadContext *tc) { string path; - if (!tc->getMemPort()->tryReadString(path, p->getSyscallArg(tc, 0))) + int index = 0; + if (!tc->getMemPort()->tryReadString(path, p->getSyscallArg(tc, index))) return (TheISA::IntReg)-EFAULT; // Adjust path for current working directory path = p->fullPath(path); - mode_t mode = p->getSyscallArg(tc, 1); + mode_t mode = p->getSyscallArg(tc, index); int result = mkdir(path.c_str(), mode); return (result == -1) ? -errno : result; @@ -356,12 +400,13 @@ renameFunc(SyscallDesc *desc, int num, LiveProcess *p, ThreadContext *tc) { string old_name; - if (!tc->getMemPort()->tryReadString(old_name, p->getSyscallArg(tc, 0))) + int index = 0; + if (!tc->getMemPort()->tryReadString(old_name, p->getSyscallArg(tc, index))) return -EFAULT; string new_name; - if (!tc->getMemPort()->tryReadString(new_name, p->getSyscallArg(tc, 1))) + if (!tc->getMemPort()->tryReadString(new_name, p->getSyscallArg(tc, index))) return -EFAULT; // Adjust path for current working directory @@ -377,10 +422,11 @@ truncateFunc(SyscallDesc *desc, int num, LiveProcess *p, ThreadContext *tc) { string path; - if (!tc->getMemPort()->tryReadString(path, p->getSyscallArg(tc, 0))) + int index = 0; + if (!tc->getMemPort()->tryReadString(path, p->getSyscallArg(tc, index))) return -EFAULT; - off_t length = p->getSyscallArg(tc, 1); + off_t length = p->getSyscallArg(tc, index); // Adjust path for current working directory path = p->fullPath(path); @@ -393,18 +439,62 @@ SyscallReturn ftruncateFunc(SyscallDesc *desc, int num, LiveProcess *process, ThreadContext *tc) { - int fd = process->sim_fd(process->getSyscallArg(tc, 0)); + int index = 0; + int fd = process->sim_fd(process->getSyscallArg(tc, index)); if (fd < 0) return -EBADF; - off_t length = process->getSyscallArg(tc, 1); + off_t length = process->getSyscallArg(tc, index); int result = ftruncate(fd, length); return (result == -1) ? -errno : result; } SyscallReturn +truncate64Func(SyscallDesc *desc, int num, + LiveProcess *process, ThreadContext *tc) +{ + int index = 0; + string path; + + if (!tc->getMemPort()->tryReadString(path, process->getSyscallArg(tc, index))) + return -EFAULT; + + int64_t length = process->getSyscallArg(tc, index, 64); + + // Adjust path for current working directory + path = process->fullPath(path); + +#if NO_STAT64 + int result = truncate(path.c_str(), length); +#else + int result = truncate64(path.c_str(), length); +#endif + return (result == -1) ? -errno : result; +} + +SyscallReturn +ftruncate64Func(SyscallDesc *desc, int num, + LiveProcess *process, ThreadContext *tc) +{ + int index = 0; + int fd = process->sim_fd(process->getSyscallArg(tc, index)); + + if (fd < 0) + return -EBADF; + + int64_t length = process->getSyscallArg(tc, index, 64); + +#if NO_STAT64 + int result = ftruncate(fd, length); +#else + int result = ftruncate64(fd, length); +#endif + return (result == -1) ? -errno : result; +} + +SyscallReturn umaskFunc(SyscallDesc *desc, int num, LiveProcess *process, ThreadContext *tc) { // Letting the simulated program change the simulator's umask seems like @@ -420,13 +510,14 @@ chownFunc(SyscallDesc *desc, int num, LiveProcess *p, ThreadContext *tc) { string path; - if (!tc->getMemPort()->tryReadString(path, p->getSyscallArg(tc, 0))) + int index = 0; + if (!tc->getMemPort()->tryReadString(path, p->getSyscallArg(tc, index))) return -EFAULT; /* XXX endianess */ - uint32_t owner = p->getSyscallArg(tc, 1); + uint32_t owner = p->getSyscallArg(tc, index); uid_t hostOwner = owner; - uint32_t group = p->getSyscallArg(tc, 2); + uint32_t group = p->getSyscallArg(tc, index); gid_t hostGroup = group; // Adjust path for current working directory @@ -439,15 +530,16 @@ chownFunc(SyscallDesc *desc, int num, LiveProcess *p, ThreadContext *tc) SyscallReturn fchownFunc(SyscallDesc *desc, int num, LiveProcess *process, ThreadContext *tc) { - int fd = process->sim_fd(process->getSyscallArg(tc, 0)); + int index = 0; + int fd = process->sim_fd(process->getSyscallArg(tc, index)); if (fd < 0) return -EBADF; /* XXX endianess */ - uint32_t owner = process->getSyscallArg(tc, 1); + uint32_t owner = process->getSyscallArg(tc, index); uid_t hostOwner = owner; - uint32_t group = process->getSyscallArg(tc, 2); + uint32_t group = process->getSyscallArg(tc, index); gid_t hostGroup = group; int result = fchown(fd, hostOwner, hostGroup); @@ -458,11 +550,12 @@ fchownFunc(SyscallDesc *desc, int num, LiveProcess *process, ThreadContext *tc) SyscallReturn dupFunc(SyscallDesc *desc, int num, LiveProcess *process, ThreadContext *tc) { - int fd = process->sim_fd(process->getSyscallArg(tc, 0)); + int index = 0; + int fd = process->sim_fd(process->getSyscallArg(tc, index)); if (fd < 0) return -EBADF; - Process::FdMap *fdo = process->sim_fd_obj(process->getSyscallArg(tc, 0)); + Process::FdMap *fdo = process->sim_fd_obj(fd); int result = dup(fd); return (result == -1) ? -errno : @@ -474,12 +567,13 @@ SyscallReturn fcntlFunc(SyscallDesc *desc, int num, LiveProcess *process, ThreadContext *tc) { - int fd = process->getSyscallArg(tc, 0); + int index = 0; + int fd = process->getSyscallArg(tc, index); if (fd < 0 || process->sim_fd(fd) < 0) return -EBADF; - int cmd = process->getSyscallArg(tc, 1); + int cmd = process->getSyscallArg(tc, index); switch (cmd) { case 0: // F_DUPFD // if we really wanted to support this, we'd need to do it @@ -516,12 +610,13 @@ SyscallReturn fcntl64Func(SyscallDesc *desc, int num, LiveProcess *process, ThreadContext *tc) { - int fd = process->getSyscallArg(tc, 0); + int index = 0; + int fd = process->getSyscallArg(tc, index); if (fd < 0 || process->sim_fd(fd) < 0) return -EBADF; - int cmd = process->getSyscallArg(tc, 1); + int cmd = process->getSyscallArg(tc, index); switch (cmd) { case 33: //F_GETLK64 warn("fcntl64(%d, F_GETLK64) not supported, error returned\n", fd); @@ -605,7 +700,8 @@ setuidFunc(SyscallDesc *desc, int callnum, LiveProcess *process, ThreadContext *tc) { // can't fathom why a benchmark would call this. - warn("Ignoring call to setuid(%d)\n", process->getSyscallArg(tc, 0)); + int index = 0; + warn("Ignoring call to setuid(%d)\n", process->getSyscallArg(tc, index)); return 0; } @@ -661,17 +757,20 @@ SyscallReturn cloneFunc(SyscallDesc *desc, int callnum, LiveProcess *process, ThreadContext *tc) { + int index = 0; + IntReg flags = process->getSyscallArg(tc, index); + IntReg newStack = process->getSyscallArg(tc, index); + DPRINTF(SyscallVerbose, "In sys_clone:\n"); - DPRINTF(SyscallVerbose, " Flags=%llx\n", process->getSyscallArg(tc, 0)); - DPRINTF(SyscallVerbose, " Child stack=%llx\n", - process->getSyscallArg(tc, 1)); + DPRINTF(SyscallVerbose, " Flags=%llx\n", flags); + DPRINTF(SyscallVerbose, " Child stack=%llx\n", newStack); - if (process->getSyscallArg(tc, 0) != 0x10f00) { + if (flags != 0x10f00) { warn("This sys_clone implementation assumes flags " "CLONE_VM|CLONE_FS|CLONE_FILES|CLONE_SIGHAND|CLONE_THREAD " "(0x10f00), and may not work correctly with given flags " - "0x%llx\n", process->getSyscallArg(tc, 0)); + "0x%llx\n", flags); } ThreadContext* ctc; // child thread context @@ -704,7 +803,7 @@ cloneFunc(SyscallDesc *desc, int callnum, LiveProcess *process, #endif // Set up stack register - ctc->setIntReg(TheISA::StackPointerReg, process->getSyscallArg(tc, 1)); + ctc->setIntReg(TheISA::StackPointerReg, newStack); // Set up syscall return values in parent and child ctc->setIntReg(ReturnValueReg, 0); // return value, child diff --git a/src/sim/syscall_emul.hh b/src/sim/syscall_emul.hh index 5f2ebd428..66e800183 100644 --- a/src/sim/syscall_emul.hh +++ b/src/sim/syscall_emul.hh @@ -55,10 +55,12 @@ #include "base/misc.hh" #include "base/trace.hh" #include "base/types.hh" +#include "config/the_isa.hh" #include "cpu/base.hh" #include "cpu/thread_context.hh" #include "mem/translating_port.hh" #include "mem/page_table.hh" +#include "sim/system.hh" #include "sim/process.hh" /// @@ -258,6 +260,15 @@ SyscallReturn ftruncateFunc(SyscallDesc *desc, int num, LiveProcess *p, ThreadContext *tc); +/// Target truncate64() handler. +SyscallReturn truncate64Func(SyscallDesc *desc, int num, + LiveProcess *p, ThreadContext *tc); + +/// Target ftruncate64() handler. +SyscallReturn ftruncate64Func(SyscallDesc *desc, int num, + LiveProcess *p, ThreadContext *tc); + + /// Target umask() handler. SyscallReturn umaskFunc(SyscallDesc *desc, int num, LiveProcess *p, ThreadContext *tc); @@ -462,7 +473,7 @@ copyOutStat64Buf(TranslatingPort * mem, Addr addr, { typedef TypedBufferArg<typename OS::tgt_stat64> tgt_stat_buf; tgt_stat_buf tgt(addr); - convertStatBuf<tgt_stat_buf, hst_stat64>(tgt, host, fakeTTY); + convertStat64Buf<tgt_stat_buf, hst_stat64>(tgt, host, fakeTTY); tgt.copyOut(mem); } @@ -474,8 +485,9 @@ SyscallReturn ioctlFunc(SyscallDesc *desc, int callnum, LiveProcess *process, ThreadContext *tc) { - int fd = process->getSyscallArg(tc, 0); - unsigned req = process->getSyscallArg(tc, 1); + int index = 0; + int fd = process->getSyscallArg(tc, index); + unsigned req = process->getSyscallArg(tc, index); DPRINTF(SyscallVerbose, "ioctl(%d, 0x%x, ...)\n", fd, req); @@ -493,6 +505,7 @@ ioctlFunc(SyscallDesc *desc, int callnum, LiveProcess *process, case OS::TIOCGETC_: case OS::TIOCGETS_: case OS::TIOCGETA_: + case OS::TCSETAW_: return -ENOTTY; default: @@ -509,7 +522,9 @@ openFunc(SyscallDesc *desc, int callnum, LiveProcess *process, { std::string path; - if (!tc->getMemPort()->tryReadString(path, process->getSyscallArg(tc, 0))) + int index = 0; + if (!tc->getMemPort()->tryReadString(path, + process->getSyscallArg(tc, index))) return -EFAULT; if (path == "/dev/sysdev0") { @@ -519,8 +534,8 @@ openFunc(SyscallDesc *desc, int callnum, LiveProcess *process, return -ENOENT; } - int tgtFlags = process->getSyscallArg(tc, 1); - int mode = process->getSyscallArg(tc, 2); + int tgtFlags = process->getSyscallArg(tc, index); + int mode = process->getSyscallArg(tc, index); int hostFlags = 0; // translate open flags @@ -558,6 +573,24 @@ openFunc(SyscallDesc *desc, int callnum, LiveProcess *process, } +/// Target sysinfo() handler. +template <class OS> +SyscallReturn +sysinfoFunc(SyscallDesc *desc, int callnum, LiveProcess *process, + ThreadContext *tc) +{ + + int index = 0; + TypedBufferArg<typename OS::tgt_sysinfo> + sysinfo(process->getSyscallArg(tc, index)); + + sysinfo->uptime=seconds_since_epoch; + sysinfo->totalram=process->system->memSize(); + + sysinfo.copyOut(tc->getMemPort()); + + return 0; +} /// Target chmod() handler. template <class OS> @@ -567,10 +600,13 @@ chmodFunc(SyscallDesc *desc, int callnum, LiveProcess *process, { std::string path; - if (!tc->getMemPort()->tryReadString(path, process->getSyscallArg(tc, 0))) + int index = 0; + if (!tc->getMemPort()->tryReadString(path, + process->getSyscallArg(tc, index))) { return -EFAULT; + } - uint32_t mode = process->getSyscallArg(tc, 1); + uint32_t mode = process->getSyscallArg(tc, index); mode_t hostMode = 0; // XXX translate mode flags via OS::something??? @@ -594,13 +630,14 @@ SyscallReturn fchmodFunc(SyscallDesc *desc, int callnum, LiveProcess *process, ThreadContext *tc) { - int fd = process->getSyscallArg(tc, 0); + int index = 0; + int fd = process->getSyscallArg(tc, index); if (fd < 0 || process->sim_fd(fd) < 0) { // doesn't map to any simulator fd: not a valid target fd return -EBADF; } - uint32_t mode = process->getSyscallArg(tc, 1); + uint32_t mode = process->getSyscallArg(tc, index); mode_t hostMode = 0; // XXX translate mode flags via OS::someting??? @@ -619,10 +656,11 @@ template <class OS> SyscallReturn mremapFunc(SyscallDesc *desc, int callnum, LiveProcess *process, ThreadContext *tc) { - Addr start = process->getSyscallArg(tc, 0); - uint64_t old_length = process->getSyscallArg(tc, 1); - uint64_t new_length = process->getSyscallArg(tc, 2); - uint64_t flags = process->getSyscallArg(tc, 3); + int index = 0; + Addr start = process->getSyscallArg(tc, index); + uint64_t old_length = process->getSyscallArg(tc, index); + uint64_t new_length = process->getSyscallArg(tc, index); + uint64_t flags = process->getSyscallArg(tc, index); if ((start % TheISA::VMPageSize != 0) || (new_length % TheISA::VMPageSize != 0)) { @@ -668,8 +706,12 @@ statFunc(SyscallDesc *desc, int callnum, LiveProcess *process, { std::string path; - if (!tc->getMemPort()->tryReadString(path, process->getSyscallArg(tc, 0))) - return -EFAULT; + int index = 0; + if (!tc->getMemPort()->tryReadString(path, + process->getSyscallArg(tc, index))) { + return -EFAULT; + } + Addr bufPtr = process->getSyscallArg(tc, index); // Adjust path for current working directory path = process->fullPath(path); @@ -680,8 +722,7 @@ statFunc(SyscallDesc *desc, int callnum, LiveProcess *process, if (result < 0) return -errno; - copyOutStatBuf<OS>(tc->getMemPort(), process->getSyscallArg(tc, 1), - &hostBuf); + copyOutStatBuf<OS>(tc->getMemPort(), bufPtr, &hostBuf); return 0; } @@ -695,8 +736,11 @@ stat64Func(SyscallDesc *desc, int callnum, LiveProcess *process, { std::string path; - if (!tc->getMemPort()->tryReadString(path, process->getSyscallArg(tc, 0))) + int index = 0; + if (!tc->getMemPort()->tryReadString(path, + process->getSyscallArg(tc, index))) return -EFAULT; + Addr bufPtr = process->getSyscallArg(tc, index); // Adjust path for current working directory path = process->fullPath(path); @@ -712,8 +756,7 @@ stat64Func(SyscallDesc *desc, int callnum, LiveProcess *process, if (result < 0) return -errno; - copyOutStat64Buf<OS>(tc->getMemPort(), process->getSyscallArg(tc, 1), - &hostBuf); + copyOutStat64Buf<OS>(tc->getMemPort(), bufPtr, &hostBuf); return 0; } @@ -725,7 +768,9 @@ SyscallReturn fstat64Func(SyscallDesc *desc, int callnum, LiveProcess *process, ThreadContext *tc) { - int fd = process->getSyscallArg(tc, 0); + int index = 0; + int fd = process->getSyscallArg(tc, index); + Addr bufPtr = process->getSyscallArg(tc, index); if (fd < 0 || process->sim_fd(fd) < 0) { // doesn't map to any simulator fd: not a valid target fd return -EBADF; @@ -742,8 +787,7 @@ fstat64Func(SyscallDesc *desc, int callnum, LiveProcess *process, if (result < 0) return -errno; - copyOutStat64Buf<OS>(tc->getMemPort(), process->getSyscallArg(tc, 1), - &hostBuf, (fd == 1)); + copyOutStat64Buf<OS>(tc->getMemPort(), bufPtr, &hostBuf, (fd == 1)); return 0; } @@ -757,8 +801,12 @@ lstatFunc(SyscallDesc *desc, int callnum, LiveProcess *process, { std::string path; - if (!tc->getMemPort()->tryReadString(path, process->getSyscallArg(tc, 0))) - return -EFAULT; + int index = 0; + if (!tc->getMemPort()->tryReadString(path, + process->getSyscallArg(tc, index))) { + return -EFAULT; + } + Addr bufPtr = process->getSyscallArg(tc, index); // Adjust path for current working directory path = process->fullPath(path); @@ -769,8 +817,7 @@ lstatFunc(SyscallDesc *desc, int callnum, LiveProcess *process, if (result < 0) return -errno; - copyOutStatBuf<OS>(tc->getMemPort(), process->getSyscallArg(tc, 1), - &hostBuf); + copyOutStatBuf<OS>(tc->getMemPort(), bufPtr, &hostBuf); return 0; } @@ -783,8 +830,12 @@ lstat64Func(SyscallDesc *desc, int callnum, LiveProcess *process, { std::string path; - if (!tc->getMemPort()->tryReadString(path, process->getSyscallArg(tc, 0))) - return -EFAULT; + int index = 0; + if (!tc->getMemPort()->tryReadString(path, + process->getSyscallArg(tc, index))) { + return -EFAULT; + } + Addr bufPtr = process->getSyscallArg(tc, index); // Adjust path for current working directory path = process->fullPath(path); @@ -800,8 +851,7 @@ lstat64Func(SyscallDesc *desc, int callnum, LiveProcess *process, if (result < 0) return -errno; - copyOutStat64Buf<OS>(tc->getMemPort(), process->getSyscallArg(tc, 1), - &hostBuf); + copyOutStat64Buf<OS>(tc->getMemPort(), bufPtr, &hostBuf); return 0; } @@ -812,7 +862,9 @@ SyscallReturn fstatFunc(SyscallDesc *desc, int callnum, LiveProcess *process, ThreadContext *tc) { - int fd = process->sim_fd(process->getSyscallArg(tc, 0)); + int index = 0; + int fd = process->sim_fd(process->getSyscallArg(tc, index)); + Addr bufPtr = process->getSyscallArg(tc, index); DPRINTF(SyscallVerbose, "fstat(%d, ...)\n", fd); @@ -825,8 +877,7 @@ fstatFunc(SyscallDesc *desc, int callnum, LiveProcess *process, if (result < 0) return -errno; - copyOutStatBuf<OS>(tc->getMemPort(), process->getSyscallArg(tc, 1), - &hostBuf, (fd == 1)); + copyOutStatBuf<OS>(tc->getMemPort(), bufPtr, &hostBuf, (fd == 1)); return 0; } @@ -840,8 +891,12 @@ statfsFunc(SyscallDesc *desc, int callnum, LiveProcess *process, { std::string path; - if (!tc->getMemPort()->tryReadString(path, process->getSyscallArg(tc, 0))) - return -EFAULT; + int index = 0; + if (!tc->getMemPort()->tryReadString(path, + process->getSyscallArg(tc, index))) { + return -EFAULT; + } + Addr bufPtr = process->getSyscallArg(tc, index); // Adjust path for current working directory path = process->fullPath(path); @@ -852,8 +907,7 @@ statfsFunc(SyscallDesc *desc, int callnum, LiveProcess *process, if (result < 0) return -errno; - OS::copyOutStatfsBuf(tc->getMemPort(), - (Addr)(process->getSyscallArg(tc, 1)), &hostBuf); + OS::copyOutStatfsBuf(tc->getMemPort(), bufPtr, &hostBuf); return 0; } @@ -865,7 +919,9 @@ SyscallReturn fstatfsFunc(SyscallDesc *desc, int callnum, LiveProcess *process, ThreadContext *tc) { - int fd = process->sim_fd(process->getSyscallArg(tc, 0)); + int index = 0; + int fd = process->sim_fd(process->getSyscallArg(tc, index)); + Addr bufPtr = process->getSyscallArg(tc, index); if (fd < 0) return -EBADF; @@ -876,8 +932,7 @@ fstatfsFunc(SyscallDesc *desc, int callnum, LiveProcess *process, if (result < 0) return -errno; - OS::copyOutStatfsBuf(tc->getMemPort(), process->getSyscallArg(tc, 1), - &hostBuf); + OS::copyOutStatfsBuf(tc->getMemPort(), bufPtr, &hostBuf); return 0; } @@ -889,15 +944,16 @@ SyscallReturn writevFunc(SyscallDesc *desc, int callnum, LiveProcess *process, ThreadContext *tc) { - int fd = process->getSyscallArg(tc, 0); + int index = 0; + int fd = process->getSyscallArg(tc, index); if (fd < 0 || process->sim_fd(fd) < 0) { // doesn't map to any simulator fd: not a valid target fd return -EBADF; } TranslatingPort *p = tc->getMemPort(); - uint64_t tiov_base = process->getSyscallArg(tc, 1); - size_t count = process->getSyscallArg(tc, 2); + uint64_t tiov_base = process->getSyscallArg(tc, index); + size_t count = process->getSyscallArg(tc, index); struct iovec hiov[count]; for (size_t i = 0; i < count; ++i) { typename OS::tgt_iovec tiov; @@ -938,12 +994,13 @@ template <class OS> SyscallReturn mmapFunc(SyscallDesc *desc, int num, LiveProcess *p, ThreadContext *tc) { - Addr start = p->getSyscallArg(tc, 0); - uint64_t length = p->getSyscallArg(tc, 1); - // int prot = p->getSyscallArg(tc, 2); - int flags = p->getSyscallArg(tc, 3); - // int fd = p->sim_fd(p->getSyscallArg(tc, 4)); - // int offset = p->getSyscallArg(tc, 5); + int index = 0; + Addr start = p->getSyscallArg(tc, index); + uint64_t length = p->getSyscallArg(tc, index); + index++; // int prot = p->getSyscallArg(tc, index); + int flags = p->getSyscallArg(tc, index); + int fd = p->sim_fd(p->getSyscallArg(tc, index)); + // int offset = p->getSyscallArg(tc, index); if ((start % TheISA::VMPageSize) != 0 || @@ -960,13 +1017,18 @@ mmapFunc(SyscallDesc *desc, int num, LiveProcess *p, ThreadContext *tc) } // pick next address from our "mmap region" - start = p->mmap_end; + if (OS::mmapGrowsDown()) { + start = p->mmap_end - length; + p->mmap_end = start; + } else { + start = p->mmap_end; + p->mmap_end += length; + } p->pTable->allocate(start, length); - p->mmap_end += length; if (!(flags & OS::TGT_MAP_ANONYMOUS)) { warn("allowing mmap of file @ fd %d. " - "This will break if not /dev/zero.", p->getSyscallArg(tc, 4)); + "This will break if not /dev/zero.", fd); } return start; @@ -978,8 +1040,9 @@ SyscallReturn getrlimitFunc(SyscallDesc *desc, int callnum, LiveProcess *process, ThreadContext *tc) { - unsigned resource = process->getSyscallArg(tc, 0); - TypedBufferArg<typename OS::rlimit> rlp(process->getSyscallArg(tc, 1)); + int index = 0; + unsigned resource = process->getSyscallArg(tc, index); + TypedBufferArg<typename OS::rlimit> rlp(process->getSyscallArg(tc, index)); switch (resource) { case OS::TGT_RLIMIT_STACK: @@ -1013,7 +1076,8 @@ SyscallReturn gettimeofdayFunc(SyscallDesc *desc, int callnum, LiveProcess *process, ThreadContext *tc) { - TypedBufferArg<typename OS::timeval> tp(process->getSyscallArg(tc, 0)); + int index = 0; + TypedBufferArg<typename OS::timeval> tp(process->getSyscallArg(tc, index)); getElapsedTime(tp->tv_sec, tp->tv_usec); tp->tv_sec += seconds_since_epoch; @@ -1034,10 +1098,14 @@ utimesFunc(SyscallDesc *desc, int callnum, LiveProcess *process, { std::string path; - if (!tc->getMemPort()->tryReadString(path, process->getSyscallArg(tc, 0))) - return -EFAULT; + int index = 0; + if (!tc->getMemPort()->tryReadString(path, + process->getSyscallArg(tc, index))) { + return -EFAULT; + } - TypedBufferArg<typename OS::timeval [2]> tp(process->getSyscallArg(tc, 1)); + TypedBufferArg<typename OS::timeval [2]> + tp(process->getSyscallArg(tc, index)); tp.copyIn(tc->getMemPort()); struct timeval hostTimeval[2]; @@ -1063,8 +1131,9 @@ SyscallReturn getrusageFunc(SyscallDesc *desc, int callnum, LiveProcess *process, ThreadContext *tc) { - int who = process->getSyscallArg(tc, 0); // THREAD, SELF, or CHILDREN - TypedBufferArg<typename OS::rusage> rup(process->getSyscallArg(tc, 1)); + int index = 0; + int who = process->getSyscallArg(tc, index); // THREAD, SELF, or CHILDREN + TypedBufferArg<typename OS::rusage> rup(process->getSyscallArg(tc, index)); rup->ru_utime.tv_sec = 0; rup->ru_utime.tv_usec = 0; @@ -1108,7 +1177,52 @@ getrusageFunc(SyscallDesc *desc, int callnum, LiveProcess *process, return 0; } +/// Target times() function. +template <class OS> +SyscallReturn +timesFunc(SyscallDesc *desc, int callnum, LiveProcess *process, + ThreadContext *tc) +{ + int index = 0; + TypedBufferArg<typename OS::tms> bufp(process->getSyscallArg(tc, index)); + + // Fill in the time structure (in clocks) + int64_t clocks = curTick * OS::M5_SC_CLK_TCK / Clock::Int::s; + bufp->tms_utime = clocks; + bufp->tms_stime = 0; + bufp->tms_cutime = 0; + bufp->tms_cstime = 0; + // Convert to host endianness + bufp->tms_utime = htog(bufp->tms_utime); + + // Write back + bufp.copyOut(tc->getMemPort()); + + // Return clock ticks since system boot + return clocks; +} + +/// Target time() function. +template <class OS> +SyscallReturn +timeFunc(SyscallDesc *desc, int callnum, LiveProcess *process, + ThreadContext *tc) +{ + typename OS::time_t sec, usec; + getElapsedTime(sec, usec); + sec += seconds_since_epoch; + + int index = 0; + Addr taddr = (Addr)process->getSyscallArg(tc, index); + if(taddr != 0) { + typename OS::time_t t = sec; + t = htog(t); + TranslatingPort *p = tc->getMemPort(); + p->writeBlob(taddr, (uint8_t*)&t, (int)sizeof(typename OS::time_t)); + } + return sec; +} #endif // __SIM_SYSCALL_EMUL_HH__ diff --git a/src/sim/system.cc b/src/sim/system.cc index f10167bba..da77f1995 100644 --- a/src/sim/system.cc +++ b/src/sim/system.cc @@ -38,11 +38,14 @@ #include "base/loader/symtab.hh" #include "base/trace.hh" #include "cpu/thread_context.hh" +#include "config/full_system.hh" +#include "config/the_isa.hh" #include "mem/mem_object.hh" #include "mem/physical.hh" #include "sim/byteswap.hh" #include "sim/system.hh" #include "sim/debug.hh" + #if FULL_SYSTEM #include "arch/vtophys.hh" #include "kern/kernel_stats.hh" diff --git a/src/sim/system.hh b/src/sim/system.hh index aa89866bd..eabbc8351 100644 --- a/src/sim/system.hh +++ b/src/sim/system.hh @@ -45,6 +45,7 @@ #include "mem/port.hh" #include "params/System.hh" #include "sim/sim_object.hh" + #if FULL_SYSTEM #include "kern/system_events.hh" #include "mem/vport.hh" @@ -59,10 +60,7 @@ class PhysicalMemory; class Platform; #endif class GDBListener; -namespace TheISA -{ - class RemoteGDB; -} +class BaseRemoteGDB; class System : public SimObject { @@ -187,7 +185,7 @@ class System : public SimObject #endif public: - std::vector<TheISA::RemoteGDB *> remoteGDB; + std::vector<BaseRemoteGDB *> remoteGDB; std::vector<GDBListener *> gdbListen; bool breakpoint(); |