diff options
253 files changed, 16349 insertions, 8688 deletions
diff --git a/SConscript b/SConscript index 8f2ae761d..a2d5de279 100644 --- a/SConscript +++ b/SConscript @@ -62,6 +62,7 @@ base_sources = Split(''' base/range.cc base/random.cc base/sat_counter.cc + base/serializer.cc base/socket.cc base/statistics.cc base/str.cc @@ -81,70 +82,21 @@ base_sources = Split(''' base/stats/text.cc cpu/base.cc - cpu/base_dyn_inst.cc cpu/cpu_exec_context.cc cpu/exetrace.cc + cpu/op_class.cc cpu/pc_event.cc cpu/static_inst.cc cpu/sampler/sampler.cc - cpu/trace/reader/mem_trace_reader.cc - cpu/trace/reader/ibm_reader.cc - cpu/trace/reader/itx_reader.cc - cpu/trace/reader/m5_reader.cc - cpu/trace/opt_cpu.cc - cpu/trace/trace_cpu.cc - - encumbered/mem/functional/main.cc - - mem/base_hier.cc - mem/base_mem.cc - mem/hier_params.cc - mem/mem_cmd.cc - mem/mem_debug.cc - mem/mem_req.cc - mem/memory_interface.cc - mem/bus/base_interface.cc - mem/bus/bus.cc - mem/bus/bus_bridge.cc - mem/bus/bus_bridge_master.cc - mem/bus/bus_bridge_slave.cc - mem/bus/bus_interface.cc - mem/bus/dma_bus_interface.cc - mem/bus/dma_interface.cc - mem/bus/master_interface.cc - mem/bus/slave_interface.cc - mem/cache/base_cache.cc - mem/cache/cache.cc - mem/cache/cache_builder.cc - mem/cache/coherence/coherence_protocol.cc - mem/cache/coherence/uni_coherence.cc - mem/cache/miss/blocking_buffer.cc - mem/cache/miss/miss_queue.cc - mem/cache/miss/mshr.cc - mem/cache/miss/mshr_queue.cc - mem/cache/prefetch/base_prefetcher.cc - mem/cache/prefetch/prefetcher.cc - mem/cache/prefetch/tagged_prefetcher.cc - mem/cache/tags/base_tags.cc - mem/cache/tags/cache_tags.cc - mem/cache/tags/fa_lru.cc - mem/cache/tags/iic.cc - mem/cache/tags/lru.cc - mem/cache/tags/repl/gen.cc - mem/cache/tags/repl/repl.cc - mem/cache/tags/split.cc - mem/cache/tags/split_lru.cc - mem/cache/tags/split_lifo.cc - mem/functional/functional.cc - mem/timing/base_memory.cc - mem/timing/dram_memory.cc - mem/timing/dram_mem_bank.cc - mem/timing/dram_memory_builder.cc - mem/timing/memory_builder.cc - mem/timing/simple_mem_bank.cc - mem/trace/itx_writer.cc - mem/trace/mem_trace_writer.cc - mem/trace/m5_writer.cc + + mem/bridge.cc + mem/bus.cc + mem/connector.cc + mem/mem_object.cc + mem/packet.cc + mem/physical.cc + mem/port.cc + mem/request.cc python/pyconfig.cc python/embedded_py.cc @@ -165,6 +117,7 @@ base_sources = Split(''' sim/startup.cc sim/stat_context.cc sim/stat_control.cc + sim/system.cc sim/trace_context.cc ''') @@ -207,6 +160,17 @@ full_cpu_sources = Split(''' encumbered/cpu/full/iq/standard/iq_standard.cc ''') +trace_reader_sources = Split(''' + cpu/trace/reader/mem_trace_reader.cc + cpu/trace/reader/ibm_reader.cc + cpu/trace/reader/itx_reader.cc + cpu/trace/reader/m5_reader.cc + cpu/trace/opt_cpu.cc + cpu/trace/trace_cpu.cc + ''') + + + # MySql sources mysql_sources = Split(''' base/mysql.cc @@ -224,30 +188,32 @@ full_system_sources = Split(''' dev/alpha_console.cc dev/baddev.cc - dev/simconsole.cc dev/disk_image.cc dev/etherbus.cc dev/etherdump.cc dev/etherint.cc dev/etherlink.cc dev/etherpkt.cc - dev/ethertap.cc - dev/ide_ctrl.cc + dev/ethertap.cc + dev/ide_ctrl.cc dev/ide_disk.cc dev/io_device.cc + dev/isa_fake.cc dev/ns_gige.cc dev/pciconfigall.cc dev/pcidev.cc dev/pcifake.cc dev/pktfifo.cc dev/platform.cc - dev/sinic.cc + dev/simconsole.cc dev/simple_disk.cc + dev/sinic.cc dev/tsunami.cc dev/tsunami_cchip.cc - dev/isa_fake.cc dev/tsunami_io.cc + dev/tsunami_fake.cc dev/tsunami_pchip.cc + dev/uart.cc dev/uart8250.cc @@ -257,16 +223,19 @@ full_system_sources = Split(''' kern/linux/events.cc kern/linux/linux_syscalls.cc kern/linux/printk.cc + + mem/vport.cc + + sim/pseudo_inst.cc + ''') + + +if env['TARGET_ISA'] == 'alpha': + full_system_sources += Split(''' kern/tru64/dump_mbuf.cc kern/tru64/printf.cc kern/tru64/tru64_events.cc kern/tru64/tru64_syscalls.cc - - mem/functional/memory_control.cc - mem/functional/physical.cc - - sim/system.cc - sim/pseudo_inst.cc ''') # turbolaser encumbered sources @@ -291,16 +260,30 @@ turbolaser_sources = Split(''' # Syscall emulation (non-full-system) sources syscall_emulation_sources = Split(''' - cpu/memtest/memtest.cc - encumbered/eio/eio.cc - encumbered/eio/exolex.cc - encumbered/eio/libexo.cc - kern/linux/linux.cc - kern/tru64/tru64.cc + mem/translating_port.cc + mem/page_table.cc sim/process.cc sim/syscall_emul.cc ''') +#if env['TARGET_ISA'] == 'alpha': +# syscall_emulation_sources += Split(''' +# kern/tru64/tru64.cc +# ''') + +alpha_eio_sources = Split(''' + encumbered/eio/exolex.cc + encumbered/eio/libexo.cc + encumbered/eio/eio.cc + ''') + +if env['TARGET_ISA'] == 'ALPHA_ISA': + syscall_emulation_sources += alpha_eio_sources + +memtest_sources = Split(''' + cpu/memtest/memtest.cc + ''') + # Add a flag defining what THE_ISA should be for all compilation env.Append(CPPDEFINES=[('THE_ISA','%s_ISA' % env['TARGET_ISA'].upper())]) @@ -380,7 +363,7 @@ env.Append(CPPPATH='./libelf') # Debug binary debugEnv = env.Copy(OBJSUFFIX='.do') debugEnv.Label = 'debug' -debugEnv.Append(CCFLAGS=Split('-g -gstabs+ -O0')) +debugEnv.Append(CCFLAGS=Split('-g3 -gdwarf-2 -O0')) debugEnv.Append(CPPDEFINES='DEBUG') tlist = debugEnv.Program(target = 'm5.debug', source = make_objs(sources, debugEnv)) @@ -389,7 +372,7 @@ debugEnv.M5Binary = tlist[0] # Optimized binary optEnv = env.Copy() optEnv.Label = 'opt' -optEnv.Append(CCFLAGS=Split('-g -O5')) +optEnv.Append(CCFLAGS=Split('-g -O3')) tlist = optEnv.Program(target = 'm5.opt', source = make_objs(sources, optEnv)) optEnv.M5Binary = tlist[0] @@ -397,7 +380,7 @@ optEnv.M5Binary = tlist[0] # "Fast" binary fastEnv = env.Copy(OBJSUFFIX='.fo') fastEnv.Label = 'fast' -fastEnv.Append(CCFLAGS=Split('-O5')) +fastEnv.Append(CCFLAGS=Split('-O3')) fastEnv.Append(CPPDEFINES='NDEBUG') fastEnv.Program(target = 'm5.fast.unstripped', source = make_objs(sources, fastEnv)) @@ -409,7 +392,7 @@ fastEnv.M5Binary = tlist[0] # Profiled binary profEnv = env.Copy(OBJSUFFIX='.po') profEnv.Label = 'prof' -profEnv.Append(CCFLAGS=Split('-O5 -g -pg'), LINKFLAGS='-pg') +profEnv.Append(CCFLAGS=Split('-O3 -g -pg'), LINKFLAGS='-pg') tlist = profEnv.Program(target = 'm5.prof', source = make_objs(sources, profEnv)) profEnv.M5Binary = tlist[0] diff --git a/arch/SConscript b/arch/SConscript index 0533261a2..99c861568 100644 --- a/arch/SConscript +++ b/arch/SConscript @@ -45,13 +45,17 @@ sources = [] # List of headers to generate isa_switch_hdrs = Split(''' + arguments.hh + constants.hh + faults.hh isa_traits.hh - tlb.hh process.hh - arguments.hh + regfile.hh stacktrace.hh + tlb.hh + types.hh + utility.hh vtophys.hh - faults.hh ''') # Generate the header. target[0] is the full path of the output @@ -96,18 +100,12 @@ for hdr in isa_switch_hdrs: # import SCons.Scanner -def ISAScan(): - return SCons.Scanner.Classic("ISAScan", - "$ISASUFFIXES", - "SRCDIR", - '^[ \t]*##[ \t]*include[ \t]*"([^>"]+)"') - -def ISAPath(env, dir, target=None, source=None, a=None): - return (Dir(env['SRCDIR']), Dir('.')) +isa_scanner = SCons.Scanner.Classic("ISAScan", + [".isa", ".ISA"], + "SRCDIR", + r'^\s*##include\s+"([\w/.-]*)"') -iscan = Scanner(function = ISAScan().scan, skeys = [".isa", ".ISA"], - path_function = ISAPath) -env.Append(SCANNERS = iscan) +env.Append(SCANNERS = isa_scanner) # # Now create a Builder object that uses isa_parser.py to generate C++ @@ -134,8 +132,7 @@ def isa_desc_emitter(target, source, env): return (isa_desc_gen_files, [isa_parser, cpu_models_file] + source) # Pieces are in place, so create the builder. -isa_desc_builder = Builder(action='$SOURCES $TARGET.dir $CPU_MODELS', - source_scanner = iscan, +isa_desc_builder = Builder(action='python $SOURCES $TARGET.dir $CPU_MODELS', emitter = isa_desc_emitter) env.Append(BUILDERS = { 'ISADesc' : isa_desc_builder }) diff --git a/arch/alpha/SConscript b/arch/alpha/SConscript index ed7fd3404..1b20f8b1f 100644 --- a/arch/alpha/SConscript +++ b/arch/alpha/SConscript @@ -65,7 +65,9 @@ full_system_sources = Split(''' # Syscall emulation (non-full-system) sources syscall_emulation_sources = Split(''' + linux/linux.cc linux/process.cc + tru64/tru64.cc tru64/process.cc process.cc ''') diff --git a/arch/alpha/arguments.cc b/arch/alpha/arguments.cc index 019390aeb..adc371682 100644 --- a/arch/alpha/arguments.cc +++ b/arch/alpha/arguments.cc @@ -29,7 +29,7 @@ #include "arch/alpha/arguments.hh" #include "arch/alpha/vtophys.hh" #include "cpu/exec_context.hh" -#include "mem/functional/physical.hh" +#include "mem/vport.hh" using namespace AlphaISA; @@ -54,13 +54,15 @@ AlphaArguments::getArg(bool fp) { if (number < 6) { if (fp) - return xc->readFloatRegInt(16 + number); + return xc->readFloatRegBits(16 + number); else return xc->readIntReg(16 + number); } else { Addr sp = xc->readIntReg(30); - Addr paddr = vtophys(xc, sp + (number-6) * sizeof(uint64_t)); - return xc->getPhysMemPtr()->phys_read_qword(paddr); + VirtualPort *vp = xc->getVirtPort(xc); + uint64_t arg = vp->read<uint64_t>(sp + (number-6) * sizeof(uint64_t)); + xc->delVirtPort(vp); + return arg; } } diff --git a/arch/alpha/arguments.hh b/arch/alpha/arguments.hh index 75346bf58..bd1c6cb1d 100644 --- a/arch/alpha/arguments.hh +++ b/arch/alpha/arguments.hh @@ -26,8 +26,8 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef __ARGUMENTS_HH__ -#define __ARGUMENTS_HH__ +#ifndef __ARCH_ALPHA_ARGUMENTS_HH__ +#define __ARCH_ALPHA_ARGUMENTS_HH__ #include <assert.h> @@ -37,6 +37,8 @@ class ExecContext; +namespace AlphaISA { + class AlphaArguments { protected: @@ -135,9 +137,11 @@ class AlphaArguments operator char *() { char *buf = data->alloc(2048); - CopyString(xc, buf, getArg(), 2048); + CopyStringOut(xc, buf, getArg(), 2048); return buf; } }; -#endif // __ARGUMENTS_HH__ +}; // namespace AlphaISA + +#endif // __ARCH_ALPHA_ARGUMENTS_HH__ diff --git a/arch/alpha/ev5.cc b/arch/alpha/ev5.cc index 019e83dd4..12f7659e6 100644 --- a/arch/alpha/ev5.cc +++ b/arch/alpha/ev5.cc @@ -36,7 +36,6 @@ #include "cpu/base.hh" #include "cpu/cpu_exec_context.hh" #include "cpu/exec_context.hh" -#include "cpu/fast/cpu.hh" #include "kern/kernel_stats.hh" #include "sim/debug.hh" #include "sim/sim_events.hh" @@ -134,7 +133,7 @@ AlphaISA::zeroRegisters(CPU *cpu) // (no longer very clean due to the change in setIntReg() in the // cpu model. Consider changing later.) cpu->cpuXC->setIntReg(ZeroReg, 0); - cpu->cpuXC->setFloatRegDouble(ZeroReg, 0.0); + cpu->cpuXC->setFloatReg(ZeroReg, 0.0); } Fault @@ -542,10 +541,10 @@ AlphaISA::MiscRegFile::setIpr(int idx, uint64_t val, ExecContext *xc) } void -AlphaISA::MiscRegFile::copyIprs(ExecContext *xc) +AlphaISA::copyIprs(ExecContext *src, ExecContext *dest) { for (int i = IPR_Base_DepTag; i < NumInternalProcRegs; ++i) { - ipr[i] = xc->readMiscReg(i); + dest->setMiscReg(i, src->readMiscReg(i)); } } @@ -575,12 +574,4 @@ CPUExecContext::simPalCheck(int palFunc) return true; } -//Forward instantiation for FastCPU object -template -void AlphaISA::processInterrupts(FastCPU *xc); - -//Forward instantiation for FastCPU object -template -void AlphaISA::zeroRegisters(FastCPU *xc); - #endif // FULL_SYSTEM diff --git a/arch/alpha/faults.cc b/arch/alpha/faults.cc index e0918da21..c8cb9124e 100644 --- a/arch/alpha/faults.cc +++ b/arch/alpha/faults.cc @@ -30,6 +30,9 @@ #include "cpu/exec_context.hh" #include "cpu/base.hh" #include "base/trace.hh" +#if FULL_SYSTEM +#include "arch/alpha/ev5.hh" +#endif namespace AlphaISA { @@ -70,6 +73,10 @@ FaultName DtbAcvFault::_name = "dfault"; FaultVect DtbAcvFault::_vect = 0x0381; FaultStat DtbAcvFault::_count; +FaultName DtbAlignmentFault::_name = "unalign"; +FaultVect DtbAlignmentFault::_vect = 0x0301; +FaultStat DtbAlignmentFault::_count; + FaultName ItbMissFault::_name = "itbmiss"; FaultVect ItbMissFault::_vect = 0x0181; FaultStat ItbMissFault::_count; @@ -98,6 +105,10 @@ FaultName IntegerOverflowFault::_name = "intover"; FaultVect IntegerOverflowFault::_vect = 0x0501; FaultStat IntegerOverflowFault::_count; +FaultName UnimpFault::_name = "Unimplemented Simulator feature"; +FaultVect UnimpFault::_vect = 0x0001; +FaultStat UnimpFault::_count; + #if FULL_SYSTEM void AlphaFault::invoke(ExecContext * xc) @@ -125,6 +136,50 @@ void ArithmeticFault::invoke(ExecContext * xc) panic("Arithmetic traps are unimplemented!"); } +void DtbFault::invoke(ExecContext * xc) +{ + // Set fault address and flags. Even though we're modeling an + // EV5, we use the EV6 technique of not latching fault registers + // on VPTE loads (instead of locking the registers until IPR_VA is + // read, like the EV5). The EV6 approach is cleaner and seems to + // work with EV5 PAL code, but not the other way around. + if (!xc->misspeculating() + && !(reqFlags & VPTE) && !(reqFlags & NO_FAULT)) { + // set VA register with faulting address + xc->setMiscReg(AlphaISA::IPR_VA, vaddr); + + // set MM_STAT register flags + xc->setMiscReg(AlphaISA::IPR_MM_STAT, + (((EV5::Opcode(xc->getInst()) & 0x3f) << 11) + | ((EV5::Ra(xc->getInst()) & 0x1f) << 6) + | (flags & 0x3f))); + + // set VA_FORM register with faulting formatted address + xc->setMiscReg(AlphaISA::IPR_VA_FORM, + xc->readMiscReg(AlphaISA::IPR_MVPTBR) | (vaddr.vpn() << 3)); + } + + AlphaFault::invoke(xc); +} + +void ItbFault::invoke(ExecContext * xc) +{ + if (!xc->misspeculating()) { + xc->setMiscReg(AlphaISA::IPR_ITB_TAG, pc); + xc->setMiscReg(AlphaISA::IPR_IFAULT_VA_FORM, + xc->readMiscReg(AlphaISA::IPR_IVPTBR) | + (AlphaISA::VAddr(pc).vpn() << 3)); + } + + AlphaFault::invoke(xc); +} + +void UnimpFault::invoke(ExecContext * xc) +{ + FaultBase::invoke(xc); + panic("Unimpfault: %s\n", panicStr.c_str()); +} + #endif } // namespace AlphaISA diff --git a/arch/alpha/faults.hh b/arch/alpha/faults.hh index 1a196cc94..5024c124b 100644 --- a/arch/alpha/faults.hh +++ b/arch/alpha/faults.hh @@ -29,6 +29,7 @@ #ifndef __ALPHA_FAULTS_HH__ #define __ALPHA_FAULTS_HH__ +#include "arch/alpha/isa_traits.hh" #include "sim/faults.hh" // The design of the "name" and "vect" functions is in sim/faults.hh @@ -130,85 +131,167 @@ class InterruptFault : public AlphaFault FaultStat & countStat() {return _count;} }; -class NDtbMissFault : public AlphaFault +class DtbFault : public AlphaFault +{ +#if FULL_SYSTEM + private: + AlphaISA::VAddr vaddr; + uint32_t reqFlags; + uint64_t flags; + public: + DtbFault(AlphaISA::VAddr _vaddr, uint32_t _reqFlags, uint64_t _flags) + : vaddr(_vaddr), reqFlags(_reqFlags), flags(_flags) + { } +#endif + FaultName name() = 0; + FaultVect vect() = 0; + FaultStat & countStat() = 0; +#if FULL_SYSTEM + void invoke(ExecContext * xc); +#endif +}; + +class NDtbMissFault : public DtbFault { private: static FaultName _name; static FaultVect _vect; static FaultStat _count; public: +#if FULL_SYSTEM + NDtbMissFault(AlphaISA::VAddr vaddr, uint32_t reqFlags, uint64_t flags) + : DtbFault(vaddr, reqFlags, flags) + { } +#endif FaultName name() {return _name;} FaultVect vect() {return _vect;} FaultStat & countStat() {return _count;} }; -class PDtbMissFault : public AlphaFault +class PDtbMissFault : public DtbFault { private: static FaultName _name; static FaultVect _vect; static FaultStat _count; public: +#if FULL_SYSTEM + PDtbMissFault(AlphaISA::VAddr vaddr, uint32_t reqFlags, uint64_t flags) + : DtbFault(vaddr, reqFlags, flags) + { } +#endif + FaultName name() {return _name;} + FaultVect vect() {return _vect;} + FaultStat & countStat() {return _count;} +}; + +class DtbPageFault : public DtbFault +{ + private: + static FaultName _name; + static FaultVect _vect; + static FaultStat _count; + public: +#if FULL_SYSTEM + DtbPageFault(AlphaISA::VAddr vaddr, uint32_t reqFlags, uint64_t flags) + : DtbFault(vaddr, reqFlags, flags) + { } +#endif FaultName name() {return _name;} FaultVect vect() {return _vect;} FaultStat & countStat() {return _count;} }; -class DtbPageFault : public AlphaFault +class DtbAcvFault : public DtbFault { private: static FaultName _name; static FaultVect _vect; static FaultStat _count; public: +#if FULL_SYSTEM + DtbAcvFault(AlphaISA::VAddr vaddr, uint32_t reqFlags, uint64_t flags) + : DtbFault(vaddr, reqFlags, flags) + { } +#endif FaultName name() {return _name;} FaultVect vect() {return _vect;} FaultStat & countStat() {return _count;} }; -class DtbAcvFault : public AlphaFault +class DtbAlignmentFault : public DtbFault { private: static FaultName _name; static FaultVect _vect; static FaultStat _count; public: +#if FULL_SYSTEM + DtbAlignmentFault(AlphaISA::VAddr vaddr, uint32_t reqFlags, uint64_t flags) + : DtbFault(vaddr, reqFlags, flags) + { } +#endif FaultName name() {return _name;} FaultVect vect() {return _vect;} FaultStat & countStat() {return _count;} }; -class ItbMissFault : public AlphaFault +class ItbFault : public AlphaFault +{ + private: + Addr pc; + public: + ItbFault(Addr _pc) + : pc(_pc) + { } + FaultName name() = 0; + FaultVect vect() = 0; + FaultStat & countStat() = 0; +#if FULL_SYSTEM + void invoke(ExecContext * xc); +#endif +}; + +class ItbMissFault : public ItbFault { private: static FaultName _name; static FaultVect _vect; static FaultStat _count; public: + ItbMissFault(Addr pc) + : ItbFault(pc) + { } FaultName name() {return _name;} FaultVect vect() {return _vect;} FaultStat & countStat() {return _count;} }; -class ItbPageFault : public AlphaFault +class ItbPageFault : public ItbFault { private: static FaultName _name; static FaultVect _vect; static FaultStat _count; public: + ItbPageFault(Addr pc) + : ItbFault(pc) + { } FaultName name() {return _name;} FaultVect vect() {return _vect;} FaultStat & countStat() {return _count;} }; -class ItbAcvFault : public AlphaFault +class ItbAcvFault : public ItbFault { private: static FaultName _name; static FaultVect _vect; static FaultStat _count; public: + ItbAcvFault(Addr pc) + : ItbFault(pc) + { } FaultName name() {return _name;} FaultVect vect() {return _vect;} FaultStat & countStat() {return _count;} @@ -264,6 +347,26 @@ class IntegerOverflowFault : public AlphaFault FaultStat & countStat() {return _count;} }; +class UnimpFault : public AlphaFault +{ + private: + std::string panicStr; + static FaultName _name; + static FaultVect _vect; + static FaultStat _count; + public: + UnimpFault(std::string _str) + : panicStr(_str) + { } + + FaultName name() {return _name;} + FaultVect vect() {return _vect;} + FaultStat & countStat() {return _count;} +#if FULL_SYSTEM + void invoke(ExecContext * xc); +#endif +}; + } // AlphaISA namespace #endif // __FAULTS_HH__ diff --git a/arch/alpha/freebsd/system.cc b/arch/alpha/freebsd/system.cc index e32053afd..3e50fb9a5 100644 --- a/arch/alpha/freebsd/system.cc +++ b/arch/alpha/freebsd/system.cc @@ -37,8 +37,8 @@ #include "arch/alpha/freebsd/system.hh" #include "base/loader/symtab.hh" #include "cpu/exec_context.hh" -#include "mem/functional/memory_control.hh" -#include "mem/functional/physical.hh" +#include "mem/physical.hh" +#include "mem/port.hh" #include "arch/isa_traits.hh" #include "sim/builder.hh" #include "sim/byteswap.hh" @@ -74,20 +74,12 @@ FreebsdAlphaSystem::doCalibrateClocks(ExecContext *xc) { Addr ppc_vaddr = 0; Addr timer_vaddr = 0; - Addr ppc_paddr = 0; - Addr timer_paddr = 0; ppc_vaddr = (Addr)xc->readIntReg(ArgumentReg1); timer_vaddr = (Addr)xc->readIntReg(ArgumentReg2); - ppc_paddr = vtophys(physmem, ppc_vaddr); - timer_paddr = vtophys(physmem, timer_vaddr); - - uint8_t *ppc = physmem->dma_addr(ppc_paddr, sizeof(uint32_t)); - uint8_t *timer = physmem->dma_addr(timer_paddr, sizeof(uint32_t)); - - *(uint32_t *)ppc = htog((uint32_t)Clock::Frequency); - *(uint32_t *)timer = htog((uint32_t)TIMER_FREQUENCY); + virtPort.write(ppc_vaddr, (uint32_t)Clock::Frequency); + virtPort.write(timer_vaddr, (uint32_t)TIMER_FREQUENCY); } @@ -102,7 +94,6 @@ FreebsdAlphaSystem::SkipCalibrateClocksEvent::process(ExecContext *xc) BEGIN_DECLARE_SIM_OBJECT_PARAMS(FreebsdAlphaSystem) Param<Tick> boot_cpu_frequency; - SimObjectParam<MemoryController *> memctrl; SimObjectParam<PhysicalMemory *> physmem; Param<string> kernel; @@ -125,7 +116,6 @@ END_DECLARE_SIM_OBJECT_PARAMS(FreebsdAlphaSystem) BEGIN_INIT_SIM_OBJECT_PARAMS(FreebsdAlphaSystem) INIT_PARAM(boot_cpu_frequency, "Frequency of the boot CPU"), - INIT_PARAM(memctrl, "memory controller"), INIT_PARAM(physmem, "phsyical memory"), INIT_PARAM(kernel, "file that contains the kernel code"), INIT_PARAM(console, "file that contains the console code"), @@ -147,7 +137,6 @@ CREATE_SIM_OBJECT(FreebsdAlphaSystem) AlphaSystem::Params *p = new AlphaSystem::Params; p->name = getInstanceName(); p->boot_cpu_frequency = boot_cpu_frequency; - p->memctrl = memctrl; p->physmem = physmem; p->kernel_path = kernel; p->console_path = console; diff --git a/arch/alpha/isa/decoder.isa b/arch/alpha/isa/decoder.isa index f46e32fd1..1adcfb948 100644 --- a/arch/alpha/isa/decoder.isa +++ b/arch/alpha/isa/decoder.isa @@ -693,7 +693,7 @@ decode OPCODE default Unknown::unknown() { SimExit(curTick, "halt instruction encountered"); }}, IsNonSpeculative); 0x83: callsys({{ - xc->syscall(); + xc->syscall(R0); }}, IsNonSpeculative); // Read uniq reg into ABI return value register (r0) 0x9e: rduniq({{ R0 = Runiq; }}); diff --git a/arch/alpha/isa/main.isa b/arch/alpha/isa/main.isa index 17c9989ab..746fe776d 100644 --- a/arch/alpha/isa/main.isa +++ b/arch/alpha/isa/main.isa @@ -34,7 +34,7 @@ output header {{ #include "config/ss_compatible_fp.hh" #include "cpu/static_inst.hh" #include "arch/alpha/faults.hh" -#include "mem/mem_req.hh" // some constructors use MemReq flags +#include "mem/request.hh" // some constructors use MemReq flags }}; output decoder {{ @@ -418,31 +418,31 @@ def format BasicOperateWithNopCheck(code, *opt_args) {{ }}; // Integer instruction templates, formats, etc. -##include "m5/arch/alpha/isa/int.isa" +##include "int.isa" // Floating-point instruction templates, formats, etc. -##include "m5/arch/alpha/isa/fp.isa" +##include "fp.isa" // Memory instruction templates, formats, etc. -##include "m5/arch/alpha/isa/mem.isa" +##include "mem.isa" // Branch/jump instruction templates, formats, etc. -##include "m5/arch/alpha/isa/branch.isa" +##include "branch.isa" // PAL instruction templates, formats, etc. -##include "m5/arch/alpha/isa/pal.isa" +##include "pal.isa" // Opcdec fault instruction templates, formats, etc. -##include "m5/arch/alpha/isa/opcdec.isa" +##include "opcdec.isa" // Unimplemented instruction templates, formats, etc. -##include "m5/arch/alpha/isa/unimp.isa" +##include "unimp.isa" // Unknown instruction templates, formats, etc. -##include "m5/arch/alpha/isa/unknown.isa" +##include "unknown.isa" // Execution utility functions -##include "m5/arch/alpha/isa/util.isa" +##include "util.isa" // The actual decoder -##include "m5/arch/alpha/isa/decoder.isa" +##include "decoder.isa" diff --git a/arch/alpha/isa/mem.isa b/arch/alpha/isa/mem.isa index 3c8b4f755..8742d308f 100644 --- a/arch/alpha/isa/mem.isa +++ b/arch/alpha/isa/mem.isa @@ -311,8 +311,7 @@ def template LoadCompleteAcc {{ Fault fault = NoFault; %(fp_enable_check)s; - %(op_src_decl)s; - %(op_dest_decl)s; + %(op_decl)s; memcpy(&Mem, data, sizeof(Mem)); @@ -410,8 +409,7 @@ def template StoreInitiateAcc {{ uint64_t write_result = 0; %(fp_enable_check)s; - %(op_src_decl)s; - %(op_dest_decl)s; + %(op_decl)s; %(op_rd)s; %(ea_code)s; diff --git a/arch/alpha/isa_traits.hh b/arch/alpha/isa_traits.hh index 878193881..65c72115b 100644 --- a/arch/alpha/isa_traits.hh +++ b/arch/alpha/isa_traits.hh @@ -30,29 +30,15 @@ #define __ARCH_ALPHA_ISA_TRAITS_HH__ namespace LittleEndianGuest {} -using namespace LittleEndianGuest; -//#include "arch/alpha/faults.hh" -#include "base/misc.hh" +#include "arch/alpha/types.hh" +#include "arch/alpha/constants.hh" +#include "arch/alpha/regfile.hh" #include "config/full_system.hh" #include "sim/host.hh" -#include "sim/faults.hh" - -class ExecContext; -class FastCPU; -class FullCPU; -class Checkpoint; - -#define TARGET_ALPHA -class StaticInst; class StaticInstPtr; -namespace EV5 { -int DTB_ASN_ASN(uint64_t reg); -int ITB_ASN_ASN(uint64_t reg); -} - #if !FULL_SYSTEM class SyscallReturn { public: @@ -89,261 +75,21 @@ class SyscallReturn { #endif +#if FULL_SYSTEM +#include "arch/alpha/isa_fullsys_traits.hh" +#endif namespace AlphaISA { - typedef uint32_t MachInst; - typedef uint64_t ExtMachInst; - typedef uint8_t RegIndex; - - const int NumIntArchRegs = 32; - const int NumPALShadowRegs = 8; - const int NumFloatArchRegs = 32; - // @todo: Figure out what this number really should be. - const int NumMiscArchRegs = 32; - - // Static instruction parameters - const int MaxInstSrcRegs = 3; - const int MaxInstDestRegs = 2; - - // semantically meaningful register indices - const int ZeroReg = 31; // architecturally meaningful - // the rest of these depend on the ABI - const int StackPointerReg = 30; - const int GlobalPointerReg = 29; - const int ProcedureValueReg = 27; - const int ReturnAddressReg = 26; - const int ReturnValueReg = 0; - const int FramePointerReg = 15; - const int ArgumentReg0 = 16; - const int ArgumentReg1 = 17; - const int ArgumentReg2 = 18; - const int ArgumentReg3 = 19; - const int ArgumentReg4 = 20; - const int ArgumentReg5 = 21; - const int SyscallNumReg = ReturnValueReg; - const int SyscallPseudoReturnReg = ArgumentReg4; - const int SyscallSuccessReg = 19; - - - - const int LogVMPageSize = 13; // 8K bytes - const int VMPageSize = (1 << LogVMPageSize); - - const int BranchPredAddrShiftAmt = 2; // instructions are 4-byte aligned - - const int WordBytes = 4; - const int HalfwordBytes = 2; - const int ByteBytes = 1; - - - const int NumIntRegs = NumIntArchRegs + NumPALShadowRegs; - const int NumFloatRegs = NumFloatArchRegs; - const int NumMiscRegs = NumMiscArchRegs; - - // These enumerate all the registers for dependence tracking. - enum DependenceTags { - // 0..31 are the integer regs 0..31 - // 32..63 are the FP regs 0..31, i.e. use (reg + FP_Base_DepTag) - FP_Base_DepTag = 40, - Ctrl_Base_DepTag = 72, - Fpcr_DepTag = 72, // floating point control register - Uniq_DepTag = 73, - Lock_Flag_DepTag = 74, - Lock_Addr_DepTag = 75, - IPR_Base_DepTag = 76 - }; - - typedef uint64_t IntReg; - typedef IntReg IntRegFile[NumIntRegs]; - - // floating point register file entry type - typedef union { - uint64_t q; - double d; - } FloatReg; - - typedef union { - uint64_t q[NumFloatRegs]; // integer qword view - double d[NumFloatRegs]; // double-precision floating point view - } FloatRegFile; - -extern const Addr PageShift; -extern const Addr PageBytes; -extern const Addr PageMask; -extern const Addr PageOffset; +using namespace LittleEndianGuest; // redirected register map, really only used for the full system case. extern const int reg_redir[NumIntRegs]; -#if FULL_SYSTEM - - typedef uint64_t InternalProcReg; - -#include "arch/alpha/isa_fullsys_traits.hh" - -#else - const int NumInternalProcRegs = 0; -#endif - - // control register file contents - typedef uint64_t MiscReg; - class MiscRegFile { - protected: - uint64_t fpcr; // floating point condition codes - uint64_t uniq; // process-unique register - bool lock_flag; // lock flag for LL/SC - Addr lock_addr; // lock address for LL/SC - - public: - MiscReg readReg(int misc_reg); - - //These functions should be removed once the simplescalar cpu model - //has been replaced. - int getInstAsid(); - int getDataAsid(); - - MiscReg readRegWithEffect(int misc_reg, Fault &fault, ExecContext *xc); - - Fault setReg(int misc_reg, const MiscReg &val); - - Fault setRegWithEffect(int misc_reg, const MiscReg &val, - ExecContext *xc); - - void copyMiscRegs(ExecContext *xc); - -#if FULL_SYSTEM - protected: - InternalProcReg ipr[NumInternalProcRegs]; // Internal processor regs - - private: - MiscReg readIpr(int idx, Fault &fault, ExecContext *xc); - - Fault setIpr(int idx, uint64_t val, ExecContext *xc); - - void copyIprs(ExecContext *xc); -#endif - friend class RegFile; - }; - - const int TotalNumRegs = NumIntRegs + NumFloatRegs + - NumMiscRegs + NumInternalProcRegs; - - const int TotalDataRegs = NumIntRegs + NumFloatRegs; - - typedef union { - IntReg intreg; - FloatReg fpreg; - MiscReg ctrlreg; - } AnyReg; - - struct RegFile { - IntRegFile intRegFile; // (signed) integer register file - FloatRegFile floatRegFile; // floating point register file - MiscRegFile miscRegs; // control register file - Addr pc; // program counter - Addr npc; // next-cycle program counter - Addr nnpc; - -#if FULL_SYSTEM - int intrflag; // interrupt flag - inline int instAsid() - { return EV5::ITB_ASN_ASN(miscRegs.ipr[IPR_ITB_ASN]); } - inline int dataAsid() - { return EV5::DTB_ASN_ASN(miscRegs.ipr[IPR_DTB_ASN]); } -#endif // FULL_SYSTEM - - void serialize(std::ostream &os); - void unserialize(Checkpoint *cp, const std::string §ion); - }; - - static inline ExtMachInst makeExtMI(MachInst inst, const uint64_t &pc); - StaticInstPtr decodeInst(ExtMachInst); - // return a no-op instruction... used for instruction fetch faults - extern const ExtMachInst NoopMachInst; - - enum annotes { - ANNOTE_NONE = 0, - // An impossible number for instruction annotations - ITOUCH_ANNOTE = 0xffffffff, - }; - - static inline bool isCallerSaveIntegerRegister(unsigned int reg) { - panic("register classification not implemented"); - return (reg >= 1 && reg <= 8 || reg >= 22 && reg <= 25 || reg == 27); - } - - static inline bool isCalleeSaveIntegerRegister(unsigned int reg) { - panic("register classification not implemented"); - return (reg >= 9 && reg <= 15); - } - - static inline bool isCallerSaveFloatRegister(unsigned int reg) { - panic("register classification not implemented"); - return false; - } - - static inline bool isCalleeSaveFloatRegister(unsigned int reg) { - panic("register classification not implemented"); - return false; - } - - static inline Addr alignAddress(const Addr &addr, - unsigned int nbytes) { - return (addr & ~(nbytes - 1)); - } - - // 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 (not necessarily the size - // of real instructions for PISA) - static inline size_t fetchInstSize() { - return sizeof(MachInst); - } - - static inline MachInst makeRegisterCopy(int dest, int src) { - panic("makeRegisterCopy not implemented"); - return 0; - } - - // Machine operations - - void saveMachineReg(AnyReg &savereg, const RegFile ®_file, - int regnum); - - void restoreMachineReg(RegFile ®s, const AnyReg ®, - int regnum); - -#if 0 - static void serializeSpecialRegs(const Serializable::Proxy &proxy, - const RegFile ®s); - - static void unserializeSpecialRegs(const IniFile *db, - const std::string &category, - ConfigNode *node, - RegFile ®s); -#endif - - /** - * Function to insure ISA semantics about 0 registers. - * @param xc The execution context. - */ - template <class XC> - void zeroRegisters(XC *xc); - - const Addr MaxAddr = (Addr)-1; - #if !FULL_SYSTEM static inline void setSyscallReturn(SyscallReturn return_value, RegFile *regs) { @@ -352,33 +98,15 @@ extern const int reg_redir[NumIntRegs]; // return value itself in the standard return value reg (v0). if (return_value.successful()) { // no error - regs->intRegFile[SyscallSuccessReg] = 0; - regs->intRegFile[ReturnValueReg] = return_value.value(); + regs->setIntReg(SyscallSuccessReg, 0); + regs->setIntReg(ReturnValueReg, return_value.value()); } else { // got an error, return details - regs->intRegFile[SyscallSuccessReg] = (IntReg) -1; - regs->intRegFile[ReturnValueReg] = -return_value.value(); + regs->setIntReg(SyscallSuccessReg, (IntReg)-1); + regs->setIntReg(ReturnValueReg, -return_value.value()); } } #endif }; -static inline AlphaISA::ExtMachInst -AlphaISA::makeExtMI(AlphaISA::MachInst inst, const uint64_t &pc) { -#if FULL_SYSTEM - AlphaISA::ExtMachInst ext_inst = inst; - if (pc && 0x1) - return ext_inst|=(static_cast<AlphaISA::ExtMachInst>(pc & 0x1) << 32); - else - return ext_inst; -#else - return AlphaISA::ExtMachInst(inst); -#endif -} - -#if FULL_SYSTEM - -#include "arch/alpha/ev5.hh" -#endif - #endif // __ARCH_ALPHA_ISA_TRAITS_HH__ diff --git a/arch/alpha/linux/linux.cc b/arch/alpha/linux/linux.cc new file mode 100644 index 000000000..f123ae1fe --- /dev/null +++ b/arch/alpha/linux/linux.cc @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2003-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. + */ + +#include "arch/alpha/linux/linux.hh" + +// open(2) flags translation table +OpenFlagTransTable AlphaLinux::openFlagTable[] = { +#ifdef _MSC_VER + { AlphaLinux::TGT_O_RDONLY, _O_RDONLY }, + { AlphaLinux::TGT_O_WRONLY, _O_WRONLY }, + { AlphaLinux::TGT_O_RDWR, _O_RDWR }, + { AlphaLinux::TGT_O_APPEND, _O_APPEND }, + { AlphaLinux::TGT_O_CREAT, _O_CREAT }, + { AlphaLinux::TGT_O_TRUNC, _O_TRUNC }, + { AlphaLinux::TGT_O_EXCL, _O_EXCL }, +#ifdef _O_NONBLOCK + { AlphaLinux::TGT_O_NONBLOCK, _O_NONBLOCK }, +#endif +#ifdef _O_NOCTTY + { AlphaLinux::TGT_O_NOCTTY, _O_NOCTTY }, +#endif +#ifdef _O_SYNC + { AlphaLinux::TGT_O_SYNC, _O_SYNC }, +#endif +#else /* !_MSC_VER */ + { AlphaLinux::TGT_O_RDONLY, O_RDONLY }, + { AlphaLinux::TGT_O_WRONLY, O_WRONLY }, + { AlphaLinux::TGT_O_RDWR, O_RDWR }, + { AlphaLinux::TGT_O_APPEND, O_APPEND }, + { AlphaLinux::TGT_O_CREAT, O_CREAT }, + { AlphaLinux::TGT_O_TRUNC, O_TRUNC }, + { AlphaLinux::TGT_O_EXCL, O_EXCL }, + { AlphaLinux::TGT_O_NONBLOCK, O_NONBLOCK }, + { AlphaLinux::TGT_O_NOCTTY, O_NOCTTY }, +#ifdef O_SYNC + { AlphaLinux::TGT_O_SYNC, O_SYNC }, +#endif +#endif /* _MSC_VER */ +}; + +const int AlphaLinux::NUM_OPEN_FLAGS = + (sizeof(AlphaLinux::openFlagTable)/sizeof(AlphaLinux::openFlagTable[0])); + + + diff --git a/arch/alpha/linux/linux.hh b/arch/alpha/linux/linux.hh new file mode 100644 index 000000000..f04e2bfa8 --- /dev/null +++ b/arch/alpha/linux/linux.hh @@ -0,0 +1,128 @@ +/* + * Copyright (c) 2003-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. + */ + +#ifndef __ALPHA_ALPHA_LINUX_HH +#define __ALPHA_ALPHA_LINUX_HH + +#include "kern/linux/linux.hh" + +/* AlphaLinux class contains static constants/definitions/misc. + * structures which are specific to the Linux OS AND the Alpha + * architecture + */ +class AlphaLinux : public Linux +{ + public: + + /// 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_NONBLOCK = 00000004; //!< O_NONBLOCK + static const int TGT_O_APPEND = 00000010; //!< O_APPEND + static const int TGT_O_CREAT = 00001000; //!< O_CREAT + static const int TGT_O_TRUNC = 00002000; //!< O_TRUNC + static const int TGT_O_EXCL = 00004000; //!< O_EXCL + static const int TGT_O_NOCTTY = 00010000; //!< O_NOCTTY + static const int TGT_O_SYNC = 00040000; //!< O_SYNC + static const int TGT_O_DRD = 00100000; //!< O_DRD + static const int TGT_O_DIRECTIO = 00200000; //!< O_DIRECTIO + static const int TGT_O_CACHE = 00400000; //!< O_CACHE + static const int TGT_O_DSYNC = 02000000; //!< O_DSYNC + static const int TGT_O_RSYNC = 04000000; //!< O_RSYNC + //@} + + /// For mmap(). + static const unsigned TGT_MAP_ANONYMOUS = 0x10; + + //@{ + /// For getsysinfo(). + static const unsigned GSI_PLATFORM_NAME = 103; //!< platform name as string + static const unsigned GSI_CPU_INFO = 59; //!< CPU information + static const unsigned GSI_PROC_TYPE = 60; //!< get proc_type + static const unsigned GSI_MAX_CPU = 30; //!< max # cpu's on this machine + static const unsigned GSI_CPUS_IN_BOX = 55; //!< number of CPUs in system + static const unsigned GSI_PHYSMEM = 19; //!< Physical memory in KB + static const unsigned GSI_CLK_TCK = 42; //!< clock freq in Hz + static const unsigned GSI_IEEE_FP_CONTROL = 45; + //@} + + //@{ + /// For getrusage(). + static const int TGT_RUSAGE_SELF = 0; + static const int TGT_RUSAGE_CHILDREN = -1; + static const int TGT_RUSAGE_BOTH = -2; + //@} + + //@{ + /// For setsysinfo(). + static const unsigned SSI_IEEE_FP_CONTROL = 14; //!< ieee_set_fp_control() + //@} + + //@{ + /// ioctl() command codes. + 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 = 0x40127417; + //@} + + /// For table(). + static const int TBL_SYSINFO = 12; + + /// Resource enumeration for getrlimit(). + enum rlimit_resources { + TGT_RLIMIT_CPU = 0, + TGT_RLIMIT_FSIZE = 1, + TGT_RLIMIT_DATA = 2, + TGT_RLIMIT_STACK = 3, + TGT_RLIMIT_CORE = 4, + TGT_RLIMIT_RSS = 5, + TGT_RLIMIT_NOFILE = 6, + TGT_RLIMIT_AS = 7, + TGT_RLIMIT_VMEM = 7, + TGT_RLIMIT_NPROC = 8, + TGT_RLIMIT_MEMLOCK = 9, + TGT_RLIMIT_LOCKS = 10 + }; +}; + +#endif diff --git a/arch/alpha/linux/process.cc b/arch/alpha/linux/process.cc index 1c911bc50..9f4f65db8 100644 --- a/arch/alpha/linux/process.cc +++ b/arch/alpha/linux/process.cc @@ -26,13 +26,13 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +#include "arch/alpha/linux/linux.hh" #include "arch/alpha/linux/process.hh" #include "arch/alpha/isa_traits.hh" #include "base/trace.hh" #include "cpu/exec_context.hh" #include "kern/linux/linux.hh" -#include "mem/functional/functional.hh" #include "sim/process.hh" #include "sim/syscall_emul.hh" @@ -55,7 +55,7 @@ unameFunc(SyscallDesc *desc, int callnum, Process *process, strcpy(name->version, "#1 Mon Aug 18 11:32:15 EDT 2003"); strcpy(name->machine, "alpha"); - name.copyOut(xc->getMemPtr()); + name.copyOut(xc->getMemPort()); return 0; } @@ -75,7 +75,7 @@ osf_getsysinfoFunc(SyscallDesc *desc, int callnum, Process *process, TypedBufferArg<uint64_t> fpcr(xc->getSyscallArg(1)); // I don't think this exactly matches the HW FPCR *fpcr = 0; - fpcr.copyOut(xc->getMemPtr()); + fpcr.copyOut(xc->getMemPort()); return 0; } @@ -101,7 +101,7 @@ osf_setsysinfoFunc(SyscallDesc *desc, int callnum, Process *process, case 14: { // SSI_IEEE_FP_CONTROL TypedBufferArg<uint64_t> fpcr(xc->getSyscallArg(1)); // I don't think this exactly matches the HW FPCR - fpcr.copyIn(xc->getMemPtr()); + fpcr.copyIn(xc->getMemPort()); DPRINTFR(SyscallVerbose, "osf_setsysinfo(SSI_IEEE_FP_CONTROL): " " setting FPCR to 0x%x\n", gtoh(*(uint64_t*)fpcr)); return 0; @@ -133,7 +133,7 @@ SyscallDesc AlphaLinuxProcess::syscallDescs[] = { /* 12 */ SyscallDesc("chdir", unimplementedFunc), /* 13 */ SyscallDesc("fchdir", unimplementedFunc), /* 14 */ SyscallDesc("mknod", unimplementedFunc), - /* 15 */ SyscallDesc("chmod", chmodFunc<Linux>), + /* 15 */ SyscallDesc("chmod", chmodFunc<AlphaLinux>), /* 16 */ SyscallDesc("chown", chownFunc), /* 17 */ SyscallDesc("brk", obreakFunc), /* 18 */ SyscallDesc("osf_getfsstat", unimplementedFunc), @@ -163,7 +163,7 @@ SyscallDesc AlphaLinuxProcess::syscallDescs[] = { /* 42 */ SyscallDesc("pipe", pipePseudoFunc), /* 43 */ SyscallDesc("osf_set_program_attributes", unimplementedFunc), /* 44 */ SyscallDesc("osf_profil", unimplementedFunc), - /* 45 */ SyscallDesc("open", openFunc<Linux>), + /* 45 */ SyscallDesc("open", openFunc<AlphaLinux>), /* 46 */ SyscallDesc("osf_old_sigaction", unimplementedFunc), /* 47 */ SyscallDesc("getxgid", getgidPseudoFunc), /* 48 */ SyscallDesc("osf_sigprocmask", ignoreFunc), @@ -172,7 +172,7 @@ SyscallDesc AlphaLinuxProcess::syscallDescs[] = { /* 51 */ SyscallDesc("acct", unimplementedFunc), /* 52 */ SyscallDesc("sigpending", unimplementedFunc), /* 53 */ SyscallDesc("osf_classcntl", unimplementedFunc), - /* 54 */ SyscallDesc("ioctl", ioctlFunc<Linux>), + /* 54 */ SyscallDesc("ioctl", ioctlFunc<AlphaLinux>), /* 55 */ SyscallDesc("osf_reboot", unimplementedFunc), /* 56 */ SyscallDesc("osf_revoke", unimplementedFunc), /* 57 */ SyscallDesc("symlink", unimplementedFunc), @@ -185,11 +185,11 @@ SyscallDesc AlphaLinuxProcess::syscallDescs[] = { /* 64 */ SyscallDesc("getpagesize", getpagesizeFunc), /* 65 */ SyscallDesc("osf_mremap", unimplementedFunc), /* 66 */ SyscallDesc("vfork", unimplementedFunc), - /* 67 */ SyscallDesc("stat", statFunc<Linux>), - /* 68 */ SyscallDesc("lstat", lstatFunc<Linux>), + /* 67 */ SyscallDesc("stat", statFunc<AlphaLinux>), + /* 68 */ SyscallDesc("lstat", lstatFunc<AlphaLinux>), /* 69 */ SyscallDesc("osf_sbrk", unimplementedFunc), /* 70 */ SyscallDesc("osf_sstk", unimplementedFunc), - /* 71 */ SyscallDesc("mmap", mmapFunc<Linux>), + /* 71 */ SyscallDesc("mmap", mmapFunc<AlphaLinux>), /* 72 */ SyscallDesc("osf_old_vadvise", unimplementedFunc), /* 73 */ SyscallDesc("munmap", munmapFunc), /* 74 */ SyscallDesc("mprotect", ignoreFunc), @@ -209,7 +209,7 @@ SyscallDesc AlphaLinuxProcess::syscallDescs[] = { /* 88 */ SyscallDesc("sethostname", unimplementedFunc), /* 89 */ SyscallDesc("getdtablesize", unimplementedFunc), /* 90 */ SyscallDesc("dup2", unimplementedFunc), - /* 91 */ SyscallDesc("fstat", fstatFunc<Linux>), + /* 91 */ SyscallDesc("fstat", fstatFunc<AlphaLinux>), /* 92 */ SyscallDesc("fcntl", fcntlFunc), /* 93 */ SyscallDesc("osf_select", unimplementedFunc), /* 94 */ SyscallDesc("poll", unimplementedFunc), @@ -239,10 +239,10 @@ SyscallDesc AlphaLinuxProcess::syscallDescs[] = { /* 118 */ SyscallDesc("getsockopt", unimplementedFunc), /* 119 */ SyscallDesc("numa_syscalls", unimplementedFunc), /* 120 */ SyscallDesc("readv", unimplementedFunc), - /* 121 */ SyscallDesc("writev", writevFunc<Linux>), + /* 121 */ SyscallDesc("writev", writevFunc<AlphaLinux>), /* 122 */ SyscallDesc("osf_settimeofday", unimplementedFunc), /* 123 */ SyscallDesc("fchown", fchownFunc), - /* 124 */ SyscallDesc("fchmod", fchmodFunc<Linux>), + /* 124 */ SyscallDesc("fchmod", fchmodFunc<AlphaLinux>), /* 125 */ SyscallDesc("recvfrom", unimplementedFunc), /* 126 */ SyscallDesc("setreuid", unimplementedFunc), /* 127 */ SyscallDesc("setregid", unimplementedFunc), @@ -262,7 +262,7 @@ SyscallDesc AlphaLinuxProcess::syscallDescs[] = { /* 141 */ SyscallDesc("getpeername", unimplementedFunc), /* 142 */ SyscallDesc("osf_gethostid", unimplementedFunc), /* 143 */ SyscallDesc("osf_sethostid", unimplementedFunc), - /* 144 */ SyscallDesc("getrlimit", getrlimitFunc<Linux>), + /* 144 */ SyscallDesc("getrlimit", getrlimitFunc<AlphaLinux>), /* 145 */ SyscallDesc("setrlimit", ignoreFunc), /* 146 */ SyscallDesc("osf_old_killpg", unimplementedFunc), /* 147 */ SyscallDesc("setsid", unimplementedFunc), @@ -480,12 +480,12 @@ SyscallDesc AlphaLinuxProcess::syscallDescs[] = { /* 356 */ SyscallDesc("rt_sigqueueinfo", unimplementedFunc), /* 357 */ SyscallDesc("rt_sigsuspend", unimplementedFunc), /* 358 */ SyscallDesc("select", unimplementedFunc), - /* 359 */ SyscallDesc("gettimeofday", gettimeofdayFunc<Linux>), + /* 359 */ SyscallDesc("gettimeofday", gettimeofdayFunc<AlphaLinux>), /* 360 */ SyscallDesc("settimeofday", unimplementedFunc), /* 361 */ SyscallDesc("getitimer", unimplementedFunc), /* 362 */ SyscallDesc("setitimer", unimplementedFunc), - /* 363 */ SyscallDesc("utimes", utimesFunc<Linux>), - /* 364 */ SyscallDesc("getrusage", getrusageFunc<Linux>), + /* 363 */ SyscallDesc("utimes", utimesFunc<AlphaLinux>), + /* 364 */ SyscallDesc("getrusage", getrusageFunc<AlphaLinux>), /* 365 */ SyscallDesc("wait4", unimplementedFunc), /* 366 */ SyscallDesc("adjtimex", unimplementedFunc), /* 367 */ SyscallDesc("getcwd", unimplementedFunc), @@ -547,8 +547,8 @@ SyscallDesc AlphaLinuxProcess::syscallDescs[] = { /* 423 */ SyscallDesc("semtimedop", unimplementedFunc), /* 424 */ SyscallDesc("tgkill", unimplementedFunc), /* 425 */ SyscallDesc("stat64", unimplementedFunc), - /* 426 */ SyscallDesc("lstat64", lstat64Func<Linux>), - /* 427 */ SyscallDesc("fstat64", fstat64Func<Linux>), + /* 426 */ SyscallDesc("lstat64", lstat64Func<AlphaLinux>), + /* 427 */ SyscallDesc("fstat64", fstat64Func<AlphaLinux>), /* 428 */ SyscallDesc("vserver", unimplementedFunc), /* 429 */ SyscallDesc("mbind", unimplementedFunc), /* 430 */ SyscallDesc("get_mempolicy", unimplementedFunc), @@ -567,15 +567,17 @@ SyscallDesc AlphaLinuxProcess::syscallDescs[] = { AlphaLinuxProcess::AlphaLinuxProcess(const std::string &name, ObjectFile *objFile, + System *system, int stdin_fd, int stdout_fd, int stderr_fd, std::vector<std::string> &argv, std::vector<std::string> &envp) - : LiveProcess(name, objFile, stdin_fd, stdout_fd, stderr_fd, argv, envp), + : AlphaLiveProcess(name, objFile, system, stdin_fd, stdout_fd, + stderr_fd, argv, envp), Num_Syscall_Descs(sizeof(syscallDescs) / sizeof(SyscallDesc)) { - init_regs->intRegFile[0] = 0; + //init_regs->intRegFile[0] = 0; } diff --git a/arch/alpha/linux/process.hh b/arch/alpha/linux/process.hh index 7de1b1ac1..2e0566665 100644 --- a/arch/alpha/linux/process.hh +++ b/arch/alpha/linux/process.hh @@ -29,16 +29,18 @@ #ifndef __ALPHA_LINUX_PROCESS_HH__ #define __ALPHA_LINUX_PROCESS_HH__ -#include "sim/process.hh" +#include "arch/alpha/process.hh" +namespace AlphaISA { /// A process with emulated Alpha/Linux syscalls. -class AlphaLinuxProcess : public LiveProcess +class AlphaLinuxProcess : public AlphaLiveProcess { public: /// Constructor. AlphaLinuxProcess(const std::string &name, ObjectFile *objFile, + System *system, int stdin_fd, int stdout_fd, int stderr_fd, std::vector<std::string> &argv, std::vector<std::string> &envp); @@ -54,5 +56,5 @@ class AlphaLinuxProcess : public LiveProcess const int Num_Syscall_Descs; }; - +} // namespace AlphaISA #endif // __ALPHA_LINUX_PROCESS_HH__ diff --git a/arch/alpha/linux/system.cc b/arch/alpha/linux/system.cc index f9275d15e..cdb96096c 100644 --- a/arch/alpha/linux/system.cc +++ b/arch/alpha/linux/system.cc @@ -46,8 +46,8 @@ #include "dev/platform.hh" #include "kern/linux/printk.hh" #include "kern/linux/events.hh" -#include "mem/functional/memory_control.hh" -#include "mem/functional/physical.hh" +#include "mem/physical.hh" +#include "mem/port.hh" #include "sim/builder.hh" #include "sim/byteswap.hh" @@ -59,7 +59,6 @@ LinuxAlphaSystem::LinuxAlphaSystem(Params *p) : AlphaSystem(p) { Addr addr = 0; - Addr paddr = 0; /** * The symbol swapper_pg_dir marks the beginning of the kernel and @@ -73,25 +72,17 @@ LinuxAlphaSystem::LinuxAlphaSystem(Params *p) * Since we aren't using a bootloader, we have to copy the * kernel arguments directly into the kernel's memory. */ - paddr = vtophys(physmem, CommandLine()); - char *commandline = (char *)physmem->dma_addr(paddr, sizeof(uint64_t)); - if (commandline) - strncpy(commandline, params()->boot_osflags.c_str(), CommandLineSize); + virtPort.writeBlob(CommandLine(), (uint8_t*)params()->boot_osflags.c_str(), + params()->boot_osflags.length()+1); /** * find the address of the est_cycle_freq variable and insert it * so we don't through the lengthly process of trying to * calculated it by using the PIT, RTC, etc. */ - if (kernelSymtab->findAddress("est_cycle_freq", addr)) { - paddr = vtophys(physmem, addr); - uint8_t *est_cycle_frequency = - physmem->dma_addr(paddr, sizeof(uint64_t)); - - if (est_cycle_frequency) - *(uint64_t *)est_cycle_frequency = - Clock::Frequency / p->boot_cpu_frequency; - } + if (kernelSymtab->findAddress("est_cycle_freq", addr)) + virtPort.write(addr, (uint64_t)(Clock::Frequency / + p->boot_cpu_frequency)); /** @@ -100,16 +91,9 @@ LinuxAlphaSystem::LinuxAlphaSystem(Params *p) * @todo At some point we should change ev5.hh and the palcode to support * 255 ASNs. */ - if (kernelSymtab->findAddress("dp264_mv", addr)) { - paddr = vtophys(physmem, addr); - char *dp264_mv = (char *)physmem->dma_addr(paddr, sizeof(uint64_t)); - - if (dp264_mv) { - *(uint32_t*)(dp264_mv+0x18) = LittleEndianGuest::htog((uint32_t)127); - } else - panic("could not translate dp264_mv addr\n"); - - } else + if (kernelSymtab->findAddress("dp264_mv", addr)) + virtPort.write(addr + 0x18, LittleEndianGuest::htog((uint32_t)127)); + else panic("could not find dp264_mv\n"); #ifndef NDEBUG @@ -190,15 +174,10 @@ LinuxAlphaSystem::setDelayLoop(ExecContext *xc) { Addr addr = 0; if (kernelSymtab->findAddress("loops_per_jiffy", addr)) { - Addr paddr = vtophys(physmem, addr); - - uint8_t *loops_per_jiffy = - physmem->dma_addr(paddr, sizeof(uint32_t)); - Tick cpuFreq = xc->getCpuPtr()->frequency(); Tick intrFreq = platform->intrFrequency(); - *(uint32_t *)loops_per_jiffy = - (uint32_t)((cpuFreq / intrFreq) * 0.9988); + xc->getVirtPort(xc)->write(addr, + (uint32_t)((cpuFreq / intrFreq) * 0.9988)); } } @@ -224,7 +203,6 @@ LinuxAlphaSystem::PrintThreadInfo::process(ExecContext *xc) BEGIN_DECLARE_SIM_OBJECT_PARAMS(LinuxAlphaSystem) Param<Tick> boot_cpu_frequency; - SimObjectParam<MemoryController *> memctrl; SimObjectParam<PhysicalMemory *> physmem; Param<string> kernel; @@ -247,7 +225,6 @@ END_DECLARE_SIM_OBJECT_PARAMS(LinuxAlphaSystem) BEGIN_INIT_SIM_OBJECT_PARAMS(LinuxAlphaSystem) INIT_PARAM(boot_cpu_frequency, "Frequency of the boot CPU"), - INIT_PARAM(memctrl, "memory controller"), INIT_PARAM(physmem, "phsyical memory"), INIT_PARAM(kernel, "file that contains the kernel code"), INIT_PARAM(console, "file that contains the console code"), @@ -269,7 +246,6 @@ CREATE_SIM_OBJECT(LinuxAlphaSystem) AlphaSystem::Params *p = new AlphaSystem::Params; p->name = getInstanceName(); p->boot_cpu_frequency = boot_cpu_frequency; - p->memctrl = memctrl; p->physmem = physmem; p->kernel_path = kernel; p->console_path = console; diff --git a/arch/alpha/linux/system.hh b/arch/alpha/linux/system.hh index 035e2a427..0c1fb037e 100644 --- a/arch/alpha/linux/system.hh +++ b/arch/alpha/linux/system.hh @@ -39,7 +39,6 @@ class IdleStartEvent; using namespace AlphaISA; using namespace Linux; -using namespace std; /** * This class contains linux specific system code (Loading, Events, Binning). diff --git a/arch/alpha/process.cc b/arch/alpha/process.cc index b2dbe7ad1..25ee79692 100644 --- a/arch/alpha/process.cc +++ b/arch/alpha/process.cc @@ -26,28 +26,44 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +#include "arch/alpha/constants.hh" #include "arch/alpha/process.hh" +#include "arch/alpha/linux/process.hh" +#include "arch/alpha/tru64/process.hh" +#include "base/loader/object_file.hh" +#include "base/misc.hh" +#include "cpu/exec_context.hh" +#include "sim/builder.hh" +#include "sim/system.hh" -namespace AlphaISA -{ -LiveProcess * -createProcess(const std::string &nm, ObjectFile * objFile, - int stdin_fd, int stdout_fd, int stderr_fd, +using namespace AlphaISA; +using namespace std; + +AlphaLiveProcess * +AlphaLiveProcess::create(const std::string &nm, System *system, int stdin_fd, + int stdout_fd, int stderr_fd, std::string executable, std::vector<std::string> &argv, std::vector<std::string> &envp) { - LiveProcess * process = NULL; + AlphaLiveProcess *process = NULL; + + ObjectFile *objFile = createObjectFile(executable); + if (objFile == NULL) { + fatal("Can't load object file %s", executable); + } + + if (objFile->getArch() != ObjectFile::Alpha) fatal("Object file does not match architecture."); switch (objFile->getOpSys()) { case ObjectFile::Tru64: - process = new AlphaTru64Process(nm, objFile, + process = new AlphaTru64Process(nm, objFile, system, stdin_fd, stdout_fd, stderr_fd, argv, envp); break; case ObjectFile::Linux: - process = new AlphaLinuxProcess(nm, objFile, + process = new AlphaLinuxProcess(nm, objFile, system, stdin_fd, stdout_fd, stderr_fd, argv, envp); break; @@ -55,7 +71,97 @@ createProcess(const std::string &nm, ObjectFile * objFile, default: fatal("Unknown/unsupported operating system."); } + + if (process == NULL) + fatal("Unknown error creating process object."); return process; } -} // namespace AlphaISA +AlphaLiveProcess::AlphaLiveProcess(const std::string &nm, ObjectFile *objFile, + System *_system, int stdin_fd, int stdout_fd, int stderr_fd, + std::vector<std::string> &argv, std::vector<std::string> &envp) + : LiveProcess(nm, objFile, _system, stdin_fd, stdout_fd, stderr_fd, + argv, envp) +{ + brk_point = objFile->dataBase() + objFile->dataSize() + objFile->bssSize(); + brk_point = roundUp(brk_point, VMPageSize); + + // Set up stack. On Alpha, stack goes below text section. This + // code should get moved to some architecture-specific spot. + stack_base = objFile->textBase() - (409600+4096); + + // Set up region for mmaps. Tru64 seems to start just above 0 and + // grow up from there. + mmap_start = mmap_end = 0x10000; + + // Set pointer for next thread stack. Reserve 8M for main stack. + next_thread_stack_base = stack_base - (8 * 1024 * 1024); + +} + +void +AlphaLiveProcess::startup() +{ + argsInit(MachineBytes, VMPageSize); + + execContexts[0]->setIntReg(GlobalPointerReg, objFile->globalPointer()); +} + + + + +BEGIN_DECLARE_SIM_OBJECT_PARAMS(AlphaLiveProcess) + + VectorParam<string> cmd; + Param<string> executable; + Param<string> input; + Param<string> output; + VectorParam<string> env; + SimObjectParam<System *> system; + +END_DECLARE_SIM_OBJECT_PARAMS(AlphaLiveProcess) + + +BEGIN_INIT_SIM_OBJECT_PARAMS(AlphaLiveProcess) + + INIT_PARAM(cmd, "command line (executable plus arguments)"), + INIT_PARAM(executable, "executable (overrides cmd[0] if set)"), + INIT_PARAM(input, "filename for stdin (dflt: use sim stdin)"), + INIT_PARAM(output, "filename for stdout/stderr (dflt: use sim stdout)"), + INIT_PARAM(env, "environment settings"), + INIT_PARAM(system, "system") + +END_INIT_SIM_OBJECT_PARAMS(AlphaLiveProcess) + + +CREATE_SIM_OBJECT(AlphaLiveProcess) +{ + string in = input; + string out = output; + + // initialize file descriptors to default: same as simulator + int stdin_fd, stdout_fd, stderr_fd; + + if (in == "stdin" || in == "cin") + stdin_fd = STDIN_FILENO; + else + stdin_fd = Process::openInputFile(input); + + if (out == "stdout" || out == "cout") + stdout_fd = STDOUT_FILENO; + else if (out == "stderr" || out == "cerr") + stdout_fd = STDERR_FILENO; + else + stdout_fd = Process::openOutputFile(out); + + stderr_fd = (stdout_fd != STDOUT_FILENO) ? stdout_fd : STDERR_FILENO; + + return AlphaLiveProcess::create(getInstanceName(), system, + stdin_fd, stdout_fd, stderr_fd, + (string)executable == "" ? cmd[0] : executable, + cmd, env); +} + + +REGISTER_SIM_OBJECT("AlphaLiveProcess", AlphaLiveProcess) + diff --git a/arch/alpha/process.hh b/arch/alpha/process.hh index 4a2a4212e..d97b36e2d 100644 --- a/arch/alpha/process.hh +++ b/arch/alpha/process.hh @@ -30,19 +30,35 @@ #define __ALPHA_PROCESS_HH__ #include <string> +#include <vector> +#include "sim/process.hh" -#include "arch/alpha/linux/process.hh" -#include "arch/alpha/tru64/process.hh" -#include "base/loader/object_file.hh" +class ObjectFile; +class System; -namespace AlphaISA + +class AlphaLiveProcess : public LiveProcess { + protected: + AlphaLiveProcess(const std::string &nm, ObjectFile *objFile, + System *_system, int stdin_fd, int stdout_fd, int stderr_fd, + std::vector<std::string> &argv, + std::vector<std::string> &envp); + + void startup(); + + public: + // this function is used to create the LiveProcess object, since + // we can't tell which subclass of LiveProcess to use until we + // open and look at the object file. + static AlphaLiveProcess *create(const std::string &nm, + System *_system, + int stdin_fd, int stdout_fd, int stderr_fd, + std::string executable, + std::vector<std::string> &argv, + std::vector<std::string> &envp); -LiveProcess * -createProcess(const std::string &nm, ObjectFile * objFile, - int stdin_fd, int stdout_fd, int stderr_fd, - std::vector<std::string> &argv, std::vector<std::string> &envp); +}; -} // namespace AlphaISA #endif // __ALPHA_PROCESS_HH__ diff --git a/arch/alpha/regfile.hh b/arch/alpha/regfile.hh new file mode 100644 index 000000000..af01b7829 --- /dev/null +++ b/arch/alpha/regfile.hh @@ -0,0 +1,278 @@ +/* + * Copyright (c) 2003-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. + */ + +#ifndef __ARCH_ALPHA_REGFILE_HH__ +#define __ARCH_ALPHA_REGFILE_HH__ + +#include "arch/alpha/types.hh" +#include "arch/alpha/constants.hh" +#include "sim/faults.hh" + +class Checkpoint; +class ExecContext; + +namespace AlphaISA +{ + class IntRegFile + { + protected: + IntReg regs[NumIntRegs]; + + public: + + IntReg readReg(int intReg) + { + return regs[intReg]; + } + + Fault setReg(int intReg, const IntReg &val) + { + regs[intReg] = val; + return NoFault; + } + + void serialize(std::ostream &os); + + void unserialize(Checkpoint *cp, const std::string §ion); + + }; + + class FloatRegFile + { + public: + + union { + uint64_t q[NumFloatRegs]; // integer qword view + double d[NumFloatRegs]; // double-precision floating point view + }; + + void serialize(std::ostream &os); + + void unserialize(Checkpoint *cp, const std::string §ion); + + }; + + class MiscRegFile { + protected: + uint64_t fpcr; // floating point condition codes + uint64_t uniq; // process-unique register + bool lock_flag; // lock flag for LL/SC + Addr lock_addr; // lock address for LL/SC + + public: + MiscReg readReg(int misc_reg); + + MiscReg readRegWithEffect(int misc_reg, Fault &fault, + ExecContext *xc); + + //These functions should be removed once the simplescalar cpu model + //has been replaced. + int getInstAsid(); + int getDataAsid(); + + Fault setReg(int misc_reg, const MiscReg &val); + + Fault setRegWithEffect(int misc_reg, const MiscReg &val, + ExecContext *xc); + +#if FULL_SYSTEM + protected: + typedef uint64_t InternalProcReg; + + InternalProcReg ipr[NumInternalProcRegs]; // Internal processor regs + + private: + InternalProcReg readIpr(int idx, Fault &fault, ExecContext *xc); + + Fault setIpr(int idx, InternalProcReg val, ExecContext *xc); +#endif + friend class RegFile; + }; + + class RegFile { + + protected: + Addr pc; // program counter + Addr npc; // next-cycle program counter + Addr nnpc; + + public: + Addr readPC() + { + return pc; + } + + void setPC(Addr val) + { + pc = val; + } + + Addr readNextPC() + { + return npc; + } + + void setNextPC(Addr val) + { + npc = val; + } + + Addr readNextNPC() + { + return nnpc; + } + + void setNextNPC(Addr val) + { + nnpc = val; + } + + protected: + IntRegFile intRegFile; // (signed) integer register file + FloatRegFile floatRegFile; // floating point register file + MiscRegFile miscRegFile; // control register file + + public: + +#if FULL_SYSTEM + int intrflag; // interrupt flag + inline int instAsid() + { return miscRegFile.getInstAsid(); } + inline int dataAsid() + { return miscRegFile.getDataAsid(); } +#endif // FULL_SYSTEM + + void clear() + { + bzero(&intRegFile, sizeof(intRegFile)); + bzero(&floatRegFile, sizeof(floatRegFile)); + bzero(&miscRegFile, sizeof(miscRegFile)); + } + + MiscReg readMiscReg(int miscReg) + { + return miscRegFile.readReg(miscReg); + } + + MiscReg readMiscRegWithEffect(int miscReg, + Fault &fault, ExecContext *xc) + { + fault = NoFault; + return miscRegFile.readRegWithEffect(miscReg, fault, xc); + } + + Fault setMiscReg(int miscReg, const MiscReg &val) + { + return miscRegFile.setReg(miscReg, val); + } + + Fault setMiscRegWithEffect(int miscReg, const MiscReg &val, + ExecContext * xc) + { + return miscRegFile.setRegWithEffect(miscReg, val, xc); + } + + FloatReg readFloatReg(int floatReg) + { + return floatRegFile.d[floatReg]; + } + + FloatReg readFloatReg(int floatReg, int width) + { + return readFloatReg(floatReg); + } + + FloatRegBits readFloatRegBits(int floatReg) + { + return floatRegFile.q[floatReg]; + } + + FloatRegBits readFloatRegBits(int floatReg, int width) + { + return readFloatRegBits(floatReg); + } + + Fault setFloatReg(int floatReg, const FloatReg &val) + { + floatRegFile.d[floatReg] = val; + return NoFault; + } + + Fault setFloatReg(int floatReg, const FloatReg &val, int width) + { + return setFloatReg(floatReg, val); + } + + Fault setFloatRegBits(int floatReg, const FloatRegBits &val) + { + floatRegFile.q[floatReg] = val; + return NoFault; + } + + Fault setFloatRegBits(int floatReg, const FloatRegBits &val, int width) + { + return setFloatRegBits(floatReg, val); + } + + IntReg readIntReg(int intReg) + { + return intRegFile.readReg(intReg); + } + + Fault setIntReg(int intReg, const IntReg &val) + { + return intRegFile.setReg(intReg, val); + } + + void serialize(std::ostream &os); + void unserialize(Checkpoint *cp, const std::string §ion); + + enum ContextParam + { + CONTEXT_PALMODE + }; + + typedef bool ContextVal; + + void changeContext(ContextParam param, ContextVal val) + { + //This would be an alternative place to call/implement + //the swapPALShadow function + } + }; + + void copyRegs(ExecContext *src, ExecContext *dest); + + void copyMiscRegs(ExecContext *src, ExecContext *dest); + +#if FULL_SYSTEM + void copyIprs(ExecContext *src, ExecContext *dest); +#endif +} // namespace AlphaISA + +#endif diff --git a/arch/alpha/stacktrace.cc b/arch/alpha/stacktrace.cc index 26656ab5c..8691e12dc 100644 --- a/arch/alpha/stacktrace.cc +++ b/arch/alpha/stacktrace.cc @@ -47,23 +47,23 @@ ProcessInfo::ProcessInfo(ExecContext *_xc) if (!xc->getSystemPtr()->kernelSymtab->findAddress("thread_info_size", addr)) panic("thread info not compiled into kernel\n"); - thread_info_size = *(int32_t *)vtomem(xc, addr, sizeof(int32_t)); + thread_info_size = gtoh(xc->getVirtPort()->read<int32_t>(addr)); if (!xc->getSystemPtr()->kernelSymtab->findAddress("task_struct_size", addr)) panic("thread info not compiled into kernel\n"); - task_struct_size = *(int32_t *)vtomem(xc, addr, sizeof(int32_t)); + task_struct_size = gtoh(xc->getVirtPort()->read<int32_t>(addr)); if (!xc->getSystemPtr()->kernelSymtab->findAddress("thread_info_task", addr)) panic("thread info not compiled into kernel\n"); - task_off = *(int32_t *)vtomem(xc, addr, sizeof(int32_t)); + task_off = gtoh(xc->getVirtPort()->read<int32_t>(addr)); if (!xc->getSystemPtr()->kernelSymtab->findAddress("task_struct_pid", addr)) panic("thread info not compiled into kernel\n"); - pid_off = *(int32_t *)vtomem(xc, addr, sizeof(int32_t)); + pid_off = gtoh(xc->getVirtPort()->read<int32_t>(addr)); if (!xc->getSystemPtr()->kernelSymtab->findAddress("task_struct_comm", addr)) panic("thread info not compiled into kernel\n"); - name_off = *(int32_t *)vtomem(xc, addr, sizeof(int32_t)); + name_off = gtoh(xc->getVirtPort()->read<int32_t>(addr)); } Addr @@ -73,9 +73,7 @@ ProcessInfo::task(Addr ksp) const if (base == ULL(0xfffffc0000000000)) return 0; - Addr task; - CopyOut(xc, &task, base + task_off, sizeof(task)); - return task; + return gtoh(xc->getVirtPort()->read<Addr>(base + task_off)); } int @@ -85,9 +83,7 @@ ProcessInfo::pid(Addr ksp) const if (!task) return -1; - uint16_t pid; - CopyOut(xc, &pid, task + pid_off, sizeof(pid)); - return pid; + return gtoh(xc->getVirtPort()->read<uint16_t>(task + pid_off)); } string @@ -98,7 +94,7 @@ ProcessInfo::name(Addr ksp) const return "console"; char comm[256]; - CopyString(xc, comm, task + name_off, sizeof(comm)); + CopyStringOut(xc, comm, task + name_off, sizeof(comm)); if (!comm[0]) return "startup"; diff --git a/arch/alpha/system.cc b/arch/alpha/system.cc index 25543da57..4234019cd 100644 --- a/arch/alpha/system.cc +++ b/arch/alpha/system.cc @@ -26,14 +26,14 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +#include "arch/alpha/ev5.hh" #include "arch/alpha/system.hh" #include "arch/vtophys.hh" #include "base/remote_gdb.hh" #include "base/loader/object_file.hh" #include "base/loader/symtab.hh" #include "base/trace.hh" -#include "mem/functional/memory_control.hh" -#include "mem/functional/physical.hh" +#include "mem/physical.hh" #include "sim/byteswap.hh" #include "sim/builder.hh" @@ -62,8 +62,8 @@ AlphaSystem::AlphaSystem(Params *p) // Load program sections into memory - pal->loadSections(physmem, true); - console->loadSections(physmem, true); + pal->loadSections(&functionalPort, AlphaISA::LoadAddrMask); + console->loadSections(&functionalPort, AlphaISA::LoadAddrMask); // load symbols if (!console->loadGlobalSymbols(consoleSymtab)) @@ -96,11 +96,8 @@ AlphaSystem::AlphaSystem(Params *p) * others do.) */ if (consoleSymtab->findAddress("env_booted_osflags", addr)) { - Addr paddr = vtophys(physmem, addr); - char *osflags = (char *)physmem->dma_addr(paddr, sizeof(uint32_t)); - - if (osflags) - strcpy(osflags, params()->boot_osflags.c_str()); + virtPort.writeBlob(addr, (uint8_t*)params()->boot_osflags.c_str(), + strlen(params()->boot_osflags.c_str())); } /** @@ -108,14 +105,11 @@ AlphaSystem::AlphaSystem(Params *p) * information to Tsunami. */ if (consoleSymtab->findAddress("m5_rpb", addr)) { - Addr paddr = vtophys(physmem, addr); - char *hwrpb = (char *)physmem->dma_addr(paddr, sizeof(uint64_t)); - - if (!hwrpb) - panic("could not translate hwrpb addr\n"); - - *(uint64_t*)(hwrpb+0x50) = htog(params()->system_type); - *(uint64_t*)(hwrpb+0x58) = htog(params()->system_rev); + uint64_t data; + data = htog(params()->system_type); + virtPort.write(addr+0x50, data); + data = htog(params()->system_rev); + virtPort.write(addr+0x58, data); } else panic("could not find hwrpb\n"); @@ -171,16 +165,13 @@ AlphaSystem::fixFuncEventAddr(Addr addr) const uint32_t gp_ldah_pattern = (9 << 26) | (29 << 21) | (27 << 16); // lda gp,Y(gp): opcode 8, Ra = 29, rb = 29 const uint32_t gp_lda_pattern = (8 << 26) | (29 << 21) | (29 << 16); - // instruction size - const int sz = sizeof(uint32_t); - Addr paddr = vtophys(physmem, addr); - uint32_t i1 = *(uint32_t *)physmem->dma_addr(paddr, sz); - uint32_t i2 = *(uint32_t *)physmem->dma_addr(paddr+sz, sz); + uint32_t i1 = virtPort.read<uint32_t>(addr); + uint32_t i2 = virtPort.read<uint32_t>(addr + sizeof(AlphaISA::MachInst)); if ((i1 & inst_mask) == gp_ldah_pattern && (i2 & inst_mask) == gp_lda_pattern) { - Addr new_addr = addr + 2*sz; + Addr new_addr = addr + 2* sizeof(AlphaISA::MachInst); DPRINTF(Loader, "fixFuncEventAddr: %p -> %p", addr, new_addr); return new_addr; } else { @@ -194,14 +185,7 @@ AlphaSystem::setAlphaAccess(Addr access) { Addr addr = 0; if (consoleSymtab->findAddress("m5AlphaAccess", addr)) { - Addr paddr = vtophys(physmem, addr); - uint64_t *m5AlphaAccess = - (uint64_t *)physmem->dma_addr(paddr, sizeof(uint64_t)); - - if (!m5AlphaAccess) - panic("could not translate m5AlphaAccess addr\n"); - - *m5AlphaAccess = htog(EV5::Phys2K0Seg(access)); + virtPort.write(addr, htog(EV5::Phys2K0Seg(access))); } else panic("could not find m5AlphaAccess\n"); } @@ -233,7 +217,6 @@ AlphaSystem::unserialize(Checkpoint *cp, const std::string §ion) BEGIN_DECLARE_SIM_OBJECT_PARAMS(AlphaSystem) Param<Tick> boot_cpu_frequency; - SimObjectParam<MemoryController *> memctrl; SimObjectParam<PhysicalMemory *> physmem; Param<std::string> kernel; @@ -256,7 +239,6 @@ END_DECLARE_SIM_OBJECT_PARAMS(AlphaSystem) BEGIN_INIT_SIM_OBJECT_PARAMS(AlphaSystem) INIT_PARAM(boot_cpu_frequency, "Frequency of the boot CPU"), - INIT_PARAM(memctrl, "memory controller"), INIT_PARAM(physmem, "phsyical memory"), INIT_PARAM(kernel, "file that contains the kernel code"), INIT_PARAM(console, "file that contains the console code"), @@ -278,7 +260,6 @@ CREATE_SIM_OBJECT(AlphaSystem) AlphaSystem::Params *p = new AlphaSystem::Params; p->name = getInstanceName(); p->boot_cpu_frequency = boot_cpu_frequency; - p->memctrl = memctrl; p->physmem = physmem; p->kernel_path = kernel; p->console_path = console; diff --git a/arch/alpha/system.hh b/arch/alpha/system.hh index fe1307ac3..924e16826 100644 --- a/arch/alpha/system.hh +++ b/arch/alpha/system.hh @@ -45,7 +45,6 @@ class AlphaSystem : public System { std::string console_path; std::string palcode; - std::string boot_osflags; uint64_t system_type; uint64_t system_rev; }; diff --git a/arch/alpha/tlb.cc b/arch/alpha/tlb.cc index e30a8e595..877822c31 100644 --- a/arch/alpha/tlb.cc +++ b/arch/alpha/tlb.cc @@ -93,8 +93,8 @@ AlphaTLB::lookup(Addr vpn, uint8_t asn) const } -void -AlphaTLB::checkCacheability(MemReqPtr &req) +Fault +AlphaTLB::checkCacheability(RequestPtr &req) { // in Alpha, cacheability is controlled by upper-level bits of the // physical address @@ -109,33 +109,24 @@ AlphaTLB::checkCacheability(MemReqPtr &req) #if ALPHA_TLASER - if (req->paddr & PAddrUncachedBit39) { + if (req->getPaddr() & PAddrUncachedBit39) { #else - if (req->paddr & PAddrUncachedBit43) { + if (req->getPaddr() & PAddrUncachedBit43) { #endif // IPR memory space not implemented - if (PAddrIprSpace(req->paddr)) { - if (!req->xc->misspeculating()) { - switch (req->paddr) { - case ULL(0xFFFFF00188): - req->data = 0; - break; - - default: - panic("IPR memory space not implemented! PA=%x\n", - req->paddr); - } - } + if (PAddrIprSpace(req->getPaddr())) { + return new UnimpFault("IPR memory space not implemented!"); } else { // mark request as uncacheable - req->flags |= UNCACHEABLE; + req->setFlags(req->getFlags() | UNCACHEABLE); #if !ALPHA_TLASER // Clear bits 42:35 of the physical address (10-2 in Tsunami manual) - req->paddr &= PAddrUncachedMask; + req->setPaddr(req->getPaddr() & PAddrUncachedMask); #endif } } + return NoFault; } @@ -290,38 +281,24 @@ AlphaITB::regStats() accesses = hits + misses; } -void -AlphaITB::fault(Addr pc, ExecContext *xc) const -{ - if (!xc->misspeculating()) { - xc->setMiscReg(AlphaISA::IPR_ITB_TAG, pc); - xc->setMiscReg(AlphaISA::IPR_IFAULT_VA_FORM, - xc->readMiscReg(AlphaISA::IPR_IVPTBR) | - (AlphaISA::VAddr(pc).vpn() << 3)); - } -} - Fault -AlphaITB::translate(MemReqPtr &req) const +AlphaITB::translate(RequestPtr &req, ExecContext *xc) const { - ExecContext *xc = req->xc; - - if (AlphaISA::PcPAL(req->vaddr)) { + if (AlphaISA::PcPAL(req->getVaddr())) { // strip off PAL PC marker (lsb is 1) - req->paddr = (req->vaddr & ~3) & PAddrImplMask; + req->setPaddr((req->getVaddr() & ~3) & PAddrImplMask); hits++; return NoFault; } - if (req->flags & PHYSICAL) { - req->paddr = req->vaddr; + if (req->getFlags() & PHYSICAL) { + req->setPaddr(req->getVaddr()); } else { // verify that this is a good virtual address - if (!validVirtualAddress(req->vaddr)) { - fault(req->vaddr, req->xc); + if (!validVirtualAddress(req->getVaddr())) { acv++; - return new ItbAcvFault; + return new ItbAcvFault(req->getVaddr()); } @@ -329,50 +306,48 @@ AlphaITB::translate(MemReqPtr &req) const // VA<47:41> == 0x7e, VA<40:13> maps directly to PA<40:13> for EV6 #if ALPHA_TLASER if ((MCSR_SP(xc->readMiscReg(AlphaISA::IPR_MCSR)) & 2) && - VAddrSpaceEV5(req->vaddr) == 2) { + VAddrSpaceEV5(req->getVaddr()) == 2) { #else - if (VAddrSpaceEV6(req->vaddr) == 0x7e) { + if (VAddrSpaceEV6(req->getVaddr()) == 0x7e) { #endif // only valid in kernel mode if (ICM_CM(xc->readMiscReg(AlphaISA::IPR_ICM)) != AlphaISA::mode_kernel) { - fault(req->vaddr, req->xc); acv++; - return new ItbAcvFault; + return new ItbAcvFault(req->getVaddr()); } - req->paddr = req->vaddr & PAddrImplMask; + req->setPaddr(req->getVaddr() & PAddrImplMask); #if !ALPHA_TLASER // sign extend the physical address properly - if (req->paddr & PAddrUncachedBit40) - req->paddr |= ULL(0xf0000000000); + if (req->getPaddr() & PAddrUncachedBit40) + req->setPaddr(req->getPaddr() | ULL(0xf0000000000)); else - req->paddr &= ULL(0xffffffffff); + req->setPaddr(req->getPaddr() & ULL(0xffffffffff)); #endif } else { // not a physical address: need to look up pte int asn = DTB_ASN_ASN(xc->readMiscReg(AlphaISA::IPR_DTB_ASN)); - AlphaISA::PTE *pte = lookup(AlphaISA::VAddr(req->vaddr).vpn(), + AlphaISA::PTE *pte = lookup(AlphaISA::VAddr(req->getVaddr()).vpn(), asn); if (!pte) { - fault(req->vaddr, req->xc); misses++; - return new ItbPageFault; + return new ItbPageFault(req->getVaddr()); } - req->paddr = (pte->ppn << AlphaISA::PageShift) + - (AlphaISA::VAddr(req->vaddr).offset() & ~3); + req->setPaddr((pte->ppn << AlphaISA::PageShift) + + (AlphaISA::VAddr(req->getVaddr()).offset() + & ~3)); // check permissions for this access if (!(pte->xre & (1 << ICM_CM(xc->readMiscReg(AlphaISA::IPR_ICM))))) { // instruction access fault - fault(req->vaddr, req->xc); acv++; - return new ItbAcvFault; + return new ItbAcvFault(req->getVaddr()); } hits++; @@ -380,12 +355,11 @@ AlphaITB::translate(MemReqPtr &req) const } // check that the physical address is ok (catch bad physical addresses) - if (req->paddr & ~PAddrImplMask) + if (req->getPaddr() & ~PAddrImplMask) return genMachineCheckFault(); - checkCacheability(req); + return checkCacheability(req); - return NoFault; } /////////////////////////////////////////////////////////////////////// @@ -465,38 +439,9 @@ AlphaDTB::regStats() accesses = read_accesses + write_accesses; } -void -AlphaDTB::fault(MemReqPtr &req, uint64_t flags) const -{ - ExecContext *xc = req->xc; - AlphaISA::VAddr vaddr = req->vaddr; - - // Set fault address and flags. Even though we're modeling an - // EV5, we use the EV6 technique of not latching fault registers - // on VPTE loads (instead of locking the registers until IPR_VA is - // read, like the EV5). The EV6 approach is cleaner and seems to - // work with EV5 PAL code, but not the other way around. - if (!xc->misspeculating() - && !(req->flags & VPTE) && !(req->flags & NO_FAULT)) { - // set VA register with faulting address - xc->setMiscReg(AlphaISA::IPR_VA, req->vaddr); - - // set MM_STAT register flags - xc->setMiscReg(AlphaISA::IPR_MM_STAT, - (((Opcode(xc->getInst()) & 0x3f) << 11) - | ((Ra(xc->getInst()) & 0x1f) << 6) - | (flags & 0x3f))); - - // set VA_FORM register with faulting formatted address - xc->setMiscReg(AlphaISA::IPR_VA_FORM, - xc->readMiscReg(AlphaISA::IPR_MVPTBR) | (vaddr.vpn() << 3)); - } -} - Fault -AlphaDTB::translate(MemReqPtr &req, bool write) const +AlphaDTB::translate(RequestPtr &req, ExecContext *xc, bool write) const { - ExecContext *xc = req->xc; Addr pc = xc->readPC(); AlphaISA::mode_type mode = @@ -506,58 +451,57 @@ AlphaDTB::translate(MemReqPtr &req, bool write) const /** * Check for alignment faults */ - if (req->vaddr & (req->size - 1)) { - fault(req, write ? MM_STAT_WR_MASK : 0); - DPRINTF(TLB, "Alignment Fault on %#x, size = %d", req->vaddr, - req->size); - return genAlignmentFault(); + if (req->getVaddr() & (req->getSize() - 1)) { + DPRINTF(TLB, "Alignment Fault on %#x, size = %d", req->getVaddr(), + req->getSize()); + uint64_t flags = write ? MM_STAT_WR_MASK : 0; + return new DtbAlignmentFault(req->getVaddr(), req->getFlags(), flags); } if (pc & 0x1) { - mode = (req->flags & ALTMODE) ? + mode = (req->getFlags() & ALTMODE) ? (AlphaISA::mode_type)ALT_MODE_AM( xc->readMiscReg(AlphaISA::IPR_ALT_MODE)) : AlphaISA::mode_kernel; } - if (req->flags & PHYSICAL) { - req->paddr = req->vaddr; + if (req->getFlags() & PHYSICAL) { + req->setPaddr(req->getVaddr()); } else { // verify that this is a good virtual address - if (!validVirtualAddress(req->vaddr)) { - fault(req, (write ? MM_STAT_WR_MASK : 0) | - MM_STAT_BAD_VA_MASK | - MM_STAT_ACV_MASK); - + if (!validVirtualAddress(req->getVaddr())) { if (write) { write_acv++; } else { read_acv++; } - return new DtbPageFault; + uint64_t flags = (write ? MM_STAT_WR_MASK : 0) | + MM_STAT_BAD_VA_MASK | + MM_STAT_ACV_MASK; + return new DtbPageFault(req->getVaddr(), req->getFlags(), flags); } // Check for "superpage" mapping #if ALPHA_TLASER if ((MCSR_SP(xc->readMiscReg(AlphaISA::IPR_MCSR)) & 2) && - VAddrSpaceEV5(req->vaddr) == 2) { + VAddrSpaceEV5(req->getVaddr()) == 2) { #else - if (VAddrSpaceEV6(req->vaddr) == 0x7e) { + if (VAddrSpaceEV6(req->getVaddr()) == 0x7e) { #endif // only valid in kernel mode if (DTB_CM_CM(xc->readMiscReg(AlphaISA::IPR_DTB_CM)) != AlphaISA::mode_kernel) { - fault(req, ((write ? MM_STAT_WR_MASK : 0) | - MM_STAT_ACV_MASK)); if (write) { write_acv++; } else { read_acv++; } - return new DtbAcvFault; + uint64_t flags = ((write ? MM_STAT_WR_MASK : 0) | + MM_STAT_ACV_MASK); + return new DtbAcvFault(req->getVaddr(), req->getFlags(), flags); } - req->paddr = req->vaddr & PAddrImplMask; + req->setPaddr(req->getVaddr() & PAddrImplMask); #if !ALPHA_TLASER // sign extend the physical address properly - if (req->paddr & PAddrUncachedBit40) - req->paddr |= ULL(0xf0000000000); + if (req->getPaddr() & PAddrUncachedBit40) + req->setPaddr(req->getPaddr() | ULL(0xf0000000000)); else - req->paddr &= ULL(0xffffffffff); + req->setPaddr(req->getPaddr() & ULL(0xffffffffff)); #endif } else { @@ -569,48 +513,50 @@ AlphaDTB::translate(MemReqPtr &req, bool write) const int asn = DTB_ASN_ASN(xc->readMiscReg(AlphaISA::IPR_DTB_ASN)); // not a physical address: need to look up pte - AlphaISA::PTE *pte = lookup(AlphaISA::VAddr(req->vaddr).vpn(), + AlphaISA::PTE *pte = lookup(AlphaISA::VAddr(req->getVaddr()).vpn(), asn); if (!pte) { // page fault - fault(req, (write ? MM_STAT_WR_MASK : 0) | - MM_STAT_DTB_MISS_MASK); if (write) { write_misses++; } else { read_misses++; } - return (req->flags & VPTE) ? - (Fault)(new PDtbMissFault) : - (Fault)(new NDtbMissFault); + uint64_t flags = (write ? MM_STAT_WR_MASK : 0) | + MM_STAT_DTB_MISS_MASK; + return (req->getFlags() & VPTE) ? + (Fault)(new PDtbMissFault(req->getVaddr(), req->getFlags(), + flags)) : + (Fault)(new NDtbMissFault(req->getVaddr(), req->getFlags(), + flags)); } - req->paddr = (pte->ppn << AlphaISA::PageShift) + - AlphaISA::VAddr(req->vaddr).offset(); + req->setPaddr((pte->ppn << AlphaISA::PageShift) + + AlphaISA::VAddr(req->getVaddr()).offset()); if (write) { if (!(pte->xwe & MODE2MASK(mode))) { // declare the instruction access fault - fault(req, MM_STAT_WR_MASK | - MM_STAT_ACV_MASK | - (pte->fonw ? MM_STAT_FONW_MASK : 0)); write_acv++; - return new DtbPageFault; + uint64_t flags = MM_STAT_WR_MASK | + MM_STAT_ACV_MASK | + (pte->fonw ? MM_STAT_FONW_MASK : 0); + return new DtbPageFault(req->getVaddr(), req->getFlags(), flags); } if (pte->fonw) { - fault(req, MM_STAT_WR_MASK | - MM_STAT_FONW_MASK); write_acv++; - return new DtbPageFault; + uint64_t flags = MM_STAT_WR_MASK | + MM_STAT_FONW_MASK; + return new DtbPageFault(req->getVaddr(), req->getFlags(), flags); } } else { if (!(pte->xre & MODE2MASK(mode))) { - fault(req, MM_STAT_ACV_MASK | - (pte->fonr ? MM_STAT_FONR_MASK : 0)); read_acv++; - return new DtbAcvFault; + uint64_t flags = MM_STAT_ACV_MASK | + (pte->fonr ? MM_STAT_FONR_MASK : 0); + return new DtbAcvFault(req->getVaddr(), req->getFlags(), flags); } if (pte->fonr) { - fault(req, MM_STAT_FONR_MASK); read_acv++; - return new DtbPageFault; + uint64_t flags = MM_STAT_FONR_MASK; + return new DtbPageFault(req->getVaddr(), req->getFlags(), flags); } } } @@ -622,12 +568,10 @@ AlphaDTB::translate(MemReqPtr &req, bool write) const } // check that the physical address is ok (catch bad physical addresses) - if (req->paddr & ~PAddrImplMask) + if (req->getPaddr() & ~PAddrImplMask) return genMachineCheckFault(); - checkCacheability(req); - - return NoFault; + return checkCacheability(req); } AlphaISA::PTE & diff --git a/arch/alpha/tlb.hh b/arch/alpha/tlb.hh index de955fa46..f6256020e 100644 --- a/arch/alpha/tlb.hh +++ b/arch/alpha/tlb.hh @@ -31,10 +31,11 @@ #include <map> +#include "arch/alpha/ev5.hh" #include "arch/alpha/isa_traits.hh" #include "arch/alpha/faults.hh" #include "base/statistics.hh" -#include "mem/mem_req.hh" +#include "mem/request.hh" #include "sim/sim_object.hh" class ExecContext; @@ -72,7 +73,7 @@ class AlphaTLB : public SimObject return (unimplBits == 0) || (unimplBits == EV5::VAddrUnImplMask); } - static void checkCacheability(MemReqPtr &req); + static Fault checkCacheability(RequestPtr &req); // Checkpointing virtual void serialize(std::ostream &os); @@ -87,14 +88,11 @@ class AlphaITB : public AlphaTLB mutable Stats::Scalar<> acv; mutable Stats::Formula accesses; - protected: - void fault(Addr pc, ExecContext *xc) const; - public: AlphaITB(const std::string &name, int size); virtual void regStats(); - Fault translate(MemReqPtr &req) const; + Fault translate(RequestPtr &req, ExecContext *xc) const; }; class AlphaDTB : public AlphaTLB @@ -113,14 +111,11 @@ class AlphaDTB : public AlphaTLB Stats::Formula acv; Stats::Formula accesses; - protected: - void fault(MemReqPtr &req, uint64_t flags) const; - public: AlphaDTB(const std::string &name, int size); virtual void regStats(); - Fault translate(MemReqPtr &req, bool write) const; + Fault translate(RequestPtr &req, ExecContext *xc, bool write) const; }; #endif // __ALPHA_MEMORY_HH__ diff --git a/arch/alpha/tru64/process.cc b/arch/alpha/tru64/process.cc index ae83bb649..55f75f7d0 100644 --- a/arch/alpha/tru64/process.cc +++ b/arch/alpha/tru64/process.cc @@ -26,11 +26,13 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +#include "arch/alpha/tru64/tru64.hh" #include "arch/alpha/isa_traits.hh" #include "arch/alpha/tru64/process.hh" + #include "cpu/exec_context.hh" #include "kern/tru64/tru64.hh" -#include "mem/functional/functional.hh" + #include "sim/process.hh" #include "sim/syscall_emul.hh" @@ -42,7 +44,7 @@ static SyscallReturn unameFunc(SyscallDesc *desc, int callnum, Process *process, ExecContext *xc) { - TypedBufferArg<Tru64::utsname> name(xc->getSyscallArg(0)); + TypedBufferArg<AlphaTru64::utsname> name(xc->getSyscallArg(0)); strcpy(name->sysname, "OSF1"); strcpy(name->nodename, "m5.eecs.umich.edu"); @@ -50,7 +52,7 @@ unameFunc(SyscallDesc *desc, int callnum, Process *process, strcpy(name->version, "732"); strcpy(name->machine, "alpha"); - name.copyOut(xc->getMemPtr()); + name.copyOut(xc->getMemPort()); return 0; } @@ -64,29 +66,29 @@ getsysinfoFunc(SyscallDesc *desc, int callnum, Process *process, switch (op) { - case Tru64::GSI_MAX_CPU: { + case AlphaTru64::GSI_MAX_CPU: { TypedBufferArg<uint32_t> max_cpu(xc->getSyscallArg(1)); *max_cpu = htog((uint32_t)process->numCpus()); - max_cpu.copyOut(xc->getMemPtr()); + max_cpu.copyOut(xc->getMemPort()); return 1; } - case Tru64::GSI_CPUS_IN_BOX: { + case AlphaTru64::GSI_CPUS_IN_BOX: { TypedBufferArg<uint32_t> cpus_in_box(xc->getSyscallArg(1)); *cpus_in_box = htog((uint32_t)process->numCpus()); - cpus_in_box.copyOut(xc->getMemPtr()); + cpus_in_box.copyOut(xc->getMemPort()); return 1; } - case Tru64::GSI_PHYSMEM: { + case AlphaTru64::GSI_PHYSMEM: { TypedBufferArg<uint64_t> physmem(xc->getSyscallArg(1)); *physmem = htog((uint64_t)1024 * 1024); // physical memory in KB - physmem.copyOut(xc->getMemPtr()); + physmem.copyOut(xc->getMemPort()); return 1; } - case Tru64::GSI_CPU_INFO: { - TypedBufferArg<Tru64::cpu_info> infop(xc->getSyscallArg(1)); + case AlphaTru64::GSI_CPU_INFO: { + TypedBufferArg<AlphaTru64::cpu_info> infop(xc->getSyscallArg(1)); infop->current_cpu = htog(0); infop->cpus_in_box = htog(process->numCpus()); @@ -98,30 +100,30 @@ getsysinfoFunc(SyscallDesc *desc, int callnum, Process *process, infop->cpu_ex_binding = htog(0); infop->mhz = htog(667); - infop.copyOut(xc->getMemPtr()); + infop.copyOut(xc->getMemPort()); return 1; } - case Tru64::GSI_PROC_TYPE: { + case AlphaTru64::GSI_PROC_TYPE: { TypedBufferArg<uint64_t> proc_type(xc->getSyscallArg(1)); *proc_type = htog((uint64_t)11); - proc_type.copyOut(xc->getMemPtr()); + proc_type.copyOut(xc->getMemPort()); return 1; } - case Tru64::GSI_PLATFORM_NAME: { + case AlphaTru64::GSI_PLATFORM_NAME: { BufferArg bufArg(xc->getSyscallArg(1), nbytes); strncpy((char *)bufArg.bufferPtr(), "COMPAQ Professional Workstation XP1000", nbytes); - bufArg.copyOut(xc->getMemPtr()); + bufArg.copyOut(xc->getMemPort()); return 1; } - case Tru64::GSI_CLK_TCK: { + case AlphaTru64::GSI_CLK_TCK: { TypedBufferArg<uint64_t> clk_hz(xc->getSyscallArg(1)); *clk_hz = htog((uint64_t)1024); - clk_hz.copyOut(xc->getMemPtr()); + clk_hz.copyOut(xc->getMemPort()); return 1; } @@ -141,7 +143,7 @@ setsysinfoFunc(SyscallDesc *desc, int callnum, Process *process, unsigned op = xc->getSyscallArg(0); switch (op) { - case Tru64::SSI_IEEE_FP_CONTROL: + case AlphaTru64::SSI_IEEE_FP_CONTROL: warn("setsysinfo: ignoring ieee_set_fp_control() arg 0x%x\n", xc->getSyscallArg(1)); break; @@ -155,8 +157,48 @@ setsysinfoFunc(SyscallDesc *desc, int callnum, Process *process, } +/// Target table() handler. +static +SyscallReturn tableFunc(SyscallDesc *desc, int callnum,Process *process, + ExecContext *xc) +{ + using namespace std; + using namespace TheISA; + + int id = xc->getSyscallArg(0); // table ID + int index = xc->getSyscallArg(1); // index into table + // arg 2 is buffer pointer; type depends on table ID + int nel = xc->getSyscallArg(3); // number of elements + int lel = xc->getSyscallArg(4); // 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(xc->getSyscallArg(2)); + + const int clk_hz = one_million; + elp->si_user = htog(curTick / (Clock::Frequency / clk_hz)); + elp->si_nice = htog(0); + elp->si_sys = htog(0); + elp->si_idle = htog(0); + elp->wait = htog(0); + elp->si_hz = htog(clk_hz); + elp->si_phz = htog(clk_hz); + elp->si_boottime = htog(seconds_since_epoch); // seconds since epoch? + elp->si_max_procs = htog(process->numCpus()); + elp.copyOut(xc->getMemPort()); + return 0; + } + + default: + cerr << "table(): id " << id << " unknown." << endl; + return -EINVAL; + } +} + SyscallDesc AlphaTru64Process::syscallDescs[] = { - /* 0 */ SyscallDesc("syscall (#0)", Tru64::indirectSyscallFunc, + /* 0 */ SyscallDesc("syscall (#0)", AlphaTru64::indirectSyscallFunc, SyscallDesc::SuppressReturnValue), /* 1 */ SyscallDesc("exit", exitFunc), /* 2 */ SyscallDesc("fork", unimplementedFunc), @@ -202,7 +244,7 @@ SyscallDesc AlphaTru64Process::syscallDescs[] = { /* 42 */ SyscallDesc("pipe", unimplementedFunc), /* 43 */ SyscallDesc("set_program_attributes", unimplementedFunc), /* 44 */ SyscallDesc("profil", unimplementedFunc), - /* 45 */ SyscallDesc("open", openFunc<Tru64>), + /* 45 */ SyscallDesc("open", openFunc<AlphaTru64>), /* 46 */ SyscallDesc("obsolete osigaction", unimplementedFunc), /* 47 */ SyscallDesc("getgid", getgidPseudoFunc), /* 48 */ SyscallDesc("sigprocmask", ignoreFunc), @@ -211,7 +253,7 @@ SyscallDesc AlphaTru64Process::syscallDescs[] = { /* 51 */ SyscallDesc("acct", unimplementedFunc), /* 52 */ SyscallDesc("sigpending", unimplementedFunc), /* 53 */ SyscallDesc("classcntl", unimplementedFunc), - /* 54 */ SyscallDesc("ioctl", ioctlFunc<Tru64>), + /* 54 */ SyscallDesc("ioctl", ioctlFunc<AlphaTru64>), /* 55 */ SyscallDesc("reboot", unimplementedFunc), /* 56 */ SyscallDesc("revoke", unimplementedFunc), /* 57 */ SyscallDesc("symlink", unimplementedFunc), @@ -224,11 +266,11 @@ SyscallDesc AlphaTru64Process::syscallDescs[] = { /* 64 */ SyscallDesc("getpagesize", getpagesizeFunc), /* 65 */ SyscallDesc("mremap", unimplementedFunc), /* 66 */ SyscallDesc("vfork", unimplementedFunc), - /* 67 */ SyscallDesc("pre_F64_stat", statFunc<Tru64::PreF64>), - /* 68 */ SyscallDesc("pre_F64_lstat", lstatFunc<Tru64::PreF64>), + /* 67 */ SyscallDesc("pre_F64_stat", statFunc<AlphaTru64::PreF64>), + /* 68 */ SyscallDesc("pre_F64_lstat", lstatFunc<AlphaTru64::PreF64>), /* 69 */ SyscallDesc("sbrk", unimplementedFunc), /* 70 */ SyscallDesc("sstk", unimplementedFunc), - /* 71 */ SyscallDesc("mmap", mmapFunc<Tru64>), + /* 71 */ SyscallDesc("mmap", mmapFunc<AlphaTru64>), /* 72 */ SyscallDesc("ovadvise", unimplementedFunc), /* 73 */ SyscallDesc("munmap", munmapFunc), /* 74 */ SyscallDesc("mprotect", ignoreFunc), @@ -242,13 +284,13 @@ SyscallDesc AlphaTru64Process::syscallDescs[] = { /* 82 */ SyscallDesc("setpgrp", unimplementedFunc), /* 83 */ SyscallDesc("setitimer", unimplementedFunc), /* 84 */ SyscallDesc("old_wait", unimplementedFunc), - /* 85 */ SyscallDesc("table", Tru64::tableFunc), + /* 85 */ SyscallDesc("table", tableFunc), /* 86 */ SyscallDesc("getitimer", unimplementedFunc), /* 87 */ SyscallDesc("gethostname", gethostnameFunc), /* 88 */ SyscallDesc("sethostname", unimplementedFunc), /* 89 */ SyscallDesc("getdtablesize", unimplementedFunc), /* 90 */ SyscallDesc("dup2", unimplementedFunc), - /* 91 */ SyscallDesc("pre_F64_fstat", fstatFunc<Tru64::PreF64>), + /* 91 */ SyscallDesc("pre_F64_fstat", fstatFunc<AlphaTru64::PreF64>), /* 92 */ SyscallDesc("fcntl", fcntlFunc), /* 93 */ SyscallDesc("select", unimplementedFunc), /* 94 */ SyscallDesc("poll", unimplementedFunc), @@ -260,7 +302,7 @@ SyscallDesc AlphaTru64Process::syscallDescs[] = { /* 100 */ SyscallDesc("getpriority", unimplementedFunc), /* 101 */ SyscallDesc("old_send", unimplementedFunc), /* 102 */ SyscallDesc("old_recv", unimplementedFunc), - /* 103 */ SyscallDesc("sigreturn", Tru64::sigreturnFunc, + /* 103 */ SyscallDesc("sigreturn", AlphaTru64::sigreturnFunc, SyscallDesc::SuppressReturnValue), /* 104 */ SyscallDesc("bind", unimplementedFunc), /* 105 */ SyscallDesc("setsockopt", unimplementedFunc), @@ -274,8 +316,8 @@ SyscallDesc AlphaTru64Process::syscallDescs[] = { /* 113 */ SyscallDesc("old_recvmsg", unimplementedFunc), /* 114 */ SyscallDesc("old_sendmsg", unimplementedFunc), /* 115 */ SyscallDesc("obsolete vtrace", unimplementedFunc), - /* 116 */ SyscallDesc("gettimeofday", gettimeofdayFunc<Tru64>), - /* 117 */ SyscallDesc("getrusage", getrusageFunc<Tru64>), + /* 116 */ SyscallDesc("gettimeofday", gettimeofdayFunc<AlphaTru64>), + /* 117 */ SyscallDesc("getrusage", getrusageFunc<AlphaTru64>), /* 118 */ SyscallDesc("getsockopt", unimplementedFunc), /* 119 */ SyscallDesc("numa_syscalls", unimplementedFunc), /* 120 */ SyscallDesc("readv", unimplementedFunc), @@ -302,7 +344,7 @@ SyscallDesc AlphaTru64Process::syscallDescs[] = { /* 141 */ SyscallDesc("old_getpeername", unimplementedFunc), /* 142 */ SyscallDesc("gethostid", unimplementedFunc), /* 143 */ SyscallDesc("sethostid", unimplementedFunc), - /* 144 */ SyscallDesc("getrlimit", getrlimitFunc<Tru64>), + /* 144 */ SyscallDesc("getrlimit", getrlimitFunc<AlphaTru64>), /* 145 */ SyscallDesc("setrlimit", ignoreFunc), /* 146 */ SyscallDesc("old_killpg", unimplementedFunc), /* 147 */ SyscallDesc("setsid", unimplementedFunc), @@ -317,9 +359,9 @@ SyscallDesc AlphaTru64Process::syscallDescs[] = { /* 156 */ SyscallDesc("sigaction", ignoreFunc), /* 157 */ SyscallDesc("sigwaitprim", unimplementedFunc), /* 158 */ SyscallDesc("nfssvc", unimplementedFunc), - /* 159 */ SyscallDesc("getdirentries", Tru64::getdirentriesFunc), - /* 160 */ SyscallDesc("pre_F64_statfs", statfsFunc<Tru64::PreF64>), - /* 161 */ SyscallDesc("pre_F64_fstatfs", fstatfsFunc<Tru64::PreF64>), + /* 159 */ SyscallDesc("getdirentries", AlphaTru64::getdirentriesFunc), + /* 160 */ SyscallDesc("pre_F64_statfs", statfsFunc<AlphaTru64::PreF64>), + /* 161 */ SyscallDesc("pre_F64_fstatfs", fstatfsFunc<AlphaTru64::PreF64>), /* 162 */ SyscallDesc("unknown #162", unimplementedFunc), /* 163 */ SyscallDesc("async_daemon", unimplementedFunc), /* 164 */ SyscallDesc("getfh", unimplementedFunc), @@ -382,11 +424,11 @@ SyscallDesc AlphaTru64Process::syscallDescs[] = { /* 221 */ SyscallDesc("unknown #221", unimplementedFunc), /* 222 */ SyscallDesc("security", unimplementedFunc), /* 223 */ SyscallDesc("kloadcall", unimplementedFunc), - /* 224 */ SyscallDesc("stat", statFunc<Tru64::F64>), - /* 225 */ SyscallDesc("lstat", lstatFunc<Tru64::F64>), - /* 226 */ SyscallDesc("fstat", fstatFunc<Tru64::F64>), - /* 227 */ SyscallDesc("statfs", statfsFunc<Tru64::F64>), - /* 228 */ SyscallDesc("fstatfs", fstatfsFunc<Tru64::F64>), + /* 224 */ SyscallDesc("stat", statFunc<AlphaTru64::F64>), + /* 225 */ SyscallDesc("lstat", lstatFunc<AlphaTru64::F64>), + /* 226 */ SyscallDesc("fstat", fstatFunc<AlphaTru64::F64>), + /* 227 */ SyscallDesc("statfs", statfsFunc<AlphaTru64::F64>), + /* 228 */ SyscallDesc("fstatfs", fstatfsFunc<AlphaTru64::F64>), /* 229 */ SyscallDesc("getfsstat", unimplementedFunc), /* 230 */ SyscallDesc("gettimeofday64", unimplementedFunc), /* 231 */ SyscallDesc("settimeofday64", unimplementedFunc), @@ -431,13 +473,13 @@ SyscallDesc AlphaTru64Process::syscallDescs[] = { SyscallDesc AlphaTru64Process::machSyscallDescs[] = { /* 0 */ SyscallDesc("kern_invalid", unimplementedFunc), - /* 1 */ SyscallDesc("m5_mutex_lock", Tru64::m5_mutex_lockFunc), - /* 2 */ SyscallDesc("m5_mutex_trylock", Tru64::m5_mutex_trylockFunc), - /* 3 */ SyscallDesc("m5_mutex_unlock", Tru64::m5_mutex_unlockFunc), - /* 4 */ SyscallDesc("m5_cond_signal", Tru64::m5_cond_signalFunc), - /* 5 */ SyscallDesc("m5_cond_broadcast", Tru64::m5_cond_broadcastFunc), - /* 6 */ SyscallDesc("m5_cond_wait", Tru64::m5_cond_waitFunc), - /* 7 */ SyscallDesc("m5_thread_exit", Tru64::m5_thread_exitFunc), + /* 1 */ SyscallDesc("m5_mutex_lock", AlphaTru64::m5_mutex_lockFunc), + /* 2 */ SyscallDesc("m5_mutex_trylock", AlphaTru64::m5_mutex_trylockFunc), + /* 3 */ SyscallDesc("m5_mutex_unlock", AlphaTru64::m5_mutex_unlockFunc), + /* 4 */ SyscallDesc("m5_cond_signal", AlphaTru64::m5_cond_signalFunc), + /* 5 */ SyscallDesc("m5_cond_broadcast", AlphaTru64::m5_cond_broadcastFunc), + /* 6 */ SyscallDesc("m5_cond_wait", AlphaTru64::m5_cond_waitFunc), + /* 7 */ SyscallDesc("m5_thread_exit", AlphaTru64::m5_thread_exitFunc), /* 8 */ SyscallDesc("kern_invalid", unimplementedFunc), /* 9 */ SyscallDesc("kern_invalid", unimplementedFunc), /* 10 */ SyscallDesc("task_self", unimplementedFunc), @@ -454,22 +496,22 @@ SyscallDesc AlphaTru64Process::machSyscallDescs[] = { /* 21 */ SyscallDesc("msg_receive_trap", unimplementedFunc), /* 22 */ SyscallDesc("msg_rpc_trap", unimplementedFunc), /* 23 */ SyscallDesc("kern_invalid", unimplementedFunc), - /* 24 */ SyscallDesc("nxm_block", Tru64::nxm_blockFunc), - /* 25 */ SyscallDesc("nxm_unblock", Tru64::nxm_unblockFunc), + /* 24 */ SyscallDesc("nxm_block", AlphaTru64::nxm_blockFunc), + /* 25 */ SyscallDesc("nxm_unblock", AlphaTru64::nxm_unblockFunc), /* 26 */ SyscallDesc("kern_invalid", unimplementedFunc), /* 27 */ SyscallDesc("kern_invalid", unimplementedFunc), /* 28 */ SyscallDesc("kern_invalid", unimplementedFunc), /* 29 */ SyscallDesc("nxm_thread_destroy", unimplementedFunc), /* 30 */ SyscallDesc("lw_wire", unimplementedFunc), /* 31 */ SyscallDesc("lw_unwire", unimplementedFunc), - /* 32 */ SyscallDesc("nxm_thread_create", Tru64::nxm_thread_createFunc), - /* 33 */ SyscallDesc("nxm_task_init", Tru64::nxm_task_initFunc), + /* 32 */ SyscallDesc("nxm_thread_create", AlphaTru64::nxm_thread_createFunc), + /* 33 */ SyscallDesc("nxm_task_init", AlphaTru64::nxm_task_initFunc), /* 34 */ SyscallDesc("kern_invalid", unimplementedFunc), - /* 35 */ SyscallDesc("nxm_idle", Tru64::nxm_idleFunc), + /* 35 */ SyscallDesc("nxm_idle", AlphaTru64::nxm_idleFunc), /* 36 */ SyscallDesc("nxm_wakeup_idle", unimplementedFunc), /* 37 */ SyscallDesc("nxm_set_pthid", unimplementedFunc), /* 38 */ SyscallDesc("nxm_thread_kill", unimplementedFunc), - /* 39 */ SyscallDesc("nxm_thread_block", Tru64::nxm_thread_blockFunc), + /* 39 */ SyscallDesc("nxm_thread_block", AlphaTru64::nxm_thread_blockFunc), /* 40 */ SyscallDesc("nxm_thread_wakeup", unimplementedFunc), /* 41 */ SyscallDesc("init_process", unimplementedFunc), /* 42 */ SyscallDesc("nxm_get_binding", unimplementedFunc), @@ -477,7 +519,7 @@ SyscallDesc AlphaTru64Process::machSyscallDescs[] = { /* 44 */ SyscallDesc("nxm_resched", unimplementedFunc), /* 45 */ SyscallDesc("nxm_set_cancel", unimplementedFunc), /* 46 */ SyscallDesc("nxm_set_binding", unimplementedFunc), - /* 47 */ SyscallDesc("stack_create", Tru64::stack_createFunc), + /* 47 */ SyscallDesc("stack_create", AlphaTru64::stack_createFunc), /* 48 */ SyscallDesc("nxm_get_state", unimplementedFunc), /* 49 */ SyscallDesc("nxm_thread_suspend", unimplementedFunc), /* 50 */ SyscallDesc("nxm_thread_resume", unimplementedFunc), @@ -489,7 +531,7 @@ SyscallDesc AlphaTru64Process::machSyscallDescs[] = { /* 56 */ SyscallDesc("host_priv_self", unimplementedFunc), /* 57 */ SyscallDesc("kern_invalid", unimplementedFunc), /* 58 */ SyscallDesc("kern_invalid", unimplementedFunc), - /* 59 */ SyscallDesc("swtch_pri", Tru64::swtch_priFunc), + /* 59 */ SyscallDesc("swtch_pri", AlphaTru64::swtch_priFunc), /* 60 */ SyscallDesc("swtch", unimplementedFunc), /* 61 */ SyscallDesc("thread_switch", unimplementedFunc), /* 62 */ SyscallDesc("semop_fast", unimplementedFunc), @@ -497,7 +539,7 @@ SyscallDesc AlphaTru64Process::machSyscallDescs[] = { /* 64 */ SyscallDesc("nxm_pshared_block", unimplementedFunc), /* 65 */ SyscallDesc("nxm_pshared_unblock", unimplementedFunc), /* 66 */ SyscallDesc("nxm_pshared_destroy", unimplementedFunc), - /* 67 */ SyscallDesc("nxm_swtch_pri", Tru64::swtch_priFunc), + /* 67 */ SyscallDesc("nxm_swtch_pri", AlphaTru64::swtch_priFunc), /* 68 */ SyscallDesc("lw_syscall", unimplementedFunc), /* 69 */ SyscallDesc("kern_invalid", unimplementedFunc), /* 70 */ SyscallDesc("mach_sctimes_0", unimplementedFunc), @@ -530,12 +572,14 @@ AlphaTru64Process::getDesc(int callnum) AlphaTru64Process::AlphaTru64Process(const std::string &name, ObjectFile *objFile, + System *system, int stdin_fd, int stdout_fd, int stderr_fd, std::vector<std::string> &argv, std::vector<std::string> &envp) - : LiveProcess(name, objFile, stdin_fd, stdout_fd, stderr_fd, argv, envp), + : AlphaLiveProcess(name, objFile, system, stdin_fd, stdout_fd, + stderr_fd, argv, envp), Num_Syscall_Descs(sizeof(syscallDescs) / sizeof(SyscallDesc)), Num_Mach_Syscall_Descs(sizeof(machSyscallDescs) / sizeof(SyscallDesc)) { diff --git a/arch/alpha/tru64/process.hh b/arch/alpha/tru64/process.hh index 051760702..1cde4cac0 100644 --- a/arch/alpha/tru64/process.hh +++ b/arch/alpha/tru64/process.hh @@ -29,15 +29,17 @@ #ifndef __ALPHA_TRU64_PROCESS_HH__ #define __ALPHA_TRU64_PROCESS_HH__ -#include "sim/process.hh" +#include "arch/alpha/process.hh" +namespace AlphaISA { /// A process with emulated Alpha Tru64 syscalls. -class AlphaTru64Process : public LiveProcess +class AlphaTru64Process : public AlphaLiveProcess { public: /// Constructor. AlphaTru64Process(const std::string &name, ObjectFile *objFile, + System *system, int stdin_fd, int stdout_fd, int stderr_fd, std::vector<std::string> &argv, std::vector<std::string> &envp); @@ -54,5 +56,6 @@ class AlphaTru64Process : public LiveProcess virtual SyscallDesc* getDesc(int callnum); }; +} // namespace AlphaISA #endif // __ALPHA_TRU64_PROCESS_HH__ diff --git a/arch/alpha/tru64/system.cc b/arch/alpha/tru64/system.cc index d09a0c85d..2ad06d679 100644 --- a/arch/alpha/tru64/system.cc +++ b/arch/alpha/tru64/system.cc @@ -35,8 +35,8 @@ #include "cpu/exec_context.hh" #include "kern/tru64/tru64_events.hh" #include "kern/system_events.hh" -#include "mem/functional/memory_control.hh" -#include "mem/functional/physical.hh" +#include "mem/physical.hh" +#include "mem/port.hh" #include "sim/builder.hh" using namespace std; @@ -46,12 +46,7 @@ Tru64AlphaSystem::Tru64AlphaSystem(Tru64AlphaSystem::Params *p) { Addr addr = 0; if (kernelSymtab->findAddress("enable_async_printf", addr)) { - Addr paddr = vtophys(physmem, addr); - uint8_t *enable_async_printf = - physmem->dma_addr(paddr, sizeof(uint32_t)); - - if (enable_async_printf) - *(uint32_t *)enable_async_printf = 0; + virtPort.write(addr, (uint32_t)0); } #ifdef DEBUG @@ -96,7 +91,6 @@ Tru64AlphaSystem::~Tru64AlphaSystem() BEGIN_DECLARE_SIM_OBJECT_PARAMS(Tru64AlphaSystem) Param<Tick> boot_cpu_frequency; - SimObjectParam<MemoryController *> memctrl; SimObjectParam<PhysicalMemory *> physmem; Param<string> kernel; @@ -118,7 +112,6 @@ END_DECLARE_SIM_OBJECT_PARAMS(Tru64AlphaSystem) BEGIN_INIT_SIM_OBJECT_PARAMS(Tru64AlphaSystem) INIT_PARAM(boot_cpu_frequency, "frequency of the boot cpu"), - INIT_PARAM(memctrl, "memory controller"), INIT_PARAM(physmem, "phsyical memory"), INIT_PARAM(kernel, "file that contains the kernel code"), INIT_PARAM(console, "file that contains the console code"), @@ -139,7 +132,6 @@ CREATE_SIM_OBJECT(Tru64AlphaSystem) AlphaSystem::Params *p = new AlphaSystem::Params; p->name = getInstanceName(); p->boot_cpu_frequency = boot_cpu_frequency; - p->memctrl = memctrl; p->physmem = physmem; p->kernel_path = kernel; p->console_path = console; diff --git a/arch/alpha/tru64/tru64.cc b/arch/alpha/tru64/tru64.cc new file mode 100644 index 000000000..4a3e653c1 --- /dev/null +++ b/arch/alpha/tru64/tru64.cc @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2003-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. + */ + +#include "arch/alpha/tru64/tru64.hh" + +// open(2) flags translation table +OpenFlagTransTable AlphaTru64::openFlagTable[] = { +#ifdef _MSC_VER + { AlphaTru64::TGT_O_RDONLY, _O_RDONLY }, + { AlphaTru64::TGT_O_WRONLY, _O_WRONLY }, + { AlphaTru64::TGT_O_RDWR, _O_RDWR }, + { AlphaTru64::TGT_O_APPEND, _O_APPEND }, + { AlphaTru64::TGT_O_CREAT, _O_CREAT }, + { AlphaTru64::TGT_O_TRUNC, _O_TRUNC }, + { AlphaTru64::TGT_O_EXCL, _O_EXCL }, +#ifdef _O_NONBLOCK + { AlphaTru64::TGT_O_NONBLOCK, _O_NONBLOCK }, +#endif +#ifdef _O_NOCTTY + { AlphaTru64::TGT_O_NOCTTY, _O_NOCTTY }, +#endif +#ifdef _O_SYNC + { AlphaTru64::TGT_O_SYNC, _O_SYNC }, +#endif +#else /* !_MSC_VER */ + { AlphaTru64::TGT_O_RDONLY, O_RDONLY }, + { AlphaTru64::TGT_O_WRONLY, O_WRONLY }, + { AlphaTru64::TGT_O_RDWR, O_RDWR }, + { AlphaTru64::TGT_O_APPEND, O_APPEND }, + { AlphaTru64::TGT_O_CREAT, O_CREAT }, + { AlphaTru64::TGT_O_TRUNC, O_TRUNC }, + { AlphaTru64::TGT_O_EXCL, O_EXCL }, + { AlphaTru64::TGT_O_NONBLOCK, O_NONBLOCK }, + { AlphaTru64::TGT_O_NOCTTY, O_NOCTTY }, +#ifdef O_SYNC + { AlphaTru64::TGT_O_SYNC, O_SYNC }, +#endif +#endif /* _MSC_VER */ +}; + +const int AlphaTru64::NUM_OPEN_FLAGS = + (sizeof(AlphaTru64::openFlagTable)/sizeof(AlphaTru64::openFlagTable[0])); + + + diff --git a/arch/alpha/tru64/tru64.hh b/arch/alpha/tru64/tru64.hh new file mode 100644 index 000000000..19343ba23 --- /dev/null +++ b/arch/alpha/tru64/tru64.hh @@ -0,0 +1,127 @@ +/* + * Copyright (c) 2003-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. + */ + +#ifndef __ALPHA_ALPHA_TRU64_HH +#define __ALPHA_ALPHA_TRU64_HH + +#include "kern/tru64/tru64.hh" + +class AlphaTru64 : public Tru64 +{ + + public: + /// 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_NONBLOCK = 00000004; //!< O_NONBLOCK + static const int TGT_O_APPEND = 00000010; //!< O_APPEND + static const int TGT_O_CREAT = 00001000; //!< O_CREAT + static const int TGT_O_TRUNC = 00002000; //!< O_TRUNC + static const int TGT_O_EXCL = 00004000; //!< O_EXCL + static const int TGT_O_NOCTTY = 00010000; //!< O_NOCTTY + static const int TGT_O_SYNC = 00040000; //!< O_SYNC + static const int TGT_O_DRD = 00100000; //!< O_DRD + static const int TGT_O_DIRECTIO = 00200000; //!< O_DIRECTIO + static const int TGT_O_CACHE = 00400000; //!< O_CACHE + static const int TGT_O_DSYNC = 02000000; //!< O_DSYNC + static const int TGT_O_RSYNC = 04000000; //!< O_RSYNC + //@} + + /// For mmap(). + static const unsigned TGT_MAP_ANONYMOUS = 0x10; + + //@{ + /// For getsysinfo(). + static const unsigned GSI_PLATFORM_NAME = 103; //!< platform name as string + static const unsigned GSI_CPU_INFO = 59; //!< CPU information + static const unsigned GSI_PROC_TYPE = 60; //!< get proc_type + static const unsigned GSI_MAX_CPU = 30; //!< max # cpu's on this machine + static const unsigned GSI_CPUS_IN_BOX = 55; //!< number of CPUs in system + static const unsigned GSI_PHYSMEM = 19; //!< Physical memory in KB + static const unsigned GSI_CLK_TCK = 42; //!< clock freq in Hz + //@} + + //@{ + /// For getrusage(). + static const int TGT_RUSAGE_THREAD = 1; + static const int TGT_RUSAGE_SELF = 0; + static const int TGT_RUSAGE_CHILDREN = -1; + //@} + + //@{ + /// For setsysinfo(). + static const unsigned SSI_IEEE_FP_CONTROL = 14; //!< ieee_set_fp_control() + //@} + + //@{ + /// ioctl() command codes. + 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 = 0x40127417; + //@} + + //@{ + /// For table(). + static const int TBL_SYSINFO = 12; + //@} + + /// Resource enumeration for getrlimit(). + enum rlimit_resources { + TGT_RLIMIT_CPU = 0, + TGT_RLIMIT_FSIZE = 1, + TGT_RLIMIT_DATA = 2, + TGT_RLIMIT_STACK = 3, + TGT_RLIMIT_CORE = 4, + TGT_RLIMIT_RSS = 5, + TGT_RLIMIT_NOFILE = 6, + TGT_RLIMIT_AS = 7, + TGT_RLIMIT_VMEM = 7, + TGT_RLIMIT_NPROC = 8, + TGT_RLIMIT_MEMLOCK = 9, + TGT_RLIMIT_LOCKS = 10 + }; +}; + + + +#endif diff --git a/arch/alpha/types.hh b/arch/alpha/types.hh new file mode 100644 index 000000000..d4cb482d8 --- /dev/null +++ b/arch/alpha/types.hh @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2003-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. + */ + +#ifndef __ARCH_ALPHA_TYPES_HH__ +#define __ARCH_ALPHA_TYPES_HH__ + +#include "sim/host.hh" + +namespace AlphaISA +{ + + typedef uint32_t MachInst; + typedef uint64_t ExtMachInst; + typedef uint8_t RegIndex; + + typedef uint64_t IntReg; + + // floating point register file entry type + typedef double FloatReg; + typedef uint64_t FloatRegBits; + + // control register file contents + typedef uint64_t MiscReg; + + typedef union { + IntReg intreg; + FloatReg fpreg; + MiscReg ctrlreg; + } AnyReg; + + enum annotes { + ANNOTE_NONE = 0, + // An impossible number for instruction annotations + ITOUCH_ANNOTE = 0xffffffff, + }; + +} // namespace AlphaISA + +#endif diff --git a/arch/alpha/utility.hh b/arch/alpha/utility.hh new file mode 100644 index 000000000..6cc916307 --- /dev/null +++ b/arch/alpha/utility.hh @@ -0,0 +1,156 @@ +/* + * Copyright (c) 2003-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. + */ + +#ifndef __ARCH_ALPHA_UTILITY_HH__ +#define __ARCH_ALPHA_UTILITY_HH__ + +#include "config/full_system.hh" +#include "arch/alpha/types.hh" +#include "arch/alpha/constants.hh" +#include "arch/alpha/regfile.hh" +#include "base/misc.hh" + +namespace AlphaISA +{ + + static inline ExtMachInst + makeExtMI(MachInst inst, const uint64_t &pc) { +#if FULL_SYSTEM + ExtMachInst ext_inst = inst; + if (pc && 0x1) + return ext_inst|=(static_cast<ExtMachInst>(pc & 0x1) << 32); + else + return ext_inst; +#else + return ExtMachInst(inst); +#endif + } + + inline bool isCallerSaveIntegerRegister(unsigned int reg) { + panic("register classification not implemented"); + return (reg >= 1 && reg <= 8 || reg >= 22 && reg <= 25 || reg == 27); + } + + inline bool isCalleeSaveIntegerRegister(unsigned int reg) { + panic("register classification not implemented"); + return (reg >= 9 && reg <= 15); + } + + inline bool isCallerSaveFloatRegister(unsigned int reg) { + panic("register classification not implemented"); + return false; + } + + inline bool isCalleeSaveFloatRegister(unsigned int reg) { + panic("register classification not implemented"); + return false; + } + + inline Addr alignAddress(const Addr &addr, + unsigned int nbytes) { + return (addr & ~(nbytes - 1)); + } + + // Instruction address compression hooks + inline Addr realPCToFetchPC(const Addr &addr) { + return addr; + } + + inline Addr fetchPCToRealPC(const Addr &addr) { + return addr; + } + + // the size of "fetched" instructions (not necessarily the size + // of real instructions for PISA) + inline size_t fetchInstSize() { + return sizeof(MachInst); + } + + inline MachInst makeRegisterCopy(int dest, int src) { + panic("makeRegisterCopy not implemented"); + return 0; + } + + // Machine operations + + void saveMachineReg(AnyReg &savereg, const RegFile ®_file, + int regnum); + + void restoreMachineReg(RegFile ®s, const AnyReg ®, + int regnum); + + /** + * Function to insure ISA semantics about 0 registers. + * @param xc The execution context. + */ + template <class XC> + void zeroRegisters(XC *xc); + +#if FULL_SYSTEM + // Alpha IPR register accessors + inline bool PcPAL(Addr addr) { return addr & 0x1; } + + //////////////////////////////////////////////////////////////////////// + // + // Translation stuff + // + + inline Addr PteAddr(Addr a) { return (a & PteMask) << PteShift; } + + // User Virtual + inline bool IsUSeg(Addr a) { return USegBase <= a && a <= USegEnd; } + + // Kernel Direct Mapped + inline bool IsK0Seg(Addr a) { return K0SegBase <= a && a <= K0SegEnd; } + inline Addr K0Seg2Phys(Addr addr) { return addr & ~K0SegBase; } + + // Kernel Virtual + inline bool IsK1Seg(Addr a) { return K1SegBase <= a && a <= K1SegEnd; } + + inline Addr + TruncPage(Addr addr) + { return addr & ~(PageBytes - 1); } + + inline Addr + RoundPage(Addr addr) + { return (addr + PageBytes - 1) & ~(PageBytes - 1); } + + void initCPU(ExecContext *xc, int cpuId); + void initIPRs(ExecContext *xc, int cpuId); + + /** + * Function to check for and process any interrupts. + * @param xc The execution context. + */ + template <class XC> + void processInterrupts(XC *xc); +#endif + +} // namespace AlphaISA + +#endif diff --git a/arch/alpha/vtophys.cc b/arch/alpha/vtophys.cc index 40261426d..41e9b80a3 100644 --- a/arch/alpha/vtophys.cc +++ b/arch/alpha/vtophys.cc @@ -28,33 +28,35 @@ #include <string> +#include "arch/alpha/ev5.hh" #include "arch/alpha/vtophys.hh" +#include "base/chunk_generator.hh" #include "base/trace.hh" #include "cpu/exec_context.hh" -#include "mem/functional/physical.hh" +#include "mem/vport.hh" using namespace std; using namespace AlphaISA; AlphaISA::PageTableEntry -kernel_pte_lookup(PhysicalMemory *pmem, Addr ptbr, AlphaISA::VAddr vaddr) +AlphaISA::kernel_pte_lookup(FunctionalPort *mem, Addr ptbr, AlphaISA::VAddr vaddr) { Addr level1_pte = ptbr + vaddr.level1(); - AlphaISA::PageTableEntry level1 = pmem->phys_read_qword(level1_pte); + AlphaISA::PageTableEntry level1 = mem->read<uint64_t>(level1_pte); if (!level1.valid()) { DPRINTF(VtoPhys, "level 1 PTE not valid, va = %#\n", vaddr); return 0; } Addr level2_pte = level1.paddr() + vaddr.level2(); - AlphaISA::PageTableEntry level2 = pmem->phys_read_qword(level2_pte); + AlphaISA::PageTableEntry level2 = mem->read<uint64_t>(level2_pte); if (!level2.valid()) { DPRINTF(VtoPhys, "level 2 PTE not valid, va = %#x\n", vaddr); return 0; } Addr level3_pte = level2.paddr() + vaddr.level3(); - AlphaISA::PageTableEntry level3 = pmem->phys_read_qword(level3_pte); + AlphaISA::PageTableEntry level3 = mem->read<uint64_t>(level3_pte); if (!level3.valid()) { DPRINTF(VtoPhys, "level 3 PTE not valid, va = %#x\n", vaddr); return 0; @@ -63,7 +65,7 @@ kernel_pte_lookup(PhysicalMemory *pmem, Addr ptbr, AlphaISA::VAddr vaddr) } Addr -vtophys(PhysicalMemory *xc, Addr vaddr) +AlphaISA::vtophys(Addr vaddr) { Addr paddr = 0; if (AlphaISA::IsUSeg(vaddr)) @@ -79,7 +81,7 @@ vtophys(PhysicalMemory *xc, Addr vaddr) } Addr -vtophys(ExecContext *xc, Addr addr) +AlphaISA::vtophys(ExecContext *xc, Addr addr) { AlphaISA::VAddr vaddr = addr; Addr ptbr = xc->readMiscReg(AlphaISA::IPR_PALtemp20); @@ -95,7 +97,7 @@ vtophys(ExecContext *xc, Addr addr) paddr = vaddr; } else { AlphaISA::PageTableEntry pte = - kernel_pte_lookup(xc->getPhysMemPtr(), ptbr, vaddr); + kernel_pte_lookup(xc->getPhysPort(), ptbr, vaddr); if (pte.valid()) paddr = pte.paddr() | vaddr.offset(); } @@ -107,162 +109,54 @@ vtophys(ExecContext *xc, Addr addr) return paddr; } -uint8_t * -ptomem(ExecContext *xc, Addr paddr, size_t len) -{ - return xc->getPhysMemPtr()->dma_addr(paddr, len); -} - -uint8_t * -vtomem(ExecContext *xc, Addr vaddr, size_t len) -{ - Addr paddr = vtophys(xc, vaddr); - return xc->getPhysMemPtr()->dma_addr(paddr, len); -} void -CopyOut(ExecContext *xc, void *dest, Addr src, size_t cplen) +AlphaISA::CopyOut(ExecContext *xc, void *dest, Addr src, size_t cplen) { - Addr paddr; - char *dmaaddr; - char *dst = (char *)dest; - int len; + uint8_t *dst = (uint8_t *)dest; + VirtualPort *vp = xc->getVirtPort(xc); - paddr = vtophys(xc, src); - len = min((int)(AlphaISA::PageBytes - (paddr & AlphaISA::PageOffset)), - (int)cplen); - dmaaddr = (char *)xc->getPhysMemPtr()->dma_addr(paddr, len); - assert(dmaaddr); + vp->readBlob(src, dst, cplen); - memcpy(dst, dmaaddr, len); - if (len == cplen) - return; - - cplen -= len; - dst += len; - src += len; - - while (cplen > AlphaISA::PageBytes) { - paddr = vtophys(xc, src); - dmaaddr = (char *)xc->getPhysMemPtr()->dma_addr(paddr, - AlphaISA::PageBytes); - assert(dmaaddr); - - memcpy(dst, dmaaddr, AlphaISA::PageBytes); - cplen -= AlphaISA::PageBytes; - dst += AlphaISA::PageBytes; - src += AlphaISA::PageBytes; - } + xc->delVirtPort(vp); - if (cplen > 0) { - paddr = vtophys(xc, src); - dmaaddr = (char *)xc->getPhysMemPtr()->dma_addr(paddr, cplen); - assert(dmaaddr); - - memcpy(dst, dmaaddr, cplen); - } } void -CopyIn(ExecContext *xc, Addr dest, void *source, size_t cplen) +AlphaISA::CopyIn(ExecContext *xc, Addr dest, void *source, size_t cplen) { - Addr paddr; - char *dmaaddr; - char *src = (char *)source; - int len; - - paddr = vtophys(xc, dest); - len = min((int)(AlphaISA::PageBytes - (paddr & AlphaISA::PageOffset)), - (int)cplen); - dmaaddr = (char *)xc->getPhysMemPtr()->dma_addr(paddr, len); - assert(dmaaddr); - - memcpy(dmaaddr, src, len); - if (len == cplen) - return; - - cplen -= len; - src += len; - dest += len; - - while (cplen > AlphaISA::PageBytes) { - paddr = vtophys(xc, dest); - dmaaddr = (char *)xc->getPhysMemPtr()->dma_addr(paddr, - AlphaISA::PageBytes); - assert(dmaaddr); - - memcpy(dmaaddr, src, AlphaISA::PageBytes); - cplen -= AlphaISA::PageBytes; - src += AlphaISA::PageBytes; - dest += AlphaISA::PageBytes; - } + uint8_t *src = (uint8_t *)source; + VirtualPort *vp = xc->getVirtPort(xc); - if (cplen > 0) { - paddr = vtophys(xc, dest); - dmaaddr = (char *)xc->getPhysMemPtr()->dma_addr(paddr, cplen); - assert(dmaaddr); + vp->writeBlob(dest, src, cplen); - memcpy(dmaaddr, src, cplen); - } + xc->delVirtPort(vp); } void -CopyString(ExecContext *xc, char *dst, Addr vaddr, size_t maxlen) +AlphaISA::CopyStringOut(ExecContext *xc, char *dst, Addr vaddr, size_t maxlen) { - Addr paddr; - char *dmaaddr; - int len; - - paddr = vtophys(xc, vaddr); - len = min((int)(AlphaISA::PageBytes - (paddr & AlphaISA::PageOffset)), - (int)maxlen); - dmaaddr = (char *)xc->getPhysMemPtr()->dma_addr(paddr, len); - assert(dmaaddr); - - char *term = (char *)memchr(dmaaddr, 0, len); - if (term) - len = term - dmaaddr + 1; - - memcpy(dst, dmaaddr, len); - - if (term || len == maxlen) - return; - - maxlen -= len; - dst += len; - vaddr += len; - - while (maxlen > AlphaISA::PageBytes) { - paddr = vtophys(xc, vaddr); - dmaaddr = (char *)xc->getPhysMemPtr()->dma_addr(paddr, - AlphaISA::PageBytes); - assert(dmaaddr); - - char *term = (char *)memchr(dmaaddr, 0, AlphaISA::PageBytes); - len = term ? (term - dmaaddr + 1) : AlphaISA::PageBytes; + int len = 0; + VirtualPort *vp = xc->getVirtPort(xc); - memcpy(dst, dmaaddr, len); - if (term) - return; + do { + vp->readBlob(vaddr++, (uint8_t*)dst++, 1); + len++; + } while (len < maxlen && dst[len] != 0 ); - maxlen -= AlphaISA::PageBytes; - dst += AlphaISA::PageBytes; - vaddr += AlphaISA::PageBytes; - } - - if (maxlen > 0) { - paddr = vtophys(xc, vaddr); - dmaaddr = (char *)xc->getPhysMemPtr()->dma_addr(paddr, maxlen); - assert(dmaaddr); - - char *term = (char *)memchr(dmaaddr, 0, maxlen); - len = term ? (term - dmaaddr + 1) : maxlen; - - memcpy(dst, dmaaddr, len); + xc->delVirtPort(vp); + dst[len] = 0; +} - maxlen -= len; +void +AlphaISA::CopyStringIn(ExecContext *xc, char *src, Addr vaddr) +{ + VirtualPort *vp = xc->getVirtPort(xc); + for (ChunkGenerator gen(vaddr, strlen(src), AlphaISA::PageBytes); !gen.done(); + gen.next()) + { + vp->writeBlob(gen.addr(), (uint8_t*)src, gen.size()); + src += gen.size(); } - - if (maxlen == 0) - dst[maxlen] = '\0'; + xc->delVirtPort(vp); } diff --git a/arch/alpha/vtophys.hh b/arch/alpha/vtophys.hh index 95430ce77..7ab14bc5b 100644 --- a/arch/alpha/vtophys.hh +++ b/arch/alpha/vtophys.hh @@ -32,19 +32,21 @@ #include "arch/alpha/isa_traits.hh" class ExecContext; -class PhysicalMemory; +class FunctionalPort; -AlphaISA::PageTableEntry -kernel_pte_lookup(PhysicalMemory *pmem, Addr ptbr, AlphaISA::VAddr vaddr); +namespace AlphaISA { -Addr vtophys(PhysicalMemory *xc, Addr vaddr); +PageTableEntry +kernel_pte_lookup(FunctionalPort *mem, Addr ptbr, AlphaISA::VAddr vaddr); + +Addr vtophys(Addr vaddr); Addr vtophys(ExecContext *xc, Addr vaddr); -uint8_t *vtomem(ExecContext *xc, Addr vaddr, size_t len); -uint8_t *ptomem(ExecContext *xc, Addr paddr, size_t len); void CopyOut(ExecContext *xc, void *dst, Addr src, size_t len); void CopyIn(ExecContext *xc, Addr dst, void *src, size_t len); -void CopyString(ExecContext *xc, char *dst, Addr vaddr, size_t maxlen); +void CopyStringOut(ExecContext *xc, char *dst, Addr vaddr, size_t maxlen); +void CopyStringIn(ExecContext *xc, char *src, Addr vaddr); +}; #endif // __ARCH_ALPHA_VTOPHYS_H__ diff --git a/arch/isa_parser.py b/arch/isa_parser.py index 570110d84..a92c85c3f 100755 --- a/arch/isa_parser.py +++ b/arch/isa_parser.py @@ -1,5 +1,3 @@ -#! /usr/bin/env python - # Copyright (c) 2003-2005 The Regents of The University of Michigan # All rights reserved. # @@ -162,13 +160,12 @@ def t_CPPDIRECTIVE(t): def t_NEWFILE(t): r'^\#\#newfile\s+"[\w/.-]*"' - global fileNameStack - fileNameStack.append((t.value[11:-1], t.lineno)) + fileNameStack.push((t.value[11:-1], t.lineno)) t.lineno = 0 def t_ENDFILE(t): r'^\#\#endfile' - (filename, t.lineno) = fileNameStack.pop() + (old_filename, t.lineno) = fileNameStack.pop() # # The functions t_NEWLINE, t_ignore, and t_error are @@ -698,7 +695,7 @@ def p_error(t): if t: error(t.lineno, "syntax error at '%s'" % t.value) else: - error_bt(0, "unknown syntax error") + error(0, "unknown syntax error", True) # END OF GRAMMAR RULES # @@ -896,6 +893,12 @@ formatStack = Stack(NoFormat()) # The global default case stack. defaultStack = Stack( None ) +# Global stack that tracks current file and line number. +# Each element is a tuple (filename, lineno) that records the +# *current* filename and the line number in the *previous* file where +# it was included. +fileNameStack = Stack() + ################### # Utility functions @@ -932,25 +935,22 @@ def fixPythonIndentation(s): return s # Error handler. Just call exit. Output formatted to work under -# Emacs compile-mode. This function should be called when errors due -# to user input are detected (as opposed to parser bugs). -def error(lineno, string): +# Emacs compile-mode. Optional 'print_traceback' arg, if set to True, +# prints a Python stack backtrace too (can be handy when trying to +# debug the parser itself). +def error(lineno, string, print_traceback = False): spaces = "" for (filename, line) in fileNameStack[0:-1]: - print spaces + "In file included from " + filename + print spaces + "In file included from " + filename + ":" spaces += " " - # Uncomment the following line to get a Python stack backtrace for - # these errors too. Can be handy when trying to debug the parser. - # traceback.print_exc() - sys.exit(spaces + "%s:%d: %s" % (fileNameStack[-1][0], lineno, string)) - -# Like error(), but include a Python stack backtrace (for processing -# Python exceptions). This function should be called for errors that -# appear to be bugs in the parser itself. -def error_bt(lineno, string): - traceback.print_exc() - print >> sys.stderr, "%s:%d: %s" % (input_filename, lineno, string) - sys.exit(1) + # Print a Python stack backtrace if requested. + if (print_traceback): + traceback.print_exc() + if lineno != 0: + line_str = "%d:" % lineno + else: + line_str = "" + sys.exit(spaces + "%s:%s %s" % (fileNameStack[-1][0], line_str, string)) ##################################################################### @@ -1070,7 +1070,7 @@ def buildOperandTypeMap(userDict, lineno): elif size == 64: ctype = 'double' if ctype == '': - error(0, 'Unrecognized type description "%s" in userDict') + error(lineno, 'Unrecognized type description "%s" in userDict') operandTypeMap[ext] = (size, ctype, is_signed) # @@ -1217,16 +1217,27 @@ class FloatRegOperand(Operand): def makeRead(self): bit_select = 0 + width = 0; if (self.ctype == 'float'): - func = 'readFloatRegSingle' + func = 'readFloatReg' + width = 32; elif (self.ctype == 'double'): - func = 'readFloatRegDouble' + func = 'readFloatReg' + width = 64; else: - func = 'readFloatRegInt' + func = 'readFloatRegBits' + if (self.ctype == 'uint32_t'): + width = 32; + elif (self.ctype == 'uint64_t'): + width = 64; if (self.size != self.dflt_size): bit_select = 1 - base = 'xc->%s(this, %d)' % \ - (func, self.src_reg_idx) + if width: + base = 'xc->%s(this, %d, %d)' % \ + (func, self.src_reg_idx, width) + else: + base = 'xc->%s(this, %d)' % \ + (func, self.src_reg_idx) if bit_select: return '%s = bits(%s, %d, 0);\n' % \ (self.base_name, base, self.size-1) @@ -1236,21 +1247,34 @@ class FloatRegOperand(Operand): def makeWrite(self): final_val = self.base_name final_ctype = self.ctype + widthSpecifier = '' + width = 0 if (self.ctype == 'float'): - func = 'setFloatRegSingle' + width = 32 + func = 'setFloatReg' elif (self.ctype == 'double'): - func = 'setFloatRegDouble' + width = 64 + func = 'setFloatReg' + elif (self.ctype == 'uint32_t'): + func = 'setFloatRegBits' + width = 32 + elif (self.ctype == 'uint64_t'): + func = 'setFloatRegBits' + width = 64 else: - func = 'setFloatRegInt' + func = 'setFloatRegBits' final_ctype = 'uint%d_t' % self.dflt_size if (self.size != self.dflt_size and self.is_signed): final_val = 'sext<%d>(%s)' % (self.size, self.base_name) + if width: + widthSpecifier = ', %d' % width wb = ''' { %s final_val = %s; - xc->%s(this, %d, final_val);\n + xc->%s(this, %d, final_val%s);\n if (traceData) { traceData->setData(final_val); } - }''' % (final_ctype, final_val, func, self.dest_reg_idx) + }''' % (final_ctype, final_val, func, self.dest_reg_idx, + widthSpecifier) return wb class ControlRegOperand(Operand): @@ -1320,7 +1344,7 @@ class NPCOperand(Operand): return '' def makeRead(self): - return '%s = xc->readPC() + 4;\n' % self.base_name + return '%s = xc->readNextPC();\n' % self.base_name def makeWrite(self): return 'xc->setNextPC(%s);\n' % self.base_name @@ -1330,7 +1354,7 @@ class NNPCOperand(Operand): return '' def makeRead(self): - return '%s = xc->readPC() + 8;\n' % self.base_name + return '%s = xc->readNextNPC();\n' % self.base_name def makeWrite(self): return 'xc->setNextNPC(%s);\n' % self.base_name @@ -1604,13 +1628,27 @@ opClassRE = re.compile(r'.*Op|No_OpClass') class InstObjParams: def __init__(self, mnem, class_name, base_class = '', - code_block = None, opt_args = []): + code = None, opt_args = [], *extras): self.mnemonic = mnem self.class_name = class_name self.base_class = base_class - if code_block: - for code_attr in code_block.__dict__.keys(): - setattr(self, code_attr, getattr(code_block, code_attr)) + if code: + #If the user already made a CodeBlock, pick the parts from it + if isinstance(code, CodeBlock): + origCode = code.orig_code + codeBlock = code + else: + origCode = code + codeBlock = CodeBlock(code) + compositeCode = '\n'.join([origCode] + + [pair[1] for pair in extras]) + compositeBlock = CodeBlock(compositeCode) + for code_attr in compositeBlock.__dict__.keys(): + setattr(self, code_attr, getattr(compositeBlock, code_attr)) + for (key, snippet) in extras: + setattr(self, key, CodeBlock(snippet).code) + self.code = codeBlock.code + self.orig_code = origCode else: self.constructor = '' self.flags = [] @@ -1687,47 +1725,47 @@ def update_if_needed(file, contents): f.write(contents) f.close() -# This regular expression matches include directives +# This regular expression matches '##include' directives includeRE = re.compile(r'^\s*##include\s+"(?P<filename>[\w/.-]*)".*$', re.MULTILINE) -def preprocess_isa_desc(isa_desc): +# Function to replace a matched '##include' directive with the +# contents of the specified file (with nested ##includes replaced +# recursively). 'matchobj' is an re match object (from a match of +# includeRE) and 'dirname' is the directory relative to which the file +# path should be resolved. +def replace_include(matchobj, dirname): + fname = matchobj.group('filename') + full_fname = os.path.normpath(os.path.join(dirname, fname)) + contents = '##newfile "%s"\n%s\n##endfile\n' % \ + (full_fname, read_and_flatten(full_fname)) + return contents + +# Read a file and recursively flatten nested '##include' files. +def read_and_flatten(filename): + current_dir = os.path.dirname(filename) + try: + contents = open(filename).read() + except IOError: + error(0, 'Error including file "%s"' % filename) + fileNameStack.push((filename, 0)) # Find any includes and include them - pos = 0 - while 1: - m = includeRE.search(isa_desc, pos) - if not m: - break - filename = m.group('filename') - print 'Including file "%s"' % filename - try: - isa_desc = isa_desc[:m.start()] + \ - '##newfile "' + filename + '"\n' + \ - open(filename).read() + \ - '##endfile\n' + \ - isa_desc[m.end():] - except IOError: - error(0, 'Error including file "%s"' % (filename)) - pos = m.start() - return isa_desc + contents = includeRE.sub(lambda m: replace_include(m, current_dir), + contents) + fileNameStack.pop() + return contents # # Read in and parse the ISA description. # def parse_isa_desc(isa_desc_file, output_dir): - # set a global var for the input filename... used in error messages - global input_filename - input_filename = isa_desc_file - global fileNameStack - fileNameStack = [(input_filename, 1)] - - # Suck the ISA description file in. - input = open(isa_desc_file) - isa_desc = input.read() - input.close() - - # Perform Preprocessing - isa_desc = preprocess_isa_desc(isa_desc) + # Read file and (recursively) all included files into a string. + # PLY requires that the input be in a single string so we have to + # do this up front. + isa_desc = read_and_flatten(isa_desc_file) + + # Initialize filename stack with outer file. + fileNameStack.push((isa_desc_file, 0)) # Parse it. (isa_name, namespace, global_code, namespace_code) = yacc.parse(isa_desc) diff --git a/arch/isa_specific.hh b/arch/isa_specific.hh index 44f8e9d64..91c9ffb68 100644 --- a/arch/isa_specific.hh +++ b/arch/isa_specific.hh @@ -45,7 +45,7 @@ //would treat them as 0 in comparisons. #define ALPHA_ISA 21064 #define SPARC_ISA 42 -#define MIPS_ISA 1337 +#define MIPS_ISA 34000 //These tell the preprocessor where to find the files of a particular //ISA, and set the "TheISA" macro for use elsewhere. diff --git a/arch/mips/SConscript b/arch/mips/SConscript index b8efa7ef9..ef1ef25d6 100644 --- a/arch/mips/SConscript +++ b/arch/mips/SConscript @@ -57,9 +57,9 @@ full_system_sources = Split(''' # Syscall emulation (non-full-system) sources syscall_emulation_sources = Split(''' - common_syscall_emul.cc - linux_process.cc - tru64_process.cc + linux/linux.cc + linux/process.cc + process.cc ''') # Set up complete list of sources based on configuration. diff --git a/arch/mips/faults.cc b/arch/mips/faults.cc index 142dfe0a4..a31856f07 100644 --- a/arch/mips/faults.cc +++ b/arch/mips/faults.cc @@ -27,54 +27,115 @@ */ #include "arch/mips/faults.hh" +#include "cpu/exec_context.hh" +#include "cpu/base.hh" +#include "base/trace.hh" + +namespace MipsISA +{ + +FaultName MachineCheckFault::_name = "Machine Check"; +FaultVect MachineCheckFault::_vect = 0x0401; +FaultStat MachineCheckFault::_count; + +FaultName AlignmentFault::_name = "Alignment"; +FaultVect AlignmentFault::_vect = 0x0301; +FaultStat AlignmentFault::_count; + +FaultName ResetFault::_name = "reset"; +FaultVect ResetFault::_vect = 0x0001; +FaultStat ResetFault::_count; + +FaultName ArithmeticFault::_name = "arith"; +FaultVect ArithmeticFault::_vect = 0x0501; +FaultStat ArithmeticFault::_count; + +FaultName InterruptFault::_name = "interrupt"; +FaultVect InterruptFault::_vect = 0x0101; +FaultStat InterruptFault::_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 ItbMissFault::_name = "itbmiss"; +FaultVect ItbMissFault::_vect = 0x0181; +FaultStat ItbMissFault::_count; + +FaultName ItbPageFault::_name = "itbmiss"; +FaultVect ItbPageFault::_vect = 0x0181; +FaultStat ItbPageFault::_count; + +FaultName ItbAcvFault::_name = "iaccvio"; +FaultVect ItbAcvFault::_vect = 0x0081; +FaultStat ItbAcvFault::_count; + +FaultName UnimplementedOpcodeFault::_name = "opdec"; +FaultVect UnimplementedOpcodeFault::_vect = 0x0481; +FaultStat UnimplementedOpcodeFault::_count; + +FaultName FloatEnableFault::_name = "fen"; +FaultVect FloatEnableFault::_vect = 0x0581; +FaultStat FloatEnableFault::_count; + +FaultName PalFault::_name = "pal"; +FaultVect PalFault::_vect = 0x2001; +FaultStat PalFault::_count; + +FaultName IntegerOverflowFault::_name = "intover"; +FaultVect IntegerOverflowFault::_vect = 0x0501; +FaultStat IntegerOverflowFault::_count; + +FaultName UnimpFault::_name = "Unimplemented Simulator feature"; +FaultVect UnimpFault::_vect = 0x0001; +FaultStat UnimpFault::_count; + +#if FULL_SYSTEM + +void MipsFault::invoke(ExecContext * xc) +{ + FaultBase::invoke(xc); + countStat()++; + + // exception restart address + if (setRestartAddress() || !xc->inPalMode()) + xc->setMiscReg(MipsISA::IPR_EXC_ADDR, xc->readPC()); + + if (skipFaultingInstruction()) { + // traps... skip faulting instruction. + xc->setMiscReg(MipsISA::IPR_EXC_ADDR, + xc->readMiscReg(MipsISA::IPR_EXC_ADDR) + 4); + } + + xc->setPC(xc->readMiscReg(MipsISA::IPR_PAL_BASE) + vect()); + xc->setNextPC(xc->readPC() + sizeof(MachInst)); +} + +void ArithmeticFault::invoke(ExecContext * xc) +{ + FaultBase::invoke(xc); + panic("Arithmetic traps are unimplemented!"); +} + +void UnimpFault::invoke(ExecContext * xc) +{ + FaultBase::invoke(xc); + panic("Unimpfault: %s\n", panicStr.c_str()); +} + +#endif + +} // namespace MipsISA -ResetFaultType * const ResetFault = - new ResetFaultType("reset", 1, 0x0001); -ArithmeticFaultType * const ArithmeticFault = - new ArithmeticFaultType("arith", 3, 0x0501); -InterruptFaultType * const InterruptFault = - new InterruptFaultType("interrupt", 4, 0x0101); -NDtbMissFaultType * const NDtbMissFault = - new NDtbMissFaultType("dtb_miss_single", 5, 0x0201); -PDtbMissFaultType * const PDtbMissFault = - new PDtbMissFaultType("dtb_miss_double", 6, 0x0281); -DtbPageFaultType * const DtbPageFault = - new DtbPageFaultType("dfault", 8, 0x0381); -DtbAcvFaultType * const DtbAcvFault = - new DtbAcvFaultType("dfault", 9, 0x0381); -ItbMissFaultType * const ItbMissFault = - new ItbMissFaultType("itbmiss", 10, 0x0181); -ItbPageFaultType * const ItbPageFault = - new ItbPageFaultType("itbmiss", 11, 0x0181); -ItbAcvFaultType * const ItbAcvFault = - new ItbAcvFaultType("iaccvio", 12, 0x0081); -UnimplementedOpcodeFaultType * const UnimplementedOpcodeFault = - new UnimplementedOpcodeFaultType("opdec", 13, 0x0481); -FloatEnableFaultType * const FloatEnableFault = - new FloatEnableFaultType("fen", 14, 0x0581); -PalFaultType * const PalFault = - new PalFaultType("pal", 15, 0x2001); -IntegerOverflowFaultType * const IntegerOverflowFault = - new IntegerOverflowFaultType("intover", 16, 0x0501); - -Fault ** ListOfFaults[] = { - (Fault **)&NoFault, - (Fault **)&ResetFault, - (Fault **)&MachineCheckFault, - (Fault **)&ArithmeticFault, - (Fault **)&InterruptFault, - (Fault **)&NDtbMissFault, - (Fault **)&PDtbMissFault, - (Fault **)&AlignmentFault, - (Fault **)&DtbPageFault, - (Fault **)&DtbAcvFault, - (Fault **)&ItbMissFault, - (Fault **)&ItbPageFault, - (Fault **)&ItbAcvFault, - (Fault **)&UnimplementedOpcodeFault, - (Fault **)&FloatEnableFault, - (Fault **)&PalFault, - (Fault **)&IntegerOverflowFault, - }; - -int NumFaults = sizeof(ListOfFaults) / sizeof(Fault **); diff --git a/arch/mips/faults.hh b/arch/mips/faults.hh index c1cb956b0..b0d228090 100644 --- a/arch/mips/faults.hh +++ b/arch/mips/faults.hh @@ -30,131 +30,260 @@ #define __MIPS_FAULTS_HH__ #include "sim/faults.hh" -#include "arch/isa_traits.hh" //For the Addr type + +// The design of the "name" and "vect" functions is in sim/faults.hh + +namespace MipsISA +{ + +typedef const Addr FaultVect; class MipsFault : public FaultBase { + protected: + virtual bool skipFaultingInstruction() {return false;} + virtual bool setRestartAddress() {return true;} public: - MipsFault(char * newName, int newId, Addr newVect) - : FaultBase(newName, newId), vect(newVect) - {;} +#if FULL_SYSTEM + void invoke(ExecContext * xc); +#endif + virtual FaultVect vect() = 0; + virtual FaultStat & countStat() = 0; +}; + +class MachineCheckFault : public MipsFault +{ + private: + static FaultName _name; + static FaultVect _vect; + static FaultStat _count; + public: + FaultName name() {return _name;} + FaultVect vect() {return _vect;} + FaultStat & countStat() {return _count;} + bool isMachineCheckFault() {return true;} +}; + +class AlignmentFault : public MipsFault +{ + private: + static FaultName _name; + static FaultVect _vect; + static FaultStat _count; + public: + FaultName name() {return _name;} + FaultVect vect() {return _vect;} + FaultStat & countStat() {return _count;} + bool isAlignmentFault() {return true;} +}; + +static inline Fault genMachineCheckFault() +{ + return new MachineCheckFault; +} + +static inline Fault genAlignmentFault() +{ + return new AlignmentFault; +} - Addr vect; +class ResetFault : public MipsFault +{ + private: + static FaultName _name; + static FaultVect _vect; + static FaultStat _count; + public: + FaultName name() {return _name;} + FaultVect vect() {return _vect;} + FaultStat & countStat() {return _count;} }; -extern class ResetFaultType : public MipsFault +class ArithmeticFault : public MipsFault { + protected: + bool skipFaultingInstruction() {return true;} + private: + static FaultName _name; + static FaultVect _vect; + static FaultStat _count; public: - ResetFaultType(char * newName, int newId, Addr newVect) - : MipsFault(newName, newId, newVect) - {;} -} * const ResetFault; + FaultName name() {return _name;} + FaultVect vect() {return _vect;} + FaultStat & countStat() {return _count;} +#if FULL_SYSTEM + void invoke(ExecContext * xc); +#endif +}; -extern class ArithmeticFaultType : public MipsFault +class InterruptFault : public MipsFault { + protected: + bool setRestartAddress() {return false;} + private: + static FaultName _name; + static FaultVect _vect; + static FaultStat _count; public: - ArithmeticFaultType(char * newName, int newId, Addr newVect) - : MipsFault(newName, newId, newVect) - {;} -} * const ArithmeticFault; + FaultName name() {return _name;} + FaultVect vect() {return _vect;} + FaultStat & countStat() {return _count;} +}; -extern class InterruptFaultType : public MipsFault +class NDtbMissFault : public MipsFault { + private: + static FaultName _name; + static FaultVect _vect; + static FaultStat _count; public: - InterruptFaultType(char * newName, int newId, Addr newVect) - : MipsFault(newName, newId, newVect) - {;} -} * const InterruptFault; + FaultName name() {return _name;} + FaultVect vect() {return _vect;} + FaultStat & countStat() {return _count;} +}; -extern class NDtbMissFaultType : public MipsFault +class PDtbMissFault : public MipsFault { + private: + static FaultName _name; + static FaultVect _vect; + static FaultStat _count; public: - NDtbMissFaultType(char * newName, int newId, Addr newVect) - : MipsFault(newName, newId, newVect) - {;} -} * const NDtbMissFault; + FaultName name() {return _name;} + FaultVect vect() {return _vect;} + FaultStat & countStat() {return _count;} +}; -extern class PDtbMissFaultType : public MipsFault +class DtbPageFault : public MipsFault { + private: + static FaultName _name; + static FaultVect _vect; + static FaultStat _count; public: - PDtbMissFaultType(char * newName, int newId, Addr newVect) - : MipsFault(newName, newId, newVect) - {;} -} * const PDtbMissFault; + FaultName name() {return _name;} + FaultVect vect() {return _vect;} + FaultStat & countStat() {return _count;} +}; -extern class DtbPageFaultType : public MipsFault +class DtbAcvFault : public MipsFault { + private: + static FaultName _name; + static FaultVect _vect; + static FaultStat _count; public: - DtbPageFaultType(char * newName, int newId, Addr newVect) - : MipsFault(newName, newId, newVect) - {;} -} * const DtbPageFault; + FaultName name() {return _name;} + FaultVect vect() {return _vect;} + FaultStat & countStat() {return _count;} +}; -extern class DtbAcvFaultType : public MipsFault +class ItbMissFault : public MipsFault { + private: + static FaultName _name; + static FaultVect _vect; + static FaultStat _count; public: - DtbAcvFaultType(char * newName, int newId, Addr newVect) - : MipsFault(newName, newId, newVect) - {;} -} * const DtbAcvFault; + FaultName name() {return _name;} + FaultVect vect() {return _vect;} + FaultStat & countStat() {return _count;} +}; -extern class ItbMissFaultType : public MipsFault +class ItbPageFault : public MipsFault { + private: + static FaultName _name; + static FaultVect _vect; + static FaultStat _count; public: - ItbMissFaultType(char * newName, int newId, Addr newVect) - : MipsFault(newName, newId, newVect) - {;} -} * const ItbMissFault; + FaultName name() {return _name;} + FaultVect vect() {return _vect;} + FaultStat & countStat() {return _count;} +}; -extern class ItbPageFaultType : public MipsFault +class ItbAcvFault : public MipsFault { + private: + static FaultName _name; + static FaultVect _vect; + static FaultStat _count; public: - ItbPageFaultType(char * newName, int newId, Addr newVect) - : MipsFault(newName, newId, newVect) - {;} -} * const ItbPageFault; + FaultName name() {return _name;} + FaultVect vect() {return _vect;} + FaultStat & countStat() {return _count;} +}; -extern class ItbAcvFaultType : public MipsFault +class UnimplementedOpcodeFault : public MipsFault { + private: + static FaultName _name; + static FaultVect _vect; + static FaultStat _count; public: - ItbAcvFaultType(char * newName, int newId, Addr newVect) - : MipsFault(newName, newId, newVect) - {;} -} * const ItbAcvFault; + FaultName name() {return _name;} + FaultVect vect() {return _vect;} + FaultStat & countStat() {return _count;} +}; -extern class UnimplementedOpcodeFaultType : public MipsFault +class FloatEnableFault : public MipsFault { + private: + static FaultName _name; + static FaultVect _vect; + static FaultStat _count; public: - UnimplementedOpcodeFaultType(char * newName, int newId, Addr newVect) - : MipsFault(newName, newId, newVect) - {;} -} * const UnimplementedOpcodeFault; + FaultName name() {return _name;} + FaultVect vect() {return _vect;} + FaultStat & countStat() {return _count;} +}; -extern class FloatEnableFaultType : public MipsFault +class PalFault : public MipsFault { + protected: + bool skipFaultingInstruction() {return true;} + private: + static FaultName _name; + static FaultVect _vect; + static FaultStat _count; public: - FloatEnableFaultType(char * newName, int newId, Addr newVect) - : MipsFault(newName, newId, newVect) - {;} -} * const FloatEnableFault; + FaultName name() {return _name;} + FaultVect vect() {return _vect;} + FaultStat & countStat() {return _count;} +}; -extern class PalFaultType : public MipsFault +class IntegerOverflowFault : public MipsFault { + private: + static FaultName _name; + static FaultVect _vect; + static FaultStat _count; public: - PalFaultType(char * newName, int newId, Addr newVect) - : MipsFault(newName, newId, newVect) - {;} -} * const PalFault; + FaultName name() {return _name;} + FaultVect vect() {return _vect;} + FaultStat & countStat() {return _count;} +}; -extern class IntegerOverflowFaultType : public MipsFault +class UnimpFault : public MipsFault { + private: + std::string panicStr; + static FaultName _name; + static FaultVect _vect; + static FaultStat _count; public: - IntegerOverflowFaultType(char * newName, int newId, Addr newVect) - : MipsFault(newName, newId, newVect) - {;} -} * const IntegerOverflowFault; + UnimpFault(std::string _str) + : panicStr(_str) + { } + + FaultName name() {return _name;} + FaultVect vect() {return _vect;} + FaultStat & countStat() {return _count;} +#if FULL_SYSTEM + void invoke(ExecContext * xc); +#endif +}; -extern Fault ** ListOfFaults[]; -extern int NumFaults; +} // MipsISA namespace #endif // __FAULTS_HH__ diff --git a/arch/mips/isa/base.isa b/arch/mips/isa/base.isa index 4125b5101..b2a31c018 100644 --- a/arch/mips/isa/base.isa +++ b/arch/mips/isa/base.isa @@ -8,10 +8,6 @@ //Outputs to decoder.hh output header {{ -#define R31 31 -#include "arch/mips/faults.hh" -#include "arch/mips/isa_traits.hh" - using namespace MipsISA; @@ -66,27 +62,23 @@ output decoder {{ ccprintf(ss, "%-10s ", mnemonic); - // just print the first two source regs... if there's - // a third one, it's a read-modify-write dest (Rc), - // e.g. for CMOVxx - if(_numSrcRegs > 0) - { + if(_numDestRegs > 0){ + printReg(ss, _destRegIdx[0]); + } + + if(_numSrcRegs > 0) { + ss << ","; printReg(ss, _srcRegIdx[0]); } - if(_numSrcRegs > 1) - { + if(_numSrcRegs > 1) { ss << ","; printReg(ss, _srcRegIdx[1]); } - // just print the first dest... if there's a second one, - // it's generally implicit - if(_numDestRegs > 0) - { - if(_numSrcRegs > 0) - ss << ","; - printReg(ss, _destRegIdx[0]); + + if(mnemonic == "sll" || mnemonic == "sra"){ + ccprintf(ss,", %d",SA); } return ss.str(); diff --git a/arch/mips/isa/bitfields.isa b/arch/mips/isa/bitfields.isa index 58d487ad2..e1124a591 100644 --- a/arch/mips/isa/bitfields.isa +++ b/arch/mips/isa/bitfields.isa @@ -26,6 +26,7 @@ def bitfield RS <25:21>; def bitfield RS_MSB <25:25>; def bitfield RS_HI <25:24>; def bitfield RS_LO <23:21>; +def bitfield RS_SRL <25:22>; def bitfield RD <15:11>; @@ -38,7 +39,6 @@ def bitfield FT <20:16>; def bitfield FS <15:11>; def bitfield FD <10:6>; -def bitfield CC <20:18>; def bitfield ND <17:17>; def bitfield TF <16:16>; def bitfield MOVCI <16:16>; @@ -47,6 +47,10 @@ def bitfield SRL <21:21>; def bitfield SRLV < 6: 6>; def bitfield SA <10: 6>; +// Floating Point Condition Codes +def bitfield CC <10:8>; +def bitfield BRANCH_CC <20:18>; + // CP0 Register Select def bitfield SEL < 2: 0>; diff --git a/arch/mips/isa/decoder.isa b/arch/mips/isa/decoder.isa index 3f054f6a5..1454aba39 100644 --- a/arch/mips/isa/decoder.isa +++ b/arch/mips/isa/decoder.isa @@ -1,4 +1,4 @@ -// -*- mode:c++ -*- + // -*- mode:c++ -*- //////////////////////////////////////////////////////////////////// // @@ -20,36 +20,53 @@ decode OPCODE_HI default Unknown::unknown() { 0x0: decode FUNCTION_LO { 0x1: decode MOVCI { format BasicOp { - 0: movf({{ if (xc->readMiscReg(FPCR,0) != CC) Rd = Rs}}); - 1: movt({{ if (xc->readMiscReg(FPCR,0) == CC) Rd = Rs}}); + 0: movf({{ if (getFPConditionCode(FCSR, CC) == 0) Rd = Rs}}); + 1: movt({{ if (getFPConditionCode(FCSR, CC) == 1) Rd = Rs}}); } } format BasicOp { //Table A-3 Note: "1. Specific encodings of the rt, rd, and sa fields - //are used to distinguish among the SLL, NOP, SSNOP and EHB functions." - - 0x0: decode RS { - 0x0: decode RT default BasicOp::sll({{ Rd = Rt.uw << SA; }}) { - 0x0: decode RD{ - 0x0: decode HINT { - 0x0:nop({{}}); //really sll r0,r0,0 - 0x1:ssnop({{}});//really sll r0,r0,1 - 0x3:ehb({{}}); //really sll r0,r0,3 - } - } + //are used to distinguish among the SLL, NOP, SSNOP and EHB functions. + 0x0: decode RS { + 0x0: decode RT { //fix Nop traditional vs. Nop converted disassembly later + 0x0: decode RD default Nop::nop(){ + 0x0: decode SA { + 0x1: ssnop({{ ; }}); //really sll r0,r0,1 + 0x3: ehb({{ ; }}); //really sll r0,r0,3 + } + } + + default: sll({{ Rd = Rt.uw << SA; }}); } + } - 0x2: decode SRL { - 0: srl({{ Rd = Rt.uw >> SA; }}); + 0x2: decode RS_SRL { + 0x0:decode SRL { + 0: srl({{ Rd = Rt.uw >> SA; }}); - //Hardcoded assuming 32-bit ISA, probably need parameter here - 1: rotr({{ Rd = (Rt.uw << (32 - SA)) | (Rt.uw >> SA);}}); + //Hardcoded assuming 32-bit ISA, probably need parameter here + 1: rotr({{ Rd = (Rt.uw << (32 - SA)) | (Rt.uw >> SA);}}); + } } - 0x3: sra({{ Rd = Rt.sw >> SA; }}); + 0x3: decode RS { + 0x0: sra({{ + uint32_t temp = Rt >> SA; + + if ( (Rt & 0x80000000) > 0 ) { + uint32_t mask = 0x80000000; + for(int i=0; i < SA; i++) { + temp |= mask; + mask = mask >> 1; + } + } + + Rd = temp; + }}); + } 0x4: sllv({{ Rd = Rt.uw << Rs<4:0>; }}); @@ -60,7 +77,21 @@ decode OPCODE_HI default Unknown::unknown() { 1: rotrv({{ Rd = (Rt.uw << (32 - Rs<4:0>)) | (Rt.uw >> Rs<4:0>);}}); } - 0x7: srav({{ Rd = Rt.sw >> Rs<4:0>; }}); + 0x7: srav({{ + int shift_amt = Rs<4:0>; + + uint32_t temp = Rt >> shift_amt; + + if ( (Rt & 0x80000000) > 0 ) { + uint32_t mask = 0x80000000; + for(int i=0; i < shift_amt; i++) { + temp |= mask; + mask = mask >> 1; + } + } + + Rd = temp; + }}); } } @@ -76,9 +107,9 @@ decode OPCODE_HI default Unknown::unknown() { } 0x1: decode HINT { - 0: jalr({{ NNPC = Rs; }},IsCall,IsReturn); + 0: jalr({{ Rd = NNPC; NNPC = Rs; }},IsCall,IsReturn); - 1: jalr_hb({{ NNPC = Rs; clear_exe_inst_hazards();}},IsCall,IsReturn); + 1: jalr_hb({{ Rd = NNPC; NNPC = Rs; clear_exe_inst_hazards();}},IsCall,IsReturn); } } @@ -87,65 +118,69 @@ decode OPCODE_HI default Unknown::unknown() { 0x3: movn({{ if (Rt != 0) Rd = Rs; }}); } - format WarnUnimpl { - 0x4: syscall();//{{ xc->syscall()}},IsNonSpeculative - 0x5: break(); - 0x7: sync(); + format BasicOp { + 0x4: syscall({{ xc->syscall(R2); }},IsNonSpeculative); + 0x5: break({{ panic("Not implemented break yet"); }},IsNonSpeculative); + 0x7: sync({{ panic("Not implemented sync yet"); }},IsNonSpeculative); } } 0x2: decode FUNCTION_LO { format BasicOp { - 0x0: mfhi({{ Rd = xc->readMiscReg(Hi); }}); - 0x1: mthi({{ xc->setMiscReg(Hi,Rs); }}); - 0x2: mflo({{ Rd = xc->readMiscReg(Lo); }}); - 0x3: mtlo({{ xc->setMiscReg(Lo,Rs); }}); + 0x0: mfhi({{ Rd = HI; }}); + 0x1: mthi({{ HI = Rs; }}); + 0x2: mflo({{ Rd = LO; }}); + 0x3: mtlo({{ LO = Rs; }}); } } 0x3: decode FUNCTION_LO { format IntOp { 0x0: mult({{ - int64_t temp1 = Rs.sw * Rt.sw; - xc->setMiscReg(Hi,temp1<63:32>); - xc->setMiscReg(Lo,temp1<31:0>); + int64_t temp1 = Rs.sd * Rt.sd; + HI = temp1<63:32>; + LO = temp1<31:0>; }}); 0x1: multu({{ - int64_t temp1 = Rs.uw * Rt.uw; - xc->setMiscReg(Hi,temp1<63:32>); - xc->setMiscReg(Lo,temp1<31:0>); + uint64_t temp1 = Rs.ud * Rt.ud; + HI = temp1<63:32>; + LO = temp1<31:0>; }}); 0x2: div({{ - xc->setMiscReg(Hi,Rs.sw % Rt.sw); - xc->setMiscReg(Lo,Rs.sw / Rt.sw); + HI = Rs.sd % Rt.sd; + LO = Rs.sd / Rt.sd; }}); 0x3: divu({{ - xc->setMiscReg(Hi,Rs.uw % Rt.uw); - xc->setMiscReg(Lo,Rs.uw / Rt.uw); + HI = Rs.ud % Rt.ud; + LO = Rs.ud / Rt.ud; }}); } } - 0x4: decode FUNCTION_LO { - format IntOp { - 0x0: add({{ Rd.sw = Rs.sw + Rt.sw;/*Trap on Overflow*/}}); - 0x1: addu({{ Rd.sw = Rs.sw + Rt.sw;}}); - 0x2: sub({{ Rd.sw = Rs.sw - Rt.sw; /*Trap on Overflow*/}}); - 0x3: subu({{ Rd.sw = Rs.sw - Rt.uw;}}); - 0x4: and({{ Rd = Rs & Rt;}}); - 0x5: or({{ Rd = Rs | Rt;}}); - 0x6: xor({{ Rd = Rs ^ Rt;}}); - 0x7: nor({{ Rd = ~(Rs | Rt);}}); + 0x4: decode HINT { + 0x0: decode FUNCTION_LO { + format IntOp { + 0x0: add({{ Rd.sw = Rs.sw + Rt.sw; /*Trap on Overflow*/}}); + 0x1: addu({{ Rd.sw = Rs.sw + Rt.sw;}}); + 0x2: sub({{ Rd.sw = Rs.sw - Rt.sw; /*Trap on Overflow*/}}); + 0x3: subu({{ Rd.sw = Rs.sw - Rt.sw;}}); + 0x4: and({{ Rd = Rs & Rt;}}); + 0x5: or({{ Rd = Rs | Rt;}}); + 0x6: xor({{ Rd = Rs ^ Rt;}}); + 0x7: nor({{ Rd = ~(Rs | Rt);}}); + } } } - 0x5: decode FUNCTION_LO { - format IntOp{ - 0x2: slt({{ Rd.sw = ( Rs.sw < Rt.sw ) ? 1 : 0}}); - 0x3: sltu({{ Rd.uw = ( Rs.uw < Rt.uw ) ? 1 : 0}}); + 0x5: decode HINT { + 0x0: decode FUNCTION_LO { + format IntOp{ + 0x2: slt({{ Rd.sw = ( Rs.sw < Rt.sw ) ? 1 : 0}}); + 0x3: sltu({{ Rd.uw = ( Rs.uw < Rt.uw ) ? 1 : 0}}); + } } } @@ -169,7 +204,6 @@ decode OPCODE_HI default Unknown::unknown() { } format BranchLikely { - //MIPS obsolete instructions 0x2: bltzl({{ cond = (Rs.sw < 0); }}); 0x3: bgezl({{ cond = (Rs.sw >= 0); }}); } @@ -193,7 +227,6 @@ decode OPCODE_HI default Unknown::unknown() { } format BranchLikely { - //Will be removed in future MIPS releases 0x2: bltzall({{ cond = (Rs.sw < 0); }}, IsCall, IsReturn); 0x3: bgezall({{ cond = (Rs.sw >= 0); }}, IsCall, IsReturn); } @@ -215,8 +248,13 @@ decode OPCODE_HI default Unknown::unknown() { format Branch { 0x4: beq({{ cond = (Rs.sw == Rt.sw); }}); 0x5: bne({{ cond = (Rs.sw != Rt.sw); }}); - 0x6: blez({{ cond = (Rs.sw <= 0); }}); - 0x7: bgtz({{ cond = (Rs.sw > 0); }}); + 0x6: decode RT { + 0x0: blez({{ cond = (Rs.sw <= 0); }}); + } + + 0x7: decode RT { + 0x0: bgtz({{ cond = (Rs.sw > 0); }}); + } } } @@ -225,11 +263,14 @@ decode OPCODE_HI default Unknown::unknown() { 0x0: addi({{ Rt.sw = Rs.sw + imm; /*Trap If Overflow*/}}); 0x1: addiu({{ Rt.sw = Rs.sw + imm;}}); 0x2: slti({{ Rt.sw = ( Rs.sw < imm) ? 1 : 0 }}); - 0x3: sltiu({{ Rt.sw = ( Rs.sw < imm ) ? 1 : 0 }}); - 0x4: andi({{ Rt.sw = Rs.sw & INTIMM;}}); - 0x5: ori({{ Rt.sw = Rs.sw | INTIMM;}}); - 0x6: xori({{ Rt.sw = Rs.sw ^ INTIMM;}}); - 0x7: lui({{ Rt = INTIMM << 16}}); + 0x3: sltiu({{ Rt.uw = ( Rs.uw < (uint32_t)sextImm ) ? 1 : 0 }}); + 0x4: andi({{ Rt.sw = Rs.sw & zextImm;}}); + 0x5: ori({{ Rt.sw = Rs.sw | zextImm;}}); + 0x6: xori({{ Rt.sw = Rs.sw ^ zextImm;}}); + + 0x7: decode RS { + 0x0: lui({{ Rt = imm << 16}}); + } } } @@ -258,6 +299,7 @@ decode OPCODE_HI default Unknown::unknown() { //sel field. In those instances, the sel field must be zero. //MT Code Needed Here + }}); 0xC: mttr({{ @@ -283,55 +325,37 @@ decode OPCODE_HI default Unknown::unknown() { 0x0: decode SC { 0x0: dvpe({{ - int idx; - int sel; - getMiscRegIdx(MVPControl,idx,sel); - Rt.sw = xc->readMiscReg(idx,sel); - xc->setMiscReg(idx,sel); + Rt.sw = xc->readMiscReg(MVPControl); + xc->setMiscReg(MVPControl,0); }}); 0x1: evpe({{ - int idx; - int sel; - getMiscRegIdx(MVPControl,idx,sel); - Rt.sw = xc->readMiscReg(idx,sel); - xc->setMiscReg(idx,sel,1); + Rt.sw = xc->readMiscReg(MVPControl); + xc->setMiscReg(MVPControl,1); }}); } 0x1: decode SC { 0x0: dmt({{ - int idx; - int sel; - getMiscRegIdx(VPEControl,idx,sel); - Rt.sw = xc->readMiscReg(idx,sel); - xc->setMiscReg(idx,sel); + Rt.sw = xc->readMiscReg(VPEControl); + xc->setMiscReg(VPEControl,0); }}); 0x1: emt({{ - int idx; - int sel; - getMiscRegIdx(VPEControl,idx,sel); - Rt.sw = xc->readMiscReg(idx,sel); - xc->setMiscReg(idx,sel,1); + Rt.sw = xc->readMiscReg(VPEControl); + xc->setMiscReg(VPEControl,1); }}); } 0xC: decode SC { 0x0: di({{ - int idx; - int sel; - getMiscRegIdx(Status,idx,sel); - Rt.sw = xc->readMiscReg(idx,sel); - xc->setMiscReg(idx,sel); + Rt.sw = xc->readMiscReg(Status); + xc->setMiscReg(Status,0); }}); 0x1: ei({{ - int idx; - int sel; - getMiscRegIdx(Status,idx,sel); - Rt.sw = xc->readMiscReg(idx,sel); - xc->setMiscReg(idx,sel,1); + Rt.sw = xc->readMiscReg(Status); + xc->setMiscReg(Status,1); }}); } } @@ -370,27 +394,91 @@ decode OPCODE_HI default Unknown::unknown() { 0x0: decode RS_HI { 0x0: decode RS_LO { format FloatOp { - 0x0: mfc1({{ /*Rt.uw = Fs.ud<31:0>;*/ }}); - 0x2: cfc1({{ /*Rt.uw = xc->readMiscReg(FPCR[Fs]);*/}}); - 0x3: mfhc1({{ /*Rt.uw = Fs.ud<63:32>*/;}}); - 0x4: mtc1({{ /*Fs = Rt.uw*/}}); - 0x6: ctc1({{ /*xc->setMiscReg(FPCR[Fs],Rt);*/}}); - 0x7: mthc1({{ /*Fs<63:32> = Rt.uw*/}}); + 0x0: mfc1 ({{ Rt.uw = Fs.uw<31:0>; }}); + 0x3: mfhc1({{ Rt.uw = Fs.ud<63:32>;}}); + 0x4: mtc1 ({{ Fs.uw = Rt.uw; }}); + 0x7: mthc1({{ + uint64_t fs_hi = Rt.uw; + uint64_t fs_lo = Fs.ud & 0x0000FFFF; + Fs.ud = fs_hi << 32 | fs_lo; + }}); + } + + format System { + 0x2: cfc1({{ + switch (FS) + { + case 0: + Rt = FIR; + break; + case 25: + Rt = 0 | (FCSR & 0xFE000000) >> 24 | (FCSR & 0x00800000) >> 23; + break; + case 26: + Rt = 0 | (FCSR & 0x0003F07C); + break; + case 28: + Rt = 0 | (FCSR & 0x00000F80) | (FCSR & 0x01000000) >> 21 | (FCSR & 0x00000003); + break; + case 31: + Rt = FCSR; + break; + default: + panic("FP Control Value (%d) Not Available. Ignoring Access to" + "Floating Control Status Register",FS); + } + }}); + + 0x6: ctc1({{ + switch (FS) + { + case 25: + FCSR = 0 | (Rt.uw<7:1> << 25) // move 31...25 + | (FCSR & 0x01000000) // bit 24 + | (FCSR & 0x004FFFFF);// bit 22...0 + break; + + case 26: + FCSR = 0 | (FCSR & 0xFFFC0000) // move 31...18 + | Rt.uw<17:12> << 12 // bit 17...12 + | (FCSR & 0x00000F80) << 7// bit 11...7 + | Rt.uw<6:2> << 2 // bit 6...2 + | (FCSR & 0x00000002); // bit 1...0 + break; + + case 28: + FCSR = 0 | (FCSR & 0xFE000000) // move 31...25 + | Rt.uw<2:2> << 24 // bit 24 + | (FCSR & 0x00FFF000) << 23// bit 23...12 + | Rt.uw<11:7> << 7 // bit 24 + | (FCSR & 0x000007E) + | Rt.uw<1:0>;// bit 22...0 + break; + + case 31: + FCSR = Rt.uw; + break; + + default: + panic("FP Control Value (%d) Not Available. Ignoring Access to" + "Floating Control Status Register", FS); + } + }}); } } 0x1: decode ND { 0x0: decode TF { format Branch { - 0x0: bc1f({{ cond = (xc->readMiscReg(FPCR) == 0); }}); - 0x1: bc1t({{ cond = (xc->readMiscReg(FPCR) == 1); }}); + 0x0: bc1f({{ cond = (getFPConditionCode(FCSR,CC) == 0); }}); + 0x1: bc1t({{ cond = (getFPConditionCode(FCSR,CC) == 1); }}); } } 0x1: decode TF { format BranchLikely { - 0x0: bc1fl({{ cond = (xc->readMiscReg(FPCR) == 0); }}); - 0x1: bc1tl({{ cond = (xc->readMiscReg(FPCR) == 1); }}); + 0x0: bc1fl({{ cond = (getFPConditionCode(FCSR,CC) == 0); }}); + 0x1: bc1tl({{ cond = (getFPConditionCode(FCSR,CC) == 1); }}); } } } @@ -401,164 +489,422 @@ decode OPCODE_HI default Unknown::unknown() { //Table A-14 MIPS32 COP1 Encoding of Function Field When rs=S //(( single-word )) - 0x0: decode RS_HI { - 0x0: decode RS_LO { + 0x0: decode FUNCTION_HI { + 0x0: decode FUNCTION_LO { format FloatOp { - 0x0: adds({{ Fd.sf = Fs.sf + Ft.sf;}}); - 0x1: subs({{ Fd.sf = Fs.sf - Ft.sf;}}); - 0x2: muls({{ Fd.sf = Fs.sf * Ft.sf;}}); - 0x3: divs({{ Fd.sf = Fs.sf / Ft.sf;}}); - 0x4: sqrts({{ Fd.sf = sqrt(Fs.sf);}}); - 0x5: abss({{ Fd.sf = fabs(Fs.sf);}}); - 0x6: movs({{ Fd.sf = Fs.sf;}}); - 0x7: negs({{ Fd.sf = -1 * Fs.sf;}}); + 0x0: add_s({{ Fd.sf = Fs.sf + Ft.sf;}}); + 0x1: sub_s({{ Fd.sf = Fs.sf - Ft.sf;}}); + 0x2: mul_s({{ Fd.sf = Fs.sf * Ft.sf;}}); + 0x3: div_s({{ Fd.sf = Fs.sf / Ft.sf;}}); + 0x4: sqrt_s({{ Fd.sf = sqrt(Fs.sf);}}); + 0x5: abs_s({{ Fd.sf = fabs(Fs.sf);}}); + 0x6: mov_s({{ Fd.sf = Fs.sf;}}); + 0x7: neg_s({{ Fd.sf = -1 * Fs.sf;}}); } } - 0x1: decode RS_LO { - //only legal for 64 bit-FP + 0x1: decode FUNCTION_LO { format Float64Op { - 0x0: round_l_s({{ Fd = convert_and_round(Fs.sf,RND_NEAREST,FP_LONG,FP_SINGLE);}}); - 0x1: trunc_l_s({{ Fd = convert_and_round(Fs.sf,RND_ZERO,FP_LONG,FP_SINGLE);}}); - 0x2: ceil_l_s({{ Fd = convert_and_round(Fs.sf,RND_UP,FP_LONG,FP_SINGLE);}}); - 0x3: floor_l_s({{ Fd = convert_and_round(Fs.sf,RND_DOWN,FP_LONG,FP_SINGLE);}}); + 0x0: round_l_s({{ + Fd.ud = fpConvert(roundFP(Fs.sf,0), SINGLE_TO_LONG); + }}); + + 0x1: trunc_l_s({{ + Fd.ud = fpConvert(truncFP(Fs.sf), SINGLE_TO_LONG); + }}); + + 0x2: ceil_l_s({{ + Fd.ud = fpConvert(ceil(Fs.sf), SINGLE_TO_LONG); + }}); + + 0x3: floor_l_s({{ + Fd.ud = fpConvert(floor(Fs.sf), SINGLE_TO_LONG); + }}); } format FloatOp { - 0x4: round_w_s({{ Fd = convert_and_round(Fs.sf,RND_NEAREST,FP_WORD,FP_SINGLE);}}); - 0x5: trunc_w_s({{ Fd = convert_and_round(Fs.sf,RND_ZERO,FP_WORD,FP_SINGLE);}}); - 0x6: ceil_w_s({{ Fd = convert_and_round(Fs.sf,RND_UP,FP_WORD,FP_SINGLE);}}); - 0x7: floor_w_s({{ Fd = convert_and_round(Fs.sf,RND_DOWN,FP_WORD,FP_SINGLE);}}); + 0x4: round_w_s({{ + Fd.uw = fpConvert(roundFP(Fs.sf,0), SINGLE_TO_WORD); + }}); + + 0x5: trunc_w_s({{ + Fd.uw = fpConvert(truncFP(Fs.sf), SINGLE_TO_WORD); + }}); + + 0x6: ceil_w_s({{ + Fd.uw = fpConvert(ceil(Fs.sf), SINGLE_TO_WORD); + }}); + + 0x7: floor_w_s({{ + Fd.uw = fpConvert(floor(Fs.sf), SINGLE_TO_WORD); + }}); } } - 0x2: decode RS_LO { + 0x2: decode FUNCTION_LO { 0x1: decode MOVCF { format FloatOp { - 0x0: movfs({{if (xc->readMiscReg(FPCR) != CC) Fd = Fs; }}); - 0x1: movts({{if (xc->readMiscReg(FPCR) == CC) Fd = Fs;}}); + 0x0: movf_s({{if (getFPConditionCode(FCSR,CC) == 0) Fd = Fs;}}); + 0x1: movt_s({{if (getFPConditionCode(FCSR,CC) == 1) Fd = Fs;}}); } } - format BasicOp { - 0x2: movzs({{ if (Rt == 0) Fd = Fs; }}); - 0x3: movns({{ if (Rt != 0) Fd = Fs; }}); + format FloatOp { + 0x2: movz_s({{ if (Rt == 0) Fd = Fs; }}); + 0x3: movn_s({{ if (Rt != 0) Fd = Fs; }}); + 0x5: recip_s({{ Fd = 1 / Fs; }}); + 0x6: rsqrt_s({{ Fd = 1 / sqrt(Fs);}}); } + } - format Float64Op { - 0x5: recips({{ Fd = 1 / Fs; }}); - 0x6: rsqrts({{ Fd = 1 / sqrt((double)Fs.ud);}}); + 0x4: decode FUNCTION_LO { + + format FloatConvertOp { + 0x1: cvt_d_s({{ + Fd.ud = fpConvert(Fs.sf, SINGLE_TO_DOUBLE); + }}); + + 0x4: cvt_w_s({{ + Fd.uw = fpConvert(Fs.sf, SINGLE_TO_WORD); + }}); + } + + format FloatConvertOp { + 0x5: cvt_l_s({{ + Fd.ud = fpConvert(Fs.sf, SINGLE_TO_LONG); + }}); + + 0x6: cvt_ps_st({{ + Fd.ud = (uint64_t)Fs.uw << 32 | (uint64_t)Ft.uw; + }}); } } - 0x4: decode RS_LO { + 0x6: decode FUNCTION_LO { + format FloatCompareOp { + 0x0: c_f_s({{ cond = 0; }}); - format FloatOp { - 0x1: cvt_d_s({{ int rnd_mode = xc->readMiscReg(FCSR); - Fd = convert_and_round(Fs.sf,rnd_mode,FP_DOUBLE,FP_SINGLE); + 0x1: c_un_s({{ + if (isnan(Fs.sf) || isnan(Ft.sf)) + cond = 1; + else + cond = 0; }}); - 0x4: cvt_w_s({{ int rnd_mode = xc->readMiscReg(FCSR); - Fd = convert_and_round(Fs.sf,rnd_mode,FP_WORD,FP_SINGLE); + 0x2: c_eq_s({{ + if (isnan(Fs.sf) || isnan(Ft.sf)) + cond = 0; + else + cond = (Fs.sf == Ft.sf); }}); - } - //only legal for 64 bit - format Float64Op { - 0x5: cvt_l_s({{ int rnd_mode = xc->readMiscReg(FCSR); - Fd = convert_and_round(Fs.sf,rnd_mode,FP_LONG,FP_SINGLE); + 0x3: c_ueq_s({{ + if (isnan(Fs.sf) || isnan(Ft.sf)) + cond = 1; + else + cond = (Fs.sf == Ft.sf); + }}); + + 0x4: c_olt_s({{ + if (isnan(Fs.sf) || isnan(Ft.sf)) + cond = 0; + else + cond = (Fs.sf < Ft.sf); }}); - 0x6: cvt_ps_s({{ /*Fd.df = Fs.df<31:0> | Ft.df<31:0>;*/ }}); + 0x5: c_ult_s({{ + if (isnan(Fs.sf) || isnan(Ft.sf)) + cond = 1; + else + cond = (Fs.sf < Ft.sf); + }}); + + 0x6: c_ole_s({{ + if (isnan(Fs.sf) || isnan(Ft.sf)) + cond = 0; + else + cond = (Fs.sf <= Ft.sf); + }}); + + 0x7: c_ule_s({{ + if (isnan(Fs.sf) || isnan(Ft.sf)) + cond = 1; + else + cond = (Fs.sf <= Ft.sf); + }}); + } + } + + 0x7: decode FUNCTION_LO { + format FloatCompareWithXcptOp { + 0x0: c_sf_s({{ cond = 0; }}); + + 0x1: c_ngle_s({{ + if (isnan(Fs.sf) || isnan(Ft.sf)) + cond = 1; + else + cond = 0; + }}); + + 0x2: c_seq_s({{ + if (isnan(Fs.sf) || isnan(Ft.sf)) + cond = 0; + else + cond = (Fs.sf == Ft.sf); + }}); + + 0x3: c_ngl_s({{ + if (isnan(Fs.sf) || isnan(Ft.sf)) + cond = 1; + else + cond = (Fs.sf == Ft.sf); + }}); + + 0x4: c_lt_s({{ + if (isnan(Fs.sf) || isnan(Ft.sf)) + cond = 0; + else + cond = (Fs.sf < Ft.sf); + }}); + + 0x5: c_nge_s({{ + if (isnan(Fs.sf) || isnan(Ft.sf)) + cond = 1; + else + cond = (Fs.sf < Ft.sf); + }}); + + 0x6: c_le_s({{ + if (isnan(Fs.sf) || isnan(Ft.sf)) + cond = 0; + else + cond = (Fs.sf <= Ft.sf); + }}); + + 0x7: c_ngt_s({{ + if (isnan(Fs.sf) || isnan(Ft.sf)) + cond = 1; + else + cond = (Fs.sf <= Ft.sf); + }}); } } } //Table A-15 MIPS32 COP1 Encoding of Function Field When rs=D - 0x1: decode RS_HI { - 0x0: decode RS_LO { + 0x1: decode FUNCTION_HI { + 0x0: decode FUNCTION_LO { format FloatOp { - 0x0: addd({{ Fd.df = Fs.df + Ft.df;}}); - 0x1: subd({{ Fd.df = Fs.df - Ft.df;}}); - 0x2: muld({{ Fd.df = Fs.df * Ft.df;}}); - 0x3: divd({{ Fd.df = Fs.df / Ft.df;}}); - 0x4: sqrtd({{ Fd.df = sqrt(Fs.df);}}); - 0x5: absd({{ Fd.df = fabs(Fs.df);}}); - 0x6: movd({{ Fd.df = Fs.df;}}); - 0x7: negd({{ Fd.df = -1 * Fs.df;}}); + 0x0: add_d({{ Fd.df = Fs.df + Ft.df;}}); + 0x1: sub_d({{ Fd.df = Fs.df - Ft.df;}}); + 0x2: mul_d({{ Fd.df = Fs.df * Ft.df;}}); + 0x3: div_d({{ Fd.df = Fs.df / Ft.df;}}); + 0x4: sqrt_d({{ Fd.df = sqrt(Fs.df);}}); + 0x5: abs_d({{ Fd.df = fabs(Fs.df);}}); + 0x6: mov_d({{ Fd.ud = Fs.ud;}}); + 0x7: neg_d({{ Fd.df = -1 * Fs.df;}}); } } - 0x1: decode RS_LO { - //only legal for 64 bit - format Float64Op { - 0x0: round_l_d({{ Fd = convert_and_round(Fs.df,RND_NEAREST,FP_LONG,FP_DOUBLE); }}); - 0x1: trunc_l_d({{ Fd = convert_and_round(Fs.df,RND_ZERO,FP_LONG,FP_DOUBLE);}}); - 0x2: ceil_l_d({{ Fd = convert_and_round(Fs.df,RND_UP,FP_LONG,FP_DOUBLE);}}); - 0x3: floor_l_d({{ Fd = convert_and_round(Fs.df,RND_DOWN,FP_LONG,FP_DOUBLE);}}); + 0x1: decode FUNCTION_LO { + format FloatOp { + 0x0: round_l_d({{ + Fd.ud = fpConvert(roundFP(Fs.df,0), DOUBLE_TO_LONG); + }}); + + 0x1: trunc_l_d({{ + Fd.ud = fpConvert(truncFP(Fs.df), DOUBLE_TO_LONG); + }}); + + 0x2: ceil_l_d({{ + Fd.ud = fpConvert(ceil(Fs.df), DOUBLE_TO_LONG); + }}); + + 0x3: floor_l_d({{ + Fd.ud = fpConvert(floor(Fs.df), DOUBLE_TO_LONG); + }}); } format FloatOp { - 0x4: round_w_d({{ Fd = convert_and_round(Fs.df,RND_NEAREST,FP_LONG,FP_DOUBLE); }}); - 0x5: trunc_w_d({{ Fd = convert_and_round(Fs.df,RND_ZERO,FP_LONG,FP_DOUBLE); }}); - 0x6: ceil_w_d({{ Fd = convert_and_round(Fs.df,RND_UP,FP_LONG,FP_DOUBLE); }}); - 0x7: floor_w_d({{ Fd = convert_and_round(Fs.df,RND_DOWN,FP_LONG,FP_DOUBLE); }}); + 0x4: round_w_d({{ + Fd.uw = fpConvert(roundFP(Fs.df,0), DOUBLE_TO_WORD); + }}); + + 0x5: trunc_w_d({{ + Fd.uw = fpConvert(truncFP(Fs.df), DOUBLE_TO_WORD); + }}); + + 0x6: ceil_w_d({{ + Fd.uw = fpConvert(ceil(Fs.df), DOUBLE_TO_WORD); + }}); + + 0x7: floor_w_d({{ + Fd.uw = fpConvert(floor(Fs.df), DOUBLE_TO_WORD); + }}); } } - 0x2: decode RS_LO { + 0x2: decode FUNCTION_LO { 0x1: decode MOVCF { format FloatOp { - 0x0: movfd({{if (xc->readMiscReg(FPCR) != CC) Fd.df = Fs.df; }}); - 0x1: movtd({{if (xc->readMiscReg(FPCR) == CC) Fd.df = Fs.df; }}); + 0x0: movf_d({{if (getFPConditionCode(FCSR,CC) == 0) Fd.df = Fs.df; }}); + 0x1: movt_d({{if (getFPConditionCode(FCSR,CC) == 1) Fd.df = Fs.df; }}); } } format BasicOp { - 0x2: movzd({{ if (Rt == 0) Fd.df = Fs.df; }}); - 0x3: movnd({{ if (Rt != 0) Fd.df = Fs.df; }}); + 0x2: movz_d({{ if (Rt == 0) Fd.df = Fs.df; }}); + 0x3: movn_d({{ if (Rt != 0) Fd.df = Fs.df; }}); } - format Float64Op { - 0x5: recipd({{ Fd.df = 1 / Fs.df}}); - 0x6: rsqrtd({{ Fd.df = 1 / sqrt(Fs.df) }}); + format FloatOp { + 0x5: recip_d({{ Fd.df = 1 / Fs.df}}); + 0x6: rsqrt_d({{ Fd.df = 1 / sqrt(Fs.df) }}); } } - 0x4: decode RS_LO { + 0x4: decode FUNCTION_LO { format FloatOp { 0x0: cvt_s_d({{ - int rnd_mode = xc->readMiscReg(FCSR); - Fd = convert_and_round(Fs.df,rnd_mode,FP_SINGLE,FP_DOUBLE); + Fd.uw = fpConvert(Fs.df, DOUBLE_TO_SINGLE); }}); 0x4: cvt_w_d({{ - int rnd_mode = xc->readMiscReg(FCSR); - Fd = convert_and_round(Fs.df,rnd_mode,FP_WORD,FP_DOUBLE); + Fd.uw = fpConvert(Fs.df, DOUBLE_TO_WORD); }}); - } - //only legal for 64 bit - format Float64Op { 0x5: cvt_l_d({{ - int rnd_mode = xc->readMiscReg(FCSR); - Fd = convert_and_round(Fs.df,rnd_mode,FP_LONG,FP_DOUBLE); + Fd.ud = fpConvert(Fs.df, DOUBLE_TO_LONG); + }}); + } + } + + 0x6: decode FUNCTION_LO { + format FloatCompareOp { + 0x0: c_f_d({{ cond = 0; }}); + + 0x1: c_un_d({{ + if (isnan(Fs.df) || isnan(Ft.df)) + cond = 1; + else + cond = 0; + }}); + + 0x2: c_eq_d({{ + if (isnan(Fs.df) || isnan(Ft.df)) + cond = 0; + else + cond = (Fs.df == Ft.df); }}); + + 0x3: c_ueq_d({{ + if (isnan(Fs.df) || isnan(Ft.df)) + cond = 1; + else + cond = (Fs.df == Ft.df); + }}); + + 0x4: c_olt_d({{ + if (isnan(Fs.df) || isnan(Ft.df)) + cond = 0; + else + cond = (Fs.df < Ft.df); + }}); + + 0x5: c_ult_d({{ + if (isnan(Fs.df) || isnan(Ft.df)) + cond = 1; + else + cond = (Fs.df < Ft.df); + }}); + + 0x6: c_ole_d({{ + if (isnan(Fs.df) || isnan(Ft.df)) + cond = 0; + else + cond = (Fs.df <= Ft.df); + }}); + + 0x7: c_ule_d({{ + if (isnan(Fs.df) || isnan(Ft.df)) + cond = 1; + else + cond = (Fs.df <= Ft.df); + }}); + } + } + + 0x7: decode FUNCTION_LO { + format FloatCompareWithXcptOp { + 0x0: c_sf_d({{ cond = 0; }}); + + 0x1: c_ngle_d({{ + if (isnan(Fs.df) || isnan(Ft.df)) + cond = 1; + else + cond = 0; + }}); + + 0x2: c_seq_d({{ + if (isnan(Fs.df) || isnan(Ft.df)) + cond = 0; + else + cond = (Fs.df == Ft.df); + }}); + + 0x3: c_ngl_d({{ + if (isnan(Fs.df) || isnan(Ft.df)) + cond = 1; + else + cond = (Fs.df == Ft.df); + }}); + + 0x4: c_lt_d({{ + if (isnan(Fs.df) || isnan(Ft.df)) + cond = 0; + else + cond = (Fs.df < Ft.df); + }}); + + 0x5: c_nge_d({{ + if (isnan(Fs.df) || isnan(Ft.df)) + cond = 1; + else + cond = (Fs.df < Ft.df); + }}); + + 0x6: c_le_d({{ + if (isnan(Fs.df) || isnan(Ft.df)) + cond = 0; + else + cond = (Fs.df <= Ft.df); + }}); + + 0x7: c_ngt_d({{ + if (isnan(Fs.df) || isnan(Ft.df)) + cond = 1; + else + cond = (Fs.df <= Ft.df); + }}); } } } //Table A-16 MIPS32 COP1 Encoding of Function Field When rs=W 0x4: decode FUNCTION { - format FloatOp { - 0x20: cvt_s({{ - int rnd_mode = xc->readMiscReg(FCSR); - Fd = convert_and_round(Fs.df,rnd_mode,FP_SINGLE,FP_WORD); + format FloatConvertOp { + 0x20: cvt_s_w({{ + Fd.uw = fpConvert(Fs.sf, WORD_TO_SINGLE); + }}); + + 0x21: cvt_d_w({{ + Fd.ud = fpConvert(Fs.sf, WORD_TO_DOUBLE); }}); + } - 0x21: cvt_d({{ - int rnd_mode = xc->readMiscReg(FCSR); - Fd = convert_and_round(Fs.df,rnd_mode,FP_DOUBLE,FP_WORD); + format Float64ConvertOp { + 0x26: cvt_ps_pw({{ + Fd.ud = fpConvert(Fs.ud, WORD_TO_PS); }}); } } @@ -567,15 +913,17 @@ decode OPCODE_HI default Unknown::unknown() { //Note: "1. Format type L is legal only if 64-bit floating point operations //are enabled." 0x5: decode FUNCTION_HI { - format FloatOp { - 0x10: cvt_s_l({{ - int rnd_mode = xc->readMiscReg(FCSR); - Fd = convert_and_round(Fs.df,rnd_mode,FP_SINGLE,FP_LONG); + format Float64ConvertOp { + 0x20: cvt_s_l({{ + Fd.uw = fpConvert(Fs.ud, LONG_TO_SINGLE); + }}); + + 0x21: cvt_d_l({{ + Fd.ud = fpConvert(Fs.ud, LONG_TO_DOUBLE); }}); - 0x11: cvt_d_l({{ - int rnd_mode = xc->readMiscReg(FCSR); - Fd = convert_and_round(Fs.df,rnd_mode,FP_DOUBLE,FP_LONG); + 0x26: cvt_ps_l({{ + Fd.ud = fpConvert(Fs.ud, LONG_TO_PS); }}); } } @@ -583,73 +931,275 @@ decode OPCODE_HI default Unknown::unknown() { //Table A-17 MIPS64 COP1 Encoding of Function Field When rs=PS1 //Note: "1. Format type PS is legal only if 64-bit floating point operations //are enabled. " - 0x6: decode RS_HI { - 0x0: decode RS_LO { + 0x6: decode FUNCTION_HI { + 0x0: decode FUNCTION_LO { format Float64Op { - 0x0: addps({{ //Must Check for Exception Here... Supposed to Operate on Upper and - //Lower Halves Independently but we take simulator shortcut - Fd.df = Fs.df + Ft.df; + 0x0: add_ps({{ + Fd1.sf = Fs1.sf + Ft2.sf; + Fd2.sf = Fs2.sf + Ft2.sf; }}); - 0x1: subps({{ //Must Check for Exception Here... Supposed to Operate on Upper and - //Lower Halves Independently but we take simulator shortcut - Fd.df = Fs.df - Ft.df; + 0x1: sub_ps({{ + Fd1.sf = Fs1.sf - Ft2.sf; + Fd2.sf = Fs2.sf - Ft2.sf; }}); - 0x2: mulps({{ //Must Check for Exception Here... Supposed to Operate on Upper and - //Lower Halves Independently but we take simulator shortcut - Fd.df = Fs.df * Ft.df; + 0x2: mul_ps({{ + Fd1.sf = Fs1.sf * Ft2.sf; + Fd2.sf = Fs2.sf * Ft2.sf; }}); - 0x5: absps({{ //Must Check for Exception Here... Supposed to Operate on Upper and - //Lower Halves Independently but we take simulator shortcut - Fd.df = fabs(Fs.df); + 0x5: abs_ps({{ + Fd1.sf = fabs(Fs1.sf); + Fd2.sf = fabs(Fs2.sf); }}); - 0x6: movps({{ //Must Check for Exception Here... Supposed to Operate on Upper and - //Lower Halves Independently but we take simulator shortcut - //Fd.df = Fs<31:0> | Ft<31:0>; + 0x6: mov_ps({{ + Fd1.sf = Fs1.sf; + Fd2.sf = Fs2.sf; }}); - 0x7: negps({{ //Must Check for Exception Here... Supposed to Operate on Upper and - //Lower Halves Independently but we take simulator shortcut - Fd.df = -1 * Fs.df; + 0x7: neg_ps({{ + Fd1.sf = -1 * Fs1.sf; + Fd2.sf = -1 * Fs2.sf; }}); } } - 0x2: decode RS_LO { + 0x2: decode FUNCTION_LO { 0x1: decode MOVCF { format Float64Op { - 0x0: movfps({{if (xc->readMiscReg(FPCR) != CC) Fd = Fs;}}); - 0x1: movtps({{if (xc->readMiscReg(FPCR) == CC) Fd = Fs;}}); + 0x0: movf_ps({{ + if (getFPConditionCode(FCSR, CC) == 0) + Fd1 = Fs1; + if (getFPConditionCode(FCSR, CC+1) == 0) + Fd2 = Fs2; + }}); + + 0x1: movt_ps({{ + if (getFPConditionCode(FCSR, CC) == 1) + Fd1 = Fs1; + if (getFPConditionCode(FCSR, CC+1) == 1) + Fd2 = Fs2; + }}); } } - format BasicOp { - 0x2: movzps({{if (xc->readMiscReg(FPCR) != CC) Fd = Fs; }}); - 0x3: movnps({{if (xc->readMiscReg(FPCR) == CC) Fd = Fs; }}); + format Float64Op { + 0x2: movz_ps({{ + if (getFPConditionCode(FCSR, CC) == 0) + Fd1 = Fs1; + if (getFPConditionCode(FCSR, CC) == 0) + Fd2 = Fs2; + }}); + + 0x3: movn_ps({{ + if (getFPConditionCode(FCSR, CC) == 1) + Fd1 = Fs1; + if (getFPConditionCode(FCSR, CC) == 1) + Fd2 = Fs2; + }}); } } - 0x4: decode RS_LO { + 0x4: decode FUNCTION_LO { 0x0: Float64Op::cvt_s_pu({{ - int rnd_mode = xc->readMiscReg(FCSR); - Fd = convert_and_round(Fs.df,rnd_mode,FP_DOUBLE,FP_PS_HI); + Fd.uw = fpConvert(Fs2.uw, PU_TO_SINGLE); }}); } - 0x5: decode RS_LO { + 0x5: decode FUNCTION_LO { format Float64Op { 0x0: cvt_s_pl({{ - int rnd_mode = xc->readMiscReg(FCSR); - Fd = convert_and_round(Fs.df,rnd_mode,FP_SINGLE,FP_PS_LO); + Fd.uw = fpConvert(Fs1.uw, PL_TO_SINGLE); }}); - 0x4: pll({{ /*Fd.df = Fs<31:0> | Ft<31:0>*/}}); - 0x5: plu({{ /*Fd.df = Fs<31:0> | Ft<63:32>*/}}); - 0x6: pul({{ /*Fd.df = Fs<63:32> | Ft<31:0>*/}}); - 0x7: puu({{ /*Fd.df = Fs<63:32 | Ft<63:32>*/}}); + + 0x4: pll({{ Fd.ud = (uint64_t) Fs1.uw << 32 | Ft1.uw; }}); + 0x5: plu({{ Fd.ud = (uint64_t) Fs1.uw << 32 | Ft2.uw; }}); + 0x6: pul({{ Fd.ud = (uint64_t) Fs2.uw << 32 | Ft1.uw; }}); + 0x7: puu({{ Fd.ud = (uint64_t) Fs2.uw << 32 | Ft2.uw; }}); + } + } + + 0x6: decode FUNCTION_LO { + format FloatPSCompareOp { + 0x0: c_f_ps({{ cond1 = 0; cond2 = 0; }}); + + 0x1: c_un_ps({{ + if (isnan(Fs1.sf) || isnan(Ft1.sf)) + cond1 = 1; + else + cond1 = 0; + + if (isnan(Fs2.sf) || isnan(Ft2.sf)) + cond2 = 1; + else + cond2 = 0; + + }}); + + 0x2: c_eq_ps({{ + if (isnan(Fs1.sf) || isnan(Ft1.sf)) + cond1 = 0; + else + cond1 = (Fs1.sf == Ft1.sf); + + if (isnan(Fs2.sf) || isnan(Ft2.sf)) + cond2 = 0; + else + cond2 = (Fs2.sf == Ft2.sf); + }}); + + 0x3: c_ueq_ps({{ + if (isnan(Fs1.sf) || isnan(Ft1.sf)) + cond1 = 1; + else + cond1 = (Fs1.sf == Ft1.sf); + + if (isnan(Fs2.sf) || isnan(Ft2.sf)) + cond2 = 1; + else + cond2 = (Fs2.sf == Ft2.sf); + }}); + + 0x4: c_olt_ps({{ + if (isnan(Fs1.sf) || isnan(Ft1.sf)) + cond1 = 0; + else + cond1 = (Fs1.sf < Ft1.sf); + + if (isnan(Fs2.sf) || isnan(Ft2.sf)) + cond2 = 0; + else + cond2 = (Fs2.sf < Ft2.sf); + }}); + + 0x5: c_ult_ps({{ + if (isnan(Fs1.sf) || isnan(Ft1.sf)) + cond1 = 1; + else + cond1 = (Fs.sf < Ft.sf); + + if (isnan(Fs2.sf) || isnan(Ft2.sf)) + cond2 = 1; + else + cond2 = (Fs2.sf < Ft2.sf); + }}); + + 0x6: c_ole_ps({{ + if (isnan(Fs.sf) || isnan(Ft.sf)) + cond1 = 0; + else + cond1 = (Fs.sf <= Ft.sf); + + if (isnan(Fs2.sf) || isnan(Ft2.sf)) + cond2 = 0; + else + cond2 = (Fs2.sf <= Ft2.sf); + }}); + + 0x7: c_ule_ps({{ + if (isnan(Fs1.sf) || isnan(Ft1.sf)) + cond1 = 1; + else + cond1 = (Fs1.sf <= Ft1.sf); + + if (isnan(Fs2.sf) || isnan(Ft2.sf)) + cond2 = 1; + else + cond2 = (Fs2.sf <= Ft2.sf); + }}); + } + } + + 0x7: decode FUNCTION_LO { + format FloatPSCompareWithXcptOp { + 0x0: c_sf_ps({{ cond1 = 0; cond2 = 0; }}); + + 0x1: c_ngle_ps({{ + if (isnan(Fs1.sf) || isnan(Ft1.sf)) + cond1 = 1; + else + cond1 = 0; + + if (isnan(Fs2.sf) || isnan(Ft2.sf)) + cond2 = 1; + else + cond2 = 0; + }}); + + 0x2: c_seq_ps({{ + if (isnan(Fs1.sf) || isnan(Ft1.sf)) + cond1 = 0; + else + cond1 = (Fs1.sf == Ft1.sf); + + if (isnan(Fs2.sf) || isnan(Ft2.sf)) + cond2 = 0; + else + cond2 = (Fs2.sf == Ft2.sf); + }}); + + 0x3: c_ngl_ps({{ + if (isnan(Fs1.sf) || isnan(Ft1.sf)) + cond1 = 1; + else + cond1 = (Fs1.sf == Ft1.sf); + + if (isnan(Fs2.sf) || isnan(Ft2.sf)) + cond2 = 1; + else + cond2 = (Fs2.sf == Ft2.sf); + }}); + + 0x4: c_lt_ps({{ + if (isnan(Fs1.sf) || isnan(Ft1.sf)) + cond1 = 0; + else + cond1 = (Fs1.sf < Ft1.sf); + + if (isnan(Fs2.sf) || isnan(Ft2.sf)) + cond2 = 0; + else + cond2 = (Fs2.sf < Ft2.sf); + }}); + + 0x5: c_nge_ps({{ + if (isnan(Fs1.sf) || isnan(Ft1.sf)) + cond1 = 1; + else + cond1 = (Fs1.sf < Ft1.sf); + + if (isnan(Fs2.sf) || isnan(Ft2.sf)) + cond2 = 1; + else + cond2 = (Fs2.sf < Ft2.sf); + }}); + + 0x6: c_le_ps({{ + if (isnan(Fs1.sf) || isnan(Ft1.sf)) + cond1 = 0; + else + cond1 = (Fs1.sf <= Ft1.sf); + + if (isnan(Fs2.sf) || isnan(Ft2.sf)) + cond2 = 0; + else + cond2 = (Fs2.sf <= Ft2.sf); + }}); + + 0x7: c_ngt_ps({{ + if (isnan(Fs1.sf) || isnan(Ft1.sf)) + cond1 = 1; + else + cond1 = (Fs1.sf <= Ft1.sf); + + if (isnan(Fs2.sf) || isnan(Ft2.sf)) + cond2 = 1; + else + cond2 = (Fs2.sf <= Ft2.sf); + }}); } } } @@ -694,24 +1244,18 @@ decode OPCODE_HI default Unknown::unknown() { //operations are enabled." 0x3: decode FUNCTION_HI { 0x0: decode FUNCTION_LO { - format LoadMemory2 { - 0x0: lwxc1({{ EA = Rs + Rt; }},{{ /*F_t<31:0> = Mem.sf; */}}); - 0x1: ldxc1({{ EA = Rs + Rt; }},{{ /*F_t<63:0> = Mem.df;*/ }}); - 0x5: luxc1({{ //Need to make EA<2:0> = 0 - EA = Rs + Rt; - }}, - {{ /*F_t<31:0> = Mem.df; */}}); + format LoadFloatMemory { + 0x0: lwxc1({{ Ft.uw = Mem.uw;}}, {{ EA = Rs + Rt; }}); + 0x1: ldxc1({{ Ft.ud = Mem.ud;}}, {{ EA = Rs + Rt; }}); + 0x5: luxc1({{ Ft.uw = Mem.ud;}}, {{ EA = Rs + Rt; }}); } } 0x1: decode FUNCTION_LO { - format StoreMemory2 { - 0x0: swxc1({{ EA = Rs + Rt; }},{{ /*Mem.sf = Ft<31:0>; */}}); - 0x1: sdxc1({{ EA = Rs + Rt; }},{{ /*Mem.df = Ft<63:0> */}}); - 0x5: suxc1({{ //Need to make EA<2:0> = 0 - EA = Rs + Rt; - }}, - {{ /*Mem.df = F_t<63:0>;*/}}); + format StoreFloatMemory { + 0x0: swxc1({{ Mem.uw = Ft.uw;}}, {{ EA = Rs + Rt; }}); + 0x1: sdxc1({{ Mem.ud = Ft.ud;}}, {{ EA = Rs + Rt; }}); + 0x5: suxc1({{ Mem.ud = Ft.ud;}}, {{ EA = Rs + Rt; }}); } 0x7: WarnUnimpl::prefx(); @@ -722,49 +1266,44 @@ decode OPCODE_HI default Unknown::unknown() { format BasicOp { 0x4: decode FUNCTION_LO { - 0x0: madd_s({{ Fd.sf = (Fs.sf * Fs.sf) + Fr.sf; }}); - 0x1: madd_d({{ Fd.df = (Fs.df * Fs.df) + Fr.df; }}); + 0x0: madd_s({{ Fd.sf = (Fs.sf * Ft.sf) + Fr.sf; }}); + 0x1: madd_d({{ Fd.df = (Fs.df * Ft.df) + Fr.df; }}); 0x6: madd_ps({{ - //Must Check for Exception Here... Supposed to Operate on Upper and - //Lower Halves Independently but we take simulator shortcut - Fd.df = (Fs.df * Fs.df) + Fr.df; + Fd1.sf = (Fs1.df * Ft1.df) + Fr1.df; + Fd2.sf = (Fs2.df * Ft2.df) + Fr2.df; }}); } 0x5: decode FUNCTION_LO { - 0x0: msub_s({{ Fd.sf = (Fs.sf * Fs.sf) - Fr.sf; }}); - 0x1: msub_d({{ Fd.df = (Fs.df * Fs.df) - Fr.df; }}); + 0x0: msub_s({{ Fd.sf = (Fs.sf * Ft.sf) - Fr.sf; }}); + 0x1: msub_d({{ Fd.df = (Fs.df * Ft.df) - Fr.df; }}); 0x6: msub_ps({{ - //Must Check for Exception Here... Supposed to Operate on Upper and - //Lower Halves Independently but we take simulator shortcut - Fd.df = (Fs.df * Fs.df) - Fr.df; + Fd1.sf = (Fs1.df * Ft1.df) - Fr1.df; + Fd2.sf = (Fs2.df * Ft2.df) - Fr2.df; }}); } 0x6: decode FUNCTION_LO { - 0x0: nmadd_s({{ Fd.sf = (-1 * Fs.sf * Fs.sf) - Fr.sf; }}); - 0x1: nmadd_d({{ Fd.df = (-1 * Fs.df * Fs.df) + Fr.df; }}); + 0x0: nmadd_s({{ Fd.sf = (-1 * Fs.sf * Ft.sf) - Fr.sf; }}); + 0x1: nmadd_d({{ Fd.df = (-1 * Fs.df * Ft.df) + Fr.df; }}); 0x6: nmadd_ps({{ - //Must Check for Exception Here... Supposed to Operate on Upper and - //Lower Halves Independently but we take simulator shortcut - Fd.df = (-1 * Fs.df * Fs.df) + Fr.df; + Fd1.sf = -1 * ((Fs1.df * Ft1.df) + Fr1.df); + Fd2.sf = -1 * ((Fs2.df * Ft2.df) + Fr2.df); }}); } 0x7: decode FUNCTION_LO { - 0x0: nmsub_s({{ Fd.sf = (-1 * Fs.sf * Fs.sf) - Fr.sf; }}); - 0x1: nmsub_d({{ Fd.df = (-1 * Fs.df * Fs.df) - Fr.df; }}); + 0x0: nmsub_s({{ Fd.sf = (-1 * Fs.sf * Ft.sf) - Fr.sf; }}); + 0x1: nmsub_d({{ Fd.df = (-1 * Fs.df * Ft.df) - Fr.df; }}); 0x6: nmsub_ps({{ - //Must Check for Exception Here... Supposed to Operate on Upper and - //Lower Halves Independently but we take simulator shortcut - Fd.df = (-1 * Fs.df * Fs.df) + Fr.df; + Fd1.sf = -1 * ((Fs1.df * Ft1.df) - Fr1.df); + Fd2.sf = -1 * ((Fs2.df * Ft2.df) - Fr2.df); }}); } } } } - //MIPS obsolete instructions format BranchLikely { 0x4: beql({{ cond = (Rs.sw == 0); }}); 0x5: bnel({{ cond = (Rs.sw != 0); }}); @@ -781,59 +1320,63 @@ decode OPCODE_HI default Unknown::unknown() { 0x0: decode FUNCTION_LO { format IntOp { 0x0: madd({{ - int64_t temp1 = xc->readMiscReg(Hi) << 32 | xc->readMiscReg(Lo) >> 32; + int64_t temp1 = (int64_t) HI << 32 | LO; temp1 = temp1 + (Rs.sw * Rt.sw); - xc->setMiscReg(Hi,temp1<63:32>); - xc->setMiscReg(Lo,temp1<31:0>); - }}); + HI = temp1<63:32>; + LO = temp1<31:0>; + }}); 0x1: maddu({{ - int64_t temp1 = xc->readMiscReg(Hi) << 32 | xc->readMiscReg(Lo) >> 32; + int64_t temp1 = (int64_t) HI << 32 | LO; temp1 = temp1 + (Rs.uw * Rt.uw); - xc->setMiscReg(Hi,temp1<63:32>); - xc->setMiscReg(Lo,temp1<31:0>); - }}); + HI = temp1<63:32>; + LO = temp1<31:0>; + }}); 0x2: mul({{ Rd.sw = Rs.sw * Rt.sw; }}); 0x4: msub({{ - int64_t temp1 = xc->readMiscReg(Hi) << 32 | xc->readMiscReg(Lo) >> 32; + int64_t temp1 = (int64_t) HI << 32 | LO; temp1 = temp1 - (Rs.sw * Rt.sw); - xc->setMiscReg(Hi,temp1<63:32>); - xc->setMiscReg(Lo,temp1<31:0>); - }}); + HI = temp1<63:32>; + LO = temp1<31:0>; + }}); 0x5: msubu({{ - int64_t temp1 = xc->readMiscReg(Hi) << 32 | xc->readMiscReg(Lo) >> 32; + int64_t temp1 = (int64_t) HI << 32 | LO; temp1 = temp1 - (Rs.uw * Rt.uw); - xc->setMiscReg(Hi,temp1<63:32>); - xc->setMiscReg(Lo,temp1<31:0>); - }}); + HI = temp1<63:32>; + LO = temp1<31:0>; + }}); } } 0x4: decode FUNCTION_LO { format BasicOp { 0x0: clz({{ - /*int cnt = 0; - int idx = 0; - while ( Rs.uw<idx> != 1) { - cnt++; - idx--; + int cnt = 0; + uint32_t mask = 0x80000000; + for (int i=0; i < 32; i++) { + if( (Rs & mask) == 0) { + cnt++; + } else { + break; + } } - - Rd.uw = cnt;*/ + Rd.uw = cnt; }}); 0x1: clo({{ - /*int cnt = 0; - int idx = 0; - while ( Rs.uw<idx> != 0) { - cnt++; - idx--; + int cnt = 0; + uint32_t mask = 0x80000000; + for (int i=0; i < 32; i++) { + if( (Rs & mask) != 0) { + cnt++; + } else { + break; + } } - - Rd.uw = cnt;*/ + Rd.uw = cnt; }}); } } @@ -847,14 +1390,14 @@ decode OPCODE_HI default Unknown::unknown() { 0x7: decode FUNCTION_HI { 0x0: decode FUNCTION_LO { - format WarnUnimpl { + format FailUnimpl { 0x1: ext(); 0x4: ins(); } } 0x1: decode FUNCTION_LO { - format WarnUnimpl { + format FailUnimpl { 0x0: fork(); 0x1: yield(); } @@ -864,16 +1407,16 @@ decode OPCODE_HI default Unknown::unknown() { //Table A-10 MIPS32 BSHFL Encoding of sa Field 0x4: decode SA { - 0x02: WarnUnimpl::wsbh(); + 0x02: FailUnimpl::wsbh(); format BasicOp { - 0x10: seb({{ Rd.sw = /* sext32(Rt<7>,24) | */ Rt<7:0>}}); - 0x18: seh({{ Rd.sw = /* sext32(Rt<15>,16) | */ Rt<15:0>}}); + 0x10: seb({{ Rd.sw = Rt.sw<7:0>}}); + 0x18: seh({{ Rd.sw = Rt.sw<15:0>}}); } } 0x6: decode FUNCTION_LO { - 0x7: BasicOp::rdhwr({{ /*Rt = xc->hwRegs[RD];*/ }}); + 0x7: FailUnimpl::rdhwr();//{{ /*Rt = xc->hwRegs[RD];*/ }} } } } @@ -882,23 +1425,238 @@ decode OPCODE_HI default Unknown::unknown() { format LoadMemory { 0x0: lb({{ Rt.sw = Mem.sb; }}); 0x1: lh({{ Rt.sw = Mem.sh; }}); - 0x2: lwl({{ Rt.sw = Mem.sw; }});//, WordAlign); - 0x3: lw({{ Rt.sw = Mem.sb; }}); + + 0x2: lwl({{ + uint32_t mem_word = Mem.uw; + uint32_t unalign_addr = Rs + disp; + uint32_t offset = unalign_addr & 0x00000003; +#if BYTE_ORDER == BIG_ENDIAN + switch(offset) + { + case 0: + Rt = mem_word; + break; + + case 1: + Rt &= 0x000F; + Rt |= (mem_word << 4); + break; + + case 2: + Rt &= 0x00FF; + Rt |= (mem_word << 8); + break; + + case 3: + Rt &= 0x0FFF; + Rt |= (mem_word << 12); + break; + + default: + panic("lwl: bad offset"); + } +#elif BYTE_ORDER == LITTLE_ENDIAN + switch(offset) + { + case 0: + Rt &= 0x0FFF; + Rt |= (mem_word << 12); + break; + + case 1: + Rt &= 0x00FF; + Rt |= (mem_word << 8); + break; + + case 2: + Rt &= 0x000F; + Rt |= (mem_word << 4); + break; + + case 3: + Rt = mem_word; + break; + + default: + panic("lwl: bad offset"); + } +#endif + }}, {{ EA = (Rs + disp) & ~3; }}); + + 0x3: lw({{ Rt.sw = Mem.sw; }}); 0x4: lbu({{ Rt.uw = Mem.ub; }}); 0x5: lhu({{ Rt.uw = Mem.uh; }}); - 0x6: lwr({{ Rt.uw = Mem.uw; }});//, WordAlign); + 0x6: lwr({{ + uint32_t mem_word = Mem.uw; + uint32_t unalign_addr = Rs + disp; + uint32_t offset = unalign_addr & 0x00000003; + +#if BYTE_ORDER == BIG_ENDIAN + switch(offset) + { + case 0: Rt &= 0xFFF0; Rt |= (mem_word >> 12); break; + case 1: Rt &= 0xFF00; Rt |= (mem_word >> 8); break; + case 2: Rt &= 0xF000; Rt |= (mem_word >> 4); break; + case 3: Rt = mem_word; break; + default: panic("lwr: bad offset"); + } +#elif BYTE_ORDER == LITTLE_ENDIAN + switch(offset) + { + case 0: Rt = mem_word; break; + case 1: Rt &= 0xF000; Rt |= (mem_word >> 4); break; + case 2: Rt &= 0xFF00; Rt |= (mem_word >> 8); break; + case 3: Rt &= 0xFFF0; Rt |= (mem_word >> 12); break; + default: panic("lwr: bad offset"); + } +#endif + }}, + {{ EA = (Rs + disp) & ~3; }}); } - - 0x7: FailUnimpl::reserved(); } 0x5: decode OPCODE_LO default FailUnimpl::reserved() { format StoreMemory { 0x0: sb({{ Mem.ub = Rt<7:0>; }}); 0x1: sh({{ Mem.uh = Rt<15:0>; }}); - 0x2: swl({{ Mem.ub = Rt<31:0>; }});//,WordAlign); - 0x3: sw({{ Mem.ub = Rt<31:0>; }}); - 0x6: swr({{ Mem.ub = Rt<31:0>; }});//,WordAlign); + 0x2: swl({{ + uint32_t mem_word = 0; + uint32_t aligned_addr = (Rs + disp) & ~3; + uint32_t unalign_addr = Rs + disp; + uint32_t offset = unalign_addr & 0x00000003; + + DPRINTF(IEW,"Execute: aligned=0x%x unaligned=0x%x\n offset=0x%x", + aligned_addr,unalign_addr,offset); + + fault = xc->read(aligned_addr, (uint32_t&)mem_word, memAccessFlags); + +#if BYTE_ORDER == BIG_ENDIAN + switch(offset) + { + case 0: + Mem = Rt; + break; + + case 1: + mem_word &= 0xF000; + mem_word |= (Rt >> 4); + Mem = mem_word; + break; + + case 2: + mem_word &= 0xFF00; + mem_word |= (Rt >> 8); + Mem = mem_word; + break; + + case 3: + mem_word &= 0xFFF0; + mem_word |= (Rt >> 12); + Mem = mem_word; + break; + + default: + panic("swl: bad offset"); + } +#elif BYTE_ORDER == LITTLE_ENDIAN + switch(offset) + { + case 0: + mem_word &= 0xFFF0; + mem_word |= (Rt >> 12); + Mem = mem_word; + break; + + case 1: + mem_word &= 0xFF00; + mem_word |= (Rt >> 8); + Mem = mem_word; + break; + + case 2: + mem_word &= 0xF000; + mem_word |= (Rt >> 4); + Mem = mem_word; + break; + + case 3: + Mem = Rt; + break; + + default: + panic("swl: bad offset"); + } +#endif + }},{{ EA = (Rs + disp) & ~3; }},mem_flags = NO_ALIGN_FAULT); + + 0x3: sw({{ Mem.uw = Rt<31:0>; }}); + + 0x6: swr({{ + uint32_t mem_word = 0; + uint32_t aligned_addr = (Rs + disp) & ~3; + uint32_t unalign_addr = Rs + disp; + uint32_t offset = unalign_addr & 0x00000003; + + fault = xc->read(aligned_addr, (uint32_t&)mem_word, memAccessFlags); + +#if BYTE_ORDER == BIG_ENDIAN + switch(offset) + { + case 0: + mem_word &= 0x0FFF; + mem_word |= (Rt << 12); + Mem = mem_word; + break; + + case 1: + mem_word &= 0x00FF; + mem_word |= (Rt << 8); + Mem = mem_word; + break; + + case 2: + mem_word &= 0x000F; + mem_word |= (Rt << 4); + Mem = mem_word; + break; + + case 3: + Mem = Rt; + break; + + default: + panic("swr: bad offset"); + } +#elif BYTE_ORDER == LITTLE_ENDIAN + switch(offset) + { + case 0: + Mem = Rt; + break; + + case 1: + mem_word &= 0x000F; + mem_word |= (Rt << 4); + Mem = mem_word; + break; + + case 2: + mem_word &= 0x00FF; + mem_word |= (Rt << 8); + Mem = mem_word; + break; + + case 3: + mem_word &= 0x0FFF; + mem_word |= (Rt << 12); + Mem = mem_word; + break; + + default: + panic("swr: bad offset"); + } +#endif + }},{{ EA = (Rs + disp) & ~3;}},mem_flags = NO_ALIGN_FAULT); } format WarnUnimpl { @@ -908,21 +1666,21 @@ decode OPCODE_HI default Unknown::unknown() { } 0x6: decode OPCODE_LO default FailUnimpl::reserved() { - 0x0: WarnUnimpl::ll(); + 0x0: LoadMemory::ll({{Rt.uw = Mem.uw}},mem_flags=LOCKED); - format LoadMemory { - 0x1: lwc1({{ /*F_t<31:0> = Mem.sf; */}}); - 0x5: ldc1({{ /*F_t<63:0> = Mem.df; */}}); + format LoadFloatMemory { + 0x1: lwc1({{ Ft.uw = Mem.uw; }}); + 0x5: ldc1({{ Ft.ud = Mem.ud; }}); } } 0x7: decode OPCODE_LO default FailUnimpl::reserved() { - 0x0: WarnUnimpl::sc(); + 0x0: StoreMemory::sc({{ Mem.uw = Rt.uw; Rt.uw = 1; }}); - format StoreMemory { - 0x1: swc1({{ //Mem.sf = Ft<31:0>; }}); - 0x5: sdc1({{ //Mem.df = Ft<63:0>; }}); + format StoreFloatMemory { + 0x1: swc1({{ Mem.uw = Ft.uw; }}); + 0x5: sdc1({{ Mem.ud = Ft.ud; }}); } } } diff --git a/arch/mips/isa/formats.isa b/arch/mips/isa/formats.isa deleted file mode 100644 index f7a9e4ce2..000000000 --- a/arch/mips/isa/formats.isa +++ /dev/null @@ -1,35 +0,0 @@ -// -*- mode:c++ -*- - -//Templates from this format are used later -//Include the basic format -##include "m5/arch/mips/isa/formats/basic.isa" - -//Include the basic format -##include "m5/arch/mips/isa/formats/noop.isa" - -//Include utility formats/functions -##include "m5/arch/mips/isa/formats/util.isa" - -//Include the cop0 formats -##include "m5/arch/mips/isa/formats/cop0.isa" - -//Include the integer formats -##include "m5/arch/mips/isa/formats/int.isa" - -//Include the floatOp format -##include "m5/arch/mips/isa/formats/fp.isa" - -//Include the mem format -##include "m5/arch/mips/isa/formats/mem.isa" - -//Include the trap format -##include "m5/arch/mips/isa/formats/trap.isa" - -//Include the branch format -##include "m5/arch/mips/isa/formats/branch.isa" - -//Include the noop format -##include "m5/arch/mips/isa/formats/unimp.isa" - -//Include the noop format -##include "m5/arch/mips/isa/formats/unknown.isa" diff --git a/arch/mips/isa/formats/branch.isa b/arch/mips/isa/formats/branch.isa index 0d2ad7855..8cfa37a20 100644 --- a/arch/mips/isa/formats/branch.isa +++ b/arch/mips/isa/formats/branch.isa @@ -179,7 +179,7 @@ output decoder {{ ss << ","; } - Addr target = pc + 8 + disp; + Addr target = pc + 4 + disp; std::string str; if (symtab && symtab->findSymbol(target, str)) @@ -187,6 +187,12 @@ output decoder {{ else ccprintf(ss, "0x%x", target); + string inst_name = mnemonic; + + if (inst_name.substr(inst_name.length()-2,inst_name.length()) == "al"){ + ccprintf(ss, " (r31=0x%x)",pc+8); + } + return ss.str(); } @@ -255,7 +261,7 @@ def format Branch(code,*flags) {{ #Add Link Code if Link instruction strlen = len(name) if name[strlen-2:] == 'al': - code += 'r31 = NNPC;\n' + code += 'R31 = NNPC;\n' #Condition code code = 'bool cond;\n' + code @@ -265,8 +271,6 @@ def format Branch(code,*flags) {{ code += ' NNPC = NNPC;\n' code += '} \n' - code += 'cout << hex << "NPC: " << NPC << " + " << disp << " = " << NNPC << endl;' - iop = InstObjParams(name, Name, 'Branch', CodeBlock(code), ('IsDirectControl', 'IsCondControl')) @@ -281,7 +285,7 @@ def format BranchLikely(code,*flags) {{ #Add Link Code if Link instruction strlen = len(name) if name[strlen-3:] == 'all': - code += 'r31 = NNPC;\n' + code += 'R31 = NNPC;\n' #Condition code code = 'bool cond;\n' + code @@ -303,10 +307,8 @@ def format Jump(code,*flags) {{ #Add Link Code if Link instruction strlen = len(name) if strlen > 1 and name[1:] == 'al': - code = 'r31 = NNPC;\n' + code + code = 'R31 = NNPC;\n' + code - #code += 'if(NNPC == 0x80000638) { NNPC = r31; cout << "SKIPPING JUMP TO SIM_GET_MEM_CONF" << endl;}' - #code += 'target = NNPC;' iop = InstObjParams(name, Name, 'Jump', CodeBlock(code),\ ('IsIndirectControl', 'IsUncondControl')) diff --git a/arch/mips/isa/formats/formats.isa b/arch/mips/isa/formats/formats.isa new file mode 100644 index 000000000..7d493ffae --- /dev/null +++ b/arch/mips/isa/formats/formats.isa @@ -0,0 +1,35 @@ +// -*- mode:c++ -*- + +//Templates from this format are used later +//Include the basic format +##include "basic.isa" + +//Include the basic format +##include "noop.isa" + +//Include utility functions +##include "util.isa" + +//Include the cop0 formats +##include "cop0.isa" + +//Include the integer formats +##include "int.isa" + +//Include the floatOp format +##include "fp.isa" + +//Include the mem format +##include "mem.isa" + +//Include the trap format +##include "trap.isa" + +//Include the branch format +##include "branch.isa" + +//Include the noop format +##include "unimp.isa" + +//Include the noop format +##include "unknown.isa" diff --git a/arch/mips/isa/formats/fp.isa b/arch/mips/isa/formats/fp.isa index 34b71acf7..9f2c24755 100644 --- a/arch/mips/isa/formats/fp.isa +++ b/arch/mips/isa/formats/fp.isa @@ -30,7 +30,7 @@ output decoder {{ }}; -// Primary format for integer operate instructions: +// Primary format for float operate instructions: def format FloatOp(code, *flags) {{ iop = InstObjParams(name, Name, 'MipsStaticInst', CodeBlock(code), flags) header_output = BasicDeclare.subst(iop) @@ -39,7 +39,35 @@ def format FloatOp(code, *flags) {{ exec_output = BasicExecute.subst(iop) }}; -// Primary format for integer operate instructions: +def format FloatCompareOp(code, *flags) {{ + code = 'bool cond;\n' + code + code += 'FCSR = makeCCVector(FCSR, CC,cond);\n' + iop = InstObjParams(name, Name, 'MipsStaticInst', CodeBlock(code), flags) + header_output = BasicDeclare.subst(iop) + decoder_output = BasicConstructor.subst(iop) + decode_block = BasicDecode.subst(iop) + exec_output = BasicExecute.subst(iop) +}}; + +def format FloatCompareWithXcptOp(code, *flags) {{ + code = 'bool cond;\n' + code + code += 'FCSR = makeCCVector(FCSR, CC,cond);\n' + iop = InstObjParams(name, Name, 'MipsStaticInst', CodeBlock(code), flags) + header_output = BasicDeclare.subst(iop) + decoder_output = BasicConstructor.subst(iop) + decode_block = BasicDecode.subst(iop) + exec_output = BasicExecute.subst(iop) +}}; + +def format FloatConvertOp(code, *flags) {{ + iop = InstObjParams(name, Name, 'MipsStaticInst', CodeBlock(code), flags) + header_output = BasicDeclare.subst(iop) + decoder_output = BasicConstructor.subst(iop) + decode_block = BasicDecode.subst(iop) + exec_output = BasicExecute.subst(iop) +}}; + +// Primary format for float64 operate instructions: def format Float64Op(code, *flags) {{ iop = InstObjParams(name, Name, 'MipsStaticInst', CodeBlock(code), flags) header_output = BasicDeclare.subst(iop) @@ -47,3 +75,35 @@ def format Float64Op(code, *flags) {{ decode_block = BasicDecode.subst(iop) exec_output = BasicExecute.subst(iop) }}; + +def format Float64ConvertOp(code, *flags) {{ + code = 'bool cond;\n' + code + code += 'FCSR = makeCCVector(FCSR, CC,cond);\n' + iop = InstObjParams(name, Name, 'MipsStaticInst', CodeBlock(code), flags) + header_output = BasicDeclare.subst(iop) + decoder_output = BasicConstructor.subst(iop) + decode_block = BasicDecode.subst(iop) + exec_output = BasicExecute.subst(iop) +}}; + +def format FloatPSCompareOp(code, *flags) {{ + code = 'bool cond1;\nbool cond2;\n' + code + code += 'FCSR = makeCCVector(FCSR, CC+1, cond1);\n' + code += 'FCSR = makeCCVector(FCSR, CC, cond2);\n' + iop = InstObjParams(name, Name, 'MipsStaticInst', CodeBlock(code), flags) + header_output = BasicDeclare.subst(iop) + decoder_output = BasicConstructor.subst(iop) + decode_block = BasicDecode.subst(iop) + exec_output = BasicExecute.subst(iop) +}}; + +def format FloatPSCompareWithXcptOp(code, *flags) {{ + code = 'bool cond1;\nbool cond2;\n' + code + code += 'FCSR = makeCCVector(FCSR, CC+1, cond1);\n' + code += 'FCSR = makeCCVector(FCSR, CC, cond2);\n' + iop = InstObjParams(name, Name, 'MipsStaticInst', CodeBlock(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/arch/mips/isa/formats/int.isa b/arch/mips/isa/formats/int.isa index a47844bee..7d38b9ff5 100644 --- a/arch/mips/isa/formats/int.isa +++ b/arch/mips/isa/formats/int.isa @@ -29,17 +29,19 @@ output header {{ { protected: - int32_t imm; + int16_t imm; + int32_t sextImm; + uint32_t zextImm; /// Constructor IntImmOp(const char *mnem, MachInst _machInst, OpClass __opClass) : - MipsStaticInst(mnem, _machInst, __opClass),imm(INTIMM) + MipsStaticInst(mnem, _machInst, __opClass),imm(INTIMM), + sextImm(INTIMM),zextImm(0x0000FFFF & INTIMM) { //If Bit 15 is 1 then Sign Extend - int32_t temp = imm & 0x00008000; - + int32_t temp = sextImm & 0x00008000; if (temp > 0 && mnemonic != "lui") { - imm |= 0xFFFF0000; + sextImm |= 0xFFFF0000; } } @@ -62,10 +64,9 @@ output decoder {{ // it's generally implicit if (_numDestRegs > 0) { printReg(ss, _destRegIdx[0]); + ss << ","; } - ss << ","; - // just print the first two source regs... if there's // a third one, it's a read-modify-write dest (Rc), // e.g. for CMOVxx @@ -99,9 +100,9 @@ output decoder {{ } if( mnemonic == "lui") - ccprintf(ss, "%08p ", imm); + ccprintf(ss, "%08p ", sextImm); else - ss << (int) imm; + ss << (int) sextImm; return ss.str(); } diff --git a/arch/mips/isa/formats/mem.isa b/arch/mips/isa/formats/mem.isa index 8a07e63d4..e2afc7252 100644 --- a/arch/mips/isa/formats/mem.isa +++ b/arch/mips/isa/formats/mem.isa @@ -276,8 +276,7 @@ def template LoadCompleteAcc {{ Fault fault = NoFault; %(fp_enable_check)s; - %(op_src_decl)s; - %(op_dest_decl)s; + %(op_decl)s; memcpy(&Mem, data, sizeof(Mem)); @@ -375,8 +374,7 @@ def template StoreInitiateAcc {{ uint64_t write_result = 0; %(fp_enable_check)s; - %(op_src_decl)s; - %(op_dest_decl)s; + %(op_decl)s; %(op_rd)s; %(ea_code)s; @@ -449,21 +447,27 @@ def format StoreMemory(memacc_code, ea_code = {{ EA = Rs + disp; }}, }}; //FP loads are offloaded to these formats for now ... -def format LoadMemory2(ea_code = {{ EA = Rs + disp; }}, memacc_code = {{ }}, - mem_flags = [], inst_flags = []) {{ +def format LoadFloatMemory(memacc_code, ea_code = {{ EA = Rs + disp; }}, + mem_flags = [], inst_flags = []) {{ (header_output, decoder_output, decode_block, exec_output) = \ LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags, - decode_template = LoadNopCheckDecode, + decode_template = BasicDecode, exec_template_base = 'Load') }}; -//FP stores are offloaded to these formats for now ... -def format StoreMemory2(ea_code = {{ EA = Rs + disp; }},memacc_code = {{ }}, - mem_flags = [], inst_flags = []) {{ +def format StoreFloatMemory(memacc_code, ea_code = {{ EA = Rs + disp; }}, + mem_flags = [], inst_flags = []) {{ (header_output, decoder_output, decode_block, exec_output) = \ LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags, - decode_template = LoadNopCheckDecode, exec_template_base = 'Store') }}; + +def format UnalignedStore(memacc_code, postacc_code, + ea_code = {{ EA = Rb + disp; }}, + mem_flags = [], inst_flags = []) {{ + (header_output, decoder_output, decode_block, exec_output) = \ + LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags, + postacc_code, exec_template_base = 'Store') +}}; diff --git a/arch/mips/isa/formats/noop.isa b/arch/mips/isa/formats/noop.isa index d35179005..2aa4816e3 100644 --- a/arch/mips/isa/formats/noop.isa +++ b/arch/mips/isa/formats/noop.isa @@ -88,3 +88,7 @@ def format BasicOperateWithNopCheck(code, *opt_args) {{ exec_output = BasicExecute.subst(iop) }}; +def format Nop() {{ + decode_block = 'return new Nop(\"sll r0,r0,0\",machInst);\n' +}}; + diff --git a/arch/mips/isa/formats/unimp.isa b/arch/mips/isa/formats/unimp.isa index adbd5b5b1..475a88752 100644 --- a/arch/mips/isa/formats/unimp.isa +++ b/arch/mips/isa/formats/unimp.isa @@ -110,8 +110,9 @@ output exec {{ Trace::InstRecord *traceData) const { panic("attempt to execute unimplemented instruction '%s' " - "(inst 0x%08x, opcode 0x%x)", mnemonic, machInst, OPCODE); - return UnimplementedOpcodeFault; + "(inst 0x%08x, opcode 0x%x, binary:%s)", mnemonic, machInst, OPCODE, + inst2string(machInst)); + return new UnimplementedOpcodeFault; } Fault diff --git a/arch/mips/isa/formats/unknown.isa b/arch/mips/isa/formats/unknown.isa index 4601b3684..ba83c007e 100644 --- a/arch/mips/isa/formats/unknown.isa +++ b/arch/mips/isa/formats/unknown.isa @@ -26,12 +26,34 @@ // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +output header {{ + std::string inst2string(MachInst machInst); +}}; output decoder {{ + +std::string inst2string(MachInst machInst) +{ + 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; +} + std::string Unknown::generateDisassembly(Addr pc, const SymbolTable *symtab) const { - return csprintf("%-10s (inst 0x%x, opcode 0x%x)", - "unknown", machInst, OPCODE); + return csprintf("%-10s (inst 0x%x, opcode 0x%x, binary:%s)", + "unknown", machInst, OPCODE, inst2string(machInst)); } }}; @@ -41,8 +63,8 @@ output exec {{ Trace::InstRecord *traceData) const { panic("attempt to execute unknown instruction " - "(inst 0x%08x, opcode 0x%x)", machInst, OPCODE); - return UnimplementedOpcodeFault; + "(inst 0x%08x, opcode 0x%x, binary: %s)", machInst, OPCODE, inst2string(machInst)); + return new UnimplementedOpcodeFault; } }}; diff --git a/arch/mips/isa/formats/util.isa b/arch/mips/isa/formats/util.isa index db4bf204a..615160931 100644 --- a/arch/mips/isa/formats/util.isa +++ b/arch/mips/isa/formats/util.isa @@ -93,8 +93,7 @@ def LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags, output exec {{ -using namespace MipsISA; - + using namespace MipsISA; /// CLEAR ALL CPU INST/EXE HAZARDS inline void @@ -124,25 +123,7 @@ using namespace MipsISA; } #endif - double convert_and_round(float w, int x, int y, int z) - { - double temp = .34000; - - return temp; - } - enum FPTypes{ - FP_SINGLE, - FP_DOUBLE, - FP_LONG, - FP_PS_LO, - FP_PS_HI, - FP_WORD, - RND_NEAREST, - RND_ZERO, - RND_UP, - RND_DOWN - }; }}; diff --git a/arch/mips/isa/includes.isa b/arch/mips/isa/includes.isa index da919be00..9c370fbe3 100644 --- a/arch/mips/isa/includes.isa +++ b/arch/mips/isa/includes.isa @@ -9,21 +9,28 @@ output header {{ #include <iomanip> #include "cpu/static_inst.hh" -#include "mem/mem_req.hh" // some constructors use MemReq flags +#include "arch/mips/isa_traits.hh" }}; output decoder {{ +#include "arch/mips/isa_traits.hh" #include "base/cprintf.hh" #include "base/loader/symtab.hh" #include "cpu/exec_context.hh" // for Jump::branchTarget() +#include "arch/mips/faults.hh" +#include "arch/mips/isa_traits.hh" #include <math.h> #if defined(linux) #include <fenv.h> #endif + +using namespace MipsISA; }}; output exec {{ +#include "arch/mips/faults.hh" +#include "arch/mips/isa_traits.hh" #include <math.h> #if defined(linux) #include <fenv.h> @@ -35,5 +42,7 @@ output exec {{ #include "cpu/base.hh" #include "cpu/exetrace.hh" #include "sim/sim_exit.hh" + +using namespace MipsISA; }}; diff --git a/arch/mips/isa/main.isa b/arch/mips/isa/main.isa index 411e398b4..01d81323e 100644 --- a/arch/mips/isa/main.isa +++ b/arch/mips/isa/main.isa @@ -26,7 +26,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. -##include "m5/arch/mips/isa/includes.isa" +##include "includes.isa" //////////////////////////////////////////////////////////////////// // @@ -37,16 +37,16 @@ namespace MipsISA; //Include the bitfield definitions -##include "m5/arch/mips/isa/bitfields.isa" +##include "bitfields.isa" //Include the operand_types and operand definitions -##include "m5/arch/mips/isa/operands.isa" +##include "operands.isa" //Include the base class for mips instructions, and some support code -##include "m5/arch/mips/isa/base.isa" +##include "base.isa" //Include the definitions for the instruction formats -##include "m5/arch/mips/isa/formats.isa" +##include "formats/formats.isa" //Include the decoder definition -##include "m5/arch/mips/isa/decoder.isa" +##include "decoder.isa" diff --git a/arch/mips/isa/operands.isa b/arch/mips/isa/operands.isa index 13870337b..0f9c74b48 100644 --- a/arch/mips/isa/operands.isa +++ b/arch/mips/isa/operands.isa @@ -13,21 +13,49 @@ def operand_types {{ }}; def operands {{ + #General Purpose Integer Reg Operands 'Rd': ('IntReg', 'uw', 'RD', 'IsInteger', 1), 'Rs': ('IntReg', 'uw', 'RS', 'IsInteger', 2), 'Rt': ('IntReg', 'uw', 'RT', 'IsInteger', 3), - 'r31': ('IntReg', 'uw','R31','IsInteger', 4), - 'R0': ('IntReg', 'uw','R0', 'IsInteger', 5), + #Operands used for Link or Syscall Insts + 'R31': ('IntReg', 'uw','31','IsInteger', 4), + 'R2': ('IntReg', 'uw','2', 'IsInteger', 5), + + #Special Integer Reg operands + 'HI': ('IntReg', 'uw','32', 'IsInteger', 6), + 'LO': ('IntReg', 'uw','33', 'IsInteger', 7), + + #Immediate Value operand 'IntImm': ('IntReg', 'uw', 'INTIMM', 'IsInteger', 3), + #Floating Point Reg Operands 'Fd': ('FloatReg', 'sf', 'FD', 'IsFloating', 1), 'Fs': ('FloatReg', 'sf', 'FS', 'IsFloating', 2), 'Ft': ('FloatReg', 'sf', 'FT', 'IsFloating', 3), 'Fr': ('FloatReg', 'sf', 'FR', 'IsFloating', 3), - 'Mem': ('Mem', 'ud', None, ('IsMemRef', 'IsLoad', 'IsStore'), 4), + #Special Floating Point Control Reg Operands + 'FIR': ('FloatReg', 'uw', '32', 'IsFloating', 1), + 'FCCR': ('FloatReg', 'uw', '33', 'IsFloating', 2), + 'FEXR': ('FloatReg', 'uw', '34', 'IsFloating', 3), + 'FENR': ('FloatReg', 'uw', '35', 'IsFloating', 3), + 'FCSR': ('FloatReg', 'uw', '36', 'IsFloating', 3), + + #Operands For Paired Singles FP Operations + 'Fd1': ('FloatReg', 'sf', 'FD', 'IsFloating', 4), + 'Fd2': ('FloatReg', 'sf', 'FD+1', 'IsFloating', 4), + 'Fs1': ('FloatReg', 'sf', 'FS', 'IsFloating', 5), + 'Fs2': ('FloatReg', 'sf', 'FS+1', 'IsFloating', 5), + 'Ft1': ('FloatReg', 'sf', 'FT', 'IsFloating', 6), + 'Ft2': ('FloatReg', 'sf', 'FT+1', 'IsFloating', 6), + 'Fr1': ('FloatReg', 'sf', 'FR', 'IsFloating', 7), + 'Fr2': ('FloatReg', 'sf', 'FR+1', 'IsFloating', 7), + + #Memory Operand + 'Mem': ('Mem', 'uw', None, ('IsMemRef', 'IsLoad', 'IsStore'), 4), + #Program Counter Operands 'NPC': ('NPC', 'uw', None, ( None, None, 'IsControl' ), 4), 'NNPC':('NNPC', 'uw', None, ( None, None, 'IsControl' ), 4) }}; diff --git a/arch/mips/isa_traits.cc b/arch/mips/isa_traits.cc index d01fa6bd4..216a6e2ec 100644 --- a/arch/mips/isa_traits.cc +++ b/arch/mips/isa_traits.cc @@ -30,296 +30,109 @@ #include "config/full_system.hh" #include "cpu/static_inst.hh" #include "sim/serialize.hh" +#include "base/bitfield.hh" using namespace MipsISA; +using namespace std; -//Function now Obsolete in current state. -//If anyting this should return the correct miscreg index -//but that is handled implicitly with enums anyway void -MipsISA::getMiscRegIdx(int reg_name,int &idx, int &sel) +MipsISA::copyRegs(ExecContext *src, ExecContext *dest) { - switch(reg_name) - { - case Index: idx = 0; sel = 0; break; //0-0 Index into the TLB array - case MVPControl: idx = 0; sel = 1; break; //0-1 Per-processor register containing global - case MVPConf0: idx = 0; sel = 2; break; //0-2 Per-processor register containing global - case MVPConf1: idx = 0; sel = 3; break; //0-3 Per-processor register containing global - case Random: idx = 1; sel = 3; break; //1-0 Randomly generated index into the TLB array - case VPEControl: idx = 1; sel = 1; break; //1-1 Per-VPE register containing relatively volatile - //thread configuration data - case VPEConf0: idx = 1; sel = 2; break; //1-2 Per-VPE multi-thread configuration - //information - case VPEConf1: idx = 1; sel = 3; break; //1-3 Per-VPE multi-thread configuration - //information - case YQMask: idx = 1; sel = 4; break; //Per-VPE register defining which YIELD - //qualifier bits may be used without generating - //an exception - case VPESchedule: idx = 1; sel = 5; break; - case VPEScheFBack: idx = 1; sel = 6; break; - case VPEOpt: idx = 1; sel = 7; break; - case EntryLo0: idx = 1; sel = 5; break; - case TCStatus: idx = 1; sel = 5; break; - case TCBind: idx = 1; sel = 5; break; - case TCRestart: idx = 1; sel = 5; break; - case TCHalt: idx = 1; sel = 5; break; - case TCContext: idx = 1; sel = 5; break; - case TCSchedule: idx = 1; sel = 5; break; - case TCScheFBack: panic("Accessing Unimplemented CP0 Register"); break; - case EntryLo1: panic("Accessing Unimplemented CP0 Register"); break; - case Context: panic("Accessing Unimplemented CP0 Register"); break; - case ContextConfig: panic("Accessing Unimplemented CP0 Register"); break; - //case PageMask: panic("Accessing Unimplemented CP0 Register"); break; - case PageGrain: panic("Accessing Unimplemented CP0 Register"); break; - case Wired: panic("Accessing Unimplemented CP0 Register"); break; - case SRSConf0: panic("Accessing Unimplemented CP0 Register"); break; - case SRSConf1: panic("Accessing Unimplemented CP0 Register"); break; - case SRSConf2: panic("Accessing Unimplemented CP0 Register"); break; - case SRSConf3: panic("Accessing Unimplemented CP0 Register"); break; - case SRSConf4: panic("Accessing Unimplemented CP0 Register"); break; - case BadVAddr: panic("Accessing Unimplemented CP0 Register"); break; - case Count: panic("Accessing Unimplemented CP0 Register"); break; - case EntryHi: panic("Accessing Unimplemented CP0 Register"); break; - case Compare: panic("Accessing Unimplemented CP0 Register"); break; - case Status: idx = 12; sel = 0; break; //12-0 Processor status and control - case IntCtl: idx = 12; sel = 1; break; //12-1 Interrupt system status and control - case SRSCtl: idx = 12; sel = 2; break; //12-2 Shadow register set status and control - case SRSMap: idx = 12; sel = 3; break; //12-3 Shadow set IPL mapping - case Cause: idx = 13; sel = 0; break; //13-0 Cause of last general exception - case EPC: idx = 14; sel = 0; break; //14-0 Program counter at last exception - case PrId: idx = 15; sel = 0; break; //15-0 Processor identification and revision - case EBase: idx = 15; sel = 1; break; //15-1 Exception vector base register - case Config: panic("Accessing Unimplemented CP0 Register"); break; - case Config1: panic("Accessing Unimplemented CP0 Register"); break; - case Config2: panic("Accessing Unimplemented CP0 Register"); break; - case Config3: panic("Accessing Unimplemented CP0 Register"); break; - case LLAddr: panic("Accessing Unimplemented CP0 Register"); break; - case WatchLo: panic("Accessing Unimplemented CP0 Register"); break; - case WatchHi: panic("Accessing Unimplemented CP0 Register"); break; - case Debug: panic("Accessing Unimplemented CP0 Register"); break; - case TraceControl1: panic("Accessing Unimplemented CP0 Register"); break; - case TraceControl2: panic("Accessing Unimplemented CP0 Register"); break; - case UserTraceData: panic("Accessing Unimplemented CP0 Register"); break; - case TraceBPC: panic("Accessing Unimplemented CP0 Register"); break; - case DEPC: panic("Accessing Unimplemented CP0 Register"); break; - case PerfCnt: panic("Accessing Unimplemented CP0 Register"); break; - case ErrCtl: panic("Accessing Unimplemented CP0 Register"); break; - case CacheErr0: panic("Accessing Unimplemented CP0 Register"); break; - case CacheErr1: panic("Accessing Unimplemented CP0 Register"); break; - case CacheErr2: panic("Accessing Unimplemented CP0 Register"); break; - case CacheErr3: panic("Accessing Unimplemented CP0 Register"); break; - case TagLo: panic("Accessing Unimplemented CP0 Register"); break; - case DataLo: panic("Accessing Unimplemented CP0 Register"); break; - case TagHi: panic("Accessing Unimplemented CP0 Register"); break; - case DataHi: panic("Accessing Unimplemented CP0 Register"); break; - case ErrorEPC: panic("Accessing Unimplemented CP0 Register"); break; + /*fpcr = xc->readMiscReg(MipsISA::Fpcr_DepTag); + uniq = xc->readMiscReg(MipsISA::Uniq_DepTag); + lock_flag = xc->readMiscReg(MipsISA::Lock_Flag_DepTag); + lock_addr = xc->readMiscReg(MipsISA::Lock_Addr_DepTag); - default: - panic("Accessing Unimplemented Misc. Register"); - } +#if FULL_SYSTEM + copyIprs(xc); + #endif*/ } -void RegFile::coldReset() +void +MipsISA::MiscRegFile::copyMiscRegs(ExecContext *xc) { - //CP0 Random Reg: - //Randomly generated index into the TLB array - miscRegs[Random] = 0x0000003f; - - //CP0 Wired Reg. - miscRegs[Wired] = 0x0000000; - - //CP0 HWRENA - miscRegs[HWRena] = 0x0000000; - - //CP0 Status Reg. - miscRegs[Status] = 0x0400004; - - //CP0 INTCNTL - miscRegs[IntCtl] = 0xfc00000; - - //CP0 SRSCNTL - miscRegs[SRSCtl] = 0x0c00000; - - //CP0 SRSMAP - miscRegs[SRSMap] = 0x0000000; - - //CP0 Cause - miscRegs[Cause] = 0x0000000; - - //CP0 Processor ID - miscRegs[PrId] = 0x0019300; - - //CP0 EBASE - miscRegs[EBase] = 0x8000000; - - //CP0 Config Reg. - miscRegs[Config] = 0x80040482; - - //CP0 Config 1 Reg. - miscRegs[Config1] = 0xfee3719e; - - //CP0 Config 2 Reg. - miscRegs[Config2] = 0x8000000; - - //CP0 Config 3 Reg. - miscRegs[Config3] = 0x0000020; - - //CP0 Config 7 Reg. - miscRegs[Config7] = 0x0000000; - - //CP0 Debug - miscRegs[Debug] = 0x0201800; - - //CP0 PERFCNTL1 - miscRegs[PerfCnt0] = 0x0000000; - - //CP0 PERFCNTL2 - miscRegs[PerfCnt1] = 0x0000000; + /*fpcr = xc->readMiscReg(MipsISA::Fpcr_DepTag); + uniq = xc->readMiscReg(MipsISA::Uniq_DepTag); + lock_flag = xc->readMiscReg(MipsISA::Lock_Flag_DepTag); + lock_addr = xc->readMiscReg(MipsISA::Lock_Addr_DepTag); + #endif*/ } -void RegFile::createCP0Regs() +uint64_t +MipsISA::fpConvert(double fp_val, ConvertType cvt_type) { -//Resize Coprocessor Register Banks to -// the number specified in MIPS32K VOL.III -// Chapter 8 - /* - //Cop-0 Regs. Bank 0: Index, - miscRegs[0].resize(4); - - //Cop-0 Regs. Bank 1: - miscRegs[1].resize(8); - - //Cop-0 Regs. Bank 2: - miscRegs[2].resize(8); - - //Cop-0 Regs. Bank 3: - miscRegs[3].resize(1); - - //Cop-0 Regs. Bank 4: - miscRegs[4].resize(2); - - //Cop-0 Regs. Bank 5: - miscRegs[5].resize(2); - - //Cop-0 Regs. Bank 6: - miscRegs[6].resize(6); - - //Cop-0 Regs. Bank 7: - miscRegs[7].resize(1); - - //Cop-0 Regs. Bank 8: - miscRegs[8].resize(1); - - //Cop-0 Regs. Bank 9: - miscRegs[9].resize(1); - - //Cop-0 Regs. Bank 10: - miscRegs[10].resize(1); - - //Cop-0 Regs. Bank 11: - miscRegs[11].resize(1); - - //Cop-0 Regs. Bank 12: - miscRegs[12].resize(4); - - //Cop-0 Regs. Bank 13: - miscRegs[13].resize(1); - - //Cop-0 Regs. Bank 14: - miscRegs[14].resize(1); - - //Cop-0 Regs. Bank 15: - miscRegs[15].resize(2); - - //Cop-0 Regs. Bank 16: - miscRegs[16].resize(4); - //Cop-0 Regs. Bank 17: - miscRegs[17].resize(1); - - //Cop-0 Regs. Bank 18: - miscRegs[18].resize(8); - - //Cop-0 Regs. Bank 19: - miscRegs[19].resize(8); - - //Cop-0 Regs. Bank 20: - miscRegs[20].resize(1); - - //Cop-0 Regs. Bank 21: - //miscRegs[21].resize(1); - //Reserved for future extensions - - //Cop-0 Regs. Bank 22: - //miscRegs[22].resize(4); - //Available for implementation dependent use - - //Cop-0 Regs. Bank 23: - miscRegs[23].resize(5); - - //Cop-0 Regs. Bank 24: - miscRegs[24].resize(1); - - //Cop-0 Regs. Bank 25: - miscRegs[25].resize(8); + switch (cvt_type) + { + case SINGLE_TO_DOUBLE: + double sdouble_val = fp_val; + void *sdouble_ptr = &sdouble_val; + uint64_t sdp_bits = *(uint64_t *) sdouble_ptr; + return sdp_bits; + + case SINGLE_TO_WORD: + int32_t sword_val = (int32_t) fp_val; + void *sword_ptr = &sword_val; + uint64_t sword_bits= *(uint32_t *) sword_ptr; + return sword_bits; + + case WORD_TO_SINGLE: + float wfloat_val = fp_val; + void *wfloat_ptr = &wfloat_val; + uint64_t wfloat_bits = *(uint32_t *) wfloat_ptr; + return wfloat_bits; + + case WORD_TO_DOUBLE: + double wdouble_val = fp_val; + void *wdouble_ptr = &wdouble_val; + uint64_t wdp_bits = *(uint64_t *) wdouble_ptr; + return wdp_bits; - //Cop-0 Regs. Bank 26: - miscRegs[26].resize(1); + default: + panic("Invalid Floating Point Conversion Type (%d). See \"types.hh\" for List of Conversions\n",cvt_type); + return 0; + } +} - //Cop-0 Regs. Bank 27: - miscRegs[27].resize(4); +double +MipsISA::roundFP(double val, int digits) +{ + double digit_offset = pow(10.0,digits); + val = val * digit_offset; + val = val + 0.5; + val = floor(val); + val = val / digit_offset; + return val; +} - //Cop-0 Regs. Bank 28: - miscRegs[28].resize(8); +double +MipsISA::truncFP(double val) +{ + int trunc_val = (int) val; + return (double) trunc_val; +} - //Cop-0 Regs. Bank 29: - miscRegs[29].resize(8); +bool +MipsISA::getFPConditionCode(uint32_t fcsr_reg, int cc) +{ + //uint32_t cc_bits = xc->readFloatReg(35); + return false;//regFile.floatRegfile.getConditionCode(cc); +} - //Cop-0 Regs. Bank 30: - miscRegs[30].resize(1); +uint32_t +MipsISA::makeCCVector(uint32_t fcsr, int num, bool val) +{ + int shift = (num == 0) ? 22 : num + 23; - //Cop-0 Regs. Bank 31: - miscRegs[31].resize(1);*/ + fcsr = fcsr | (val << shift); + return fcsr; } - -const Addr MipsISA::PageShift = 13; -const Addr MipsISA::PageBytes = ULL(1) << PageShift; -const Addr MipsISA::PageMask = ~(PageBytes - 1); -const Addr MipsISA::PageOffset = PageBytes - 1; - #if FULL_SYSTEM -//////////////////////////////////////////////////////////////////////// -// -// Translation stuff -// - -const Addr MipsISA::PteShift = 3; -const Addr MipsISA::NPtePageShift = PageShift - PteShift; -const Addr MipsISA::NPtePage = ULL(1) << NPtePageShift; -const Addr MipsISA::PteMask = NPtePage - 1; - -// User Virtual -const Addr MipsISA::USegBase = ULL(0x0); -const Addr MipsISA::USegEnd = ULL(0x000003ffffffffff); - -// Kernel Direct Mapped -const Addr MipsISA::K0SegBase = ULL(0xfffffc0000000000); -const Addr MipsISA::K0SegEnd = ULL(0xfffffdffffffffff); - -// Kernel Virtual -const Addr MipsISA::K1SegBase = ULL(0xfffffe0000000000); -const Addr MipsISA::K1SegEnd = ULL(0xffffffffffffffff); - -#endif - -// Mips UNOP (sll r0,r0,r0) -const MachInst MipsISA::NoopMachInst = 0x00000000; - static inline Addr TruncPage(Addr addr) { return addr & ~(MipsISA::PageBytes - 1); } @@ -327,12 +140,25 @@ TruncPage(Addr addr) static inline Addr RoundPage(Addr addr) { return (addr + MipsISA::PageBytes - 1) & ~(MipsISA::PageBytes - 1); } +#endif + +void +IntRegFile::serialize(std::ostream &os) +{ + SERIALIZE_ARRAY(regs, NumIntRegs); +} + +void +IntRegFile::unserialize(Checkpoint *cp, const std::string §ion) +{ + UNSERIALIZE_ARRAY(regs, NumIntRegs); +} void RegFile::serialize(std::ostream &os) { - SERIALIZE_ARRAY(intRegFile, NumIntRegs); - SERIALIZE_ARRAY(floatRegFile.q, NumFloatRegs); + intRegFile.serialize(os); + //SERIALIZE_ARRAY(floatRegFile.q, NumFloatRegs); //SERIALIZE_SCALAR(miscRegs.fpcr); //SERIALIZE_SCALAR(miscRegs.uniq); //SERIALIZE_SCALAR(miscRegs.lock_flag); @@ -352,8 +178,8 @@ RegFile::serialize(std::ostream &os) void RegFile::unserialize(Checkpoint *cp, const std::string §ion) { - UNSERIALIZE_ARRAY(intRegFile, NumIntRegs); - UNSERIALIZE_ARRAY(floatRegFile.q, NumFloatRegs); + intRegFile.unserialize(cp, section); + //UNSERIALIZE_ARRAY(floatRegFile.q, NumFloatRegs); //UNSERIALIZE_SCALAR(miscRegs.fpcr); //UNSERIALIZE_SCALAR(miscRegs.uniq); //UNSERIALIZE_SCALAR(miscRegs.lock_flag); diff --git a/arch/mips/isa_traits.hh b/arch/mips/isa_traits.hh index 1dfa0dc7a..148c405df 100644 --- a/arch/mips/isa_traits.hh +++ b/arch/mips/isa_traits.hh @@ -29,9 +29,14 @@ #ifndef __ARCH_MIPS_ISA_TRAITS_HH__ #define __ARCH_MIPS_ISA_TRAITS_HH__ -//#include "arch/mips/misc_regfile.hh" +#include "arch/mips/constants.hh" +#include "arch/mips/types.hh" +#include "arch/mips/regfile/regfile.hh" +#include "arch/mips/faults.hh" +#include "arch/mips/utility.hh" #include "base/misc.hh" #include "config/full_system.hh" +#include "sim/byteswap.hh" #include "sim/host.hh" #include "sim/faults.hh" @@ -40,9 +45,9 @@ class FastCPU; class FullCPU; class Checkpoint; +class ExecContext; namespace LittleEndianGuest {}; -using namespace LittleEndianGuest; #define TARGET_MIPS @@ -54,396 +59,107 @@ int DTB_ASN_ASN(uint64_t reg); int ITB_ASN_ASN(uint64_t reg); }; -namespace MipsISA -{ - typedef uint32_t MachInst; -// typedef uint64_t Addr; - typedef uint8_t RegIndex; - - enum { - MemoryEnd = 0xffffffffffffffffULL, - - NumIntRegs = 32, - NumFloatRegs = 32, - NumMiscRegs = 258, //account for hi,lo regs - - MaxRegsOfAnyType = 32, - // Static instruction parameters - MaxInstSrcRegs = 3, - MaxInstDestRegs = 2, - - // semantically meaningful register indices - ZeroReg = 0, // architecturally meaningful - // the rest of these depend on the ABI - StackPointerReg = 30, - GlobalPointerReg = 29, - ProcedureValueReg = 27, - ReturnAddressReg = 26, - ReturnValueReg = 0, - FramePointerReg = 15, - ArgumentReg0 = 16, - ArgumentReg1 = 17, - ArgumentReg2 = 18, - ArgumentReg3 = 19, - ArgumentReg4 = 20, - ArgumentReg5 = 21, - - LogVMPageSize = 13, // 8K bytes - VMPageSize = (1 << LogVMPageSize), - - BranchPredAddrShiftAmt = 2, // instructions are 4-byte aligned - - WordBytes = 4, - HalfwordBytes = 2, - ByteBytes = 1, - DepNA = 0, - }; - - // These enumerate all the registers for dependence tracking. - enum DependenceTags { - // 0..31 are the integer regs 0..31 - // 32..63 are the FP regs 0..31, i.e. use (reg + FP_Base_DepTag) - FP_Base_DepTag = 32, - Ctrl_Base_DepTag = 64, - Fpcr_DepTag = 64, // floating point control register - Uniq_DepTag = 65, - IPR_Base_DepTag = 66, - MiscReg_DepTag = 67 - }; - - typedef uint64_t IntReg; - typedef IntReg IntRegFile[NumIntRegs]; - - // floating point register file entry type - typedef union { - uint64_t q; - double d; - } FloatReg; - - typedef union { - uint64_t q[NumFloatRegs]; // integer qword view - double d[NumFloatRegs]; // double-precision floating point view - } FloatRegFile; - - // cop-0/cop-1 system control register file - typedef uint64_t MiscReg; -//typedef MiscReg MiscRegFile[NumMiscRegs]; - class MiscRegFile { - public: - MiscReg - protected: - uint64_t fpcr; // floating point condition codes - uint64_t uniq; // process-unique register - bool lock_flag; // lock flag for LL/SC - Addr lock_addr; // lock address for LL/SC - - MiscReg miscRegFile[NumMiscRegs]; - - public: - //These functions should be removed once the simplescalar cpu model - //has been replaced. - int getInstAsid(); - int getDataAsid(); - - MiscReg readReg(int misc_reg) - { return miscRegFile[misc_reg]; } - - MiscReg readRegWithEffect(int misc_reg, Fault &fault, ExecContext *xc) - { return miscRegFile[misc_reg];} - - Fault setReg(int misc_reg, const MiscReg &val) - { miscRegFile[misc_reg] = val; return NoFault; } - - Fault setRegWithEffect(int misc_reg, const MiscReg &val, - ExecContext *xc) - { miscRegFile[misc_reg] = val; return NoFault; } - -#if FULL_SYSTEM - void clearIprs() { }; - - protected: - InternalProcReg ipr[NumInternalProcRegs]; // Internal processor regs - - private: - MiscReg readIpr(int idx, Fault &fault, ExecContext *xc) { } - - Fault setIpr(int idx, uint64_t val, ExecContext *xc) { } -#endif - friend class RegFile; - }; - - enum MiscRegTags { - //Coprocessor 0 Registers - //Reference MIPS32 Arch. for Programmers, Vol. III, Ch.8 - //(Register Number-Register Select) Summary of Register - //------------------------------------------------------ - Index = 0, //0-0 Index into the TLB array - - MVPControl = 1, //0-1 Per-processor register containing global - //MIPS® MT configuration data - - MVPConf0 = 2, //0-2 Per-processor register containing global - //MIPS® MT configuration data - - MVPConf1 = 3, //0-3 Per-processor register containing global - //MIPS® MT configuration data - - Random = 8, //1-0 Randomly generated index into the TLB array - - VPEControl = 9, //1-1 Per-VPE register containing relatively volatile - //thread configuration data - - VPEConf0 = 10, //1-2 Per-VPE multi-thread configuration - //information - - - VPEConf1 = 11, //1-2 Per-VPE multi-thread configuration - //information - - YQMask = 12, //Per-VPE register defining which YIELD - //qualifier bits may be used without generating - //an exception - - VPESchedule = 13, - VPEScheFBack = 14, - VPEOpt = 15, - EntryLo0 = 16, // Bank 3: 16 - 23 - TCStatus = 17, - TCBind = 18, - TCRestart = 19, - TCHalt = 20, - TCContext = 21, - TCSchedule = 22, - TCScheFBack = 23, - - EntryLo1 = 24,// Bank 4: 24 - 31 - - Context = 32, // Bank 5: 32 - 39 - ContextConfig = 33, - - //PageMask = 40, //Bank 6: 40 - 47 - PageGrain = 41, - - Wired = 48, //Bank 7:48 - 55 - SRSConf0 = 49, - SRSConf1 = 50, - SRSConf2 = 51, - SRSConf3 = 52, - SRSConf4 = 53, - BadVAddr = 54, - - HWRena = 56,//Bank 8:56 - 63 - - Count = 64, //Bank 9:64 - 71 - - EntryHi = 72,//Bank 10:72 - 79 - - Compare = 80,//Bank 11:80 - 87 - - Status = 88,//Bank 12:88 - 96 //12-0 Processor status and control - IntCtl = 89, //12-1 Interrupt system status and control - SRSCtl = 90, //12-2 Shadow register set status and control - SRSMap = 91, //12-3 Shadow set IPL mapping - - Cause = 97,//97-104 //13-0 Cause of last general exception - - EPC = 105,//105-112 //14-0 Program counter at last exception - - PRId = 113//113-120, //15-0 Processor identification and revision - EBase = 114, //15-1 Exception vector base register - - Config = 121,//Bank 16: 121-128 - Config1 = 122, - Config2 = 123, - Config3 = 124, - Config6 = 127, - Config7 = 128, - - - LLAddr = 129,//Bank 17: 129-136 - - WatchLo0 = 137,//Bank 18: 137-144 - WatchLo1 = 138, - WatchLo2 = 139, - WatchLo3 = 140, - WatchLo4 = 141, - WatchLo5 = 142, - WatchLo6 = 143, - WatchLo7 = 144, +#if !FULL_SYSTEM +class SyscallReturn { + public: + template <class T> + SyscallReturn(T v, bool s) + { + retval = (uint32_t)v; + success = s; + } - WatchHi0 = 145,//Bank 19: 145-152 - WatchHi1 = 146, - WatchHi2 = 147, - WatchHi3 = 148, - WatchHi4 = 149, - WatchHi5 = 150, - WatchHi6 = 151, - WatchHi7 = 152, + template <class T> + SyscallReturn(T v) + { + success = (v >= 0); + retval = (uint32_t)v; + } - XCContext64 = 153,//Bank 20: 153-160 + ~SyscallReturn() {} - //Bank 21: 161-168 + SyscallReturn& operator=(const SyscallReturn& s) { + retval = s.retval; + success = s.success; + return *this; + } - //Bank 22: 169-176 - - Debug = 177, //Bank 23: 177-184 - TraceControl1 = 178, - TraceControl2 = 179, - UserTraceData = 180, - TraceBPC = 181, - - DEPC = 185,//Bank 24: 185-192 - - PerfCnt0 = 193,//Bank 25: 193 - 200 - PerfCnt1 = 194, - PerfCnt2 = 195, - PerfCnt3 = 196, - PerfCnt4 = 197, - PerfCnt5 = 198, - PerfCnt6 = 199, - PerfCnt7 = 200, - - ErrCtl = 201, //Bank 26: 201 - 208 - - CacheErr0 = 209, //Bank 27: 209 - 216 - CacheErr1 = 210, - CacheErr2 = 211, - CacheErr3 = 212, - - TagLo0 = 217,//Bank 28: 217 - 224 - DataLo1 = 218, - TagLo2 = 219, - DataLo3 = 220, - TagLo4 = 221, - DataLo5 = 222, - TagLo6 = 223, - DataLo7 = 234, - - TagHi0 = 233,//Bank 29: 233 - 240 - DataHi1 = 234, - TagHi2 = 235, - DataHi3 = 236, - TagHi4 = 237, - DataHi5 = 238, - TagHi6 = 239, - DataHi7 = 240, + bool successful() { return success; } + uint64_t value() { return retval; } - ErrorEPC = 249,//Bank 30: 241 - 248 + private: + uint64_t retval; + bool success; +}; +#endif - DESAVE = 257,//Bank 31: 249-256 +namespace MipsISA +{ + using namespace LittleEndianGuest; + + static inline void setSyscallReturn(SyscallReturn return_value, RegFile *regs) + { + if (return_value.successful()) { + // no error + regs->setIntReg(SyscallSuccessReg, 0); + regs->setIntReg(ReturnValueReg1, return_value.value()); + } else { + // got an error, return details + regs->setIntReg(SyscallSuccessReg, (IntReg) -1); + regs->setIntReg(ReturnValueReg1, -return_value.value()); + } + } - //More Misc. Regs - Hi, - Lo, - FCSR, - FPCR, - - //Alpha Regs, but here now, for - //compiling sake - UNIQ, - LockAddr, - LockFlag - }; - -extern const Addr PageShift; -extern const Addr PageBytes; -extern const Addr PageMask; -extern const Addr PageOffset; + StaticInstPtr decodeInst(ExtMachInst); + static inline ExtMachInst + makeExtMI(MachInst inst, const uint64_t &pc) { #if FULL_SYSTEM - - typedef uint64_t InternalProcReg; - -#include "arch/mips/isa_fullsys_traits.hh" - + ExtMachInst ext_inst = inst; + if (pc && 0x1) + return ext_inst|=(static_cast<ExtMachInst>(pc & 0x1) << 32); + else + return ext_inst; #else - enum { - NumInternalProcRegs = 0 - }; + return ExtMachInst(inst); #endif + } - enum { - TotalNumRegs = - NumIntRegs + NumFloatRegs + NumMiscRegs + NumInternalProcRegs - }; - - enum { - TotalDataRegs = NumIntRegs + NumFloatRegs - }; - - typedef union { - IntReg intreg; - FloatReg fpreg; - MiscReg ctrlreg; - } AnyReg; - - struct RegFile { - IntRegFile intRegFile; // (signed) integer register file - FloatRegFile floatRegFile; // floating point register file - MiscRegFile miscRegs; // control register file - - - Addr pc; // program counter - Addr npc; // next-cycle program counter - Addr nnpc; // next-next-cycle program counter - // used to implement branch delay slot - // not real register - - MiscReg hi; // MIPS HI Register - MiscReg lo; // MIPS LO Register - - -#if FULL_SYSTEM - IntReg palregs[NumIntRegs]; // PAL shadow registers - InternalProcReg ipr[NumInternalProcRegs]; // internal processor regs - int intrflag; // interrupt flag - bool pal_shadow; // using pal_shadow registers - inline int instAsid() { return MIPS34K::ITB_ASN_ASN(ipr[IPR_ITB_ASN]); } - inline int dataAsid() { return MIPS34K::DTB_ASN_ASN(ipr[IPR_DTB_ASN]); } -#endif // FULL_SYSTEM - - //void initCP0Regs(); - void serialize(std::ostream &os); - void unserialize(Checkpoint *cp, const std::string §ion); - - void createCP0Regs(); - void coldReset(); - }; - - StaticInstPtr decodeInst(MachInst); + /** + * Function to insure ISA semantics about 0 registers. + * @param xc The execution context. + */ + template <class XC> + void zeroRegisters(XC *xc); - // return a no-op instruction... used for instruction fetch faults - extern const MachInst NoopMachInst; + const Addr MaxAddr = (Addr)-1; - enum annotes { - ANNOTE_NONE = 0, - // An impossible number for instruction annotations - ITOUCH_ANNOTE = 0xffffffff, - }; + void copyRegs(ExecContext *src, ExecContext *dest); - void getMiscRegIdx(int reg_name,int &idx, int &sel); + uint64_t fpConvert(double fp_val, ConvertType cvt_type); + double roundFP(double val, int digits); + double truncFP(double val); + bool getFPConditionCode(uint32_t fcsr_reg, int cc); + uint32_t makeCCVector(uint32_t fcsr, int num, bool val); + // Machine operations - static inline bool isCallerSaveIntegerRegister(unsigned int reg) { - panic("register classification not implemented"); - return (reg >= 1 && reg <= 8 || reg >= 22 && reg <= 25 || reg == 27); - } + void saveMachineReg(AnyReg &savereg, const RegFile ®_file, + int regnum); - static inline bool isCalleeSaveIntegerRegister(unsigned int reg) { - panic("register classification not implemented"); - return (reg >= 9 && reg <= 15); - } + void restoreMachineReg(RegFile ®s, const AnyReg ®, + int regnum); - static inline bool isCallerSaveFloatRegister(unsigned int reg) { - panic("register classification not implemented"); - return false; - } +#if 0 + static void serializeSpecialRegs(const Serializable::Proxy &proxy, + const RegFile ®s); - static inline bool isCalleeSaveFloatRegister(unsigned int reg) { - panic("register classification not implemented"); - return false; - } + static void unserializeSpecialRegs(const IniFile *db, + const std::string &category, + ConfigNode *node, + RegFile ®s); +#endif static inline Addr alignAddress(const Addr &addr, unsigned int nbytes) { @@ -470,77 +186,14 @@ extern const Addr PageOffset; return 0; } - // Machine operations - - void saveMachineReg(AnyReg &savereg, const RegFile ®_file, - int regnum); - - void restoreMachineReg(RegFile ®s, const AnyReg ®, - int regnum); - -#if 0 - static void serializeSpecialRegs(const Serializable::Proxy &proxy, - const RegFile ®s); - - static void unserializeSpecialRegs(const IniFile *db, - const std::string &category, - ConfigNode *node, - RegFile ®s); -#endif - - /** - * Function to insure ISA semantics about 0 registers. - * @param xc The execution context. - */ - template <class XC> - void zeroRegisters(XC *xc); - - const Addr MaxAddr = (Addr)-1; }; -#if !FULL_SYSTEM -class SyscallReturn { - public: - template <class T> - SyscallReturn(T v, bool s) - { - retval = (uint64_t)v; - success = s; - } - - template <class T> - SyscallReturn(T v) - { - success = (v >= 0); - retval = (uint64_t)v; - } - - ~SyscallReturn() {} - - SyscallReturn& operator=(const SyscallReturn& s) { - retval = s.retval; - success = s.success; - return *this; - } - - bool successful() { return success; } - uint64_t value() { return retval; } - - - private: - uint64_t retval; - bool success; -}; - -#endif - - #if FULL_SYSTEM -//typedef TheISA::InternalProcReg InternalProcReg; -//const int NumInternalProcRegs = TheISA::NumInternalProcRegs; -//const int NumInterruptLevels = TheISA::NumInterruptLevels; #include "arch/mips/mips34k.hh" + #endif +using namespace MipsISA; + #endif // __ARCH_MIPS_ISA_TRAITS_HH__ diff --git a/arch/mips/linux/linux.cc b/arch/mips/linux/linux.cc new file mode 100644 index 000000000..ebff886dd --- /dev/null +++ b/arch/mips/linux/linux.cc @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2003-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. + */ + +#include "arch/mips/linux/linux.hh" + +// open(2) flags translation table +OpenFlagTransTable MipsLinux::openFlagTable[] = { +#ifdef _MSC_VER + { MipsLinux::TGT_O_RDONLY, _O_RDONLY }, + { MipsLinux::TGT_O_WRONLY, _O_WRONLY }, + { MipsLinux::TGT_O_RDWR, _O_RDWR }, + { MipsLinux::TGT_O_APPEND, _O_APPEND }, + { MipsLinux::TGT_O_CREAT, _O_CREAT }, + { MipsLinux::TGT_O_TRUNC, _O_TRUNC }, + { MipsLinux::TGT_O_EXCL, _O_EXCL }, +#ifdef _O_NONBLOCK + { MipsLinux::TGT_O_NONBLOCK, _O_NONBLOCK }, +#endif +#ifdef _O_NOCTTY + { MipsLinux::TGT_O_NOCTTY, _O_NOCTTY }, +#endif +#ifdef _O_SYNC + { MipsLinux::TGT_O_SYNC, _O_SYNC }, +#endif +#else /* !_MSC_VER */ + { MipsLinux::TGT_O_RDONLY, O_RDONLY }, + { MipsLinux::TGT_O_WRONLY, O_WRONLY }, + { MipsLinux::TGT_O_RDWR, O_RDWR }, + { MipsLinux::TGT_O_APPEND, O_APPEND }, + { MipsLinux::TGT_O_CREAT, O_CREAT }, + { MipsLinux::TGT_O_TRUNC, O_TRUNC }, + { MipsLinux::TGT_O_EXCL, O_EXCL }, + { MipsLinux::TGT_O_NONBLOCK, O_NONBLOCK }, + { MipsLinux::TGT_O_NOCTTY, O_NOCTTY }, +#ifdef O_SYNC + { MipsLinux::TGT_O_SYNC, O_SYNC }, +#endif +#endif /* _MSC_VER */ +}; + +const int MipsLinux::NUM_OPEN_FLAGS = + (sizeof(MipsLinux::openFlagTable)/sizeof(MipsLinux::openFlagTable[0])); + + + diff --git a/arch/mips/linux/linux.hh b/arch/mips/linux/linux.hh new file mode 100644 index 000000000..fd08e8c87 --- /dev/null +++ b/arch/mips/linux/linux.hh @@ -0,0 +1,124 @@ +/* + * Copyright (c) 2003-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. + */ + +#ifndef __MIPS_MIPS_LINUX_HH +#define __MIPS_MIPS_LINUX_HH + +#include "kern/linux/linux.hh" + +class MipsLinux : public Linux +{ + public: + + /// 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 = 0x00000000; //!< O_RDONLY + static const int TGT_O_WRONLY = 0x00000001; //!< O_WRONLY + static const int TGT_O_RDWR = 0x00000002; //!< O_RDWR + static const int TGT_O_NONBLOCK = 0x00000080; //!< O_NONBLOCK + static const int TGT_O_APPEND = 0x00000008; //!< O_APPEND + static const int TGT_O_CREAT = 0x00000100; //!< O_CREAT + static const int TGT_O_TRUNC = 0x00000200; //!< O_TRUNC + static const int TGT_O_EXCL = 0x00000400; //!< O_EXCL + static const int TGT_O_NOCTTY = 0x00000800; //!< O_NOCTTY + static const int TGT_O_SYNC = 0x00000010; //!< O_SYNC + static const int TGT_O_DRD = 0x00010000; //!< O_DRD + static const int TGT_O_DIRECTIO = 0x00020000; //!< O_DIRECTIO + static const int TGT_O_CACHE = 0x00002000; //!< O_CACHE + static const int TGT_O_DSYNC = 0x00008000; //!< O_DSYNC + static const int TGT_O_RSYNC = 0x00040000; //!< O_RSYNC + //@} + + /// For mmap(). + static const unsigned TGT_MAP_ANONYMOUS = 0x800; + + //@{ + /// For getsysinfo(). + static const unsigned GSI_PLATFORM_NAME = 103; //!< platform name as string + static const unsigned GSI_CPU_INFO = 59; //!< CPU information + static const unsigned GSI_PROC_TYPE = 60; //!< get proc_type + static const unsigned GSI_MAX_CPU = 30; //!< max # cpu's on this machine + static const unsigned GSI_CPUS_IN_BOX = 55; //!< number of CPUs in system + static const unsigned GSI_PHYSMEM = 19; //!< Physical memory in KB + static const unsigned GSI_CLK_TCK = 42; //!< clock freq in Hz + //@} + + //@{ + /// For getrusage(). + static const int TGT_RUSAGE_SELF = 0; + static const int TGT_RUSAGE_CHILDREN = -1; + static const int TGT_RUSAGE_BOTH = -2; + //@} + + //@{ + /// For setsysinfo(). + static const unsigned SSI_IEEE_FP_CONTROL = 14; //!< ieee_set_fp_control() + //@} + + //@{ + /// ioctl() command codes. + static const unsigned TIOCGETP = 0x7408; + static const unsigned TIOCSETP = 0x7409; + static const unsigned TIOCSETN = 0x740a; + static const unsigned TIOCSETC = 0x7411; + static const unsigned TIOCGETC = 0x7412; + static const unsigned FIONREAD = 0x467f; + static const unsigned TIOCISATTY = 0x5480; + static const unsigned TIOCGETS = 0x7413; + static const unsigned TIOCGETA = 0x7417; + //@} + + /// For table(). + static const int TBL_SYSINFO = 12; + + /// Resource enumeration for getrlimit(). + enum rlimit_resources { + TGT_RLIMIT_CPU = 0, + TGT_RLIMIT_FSIZE = 1, + TGT_RLIMIT_DATA = 2, + TGT_RLIMIT_STACK = 3, + TGT_RLIMIT_CORE = 4, + TGT_RLIMIT_NOFILE = 5, + TGT_RLIMIT_AS = 6, + TGT_RLIMIT_RSS = 7, + TGT_RLIMIT_VMEM = 7, + TGT_RLIMIT_NPROC = 8, + TGT_RLIMIT_MEMLOCK = 9, + TGT_RLIMIT_LOCKS = 10 + }; + +}; + +#endif diff --git a/arch/mips/linux/process.cc b/arch/mips/linux/process.cc new file mode 100644 index 000000000..ffc5da2e1 --- /dev/null +++ b/arch/mips/linux/process.cc @@ -0,0 +1,429 @@ +/* + * Copyright (c) 2003-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. + */ + +#include "arch/mips/linux/linux.hh" +#include "arch/mips/linux/process.hh" +#include "arch/mips/isa_traits.hh" + +#include "base/trace.hh" +#include "cpu/exec_context.hh" +#include "kern/linux/linux.hh" + +#include "sim/process.hh" +#include "sim/syscall_emul.hh" + +using namespace std; +using namespace MipsISA; + +/// Target uname() handler. +static SyscallReturn +unameFunc(SyscallDesc *desc, int callnum, Process *process, + ExecContext *xc) +{ + TypedBufferArg<Linux::utsname> name(xc->getSyscallArg(0)); + + strcpy(name->sysname, "Linux"); + strcpy(name->nodename, "m5.eecs.umich.edu"); + strcpy(name->release, "2.4.20"); + strcpy(name->version, "#1 Mon Aug 18 11:32:15 EDT 2003"); + strcpy(name->machine, "mips"); + + name.copyOut(xc->getMemPort()); + return 0; +} + +/// Target sys_getsysyinfo() handler. Even though this call is +/// borrowed from Tru64, the subcases that get used appear to be +/// different in practice from those used by Tru64 processes. +static SyscallReturn +sys_getsysinfoFunc(SyscallDesc *desc, int callnum, Process *process, + ExecContext *xc) +{ + unsigned op = xc->getSyscallArg(0); + // unsigned nbytes = xc->getSyscallArg(2); + + switch (op) { + + case 45: { // GSI_IEEE_FP_CONTROL + TypedBufferArg<uint64_t> fpcr(xc->getSyscallArg(1)); + // I don't think this exactly matches the HW FPCR + *fpcr = 0; + fpcr.copyOut(xc->getMemPort()); + return 0; + } + + default: + cerr << "sys_getsysinfo: unknown op " << op << endl; + abort(); + break; + } + + return 1; +} + +/// Target sys_setsysinfo() handler. +static SyscallReturn +sys_setsysinfoFunc(SyscallDesc *desc, int callnum, Process *process, + ExecContext *xc) +{ + unsigned op = xc->getSyscallArg(0); + // unsigned nbytes = xc->getSyscallArg(2); + + switch (op) { + + case 14: { // SSI_IEEE_FP_CONTROL + TypedBufferArg<uint64_t> fpcr(xc->getSyscallArg(1)); + // I don't think this exactly matches the HW FPCR + fpcr.copyIn(xc->getMemPort()); + DPRINTFR(SyscallVerbose, "sys_setsysinfo(SSI_IEEE_FP_CONTROL): " + " setting FPCR to 0x%x\n", gtoh(*(uint64_t*)fpcr)); + return 0; + } + + default: + cerr << "sys_setsysinfo: unknown op " << op << endl; + abort(); + break; + } + + return 1; +} + + +SyscallDesc MipsLinuxProcess::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<MipsLinux>), + /* 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", unimplementedFunc), + /* 14 */ SyscallDesc("mknod", unimplementedFunc), + /* 15 */ SyscallDesc("chmod", chmodFunc<MipsLinux>), + /* 16 */ SyscallDesc("lchown", chownFunc), + /* 17 */ SyscallDesc("break", obreakFunc), /*obreak*/ + /* 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", unimplementedFunc), + /* 39 */ SyscallDesc("mkdir", unimplementedFunc), + /* 40 */ SyscallDesc("rmdir", unimplementedFunc), + /* 41 */ SyscallDesc("dup", unimplementedFunc), + /* 42 */ SyscallDesc("pipe", unimplementedFunc), + /* 43 */ SyscallDesc("times", unimplementedFunc), + /* 44 */ SyscallDesc("prof", unimplementedFunc), + /* 45 */ SyscallDesc("brk", obreakFunc),/*openFunc<MipsLinux>*/ + /* 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<MipsLinux>), + /* 55 */ SyscallDesc("fcntl", unimplementedFunc), + /* 56 */ SyscallDesc("mpx", unimplementedFunc), + /* 57 */ SyscallDesc("setpgid", unimplementedFunc), + /* 58 */ SyscallDesc("ulimit", unimplementedFunc), + /* 59 */ SyscallDesc("unused#59", unimplementedFunc), + /* 60 */ SyscallDesc("umask", unimplementedFunc), + /* 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", unimplementedFunc), + /* 76 */ SyscallDesc("getrlimit", unimplementedFunc), + /* 77 */ SyscallDesc("getrusage", unimplementedFunc), + /* 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<MipsLinux>), + /* 91 */ SyscallDesc("munmap",munmapFunc), + /* 92 */ SyscallDesc("truncate", fcntlFunc), + /* 93 */ SyscallDesc("ftruncate", unimplementedFunc), + /* 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<MipsLinux>), + /* 107 */ SyscallDesc("lstat", unimplementedFunc), + /* 108 */ SyscallDesc("fstat", fstatFunc<MipsLinux>), + /* 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", unimplementedFunc), + /* 141 */ SyscallDesc("getdents", unimplementedFunc), + /* 142 */ SyscallDesc("newselect", unimplementedFunc), + /* 143 */ SyscallDesc("flock", unimplementedFunc), + /* 144 */ SyscallDesc("msync", unimplementedFunc),/*getrlimitFunc<MipsLinux>*/ + /* 145 */ SyscallDesc("readv", unimplementedFunc), + /* 146 */ SyscallDesc("writev", writevFunc<MipsLinux>), + /* 147 */ SyscallDesc("cacheflush", unimplementedFunc), + /* 148 */ SyscallDesc("cachectl", unimplementedFunc), + /* 149 */ SyscallDesc("sysmips", unimplementedFunc), + /* 150 */ SyscallDesc("unused#150", unimplementedFunc), + /* 151 */ SyscallDesc("getsid", unimplementedFunc), + /* 152 */ SyscallDesc("fdatasync", unimplementedFunc), + /* 153 */ SyscallDesc("sysctl", unimplementedFunc), + /* 154 */ SyscallDesc("mlock", unimplementedFunc), + /* 155 */ SyscallDesc("munlock", unimplementedFunc), + /* 156 */ SyscallDesc("mlockall", unimplementedFunc), + /* 157 */ SyscallDesc("munlockall", unimplementedFunc), + /* 158 */ SyscallDesc("sched_setparam", unimplementedFunc), + /* 159 */ SyscallDesc("sched_getparam", unimplementedFunc), + /* 160 */ SyscallDesc("sched_setscheduler", unimplementedFunc), + /* 161 */ SyscallDesc("sched_getscheduler", unimplementedFunc), + /* 162 */ SyscallDesc("sched_yield", unimplementedFunc), + /* 163 */ SyscallDesc("sched_get_prioritymax", unimplementedFunc), + /* 164 */ SyscallDesc("sched_get_priority_min", unimplementedFunc), + /* 165 */ SyscallDesc("sched_rr_get_interval", unimplementedFunc), + /* 166 */ SyscallDesc("nanosleep", unimplementedFunc), + /* 167 */ SyscallDesc("mremap", unimplementedFunc), + /* 168 */ SyscallDesc("accept", unimplementedFunc), + /* 169 */ SyscallDesc("bind", unimplementedFunc), + /* 170 */ SyscallDesc("connect", unimplementedFunc), + /* 171 */ SyscallDesc("getpeername", unimplementedFunc), + /* 172 */ SyscallDesc("getsockname", unimplementedFunc), + /* 173 */ SyscallDesc("getsockopt", unimplementedFunc), + /* 174 */ SyscallDesc("listen", unimplementedFunc), + /* 175 */ SyscallDesc("recv", unimplementedFunc), + /* 176 */ SyscallDesc("recvmsg", unimplementedFunc), + /* 177 */ SyscallDesc("send", unimplementedFunc), + /* 178 */ SyscallDesc("sendmsg", ignoreFunc), + /* 179 */ SyscallDesc("sendto", unimplementedFunc), + /* 180 */ SyscallDesc("setsockopt", unimplementedFunc), + /* 181 */ SyscallDesc("shutdown", unimplementedFunc), + /* 182 */ SyscallDesc("unknown #182", unimplementedFunc), + /* 183 */ SyscallDesc("socket", ignoreFunc), + /* 184 */ SyscallDesc("socketpair", unimplementedFunc), + /* 185 */ SyscallDesc("setresuid", unimplementedFunc), + /* 186 */ SyscallDesc("getresuid", unimplementedFunc), + /* 187 */ SyscallDesc("query_module", unimplementedFunc), + /* 188 */ SyscallDesc("poll", unimplementedFunc), + /* 189 */ SyscallDesc("nfsservctl", unimplementedFunc), + /* 190 */ SyscallDesc("setresgid", unimplementedFunc), + /* 191 */ SyscallDesc("getresgid", unimplementedFunc), + /* 192 */ SyscallDesc("prctl", unimplementedFunc), + /* 193 */ SyscallDesc("rt_sigreturn", unimplementedFunc), + /* 194 */ SyscallDesc("rt_sigaction", ignoreFunc), + /* 195 */ SyscallDesc("rt_sigprocmask", ignoreFunc), + /* 196 */ SyscallDesc("rt_sigpending", unimplementedFunc), + /* 197 */ SyscallDesc("rt_sigtimedwait", unimplementedFunc), + /* 198 */ SyscallDesc("rt_sigqueueinfo", ignoreFunc), + /* 199 */ SyscallDesc("rt_sigsuspend", unimplementedFunc), + /* 200 */ SyscallDesc("pread64", unimplementedFunc), + /* 201 */ SyscallDesc("pwrite64", unimplementedFunc), + /* 202 */ SyscallDesc("chown", unimplementedFunc), + /* 203 */ SyscallDesc("getcwd", unimplementedFunc), + /* 204 */ SyscallDesc("capget", unimplementedFunc), + /* 205 */ SyscallDesc("capset", unimplementedFunc), + /* 206 */ SyscallDesc("sigalstack", unimplementedFunc), + /* 207 */ SyscallDesc("sendfile", unimplementedFunc), + /* 208 */ SyscallDesc("getpmsg", unimplementedFunc), + /* 209 */ SyscallDesc("putpmsg", unimplementedFunc), + /* 210 */ SyscallDesc("mmap2", unimplementedFunc), + /* 211 */ SyscallDesc("truncate64", unimplementedFunc), + /* 212 */ SyscallDesc("ftruncate64", unimplementedFunc), + /* 213 */ SyscallDesc("stat64", unimplementedFunc), + /* 214 */ SyscallDesc("lstat64", lstat64Func<MipsLinux>), + /* 215 */ SyscallDesc("fstat64", fstat64Func<MipsLinux>), + /* 216 */ SyscallDesc("pivot_root", unimplementedFunc), + /* 217 */ SyscallDesc("mincore", unimplementedFunc), + /* 218 */ SyscallDesc("madvise", unimplementedFunc), + /* 219 */ SyscallDesc("getdents64", unimplementedFunc), + /* 220 */ SyscallDesc("fcntl64", fcntlFunc), + /* 221 */ SyscallDesc("reserved#221", unimplementedFunc), + /* 222 */ SyscallDesc("gettid", unimplementedFunc), + /* 223 */ SyscallDesc("readahead", unimplementedFunc), + /* 224 */ SyscallDesc("setxattr", unimplementedFunc), + /* 225 */ SyscallDesc("lsetxattr", unimplementedFunc), + /* 226 */ SyscallDesc("fsetxattr", unimplementedFunc), + /* 227 */ SyscallDesc("getxattr", unimplementedFunc), + /* 228 */ SyscallDesc("lgetxattr", unimplementedFunc), + /* 229 */ SyscallDesc("fgetxattr", unimplementedFunc), + /* 230 */ SyscallDesc("listxattr", unimplementedFunc), + /* 231 */ SyscallDesc("llistxattr", unimplementedFunc), + /* 232 */ SyscallDesc("flistxattr", unimplementedFunc), + /* 233 */ SyscallDesc("removexattr", unimplementedFunc), + /* 234 */ SyscallDesc("lremovexattr", unimplementedFunc), + /* 235 */ SyscallDesc("fremovexattr", ignoreFunc), + /* 236 */ SyscallDesc("tkill", unimplementedFunc), + /* 237 */ SyscallDesc("sendfile64", unimplementedFunc), + /* 238 */ SyscallDesc("futex", unimplementedFunc), + /* 239 */ SyscallDesc("sched_setaffinity", unimplementedFunc), + /* 240 */ SyscallDesc("sched_getaffinity", unimplementedFunc), + /* 241 */ SyscallDesc("io_setup", unimplementedFunc), + /* 242 */ SyscallDesc("io_destroy", unimplementedFunc), + /* 243 */ SyscallDesc("io_getevents", unimplementedFunc), + /* 244 */ SyscallDesc("io_submit", unimplementedFunc), + /* 245 */ SyscallDesc("io_cancel", unimplementedFunc), + /* 246 */ SyscallDesc("exit_group", exitFunc), + /* 247 */ SyscallDesc("lookup_dcookie", unimplementedFunc), + /* 248 */ SyscallDesc("epoll_create", unimplementedFunc), + /* 249 */ SyscallDesc("epoll_ctl", unimplementedFunc), + /* 250 */ SyscallDesc("epoll_wait", unimplementedFunc), + /* 251 */ SyscallDesc("remap_file_pages", unimplementedFunc), + /* 252 */ SyscallDesc("set_tid_address", unimplementedFunc), + /* 253 */ SyscallDesc("restart_syscall", unimplementedFunc), + /* 254 */ SyscallDesc("fadvise64", unimplementedFunc), + /* 255 */ SyscallDesc("statfs64", unimplementedFunc), + /* 256 */ SyscallDesc("fstafs64", unimplementedFunc), + /* 257 */ SyscallDesc("timer_create", sys_getsysinfoFunc), + /* 258 */ SyscallDesc("timer_settime", sys_setsysinfoFunc), + /* 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("tgkill", unimplementedFunc), + /* 267 */ SyscallDesc("utimes", unimplementedFunc), + /* 268 */ SyscallDesc("mbind", unimplementedFunc), + /* 269 */ SyscallDesc("get_mempolicy", unimplementedFunc), + /* 270 */ SyscallDesc("set_mempolicy", unimplementedFunc), + /* 271 */ SyscallDesc("mq_open", unimplementedFunc), + /* 272 */ SyscallDesc("mq_unlink", unimplementedFunc), + /* 273 */ SyscallDesc("mq_timedsend", unimplementedFunc), + /* 274 */ SyscallDesc("mq_timedreceive", unimplementedFunc), + /* 275 */ SyscallDesc("mq_notify", unimplementedFunc), + /* 276 */ SyscallDesc("mq_getsetattr", unimplementedFunc), + /* 277 */ SyscallDesc("vserver", unimplementedFunc), + /* 278 */ SyscallDesc("waitid", unimplementedFunc), + /* 279 */ SyscallDesc("unknown #279", unimplementedFunc), + /* 280 */ SyscallDesc("add_key", unimplementedFunc), + /* 281 */ SyscallDesc("request_key", unimplementedFunc), + /* 282 */ SyscallDesc("keyctl", unimplementedFunc), +}; + +MipsLinuxProcess::MipsLinuxProcess(const std::string &name, + ObjectFile *objFile, + System *system, + int stdin_fd, + int stdout_fd, + int stderr_fd, + std::vector<std::string> &argv, + std::vector<std::string> &envp) + : MipsLiveProcess(name, objFile, system, stdin_fd, stdout_fd, stderr_fd, + argv, envp), + Num_Syscall_Descs(sizeof(syscallDescs) / sizeof(SyscallDesc)) +{ + //init_regs->intRegFile[0] = 0; +} + +SyscallDesc* +MipsLinuxProcess::getDesc(int callnum) +{ + //MIPS32 syscalls are in the range of 4000 - 4999 + int m5_sys_idx = callnum - 4000; + + if (m5_sys_idx < 0 || m5_sys_idx > Num_Syscall_Descs) + return NULL; + + return &syscallDescs[m5_sys_idx]; +} diff --git a/arch/mips/linux_process.hh b/arch/mips/linux/process.hh index 5408a6c44..68da3227b 100644 --- a/arch/mips/linux_process.hh +++ b/arch/mips/linux/process.hh @@ -29,16 +29,17 @@ #ifndef __MIPS_LINUX_PROCESS_HH__ #define __MIPS_LINUX_PROCESS_HH__ -#include "sim/process.hh" +#include "arch/mips/process.hh" /// A process with emulated Mips/Linux syscalls. -class MipsLinuxProcess : public LiveProcess +class MipsLinuxProcess : public MipsLiveProcess { public: /// Constructor. MipsLinuxProcess(const std::string &name, ObjectFile *objFile, + System *system, int stdin_fd, int stdout_fd, int stderr_fd, std::vector<std::string> &argv, std::vector<std::string> &envp); diff --git a/arch/mips/linux_process.cc b/arch/mips/linux_process.cc deleted file mode 100644 index 1d4f62350..000000000 --- a/arch/mips/linux_process.cc +++ /dev/null @@ -1,588 +0,0 @@ -/* - * Copyright (c) 2003-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. - */ - -#include "arch/mips/common_syscall_emul.hh" -#include "arch/mips/linux_process.hh" -#include "arch/mips/isa_traits.hh" - -#include "base/trace.hh" -#include "cpu/exec_context.hh" -#include "kern/linux/linux.hh" -#include "mem/functional/functional.hh" - -#include "sim/process.hh" -#include "sim/syscall_emul.hh" - -using namespace std; -using namespace MipsISA; - -/// Target uname() handler. -static SyscallReturn -unameFunc(SyscallDesc *desc, int callnum, Process *process, - ExecContext *xc) -{ - TypedBufferArg<Linux::utsname> name(xc->getSyscallArg(0)); - - strcpy(name->sysname, "Linux"); - strcpy(name->nodename, "m5.eecs.umich.edu"); - strcpy(name->release, "2.4.20"); - strcpy(name->version, "#1 Mon Aug 18 11:32:15 EDT 2003"); - strcpy(name->machine, "mips"); - - name.copyOut(xc->mem); - return 0; -} - -/// Target osf_getsysyinfo() handler. Even though this call is -/// borrowed from Tru64, the subcases that get used appear to be -/// different in practice from those used by Tru64 processes. -static SyscallReturn -osf_getsysinfoFunc(SyscallDesc *desc, int callnum, Process *process, - ExecContext *xc) -{ - unsigned op = xc->getSyscallArg(0); - // unsigned nbytes = xc->getSyscallArg(2); - - switch (op) { - - case 45: { // GSI_IEEE_FP_CONTROL - TypedBufferArg<uint64_t> fpcr(xc->getSyscallArg(1)); - // I don't think this exactly matches the HW FPCR - *fpcr = 0; - fpcr.copyOut(xc->mem); - return 0; - } - - default: - cerr << "osf_getsysinfo: unknown op " << op << endl; - abort(); - break; - } - - return 1; -} - -/// Target osf_setsysinfo() handler. -static SyscallReturn -osf_setsysinfoFunc(SyscallDesc *desc, int callnum, Process *process, - ExecContext *xc) -{ - unsigned op = xc->getSyscallArg(0); - // unsigned nbytes = xc->getSyscallArg(2); - - switch (op) { - - case 14: { // SSI_IEEE_FP_CONTROL - TypedBufferArg<uint64_t> fpcr(xc->getSyscallArg(1)); - // I don't think this exactly matches the HW FPCR - fpcr.copyIn(xc->mem); - DPRINTFR(SyscallVerbose, "osf_setsysinfo(SSI_IEEE_FP_CONTROL): " - " setting FPCR to 0x%x\n", gtoh(*(uint64_t*)fpcr)); - return 0; - } - - default: - cerr << "osf_setsysinfo: unknown op " << op << endl; - abort(); - break; - } - - return 1; -} - - -SyscallDesc MipsLinuxProcess::syscallDescs[] = { - /* 0 */ SyscallDesc("osf_syscall", unimplementedFunc), - /* 1 */ SyscallDesc("exit", exitFunc), - /* 2 */ SyscallDesc("fork", unimplementedFunc), - /* 3 */ SyscallDesc("read", readFunc), - /* 4 */ SyscallDesc("write", writeFunc), - /* 5 */ SyscallDesc("osf_old_open", unimplementedFunc), - /* 6 */ SyscallDesc("close", closeFunc), - /* 7 */ SyscallDesc("osf_wait4", unimplementedFunc), - /* 8 */ SyscallDesc("osf_old_creat", unimplementedFunc), - /* 9 */ SyscallDesc("link", unimplementedFunc), - /* 10 */ SyscallDesc("unlink", unlinkFunc), - /* 11 */ SyscallDesc("osf_execve", unimplementedFunc), - /* 12 */ SyscallDesc("chdir", unimplementedFunc), - /* 13 */ SyscallDesc("fchdir", unimplementedFunc), - /* 14 */ SyscallDesc("mknod", unimplementedFunc), - /* 15 */ SyscallDesc("chmod", chmodFunc<Linux>), - /* 16 */ SyscallDesc("chown", chownFunc), - /* 17 */ SyscallDesc("brk", obreakFunc), - /* 18 */ SyscallDesc("osf_getfsstat", unimplementedFunc), - /* 19 */ SyscallDesc("lseek", lseekFunc), - /* 20 */ SyscallDesc("getxpid", getpidFunc), - /* 21 */ SyscallDesc("osf_mount", unimplementedFunc), - /* 22 */ SyscallDesc("umount", unimplementedFunc), - /* 23 */ SyscallDesc("setuid", setuidFunc), - /* 24 */ SyscallDesc("getxuid", getuidFunc), - /* 25 */ SyscallDesc("exec_with_loader", unimplementedFunc), - /* 26 */ SyscallDesc("osf_ptrace", unimplementedFunc), - /* 27 */ SyscallDesc("osf_nrecvmsg", unimplementedFunc), - /* 28 */ SyscallDesc("osf_nsendmsg", unimplementedFunc), - /* 29 */ SyscallDesc("osf_nrecvfrom", unimplementedFunc), - /* 30 */ SyscallDesc("osf_naccept", unimplementedFunc), - /* 31 */ SyscallDesc("osf_ngetpeername", unimplementedFunc), - /* 32 */ SyscallDesc("osf_ngetsockname", unimplementedFunc), - /* 33 */ SyscallDesc("access", unimplementedFunc), - /* 34 */ SyscallDesc("osf_chflags", unimplementedFunc), - /* 35 */ SyscallDesc("osf_fchflags", unimplementedFunc), - /* 36 */ SyscallDesc("sync", unimplementedFunc), - /* 37 */ SyscallDesc("kill", unimplementedFunc), - /* 38 */ SyscallDesc("osf_old_stat", unimplementedFunc), - /* 39 */ SyscallDesc("setpgid", unimplementedFunc), - /* 40 */ SyscallDesc("osf_old_lstat", unimplementedFunc), - /* 41 */ SyscallDesc("dup", unimplementedFunc), - /* 42 */ SyscallDesc("pipe", unimplementedFunc), - /* 43 */ SyscallDesc("osf_set_program_attributes", unimplementedFunc), - /* 44 */ SyscallDesc("osf_profil", unimplementedFunc), - /* 45 */ SyscallDesc("open", openFunc<Linux>), - /* 46 */ SyscallDesc("osf_old_sigaction", unimplementedFunc), - /* 47 */ SyscallDesc("getxgid", getgidFunc), - /* 48 */ SyscallDesc("osf_sigprocmask", ignoreFunc), - /* 49 */ SyscallDesc("osf_getlogin", unimplementedFunc), - /* 50 */ SyscallDesc("osf_setlogin", unimplementedFunc), - /* 51 */ SyscallDesc("acct", unimplementedFunc), - /* 52 */ SyscallDesc("sigpending", unimplementedFunc), - /* 53 */ SyscallDesc("osf_classcntl", unimplementedFunc), - /* 54 */ SyscallDesc("ioctl", ioctlFunc<Linux>), - /* 55 */ SyscallDesc("osf_reboot", unimplementedFunc), - /* 56 */ SyscallDesc("osf_revoke", unimplementedFunc), - /* 57 */ SyscallDesc("symlink", unimplementedFunc), - /* 58 */ SyscallDesc("readlink", unimplementedFunc), - /* 59 */ SyscallDesc("execve", unimplementedFunc), - /* 60 */ SyscallDesc("umask", unimplementedFunc), - /* 61 */ SyscallDesc("chroot", unimplementedFunc), - /* 62 */ SyscallDesc("osf_old_fstat", unimplementedFunc), - /* 63 */ SyscallDesc("getpgrp", unimplementedFunc), - /* 64 */ SyscallDesc("getpagesize", getpagesizeFunc), - /* 65 */ SyscallDesc("osf_mremap", unimplementedFunc), - /* 66 */ SyscallDesc("vfork", unimplementedFunc), - /* 67 */ SyscallDesc("stat", statFunc<Linux>), - /* 68 */ SyscallDesc("lstat", lstatFunc<Linux>), - /* 69 */ SyscallDesc("osf_sbrk", unimplementedFunc), - /* 70 */ SyscallDesc("osf_sstk", unimplementedFunc), - /* 71 */ SyscallDesc("mmap", mmapFunc<Linux>), - /* 72 */ SyscallDesc("osf_old_vadvise", unimplementedFunc), - /* 73 */ SyscallDesc("munmap", munmapFunc), - /* 74 */ SyscallDesc("mprotect", ignoreFunc), - /* 75 */ SyscallDesc("madvise", unimplementedFunc), - /* 76 */ SyscallDesc("vhangup", unimplementedFunc), - /* 77 */ SyscallDesc("osf_kmodcall", unimplementedFunc), - /* 78 */ SyscallDesc("osf_mincore", unimplementedFunc), - /* 79 */ SyscallDesc("getgroups", unimplementedFunc), - /* 80 */ SyscallDesc("setgroups", unimplementedFunc), - /* 81 */ SyscallDesc("osf_old_getpgrp", unimplementedFunc), - /* 82 */ SyscallDesc("setpgrp", unimplementedFunc), - /* 83 */ SyscallDesc("osf_setitimer", unimplementedFunc), - /* 84 */ SyscallDesc("osf_old_wait", unimplementedFunc), - /* 85 */ SyscallDesc("osf_table", unimplementedFunc), - /* 86 */ SyscallDesc("osf_getitimer", unimplementedFunc), - /* 87 */ SyscallDesc("gethostname", gethostnameFunc), - /* 88 */ SyscallDesc("sethostname", unimplementedFunc), - /* 89 */ SyscallDesc("getdtablesize", unimplementedFunc), - /* 90 */ SyscallDesc("dup2", unimplementedFunc), - /* 91 */ SyscallDesc("fstat", fstatFunc<Linux>), - /* 92 */ SyscallDesc("fcntl", fcntlFunc), - /* 93 */ SyscallDesc("osf_select", unimplementedFunc), - /* 94 */ SyscallDesc("poll", unimplementedFunc), - /* 95 */ SyscallDesc("fsync", unimplementedFunc), - /* 96 */ SyscallDesc("setpriority", unimplementedFunc), - /* 97 */ SyscallDesc("socket", unimplementedFunc), - /* 98 */ SyscallDesc("connect", unimplementedFunc), - /* 99 */ SyscallDesc("accept", unimplementedFunc), - /* 100 */ SyscallDesc("getpriority", unimplementedFunc), - /* 101 */ SyscallDesc("send", unimplementedFunc), - /* 102 */ SyscallDesc("recv", unimplementedFunc), - /* 103 */ SyscallDesc("sigreturn", unimplementedFunc), - /* 104 */ SyscallDesc("bind", unimplementedFunc), - /* 105 */ SyscallDesc("setsockopt", unimplementedFunc), - /* 106 */ SyscallDesc("listen", unimplementedFunc), - /* 107 */ SyscallDesc("osf_plock", unimplementedFunc), - /* 108 */ SyscallDesc("osf_old_sigvec", unimplementedFunc), - /* 109 */ SyscallDesc("osf_old_sigblock", unimplementedFunc), - /* 110 */ SyscallDesc("osf_old_sigsetmask", unimplementedFunc), - /* 111 */ SyscallDesc("sigsuspend", unimplementedFunc), - /* 112 */ SyscallDesc("osf_sigstack", ignoreFunc), - /* 113 */ SyscallDesc("recvmsg", unimplementedFunc), - /* 114 */ SyscallDesc("sendmsg", unimplementedFunc), - /* 115 */ SyscallDesc("osf_old_vtrace", unimplementedFunc), - /* 116 */ SyscallDesc("osf_gettimeofday", unimplementedFunc), - /* 117 */ SyscallDesc("osf_getrusage", unimplementedFunc), - /* 118 */ SyscallDesc("getsockopt", unimplementedFunc), - /* 119 */ SyscallDesc("numa_syscalls", unimplementedFunc), - /* 120 */ SyscallDesc("readv", unimplementedFunc), - /* 121 */ SyscallDesc("writev", writevFunc<Linux>), - /* 122 */ SyscallDesc("osf_settimeofday", unimplementedFunc), - /* 123 */ SyscallDesc("fchown", fchownFunc), - /* 124 */ SyscallDesc("fchmod", fchmodFunc<Linux>), - /* 125 */ SyscallDesc("recvfrom", unimplementedFunc), - /* 126 */ SyscallDesc("setreuid", unimplementedFunc), - /* 127 */ SyscallDesc("setregid", unimplementedFunc), - /* 128 */ SyscallDesc("rename", renameFunc), - /* 129 */ SyscallDesc("truncate", unimplementedFunc), - /* 130 */ SyscallDesc("ftruncate", unimplementedFunc), - /* 131 */ SyscallDesc("flock", unimplementedFunc), - /* 132 */ SyscallDesc("setgid", unimplementedFunc), - /* 133 */ SyscallDesc("sendto", unimplementedFunc), - /* 134 */ SyscallDesc("shutdown", unimplementedFunc), - /* 135 */ SyscallDesc("socketpair", unimplementedFunc), - /* 136 */ SyscallDesc("mkdir", unimplementedFunc), - /* 137 */ SyscallDesc("rmdir", unimplementedFunc), - /* 138 */ SyscallDesc("osf_utimes", unimplementedFunc), - /* 139 */ SyscallDesc("osf_old_sigreturn", unimplementedFunc), - /* 140 */ SyscallDesc("osf_adjtime", unimplementedFunc), - /* 141 */ SyscallDesc("getpeername", unimplementedFunc), - /* 142 */ SyscallDesc("osf_gethostid", unimplementedFunc), - /* 143 */ SyscallDesc("osf_sethostid", unimplementedFunc), - /* 144 */ SyscallDesc("getrlimit", getrlimitFunc<Linux>), - /* 145 */ SyscallDesc("setrlimit", ignoreFunc), - /* 146 */ SyscallDesc("osf_old_killpg", unimplementedFunc), - /* 147 */ SyscallDesc("setsid", unimplementedFunc), - /* 148 */ SyscallDesc("quotactl", unimplementedFunc), - /* 149 */ SyscallDesc("osf_oldquota", unimplementedFunc), - /* 150 */ SyscallDesc("getsockname", unimplementedFunc), - /* 151 */ SyscallDesc("osf_pread", unimplementedFunc), - /* 152 */ SyscallDesc("osf_pwrite", unimplementedFunc), - /* 153 */ SyscallDesc("osf_pid_block", unimplementedFunc), - /* 154 */ SyscallDesc("osf_pid_unblock", unimplementedFunc), - /* 155 */ SyscallDesc("osf_signal_urti", unimplementedFunc), - /* 156 */ SyscallDesc("sigaction", ignoreFunc), - /* 157 */ SyscallDesc("osf_sigwaitprim", unimplementedFunc), - /* 158 */ SyscallDesc("osf_nfssvc", unimplementedFunc), - /* 159 */ SyscallDesc("osf_getdirentries", unimplementedFunc), - /* 160 */ SyscallDesc("osf_statfs", unimplementedFunc), - /* 161 */ SyscallDesc("osf_fstatfs", unimplementedFunc), - /* 162 */ SyscallDesc("unknown #162", unimplementedFunc), - /* 163 */ SyscallDesc("osf_async_daemon", unimplementedFunc), - /* 164 */ SyscallDesc("osf_getfh", unimplementedFunc), - /* 165 */ SyscallDesc("osf_getdomainname", unimplementedFunc), - /* 166 */ SyscallDesc("setdomainname", unimplementedFunc), - /* 167 */ SyscallDesc("unknown #167", unimplementedFunc), - /* 168 */ SyscallDesc("unknown #168", unimplementedFunc), - /* 169 */ SyscallDesc("osf_exportfs", unimplementedFunc), - /* 170 */ SyscallDesc("unknown #170", unimplementedFunc), - /* 171 */ SyscallDesc("unknown #171", unimplementedFunc), - /* 172 */ SyscallDesc("unknown #172", unimplementedFunc), - /* 173 */ SyscallDesc("unknown #173", unimplementedFunc), - /* 174 */ SyscallDesc("unknown #174", unimplementedFunc), - /* 175 */ SyscallDesc("unknown #175", unimplementedFunc), - /* 176 */ SyscallDesc("unknown #176", unimplementedFunc), - /* 177 */ SyscallDesc("unknown #177", unimplementedFunc), - /* 178 */ SyscallDesc("unknown #178", unimplementedFunc), - /* 179 */ SyscallDesc("unknown #179", unimplementedFunc), - /* 180 */ SyscallDesc("unknown #180", unimplementedFunc), - /* 181 */ SyscallDesc("osf_alt_plock", unimplementedFunc), - /* 182 */ SyscallDesc("unknown #182", unimplementedFunc), - /* 183 */ SyscallDesc("unknown #183", unimplementedFunc), - /* 184 */ SyscallDesc("osf_getmnt", unimplementedFunc), - /* 185 */ SyscallDesc("unknown #185", unimplementedFunc), - /* 186 */ SyscallDesc("unknown #186", unimplementedFunc), - /* 187 */ SyscallDesc("osf_alt_sigpending", unimplementedFunc), - /* 188 */ SyscallDesc("osf_alt_setsid", unimplementedFunc), - /* 189 */ SyscallDesc("unknown #189", unimplementedFunc), - /* 190 */ SyscallDesc("unknown #190", unimplementedFunc), - /* 191 */ SyscallDesc("unknown #191", unimplementedFunc), - /* 192 */ SyscallDesc("unknown #192", unimplementedFunc), - /* 193 */ SyscallDesc("unknown #193", unimplementedFunc), - /* 194 */ SyscallDesc("unknown #194", unimplementedFunc), - /* 195 */ SyscallDesc("unknown #195", unimplementedFunc), - /* 196 */ SyscallDesc("unknown #196", unimplementedFunc), - /* 197 */ SyscallDesc("unknown #197", unimplementedFunc), - /* 198 */ SyscallDesc("unknown #198", unimplementedFunc), - /* 199 */ SyscallDesc("osf_swapon", unimplementedFunc), - /* 200 */ SyscallDesc("msgctl", unimplementedFunc), - /* 201 */ SyscallDesc("msgget", unimplementedFunc), - /* 202 */ SyscallDesc("msgrcv", unimplementedFunc), - /* 203 */ SyscallDesc("msgsnd", unimplementedFunc), - /* 204 */ SyscallDesc("semctl", unimplementedFunc), - /* 205 */ SyscallDesc("semget", unimplementedFunc), - /* 206 */ SyscallDesc("semop", unimplementedFunc), - /* 207 */ SyscallDesc("osf_utsname", unimplementedFunc), - /* 208 */ SyscallDesc("lchown", unimplementedFunc), - /* 209 */ SyscallDesc("osf_shmat", unimplementedFunc), - /* 210 */ SyscallDesc("shmctl", unimplementedFunc), - /* 211 */ SyscallDesc("shmdt", unimplementedFunc), - /* 212 */ SyscallDesc("shmget", unimplementedFunc), - /* 213 */ SyscallDesc("osf_mvalid", unimplementedFunc), - /* 214 */ SyscallDesc("osf_getaddressconf", unimplementedFunc), - /* 215 */ SyscallDesc("osf_msleep", unimplementedFunc), - /* 216 */ SyscallDesc("osf_mwakeup", unimplementedFunc), - /* 217 */ SyscallDesc("msync", unimplementedFunc), - /* 218 */ SyscallDesc("osf_signal", unimplementedFunc), - /* 219 */ SyscallDesc("osf_utc_gettime", unimplementedFunc), - /* 220 */ SyscallDesc("osf_utc_adjtime", unimplementedFunc), - /* 221 */ SyscallDesc("unknown #221", unimplementedFunc), - /* 222 */ SyscallDesc("osf_security", unimplementedFunc), - /* 223 */ SyscallDesc("osf_kloadcall", unimplementedFunc), - /* 224 */ SyscallDesc("unknown #224", unimplementedFunc), - /* 225 */ SyscallDesc("unknown #225", unimplementedFunc), - /* 226 */ SyscallDesc("unknown #226", unimplementedFunc), - /* 227 */ SyscallDesc("unknown #227", unimplementedFunc), - /* 228 */ SyscallDesc("unknown #228", unimplementedFunc), - /* 229 */ SyscallDesc("unknown #229", unimplementedFunc), - /* 230 */ SyscallDesc("unknown #230", unimplementedFunc), - /* 231 */ SyscallDesc("unknown #231", unimplementedFunc), - /* 232 */ SyscallDesc("unknown #232", unimplementedFunc), - /* 233 */ SyscallDesc("getpgid", unimplementedFunc), - /* 234 */ SyscallDesc("getsid", unimplementedFunc), - /* 235 */ SyscallDesc("sigaltstack", ignoreFunc), - /* 236 */ SyscallDesc("osf_waitid", unimplementedFunc), - /* 237 */ SyscallDesc("osf_priocntlset", unimplementedFunc), - /* 238 */ SyscallDesc("osf_sigsendset", unimplementedFunc), - /* 239 */ SyscallDesc("osf_set_speculative", unimplementedFunc), - /* 240 */ SyscallDesc("osf_msfs_syscall", unimplementedFunc), - /* 241 */ SyscallDesc("osf_sysinfo", unimplementedFunc), - /* 242 */ SyscallDesc("osf_uadmin", unimplementedFunc), - /* 243 */ SyscallDesc("osf_fuser", unimplementedFunc), - /* 244 */ SyscallDesc("osf_proplist_syscall", unimplementedFunc), - /* 245 */ SyscallDesc("osf_ntp_adjtime", unimplementedFunc), - /* 246 */ SyscallDesc("osf_ntp_gettime", unimplementedFunc), - /* 247 */ SyscallDesc("osf_pathconf", unimplementedFunc), - /* 248 */ SyscallDesc("osf_fpathconf", unimplementedFunc), - /* 249 */ SyscallDesc("unknown #249", unimplementedFunc), - /* 250 */ SyscallDesc("osf_uswitch", unimplementedFunc), - /* 251 */ SyscallDesc("osf_usleep_thread", unimplementedFunc), - /* 252 */ SyscallDesc("osf_audcntl", unimplementedFunc), - /* 253 */ SyscallDesc("osf_audgen", unimplementedFunc), - /* 254 */ SyscallDesc("sysfs", unimplementedFunc), - /* 255 */ SyscallDesc("osf_subsys_info", unimplementedFunc), - /* 256 */ SyscallDesc("osf_getsysinfo", osf_getsysinfoFunc), - /* 257 */ SyscallDesc("osf_setsysinfo", osf_setsysinfoFunc), - /* 258 */ SyscallDesc("osf_afs_syscall", unimplementedFunc), - /* 259 */ SyscallDesc("osf_swapctl", unimplementedFunc), - /* 260 */ SyscallDesc("osf_memcntl", unimplementedFunc), - /* 261 */ SyscallDesc("osf_fdatasync", unimplementedFunc), - /* 262 */ SyscallDesc("unknown #262", unimplementedFunc), - /* 263 */ SyscallDesc("unknown #263", unimplementedFunc), - /* 264 */ SyscallDesc("unknown #264", unimplementedFunc), - /* 265 */ SyscallDesc("unknown #265", unimplementedFunc), - /* 266 */ SyscallDesc("unknown #266", unimplementedFunc), - /* 267 */ SyscallDesc("unknown #267", unimplementedFunc), - /* 268 */ SyscallDesc("unknown #268", unimplementedFunc), - /* 269 */ SyscallDesc("unknown #269", unimplementedFunc), - /* 270 */ SyscallDesc("unknown #270", unimplementedFunc), - /* 271 */ SyscallDesc("unknown #271", unimplementedFunc), - /* 272 */ SyscallDesc("unknown #272", unimplementedFunc), - /* 273 */ SyscallDesc("unknown #273", unimplementedFunc), - /* 274 */ SyscallDesc("unknown #274", unimplementedFunc), - /* 275 */ SyscallDesc("unknown #275", unimplementedFunc), - /* 276 */ SyscallDesc("unknown #276", unimplementedFunc), - /* 277 */ SyscallDesc("unknown #277", unimplementedFunc), - /* 278 */ SyscallDesc("unknown #278", unimplementedFunc), - /* 279 */ SyscallDesc("unknown #279", unimplementedFunc), - /* 280 */ SyscallDesc("unknown #280", unimplementedFunc), - /* 281 */ SyscallDesc("unknown #281", unimplementedFunc), - /* 282 */ SyscallDesc("unknown #282", unimplementedFunc), - /* 283 */ SyscallDesc("unknown #283", unimplementedFunc), - /* 284 */ SyscallDesc("unknown #284", unimplementedFunc), - /* 285 */ SyscallDesc("unknown #285", unimplementedFunc), - /* 286 */ SyscallDesc("unknown #286", unimplementedFunc), - /* 287 */ SyscallDesc("unknown #287", unimplementedFunc), - /* 288 */ SyscallDesc("unknown #288", unimplementedFunc), - /* 289 */ SyscallDesc("unknown #289", unimplementedFunc), - /* 290 */ SyscallDesc("unknown #290", unimplementedFunc), - /* 291 */ SyscallDesc("unknown #291", unimplementedFunc), - /* 292 */ SyscallDesc("unknown #292", unimplementedFunc), - /* 293 */ SyscallDesc("unknown #293", unimplementedFunc), - /* 294 */ SyscallDesc("unknown #294", unimplementedFunc), - /* 295 */ SyscallDesc("unknown #295", unimplementedFunc), - /* 296 */ SyscallDesc("unknown #296", unimplementedFunc), - /* 297 */ SyscallDesc("unknown #297", unimplementedFunc), - /* 298 */ SyscallDesc("unknown #298", unimplementedFunc), - /* 299 */ SyscallDesc("unknown #299", unimplementedFunc), -/* - * Linux-specific system calls begin at 300 - */ - /* 300 */ SyscallDesc("bdflush", unimplementedFunc), - /* 301 */ SyscallDesc("sethae", unimplementedFunc), - /* 302 */ SyscallDesc("mount", unimplementedFunc), - /* 303 */ SyscallDesc("old_adjtimex", unimplementedFunc), - /* 304 */ SyscallDesc("swapoff", unimplementedFunc), - /* 305 */ SyscallDesc("getdents", unimplementedFunc), - /* 306 */ SyscallDesc("create_module", unimplementedFunc), - /* 307 */ SyscallDesc("init_module", unimplementedFunc), - /* 308 */ SyscallDesc("delete_module", unimplementedFunc), - /* 309 */ SyscallDesc("get_kernel_syms", unimplementedFunc), - /* 310 */ SyscallDesc("syslog", unimplementedFunc), - /* 311 */ SyscallDesc("reboot", unimplementedFunc), - /* 312 */ SyscallDesc("clone", unimplementedFunc), - /* 313 */ SyscallDesc("uselib", unimplementedFunc), - /* 314 */ SyscallDesc("mlock", unimplementedFunc), - /* 315 */ SyscallDesc("munlock", unimplementedFunc), - /* 316 */ SyscallDesc("mlockall", unimplementedFunc), - /* 317 */ SyscallDesc("munlockall", unimplementedFunc), - /* 318 */ SyscallDesc("sysinfo", unimplementedFunc), - /* 319 */ SyscallDesc("_sysctl", unimplementedFunc), - /* 320 */ SyscallDesc("was sys_idle", unimplementedFunc), - /* 321 */ SyscallDesc("oldumount", unimplementedFunc), - /* 322 */ SyscallDesc("swapon", unimplementedFunc), - /* 323 */ SyscallDesc("times", ignoreFunc), - /* 324 */ SyscallDesc("personality", unimplementedFunc), - /* 325 */ SyscallDesc("setfsuid", unimplementedFunc), - /* 326 */ SyscallDesc("setfsgid", unimplementedFunc), - /* 327 */ SyscallDesc("ustat", unimplementedFunc), - /* 328 */ SyscallDesc("statfs", unimplementedFunc), - /* 329 */ SyscallDesc("fstatfs", unimplementedFunc), - /* 330 */ SyscallDesc("sched_setparam", unimplementedFunc), - /* 331 */ SyscallDesc("sched_getparam", unimplementedFunc), - /* 332 */ SyscallDesc("sched_setscheduler", unimplementedFunc), - /* 333 */ SyscallDesc("sched_getscheduler", unimplementedFunc), - /* 334 */ SyscallDesc("sched_yield", unimplementedFunc), - /* 335 */ SyscallDesc("sched_get_priority_max", unimplementedFunc), - /* 336 */ SyscallDesc("sched_get_priority_min", unimplementedFunc), - /* 337 */ SyscallDesc("sched_rr_get_interval", unimplementedFunc), - /* 338 */ SyscallDesc("afs_syscall", unimplementedFunc), - /* 339 */ SyscallDesc("uname", unameFunc), - /* 340 */ SyscallDesc("nanosleep", unimplementedFunc), - /* 341 */ SyscallDesc("mremap", unimplementedFunc), - /* 342 */ SyscallDesc("nfsservctl", unimplementedFunc), - /* 343 */ SyscallDesc("setresuid", unimplementedFunc), - /* 344 */ SyscallDesc("getresuid", unimplementedFunc), - /* 345 */ SyscallDesc("pciconfig_read", unimplementedFunc), - /* 346 */ SyscallDesc("pciconfig_write", unimplementedFunc), - /* 347 */ SyscallDesc("query_module", unimplementedFunc), - /* 348 */ SyscallDesc("prctl", unimplementedFunc), - /* 349 */ SyscallDesc("pread", unimplementedFunc), - /* 350 */ SyscallDesc("pwrite", unimplementedFunc), - /* 351 */ SyscallDesc("rt_sigreturn", unimplementedFunc), - /* 352 */ SyscallDesc("rt_sigaction", ignoreFunc), - /* 353 */ SyscallDesc("rt_sigprocmask", unimplementedFunc), - /* 354 */ SyscallDesc("rt_sigpending", unimplementedFunc), - /* 355 */ SyscallDesc("rt_sigtimedwait", unimplementedFunc), - /* 356 */ SyscallDesc("rt_sigqueueinfo", unimplementedFunc), - /* 357 */ SyscallDesc("rt_sigsuspend", unimplementedFunc), - /* 358 */ SyscallDesc("select", unimplementedFunc), - /* 359 */ SyscallDesc("gettimeofday", gettimeofdayFunc<Linux>), - /* 360 */ SyscallDesc("settimeofday", unimplementedFunc), - /* 361 */ SyscallDesc("getitimer", unimplementedFunc), - /* 362 */ SyscallDesc("setitimer", unimplementedFunc), - /* 363 */ SyscallDesc("utimes", utimesFunc<Linux>), - /* 364 */ SyscallDesc("getrusage", getrusageFunc<Linux>), - /* 365 */ SyscallDesc("wait4", unimplementedFunc), - /* 366 */ SyscallDesc("adjtimex", unimplementedFunc), - /* 367 */ SyscallDesc("getcwd", unimplementedFunc), - /* 368 */ SyscallDesc("capget", unimplementedFunc), - /* 369 */ SyscallDesc("capset", unimplementedFunc), - /* 370 */ SyscallDesc("sendfile", unimplementedFunc), - /* 371 */ SyscallDesc("setresgid", unimplementedFunc), - /* 372 */ SyscallDesc("getresgid", unimplementedFunc), - /* 373 */ SyscallDesc("dipc", unimplementedFunc), - /* 374 */ SyscallDesc("pivot_root", unimplementedFunc), - /* 375 */ SyscallDesc("mincore", unimplementedFunc), - /* 376 */ SyscallDesc("pciconfig_iobase", unimplementedFunc), - /* 377 */ SyscallDesc("getdents64", unimplementedFunc), - /* 378 */ SyscallDesc("gettid", unimplementedFunc), - /* 379 */ SyscallDesc("readahead", unimplementedFunc), - /* 380 */ SyscallDesc("security", unimplementedFunc), - /* 381 */ SyscallDesc("tkill", unimplementedFunc), - /* 382 */ SyscallDesc("setxattr", unimplementedFunc), - /* 383 */ SyscallDesc("lsetxattr", unimplementedFunc), - /* 384 */ SyscallDesc("fsetxattr", unimplementedFunc), - /* 385 */ SyscallDesc("getxattr", unimplementedFunc), - /* 386 */ SyscallDesc("lgetxattr", unimplementedFunc), - /* 387 */ SyscallDesc("fgetxattr", unimplementedFunc), - /* 388 */ SyscallDesc("listxattr", unimplementedFunc), - /* 389 */ SyscallDesc("llistxattr", unimplementedFunc), - /* 390 */ SyscallDesc("flistxattr", unimplementedFunc), - /* 391 */ SyscallDesc("removexattr", unimplementedFunc), - /* 392 */ SyscallDesc("lremovexattr", unimplementedFunc), - /* 393 */ SyscallDesc("fremovexattr", unimplementedFunc), - /* 394 */ SyscallDesc("futex", unimplementedFunc), - /* 395 */ SyscallDesc("sched_setaffinity", unimplementedFunc), - /* 396 */ SyscallDesc("sched_getaffinity", unimplementedFunc), - /* 397 */ SyscallDesc("tuxcall", unimplementedFunc), - /* 398 */ SyscallDesc("io_setup", unimplementedFunc), - /* 399 */ SyscallDesc("io_destroy", unimplementedFunc), - /* 400 */ SyscallDesc("io_getevents", unimplementedFunc), - /* 401 */ SyscallDesc("io_submit", unimplementedFunc), - /* 402 */ SyscallDesc("io_cancel", unimplementedFunc), - /* 403 */ SyscallDesc("unknown #403", unimplementedFunc), - /* 404 */ SyscallDesc("unknown #404", unimplementedFunc), - /* 405 */ SyscallDesc("exit_group", exitFunc), // exit all threads... - /* 406 */ SyscallDesc("lookup_dcookie", unimplementedFunc), - /* 407 */ SyscallDesc("sys_epoll_create", unimplementedFunc), - /* 408 */ SyscallDesc("sys_epoll_ctl", unimplementedFunc), - /* 409 */ SyscallDesc("sys_epoll_wait", unimplementedFunc), - /* 410 */ SyscallDesc("remap_file_pages", unimplementedFunc), - /* 411 */ SyscallDesc("set_tid_address", unimplementedFunc), - /* 412 */ SyscallDesc("restart_syscall", unimplementedFunc), - /* 413 */ SyscallDesc("fadvise64", unimplementedFunc), - /* 414 */ SyscallDesc("timer_create", unimplementedFunc), - /* 415 */ SyscallDesc("timer_settime", unimplementedFunc), - /* 416 */ SyscallDesc("timer_gettime", unimplementedFunc), - /* 417 */ SyscallDesc("timer_getoverrun", unimplementedFunc), - /* 418 */ SyscallDesc("timer_delete", unimplementedFunc), - /* 419 */ SyscallDesc("clock_settime", unimplementedFunc), - /* 420 */ SyscallDesc("clock_gettime", unimplementedFunc), - /* 421 */ SyscallDesc("clock_getres", unimplementedFunc), - /* 422 */ SyscallDesc("clock_nanosleep", unimplementedFunc), - /* 423 */ SyscallDesc("semtimedop", unimplementedFunc), - /* 424 */ SyscallDesc("tgkill", unimplementedFunc), - /* 425 */ SyscallDesc("stat64", unimplementedFunc), - /* 426 */ SyscallDesc("lstat64", lstat64Func<Linux>), - /* 427 */ SyscallDesc("fstat64", fstat64Func<Linux>), - /* 428 */ SyscallDesc("vserver", unimplementedFunc), - /* 429 */ SyscallDesc("mbind", unimplementedFunc), - /* 430 */ SyscallDesc("get_mempolicy", unimplementedFunc), - /* 431 */ SyscallDesc("set_mempolicy", unimplementedFunc), - /* 432 */ SyscallDesc("mq_open", unimplementedFunc), - /* 433 */ SyscallDesc("mq_unlink", unimplementedFunc), - /* 434 */ SyscallDesc("mq_timedsend", unimplementedFunc), - /* 435 */ SyscallDesc("mq_timedreceive", unimplementedFunc), - /* 436 */ SyscallDesc("mq_notify", unimplementedFunc), - /* 437 */ SyscallDesc("mq_getsetattr", unimplementedFunc), - /* 438 */ SyscallDesc("waitid", unimplementedFunc), - /* 439 */ SyscallDesc("add_key", unimplementedFunc), - /* 440 */ SyscallDesc("request_key", unimplementedFunc), - /* 441 */ SyscallDesc("keyctl", unimplementedFunc) -}; - -MipsLinuxProcess::MipsLinuxProcess(const std::string &name, - ObjectFile *objFile, - int stdin_fd, - int stdout_fd, - int stderr_fd, - std::vector<std::string> &argv, - std::vector<std::string> &envp) - : LiveProcess(name, objFile, stdin_fd, stdout_fd, stderr_fd, argv, envp), - Num_Syscall_Descs(sizeof(syscallDescs) / sizeof(SyscallDesc)) -{ - init_regs->intRegFile[0] = 0; -} - - - -SyscallDesc* -MipsLinuxProcess::getDesc(int callnum) -{ - if (callnum < 0 || callnum > Num_Syscall_Descs) - return NULL; - return &syscallDescs[callnum]; -} diff --git a/arch/mips/process.cc b/arch/mips/process.cc index 6de44fe9f..7831551be 100644 --- a/arch/mips/process.cc +++ b/arch/mips/process.cc @@ -26,22 +26,37 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +#include "arch/mips/isa_traits.hh" #include "arch/mips/process.hh" +#include "arch/mips/linux/process.hh" +#include "base/loader/object_file.hh" +#include "base/misc.hh" +#include "cpu/exec_context.hh" +#include "sim/builder.hh" +#include "sim/system.hh" + +using namespace std; +using namespace MipsISA; -namespace MipsISA -{ -LiveProcess * -createProcess(const string &nm, ObjectFile * objFile, - int stdin_fd, int stdout_fd, int stderr_fd, - vector<string> &argv, vector<string> &envp) +MipsLiveProcess * +MipsLiveProcess::create(const std::string &nm, System *system, int stdin_fd, + int stdout_fd, int stderr_fd, std::string executable, + std::vector<std::string> &argv, std::vector<std::string> &envp) { - LiveProcess * process = NULL; - if (objFile->getArch() != ObjectFile::MIPS) + MipsLiveProcess *process = NULL; + + ObjectFile *objFile = createObjectFile(executable); + if (objFile == NULL) { + fatal("Can't load object file %s", executable); + } + + + if (objFile->getArch() != ObjectFile::Mips) fatal("Object file does not match architecture."); switch (objFile->getOpSys()) { case ObjectFile::Linux: - process = new MipsLinuxProcess(nm, objFile, + process = new MipsLinuxProcess(nm, objFile, system, stdin_fd, stdout_fd, stderr_fd, argv, envp); break; @@ -49,8 +64,98 @@ createProcess(const string &nm, ObjectFile * objFile, default: fatal("Unknown/unsupported operating system."); } + + if (process == NULL) + fatal("Unknown error creating process object."); return process; } -} // namespace MipsISA +MipsLiveProcess::MipsLiveProcess(const std::string &nm, ObjectFile *objFile, + System *_system, int stdin_fd, int stdout_fd, int stderr_fd, + std::vector<std::string> &argv, std::vector<std::string> &envp) + : LiveProcess(nm, objFile, _system, stdin_fd, stdout_fd, stderr_fd, + argv, envp) +{ + + // XXX all the below need to be updated for SPARC - Ali + brk_point = objFile->dataBase() + objFile->dataSize() + objFile->bssSize(); + brk_point = roundUp(brk_point, VMPageSize); + + // Set up stack. On Alpha, stack goes below text section. This + // code should get moved to some architecture-specific spot. + stack_base = objFile->textBase() - (409600+4096); + + // Set up region for mmaps. Tru64 seems to start just above 0 and + // grow up from there. + mmap_start = mmap_end = 0x10000; + + // Set pointer for next thread stack. Reserve 8M for main stack. + next_thread_stack_base = stack_base - (8 * 1024 * 1024); + +} + +void +MipsLiveProcess::startup() +{ + argsInit(MachineBytes, VMPageSize); +} + + + + +BEGIN_DECLARE_SIM_OBJECT_PARAMS(MipsLiveProcess) + + VectorParam<string> cmd; + Param<string> executable; + Param<string> input; + Param<string> output; + VectorParam<string> env; + SimObjectParam<System *> system; + +END_DECLARE_SIM_OBJECT_PARAMS(MipsLiveProcess) + + +BEGIN_INIT_SIM_OBJECT_PARAMS(MipsLiveProcess) + + INIT_PARAM(cmd, "command line (executable plus arguments)"), + INIT_PARAM(executable, "executable (overrides cmd[0] if set)"), + INIT_PARAM(input, "filename for stdin (dflt: use sim stdin)"), + INIT_PARAM(output, "filename for stdout/stderr (dflt: use sim stdout)"), + INIT_PARAM(env, "environment settings"), + INIT_PARAM(system, "system") + +END_INIT_SIM_OBJECT_PARAMS(MipsLiveProcess) + + +CREATE_SIM_OBJECT(MipsLiveProcess) +{ + string in = input; + string out = output; + + // initialize file descriptors to default: same as simulator + int stdin_fd, stdout_fd, stderr_fd; + + if (in == "stdin" || in == "cin") + stdin_fd = STDIN_FILENO; + else + stdin_fd = Process::openInputFile(input); + + if (out == "stdout" || out == "cout") + stdout_fd = STDOUT_FILENO; + else if (out == "stderr" || out == "cerr") + stdout_fd = STDERR_FILENO; + else + stdout_fd = Process::openOutputFile(out); + + stderr_fd = (stdout_fd != STDOUT_FILENO) ? stdout_fd : STDERR_FILENO; + + return MipsLiveProcess::create(getInstanceName(), system, + stdin_fd, stdout_fd, stderr_fd, + (string)executable == "" ? cmd[0] : executable, + cmd, env); +} + + +REGISTER_SIM_OBJECT("MipsLiveProcess", MipsLiveProcess) + diff --git a/arch/mips/process.hh b/arch/mips/process.hh index ab4323107..2a13dc955 100644 --- a/arch/mips/process.hh +++ b/arch/mips/process.hh @@ -29,17 +29,36 @@ #ifndef __MIPS_PROCESS_HH__ #define __MIPS_PROCESS_HH__ -#include "arch/mips/linux_process.hh" -#include "base/loader/object_file.hh" +#include <string> +#include <vector> +#include "sim/process.hh" -namespace MipsISA +class LiveProcess; +class ObjectFile; +class System; + +class MipsLiveProcess : public LiveProcess { + protected: + MipsLiveProcess(const std::string &nm, ObjectFile *objFile, + System *_system, int stdin_fd, int stdout_fd, int stderr_fd, + std::vector<std::string> &argv, + std::vector<std::string> &envp); + + void startup(); + + public: + // this function is used to create the LiveProcess object, since + // we can't tell which subclass of LiveProcess to use until we + // open and look at the object file. + static MipsLiveProcess *create(const std::string &nm, + System *_system, + int stdin_fd, int stdout_fd, int stderr_fd, + std::string executable, + std::vector<std::string> &argv, + std::vector<std::string> &envp); -LiveProcess * -createProcess(const string &nm, ObjectFile * objFile, - int stdin_fd, int stdout_fd, int stderr_fd, - vector<string> &argv, vector<string> &envp); +}; -} // namespace MipsISA #endif // __MIPS_PROCESS_HH__ diff --git a/arch/mips/regfile/float_regfile.hh b/arch/mips/regfile/float_regfile.hh new file mode 100644 index 000000000..15c6f97f4 --- /dev/null +++ b/arch/mips/regfile/float_regfile.hh @@ -0,0 +1,159 @@ +/* + * Copyright (c) 2003-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. + */ + +#ifndef __ARCH_MIPS_FLOAT_REGFILE_HH__ +#define __ARCH_MIPS_FLOAT_REGFILE_HH__ + +#include "arch/mips/types.hh" +#include "arch/mips/constants.hh" +#include "base/misc.hh" +#include "config/full_system.hh" +#include "sim/byteswap.hh" +#include "sim/faults.hh" +#include "sim/host.hh" + +class Checkpoint; +class ExecContext; +class Regfile; + +namespace MipsISA +{ + class FloatRegFile + { + protected: + FloatReg32 regs[NumFloatRegs]; + + public: + + void clear() + { + bzero(regs, sizeof(regs)); + } + + double readReg(int floatReg, int width) + { + switch(width) + { + case SingleWidth: + void *float_ptr = ®s[floatReg]; + return *(float *) float_ptr; + + case DoubleWidth: + uint64_t double_val = (FloatReg64)regs[floatReg + 1] << 32 | regs[floatReg]; + void *double_ptr = &double_val; + return *(double *) double_ptr; + + default: + panic("Attempted to read a %d bit floating point register!", width); + } + } + + FloatRegBits readRegBits(int floatReg, int width) + { + if (floatReg < NumFloatArchRegs - 1) { + switch(width) + { + case SingleWidth: + return regs[floatReg]; + + case DoubleWidth: + return (FloatReg64)regs[floatReg + 1] << 32 | regs[floatReg]; + + default: + panic("Attempted to read a %d bit floating point register!", width); + } + } else { + if (width > SingleWidth) + assert("Control Regs are only 32 bits wide"); + + return regs[floatReg]; + } + } + + Fault setReg(int floatReg, const FloatReg &val, int width) + { + + switch(width) + { + case SingleWidth: + float temp = val; + void *float_ptr = &temp; + regs[floatReg] = *(FloatReg32 *) float_ptr; + break; + + case DoubleWidth: + const void *double_ptr = &val; + FloatReg64 temp_double = *(FloatReg64 *) double_ptr; + regs[floatReg + 1] = temp_double >> 32; + regs[floatReg] = temp_double; + break; + + default: + panic("Attempted to read a %d bit floating point register!", width); + } + + return NoFault; + } + + Fault setRegBits(int floatReg, const FloatRegBits &val, int width) + { + using namespace std; + + switch(width) + { + case SingleWidth: + regs[floatReg] = val; + break; + + case DoubleWidth: + regs[floatReg + 1] = val >> 32; + regs[floatReg] = val; + break; + + default: + panic("Attempted to read a %d bit floating point register!", width); + } + return NoFault; + } + + void serialize(std::ostream &os); + + void unserialize(Checkpoint *cp, const std::string §ion); + }; + + enum MiscFloatRegNums { + FIR = NumFloatArchRegs, + FCCR, + FEXR, + FENR, + FCSR + }; + +} // namespace MipsISA + +#endif diff --git a/arch/mips/regfile/int_regfile.hh b/arch/mips/regfile/int_regfile.hh new file mode 100644 index 000000000..3cd87734d --- /dev/null +++ b/arch/mips/regfile/int_regfile.hh @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2003-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. + */ + +#ifndef __ARCH_MIPS_INT_REGFILE_HH__ +#define __ARCH_MIPS_INT_REGFILE_HH__ + +#include "arch/mips/types.hh" +#include "arch/mips/constants.hh" +#include "base/misc.hh" +#include "sim/faults.hh" + +class Checkpoint; +class ExecContext; +class Regfile; + +namespace MipsISA +{ + class IntRegFile + { + protected: + IntReg regs[NumIntRegs]; + + public: + IntReg readReg(int intReg) + { + return regs[intReg]; + } + + Fault setReg(int intReg, const IntReg &val) + { + regs[intReg] = val; + return NoFault; + } + + void serialize(std::ostream &os); + + void unserialize(Checkpoint *cp, const std::string §ion); + + }; + + enum MiscIntRegNums { + HI = NumIntArchRegs, + LO + }; + +} // namespace MipsISA + +#endif diff --git a/arch/mips/regfile/misc_regfile.hh b/arch/mips/regfile/misc_regfile.hh new file mode 100644 index 000000000..9f054e5f7 --- /dev/null +++ b/arch/mips/regfile/misc_regfile.hh @@ -0,0 +1,96 @@ +/* + * Copyright (c) 2003-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. + */ + +#ifndef __ARCH_MIPS_MISC_REGFILE_HH__ +#define __ARCH_MIPS_MISC_REGFILE_HH__ + +#include "arch/mips/types.hh" +#include "arch/mips/constants.hh" +#include "sim/faults.hh" + +class Checkpoint; +class ExecContext; +class Regfile; + +namespace MipsISA +{ + class MiscRegFile { + + protected: + uint64_t fpcr; // floating point condition codes + uint64_t uniq; // process-unique register + bool lock_flag; // lock flag for LL/SC + Addr lock_addr; // lock address for LL/SC + + MiscReg miscRegFile[NumMiscRegs]; + + public: + //These functions should be removed once the simplescalar cpu model + //has been replaced. + int getInstAsid(); + int getDataAsid(); + + void copyMiscRegs(ExecContext *xc); + + MiscReg readReg(int misc_reg) + { + return miscRegFile[misc_reg]; + } + + MiscReg readRegWithEffect(int misc_reg, Fault &fault, ExecContext *xc) + { + return miscRegFile[misc_reg]; + } + + Fault setReg(int misc_reg, const MiscReg &val) + { + miscRegFile[misc_reg] = val; return NoFault; + } + + Fault setRegWithEffect(int misc_reg, const MiscReg &val, + ExecContext *xc) + { + miscRegFile[misc_reg] = val; return NoFault; + } + +#if FULL_SYSTEM + void clearIprs() { } + + protected: + InternalProcReg ipr[NumInternalProcRegs]; // Internal processor regs + + private: + MiscReg readIpr(int idx, Fault &fault, ExecContext *xc) { } + + Fault setIpr(int idx, uint64_t val, ExecContext *xc) { } +#endif + friend class RegFile; + }; +} // namespace MipsISA + +#endif diff --git a/arch/mips/regfile/regfile.hh b/arch/mips/regfile/regfile.hh new file mode 100644 index 000000000..e77571b33 --- /dev/null +++ b/arch/mips/regfile/regfile.hh @@ -0,0 +1,199 @@ +/* + * Copyright (c) 2003-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. + */ + +#ifndef __ARCH_MIPS_REGFILE_HH__ +#define __ARCH_MIPS_REGFILE_HH__ + +#include "arch/mips/types.hh" +#include "arch/mips/constants.hh" +#include "arch/mips/regfile/int_regfile.hh" +#include "arch/mips/regfile/float_regfile.hh" +#include "arch/mips/regfile/misc_regfile.hh" +#include "sim/faults.hh" + +class Checkpoint; +class ExecContext; + +namespace MipsISA +{ + class RegFile { + protected: + IntRegFile intRegFile; // (signed) integer register file + FloatRegFile floatRegFile; // floating point register file + MiscRegFile miscRegFile; // control register file + + public: + + void clear() + { + bzero(&intRegFile, sizeof(intRegFile)); + bzero(&floatRegFile, sizeof(floatRegFile)); + bzero(&miscRegFile, sizeof(miscRegFile)); + } + + MiscReg readMiscReg(int miscReg) + { + return miscRegFile.readReg(miscReg); + } + + MiscReg readMiscRegWithEffect(int miscReg, + Fault &fault, ExecContext *xc) + { + fault = NoFault; + return miscRegFile.readRegWithEffect(miscReg, fault, xc); + } + + Fault setMiscReg(int miscReg, const MiscReg &val) + { + return miscRegFile.setReg(miscReg, val); + } + + Fault setMiscRegWithEffect(int miscReg, const MiscReg &val, + ExecContext * xc) + { + return miscRegFile.setRegWithEffect(miscReg, val, xc); + } + + FloatReg readFloatReg(int floatReg) + { + return floatRegFile.readReg(floatReg,SingleWidth); + } + + FloatReg readFloatReg(int floatReg, int width) + { + return floatRegFile.readReg(floatReg,width); + } + + FloatRegBits readFloatRegBits(int floatReg) + { + return floatRegFile.readRegBits(floatReg,SingleWidth); + } + + FloatRegBits readFloatRegBits(int floatReg, int width) + { + return floatRegFile.readRegBits(floatReg,width); + } + + Fault setFloatReg(int floatReg, const FloatReg &val) + { + return floatRegFile.setReg(floatReg, val, SingleWidth); + } + + Fault setFloatReg(int floatReg, const FloatReg &val, int width) + { + return floatRegFile.setReg(floatReg, val, width); + } + + Fault setFloatRegBits(int floatReg, const FloatRegBits &val) + { + return floatRegFile.setRegBits(floatReg, val, SingleWidth); + } + + Fault setFloatRegBits(int floatReg, const FloatRegBits &val, int width) + { + return floatRegFile.setRegBits(floatReg, val, width); + } + + IntReg readIntReg(int intReg) + { + return intRegFile.readReg(intReg); + } + + Fault setIntReg(int intReg, const IntReg &val) + { + return intRegFile.setReg(intReg, val); + } + protected: + + Addr pc; // program counter + Addr npc; // next-cycle program counter + Addr nnpc; // next-next-cycle program counter + // used to implement branch delay slot + // not real register + public: + Addr readPC() + { + return pc; + } + + void setPC(Addr val) + { + pc = val; + } + + Addr readNextPC() + { + return npc; + } + + void setNextPC(Addr val) + { + npc = val; + } + + Addr readNextNPC() + { + return nnpc; + } + + void setNextNPC(Addr val) + { + nnpc = val; + } + + +#if FULL_SYSTEM + IntReg palregs[NumIntRegs]; // PAL shadow registers + InternalProcReg ipr[NumInternalProcRegs]; // internal processor regs + int intrflag; // interrupt flag + bool pal_shadow; // using pal_shadow registers + inline int instAsid() { return MIPS34K::ITB_ASN_ASN(ipr[IPR_ITB_ASN]); } + inline int dataAsid() { return MIPS34K::DTB_ASN_ASN(ipr[IPR_DTB_ASN]); } +#endif // FULL_SYSTEM + + void serialize(std::ostream &os); + void unserialize(Checkpoint *cp, const std::string §ion); + + typedef int ContextParam; + typedef int ContextVal; + + void changeContext(ContextParam param, ContextVal val) + { + } + }; + + void copyRegs(ExecContext *src, ExecContext *dest); + + void copyMiscRegs(ExecContext *src, ExecContext *dest); + +#if FULL_SYSTEM + void copyIprs(ExecContext *src, ExecContext *dest); +#endif +} // namespace MipsISA + +#endif diff --git a/arch/mips/types.hh b/arch/mips/types.hh new file mode 100644 index 000000000..4d5fb3456 --- /dev/null +++ b/arch/mips/types.hh @@ -0,0 +1,92 @@ +/* + * Copyright (c) 2003-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. + */ + +#ifndef __ARCH_MIPS_TYPES_HH__ +#define __ARCH_MIPS_TYPES_HH__ + +#include "sim/host.hh" + +namespace MipsISA +{ + typedef uint32_t MachInst; + typedef uint64_t ExtMachInst; + typedef uint8_t RegIndex; + + typedef uint32_t IntReg; + + // floating point register file entry type + typedef double FloatReg; + typedef uint32_t FloatReg32; + typedef uint64_t FloatReg64; + typedef uint64_t FloatRegBits; + + // cop-0/cop-1 system control register + typedef uint64_t MiscReg; + typedef uint64_t InternalProcReg; + + typedef union { + IntReg intreg; + FloatReg fpreg; + MiscReg ctrlreg; + } AnyReg; + + //used in FP convert & round function + enum ConvertType{ + SINGLE_TO_DOUBLE, + SINGLE_TO_WORD, + SINGLE_TO_LONG, + + DOUBLE_TO_SINGLE, + DOUBLE_TO_WORD, + DOUBLE_TO_LONG, + + LONG_TO_SINGLE, + LONG_TO_DOUBLE, + LONG_TO_WORD, + LONG_TO_PS, + + WORD_TO_SINGLE, + WORD_TO_DOUBLE, + WORD_TO_LONG, + WORD_TO_PS, + + PL_TO_SINGLE, + PU_TO_SINGLE + }; + + //used in FP convert & round function + enum RoundMode{ + RND_ZERO, + RND_DOWN, + RND_UP, + RND_NEAREST + }; + +} // namespace MipsISA + +#endif diff --git a/arch/mips/utility.hh b/arch/mips/utility.hh new file mode 100644 index 000000000..b213a9f24 --- /dev/null +++ b/arch/mips/utility.hh @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2003-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. + */ + +#ifndef __ARCH_MIPS_UTILITY_HH__ +#define __ARCH_MIPS_UTILITY_HH__ + +#include "arch/mips/types.hh" +#include "arch/mips/constants.hh" +#include "base/misc.hh" +#include "sim/host.hh" + +namespace MipsISA { + +}; + +#endif diff --git a/arch/sparc/SConscript b/arch/sparc/SConscript index edff5821e..fd0df9349 100644 --- a/arch/sparc/SConscript +++ b/arch/sparc/SConscript @@ -57,8 +57,8 @@ full_system_sources = Split(''' # Syscall emulation (non-full-system) sources syscall_emulation_sources = Split(''' - common_syscall_emul.cc - linux_process.cc + linux/linux.cc + linux/process.cc process.cc ''') diff --git a/arch/sparc/faults.cc b/arch/sparc/faults.cc index b48fc600b..e83bba800 100644 --- a/arch/sparc/faults.cc +++ b/arch/sparc/faults.cc @@ -89,10 +89,10 @@ TrapType IllegalInstruction::_trapType = 0x010; FaultPriority IllegalInstruction::_priority = 7; FaultStat IllegalInstruction::_count; -FaultName PrivelegedOpcode::_name = "priv_opcode"; -TrapType PrivelegedOpcode::_trapType = 0x011; -FaultPriority PrivelegedOpcode::_priority = 6; -FaultStat PrivelegedOpcode::_count; +FaultName PrivilegedOpcode::_name = "priv_opcode"; +TrapType PrivilegedOpcode::_trapType = 0x011; +FaultPriority PrivilegedOpcode::_priority = 6; +FaultStat PrivilegedOpcode::_count; FaultName UnimplementedLDD::_name = "unimp_ldd"; TrapType UnimplementedLDD::_trapType = 0x012; @@ -159,10 +159,10 @@ TrapType STDFMemAddressNotAligned::_trapType = 0x036; FaultPriority STDFMemAddressNotAligned::_priority = 10; FaultStat STDFMemAddressNotAligned::_count; -FaultName PrivelegedAction::_name = "priv_action"; -TrapType PrivelegedAction::_trapType = 0x037; -FaultPriority PrivelegedAction::_priority = 11; -FaultStat PrivelegedAction::_count; +FaultName PrivilegedAction::_name = "priv_action"; +TrapType PrivilegedAction::_trapType = 0x037; +FaultPriority PrivilegedAction::_priority = 11; +FaultStat PrivilegedAction::_count; FaultName LDQFMemAddressNotAligned::_name = "unalign_ldqf"; TrapType LDQFMemAddressNotAligned::_trapType = 0x038; @@ -179,13 +179,13 @@ TrapType AsyncDataError::_trapType = 0x040; FaultPriority AsyncDataError::_priority = 2; FaultStat AsyncDataError::_count; -//The enumerated faults - FaultName CleanWindow::_name = "clean_win"; -TrapType CleanWindow::_baseTrapType = 0x024; +TrapType CleanWindow::_trapType = 0x024; FaultPriority CleanWindow::_priority = 10; FaultStat CleanWindow::_count; +//The enumerated faults + FaultName InterruptLevelN::_name = "interrupt_n"; TrapType InterruptLevelN::_baseTrapType = 0x041; FaultStat InterruptLevelN::_count; @@ -215,7 +215,10 @@ TrapType TrapInstruction::_baseTrapType = 0x100; FaultPriority TrapInstruction::_priority = 16; FaultStat TrapInstruction::_count; - +FaultName UnimpFault::_name = "Unimplemented Simulator feature"; +TrapType UnimpFault::_trapType = 0x000; +FaultPriority UnimpFault::_priority = 0; +FaultStat UnimpFault::_count; #if FULL_SYSTEM @@ -242,6 +245,12 @@ void SparcFault::invoke(ExecContext * xc) xc->regs.npc = xc->regs.pc + sizeof(MachInst);*/ } +void UnimpFault::invoke(ExecContext * xc) +{ + panic("Unimpfault: %s\n", panicStr.c_str()); +} + + #endif } // namespace SparcISA diff --git a/arch/sparc/faults.hh b/arch/sparc/faults.hh index 318b1ad5a..87de8daaa 100644 --- a/arch/sparc/faults.hh +++ b/arch/sparc/faults.hh @@ -216,7 +216,7 @@ class IllegalInstruction : public SparcFault FaultStat & countStat() {return _count;} }; -class PrivelegedOpcode : public SparcFault +class PrivilegedOpcode : public SparcFault { private: static FaultName _name; @@ -412,7 +412,7 @@ class STDFMemAddressNotAligned : public SparcFault FaultStat & countStat() {return _count;} }; -class PrivelegedAction : public SparcFault +class PrivilegedAction : public SparcFault { private: static FaultName _name; @@ -468,31 +468,30 @@ class AsyncDataError : public SparcFault FaultStat & countStat() {return _count;} }; -class EnumeratedFault : public SparcFault -{ - protected: - uint32_t _n; - virtual TrapType baseTrapType() = 0; - public: - EnumeratedFault(uint32_t n) : SparcFault() {_n = n;} - TrapType trapType() {return baseTrapType() + _n;} -}; - -class CleanWindow : public EnumeratedFault +class CleanWindow : public SparcFault { private: static FaultName _name; - static TrapType _baseTrapType; + static TrapType _trapType; static FaultPriority _priority; static FaultStat _count; - TrapType baseTrapType() {return _baseTrapType;} public: - CleanWindow(uint32_t n) : EnumeratedFault(n) {;} FaultName name() {return _name;} + TrapType trapType() {return _trapType;} FaultPriority priority() {return _priority;} FaultStat & countStat() {return _count;} }; +class EnumeratedFault : public SparcFault +{ + protected: + uint32_t _n; + virtual TrapType baseTrapType() = 0; + public: + EnumeratedFault(uint32_t n) : SparcFault() {_n = n;} + TrapType trapType() {return baseTrapType() + _n;} +}; + class InterruptLevelN : public EnumeratedFault { private: @@ -582,6 +581,29 @@ class TrapInstruction : public EnumeratedFault FaultStat & countStat() {return _count;} }; +class UnimpFault : public SparcFault +{ + private: + static FaultName _name; + static TrapType _trapType; + static FaultPriority _priority; + static FaultStat _count; + std::string panicStr; + public: + UnimpFault(std::string _str) + : panicStr(_str) + { } + + FaultName name() {return _name;} + TrapType trapType() {return _trapType;} + FaultPriority priority() {return _priority;} + FaultStat & countStat() {return _count;} +#if FULL_SYSTEM + void invoke(ExecContext * xc); +#endif +}; + + } // SparcISA namespace #endif // __FAULTS_HH__ diff --git a/arch/sparc/isa/base.isa b/arch/sparc/isa/base.isa index 992504369..cb370a3e7 100644 --- a/arch/sparc/isa/base.isa +++ b/arch/sparc/isa/base.isa @@ -5,15 +5,19 @@ output header {{ - struct condCodes + union CondCodes { - uint8_t c:1; - uint8_t v:1; - uint8_t z:1; - uint8_t n:1; - } + struct + { + uint8_t c:1; + uint8_t v:1; + uint8_t z:1; + uint8_t n:1; + }; + uint32_t bits; + }; - enum condTest + enum CondTest { Always=0x8, Never=0x0, @@ -31,7 +35,9 @@ output header {{ Negative=0x6, OverflowClear=0xF, OverflowSet=0x7 - } + }; + + extern char * CondTestAbbrev[]; /** * Base class for all SPARC static instructions. @@ -48,19 +54,100 @@ output header {{ std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const; + + void printReg(std::ostream &os, int reg) const; }; - bool passesCondition(condCodes codes, condTest condition); + bool passesCondition(uint32_t codes, uint32_t condition); + + inline int64_t sign_ext(uint64_t data, int origWidth) + { + int shiftAmount = 64 - origWidth; + return (((int64_t)data) << shiftAmount) >> shiftAmount; + } }}; output decoder {{ + char * CondTestAbbrev[] = + { + "nev", //Never + "e", //Equal + "le", //Less or Equal + "l", //Less + "leu", //Less or Equal Unsigned + "c", //Carry set + "n", //Negative + "o", //Overflow set + "a", //Always + "ne", //Not Equal + "g", //Greater + "ge", //Greater or Equal + "gu", //Greater Unsigned + "cc", //Carry clear + "p", //Positive + "oc" //Overflow Clear + }; +}}; + +def template ROrImmDecode {{ + { + return (I ? (SparcStaticInst *)(new %(class_name)sImm(machInst)) + : (SparcStaticInst *)(new %(class_name)s(machInst))); + } +}}; + +let {{ + def splitOutImm(code): + matcher = re.compile(r'Rs(?P<rNum>\d)_or_imm(?P<iNum>\d+)') + rOrImmMatch = matcher.search(code) + if (rOrImmMatch == None): + return (False, code, '', '', '') + rString = rOrImmMatch.group("rNum") + iString = rOrImmMatch.group("iNum") + orig_code = code + code = matcher.sub('Rs' + rOrImmMatch.group("rNum"), orig_code) + imm_code = matcher.sub('imm', orig_code) + return (True, code, imm_code, rString, iString) +}}; + +output decoder {{ + + inline void printMnemonic(std::ostream &os, const char * mnemonic) + { + ccprintf(os, "\t%s ", mnemonic); + } + + void + SparcStaticInst::printReg(std::ostream &os, int reg) const + { + const int MaxGlobal = 8; + const int MaxOutput = 16; + const int MaxLocal = 24; + const int MaxInput = 32; + if (reg == FramePointerReg) + ccprintf(os, "%%fp"); + else if (reg == StackPointerReg) + ccprintf(os, "%%sp"); + else if(reg < MaxGlobal) + ccprintf(os, "%%g%d", reg); + else if(reg < MaxOutput) + ccprintf(os, "%%o%d", reg - MaxGlobal); + else if(reg < MaxLocal) + ccprintf(os, "%%l%d", reg - MaxOutput); + else if(reg < MaxInput) + ccprintf(os, "%%i%d", reg - MaxLocal); + else { + ccprintf(os, "%%f%d", reg - FP_Base_DepTag); + } + } + std::string SparcStaticInst::generateDisassembly(Addr pc, const SymbolTable *symtab) const { std::stringstream ss; - ccprintf(ss, "%-10s ", mnemonic); + printMnemonic(ss, mnemonic); // just print the first two source regs... if there's // a third one, it's a read-modify-write dest (Rc), @@ -87,8 +174,10 @@ output decoder {{ return ss.str(); } - bool passesCondition(condCodes codes, condTest condition) + bool passesCondition(uint32_t codes, uint32_t condition) { + CondCodes condCodes; + condCodes.bits = codes; switch(condition) { case Always: @@ -96,34 +185,36 @@ output decoder {{ case Never: return false; case NotEqual: - return !codes.z; + return !condCodes.z; case Equal: - return codes.z; + return condCodes.z; case Greater: - return !(codes.z | (codes.n ^ codes.v)); + return !(condCodes.z | (condCodes.n ^ condCodes.v)); case LessOrEqual: - return codes.z | (codes.n ^ codes.v); + return condCodes.z | (condCodes.n ^ condCodes.v); case GreaterOrEqual: - return !(codes.n ^ codes.v); + return !(condCodes.n ^ condCodes.v); case Less: - return (codes.n ^ codes.v); + return (condCodes.n ^ condCodes.v); case GreaterUnsigned: - return !(codes.c | codes.z); + return !(condCodes.c | condCodes.z); case LessOrEqualUnsigned: - return (codes.c | codes.z); + return (condCodes.c | condCodes.z); case CarryClear: - return !codes.c; + return !condCodes.c; case CarrySet: - return codes.c; + return condCodes.c; case Positive: - return !codes.n; + return !condCodes.n; case Negative: - return codes.n; + return condCodes.n; case OverflowClear: - return !codes.v; + return !condCodes.v; case OverflowSet: - return codes.v; + return condCodes.v; } + panic("Tried testing condition nonexistant " + "condition code %d", condition); } }}; diff --git a/arch/sparc/isa/bitfields.isa b/arch/sparc/isa/bitfields.isa index b0ac57575..2e4478099 100644 --- a/arch/sparc/isa/bitfields.isa +++ b/arch/sparc/isa/bitfields.isa @@ -7,13 +7,11 @@ // simply defined alphabetically def bitfield A <29>; -def bitfield CC02 <20>; -def bitfield CC03 <25>; -def bitfield CC04 <11>; -def bitfield CC12 <21>; -def bitfield CC13 <26>; -def bitfield CC14 <12>; -def bitfield CC2 <18>; +def bitfield BPCC <21:20>; // for BPcc & FBPcc +def bitfield FCMPCC <26:56>; // for FCMP & FCMPEa +def bitfield FMOVCC <13:11>; // for FMOVcc +def bitfield CC <12:11>; // for MOVcc & Tcc +def bitfield MOVCC3 <18>; // also for MOVcc def bitfield CMASK <6:4>; def bitfield COND2 <28:25>; def bitfield COND4 <17:14>; @@ -46,5 +44,5 @@ def bitfield SHCNT64 <5:0>; def bitfield SIMM10 <9:0>; def bitfield SIMM11 <10:0>; def bitfield SIMM13 <12:0>; -def bitfield SW_TRAP <6:0>; +def bitfield SW_TRAP <7:0>; def bitfield X <12>; diff --git a/arch/sparc/isa/decoder.isa b/arch/sparc/isa/decoder.isa index eb458211b..b9e83afd6 100644 --- a/arch/sparc/isa/decoder.isa +++ b/arch/sparc/isa/decoder.isa @@ -3,660 +3,693 @@ // The actual decoder specification // -decode OP default Trap::unknown({{IllegalInstruction}}) { - - 0x0: decode OP2 { - 0x0: Trap::illtrap({{illegal_instruction}}); //ILLTRAP - 0x1: Branch::bpcc({{ - switch((CC12 << 1) | CC02) +decode OP default Unknown::unknown() +{ + 0x0: decode OP2 + { + //Throw an illegal instruction acception + 0x0: Trap::illtrap({{fault = new IllegalInstruction;}}); + 0x1: decode BPCC + { + format Branch19 + { + 0x0: bpcci({{ + if(passesCondition(CcrIcc, COND2)) + NNPC = xc->readPC() + disp; + else + handle_annul + }}); + 0x2: bpccx({{ + if(passesCondition(CcrXcc, COND2)) + NNPC = xc->readPC() + disp; + else + handle_annul + }}); + } + } + 0x2: Branch22::bicc({{ + if(passesCondition(CcrIcc, COND2)) + NNPC = xc->readPC() + disp; + else + handle_annul + }}); + 0x3: decode RCOND2 + { + format BranchSplit + { + 0x1: bpreq({{ + if(Rs1.sdw == 0) + NNPC = xc->readPC() + disp; + else + handle_annul + }}); + 0x2: bprle({{ + if(Rs1.sdw <= 0) + NNPC = xc->readPC() + disp; + else + handle_annul + }}); + 0x3: bprl({{ + if(Rs1.sdw < 0) + NNPC = xc->readPC() + disp; + else + handle_annul + }}); + 0x5: bprne({{ + if(Rs1.sdw != 0) + NNPC = xc->readPC() + disp; + else + handle_annul + }}); + 0x6: bprg({{ + if(Rs1.sdw > 0) + NNPC = xc->readPC() + disp; + else + handle_annul + }}); + 0x7: bprge({{ + if(Rs1.sdw >= 0) + NNPC = xc->readPC() + disp; + else + handle_annul + }}); + } + } + //SETHI (or NOP if rd == 0 and imm == 0) + 0x4: SetHi::sethi({{Rd = imm;}}); + 0x5: Trap::fbpfcc({{fault = new FpDisabled;}}); + 0x6: Trap::fbfcc({{fault = new FpDisabled;}}); + } + 0x1: Branch30::call({{ + R15 = xc->readPC(); + NNPC = R15 + disp; + }}); + 0x2: decode OP3 { + format IntOp { + 0x00: add({{Rd = Rs1.sdw + Rs2_or_imm13;}}); + 0x01: and({{Rd = Rs1.udw & Rs2_or_imm13;}}); + 0x02: or({{Rd = Rs1.udw | Rs2_or_imm13;}}); + 0x03: xor({{Rd = Rs1.udw ^ Rs2_or_imm13;}}); + 0x04: sub({{Rd = Rs1.sdw - Rs2_or_imm13;}}); + 0x05: andn({{Rd = Rs1.udw & ~Rs2_or_imm13;}}); + 0x06: orn({{Rd = Rs1.udw | ~Rs2_or_imm13;}}); + 0x07: xnor({{Rd = ~(Rs1.udw ^ Rs2_or_imm13);}}); + 0x08: addc({{Rd = Rs1.sdw + Rs2_or_imm13 + CcrIccC;}}); + 0x09: mulx({{Rd = Rs1 * Rs2_or_imm13;}}); + 0x0A: umul({{ + Rd = Rs1.udw<31:0> * Rs2_or_imm13<31:0>; + YValue = Rd<63:32>; + }}); + 0x0B: smul({{ + Rd.sdw = Rs1.sdw<31:0> * Rs2_or_imm13<31:0>; + YValue = Rd.sdw; + }}); + 0x0C: subc({{Rd.sdw = Rs1.sdw + (~Rs2_or_imm13) + 1 + CcrIccC;}}); + 0x0D: udivx({{ + if(Rs2_or_imm13 == 0) fault = new DivisionByZero; + else Rd.udw = Rs1.udw / Rs2_or_imm13; + }}); + 0x0E: udiv({{ + if(Rs2_or_imm13 == 0) fault = new DivisionByZero; + else { - case 1: - case 3: - fault = new IllegalInstruction; - case 0: - if(passesCondition(xc->regs.MiscRegs.ccrFields.icc, COND2)) - ;//branchHere - break; - case 2: - if(passesCondition(xc->regs.MiscRegs.ccrFields.xcc, COND2)) - ;//branchHere - break; + Rd.udw = ((YValue << 32) | Rs1.udw<31:0>) / Rs2_or_imm13; + if(Rd.udw >> 32 != 0) + Rd.udw = 0xFFFFFFFF; } - }});//BPcc - 0x2: Branch::bicc({{ - if(passesCondition(xc->regs.MiscRegs.ccrFields.icc, COND2)) - ;//branchHere - }});//Bicc - 0x3: Branch::bpr({{ - switch(RCOND) + }}); + 0x0F: sdiv({{ + if(Rs2_or_imm13 == 0) + fault = new DivisionByZero; + else { - case 0: - case 4: - fault = new IllegalInstruction; - case 1: - if(Rs1 == 0) - ;//branchHere - break; - case 2: - if(Rs1 <= 0) - ;//branchHere - break; - case 3: - if(Rs1 < 0) - ;//branchHere - break; - case 5: - if(Rs1 != 0) - ;//branchHere - break; - case 6: - if(Rs1 > 0) - ;//branchHere - break; - case 7: - if(Rs1 >= 0) - ;//branchHere - break; + Rd.udw = ((YValue << 32) | Rs1.sdw<31:0>) / Rs2_or_imm13; + if(Rd.udw<63:31> != 0) + Rd.udw = 0x7FFFFFFF; + else if(Rd.udw<63:> && Rd.udw<62:31> != 0xFFFFFFFF) + Rd.udw = 0xFFFFFFFF80000000ULL; } - }}); //BPr - //SETHI (or NOP if rd == 0 and imm == 0) - 0x4: IntegerOp::sethi({{Rd = (IMM22 << 10) & 0xFFFFFC00;}}); - 0x5: Trap::fbpfcc({{throw fp_disabled;}}); //FBPfcc - 0x6: Trap::fbfcc({{throw fp_disabled;}}); //FBfcc + }}); } - 0x1: Branch::call({{ - //branch here - Rd = xc->pc; - }}); - 0x2: decode OP3 { - format IntegerOp { - 0x00: add({{ - int64_t val2 = (I ? SIMM13.sdw : Rs2.sdw); - Rd = Rs1.sdw + val2; - }});//ADD - 0x01: and({{ - uint64_t val2 = (I ? SIMM13.sdw : Rs2.udw); - Rd = Rs1.udw & val2; - }});//AND - 0x02: or({{ - uint64_t val2 = (I ? SIMM13.sdw : Rs2.udw); - Rd = Rs1.udw | val2; - }});//OR - 0x03: xor({{ - uint64_t val2 = (I ? SIMM13.sdw : Rs2.udw); - Rd = Rs1.udw ^ val2; - }});//XOR - 0x04: sub({{ - int64_t val2 = ~((uint64_t)(I ? SIMM13.sdw : Rs2.udw))+1; - Rd = Rs1.sdw + val2; - }});//SUB - 0x05: andn({{ - uint64_t val2 = (I ? SIMM13.sdw : Rs2.udw); - Rd = Rs1.udw & ~val2; - }});//ANDN - 0x06: orn({{ - uint64_t val2 = (I ? SIMM13.sdw : Rs2.udw); - Rd = Rs1.udw | ~val2; - }});//ORN - 0x07: xnor({{ - uint64_t val2 = (I ? SIMM13.sdw : Rs2.udw); - Rd = ~(Rs1.udw ^ val2); - }});//XNOR - 0x08: addc({{ - int64_t val2 = (I ? SIMM13.sdw : Rs2.sdw); - int64_t carryin = xc->regs.MiscRegs.ccrfields.iccfields.c; - Rd = Rs1.sdw + val2 + carryin; - }});//ADDC - 0x09: mulx({{ - int64_t val2 = (I ? SIMM13.sdw : Rs2); - Rd = Rs1 * val2; - }});//MULX - 0x0A: umul({{ - uint64_t resTemp, val2 = (I ? SIMM13.sdw : Rs2.udw); - Rd = resTemp = Rs1.udw<31:0> * val2<31:0>; - xc->regs.MiscRegs.yFields.value = resTemp<63:32>; - }});//UMUL - 0x0B: smul({{ - int64_t resTemp, val2 = (I ? SIMM13.sdw : Rs2.sdw); - rd.sdw = resTemp = Rs1.sdw<31:0> * val2<31:0>; - xc->regs.MiscRegs.yFields.value = resTemp<63:32>; - }});//SMUL - 0x0C: subc({{ - int64_t val2 = ~((int64_t)(I ? SIMM13.sdw : Rs2.sdw))+1; - int64_t carryin = xc->regs.MiscRegs.ccrfields.iccfields.c; - Rd.sdw = Rs1.sdw + val2 + carryin; - }});//SUBC - 0x0D: udivx({{ - uint64_t val2 = (I ? SIMM13.sdw : Rs2.udw); - if(val2 == 0) throw division_by_zero; - Rd.udw = Rs1.udw / val2; - }});//UDIVX - 0x0E: udiv({{ - uint32_t resTemp, val2 = (I ? SIMM13.sw : Rs2.udw<31:0>); - if(val2 == 0) - fault = new DivisionByZero; - resTemp = (uint64_t)((xc->regs.MiscRegs.yFields.value << 32) - | Rs1.udw<31:0>) / val2; - int32_t overflow = (resTemp<63:32> != 0); - if(overflow) - rd.udw = resTemp = 0xFFFFFFFF; + format IntOpCc { + 0x10: addcc({{ + int64_t resTemp, val2 = Rs2_or_imm13; + Rd = resTemp = Rs1 + val2;}}, + {{(Rs1<31:0> + val2<31:0>)<32:>}}, + {{Rs1<31:> == val2<31:> && val2<31:> != resTemp<31:>}}, + {{(Rs1<63:1> + val2<63:1> + (Rs1 & val2)<0:>)<63:>}}, + {{Rs1<63:> == val2<63:> && val2<63:> != resTemp<63:>}} + ); + 0x11: IntOpCcRes::andcc({{Rd = Rs1 & Rs2_or_imm13;}}); + 0x12: IntOpCcRes::orcc({{Rd = Rs1 | Rs2_or_imm13;}}); + 0x13: IntOpCcRes::xorcc({{Rd = Rs1 ^ Rs2_or_imm13;}}); + 0x14: subcc({{ + int64_t val2 = Rs2_or_imm13; + Rd = Rs1 - val2;}}, + {{(~(Rs1<31:0> + (~val2)<31:0> + 1))<32:>}}, + {{(Rs1<31:> != val2<31:>) && (Rs1<31:> != Rd<31:>)}}, + {{(~(Rs1<63:1> + (~val2)<63:1> + + (Rs1 | ~val2)<0:>))<63:>}}, + {{Rs1<63:> != val2<63:> && Rs1<63:> != Rd<63:>}} + ); + 0x15: IntOpCcRes::andncc({{Rd = Rs1 & ~Rs2_or_imm13;}}); + 0x16: IntOpCcRes::orncc({{Rd = Rs1 | ~Rs2_or_imm13;}}); + 0x17: IntOpCcRes::xnorcc({{Rd = ~(Rs1 ^ Rs2_or_imm13);}}); + 0x18: addccc({{ + int64_t resTemp, val2 = Rs2_or_imm13; + int64_t carryin = CcrIccC; + Rd = resTemp = Rs1 + val2 + carryin;}}, + {{(Rs1<31:0> + val2<31:0> + carryin)<32:>}}, + {{Rs1<31:> == val2<31:> && val2<31:> != resTemp<31:>}}, + {{(Rs1<63:1> + val2<63:1> + + ((Rs1 & val2) | (carryin & (Rs1 | val2)))<0:>)<63:>}}, + {{Rs1<63:> == val2<63:> && val2<63:> != resTemp<63:>}} + ); + 0x1A: umulcc({{ + uint64_t resTemp, val2 = Rs2_or_imm13; + Rd = resTemp = Rs1.udw<31:0> * val2<31:0>; + YValue = resTemp<63:32>;}}, + {{0}},{{0}},{{0}},{{0}}); + 0x1B: smulcc({{ + int64_t resTemp, val2 = Rs2_or_imm13; + Rd = resTemp = Rs1.sdw<31:0> * val2<31:0>; + YValue = resTemp<63:32>;}}, + {{0}},{{0}},{{0}},{{0}}); + 0x1C: subccc({{ + int64_t resTemp, val2 = Rs2_or_imm13; + int64_t carryin = CcrIccC; + Rd = resTemp = Rs1 + ~(val2 + carryin) + 1;}}, + {{(~((Rs1<31:0> + (~(val2 + carryin))<31:0> + 1))<32:>)}}, + {{Rs1<31:> != val2<31:> && Rs1<31:> != resTemp<31:>}}, + {{(~((Rs1<63:1> + (~(val2 + carryin))<63:1>) + (Rs1<0:> + (~(val2+carryin))<0:> + 1)<63:1>))<63:>}}, + {{Rs1<63:> != val2<63:> && Rs1<63:> != resTemp<63:>}} + ); + 0x1D: udivxcc({{ + if(Rs2_or_imm13 == 0) fault = new DivisionByZero; + else Rd = Rs1.udw / Rs2_or_imm13;}} + ,{{0}},{{0}},{{0}},{{0}}); + 0x1E: udivcc({{ + uint32_t resTemp, val2 = Rs2_or_imm13; + int32_t overflow; + if(val2 == 0) fault = new DivisionByZero; + else + { + resTemp = (uint64_t)((YValue << 32) | Rs1.udw<31:0>) / val2; + overflow = (resTemp<63:32> != 0); + if(overflow) Rd = resTemp = 0xFFFFFFFF; + else Rd = resTemp; + } }}, + {{0}}, + {{overflow}}, + {{0}}, + {{0}} + ); + 0x1F: sdivcc({{ + int32_t resTemp, val2 = Rs2_or_imm13; + int32_t overflow, underflow; + if(val2 == 0) fault = new DivisionByZero; + else + { + Rd = resTemp = (int64_t)((YValue << 32) | Rs1.sdw<31:0>) / val2; + overflow = (resTemp<63:31> != 0); + underflow = (resTemp<63:> && resTemp<62:31> != 0xFFFFFFFF); + if(overflow) Rd = resTemp = 0x7FFFFFFF; + else if(underflow) Rd = resTemp = 0xFFFFFFFF80000000ULL; + else Rd = resTemp; + } }}, + {{0}}, + {{overflow || underflow}}, + {{0}}, + {{0}} + ); + 0x20: taddcc({{ + int64_t resTemp, val2 = Rs2_or_imm13; + Rd = resTemp = Rs1 + val2; + int32_t overflow = Rs1<1:0> || val2<1:0> || (Rs1<31:> == val2<31:> && val2<31:> != resTemp<31:>);}}, + {{((Rs1 & 0xFFFFFFFF + val2 & 0xFFFFFFFF) >> 31)}}, + {{overflow}}, + {{((Rs1 >> 1) + (val2 >> 1) + (Rs1 & val2 & 0x1))<63:>}}, + {{Rs1<63:> == val2<63:> && val2<63:> != resTemp<63:>}} + ); + 0x21: tsubcc({{ + int64_t resTemp, val2 = Rs2_or_imm13; + Rd = resTemp = Rs1 + val2; + int32_t overflow = Rs1<1:0> || val2<1:0> || (Rs1<31:> == val2<31:> && val2<31:> != resTemp<31:>);}}, + {{(Rs1 & 0xFFFFFFFF + val2 & 0xFFFFFFFF) >> 31}}, + {{overflow}}, + {{((Rs1 >> 1) + (val2 >> 1) + (Rs1 & val2 & 0x1))<63:>}}, + {{Rs1<63:> == val2<63:> && val2<63:> != resTemp<63:>}} + ); + 0x22: taddcctv({{ + int64_t resTemp, val2 = Rs2_or_imm13; + Rd = resTemp = Rs1 + val2; + int32_t overflow = Rs1<1:0> || val2<1:0> || (Rs1<31:> == val2<31:> && val2<31:> != resTemp<31:>); + if(overflow) fault = new TagOverflow;}}, + {{((Rs1 & 0xFFFFFFFF + val2 & 0xFFFFFFFF) >> 31)}}, + {{overflow}}, + {{((Rs1 >> 1) + (val2 >> 1) + (Rs1 & val2 & 0x1))<63:>}}, + {{Rs1<63:> == val2<63:> && val2<63:> != resTemp<63:>}} + ); + 0x23: tsubcctv({{ + int64_t resTemp, val2 = Rs2_or_imm13; + Rd = resTemp = Rs1 + val2; + int32_t overflow = Rs1<1:0> || val2<1:0> || (Rs1<31:> == val2<31:> && val2<31:> != resTemp<31:>); + if(overflow) fault = new TagOverflow;}}, + {{((Rs1 & 0xFFFFFFFF + val2 & 0xFFFFFFFF) >> 31)}}, + {{overflow}}, + {{((Rs1 >> 1) + (val2 >> 1) + (Rs1 & val2 & 0x1))<63:>}}, + {{Rs1<63:> == val2<63:> && val2<63:> != resTemp<63:>}} + ); + 0x24: mulscc({{ + int64_t resTemp, multiplicand = Rs2_or_imm13; + int32_t multiplier = Rs1<31:0>; + int32_t savedLSB = Rs1<0:>; + multiplier = multiplier<31:1> | + ((CcrIccN + ^ CcrIccV) << 32); + if(!YValue<0:>) + multiplicand = 0; + Rd = resTemp = multiplicand + multiplier; + YValue = YValue<31:1> | (savedLSB << 31);}}, + {{((multiplicand & 0xFFFFFFFF + multiplier & 0xFFFFFFFF) >> 31)}}, + {{multiplicand<31:> == multiplier<31:> && multiplier<31:> != resTemp<31:>}}, + {{((multiplicand >> 1) + (multiplier >> 1) + (multiplicand & multiplier & 0x1))<63:>}}, + {{multiplicand<63:> == multiplier<63:> && multiplier<63:> != resTemp<63:>}} + ); + } + format IntOp + { + 0x25: decode X { + 0x0: sll({{Rd = Rs1 << (I ? SHCNT32 : Rs2<4:0>);}}); + 0x1: sllx({{Rd = Rs1 << (I ? SHCNT64 : Rs2<5:0>);}}); + } + 0x26: decode X { + 0x0: srl({{Rd = Rs1.uw >> (I ? SHCNT32 : Rs2<4:0>);}}); + 0x1: srlx({{Rd = Rs1.udw >> (I ? SHCNT64 : Rs2<5:0>);}}); + } + 0x27: decode X { + 0x0: sra({{Rd = Rs1.sw >> (I ? SHCNT32 : Rs2<4:0>);}}); + 0x1: srax({{Rd = Rs1.sdw >> (I ? SHCNT64 : Rs2<5:0>);}}); + } + 0x28: decode RS1 { + 0x0: rdy({{Rd = YValue;}}); + 0x2: rdccr({{Rd = Ccr;}}); + 0x3: rdasi({{Rd = Asi;}}); + 0x4: PrivTick::rdtick({{Rd = Tick;}}); + 0x5: rdpc({{Rd = xc->readPC();}}); + 0x6: rdfprs({{Rd = Fprs;}}); + 0xF: decode I { + 0x0: Nop::membar({{/*Membar isn't needed yet*/}}); + 0x1: Nop::stbar({{/*Stbar isn't needed yet*/}}); + } + } + 0x2A: decode RS1 { + format Priv + { + 0x0: rdprtpc({{ + Rd = xc->readMiscReg(MISCREG_TPC_BASE + Tl); + }}); + 0x1: rdprtnpc({{ + Rd = xc->readMiscReg(MISCREG_TNPC_BASE + Tl); + }}); + 0x2: rdprtstate({{ + Rd = xc->readMiscReg(MISCREG_TSTATE_BASE + Tl); + }}); + 0x3: rdprtt({{ + Rd = xc->readMiscReg(MISCREG_TT_BASE + Tl); + }}); + 0x4: rdprtick({{Rd = Tick;}}); + 0x5: rdprtba({{Rd = Tba;}}); + 0x6: rdprpstate({{Rd = Pstate;}}); + 0x7: rdprtl({{Rd = Tl;}}); + 0x8: rdprpil({{Rd = Pil;}}); + 0x9: rdprcwp({{Rd = Cwp;}}); + 0xA: rdprcansave({{Rd = Cansave;}}); + 0xB: rdprcanrestore({{Rd = Canrestore;}}); + 0xC: rdprcleanwin({{Rd = Cleanwin;}}); + 0xD: rdprotherwin({{Rd = Otherwin;}}); + 0xE: rdprwstate({{Rd = Wstate;}}); + } + //The floating point queue isn't implemented right now. + 0xF: Trap::rdprfq({{fault = new IllegalInstruction;}}); + 0x1F: Priv::rdprver({{Rd = Ver;}}); + } + 0x2B: BasicOperate::flushw({{ + if(NWindows - 2 - Cansave == 0) + { + if(Otherwin) + fault = new SpillNOther(WstateOther); else - rd.udw = resTemp; - }}); //UDIV - 0x0F: sdiv({{ - int32_t resTemp, val2 = (I ? SIMM13.sw : Rs2.sdw<31:0>); - if(val2 == 0) - fault = new DivisionByZero; - - Rd.sdw = (int64_t)((xc->regs.MiscRegs.yFields.value << 32) | - Rs1.sdw<31:0>) / val2; - resTemp = Rd.sdw; - int32_t overflow = (resTemp<63:31> != 0); - int32_t underflow = - (resTemp<63:> && resTemp<62:31> != 0xFFFFFFFF); - if(overflow) - rd.udw = resTemp = 0x7FFFFFFF; - else if(underflow) - rd.udw = resTemp = 0xFFFFFFFF80000000; + fault = new SpillNNormal(WstateNormal); + } + }}); + 0x2C: decode MOVCC3 + { + 0x0: Trap::movccfcc({{fault = new FpDisabled;}}); + 0x1: decode CC + { + 0x0: movcci({{ + if(passesCondition(CcrIcc, COND4)) + Rd = Rs2_or_imm11; + else + Rd = Rd; + }}); + 0x2: movccx({{ + if(passesCondition(CcrXcc, COND4)) + Rd = Rs2_or_imm11; + else + Rd = Rd; + }}); + } + } + 0x2D: sdivx({{ + if(Rs2_or_imm13 == 0) fault = new DivisionByZero; + else Rd.sdw = Rs1.sdw / Rs2_or_imm13; + }}); + 0x2E: decode RS1 { + 0x0: IntOp::popc({{ + int64_t count = 0; + uint64_t temp = Rs2_or_imm13; + //Count the 1s in the front 4bits until none are left + uint8_t oneBits[] = {0,1,1,2,1,2,2,3,1,2,2,3,2,3,3,4}; + while(temp) + { + count += oneBits[temp & 0xF]; + temp = temp >> 4; + } + Rd = count; + }}); + } + 0x2F: decode RCOND3 + { + 0x1: movreq({{Rd = (Rs1 == 0) ? Rs2_or_imm10 : Rd;}}); + 0x2: movrle({{Rd = (Rs1 <= 0) ? Rs2_or_imm10 : Rd;}}); + 0x3: movrl({{Rd = (Rs1 < 0) ? Rs2_or_imm10 : Rd;}}); + 0x5: movrne({{Rd = (Rs1 != 0) ? Rs2_or_imm10 : Rd;}}); + 0x6: movrg({{Rd = (Rs1 > 0) ? Rs2_or_imm10 : Rd;}}); + 0x7: movrge({{Rd = (Rs1 >= 0) ? Rs2_or_imm10 : Rd;}}); + } + 0x30: decode RD { + 0x0: wry({{Y = Rs1 ^ Rs2_or_imm13;}}); + 0x2: wrccr({{Ccr = Rs1 ^ Rs2_or_imm13;}}); + 0x3: wrasi({{Asi = Rs1 ^ Rs2_or_imm13;}}); + 0x6: wrfprs({{Asi = Rs1 ^ Rs2_or_imm13;}}); + 0xF: Trap::sir({{fault = new SoftwareInitiatedReset;}}); + } + 0x31: decode FCN { + 0x0: BasicOperate::saved({{/*Boogy Boogy*/}}); + 0x1: BasicOperate::restored({{/*Boogy Boogy*/}}); + } + 0x32: decode RD { + format Priv + { + 0x0: wrprtpc({{ + xc->setMiscReg(MISCREG_TPC_BASE + Tl, + Rs1 ^ Rs2_or_imm13); + }}); + 0x1: wrprtnpc({{ + xc->setMiscReg(MISCREG_TNPC_BASE + Tl, + Rs1 ^ Rs2_or_imm13); + }}); + 0x2: wrprtstate({{ + xc->setMiscReg(MISCREG_TSTATE_BASE + Tl, + Rs1 ^ Rs2_or_imm13); + }}); + 0x3: wrprtt({{ + xc->setMiscReg(MISCREG_TT_BASE + Tl, + Rs1 ^ Rs2_or_imm13); + }}); + 0x4: wrprtick({{Tick = Rs1 ^ Rs2_or_imm13;}}); + 0x5: wrprtba({{Tba = Rs1 ^ Rs2_or_imm13;}}); + 0x6: wrprpstate({{Pstate = Rs1 ^ Rs2_or_imm13;}}); + 0x7: wrprtl({{Tl = Rs1 ^ Rs2_or_imm13;}}); + 0x8: wrprpil({{Pil = Rs1 ^ Rs2_or_imm13;}}); + 0x9: wrprcwp({{Cwp = Rs1 ^ Rs2_or_imm13;}}); + 0xA: wrprcansave({{Cansave = Rs1 ^ Rs2_or_imm13;}}); + 0xB: wrprcanrestore({{Canrestore = Rs1 ^ Rs2_or_imm13;}}); + 0xC: wrprcleanwin({{Cleanwin = Rs1 ^ Rs2_or_imm13;}}); + 0xD: wrprotherwin({{Otherwin = Rs1 ^ Rs2_or_imm13;}}); + 0xE: wrprwstate({{Wstate = Rs1 ^ Rs2_or_imm13;}}); + } + } + 0x34: Trap::fpop1({{fault = new FpDisabled;}}); + 0x35: Trap::fpop2({{fault = new FpDisabled;}}); + 0x38: Branch::jmpl({{ + Addr target = Rs1 + Rs2_or_imm13; + if(target & 0x3) + fault = new MemAddressNotAligned; + else + { + Rd = xc->readPC(); + NNPC = target; + } + }}); + 0x39: Branch::return({{ + //If both MemAddressNotAligned and + //a fill trap happen, it's not clear + //which one should be returned. + Addr target = Rs1 + Rs2_or_imm13; + if(target & 0x3) + fault = new MemAddressNotAligned; + else + NNPC = target; + if(fault == NoFault) + { + //CWP should be set directly so that it always happens + //Also, this will allow writing to the new window and + //reading from the old one + Cwp = (Cwp - 1 + NWindows) % NWindows; + if(Canrestore == 0) + { + if(Otherwin) + fault = new FillNOther(WstateOther); + else + fault = new FillNNormal(WstateNormal); + } + else + { + Rd = Rs1 + Rs2_or_imm13; + Cansave = Cansave + 1; + Canrestore = Canrestore - 1; + } + //This is here to make sure the CWP is written + //no matter what. This ensures that the results + //are written in the new window as well. + xc->setMiscRegWithEffect(MISCREG_CWP, Cwp); + } + }}); + 0x3A: decode CC + { + 0x0: Trap::tcci({{ + if(passesCondition(CcrIcc, COND2)) + { + int lTrapNum = I ? (Rs1 + SW_TRAP) : (Rs1 + Rs2); + DPRINTF(Sparc, "The trap number is %d\n", lTrapNum); +#if FULL_SYSTEM + fault = new TrapInstruction(lTrapNum); +#else + DPRINTF(Sparc, "The syscall number is %d\n", R1); + xc->syscall(R1); +#endif + } else - rd.udw = resTemp; - }});//SDIV + { + DPRINTF(Sparc, "Didn't fire on %s\n", CondTestAbbrev[machInst<25:28>]); + } + }}); + 0x2: Trap::tccx({{ + if(passesCondition(CcrXcc, COND2)) + { + int lTrapNum = I ? (Rs1 + SW_TRAP) : (Rs1 + Rs2); + DPRINTF(Sparc, "The trap number is %d\n", lTrapNum); +#if FULL_SYSTEM + fault = new TrapInstruction(lTrapNum); +#else + DPRINTF(Sparc, "The syscall number is %d\n", R1); + xc->syscall(R1); +#endif + } + }}); } - format IntegerOpCc { - 0x10: addcc({{ - int64_t resTemp, val2 = (I ? SIMM13.sdw : Rs2); - Rd = resTemp = Rs1 + val2;}}, - {{((Rs1 & 0xFFFFFFFF + val2 & 0xFFFFFFFF) >> 31)}}, - {{Rs1<31:> == val2<31:> && val2<31:> != resTemp<31:>}}, - {{((Rs1 >> 1) + (val2 >> 1) + (Rs1 & val2 & 0x1))<63:>}}, - {{Rs1<63:> == val2<63:> && val2<63:> != resTemp<63:>}} - );//ADDcc - 0x11: andcc({{ - int64_t val2 = (I ? SIMM13.sdw : Rs2); - Rd = Rs1 & val2;}}, - {{0}},{{0}},{{0}},{{0}});//ANDcc - 0x12: orcc({{ - int64_t val2 = (I ? SIMM13.sdw : Rs2); - Rd = Rs1 | val2;}}, - {{0}},{{0}},{{0}},{{0}});//ORcc - 0x13: xorcc({{ - int64_t val2 = (I ? SIMM13.sdw : Rs2); - Rd = Rs1 ^ val2;}}, - {{0}},{{0}},{{0}},{{0}});//XORcc - 0x14: subcc({{ - int64_t resTemp, val2 = (int64_t)(I ? SIMM13.sdw : Rs2); - Rd = resTemp = Rs1 - val2;}}, - {{((Rs1 & 0xFFFFFFFF + (~val2) & 0xFFFFFFFF + 1) >> 31)}}, - {{Rs1<31:> != val2<31:> && Rs1<31:> != resTemp<31:>}}, - {{((Rs1 >> 1) + (~val2) >> 1) + - ((Rs1 | ~val2) & 0x1))<63:>}}, - {{Rs1<63:> != val2<63:> && Rs1<63:> != resTemp<63:>}} - );//SUBcc - 0x15: andncc({{ - int64_t val2 = (I ? SIMM13.sdw : Rs2); - Rd = Rs1 & ~val2;}}, - {{0}},{{0}},{{0}},{{0}});//ANDNcc - 0x16: orncc({{ - int64_t val2 = (I ? SIMM13.sdw : Rs2); - Rd = Rs1 | ~val2;}}, - {{0}},{{0}},{{0}},{{0}});//ORNcc - 0x17: xnorcc({{ - int64_t val2 = (I ? SIMM13.sdw : Rs2); - Rd = ~(Rs1 ^ val2);}}, - {{0}},{{0}},{{0}},{{0}});//XNORcc - 0x18: addccc({{ - int64_t resTemp, val2 = (I ? SIMM13.sdw : Rs2); - int64_t carryin = xc->regs.MiscRegs.ccrfields.iccfields.c; - Rd = resTemp = Rs1 + val2 + carryin;}}, - {{((Rs1 & 0xFFFFFFFF + val2 & 0xFFFFFFFF) >> 31 - + carryin)}}, - {{Rs1<31:> == val2<31:> && val2<31:> != resTemp<31:>}}, - {{((Rs1 >> 1) + (val2 >> 1) + - ((Rs1 & val2) | (carryin & (Rs1 | val2)) & 0x1))<63:>}}, - {{Rs1<63:> == val2<63:> && val2<63:> != resTemp<63:>}} - );//ADDCcc - 0x1A: umulcc({{ - uint64_t resTemp, val2 = (I ? SIMM13.sdw : Rs2); - Rd = resTemp = Rs1.udw<31:0> * val2<31:0>; - xc->regs.MiscRegs.yFields.value = resTemp<63:32>;}}, - {{0}},{{0}},{{0}},{{0}});//UMULcc - 0x1B: smulcc({{ - int64_t resTemp, val2 = (I ? SIMM13.sdw : Rs2); - Rd = resTemp = Rs1.sdw<31:0> * val2<31:0>; - xc->regs.MiscRegs.yFields.value = resTemp<63:32>;}} - ,{{0}},{{0}},{{0}},{{0}});//SMULcc - 0x1C: subccc({{ - int64_t resTemp, val2 = (int64_t)(I ? SIMM13.sdw : Rs2); - int64_t carryin = xc->regs.MiscRegs.ccrfields.iccfields.c; - Rd = resTemp = Rs1 + ~(val2 + carryin) + 1;}}, - {{((Rs1 & 0xFFFFFFFF + (~(val2 + carryin)) & 0xFFFFFFFF + 1) >> 31)}}, - {{Rs1<31:> != val2<31:> && Rs1<31:> != resTemp<31:>}}, - {{((Rs1 >> 1) + (~(val2 + carryin)) >> 1) + ((Rs1 | ~(val2+carryin)) & 0x1))<63:>}}, - {{Rs1<63:> != val2<63:> && Rs1<63:> != resTemp<63:>}} - );//SUBCcc - 0x1D: udivxcc({{ - uint64_t val2 = (I ? SIMM13.sdw : Rs2.udw); - if(val2 == 0) throw division_by_zero; - Rd.udw = Rs1.udw / val2;}} - ,{{0}},{{0}},{{0}},{{0}});//UDIVXcc - 0x1E: udivcc({{ - uint32_t resTemp, val2 = (I ? SIMM13.sw : Rs2.udw<31:0>); - if(val2 == 0) throw division_by_zero; - resTemp = (uint64_t)((xc->regs.MiscRegs.yFields.value << 32) | Rs1.udw<31:0>) / val2; - int32_t overflow = (resTemp<63:32> != 0); - if(overflow) rd.udw = resTemp = 0xFFFFFFFF; - else rd.udw = resTemp;}}, - {{0}}, - {{overflow}}, - {{0}}, - {{0}} - );//UDIVcc - 0x1F: sdivcc({{ - int32_t resTemp, val2 = (I ? SIMM13.sw : Rs2.sdw<31:0>); - if(val2 == 0) throw division_by_zero; - Rd.sdw = resTemp = (int64_t)((xc->regs.MiscRegs.yFields.value << 32) | Rs1.sdw<31:0>) / val2; - int32_t overflow = (resTemp<63:31> != 0); - int32_t underflow = (resTemp<63:> && resTemp<62:31> != 0xFFFFFFFF); - if(overflow) rd.udw = resTemp = 0x7FFFFFFF; - else if(underflow) rd.udw = resTemp = 0xFFFFFFFF80000000; - else rd.udw = resTemp;}}, - {{0}}, - {{overflow || underflow}}, - {{0}}, - {{0}} - );//SDIVcc - 0x20: taddcc({{ - int64_t resTemp, val2 = (I ? SIMM13.sdw : Rs2); - Rd = resTemp = Rs1 + val2; - int32_t overflow = Rs1<1:0> || val2<1:0> || (Rs1<31:> == val2<31:> && val2<31:> != resTemp<31:>);}}, - {{((Rs1 & 0xFFFFFFFF + val2 & 0xFFFFFFFF) >> 31)}}, - {{overflow}}, - {{((Rs1 >> 1) + (val2 >> 1) + (Rs1 & val2 & 0x1))<63:>}}, - {{Rs1<63:> == val2<63:> && val2<63:> != resTemp<63:>}} - );//TADDcc - 0x21: tsubcc({{ - int64_t resTemp, val2 = (I ? SIMM13.sdw : Rs2); - Rd = resTemp = Rs1 + val2; - int32_t overflow = Rs1<1:0> || val2<1:0> || (Rs1<31:> == val2<31:> && val2<31:> != resTemp<31:>);}}, - {{(Rs1 & 0xFFFFFFFF + val2 & 0xFFFFFFFF) >> 31)}}, - {{overflow}}, - {{((Rs1 >> 1) + (val2 >> 1) + (Rs1 & val2 & 0x1))<63:>}}, - {{Rs1<63:> == val2<63:> && val2<63:> != resTemp<63:>}} - );//TSUBcc - 0x22: taddcctv({{ - int64_t resTemp, val2 = (I ? SIMM13.sdw : Rs2); - Rd = resTemp = Rs1 + val2; - int32_t overflow = Rs1<1:0> || val2<1:0> || (Rs1<31:> == val2<31:> && val2<31:> != resTemp<31:>); - if(overflow) throw tag_overflow;}}, - {{((Rs1 & 0xFFFFFFFF + val2 & 0xFFFFFFFF) >> 31)}}, - {{overflow}}, - {{((Rs1 >> 1) + (val2 >> 1) + (Rs1 & val2 & 0x1))<63:>}}, - {{Rs1<63:> == val2<63:> && val2<63:> != resTemp<63:>}} - );//TADDccTV - 0x23: tsubcctv({{ - int64_t resTemp, val2 = (I ? SIMM13.sdw : Rs2); - Rd = resTemp = Rs1 + val2; - int32_t overflow = Rs1<1:0> || val2<1:0> || (Rs1<31:> == val2<31:> && val2<31:> != resTemp<31:>); - if(overflow) throw tag_overflow;}}, - {{((Rs1 & 0xFFFFFFFF + val2 & 0xFFFFFFFF) >> 31)}}, - {{overflow}}, - {{((Rs1 >> 1) + (val2 >> 1) + (Rs1 & val2 & 0x1))<63:>}}, - {{Rs1<63:> == val2<63:> && val2<63:> != resTemp<63:>}} - );//TSUBccTV - 0x24: mulscc({{ - int64_t resTemp, multiplicand = (I ? SIMM13.sdw : Rs2); - int32_t multiplier = Rs1<31:0>; - int32_t savedLSB = Rs1<0:>; - multiplier = multipler<31:1> | - ((xc->regs.MiscRegs.ccrFields.iccFields.n - ^ xc->regs.MiscRegs.ccrFields.iccFields.v) << 32); - if(!xc->regs.MiscRegs.yFields.value<0:>) - multiplicand = 0; - Rd = resTemp = multiplicand + multiplier; - xc->regs.MiscRegs.yFields.value = xc->regs.MiscRegs.yFields.value<31:1> | (savedLSB << 31);}}, - {{((multiplicand & 0xFFFFFFFF + multiplier & 0xFFFFFFFF) >> 31)}}, - {{multiplicand<31:> == multiplier<31:> && multiplier<31:> != resTemp<31:>}}, - {{((multiplicand >> 1) + (multiplier >> 1) + (multiplicand & multiplier & 0x1))<63:>}}, - {{multiplicand<63:> == multiplier<63:> && multiplier<63:> != resTemp<63:>}} - );//MULScc + 0x3B: Nop::flush({{/*Instruction memory flush*/}}); + 0x3C: save({{ + //CWP should be set directly so that it always happens + //Also, this will allow writing to the new window and + //reading from the old one + if(Cansave == 0) + { + if(Otherwin) + fault = new SpillNOther(WstateOther); + else + fault = new SpillNNormal(WstateNormal); + Cwp = (Cwp + 2) % NWindows; } - format IntegerOp + else if(Cleanwin - Canrestore == 0) { - 0x25: decode X { - 0x0: sll({{Rd = Rs1 << (I ? SHCNT32 : Rs2<4:0>);}}); //SLL - 0x1: sllx({{Rd = Rs1 << (I ? SHCNT64 : Rs2<5:0>);}}); //SLLX - } - 0x26: decode X { - 0x0: srl({{Rd = Rs1.udw<31:0> >> (I ? SHCNT32 : Rs2<4:0>);}}); //SRL - 0x1: srlx({{Rd = Rs1.udw >> (I ? SHCNT64 : Rs2<5:0>);}});//SRLX - } - 0x27: decode X { - 0x0: sra({{Rd = Rs1.sdw<31:0> >> (I ? SHCNT32 : Rs2<4:0>);}}); //SRA - 0x1: srax({{Rd = Rs1.sdw >> (I ? SHCNT64 : Rs2<5:0>);}});//SRAX - } - 0x28: decode RS1 { - 0x0: rdy({{Rd = xc->regs.MiscRegs.yFields.value;}}); //RDY - 0x2: rdccr({{Rd = xc->regs.MiscRegs.ccr;}}); //RDCCR - 0x3: rdasi({{Rd = xc->regs.MiscRegs.asi;}}); //RDASI - 0x4: rdtick({{ - if(xc->regs.MiscRegs.pstateFields.priv == 0 && - xc->regs.MiscRegs.tickFields.npt == 1) - throw privileged_action; - Rd = xc->regs.MiscRegs.tick; - }});//RDTICK - 0x5: rdpc({{Rd = xc->regs.pc;}}); //RDPC - 0x6: rdfprs({{Rd = xc->regs.MiscRegs.fprs;}}); //RDFPRS - 0xF: decode I { - 0x0: Noop::membar({{//Membar isn't needed yet}}); //MEMBAR - 0x1: Noop::stbar({{//Stbar isn/'t needed yet}}); //STBAR - } - } - - 0x2A: decode RS1 { - 0x0: rdprtpc({{checkPriv Rd = xc->regs.MiscRegs.tpc[xc->regs.MiscRegs.tl];}}); - 0x1: rdprtnpc({{checkPriv Rd = xc->regs.MiscRegs.tnpc[xc->regs.MiscRegs.tl];}}); - 0x2: rdprtstate({{checkPriv Rd = xc->regs.MiscRegs.tstate[xc->regs.MiscRegs.tl];}}); - 0x3: rdprtt({{checkPriv Rd = xc->regs.MiscRegs.tt[xc->regs.MiscRegs.tl];}}); - 0x4: rdprtick({{checkPriv Rd = xc->regs.MiscRegs.tick;}}); - 0x5: rdprtba({{checkPriv Rd = xc->regs.MiscRegs.tba;}}); - 0x6: rdprpstate({{checkPriv Rd = xc->regs.MiscRegs.pstate;}}); - 0x7: rdprtl({{checkPriv Rd = xc->regs.MiscRegs.tl;}}); - 0x8: rdprpil({{checkPriv Rd = xc->regs.MiscRegs.pil;}}); - 0x9: rdprcwp({{checkPriv Rd = xc->regs.MiscRegs.cwp;}}); - 0xA: rdprcansave({{checkPriv Rd = xc->regs.MiscRegs.cansave;}}); - 0xB: rdprcanrestore({{checkPriv Rd = xc->regs.MiscRegs.canrestore;}}); - 0xC: rdprcleanwin({{checkPriv Rd = xc->regs.MiscRegs.cleanwin;}}); - 0xD: rdprotherwin({{checkPriv Rd = xc->regs.MiscRegs.otherwin;}}); - 0xE: rdprwstate({{checkPriv Rd = xc->regs.MiscRegs.wstate;}}); - 0xF: rdprfq({{throw illegal_instruction;}}); //The floating point queue isn't implemented right now. - } - 0x2B: BasicOperate::flushw({{\\window toilet}}); //FLUSHW - 0x2C: movcc({{ - ccBank = (CC24 << 2) | (CC14 << 1) | (CC04 << 0); - switch(ccBank) - { - case 0: case 1: case 2: case 3: - throw fp_disabled; - break; - case 5: case 7: - throw illegal_instruction; - break; - case 4: - if(passesCondition(xc->regs.MiscRegs.ccrFields.icc, COND4)) - Rd = (I ? SIMM11.sdw : RS2); - break; - case 6: - if(passesCondition(xc->regs.MiscRegs.ccrFields.xcc, COND4)) - Rd = (I ? SIMM11.sdw : RS2); - break; - } - }});//MOVcc - 0x2D: sdivx({{ - int64_t val2 = (I ? SIMM13.sdw : Rs2.sdw); - if(val2 == 0) throw division_by_zero; - Rd.sdw = Rs1.sdw / val2; - }});//SDIVX - 0x2E: decode RS1 { - 0x0: IntegerOp::popc({{ - int64_t count = 0, val2 = (I ? SIMM13.sdw : Rs2.sdw); - uint8_t oneBits[] = {0,1,1,2,1,2,2,3,1,2,2,3,2,3,3,4} - for(unsigned int x = 0; x < 16; x++) - { - count += oneBits[val2 & 0xF]; - val2 >> 4; - } - }});//POPC - } - 0x2F: movr({{ - uint64_t val2 = (I ? SIMM10.sdw : Rs2.sdw); - switch(RCOND) - { - case 0: case 4: - throw illegal_instruction; - break; - case 1: - if(Rs1 == 0) Rd = val2; - break; - case 2: - if(Rs1 <= 0) Rd = val2; - break; - case 3: - if(Rs1 = 0) Rd = val2; - break; - case 5: - if(Rs1 != 0) Rd = val2; - break; - case 6: - if(Rs1 > 0) Rd = val2; - break; - case 7: - if(Rs1 >= 0) Rd = val2; - break; - } - }});//MOVR - 0x30: decode RD { - 0x0: wry({{ - uint64_t val2 = (I ? SIMM13.sdw : Rs2.sdw); - xc->regs.MiscRegs.y = Rs1 ^ val2; - }});//WRY - 0x2: wrccr({{ - uint64_t val2 = (I ? SIMM13.sdw : Rs2.sdw); - xc->regs.MiscRegs.ccr = Rs1 ^ val2; - }});//WRCCR - 0x3: wrasi({{ - uint64_t val2 = (I ? SIMM13.sdw : Rs2.sdw); - xc->regs.MiscRegs.asi = Rs1 ^ val2; - }});//WRASI - 0x6: wrfprs({{ - uint64_t val2 = (I ? SIMM13.sdw : Rs2.sdw); - xc->regs.MiscRegs.asi = Rs1 ^ val2; - }});//WRFPRS - 0xF: Trap::sir({{software_initiated_reset}}); //SIR - } - 0x31: decode FCN { - 0x0: BasicOperate::saved({{\\Boogy Boogy}}); //SAVED - 0x1: BasicOperate::restored({{\\Boogy Boogy}}); //RESTORED - } - 0x32: decode RD { - 0x0: wrprtpc({{checkPriv - uint64_t val2 = (I ? SIMM13.sdw : Rs2.sdw); - xc->regs.MiscRegs.tpc[xc->regs.MiscRegs.tl] = Rs1 ^ val2; - }}); - 0x1: wrprtnpc({{checkPriv - uint64_t val2 = (I ? SIMM13.sdw : Rs2.sdw); - xc->regs.MiscRegs.tnpc[xc->regs.MiscRegs.tl] = Rs1 ^ val2; - }}); - 0x2: wrprtstate({{checkPriv - uint64_t val2 = (I ? SIMM13.sdw : Rs2.sdw); - xc->regs.MiscRegs.tstate[xc->regs.MiscRegs.tl] = Rs1 ^ val2; - }}); - 0x3: wrprtt({{checkPriv - uint64_t val2 = (I ? SIMM13.sdw : Rs2.sdw); - xc->regs.MiscRegs.tt[xc->regs.MiscRegs.tl] = Rs1 ^ val2; - }}); - 0x4: wrprtick({{checkPriv - uint64_t val2 = (I ? SIMM13.sdw : Rs2.sdw); - xc->regs.MiscRegs.tick = Rs1 ^ val2; - }}); - 0x5: wrprtba({{checkPriv - uint64_t val2 = (I ? SIMM13.sdw : Rs2.sdw); - xc->regs.MiscRegs.tba = Rs1 ^ val2; - }}); - 0x6: wrprpstate({{checkPriv - uint64_t val2 = (I ? SIMM13.sdw : Rs2.sdw); - xc->regs.MiscRegs.pstate = Rs1 ^ val2; - }}); - 0x7: wrprtl({{checkPriv - uint64_t val2 = (I ? SIMM13.sdw : Rs2.sdw); - xc->regs.MiscRegs.tl = Rs1 ^ val2; - }}); - 0x8: wrprpil({{checkPriv - uint64_t val2 = (I ? SIMM13.sdw : Rs2.sdw); - xc->regs.MiscRegs.pil = Rs1 ^ val2; - }}); - 0x9: wrprcwp({{checkPriv - uint64_t val2 = (I ? SIMM13.sdw : Rs2.sdw); - xc->regs.MiscRegs.cwp = Rs1 ^ val2; - }}); - 0xA: wrprcansave({{checkPriv - uint64_t val2 = (I ? SIMM13.sdw : Rs2.sdw); - xc->regs.MiscRegs.cansave = Rs1 ^ val2; - }}); - 0xB: wrprcanrestore({{checkPriv - uint64_t val2 = (I ? SIMM13.sdw : Rs2.sdw); - xc->regs.MiscRegs.canrestore = Rs1 ^ val2; - }}); - 0xC: wrprcleanwin({{checkPriv - uint64_t val2 = (I ? SIMM13.sdw : Rs2.sdw); - xc->regs.MiscRegs.cleanwin = Rs1 ^ val2; - }}); - 0xD: wrprotherwin({{checkPriv - uint64_t val2 = (I ? SIMM13.sdw : Rs2.sdw); - xc->regs.MiscRegs.otherwin = Rs1 ^ val2; - }}); - 0xE: wrprwstate({{checkPriv - uint64_t val2 = (I ? SIMM13.sdw : Rs2.sdw); - xc->regs.MiscRegs.wstate = Rs1 ^ val2; - }}); - } - - 0x34: Trap::fpop1({{Throw fp_disabled;}}); //FPOP1 - 0x35: Trap::fpop2({{Throw fp_disabled;}}); //FPOP2 - - - 0x38: Branch::jmpl({{//Stuff}}); //JMPL - 0x39: Branch::return({{//Other Stuff}}); //RETURN - 0x3A: Trap::tcc({{ - switch((CC14 << 1) | (CC04 << 0)) - { - case 1: case 3: - throw illegal_instruction; - case 0: - if(passesCondition(xc->regs.MiscRegs.ccrFields.icc, machInst<25:28>)) - throw trap_instruction; - break; - case 2: - if(passesCondition(xc->regs.MiscRegs.ccrFields.xcc, machInst<25:28>)) - throw trap_instruction; - break; - } - }}); //Tcc - 0x3B: BasicOperate::flush({{//Lala}}); //FLUSH - 0x3C: BasicOperate::save({{//leprechauns); //SAVE - 0x3D: BasicOperate::restore({{//Eat my short int}}); //RESTORE - 0x3E: decode FCN { - 0x1: BasicOperate::done({{//Done thing}}); //DONE - 0x2: BasicOperate::retry({{//Retry thing}}); //RETRY - } + Cwp = (Cwp + 1) % NWindows; + fault = new CleanWindow; } - } - 0x3: decode OP3 { - format Mem { - 0x00: lduw({{Rd.uw = Mem.uw;}}); //LDUW - 0x01: ldub({{Rd.ub = Mem.ub;}}); //LDUB - 0x02: lduh({{Rd.uhw = Mem.uhw;}}); //LDUH - 0x03: ldd({{ - uint64_t val = Mem.udw; - setIntReg(RD & (~1), val<31:0>); - setIntReg(RD | 1, val<63:32>); - }});//LDD - 0x04: stw({{Mem.sw = Rd.sw;}}); //STW - 0x05: stb({{Mem.sb = Rd.sb;}}); //STB - 0x06: sth({{Mem.shw = Rd.shw;}}); //STH - 0x07: std({{ - Mem.udw = readIntReg(RD & (~1))<31:0> | (readIntReg(RD | 1)<31:0> << 32); - }});//STD - 0x08: ldsw({{Rd.sw = Mem.sw;}}); //LDSW - 0x09: ldsb({{Rd.sb = Mem.sb;}}); //LDSB - 0x0A: ldsh({{Rd.shw = Mem.shw;}}); //LDSH - 0x0B: ldx({{Rd.udw = Mem.udw;}}); //LDX - - 0x0D: ldstub({{ - Rd.ub = Mem.ub; - Mem.ub = 0xFF; - }}); //LDSTUB - 0x0E: stx({{Rd.udw = Mem.udw;}}); //STX - 0x0F: swap({{ - uint32_t temp = Rd.uw; - Rd.uw = Mem.uw; - Mem.uw = temp; - }}); //SWAP - 0x10: lduwa({{Rd.uw = Mem.uw;}}); //LDUWA - 0x11: lduba({{Rd.ub = Mem.ub;}}); //LDUBA - 0x12: lduha({{Rd.uhw = Mem.uhw;}}); //LDUHA - 0x13: ldda({{ - uint64_t val = Mem.udw; - setIntReg(RD & (~1), val<31:0>); - setIntReg(RD | 1, val<63:32>); - }}); //LDDA - 0x14: stwa({{Mem.uw = Rd.uw;}}); //STWA - 0x15: stba({{Mem.ub = Rd.ub;}}); //STBA - 0x16: stha({{Mem.uhw = Rd.uhw;}}); //STHA - 0x17: stda({{ - Mem.udw = readIntReg(RD & (~1))<31:0> | (readIntReg(RD | 1)<31:0> << 32); - }}); //STDA - 0x18: ldswa({{Rd.sw = Mem.sw;}}); //LDSWA - 0x19: ldsba({{Rd.sb = Mem.sb;}}); //LDSBA - 0x1A: ldsha({{Rd.shw = Mem.shw;}}); //LDSHA - 0x1B: ldxa({{Rd.sdw = Mem.sdw;}}); //LDXA - - 0x1D: ldstuba({{ - Rd.ub = Mem.ub; - Mem.ub = 0xFF; - }}); //LDSTUBA - 0x1E: stxa({{Mem.sdw = Rd.sdw}}); //STXA - 0x1F: swapa({{ - uint32_t temp = Rd.uw; - Rd.uw = Mem.uw; - Mem.uw = temp; - }}); //SWAPA - 0x20: Trap::ldf({{throw fp_disabled;}}); //LDF - 0x21: decode X { - 0x0: Trap::ldfsr({{throw fp_disabled;}}); //LDFSR - 0x1: Trap::ldxfsr({{throw fp_disabled;}}); //LDXFSR - } - 0x22: Trap::ldqf({{throw fp_disabled;}}); //LDQF - 0x23: Trap::lddf({{throw fp_disabled;}}); //LDDF - 0x24: Trap::stf({{throw fp_disabled;}}); //STF - 0x25: decode X { - 0x0: Trap::stfsr({{throw fp_disabled;}}); //STFSR - 0x1: Trap::stxfsr({{throw fp_disabled;}}); //STXFSR - } - 0x26: Trap::stqf({{throw fp_disabled;}}); //STQF - 0x27: Trap::stdf({{throw fp_disabled;}}); //STDF - - - - - - 0x2D: Noop::prefetch({{ }}); //PREFETCH - - - 0x30: Trap::ldfa({{throw fp_disabled;}}); //LDFA - - 0x32: Trap::ldqfa({{throw fp_disabled;}}); //LDQFA - 0x33: Trap::lddfa({{throw fp_disabled;}}); //LDDFA - 0x34: Trap::stfa({{throw fp_disabled;}}); //STFA - 0x35: Trap::stqfa({{throw fp_disabled;}}); //STQFA - 0x36: Trap::stdfa({{throw fp_disabled;}}); //STDFA - - - - - - 0x3C: Cas::casa( - {{uint64_t val = Mem.uw; - if(Rs2.uw == val) - Mem.uw = Rd.uw; - Rd.uw = val; - }}); //CASA - 0x3D: Noop::prefetcha({{ }}); //PREFETCHA - 0x3E: Cas::casxa( - {{uint64_t val = Mem.udw; - if(Rs2 == val) - Mem.udw = Rd; - Rd = val; - }}); //CASXA + else + { + Cwp = (Cwp + 1) % NWindows; + Rd = Rs1 + Rs2_or_imm13; + Cansave = Cansave - 1; + Canrestore = Canrestore + 1; + } + //This is here to make sure the CWP is written + //no matter what. This ensures that the results + //are written in the new window as well. + xc->setMiscRegWithEffect(MISCREG_CWP, Cwp); + }}); + 0x3D: restore({{ + //CWP should be set directly so that it always happens + //Also, this will allow writing to the new window and + //reading from the old one + Cwp = (Cwp - 1 + NWindows) % NWindows; + if(Canrestore == 0) + { + if(Otherwin) + fault = new FillNOther(WstateOther); + else + fault = new FillNNormal(WstateNormal); + } + else + { + Rd = Rs1 + Rs2_or_imm13; + Cansave = Cansave + 1; + Canrestore = Canrestore - 1; } + //This is here to make sure the CWP is written + //no matter what. This ensures that the results + //are written in the new window as well. + xc->setMiscRegWithEffect(MISCREG_CWP, Cwp); + }}); + 0x3E: decode FCN { + 0x0: Priv::done({{ + if(Tl == 0) + return new IllegalInstruction; + Cwp = xc->readMiscReg(MISCREG_TSTATE_CWP_BASE + Tl); + Asi = xc->readMiscReg(MISCREG_TSTATE_ASI_BASE + Tl); + Ccr = xc->readMiscReg(MISCREG_TSTATE_CCR_BASE + Tl); + Pstate = xc->readMiscReg(MISCREG_TSTATE_PSTATE_BASE + Tl); + NPC = xc->readMiscReg(MISCREG_TNPC_BASE + Tl); + NNPC = NPC + 4; + Tl = Tl - 1; + }}); + 0x1: BasicOperate::retry({{ + if(Tl == 0) + return new IllegalInstruction; + Cwp = xc->readMiscReg(MISCREG_TSTATE_CWP_BASE + Tl); + Asi = xc->readMiscReg(MISCREG_TSTATE_ASI_BASE + Tl); + Ccr = xc->readMiscReg(MISCREG_TSTATE_CCR_BASE + Tl); + Pstate = xc->readMiscReg(MISCREG_TSTATE_PSTATE_BASE + Tl); + NPC = xc->readMiscReg(MISCREG_TPC_BASE + Tl); + NNPC = xc->readMiscReg(MISCREG_TNPC_BASE + Tl); + Tl = Tl - 1; + }}); + } + } + } + 0x3: decode OP3 { + format Load { + 0x00: lduw({{Rd = Mem;}}, {{32}}); + 0x01: ldub({{Rd = Mem;}}, {{8}}); + 0x02: lduh({{Rd = Mem;}}, {{16}}); + 0x03: ldd({{ + uint64_t val = Mem; + RdLow = val<31:0>; + RdHigh = val<63:32>; + }}, {{64}}); + } + format Store { + 0x04: stw({{Mem = Rd.sw;}}, {{32}}); + 0x05: stb({{Mem = Rd.sb;}}, {{8}}); + 0x06: sth({{Mem = Rd.shw;}}, {{16}}); + 0x07: std({{Mem = RdLow<31:0> | RdHigh<31:0> << 32;}}, {{64}}); + } + format Load { + 0x08: ldsw({{Rd = (int32_t)Mem;}}, {{32}}); + 0x09: ldsb({{Rd = (int8_t)Mem;}}, {{8}}); + 0x0A: ldsh({{Rd = (int16_t)Mem;}}, {{16}}); + 0x0B: ldx({{Rd = (int64_t)Mem;}}, {{64}}); + 0x0D: ldstub({{ + Rd = Mem; + Mem = 0xFF; + }}, {{8}}); + } + 0x0E: Store::stx({{Mem = Rd}}, {{64}}); + 0x0F: LoadStore::swap({{ + uint32_t temp = Rd; + Rd = Mem; + Mem = temp; + }}, {{32}}); + format Load { + 0x10: lduwa({{Rd = Mem;}}, {{32}}); + 0x11: lduba({{Rd = Mem;}}, {{8}}); + 0x12: lduha({{Rd = Mem;}}, {{16}}); + 0x13: ldda({{ + uint64_t val = Mem; + RdLow = val<31:0>; + RdHigh = val<63:32>; + }}, {{64}}); + } + format Store { + 0x14: stwa({{Mem = Rd;}}, {{32}}); + 0x15: stba({{Mem = Rd;}}, {{8}}); + 0x16: stha({{Mem = Rd;}}, {{16}}); + 0x17: stda({{Mem = RdLow<31:0> | RdHigh<31:0> << 32;}}, {{64}}); + } + format Load { + 0x18: ldswa({{Rd = (int32_t)Mem;}}, {{32}}); + 0x19: ldsba({{Rd = (int8_t)Mem;}}, {{8}}); + 0x1A: ldsha({{Rd = (int16_t)Mem;}}, {{16}}); + 0x1B: ldxa({{Rd = (int64_t)Mem;}}, {{64}}); + } + 0x1D: LoadStore::ldstuba({{ + Rd = Mem; + Mem = 0xFF; + }}, {{8}}); + 0x1E: Store::stxa({{Mem = Rd}}, {{64}}); + 0x1F: LoadStore::swapa({{ + uint32_t temp = Rd; + Rd = Mem; + Mem = temp; + }}, {{32}}); + format Trap { + 0x20: ldf({{fault = new FpDisabled;}}); + 0x21: decode X { + 0x0: Load::ldfsr({{Fsr = Mem<31:0> | Fsr<63:32>;}}, {{32}}); + 0x1: Load::ldxfsr({{Fsr = Mem;}}, {{64}}); + } + 0x22: ldqf({{fault = new FpDisabled;}}); + 0x23: lddf({{fault = new FpDisabled;}}); + 0x24: stf({{fault = new FpDisabled;}}); + 0x25: decode X { + 0x0: Store::stfsr({{Mem = Fsr<31:0>;}}, {{32}}); + 0x1: Store::stxfsr({{Mem = Fsr;}}, {{64}}); + } + 0x26: stqf({{fault = new FpDisabled;}}); + 0x27: stdf({{fault = new FpDisabled;}}); + 0x2D: Nop::prefetch({{ }}); + 0x30: ldfa({{return new FpDisabled;}}); + 0x32: ldqfa({{fault = new FpDisabled;}}); + 0x33: lddfa({{fault = new FpDisabled;}}); + 0x34: stfa({{fault = new FpDisabled;}}); + 0x35: stqfa({{fault = new FpDisabled;}}); + 0x36: stdfa({{fault = new FpDisabled;}}); + 0x3C: Cas::casa({{ + uint64_t val = Mem.uw; + if(Rs2.uw == val) + Mem.uw = Rd.uw; + Rd.uw = val; + }}); + 0x3D: Nop::prefetcha({{ }}); + 0x3E: Cas::casxa({{ + uint64_t val = Mem.udw; + if(Rs2 == val) + Mem.udw = Rd; + Rd = val; + }}); } + } } diff --git a/arch/sparc/isa/formats.isa b/arch/sparc/isa/formats.isa index 547f8be48..17d68061b 100644 --- a/arch/sparc/isa/formats.isa +++ b/arch/sparc/isa/formats.isa @@ -1,19 +1,28 @@ //Include the basic format //Templates from this format are used later -##include "m5/arch/sparc/isa/formats/basic.isa" +##include "formats/basic.isa" + +//Include the noop format +##include "formats/nop.isa" //Include the integerOp and integerOpCc format -##include "m5/arch/sparc/isa/formats/integerop.isa" +##include "formats/integerop.isa" -//Include the mem format -##include "m5/arch/sparc/isa/formats/mem.isa" +//Include the memory format +##include "formats/mem.isa" + +//Include the compare and swap format +##include "formats/cas.isa" //Include the trap format -##include "m5/arch/sparc/isa/formats/trap.isa" +##include "formats/trap.isa" -//Include the branch format -##include "m5/arch/sparc/isa/formats/branch.isa" +//Include the "unknown" format +##include "formats/unknown.isa" -//Include the noop format -##include "m5/arch/sparc/isa/formats/noop.isa" +//Include the priveleged mode format +##include "formats/priv.isa" + +//Include the branch format +##include "formats/branch.isa" diff --git a/arch/sparc/isa/formats/branch.isa b/arch/sparc/isa/formats/branch.isa index 80101de1b..37bdb9402 100644 --- a/arch/sparc/isa/formats/branch.isa +++ b/arch/sparc/isa/formats/branch.isa @@ -5,7 +5,7 @@ output header {{ /** - * Base class for integer operations. + * Base class for branch operations. */ class Branch : public SparcStaticInst { @@ -19,12 +19,187 @@ output header {{ std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const; }; + + /** + * Base class for branch operations with an immediate displacement. + */ + class BranchDisp : public Branch + { + protected: + // Constructor + BranchDisp(const char *mnem, MachInst _machInst, + OpClass __opClass) : + Branch(mnem, _machInst, __opClass) + { + } + + std::string generateDisassembly(Addr pc, + const SymbolTable *symtab) const; + + int32_t disp; + }; + + /** + * Base class for branches with 19 bit displacements. + */ + class Branch19 : public BranchDisp + { + protected: + // Constructor + Branch19(const char *mnem, MachInst _machInst, + OpClass __opClass) : + BranchDisp(mnem, _machInst, __opClass) + { + disp = sign_ext(DISP19 << 2, 21); + } + }; + + /** + * Base class for branches with 22 bit displacements. + */ + class Branch22 : public BranchDisp + { + protected: + // Constructor + Branch22(const char *mnem, MachInst _machInst, + OpClass __opClass) : + BranchDisp(mnem, _machInst, __opClass) + { + disp = sign_ext(DISP22 << 2, 24); + } + }; + + /** + * Base class for branches with 30 bit displacements. + */ + class Branch30 : public BranchDisp + { + protected: + // Constructor + Branch30(const char *mnem, MachInst _machInst, + OpClass __opClass) : + BranchDisp(mnem, _machInst, __opClass) + { + disp = sign_ext(DISP30 << 2, 32); + } + }; + + /** + * Base class for 16bit split displacements. + */ + class BranchSplit : public BranchDisp + { + protected: + // Constructor + BranchSplit(const char *mnem, MachInst _machInst, + OpClass __opClass) : + BranchDisp(mnem, _machInst, __opClass) + { + disp = sign_ext((D16HI << 16) | (D16LO << 2), 18); + } + }; + + /** + * Base class for branches that use an immediate and a register to + * compute their displacements. + */ + class BranchImm13 : public Branch + { + protected: + // Constructor + BranchImm13(const char *mnem, MachInst _machInst, OpClass __opClass) : + Branch(mnem, _machInst, __opClass), imm(sign_ext(SIMM13, 13)) + { + } + + std::string generateDisassembly(Addr pc, + const SymbolTable *symtab) const; + + int32_t imm; + }; }}; output decoder {{ - std::string Branch::generateDisassembly(Addr pc, const SymbolTable *symtab) const + std::string Branch::generateDisassembly(Addr pc, + const SymbolTable *symtab) const + { + std::stringstream response; + + printMnemonic(response, mnemonic); + + if (_numSrcRegs > 0) + { + printReg(response, _srcRegIdx[0]); + for(int x = 1; x < _numSrcRegs; x++) + { + response << ", "; + printReg(response, _srcRegIdx[x]); + } + } + + if (_numDestRegs > 0) + { + if(_numSrcRegs > 0) + response << ", "; + printReg(response, _destRegIdx[0]); + } + + return response.str(); + } + + std::string BranchImm13::generateDisassembly(Addr pc, + const SymbolTable *symtab) const + { + std::stringstream response; + + printMnemonic(response, mnemonic); + + if (_numSrcRegs > 0) + { + printReg(response, _srcRegIdx[0]); + for(int x = 1; x < _numSrcRegs; x++) + { + response << ", "; + printReg(response, _srcRegIdx[x]); + } + } + + if(_numSrcRegs > 0) + response << ", "; + + ccprintf(response, "0x%x", imm); + + if (_numDestRegs > 0) + { + response << ", "; + printReg(response, _destRegIdx[0]); + } + + return response.str(); + } + + std::string BranchDisp::generateDisassembly(Addr pc, + const SymbolTable *symtab) const { - return "Branch instruction\n"; + std::stringstream response; + std::string symbol; + Addr symbolAddr; + + Addr target = disp + pc; + + printMnemonic(response, mnemonic); + ccprintf(response, "0x%x", target); + + if(symtab->findNearestSymbol(target, symbol, symbolAddr)) + { + ccprintf(response, " <%s", symbol); + if(symbolAddr != target) + ccprintf(response, "+%d>", target - symbolAddr); + else + ccprintf(response, ">"); + } + + return response.str(); } }}; @@ -34,10 +209,11 @@ def template BranchExecute {{ { //Attempt to execute the instruction Fault fault = NoFault; - checkPriv; %(op_decl)s; %(op_rd)s; + + NNPC = xc->readNextNPC(); %(code)s; if(fault == NoFault) @@ -50,13 +226,83 @@ def template BranchExecute {{ } }}; -// Primary format for integer operate instructions: +let {{ + handle_annul = ''' + { + if(A) + { + NPC = xc->readNextNPC(); + NNPC = NPC + 4; + } + else + { + NPC = xc->readNextPC(); + NNPC = xc->readNextNPC(); + } + }''' +}}; + +// Primary format for branch instructions: def format Branch(code, *opt_flags) {{ - orig_code = code - cblk = CodeBlock(code) - iop = InstObjParams(name, Name, 'SparcStaticInst', cblk, opt_flags) + code = re.sub(r'handle_annul', handle_annul, code) + (usesImm, code, immCode, + rString, iString) = splitOutImm(code) + iop = InstObjParams(name, Name, 'Branch', code, opt_flags) + header_output = BasicDeclare.subst(iop) + decoder_output = BasicConstructor.subst(iop) + exec_output = BranchExecute.subst(iop) + if usesImm: + imm_iop = InstObjParams(name, Name + 'Imm', 'BranchImm' + iString, + immCode, opt_flags) + header_output += BasicDeclare.subst(imm_iop) + decoder_output += BasicConstructor.subst(imm_iop) + exec_output += BranchExecute.subst(imm_iop) + decode_block = ROrImmDecode.subst(iop) + else: + decode_block = BasicDecode.subst(iop) +}}; + +// Primary format for branch instructions: +def format Branch19(code, *opt_flags) {{ + code = re.sub(r'handle_annul', handle_annul, code) + codeBlk = CodeBlock(code) + iop = InstObjParams(name, Name, 'Branch19', codeBlk, opt_flags) + header_output = BasicDeclare.subst(iop) + decoder_output = BasicConstructor.subst(iop) + exec_output = BranchExecute.subst(iop) + decode_block = BasicDecode.subst(iop) +}}; + +// Primary format for branch instructions: +def format Branch22(code, *opt_flags) {{ + code = re.sub(r'handle_annul', handle_annul, code) + codeBlk = CodeBlock(code) + iop = InstObjParams(name, Name, 'Branch22', codeBlk, opt_flags) header_output = BasicDeclare.subst(iop) decoder_output = BasicConstructor.subst(iop) - decode_block = BasicDecodeWithMnemonic.subst(iop) exec_output = BranchExecute.subst(iop) + decode_block = BasicDecode.subst(iop) }}; + +// Primary format for branch instructions: +def format Branch30(code, *opt_flags) {{ + code = re.sub(r'handle_annul', handle_annul, code) + codeBlk = CodeBlock(code) + iop = InstObjParams(name, Name, 'Branch30', codeBlk, opt_flags) + header_output = BasicDeclare.subst(iop) + decoder_output = BasicConstructor.subst(iop) + exec_output = BranchExecute.subst(iop) + decode_block = BasicDecode.subst(iop) +}}; + +// Primary format for branch instructions: +def format BranchSplit(code, *opt_flags) {{ + code = re.sub(r'handle_annul', handle_annul, code) + codeBlk = CodeBlock(code) + iop = InstObjParams(name, Name, 'BranchSplit', codeBlk, opt_flags) + header_output = BasicDeclare.subst(iop) + decoder_output = BasicConstructor.subst(iop) + exec_output = BranchExecute.subst(iop) + decode_block = BasicDecode.subst(iop) +}}; + diff --git a/arch/sparc/isa/formats/integerop.isa b/arch/sparc/isa/formats/integerop.isa index 5a9e09896..881154b67 100644 --- a/arch/sparc/isa/formats/integerop.isa +++ b/arch/sparc/isa/formats/integerop.isa @@ -7,106 +7,343 @@ output header {{ /** * Base class for integer operations. */ - class IntegerOp : public SparcStaticInst + class IntOp : public SparcStaticInst { protected: // Constructor - IntegerOp(const char *mnem, MachInst _machInst, OpClass __opClass) : + IntOp(const char *mnem, ExtMachInst _machInst, + OpClass __opClass) : SparcStaticInst(mnem, _machInst, __opClass) { } std::string generateDisassembly(Addr pc, + const SymbolTable *symtab) const; + + virtual bool printPseudoOps(std::ostream &os, Addr pc, + const SymbolTable *symtab) const; + }; + + /** + * Base class for immediate integer operations. + */ + class IntOpImm : public IntOp + { + protected: + // Constructor + IntOpImm(const char *mnem, ExtMachInst _machInst, + OpClass __opClass) : + IntOp(mnem, _machInst, __opClass) + { + } + + int32_t imm; + + std::string generateDisassembly(Addr pc, + const SymbolTable *symtab) const; + + virtual bool printPseudoOps(std::ostream &os, Addr pc, const SymbolTable *symtab) const; }; + + /** + * Base class for 10 bit immediate integer operations. + */ + class IntOpImm10 : public IntOpImm + { + protected: + // Constructor + IntOpImm10(const char *mnem, ExtMachInst _machInst, + OpClass __opClass) : + IntOpImm(mnem, _machInst, __opClass) + { + imm = sign_ext(SIMM10, 10); + } + }; + + /** + * Base class for 11 bit immediate integer operations. + */ + class IntOpImm11 : public IntOpImm + { + protected: + // Constructor + IntOpImm11(const char *mnem, ExtMachInst _machInst, + OpClass __opClass) : + IntOpImm(mnem, _machInst, __opClass) + { + imm = sign_ext(SIMM11, 11); + } + }; + + /** + * Base class for 13 bit immediate integer operations. + */ + class IntOpImm13 : public IntOpImm + { + protected: + // Constructor + IntOpImm13(const char *mnem, ExtMachInst _machInst, + OpClass __opClass) : + IntOpImm(mnem, _machInst, __opClass) + { + imm = sign_ext(SIMM13, 13); + } + }; + + /** + * Base class for sethi. + */ + class SetHi : public IntOpImm + { + protected: + // Constructor + SetHi(const char *mnem, ExtMachInst _machInst, + OpClass __opClass) : + IntOpImm(mnem, _machInst, __opClass) + { + imm = (IMM22 << 10) & 0xFFFFFC00; + } + + std::string generateDisassembly(Addr pc, + const SymbolTable *symtab) const; + }; +}}; + +def template SetHiDecode {{ + { + if(RD == 0 && IMM22 == 0) + return (SparcStaticInst *)(new Nop("nop", machInst, No_OpClass)); + else + return (SparcStaticInst *)(new %(class_name)s(machInst)); + } }}; output decoder {{ - std::string IntegerOp::generateDisassembly(Addr pc, - const SymbolTable *symtab) const + + bool IntOp::printPseudoOps(std::ostream &os, Addr pc, + const SymbolTable *symbab) const { - return "Integer instruction\n"; + if(!strcmp(mnemonic, "or") && _srcRegIdx[0] == 0) + { + printMnemonic(os, "mov"); + if(_numSrcRegs > 0) + printReg(os, _srcRegIdx[1]); + ccprintf(os, ", "); + if(_numDestRegs > 0) + printReg(os, _destRegIdx[0]); + + return true; + } + return false; } -}}; -def template IntegerExecute {{ - Fault %(class_name)s::execute(%(CPU_exec_context)s *xc, Trace::InstRecord *traceData) const + bool IntOpImm::printPseudoOps(std::ostream &os, Addr pc, + const SymbolTable *symbab) const { - //These are set to constants when the execute method - //is generated - bool useCc = ; - bool checkPriv = ; - - //Attempt to execute the instruction - try + if(!strcmp(mnemonic, "or")) + { + if(_srcRegIdx[0] == 0) + { + if(imm == 0) + { + printMnemonic(os, "clr"); + if(_numDestRegs > 0) + printReg(os, _destRegIdx[0]); + return true; + } + else + { + printMnemonic(os, "mov"); + ccprintf(os, ", 0x%x, ", imm); + if(_numDestRegs > 0) + printReg(os, _destRegIdx[0]); + return true; + } + } + else if(imm == 0) { - checkPriv; + printMnemonic(os, "mov"); + if(_numSrcRegs > 0) + printReg(os, _srcRegIdx[0]); + ccprintf(os, ", "); + if(_numDestRegs > 0) + printReg(os, _destRegIdx[0]); + return true; + } + } + return false; + } + + std::string IntOp::generateDisassembly(Addr pc, + const SymbolTable *symtab) const + { + std::stringstream response; - %(op_decl)s; - %(op_rd)s; - %(code)s; + if(!printPseudoOps(response, pc, symtab)) + { + printMnemonic(response, mnemonic); + if (_numSrcRegs > 0) + { + printReg(response, _srcRegIdx[0]); + for(int x = 1; x < _numSrcRegs; x++) + { + response << ", "; + printReg(response, _srcRegIdx[x]); + } } - //If we have an exception for some reason, - //deal with it - catch(SparcException except) + if (_numDestRegs > 0) { - //Deal with exception - return No_Fault; + if(_numSrcRegs > 0) + response << ", "; + printReg(response, _destRegIdx[0]); } + } + return response.str(); + } - //Write the resulting state to the execution context - %(op_wb)s; - if(useCc) + std::string IntOpImm::generateDisassembly(Addr pc, + const SymbolTable *symtab) const + { + std::stringstream response; + + if(!printPseudoOps(response, pc, symtab)) + { + printMnemonic(response, mnemonic); + if (_numSrcRegs > 0) + { + printReg(response, _srcRegIdx[0]); + for(int x = 1; x < _numSrcRegs - 1; x++) + { + response << ", "; + printReg(response, _srcRegIdx[x]); + } + } + if(_numSrcRegs > 0) + response << ", "; + ccprintf(response, "0x%x", imm); + if (_numDestRegs > 0) { - xc->regs.miscRegFile.ccrFields.iccFields.n = Rd & (1 << 63); - xc->regs.miscRegFile.ccrFields.iccFields.z = (Rd == 0); - xc->regs.miscRegFile.ccrFields.iccFields.v = ivValue; - xc->regs.miscRegFile.ccrFields.iccFields.c = icValue; - xc->regs.miscRegFile.ccrFields.xccFields.n = Rd & (1 << 31); - xc->regs.miscRegFile.ccrFields.xccFields.z = ((Rd & 0xFFFFFFFF) == 0); - xc->regs.miscRegFile.ccrFields.xccFields.v = xvValue; - xc->regs.miscRegFile.ccrFields.xccFields.c = xcValue; + response << ", "; + printReg(response, _destRegIdx[0]); } - return No_Fault; + } + return response.str(); + } + + std::string SetHi::generateDisassembly(Addr pc, + const SymbolTable *symtab) const + { + std::stringstream response; + + printMnemonic(response, mnemonic); + if(_numSrcRegs > 0) + response << ", "; + ccprintf(response, "%%hi(0x%x), ", imm); + printReg(response, _destRegIdx[0]); + return response.str(); } }}; -// Primary format for integer operate instructions: -def format IntegerOp(code, *opt_flags) {{ - orig_code = code - cblk = CodeBlock(code) - checkPriv = (code.find('checkPriv') != -1) - code.replace('checkPriv', '') - if checkPriv: - code.replace('checkPriv;', 'if(!xc->regs.miscRegFile.pstateFields.priv) throw privileged_opcode;') - else: - code.replace('checkPriv;', '') - for (marker, value) in (('ivValue', '0'), ('icValue', '0'), - ('xvValue', '0'), ('xcValue', '0')): - code.replace(marker, value) - iop = InstObjParams(name, Name, 'SparcStaticInst', cblk, opt_flags) +def template IntOpExecute {{ + 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; + + //Write the resulting state to the execution context + if(fault == NoFault) + { + %(cc_code)s; + %(op_wb)s; + } + return fault; + } +}}; + +let {{ + def doIntFormat(code, ccCode, name, Name, opt_flags): + (usesImm, code, immCode, + rString, iString) = splitOutImm(code) + iop = InstObjParams(name, Name, 'IntOp', code, + opt_flags, ("cc_code", ccCode)) header_output = BasicDeclare.subst(iop) decoder_output = BasicConstructor.subst(iop) - decode_block = BasicDecodeWithMnemonic.subst(iop) - exec_output = IntegerExecute.subst(iop) + exec_output = IntOpExecute.subst(iop) + if usesImm: + imm_iop = InstObjParams(name, Name + 'Imm', 'IntOpImm' + iString, + immCode, opt_flags, ("cc_code", ccCode)) + header_output += BasicDeclare.subst(imm_iop) + decoder_output += BasicConstructor.subst(imm_iop) + exec_output += IntOpExecute.subst(imm_iop) + decode_block = ROrImmDecode.subst(iop) + else: + decode_block = BasicDecode.subst(iop) + return (header_output, decoder_output, exec_output, decode_block) + + calcCcCode = ''' + CcrIccN = (Rd >> 31) & 1; + CcrIccZ = ((Rd & 0xFFFFFFFF) == 0); + CcrXccN = (Rd >> 63) & 1; + CcrXccZ = (Rd == 0); + CcrIccV = %(ivValue)s; + CcrIccC = %(icValue)s; + CcrXccV = %(xvValue)s; + CcrXccC = %(xcValue)s; + DPRINTF(Sparc, "in = %%d\\n", CcrIccN); + DPRINTF(Sparc, "iz = %%d\\n", CcrIccZ); + DPRINTF(Sparc, "xn = %%d\\n", CcrXccN); + DPRINTF(Sparc, "xz = %%d\\n", CcrXccZ); + DPRINTF(Sparc, "iv = %%d\\n", CcrIccV); + DPRINTF(Sparc, "ic = %%d\\n", CcrIccC); + DPRINTF(Sparc, "xv = %%d\\n", CcrXccV); + DPRINTF(Sparc, "xc = %%d\\n", CcrXccC); + ''' }}; // Primary format for integer operate instructions: -def format IntegerOpCc(code, icValue, ivValue, xcValue, xvValue, *opt_flags) {{ - orig_code = code - cblk = CodeBlock(code) - checkPriv = (code.find('checkPriv') != -1) - code.replace('checkPriv', '') - if checkPriv: - code.replace('checkPriv;', 'if(!xc->regs.miscRegFile.pstateFields.priv) throw privileged_opcode;') - else: - code.replace('checkPriv;', '') - for (marker, value) in (('ivValue', ivValue), ('icValue', icValue), - ('xvValue', xvValue), ('xcValue', xcValue)): - code.replace(marker, value) - iop = InstObjParams(name, Name, 'SparcStaticInst', cblk, opt_flags) - header_output = BasicDeclare.subst(iop) - decoder_output = BasicConstructor.subst(iop) - decode_block = BasicDecodeWithMnemonic.subst(iop) - exec_output = IntegerExecute.subst(iop) +def format IntOp(code, *opt_flags) {{ + ccCode = '' + (header_output, + decoder_output, + exec_output, + decode_block) = doIntFormat(code, ccCode, + name, Name, opt_flags) +}}; + +// Primary format for integer operate instructions: +def format IntOpCc(code, icValue, ivValue, xcValue, xvValue, *opt_flags) {{ + ccCode = calcCcCode % vars() + (header_output, + decoder_output, + exec_output, + decode_block) = doIntFormat(code, ccCode, + name, Name, opt_flags) +}}; + +// Primary format for integer operate instructions: +def format IntOpCcRes(code, *opt_flags) {{ + ccCode = calcCcCode % {"icValue":"0", + "ivValue":"0", + "xcValue":"0", + "xvValue":"0"} + (header_output, + decoder_output, + exec_output, + decode_block) = doIntFormat(code, ccCode, + name, Name, opt_flags) }}; + +def format SetHi(code, *opt_flags) {{ + iop = InstObjParams(name, Name, 'SetHi', + code, opt_flags, ("cc_code", '')) + header_output = BasicDeclare.subst(iop) + decoder_output = BasicConstructor.subst(iop) + exec_output = IntOpExecute.subst(iop) + decode_block = SetHiDecode.subst(iop) +}}; + diff --git a/arch/sparc/isa/formats/mem.isa b/arch/sparc/isa/formats/mem.isa index d72de47d0..12dae57e5 100644 --- a/arch/sparc/isa/formats/mem.isa +++ b/arch/sparc/isa/formats/mem.isa @@ -5,14 +5,14 @@ output header {{ /** - * Base class for integer operations. + * Base class for memory operations. */ class Mem : public SparcStaticInst { protected: // Constructor - Mem(const char *mnem, MachInst _machInst, OpClass __opClass) : + Mem(const char *mnem, ExtMachInst _machInst, OpClass __opClass) : SparcStaticInst(mnem, _machInst, __opClass) { } @@ -20,12 +20,82 @@ output header {{ std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const; }; + + /** + * Class for memory operations which use an immediate offset. + */ + class MemImm : public Mem + { + protected: + + // Constructor + MemImm(const char *mnem, ExtMachInst _machInst, OpClass __opClass) : + Mem(mnem, _machInst, __opClass) + { + imm = sign_ext(SIMM13, 13); + } + + std::string generateDisassembly(Addr pc, + const SymbolTable *symtab) const; + + int32_t imm; + }; }}; output decoder {{ - std::string Mem::generateDisassembly(Addr pc, const SymbolTable *symtab) const + std::string Mem::generateDisassembly(Addr pc, + const SymbolTable *symtab) const + { + std::stringstream response; + bool load = flags[IsLoad]; + bool save = flags[IsStore]; + + printMnemonic(response, mnemonic); + if(save) + { + printReg(response, _srcRegIdx[0]); + ccprintf(response, ", "); + } + ccprintf(response, "[ "); + printReg(response, _srcRegIdx[!save ? 0 : 1]); + ccprintf(response, " + "); + printReg(response, _srcRegIdx[!save ? 1 : 2]); + ccprintf(response, " ]"); + if(load) + { + ccprintf(response, ", "); + printReg(response, _destRegIdx[0]); + } + + return response.str(); + } + + std::string MemImm::generateDisassembly(Addr pc, + const SymbolTable *symtab) const { - return "Memory instruction\n"; + std::stringstream response; + bool load = flags[IsLoad]; + bool save = flags[IsStore]; + + printMnemonic(response, mnemonic); + if(save) + { + printReg(response, _srcRegIdx[0]); + ccprintf(response, ", "); + } + ccprintf(response, "[ "); + printReg(response, _srcRegIdx[!save ? 0 : 1]); + if(imm >= 0) + ccprintf(response, " + 0x%x ]", imm); + else + ccprintf(response, " + -0x%x ]", -imm); + if(load) + { + ccprintf(response, ", "); + printReg(response, _destRegIdx[0]); + } + + return response.str(); } }}; @@ -34,10 +104,14 @@ def template MemExecute {{ Trace::InstRecord *traceData) const { Fault fault = NoFault; + Addr EA; %(op_decl)s; %(op_rd)s; - ea_code + %(ea_code)s; + DPRINTF(Sparc, "The address is 0x%x\n", EA); + %(load)s; %(code)s; + %(store)s; if(fault == NoFault) { @@ -49,25 +123,49 @@ def template MemExecute {{ } }}; -// Primary format for integer operate instructions: -def format Mem(code, *opt_flags) {{ - orig_code = code - cblk = CodeBlock(code) - iop = InstObjParams(name, Name, 'SparcStaticInst', cblk, opt_flags) - header_output = BasicDeclare.subst(iop) - decoder_output = BasicConstructor.subst(iop) - decode_block = BasicDecodeWithMnemonic.subst(iop) - exec_output = MemExecute.subst(iop) - exec_output.replace('ea_code', 'EA = I ? (R1 + SIMM13) : R1 + R2;'); +let {{ + # Leave memAccessFlags at 0 for now + loadString = "xc->read(EA, (uint%(width)s_t&)Mem, 0);" + storeString = "uint64_t write_result = 0; \ + xc->write((uint%(width)s_t)Mem, EA, 0, &write_result);" + + def doMemFormat(code, load, store, name, Name, opt_flags): + addrCalcReg = 'EA = Rs1 + Rs2;' + addrCalcImm = 'EA = Rs1 + imm;' + iop = InstObjParams(name, Name, 'Mem', code, + opt_flags, ("ea_code", addrCalcReg), + ("load", load), ("store", store)) + iop_imm = InstObjParams(name, Name + 'Imm', 'MemImm', code, + opt_flags, ("ea_code", addrCalcImm), + ("load", load), ("store", store)) + header_output = BasicDeclare.subst(iop) + BasicDeclare.subst(iop_imm) + decoder_output = BasicConstructor.subst(iop) + BasicConstructor.subst(iop_imm) + decode_block = ROrImmDecode.subst(iop) + exec_output = MemExecute.subst(iop) + MemExecute.subst(iop_imm) + return (header_output, decoder_output, exec_output, decode_block) +}}; + +def format Load(code, width, *opt_flags) {{ + (header_output, + decoder_output, + exec_output, + decode_block) = doMemFormat(code, + loadString % {"width":width}, '', name, Name, opt_flags) +}}; + +def format Store(code, width, *opt_flags) {{ + (header_output, + decoder_output, + exec_output, + decode_block) = doMemFormat(code, '', + storeString % {"width":width}, name, Name, opt_flags) }}; -def format Cas(code, *opt_flags) {{ - orig_code = code - cblk = CodeBlock(code) - iop = InstObjParams(name, Name, 'SparcStaticInst', cblk, opt_flags) - header_output = BasicDeclare.subst(iop) - decoder_output = BasicConstructor.subst(iop) - decode_block = BasicDecodeWithMnemonic.subst(iop) - exec_output = MemExecute.subst(iop) - exec_output.replace('ea_code', 'EA = R1;'); +def format LoadStore(code, width, *opt_flags) {{ + (header_output, + decoder_output, + exec_output, + decode_block) = doMemFormat(code, + loadString % {"width":width}, storeString % {"width":width}, + name, Name, opt_flags) }}; diff --git a/arch/sparc/isa/formats/noop.isa b/arch/sparc/isa/formats/noop.isa deleted file mode 100644 index fa4047f06..000000000 --- a/arch/sparc/isa/formats/noop.isa +++ /dev/null @@ -1,50 +0,0 @@ -//////////////////////////////////////////////////////////////////// -// -// Noop instruction -// - -output header {{ - /** - * Noop class. - */ - class Noop : public SparcStaticInst - { - protected: - // Constructor - Noop(const char *mnem, MachInst _machInst, OpClass __opClass) : - SparcStaticInst(mnem, _machInst, __opClass) - { - } - - std::string generateDisassembly(Addr pc, - const SymbolTable *symtab) const; - }; -}}; - -output decoder {{ - std::string Noop::generateDisassembly(Addr pc, - const SymbolTable *symtab) const - { - return "Noop\n"; - } -}}; - -def template NoopExecute {{ - Fault %(class_name)s::execute(%(CPU_exec_context)s *xc, - Trace::InstRecord *traceData) const - { - //Nothing to see here, move along - return NoFault; - } -}}; - -// Primary format for integer operate instructions: -def format Noop(code, *opt_flags) {{ - orig_code = code - cblk = CodeBlock(code) - iop = InstObjParams(name, Name, 'SparcStaticInst', cblk, opt_flags) - header_output = BasicDeclare.subst(iop) - decoder_output = BasicConstructor.subst(iop) - decode_block = BasicDecodeWithMnemonic.subst(iop) - exec_output = NoopExecute.subst(iop) -}}; diff --git a/arch/sparc/isa/formats/nop.isa b/arch/sparc/isa/formats/nop.isa new file mode 100644 index 000000000..df7503eee --- /dev/null +++ b/arch/sparc/isa/formats/nop.isa @@ -0,0 +1,62 @@ +//////////////////////////////////////////////////////////////////// +// +// Nop instruction +// + +output header {{ + /** + * Nop class. + */ + class Nop : public SparcStaticInst + { + public: + // Constructor + Nop(const char *mnem, ExtMachInst _machInst, OpClass __opClass) : + SparcStaticInst(mnem, _machInst, __opClass) + { + } + + // All Nop instructions do the same thing, so this can be + // defined here. Nops can be defined directly, so there needs + // to be a default implementation + Fault execute(%(CPU_exec_context)s *xc, + Trace::InstRecord *traceData) const + { + //Nothing to see here, move along + return NoFault; + } + + std::string generateDisassembly(Addr pc, + const SymbolTable *symtab) const; + }; +}}; + +output decoder {{ + std::string Nop::generateDisassembly(Addr pc, + const SymbolTable *symtab) const + { + std::stringstream response; + printMnemonic(response, mnemonic); + return response.str(); + } +}}; + +def template NopExecute {{ + Fault %(class_name)s::execute(%(CPU_exec_context)s *xc, + Trace::InstRecord *traceData) const + { + //Nothing to see here, move along + return NoFault; + } +}}; + +// Primary format for integer operate instructions: +def format Nop(code, *opt_flags) {{ + orig_code = code + cblk = CodeBlock(code) + iop = InstObjParams(name, Name, 'Nop', cblk, opt_flags) + header_output = BasicDeclare.subst(iop) + decoder_output = BasicConstructor.subst(iop) + decode_block = BasicDecode.subst(iop) + exec_output = NopExecute.subst(iop) +}}; diff --git a/arch/sparc/isa/formats/priv.isa b/arch/sparc/isa/formats/priv.isa new file mode 100644 index 000000000..f9fea01f2 --- /dev/null +++ b/arch/sparc/isa/formats/priv.isa @@ -0,0 +1,139 @@ +//////////////////////////////////////////////////////////////////// +// +// Privilege mode instructions +// + +output header {{ + /** + * Base class for privelege mode operations. + */ + class Priv : public SparcStaticInst + { + protected: + // Constructor + Priv(const char *mnem, ExtMachInst _machInst, OpClass __opClass) : + SparcStaticInst(mnem, _machInst, __opClass) + { + } + + std::string generateDisassembly(Addr pc, + const SymbolTable *symtab) const; + }; + + /** + * Base class for user mode "tick" access. + */ + class PrivTick : public SparcStaticInst + { + protected: + // Constructor + PrivTick(const char *mnem, ExtMachInst _machInst, + OpClass __opClass) : + SparcStaticInst(mnem, _machInst, __opClass) + { + } + + std::string generateDisassembly(Addr pc, + const SymbolTable *symtab) const; + }; + + /** + * Base class for privelege mode operations with immediates. + */ + class PrivImm : public Priv + { + protected: + // Constructor + PrivImm(const char *mnem, ExtMachInst _machInst, + OpClass __opClass) : + Priv(mnem, _machInst, __opClass), imm(SIMM13) + { + } + + int32_t imm; + }; + + /** + * Base class for user mode "tick" access with immediates. + */ + class PrivTickImm : public PrivTick + { + protected: + // Constructor + PrivTickImm(const char *mnem, ExtMachInst _machInst, + OpClass __opClass) : + PrivTick(mnem, _machInst, __opClass), imm(SIMM13) + { + } + + int32_t imm; + }; +}}; + +output decoder {{ + std::string Priv::generateDisassembly(Addr pc, + const SymbolTable *symtab) const + { + return "Privileged Instruction"; + } + + std::string PrivTick::generateDisassembly(Addr pc, + const SymbolTable *symtab) const + { + return "Regular access to Tick"; + } +}}; + +def template PrivExecute {{ + Fault %(class_name)s::execute(%(CPU_exec_context)s *xc, + Trace::InstRecord *traceData) const + { + %(op_decl)s; + %(op_rd)s; + + //If the processor isn't in privileged mode, fault out right away + if(%(check)s) + return new PrivilegedAction; + + %(code)s; + %(op_wb)s; + return NoFault; + } +}}; + +let {{ + def doPrivFormat(code, checkCode, name, Name, opt_flags): + (usesImm, code, immCode, + rString, iString) = splitOutImm(code) + iop = InstObjParams(name, Name, 'Priv', code, + opt_flags, ("check", checkCode)) + header_output = BasicDeclare.subst(iop) + decoder_output = BasicConstructor.subst(iop) + exec_output = PrivExecute.subst(iop) + if usesImm: + imm_iop = InstObjParams(name, Name + 'Imm', 'PrivImm', + immCode, opt_flags, ("check", checkCode)) + header_output += BasicDeclare.subst(imm_iop) + decoder_output += BasicConstructor.subst(imm_iop) + exec_output += PrivExecute.subst(imm_iop) + decode_block = ROrImmDecode.subst(iop) + else: + decode_block = BasicDecode.subst(iop) + return (header_output, decoder_output, exec_output, decode_block) +}}; + +// Primary format for integer operate instructions: +def format Priv(code, *opt_flags) {{ + checkCode = "(!PstatePriv)" + (header_output, decoder_output, + exec_output, decode_block) = doPrivFormat(code, + checkCode, name, Name, opt_flags) +}}; + +// Primary format for integer operate instructions: +def format PrivTick(code, *opt_flags) {{ + checkCode = "(!PstatePriv && TickNpt)" + (header_output, decoder_output, + exec_output, decode_block) = doPrivFormat(code, + checkCode, name, Name, opt_flags) +}}; diff --git a/arch/sparc/isa/formats/trap.isa b/arch/sparc/isa/formats/trap.isa index ff3aadf72..f6a45ca48 100644 --- a/arch/sparc/isa/formats/trap.isa +++ b/arch/sparc/isa/formats/trap.isa @@ -5,20 +5,23 @@ output header {{ /** - * Base class for integer operations. + * Base class for trap instructions, + * or instructions that always fault. */ class Trap : public SparcStaticInst { protected: // Constructor - Trap(const char *mnem, MachInst _machInst, OpClass __opClass) : - SparcStaticInst(mnem, _machInst, __opClass) + Trap(const char *mnem, ExtMachInst _machInst, OpClass __opClass) : + SparcStaticInst(mnem, _machInst, __opClass), trapNum(SW_TRAP) { } std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const; + + int trapNum; }; }}; @@ -26,7 +29,15 @@ output decoder {{ std::string Trap::generateDisassembly(Addr pc, const SymbolTable *symtab) const { - return "Trap instruction\n"; + std::stringstream response; + + printMnemonic(response, mnemonic); + ccprintf(response, " "); + printReg(response, _srcRegIdx[0]); + ccprintf(response, ", 0x%x", trapNum); + ccprintf(response, ", or "); + printReg(response, _srcRegIdx[1]); + return response.str(); } }}; @@ -34,18 +45,20 @@ def template TrapExecute {{ Fault %(class_name)s::execute(%(CPU_exec_context)s *xc, Trace::InstRecord *traceData) const { - //TODO: set up a software fault and return it. - return NoFault; + Fault fault = NoFault; + %(op_decl)s; + %(op_rd)s; + %(code)s + return fault; } }}; -// Primary format for integer operate instructions: def format Trap(code, *opt_flags) {{ orig_code = code cblk = CodeBlock(code) - iop = InstObjParams(name, Name, 'SparcStaticInst', cblk, opt_flags) + iop = InstObjParams(name, Name, 'Trap', cblk, opt_flags) header_output = BasicDeclare.subst(iop) decoder_output = BasicConstructor.subst(iop) - decode_block = BasicDecodeWithMnemonic.subst(iop) + decode_block = BasicDecode.subst(iop) exec_output = TrapExecute.subst(iop) }}; diff --git a/arch/sparc/isa/formats/unknown.isa b/arch/sparc/isa/formats/unknown.isa new file mode 100644 index 000000000..223111905 --- /dev/null +++ b/arch/sparc/isa/formats/unknown.isa @@ -0,0 +1,46 @@ +//////////////////////////////////////////////////////////////////// +// +// Unknown instructions +// + +output header {{ + /** + * Class for Unknown/Illegal instructions + */ + class Unknown : public SparcStaticInst + { + public: + + // Constructor + Unknown(ExtMachInst _machInst) : + SparcStaticInst("unknown", _machInst, No_OpClass) + { + } + + %(BasicExecDeclare)s + + std::string generateDisassembly(Addr pc, + const SymbolTable *symtab) const; + + }; +}}; + +output decoder {{ + std::string Unknown::generateDisassembly(Addr pc, + const SymbolTable *symtab) const + { + return "Unknown instruction"; + } +}}; + +output exec {{ + Fault Unknown::execute(%(CPU_exec_context)s *xc, + Trace::InstRecord *traceData) const + { + return new IllegalInstruction; + } +}}; + +def format Unknown() {{ + decode_block = 'return new Unknown(machInst);\n' +}}; diff --git a/arch/sparc/isa/includes.isa b/arch/sparc/isa/includes.isa index a99018b49..ff4174899 100644 --- a/arch/sparc/isa/includes.isa +++ b/arch/sparc/isa/includes.isa @@ -10,8 +10,9 @@ output header {{ #include "cpu/static_inst.hh" #include "arch/sparc/faults.hh" -#include "mem/mem_req.hh" // some constructors use MemReq flags +#include "mem/request.hh" // some constructors use MemReq flags #include "arch/sparc/isa_traits.hh" +#include "arch/sparc/regfile.hh" }}; output decoder {{ @@ -34,10 +35,12 @@ output exec {{ #endif #ifdef FULL_SYSTEM -//#include "arch/alpha/pseudo_inst.hh" +//#include "sim/pseudo_inst.hh" #endif #include "cpu/base.hh" #include "cpu/exetrace.hh" #include "sim/sim_exit.hh" + +using namespace SparcISA; }}; diff --git a/arch/sparc/isa/main.isa b/arch/sparc/isa/main.isa index ab0290d58..35167d6b7 100644 --- a/arch/sparc/isa/main.isa +++ b/arch/sparc/isa/main.isa @@ -26,7 +26,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. -##include "m5/arch/sparc/isa/includes.isa" +##include "includes.isa" //////////////////////////////////////////////////////////////////// // @@ -37,16 +37,16 @@ namespace SparcISA; //Include the bitfield definitions -##include "m5/arch/sparc/isa/bitfields.isa" +##include "bitfields.isa" //Include the operand_types and operand definitions -##include "m5/arch/sparc/isa/operands.isa" +##include "operands.isa" //Include the base class for sparc instructions, and some support code -##include "m5/arch/sparc/isa/base.isa" +##include "base.isa" //Include the definitions for the instruction formats -##include "m5/arch/sparc/isa/formats.isa" +##include "formats.isa" //Include the decoder definition -##include "m5/arch/sparc/isa/decoder.isa" +##include "decoder.isa" diff --git a/arch/sparc/isa/operands.isa b/arch/sparc/isa/operands.isa index 64f5abd08..64a032eea 100644 --- a/arch/sparc/isa/operands.isa +++ b/arch/sparc/isa/operands.isa @@ -16,16 +16,100 @@ def operands {{ # Int regs default to unsigned, but code should not count on this. # For clarity, descriptions that depend on unsigned behavior should # explicitly specify '.uq'. - 'Rd': ('IntReg', 'udw', 'RD', 'IsInteger', 1), - 'Rs1': ('IntReg', 'udw', 'RS1', 'IsInteger', 2), - 'Rs2': ('IntReg', 'udw', 'RS2', 'IsInteger', 3), + 'Rd': ('IntReg', 'udw', 'RD', 'IsInteger', 1), + 'RdLow': ('IntReg', 'udw', 'RD & (~1)', 'IsInteger', 2), + 'RdHigh': ('IntReg', 'udw', 'RD | 1', 'IsInteger', 3), + 'Rs1': ('IntReg', 'udw', 'RS1', 'IsInteger', 4), + 'Rs2': ('IntReg', 'udw', 'RS2', 'IsInteger', 5), #'Fa': ('FloatReg', 'df', 'FA', 'IsFloating', 1), #'Fb': ('FloatReg', 'df', 'FB', 'IsFloating', 2), #'Fc': ('FloatReg', 'df', 'FC', 'IsFloating', 3), - 'Mem': ('Mem', 'udw', None, ('IsMemRef', 'IsLoad', 'IsStore'), 4), - #'NPC': ('NPC', 'uq', None, ( None, None, 'IsControl' ), 4), + 'Mem': ('Mem', 'udw', None, ('IsMemRef', 'IsLoad', 'IsStore'), 4), + 'NPC': ('NPC', 'udw', None, ( None, None, 'IsControl' ), 4), + 'NNPC': ('NNPC', 'udw', None, (None, None, 'IsControl' ), 4), #'Runiq': ('ControlReg', 'uq', 'Uniq', None, 1), #'FPCR': ('ControlReg', 'uq', 'Fpcr', None, 1), - 'R0': ('IntReg', 'udw', '0', None, 1), - 'R16': ('IntReg', 'udw', '16', None, 1) + 'R0': ('IntReg', 'udw', '0', None, 6), + 'R1': ('IntReg', 'udw', '1', None, 7), + 'R15': ('IntReg', 'udw', '15', 'IsInteger', 8), + 'R16': ('IntReg', 'udw', '16', None, 9), + # Control registers + 'Pstate': ('ControlReg', 'udw', 'MISCREG_PSTATE', None, 1), + 'PstateAg': ('ControlReg', 'udw', 'MISCREG_PSTATE_AG', None, 2), + 'PstateIe': ('ControlReg', 'udw', 'MISCREG_PSTATE_IE', None, 3), + 'PstatePriv': ('ControlReg', 'udw', 'MISCREG_PSTATE_PRIV', None, 4), + 'PstateAm': ('ControlReg', 'udw', 'MISCREG_PSTATE_AM', None, 5), + 'PstatePef': ('ControlReg', 'udw', 'MISCREG_PSTATE_PEF', None, 6), + 'PstateRed': ('ControlReg', 'udw', 'MISCREG_PSTATE_RED', None, 7), + 'PstateMm': ('ControlReg', 'udw', 'MISCREG_PSTATE_MM', None, 8), + 'PstateTle': ('ControlReg', 'udw', 'MISCREG_PSTATE_TLE', None, 9), + 'PstateCle': ('ControlReg', 'udw', 'MISCREG_PSTATE_CLE', None, 10), + 'Tba': ('ControlReg', 'udw', 'MISCREG_TBA', None, 11), + 'Y': ('ControlReg', 'udw', 'MISCREG_Y', None, 12), + 'YValue': ('ControlReg', 'udw', 'MISCREG_Y_VALUE', None, 13), + 'Pil': ('ControlReg', 'udw', 'MISCREG_PIL', None, 14), + 'Cwp': ('ControlReg', 'udw', 'MISCREG_CWP', None, 15), + #'Tt': ('ControlReg', 'udw', 'MISCREG_TT_BASE + tl', None, 16), + 'Ccr': ('ControlReg', 'udw', 'MISCREG_CCR', None, 17), + 'CcrIcc': ('ControlReg', 'udw', 'MISCREG_CCR_ICC', None, 18), + 'CcrIccC': ('ControlReg', 'udw', 'MISCREG_CCR_ICC_C', None, 19), + 'CcrIccV': ('ControlReg', 'udw', 'MISCREG_CCR_ICC_V', None, 20), + 'CcrIccZ': ('ControlReg', 'udw', 'MISCREG_CCR_ICC_Z', None, 21), + 'CcrIccN': ('ControlReg', 'udw', 'MISCREG_CCR_ICC_N', None, 22), + 'CcrXcc': ('ControlReg', 'udw', 'MISCREG_CCR_XCC', None, 23), + 'CcrXccC': ('ControlReg', 'udw', 'MISCREG_CCR_XCC_C', None, 22), + 'CcrXccV': ('ControlReg', 'udw', 'MISCREG_CCR_XCC_V', None, 23), + 'CcrXccZ': ('ControlReg', 'udw', 'MISCREG_CCR_XCC_Z', None, 24), + 'CcrXccN': ('ControlReg', 'udw', 'MISCREG_CCR_XCC_N', None, 25), + 'Asi': ('ControlReg', 'udw', 'MISCREG_ASI', None, 26), + 'Tl': ('ControlReg', 'udw', 'MISCREG_TL', None, 27), + #'Tpc': ('ControlReg', 'udw', 'MISCREG_TPC', None, 28), + 'Tick': ('ControlReg', 'udw', 'MISCREG_TICK', None, 29), + 'TickCounter': ('ControlReg', 'udw', 'MISCREG_TICK_COUNTER', None, 32), + 'TickNpt': ('ControlReg', 'udw', 'MISCREG_TICK_NPT', None, 33), + 'Cansave': ('ControlReg', 'udw', 'MISCREG_CANSAVE', None, 34), + 'Canrestore': ('ControlReg', 'udw', 'MISCREG_CANRESTORE', None, 35), + 'Otherwin': ('ControlReg', 'udw', 'MISCREG_OTHERWIN', None, 36), + 'Cleanwin': ('ControlReg', 'udw', 'MISCREG_CLEANWIN', None, 37), + 'Wstate': ('ControlReg', 'udw', 'MISCREG_WSTATE', None, 38), + 'WstateNormal': ('ControlReg', 'udw', 'MISCREG_WSTATE_NORMAL', None,39), + 'WstateOther': ('ControlReg', 'udw', 'MISCREG_WSTATE_OTHER', None, 40), + 'Ver': ('ControlReg', 'udw', 'MISCREG_VER', None, 41), + 'VerMaxwin': ('ControlReg', 'udw', 'MISCREG_VER_MAXWIN', None, 42), + 'VerMaxtl': ('ControlReg', 'udw', 'MISCREG_VER_MAXTL', None, 43), + 'VerMask': ('ControlReg', 'udw', 'MISCREG_VER_MASK', None, 44), + 'VerImpl': ('ControlReg', 'udw', 'MISCREG_VER_MASK', None, 45), + 'VerManuf': ('ControlReg', 'udw', 'MISCREG_VER_MANUF', None, 46), + 'Fsr': ('ControlReg', 'udw', 'MISCREG_FSR', None, 47), + 'FsrCexc': ('ControlReg', 'udw', 'MISCREG_FSR_CEXC', None, 48), + 'FsrCexcNxc': ('ControlReg', 'udw', 'MISCREG_FSR_CEXC_NXC', None, 49), + 'FsrCexcDzc': ('ControlReg', 'udw', 'MISCREG_FSR_CEXC_DZC', None, 50), + 'FsrCexcUfc': ('ControlReg', 'udw', 'MISCREG_FSR_CEXC_UFC', None, 51), + 'FsrCexcOfc': ('ControlReg', 'udw', 'MISCREG_FSR_CEXC_OFC', None, 52), + 'FsrCexcNvc': ('ControlReg', 'udw', 'MISCREG_FSR_CEXC_NVC', None, 53), + 'FsrAexc': ('ControlReg', 'udw', 'MISCREG_FSR_AEXC', None, 54), + 'FsrAexcNxc': ('ControlReg', 'udw', 'MISCREG_FSR_AEXC_NXC', None, 55), + 'FsrAexcDzc': ('ControlReg', 'udw', 'MISCREG_FSR_AEXC_DZC', None, 56), + 'FsrAexcUfc': ('ControlReg', 'udw', 'MISCREG_FSR_AEXC_UFC', None, 57), + 'FsrAexcOfc': ('ControlReg', 'udw', 'MISCREG_FSR_AEXC_OFC', None, 58), + 'FsrAexcNvc': ('ControlReg', 'udw', 'MISCREC_FSR_AEXC_NVC', None, 59), + 'FsrFcc0': ('ControlReg', 'udw', 'MISCREG_FSR_FCC0', None, 60), + 'FsrQne': ('ControlReg', 'udw', 'MISCREG_FSR_QNE', None, 61), + 'FsrFtt': ('ControlReg', 'udw', 'MISCREG_FSR_FTT', None, 62), + 'FsrVer': ('ControlReg', 'udw', 'MISCREG_FSR_VER', None, 63), + 'FsrNs': ('ControlReg', 'udw', 'MISCREG_FSR_NS', None, 64), + 'FsrTem': ('ControlReg', 'udw', 'MISCREG_FSR_TEM', None, 65), + 'FsrTemNxm': ('ControlReg', 'udw', 'MISCREG_FSR_TEM_NXM', None, 66), + 'FsrTemDzm': ('ControlReg', 'udw', 'MISCREG_FSR_TEM_DZM', None, 67), + 'FsrTemUfm': ('ControlReg', 'udw', 'MISCREG_FSR_TEM_UFM', None, 68), + 'FsrTemOfm': ('ControlReg', 'udw', 'MISCREG_FSR_TEM_OFM', None, 69), + 'FsrTemNvm': ('ControlReg', 'udw', 'MISCREG_FSR_TEM_NVM', None, 70), + 'FsrRd': ('ControlReg', 'udw', 'MISCREG_FSR_RD', None, 71), + 'FsrFcc1': ('ControlReg', 'udw', 'MISCREG_FSR_FCC1', None, 72), + 'FsrFcc2': ('ControlReg', 'udw', 'MISCREG_FSR_FCC2', None, 73), + 'FsrFcc3': ('ControlReg', 'udw', 'MISCREG_FSR_FCC3', None, 74), + 'Fprs': ('ControlReg', 'udw', 'MISCREG_FPRS', None, 75), + 'FprsDl': ('ControlReg', 'udw', 'MISCREG_FPRS_DL', None, 76), + 'FprsDu': ('ControlReg', 'udw', 'MISCREG_FPRS_DU', None, 77), + 'FprsFef': ('ControlReg', 'udw', 'MISCREG_FPRS_FEF', None, 78) }}; diff --git a/arch/sparc/isa_traits.hh b/arch/sparc/isa_traits.hh index bd3c35beb..453d14664 100644 --- a/arch/sparc/isa_traits.hh +++ b/arch/sparc/isa_traits.hh @@ -29,46 +29,85 @@ #ifndef __ARCH_SPARC_ISA_TRAITS_HH__ #define __ARCH_SPARC_ISA_TRAITS_HH__ -#include "arch/sparc/faults.hh" #include "base/misc.hh" #include "config/full_system.hh" #include "sim/host.hh" -//This makes sure the big endian versions of certain functions are used. -namespace BigEndianGuest {} -using namespace BigEndianGuest; - class ExecContext; class FastCPU; //class FullCPU; class Checkpoint; -#define TARGET_SPARC - class StaticInst; class StaticInstPtr; -//namespace EV5 -//{ -// int DTB_ASN_ASN(uint64_t reg); -// int ITB_ASN_ASN(uint64_t reg); -//} +namespace BigEndianGuest {} + +#if !FULL_SYSTEM +class SyscallReturn +{ + public: + template <class T> + SyscallReturn(T v, bool s) + { + retval = (uint64_t)v; + success = s; + } + + template <class T> + SyscallReturn(T v) + { + success = (v >= 0); + retval = (uint64_t)v; + } + + ~SyscallReturn() {} + + SyscallReturn& operator=(const SyscallReturn& s) + { + retval = s.retval; + success = s.success; + return *this; + } + + bool successful() { return success; } + uint64_t value() { return retval; } + + private: + uint64_t retval; + bool success; +}; + +#endif + namespace SparcISA { + + // These enumerate all the registers for dependence tracking. + enum DependenceTags { + // 0..31 are the integer regs 0..31 + // 32..63 are the FP regs 0..31, i.e. use (reg + FP_Base_DepTag) + FP_Base_DepTag = 32, + Ctrl_Base_DepTag = 96, + //XXX These are here solely to get compilation and won't work + Fpcr_DepTag = 0, + Uniq_DepTag = 0 + }; + + //This makes sure the big endian versions of certain functions are used. + using namespace BigEndianGuest; + typedef uint32_t MachInst; typedef uint64_t ExtMachInst; - typedef uint8_t RegIndex; - const int NumFloatRegs = 32; + const int NumIntRegs = 32; + const int NumFloatRegs = 64; const int NumMiscRegs = 32; - const int // Maximum trap level - const int MaxTL = 4; - const int - const int // semantically meaningful register indices + // semantically meaningful register indices const int ZeroReg = 0; // architecturally meaningful - const int // the rest of these depend on the ABI + // the rest of these depend on the ABI const int StackPointerReg = 14; const int ReturnAddressReg = 31; // post call, precall is 15 const int ReturnValueReg = 8; // Post return, 24 is pre-return. @@ -79,449 +118,70 @@ namespace SparcISA const int ArgumentReg3 = 11; const int ArgumentReg4 = 12; const int ArgumentReg5 = 13; - // Some OS syscall sue a second register (o1) to return a second value + // Some OS syscall use a second register (o1) to return a second value const int SyscallPseudoReturnReg = ArgumentReg1; + //XXX These numbers are bogus + const int MaxInstSrcRegs = 8; + const int MaxInstDestRegs = 9; + + typedef uint64_t IntReg; + + // control register file contents + typedef uint64_t MiscReg; + + typedef double FloatReg; + typedef uint64_t FloatRegBits; //8K. This value is implmentation specific; and should probably //be somewhere else. const int LogVMPageSize = 13; const int VMPageSize = (1 << LogVMPageSize); + //Why does both the previous set of constants and this one exist? + const int PageShift = 13; + const int PageBytes = ULL(1) << PageShift; + const int BranchPredAddrShiftAmt = 2; - - - - - - - - - - - - - - - - - - - - - typedef uint64_t IntReg; - - class IntRegFile - { - private: - //For right now, let's pretend the register file is static - IntReg regs[32]; - public: - IntReg & operator [] (RegIndex index) - { - //Don't allow indexes outside of the 32 registers - index &= 0x1F; - return regs[index]; - } - }; + const int MachineBytes = 8; + const int WordBytes = 4; + const int HalfwordBytes = 2; + const int ByteBytes = 1; void serialize(std::ostream & os); void unserialize(Checkpoint *cp, const std::string §ion); - typedef float float32_t; - typedef double float64_t; - //FIXME This actually usually refers to a 10 byte float, rather than a - //16 byte float as required. This data type may have to be emulated. - typedef long double float128_t; - - class FloatRegFile - { - private: - //By using the largest data type, we ensure everything - //is aligned correctly in memory - union - { - float128_t rawRegs[16]; - uint64_t regDump[32]; - }; - class QuadRegs - { - private: - FloatRegFile * parent; - public: - QuadRegs(FloatRegFile * p) : parent(p) {;} - float128_t & operator [] (RegIndex index) - { - //Quad floats are index by the single - //precision register the start on, - //and only 16 should be accessed - index = (index >> 2) & 0xF; - return parent->rawRegs[index]; - } - }; - class DoubleRegs - { - private: - FloatRegFile * parent; - public: - DoubleRegs(FloatRegFile * p) : parent(p) {;} - float64_t & operator [] (RegIndex index) - { - //Double floats are index by the single - //precision register the start on, - //and only 32 should be accessed - index = (index >> 1) & 0x1F; - return ((float64_t *)parent->rawRegs)[index]; - } - }; - class SingleRegs - { - private: - FloatRegFile * parent; - public: - SingleRegs(FloatRegFile * p) : parent(p) {;} - float32_t & operator [] (RegIndex index) - { - //Only 32 single floats should be accessed - index &= 0x1F; - return ((float32_t *)parent->rawRegs)[index]; - } - }; - public: - void serialize(std::ostream & os); - - void unserialize(Checkpoint * cp, std::string & section); - - QuadRegs quadRegs; - DoubleRegs doubleRegs; - SingleRegs singleRegs; - FloatRegFile() : quadRegs(this), doubleRegs(this), singleRegs(this) - {;} - }; - - // control register file contents - typedef uint64_t MiscReg; - // The control registers, broken out into fields - class MiscRegFile - { - private: - union - { - uint16_t pstate; // Process State Register - struct - { - uint16_t ag:1; // Alternate Globals - uint16_t ie:1; // Interrupt enable - uint16_t priv:1; // Privelege mode - uint16_t am:1; // Address mask - uint16_t pef:1; // PSTATE enable floating-point - uint16_t red:1; // RED (reset, error, debug) state - uint16_t mm:2; // Memory Model - uint16_t tle:1; // Trap little-endian - uint16_t cle:1; // Current little-endian - } pstateFields; - }; - uint64_t tba; // Trap Base Address - union - { - uint64_t y; // Y (used in obsolete multiplication) - struct - { - uint64_t value:32; // The actual value stored in y - uint64_t :32; // reserved bits - } yFields; - }; - uint8_t pil; // Process Interrupt Register - uint8_t cwp; // Current Window Pointer - uint16_t tt[MaxTL]; // Trap Type (Type of trap which occured - // on the previous level) - union - { - uint8_t ccr; // Condition Code Register - struct - { - union - { - uint8_t icc:4; // 32-bit condition codes - struct - { - uint8_t c:1; // Carry - uint8_t v:1; // Overflow - uint8_t z:1; // Zero - uint8_t n:1; // Negative - } iccFields; - }; - union - { - uint8_t xcc:4; // 64-bit condition codes - struct - { - uint8_t c:1; // Carry - uint8_t v:1; // Overflow - uint8_t z:1; // Zero - uint8_t n:1; // Negative - } xccFields; - }; - } ccrFields; - }; - uint8_t asi; // Address Space Identifier - uint8_t tl; // Trap Level - uint64_t tpc[MaxTL]; // Trap Program Counter (value from - // previous trap level) - uint64_t tnpc[MaxTL]; // Trap Next Program Counter (value from - // previous trap level) - union - { - uint64_t tstate[MaxTL]; // Trap State - struct - { - //Values are from previous trap level - uint64_t cwp:5; // Current Window Pointer - uint64_t :2; // Reserved bits - uint64_t pstate:10; // Process State - uint64_t :6; // Reserved bits - uint64_t asi:8; // Address Space Identifier - uint64_t ccr:8; // Condition Code Register - } tstateFields[MaxTL]; - }; - union - { - uint64_t tick; // Hardware clock-tick counter - struct - { - uint64_t counter:63; // Clock-tick count - uint64_t npt:1; // Non-priveleged trap - } tickFields; - }; - uint8_t cansave; // Savable windows - uint8_t canrestore; // Restorable windows - uint8_t otherwin; // Other windows - uint8_t cleanwin; // Clean windows - union - { - uint8_t wstate; // Window State - struct - { - uint8_t normal:3; // Bits TT<4:2> are set to on a normal - // register window trap - uint8_t other:3; // Bits TT<4:2> are set to on an "otherwin" - // register window trap - } wstateFields; - }; - union - { - uint64_t ver; // Version - struct - { - uint64_t maxwin:5; // Max CWP value - uint64_t :2; // Reserved bits - uint64_t maxtl:8; // Maximum trap level - uint64_t :8; // Reserved bits - uint64_t mask:8; // Processor mask set revision number - uint64_t impl:16; // Implementation identification number - uint64_t manuf:16; // Manufacturer code - } verFields; - }; - union - { - uint64_t fsr; // Floating-Point State Register - struct - { - union - { - uint64_t cexc:5; // Current excpetion - struct - { - uint64_t nxc:1; // Inexact - uint64_t dzc:1; // Divide by zero - uint64_t ufc:1; // Underflow - uint64_t ofc:1; // Overflow - uint64_t nvc:1; // Invalid operand - } cexecFields; - }; - union - { - uint64_t aexc:5; // Accrued exception - struct - { - uint64_t nxc:1; // Inexact - uint64_t dzc:1; // Divide by zero - uint64_t ufc:1; // Underflow - uint64_t ofc:1; // Overflow - uint64_t nvc:1; // Invalid operand - } aexecFields; - }; - uint64_t fcc0:2; // Floating-Point condtion codes - uint64_t :1; // Reserved bits - uint64_t qne:1; // Deferred trap queue not empty - // with no queue, it should read 0 - uint64_t ftt:3; // Floating-Point trap type - uint64_t ver:3; // Version (of the FPU) - uint64_t :2; // Reserved bits - uint64_t ns:1; // Nonstandard floating point - union - { - uint64_t tem:5; // Trap Enable Mask - struct - { - uint64_t nxm:1; // Inexact - uint64_t dzm:1; // Divide by zero - uint64_t ufm:1; // Underflow - uint64_t ofm:1; // Overflow - uint64_t nvm:1; // Invalid operand - } temFields; - }; - uint64_t :2; // Reserved bits - uint64_t rd:2; // Rounding direction - uint64_t fcc1:2; // Floating-Point condition codes - uint64_t fcc2:2; // Floating-Point condition codes - uint64_t fcc3:2; // Floating-Point condition codes - uint64_t :26; // Reserved bits - } fsrFields; - }; - union - { - uint8_t fprs; // Floating-Point Register State - struct - { - uint8_t dl:1; // Dirty lower - uint8_t du:1; // Dirty upper - uint8_t fef:1; // FPRS enable floating-Point - } fprsFields; - }; - - public: - MiscReg readReg(int misc_reg); - - MiscReg readRegWithEffect(int misc_reg, Fault &fault, ExecContext *xc); - - Fault setReg(int misc_reg, const MiscReg &val); - - Fault setRegWithEffect(int misc_reg, const MiscReg &val, - ExecContext *xc); - - void serialize(std::ostream & os); - - void unserialize(Checkpoint * cp, std::string & section); - }; - - typedef union - { - float32_t singReg; - float64_t doubReg; - float128_t quadReg; - } FloatReg; - - typedef union - { - IntReg intreg; - FloatReg fpreg; - MiscReg ctrlreg; - } AnyReg; - - struct RegFile - { - IntRegFile intRegFile; // (signed) integer register file - FloatRegFile floatRegFile; // floating point register file - MiscRegFile miscRegFile; // control register file - - Addr pc; // Program Counter - Addr npc; // Next Program Counter - Addr nnpc; - - void serialize(std::ostream &os); - void unserialize(Checkpoint *cp, const std::string §ion); - }; - - StaticInstPtr decodeInst(MachInst); + StaticInstPtr decodeInst(ExtMachInst); // return a no-op instruction... used for instruction fetch faults extern const MachInst NoopMachInst; +} - // Instruction address compression hooks - inline Addr realPCToFetchPC(const Addr &addr) - { - return addr; - } - - inline Addr fetchPCToRealPC(const Addr &addr) - { - return addr; - } - - // the size of "fetched" instructions (not necessarily the size - // of real instructions for PISA) - inline size_t fetchInstSize() - { - return sizeof(MachInst); - } +#include "arch/sparc/regfile.hh" - /** - * Function to insure ISA semantics about 0 registers. - * @param xc The execution context. - */ - template <class XC> +namespace SparcISA +{ - static inline setSyscallReturn(SyscallReturn return_value, RegFile *regs) +#if !FULL_SYSTEM + static inline void setSyscallReturn(SyscallReturn return_value, + RegFile *regs) { // check for error condition. SPARC syscall convention is to // indicate success/failure in reg the carry bit of the ccr // and put the return value itself in the standard return value reg (). if (return_value.successful()) { // no error - regs->miscRegFile.ccrFields.iccFields.c = 0; - regs->intRegFile[ReturnValueReg] = return_value.value(); + regs->setMiscReg(MISCREG_CCR_XCC_C, 0); + regs->setIntReg(ReturnValueReg, return_value.value()); } else { // got an error, return details - regs->miscRegFile.ccrFields.iccFields.c = 1; - regs->intRegFile[ReturnValueReg] = -return_value.value(); + regs->setMiscReg(MISCREG_CCR_XCC_C, 1); + regs->setIntReg(ReturnValueReg, return_value.value()); } } -}; - -#if !FULL_SYSTEM -class SyscallReturn -{ - public: - template <class T> - SyscallReturn(T v, bool s) - { - retval = (uint64_t)v; - success = s; - } - - template <class T> - SyscallReturn(T v) - { - success = (v >= 0); - retval = (uint64_t)v; - } - - ~SyscallReturn() {} - - SyscallReturn& operator=(const SyscallReturn& s) - { - retval = s.retval; - success = s.success; - return *this; - } - - bool successful() { return success; } - uint64_t value() { return retval; } - - private: - uint64_t retval; - bool success; -}; - -#endif - - -#if FULL_SYSTEM - -#include "arch/alpha/ev5.hh" #endif +}; #endif // __ARCH_SPARC_ISA_TRAITS_HH__ diff --git a/arch/sparc/linux/linux.cc b/arch/sparc/linux/linux.cc new file mode 100644 index 000000000..c7ed29358 --- /dev/null +++ b/arch/sparc/linux/linux.cc @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2003-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. + */ + +#include "arch/sparc/linux/linux.hh" + +// open(2) flags translation table +OpenFlagTransTable SparcLinux::openFlagTable[] = { +#ifdef _MSC_VER + { SparcLinux::TGT_O_RDONLY, _O_RDONLY }, + { SparcLinux::TGT_O_WRONLY, _O_WRONLY }, + { SparcLinux::TGT_O_RDWR, _O_RDWR }, + { SparcLinux::TGT_O_APPEND, _O_APPEND }, + { SparcLinux::TGT_O_CREAT, _O_CREAT }, + { SparcLinux::TGT_O_TRUNC, _O_TRUNC }, + { SparcLinux::TGT_O_EXCL, _O_EXCL }, +#ifdef _O_NONBLOCK + { SparcLinux::TGT_O_NONBLOCK, _O_NONBLOCK }, +#endif +#ifdef _O_NOCTTY + { SparcLinux::TGT_O_NOCTTY, _O_NOCTTY }, +#endif +#ifdef _O_SYNC + { SparcLinux::TGT_O_SYNC, _O_SYNC }, +#endif +#else /* !_MSC_VER */ + { SparcLinux::TGT_O_RDONLY, O_RDONLY }, + { SparcLinux::TGT_O_WRONLY, O_WRONLY }, + { SparcLinux::TGT_O_RDWR, O_RDWR }, + { SparcLinux::TGT_O_APPEND, O_APPEND }, + { SparcLinux::TGT_O_CREAT, O_CREAT }, + { SparcLinux::TGT_O_TRUNC, O_TRUNC }, + { SparcLinux::TGT_O_EXCL, O_EXCL }, + { SparcLinux::TGT_O_NONBLOCK, O_NONBLOCK }, + { SparcLinux::TGT_O_NOCTTY, O_NOCTTY }, +#ifdef O_SYNC + { SparcLinux::TGT_O_SYNC, O_SYNC }, +#endif +#endif /* _MSC_VER */ +}; + +const int SparcLinux::NUM_OPEN_FLAGS = + (sizeof(SparcLinux::openFlagTable)/sizeof(SparcLinux::openFlagTable[0])); + diff --git a/arch/sparc/linux/linux.hh b/arch/sparc/linux/linux.hh new file mode 100644 index 000000000..1b31f67b0 --- /dev/null +++ b/arch/sparc/linux/linux.hh @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2003-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. + */ + +#ifndef __MIPS_MIPS_LINUX_HH +#define __MIPS_MIPS_LINUX_HH + +#include "kern/linux/linux.hh" + +class SparcLinux : public Linux +{ + public: + + static OpenFlagTransTable openFlagTable[]; + + static const int TGT_O_RDONLY = 0x00000000; //!< O_RDONLY + static const int TGT_O_WRONLY = 0x00000001; //!< O_WRONLY + static const int TGT_O_RDWR = 0x00000002; //!< O_RDWR + static const int TGT_O_NONBLOCK = 0x00004000; //!< O_NONBLOCK + static const int TGT_O_APPEND = 0x00000008; //!< O_APPEND + static const int TGT_O_CREAT = 0x00000200; //!< O_CREAT + static const int TGT_O_TRUNC = 0x00000400; //!< O_TRUNC + static const int TGT_O_EXCL = 0x00000800; //!< O_EXCL + static const int TGT_O_NOCTTY = 0x00008000; //!< O_NOCTTY + static const int TGT_O_SYNC = 0x00002000; //!< O_SYNC +// static const int TGT_O_DRD = 0x00010000; //!< O_DRD +// static const int TGT_O_DIRECTIO = 0x00020000; //!< O_DIRECTIO +// static const int TGT_O_CACHE = 0x00002000; //!< O_CACHE +// static const int TGT_O_DSYNC = 0x00008000; //!< O_DSYNC +// static const int TGT_O_RSYNC = 0x00040000; //!< O_RSYNC + + static const int NUM_OPEN_FLAGS; + + static const unsigned TGT_MAP_ANONYMOUS = 0x20; +}; + +#endif diff --git a/arch/sparc/linux/process.cc b/arch/sparc/linux/process.cc index fa2a7b9f5..71be6a83a 100644 --- a/arch/sparc/linux/process.cc +++ b/arch/sparc/linux/process.cc @@ -26,14 +26,13 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#include "arch/sparc/common_syscall_emul.hh" -#include "arch/sparc/linux/process.hh" #include "arch/sparc/isa_traits.hh" +#include "arch/sparc/linux/process.hh" +#include "arch/sparc/regfile.hh" #include "base/trace.hh" #include "cpu/exec_context.hh" #include "kern/linux/linux.hh" -#include "mem/functional/functional.hh" #include "sim/process.hh" #include "sim/syscall_emul.hh" @@ -55,318 +54,352 @@ unameFunc(SyscallDesc *desc, int callnum, Process *process, strcpy(name->version, "#1 Mon Aug 18 11:32:15 EDT 2003"); strcpy(name->machine, "sparc"); - name.copyOut(xc->mem); + name.copyOut(xc->getMemPort()); + + return 0; +} + + +SyscallReturn SparcISA::getresuidFunc(SyscallDesc *desc, int num, + Process *p, ExecContext *xc) +{ + const IntReg id = htog(100); + Addr ruid = xc->getSyscallArg(0); + Addr euid = xc->getSyscallArg(1); + Addr suid = xc->getSyscallArg(2); + //Handle the EFAULT case + //Set the ruid + if(ruid) + { + BufferArg ruidBuff(ruid, sizeof(IntReg)); + memcpy(ruidBuff.bufferPtr(), &id, sizeof(IntReg)); + ruidBuff.copyOut(xc->getMemPort()); + } + //Set the euid + if(euid) + { + BufferArg euidBuff(euid, sizeof(IntReg)); + memcpy(euidBuff.bufferPtr(), &id, sizeof(IntReg)); + euidBuff.copyOut(xc->getMemPort()); + } + //Set the suid + if(suid) + { + BufferArg suidBuff(suid, sizeof(IntReg)); + memcpy(suidBuff.bufferPtr(), &id, sizeof(IntReg)); + suidBuff.copyOut(xc->getMemPort()); + } return 0; } SyscallDesc SparcLinuxProcess::syscallDescs[] = { - /* 0 */ SyscallDesc("restart_syscall", unimplementedFunc); - /* 1 */ SyscallDesc("exit", exitFunc); - /* 2 */ SyscallDesc("fork", unimplementedFunc); - /* 3 */ SyscallDesc("read", readFunc); - /* 4 */ SyscallDesc("write", writeFunc); - /* 5 */ SyscallDesc("open", openFunc<Linux>); - /* 6 */ SyscallDesc("close", closeFinc); - /* 7 */ SyscallDesc("wait4", unimplementedFunc); - /* 8 */ SyscallDesc("creat", unimplementedFunc); - /* 9 */ SyscallDesc("link", unimplementedFunc); - /* 10 */ SyscallDesc("unlink", unlinkFunc); - /* 11 */ SyscallDesc("execv", unimplementedFunc); - /* 12 */ SyscallDesc("chdir", unimplementedFunc); - /* 13 */ SyscallDesc("chown", chownFunc); - /* 14 */ SyscallDesc("mknod", unimplementedFunc); - /* 15 */ SyscallDesc("chmod", chmodFunc<Linux>); - /* 16 */ SyscallDesc("lchown", unimplementedFunc); - /* 17 */ SyscallDesc("brk", obreakFunc); - /* 18 */ SyscallDesc("perfctr", unimplementedFunc); - /* 19 */ SyscallDesc("lseek", lseekFunc); - /* 20 */ SyscallDesc("getpid", getpidFunc); - /* 21 */ SyscallDesc("capget", unimplementedFunc); - /* 22 */ SyscallDesc("capset", unimplementedFunc); - /* 23 */ SyscallDesc("setuid", setuidFunc); - /* 24 */ SyscallDesc("getuid", getuidFunc); - /* 25 */ SyscallDesc("time", unimplementedFunc); - /* 26 */ SyscallDesc("ptrace", unimplementedFunc); - /* 27 */ SyscallDesc("alarm", unimplementedFunc); - /* 28 */ SyscallDesc("sigaltstack", unimplementedFunc); - /* 29 */ SyscallDesc("pause", unimplementedFunc); - /* 30 */ SyscallDesc("utime", unimplementedFunc); - /* 31 */ SyscallDesc("lchown32", unimplementedFunc); - /* 32 */ SyscallDesc("fchown32", unimplementedFunc); - /* 33 */ SyscallDesc("access", unimplementedFunc); - /* 34 */ SyscallDesc("nice", unimplementedFunc); - /* 35 */ SyscallDesc("chown32", unimplementedFunc); - /* 36 */ SyscallDesc("sync", unimplementedFunc); - /* 37 */ SyscallDesc("kill", unimplementedFunc); - /* 38 */ SyscallDesc("stat", unimplementedFunc); - /* 39 */ SyscallDesc("sendfile", unimplementedFunc); - /* 40 */ SyscallDesc("lstat", unimplementedFunc); - /* 41 */ SyscallDesc("dup", unimplementedFunc); - /* 42 */ SyscallDesc("pipe", pipePseudoFunc); - /* 43 */ SyscallDesc("times", unimplementedFunc); - /* 44 */ SyscallDesc("getuid32", unimplementedFunc); - /* 45 */ SyscallDesc("umount2", unimplementedFunc); - /* 46 */ SyscallDesc("setgid", unimplementedFunc); - /* 47 */ SyscallDesc("getgid", getgidFunc); - /* 48 */ SyscallDesc("signal", unimplementedFunc); - /* 49 */ SyscallDesc("geteuid", geteuidFunc); - /* 50 */ SyscallDesc("getegid", getegidFunc); - /* 51 */ SyscallDesc("acct", unimplementedFunc); - /* 52 */ SyscallDesc("memory_ordering", unimplementedFunc); - /* 53 */ SyscallDesc("getgid32", unimplementedFunc); - /* 54 */ SyscallDesc("ioctl", unimplementedFunc); - /* 55 */ SyscallDesc("reboot", unimplementedFunc); - /* 56 */ SyscallDesc("mmap2", unimplementedFunc); - /* 57 */ SyscallDesc("symlink", unimplementedFunc); - /* 58 */ SyscallDesc("readlink", unimplementedFunc); - /* 59 */ SyscallDesc("execve", unimplementedFunc); - /* 60 */ SyscallDesc("umask", unimplementedFunc); - /* 61 */ SyscallDesc("chroot", unimplementedFunc); - /* 62 */ SyscallDesc("fstat", unimplementedFunc); - /* 63 */ SyscallDesc("fstat64", unimplementedFunc); - /* 64 */ SyscallDesc("getpagesize", unimplementedFunc); - /* 65 */ SyscallDesc("msync", unimplementedFunc); - /* 66 */ SyscallDesc("vfork", unimplementedFunc); - /* 67 */ SyscallDesc("pread64", unimplementedFunc); - /* 68 */ SyscallDesc("pwrite64", unimplementedFunc); - /* 69 */ SyscallDesc("geteuid32", unimplementedFunc); - /* 70 */ SyscallDesc("getdgid32", unimplementedFunc); - /* 71 */ SyscallDesc("mmap", unimplementedFunc); - /* 72 */ SyscallDesc("setreuid32", unimplementedFunc); - /* 73 */ SyscallDesc("munmap", unimplementedFunc); - /* 74 */ SyscallDesc("mprotect", unimplementedFunc); - /* 75 */ SyscallDesc("madvise", unimplementedFunc); - /* 76 */ SyscallDesc("vhangup", unimplementedFunc); - /* 77 */ SyscallDesc("truncate64", unimplementedFunc); - /* 78 */ SyscallDesc("mincore", unimplementedFunc); - /* 79 */ SyscallDesc("getgroups", unimplementedFunc); - /* 80 */ SyscallDesc("setgroups", unimplementedFunc); - /* 81 */ SyscallDesc("getpgrp", unimplementedFunc); - /* 82 */ SyscallDesc("setgroups32", unimplementedFunc); - /* 83 */ SyscallDesc("setitimer", unimplementedFunc); - /* 84 */ SyscallDesc("ftruncate64", unimplementedFunc); - /* 85 */ SyscallDesc("swapon", unimplementedFunc); - /* 86 */ SyscallDesc("getitimer", unimplementedFunc); - /* 87 */ SyscallDesc("setuid32", unimplementedFunc); - /* 88 */ SyscallDesc("sethostname", unimplementedFunc); - /* 89 */ SyscallDesc("setgid32", unimplementedFunc); - /* 90 */ SyscallDesc("dup2", unimplementedFunc); - /* 91 */ SyscallDesc("setfsuid32", unimplementedFunc); - /* 92 */ SyscallDesc("fcntl", unimplementedFunc); - /* 93 */ SyscallDesc("select", unimplementedFunc); - /* 94 */ SyscallDesc("setfsgid32", unimplementedFunc); - /* 95 */ SyscallDesc("fsync", unimplementedFunc); - /* 96 */ SyscallDesc("setpriority", unimplementedFunc); - /* 97 */ SyscallDesc("socket", unimplementedFunc); - /* 98 */ SyscallDesc("connect", unimplementedFunc); - /* 99 */ SyscallDesc("accept", unimplementedFunc); - /* 100 */ SyscallDesc("getpriority", unimplementedFunc); - /* 101 */ SyscallDesc("rt_sigreturn", unimplementedFunc); - /* 102 */ SyscallDesc("rt_sigaction", unimplementedFunc); - /* 103 */ SyscallDesc("rt_sigprocmask", unimplementedFunc); - /* 104 */ SyscallDesc("rt_sigpending", unimplementedFunc); - /* 105 */ SyscallDesc("rt_sigtimedwait", unimplementedFunc); - /* 106 */ SyscallDesc("rt_sigqueueinfo", unimplementedFunc); - /* 107 */ SyscallDesc("rt_sigsuspend", unimplementedFunc); - /* 108 */ SyscallDesc("setresuid", unimplementedFunc); - /* 109 */ SyscallDesc("getresuid", unimplementedFunc); - /* 110 */ SyscallDesc("setresgid", unimplementedFunc); - /* 111 */ SyscallDesc("getresgid", unimplementedFunc); - /* 112 */ SyscallDesc("setregid32", unimplementedFunc); - /* 113 */ SyscallDesc("recvmsg", unimplementedFunc); - /* 114 */ SyscallDesc("sendmsg", unimplementedFunc); - /* 115 */ SyscallDesc("getgroups32", unimplementedFunc); - /* 116 */ SyscallDesc("gettimeofday", unimplementedFunc); - /* 117 */ SyscallDesc("getrusage", unimplementedFunc); - /* 118 */ SyscallDesc("getsockopt", unimplementedFunc); - /* 119 */ SyscallDesc("getcwd", unimplementedFunc); - /* 120 */ SyscallDesc("readv", unimplementedFunc); - /* 121 */ SyscallDesc("writev", unimplementedFunc); - /* 122 */ SyscallDesc("settimeofday", unimplementedFunc); - /* 123 */ SyscallDesc("fchown", unimplementedFunc); - /* 124 */ SyscallDesc("fchmod", unimplementedFunc); - /* 125 */ SyscallDesc("recvfrom", unimplementedFunc); - /* 126 */ SyscallDesc("setreuid", unimplementedFunc); - /* 127 */ SyscallDesc("setregid", unimplementedFunc); - /* 128 */ SyscallDesc("rename", unimplementedFunc); - /* 129 */ SyscallDesc("truncate", unimplementedFunc); - /* 130 */ SyscallDesc("ftruncate", unimplementedFunc); - /* 131 */ SyscallDesc("flock", unimplementedFunc); - /* 132 */ SyscallDesc("lstat64", unimplementedFunc); - /* 133 */ SyscallDesc("sendto", unimplementedFunc); - /* 134 */ SyscallDesc("shutdown", unimplementedFunc); - /* 135 */ SyscallDesc("socketpair", unimplementedFunc); - /* 136 */ SyscallDesc("mkdir", unimplementedFunc); - /* 137 */ SyscallDesc("rmdir", unimplementedFunc); - /* 138 */ SyscallDesc("utimes", unimplementedFunc); - /* 139 */ SyscallDesc("stat64", unimplementedFunc); - /* 140 */ SyscallDesc("sendfile64", unimplementedFunc); - /* 141 */ SyscallDesc("getpeername", unimplementedFunc); - /* 142 */ SyscallDesc("futex", unimplementedFunc); - /* 143 */ SyscallDesc("gettid", unimplementedFunc); - /* 144 */ SyscallDesc("getrlimit", unimplementedFunc); - /* 145 */ SyscallDesc("setrlimit", unimplementedFunc); - /* 146 */ SyscallDesc("pivot_root", unimplementedFunc); - /* 147 */ SyscallDesc("prctl", unimplementedFunc); - /* 148 */ SyscallDesc("pciconfig_read", unimplementedFunc); - /* 149 */ SyscallDesc("pciconfig_write", unimplementedFunc); - /* 150 */ SyscallDesc("getsockname", unimplementedFunc); - /* 151 */ SyscallDesc("inotify_init", unimplementedFunc); - /* 152 */ SyscallDesc("inotify_add_watch", unimplementedFunc); - /* 153 */ SyscallDesc("poll", unimplementedFunc); - /* 154 */ SyscallDesc("getdents64", unimplementedFunc); - /* 155 */ SyscallDesc("fcntl64", unimplementedFunc); - /* 156 */ SyscallDesc("inotify_rm_watch", unimplementedFunc); - /* 157 */ SyscallDesc("statfs", unimplementedFunc); - /* 158 */ SyscallDesc("fstatfs", unimplementedFunc); - /* 159 */ SyscallDesc("umount", unimplementedFunc); - /* 160 */ SyscallDesc("sched_set_affinity", unimplementedFunc); - /* 161 */ SyscallDesc("sched_get_affinity", unimplementedFunc); - /* 162 */ SyscallDesc("getdomainname", unimplementedFunc); - /* 163 */ SyscallDesc("setdomainname", unimplementedFunc); - /* 164 */ SyscallDesc("utrap_install", unimplementedFunc); - /* 165 */ SyscallDesc("quotactl", unimplementedFunc); - /* 166 */ SyscallDesc("set_tid_address", unimplementedFunc); - /* 167 */ SyscallDesc("mount", unimplementedFunc); - /* 168 */ SyscallDesc("ustat", unimplementedFunc); - /* 169 */ SyscallDesc("setxattr", unimplementedFunc); - /* 170 */ SyscallDesc("lsetxattr", unimplementedFunc); - /* 171 */ SyscallDesc("fsetxattr", unimplementedFunc); - /* 172 */ SyscallDesc("getxattr", unimplementedFunc); - /* 173 */ SyscallDesc("lgetxattr", unimplementedFunc); - /* 174 */ SyscallDesc("getdents", unimplementedFunc); - /* 175 */ SyscallDesc("setsid", unimplementedFunc); - /* 176 */ SyscallDesc("fchdir", unimplementedFunc); - /* 177 */ SyscallDesc("fgetxattr", unimplementedFunc); - /* 178 */ SyscallDesc("listxattr", unimplementedFunc); - /* 179 */ SyscallDesc("llistxattr", unimplementedFunc); - /* 180 */ SyscallDesc("flistxattr", unimplementedFunc); - /* 181 */ SyscallDesc("removexattr", unimplementedFunc); - /* 182 */ SyscallDesc("lremovexattr", unimplementedFunc); - /* 183 */ SyscallDesc("sigpending", unimplementedFunc); - /* 184 */ SyscallDesc("query_module", unimplementedFunc); - /* 185 */ SyscallDesc("setpgid", unimplementedFunc); - /* 186 */ SyscallDesc("fremovexattr", unimplementedFunc); - /* 187 */ SyscallDesc("tkill", unimplementedFunc); - /* 188 */ SyscallDesc("exit_group", unimplementedFunc); - /* 189 */ SyscallDesc("uname", unameFunc); - /* 190 */ SyscallDesc("init_module", unimplementedFunc); - /* 191 */ SyscallDesc("personality", unimplementedFunc); - /* 192 */ SyscallDesc("remap_file_pages", unimplementedFunc); - /* 193 */ SyscallDesc("epoll_create", unimplementedFunc); - /* 194 */ SyscallDesc("epoll_ctl", unimplementedFunc); - /* 195 */ SyscallDesc("epoll_wait", unimplementedFunc); - /* 196 */ SyscallDesc("ioprio_set", unimplementedFunc); - /* 197 */ SyscallDesc("getppid", getppidFunc); - /* 198 */ SyscallDesc("sigaction", unimplementedFunc); - /* 199 */ SyscallDesc("sgetmask", unimplementedFunc); - /* 200 */ SyscallDesc("ssetmask", unimplementedFunc); - /* 201 */ SyscallDesc("sigsuspend", unimplementedFunc); - /* 202 */ SyscallDesc("oldlstat", unimplementedFunc); - /* 203 */ SyscallDesc("uselib", unimplementedFunc); - /* 204 */ SyscallDesc("readdir", unimplementedFunc); - /* 205 */ SyscallDesc("readahead", unimplementedFunc); - /* 206 */ SyscallDesc("socketcall", unimplementedFunc); - /* 207 */ SyscallDesc("syslog", unimplementedFunc); - /* 208 */ SyscallDesc("lookup_dcookie", unimplementedFunc); - /* 209 */ SyscallDesc("fadvise64", unimplementedFunc); - /* 210 */ SyscallDesc("fadvise64_64", unimplementedFunc); - /* 211 */ SyscallDesc("tgkill", unimplementedFunc); - /* 212 */ SyscallDesc("waitpid", unimplementedFunc); - /* 213 */ SyscallDesc("swapoff", unimplementedFunc); - /* 214 */ SyscallDesc("sysinfo", unimplementedFunc); - /* 215 */ SyscallDesc("ipc", unimplementedFunc); - /* 216 */ SyscallDesc("sigreturn", unimplementedFunc); - /* 217 */ SyscallDesc("clone", unimplementedFunc); - /* 218 */ SyscallDesc("ioprio_get", unimplementedFunc); - /* 219 */ SyscallDesc("adjtimex", unimplementedFunc); - /* 220 */ SyscallDesc("sigprocmask", unimplementedFunc); - /* 221 */ SyscallDesc("create_module", unimplementedFunc); - /* 222 */ SyscallDesc("delete_module", unimplementedFunc); - /* 223 */ SyscallDesc("get_kernel_syms", unimplementedFunc); - /* 224 */ SyscallDesc("getpgid", unimplementedFunc); - /* 225 */ SyscallDesc("bdflush", unimplementedFunc); - /* 226 */ SyscallDesc("sysfs", unimplementedFunc); - /* 227 */ SyscallDesc("afs_syscall", unimplementedFunc); - /* 228 */ SyscallDesc("setfsuid", unimplementedFunc); - /* 229 */ SyscallDesc("setfsgid", unimplementedFunc); - /* 230 */ SyscallDesc("_newselect", unimplementedFunc); - /* 231 */ SyscallDesc("time", unimplementedFunc); - /* 232 */ SyscallDesc("oldstat", unimplementedFunc); - /* 233 */ SyscallDesc("stime", unimplementedFunc); - /* 234 */ SyscallDesc("statfs64", unimplementedFunc); - /* 235 */ SyscallDesc("fstatfs64", unimplementedFunc); - /* 236 */ SyscallDesc("_llseek", unimplementedFunc); - /* 237 */ SyscallDesc("mlock", unimplementedFunc); - /* 238 */ SyscallDesc("munlock", unimplementedFunc); - /* 239 */ SyscallDesc("mlockall", unimplementedFunc); - /* 240 */ SyscallDesc("munlockall", unimplementedFunc); - /* 241 */ SyscallDesc("sched_setparam", unimplementedFunc); - /* 242 */ SyscallDesc("sched_getparam", unimplementedFunc); - /* 243 */ SyscallDesc("sched_setscheduler", unimplementedFunc); - /* 244 */ SyscallDesc("sched_getscheduler", unimplementedFunc); - /* 245 */ SyscallDesc("sched_yield", unimplementedFunc); - /* 246 */ SyscallDesc("sched_get_priority_max", unimplimented); - /* 247 */ SyscallDesc("sched_get_priority_min", unimplimented); - /* 248 */ SyscallDesc("sched_rr_get_interval", unimplimented); - /* 249 */ SyscallDesc("nanosleep", unimplementedFunc); - /* 250 */ SyscallDesc("mremap", unimplementedFunc); - /* 251 */ SyscallDesc("_sysctl", unimplementedFunc); - /* 252 */ SyscallDesc("getsid", unimplementedFunc); - /* 253 */ SyscallDesc("fdatasync", unimplementedFunc); - /* 254 */ SyscallDesc("nfsservctl", unimplementedFunc); - /* 255 */ SyscallDesc("aplib", unimplementedFunc); - /* 256 */ SyscallDesc("clock_settime", unimplementedFunc); - /* 257 */ SyscallDesc("clock_gettime", unimplementedFunc); - /* 258 */ SyscallDesc("clock_getres", unimplementedFunc); - /* 259 */ SyscallDesc("clock_nanosleep", unimplementedFunc); - /* 260 */ SyscallDesc("sched_getaffinity", unimplementedFunc); - /* 261 */ SyscallDesc("sched_setaffinity", unimplementedFunc); - /* 262 */ SyscallDesc("timer_settime", unimplementedFunc); - /* 263 */ SyscallDesc("timer_gettime", unimplementedFunc); - /* 264 */ SyscallDesc("timer_getoverrun", unimplementedFunc); - /* 265 */ SyscallDesc("timer_delete", unimplementedFunc); - /* 266 */ SyscallDesc("timer_create", unimplementedFunc); - /* 267 */ SyscallDesc("vserver", unimplementedFunc); - /* 268 */ SyscallDesc("io_setup", unimplementedFunc); - /* 269 */ SyscallDesc("io_destroy", unimplementedFunc); - /* 270 */ SyscallDesc("io_submit", unimplementedFunc); - /* 271 */ SyscallDesc("io_cancel", unimplementedFunc); - /* 272 */ SyscallDesc("io_getevents", unimplementedFunc); - /* 273 */ SyscallDesc("mq_open", unimplementedFunc); - /* 274 */ SyscallDesc("mq_unlink", unimplementedFunc); - /* 275 */ SyscallDesc("mq_timedsend", unimplementedFunc); - /* 276 */ SyscallDesc("mq_timedreceive", unimplementedFunc); - /* 277 */ SyscallDesc("mq_notify", unimplementedFunc); - /* 278 */ SyscallDesc("mq_getsetattr", unimplementedFunc); - /* 279 */ SyscallDesc("waitid", unimplementedFunc); - /* 280 */ SyscallDesc("sys_setaltroot", unimplementedFunc); - /* 281 */ SyscallDesc("add_key", unimplementedFunc); - /* 282 */ SyscallDesc("request_key", unimplementedFunc); - /* 283 */ SyscallDesc("keyctl", unimplementedFunc); + /* 0 */ SyscallDesc("restart_syscall", unimplementedFunc), + /* 1 */ SyscallDesc("exit", exitFunc), + /* 2 */ SyscallDesc("fork", unimplementedFunc), + /* 3 */ SyscallDesc("read", readFunc), + /* 4 */ SyscallDesc("write", writeFunc), + /* 5 */ SyscallDesc("open", openFunc<SparcLinux>), + /* 6 */ SyscallDesc("close", closeFunc), + /* 7 */ SyscallDesc("wait4", unimplementedFunc), + /* 8 */ SyscallDesc("creat", unimplementedFunc), + /* 9 */ SyscallDesc("link", unimplementedFunc), + /* 10 */ SyscallDesc("unlink", unlinkFunc), + /* 11 */ SyscallDesc("execv", unimplementedFunc), + /* 12 */ SyscallDesc("chdir", unimplementedFunc), + /* 13 */ SyscallDesc("chown", chownFunc), + /* 14 */ SyscallDesc("mknod", unimplementedFunc), + /* 15 */ SyscallDesc("chmod", chmodFunc<Linux>), + /* 16 */ SyscallDesc("lchown", unimplementedFunc), + /* 17 */ SyscallDesc("brk", obreakFunc), + /* 18 */ SyscallDesc("perfctr", unimplementedFunc), + /* 19 */ SyscallDesc("lseek", lseekFunc), + /* 20 */ SyscallDesc("getpid", getpidFunc), + /* 21 */ SyscallDesc("capget", unimplementedFunc), + /* 22 */ SyscallDesc("capset", unimplementedFunc), + /* 23 */ SyscallDesc("setuid", setuidFunc), + /* 24 */ SyscallDesc("getuid", getuidFunc), + /* 25 */ SyscallDesc("time", unimplementedFunc), + /* 26 */ SyscallDesc("ptrace", unimplementedFunc), + /* 27 */ SyscallDesc("alarm", unimplementedFunc), + /* 28 */ SyscallDesc("sigaltstack", unimplementedFunc), + /* 29 */ SyscallDesc("pause", unimplementedFunc), + /* 30 */ SyscallDesc("utime", unimplementedFunc), + /* 31 */ SyscallDesc("lchown32", unimplementedFunc), + /* 32 */ SyscallDesc("fchown32", unimplementedFunc), + /* 33 */ SyscallDesc("access", unimplementedFunc), + /* 34 */ SyscallDesc("nice", unimplementedFunc), + /* 35 */ SyscallDesc("chown32", unimplementedFunc), + /* 36 */ SyscallDesc("sync", unimplementedFunc), + /* 37 */ SyscallDesc("kill", unimplementedFunc), + /* 38 */ SyscallDesc("stat", unimplementedFunc), + /* 39 */ SyscallDesc("sendfile", unimplementedFunc), + /* 40 */ SyscallDesc("lstat", unimplementedFunc), + /* 41 */ SyscallDesc("dup", unimplementedFunc), + /* 42 */ SyscallDesc("pipe", pipePseudoFunc), + /* 43 */ SyscallDesc("times", unimplementedFunc), + /* 44 */ SyscallDesc("getuid32", unimplementedFunc), + /* 45 */ SyscallDesc("umount2", unimplementedFunc), + /* 46 */ SyscallDesc("setgid", unimplementedFunc), + /* 47 */ SyscallDesc("getgid", getgidFunc), + /* 48 */ SyscallDesc("signal", unimplementedFunc), + /* 49 */ SyscallDesc("geteuid", geteuidFunc), + /* 50 */ SyscallDesc("getegid", getegidFunc), + /* 51 */ SyscallDesc("acct", unimplementedFunc), + /* 52 */ SyscallDesc("memory_ordering", unimplementedFunc), + /* 53 */ SyscallDesc("getgid32", unimplementedFunc), + /* 54 */ SyscallDesc("ioctl", unimplementedFunc), + /* 55 */ SyscallDesc("reboot", unimplementedFunc), + /* 56 */ SyscallDesc("mmap2", unimplementedFunc), + /* 57 */ SyscallDesc("symlink", unimplementedFunc), + /* 58 */ SyscallDesc("readlink", unimplementedFunc), + /* 59 */ SyscallDesc("execve", unimplementedFunc), + /* 60 */ SyscallDesc("umask", unimplementedFunc), + /* 61 */ SyscallDesc("chroot", unimplementedFunc), + /* 62 */ SyscallDesc("fstat", fstatFunc<SparcLinux>), + /* 63 */ SyscallDesc("fstat64", unimplementedFunc), + /* 64 */ SyscallDesc("getpagesize", unimplementedFunc), + /* 65 */ SyscallDesc("msync", unimplementedFunc), + /* 66 */ SyscallDesc("vfork", unimplementedFunc), + /* 67 */ SyscallDesc("pread64", unimplementedFunc), + /* 68 */ SyscallDesc("pwrite64", unimplementedFunc), + /* 69 */ SyscallDesc("geteuid32", unimplementedFunc), + /* 70 */ SyscallDesc("getdgid32", unimplementedFunc), + /* 71 */ SyscallDesc("mmap", mmapFunc<SparcLinux>), + /* 72 */ SyscallDesc("setreuid32", unimplementedFunc), + /* 73 */ SyscallDesc("munmap", munmapFunc), + /* 74 */ SyscallDesc("mprotect", unimplementedFunc), + /* 75 */ SyscallDesc("madvise", unimplementedFunc), + /* 76 */ SyscallDesc("vhangup", unimplementedFunc), + /* 77 */ SyscallDesc("truncate64", unimplementedFunc), + /* 78 */ SyscallDesc("mincore", unimplementedFunc), + /* 79 */ SyscallDesc("getgroups", unimplementedFunc), + /* 80 */ SyscallDesc("setgroups", unimplementedFunc), + /* 81 */ SyscallDesc("getpgrp", unimplementedFunc), + /* 82 */ SyscallDesc("setgroups32", unimplementedFunc), + /* 83 */ SyscallDesc("setitimer", unimplementedFunc), + /* 84 */ SyscallDesc("ftruncate64", unimplementedFunc), + /* 85 */ SyscallDesc("swapon", unimplementedFunc), + /* 86 */ SyscallDesc("getitimer", unimplementedFunc), + /* 87 */ SyscallDesc("setuid32", unimplementedFunc), + /* 88 */ SyscallDesc("sethostname", unimplementedFunc), + /* 89 */ SyscallDesc("setgid32", unimplementedFunc), + /* 90 */ SyscallDesc("dup2", unimplementedFunc), + /* 91 */ SyscallDesc("setfsuid32", unimplementedFunc), + /* 92 */ SyscallDesc("fcntl", unimplementedFunc), + /* 93 */ SyscallDesc("select", unimplementedFunc), + /* 94 */ SyscallDesc("setfsgid32", unimplementedFunc), + /* 95 */ SyscallDesc("fsync", unimplementedFunc), + /* 96 */ SyscallDesc("setpriority", unimplementedFunc), + /* 97 */ SyscallDesc("socket", unimplementedFunc), + /* 98 */ SyscallDesc("connect", unimplementedFunc), + /* 99 */ SyscallDesc("accept", unimplementedFunc), + /* 100 */ SyscallDesc("getpriority", unimplementedFunc), + /* 101 */ SyscallDesc("rt_sigreturn", unimplementedFunc), + /* 102 */ SyscallDesc("rt_sigaction", unimplementedFunc), + /* 103 */ SyscallDesc("rt_sigprocmask", unimplementedFunc), + /* 104 */ SyscallDesc("rt_sigpending", unimplementedFunc), + /* 105 */ SyscallDesc("rt_sigtimedwait", unimplementedFunc), + /* 106 */ SyscallDesc("rt_sigqueueinfo", unimplementedFunc), + /* 107 */ SyscallDesc("rt_sigsuspend", unimplementedFunc), + /* 108 */ SyscallDesc("setresuid", unimplementedFunc), + /* 109 */ SyscallDesc("getresuid", getresuidFunc), + /* 110 */ SyscallDesc("setresgid", unimplementedFunc), + /* 111 */ SyscallDesc("getresgid", unimplementedFunc), + /* 112 */ SyscallDesc("setregid32", unimplementedFunc), + /* 113 */ SyscallDesc("recvmsg", unimplementedFunc), + /* 114 */ SyscallDesc("sendmsg", unimplementedFunc), + /* 115 */ SyscallDesc("getgroups32", unimplementedFunc), + /* 116 */ SyscallDesc("gettimeofday", unimplementedFunc), + /* 117 */ SyscallDesc("getrusage", unimplementedFunc), + /* 118 */ SyscallDesc("getsockopt", unimplementedFunc), + /* 119 */ SyscallDesc("getcwd", unimplementedFunc), + /* 120 */ SyscallDesc("readv", unimplementedFunc), + /* 121 */ SyscallDesc("writev", unimplementedFunc), + /* 122 */ SyscallDesc("settimeofday", unimplementedFunc), + /* 123 */ SyscallDesc("fchown", unimplementedFunc), + /* 124 */ SyscallDesc("fchmod", unimplementedFunc), + /* 125 */ SyscallDesc("recvfrom", unimplementedFunc), + /* 126 */ SyscallDesc("setreuid", unimplementedFunc), + /* 127 */ SyscallDesc("setregid", unimplementedFunc), + /* 128 */ SyscallDesc("rename", unimplementedFunc), + /* 129 */ SyscallDesc("truncate", unimplementedFunc), + /* 130 */ SyscallDesc("ftruncate", unimplementedFunc), + /* 131 */ SyscallDesc("flock", unimplementedFunc), + /* 132 */ SyscallDesc("lstat64", unimplementedFunc), + /* 133 */ SyscallDesc("sendto", unimplementedFunc), + /* 134 */ SyscallDesc("shutdown", unimplementedFunc), + /* 135 */ SyscallDesc("socketpair", unimplementedFunc), + /* 136 */ SyscallDesc("mkdir", unimplementedFunc), + /* 137 */ SyscallDesc("rmdir", unimplementedFunc), + /* 138 */ SyscallDesc("utimes", unimplementedFunc), + /* 139 */ SyscallDesc("stat64", unimplementedFunc), + /* 140 */ SyscallDesc("sendfile64", unimplementedFunc), + /* 141 */ SyscallDesc("getpeername", unimplementedFunc), + /* 142 */ SyscallDesc("futex", unimplementedFunc), + /* 143 */ SyscallDesc("gettid", unimplementedFunc), + /* 144 */ SyscallDesc("getrlimit", unimplementedFunc), + /* 145 */ SyscallDesc("setrlimit", unimplementedFunc), + /* 146 */ SyscallDesc("pivot_root", unimplementedFunc), + /* 147 */ SyscallDesc("prctl", unimplementedFunc), + /* 148 */ SyscallDesc("pciconfig_read", unimplementedFunc), + /* 149 */ SyscallDesc("pciconfig_write", unimplementedFunc), + /* 150 */ SyscallDesc("getsockname", unimplementedFunc), + /* 151 */ SyscallDesc("inotify_init", unimplementedFunc), + /* 152 */ SyscallDesc("inotify_add_watch", unimplementedFunc), + /* 153 */ SyscallDesc("poll", unimplementedFunc), + /* 154 */ SyscallDesc("getdents64", unimplementedFunc), + /* 155 */ SyscallDesc("fcntl64", unimplementedFunc), + /* 156 */ SyscallDesc("inotify_rm_watch", unimplementedFunc), + /* 157 */ SyscallDesc("statfs", unimplementedFunc), + /* 158 */ SyscallDesc("fstatfs", unimplementedFunc), + /* 159 */ SyscallDesc("umount", unimplementedFunc), + /* 160 */ SyscallDesc("sched_set_affinity", unimplementedFunc), + /* 161 */ SyscallDesc("sched_get_affinity", unimplementedFunc), + /* 162 */ SyscallDesc("getdomainname", unimplementedFunc), + /* 163 */ SyscallDesc("setdomainname", unimplementedFunc), + /* 164 */ SyscallDesc("utrap_install", unimplementedFunc), + /* 165 */ SyscallDesc("quotactl", unimplementedFunc), + /* 166 */ SyscallDesc("set_tid_address", unimplementedFunc), + /* 167 */ SyscallDesc("mount", unimplementedFunc), + /* 168 */ SyscallDesc("ustat", unimplementedFunc), + /* 169 */ SyscallDesc("setxattr", unimplementedFunc), + /* 170 */ SyscallDesc("lsetxattr", unimplementedFunc), + /* 171 */ SyscallDesc("fsetxattr", unimplementedFunc), + /* 172 */ SyscallDesc("getxattr", unimplementedFunc), + /* 173 */ SyscallDesc("lgetxattr", unimplementedFunc), + /* 174 */ SyscallDesc("getdents", unimplementedFunc), + /* 175 */ SyscallDesc("setsid", unimplementedFunc), + /* 176 */ SyscallDesc("fchdir", unimplementedFunc), + /* 177 */ SyscallDesc("fgetxattr", unimplementedFunc), + /* 178 */ SyscallDesc("listxattr", unimplementedFunc), + /* 179 */ SyscallDesc("llistxattr", unimplementedFunc), + /* 180 */ SyscallDesc("flistxattr", unimplementedFunc), + /* 181 */ SyscallDesc("removexattr", unimplementedFunc), + /* 182 */ SyscallDesc("lremovexattr", unimplementedFunc), + /* 183 */ SyscallDesc("sigpending", unimplementedFunc), + /* 184 */ SyscallDesc("query_module", unimplementedFunc), + /* 185 */ SyscallDesc("setpgid", unimplementedFunc), + /* 186 */ SyscallDesc("fremovexattr", unimplementedFunc), + /* 187 */ SyscallDesc("tkill", unimplementedFunc), + /* 188 */ SyscallDesc("exit_group", exitFunc), + /* 189 */ SyscallDesc("uname", unameFunc), + /* 190 */ SyscallDesc("init_module", unimplementedFunc), + /* 191 */ SyscallDesc("personality", unimplementedFunc), + /* 192 */ SyscallDesc("remap_file_pages", unimplementedFunc), + /* 193 */ SyscallDesc("epoll_create", unimplementedFunc), + /* 194 */ SyscallDesc("epoll_ctl", unimplementedFunc), + /* 195 */ SyscallDesc("epoll_wait", unimplementedFunc), + /* 196 */ SyscallDesc("ioprio_set", unimplementedFunc), + /* 197 */ SyscallDesc("getppid", getppidFunc), + /* 198 */ SyscallDesc("sigaction", unimplementedFunc), + /* 199 */ SyscallDesc("sgetmask", unimplementedFunc), + /* 200 */ SyscallDesc("ssetmask", unimplementedFunc), + /* 201 */ SyscallDesc("sigsuspend", unimplementedFunc), + /* 202 */ SyscallDesc("oldlstat", unimplementedFunc), + /* 203 */ SyscallDesc("uselib", unimplementedFunc), + /* 204 */ SyscallDesc("readdir", unimplementedFunc), + /* 205 */ SyscallDesc("readahead", unimplementedFunc), + /* 206 */ SyscallDesc("socketcall", unimplementedFunc), + /* 207 */ SyscallDesc("syslog", unimplementedFunc), + /* 208 */ SyscallDesc("lookup_dcookie", unimplementedFunc), + /* 209 */ SyscallDesc("fadvise64", unimplementedFunc), + /* 210 */ SyscallDesc("fadvise64_64", unimplementedFunc), + /* 211 */ SyscallDesc("tgkill", unimplementedFunc), + /* 212 */ SyscallDesc("waitpid", unimplementedFunc), + /* 213 */ SyscallDesc("swapoff", unimplementedFunc), + /* 214 */ SyscallDesc("sysinfo", unimplementedFunc), + /* 215 */ SyscallDesc("ipc", unimplementedFunc), + /* 216 */ SyscallDesc("sigreturn", unimplementedFunc), + /* 217 */ SyscallDesc("clone", unimplementedFunc), + /* 218 */ SyscallDesc("ioprio_get", unimplementedFunc), + /* 219 */ SyscallDesc("adjtimex", unimplementedFunc), + /* 220 */ SyscallDesc("sigprocmask", unimplementedFunc), + /* 221 */ SyscallDesc("create_module", unimplementedFunc), + /* 222 */ SyscallDesc("delete_module", unimplementedFunc), + /* 223 */ SyscallDesc("get_kernel_syms", unimplementedFunc), + /* 224 */ SyscallDesc("getpgid", unimplementedFunc), + /* 225 */ SyscallDesc("bdflush", unimplementedFunc), + /* 226 */ SyscallDesc("sysfs", unimplementedFunc), + /* 227 */ SyscallDesc("afs_syscall", unimplementedFunc), + /* 228 */ SyscallDesc("setfsuid", unimplementedFunc), + /* 229 */ SyscallDesc("setfsgid", unimplementedFunc), + /* 230 */ SyscallDesc("_newselect", unimplementedFunc), + /* 231 */ SyscallDesc("time", unimplementedFunc), + /* 232 */ SyscallDesc("oldstat", unimplementedFunc), + /* 233 */ SyscallDesc("stime", unimplementedFunc), + /* 234 */ SyscallDesc("statfs64", unimplementedFunc), + /* 235 */ SyscallDesc("fstatfs64", unimplementedFunc), + /* 236 */ SyscallDesc("_llseek", unimplementedFunc), + /* 237 */ SyscallDesc("mlock", unimplementedFunc), + /* 238 */ SyscallDesc("munlock", unimplementedFunc), + /* 239 */ SyscallDesc("mlockall", unimplementedFunc), + /* 240 */ SyscallDesc("munlockall", unimplementedFunc), + /* 241 */ SyscallDesc("sched_setparam", unimplementedFunc), + /* 242 */ SyscallDesc("sched_getparam", unimplementedFunc), + /* 243 */ SyscallDesc("sched_setscheduler", unimplementedFunc), + /* 244 */ SyscallDesc("sched_getscheduler", unimplementedFunc), + /* 245 */ SyscallDesc("sched_yield", unimplementedFunc), + /* 246 */ SyscallDesc("sched_get_priority_max", unimplementedFunc), + /* 247 */ SyscallDesc("sched_get_priority_min", unimplementedFunc), + /* 248 */ SyscallDesc("sched_rr_get_interval", unimplementedFunc), + /* 249 */ SyscallDesc("nanosleep", unimplementedFunc), + /* 250 */ SyscallDesc("mremap", unimplementedFunc), + /* 251 */ SyscallDesc("_sysctl", unimplementedFunc), + /* 252 */ SyscallDesc("getsid", unimplementedFunc), + /* 253 */ SyscallDesc("fdatasync", unimplementedFunc), + /* 254 */ SyscallDesc("nfsservctl", unimplementedFunc), + /* 255 */ SyscallDesc("aplib", unimplementedFunc), + /* 256 */ SyscallDesc("clock_settime", unimplementedFunc), + /* 257 */ SyscallDesc("clock_gettime", unimplementedFunc), + /* 258 */ SyscallDesc("clock_getres", unimplementedFunc), + /* 259 */ SyscallDesc("clock_nanosleep", unimplementedFunc), + /* 260 */ SyscallDesc("sched_getaffinity", unimplementedFunc), + /* 261 */ SyscallDesc("sched_setaffinity", unimplementedFunc), + /* 262 */ SyscallDesc("timer_settime", unimplementedFunc), + /* 263 */ SyscallDesc("timer_gettime", unimplementedFunc), + /* 264 */ SyscallDesc("timer_getoverrun", unimplementedFunc), + /* 265 */ SyscallDesc("timer_delete", unimplementedFunc), + /* 266 */ SyscallDesc("timer_create", unimplementedFunc), + /* 267 */ SyscallDesc("vserver", unimplementedFunc), + /* 268 */ SyscallDesc("io_setup", unimplementedFunc), + /* 269 */ SyscallDesc("io_destroy", unimplementedFunc), + /* 270 */ SyscallDesc("io_submit", unimplementedFunc), + /* 271 */ SyscallDesc("io_cancel", unimplementedFunc), + /* 272 */ SyscallDesc("io_getevents", unimplementedFunc), + /* 273 */ SyscallDesc("mq_open", unimplementedFunc), + /* 274 */ SyscallDesc("mq_unlink", unimplementedFunc), + /* 275 */ SyscallDesc("mq_timedsend", unimplementedFunc), + /* 276 */ SyscallDesc("mq_timedreceive", unimplementedFunc), + /* 277 */ SyscallDesc("mq_notify", unimplementedFunc), + /* 278 */ SyscallDesc("mq_getsetattr", unimplementedFunc), + /* 279 */ SyscallDesc("waitid", unimplementedFunc), + /* 280 */ SyscallDesc("sys_setaltroot", unimplementedFunc), + /* 281 */ SyscallDesc("add_key", unimplementedFunc), + /* 282 */ SyscallDesc("request_key", unimplementedFunc), + /* 283 */ SyscallDesc("keyctl", unimplementedFunc) }; SparcLinuxProcess::SparcLinuxProcess(const std::string &name, ObjectFile *objFile, + System * system, int stdin_fd, int stdout_fd, int stderr_fd, std::vector<std::string> &argv, std::vector<std::string> &envp) - : LiveProcess(name, objFile, stdin_fd, stdout_fd, stderr_fd, argv, envp), + : SparcLiveProcess(name, objFile, system, + stdin_fd, stdout_fd, stderr_fd, argv, envp), Num_Syscall_Descs(sizeof(syscallDescs) / sizeof(SyscallDesc)) { - // The sparc syscall table must be <= 283 entries because that is all there + // The sparc syscall table must be <= 284 entries because that is all there // is space for. - assert(Num_Syscall_Descs <= 283); - - init_regs->intRegFile[0] = 0; + assert(Num_Syscall_Descs <= 284); } SyscallDesc* -AlphaLinuxProcess::getDesc(int callnum) +SparcLinuxProcess::getDesc(int callnum) { if (callnum < 0 || callnum > Num_Syscall_Descs) return NULL; diff --git a/arch/sparc/linux/process.hh b/arch/sparc/linux/process.hh index c41406b4b..23ce66d02 100644 --- a/arch/sparc/linux/process.hh +++ b/arch/sparc/linux/process.hh @@ -29,16 +29,20 @@ #ifndef __SPARC_LINUX_PROCESS_HH__ #define __SPARC_LINUX_PROCESS_HH__ +#include "arch/sparc/linux/linux.hh" +#include "arch/sparc/process.hh" #include "sim/process.hh" +namespace SparcISA { /// A process with emulated SPARC/Linux syscalls. -class SparcLinuxProcess : public LiveProcess +class SparcLinuxProcess : public SparcLiveProcess { public: /// Constructor. SparcLinuxProcess(const std::string &name, ObjectFile *objFile, + System * system, int stdin_fd, int stdout_fd, int stderr_fd, std::vector<std::string> &argv, std::vector<std::string> &envp); @@ -54,5 +58,8 @@ class SparcLinuxProcess : public LiveProcess const int Num_Syscall_Descs; }; +SyscallReturn getresuidFunc(SyscallDesc *desc, int num, + Process *p, ExecContext *xc); +} // namespace SparcISA #endif // __ALPHA_LINUX_PROCESS_HH__ diff --git a/arch/sparc/process.cc b/arch/sparc/process.cc index 53a215379..7f2b0d40a 100644 --- a/arch/sparc/process.cc +++ b/arch/sparc/process.cc @@ -26,22 +26,38 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +#include "arch/sparc/isa_traits.hh" #include "arch/sparc/process.hh" +#include "arch/sparc/linux/process.hh" +#include "base/loader/object_file.hh" +#include "base/misc.hh" +#include "cpu/exec_context.hh" +#include "mem/page_table.hh" +#include "mem/translating_port.hh" +#include "sim/builder.hh" +#include "sim/system.hh" -namespace SparcISA -{ +using namespace std; +using namespace SparcISA; -LiveProcess * -createProcess(const string &nm, ObjectFile * objFile, - int stdin_fd, int stdout_fd, int stderr_fd, - vector<string> &argv, vector<string> &envp) +SparcLiveProcess * +SparcLiveProcess::create(const std::string &nm, System *system, int stdin_fd, + int stdout_fd, int stderr_fd, std::string executable, + std::vector<std::string> &argv, std::vector<std::string> &envp) { - LiveProcess * process = NULL; + SparcLiveProcess *process = NULL; + + ObjectFile *objFile = createObjectFile(executable); + if (objFile == NULL) { + fatal("Can't load object file %s", executable); + } + + if (objFile->getArch() != ObjectFile::SPARC) - fatal("Object file does not match architecture."); + fatal("Object file with arch %x does not match architecture %x.", objFile->getArch(), ObjectFile::SPARC); switch (objFile->getOpSys()) { case ObjectFile::Linux: - process = new SparcLinuxProcess(nm, objFile, + process = new SparcLinuxProcess(nm, objFile, system, stdin_fd, stdout_fd, stderr_fd, argv, envp); break; @@ -50,7 +66,316 @@ createProcess(const string &nm, ObjectFile * objFile, default: fatal("Unknown/unsupported operating system."); } + + if (process == NULL) + fatal("Unknown error creating process object."); return process; } -} // namespace SparcISA +SparcLiveProcess::SparcLiveProcess(const std::string &nm, ObjectFile *objFile, + System *_system, int stdin_fd, int stdout_fd, int stderr_fd, + std::vector<std::string> &argv, std::vector<std::string> &envp) + : LiveProcess(nm, objFile, _system, stdin_fd, stdout_fd, stderr_fd, + argv, envp) +{ + + // XXX all the below need to be updated for SPARC - Ali + brk_point = objFile->dataBase() + objFile->dataSize() + objFile->bssSize(); + brk_point = roundUp(brk_point, VMPageSize); + + // Set up stack. On SPARC Linux, stack goes from the top of memory + // downward, less the hole for the kernel address space. + stack_base = ((Addr)0x80000000000ULL); + + // Set up region for mmaps. Tru64 seems to start just above 0 and + // grow up from there. + mmap_start = mmap_end = 0x800000; + + // Set pointer for next thread stack. Reserve 8M for main stack. + next_thread_stack_base = stack_base - (8 * 1024 * 1024); +} + +void +SparcLiveProcess::startup() +{ + argsInit(MachineBytes, VMPageSize); + + //From the SPARC ABI + + //The process runs in user mode + execContexts[0]->setMiscRegWithEffect(MISCREG_PSTATE_PRIV, 0); + //Interrupts are enabled + execContexts[0]->setMiscRegWithEffect(MISCREG_PSTATE_IE, 1); + //Round to nearest + execContexts[0]->setMiscRegWithEffect(MISCREG_FSR_RD, 0); + //Floating point traps are not enabled + execContexts[0]->setMiscRegWithEffect(MISCREG_FSR_TEM, 0); + //Turn non standard mode off + execContexts[0]->setMiscRegWithEffect(MISCREG_FSR_NS, 0); + //The floating point queue is empty + execContexts[0]->setMiscRegWithEffect(MISCREG_FSR_QNE, 0); + //There are no accrued eexecContext[0]eptions + execContexts[0]->setMiscRegWithEffect(MISCREG_FSR_AEXC, 0); + //There are no current eexecContext[0]eptions + execContexts[0]->setMiscRegWithEffect(MISCREG_FSR_CEXC, 0); + + /* + * Register window management registers + */ + + //No windows contain info from other programs + execContexts[0]->setMiscRegWithEffect(MISCREG_OTHERWIN, 0); + //There are no windows to pop + execContexts[0]->setMiscRegWithEffect(MISCREG_CANRESTORE, 0); + //All windows are available to save into + execContexts[0]->setMiscRegWithEffect(MISCREG_CANSAVE, NWindows - 2); + //All windows are "clean" + execContexts[0]->setMiscRegWithEffect(MISCREG_CLEANWIN, NWindows); + //Start with register window 0 + execContexts[0]->setMiscRegWithEffect(MISCREG_CWP, 0); +} + +m5_auxv_t buildAuxVect(int64_t type, int64_t val) +{ + m5_auxv_t result; + result.a_type = TheISA::htog(type); + result.a_val = TheISA::htog(val); + return result; +} + +void +SparcLiveProcess::argsInit(int intSize, int pageSize) +{ + Process::startup(); + + Addr alignmentMask = ~(intSize - 1); + + // load object file into target memory + objFile->loadSections(initVirtMem); + + //These are the auxilliary vector types + enum auxTypes + { + SPARC_AT_HWCAP = 16, + SPARC_AT_PAGESZ = 6, + SPARC_AT_CLKTCK = 17, + SPARC_AT_PHDR = 3, + SPARC_AT_PHENT = 4, + SPARC_AT_PHNUM = 5, + SPARC_AT_BASE = 7, + SPARC_AT_FLAGS = 8, + SPARC_AT_ENTRY = 9, + SPARC_AT_UID = 11, + SPARC_AT_EUID = 12, + SPARC_AT_GID = 13, + SPARC_AT_EGID = 14 + }; + + enum hardwareCaps + { + M5_HWCAP_SPARC_FLUSH = 1, + M5_HWCAP_SPARC_STBAR = 2, + M5_HWCAP_SPARC_SWAP = 4, + M5_HWCAP_SPARC_MULDIV = 8, + M5_HWCAP_SPARC_V9 = 16, + //This one should technically only be set + //if there is a cheetah or cheetah_plus tlb, + //but we'll use it all the time + M5_HWCAP_SPARC_ULTRA3 = 32 + }; + + const int64_t hwcap = + M5_HWCAP_SPARC_FLUSH | + M5_HWCAP_SPARC_STBAR | + M5_HWCAP_SPARC_SWAP | + M5_HWCAP_SPARC_MULDIV | + M5_HWCAP_SPARC_V9 | + M5_HWCAP_SPARC_ULTRA3; + + //Setup the auxilliary vectors. These will already have + //endian conversion. + auxv.push_back(buildAuxVect(SPARC_AT_EGID, 100)); + auxv.push_back(buildAuxVect(SPARC_AT_GID, 100)); + auxv.push_back(buildAuxVect(SPARC_AT_EUID, 100)); + auxv.push_back(buildAuxVect(SPARC_AT_UID, 100)); + //This would work, but the entry point is a protected member + //auxv.push_back(buildAuxVect(SPARC_AT_ENTRY, objFile->entry)); + auxv.push_back(buildAuxVect(SPARC_AT_FLAGS, 0)); + //This is the address of the elf "interpreter", which I don't + //think we currently set up. It should be set to 0 (I think) + //auxv.push_back(buildAuxVect(SPARC_AT_BASE, 0)); + //This is the number of headers which were in the original elf + //file. This information isn't avaibale by this point. + //auxv.push_back(buildAuxVect(SPARC_AT_PHNUM, 3)); + //This is the size of a program header entry. This isn't easy + //to compute here. + //auxv.push_back(buildAuxVect(SPARC_AT_PHENT, blah)); + //This is should be set to load_addr (whatever that is) + + //e_phoff. I think it's a pointer to the program headers. + //auxv.push_back(buildAuxVect(SPARC_AT_PHDR, blah)); + //This should be easy to get right, but I won't set it for now + //auxv.push_back(buildAuxVect(SPARC_AT_CLKTCK, blah)); + auxv.push_back(buildAuxVect(SPARC_AT_PAGESZ, SparcISA::VMPageSize)); + auxv.push_back(buildAuxVect(SPARC_AT_HWCAP, hwcap)); + + //Figure out how big the initial stack needs to be + + //Each auxilliary vector is two 8 byte words + int aux_data_size = 2 * intSize * auxv.size(); + 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 aux_array_size = intSize * 2 * (auxv.size() + 1); + + int argv_array_size = intSize * (argv.size() + 1); + int envp_array_size = intSize * (envp.size() + 1); + + int argc_size = intSize; + int window_save_size = intSize * 16; + + int info_block_size = + (aux_data_size + + env_data_size + + arg_data_size + + ~alignmentMask) & alignmentMask; + + int info_block_padding = + info_block_size - + aux_data_size - + env_data_size - + arg_data_size; + + int space_needed = + info_block_size + + aux_array_size + + envp_array_size + + argv_array_size + + argc_size + + window_save_size; + + stack_min = stack_base - space_needed; + stack_min &= alignmentMask; + stack_size = stack_base - stack_min; + + // map memory + pTable->allocate(roundDown(stack_min, pageSize), + roundUp(stack_size, pageSize)); + + // map out initial stack contents + Addr aux_data_base = stack_base - aux_data_size - info_block_padding; + Addr env_data_base = aux_data_base - env_data_size; + Addr arg_data_base = env_data_base - arg_data_size; + Addr auxv_array_base = arg_data_base - aux_array_size; + Addr envp_array_base = auxv_array_base - envp_array_size; + Addr argv_array_base = envp_array_base - argv_array_size; + Addr argc_base = argv_array_base - argc_size; + Addr window_save_base = argc_base - window_save_size; + + DPRINTF(Sparc, "The addresses of items on the initial stack:\n"); + DPRINTF(Sparc, "0x%x - aux data\n", aux_data_base); + DPRINTF(Sparc, "0x%x - env data\n", env_data_base); + DPRINTF(Sparc, "0x%x - arg data\n", arg_data_base); + DPRINTF(Sparc, "0x%x - auxv array\n", auxv_array_base); + DPRINTF(Sparc, "0x%x - envp array\n", envp_array_base); + DPRINTF(Sparc, "0x%x - argv array\n", argv_array_base); + DPRINTF(Sparc, "0x%x - argc \n", argc_base); + DPRINTF(Sparc, "0x%x - window save\n", window_save_base); + DPRINTF(Sparc, "0x%x - stack min\n", stack_min); + + // write contents to stack + uint64_t argc = argv.size(); + uint64_t guestArgc = TheISA::htog(argc); + + //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); + + execContexts[0]->setIntReg(ArgumentReg0, argc); + execContexts[0]->setIntReg(ArgumentReg1, argv_array_base); + execContexts[0]->setIntReg(StackPointerReg, stack_min - StackBias); + + Addr prog_entry = objFile->entryPoint(); + execContexts[0]->setPC(prog_entry); + execContexts[0]->setNextPC(prog_entry + sizeof(MachInst)); + execContexts[0]->setNextNPC(prog_entry + (2 * sizeof(MachInst))); + +// num_processes++; +} + + +BEGIN_DECLARE_SIM_OBJECT_PARAMS(SparcLiveProcess) + + VectorParam<string> cmd; + Param<string> executable; + Param<string> input; + Param<string> output; + VectorParam<string> env; + SimObjectParam<System *> system; + +END_DECLARE_SIM_OBJECT_PARAMS(SparcLiveProcess) + + +BEGIN_INIT_SIM_OBJECT_PARAMS(SparcLiveProcess) + + INIT_PARAM(cmd, "command line (executable plus arguments)"), + INIT_PARAM(executable, "executable (overrides cmd[0] if set)"), + INIT_PARAM(input, "filename for stdin (dflt: use sim stdin)"), + INIT_PARAM(output, "filename for stdout/stderr (dflt: use sim stdout)"), + INIT_PARAM(env, "environment settings"), + INIT_PARAM(system, "system") + +END_INIT_SIM_OBJECT_PARAMS(SparcLiveProcess) + + +CREATE_SIM_OBJECT(SparcLiveProcess) +{ + string in = input; + string out = output; + + // initialize file descriptors to default: same as simulator + int stdin_fd, stdout_fd, stderr_fd; + + if (in == "stdin" || in == "cin") + stdin_fd = STDIN_FILENO; + else + stdin_fd = Process::openInputFile(input); + + if (out == "stdout" || out == "cout") + stdout_fd = STDOUT_FILENO; + else if (out == "stderr" || out == "cerr") + stdout_fd = STDERR_FILENO; + else + stdout_fd = Process::openOutputFile(out); + + stderr_fd = (stdout_fd != STDOUT_FILENO) ? stdout_fd : STDERR_FILENO; + + return SparcLiveProcess::create(getInstanceName(), system, + stdin_fd, stdout_fd, stderr_fd, + (string)executable == "" ? cmd[0] : executable, + cmd, env); +} + + +REGISTER_SIM_OBJECT("SparcLiveProcess", SparcLiveProcess) + + diff --git a/arch/sparc/process.hh b/arch/sparc/process.hh index 48041a316..c177f20a5 100644 --- a/arch/sparc/process.hh +++ b/arch/sparc/process.hh @@ -29,17 +29,51 @@ #ifndef __SPARC_PROCESS_HH__ #define __SPARC_PROCESS_HH__ -#include "arch/sparc/linux/process.hh" -#include "base/loader/object_file.hh" +#include <string> +#include <vector> +#include "sim/process.hh" -namespace SparcISA +class ObjectFile; +class System; + +typedef struct +{ + int64_t a_type; + union { + int64_t a_val; + Addr a_ptr; + Addr a_fcn; + }; +} m5_auxv_t; + +class SparcLiveProcess : public LiveProcess { + protected: + + static const Addr StackBias = 2047; + + std::vector<m5_auxv_t> auxv; + + SparcLiveProcess(const std::string &nm, ObjectFile *objFile, + System *_system, int stdin_fd, int stdout_fd, int stderr_fd, + std::vector<std::string> &argv, + std::vector<std::string> &envp); + + void startup(); + + public: + // this function is used to create the LiveProcess object, since + // we can't tell which subclass of LiveProcess to use until we + // open and look at the object file. + static SparcLiveProcess *create(const std::string &nm, + System *_system, + int stdin_fd, int stdout_fd, int stderr_fd, + std::string executable, + std::vector<std::string> &argv, + std::vector<std::string> &envp); -LiveProcess * -createProcess(const string &nm, ObjectFile * objFile, - int stdin_fd, int stdout_fd, int stderr_fd, - vector<string> &argv, vector<string> &envp); + void argsInit(int intSize, int pageSize); -} // namespace SparcISA +}; #endif // __SPARC_PROCESS_HH__ diff --git a/arch/sparc/regfile.hh b/arch/sparc/regfile.hh new file mode 100644 index 000000000..5169a332f --- /dev/null +++ b/arch/sparc/regfile.hh @@ -0,0 +1,812 @@ +/* + * Copyright (c) 2003-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. + */ + +#ifndef __ARCH_SPARC_REGFILE_HH__ +#define __ARCH_SPARC_REGFILE_HH__ + +#include "arch/sparc/faults.hh" +#include "base/trace.hh" +#include "sim/byteswap.hh" +#include "sim/host.hh" + +class Checkpoint; + +namespace SparcISA +{ + + typedef uint8_t RegIndex; + + // MAXTL - maximum trap level + const int MaxTL = 4; + + // NWINDOWS - number of register windows, can be 3 to 32 + const int NWindows = 32; + + class IntRegFile + { + protected: + static const int FrameOffsetBits = 3; + static const int FrameNumBits = 2; + + static const int RegsPerFrame = 1 << FrameOffsetBits; + static const int FrameNumMask = + (FrameNumBits == sizeof(int)) ? + (unsigned int)(-1) : + (1 << FrameNumBits) - 1; + static const int FrameOffsetMask = + (FrameOffsetBits == sizeof(int)) ? + (unsigned int)(-1) : + (1 << FrameOffsetBits) - 1; + + IntReg regGlobals[RegsPerFrame]; + IntReg altGlobals[RegsPerFrame]; + IntReg regSegments[2 * NWindows][RegsPerFrame]; + + enum regFrame {Globals, Outputs, Locals, Inputs, NumFrames}; + + IntReg * regView[NumFrames]; + + static const int RegGlobalOffset = 0; + static const int AltGlobalOffset = 8; + static const int FrameOffset = 16; + int offset[NumFrames]; + + public: + + int flattenIndex(int reg) + { + int flatIndex = offset[reg >> FrameOffsetBits] + | (reg & FrameOffsetMask); + DPRINTF(Sparc, "Flattened index %d into %d.\n", reg, flatIndex); + return flatIndex; + } + + void clear() + { + bzero(regGlobals, sizeof(regGlobals)); + bzero(altGlobals, sizeof(altGlobals)); + for(int x = 0; x < 2 * NWindows; x++) + bzero(regSegments[x], sizeof(regSegments[x])); + } + + IntRegFile() + { + offset[Globals] = 0; + regView[Globals] = regGlobals; + setCWP(0); + clear(); + } + + IntReg readReg(int intReg) + { + IntReg val = + regView[intReg >> FrameOffsetBits][intReg & FrameOffsetMask]; + DPRINTF(Sparc, "Read register %d = 0x%x\n", intReg, val); + return val; + } + + Fault setReg(int intReg, const IntReg &val) + { + if(intReg) + DPRINTF(Sparc, "Wrote register %d = 0x%x\n", intReg, val); + regView[intReg >> FrameOffsetBits][intReg & FrameOffsetMask] = val; + return NoFault; + } + + //This doesn't effect the actual CWP register. + //It's purpose is to adjust the view of the register file + //to what it would be if CWP = cwp. + void setCWP(int cwp) + { + int index = ((NWindows - cwp) % NWindows) * 2; + offset[Outputs] = FrameOffset + (index * RegsPerFrame); + offset[Locals] = FrameOffset + ((index+1) * RegsPerFrame); + offset[Inputs] = FrameOffset + + (((index+2) % (NWindows * 2)) * RegsPerFrame); + regView[Outputs] = regSegments[index]; + regView[Locals] = regSegments[index+1]; + regView[Inputs] = regSegments[(index+2) % (NWindows * 2)]; + + DPRINTF(Sparc, "Changed the CWP value to %d\n", cwp); + } + + void setAltGlobals(bool useAlt) + { + DPRINTF(Sparc, "Now using %s globals", + useAlt ? "alternate" : "regular"); + regView[Globals] = useAlt ? altGlobals : regGlobals; + + // You have not included an out-of-class definition of your static + // members. See [9.4.2]/4 and about a billion gcc bug reports. If + // statements get around the problem through some magic, and than + // seems nicer that putting a definition of them in a c file + // somewhere. + if (useAlt) + offset[Globals] = AltGlobalOffset; + else + offset[Globals] = RegGlobalOffset; + } + + void serialize(std::ostream &os); + + void unserialize(Checkpoint *cp, const std::string §ion); + }; + + typedef float float32_t; + typedef double float64_t; + //FIXME long double refers to a 10 byte float, rather than a + //16 byte float as required. This data type may have to be emulated. + typedef double float128_t; + + class FloatRegFile + { + public: + static const int SingleWidth = 32; + static const int DoubleWidth = 64; + static const int QuadWidth = 128; + + protected: + + //Since the floating point registers overlap each other, + //A generic storage space is used. The float to be returned is + //pulled from the appropriate section of this region. + char regSpace[SingleWidth / 8 * NumFloatRegs]; + + public: + + void clear() + { + bzero(regSpace, sizeof(regSpace)); + } + + FloatReg readReg(int floatReg, int width) + { + //In each of these cases, we have to copy the value into a temporary + //variable. This is because we may otherwise try to access an + //unaligned portion of memory. + switch(width) + { + case SingleWidth: + float32_t result32; + memcpy(&result32, regSpace + 4 * floatReg, width); + return htog(result32); + case DoubleWidth: + float64_t result64; + memcpy(&result64, regSpace + 4 * floatReg, width); + return htog(result64); + case QuadWidth: + float128_t result128; + memcpy(&result128, regSpace + 4 * floatReg, width); + return htog(result128); + default: + panic("Attempted to read a %d bit floating point register!", width); + } + } + + FloatRegBits readRegBits(int floatReg, int width) + { + //In each of these cases, we have to copy the value into a temporary + //variable. This is because we may otherwise try to access an + //unaligned portion of memory. + switch(width) + { + case SingleWidth: + uint32_t result32; + memcpy(&result32, regSpace + 4 * floatReg, width); + return htog(result32); + case DoubleWidth: + uint64_t result64; + memcpy(&result64, regSpace + 4 * floatReg, width); + return htog(result64); + case QuadWidth: + uint64_t result128; + memcpy(&result128, regSpace + 4 * floatReg, width); + return htog(result128); + default: + panic("Attempted to read a %d bit floating point register!", width); + } + } + + Fault setReg(int floatReg, const FloatReg &val, int width) + { + //In each of these cases, we have to copy the value into a temporary + //variable. This is because we may otherwise try to access an + //unaligned portion of memory. + switch(width) + { + case SingleWidth: + uint32_t result32 = gtoh((uint32_t)val); + memcpy(regSpace + 4 * floatReg, &result32, width); + case DoubleWidth: + uint64_t result64 = gtoh((uint64_t)val); + memcpy(regSpace + 4 * floatReg, &result64, width); + case QuadWidth: + uint64_t result128 = gtoh((uint64_t)val); + memcpy(regSpace + 4 * floatReg, &result128, width); + default: + panic("Attempted to read a %d bit floating point register!", width); + } + return NoFault; + } + + Fault setRegBits(int floatReg, const FloatRegBits &val, int width) + { + //In each of these cases, we have to copy the value into a temporary + //variable. This is because we may otherwise try to access an + //unaligned portion of memory. + switch(width) + { + case SingleWidth: + uint32_t result32 = gtoh((uint32_t)val); + memcpy(regSpace + 4 * floatReg, &result32, width); + case DoubleWidth: + uint64_t result64 = gtoh((uint64_t)val); + memcpy(regSpace + 4 * floatReg, &result64, width); + case QuadWidth: + uint64_t result128 = gtoh((uint64_t)val); + memcpy(regSpace + 4 * floatReg, &result128, width); + default: + panic("Attempted to read a %d bit floating point register!", width); + } + return NoFault; + } + + void serialize(std::ostream &os); + + void unserialize(Checkpoint *cp, const std::string §ion); + }; + + enum MiscRegIndex + { + MISCREG_PSTATE, + MISCREG_PSTATE_AG, + MISCREG_PSTATE_IE, + MISCREG_PSTATE_PRIV, + MISCREG_PSTATE_AM, + MISCREG_PSTATE_PEF, + MISCREG_PSTATE_RED, + MISCREG_PSTATE_MM, + MISCREG_PSTATE_TLE, + MISCREG_PSTATE_CLE, + MISCREG_TBA, + MISCREG_Y, + MISCREG_Y_VALUE, + MISCREG_PIL, + MISCREG_CWP, + MISCREG_TT_BASE, + MISCREG_TT_END = MISCREG_TT_BASE + MaxTL, + MISCREG_CCR, + MISCREG_CCR_ICC, + MISCREG_CCR_ICC_C, + MISCREG_CCR_ICC_V, + MISCREG_CCR_ICC_Z, + MISCREG_CCR_ICC_N, + MISCREG_CCR_XCC, + MISCREG_CCR_XCC_C, + MISCREG_CCR_XCC_V, + MISCREG_CCR_XCC_Z, + MISCREG_CCR_XCC_N, + MISCREG_ASI, + MISCREG_TL, + MISCREG_TPC_BASE, + MISCREG_TPC_END = MISCREG_TPC_BASE + MaxTL, + MISCREG_TNPC_BASE, + MISCREG_TNPC_END = MISCREG_TNPC_BASE + MaxTL, + MISCREG_TSTATE_BASE, + MISCREG_TSTATE_END = MISCREG_TSTATE_BASE + MaxTL, + MISCREG_TSTATE_CWP_BASE, + MISCREG_TSTATE_CWP_END = MISCREG_TSTATE_CWP_BASE + MaxTL, + MISCREG_TSTATE_PSTATE_BASE, + MISCREG_TSTATE_PSTATE_END = MISCREG_TSTATE_PSTATE_BASE + MaxTL, + MISCREG_TSTATE_ASI_BASE, + MISCREG_TSTATE_ASI_END = MISCREG_TSTATE_ASI_BASE + MaxTL, + MISCREG_TSTATE_CCR_BASE, + MISCREG_TSTATE_CCR_END = MISCREG_TSTATE_CCR_BASE + MaxTL, + MISCREG_TICK, + MISCREG_TICK_COUNTER, + MISCREG_TICK_NPT, + MISCREG_CANSAVE, + MISCREG_CANRESTORE, + MISCREG_OTHERWIN, + MISCREG_CLEANWIN, + MISCREG_WSTATE, + MISCREG_WSTATE_NORMAL, + MISCREG_WSTATE_OTHER, + MISCREG_VER, + MISCREG_VER_MAXWIN, + MISCREG_VER_MAXTL, + MISCREG_VER_MASK, + MISCREG_VER_IMPL, + MISCREG_VER_MANUF, + MISCREG_FSR, + MISCREG_FSR_CEXC, + MISCREG_FSR_CEXC_NXC, + MISCREG_FSR_CEXC_DZC, + MISCREG_FSR_CEXC_UFC, + MISCREG_FSR_CEXC_OFC, + MISCREG_FSR_CEXC_NVC, + MISCREG_FSR_AEXC, + MISCREG_FSR_AEXC_NXC, + MISCREG_FSR_AEXC_DZC, + MISCREG_FSR_AEXC_UFC, + MISCREG_FSR_AEXC_OFC, + MISCREG_FSR_AEXC_NVC, + MISCREG_FSR_FCC0, + MISCREG_FSR_QNE, + MISCREG_FSR_FTT, + MISCREG_FSR_VER, + MISCREG_FSR_NS, + MISCREG_FSR_TEM, + MISCREG_FSR_TEM_NXM, + MISCREG_FSR_TEM_DZM, + MISCREG_FSR_TEM_UFM, + MISCREG_FSR_TEM_OFM, + MISCREG_FSR_TEM_NVM, + MISCREG_FSR_RD, + MISCREG_FSR_FCC1, + MISCREG_FSR_FCC2, + MISCREG_FSR_FCC3, + MISCREG_FPRS, + MISCREG_FPRS_DL, + MISCREG_FPRS_DU, + MISCREG_FPRS_FEF, + numMiscRegs + }; + + // The control registers, broken out into fields + class MiscRegFile + { + private: + union + { + uint16_t pstate; // Process State Register + struct + { + uint16_t ag:1; // Alternate Globals + uint16_t ie:1; // Interrupt enable + uint16_t priv:1; // Privelege mode + uint16_t am:1; // Address mask + uint16_t pef:1; // PSTATE enable floating-point + uint16_t red:1; // RED (reset, error, debug) state + uint16_t mm:2; // Memory Model + uint16_t tle:1; // Trap little-endian + uint16_t cle:1; // Current little-endian + } pstateFields; + }; + uint64_t tba; // Trap Base Address + union + { + uint64_t y; // Y (used in obsolete multiplication) + struct + { + uint64_t value:32; // The actual value stored in y + uint64_t :32; // reserved bits + } yFields; + }; + uint8_t pil; // Process Interrupt Register + uint8_t cwp; // Current Window Pointer + uint16_t tt[MaxTL]; // Trap Type (Type of trap which occured + // on the previous level) + union + { + uint8_t ccr; // Condition Code Register + struct + { + union + { + uint8_t icc:4; // 32-bit condition codes + struct + { + uint8_t c:1; // Carry + uint8_t v:1; // Overflow + uint8_t z:1; // Zero + uint8_t n:1; // Negative + } iccFields; + }; + union + { + uint8_t xcc:4; // 64-bit condition codes + struct + { + uint8_t c:1; // Carry + uint8_t v:1; // Overflow + uint8_t z:1; // Zero + uint8_t n:1; // Negative + } xccFields; + }; + } ccrFields; + }; + uint8_t asi; // Address Space Identifier + uint8_t tl; // Trap Level + uint64_t tpc[MaxTL]; // Trap Program Counter (value from + // previous trap level) + uint64_t tnpc[MaxTL]; // Trap Next Program Counter (value from + // previous trap level) + union + { + uint64_t tstate[MaxTL]; // Trap State + struct + { + //Values are from previous trap level + uint64_t cwp:5; // Current Window Pointer + uint64_t :2; // Reserved bits + uint64_t pstate:10; // Process State + uint64_t :6; // Reserved bits + uint64_t asi:8; // Address Space Identifier + uint64_t ccr:8; // Condition Code Register + } tstateFields[MaxTL]; + }; + union + { + uint64_t tick; // Hardware clock-tick counter + struct + { + uint64_t counter:63; // Clock-tick count + uint64_t npt:1; // Non-priveleged trap + } tickFields; + }; + uint8_t cansave; // Savable windows + uint8_t canrestore; // Restorable windows + uint8_t otherwin; // Other windows + uint8_t cleanwin; // Clean windows + union + { + uint8_t wstate; // Window State + struct + { + uint8_t normal:3; // Bits TT<4:2> are set to on a normal + // register window trap + uint8_t other:3; // Bits TT<4:2> are set to on an "otherwin" + // register window trap + } wstateFields; + }; + union + { + uint64_t ver; // Version + struct + { + uint64_t maxwin:5; // Max CWP value + uint64_t :2; // Reserved bits + uint64_t maxtl:8; // Maximum trap level + uint64_t :8; // Reserved bits + uint64_t mask:8; // Processor mask set revision number + uint64_t impl:16; // Implementation identification number + uint64_t manuf:16; // Manufacturer code + } verFields; + }; + union + { + uint64_t fsr; // Floating-Point State Register + struct + { + union + { + uint64_t cexc:5; // Current excpetion + struct + { + uint64_t nxc:1; // Inexact + uint64_t dzc:1; // Divide by zero + uint64_t ufc:1; // Underflow + uint64_t ofc:1; // Overflow + uint64_t nvc:1; // Invalid operand + } cexcFields; + }; + union + { + uint64_t aexc:5; // Accrued exception + struct + { + uint64_t nxc:1; // Inexact + uint64_t dzc:1; // Divide by zero + uint64_t ufc:1; // Underflow + uint64_t ofc:1; // Overflow + uint64_t nvc:1; // Invalid operand + } aexcFields; + }; + uint64_t fcc0:2; // Floating-Point condtion codes + uint64_t :1; // Reserved bits + uint64_t qne:1; // Deferred trap queue not empty + // with no queue, it should read 0 + uint64_t ftt:3; // Floating-Point trap type + uint64_t ver:3; // Version (of the FPU) + uint64_t :2; // Reserved bits + uint64_t ns:1; // Nonstandard floating point + union + { + uint64_t tem:5; // Trap Enable Mask + struct + { + uint64_t nxm:1; // Inexact + uint64_t dzm:1; // Divide by zero + uint64_t ufm:1; // Underflow + uint64_t ofm:1; // Overflow + uint64_t nvm:1; // Invalid operand + } temFields; + }; + uint64_t :2; // Reserved bits + uint64_t rd:2; // Rounding direction + uint64_t fcc1:2; // Floating-Point condition codes + uint64_t fcc2:2; // Floating-Point condition codes + uint64_t fcc3:2; // Floating-Point condition codes + uint64_t :26; // Reserved bits + } fsrFields; + }; + union + { + uint8_t fprs; // Floating-Point Register State + struct + { + uint8_t dl:1; // Dirty lower + uint8_t du:1; // Dirty upper + uint8_t fef:1; // FPRS enable floating-Point + } fprsFields; + }; + + public: + + void reset() + { + pstateFields.pef = 0; //No FPU + //pstateFields.pef = 1; //FPU +#if FULL_SYSTEM + //For SPARC, when a system is first started, there is a power + //on reset Trap which sets the processor into the following state. + //Bits that aren't set aren't defined on startup. + tl = MaxTL; + tt[tl] = PowerOnReset.trapType(); + pstateFields.mm = 0; //Total Store Order + pstateFields.red = 1; //Enter RED_State + pstateFields.am = 0; //Address Masking is turned off + pstateFields.priv = 1; //Processor enters privileged mode + pstateFields.ie = 0; //Interrupts are disabled + pstateFields.ag = 1; //Globals are replaced with alternate globals + pstateFields.tle = 0; //Big Endian mode for traps + pstateFields.cle = 0; //Big Endian mode for non-traps + tickFields.npt = 1; //The TICK register is unreadable by + //non-priveleged software +#else +/* //This sets up the initial state of the processor for usermode processes + pstateFields.priv = 0; //Process runs in user mode + pstateFields.ie = 1; //Interrupts are enabled + fsrFields.rd = 0; //Round to nearest + fsrFields.tem = 0; //Floating point traps not enabled + fsrFields.ns = 0; //Non standard mode off + fsrFields.qne = 0; //Floating point queue is empty + fsrFields.aexc = 0; //No accrued exceptions + fsrFields.cexc = 0; //No current exceptions + + //Register window management registers + otherwin = 0; //No windows contain info from other programs + canrestore = 0; //There are no windows to pop + cansave = MaxTL - 2; //All windows are available to save into + cleanwin = MaxTL;*/ +#endif + } + + MiscRegFile() + { + reset(); + } + + MiscReg readReg(int miscReg); + + MiscReg readRegWithEffect(int miscReg, Fault &fault, ExecContext *xc); + + Fault setReg(int miscReg, const MiscReg &val); + + Fault setRegWithEffect(int miscReg, + const MiscReg &val, ExecContext * xc); + + void serialize(std::ostream & os); + + void unserialize(Checkpoint * cp, const std::string & section); + + void copyMiscRegs(ExecContext * xc); + }; + + typedef union + { + IntReg intreg; + FloatReg fpreg; + MiscReg ctrlreg; + } AnyReg; + + class RegFile + { + protected: + Addr pc; // Program Counter + Addr npc; // Next Program Counter + Addr nnpc; + + public: + Addr readPC() + { + return pc; + } + + void setPC(Addr val) + { + pc = val; + } + + Addr readNextPC() + { + return npc; + } + + void setNextPC(Addr val) + { + npc = val; + } + + Addr readNextNPC() + { + return nnpc; + } + + void setNextNPC(Addr val) + { + nnpc = val; + } + + protected: + IntRegFile intRegFile; // integer register file + FloatRegFile floatRegFile; // floating point register file + MiscRegFile miscRegFile; // control register file + + public: + + void clear() + { + intRegFile.clear(); + floatRegFile.clear(); + } + + int flattenIntIndex(int reg) + { + return intRegFile.flattenIndex(reg); + } + + MiscReg readMiscReg(int miscReg) + { + return miscRegFile.readReg(miscReg); + } + + MiscReg readMiscRegWithEffect(int miscReg, + Fault &fault, ExecContext *xc) + { + return miscRegFile.readRegWithEffect(miscReg, fault, xc); + } + + Fault setMiscReg(int miscReg, const MiscReg &val) + { + return miscRegFile.setReg(miscReg, val); + } + + Fault setMiscRegWithEffect(int miscReg, const MiscReg &val, + ExecContext * xc) + { + return miscRegFile.setRegWithEffect(miscReg, val, xc); + } + + FloatReg readFloatReg(int floatReg, int width) + { + return floatRegFile.readReg(floatReg, width); + } + + FloatReg readFloatReg(int floatReg) + { + //Use the "natural" width of a single float + return floatRegFile.readReg(floatReg, FloatRegFile::SingleWidth); + } + + FloatRegBits readFloatRegBits(int floatReg, int width) + { + return floatRegFile.readRegBits(floatReg, width); + } + + FloatRegBits readFloatRegBits(int floatReg) + { + //Use the "natural" width of a single float + return floatRegFile.readRegBits(floatReg, + FloatRegFile::SingleWidth); + } + + Fault setFloatReg(int floatReg, const FloatReg &val, int width) + { + return floatRegFile.setReg(floatReg, val, width); + } + + Fault setFloatReg(int floatReg, const FloatReg &val) + { + //Use the "natural" width of a single float + return setFloatReg(floatReg, val, FloatRegFile::SingleWidth); + } + + Fault setFloatRegBits(int floatReg, const FloatRegBits &val, int width) + { + return floatRegFile.setRegBits(floatReg, val, width); + } + + Fault setFloatRegBits(int floatReg, const FloatRegBits &val) + { + //Use the "natural" width of a single float + return floatRegFile.setRegBits(floatReg, val, + FloatRegFile::SingleWidth); + } + + IntReg readIntReg(int intReg) + { + return intRegFile.readReg(intReg); + } + + Fault setIntReg(int intReg, const IntReg &val) + { + return intRegFile.setReg(intReg, val); + } + + void serialize(std::ostream &os); + void unserialize(Checkpoint *cp, const std::string §ion); + + public: + + enum ContextParam + { + CONTEXT_CWP, + CONTEXT_GLOBALS + }; + + union ContextVal + { + MiscReg reg; + bool altGlobals; + }; + + void changeContext(ContextParam param, ContextVal val) + { + switch(param) + { + case CONTEXT_CWP: + intRegFile.setCWP(val.reg); + break; + case CONTEXT_GLOBALS: + intRegFile.setAltGlobals(val.altGlobals); + break; + default: + panic("Tried to set illegal context parameter in the SPARC regfile.\n"); + } + } + }; + + void copyRegs(ExecContext *src, ExecContext *dest); + + void copyMiscRegs(ExecContext *src, ExecContext *dest); + +} // namespace SparcISA + +#endif diff --git a/arch/sparc/system.cc b/arch/sparc/system.cc new file mode 100644 index 000000000..1e2882607 --- /dev/null +++ b/arch/sparc/system.cc @@ -0,0 +1,200 @@ +/* + * Copyright (c) 2002-2006 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "arch/sparc/system.hh" +#include "arch/vtophys.hh" +#include "base/remote_gdb.hh" +#include "base/loader/object_file.hh" +#include "base/loader/symtab.hh" +#include "base/trace.hh" +#include "mem/physical.hh" +#include "sim/byteswap.hh" +#include "sim/builder.hh" + + +using namespace BigEndianGuest; + +SparcSystem::SparcSystem(Params *p) + : System(p) +{ + resetSymtab = new SymbolTable; + hypervisorSymtab = new SymbolTable; + openbootSymtab = new SymbolTable; + + + /** + * Load the boot code, and hypervisor into memory. + */ + // Read the reset binary + reset = createObjectFile(params()->reset_bin); + if (reset == NULL) + fatal("Could not load reset binary %s", params()->reset_bin); + + // Read the openboot binary + openboot = createObjectFile(params()->openboot_bin); + if (openboot == NULL) + fatal("Could not load openboot bianry %s", params()->openboot_bin); + + // Read the hypervisor binary + hypervisor = createObjectFile(params()->hypervisor_bin); + if (hypervisor == NULL) + fatal("Could not load hypervisor binary %s", params()->hypervisor_bin); + + + // Load reset binary into memory + reset->loadSections(&functionalPort, SparcISA::LoadAddrMask); + // Load the openboot binary + openboot->loadSections(&functionalPort, SparcISA::LoadAddrMask); + // Load the hypervisor binary + hypervisor->loadSections(&functionalPort, SparcISA::LoadAddrMask); + + // load symbols + if (!reset->loadGlobalSymbols(reset)) + panic("could not load reset symbols\n"); + + if (!openboot->loadGlobalSymbols(openbootSymtab)) + panic("could not load openboot symbols\n"); + + if (!hypervisor->loadLocalSymbols(hypervisorSymtab)) + panic("could not load hypervisor symbols\n"); + + // load symbols into debug table + if (!reset->loadGlobalSymbols(debugSymbolTable)) + panic("could not load reset symbols\n"); + + if (!openboot->loadGlobalSymbols(debugSymbolTable)) + panic("could not load openboot symbols\n"); + + if (!hypervisor->loadLocalSymbols(debugSymbolTable)) + panic("could not load hypervisor symbols\n"); + + + // @todo any fixup code over writing data in binaries on setting break + // events on functions should happen here. + +} + +SparcSystem::~SparcSystem() +{ + delete resetSymtab; + delete hypervisorSymtab; + delete openbootSymtab; + delete reset; + delete openboot; + delete hypervisor; +} + +bool +SparcSystem::breakpoint() +{ + panic("Need to implement"); +} + +void +SparcSystem::serialize(std::ostream &os) +{ + System::serialize(os); + resetSymtab->serialize("reset_symtab", os); + hypervisorSymtab->serialize("hypervisor_symtab", os); + openbootSymtab->serialize("openboot_symtab", os); +} + + +void +SparcSystem::unserialize(Checkpoint *cp, const std::string §ion) +{ + System::unserialize(cp,section); + resetSymtab->unserialize("reset_symtab", cp, section); + hypervisorSymtab->unserialize("hypervisor_symtab", cp, section); + openbootSymtab->unserialize("openboot_symtab", cp, section); +} + + +BEGIN_DECLARE_SIM_OBJECT_PARAMS(SparcSystem) + + SimObjectParam<PhysicalMemory *> physmem; + + Param<std::string> kernel; + Param<std::string> reset_bin; + Param<std::string> hypervisor_bin; + Param<std::string> openboot_bin; + + Param<std::string> boot_osflags; + Param<std::string> readfile; + Param<unsigned int> init_param; + + Param<bool> bin; + VectorParam<std::string> binned_fns; + Param<bool> bin_int; + +END_DECLARE_SIM_OBJECT_PARAMS(SparcSystem) + +BEGIN_INIT_SIM_OBJECT_PARAMS(SparcSystem) + + INIT_PARAM(boot_cpu_frequency, "Frequency of the boot CPU"), + INIT_PARAM(physmem, "phsyical memory"), + INIT_PARAM(kernel, "file that contains the kernel code"), + INIT_PARAM(reset_bin, "file that contains the reset code"), + INIT_PARAM(hypervisor_bin, "file that contains the hypervisor code"), + INIT_PARAM(openboot_bin, "file that contains the openboot code"), + INIT_PARAM_DFLT(boot_osflags, "flags to pass to the kernel during boot", + "a"), + INIT_PARAM_DFLT(readfile, "file to read startup script from", ""), + INIT_PARAM_DFLT(init_param, "numerical value to pass into simulator", 0), + INIT_PARAM_DFLT(system_type, "Type of system we are emulating", 34), + INIT_PARAM_DFLT(system_rev, "Revision of system we are emulating", 1<<10), + INIT_PARAM_DFLT(bin, "is this system to be binned", false), + INIT_PARAM(binned_fns, "functions to be broken down and binned"), + INIT_PARAM_DFLT(bin_int, "is interrupt code binned seperately?", true) + +END_INIT_SIM_OBJECT_PARAMS(SparcSystem) + +CREATE_SIM_OBJECT(SparcSystem) +{ + SparcSystem::Params *p = new SparcSystem::Params; + p->name = getInstanceName(); + p->boot_cpu_frequency = boot_cpu_frequency; + p->physmem = physmem; + p->kernel_path = kernel; + p->reset_bin = reset_bin; + p->hypervisor_bin = hypervisor_bin; + p->openboot_bin = openboot_bin; + p->boot_osflags = boot_osflags; + p->init_param = init_param; + p->readfile = readfile; + p->system_type = system_type; + p->system_rev = system_rev; + p->bin = bin; + p->binned_fns = binned_fns; + p->bin_int = bin_int; + return new SparcSystem(p); +} + +REGISTER_SIM_OBJECT("SparcSystem", SparcSystem) + + diff --git a/arch/sparc/system.hh b/arch/sparc/system.hh new file mode 100644 index 000000000..27aa8768a --- /dev/null +++ b/arch/sparc/system.hh @@ -0,0 +1,114 @@ +/* + * Copyright (c) 2002-2005 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef __ARCH_SPARC_SYSTEM_HH__ +#define __ARCH_SPARC_SYSTEM_HH__ + +#include <string> +#include <vector> + +#include "base/loader/symtab.hh" +#include "cpu/pc_event.hh" +#include "kern/system_events.hh" +#include "sim/sim_object.hh" +#include "sim/system.hh" + +class SparcSystem : public System +{ + public: + struct Params : public System::Params + { + std::string reset_bin; + std::string hypervison_bin; + std::string openboot_bin; + std::string boot_osflags; + uint64_t system_type; + uint64_t system_rev; + }; + + SparcSystem(Params *p); + + ~SparcaSystem(); + + virtual bool breakpoint(); + +/** + * Serialization stuff + */ + public: + virtual void serialize(std::ostream &os); + virtual void unserialize(Checkpoint *cp, const std::string §ion); + + /** reset binary symbol table */ + SymbolTable *resetSymtab; + + /** hypervison binary symbol table */ + SymbolTable *hypervisorSymtab; + + /** openboot symbol table */ + SymbolTable *openbootSymtab; + + /** Object pointer for the reset binary */ + ObjectFile *reset; + + /** Object pointer for the hypervisor code */ + ObjectFile *hypervisor; + + /** Object pointer for the openboot code */ + ObjectFile *openboot; + + protected: + const Params *params() const { return (const Params *)_params; } + + /** Add a function-based event to reset binary. */ + template <class T> + T *SparcSystem::addResetFuncEvent(const char *lbl) + { + return addFuncEvent<T>(resetSymtab, lbl); + } + + /** Add a function-based event to the hypervisor. */ + template <class T> + T *SparcSystem::addHypervisorFuncEvent(const char *lbl) + { + return addFuncEvent<T>(hypervisorSymtab, lbl); + } + + /** Add a function-based event to the openboot. */ + template <class T> + T *SparcSystem::addOpenbootFuncEvent(const char *lbl) + { + return addFuncEvent<T>(openbootSymtab, lbl); + } + + virtual Addr fixFuncEventAddr(Addr addr); + +}; + +#endif + diff --git a/arch/sparc/utility.hh b/arch/sparc/utility.hh new file mode 100644 index 000000000..1e67b3370 --- /dev/null +++ b/arch/sparc/utility.hh @@ -0,0 +1,89 @@ +/* + * Copyright (c) 2003-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. + */ + +#ifndef __ARCH_SPARC_UTILITY_HH__ +#define __ARCH_SPARC_UTILITY_HH__ + +#include "arch/sparc/isa_traits.hh" +#include "base/misc.hh" + +namespace SparcISA +{ + inline ExtMachInst + makeExtMI(MachInst inst, const Addr &pc) { + return ExtMachInst(inst); + } + + inline bool isCallerSaveIntegerRegister(unsigned int reg) { + panic("register classification not implemented"); + return false; + } + + inline bool isCalleeSaveIntegerRegister(unsigned int reg) { + panic("register classification not implemented"); + return false; + } + + inline bool isCallerSaveFloatRegister(unsigned int reg) { + panic("register classification not implemented"); + return false; + } + + inline bool isCalleeSaveFloatRegister(unsigned int reg) { + panic("register classification not implemented"); + return false; + } + + // Instruction address compression hooks + inline Addr realPCToFetchPC(const Addr &addr) + { + return addr; + } + + inline Addr fetchPCToRealPC(const Addr &addr) + { + return addr; + } + + // the size of "fetched" instructions (not necessarily the size + // of real instructions for PISA) + inline size_t fetchInstSize() + { + return sizeof(MachInst); + } + + /** + * Function to insure ISA semantics about 0 registers. + * @param xc The execution context. + */ + template <class XC> + void zeroRegisters(XC *xc); + +} // namespace SparcISA + +#endif diff --git a/base/chunk_generator.hh b/base/chunk_generator.hh new file mode 100644 index 000000000..4f708bd4b --- /dev/null +++ b/base/chunk_generator.hh @@ -0,0 +1,141 @@ +/* + * Copyright (c) 2001-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. + */ + +#ifndef __BASE__CHUNK_GENERATOR_HH__ +#define __BASE__CHUNK_GENERATOR_HH__ + +/** + * @file + * Declaration and inline definition of ChunkGenerator object. + */ + +#include <algorithm> +#include "base/intmath.hh" +#include "arch/isa_traits.hh" // for Addr + +/** + * This class takes an arbitrary memory region (address/length pair) + * and generates a series of appropriately (e.g. block- or page-) + * aligned chunks covering the same region. + * + * Example usage: + +\code + for (ChunkGenerator gen(addr, size, chunkSize); !gen.done(); gen.next()) { + doSomethingChunky(gen.addr(), gen.size()); + } +\endcode + */ +class ChunkGenerator +{ + private: + /** The starting address of the current chunk. */ + Addr curAddr; + /** The starting address of the next chunk (after the current one). */ + Addr nextAddr; + /** The size of the current chunk (in bytes). */ + int curSize; + /** The number of bytes remaining in the region after the current chunk. */ + int sizeLeft; + /** The start address so we can calculate offset in writing block. */ + const Addr startAddr; + /** The maximum chunk size, e.g., the cache block size or page size. */ + const int chunkSize; + + public: + /** + * Constructor. + * @param startAddr The starting address of the region. + * @param totalSize The total size of the region. + * @param _chunkSize The size/alignment of chunks into which + * the region should be decomposed. + */ + ChunkGenerator(Addr _startAddr, int totalSize, int _chunkSize) + : startAddr(_startAddr), chunkSize(_chunkSize) + { + // chunkSize must be a power of two + assert(chunkSize == 0 || isPowerOf2(chunkSize)); + + // set up initial chunk. + curAddr = startAddr; + + if (chunkSize == 0) //Special Case, if we see 0, assume no chuncking + { + nextAddr = startAddr + totalSize; + } + else + { + // nextAddr should be *next* chunk start + nextAddr = roundUp(startAddr, chunkSize); + if (curAddr == nextAddr) { + // ... even if startAddr is already chunk-aligned + nextAddr += chunkSize; + } + } + + // how many bytes are left between curAddr and the end of this chunk? + int left_in_chunk = nextAddr - curAddr; + curSize = std::min(totalSize, left_in_chunk); + sizeLeft = totalSize - curSize; + } + + /** Return starting address of current chunk. */ + Addr addr() { return curAddr; } + /** Return size in bytes of current chunk. */ + int size() { return curSize; } + + /** Number of bytes we have already chunked up. */ + int complete() { return curAddr - startAddr; } + /** + * Are we done? That is, did the last call to next() advance + * past the end of the region? + * @return True if yes, false if more to go. + */ + bool done() { return (curSize == 0); } + + /** + * Advance generator to next chunk. + * @return True if successful, false if unsuccessful + * (because we were at the last chunk). + */ + bool next() + { + if (sizeLeft == 0) { + curSize = 0; + return false; + } + + curAddr = nextAddr; + curSize = std::min(sizeLeft, chunkSize); + sizeLeft -= curSize; + nextAddr += curSize; + return true; + } +}; + +#endif // __BASE__CHUNK_GENERATOR_HH__ diff --git a/base/inet.hh b/base/inet.hh index e07e01935..e5d0473f9 100644 --- a/base/inet.hh +++ b/base/inet.hh @@ -117,11 +117,11 @@ class EthPtr { protected: friend class IpPtr; - PacketPtr p; + EthPacketPtr p; public: EthPtr() {} - EthPtr(const PacketPtr &ptr) : p(ptr) { } + EthPtr(const EthPacketPtr &ptr) : p(ptr) { } EthHdr *operator->() { return (EthHdr *)p->data; } EthHdr &operator*() { return *(EthHdr *)p->data; } @@ -131,10 +131,10 @@ class EthPtr const EthHdr &operator*() const { return *(const EthHdr *)p->data; } operator const EthHdr *() const { return (const EthHdr *)p->data; } - const EthPtr &operator=(const PacketPtr &ptr) { p = ptr; return *this; } + const EthPtr &operator=(const EthPacketPtr &ptr) { p = ptr; return *this; } - const PacketPtr packet() const { return p; } - PacketPtr packet() { return p; } + const EthPacketPtr packet() const { return p; } + EthPacketPtr packet() { return p; } bool operator!() const { return !p; } operator bool() const { return p; } }; @@ -174,13 +174,13 @@ class IpPtr protected: friend class TcpPtr; friend class UdpPtr; - PacketPtr p; + EthPacketPtr p; const IpHdr *h() const { return (const IpHdr *)(p->data + sizeof(eth_hdr)); } IpHdr *h() { return (IpHdr *)(p->data + sizeof(eth_hdr)); } - void set(const PacketPtr &ptr) + void set(const EthPacketPtr &ptr) { EthHdr *eth = (EthHdr *)ptr->data; if (eth->type() == ETH_TYPE_IP) @@ -191,7 +191,7 @@ class IpPtr public: IpPtr() {} - IpPtr(const PacketPtr &ptr) { set(ptr); } + IpPtr(const EthPacketPtr &ptr) { set(ptr); } IpPtr(const EthPtr &ptr) { set(ptr.p); } IpPtr(const IpPtr &ptr) : p(ptr.p) { } @@ -203,12 +203,12 @@ class IpPtr const IpHdr &operator*() const { return *h(); } operator const IpHdr *() const { return h(); } - const IpPtr &operator=(const PacketPtr &ptr) { set(ptr); return *this; } + const IpPtr &operator=(const EthPacketPtr &ptr) { set(ptr); return *this; } const IpPtr &operator=(const EthPtr &ptr) { set(ptr.p); return *this; } const IpPtr &operator=(const IpPtr &ptr) { p = ptr.p; return *this; } - const PacketPtr packet() const { return p; } - PacketPtr packet() { return p; } + const EthPacketPtr packet() const { return p; } + EthPacketPtr packet() { return p; } bool operator!() const { return !p; } operator bool() const { return p; } operator bool() { return p; } @@ -272,13 +272,13 @@ struct TcpHdr : public tcp_hdr class TcpPtr { protected: - PacketPtr p; + EthPacketPtr p; int off; const TcpHdr *h() const { return (const TcpHdr *)(p->data + off); } TcpHdr *h() { return (TcpHdr *)(p->data + off); } - void set(const PacketPtr &ptr, int offset) { p = ptr; off = offset; } + void set(const EthPacketPtr &ptr, int offset) { p = ptr; off = offset; } void set(const IpPtr &ptr) { if (ptr->proto() == IP_PROTO_TCP) @@ -303,8 +303,8 @@ class TcpPtr const TcpPtr &operator=(const IpPtr &i) { set(i); return *this; } const TcpPtr &operator=(const TcpPtr &t) { set(t.p, t.off); return *this; } - const PacketPtr packet() const { return p; } - PacketPtr packet() { return p; } + const EthPacketPtr packet() const { return p; } + EthPacketPtr packet() { return p; } bool operator!() const { return !p; } operator bool() const { return p; } operator bool() { return p; } @@ -362,13 +362,13 @@ struct UdpHdr : public udp_hdr class UdpPtr { protected: - PacketPtr p; + EthPacketPtr p; int off; const UdpHdr *h() const { return (const UdpHdr *)(p->data + off); } UdpHdr *h() { return (UdpHdr *)(p->data + off); } - void set(const PacketPtr &ptr, int offset) { p = ptr; off = offset; } + void set(const EthPacketPtr &ptr, int offset) { p = ptr; off = offset; } void set(const IpPtr &ptr) { if (ptr->proto() == IP_PROTO_UDP) @@ -393,8 +393,8 @@ class UdpPtr const UdpPtr &operator=(const IpPtr &i) { set(i); return *this; } const UdpPtr &operator=(const UdpPtr &t) { set(t.p, t.off); return *this; } - const PacketPtr packet() const { return p; } - PacketPtr packet() { return p; } + const EthPacketPtr packet() const { return p; } + EthPacketPtr packet() { return p; } bool operator!() const { return !p; } operator bool() const { return p; } operator bool() { return p; } diff --git a/base/intmath.hh b/base/intmath.hh index df0687c62..51baddb91 100644 --- a/base/intmath.hh +++ b/base/intmath.hh @@ -186,9 +186,9 @@ roundUp(T val, int align) template <class T> inline T -roundDown(T val, T align) +roundDown(T val, int align) { - T mask = align - 1; + T mask = (T)align - 1; return val & ~mask; } diff --git a/base/loader/aout_object.cc b/base/loader/aout_object.cc index c81f7123f..564898ca3 100644 --- a/base/loader/aout_object.cc +++ b/base/loader/aout_object.cc @@ -30,7 +30,6 @@ #include "base/loader/aout_object.hh" -#include "mem/functional/functional.hh" #include "base/loader/symtab.hh" #include "base/trace.hh" // for DPRINTF @@ -64,12 +63,15 @@ AoutObject::AoutObject(const string &_filename, int _fd, text.baseAddr = N_TXTADDR(*execHdr); text.size = execHdr->tsize; + text.fileImage = fileData + N_TXTOFF(*execHdr); data.baseAddr = N_DATADDR(*execHdr); data.size = execHdr->dsize; + data.fileImage = fileData + N_DATOFF(*execHdr); bss.baseAddr = N_BSSADDR(*execHdr); bss.size = execHdr->bsize; + bss.fileImage = NULL; DPRINTFR(Loader, "text: 0x%x %d\ndata: 0x%x %d\nbss: 0x%x %d\n", text.baseAddr, text.size, data.baseAddr, data.size, @@ -78,28 +80,6 @@ AoutObject::AoutObject(const string &_filename, int _fd, bool -AoutObject::loadSections(FunctionalMemory *mem, bool loadPhys) -{ - Addr textAddr = text.baseAddr; - Addr dataAddr = data.baseAddr; - - if (loadPhys) { - textAddr &= (ULL(1) << 40) - 1; - dataAddr &= (ULL(1) << 40) - 1; - } - - // Since we don't really have an MMU and all memory is - // zero-filled, there's no need to set up the BSS segment. - if (text.size != 0) - mem->prot_write(textAddr, fileData + N_TXTOFF(*execHdr), text.size); - if (data.size != 0) - mem->prot_write(dataAddr, fileData + N_DATOFF(*execHdr), data.size); - - return true; -} - - -bool AoutObject::loadGlobalSymbols(SymbolTable *symtab) { // a.out symbols not supported yet diff --git a/base/loader/aout_object.hh b/base/loader/aout_object.hh index 1868192b2..aeb710427 100644 --- a/base/loader/aout_object.hh +++ b/base/loader/aout_object.hh @@ -46,8 +46,6 @@ class AoutObject : public ObjectFile public: virtual ~AoutObject() {} - virtual bool loadSections(FunctionalMemory *mem, - bool loadPhys = false); virtual bool loadGlobalSymbols(SymbolTable *symtab); virtual bool loadLocalSymbols(SymbolTable *symtab); diff --git a/base/loader/ecoff_object.cc b/base/loader/ecoff_object.cc index 353a5f333..80917ee9c 100644 --- a/base/loader/ecoff_object.cc +++ b/base/loader/ecoff_object.cc @@ -29,8 +29,7 @@ #include <string> #include "base/loader/ecoff_object.hh" - -#include "mem/functional/functional.hh" +#include "base/misc.hh" #include "base/loader/symtab.hh" #include "base/trace.hh" // for DPRINTF @@ -68,12 +67,15 @@ EcoffObject::EcoffObject(const string &_filename, int _fd, text.baseAddr = aoutHdr->text_start; text.size = aoutHdr->tsize; + text.fileImage = fileData + ECOFF_TXTOFF(execHdr); data.baseAddr = aoutHdr->data_start; data.size = aoutHdr->dsize; + data.fileImage = fileData + ECOFF_DATOFF(execHdr); bss.baseAddr = aoutHdr->bss_start; bss.size = aoutHdr->bsize; + bss.fileImage = NULL; DPRINTFR(Loader, "text: 0x%x %d\ndata: 0x%x %d\nbss: 0x%x %d\n", text.baseAddr, text.size, data.baseAddr, data.size, @@ -82,26 +84,6 @@ EcoffObject::EcoffObject(const string &_filename, int _fd, bool -EcoffObject::loadSections(FunctionalMemory *mem, bool loadPhys) -{ - Addr textAddr = text.baseAddr; - Addr dataAddr = data.baseAddr; - - if (loadPhys) { - textAddr &= (ULL(1) << 40) - 1; - dataAddr &= (ULL(1) << 40) - 1; - } - - // Since we don't really have an MMU and all memory is - // zero-filled, there's no need to set up the BSS segment. - mem->prot_write(textAddr, fileData + ECOFF_TXTOFF(execHdr), text.size); - mem->prot_write(dataAddr, fileData + ECOFF_DATOFF(execHdr), data.size); - - return true; -} - - -bool EcoffObject::loadGlobalSymbols(SymbolTable *symtab) { if (!symtab) diff --git a/base/loader/ecoff_object.hh b/base/loader/ecoff_object.hh index 78aa7f3f7..603c70bec 100644 --- a/base/loader/ecoff_object.hh +++ b/base/loader/ecoff_object.hh @@ -50,8 +50,6 @@ class EcoffObject : public ObjectFile public: virtual ~EcoffObject() {} - virtual bool loadSections(FunctionalMemory *mem, - bool loadPhys = false); virtual bool loadGlobalSymbols(SymbolTable *symtab); virtual bool loadLocalSymbols(SymbolTable *symtab); diff --git a/base/loader/elf_object.cc b/base/loader/elf_object.cc index 791c6f6de..a104719af 100644 --- a/base/loader/elf_object.cc +++ b/base/loader/elf_object.cc @@ -42,12 +42,14 @@ #include "libelf/gelf.h" #include "base/loader/elf_object.hh" +#include "base/misc.hh" -#include "mem/functional/functional.hh" #include "base/loader/symtab.hh" #include "base/trace.hh" // for DPRINTF +#include "sim/byteswap.hh" + using namespace std; @@ -73,14 +75,8 @@ ElfObject::tryFile(const string &fname, int fd, size_t len, uint8_t *data) DPRINTFR(Loader, "Not ELF\n"); elf_end(elf); return NULL; - } - else { + } else { //Detect the architecture - //Versioning issues in libelf need to be resolved to get the correct - //SPARC constants. - //If MIPS supports 32 bit executables, this may need to be changed. - //Also, there are other MIPS constants which may be used, like - //EM_MIPS_RS3_LE and EM_MIPS_X //Since we don't know how to check for alpha right now, we'll //just assume if it wasn't something else and it's 64 bit, that's //what it must be. @@ -90,7 +86,7 @@ ElfObject::tryFile(const string &fname, int fd, size_t len, uint8_t *data) arch = ObjectFile::SPARC; } else if (ehdr.e_machine == EM_MIPS && ehdr.e_ident[EI_CLASS] == ELFCLASS32) { - arch = ObjectFile::MIPS; + arch = ObjectFile::Mips; } else if (ehdr.e_ident[EI_CLASS] == ELFCLASS64) { arch = ObjectFile::Alpha; } else { @@ -154,6 +150,7 @@ ElfObject::tryFile(const string &fname, int fd, size_t len, uint8_t *data) section = elf_getscn(elf, ++secIdx); } // while sections } + elf_end(elf); return new ElfObject(fname, fd, len, data, arch, opSys); } @@ -185,6 +182,7 @@ ElfObject::ElfObject(const string &_filename, int _fd, entry = ehdr.e_entry; + // initialize segment sizes to 0 in case they're not present text.size = data.size = bss.size = 0; @@ -203,20 +201,18 @@ ElfObject::ElfObject(const string &_filename, int _fd, if (text.size == 0) { // haven't seen text segment yet text.baseAddr = phdr.p_vaddr; text.size = phdr.p_filesz; - // remember where the data is for loadSections() - fileTextBits = fileData + phdr.p_offset; + text.fileImage = fileData + phdr.p_offset; // if there's any padding at the end that's not in the // file, call it the bss. This happens in the "text" // segment if there's only one loadable segment (as for // kernel images). bss.size = phdr.p_memsz - phdr.p_filesz; bss.baseAddr = phdr.p_vaddr + phdr.p_filesz; - } - else if (data.size == 0) { // have text, this must be data + bss.fileImage = NULL; + } else if (data.size == 0) { // have text, this must be data data.baseAddr = phdr.p_vaddr; data.size = phdr.p_filesz; - // remember where the data is for loadSections() - fileDataBits = fileData + phdr.p_offset; + data.fileImage = fileData + phdr.p_offset; // if there's any padding at the end that's not in the // file, call it the bss. Warn if this happens for both // the text & data segments (should only have one bss). @@ -225,6 +221,11 @@ ElfObject::ElfObject(const string &_filename, int _fd, } bss.size = phdr.p_memsz - phdr.p_filesz; bss.baseAddr = phdr.p_vaddr + phdr.p_filesz; + bss.fileImage = NULL; + } else { + warn("More than two loadable segments in ELF object."); + warn("Ignoring segment @ 0x%x length 0x%x.", + phdr.p_vaddr, phdr.p_filesz); } } @@ -242,28 +243,6 @@ ElfObject::ElfObject(const string &_filename, int _fd, bool -ElfObject::loadSections(FunctionalMemory *mem, bool loadPhys) -{ - Addr textAddr = text.baseAddr; - Addr dataAddr = data.baseAddr; - - if (loadPhys) { - textAddr &= (ULL(1) << 40) - 1; - dataAddr &= (ULL(1) << 40) - 1; - } - - // Since we don't really have an MMU and all memory is - // zero-filled, there's no need to set up the BSS segment. - if (text.size != 0) - mem->prot_write(textAddr, fileTextBits, text.size); - if (data.size != 0) - mem->prot_write(dataAddr, fileDataBits, data.size); - - return true; -} - - -bool ElfObject::loadSomeSymbols(SymbolTable *symtab, int binding) { Elf *elf; diff --git a/base/loader/elf_object.hh b/base/loader/elf_object.hh index 66d8b3e63..72c265edd 100644 --- a/base/loader/elf_object.hh +++ b/base/loader/elf_object.hh @@ -35,9 +35,6 @@ class ElfObject : public ObjectFile { protected: - uint8_t *fileTextBits; //!< Pointer to file's text segment image - uint8_t *fileDataBits; //!< Pointer to file's data segment image - /// Helper functions for loadGlobalSymbols() and loadLocalSymbols(). bool loadSomeSymbols(SymbolTable *symtab, int binding); @@ -48,8 +45,6 @@ class ElfObject : public ObjectFile public: virtual ~ElfObject() {} - virtual bool loadSections(FunctionalMemory *mem, - bool loadPhys = false); virtual bool loadGlobalSymbols(SymbolTable *symtab); virtual bool loadLocalSymbols(SymbolTable *symtab); diff --git a/base/loader/object_file.cc b/base/loader/object_file.cc index 1410d05b8..c6dfced1d 100644 --- a/base/loader/object_file.cc +++ b/base/loader/object_file.cc @@ -43,6 +43,8 @@ #include "base/loader/aout_object.hh" #include "base/loader/elf_object.hh" +#include "mem/translating_port.hh" + using namespace std; ObjectFile::ObjectFile(const string &_filename, int _fd, @@ -60,6 +62,32 @@ ObjectFile::~ObjectFile() } +bool +ObjectFile::loadSection(Section *sec, Port *memPort, Addr addrMask) +{ + if (sec->size != 0) { + Addr addr = sec->baseAddr & addrMask; + if (sec->fileImage) { + memPort->writeBlob(addr, sec->fileImage, sec->size); + } + else { + // no image: must be bss + memPort->memsetBlob(addr, 0, sec->size); + } + } + return true; +} + + +bool +ObjectFile::loadSections(Port *memPort, Addr addrMask) +{ + return (loadSection(&text, memPort, addrMask) + && loadSection(&data, memPort, addrMask) + && loadSection(&bss, memPort, addrMask)); +} + + void ObjectFile::close() { diff --git a/base/loader/object_file.hh b/base/loader/object_file.hh index 1b44ae14f..b43989cb5 100644 --- a/base/loader/object_file.hh +++ b/base/loader/object_file.hh @@ -29,11 +29,12 @@ #ifndef __OBJECT_FILE_HH__ #define __OBJECT_FILE_HH__ +#include <limits> #include <string> #include "sim/host.hh" // for Addr -class FunctionalMemory; +class Port; class SymbolTable; class ObjectFile @@ -44,7 +45,7 @@ class ObjectFile UnknownArch, Alpha, SPARC, - MIPS + Mips }; enum OpSys { @@ -72,8 +73,8 @@ class ObjectFile void close(); - virtual bool loadSections(FunctionalMemory *mem, - bool loadPhys = false) = 0; + virtual bool loadSections(Port *memPort, Addr addrMask = + std::numeric_limits<Addr>::max()); virtual bool loadGlobalSymbols(SymbolTable *symtab) = 0; virtual bool loadLocalSymbols(SymbolTable *symtab) = 0; @@ -83,8 +84,9 @@ class ObjectFile protected: struct Section { - Addr baseAddr; - size_t size; + Addr baseAddr; + uint8_t *fileImage; + size_t size; }; Addr entry; @@ -94,8 +96,12 @@ class ObjectFile Section data; Section bss; + bool loadSection(Section *sec, Port *memPort, Addr addrMask); + void setGlobalPointer(Addr global_ptr) { globalPtr = global_ptr; } + public: Addr entryPoint() const { return entry; } + Addr globalPointer() const { return globalPtr; } Addr textBase() const { return text.baseAddr; } diff --git a/base/remote_gdb.cc b/base/remote_gdb.cc index 84093459c..6b85bc680 100644 --- a/base/remote_gdb.cc +++ b/base/remote_gdb.cc @@ -120,16 +120,18 @@ #include <string> #include <unistd.h> +#include "arch/vtophys.hh" #include "base/intmath.hh" #include "base/kgdb.h" #include "base/remote_gdb.hh" #include "base/socket.hh" #include "base/trace.hh" +#include "config/full_system.hh" #include "cpu/exec_context.hh" #include "cpu/static_inst.hh" -#include "mem/functional/physical.hh" +#include "mem/physical.hh" +#include "mem/port.hh" #include "sim/system.hh" -#include "arch/vtophys.hh" using namespace std; using namespace TheISA; @@ -372,7 +374,7 @@ RemoteGDB::acc(Addr va, size_t len) return true; Addr ptbr = context->readMiscReg(AlphaISA::IPR_PALtemp20); - TheISA::PageTableEntry pte = kernel_pte_lookup(pmem, ptbr, va); + TheISA::PageTableEntry pte = TheISA::kernel_pte_lookup(context->getPhysPort(), ptbr, va); if (!pte.valid()) { DPRINTF(GDBAcc, "acc: %#x pte is invalid\n", va); return false; @@ -440,7 +442,7 @@ RemoteGDB::getregs() #ifdef KGDB_FP_REGS for (int i = 0; i < TheISA::NumFloatArchRegs; ++i) { - gdbregs[i + KGDB_REG_F0] = context->readFloatRegInt(i); + gdbregs[i + KGDB_REG_F0] = context->readFloatRegBits(i); } #endif } @@ -467,7 +469,7 @@ RemoteGDB::setregs() #ifdef KGDB_FP_REGS for (int i = 0; i < TheISA::NumFloatArchRegs; ++i) { - context->setFloatRegInt(i, gdbregs[i + KGDB_REG_F0]); + context->setFloatRegBits(i, gdbregs[i + KGDB_REG_F0]); } #endif context->setPC(gdbregs[KGDB_REG_PC]); @@ -632,51 +634,20 @@ RemoteGDB::read(Addr vaddr, size_t size, char *data) static Addr lastaddr = 0; static size_t lastsize = 0; - uint8_t *maddr; - if (vaddr < 10) { DPRINTF(GDBRead, "read: reading memory location zero!\n"); vaddr = lastaddr + lastsize; } DPRINTF(GDBRead, "read: addr=%#x, size=%d", vaddr, size); -#if TRACING_ON - char *d = data; - size_t s = size; -#endif - - lastaddr = vaddr; - lastsize = size; - size_t count = min((Addr)size, - VMPageSize - (vaddr & (VMPageSize - 1))); - - maddr = vtomem(context, vaddr, count); - memcpy(data, maddr, count); - - vaddr += count; - data += count; - size -= count; - - while (size >= VMPageSize) { - maddr = vtomem(context, vaddr, count); - memcpy(data, maddr, VMPageSize); - - vaddr += VMPageSize; - data += VMPageSize; - size -= VMPageSize; - } - - if (size > 0) { - maddr = vtomem(context, vaddr, count); - memcpy(data, maddr, size); - } + context->getVirtPort(context)->readBlob(vaddr, (uint8_t*)data, size); #if TRACING_ON if (DTRACE(GDBRead)) { if (DTRACE(GDBExtra)) { char buf[1024]; - mem2hex(buf, d, s); + mem2hex(buf, data, size); DPRINTFNR(": %s\n", buf); } else DPRINTFNR("\n"); @@ -693,8 +664,6 @@ RemoteGDB::write(Addr vaddr, size_t size, const char *data) static Addr lastaddr = 0; static size_t lastsize = 0; - uint8_t *maddr; - if (vaddr < 10) { DPRINTF(GDBWrite, "write: writing memory location zero!\n"); vaddr = lastaddr + lastsize; @@ -710,32 +679,7 @@ RemoteGDB::write(Addr vaddr, size_t size, const char *data) DPRINTFNR("\n"); } - lastaddr = vaddr; - lastsize = size; - - size_t count = min((Addr)size, - VMPageSize - (vaddr & (VMPageSize - 1))); - - maddr = vtomem(context, vaddr, count); - memcpy(maddr, data, count); - - vaddr += count; - data += count; - size -= count; - - while (size >= VMPageSize) { - maddr = vtomem(context, vaddr, count); - memcpy(maddr, data, VMPageSize); - - vaddr += VMPageSize; - data += VMPageSize; - size -= VMPageSize; - } - - if (size > 0) { - maddr = vtomem(context, vaddr, count); - memcpy(maddr, data, size); - } + context->getVirtPort(context)->writeBlob(vaddr, (uint8_t*)data, size); #ifdef IMB alpha_pal_imb(); diff --git a/base/timebuf.hh b/base/timebuf.hh index 435803fae..f6b5b2781 100644 --- a/base/timebuf.hh +++ b/base/timebuf.hh @@ -31,8 +31,6 @@ #include <vector> -using namespace std; - template <class T> class TimeBuffer { @@ -42,7 +40,7 @@ class TimeBuffer int size; char *data; - vector<char *> index; + std::vector<char *> index; int base; void valid(int idx) diff --git a/base/traceflags.py b/base/traceflags.py index e814a00fb..7dbaac60e 100644 --- a/base/traceflags.py +++ b/base/traceflags.py @@ -142,6 +142,8 @@ baseFlags = [ 'OoOCPU', 'HWPrefetch', 'Stack', + 'SimpleCPU', + 'Sparc', ] # diff --git a/build/SConstruct b/build/SConstruct index 306d3a9dc..28940fc5a 100644 --- a/build/SConstruct +++ b/build/SConstruct @@ -231,6 +231,11 @@ sticky_opts = Options(args=ARGUMENTS) sticky_opts.AddOptions( EnumOption('TARGET_ISA', 'Target ISA', 'alpha', env['ALL_ISA_LIST']), BoolOption('FULL_SYSTEM', 'Full-system support', False), + # There's a bug in scons 0.96.1 that causes ListOptions with list + # values (more than one value) not to be able to be restored from + # a saved option file. If this causes trouble then upgrade to + # scons 0.96.90 or later. + ListOption('CPU_MODELS', 'CPU models', 'all', env['ALL_CPU_LIST']), BoolOption('ALPHA_TLASER', 'Model Alpha TurboLaser platform (vs. Tsunami)', False), BoolOption('NO_FAST_ALLOC', 'Disable fast object allocator', False), @@ -254,12 +259,6 @@ sticky_opts.AddOptions( # Non-sticky options only apply to the current build. nonsticky_opts = Options(args=ARGUMENTS) nonsticky_opts.AddOptions( - # This really should be a sticky option, but there's a bug in - # scons 0.96.1 that causes ListOptions not to be able to be - # restored from a saved option file. It looks like this is fixed - # in 0.96.9, but there's a different bug in that version that means we - # can't just upgrade. - ListOption('CPU_MODELS', 'CPU models', 'all', env['ALL_CPU_LIST']), BoolOption('update_ref', 'Update test reference outputs', False) ) @@ -329,6 +328,11 @@ env.Append(BUILDERS = { 'ConfigFile' : config_builder }) # rename base env base_env = env +help_text = ''' +Usage: scons [scons options] [build options] [target(s)] + +''' + for build_dir in build_dirs: # Make a copy of the default environment to use for this config. env = base_env.Copy() @@ -362,6 +366,11 @@ for build_dir in build_dirs: sticky_opts.Update(env) nonsticky_opts.Update(env) + help_text += "Sticky options for %s:\n" % build_dir \ + + sticky_opts.GenerateHelpText(env) \ + + "\nNon-sticky options for %s:\n" % build_dir \ + + nonsticky_opts.GenerateHelpText(env) + # Process option settings. if not have_fenv and env['USE_FENV']: @@ -410,6 +419,8 @@ for build_dir in build_dirs: build_dir = os.path.join(build_dir, 'test', e.Label), exports = { 'env' : e }, duplicate = False) +Help(help_text) + ################################################### # # Let SCons do its thing. At this point SCons will use the defined diff --git a/configs/test/SysPaths.py b/configs/test/SysPaths.py new file mode 100644 index 000000000..7f231916c --- /dev/null +++ b/configs/test/SysPaths.py @@ -0,0 +1,32 @@ +from m5 import * + +import os.path +import sys + +# Edit the following list to include the possible paths to the binary +# and disk image directories. The first directory on the list that +# exists will be selected. +SYSTEMDIR_PATH = ['/n/poolfs/z/dist/m5/system'] + +SYSTEMDIR = None +for d in SYSTEMDIR_PATH: + if os.path.exists(d): + SYSTEMDIR = d + break + +if not SYSTEMDIR: + print >>sys.stderr, "Can't find a path to system files." + sys.exit(1) + +BINDIR = SYSTEMDIR + '/binaries' +DISKDIR = SYSTEMDIR + '/disks' + +def disk(file): + return '%s/%s' % (DISKDIR, file) + +def binary(file): + return '%s/%s' % (BINDIR, file) + +def script(file): + return '%s/%s' % ('/z/saidi/work/m5.newmem/configs/boot', file) + diff --git a/configs/test/fs.py b/configs/test/fs.py new file mode 100644 index 000000000..ce121bd76 --- /dev/null +++ b/configs/test/fs.py @@ -0,0 +1,215 @@ +from m5 import * +import os +from SysPaths import * + +# Base for tests is directory containing this file. +test_base = os.path.dirname(__file__) + +linux_image = env.get('LINUX_IMAGE', disk('linux-latest.img')) + +class IdeControllerPciData(PciConfigData): + VendorID = 0x8086 + DeviceID = 0x7111 + Command = 0x0 + Status = 0x280 + Revision = 0x0 + ClassCode = 0x01 + SubClassCode = 0x01 + ProgIF = 0x85 + BAR0 = 0x00000001 + BAR1 = 0x00000001 + BAR2 = 0x00000001 + BAR3 = 0x00000001 + BAR4 = 0x00000001 + BAR5 = 0x00000001 + InterruptLine = 0x1f + InterruptPin = 0x01 + BAR0Size = '8B' + BAR1Size = '4B' + BAR2Size = '8B' + BAR3Size = '4B' + BAR4Size = '16B' + +class SinicPciData(PciConfigData): + VendorID = 0x1291 + DeviceID = 0x1293 + Status = 0x0290 + SubClassCode = 0x00 + ClassCode = 0x02 + ProgIF = 0x00 + BAR0 = 0x00000000 + BAR1 = 0x00000000 + BAR2 = 0x00000000 + BAR3 = 0x00000000 + BAR4 = 0x00000000 + BAR5 = 0x00000000 + MaximumLatency = 0x34 + MinimumGrant = 0xb0 + InterruptLine = 0x1e + InterruptPin = 0x01 + BAR0Size = '64kB' + +class NSGigEPciData(PciConfigData): + VendorID = 0x100B + DeviceID = 0x0022 + Status = 0x0290 + SubClassCode = 0x00 + ClassCode = 0x02 + ProgIF = 0x00 + BAR0 = 0x00000001 + BAR1 = 0x00000000 + BAR2 = 0x00000000 + BAR3 = 0x00000000 + BAR4 = 0x00000000 + BAR5 = 0x00000000 + MaximumLatency = 0x34 + MinimumGrant = 0xb0 + InterruptLine = 0x1e + InterruptPin = 0x01 + BAR0Size = '256B' + BAR1Size = '4kB' + +class LinuxRootDisk(IdeDisk): + raw_image = RawDiskImage(image_file=linux_image, read_only=True) + image = CowDiskImage(child=Parent.raw_image, read_only=False) + +class LinuxSwapDisk(IdeDisk): + raw_image = RawDiskImage(image_file = disk('linux-bigswap2.img'), + read_only=True) + image = CowDiskImage(child = Parent.raw_image, read_only=False) + +class SpecwebFilesetDisk(IdeDisk): + raw_image = RawDiskImage(image_file = disk('specweb-fileset.img'), + read_only=True) + image = CowDiskImage(child = Parent.raw_image, read_only=False) + +class BaseTsunami(Tsunami): + cchip = TsunamiCChip(pio_addr=0x801a0000000) + pchip = TsunamiPChip(pio_addr=0x80180000000) + pciconfig = PciConfigAll(pio_addr=0x801fe000000) + fake_sm_chip = IsaFake(pio_addr=0x801fc000370) + + fake_uart1 = IsaFake(pio_addr=0x801fc0002f8) + fake_uart2 = IsaFake(pio_addr=0x801fc0003e8) + fake_uart3 = IsaFake(pio_addr=0x801fc0002e8) + fake_uart4 = IsaFake(pio_addr=0x801fc0003f0) + + fake_ppc = IsaFake(pio_addr=0x801fc0003bc) + + fake_OROM = IsaFake(pio_addr=0x800000a0000, pio_size=0x60000) + + fake_pnp_addr = IsaFake(pio_addr=0x801fc000279) + fake_pnp_write = IsaFake(pio_addr=0x801fc000a79) + fake_pnp_read0 = IsaFake(pio_addr=0x801fc000203) + fake_pnp_read1 = IsaFake(pio_addr=0x801fc000243) + fake_pnp_read2 = IsaFake(pio_addr=0x801fc000283) + fake_pnp_read3 = IsaFake(pio_addr=0x801fc0002c3) + fake_pnp_read4 = IsaFake(pio_addr=0x801fc000303) + fake_pnp_read5 = IsaFake(pio_addr=0x801fc000343) + fake_pnp_read6 = IsaFake(pio_addr=0x801fc000383) + fake_pnp_read7 = IsaFake(pio_addr=0x801fc0003c3) + + fake_ata0 = IsaFake(pio_addr=0x801fc0001f0) + fake_ata1 = IsaFake(pio_addr=0x801fc000170) + + fb = BadDevice(pio_addr=0x801fc0003d0, devicename='FrameBuffer') + io = TsunamiIO(pio_addr=0x801fc000000) + uart = Uart8250(pio_addr=0x801fc0003f8) + ethernet = NSGigE(configdata=NSGigEPciData(), + pci_bus=0, pci_dev=1, pci_func=0) + etherint = NSGigEInt(device=Parent.ethernet) +# ethernet = Sinic(configdata=SinicPciData(), +# pci_bus=0, pci_dev=1, pci_func=0) +# etherint = SinicInt(device=Parent.ethernet) + console = AlphaConsole(pio_addr=0x80200000000, disk=Parent.simple_disk) +# bridge = PciFake(configdata=BridgePciData(), pci_bus=0, pci_dev=2, pci_func=0) + +#class FreeBSDTsunami(BaseTsunami): +# disk0 = FreeBSDRootDisk(delay='0us', driveID='master') +# ide = IdeController(disks=[Parent.disk0], +# configdata=IdeControllerPciData(), +# pci_func=0, pci_dev=0, pci_bus=0) + +class LinuxTsunami(BaseTsunami): + disk0 = LinuxRootDisk(driveID='master') + disk1 = SpecwebFilesetDisk(driveID='slave') + disk2 = LinuxSwapDisk(driveID='master') + ide = IdeController(disks=[Parent.disk0, Parent.disk1, Parent.disk2], + configdata=IdeControllerPciData(), + pci_func=0, pci_dev=0, pci_bus=0) + +class LinuxAlphaSystem(LinuxAlphaSystem): + magicbus = Bus(bus_id=0) + magicbus2 = Bus(bus_id=1) + bridge = Bridge() + physmem = PhysicalMemory(range = AddrRange('128MB')) + c0a = Connector(side_a=Parent.magicbus, side_b=Parent.bridge, side_b_name="side_a") + c0b = Connector(side_a=Parent.magicbus2, side_b=Parent.bridge, side_b_name="side_b") + c1 = Connector(side_a=Parent.physmem, side_b=Parent.magicbus2) + tsunami = LinuxTsunami() + c2 = Connector(side_a=Parent.tsunami.cchip, side_a_name='pio', side_b=Parent.magicbus) + c3 = Connector(side_a=Parent.tsunami.pchip, side_a_name='pio', side_b=Parent.magicbus) + c4 = Connector(side_a=Parent.tsunami.pciconfig, side_a_name='pio', side_b=Parent.magicbus) + c5 = Connector(side_a=Parent.tsunami.fake_sm_chip, side_a_name='pio', side_b=Parent.magicbus) + c6 = Connector(side_a=Parent.tsunami.ethernet, side_a_name='pio', side_b=Parent.magicbus) + c6a = Connector(side_a=Parent.tsunami.ethernet, side_a_name='dma', side_b=Parent.magicbus) + c7 = Connector(side_a=Parent.tsunami.fake_uart1, side_a_name='pio', side_b=Parent.magicbus) + c8 = Connector(side_a=Parent.tsunami.fake_uart2, side_a_name='pio', side_b=Parent.magicbus) + c9 = Connector(side_a=Parent.tsunami.fake_uart3, side_a_name='pio', side_b=Parent.magicbus) + c10 = Connector(side_a=Parent.tsunami.fake_uart4, side_a_name='pio', side_b=Parent.magicbus) + c11 = Connector(side_a=Parent.tsunami.ide, side_a_name='pio', side_b=Parent.magicbus) + c13 = Connector(side_a=Parent.tsunami.ide, side_a_name='dma', side_b=Parent.magicbus) + c12 = Connector(side_a=Parent.tsunami.fake_ppc, side_a_name='pio', side_b=Parent.magicbus) + c14 = Connector(side_a=Parent.tsunami.fake_OROM, side_a_name='pio', side_b=Parent.magicbus) + c16 = Connector(side_a=Parent.tsunami.fake_pnp_addr, side_a_name='pio', side_b=Parent.magicbus) + c17 = Connector(side_a=Parent.tsunami.fake_pnp_write, side_a_name='pio', side_b=Parent.magicbus) + c18 = Connector(side_a=Parent.tsunami.fake_pnp_read0, side_a_name='pio', side_b=Parent.magicbus) + c19 = Connector(side_a=Parent.tsunami.fake_pnp_read1, side_a_name='pio', side_b=Parent.magicbus) + c20 = Connector(side_a=Parent.tsunami.fake_pnp_read2, side_a_name='pio', side_b=Parent.magicbus) + c21 = Connector(side_a=Parent.tsunami.fake_pnp_read3, side_a_name='pio', side_b=Parent.magicbus) + c22 = Connector(side_a=Parent.tsunami.fake_pnp_read4, side_a_name='pio', side_b=Parent.magicbus) + c23 = Connector(side_a=Parent.tsunami.fake_pnp_read5, side_a_name='pio', side_b=Parent.magicbus) + c24 = Connector(side_a=Parent.tsunami.fake_pnp_read6, side_a_name='pio', side_b=Parent.magicbus) + c25 = Connector(side_a=Parent.tsunami.fake_pnp_read7, side_a_name='pio', side_b=Parent.magicbus) + c27 = Connector(side_a=Parent.tsunami.fake_ata0, side_a_name='pio', side_b=Parent.magicbus) + c28 = Connector(side_a=Parent.tsunami.fake_ata1, side_a_name='pio', side_b=Parent.magicbus) + c30 = Connector(side_a=Parent.tsunami.fb, side_a_name='pio', side_b=Parent.magicbus) + c31 = Connector(side_a=Parent.tsunami.io, side_a_name='pio', side_b=Parent.magicbus) + c32 = Connector(side_a=Parent.tsunami.uart, side_a_name='pio', side_b=Parent.magicbus) + c33 = Connector(side_a=Parent.tsunami.console, side_a_name='pio', side_b=Parent.magicbus) + raw_image = RawDiskImage(image_file=disk('linux-latest.img'), + read_only=True) + simple_disk = SimpleDisk(disk=Parent.raw_image) + intrctrl = IntrControl() + cpu = SimpleCPU(mem=Parent.magicbus2) + sim_console = SimConsole(listener=ConsoleListener(port=3456)) + kernel = '/z/saidi/work/m5.newmem/build/vmlinux' + pal = binary('ts_osfpal') + console = binary('console') + boot_osflags = 'root=/dev/hda1 console=ttyS0' +# readfile = os.path.join(test_base, 'halt.sh') + + +BaseCPU.itb = AlphaITB() +BaseCPU.dtb = AlphaDTB() +BaseCPU.system = Parent.any + +class TsunamiRoot(System): + pass + + +def DualRoot(ClientSystem, ServerSystem): + self = Root() + self.client = ClientSystem() + self.server = ServerSystem() + + self.etherdump = EtherDump(file='ethertrace') + self.etherlink = EtherLink(int1 = Parent.client.tsunami.etherint[0], + int2 = Parent.server.tsunami.etherint[0], + dump = Parent.etherdump) + self.clock = '5GHz' + return self + +root = DualRoot(ClientSystem = LinuxAlphaSystem(readfile=script('netperf-stream-nt-client.rcS')), + ServerSystem = LinuxAlphaSystem(readfile=script('netperf-server.rcS'))) + diff --git a/configs/test/hello b/configs/test/hello Binary files differnew file mode 100755 index 000000000..59c0d195c --- /dev/null +++ b/configs/test/hello diff --git a/configs/test/hello_mips b/configs/test/hello_mips Binary files differnew file mode 100755 index 000000000..a3db001ec --- /dev/null +++ b/configs/test/hello_mips diff --git a/configs/test/hello_sparc b/configs/test/hello_sparc Binary files differnew file mode 100755 index 000000000..e254ae33f --- /dev/null +++ b/configs/test/hello_sparc diff --git a/configs/test/test.py b/configs/test/test.py new file mode 100644 index 000000000..695d84b73 --- /dev/null +++ b/configs/test/test.py @@ -0,0 +1,12 @@ +from m5 import * + +class HelloWorld(AlphaLiveProcess): + executable = '../configs/test/hello' + cmd = 'hello' + +magicbus = Bus() +mem = PhysicalMemory() +cpu = SimpleCPU(workload=HelloWorld(), mem=magicbus) +system = System(physmem=mem, cpu=cpu) +system.c1 = Connector(side_a=mem, side_b=magicbus) +root = Root(system=system) diff --git a/cpu/base.cc b/cpu/base.cc index 2eb5f7fd3..9ce458c64 100644 --- a/cpu/base.cc +++ b/cpu/base.cc @@ -65,7 +65,7 @@ BaseCPU::BaseCPU(Params *p) #else BaseCPU::BaseCPU(Params *p) : SimObject(p->name), clock(p->clock), params(p), - number_of_threads(p->numberOfThreads) + number_of_threads(p->numberOfThreads), system(p->system) #endif { DPRINTF(FullCPU, "BaseCPU: Creating object, mem address %#x.\n", this); @@ -229,6 +229,7 @@ BaseCPU::registerExecContexts() { for (int i = 0; i < execContexts.size(); ++i) { ExecContext *xc = execContexts[i]; + #if FULL_SYSTEM int id = params->cpu_id; if (id != -1) diff --git a/cpu/base.hh b/cpu/base.hh index d9d5d2b88..79700c117 100644 --- a/cpu/base.hh +++ b/cpu/base.hh @@ -38,11 +38,8 @@ #include "sim/sim_object.hh" #include "arch/isa_traits.hh" -#if FULL_SYSTEM class System; namespace Kernel { class Statistics; } -#endif - class BranchPred; class ExecContext; @@ -123,8 +120,8 @@ class BaseCPU : public SimObject Tick clock; bool functionTrace; Tick functionTraceStart; -#if FULL_SYSTEM System *system; +#if FULL_SYSTEM int cpu_id; Tick profile; #endif @@ -173,9 +170,9 @@ class BaseCPU : public SimObject */ EventQueue **comLoadEventQueue; -#if FULL_SYSTEM System *system; +#if FULL_SYSTEM /** * Serialize this object to the given output stream. * @param os The stream to serialize to. diff --git a/cpu/cpu_exec_context.cc b/cpu/cpu_exec_context.cc index b7238e73a..ec1e94561 100644 --- a/cpu/cpu_exec_context.cc +++ b/cpu/cpu_exec_context.cc @@ -28,6 +28,7 @@ #include <string> +#include "arch/isa_traits.hh" #include "cpu/base.hh" #include "cpu/cpu_exec_context.hh" #include "cpu/exec_context.hh" @@ -41,10 +42,11 @@ #include "kern/kernel_stats.hh" #include "sim/serialize.hh" #include "sim/sim_exit.hh" -#include "sim/system.hh" #include "arch/stacktrace.hh" #else #include "sim/process.hh" +#include "sim/system.hh" +#include "mem/translating_port.hh" #endif using namespace std; @@ -52,16 +54,16 @@ using namespace std; // constructor #if FULL_SYSTEM CPUExecContext::CPUExecContext(BaseCPU *_cpu, int _thread_num, System *_sys, - AlphaITB *_itb, AlphaDTB *_dtb, - FunctionalMemory *_mem) + AlphaITB *_itb, AlphaDTB *_dtb) : _status(ExecContext::Unallocated), cpu(_cpu), thread_num(_thread_num), - cpu_id(-1), lastActivate(0), lastSuspend(0), mem(_mem), itb(_itb), - dtb(_dtb), system(_sys), memctrl(_sys->memctrl), physmem(_sys->physmem), - profile(NULL), quiesceEvent(this), func_exe_inst(0), storeCondFailures(0) + cpu_id(-1), lastActivate(0), lastSuspend(0), system(_sys), itb(_itb), + dtb(_dtb), profile(NULL), quiesceEvent(this), func_exe_inst(0), + storeCondFailures(0) + { proxy = new ProxyExecContext<CPUExecContext>(this); - memset(®s, 0, sizeof(RegFile)); + regs.clear(); if (cpu->params->profile) { profile = new FunctionProfile(system->kernelSymtab); @@ -76,30 +78,39 @@ CPUExecContext::CPUExecContext(BaseCPU *_cpu, int _thread_num, System *_sys, static ProfileNode dummyNode; profileNode = &dummyNode; profilePC = 3; + + Port *mem_port; + physPort = new FunctionalPort(); + mem_port = system->physmem->getPort("functional"); + mem_port->setPeer(physPort); + physPort->setPeer(mem_port); + + virtPort = new VirtualPort(); + mem_port = system->physmem->getPort("functional"); + mem_port->setPeer(virtPort); + virtPort->setPeer(mem_port); } #else CPUExecContext::CPUExecContext(BaseCPU *_cpu, int _thread_num, - Process *_process, int _asid) + Process *_process, int _asid, MemObject* memobj) : _status(ExecContext::Unallocated), cpu(_cpu), thread_num(_thread_num), cpu_id(-1), lastActivate(0), - lastSuspend(0), process(_process), mem(process->getMemory()), asid(_asid), - func_exe_inst(0), storeCondFailures(0) -{ - memset(®s, 0, sizeof(RegFile)); - proxy = new ProxyExecContext<CPUExecContext>(this); -} - -CPUExecContext::CPUExecContext(BaseCPU *_cpu, int _thread_num, - FunctionalMemory *_mem, int _asid) - : cpu(_cpu), thread_num(_thread_num), process(0), mem(_mem), asid(_asid), + lastSuspend(0), process(_process), asid(_asid), func_exe_inst(0), storeCondFailures(0) { - memset(®s, 0, sizeof(RegFile)); + /* Use this port to for syscall emulation writes to memory. */ + Port *mem_port; + port = new TranslatingPort(process->pTable, false); + mem_port = memobj->getPort("functional"); + mem_port->setPeer(port); + port->setPeer(mem_port); + + regs.clear(); proxy = new ProxyExecContext<CPUExecContext>(this); } CPUExecContext::CPUExecContext(RegFile *regFile) - : cpu(NULL), thread_num(-1), process(NULL), mem(NULL), asid(-1), + : cpu(NULL), thread_num(-1), process(NULL), asid(-1), func_exe_inst(0), storeCondFailures(0) { regs = *regFile; @@ -158,7 +169,6 @@ void CPUExecContext::takeOverFrom(ExecContext *oldContext) { // some things should already be set up - assert(mem == oldContext->getMemPtr()); #if FULL_SYSTEM assert(system == oldContext->getSystemPtr()); #else @@ -277,22 +287,34 @@ CPUExecContext::regStats(const string &name) void CPUExecContext::copyArchRegs(ExecContext *xc) { - // First loop through the integer registers. - for (int i = 0; i < AlphaISA::NumIntRegs; ++i) { - setIntReg(i, xc->readIntReg(i)); - } + TheISA::copyRegs(xc, proxy); +} - // Then loop through the floating point registers. - for (int i = 0; i < AlphaISA::NumFloatRegs; ++i) { - setFloatRegDouble(i, xc->readFloatRegDouble(i)); - setFloatRegInt(i, xc->readFloatRegInt(i)); - } +#if FULL_SYSTEM +VirtualPort* +CPUExecContext::getVirtPort(ExecContext *xc) +{ + if (!xc) + return virtPort; - // Copy misc. registers - regs.miscRegs.copyMiscRegs(xc); + VirtualPort *vp; + Port *mem_port; - // Lastly copy PC/NPC - setPC(xc->readPC()); - setNextPC(xc->readNextPC()); + vp = new VirtualPort(xc); + mem_port = system->physmem->getPort("functional"); + mem_port->setPeer(vp); + vp->setPeer(mem_port); + return vp; } +void +CPUExecContext::delVirtPort(VirtualPort *vp) +{ +// assert(!vp->nullExecContext()); + delete vp->getPeer(); + delete vp; +} + + +#endif + diff --git a/cpu/cpu_exec_context.hh b/cpu/cpu_exec_context.hh index beaf67352..2c06a7b3b 100644 --- a/cpu/cpu_exec_context.hh +++ b/cpu/cpu_exec_context.hh @@ -32,16 +32,13 @@ #include "arch/isa_traits.hh" #include "config/full_system.hh" #include "cpu/exec_context.hh" -#include "mem/functional/functional.hh" -#include "mem/mem_req.hh" +#include "mem/physical.hh" +#include "mem/request.hh" #include "sim/byteswap.hh" #include "sim/eventq.hh" #include "sim/host.hh" #include "sim/serialize.hh" -// forward declaration: see functional_memory.hh -class FunctionalMemory; -class PhysicalMemory; class BaseCPU; #if FULL_SYSTEM @@ -51,11 +48,16 @@ class BaseCPU; class FunctionProfile; class ProfileNode; -class MemoryController; +class FunctionalPort; +class PhysicalPort; + #else // !FULL_SYSTEM #include "sim/process.hh" +#include "mem/page_table.hh" +class TranslatingPort; + #endif // FULL_SYSTEM @@ -72,6 +74,8 @@ class CPUExecContext typedef TheISA::MachInst MachInst; typedef TheISA::MiscRegFile MiscRegFile; typedef TheISA::MiscReg MiscReg; + typedef TheISA::FloatReg FloatReg; + typedef TheISA::FloatRegBits FloatRegBits; public: typedef ExecContext::Status Status; @@ -118,17 +122,20 @@ class CPUExecContext Tick lastActivate; Tick lastSuspend; + System *system; + + #if FULL_SYSTEM - FunctionalMemory *mem; AlphaITB *itb; AlphaDTB *dtb; - System *system; - // the following two fields are redundant, since we can always - // look them up through the system pointer, but we'll leave them - // here for now for convenience - MemoryController *memctrl; - PhysicalMemory *physmem; + /** A functional port outgoing only for functional accesses to physical + * addresses.*/ + FunctionalPort *physPort; + + /** A functional port, outgoing only, for functional accesse to virtual + * addresses. That doen't require execution context information */ + VirtualPort *virtPort; FunctionProfile *profile; ProfileNode *profileNode; @@ -162,9 +169,10 @@ class CPUExecContext void profileSample(); #else - Process *process; + /// Port that syscalls can use to access memory (provides translation step). + TranslatingPort *port; - FunctionalMemory *mem; // functional storage for process address space + Process *process; // Address space ID. Note that this is used for TIMING cache // simulation only; all functional memory accesses should use @@ -200,11 +208,10 @@ class CPUExecContext // constructor: initialize context from given process structure #if FULL_SYSTEM CPUExecContext(BaseCPU *_cpu, int _thread_num, System *_system, - AlphaITB *_itb, AlphaDTB *_dtb, FunctionalMemory *_dem); + AlphaITB *_itb, AlphaDTB *_dtb); #else - CPUExecContext(BaseCPU *_cpu, int _thread_num, Process *_process, int _asid); - CPUExecContext(BaseCPU *_cpu, int _thread_num, FunctionalMemory *_mem, - int _asid); + CPUExecContext(BaseCPU *_cpu, int _thread_num, Process *_process, int _asid, + MemObject *memobj); // Constructor to use XC to pass reg file around. Not used for anything // else. CPUExecContext(RegFile *regFile); @@ -227,74 +234,67 @@ class CPUExecContext #if FULL_SYSTEM System *getSystemPtr() { return system; } - PhysicalMemory *getPhysMemPtr() { return physmem; } - AlphaITB *getITBPtr() { return itb; } AlphaDTB *getDTBPtr() { return dtb; } - bool validInstAddr(Addr addr) { return true; } - bool validDataAddr(Addr addr) { return true; } int getInstAsid() { return regs.instAsid(); } int getDataAsid() { return regs.dataAsid(); } - Fault translateInstReq(MemReqPtr &req) + Fault translateInstReq(RequestPtr &req) { - return itb->translate(req); + return itb->translate(req, proxy); } - Fault translateDataReadReq(MemReqPtr &req) + Fault translateDataReadReq(RequestPtr &req) { - return dtb->translate(req, false); + return dtb->translate(req, proxy, false); } - Fault translateDataWriteReq(MemReqPtr &req) + Fault translateDataWriteReq(RequestPtr &req) { - return dtb->translate(req, true); + return dtb->translate(req, proxy, true); } -#else - Process *getProcessPtr() { return process; } + FunctionalPort *getPhysPort() { return physPort; } - bool validInstAddr(Addr addr) - { return process->validInstAddr(addr); } + /** Return a virtual port. If no exec context is specified then a static + * port is returned. Otherwise a port is created and returned. It must be + * deleted by deleteVirtPort(). */ + VirtualPort *getVirtPort(ExecContext *xc); - bool validDataAddr(Addr addr) - { return process->validDataAddr(addr); } + void delVirtPort(VirtualPort *vp); + +#else + TranslatingPort *getMemPort() { return port; } + + Process *getProcessPtr() { return process; } int getInstAsid() { return asid; } int getDataAsid() { return asid; } - Fault dummyTranslation(MemReqPtr &req) - { -#if 0 - assert((req->vaddr >> 48 & 0xffff) == 0); -#endif - - // put the asid in the upper 16 bits of the paddr - req->paddr = req->vaddr & ~((Addr)0xffff << sizeof(Addr) * 8 - 16); - req->paddr = req->paddr | (Addr)req->asid << sizeof(Addr) * 8 - 16; - return NoFault; - } - Fault translateInstReq(MemReqPtr &req) + Fault translateInstReq(RequestPtr &req) { - return dummyTranslation(req); + return process->pTable->translate(req); } - Fault translateDataReadReq(MemReqPtr &req) + + Fault translateDataReadReq(RequestPtr &req) { - return dummyTranslation(req); + return process->pTable->translate(req); } - Fault translateDataWriteReq(MemReqPtr &req) + + Fault translateDataWriteReq(RequestPtr &req) { - return dummyTranslation(req); + return process->pTable->translate(req); } #endif +/* template <class T> - Fault read(MemReqPtr &req, T &data) + Fault read(RequestPtr &req, T &data) { -#if FULL_SYSTEM && defined(TARGET_ALPHA) +#if FULL_SYSTEM && THE_ISA == ALPHA_ISA if (req->flags & LOCKED) { req->xc->setMiscReg(TheISA::Lock_Addr_DepTag, req->paddr); req->xc->setMiscReg(TheISA::Lock_Flag_DepTag, true); @@ -302,15 +302,15 @@ class CPUExecContext #endif Fault error; - error = mem->read(req, data); + error = mem->prot_read(req->paddr, data, req->size); data = LittleEndianGuest::gtoh(data); return error; } template <class T> - Fault write(MemReqPtr &req, T &data) + Fault write(RequestPtr &req, T &data) { -#if FULL_SYSTEM && defined(TARGET_ALPHA) +#if FULL_SYSTEM && THE_ISA == ALPHA_ISA ExecContext *xc; // If this is a store conditional, act appropriately @@ -356,9 +356,9 @@ class CPUExecContext } #endif - return mem->write(req, (T)LittleEndianGuest::htog(data)); + return mem->prot_write(req->paddr, (T)htog(data), req->size); } - +*/ virtual bool misspeculating(); @@ -369,17 +369,17 @@ class CPUExecContext inst = new_inst; } - Fault instRead(MemReqPtr &req) + Fault instRead(RequestPtr &req) { - return mem->read(req, inst); + panic("instRead not implemented"); + // return funcPhysMem->read(req, inst); + return NoFault; } void setCpuId(int id) { cpu_id = id; } int readCpuId() { return cpu_id; } - FunctionalMemory *getMemPtr() { return mem; } - void copyArchRegs(ExecContext *xc); // @@ -387,93 +387,103 @@ class CPUExecContext // uint64_t readIntReg(int reg_idx) { - return regs.intRegFile[reg_idx]; + return regs.readIntReg(reg_idx); } - float readFloatRegSingle(int reg_idx) + FloatReg readFloatReg(int reg_idx, int width) { - return (float)regs.floatRegFile.d[reg_idx]; + return regs.readFloatReg(reg_idx, width); } - double readFloatRegDouble(int reg_idx) + FloatReg readFloatReg(int reg_idx) { - return regs.floatRegFile.d[reg_idx]; + return regs.readFloatReg(reg_idx); } - uint64_t readFloatRegInt(int reg_idx) + FloatRegBits readFloatRegBits(int reg_idx, int width) { - return regs.floatRegFile.q[reg_idx]; + return regs.readFloatRegBits(reg_idx, width); + } + + FloatRegBits readFloatRegBits(int reg_idx) + { + return regs.readFloatRegBits(reg_idx); } void setIntReg(int reg_idx, uint64_t val) { - regs.intRegFile[reg_idx] = val; + regs.setIntReg(reg_idx, val); } - void setFloatRegSingle(int reg_idx, float val) + void setFloatReg(int reg_idx, FloatReg val, int width) { - regs.floatRegFile.d[reg_idx] = (double)val; + regs.setFloatReg(reg_idx, val, width); } - void setFloatRegDouble(int reg_idx, double val) + void setFloatReg(int reg_idx, FloatReg val) { - regs.floatRegFile.d[reg_idx] = val; + regs.setFloatReg(reg_idx, val); } - void setFloatRegInt(int reg_idx, uint64_t val) + void setFloatRegBits(int reg_idx, FloatRegBits val, int width) { - regs.floatRegFile.q[reg_idx] = val; + regs.setFloatRegBits(reg_idx, val, width); + } + + void setFloatRegBits(int reg_idx, FloatRegBits val) + { + regs.setFloatRegBits(reg_idx, val); } uint64_t readPC() { - return regs.pc; + return regs.readPC(); } void setPC(uint64_t val) { - regs.pc = val; + regs.setPC(val); } uint64_t readNextPC() { - return regs.npc; + return regs.readNextPC(); } void setNextPC(uint64_t val) { - regs.npc = val; + regs.setNextPC(val); } uint64_t readNextNPC() { - return regs.nnpc; + return regs.readNextNPC(); } void setNextNPC(uint64_t val) { - regs.nnpc = val; + regs.setNextNPC(val); } MiscReg readMiscReg(int misc_reg) { - return regs.miscRegs.readReg(misc_reg); + return regs.readMiscReg(misc_reg); } MiscReg readMiscRegWithEffect(int misc_reg, Fault &fault) { - return regs.miscRegs.readRegWithEffect(misc_reg, fault, proxy); + return regs.readMiscRegWithEffect(misc_reg, fault, proxy); } Fault setMiscReg(int misc_reg, const MiscReg &val) { - return regs.miscRegs.setReg(misc_reg, val); + return regs.setMiscReg(misc_reg, val); } Fault setMiscRegWithEffect(int misc_reg, const MiscReg &val) { - return regs.miscRegs.setRegWithEffect(misc_reg, val, proxy); + return regs.setMiscRegWithEffect(misc_reg, val, proxy); } unsigned readStCondFailures() { return storeCondFailures; } @@ -481,26 +491,26 @@ class CPUExecContext void setStCondFailures(unsigned sc_failures) { storeCondFailures = sc_failures; } - void clearArchRegs() { memset(®s, 0, sizeof(regs)); } + void clearArchRegs() { regs.clear(); } #if FULL_SYSTEM int readIntrFlag() { return regs.intrflag; } void setIntrFlag(int val) { regs.intrflag = val; } Fault hwrei(); - bool inPalMode() { return AlphaISA::PcPAL(regs.pc); } + bool inPalMode() { return AlphaISA::PcPAL(regs.readPC()); } bool simPalCheck(int palFunc); #endif #if !FULL_SYSTEM TheISA::IntReg getSyscallArg(int i) { - return regs.intRegFile[TheISA::ArgumentReg0 + i]; + return regs.readIntReg(TheISA::ArgumentReg0 + i); } // used to shift args for indirect syscall void setSyscallArg(int i, TheISA::IntReg val) { - regs.intRegFile[TheISA::ArgumentReg0 + i] = val; + regs.setIntReg(TheISA::ArgumentReg0 + i, val); } void setSyscallReturn(SyscallReturn return_value) @@ -508,15 +518,21 @@ class CPUExecContext TheISA::setSyscallReturn(return_value, ®s); } - void syscall() + void syscall(int64_t callnum) { - process->syscall(proxy); + process->syscall(callnum, proxy); } Counter readFuncExeInst() { return func_exe_inst; } void setFuncExeInst(Counter new_val) { func_exe_inst = new_val; } #endif + + void changeRegFileContext(RegFile::ContextParam param, + RegFile::ContextVal val) + { + regs.changeContext(param, val); + } }; diff --git a/cpu/exec_context.hh b/cpu/exec_context.hh index 2b6c41bd7..1f26183ab 100644 --- a/cpu/exec_context.hh +++ b/cpu/exec_context.hh @@ -30,21 +30,21 @@ #define __CPU_EXEC_CONTEXT_HH__ #include "config/full_system.hh" -#include "mem/mem_req.hh" +#include "mem/request.hh" #include "sim/faults.hh" #include "sim/host.hh" #include "sim/serialize.hh" #include "sim/byteswap.hh" -// forward declaration: see functional_memory.hh // @todo: Figure out a more architecture independent way to obtain the ITB and // DTB pointers. class AlphaDTB; class AlphaITB; class BaseCPU; class Event; -class FunctionalMemory; -class PhysicalMemory; +class TranslatingPort; +class FunctionalPort; +class VirtualPort; class Process; class System; @@ -54,6 +54,8 @@ class ExecContext typedef TheISA::RegFile RegFile; typedef TheISA::MachInst MachInst; typedef TheISA::IntReg IntReg; + typedef TheISA::FloatReg FloatReg; + typedef TheISA::FloatRegBits FloatRegBits; typedef TheISA::MiscRegFile MiscRegFile; typedef TheISA::MiscReg MiscReg; public: @@ -87,17 +89,21 @@ class ExecContext virtual int readCpuId() = 0; - virtual FunctionalMemory *getMemPtr() = 0; - #if FULL_SYSTEM virtual System *getSystemPtr() = 0; - virtual PhysicalMemory *getPhysMemPtr() = 0; - virtual AlphaITB *getITBPtr() = 0; virtual AlphaDTB * getDTBPtr() = 0; + + virtual FunctionalPort *getPhysPort() = 0; + + virtual VirtualPort *getVirtPort(ExecContext *xc = NULL) = 0; + + virtual void delVirtPort(VirtualPort *vp) = 0; #else + virtual TranslatingPort *getMemPort() = 0; + virtual Process *getProcessPtr() = 0; #endif @@ -143,16 +149,14 @@ class ExecContext virtual int getThreadNum() = 0; - virtual bool validInstAddr(Addr addr) = 0; - virtual bool validDataAddr(Addr addr) = 0; virtual int getInstAsid() = 0; virtual int getDataAsid() = 0; - virtual Fault translateInstReq(MemReqPtr &req) = 0; + virtual Fault translateInstReq(RequestPtr &req) = 0; - virtual Fault translateDataReadReq(MemReqPtr &req) = 0; + virtual Fault translateDataReadReq(RequestPtr &req) = 0; - virtual Fault translateDataWriteReq(MemReqPtr &req) = 0; + virtual Fault translateDataWriteReq(RequestPtr &req) = 0; // Also somewhat obnoxious. Really only used for the TLB fault. // However, may be quite useful in SPARC. @@ -167,19 +171,23 @@ class ExecContext // virtual uint64_t readIntReg(int reg_idx) = 0; - virtual float readFloatRegSingle(int reg_idx) = 0; + virtual FloatReg readFloatReg(int reg_idx, int width) = 0; - virtual double readFloatRegDouble(int reg_idx) = 0; + virtual FloatReg readFloatReg(int reg_idx) = 0; - virtual uint64_t readFloatRegInt(int reg_idx) = 0; + virtual FloatRegBits readFloatRegBits(int reg_idx, int width) = 0; + + virtual FloatRegBits readFloatRegBits(int reg_idx) = 0; virtual void setIntReg(int reg_idx, uint64_t val) = 0; - virtual void setFloatRegSingle(int reg_idx, float val) = 0; + virtual void setFloatReg(int reg_idx, FloatReg val, int width) = 0; + + virtual void setFloatReg(int reg_idx, FloatReg val) = 0; - virtual void setFloatRegDouble(int reg_idx, double val) = 0; + virtual void setFloatRegBits(int reg_idx, FloatRegBits val) = 0; - virtual void setFloatRegInt(int reg_idx, uint64_t val) = 0; + virtual void setFloatRegBits(int reg_idx, FloatRegBits val, int width) = 0; virtual uint64_t readPC() = 0; @@ -189,6 +197,10 @@ class ExecContext virtual void setNextPC(uint64_t val) = 0; + virtual uint64_t readNextNPC() = 0; + + virtual void setNextNPC(uint64_t val) = 0; + virtual MiscReg readMiscReg(int misc_reg) = 0; virtual MiscReg readMiscRegWithEffect(int misc_reg, Fault &fault) = 0; @@ -222,13 +234,16 @@ class ExecContext virtual void setSyscallReturn(SyscallReturn return_value) = 0; - virtual void syscall() = 0; + virtual void syscall(int64_t callnum) = 0; // Same with st cond failures. virtual Counter readFuncExeInst() = 0; virtual void setFuncExeInst(Counter new_val) = 0; #endif + + virtual void changeRegFileContext(RegFile::ContextParam param, + RegFile::ContextVal val) = 0; }; template <class XC> @@ -249,17 +264,21 @@ class ProxyExecContext : public ExecContext int readCpuId() { return actualXC->readCpuId(); } - FunctionalMemory *getMemPtr() { return actualXC->getMemPtr(); } - #if FULL_SYSTEM System *getSystemPtr() { return actualXC->getSystemPtr(); } - PhysicalMemory *getPhysMemPtr() { return actualXC->getPhysMemPtr(); } - AlphaITB *getITBPtr() { return actualXC->getITBPtr(); } AlphaDTB *getDTBPtr() { return actualXC->getDTBPtr(); } + + FunctionalPort *getPhysPort() { return actualXC->getPhysPort(); } + + VirtualPort *getVirtPort(ExecContext *xc = NULL) { return actualXC->getVirtPort(xc); } + + void delVirtPort(VirtualPort *vp) { return actualXC->delVirtPort(vp); } #else + TranslatingPort *getMemPort() { return actualXC->getMemPort(); } + Process *getProcessPtr() { return actualXC->getProcessPtr(); } #endif @@ -305,18 +324,16 @@ class ProxyExecContext : public ExecContext int getThreadNum() { return actualXC->getThreadNum(); } - bool validInstAddr(Addr addr) { return actualXC->validInstAddr(addr); } - bool validDataAddr(Addr addr) { return actualXC->validDataAddr(addr); } int getInstAsid() { return actualXC->getInstAsid(); } int getDataAsid() { return actualXC->getDataAsid(); } - Fault translateInstReq(MemReqPtr &req) + Fault translateInstReq(RequestPtr &req) { return actualXC->translateInstReq(req); } - Fault translateDataReadReq(MemReqPtr &req) + Fault translateDataReadReq(RequestPtr &req) { return actualXC->translateDataReadReq(req); } - Fault translateDataWriteReq(MemReqPtr &req) + Fault translateDataWriteReq(RequestPtr &req) { return actualXC->translateDataWriteReq(req); } // @todo: Do I need this? @@ -333,26 +350,32 @@ class ProxyExecContext : public ExecContext uint64_t readIntReg(int reg_idx) { return actualXC->readIntReg(reg_idx); } - float readFloatRegSingle(int reg_idx) - { return actualXC->readFloatRegSingle(reg_idx); } + FloatReg readFloatReg(int reg_idx, int width) + { return actualXC->readFloatReg(reg_idx, width); } + + FloatReg readFloatReg(int reg_idx) + { return actualXC->readFloatReg(reg_idx); } - double readFloatRegDouble(int reg_idx) - { return actualXC->readFloatRegDouble(reg_idx); } + FloatRegBits readFloatRegBits(int reg_idx, int width) + { return actualXC->readFloatRegBits(reg_idx, width); } - uint64_t readFloatRegInt(int reg_idx) - { return actualXC->readFloatRegInt(reg_idx); } + FloatRegBits readFloatRegBits(int reg_idx) + { return actualXC->readFloatRegBits(reg_idx); } void setIntReg(int reg_idx, uint64_t val) { actualXC->setIntReg(reg_idx, val); } - void setFloatRegSingle(int reg_idx, float val) - { actualXC->setFloatRegSingle(reg_idx, val); } + void setFloatReg(int reg_idx, FloatReg val, int width) + { actualXC->setFloatReg(reg_idx, val, width); } - void setFloatRegDouble(int reg_idx, double val) - { actualXC->setFloatRegDouble(reg_idx, val); } + void setFloatReg(int reg_idx, FloatReg val) + { actualXC->setFloatReg(reg_idx, val); } - void setFloatRegInt(int reg_idx, uint64_t val) - { actualXC->setFloatRegInt(reg_idx, val); } + void setFloatRegBits(int reg_idx, FloatRegBits val, int width) + { actualXC->setFloatRegBits(reg_idx, val, width); } + + void setFloatRegBits(int reg_idx, FloatRegBits val) + { actualXC->setFloatRegBits(reg_idx, val); } uint64_t readPC() { return actualXC->readPC(); } @@ -362,6 +385,10 @@ class ProxyExecContext : public ExecContext void setNextPC(uint64_t val) { actualXC->setNextPC(val); } + uint64_t readNextNPC() { return actualXC->readNextNPC(); } + + void setNextNPC(uint64_t val) { actualXC->setNextNPC(val); } + MiscReg readMiscReg(int misc_reg) { return actualXC->readMiscReg(misc_reg); } @@ -405,13 +432,19 @@ class ProxyExecContext : public ExecContext void setSyscallReturn(SyscallReturn return_value) { actualXC->setSyscallReturn(return_value); } - void syscall() { actualXC->syscall(); } + void syscall(int64_t callnum) { actualXC->syscall(callnum); } Counter readFuncExeInst() { return actualXC->readFuncExeInst(); } void setFuncExeInst(Counter new_val) { return actualXC->setFuncExeInst(new_val); } #endif + + void changeRegFileContext(RegFile::ContextParam param, + RegFile::ContextVal val) + { + actualXC->changeRegFileContext(param, val); + } }; #endif diff --git a/cpu/exetrace.cc b/cpu/exetrace.cc index 84b5eacf7..0ed3b43c4 100644 --- a/cpu/exetrace.cc +++ b/cpu/exetrace.cc @@ -29,14 +29,12 @@ #include <fstream> #include <iomanip> -#include "sim/param.hh" -#include "encumbered/cpu/full/dyn_inst.hh" -#include "encumbered/cpu/full/spec_state.hh" -#include "encumbered/cpu/full/issue.hh" -#include "cpu/exetrace.hh" #include "base/loader/symtab.hh" #include "cpu/base.hh" +#include "cpu/exetrace.hh" #include "cpu/static_inst.hh" +#include "sim/param.hh" +#include "sim/system.hh" using namespace std; @@ -130,10 +128,11 @@ Trace::InstRecord::dump(ostream &outs) outs << " A=0x" << hex << addr; if (flags[PRINT_INT_REGS] && regs_valid) { - for (int i = 0; i < 32;) + for (int i = 0; i < TheISA::NumIntRegs;) for (int j = i + 1; i <= j; i++) - ccprintf(outs, "r%02d = %#018x%s", i, iregs->regs[i], - ((i == j) ? "\n" : " ")); + ccprintf(outs, "r%02d = %#018x%s", i, + iregs->regs.readReg(i), + ((i == j) ? "\n" : " ")); outs << "\n"; } diff --git a/cpu/exetrace.hh b/cpu/exetrace.hh index 67d042ec8..a26cdc517 100644 --- a/cpu/exetrace.hh +++ b/cpu/exetrace.hh @@ -163,7 +163,7 @@ InstRecord::setRegs(const IntRegFile ®s) if (!iregs) iregs = new iRegFile; - memcpy(&iregs->regs, regs, sizeof(IntRegFile)); + memcpy(&iregs->regs, ®s, sizeof(IntRegFile)); regs_valid = true; } diff --git a/cpu/o3/alpha_cpu.hh b/cpu/o3/alpha_cpu.hh index 0352e9972..8e1e0f42a 100644 --- a/cpu/o3/alpha_cpu.hh +++ b/cpu/o3/alpha_cpu.hh @@ -208,7 +208,7 @@ class AlphaFullCPU : public FullO3CPU<Impl> template <class T> Fault read(MemReqPtr &req, T &data) { -#if FULL_SYSTEM && defined(TARGET_ALPHA) +#if FULL_SYSTEM && THE_ISA == ALPHA_ISA if (req->flags & LOCKED) { req->xc->setMiscReg(TheISA::Lock_Addr_DepTag, req->paddr); req->xc->setMiscReg(TheISA::Lock_Flag_DepTag, true); @@ -230,7 +230,7 @@ class AlphaFullCPU : public FullO3CPU<Impl> template <class T> Fault write(MemReqPtr &req, T &data) { -#if FULL_SYSTEM && defined(TARGET_ALPHA) +#if FULL_SYSTEM && THE_ISA == ALPHA_ISA ExecContext *xc; // If this is a store conditional, act appropriately diff --git a/cpu/o3/alpha_cpu_impl.hh b/cpu/o3/alpha_cpu_impl.hh index 9f1fa24f6..7c4c2b969 100644 --- a/cpu/o3/alpha_cpu_impl.hh +++ b/cpu/o3/alpha_cpu_impl.hh @@ -175,10 +175,8 @@ AlphaFullCPU<Impl>::copyToXC() for (int i = 0; i < AlphaISA::NumFloatRegs; ++i) { renamed_reg = this->renameMap.lookup(i + AlphaISA::FP_Base_DepTag); - this->cpuXC->setFloatRegDouble(i, - this->regFile.readFloatRegDouble(renamed_reg)); - this->cpuXC->setFloatRegInt(i, - this->regFile.readFloatRegInt(renamed_reg)); + this->cpuXC->setFloatRegBits(i, + this->regFile.readFloatRegBits(renamed_reg)); } this->cpuXC->setMiscReg(AlphaISA::Fpcr_DepTag, @@ -223,10 +221,8 @@ AlphaFullCPU<Impl>::copyFromXC() for (int i = 0; i < AlphaISA::NumFloatRegs; ++i) { renamed_reg = this->renameMap.lookup(i + AlphaISA::FP_Base_DepTag); - this->regFile.setFloatRegDouble(renamed_reg, - this->cpuXC->readFloatRegDouble(i)); - this->regFile.setFloatRegInt(renamed_reg, - this->cpuXC->readFloatRegInt(i)); + this->regFile.setFloatRegBits(renamed_reg, + this->cpuXC->readFloatRegBits(i)); } // Then loop through the misc registers. diff --git a/cpu/o3/alpha_dyn_inst.hh b/cpu/o3/alpha_dyn_inst.hh index e7f7d3a57..5b8a05e5c 100644 --- a/cpu/o3/alpha_dyn_inst.hh +++ b/cpu/o3/alpha_dyn_inst.hh @@ -152,19 +152,24 @@ class AlphaDynInst : public BaseDynInst<Impl> return this->cpu->readIntReg(_srcRegIdx[idx]); } - float readFloatRegSingle(const StaticInst *si, int idx) + FloatReg readFloatReg(const StaticInst *si, int idx, int width) { - return this->cpu->readFloatRegSingle(_srcRegIdx[idx]); + return this->cpu->readFloatReg(_srcRegIdx[idx], width); } - double readFloatRegDouble(const StaticInst *si, int idx) + FloatReg readFloatReg(const StaticInst *si, int idx) { - return this->cpu->readFloatRegDouble(_srcRegIdx[idx]); + return this->cpu->readFloatReg(_srcRegIdx[idx]); } - uint64_t readFloatRegInt(const StaticInst *si, int idx) + FloatRegBits readFloatRegBits(const StaticInst *si, int idx, int width) { - return this->cpu->readFloatRegInt(_srcRegIdx[idx]); + return this->cpu->readFloatRegBits(_srcRegIdx[idx], width); + } + + FloatRegBits readFloatRegBits(const StaticInst *si, int idx) + { + return this->cpu->readFloatRegBits(_srcRegIdx[idx]); } /** @todo: Make results into arrays so they can handle multiple dest @@ -176,21 +181,28 @@ class AlphaDynInst : public BaseDynInst<Impl> this->instResult.integer = val; } - void setFloatRegSingle(const StaticInst *si, int idx, float val) + void setFloatReg(const StaticInst *si, int idx, FloatReg val, int width) { - this->cpu->setFloatRegSingle(_destRegIdx[idx], val); + this->cpu->setFloatReg(_destRegIdx[idx], val, width); this->instResult.fp = val; } - void setFloatRegDouble(const StaticInst *si, int idx, double val) + void setFloatReg(const StaticInst *si, int idx, FloatReg val) { - this->cpu->setFloatRegDouble(_destRegIdx[idx], val); + this->cpu->setFloatReg(_destRegIdx[idx], val); this->instResult.dbl = val; } - void setFloatRegInt(const StaticInst *si, int idx, uint64_t val) + void setFloatRegBits(const StaticInst *si, int idx, + FloatRegBits val, int width) + { + this->cpu->setFloatRegBits(_destRegIdx[idx], val, width); + this->instResult.integer = val; + } + + void setFloatRegBits(const StaticInst *si, int idx, FloatRegBits val) { - this->cpu->setFloatRegInt(_destRegIdx[idx], val); + this->cpu->setFloatRegBits(_destRegIdx[idx], val); this->instResult.integer = val; } diff --git a/cpu/o3/cpu.cc b/cpu/o3/cpu.cc index 62d68bb33..a268dbc23 100644 --- a/cpu/o3/cpu.cc +++ b/cpu/o3/cpu.cc @@ -258,8 +258,7 @@ FullO3CPU<Impl>::init() // Then loop through the floating point registers. for (int i = 0; i < TheISA::NumFloatRegs; ++i) { - regFile.floatRegFile[i].d = src_xc->readFloatRegDouble(i); - regFile.floatRegFile[i].q = src_xc->readFloatRegInt(i); + regFile.floatRegFile.setRegBits(i, src_xc->readRegBits(i)) } /* // Then loop through the misc registers. @@ -348,24 +347,31 @@ FullO3CPU<Impl>::readIntReg(int reg_idx) } template <class Impl> -float -FullO3CPU<Impl>::readFloatRegSingle(int reg_idx) +FloatReg +FullO3CPU<Impl>::readFloatReg(int reg_idx, int width) { - return regFile.readFloatRegSingle(reg_idx); + return regFile.readFloatReg(reg_idx, width); } template <class Impl> -double -FullO3CPU<Impl>::readFloatRegDouble(int reg_idx) +FloatReg +FullO3CPU<Impl>::readFloatReg(int reg_idx) { - return regFile.readFloatRegDouble(reg_idx); + return regFile.readFloatReg(reg_idx); } template <class Impl> -uint64_t -FullO3CPU<Impl>::readFloatRegInt(int reg_idx) +FloatRegBits +FullO3CPU<Impl>::readFloatRegBits(int reg_idx, int width) +{ + return regFile.readFloatRegBits(reg_idx, width); +} + +template <class Impl> +FloatRegBits +FullO3CPU<Impl>::readFloatRegBits(int reg_idx) { - return regFile.readFloatRegInt(reg_idx); + return regFile.readFloatRegBits(reg_idx); } template <class Impl> @@ -377,23 +383,30 @@ FullO3CPU<Impl>::setIntReg(int reg_idx, uint64_t val) template <class Impl> void -FullO3CPU<Impl>::setFloatRegSingle(int reg_idx, float val) +FullO3CPU<Impl>::setFloatReg(int reg_idx, FloatReg val, int width) +{ + regFile.setFloatReg(reg_idx, val, width); +} + +template <class Impl> +void +FullO3CPU<Impl>::setFloatReg(int reg_idx, FloatReg val) { - regFile.setFloatRegSingle(reg_idx, val); + regFile.setFloatReg(reg_idx, val); } template <class Impl> void -FullO3CPU<Impl>::setFloatRegDouble(int reg_idx, double val) +FullO3CPU<Impl>::setFloatRegBits(int reg_idx, FloatRegBits val, int width) { - regFile.setFloatRegDouble(reg_idx, val); + regFile.setFloatRegBits(reg_idx, val, width); } template <class Impl> void -FullO3CPU<Impl>::setFloatRegInt(int reg_idx, uint64_t val) +FullO3CPU<Impl>::setFloatRegBits(int reg_idx, FloatRegBits val) { - regFile.setFloatRegInt(reg_idx, val); + regFile.setFloatRegBits(reg_idx, val); } template <class Impl> diff --git a/cpu/o3/cpu.hh b/cpu/o3/cpu.hh index 6577e46e4..f7c80e8a1 100644 --- a/cpu/o3/cpu.hh +++ b/cpu/o3/cpu.hh @@ -170,19 +170,23 @@ class FullO3CPU : public BaseFullCPU // uint64_t readIntReg(int reg_idx); - float readFloatRegSingle(int reg_idx); + FloatReg readFloatReg(int reg_idx); - double readFloatRegDouble(int reg_idx); + FloatReg readFloatReg(int reg_idx, int width); - uint64_t readFloatRegInt(int reg_idx); + FloatRegBits readFloatRegBits(int reg_idx); + + FloatRegBits readFloatRegBits(int reg_idx, int width); void setIntReg(int reg_idx, uint64_t val); - void setFloatRegSingle(int reg_idx, float val); + void setFloatReg(int reg_idx, FloatReg val, int width); + + void setFloatReg(int reg_idx, FloatReg val, int width); - void setFloatRegDouble(int reg_idx, double val); + void setFloatRegBits(int reg_idx, FloatRegBits val); - void setFloatRegInt(int reg_idx, uint64_t val); + void setFloatRegBits(int reg_idx, FloatRegBits val); uint64_t readPC(); diff --git a/cpu/o3/regfile.hh b/cpu/o3/regfile.hh index 1e6e10f29..a5cfa8f3c 100644 --- a/cpu/o3/regfile.hh +++ b/cpu/o3/regfile.hh @@ -89,43 +89,64 @@ class PhysRegFile return intRegFile[reg_idx]; } - float readFloatRegSingle(PhysRegIndex reg_idx) + FloatReg readFloatReg(PhysRegIndex reg_idx, int width) { // Remove the base Float reg dependency. reg_idx = reg_idx - numPhysicalIntRegs; assert(reg_idx < numPhysicalFloatRegs + numPhysicalIntRegs); - DPRINTF(IEW, "RegFile: Access to float register %i as single, has " - "data %8.8f\n", int(reg_idx), (float)floatRegFile[reg_idx].d); + FloatReg floatReg = floatRegFile.readReg(reg_idx, width); - return (float)floatRegFile[reg_idx].d; + DPRINTF(IEW, "RegFile: Access to %d byte float register %i, has " + "data %8.8d\n", int(reg_idx), (double)floatReg); + + return floatReg; } - double readFloatRegDouble(PhysRegIndex reg_idx) + FloatReg readFloatReg(PhysRegIndex reg_idx) { // Remove the base Float reg dependency. reg_idx = reg_idx - numPhysicalIntRegs; assert(reg_idx < numPhysicalFloatRegs + numPhysicalIntRegs); - DPRINTF(IEW, "RegFile: Access to float register %i as double, has " - " data %8.8f\n", int(reg_idx), floatRegFile[reg_idx].d); + FloatReg floatReg = floatRegFile.readReg(reg_idx); + + DPRINTF(IEW, "RegFile: Access to float register %i, has " + "data %8.8d\n", int(reg_idx), (double)floatReg); - return floatRegFile[reg_idx].d; + return floatReg; } - uint64_t readFloatRegInt(PhysRegIndex reg_idx) + FloatRegBits readFloatRegBits(PhysRegIndex reg_idx, int width) { // Remove the base Float reg dependency. reg_idx = reg_idx - numPhysicalIntRegs; assert(reg_idx < numPhysicalFloatRegs + numPhysicalIntRegs); - DPRINTF(IEW, "RegFile: Access to float register %i as int, has data " - "%lli\n", int(reg_idx), floatRegFile[reg_idx].q); + FloatRegBits floatRegBits = floatRegFile.readRegBits(reg_idx, width); + + DPRINTF(IEW, "RegFile: Access to %d byte float register %i as int, " + "has data %lli\n", int(reg_idx), (uint64_t)floatRegBits); + + return floatRegBits; + } + + FloatRegBits readFloatRegBits(PhysRegIndex reg_idx) + { + // Remove the base Float reg dependency. + reg_idx = reg_idx - numPhysicalIntRegs; + + assert(reg_idx < numPhysicalFloatRegs + numPhysicalIntRegs); + + FloatRegBits floatRegBits = floatRegFile.readRegBits(reg_idx); + + DPRINTF(IEW, "RegFile: Access to float register %i as int, " + "has data %lli\n", int(reg_idx), (uint64_t)floatRegBits); - return floatRegFile[reg_idx].q; + return floatRegBits; } void setIntReg(PhysRegIndex reg_idx, uint64_t val) @@ -138,33 +159,33 @@ class PhysRegFile intRegFile[reg_idx] = val; } - void setFloatRegSingle(PhysRegIndex reg_idx, float val) + void setFloatReg(PhysRegIndex reg_idx, FloatReg val, int width) { // Remove the base Float reg dependency. reg_idx = reg_idx - numPhysicalIntRegs; assert(reg_idx < numPhysicalFloatRegs + numPhysicalIntRegs); - DPRINTF(IEW, "RegFile: Setting float register %i to %8.8f\n", - int(reg_idx), val); + DPRINTF(IEW, "RegFile: Setting float register %i to %8.8d\n", + int(reg_idx), (double)val); - floatRegFile[reg_idx].d = (double)val; + floatRegFile.setReg(reg_idx, val, width); } - void setFloatRegDouble(PhysRegIndex reg_idx, double val) + void setFloatReg(PhysRegIndex reg_idx, FloatReg val) { // Remove the base Float reg dependency. reg_idx = reg_idx - numPhysicalIntRegs; assert(reg_idx < numPhysicalFloatRegs + numPhysicalIntRegs); - DPRINTF(IEW, "RegFile: Setting float register %i to %8.8f\n", - int(reg_idx), val); + DPRINTF(IEW, "RegFile: Setting float register %i to %8.8d\n", + int(reg_idx), (double)val); - floatRegFile[reg_idx].d = val; + floatRegFile.setReg(reg_idx, val); } - void setFloatRegInt(PhysRegIndex reg_idx, uint64_t val) + void setFloatRegBits(PhysRegIndex reg_idx, FloatRegBits val, int width) { // Remove the base Float reg dependency. reg_idx = reg_idx - numPhysicalIntRegs; @@ -172,9 +193,22 @@ class PhysRegFile assert(reg_idx < numPhysicalFloatRegs + numPhysicalIntRegs); DPRINTF(IEW, "RegFile: Setting float register %i to %lli\n", - int(reg_idx), val); + int(reg_idx), (uint64_t)val); + + floatRegFile.setRegBits(reg_idx, val, width); + } + + void setFloatRegBits(PhysRegIndex reg_idx, FloatRegBits val) + { + // Remove the base Float reg dependency. + reg_idx = reg_idx - numPhysicalIntRegs; + + assert(reg_idx < numPhysicalFloatRegs + numPhysicalIntRegs); + + DPRINTF(IEW, "RegFile: Setting float register %i to %lli\n", + int(reg_idx), (uint64_t)val); - floatRegFile[reg_idx].q = val; + floatRegFile.setRegBits(reg_idx, val); } uint64_t readPC() diff --git a/cpu/op_class.cc b/cpu/op_class.cc new file mode 100644 index 000000000..00136ded5 --- /dev/null +++ b/cpu/op_class.cc @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2003-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. + */ + +#include "cpu/op_class.hh" + +/** OpClass enum -> description string */ +const char * +opClassStrings[Num_OpClasses] = +{ + "(null)", + "IntAlu", + "IntMult", + "IntDiv", + "FloatAdd", + "FloatCmp", + "FloatCvt", + "FloatMult", + "FloatDiv", + "FloatSqrt", + "MemRead", + "MemWrite", + "IprAccess", + "InstPrefetch" +}; + diff --git a/encumbered/cpu/full/op_class.hh b/cpu/op_class.hh index ff53b58d2..cdb40a0fb 100644 --- a/encumbered/cpu/full/op_class.hh +++ b/cpu/op_class.hh @@ -26,8 +26,8 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef __ENCUMBERED_CPU_FULL_OP_CLASS_HH__ -#define __ENCUMBERED_CPU_FULL_OP_CLASS_HH__ +#ifndef __CPU__OP_CLASS_HH__ +#define __CPU__OP_CLASS_HH__ /** * @file @@ -39,26 +39,26 @@ * assigning instructions to functional units. */ enum OpClass { - No_OpClass = 0, /* inst does not use a functional unit */ - IntAluOp, /* integer ALU */ - IntMultOp, /* integer multiplier */ - IntDivOp, /* integer divider */ - FloatAddOp, /* floating point adder/subtractor */ - FloatCmpOp, /* floating point comparator */ - FloatCvtOp, /* floating point<->integer converter */ - FloatMultOp, /* floating point multiplier */ - FloatDivOp, /* floating point divider */ - FloatSqrtOp, /* floating point square root */ - MemReadOp, /* memory read port */ - MemWriteOp, /* memory write port */ - IprAccessOp, /* Internal Processor Register read/write port */ - InstPrefetchOp, /* instruction prefetch port (on I-cache) */ - Num_OpClasses /* total functional unit classes */ + No_OpClass = 0, ///< Instruction does not use a functional unit + IntAluOp, ///< Integer ALU operaton (add/sub/logical) + IntMultOp, ///< Integer multiply + IntDivOp, ///< Integer divide + FloatAddOp, ///< Floating point add/subtract + FloatCmpOp, ///< Floating point comparison + FloatCvtOp, ///< Floating point<->integer conversion + FloatMultOp, ///< Floating point multiply + FloatDivOp, ///< Floating point divide + FloatSqrtOp, ///< Floating point square root + MemReadOp, ///< Memory read port + MemWriteOp, ///< Memory write port + IprAccessOp, ///< Internal Processor Register read/write port + InstPrefetchOp, ///< Instruction prefetch port (on I-cache) + Num_OpClasses ///< Total number of operation classes }; /** - * Array mapping OpClass enum values to strings. Defined in fu_pool.cc. + * Array mapping OpClass enum values to strings. Defined in op_class.cc. */ extern const char *opClassStrings[]; -#endif // __ENCUMBERED_CPU_FULL_OP_CLASS_HH__ +#endif // __CPU__OP_CLASS_HH__ diff --git a/cpu/ozone/cpu.hh b/cpu/ozone/cpu.hh index f5d84d656..fa849bb09 100644 --- a/cpu/ozone/cpu.hh +++ b/cpu/ozone/cpu.hh @@ -406,22 +406,28 @@ class OoOCPU : public BaseCPU return xc->readIntReg(si->srcRegIdx(idx)); } - float readFloatRegSingle(StaticInst *si, int idx) + FloatReg readFloatReg(StaticInst *si, int idx, width) { int reg_idx = si->srcRegIdx(idx) - TheISA::FP_Base_DepTag; - return xc->readFloatRegSingle(reg_idx); + return xc->readFloatReg(reg_idx, width); } - double readFloatRegDouble(StaticInst *si, int idx) + FloatReg readFloatReg(StaticInst *si, int idx) { int reg_idx = si->srcRegIdx(idx) - TheISA::FP_Base_DepTag; - return xc->readFloatRegDouble(reg_idx); + return xc->readFloatReg(reg_idx); } - uint64_t readFloatRegInt(StaticInst *si, int idx) + FloatRegBits readFloatRegBits(StaticInst *si, int idx, int width) { int reg_idx = si->srcRegIdx(idx) - TheISA::FP_Base_DepTag; - return xc->readFloatRegInt(reg_idx); + return xc->readFloatRegBits(reg_idx, width); + } + + FloatRegBits readFloatRegBits(StaticInst *si, int idx) + { + int reg_idx = si->srcRegIdx(idx) - TheISA::FP_Base_DepTag; + return xc->readFloatRegBits(reg_idx); } void setIntReg(StaticInst *si, int idx, uint64_t val) @@ -429,22 +435,28 @@ class OoOCPU : public BaseCPU xc->setIntReg(si->destRegIdx(idx), val); } - void setFloatRegSingle(StaticInst *si, int idx, float val) + void setFloatReg(StaticInst *si, int idx, FloatReg val, int width) + { + int reg_idx = si->destRegIdx(idx) - TheISA::FP_Base_DepTag; + xc->setFloatReg(reg_idx, val, width); + } + + void setFloatReg(StaticInst *si, int idx, FloatReg val) { int reg_idx = si->destRegIdx(idx) - TheISA::FP_Base_DepTag; - xc->setFloatRegSingle(reg_idx, val); + xc->setFloatReg(reg_idx, val); } - void setFloatRegDouble(StaticInst *si, int idx, double val) + void setFloatRegBits(StaticInst *si, int idx, FloatRegBits val, int width) { int reg_idx = si->destRegIdx(idx) - TheISA::FP_Base_DepTag; - xc->setFloatRegDouble(reg_idx, val); + xc->setFloatRegBits(reg_idx, val, width); } - void setFloatRegInt(StaticInst *si, int idx, uint64_t val) + void setFloatRegBits(StaticInst *si, int idx, FloatRegBits val) { int reg_idx = si->destRegIdx(idx) - TheISA::FP_Base_DepTag; - xc->setFloatRegInt(reg_idx, val); + xc->setFloatRegBits(reg_idx, val); } uint64_t readPC() { return PC; } diff --git a/cpu/pc_event.hh b/cpu/pc_event.hh index 7fa3902cc..32b7f3ef5 100644 --- a/cpu/pc_event.hh +++ b/cpu/pc_event.hh @@ -31,7 +31,7 @@ #include <vector> -#include "mem/mem_req.hh" +#include "base/misc.hh" class ExecContext; class PCEventQueue; @@ -39,9 +39,6 @@ class PCEventQueue; class PCEvent { protected: - static const Addr badpc = MemReq::inval_addr; - - protected: std::string description; PCEventQueue *queue; Addr evpc; diff --git a/cpu/simple/cpu.cc b/cpu/simple/cpu.cc index 8db72b77e..33fe63c26 100644 --- a/cpu/simple/cpu.cc +++ b/cpu/simple/cpu.cc @@ -35,6 +35,7 @@ #include <sstream> #include <string> +#include "arch/utility.hh" #include "base/cprintf.hh" #include "base/inifile.hh" #include "base/loader/symtab.hh" @@ -53,8 +54,7 @@ #include "cpu/smt.hh" #include "cpu/static_inst.hh" #include "kern/kernel_stats.hh" -#include "mem/base_mem.hh" -#include "mem/mem_interface.hh" +#include "mem/packet_impl.hh" #include "sim/byteswap.hh" #include "sim/builder.hh" #include "sim/debug.hh" @@ -65,20 +65,18 @@ #if FULL_SYSTEM #include "base/remote_gdb.hh" -#include "mem/functional/memory_control.hh" -#include "mem/functional/physical.hh" +//#include "mem/functional/memory_control.hh" +//#include "mem/functional/physical.hh" #include "sim/system.hh" #include "arch/tlb.hh" #include "arch/stacktrace.hh" #include "arch/vtophys.hh" #else // !FULL_SYSTEM -#include "mem/functional/functional.hh" +#include "mem/mem_object.hh" #endif // FULL_SYSTEM using namespace std; -//The SimpleCPU does alpha only -using namespace AlphaISA; - +using namespace TheISA; SimpleCPU::TickEvent::TickEvent(SimpleCPU *c, int w) : Event(&mainEventQueue, CPU_Tick_Pri), cpu(c), width(w) @@ -89,6 +87,15 @@ SimpleCPU::TickEvent::TickEvent(SimpleCPU *c, int w) void SimpleCPU::init() { + //Create Memory Ports (conect them up) + Port *mem_dport = mem->getPort(""); + dcachePort.setPeer(mem_dport); + mem_dport->setPeer(&dcachePort); + + Port *mem_iport = mem->getPort(""); + icachePort.setPeer(mem_iport); + mem_iport->setPeer(&icachePort); + BaseCPU::init(); #if FULL_SYSTEM for (int i = 0; i < execContexts.size(); ++i) { @@ -116,43 +123,82 @@ SimpleCPU::TickEvent::description() } -SimpleCPU::CacheCompletionEvent::CacheCompletionEvent(SimpleCPU *_cpu) - : Event(&mainEventQueue), cpu(_cpu) +bool +SimpleCPU::CpuPort::recvTiming(Packet &pkt) { + cpu->processResponse(pkt); + return true; } -void SimpleCPU::CacheCompletionEvent::process() +Tick +SimpleCPU::CpuPort::recvAtomic(Packet &pkt) { - cpu->processCacheCompletion(); + panic("CPU doesn't expect callback!"); + return curTick; } -const char * -SimpleCPU::CacheCompletionEvent::description() +void +SimpleCPU::CpuPort::recvFunctional(Packet &pkt) +{ + panic("CPU doesn't expect callback!"); +} + +void +SimpleCPU::CpuPort::recvStatusChange(Status status) { - return "SimpleCPU cache completion event"; + cpu->recvStatusChange(status); +} + +Packet * +SimpleCPU::CpuPort::recvRetry() +{ + return cpu->processRetry(); } SimpleCPU::SimpleCPU(Params *p) - : BaseCPU(p), tickEvent(this, p->width), cpuXC(NULL), - cacheCompletionEvent(this) + : BaseCPU(p), mem(p->mem), icachePort(this), + dcachePort(this), tickEvent(this, p->width), cpuXC(NULL) { _status = Idle; -#if FULL_SYSTEM - cpuXC = new CPUExecContext(this, 0, p->system, p->itb, p->dtb, p->mem); +#if FULL_SYSTEM + cpuXC = new CPUExecContext(this, 0, p->system, p->itb, p->dtb); #else cpuXC = new CPUExecContext(this, /* thread_num */ 0, p->process, - /* asid */ 0); + /* asid */ 0, mem); #endif // !FULL_SYSTEM - xcProxy = cpuXC->getProxy(); - icacheInterface = p->icache_interface; - dcacheInterface = p->dcache_interface; + xcProxy = cpuXC->getProxy(); - memReq = new MemReq(); - memReq->xc = xcProxy; - memReq->asid = 0; - memReq->data = new uint8_t[64]; +#if SIMPLE_CPU_MEM_ATOMIC || SIMPLE_CPU_MEM_IMMEDIATE + ifetch_req = new Request(true); + ifetch_req->setAsid(0); + // @todo fix me and get the real cpu iD!!! + ifetch_req->setCpuNum(0); + ifetch_req->setSize(sizeof(MachInst)); + ifetch_pkt = new Packet; + ifetch_pkt->cmd = Read; + ifetch_pkt->dataStatic(&inst); + ifetch_pkt->req = ifetch_req; + ifetch_pkt->size = sizeof(MachInst); + + data_read_req = new Request(true); + // @todo fix me and get the real cpu iD!!! + data_read_req->setCpuNum(0); + data_read_req->setAsid(0); + data_read_pkt = new Packet; + data_read_pkt->cmd = Read; + data_read_pkt->dataStatic(&dataReg); + data_read_pkt->req = data_read_req; + + data_write_req = new Request(true); + // @todo fix me and get the real cpu iD!!! + data_write_req->setCpuNum(0); + data_write_req->setAsid(0); + data_write_pkt = new Packet; + data_write_pkt->cmd = Write; + data_write_pkt->req = data_write_req; +#endif numInst = 0; startNumInst = 0; @@ -172,9 +218,9 @@ void SimpleCPU::switchOut(Sampler *s) { sampler = s; - if (status() == DcacheMissStall) { + if (status() == DcacheWaitResponse) { DPRINTF(Sampler,"Outstanding dcache access, waiting for completion\n"); - _status = DcacheMissSwitch; + _status = DcacheWaitSwitch; } else { _status = SwitchedOut; @@ -287,6 +333,18 @@ SimpleCPU::regStats() .prereq(dcacheStallCycles) ; + icacheRetryCycles + .name(name() + ".icache_retry_cycles") + .desc("ICache total retry cycles") + .prereq(icacheRetryCycles) + ; + + dcacheRetryCycles + .name(name() + ".dcache_retry_cycles") + .desc("DCache total retry cycles") + .prereq(dcacheRetryCycles) + ; + idleFraction = constant(1.0) - notIdleFraction; } @@ -308,7 +366,6 @@ SimpleCPU::serialize(ostream &os) nameOut(os, csprintf("%s.tickEvent", name())); tickEvent.serialize(os); nameOut(os, csprintf("%s.cacheCompletionEvent", name())); - cacheCompletionEvent.serialize(os); } void @@ -319,8 +376,6 @@ SimpleCPU::unserialize(Checkpoint *cp, const string §ion) UNSERIALIZE_SCALAR(inst); cpuXC->unserialize(cp, csprintf("%s.xc", section)); tickEvent.unserialize(cp, csprintf("%s.tickEvent", section)); - cacheCompletionEvent - .unserialize(cp, csprintf("%s.cacheCompletionEvent", section)); } void @@ -331,6 +386,7 @@ change_thread_state(int thread_number, int activate, int priority) Fault SimpleCPU::copySrcTranslate(Addr src) { +#if 0 static bool no_warn = true; int blk_size = (dcacheInterface) ? dcacheInterface->getBlockSize() : 64; // Only support block sizes of 64 atm. @@ -347,8 +403,7 @@ SimpleCPU::copySrcTranslate(Addr src) memReq->reset(src & ~(blk_size - 1), blk_size); - // translate to physical address - Fault fault = cpuXC->translateDataReadReq(memReq); + // translate to physical address Fault fault = cpuXC->translateDataReadReq(req); if (fault == NoFault) { cpuXC->copySrcAddr = src; @@ -360,11 +415,15 @@ SimpleCPU::copySrcTranslate(Addr src) cpuXC->copySrcPhysAddr = 0; } return fault; +#else + return NoFault; +#endif } Fault SimpleCPU::copy(Addr dest) { +#if 0 static bool no_warn = true; int blk_size = (dcacheInterface) ? dcacheInterface->getBlockSize() : 64; // Only support block sizes of 64 atm. @@ -383,7 +442,7 @@ SimpleCPU::copy(Addr dest) memReq->reset(dest & ~(blk_size -1), blk_size); // translate to physical address - Fault fault = cpuXC->translateDataWriteReq(memReq); + Fault fault = cpuXC->translateDataWriteReq(req); if (fault == NoFault) { Addr dest_addr = memReq->paddr + offset; @@ -407,6 +466,10 @@ SimpleCPU::copy(Addr dest) assert(!fault->isAlignmentFault()); return fault; +#else + panic("copy not implemented"); + return NoFault; +#endif } // precise architected memory state accessor macros @@ -414,22 +477,65 @@ template <class T> Fault SimpleCPU::read(Addr addr, T &data, unsigned flags) { - if (status() == DcacheMissStall || status() == DcacheMissSwitch) { - Fault fault = cpuXC->read(memReq,data); + if (status() == DcacheWaitResponse || status() == DcacheWaitSwitch) { +// Fault fault = xc->read(memReq,data); + // Not sure what to check for no fault... + if (data_read_pkt->result == Success) { + data = data_read_pkt->get<T>(); + } if (traceData) { - traceData->setAddr(addr); + traceData->setAddr(data_read_req->getVaddr()); } - return fault; + + // @todo: Figure out a way to create a Fault from the packet result. + return NoFault; } - memReq->reset(addr, sizeof(T), flags); +// memReq->reset(addr, sizeof(T), flags); + +#if SIMPLE_CPU_MEM_TIMING + CpuRequest *data_read_req = new Request(true); +#endif + + data_read_req->setVaddr(addr); + data_read_req->setSize(sizeof(T)); + data_read_req->setFlags(flags); + data_read_req->setTime(curTick); // translate to physical address - Fault fault = cpuXC->translateDataReadReq(memReq); + Fault fault = cpuXC->translateDataReadReq(data_read_req); - // if we have a cache, do cache access too - if (fault == NoFault && dcacheInterface) { + // Now do the access. + if (fault == NoFault) { +#if SIMPLE_CPU_MEM_TIMING + data_read_pkt = new Packet; + data_read_pkt->cmd = Read; + data_read_pkt->req = data_read_req; + data_read_pkt->data = new uint8_t[8]; +#endif + data_read_pkt->reset(); + data_read_pkt->addr = data_read_req->getPaddr(); + data_read_pkt->size = sizeof(T); + + sendDcacheRequest(data_read_pkt); + +#if SIMPLE_CPU_MEM_IMMEDIATE + // Need to find a way to not duplicate code above. + + if (data_read_pkt->result == Success) { + data = data_read_pkt->get<T>(); + } + + if (traceData) { + traceData->setAddr(addr); + } + + // @todo: Figure out a way to create a Fault from the packet result. + return NoFault; +#endif + } +/* memReq->cmd = Read; memReq->completionEvent = NULL; memReq->time = curTick; @@ -454,8 +560,9 @@ SimpleCPU::read(Addr addr, T &data, unsigned flags) fault = cpuXC->read(memReq, data); } - - if (!dcacheInterface && (memReq->flags & UNCACHEABLE)) +*/ + // This will need a new way to tell if it has a dcache attached. + if (data_read_req->getFlags() & UNCACHEABLE) recordEvent("Uncached Read"); return fault; @@ -508,11 +615,33 @@ template <class T> Fault SimpleCPU::write(T data, Addr addr, unsigned flags, uint64_t *res) { - memReq->reset(addr, sizeof(T), flags); + data_write_req->setVaddr(addr); + data_write_req->setTime(curTick); + data_write_req->setSize(sizeof(T)); + data_write_req->setFlags(flags); // translate to physical address - Fault fault = cpuXC->translateDataWriteReq(memReq); + Fault fault = cpuXC->translateDataWriteReq(data_write_req); + // Now do the access. + if (fault == NoFault) { +#if SIMPLE_CPU_MEM_TIMING + data_write_pkt = new Packet; + data_write_pkt->cmd = Write; + data_write_pkt->req = data_write_req; + data_write_pkt->allocate(); + data_write_pkt->set(data); +#else + data_write_pkt->reset(); + data = htog(data); + data_write_pkt->dataStatic(&data); +#endif + data_write_pkt->addr = data_write_req->getPaddr(); + data_write_pkt->size = sizeof(T); + + sendDcacheRequest(data_write_pkt); + } +/* // do functional access if (fault == NoFault) fault = cpuXC->write(memReq, data); @@ -535,13 +664,21 @@ SimpleCPU::write(T data, Addr addr, unsigned flags, uint64_t *res) _status = DcacheMissStall; } } - +*/ if (res && (fault == NoFault)) - *res = memReq->result; + *res = data_write_pkt->result; - if (!dcacheInterface && (memReq->flags & UNCACHEABLE)) + // This will need a new way to tell if it's hooked up to a cache or not. + if (data_write_req->getFlags() & UNCACHEABLE) recordEvent("Uncached Write"); + // @todo this is a hack and only works on uniprocessor systems some one else + // can implement LL/SC. + if (data_write_req->getFlags() & LOCKED) + *res = 1; + + // If the write needs to have a fault on the access, consider calling + // changeStatus() and changing it to "bad addr write" or something. return fault; } @@ -597,36 +734,130 @@ SimpleCPU::dbg_vtophys(Addr addr) #endif // FULL_SYSTEM void -SimpleCPU::processCacheCompletion() +SimpleCPU::sendIcacheRequest(Packet *pkt) { + assert(!tickEvent.scheduled()); +#if SIMPLE_CPU_MEM_TIMING + retry_pkt = pkt; + bool success = icachePort.sendTiming(*pkt); + + unscheduleTickEvent(); + + lastIcacheStall = curTick; + + if (!success) { + // Need to wait for retry + _status = IcacheRetry; + } else { + // Need to wait for cache to respond + _status = IcacheWaitResponse; + } +#elif SIMPLE_CPU_MEM_ATOMIC + Tick latency = icachePort.sendAtomic(*pkt); + + unscheduleTickEvent(); + scheduleTickEvent(latency); + + // Note that Icache miss cycles will be incorrect. Unless + // we check the status of the packet sent (is this valid?), + // we won't know if the latency is a hit or a miss. + icacheStallCycles += latency; + + _status = IcacheAccessComplete; +#elif SIMPLE_CPU_MEM_IMMEDIATE + icachePort.sendAtomic(*pkt); +#else +#error "SimpleCPU has no mem model set" +#endif +} + +void +SimpleCPU::sendDcacheRequest(Packet *pkt) +{ + assert(!tickEvent.scheduled()); +#if SIMPLE_CPU_MEM_TIMING + unscheduleTickEvent(); + + retry_pkt = pkt; + bool success = dcachePort.sendTiming(*pkt); + + lastDcacheStall = curTick; + + if (!success) { + _status = DcacheRetry; + } else { + _status = DcacheWaitResponse; + } +#elif SIMPLE_CPU_MEM_ATOMIC + unscheduleTickEvent(); + + Tick latency = dcachePort.sendAtomic(*pkt); + + scheduleTickEvent(latency); + + // Note that Dcache miss cycles will be incorrect. Unless + // we check the status of the packet sent (is this valid?), + // we won't know if the latency is a hit or a miss. + dcacheStallCycles += latency; +#elif SIMPLE_CPU_MEM_IMMEDIATE + dcachePort.sendAtomic(*pkt); +#else +#error "SimpleCPU has no mem model set" +#endif +} + +void +SimpleCPU::processResponse(Packet &response) +{ + assert(SIMPLE_CPU_MEM_TIMING); + + // For what things is the CPU the consumer of the packet it sent + // out? This may create a memory leak if that's the case and it's + // expected of the SimpleCPU to delete its own packet. + Packet *pkt = &response; + switch (status()) { - case IcacheMissStall: + case IcacheWaitResponse: icacheStallCycles += curTick - lastIcacheStall; - _status = IcacheMissComplete; + + _status = IcacheAccessComplete; scheduleTickEvent(1); + + // Copy the icache data into the instruction itself. + inst = pkt->get<MachInst>(); + + delete pkt; break; - case DcacheMissStall: - if (memReq->cmd.isRead()) { + case DcacheWaitResponse: + if (pkt->cmd == Read) { curStaticInst->execute(this,traceData); if (traceData) traceData->finalize(); } + + delete pkt; + dcacheStallCycles += curTick - lastDcacheStall; _status = Running; scheduleTickEvent(1); break; - case DcacheMissSwitch: - if (memReq->cmd.isRead()) { + case DcacheWaitSwitch: + if (pkt->cmd == Read) { curStaticInst->execute(this,traceData); if (traceData) traceData->finalize(); } + + delete pkt; + _status = SwitchedOut; sampler->signalSwitched(); case SwitchedOut: // If this CPU has been switched out due to sampling/warm-up, // ignore any further status changes (e.g., due to cache // misses outstanding at the time of the switch). + delete pkt; + return; default: panic("SimpleCPU::processCacheCompletion: bad state"); @@ -634,6 +865,28 @@ SimpleCPU::processCacheCompletion() } } +Packet * +SimpleCPU::processRetry() +{ +#if SIMPLE_CPU_MEM_TIMING + switch(status()) { + case IcacheRetry: + icacheRetryCycles += curTick - lastIcacheStall; + return retry_pkt; + break; + case DcacheRetry: + dcacheRetryCycles += curTick - lastDcacheStall; + return retry_pkt; + break; + default: + panic("SimpleCPU::processRetry: bad state"); + break; + } +#else + panic("shouldn't be here"); +#endif +} + #if FULL_SYSTEM void SimpleCPU::post_interrupt(int int_num, int index) @@ -651,6 +904,8 @@ SimpleCPU::post_interrupt(int int_num, int index) void SimpleCPU::tick() { + DPRINTF(SimpleCPU,"\n\n"); + numCycles++; traceData = NULL; @@ -659,7 +914,7 @@ SimpleCPU::tick() #if FULL_SYSTEM if (checkInterrupts && check_interrupts() && !cpuXC->inPalMode() && - status() != IcacheMissComplete) { + status() != IcacheAccessComplete) { int ipl = 0; int summary = 0; checkInterrupts = false; @@ -702,37 +957,57 @@ SimpleCPU::tick() // maintain $r0 semantics cpuXC->setIntReg(ZeroReg, 0); -#ifdef TARGET_ALPHA - cpuXC->setFloatRegDouble(ZeroReg, 0.0); -#endif // TARGET_ALPHA +#if THE_ISA == ALPHA_ISA + cpuXC->setFloatReg(ZeroReg, 0.0); +#endif // ALPHA_ISA - if (status() == IcacheMissComplete) { + if (status() == IcacheAccessComplete) { // We've already fetched an instruction and were stalled on an // I-cache miss. No need to fetch it again. // Set status to running; tick event will get rescheduled if // necessary at end of tick() function. _status = Running; - } - else { + } else { // Try to fetch an instruction // set up memory request for instruction fetch + + DPRINTF(Fetch,"Fetch: PC:%08p NPC:%08p NNPC:%08p\n",cpuXC->readPC(), + cpuXC->readNextPC(),cpuXC->readNextNPC()); + +#if SIMPLE_CPU_MEM_TIMING + CpuRequest *ifetch_req = new CpuRequest(); + ifetch_req->setSize(sizeof(MachInst)); +#endif + + ifetch_req->resetMin(); + ifetch_req->setVaddr(cpuXC->readPC() & ~3); + ifetch_req->setTime(curTick); #if FULL_SYSTEM -#define IFETCH_FLAGS(pc) ((pc) & 1) ? PHYSICAL : 0 + ifetch_req->setFlags((cpuXC->readPC() & 1) ? PHYSICAL : 0); #else -#define IFETCH_FLAGS(pc) 0 + ifetch_req->setFlags(0); #endif - memReq->cmd = Read; - memReq->reset(cpuXC->readPC() & ~3, sizeof(uint32_t), - IFETCH_FLAGS(cpuXC->readPC())); - - fault = cpuXC->translateInstReq(memReq); + fault = cpuXC->translateInstReq(ifetch_req); - if (fault == NoFault) - fault = cpuXC->mem->read(memReq, inst); + if (fault == NoFault) { +#if SIMPLE_CPU_MEM_TIMING + Packet *ifetch_pkt = new Packet; + ifetch_pkt->cmd = Read; + ifetch_pkt->data = (uint8_t *)&inst; + ifetch_pkt->req = ifetch_req; + ifetch_pkt->size = sizeof(MachInst); +#endif + ifetch_pkt->reset(); + ifetch_pkt->addr = ifetch_req->getPaddr(); + sendIcacheRequest(ifetch_pkt); +#if SIMPLE_CPU_MEM_TIMING || SIMPLE_CPU_MEM_ATOMIC + return; +#endif +/* if (icacheInterface && fault == NoFault) { memReq->completionEvent = NULL; @@ -743,7 +1018,7 @@ SimpleCPU::tick() // Ugly hack to get an event scheduled *only* if the access is // a miss. We really should add first-class support for this // at some point. - if (result != MA_HIT && icacheInterface->doEvents()) { + if (result != MA_HIT && icacheInterface->doEvents()) { memReq->completionEvent = &cacheCompletionEvent; lastIcacheStall = curTick; unscheduleTickEvent(); @@ -751,6 +1026,8 @@ SimpleCPU::tick() return; } } +*/ + } } // If we've got a valid instruction (i.e., no fault on instruction @@ -771,6 +1048,9 @@ SimpleCPU::tick() traceData = Trace::getInstRecord(curTick, xcProxy, this, curStaticInst, cpuXC->readPC()); + DPRINTF(Decode,"Decode: Decoded %s instruction (opcode: 0x%x): 0x%x\n", + curStaticInst->getName(),curStaticInst->getOpcode(), curStaticInst->machInst); + #if FULL_SYSTEM cpuXC->setInst(inst); #endif // FULL_SYSTEM @@ -806,8 +1086,7 @@ SimpleCPU::tick() // If we have a dcache miss, then we can't finialize the instruction // trace yet because we want to populate it with the data later - if (traceData && - !(status() == DcacheMissStall && memReq->cmd.isRead())) { + if (traceData && (status() != DcacheWaitResponse)) { traceData->finalize(); } @@ -819,11 +1098,11 @@ SimpleCPU::tick() #if FULL_SYSTEM fault->invoke(xcProxy); #else // !FULL_SYSTEM - fatal("fault (%d) detected @ PC 0x%08p", fault, cpuXC->readPC()); + fatal("fault (%s) detected @ PC %08p", fault->name(), cpuXC->readPC()); #endif // FULL_SYSTEM } else { -#if THE_ISA != MIPS_ISA +#if THE_ISA == ALPHA_ISA // go to the next instruction cpuXC->setPC(cpuXC->readNextPC()); cpuXC->setNextPC(cpuXC->readNextPC() + sizeof(MachInst)); @@ -846,7 +1125,7 @@ SimpleCPU::tick() assert(status() == Running || status() == Idle || - status() == DcacheMissStall); + status() == DcacheWaitResponse); if (status() == Running && !tickEvent.scheduled()) tickEvent.schedule(curTick + cycles(1)); @@ -862,11 +1141,11 @@ BEGIN_DECLARE_SIM_OBJECT_PARAMS(SimpleCPU) Param<Counter> max_insts_all_threads; Param<Counter> max_loads_any_thread; Param<Counter> max_loads_all_threads; + SimObjectParam<MemObject *> mem; #if FULL_SYSTEM SimObjectParam<AlphaITB *> itb; SimObjectParam<AlphaDTB *> dtb; - SimObjectParam<FunctionalMemory *> mem; SimObjectParam<System *> system; Param<int> cpu_id; Param<Tick> profile; @@ -875,8 +1154,6 @@ BEGIN_DECLARE_SIM_OBJECT_PARAMS(SimpleCPU) #endif // FULL_SYSTEM Param<int> clock; - SimObjectParam<BaseMem *> icache; - SimObjectParam<BaseMem *> dcache; Param<bool> defer_registration; Param<int> width; @@ -895,11 +1172,11 @@ BEGIN_INIT_SIM_OBJECT_PARAMS(SimpleCPU) "terminate when any thread reaches this load count"), INIT_PARAM(max_loads_all_threads, "terminate when all threads have reached this load count"), + INIT_PARAM(mem, "memory"), #if FULL_SYSTEM INIT_PARAM(itb, "Instruction TLB"), INIT_PARAM(dtb, "Data TLB"), - INIT_PARAM(mem, "memory"), INIT_PARAM(system, "system object"), INIT_PARAM(cpu_id, "processor ID"), INIT_PARAM(profile, ""), @@ -908,8 +1185,6 @@ BEGIN_INIT_SIM_OBJECT_PARAMS(SimpleCPU) #endif // FULL_SYSTEM INIT_PARAM(clock, "clock speed"), - INIT_PARAM(icache, "L1 instruction cache object"), - INIT_PARAM(dcache, "L1 data cache object"), INIT_PARAM(defer_registration, "defer system registration (for sampling)"), INIT_PARAM(width, "cpu width"), INIT_PARAM(function_trace, "Enable function trace"), @@ -931,14 +1206,12 @@ CREATE_SIM_OBJECT(SimpleCPU) params->clock = clock; params->functionTrace = function_trace; params->functionTraceStart = function_trace_start; - params->icache_interface = (icache) ? icache->getInterface() : NULL; - params->dcache_interface = (dcache) ? dcache->getInterface() : NULL; params->width = width; + params->mem = mem; #if FULL_SYSTEM params->itb = itb; params->dtb = dtb; - params->mem = mem; params->system = system; params->cpu_id = cpu_id; params->profile = profile; diff --git a/cpu/simple/cpu.hh b/cpu/simple/cpu.hh index 4ab9a1c3e..945de20af 100644 --- a/cpu/simple/cpu.hh +++ b/cpu/simple/cpu.hh @@ -36,6 +36,9 @@ #include "cpu/pc_event.hh" #include "cpu/sampler/sampler.hh" #include "cpu/static_inst.hh" +#include "mem/packet.hh" +#include "mem/port.hh" +#include "mem/request.hh" #include "sim/eventq.hh" // forward declarations @@ -43,7 +46,7 @@ class Processor; class AlphaITB; class AlphaDTB; -class PhysicalMemory; +class MemObject; class RemoteGDB; class GDBListener; @@ -55,18 +58,61 @@ class Process; #endif // FULL_SYSTEM class ExecContext; -class MemInterface; class Checkpoint; namespace Trace { class InstRecord; } + +// Set exactly one of these symbols to 1 to set the memory access +// model. Probably should make these template parameters, or even +// just fork the CPU models. +// +#define SIMPLE_CPU_MEM_TIMING 0 +#define SIMPLE_CPU_MEM_ATOMIC 0 +#define SIMPLE_CPU_MEM_IMMEDIATE 1 + + class SimpleCPU : public BaseCPU { protected: typedef TheISA::MachInst MachInst; typedef TheISA::MiscReg MiscReg; + typedef TheISA::FloatReg FloatReg; + typedef TheISA::FloatRegBits FloatRegBits; + class CpuPort : public Port + { + + SimpleCPU *cpu; + + public: + + CpuPort(SimpleCPU *_cpu) + : cpu(_cpu) + { } + + protected: + + virtual bool recvTiming(Packet &pkt); + + virtual Tick recvAtomic(Packet &pkt); + + virtual void recvFunctional(Packet &pkt); + + virtual void recvStatusChange(Status status); + + virtual Packet *recvRetry(); + + virtual void getDeviceAddressRanges(AddrRangeList &resp, + AddrRangeList &snoop) + { resp.clear(); snoop.clear(); } + }; + + MemObject *mem; + CpuPort icachePort; + CpuPort dcachePort; + public: // main simulation loop (one cycle) void tick(); @@ -109,10 +155,12 @@ class SimpleCPU : public BaseCPU enum Status { Running, Idle, - IcacheMissStall, - IcacheMissComplete, - DcacheMissStall, - DcacheMissSwitch, + IcacheRetry, + IcacheWaitResponse, + IcacheAccessComplete, + DcacheRetry, + DcacheWaitResponse, + DcacheWaitSwitch, SwitchedOut }; @@ -133,13 +181,11 @@ class SimpleCPU : public BaseCPU public: struct Params : public BaseCPU::Params { - MemInterface *icache_interface; - MemInterface *dcache_interface; int width; + MemObject *mem; #if FULL_SYSTEM AlphaITB *itb; AlphaDTB *dtb; - FunctionalMemory *mem; #else Process *process; #endif @@ -162,17 +208,22 @@ class SimpleCPU : public BaseCPU bool interval_stats; #endif - // L1 instruction cache - MemInterface *icacheInterface; - - // L1 data cache - MemInterface *dcacheInterface; - // current instruction MachInst inst; - // Refcounted pointer to the one memory request. - MemReqPtr memReq; + // Static data storage + TheISA::IntReg dataReg; + +#if SIMPLE_CPU_MEM_TIMING + Packet *retry_pkt; +#elif SIMPLE_CPU_MEM_ATOMIC || SIMPLE_CPU_MEM_IMMEDIATE + Request *ifetch_req; + Packet *ifetch_pkt; + Request *data_read_req; + Packet *data_read_pkt; + Request *data_write_req; + Packet *data_write_pkt; +#endif // Pointer to the sampler that is telling us to switchover. // Used to signal the completion of the pipe drain and schedule @@ -181,20 +232,6 @@ class SimpleCPU : public BaseCPU StaticInstPtr curStaticInst; - class CacheCompletionEvent : public Event - { - private: - SimpleCPU *cpu; - - public: - CacheCompletionEvent(SimpleCPU *_cpu); - - virtual void process(); - virtual const char *description(); - }; - - CacheCompletionEvent cacheCompletionEvent; - Status status() const { return _status; } virtual void activateContext(int thread_num, int delay); @@ -227,15 +264,28 @@ class SimpleCPU : public BaseCPU Stats::Average<> notIdleFraction; Stats::Formula idleFraction; - // number of cycles stalled for I-cache misses + // number of cycles stalled for I-cache responses Stats::Scalar<> icacheStallCycles; Counter lastIcacheStall; - // number of cycles stalled for D-cache misses + // number of cycles stalled for I-cache retries + Stats::Scalar<> icacheRetryCycles; + Counter lastIcacheRetry; + + // number of cycles stalled for D-cache responses Stats::Scalar<> dcacheStallCycles; Counter lastDcacheStall; - void processCacheCompletion(); + // number of cycles stalled for D-cache retries + Stats::Scalar<> dcacheRetryCycles; + Counter lastDcacheRetry; + + void sendIcacheRequest(Packet *pkt); + void sendDcacheRequest(Packet *pkt); + void processResponse(Packet &response); + + Packet * processRetry(); + void recvStatusChange(Port::Status status) {} virtual void serialize(std::ostream &os); virtual void unserialize(Checkpoint *cp, const std::string §ion); @@ -281,22 +331,28 @@ class SimpleCPU : public BaseCPU return cpuXC->readIntReg(si->srcRegIdx(idx)); } - float readFloatRegSingle(const StaticInst *si, int idx) + FloatReg readFloatReg(const StaticInst *si, int idx, int width) + { + int reg_idx = si->srcRegIdx(idx) - TheISA::FP_Base_DepTag; + return cpuXC->readFloatReg(reg_idx, width); + } + + FloatReg readFloatReg(const StaticInst *si, int idx) { int reg_idx = si->srcRegIdx(idx) - TheISA::FP_Base_DepTag; - return cpuXC->readFloatRegSingle(reg_idx); + return cpuXC->readFloatReg(reg_idx); } - double readFloatRegDouble(const StaticInst *si, int idx) + FloatRegBits readFloatRegBits(const StaticInst *si, int idx, int width) { int reg_idx = si->srcRegIdx(idx) - TheISA::FP_Base_DepTag; - return cpuXC->readFloatRegDouble(reg_idx); + return cpuXC->readFloatRegBits(reg_idx, width); } - uint64_t readFloatRegInt(const StaticInst *si, int idx) + FloatRegBits readFloatRegBits(const StaticInst *si, int idx) { int reg_idx = si->srcRegIdx(idx) - TheISA::FP_Base_DepTag; - return cpuXC->readFloatRegInt(reg_idx); + return cpuXC->readFloatRegBits(reg_idx); } void setIntReg(const StaticInst *si, int idx, uint64_t val) @@ -304,26 +360,38 @@ class SimpleCPU : public BaseCPU cpuXC->setIntReg(si->destRegIdx(idx), val); } - void setFloatRegSingle(const StaticInst *si, int idx, float val) + void setFloatReg(const StaticInst *si, int idx, FloatReg val, int width) { int reg_idx = si->destRegIdx(idx) - TheISA::FP_Base_DepTag; - cpuXC->setFloatRegSingle(reg_idx, val); + cpuXC->setFloatReg(reg_idx, val, width); } - void setFloatRegDouble(const StaticInst *si, int idx, double val) + void setFloatReg(const StaticInst *si, int idx, FloatReg val) { int reg_idx = si->destRegIdx(idx) - TheISA::FP_Base_DepTag; - cpuXC->setFloatRegDouble(reg_idx, val); + cpuXC->setFloatReg(reg_idx, val); } - void setFloatRegInt(const StaticInst *si, int idx, uint64_t val) + void setFloatRegBits(const StaticInst *si, int idx, + FloatRegBits val, int width) { int reg_idx = si->destRegIdx(idx) - TheISA::FP_Base_DepTag; - cpuXC->setFloatRegInt(reg_idx, val); + cpuXC->setFloatRegBits(reg_idx, val, width); + } + + void setFloatRegBits(const StaticInst *si, int idx, FloatRegBits val) + { + int reg_idx = si->destRegIdx(idx) - TheISA::FP_Base_DepTag; + cpuXC->setFloatRegBits(reg_idx, val); } uint64_t readPC() { return cpuXC->readPC(); } + uint64_t readNextPC() { return cpuXC->readNextPC(); } + uint64_t readNextNPC() { return cpuXC->readNextNPC(); } + + void setPC(uint64_t val) { cpuXC->setPC(val); } void setNextPC(uint64_t val) { cpuXC->setNextPC(val); } + void setNextNPC(uint64_t val) { cpuXC->setNextNPC(val); } MiscReg readMiscReg(int misc_reg) { @@ -353,7 +421,7 @@ class SimpleCPU : public BaseCPU void ev5_trap(Fault fault) { fault->invoke(xcProxy); } bool simPalCheck(int palFunc) { return cpuXC->simPalCheck(palFunc); } #else - void syscall() { cpuXC->syscall(); } + void syscall(int64_t callnum) { cpuXC->syscall(callnum); } #endif bool misspeculating() { return cpuXC->misspeculating(); } diff --git a/cpu/static_inst.hh b/cpu/static_inst.hh index 20116554e..f0b75c10e 100644 --- a/cpu/static_inst.hh +++ b/cpu/static_inst.hh @@ -33,8 +33,9 @@ #include <string> #include "base/hashmap.hh" +#include "base/misc.hh" #include "base/refcnt.hh" -#include "encumbered/cpu/full/op_class.hh" +#include "cpu/op_class.hh" #include "sim/host.hh" #include "arch/isa_traits.hh" @@ -390,6 +391,18 @@ class StaticInst : public StaticInstBase /// @retval A pointer to the corresponding StaticInst object. //This is defined as inline below. static StaticInstPtr decode(ExtMachInst mach_inst); + + //MIPS Decoder Debug Functions + int getOpcode() { return (machInst & 0xFC000000) >> 26 ; }//31..26 + int getRs() { return (machInst & 0x03E00000) >> 21; } //25...21 + int getRt() { return (machInst & 0x001F0000) >> 16; } //20...16 + int getRd() { return (machInst & 0x0000F800) >> 11; } //15...11 + int getImm() { return (machInst & 0x0000FFFF); } //15...0 + int getFunction(){ return (machInst & 0x0000003F); }//5...0 + int getBranch(){ return (machInst & 0x0000FFFF); }//15...0 + int getJump(){ return (machInst & 0x03FFFFFF); }//5...0 + int getHint(){ return (machInst & 0x000007C0) >> 6; } //10...6 + std::string getName() { return mnemonic; } }; typedef RefCountingPtr<StaticInstBase> StaticInstBasePtr; diff --git a/dev/alpha_console.cc b/dev/alpha_console.cc index 6ca5e3a06..2e46f7be1 100644 --- a/dev/alpha_console.cc +++ b/dev/alpha_console.cc @@ -41,36 +41,25 @@ #include "cpu/base.hh" #include "cpu/exec_context.hh" #include "dev/alpha_console.hh" +#include "dev/platform.hh" #include "dev/simconsole.hh" #include "dev/simple_disk.hh" -#include "dev/tsunami_io.hh" -#include "mem/bus/bus.hh" -#include "mem/bus/pio_interface.hh" -#include "mem/bus/pio_interface_impl.hh" -#include "mem/functional/memory_control.hh" -#include "mem/functional/physical.hh" +#include "mem/physical.hh" #include "sim/builder.hh" #include "sim/sim_object.hh" using namespace std; using namespace AlphaISA; -AlphaConsole::AlphaConsole(const string &name, SimConsole *cons, SimpleDisk *d, - AlphaSystem *s, BaseCPU *c, Platform *p, - MemoryController *mmu, Addr a, - HierParams *hier, Bus *pio_bus) - : PioDevice(name, p), disk(d), console(cons), system(s), cpu(c), addr(a) +AlphaConsole::AlphaConsole(Params *p) + : BasicPioDevice(p), disk(p->disk), + console(params()->cons), system(params()->alpha_sys), cpu(params()->cpu) { - mmu->add_child(this, RangeSize(addr, size)); - if (pio_bus) { - pioInterface = newPioInterface(name + ".pio", hier, pio_bus, this, - &AlphaConsole::cacheAccess); - pioInterface->addAddrRange(RangeSize(addr, size)); - } + pioSize = sizeof(struct AlphaAccess); - alphaAccess = new Access; - alphaAccess->last_offset = size - 1; + alphaAccess = new Access(); + alphaAccess->last_offset = pioSize - 1; alphaAccess->version = ALPHA_ACCESS_VERSION; alphaAccess->diskUnit = 1; @@ -83,130 +72,133 @@ AlphaConsole::AlphaConsole(const string &name, SimConsole *cons, SimpleDisk *d, alphaAccess->inputChar = 0; bzero(alphaAccess->cpuStack, sizeof(alphaAccess->cpuStack)); - system->setAlphaAccess(addr); } void AlphaConsole::startup() { + system->setAlphaAccess(pioAddr); alphaAccess->numCPUs = system->getNumCPUs(); alphaAccess->kernStart = system->getKernelStart(); alphaAccess->kernEnd = system->getKernelEnd(); alphaAccess->entryPoint = system->getKernelEntry(); alphaAccess->mem_size = system->physmem->size(); alphaAccess->cpuClock = cpu->frequency() / 1000000; // In MHz - alphaAccess->intrClockFrequency = platform->intrFrequency(); + alphaAccess->intrClockFrequency = params()->platform->intrFrequency(); } -Fault -AlphaConsole::read(MemReqPtr &req, uint8_t *data) +Tick +AlphaConsole::read(Packet &pkt) { - memset(data, 0, req->size); - Addr daddr = req->paddr - (addr & EV5::PAddrImplMask); + /** XXX Do we want to push the addr munging to a bus brige or something? So + * the device has it's physical address and then the bridge adds on whatever + * machine dependent address swizzle is required? + */ + + assert(pkt.result == Unknown); + assert(pkt.addr >= pioAddr && pkt.addr < pioAddr + pioSize); - switch (req->size) + pkt.time += pioDelay; + Addr daddr = pkt.addr - pioAddr; + + pkt.allocate(); + + switch (pkt.size) { case sizeof(uint32_t): - DPRINTF(AlphaConsole, "read: offset=%#x val=%#x\n", daddr, - *(uint32_t*)data); switch (daddr) { case offsetof(AlphaAccess, last_offset): - *(uint32_t*)data = alphaAccess->last_offset; + pkt.set(alphaAccess->last_offset); break; case offsetof(AlphaAccess, version): - *(uint32_t*)data = alphaAccess->version; + pkt.set(alphaAccess->version); break; case offsetof(AlphaAccess, numCPUs): - *(uint32_t*)data = alphaAccess->numCPUs; + pkt.set(alphaAccess->numCPUs); break; case offsetof(AlphaAccess, intrClockFrequency): - *(uint32_t*)data = alphaAccess->intrClockFrequency; + pkt.set(alphaAccess->intrClockFrequency); break; default: - // Old console code read in everyting as a 32bit int - *(uint32_t*)data = *(uint32_t*)(consoleData + daddr); - + /* Old console code read in everyting as a 32bit int + * we now break that for better error checking. + */ + pkt.result = BadAddress; } + DPRINTF(AlphaConsole, "read: offset=%#x val=%#x\n", daddr, + pkt.get<uint32_t>()); break; case sizeof(uint64_t): - DPRINTF(AlphaConsole, "read: offset=%#x val=%#x\n", daddr, - *(uint64_t*)data); switch (daddr) { case offsetof(AlphaAccess, inputChar): - *(uint64_t*)data = console->console_in(); + pkt.set(console->console_in()); break; case offsetof(AlphaAccess, cpuClock): - *(uint64_t*)data = alphaAccess->cpuClock; + pkt.set(alphaAccess->cpuClock); break; case offsetof(AlphaAccess, mem_size): - *(uint64_t*)data = alphaAccess->mem_size; + pkt.set(alphaAccess->mem_size); break; case offsetof(AlphaAccess, kernStart): - *(uint64_t*)data = alphaAccess->kernStart; + pkt.set(alphaAccess->kernStart); break; case offsetof(AlphaAccess, kernEnd): - *(uint64_t*)data = alphaAccess->kernEnd; + pkt.set(alphaAccess->kernEnd); break; case offsetof(AlphaAccess, entryPoint): - *(uint64_t*)data = alphaAccess->entryPoint; + pkt.set(alphaAccess->entryPoint); break; case offsetof(AlphaAccess, diskUnit): - *(uint64_t*)data = alphaAccess->diskUnit; + pkt.set(alphaAccess->diskUnit); break; case offsetof(AlphaAccess, diskCount): - *(uint64_t*)data = alphaAccess->diskCount; + pkt.set(alphaAccess->diskCount); break; case offsetof(AlphaAccess, diskPAddr): - *(uint64_t*)data = alphaAccess->diskPAddr; + pkt.set(alphaAccess->diskPAddr); break; case offsetof(AlphaAccess, diskBlock): - *(uint64_t*)data = alphaAccess->diskBlock; + pkt.set(alphaAccess->diskBlock); break; case offsetof(AlphaAccess, diskOperation): - *(uint64_t*)data = alphaAccess->diskOperation; + pkt.set(alphaAccess->diskOperation); break; case offsetof(AlphaAccess, outputChar): - *(uint64_t*)data = alphaAccess->outputChar; + pkt.set(alphaAccess->outputChar); break; default: int cpunum = (daddr - offsetof(AlphaAccess, cpuStack)) / sizeof(alphaAccess->cpuStack[0]); if (cpunum >= 0 && cpunum < 64) - *(uint64_t*)data = alphaAccess->cpuStack[cpunum]; + pkt.set(alphaAccess->cpuStack[cpunum]); else panic("Unknown 64bit access, %#x\n", daddr); } + DPRINTF(AlphaConsole, "read: offset=%#x val=%#x\n", daddr, + pkt.get<uint64_t>()); break; default: - return genMachineCheckFault(); + pkt.result = BadAddress; } - - return NoFault; + if (pkt.result == Unknown) pkt.result = Success; + return pioDelay; } -Fault -AlphaConsole::write(MemReqPtr &req, const uint8_t *data) +Tick +AlphaConsole::write(Packet &pkt) { - uint64_t val; - - switch (req->size) { - case sizeof(uint32_t): - val = *(uint32_t *)data; - break; + pkt.time += pioDelay; - case sizeof(uint64_t): - val = *(uint64_t *)data; - break; - default: - return genMachineCheckFault(); - } + assert(pkt.result == Unknown); + assert(pkt.addr >= pioAddr && pkt.addr < pioAddr + pioSize); + Addr daddr = pkt.addr - pioAddr; - Addr daddr = req->paddr - (addr & EV5::PAddrImplMask); - ExecContext *other_xc; + uint64_t val = pkt.get<uint64_t>(); + assert(pkt.size == sizeof(uint64_t)); switch (daddr) { case offsetof(AlphaAccess, diskUnit): @@ -238,9 +230,6 @@ AlphaConsole::write(MemReqPtr &req, const uint8_t *data) console->out((char)(val & 0xff)); break; - other_xc->activate(); //Start the cpu - break; - default: int cpunum = (daddr - offsetof(AlphaAccess, cpuStack)) / sizeof(alphaAccess->cpuStack[0]); @@ -252,13 +241,9 @@ AlphaConsole::write(MemReqPtr &req, const uint8_t *data) panic("Unknown 64bit access, %#x\n", daddr); } - return NoFault; -} + pkt.result = Success; -Tick -AlphaConsole::cacheAccess(MemReqPtr &req) -{ - return curTick + 1000; + return pioDelay; } void @@ -321,14 +306,11 @@ BEGIN_DECLARE_SIM_OBJECT_PARAMS(AlphaConsole) SimObjectParam<SimConsole *> sim_console; SimObjectParam<SimpleDisk *> disk; - SimObjectParam<MemoryController *> mmu; - Param<Addr> addr; + Param<Addr> pio_addr; SimObjectParam<AlphaSystem *> system; SimObjectParam<BaseCPU *> cpu; SimObjectParam<Platform *> platform; - SimObjectParam<Bus*> pio_bus; Param<Tick> pio_latency; - SimObjectParam<HierParams *> hier; END_DECLARE_SIM_OBJECT_PARAMS(AlphaConsole) @@ -336,21 +318,27 @@ BEGIN_INIT_SIM_OBJECT_PARAMS(AlphaConsole) INIT_PARAM(sim_console, "The Simulator Console"), INIT_PARAM(disk, "Simple Disk"), - INIT_PARAM(mmu, "Memory Controller"), - INIT_PARAM(addr, "Device Address"), + INIT_PARAM(pio_addr, "Device Address"), INIT_PARAM(system, "system object"), INIT_PARAM(cpu, "Processor"), INIT_PARAM(platform, "platform"), - INIT_PARAM(pio_bus, "The IO Bus to attach to"), - INIT_PARAM_DFLT(pio_latency, "Programmed IO latency", 1000), - INIT_PARAM_DFLT(hier, "Hierarchy global variables", &defaultHierParams) + INIT_PARAM_DFLT(pio_latency, "Programmed IO latency", 1000) END_INIT_SIM_OBJECT_PARAMS(AlphaConsole) CREATE_SIM_OBJECT(AlphaConsole) { - return new AlphaConsole(getInstanceName(), sim_console, disk, - system, cpu, platform, mmu, addr, hier, pio_bus); + AlphaConsole::Params *p = new AlphaConsole::Params; + p->name = getInstanceName(); + p->platform = platform; + p->pio_addr = pio_addr; + p->pio_delay = pio_latency; + p->cons = sim_console; + p->disk = disk; + p->alpha_sys = system; + p->system = system; + p->cpu = cpu; + return new AlphaConsole(p); } REGISTER_SIM_OBJECT("AlphaConsole", AlphaConsole) diff --git a/dev/alpha_console.hh b/dev/alpha_console.hh index f63c6ad7e..05aec5ec1 100644 --- a/dev/alpha_console.hh +++ b/dev/alpha_console.hh @@ -43,7 +43,6 @@ class BaseCPU; class SimConsole; class AlphaSystem; class SimpleDisk; -class MemoryController; /** * Memory mapped interface to the system console. This device @@ -70,7 +69,7 @@ class MemoryController; * primarily used doing boot before the kernel has loaded its device * drivers. */ -class AlphaConsole : public PioDevice +class AlphaConsole : public BasicPioDevice { protected: struct Access : public AlphaAccess @@ -96,32 +95,35 @@ class AlphaConsole : public PioDevice /** a pointer to the CPU boot cpu */ BaseCPU *cpu; - Addr addr; - static const Addr size = sizeof(struct AlphaAccess); + public: + struct Params : public BasicPioDevice::Params + { + SimConsole *cons; + SimpleDisk *disk; + AlphaSystem *alpha_sys; + BaseCPU *cpu; + }; + protected: + const Params *params() const {return (const Params *)_params; } public: + /** Standard Constructor */ - AlphaConsole(const std::string &name, SimConsole *cons, SimpleDisk *d, - AlphaSystem *s, BaseCPU *c, Platform *platform, - MemoryController *mmu, Addr addr, - HierParams *hier, Bus *pio_bus); + AlphaConsole(Params *p); virtual void startup(); /** * memory mapped reads and writes */ - virtual Fault read(MemReqPtr &req, uint8_t *data); - virtual Fault write(MemReqPtr &req, const uint8_t *data); + virtual Tick read(Packet &pkt); + virtual Tick write(Packet &pkt); /** * standard serialization routines for checkpointing */ virtual void serialize(std::ostream &os); virtual void unserialize(Checkpoint *cp, const std::string §ion); - - public: - Tick cacheAccess(MemReqPtr &req); }; #endif // __ALPHA_CONSOLE_HH__ diff --git a/dev/baddev.cc b/dev/baddev.cc index 87d683a5d..dcabdbe0a 100644 --- a/dev/baddev.cc +++ b/dev/baddev.cc @@ -35,82 +35,63 @@ #include <vector> #include "base/trace.hh" -#include "cpu/exec_context.hh" #include "dev/baddev.hh" #include "dev/platform.hh" -#include "mem/bus/bus.hh" -#include "mem/bus/pio_interface.hh" -#include "mem/bus/pio_interface_impl.hh" -#include "mem/functional/memory_control.hh" +#include "mem/port.hh" #include "sim/builder.hh" #include "sim/system.hh" using namespace std; using namespace TheISA; -BadDevice::BadDevice(const string &name, Addr a, MemoryController *mmu, - HierParams *hier, Bus *pio_bus, const string &devicename) - : PioDevice(name, NULL), addr(a), devname(devicename) +BadDevice::BadDevice(Params *p) + : BasicPioDevice(p), devname(p->device_name) { - mmu->add_child(this, RangeSize(addr, size)); - - if (pio_bus) { - pioInterface = newPioInterface(name, hier, pio_bus, this, - &BadDevice::cacheAccess); - pioInterface->addAddrRange(RangeSize(addr, size)); - } - + pioSize = 0xf; } -Fault -BadDevice::read(MemReqPtr &req, uint8_t *data) -{ - - panic("Device %s not imlpmented\n", devname); - return NoFault; -} - -Fault -BadDevice::write(MemReqPtr &req, const uint8_t *data) +Tick +BadDevice::read(Packet &pkt) { panic("Device %s not imlpmented\n", devname); - return NoFault; } Tick -BadDevice::cacheAccess(MemReqPtr &req) +BadDevice::write(Packet &pkt) { - return curTick; + panic("Device %s not imlpmented\n", devname); } BEGIN_DECLARE_SIM_OBJECT_PARAMS(BadDevice) + Param<string> devicename; + Param<Addr> pio_addr; + SimObjectParam<System *> system; SimObjectParam<Platform *> platform; - SimObjectParam<MemoryController *> mmu; - Param<Addr> addr; - SimObjectParam<HierParams *> hier; - SimObjectParam<Bus*> pio_bus; Param<Tick> pio_latency; - Param<string> devicename; END_DECLARE_SIM_OBJECT_PARAMS(BadDevice) BEGIN_INIT_SIM_OBJECT_PARAMS(BadDevice) - INIT_PARAM(platform, "Platform"), - INIT_PARAM(mmu, "Memory Controller"), - INIT_PARAM(addr, "Device Address"), - INIT_PARAM_DFLT(hier, "Hierarchy global variables", &defaultHierParams), - INIT_PARAM_DFLT(pio_bus, "The IO Bus to attach to", NULL), - INIT_PARAM_DFLT(pio_latency, "Programmed IO latency", 1000), - INIT_PARAM(devicename, "Name of device to error on") + INIT_PARAM(devicename, "Name of device to error on"), + INIT_PARAM(pio_addr, "Device Address"), + INIT_PARAM(system, "system object"), + INIT_PARAM(platform, "platform"), + INIT_PARAM_DFLT(pio_latency, "Programmed IO latency", 1000) END_INIT_SIM_OBJECT_PARAMS(BadDevice) CREATE_SIM_OBJECT(BadDevice) { - return new BadDevice(getInstanceName(), addr, mmu, hier, pio_bus, - devicename); + BadDevice::Params *p = new BadDevice::Params; + p->name =getInstanceName(); + p->platform = platform; + p->pio_addr = pio_addr; + p->pio_delay = pio_latency; + p->system = system; + p->device_name = devicename; + return new BadDevice(p); } REGISTER_SIM_OBJECT("BadDevice", BadDevice) diff --git a/dev/baddev.hh b/dev/baddev.hh index 189f28331..4cf0d6ba4 100644 --- a/dev/baddev.hh +++ b/dev/baddev.hh @@ -37,7 +37,6 @@ #include "base/range.hh" #include "dev/io_device.hh" -class MemoryController; /** * BadDevice @@ -45,51 +44,29 @@ class MemoryController; * the user that the kernel they are running has unsupported * options (i.e. frame buffer) */ -class BadDevice : public PioDevice +class BadDevice : public BasicPioDevice { private: - Addr addr; - static const Addr size = 0xf; - std::string devname; public: + struct Params : public BasicPioDevice::Params + { + std::string device_name; + }; + protected: + const Params *params() const { return (const Params *)_params; } + + public: /** * Constructor for the Baddev Class. - * @param name name of the object + * @param p object parameters * @param a base address of the write - * @param mmu the memory controller - * @param hier object to store parameters universal the device hierarchy - * @param bus The bus that this device is attached to - * @param devicename device that is not implemented - */ - BadDevice(const std::string &name, Addr a, MemoryController *mmu, - HierParams *hier, Bus *bus, const std::string &devicename); - - /** - * On a read event we just panic aand hopefully print a - * meaningful error message. - * @param req Contains the address to read from. - * @param data A pointer to write the read data to. - * @return The fault condition of the access. - */ - virtual Fault read(MemReqPtr &req, uint8_t *data); - - /** - * On a write event we just panic aand hopefully print a - * meaningful error message. - * @param req Contains the address to write to. - * @param data The data to write. - * @return The fault condition of the access. */ - virtual Fault write(MemReqPtr &req, const uint8_t *data); + BadDevice(Params *p); - /** - * Return how long this access will take. - * @param req the memory request to calcuate - * @return Tick when the request is done - */ - Tick cacheAccess(MemReqPtr &req); + virtual Tick read(Packet &pkt); + virtual Tick write(Packet &pkt); }; #endif // __DEV_BADDEV_HH__ diff --git a/dev/etherbus.cc b/dev/etherbus.cc index c6b131e8e..906e324d3 100644 --- a/dev/etherbus.cc +++ b/dev/etherbus.cc @@ -81,7 +81,7 @@ EtherBus::reg(EtherInt *dev) { devlist.push_back(dev); } bool -EtherBus::send(EtherInt *sndr, PacketPtr &pkt) +EtherBus::send(EtherInt *sndr, EthPacketPtr &pkt) { if (busy()) { DPRINTF(Ethernet, "ethernet packet not sent, bus busy\n", curTick); diff --git a/dev/etherbus.hh b/dev/etherbus.hh index ca859d85f..4a364abd8 100644 --- a/dev/etherbus.hh +++ b/dev/etherbus.hh @@ -61,7 +61,7 @@ class EtherBus : public SimObject }; DoneEvent event; - PacketPtr packet; + EthPacketPtr packet; EtherInt *sender; EtherDump *dump; @@ -73,7 +73,7 @@ class EtherBus : public SimObject void txDone(); void reg(EtherInt *dev); bool busy() const { return (bool)packet; } - bool send(EtherInt *sender, PacketPtr &packet); + bool send(EtherInt *sender, EthPacketPtr &packet); }; #endif // __ETHERBUS_H__ diff --git a/dev/etherdump.cc b/dev/etherdump.cc index d8a51fc5b..cb5f0b70e 100644 --- a/dev/etherdump.cc +++ b/dev/etherdump.cc @@ -102,7 +102,7 @@ EtherDump::init() } void -EtherDump::dumpPacket(PacketPtr &packet) +EtherDump::dumpPacket(EthPacketPtr &packet) { pcap_pkthdr pkthdr; pkthdr.seconds = curtime + (curTick / Clock::Int::s); diff --git a/dev/etherdump.hh b/dev/etherdump.hh index 149192cd7..8bba073fe 100644 --- a/dev/etherdump.hh +++ b/dev/etherdump.hh @@ -45,7 +45,7 @@ class EtherDump : public SimObject private: std::ofstream stream; const int maxlen; - void dumpPacket(PacketPtr &packet); + void dumpPacket(EthPacketPtr &packet); void init(); Tick curtime; @@ -53,7 +53,7 @@ class EtherDump : public SimObject public: EtherDump(const std::string &name, const std::string &file, int max); - inline void dump(PacketPtr &pkt) { dumpPacket(pkt); } + inline void dump(EthPacketPtr &pkt) { dumpPacket(pkt); } }; #endif // __ETHERDUMP_H__ diff --git a/dev/etherint.hh b/dev/etherint.hh index e397846ae..1f641fadb 100644 --- a/dev/etherint.hh +++ b/dev/etherint.hh @@ -58,9 +58,9 @@ class EtherInt : public SimObject void recvDone() { peer->sendDone(); } virtual void sendDone() = 0; - bool sendPacket(PacketPtr packet) + bool sendPacket(EthPacketPtr packet) { return peer ? peer->recvPacket(packet) : true; } - virtual bool recvPacket(PacketPtr packet) = 0; + virtual bool recvPacket(EthPacketPtr packet) = 0; }; #endif // __DEV_ETHERINT_HH__ diff --git a/dev/etherlink.cc b/dev/etherlink.cc index f68332926..5b6531c2e 100644 --- a/dev/etherlink.cc +++ b/dev/etherlink.cc @@ -102,7 +102,7 @@ EtherLink::unserialize(Checkpoint *cp, const string §ion) } void -EtherLink::Link::txComplete(PacketPtr packet) +EtherLink::Link::txComplete(EthPacketPtr packet) { DPRINTF(Ethernet, "packet received: len=%d\n", packet->length); DDUMP(EthernetData, packet->data, packet->length); @@ -113,12 +113,12 @@ class LinkDelayEvent : public Event { protected: EtherLink::Link *link; - PacketPtr packet; + EthPacketPtr packet; public: // non-scheduling version for createForUnserialize() LinkDelayEvent(); - LinkDelayEvent(EtherLink::Link *link, PacketPtr pkt, Tick when); + LinkDelayEvent(EtherLink::Link *link, EthPacketPtr pkt, Tick when); void process(); @@ -148,7 +148,7 @@ EtherLink::Link::txDone() } bool -EtherLink::Link::transmit(PacketPtr pkt) +EtherLink::Link::transmit(EthPacketPtr pkt) { if (busy()) { DPRINTF(Ethernet, "packet not sent, link busy\n"); @@ -195,7 +195,7 @@ EtherLink::Link::unserialize(const string &base, Checkpoint *cp, bool packet_exists; paramIn(cp, section, base + ".packet_exists", packet_exists); if (packet_exists) { - packet = new PacketData(16384); + packet = new EthPacketData(16384); packet->unserialize(base + ".packet", cp, section); } @@ -215,7 +215,7 @@ LinkDelayEvent::LinkDelayEvent() setFlags(AutoDelete); } -LinkDelayEvent::LinkDelayEvent(EtherLink::Link *l, PacketPtr p, Tick when) +LinkDelayEvent::LinkDelayEvent(EtherLink::Link *l, EthPacketPtr p, Tick when) : Event(&mainEventQueue), link(l), packet(p) { setFlags(AutoSerialize); @@ -256,7 +256,7 @@ LinkDelayEvent::unserialize(Checkpoint *cp, const string §ion) link = parent->link[number]; - packet = new PacketData(16384); + packet = new EthPacketData(16384); packet->unserialize("packet", cp, section); } diff --git a/dev/etherlink.hh b/dev/etherlink.hh index 305007d9e..570444e1b 100644 --- a/dev/etherlink.hh +++ b/dev/etherlink.hh @@ -73,14 +73,14 @@ class EtherLink : public SimObject /* * Transfer is complete */ - PacketPtr packet; + EthPacketPtr packet; void txDone(); typedef EventWrapper<Link, &Link::txDone> DoneEvent; friend void DoneEvent::process(); DoneEvent doneEvent; friend class LinkDelayEvent; - void txComplete(PacketPtr packet); + void txComplete(EthPacketPtr packet); public: Link(const std::string &name, EtherLink *p, int num, @@ -90,7 +90,7 @@ class EtherLink : public SimObject const std::string name() const { return objName; } bool busy() const { return (bool)packet; } - bool transmit(PacketPtr packet); + bool transmit(EthPacketPtr packet); void setTxInt(Interface *i) { assert(!txint); txint = i; } void setRxInt(Interface *i) { assert(!rxint); rxint = i; } @@ -110,7 +110,7 @@ class EtherLink : public SimObject public: Interface(const std::string &name, Link *txlink, Link *rxlink); - bool recvPacket(PacketPtr packet) { return txlink->transmit(packet); } + bool recvPacket(EthPacketPtr packet) { return txlink->transmit(packet); } void sendDone() { peer->sendDone(); } }; diff --git a/dev/etherpkt.cc b/dev/etherpkt.cc index 44dbd7c18..85e18e981 100644 --- a/dev/etherpkt.cc +++ b/dev/etherpkt.cc @@ -35,7 +35,7 @@ using namespace std; void -PacketData::serialize(const string &base, ostream &os) +EthPacketData::serialize(const string &base, ostream &os) { paramOut(os, base + ".length", length); paramOut(os, base + ".slack", slack); @@ -43,7 +43,7 @@ PacketData::serialize(const string &base, ostream &os) } void -PacketData::unserialize(const string &base, Checkpoint *cp, +EthPacketData::unserialize(const string &base, Checkpoint *cp, const string §ion) { paramIn(cp, section, base + ".length", length); diff --git a/dev/etherpkt.hh b/dev/etherpkt.hh index cb9022d72..01741b3d5 100644 --- a/dev/etherpkt.hh +++ b/dev/etherpkt.hh @@ -44,7 +44,7 @@ * Reference counted class containing ethernet packet data */ class Checkpoint; -class PacketData : public RefCounted +class EthPacketData : public RefCounted { public: /* @@ -66,12 +66,12 @@ class PacketData : public RefCounted int slack; public: - PacketData() : data(NULL), length(0), slack(0) { } - explicit PacketData(size_t size) + EthPacketData() : data(NULL), length(0), slack(0) { } + explicit EthPacketData(size_t size) : data(new uint8_t[size]), length(0), slack(0) { } - PacketData(std::auto_ptr<uint8_t> d, int l, int s = 0) + EthPacketData(std::auto_ptr<uint8_t> d, int l, int s = 0) : data(d.release()), length(l), slack(s) { } - ~PacketData() { if (data) delete [] data; } + ~EthPacketData() { if (data) delete [] data; } public: void serialize(const std::string &base, std::ostream &os); @@ -79,6 +79,6 @@ class PacketData : public RefCounted const std::string §ion); }; -typedef RefCountingPtr<PacketData> PacketPtr; +typedef RefCountingPtr<EthPacketData> EthPacketPtr; #endif // __ETHERPKT_HH__ diff --git a/dev/ethertap.cc b/dev/ethertap.cc index 7589991ef..b5abb1d62 100644 --- a/dev/ethertap.cc +++ b/dev/ethertap.cc @@ -169,7 +169,7 @@ EtherTap::detach() } bool -EtherTap::recvPacket(PacketPtr packet) +EtherTap::recvPacket(EthPacketPtr packet) { if (dump) dump->dump(packet); @@ -218,8 +218,8 @@ EtherTap::process(int revent) } while (data_len != 0 && buffer_offset >= data_len + sizeof(u_int32_t)) { - PacketPtr packet; - packet = new PacketData(data_len); + EthPacketPtr packet; + packet = new EthPacketData(data_len); packet->length = data_len; memcpy(packet->data, data, data_len); @@ -250,7 +250,7 @@ EtherTap::retransmit() if (packetBuffer.empty()) return; - PacketPtr packet = packetBuffer.front(); + EthPacketPtr packet = packetBuffer.front(); if (sendPacket(packet)) { if (dump) dump->dump(packet); diff --git a/dev/ethertap.hh b/dev/ethertap.hh index 069ba734f..40ce6af0b 100644 --- a/dev/ethertap.hh +++ b/dev/ethertap.hh @@ -70,10 +70,10 @@ class EtherTap : public EtherInt protected: std::string device; - std::queue<PacketPtr> packetBuffer; + std::queue<EthPacketPtr> packetBuffer; void process(int revent); - void enqueue(PacketData *packet); + void enqueue(EthPacketData *packet); void retransmit(); /* @@ -97,7 +97,7 @@ class EtherTap : public EtherInt EtherTap(const std::string &name, EtherDump *dump, int port, int bufsz); virtual ~EtherTap(); - virtual bool recvPacket(PacketPtr packet); + virtual bool recvPacket(EthPacketPtr packet); virtual void sendDone(); virtual void serialize(std::ostream &os); diff --git a/dev/ide_ctrl.cc b/dev/ide_ctrl.cc index 05c756f04..abdbe5d0a 100644 --- a/dev/ide_ctrl.cc +++ b/dev/ide_ctrl.cc @@ -38,17 +38,12 @@ #include "dev/pciconfigall.hh" #include "dev/pcireg.h" #include "dev/platform.hh" -#include "mem/bus/bus.hh" -#include "mem/bus/dma_interface.hh" -#include "mem/bus/pio_interface.hh" -#include "mem/bus/pio_interface_impl.hh" -#include "mem/functional/memory_control.hh" -#include "mem/functional/physical.hh" +#include "mem/packet.hh" #include "sim/builder.hh" #include "sim/sim_object.hh" +#include "sim/byteswap.hh" using namespace std; -using namespace TheISA; //// // Initialization and destruction @@ -91,22 +86,6 @@ IdeController::IdeController(Params *p) bm_enabled = false; memset(cmd_in_progress, 0, sizeof(cmd_in_progress)); - pioInterface = NULL; - dmaInterface = NULL; - // create the PIO and DMA interfaces - if (params()->pio_bus) { - pioInterface = newPioInterface(name() + ".pio", params()->hier, - params()->pio_bus, this, - &IdeController::cacheAccess); - pioLatency = params()->pio_latency * params()->pio_bus->clockRate; - } - - if (params()->dma_bus) { - dmaInterface = new DMAInterface<Bus>(name() + ".dma", - params()->dma_bus, - params()->dma_bus, 1, true); - } - // setup the disks attached to controller memset(disks, 0, sizeof(disks)); dev[0] = 0; @@ -117,7 +96,7 @@ IdeController::IdeController(Params *p) for (int i = 0; i < params()->disks.size(); i++) { disks[i] = params()->disks[i]; - disks[i]->setController(this, dmaInterface); + disks[i]->setController(this); } } @@ -239,121 +218,158 @@ IdeController::setDmaComplete(IdeDisk *disk) } } -//// -// Bus timing and bus access functions -//// - -Tick -IdeController::cacheAccess(MemReqPtr &req) -{ - // @todo Add more accurate timing to cache access - return curTick + pioLatency; -} //// // Read and write handling //// void -IdeController::readConfig(int offset, int size, uint8_t *data) +IdeController::readConfig(int offset, uint8_t *data) { - int config_offset; - if (offset < PCI_DEVICE_SPECIFIC) { - PciDev::readConfig(offset, size, data); + PciDev::readConfig(offset, data); } else if (offset >= IDE_CTRL_CONF_START && - (offset + size) <= IDE_CTRL_CONF_END) { + (offset + 1) <= IDE_CTRL_CONF_END) { - config_offset = offset - IDE_CTRL_CONF_START; - - switch (size) { - case sizeof(uint8_t): - *data = config_regs.data[config_offset]; + switch (offset) { + case IDE_CTRL_CONF_DEV_TIMING: + *data = config_regs.sidetim; break; - case sizeof(uint16_t): - *(uint16_t*)data = *(uint16_t*)&config_regs.data[config_offset]; + case IDE_CTRL_CONF_UDMA_CNTRL: + *data = config_regs.udmactl; break; - case sizeof(uint32_t): - *(uint32_t*)data = *(uint32_t*)&config_regs.data[config_offset]; + case IDE_CTRL_CONF_PRIM_TIMING+1: + *data = htole(config_regs.idetim0) >> 8; + break; + case IDE_CTRL_CONF_SEC_TIMING+1: + *data = htole(config_regs.idetim1) >> 8; + break; + case IDE_CTRL_CONF_IDE_CONFIG: + *data = htole(config_regs.ideconfig) & 0xFF; + break; + case IDE_CTRL_CONF_IDE_CONFIG+1: + *data = htole(config_regs.ideconfig) >> 8; break; default: - panic("Invalid PCI configuration read size!\n"); + panic("Invalid PCI configuration read for size 1 at offset: %#x!\n", + offset); } - - } else { panic("Read of unimplemented PCI config. register: %x\n", offset); } - switch (size) { - case sizeof(uint8_t): - DPRINTF(IdeCtrl, "PCI read offset: %#x size: %d data: %#x\n", - offset, size, (uint32_t)*data); + DPRINTF(IdeCtrl, "PCI read offset: %#x size: 1 data: %#x\n", + offset, (uint32_t)*data); +} + +void +IdeController::readConfig(int offset, uint16_t *data) +{ + if (offset < PCI_DEVICE_SPECIFIC) { + PciDev::readConfig(offset, data); + } else if (offset >= IDE_CTRL_CONF_START && + (offset + 2) <= IDE_CTRL_CONF_END) { + + switch (offset) { + case IDE_CTRL_CONF_PRIM_TIMING: + *data = config_regs.idetim0; break; - case sizeof(uint16_t): - DPRINTF(IdeCtrl, "PCI read offset: %#x size: %d data: %#x\n", - offset, size, *(uint16_t*)data); + case IDE_CTRL_CONF_SEC_TIMING: + *data = config_regs.idetim1; break; - case sizeof(uint32_t): - DPRINTF(IdeCtrl, "PCI read offset: %#x size: %d data: %#x\n", - offset, size, *(uint32_t*)data); + case IDE_CTRL_CONF_UDMA_TIMING: + *data = config_regs.udmatim; + break; + case IDE_CTRL_CONF_IDE_CONFIG: + *data = config_regs.ideconfig; break; default: - panic("Invalid PCI configuration read size!\n"); + panic("Invalid PCI configuration read for size 2 offset: %#x!\n", + offset); } + } else { + panic("Read of unimplemented PCI config. register: %x\n", offset); + } + DPRINTF(IdeCtrl, "PCI read offset: %#x size: 2 data: %#x\n", offset, *data); } void -IdeController::writeConfig(int offset, int size, const uint8_t *data) +IdeController::readConfig(int offset, uint32_t *data) { - int config_offset; - if (offset < PCI_DEVICE_SPECIFIC) { - PciDev::writeConfig(offset, size, data); + PciDev::readConfig(offset, data); + } else { + panic("Read of unimplemented PCI config. register: %x\n", offset); + } + DPRINTF(IdeCtrl, "PCI read offset: %#x size: 4 data: %#x\n", offset, *data); +} +void +IdeController::writeConfig(int offset, const uint8_t data) +{ + if (offset < PCI_DEVICE_SPECIFIC) { + PciDev::writeConfig(offset, data); } else if (offset >= IDE_CTRL_CONF_START && - (offset + size) <= IDE_CTRL_CONF_END) { + (offset + 1) <= IDE_CTRL_CONF_END) { - config_offset = offset - IDE_CTRL_CONF_START; - - switch(size) { - case sizeof(uint8_t): - config_regs.data[config_offset] = *data; + switch (offset) { + case IDE_CTRL_CONF_DEV_TIMING: + config_regs.sidetim = data; break; - case sizeof(uint16_t): - *(uint16_t*)&config_regs.data[config_offset] = *(uint16_t*)data; + case IDE_CTRL_CONF_UDMA_CNTRL: + config_regs.udmactl = data; break; - case sizeof(uint32_t): - *(uint32_t*)&config_regs.data[config_offset] = *(uint32_t*)data; + case IDE_CTRL_CONF_IDE_CONFIG: + config_regs.ideconfig = (config_regs.ideconfig & 0xFF00) | (data); + break; + case IDE_CTRL_CONF_IDE_CONFIG+1: + config_regs.ideconfig = (config_regs.ideconfig & 0x00FF) | data << 8; break; default: - panic("Invalid PCI configuration write size!\n"); + panic("Invalid PCI configuration write for size 1 offset: %#x!\n", + offset); } + } else { - panic("Write of unimplemented PCI config. register: %x\n", offset); + panic("Read of unimplemented PCI config. register: %x\n", offset); } + DPRINTF(IdeCtrl, "PCI write offset: %#x size: 1 data: %#x\n", + offset, (uint32_t)data); +} - switch(size) { - case sizeof(uint8_t): - DPRINTF(IdeCtrl, "PCI write offset: %#x size: %d data: %#x\n", - offset, size, (uint32_t)*data); +void +IdeController::writeConfig(int offset, const uint16_t data) +{ + if (offset < PCI_DEVICE_SPECIFIC) { + PciDev::writeConfig(offset, data); + } else if (offset >= IDE_CTRL_CONF_START && + (offset + 2) <= IDE_CTRL_CONF_END) { + + switch (offset) { + case IDE_CTRL_CONF_PRIM_TIMING: + config_regs.idetim0 = data; break; - case sizeof(uint16_t): - DPRINTF(IdeCtrl, "PCI write offset: %#x size: %d data: %#x\n", - offset, size, *(uint16_t*)data); + case IDE_CTRL_CONF_SEC_TIMING: + config_regs.idetim1 = data; break; - case sizeof(uint32_t): - DPRINTF(IdeCtrl, "PCI write offset: %#x size: %d data: %#x\n", - offset, size, *(uint32_t*)data); + case IDE_CTRL_CONF_UDMA_TIMING: + config_regs.udmatim = data; + break; + case IDE_CTRL_CONF_IDE_CONFIG: + config_regs.ideconfig = data; break; default: - panic("Invalid PCI configuration write size!\n"); + panic("Invalid PCI configuration write for size 2 offset: %#x!\n", + offset); } - // Catch the writes to specific PCI registers that have side affects - // (like updating the PIO ranges) - switch (offset) { - case PCI_COMMAND: + } else { + panic("Write of unimplemented PCI config. register: %x\n", offset); + } + DPRINTF(IdeCtrl, "PCI write offset: %#x size: 2 data: %#x\n", offset, data); + + /* Trap command register writes and enable IO/BM as appropriate. */ + if (offset == PCI_COMMAND) { if (letoh(config.command) & PCI_CMD_IOSE) io_enabled = true; else @@ -363,91 +379,83 @@ IdeController::writeConfig(int offset, int size, const uint8_t *data) bm_enabled = true; else bm_enabled = false; - break; + } + +} + +void +IdeController::writeConfig(int offset, const uint32_t data) +{ + if (offset < PCI_DEVICE_SPECIFIC) { + PciDev::writeConfig(offset, data); + } else { + panic("Read of unimplemented PCI config. register: %x\n", offset); + } + + DPRINTF(IdeCtrl, "PCI write offset: %#x size: 4 data: %#x\n", offset, data); + switch(offset) { case PCI0_BASE_ADDR0: - if (BARAddrs[0] != 0) { + if (BARAddrs[0] != 0) pri_cmd_addr = BARAddrs[0]; - if (pioInterface) - pioInterface->addAddrRange(RangeSize(pri_cmd_addr, - pri_cmd_size)); - - pri_cmd_addr &= EV5::PAddrUncachedMask; - } break; case PCI0_BASE_ADDR1: - if (BARAddrs[1] != 0) { + if (BARAddrs[1] != 0) pri_ctrl_addr = BARAddrs[1]; - if (pioInterface) - pioInterface->addAddrRange(RangeSize(pri_ctrl_addr, - pri_ctrl_size)); - - pri_ctrl_addr &= EV5::PAddrUncachedMask; - } break; case PCI0_BASE_ADDR2: - if (BARAddrs[2] != 0) { + if (BARAddrs[2] != 0) sec_cmd_addr = BARAddrs[2]; - if (pioInterface) - pioInterface->addAddrRange(RangeSize(sec_cmd_addr, - sec_cmd_size)); - - sec_cmd_addr &= EV5::PAddrUncachedMask; - } break; case PCI0_BASE_ADDR3: - if (BARAddrs[3] != 0) { + if (BARAddrs[3] != 0) sec_ctrl_addr = BARAddrs[3]; - if (pioInterface) - pioInterface->addAddrRange(RangeSize(sec_ctrl_addr, - sec_ctrl_size)); - - sec_ctrl_addr &= EV5::PAddrUncachedMask; - } break; case PCI0_BASE_ADDR4: - if (BARAddrs[4] != 0) { + if (BARAddrs[4] != 0) bmi_addr = BARAddrs[4]; - if (pioInterface) - pioInterface->addAddrRange(RangeSize(bmi_addr, bmi_size)); - - bmi_addr &= EV5::PAddrUncachedMask; - } break; } } -Fault -IdeController::read(MemReqPtr &req, uint8_t *data) +Tick +IdeController::read(Packet &pkt) { Addr offset; IdeChannel channel; IdeRegType reg_type; int disk; - parseAddr(req->paddr, offset, channel, reg_type); + pkt.time += pioDelay; + pkt.allocate(); + if (pkt.size != 1 && pkt.size != 2 && pkt.size !=4) + panic("Bad IDE read size: %d\n", pkt.size); + + parseAddr(pkt.addr, offset, channel, reg_type); - if (!io_enabled) - return NoFault; + if (!io_enabled) { + pkt.result = Success; + return pioDelay; + } switch (reg_type) { case BMI_BLOCK: - switch (req->size) { + switch (pkt.size) { case sizeof(uint8_t): - *data = bmi_regs.data[offset]; + pkt.set(bmi_regs.data[offset]); break; case sizeof(uint16_t): - *(uint16_t*)data = *(uint16_t*)&bmi_regs.data[offset]; + pkt.set(*(uint16_t*)&bmi_regs.data[offset]); break; case sizeof(uint32_t): - *(uint32_t*)data = *(uint32_t*)&bmi_regs.data[offset]; + pkt.set(*(uint32_t*)&bmi_regs.data[offset]); break; default: - panic("IDE read of BMI reg invalid size: %#x\n", req->size); + panic("IDE read of BMI reg invalid size: %#x\n", pkt.size); } break; @@ -455,51 +463,54 @@ IdeController::read(MemReqPtr &req, uint8_t *data) case CONTROL_BLOCK: disk = getDisk(channel); - if (disks[disk] == NULL) + if (disks[disk] == NULL) { + pkt.set<uint8_t>(0); break; + } switch (offset) { case DATA_OFFSET: - switch (req->size) { + switch (pkt.size) { case sizeof(uint16_t): - disks[disk]->read(offset, reg_type, data); + disks[disk]->read(offset, reg_type, pkt.getPtr<uint8_t>()); break; case sizeof(uint32_t): - disks[disk]->read(offset, reg_type, data); - disks[disk]->read(offset, reg_type, &data[2]); + disks[disk]->read(offset, reg_type, pkt.getPtr<uint8_t>()); + disks[disk]->read(offset, reg_type, + pkt.getPtr<uint8_t>() + sizeof(uint16_t)); break; default: - panic("IDE read of data reg invalid size: %#x\n", req->size); + panic("IDE read of data reg invalid size: %#x\n", pkt.size); } break; default: - if (req->size == sizeof(uint8_t)) { - disks[disk]->read(offset, reg_type, data); + if (pkt.size == sizeof(uint8_t)) { + disks[disk]->read(offset, reg_type, pkt.getPtr<uint8_t>()); } else - panic("IDE read of command reg of invalid size: %#x\n", req->size); + panic("IDE read of command reg of invalid size: %#x\n", pkt.size); } break; default: panic("IDE controller read of unknown register block type!\n"); } - - if (req->size == 1) + if (pkt.size == 1) DPRINTF(IdeCtrl, "read from offset: %#x size: %#x data: %#x\n", - offset, req->size, (uint32_t)*data); - else if (req->size == 2) + offset, pkt.size, (uint32_t)pkt.get<uint8_t>()); + else if (pkt.size == 2) DPRINTF(IdeCtrl, "read from offset: %#x size: %#x data: %#x\n", - offset, req->size, *(uint16_t*)data); + offset, pkt.size, pkt.get<uint16_t>()); else DPRINTF(IdeCtrl, "read from offset: %#x size: %#x data: %#x\n", - offset, req->size, *(uint32_t*)data); + offset, pkt.size, pkt.get<uint32_t>()); - return NoFault; + pkt.result = Success; + return pioDelay; } -Fault -IdeController::write(MemReqPtr &req, const uint8_t *data) +Tick +IdeController::write(Packet &pkt) { Addr offset; IdeChannel channel; @@ -507,28 +518,35 @@ IdeController::write(MemReqPtr &req, const uint8_t *data) int disk; uint8_t oldVal, newVal; - parseAddr(req->paddr, offset, channel, reg_type); + pkt.time += pioDelay; - if (!io_enabled) - return NoFault; + parseAddr(pkt.addr, offset, channel, reg_type); + + if (!io_enabled) { + pkt.result = Success; + DPRINTF(IdeCtrl, "io not enabled\n"); + return pioDelay; + } switch (reg_type) { case BMI_BLOCK: - if (!bm_enabled) - return NoFault; + if (!bm_enabled) { + pkt.result = Success; + return pioDelay; + } switch (offset) { // Bus master IDE command register case BMIC1: case BMIC0: - if (req->size != sizeof(uint8_t)) - panic("Invalid BMIC write size: %x\n", req->size); + if (pkt.size != sizeof(uint8_t)) + panic("Invalid BMIC write size: %x\n", pkt.size); // select the current disk based on DEV bit disk = getDisk(channel); oldVal = bmi_regs.chan[channel].bmic; - newVal = *data; + newVal = pkt.get<uint8_t>(); // if a DMA transfer is in progress, R/W control cannot change if (oldVal & SSBM) { @@ -577,11 +595,11 @@ IdeController::write(MemReqPtr &req, const uint8_t *data) // Bus master IDE status register case BMIS0: case BMIS1: - if (req->size != sizeof(uint8_t)) - panic("Invalid BMIS write size: %x\n", req->size); + if (pkt.size != sizeof(uint8_t)) + panic("Invalid BMIS write size: %x\n", pkt.size); oldVal = bmi_regs.chan[channel].bmis; - newVal = *data; + newVal = pkt.get<uint8_t>(); // the BMIDEA bit is RO newVal |= (oldVal & BMIDEA); @@ -604,30 +622,28 @@ IdeController::write(MemReqPtr &req, const uint8_t *data) case BMIDTP0: case BMIDTP1: { - if (req->size != sizeof(uint32_t)) - panic("Invalid BMIDTP write size: %x\n", req->size); + if (pkt.size != sizeof(uint32_t)) + panic("Invalid BMIDTP write size: %x\n", pkt.size); - uint32_t host_data = letoh(*(uint32_t*)data); - host_data &= ~0x3; - bmi_regs.chan[channel].bmidtp = htole(host_data); + bmi_regs.chan[channel].bmidtp = htole(pkt.get<uint32_t>() & ~0x3); } break; default: - if (req->size != sizeof(uint8_t) && - req->size != sizeof(uint16_t) && - req->size != sizeof(uint32_t)) + if (pkt.size != sizeof(uint8_t) && + pkt.size != sizeof(uint16_t) && + pkt.size != sizeof(uint32_t)) panic("IDE controller write of invalid write size: %x\n", - req->size); + pkt.size); // do a default copy of data into the registers - memcpy(&bmi_regs.data[offset], data, req->size); + memcpy(&bmi_regs.data[offset], pkt.getPtr<uint8_t>(), pkt.size); } break; case COMMAND_BLOCK: if (offset == IDE_SELECT_OFFSET) { uint8_t *devBit = &dev[channel]; - *devBit = (letoh(*data) & IDE_SELECT_DEV_BIT) ? 1 : 0; + *devBit = (letoh(pkt.get<uint8_t>()) & IDE_SELECT_DEV_BIT) ? 1 : 0; } // fall-through ok! case CONTROL_BLOCK: @@ -638,40 +654,44 @@ IdeController::write(MemReqPtr &req, const uint8_t *data) switch (offset) { case DATA_OFFSET: - switch (req->size) { + switch (pkt.size) { case sizeof(uint16_t): - disks[disk]->write(offset, reg_type, data); + disks[disk]->write(offset, reg_type, pkt.getPtr<uint8_t>()); break; case sizeof(uint32_t): - disks[disk]->write(offset, reg_type, data); - disks[disk]->write(offset, reg_type, &data[2]); + disks[disk]->write(offset, reg_type, pkt.getPtr<uint8_t>()); + disks[disk]->write(offset, reg_type, pkt.getPtr<uint8_t>() + + sizeof(uint16_t)); break; default: - panic("IDE write of data reg invalid size: %#x\n", req->size); + panic("IDE write of data reg invalid size: %#x\n", pkt.size); } break; default: - if (req->size == sizeof(uint8_t)) { - disks[disk]->write(offset, reg_type, data); + if (pkt.size == sizeof(uint8_t)) { + disks[disk]->write(offset, reg_type, pkt.getPtr<uint8_t>()); } else - panic("IDE write of command reg of invalid size: %#x\n", req->size); + panic("IDE write of command reg of invalid size: %#x\n", pkt.size); } break; default: panic("IDE controller write of unknown register block type!\n"); } - if (req->size == 1) + + if (pkt.size == 1) DPRINTF(IdeCtrl, "write to offset: %#x size: %#x data: %#x\n", - offset, req->size, (uint32_t)*data); - else if (req->size == 2) + offset, pkt.size, (uint32_t)pkt.get<uint8_t>()); + else if (pkt.size == 2) DPRINTF(IdeCtrl, "write to offset: %#x size: %#x data: %#x\n", - offset, req->size, *(uint16_t*)data); + offset, pkt.size, pkt.get<uint16_t>()); else DPRINTF(IdeCtrl, "write to offset: %#x size: %#x data: %#x\n", - offset, req->size, *(uint32_t*)data); + offset, pkt.size, pkt.get<uint32_t>()); - return NoFault; + + pkt.result = Success; + return pioDelay; } //// @@ -740,51 +760,36 @@ IdeController::unserialize(Checkpoint *cp, const std::string §ion) UNSERIALIZE_SCALAR(bm_enabled); UNSERIALIZE_ARRAY(cmd_in_progress, sizeof(cmd_in_progress) / sizeof(cmd_in_progress[0])); - - if (pioInterface) { - pioInterface->addAddrRange(RangeSize(pri_cmd_addr, pri_cmd_size)); - pioInterface->addAddrRange(RangeSize(pri_ctrl_addr, pri_ctrl_size)); - pioInterface->addAddrRange(RangeSize(sec_cmd_addr, sec_cmd_size)); - pioInterface->addAddrRange(RangeSize(sec_ctrl_addr, sec_ctrl_size)); - pioInterface->addAddrRange(RangeSize(bmi_addr, bmi_size)); - } + pioPort->sendStatusChange(Port::RangeChange); } #ifndef DOXYGEN_SHOULD_SKIP_THIS BEGIN_DECLARE_SIM_OBJECT_PARAMS(IdeController) - Param<Addr> addr; - SimObjectVectorParam<IdeDisk *> disks; - SimObjectParam<MemoryController *> mmu; + SimObjectParam<System *> system; + SimObjectParam<Platform *> platform; SimObjectParam<PciConfigAll *> configspace; SimObjectParam<PciConfigData *> configdata; - SimObjectParam<Platform *> platform; Param<uint32_t> pci_bus; Param<uint32_t> pci_dev; Param<uint32_t> pci_func; - SimObjectParam<Bus *> pio_bus; - SimObjectParam<Bus *> dma_bus; Param<Tick> pio_latency; - SimObjectParam<HierParams *> hier; + SimObjectVectorParam<IdeDisk *> disks; END_DECLARE_SIM_OBJECT_PARAMS(IdeController) BEGIN_INIT_SIM_OBJECT_PARAMS(IdeController) - INIT_PARAM(addr, "Device Address"), - INIT_PARAM(disks, "IDE disks attached to this controller"), - INIT_PARAM(mmu, "Memory controller"), + INIT_PARAM(system, "System pointer"), + INIT_PARAM(platform, "Platform pointer"), INIT_PARAM(configspace, "PCI Configspace"), INIT_PARAM(configdata, "PCI Config data"), - INIT_PARAM(platform, "Platform pointer"), INIT_PARAM(pci_bus, "PCI bus ID"), INIT_PARAM(pci_dev, "PCI device number"), INIT_PARAM(pci_func, "PCI function code"), - INIT_PARAM(pio_bus, ""), - INIT_PARAM(dma_bus, ""), INIT_PARAM_DFLT(pio_latency, "Programmed IO latency in bus cycles", 1), - INIT_PARAM_DFLT(hier, "Hierarchy global variables", &defaultHierParams) + INIT_PARAM(disks, "IDE disks attached to this controller") END_INIT_SIM_OBJECT_PARAMS(IdeController) @@ -792,19 +797,15 @@ CREATE_SIM_OBJECT(IdeController) { IdeController::Params *params = new IdeController::Params; params->name = getInstanceName(); - params->mmu = mmu; + params->platform = platform; + params->system = system; params->configSpace = configspace; params->configData = configdata; - params->plat = platform; params->busNum = pci_bus; params->deviceNum = pci_dev; params->functionNum = pci_func; - + params->pio_delay = pio_latency; params->disks = disks; - params->pio_bus = pio_bus; - params->dma_bus = dma_bus; - params->pio_latency = pio_latency; - params->hier = hier; return new IdeController(params); } diff --git a/dev/ide_ctrl.hh b/dev/ide_ctrl.hh index 0fbaf9207..a074f4f97 100644 --- a/dev/ide_ctrl.hh +++ b/dev/ide_ctrl.hh @@ -70,6 +70,13 @@ #define IDE_CTRL_CONF_START 0x40 #define IDE_CTRL_CONF_END ((IDE_CTRL_CONF_START) + sizeof(config_regs)) +#define IDE_CTRL_CONF_PRIM_TIMING 0x40 +#define IDE_CTRL_CONF_SEC_TIMING 0x42 +#define IDE_CTRL_CONF_DEV_TIMING 0x44 +#define IDE_CTRL_CONF_UDMA_CNTRL 0x48 +#define IDE_CTRL_CONF_UDMA_TIMING 0x4A +#define IDE_CTRL_CONF_IDE_CONFIG 0x54 + enum IdeRegType { COMMAND_BLOCK, @@ -77,13 +84,9 @@ enum IdeRegType { BMI_BLOCK }; -class BaseInterface; -class Bus; -class HierParams; class IdeDisk; class IntrControl; class PciConfigAll; -class PhysicalMemory; class Platform; /** @@ -191,10 +194,6 @@ class IdeController : public PciDev { /** Array of disk objects */ std::vector<IdeDisk *> disks; - Bus *pio_bus; - Bus *dma_bus; - Tick pio_latency; - HierParams *hier; }; const Params *params() const { return (const Params *)_params; } @@ -202,26 +201,28 @@ class IdeController : public PciDev IdeController(Params *p); ~IdeController(); - virtual void writeConfig(int offset, int size, const uint8_t *data); - virtual void readConfig(int offset, int size, uint8_t *data); + virtual void writeConfig(int offset, const uint8_t data); + virtual void writeConfig(int offset, const uint16_t data); + virtual void writeConfig(int offset, const uint32_t data); + virtual void readConfig(int offset, uint8_t *data); + virtual void readConfig(int offset, uint16_t *data); + virtual void readConfig(int offset, uint32_t *data); void setDmaComplete(IdeDisk *disk); /** * Read a done field for a given target. - * @param req Contains the address of the field to read. - * @param data Return the field read. - * @return The fault condition of the access. + * @param pkt Packet describing what is to be read + * @return The amount of time to complete this request */ - virtual Fault read(MemReqPtr &req, uint8_t *data); + virtual Tick read(Packet &pkt); /** - * Write to the mmapped I/O control registers. - * @param req Contains the address to write to. - * @param data The data to write. - * @return The fault condition of the access. + * Write a done field for a given target. + * @param pkt Packet describing what is to be written + * @return The amount of time to complete this request */ - virtual Fault write(MemReqPtr &req, const uint8_t *data); + virtual Tick write(Packet &pkt); /** * Serialize this object to the given output stream. @@ -236,11 +237,5 @@ class IdeController : public PciDev */ virtual void unserialize(Checkpoint *cp, const std::string §ion); - /** - * Return how long this access will take. - * @param req the memory request to calcuate - * @return Tick when the request is done - */ - Tick cacheAccess(MemReqPtr &req); }; #endif // __IDE_CTRL_HH_ diff --git a/dev/ide_disk.cc b/dev/ide_disk.cc index c13556ed6..6f4234a1d 100644 --- a/dev/ide_disk.cc +++ b/dev/ide_disk.cc @@ -35,6 +35,7 @@ #include <deque> #include <string> +#include "base/chunk_generator.hh" #include "base/cprintf.hh" // csprintf #include "base/trace.hh" #include "dev/disk_image.hh" @@ -42,11 +43,6 @@ #include "dev/ide_ctrl.hh" #include "dev/tsunami.hh" #include "dev/tsunami_pchip.hh" -#include "mem/functional/physical.hh" -#include "mem/bus/bus.hh" -#include "mem/bus/dma_interface.hh" -#include "mem/bus/pio_interface.hh" -#include "mem/bus/pio_interface_impl.hh" #include "sim/builder.hh" #include "sim/sim_object.hh" #include "sim/root.hh" @@ -55,11 +51,11 @@ using namespace std; using namespace TheISA; -IdeDisk::IdeDisk(const string &name, DiskImage *img, PhysicalMemory *phys, +IdeDisk::IdeDisk(const string &name, DiskImage *img, int id, Tick delay) - : SimObject(name), ctrl(NULL), image(img), physmem(phys), diskDelay(delay), - dmaTransferEvent(this), dmaReadWaitEvent(this), - dmaWriteWaitEvent(this), dmaPrdReadEvent(this), + : SimObject(name), ctrl(NULL), image(img), diskDelay(delay), + dmaTransferEvent(this), dmaReadCG(NULL), dmaReadWaitEvent(this), + dmaWriteCG(NULL), dmaWriteWaitEvent(this), dmaPrdReadEvent(this), dmaReadEvent(this), dmaWriteEvent(this) { // Reset the device state @@ -139,7 +135,6 @@ IdeDisk::reset(int id) memset(&cmdReg, 0, sizeof(CommandReg_t)); memset(&curPrd.entry, 0, sizeof(PrdEntry_t)); - dmaInterfaceBytes = 0; curPrdAddr = 0; curSector = 0; cmdBytes = 0; @@ -188,29 +183,6 @@ IdeDisk::pciToDma(Addr pciAddr) panic("Access to unset controller!\n"); } -uint32_t -IdeDisk::bytesInDmaPage(Addr curAddr, uint32_t bytesLeft) -{ - uint32_t bytesInPage = 0; - - // First calculate how many bytes could be in the page - if (bytesLeft > TheISA::PageBytes) - bytesInPage = TheISA::PageBytes; - else - bytesInPage = bytesLeft; - - // Next, see if we have crossed a page boundary, and adjust - Addr upperBound = curAddr + bytesInPage; - Addr pageBound = TheISA::TruncPage(curAddr) + TheISA::PageBytes; - - assert(upperBound >= curAddr && "DMA read wraps around address space!\n"); - - if (upperBound >= pageBound) - bytesInPage = pageBound - curAddr; - - return bytesInPage; -} - //// // Device registers read/write //// @@ -263,6 +235,8 @@ IdeDisk::read(const Addr &offset, IdeRegType reg_type, uint8_t *data) default: panic("Unknown register block!\n"); } + DPRINTF(IdeDisk, "Read to disk at offset: %#x data %#x\n", offset, + (uint32_t)*data); if (action != ACT_NONE) updateState(action); @@ -324,6 +298,8 @@ IdeDisk::write(const Addr &offset, IdeRegType reg_type, const uint8_t *data) panic("Unknown register block!\n"); } + DPRINTF(IdeDisk, "Write to disk at offset: %#x data %#x\n", offset, + (uint32_t)*data); if (action != ACT_NONE) updateState(action); } @@ -339,29 +315,17 @@ IdeDisk::doDmaTransfer() panic("Inconsistent DMA transfer state: dmaState = %d devState = %d\n", dmaState, devState); - // first read the current PRD - if (dmaInterface) { - if (dmaInterface->busy()) { - // reschedule after waiting period - dmaTransferEvent.schedule(curTick + DMA_BACKOFF_PERIOD); - return; - } - - dmaInterface->doDMA(Read, curPrdAddr, sizeof(PrdEntry_t), curTick, - &dmaPrdReadEvent); - } else { - dmaPrdReadDone(); - } + if (ctrl->dmaPending()) { + dmaTransferEvent.schedule(curTick + DMA_BACKOFF_PERIOD); + return; + } else + ctrl->dmaRead(curPrdAddr, sizeof(PrdEntry_t), &dmaPrdReadEvent, + (uint8_t*)&curPrd.entry); } void IdeDisk::dmaPrdReadDone() { - // actually copy the PRD from physical memory - memcpy((void *)&curPrd.entry, - physmem->dma_addr(curPrdAddr, sizeof(PrdEntry_t)), - sizeof(PrdEntry_t)); - DPRINTF(IdeDisk, "PRD: baseAddr:%#x (%#x) byteCount:%d (%d) eot:%#x sector:%d\n", curPrd.getBaseAddr(), pciToDma(curPrd.getBaseAddr()), @@ -372,73 +336,49 @@ IdeDisk::dmaPrdReadDone() curPrdAddr = curPrdAddr + sizeof(PrdEntry_t); if (dmaRead) - doDmaRead(); + doDmaDataRead(); else - doDmaWrite(); + doDmaDataWrite(); } void -IdeDisk::regStats() -{ - using namespace Stats; - dmaReadFullPages - .name(name() + ".dma_read_full_pages") - .desc("Number of full page size DMA reads (not PRD).") - ; - dmaReadBytes - .name(name() + ".dma_read_bytes") - .desc("Number of bytes transfered via DMA reads (not PRD).") - ; - dmaReadTxs - .name(name() + ".dma_read_txs") - .desc("Number of DMA read transactions (not PRD).") - ; - - dmaWriteFullPages - .name(name() + ".dma_write_full_pages") - .desc("Number of full page size DMA writes.") - ; - dmaWriteBytes - .name(name() + ".dma_write_bytes") - .desc("Number of bytes transfered via DMA writes.") - ; - dmaWriteTxs - .name(name() + ".dma_write_txs") - .desc("Number of DMA write transactions.") - ; -} - -void -IdeDisk::doDmaRead() +IdeDisk::doDmaDataRead() { /** @todo we need to figure out what the delay actually will be */ Tick totalDiskDelay = diskDelay + (curPrd.getByteCount() / SectorSize); DPRINTF(IdeDisk, "doDmaRead, diskDelay: %d totalDiskDelay: %d\n", diskDelay, totalDiskDelay); - if (dmaInterface) { - if (dmaInterface->busy()) { - // reschedule after waiting period - dmaReadWaitEvent.schedule(curTick + DMA_BACKOFF_PERIOD); - return; - } - Addr dmaAddr = pciToDma(curPrd.getBaseAddr()); + dmaReadWaitEvent.schedule(curTick + totalDiskDelay); +} - uint32_t bytesInPage = bytesInDmaPage(curPrd.getBaseAddr(), - (uint32_t)curPrd.getByteCount()); - dmaInterfaceBytes = bytesInPage; +void +IdeDisk::doDmaRead() +{ - if (bytesInPage == TheISA::VMPageSize) - dmaReadFullPages++; - dmaReadBytes += bytesInPage; - dmaReadTxs++; - dmaInterface->doDMA(Read, dmaAddr, bytesInPage, - curTick + totalDiskDelay, &dmaReadEvent); + if (!dmaReadCG) { + // clear out the data buffer + memset(dataBuffer, 0, MAX_DMA_SIZE); + dmaReadCG = new ChunkGenerator(curPrd.getBaseAddr(), + curPrd.getByteCount(), TheISA::PageBytes); + + } + if (ctrl->dmaPending()) { + panic("shouldn't be reentant??"); + dmaReadWaitEvent.schedule(curTick + DMA_BACKOFF_PERIOD); + return; + } else if (!dmaReadCG->done()) { + assert(dmaReadCG->complete() < MAX_DMA_SIZE); + ctrl->dmaRead(pciToDma(dmaReadCG->addr()), dmaReadCG->size(), + &dmaReadWaitEvent, dataBuffer + dmaReadCG->complete()); + dmaReadCG->next(); } else { - // schedule dmaReadEvent with sectorDelay (dmaReadDone) - dmaReadEvent.schedule(curTick + totalDiskDelay); + assert(dmaReadCG->done()); + delete dmaReadCG; + dmaReadCG = NULL; + dmaReadDone(); } } @@ -446,68 +386,14 @@ void IdeDisk::dmaReadDone() { - Addr curAddr = 0, dmaAddr = 0; - uint32_t bytesWritten = 0, bytesInPage = 0, bytesLeft = 0; - - // continue to use the DMA interface until all pages are read - if (dmaInterface && (dmaInterfaceBytes < curPrd.getByteCount())) { - // see if the interface is busy - if (dmaInterface->busy()) { - // reschedule after waiting period - dmaReadEvent.schedule(curTick + DMA_BACKOFF_PERIOD); - return; - } - - uint32_t bytesLeft = curPrd.getByteCount() - dmaInterfaceBytes; - curAddr = curPrd.getBaseAddr() + dmaInterfaceBytes; - dmaAddr = pciToDma(curAddr); - - bytesInPage = bytesInDmaPage(curAddr, bytesLeft); - dmaInterfaceBytes += bytesInPage; - - if (bytesInPage == TheISA::VMPageSize) - dmaReadFullPages++; - dmaReadBytes += bytesInPage; - dmaReadTxs++; - - dmaInterface->doDMA(Read, dmaAddr, bytesInPage, - curTick, &dmaReadEvent); - - return; - } - - // set initial address - curAddr = curPrd.getBaseAddr(); - - // clear out the data buffer - memset(dataBuffer, 0, MAX_DMA_SIZE); - - // read the data from memory via DMA into a data buffer - while (bytesWritten < curPrd.getByteCount()) { - if (cmdBytesLeft <= 0) - panic("DMA data is larger than # of sectors specified\n"); - - dmaAddr = pciToDma(curAddr); - - // calculate how many bytes are in the current page - bytesLeft = curPrd.getByteCount() - bytesWritten; - bytesInPage = bytesInDmaPage(curAddr, bytesLeft); + uint32_t bytesWritten = 0; - // copy the data from memory into the data buffer - memcpy((void *)(dataBuffer + bytesWritten), - physmem->dma_addr(dmaAddr, bytesInPage), - bytesInPage); - - curAddr += bytesInPage; - bytesWritten += bytesInPage; - cmdBytesLeft -= bytesInPage; - } // write the data to the disk image - for (bytesWritten = 0; - bytesWritten < curPrd.getByteCount(); + for (bytesWritten = 0; bytesWritten < curPrd.getByteCount(); bytesWritten += SectorSize) { + cmdBytesLeft -= SectorSize; writeDisk(curSector++, (uint8_t *)(dataBuffer + bytesWritten)); } @@ -522,117 +408,55 @@ IdeDisk::dmaReadDone() } void -IdeDisk::doDmaWrite() +IdeDisk::doDmaDataWrite() { /** @todo we need to figure out what the delay actually will be */ Tick totalDiskDelay = diskDelay + (curPrd.getByteCount() / SectorSize); + uint32_t bytesRead = 0; DPRINTF(IdeDisk, "doDmaWrite, diskDelay: %d totalDiskDelay: %d\n", diskDelay, totalDiskDelay); - if (dmaInterface) { - if (dmaInterface->busy()) { - // reschedule after waiting period - dmaWriteWaitEvent.schedule(curTick + DMA_BACKOFF_PERIOD); - return; - } - - Addr dmaAddr = pciToDma(curPrd.getBaseAddr()); - - uint32_t bytesInPage = bytesInDmaPage(curPrd.getBaseAddr(), - (uint32_t)curPrd.getByteCount()); + memset(dataBuffer, 0, MAX_DMA_SIZE); + assert(cmdBytesLeft <= MAX_DMA_SIZE); + while (bytesRead < curPrd.getByteCount()) { + readDisk(curSector++, (uint8_t *)(dataBuffer + bytesRead)); + bytesRead += SectorSize; + cmdBytesLeft -= SectorSize; + } - dmaInterfaceBytes = bytesInPage; + dmaWriteWaitEvent.schedule(curTick + totalDiskDelay); +} - if (bytesInPage == TheISA::VMPageSize) - dmaWriteFullPages++; - dmaWriteBytes += bytesInPage; - dmaWriteTxs++; +void +IdeDisk::doDmaWrite() +{ - dmaInterface->doDMA(WriteInvalidate, dmaAddr, - bytesInPage, curTick + totalDiskDelay, - &dmaWriteEvent); + if (!dmaWriteCG) { + // clear out the data buffer + dmaWriteCG = new ChunkGenerator(curPrd.getBaseAddr(), + curPrd.getByteCount(), TheISA::PageBytes); + } + if (ctrl->dmaPending()) { + panic("shouldn't be reentant??"); + dmaWriteWaitEvent.schedule(curTick + DMA_BACKOFF_PERIOD); + return; + } else if (!dmaWriteCG->done()) { + assert(dmaWriteCG->complete() < MAX_DMA_SIZE); + ctrl->dmaWrite(pciToDma(dmaWriteCG->addr()), dmaWriteCG->size(), + &dmaWriteWaitEvent, dataBuffer + dmaWriteCG->complete()); + dmaWriteCG->next(); } else { - // schedule event with disk delay (dmaWriteDone) - dmaWriteEvent.schedule(curTick + totalDiskDelay); + assert(dmaWriteCG->done()); + delete dmaWriteCG; + dmaWriteCG = NULL; + dmaWriteDone(); } } void IdeDisk::dmaWriteDone() { - Addr curAddr = 0, pageAddr = 0, dmaAddr = 0; - uint32_t bytesRead = 0, bytesInPage = 0; - - // continue to use the DMA interface until all pages are read - if (dmaInterface && (dmaInterfaceBytes < curPrd.getByteCount())) { - // see if the interface is busy - if (dmaInterface->busy()) { - // reschedule after waiting period - dmaWriteEvent.schedule(curTick + DMA_BACKOFF_PERIOD); - return; - } - - uint32_t bytesLeft = curPrd.getByteCount() - dmaInterfaceBytes; - curAddr = curPrd.getBaseAddr() + dmaInterfaceBytes; - dmaAddr = pciToDma(curAddr); - - bytesInPage = bytesInDmaPage(curAddr, bytesLeft); - dmaInterfaceBytes += bytesInPage; - - if (bytesInPage == TheISA::VMPageSize) - dmaWriteFullPages++; - dmaWriteBytes += bytesInPage; - dmaWriteTxs++; - - dmaInterface->doDMA(WriteInvalidate, dmaAddr, - bytesInPage, curTick, - &dmaWriteEvent); - - return; - } - - // setup the initial page and DMA address - curAddr = curPrd.getBaseAddr(); - pageAddr = TheISA::TruncPage(curAddr); - dmaAddr = pciToDma(curAddr); - - // clear out the data buffer - memset(dataBuffer, 0, MAX_DMA_SIZE); - - while (bytesRead < curPrd.getByteCount()) { - // see if we have crossed into a new page - if (pageAddr != TheISA::TruncPage(curAddr)) { - // write the data to memory - memcpy(physmem->dma_addr(dmaAddr, bytesInPage), - (void *)(dataBuffer + (bytesRead - bytesInPage)), - bytesInPage); - - // update the DMA address and page address - pageAddr = TheISA::TruncPage(curAddr); - dmaAddr = pciToDma(curAddr); - - bytesInPage = 0; - } - - if (cmdBytesLeft <= 0) - panic("DMA requested data is larger than # sectors specified\n"); - - readDisk(curSector++, (uint8_t *)(dataBuffer + bytesRead)); - - curAddr += SectorSize; - bytesRead += SectorSize; - bytesInPage += SectorSize; - cmdBytesLeft -= SectorSize; - } - - // write the last page worth read to memory - if (bytesInPage != 0) { - memcpy(physmem->dma_addr(dmaAddr, bytesInPage), - (void *)(dataBuffer + (bytesRead - bytesInPage)), - bytesInPage); - } - // check for the EOT if (curPrd.getEOT()) { assert(cmdBytesLeft == 0); @@ -1188,13 +1012,13 @@ IdeDisk::serialize(ostream &os) SERIALIZE_SCALAR(curPrd.entry.endOfTable); SERIALIZE_SCALAR(curPrdAddr); + /** @todo need to serialized chunk generator stuff!! */ // Serialize current transfer related information SERIALIZE_SCALAR(cmdBytesLeft); SERIALIZE_SCALAR(cmdBytes); SERIALIZE_SCALAR(drqBytesLeft); SERIALIZE_SCALAR(curSector); SERIALIZE_SCALAR(dmaRead); - SERIALIZE_SCALAR(dmaInterfaceBytes); SERIALIZE_SCALAR(intrPending); SERIALIZE_ENUM(devState); SERIALIZE_ENUM(dmaState); @@ -1240,13 +1064,13 @@ IdeDisk::unserialize(Checkpoint *cp, const string §ion) UNSERIALIZE_SCALAR(curPrd.entry.endOfTable); UNSERIALIZE_SCALAR(curPrdAddr); + /** @todo need to serialized chunk generator stuff!! */ // Unserialize current transfer related information UNSERIALIZE_SCALAR(cmdBytes); UNSERIALIZE_SCALAR(cmdBytesLeft); UNSERIALIZE_SCALAR(drqBytesLeft); UNSERIALIZE_SCALAR(curSector); UNSERIALIZE_SCALAR(dmaRead); - UNSERIALIZE_SCALAR(dmaInterfaceBytes); UNSERIALIZE_SCALAR(intrPending); UNSERIALIZE_ENUM(devState); UNSERIALIZE_ENUM(dmaState); @@ -1260,7 +1084,6 @@ static const char *DriveID_strings[] = { "master", "slave" }; BEGIN_DECLARE_SIM_OBJECT_PARAMS(IdeDisk) SimObjectParam<DiskImage *> image; - SimObjectParam<PhysicalMemory *> physmem; SimpleEnumParam<DriveID> driveID; Param<int> delay; @@ -1269,7 +1092,6 @@ END_DECLARE_SIM_OBJECT_PARAMS(IdeDisk) BEGIN_INIT_SIM_OBJECT_PARAMS(IdeDisk) INIT_PARAM(image, "Disk image"), - INIT_PARAM(physmem, "Physical memory"), INIT_ENUM_PARAM(driveID, "Drive ID (0=master 1=slave)", DriveID_strings), INIT_PARAM_DFLT(delay, "Fixed disk delay in microseconds", 1) @@ -1278,7 +1100,7 @@ END_INIT_SIM_OBJECT_PARAMS(IdeDisk) CREATE_SIM_OBJECT(IdeDisk) { - return new IdeDisk(getInstanceName(), image, physmem, driveID, delay); + return new IdeDisk(getInstanceName(), image, driveID, delay); } REGISTER_SIM_OBJECT("IdeDisk", IdeDisk) diff --git a/dev/ide_disk.hh b/dev/ide_disk.hh index 402ae44ee..891c462b5 100644 --- a/dev/ide_disk.hh +++ b/dev/ide_disk.hh @@ -191,12 +191,8 @@ class IdeDisk : public SimObject protected: /** The IDE controller for this disk. */ IdeController *ctrl; - /** The DMA interface to use for transfers */ - DMAInterface<Bus> *dmaInterface; /** The image that contains the data of this disk. */ DiskImage *image; - /** Pointer to physical memory for DMA transfers */ - PhysicalMemory *physmem; protected: /** The disk delay in microseconds. */ @@ -231,8 +227,6 @@ class IdeDisk : public SimObject uint32_t curPrdAddr; /** PRD entry */ PrdTableEntry curPrd; - /** Number of bytes transfered by DMA interface for current transfer */ - uint32_t dmaInterfaceBytes; /** Device ID (master=0/slave=1) */ int devID; /** Interrupt pending */ @@ -250,12 +244,10 @@ class IdeDisk : public SimObject * Create and initialize this Disk. * @param name The name of this disk. * @param img The disk image of this disk. - * @param phys Pointer to physical memory * @param id The disk ID (master=0/slave=1) * @param disk_delay The disk delay in milliseconds */ - IdeDisk(const std::string &name, DiskImage *img, PhysicalMemory *phys, - int id, Tick disk_delay); + IdeDisk(const std::string &name, DiskImage *img, int id, Tick disk_delay); /** * Delete the data buffer. @@ -277,10 +269,9 @@ class IdeDisk : public SimObject * Set the controller for this device * @param c The IDE controller */ - void setController(IdeController *c, DMAInterface<Bus> *dmaIntr) { + void setController(IdeController *c) { if (ctrl) panic("Cannot change the controller once set!\n"); ctrl = c; - dmaInterface = dmaIntr; } // Device register read/write @@ -303,11 +294,17 @@ class IdeDisk : public SimObject friend class EventWrapper<IdeDisk, &IdeDisk::doDmaTransfer>; EventWrapper<IdeDisk, &IdeDisk::doDmaTransfer> dmaTransferEvent; + void doDmaDataRead(); + void doDmaRead(); + ChunkGenerator *dmaReadCG; friend class EventWrapper<IdeDisk, &IdeDisk::doDmaRead>; EventWrapper<IdeDisk, &IdeDisk::doDmaRead> dmaReadWaitEvent; + void doDmaDataWrite(); + void doDmaWrite(); + ChunkGenerator *dmaWriteCG; friend class EventWrapper<IdeDisk, &IdeDisk::doDmaWrite>; EventWrapper<IdeDisk, &IdeDisk::doDmaWrite> dmaWriteWaitEvent; @@ -353,8 +350,6 @@ class IdeDisk : public SimObject inline Addr pciToDma(Addr pciAddr); - uint32_t bytesInDmaPage(Addr curAddr, uint32_t bytesLeft); - /** * Serialize this object to the given output stream. * @param os The stream to serialize to. diff --git a/dev/io_device.cc b/dev/io_device.cc index 6ab876ab8..24f33d84d 100644 --- a/dev/io_device.cc +++ b/dev/io_device.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004-2005 The Regents of The University of Michigan + * Copyright (c) 2006 The Regents of The University of Michigan * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -27,31 +27,213 @@ */ #include "dev/io_device.hh" -#include "mem/bus/base_interface.hh" -#include "mem/bus/dma_interface.hh" #include "sim/builder.hh" -PioDevice::PioDevice(const std::string &name, Platform *p) - : FunctionalMemory(name), platform(p), pioInterface(NULL), pioLatency(0) -{} + +PioPort::PioPort(PioDevice *dev, Platform *p) + : device(dev), platform(p) +{ } + + +Tick +PioPort::recvAtomic(Packet &pkt) +{ + return device->recvAtomic(pkt); +} + +void +PioPort::recvFunctional(Packet &pkt) +{ + device->recvAtomic(pkt); +} + +void +PioPort::getDeviceAddressRanges(AddrRangeList &resp, AddrRangeList &snoop) +{ + snoop.clear(); + device->addressRanges(resp); +} + + +Packet * +PioPort::recvRetry() +{ + Packet* pkt = transmitList.front(); + transmitList.pop_front(); + return pkt; +} + + +void +PioPort::SendEvent::process() +{ + if (port->Port::sendTiming(packet) == Success) + return; + + port->transmitList.push_back(&packet); +} + + +bool +PioPort::recvTiming(Packet &pkt) +{ + device->recvAtomic(pkt); + sendTiming(pkt, pkt.time-pkt.req->getTime()); + return Success; +} PioDevice::~PioDevice() { - if (pioInterface) - delete pioInterface; + if (pioPort) + delete pioPort; } -DEFINE_SIM_OBJECT_CLASS_NAME("PioDevice", PioDevice) +void +PioDevice::init() +{ + if (!pioPort) + panic("Pio port not connected to anything!"); + pioPort->sendStatusChange(Port::RangeChange); +} -DmaDevice::DmaDevice(const std::string &name, Platform *p) - : PioDevice(name, p), dmaInterface(NULL) -{} +void +BasicPioDevice::addressRanges(AddrRangeList &range_list) +{ + assert(pioSize != 0); + range_list.clear(); + range_list.push_back(RangeSize(pioAddr, pioSize)); +} + + +DmaPort::DmaPort(DmaDevice *dev, Platform *p) + : device(dev), platform(p), pendingCount(0) +{ } + +bool +DmaPort::recvTiming(Packet &pkt) +{ + if (pkt.senderState) { + DmaReqState *state; + state = (DmaReqState*)pkt.senderState; + state->completionEvent->schedule(pkt.time - pkt.req->getTime()); + delete pkt.req; + delete &pkt; + } else { + delete pkt.req; + delete &pkt; + } + + return Success; +} + +DmaDevice::DmaDevice(Params *p) + : PioDevice(p), dmaPort(NULL) +{ } + +void +DmaPort::SendEvent::process() +{ + if (port->Port::sendTiming(packet) == Success) + return; + + port->transmitList.push_back(&packet); +} + +Packet * +DmaPort::recvRetry() +{ + Packet* pkt = transmitList.front(); + transmitList.pop_front(); + return pkt; +} +void +DmaPort::dmaAction(Command cmd, Addr addr, int size, Event *event, + uint8_t *data) +{ + + assert(event); + + int prevSize = 0; + Packet basePkt; + Request baseReq(false); + + basePkt.flags = 0; + basePkt.coherence = NULL; + basePkt.senderState = NULL; + basePkt.src = 0; + basePkt.dest = 0; + basePkt.cmd = cmd; + basePkt.result = Unknown; + basePkt.req = NULL; +// baseReq.nicReq = true; + baseReq.setTime(curTick); + + for (ChunkGenerator gen(addr, size, peerBlockSize()); + !gen.done(); gen.next()) { + Packet *pkt = new Packet(basePkt); + Request *req = new Request(baseReq); + pkt->addr = gen.addr(); + pkt->size = gen.size(); + pkt->req = req; + pkt->req->setPaddr(pkt->addr); + pkt->req->setSize(pkt->size); + // Increment the data pointer on a write + if (data) + pkt->dataStatic(data + prevSize) ; + prevSize += pkt->size; + // Set the last bit of the dma as the final packet for this dma + // and set it's completion event. + if (prevSize == size) { + DmaReqState *state = new DmaReqState(event, true); + + pkt->senderState = (void*)state; + } + assert(pendingCount >= 0); + pendingCount++; + sendDma(pkt); + } + // since this isn't getting used and we want a check to make sure that all + // packets had data in them at some point. + basePkt.dataStatic((uint8_t*)NULL); +} + + +void +DmaPort::sendDma(Packet *pkt) +{ + // some kind of selction between access methods + // more work is going to have to be done to make + // switching actually work + /* MemState state = device->platform->system->memState; + + if (state == Timing) { + if (sendTiming(pkt) == Failure) + transmitList.push_back(&packet); + } else if (state == Atomic) {*/ + sendAtomic(*pkt); + if (pkt->senderState) { + DmaReqState *state = (DmaReqState*)pkt->senderState; + state->completionEvent->schedule(curTick + (pkt->time - pkt->req->getTime()) +1); + } + pendingCount--; + assert(pendingCount >= 0); + delete pkt->req; + delete pkt; + +/* } else if (state == Functional) { + sendFunctional(pkt); + // Is this correct??? + completionEvent->schedule(pkt.req->responseTime - pkt.req->requestTime); + completionEvent == NULL; + } else + panic("Unknown memory command state."); + */ +} DmaDevice::~DmaDevice() { - if (dmaInterface) - delete dmaInterface; + if (dmaPort) + delete dmaPort; } -DEFINE_SIM_OBJECT_CLASS_NAME("DmaDevice", DmaDevice) diff --git a/dev/io_device.hh b/dev/io_device.hh index bcfd062b9..e492ccf0b 100644 --- a/dev/io_device.hh +++ b/dev/io_device.hh @@ -29,34 +29,307 @@ #ifndef __DEV_IO_DEVICE_HH__ #define __DEV_IO_DEVICE_HH__ -#include "mem/functional/functional.hh" +#include "base/chunk_generator.hh" +#include "mem/mem_object.hh" +#include "mem/packet_impl.hh" +#include "sim/eventq.hh" +#include "sim/sim_object.hh" -class BaseInterface; -class Bus; -class HierParams; class Platform; -template <class BusType> class DMAInterface; +class PioDevice; +class DmaDevice; +class System; -class PioDevice : public FunctionalMemory +/** + * The PioPort class is a programmed i/o port that all devices that are + * sensitive to an address range use. The port takes all the memory + * access types and roles them into one read() and write() call that the device + * must respond to. The device must also provide the addressRanges() function + * with which it returns the address ranges it is interested in. An extra + * sendTiming() function is implemented which takes an delay. In this way the + * device can immediatly call sendTiming(pkt, time) after processing a request + * and the request will be handled by the port even if the port bus the device + * connects to is blocked. + */ +class PioPort : public Port +{ + protected: + /** The device that this port serves. */ + PioDevice *device; + + /** The platform that device/port are in. This is used to select which mode + * we are currently operating in. */ + Platform *platform; + + /** A list of outgoing timing response packets that haven't been serviced + * yet. */ + std::list<Packet*> transmitList; + + /** The current status of the peer(bus) that we are connected to. */ + Status peerStatus; + + virtual bool recvTiming(Packet &pkt); + + virtual Tick recvAtomic(Packet &pkt); + + virtual void recvFunctional(Packet &pkt) ; + + virtual void recvStatusChange(Status status) + { peerStatus = status; } + + virtual void getDeviceAddressRanges(AddrRangeList &resp, AddrRangeList &snoop); + + /** + * This class is used to implemented sendTiming() with a delay. When a delay + * is requested a new event is created. When the event time expires it + * attempts to send the packet. If it cannot, the packet is pushed onto the + * transmit list to be sent when recvRetry() is called. */ + class SendEvent : public Event + { + PioPort *port; + Packet packet; + + SendEvent(PioPort *p, Packet &pkt, Tick t) + : Event(&mainEventQueue), packet(pkt) + { schedule(curTick + t); } + + virtual void process(); + + virtual const char *description() + { return "Future scheduled sendTiming event"; } + + friend class PioPort; + }; + + /** Schedule a sendTiming() event to be called in the future. */ + void sendTiming(Packet &pkt, Tick time) + { new PioPort::SendEvent(this, pkt, time); } + + /** This function pops the last element off the transmit list and sends it.*/ + virtual Packet *recvRetry(); + + public: + PioPort(PioDevice *dev, Platform *p); + + friend class PioPort::SendEvent; +}; + + +struct DmaReqState +{ + Event *completionEvent; + bool final; + DmaReqState(Event *ce, bool f) + : completionEvent(ce), final(f) + {} +}; + +class DmaPort : public Port { protected: + DmaDevice *device; + std::list<Packet*> transmitList; + + /** The platform that device/port are in. This is used to select which mode + * we are currently operating in. */ Platform *platform; - BaseInterface *pioInterface; - Tick pioLatency; + + /** Number of outstanding packets the dma port has. */ + int pendingCount; + + virtual bool recvTiming(Packet &pkt); + virtual Tick recvAtomic(Packet &pkt) + { panic("dma port shouldn't be used for pio access."); } + virtual void recvFunctional(Packet &pkt) + { panic("dma port shouldn't be used for pio access."); } + + virtual void recvStatusChange(Status status) + { ; } + + virtual Packet *recvRetry() ; + + virtual void getDeviceAddressRanges(AddrRangeList &resp, AddrRangeList &snoop) + { resp.clear(); snoop.clear(); } + + class SendEvent : public Event + { + DmaPort *port; + Packet packet; + + SendEvent(PioPort *p, Packet &pkt, Tick t) + : Event(&mainEventQueue), packet(pkt) + { schedule(curTick + t); } + + virtual void process(); + + virtual const char *description() + { return "Future scheduled sendTiming event"; } + + friend class DmaPort; + }; + + void sendDma(Packet *pkt); public: - PioDevice(const std::string &name, Platform *p); + DmaPort(DmaDevice *dev, Platform *p); + + void dmaAction(Command cmd, Addr addr, int size, Event *event, + uint8_t *data = NULL); + + bool dmaPending() { return pendingCount > 0; } + + friend class DmaPort::SendEvent; + +}; + +/** + * This device is the base class which all devices senstive to an address range + * inherit from. There are three pure virtual functions which all devices must + * implement addressRanges(), read(), and write(). The magic do choose which + * mode we are in, etc is handled by the PioPort so the device doesn't have to + * bother. + */ + +class PioDevice : public MemObject +{ + protected: + + /** The platform we are in. This is used to decide what type of memory + * transaction we should perform. */ + Platform *platform; + + /** The pioPort that handles the requests for us and provides us requests + * that it sees. */ + PioPort *pioPort; + + virtual void addressRanges(AddrRangeList &range_list) = 0; + + /** As far as the devices are concerned they only accept atomic transactions + * which are converted to either a write or a read. */ + Tick recvAtomic(Packet &pkt) + { return pkt.cmd == Read ? this->read(pkt) : this->write(pkt); } + + /** Pure virtual function that the device must implement. Called when a read + * command is recieved by the port. + * @param pkt Packet describing this request + * @return number of ticks it took to complete + */ + virtual Tick read(Packet &pkt) = 0; + + /** Pure virtual function that the device must implement. Called when a + * write command is recieved by the port. + * @param pkt Packet describing this request + * @return number of ticks it took to complete + */ + virtual Tick write(Packet &pkt) = 0; + + public: + /** Params struct which is extended through each device based on the + * parameters it needs. Since we are re-writing everything, we might as well + * start from the bottom this time. */ + + struct Params + { + std::string name; + Platform *platform; + System *system; + }; + + protected: + Params *_params; + + public: + const Params *params() const { return _params; } + + PioDevice(Params *p) + : MemObject(p->name), platform(p->platform), pioPort(NULL), + _params(p) + {} + virtual ~PioDevice(); + + virtual void init(); + + virtual Port *getPort(const std::string &if_name) + { + if (if_name == "pio") { + if (pioPort != NULL) + panic("pio port already connected to."); + pioPort = new PioPort(this, params()->platform); + return pioPort; + } else + return NULL; + } + friend class PioPort; + +}; + +class BasicPioDevice : public PioDevice +{ + public: + struct Params : public PioDevice::Params + { + Addr pio_addr; + Tick pio_delay; + }; + + protected: + /** Address that the device listens to. */ + Addr pioAddr; + + /** Size that the device's address range. */ + Addr pioSize; + + /** Delay that the device experinces on an access. */ + Tick pioDelay; + + public: + BasicPioDevice(Params *p) + : PioDevice(p), pioAddr(p->pio_addr), pioSize(0), pioDelay(p->pio_delay) + {} + + /** return the address ranges that this device responds to. + * @params range_list range list to populate with ranges + */ + void addressRanges(AddrRangeList &range_list); + }; class DmaDevice : public PioDevice { protected: - DMAInterface<Bus> *dmaInterface; + DmaPort *dmaPort; public: - DmaDevice(const std::string &name, Platform *p); + DmaDevice(Params *p); virtual ~DmaDevice(); + + void dmaWrite(Addr addr, int size, Event *event, uint8_t *data) + { dmaPort->dmaAction(Write, addr, size, event, data) ; } + + void dmaRead(Addr addr, int size, Event *event, uint8_t *data = NULL) + { dmaPort->dmaAction(Read, addr, size, event, data); } + + bool dmaPending() { return dmaPort->dmaPending(); } + + virtual Port *getPort(const std::string &if_name) + { + if (if_name == "pio") { + if (pioPort != NULL) + panic("pio port already connected to."); + pioPort = new PioPort(this, params()->platform); + return pioPort; + } else if (if_name == "dma") { + if (dmaPort != NULL) + panic("dma port already connected to."); + dmaPort = new DmaPort(this, params()->platform); + return dmaPort; + } else + return NULL; + } + + friend class DmaPort; }; + #endif // __DEV_IO_DEVICE_HH__ diff --git a/dev/isa_fake.cc b/dev/isa_fake.cc index 2afebbded..2f392a41a 100644 --- a/dev/isa_fake.cc +++ b/dev/isa_fake.cc @@ -35,106 +35,87 @@ #include <vector> #include "base/trace.hh" -#include "cpu/exec_context.hh" #include "dev/isa_fake.hh" -#include "mem/bus/bus.hh" -#include "mem/bus/pio_interface.hh" -#include "mem/bus/pio_interface_impl.hh" -#include "mem/functional/memory_control.hh" +#include "mem/packet.hh" #include "sim/builder.hh" #include "sim/system.hh" using namespace std; -using namespace TheISA; -IsaFake::IsaFake(const string &name, Addr a, MemoryController *mmu, - HierParams *hier, Bus *pio_bus, Addr size) - : PioDevice(name, NULL), addr(a) +IsaFake::IsaFake(Params *p) + : BasicPioDevice(p) { - mmu->add_child(this, RangeSize(addr, size)); - - if (pio_bus) { - pioInterface = newPioInterface(name + ".pio", hier, pio_bus, this, - &IsaFake::cacheAccess); - pioInterface->addAddrRange(RangeSize(addr, size)); - } + pioSize = p->pio_size; } -Fault -IsaFake::read(MemReqPtr &req, uint8_t *data) +Tick +IsaFake::read(Packet &pkt) { - DPRINTF(Tsunami, "read va=%#x size=%d\n", - req->vaddr, req->size); + assert(pkt.result == Unknown); + assert(pkt.addr >= pioAddr && pkt.addr < pioAddr + pioSize); -#if TRACING_ON - Addr daddr = (req->paddr - (addr & EV5::PAddrImplMask)) >> 6; -#endif + pkt.time += pioDelay; - switch (req->size) { + DPRINTF(Tsunami, "read va=%#x size=%d\n", pkt.addr, pkt.size); - case sizeof(uint64_t): - *(uint64_t*)data = 0xFFFFFFFFFFFFFFFFULL; - return NoFault; + switch (pkt.size) { + pkt.set(0xFFFFFFFFFFFFFFFFULL); + break; case sizeof(uint32_t): - *(uint32_t*)data = 0xFFFFFFFF; - return NoFault; + pkt.set((uint32_t)0xFFFFFFFF); + break; case sizeof(uint16_t): - *(uint16_t*)data = 0xFFFF; - return NoFault; + pkt.set((uint16_t)0xFFFF); + break; case sizeof(uint8_t): - *(uint8_t*)data = 0xFF; - return NoFault; - + pkt.set((uint8_t)0xFF); + break; default: panic("invalid access size(?) for PCI configspace!\n"); } - DPRINTFN("Isa FakeSMC ERROR: read daddr=%#x size=%d\n", daddr, req->size); - - return NoFault; -} - -Fault -IsaFake::write(MemReqPtr &req, const uint8_t *data) -{ - DPRINTF(Tsunami, "write - va=%#x size=%d \n", - req->vaddr, req->size); - - //:Addr daddr = (req->paddr & addr_mask) >> 6; - - return NoFault; + pkt.result = Success; + return pioDelay; } Tick -IsaFake::cacheAccess(MemReqPtr &req) +IsaFake::write(Packet &pkt) { - return curTick; + pkt.time += pioDelay; + DPRINTF(Tsunami, "write - va=%#x size=%d \n", pkt.addr, pkt.size); + pkt.result = Success; + return pioDelay; } BEGIN_DECLARE_SIM_OBJECT_PARAMS(IsaFake) - SimObjectParam<MemoryController *> mmu; - Param<Addr> addr; - SimObjectParam<Bus*> pio_bus; + Param<Addr> pio_addr; Param<Tick> pio_latency; - SimObjectParam<HierParams *> hier; - Param<Addr> size; + Param<Addr> pio_size; + SimObjectParam<Platform *> platform; + SimObjectParam<System *> system; END_DECLARE_SIM_OBJECT_PARAMS(IsaFake) BEGIN_INIT_SIM_OBJECT_PARAMS(IsaFake) - INIT_PARAM(mmu, "Memory Controller"), - INIT_PARAM(addr, "Device Address"), - INIT_PARAM_DFLT(pio_bus, "The IO Bus to attach to", NULL), - INIT_PARAM_DFLT(pio_latency, "Programmed IO latency", 1000), - INIT_PARAM_DFLT(hier, "Hierarchy global variables", &defaultHierParams), - INIT_PARAM_DFLT(size, "Size of address range", 0x8) + INIT_PARAM(pio_addr, "Device Address"), + INIT_PARAM(pio_latency, "Programmed IO latency"), + INIT_PARAM(pio_size, "Size of address range"), + INIT_PARAM(platform, "platform"), + INIT_PARAM(system, "system object") END_INIT_SIM_OBJECT_PARAMS(IsaFake) CREATE_SIM_OBJECT(IsaFake) { - return new IsaFake(getInstanceName(), addr, mmu, hier, pio_bus, size); + IsaFake::Params *p = new IsaFake::Params; + p->name = getInstanceName(); + p->pio_addr = pio_addr; + p->pio_delay = pio_latency; + p->pio_size = pio_size; + p->platform = platform; + p->system = system; + return new IsaFake(p); } REGISTER_SIM_OBJECT("IsaFake", IsaFake) diff --git a/dev/isa_fake.hh b/dev/isa_fake.hh index 73e40c681..29050833d 100644 --- a/dev/isa_fake.hh +++ b/dev/isa_fake.hh @@ -37,51 +37,42 @@ #include "base/range.hh" #include "dev/io_device.hh" -class MemoryController; - /** * IsaFake is a device that returns -1 on all reads and * accepts all writes. It is meant to be placed at an address range * so that an mcheck doesn't occur when an os probes a piece of hw * that doesn't exist (e.g. UARTs1-3). */ -class IsaFake : public PioDevice +class IsaFake : public BasicPioDevice { - private: - /** The address in memory that we respond to */ - Addr addr; + public: + struct Params : public BasicPioDevice::Params + { + Addr pio_size; + }; + protected: + const Params *params() const { return (const Params*)_params; } public: /** * The constructor for Tsunmami Fake just registers itself with the MMU. - * @param name name of this device. - * @param a address to respond to. - * @param mmu the mmu we register with. - * @param size number of addresses to respond to + * @param p params structure */ - IsaFake(const std::string &name, Addr a, MemoryController *mmu, - HierParams *hier, Bus *pio_bus, Addr size = 0x8); + IsaFake(Params *p); /** * This read always returns -1. * @param req The memory request. * @param data Where to put the data. */ - virtual Fault read(MemReqPtr &req, uint8_t *data); + virtual Tick read(Packet &pkt); /** * All writes are simply ignored. * @param req The memory request. * @param data the data to not write. */ - virtual Fault write(MemReqPtr &req, const uint8_t *data); - - /** - * Return how long this access will take. - * @param req the memory request to calcuate - * @return Tick when the request is done - */ - Tick cacheAccess(MemReqPtr &req); + virtual Tick write(Packet &pkt); }; -#endif // __ISA_FAKE_HH__ +#endif // __TSUNAMI_FAKE_HH__ diff --git a/dev/ns_gige.cc b/dev/ns_gige.cc index ed8c794f9..a2e224ed0 100644 --- a/dev/ns_gige.cc +++ b/dev/ns_gige.cc @@ -34,22 +34,18 @@ #include <deque> #include <string> +#include "arch/alpha/ev5.hh" #include "base/inet.hh" #include "cpu/exec_context.hh" #include "dev/etherlink.hh" #include "dev/ns_gige.hh" #include "dev/pciconfigall.hh" -#include "mem/bus/bus.hh" -#include "mem/bus/dma_interface.hh" -#include "mem/bus/pio_interface.hh" -#include "mem/bus/pio_interface_impl.hh" -#include "mem/functional/memory_control.hh" -#include "mem/functional/physical.hh" +#include "mem/packet.hh" #include "sim/builder.hh" #include "sim/debug.hh" #include "sim/host.hh" #include "sim/stats.hh" -#include "arch/vtophys.hh" +#include "sim/system.hh" const char *NsRxStateStrings[] = { @@ -107,29 +103,9 @@ NSGigE::NSGigE(Params *p) txEvent(this), rxFilterEnable(p->rx_filter), acceptBroadcast(false), acceptMulticast(false), acceptUnicast(false), acceptPerfect(false), acceptArp(false), multicastHashEnable(false), - physmem(p->pmem), intrTick(0), cpuPendingIntr(false), + intrTick(0), cpuPendingIntr(false), intrEvent(0), interface(0) { - if (p->pio_bus) { - pioInterface = newPioInterface(name() + ".pio", p->hier, - p->pio_bus, this, - &NSGigE::cacheAccess); - pioLatency = p->pio_latency * p->pio_bus->clockRate; - } - - if (p->header_bus) { - if (p->payload_bus) - dmaInterface = new DMAInterface<Bus>(name() + ".dma", - p->header_bus, - p->payload_bus, 1, - p->dma_no_allocate); - else - dmaInterface = new DMAInterface<Bus>(name() + ".dma", - p->header_bus, - p->header_bus, 1, - p->dma_no_allocate); - } else if (p->payload_bus) - panic("Must define a header bus if defining a payload bus"); intrDelay = p->intr_delay; dmaReadDelay = p->dma_read_delay; @@ -483,30 +459,18 @@ NSGigE::regStats() rxPacketRate = rxPackets / simSeconds; } -/** - * This is to read the PCI general configuration registers - */ -void -NSGigE::readConfig(int offset, int size, uint8_t *data) -{ - if (offset < PCI_DEVICE_SPECIFIC) - PciDev::readConfig(offset, size, data); - else - panic("Device specific PCI config space not implemented!\n"); -} /** * This is to write to the PCI general configuration registers */ void -NSGigE::writeConfig(int offset, int size, const uint8_t* data) +NSGigE::writeConfig(int offset, const uint16_t data) { if (offset < PCI_DEVICE_SPECIFIC) - PciDev::writeConfig(offset, size, data); + PciDev::writeConfig(offset, data); else panic("Device specific PCI config space not implemented!\n"); - // Need to catch writes to BARs to update the PIO interface switch (offset) { // seems to work fine without all these PCI settings, but i // put in the IO to double check, an assertion will fail if we @@ -516,39 +480,6 @@ NSGigE::writeConfig(int offset, int size, const uint8_t* data) ioEnable = true; else ioEnable = false; - -#if 0 - if (config.data[offset] & PCI_CMD_BME) { - bmEnabled = true; - } - else { - bmEnabled = false; - } - - if (config.data[offset] & PCI_CMD_MSE) { - memEnable = true; - } - else { - memEnable = false; - } -#endif - break; - - case PCI0_BASE_ADDR0: - if (BARAddrs[0] != 0) { - if (pioInterface) - pioInterface->addAddrRange(RangeSize(BARAddrs[0], BARSize[0])); - - BARAddrs[0] &= EV5::PAddrUncachedMask; - } - break; - case PCI0_BASE_ADDR1: - if (BARAddrs[1] != 0) { - if (pioInterface) - pioInterface->addAddrRange(RangeSize(BARAddrs[1], BARSize[1])); - - BARAddrs[1] &= EV5::PAddrUncachedMask; - } break; } } @@ -557,15 +488,18 @@ NSGigE::writeConfig(int offset, int size, const uint8_t* data) * This reads the device registers, which are detailed in the NS83820 * spec sheet */ -Fault -NSGigE::read(MemReqPtr &req, uint8_t *data) +Tick +NSGigE::read(Packet &pkt) { assert(ioEnable); + pkt.time += pioDelay; + pkt.allocate(); + //The mask is to give you only the offset into the device register file - Addr daddr = req->paddr & 0xfff; - DPRINTF(EthernetPIO, "read da=%#x pa=%#x va=%#x size=%d\n", - daddr, req->paddr, req->vaddr, req->size); + Addr daddr = pkt.addr & 0xfff; + DPRINTF(EthernetPIO, "read da=%#x pa=%#x size=%d\n", + daddr, pkt.addr, pkt.size); // there are some reserved registers, you can see ns_gige_reg.h and @@ -573,240 +507,246 @@ NSGigE::read(MemReqPtr &req, uint8_t *data) if (daddr > LAST && daddr <= RESERVED) { panic("Accessing reserved register"); } else if (daddr > RESERVED && daddr <= 0x3FC) { - readConfig(daddr & 0xff, req->size, data); - return NoFault; + if (pkt.size == sizeof(uint8_t)) + readConfig(daddr & 0xff, pkt.getPtr<uint8_t>()); + if (pkt.size == sizeof(uint16_t)) + readConfig(daddr & 0xff, pkt.getPtr<uint16_t>()); + if (pkt.size == sizeof(uint32_t)) + readConfig(daddr & 0xff, pkt.getPtr<uint32_t>()); + pkt.result = Success; + return pioDelay; } else if (daddr >= MIB_START && daddr <= MIB_END) { // don't implement all the MIB's. hopefully the kernel // doesn't actually DEPEND upon their values // MIB are just hardware stats keepers - uint32_t ® = *(uint32_t *) data; - reg = 0; - return NoFault; + pkt.set<uint32_t>(0); + pkt.result = Success; + return pioDelay; } else if (daddr > 0x3FC) panic("Something is messed up!\n"); - switch (req->size) { - case sizeof(uint32_t): - { - uint32_t ® = *(uint32_t *)data; - uint16_t rfaddr; - - switch (daddr) { - case CR: - reg = regs.command; - //these are supposed to be cleared on a read - reg &= ~(CR_RXD | CR_TXD | CR_TXR | CR_RXR); - break; + assert(pkt.size == sizeof(uint32_t)); + uint32_t ® = *pkt.getPtr<uint32_t>(); + uint16_t rfaddr; - case CFGR: - reg = regs.config; - break; + switch (daddr) { + case CR: + reg = regs.command; + //these are supposed to be cleared on a read + reg &= ~(CR_RXD | CR_TXD | CR_TXR | CR_RXR); + break; - case MEAR: - reg = regs.mear; - break; + case CFGR: + reg = regs.config; + break; - case PTSCR: - reg = regs.ptscr; - break; + case MEAR: + reg = regs.mear; + break; - case ISR: - reg = regs.isr; - devIntrClear(ISR_ALL); - break; + case PTSCR: + reg = regs.ptscr; + break; - case IMR: - reg = regs.imr; - break; + case ISR: + reg = regs.isr; + devIntrClear(ISR_ALL); + break; - case IER: - reg = regs.ier; - break; + case IMR: + reg = regs.imr; + break; - case IHR: - reg = regs.ihr; - break; + case IER: + reg = regs.ier; + break; - case TXDP: - reg = regs.txdp; - break; + case IHR: + reg = regs.ihr; + break; - case TXDP_HI: - reg = regs.txdp_hi; - break; + case TXDP: + reg = regs.txdp; + break; - case TX_CFG: - reg = regs.txcfg; - break; + case TXDP_HI: + reg = regs.txdp_hi; + break; - case GPIOR: - reg = regs.gpior; - break; + case TX_CFG: + reg = regs.txcfg; + break; - case RXDP: - reg = regs.rxdp; - break; + case GPIOR: + reg = regs.gpior; + break; - case RXDP_HI: - reg = regs.rxdp_hi; - break; + case RXDP: + reg = regs.rxdp; + break; - case RX_CFG: - reg = regs.rxcfg; - break; + case RXDP_HI: + reg = regs.rxdp_hi; + break; - case PQCR: - reg = regs.pqcr; - break; + case RX_CFG: + reg = regs.rxcfg; + break; - case WCSR: - reg = regs.wcsr; - break; + case PQCR: + reg = regs.pqcr; + break; - case PCR: - reg = regs.pcr; - break; + case WCSR: + reg = regs.wcsr; + break; + + case PCR: + reg = regs.pcr; + break; + + // see the spec sheet for how RFCR and RFDR work + // basically, you write to RFCR to tell the machine + // what you want to do next, then you act upon RFDR, + // and the device will be prepared b/c of what you + // wrote to RFCR + case RFCR: + reg = regs.rfcr; + break; - // see the spec sheet for how RFCR and RFDR work - // basically, you write to RFCR to tell the machine - // what you want to do next, then you act upon RFDR, - // and the device will be prepared b/c of what you - // wrote to RFCR - case RFCR: - reg = regs.rfcr; + case RFDR: + rfaddr = (uint16_t)(regs.rfcr & RFCR_RFADDR); + switch (rfaddr) { + // Read from perfect match ROM octets + case 0x000: + reg = rom.perfectMatch[1]; + reg = reg << 8; + reg += rom.perfectMatch[0]; + break; + case 0x002: + reg = rom.perfectMatch[3] << 8; + reg += rom.perfectMatch[2]; break; + case 0x004: + reg = rom.perfectMatch[5] << 8; + reg += rom.perfectMatch[4]; + break; + default: + // Read filter hash table + if (rfaddr >= FHASH_ADDR && + rfaddr < FHASH_ADDR + FHASH_SIZE) { - case RFDR: - rfaddr = (uint16_t)(regs.rfcr & RFCR_RFADDR); - switch (rfaddr) { - // Read from perfect match ROM octets - case 0x000: - reg = rom.perfectMatch[1]; - reg = reg << 8; - reg += rom.perfectMatch[0]; - break; - case 0x002: - reg = rom.perfectMatch[3] << 8; - reg += rom.perfectMatch[2]; - break; - case 0x004: - reg = rom.perfectMatch[5] << 8; - reg += rom.perfectMatch[4]; - break; - default: - // Read filter hash table - if (rfaddr >= FHASH_ADDR && - rfaddr < FHASH_ADDR + FHASH_SIZE) { - - // Only word-aligned reads supported - if (rfaddr % 2) - panic("unaligned read from filter hash table!"); - - reg = rom.filterHash[rfaddr - FHASH_ADDR + 1] << 8; - reg += rom.filterHash[rfaddr - FHASH_ADDR]; - break; - } + // Only word-aligned reads supported + if (rfaddr % 2) + panic("unaligned read from filter hash table!"); - panic("reading RFDR for something other than pattern" - " matching or hashing! %#x\n", rfaddr); + reg = rom.filterHash[rfaddr - FHASH_ADDR + 1] << 8; + reg += rom.filterHash[rfaddr - FHASH_ADDR]; + break; } - break; - case SRR: - reg = regs.srr; - break; + panic("reading RFDR for something other than pattern" + " matching or hashing! %#x\n", rfaddr); + } + break; - case MIBC: - reg = regs.mibc; - reg &= ~(MIBC_MIBS | MIBC_ACLR); - break; + case SRR: + reg = regs.srr; + break; - case VRCR: - reg = regs.vrcr; - break; + case MIBC: + reg = regs.mibc; + reg &= ~(MIBC_MIBS | MIBC_ACLR); + break; - case VTCR: - reg = regs.vtcr; - break; + case VRCR: + reg = regs.vrcr; + break; - case VDR: - reg = regs.vdr; - break; + case VTCR: + reg = regs.vtcr; + break; - case CCSR: - reg = regs.ccsr; - break; + case VDR: + reg = regs.vdr; + break; - case TBICR: - reg = regs.tbicr; - break; + case CCSR: + reg = regs.ccsr; + break; - case TBISR: - reg = regs.tbisr; - break; + case TBICR: + reg = regs.tbicr; + break; - case TANAR: - reg = regs.tanar; - break; + case TBISR: + reg = regs.tbisr; + break; - case TANLPAR: - reg = regs.tanlpar; - break; + case TANAR: + reg = regs.tanar; + break; - case TANER: - reg = regs.taner; - break; + case TANLPAR: + reg = regs.tanlpar; + break; - case TESR: - reg = regs.tesr; - break; + case TANER: + reg = regs.taner; + break; - case M5REG: - reg = 0; - if (params()->rx_thread) - reg |= M5REG_RX_THREAD; - if (params()->tx_thread) - reg |= M5REG_TX_THREAD; - if (params()->rss) - reg |= M5REG_RSS; - break; + case TESR: + reg = regs.tesr; + break; - default: - panic("reading unimplemented register: addr=%#x", daddr); - } + case M5REG: + reg = 0; + if (params()->rx_thread) + reg |= M5REG_RX_THREAD; + if (params()->tx_thread) + reg |= M5REG_TX_THREAD; + if (params()->rss) + reg |= M5REG_RSS; + break; - DPRINTF(EthernetPIO, "read from %#x: data=%d data=%#x\n", - daddr, reg, reg); + default: + panic("reading unimplemented register: addr=%#x", daddr); } - break; - default: - panic("accessing register with invalid size: addr=%#x, size=%d", - daddr, req->size); - } + DPRINTF(EthernetPIO, "read from %#x: data=%d data=%#x\n", + daddr, reg, reg); - return NoFault; + pkt.result = Success; + return pioDelay; } -Fault -NSGigE::write(MemReqPtr &req, const uint8_t *data) +Tick +NSGigE::write(Packet &pkt) { assert(ioEnable); - Addr daddr = req->paddr & 0xfff; - DPRINTF(EthernetPIO, "write da=%#x pa=%#x va=%#x size=%d\n", - daddr, req->paddr, req->vaddr, req->size); + Addr daddr = pkt.addr & 0xfff; + DPRINTF(EthernetPIO, "write da=%#x pa=%#x size=%d\n", + daddr, pkt.addr, pkt.size); + + pkt.time += pioDelay; if (daddr > LAST && daddr <= RESERVED) { panic("Accessing reserved register"); } else if (daddr > RESERVED && daddr <= 0x3FC) { - writeConfig(daddr & 0xff, req->size, data); - return NoFault; + if (pkt.size == sizeof(uint8_t)) + writeConfig(daddr & 0xff, pkt.get<uint8_t>()); + if (pkt.size == sizeof(uint16_t)) + writeConfig(daddr & 0xff, pkt.get<uint16_t>()); + if (pkt.size == sizeof(uint32_t)) + writeConfig(daddr & 0xff, pkt.get<uint32_t>()); + pkt.result = Success; + return pioDelay; } else if (daddr > 0x3FC) panic("Something is messed up!\n"); - if (req->size == sizeof(uint32_t)) { - uint32_t reg = *(uint32_t *)data; + if (pkt.size == sizeof(uint32_t)) { + uint32_t reg = pkt.get<uint32_t>(); uint16_t rfaddr; DPRINTF(EthernetPIO, "write data=%d data=%#x\n", reg, reg); @@ -1192,8 +1132,8 @@ NSGigE::write(MemReqPtr &req, const uint8_t *data) } else { panic("Invalid Request Size"); } - - return NoFault; + pkt.result = Success; + return pioDelay; } void @@ -1443,42 +1383,17 @@ NSGigE::regsReset() acceptArp = false; } -void -NSGigE::rxDmaReadCopy() -{ - assert(rxDmaState == dmaReading); - - physmem->dma_read((uint8_t *)rxDmaData, rxDmaAddr, rxDmaLen); - rxDmaState = dmaIdle; - - DPRINTF(EthernetDMA, "rx dma read paddr=%#x len=%d\n", - rxDmaAddr, rxDmaLen); - DDUMP(EthernetDMA, rxDmaData, rxDmaLen); -} - bool NSGigE::doRxDmaRead() { assert(rxDmaState == dmaIdle || rxDmaState == dmaReadWaiting); rxDmaState = dmaReading; - if (dmaInterface && !rxDmaFree) { - if (dmaInterface->busy()) - rxDmaState = dmaReadWaiting; - else - dmaInterface->doDMA(Read, rxDmaAddr, rxDmaLen, curTick, - &rxDmaReadEvent, true); - return true; - } - - if (dmaReadDelay == 0 && dmaReadFactor == 0) { - rxDmaReadCopy(); - return false; - } + if (dmaPending()) + rxDmaState = dmaReadWaiting; + else + dmaRead(rxDmaAddr, rxDmaLen, &rxDmaReadEvent, (uint8_t*)rxDmaData); - Tick factor = ((rxDmaLen + ULL(63)) >> ULL(6)) * dmaReadFactor; - Tick start = curTick + dmaReadDelay + factor; - rxDmaReadEvent.schedule(start); return true; } @@ -1486,7 +1401,11 @@ void NSGigE::rxDmaReadDone() { assert(rxDmaState == dmaReading); - rxDmaReadCopy(); + rxDmaState = dmaIdle; + + DPRINTF(EthernetDMA, "rx dma read paddr=%#x len=%d\n", + rxDmaAddr, rxDmaLen); + DDUMP(EthernetDMA, rxDmaData, rxDmaLen); // If the transmit state machine has a pending DMA, let it go first if (txDmaState == dmaReadWaiting || txDmaState == dmaWriteWaiting) @@ -1495,42 +1414,16 @@ NSGigE::rxDmaReadDone() rxKick(); } -void -NSGigE::rxDmaWriteCopy() -{ - assert(rxDmaState == dmaWriting); - - physmem->dma_write(rxDmaAddr, (uint8_t *)rxDmaData, rxDmaLen); - rxDmaState = dmaIdle; - - DPRINTF(EthernetDMA, "rx dma write paddr=%#x len=%d\n", - rxDmaAddr, rxDmaLen); - DDUMP(EthernetDMA, rxDmaData, rxDmaLen); -} - bool NSGigE::doRxDmaWrite() { assert(rxDmaState == dmaIdle || rxDmaState == dmaWriteWaiting); rxDmaState = dmaWriting; - if (dmaInterface && !rxDmaFree) { - if (dmaInterface->busy()) - rxDmaState = dmaWriteWaiting; - else - dmaInterface->doDMA(WriteInvalidate, rxDmaAddr, rxDmaLen, curTick, - &rxDmaWriteEvent, true); - return true; - } - - if (dmaWriteDelay == 0 && dmaWriteFactor == 0) { - rxDmaWriteCopy(); - return false; - } - - Tick factor = ((rxDmaLen + ULL(63)) >> ULL(6)) * dmaWriteFactor; - Tick start = curTick + dmaWriteDelay + factor; - rxDmaWriteEvent.schedule(start); + if (dmaPending()) + rxDmaState = dmaWriteWaiting; + else + dmaWrite(rxDmaAddr, rxDmaLen, &rxDmaWriteEvent, (uint8_t*)rxDmaData); return true; } @@ -1538,7 +1431,11 @@ void NSGigE::rxDmaWriteDone() { assert(rxDmaState == dmaWriting); - rxDmaWriteCopy(); + rxDmaState = dmaIdle; + + DPRINTF(EthernetDMA, "rx dma write paddr=%#x len=%d\n", + rxDmaAddr, rxDmaLen); + DDUMP(EthernetDMA, rxDmaData, rxDmaLen); // If the transmit state machine has a pending DMA, let it go first if (txDmaState == dmaReadWaiting || txDmaState == dmaWriteWaiting) @@ -1935,42 +1832,17 @@ NSGigE::transmit() } } -void -NSGigE::txDmaReadCopy() -{ - assert(txDmaState == dmaReading); - - physmem->dma_read((uint8_t *)txDmaData, txDmaAddr, txDmaLen); - txDmaState = dmaIdle; - - DPRINTF(EthernetDMA, "tx dma read paddr=%#x len=%d\n", - txDmaAddr, txDmaLen); - DDUMP(EthernetDMA, txDmaData, txDmaLen); -} - bool NSGigE::doTxDmaRead() { assert(txDmaState == dmaIdle || txDmaState == dmaReadWaiting); txDmaState = dmaReading; - if (dmaInterface && !txDmaFree) { - if (dmaInterface->busy()) - txDmaState = dmaReadWaiting; - else - dmaInterface->doDMA(Read, txDmaAddr, txDmaLen, curTick, - &txDmaReadEvent, true); - return true; - } - - if (dmaReadDelay == 0 && dmaReadFactor == 0.0) { - txDmaReadCopy(); - return false; - } + if (dmaPending()) + txDmaState = dmaReadWaiting; + else + dmaRead(txDmaAddr, txDmaLen, &txDmaReadEvent, (uint8_t*)txDmaData); - Tick factor = ((txDmaLen + ULL(63)) >> ULL(6)) * dmaReadFactor; - Tick start = curTick + dmaReadDelay + factor; - txDmaReadEvent.schedule(start); return true; } @@ -1978,7 +1850,11 @@ void NSGigE::txDmaReadDone() { assert(txDmaState == dmaReading); - txDmaReadCopy(); + txDmaState = dmaIdle; + + DPRINTF(EthernetDMA, "tx dma read paddr=%#x len=%d\n", + txDmaAddr, txDmaLen); + DDUMP(EthernetDMA, txDmaData, txDmaLen); // If the receive state machine has a pending DMA, let it go first if (rxDmaState == dmaReadWaiting || rxDmaState == dmaWriteWaiting) @@ -1987,42 +1863,16 @@ NSGigE::txDmaReadDone() txKick(); } -void -NSGigE::txDmaWriteCopy() -{ - assert(txDmaState == dmaWriting); - - physmem->dma_write(txDmaAddr, (uint8_t *)txDmaData, txDmaLen); - txDmaState = dmaIdle; - - DPRINTF(EthernetDMA, "tx dma write paddr=%#x len=%d\n", - txDmaAddr, txDmaLen); - DDUMP(EthernetDMA, txDmaData, txDmaLen); -} - bool NSGigE::doTxDmaWrite() { assert(txDmaState == dmaIdle || txDmaState == dmaWriteWaiting); txDmaState = dmaWriting; - if (dmaInterface && !txDmaFree) { - if (dmaInterface->busy()) - txDmaState = dmaWriteWaiting; - else - dmaInterface->doDMA(WriteInvalidate, txDmaAddr, txDmaLen, curTick, - &txDmaWriteEvent, true); - return true; - } - - if (dmaWriteDelay == 0 && dmaWriteFactor == 0.0) { - txDmaWriteCopy(); - return false; - } - - Tick factor = ((txDmaLen + ULL(63)) >> ULL(6)) * dmaWriteFactor; - Tick start = curTick + dmaWriteDelay + factor; - txDmaWriteEvent.schedule(start); + if (dmaPending()) + txDmaState = dmaWriteWaiting; + else + dmaWrite(txDmaAddr, txDmaLen, &txDmaWriteEvent, (uint8_t*)txDmaData); return true; } @@ -2030,7 +1880,11 @@ void NSGigE::txDmaWriteDone() { assert(txDmaState == dmaWriting); - txDmaWriteCopy(); + txDmaState = dmaIdle; + + DPRINTF(EthernetDMA, "tx dma write paddr=%#x len=%d\n", + txDmaAddr, txDmaLen); + DDUMP(EthernetDMA, txDmaData, txDmaLen); // If the receive state machine has a pending DMA, let it go first if (rxDmaState == dmaReadWaiting || rxDmaState == dmaWriteWaiting) @@ -2147,7 +2001,7 @@ NSGigE::txKick() case txFifoBlock: if (!txPacket) { DPRINTF(EthernetSM, "****starting the tx of a new packet****\n"); - txPacket = new PacketData(16384); + txPacket = new EthPacketData(16384); txPacketBufPtr = txPacket->data; } @@ -2473,7 +2327,7 @@ NSGigE::transferDone() } bool -NSGigE::rxFilter(const PacketPtr &packet) +NSGigE::rxFilter(const EthPacketPtr &packet) { EthPtr eth = packet; bool drop = true; @@ -2516,7 +2370,7 @@ NSGigE::rxFilter(const PacketPtr &packet) } bool -NSGigE::recvPacket(PacketPtr packet) +NSGigE::recvPacket(EthPacketPtr packet) { rxBytes += packet->length; rxPackets++; @@ -2576,14 +2430,7 @@ NSGigE::serialize(ostream &os) /* * Finalize any DMA events now. */ - if (rxDmaReadEvent.scheduled()) - rxDmaReadCopy(); - if (rxDmaWriteEvent.scheduled()) - rxDmaWriteCopy(); - if (txDmaReadEvent.scheduled()) - txDmaReadCopy(); - if (txDmaWriteEvent.scheduled()) - txDmaWriteCopy(); + // @todo will mem system save pending dma? /* * Serialize the device registers @@ -2804,7 +2651,7 @@ NSGigE::unserialize(Checkpoint *cp, const std::string §ion) bool txPacketExists; UNSERIALIZE_SCALAR(txPacketExists); if (txPacketExists) { - txPacket = new PacketData(16384); + txPacket = new EthPacketData(16384); txPacket->unserialize("txPacket", cp, section); uint32_t txPktBufPtr; UNSERIALIZE_SCALAR(txPktBufPtr); @@ -2816,7 +2663,7 @@ NSGigE::unserialize(Checkpoint *cp, const std::string §ion) UNSERIALIZE_SCALAR(rxPacketExists); rxPacket = 0; if (rxPacketExists) { - rxPacket = new PacketData(16384); + rxPacket = new EthPacketData(16384); rxPacket->unserialize("rxPacket", cp, section); uint32_t rxPktBufPtr; UNSERIALIZE_SCALAR(rxPktBufPtr); @@ -2925,23 +2772,6 @@ NSGigE::unserialize(Checkpoint *cp, const std::string §ion) intrEvent = new IntrEvent(this, true); intrEvent->schedule(intrEventTick); } - - /* - * re-add addrRanges to bus bridges - */ - if (pioInterface) { - pioInterface->addAddrRange(RangeSize(BARAddrs[0], BARSize[0])); - pioInterface->addAddrRange(RangeSize(BARAddrs[1], BARSize[1])); - } -} - -Tick -NSGigE::cacheAccess(MemReqPtr &req) -{ - DPRINTF(EthernetPIO, "timing access to paddr=%#x (daddr=%#x)\n", - req->paddr, req->paddr & 0xfff); - - return curTick + pioLatency; } BEGIN_DECLARE_SIM_OBJECT_PARAMS(NSGigEInt) @@ -2976,22 +2806,16 @@ REGISTER_SIM_OBJECT("NSGigEInt", NSGigEInt) BEGIN_DECLARE_SIM_OBJECT_PARAMS(NSGigE) - Param<Tick> clock; - - Param<Addr> addr; - SimObjectParam<MemoryController *> mmu; - SimObjectParam<PhysicalMemory *> physmem; + SimObjectParam<System *> system; + SimObjectParam<Platform *> platform; SimObjectParam<PciConfigAll *> configspace; SimObjectParam<PciConfigData *> configdata; - SimObjectParam<Platform *> platform; Param<uint32_t> pci_bus; Param<uint32_t> pci_dev; Param<uint32_t> pci_func; + Param<Tick> pio_latency; - SimObjectParam<HierParams *> hier; - SimObjectParam<Bus*> pio_bus; - SimObjectParam<Bus*> dma_bus; - SimObjectParam<Bus*> payload_bus; + Param<Tick> clock; Param<bool> dma_desc_free; Param<bool> dma_data_free; Param<Tick> dma_read_delay; @@ -2999,7 +2823,6 @@ BEGIN_DECLARE_SIM_OBJECT_PARAMS(NSGigE) Param<Tick> dma_read_factor; Param<Tick> dma_write_factor; Param<bool> dma_no_allocate; - Param<Tick> pio_latency; Param<Tick> intr_delay; Param<Tick> rx_delay; @@ -3017,22 +2840,16 @@ END_DECLARE_SIM_OBJECT_PARAMS(NSGigE) BEGIN_INIT_SIM_OBJECT_PARAMS(NSGigE) - INIT_PARAM(clock, "State machine processor frequency"), - - INIT_PARAM(addr, "Device Address"), - INIT_PARAM(mmu, "Memory Controller"), - INIT_PARAM(physmem, "Physical Memory"), + INIT_PARAM(system, "System pointer"), + INIT_PARAM(platform, "Platform pointer"), INIT_PARAM(configspace, "PCI Configspace"), INIT_PARAM(configdata, "PCI Config data"), - INIT_PARAM(platform, "Platform"), - INIT_PARAM(pci_bus, "PCI bus"), + INIT_PARAM(pci_bus, "PCI bus ID"), INIT_PARAM(pci_dev, "PCI device number"), INIT_PARAM(pci_func, "PCI function code"), + INIT_PARAM_DFLT(pio_latency, "Programmed IO latency in bus cycles", 1), + INIT_PARAM(clock, "State machine cycle time"), - INIT_PARAM(hier, "Hierarchy global variables"), - INIT_PARAM(pio_bus, ""), - INIT_PARAM(dma_bus, ""), - INIT_PARAM(payload_bus, "The IO Bus to attach to for payload"), INIT_PARAM(dma_desc_free, "DMA of Descriptors is free"), INIT_PARAM(dma_data_free, "DMA of Data is free"), INIT_PARAM(dma_read_delay, "fixed delay for dma reads"), @@ -3040,7 +2857,6 @@ BEGIN_INIT_SIM_OBJECT_PARAMS(NSGigE) INIT_PARAM(dma_read_factor, "multiplier for dma reads"), INIT_PARAM(dma_write_factor, "multiplier for dma writes"), INIT_PARAM(dma_no_allocate, "Should DMA reads allocate cache lines"), - INIT_PARAM(pio_latency, "Programmed IO latency in bus cycles"), INIT_PARAM(intr_delay, "Interrupt Delay in microseconds"), INIT_PARAM(rx_delay, "Receive Delay"), @@ -3062,22 +2878,16 @@ CREATE_SIM_OBJECT(NSGigE) NSGigE::Params *params = new NSGigE::Params; params->name = getInstanceName(); - - params->clock = clock; - - params->mmu = mmu; - params->pmem = physmem; + params->platform = platform; + params->system = system; params->configSpace = configspace; params->configData = configdata; - params->plat = platform; params->busNum = pci_bus; params->deviceNum = pci_dev; params->functionNum = pci_func; + params->pio_delay = pio_latency; - params->hier = hier; - params->pio_bus = pio_bus; - params->header_bus = dma_bus; - params->payload_bus = payload_bus; + params->clock = clock; params->dma_desc_free = dma_desc_free; params->dma_data_free = dma_data_free; params->dma_read_delay = dma_read_delay; @@ -3085,7 +2895,7 @@ CREATE_SIM_OBJECT(NSGigE) params->dma_read_factor = dma_read_factor; params->dma_write_factor = dma_write_factor; params->dma_no_allocate = dma_no_allocate; - params->pio_latency = pio_latency; + params->pio_delay = pio_latency; params->intr_delay = intr_delay; params->rx_delay = rx_delay; diff --git a/dev/ns_gige.hh b/dev/ns_gige.hh index 59c55056e..7bb422287 100644 --- a/dev/ns_gige.hh +++ b/dev/ns_gige.hh @@ -42,7 +42,6 @@ #include "dev/ns_gige_reg.h" #include "dev/pcidev.hh" #include "dev/pktfifo.hh" -#include "mem/bus/bus.hh" #include "sim/eventq.hh" // Hash filtering constants @@ -111,10 +110,7 @@ struct dp_rom { }; class NSGigEInt; -class PhysicalMemory; -class BaseInterface; -class HierParams; -class Bus; +class Packet; class PciConfigAll; /** @@ -165,10 +161,6 @@ class NSGigE : public PciDev eepromRead }; - private: - Addr addr; - static const Addr size = sizeof(dp_regs); - protected: /** device register file */ dp_regs regs; @@ -187,8 +179,8 @@ class NSGigE : public PciDev PacketFifo rxFifo; /** various helper vars */ - PacketPtr txPacket; - PacketPtr rxPacket; + EthPacketPtr txPacket; + EthPacketPtr rxPacket; uint8_t *txPacketBufPtr; uint8_t *rxPacketBufPtr; uint32_t txXferLen; @@ -258,16 +250,12 @@ class NSGigE : public PciDev int rxDmaLen; bool doRxDmaRead(); bool doRxDmaWrite(); - void rxDmaReadCopy(); - void rxDmaWriteCopy(); void *txDmaData; Addr txDmaAddr; int txDmaLen; bool doTxDmaRead(); bool doTxDmaWrite(); - void txDmaReadCopy(); - void txDmaWriteCopy(); void rxDmaReadDone(); friend class EventWrapper<NSGigE, &NSGigE::rxDmaReadDone>; @@ -331,7 +319,7 @@ class NSGigE : public PciDev * receive address filter */ bool rxFilterEnable; - bool rxFilter(const PacketPtr &packet); + bool rxFilter(const EthPacketPtr &packet); bool acceptBroadcast; bool acceptMulticast; bool acceptUnicast; @@ -339,8 +327,6 @@ class NSGigE : public PciDev bool acceptArp; bool multicastHashEnable; - PhysicalMemory *physmem; - /** * Interrupt management */ @@ -363,16 +349,10 @@ class NSGigE : public PciDev public: struct Params : public PciDev::Params { - PhysicalMemory *pmem; - HierParams *hier; - Bus *pio_bus; - Bus *header_bus; - Bus *payload_bus; Tick clock; Tick intr_delay; Tick tx_delay; Tick rx_delay; - Tick pio_latency; bool dma_desc_free; bool dma_data_free; Tick dma_read_delay; @@ -393,16 +373,15 @@ class NSGigE : public PciDev ~NSGigE(); const Params *params() const { return (const Params *)_params; } - virtual void writeConfig(int offset, int size, const uint8_t *data); - virtual void readConfig(int offset, int size, uint8_t *data); + virtual void writeConfig(int offset, const uint16_t data); - virtual Fault read(MemReqPtr &req, uint8_t *data); - virtual Fault write(MemReqPtr &req, const uint8_t *data); + virtual Tick read(Packet &pkt); + virtual Tick write(Packet &pkt); bool cpuIntrPending() const; void cpuIntrAck() { cpuIntrClear(); } - bool recvPacket(PacketPtr packet); + bool recvPacket(EthPacketPtr packet); void transferDone(); void setInterface(NSGigEInt *i) { assert(!interface); interface = i; } @@ -463,9 +442,6 @@ class NSGigE : public PciDev Stats::Formula coalescedTotal; Stats::Scalar<> postedInterrupts; Stats::Scalar<> droppedPackets; - - public: - Tick cacheAccess(MemReqPtr &req); }; /* @@ -480,7 +456,7 @@ class NSGigEInt : public EtherInt NSGigEInt(const std::string &name, NSGigE *d) : EtherInt(name), dev(d) { dev->setInterface(this); } - virtual bool recvPacket(PacketPtr pkt) { return dev->recvPacket(pkt); } + virtual bool recvPacket(EthPacketPtr pkt) { return dev->recvPacket(pkt); } virtual void sendDone() { dev->transferDone(); } }; diff --git a/dev/pciconfigall.cc b/dev/pciconfigall.cc index d55084fa5..dfb1d48f6 100644 --- a/dev/pciconfigall.cc +++ b/dev/pciconfigall.cc @@ -39,29 +39,21 @@ #include "dev/pciconfigall.hh" #include "dev/pcidev.hh" #include "dev/pcireg.h" -#include "mem/bus/bus.hh" -#include "mem/bus/pio_interface.hh" -#include "mem/bus/pio_interface_impl.hh" -#include "mem/functional/memory_control.hh" +#include "dev/platform.hh" +#include "mem/packet.hh" #include "sim/builder.hh" #include "sim/system.hh" using namespace std; -using namespace TheISA; -PciConfigAll::PciConfigAll(const string &name, - Addr a, MemoryController *mmu, - HierParams *hier, Bus *pio_bus, Tick pio_latency) - : PioDevice(name, NULL), addr(a) +PciConfigAll::PciConfigAll(Params *p) + : BasicPioDevice(p) { - mmu->add_child(this, RangeSize(addr, size)); + pioSize = 0xffffff; - if (pio_bus) { - pioInterface = newPioInterface(name + ".pio", hier, pio_bus, this, - &PciConfigAll::cacheAccess); - pioInterface->addAddrRange(RangeSize(addr, size)); - pioLatency = pio_latency * pio_bus->clockRate; - } + // Set backpointer for pci config. Really the config stuff should be able to + // automagically do this + p->platform->pciconfig = this; // Make all the pointers to devices null for(int x=0; x < MAX_PCI_DEV; x++) @@ -96,58 +88,59 @@ PciConfigAll::startup() } -Fault -PciConfigAll::read(MemReqPtr &req, uint8_t *data) +Tick +PciConfigAll::read(Packet &pkt) { + assert(pkt.result == Unknown); + assert(pkt.addr >= pioAddr && pkt.addr < pioAddr + pioSize); - Addr daddr = (req->paddr - (addr & EV5::PAddrImplMask)); - - DPRINTF(PciConfigAll, "read va=%#x da=%#x size=%d\n", - req->vaddr, daddr, req->size); - + Addr daddr = pkt.addr - pioAddr; int device = (daddr >> 11) & 0x1F; int func = (daddr >> 8) & 0x7; int reg = daddr & 0xFF; - if (devices[device][func] == NULL) { - switch (req->size) { - // case sizeof(uint64_t): - // *(uint64_t*)data = 0xFFFFFFFFFFFFFFFF; - // return NoFault; - case sizeof(uint32_t): - *(uint32_t*)data = 0xFFFFFFFF; - return NoFault; - case sizeof(uint16_t): - *(uint16_t*)data = 0xFFFF; - return NoFault; - case sizeof(uint8_t): - *(uint8_t*)data = 0xFF; - return NoFault; - default: - panic("invalid access size(?) for PCI configspace!\n"); - } - } else { - switch (req->size) { - case sizeof(uint32_t): - case sizeof(uint16_t): - case sizeof(uint8_t): - devices[device][func]->readConfig(reg, req->size, data); - return NoFault; - default: - panic("invalid access size(?) for PCI configspace!\n"); - } + pkt.time += pioDelay; + pkt.allocate(); + + DPRINTF(PciConfigAll, "read va=%#x da=%#x size=%d\n", pkt.addr, daddr, + pkt.size); + + switch (pkt.size) { + case sizeof(uint32_t): + if (devices[device][func] == NULL) + pkt.set<uint32_t>(0xFFFFFFFF); + else + devices[device][func]->readConfig(reg, pkt.getPtr<uint32_t>()); + break; + case sizeof(uint16_t): + if (devices[device][func] == NULL) + pkt.set<uint16_t>(0xFFFF); + else + devices[device][func]->readConfig(reg, pkt.getPtr<uint16_t>()); + break; + case sizeof(uint8_t): + if (devices[device][func] == NULL) + pkt.set<uint8_t>(0xFF); + else + devices[device][func]->readConfig(reg, pkt.getPtr<uint8_t>()); + break; + default: + panic("invalid access size(?) for PCI configspace!\n"); } - - DPRINTFN("PCI Configspace ERROR: read daddr=%#x size=%d\n", - daddr, req->size); - - return NoFault; + pkt.result = Success; + return pioDelay; } -Fault -PciConfigAll::write(MemReqPtr &req, const uint8_t *data) +Tick +PciConfigAll::write(Packet &pkt) { - Addr daddr = (req->paddr - (addr & EV5::PAddrImplMask)); + pkt.time += pioDelay; + + assert(pkt.result == Unknown); + assert(pkt.addr >= pioAddr && pkt.addr < pioAddr + pioSize); + assert(pkt.size == sizeof(uint8_t) || pkt.size == sizeof(uint16_t) || + pkt.size == sizeof(uint32_t)); + Addr daddr = pkt.addr - pioAddr; int device = (daddr >> 11) & 0x1F; int func = (daddr >> 8) & 0x7; @@ -155,17 +148,24 @@ PciConfigAll::write(MemReqPtr &req, const uint8_t *data) if (devices[device][func] == NULL) panic("Attempting to write to config space on non-existant device\n"); - else if (req->size != sizeof(uint8_t) && - req->size != sizeof(uint16_t) && - req->size != sizeof(uint32_t)) - panic("invalid access size(?) for PCI configspace!\n"); DPRINTF(PciConfigAll, "write - va=%#x size=%d data=%#x\n", - req->vaddr, req->size, *(uint32_t*)data); - - devices[device][func]->writeConfig(reg, req->size, data); - - return NoFault; + pkt.addr, pkt.size, pkt.get<uint32_t>()); + + switch (pkt.size) { + case sizeof(uint8_t): + devices[device][func]->writeConfig(reg, pkt.get<uint8_t>()); + break; + case sizeof(uint16_t): + devices[device][func]->writeConfig(reg, pkt.get<uint16_t>()); + break; + case sizeof(uint32_t): + devices[device][func]->writeConfig(reg, pkt.get<uint32_t>()); + break; + default: + panic("invalid pci config write size\n"); + } + return pioDelay; } void @@ -188,40 +188,34 @@ PciConfigAll::unserialize(Checkpoint *cp, const std::string §ion) */ } -Tick -PciConfigAll::cacheAccess(MemReqPtr &req) -{ - return curTick + pioLatency; -} - #ifndef DOXYGEN_SHOULD_SKIP_THIS BEGIN_DECLARE_SIM_OBJECT_PARAMS(PciConfigAll) - SimObjectParam<MemoryController *> mmu; - Param<Addr> addr; - Param<Addr> mask; - SimObjectParam<Bus*> pio_bus; + Param<Addr> pio_addr; Param<Tick> pio_latency; - SimObjectParam<HierParams *> hier; + SimObjectParam<Platform *> platform; + SimObjectParam<System *> system; END_DECLARE_SIM_OBJECT_PARAMS(PciConfigAll) BEGIN_INIT_SIM_OBJECT_PARAMS(PciConfigAll) - INIT_PARAM(mmu, "Memory Controller"), - INIT_PARAM(addr, "Device Address"), - INIT_PARAM(mask, "Address Mask"), - INIT_PARAM_DFLT(pio_bus, "The IO Bus to attach to", NULL), - INIT_PARAM_DFLT(pio_latency, "Programmed IO latency in bus cycles", 1), - INIT_PARAM_DFLT(hier, "Hierarchy global variables", &defaultHierParams) + INIT_PARAM(pio_addr, "Device Address"), + INIT_PARAM(pio_latency, "Programmed IO latency"), + INIT_PARAM(platform, "platform"), + INIT_PARAM(system, "system object") END_INIT_SIM_OBJECT_PARAMS(PciConfigAll) CREATE_SIM_OBJECT(PciConfigAll) { - return new PciConfigAll(getInstanceName(), addr, mmu, hier, pio_bus, - pio_latency); + BasicPioDevice::Params *p = new BasicPioDevice::Params; + p->pio_addr = pio_addr; + p->pio_delay = pio_latency; + p->platform = platform; + p->system = system; + return new PciConfigAll(p); } REGISTER_SIM_OBJECT("PciConfigAll", PciConfigAll) diff --git a/dev/pciconfigall.hh b/dev/pciconfigall.hh index c6a0241d8..2393b445e 100644 --- a/dev/pciconfigall.hh +++ b/dev/pciconfigall.hh @@ -43,7 +43,6 @@ static const uint32_t MAX_PCI_DEV = 32; static const uint32_t MAX_PCI_FUNC = 8; class PciDev; -class MemoryController; /** * PCI Config Space @@ -52,12 +51,9 @@ class MemoryController; * space and passes the requests on to TsunamiPCIDev devices as * appropriate. */ -class PciConfigAll : public PioDevice +class PciConfigAll : public BasicPioDevice { private: - Addr addr; - static const Addr size = 0xffffff; - /** * Pointers to all the devices that are registered with this * particular config space. @@ -67,15 +63,9 @@ class PciConfigAll : public PioDevice public: /** * Constructor for PCIConfigAll - * @param name name of the object - * @param a base address of the write - * @param mmu the memory controller - * @param hier object to store parameters universal the device hierarchy - * @param bus The bus that this device is attached to + * @param p parameters structure */ - PciConfigAll(const std::string &name, Addr a, MemoryController *mmu, - HierParams *hier, Bus *pio_bus, Tick pio_latency); - + PciConfigAll(Params *p); /** * Check if a device exists. @@ -99,11 +89,10 @@ class PciConfigAll : public PioDevice * Read something in PCI config space. If the device does not exist * -1 is returned, if the device does exist its PciDev::ReadConfig (or the * virtual function that overrides) it is called. - * @param req Contains the address of the field to read. - * @param data Return the field read. - * @return The fault condition of the access. + * @param pkt Contains the address of the field to read. + * @return Amount of time to do the read */ - virtual Fault read(MemReqPtr &req, uint8_t *data); + virtual Tick read(Packet &pkt); /** * Write to PCI config spcae. If the device does not exit the simulator @@ -114,7 +103,7 @@ class PciConfigAll : public PioDevice * @return The fault condition of the access. */ - virtual Fault write(MemReqPtr &req, const uint8_t *data); + virtual Tick write(Packet &pkt); /** * Start up function to check if more than one person is using an interrupt line @@ -134,14 +123,6 @@ class PciConfigAll : public PioDevice * @param section The section name of this object */ virtual void unserialize(Checkpoint *cp, const std::string §ion); - - /** - * Return how long this access will take. - * @param req the memory request to calcuate - * @return Tick when the request is done - */ - Tick cacheAccess(MemReqPtr &req); - }; #endif // __PCICONFIGALL_HH__ diff --git a/dev/pcidev.cc b/dev/pcidev.cc index a05ee3803..c40ef62e4 100644 --- a/dev/pcidev.cc +++ b/dev/pcidev.cc @@ -39,20 +39,20 @@ #include "base/misc.hh" #include "base/str.hh" // for to_number #include "base/trace.hh" -#include "dev/pcidev.hh" #include "dev/pciconfigall.hh" -#include "mem/bus/bus.hh" -#include "mem/functional/memory_control.hh" +#include "dev/pcidev.hh" +#include "dev/tsunamireg.h" +#include "mem/packet.hh" #include "sim/builder.hh" +#include "sim/byteswap.hh" #include "sim/param.hh" #include "sim/root.hh" -#include "dev/tsunamireg.h" using namespace std; PciDev::PciDev(Params *p) - : DmaDevice(p->name, p->plat), _params(p), plat(p->plat), - configData(p->configData) + : DmaDevice(p), plat(p->platform), configData(p->configData), + pioDelay(p->pio_delay) { // copy the config data from the PciConfigData object if (configData) { @@ -70,214 +70,180 @@ PciDev::PciDev(Params *p) p->configSpace->registerDevice(p->deviceNum, p->functionNum, this); } -Fault -PciDev::read(MemReqPtr &req, uint8_t *data) -{ return NoFault; } - -Fault -PciDev::write(MemReqPtr &req, const uint8_t *data) -{ return NoFault; } - -Fault -PciDev::readBar0(MemReqPtr &req, Addr daddr, uint8_t *data) -{ panic("not implemented"); } - -Fault -PciDev::readBar1(MemReqPtr &req, Addr daddr, uint8_t *data) -{ panic("not implemented"); } +void +PciDev::readConfig(int offset, uint8_t *data) +{ + if (offset >= PCI_DEVICE_SPECIFIC) + panic("Device specific PCI config space not implemented!\n"); -Fault -PciDev::readBar2(MemReqPtr &req, Addr daddr, uint8_t *data) -{ panic("not implemented"); } + *data = config.data[offset]; -Fault -PciDev::readBar3(MemReqPtr &req, Addr daddr, uint8_t *data) -{ panic("not implemented"); } + DPRINTF(PCIDEV, + "read device: %#x function: %#x register: %#x 1 bytes: data: %#x\n", + params()->deviceNum, params()->functionNum, offset, *data); +} -Fault -PciDev::readBar4(MemReqPtr &req, Addr daddr, uint8_t *data) -{ panic("not implemented"); } +void +PciDev::addressRanges(AddrRangeList &range_list) +{ + int x = 0; + range_list.clear(); + for (x = 0; x < 6; x++) + if (BARAddrs[x] != 0) + range_list.push_back(RangeSize(BARAddrs[x],BARSize[x])); +} -Fault -PciDev::readBar5(MemReqPtr &req, Addr daddr, uint8_t *data) -{ panic("not implemented"); } +void +PciDev::readConfig(int offset, uint16_t *data) +{ + if (offset >= PCI_DEVICE_SPECIFIC) + panic("Device specific PCI config space not implemented!\n"); -Fault -PciDev::writeBar0(MemReqPtr &req, Addr daddr, const uint8_t *data) -{ panic("not implemented"); } + *data = *(uint16_t*)&config.data[offset]; -Fault -PciDev::writeBar1(MemReqPtr &req, Addr daddr, const uint8_t *data) -{ panic("not implemented"); } + DPRINTF(PCIDEV, + "read device: %#x function: %#x register: %#x 2 bytes: data: %#x\n", + params()->deviceNum, params()->functionNum, offset, *data); +} -Fault -PciDev::writeBar2(MemReqPtr &req, Addr daddr, const uint8_t *data) -{ panic("not implemented"); } +void +PciDev::readConfig(int offset, uint32_t *data) +{ + if (offset >= PCI_DEVICE_SPECIFIC) + panic("Device specific PCI config space not implemented!\n"); -Fault -PciDev::writeBar3(MemReqPtr &req, Addr daddr, const uint8_t *data) -{ panic("not implemented"); } + *data = *(uint32_t*)&config.data[offset]; -Fault -PciDev::writeBar4(MemReqPtr &req, Addr daddr, const uint8_t *data) -{ panic("not implemented"); } + DPRINTF(PCIDEV, + "read device: %#x function: %#x register: %#x 4 bytes: data: %#x\n", + params()->deviceNum, params()->functionNum, offset, *data); +} -Fault -PciDev::writeBar5(MemReqPtr &req, Addr daddr, const uint8_t *data) -{ panic("not implemented"); } void -PciDev::readConfig(int offset, int size, uint8_t *data) +PciDev::writeConfig(int offset, const uint8_t data) { if (offset >= PCI_DEVICE_SPECIFIC) panic("Device specific PCI config space not implemented!\n"); - switch(size) { - case sizeof(uint8_t): - *data = config.data[offset]; - break; - case sizeof(uint16_t): - *(uint16_t*)data = *(uint16_t*)&config.data[offset]; + DPRINTF(PCIDEV, + "write device: %#x function: %#x reg: %#x size: 1 data: %#x\n", + params()->deviceNum, params()->functionNum, offset, data); + + switch (offset) { + case PCI0_INTERRUPT_LINE: + config.interruptLine = data; + case PCI_CACHE_LINE_SIZE: + config.cacheLineSize = data; + case PCI_LATENCY_TIMER: + config.latencyTimer = data; break; - case sizeof(uint32_t): - *(uint32_t*)data = *(uint32_t*)&config.data[offset]; + /* Do nothing for these read-only registers */ + case PCI0_INTERRUPT_PIN: + case PCI0_MINIMUM_GRANT: + case PCI0_MAXIMUM_LATENCY: + case PCI_CLASS_CODE: + case PCI_REVISION_ID: break; default: - panic("Invalid PCI configuration read size!\n"); + panic("writing to a read only register"); } - - DPRINTF(PCIDEV, - "read device: %#x function: %#x register: %#x %d bytes: data: %#x\n", - params()->deviceNum, params()->functionNum, offset, size, - *(uint32_t*)data); } void -PciDev::writeConfig(int offset, int size, const uint8_t *data) +PciDev::writeConfig(int offset, const uint16_t data) { if (offset >= PCI_DEVICE_SPECIFIC) panic("Device specific PCI config space not implemented!\n"); - uint8_t &data8 = *(uint8_t*)data; - uint16_t &data16 = *(uint16_t*)data; - uint32_t &data32 = *(uint32_t*)data; - DPRINTF(PCIDEV, - "write device: %#x function: %#x reg: %#x size: %d data: %#x\n", - params()->deviceNum, params()->functionNum, offset, size, data32); - - switch (size) { - case sizeof(uint8_t): // 1-byte access - switch (offset) { - case PCI0_INTERRUPT_LINE: - config.interruptLine = data8; - case PCI_CACHE_LINE_SIZE: - config.cacheLineSize = data8; - case PCI_LATENCY_TIMER: - config.latencyTimer = data8; - break; - /* Do nothing for these read-only registers */ - case PCI0_INTERRUPT_PIN: - case PCI0_MINIMUM_GRANT: - case PCI0_MAXIMUM_LATENCY: - case PCI_CLASS_CODE: - case PCI_REVISION_ID: - break; - default: - panic("writing to a read only register"); - } + "write device: %#x function: %#x reg: %#x size: 2 data: %#x\n", + params()->deviceNum, params()->functionNum, offset, data); + + switch (offset) { + case PCI_COMMAND: + config.command = data; + case PCI_STATUS: + config.status = data; + case PCI_CACHE_LINE_SIZE: + config.cacheLineSize = data; break; + default: + panic("writing to a read only register"); + } +} - case sizeof(uint16_t): // 2-byte access - switch (offset) { - case PCI_COMMAND: - config.command = data16; - case PCI_STATUS: - config.status = data16; - case PCI_CACHE_LINE_SIZE: - config.cacheLineSize = data16; - break; - default: - panic("writing to a read only register"); - } - break; - case sizeof(uint32_t): // 4-byte access - switch (offset) { - case PCI0_BASE_ADDR0: - case PCI0_BASE_ADDR1: - case PCI0_BASE_ADDR2: - case PCI0_BASE_ADDR3: - case PCI0_BASE_ADDR4: - case PCI0_BASE_ADDR5: - - uint32_t barnum, bar_mask; - Addr base_addr, base_size, space_base; - - barnum = BAR_NUMBER(offset); - - if (BAR_IO_SPACE(letoh(config.baseAddr[barnum]))) { - bar_mask = BAR_IO_MASK; - space_base = TSUNAMI_PCI0_IO; - } else { - bar_mask = BAR_MEM_MASK; - space_base = TSUNAMI_PCI0_MEMORY; - } +void +PciDev::writeConfig(int offset, const uint32_t data) +{ + if (offset >= PCI_DEVICE_SPECIFIC) + panic("Device specific PCI config space not implemented!\n"); - // Writing 0xffffffff to a BAR tells the card to set the - // value of the bar to size of memory it needs - if (letoh(data32) == 0xffffffff) { - // This is I/O Space, bottom two bits are read only + DPRINTF(PCIDEV, + "write device: %#x function: %#x reg: %#x size: 4 data: %#x\n", + params()->deviceNum, params()->functionNum, offset, data); + + switch (offset) { + case PCI0_BASE_ADDR0: + case PCI0_BASE_ADDR1: + case PCI0_BASE_ADDR2: + case PCI0_BASE_ADDR3: + case PCI0_BASE_ADDR4: + case PCI0_BASE_ADDR5: + + uint32_t barnum, bar_mask; + Addr base_addr, base_size, space_base; + + barnum = BAR_NUMBER(offset); + + if (BAR_IO_SPACE(letoh(config.baseAddr[barnum]))) { + bar_mask = BAR_IO_MASK; + space_base = TSUNAMI_PCI0_IO; + } else { + bar_mask = BAR_MEM_MASK; + space_base = TSUNAMI_PCI0_MEMORY; + } - config.baseAddr[barnum] = letoh( - (~(BARSize[barnum] - 1) & ~bar_mask) | - (letoh(config.baseAddr[barnum]) & bar_mask)); - } else { - MemoryController *mmu = params()->mmu; + // Writing 0xffffffff to a BAR tells the card to set the + // value of the bar to size of memory it needs + if (letoh(data) == 0xffffffff) { + // This is I/O Space, bottom two bits are read only - config.baseAddr[barnum] = letoh( - (letoh(data32) & ~bar_mask) | + config.baseAddr[barnum] = letoh( + (~(BARSize[barnum] - 1) & ~bar_mask) | (letoh(config.baseAddr[barnum]) & bar_mask)); + } else { + config.baseAddr[barnum] = letoh( + (letoh(data) & ~bar_mask) | + (letoh(config.baseAddr[barnum]) & bar_mask)); + + if (letoh(config.baseAddr[barnum]) & ~bar_mask) { + base_addr = (letoh(data) & ~bar_mask) + space_base; + base_size = BARSize[barnum]; + BARAddrs[barnum] = base_addr; - if (letoh(config.baseAddr[barnum]) & ~bar_mask) { - base_addr = (letoh(data32) & ~bar_mask) + space_base; - base_size = BARSize[barnum]; - - // It's never been set - if (BARAddrs[barnum] == 0) - mmu->add_child((FunctionalMemory *)this, - RangeSize(base_addr, base_size)); - else - mmu->update_child((FunctionalMemory *)this, - RangeSize(BARAddrs[barnum], base_size), - RangeSize(base_addr, base_size)); - - BARAddrs[barnum] = base_addr; - } + pioPort->sendStatusChange(Port::RangeChange); } - break; - - case PCI0_ROM_BASE_ADDR: - if (letoh(data32) == 0xfffffffe) - config.expansionROM = htole((uint32_t)0xffffffff); - else - config.expansionROM = data32; - break; - - case PCI_COMMAND: - // This could also clear some of the error bits in the Status - // register. However they should never get set, so lets ignore - // it for now - config.command = data16; - break; - - default: - DPRINTF(PCIDEV, "Writing to a read only register"); } break; + case PCI0_ROM_BASE_ADDR: + if (letoh(data) == 0xfffffffe) + config.expansionROM = htole((uint32_t)0xffffffff); + else + config.expansionROM = data; + break; + + case PCI_COMMAND: + // This could also clear some of the error bits in the Status + // register. However they should never get set, so lets ignore + // it for now + config.command = data; + break; + default: - panic("invalid access size"); + DPRINTF(PCIDEV, "Writing to a read only register"); } } @@ -296,12 +262,6 @@ PciDev::unserialize(Checkpoint *cp, const std::string §ion) UNSERIALIZE_ARRAY(BARAddrs, sizeof(BARAddrs) / sizeof(BARAddrs[0])); UNSERIALIZE_ARRAY(config.data, sizeof(config.data) / sizeof(config.data[0])); - - // Add the MMU mappings for the BARs - for (int i=0; i < 6; i++) { - if (BARAddrs[i] != 0) - params()->mmu->add_child(this, RangeSize(BARAddrs[i], BARSize[i])); - } } #ifndef DOXYGEN_SHOULD_SKIP_THIS diff --git a/dev/pcidev.hh b/dev/pcidev.hh index bdfc6b932..fc4773908 100644 --- a/dev/pcidev.hh +++ b/dev/pcidev.hh @@ -44,7 +44,6 @@ #define BAR_NUMBER(x) (((x) - PCI0_BASE_ADDR0) >> 0x2); class PciConfigAll; -class MemoryController; /** @@ -85,12 +84,8 @@ class PciConfigData : public SimObject class PciDev : public DmaDevice { public: - struct Params + struct Params : public ::PioDevice::Params { - std::string name; - Platform *plat; - MemoryController *mmu; - /** * A pointer to the configspace all object that calls us when * a read comes to this particular device/function. @@ -111,13 +106,13 @@ class PciDev : public DmaDevice /** The function number */ uint32_t functionNum; - }; - protected: - Params *_params; + /** The latency for pio accesses. */ + Tick pio_delay; + }; public: - const Params *params() const { return _params; } + const Params *params() const { return (const Params *)_params; } protected: /** The current config space. Unlike the PciConfigData this is @@ -164,6 +159,7 @@ class PciDev : public DmaDevice protected: Platform *plat; PciConfigData *configData; + Tick pioDelay; public: Addr pciToDma(Addr pciAddr) const @@ -181,7 +177,11 @@ class PciDev : public DmaDevice interruptLine() { return configData->config.interruptLine; } - public: + /** return the address ranges that this device responds to. + * @params range_list range list to populate with ranges + */ + void addressRanges(AddrRangeList &range_list); + /** * Constructor for PCI Dev. This function copies data from the * config file object PCIConfigData and registers the device with @@ -189,39 +189,6 @@ class PciDev : public DmaDevice */ PciDev(Params *params); - virtual Fault read(MemReqPtr &req, uint8_t *data); - virtual Fault write(MemReqPtr &req, const uint8_t *data); - - public: - /** - * Implement the read/write as BAR accesses - */ - Fault readBar(MemReqPtr &req, uint8_t *data); - Fault writeBar(MemReqPtr &req, const uint8_t *data); - - public: - /** - * Read from a specific BAR - */ - virtual Fault readBar0(MemReqPtr &req, Addr daddr, uint8_t *data); - virtual Fault readBar1(MemReqPtr &req, Addr daddr, uint8_t *data); - virtual Fault readBar2(MemReqPtr &req, Addr daddr, uint8_t *data); - virtual Fault readBar3(MemReqPtr &req, Addr daddr, uint8_t *data); - virtual Fault readBar4(MemReqPtr &req, Addr daddr, uint8_t *data); - virtual Fault readBar5(MemReqPtr &req, Addr daddr, uint8_t *data); - - public: - /** - * Write to a specific BAR - */ - virtual Fault writeBar0(MemReqPtr &req, Addr daddr, const uint8_t *data); - virtual Fault writeBar1(MemReqPtr &req, Addr daddr, const uint8_t *data); - virtual Fault writeBar2(MemReqPtr &req, Addr daddr, const uint8_t *data); - virtual Fault writeBar3(MemReqPtr &req, Addr daddr, const uint8_t *data); - virtual Fault writeBar4(MemReqPtr &req, Addr daddr, const uint8_t *data); - virtual Fault writeBar5(MemReqPtr &req, Addr daddr, const uint8_t *data); - - public: /** * Write to the PCI config space data that is stored locally. This may be * overridden by the device but at some point it will eventually call this @@ -230,7 +197,9 @@ class PciDev : public DmaDevice * @param size the size of the write * @param data the data to write */ - virtual void writeConfig(int offset, int size, const uint8_t* data); + virtual void writeConfig(int offset, const uint8_t data); + virtual void writeConfig(int offset, const uint16_t data); + virtual void writeConfig(int offset, const uint32_t data); /** @@ -241,7 +210,9 @@ class PciDev : public DmaDevice * @param size the size of the read * @param data pointer to the location where the read value should be stored */ - virtual void readConfig(int offset, int size, uint8_t *data); + virtual void readConfig(int offset, uint8_t *data); + virtual void readConfig(int offset, uint16_t *data); + virtual void readConfig(int offset, uint32_t *data); /** * Serialize this object to the given output stream. @@ -256,43 +227,4 @@ class PciDev : public DmaDevice */ virtual void unserialize(Checkpoint *cp, const std::string §ion); }; - -inline Fault -PciDev::readBar(MemReqPtr &req, uint8_t *data) -{ - using namespace TheISA; - if (isBAR(req->paddr, 0)) - return readBar0(req, req->paddr - BARAddrs[0], data); - if (isBAR(req->paddr, 1)) - return readBar1(req, req->paddr - BARAddrs[1], data); - if (isBAR(req->paddr, 2)) - return readBar2(req, req->paddr - BARAddrs[2], data); - if (isBAR(req->paddr, 3)) - return readBar3(req, req->paddr - BARAddrs[3], data); - if (isBAR(req->paddr, 4)) - return readBar4(req, req->paddr - BARAddrs[4], data); - if (isBAR(req->paddr, 5)) - return readBar5(req, req->paddr - BARAddrs[5], data); - return genMachineCheckFault(); -} - -inline Fault -PciDev::writeBar(MemReqPtr &req, const uint8_t *data) -{ - using namespace TheISA; - if (isBAR(req->paddr, 0)) - return writeBar0(req, req->paddr - BARAddrs[0], data); - if (isBAR(req->paddr, 1)) - return writeBar1(req, req->paddr - BARAddrs[1], data); - if (isBAR(req->paddr, 2)) - return writeBar2(req, req->paddr - BARAddrs[2], data); - if (isBAR(req->paddr, 3)) - return writeBar3(req, req->paddr - BARAddrs[3], data); - if (isBAR(req->paddr, 4)) - return writeBar4(req, req->paddr - BARAddrs[4], data); - if (isBAR(req->paddr, 5)) - return writeBar5(req, req->paddr - BARAddrs[5], data); - return genMachineCheckFault(); -} - #endif // __DEV_PCIDEV_HH__ diff --git a/dev/pktfifo.cc b/dev/pktfifo.cc index 639009be9..922a66912 100644 --- a/dev/pktfifo.cc +++ b/dev/pktfifo.cc @@ -38,8 +38,8 @@ PacketFifo::copyout(void *dest, int offset, int len) if (offset + len >= size()) return false; - list<PacketPtr>::iterator p = fifo.begin(); - list<PacketPtr>::iterator end = fifo.end(); + list<EthPacketPtr>::iterator p = fifo.begin(); + list<EthPacketPtr>::iterator end = fifo.end(); while (len > 0) { while (offset >= (*p)->length) { offset -= (*p)->length; @@ -70,8 +70,8 @@ PacketFifo::serialize(const string &base, ostream &os) paramOut(os, base + ".packets", fifo.size()); int i = 0; - list<PacketPtr>::iterator p = fifo.begin(); - list<PacketPtr>::iterator end = fifo.end(); + list<EthPacketPtr>::iterator p = fifo.begin(); + list<EthPacketPtr>::iterator end = fifo.end(); while (p != end) { (*p)->serialize(csprintf("%s.packet%d", base, i), os); ++p; @@ -92,7 +92,7 @@ PacketFifo::unserialize(const string &base, Checkpoint *cp, fifo.clear(); for (int i = 0; i < fifosize; ++i) { - PacketPtr p = new PacketData(16384); + EthPacketPtr p = new EthPacketData(16384); p->unserialize(csprintf("%s.packet%d", base, i), cp, section); fifo.push_back(p); } diff --git a/dev/pktfifo.hh b/dev/pktfifo.hh index e245840a8..336da22d8 100644 --- a/dev/pktfifo.hh +++ b/dev/pktfifo.hh @@ -40,11 +40,11 @@ class Checkpoint; class PacketFifo { public: - typedef std::list<PacketPtr> fifo_list; + typedef std::list<EthPacketPtr> fifo_list; typedef fifo_list::iterator iterator; protected: - std::list<PacketPtr> fifo; + std::list<EthPacketPtr> fifo; int _maxsize; int _size; int _reserved; @@ -71,9 +71,9 @@ class PacketFifo iterator begin() { return fifo.begin(); } iterator end() { return fifo.end(); } - PacketPtr front() { return fifo.front(); } + EthPacketPtr front() { return fifo.front(); } - bool push(PacketPtr ptr) + bool push(EthPacketPtr ptr) { assert(ptr->length); assert(_reserved <= ptr->length); @@ -92,7 +92,7 @@ class PacketFifo if (empty()) return; - PacketPtr &packet = fifo.front(); + EthPacketPtr &packet = fifo.front(); _size -= packet->length; _size -= packet->slack; packet->slack = 0; @@ -111,7 +111,7 @@ class PacketFifo void remove(iterator i) { - PacketPtr &packet = *i; + EthPacketPtr &packet = *i; if (i != fifo.begin()) { iterator prev = i; --prev; diff --git a/dev/platform.cc b/dev/platform.cc index 5b667b12c..9d10e0828 100644 --- a/dev/platform.cc +++ b/dev/platform.cc @@ -33,8 +33,8 @@ using namespace std; using namespace TheISA; -Platform::Platform(const string &name, IntrControl *intctrl, PciConfigAll *pci) - : SimObject(name), intrctrl(intctrl), pciconfig(pci) +Platform::Platform(const string &name, IntrControl *intctrl) + : SimObject(name), intrctrl(intctrl) { } diff --git a/dev/platform.hh b/dev/platform.hh index 1ee645454..f149ca2fb 100644 --- a/dev/platform.hh +++ b/dev/platform.hh @@ -41,6 +41,7 @@ class PciConfigAll; class IntrControl; class SimConsole; class Uart; +class System; class Platform : public SimObject { @@ -54,9 +55,13 @@ class Platform : public SimObject /** Pointer to the UART, set by the uart */ Uart *uart; + /** Pointer to the system for info about the memory system. */ + System *system; + public: - Platform(const std::string &name, IntrControl *intctrl, PciConfigAll *pci); + Platform(const std::string &name, IntrControl *intctrl); virtual ~Platform(); + virtual void init() { if (pciconfig == NULL) panic("PCI Config not set"); } virtual void postConsoleInt() = 0; virtual void clearConsoleInt() = 0; virtual Tick intrFrequency() = 0; diff --git a/dev/simconsole.cc b/dev/simconsole.cc index b818e61f4..c3e4f554a 100644 --- a/dev/simconsole.cc +++ b/dev/simconsole.cc @@ -49,7 +49,6 @@ #include "dev/platform.hh" #include "dev/simconsole.hh" #include "dev/uart.hh" -#include "mem/functional/memory_control.hh" #include "sim/builder.hh" using namespace std; diff --git a/dev/simple_disk.cc b/dev/simple_disk.cc index b8c5d44ab..9eee4668c 100644 --- a/dev/simple_disk.cc +++ b/dev/simple_disk.cc @@ -42,14 +42,14 @@ #include "base/trace.hh" #include "dev/disk_image.hh" #include "dev/simple_disk.hh" -#include "mem/functional/physical.hh" +#include "mem/port.hh" #include "sim/builder.hh" +#include "sim/system.hh" using namespace std; -SimpleDisk::SimpleDisk(const string &name, PhysicalMemory *pmem, - DiskImage *img) - : SimObject(name), physmem(pmem), image(img) +SimpleDisk::SimpleDisk(const string &name, System *sys, DiskImage *img) + : SimObject(name), system(sys), image(img) {} SimpleDisk::~SimpleDisk() @@ -59,9 +59,7 @@ SimpleDisk::~SimpleDisk() void SimpleDisk::read(Addr addr, baddr_t block, int count) const { - uint8_t *data = physmem->dma_addr(addr, count); - if (!data) - panic("dma out of range! read addr=%#x count=%d\n", addr, count); + uint8_t *data = new uint8_t[SectorSize * count]; if (count & (SectorSize - 1)) panic("Not reading a multiple of a sector (count = %d)", count); @@ -69,8 +67,12 @@ SimpleDisk::read(Addr addr, baddr_t block, int count) const for (int i = 0, j = 0; i < count; i += SectorSize, j++) image->read(data + i, block + j); + system->functionalPort.writeBlob(addr, data, count); + DPRINTF(SimpleDisk, "read block=%#x len=%d\n", (uint64_t)block, count); DDUMP(SimpleDiskData, data, count); + + delete data; } void @@ -89,21 +91,21 @@ SimpleDisk::write(Addr addr, baddr_t block, int count) BEGIN_DECLARE_SIM_OBJECT_PARAMS(SimpleDisk) - SimObjectParam<PhysicalMemory *> physmem; + SimObjectParam<System *> system; SimObjectParam<DiskImage *> disk; END_DECLARE_SIM_OBJECT_PARAMS(SimpleDisk) BEGIN_INIT_SIM_OBJECT_PARAMS(SimpleDisk) - INIT_PARAM(physmem, "Physical Memory"), + INIT_PARAM(system, "System pointer"), INIT_PARAM(disk, "Disk Image") END_INIT_SIM_OBJECT_PARAMS(SimpleDisk) CREATE_SIM_OBJECT(SimpleDisk) { - return new SimpleDisk(getInstanceName(), physmem, disk); + return new SimpleDisk(getInstanceName(), system, disk); } REGISTER_SIM_OBJECT("SimpleDisk", SimpleDisk) diff --git a/dev/simple_disk.hh b/dev/simple_disk.hh index 57f81c5a9..19967f208 100644 --- a/dev/simple_disk.hh +++ b/dev/simple_disk.hh @@ -37,7 +37,7 @@ #include "arch/isa_traits.hh" class DiskImage; -class PhysicalMemory; +class System; /* * Trivial interface to a disk image used by the System Console @@ -48,11 +48,11 @@ class SimpleDisk : public SimObject typedef uint64_t baddr_t; protected: - PhysicalMemory *physmem; + System *system; DiskImage *image; public: - SimpleDisk(const std::string &name, PhysicalMemory *pmem, DiskImage *img); + SimpleDisk(const std::string &name, System *sys, DiskImage *img); ~SimpleDisk(); void read(Addr addr, baddr_t block, int count) const; diff --git a/dev/sinic.cc b/dev/sinic.cc index 0853717ba..66ca88dbe 100644 --- a/dev/sinic.cc +++ b/dev/sinic.cc @@ -28,6 +28,7 @@ #include <cstdio> #include <deque> +#include <limits> #include <string> #include "base/inet.hh" @@ -36,12 +37,7 @@ #include "dev/etherlink.hh" #include "dev/sinic.hh" #include "dev/pciconfigall.hh" -#include "mem/bus/bus.hh" -#include "mem/bus/dma_interface.hh" -#include "mem/bus/pio_interface.hh" -#include "mem/bus/pio_interface_impl.hh" -#include "mem/functional/memory_control.hh" -#include "mem/functional/physical.hh" +#include "mem/packet.hh" #include "sim/builder.hh" #include "sim/debug.hh" #include "sim/eventq.hh" @@ -87,7 +83,6 @@ Base::Base(Params *p) Device::Device(Params *p) : Base(p), plat(p->plat), physmem(p->physmem), rxUnique(0), txUnique(0), virtualRegs(p->virtual_count < 1 ? 1 : p->virtual_count), - rxFifo(p->rx_fifo_size), txFifo(p->tx_fifo_size), rxKickTick(0), txKickTick(0), txEvent(this), rxDmaEvent(this), txDmaEvent(this), dmaReadDelay(p->dma_read_delay), dmaReadFactor(p->dma_read_factor), @@ -95,25 +90,6 @@ Device::Device(Params *p) { reset(); - if (p->pio_bus) { - pioInterface = newPioInterface(p->name + ".pio", p->hier, p->pio_bus, - this, &Device::cacheAccess); - pioLatency = p->pio_latency * p->pio_bus->clockRate; - } - - if (p->header_bus) { - if (p->payload_bus) - dmaInterface = new DMAInterface<Bus>(p->name + ".dma", - p->header_bus, - p->payload_bus, 1, - p->dma_no_allocate); - else - dmaInterface = new DMAInterface<Bus>(p->name + ".dma", - p->header_bus, - p->header_bus, 1, - p->dma_no_allocate); - } else if (p->payload_bus) - panic("must define a header bus if defining a payload bus"); } Device::~Device() @@ -289,29 +265,6 @@ Device::regStats() rxPacketRate = rxPackets / simSeconds; } -/** - * This is to write to the PCI general configuration registers - */ -void -Device::writeConfig(int offset, int size, const uint8_t *data) -{ - switch (offset) { - case PCI0_BASE_ADDR0: - // Need to catch writes to BARs to update the PIO interface - PciDev::writeConfig(offset, size, data); - if (BARAddrs[0] != 0) { - if (pioInterface) - pioInterface->addAddrRange(RangeSize(BARAddrs[0], BARSize[0])); - - BARAddrs[0] &= EV5::PAddrUncachedMask; - } - break; - - default: - PciDev::writeConfig(offset, size, data); - } -} - void Device::prepareIO(int cpu, int index) { @@ -358,76 +311,65 @@ Device::prepareWrite(int cpu, int index) /** * I/O read of device register */ -Fault -Device::read(MemReqPtr &req, uint8_t *data) +Tick +Device::read(Packet &pkt) { assert(config.command & PCI_CMD_MSE); - Fault fault = readBar(req, data); - - if (fault && fault->isMachineCheckFault()) { - panic("address does not map to a BAR pa=%#x va=%#x size=%d", - req->paddr, req->vaddr, req->size); - - return genMachineCheckFault(); - } + assert(pkt.addr >= BARAddrs[0] && pkt.size < BARSize[0]); - return fault; -} - -Fault -Device::readBar0(MemReqPtr &req, Addr daddr, uint8_t *data) -{ - int cpu = (req->xc->readMiscReg(TheISA::IPR_PALtemp16) >> 8) & 0xff; + int cpu = pkt.req->getCpuNum(); + Addr daddr = pkt.addr - BARAddrs[0]; Addr index = daddr >> Regs::VirtualShift; Addr raddr = daddr & Regs::VirtualMask; + pkt.time += pioDelay; + pkt.allocate(); + if (!regValid(raddr)) - panic("invalid register: cpu=%d vnic=%d da=%#x pa=%#x va=%#x size=%d", - cpu, index, daddr, req->paddr, req->vaddr, req->size); + panic("invalid register: cpu=%d vnic=%d da=%#x pa=%#x size=%d", + cpu, index, daddr, pkt.addr, pkt.size); const Regs::Info &info = regInfo(raddr); if (!info.read) panic("read %s (write only): " - "cpu=%d vnic=%d da=%#x pa=%#x va=%#x size=%d", - info.name, cpu, index, daddr, req->paddr, req->vaddr, req->size); + "cpu=%d vnic=%d da=%#x pa=%#x size=%d", + info.name, cpu, index, daddr, pkt.addr, pkt.size); - if (req->size != info.size) panic("read %s (invalid size): " - "cpu=%d vnic=%d da=%#x pa=%#x va=%#x size=%d", - info.name, cpu, index, daddr, req->paddr, req->vaddr, req->size); + "cpu=%d vnic=%d da=%#x pa=%#x size=%d", + info.name, cpu, index, daddr, pkt.addr, pkt.size); prepareRead(cpu, index); uint64_t value = 0; - if (req->size == 4) { - uint32_t ® = *(uint32_t *)data; - reg = regData32(raddr); + if (pkt.size == 4) { + uint32_t reg = regData32(raddr); + pkt.set(reg); value = reg; } - if (req->size == 8) { - uint64_t ® = *(uint64_t *)data; - reg = regData64(raddr); + if (pkt.size == 8) { + uint64_t reg = regData64(raddr); + pkt.set(reg); value = reg; } DPRINTF(EthernetPIO, - "read %s: cpu=%d vnic=%d da=%#x pa=%#x va=%#x size=%d val=%#x\n", - info.name, cpu, index, daddr, req->paddr, req->vaddr, req->size, - value); + "read %s: cpu=%d vnic=%d da=%#x pa=%#x size=%d val=%#x\n", + info.name, cpu, index, daddr, pkt.addr, pkt.size, value); // reading the interrupt status register has the side effect of // clearing it if (raddr == Regs::IntrStatus) devIntrClear(); - return NoFault; + return pioDelay; } /** * IPR read of device register - */ -Fault + + Fault Device::iprRead(Addr daddr, int cpu, uint64_t &result) { if (!regValid(daddr)) @@ -453,74 +395,62 @@ Device::iprRead(Addr daddr, int cpu, uint64_t &result) return NoFault; } - +*/ /** * I/O write of device register */ -Fault -Device::write(MemReqPtr &req, const uint8_t *data) +Tick +Device::write(Packet &pkt) { assert(config.command & PCI_CMD_MSE); - Fault fault = writeBar(req, data); - - if (fault && fault->isMachineCheckFault()) { - panic("address does not map to a BAR pa=%#x va=%#x size=%d", - req->paddr, req->vaddr, req->size); + assert(pkt.addr >= BARAddrs[0] && pkt.size < BARSize[0]); - return genMachineCheckFault(); - } - - return fault; -} - -Fault -Device::writeBar0(MemReqPtr &req, Addr daddr, const uint8_t *data) -{ - int cpu = (req->xc->readMiscReg(TheISA::IPR_PALtemp16) >> 8) & 0xff; + int cpu = pkt.req->getCpuNum(); + Addr daddr = pkt.addr - BARAddrs[0]; Addr index = daddr >> Regs::VirtualShift; Addr raddr = daddr & Regs::VirtualMask; + pkt.time += pioDelay; + if (!regValid(raddr)) - panic("invalid address: cpu=%d da=%#x pa=%#x va=%#x size=%d", - cpu, daddr, req->paddr, req->vaddr, req->size); + panic("invalid register: cpu=%d, da=%#x pa=%#x size=%d", + cpu, daddr, pkt.addr, pkt.size); const Regs::Info &info = regInfo(raddr); if (!info.write) panic("write %s (read only): " - "cpu=%d vnic=%d da=%#x pa=%#x va=%#x size=%d", - info.name, cpu, index, daddr, req->paddr, req->vaddr, req->size); + "cpu=%d vnic=%d da=%#x pa=%#x size=%d", + info.name, cpu, index, daddr, pkt.addr, pkt.size); - if (req->size != info.size) + if (pkt.size != info.size) panic("write %s (invalid size): " - "cpu=%d vnic=%d da=%#x pa=%#x va=%#x size=%d", - info.name, cpu, index, daddr, req->paddr, req->vaddr, req->size); + "cpu=%d vnic=%d da=%#x pa=%#x size=%d", + info.name, cpu, index, daddr, pkt.addr, pkt.size); - uint32_t reg32 = *(uint32_t *)data; - uint64_t reg64 = *(uint64_t *)data; VirtualReg &vnic = virtualRegs[index]; DPRINTF(EthernetPIO, - "write %s vnic %d: cpu=%d val=%#x da=%#x pa=%#x va=%#x size=%d\n", - info.name, index, cpu, info.size == 4 ? reg32 : reg64, daddr, - req->paddr, req->vaddr, req->size); + "write %s vnic %d: cpu=%d val=%#x da=%#x pa=%#x size=%d\n", + info.name, index, cpu, info.size == 4 ? pkt.get<uint32_t>() : + pkt.get<uint64_t>(), daddr, pkt.addr, pkt.size); prepareWrite(cpu, index); switch (raddr) { case Regs::Config: - changeConfig(reg32); + changeConfig(pkt.get<uint32_t>()); break; case Regs::Command: - command(reg32); + command(pkt.get<uint32_t>()); break; case Regs::IntrStatus: - devIntrClear(regs.IntrStatus & reg32); + devIntrClear(regs.IntrStatus & pkt.get<uint32_t>()); break; case Regs::IntrMask: - devIntrChangeMask(reg32); + devIntrChangeMask(pkt.get<uint32_t>()); break; case Regs::RxData: @@ -530,7 +460,7 @@ Device::writeBar0(MemReqPtr &req, Addr daddr, const uint8_t *data) vnic.rxUnique = rxUnique++; vnic.RxDone = Regs::RxDone_Busy; - vnic.RxData = reg64; + vnic.RxData = pkt.get<uint64_t>(); if (Regs::get_RxData_Vaddr(reg64)) { Addr vaddr = Regs::get_RxData_Addr(reg64); @@ -566,16 +496,16 @@ Device::writeBar0(MemReqPtr &req, Addr daddr, const uint8_t *data) vnic.txUnique = txUnique++; vnic.TxDone = Regs::TxDone_Busy; - vnic.TxData = reg64; - if (Regs::get_TxData_Vaddr(reg64)) { - Addr vaddr = Regs::get_TxData_Addr(reg64); + if (Regs::get_TxData_Vaddr(pkt.get<uint64_t>())) { + panic("vtophys won't work here in newmem.\n"); + /*Addr vaddr = Regs::get_TxData_Addr(reg64); Addr paddr = vtophys(req->xc, vaddr); DPRINTF(EthernetPIO, "write TxData vnic %d (rxunique %d): " "vaddr=%#x, paddr=%#x\n", index, vnic.txUnique, vaddr, paddr); - vnic.TxData = Regs::set_TxData_Addr(vnic.TxData, paddr); + vnic.TxData = Regs::set_TxData_Addr(vnic.TxData, paddr);*/ } else { DPRINTF(EthernetPIO, "write TxData vnic %d (rxunique %d)\n", index, vnic.txUnique); @@ -590,7 +520,7 @@ Device::writeBar0(MemReqPtr &req, Addr daddr, const uint8_t *data) break; } - return NoFault; + return pioDelay; } void @@ -850,22 +780,13 @@ Device::reset() } void -Device::rxDmaCopy() +Device::rxDmaDone() { assert(rxState == rxCopy); rxState = rxCopyDone; - DPRINTF(EthernetDMA, "begin rx dma write paddr=%#x len=%d\n", - rxDmaAddr, rxDmaLen); - physmem->dma_write(rxDmaAddr, (uint8_t *)rxDmaData, rxDmaLen); DPRINTF(EthernetDMA, "end rx dma write paddr=%#x len=%d\n", rxDmaAddr, rxDmaLen); DDUMP(EthernetData, rxDmaData, rxDmaLen); -} - -void -Device::rxDmaDone() -{ - rxDmaCopy(); // If the transmit state machine has a pending DMA, let it go first if (txState == txBeginCopy) @@ -1001,34 +922,22 @@ Device::rxKick() break; case rxBeginCopy: - if (dmaInterface && dmaInterface->busy()) + if (dmaPending()) goto exit; - rxDmaAddr = plat->pciToDma(Regs::get_RxData_Addr(vnic->RxData)); - rxDmaLen = min<int>(Regs::get_RxData_Len(vnic->RxData), + rxDmaAddr = params()->platform->pciToDma( + Regs::get_RxData_Addr(vnic->RxData)); + rxDmaLen = std::min<int>(Regs::get_RxData_Len(vnic->RxData), vnic->rxPacketBytes); rxDmaData = (*vnic->rxPacket)->data + vnic->rxPacketOffset; rxState = rxCopy; - if (rxDmaAddr == 1LL) { rxState = rxCopyDone; break; } - if (dmaInterface) { - dmaInterface->doDMA(WriteInvalidate, rxDmaAddr, rxDmaLen, - curTick, &rxDmaEvent, true); - goto exit; - } - - if (dmaWriteDelay != 0 || dmaWriteFactor != 0) { - Tick factor = ((rxDmaLen + ULL(63)) >> ULL(6)) * dmaWriteFactor; - Tick start = curTick + dmaWriteDelay + factor; - rxDmaEvent.schedule(start); - goto exit; - } - rxDmaCopy(); + dmaWrite(rxDmaAddr, rxDmaLen, &rxDmaEvent, rxDmaData); break; case rxCopy: @@ -1095,20 +1004,13 @@ Device::rxKick() } void -Device::txDmaCopy() +Device::txDmaDone() { assert(txState == txCopy); txState = txCopyDone; - physmem->dma_read((uint8_t *)txDmaData, txDmaAddr, txDmaLen); DPRINTF(EthernetDMA, "tx dma read paddr=%#x len=%d\n", txDmaAddr, txDmaLen); DDUMP(EthernetData, txDmaData, txDmaLen); -} - -void -Device::txDmaDone() -{ - txDmaCopy(); // If the receive state machine has a pending DMA, let it go first if (rxState == rxBeginCopy) @@ -1126,7 +1028,7 @@ Device::transmit() } uint32_t interrupts; - PacketPtr packet = txFifo.front(); + EthPacketPtr packet = txFifo.front(); if (!interface->sendPacket(packet)) { DPRINTF(Ethernet, "Packet Transmit: failed txFifo available %d\n", txFifo.avail()); @@ -1194,7 +1096,7 @@ Device::txKick() assert(Regs::get_TxDone_Busy(vnic->TxDone)); if (!txPacket) { // Grab a new packet from the fifo. - txPacket = new PacketData(16384); + txPacket = new EthPacketData(16384); txPacketOffset = 0; } @@ -1208,28 +1110,16 @@ Device::txKick() break; case txBeginCopy: - if (dmaInterface && dmaInterface->busy()) + if (dmaPending()) goto exit; - txDmaAddr = plat->pciToDma(Regs::get_TxData_Addr(vnic->TxData)); + txDmaAddr = params()->platform->pciToDma( + Regs::get_TxData_Addr(vnic->TxData)); txDmaLen = Regs::get_TxData_Len(vnic->TxData); txDmaData = txPacket->data + txPacketOffset; txState = txCopy; - if (dmaInterface) { - dmaInterface->doDMA(Read, txDmaAddr, txDmaLen, - curTick, &txDmaEvent, true); - goto exit; - } - - if (dmaReadDelay != 0 || dmaReadFactor != 0) { - Tick factor = ((txDmaLen + ULL(63)) >> ULL(6)) * dmaReadFactor; - Tick start = curTick + dmaReadDelay + factor; - txDmaEvent.schedule(start); - goto exit; - } - - txDmaCopy(); + dmaRead(txDmaAddr, txDmaLen, &txDmaEvent, txDmaData); break; case txCopy: @@ -1316,7 +1206,7 @@ Device::transferDone() } bool -Device::rxFilter(const PacketPtr &packet) +Device::rxFilter(const EthPacketPtr &packet) { if (!Regs::get_Config_Filter(regs.Config)) return false; @@ -1361,7 +1251,7 @@ Device::rxFilter(const PacketPtr &packet) } bool -Device::recvPacket(PacketPtr packet) +Device::recvPacket(EthPacketPtr packet) { rxBytes += packet->length; rxPackets++; @@ -1402,7 +1292,7 @@ Device::recvPacket(PacketPtr packet) // // void -Base::serialize(ostream &os) +Base::serialize(std::ostream &os) { // Serialize the PciDev base class PciDev::serialize(os); @@ -1446,7 +1336,7 @@ Base::unserialize(Checkpoint *cp, const std::string §ion) } void -Device::serialize(ostream &os) +Device::serialize(std::ostream &os) { int count; @@ -1484,7 +1374,7 @@ Device::serialize(ostream &os) for (int i = 0; i < virtualRegsSize; ++i) { VirtualReg *vnic = &virtualRegs[i]; - string reg = csprintf("vnic%d", i); + std::string reg = csprintf("vnic%d", i); paramOut(os, reg + ".RxData", vnic->RxData); paramOut(os, reg + ".RxDone", vnic->RxDone); paramOut(os, reg + ".TxData", vnic->TxData); @@ -1639,7 +1529,7 @@ Device::unserialize(Checkpoint *cp, const std::string §ion) UNSERIALIZE_SCALAR(txPacketExists); txPacket = 0; if (txPacketExists) { - txPacket = new PacketData(16384); + txPacket = new EthPacketData(16384); txPacket->unserialize("txPacket", cp, section); UNSERIALIZE_SCALAR(txPacketOffset); UNSERIALIZE_SCALAR(txPacketBytes); @@ -1657,7 +1547,7 @@ Device::unserialize(Checkpoint *cp, const std::string §ion) virtualRegs.resize(virtualRegsSize); for (int i = 0; i < virtualRegsSize; ++i) { VirtualReg *vnic = &virtualRegs[i]; - string reg = csprintf("vnic%d", i); + std::string reg = csprintf("vnic%d", i); paramIn(cp, section, reg + ".RxData", vnic->RxData); paramIn(cp, section, reg + ".RxDone", vnic->RxDone); @@ -1693,28 +1583,11 @@ Device::unserialize(Checkpoint *cp, const std::string §ion) if (transmitTick) txEvent.schedule(curTick + transmitTick); - /* - * re-add addrRanges to bus bridges - */ - if (pioInterface) - pioInterface->addAddrRange(RangeSize(BARAddrs[0], BARSize[0])); -} - -Tick -Device::cacheAccess(MemReqPtr &req) -{ - Addr daddr; - int bar; - if (!getBAR(req->paddr, daddr, bar)) - panic("address does not map to a BAR pa=%#x va=%#x size=%d", - req->paddr, req->vaddr, req->size); + pioPort->sendStatusChange(Port::RangeChange); - DPRINTF(EthernetPIO, "timing %s to paddr=%#x bar=%d daddr=%#x\n", - req->cmd.toString(), req->paddr, bar, daddr); - - return curTick + pioLatency; } + BEGIN_DECLARE_SIM_OBJECT_PARAMS(Interface) SimObjectParam<EtherInt *> peer; @@ -1747,29 +1620,22 @@ REGISTER_SIM_OBJECT("SinicInt", Interface) BEGIN_DECLARE_SIM_OBJECT_PARAMS(Device) - Param<Tick> clock; - Param<Addr> addr; - SimObjectParam<MemoryController *> mmu; - SimObjectParam<PhysicalMemory *> physmem; + SimObjectParam<System *> system; + SimObjectParam<Platform *> platform; SimObjectParam<PciConfigAll *> configspace; SimObjectParam<PciConfigData *> configdata; - SimObjectParam<Platform *> platform; Param<uint32_t> pci_bus; Param<uint32_t> pci_dev; Param<uint32_t> pci_func; + Param<Tick> pio_latency; + Param<Tick> intr_delay; - SimObjectParam<HierParams *> hier; - SimObjectParam<Bus*> pio_bus; - SimObjectParam<Bus*> dma_bus; - SimObjectParam<Bus*> payload_bus; + Param<Tick> clock; Param<Tick> dma_read_delay; Param<Tick> dma_read_factor; Param<Tick> dma_write_delay; Param<Tick> dma_write_factor; - Param<bool> dma_no_allocate; - Param<Tick> pio_latency; - Param<Tick> intr_delay; Param<Tick> rx_delay; Param<Tick> tx_delay; @@ -1784,7 +1650,7 @@ BEGIN_DECLARE_SIM_OBJECT_PARAMS(Device) Param<uint32_t> tx_fifo_threshold; Param<bool> rx_filter; - Param<string> hardware_address; + Param<std::string> hardware_address; Param<bool> rx_thread; Param<bool> tx_thread; Param<bool> rss; @@ -1797,29 +1663,22 @@ END_DECLARE_SIM_OBJECT_PARAMS(Device) BEGIN_INIT_SIM_OBJECT_PARAMS(Device) - INIT_PARAM(clock, "State machine cycle time"), - INIT_PARAM(addr, "Device Address"), - INIT_PARAM(mmu, "Memory Controller"), - INIT_PARAM(physmem, "Physical Memory"), + INIT_PARAM(system, "System pointer"), + INIT_PARAM(platform, "Platform pointer"), INIT_PARAM(configspace, "PCI Configspace"), INIT_PARAM(configdata, "PCI Config data"), - INIT_PARAM(platform, "Platform"), - INIT_PARAM(pci_bus, "PCI bus"), + INIT_PARAM(pci_bus, "PCI bus ID"), INIT_PARAM(pci_dev, "PCI device number"), INIT_PARAM(pci_func, "PCI function code"), + INIT_PARAM_DFLT(pio_latency, "Programmed IO latency in bus cycles", 1), + INIT_PARAM(intr_delay, "Interrupt Delay"), + INIT_PARAM(clock, "State machine cycle time"), - INIT_PARAM(hier, "Hierarchy global variables"), - INIT_PARAM(pio_bus, ""), - INIT_PARAM(dma_bus, ""), - INIT_PARAM(payload_bus, "The IO Bus to attach to for payload"), INIT_PARAM(dma_read_delay, "fixed delay for dma reads"), INIT_PARAM(dma_read_factor, "multiplier for dma reads"), INIT_PARAM(dma_write_delay, "fixed delay for dma writes"), INIT_PARAM(dma_write_factor, "multiplier for dma writes"), - INIT_PARAM(dma_no_allocate, "Should we allocat on read in cache"), - INIT_PARAM(pio_latency, "Programmed IO latency in bus cycles"), - INIT_PARAM(intr_delay, "Interrupt Delay"), INIT_PARAM(rx_delay, "Receive Delay"), INIT_PARAM(tx_delay, "Transmit Delay"), @@ -1849,31 +1708,22 @@ END_INIT_SIM_OBJECT_PARAMS(Device) CREATE_SIM_OBJECT(Device) { Device::Params *params = new Device::Params; - params->name = getInstanceName(); - - params->clock = clock; - - params->mmu = mmu; - params->physmem = physmem; + params->platform = platform; + params->system = system; params->configSpace = configspace; params->configData = configdata; - params->plat = platform; params->busNum = pci_bus; params->deviceNum = pci_dev; params->functionNum = pci_func; + params->pio_delay = pio_latency; + params->intr_delay = intr_delay; + params->clock = clock; - params->hier = hier; - params->pio_bus = pio_bus; - params->header_bus = dma_bus; - params->payload_bus = payload_bus; params->dma_read_delay = dma_read_delay; params->dma_read_factor = dma_read_factor; params->dma_write_delay = dma_write_delay; params->dma_write_factor = dma_write_factor; - params->dma_no_allocate = dma_no_allocate; - params->pio_latency = pio_latency; - params->intr_delay = intr_delay; params->tx_delay = tx_delay; params->rx_delay = rx_delay; diff --git a/dev/sinic.hh b/dev/sinic.hh index 892b3ab69..a786c3e44 100644 --- a/dev/sinic.hh +++ b/dev/sinic.hh @@ -37,7 +37,6 @@ #include "dev/pcidev.hh" #include "dev/pktfifo.hh" #include "dev/sinicreg.hh" -#include "mem/bus/bus.hh" #include "sim/eventq.hh" namespace Sinic { @@ -91,10 +90,6 @@ class Base : public PciDev class Device : public Base { protected: - Platform *plat; - PhysicalMemory *physmem; - - protected: /** Receive State Machine States */ enum RxState { rxIdle, @@ -169,10 +164,6 @@ class Device : public Base uint32_t ®Data32(Addr daddr) { return *(uint32_t *)®Data8(daddr); } uint64_t ®Data64(Addr daddr) { return *(uint64_t *)®Data8(daddr); } - private: - Addr addr; - static const Addr size = Regs::Size; - protected: RxState rxState; PacketFifo rxFifo; @@ -186,7 +177,7 @@ class Device : public Base TxState txState; PacketFifo txFifo; bool txFull; - PacketPtr txPacket; + EthPacketPtr txPacket; int txPacketOffset; int txPacketBytes; Addr txDmaAddr; @@ -226,7 +217,7 @@ class Device : public Base /** * receive address filter */ - bool rxFilter(const PacketPtr &packet); + bool rxFilter(const EthPacketPtr &packet); /** * device configuration @@ -238,7 +229,7 @@ class Device : public Base * device ethernet interface */ public: - bool recvPacket(PacketPtr packet); + bool recvPacket(EthPacketPtr packet); void transferDone(); void setInterface(Interface *i) { assert(!interface); interface = i; } @@ -246,12 +237,10 @@ class Device : public Base * DMA parameters */ protected: - void rxDmaCopy(); void rxDmaDone(); friend class EventWrapper<Device, &Device::rxDmaDone>; EventWrapper<Device, &Device::rxDmaDone> rxDmaEvent; - void txDmaCopy(); void txDmaDone(); friend class EventWrapper<Device, &Device::txDmaDone>; EventWrapper<Device, &Device::txDmaDone> txDmaEvent; @@ -270,25 +259,16 @@ class Device : public Base void devIntrChangeMask(uint32_t newmask); /** - * PCI Configuration interface - */ - public: - virtual void writeConfig(int offset, int size, const uint8_t *data); - -/** * Memory Interface */ public: - virtual Fault read(MemReqPtr &req, uint8_t *data); - virtual Fault write(MemReqPtr &req, const uint8_t *data); + virtual Tick read(Packet &pkt); + virtual Tick write(Packet &pkt); void prepareIO(int cpu, int index); void prepareRead(int cpu, int index); void prepareWrite(int cpu, int index); - Fault iprRead(Addr daddr, int cpu, uint64_t &result); - Fault readBar0(MemReqPtr &req, Addr daddr, uint8_t *data); - Fault writeBar0(MemReqPtr &req, Addr daddr, const uint8_t *data); - Tick cacheAccess(MemReqPtr &req); + // Fault iprRead(Addr daddr, int cpu, uint64_t &result); /** * Statistics @@ -336,17 +316,8 @@ class Device : public Base public: struct Params : public Base::Params { - IntrControl *i; - PhysicalMemory *pmem; Tick tx_delay; Tick rx_delay; - HierParams *hier; - Bus *pio_bus; - Bus *header_bus; - Bus *payload_bus; - Tick pio_latency; - PhysicalMemory *physmem; - IntrControl *intctrl; bool rx_filter; Net::EthAddr eaddr; uint32_t rx_max_copy; @@ -362,7 +333,6 @@ class Device : public Base Tick dma_read_factor; Tick dma_write_delay; Tick dma_write_factor; - bool dma_no_allocate; bool rx_thread; bool tx_thread; bool rss; @@ -392,7 +362,7 @@ class Interface : public EtherInt Interface(const std::string &name, Device *d) : EtherInt(name), dev(d) { dev->setInterface(this); } - virtual bool recvPacket(PacketPtr pkt) { return dev->recvPacket(pkt); } + virtual bool recvPacket(EthPacketPtr pkt) { return dev->recvPacket(pkt); } virtual void sendDone() { dev->transferDone(); } }; diff --git a/dev/tsunami.cc b/dev/tsunami.cc index 58fc7434e..ed011531d 100644 --- a/dev/tsunami.cc +++ b/dev/tsunami.cc @@ -36,12 +36,10 @@ #include "cpu/intr_control.hh" #include "dev/simconsole.hh" -#include "dev/ide_ctrl.hh" #include "dev/tsunami_cchip.hh" #include "dev/tsunami_pchip.hh" #include "dev/tsunami_io.hh" #include "dev/tsunami.hh" -#include "dev/pciconfigall.hh" #include "sim/builder.hh" #include "sim/system.hh" @@ -49,9 +47,8 @@ using namespace std; //Should this be AlphaISA? using namespace TheISA; -Tsunami::Tsunami(const string &name, System *s, IntrControl *ic, - PciConfigAll *pci) - : Platform(name, ic, pci), system(s) +Tsunami::Tsunami(const string &name, System *s, IntrControl *ic) + : Platform(name, ic), system(s) { // set the back pointer from the system to myself system->platform = this; @@ -112,21 +109,19 @@ BEGIN_DECLARE_SIM_OBJECT_PARAMS(Tsunami) SimObjectParam<System *> system; SimObjectParam<IntrControl *> intrctrl; - SimObjectParam<PciConfigAll *> pciconfig; END_DECLARE_SIM_OBJECT_PARAMS(Tsunami) BEGIN_INIT_SIM_OBJECT_PARAMS(Tsunami) INIT_PARAM(system, "system"), - INIT_PARAM(intrctrl, "interrupt controller"), - INIT_PARAM(pciconfig, "PCI configuration") + INIT_PARAM(intrctrl, "interrupt controller") END_INIT_SIM_OBJECT_PARAMS(Tsunami) CREATE_SIM_OBJECT(Tsunami) { - return new Tsunami(getInstanceName(), system, intrctrl, pciconfig); + return new Tsunami(getInstanceName(), system, intrctrl); } REGISTER_SIM_OBJECT("Tsunami", Tsunami) diff --git a/dev/tsunami.hh b/dev/tsunami.hh index 7fd91d5b2..668c82674 100644 --- a/dev/tsunami.hh +++ b/dev/tsunami.hh @@ -38,12 +38,9 @@ #include "dev/platform.hh" class IdeController; -class TlaserClock; -class NSGigE; class TsunamiCChip; class TsunamiPChip; class TsunamiIO; -class PciConfigAll; class System; /** @@ -86,8 +83,7 @@ class Tsunami : public Platform * @param name name of the object * @param intrctrl pointer to the interrupt controller */ - Tsunami(const std::string &name, System *s, IntrControl *intctrl, - PciConfigAll *pci); + Tsunami(const std::string &name, System *s, IntrControl *intctrl); /** * Return the interrupting frequency to AlphaAccess diff --git a/dev/tsunami_cchip.cc b/dev/tsunami_cchip.cc index 2649fe27a..7b9032f6e 100644 --- a/dev/tsunami_cchip.cc +++ b/dev/tsunami_cchip.cc @@ -34,14 +34,12 @@ #include <string> #include <vector> +#include "arch/alpha/ev5.hh" #include "base/trace.hh" #include "dev/tsunami_cchip.hh" #include "dev/tsunamireg.h" #include "dev/tsunami.hh" -#include "mem/bus/bus.hh" -#include "mem/bus/pio_interface.hh" -#include "mem/bus/pio_interface_impl.hh" -#include "mem/functional/memory_control.hh" +#include "mem/port.hh" #include "cpu/exec_context.hh" #include "cpu/intr_control.hh" #include "sim/builder.hh" @@ -51,19 +49,10 @@ using namespace std; //Should this be AlphaISA? using namespace TheISA; -TsunamiCChip::TsunamiCChip(const string &name, Tsunami *t, Addr a, - MemoryController *mmu, HierParams *hier, - Bus* pio_bus, Tick pio_latency) - : PioDevice(name, t), addr(a), tsunami(t) +TsunamiCChip::TsunamiCChip(Params *p) + : BasicPioDevice(p), tsunami(p->tsunami) { - mmu->add_child(this, RangeSize(addr, size)); - - if (pio_bus) { - pioInterface = newPioInterface(name + ".pio", hier, pio_bus, this, - &TsunamiCChip::cacheAccess); - pioInterface->addAddrRange(RangeSize(addr, size)); - pioLatency = pio_latency * pio_bus->clockRate; - } + pioSize = 0xfffffff; drir = 0; ipint = 0; @@ -79,315 +68,302 @@ TsunamiCChip::TsunamiCChip(const string &name, Tsunami *t, Addr a, tsunami->cchip = this; } -Fault -TsunamiCChip::read(MemReqPtr &req, uint8_t *data) +Tick +TsunamiCChip::read(Packet &pkt) { - DPRINTF(Tsunami, "read va=%#x size=%d\n", req->vaddr, req->size); + DPRINTF(Tsunami, "read va=%#x size=%d\n", pkt.addr, pkt.size); - Addr regnum = (req->paddr - (addr & EV5::PAddrImplMask)) >> 6; - Addr daddr = (req->paddr - (addr & EV5::PAddrImplMask)); + assert(pkt.result == Unknown); + assert(pkt.addr >= pioAddr && pkt.addr < pioAddr + pioSize); - ExecContext *xc = req->xc; + pkt.time += pioDelay; + Addr regnum = (pkt.addr - pioAddr) >> 6; + Addr daddr = (pkt.addr - pioAddr); - switch (req->size) { + pkt.allocate(); + switch (pkt.size) { case sizeof(uint64_t): if (daddr & TSDEV_CC_BDIMS) { - *(uint64_t*)data = dim[(daddr >> 4) & 0x3F]; - return NoFault; + pkt.set(dim[(daddr >> 4) & 0x3F]); + break; } if (daddr & TSDEV_CC_BDIRS) { - *(uint64_t*)data = dir[(daddr >> 4) & 0x3F]; - return NoFault; + pkt.set(dir[(daddr >> 4) & 0x3F]); + break; } switch(regnum) { case TSDEV_CC_CSR: - *(uint64_t*)data = 0x0; - return NoFault; + pkt.set(0x0); + break; case TSDEV_CC_MTR: panic("TSDEV_CC_MTR not implemeted\n"); - return NoFault; + break; case TSDEV_CC_MISC: - *(uint64_t*)data = (ipint << 8) & 0xF | - (itint << 4) & 0xF | - (xc->readCpuId() & 0x3); - return NoFault; + pkt.set((ipint << 8) & 0xF | (itint << 4) & 0xF | + (pkt.req->getCpuNum() & 0x3)); + break; case TSDEV_CC_AAR0: case TSDEV_CC_AAR1: case TSDEV_CC_AAR2: case TSDEV_CC_AAR3: - *(uint64_t*)data = 0; - return NoFault; + pkt.set(0); + break; case TSDEV_CC_DIM0: - *(uint64_t*)data = dim[0]; - return NoFault; + pkt.set(dim[0]); + break; case TSDEV_CC_DIM1: - *(uint64_t*)data = dim[1]; - return NoFault; + pkt.set(dim[1]); + break; case TSDEV_CC_DIM2: - *(uint64_t*)data = dim[2]; - return NoFault; + pkt.set(dim[2]); + break; case TSDEV_CC_DIM3: - *(uint64_t*)data = dim[3]; - return NoFault; + pkt.set(dim[3]); + break; case TSDEV_CC_DIR0: - *(uint64_t*)data = dir[0]; - return NoFault; + pkt.set(dir[0]); + break; case TSDEV_CC_DIR1: - *(uint64_t*)data = dir[1]; - return NoFault; + pkt.set(dir[1]); + break; case TSDEV_CC_DIR2: - *(uint64_t*)data = dir[2]; - return NoFault; + pkt.set(dir[2]); + break; case TSDEV_CC_DIR3: - *(uint64_t*)data = dir[3]; - return NoFault; + pkt.set(dir[3]); + break; case TSDEV_CC_DRIR: - *(uint64_t*)data = drir; - return NoFault; + pkt.set(drir); + break; case TSDEV_CC_PRBEN: panic("TSDEV_CC_PRBEN not implemented\n"); - return NoFault; + break; case TSDEV_CC_IIC0: case TSDEV_CC_IIC1: case TSDEV_CC_IIC2: case TSDEV_CC_IIC3: panic("TSDEV_CC_IICx not implemented\n"); - return NoFault; + break; case TSDEV_CC_MPR0: case TSDEV_CC_MPR1: case TSDEV_CC_MPR2: case TSDEV_CC_MPR3: panic("TSDEV_CC_MPRx not implemented\n"); - return NoFault; + break; case TSDEV_CC_IPIR: - *(uint64_t*)data = ipint; - return NoFault; + pkt.set(ipint); + break; case TSDEV_CC_ITIR: - *(uint64_t*)data = itint; - return NoFault; + pkt.set(itint); + break; default: panic("default in cchip read reached, accessing 0x%x\n"); } // uint64_t break; case sizeof(uint32_t): - if (regnum == TSDEV_CC_DRIR) { - warn("accessing DRIR with 32 bit read, " - "hopefully your just reading this for timing"); - *(uint32_t*)data = drir; - } else - panic("invalid access size(?) for tsunami register!\n"); - return NoFault; case sizeof(uint16_t): case sizeof(uint8_t): default: panic("invalid access size(?) for tsunami register!\n"); } - DPRINTFN("Tsunami CChip ERROR: read regnum=%#x size=%d\n", regnum, req->size); + DPRINTF(Tsunami, "Tsunami CChip: read regnum=%#x size=%d data=%lld\n", + regnum, pkt.size, pkt.get<uint64_t>()); - return NoFault; + pkt.result = Success; + return pioDelay; } -Fault -TsunamiCChip::write(MemReqPtr &req, const uint8_t *data) +Tick +TsunamiCChip::write(Packet &pkt) { - DPRINTF(Tsunami, "write - va=%#x value=%#x size=%d \n", - req->vaddr, *(uint64_t*)data, req->size); + pkt.time += pioDelay; - Addr daddr = (req->paddr - (addr & EV5::PAddrImplMask)); - Addr regnum = (req->paddr - (addr & EV5::PAddrImplMask)) >> 6; - bool supportedWrite = false; + assert(pkt.addr >= pioAddr && pkt.addr < pioAddr + pioSize); + Addr daddr = pkt.addr - pioAddr; + Addr regnum = (pkt.addr - pioAddr) >> 6 ; - switch (req->size) { - case sizeof(uint64_t): - if (daddr & TSDEV_CC_BDIMS) - { - int number = (daddr >> 4) & 0x3F; - - uint64_t bitvector; - uint64_t olddim; - uint64_t olddir; - - olddim = dim[number]; - olddir = dir[number]; - dim[number] = *(uint64_t*)data; - dir[number] = dim[number] & drir; - for(int x = 0; x < Tsunami::Max_CPUs; x++) - { - bitvector = ULL(1) << x; - // Figure out which bits have changed - if ((dim[number] & bitvector) != (olddim & bitvector)) - { - // The bit is now set and it wasn't before (set) - if((dim[number] & bitvector) && (dir[number] & bitvector)) - { - tsunami->intrctrl->post(number, TheISA::INTLEVEL_IRQ1, x); - DPRINTF(Tsunami, "dim write resulting in posting dir" - " interrupt to cpu %d\n", number); - } - else if ((olddir & bitvector) && - !(dir[number] & bitvector)) - { - // The bit was set and now its now clear and - // we were interrupting on that bit before - tsunami->intrctrl->clear(number, TheISA::INTLEVEL_IRQ1, x); - DPRINTF(Tsunami, "dim write resulting in clear" - " dir interrupt to cpu %d\n", number); + assert(pkt.size == sizeof(uint64_t)); - } + DPRINTF(Tsunami, "write - addr=%#x value=%#x\n", pkt.addr, pkt.get<uint64_t>()); + bool supportedWrite = false; - } - } - return NoFault; - } - switch(regnum) { - case TSDEV_CC_CSR: - panic("TSDEV_CC_CSR write\n"); - return NoFault; - case TSDEV_CC_MTR: - panic("TSDEV_CC_MTR write not implemented\n"); - return NoFault; - case TSDEV_CC_MISC: - uint64_t ipreq; - ipreq = (*(uint64_t*)data >> 12) & 0xF; - //If it is bit 12-15, this is an IPI post - if (ipreq) { - reqIPI(ipreq); - supportedWrite = true; + if (daddr & TSDEV_CC_BDIMS) + { + int number = (daddr >> 4) & 0x3F; + + uint64_t bitvector; + uint64_t olddim; + uint64_t olddir; + + olddim = dim[number]; + olddir = dir[number]; + dim[number] = pkt.get<uint64_t>(); + dir[number] = dim[number] & drir; + for(int x = 0; x < Tsunami::Max_CPUs; x++) + { + bitvector = ULL(1) << x; + // Figure out which bits have changed + if ((dim[number] & bitvector) != (olddim & bitvector)) + { + // The bit is now set and it wasn't before (set) + if((dim[number] & bitvector) && (dir[number] & bitvector)) + { + tsunami->intrctrl->post(number, TheISA::INTLEVEL_IRQ1, x); + DPRINTF(Tsunami, "dim write resulting in posting dir" + " interrupt to cpu %d\n", number); } + else if ((olddir & bitvector) && + !(dir[number] & bitvector)) + { + // The bit was set and now its now clear and + // we were interrupting on that bit before + tsunami->intrctrl->clear(number, TheISA::INTLEVEL_IRQ1, x); + DPRINTF(Tsunami, "dim write resulting in clear" + " dir interrupt to cpu %d\n", number); - //If it is bit 8-11, this is an IPI clear - uint64_t ipintr; - ipintr = (*(uint64_t*)data >> 8) & 0xF; - if (ipintr) { - clearIPI(ipintr); - supportedWrite = true; } - //If it is the 4-7th bit, clear the RTC interrupt - uint64_t itintr; - itintr = (*(uint64_t*)data >> 4) & 0xF; - if (itintr) { - clearITI(itintr); - supportedWrite = true; - } - // ignore NXMs - if (*(uint64_t*)data & 0x10000000) - supportedWrite = true; + } + } + } else { + switch(regnum) { + case TSDEV_CC_CSR: + panic("TSDEV_CC_CSR write\n"); + case TSDEV_CC_MTR: + panic("TSDEV_CC_MTR write not implemented\n"); + case TSDEV_CC_MISC: + uint64_t ipreq; + ipreq = (pkt.get<uint64_t>() >> 12) & 0xF; + //If it is bit 12-15, this is an IPI post + if (ipreq) { + reqIPI(ipreq); + supportedWrite = true; + } - if(!supportedWrite) - panic("TSDEV_CC_MISC write not implemented\n"); + //If it is bit 8-11, this is an IPI clear + uint64_t ipintr; + ipintr = (pkt.get<uint64_t>() >> 8) & 0xF; + if (ipintr) { + clearIPI(ipintr); + supportedWrite = true; + } - return NoFault; - case TSDEV_CC_AAR0: - case TSDEV_CC_AAR1: - case TSDEV_CC_AAR2: - case TSDEV_CC_AAR3: - panic("TSDEV_CC_AARx write not implemeted\n"); - return NoFault; - case TSDEV_CC_DIM0: - case TSDEV_CC_DIM1: - case TSDEV_CC_DIM2: - case TSDEV_CC_DIM3: - int number; - if(regnum == TSDEV_CC_DIM0) - number = 0; - else if(regnum == TSDEV_CC_DIM1) - number = 1; - else if(regnum == TSDEV_CC_DIM2) - number = 2; - else - number = 3; - - uint64_t bitvector; - uint64_t olddim; - uint64_t olddir; - - olddim = dim[number]; - olddir = dir[number]; - dim[number] = *(uint64_t*)data; - dir[number] = dim[number] & drir; - for(int x = 0; x < 64; x++) - { - bitvector = ULL(1) << x; - // Figure out which bits have changed - if ((dim[number] & bitvector) != (olddim & bitvector)) - { - // The bit is now set and it wasn't before (set) - if((dim[number] & bitvector) && (dir[number] & bitvector)) - { - tsunami->intrctrl->post(number, TheISA::INTLEVEL_IRQ1, x); - DPRINTF(Tsunami, "posting dir interrupt to cpu 0\n"); - } - else if ((olddir & bitvector) && - !(dir[number] & bitvector)) - { - // The bit was set and now its now clear and - // we were interrupting on that bit before - tsunami->intrctrl->clear(number, TheISA::INTLEVEL_IRQ1, x); - DPRINTF(Tsunami, "dim write resulting in clear" - " dir interrupt to cpu %d\n", - x); - - } - - - } - } - return NoFault; - case TSDEV_CC_DIR0: - case TSDEV_CC_DIR1: - case TSDEV_CC_DIR2: - case TSDEV_CC_DIR3: - panic("TSDEV_CC_DIR write not implemented\n"); - case TSDEV_CC_DRIR: - panic("TSDEV_CC_DRIR write not implemented\n"); - case TSDEV_CC_PRBEN: - panic("TSDEV_CC_PRBEN write not implemented\n"); - case TSDEV_CC_IIC0: - case TSDEV_CC_IIC1: - case TSDEV_CC_IIC2: - case TSDEV_CC_IIC3: - panic("TSDEV_CC_IICx write not implemented\n"); - case TSDEV_CC_MPR0: - case TSDEV_CC_MPR1: - case TSDEV_CC_MPR2: - case TSDEV_CC_MPR3: - panic("TSDEV_CC_MPRx write not implemented\n"); - case TSDEV_CC_IPIR: - clearIPI(*(uint64_t*)data); - return NoFault; - case TSDEV_CC_ITIR: - clearITI(*(uint64_t*)data); - return NoFault; - case TSDEV_CC_IPIQ: - reqIPI(*(uint64_t*)data); - return NoFault; - default: - panic("default in cchip read reached, accessing 0x%x\n"); - } + //If it is the 4-7th bit, clear the RTC interrupt + uint64_t itintr; + itintr = (pkt.get<uint64_t>() >> 4) & 0xF; + if (itintr) { + clearITI(itintr); + supportedWrite = true; + } - break; - case sizeof(uint32_t): - case sizeof(uint16_t): - case sizeof(uint8_t): - default: - panic("invalid access size(?) for tsunami register!\n"); - } + // ignore NXMs + if (pkt.get<uint64_t>() & 0x10000000) + supportedWrite = true; + + if(!supportedWrite) + panic("TSDEV_CC_MISC write not implemented\n"); + + break; + case TSDEV_CC_AAR0: + case TSDEV_CC_AAR1: + case TSDEV_CC_AAR2: + case TSDEV_CC_AAR3: + panic("TSDEV_CC_AARx write not implemeted\n"); + case TSDEV_CC_DIM0: + case TSDEV_CC_DIM1: + case TSDEV_CC_DIM2: + case TSDEV_CC_DIM3: + int number; + if(regnum == TSDEV_CC_DIM0) + number = 0; + else if(regnum == TSDEV_CC_DIM1) + number = 1; + else if(regnum == TSDEV_CC_DIM2) + number = 2; + else + number = 3; + + uint64_t bitvector; + uint64_t olddim; + uint64_t olddir; + + olddim = dim[number]; + olddir = dir[number]; + dim[number] = pkt.get<uint64_t>(); + dir[number] = dim[number] & drir; + for(int x = 0; x < 64; x++) + { + bitvector = ULL(1) << x; + // Figure out which bits have changed + if ((dim[number] & bitvector) != (olddim & bitvector)) + { + // The bit is now set and it wasn't before (set) + if((dim[number] & bitvector) && (dir[number] & bitvector)) + { + tsunami->intrctrl->post(number, TheISA::INTLEVEL_IRQ1, x); + DPRINTF(Tsunami, "posting dir interrupt to cpu 0\n"); + } + else if ((olddir & bitvector) && + !(dir[number] & bitvector)) + { + // The bit was set and now its now clear and + // we were interrupting on that bit before + tsunami->intrctrl->clear(number, TheISA::INTLEVEL_IRQ1, x); + DPRINTF(Tsunami, "dim write resulting in clear" + " dir interrupt to cpu %d\n", + x); + + } - DPRINTFN("Tsunami ERROR: write daddr=%#x size=%d\n", daddr, req->size); - return NoFault; + } + } + break; + case TSDEV_CC_DIR0: + case TSDEV_CC_DIR1: + case TSDEV_CC_DIR2: + case TSDEV_CC_DIR3: + panic("TSDEV_CC_DIR write not implemented\n"); + case TSDEV_CC_DRIR: + panic("TSDEV_CC_DRIR write not implemented\n"); + case TSDEV_CC_PRBEN: + panic("TSDEV_CC_PRBEN write not implemented\n"); + case TSDEV_CC_IIC0: + case TSDEV_CC_IIC1: + case TSDEV_CC_IIC2: + case TSDEV_CC_IIC3: + panic("TSDEV_CC_IICx write not implemented\n"); + case TSDEV_CC_MPR0: + case TSDEV_CC_MPR1: + case TSDEV_CC_MPR2: + case TSDEV_CC_MPR3: + panic("TSDEV_CC_MPRx write not implemented\n"); + case TSDEV_CC_IPIR: + clearIPI(pkt.get<uint64_t>()); + break; + case TSDEV_CC_ITIR: + clearITI(pkt.get<uint64_t>()); + break; + case TSDEV_CC_IPIQ: + reqIPI(pkt.get<uint64_t>()); + break; + default: + panic("default in cchip read reached, accessing 0x%x\n"); + } // swtich(regnum) + } // not BIG_TSUNAMI write + pkt.result = Success; + return pioDelay; } void @@ -471,11 +447,11 @@ TsunamiCChip::postRTC() for (int i = 0; i < size; i++) { uint64_t cpumask = ULL(1) << i; - if (!(cpumask & itint)) { - itint |= cpumask; - tsunami->intrctrl->post(i, TheISA::INTLEVEL_IRQ2, 0); - DPRINTF(Tsunami, "Posting RTC interrupt to cpu=%d", i); - } + if (!(cpumask & itint)) { + itint |= cpumask; + tsunami->intrctrl->post(i, TheISA::INTLEVEL_IRQ2, 0); + DPRINTF(Tsunami, "Posting RTC interrupt to cpu=%d", i); + } } } @@ -490,11 +466,11 @@ TsunamiCChip::postDRIR(uint32_t interrupt) for(int i=0; i < size; i++) { dir[i] = dim[i] & drir; - if (dim[i] & bitvector) { - tsunami->intrctrl->post(i, TheISA::INTLEVEL_IRQ1, interrupt); - DPRINTF(Tsunami, "posting dir interrupt to cpu %d," + if (dim[i] & bitvector) { + tsunami->intrctrl->post(i, TheISA::INTLEVEL_IRQ1, interrupt); + DPRINTF(Tsunami, "posting dir interrupt to cpu %d," "interrupt %d\n",i, interrupt); - } + } } } @@ -509,25 +485,19 @@ TsunamiCChip::clearDRIR(uint32_t interrupt) { drir &= ~bitvector; for(int i=0; i < size; i++) { - if (dir[i] & bitvector) { - tsunami->intrctrl->clear(i, TheISA::INTLEVEL_IRQ1, interrupt); - DPRINTF(Tsunami, "clearing dir interrupt to cpu %d," + if (dir[i] & bitvector) { + tsunami->intrctrl->clear(i, TheISA::INTLEVEL_IRQ1, interrupt); + DPRINTF(Tsunami, "clearing dir interrupt to cpu %d," "interrupt %d\n",i, interrupt); - } - dir[i] = dim[i] & drir; + } + dir[i] = dim[i] & drir; } } else DPRINTF(Tsunami, "Spurrious clear? interrupt %d\n", interrupt); } -Tick -TsunamiCChip::cacheAccess(MemReqPtr &req) -{ - return curTick + pioLatency; -} - void TsunamiCChip::serialize(std::ostream &os) @@ -551,30 +521,34 @@ TsunamiCChip::unserialize(Checkpoint *cp, const std::string §ion) BEGIN_DECLARE_SIM_OBJECT_PARAMS(TsunamiCChip) - SimObjectParam<Tsunami *> tsunami; - SimObjectParam<MemoryController *> mmu; - Param<Addr> addr; - SimObjectParam<Bus*> pio_bus; + Param<Addr> pio_addr; Param<Tick> pio_latency; - SimObjectParam<HierParams *> hier; + SimObjectParam<Platform *> platform; + SimObjectParam<System *> system; + SimObjectParam<Tsunami *> tsunami; END_DECLARE_SIM_OBJECT_PARAMS(TsunamiCChip) BEGIN_INIT_SIM_OBJECT_PARAMS(TsunamiCChip) - INIT_PARAM(tsunami, "Tsunami"), - INIT_PARAM(mmu, "Memory Controller"), - INIT_PARAM(addr, "Device Address"), - INIT_PARAM_DFLT(pio_bus, "The IO Bus to attach to", NULL), - INIT_PARAM_DFLT(pio_latency, "Programmed IO latency in bus cycles", 1), - INIT_PARAM_DFLT(hier, "Hierarchy global variables", &defaultHierParams) + INIT_PARAM(pio_addr, "Device Address"), + INIT_PARAM(pio_latency, "Programmed IO latency"), + INIT_PARAM(platform, "platform"), + INIT_PARAM(system, "system object"), + INIT_PARAM(tsunami, "Tsunami") END_INIT_SIM_OBJECT_PARAMS(TsunamiCChip) CREATE_SIM_OBJECT(TsunamiCChip) { - return new TsunamiCChip(getInstanceName(), tsunami, addr, mmu, hier, - pio_bus, pio_latency); + TsunamiCChip::Params *p = new TsunamiCChip::Params; + p->name = getInstanceName(); + p->pio_addr = pio_addr; + p->pio_delay = pio_latency; + p->platform = platform; + p->system = system; + p->tsunami = tsunami; + return new TsunamiCChip(p); } REGISTER_SIM_OBJECT("TsunamiCChip", TsunamiCChip) diff --git a/dev/tsunami_cchip.hh b/dev/tsunami_cchip.hh index d88ad375f..6cd6cf13f 100644 --- a/dev/tsunami_cchip.hh +++ b/dev/tsunami_cchip.hh @@ -37,21 +37,13 @@ #include "base/range.hh" #include "dev/io_device.hh" -class MemoryController; /** * Tsunami CChip CSR Emulation. This device includes all the interrupt * handling code for the chipset. */ -class TsunamiCChip : public PioDevice +class TsunamiCChip : public BasicPioDevice { - private: - /** The base address of this device */ - Addr addr; - - /** The size of mappad from the above address */ - static const Addr size = 0xfffffff; - protected: /** * pointer to the tsunami object. @@ -85,36 +77,24 @@ class TsunamiCChip : public PioDevice uint64_t itint; public: + struct Params : public BasicPioDevice::Params + { + Tsunami *tsunami; + }; + protected: + const Params *params() const {return (const Params *)_params; } + + public: /** * Initialize the Tsunami CChip by setting all of the * device register to 0. - * @param name name of this device. - * @param t pointer back to the Tsunami object that we belong to. - * @param a address we are mapped at. - * @param mmu pointer to the memory controller that sends us events. - * @param hier object to store parameters universal the device hierarchy - * @param bus The bus that this device is attached to + * @param p params struct */ - TsunamiCChip(const std::string &name, Tsunami *t, Addr a, - MemoryController *mmu, HierParams *hier, Bus *pio_bus, - Tick pio_latency); - - /** - * Process a read to the CChip. - * @param req Contains the address to read from. - * @param data A pointer to write the read data to. - * @return The fault condition of the access. - */ - virtual Fault read(MemReqPtr &req, uint8_t *data); + TsunamiCChip(Params *p); + virtual Tick read(Packet &pkt); - /** - * Process a write to the CChip. - * @param req Contains the address to write to. - * @param data The data to write. - * @return The fault condition of the access. - */ - virtual Fault write(MemReqPtr &req, const uint8_t *data); + virtual Tick write(Packet &pkt); /** * post an RTC interrupt to the CPU @@ -165,12 +145,6 @@ class TsunamiCChip : public PioDevice */ virtual void unserialize(Checkpoint *cp, const std::string §ion); - /** - * Return how long this access will take. - * @param req the memory request to calcuate - * @return Tick when the request is done - */ - Tick cacheAccess(MemReqPtr &req); }; #endif // __TSUNAMI_CCHIP_HH__ diff --git a/dev/tsunami_io.cc b/dev/tsunami_io.cc index e66d6653b..0efcc1028 100644 --- a/dev/tsunami_io.cc +++ b/dev/tsunami_io.cc @@ -37,17 +37,15 @@ #include <vector> #include "base/trace.hh" -#include "dev/tsunami_io.hh" -#include "dev/tsunami.hh" #include "dev/pitreg.h" -#include "mem/bus/bus.hh" -#include "mem/bus/pio_interface.hh" -#include "mem/bus/pio_interface_impl.hh" -#include "sim/builder.hh" +#include "dev/rtcreg.h" #include "dev/tsunami_cchip.hh" +#include "dev/tsunami.hh" +#include "dev/tsunami_io.hh" #include "dev/tsunamireg.h" -#include "dev/rtcreg.h" -#include "mem/functional/memory_control.hh" +#include "mem/port.hh" +#include "sim/builder.hh" +#include "sim/system.hh" using namespace std; //Should this be AlphaISA? @@ -79,38 +77,38 @@ TsunamiIO::RTC::set_time(time_t t) } void -TsunamiIO::RTC::writeAddr(const uint8_t *data) +TsunamiIO::RTC::writeAddr(const uint8_t data) { - if (*data <= RTC_STAT_REGD) - addr = *data; + if (data <= RTC_STAT_REGD) + addr = data; else panic("RTC addresses over 0xD are not implemented.\n"); } void -TsunamiIO::RTC::writeData(const uint8_t *data) +TsunamiIO::RTC::writeData(const uint8_t data) { if (addr < RTC_STAT_REGA) - clock_data[addr] = *data; + clock_data[addr] = data; else { switch (addr) { case RTC_STAT_REGA: - if (*data != (RTCA_32768HZ | RTCA_1024HZ)) + if (data != (RTCA_32768HZ | RTCA_1024HZ)) panic("Unimplemented RTC register A value write!\n"); - stat_regA = *data; + stat_regA = data; break; case RTC_STAT_REGB: - if ((*data & ~(RTCB_PRDC_IE | RTCB_SQWE)) != (RTCB_BIN | RTCB_24HR)) + if ((data & ~(RTCB_PRDC_IE | RTCB_SQWE)) != (RTCB_BIN | RTCB_24HR)) panic("Write to RTC reg B bits that are not implemented!\n"); - if (*data & RTCB_PRDC_IE) { + if (data & RTCB_PRDC_IE) { if (!event.scheduled()) event.scheduleIntr(); } else { if (event.scheduled()) event.deschedule(); } - stat_regB = *data; + stat_regB = data; break; case RTC_STAT_REGC: case RTC_STAT_REGD: @@ -206,24 +204,24 @@ TsunamiIO::PITimer::PITimer(const string &name) } void -TsunamiIO::PITimer::writeControl(const uint8_t *data) +TsunamiIO::PITimer::writeControl(const uint8_t data) { int rw; int sel; - sel = GET_CTRL_SEL(*data); + sel = GET_CTRL_SEL(data); if (sel == PIT_READ_BACK) panic("PITimer Read-Back Command is not implemented.\n"); - rw = GET_CTRL_RW(*data); + rw = GET_CTRL_RW(data); if (rw == PIT_RW_LATCH_COMMAND) counter[sel]->latchCount(); else { counter[sel]->setRW(rw); - counter[sel]->setMode(GET_CTRL_MODE(*data)); - counter[sel]->setBCD(GET_CTRL_BCD(*data)); + counter[sel]->setMode(GET_CTRL_MODE(data)); + counter[sel]->setBCD(GET_CTRL_BCD(data)); } } @@ -295,11 +293,11 @@ TsunamiIO::PITimer::Counter::read(uint8_t *data) } void -TsunamiIO::PITimer::Counter::write(const uint8_t *data) +TsunamiIO::PITimer::Counter::write(const uint8_t data) { switch (write_byte) { case LSB: - count = (count & 0xFF00) | *data; + count = (count & 0xFF00) | data; if (event.scheduled()) event.deschedule(); @@ -308,7 +306,7 @@ TsunamiIO::PITimer::Counter::write(const uint8_t *data) break; case MSB: - count = (count & 0x00FF) | (*data << 8); + count = (count & 0x00FF) | (data << 8); period = count; if (period > 0) { @@ -416,26 +414,17 @@ TsunamiIO::PITimer::Counter::CounterEvent::description() return "tsunami 8254 Interval timer"; } -TsunamiIO::TsunamiIO(const string &name, Tsunami *t, time_t init_time, - Addr a, MemoryController *mmu, HierParams *hier, - Bus *pio_bus, Tick pio_latency, Tick ci) - : PioDevice(name, t), addr(a), clockInterval(ci), tsunami(t), - pitimer(name + "pitimer"), rtc(name + ".rtc", t, ci) +TsunamiIO::TsunamiIO(Params *p) + : BasicPioDevice(p), tsunami(p->tsunami), pitimer(p->name + "pitimer"), + rtc(p->name + ".rtc", p->tsunami, p->frequency) { - mmu->add_child(this, RangeSize(addr, size)); - - if (pio_bus) { - pioInterface = newPioInterface(name + ".pio", hier, pio_bus, this, - &TsunamiIO::cacheAccess); - pioInterface->addAddrRange(RangeSize(addr, size)); - pioLatency = pio_latency * pio_bus->clockRate; - } + pioSize = 0xff; // set the back pointer from tsunami to myself tsunami->io = this; timerData = 0; - rtc.set_time(init_time == 0 ? time(NULL) : init_time); + rtc.set_time(p->init_time == 0 ? time(NULL) : p->init_time); picr = 0; picInterrupting = false; } @@ -443,185 +432,156 @@ TsunamiIO::TsunamiIO(const string &name, Tsunami *t, time_t init_time, Tick TsunamiIO::frequency() const { - return Clock::Frequency / clockInterval; + return Clock::Frequency / params()->frequency; } -Fault -TsunamiIO::read(MemReqPtr &req, uint8_t *data) +Tick +TsunamiIO::read(Packet &pkt) { - DPRINTF(Tsunami, "io read va=%#x size=%d IOPorrt=%#x\n", - req->vaddr, req->size, req->vaddr & 0xfff); + assert(pkt.result == Unknown); + assert(pkt.addr >= pioAddr && pkt.addr < pioAddr + pioSize); + + pkt.time += pioDelay; + Addr daddr = pkt.addr - pioAddr; - Addr daddr = (req->paddr - (addr & EV5::PAddrImplMask)); + DPRINTF(Tsunami, "io read va=%#x size=%d IOPorrt=%#x\n", pkt.addr, + pkt.size, daddr); + pkt.allocate(); - switch(req->size) { - case sizeof(uint8_t): + if (pkt.size == sizeof(uint8_t)) { switch(daddr) { // PIC1 mask read case TSDEV_PIC1_MASK: - *(uint8_t*)data = ~mask1; - return NoFault; + pkt.set(~mask1); + break; case TSDEV_PIC2_MASK: - *(uint8_t*)data = ~mask2; - return NoFault; + pkt.set(~mask2); + break; case TSDEV_PIC1_ISR: // !!! If this is modified 64bit case needs to be too // Pal code has to do a 64 bit physical read because there is // no load physical byte instruction - *(uint8_t*)data = picr; - return NoFault; + pkt.set(picr); + break; case TSDEV_PIC2_ISR: // PIC2 not implemnted... just return 0 - *(uint8_t*)data = 0x00; - return NoFault; + pkt.set(0x00); + break; case TSDEV_TMR0_DATA: - pitimer.counter0.read(data); - return NoFault; + pitimer.counter0.read(pkt.getPtr<uint8_t>()); + break; case TSDEV_TMR1_DATA: - pitimer.counter1.read(data); - return NoFault; + pitimer.counter1.read(pkt.getPtr<uint8_t>()); + break; case TSDEV_TMR2_DATA: - pitimer.counter2.read(data); - return NoFault; + pitimer.counter2.read(pkt.getPtr<uint8_t>()); + break; case TSDEV_RTC_DATA: - rtc.readData(data); - return NoFault; + rtc.readData(pkt.getPtr<uint8_t>()); + break; case TSDEV_CTRL_PORTB: if (pitimer.counter2.outputHigh()) - *data = PORTB_SPKR_HIGH; + pkt.set(PORTB_SPKR_HIGH); else - *data = 0x00; - return NoFault; + pkt.set(0x00); + break; default: - panic("I/O Read - va%#x size %d\n", req->vaddr, req->size); + panic("I/O Read - va%#x size %d\n", pkt.addr, pkt.size); } - case sizeof(uint16_t): - case sizeof(uint32_t): - panic("I/O Read - invalid size - va %#x size %d\n", - req->vaddr, req->size); - - case sizeof(uint64_t): - switch(daddr) { - case TSDEV_PIC1_ISR: - // !!! If this is modified 8bit case needs to be too - // Pal code has to do a 64 bit physical read because there is - // no load physical byte instruction - *(uint64_t*)data = (uint64_t)picr; - return NoFault; - default: - panic("I/O Read - invalid size - va %#x size %d\n", - req->vaddr, req->size); - } - - default: - panic("I/O Read - invalid size - va %#x size %d\n", - req->vaddr, req->size); + } else if (pkt.size == sizeof(uint64_t)) { + if (daddr == TSDEV_PIC1_ISR) + pkt.set<uint64_t>(picr); + else + panic("I/O Read - invalid addr - va %#x size %d\n", + pkt.addr, pkt.size); + } else { + panic("I/O Read - invalid size - va %#x size %d\n", pkt.addr, pkt.size); } - panic("I/O Read - va%#x size %d\n", req->vaddr, req->size); - - return NoFault; + pkt.result = Success; + return pioDelay; } -Fault -TsunamiIO::write(MemReqPtr &req, const uint8_t *data) +Tick +TsunamiIO::write(Packet &pkt) { + pkt.time += pioDelay; -#if TRACING_ON - uint8_t dt = *(uint8_t*)data; - uint64_t dt64 = dt; -#endif + assert(pkt.result == Unknown); + assert(pkt.addr >= pioAddr && pkt.addr < pioAddr + pioSize); + Addr daddr = pkt.addr - pioAddr; DPRINTF(Tsunami, "io write - va=%#x size=%d IOPort=%#x Data=%#x\n", - req->vaddr, req->size, req->vaddr & 0xfff, dt64); + pkt.addr, pkt.size, pkt.addr & 0xfff, (uint32_t)pkt.get<uint8_t>()); - Addr daddr = (req->paddr - (addr & EV5::PAddrImplMask)); + assert(pkt.size == sizeof(uint8_t)); - switch(req->size) { - case sizeof(uint8_t): - switch(daddr) { - case TSDEV_PIC1_MASK: - mask1 = ~(*(uint8_t*)data); - if ((picr & mask1) && !picInterrupting) { - picInterrupting = true; - tsunami->cchip->postDRIR(55); - DPRINTF(Tsunami, "posting pic interrupt to cchip\n"); - } - if ((!(picr & mask1)) && picInterrupting) { - picInterrupting = false; - tsunami->cchip->clearDRIR(55); - DPRINTF(Tsunami, "clearing pic interrupt\n"); - } - return NoFault; - case TSDEV_PIC2_MASK: - mask2 = *(uint8_t*)data; - //PIC2 Not implemented to interrupt - return NoFault; - case TSDEV_PIC1_ACK: - // clear the interrupt on the PIC - picr &= ~(1 << (*(uint8_t*)data & 0xF)); - if (!(picr & mask1)) - tsunami->cchip->clearDRIR(55); - return NoFault; - case TSDEV_DMA1_CMND: - return NoFault; - case TSDEV_DMA2_CMND: - return NoFault; - case TSDEV_DMA1_MMASK: - return NoFault; - case TSDEV_DMA2_MMASK: - return NoFault; - case TSDEV_PIC2_ACK: - return NoFault; - case TSDEV_DMA1_RESET: - return NoFault; - case TSDEV_DMA2_RESET: - return NoFault; - case TSDEV_DMA1_MODE: - mode1 = *(uint8_t*)data; - return NoFault; - case TSDEV_DMA2_MODE: - mode2 = *(uint8_t*)data; - return NoFault; - case TSDEV_DMA1_MASK: - case TSDEV_DMA2_MASK: - return NoFault; - case TSDEV_TMR0_DATA: - pitimer.counter0.write(data); - return NoFault; - case TSDEV_TMR1_DATA: - pitimer.counter1.write(data); - return NoFault; - case TSDEV_TMR2_DATA: - pitimer.counter2.write(data); - return NoFault; - case TSDEV_TMR_CTRL: - pitimer.writeControl(data); - return NoFault; - case TSDEV_RTC_ADDR: - rtc.writeAddr(data); - return NoFault; - case TSDEV_KBD: - return NoFault; - case TSDEV_RTC_DATA: - rtc.writeData(data); - return NoFault; - case TSDEV_CTRL_PORTB: - // System Control Port B not implemented - return NoFault; - default: - panic("I/O Write - va%#x size %d data %#x\n", req->vaddr, req->size, (int)*data); + switch(daddr) { + case TSDEV_PIC1_MASK: + mask1 = ~(pkt.get<uint8_t>()); + if ((picr & mask1) && !picInterrupting) { + picInterrupting = true; + tsunami->cchip->postDRIR(55); + DPRINTF(Tsunami, "posting pic interrupt to cchip\n"); + } + if ((!(picr & mask1)) && picInterrupting) { + picInterrupting = false; + tsunami->cchip->clearDRIR(55); + DPRINTF(Tsunami, "clearing pic interrupt\n"); } - case sizeof(uint16_t): - case sizeof(uint32_t): - case sizeof(uint64_t): + break; + case TSDEV_PIC2_MASK: + mask2 = pkt.get<uint8_t>(); + //PIC2 Not implemented to interrupt + break; + case TSDEV_PIC1_ACK: + // clear the interrupt on the PIC + picr &= ~(1 << (pkt.get<uint8_t>() & 0xF)); + if (!(picr & mask1)) + tsunami->cchip->clearDRIR(55); + break; + case TSDEV_DMA1_MODE: + mode1 = pkt.get<uint8_t>(); + break; + case TSDEV_DMA2_MODE: + mode2 = pkt.get<uint8_t>(); + break; + case TSDEV_TMR0_DATA: + pitimer.counter0.write(pkt.get<uint8_t>()); + break; + case TSDEV_TMR1_DATA: + pitimer.counter1.write(pkt.get<uint8_t>()); + break; + case TSDEV_TMR2_DATA: + pitimer.counter2.write(pkt.get<uint8_t>()); + break; + case TSDEV_TMR_CTRL: + pitimer.writeControl(pkt.get<uint8_t>()); + break; + case TSDEV_RTC_ADDR: + rtc.writeAddr(pkt.get<uint8_t>()); + break; + case TSDEV_RTC_DATA: + rtc.writeData(pkt.get<uint8_t>()); + break; + case TSDEV_KBD: + case TSDEV_DMA1_CMND: + case TSDEV_DMA2_CMND: + case TSDEV_DMA1_MMASK: + case TSDEV_DMA2_MMASK: + case TSDEV_PIC2_ACK: + case TSDEV_DMA1_RESET: + case TSDEV_DMA2_RESET: + case TSDEV_DMA1_MASK: + case TSDEV_DMA2_MASK: + case TSDEV_CTRL_PORTB: + break; default: - panic("I/O Write - invalid size - va %#x size %d\n", - req->vaddr, req->size); + panic("I/O Write - va%#x size %d data %#x\n", pkt.addr, pkt.size, pkt.get<uint8_t>()); } - - return NoFault; + pkt.result = Success; + return pioDelay; } void @@ -646,12 +606,6 @@ TsunamiIO::clearPIC(uint8_t bitvector) } } -Tick -TsunamiIO::cacheAccess(MemReqPtr &req) -{ - return curTick + pioLatency; -} - void TsunamiIO::serialize(ostream &os) { @@ -686,34 +640,40 @@ TsunamiIO::unserialize(Checkpoint *cp, const string §ion) BEGIN_DECLARE_SIM_OBJECT_PARAMS(TsunamiIO) - SimObjectParam<Tsunami *> tsunami; - Param<time_t> time; - SimObjectParam<MemoryController *> mmu; - Param<Addr> addr; - SimObjectParam<Bus*> pio_bus; + Param<Addr> pio_addr; Param<Tick> pio_latency; - SimObjectParam<HierParams *> hier; Param<Tick> frequency; + SimObjectParam<Platform *> platform; + SimObjectParam<System *> system; + Param<time_t> time; + SimObjectParam<Tsunami *> tsunami; END_DECLARE_SIM_OBJECT_PARAMS(TsunamiIO) BEGIN_INIT_SIM_OBJECT_PARAMS(TsunamiIO) - INIT_PARAM(tsunami, "Tsunami"), + INIT_PARAM(pio_addr, "Device Address"), + INIT_PARAM(pio_latency, "Programmed IO latency"), + INIT_PARAM(frequency, "clock interrupt frequency"), + INIT_PARAM(platform, "platform"), + INIT_PARAM(system, "system object"), INIT_PARAM(time, "System time to use (0 for actual time"), - INIT_PARAM(mmu, "Memory Controller"), - INIT_PARAM(addr, "Device Address"), - INIT_PARAM(pio_bus, "The IO Bus to attach to"), - INIT_PARAM_DFLT(pio_latency, "Programmed IO latency in bus cycles", 1), - INIT_PARAM_DFLT(hier, "Hierarchy global variables", &defaultHierParams), - INIT_PARAM(frequency, "clock interrupt frequency") + INIT_PARAM(tsunami, "Tsunami") END_INIT_SIM_OBJECT_PARAMS(TsunamiIO) CREATE_SIM_OBJECT(TsunamiIO) { - return new TsunamiIO(getInstanceName(), tsunami, time, addr, mmu, hier, - pio_bus, pio_latency, frequency); + TsunamiIO::Params *p = new TsunamiIO::Params; + p->frequency = frequency; + p->name = getInstanceName(); + p->pio_addr = pio_addr; + p->pio_delay = pio_latency; + p->platform = platform; + p->system = system; + p->init_time = time; + p->tsunami = tsunami; + return new TsunamiIO(p); } REGISTER_SIM_OBJECT("TsunamiIO", TsunamiIO) diff --git a/dev/tsunami_io.hh b/dev/tsunami_io.hh index b024ecd14..c37f3aa16 100644 --- a/dev/tsunami_io.hh +++ b/dev/tsunami_io.hh @@ -38,21 +38,13 @@ #include "dev/tsunami.hh" #include "sim/eventq.hh" -class MemoryController; - /** * Tsunami I/O device is a catch all for all the south bridge stuff we care * to implement. */ -class TsunamiIO : public PioDevice +class TsunamiIO : public BasicPioDevice { private: - /** The base address of this device */ - Addr addr; - - /** The size of mappad from the above address */ - static const Addr size = 0xff; - struct tm tm; protected: @@ -120,10 +112,10 @@ class TsunamiIO : public PioDevice void set_time(time_t t); /** RTC address port: write address of RTC RAM data to access */ - void writeAddr(const uint8_t *data); + void writeAddr(const uint8_t data); /** RTC write data */ - void writeData(const uint8_t *data); + void writeData(const uint8_t data); /** RTC read data */ void readData(uint8_t *data); @@ -218,7 +210,7 @@ class TsunamiIO : public PioDevice void read(uint8_t *data); /** Write a count byte */ - void write(const uint8_t *data); + void write(const uint8_t data); /** Is the output high? */ bool outputHigh(); @@ -254,7 +246,7 @@ class TsunamiIO : public PioDevice PITimer(const std::string &name); /** Write control word */ - void writeControl(const uint8_t* data); + void writeControl(const uint8_t data); /** * Serialize this object to the given output stream. @@ -289,8 +281,6 @@ class TsunamiIO : public PioDevice /** Is the pic interrupting right now or not. */ bool picInterrupting; - Tick clockInterval; - /** A pointer to the Tsunami device which be belong to */ Tsunami *tsunami; @@ -312,33 +302,24 @@ class TsunamiIO : public PioDevice */ Tick frequency() const; + struct Params : public BasicPioDevice::Params + { + Tick frequency; + Tsunami *tsunami; + time_t init_time; + }; + protected: + const Params *params() const { return (const Params*)_params; } + + public: /** * Initialize all the data for devices supported by Tsunami I/O. - * @param name name of this device. - * @param t pointer back to the Tsunami object that we belong to. - * @param init_time Time (as in seconds since 1970) to set RTC to. - * @param a address we are mapped at. - * @param mmu pointer to the memory controller that sends us events. + * @param p pointer to Params struct */ - TsunamiIO(const std::string &name, Tsunami *t, time_t init_time, - Addr a, MemoryController *mmu, HierParams *hier, Bus *pio_bus, - Tick pio_latency, Tick ci); + TsunamiIO(Params *p); - /** - * Process a read to one of the devices we are emulating. - * @param req Contains the address to read from. - * @param data A pointer to write the read data to. - * @return The fault condition of the access. - */ - virtual Fault read(MemReqPtr &req, uint8_t *data); - - /** - * Process a write to one of the devices we emulate. - * @param req Contains the address to write to. - * @param data The data to write. - * @return The fault condition of the access. - */ - virtual Fault write(MemReqPtr &req, const uint8_t *data); + virtual Tick read(Packet &pkt); + virtual Tick write(Packet &pkt); /** * Post an PIC interrupt to the CPU via the CChip @@ -365,7 +346,6 @@ class TsunamiIO : public PioDevice */ virtual void unserialize(Checkpoint *cp, const std::string §ion); - Tick cacheAccess(MemReqPtr &req); }; #endif // __DEV_TSUNAMI_IO_HH__ diff --git a/dev/tsunami_pchip.cc b/dev/tsunami_pchip.cc index 46efc3dfe..1323a0548 100644 --- a/dev/tsunami_pchip.cc +++ b/dev/tsunami_pchip.cc @@ -38,11 +38,7 @@ #include "dev/tsunami_pchip.hh" #include "dev/tsunamireg.h" #include "dev/tsunami.hh" -#include "mem/bus/bus.hh" -#include "mem/bus/pio_interface.hh" -#include "mem/bus/pio_interface_impl.hh" -#include "mem/functional/memory_control.hh" -#include "mem/functional/physical.hh" +#include "mem/packet.hh" #include "sim/builder.hh" #include "sim/system.hh" @@ -50,12 +46,10 @@ using namespace std; //Should this be AlphaISA? using namespace TheISA; -TsunamiPChip::TsunamiPChip(const string &name, Tsunami *t, Addr a, - MemoryController *mmu, HierParams *hier, - Bus *pio_bus, Tick pio_latency) - : PioDevice(name, t), addr(a), tsunami(t) +TsunamiPChip::TsunamiPChip(Params *p) +: BasicPioDevice(p) { - mmu->add_child(this, RangeSize(addr, size)); + pioSize = 0xfff; for (int i = 0; i < 4; i++) { wsba[i] = 0; @@ -63,195 +57,175 @@ TsunamiPChip::TsunamiPChip(const string &name, Tsunami *t, Addr a, tba[i] = 0; } - if (pio_bus) { - pioInterface = newPioInterface(name + ".pio", hier, pio_bus, this, - &TsunamiPChip::cacheAccess); - pioInterface->addAddrRange(RangeSize(addr, size)); - pioLatency = pio_latency * pio_bus->clockRate; - } - - // initialize pchip control register pctl = (ULL(0x1) << 20) | (ULL(0x1) << 32) | (ULL(0x2) << 36); //Set back pointer in tsunami - tsunami->pchip = this; + p->tsunami->pchip = this; } -Fault -TsunamiPChip::read(MemReqPtr &req, uint8_t *data) +Tick +TsunamiPChip::read(Packet &pkt) { - DPRINTF(Tsunami, "read va=%#x size=%d\n", - req->vaddr, req->size); - - Addr daddr = (req->paddr - (addr & EV5::PAddrImplMask)) >> 6; - - switch (req->size) { - - case sizeof(uint64_t): - switch(daddr) { - case TSDEV_PC_WSBA0: - *(uint64_t*)data = wsba[0]; - return NoFault; - case TSDEV_PC_WSBA1: - *(uint64_t*)data = wsba[1]; - return NoFault; - case TSDEV_PC_WSBA2: - *(uint64_t*)data = wsba[2]; - return NoFault; - case TSDEV_PC_WSBA3: - *(uint64_t*)data = wsba[3]; - return NoFault; - case TSDEV_PC_WSM0: - *(uint64_t*)data = wsm[0]; - return NoFault; - case TSDEV_PC_WSM1: - *(uint64_t*)data = wsm[1]; - return NoFault; - case TSDEV_PC_WSM2: - *(uint64_t*)data = wsm[2]; - return NoFault; - case TSDEV_PC_WSM3: - *(uint64_t*)data = wsm[3]; - return NoFault; - case TSDEV_PC_TBA0: - *(uint64_t*)data = tba[0]; - return NoFault; - case TSDEV_PC_TBA1: - *(uint64_t*)data = tba[1]; - return NoFault; - case TSDEV_PC_TBA2: - *(uint64_t*)data = tba[2]; - return NoFault; - case TSDEV_PC_TBA3: - *(uint64_t*)data = tba[3]; - return NoFault; - case TSDEV_PC_PCTL: - *(uint64_t*)data = pctl; - return NoFault; - case TSDEV_PC_PLAT: - panic("PC_PLAT not implemented\n"); - case TSDEV_PC_RES: - panic("PC_RES not implemented\n"); - case TSDEV_PC_PERROR: - *(uint64_t*)data = 0x00; - return NoFault; - case TSDEV_PC_PERRMASK: - *(uint64_t*)data = 0x00; - return NoFault; - case TSDEV_PC_PERRSET: - panic("PC_PERRSET not implemented\n"); - case TSDEV_PC_TLBIV: - panic("PC_TLBIV not implemented\n"); - case TSDEV_PC_TLBIA: - *(uint64_t*)data = 0x00; // shouldn't be readable, but linux - return NoFault; - case TSDEV_PC_PMONCTL: - panic("PC_PMONCTL not implemented\n"); - case TSDEV_PC_PMONCNT: - panic("PC_PMONCTN not implemented\n"); - default: - panic("Default in PChip Read reached reading 0x%x\n", daddr); - - } // uint64_t - - break; - case sizeof(uint32_t): - case sizeof(uint16_t): - case sizeof(uint8_t): + assert(pkt.result == Unknown); + assert(pkt.addr >= pioAddr && pkt.addr < pioAddr + pioSize); + + + pkt.time += pioDelay; + pkt.allocate(); + Addr daddr = (pkt.addr - pioAddr) >> 6;; + assert(pkt.size == sizeof(uint64_t)); + + + DPRINTF(Tsunami, "read va=%#x size=%d\n", pkt.addr, pkt.size); + + switch(daddr) { + case TSDEV_PC_WSBA0: + pkt.set(wsba[0]); + break; + case TSDEV_PC_WSBA1: + pkt.set(wsba[1]); + break; + case TSDEV_PC_WSBA2: + pkt.set(wsba[2]); + break; + case TSDEV_PC_WSBA3: + pkt.set(wsba[3]); + break; + case TSDEV_PC_WSM0: + pkt.set(wsm[0]); + break; + case TSDEV_PC_WSM1: + pkt.set(wsm[1]); + break; + case TSDEV_PC_WSM2: + pkt.set(wsm[2]); + break; + case TSDEV_PC_WSM3: + pkt.set(wsm[3]); + break; + case TSDEV_PC_TBA0: + pkt.set(tba[0]); + break; + case TSDEV_PC_TBA1: + pkt.set(tba[1]); + break; + case TSDEV_PC_TBA2: + pkt.set(tba[2]); + break; + case TSDEV_PC_TBA3: + pkt.set(tba[3]); + break; + case TSDEV_PC_PCTL: + pkt.set(pctl); + break; + case TSDEV_PC_PLAT: + panic("PC_PLAT not implemented\n"); + case TSDEV_PC_RES: + panic("PC_RES not implemented\n"); + case TSDEV_PC_PERROR: + pkt.set((uint64_t)0x00); + break; + case TSDEV_PC_PERRMASK: + pkt.set((uint64_t)0x00); + break; + case TSDEV_PC_PERRSET: + panic("PC_PERRSET not implemented\n"); + case TSDEV_PC_TLBIV: + panic("PC_TLBIV not implemented\n"); + case TSDEV_PC_TLBIA: + pkt.set((uint64_t)0x00); // shouldn't be readable, but linux + break; + case TSDEV_PC_PMONCTL: + panic("PC_PMONCTL not implemented\n"); + case TSDEV_PC_PMONCNT: + panic("PC_PMONCTN not implemented\n"); default: - panic("invalid access size(?) for tsunami register!\n\n"); + panic("Default in PChip Read reached reading 0x%x\n", daddr); } - DPRINTFN("Tsunami PChip ERROR: read daddr=%#x size=%d\n", daddr, req->size); + pkt.result = Success; + return pioDelay; - return NoFault; } -Fault -TsunamiPChip::write(MemReqPtr &req, const uint8_t *data) +Tick +TsunamiPChip::write(Packet &pkt) { - DPRINTF(Tsunami, "write - va=%#x size=%d \n", - req->vaddr, req->size); - - Addr daddr = (req->paddr - (addr & EV5::PAddrImplMask)) >> 6; - - switch (req->size) { - - case sizeof(uint64_t): - switch(daddr) { - case TSDEV_PC_WSBA0: - wsba[0] = *(uint64_t*)data; - return NoFault; - case TSDEV_PC_WSBA1: - wsba[1] = *(uint64_t*)data; - return NoFault; - case TSDEV_PC_WSBA2: - wsba[2] = *(uint64_t*)data; - return NoFault; - case TSDEV_PC_WSBA3: - wsba[3] = *(uint64_t*)data; - return NoFault; - case TSDEV_PC_WSM0: - wsm[0] = *(uint64_t*)data; - return NoFault; - case TSDEV_PC_WSM1: - wsm[1] = *(uint64_t*)data; - return NoFault; - case TSDEV_PC_WSM2: - wsm[2] = *(uint64_t*)data; - return NoFault; - case TSDEV_PC_WSM3: - wsm[3] = *(uint64_t*)data; - return NoFault; - case TSDEV_PC_TBA0: - tba[0] = *(uint64_t*)data; - return NoFault; - case TSDEV_PC_TBA1: - tba[1] = *(uint64_t*)data; - return NoFault; - case TSDEV_PC_TBA2: - tba[2] = *(uint64_t*)data; - return NoFault; - case TSDEV_PC_TBA3: - tba[3] = *(uint64_t*)data; - return NoFault; - case TSDEV_PC_PCTL: - pctl = *(uint64_t*)data; - return NoFault; - case TSDEV_PC_PLAT: - panic("PC_PLAT not implemented\n"); - case TSDEV_PC_RES: - panic("PC_RES not implemented\n"); - case TSDEV_PC_PERROR: - return NoFault; - case TSDEV_PC_PERRMASK: - panic("PC_PERRMASK not implemented\n"); - case TSDEV_PC_PERRSET: - panic("PC_PERRSET not implemented\n"); - case TSDEV_PC_TLBIV: - panic("PC_TLBIV not implemented\n"); - case TSDEV_PC_TLBIA: - return NoFault; // value ignored, supposted to invalidate SG TLB - case TSDEV_PC_PMONCTL: - panic("PC_PMONCTL not implemented\n"); - case TSDEV_PC_PMONCNT: - panic("PC_PMONCTN not implemented\n"); - default: - panic("Default in PChip Read reached reading 0x%x\n", daddr); - - } // uint64_t - - break; - case sizeof(uint32_t): - case sizeof(uint16_t): - case sizeof(uint8_t): - default: - panic("invalid access size(?) for tsunami register!\n\n"); - } - - DPRINTFN("Tsunami ERROR: write daddr=%#x size=%d\n", daddr, req->size); - - return NoFault; + pkt.time += pioDelay; + + assert(pkt.result == Unknown); + assert(pkt.addr >= pioAddr && pkt.addr < pioAddr + pioSize); + Addr daddr = (pkt.addr - pioAddr) >> 6; + + assert(pkt.size == sizeof(uint64_t)); + + DPRINTF(Tsunami, "write - va=%#x size=%d \n", pkt.addr, pkt.size); + + switch(daddr) { + case TSDEV_PC_WSBA0: + wsba[0] = pkt.get<uint64_t>(); + break; + case TSDEV_PC_WSBA1: + wsba[1] = pkt.get<uint64_t>(); + break; + case TSDEV_PC_WSBA2: + wsba[2] = pkt.get<uint64_t>(); + break; + case TSDEV_PC_WSBA3: + wsba[3] = pkt.get<uint64_t>(); + break; + case TSDEV_PC_WSM0: + wsm[0] = pkt.get<uint64_t>(); + break; + case TSDEV_PC_WSM1: + wsm[1] = pkt.get<uint64_t>(); + break; + case TSDEV_PC_WSM2: + wsm[2] = pkt.get<uint64_t>(); + break; + case TSDEV_PC_WSM3: + wsm[3] = pkt.get<uint64_t>(); + break; + case TSDEV_PC_TBA0: + tba[0] = pkt.get<uint64_t>(); + break; + case TSDEV_PC_TBA1: + tba[1] = pkt.get<uint64_t>(); + break; + case TSDEV_PC_TBA2: + tba[2] = pkt.get<uint64_t>(); + break; + case TSDEV_PC_TBA3: + tba[3] = pkt.get<uint64_t>(); + break; + case TSDEV_PC_PCTL: + pctl = pkt.get<uint64_t>(); + break; + case TSDEV_PC_PLAT: + panic("PC_PLAT not implemented\n"); + case TSDEV_PC_RES: + panic("PC_RES not implemented\n"); + case TSDEV_PC_PERROR: + break; + case TSDEV_PC_PERRMASK: + panic("PC_PERRMASK not implemented\n"); + case TSDEV_PC_PERRSET: + panic("PC_PERRSET not implemented\n"); + case TSDEV_PC_TLBIV: + panic("PC_TLBIV not implemented\n"); + case TSDEV_PC_TLBIA: + break; // value ignored, supposted to invalidate SG TLB + case TSDEV_PC_PMONCTL: + panic("PC_PMONCTL not implemented\n"); + case TSDEV_PC_PMONCNT: + panic("PC_PMONCTN not implemented\n"); + default: + panic("Default in PChip write reached reading 0x%x\n", daddr); + + } // uint64_t + + pkt.result = Success; + return pioDelay; } #define DMA_ADDR_MASK ULL(0x3ffffffff) @@ -311,10 +285,7 @@ TsunamiPChip::translatePciToDma(Addr busAddr) baMask = (wsm[i] & (ULL(0xfff) << 20)) | (ULL(0x7f) << 13); pteAddr = (tba[i] & tbaMask) | ((busAddr & baMask) >> 10); - memcpy((void *)&pteEntry, - tsunami->system-> - physmem->dma_addr(pteAddr, sizeof(uint64_t)), - sizeof(uint64_t)); + pioPort->readBlob(pteAddr, (uint8_t*)&pteEntry, sizeof(uint64_t)); dmaAddr = ((pteEntry & ~ULL(0x1)) << 12) | (busAddr & ULL(0x1fff)); @@ -351,38 +322,37 @@ TsunamiPChip::unserialize(Checkpoint *cp, const std::string §ion) UNSERIALIZE_ARRAY(tba, 4); } -Tick -TsunamiPChip::cacheAccess(MemReqPtr &req) -{ - return curTick + pioLatency; -} BEGIN_DECLARE_SIM_OBJECT_PARAMS(TsunamiPChip) - SimObjectParam<Tsunami *> tsunami; - SimObjectParam<MemoryController *> mmu; - Param<Addr> addr; - SimObjectParam<Bus*> pio_bus; + Param<Addr> pio_addr; Param<Tick> pio_latency; - SimObjectParam<HierParams *> hier; + SimObjectParam<Platform *> platform; + SimObjectParam<System *> system; + SimObjectParam<Tsunami *> tsunami; END_DECLARE_SIM_OBJECT_PARAMS(TsunamiPChip) BEGIN_INIT_SIM_OBJECT_PARAMS(TsunamiPChip) - INIT_PARAM(tsunami, "Tsunami"), - INIT_PARAM(mmu, "Memory Controller"), - INIT_PARAM(addr, "Device Address"), - INIT_PARAM_DFLT(pio_bus, "The IO Bus to attach to", NULL), - INIT_PARAM_DFLT(pio_latency, "Programmed IO latency in bus cycles", 1), - INIT_PARAM_DFLT(hier, "Hierarchy global variables", &defaultHierParams) + INIT_PARAM(pio_addr, "Device Address"), + INIT_PARAM(pio_latency, "Programmed IO latency"), + INIT_PARAM(platform, "platform"), + INIT_PARAM(system, "system object"), + INIT_PARAM(tsunami, "Tsunami") END_INIT_SIM_OBJECT_PARAMS(TsunamiPChip) CREATE_SIM_OBJECT(TsunamiPChip) { - return new TsunamiPChip(getInstanceName(), tsunami, addr, mmu, hier, - pio_bus, pio_latency); + TsunamiPChip::Params *p = new TsunamiPChip::Params; + p->name = getInstanceName(); + p->pio_addr = pio_addr; + p->pio_delay = pio_latency; + p->platform = platform; + p->system = system; + p->tsunami = tsunami; + return new TsunamiPChip(p); } REGISTER_SIM_OBJECT("TsunamiPChip", TsunamiPChip) diff --git a/dev/tsunami_pchip.hh b/dev/tsunami_pchip.hh index c1d95431b..2f3e8f078 100644 --- a/dev/tsunami_pchip.hh +++ b/dev/tsunami_pchip.hh @@ -37,28 +37,12 @@ #include "base/range.hh" #include "dev/io_device.hh" -class MemoryController; - /** * A very simple implementation of the Tsunami PCI interface chips. */ -class TsunamiPChip : public PioDevice +class TsunamiPChip : public BasicPioDevice { - private: - /** The base address of this device */ - Addr addr; - - /** The size of mappad from the above address */ - static const Addr size = 0xfff; - protected: - /** - * pointer to the tsunami object. - * This is our access to all the other tsunami - * devices. - */ - Tsunami *tsunami; - /** Pchip control register */ uint64_t pctl; @@ -72,18 +56,19 @@ class TsunamiPChip : public PioDevice uint64_t tba[4]; public: + struct Params : public BasicPioDevice::Params + { + Tsunami *tsunami; + }; + protected: + const Params *params() const { return (const Params*)_params; } + + public: /** * Register the PChip with the mmu and init all wsba, wsm, and tba to 0 - * @param name the name of thes device - * @param t a pointer to the tsunami device - * @param a the address which we respond to - * @param mmu the mmu we are to register with - * @param hier object to store parameters universal the device hierarchy - * @param bus The bus that this device is attached to + * @param p pointer to the parameters struct */ - TsunamiPChip(const std::string &name, Tsunami *t, Addr a, - MemoryController *mmu, HierParams *hier, Bus *pio_bus, - Tick pio_latency); + TsunamiPChip(Params *p); /** * Translate a PCI bus address to a memory address for DMA. @@ -93,21 +78,8 @@ class TsunamiPChip : public PioDevice */ Addr translatePciToDma(Addr busAddr); - /** - * Process a read to the PChip. - * @param req Contains the address to read from. - * @param data A pointer to write the read data to. - * @return The fault condition of the access. - */ - virtual Fault read(MemReqPtr &req, uint8_t *data); - - /** - * Process a write to the PChip. - * @param req Contains the address to write to. - * @param data The data to write. - * @return The fault condition of the access. - */ - virtual Fault write(MemReqPtr &req, const uint8_t *data); + virtual Tick read(Packet &pkt); + virtual Tick write(Packet &pkt); /** * Serialize this object to the given output stream. @@ -121,13 +93,6 @@ class TsunamiPChip : public PioDevice * @param section The section name of this object */ virtual void unserialize(Checkpoint *cp, const std::string §ion); - - /** - * Return how long this access will take. - * @param req the memory request to calcuate - * @return Tick when the request is done - */ - Tick cacheAccess(MemReqPtr &req); }; #endif // __TSUNAMI_PCHIP_HH__ diff --git a/dev/uart.cc b/dev/uart.cc index b2eeb8e9f..4a9f2b505 100644 --- a/dev/uart.cc +++ b/dev/uart.cc @@ -27,39 +27,19 @@ */ /** @file - * Implements a 8250 UART + * Implements a base class for UARTs */ -#include <string> -#include <vector> - -#include "base/inifile.hh" -#include "base/str.hh" // for to_number -#include "base/trace.hh" #include "dev/simconsole.hh" #include "dev/uart.hh" #include "dev/platform.hh" -#include "mem/bus/bus.hh" -#include "mem/bus/pio_interface.hh" -#include "mem/bus/pio_interface_impl.hh" -#include "mem/functional/memory_control.hh" #include "sim/builder.hh" using namespace std; -Uart::Uart(const string &name, SimConsole *c, MemoryController *mmu, Addr a, - Addr s, HierParams *hier, Bus *bus, Tick pio_latency, Platform *p) - : PioDevice(name, p), addr(a), size(s), cons(c) +Uart::Uart(Params *p) + : BasicPioDevice(p), platform(p->platform), cons(p->cons) { - mmu->add_child(this, RangeSize(addr, size)); - - - if (bus) { - pioInterface = newPioInterface(name, hier, bus, this, - &Uart::cacheAccess); - pioInterface->addAddrRange(RangeSize(addr, size)); - pioLatency = pio_latency * bus->clockRate; - } status = 0; @@ -68,11 +48,5 @@ Uart::Uart(const string &name, SimConsole *c, MemoryController *mmu, Addr a, platform->uart = this; } -Tick -Uart::cacheAccess(MemReqPtr &req) -{ - return curTick + pioLatency; -} - DEFINE_SIM_OBJECT_CLASS_NAME("Uart", Uart) diff --git a/dev/uart.hh b/dev/uart.hh index 78b1dc68e..2dd15d9b8 100644 --- a/dev/uart.hh +++ b/dev/uart.hh @@ -37,30 +37,27 @@ #include "dev/io_device.hh" class SimConsole; -class MemoryController; class Platform; const int RX_INT = 0x1; const int TX_INT = 0x2; -class Uart : public PioDevice +class Uart : public BasicPioDevice { protected: int status; - Addr addr; - Addr size; + Platform *platform; SimConsole *cons; public: - Uart(const std::string &name, SimConsole *c, MemoryController *mmu, - Addr a, Addr s, HierParams *hier, Bus *bus, Tick pio_latency, - Platform *p); - - virtual Fault read(MemReqPtr &req, uint8_t *data) = 0; - virtual Fault write(MemReqPtr &req, const uint8_t *data) = 0; + struct Params : public BasicPioDevice::Params + { + SimConsole *cons; + }; + Uart(Params *p); /** * Inform the uart that there is data available. @@ -74,12 +71,9 @@ class Uart : public PioDevice */ bool intStatus() { return status ? true : false; } - /** - * Return how long this access will take. - * @param req the memory request to calcuate - * @return Tick when the request is done - */ - Tick cacheAccess(MemReqPtr &req); + protected: + const Params *params() const {return (const Params *)_params; } + }; #endif // __UART_HH__ diff --git a/dev/uart8250.cc b/dev/uart8250.cc index 65bccee86..15752c735 100644 --- a/dev/uart8250.cc +++ b/dev/uart8250.cc @@ -33,16 +33,13 @@ #include <string> #include <vector> +#include "arch/alpha/ev5.hh" #include "base/inifile.hh" #include "base/str.hh" // for to_number #include "base/trace.hh" #include "dev/simconsole.hh" #include "dev/uart8250.hh" #include "dev/platform.hh" -#include "mem/bus/bus.hh" -#include "mem/bus/pio_interface.hh" -#include "mem/bus/pio_interface_impl.hh" -#include "mem/functional/memory_control.hh" #include "sim/builder.hh" using namespace std; @@ -99,34 +96,37 @@ Uart8250::IntrEvent::scheduleIntr() } -Uart8250::Uart8250(const string &name, SimConsole *c, MemoryController *mmu, - Addr a, Addr s, HierParams *hier, Bus *pio_bus, - Tick pio_latency, Platform *p) - : Uart(name, c, mmu, a, s, hier, pio_bus, pio_latency, p), - txIntrEvent(this, TX_INT), rxIntrEvent(this, RX_INT) +Uart8250::Uart8250(Params *p) + : Uart(p), txIntrEvent(this, TX_INT), rxIntrEvent(this, RX_INT) { + pioSize = 8; + IER = 0; DLAB = 0; LCR = 0; MCR = 0; - } -Fault -Uart8250::read(MemReqPtr &req, uint8_t *data) +Tick +Uart8250::read(Packet &pkt) { - Addr daddr = req->paddr - (addr & EV5::PAddrImplMask); - DPRINTF(Uart, " read register %#x\n", daddr); + assert(pkt.result == Unknown); + assert(pkt.addr >= pioAddr && pkt.addr < pioAddr + pioSize); + assert(pkt.size == 1); - assert(req->size == 1); + pkt.time += pioDelay; + Addr daddr = pkt.addr - pioAddr; + pkt.allocate(); + + DPRINTF(Uart, " read register %#x\n", daddr); switch (daddr) { case 0x0: if (!(LCR & 0x80)) { // read byte if (cons->dataAvailable()) - cons->in(*data); + cons->in(*pkt.getPtr<uint8_t>()); else { - *(uint8_t*)data = 0; + pkt.set((uint8_t)0); // A limited amount of these are ok. DPRINTF(Uart, "empty read of RX register\n"); } @@ -141,7 +141,7 @@ Uart8250::read(MemReqPtr &req, uint8_t *data) break; case 0x1: if (!(LCR & 0x80)) { // Intr Enable Register(IER) - *(uint8_t*)data = IER; + pkt.set(IER); } else { // DLM divisor latch MSB ; } @@ -150,17 +150,17 @@ Uart8250::read(MemReqPtr &req, uint8_t *data) DPRINTF(Uart, "IIR Read, status = %#x\n", (uint32_t)status); if (status & RX_INT) /* Rx data interrupt has a higher priority */ - *(uint8_t*)data = IIR_RXID; + pkt.set(IIR_RXID); else if (status & TX_INT) - *(uint8_t*)data = IIR_TXID; + pkt.set(IIR_TXID); else - *(uint8_t*)data = IIR_NOPEND; + pkt.set(IIR_NOPEND); //Tx interrupts are cleared on IIR reads status &= ~TX_INT; break; case 0x3: // Line Control Register (LCR) - *(uint8_t*)data = LCR; + pkt.set(LCR); break; case 0x4: // Modem Control Register (MCR) break; @@ -171,34 +171,42 @@ Uart8250::read(MemReqPtr &req, uint8_t *data) if (cons->dataAvailable()) lsr = UART_LSR_DR; lsr |= UART_LSR_TEMT | UART_LSR_THRE; - *(uint8_t*)data = lsr; + pkt.set(lsr); break; case 0x6: // Modem Status Register (MSR) - *(uint8_t*)data = 0; + pkt.set((uint8_t)0); break; case 0x7: // Scratch Register (SCR) - *(uint8_t*)data = 0; // doesn't exist with at 8250. + pkt.set((uint8_t)0); // doesn't exist with at 8250. break; default: panic("Tried to access a UART port that doesn't exist\n"); break; } - - return NoFault; - +/* uint32_t d32 = *data; + DPRINTF(Uart, "Register read to register %#x returned %#x\n", daddr, d32); +*/ + pkt.result = Success; + return pioDelay; } -Fault -Uart8250::write(MemReqPtr &req, const uint8_t *data) +Tick +Uart8250::write(Packet &pkt) { - Addr daddr = req->paddr - (addr & EV5::PAddrImplMask); - DPRINTF(Uart, " write register %#x value %#x\n", daddr, *(uint8_t*)data); + assert(pkt.result == Unknown); + assert(pkt.addr >= pioAddr && pkt.addr < pioAddr + pioSize); + assert(pkt.size == 1); + + pkt.time += pioDelay; + Addr daddr = pkt.addr - pioAddr; + + DPRINTF(Uart, " write register %#x value %#x\n", daddr, pkt.get<uint8_t>()); switch (daddr) { case 0x0: if (!(LCR & 0x80)) { // write byte - cons->out(*(uint8_t *)data); + cons->out(pkt.get<uint8_t>()); platform->clearConsoleInt(); status &= ~TX_INT; if (UART_IER_THRI & IER) @@ -209,7 +217,7 @@ Uart8250::write(MemReqPtr &req, const uint8_t *data) break; case 0x1: if (!(LCR & 0x80)) { // Intr Enable Register(IER) - IER = *(uint8_t*)data; + IER = pkt.get<uint8_t>(); if (UART_IER_THRI & IER) { DPRINTF(Uart, "IER: IER_THRI set, scheduling TX intrrupt\n"); @@ -243,10 +251,10 @@ Uart8250::write(MemReqPtr &req, const uint8_t *data) case 0x2: // FIFO Control Register (FCR) break; case 0x3: // Line Control Register (LCR) - LCR = *(uint8_t*)data; + LCR = pkt.get<uint8_t>(); break; case 0x4: // Modem Control Register (MCR) - if (*(uint8_t*)data == (UART_MCR_LOOP | 0x0A)) + if (pkt.get<uint8_t>() == (UART_MCR_LOOP | 0x0A)) MCR = 0x9A; break; case 0x7: // Scratch Register (SCR) @@ -256,7 +264,8 @@ Uart8250::write(MemReqPtr &req, const uint8_t *data) panic("Tried to access a UART port that doesn't exist\n"); break; } - return NoFault; + pkt.result = Success; + return pioDelay; } void @@ -271,6 +280,14 @@ Uart8250::dataAvailable() } +void +Uart8250::addressRanges(AddrRangeList &range_list) +{ + assert(pioSize != 0); + range_list.clear(); + range_list.push_back(RangeSize(pioAddr, pioSize)); +} + void @@ -315,35 +332,35 @@ Uart8250::unserialize(Checkpoint *cp, const std::string §ion) BEGIN_DECLARE_SIM_OBJECT_PARAMS(Uart8250) - SimObjectParam<SimConsole *> console; - SimObjectParam<MemoryController *> mmu; - SimObjectParam<Platform *> platform; - Param<Addr> addr; - Param<Addr> size; - SimObjectParam<Bus*> pio_bus; + Param<Addr> pio_addr; Param<Tick> pio_latency; - SimObjectParam<HierParams *> hier; - + SimObjectParam<Platform *> platform; + SimObjectParam<SimConsole *> sim_console; + SimObjectParam<System *> system; END_DECLARE_SIM_OBJECT_PARAMS(Uart8250) BEGIN_INIT_SIM_OBJECT_PARAMS(Uart8250) - INIT_PARAM(console, "The console"), - INIT_PARAM(mmu, "Memory Controller"), - INIT_PARAM(platform, "Pointer to platfrom"), - INIT_PARAM(addr, "Device Address"), - INIT_PARAM_DFLT(size, "Device size", 0x8), - INIT_PARAM(pio_bus, ""), - INIT_PARAM_DFLT(pio_latency, "Programmed IO latency in bus cycles", 1), - INIT_PARAM_DFLT(hier, "Hierarchy global variables", &defaultHierParams) + INIT_PARAM(pio_addr, "Device Address"), + INIT_PARAM_DFLT(pio_latency, "Programmed IO latency", 1000), + INIT_PARAM(platform, "platform"), + INIT_PARAM(sim_console, "The Simulator Console"), + INIT_PARAM(system, "system object") END_INIT_SIM_OBJECT_PARAMS(Uart8250) CREATE_SIM_OBJECT(Uart8250) { - return new Uart8250(getInstanceName(), console, mmu, addr, size, hier, - pio_bus, pio_latency, platform); + Uart8250::Params *p = new Uart8250::Params; + p->name = getInstanceName(); + p->pio_addr = pio_addr; + p->pio_delay = pio_latency; + p->platform = platform; + p->cons = sim_console; + p->system = system; + return new Uart8250(p); } REGISTER_SIM_OBJECT("Uart8250", Uart8250) + diff --git a/dev/uart8250.hh b/dev/uart8250.hh index 63d1da3cf..19e4438bc 100644 --- a/dev/uart8250.hh +++ b/dev/uart8250.hh @@ -30,8 +30,8 @@ * Defines a 8250 UART */ -#ifndef __TSUNAMI_UART_HH__ -#define __TSUNAMI_UART_HH__ +#ifndef __DEV_UART8250_HH__ +#define __DEV_UART8250_HH__ #include "dev/tsunamireg.h" #include "base/range.hh" @@ -44,16 +44,15 @@ * bit 2:1 ID of highest priority interrupt * bit 7:3 zeroes */ -#define IIR_NOPEND 0x1 +const uint8_t IIR_NOPEND = 0x1; // Interrupt IDs -#define IIR_MODEM 0x00 /* Modem Status (lowest priority) */ -#define IIR_TXID 0x02 /* Tx Data */ -#define IIR_RXID 0x04 /* Rx Data */ -#define IIR_LINE 0x06 /* Rx Line Status (highest priority)*/ +const uint8_t IIR_MODEM = 0x00; /* Modem Status (lowest priority) */ +const uint8_t IIR_TXID = 0x02; /* Tx Data */ +const uint8_t IIR_RXID = 0x04; /* Rx Data */ +const uint8_t IIR_LINE = 0x06; /* Rx Line Status (highest priority)*/ class SimConsole; -class MemoryController; class Platform; class Uart8250 : public Uart @@ -79,12 +78,11 @@ class Uart8250 : public Uart IntrEvent rxIntrEvent; public: - Uart8250(const std::string &name, SimConsole *c, MemoryController *mmu, - Addr a, Addr s, HierParams *hier, Bus *pio_bus, Tick pio_latency, - Platform *p); + Uart8250(Params *p); - virtual Fault read(MemReqPtr &req, uint8_t *data); - virtual Fault write(MemReqPtr &req, const uint8_t *data); + virtual Tick read(Packet &pkt); + virtual Tick write(Packet &pkt); + virtual void addressRanges(AddrRangeList &range_list); /** diff --git a/kern/linux/events.cc b/kern/linux/events.cc index 9f50eef04..b688e9dd0 100644 --- a/kern/linux/events.cc +++ b/kern/linux/events.cc @@ -46,7 +46,7 @@ DebugPrintkEvent::process(ExecContext *xc) DPRINTFN(""); } - AlphaArguments args(xc); + AlphaISA::AlphaArguments args(xc); Printk(args); SkipFuncEvent::process(xc); } diff --git a/kern/linux/linux.hh b/kern/linux/linux.hh index 0dbccf546..63e0dd5ca 100644 --- a/kern/linux/linux.hh +++ b/kern/linux/linux.hh @@ -44,8 +44,11 @@ class Linux {}; #include <sys/types.h> #include <unistd.h> +#include "arch/isa_traits.hh" #include "sim/syscall_emul.hh" +class TranslatingPort; + /// /// This class encapsulates the types, structures, constants, /// functions, and syscall-number mappings specific to the Alpha Linux @@ -72,33 +75,6 @@ class Linux { typedef struct stat64 hst_stat64; #endif - - //@{ - /// 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_NONBLOCK = 00000004; //!< O_NONBLOCK - static const int TGT_O_APPEND = 00000010; //!< O_APPEND - static const int TGT_O_CREAT = 00001000; //!< O_CREAT - static const int TGT_O_TRUNC = 00002000; //!< O_TRUNC - static const int TGT_O_EXCL = 00004000; //!< O_EXCL - static const int TGT_O_NOCTTY = 00010000; //!< O_NOCTTY - static const int TGT_O_SYNC = 00040000; //!< O_SYNC - static const int TGT_O_DRD = 00100000; //!< O_DRD - static const int TGT_O_DIRECTIO = 00200000; //!< O_DIRECTIO - static const int TGT_O_CACHE = 00400000; //!< O_CACHE - static const int TGT_O_DSYNC = 02000000; //!< O_DSYNC - static const int TGT_O_RSYNC = 04000000; //!< O_RSYNC - //@} - - /// 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; - /// Stat buffer. Note that we can't call it 'stat' since that /// gets #defined to something else on some systems. struct tgt_stat { @@ -156,46 +132,12 @@ class Linux { char machine[_SYS_NMLN]; //!< Machine type. }; - - //@{ - /// ioctl() command codes. - 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 = 0x40127417; - //@} - - /// Resource enumeration for getrlimit(). - enum rlimit_resources { - TGT_RLIMIT_CPU = 0, - TGT_RLIMIT_FSIZE = 1, - TGT_RLIMIT_DATA = 2, - TGT_RLIMIT_STACK = 3, - TGT_RLIMIT_CORE = 4, - TGT_RLIMIT_RSS = 5, - TGT_RLIMIT_NOFILE = 6, - TGT_RLIMIT_AS = 7, - TGT_RLIMIT_VMEM = 7, - TGT_RLIMIT_NPROC = 8, - TGT_RLIMIT_MEMLOCK = 9, - TGT_RLIMIT_LOCKS = 10 - }; - /// Limit struct for getrlimit/setrlimit. struct rlimit { uint64_t rlim_cur; //!< soft limit uint64_t rlim_max; //!< hard limit }; - - /// For mmap(). - static const unsigned TGT_MAP_ANONYMOUS = 0x10; - /// For gettimeofday(). struct timeval { int64_t tv_sec; //!< seconds @@ -208,12 +150,6 @@ class Linux { uint64_t iov_len; }; - //@{ - /// For getrusage(). - static const int TGT_RUSAGE_SELF = 0; - static const int TGT_RUSAGE_CHILDREN = -1; - static const int TGT_RUSAGE_BOTH = -2; - //@} /// For getrusage(). struct rusage { @@ -240,8 +176,10 @@ class Linux { /// memory space. Used by stat(), fstat(), and lstat(). #if !BSD_HOST static void - copyOutStatBuf(FunctionalMemory *mem, Addr addr, hst_stat *host) + copyOutStatBuf(TranslatingPort *mem, Addr addr, hst_stat *host) { + using namespace TheISA; + TypedBufferArg<Linux::tgt_stat> tgt(addr); tgt->st_dev = htog(host->st_dev); @@ -264,8 +202,10 @@ class Linux { // Third version for bsd systems which no longer have any support for // the old stat() call and stat() is actually a stat64() static void - copyOutStatBuf(FunctionalMemory *mem, Addr addr, hst_stat64 *host) + copyOutStatBuf(TranslatingPort *mem, Addr addr, hst_stat64 *host) { + using namespace TheISA; + TypedBufferArg<Linux::tgt_stat> tgt(addr); tgt->st_dev = htog(host->st_dev); @@ -289,8 +229,10 @@ class Linux { // Same for stat64 static void - copyOutStat64Buf(FunctionalMemory *mem, int fd, Addr addr, hst_stat64 *host) + copyOutStat64Buf(TranslatingPort *mem, int fd, Addr addr, hst_stat64 *host) { + using namespace TheISA; + TypedBufferArg<Linux::tgt_stat64> tgt(addr); // fd == 1 checks are because libc does some checks diff --git a/kern/linux/printk.cc b/kern/linux/printk.cc index f5313759b..918b8dabe 100644 --- a/kern/linux/printk.cc +++ b/kern/linux/printk.cc @@ -36,7 +36,7 @@ using namespace std; void -Printk(AlphaArguments args) +Printk(AlphaISA::AlphaArguments args) { char *p = (char *)args++; diff --git a/kern/linux/printk.hh b/kern/linux/printk.hh index 45eab6b88..b88c40f5e 100644 --- a/kern/linux/printk.hh +++ b/kern/linux/printk.hh @@ -29,8 +29,8 @@ #ifndef __PRINTK_HH__ #define __PRINTK_HH__ -class AlphaArguments; +class AlphaISA::AlphaArguments; -void Printk(AlphaArguments args); +void Printk(AlphaISA::AlphaArguments args); #endif // __PRINTK_HH__ diff --git a/kern/system_events.cc b/kern/system_events.cc index 9b9861497..fd5c12e44 100644 --- a/kern/system_events.cc +++ b/kern/system_events.cc @@ -26,8 +26,11 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#include "encumbered/cpu/full/cpu.hh" +#include "cpu/base.hh" +#include "cpu/cpu_exec_context.hh" #include "kern/kernel_stats.hh" +#include "kern/system_events.hh" +#include "sim/system.hh" using namespace TheISA; @@ -41,11 +44,12 @@ SkipFuncEvent::process(ExecContext *xc) xc->setPC(newpc); xc->setNextPC(xc->readPC() + sizeof(TheISA::MachInst)); - +/* BranchPred *bp = xc->getCpuPtr()->getBranchPred(); if (bp != NULL) { bp->popRAS(xc->getThreadNum()); } +*/ } diff --git a/kern/tru64/dump_mbuf.hh b/kern/tru64/dump_mbuf.hh index 0ff5da3d7..9e1698ff1 100644 --- a/kern/tru64/dump_mbuf.hh +++ b/kern/tru64/dump_mbuf.hh @@ -29,10 +29,10 @@ #ifndef __DUMP_MBUF_HH__ #define __DUMP_MBUF_HH__ -class AlphaArguments; +#include "arch/arguments.hh" namespace tru64 { - void DumpMbuf(AlphaArguments args); + void DumpMbuf(AlphaISA::AlphaArguments args); } #endif // __DUMP_MBUF_HH__ diff --git a/kern/tru64/printf.cc b/kern/tru64/printf.cc index 77ac17c3a..319d36673 100644 --- a/kern/tru64/printf.cc +++ b/kern/tru64/printf.cc @@ -40,7 +40,7 @@ using namespace std; namespace tru64 { void -Printf(AlphaArguments args) +Printf(AlphaISA::AlphaArguments args) { char *p = (char *)args++; diff --git a/kern/tru64/printf.hh b/kern/tru64/printf.hh index a48b4482c..61236e83a 100644 --- a/kern/tru64/printf.hh +++ b/kern/tru64/printf.hh @@ -29,10 +29,10 @@ #ifndef __PRINTF_HH__ #define __PRINTF_HH__ -class AlphaArguments; +#include "arch/arguments.hh" namespace tru64 { - void Printf(AlphaArguments args); + void Printf(AlphaISA::AlphaArguments args); } #endif // __PRINTF_HH__ diff --git a/kern/tru64/tru64.hh b/kern/tru64/tru64.hh index 112f00f31..91db5bb84 100644 --- a/kern/tru64/tru64.hh +++ b/kern/tru64/tru64.hh @@ -55,12 +55,12 @@ class Tru64 {}; #include "sim/root.hh" #include "sim/syscall_emul.hh" -using namespace std; - typedef struct stat global_stat; typedef struct statfs global_statfs; typedef struct dirent global_dirent; +class TranslatingPort; + /// /// This class encapsulates the types, structures, constants, /// functions, and syscall-number mappings specific to the Alpha Tru64 @@ -85,32 +85,6 @@ class Tru64 { typedef quad fsid_t; //@} - //@{ - /// open(2) flag values. - static const int TGT_O_RDONLY = 00000000; - static const int TGT_O_WRONLY = 00000001; - static const int TGT_O_RDWR = 00000002; - static const int TGT_O_NONBLOCK = 00000004; - static const int TGT_O_APPEND = 00000010; - static const int TGT_O_CREAT = 00001000; - static const int TGT_O_TRUNC = 00002000; - static const int TGT_O_EXCL = 00004000; - static const int TGT_O_NOCTTY = 00010000; - static const int TGT_O_SYNC = 00040000; - static const int TGT_O_DRD = 00100000; - static const int TGT_O_DIRECTIO = 00200000; - static const int TGT_O_CACHE = 00400000; - static const int TGT_O_DSYNC = 02000000; - static const int TGT_O_RSYNC = 04000000; - //@} - - /// 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; - /// Stat buffer. Note that Tru64 v5.0+ use a new "F64" stat /// structure, and a new set of syscall numbers for stat calls. /// On some hosts (notably Linux) define st_atime, st_mtime, and @@ -246,33 +220,6 @@ class Tru64 { char machine[_SYS_NMLN]; //!< Machine type. }; - //@{ - /// ioctl() command codes. - 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; - // TIOCGETS not defined in tru64, so I made up a number - static const unsigned TIOCGETS = 0x40000000; - static const unsigned TIOCGETA = 0x402c7413; - //@} - - /// Resource enumeration for getrlimit(). - enum rlimit_resources { - TGT_RLIMIT_CPU = 0, - TGT_RLIMIT_FSIZE = 1, - TGT_RLIMIT_DATA = 2, - TGT_RLIMIT_STACK = 3, - TGT_RLIMIT_CORE = 4, - TGT_RLIMIT_RSS = 5, - TGT_RLIMIT_NOFILE = 6, - TGT_RLIMIT_AS = 7, - TGT_RLIMIT_VMEM = 7 - }; - /// Limit struct for getrlimit/setrlimit. struct rlimit { uint64_t rlim_cur; //!< soft limit @@ -280,21 +227,6 @@ class Tru64 { }; - /// For mmap(). - static const unsigned TGT_MAP_ANONYMOUS = 0x10; - - - //@{ - /// For getsysinfo(). - static const unsigned GSI_PLATFORM_NAME = 103; //!< platform name as string - static const unsigned GSI_CPU_INFO = 59; //!< CPU information - static const unsigned GSI_PROC_TYPE = 60; //!< get proc_type - static const unsigned GSI_MAX_CPU = 30; //!< max # cpu's on this machine - static const unsigned GSI_CPUS_IN_BOX = 55; //!< number of CPUs in system - static const unsigned GSI_PHYSMEM = 19; //!< Physical memory in KB - static const unsigned GSI_CLK_TCK = 42; //!< clock freq in Hz - //@} - /// For getsysinfo() GSI_CPU_INFO option. struct cpu_info { uint32_t current_cpu; //!< current_cpu @@ -309,24 +241,12 @@ class Tru64 { uint32_t unused[3]; //!< future expansion }; - //@{ - /// For setsysinfo(). - static const unsigned SSI_IEEE_FP_CONTROL = 14; //!< ieee_set_fp_control() - //@} - /// For gettimeofday. struct timeval { uint32_t tv_sec; //!< seconds uint32_t tv_usec; //!< microseconds }; - //@{ - /// For getrusage(). - static const int TGT_RUSAGE_THREAD = 1; - static const int TGT_RUSAGE_SELF = 0; - static const int TGT_RUSAGE_CHILDREN = -1; - //@} - /// For getrusage(). struct rusage { struct timeval ru_utime; //!< user time used @@ -372,8 +292,6 @@ class Tru64 { }; - /// For table(). - static const int TBL_SYSINFO = 12; /// For table(). struct tbl_sysinfo { @@ -540,8 +458,10 @@ class Tru64 { /// memory space. Used by stat(), fstat(), and lstat(). template <class T> static void - copyOutStatBuf(FunctionalMemory *mem, Addr addr, global_stat *host) + copyOutStatBuf(TranslatingPort *mem, Addr addr, global_stat *host) { + using namespace TheISA; + TypedBufferArg<T> tgt(addr); tgt->st_dev = htog(host->st_dev); @@ -566,8 +486,10 @@ class Tru64 { /// memory space. Used by statfs() and fstatfs(). template <class T> static void - copyOutStatfsBuf(FunctionalMemory *mem, Addr addr, global_statfs *host) + copyOutStatfsBuf(TranslatingPort *mem, Addr addr, global_statfs *host) { + using namespace TheISA; + TypedBufferArg<T> tgt(addr); #if defined(__OpenBSD__) || defined(__APPLE__) || defined(__FreeBSD__) @@ -590,13 +512,13 @@ class Tru64 { class F64 { public: - static void copyOutStatBuf(FunctionalMemory *mem, Addr addr, + static void copyOutStatBuf(TranslatingPort *mem, Addr addr, global_stat *host) { Tru64::copyOutStatBuf<Tru64::F64_stat>(mem, addr, host); } - static void copyOutStatfsBuf(FunctionalMemory *mem, Addr addr, + static void copyOutStatfsBuf(TranslatingPort *mem, Addr addr, global_statfs *host) { Tru64::copyOutStatfsBuf<Tru64::F64_statfs>(mem, addr, host); @@ -605,13 +527,13 @@ class Tru64 { class PreF64 { public: - static void copyOutStatBuf(FunctionalMemory *mem, Addr addr, + static void copyOutStatBuf(TranslatingPort *mem, Addr addr, global_stat *host) { Tru64::copyOutStatBuf<Tru64::pre_F64_stat>(mem, addr, host); } - static void copyOutStatfsBuf(FunctionalMemory *mem, Addr addr, + static void copyOutStatfsBuf(TranslatingPort *mem, Addr addr, global_statfs *host) { Tru64::copyOutStatfsBuf<Tru64::pre_F64_statfs>(mem, addr, host); @@ -623,8 +545,10 @@ class Tru64 { /// the simulated memory space. Used by pre_F64_stat(), /// pre_F64_fstat(), and pre_F64_lstat(). static void - copyOutPreF64StatBuf(FunctionalMemory *mem, Addr addr, struct stat *host) + copyOutPreF64StatBuf(TranslatingPort *mem, Addr addr, struct stat *host) { + using namespace TheISA; + TypedBufferArg<Tru64::pre_F64_stat> tgt(addr); tgt->st_dev = htog(host->st_dev); @@ -654,6 +578,8 @@ class Tru64 { getdirentriesFunc(SyscallDesc *desc, int callnum, Process *process, ExecContext *xc) { + using namespace TheISA; + #ifdef __CYGWIN__ panic("getdirent not implemented on cygwin!"); #else @@ -666,7 +592,7 @@ class Tru64 { // just pass basep through uninterpreted. TypedBufferArg<int64_t> basep(tgt_basep); - basep.copyIn(xc->getMemPtr()); + basep.copyIn(xc->getMemPort()); long host_basep = (off_t)htog((int64_t)*basep); int host_result = getdirentries(fd, host_buf, tgt_nbytes, &host_basep); @@ -693,7 +619,7 @@ class Tru64 { tgt_dp->d_reclen = tgt_bufsize; tgt_dp->d_namlen = namelen; strcpy(tgt_dp->d_name, host_dp->d_name); - tgt_dp.copyOut(xc->getMemPtr()); + tgt_dp.copyOut(xc->getMemPort()); tgt_buf_ptr += tgt_bufsize; host_buf_ptr += host_dp->d_reclen; @@ -702,7 +628,7 @@ class Tru64 { delete [] host_buf; *basep = htog((int64_t)host_basep); - basep.copyOut(xc->getMemPtr()); + basep.copyOut(xc->getMemPort()); return tgt_buf_ptr - tgt_buf; #endif @@ -713,10 +639,12 @@ class Tru64 { sigreturnFunc(SyscallDesc *desc, int callnum, Process *process, ExecContext *xc) { + using namespace TheISA; + using TheISA::RegFile; TypedBufferArg<Tru64::sigcontext> sc(xc->getSyscallArg(0)); - sc.copyIn(xc->getMemPtr()); + sc.copyIn(xc->getMemPort()); // Restore state from sigcontext structure. // Note that we'll advance PC <- NPC before the end of the cycle, @@ -726,7 +654,7 @@ class Tru64 { for (int i = 0; i < 31; ++i) { xc->setIntReg(i, htog(sc->sc_regs[i])); - xc->setFloatRegInt(i, htog(sc->sc_fpregs[i])); + xc->setFloatRegBits(i, htog(sc->sc_fpregs[i])); } xc->setMiscReg(TheISA::Fpcr_DepTag, htog(sc->sc_fpcr)); @@ -734,42 +662,6 @@ class Tru64 { return 0; } - /// Target table() handler. - static SyscallReturn - tableFunc(SyscallDesc *desc, int callnum, Process *process, - ExecContext *xc) - { - int id = xc->getSyscallArg(0); // table ID - int index = xc->getSyscallArg(1); // index into table - // arg 2 is buffer pointer; type depends on table ID - int nel = xc->getSyscallArg(3); // number of elements - int lel = xc->getSyscallArg(4); // expected element size - - switch (id) { - case Tru64::TBL_SYSINFO: { - if (index != 0 || nel != 1 || lel != sizeof(Tru64::tbl_sysinfo)) - return -EINVAL; - TypedBufferArg<Tru64::tbl_sysinfo> elp(xc->getSyscallArg(2)); - - const int clk_hz = one_million; - elp->si_user = htog(curTick / (Clock::Frequency / clk_hz)); - elp->si_nice = htog(0); - elp->si_sys = htog(0); - elp->si_idle = htog(0); - elp->wait = htog(0); - elp->si_hz = htog(clk_hz); - elp->si_phz = htog(clk_hz); - elp->si_boottime = htog(seconds_since_epoch); // seconds since epoch? - elp->si_max_procs = htog(process->numCpus()); - elp.copyOut(xc->getMemPtr()); - return 0; - } - - default: - cerr << "table(): id " << id << " unknown." << endl; - return -EINVAL; - } - } // // Mach syscalls -- identified by negated syscall numbers @@ -780,9 +672,11 @@ class Tru64 { stack_createFunc(SyscallDesc *desc, int callnum, Process *process, ExecContext *xc) { + using namespace TheISA; + TypedBufferArg<Tru64::vm_stack> argp(xc->getSyscallArg(0)); - argp.copyIn(xc->getMemPtr()); + argp.copyIn(xc->getMemPort()); // if the user chose an address, just let them have it. Otherwise // pick one for them. @@ -791,7 +685,7 @@ class Tru64 { int stack_size = (htog(argp->rsize) + htog(argp->ysize) + htog(argp->gsize)); process->next_thread_stack_base -= stack_size; - argp.copyOut(xc->getMemPtr()); + argp.copyOut(xc->getMemPort()); } return 0; @@ -808,10 +702,13 @@ class Tru64 { nxm_task_initFunc(SyscallDesc *desc, int callnum, Process *process, ExecContext *xc) { + using namespace std; + using namespace TheISA; + TypedBufferArg<Tru64::nxm_task_attr> attrp(xc->getSyscallArg(0)); TypedBufferArg<Addr> configptr_ptr(xc->getSyscallArg(1)); - attrp.copyIn(xc->getMemPtr()); + attrp.copyIn(xc->getMemPort()); if (gtoh(attrp->nxm_version) != NXM_LIB_VERSION) { cerr << "nxm_task_init: thread library version mismatch! " @@ -852,7 +749,7 @@ class Tru64 { config->nxm_slot_state = htog(slot_state_addr); config->nxm_rad[0] = htog(rad_state_addr); - config.copyOut(xc->getMemPtr()); + config.copyOut(xc->getMemPort()); // initialize the slot_state array and copy it out TypedBufferArg<Tru64::nxm_slot_state_t> slot_state(slot_state_addr, @@ -865,7 +762,7 @@ class Tru64 { (i == 0) ? Tru64::NXM_SLOT_BOUND : Tru64::NXM_SLOT_AVAIL; } - slot_state.copyOut(xc->getMemPtr()); + slot_state.copyOut(xc->getMemPort()); // same for the per-RAD "shared" struct. Note that we need to // allocate extra bytes for the per-VP array which is embedded at @@ -899,13 +796,13 @@ class Tru64 { } } - rad_state.copyOut(xc->getMemPtr()); + rad_state.copyOut(xc->getMemPort()); // // copy pointer to shared config area out to user // *configptr_ptr = htog(config_addr); - configptr_ptr.copyOut(xc->getMemPtr()); + configptr_ptr.copyOut(xc->getMemPort()); // Register this as a valid address range with the process process->nxm_start = base_addr; @@ -919,6 +816,8 @@ class Tru64 { init_exec_context(ExecContext *ec, Tru64::nxm_thread_attr *attrp, uint64_t uniq_val) { + using namespace TheISA; + ec->clearArchRegs(); ec->setIntReg(TheISA::ArgumentReg0, gtoh(attrp->registers.a0)); @@ -937,12 +836,15 @@ class Tru64 { nxm_thread_createFunc(SyscallDesc *desc, int callnum, Process *process, ExecContext *xc) { + using namespace std; + using namespace TheISA; + TypedBufferArg<Tru64::nxm_thread_attr> attrp(xc->getSyscallArg(0)); TypedBufferArg<uint64_t> kidp(xc->getSyscallArg(1)); int thread_index = xc->getSyscallArg(2); // get attribute args - attrp.copyIn(xc->getMemPtr()); + attrp.copyIn(xc->getMemPort()); if (gtoh(attrp->version) != NXM_LIB_VERSION) { cerr << "nxm_thread_create: thread library version mismatch! " @@ -967,7 +869,7 @@ class Tru64 { TypedBufferArg<Tru64::nxm_shared> rad_state(0x14000, rad_state_size); - rad_state.copyIn(xc->getMemPtr()); + rad_state.copyIn(xc->getMemPort()); uint64_t uniq_val = gtoh(attrp->pthid) - gtoh(rad_state->nxm_uniq_offset); @@ -978,7 +880,7 @@ class Tru64 { // This is supposed to be a port number. Make something up. *kidp = htog(99); - kidp.copyOut(xc->getMemPtr()); + kidp.copyOut(xc->getMemPort()); return 0; } else if (gtoh(attrp->type) == Tru64::NXM_TYPE_VP) { @@ -992,7 +894,7 @@ class Tru64 { ssp->nxm_u.pth_id = attrp->pthid; ssp->nxm_u.nxm_active = htog(uniq_val | 1); - rad_state.copyOut(xc->getMemPtr()); + rad_state.copyOut(xc->getMemPort()); Addr slot_state_addr = 0x12000 + sizeof(Tru64::nxm_config_info); int slot_state_size = @@ -1002,7 +904,7 @@ class Tru64 { slot_state(slot_state_addr, slot_state_size); - slot_state.copyIn(xc->getMemPtr()); + slot_state.copyIn(xc->getMemPort()); if (slot_state[thread_index] != Tru64::NXM_SLOT_AVAIL) { cerr << "nxm_thread_createFunc: requested VP slot " @@ -1014,7 +916,7 @@ class Tru64 { // doesn't work anyway slot_state[thread_index] = Tru64::NXM_SLOT_BOUND; - slot_state.copyOut(xc->getMemPtr()); + slot_state.copyOut(xc->getMemPort()); // Find a free simulator execution context. for (int i = 0; i < process->numCpus(); ++i) { @@ -1028,7 +930,7 @@ class Tru64 { // and get away with just sticking the thread index // here. *kidp = htog(thread_index); - kidp.copyOut(xc->getMemPtr()); + kidp.copyOut(xc->getMemPort()); return 0; } @@ -1059,6 +961,8 @@ class Tru64 { nxm_thread_blockFunc(SyscallDesc *desc, int callnum, Process *process, ExecContext *xc) { + using namespace std; + uint64_t tid = xc->getSyscallArg(0); uint64_t secs = xc->getSyscallArg(1); uint64_t flags = xc->getSyscallArg(2); @@ -1076,6 +980,8 @@ class Tru64 { nxm_blockFunc(SyscallDesc *desc, int callnum, Process *process, ExecContext *xc) { + using namespace std; + Addr uaddr = xc->getSyscallArg(0); uint64_t val = xc->getSyscallArg(1); uint64_t secs = xc->getSyscallArg(2); @@ -1097,6 +1003,8 @@ class Tru64 { nxm_unblockFunc(SyscallDesc *desc, int callnum, Process *process, ExecContext *xc) { + using namespace std; + Addr uaddr = xc->getSyscallArg(0); cout << xc->getCpuPtr()->name() << ": nxm_unblock " @@ -1127,6 +1035,8 @@ class Tru64 { activate_waiting_context(Addr uaddr, Process *process, bool activate_all = false) { + using namespace std; + int num_activated = 0; list<Process::WaitRec>::iterator i = process->waitList.begin(); @@ -1155,14 +1065,16 @@ class Tru64 { static void m5_lock_mutex(Addr uaddr, Process *process, ExecContext *xc) { + using namespace TheISA; + TypedBufferArg<uint64_t> lockp(uaddr); - lockp.copyIn(xc->getMemPtr()); + lockp.copyIn(xc->getMemPort()); if (gtoh(*lockp) == 0) { // lock is free: grab it *lockp = htog(1); - lockp.copyOut(xc->getMemPtr()); + lockp.copyOut(xc->getMemPort()); } else { // lock is busy: disable until free process->waitList.push_back(Process::WaitRec(uaddr, xc)); @@ -1176,7 +1088,7 @@ class Tru64 { { TypedBufferArg<uint64_t> lockp(uaddr); - lockp.copyIn(xc->getMemPtr()); + lockp.copyIn(xc->getMemPort()); assert(*lockp != 0); // Check for a process waiting on the lock. @@ -1185,7 +1097,7 @@ class Tru64 { // clear lock field if no waiting context is taking over the lock if (num_waiting == 0) { *lockp = 0; - lockp.copyOut(xc->getMemPtr()); + lockp.copyOut(xc->getMemPort()); } } @@ -1209,15 +1121,17 @@ class Tru64 { m5_mutex_trylockFunc(SyscallDesc *desc, int callnum, Process *process, ExecContext *xc) { + using namespace TheISA; + Addr uaddr = xc->getSyscallArg(0); TypedBufferArg<uint64_t> lockp(uaddr); - lockp.copyIn(xc->getMemPtr()); + lockp.copyIn(xc->getMemPort()); if (gtoh(*lockp) == 0) { // lock is free: grab it *lockp = htog(1); - lockp.copyOut(xc->getMemPtr()); + lockp.copyOut(xc->getMemPort()); return 0; } else { return 1; @@ -1266,13 +1180,15 @@ class Tru64 { m5_cond_waitFunc(SyscallDesc *desc, int callnum, Process *process, ExecContext *xc) { + using namespace TheISA; + Addr cond_addr = xc->getSyscallArg(0); Addr lock_addr = xc->getSyscallArg(1); TypedBufferArg<uint64_t> condp(cond_addr); TypedBufferArg<uint64_t> lockp(lock_addr); // user is supposed to acquire lock before entering - lockp.copyIn(xc->getMemPtr()); + lockp.copyIn(xc->getMemPort()); assert(gtoh(*lockp) != 0); m5_unlock_mutex(lock_addr, process, xc); diff --git a/kern/tru64/tru64_events.cc b/kern/tru64/tru64_events.cc index 8f2be6d9b..69fc5c55d 100644 --- a/kern/tru64/tru64_events.cc +++ b/kern/tru64/tru64_events.cc @@ -32,7 +32,7 @@ #include "kern/tru64/tru64_events.hh" #include "kern/tru64/dump_mbuf.hh" #include "kern/tru64/printf.hh" -#include "mem/functional/memory_control.hh" +#include "arch/alpha/ev5.hh" #include "arch/arguments.hh" #include "arch/isa_traits.hh" #include "sim/system.hh" @@ -50,9 +50,19 @@ BadAddrEvent::process(ExecContext *xc) uint64_t a0 = xc->readIntReg(ArgumentReg0); - if (!TheISA::IsK0Seg(a0) || - xc->getSystemPtr()->memctrl->badaddr( - TheISA::K0Seg2Phys(a0) & EV5::PAddrImplMask)) { + AddrRangeList resp; + AddrRangeList snoop; + AddrRangeIter iter; + bool found = false; + + xc->getPhysPort()->getPeerAddressRanges(resp, snoop); + for(iter = resp.begin(); iter != resp.end(); iter++) + { + if (*iter == (TheISA::K0Seg2Phys(a0) & EV5::PAddrImplMask)) + found = true; + } + + if (!TheISA::IsK0Seg(a0) || found ) { DPRINTF(BADADDR, "badaddr arg=%#x bad\n", a0); xc->setIntReg(ReturnValueReg, 0x1); diff --git a/mem/bridge.cc b/mem/bridge.cc new file mode 100644 index 000000000..d358ef77b --- /dev/null +++ b/mem/bridge.cc @@ -0,0 +1,263 @@ + +/* + * Copyright (c) 2006 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * @file Definition of a simple bus bridge without buffering. + */ + + +#include "base/trace.hh" +#include "mem/bridge.hh" +#include "sim/builder.hh" + +void +Bridge::init() +{ + // Make sure that both sides are connected to. + if (sideA == NULL || sideB == NULL) + panic("Both ports of bus bridge are not connected to a bus.\n"); +} + + +/** Function called by the port when the bus is recieving a Timing + * transaction.*/ +bool +Bridge::recvTiming(Packet &pkt, Side id) +{ + if (blockedA && id == SideA) + return false; + if (blockedB && id == SideB) + return false; + + if (delay) { + if (!sendEvent.scheduled()) + sendEvent.schedule(curTick + delay); + if (id == SideA) { + inboundA.push_back(std::make_pair<Packet*, Tick>(&pkt, curTick)); + blockCheck(SideA); + } else { + inboundB.push_back(std::make_pair<Packet*, Tick>(&pkt, curTick)); + blockCheck(SideB); + } + } else { + if (id == SideB) { + sideA->sendPkt(pkt); + blockCheck(SideB); + } else { + sideB->sendPkt(pkt); + blockCheck(SideA); + } + } + return true; + +} + +void +Bridge::blockCheck(Side id) +{ + /* Check that we still have buffer space available. */ + if (id == SideB) { + if (sideA->numQueued() + inboundB.size() >= queueSizeA && !blockedB) { + sideB->sendStatusChange(Port::Blocked); + blockedB = true; + } else if (sideA->numQueued() + inboundB.size() < queueSizeA && blockedB) { + sideB->sendStatusChange(Port::Unblocked); + blockedB = false; + } + } else { + if (sideB->numQueued() + inboundA.size() >= queueSizeB && !blockedA) { + sideA->sendStatusChange(Port::Blocked); + blockedA = true; + } else if (sideB->numQueued() + inboundA.size() < queueSizeB && blockedA) { + sideA->sendStatusChange(Port::Unblocked); + blockedA = false; + } + } +} + +void Bridge::timerEvent() +{ + Tick t = 0; + + assert(inboundA.size() || inboundB.size()); + if (inboundA.size()) { + while (inboundA.front().second <= curTick + delay){ + sideB->sendPkt(inboundA.front()); + inboundA.pop_front(); + } + if (inboundA.size()) + t = inboundA.front().second + delay; + } + if (inboundB.size()) { + while (inboundB.front().second <= curTick + delay){ + sideB->sendPkt(inboundA.front()); + inboundB.pop_front(); + } + if (inboundB.size()) + if (t == 0) + t = inboundB.front().second + delay; + else + t = std::min(t,inboundB.front().second + delay); + } else { + panic("timerEvent() called but nothing to do?"); + } + + if (t != 0) + sendEvent.schedule(t); +} + + +void +Bridge::BridgePort::sendPkt(Packet &pkt) +{ + if (!sendTiming(pkt)) + outbound.push_back(std::make_pair<Packet*,Tick>(&pkt, curTick)); +} + +void +Bridge::BridgePort::sendPkt(std::pair<Packet*, Tick> p) +{ + if (!sendTiming(*p.first)) + outbound.push_back(p); +} + + +Packet * +Bridge::BridgePort::recvRetry() +{ + Packet *pkt; + assert(outbound.size() > 0); + assert(outbound.front().second >= curTick + bridge->delay); + pkt = outbound.front().first; + outbound.pop_front(); + bridge->blockCheck(side); + return pkt; +} + +/** Function called by the port when the bus is recieving a Atomic + * transaction.*/ +Tick +Bridge::recvAtomic(Packet &pkt, Side id) +{ + pkt.time += delay; + + if (id == SideA) + return sideB->sendAtomic(pkt); + else + return sideA->sendAtomic(pkt); +} + +/** Function called by the port when the bus is recieving a Functional + * transaction.*/ +void +Bridge::recvFunctional(Packet &pkt, Side id) +{ + pkt.time += delay; + std::list<std::pair<Packet*, Tick> >::iterator i; + bool pktContinue = true; + + for(i = inboundA.begin(); i != inboundA.end(); ++i) { + if (pkt.intersect(i->first)) { + pktContinue &= fixPacket(pkt, *i->first); + } + } + + for(i = inboundB.begin(); i != inboundB.end(); ++i) { + if (pkt.intersect(i->first)) { + pktContinue &= fixPacket(pkt, *i->first); + } + } + + for(i = sideA->outbound.begin(); i != sideA->outbound.end(); ++i) { + if (pkt.intersect(i->first)) { + pktContinue &= fixPacket(pkt, *i->first); + } + } + + for(i = sideB->outbound.begin(); i != sideB->outbound.end(); ++i) { + if (pkt.intersect(i->first)) { + pktContinue &= fixPacket(pkt, *i->first); + } + } + + if (pktContinue) { + if (id == SideA) + sideB->sendFunctional(pkt); + else + sideA->sendFunctional(pkt); + } +} + +/** Function called by the port when the bus is recieving a status change.*/ +void +Bridge::recvStatusChange(Port::Status status, Side id) +{ + if (status == Port::Blocked || status == Port::Unblocked) + return ; + + if (id == SideA) + sideB->sendStatusChange(status); + else + sideA->sendStatusChange(status); +} + +void +Bridge::addressRanges(AddrRangeList &resp, AddrRangeList &snoop, Side id) +{ + if (id == SideA) + sideB->getPeerAddressRanges(resp, snoop); + else + sideA->getPeerAddressRanges(resp, snoop); +} + +BEGIN_DECLARE_SIM_OBJECT_PARAMS(Bridge) + + Param<int> queue_size_a; + Param<int> queue_size_b; + Param<Tick> delay; + Param<bool> write_ack; + +END_DECLARE_SIM_OBJECT_PARAMS(Bridge) + +BEGIN_INIT_SIM_OBJECT_PARAMS(Bridge) + + INIT_PARAM(queue_size_a, "The size of the queue for data coming into side a"), + INIT_PARAM(queue_size_b, "The size of the queue for data coming into side b"), + INIT_PARAM(delay, "The miminum delay to cross this bridge"), + INIT_PARAM(write_ack, "Acknowledge any writes that are received.") + +END_INIT_SIM_OBJECT_PARAMS(Bridge) + +CREATE_SIM_OBJECT(Bridge) +{ + return new Bridge(getInstanceName(), queue_size_a, queue_size_b, delay, + write_ack); +} + +REGISTER_SIM_OBJECT("Bridge", Bridge) diff --git a/mem/bridge.hh b/mem/bridge.hh new file mode 100644 index 000000000..6bd4d81ab --- /dev/null +++ b/mem/bridge.hh @@ -0,0 +1,214 @@ +/* + * Copyright (c) 2006 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * @file Decleration of a simple bus bridge object with no buffering + */ + +#ifndef __MEM_BRIDGE_HH__ +#define __MEM_BRIDGE_HH__ + +#include <string> +#include <list> +#include <inttypes.h> +#include <queue> + + +#include "mem/mem_object.hh" +#include "mem/packet.hh" +#include "mem/port.hh" +#include "sim/eventq.hh" + +class Bridge : public MemObject +{ + public: + enum Side + { + SideA, + SideB + }; + + protected: + /** Function called by the port when the bus is recieving a Timing + transaction.*/ + bool recvTiming(Packet &pkt, Side id); + + /** Function called by the port when the bus is recieving a Atomic + transaction.*/ + Tick recvAtomic(Packet &pkt, Side id); + + /** Function called by the port when the bus is recieving a Functional + transaction.*/ + void recvFunctional(Packet &pkt, Side id); + + /** Function called by the port when the bus is recieving a status change.*/ + void recvStatusChange(Port::Status status, Side id); + + /** Process address range request. + * @param resp addresses that we can respond to + * @param snoop addresses that we would like to snoop + * @param id ide of the busport that made the request. + */ + void addressRanges(AddrRangeList &resp, AddrRangeList &snoop, Side id); + + + /** Event that the SendEvent calls when it fires. This code must reschedule + * the send event as required. */ + void timerEvent(); + + /** Decleration of the buses port type, one will be instantiated for each + of the interfaces connecting to the bus. */ + class BridgePort : public Port + { + /** A pointer to the bus to which this port belongs. */ + Bridge *bridge; + + /** A id to keep track of the intercafe ID this port is connected to. */ + Bridge::Side side; + + public: + + /** Constructor for the BusPort.*/ + BridgePort(Bridge *_bridge, Side _side) + : bridge(_bridge), side(_side) + { } + + int numQueued() { return outbound.size(); } + + protected: + /** Data this is waiting to be transmitted. */ + std::list<std::pair<Packet*, Tick> > outbound; + + void sendPkt(Packet &pkt); + void sendPkt(std::pair<Packet*, Tick> p); + + /** When reciving a timing request from the peer port, + pass it to the bridge. */ + virtual bool recvTiming(Packet &pkt) + { return bridge->recvTiming(pkt, side); } + + /** When reciving a retry request from the peer port, + pass it to the bridge. */ + virtual Packet* recvRetry(); + + /** When reciving a Atomic requestfrom the peer port, + pass it to the bridge. */ + virtual Tick recvAtomic(Packet &pkt) + { return bridge->recvAtomic(pkt, side); } + + /** When reciving a Functional request from the peer port, + pass it to the bridge. */ + virtual void recvFunctional(Packet &pkt) + { bridge->recvFunctional(pkt, side); } + + /** When reciving a status changefrom the peer port, + pass it to the bridge. */ + virtual void recvStatusChange(Status status) + { bridge->recvStatusChange(status, side); } + + /** When reciving a address range request the peer port, + pass it to the bridge. */ + virtual void getDeviceAddressRanges(AddrRangeList &resp, AddrRangeList &snoop) + { bridge->addressRanges(resp, snoop, side); } + + friend class Bridge; + }; + + class SendEvent : public Event + { + Bridge *bridge; + + SendEvent(Bridge *b) + : Event(&mainEventQueue), bridge(b) {} + + virtual void process() { bridge->timerEvent(); } + + virtual const char *description() { return "bridge delay event"; } + friend class Bridge; + }; + + SendEvent sendEvent; + + /** Sides of the bus bridges. */ + BridgePort* sideA; + BridgePort* sideB; + + /** inbound queues on both sides. */ + std::list<std::pair<Packet*, Tick> > inboundA; + std::list<std::pair<Packet*, Tick> > inboundB; + + /** The size of the queue for data coming into side a */ + int queueSizeA; + int queueSizeB; + + /* if the side is blocked or not. */ + bool blockedA; + bool blockedB; + + /** Miminum delay though this bridge. */ + Tick delay; + + /** If this bridge should acknowledge writes. */ + bool ackWrites; + + public: + + /** A function used to return the port associated with this bus object. */ + virtual Port *getPort(const std::string &if_name) + { + if (if_name == "side_a") { + if (sideA != NULL) + panic("bridge side a already connected to."); + sideA = new BridgePort(this, SideA); + return sideA; + } else if (if_name == "side_b") { + if (sideB != NULL) + panic("bridge side b already connected to."); + sideB = new BridgePort(this, SideB); + return sideB; + } else + return NULL; + } + + virtual void init(); + + Bridge(const std::string &n, int qsa, int qsb, Tick _delay, int write_ack) + : MemObject(n), sendEvent(this), sideA(NULL), sideB(NULL), + queueSizeA(qsa), queueSizeB(qsb), blockedA(false), blockedB(false), + delay(_delay), ackWrites(write_ack) + {} + + /** Check if the port should block/unblock after recieving/sending a packet. + * */ + void blockCheck(Side id); + + friend class Bridge::SendEvent; + +}; + +#endif //__MEM_BUS_HH__ diff --git a/mem/bus.cc b/mem/bus.cc new file mode 100644 index 000000000..acc941434 --- /dev/null +++ b/mem/bus.cc @@ -0,0 +1,179 @@ +/* + * Copyright (c) 2006 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * @file Definition of a bus object. + */ + + +#include "base/trace.hh" +#include "mem/bus.hh" +#include "sim/builder.hh" + +/** Get the ranges of anyone that we are connected to. */ +void +Bus::init() +{ + std::vector<Port*>::iterator intIter; + for (intIter = interfaces.begin(); intIter != interfaces.end(); intIter++) + (*intIter)->sendStatusChange(Port::RangeChange); +} + + +/** Function called by the port when the bus is recieving a Timing + * transaction.*/ +bool +Bus::recvTiming(Packet &pkt, int id) +{ + return findPort(pkt.addr, id)->sendTiming(pkt); +} + +Port * +Bus::findPort(Addr addr, int id) +{ + /* An interval tree would be a better way to do this. --ali. */ + int dest_id = -1; + int i = 0; + bool found = false; + + while (i < portList.size() && !found) + { + if (portList[i].range == addr) { + dest_id = portList[i].portId; + found = true; + DPRINTF(Bus, "Found Addr: %llx on device %d\n", addr, dest_id); + } + i++; + } + if (dest_id == -1) + panic("Unable to find destination for addr: %llx", addr); + + // we shouldn't be sending this back to where it came from + assert(dest_id != id); + + return interfaces[dest_id]; +} + +/** Function called by the port when the bus is recieving a Atomic + * transaction.*/ +Tick +Bus::recvAtomic(Packet &pkt, int id) +{ + return findPort(pkt.addr, id)->sendAtomic(pkt); +} + +/** Function called by the port when the bus is recieving a Functional + * transaction.*/ +void +Bus::recvFunctional(Packet &pkt, int id) +{ + findPort(pkt.addr, id)->sendFunctional(pkt); +} + +/** Function called by the port when the bus is recieving a status change.*/ +void +Bus::recvStatusChange(Port::Status status, int id) +{ + DPRINTF(Bus, "Bus %d recieved status change from device id %d\n", + busId, id); + assert(status == Port::RangeChange && + "The other statuses need to be implemented."); + + assert(id < interfaces.size() && id >= 0); + int x; + Port *port = interfaces[id]; + AddrRangeList ranges; + AddrRangeList snoops; + AddrRangeIter iter; + std::vector<DevMap>::iterator portIter; + + // Clean out any previously existent ids + for (portIter = portList.begin(); portIter != portList.end(); ) { + if (portIter->portId == id) + portIter = portList.erase(portIter); + else + portIter++; + } + + port->getPeerAddressRanges(ranges, snoops); + + // not dealing with snooping yet either + assert(snoops.size() == 0); + for(iter = ranges.begin(); iter != ranges.end(); iter++) { + DevMap dm; + dm.portId = id; + dm.range = *iter; + + DPRINTF(MMU, "Adding range %llx - %llx for id %d\n", dm.range.start, + dm.range.end, id); + portList.push_back(dm); + } + DPRINTF(MMU, "port list has %d entries\n", portList.size()); + + // tell all our peers that our address range has changed. + // Don't tell the device that caused this change, it already knows + for (x = 0; x < interfaces.size(); x++) + if (x != id) + interfaces[x]->sendStatusChange(Port::RangeChange); +} + +void +Bus::addressRanges(AddrRangeList &resp, AddrRangeList &snoop, int id) +{ + std::vector<DevMap>::iterator portIter; + + resp.clear(); + snoop.clear(); + + DPRINTF(Bus, "Bus id %d recieved address range request returning\n", + busId); + for (portIter = portList.begin(); portIter != portList.end(); portIter++) { + if (portIter->portId != id) { + resp.push_back(portIter->range); + DPRINTF(Bus, "-- %#llX : %#llX\n", portIter->range.start, + portIter->range.end); + } + } +} + +BEGIN_DECLARE_SIM_OBJECT_PARAMS(Bus) + + Param<int> bus_id; + +END_DECLARE_SIM_OBJECT_PARAMS(Bus) + +BEGIN_INIT_SIM_OBJECT_PARAMS(Bus) + INIT_PARAM(bus_id, "a globally unique bus id") +END_INIT_SIM_OBJECT_PARAMS(Bus) + +CREATE_SIM_OBJECT(Bus) +{ + return new Bus(getInstanceName(), bus_id); +} + +REGISTER_SIM_OBJECT("Bus", Bus) diff --git a/mem/bus.hh b/mem/bus.hh new file mode 100644 index 000000000..de9259a90 --- /dev/null +++ b/mem/bus.hh @@ -0,0 +1,164 @@ +/* + * Copyright (c) 2002-2005 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * @file Decleration of a bus object. + */ + +#ifndef __MEM_BUS_HH__ +#define __MEM_BUS_HH__ + +#include <string> +#include <list> +#include <inttypes.h> + +#include "base/range.hh" +#include "mem/mem_object.hh" +#include "mem/packet.hh" +#include "mem/port.hh" +#include "mem/request.hh" + +class Bus : public MemObject +{ + /** a globally unique id for this bus. */ + int busId; + + struct DevMap { + int portId; + Range<Addr> range; + }; + std::vector<DevMap> portList; + + + /** Function called by the port when the bus is recieving a Timing + transaction.*/ + bool recvTiming(Packet &pkt, int id); + + /** Function called by the port when the bus is recieving a Atomic + transaction.*/ + Tick recvAtomic(Packet &pkt, int id); + + /** Function called by the port when the bus is recieving a Functional + transaction.*/ + void recvFunctional(Packet &pkt, int id); + + /** Function called by the port when the bus is recieving a status change.*/ + void recvStatusChange(Port::Status status, int id); + + /** Find which port connected to this bus (if any) should be given a packet + * with this address. + * @param addr Address to find port for. + * @param id Id of the port this packet was received from (to prevent + * loops) + * @return pointer to port that the packet should be sent out of. + */ + Port * + Bus::findPort(Addr addr, int id); + + /** Process address range request. + * @param resp addresses that we can respond to + * @param snoop addresses that we would like to snoop + * @param id ide of the busport that made the request. + */ + void addressRanges(AddrRangeList &resp, AddrRangeList &snoop, int id); + + + /** Decleration of the buses port type, one will be instantiated for each + of the interfaces connecting to the bus. */ + class BusPort : public Port + { + /** A pointer to the bus to which this port belongs. */ + Bus *bus; + + /** A id to keep track of the intercafe ID this port is connected to. */ + int id; + + public: + + /** Constructor for the BusPort.*/ + BusPort(Bus *_bus, int _id) + : bus(_bus), id(_id) + { } + + protected: + + /** When reciving a timing request from the peer port (at id), + pass it to the bus. */ + virtual bool recvTiming(Packet &pkt) + { return bus->recvTiming(pkt, id); } + + /** When reciving a Atomic requestfrom the peer port (at id), + pass it to the bus. */ + virtual Tick recvAtomic(Packet &pkt) + { return bus->recvAtomic(pkt, id); } + + /** When reciving a Functional requestfrom the peer port (at id), + pass it to the bus. */ + virtual void recvFunctional(Packet &pkt) + { bus->recvFunctional(pkt, id); } + + /** When reciving a status changefrom the peer port (at id), + pass it to the bus. */ + virtual void recvStatusChange(Status status) + { bus->recvStatusChange(status, id); } + + // This should return all the 'owned' addresses that are + // downstream from this bus, yes? That is, the union of all + // the 'owned' address ranges of all the other interfaces on + // this bus... + virtual void getDeviceAddressRanges(AddrRangeList &resp, AddrRangeList &snoop) + { bus->addressRanges(resp, snoop, id); } + + // Hack to make translating port work without changes + virtual int deviceBlockSize() { return 32; } + + }; + + /** An array of pointers to the peer port interfaces + connected to this bus.*/ + std::vector<Port*> interfaces; + + public: + + /** A function used to return the port associated with this bus object. */ + virtual Port *getPort(const std::string &if_name) + { + // if_name ignored? forced to be empty? + int id = interfaces.size(); + interfaces.push_back(new BusPort(this, id)); + return interfaces.back(); + } + + virtual void init(); + + Bus(const std::string &n, int bus_id) + : MemObject(n), busId(bus_id) {} + +}; + +#endif //__MEM_BUS_HH__ diff --git a/mem/mem_object.cc b/mem/mem_object.cc new file mode 100644 index 000000000..f579a0727 --- /dev/null +++ b/mem/mem_object.cc @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2002-2005 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "mem/mem_object.hh" +#include "sim/param.hh" + +MemObject::MemObject(const std::string &name) + : SimObject(name) +{ +} + +DEFINE_SIM_OBJECT_CLASS_NAME("MemObject", MemObject) diff --git a/mem/mem_object.hh b/mem/mem_object.hh new file mode 100644 index 000000000..58930eccc --- /dev/null +++ b/mem/mem_object.hh @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2002-2005 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * @file + * Base Memory Object decleration. + */ + +#ifndef __MEM_MEM_OBJECT_HH__ +#define __MEM_MEM_OBJECT_HH__ + +#include "sim/sim_object.hh" +#include "mem/port.hh" + +/** + * The base MemoryObject class, allows for an accesor function to a + * simobj that returns the Port. + */ +class MemObject : public SimObject +{ + public: + MemObject(const std::string &name); + + public: + /** Additional function to return the Port of a memory object. */ + virtual Port *getPort(const std::string &if_name) = 0; +}; + +#endif //__MEM_MEM_OBJECT_HH__ diff --git a/mem/packet.cc b/mem/packet.cc new file mode 100644 index 000000000..ecd2a7be1 --- /dev/null +++ b/mem/packet.cc @@ -0,0 +1,94 @@ +/* + * Copyright (c) 2006 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * @file + * Definition of the Packet Class, a packet is a transaction occuring + * between a single level of the memory heirarchy (ie L1->L2). + */ +#include "base/misc.hh" +#include "mem/packet.hh" + + +/** delete the data pointed to in the data pointer. Ok to call to matter how + * data was allocted. */ +void +Packet::deleteData() { + assert(staticData || dynamicData); + if (staticData) + return; + + if (arrayData) + delete [] data; + else + delete data; +} + +/** If there isn't data in the packet, allocate some. */ +void +Packet::allocate() { + if (data) + return; + assert(!staticData); + dynamicData = true; + arrayData = true; + data = new uint8_t[size]; +} + +/** Do the packet modify the same addresses. */ +bool +Packet::intersect(Packet *p) { + Addr s1 = addr; + Addr e1 = addr + size; + Addr s2 = p->addr; + Addr e2 = p->addr + p->size; + + if (s1 >= s2 && s1 < e2) + return true; + if (e1 >= s2 && e1 < e2) + return true; + return false; +} + +/** Minimally reset a packet so something like simple cpu can reuse it. */ +void +Packet::reset() { + result = Unknown; + if (dynamicData) { + deleteData(); + dynamicData = false; + arrayData = false; + time = curTick; + } +} + + + + +bool fixPacket(Packet &func, Packet &timing) +{ panic("Need to implement!"); } diff --git a/mem/packet.hh b/mem/packet.hh new file mode 100644 index 000000000..69d00675d --- /dev/null +++ b/mem/packet.hh @@ -0,0 +1,192 @@ +/* + * Copyright (c) 2006 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * @file + * Declaration of the Packet Class, a packet is a transaction occuring + * between a single level of the memory heirarchy (ie L1->L2). + */ + +#ifndef __MEM_PACKET_HH__ +#define __MEM_PACKET_HH__ + +#include "mem/request.hh" +#include "arch/isa_traits.hh" +#include "sim/root.hh" + +struct Packet; +typedef Packet* PacketPtr; +typedef uint8_t* PacketDataPtr; + +/** List of all commands associated with a packet. */ +enum Command +{ + Read, + Write +}; + +/** The result of a particular pakets request. */ +enum PacketResult +{ + Success, + BadAddress, + Unknown +}; + +class SenderState{}; +class Coherence{}; + +/** + * A Packet is the structure to handle requests between two levels + * of the memory system. The Request is a global object that trancends + * all of the memory heirarchy, but at each levels interface a packet + * is created to transfer data/requests. For example, a request would + * be used to initiate a request to go to memory/IOdevices, as the request + * passes through the memory system several packets will be created. One + * will be created to go between the L1 and L2 caches and another to go to + * the next level and so forth. + * + * Packets are assumed to be returned in the case of a single response. If + * the transaction has no response, then the consumer will delete the packet. + */ +struct Packet +{ + private: + /** A pointer to the data being transfered. It can be differnt sizes + at each level of the heirarchy so it belongs in the packet, + not request. This may or may not be populated when a responder recieves + the packet. If not populated it memory should be allocated. + */ + PacketDataPtr data; + + /** Is the data pointer set to a value that shouldn't be freed when the + * packet is destroyed? */ + bool staticData; + /** The data pointer points to a value that should be freed when the packet + * is destroyed. */ + bool dynamicData; + /** the data pointer points to an array (thus delete [] ) needs to be called + * on it rather than simply delete.*/ + bool arrayData; + + + public: + /** The address of the request, could be virtual or physical (depending on + cache configurations). */ + Addr addr; + + /** Flag structure to hold flags for this particular packet */ + uint64_t flags; + + /** A pointer to the overall request. */ + RequestPtr req; + + /** A virtual base opaque structure used to hold + coherence status messages. */ + Coherence *coherence; // virtual base opaque, + // assert(dynamic_cast<Foo>) etc. + + /** A virtual base opaque structure used to hold the senders state. */ + void *senderState; // virtual base opaque, + // assert(dynamic_cast<Foo>) etc. + + /** Indicates the size of the request. */ + int size; + + /** A index of the source of the transaction. */ + short src; + + /** A index to the destination of the transaction. */ + short dest; + + /** The command of the transaction. */ + Command cmd; + + /** The time this request was responded to. Used to calculate latencies. */ + Tick time; + + /** The result of the packet transaction. */ + PacketResult result; + + /** Accessor function that returns the source index of the packet. */ + short getSrc() const { return src; } + + /** Accessor function that returns the destination index of + the packet. */ + short getDest() const { return dest; } + + Packet() + : data(NULL), staticData(false), dynamicData(false), arrayData(false), + time(curTick), result(Unknown) + {} + + ~Packet() + { deleteData(); } + + + /** Minimally reset a packet so something like simple cpu can reuse it. */ + void reset(); + + /** Set the data pointer to the following value that should not be freed. */ + template <typename T> + void dataStatic(T *p); + + /** Set the data pointer to a value that should have delete [] called on it. + */ + template <typename T> + void dataDynamicArray(T *p); + + /** set the data pointer to a value that should have delete called on it. */ + template <typename T> + void dataDynamic(T *p); + + /** return the value of what is pointed to in the packet. */ + template <typename T> + T get(); + + /** get a pointer to the data ptr. */ + template <typename T> + T* getPtr(); + + /** set the value in the data pointer to v. */ + template <typename T> + void set(T v); + + /** delete the data pointed to in the data pointer. Ok to call to matter how + * data was allocted. */ + void deleteData(); + + /** If there isn't data in the packet, allocate some. */ + void allocate(); + + /** Do the packet modify the same addresses. */ + bool intersect(Packet *p); +}; + +bool fixPacket(Packet &func, Packet &timing); +#endif //__MEM_PACKET_HH diff --git a/mem/page_table.cc b/mem/page_table.cc new file mode 100644 index 000000000..c4e1ea193 --- /dev/null +++ b/mem/page_table.cc @@ -0,0 +1,134 @@ +/* + * Copyright (c) 2003 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. + */ + +/** + * @file + * Definitions of page table. + */ +#include <string> +#include <map> +#include <fstream> + +#include "arch/faults.hh" +#include "base/bitfield.hh" +#include "base/intmath.hh" +#include "base/trace.hh" +#include "mem/page_table.hh" +#include "sim/builder.hh" +#include "sim/sim_object.hh" +#include "sim/system.hh" + +using namespace std; +using namespace TheISA; + +PageTable::PageTable(System *_system, Addr _pageSize) + : pageSize(_pageSize), offsetMask(mask(floorLog2(_pageSize))), + system(_system) +{ + assert(isPowerOf2(pageSize)); +} + +PageTable::~PageTable() +{ +} + +Fault +PageTable::page_check(Addr addr, int size) const +{ + if (size < sizeof(uint64_t)) { + if (!isPowerOf2(size)) { + panic("Invalid request size!\n"); + return genMachineCheckFault(); + } + + if ((size - 1) & addr) + return genAlignmentFault(); + } + else { + if ((addr & (VMPageSize - 1)) + size > VMPageSize) { + panic("Invalid request size!\n"); + return genMachineCheckFault(); + } + + if ((sizeof(uint64_t) - 1) & addr) + return genAlignmentFault(); + } + + return NoFault; +} + + + + +void +PageTable::allocate(Addr vaddr, int size) +{ + // starting address must be page aligned + assert(pageOffset(vaddr) == 0); + + for (; size > 0; size -= pageSize, vaddr += pageSize) { + std::map<Addr,Addr>::iterator iter = pTable.find(vaddr); + + if (iter != pTable.end()) { + // already mapped + fatal("PageTable::allocate: address 0x%x already mapped", vaddr); + } + + pTable[vaddr] = system->new_page(); + } +} + + + +bool +PageTable::translate(Addr vaddr, Addr &paddr) +{ + Addr page_addr = pageAlign(vaddr); + std::map<Addr,Addr>::iterator iter = pTable.find(page_addr); + + if (iter == pTable.end()) { + return false; + } + + paddr = iter->second + pageOffset(vaddr); + return true; +} + + +Fault +PageTable::translate(RequestPtr &req) +{ + Addr paddr; + assert(pageAlign(req->getVaddr() + req->getSize() - 1) + == pageAlign(req->getVaddr())); + if (!translate(req->getVaddr(), paddr)) { + return genMachineCheckFault(); + } + req->setPaddr(paddr); + return page_check(req->getPaddr(), req->getSize()); +} diff --git a/mem/page_table.hh b/mem/page_table.hh new file mode 100644 index 000000000..26248261a --- /dev/null +++ b/mem/page_table.hh @@ -0,0 +1,90 @@ +/* + * Copyright (c) 2003 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. + */ + +/** + * @file + * Declaration of a non-full system Page Table. + */ + +#ifndef __PAGE_TABLE__ +#define __PAGE_TABLE__ + +#include <string> +#include <map> + +#include "arch/isa_traits.hh" +#include "base/trace.hh" +#include "mem/request.hh" +#include "mem/packet.hh" +#include "sim/sim_object.hh" + +class System; + +/** + * Page Table Decleration. + */ +class PageTable +{ + protected: + std::map<Addr,Addr> pTable; + + const Addr pageSize; + const Addr offsetMask; + + System *system; + + public: + + PageTable(System *_system, Addr _pageSize = TheISA::VMPageSize); + + ~PageTable(); + + Addr pageAlign(Addr a) { return (a & ~offsetMask); } + Addr pageOffset(Addr a) { return (a & offsetMask); } + + Fault page_check(Addr addr, int size) const; + + void allocate(Addr vaddr, int size); + + /** + * Translate function + * @param vaddr The virtual address. + * @return Physical address from translation. + */ + bool translate(Addr vaddr, Addr &paddr); + + /** + * Perform a translation on the memory request, fills in paddr + * field of mem_req. + * @param req The memory request. + */ + Fault translate(RequestPtr &req); + +}; + +#endif diff --git a/mem/physical.cc b/mem/physical.cc new file mode 100644 index 000000000..a9cefc70b --- /dev/null +++ b/mem/physical.cc @@ -0,0 +1,368 @@ +/* + * Copyright (c) 2001-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. + */ + +#include <sys/types.h> +#include <sys/mman.h> +#include <errno.h> +#include <fcntl.h> +#include <unistd.h> +#include <zlib.h> + +#include <cstdio> +#include <iostream> +#include <string> + + +#include "base/misc.hh" +#include "config/full_system.hh" +#include "mem/packet_impl.hh" +#include "mem/physical.hh" +#include "sim/host.hh" +#include "sim/builder.hh" +#include "sim/eventq.hh" +#include "arch/isa_traits.hh" + + +using namespace std; +using namespace TheISA; + +PhysicalMemory::MemResponseEvent::MemResponseEvent(Packet &pkt, MemoryPort* _m) + : Event(&mainEventQueue, CPU_Tick_Pri), pkt(pkt), memoryPort(_m) +{ + + this->setFlags(AutoDelete); +} + +void +PhysicalMemory::MemResponseEvent::process() +{ + memoryPort->sendTiming(pkt); +} + +const char * +PhysicalMemory::MemResponseEvent::description() +{ + return "Physical Memory Timing Access respnse event"; +} + +PhysicalMemory::PhysicalMemory(const string &n, Tick latency) + : MemObject(n),base_addr(0), pmem_addr(NULL), port(NULL), lat(latency) +{ + // Hardcoded to 128 MB for now. + pmem_size = 1 << 27; + + if (pmem_size % TheISA::PageBytes != 0) + panic("Memory Size not divisible by page size\n"); + + int map_flags = MAP_ANON | MAP_PRIVATE; + pmem_addr = (uint8_t *)mmap(NULL, pmem_size, PROT_READ | PROT_WRITE, + map_flags, -1, 0); + + if (pmem_addr == (void *)MAP_FAILED) { + perror("mmap"); + fatal("Could not mmap!\n"); + } + + page_ptr = 0; +} + +void +PhysicalMemory::init() +{ + if (!port) + panic("PhysicalMemory not connected to anything!"); + port->sendStatusChange(Port::RangeChange); +} + +PhysicalMemory::~PhysicalMemory() +{ + if (pmem_addr) + munmap(pmem_addr, pmem_size); + //Remove memPorts? +} + +Addr +PhysicalMemory::new_page() +{ + Addr return_addr = page_ptr << LogVMPageSize; + return_addr += base_addr; + + ++page_ptr; + return return_addr; +} + +int +PhysicalMemory::deviceBlockSize() +{ + //Can accept anysize request + return 0; +} + +bool +PhysicalMemory::doTimingAccess (Packet &pkt, MemoryPort* memoryPort) +{ + doFunctionalAccess(pkt); + + MemResponseEvent* response = new MemResponseEvent(pkt, memoryPort); + response->schedule(curTick + lat); + + return true; +} + +Tick +PhysicalMemory::doAtomicAccess(Packet &pkt) +{ + doFunctionalAccess(pkt); + pkt.time = curTick + lat; + return curTick + lat; +} + +void +PhysicalMemory::doFunctionalAccess(Packet &pkt) +{ + assert(pkt.addr + pkt.size < pmem_size); + + switch (pkt.cmd) { + case Read: + memcpy(pkt.getPtr<uint8_t>(), pmem_addr + pkt.addr - base_addr, + pkt.size); + break; + case Write: + memcpy(pmem_addr + pkt.addr - base_addr, pkt.getPtr<uint8_t>(), + pkt.size); + break; + default: + panic("unimplemented"); + } + + pkt.result = Success; +} + +Port * +PhysicalMemory::getPort(const std::string &if_name) +{ + if (if_name == "") { + if (port != NULL) + panic("PhysicalMemory::getPort: additional port requested to memory!"); + port = new MemoryPort(this); + return port; + } else if (if_name == "functional") { + /* special port for functional writes at startup. */ + return new MemoryPort(this); + } else { + panic("PhysicalMemory::getPort: unknown port %s requested", if_name); + } +} + +void +PhysicalMemory::recvStatusChange(Port::Status status) +{ +} + +PhysicalMemory::MemoryPort::MemoryPort(PhysicalMemory *_memory) + : memory(_memory) +{ } + +void +PhysicalMemory::MemoryPort::recvStatusChange(Port::Status status) +{ + memory->recvStatusChange(status); +} + +void +PhysicalMemory::MemoryPort::getDeviceAddressRanges(AddrRangeList &resp, + AddrRangeList &snoop) +{ + memory->getAddressRanges(resp, snoop); +} + +void +PhysicalMemory::getAddressRanges(AddrRangeList &resp, AddrRangeList &snoop) +{ + snoop.clear(); + resp.clear(); + resp.push_back(RangeSize(base_addr, pmem_size)); +} + +int +PhysicalMemory::MemoryPort::deviceBlockSize() +{ + return memory->deviceBlockSize(); +} + +bool +PhysicalMemory::MemoryPort::recvTiming(Packet &pkt) +{ + return memory->doTimingAccess(pkt, this); +} + +Tick +PhysicalMemory::MemoryPort::recvAtomic(Packet &pkt) +{ + return memory->doAtomicAccess(pkt); +} + +void +PhysicalMemory::MemoryPort::recvFunctional(Packet &pkt) +{ + memory->doFunctionalAccess(pkt); +} + + + +void +PhysicalMemory::serialize(ostream &os) +{ + gzFile compressedMem; + string filename = name() + ".physmem"; + + SERIALIZE_SCALAR(pmem_size); + SERIALIZE_SCALAR(filename); + + // write memory file + string thefile = Checkpoint::dir() + "/" + filename.c_str(); + int fd = creat(thefile.c_str(), 0664); + if (fd < 0) { + perror("creat"); + fatal("Can't open physical memory checkpoint file '%s'\n", filename); + } + + compressedMem = gzdopen(fd, "wb"); + if (compressedMem == NULL) + fatal("Insufficient memory to allocate compression state for %s\n", + filename); + + if (gzwrite(compressedMem, pmem_addr, pmem_size) != pmem_size) { + fatal("Write failed on physical memory checkpoint file '%s'\n", + filename); + } + + if (gzclose(compressedMem)) + fatal("Close failed on physical memory checkpoint file '%s'\n", + filename); +} + +void +PhysicalMemory::unserialize(Checkpoint *cp, const string §ion) +{ + gzFile compressedMem; + long *tempPage; + long *pmem_current; + uint64_t curSize; + uint32_t bytesRead; + const int chunkSize = 16384; + + + // unmap file that was mmaped in the constructor + munmap(pmem_addr, pmem_size); + + string filename; + + UNSERIALIZE_SCALAR(pmem_size); + UNSERIALIZE_SCALAR(filename); + + filename = cp->cptDir + "/" + filename; + + // mmap memoryfile + int fd = open(filename.c_str(), O_RDONLY); + if (fd < 0) { + perror("open"); + fatal("Can't open physical memory checkpoint file '%s'", filename); + } + + compressedMem = gzdopen(fd, "rb"); + if (compressedMem == NULL) + fatal("Insufficient memory to allocate compression state for %s\n", + filename); + + + pmem_addr = (uint8_t *)mmap(NULL, pmem_size, PROT_READ | PROT_WRITE, + MAP_ANON | MAP_PRIVATE, -1, 0); + + if (pmem_addr == (void *)MAP_FAILED) { + perror("mmap"); + fatal("Could not mmap physical memory!\n"); + } + + curSize = 0; + tempPage = (long*)malloc(chunkSize); + if (tempPage == NULL) + fatal("Unable to malloc memory to read file %s\n", filename); + + /* Only copy bytes that are non-zero, so we don't give the VM system hell */ + while (curSize < pmem_size) { + bytesRead = gzread(compressedMem, tempPage, chunkSize); + if (bytesRead != chunkSize && bytesRead != pmem_size - curSize) + fatal("Read failed on physical memory checkpoint file '%s'" + " got %d bytes, expected %d or %d bytes\n", + filename, bytesRead, chunkSize, pmem_size-curSize); + + assert(bytesRead % sizeof(long) == 0); + + for (int x = 0; x < bytesRead/sizeof(long); x++) + { + if (*(tempPage+x) != 0) { + pmem_current = (long*)(pmem_addr + curSize + x * sizeof(long)); + *pmem_current = *(tempPage+x); + } + } + curSize += bytesRead; + } + + free(tempPage); + + if (gzclose(compressedMem)) + fatal("Close failed on physical memory checkpoint file '%s'\n", + filename); + +} + + +BEGIN_DECLARE_SIM_OBJECT_PARAMS(PhysicalMemory) + + Param<string> file; + Param<Range<Addr> > range; + Param<Tick> latency; + +END_DECLARE_SIM_OBJECT_PARAMS(PhysicalMemory) + +BEGIN_INIT_SIM_OBJECT_PARAMS(PhysicalMemory) + + INIT_PARAM_DFLT(file, "memory mapped file", ""), + INIT_PARAM(range, "Device Address Range"), + INIT_PARAM(latency, "Memory access latency") + +END_INIT_SIM_OBJECT_PARAMS(PhysicalMemory) + +CREATE_SIM_OBJECT(PhysicalMemory) +{ + + return new PhysicalMemory(getInstanceName(), latency); +} + +REGISTER_SIM_OBJECT("PhysicalMemory", PhysicalMemory) diff --git a/mem/physical.hh b/mem/physical.hh new file mode 100644 index 000000000..f87683c45 --- /dev/null +++ b/mem/physical.hh @@ -0,0 +1,127 @@ +/* + * Copyright (c) 2001-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. + */ + +/* @file + */ + +#ifndef __PHYSICAL_MEMORY_HH__ +#define __PHYSICAL_MEMORY_HH__ + +#include "base/range.hh" +#include "mem/mem_object.hh" +#include "mem/packet.hh" +#include "mem/port.hh" +#include "sim/eventq.hh" +#include <map> +#include <string> + +// +// Functional model for a contiguous block of physical memory. (i.e. RAM) +// +class PhysicalMemory : public MemObject +{ + class MemoryPort : public Port + { + PhysicalMemory *memory; + + public: + + MemoryPort(PhysicalMemory *_memory); + + protected: + + virtual bool recvTiming(Packet &pkt); + + virtual Tick recvAtomic(Packet &pkt); + + virtual void recvFunctional(Packet &pkt); + + virtual void recvStatusChange(Status status); + + virtual void getDeviceAddressRanges(AddrRangeList &resp, + AddrRangeList &snoop); + + virtual int deviceBlockSize(); + }; + + int numPorts; + + + struct MemResponseEvent : public Event + { + Packet &pkt; + MemoryPort *memoryPort; + + MemResponseEvent(Packet &pkt, MemoryPort *memoryPort); + void process(); + const char *description(); + }; + + private: + // prevent copying of a MainMemory object + PhysicalMemory(const PhysicalMemory &specmem); + const PhysicalMemory &operator=(const PhysicalMemory &specmem); + + protected: + Addr base_addr; + Addr pmem_size; + uint8_t *pmem_addr; + MemoryPort *port; + int page_ptr; + Tick lat; + + public: + Addr new_page(); + uint64_t size() { return pmem_size; } + + public: + PhysicalMemory(const std::string &n, Tick latency); + virtual ~PhysicalMemory(); + + public: + int deviceBlockSize(); + void getAddressRanges(AddrRangeList &resp, AddrRangeList &snoop); + virtual Port *getPort(const std::string &if_name); + void virtual init(); + + // fast back-door memory access for vtophys(), remote gdb, etc. + // uint64_t phys_read_qword(Addr addr) const; + private: + bool doTimingAccess(Packet &pkt, MemoryPort *memoryPort); + Tick doAtomicAccess(Packet &pkt); + void doFunctionalAccess(Packet &pkt); + + void recvStatusChange(Port::Status status); + + public: + virtual void serialize(std::ostream &os); + virtual void unserialize(Checkpoint *cp, const std::string §ion); + +}; + +#endif //__PHYSICAL_MEMORY_HH__ diff --git a/mem/port.cc b/mem/port.cc new file mode 100644 index 000000000..32031d96c --- /dev/null +++ b/mem/port.cc @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2002-2005 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * @file Port object definitions. + */ + +#include "base/chunk_generator.hh" +#include "mem/port.hh" + +void +Port::blobHelper(Addr addr, uint8_t *p, int size, Command cmd) +{ + Request req(false); + Packet pkt; + pkt.req = &req; + pkt.cmd = cmd; + + for (ChunkGenerator gen(addr, size, peerBlockSize()); + !gen.done(); gen.next()) { + req.setPaddr(pkt.addr = gen.addr()); + req.setSize(pkt.size = gen.size()); + pkt.dataStatic(p); + sendFunctional(pkt); + p += gen.size(); + } +} + +void +Port::writeBlob(Addr addr, uint8_t *p, int size) +{ + blobHelper(addr, p, size, Write); +} + +void +Port::readBlob(Addr addr, uint8_t *p, int size) +{ + blobHelper(addr, p, size, Read); +} + +void +Port::memsetBlob(Addr addr, uint8_t val, int size) +{ + // quick and dirty... + uint8_t *buf = new uint8_t[size]; + + memset(buf, val, size); + blobHelper(addr, buf, size, Write); + + delete [] buf; +} diff --git a/mem/port.hh b/mem/port.hh new file mode 100644 index 000000000..2ab2806c9 --- /dev/null +++ b/mem/port.hh @@ -0,0 +1,247 @@ +/* + * Copyright (c) 2002-2005 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * @file + * Port Object Decleration. Ports are used to interface memory objects to + * each other. They will always come in pairs, and we refer to the other + * port object as the peer. These are used to make the design more + * modular so that a specific interface between every type of objcet doesn't + * have to be created. + */ + +#ifndef __MEM_PORT_HH__ +#define __MEM_PORT_HH__ + +#include <list> +#include <inttypes.h> + +#include "base/misc.hh" +#include "base/range.hh" +#include "mem/packet.hh" +#include "mem/request.hh" + +/** This typedef is used to clean up the parameter list of + * getDeviceAddressRanges() and getPeerAddressRanges(). It's declared + * outside the Port object since it's also used by some mem objects. + * Eventually we should move this typedef to wherever Addr is + * defined. + */ + +typedef std::list<Range<Addr> > AddrRangeList; +typedef std::list<Range<Addr> >::iterator AddrRangeIter; + +/** + * Ports are used to interface memory objects to + * each other. They will always come in pairs, and we refer to the other + * port object as the peer. These are used to make the design more + * modular so that a specific interface between every type of objcet doesn't + * have to be created. + * + * Recv accesor functions are being called from the peer interface. + * Send accessor functions are being called from the device the port is + * associated with, and it will call the peer recv. accessor function. + */ +class Port +{ + public: + + virtual ~Port() {}; + // mey be better to use subclasses & RTTI? + /** Holds the ports status. Keeps track if it is blocked, or has + calculated a range change. */ + enum Status { + Blocked, + Unblocked, + RangeChange + }; + + private: + + /** A pointer to the peer port. Ports always come in pairs, that way they + can use a standardized interface to communicate between different + memory objects. */ + Port *peer; + + public: + + /** Function to set the pointer for the peer port. + @todo should be called by the configuration stuff (python). + */ + void setPeer(Port *port) { peer = port; } + + /** Function to set the pointer for the peer port. + @todo should be called by the configuration stuff (python). + */ + Port *getPeer() { return peer; } + + protected: + + /** These functions are protected because they should only be + * called by a peer port, never directly by any outside object. */ + + /** Called to recive a timing call from the peer port. */ + virtual bool recvTiming(Packet &pkt) = 0; + + /** Called to recive a atomic call from the peer port. */ + virtual Tick recvAtomic(Packet &pkt) = 0; + + /** Called to recive a functional call from the peer port. */ + virtual void recvFunctional(Packet &pkt) = 0; + + /** Called to recieve a status change from the peer port. */ + virtual void recvStatusChange(Status status) = 0; + + /** Called by a peer port if the send was unsuccesful, and had to + wait. This shouldn't be valid for response paths (IO Devices). + so it is set to panic if it isn't already defined. + */ + virtual Packet *recvRetry() { panic("??"); } + + /** Called by a peer port in order to determine the block size of the + device connected to this port. It sometimes doesn't make sense for + this function to be called, a DMA interface doesn't really have a + block size, so it is defaulted to a panic. + */ + virtual int deviceBlockSize() { panic("??"); } + + /** The peer port is requesting us to reply with a list of the ranges we + are responsible for. + @param resp is a list of ranges responded to + @param snoop is a list of ranges snooped + */ + virtual void getDeviceAddressRanges(AddrRangeList &resp, + AddrRangeList &snoop) + { panic("??"); } + + public: + + /** Function called by associated memory device (cache, memory, iodevice) + in order to send a timing request to the port. Simply calls the peer + port receive function. + @return This function returns if the send was succesful in it's + recieve. If it was a failure, then the port will wait for a recvRetry + at which point it can issue a successful sendTiming. This is used in + case a cache has a higher priority request come in while waiting for + the bus to arbitrate. + */ + bool sendTiming(Packet &pkt) { return peer->recvTiming(pkt); } + + /** Function called by the associated device to send an atomic access, + an access in which the data is moved and the state is updated in one + cycle, without interleaving with other memory accesses. + */ + Tick sendAtomic(Packet &pkt) + { return peer->recvAtomic(pkt); } + + /** Function called by the associated device to send a functional access, + an access in which the data is instantly updated everywhere in the + memory system, without affecting the current state of any block or + moving the block. + */ + void sendFunctional(Packet &pkt) + { return peer->recvFunctional(pkt); } + + /** Called by the associated device to send a status change to the device + connected to the peer interface. + */ + void sendStatusChange(Status status) {peer->recvStatusChange(status); } + + /** When a timing access doesn't return a success, some time later the + Retry will be sent. + */ + Packet *sendRetry() { return peer->recvRetry(); } + + /** Called by the associated device if it wishes to find out the blocksize + of the device on attached to the peer port. + */ + int peerBlockSize() { return peer->deviceBlockSize(); } + + /** Called by the associated device if it wishes to find out the address + ranges connected to the peer ports devices. + */ + void getPeerAddressRanges(AddrRangeList &resp, AddrRangeList &snoop) + { peer->getDeviceAddressRanges(resp, snoop); } + + /** This function is a wrapper around sendFunctional() + that breaks a larger, arbitrarily aligned access into + appropriate chunks. The default implementation can use + getBlockSize() to determine the block size and go from there. + */ + virtual void readBlob(Addr addr, uint8_t *p, int size); + + /** This function is a wrapper around sendFunctional() + that breaks a larger, arbitrarily aligned access into + appropriate chunks. The default implementation can use + getBlockSize() to determine the block size and go from there. + */ + virtual void writeBlob(Addr addr, uint8_t *p, int size); + + /** Fill size bytes starting at addr with byte value val. This + should not need to be virtual, since it can be implemented in + terms of writeBlob(). However, it shouldn't be + performance-critical either, so it could be if we wanted to. + */ + virtual void memsetBlob(Addr addr, uint8_t val, int size); + + private: + + /** Internal helper function for read/writeBlob(). + */ + void blobHelper(Addr addr, uint8_t *p, int size, Command cmd); +}; + +/** A simple functional port that is only meant for one way communication to + * physical memory. It is only meant to be used to load data into memory before + * the simulation begins. + */ + +class FunctionalPort : public Port +{ + public: + virtual bool recvTiming(Packet &pkt) { panic("FuncPort is UniDir"); } + virtual Tick recvAtomic(Packet &pkt) { panic("FuncPort is UniDir"); } + virtual void recvFunctional(Packet &pkt) { panic("FuncPort is UniDir"); } + virtual void recvStatusChange(Status status) {} + + template <typename T> + inline void write(Addr addr, T d) + { + writeBlob(addr, (uint8_t*)&d, sizeof(T)); + } + + template <typename T> + inline T read(Addr addr) + { + T d; + readBlob(addr, (uint8_t*)&d, sizeof(T)); + return d; + } +}; + +#endif //__MEM_PORT_HH__ diff --git a/mem/request.hh b/mem/request.hh new file mode 100644 index 000000000..903e7503c --- /dev/null +++ b/mem/request.hh @@ -0,0 +1,202 @@ +/* + * Copyright (c) 2002-2005 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * @file Decleration of a request, the overall memory request consisting of + the parts of the request that are persistent throughout the transaction. + */ + +#ifndef __MEM_REQUEST_HH__ +#define __MEM_REQUEST_HH__ + +#include "arch/isa_traits.hh" + +class Request; + +typedef Request* RequestPtr; + +/** The request is a Load locked/store conditional. */ +const unsigned LOCKED = 0x001; +/** The virtual address is also the physical address. */ +const unsigned PHYSICAL = 0x002; +/** The request is an ALPHA VPTE pal access (hw_ld). */ +const unsigned VPTE = 0x004; +/** Use the alternate mode bits in ALPHA. */ +const unsigned ALTMODE = 0x008; +/** The request is to an uncacheable address. */ +const unsigned UNCACHEABLE = 0x010; +/** The request should not cause a page fault. */ +const unsigned NO_FAULT = 0x020; +/** The request should be prefetched into the exclusive state. */ +const unsigned PF_EXCLUSIVE = 0x100; +/** The request should be marked as LRU. */ +const unsigned EVICT_NEXT = 0x200; +/** The request should ignore unaligned access faults */ +const unsigned NO_ALIGN_FAULT = 0x400; + +class Request +{ + //@todo Make Accesor functions, make these private. + public: + /** Constructor, needs a bool to signify if it is/isn't Cpu Request. */ + Request(bool isCpu); + + /** reset the request to it's initial state so it can be reused.*/ + void resetAll(bool isCpu); + + /** reset the request's addrs times, etc, so but not everything to same + * time. */ + void resetMin(); + +//First non-cpu request fields + private: + /** The physical address of the request. */ + Addr paddr; + /** Wether or not paddr is valid (has been written yet). */ + bool validPaddr; + + /** The size of the request. */ + int size; + /** Wether or not size is valid (has been written yet). */ + bool validSize; + + /** The time this request was started. Used to calculate latencies. */ + Tick time; + /** Wether or not time is valid (has been written yet). */ + bool validTime; + + /** Destination address if this is a block copy. */ + Addr copyDest; + /** Wether or not copyDest is valid (has been written yet). */ + bool validCopyDest; + + /** Flag structure for the request. */ + uint32_t flags; + /** Wether or not flags is valid (has been written yet). */ + bool validFlags; + +//Accsesors for non-cpu request fields + public: + /** Accesor for paddr. */ + Addr getPaddr(); + /** Accesor for paddr. */ + void setPaddr(Addr _paddr); + + /** Accesor for size. */ + int getSize(); + /** Accesor for size. */ + void setSize(int _size); + + /** Accesor for time. */ + Tick getTime(); + /** Accesor for time. */ + void setTime(Tick _time); + + /** Accesor for copy dest. */ + Addr getCopyDest(); + /** Accesor for copy dest. */ + void setCopyDest(Addr _copyDest); + + /** Accesor for flags. */ + uint32_t getFlags(); + /** Accesor for paddr. */ + void setFlags(uint32_t _flags); + +//Now cpu-request fields + private: + /** Bool to signify if this is a cpuRequest. */ + bool cpuReq; + + /** The virtual address of the request. */ + Addr vaddr; + /** Wether or not the vaddr is valid. */ + bool validVaddr; + + /** The address space ID. */ + int asid; + /** Wether or not the asid is valid. */ + bool validAsid; + + /** The return value of store conditional. */ + uint64_t scResult; + /** Wether or not the sc result is valid. */ + bool validScResult; + + /** The cpu number for statistics. */ + int cpuNum; + /** Wether or not the cpu number is valid. */ + bool validCpuNum; + + /** The requesting thread id. */ + int threadNum; + /** Wether or not the thread id is valid. */ + bool validThreadNum; + + /** program counter of initiating access; for tracing/debugging */ + Addr pc; + /** Wether or not the pc is valid. */ + bool validPC; + +//Accessor Functions for cpu request fields + public: + /** Accesor function to determine if this is a cpu request or not.*/ + bool isCpuRequest(); + + /** Accesor function for vaddr.*/ + Addr getVaddr(); + /** Accesor function for vaddr.*/ + void setVaddr(Addr _vaddr); + + /** Accesor function for asid.*/ + int getAsid(); + /** Accesor function for asid.*/ + void setAsid(int _asid); + + /** Accesor function for store conditional return value.*/ + uint64_t getScResult(); + /** Accesor function for store conditional return value.*/ + void setScResult(uint64_t _scResult); + + /** Accesor function for cpu number.*/ + int getCpuNum(); + /** Accesor function for cpu number.*/ + void setCpuNum(int _cpuNum); + + /** Accesor function for thread number.*/ + int getThreadNum(); + /** Accesor function for thread number.*/ + void setThreadNum(int _threadNum); + + /** Accesor function for pc.*/ + Addr getPC(); + /** Accesor function for pc.*/ + void setPC(Addr _pc); + +}; + +#endif // __MEM_REQUEST_HH__ diff --git a/mem/translating_port.cc b/mem/translating_port.cc new file mode 100644 index 000000000..5dfeaff31 --- /dev/null +++ b/mem/translating_port.cc @@ -0,0 +1,186 @@ +/* + * Copyright (c) 2001-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. + */ + +#include <string> +#include "base/chunk_generator.hh" +#include "mem/port.hh" +#include "mem/translating_port.hh" +#include "mem/page_table.hh" + +using namespace TheISA; + +TranslatingPort::TranslatingPort(PageTable *p_table, bool alloc) + : pTable(p_table), allocating(alloc) +{ } + +TranslatingPort::~TranslatingPort() +{ } + +bool +TranslatingPort::tryReadBlob(Addr addr, uint8_t *p, int size) +{ + Addr paddr; + int prevSize = 0; + + for (ChunkGenerator gen(addr, size, VMPageSize); !gen.done(); gen.next()) { + + if (!pTable->translate(gen.addr(),paddr)) + return false; + + Port::readBlob(paddr, p + prevSize, gen.size()); + prevSize += gen.size(); + } + + return true; +} + +void +TranslatingPort::readBlob(Addr addr, uint8_t *p, int size) +{ + if (!tryReadBlob(addr, p, size)) + fatal("readBlob(0x%x, ...) failed", addr); +} + + +bool +TranslatingPort::tryWriteBlob(Addr addr, uint8_t *p, int size) +{ + + Addr paddr; + int prevSize = 0; + + for (ChunkGenerator gen(addr, size, VMPageSize); !gen.done(); gen.next()) { + + if (!pTable->translate(gen.addr(), paddr)) { + if (allocating) { + pTable->allocate(roundDown(gen.addr(), VMPageSize), + VMPageSize); + pTable->translate(gen.addr(), paddr); + } else { + return false; + } + } + + Port::writeBlob(paddr, p + prevSize, gen.size()); + prevSize += gen.size(); + } + + return true; +} + + +void +TranslatingPort::writeBlob(Addr addr, uint8_t *p, int size) +{ + if (!tryWriteBlob(addr, p, size)) + fatal("writeBlob(0x%x, ...) failed", addr); +} + +bool +TranslatingPort::tryMemsetBlob(Addr addr, uint8_t val, int size) +{ + Addr paddr; + + for (ChunkGenerator gen(addr, size, VMPageSize); !gen.done(); gen.next()) { + + if (!pTable->translate(gen.addr(), paddr)) { + if (allocating) { + pTable->allocate(roundDown(gen.addr(), VMPageSize), + VMPageSize); + pTable->translate(gen.addr(), paddr); + } else { + return false; + } + } + + Port::memsetBlob(paddr, val, gen.size()); + } + + return true; +} + +void +TranslatingPort::memsetBlob(Addr addr, uint8_t val, int size) +{ + if (!tryMemsetBlob(addr, val, size)) + fatal("memsetBlob(0x%x, ...) failed", addr); +} + + +bool +TranslatingPort::tryWriteString(Addr addr, const char *str) +{ + Addr paddr,vaddr; + uint8_t c; + + vaddr = addr; + + do { + c = *str++; + if (!pTable->translate(vaddr++,paddr)) + return false; + + Port::writeBlob(paddr, &c, 1); + } while (c); + + return true; +} + +void +TranslatingPort::writeString(Addr addr, const char *str) +{ + if (!tryWriteString(addr, str)) + fatal("writeString(0x%x, ...) failed", addr); +} + +bool +TranslatingPort::tryReadString(std::string &str, Addr addr) +{ + Addr paddr,vaddr; + uint8_t c; + + vaddr = addr; + + do { + if (!pTable->translate(vaddr++,paddr)) + return false; + + Port::readBlob(paddr, &c, 1); + str += c; + } while (c); + + return true; +} + +void +TranslatingPort::readString(std::string &str, Addr addr) +{ + if (!tryReadString(str, addr)) + fatal("readString(0x%x, ...) failed", addr); +} + diff --git a/mem/translating_port.hh b/mem/translating_port.hh new file mode 100644 index 000000000..7611ac3c7 --- /dev/null +++ b/mem/translating_port.hh @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2001-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. + */ + +#ifndef __MEM_TRANSLATING_PROT_HH__ +#define __MEM_TRANSLATING_PROT_HH__ + +#include "mem/port.hh" + +class PageTable; + +class TranslatingPort : public FunctionalPort +{ + private: + PageTable *pTable; + bool allocating; + + TranslatingPort(const TranslatingPort &specmem); + const TranslatingPort &operator=(const TranslatingPort &specmem); + + public: + TranslatingPort(PageTable *p_table, bool alloc = false); + virtual ~TranslatingPort(); + + public: + bool tryReadBlob(Addr addr, uint8_t *p, int size); + bool tryWriteBlob(Addr addr, uint8_t *p, int size); + bool tryMemsetBlob(Addr addr, uint8_t val, int size); + bool tryWriteString(Addr addr, const char *str); + bool tryReadString(std::string &str, Addr addr); + + virtual void readBlob(Addr addr, uint8_t *p, int size); + virtual void writeBlob(Addr addr, uint8_t *p, int size); + virtual void memsetBlob(Addr addr, uint8_t val, int size); + void writeString(Addr addr, const char *str); + void readString(std::string &str, Addr addr); + +}; + +#endif diff --git a/mem/vport.cc b/mem/vport.cc new file mode 100644 index 000000000..cc569acf3 --- /dev/null +++ b/mem/vport.cc @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2006 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * @file Port object definitions. + */ + +#include "base/chunk_generator.hh" +#include "mem/vport.hh" + +void +VirtualPort::readBlob(Addr addr, uint8_t *p, int size) +{ + Addr paddr; + for (ChunkGenerator gen(addr, size, TheISA::PageBytes); !gen.done(); + gen.next()) + { + if (xc) + paddr = TheISA::vtophys(xc,gen.addr()); + else + paddr = TheISA::vtophys(gen.addr()); + + FunctionalPort::readBlob(paddr, p, gen.size()); + p += gen.size(); + } +} + +void +VirtualPort::writeBlob(Addr addr, uint8_t *p, int size) +{ + Addr paddr; + for (ChunkGenerator gen(addr, size, TheISA::PageBytes); !gen.done(); + gen.next()) + { + if (xc) + paddr = TheISA::vtophys(xc,gen.addr()); + else + paddr = TheISA::vtophys(gen.addr()); + + FunctionalPort::writeBlob(paddr, p, gen.size()); + p += gen.size(); + } +} + diff --git a/mem/vport.hh b/mem/vport.hh new file mode 100644 index 000000000..fbc230ba3 --- /dev/null +++ b/mem/vport.hh @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2006 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * @file + * Virtual Port Object Decleration. These ports incorporate some translation + * into their access methods. Thus you can use one to read and write data + * to/from virtual addresses. + */ + +#ifndef __MEM_VPORT_HH__ +#define __MEM_VPORT_HH__ + +#include "mem/port.hh" +#include "config/full_system.hh" +#include "arch/vtophys.hh" + + +/** A class that translates a virtual address to a physical address and then + * calls the above read/write functions. If an execution context is provided the + * address can alway be translated, If not it can only be translated if it is a + * simple address masking operation (such as alpha super page accesses). + */ + +class VirtualPort : public FunctionalPort +{ + private: + ExecContext *xc; + + public: + VirtualPort(ExecContext *_xc = NULL) + : xc(_xc) + {} + + /** Return true if we have an exec context. This is used to prevent someone + * from accidently deleting the cpus statically allocated vport. + * @return true if an execution context isn't valid + */ + bool nullExecContext() { return xc != NULL; } + + /** Version of readblob that translates virt->phys and deals + * with page boundries. */ + virtual void readBlob(Addr addr, uint8_t *p, int size); + + /** Version of writeBlob that translates virt->phys and deals + * with page boundries. */ + virtual void writeBlob(Addr addr, uint8_t *p, int size); +}; + +#endif //__MEM_VPORT_HH__ + diff --git a/python/m5/objects/AlphaConsole.py b/python/m5/objects/AlphaConsole.py index f8f034682..68e6089ab 100644 --- a/python/m5/objects/AlphaConsole.py +++ b/python/m5/objects/AlphaConsole.py @@ -1,9 +1,9 @@ from m5 import * -from Device import PioDevice +from Device import BasicPioDevice -class AlphaConsole(PioDevice): +class AlphaConsole(BasicPioDevice): type = 'AlphaConsole' cpu = Param.BaseCPU(Parent.any, "Processor") disk = Param.SimpleDisk("Simple Disk") sim_console = Param.SimConsole(Parent.any, "The Simulator Console") - system = Param.System(Parent.any, "system object") + system = Param.AlphaSystem(Parent.any, "system object") diff --git a/python/m5/objects/BadDevice.py b/python/m5/objects/BadDevice.py index 3fba4637d..9cb9a8f03 100644 --- a/python/m5/objects/BadDevice.py +++ b/python/m5/objects/BadDevice.py @@ -1,6 +1,6 @@ from m5 import * -from Device import PioDevice +from Device import BasicPioDevice -class BadDevice(PioDevice): +class BadDevice(BasicPioDevice): type = 'BadDevice' devicename = Param.String("Name of device to error on") diff --git a/python/m5/objects/BaseCPU.py b/python/m5/objects/BaseCPU.py index a90203729..49cb2a8f3 100644 --- a/python/m5/objects/BaseCPU.py +++ b/python/m5/objects/BaseCPU.py @@ -2,13 +2,11 @@ from m5 import * class BaseCPU(SimObject): type = 'BaseCPU' abstract = True - icache = Param.BaseMem(NULL, "L1 instruction cache object") - dcache = Param.BaseMem(NULL, "L1 data cache object") + mem = Param.MemObject("memory") if build_env['FULL_SYSTEM']: dtb = Param.AlphaDTB("Data TLB") itb = Param.AlphaITB("Instruction TLB") - mem = Param.FunctionalMemory("memory") system = Param.System(Parent.any, "system object") cpu_id = Param.Int(-1, "CPU identifier") else: diff --git a/python/m5/objects/Bridge.py b/python/m5/objects/Bridge.py new file mode 100644 index 000000000..ada715ce9 --- /dev/null +++ b/python/m5/objects/Bridge.py @@ -0,0 +1,9 @@ +from m5 import * +from MemObject import MemObject + +class Bridge(MemObject): + type = 'Bridge' + queue_size_a = Param.Int(16, "The number of requests to buffer") + queue_size_b = Param.Int(16, "The number of requests to buffer") + delay = Param.Latency('0ns', "The latency of this bridge") + write_ack = Param.Bool(False, "Should this bridge ack writes") diff --git a/python/m5/objects/Bus.py b/python/m5/objects/Bus.py index 26509d7d2..8c5397281 100644 --- a/python/m5/objects/Bus.py +++ b/python/m5/objects/Bus.py @@ -1,7 +1,6 @@ from m5 import * -from BaseHier import BaseHier +from MemObject import MemObject -class Bus(BaseHier): +class Bus(MemObject): type = 'Bus' - clock = Param.Clock("bus frequency") - width = Param.Int("bus width in bytes") + bus_id = Param.Int(0, "blah") diff --git a/python/m5/objects/Device.py b/python/m5/objects/Device.py index d7ca014a9..2a71bbc65 100644 --- a/python/m5/objects/Device.py +++ b/python/m5/objects/Device.py @@ -1,35 +1,18 @@ from m5 import * -from FunctionalMemory import FunctionalMemory +from MemObject import MemObject -# This device exists only because there are some devices that I don't -# want to have a Platform parameter because it would cause a cycle in -# the C++ that cannot be easily solved. -# -# The real solution to this problem is to pass the ParamXXX structure -# to the constructor, but with the express condition that SimObject -# parameter values are not to be available at construction time. If -# some further configuration must be done, it must be done during the -# initialization phase at which point all SimObject pointers will be -# valid. -class FooPioDevice(FunctionalMemory): +class PioDevice(MemObject): type = 'PioDevice' abstract = True - addr = Param.Addr("Device Address") - mmu = Param.MemoryController(Parent.any, "Memory Controller") - pio_bus = Param.Bus(NULL, "Bus to attach to for PIO") - pio_latency = Param.Tick(1, "Programmed IO latency in bus cycles") + platform = Param.Platform(Parent.any, "Platform this device is part of") + system = Param.System(Parent.any, "System this device is part of") -class FooDmaDevice(FooPioDevice): - type = 'DmaDevice' - abstract = True - dma_bus = Param.Bus(Self.pio_bus, "Bus to attach to for DMA") - -class PioDevice(FooPioDevice): - type = 'PioDevice' +class BasicPioDevice(PioDevice): + type = 'BasicPioDevice' abstract = True - platform = Param.Platform(Parent.any, "Platform") + pio_addr = Param.Addr("Device Address") + pio_latency = Param.Tick(1, "Programmed IO latency in simticks") class DmaDevice(PioDevice): type = 'DmaDevice' abstract = True - dma_bus = Param.Bus(Self.pio_bus, "Bus to attach to for DMA") diff --git a/python/m5/objects/Ethernet.py b/python/m5/objects/Ethernet.py index 68b21b404..4286c71c8 100644 --- a/python/m5/objects/Ethernet.py +++ b/python/m5/objects/Ethernet.py @@ -67,15 +67,10 @@ class EtherDevBase(PciDevice): clock = Param.Clock('0ns', "State machine processor frequency") - physmem = Param.PhysicalMemory(Parent.any, "Physical Memory") - - hier = Param.HierParams(Parent.any, "Hierarchy global variables") - payload_bus = Param.Bus(NULL, "The IO Bus to attach to for payload") dma_read_delay = Param.Latency('0us', "fixed delay for dma reads") dma_read_factor = Param.Latency('0us', "multiplier for dma reads") dma_write_delay = Param.Latency('0us', "fixed delay for dma writes") dma_write_factor = Param.Latency('0us', "multiplier for dma writes") - dma_no_allocate = Param.Bool(True, "Should we allocate cache on read") rx_delay = Param.Latency('1us', "Receive Delay") tx_delay = Param.Latency('1us', "Transmit Delay") @@ -93,6 +88,7 @@ class NSGigE(EtherDevBase): dma_data_free = Param.Bool(False, "DMA of Data is free") dma_desc_free = Param.Bool(False, "DMA of Descriptors is free") + dma_no_allocate = Param.Bool(True, "Should we allocate cache on read") class NSGigEInt(EtherInt): diff --git a/python/m5/objects/Ide.py b/python/m5/objects/Ide.py index 6855ec653..2403e6d36 100644 --- a/python/m5/objects/Ide.py +++ b/python/m5/objects/Ide.py @@ -8,7 +8,6 @@ class IdeDisk(SimObject): delay = Param.Latency('1us', "Fixed disk delay in microseconds") driveID = Param.IdeID('master', "Drive ID") image = Param.DiskImage("Disk image") - physmem = Param.PhysicalMemory(Parent.any, "Physical memory") class IdeController(PciDevice): type = 'IdeController' diff --git a/python/m5/objects/MemObject.py b/python/m5/objects/MemObject.py new file mode 100644 index 000000000..4d68243e6 --- /dev/null +++ b/python/m5/objects/MemObject.py @@ -0,0 +1,5 @@ +from m5 import * + +class MemObject(SimObject): + type = 'MemObject' + abstract = True diff --git a/python/m5/objects/Pci.py b/python/m5/objects/Pci.py index 4124d0b92..85cefcd44 100644 --- a/python/m5/objects/Pci.py +++ b/python/m5/objects/Pci.py @@ -1,5 +1,5 @@ from m5 import * -from Device import FooPioDevice, DmaDevice +from Device import BasicPioDevice, DmaDevice class PciConfigData(SimObject): type = 'PciConfigData' @@ -38,16 +38,16 @@ class PciConfigData(SimObject): MaximumLatency = Param.UInt8(0x00, "Maximum Latency") MinimumGrant = Param.UInt8(0x00, "Minimum Grant") -class PciConfigAll(FooPioDevice): +class PciConfigAll(BasicPioDevice): type = 'PciConfigAll' class PciDevice(DmaDevice): type = 'PciDevice' abstract = True - addr = 0xffffffffL pci_bus = Param.Int("PCI bus") pci_dev = Param.Int("PCI device number") pci_func = Param.Int("PCI function code") + pio_latency = Param.Tick(1, "Programmed IO latency in simticks") configdata = Param.PciConfigData(Parent.any, "PCI Config data") configspace = Param.PciConfigAll(Parent.any, "PCI Configspace") diff --git a/python/m5/objects/PhysicalMemory.py b/python/m5/objects/PhysicalMemory.py index f50937ee6..e59e94e9b 100644 --- a/python/m5/objects/PhysicalMemory.py +++ b/python/m5/objects/PhysicalMemory.py @@ -1,8 +1,8 @@ from m5 import * -from FunctionalMemory import FunctionalMemory +from MemObject import * -class PhysicalMemory(FunctionalMemory): +class PhysicalMemory(MemObject): type = 'PhysicalMemory' range = Param.AddrRange("Device Address") file = Param.String('', "memory mapped file") - mmu = Param.MemoryController(Parent.any, "Memory Controller") + latency = Param.Latency('10ns', "latency of an access") diff --git a/python/m5/objects/Process.py b/python/m5/objects/Process.py index b4ccc1bec..60b00229e 100644 --- a/python/m5/objects/Process.py +++ b/python/m5/objects/Process.py @@ -3,6 +3,7 @@ class Process(SimObject): type = 'Process' abstract = True output = Param.String('cout', 'filename for stdout/stderr') + system = Param.System(Parent.any, "system process will run on") class LiveProcess(Process): type = 'LiveProcess' @@ -11,6 +12,15 @@ class LiveProcess(Process): env = VectorParam.String('', "environment settings") input = Param.String('cin', "filename for stdin") +class AlphaLiveProcess(LiveProcess): + type = 'AlphaLiveProcess' + +class SparcLiveProcess(LiveProcess): + type = 'SparcLiveProcess' + +class MipsLiveProcess(LiveProcess): + type = 'MipsLiveProcess' + class EioProcess(Process): type = 'EioProcess' chkpt = Param.String('', "EIO checkpoint file name (optional)") diff --git a/python/m5/objects/Root.py b/python/m5/objects/Root.py index 23b13fc67..f51516098 100644 --- a/python/m5/objects/Root.py +++ b/python/m5/objects/Root.py @@ -1,5 +1,4 @@ from m5 import * -from HierParams import HierParams from Serialize import Serialize from Statistics import Statistics from Trace import Trace @@ -13,12 +12,9 @@ class Root(SimObject): "print a progress message every n ticks (0 = never)") output_file = Param.String('cout', "file to dump simulator output to") checkpoint = Param.String('', "checkpoint file to load") -# hier = Param.HierParams(HierParams(do_data = False, do_events = True), -# "shared memory hierarchy parameters") # stats = Param.Statistics(Statistics(), "statistics object") # trace = Param.Trace(Trace(), "trace object") # serialize = Param.Serialize(Serialize(), "checkpoint generation options") - hier = HierParams(do_data = False, do_events = True) stats = Statistics() trace = Trace() exetrace = ExecutionTrace() diff --git a/python/m5/objects/SimpleDisk.py b/python/m5/objects/SimpleDisk.py index 48448e6e5..e34155ace 100644 --- a/python/m5/objects/SimpleDisk.py +++ b/python/m5/objects/SimpleDisk.py @@ -2,4 +2,4 @@ from m5 import * class SimpleDisk(SimObject): type = 'SimpleDisk' disk = Param.DiskImage("Disk Image") - physmem = Param.PhysicalMemory(Parent.any, "Physical Memory") + system = Param.System(Parent.any, "Sysetm Pointer") diff --git a/python/m5/objects/System.py b/python/m5/objects/System.py index 5925cadf5..622b5a870 100644 --- a/python/m5/objects/System.py +++ b/python/m5/objects/System.py @@ -2,20 +2,20 @@ from m5 import * class System(SimObject): type = 'System' - boot_cpu_frequency = Param.Frequency(Self.cpu[0].clock.frequency, - "boot processor frequency") - memctrl = Param.MemoryController(Parent.any, "memory controller") physmem = Param.PhysicalMemory(Parent.any, "phsyical memory") - init_param = Param.UInt64(0, "numerical value to pass into simulator") - bin = Param.Bool(False, "is this system binned") - binned_fns = VectorParam.String([], "functions broken down and binned") - kernel = Param.String("file that contains the kernel code") - readfile = Param.String("", "file to read startup script from") + if build_env['FULL_SYSTEM']: + boot_cpu_frequency = Param.Frequency(Self.cpu[0].clock.frequency, + "boot processor frequency") + init_param = Param.UInt64(0, "numerical value to pass into simulator") + bin = Param.Bool(False, "is this system binned") + binned_fns = VectorParam.String([], "functions broken down and binned") + boot_osflags = Param.String("a", "boot flags to pass to the kernel") + kernel = Param.String("file that contains the kernel code") + readfile = Param.String("", "file to read startup script from") class AlphaSystem(System): type = 'AlphaSystem' console = Param.String("file that contains the console code") pal = Param.String("file that contains palcode") - boot_osflags = Param.String("a", "boot flags to pass to the kernel") system_type = Param.UInt64("Type of system we are emulating") system_rev = Param.UInt64("Revision of system we are emulating") diff --git a/python/m5/objects/Tsunami.py b/python/m5/objects/Tsunami.py index 5425f421f..27ea0bce8 100644 --- a/python/m5/objects/Tsunami.py +++ b/python/m5/objects/Tsunami.py @@ -1,27 +1,27 @@ from m5 import * -from Device import FooPioDevice +from Device import BasicPioDevice from Platform import Platform class Tsunami(Platform): type = 'Tsunami' - pciconfig = Param.PciConfigAll("PCI configuration") +# pciconfig = Param.PciConfigAll("PCI configuration") system = Param.System(Parent.any, "system") -class TsunamiCChip(FooPioDevice): +class TsunamiCChip(BasicPioDevice): type = 'TsunamiCChip' tsunami = Param.Tsunami(Parent.any, "Tsunami") -class IsaFake(FooPioDevice): +class IsaFake(BasicPioDevice): type = 'IsaFake' - size = Param.Addr("Size of address range") + pio_size = Param.Addr(0x8, "Size of address range") -class TsunamiIO(FooPioDevice): +class TsunamiIO(BasicPioDevice): type = 'TsunamiIO' time = Param.UInt64(1136073600, "System time to use (0 for actual time, default is 1/1/06)") tsunami = Param.Tsunami(Parent.any, "Tsunami") frequency = Param.Frequency('1024Hz', "frequency of interrupts") -class TsunamiPChip(FooPioDevice): +class TsunamiPChip(BasicPioDevice): type = 'TsunamiPChip' tsunami = Param.Tsunami(Parent.any, "Tsunami") diff --git a/python/m5/objects/Uart.py b/python/m5/objects/Uart.py index 6eda5cdb3..54754aeb9 100644 --- a/python/m5/objects/Uart.py +++ b/python/m5/objects/Uart.py @@ -1,11 +1,10 @@ from m5 import * -from Device import PioDevice +from Device import BasicPioDevice -class Uart(PioDevice): +class Uart(BasicPioDevice): type = 'Uart' abstract = True - console = Param.SimConsole(Parent.any, "The console") - size = Param.Addr(0x8, "Device size") + sim_console = Param.SimConsole(Parent.any, "The console") class Uart8250(Uart): type = 'Uart8250' diff --git a/sim/byteswap.hh b/sim/byteswap.hh index c5d8801ab..a8c5da9d7 100644 --- a/sim/byteswap.hh +++ b/sim/byteswap.hh @@ -38,6 +38,10 @@ // This lets us figure out what the byte order of the host system is #if defined(linux) #include <endian.h> +// If this is a linux system, lets used the optimized definitions if they exist. +// If one doesn't exist, we pretty much get what is listed below, so it all +// works out +#include <byteswap.h> #else #include <machine/endian.h> #endif @@ -47,6 +51,9 @@ static inline uint64_t swap_byte64(uint64_t x) { +#if defined(linux) + return bswap_64(x); +#else return (uint64_t)((((uint64_t)(x) & 0xff) << 56) | ((uint64_t)(x) & 0xff00ULL) << 40 | ((uint64_t)(x) & 0xff0000ULL) << 24 | @@ -55,22 +62,30 @@ swap_byte64(uint64_t x) ((uint64_t)(x) & 0xff0000000000ULL) >> 24 | ((uint64_t)(x) & 0xff000000000000ULL) >> 40 | ((uint64_t)(x) & 0xff00000000000000ULL) >> 56) ; +#endif } static inline uint32_t swap_byte32(uint32_t x) { +#if defined(linux) + return bswap_32(x); +#else return (uint32_t)(((uint32_t)(x) & 0xff) << 24 | ((uint32_t)(x) & 0xff00) << 8 | ((uint32_t)(x) & 0xff0000) >> 8 | ((uint32_t)(x) & 0xff000000) >> 24); - +#endif } static inline uint16_t swap_byte16(uint16_t x) { +#if defined(linux) + return bswap_16(x); +#else return (uint16_t)(((uint16_t)(x) & 0xff) << 8 | ((uint16_t)(x) & 0xff00) >> 8); +#endif } //This lets the compiler figure out how to call the swap_byte functions above @@ -79,7 +94,9 @@ static inline uint64_t swap_byte(uint64_t x) {return swap_byte64(x);} static inline int64_t swap_byte(int64_t x) {return swap_byte64((uint64_t)x);} static inline uint32_t swap_byte(uint32_t x) {return swap_byte32(x);} static inline int32_t swap_byte(int32_t x) {return swap_byte32((uint32_t)x);} -#if defined(__APPLE__) +//This is to prevent the following two functions from compiling on +//64bit machines. It won't detect everything, so it should be changed. +#ifndef __x86_64__ static inline long swap_byte(long x) {return swap_byte32((long)x);} static inline unsigned long swap_byte(unsigned long x) { return swap_byte32((unsigned long)x);} diff --git a/sim/faults.cc b/sim/faults.cc index 701384989..f7e9a0691 100644 --- a/sim/faults.cc +++ b/sim/faults.cc @@ -26,6 +26,7 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +#include "base/misc.hh" #include "sim/faults.hh" #include "cpu/exec_context.hh" #include "cpu/base.hh" diff --git a/sim/host.hh b/sim/host.hh index f7e64f23c..48c977331 100644 --- a/sim/host.hh +++ b/sim/host.hh @@ -62,4 +62,6 @@ typedef int64_t Tick; */ typedef uint64_t Addr; +const Addr MaxAddr = (Addr)-1; + #endif // __HOST_H__ diff --git a/sim/main.cc b/sim/main.cc index 6f6143506..aecc171ed 100644 --- a/sim/main.cc +++ b/sim/main.cc @@ -355,6 +355,10 @@ main(int argc, char **argv) echoCommandLine(argc, argv, *outputStream); ParamContext::showAllContexts(*configStream); + // Any objects that can't connect themselves until after construction should + // do so now + SimObject::connectAll(); + // Do a second pass to finish initializing the sim objects SimObject::initAll(); diff --git a/sim/process.cc b/sim/process.cc index a84a4f7ba..d88716f1e 100644 --- a/sim/process.cc +++ b/sim/process.cc @@ -37,18 +37,15 @@ #include "base/loader/symtab.hh" #include "base/statistics.hh" #include "config/full_system.hh" -#include "cpu/cpu_exec_context.hh" #include "cpu/exec_context.hh" -#include "cpu/smt.hh" -#include "encumbered/cpu/full/thread.hh" -#include "encumbered/eio/eio.hh" -#include "encumbered/mem/functional/main.hh" +#include "mem/page_table.hh" +#include "mem/physical.hh" +#include "mem/translating_port.hh" #include "sim/builder.hh" #include "sim/process.hh" #include "sim/stats.hh" #include "sim/syscall_emul.hh" - -#include "arch/process.hh" +#include "sim/system.hh" using namespace std; using namespace TheISA; @@ -66,20 +63,12 @@ using namespace TheISA; int num_processes = 0; Process::Process(const string &nm, + System *_system, int stdin_fd, // initial I/O descriptors int stdout_fd, int stderr_fd) - : SimObject(nm) + : SimObject(nm), system(_system) { - // allocate memory space - memory = new MainMemory(nm + ".MainMem"); - - // allocate initial register file - init_regs = new RegFile; - memset(init_regs, 0, sizeof(RegFile)); - - cpuXC = new CPUExecContext(init_regs); - // initialize first 3 fds (stdin, stdout, stderr) fd_map[STDIN_FILENO] = stdin_fd; fd_map[STDOUT_FILENO] = stdout_fd; @@ -92,9 +81,11 @@ Process::Process(const string &nm, mmap_start = mmap_end = 0; nxm_start = nxm_end = 0; + pTable = new PageTable(system); // other parameters will be initialized when the program is loaded } + void Process::regStats() { @@ -146,13 +137,7 @@ Process::registerExecContext(ExecContext *xc) int myIndex = execContexts.size(); execContexts.push_back(xc); - if (myIndex == 0) { - // copy process's initial regs struct - // Hack for now to copy init regs - xc->copyArchRegs(cpuXC->getProxy()); - } - - // return CPU number to caller and increment available CPU count + // return CPU number to caller return myIndex; } @@ -160,13 +145,19 @@ void Process::startup() { if (execContexts.empty()) - return; + fatal("Process %s is not associated with any CPUs!\n", name()); // first exec context for this process... initialize & enable ExecContext *xc = execContexts[0]; // mark this context as active so it will start ticking. xc->activate(0); + + Port *mem_port; + mem_port = system->physmem->getPort("functional"); + initVirtMem = new TranslatingPort(pTable, true); + mem_port->setPeer(initVirtMem); + initVirtMem->setPeer(mem_port); } void @@ -249,40 +240,33 @@ DEFINE_SIM_OBJECT_CLASS_NAME("Process", Process) //////////////////////////////////////////////////////////////////////// -static void +void copyStringArray(vector<string> &strings, Addr array_ptr, Addr data_ptr, - FunctionalMemory *memory) + TranslatingPort* memPort) { Addr data_ptr_swap; for (int i = 0; i < strings.size(); ++i) { data_ptr_swap = htog(data_ptr); - memory->access(Write, array_ptr, &data_ptr_swap, sizeof(Addr)); - memory->writeString(data_ptr, strings[i].c_str()); + memPort->writeBlob(array_ptr, (uint8_t*)&data_ptr_swap, sizeof(Addr)); + memPort->writeString(data_ptr, strings[i].c_str()); array_ptr += sizeof(Addr); data_ptr += strings[i].size() + 1; } // add NULL terminator data_ptr = 0; - memory->access(Write, array_ptr, &data_ptr, sizeof(Addr)); + + memPort->writeBlob(array_ptr, (uint8_t*)&data_ptr, sizeof(Addr)); } -LiveProcess::LiveProcess(const string &nm, ObjectFile *objFile, +LiveProcess::LiveProcess(const string &nm, ObjectFile *_objFile, + System *_system, int stdin_fd, int stdout_fd, int stderr_fd, - vector<string> &argv, vector<string> &envp) - : Process(nm, stdin_fd, stdout_fd, stderr_fd) + vector<string> &_argv, vector<string> &_envp) + : Process(nm, _system, stdin_fd, stdout_fd, stderr_fd), + objFile(_objFile), argv(_argv), envp(_envp) { prog_fname = argv[0]; - prog_entry = objFile->entryPoint(); - text_base = objFile->textBase(); - text_size = objFile->textSize(); - data_base = objFile->dataBase(); - data_size = objFile->dataSize() + objFile->bssSize(); - brk_point = roundUp(data_base + data_size, VMPageSize); - - // load object file into target memory - objFile->loadSections(memory); - // load up symbols, if any... these may be used for debugging or // profiling. if (!debugSymbolTable) { @@ -294,21 +278,19 @@ LiveProcess::LiveProcess(const string &nm, ObjectFile *objFile, debugSymbolTable = NULL; } } +} - // Set up stack. On Alpha, stack goes below text section. This - // code should get moved to some architecture-specific spot. - stack_base = text_base - (409600+4096); - - // Set up region for mmaps. Tru64 seems to start just above 0 and - // grow up from there. - mmap_start = mmap_end = 0x10000; +void +LiveProcess::argsInit(int intSize, int pageSize) +{ + Process::startup(); - // Set pointer for next thread stack. Reserve 8M for main stack. - next_thread_stack_base = stack_base - (8 * 1024 * 1024); + // load object file into target memory + objFile->loadSections(initVirtMem); // Calculate how much space we need for arg & env arrays. - int argv_array_size = sizeof(Addr) * (argv.size() + 1); - int envp_array_size = sizeof(Addr) * (envp.size() + 1); + int argv_array_size = intSize * (argv.size() + 1); + int envp_array_size = intSize * (envp.size() + 1); int arg_data_size = 0; for (int i = 0; i < argv.size(); ++i) { arg_data_size += argv[i].size() + 1; @@ -327,38 +309,49 @@ LiveProcess::LiveProcess(const string &nm, ObjectFile *objFile, // set bottom of stack stack_min = stack_base - space_needed; // align it - stack_min &= ~7; + stack_min &= ~(intSize-1); stack_size = stack_base - stack_min; + // map memory + pTable->allocate(roundDown(stack_min, pageSize), + roundUp(stack_size, pageSize)); // map out initial stack contents - Addr argv_array_base = stack_min + sizeof(uint64_t); // room for argc + Addr argv_array_base = stack_min + intSize; // room for argc Addr envp_array_base = argv_array_base + argv_array_size; Addr arg_data_base = envp_array_base + envp_array_size; Addr env_data_base = arg_data_base + arg_data_size; // write contents to stack uint64_t argc = argv.size(); - argc = htog(argc); - memory->access(Write, stack_min, &argc, sizeof(uint64_t)); - - copyStringArray(argv, argv_array_base, arg_data_base, memory); - copyStringArray(envp, envp_array_base, env_data_base, memory); - - cpuXC->setIntReg(ArgumentReg0, argc); - cpuXC->setIntReg(ArgumentReg1, argv_array_base); - cpuXC->setIntReg(StackPointerReg, stack_min); - cpuXC->setIntReg(GlobalPointerReg, objFile->globalPointer()); - cpuXC->setPC(prog_entry); - cpuXC->setNextPC(prog_entry + sizeof(MachInst)); + 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); + + execContexts[0]->setIntReg(ArgumentReg0, argc); + execContexts[0]->setIntReg(ArgumentReg1, argv_array_base); + execContexts[0]->setIntReg(StackPointerReg, stack_min); + + Addr prog_entry = objFile->entryPoint(); + execContexts[0]->setPC(prog_entry); + execContexts[0]->setNextPC(prog_entry + sizeof(MachInst)); + execContexts[0]->setNextNPC(prog_entry + (2 * sizeof(MachInst))); + + num_processes++; } void -LiveProcess::syscall(ExecContext *xc) +LiveProcess::syscall(int64_t callnum, ExecContext *xc) { num_syscalls++; - int64_t callnum = xc->readIntReg(SyscallNumReg); - SyscallDesc *desc = getDesc(callnum); if (desc == NULL) fatal("Syscall %d out of range", callnum); @@ -366,81 +359,4 @@ LiveProcess::syscall(ExecContext *xc) desc->doSyscall(callnum, this, xc); } -LiveProcess * -LiveProcess::create(const string &nm, - int stdin_fd, int stdout_fd, int stderr_fd, - string executable, - vector<string> &argv, vector<string> &envp) -{ - LiveProcess *process = NULL; - ObjectFile *objFile = createObjectFile(executable); - if (objFile == NULL) { - fatal("Can't load object file %s", executable); - } - - // set up syscall emulation pointer for the current ISA - process = createProcess(nm, objFile, - stdin_fd, stdout_fd, stderr_fd, - argv, envp); - - delete objFile; - - if (process == NULL) - fatal("Unknown error creating process object."); - - return process; -} - - - -BEGIN_DECLARE_SIM_OBJECT_PARAMS(LiveProcess) - - VectorParam<string> cmd; - Param<string> executable; - Param<string> input; - Param<string> output; - VectorParam<string> env; - -END_DECLARE_SIM_OBJECT_PARAMS(LiveProcess) - - -BEGIN_INIT_SIM_OBJECT_PARAMS(LiveProcess) - - INIT_PARAM(cmd, "command line (executable plus arguments)"), - INIT_PARAM(executable, "executable (overrides cmd[0] if set)"), - INIT_PARAM(input, "filename for stdin (dflt: use sim stdin)"), - INIT_PARAM(output, "filename for stdout/stderr (dflt: use sim stdout)"), - INIT_PARAM(env, "environment settings") - -END_INIT_SIM_OBJECT_PARAMS(LiveProcess) - - -CREATE_SIM_OBJECT(LiveProcess) -{ - string in = input; - string out = output; - - // initialize file descriptors to default: same as simulator - int stdin_fd, stdout_fd, stderr_fd; - - if (in == "stdin" || in == "cin") - stdin_fd = STDIN_FILENO; - else - stdin_fd = Process::openInputFile(input); - - if (out == "stdout" || out == "cout") - stdout_fd = STDOUT_FILENO; - else if (out == "stderr" || out == "cerr") - stdout_fd = STDERR_FILENO; - else - stdout_fd = Process::openOutputFile(out); - - stderr_fd = (stdout_fd != STDOUT_FILENO) ? stdout_fd : STDERR_FILENO; - - return LiveProcess::create(getInstanceName(), - stdin_fd, stdout_fd, stderr_fd, - (string)executable == "" ? cmd[0] : executable, - cmd, env); -} - -REGISTER_SIM_OBJECT("LiveProcess", LiveProcess) +DEFINE_SIM_OBJECT_CLASS_NAME("LiveProcess", LiveProcess); diff --git a/sim/process.hh b/sim/process.hh index 3a48f128c..807bf330f 100644 --- a/sim/process.hh +++ b/sim/process.hh @@ -40,23 +40,28 @@ #include <vector> -#include "arch/isa_traits.hh" -#include "sim/sim_object.hh" -#include "sim/stats.hh" #include "base/statistics.hh" -#include "base/trace.hh" +#include "sim/sim_object.hh" class CPUExecContext; class ExecContext; -class FunctionalMemory; class SyscallDesc; +class PageTable; +class TranslatingPort; +class System; + +void +copyStringArray(std::vector<std::string> &strings, Addr array_ptr, + Addr data_ptr, TranslatingPort* memPort); + class Process : public SimObject { - protected: - typedef TheISA::RegFile RegFile; - typedef TheISA::MachInst MachInst; public: + /// Pointer to object representing the system this process is + /// running on. + System *system; + // have we initialized an execution context from this process? If // yes, subsequent contexts are assumed to be for dynamically // created threads and are not initialized. @@ -76,22 +81,12 @@ class Process : public SimObject WaitRec(Addr chan, ExecContext *ctx) : waitChan(chan), waitingContext(ctx) - { - } + { } }; // list of all blocked contexts std::list<WaitRec> waitList; - RegFile *init_regs; // initial register contents - CPUExecContext *cpuXC; // XC to hold the init_regs - - Addr text_base; // text (code) segment base - unsigned text_size; // text (code) size in bytes - - Addr data_base; // initialized data segment base - unsigned data_size; // initialized data + bss size in bytes - Addr brk_point; // top of the data segment Addr stack_base; // stack segment base (highest address) @@ -110,7 +105,6 @@ class Process : public SimObject Addr nxm_end; std::string prog_fname; // file name - Addr prog_entry; // entry point (initial PC) Stats::Scalar<> num_syscalls; // number of syscalls executed @@ -118,6 +112,7 @@ class Process : public SimObject protected: // constructor Process(const std::string &nm, + System *_system, int stdin_fd, // initial I/O descriptors int stdout_fd, int stderr_fd); @@ -126,7 +121,11 @@ class Process : public SimObject virtual void startup(); protected: - FunctionalMemory *memory; + /// Memory object for initialization (image loading) + TranslatingPort *initVirtMem; + + public: + PageTable *pTable; private: // file descriptor remapping support @@ -160,29 +159,7 @@ class Process : public SimObject // look up simulator fd for given target fd int sim_fd(int tgt_fd); - // is this a valid instruction fetch address? - bool validInstAddr(Addr addr) - { - return (text_base <= addr && - addr < text_base + text_size && - !(addr & (sizeof(MachInst)-1))); - } - - // is this a valid address? (used to filter data fetches) - // note that we just assume stack size <= 16MB - // this may be alpha-specific - bool validDataAddr(Addr addr) - { - return ((data_base <= addr && addr < brk_point) || - (next_thread_stack_base <= addr && addr < stack_base) || - (text_base <= addr && addr < (text_base + text_size)) || - (mmap_start <= addr && addr < mmap_end) || - (nxm_start <= addr && addr < nxm_end)); - } - - virtual void syscall(ExecContext *xc) = 0; - - virtual FunctionalMemory *getMemory() { return memory; } + virtual void syscall(int64_t callnum, ExecContext *xc) = 0; }; // @@ -192,25 +169,21 @@ class ObjectFile; class LiveProcess : public Process { protected: + ObjectFile *objFile; + std::vector<std::string> argv; + std::vector<std::string> envp; + LiveProcess(const std::string &nm, ObjectFile *objFile, - int stdin_fd, int stdout_fd, int stderr_fd, + System *_system, int stdin_fd, int stdout_fd, int stderr_fd, std::vector<std::string> &argv, std::vector<std::string> &envp); - public: - // this function is used to create the LiveProcess object, since - // we can't tell which subclass of LiveProcess to use until we - // open and look at the object file. - static LiveProcess *create(const std::string &nm, - int stdin_fd, int stdout_fd, int stderr_fd, - std::string executable, - std::vector<std::string> &argv, - std::vector<std::string> &envp); - - virtual void syscall(ExecContext *xc); + virtual void argsInit(int intSize, int pageSize); - virtual SyscallDesc* getDesc(int callnum) { panic("Must be implemented."); } + public: + virtual void syscall(int64_t callnum, ExecContext *xc); + virtual SyscallDesc* getDesc(int callnum) = 0; }; diff --git a/sim/pseudo_inst.cc b/sim/pseudo_inst.cc index e475006e7..3cdc05e78 100644 --- a/sim/pseudo_inst.cc +++ b/sim/pseudo_inst.cc @@ -175,7 +175,7 @@ namespace AlphaPseudo addsymbol(ExecContext *xc, Addr addr, Addr symbolAddr) { char symb[100]; - CopyString(xc, symb, symbolAddr, 100); + CopyStringOut(xc, symb, symbolAddr, 100); std::string symbol(symb); DPRINTF(Loader, "Loaded symbol: %s @ %#llx\n", symbol, addr); diff --git a/sim/sim_object.cc b/sim/sim_object.cc index f34e17fe6..17d58ba4f 100644 --- a/sim/sim_object.cc +++ b/sim/sim_object.cc @@ -34,6 +34,7 @@ #include "base/misc.hh" #include "base/trace.hh" #include "base/stats/events.hh" +#include "base/serializer.hh" #include "sim/configfile.hh" #include "sim/host.hh" #include "sim/sim_object.hh" @@ -88,6 +89,11 @@ SimObject::SimObject(const string &_name) } void +SimObject::connect() +{ +} + +void SimObject::init() { } @@ -151,6 +157,21 @@ SimObject::regAllStats() } // +// static function: call connect() on all SimObjects. +// +void +SimObject::connectAll() +{ + SimObjectList::iterator i = simObjectList.begin(); + SimObjectList::iterator end = simObjectList.end(); + + for (; i != end; ++i) { + SimObject *obj = *i; + obj->connect(); + } +} + +// // static function: call init() on all SimObjects. // void @@ -228,4 +249,10 @@ SimObject::recordEvent(const std::string &stat) Stats::recordEvent(stat); } +void +SimObject::drain(Serializer *serializer) +{ + serializer->signalDrained(); +} + DEFINE_SIM_OBJECT_CLASS_NAME("SimObject", SimObject) diff --git a/sim/sim_object.hh b/sim/sim_object.hh index 59d9daf45..76aba7ea1 100644 --- a/sim/sim_object.hh +++ b/sim/sim_object.hh @@ -41,6 +41,8 @@ #include "sim/serialize.hh" #include "sim/startup.hh" +class Serializer; + /* * Abstract superclass for simulation objects. Represents things that * correspond to physical components and can be specified via the @@ -78,7 +80,9 @@ class SimObject : public Serializable, protected StartupCallback // initialization pass of all objects. // Gets invoked after construction, before unserialize. virtual void init(); + virtual void connect(); static void initAll(); + static void connectAll(); // register statistics for this object virtual void regStats(); @@ -94,6 +98,13 @@ class SimObject : public Serializable, protected StartupCallback // static: call nameOut() & serialize() on all SimObjects static void serializeAll(std::ostream &); + // Methods to drain objects in order to take checkpoints + // Or switch from timing -> atomic memory model + virtual void drain(Serializer *serializer); + virtual void resume() { return;} ; + virtual void serializationComplete() + { assert(0 && "Unimplemented"); }; + #ifdef DEBUG public: bool doDebugBreak; diff --git a/sim/syscall_emul.cc b/sim/syscall_emul.cc index 00168b025..ed0da628e 100644 --- a/sim/syscall_emul.cc +++ b/sim/syscall_emul.cc @@ -33,9 +33,11 @@ #include <iostream> #include "sim/syscall_emul.hh" +#include "base/chunk_generator.hh" #include "base/trace.hh" #include "cpu/exec_context.hh" #include "cpu/base.hh" +#include "mem/page_table.hh" #include "sim/process.hh" #include "sim/sim_events.hh" @@ -46,13 +48,15 @@ using namespace TheISA; void SyscallDesc::doSyscall(int callnum, Process *process, ExecContext *xc) { - DPRINTFR(SyscallVerbose, "%s: syscall %s called\n", - xc->getCpuPtr()->name(), name); + DPRINTFR(SyscallVerbose, "%d: %s: syscall %s called w/arguments %d,%d,%d,%d\n", + curTick,xc->getCpuPtr()->name(), name, + xc->getSyscallArg(0),xc->getSyscallArg(1), + xc->getSyscallArg(2),xc->getSyscallArg(3)); SyscallReturn retval = (*funcPtr)(this, callnum, process, xc); - DPRINTFR(SyscallVerbose, "%s: syscall %s returns %d\n", - xc->getCpuPtr()->name(), name, retval.value()); + DPRINTFR(SyscallVerbose, "%d: %s: syscall %s returns %d\n", + curTick,xc->getCpuPtr()->name(), name, retval.value()); if (!(flags & SyscallDesc::SuppressReturnValue)) xc->setSyscallReturn(retval); @@ -64,6 +68,8 @@ unimplementedFunc(SyscallDesc *desc, int callnum, Process *process, ExecContext *xc) { fatal("syscall %s (#%d) unimplemented.", desc->name, callnum); + + return 1; } @@ -82,7 +88,7 @@ SyscallReturn exitFunc(SyscallDesc *desc, int callnum, Process *process, ExecContext *xc) { - new SimExitEvent("syscall caused exit", xc->getSyscallArg(0) & 0xff); + new SimExitEvent("target called exit()", xc->getSyscallArg(0) & 0xff); return 1; } @@ -98,11 +104,18 @@ getpagesizeFunc(SyscallDesc *desc, int num, Process *p, ExecContext *xc) SyscallReturn obreakFunc(SyscallDesc *desc, int num, Process *p, ExecContext *xc) { + Addr junk; + // change brk addr to first arg Addr new_brk = xc->getSyscallArg(0); - if (new_brk != 0) - { - p->brk_point = xc->getSyscallArg(0); + if (new_brk != 0) { + for (ChunkGenerator gen(p->brk_point, new_brk - p->brk_point, + VMPageSize); !gen.done(); gen.next()) { + if (!p->pTable->translate(gen.addr(), junk)) + p->pTable->allocate(roundDown(gen.addr(), VMPageSize), + VMPageSize); + } + p->brk_point = new_brk; } DPRINTF(SyscallVerbose, "Break Point changed to: %#X\n", p->brk_point); return p->brk_point; @@ -130,7 +143,7 @@ readFunc(SyscallDesc *desc, int num, Process *p, ExecContext *xc) int bytes_read = read(fd, bufArg.bufferPtr(), nbytes); if (bytes_read != -1) - bufArg.copyOut(xc->getMemPtr()); + bufArg.copyOut(xc->getMemPort()); return bytes_read; } @@ -142,7 +155,7 @@ writeFunc(SyscallDesc *desc, int num, Process *p, ExecContext *xc) int nbytes = xc->getSyscallArg(2); BufferArg bufArg(xc->getSyscallArg(1), nbytes); - bufArg.copyIn(xc->getMemPtr()); + bufArg.copyIn(xc->getMemPort()); int bytes_written = write(fd, bufArg.bufferPtr(), nbytes); @@ -183,7 +196,7 @@ gethostnameFunc(SyscallDesc *desc, int num, Process *p, ExecContext *xc) strncpy((char *)name.bufferPtr(), hostname, name_len); - name.copyOut(xc->getMemPtr()); + name.copyOut(xc->getMemPort()); return 0; } @@ -193,7 +206,7 @@ unlinkFunc(SyscallDesc *desc, int num, Process *p, ExecContext *xc) { string path; - if (xc->getMemPtr()->readString(path, xc->getSyscallArg(0)) != NoFault) + if (!xc->getMemPort()->tryReadString(path, xc->getSyscallArg(0))) return (TheISA::IntReg)-EFAULT; int result = unlink(path.c_str()); @@ -205,12 +218,12 @@ renameFunc(SyscallDesc *desc, int num, Process *p, ExecContext *xc) { string old_name; - if (xc->getMemPtr()->readString(old_name, xc->getSyscallArg(0)) != NoFault) + if (!xc->getMemPort()->tryReadString(old_name, xc->getSyscallArg(0))) return -EFAULT; string new_name; - if (xc->getMemPtr()->readString(new_name, xc->getSyscallArg(1)) != NoFault) + if (!xc->getMemPort()->tryReadString(new_name, xc->getSyscallArg(1))) return -EFAULT; int64_t result = rename(old_name.c_str(), new_name.c_str()); @@ -222,7 +235,7 @@ truncateFunc(SyscallDesc *desc, int num, Process *p, ExecContext *xc) { string path; - if (xc->getMemPtr()->readString(path, xc->getSyscallArg(0)) != NoFault) + if (!xc->getMemPort()->tryReadString(path, xc->getSyscallArg(0))) return -EFAULT; off_t length = xc->getSyscallArg(1); @@ -250,7 +263,7 @@ chownFunc(SyscallDesc *desc, int num, Process *p, ExecContext *xc) { string path; - if (xc->getMemPtr()->readString(path, xc->getSyscallArg(0)) != NoFault) + if (!xc->getMemPort()->tryReadString(path, xc->getSyscallArg(0))) return -EFAULT; /* XXX endianess */ diff --git a/sim/syscall_emul.hh b/sim/syscall_emul.hh index 35129bcb4..00f016410 100644 --- a/sim/syscall_emul.hh +++ b/sim/syscall_emul.hh @@ -45,12 +45,15 @@ #endif #include <sys/uio.h> -#include "base/intmath.hh" // for RoundUp -#include "mem/functional/functional.hh" #include "arch/isa_traits.hh" // for Addr - +#include "base/chunk_generator.hh" +#include "base/intmath.hh" // for RoundUp +#include "base/misc.hh" #include "base/trace.hh" +#include "cpu/base.hh" #include "cpu/exec_context.hh" +#include "mem/translating_port.hh" +#include "mem/page_table.hh" #include "sim/process.hh" /// @@ -106,18 +109,18 @@ class BaseBufferArg { // // copy data into simulator space (read from target memory) // - virtual bool copyIn(FunctionalMemory *mem) + virtual bool copyIn(TranslatingPort *memport) { - mem->access(Read, addr, bufPtr, size); + memport->readBlob(addr, bufPtr, size); return true; // no EFAULT detection for now } // // copy data out of simulator space (write to target memory) // - virtual bool copyOut(FunctionalMemory *mem) + virtual bool copyOut(TranslatingPort *memport) { - mem->access(Write, addr, bufPtr, size); + memport->writeBlob(addr, bufPtr, size); return true; // no EFAULT detection for now } @@ -369,7 +372,7 @@ openFunc(SyscallDesc *desc, int callnum, Process *process, { std::string path; - if (xc->getMemPtr()->readString(path, xc->getSyscallArg(0)) != NoFault) + if (!xc->getMemPort()->tryReadString(path, xc->getSyscallArg(0))) return -EFAULT; if (path == "/dev/sysdev0") { @@ -416,7 +419,7 @@ chmodFunc(SyscallDesc *desc, int callnum, Process *process, { std::string path; - if (xc->getMemPtr()->readString(path, xc->getSyscallArg(0)) != NoFault) + if (!xc->getMemPort()->tryReadString(path, xc->getSyscallArg(0))) return -EFAULT; uint32_t mode = xc->getSyscallArg(1); @@ -469,8 +472,8 @@ statFunc(SyscallDesc *desc, int callnum, Process *process, { std::string path; - if (xc->getMemPtr()->readString(path, xc->getSyscallArg(0)) != NoFault) - return -EFAULT; + if (!xc->getMemPort()->tryReadString(path, xc->getSyscallArg(0))) + return -EFAULT; struct stat hostBuf; int result = stat(path.c_str(), &hostBuf); @@ -478,7 +481,7 @@ statFunc(SyscallDesc *desc, int callnum, Process *process, if (result < 0) return -errno; - OS::copyOutStatBuf(xc->getMemPtr(), xc->getSyscallArg(1), &hostBuf); + OS::copyOutStatBuf(xc->getMemPort(), xc->getSyscallArg(1), &hostBuf); return 0; } @@ -507,7 +510,7 @@ fstat64Func(SyscallDesc *desc, int callnum, Process *process, if (result < 0) return -errno; - OS::copyOutStat64Buf(xc->getMemPtr(), fd, xc->getSyscallArg(1), &hostBuf); + OS::copyOutStat64Buf(xc->getMemPort(), fd, xc->getSyscallArg(1), &hostBuf); return 0; } @@ -521,8 +524,8 @@ lstatFunc(SyscallDesc *desc, int callnum, Process *process, { std::string path; - if (xc->getMemPtr()->readString(path, xc->getSyscallArg(0)) != NoFault) - return -EFAULT; + if (!xc->getMemPort()->tryReadString(path, xc->getSyscallArg(0))) + return -EFAULT; struct stat hostBuf; int result = lstat(path.c_str(), &hostBuf); @@ -530,7 +533,7 @@ lstatFunc(SyscallDesc *desc, int callnum, Process *process, if (result < 0) return -errno; - OS::copyOutStatBuf(xc->getMemPtr(), xc->getSyscallArg(1), &hostBuf); + OS::copyOutStatBuf(xc->getMemPort(), xc->getSyscallArg(1), &hostBuf); return 0; } @@ -543,8 +546,8 @@ lstat64Func(SyscallDesc *desc, int callnum, Process *process, { std::string path; - if (xc->getMemPtr()->readString(path, xc->getSyscallArg(0)) != NoFault) - return -EFAULT; + if (!xc->getMemPort()->tryReadString(path, xc->getSyscallArg(0))) + return -EFAULT; #if BSD_HOST struct stat hostBuf; @@ -557,7 +560,7 @@ lstat64Func(SyscallDesc *desc, int callnum, Process *process, if (result < 0) return -errno; - OS::copyOutStat64Buf(xc->getMemPtr(), -1, xc->getSyscallArg(1), &hostBuf); + OS::copyOutStat64Buf(xc->getMemPort(), -1, xc->getSyscallArg(1), &hostBuf); return 0; } @@ -581,7 +584,8 @@ fstatFunc(SyscallDesc *desc, int callnum, Process *process, if (result < 0) return -errno; - OS::copyOutStatBuf(xc->getMemPtr(), xc->getSyscallArg(1), &hostBuf); + OS::copyOutStatBuf(xc->getMemPort(), xc->getSyscallArg(1), &hostBuf); + return 0; } @@ -594,8 +598,8 @@ statfsFunc(SyscallDesc *desc, int callnum, Process *process, { std::string path; - if (xc->getMemPtr()->readString(path, xc->getSyscallArg(0)) != NoFault) - return -EFAULT; + if (!xc->getMemPort()->tryReadString(path, xc->getSyscallArg(0))) + return -EFAULT; struct statfs hostBuf; int result = statfs(path.c_str(), &hostBuf); @@ -603,7 +607,7 @@ statfsFunc(SyscallDesc *desc, int callnum, Process *process, if (result < 0) return -errno; - OS::copyOutStatfsBuf(xc->getMemPtr(), xc->getSyscallArg(1), &hostBuf); + OS::copyOutStatfsBuf(xc->getMemPort(), xc->getSyscallArg(1), &hostBuf); return 0; } @@ -626,7 +630,7 @@ fstatfsFunc(SyscallDesc *desc, int callnum, Process *process, if (result < 0) return -errno; - OS::copyOutStatfsBuf(xc->getMemPtr(), xc->getSyscallArg(1), &hostBuf); + OS::copyOutStatfsBuf(xc->getMemPort(), xc->getSyscallArg(1), &hostBuf); return 0; } @@ -644,18 +648,20 @@ writevFunc(SyscallDesc *desc, int callnum, Process *process, return -EBADF; } + TranslatingPort *p = xc->getMemPort(); uint64_t tiov_base = xc->getSyscallArg(1); size_t count = xc->getSyscallArg(2); struct iovec hiov[count]; for (int i = 0; i < count; ++i) { typename OS::tgt_iovec tiov; - xc->getMemPtr()->access(Read, tiov_base + i*sizeof(typename OS::tgt_iovec), - &tiov, sizeof(typename OS::tgt_iovec)); + + p->readBlob(tiov_base + i*sizeof(typename OS::tgt_iovec), + (uint8_t*)&tiov, sizeof(typename OS::tgt_iovec)); hiov[i].iov_len = gtoh(tiov.iov_len); hiov[i].iov_base = new char [hiov[i].iov_len]; - xc->getMemPtr()->access(Read, gtoh(tiov.iov_base), - hiov[i].iov_base, hiov[i].iov_len); + p->readBlob(gtoh(tiov.iov_base), (uint8_t *)hiov[i].iov_base, + hiov[i].iov_len); } int result = writev(process->sim_fd(fd), hiov, count); @@ -695,16 +701,24 @@ mmapFunc(SyscallDesc *desc, int num, Process *p, ExecContext *xc) // int fd = p->sim_fd(xc->getSyscallArg(4)); // int offset = xc->getSyscallArg(5); - if (start == 0) { - // user didn't give an address... pick one from our "mmap region" - start = p->mmap_end; - p->mmap_end += roundUp(length, TheISA::VMPageSize); - if (p->nxm_start != 0) { - //If we have an nxm space, make sure we haven't colided - assert(p->mmap_end < p->nxm_start); - } + if ((start % TheISA::VMPageSize) != 0 || + (length % TheISA::VMPageSize) != 0) { + warn("mmap failing: arguments not page-aligned: " + "start 0x%x length 0x%x", + start, length); + return -EINVAL; + } + + if (start != 0) { + warn("mmap: ignoring suggested map address 0x%x, using 0x%x", + start, p->mmap_end); } + // pick next address from our "mmap region" + start = p->mmap_end; + 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.", xc->getSyscallArg(4)); @@ -737,7 +751,7 @@ getrlimitFunc(SyscallDesc *desc, int callnum, Process *process, break; } - rlp.copyOut(xc->getMemPtr()); + rlp.copyOut(xc->getMemPort()); return 0; } @@ -754,7 +768,7 @@ gettimeofdayFunc(SyscallDesc *desc, int callnum, Process *process, tp->tv_sec = htog(tp->tv_sec); tp->tv_usec = htog(tp->tv_usec); - tp.copyOut(xc->getMemPtr()); + tp.copyOut(xc->getMemPort()); return 0; } @@ -768,11 +782,11 @@ utimesFunc(SyscallDesc *desc, int callnum, Process *process, { std::string path; - if (xc->getMemPtr()->readString(path, xc->getSyscallArg(0)) != NoFault) - return -EFAULT; + if (!xc->getMemPort()->tryReadString(path, xc->getSyscallArg(0))) + return -EFAULT; TypedBufferArg<typename OS::timeval [2]> tp(xc->getSyscallArg(1)); - tp.copyIn(xc->getMemPtr()); + tp.copyIn(xc->getMemPort()); struct timeval hostTimeval[2]; for (int i = 0; i < 2; ++i) @@ -824,9 +838,12 @@ getrusageFunc(SyscallDesc *desc, int callnum, Process *process, rup->ru_nvcsw = 0; rup->ru_nivcsw = 0; - rup.copyOut(xc->getMemPtr()); + rup.copyOut(xc->getMemPort()); return 0; } + + + #endif // __SIM_SYSCALL_EMUL_HH__ diff --git a/sim/system.cc b/sim/system.cc index 8820922c1..ca9d68d77 100644 --- a/sim/system.cc +++ b/sim/system.cc @@ -1,16 +1,18 @@ +#include "arch/isa_traits.hh" #include "base/loader/object_file.hh" #include "base/loader/symtab.hh" -#include "base/remote_gdb.hh" +#include "base/trace.hh" #include "cpu/exec_context.hh" -#include "kern/kernel_stats.hh" -#include "mem/functional/memory_control.hh" -#include "mem/functional/physical.hh" -#include "arch/vtophys.hh" +#include "mem/mem_object.hh" +#include "mem/physical.hh" #include "sim/builder.hh" -#include "arch/isa_traits.hh" #include "sim/byteswap.hh" #include "sim/system.hh" -#include "base/trace.hh" +#if FULL_SYSTEM +#include "arch/vtophys.hh" +#include "base/remote_gdb.hh" +#include "kern/kernel_stats.hh" +#endif using namespace std; using namespace TheISA; @@ -20,15 +22,35 @@ vector<System *> System::systemList; int System::numSystemsRunning = 0; System::System(Params *p) - : SimObject(p->name), memctrl(p->memctrl), physmem(p->physmem), - init_param(p->init_param), numcpus(0), _params(p) + : SimObject(p->name), physmem(p->physmem), numcpus(0), +#if FULL_SYSTEM + init_param(p->init_param), +#else + page_ptr(0), +#endif + _params(p) { // add self to global system list systemList.push_back(this); +#if FULL_SYSTEM kernelSymtab = new SymbolTable; debugSymbolTable = new SymbolTable; + + /** + * Get a functional port to memory + */ + Port *mem_port; + mem_port = physmem->getPort("functional"); + functionalPort.setPeer(mem_port); + mem_port->setPeer(&functionalPort); + + mem_port = physmem->getPort("functional"); + virtPort.setPeer(mem_port); + mem_port->setPeer(&virtPort); + + /** * Load the kernel code into memory */ @@ -38,7 +60,7 @@ System::System(Params *p) fatal("Could not load kernel file %s", params()->kernel_path); // Load program sections into memory - kernel->loadSections(physmem, true); + kernel->loadSections(&functionalPort, LoadAddrMask); // setup entry points kernelStart = kernel->textBase(); @@ -63,25 +85,33 @@ System::System(Params *p) DPRINTF(Loader, "Kernel entry = %#x\n", kernelEntry); DPRINTF(Loader, "Kernel loaded...\n"); + kernelBinning = new Kernel::Binning(this); +#endif // FULL_SYSTEM + // increment the number of running systms numSystemsRunning++; - - kernelBinning = new Kernel::Binning(this); } System::~System() { +#if FULL_SYSTEM delete kernelSymtab; delete kernel; delete kernelBinning; +#else + panic("System::fixFuncEventAddr needs to be rewritten " + "to work with syscall emulation"); +#endif // FULL_SYSTEM} } - +#if FULL_SYSTEM int rgdb_wait = -1; +#endif // FULL_SYSTEM + int System::registerExecContext(ExecContext *xc, int id) { @@ -101,6 +131,7 @@ System::registerExecContext(ExecContext *xc, int id) execContexts[id] = xc; numcpus++; +#if FULL_SYSTEM RemoteGDB *rgdb = new RemoteGDB(this, xc); GDBListener *gdbl = new GDBListener(rgdb, 7000 + id); gdbl->listen(); @@ -116,6 +147,7 @@ System::registerExecContext(ExecContext *xc, int id) } remoteGDB[id] = rgdb; +#endif // FULL_SYSTEM return id; } @@ -137,30 +169,48 @@ System::replaceExecContext(ExecContext *xc, int id) } execContexts[id] = xc; +#if FULL_SYSTEM remoteGDB[id]->replaceExecContext(xc); +#endif // FULL_SYSTEM +} + +#if !FULL_SYSTEM +Addr +System::new_page() +{ + Addr return_addr = page_ptr << LogVMPageSize; + ++page_ptr; + return return_addr; } +#endif void System::regStats() { +#if FULL_SYSTEM kernelBinning->regStats(name() + ".kern"); +#endif // FULL_SYSTEM } void System::serialize(ostream &os) { +#if FULL_SYSTEM kernelBinning->serialize(os); kernelSymtab->serialize("kernel_symtab", os); +#endif // FULL_SYSTEM } void System::unserialize(Checkpoint *cp, const string §ion) { +#if FULL_SYSTEM kernelBinning->unserialize(cp, section); kernelSymtab->unserialize("kernel_symtab", cp, section); +#endif // FULL_SYSTEM } void @@ -181,5 +231,35 @@ printSystems() System::printSystems(); } +#if FULL_SYSTEM + +// In full system mode, only derived classes (e.g. AlphaLinuxSystem) +// can be created directly. + DEFINE_SIM_OBJECT_CLASS_NAME("System", System) +#else + +BEGIN_DECLARE_SIM_OBJECT_PARAMS(System) + + SimObjectParam<PhysicalMemory *> physmem; + +END_DECLARE_SIM_OBJECT_PARAMS(System) + +BEGIN_INIT_SIM_OBJECT_PARAMS(System) + + INIT_PARAM(physmem, "physical memory") + +END_INIT_SIM_OBJECT_PARAMS(System) + +CREATE_SIM_OBJECT(System) +{ + System::Params *p = new System::Params; + p->name = getInstanceName(); + p->physmem = physmem; + return new System(p); +} + +REGISTER_SIM_OBJECT("System", System) + +#endif diff --git a/sim/system.hh b/sim/system.hh index ea482a102..7e21bd587 100644 --- a/sim/system.hh +++ b/sim/system.hh @@ -32,30 +32,34 @@ #include <string> #include <vector> -#include "base/statistics.hh" #include "base/loader/symtab.hh" +#include "base/misc.hh" +#include "base/statistics.hh" #include "cpu/pc_event.hh" -#include "kern/system_events.hh" +#include "mem/port.hh" #include "sim/sim_object.hh" +#if FULL_SYSTEM +#include "kern/system_events.hh" +#include "mem/vport.hh" +#endif class BaseCPU; class ExecContext; -class GDBListener; -class MemoryController; class ObjectFile; class PhysicalMemory; + +#if FULL_SYSTEM class Platform; +class GDBListener; class RemoteGDB; namespace Kernel { class Binning; } +#endif class System : public SimObject { public: - MemoryController *memctrl; PhysicalMemory *physmem; - Platform *platform; PCEventQueue pcEventQueue; - uint64_t init_param; std::vector<ExecContext *> execContexts; int numcpus; @@ -68,6 +72,15 @@ class System : public SimObject return numcpus; } +#if FULL_SYSTEM + Platform *platform; + uint64_t init_param; + + /** Port to physical memory used for writing object files into ram at + * boot.*/ + FunctionalPort functionalPort; + VirtualPort virtPort; + /** kernel symbol table */ SymbolTable *kernelSymtab; @@ -85,8 +98,16 @@ class System : public SimObject Kernel::Binning *kernelBinning; +#else + + int page_ptr; + + +#endif // FULL_SYSTEM + protected: +#if FULL_SYSTEM /** * Fix up an address used to match PCs for hooking simulator * events on to target function executions. See comment in @@ -118,18 +139,23 @@ class System : public SimObject return addFuncEvent<T>(kernelSymtab, lbl); } +#endif public: +#if FULL_SYSTEM std::vector<RemoteGDB *> remoteGDB; std::vector<GDBListener *> gdbListen; virtual bool breakpoint() = 0; +#endif // FULL_SYSTEM public: struct Params { std::string name; - Tick boot_cpu_frequency; - MemoryController *memctrl; PhysicalMemory *physmem; + +#if FULL_SYSTEM + Tick boot_cpu_frequency; + std::string boot_osflags; uint64_t init_param; bool bin; std::vector<std::string> binned_fns; @@ -137,6 +163,7 @@ class System : public SimObject std::string kernel_path; std::string readfile; +#endif }; protected: @@ -151,6 +178,8 @@ class System : public SimObject const Params *params() const { return (const Params *)_params; } public: + +#if FULL_SYSTEM /** * Returns the addess the kernel starts at. * @return address the kernel starts at @@ -169,6 +198,12 @@ class System : public SimObject */ Addr getKernelEntry() const { return kernelEntry; } +#else + + Addr new_page(); + +#endif // FULL_SYSTEM + int registerExecContext(ExecContext *xc, int xcIndex); void replaceExecContext(ExecContext *xc, int xcIndex); diff --git a/sim/vptr.hh b/sim/vptr.hh index 0ec452f25..cc57e63f0 100644 --- a/sim/vptr.hh +++ b/sim/vptr.hh @@ -96,20 +96,26 @@ class VPtr operator T *() { - void *addr = vtomem(xc, ptr, sizeof(T)); + panic("Needs to be rewritten\n"); +/* void *addr = vtomem(xc, ptr, sizeof(T)); return (T *)addr; + */ } T *operator->() { - void *addr = vtomem(xc, ptr, sizeof(T)); + panic("Needs to be rewritten\n"); +/* void *addr = vtomem(xc, ptr, sizeof(T)); return (T *)addr; + */ } T &operator*() { - void *addr = vtomem(xc, ptr, sizeof(T)); + panic("Needs to be rewritten\n"); +/* void *addr = vtomem(xc, ptr, sizeof(T)); return *(T *)addr; + */ } }; @@ -179,10 +179,10 @@ try: if output_dir: secs_waited = 0 - while not shell.dir_exists(output_dir) and secs_waited < 45: + while not shell.dir_exists(output_dir) and secs_waited < 90: time.sleep(5) secs_waited += 5 - if secs_waited > 10: + if secs_waited > 30: print "waited", secs_waited, "seconds for", output_dir # run command |