summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--SConscript73
-rw-r--r--arch/alpha/alpha_memory.cc126
-rw-r--r--arch/alpha/alpha_memory.hh7
-rw-r--r--arch/alpha/arguments.cc4
-rw-r--r--arch/alpha/arguments.hh2
-rw-r--r--arch/alpha/ev5.cc56
-rw-r--r--arch/alpha/ev5.hh183
-rw-r--r--arch/alpha/faults.cc2
-rw-r--r--arch/alpha/isa_desc14
-rw-r--r--arch/alpha/isa_traits.hh28
-rw-r--r--arch/alpha/osfpal.cc2
-rw-r--r--arch/alpha/pseudo_inst.cc9
-rw-r--r--arch/alpha/vtophys.cc118
-rw-r--r--arch/alpha/vtophys.hh16
-rwxr-xr-xarch/isa_parser.py3
-rw-r--r--base/bitfield.hh8
-rw-r--r--base/callback.hh18
-rw-r--r--base/compression/null_compression.hh8
-rw-r--r--base/crc.cc117
-rw-r--r--base/crc.hh37
-rw-r--r--base/inet.cc251
-rw-r--r--base/inet.hh382
-rw-r--r--base/intmath.hh2
-rw-r--r--base/loader/ecoff_object.cc12
-rw-r--r--base/loader/symtab.cc44
-rw-r--r--base/loader/symtab.hh31
-rw-r--r--base/random.cc2
-rw-r--r--base/random.hh24
-rw-r--r--base/range.cc18
-rw-r--r--base/range.hh119
-rw-r--r--base/refcnt.hh35
-rw-r--r--base/remote_gdb.cc17
-rw-r--r--base/socket.cc2
-rw-r--r--base/stats/types.hh2
-rw-r--r--base/trace.hh10
-rw-r--r--base/traceflags.py1
-rw-r--r--build/SConstruct14
-rw-r--r--configs/boot/nat-netperf-maerts-client.rcS48
-rw-r--r--configs/boot/nat-netperf-server.rcS30
-rw-r--r--configs/boot/nat-netperf-stream-client.rcS48
-rw-r--r--configs/boot/nat-spec-surge-client.rcS51
-rwxr-xr-xconfigs/boot/nat-spec-surge-server.rcS56
-rw-r--r--configs/boot/natbox-netperf.rcS51
-rw-r--r--configs/boot/natbox-spec-surge.rcS51
-rw-r--r--configs/boot/netperf-maerts-client.rcS (renamed from configs/boot/client.netperf.maerts)4
-rw-r--r--configs/boot/netperf-rr.rcS (renamed from configs/boot/client.netperf.rr)4
-rw-r--r--configs/boot/netperf-server.rcS (renamed from configs/boot/server.netperf)0
-rw-r--r--configs/boot/netperf-stream-client.rcS (renamed from configs/boot/client.netperf.stream)4
-rw-r--r--configs/boot/netperf-stream-nt-client.rcS45
-rwxr-xr-xconfigs/boot/nfs-client-smallb.rcS50
-rwxr-xr-xconfigs/boot/nfs-client-tcp-smallb.rcS50
-rwxr-xr-xconfigs/boot/nfs-client-tcp.rcS50
-rwxr-xr-xconfigs/boot/nfs-client.rcS50
-rwxr-xr-xconfigs/boot/nfs-server.rcS70
-rw-r--r--configs/boot/spec-surge-client.rcS46
-rwxr-xr-xconfigs/boot/spec-surge-server.rcS55
-rwxr-xr-xconfigs/boot/surge-client.rcS46
-rwxr-xr-xconfigs/boot/surge-server.rcS54
-rw-r--r--cpu/base_cpu.cc94
-rw-r--r--cpu/base_cpu.hh33
-rw-r--r--cpu/exec_context.cc90
-rw-r--r--cpu/exec_context.hh31
-rw-r--r--cpu/exetrace.cc16
-rw-r--r--cpu/memtest/memtest.cc52
-rw-r--r--cpu/memtest/memtest.hh15
-rw-r--r--cpu/pc_event.cc4
-rw-r--r--cpu/pc_event.hh4
-rw-r--r--cpu/simple_cpu/simple_cpu.cc103
-rw-r--r--cpu/simple_cpu/simple_cpu.hh14
-rw-r--r--cpu/static_inst.hh1
-rw-r--r--cpu/trace/opt_cpu.cc240
-rw-r--r--cpu/trace/opt_cpu.hh222
-rw-r--r--cpu/trace/reader/itx_reader.cc10
-rw-r--r--cpu/trace/reader/itx_reader.hh1
-rw-r--r--cpu/trace/trace_cpu.cc102
-rw-r--r--cpu/trace/trace_cpu.hh24
-rw-r--r--dev/alpha_console.cc8
-rw-r--r--dev/baddev.cc4
-rw-r--r--dev/etherdump.cc39
-rw-r--r--dev/etherdump.hh6
-rw-r--r--dev/etherint.hh16
-rw-r--r--dev/etherlink.cc28
-rw-r--r--dev/etherlink.hh6
-rw-r--r--dev/etherpkt.cc16
-rw-r--r--dev/etherpkt.hh62
-rw-r--r--dev/ethertap.cc5
-rw-r--r--dev/ethertap.hh4
-rw-r--r--dev/ide_ctrl.cc123
-rw-r--r--dev/ide_ctrl.hh50
-rw-r--r--dev/ide_disk.cc18
-rw-r--r--dev/io_device.hh2
-rw-r--r--dev/ns_gige.cc827
-rw-r--r--dev/ns_gige.hh111
-rw-r--r--dev/pciconfigall.cc37
-rw-r--r--dev/pciconfigall.hh7
-rw-r--r--dev/pcidev.cc101
-rw-r--r--dev/pcidev.hh95
-rw-r--r--dev/pktfifo.cc70
-rw-r--r--dev/pktfifo.hh107
-rw-r--r--dev/platform.cc18
-rw-r--r--dev/platform.hh4
-rw-r--r--dev/simconsole.cc36
-rw-r--r--dev/simconsole.hh2
-rw-r--r--dev/sinic.cc1433
-rw-r--r--dev/sinic.hh340
-rw-r--r--dev/sinicreg.hh187
-rw-r--r--dev/tsunami.cc18
-rw-r--r--dev/tsunami.hh19
-rw-r--r--dev/tsunami_cchip.cc292
-rw-r--r--dev/tsunami_cchip.hh36
-rw-r--r--dev/tsunami_io.cc8
-rw-r--r--dev/tsunami_pchip.cc8
-rw-r--r--dev/tsunamireg.h7
-rw-r--r--dev/uart.cc11
-rw-r--r--kern/kernel_stats.cc324
-rw-r--r--kern/kernel_stats.hh159
-rw-r--r--kern/linux/aligned.hh21
-rw-r--r--kern/linux/hwrpb.hh18
-rw-r--r--kern/linux/linux_syscalls.hh7
-rw-r--r--kern/linux/linux_system.cc295
-rw-r--r--kern/linux/linux_system.hh112
-rw-r--r--kern/linux/linux_threadinfo.hh91
-rw-r--r--kern/linux/sched.hh110
-rw-r--r--kern/linux/thread_info.hh27
-rw-r--r--kern/system_events.cc65
-rw-r--r--kern/system_events.hh35
-rw-r--r--kern/tru64/tru64_events.cc7
-rw-r--r--kern/tru64/tru64_syscalls.hh7
-rw-r--r--kern/tru64/tru64_system.cc213
-rw-r--r--kern/tru64/tru64_system.hh56
-rw-r--r--sim/builder.cc30
-rw-r--r--sim/builder.hh3
-rw-r--r--sim/debug.cc6
-rw-r--r--sim/debug.hh4
-rw-r--r--sim/main.cc82
-rw-r--r--sim/param.cc25
-rw-r--r--sim/param.hh32
-rw-r--r--sim/process.cc27
-rw-r--r--sim/process.hh2
-rw-r--r--sim/serialize.cc5
-rw-r--r--sim/sim_events.cc26
-rw-r--r--sim/sim_object.hh6
-rw-r--r--sim/startup.cc51
-rw-r--r--sim/startup.hh41
-rw-r--r--sim/system.cc348
-rw-r--r--sim/system.hh136
-rw-r--r--sim/universe.cc81
-rw-r--r--util/ccdrv/devtime.c33
-rw-r--r--util/stats/info.py47
-rwxr-xr-xutil/stats/stats.py262
-rwxr-xr-xutil/tracediff18
151 files changed, 7707 insertions, 2982 deletions
diff --git a/SConscript b/SConscript
index 8a9b99cb5..9d3a41964 100644
--- a/SConscript
+++ b/SConscript
@@ -47,6 +47,7 @@ base_sources = Split('''
arch/alpha/alpha_full_cpu_exec.cc
arch/alpha/fast_cpu_exec.cc
arch/alpha/simple_cpu_exec.cc
+ arch/alpha/inorder_cpu_exec.cc
arch/alpha/full_cpu_exec.cc
arch/alpha/faults.cc
arch/alpha/isa_traits.cc
@@ -65,6 +66,7 @@ base_sources = Split('''
base/pollevent.cc
base/python.cc
base/range.cc
+ base/random.cc
base/sat_counter.cc
base/socket.cc
base/statistics.cc
@@ -131,6 +133,7 @@ base_sources = Split('''
cpu/full_cpu/issue.cc
cpu/full_cpu/ls_queue.cc
cpu/full_cpu/machine_queue.cc
+ cpu/full_cpu/pc_sample_profile.cc
cpu/full_cpu/pipetrace.cc
cpu/full_cpu/readyq.cc
cpu/full_cpu/reg_info.cc
@@ -150,6 +153,7 @@ base_sources = Split('''
cpu/full_cpu/iq/standard/iq_standard.cc
cpu/sampling_cpu/sampling_cpu.cc
cpu/simple_cpu/simple_cpu.cc
+ cpu/inorder_cpu/inorder_cpu.cc
cpu/trace/reader/mem_trace_reader.cc
cpu/trace/reader/ibm_reader.cc
cpu/trace/reader/itx_reader.cc
@@ -196,6 +200,7 @@ base_sources = Split('''
mem/timing_mem/base_memory.cc
mem/timing_mem/memory_builder.cc
mem/timing_mem/simple_mem_bank.cc
+ mem/trace/itx_writer.cc
mem/trace/mem_trace_writer.cc
mem/trace/m5_writer.cc
@@ -209,11 +214,10 @@ base_sources = Split('''
sim/serialize.cc
sim/sim_events.cc
sim/sim_exit.cc
- sim/sim_init.cc
sim/sim_object.cc
+ sim/startup.cc
sim/stat_context.cc
sim/stat_control.cc
- sim/sw_context.cc
sim/trace_context.cc
sim/universe.cc
sim/pyconfig/pyconfig.cc
@@ -233,6 +237,7 @@ base_obj_desc_files = Split('''
cpu/full_cpu/PipeTrace.od
cpu/sampling_cpu/SamplingCPU.od
cpu/simple_cpu/SimpleCPU.od
+ cpu/inorder_cpu/InorderCPU.od
cpu/BaseCPU.od
cpu/IntrControl.od
mem/bus/Bus.od
@@ -267,6 +272,7 @@ full_system_sources = Split('''
arch/alpha/pseudo_inst.cc
arch/alpha/vtophys.cc
+ base/crc.cc
base/inet.cc
base/remote_gdb.cc
@@ -290,10 +296,12 @@ full_system_sources = Split('''
dev/etherdev.cc
dev/pciconfigall.cc
dev/pcidev.cc
+ dev/pktfifo.cc
dev/scsi.cc
dev/scsi_ctrl.cc
dev/scsi_disk.cc
dev/scsi_none.cc
+ dev/sinic.cc
dev/simple_disk.cc
dev/tlaser_clock.cc
dev/tlaser_ipi.cc
@@ -311,6 +319,7 @@ full_system_sources = Split('''
dev/tsunami_pchip.cc
dev/uart.cc
+ kern/kernel_binning.cc
kern/kernel_stats.cc
kern/system_events.cc
kern/linux/linux_events.cc
@@ -374,6 +383,7 @@ syscall_emulation_sources = Split('''
arch/alpha/alpha_linux_process.cc
arch/alpha/alpha_tru64_process.cc
cpu/memtest/memtest.cc
+ cpu/trace/opt_cpu.cc
cpu/trace/trace_cpu.cc
eio/eio.cc
eio/exolex.cc
@@ -389,6 +399,32 @@ syscall_emulation_obj_desc_files = Split('''
sim/Process.od
''')
+targetarch_files = Split('''
+ alpha_common_syscall_emul.hh
+ alpha_linux_process.hh
+ alpha_memory.hh
+ alpha_tru64_process.hh
+ aout_machdep.h
+ arguments.hh
+ byte_swap.hh
+ ecoff_machdep.h
+ elf_machdep.h
+ ev5.hh
+ faults.hh
+ isa_fullsys_traits.hh
+ isa_traits.hh
+ machine_exo.h
+ osfpal.hh
+ pseudo_inst.hh
+ vptr.hh
+ vtophys.hh
+ ''')
+
+for f in targetarch_files:
+ env.Command('targetarch/' + f, 'arch/alpha/' + f,
+ '''echo '#include "arch/alpha/%s"' > $TARGET''' % f)
+
+
# Set up complete list of sources based on configuration.
sources = base_sources
obj_desc_files = base_obj_desc_files
@@ -400,8 +436,19 @@ else:
sources += syscall_emulation_sources
obj_desc_files += syscall_emulation_obj_desc_files
+extra_libraries = []
+env.Append(LIBS=['z'])
if env['USE_MYSQL']:
sources += mysql_sources
+ env.Append(CPPDEFINES = 'USE_MYSQL')
+ env.Append(CPPDEFINES = 'STATS_BINNING')
+ env.Append(CPPPATH=['/usr/local/include/mysql', '/usr/include/mysql'])
+ if os.path.isdir('/usr/lib64'):
+ env.Append(LIBPATH=['/usr/lib64/mysql'])
+ else:
+ env.Append(LIBPATH=['/usr/lib/mysql/'])
+ env.Append(LIBS=['mysqlclient'])
+
###################################################
#
@@ -421,28 +468,13 @@ env.Command(Split('''arch/alpha/decoder.cc
arch/alpha/alpha_full_cpu_exec.cc
arch/alpha/fast_cpu_exec.cc
arch/alpha/simple_cpu_exec.cc
+ arch/alpha/inorder_cpu_exec.cc
arch/alpha/full_cpu_exec.cc'''),
Split('''arch/alpha/isa_desc
arch/isa_parser.py'''),
'$SRCDIR/arch/isa_parser.py $SOURCE $TARGET.dir arch/alpha')
-# 'targetarch' is a symlink to arch/$TARGET_ISA.
-def link_targetarch(target, source, env):
- link_target = str(target[0])
- link_source = env.subst('$SRCDIR/arch/$TARGET_ISA')
- if not os.path.isdir(link_target):
- print "symlinking", link_source, "to", link_target
- try:
- os.symlink(link_source, link_target)
- except OSError, desc:
- print "Error creating symlink %s: %s" % (link_target, desc)
- sys.exit(-1)
-
-# Tell SCons to use the link_targetarch function to make 'targetarch'
-env.Command('targetarch', None, link_targetarch)
-
-
# libelf build is described in its own SConscript file.
# SConscript-local is the per-config build, which just copies some
# header files into a place where they can be found.
@@ -456,16 +488,15 @@ SConscript('sim/pyconfig/SConscript', exports = ['env', 'obj_desc_files'],
# environment, and returns a list of all the corresponding SCons
# Object nodes (including an extra one for date.cc). We explicitly
# add the Object nodes so we can set up special dependencies for
-# targetarch and date.cc.
+# date.cc.
def make_objs(sources, env):
objs = [env.Object(s) for s in sources]
- # make all objects depend on the targetarch link so it gets made first.
- env.Depends(objs, 'targetarch')
# make date.cc depend on all other objects so it always gets
# recompiled whenever anything else does
date_obj = env.Object('base/date.cc')
env.Depends(date_obj, objs)
objs.append(date_obj)
+ objs.extend(extra_libraries)
return objs
###################################################
diff --git a/arch/alpha/alpha_memory.cc b/arch/alpha/alpha_memory.cc
index 9f5ab185e..81a1902a0 100644
--- a/arch/alpha/alpha_memory.cc
+++ b/arch/alpha/alpha_memory.cc
@@ -30,15 +30,15 @@
#include <string>
#include <vector>
+#include "arch/alpha/alpha_memory.hh"
#include "base/inifile.hh"
#include "base/str.hh"
#include "base/trace.hh"
#include "cpu/exec_context.hh"
#include "sim/builder.hh"
-#include "targetarch/alpha_memory.hh"
-#include "targetarch/ev5.hh"
using namespace std;
+using namespace EV5;
///////////////////////////////////////////////////////////////////////
//
@@ -49,6 +49,8 @@ bool uncacheBit39 = false;
bool uncacheBit40 = false;
#endif
+#define MODE2MASK(X) (1 << (X))
+
AlphaTLB::AlphaTLB(const string &name, int s)
: SimObject(name), size(s), nlu(0)
{
@@ -103,12 +105,12 @@ AlphaTLB::checkCacheability(MemReqPtr &req)
#ifdef ALPHA_TLASER
- if (req->paddr & PA_UNCACHED_BIT_39) {
+ if (req->paddr & PAddrUncachedBit39) {
#else
- if (req->paddr & PA_UNCACHED_BIT_43) {
+ if (req->paddr & PAddrUncachedBit43) {
#endif
// IPR memory space not implemented
- if (PA_IPR_SPACE(req->paddr)) {
+ if (PAddrIprSpace(req->paddr)) {
if (!req->xc->misspeculating()) {
switch (req->paddr) {
case ULL(0xFFFFF00188):
@@ -126,7 +128,7 @@ AlphaTLB::checkCacheability(MemReqPtr &req)
#ifndef ALPHA_TLASER
// Clear bits 42:35 of the physical address (10-2 in Tsunami manual)
- req->paddr &= PA_UNCACHED_MASK;
+ req->paddr &= PAddrUncachedMask;
#endif
}
}
@@ -135,8 +137,9 @@ AlphaTLB::checkCacheability(MemReqPtr &req)
// insert a new TLB entry
void
-AlphaTLB::insert(Addr vaddr, AlphaISA::PTE &pte)
+AlphaTLB::insert(Addr addr, AlphaISA::PTE &pte)
{
+ AlphaISA::VAddr vaddr = addr;
if (table[nlu].valid) {
Addr oldvpn = table[nlu].tag;
PageTable::iterator i = lookupTable.find(oldvpn);
@@ -157,14 +160,13 @@ AlphaTLB::insert(Addr vaddr, AlphaISA::PTE &pte)
lookupTable.erase(i);
}
- Addr vpn = VA_VPN(vaddr);
- DPRINTF(TLB, "insert @%d: %#x -> %#x\n", nlu, vpn, pte.ppn);
+ DPRINTF(TLB, "insert @%d: %#x -> %#x\n", nlu, vaddr.vpn(), pte.ppn);
table[nlu] = pte;
- table[nlu].tag = vpn;
+ table[nlu].tag = vaddr.vpn();
table[nlu].valid = true;
- lookupTable.insert(make_pair(vpn, nlu));
+ lookupTable.insert(make_pair(vaddr.vpn(), nlu));
nextnlu();
}
@@ -197,21 +199,22 @@ AlphaTLB::flushProcesses()
}
void
-AlphaTLB::flushAddr(Addr vaddr, uint8_t asn)
+AlphaTLB::flushAddr(Addr addr, uint8_t asn)
{
- Addr vpn = VA_VPN(vaddr);
+ AlphaISA::VAddr vaddr = addr;
- PageTable::iterator i = lookupTable.find(vpn);
+ PageTable::iterator i = lookupTable.find(vaddr.vpn());
if (i == lookupTable.end())
return;
- while (i->first == vpn) {
+ while (i->first == vaddr.vpn()) {
int index = i->second;
AlphaISA::PTE *pte = &table[index];
assert(pte->valid);
- if (vpn == pte->tag && (pte->asma || pte->asn == asn)) {
- DPRINTF(TLB, "flushaddr @%d: %#x -> %#x\n", index, vpn, pte->ppn);
+ if (vaddr.vpn() == pte->tag && (pte->asma || pte->asn == asn)) {
+ DPRINTF(TLB, "flushaddr @%d: %#x -> %#x\n", index, vaddr.vpn(),
+ pte->ppn);
// invalidate this entry
pte->valid = false;
@@ -287,7 +290,7 @@ AlphaITB::fault(Addr pc, ExecContext *xc) const
if (!xc->misspeculating()) {
ipr[AlphaISA::IPR_ITB_TAG] = pc;
ipr[AlphaISA::IPR_IFAULT_VA_FORM] =
- ipr[AlphaISA::IPR_IVPTBR] | (VA_VPN(pc) << 3);
+ ipr[AlphaISA::IPR_IVPTBR] | (AlphaISA::VAddr(pc).vpn() << 3);
}
}
@@ -297,9 +300,9 @@ AlphaITB::translate(MemReqPtr &req) const
{
InternalProcReg *ipr = req->xc->regs.ipr;
- if (PC_PAL(req->vaddr)) {
+ if (AlphaISA::PcPAL(req->vaddr)) {
// strip off PAL PC marker (lsb is 1)
- req->paddr = (req->vaddr & ~3) & PA_IMPL_MASK;
+ req->paddr = (req->vaddr & ~3) & PAddrImplMask;
hits++;
return No_Fault;
}
@@ -319,24 +322,23 @@ AlphaITB::translate(MemReqPtr &req) const
// VA<47:41> == 0x7e, VA<40:13> maps directly to PA<40:13> for EV6
#ifdef ALPHA_TLASER
if ((MCSR_SP(ipr[AlphaISA::IPR_MCSR]) & 2) &&
- VA_SPACE_EV5(req->vaddr) == 2) {
+ VAddrSpaceEV5(req->vaddr) == 2) {
#else
- if (VA_SPACE_EV6(req->vaddr) == 0x7e) {
+ if (VAddrSpaceEV6(req->vaddr) == 0x7e) {
#endif
-
-
// only valid in kernel mode
- if (ICM_CM(ipr[AlphaISA::IPR_ICM]) != AlphaISA::mode_kernel) {
+ if (ICM_CM(ipr[AlphaISA::IPR_ICM]) !=
+ AlphaISA::mode_kernel) {
fault(req->vaddr, req->xc);
acv++;
return ITB_Acv_Fault;
}
- req->paddr = req->vaddr & PA_IMPL_MASK;
+ req->paddr = req->vaddr & PAddrImplMask;
#ifndef ALPHA_TLASER
// sign extend the physical address properly
- if (req->paddr & PA_UNCACHED_BIT_40)
+ if (req->paddr & PAddrUncachedBit40)
req->paddr |= ULL(0xf0000000000);
else
req->paddr &= ULL(0xffffffffff);
@@ -344,8 +346,8 @@ AlphaITB::translate(MemReqPtr &req) const
} else {
// not a physical address: need to look up pte
- AlphaISA::PTE *pte = lookup(VA_VPN(req->vaddr),
- DTB_ASN_ASN(ipr[AlphaISA::IPR_DTB_ASN]));
+ AlphaISA::PTE *pte = lookup(AlphaISA::VAddr(req->vaddr).vpn(),
+ DTB_ASN_ASN(ipr[AlphaISA::IPR_DTB_ASN]));
if (!pte) {
fault(req->vaddr, req->xc);
@@ -353,7 +355,8 @@ AlphaITB::translate(MemReqPtr &req) const
return ITB_Fault_Fault;
}
- req->paddr = PA_PFN2PA(pte->ppn) + VA_POFS(req->vaddr & ~3);
+ req->paddr = (pte->ppn << AlphaISA::PageShift) +
+ (AlphaISA::VAddr(req->vaddr).offset() & ~3);
// check permissions for this access
if (!(pte->xre & (1 << ICM_CM(ipr[AlphaISA::IPR_ICM])))) {
@@ -368,7 +371,7 @@ AlphaITB::translate(MemReqPtr &req) const
}
// check that the physical address is ok (catch bad physical addresses)
- if (req->paddr & ~PA_IMPL_MASK)
+ if (req->paddr & ~PAddrImplMask)
return Machine_Check_Fault;
checkCacheability(req);
@@ -457,7 +460,7 @@ void
AlphaDTB::fault(MemReqPtr &req, uint64_t flags) const
{
ExecContext *xc = req->xc;
- Addr vaddr = req->vaddr;
+ AlphaISA::VAddr vaddr = req->vaddr;
uint64_t *ipr = xc->regs.ipr;
// Set fault address and flags. Even though we're modeling an
@@ -468,16 +471,17 @@ AlphaDTB::fault(MemReqPtr &req, uint64_t flags) const
if (!xc->misspeculating()
&& !(req->flags & VPTE) && !(req->flags & NO_FAULT)) {
// set VA register with faulting address
- ipr[AlphaISA::IPR_VA] = vaddr;
+ ipr[AlphaISA::IPR_VA] = req->vaddr;
// set MM_STAT register flags
- ipr[AlphaISA::IPR_MM_STAT] = (((OPCODE(xc->getInst()) & 0x3f) << 11)
- | ((RA(xc->getInst()) & 0x1f) << 6)
- | (flags & 0x3f));
+ ipr[AlphaISA::IPR_MM_STAT] =
+ (((Opcode(xc->getInst()) & 0x3f) << 11)
+ | ((Ra(xc->getInst()) & 0x1f) << 6)
+ | (flags & 0x3f));
// set VA_FORM register with faulting formatted address
ipr[AlphaISA::IPR_VA_FORM] =
- ipr[AlphaISA::IPR_MVPTBR] | (VA_VPN(vaddr) << 3);
+ ipr[AlphaISA::IPR_MVPTBR] | (vaddr.vpn() << 3);
}
}
@@ -492,14 +496,15 @@ AlphaDTB::translate(MemReqPtr &req, bool write) const
(AlphaISA::mode_type)DTB_CM_CM(ipr[AlphaISA::IPR_DTB_CM]);
- /* @todo this should actually be in there but for whatever reason
- * Its not working at present.
+ /**
+ * Check for alignment faults
*/
if (req->vaddr & (req->size - 1)) {
+ fault(req, write ? MM_STAT_WR_MASK : 0);
return Alignment_Fault;
}
- if (PC_PAL(pc)) {
+ if (pc & 0x1) {
mode = (req->flags & ALTMODE) ?
(AlphaISA::mode_type)ALT_MODE_AM(ipr[AlphaISA::IPR_ALT_MODE])
: AlphaISA::mode_kernel;
@@ -510,8 +515,9 @@ AlphaDTB::translate(MemReqPtr &req, bool write) const
} 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));
+ fault(req, (write ? MM_STAT_WR_MASK : 0) |
+ MM_STAT_BAD_VA_MASK |
+ MM_STAT_ACV_MASK);
if (write) { write_acv++; } else { read_acv++; }
return DTB_Fault_Fault;
@@ -520,24 +526,25 @@ AlphaDTB::translate(MemReqPtr &req, bool write) const
// Check for "superpage" mapping
#ifdef ALPHA_TLASER
if ((MCSR_SP(ipr[AlphaISA::IPR_MCSR]) & 2) &&
- VA_SPACE_EV5(req->vaddr) == 2) {
+ VAddrSpaceEV5(req->vaddr) == 2) {
#else
- if (VA_SPACE_EV6(req->vaddr) == 0x7e) {
+ if (VAddrSpaceEV6(req->vaddr) == 0x7e) {
#endif
// only valid in kernel mode
if (DTB_CM_CM(ipr[AlphaISA::IPR_DTB_CM]) !=
AlphaISA::mode_kernel) {
- fault(req, ((write ? MM_STAT_WR_MASK : 0) | MM_STAT_ACV_MASK));
+ fault(req, ((write ? MM_STAT_WR_MASK : 0) |
+ MM_STAT_ACV_MASK));
if (write) { write_acv++; } else { read_acv++; }
return DTB_Acv_Fault;
}
- req->paddr = req->vaddr & PA_IMPL_MASK;
+ req->paddr = req->vaddr & PAddrImplMask;
#ifndef ALPHA_TLASER
// sign extend the physical address properly
- if (req->paddr & PA_UNCACHED_BIT_40)
+ if (req->paddr & PAddrUncachedBit40)
req->paddr |= ULL(0xf0000000000);
else
req->paddr &= ULL(0xffffffffff);
@@ -550,36 +557,39 @@ AlphaDTB::translate(MemReqPtr &req, bool write) const
read_accesses++;
// not a physical address: need to look up pte
- AlphaISA::PTE *pte = lookup(VA_VPN(req->vaddr),
- DTB_ASN_ASN(ipr[AlphaISA::IPR_DTB_ASN]));
+ AlphaISA::PTE *pte = lookup(AlphaISA::VAddr(req->vaddr).vpn(),
+ DTB_ASN_ASN(ipr[AlphaISA::IPR_DTB_ASN]));
if (!pte) {
// page fault
- fault(req,
- (write ? MM_STAT_WR_MASK : 0) | MM_STAT_DTB_MISS_MASK);
+ fault(req, (write ? MM_STAT_WR_MASK : 0) |
+ MM_STAT_DTB_MISS_MASK);
if (write) { write_misses++; } else { read_misses++; }
return (req->flags & VPTE) ? Pdtb_Miss_Fault : Ndtb_Miss_Fault;
}
- req->paddr = PA_PFN2PA(pte->ppn) | VA_POFS(req->vaddr);
+ req->paddr = (pte->ppn << AlphaISA::PageShift) +
+ AlphaISA::VAddr(req->vaddr).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)));
+ fault(req, MM_STAT_WR_MASK |
+ MM_STAT_ACV_MASK |
+ (pte->fonw ? MM_STAT_FONW_MASK : 0));
write_acv++;
return DTB_Fault_Fault;
}
if (pte->fonw) {
- fault(req, MM_STAT_WR_MASK | MM_STAT_FONW_MASK);
+ fault(req, MM_STAT_WR_MASK |
+ MM_STAT_FONW_MASK);
write_acv++;
return DTB_Fault_Fault;
}
} else {
if (!(pte->xre & MODE2MASK(mode))) {
- fault(req, (MM_STAT_ACV_MASK |
- (pte->fonr ? MM_STAT_FONR_MASK : 0)));
+ fault(req, MM_STAT_ACV_MASK |
+ (pte->fonr ? MM_STAT_FONR_MASK : 0));
read_acv++;
return DTB_Acv_Fault;
}
@@ -598,7 +608,7 @@ AlphaDTB::translate(MemReqPtr &req, bool write) const
}
// check that the physical address is ok (catch bad physical addresses)
- if (req->paddr & ~PA_IMPL_MASK)
+ if (req->paddr & ~PAddrImplMask)
return Machine_Check_Fault;
checkCacheability(req);
diff --git a/arch/alpha/alpha_memory.hh b/arch/alpha/alpha_memory.hh
index 42bc03ddd..0d4b8d1f2 100644
--- a/arch/alpha/alpha_memory.hh
+++ b/arch/alpha/alpha_memory.hh
@@ -31,9 +31,10 @@
#include <map>
+#include "arch/alpha/isa_traits.hh"
+#include "base/statistics.hh"
#include "mem/mem_req.hh"
#include "sim/sim_object.hh"
-#include "base/statistics.hh"
class ExecContext;
@@ -66,8 +67,8 @@ class AlphaTLB : public SimObject
// static helper functions... really EV5 VM traits
static bool validVirtualAddress(Addr vaddr) {
// unimplemented bits must be all 0 or all 1
- Addr unimplBits = vaddr & VA_UNIMPL_MASK;
- return (unimplBits == 0) || (unimplBits == VA_UNIMPL_MASK);
+ Addr unimplBits = vaddr & EV5::VAddrUnImplMask;
+ return (unimplBits == 0) || (unimplBits == EV5::VAddrUnImplMask);
}
static void checkCacheability(MemReqPtr &req);
diff --git a/arch/alpha/arguments.cc b/arch/alpha/arguments.cc
index 2dca3f51e..905d6b9ae 100644
--- a/arch/alpha/arguments.cc
+++ b/arch/alpha/arguments.cc
@@ -26,10 +26,10 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
+#include "arch/alpha/arguments.hh"
+#include "arch/alpha/vtophys.hh"
#include "cpu/exec_context.hh"
#include "mem/functional_mem/physical_memory.hh"
-#include "targetarch/arguments.hh"
-#include "targetarch/vtophys.hh"
AlphaArguments::Data::~Data()
{
diff --git a/arch/alpha/arguments.hh b/arch/alpha/arguments.hh
index 78e66b3fd..b4dc0eea8 100644
--- a/arch/alpha/arguments.hh
+++ b/arch/alpha/arguments.hh
@@ -31,9 +31,9 @@
#include <assert.h>
+#include "arch/alpha/vtophys.hh"
#include "base/refcnt.hh"
#include "sim/host.hh"
-#include "targetarch/vtophys.hh"
class ExecContext;
diff --git a/arch/alpha/ev5.cc b/arch/alpha/ev5.cc
index b043ed0ee..2e32da531 100644
--- a/arch/alpha/ev5.cc
+++ b/arch/alpha/ev5.cc
@@ -9,14 +9,13 @@
#include "cpu/base_cpu.hh"
#include "cpu/exec_context.hh"
#include "cpu/fast_cpu/fast_cpu.hh"
+#include "kern/kernel_stats.hh"
#include "sim/debug.hh"
#include "sim/sim_events.hh"
#ifdef FULL_SYSTEM
-#ifndef SYSTEM_EV5
-#error This code is only valid for EV5 systems
-#endif
+using namespace EV5;
////////////////////////////////////////////////////////////////////////
//
@@ -95,22 +94,22 @@ AlphaISA::initIPRs(RegFile *regs)
uint64_t *ipr = regs->ipr;
bzero((char *)ipr, NumInternalProcRegs * sizeof(InternalProcReg));
- ipr[IPR_PAL_BASE] = PAL_BASE;
+ ipr[IPR_PAL_BASE] = PalBase;
ipr[IPR_MCSR] = 0x6;
}
-template <class XC>
+template <class CPU>
void
-AlphaISA::processInterrupts(XC *xc)
+AlphaISA::processInterrupts(CPU *cpu)
{
//Check if there are any outstanding interrupts
//Handle the interrupts
int ipl = 0;
int summary = 0;
- IntReg *ipr = xc->getIprPtr();
+ IntReg *ipr = cpu->getIprPtr();
- check_interrupts = 0;
+ cpu->checkInterrupts = false;
if (ipr[IPR_ASTRR])
panic("asynchronous traps not implemented\n");
@@ -126,7 +125,7 @@ AlphaISA::processInterrupts(XC *xc)
}
}
- uint64_t interrupts = xc->intr_status();
+ uint64_t interrupts = cpu->intr_status();
if (interrupts) {
for (int i = INTLEVEL_EXTERNAL_MIN;
@@ -142,32 +141,32 @@ AlphaISA::processInterrupts(XC *xc)
if (ipl && ipl > ipr[IPR_IPLR]) {
ipr[IPR_ISR] = summary;
ipr[IPR_INTID] = ipl;
- xc->trap(Interrupt_Fault);
+ cpu->trap(Interrupt_Fault);
DPRINTF(Flow, "Interrupt! IPLR=%d ipl=%d summary=%x\n",
ipr[IPR_IPLR], ipl, summary);
}
}
-template <class XC>
+template <class CPU>
void
-AlphaISA::zeroRegisters(XC *xc)
+AlphaISA::zeroRegisters(CPU *cpu)
{
// Insure ISA semantics
// (no longer very clean due to the change in setIntReg() in the
// cpu model. Consider changing later.)
- xc->xc->setIntReg(ZeroReg, 0);
- xc->xc->setFloatRegDouble(ZeroReg, 0.0);
+ cpu->xc->setIntReg(ZeroReg, 0);
+ cpu->xc->setFloatRegDouble(ZeroReg, 0.0);
}
void
ExecContext::ev5_trap(Fault fault)
{
- DPRINTF(Fault, "Fault %s\n", FaultName(fault));
+ DPRINTF(Fault, "Fault %s at PC: %#x\n", FaultName(fault), regs.pc);
cpu->recordEvent(csprintf("Fault %s", FaultName(fault)));
assert(!misspeculating());
- kernelStats.fault(fault);
+ kernelStats->fault(fault);
if (fault == Arithmetic_Fault)
panic("Arithmetic traps are unimplemented!");
@@ -175,16 +174,16 @@ ExecContext::ev5_trap(Fault fault)
AlphaISA::InternalProcReg *ipr = regs.ipr;
// exception restart address
- if (fault != Interrupt_Fault || !PC_PAL(regs.pc))
+ if (fault != Interrupt_Fault || !inPalMode())
ipr[AlphaISA::IPR_EXC_ADDR] = regs.pc;
if (fault == Pal_Fault || fault == Arithmetic_Fault /* ||
- fault == Interrupt_Fault && !PC_PAL(regs.pc) */) {
+ fault == Interrupt_Fault && !inPalMode() */) {
// traps... skip faulting instruction
ipr[AlphaISA::IPR_EXC_ADDR] += 4;
}
- if (!PC_PAL(regs.pc))
+ if (!inPalMode())
AlphaISA::swap_palshadow(&regs, true);
regs.pc = ipr[AlphaISA::IPR_PAL_BASE] + AlphaISA::fault_addr[fault];
@@ -219,25 +218,23 @@ AlphaISA::intr_post(RegFile *regs, Fault fault, Addr pc)
// that's it! (orders of magnitude less painful than x86)
}
-bool AlphaISA::check_interrupts = false;
-
Fault
ExecContext::hwrei()
{
uint64_t *ipr = regs.ipr;
- if (!PC_PAL(regs.pc))
+ if (!inPalMode())
return Unimplemented_Opcode_Fault;
setNextPC(ipr[AlphaISA::IPR_EXC_ADDR]);
if (!misspeculating()) {
- kernelStats.hwrei();
+ kernelStats->hwrei();
if ((ipr[AlphaISA::IPR_EXC_ADDR] & 1) == 0)
AlphaISA::swap_palshadow(&regs, false);
- AlphaISA::check_interrupts = true;
+ cpu->checkInterrupts = true;
}
// FIXME: XXX check for interrupts? XXX
@@ -415,7 +412,7 @@ ExecContext::setIpr(int idx, uint64_t val)
// write entire quad w/ no side-effect
old = ipr[idx];
ipr[idx] = val;
- kernelStats.context(old, val);
+ kernelStats->context(old, val);
break;
case AlphaISA::IPR_DTB_PTE:
@@ -442,11 +439,14 @@ ExecContext::setIpr(int idx, uint64_t val)
// only write least significant five bits - interrupt level
ipr[idx] = val & 0x1f;
- kernelStats.swpipl(ipr[idx]);
+ kernelStats->swpipl(ipr[idx]);
break;
case AlphaISA::IPR_DTB_CM:
- kernelStats.mode((val & 0x18) != 0);
+ if (val & 0x18)
+ kernelStats->mode(Kernel::user);
+ else
+ kernelStats->mode(Kernel::kernel);
case AlphaISA::IPR_ICM:
// only write two mode bits - processor mode
@@ -622,7 +622,7 @@ ExecContext::setIpr(int idx, uint64_t val)
bool
ExecContext::simPalCheck(int palFunc)
{
- kernelStats.callpal(palFunc);
+ kernelStats->callpal(palFunc);
switch (palFunc) {
case PAL::halt:
diff --git a/arch/alpha/ev5.hh b/arch/alpha/ev5.hh
index f49eadeb0..317f3d19d 100644
--- a/arch/alpha/ev5.hh
+++ b/arch/alpha/ev5.hh
@@ -1,128 +1,79 @@
/* $Id$ */
-#ifndef __EV5_H__
-#define __EV5_H__
+#ifndef __ARCH_ALPHA_EV5_HH__
+#define __ARCH_ALPHA_EV5_HH__
-#ifndef SYSTEM_EV5
-#error This code is only valid for EV5 systems
-#endif
-
-#include "targetarch/isa_traits.hh"
-
-////////////////////////////////////////////////////////////////////////
-//
-//
-//
-
-////////////////////////////////////////////////////////////////////////
-//
-//
-//
-
-#define MODE2MASK(X) (1 << (X))
-
-// Alpha IPR register accessors
-#define PC_PAL(X) ((X) & 0x1)
-#define MCSR_SP(X) (((X) >> 1) & 0x3)
-
-#define ICSR_SDE(X) (((X) >> 30) & 0x1)
-#define ICSR_SPE(X) (((X) >> 28) & 0x3)
-#define ICSR_FPE(X) (((X) >> 26) & 0x1)
-
-#define ALT_MODE_AM(X) (((X) >> 3) & 0x3)
-
-#define DTB_CM_CM(X) (((X) >> 3) & 0x3)
-
-#ifdef ALPHA_TLASER
-#define DTB_ASN_ASN(X) (((X) >> 57) & 0x7f)
-#define DTB_PTE_PPN(X) (((X) >> 32) & 0x07ffffff)
-#else
-#define DTB_ASN_ASN(X) (((X) >> 57) & 0xff)
-#define DTB_PTE_PPN(X) (((X) >> 32) & 0x07fffffff)
-#endif
-
-#define DTB_PTE_XRE(X) (((X) >> 8) & 0xf)
-#define DTB_PTE_XWE(X) (((X) >> 12) & 0xf)
-#define DTB_PTE_FONR(X) (((X) >> 1) & 0x1)
-#define DTB_PTE_FONW(X) (((X) >> 2) & 0x1)
-#define DTB_PTE_GH(X) (((X) >> 5) & 0x3)
-#define DTB_PTE_ASMA(X) (((X) >> 4) & 0x1)
-
-#define ICM_CM(X) (((X) >> 3) & 0x3)
+namespace EV5 {
#ifdef ALPHA_TLASER
-#define ITB_ASN_ASN(X) (((X) >> 4) & 0x7f)
-#define ITB_PTE_PPN(X) (((X) >> 32) & 0x07ffffff)
+const uint64_t AsnMask = ULL(0x7f);
#else
-#define ITB_ASN_ASN(X) (((X) >> 4) & 0xff)
-#define ITB_PTE_PPN(X) (((X) >> 32) & 0x07fffffff)
+const uint64_t AsnMask = ULL(0xff);
#endif
-#define ITB_PTE_XRE(X) (((X) >> 8) & 0xf)
-#define ITB_PTE_FONR(X) (((X) >> 1) & 0x1)
-#define ITB_PTE_FONW(X) (((X) >> 2) & 0x1)
-#define ITB_PTE_GH(X) (((X) >> 5) & 0x3)
-#define ITB_PTE_ASMA(X) (((X) >> 4) & 0x1)
+const int VAddrImplBits = 43;
+const Addr VAddrImplMask = (ULL(1) << VAddrImplBits) - 1;
+const Addr VAddrUnImplMask = ~VAddrImplMask;
+inline Addr VAddrImpl(Addr a) { return a & VAddrImplMask; }
+inline Addr VAddrVPN(Addr a) { return a >> AlphaISA::PageShift; }
+inline Addr VAddrOffset(Addr a) { return a & AlphaISA::PageOffset; }
+inline Addr VAddrSpaceEV5(Addr a) { return a >> 41 & 0x3; }
+inline Addr VAddrSpaceEV6(Addr a) { return a >> 41 & 0x7f; }
-#define VA_UNIMPL_MASK ULL(0xfffff80000000000)
-#define VA_IMPL_MASK ULL(0x000007ffffffffff)
-#define VA_IMPL(X) ((X) & VA_IMPL_MASK)
-#define VA_VPN(X) (VA_IMPL(X) >> 13)
-#define VA_SPACE_EV5(X) (((X) >> 41) & 0x3)
-#define VA_SPACE_EV6(X) (((X) >> 41) & 0x7f)
-#define VA_POFS(X) ((X) & 0x1fff)
-
-#define PA_UNCACHED_BIT_39 ULL(0x8000000000)
-#define PA_UNCACHED_BIT_40 ULL(0x10000000000)
-#define PA_UNCACHED_BIT_43 ULL(0x80000000000)
-#define PA_UNCACHED_MASK ULL(0x807ffffffff) // Clear PA<42:35>
#ifdef ALPHA_TLASER
-#define PA_IPR_SPACE(X) ((X) >= ULL(0xFFFFF00000))
-#define PA_IMPL_MASK ULL(0xffffffffff)
+inline bool PAddrIprSpace(Addr a) { return a >= ULL(0xFFFFF00000); }
+const int PAddrImplBits = 40;
#else
-#define PA_IPR_SPACE(X) ((X) >= ULL(0xFFFFFF00000))
-#define PA_IMPL_MASK ULL(0xfffffffffff) // for Tsunami
+inline bool PAddrIprSpace(Addr a) { return a >= ULL(0xFFFFFF00000); }
+const int PAddrImplBits = 44; // for Tsunami
#endif
-
-#define PA_PFN2PA(X) ((X) << 13)
-
-
-#define MM_STAT_BAD_VA_MASK 0x0020
-#define MM_STAT_DTB_MISS_MASK 0x0010
-#define MM_STAT_FONW_MASK 0x0008
-#define MM_STAT_FONR_MASK 0x0004
-#define MM_STAT_ACV_MASK 0x0002
-#define MM_STAT_WR_MASK 0x0001
-
-#define OPCODE(X) (X >> 26) & 0x3f
-#define RA(X) (X >> 21) & 0x1f
-
-////////////////////////////////////////////////////////////////////////
-//
-//
-//
-
-// VPTE size for HW_LD/HW_ST
-#define HW_VPTE ((inst >> 11) & 0x1)
-
-// QWORD size for HW_LD/HW_ST
-#define HW_QWORD ((inst >> 12) & 0x1)
-
-// ALT mode for HW_LD/HW_ST
-#define HW_ALT (((inst >> 14) & 0x1) ? ALTMODE : 0)
-
-// LOCK/COND mode for HW_LD/HW_ST
-#define HW_LOCK (((inst >> 10) & 0x1) ? LOCKED : 0)
-#define HW_COND (((inst >> 10) & 0x1) ? LOCKED : 0)
-
-// PHY size for HW_LD/HW_ST
-#define HW_PHY (((inst >> 15) & 0x1) ? PHYSICAL : 0)
-
-// OFFSET for HW_LD/HW_ST
-#define HW_OFS (inst & 0x3ff)
-
-
-#define PAL_BASE 0x4000
-#define PAL_MAX 0x10000
-
-#endif //__EV5_H__
+const Addr PAddrImplMask = (ULL(1) << PAddrImplBits) - 1;
+const Addr PAddrUncachedBit39 = ULL(0x8000000000);
+const Addr PAddrUncachedBit40 = ULL(0x10000000000);
+const Addr PAddrUncachedBit43 = ULL(0x80000000000);
+const Addr PAddrUncachedMask = ULL(0x807ffffffff); // Clear PA<42:35>
+
+inline int DTB_ASN_ASN(uint64_t reg) { return reg >> 57 & AsnMask; }
+inline Addr DTB_PTE_PPN(uint64_t reg)
+{ return reg >> 32 & (ULL(1) << PAddrImplBits - AlphaISA::PageShift) - 1; }
+inline int DTB_PTE_XRE(uint64_t reg) { return reg >> 8 & 0xf; }
+inline int DTB_PTE_XWE(uint64_t reg) { return reg >> 12 & 0xf; }
+inline int DTB_PTE_FONR(uint64_t reg) { return reg >> 1 & 0x1; }
+inline int DTB_PTE_FONW(uint64_t reg) { return reg >> 2 & 0x1; }
+inline int DTB_PTE_GH(uint64_t reg) { return reg >> 5 & 0x3; }
+inline int DTB_PTE_ASMA(uint64_t reg) { return reg >> 4 & 0x1; }
+
+inline int ITB_ASN_ASN(uint64_t reg) { return reg >> 4 & AsnMask; }
+inline Addr ITB_PTE_PPN(uint64_t reg)
+{ return reg >> 32 & (ULL(1) << PAddrImplBits - AlphaISA::PageShift) - 1; }
+inline int ITB_PTE_XRE(uint64_t reg) { return reg >> 8 & 0xf; }
+inline bool ITB_PTE_FONR(uint64_t reg) { return reg >> 1 & 0x1; }
+inline bool ITB_PTE_FONW(uint64_t reg) { return reg >> 2 & 0x1; }
+inline int ITB_PTE_GH(uint64_t reg) { return reg >> 5 & 0x3; }
+inline bool ITB_PTE_ASMA(uint64_t reg) { return reg >> 4 & 0x1; }
+
+inline uint64_t MCSR_SP(uint64_t reg) { return reg >> 1 & 0x3; }
+
+inline bool ICSR_SDE(uint64_t reg) { return reg >> 30 & 0x1; }
+inline int ICSR_SPE(uint64_t reg) { return reg >> 28 & 0x3; }
+inline bool ICSR_FPE(uint64_t reg) { return reg >> 26 & 0x1; }
+
+inline uint64_t ALT_MODE_AM(uint64_t reg) { return reg >> 3 & 0x3; }
+inline uint64_t DTB_CM_CM(uint64_t reg) { return reg >> 3 & 0x3; }
+inline uint64_t ICM_CM(uint64_t reg) { return reg >> 3 & 0x3; }
+
+const uint64_t MM_STAT_BAD_VA_MASK = ULL(0x0020);
+const uint64_t MM_STAT_DTB_MISS_MASK = ULL(0x0010);
+const uint64_t MM_STAT_FONW_MASK = ULL(0x0008);
+const uint64_t MM_STAT_FONR_MASK = ULL(0x0004);
+const uint64_t MM_STAT_ACV_MASK = ULL(0x0002);
+const uint64_t MM_STAT_WR_MASK = ULL(0x0001);
+inline int Opcode(AlphaISA::MachInst inst) { return inst >> 26 & 0x3f; }
+inline int Ra(AlphaISA::MachInst inst) { return inst >> 21 & 0x1f; }
+
+const Addr PalBase = 0x4000;
+const Addr PalMax = 0x10000;
+
+/* namespace EV5 */ }
+
+#endif // __ARCH_ALPHA_EV5_HH__
diff --git a/arch/alpha/faults.cc b/arch/alpha/faults.cc
index a800f9886..c98bb91a5 100644
--- a/arch/alpha/faults.cc
+++ b/arch/alpha/faults.cc
@@ -26,7 +26,7 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#include "targetarch/faults.hh"
+#include "arch/alpha/faults.hh"
namespace {
const char *
diff --git a/arch/alpha/isa_desc b/arch/alpha/isa_desc
index eaf3aa379..fbd4cfe60 100644
--- a/arch/alpha/isa_desc
+++ b/arch/alpha/isa_desc
@@ -38,14 +38,12 @@ output exec {{
#include <fenv.h>
#endif
-#include "cpu/base_cpu.hh"
-#include "cpu/exetrace.hh"
-#include "sim/sim_exit.hh"
-
#ifdef FULL_SYSTEM
-#include "arch/alpha/ev5.hh"
#include "arch/alpha/pseudo_inst.hh"
#endif
+#include "cpu/base_cpu.hh"
+#include "cpu/exetrace.hh"
+#include "sim/sim_exit.hh"
}};
////////////////////////////////////////////////////////////////////
@@ -515,7 +513,7 @@ output exec {{
inline Fault checkFpEnableFault(%(CPU_exec_context)s *xc)
{
Fault fault = No_Fault; // dummy... this ipr access should not fault
- if (!ICSR_FPE(xc->readIpr(AlphaISA::IPR_ICSR, fault))) {
+ if (!EV5::ICSR_FPE(xc->readIpr(AlphaISA::IPR_ICSR, fault))) {
fault = Fen_Fault;
}
return fault;
@@ -1842,7 +1840,7 @@ decode OPCODE default Unknown::unknown() {
0x2a: ldl_l({{ EA = Rb + disp; }}, {{ Ra.sl = Mem.sl; }}, LOCKED);
0x2b: ldq_l({{ EA = Rb + disp; }}, {{ Ra.uq = Mem.uq; }}, LOCKED);
0x20: copy_load({{EA = Ra;}},
- {{ fault = xc->copySrcTranslate(EA);}},
+ {{fault = xc->copySrcTranslate(EA);}},
IsMemRef, IsLoad, IsCopy);
}
@@ -1864,7 +1862,7 @@ decode OPCODE default Unknown::unknown() {
0x26: sts({{ EA = Rb + disp; }}, {{ Mem.ul = t_to_s(Fa.uq); }});
0x27: stt({{ EA = Rb + disp; }}, {{ Mem.df = Fa; }});
0x24: copy_store({{EA = Rb;}},
- {{ fault = xc->copy(EA);}},
+ {{fault = xc->copy(EA);}},
IsMemRef, IsStore, IsCopy);
}
diff --git a/arch/alpha/isa_traits.hh b/arch/alpha/isa_traits.hh
index 6559368e4..ff3da1502 100644
--- a/arch/alpha/isa_traits.hh
+++ b/arch/alpha/isa_traits.hh
@@ -26,12 +26,12 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#ifndef __ISA_TRAITS_HH__
-#define __ISA_TRAITS_HH__
+#ifndef __ARCH_ALPHA_ISA_TRAITS_HH__
+#define __ARCH_ALPHA_ISA_TRAITS_HH__
-#include "sim/host.hh"
-#include "targetarch/faults.hh"
+#include "arch/alpha/faults.hh"
#include "base/misc.hh"
+#include "sim/host.hh"
class FastCPU;
class FullCPU;
@@ -42,6 +42,11 @@ class Checkpoint;
template <class ISA> class StaticInst;
template <class ISA> class StaticInstPtr;
+namespace EV5 {
+int DTB_ASN_ASN(uint64_t reg);
+int ITB_ASN_ASN(uint64_t reg);
+}
+
class AlphaISA
{
public:
@@ -121,11 +126,16 @@ class AlphaISA
Addr lock_addr; // lock address for LL/SC
} MiscRegFile;
+static const Addr PageShift = 13;
+static const Addr PageBytes = ULL(1) << PageShift;
+static const Addr PageMask = ~(PageBytes - 1);
+static const Addr PageOffset = PageBytes - 1;
+
#ifdef FULL_SYSTEM
typedef uint64_t InternalProcReg;
-#include "targetarch/isa_fullsys_traits.hh"
+#include "arch/alpha/isa_fullsys_traits.hh"
#else
enum {
@@ -155,6 +165,8 @@ class AlphaISA
InternalProcReg ipr[NumInternalProcRegs]; // internal processor regs
int intrflag; // interrupt flag
bool pal_shadow; // using pal_shadow registers
+ inline int instAsid() { return EV5::ITB_ASN_ASN(ipr[IPR_ITB_ASN]); }
+ inline int dataAsid() { return EV5::DTB_ASN_ASN(ipr[IPR_DTB_ASN]); }
#endif // FULL_SYSTEM
void serialize(std::ostream &os);
@@ -276,9 +288,7 @@ typedef TheISA::InternalProcReg InternalProcReg;
const int NumInternalProcRegs = TheISA::NumInternalProcRegs;
const int NumInterruptLevels = TheISA::NumInterruptLevels;
-// more stuff that should be imported here, but I'm too tired to do it
-// right now...
-#include "targetarch/ev5.hh"
+#include "arch/alpha/ev5.hh"
#endif
-#endif // __ALPHA_ISA_H__
+#endif // __ARCH_ALPHA_ISA_TRAITS_HH__
diff --git a/arch/alpha/osfpal.cc b/arch/alpha/osfpal.cc
index 2717079ab..3cdc3864a 100644
--- a/arch/alpha/osfpal.cc
+++ b/arch/alpha/osfpal.cc
@@ -26,7 +26,7 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#include "targetarch/osfpal.hh"
+#include "arch/alpha/osfpal.hh"
namespace {
const char *strings[PAL::NumCodes] = {
diff --git a/arch/alpha/pseudo_inst.cc b/arch/alpha/pseudo_inst.cc
index fd6742801..95c85b45a 100644
--- a/arch/alpha/pseudo_inst.cc
+++ b/arch/alpha/pseudo_inst.cc
@@ -37,6 +37,7 @@
#include "cpu/base_cpu.hh"
#include "cpu/sampling_cpu/sampling_cpu.hh"
#include "cpu/exec_context.hh"
+#include "kern/kernel_stats.hh"
#include "sim/param.hh"
#include "sim/serialize.hh"
#include "sim/sim_exit.hh"
@@ -60,7 +61,7 @@ namespace AlphaPseudo
void
arm(ExecContext *xc)
{
- xc->kernelStats.arm();
+ xc->kernelStats->arm();
}
void
@@ -70,13 +71,13 @@ namespace AlphaPseudo
return;
xc->suspend();
- xc->kernelStats.quiesce();
+ xc->kernelStats->quiesce();
}
void
ivlb(ExecContext *xc)
{
- xc->kernelStats.ivlb();
+ xc->kernelStats->ivlb();
}
void
@@ -164,7 +165,7 @@ namespace AlphaPseudo
void
readfile(ExecContext *xc)
{
- const string &file = xc->cpu->system->readfile;
+ const string &file = xc->cpu->system->params->readfile;
if (file.empty()) {
xc->regs.intRegFile[0] = ULL(0);
return;
diff --git a/arch/alpha/vtophys.cc b/arch/alpha/vtophys.cc
index 5468d4b07..e26721aab 100644
--- a/arch/alpha/vtophys.cc
+++ b/arch/alpha/vtophys.cc
@@ -28,61 +28,47 @@
#include <string>
-#include "targetarch/pmap.h"
-
+#include "arch/alpha/vtophys.hh"
+#include "base/trace.hh"
#include "cpu/exec_context.hh"
#include "mem/functional_mem/physical_memory.hh"
-#include "base/trace.hh"
-#include "targetarch/vtophys.hh"
using namespace std;
-inline Addr
-level3_index(Addr vaddr)
-{ return (vaddr >> ALPHA_PGSHIFT) & PTEMASK; }
-
-inline Addr
-level2_index(Addr vaddr)
-{ return (vaddr >> (ALPHA_PGSHIFT + NPTEPG_SHIFT)) & PTEMASK; }
-
-inline Addr
-level1_index(Addr vaddr)
-{ return (vaddr >> (ALPHA_PGSHIFT + 2 * NPTEPG_SHIFT)) & PTEMASK; }
-
-Addr
-kernel_pte_lookup(PhysicalMemory *pmem, Addr ptbr, Addr vaddr)
+AlphaISA::PageTableEntry
+kernel_pte_lookup(PhysicalMemory *pmem, Addr ptbr, AlphaISA::VAddr vaddr)
{
- uint64_t level1_map = ptbr;
- Addr level1_pte = level1_map + (level1_index(vaddr) << PTESHIFT);
-
- uint64_t level1 = pmem->phys_read_qword(level1_pte);
- if (!entry_valid(level1)) {
+ Addr level1_pte = ptbr + vaddr.level1();
+ AlphaISA::PageTableEntry level1 = pmem->phys_read_qword(level1_pte);
+ if (!level1.valid()) {
DPRINTF(VtoPhys, "level 1 PTE not valid, va = %#\n", vaddr);
return 0;
}
- uint64_t level2_map = PMAP_PTE_PA(level1);
- Addr level2_pte = level2_map + (level2_index(vaddr) << PTESHIFT);
- uint64_t level2 = pmem->phys_read_qword(level2_pte);
- if (!entry_valid(level2)) {
+ Addr level2_pte = level1.paddr() + vaddr.level2();
+ AlphaISA::PageTableEntry level2 = pmem->phys_read_qword(level2_pte);
+ if (!level2.valid()) {
DPRINTF(VtoPhys, "level 2 PTE not valid, va = %#x\n", vaddr);
return 0;
}
- uint64_t level3_map = PMAP_PTE_PA(level2);
- Addr level3_pte = level3_map + (level3_index(vaddr) << PTESHIFT);
-
- return level3_pte;
+ Addr level3_pte = level2.paddr() + vaddr.level3();
+ AlphaISA::PageTableEntry level3 = pmem->phys_read_qword(level3_pte);
+ if (!level3.valid()) {
+ DPRINTF(VtoPhys, "level 3 PTE not valid, va = %#x\n", vaddr);
+ return 0;
+ }
+ return level3;
}
Addr
vtophys(PhysicalMemory *xc, Addr vaddr)
{
Addr paddr = 0;
- if (vaddr < ALPHA_K0SEG_BASE)
+ if (AlphaISA::IsUSeg(vaddr))
DPRINTF(VtoPhys, "vtophys: invalid vaddr %#x", vaddr);
- else if (vaddr < ALPHA_K1SEG_BASE)
- paddr = ALPHA_K0SEG_TO_PHYS(vaddr);
+ else if (AlphaISA::IsK0Seg(vaddr))
+ paddr = AlphaISA::K0Seg2Phys(vaddr);
else
panic("vtophys: ptbr is not set on virtual lookup");
@@ -92,24 +78,25 @@ vtophys(PhysicalMemory *xc, Addr vaddr)
}
Addr
-vtophys(ExecContext *xc, Addr vaddr)
+vtophys(ExecContext *xc, Addr addr)
{
+ AlphaISA::VAddr vaddr = addr;
Addr ptbr = xc->regs.ipr[AlphaISA::IPR_PALtemp20];
Addr paddr = 0;
//@todo Andrew couldn't remember why he commented some of this code
//so I put it back in. Perhaps something to do with gdb debugging?
- if (PC_PAL(vaddr) && (vaddr < PAL_MAX)) {
+ if (AlphaISA::PcPAL(vaddr) && (vaddr < EV5::PalMax)) {
paddr = vaddr & ~ULL(1);
} else {
- if (vaddr >= ALPHA_K0SEG_BASE && vaddr <= ALPHA_K0SEG_END) {
- paddr = ALPHA_K0SEG_TO_PHYS(vaddr);
+ if (AlphaISA::IsK0Seg(vaddr)) {
+ paddr = AlphaISA::K0Seg2Phys(vaddr);
} else if (!ptbr) {
paddr = vaddr;
} else {
- Addr pte = kernel_pte_lookup(xc->physmem, ptbr, vaddr);
- uint64_t entry = xc->physmem->phys_read_qword(pte);
- if (pte && entry_valid(entry))
- paddr = PMAP_PTE_PA(entry) | (vaddr & PGOFSET);
+ AlphaISA::PageTableEntry pte =
+ kernel_pte_lookup(xc->physmem, ptbr, vaddr);
+ if (pte.valid())
+ paddr = pte.paddr() | vaddr.offset();
}
}
@@ -141,7 +128,8 @@ CopyOut(ExecContext *xc, void *dest, Addr src, size_t cplen)
int len;
paddr = vtophys(xc, src);
- len = min((int)(ALPHA_PGBYTES - (paddr & PGOFSET)), (int)cplen);
+ len = min((int)(AlphaISA::PageBytes - (paddr & AlphaISA::PageOffset)),
+ (int)cplen);
dmaaddr = (char *)xc->physmem->dma_addr(paddr, len);
assert(dmaaddr);
@@ -153,15 +141,15 @@ CopyOut(ExecContext *xc, void *dest, Addr src, size_t cplen)
dst += len;
src += len;
- while (cplen > ALPHA_PGBYTES) {
+ while (cplen > AlphaISA::PageBytes) {
paddr = vtophys(xc, src);
- dmaaddr = (char *)xc->physmem->dma_addr(paddr, ALPHA_PGBYTES);
+ dmaaddr = (char *)xc->physmem->dma_addr(paddr, AlphaISA::PageBytes);
assert(dmaaddr);
- memcpy(dst, dmaaddr, ALPHA_PGBYTES);
- cplen -= ALPHA_PGBYTES;
- dst += ALPHA_PGBYTES;
- src += ALPHA_PGBYTES;
+ memcpy(dst, dmaaddr, AlphaISA::PageBytes);
+ cplen -= AlphaISA::PageBytes;
+ dst += AlphaISA::PageBytes;
+ src += AlphaISA::PageBytes;
}
if (cplen > 0) {
@@ -182,7 +170,8 @@ CopyIn(ExecContext *xc, Addr dest, void *source, size_t cplen)
int len;
paddr = vtophys(xc, dest);
- len = min((int)(ALPHA_PGBYTES - (paddr & PGOFSET)), (int)cplen);
+ len = min((int)(AlphaISA::PageBytes - (paddr & AlphaISA::PageOffset)),
+ (int)cplen);
dmaaddr = (char *)xc->physmem->dma_addr(paddr, len);
assert(dmaaddr);
@@ -194,15 +183,15 @@ CopyIn(ExecContext *xc, Addr dest, void *source, size_t cplen)
src += len;
dest += len;
- while (cplen > ALPHA_PGBYTES) {
+ while (cplen > AlphaISA::PageBytes) {
paddr = vtophys(xc, dest);
- dmaaddr = (char *)xc->physmem->dma_addr(paddr, ALPHA_PGBYTES);
+ dmaaddr = (char *)xc->physmem->dma_addr(paddr, AlphaISA::PageBytes);
assert(dmaaddr);
- memcpy(dmaaddr, src, ALPHA_PGBYTES);
- cplen -= ALPHA_PGBYTES;
- src += ALPHA_PGBYTES;
- dest += ALPHA_PGBYTES;
+ memcpy(dmaaddr, src, AlphaISA::PageBytes);
+ cplen -= AlphaISA::PageBytes;
+ src += AlphaISA::PageBytes;
+ dest += AlphaISA::PageBytes;
}
if (cplen > 0) {
@@ -222,7 +211,8 @@ CopyString(ExecContext *xc, char *dst, Addr vaddr, size_t maxlen)
int len;
paddr = vtophys(xc, vaddr);
- len = min((int)(ALPHA_PGBYTES - (paddr & PGOFSET)), (int)maxlen);
+ len = min((int)(AlphaISA::PageBytes - (paddr & AlphaISA::PageOffset)),
+ (int)maxlen);
dmaaddr = (char *)xc->physmem->dma_addr(paddr, len);
assert(dmaaddr);
@@ -239,21 +229,21 @@ CopyString(ExecContext *xc, char *dst, Addr vaddr, size_t maxlen)
dst += len;
vaddr += len;
- while (maxlen > ALPHA_PGBYTES) {
+ while (maxlen > AlphaISA::PageBytes) {
paddr = vtophys(xc, vaddr);
- dmaaddr = (char *)xc->physmem->dma_addr(paddr, ALPHA_PGBYTES);
+ dmaaddr = (char *)xc->physmem->dma_addr(paddr, AlphaISA::PageBytes);
assert(dmaaddr);
- char *term = (char *)memchr(dmaaddr, 0, ALPHA_PGBYTES);
- len = term ? (term - dmaaddr + 1) : ALPHA_PGBYTES;
+ char *term = (char *)memchr(dmaaddr, 0, AlphaISA::PageBytes);
+ len = term ? (term - dmaaddr + 1) : AlphaISA::PageBytes;
memcpy(dst, dmaaddr, len);
if (term)
return;
- maxlen -= ALPHA_PGBYTES;
- dst += ALPHA_PGBYTES;
- vaddr += ALPHA_PGBYTES;
+ maxlen -= AlphaISA::PageBytes;
+ dst += AlphaISA::PageBytes;
+ vaddr += AlphaISA::PageBytes;
}
if (maxlen > 0) {
diff --git a/arch/alpha/vtophys.hh b/arch/alpha/vtophys.hh
index 7c22e3371..8e47a0031 100644
--- a/arch/alpha/vtophys.hh
+++ b/arch/alpha/vtophys.hh
@@ -26,19 +26,17 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#ifndef __VTOPHYS_H__
-#define __VTOPHYS_H__
+#ifndef __ARCH_ALPHA_VTOPHYS_H__
+#define __ARCH_ALPHA_VTOPHYS_H__
-#include "targetarch/isa_traits.hh"
-#include "targetarch/pmap.h"
-
-inline bool entry_valid(uint64_t entry)
-{ return (entry & ALPHA_PTE_VALID) != 0; }
+#include "arch/alpha/isa_traits.hh"
class ExecContext;
class PhysicalMemory;
-Addr kernel_pte_lookup(PhysicalMemory *pmem, Addr ptbr, Addr vaddr);
+AlphaISA::PageTableEntry
+kernel_pte_lookup(PhysicalMemory *pmem, Addr ptbr, AlphaISA::VAddr vaddr);
+
Addr vtophys(PhysicalMemory *xc, Addr vaddr);
Addr vtophys(ExecContext *xc, Addr vaddr);
uint8_t *vtomem(ExecContext *xc, Addr vaddr, size_t len);
@@ -48,5 +46,5 @@ 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);
-#endif // __VTOPHYS_H__
+#endif // __ARCH_ALPHA_VTOPHYS_H__
diff --git a/arch/isa_parser.py b/arch/isa_parser.py
index f86e6193d..7228f99b6 100755
--- a/arch/isa_parser.py
+++ b/arch/isa_parser.py
@@ -627,6 +627,9 @@ class CpuModel:
# Define CPU models. The following lines should contain the only
# CPU-model-specific information in this file. Note that the ISA
# description itself should have *no* CPU-model-specific content.
+CpuModel('InorderCPU', 'inorder_cpu_exec.cc',
+ '#include "cpu/inorder_cpu/inorder_cpu.hh"',
+ { 'CPU_exec_context': 'InorderCPU' })
CpuModel('SimpleCPU', 'simple_cpu_exec.cc',
'#include "cpu/simple_cpu/simple_cpu.hh"',
{ 'CPU_exec_context': 'SimpleCPU' })
diff --git a/base/bitfield.hh b/base/bitfield.hh
index ee5ea72cf..bdc3fb13e 100644
--- a/base/bitfield.hh
+++ b/base/bitfield.hh
@@ -26,10 +26,10 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#ifndef __BITFIELD_HH
-#define __BITFIELD_HH
+#ifndef __BASE_BITFIELD_HH__
+#define __BASE_BITFIELD_HH__
-#include <inttypes.h>
+#include "sim/host.hh"
/**
* Generate a 64-bit mask of 'nbits' 1s, right justified.
@@ -66,4 +66,4 @@ sext(uint64_t val)
return sign_bit ? (val | ~mask(N)) : val;
}
-#endif
+#endif // __BASE_BITFIELD_HH__
diff --git a/base/callback.hh b/base/callback.hh
index eee629cf5..cc2a2f429 100644
--- a/base/callback.hh
+++ b/base/callback.hh
@@ -32,7 +32,7 @@
#include <list>
/**
- * Generic callback class. This base class provides a virutal process
+ * Generic callback class. This base class provides a virtual process
* function that gets called when the callback queue is processed.
*/
class Callback
@@ -103,4 +103,20 @@ class CallbackQueue
}
};
+/// Helper template class to turn a simple class member function into
+/// a callback.
+template <class T, void (T::* F)()>
+class MakeCallback : public Callback
+{
+ private:
+ T *object;
+
+ public:
+ MakeCallback(T *o)
+ : object(o)
+ { }
+
+ void process() { (object->*F)(); }
+};
+
#endif // __CALLBACK_HH__
diff --git a/base/compression/null_compression.hh b/base/compression/null_compression.hh
index 195498f1b..63364a955 100644
--- a/base/compression/null_compression.hh
+++ b/base/compression/null_compression.hh
@@ -26,16 +26,16 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#ifndef __NULL_COMPRESSION_HH__
-#define __NULL_COMPRESSION_HH__
+#ifndef __BASE_COMPRESSION_NULL_COMPRESSION_HH__
+#define __BASE_COMPRESSION_NULL_COMPRESSION_HH__
/**
* @file
* This file defines a doNothing compression algorithm.
*/
-#include <inttypes.h> // for uint8_t
#include "base/misc.hh" // for fatal()
+#include "sim/host.hh"
/**
@@ -73,4 +73,4 @@ class NullCompression
}
};
-#endif //__NULL_COMPRESSION_HH__
+#endif //__BASE_COMPRESSION_NULL_COMPRESSION_HH__
diff --git a/base/crc.cc b/base/crc.cc
new file mode 100644
index 000000000..8bff4b868
--- /dev/null
+++ b/base/crc.cc
@@ -0,0 +1,117 @@
+/* $Id$ */
+
+/*
+ * Copyright (c) 1988, 1992, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University 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 REGENTS 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 REGENTS 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 <sstream>
+#include <string>
+
+#include "sim/host.hh"
+#include "base/crc.hh"
+
+#define ETHER_CRC_POLY_LE 0xedb88320
+#define ETHER_CRC_POLY_BE 0x04c11db6
+
+#if 0
+/*
+ * This is for reference. We have a table-driven version
+ * of the little-endian crc32 generator, which is faster
+ * than the double-loop.
+ */
+uint32_t
+crc32le(const uint8_t *buf, size_t len)
+{
+ uint32_t c, crc, carry;
+ size_t i, j;
+
+ crc = 0xffffffffU; /* initial value */
+
+ for (i = 0; i < len; i++) {
+ c = buf[i];
+ for (j = 0; j < 8; j++) {
+ carry = ((crc & 0x01) ? 1 : 0) ^ (c & 0x01);
+ crc >>= 1;
+ c >>= 1;
+ if (carry)
+ crc = (crc ^ ETHER_CRC_POLY_LE);
+ }
+ }
+
+ return (crc);
+}
+#else
+uint32_t
+crc32le(const uint8_t *buf, size_t len)
+{
+ static const uint32_t crctab[] = {
+ 0x00000000, 0x1db71064, 0x3b6e20c8, 0x26d930ac,
+ 0x76dc4190, 0x6b6b51f4, 0x4db26158, 0x5005713c,
+ 0xedb88320, 0xf00f9344, 0xd6d6a3e8, 0xcb61b38c,
+ 0x9b64c2b0, 0x86d3d2d4, 0xa00ae278, 0xbdbdf21c
+ };
+ uint32_t crc;
+ int i;
+
+ crc = 0xffffffffU; /* initial value */
+
+ for (i = 0; i < len; i++) {
+ crc ^= buf[i];
+ crc = (crc >> 4) ^ crctab[crc & 0xf];
+ crc = (crc >> 4) ^ crctab[crc & 0xf];
+ }
+
+ return (crc);
+}
+#endif
+
+uint32_t
+crc32be(const uint8_t *buf, size_t len)
+{
+ uint32_t c, crc, carry;
+ size_t i, j;
+
+ crc = 0xffffffffU; /* initial value */
+
+ for (i = 0; i < len; i++) {
+ c = buf[i];
+ for (j = 0; j < 8; j++) {
+ carry = ((crc & 0x80000000U) ? 1 : 0) ^ (c & 0x01);
+ crc <<= 1;
+ c >>= 1;
+ if (carry)
+ crc = (crc ^ ETHER_CRC_POLY_BE) | carry;
+ }
+ }
+
+ return (crc);
+}
diff --git a/base/crc.hh b/base/crc.hh
new file mode 100644
index 000000000..bd6719b98
--- /dev/null
+++ b/base/crc.hh
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2002-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.
+ */
+
+#ifndef __BASE_CRC_HH__
+#define __BASE_CRC_HH__
+
+#include "sim/host.hh"
+
+uint32_t crc32be(const uint8_t *buf, size_t len);
+uint32_t crc32le(const uint8_t *buf, size_t len);
+
+#endif // __BASE_CRC_HH__
diff --git a/base/inet.cc b/base/inet.cc
index e2bdd19ff..eca7238ff 100644
--- a/base/inet.cc
+++ b/base/inet.cc
@@ -26,6 +26,7 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
+#include <cstdio>
#include <sstream>
#include <string>
@@ -33,129 +34,175 @@
#include "sim/host.hh"
#include "base/inet.hh"
-using namespace::std;
+using namespace std;
+namespace Net {
+
+EthAddr::EthAddr()
+{
+ memset(data, 0, ETH_ADDR_LEN);
+}
+
+EthAddr::EthAddr(const uint8_t ea[ETH_ADDR_LEN])
+{
+ *data = *ea;
+}
+
+EthAddr::EthAddr(const eth_addr &ea)
+{
+ *data = *ea.data;
+}
+
+EthAddr::EthAddr(const std::string &addr)
+{
+ parse(addr);
+}
+
+const EthAddr &
+EthAddr::operator=(const eth_addr &ea)
+{
+ *data = *ea.data;
+ return *this;
+}
+
+const EthAddr &
+EthAddr::operator=(const std::string &addr)
+{
+ parse(addr);
+ return *this;
+}
+
+void
+EthAddr::parse(const std::string &addr)
+{
+ // the hack below is to make sure that ETH_ADDR_LEN is 6 otherwise
+ // the sscanf function won't work.
+ int bytes[ETH_ADDR_LEN == 6 ? ETH_ADDR_LEN : -1];
+ if (sscanf(addr.c_str(), "%x:%x:%x:%x:%x:%x", &bytes[0], &bytes[1],
+ &bytes[2], &bytes[3], &bytes[4], &bytes[5]) != ETH_ADDR_LEN) {
+ memset(data, 0xff, ETH_ADDR_LEN);
+ return;
+ }
+
+ for (int i = 0; i < ETH_ADDR_LEN; ++i) {
+ if (bytes[i] & ~0xff) {
+ memset(data, 0xff, ETH_ADDR_LEN);
+ return;
+ }
+
+ data[i] = bytes[i];
+ }
+}
+
string
-eaddr_string(const uint8_t a[6])
+EthAddr::string() const
{
stringstream stream;
+ stream << *this;
+ return stream.str();
+}
+
+bool
+operator==(const EthAddr &left, const EthAddr &right)
+{
+ return memcmp(left.bytes(), right.bytes(), ETH_ADDR_LEN);
+}
+
+ostream &
+operator<<(ostream &stream, const EthAddr &ea)
+{
+ const uint8_t *a = ea.addr();
ccprintf(stream, "%x:%x:%x:%x:%x:%x", a[0], a[1], a[2], a[3], a[4], a[5]);
+ return stream;
+}
- return stream.str();
+uint16_t
+cksum(const IpPtr &ptr)
+{
+ int sum = ip_cksum_add(ptr->bytes(), ptr->hlen(), 0);
+ return ip_cksum_carry(sum);
}
-/*
- * Copyright (c) 1988, 1992, 1993
- * The Regents of the University of California. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. 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.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University 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 REGENTS 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 REGENTS 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.
- */
-/***********************************************************************
- This section of code taken from NetBSD
-***********************************************************************/
+uint16_t
+__tu_cksum(const IpPtr &ip)
+{
+ int tcplen = ip->len() - ip->hlen();
+ int sum = ip_cksum_add(ip->payload(), tcplen, 0);
+ sum = ip_cksum_add(&ip->ip_src, 8, sum); // source and destination
+ sum += htons(ip->ip_p + tcplen);
+ return ip_cksum_carry(sum);
+}
-#define ETHER_CRC_POLY_LE 0xedb88320
-#define ETHER_CRC_POLY_BE 0x04c11db6
+uint16_t
+cksum(const TcpPtr &tcp)
+{ return __tu_cksum(IpPtr(tcp.packet())); }
-#if 0
-/*
- * This is for reference. We have a table-driven version
- * of the little-endian crc32 generator, which is faster
- * than the double-loop.
- */
-uint32_t
-crc32le(const uint8_t *buf, size_t len)
+uint16_t
+cksum(const UdpPtr &udp)
+{ return __tu_cksum(IpPtr(udp.packet())); }
+
+bool
+IpHdr::options(vector<const IpOpt *> &vec) const
{
- uint32_t c, crc, carry;
- size_t i, j;
-
- crc = 0xffffffffU; /* initial value */
-
- for (i = 0; i < len; i++) {
- c = buf[i];
- for (j = 0; j < 8; j++) {
- carry = ((crc & 0x01) ? 1 : 0) ^ (c & 0x01);
- crc >>= 1;
- c >>= 1;
- if (carry)
- crc = (crc ^ ETHER_CRC_POLY_LE);
- }
+ vec.clear();
+
+ const uint8_t *data = bytes() + sizeof(struct ip_hdr);
+ int all = hlen() - sizeof(struct ip_hdr);
+ while (all > 0) {
+ const IpOpt *opt = (const IpOpt *)data;
+ int len = opt->len();
+ if (all < len)
+ return false;
+
+ vec.push_back(opt);
+ all -= len;
+ data += len;
}
- return (crc);
+ return true;
}
-#else
-uint32_t
-crc32le(const uint8_t *buf, size_t len)
+
+bool
+TcpHdr::options(vector<const TcpOpt *> &vec) const
{
- static const uint32_t crctab[] = {
- 0x00000000, 0x1db71064, 0x3b6e20c8, 0x26d930ac,
- 0x76dc4190, 0x6b6b51f4, 0x4db26158, 0x5005713c,
- 0xedb88320, 0xf00f9344, 0xd6d6a3e8, 0xcb61b38c,
- 0x9b64c2b0, 0x86d3d2d4, 0xa00ae278, 0xbdbdf21c
- };
- uint32_t crc;
- int i;
-
- crc = 0xffffffffU; /* initial value */
-
- for (i = 0; i < len; i++) {
- crc ^= buf[i];
- crc = (crc >> 4) ^ crctab[crc & 0xf];
- crc = (crc >> 4) ^ crctab[crc & 0xf];
+ vec.clear();
+
+ const uint8_t *data = bytes() + sizeof(struct tcp_hdr);
+ int all = off() - sizeof(struct tcp_hdr);
+ while (all > 0) {
+ const TcpOpt *opt = (const TcpOpt *)data;
+ int len = opt->len();
+ if (all < len)
+ return false;
+
+ vec.push_back(opt);
+ all -= len;
+ data += len;
}
- return (crc);
+ return true;
}
-#endif
-uint32_t
-crc32be(const uint8_t *buf, size_t len)
+bool
+TcpOpt::sack(vector<SackRange> &vec) const
{
- uint32_t c, crc, carry;
- size_t i, j;
-
- crc = 0xffffffffU; /* initial value */
-
- for (i = 0; i < len; i++) {
- c = buf[i];
- for (j = 0; j < 8; j++) {
- carry = ((crc & 0x80000000U) ? 1 : 0) ^ (c & 0x01);
- crc <<= 1;
- c >>= 1;
- if (carry)
- crc = (crc ^ ETHER_CRC_POLY_BE) | carry;
+ vec.clear();
+
+ const uint8_t *data = bytes() + sizeof(struct tcp_hdr);
+ int all = len() - offsetof(tcp_opt, opt_data.sack);
+ while (all > 0) {
+ const uint16_t *sack = (const uint16_t *)data;
+ int len = sizeof(uint16_t) * 2;
+ if (all < len) {
+ vec.clear();
+ return false;
}
+
+ vec.push_back(RangeIn(ntohs(sack[0]), ntohs(sack[1])));
+ all -= len;
+ data += len;
}
- return (crc);
+ return false;
}
-/***********************************************************************
- This is the end of the NetBSD code
-***********************************************************************/
+/* namespace Net */ }
diff --git a/base/inet.hh b/base/inet.hh
index 67ac5a504..4f3857a15 100644
--- a/base/inet.hh
+++ b/base/inet.hh
@@ -26,12 +26,382 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#ifndef __INET_HH__
-#define __INET_HH__
+#ifndef __BASE_INET_HH__
+#define __BASE_INET_HH__
+#include <iosfwd>
+#include <string>
+#include <utility>
+#include <vector>
+
+#include "base/range.hh"
+#include "dev/etherpkt.hh"
#include "sim/host.hh"
-uint32_t crc32be(const uint8_t *buf, size_t len);
-uint32_t crc32le(const uint8_t *buf, size_t len);
-std::string eaddr_string(const uint8_t a[6]);
-#endif // __INET_HH__
+#include "dnet/os.h"
+#include "dnet/eth.h"
+#include "dnet/ip.h"
+#include "dnet/ip6.h"
+#include "dnet/addr.h"
+#include "dnet/arp.h"
+#include "dnet/icmp.h"
+#include "dnet/tcp.h"
+#include "dnet/udp.h"
+#include "dnet/intf.h"
+#include "dnet/route.h"
+#include "dnet/fw.h"
+#include "dnet/blob.h"
+#include "dnet/rand.h"
+
+namespace Net {
+
+/*
+ * Ethernet Stuff
+ */
+struct EthAddr : protected eth_addr
+{
+ protected:
+ void parse(const std::string &addr);
+
+ public:
+ EthAddr();
+ EthAddr(const uint8_t ea[ETH_ADDR_LEN]);
+ EthAddr(const eth_addr &ea);
+ EthAddr(const std::string &addr);
+ const EthAddr &operator=(const eth_addr &ea);
+ const EthAddr &operator=(const std::string &addr);
+
+ int size() const { return sizeof(eth_addr); }
+
+ const uint8_t *bytes() const { return &data[0]; }
+ uint8_t *bytes() { return &data[0]; }
+
+ const uint8_t *addr() const { return &data[0]; }
+ bool unicast() const { return data[0] == 0x00; }
+ bool multicast() const { return data[0] == 0x01; }
+ bool broadcast() const { return data[0] == 0xff; }
+ std::string string() const;
+
+ operator uint64_t() const
+ {
+ uint64_t reg = 0;
+ reg |= ((uint64_t)data[0]) << 40;
+ reg |= ((uint64_t)data[1]) << 32;
+ reg |= ((uint64_t)data[2]) << 24;
+ reg |= ((uint64_t)data[3]) << 16;
+ reg |= ((uint64_t)data[4]) << 8;
+ reg |= ((uint64_t)data[5]) << 0;
+ return reg;
+ }
+
+};
+
+std::ostream &operator<<(std::ostream &stream, const EthAddr &ea);
+bool operator==(const EthAddr &left, const EthAddr &right);
+
+struct EthHdr : public eth_hdr
+{
+ uint16_t type() const { return ntohs(eth_type); }
+ const EthAddr &src() const { return *(EthAddr *)&eth_src; }
+ const EthAddr &dst() const { return *(EthAddr *)&eth_dst; }
+
+ int size() const { return sizeof(eth_hdr); }
+
+ const uint8_t *bytes() const { return (const uint8_t *)this; }
+ const uint8_t *payload() const { return bytes() + size(); }
+ uint8_t *bytes() { return (uint8_t *)this; }
+ uint8_t *payload() { return bytes() + size(); }
+};
+
+class EthPtr
+{
+ protected:
+ friend class IpPtr;
+ PacketPtr p;
+
+ public:
+ EthPtr() {}
+ EthPtr(const PacketPtr &ptr) : p(ptr) { }
+
+ EthHdr *operator->() { return (EthHdr *)p->data; }
+ EthHdr &operator*() { return *(EthHdr *)p->data; }
+ operator EthHdr *() { return (EthHdr *)p->data; }
+
+ const EthHdr *operator->() const { return (const EthHdr *)p->data; }
+ 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 PacketPtr packet() const { return p; }
+ PacketPtr packet() { return p; }
+ bool operator!() const { return !p; }
+ operator bool() const { return p; }
+};
+
+/*
+ * IP Stuff
+ */
+struct IpOpt;
+struct IpHdr : public ip_hdr
+{
+ uint8_t version() const { return ip_v; }
+ uint8_t hlen() const { return ip_hl * 4; }
+ uint8_t tos() const { return ip_tos; }
+ uint16_t len() const { return ntohs(ip_len); }
+ uint16_t id() const { return ntohs(ip_id); }
+ uint16_t frag_flags() const { return ntohs(ip_off) >> 13; }
+ uint16_t frag_off() const { return ntohs(ip_off) & 0x1fff; }
+ uint8_t ttl() const { return ip_ttl; }
+ uint8_t proto() const { return ip_p; }
+ uint16_t sum() const { return ip_sum; }
+ uint32_t src() const { return ntohl(ip_src); }
+ uint32_t dst() const { return ntohl(ip_dst); }
+
+ void sum(uint16_t sum) { ip_sum = sum; }
+
+ bool options(std::vector<const IpOpt *> &vec) const;
+
+ int size() const { return hlen(); }
+ const uint8_t *bytes() const { return (const uint8_t *)this; }
+ const uint8_t *payload() const { return bytes() + size(); }
+ uint8_t *bytes() { return (uint8_t *)this; }
+ uint8_t *payload() { return bytes() + size(); }
+};
+
+class IpPtr
+{
+ protected:
+ friend class TcpPtr;
+ friend class UdpPtr;
+ PacketPtr 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)
+ {
+ EthHdr *eth = (EthHdr *)ptr->data;
+ if (eth->type() == ETH_TYPE_IP)
+ p = ptr;
+ else
+ p = 0;
+ }
+
+ public:
+ IpPtr() {}
+ IpPtr(const PacketPtr &ptr) { set(ptr); }
+ IpPtr(const EthPtr &ptr) { set(ptr.p); }
+ IpPtr(const IpPtr &ptr) : p(ptr.p) { }
+
+ IpHdr *operator->() { return h(); }
+ IpHdr &operator*() { return *h(); }
+ operator IpHdr *() { return h(); }
+
+ const IpHdr *operator->() const { return h(); }
+ 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 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; }
+ bool operator!() const { return !p; }
+ operator bool() const { return p; }
+ operator bool() { return p; }
+};
+
+uint16_t cksum(const IpPtr &ptr);
+
+struct IpOpt : public ip_opt
+{
+ uint8_t type() const { return opt_type; }
+ uint8_t typeNumber() const { return IP_OPT_NUMBER(opt_type); }
+ uint8_t typeClass() const { return IP_OPT_CLASS(opt_type); }
+ uint8_t typeCopied() const { return IP_OPT_COPIED(opt_type); }
+ uint8_t len() const { return IP_OPT_TYPEONLY(type()) ? 1 : opt_len; }
+
+ bool isNumber(int num) const { return typeNumber() == IP_OPT_NUMBER(num); }
+ bool isClass(int cls) const { return typeClass() == IP_OPT_CLASS(cls); }
+ bool isCopied(int cpy) const { return typeCopied() == IP_OPT_COPIED(cpy); }
+
+ const uint8_t *data() const { return opt_data.data8; }
+ void sec(ip_opt_data_sec &sec) const;
+ void lsrr(ip_opt_data_rr &rr) const;
+ void ssrr(ip_opt_data_rr &rr) const;
+ void ts(ip_opt_data_ts &ts) const;
+ uint16_t satid() const { return ntohs(opt_data.satid); }
+ uint16_t mtup() const { return ntohs(opt_data.mtu); }
+ uint16_t mtur() const { return ntohs(opt_data.mtu); }
+ void tr(ip_opt_data_tr &tr) const;
+ const uint32_t *addext() const { return &opt_data.addext[0]; }
+ uint16_t rtralt() const { return ntohs(opt_data.rtralt); }
+ void sdb(std::vector<uint32_t> &vec) const;
+};
+
+/*
+ * TCP Stuff
+ */
+struct TcpOpt;
+struct TcpHdr : public tcp_hdr
+{
+ uint16_t sport() const { return ntohs(th_sport); }
+ uint16_t dport() const { return ntohs(th_dport); }
+ uint32_t seq() const { return ntohl(th_seq); }
+ uint32_t ack() const { return ntohl(th_ack); }
+ uint8_t off() const { return th_off; }
+ uint8_t flags() const { return th_flags & 0x3f; }
+ uint16_t win() const { return ntohs(th_win); }
+ uint16_t sum() const { return th_sum; }
+ uint16_t urp() const { return ntohs(th_urp); }
+
+ void sum(uint16_t sum) { th_sum = sum; }
+
+ bool options(std::vector<const TcpOpt *> &vec) const;
+
+ int size() const { return off(); }
+ const uint8_t *bytes() const { return (const uint8_t *)this; }
+ const uint8_t *payload() const { return bytes() + size(); }
+ uint8_t *bytes() { return (uint8_t *)this; }
+ uint8_t *payload() { return bytes() + size(); }
+};
+
+class TcpPtr
+{
+ protected:
+ PacketPtr 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 IpPtr &ptr)
+ {
+ if (ptr->proto() == IP_PROTO_TCP)
+ set(ptr.p, sizeof(eth_hdr) + ptr->hlen());
+ else
+ set(0, 0);
+ }
+
+ public:
+ TcpPtr() {}
+ TcpPtr(const IpPtr &ptr) { set(ptr); }
+ TcpPtr(const TcpPtr &ptr) : p(ptr.p), off(ptr.off) {}
+
+ TcpHdr *operator->() { return h(); }
+ TcpHdr &operator*() { return *h(); }
+ operator TcpHdr *() { return h(); }
+
+ const TcpHdr *operator->() const { return h(); }
+ const TcpHdr &operator*() const { return *h(); }
+ operator const TcpHdr *() const { return h(); }
+
+ 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; }
+ bool operator!() const { return !p; }
+ operator bool() const { return p; }
+ operator bool() { return p; }
+};
+
+uint16_t cksum(const TcpPtr &ptr);
+
+typedef Range<uint16_t> SackRange;
+
+struct TcpOpt : public tcp_opt
+{
+ uint8_t type() const { return opt_type; }
+ uint8_t len() const { return TCP_OPT_TYPEONLY(type()) ? 1 : opt_len; }
+
+ bool isopt(int opt) const { return type() == opt; }
+
+ const uint8_t *data() const { return opt_data.data8; }
+
+ uint16_t mss() const { return ntohs(opt_data.mss); }
+ uint8_t wscale() const { return opt_data.wscale; }
+ bool sack(std::vector<SackRange> &vec) const;
+ uint32_t echo() const { return ntohl(opt_data.echo); }
+ uint32_t tsval() const { return ntohl(opt_data.timestamp[0]); }
+ uint32_t tsecr() const { return ntohl(opt_data.timestamp[1]); }
+ uint32_t cc() const { return ntohl(opt_data.cc); }
+ uint8_t cksum() const{ return opt_data.cksum; }
+ const uint8_t *md5() const { return opt_data.md5; }
+
+ int size() const { return len(); }
+ const uint8_t *bytes() const { return (const uint8_t *)this; }
+ const uint8_t *payload() const { return bytes() + size(); }
+ uint8_t *bytes() { return (uint8_t *)this; }
+ uint8_t *payload() { return bytes() + size(); }
+};
+
+/*
+ * UDP Stuff
+ */
+struct UdpHdr : public udp_hdr
+{
+ uint16_t sport() const { return ntohs(uh_sport); }
+ uint16_t dport() const { return ntohs(uh_dport); }
+ uint16_t len() const { return ntohs(uh_ulen); }
+ uint16_t sum() const { return uh_sum; }
+
+ void sum(uint16_t sum) { uh_sum = sum; }
+
+ int size() const { return sizeof(udp_hdr); }
+ const uint8_t *bytes() const { return (const uint8_t *)this; }
+ const uint8_t *payload() const { return bytes() + size(); }
+ uint8_t *bytes() { return (uint8_t *)this; }
+ uint8_t *payload() { return bytes() + size(); }
+};
+
+class UdpPtr
+{
+ protected:
+ PacketPtr 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 IpPtr &ptr)
+ {
+ if (ptr->proto() == IP_PROTO_UDP)
+ set(ptr.p, sizeof(eth_hdr) + ptr->hlen());
+ else
+ set(0, 0);
+ }
+
+ public:
+ UdpPtr() {}
+ UdpPtr(const IpPtr &ptr) { set(ptr); }
+ UdpPtr(const UdpPtr &ptr) : p(ptr.p), off(ptr.off) {}
+
+ UdpHdr *operator->() { return h(); }
+ UdpHdr &operator*() { return *h(); }
+ operator UdpHdr *() { return h(); }
+
+ const UdpHdr *operator->() const { return h(); }
+ const UdpHdr &operator*() const { return *h(); }
+ operator const UdpHdr *() const { return h(); }
+
+ 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; }
+ bool operator!() const { return !p; }
+ operator bool() const { return p; }
+ operator bool() { return p; }
+};
+
+uint16_t cksum(const UdpPtr &ptr);
+
+/* namespace Net */ }
+
+#endif // __BASE_INET_HH__
diff --git a/base/intmath.hh b/base/intmath.hh
index 821514668..5ffe27103 100644
--- a/base/intmath.hh
+++ b/base/intmath.hh
@@ -120,7 +120,7 @@ FloorLog2(int64_t x)
}
#if defined(__APPLE__)
-int
+inline int
FloorLog2(size_t x)
{
assert(x > 0);
diff --git a/base/loader/ecoff_object.cc b/base/loader/ecoff_object.cc
index bab75944d..714f1d7b8 100644
--- a/base/loader/ecoff_object.cc
+++ b/base/loader/ecoff_object.cc
@@ -108,14 +108,14 @@ EcoffObject::loadGlobalSymbols(SymbolTable *symtab)
return false;
if (fileHdr->f_magic != ECOFF_MAGIC_ALPHA) {
- cprintf("wrong magic\n");
+ warn("loadGlobalSymbols: wrong magic on %s\n", filename);
return false;
}
ecoff_symhdr *syms = (ecoff_symhdr *)(fileData + fileHdr->f_symptr);
if (syms->magic != magicSym2) {
- cprintf("bad symbol header magic\n");
- exit(1);
+ warn("loadGlobalSymbols: bad symbol header magic on %s\n", filename);
+ return false;
}
ecoff_extsym *ext_syms = (ecoff_extsym *)(fileData + syms->cbExtOffset);
@@ -137,14 +137,14 @@ EcoffObject::loadLocalSymbols(SymbolTable *symtab)
return false;
if (fileHdr->f_magic != ECOFF_MAGIC_ALPHA) {
- cprintf("wrong magic\n");
+ warn("loadGlobalSymbols: wrong magic on %s\n", filename);
return false;
}
ecoff_symhdr *syms = (ecoff_symhdr *)(fileData + fileHdr->f_symptr);
if (syms->magic != magicSym2) {
- cprintf("bad symbol header magic\n");
- exit(1);
+ warn("loadGlobalSymbols: bad symbol header magic on %s\n", filename);
+ return false;
}
ecoff_sym *local_syms = (ecoff_sym *)(fileData + syms->cbSymOffset);
diff --git a/base/loader/symtab.cc b/base/loader/symtab.cc
index f6abf7e3d..2a29a8575 100644
--- a/base/loader/symtab.cc
+++ b/base/loader/symtab.cc
@@ -38,6 +38,8 @@
using namespace std;
+SymbolTable *debugSymbolTable = NULL;
+
bool
SymbolTable::insert(Addr address, string symbol)
{
@@ -95,26 +97,20 @@ SymbolTable::load(const string &filename)
}
bool
-SymbolTable::findNearestSymbol(Addr address, string &symbol) const
+SymbolTable::findNearestSymbol(Addr address, string &symbol,
+ Addr &sym_address, Addr &next_sym_address) const
{
- ATable::const_iterator i = addrTable.lower_bound(address);
-
- // check for PALCode
- if (address & 0x1)
- return false;
+ // find first key *larger* than desired address
+ ATable::const_iterator i = addrTable.upper_bound(address);
- // first check for the end
- if (i == addrTable.end())
- i--;
- else if (i == addrTable.begin() && (*i).first != address)
+ // if very first key is larger, we're out of luck
+ if (i == addrTable.begin())
return false;
- else if ((*i).first != address)
- i--;
-
- symbol = (*i).second;
- if (address != (*i).first)
- symbol += csprintf("+%d", address - (*i).first);
+ next_sym_address = i->first;
+ --i;
+ sym_address = i->first;
+ symbol = i->second;
return true;
}
@@ -140,19 +136,3 @@ SymbolTable::findAddress(const string &symbol, Addr &address) const
address = (*i).second;
return true;
}
-
-string
-SymbolTable::find(Addr addr) const
-{
- string s;
- findSymbol(addr, s);
- return s;
-}
-
-Addr
-SymbolTable::find(const string &symbol) const
-{
- Addr a = 0;
- findAddress(symbol, a);
- return a;
-}
diff --git a/base/loader/symtab.hh b/base/loader/symtab.hh
index 48230c7a2..5ae29b057 100644
--- a/base/loader/symtab.hh
+++ b/base/loader/symtab.hh
@@ -49,12 +49,35 @@ class SymbolTable
bool insert(Addr address, std::string symbol);
bool load(const std::string &file);
- bool findNearestSymbol(Addr address, std::string &symbol) const;
+ /// Find the nearest symbol equal to or less than the supplied
+ /// address (e.g., the label for the enclosing function).
+ /// @param address The address to look up.
+ /// @param symbol Return reference for symbol string.
+ /// @param sym_address Return reference for symbol address.
+ /// @param next_sym_address Address of following symbol (for
+ /// determining valid range of symbol).
+ /// @retval True if a symbol was found.
+ bool findNearestSymbol(Addr address, std::string &symbol,
+ Addr &sym_address, Addr &next_sym_address) const;
+
+ /// Overload for findNearestSymbol() for callers who don't care
+ /// about next_sym_address.
+ bool findNearestSymbol(Addr address, std::string &symbol,
+ Addr &sym_address) const
+ {
+ Addr dummy;
+ return findNearestSymbol(address, symbol, sym_address, dummy);
+ }
+
+
bool findSymbol(Addr address, std::string &symbol) const;
bool findAddress(const std::string &symbol, Addr &address) const;
-
- std::string find(Addr addr) const;
- Addr find(const std::string &symbol) const;
};
+/// Global unified debugging symbol table (for target). Conceptually
+/// there should be one of these per System object for full system,
+/// and per Process object for non-full-system, but so far one big
+/// global one has worked well enough.
+extern SymbolTable *debugSymbolTable;
+
#endif // __SYMTAB_HH__
diff --git a/base/random.cc b/base/random.cc
index f18ed546d..9a4562e8a 100644
--- a/base/random.cc
+++ b/base/random.cc
@@ -39,7 +39,7 @@ class RandomContext : public ParamContext
public:
RandomContext(const string &_iniSection)
: ::ParamContext(_iniSection) {}
- ~RandomContext();
+ ~RandomContext() {}
void checkParams();
};
diff --git a/base/random.hh b/base/random.hh
index 5169c548a..0bfed100c 100644
--- a/base/random.hh
+++ b/base/random.hh
@@ -26,8 +26,8 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#ifndef __RANDOM_HH__
-#define __RANDOM_HH__
+#ifndef __BASE_RANDOM_HH__
+#define __BASE_RANDOM_HH__
#include "sim/host.hh"
@@ -45,56 +45,56 @@ struct Random<int8_t>
struct Random<uint8_t>
{
- uint8_t get()
+ static uint8_t get()
{ return getLong() & (uint8_t)-1; }
};
struct Random<int16_t>
{
- int16_t get()
+ static int16_t get()
{ return getLong() & (int16_t)-1; }
};
struct Random<uint16_t>
{
- uint16_t get()
+ static uint16_t get()
{ return getLong() & (uint16_t)-1; }
};
struct Random<int32_t>
{
- int32_t get()
+ static int32_t get()
{ return (int32_t)getLong(); }
};
struct Random<uint32_t>
{
- uint32_t get()
+ static uint32_t get()
{ return (uint32_t)getLong(); }
};
struct Random<int64_t>
{
- int64_t get()
+ static int64_t get()
{ return (int64_t)getLong() << 32 || (uint64_t)getLong(); }
};
struct Random<uint64_t>
{
- uint64_t get()
+ static uint64_t get()
{ return (uint64_t)getLong() << 32 || (uint64_t)getLong(); }
};
struct Random<float>
{
- float get()
+ static float get()
{ return getDouble(); }
};
struct Random<double>
{
- double get()
+ static double get()
{ return getDouble(); }
};
-#endif // __RANDOM_HH__
+#endif // __BASE_RANDOM_HH__
diff --git a/base/range.cc b/base/range.cc
index 4453ecc9f..1087c02c8 100644
--- a/base/range.cc
+++ b/base/range.cc
@@ -34,12 +34,12 @@ using namespace std;
template <class T>
bool
-__x_parse_range(const std::string &str, T &start, T &end)
+__x_parse_range(const std::string &str, T &first, T &last)
{
std::vector<std::string> values;
tokenize(values, str, ':');
- T thestart, theend;
+ T thefirst, thelast;
if (values.size() != 2)
return false;
@@ -47,29 +47,29 @@ __x_parse_range(const std::string &str, T &start, T &end)
std::string s = values[0];
std::string e = values[1];
- if (!to_number(s, thestart))
+ if (!to_number(s, thefirst))
return false;
bool increment = (e[0] == '+');
if (increment)
e = e.substr(1);
- if (!to_number(e, theend))
+ if (!to_number(e, thelast))
return false;
if (increment)
- theend += thestart;
+ thelast += thefirst - 1;
- start = thestart;
- end = theend;
+ first = thefirst;
+ last = thelast;
return true;
}
#define RANGE_PARSE(type) \
template<> bool \
-__parse_range(const std::string &s, type &start, type &end) \
-{ return __x_parse_range(s, start, end); }
+__parse_range(const std::string &s, type &first, type &last) \
+{ return __x_parse_range(s, first, last); }
RANGE_PARSE(unsigned long long);
RANGE_PARSE(signed long long);
diff --git a/base/range.hh b/base/range.hh
index 2197e2f86..9289792ea 100644
--- a/base/range.hh
+++ b/base/range.hh
@@ -26,44 +26,32 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#ifndef __RANGE_HH__
-#define __RANGE_HH__
+#ifndef __BASE_RANGE_HH__
+#define __BASE_RANGE_HH__
#include <cassert>
#include <string>
+/**
+ * @param s range string
+ * EndExclusive Ranges are in the following format:
+ * <range> := {<start_val>}:{<end>}
+ * <start> := <end_val> | +<delta>
+ */
template <class T>
bool __parse_range(const std::string &s, T &start, T &end);
template <class T>
struct Range
{
- private:
- /**
- * @param s range string
- * Ranges are in the following format:
- * <range> := {<start_val>}:{<end>}
- * <end> := <end_val> | +<delta>
- */
- void
- parse(const std::string &s)
- {
- if (!__parse_range(s, start, end))
- invalidate();
- }
-
- public:
T start;
T end;
- public:
- Range()
- {
- invalidate();
- }
+ Range() { invalidate(); }
- Range(T first, T second)
- : start(first), end(second)
+ template <class U>
+ Range(const std::pair<U, U> &r)
+ : start(r.first), end(r.second)
{}
template <class U>
@@ -71,14 +59,10 @@ struct Range
: start(r.start), end(r.end)
{}
- template <class U>
- Range(const std::pair<U, U> &r)
- : start(r.first), end(r.second)
- {}
-
Range(const std::string &s)
{
- parse(s);
+ if (!__parse_range(s, start, end))
+ invalidate();
}
template <class U>
@@ -99,32 +83,39 @@ struct Range
const Range &operator=(const std::string &s)
{
- parse(s);
+ if (!__parse_range(s, start, end))
+ invalidate();
return *this;
}
- void invalidate() { start = 0; end = 0; }
- T size() const { return end - start; }
+ void invalidate() { start = 1; end = 0; }
+ T size() const { return end - start + 1; }
bool valid() const { return start < end; }
};
template <class T>
-inline Range<T>
-make_range(T start, T end)
-{
- return Range<T>(start, end);
-}
-
-template <class T>
inline std::ostream &
operator<<(std::ostream &o, const Range<T> &r)
{
- // don't currently support output of invalid ranges
- assert(r.valid());
- o << r.start << ":" << r.end;
+ o << '[' << r.start << "," << r.end << ']';
return o;
}
+template <class T>
+inline Range<T>
+RangeEx(T start, T end)
+{ return std::make_pair(start, end - 1); }
+
+template <class T>
+inline Range<T>
+RangeIn(T start, T end)
+{ return std::make_pair(start, end); }
+
+template <class T, class U>
+inline Range<T>
+RangeSize(T start, U size)
+{ return std::make_pair(start, start + size - 1); }
+
////////////////////////////////////////////////////////////////////////
//
// Range to Range Comparisons
@@ -139,7 +130,6 @@ template <class T, class U>
inline bool
operator==(const Range<T> &range1, const Range<U> &range2)
{
- assert(range1.valid() && range2.valid());
return range1.start == range2.start && range1.end == range2.end;
}
@@ -152,7 +142,6 @@ template <class T, class U>
inline bool
operator!=(const Range<T> &range1, const Range<U> &range2)
{
- assert(range1.valid() && range2.valid());
return range1.start != range2.start || range1.end != range2.end;
}
@@ -165,8 +154,7 @@ template <class T, class U>
inline bool
operator<(const Range<T> &range1, const Range<U> &range2)
{
- assert(range1.valid() && range2.valid());
- return range1.end <= range2.start;
+ return range1.start < range2.start;
}
/**
@@ -179,8 +167,7 @@ template <class T, class U>
inline bool
operator<=(const Range<T> &range1, const Range<U> &range2)
{
- assert(range1.valid() && range2.valid());
- return range1.start <= range2.start && range1.end <= range2.end;
+ return range1.start <= range2.start;
}
/**
@@ -192,8 +179,7 @@ template <class T, class U>
inline bool
operator>(const Range<T> &range1, const Range<U> &range2)
{
- assert(range1.valid() && range2.valid());
- return range1.start >= range2.end;
+ return range1.start > range2.start;
}
/**
@@ -206,8 +192,7 @@ template <class T, class U>
inline bool
operator>=(const Range<T> &range1, const Range<U> &range2)
{
- assert(range1.valid() && range2.valid());
- return range1.start >= range2.start && range1.end >= range2.end;
+ return range1.start >= range2.start;
}
////////////////////////////////////////////////////////////////////////
@@ -224,7 +209,6 @@ template <class T, class U>
inline bool
operator==(const T &pos, const Range<U> &range)
{
- assert(range.valid());
return pos >= range.start && pos <= range.end;
}
@@ -237,8 +221,7 @@ template <class T, class U>
inline bool
operator!=(const T &pos, const Range<U> &range)
{
- assert(range.valid());
- return pos < range.start || pos >= range.end;
+ return pos < range.start || pos > range.end;
}
/**
@@ -250,7 +233,6 @@ template <class T, class U>
inline bool
operator<(const T &pos, const Range<U> &range)
{
- assert(range.valid());
return pos < range.start;
}
@@ -263,8 +245,7 @@ template <class T, class U>
inline bool
operator<=(const T &pos, const Range<U> &range)
{
- assert(range.valid());
- return pos < range.end;
+ return pos <= range.end;
}
/**
@@ -276,8 +257,7 @@ template <class T, class U>
inline bool
operator>(const T &pos, const Range<U> &range)
{
- assert(range.valid());
- return pos >= range.end;
+ return pos > range.end;
}
/**
@@ -289,7 +269,6 @@ template <class T, class U>
inline bool
operator>=(const T &pos, const Range<U> &range)
{
- assert(range.valid());
return pos >= range.start;
}
@@ -307,8 +286,7 @@ template <class T, class U>
inline bool
operator==(const Range<T> &range, const U &pos)
{
- assert(range.valid());
- return pos >= range.start && pos < range.end;
+ return pos >= range.start && pos <= range.end;
}
/**
@@ -320,8 +298,7 @@ template <class T, class U>
inline bool
operator!=(const Range<T> &range, const U &pos)
{
- assert(range.valid());
- return pos < range.start || pos >= range.end;
+ return pos < range.start || pos > range.end;
}
/**
@@ -333,8 +310,7 @@ template <class T, class U>
inline bool
operator<(const Range<T> &range, const U &pos)
{
- assert(range.valid());
- return range.end <= pos;
+ return range.end < pos;
}
/**
@@ -346,7 +322,6 @@ template <class T, class U>
inline bool
operator<=(const Range<T> &range, const U &pos)
{
- assert(range.valid());
return range.start <= pos;
}
@@ -359,7 +334,6 @@ template <class T, class U>
inline bool
operator>(const Range<T> &range, const U &pos)
{
- assert(range.valid());
return range.start > pos;
}
@@ -372,8 +346,7 @@ template <class T, class U>
inline bool
operator>=(const Range<T> &range, const U &pos)
{
- assert(range.valid());
- return range.end > pos;
+ return range.end >= pos;
}
-#endif // __RANGE_HH__
+#endif // __BASE_RANGE_HH__
diff --git a/base/refcnt.hh b/base/refcnt.hh
index d308dd0cf..00ba8fa4a 100644
--- a/base/refcnt.hh
+++ b/base/refcnt.hh
@@ -48,18 +48,29 @@ class RefCounted
template <class T>
class RefCountingPtr
{
- private:
+ protected:
T *data;
- void copy(T *d) {
+ void copy(T *d)
+ {
data = d;
if (data)
data->incref();
}
- void del() {
+ void del()
+ {
if (data)
data->decref();
}
+ void set(T *d)
+ {
+ if (data == d)
+ return;
+
+ del();
+ copy(d);
+ }
+
public:
RefCountingPtr() : data(NULL) {}
@@ -75,21 +86,9 @@ class RefCountingPtr
const T &operator*() const { return *data; }
const T *get() const { return data; }
- RefCountingPtr &operator=(T *p) {
- if (data != p) {
- del();
- copy(p);
- }
- return *this;
- }
-
- RefCountingPtr &operator=(const RefCountingPtr &r) {
- if (data != r.data) {
- del();
- copy(r.data);
- }
- return *this;
- }
+ RefCountingPtr &operator=(T *p) { set(p); return *this; }
+ RefCountingPtr &operator=(const RefCountingPtr &r)
+ { return operator=(r.data); }
bool operator!() const { return data == 0; }
operator bool() const { return data != 0; }
diff --git a/base/remote_gdb.cc b/base/remote_gdb.cc
index 41f11005d..484a01944 100644
--- a/base/remote_gdb.cc
+++ b/base/remote_gdb.cc
@@ -326,14 +326,13 @@ bool
RemoteGDB::acc(Addr va, size_t len)
{
Addr last_va;
- Addr pte;
- va = alpha_trunc_page(va);
- last_va = alpha_round_page(va + len);
+ va = TheISA::TruncPage(va);
+ last_va = TheISA::RoundPage(va + len);
do {
- if (va >= ALPHA_K0SEG_BASE && va < ALPHA_K1SEG_BASE) {
- if (va < (ALPHA_K0SEG_BASE + pmem->size())) {
+ if (TheISA::IsK0Seg(va)) {
+ if (va < (TheISA::K0SegBase + pmem->size())) {
DPRINTF(GDBAcc, "acc: Mapping is valid K0SEG <= "
"%#x < K0SEG + size\n", va);
return true;
@@ -351,16 +350,16 @@ RemoteGDB::acc(Addr va, size_t len)
* but there is no easy way to do it.
*/
- if (PC_PAL(va) || va < 0x10000)
+ if (AlphaISA::PcPAL(va) || va < 0x10000)
return true;
Addr ptbr = context->regs.ipr[AlphaISA::IPR_PALtemp20];
- pte = kernel_pte_lookup(pmem, ptbr, va);
- if (!pte || !entry_valid(pmem->phys_read_qword(pte))) {
+ TheISA::PageTableEntry pte = kernel_pte_lookup(pmem, ptbr, va);
+ if (!pte.valid()) {
DPRINTF(GDBAcc, "acc: %#x pte is invalid\n", va);
return false;
}
- va += ALPHA_PGBYTES;
+ va += TheISA::PageBytes;
} while (va < last_va);
DPRINTF(GDBAcc, "acc: %#x mapping is valid\n", va);
diff --git a/base/socket.cc b/base/socket.cc
index aa6a183a9..ee87dc057 100644
--- a/base/socket.cc
+++ b/base/socket.cc
@@ -64,7 +64,7 @@ ListenSocket::listen(int port, bool reuse)
fd = ::socket(PF_INET, SOCK_STREAM, 0);
if (fd < 0)
- panic("Can't create socket!");
+ panic("Can't create socket:%s !", strerror(errno));
if (reuse) {
int i = 1;
diff --git a/base/stats/types.hh b/base/stats/types.hh
index fbabfb118..8e45531fb 100644
--- a/base/stats/types.hh
+++ b/base/stats/types.hh
@@ -30,7 +30,7 @@
#define __BASE_STATS_TYPES_HH__
#include <vector>
-#include <inttypes.h>
+#include "sim/host.hh"
namespace Stats {
diff --git a/base/trace.hh b/base/trace.hh
index 1aadb36cf..5e05d6e5e 100644
--- a/base/trace.hh
+++ b/base/trace.hh
@@ -157,8 +157,16 @@ namespace Trace {
extern const std::string DefaultName;
};
-inline const std::string &name() { return Trace::DefaultName; }
+// This silly little class allows us to wrap a string in a functor
+// object so that we can give a name() that DPRINTF will like
+struct StringWrap
+{
+ std::string str;
+ StringWrap(const std::string &s) : str(s) {}
+ const std::string &operator()() const { return str; }
+};
+inline const std::string &name() { return Trace::DefaultName; }
std::ostream &DebugOut();
//
diff --git a/base/traceflags.py b/base/traceflags.py
index eb404fa54..1f69e5e88 100644
--- a/base/traceflags.py
+++ b/base/traceflags.py
@@ -123,6 +123,7 @@ baseFlags = [
'Uart',
'Split',
'SQL',
+ 'Thread',
'Fetch',
'Decode',
'Rename',
diff --git a/build/SConstruct b/build/SConstruct
index 22f39b72c..a1f1cdc5c 100644
--- a/build/SConstruct
+++ b/build/SConstruct
@@ -93,7 +93,7 @@ def AlphaConfig(env):
def KernelConfig(env):
env.Replace(TARGET_ISA = 'alpha')
env.Replace(FULL_SYSTEM = True)
- env.Append(CPPDEFINES = ['FULL_SYSTEM', 'SYSTEM_EV5'])
+ env.Append(CPPDEFINES = ['FULL_SYSTEM'])
# Base configurations map.
configs_map = {
@@ -244,12 +244,24 @@ default_env = Environment(ENV = os.environ, # inherit user's enviroment vars
FULL_SYSTEM = False,
USE_MYSQL = False)
+default_env.SConsignFile("sconsign")
+
+# For some reason, the CC and CXX variables don't get passed into the
+# environment correctly. This is probably some sort of scons bug that
+# will eventually be fixed.
+if os.environ.has_key('CC'):
+ default_env.Replace(CC=os.environ['CC'])
+
+if os.environ.has_key('CXX'):
+ default_env.Replace(CXX=os.environ['CXX'])
+
# M5_EXT is used by isa_parser.py to find the PLY package.
default_env.Append(ENV = { 'M5_EXT' : EXT_SRCDIR })
default_env.Append(CCFLAGS='-pipe')
default_env.Append(CCFLAGS='-fno-strict-aliasing')
default_env.Append(CCFLAGS=Split('-Wall -Wno-sign-compare -Werror -Wundef'))
+default_env.Append(CPPPATH=[os.path.join(EXT_SRCDIR + '/dnet')])
# libelf build is described in its own SConscript file. Using a
# dictionary for exports lets us export "default_env" so the
diff --git a/configs/boot/nat-netperf-maerts-client.rcS b/configs/boot/nat-netperf-maerts-client.rcS
new file mode 100644
index 000000000..fa3e174e7
--- /dev/null
+++ b/configs/boot/nat-netperf-maerts-client.rcS
@@ -0,0 +1,48 @@
+#!/bin/sh
+SERVER=192.168.0.1
+CLIENT=10.0.0.2
+
+echo "setting up network..."
+ifconfig lo 127.0.0.1
+ifconfig eth0 $CLIENT txqueuelen 1000
+
+echo "modifying route table..."
+route add default gw 10.0.0.1
+
+echo "0" > /proc/sys/net/ipv4/tcp_timestamps
+echo "0" > /proc/sys/net/ipv4/tcp_sack
+echo "5000000 5000000 5000000" > /proc/sys/net/ipv4/tcp_rmem
+echo "5000000 5000000 5000000" > /proc/sys/net/ipv4/tcp_wmem
+echo "5000000 5000000 5000000" > /proc/sys/net/ipv4/tcp_mem
+echo "262143" > /proc/sys/net/core/rmem_max
+echo "262143" > /proc/sys/net/core/wmem_max
+echo "262143" > /proc/sys/net/core/rmem_default
+echo "262143" > /proc/sys/net/core/wmem_default
+echo "262143" > /proc/sys/net/core/optmem_max
+echo "100000" > /proc/sys/net/core/netdev_max_backlog
+
+echo -n "waiting for server..."
+/usr/bin/netcat -c -l -p 8000
+
+BINARY=/benchmarks/netperf/netperf
+TEST="TCP_MAERTS"
+SHORT_ARGS="-l -100k"
+LONG_ARGS="-k16384,0 -K16384,0 -- -m 65536 -M 65536 -s 262144 -S 262144"
+
+
+SHORT="$BINARY -H $SERVER -t $TEST $SHORT_ARGS"
+LONG="$BINARY -H $SERVER -t $TEST $LONG_ARGS"
+
+echo "starting test..."
+echo "netperf warmup"
+echo $SHORT
+eval $SHORT
+
+echo "netperf benchmark"
+echo $LONG
+/sbin/m5 ivlb 1
+/sbin/m5 resetstats
+/sbin/m5 dumpresetstats 200000000 2000000000
+/sbin/m5 checkpoint 200000000 2000000000
+eval $LONG
+/sbin/m5 exit
diff --git a/configs/boot/nat-netperf-server.rcS b/configs/boot/nat-netperf-server.rcS
new file mode 100644
index 000000000..c0646b61c
--- /dev/null
+++ b/configs/boot/nat-netperf-server.rcS
@@ -0,0 +1,30 @@
+#!/bin/sh
+SERVER=192.168.0.1
+CLIENT=10.0.0.2
+NATBOX=192.168.0.2
+
+echo "setting up network..."
+ifconfig lo 127.0.0.1
+ifconfig eth0 $SERVER txqueuelen 1000
+
+echo "0" > /proc/sys/net/ipv4/tcp_timestamps
+echo "0" > /proc/sys/net/ipv4/tcp_sack
+echo "5000000 5000000 5000000" > /proc/sys/net/ipv4/tcp_rmem
+echo "5000000 5000000 5000000" > /proc/sys/net/ipv4/tcp_wmem
+echo "5000000 5000000 5000000" > /proc/sys/net/ipv4/tcp_mem
+echo "262143" > /proc/sys/net/core/rmem_max
+echo "262143" > /proc/sys/net/core/wmem_max
+echo "262143" > /proc/sys/net/core/rmem_default
+echo "262143" > /proc/sys/net/core/wmem_default
+echo "262143" > /proc/sys/net/core/optmem_max
+echo "100000" > /proc/sys/net/core/netdev_max_backlog
+
+echo "running netserver..."
+/benchmarks/netperf/netserver
+
+echo -n "signal client to begin..."
+echo "server ready" | /usr/bin/netcat -c $NATBOX 8000
+echo "done."
+
+echo "starting bash..."
+exec /bin/bash
diff --git a/configs/boot/nat-netperf-stream-client.rcS b/configs/boot/nat-netperf-stream-client.rcS
new file mode 100644
index 000000000..f0f3a23ce
--- /dev/null
+++ b/configs/boot/nat-netperf-stream-client.rcS
@@ -0,0 +1,48 @@
+#!/bin/sh
+SERVER=192.168.0.1
+CLIENT=10.0.0.2
+
+echo "setting up network..."
+ifconfig lo 127.0.0.1
+ifconfig eth0 $CLIENT txqueuelen 1000
+
+echo "0" > /proc/sys/net/ipv4/tcp_timestamps
+echo "0" > /proc/sys/net/ipv4/tcp_sack
+echo "5000000 5000000 5000000" > /proc/sys/net/ipv4/tcp_rmem
+echo "5000000 5000000 5000000" > /proc/sys/net/ipv4/tcp_wmem
+echo "5000000 5000000 5000000" > /proc/sys/net/ipv4/tcp_mem
+echo "262143" > /proc/sys/net/core/rmem_max
+echo "262143" > /proc/sys/net/core/wmem_max
+echo "262143" > /proc/sys/net/core/rmem_default
+echo "262143" > /proc/sys/net/core/wmem_default
+echo "262143" > /proc/sys/net/core/optmem_max
+echo "100000" > /proc/sys/net/core/netdev_max_backlog
+
+echo "modifying route table"
+route add default gw 10.0.0.1
+
+echo -n "waiting for server..."
+/usr/bin/netcat -c -l -p 8000
+
+BINARY=/benchmarks/netperf/netperf
+TEST="TCP_STREAM"
+SHORT_ARGS="-l -100k"
+LONG_ARGS="-k16384,0 -K16384,0 -- -m 65536 -M 65536 -s 262144 -S 262144"
+
+
+SHORT="$BINARY -H $SERVER -t $TEST $SHORT_ARGS"
+LONG="$BINARY -H $SERVER -t $TEST $LONG_ARGS"
+
+echo "starting test..."
+echo "netperf warmup"
+echo $SHORT
+eval $SHORT
+
+echo "netperf benchmark"
+echo $LONG
+/sbin/m5 ivlb 1
+/sbin/m5 resetstats
+/sbin/m5 dumpresetstats 200000000 2000000000
+/sbin/m5 checkpoint 200000000 2000000000
+eval $LONG
+/sbin/m5 exit
diff --git a/configs/boot/nat-spec-surge-client.rcS b/configs/boot/nat-spec-surge-client.rcS
new file mode 100644
index 000000000..2c0b46607
--- /dev/null
+++ b/configs/boot/nat-spec-surge-client.rcS
@@ -0,0 +1,51 @@
+#!/bin/sh
+#
+# /etc/init.d/rcS
+#
+CLIENT=10.0.0.2
+SERVER=192.168.0.1
+
+echo -n "mounting swap..."
+/sbin/swapon /dev/hdc
+echo "done."
+
+echo -n "setting up network..."
+/sbin/ifconfig eth0 $CLIENT txqueuelen 1000
+/sbin/ifconfig lo 127.0.0.1
+
+echo "1" > /proc/sys/net/ipv4/tcp_tw_recycle
+echo "1" > /proc/sys/net/ipv4/tcp_tw_reuse
+echo "1" > /proc/sys/net/ipv4/tcp_window_scaling
+echo "0" > /proc/sys/net/ipv4/tcp_timestamps
+echo "0" > /proc/sys/net/ipv4/tcp_sack
+echo "15" > /proc/sys/net/ipv4/tcp_fin_timeout
+echo "16384" > /proc/sys/net/ipv4/tcp_max_syn_backlog
+
+echo "1024 65535" > /proc/sys/net/ipv4/ip_local_port_range
+echo "10000000 10000000 10000000" > /proc/sys/net/ipv4/tcp_rmem
+echo "10000000 10000000 10000000" > /proc/sys/net/ipv4/tcp_wmem
+echo "10000000 10000000 10000000" > /proc/sys/net/ipv4/tcp_mem
+
+echo "524287" > /proc/sys/net/core/rmem_max
+echo "524287" > /proc/sys/net/core/wmem_max
+echo "524287" > /proc/sys/net/core/optmem_max
+echo "300000" > /proc/sys/net/core/netdev_max_backlog
+
+echo "131072" > /proc/sys/fs/file-max
+echo "done."
+
+echo "changing route table..."
+route add default gw 10.0.0.1
+
+echo "waiting for server..."
+/usr/bin/netcat -c -l -p 8000
+
+echo -n "running surge client..."
+/bin/bash -c "cd /benchmarks/surge && ./spec-m5 1 20 1 $SERVER 5 40000 1000000000 1000"
+echo "done."
+
+echo -n "halting machine"
+m5 exit
+
+echo -n "starting bash shell..."
+/bin/bash
diff --git a/configs/boot/nat-spec-surge-server.rcS b/configs/boot/nat-spec-surge-server.rcS
new file mode 100755
index 000000000..ed0e96a44
--- /dev/null
+++ b/configs/boot/nat-spec-surge-server.rcS
@@ -0,0 +1,56 @@
+#!/bin/sh
+#
+# /etc/init.d/rcS
+#
+NATBOX=192.168.0.7
+
+echo -n "mounting swap..."
+/sbin/swapon /dev/hdc
+echo "done."
+
+echo -n "setting up network..."
+/sbin/ifconfig eth0 192.168.0.1 txqueuelen 1000
+/sbin/ifconfig eth0:1 192.168.0.2 txqueuelen 1000
+/sbin/ifconfig eth0:2 192.168.0.3 txqueuelen 1000
+/sbin/ifconfig eth0:3 192.168.0.4 txqueuelen 1000
+/sbin/ifconfig eth0:4 192.168.0.5 txqueuelen 1000
+/sbin/ifconfig lo 127.0.0.1
+
+echo "1" > /proc/sys/net/ipv4/tcp_tw_recycle
+echo "1" > /proc/sys/net/ipv4/tcp_tw_reuse
+echo "1" > /proc/sys/net/ipv4/tcp_window_scaling
+echo "0" > /proc/sys/net/ipv4/tcp_timestamps
+echo "0" > /proc/sys/net/ipv4/tcp_sack
+echo "15" > /proc/sys/net/ipv4/tcp_fin_timeout
+echo "16384" > /proc/sys/net/ipv4/tcp_max_syn_backlog
+
+echo "1024 65535" > /proc/sys/net/ipv4/ip_local_port_range
+echo "10000000 10000000 10000000" > /proc/sys/net/ipv4/tcp_rmem
+echo "10000000 10000000 10000000" > /proc/sys/net/ipv4/tcp_wmem
+echo "10000000 10000000 10000000" > /proc/sys/net/ipv4/tcp_mem
+
+echo "524287" > /proc/sys/net/core/rmem_max
+echo "524287" > /proc/sys/net/core/wmem_max
+echo "524287" > /proc/sys/net/core/optmem_max
+echo "300000" > /proc/sys/net/core/netdev_max_backlog
+
+echo "131072" > /proc/sys/fs/file-max
+echo "done."
+
+echo -n "mounting file set..."
+mkdir -p /z/htdocs
+mount /dev/hdb1 /z/htdocs
+echo "done."
+
+echo -n "starting httpd..."
+/benchmarks/apache2/bin/apachectl start
+sleep 2
+cat /benchmarks/apache2/logs/error_log
+echo "done."
+
+echo "notifying natbox..."
+echo "server ready" | /usr/bin/netcat -c $NATBOX 8000
+echo "done"
+
+echo -n "starting bash shell..."
+/bin/bash
diff --git a/configs/boot/natbox-netperf.rcS b/configs/boot/natbox-netperf.rcS
new file mode 100644
index 000000000..d665670fe
--- /dev/null
+++ b/configs/boot/natbox-netperf.rcS
@@ -0,0 +1,51 @@
+#!/bin/sh
+EXTIF=192.168.0.2
+INTIF=10.0.0.1
+CLIENT=10.0.0.2
+
+echo "setting up network..."
+ifconfig lo 127.0.0.1
+ifconfig eth0 $EXTIF txqueuelen 1000
+ifconfig eth1 $INTIF txqueuelen 1000
+
+echo "0" > /proc/sys/net/ipv4/tcp_timestamps
+echo "0" > /proc/sys/net/ipv4/tcp_sack
+echo "5000000 5000000 5000000" > /proc/sys/net/ipv4/tcp_rmem
+echo "5000000 5000000 5000000" > /proc/sys/net/ipv4/tcp_wmem
+echo "5000000 5000000 5000000" > /proc/sys/net/ipv4/tcp_mem
+echo "262143" > /proc/sys/net/core/rmem_max
+echo "262143" > /proc/sys/net/core/wmem_max
+echo "262143" > /proc/sys/net/core/rmem_default
+echo "262143" > /proc/sys/net/core/wmem_default
+echo "262143" > /proc/sys/net/core/optmem_max
+echo "100000" > /proc/sys/net/core/netdev_max_backlog
+
+echo "1" > /proc/sys/net/ipv4/ip_forward
+
+echo "waiting for netserver..."
+/usr/bin/netcat -c -l -p 8000
+
+echo "setting up iptables..."
+IPTABLES=/sbin/iptables
+EXTIF=eth0
+INTIF=eth1
+
+$IPTABLES -P INPUT ACCEPT
+$IPTABLES -F INPUT
+$IPTABLES -P OUTPUT ACCEPT
+$IPTABLES -F OUTPUT
+$IPTABLES -P FORWARD DROP
+$IPTABLES -F FORWARD
+$IPTABLES -t nat -F
+
+$IPTABLES -A FORWARD -i $EXTIF -o $INTIF -m state --state ESTABLISHED,RELATED -j ACCEPT
+$IPTABLES -A FORWARD -i $INTIF -o $EXTIF -j ACCEPT
+$IPTABLES -A FORWARD -j LOG
+
+$IPTABLES -t nat -A POSTROUTING -o $EXTIF -j MASQUERADE
+
+echo "informing client..."
+echo "server ready" | /usr/bin/netcat -c $CLIENT 8000
+
+echo "starting bash..."
+exec /bin/bash
diff --git a/configs/boot/natbox-spec-surge.rcS b/configs/boot/natbox-spec-surge.rcS
new file mode 100644
index 000000000..ed74b71bd
--- /dev/null
+++ b/configs/boot/natbox-spec-surge.rcS
@@ -0,0 +1,51 @@
+#!/bin/sh
+EXTIF=192.168.0.7
+INTIF=10.0.0.1
+CLIENT=10.0.0.2
+
+echo "setting up network..."
+ifconfig lo 127.0.0.1
+ifconfig eth0 $EXTIF txqueuelen 1000
+ifconfig eth1 $INTIF txqueuelen 1000
+
+echo "0" > /proc/sys/net/ipv4/tcp_timestamps
+echo "0" > /proc/sys/net/ipv4/tcp_sack
+echo "5000000 5000000 5000000" > /proc/sys/net/ipv4/tcp_rmem
+echo "5000000 5000000 5000000" > /proc/sys/net/ipv4/tcp_wmem
+echo "5000000 5000000 5000000" > /proc/sys/net/ipv4/tcp_mem
+echo "262143" > /proc/sys/net/core/rmem_max
+echo "262143" > /proc/sys/net/core/wmem_max
+echo "262143" > /proc/sys/net/core/rmem_default
+echo "262143" > /proc/sys/net/core/wmem_default
+echo "262143" > /proc/sys/net/core/optmem_max
+echo "100000" > /proc/sys/net/core/netdev_max_backlog
+
+echo "1" > /proc/sys/net/ipv4/ip_forward
+
+echo "waiting for netserver..."
+/usr/bin/netcat -c -l -p 8000
+
+echo "setting up iptables..."
+IPTABLES=/sbin/iptables
+EXTIF=eth0
+INTIF=eth1
+
+$IPTABLES -P INPUT ACCEPT
+$IPTABLES -F INPUT
+$IPTABLES -P OUTPUT ACCEPT
+$IPTABLES -F OUTPUT
+$IPTABLES -P FORWARD DROP
+$IPTABLES -F FORWARD
+$IPTABLES -t nat -F
+
+$IPTABLES -A FORWARD -i $EXTIF -o $INTIF -m state --state ESTABLISHED,RELATED -j ACCEPT
+$IPTABLES -A FORWARD -i $INTIF -o $EXTIF -j ACCEPT
+$IPTABLES -A FORWARD -j LOG
+
+$IPTABLES -t nat -A POSTROUTING -o $EXTIF -j MASQUERADE
+
+echo "informing client..."
+echo "server ready" | /usr/bin/netcat -c $CLIENT 8000
+
+echo "starting bash..."
+exec /bin/bash
diff --git a/configs/boot/client.netperf.maerts b/configs/boot/netperf-maerts-client.rcS
index 916bb25ab..bd56dafc3 100644
--- a/configs/boot/client.netperf.maerts
+++ b/configs/boot/netperf-maerts-client.rcS
@@ -39,7 +39,7 @@ echo "netperf benchmark"
echo $LONG
/sbin/m5 ivlb 1
/sbin/m5 resetstats
-/sbin/m5 dumpresetstats 2000000000 2000000000
-/sbin/m5 checkpoint 2000000000 2000000000
+/sbin/m5 dumpresetstats 200000000 2000000000
+/sbin/m5 checkpoint 200000000 2000000000
eval $LONG
/sbin/m5 exit
diff --git a/configs/boot/client.netperf.rr b/configs/boot/netperf-rr.rcS
index b2128bed4..8c5ea050c 100644
--- a/configs/boot/client.netperf.rr
+++ b/configs/boot/netperf-rr.rcS
@@ -39,7 +39,7 @@ echo "netperf benchmark"
echo $LONG
/sbin/m5 ivlb 1
/sbin/m5 resetstats
-/sbin/m5 dumpresetstats 2000000000 2000000000
-/sbin/m5 checkpoint 2000000000 2000000000
+/sbin/m5 dumpresetstats 200000000 2000000000
+/sbin/m5 checkpoint 200000000 2000000000
eval $LONG
/sbin/m5 exit
diff --git a/configs/boot/server.netperf b/configs/boot/netperf-server.rcS
index f77ff0ce8..f77ff0ce8 100644
--- a/configs/boot/server.netperf
+++ b/configs/boot/netperf-server.rcS
diff --git a/configs/boot/client.netperf.stream b/configs/boot/netperf-stream-client.rcS
index 0dba6f1a2..430ac265c 100644
--- a/configs/boot/client.netperf.stream
+++ b/configs/boot/netperf-stream-client.rcS
@@ -39,7 +39,7 @@ echo "netperf benchmark"
echo $LONG
/sbin/m5 ivlb 1
/sbin/m5 resetstats
-/sbin/m5 dumpresetstats 2000000000 2000000000
-/sbin/m5 checkpoint 2000000000 2000000000
+/sbin/m5 dumpresetstats 200000000 2000000000
+/sbin/m5 checkpoint 200000000 2000000000
eval $LONG
/sbin/m5 exit
diff --git a/configs/boot/netperf-stream-nt-client.rcS b/configs/boot/netperf-stream-nt-client.rcS
new file mode 100644
index 000000000..96b6b38c3
--- /dev/null
+++ b/configs/boot/netperf-stream-nt-client.rcS
@@ -0,0 +1,45 @@
+#!/bin/sh
+SERVER=10.0.0.1
+CLIENT=10.0.0.2
+
+echo "setting up network..."
+ifconfig lo 127.0.0.1
+ifconfig eth0 $CLIENT txqueuelen 1000
+
+echo "0" > /proc/sys/net/ipv4/tcp_timestamps
+echo "0" > /proc/sys/net/ipv4/tcp_sack
+echo "5000000 5000000 5000000" > /proc/sys/net/ipv4/tcp_rmem
+echo "5000000 5000000 5000000" > /proc/sys/net/ipv4/tcp_wmem
+echo "5000000 5000000 5000000" > /proc/sys/net/ipv4/tcp_mem
+echo "262143" > /proc/sys/net/core/rmem_max
+echo "262143" > /proc/sys/net/core/wmem_max
+echo "262143" > /proc/sys/net/core/rmem_default
+echo "262143" > /proc/sys/net/core/wmem_default
+echo "262143" > /proc/sys/net/core/optmem_max
+echo "100000" > /proc/sys/net/core/netdev_max_backlog
+
+echo -n "waiting for server..."
+/usr/bin/netcat -c -l -p 8000
+
+BINARY=/benchmarks/netperf/netperf
+TEST="TCP_STREAM"
+SHORT_ARGS="-l -100k"
+LONG_ARGS="-- -m 65536 -M 65536 -s 262144 -S 262144"
+
+
+SHORT="$BINARY -H $SERVER -t $TEST $SHORT_ARGS"
+LONG="$BINARY -H $SERVER -t $TEST $LONG_ARGS"
+
+echo "starting test..."
+echo "netperf warmup"
+echo $SHORT
+eval $SHORT
+
+echo "netperf benchmark"
+echo $LONG
+/sbin/m5 ivlb 1
+/sbin/m5 resetstats
+/sbin/m5 dumpresetstats 200000000 2000000000
+/sbin/m5 checkpoint 200000000 2000000000
+eval $LONG
+/sbin/m5 exit
diff --git a/configs/boot/nfs-client-smallb.rcS b/configs/boot/nfs-client-smallb.rcS
new file mode 100755
index 000000000..22e2107eb
--- /dev/null
+++ b/configs/boot/nfs-client-smallb.rcS
@@ -0,0 +1,50 @@
+#!/bin/sh
+#
+# /etc/init.d/rcS
+#
+
+echo -n "mounting swap..."
+/sbin/swapon /dev/hdc
+echo "done."
+
+echo -n "setting up network..."
+/sbin/ifconfig eth0 10.0.0.2 txqueuelen 1000
+/sbin/ifconfig lo 127.0.0.1
+
+echo "1" > /proc/sys/net/ipv4/tcp_tw_recycle
+echo "1" > /proc/sys/net/ipv4/tcp_tw_reuse
+echo "1" > /proc/sys/net/ipv4/tcp_window_scaling
+echo "0" > /proc/sys/net/ipv4/tcp_timestamps
+echo "0" > /proc/sys/net/ipv4/tcp_sack
+echo "15" > /proc/sys/net/ipv4/tcp_fin_timeout
+echo "16384" > /proc/sys/net/ipv4/tcp_max_syn_backlog
+
+echo "1024 65535" > /proc/sys/net/ipv4/ip_local_port_range
+echo "10000000 10000000 10000000" > /proc/sys/net/ipv4/tcp_rmem
+echo "10000000 10000000 10000000" > /proc/sys/net/ipv4/tcp_wmem
+echo "10000000 10000000 10000000" > /proc/sys/net/ipv4/tcp_mem
+
+echo "524287" > /proc/sys/net/core/rmem_max
+echo "524287" > /proc/sys/net/core/wmem_max
+echo "524287" > /proc/sys/net/core/optmem_max
+echo "300000" > /proc/sys/net/core/netdev_max_backlog
+
+echo "131072" > /proc/sys/fs/file-max
+echo "done."
+
+echo -n "starting nfs client..."
+/sbin/portmap &
+/sbin/lockd &
+echo "done."
+
+echo -n "waiting for server..."
+/usr/bin/netcat -c -l -p 8000
+
+echo -n "mounting remote share..."
+mkdir /nfs
+mount -o rsize=1460,wsize=1460 10.0.0.1:/nfs /nfs
+echo "done."
+
+/bin/bonnie++ -u 99 -s 700 -r 0 -n 0 -f -F -d /nfs
+
+/sbin/m5 exit
diff --git a/configs/boot/nfs-client-tcp-smallb.rcS b/configs/boot/nfs-client-tcp-smallb.rcS
new file mode 100755
index 000000000..2ee232158
--- /dev/null
+++ b/configs/boot/nfs-client-tcp-smallb.rcS
@@ -0,0 +1,50 @@
+#!/bin/sh
+#
+# /etc/init.d/rcS
+#
+
+echo -n "mounting swap..."
+/sbin/swapon /dev/hdc
+echo "done."
+
+echo -n "setting up network..."
+/sbin/ifconfig eth0 10.0.0.2 txqueuelen 1000
+/sbin/ifconfig lo 127.0.0.1
+
+echo "1" > /proc/sys/net/ipv4/tcp_tw_recycle
+echo "1" > /proc/sys/net/ipv4/tcp_tw_reuse
+echo "1" > /proc/sys/net/ipv4/tcp_window_scaling
+echo "0" > /proc/sys/net/ipv4/tcp_timestamps
+echo "0" > /proc/sys/net/ipv4/tcp_sack
+echo "15" > /proc/sys/net/ipv4/tcp_fin_timeout
+echo "16384" > /proc/sys/net/ipv4/tcp_max_syn_backlog
+
+echo "1024 65535" > /proc/sys/net/ipv4/ip_local_port_range
+echo "10000000 10000000 10000000" > /proc/sys/net/ipv4/tcp_rmem
+echo "10000000 10000000 10000000" > /proc/sys/net/ipv4/tcp_wmem
+echo "10000000 10000000 10000000" > /proc/sys/net/ipv4/tcp_mem
+
+echo "524287" > /proc/sys/net/core/rmem_max
+echo "524287" > /proc/sys/net/core/wmem_max
+echo "524287" > /proc/sys/net/core/optmem_max
+echo "300000" > /proc/sys/net/core/netdev_max_backlog
+
+echo "131072" > /proc/sys/fs/file-max
+echo "done."
+
+echo -n "starting nfs client..."
+/sbin/portmap &
+/sbin/lockd &
+echo "done."
+
+echo -n "waiting for server..."
+/usr/bin/netcat -c -l -p 8000
+
+echo -n "mounting remote share..."
+mkdir /nfs
+mount -o rsize=1460,wsize=1460,tcp 10.0.0.1:/nfs /nfs
+echo "done."
+
+/bin/bonnie++ -u 99 -s 700 -r 0 -n 0 -f -F -d /nfs
+
+/sbin/m5 exit
diff --git a/configs/boot/nfs-client-tcp.rcS b/configs/boot/nfs-client-tcp.rcS
new file mode 100755
index 000000000..a67facbb2
--- /dev/null
+++ b/configs/boot/nfs-client-tcp.rcS
@@ -0,0 +1,50 @@
+#!/bin/sh
+#
+# /etc/init.d/rcS
+#
+
+echo -n "mounting swap..."
+/sbin/swapon /dev/hdc
+echo "done."
+
+echo -n "setting up network..."
+/sbin/ifconfig eth0 10.0.0.2 txqueuelen 1000
+/sbin/ifconfig lo 127.0.0.1
+
+echo "1" > /proc/sys/net/ipv4/tcp_tw_recycle
+echo "1" > /proc/sys/net/ipv4/tcp_tw_reuse
+echo "1" > /proc/sys/net/ipv4/tcp_window_scaling
+echo "0" > /proc/sys/net/ipv4/tcp_timestamps
+echo "0" > /proc/sys/net/ipv4/tcp_sack
+echo "15" > /proc/sys/net/ipv4/tcp_fin_timeout
+echo "16384" > /proc/sys/net/ipv4/tcp_max_syn_backlog
+
+echo "1024 65535" > /proc/sys/net/ipv4/ip_local_port_range
+echo "10000000 10000000 10000000" > /proc/sys/net/ipv4/tcp_rmem
+echo "10000000 10000000 10000000" > /proc/sys/net/ipv4/tcp_wmem
+echo "10000000 10000000 10000000" > /proc/sys/net/ipv4/tcp_mem
+
+echo "524287" > /proc/sys/net/core/rmem_max
+echo "524287" > /proc/sys/net/core/wmem_max
+echo "524287" > /proc/sys/net/core/optmem_max
+echo "300000" > /proc/sys/net/core/netdev_max_backlog
+
+echo "131072" > /proc/sys/fs/file-max
+echo "done."
+
+echo -n "starting nfs client..."
+/sbin/portmap &
+/sbin/lockd &
+echo "done."
+
+echo -n "waiting for server..."
+/usr/bin/netcat -c -l -p 8000
+
+echo -n "mounting remote share..."
+mkdir /nfs
+mount -o tcp 10.0.0.1:/nfs /nfs
+echo "done."
+
+/bin/bonnie++ -u 99 -s 700 -r 0 -n 0 -f -F -d /nfs
+
+/sbin/m5 exit
diff --git a/configs/boot/nfs-client.rcS b/configs/boot/nfs-client.rcS
new file mode 100755
index 000000000..a999fb72c
--- /dev/null
+++ b/configs/boot/nfs-client.rcS
@@ -0,0 +1,50 @@
+#!/bin/sh
+#
+# /etc/init.d/rcS
+#
+
+echo -n "mounting swap..."
+/sbin/swapon /dev/hdc
+echo "done."
+
+echo -n "setting up network..."
+/sbin/ifconfig eth0 10.0.0.2 txqueuelen 1000
+/sbin/ifconfig lo 127.0.0.1
+
+echo "1" > /proc/sys/net/ipv4/tcp_tw_recycle
+echo "1" > /proc/sys/net/ipv4/tcp_tw_reuse
+echo "1" > /proc/sys/net/ipv4/tcp_window_scaling
+echo "0" > /proc/sys/net/ipv4/tcp_timestamps
+echo "0" > /proc/sys/net/ipv4/tcp_sack
+echo "15" > /proc/sys/net/ipv4/tcp_fin_timeout
+echo "16384" > /proc/sys/net/ipv4/tcp_max_syn_backlog
+
+echo "1024 65535" > /proc/sys/net/ipv4/ip_local_port_range
+echo "10000000 10000000 10000000" > /proc/sys/net/ipv4/tcp_rmem
+echo "10000000 10000000 10000000" > /proc/sys/net/ipv4/tcp_wmem
+echo "10000000 10000000 10000000" > /proc/sys/net/ipv4/tcp_mem
+
+echo "524287" > /proc/sys/net/core/rmem_max
+echo "524287" > /proc/sys/net/core/wmem_max
+echo "524287" > /proc/sys/net/core/optmem_max
+echo "300000" > /proc/sys/net/core/netdev_max_backlog
+
+echo "131072" > /proc/sys/fs/file-max
+echo "done."
+
+echo -n "starting nfs client..."
+/sbin/portmap &
+/sbin/lockd &
+echo "done."
+
+echo -n "waiting for server..."
+/usr/bin/netcat -c -l -p 8000
+
+echo -n "mounting remote share..."
+mkdir /nfs
+mount 10.0.0.1:/nfs /nfs
+echo "done."
+
+/bin/bonnie++ -u 99 -s 700 -r 0 -n 0 -f -F -d /nfs
+
+/sbin/m5 exit
diff --git a/configs/boot/nfs-server.rcS b/configs/boot/nfs-server.rcS
new file mode 100755
index 000000000..21b7ab83c
--- /dev/null
+++ b/configs/boot/nfs-server.rcS
@@ -0,0 +1,70 @@
+#!/bin/sh
+#
+# /etc/init.d/rcS
+#
+
+echo -n "mounting swap..."
+/sbin/swapon /dev/hdc
+echo "done."
+
+echo -n "setting up network..."
+/sbin/ifconfig eth0 10.0.0.1 txqueuelen 1000
+/sbin/ifconfig lo 127.0.0.1
+
+echo "1" > /proc/sys/net/ipv4/tcp_tw_recycle
+echo "1" > /proc/sys/net/ipv4/tcp_tw_reuse
+echo "1" > /proc/sys/net/ipv4/tcp_window_scaling
+echo "0" > /proc/sys/net/ipv4/tcp_timestamps
+echo "0" > /proc/sys/net/ipv4/tcp_sack
+echo "15" > /proc/sys/net/ipv4/tcp_fin_timeout
+echo "16384" > /proc/sys/net/ipv4/tcp_max_syn_backlog
+
+echo "1024 65535" > /proc/sys/net/ipv4/ip_local_port_range
+echo "10000000 10000000 10000000" > /proc/sys/net/ipv4/tcp_rmem
+echo "10000000 10000000 10000000" > /proc/sys/net/ipv4/tcp_wmem
+echo "10000000 10000000 10000000" > /proc/sys/net/ipv4/tcp_mem
+
+echo "524287" > /proc/sys/net/core/rmem_max
+echo "524287" > /proc/sys/net/core/wmem_max
+echo "524287" > /proc/sys/net/core/optmem_max
+echo "300000" > /proc/sys/net/core/netdev_max_backlog
+
+echo "131072" > /proc/sys/fs/file-max
+echo "done."
+
+#if [ ! -x /dev/sda ]
+#then
+# mknod /dev/sda b 8 0
+# mknod /dev/sda1 b 8 1
+#fi
+
+/sbin/insmod /modules/scsi_debug.ko dev_size_mb=768
+
+echo -n "creating partition and formatting..."
+#echo "1,767,L" > /tmp/sfdisk.run
+#/usr/sbin/sfdisk -uM --force /dev/sda < /tmp/sfdisk.run
+/sbin/mke2fs -F /dev/sda
+mkdir /nfs
+/bin/mount /dev/sda /nfs
+chmod a+rwx /nfs
+#/usr/sbin/sfdisk -uM -l /dev/sda
+echo "done."
+
+echo "/nfs 10.0.0.0/255.0.0.0(rw,sync,no_root_squash)" > /etc/exports
+echo -n "starting nfs kernel server..."
+/sbin/portmap
+/sbin/lockd
+/sbin/statd
+/sbin/nfsd 8
+/sbin/mountd
+echo "done."
+
+echo "Exporting shares..."
+/sbin/exportfs -r -v
+
+echo -n "signal client to mount..."
+echo "server ready" | /usr/bin/netcat -c 10.0.0.2 8000
+echo "done."
+
+echo -n "starting bash shell..."
+/bin/bash
diff --git a/configs/boot/spec-surge-client.rcS b/configs/boot/spec-surge-client.rcS
new file mode 100644
index 000000000..6ce2ce9de
--- /dev/null
+++ b/configs/boot/spec-surge-client.rcS
@@ -0,0 +1,46 @@
+#!/bin/sh
+#
+# /etc/init.d/rcS
+#
+
+echo -n "mounting swap..."
+/sbin/swapon /dev/hdc
+echo "done."
+
+echo -n "setting up network..."
+/sbin/ifconfig eth0 192.168.0.10 txqueuelen 1000
+/sbin/ifconfig lo 127.0.0.1
+
+echo "1" > /proc/sys/net/ipv4/tcp_tw_recycle
+echo "1" > /proc/sys/net/ipv4/tcp_tw_reuse
+echo "1" > /proc/sys/net/ipv4/tcp_window_scaling
+echo "0" > /proc/sys/net/ipv4/tcp_timestamps
+echo "0" > /proc/sys/net/ipv4/tcp_sack
+echo "15" > /proc/sys/net/ipv4/tcp_fin_timeout
+echo "16384" > /proc/sys/net/ipv4/tcp_max_syn_backlog
+
+echo "1024 65535" > /proc/sys/net/ipv4/ip_local_port_range
+echo "10000000 10000000 10000000" > /proc/sys/net/ipv4/tcp_rmem
+echo "10000000 10000000 10000000" > /proc/sys/net/ipv4/tcp_wmem
+echo "10000000 10000000 10000000" > /proc/sys/net/ipv4/tcp_mem
+
+echo "524287" > /proc/sys/net/core/rmem_max
+echo "524287" > /proc/sys/net/core/wmem_max
+echo "524287" > /proc/sys/net/core/optmem_max
+echo "300000" > /proc/sys/net/core/netdev_max_backlog
+
+echo "131072" > /proc/sys/fs/file-max
+echo "done."
+
+echo "waiting for server..."
+/usr/bin/netcat -c -l -p 8000
+
+echo -n "running surge client..."
+/bin/bash -c "cd /benchmarks/surge && ./spec-m5 1 20 1 192.168.0.1 5 40000 1000000000 1000"
+echo "done."
+
+echo -n "halting machine"
+m5 exit
+
+echo -n "starting bash shell..."
+/bin/bash
diff --git a/configs/boot/spec-surge-server.rcS b/configs/boot/spec-surge-server.rcS
new file mode 100755
index 000000000..12e31696b
--- /dev/null
+++ b/configs/boot/spec-surge-server.rcS
@@ -0,0 +1,55 @@
+#!/bin/sh
+#
+# /etc/init.d/rcS
+#
+
+echo -n "mounting swap..."
+/sbin/swapon /dev/hdc
+echo "done."
+
+echo -n "setting up network..."
+/sbin/ifconfig eth0 192.168.0.1 txqueuelen 1000
+/sbin/ifconfig eth0:1 192.168.0.2 txqueuelen 1000
+/sbin/ifconfig eth0:2 192.168.0.3 txqueuelen 1000
+/sbin/ifconfig eth0:3 192.168.0.4 txqueuelen 1000
+/sbin/ifconfig eth0:4 192.168.0.5 txqueuelen 1000
+/sbin/ifconfig lo 127.0.0.1
+
+echo "1" > /proc/sys/net/ipv4/tcp_tw_recycle
+echo "1" > /proc/sys/net/ipv4/tcp_tw_reuse
+echo "1" > /proc/sys/net/ipv4/tcp_window_scaling
+echo "0" > /proc/sys/net/ipv4/tcp_timestamps
+echo "0" > /proc/sys/net/ipv4/tcp_sack
+echo "15" > /proc/sys/net/ipv4/tcp_fin_timeout
+echo "16384" > /proc/sys/net/ipv4/tcp_max_syn_backlog
+
+echo "1024 65535" > /proc/sys/net/ipv4/ip_local_port_range
+echo "10000000 10000000 10000000" > /proc/sys/net/ipv4/tcp_rmem
+echo "10000000 10000000 10000000" > /proc/sys/net/ipv4/tcp_wmem
+echo "10000000 10000000 10000000" > /proc/sys/net/ipv4/tcp_mem
+
+echo "524287" > /proc/sys/net/core/rmem_max
+echo "524287" > /proc/sys/net/core/wmem_max
+echo "524287" > /proc/sys/net/core/optmem_max
+echo "300000" > /proc/sys/net/core/netdev_max_backlog
+
+echo "131072" > /proc/sys/fs/file-max
+echo "done."
+
+echo -n "mounting file set..."
+mkdir -p /z/htdocs
+mount /dev/hdb1 /z/htdocs
+echo "done."
+
+echo -n "starting httpd..."
+/benchmarks/apache2/bin/apachectl start
+sleep 2
+cat /benchmarks/apache2/logs/error_log
+echo "done."
+
+echo "notifying client..."
+echo "server ready" | /usr/bin/netcat -c 192.168.0.10 8000
+echo "done"
+
+echo -n "starting bash shell..."
+/bin/bash
diff --git a/configs/boot/surge-client.rcS b/configs/boot/surge-client.rcS
new file mode 100755
index 000000000..208524a9c
--- /dev/null
+++ b/configs/boot/surge-client.rcS
@@ -0,0 +1,46 @@
+#!/bin/sh
+#
+# /etc/init.d/rcS
+#
+
+echo -n "mounting swap..."
+/sbin/swapon /dev/hdc
+echo "done."
+
+echo -n "setting up network..."
+/sbin/ifconfig eth0 192.168.0.10 txqueuelen 1000
+/sbin/ifconfig lo 127.0.0.1
+
+echo "1" > /proc/sys/net/ipv4/tcp_tw_recycle
+echo "1" > /proc/sys/net/ipv4/tcp_tw_reuse
+echo "1" > /proc/sys/net/ipv4/tcp_window_scaling
+echo "0" > /proc/sys/net/ipv4/tcp_timestamps
+echo "0" > /proc/sys/net/ipv4/tcp_sack
+echo "15" > /proc/sys/net/ipv4/tcp_fin_timeout
+echo "16384" > /proc/sys/net/ipv4/tcp_max_syn_backlog
+
+echo "1024 65535" > /proc/sys/net/ipv4/ip_local_port_range
+echo "10000000 10000000 10000000" > /proc/sys/net/ipv4/tcp_rmem
+echo "10000000 10000000 10000000" > /proc/sys/net/ipv4/tcp_wmem
+echo "10000000 10000000 10000000" > /proc/sys/net/ipv4/tcp_mem
+
+echo "524287" > /proc/sys/net/core/rmem_max
+echo "524287" > /proc/sys/net/core/wmem_max
+echo "524287" > /proc/sys/net/core/optmem_max
+echo "300000" > /proc/sys/net/core/netdev_max_backlog
+
+echo "131072" > /proc/sys/fs/file-max
+echo "done."
+
+echo "waiting for server..."
+/usr/bin/netcat -c -l -p 8000
+
+echo -n "running surge client..."
+/bin/bash -c "cd /benchmarks/surge && ./Surge 2 100 1 192.168.0.1 5"
+echo "done."
+
+echo -n "halting machine"
+m5 exit
+
+echo -n "starting bash shell..."
+/bin/bash
diff --git a/configs/boot/surge-server.rcS b/configs/boot/surge-server.rcS
new file mode 100755
index 000000000..3feb7b581
--- /dev/null
+++ b/configs/boot/surge-server.rcS
@@ -0,0 +1,54 @@
+#!/bin/sh
+#
+# /etc/init.d/rcS
+#
+
+
+echo -n "mounting swap..."
+/sbin/swapon /dev/hdc
+echo "done."
+
+echo -n "setting up network..."
+/sbin/ifconfig eth0 192.168.0.1 txqueuelen 1000
+/sbin/ifconfig eth0:1 192.168.0.2 txqueuelen 1000
+/sbin/ifconfig eth0:2 192.168.0.3 txqueuelen 1000
+/sbin/ifconfig eth0:3 192.168.0.4 txqueuelen 1000
+/sbin/ifconfig eth0:4 192.168.0.5 txqueuelen 1000
+/sbin/ifconfig lo 127.0.0.1
+
+echo "1" > /proc/sys/net/ipv4/tcp_tw_recycle
+echo "1" > /proc/sys/net/ipv4/tcp_tw_reuse
+echo "1" > /proc/sys/net/ipv4/tcp_window_scaling
+echo "0" > /proc/sys/net/ipv4/tcp_timestamps
+echo "0" > /proc/sys/net/ipv4/tcp_sack
+echo "15" > /proc/sys/net/ipv4/tcp_fin_timeout
+echo "16384" > /proc/sys/net/ipv4/tcp_max_syn_backlog
+
+echo "1024 65535" > /proc/sys/net/ipv4/ip_local_port_range
+echo "10000000 10000000 10000000" > /proc/sys/net/ipv4/tcp_rmem
+echo "10000000 10000000 10000000" > /proc/sys/net/ipv4/tcp_wmem
+echo "10000000 10000000 10000000" > /proc/sys/net/ipv4/tcp_mem
+
+echo "524287" > /proc/sys/net/core/rmem_max
+echo "524287" > /proc/sys/net/core/wmem_max
+echo "524287" > /proc/sys/net/core/optmem_max
+echo "300000" > /proc/sys/net/core/netdev_max_backlog
+
+echo "131072" > /proc/sys/fs/file-max
+echo "done."
+
+echo -n "mounting file set..."
+mkdir -p /z/htdocs
+mount /dev/hdb1 /z/htdocs
+echo "done."
+
+echo -n "starting httpd..."
+/benchmarks/apache2/bin/apachectl start
+sleep 2
+cat /benchmarks/apache2/logs/error_log
+echo "done."
+
+echo "server ready" | /usr/bin/netcat -c 192.168.10 8000
+
+echo -n "starting bash shell..."
+/bin/bash
diff --git a/cpu/base_cpu.cc b/cpu/base_cpu.cc
index 988c7a602..2275f12e3 100644
--- a/cpu/base_cpu.cc
+++ b/cpu/base_cpu.cc
@@ -30,10 +30,11 @@
#include <sstream>
#include <iostream>
-#include "cpu/base_cpu.hh"
#include "base/cprintf.hh"
-#include "cpu/exec_context.hh"
+#include "base/loader/symtab.hh"
#include "base/misc.hh"
+#include "cpu/base_cpu.hh"
+#include "cpu/exec_context.hh"
#include "sim/param.hh"
#include "sim/sim_events.hh"
@@ -50,21 +51,25 @@ int maxThreadsPerCPU = 1;
extern void debug_break();
#ifdef FULL_SYSTEM
-BaseCPU::BaseCPU(const string &_name, int _number_of_threads,
+BaseCPU::BaseCPU(const string &_name, int _number_of_threads, bool _def_reg,
Counter max_insts_any_thread,
Counter max_insts_all_threads,
Counter max_loads_any_thread,
Counter max_loads_all_threads,
- System *_system, Tick freq)
- : SimObject(_name), frequency(freq),
- number_of_threads(_number_of_threads), system(_system)
+ System *_system, Tick freq,
+ bool _function_trace, Tick _function_trace_start)
+ : SimObject(_name), frequency(freq), checkInterrupts(true),
+ deferRegistration(_def_reg), number_of_threads(_number_of_threads),
+ system(_system)
#else
-BaseCPU::BaseCPU(const string &_name, int _number_of_threads,
+BaseCPU::BaseCPU(const string &_name, int _number_of_threads, bool _def_reg,
Counter max_insts_any_thread,
Counter max_insts_all_threads,
Counter max_loads_any_thread,
- Counter max_loads_all_threads)
- : SimObject(_name), number_of_threads(_number_of_threads)
+ Counter max_loads_all_threads,
+ bool _function_trace, Tick _function_trace_start)
+ : SimObject(_name), deferRegistration(_def_reg),
+ number_of_threads(_number_of_threads)
#endif
{
DPRINTF(FullCPU, "BaseCPU: Creating object, mem address %#x.\n", this);
@@ -134,10 +139,47 @@ BaseCPU::BaseCPU(const string &_name, int _number_of_threads,
memset(interrupts, 0, sizeof(interrupts));
intstatus = 0;
#endif
+
+ functionTracingEnabled = false;
+ if (_function_trace) {
+ std::string filename = csprintf("ftrace.%s", name());
+ functionTraceStream = makeOutputStream(filename);
+ currentFunctionStart = currentFunctionEnd = 0;
+ functionEntryTick = _function_trace_start;
+
+ if (_function_trace_start == 0) {
+ functionTracingEnabled = true;
+ } else {
+ Event *e =
+ new EventWrapper<BaseCPU, &BaseCPU::enableFunctionTrace>(this,
+ true);
+ e->schedule(_function_trace_start);
+ }
+ }
+}
+
+
+void
+BaseCPU::enableFunctionTrace()
+{
+ functionTracingEnabled = true;
+}
+
+BaseCPU::~BaseCPU()
+{
+ if (functionTracingEnabled)
+ closeOutputStream(functionTraceStream);
}
void
+BaseCPU::init()
+{
+ if (!deferRegistration)
+ registerExecContexts();
+}
+
+void
BaseCPU::regStats()
{
using namespace Stats;
@@ -195,10 +237,10 @@ BaseCPU::takeOverFrom(BaseCPU *oldCPU)
newXC->takeOverFrom(oldXC);
assert(newXC->cpu_id == oldXC->cpu_id);
#ifdef FULL_SYSTEM
- system->replaceExecContext(newXC->cpu_id, newXC);
+ system->replaceExecContext(newXC, newXC->cpu_id);
#else
assert(newXC->process == oldXC->process);
- newXC->process->replaceExecContext(newXC->cpu_id, newXC);
+ newXC->process->replaceExecContext(newXC, newXC->cpu_id);
#endif
}
@@ -222,7 +264,7 @@ BaseCPU::post_interrupt(int int_num, int index)
if (index < 0 || index >= sizeof(uint64_t) * 8)
panic("int_num out of bounds\n");
- AlphaISA::check_interrupts = 1;
+ checkInterrupts = true;
interrupts[int_num] |= 1 << index;
intstatus |= (ULL(1) << int_num);
}
@@ -269,4 +311,32 @@ BaseCPU::unserialize(Checkpoint *cp, const std::string &section)
#endif // FULL_SYSTEM
+void
+BaseCPU::traceFunctionsInternal(Addr pc)
+{
+ if (!debugSymbolTable)
+ return;
+
+ // if pc enters different function, print new function symbol and
+ // update saved range. Otherwise do nothing.
+ if (pc < currentFunctionStart || pc >= currentFunctionEnd) {
+ string sym_str;
+ bool found = debugSymbolTable->findNearestSymbol(pc, sym_str,
+ currentFunctionStart,
+ currentFunctionEnd);
+
+ if (!found) {
+ // no symbol found: use addr as label
+ sym_str = csprintf("0x%x", pc);
+ currentFunctionStart = pc;
+ currentFunctionEnd = pc + 1;
+ }
+
+ ccprintf(*functionTraceStream, " (%d)\n%d: %s",
+ curTick - functionEntryTick, curTick, sym_str);
+ functionEntryTick = curTick;
+ }
+}
+
+
DEFINE_SIM_OBJECT_CLASS_NAME("BaseCPU", BaseCPU)
diff --git a/cpu/base_cpu.hh b/cpu/base_cpu.hh
index f75f00409..baa956aa8 100644
--- a/cpu/base_cpu.hh
+++ b/cpu/base_cpu.hh
@@ -55,6 +55,7 @@ class BaseCPU : public SimObject
virtual void post_interrupt(int int_num, int index);
virtual void clear_interrupt(int int_num, int index);
virtual void clear_interrupts();
+ bool checkInterrupts;
bool check_interrupt(int int_num) const {
if (int_num > NumInterruptLevels)
@@ -91,22 +92,26 @@ class BaseCPU : public SimObject
public:
#ifdef FULL_SYSTEM
- BaseCPU(const std::string &_name, int _number_of_threads,
+ BaseCPU(const std::string &_name, int _number_of_threads, bool _def_reg,
Counter max_insts_any_thread, Counter max_insts_all_threads,
Counter max_loads_any_thread, Counter max_loads_all_threads,
- System *_system, Tick freq);
+ System *_system, Tick freq,
+ bool _function_trace = false, Tick _function_trace_start = 0);
#else
- BaseCPU(const std::string &_name, int _number_of_threads,
+ BaseCPU(const std::string &_name, int _number_of_threads, bool _def_reg,
Counter max_insts_any_thread = 0,
Counter max_insts_all_threads = 0,
Counter max_loads_any_thread = 0,
- Counter max_loads_all_threads = 0);
+ Counter max_loads_all_threads = 0,
+ bool _function_trace = false, Tick _function_trace_start = 0);
#endif
- virtual ~BaseCPU() {}
+ virtual ~BaseCPU();
+ virtual void init();
virtual void regStats();
+ bool deferRegistration;
void registerExecContexts();
/// Prepare for another CPU to take over execution. Called by
@@ -140,7 +145,6 @@ class BaseCPU : public SimObject
#ifdef FULL_SYSTEM
System *system;
-
/**
* Serialize this object to the given output stream.
* @param os The stream to serialize to.
@@ -164,6 +168,23 @@ class BaseCPU : public SimObject
virtual Counter totalInstructions() const { return 0; }
+ // Function tracing
+ private:
+ bool functionTracingEnabled;
+ std::ostream *functionTraceStream;
+ Addr currentFunctionStart;
+ Addr currentFunctionEnd;
+ Tick functionEntryTick;
+ void enableFunctionTrace();
+ void traceFunctionsInternal(Addr pc);
+
+ protected:
+ void traceFunctions(Addr pc)
+ {
+ if (functionTracingEnabled)
+ traceFunctionsInternal(pc);
+ }
+
private:
static std::vector<BaseCPU *> cpuList; //!< Static global cpu list
diff --git a/cpu/exec_context.cc b/cpu/exec_context.cc
index 9c21b3a56..1cb33f13e 100644
--- a/cpu/exec_context.cc
+++ b/cpu/exec_context.cc
@@ -32,6 +32,9 @@
#include "cpu/exec_context.hh"
#ifdef FULL_SYSTEM
+#include "base/cprintf.hh"
+#include "kern/kernel_stats.hh"
+#include "sim/serialize.hh"
#include "sim/system.hh"
#else
#include "sim/process.hh"
@@ -44,12 +47,13 @@ using namespace std;
ExecContext::ExecContext(BaseCPU *_cpu, int _thread_num, System *_sys,
AlphaITB *_itb, AlphaDTB *_dtb,
FunctionalMemory *_mem)
- : _status(ExecContext::Unallocated),
- kernelStats(this, _cpu), cpu(_cpu), thread_num(_thread_num),
+ : _status(ExecContext::Unallocated), cpu(_cpu), thread_num(_thread_num),
cpu_id(-1), mem(_mem), itb(_itb), dtb(_dtb), system(_sys),
- memCtrl(_sys->memCtrl), physmem(_sys->physmem),
- swCtx(NULL), func_exe_inst(0), storeCondFailures(0)
+ memctrl(_sys->memctrl), physmem(_sys->physmem),
+ kernelBinning(system->kernelBinning), bin(kernelBinning->bin),
+ fnbin(kernelBinning->fnbin), func_exe_inst(0), storeCondFailures(0)
{
+ kernelStats = new Kernel::Statistics(this);
memset(&regs, 0, sizeof(RegFile));
}
#else
@@ -72,6 +76,13 @@ ExecContext::ExecContext(BaseCPU *_cpu, int _thread_num,
}
#endif
+ExecContext::~ExecContext()
+{
+#ifdef FULL_SYSTEM
+ delete kernelStats;
+#endif
+}
+
void
ExecContext::takeOverFrom(ExecContext *oldContext)
@@ -86,9 +97,6 @@ ExecContext::takeOverFrom(ExecContext *oldContext)
// copy over functional state
_status = oldContext->_status;
-#ifdef FULL_SYSTEM
- kernelStats = oldContext->kernelStats;
-#endif
regs = oldContext->regs;
cpu_id = oldContext->cpu_id;
func_exe_inst = oldContext->func_exe_inst;
@@ -98,6 +106,14 @@ ExecContext::takeOverFrom(ExecContext *oldContext)
oldContext->_status = ExecContext::Unallocated;
}
+#ifdef FULL_SYSTEM
+void
+ExecContext::execute(const StaticInstBase *inst)
+{
+ assert(kernelStats);
+ system->kernelBinning->execute(this, inst);
+}
+#endif
void
ExecContext::serialize(ostream &os)
@@ -109,31 +125,8 @@ ExecContext::serialize(ostream &os)
SERIALIZE_SCALAR(inst);
#ifdef FULL_SYSTEM
- bool ctx = false;
- if (swCtx) {
- ctx = true;
- SERIALIZE_SCALAR(ctx);
- SERIALIZE_SCALAR(swCtx->calls);
- std::stack<fnCall *> *stack = &(swCtx->callStack);
- fnCall *top;
- int size = stack->size();
- SERIALIZE_SCALAR(size);
-
- for (int j=0; j<size; ++j) {
- top = stack->top();
- paramOut(os, csprintf("stackpos[%d]",j), top->name);
- delete top;
- stack->pop();
- }
- } else {
- SERIALIZE_SCALAR(ctx);
- }
- if (system->bin) {
- Stats::MainBin *cur = Stats::MainBin::curBin();
- string bin_name = cur->name();
- SERIALIZE_SCALAR(bin_name);
- }
-#endif //FULL_SYSTEM
+ kernelStats->serialize(os);
+#endif
}
@@ -147,35 +140,8 @@ ExecContext::unserialize(Checkpoint *cp, const std::string &section)
UNSERIALIZE_SCALAR(inst);
#ifdef FULL_SYSTEM
- bool ctx;
- UNSERIALIZE_SCALAR(ctx);
- if (ctx) {
- swCtx = new SWContext;
- UNSERIALIZE_SCALAR(swCtx->calls);
- int size;
- UNSERIALIZE_SCALAR(size);
-
- vector<fnCall *> calls;
- fnCall *call;
- for (int i=0; i<size; ++i) {
- call = new fnCall;
- paramIn(cp, section, csprintf("stackpos[%d]",i), call->name);
- call->myBin = system->getBin(call->name);
- calls.push_back(call);
- }
-
- for (int i=size-1; i>=0; --i) {
- swCtx->callStack.push(calls[i]);
- }
-
- }
-
- if (system->bin) {
- string bin_name;
- UNSERIALIZE_SCALAR(bin_name);
- system->getBin(bin_name)->activate();
- }
-#endif //FULL_SYSTEM
+ kernelStats->unserialize(cp, section);
+#endif
}
@@ -232,7 +198,7 @@ void
ExecContext::regStats(const string &name)
{
#ifdef FULL_SYSTEM
- kernelStats.regStats(name + ".kern");
+ kernelStats->regStats(name + ".kern");
#endif
}
diff --git a/cpu/exec_context.hh b/cpu/exec_context.hh
index b47f5cd08..8437a5585 100644
--- a/cpu/exec_context.hh
+++ b/cpu/exec_context.hh
@@ -42,12 +42,12 @@ class BaseCPU;
#ifdef FULL_SYSTEM
+#include "sim/system.hh"
#include "targetarch/alpha_memory.hh"
-class MemoryController;
-#include "kern/kernel_stats.hh"
-#include "sim/system.hh"
-#include "sim/sw_context.hh"
+class MemoryController;
+class StaticInstBase;
+namespace Kernel { class Binning; class Statistics; }
#else // !FULL_SYSTEM
@@ -105,11 +105,6 @@ class ExecContext
/// Set the status to Halted.
void halt();
-#ifdef FULL_SYSTEM
- public:
- KernelStats kernelStats;
-#endif
-
public:
RegFile regs; // correct-path register context
@@ -127,7 +122,6 @@ class ExecContext
int cpu_id;
#ifdef FULL_SYSTEM
-
FunctionalMemory *mem;
AlphaITB *itb;
AlphaDTB *dtb;
@@ -136,10 +130,15 @@ class ExecContext
// 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;
+ MemoryController *memctrl;
PhysicalMemory *physmem;
- SWContext *swCtx;
+ Kernel::Binning *kernelBinning;
+ Kernel::Statistics *kernelStats;
+ bool bin;
+ bool fnbin;
+ void execute(const StaticInstBase *inst);
+
#else
Process *process;
@@ -185,7 +184,7 @@ class ExecContext
ExecContext(BaseCPU *_cpu, int _thread_num, FunctionalMemory *_mem,
int _asid);
#endif
- virtual ~ExecContext() {}
+ virtual ~ExecContext();
virtual void takeOverFrom(ExecContext *oldContext);
@@ -197,8 +196,8 @@ class ExecContext
#ifdef FULL_SYSTEM
bool validInstAddr(Addr addr) { return true; }
bool validDataAddr(Addr addr) { return true; }
- int getInstAsid() { return ITB_ASN_ASN(regs.ipr[TheISA::IPR_ITB_ASN]); }
- int getDataAsid() { return DTB_ASN_ASN(regs.ipr[TheISA::IPR_DTB_ASN]); }
+ int getInstAsid() { return regs.instAsid(); }
+ int getDataAsid() { return regs.dataAsid(); }
Fault translateInstReq(MemReqPtr &req)
{
@@ -411,7 +410,7 @@ class ExecContext
int readIntrFlag() { return regs.intrflag; }
void setIntrFlag(int val) { regs.intrflag = val; }
Fault hwrei();
- bool inPalMode() { return PC_PAL(regs.pc); }
+ bool inPalMode() { return AlphaISA::PcPAL(regs.pc); }
void ev5_trap(Fault fault);
bool simPalCheck(int palFunc);
#endif
diff --git a/cpu/exetrace.cc b/cpu/exetrace.cc
index e31c3590c..ff7e90c9e 100644
--- a/cpu/exetrace.cc
+++ b/cpu/exetrace.cc
@@ -48,8 +48,6 @@ using namespace std;
//
-SymbolTable *debugSymbolTable = NULL;
-
void
Trace::InstRecord::dump(ostream &outs)
{
@@ -66,11 +64,17 @@ Trace::InstRecord::dump(ostream &outs)
outs << "T" << thread << " : ";
- std::string str;
- if ((debugSymbolTable) && (debugSymbolTable->findNearestSymbol(PC, str)))
- outs << "@" << setw(17) << str << " : ";
- else
+ std::string sym_str;
+ Addr sym_addr;
+ if (debugSymbolTable
+ && debugSymbolTable->findNearestSymbol(PC, sym_str, sym_addr)) {
+ if (PC != sym_addr)
+ sym_str += csprintf("+%d", PC - sym_addr);
+ outs << "@" << sym_str << " : ";
+ }
+ else {
outs << "0x" << hex << PC << " : ";
+ }
//
// Print decoded instruction
diff --git a/cpu/memtest/memtest.cc b/cpu/memtest/memtest.cc
index b55af332a..e967c79da 100644
--- a/cpu/memtest/memtest.cc
+++ b/cpu/memtest/memtest.cc
@@ -28,9 +28,10 @@
// FIX ME: make trackBlkAddr use blocksize from actual cache, not hard coded
-#include <string>
-#include <sstream>
#include <iomanip>
+#include <set>
+#include <sstream>
+#include <string>
#include <vector>
#include "base/misc.hh"
@@ -44,6 +45,8 @@
using namespace std;
+int TESTER_ALLOCATOR=0;
+
MemTest::MemTest(const string &name,
MemInterface *_cache_interface,
FunctionalMemory *main_mem,
@@ -58,7 +61,8 @@ MemTest::MemTest(const string &name,
Addr _traceAddr,
Counter max_loads_any_thread,
Counter max_loads_all_threads)
- : BaseCPU(name, 1, 0, 0, max_loads_any_thread, max_loads_all_threads),
+ : BaseCPU(name, 1, true, 0, 0, max_loads_any_thread,
+ max_loads_all_threads),
tickEvent(this),
cacheInterface(_cache_interface),
mainMem(main_mem),
@@ -110,6 +114,8 @@ MemTest::MemTest(const string &name,
noResponseCycles = 0;
numReads = 0;
tickEvent.schedule(0);
+
+ id = TESTER_ALLOCATOR++;
}
static void
@@ -126,6 +132,11 @@ printData(ostream &os, uint8_t *data, int nbytes)
void
MemTest::completeRequest(MemReqPtr &req, uint8_t *data)
{
+ //Remove the address from the list of outstanding
+ std::set<unsigned>::iterator removeAddr = outstandingAddrs.find(req->paddr);
+ assert(removeAddr != outstandingAddrs.end());
+ outstandingAddrs.erase(removeAddr);
+
switch (req->cmd) {
case Read:
if (memcmp(req->data, data, req->size) != 0) {
@@ -157,6 +168,10 @@ MemTest::completeRequest(MemReqPtr &req, uint8_t *data)
break;
case Copy:
+ //Also remove dest from outstanding list
+ removeAddr = outstandingAddrs.find(req->dest);
+ assert(removeAddr != outstandingAddrs.end());
+ outstandingAddrs.erase(removeAddr);
numCopiesStat++;
break;
@@ -211,7 +226,7 @@ MemTest::tick()
if (!tickEvent.scheduled())
tickEvent.schedule(curTick + 1);
- if (++noResponseCycles >= 5000) {
+ if (++noResponseCycles >= 500000) {
cerr << name() << ": deadlocked at cycle " << curTick << endl;
fatal("");
}
@@ -231,6 +246,16 @@ MemTest::tick()
unsigned source_align = rand() % 100;
unsigned dest_align = rand() % 100;
+ //If we aren't doing copies, use id as offset, and do a false sharing
+ //mem tester
+ if (percentCopies == 0) {
+ //We can eliminate the lower bits of the offset, and then use the id
+ //to offset within the blks
+ offset1 &= ~63; //Not the low order bits
+ offset1 += id;
+ access_size = 0;
+ }
+
MemReqPtr req = new MemReq();
if (cacheable < percentUncacheable) {
@@ -250,6 +275,13 @@ MemTest::tick()
if (cmd < percentReads) {
// read
+
+ //For now we only allow one outstanding request per addreess per tester
+ //This means we assume CPU does write forwarding to reads that alias something
+ //in the cpu store buffer.
+ if (outstandingAddrs.find(req->paddr) != outstandingAddrs.end()) return;
+ else outstandingAddrs.insert(req->paddr);
+
req->cmd = Read;
uint8_t *result = new uint8_t[8];
checkMem->access(Read, req->paddr, result, req->size);
@@ -272,6 +304,13 @@ MemTest::tick()
}
} else if (cmd < (100 - percentCopies)){
// write
+
+ //For now we only allow one outstanding request per addreess per tester
+ //This means we assume CPU does write forwarding to reads that alias something
+ //in the cpu store buffer.
+ if (outstandingAddrs.find(req->paddr) != outstandingAddrs.end()) return;
+ else outstandingAddrs.insert(req->paddr);
+
req->cmd = Write;
memcpy(req->data, &data, req->size);
checkMem->access(Write, req->paddr, req->data, req->size);
@@ -297,6 +336,11 @@ MemTest::tick()
// copy
Addr source = ((base) ? baseAddr1 : baseAddr2) + offset1;
Addr dest = ((base) ? baseAddr2 : baseAddr1) + offset2;
+ if (outstandingAddrs.find(source) != outstandingAddrs.end()) return;
+ else outstandingAddrs.insert(source);
+ if (outstandingAddrs.find(dest) != outstandingAddrs.end()) return;
+ else outstandingAddrs.insert(dest);
+
if (source_align >= percentSourceUnaligned) {
source = blockAddr(source);
}
diff --git a/cpu/memtest/memtest.hh b/cpu/memtest/memtest.hh
index 72e0709d9..43b17a713 100644
--- a/cpu/memtest/memtest.hh
+++ b/cpu/memtest/memtest.hh
@@ -29,13 +29,14 @@
#ifndef __MEMTEST_HH__
#define __MEMTEST_HH__
-#include "sim/sim_object.hh"
-#include "mem/mem_interface.hh"
-#include "mem/functional_mem/functional_memory.hh"
-#include "cpu/base_cpu.hh"
-#include "cpu/exec_context.hh"
+#include <set>
#include "base/statistics.hh"
+#include "cpu/base_cpu.hh"
+#include "cpu/exec_context.hh"
+#include "mem/functional_mem/functional_memory.hh"
+#include "mem/mem_interface.hh"
+#include "sim/sim_object.hh"
#include "sim/stats.hh"
class MemTest : public BaseCPU
@@ -87,6 +88,10 @@ class MemTest : public BaseCPU
unsigned percentCopies; // target percentage of copy accesses
unsigned percentUncacheable;
+ int id;
+
+ std::set<unsigned> outstandingAddrs;
+
unsigned blockSize;
Addr blockAddrMask;
diff --git a/cpu/pc_event.cc b/cpu/pc_event.cc
index a86c017d4..8f046a7a4 100644
--- a/cpu/pc_event.cc
+++ b/cpu/pc_event.cc
@@ -77,7 +77,7 @@ PCEventQueue::schedule(PCEvent *event)
bool
PCEventQueue::doService(ExecContext *xc)
{
- Addr pc = xc->regs.pc;
+ Addr pc = xc->regs.pc & ~0x3;
int serviced = 0;
range_t range = equal_range(pc);
for (iterator i = range.first; i != range.second; ++i) {
@@ -85,7 +85,7 @@ PCEventQueue::doService(ExecContext *xc)
// another event. This for example, prevents two invocations
// of the SkipFuncEvent. Maybe we should have separate PC
// event queues for each processor?
- if (pc != xc->regs.pc)
+ if (pc != (xc->regs.pc & ~0x3))
continue;
DPRINTF(PCEvent, "PC based event serviced at %#x: %s\n",
diff --git a/cpu/pc_event.hh b/cpu/pc_event.hh
index 131016fc6..9983d679b 100644
--- a/cpu/pc_event.hh
+++ b/cpu/pc_event.hh
@@ -143,7 +143,7 @@ PCEvent::schedule(Addr pc)
{
if (evpc != badpc)
panic("cannot switch PC");
- evpc = pc;
+ evpc = pc & ~0x3;
return schedule();
}
@@ -158,7 +158,7 @@ PCEvent::schedule(PCEventQueue *q, Addr pc)
panic("cannot switch addresses");
queue = q;
- evpc = pc;
+ evpc = pc & ~0x3;
return schedule();
}
diff --git a/cpu/simple_cpu/simple_cpu.cc b/cpu/simple_cpu/simple_cpu.cc
index 6c22d7c81..d48f93663 100644
--- a/cpu/simple_cpu/simple_cpu.cc
+++ b/cpu/simple_cpu/simple_cpu.cc
@@ -123,11 +123,12 @@ SimpleCPU::SimpleCPU(const string &_name,
FunctionalMemory *mem,
MemInterface *icache_interface,
MemInterface *dcache_interface,
- bool _def_reg, Tick freq)
- : BaseCPU(_name, /* number_of_threads */ 1,
+ bool _def_reg, Tick freq,
+ bool _function_trace, Tick _function_trace_start)
+ : BaseCPU(_name, /* number_of_threads */ 1, _def_reg,
max_insts_any_thread, max_insts_all_threads,
max_loads_any_thread, max_loads_all_threads,
- _system, freq),
+ _system, freq, _function_trace, _function_trace_start),
#else
SimpleCPU::SimpleCPU(const string &_name, Process *_process,
Counter max_insts_any_thread,
@@ -136,13 +137,14 @@ SimpleCPU::SimpleCPU(const string &_name, Process *_process,
Counter max_loads_all_threads,
MemInterface *icache_interface,
MemInterface *dcache_interface,
- bool _def_reg)
- : BaseCPU(_name, /* number_of_threads */ 1,
+ bool _def_reg,
+ bool _function_trace, Tick _function_trace_start)
+ : BaseCPU(_name, /* number_of_threads */ 1, _def_reg,
max_insts_any_thread, max_insts_all_threads,
- max_loads_any_thread, max_loads_all_threads),
+ max_loads_any_thread, max_loads_all_threads,
+ _function_trace, _function_trace_start),
#endif
- tickEvent(this), xc(NULL), defer_registration(_def_reg),
- cacheCompletionEvent(this)
+ tickEvent(this), xc(NULL), cacheCompletionEvent(this)
{
_status = Idle;
#ifdef FULL_SYSTEM
@@ -176,13 +178,6 @@ SimpleCPU::~SimpleCPU()
{
}
-void SimpleCPU::init()
-{
- if (!defer_registration) {
- this->registerExecContexts();
- }
-}
-
void
SimpleCPU::switchOut()
{
@@ -338,16 +333,30 @@ change_thread_state(int thread_number, int activate, int priority)
Fault
SimpleCPU::copySrcTranslate(Addr src)
{
- memReq->reset(src, (dcacheInterface) ?
- dcacheInterface->getBlockSize()
- : 64);
+ static bool no_warn = true;
+ int blk_size = (dcacheInterface) ? dcacheInterface->getBlockSize() : 64;
+ // Only support block sizes of 64 atm.
+ assert(blk_size == 64);
+ int offset = src & (blk_size - 1);
+
+ // Make sure block doesn't span page
+ if (no_warn &&
+ (src & TheISA::PageMask) != ((src + blk_size) & TheISA::PageMask) &&
+ (src >> 40) != 0xfffffc) {
+ warn("Copied block source spans pages %x.", src);
+ no_warn = false;
+ }
+
+ memReq->reset(src & ~(blk_size - 1), blk_size);
// translate to physical address
Fault fault = xc->translateDataReadReq(memReq);
+ assert(fault != Alignment_Fault);
+
if (fault == No_Fault) {
xc->copySrcAddr = src;
- xc->copySrcPhysAddr = memReq->paddr;
+ xc->copySrcPhysAddr = memReq->paddr + offset;
} else {
xc->copySrcAddr = 0;
xc->copySrcPhysAddr = 0;
@@ -358,19 +367,44 @@ SimpleCPU::copySrcTranslate(Addr src)
Fault
SimpleCPU::copy(Addr dest)
{
+ static bool no_warn = true;
int blk_size = (dcacheInterface) ? dcacheInterface->getBlockSize() : 64;
+ // Only support block sizes of 64 atm.
+ assert(blk_size == 64);
uint8_t data[blk_size];
- assert(xc->copySrcAddr);
- memReq->reset(dest, blk_size);
+ //assert(xc->copySrcAddr);
+ int offset = dest & (blk_size - 1);
+
+ // Make sure block doesn't span page
+ if (no_warn &&
+ (dest & TheISA::PageMask) != ((dest + blk_size) & TheISA::PageMask) &&
+ (dest >> 40) != 0xfffffc) {
+ no_warn = false;
+ warn("Copied block destination spans pages %x. ", dest);
+ }
+
+ memReq->reset(dest & ~(blk_size -1), blk_size);
// translate to physical address
Fault fault = xc->translateDataWriteReq(memReq);
+
+ assert(fault != Alignment_Fault);
+
if (fault == No_Fault) {
- Addr dest_addr = memReq->paddr;
+ Addr dest_addr = memReq->paddr + offset;
// Need to read straight from memory since we have more than 8 bytes.
memReq->paddr = xc->copySrcPhysAddr;
xc->mem->read(memReq, data);
memReq->paddr = dest_addr;
xc->mem->write(memReq, data);
+ if (dcacheInterface) {
+ memReq->cmd = Copy;
+ memReq->completionEvent = NULL;
+ memReq->paddr = xc->copySrcPhysAddr;
+ memReq->dest = dest_addr;
+ memReq->size = 64;
+ memReq->time = curTick;
+ dcacheInterface->access(memReq);
+ }
}
return fault;
}
@@ -610,13 +644,11 @@ SimpleCPU::tick()
Fault fault = No_Fault;
#ifdef FULL_SYSTEM
- if (AlphaISA::check_interrupts &&
- xc->cpu->check_interrupts() &&
- !PC_PAL(xc->regs.pc) &&
+ if (checkInterrupts && check_interrupts() && !xc->inPalMode() &&
status() != IcacheMissComplete) {
int ipl = 0;
int summary = 0;
- AlphaISA::check_interrupts = 0;
+ checkInterrupts = false;
IntReg *ipr = xc->regs.ipr;
if (xc->regs.ipr[TheISA::IPR_SIRR]) {
@@ -733,9 +765,8 @@ SimpleCPU::tick()
fault = si->execute(this, traceData);
#ifdef FULL_SYSTEM
- SWContext *ctx = xc->swCtx;
- if (ctx)
- ctx->process(xc, si.get());
+ if (xc->fnbin)
+ xc->execute(si.get());
#endif
if (si->isMemRef()) {
@@ -750,6 +781,8 @@ SimpleCPU::tick()
if (traceData)
traceData->finalize();
+ traceFunctions(xc->regs.pc);
+
} // if (fault == No_Fault)
if (fault != No_Fault) {
@@ -808,6 +841,8 @@ BEGIN_DECLARE_SIM_OBJECT_PARAMS(SimpleCPU)
Param<bool> defer_registration;
Param<int> multiplier;
+ Param<bool> function_trace;
+ Param<Tick> function_trace_start;
END_DECLARE_SIM_OBJECT_PARAMS(SimpleCPU)
@@ -841,7 +876,9 @@ BEGIN_INIT_SIM_OBJECT_PARAMS(SimpleCPU)
INIT_PARAM_DFLT(defer_registration, "defer registration with system "
"(for sampling)", false),
- INIT_PARAM_DFLT(multiplier, "clock multiplier", 1)
+ INIT_PARAM_DFLT(multiplier, "clock multiplier", 1),
+ INIT_PARAM_DFLT(function_trace, "Enable function trace", false),
+ INIT_PARAM_DFLT(function_trace_start, "Cycle to start function trace", 0)
END_INIT_SIM_OBJECT_PARAMS(SimpleCPU)
@@ -860,7 +897,8 @@ CREATE_SIM_OBJECT(SimpleCPU)
(icache) ? icache->getInterface() : NULL,
(dcache) ? dcache->getInterface() : NULL,
defer_registration,
- ticksPerSecond * mult);
+ ticksPerSecond * mult,
+ function_trace, function_trace_start);
#else
cpu = new SimpleCPU(getInstanceName(), workload,
@@ -868,7 +906,8 @@ CREATE_SIM_OBJECT(SimpleCPU)
max_loads_any_thread, max_loads_all_threads,
(icache) ? icache->getInterface() : NULL,
(dcache) ? dcache->getInterface() : NULL,
- defer_registration);
+ defer_registration,
+ function_trace, function_trace_start);
#endif // FULL_SYSTEM
diff --git a/cpu/simple_cpu/simple_cpu.hh b/cpu/simple_cpu/simple_cpu.hh
index 6ab231e7e..341a0da23 100644
--- a/cpu/simple_cpu/simple_cpu.hh
+++ b/cpu/simple_cpu/simple_cpu.hh
@@ -31,7 +31,6 @@
#include "cpu/base_cpu.hh"
#include "sim/eventq.hh"
-#include "base/loader/symtab.hh"
#include "cpu/pc_event.hh"
#include "base/statistics.hh"
#include "cpu/exec_context.hh"
@@ -40,7 +39,6 @@
// forward declarations
#ifdef FULL_SYSTEM
class Processor;
-class Kernel;
class AlphaITB;
class AlphaDTB;
class PhysicalMemory;
@@ -144,7 +142,8 @@ class SimpleCPU : public BaseCPU
Counter max_loads_any_thread, Counter max_loads_all_threads,
AlphaITB *itb, AlphaDTB *dtb, FunctionalMemory *mem,
MemInterface *icache_interface, MemInterface *dcache_interface,
- bool _def_reg, Tick freq);
+ bool _def_reg, Tick freq,
+ bool _function_trace, Tick _function_trace_start);
#else
@@ -154,12 +153,12 @@ class SimpleCPU : public BaseCPU
Counter max_loads_any_thread,
Counter max_loads_all_threads,
MemInterface *icache_interface, MemInterface *dcache_interface,
- bool _def_reg);
+ bool _def_reg,
+ bool _function_trace, Tick _function_trace_start);
#endif
virtual ~SimpleCPU();
- virtual void init();
// execution context
ExecContext *xc;
@@ -179,8 +178,6 @@ class SimpleCPU : public BaseCPU
// L1 data cache
MemInterface *dcacheInterface;
- bool defer_registration;
-
// current instruction
MachInst inst;
@@ -250,8 +247,7 @@ class SimpleCPU : public BaseCPU
Fault read(Addr addr, T &data, unsigned flags);
template <class T>
- Fault write(T data, Addr addr, unsigned flags,
- uint64_t *res);
+ Fault write(T data, Addr addr, unsigned flags, uint64_t *res);
void prefetch(Addr addr, unsigned flags)
{
diff --git a/cpu/static_inst.hh b/cpu/static_inst.hh
index 71e9ef441..c47fa32db 100644
--- a/cpu/static_inst.hh
+++ b/cpu/static_inst.hh
@@ -48,6 +48,7 @@ class AlphaDynInst;
class FastCPU;
class SimpleCPU;
+class InorderCPU;
class SymbolTable;
namespace Trace {
diff --git a/cpu/trace/opt_cpu.cc b/cpu/trace/opt_cpu.cc
new file mode 100644
index 000000000..77211e382
--- /dev/null
+++ b/cpu/trace/opt_cpu.cc
@@ -0,0 +1,240 @@
+
+/*
+ * Copyright (c) 2004 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 memory trace CPU object for optimal caches. Uses a memory
+ * trace to access a fully associative cache with optimal replacement.
+ */
+
+#include <algorithm> // For heap functions.
+
+#include "cpu/trace/opt_cpu.hh"
+#include "cpu/trace/reader/mem_trace_reader.hh"
+
+#include "sim/builder.hh"
+#include "sim/sim_events.hh"
+
+using namespace std;
+
+OptCPU::OptCPU(const string &name,
+ MemTraceReader *_trace,
+ int block_size,
+ int cache_size,
+ int _assoc)
+ : BaseCPU(name, 1, true), tickEvent(this), trace(_trace),
+ numBlks(cache_size/block_size), assoc(_assoc), numSets(numBlks/assoc),
+ setMask(numSets - 1)
+{
+ int log_block_size = 0;
+ int tmp_block_size = block_size;
+ while (tmp_block_size > 1) {
+ ++log_block_size;
+ tmp_block_size = tmp_block_size >> 1;
+ }
+ assert(1<<log_block_size == block_size);
+ MemReqPtr req;
+ trace->getNextReq(req);
+ refInfo.resize(numSets);
+ while (req) {
+ RefInfo temp;
+ temp.addr = req->paddr >> log_block_size;
+ int set = temp.addr & setMask;
+ refInfo[set].push_back(temp);
+ trace->getNextReq(req);
+ }
+
+ // Initialize top level of lookup table.
+ lookupTable.resize(16);
+
+ // Annotate references with next ref time.
+ for (int k = 0; k < numSets; ++k) {
+ for (RefIndex i = refInfo[k].size() - 1; i >= 0; --i) {
+ Addr addr = refInfo[k][i].addr;
+ initTable(addr, InfiniteRef);
+ refInfo[k][i].nextRefTime = lookupValue(addr);
+ setValue(addr, i);
+ }
+ }
+
+ // Reset the lookup table
+ for (int j = 0; j < 16; ++j) {
+ if (lookupTable[j].size() == (1<<16)) {
+ for (int k = 0; k < (1<<16); ++k) {
+ if (lookupTable[j][k].size() == (1<<16)) {
+ for (int l = 0; l < (1<<16); ++l) {
+ lookupTable[j][k][l] = -1;
+ }
+ }
+ }
+ }
+ }
+
+ tickEvent.schedule(0);
+
+ hits = 0;
+ misses = 0;
+}
+
+void
+OptCPU::processSet(int set)
+{
+ // Initialize cache
+ int blks_in_cache = 0;
+ RefIndex i = 0;
+ cacheHeap.clear();
+ cacheHeap.resize(assoc);
+
+ while (blks_in_cache < assoc) {
+ RefIndex cache_index = lookupValue(refInfo[set][i].addr);
+ if (cache_index == -1) {
+ // First reference to this block
+ misses++;
+ cache_index = blks_in_cache++;
+ setValue(refInfo[set][i].addr, cache_index);
+ } else {
+ hits++;
+ }
+ // update cache heap to most recent reference
+ cacheHeap[cache_index] = i;
+ if (++i >= refInfo[set].size()) {
+ return;
+ }
+ }
+ for (int start = assoc/2; start >= 0; --start) {
+ heapify(set,start);
+ }
+ //verifyHeap(set,0);
+
+ for (; i < refInfo[set].size(); ++i) {
+ RefIndex cache_index = lookupValue(refInfo[set][i].addr);
+ if (cache_index == -1) {
+ // miss
+ misses++;
+ // replace from cacheHeap[0]
+ // mark replaced block as absent
+ setValue(refInfo[set][cacheHeap[0]].addr, -1);
+ setValue(refInfo[set][i].addr, 0);
+ cacheHeap[0] = i;
+ heapify(set, 0);
+ // Make sure its in the cache
+ assert(lookupValue(refInfo[set][i].addr) != -1);
+ } else {
+ // hit
+ hits++;
+ assert(refInfo[set][cacheHeap[cache_index]].addr ==
+ refInfo[set][i].addr);
+ assert(refInfo[set][cacheHeap[cache_index]].nextRefTime == i);
+ assert(heapLeft(cache_index) >= assoc);
+
+ cacheHeap[cache_index] = i;
+ processRankIncrease(set, cache_index);
+ assert(lookupValue(refInfo[set][i].addr) != -1);
+ }
+ }
+}
+void
+OptCPU::tick()
+{
+ // Do opt simulation
+
+ int references = 0;
+ for (int set = 0; set < numSets; ++set) {
+ if (!refInfo[set].empty()) {
+ processSet(set);
+ }
+ references += refInfo[set].size();
+ }
+ // exit;
+ fprintf(stderr,"sys.cpu.misses %d #opt cache misses\n",misses);
+ fprintf(stderr,"sys.cpu.hits %d #opt cache hits\n", hits);
+ fprintf(stderr,"sys.cpu.accesses %d #opt cache acceses\n", references);
+ new SimExitEvent("Finshed Memory Trace");
+}
+
+void
+OptCPU::initTable(Addr addr, RefIndex index)
+{
+ int l1_index = (addr >> 32) & 0x0f;
+ int l2_index = (addr >> 16) & 0xffff;
+ assert(l1_index == addr >> 32);
+ if (lookupTable[l1_index].size() != (1<<16)) {
+ lookupTable[l1_index].resize(1<<16);
+ }
+ if (lookupTable[l1_index][l2_index].size() != (1<<16)) {
+ lookupTable[l1_index][l2_index].resize(1<<16, index);
+ }
+}
+
+OptCPU::TickEvent::TickEvent(OptCPU *c)
+ : Event(&mainEventQueue, CPU_Tick_Pri), cpu(c)
+{
+}
+
+void
+OptCPU::TickEvent::process()
+{
+ cpu->tick();
+}
+
+const char *
+OptCPU::TickEvent::description()
+{
+ return "OptCPU tick event";
+}
+
+
+BEGIN_DECLARE_SIM_OBJECT_PARAMS(OptCPU)
+
+ SimObjectParam<MemTraceReader *> data_trace;
+ Param<int> size;
+ Param<int> block_size;
+Param<int> assoc;
+
+END_DECLARE_SIM_OBJECT_PARAMS(OptCPU)
+
+BEGIN_INIT_SIM_OBJECT_PARAMS(OptCPU)
+
+ INIT_PARAM_DFLT(data_trace, "memory trace", NULL),
+ INIT_PARAM(size, "cache size"),
+ INIT_PARAM(block_size, "block size"),
+ INIT_PARAM(assoc,"associativity")
+
+END_INIT_SIM_OBJECT_PARAMS(OptCPU)
+
+CREATE_SIM_OBJECT(OptCPU)
+{
+ return new OptCPU(getInstanceName(),
+ data_trace,
+ block_size,
+ size,
+ assoc);
+}
+
+REGISTER_SIM_OBJECT("OptCPU", OptCPU)
diff --git a/cpu/trace/opt_cpu.hh b/cpu/trace/opt_cpu.hh
new file mode 100644
index 000000000..847147b3c
--- /dev/null
+++ b/cpu/trace/opt_cpu.hh
@@ -0,0 +1,222 @@
+/*
+ * Copyright (c) 2004 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 memory trace CPU object for optimal caches. Uses a memory
+ * trace to access a fully associative cache with optimal replacement.
+ */
+
+#ifndef __OPT_CPU_HH__
+#define __OPT_CPU_HH__
+
+#include <vector>
+
+#include "cpu/base_cpu.hh"
+#include "mem/mem_req.hh" // for MemReqPtr
+#include "sim/eventq.hh" // for Event
+
+// Forward Declaration
+class MemTraceReader;
+
+/**
+ * A CPU object to simulate a fully-associative cache with optimal replacement.
+ */
+class OptCPU : public BaseCPU
+{
+ typedef int RefIndex;
+
+ typedef std::vector<RefIndex> L3Table;
+ typedef std::vector<L3Table> L2Table;
+ typedef std::vector<L2Table> L1Table;
+
+ /**
+ * Event to call OptCPU::tick
+ */
+ class TickEvent : public Event
+ {
+ private:
+ /** The associated CPU */
+ OptCPU *cpu;
+
+ public:
+ /**
+ * Construct this event;
+ */
+ TickEvent(OptCPU *c);
+
+ /**
+ * Call the tick function.
+ */
+ void process();
+
+ /**
+ * Return a string description of this event.
+ */
+ const char *description();
+ };
+
+ TickEvent tickEvent;
+
+ class RefInfo
+ {
+ public:
+ RefIndex nextRefTime;
+ Addr addr;
+ };
+
+ /** Reference Information, per set. */
+ std::vector<std::vector<RefInfo> > refInfo;
+
+ /** Lookup table to track blocks in the cache heap */
+ L1Table lookupTable;
+
+ /**
+ * Return the correct value in the lookup table.
+ */
+ RefIndex lookupValue(Addr addr)
+ {
+ int l1_index = (addr >> 32) & 0x0f;
+ int l2_index = (addr >> 16) & 0xffff;
+ int l3_index = addr & 0xffff;
+ assert(l1_index == addr >> 32);
+ return lookupTable[l1_index][l2_index][l3_index];
+ }
+
+ /**
+ * Set the value in the lookup table.
+ */
+ void setValue(Addr addr, RefIndex index)
+ {
+ int l1_index = (addr >> 32) & 0x0f;
+ int l2_index = (addr >> 16) & 0xffff;
+ int l3_index = addr & 0xffff;
+ assert(l1_index == addr >> 32);
+ lookupTable[l1_index][l2_index][l3_index]=index;
+ }
+
+ /**
+ * Initialize the lookup table to the given value.
+ */
+ void initTable(Addr addr, RefIndex index);
+
+ void heapSwap(int set, int a, int b) {
+ RefIndex tmp = cacheHeap[a];
+ cacheHeap[a] = cacheHeap[b];
+ cacheHeap[b] = tmp;
+
+ setValue(refInfo[set][cacheHeap[a]].addr, a);
+ setValue(refInfo[set][cacheHeap[b]].addr, b);
+ }
+
+ int heapLeft(int index) { return index + index + 1; }
+ int heapRight(int index) { return index + index + 2; }
+ int heapParent(int index) { return (index - 1) >> 1; }
+
+ RefIndex heapRank(int set, int index) {
+ return refInfo[set][cacheHeap[index]].nextRefTime;
+ }
+
+ void heapify(int set, int start){
+ int left = heapLeft(start);
+ int right = heapRight(start);
+ int max = start;
+ if (left < assoc && heapRank(set, left) > heapRank(set, start)) {
+ max = left;
+ }
+ if (right < assoc && heapRank(set, right) > heapRank(set, max)) {
+ max = right;
+ }
+
+ if (max != start) {
+ heapSwap(set, start, max);
+ heapify(set, max);
+ }
+ }
+
+ void verifyHeap(int set, int start) {
+ int left = heapLeft(start);
+ int right = heapRight(start);
+
+ if (left < assoc) {
+ assert(heapRank(set, start) >= heapRank(set, left));
+ verifyHeap(set, left);
+ }
+ if (right < assoc) {
+ assert(heapRank(set, start) >= heapRank(set, right));
+ verifyHeap(set, right);
+ }
+ }
+
+ void processRankIncrease(int set, int start) {
+ int parent = heapParent(start);
+ while (start > 0 && heapRank(set,parent) < heapRank(set,start)) {
+ heapSwap(set, parent, start);
+ start = parent;
+ parent = heapParent(start);
+ }
+ }
+
+ void processSet(int set);
+
+ static const RefIndex InfiniteRef = 0x7fffffff;
+
+ /** Memory reference trace. */
+ MemTraceReader *trace;
+
+ /** Cache heap for replacement. */
+ std::vector<RefIndex> cacheHeap;
+
+ /** The number of blocks in the cache. */
+ const int numBlks;
+
+ const int assoc;
+ const int numSets;
+ const int setMask;
+
+
+ int misses;
+ int hits;
+
+ public:
+ /**
+ * Construct a OptCPU object.
+ */
+ OptCPU(const std::string &name,
+ MemTraceReader *_trace,
+ int block_size,
+ int cache_size,
+ int assoc);
+
+ /**
+ * Perform the optimal replacement simulation.
+ */
+ void tick();
+};
+
+#endif
diff --git a/cpu/trace/reader/itx_reader.cc b/cpu/trace/reader/itx_reader.cc
index 593d383ec..006fcc9dd 100644
--- a/cpu/trace/reader/itx_reader.cc
+++ b/cpu/trace/reader/itx_reader.cc
@@ -102,6 +102,7 @@ ITXReader::getNextReq(MemReqPtr &req)
} else {
codePhysAddr += tmp_req->size;
}
+ assert(tmp_req->paddr >> 36 == 0);
} else {
codePhysValid = false;
}
@@ -130,12 +131,13 @@ ITXReader::getNextReq(MemReqPtr &req)
// Get the page offset from the virtual address.
tmp_req->paddr = tmp_req->vaddr & 0xfff;
tmp_req->paddr |= (c & 0xf0) << 8;
+ tmp_req->paddr |= (Addr)(c & 0x0f) << 32;
for (int i = 2; i < 4; ++i) {
c = getc(trace);
if (c == EOF) {
fatal("Unexpected end of trace file.");
}
- tmp_req->paddr |= (c & 0xff) << (8 * i);
+ tmp_req->paddr |= (Addr)(c & 0xff) << (8 * i);
}
if (type == ITXCode) {
if (((tmp_req->paddr & 0xfff) + tmp_req->size)
@@ -148,6 +150,7 @@ ITXReader::getNextReq(MemReqPtr &req)
codePhysValid = true;
}
}
+ assert(tmp_req->paddr >> 36 == 0);
} else if (type == ITXCode) {
codePhysValid = false;
}
@@ -158,8 +161,12 @@ ITXReader::getNextReq(MemReqPtr &req)
case ITXWrite:
tmp_req->cmd = Write;
break;
+ case ITXWriteback:
+ tmp_req->cmd = Writeback;
+ break;
case ITXCode:
tmp_req->cmd = Read;
+ tmp_req->flags |= INST_READ;
break;
default:
fatal("Unknown ITX type");
@@ -173,6 +180,7 @@ ITXReader::getNextReq(MemReqPtr &req)
}
} while (!phys_val);
req = tmp_req;
+ assert(!req || (req->paddr >> 36) == 0);
return 0;
}
diff --git a/cpu/trace/reader/itx_reader.hh b/cpu/trace/reader/itx_reader.hh
index 0e08d5db5..d45a16a69 100644
--- a/cpu/trace/reader/itx_reader.hh
+++ b/cpu/trace/reader/itx_reader.hh
@@ -35,6 +35,7 @@
#define __ITX_READER_HH__
#include <stdio.h>
+#include <string>
#include "cpu/trace/reader/mem_trace_reader.hh"
#include "mem/mem_req.hh"
diff --git a/cpu/trace/trace_cpu.cc b/cpu/trace/trace_cpu.cc
index 94f311d4b..f1160337a 100644
--- a/cpu/trace/trace_cpu.cc
+++ b/cpu/trace/trace_cpu.cc
@@ -46,23 +46,13 @@ using namespace std;
TraceCPU::TraceCPU(const string &name,
MemInterface *icache_interface,
MemInterface *dcache_interface,
- MemTraceReader *inst_trace,
- MemTraceReader *data_trace,
- int icache_ports,
- int dcache_ports)
- : BaseCPU(name, 4), icacheInterface(icache_interface),
- dcacheInterface(dcache_interface), instTrace(inst_trace),
- dataTrace(data_trace), icachePorts(icache_ports),
- dcachePorts(dcache_ports), outstandingRequests(0), tickEvent(this)
+ MemTraceReader *data_trace)
+ : BaseCPU(name, 4, true), icacheInterface(icache_interface),
+ dcacheInterface(dcache_interface),
+ dataTrace(data_trace), outstandingRequests(0), tickEvent(this)
{
- if (instTrace) {
- assert(icacheInterface);
- nextInstCycle = instTrace->getNextReq(nextInstReq);
- }
- if (dataTrace) {
- assert(dcacheInterface);
- nextDataCycle = dataTrace->getNextReq(nextDataReq);
- }
+ assert(dcacheInterface);
+ nextCycle = dataTrace->getNextReq(nextReq);
tickEvent.schedule(0);
}
@@ -74,41 +64,46 @@ TraceCPU::tick()
int instReqs = 0;
int dataReqs = 0;
- // Do data first to match tracing with FullCPU dumps
-
- while (nextDataReq && (dataReqs < dcachePorts) &&
- curTick >= nextDataCycle) {
- assert(nextDataReq->thread_num < 4 && "Not enough threads");
- if (dcacheInterface->isBlocked())
- break;
-
- ++dataReqs;
- nextDataReq->time = curTick;
- nextDataReq->completionEvent =
- new TraceCompleteEvent(nextDataReq, this);
- dcacheInterface->access(nextDataReq);
- nextDataCycle = dataTrace->getNextReq(nextDataReq);
- }
-
- while (nextInstReq && (instReqs < icachePorts) &&
- curTick >= nextInstCycle) {
- assert(nextInstReq->thread_num < 4 && "Not enough threads");
- if (icacheInterface->isBlocked())
- break;
-
- nextInstReq->time = curTick;
- if (nextInstReq->cmd == Squash) {
- icacheInterface->squash(nextInstReq->asid);
+ while (nextReq && curTick >= nextCycle) {
+ assert(nextReq->thread_num < 4 && "Not enough threads");
+ if (nextReq->isInstRead() && icacheInterface) {
+ if (icacheInterface->isBlocked())
+ break;
+
+ nextReq->time = curTick;
+ if (nextReq->cmd == Squash) {
+ icacheInterface->squash(nextReq->asid);
+ } else {
+ ++instReqs;
+ if (icacheInterface->doEvents()) {
+ nextReq->completionEvent =
+ new TraceCompleteEvent(nextReq, this);
+ icacheInterface->access(nextReq);
+ } else {
+ icacheInterface->access(nextReq);
+ completeRequest(nextReq);
+ }
+ }
} else {
- ++instReqs;
- nextInstReq->completionEvent =
- new TraceCompleteEvent(nextInstReq, this);
- icacheInterface->access(nextInstReq);
+ if (dcacheInterface->isBlocked())
+ break;
+
+ ++dataReqs;
+ nextReq->time = curTick;
+ if (dcacheInterface->doEvents()) {
+ nextReq->completionEvent =
+ new TraceCompleteEvent(nextReq, this);
+ dcacheInterface->access(nextReq);
+ } else {
+ dcacheInterface->access(nextReq);
+ completeRequest(nextReq);
+ }
+
}
- nextInstCycle = instTrace->getNextReq(nextInstReq);
+ nextCycle = dataTrace->getNextReq(nextReq);
}
- if (!nextInstReq && !nextDataReq) {
+ if (!nextReq) {
// No more requests to send. Finish trailing events and exit.
if (mainEventQueue.empty()) {
new SimExitEvent("Finshed Memory Trace");
@@ -116,8 +111,7 @@ TraceCPU::tick()
tickEvent.schedule(mainEventQueue.nextEventTime() + 1);
}
} else {
- tickEvent.schedule(max(curTick + 1,
- min(nextInstCycle, nextDataCycle)));
+ tickEvent.schedule(max(curTick + 1, nextCycle));
}
}
@@ -161,10 +155,7 @@ BEGIN_DECLARE_SIM_OBJECT_PARAMS(TraceCPU)
SimObjectParam<BaseMem *> icache;
SimObjectParam<BaseMem *> dcache;
- SimObjectParam<MemTraceReader *> inst_trace;
SimObjectParam<MemTraceReader *> data_trace;
- Param<int> inst_ports;
- Param<int> data_ports;
END_DECLARE_SIM_OBJECT_PARAMS(TraceCPU)
@@ -172,10 +163,7 @@ BEGIN_INIT_SIM_OBJECT_PARAMS(TraceCPU)
INIT_PARAM_DFLT(icache, "instruction cache", NULL),
INIT_PARAM_DFLT(dcache, "data cache", NULL),
- INIT_PARAM_DFLT(inst_trace, "instruction trace", NULL),
- INIT_PARAM_DFLT(data_trace, "data trace", NULL),
- INIT_PARAM_DFLT(inst_ports, "instruction cache read ports", 4),
- INIT_PARAM_DFLT(data_ports, "data cache read/write ports", 4)
+ INIT_PARAM_DFLT(data_trace, "data trace", NULL)
END_INIT_SIM_OBJECT_PARAMS(TraceCPU)
@@ -184,7 +172,7 @@ CREATE_SIM_OBJECT(TraceCPU)
return new TraceCPU(getInstanceName(),
(icache) ? icache->getInterface() : NULL,
(dcache) ? dcache->getInterface() : NULL,
- inst_trace, data_trace, inst_ports, data_ports);
+ data_trace);
}
REGISTER_SIM_OBJECT("TraceCPU", TraceCPU)
diff --git a/cpu/trace/trace_cpu.hh b/cpu/trace/trace_cpu.hh
index 6f3ef50a6..1711646a8 100644
--- a/cpu/trace/trace_cpu.hh
+++ b/cpu/trace/trace_cpu.hh
@@ -55,28 +55,17 @@ class TraceCPU : public BaseCPU
/** Interface for data trace requests, if any. */
MemInterface *dcacheInterface;
- /** Instruction reference trace. */
- MemTraceReader *instTrace;
/** Data reference trace. */
MemTraceReader *dataTrace;
- /** Number of Icache read ports. */
- int icachePorts;
- /** Number of Dcache read/write ports. */
- int dcachePorts;
-
/** Number of outstanding requests. */
int outstandingRequests;
- /** Cycle of the next instruction request, 0 if not available. */
- Tick nextInstCycle;
- /** Cycle of the next data request, 0 if not available. */
- Tick nextDataCycle;
+ /** Cycle of the next request, 0 if not available. */
+ Tick nextCycle;
- /** Next instruction request. */
- MemReqPtr nextInstReq;
- /** Next data request. */
- MemReqPtr nextDataReq;
+ /** Next request. */
+ MemReqPtr nextReq;
/**
* Event to call the TraceCPU::tick
@@ -113,10 +102,7 @@ class TraceCPU : public BaseCPU
TraceCPU(const std::string &name,
MemInterface *icache_interface,
MemInterface *dcache_interface,
- MemTraceReader *inst_trace,
- MemTraceReader *data_trace,
- int icache_ports,
- int dcache_ports);
+ MemTraceReader *data_trace);
/**
* Perform all the accesses for one cycle.
diff --git a/dev/alpha_console.cc b/dev/alpha_console.cc
index 680704b30..7deabe2fc 100644
--- a/dev/alpha_console.cc
+++ b/dev/alpha_console.cc
@@ -61,12 +61,12 @@ AlphaConsole::AlphaConsole(const string &name, SimConsole *cons, SimpleDisk *d,
HierParams *hier, Bus *bus)
: PioDevice(name), disk(d), console(cons), addr(a)
{
- mmu->add_child(this, Range<Addr>(addr, addr + size));
+ mmu->add_child(this, RangeSize(addr, size));
if (bus) {
pioInterface = newPioInterface(name, hier, bus, this,
&AlphaConsole::cacheAccess);
- pioInterface->addAddrRange(addr, addr + size);
+ pioInterface->addAddrRange(RangeSize(addr, size));
}
alphaAccess = new AlphaAccess;
@@ -98,7 +98,7 @@ AlphaConsole::read(MemReqPtr &req, uint8_t *data)
{
memset(data, 0, req->size);
- Addr daddr = req->paddr - (addr & PA_IMPL_MASK);
+ Addr daddr = req->paddr - (addr & EV5::PAddrImplMask);
switch (req->size)
{
@@ -198,7 +198,7 @@ AlphaConsole::write(MemReqPtr &req, const uint8_t *data)
return Machine_Check_Fault;
}
- Addr daddr = req->paddr - (addr & PA_IMPL_MASK);
+ Addr daddr = req->paddr - (addr & EV5::PAddrImplMask);
ExecContext *other_xc;
switch (daddr) {
diff --git a/dev/baddev.cc b/dev/baddev.cc
index 7c563e80a..73b082d47 100644
--- a/dev/baddev.cc
+++ b/dev/baddev.cc
@@ -50,12 +50,12 @@ BadDevice::BadDevice(const string &name, Addr a, MemoryController *mmu,
HierParams *hier, Bus *bus, const string &devicename)
: PioDevice(name), addr(a), devname(devicename)
{
- mmu->add_child(this, Range<Addr>(addr, addr + size));
+ mmu->add_child(this, RangeSize(addr, size));
if (bus) {
pioInterface = newPioInterface(name, hier, bus, this,
&BadDevice::cacheAccess);
- pioInterface->addAddrRange(addr, addr + size - 1);
+ pioInterface->addAddrRange(RangeSize(addr, size));
}
}
diff --git a/dev/etherdump.cc b/dev/etherdump.cc
index 27817d456..485d5599c 100644
--- a/dev/etherdump.cc
+++ b/dev/etherdump.cc
@@ -42,11 +42,9 @@
using std::string;
-EtherDump::EtherDump(const string &name, const string &file, int max)
- : SimObject(name), maxlen(max)
+EtherDump::EtherDump(const string &name, std::ostream *_stream, int max)
+ : SimObject(name), stream(_stream), maxlen(max)
{
- if (!file.empty())
- stream.open(file.c_str());
}
#define DLT_EN10MB 1 // Ethernet (10Mb)
@@ -74,9 +72,6 @@ struct pcap_pkthdr {
void
EtherDump::init()
{
- if (!stream.is_open())
- return;
-
curtime = time(NULL);
s_freq = ticksPerSecond;
us_freq = ticksPerSecond / ULL(1000000);
@@ -91,7 +86,7 @@ EtherDump::init()
hdr.sigfigs = 0;
hdr.linktype = DLT_EN10MB;
- stream.write(reinterpret_cast<char *>(&hdr), sizeof(hdr));
+ stream->write(reinterpret_cast<char *>(&hdr), sizeof(hdr));
/*
* output an empty packet with the current time so that we know
@@ -103,9 +98,9 @@ EtherDump::init()
pkthdr.microseconds = 0;
pkthdr.caplen = 0;
pkthdr.len = 0;
- stream.write(reinterpret_cast<char *>(&pkthdr), sizeof(pkthdr));
+ stream->write(reinterpret_cast<char *>(&pkthdr), sizeof(pkthdr));
- stream.flush();
+ stream->flush();
}
void
@@ -116,9 +111,9 @@ EtherDump::dumpPacket(PacketPtr &packet)
pkthdr.microseconds = (curTick / us_freq) % ULL(1000000);
pkthdr.caplen = std::min(packet->length, maxlen);
pkthdr.len = packet->length;
- stream.write(reinterpret_cast<char *>(&pkthdr), sizeof(pkthdr));
- stream.write(reinterpret_cast<char *>(packet->data), pkthdr.caplen);
- stream.flush();
+ stream->write(reinterpret_cast<char *>(&pkthdr), sizeof(pkthdr));
+ stream->write(reinterpret_cast<char *>(packet->data), pkthdr.caplen);
+ stream->flush();
}
BEGIN_DECLARE_SIM_OBJECT_PARAMS(EtherDump)
@@ -130,28 +125,14 @@ END_DECLARE_SIM_OBJECT_PARAMS(EtherDump)
BEGIN_INIT_SIM_OBJECT_PARAMS(EtherDump)
- INIT_PARAM(file, "file to dump packets to"),
+ INIT_PARAM_DFLT(file, "file to dump packets to", "etherdump"),
INIT_PARAM_DFLT(maxlen, "max portion of packet data to dump", 96)
END_INIT_SIM_OBJECT_PARAMS(EtherDump)
CREATE_SIM_OBJECT(EtherDump)
{
- string filename;
- if (file.isValid()) {
- filename = file;
-
- if (filename[0] != '/' && !outputDirectory.empty())
- filename = outputDirectory + filename;
- } else {
- if (outputDirectory.empty()) {
- filename = "etherdump";
- } else {
- filename = outputDirectory + "etherdump";
- }
- }
-
- return new EtherDump(getInstanceName(), filename, maxlen);
+ return new EtherDump(getInstanceName(), makeOutputStream(file), maxlen);
}
REGISTER_SIM_OBJECT("EtherDump", EtherDump)
diff --git a/dev/etherdump.hh b/dev/etherdump.hh
index 62364359e..b127d05e2 100644
--- a/dev/etherdump.hh
+++ b/dev/etherdump.hh
@@ -43,7 +43,7 @@
class EtherDump : public SimObject
{
private:
- std::ofstream stream;
+ std::ostream *stream;
const int maxlen;
void dumpPacket(PacketPtr &packet);
void init();
@@ -53,9 +53,9 @@ class EtherDump : public SimObject
Tick us_freq;
public:
- EtherDump(const std::string &name, const std::string &file, int max);
+ EtherDump(const std::string &name, std::ostream *_stream, int max);
- inline void dump(PacketPtr &pkt) { if (stream.is_open()) dumpPacket(pkt); }
+ inline void dump(PacketPtr &pkt) { dumpPacket(pkt); }
};
#endif // __ETHERDUMP_H__
diff --git a/dev/etherint.hh b/dev/etherint.hh
index ddfe16d88..bcdf0ae06 100644
--- a/dev/etherint.hh
+++ b/dev/etherint.hh
@@ -31,8 +31,8 @@
* components.
*/
-#ifndef __ETHERINT_HH__
-#define __ETHERINT_HH__
+#ifndef __DEV_ETHERINT_HH__
+#define __DEV_ETHERINT_HH__
#include <string>
@@ -54,13 +54,13 @@ class EtherInt : public SimObject
virtual ~EtherInt() {}
void setPeer(EtherInt *p);
- virtual bool recvPacket(PacketPtr &packet) = 0;
+
void recvDone() { peer->sendDone(); }
- bool sendPacket(PacketPtr &packet)
- {
- return peer ? peer->recvPacket(packet) : true;
- }
virtual void sendDone() = 0;
+
+ bool sendPacket(PacketPtr packet)
+ { return peer ? peer->recvPacket(packet) : true; }
+ virtual bool recvPacket(PacketPtr packet) = 0;
};
-#endif // __ETHERINT_HH__
+#endif // __DEV_ETHERINT_HH__
diff --git a/dev/etherlink.cc b/dev/etherlink.cc
index 3cc4f75ea..d637e152a 100644
--- a/dev/etherlink.cc
+++ b/dev/etherlink.cc
@@ -41,8 +41,9 @@
#include "dev/etherlink.hh"
#include "dev/etherpkt.hh"
#include "sim/builder.hh"
-#include "sim/universe.hh"
+#include "sim/serialize.hh"
#include "sim/system.hh"
+#include "sim/universe.hh"
using namespace std;
@@ -104,7 +105,7 @@ EtherLink::unserialize(Checkpoint *cp, const string &section)
}
void
-EtherLink::Link::txComplete(PacketPtr &packet)
+EtherLink::Link::txComplete(PacketPtr packet)
{
DPRINTF(Ethernet, "packet received: len=%d\n", packet->length);
DDUMP(EthernetData, packet->data, packet->length);
@@ -121,7 +122,7 @@ class LinkDelayEvent : public Event
LinkDelayEvent(EtherLink::Link *link);
public:
- LinkDelayEvent(EtherLink::Link *link, PacketPtr &pkt, Tick when);
+ LinkDelayEvent(EtherLink::Link *link, PacketPtr pkt, Tick when);
void process();
@@ -152,7 +153,7 @@ EtherLink::Link::txDone()
}
bool
-EtherLink::Link::transmit(PacketPtr &pkt)
+EtherLink::Link::transmit(PacketPtr pkt)
{
if (busy()) {
DPRINTF(Ethernet, "packet not sent, link busy\n");
@@ -184,10 +185,8 @@ EtherLink::Link::serialize(ostream &os)
SERIALIZE_SCALAR(event_time);
}
- if (packet_exists) {
- nameOut(os, csprintf("%s.packet", name()));
- packet->serialize(os);
- }
+ if (packet_exists)
+ packet->serialize("packet", os);
}
void
@@ -196,8 +195,8 @@ EtherLink::Link::unserialize(Checkpoint *cp, const string &section)
bool packet_exists;
UNSERIALIZE_SCALAR(packet_exists);
if (packet_exists) {
- packet = new EtherPacket;
- packet->unserialize(cp, csprintf("%s.packet", section));
+ packet = new PacketData(16384);
+ packet->unserialize("packet", cp, section);
}
bool event_scheduled;
@@ -216,7 +215,7 @@ LinkDelayEvent::LinkDelayEvent(EtherLink::Link *l)
setFlags(AutoDelete);
}
-LinkDelayEvent::LinkDelayEvent(EtherLink::Link *l, PacketPtr &p, Tick when)
+LinkDelayEvent::LinkDelayEvent(EtherLink::Link *l, PacketPtr p, Tick when)
: Event(&mainEventQueue), link(l), packet(p)
{
setFlags(AutoSerialize);
@@ -237,8 +236,7 @@ LinkDelayEvent::serialize(ostream &os)
Event::serialize(os);
SERIALIZE_OBJPTR(link);
- nameOut(os, csprintf("%s.packet", name()));
- packet->serialize(os);
+ packet->serialize("packet", os);
}
@@ -246,8 +244,8 @@ void
LinkDelayEvent::unserialize(Checkpoint *cp, const string &section)
{
Event::unserialize(cp, section);
- packet = new EtherPacket;
- packet->unserialize(cp, csprintf("%s.packet", section));
+ packet = new PacketData(16384);
+ packet->unserialize("packet", cp, section);
}
diff --git a/dev/etherlink.hh b/dev/etherlink.hh
index 204348c6d..e998a006f 100644
--- a/dev/etherlink.hh
+++ b/dev/etherlink.hh
@@ -75,7 +75,7 @@ class EtherLink : public SimObject
DoneEvent doneEvent;
friend class LinkDelayEvent;
- void txComplete(PacketPtr &packet);
+ void txComplete(PacketPtr packet);
public:
Link(const std::string &name, double rate, Tick delay,
@@ -85,7 +85,7 @@ class EtherLink : public SimObject
virtual const std::string name() const { return objName; }
bool busy() const { return (bool)packet; }
- bool transmit(PacketPtr &packet);
+ bool transmit(PacketPtr packet);
void setTxInt(Interface *i) { assert(!txint); txint = i; }
void setRxInt(Interface *i) { assert(!rxint); rxint = i; }
@@ -104,7 +104,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(PacketPtr packet) { return txlink->transmit(packet); }
void sendDone() { peer->sendDone(); }
};
diff --git a/dev/etherpkt.cc b/dev/etherpkt.cc
index 9eda89e9d..bf60bc150 100644
--- a/dev/etherpkt.cc
+++ b/dev/etherpkt.cc
@@ -28,23 +28,23 @@
#include <iostream>
+#include "base/misc.hh"
#include "dev/etherpkt.hh"
#include "sim/serialize.hh"
using namespace std;
void
-EtherPacket::serialize(ostream &os)
+PacketData::serialize(const string &base, ostream &os)
{
- SERIALIZE_SCALAR(length);
- SERIALIZE_ARRAY(data, length);
+ paramOut(os, base + ".length", length);
+ arrayParamOut(os, base + ".data", data, length);
}
void
-EtherPacket::unserialize(Checkpoint *cp, const string &section)
+PacketData::unserialize(const string &base, Checkpoint *cp,
+ const string &section)
{
- UNSERIALIZE_SCALAR(length);
- data = new uint8_t[length];
- UNSERIALIZE_ARRAY(data, length);
+ paramIn(cp, section, base + ".length", length);
+ arrayParamIn(cp, section, base + ".data", data, length);
}
-
diff --git a/dev/etherpkt.hh b/dev/etherpkt.hh
index abdf30166..7a7809f0a 100644
--- a/dev/etherpkt.hh
+++ b/dev/etherpkt.hh
@@ -37,70 +37,32 @@
#include <memory>
#include <assert.h>
-#include "sim/host.hh"
#include "base/refcnt.hh"
-#include "base/inet_hdrs.hh"
+#include "sim/host.hh"
-class Checkpoint;
/*
* Reference counted class containing ethernet packet data
*/
-class EtherPacket : public RefCounted
+class Checkpoint;
+class PacketData : public RefCounted
{
public:
uint8_t *data;
int length;
public:
- EtherPacket() : data(NULL), length(0) {}
- EtherPacket(std::auto_ptr<uint8_t> d, int l)
- : data(d.release()), length(l) {}
- ~EtherPacket() { if (data) delete [] data; }
+ PacketData() : data(NULL), length(0) { }
+ explicit PacketData(size_t size) : data(new uint8_t[size]), length(0) { }
+ PacketData(std::auto_ptr<uint8_t> d, int l)
+ : data(d.release()), length(l) { }
+ ~PacketData() { if (data) delete [] data; }
public:
- bool IsUnicast() { return data[0] == 0x00; }
- bool IsMulticast() { return data[0] == 0x01; }
- bool IsBroadcast() { return data[0] == 0xff; }
-
- bool isIpPkt() {
- eth_header *eth = (eth_header *) data;
- return (eth->type == 0x8);
- }
- bool isTcpPkt(ip_header *ip) {
- return (ip->protocol == 0x6);
- }
- bool isTcpPkt() {
- ip_header *ip = getIpHdr();
- return (ip->protocol == 0x6);
- }
- bool isUdpPkt(ip_header *ip) {
- return (ip->protocol == 17);
- }
- bool isUdpPkt() {
- ip_header *ip = getIpHdr();
- return (ip->protocol == 17);
- }
-
- ip_header *getIpHdr() {
- assert(isIpPkt());
- return (ip_header *) (data + sizeof(eth_header));
- }
-
- tcp_header *getTcpHdr(ip_header *ip) {
- assert(isTcpPkt(ip));
- return (tcp_header *) ((uint8_t *) ip + (ip->vers_len & 0xf)*4);
- }
-
- udp_header *getUdpHdr(ip_header *ip) {
- assert(isUdpPkt(ip));
- return (udp_header *) ((uint8_t *) ip + (ip->vers_len & 0xf)*4);
- }
- typedef RefCountingPtr<EtherPacket> PacketPtr;
-
- void serialize(std::ostream &os);
- void unserialize(Checkpoint *cp, const std::string &section);
+ void serialize(const std::string &base, std::ostream &os);
+ void unserialize(const std::string &base, Checkpoint *cp,
+ const std::string &section);
};
-typedef RefCountingPtr<EtherPacket> PacketPtr;
+typedef RefCountingPtr<PacketData> PacketPtr;
#endif // __ETHERPKT_HH__
diff --git a/dev/ethertap.cc b/dev/ethertap.cc
index edc400760..1603a9bd3 100644
--- a/dev/ethertap.cc
+++ b/dev/ethertap.cc
@@ -169,7 +169,7 @@ EtherTap::detach()
}
bool
-EtherTap::recvPacket(PacketPtr &packet)
+EtherTap::recvPacket(PacketPtr packet)
{
if (dump)
dump->dump(packet);
@@ -219,8 +219,7 @@ EtherTap::process(int revent)
while (data_len != 0 && buffer_offset >= data_len + sizeof(u_int32_t)) {
PacketPtr packet;
- packet = new EtherPacket;
- packet->data = new uint8_t[data_len];
+ packet = new PacketData(data_len);
packet->length = data_len;
memcpy(packet->data, data, data_len);
diff --git a/dev/ethertap.hh b/dev/ethertap.hh
index 1fe368085..5f760ed34 100644
--- a/dev/ethertap.hh
+++ b/dev/ethertap.hh
@@ -70,7 +70,7 @@ class EtherTap : public EtherInt
std::queue<PacketPtr> packetBuffer;
void process(int revent);
- void enqueue(EtherPacket *packet);
+ void enqueue(PacketData *packet);
void retransmit();
/*
@@ -94,7 +94,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(PacketPtr packet);
virtual void sendDone();
virtual void serialize(std::ostream &os);
diff --git a/dev/ide_ctrl.cc b/dev/ide_ctrl.cc
index e40248461..109908ead 100644
--- a/dev/ide_ctrl.cc
+++ b/dev/ide_ctrl.cc
@@ -34,16 +34,15 @@
#include "base/trace.hh"
#include "cpu/intr_control.hh"
#include "dev/dma.hh"
-#include "dev/pcireg.h"
-#include "dev/pciconfigall.hh"
-#include "dev/ide_disk.hh"
#include "dev/ide_ctrl.hh"
-#include "dev/tsunami_cchip.hh"
+#include "dev/ide_disk.hh"
+#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/bus/dma_interface.hh"
-#include "dev/tsunami.hh"
#include "mem/functional_mem/memory_control.hh"
#include "mem/functional_mem/physical_memory.hh"
#include "sim/builder.hh"
@@ -55,17 +54,9 @@ using namespace std;
// Initialization and destruction
////
-IdeController::IdeController(const string &name, IntrControl *ic,
- const vector<IdeDisk *> &new_disks,
- MemoryController *mmu, PciConfigAll *cf,
- PciConfigData *cd, Tsunami *t, uint32_t bus_num,
- uint32_t dev_num, uint32_t func_num,
- Bus *host_bus, Tick pio_latency, HierParams *hier)
- : PciDev(name, mmu, cf, cd, bus_num, dev_num, func_num), tsunami(t)
+IdeController::IdeController(Params *p)
+ : PciDev(p)
{
- // put back pointer into Tsunami
- tsunami->disk_controller = this;
-
// initialize the PIO interface addresses
pri_cmd_addr = 0;
pri_cmd_size = BARSize[0];
@@ -99,23 +90,25 @@ IdeController::IdeController(const string &name, IntrControl *ic,
memset(cmd_in_progress, 0, sizeof(cmd_in_progress));
// create the PIO and DMA interfaces
- if (host_bus) {
- pioInterface = newPioInterface(name, hier, host_bus, this,
+ if (params()->host_bus) {
+ pioInterface = newPioInterface(name(), params()->hier,
+ params()->host_bus, this,
&IdeController::cacheAccess);
- dmaInterface = new DMAInterface<Bus>(name + ".dma", host_bus,
- host_bus, 1);
- pioLatency = pio_latency * host_bus->clockRatio;
+ dmaInterface = new DMAInterface<Bus>(name() + ".dma",
+ params()->host_bus,
+ params()->host_bus, 1);
+ pioLatency = params()->pio_latency * params()->host_bus->clockRatio;
}
// setup the disks attached to controller
memset(disks, 0, sizeof(IdeDisk *) * 4);
- if (new_disks.size() > 3)
+ if (params()->disks.size() > 3)
panic("IDE controllers support a maximum of 4 devices attached!\n");
- for (int i = 0; i < new_disks.size(); i++) {
- disks[i] = new_disks[i];
+ for (int i = 0; i < params()->disks.size(); i++) {
+ disks[i] = params()->disks[i];
disks[i]->setController(this, dmaInterface);
}
}
@@ -239,22 +232,6 @@ IdeController::setDmaComplete(IdeDisk *disk)
}
////
-// Interrupt handling
-////
-
-void
-IdeController::intrPost()
-{
- tsunami->cchip->postDRIR(configData->config.hdr.pci0.interruptLine);
-}
-
-void
-IdeController::intrClear()
-{
- tsunami->cchip->clearDRIR(configData->config.hdr.pci0.interruptLine);
-}
-
-////
// Bus timing and bus access functions
////
@@ -377,10 +354,10 @@ IdeController::WriteConfig(int offset, int size, uint32_t data)
if (BARAddrs[0] != 0) {
pri_cmd_addr = BARAddrs[0];
if (pioInterface)
- pioInterface->addAddrRange(pri_cmd_addr,
- pri_cmd_addr + pri_cmd_size - 1);
+ pioInterface->addAddrRange(RangeSize(pri_cmd_addr,
+ pri_cmd_size));
- pri_cmd_addr &= PA_UNCACHED_MASK;
+ pri_cmd_addr &= EV5::PAddrUncachedMask;
}
break;
@@ -388,10 +365,10 @@ IdeController::WriteConfig(int offset, int size, uint32_t data)
if (BARAddrs[1] != 0) {
pri_ctrl_addr = BARAddrs[1];
if (pioInterface)
- pioInterface->addAddrRange(pri_ctrl_addr,
- pri_ctrl_addr + pri_ctrl_size - 1);
+ pioInterface->addAddrRange(RangeSize(pri_ctrl_addr,
+ pri_ctrl_size));
- pri_ctrl_addr &= PA_UNCACHED_MASK;
+ pri_ctrl_addr &= EV5::PAddrUncachedMask;
}
break;
@@ -399,10 +376,10 @@ IdeController::WriteConfig(int offset, int size, uint32_t data)
if (BARAddrs[2] != 0) {
sec_cmd_addr = BARAddrs[2];
if (pioInterface)
- pioInterface->addAddrRange(sec_cmd_addr,
- sec_cmd_addr + sec_cmd_size - 1);
+ pioInterface->addAddrRange(RangeSize(sec_cmd_addr,
+ sec_cmd_size));
- sec_cmd_addr &= PA_UNCACHED_MASK;
+ sec_cmd_addr &= EV5::PAddrUncachedMask;
}
break;
@@ -410,10 +387,10 @@ IdeController::WriteConfig(int offset, int size, uint32_t data)
if (BARAddrs[3] != 0) {
sec_ctrl_addr = BARAddrs[3];
if (pioInterface)
- pioInterface->addAddrRange(sec_ctrl_addr,
- sec_ctrl_addr + sec_ctrl_size - 1);
+ pioInterface->addAddrRange(RangeSize(sec_ctrl_addr,
+ sec_ctrl_size));
- sec_ctrl_addr &= PA_UNCACHED_MASK;
+ sec_ctrl_addr &= EV5::PAddrUncachedMask;
}
break;
@@ -421,9 +398,9 @@ IdeController::WriteConfig(int offset, int size, uint32_t data)
if (BARAddrs[4] != 0) {
bmi_addr = BARAddrs[4];
if (pioInterface)
- pioInterface->addAddrRange(bmi_addr, bmi_addr + bmi_size - 1);
+ pioInterface->addAddrRange(RangeSize(bmi_addr, bmi_size));
- bmi_addr &= PA_UNCACHED_MASK;
+ bmi_addr &= EV5::PAddrUncachedMask;
}
break;
}
@@ -675,15 +652,11 @@ IdeController::unserialize(Checkpoint *cp, const std::string &section)
UNSERIALIZE_ARRAY(cmd_in_progress, 4);
if (pioInterface) {
- pioInterface->addAddrRange(pri_cmd_addr, pri_cmd_addr +
- pri_cmd_size - 1);
- pioInterface->addAddrRange(pri_ctrl_addr, pri_ctrl_addr +
- pri_ctrl_size - 1);
- pioInterface->addAddrRange(sec_cmd_addr, sec_cmd_addr +
- sec_cmd_size - 1);
- pioInterface->addAddrRange(sec_ctrl_addr, sec_ctrl_addr +
- sec_ctrl_size - 1);
- pioInterface->addAddrRange(bmi_addr, bmi_addr + bmi_size - 1);
+ 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));
}
}
@@ -691,12 +664,11 @@ IdeController::unserialize(Checkpoint *cp, const std::string &section)
BEGIN_DECLARE_SIM_OBJECT_PARAMS(IdeController)
- SimObjectParam<IntrControl *> intr_ctrl;
SimObjectVectorParam<IdeDisk *> disks;
SimObjectParam<MemoryController *> mmu;
SimObjectParam<PciConfigAll *> configspace;
SimObjectParam<PciConfigData *> configdata;
- SimObjectParam<Tsunami *> tsunami;
+ SimObjectParam<Platform *> platform;
Param<uint32_t> pci_bus;
Param<uint32_t> pci_dev;
Param<uint32_t> pci_func;
@@ -708,12 +680,11 @@ END_DECLARE_SIM_OBJECT_PARAMS(IdeController)
BEGIN_INIT_SIM_OBJECT_PARAMS(IdeController)
- INIT_PARAM(intr_ctrl, "Interrupt Controller"),
INIT_PARAM(disks, "IDE disks attached to this controller"),
INIT_PARAM(mmu, "Memory controller"),
INIT_PARAM(configspace, "PCI Configspace"),
INIT_PARAM(configdata, "PCI Config data"),
- INIT_PARAM(tsunami, "Tsunami chipset pointer"),
+ 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"),
@@ -725,9 +696,21 @@ END_INIT_SIM_OBJECT_PARAMS(IdeController)
CREATE_SIM_OBJECT(IdeController)
{
- return new IdeController(getInstanceName(), intr_ctrl, disks, mmu,
- configspace, configdata, tsunami, pci_bus,
- pci_dev, pci_func, io_bus, pio_latency, hier);
+ IdeController::Params *params = new IdeController::Params;
+ params->name = getInstanceName();
+ params->mmu = mmu;
+ params->configSpace = configspace;
+ params->configData = configdata;
+ params->plat = platform;
+ params->busNum = pci_bus;
+ params->deviceNum = pci_dev;
+ params->functionNum = pci_func;
+
+ params->disks = disks;
+ params->host_bus = io_bus;
+ params->pio_latency = pio_latency;
+ params->hier = hier;
+ return new IdeController(params);
}
REGISTER_SIM_OBJECT("IdeController", IdeController)
diff --git a/dev/ide_ctrl.hh b/dev/ide_ctrl.hh
index b29e5ae9a..f1082d094 100644
--- a/dev/ide_ctrl.hh
+++ b/dev/ide_ctrl.hh
@@ -80,14 +80,14 @@ typedef enum RegType {
BMI_BLOCK
} RegType_t;
+class BaseInterface;
+class Bus;
+class HierParams;
class IdeDisk;
class IntrControl;
class PciConfigAll;
-class Tsunami;
class PhysicalMemory;
-class BaseInterface;
-class HierParams;
-class Bus;
+class Platform;
/**
* Device model for an Intel PIIX4 IDE controller
@@ -95,6 +95,8 @@ class Bus;
class IdeController : public PciDev
{
+ friend class IdeDisk;
+
private:
/** Primary command block registers */
Addr pri_cmd_addr;
@@ -125,10 +127,6 @@ class IdeController : public PciDev
bool bm_enabled;
bool cmd_in_progress[4];
- public:
- /** Pointer to the chipset */
- Tsunami *tsunami;
-
private:
/** IDE disks connected to controller */
IdeDisk *disks[4];
@@ -149,37 +147,23 @@ class IdeController : public PciDev
bool isDiskSelected(IdeDisk *diskPtr);
public:
- /**
- * Constructs and initializes this controller.
- * @param name The name of this controller.
- * @param ic The interrupt controller.
- * @param mmu The memory controller
- * @param cf PCI config space
- * @param cd PCI config data
- * @param bus_num The PCI bus number
- * @param dev_num The PCI device number
- * @param func_num The PCI function number
- * @param host_bus The host bus to connect to
- * @param hier The hierarchy parameters
- */
- IdeController(const std::string &name, IntrControl *ic,
- const std::vector<IdeDisk *> &new_disks,
- MemoryController *mmu, PciConfigAll *cf,
- PciConfigData *cd, Tsunami *t,
- uint32_t bus_num, uint32_t dev_num, uint32_t func_num,
- Bus *host_bus, Tick pio_latency, HierParams *hier);
+ struct Params : public PciDev::Params
+ {
+ /** Array of disk objects */
+ std::vector<IdeDisk *> disks;
+ Bus *host_bus;
+ Tick pio_latency;
+ HierParams *hier;
+ };
+ const Params *params() const { return (const Params *)_params; }
- /**
- * Deletes the connected devices.
- */
+ public:
+ IdeController(Params *p);
~IdeController();
virtual void WriteConfig(int offset, int size, uint32_t data);
virtual void ReadConfig(int offset, int size, uint8_t *data);
- void intrPost();
- void intrClear();
-
void setDmaComplete(IdeDisk *disk);
/**
diff --git a/dev/ide_disk.cc b/dev/ide_disk.cc
index 99724f077..073c10436 100644
--- a/dev/ide_disk.cc
+++ b/dev/ide_disk.cc
@@ -35,7 +35,6 @@
#include <deque>
#include <string>
-#include "arch/alpha/pmap.h"
#include "base/cprintf.hh" // csprintf
#include "base/trace.hh"
#include "dev/disk_image.hh"
@@ -51,6 +50,7 @@
#include "sim/builder.hh"
#include "sim/sim_object.hh"
#include "sim/universe.hh"
+#include "targetarch/isa_traits.hh"
using namespace std;
@@ -177,7 +177,7 @@ Addr
IdeDisk::pciToDma(Addr pciAddr)
{
if (ctrl)
- return ctrl->tsunami->pchip->translatePciToDma(pciAddr);
+ return ctrl->plat->pciToDma(pciAddr);
else
panic("Access to unset controller!\n");
}
@@ -188,14 +188,14 @@ IdeDisk::bytesInDmaPage(Addr curAddr, uint32_t bytesLeft)
uint32_t bytesInPage = 0;
// First calculate how many bytes could be in the page
- if (bytesLeft > ALPHA_PGBYTES)
- bytesInPage = ALPHA_PGBYTES;
+ 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 = alpha_trunc_page(curAddr) + ALPHA_PGBYTES;
+ Addr pageBound = TheISA::TruncPage(curAddr) + TheISA::PageBytes;
assert(upperBound >= curAddr && "DMA read wraps around address space!\n");
@@ -510,7 +510,7 @@ IdeDisk::dmaWriteDone()
// setup the initial page and DMA address
curAddr = curPrd.getBaseAddr();
- pageAddr = alpha_trunc_page(curAddr);
+ pageAddr = TheISA::TruncPage(curAddr);
dmaAddr = pciToDma(curAddr);
// clear out the data buffer
@@ -518,14 +518,14 @@ IdeDisk::dmaWriteDone()
while (bytesRead < curPrd.getByteCount()) {
// see if we have crossed into a new page
- if (pageAddr != alpha_trunc_page(curAddr)) {
+ 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 = alpha_trunc_page(curAddr);
+ pageAddr = TheISA::TruncPage(curAddr);
dmaAddr = pciToDma(curAddr);
bytesInPage = 0;
@@ -732,6 +732,7 @@ IdeDisk::startCommand()
void
IdeDisk::intrPost()
{
+ DPRINTF(IdeDisk, "IDE Disk Posting Interrupt\n");
if (intrPending)
panic("Attempt to post an interrupt with one pending\n");
@@ -745,6 +746,7 @@ IdeDisk::intrPost()
void
IdeDisk::intrClear()
{
+ DPRINTF(IdeDisk, "IDE Disk Clearing Interrupt\n");
if (!intrPending)
panic("Attempt to clear a non-pending interrupt\n");
diff --git a/dev/io_device.hh b/dev/io_device.hh
index f49afc0a6..8c9dc4a35 100644
--- a/dev/io_device.hh
+++ b/dev/io_device.hh
@@ -34,7 +34,7 @@
class BaseInterface;
class Bus;
class HierParams;
-template <class Bus> class DMAInterface;
+template <class BusType> class DMAInterface;
class PioDevice : public FunctionalMemory
{
diff --git a/dev/ns_gige.cc b/dev/ns_gige.cc
index f7f56d39b..eee8fbbce 100644
--- a/dev/ns_gige.cc
+++ b/dev/ns_gige.cc
@@ -41,7 +41,6 @@
#include "dev/etherlink.hh"
#include "dev/ns_gige.hh"
#include "dev/pciconfigall.hh"
-#include "dev/tsunami_cchip.hh"
#include "mem/bus/bus.hh"
#include "mem/bus/dma_interface.hh"
#include "mem/bus/pio_interface.hh"
@@ -51,7 +50,7 @@
#include "sim/builder.hh"
#include "sim/debug.hh"
#include "sim/host.hh"
-#include "sim/sim_stats.hh"
+#include "sim/stats.hh"
#include "targetarch/vtophys.hh"
const char *NsRxStateStrings[] =
@@ -86,82 +85,68 @@ const char *NsDmaState[] =
};
using namespace std;
-
-// helper function declarations
-// These functions reverse Endianness so we can evaluate network data
-// correctly
-uint16_t reverseEnd16(uint16_t);
-uint32_t reverseEnd32(uint32_t);
+using namespace Net;
///////////////////////////////////////////////////////////////////////
//
// NSGigE PCI Device
//
-NSGigE::NSGigE(const std::string &name, IntrControl *i, Tick intr_delay,
- PhysicalMemory *pmem, Tick tx_delay, Tick rx_delay,
- MemoryController *mmu, HierParams *hier, Bus *header_bus,
- Bus *payload_bus, Tick pio_latency, bool dma_desc_free,
- bool dma_data_free, Tick dma_read_delay, Tick dma_write_delay,
- Tick dma_read_factor, Tick dma_write_factor, PciConfigAll *cf,
- PciConfigData *cd, Tsunami *t, uint32_t bus, uint32_t dev,
- uint32_t func, bool rx_filter, const int eaddr[6],
- uint32_t tx_fifo_size, uint32_t rx_fifo_size)
- : PciDev(name, mmu, cf, cd, bus, dev, func), tsunami(t), ioEnable(false),
- maxTxFifoSize(tx_fifo_size), maxRxFifoSize(rx_fifo_size),
+NSGigE::NSGigE(Params *p)
+ : PciDev(p), ioEnable(false),
+ txFifo(p->tx_fifo_size), rxFifo(p->rx_fifo_size),
txPacket(0), rxPacket(0), txPacketBufPtr(NULL), rxPacketBufPtr(NULL),
txXferLen(0), rxXferLen(0), txState(txIdle), txEnable(false),
- CTDD(false), txFifoAvail(tx_fifo_size),
+ CTDD(false),
txFragPtr(0), txDescCnt(0), txDmaState(dmaIdle), rxState(rxIdle),
- rxEnable(false), CRDD(false), rxPktBytes(0), rxFifoCnt(0),
+ rxEnable(false), CRDD(false), rxPktBytes(0),
rxFragPtr(0), rxDescCnt(0), rxDmaState(dmaIdle), extstsEnable(false),
rxDmaReadEvent(this), rxDmaWriteEvent(this),
txDmaReadEvent(this), txDmaWriteEvent(this),
- dmaDescFree(dma_desc_free), dmaDataFree(dma_data_free),
- txDelay(tx_delay), rxDelay(rx_delay), rxKickTick(0), txKickTick(0),
- txEvent(this), rxFilterEnable(rx_filter), acceptBroadcast(false),
+ dmaDescFree(p->dma_desc_free), dmaDataFree(p->dma_data_free),
+ txDelay(p->tx_delay), rxDelay(p->rx_delay),
+ rxKickTick(0), txKickTick(0),
+ txEvent(this), rxFilterEnable(p->rx_filter), acceptBroadcast(false),
acceptMulticast(false), acceptUnicast(false),
acceptPerfect(false), acceptArp(false),
- physmem(pmem), intctrl(i), intrTick(0), cpuPendingIntr(false),
+ physmem(p->pmem), intrTick(0), cpuPendingIntr(false),
intrEvent(0), interface(0)
{
- tsunami->ethernet = this;
-
- if (header_bus) {
- pioInterface = newPioInterface(name, hier, header_bus, this,
+ if (p->header_bus) {
+ pioInterface = newPioInterface(name(), p->hier,
+ p->header_bus, this,
&NSGigE::cacheAccess);
- pioLatency = pio_latency * header_bus->clockRatio;
+ pioLatency = p->pio_latency * p->header_bus->clockRatio;
- if (payload_bus)
- dmaInterface = new DMAInterface<Bus>(name + ".dma",
- header_bus, payload_bus, 1);
+ if (p->payload_bus)
+ dmaInterface = new DMAInterface<Bus>(name() + ".dma",
+ p->header_bus,
+ p->payload_bus, 1);
else
- dmaInterface = new DMAInterface<Bus>(name + ".dma",
- header_bus, header_bus, 1);
- } else if (payload_bus) {
- pioInterface = newPioInterface(name, hier, payload_bus, this,
+ dmaInterface = new DMAInterface<Bus>(name() + ".dma",
+ p->header_bus,
+ p->header_bus, 1);
+ } else if (p->payload_bus) {
+ pioInterface = newPioInterface(name(), p->hier,
+ p->payload_bus, this,
&NSGigE::cacheAccess);
- pioLatency = pio_latency * payload_bus->clockRatio;
+ pioLatency = p->pio_latency * p->payload_bus->clockRatio;
- dmaInterface = new DMAInterface<Bus>(name + ".dma", payload_bus,
- payload_bus, 1);
+ dmaInterface = new DMAInterface<Bus>(name() + ".dma",
+ p->payload_bus,
+ p->payload_bus, 1);
}
- intrDelay = US2Ticks(intr_delay);
- dmaReadDelay = dma_read_delay;
- dmaWriteDelay = dma_write_delay;
- dmaReadFactor = dma_read_factor;
- dmaWriteFactor = dma_write_factor;
+ intrDelay = US2Ticks(p->intr_delay);
+ dmaReadDelay = p->dma_read_delay;
+ dmaWriteDelay = p->dma_write_delay;
+ dmaReadFactor = p->dma_read_factor;
+ dmaWriteFactor = p->dma_write_factor;
regsReset();
- rom.perfectMatch[0] = eaddr[0];
- rom.perfectMatch[1] = eaddr[1];
- rom.perfectMatch[2] = eaddr[2];
- rom.perfectMatch[3] = eaddr[3];
- rom.perfectMatch[4] = eaddr[4];
- rom.perfectMatch[5] = eaddr[5];
+ memcpy(&rom.perfectMatch, p->eaddr.bytes(), ETH_ADDR_LEN);
}
NSGigE::~NSGigE()
@@ -194,34 +179,48 @@ NSGigE::regStats()
.prereq(rxBytes)
;
- txIPChecksums
- .name(name() + ".txIPChecksums")
+ txIpChecksums
+ .name(name() + ".txIpChecksums")
.desc("Number of tx IP Checksums done by device")
.precision(0)
.prereq(txBytes)
;
- rxIPChecksums
- .name(name() + ".rxIPChecksums")
+ rxIpChecksums
+ .name(name() + ".rxIpChecksums")
.desc("Number of rx IP Checksums done by device")
.precision(0)
.prereq(rxBytes)
;
- txTCPChecksums
- .name(name() + ".txTCPChecksums")
+ txTcpChecksums
+ .name(name() + ".txTcpChecksums")
.desc("Number of tx TCP Checksums done by device")
.precision(0)
.prereq(txBytes)
;
- rxTCPChecksums
- .name(name() + ".rxTCPChecksums")
+ rxTcpChecksums
+ .name(name() + ".rxTcpChecksums")
.desc("Number of rx TCP Checksums done by device")
.precision(0)
.prereq(rxBytes)
;
+ txUdpChecksums
+ .name(name() + ".txUdpChecksums")
+ .desc("Number of tx UDP Checksums done by device")
+ .precision(0)
+ .prereq(txBytes)
+ ;
+
+ rxUdpChecksums
+ .name(name() + ".rxUdpChecksums")
+ .desc("Number of rx UDP Checksums done by device")
+ .precision(0)
+ .prereq(rxBytes)
+ ;
+
descDmaReads
.name(name() + ".descDMAReads")
.desc("Number of descriptors the device read w/ DMA")
@@ -275,6 +274,180 @@ NSGigE::regStats()
.prereq(rxBytes)
;
+ postedSwi
+ .name(name() + ".postedSwi")
+ .desc("number of software interrupts posted to CPU")
+ .precision(0)
+ ;
+
+ totalSwi
+ .name(name() + ".totalSwi")
+ .desc("number of total Swi written to ISR")
+ .precision(0)
+ ;
+
+ coalescedSwi
+ .name(name() + ".coalescedSwi")
+ .desc("average number of Swi's coalesced into each post")
+ .precision(0)
+ ;
+
+ postedRxIdle
+ .name(name() + ".postedRxIdle")
+ .desc("number of rxIdle interrupts posted to CPU")
+ .precision(0)
+ ;
+
+ totalRxIdle
+ .name(name() + ".totalRxIdle")
+ .desc("number of total RxIdle written to ISR")
+ .precision(0)
+ ;
+
+ coalescedRxIdle
+ .name(name() + ".coalescedRxIdle")
+ .desc("average number of RxIdle's coalesced into each post")
+ .precision(0)
+ ;
+
+ postedRxOk
+ .name(name() + ".postedRxOk")
+ .desc("number of RxOk interrupts posted to CPU")
+ .precision(0)
+ ;
+
+ totalRxOk
+ .name(name() + ".totalRxOk")
+ .desc("number of total RxOk written to ISR")
+ .precision(0)
+ ;
+
+ coalescedRxOk
+ .name(name() + ".coalescedRxOk")
+ .desc("average number of RxOk's coalesced into each post")
+ .precision(0)
+ ;
+
+ postedRxDesc
+ .name(name() + ".postedRxDesc")
+ .desc("number of RxDesc interrupts posted to CPU")
+ .precision(0)
+ ;
+
+ totalRxDesc
+ .name(name() + ".totalRxDesc")
+ .desc("number of total RxDesc written to ISR")
+ .precision(0)
+ ;
+
+ coalescedRxDesc
+ .name(name() + ".coalescedRxDesc")
+ .desc("average number of RxDesc's coalesced into each post")
+ .precision(0)
+ ;
+
+ postedTxOk
+ .name(name() + ".postedTxOk")
+ .desc("number of TxOk interrupts posted to CPU")
+ .precision(0)
+ ;
+
+ totalTxOk
+ .name(name() + ".totalTxOk")
+ .desc("number of total TxOk written to ISR")
+ .precision(0)
+ ;
+
+ coalescedTxOk
+ .name(name() + ".coalescedTxOk")
+ .desc("average number of TxOk's coalesced into each post")
+ .precision(0)
+ ;
+
+ postedTxIdle
+ .name(name() + ".postedTxIdle")
+ .desc("number of TxIdle interrupts posted to CPU")
+ .precision(0)
+ ;
+
+ totalTxIdle
+ .name(name() + ".totalTxIdle")
+ .desc("number of total TxIdle written to ISR")
+ .precision(0)
+ ;
+
+ coalescedTxIdle
+ .name(name() + ".coalescedTxIdle")
+ .desc("average number of TxIdle's coalesced into each post")
+ .precision(0)
+ ;
+
+ postedTxDesc
+ .name(name() + ".postedTxDesc")
+ .desc("number of TxDesc interrupts posted to CPU")
+ .precision(0)
+ ;
+
+ totalTxDesc
+ .name(name() + ".totalTxDesc")
+ .desc("number of total TxDesc written to ISR")
+ .precision(0)
+ ;
+
+ coalescedTxDesc
+ .name(name() + ".coalescedTxDesc")
+ .desc("average number of TxDesc's coalesced into each post")
+ .precision(0)
+ ;
+
+ postedRxOrn
+ .name(name() + ".postedRxOrn")
+ .desc("number of RxOrn posted to CPU")
+ .precision(0)
+ ;
+
+ totalRxOrn
+ .name(name() + ".totalRxOrn")
+ .desc("number of total RxOrn written to ISR")
+ .precision(0)
+ ;
+
+ coalescedRxOrn
+ .name(name() + ".coalescedRxOrn")
+ .desc("average number of RxOrn's coalesced into each post")
+ .precision(0)
+ ;
+
+ coalescedTotal
+ .name(name() + ".coalescedTotal")
+ .desc("average number of interrupts coalesced into each post")
+ .precision(0)
+ ;
+
+ postedInterrupts
+ .name(name() + ".postedInterrupts")
+ .desc("number of posts to CPU")
+ .precision(0)
+ ;
+
+ droppedPackets
+ .name(name() + ".droppedPackets")
+ .desc("number of packets dropped")
+ .precision(0)
+ ;
+
+ coalescedSwi = totalSwi / postedInterrupts;
+ coalescedRxIdle = totalRxIdle / postedInterrupts;
+ coalescedRxOk = totalRxOk / postedInterrupts;
+ coalescedRxDesc = totalRxDesc / postedInterrupts;
+ coalescedTxOk = totalTxOk / postedInterrupts;
+ coalescedTxIdle = totalTxIdle / postedInterrupts;
+ coalescedTxDesc = totalTxDesc / postedInterrupts;
+ coalescedRxOrn = totalRxOrn / postedInterrupts;
+
+ coalescedTotal = (totalSwi + totalRxIdle + totalRxOk + totalRxDesc + totalTxOk
+ + totalTxIdle + totalTxDesc + totalRxOrn) / postedInterrupts;
+
txBandwidth = txBytes * Stats::constant(8) / simSeconds;
rxBandwidth = rxBytes * Stats::constant(8) / simSeconds;
txPacketRate = txPackets / simSeconds;
@@ -335,19 +508,17 @@ NSGigE::WriteConfig(int offset, int size, uint32_t data)
case PCI0_BASE_ADDR0:
if (BARAddrs[0] != 0) {
if (pioInterface)
- pioInterface->addAddrRange(BARAddrs[0],
- BARAddrs[0] + BARSize[0] - 1);
+ pioInterface->addAddrRange(RangeSize(BARAddrs[0], BARSize[0]));
- BARAddrs[0] &= PA_UNCACHED_MASK;
+ BARAddrs[0] &= EV5::PAddrUncachedMask;
}
break;
case PCI0_BASE_ADDR1:
if (BARAddrs[1] != 0) {
if (pioInterface)
- pioInterface->addAddrRange(BARAddrs[1],
- BARAddrs[1] + BARSize[1] - 1);
+ pioInterface->addAddrRange(RangeSize(BARAddrs[1], BARSize[1]));
- BARAddrs[1] &= PA_UNCACHED_MASK;
+ BARAddrs[1] &= EV5::PAddrUncachedMask;
}
break;
}
@@ -934,6 +1105,33 @@ NSGigE::devIntrPost(uint32_t interrupts)
interrupts &= ~ISR_NOIMPL;
regs.isr |= interrupts;
+ if (interrupts & regs.imr) {
+ if (interrupts & ISR_SWI) {
+ totalSwi++;
+ }
+ if (interrupts & ISR_RXIDLE) {
+ totalRxIdle++;
+ }
+ if (interrupts & ISR_RXOK) {
+ totalRxOk++;
+ }
+ if (interrupts & ISR_RXDESC) {
+ totalRxDesc++;
+ }
+ if (interrupts & ISR_TXOK) {
+ totalTxOk++;
+ }
+ if (interrupts & ISR_TXIDLE) {
+ totalTxIdle++;
+ }
+ if (interrupts & ISR_TXDESC) {
+ totalTxDesc++;
+ }
+ if (interrupts & ISR_RXORN) {
+ totalRxOrn++;
+ }
+ }
+
DPRINTF(EthernetIntr,
"interrupt written to ISR: intr=%#x isr=%#x imr=%#x\n",
interrupts, regs.isr, regs.imr);
@@ -946,12 +1144,46 @@ NSGigE::devIntrPost(uint32_t interrupts)
}
}
+/* writing this interrupt counting stats inside this means that this function
+ is now limited to being used to clear all interrupts upon the kernel
+ reading isr and servicing. just telling you in case you were thinking
+ of expanding use.
+*/
void
NSGigE::devIntrClear(uint32_t interrupts)
{
if (interrupts & ISR_RESERVE)
panic("Cannot clear a reserved interrupt");
+ if (regs.isr & regs.imr & ISR_SWI) {
+ postedSwi++;
+ }
+ if (regs.isr & regs.imr & ISR_RXIDLE) {
+ postedRxIdle++;
+ }
+ if (regs.isr & regs.imr & ISR_RXOK) {
+ postedRxOk++;
+ }
+ if (regs.isr & regs.imr & ISR_RXDESC) {
+ postedRxDesc++;
+ }
+ if (regs.isr & regs.imr & ISR_TXOK) {
+ postedTxOk++;
+ }
+ if (regs.isr & regs.imr & ISR_TXIDLE) {
+ postedTxIdle++;
+ }
+ if (regs.isr & regs.imr & ISR_TXDESC) {
+ postedTxDesc++;
+ }
+ if (regs.isr & regs.imr & ISR_RXORN) {
+ postedRxOrn++;
+ }
+
+ if (regs.isr & regs.imr & (ISR_SWI | ISR_RXIDLE | ISR_RXOK | ISR_RXDESC |
+ ISR_TXOK | ISR_TXIDLE | ISR_TXDESC | ISR_RXORN) )
+ postedInterrupts++;
+
interrupts &= ~ISR_NOIMPL;
regs.isr &= ~interrupts;
@@ -987,61 +1219,50 @@ NSGigE::cpuIntrPost(Tick when)
* @todo this warning should be removed and the intrTick code should
* be fixed.
*/
- if (intrTick < curTick && intrTick != 0) {
- warn("intrTick < curTick !!! intrTick=%d curTick=%d\n",
- intrTick, curTick);
- intrTick = 0;
- }
- assert((intrTick >= curTick) || (intrTick == 0));
- if (when > intrTick && intrTick != 0)
+ assert(when >= curTick);
+ assert(intrTick >= curTick || intrTick == 0);
+ if (when > intrTick && intrTick != 0) {
+ DPRINTF(EthernetIntr, "don't need to schedule event...intrTick=%d\n",
+ intrTick);
return;
+ }
intrTick = when;
-
- if (intrEvent) {
- intrEvent->squash();
- intrEvent = 0;
+ if (intrTick < curTick) {
+ debug_break();
+ intrTick = curTick;
}
- if (when < curTick) {
- cpuInterrupt();
- } else {
- DPRINTF(EthernetIntr,
- "going to schedule an interrupt for intrTick=%d\n",
- intrTick);
- intrEvent = new IntrEvent(this, true);
- intrEvent->schedule(intrTick);
- }
+ DPRINTF(EthernetIntr, "going to schedule an interrupt for intrTick=%d\n",
+ intrTick);
+
+ if (intrEvent)
+ intrEvent->squash();
+ intrEvent = new IntrEvent(this, true);
+ intrEvent->schedule(intrTick);
}
void
NSGigE::cpuInterrupt()
{
- // Don't send an interrupt if there's already one
- if (cpuPendingIntr) {
- DPRINTF(EthernetIntr,
- "would send an interrupt now, but there's already pending\n");
- intrTick = 0;
- return;
- }
- // Don't send an interrupt if it's supposed to be delayed
- if (intrTick > curTick) {
- DPRINTF(EthernetIntr,
- "an interrupt is scheduled for %d, wait til then\n",
- intrTick);
- return;
- }
+ assert(intrTick == curTick);
// Whether or not there's a pending interrupt, we don't care about
// it anymore
intrEvent = 0;
intrTick = 0;
- // Send interrupt
- cpuPendingIntr = true;
+ // Don't send an interrupt if there's already one
+ if (cpuPendingIntr) {
+ DPRINTF(EthernetIntr,
+ "would send an interrupt now, but there's already pending\n");
+ } else {
+ // Send interrupt
+ cpuPendingIntr = true;
- DPRINTF(EthernetIntr, "posting cchip interrupt\n");
- tsunami->cchip->postDRIR(configData->config.hdr.pci0.interruptLine);
+ DPRINTF(EthernetIntr, "posting interrupt\n");
+ intrPost();
+ }
}
void
@@ -1050,10 +1271,17 @@ NSGigE::cpuIntrClear()
if (!cpuPendingIntr)
return;
+ if (intrEvent) {
+ intrEvent->squash();
+ intrEvent = 0;
+ }
+
+ intrTick = 0;
+
cpuPendingIntr = false;
- DPRINTF(EthernetIntr, "clearing cchip interrupt\n");
- tsunami->cchip->clearDRIR(configData->config.hdr.pci0.interruptLine);
+ DPRINTF(EthernetIntr, "clearing interrupt\n");
+ intrClear();
}
bool
@@ -1067,7 +1295,6 @@ NSGigE::txReset()
DPRINTF(Ethernet, "transmit reset\n");
CTDD = false;
- txFifoAvail = maxTxFifoSize;
txEnable = false;;
txFragPtr = 0;
assert(txDescCnt == 0);
@@ -1083,7 +1310,6 @@ NSGigE::rxReset()
CRDD = false;
assert(rxPktBytes == 0);
- rxFifoCnt = 0;
rxEnable = false;
rxFragPtr = 0;
assert(rxDescCnt == 0);
@@ -1336,14 +1562,13 @@ NSGigE::rxKick()
#if TRACING_ON
if (DTRACE(Ethernet)) {
- if (rxPacket->isIpPkt()) {
- ip_header *ip = rxPacket->getIpHdr();
- DPRINTF(Ethernet, "ID is %d\n", reverseEnd16(ip->ID));
- if (rxPacket->isTcpPkt()) {
- tcp_header *tcp = rxPacket->getTcpHdr(ip);
+ IpPtr ip(rxPacket);
+ if (ip) {
+ DPRINTF(Ethernet, "ID is %d\n", ip->id());
+ TcpPtr tcp(ip);
+ if (tcp) {
DPRINTF(Ethernet, "Src Port=%d, Dest Port=%d\n",
- reverseEnd16(tcp->src_port_num),
- reverseEnd16(tcp->dest_port_num));
+ tcp->sport(), tcp->dport());
}
}
}
@@ -1351,12 +1576,7 @@ NSGigE::rxKick()
// sanity check - i think the driver behaves like this
assert(rxDescCnt >= rxPktBytes);
-
- // Must clear the value before popping to decrement the
- // reference count
- rxFifo.front() = NULL;
- rxFifo.pop_front();
- rxFifoCnt -= rxPacket->length;
+ rxFifo.pop();
}
@@ -1399,33 +1619,38 @@ NSGigE::rxKick()
*/
if (rxFilterEnable) {
rxDescCache.cmdsts &= ~CMDSTS_DEST_MASK;
- if (rxFifo.front()->IsUnicast())
+ const EthAddr &dst = rxFifoFront()->dst();
+ if (dst->unicast())
rxDescCache.cmdsts |= CMDSTS_DEST_SELF;
- if (rxFifo.front()->IsMulticast())
+ if (dst->multicast())
rxDescCache.cmdsts |= CMDSTS_DEST_MULTI;
- if (rxFifo.front()->IsBroadcast())
+ if (dst->broadcast())
rxDescCache.cmdsts |= CMDSTS_DEST_MASK;
}
#endif
- if (rxPacket->isIpPkt() && extstsEnable) {
+ IpPtr ip(rxPacket);
+ if (extstsEnable && ip) {
rxDescCache.extsts |= EXTSTS_IPPKT;
- rxIPChecksums++;
- if (!ipChecksum(rxPacket, false)) {
+ rxIpChecksums++;
+ if (cksum(ip) != 0) {
DPRINTF(EthernetCksum, "Rx IP Checksum Error\n");
rxDescCache.extsts |= EXTSTS_IPERR;
}
- if (rxPacket->isTcpPkt()) {
+ TcpPtr tcp(ip);
+ UdpPtr udp(ip);
+ if (tcp) {
rxDescCache.extsts |= EXTSTS_TCPPKT;
- rxTCPChecksums++;
- if (!tcpChecksum(rxPacket, false)) {
+ rxTcpChecksums++;
+ if (cksum(tcp) != 0) {
DPRINTF(EthernetCksum, "Rx TCP Checksum Error\n");
rxDescCache.extsts |= EXTSTS_TCPERR;
}
- } else if (rxPacket->isUdpPkt()) {
+ } else if (udp) {
rxDescCache.extsts |= EXTSTS_UDPPKT;
- if (!udpChecksum(rxPacket, false)) {
+ rxUdpChecksums++;
+ if (cksum(udp) != 0) {
DPRINTF(EthernetCksum, "Rx UDP Checksum Error\n");
rxDescCache.extsts |= EXTSTS_UDPERR;
}
@@ -1539,18 +1764,17 @@ NSGigE::transmit()
}
DPRINTF(Ethernet, "Attempt Pkt Transmit: txFifo length=%d\n",
- maxTxFifoSize - txFifoAvail);
+ txFifo.size());
if (interface->sendPacket(txFifo.front())) {
#if TRACING_ON
if (DTRACE(Ethernet)) {
- if (txFifo.front()->isIpPkt()) {
- ip_header *ip = txFifo.front()->getIpHdr();
- DPRINTF(Ethernet, "ID is %d\n", reverseEnd16(ip->ID));
- if (txFifo.front()->isTcpPkt()) {
- tcp_header *tcp = txFifo.front()->getTcpHdr(ip);
+ IpPtr ip(txFifo.front());
+ if (ip) {
+ DPRINTF(Ethernet, "ID is %d\n", ip->id());
+ TcpPtr tcp(ip);
+ if (tcp) {
DPRINTF(Ethernet, "Src Port=%d, Dest Port=%d\n",
- reverseEnd16(tcp->src_port_num),
- reverseEnd16(tcp->dest_port_num));
+ tcp->sport(), tcp->dport());
}
}
}
@@ -1560,12 +1784,9 @@ NSGigE::transmit()
txBytes += txFifo.front()->length;
txPackets++;
- txFifoAvail += txFifo.front()->length;
-
DPRINTF(Ethernet, "Successful Xmit! now txFifoAvail is %d\n",
- txFifoAvail);
- txFifo.front() = NULL;
- txFifo.pop_front();
+ txFifo.avail());
+ txFifo.pop();
/*
* normally do a writeback of the descriptor here, and ONLY
@@ -1575,9 +1796,6 @@ NSGigE::transmit()
* besides, it's functionally the same.
*/
devIntrPost(ISR_TXOK);
- } else {
- DPRINTF(Ethernet,
- "May need to rethink always sending the descriptors back?\n");
}
if (!txFifo.empty() && !txEvent.scheduled()) {
@@ -1784,8 +2002,7 @@ NSGigE::txKick()
case txFifoBlock:
if (!txPacket) {
DPRINTF(EthernetSM, "****starting the tx of a new packet****\n");
- txPacket = new EtherPacket;
- txPacket->data = new uint8_t[16384];
+ txPacket = new PacketData(16384);
txPacketBufPtr = txPacket->data;
}
@@ -1810,15 +2027,22 @@ NSGigE::txKick()
DPRINTF(EthernetSM, "This packet is done, let's wrap it up\n");
/* deal with the the packet that just finished */
if ((regs.vtcr & VTCR_PPCHK) && extstsEnable) {
+ IpPtr ip(txPacket);
if (txDescCache.extsts & EXTSTS_UDPPKT) {
- udpChecksum(txPacket, true);
+ UdpPtr udp(ip);
+ udp->sum(0);
+ udp->sum(cksum(udp));
+ txUdpChecksums++;
} else if (txDescCache.extsts & EXTSTS_TCPPKT) {
- tcpChecksum(txPacket, true);
- txTCPChecksums++;
+ TcpPtr tcp(ip);
+ tcp->sum(0);
+ tcp->sum(cksum(tcp));
+ txTcpChecksums++;
}
if (txDescCache.extsts & EXTSTS_IPPKT) {
- ipChecksum(txPacket, true);
- txIPChecksums++;
+ ip->sum(0);
+ ip->sum(cksum(ip));
+ txIpChecksums++;
}
}
@@ -1826,7 +2050,11 @@ NSGigE::txKick()
// this is just because the receive can't handle a
// packet bigger want to make sure
assert(txPacket->length <= 1514);
- txFifo.push_back(txPacket);
+#ifndef NDEBUG
+ bool success =
+#endif
+ txFifo.push(txPacket);
+ assert(success);
/*
* this following section is not tqo spec, but
@@ -1872,7 +2100,7 @@ NSGigE::txKick()
}
} else {
DPRINTF(EthernetSM, "this descriptor isn't done yet\n");
- if (txFifoAvail) {
+ if (!txFifo.full()) {
txState = txFragRead;
/*
@@ -1881,7 +2109,7 @@ NSGigE::txKick()
* is not enough room in the fifo, just whatever room
* is left in the fifo
*/
- txXferLen = min<uint32_t>(txDescCnt, txFifoAvail);
+ txXferLen = min<uint32_t>(txDescCnt, txFifo.avail());
txDmaAddr = txFragPtr & 0x3fffffff;
txDmaData = txPacketBufPtr;
@@ -1907,7 +2135,7 @@ NSGigE::txKick()
txPacketBufPtr += txXferLen;
txFragPtr += txXferLen;
txDescCnt -= txXferLen;
- txFifoAvail -= txXferLen;
+ txFifo.reserve(txXferLen);
txState = txFifoBlock;
break;
@@ -1976,45 +2204,35 @@ NSGigE::transferDone()
}
bool
-NSGigE::rxFilter(PacketPtr packet)
+NSGigE::rxFilter(const PacketPtr &packet)
{
+ EthPtr eth = packet;
bool drop = true;
string type;
- if (packet->IsUnicast()) {
- type = "unicast";
-
+ const EthAddr &dst = eth->dst();
+ if (dst.unicast()) {
// If we're accepting all unicast addresses
if (acceptUnicast)
drop = false;
// If we make a perfect match
- if (acceptPerfect &&
- memcmp(rom.perfectMatch, packet->data, EADDR_LEN) == 0)
+ if (acceptPerfect && dst == rom.perfectMatch)
drop = false;
- eth_header *eth = (eth_header *) packet->data;
- if ((acceptArp) && (eth->type == 0x608))
+ if (acceptArp && eth->type() == ETH_TYPE_ARP)
drop = false;
- } else if (packet->IsBroadcast()) {
- type = "broadcast";
-
+ } else if (dst.broadcast()) {
// if we're accepting broadcasts
if (acceptBroadcast)
drop = false;
- } else if (packet->IsMulticast()) {
- type = "multicast";
-
+ } else if (dst.multicast()) {
// if we're accepting all multicasts
if (acceptMulticast)
drop = false;
- } else {
- type = "unknown";
-
- // oh well, punt on this one
}
if (drop) {
@@ -2032,7 +2250,7 @@ NSGigE::recvPacket(PacketPtr packet)
rxPackets++;
DPRINTF(Ethernet, "Receiving packet from wire, rxFifoAvail=%d\n",
- maxRxFifoSize - rxFifoCnt);
+ rxFifo.avail());
if (!rxEnable) {
DPRINTF(Ethernet, "receive disabled...packet dropped\n");
@@ -2047,136 +2265,21 @@ NSGigE::recvPacket(PacketPtr packet)
return true;
}
- if ((rxFifoCnt + packet->length) >= maxRxFifoSize) {
+ if (rxFifo.avail() < packet->length) {
DPRINTF(Ethernet,
"packet will not fit in receive buffer...packet dropped\n");
+ droppedPackets++;
devIntrPost(ISR_RXORN);
return false;
}
- rxFifo.push_back(packet);
- rxFifoCnt += packet->length;
+ rxFifo.push(packet);
interface->recvDone();
rxKick();
return true;
}
-/**
- * does a udp checksum. if gen is true, then it generates it and puts
- * it in the right place else, it just checks what it calculates
- * against the value in the header in packet
- */
-bool
-NSGigE::udpChecksum(PacketPtr packet, bool gen)
-{
- ip_header *ip = packet->getIpHdr();
- udp_header *hdr = packet->getUdpHdr(ip);
-
- pseudo_header *pseudo = new pseudo_header;
-
- pseudo->src_ip_addr = ip->src_ip_addr;
- pseudo->dest_ip_addr = ip->dest_ip_addr;
- pseudo->protocol = ip->protocol;
- pseudo->len = hdr->len;
-
- uint16_t cksum = checksumCalc((uint16_t *) pseudo, (uint16_t *) hdr,
- (uint32_t) hdr->len);
-
- delete pseudo;
- if (gen)
- hdr->chksum = cksum;
- else
- if (cksum != 0)
- return false;
-
- return true;
-}
-
-bool
-NSGigE::tcpChecksum(PacketPtr packet, bool gen)
-{
- ip_header *ip = packet->getIpHdr();
- tcp_header *hdr = packet->getTcpHdr(ip);
-
- uint16_t cksum;
- pseudo_header *pseudo = new pseudo_header;
- if (!gen) {
- pseudo->src_ip_addr = ip->src_ip_addr;
- pseudo->dest_ip_addr = ip->dest_ip_addr;
- pseudo->protocol = reverseEnd16(ip->protocol);
- pseudo->len = reverseEnd16(reverseEnd16(ip->dgram_len) -
- (ip->vers_len & 0xf)*4);
-
- cksum = checksumCalc((uint16_t *) pseudo, (uint16_t *) hdr,
- (uint32_t) reverseEnd16(pseudo->len));
- } else {
- pseudo->src_ip_addr = 0;
- pseudo->dest_ip_addr = 0;
- pseudo->protocol = hdr->chksum;
- pseudo->len = 0;
- hdr->chksum = 0;
- cksum = checksumCalc((uint16_t *) pseudo, (uint16_t *) hdr,
- (uint32_t) (reverseEnd16(ip->dgram_len) -
- (ip->vers_len & 0xf)*4));
- }
-
- delete pseudo;
- if (gen)
- hdr->chksum = cksum;
- else
- if (cksum != 0)
- return false;
-
- return true;
-}
-
-bool
-NSGigE::ipChecksum(PacketPtr packet, bool gen)
-{
- ip_header *hdr = packet->getIpHdr();
-
- uint16_t cksum = checksumCalc(NULL, (uint16_t *) hdr,
- (hdr->vers_len & 0xf)*4);
-
- if (gen) {
- DPRINTF(EthernetCksum, "generated checksum: %#x\n", cksum);
- hdr->hdr_chksum = cksum;
- }
- else
- if (cksum != 0)
- return false;
-
- return true;
-}
-
-uint16_t
-NSGigE::checksumCalc(uint16_t *pseudo, uint16_t *buf, uint32_t len)
-{
- uint32_t sum = 0;
-
- uint16_t last_pad = 0;
- if (len & 1) {
- last_pad = buf[len/2] & 0xff;
- len--;
- sum += last_pad;
- }
-
- if (pseudo) {
- sum = pseudo[0] + pseudo[1] + pseudo[2] +
- pseudo[3] + pseudo[4] + pseudo[5];
- }
-
- for (int i=0; i < (len/2); ++i) {
- sum += buf[i];
- }
-
- while (sum >> 16)
- sum = (sum >> 16) + (sum & 0xffff);
-
- return ~sum;
-}
-
//=====================================================================
//
//
@@ -2234,30 +2337,15 @@ NSGigE::serialize(ostream &os)
SERIALIZE_SCALAR(regs.taner);
SERIALIZE_SCALAR(regs.tesr);
- SERIALIZE_ARRAY(rom.perfectMatch, EADDR_LEN);
+ SERIALIZE_ARRAY(rom.perfectMatch, ETH_ADDR_LEN);
SERIALIZE_SCALAR(ioEnable);
/*
* Serialize the data Fifos
*/
- int txNumPkts = txFifo.size();
- SERIALIZE_SCALAR(txNumPkts);
- int i = 0;
- pktiter_t end = txFifo.end();
- for (pktiter_t p = txFifo.begin(); p != end; ++p) {
- nameOut(os, csprintf("%s.txFifo%d", name(), i++));
- (*p)->serialize(os);
- }
-
- int rxNumPkts = rxFifo.size();
- SERIALIZE_SCALAR(rxNumPkts);
- i = 0;
- end = rxFifo.end();
- for (pktiter_t p = rxFifo.begin(); p != end; ++p) {
- nameOut(os, csprintf("%s.rxFifo%d", name(), i++));
- (*p)->serialize(os);
- }
+ rxFifo.serialize("rxFifo", os);
+ txFifo.serialize("txFifo", os);
/*
* Serialize the various helper variables
@@ -2265,8 +2353,7 @@ NSGigE::serialize(ostream &os)
bool txPacketExists = txPacket;
SERIALIZE_SCALAR(txPacketExists);
if (txPacketExists) {
- nameOut(os, csprintf("%s.txPacket", name()));
- txPacket->serialize(os);
+ txPacket->serialize("txPacket", os);
uint32_t txPktBufPtr = (uint32_t) (txPacketBufPtr - txPacket->data);
SERIALIZE_SCALAR(txPktBufPtr);
}
@@ -2274,8 +2361,7 @@ NSGigE::serialize(ostream &os)
bool rxPacketExists = rxPacket;
SERIALIZE_SCALAR(rxPacketExists);
if (rxPacketExists) {
- nameOut(os, csprintf("%s.rxPacket", name()));
- rxPacket->serialize(os);
+ rxPacket->serialize("rxPacket", os);
uint32_t rxPktBufPtr = (uint32_t) (rxPacketBufPtr - rxPacket->data);
SERIALIZE_SCALAR(rxPktBufPtr);
}
@@ -2302,7 +2388,6 @@ NSGigE::serialize(ostream &os)
SERIALIZE_SCALAR(txState);
SERIALIZE_SCALAR(txEnable);
SERIALIZE_SCALAR(CTDD);
- SERIALIZE_SCALAR(txFifoAvail);
SERIALIZE_SCALAR(txFragPtr);
SERIALIZE_SCALAR(txDescCnt);
int txDmaState = this->txDmaState;
@@ -2316,7 +2401,7 @@ NSGigE::serialize(ostream &os)
SERIALIZE_SCALAR(rxEnable);
SERIALIZE_SCALAR(CRDD);
SERIALIZE_SCALAR(rxPktBytes);
- SERIALIZE_SCALAR(rxFifoCnt);
+ SERIALIZE_SCALAR(rxFragPtr);
SERIALIZE_SCALAR(rxDescCnt);
int rxDmaState = this->rxDmaState;
SERIALIZE_SCALAR(rxDmaState);
@@ -2391,29 +2476,15 @@ NSGigE::unserialize(Checkpoint *cp, const std::string &section)
UNSERIALIZE_SCALAR(regs.taner);
UNSERIALIZE_SCALAR(regs.tesr);
- UNSERIALIZE_ARRAY(rom.perfectMatch, EADDR_LEN);
+ UNSERIALIZE_ARRAY(rom.perfectMatch, ETH_ADDR_LEN);
UNSERIALIZE_SCALAR(ioEnable);
/*
* unserialize the data fifos
*/
- int txNumPkts;
- UNSERIALIZE_SCALAR(txNumPkts);
- int i;
- for (i = 0; i < txNumPkts; ++i) {
- PacketPtr p = new EtherPacket;
- p->unserialize(cp, csprintf("%s.rxFifo%d", section, i));
- txFifo.push_back(p);
- }
-
- int rxNumPkts;
- UNSERIALIZE_SCALAR(rxNumPkts);
- for (i = 0; i < rxNumPkts; ++i) {
- PacketPtr p = new EtherPacket;
- p->unserialize(cp, csprintf("%s.rxFifo%d", section, i));
- rxFifo.push_back(p);
- }
+ rxFifo.unserialize("rxFifo", cp, section);
+ txFifo.unserialize("txFifo", cp, section);
/*
* unserialize the various helper variables
@@ -2421,8 +2492,8 @@ NSGigE::unserialize(Checkpoint *cp, const std::string &section)
bool txPacketExists;
UNSERIALIZE_SCALAR(txPacketExists);
if (txPacketExists) {
- txPacket = new EtherPacket;
- txPacket->unserialize(cp, csprintf("%s.txPacket", section));
+ txPacket = new PacketData(16384);
+ txPacket->unserialize("txPacket", cp, section);
uint32_t txPktBufPtr;
UNSERIALIZE_SCALAR(txPktBufPtr);
txPacketBufPtr = (uint8_t *) txPacket->data + txPktBufPtr;
@@ -2433,8 +2504,8 @@ NSGigE::unserialize(Checkpoint *cp, const std::string &section)
UNSERIALIZE_SCALAR(rxPacketExists);
rxPacket = 0;
if (rxPacketExists) {
- rxPacket = new EtherPacket;
- rxPacket->unserialize(cp, csprintf("%s.rxPacket", section));
+ rxPacket = new PacketData(16384);
+ rxPacket->unserialize("rxPacket", cp, section);
uint32_t rxPktBufPtr;
UNSERIALIZE_SCALAR(rxPktBufPtr);
rxPacketBufPtr = (uint8_t *) rxPacket->data + rxPktBufPtr;
@@ -2464,7 +2535,6 @@ NSGigE::unserialize(Checkpoint *cp, const std::string &section)
this->txState = (TxState) txState;
UNSERIALIZE_SCALAR(txEnable);
UNSERIALIZE_SCALAR(CTDD);
- UNSERIALIZE_SCALAR(txFifoAvail);
UNSERIALIZE_SCALAR(txFragPtr);
UNSERIALIZE_SCALAR(txDescCnt);
int txDmaState;
@@ -2480,7 +2550,7 @@ NSGigE::unserialize(Checkpoint *cp, const std::string &section)
UNSERIALIZE_SCALAR(rxEnable);
UNSERIALIZE_SCALAR(CRDD);
UNSERIALIZE_SCALAR(rxPktBytes);
- UNSERIALIZE_SCALAR(rxFifoCnt);
+ UNSERIALIZE_SCALAR(rxFragPtr);
UNSERIALIZE_SCALAR(rxDescCnt);
int rxDmaState;
UNSERIALIZE_SCALAR(rxDmaState);
@@ -2522,8 +2592,8 @@ NSGigE::unserialize(Checkpoint *cp, const std::string &section)
* re-add addrRanges to bus bridges
*/
if (pioInterface) {
- pioInterface->addAddrRange(BARAddrs[0], BARAddrs[0] + BARSize[0] - 1);
- pioInterface->addAddrRange(BARAddrs[1], BARAddrs[1] + BARSize[1] - 1);
+ pioInterface->addAddrRange(RangeSize(BARAddrs[0], BARSize[0]));
+ pioInterface->addAddrRange(RangeSize(BARAddrs[1], BARSize[1]));
}
}
@@ -2534,28 +2604,6 @@ NSGigE::cacheAccess(MemReqPtr &req)
req->paddr, req->paddr - addr);
return curTick + pioLatency;
}
-//=====================================================================
-
-
-//********** helper functions******************************************
-
-uint16_t reverseEnd16(uint16_t num)
-{
- uint16_t reverse = (num & 0xff)<<8;
- reverse += ((num & 0xff00) >> 8);
- return reverse;
-}
-
-uint32_t reverseEnd32(uint32_t num)
-{
- uint32_t reverse = (reverseEnd16(num & 0xffff)) << 16;
- reverse += reverseEnd16((uint16_t) ((num & 0xffff0000) >> 8));
- return reverse;
-}
-
-
-
-//=====================================================================
BEGIN_DECLARE_SIM_OBJECT_PARAMS(NSGigEInt)
@@ -2591,7 +2639,6 @@ BEGIN_DECLARE_SIM_OBJECT_PARAMS(NSGigE)
Param<Tick> tx_delay;
Param<Tick> rx_delay;
- SimObjectParam<IntrControl *> intr_ctrl;
Param<Tick> intr_delay;
SimObjectParam<MemoryController *> mmu;
SimObjectParam<PhysicalMemory *> physmem;
@@ -2609,7 +2656,7 @@ BEGIN_DECLARE_SIM_OBJECT_PARAMS(NSGigE)
Param<Tick> dma_write_factor;
SimObjectParam<PciConfigAll *> configspace;
SimObjectParam<PciConfigData *> configdata;
- SimObjectParam<Tsunami *> tsunami;
+ SimObjectParam<Platform *> platform;
Param<uint32_t> pci_bus;
Param<uint32_t> pci_dev;
Param<uint32_t> pci_func;
@@ -2622,7 +2669,6 @@ BEGIN_INIT_SIM_OBJECT_PARAMS(NSGigE)
INIT_PARAM_DFLT(tx_delay, "Transmit Delay", 1000),
INIT_PARAM_DFLT(rx_delay, "Receive Delay", 1000),
- INIT_PARAM(intr_ctrl, "Interrupt Controller"),
INIT_PARAM_DFLT(intr_delay, "Interrupt Delay in microseconds", 0),
INIT_PARAM(mmu, "Memory Controller"),
INIT_PARAM(physmem, "Physical Memory"),
@@ -2641,7 +2687,7 @@ BEGIN_INIT_SIM_OBJECT_PARAMS(NSGigE)
INIT_PARAM_DFLT(dma_write_factor, "multiplier for dma writes", 0),
INIT_PARAM(configspace, "PCI Configspace"),
INIT_PARAM(configdata, "PCI Config data"),
- INIT_PARAM(tsunami, "Tsunami"),
+ INIT_PARAM(platform, "Platform"),
INIT_PARAM(pci_bus, "PCI bus"),
INIT_PARAM(pci_dev, "PCI device number"),
INIT_PARAM(pci_func, "PCI function code"),
@@ -2653,17 +2699,36 @@ END_INIT_SIM_OBJECT_PARAMS(NSGigE)
CREATE_SIM_OBJECT(NSGigE)
{
- int eaddr[6];
- sscanf(((string)hardware_address).c_str(), "%x:%x:%x:%x:%x:%x",
- &eaddr[0], &eaddr[1], &eaddr[2], &eaddr[3], &eaddr[4], &eaddr[5]);
-
- return new NSGigE(getInstanceName(), intr_ctrl, intr_delay,
- physmem, tx_delay, rx_delay, mmu, hier, header_bus,
- payload_bus, pio_latency, dma_desc_free, dma_data_free,
- dma_read_delay, dma_write_delay, dma_read_factor,
- dma_write_factor, configspace, configdata,
- tsunami, pci_bus, pci_dev, pci_func, rx_filter, eaddr,
- tx_fifo_size, rx_fifo_size);
+ NSGigE::Params *params = new NSGigE::Params;
+
+ params->name = getInstanceName();
+ params->mmu = mmu;
+ params->configSpace = configspace;
+ params->configData = configdata;
+ params->plat = platform;
+ params->busNum = pci_bus;
+ params->deviceNum = pci_dev;
+ params->functionNum = pci_func;
+
+ params->intr_delay = intr_delay;
+ params->pmem = physmem;
+ params->tx_delay = tx_delay;
+ params->rx_delay = rx_delay;
+ params->hier = hier;
+ params->header_bus = header_bus;
+ params->payload_bus = payload_bus;
+ params->pio_latency = pio_latency;
+ params->dma_desc_free = dma_desc_free;
+ params->dma_data_free = dma_data_free;
+ params->dma_read_delay = dma_read_delay;
+ params->dma_write_delay = dma_write_delay;
+ params->dma_read_factor = dma_read_factor;
+ params->dma_write_factor = dma_write_factor;
+ params->rx_filter = rx_filter;
+ params->eaddr = hardware_address;
+ params->tx_fifo_size = tx_fifo_size;
+ params->rx_fifo_size = rx_fifo_size;
+ return new NSGigE(params);
}
REGISTER_SIM_OBJECT("NSGigE", NSGigE)
diff --git a/dev/ns_gige.hh b/dev/ns_gige.hh
index 82f640db1..8d6016126 100644
--- a/dev/ns_gige.hh
+++ b/dev/ns_gige.hh
@@ -31,22 +31,20 @@
* DP83820 ethernet controller
*/
-#ifndef __NS_GIGE_HH__
-#define __NS_GIGE_HH__
+#ifndef __DEV_NS_GIGE_HH__
+#define __DEV_NS_GIGE_HH__
+#include "base/inet.hh"
#include "base/statistics.hh"
#include "dev/etherint.hh"
#include "dev/etherpkt.hh"
#include "dev/io_device.hh"
#include "dev/ns_gige_reg.h"
#include "dev/pcidev.hh"
-#include "dev/tsunami.hh"
+#include "dev/pktfifo.hh"
#include "mem/bus/bus.hh"
#include "sim/eventq.hh"
-/** length of ethernet address in bytes */
-#define EADDR_LEN 6
-
/**
* Ethernet device registers
*/
@@ -90,7 +88,7 @@ struct dp_rom {
* for perfect match memory.
* the linux driver doesn't use any other ROM
*/
- uint8_t perfectMatch[EADDR_LEN];
+ uint8_t perfectMatch[ETH_ADDR_LEN];
};
class IntrControl;
@@ -141,10 +139,6 @@ class NSGigE : public PciDev
};
private:
- /** pointer to the chipset */
- Tsunami *tsunami;
-
- private:
Addr addr;
static const Addr size = sizeof(dp_regs);
@@ -165,10 +159,8 @@ class NSGigE : public PciDev
/*** BASIC STRUCTURES FOR TX/RX ***/
/* Data FIFOs */
- pktbuf_t txFifo;
- uint32_t maxTxFifoSize;
- pktbuf_t rxFifo;
- uint32_t maxRxFifoSize;
+ PacketFifo txFifo;
+ PacketFifo rxFifo;
/** various helper vars */
PacketPtr txPacket;
@@ -190,8 +182,6 @@ class NSGigE : public PciDev
/** Current Transmit Descriptor Done */
bool CTDD;
- /** current amt of free space in txDataFifo in bytes */
- uint32_t txFifoAvail;
/** halt the tx state machine after next packet */
bool txHalt;
/** ptr to the next byte in the current fragment */
@@ -208,8 +198,6 @@ class NSGigE : public PciDev
bool CRDD;
/** num of bytes in the current packet being drained from rxDataFifo */
uint32_t rxPktBytes;
- /** number of bytes in the rxFifo */
- uint32_t rxFifoCnt;
/** halt the rx state machine after current packet */
bool rxHalt;
/** ptr to the next byte in current fragment */
@@ -302,7 +290,7 @@ class NSGigE : public PciDev
* receive address filter
*/
bool rxFilterEnable;
- bool rxFilter(PacketPtr packet);
+ bool rxFilter(const PacketPtr &packet);
bool acceptBroadcast;
bool acceptMulticast;
bool acceptUnicast;
@@ -329,28 +317,34 @@ class NSGigE : public PciDev
typedef EventWrapper<NSGigE, &NSGigE::cpuInterrupt> IntrEvent;
friend class IntrEvent;
IntrEvent *intrEvent;
-
- /**
- * Hardware checksum support
- */
- bool udpChecksum(PacketPtr packet, bool gen);
- bool tcpChecksum(PacketPtr packet, bool gen);
- bool ipChecksum(PacketPtr packet, bool gen);
- uint16_t checksumCalc(uint16_t *pseudo, uint16_t *buf, uint32_t len);
-
NSGigEInt *interface;
public:
- NSGigE(const std::string &name, IntrControl *i, Tick intr_delay,
- PhysicalMemory *pmem, Tick tx_delay, Tick rx_delay,
- MemoryController *mmu, HierParams *hier, Bus *header_bus,
- Bus *payload_bus, Tick pio_latency, bool dma_desc_free,
- bool dma_data_free, Tick dma_read_delay, Tick dma_write_delay,
- Tick dma_read_factor, Tick dma_write_factor, PciConfigAll *cf,
- PciConfigData *cd, Tsunami *t, uint32_t bus, uint32_t dev,
- uint32_t func, bool rx_filter, const int eaddr[6],
- uint32_t tx_fifo_size, uint32_t rx_fifo_size);
+ struct Params : public PciDev::Params
+ {
+ PhysicalMemory *pmem;
+ HierParams *hier;
+ Bus *header_bus;
+ Bus *payload_bus;
+ Tick intr_delay;
+ Tick tx_delay;
+ Tick rx_delay;
+ Tick pio_latency;
+ bool dma_desc_free;
+ bool dma_data_free;
+ Tick dma_read_delay;
+ Tick dma_write_delay;
+ Tick dma_read_factor;
+ Tick dma_write_factor;
+ bool rx_filter;
+ Net::EthAddr eaddr;
+ uint32_t tx_fifo_size;
+ uint32_t rx_fifo_size;
+ };
+
+ NSGigE(Params *params);
~NSGigE();
+ const Params *params() const { return (const Params *)_params; }
virtual void WriteConfig(int offset, int size, uint32_t data);
virtual void ReadConfig(int offset, int size, uint8_t *data);
@@ -377,10 +371,12 @@ class NSGigE : public PciDev
Stats::Scalar<> rxBytes;
Stats::Scalar<> txPackets;
Stats::Scalar<> rxPackets;
- Stats::Scalar<> txIPChecksums;
- Stats::Scalar<> rxIPChecksums;
- Stats::Scalar<> txTCPChecksums;
- Stats::Scalar<> rxTCPChecksums;
+ Stats::Scalar<> txIpChecksums;
+ Stats::Scalar<> rxIpChecksums;
+ Stats::Scalar<> txTcpChecksums;
+ Stats::Scalar<> rxTcpChecksums;
+ Stats::Scalar<> txUdpChecksums;
+ Stats::Scalar<> rxUdpChecksums;
Stats::Scalar<> descDmaReads;
Stats::Scalar<> descDmaWrites;
Stats::Scalar<> descDmaRdBytes;
@@ -389,6 +385,33 @@ class NSGigE : public PciDev
Stats::Formula rxBandwidth;
Stats::Formula txPacketRate;
Stats::Formula rxPacketRate;
+ Stats::Scalar<> postedSwi;
+ Stats::Formula coalescedSwi;
+ Stats::Scalar<> totalSwi;
+ Stats::Scalar<> postedRxIdle;
+ Stats::Formula coalescedRxIdle;
+ Stats::Scalar<> totalRxIdle;
+ Stats::Scalar<> postedRxOk;
+ Stats::Formula coalescedRxOk;
+ Stats::Scalar<> totalRxOk;
+ Stats::Scalar<> postedRxDesc;
+ Stats::Formula coalescedRxDesc;
+ Stats::Scalar<> totalRxDesc;
+ Stats::Scalar<> postedTxOk;
+ Stats::Formula coalescedTxOk;
+ Stats::Scalar<> totalTxOk;
+ Stats::Scalar<> postedTxIdle;
+ Stats::Formula coalescedTxIdle;
+ Stats::Scalar<> totalTxIdle;
+ Stats::Scalar<> postedTxDesc;
+ Stats::Formula coalescedTxDesc;
+ Stats::Scalar<> totalTxDesc;
+ Stats::Scalar<> postedRxOrn;
+ Stats::Formula coalescedRxOrn;
+ Stats::Scalar<> totalRxOrn;
+ Stats::Formula coalescedTotal;
+ Stats::Scalar<> postedInterrupts;
+ Stats::Scalar<> droppedPackets;
public:
Tick cacheAccess(MemReqPtr &req);
@@ -406,8 +429,8 @@ 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(PacketPtr pkt) { return dev->recvPacket(pkt); }
virtual void sendDone() { dev->transferDone(); }
};
-#endif // __NS_GIGE_HH__
+#endif // __DEV_NS_GIGE_HH__
diff --git a/dev/pciconfigall.cc b/dev/pciconfigall.cc
index 740a9b4ac..609763e92 100644
--- a/dev/pciconfigall.cc
+++ b/dev/pciconfigall.cc
@@ -33,10 +33,12 @@
#include <deque>
#include <string>
#include <vector>
+#include <bitset>
#include "base/trace.hh"
#include "dev/pciconfigall.hh"
#include "dev/pcidev.hh"
+#include "dev/pcireg.h"
#include "mem/bus/bus.hh"
#include "mem/bus/pio_interface.hh"
#include "mem/bus/pio_interface_impl.hh"
@@ -50,12 +52,12 @@ PciConfigAll::PciConfigAll(const string &name, Addr a, MemoryController *mmu,
HierParams *hier, Bus *bus, Tick pio_latency)
: PioDevice(name), addr(a)
{
- mmu->add_child(this, Range<Addr>(addr, addr + size));
+ mmu->add_child(this, RangeSize(addr, size));
if (bus) {
pioInterface = newPioInterface(name, hier, bus, this,
&PciConfigAll::cacheAccess);
- pioInterface->addAddrRange(addr, addr + size - 1);
+ pioInterface->addAddrRange(RangeSize(addr, size));
pioLatency = pio_latency * bus->clockRatio;
}
@@ -65,13 +67,40 @@ PciConfigAll::PciConfigAll(const string &name, Addr a, MemoryController *mmu,
devices[x][y] = NULL;
}
+// If two interrupts share the same line largely bad things will happen.
+// Since we don't track how many times an interrupt was set and correspondingly
+// cleared two devices on the same interrupt line and assert and deassert each
+// others interrupt "line". Interrupts will not work correctly.
+void
+PciConfigAll::startup()
+{
+ bitset<256> intLines;
+ PciDev *tempDev;
+ uint8_t intline;
+
+ for (int x = 0; x < MAX_PCI_DEV; x++) {
+ for (int y = 0; y < MAX_PCI_FUNC; y++) {
+ if (devices[x][y] != NULL) {
+ tempDev = devices[x][y];
+ intline = tempDev->interruptLine();
+ if (intLines.test(intline))
+ warn("Interrupt line %#X is used multiple times"
+ "(You probably want to fix this).\n", (uint32_t)intline);
+ else
+ intLines.set(intline);
+ } // devices != NULL
+ } // PCI_FUNC
+ } // PCI_DEV
+
+}
+
Fault
PciConfigAll::read(MemReqPtr &req, uint8_t *data)
{
DPRINTF(PciConfigAll, "read va=%#x size=%d\n",
req->vaddr, req->size);
- Addr daddr = (req->paddr - (addr & PA_IMPL_MASK));
+ Addr daddr = (req->paddr - (addr & EV5::PAddrImplMask));
int device = (daddr >> 11) & 0x1F;
int func = (daddr >> 8) & 0x7;
@@ -115,7 +144,7 @@ PciConfigAll::read(MemReqPtr &req, uint8_t *data)
Fault
PciConfigAll::write(MemReqPtr &req, const uint8_t *data)
{
- Addr daddr = (req->paddr - (addr & PA_IMPL_MASK));
+ Addr daddr = (req->paddr - (addr & EV5::PAddrImplMask));
int device = (daddr >> 11) & 0x1F;
int func = (daddr >> 8) & 0x7;
diff --git a/dev/pciconfigall.hh b/dev/pciconfigall.hh
index d6b37b9b1..9cf2cf972 100644
--- a/dev/pciconfigall.hh
+++ b/dev/pciconfigall.hh
@@ -116,6 +116,12 @@ class PciConfigAll : public PioDevice
virtual Fault write(MemReqPtr &req, const uint8_t *data);
/**
+ * Start up function to check if more than one person is using an interrupt line
+ * and print a warning if such a case exists
+ */
+ virtual void startup();
+
+ /**
* Serialize this object to the given output stream.
* @param os The stream to serialize to.
*/
@@ -134,6 +140,7 @@ class PciConfigAll : public PioDevice
* @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 7b13aac80..d156b6a02 100644
--- a/dev/pcidev.cc
+++ b/dev/pcidev.cc
@@ -50,36 +50,38 @@
using namespace std;
-PciDev::PciDev(const string &name, MemoryController *mmu, PciConfigAll *cf,
- PciConfigData *cd, uint32_t bus, uint32_t dev, uint32_t func)
- : DmaDevice(name), mmu(mmu), configSpace(cf), configData(cd), busNum(bus),
- deviceNum(dev), functionNum(func)
+PciDev::PciDev(Params *p)
+ : DmaDevice(p->name), _params(p), plat(p->plat), configData(p->configData)
{
// copy the config data from the PciConfigData object
- if (cd) {
- memcpy(config.data, cd->config.data, sizeof(config.data));
- memcpy(BARSize, cd->BARSize, sizeof(BARSize));
- memcpy(BARAddrs, cd->BARAddrs, sizeof(BARAddrs));
+ if (configData) {
+ memcpy(config.data, configData->config.data, sizeof(config.data));
+ memcpy(BARSize, configData->BARSize, sizeof(BARSize));
+ memcpy(BARAddrs, configData->BARAddrs, sizeof(BARAddrs));
} else
panic("NULL pointer to configuration data");
// Setup pointer in config space to point to this entry
- if (cf->deviceExists(dev,func))
- panic("Two PCI devices occuping same dev: %#x func: %#x", dev, func);
+ if (p->configSpace->deviceExists(p->deviceNum, p->functionNum))
+ panic("Two PCI devices occuping same dev: %#x func: %#x",
+ p->deviceNum, p->functionNum);
else
- cf->registerDevice(dev, func, this);
+ p->configSpace->registerDevice(p->deviceNum, p->functionNum, this);
}
void
PciDev::ReadConfig(int offset, int size, uint8_t *data)
{
+ if (offset >= PCI_DEVICE_SPECIFIC)
+ panic("Device specific PCI config space not implemented!\n");
+
switch(size) {
case sizeof(uint32_t):
memcpy((uint8_t*)data, config.data + offset, sizeof(uint32_t));
*(uint32_t*)data = htoa(*(uint32_t*)data);
DPRINTF(PCIDEV,
"read device: %#x function: %#x register: %#x %d bytes: data: %#x\n",
- deviceNum, functionNum, offset, size,
+ params()->deviceNum, params()->functionNum, offset, size,
*(uint32_t*)(config.data + offset));
break;
@@ -88,7 +90,7 @@ PciDev::ReadConfig(int offset, int size, uint8_t *data)
*(uint16_t*)data = htoa(*(uint16_t*)data);
DPRINTF(PCIDEV,
"read device: %#x function: %#x register: %#x %d bytes: data: %#x\n",
- deviceNum, functionNum, offset, size,
+ params()->deviceNum, params()->functionNum, offset, size,
*(uint16_t*)(config.data + offset));
break;
@@ -96,7 +98,7 @@ PciDev::ReadConfig(int offset, int size, uint8_t *data)
memcpy((uint8_t*)data, config.data + offset, sizeof(uint8_t));
DPRINTF(PCIDEV,
"read device: %#x function: %#x register: %#x %d bytes: data: %#x\n",
- deviceNum, functionNum, offset, size,
+ params()->deviceNum, params()->functionNum, offset, size,
(uint16_t)(*(uint8_t*)(config.data + offset)));
break;
@@ -108,6 +110,9 @@ PciDev::ReadConfig(int offset, int size, uint8_t *data)
void
PciDev::WriteConfig(int offset, int size, uint32_t data)
{
+ if (offset >= PCI_DEVICE_SPECIFIC)
+ panic("Device specific PCI config space not implemented!\n");
+
uint32_t barnum;
union {
@@ -119,7 +124,8 @@ PciDev::WriteConfig(int offset, int size, uint32_t data)
DPRINTF(PCIDEV,
"write device: %#x function: %#x reg: %#x size: %d data: %#x\n",
- deviceNum, functionNum, offset, size, word_value);
+ params()->deviceNum, params()->functionNum, offset, size,
+ word_value);
barnum = (offset - PCI0_BASE_ADDR0) >> 2;
@@ -129,7 +135,7 @@ PciDev::WriteConfig(int offset, int size, uint32_t data)
case PCI0_INTERRUPT_LINE:
case PCI_CACHE_LINE_SIZE:
case PCI_LATENCY_TIMER:
- *(uint8_t *)&config.data[offset] = byte_value;
+ *(uint8_t *)&config.data[offset] = htoa(byte_value);
break;
default:
@@ -142,7 +148,7 @@ PciDev::WriteConfig(int offset, int size, uint32_t data)
case PCI_COMMAND:
case PCI_STATUS:
case PCI_CACHE_LINE_SIZE:
- *(uint16_t *)&config.data[offset] = half_value;
+ *(uint16_t *)&config.data[offset] = htoa(half_value);
break;
default:
@@ -166,67 +172,63 @@ PciDev::WriteConfig(int offset, int size, uint32_t data)
// to size of memory it needs
if (word_value == 0xffffffff) {
// This is I/O Space, bottom two bits are read only
- if (config.data[offset] & 0x1) {
- *(uint32_t *)&config.data[offset] =
+ if (htoa(config.data[offset]) & 0x1) {
+ *(uint32_t *)&config.data[offset] = htoa(
~(BARSize[barnum] - 1) |
- (config.data[offset] & 0x3);
+ (htoa(config.data[offset]) & 0x3));
} else {
// This is memory space, bottom four bits are read only
- *(uint32_t *)&config.data[offset] =
+ *(uint32_t *)&config.data[offset] = htoa(
~(BARSize[barnum] - 1) |
- (config.data[offset] & 0xF);
+ (htoa(config.data[offset]) & 0xF));
}
} else {
+ MemoryController *mmu = params()->mmu;
+
// This is I/O Space, bottom two bits are read only
- if(config.data[offset] & 0x1) {
- *(uint32_t *)&config.data[offset] = (word_value & ~0x3) |
- (config.data[offset] & 0x3);
+ if(htoa(config.data[offset]) & 0x1) {
+ *(uint32_t *)&config.data[offset] =
+ htoa((word_value & ~0x3) |
+ (htoa(config.data[offset]) & 0x3));
if (word_value & ~0x1) {
Addr base_addr = (word_value & ~0x1) + TSUNAMI_PCI0_IO;
- Addr base_size = BARSize[barnum]-1;
+ Addr base_size = BARSize[barnum];
// It's never been set
if (BARAddrs[barnum] == 0)
mmu->add_child((FunctionalMemory *)this,
- Range<Addr>(base_addr,
- base_addr + base_size));
+ RangeSize(base_addr, base_size));
else
mmu->update_child((FunctionalMemory *)this,
- Range<Addr>(BARAddrs[barnum],
- BARAddrs[barnum] +
- base_size),
- Range<Addr>(base_addr,
- base_addr +
- base_size));
+ RangeSize(BARAddrs[barnum],
+ base_size),
+ RangeSize(base_addr, base_size));
BARAddrs[barnum] = base_addr;
}
} else {
// This is memory space, bottom four bits are read only
- *(uint32_t *)&config.data[offset] = (word_value & ~0xF) |
- (config.data[offset] & 0xF);
+ *(uint32_t *)&config.data[offset] =
+ htoa((word_value & ~0xF) |
+ (htoa(config.data[offset]) & 0xF));
if (word_value & ~0x3) {
Addr base_addr = (word_value & ~0x3) +
TSUNAMI_PCI0_MEMORY;
- Addr base_size = BARSize[barnum]-1;
+ Addr base_size = BARSize[barnum];
// It's never been set
if (BARAddrs[barnum] == 0)
mmu->add_child((FunctionalMemory *)this,
- Range<Addr>(base_addr,
- base_addr + base_size));
+ RangeSize(base_addr, base_size));
else
mmu->update_child((FunctionalMemory *)this,
- Range<Addr>(BARAddrs[barnum],
- BARAddrs[barnum] +
- base_size),
- Range<Addr>(base_addr,
- base_addr +
- base_size));
+ RangeSize(BARAddrs[barnum],
+ base_size),
+ RangeSize(base_addr, base_size));
BARAddrs[barnum] = base_addr;
}
@@ -238,14 +240,14 @@ PciDev::WriteConfig(int offset, int size, uint32_t data)
if (word_value == 0xfffffffe)
*(uint32_t *)&config.data[offset] = 0xffffffff;
else
- *(uint32_t *)&config.data[offset] = word_value;
+ *(uint32_t *)&config.data[offset] = htoa(word_value);
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
- *(uint16_t *)&config.data[offset] = half_value;
+ *(uint16_t *)&config.data[offset] = htoa(half_value);
break;
default:
@@ -273,10 +275,7 @@ PciDev::unserialize(Checkpoint *cp, const std::string &section)
// Add the MMU mappings for the BARs
for (int i=0; i < 6; i++) {
if (BARAddrs[i] != 0)
- mmu->add_child((FunctionalMemory *)this,
- Range<Addr>(BARAddrs[i],
- BARAddrs[i] +
- BARSize[i] - 1));
+ params()->mmu->add_child(this, RangeSize(BARAddrs[i], BARSize[i]));
}
}
diff --git a/dev/pcidev.hh b/dev/pcidev.hh
index c0fe47ac4..4b947b560 100644
--- a/dev/pcidev.hh
+++ b/dev/pcidev.hh
@@ -30,11 +30,12 @@
* Interface for devices using PCI configuration
*/
-#ifndef __PCI_DEV_HH__
-#define __PCI_DEV_HH__
+#ifndef __DEV_PCIDEV_HH__
+#define __DEV_PCIDEV_HH__
-#include "dev/pcireg.h"
#include "dev/io_device.hh"
+#include "dev/pcireg.h"
+#include "dev/platform.hh"
class PciConfigAll;
class MemoryController;
@@ -78,29 +79,43 @@ class PciConfigData : public SimObject
class PciDev : public DmaDevice
{
protected:
- MemoryController *mmu;
- /** A pointer to the configspace all object that calls
- * us when a read comes to this particular device/function.
- */
- PciConfigAll *configSpace;
+ struct Params;
+ Params *_params;
- /**
- * A pointer to the object that contains the first 64 bytes of
- * config space
- */
- PciConfigData *configData;
+ public:
+ struct 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.
+ */
+ PciConfigAll *configSpace;
+
+ /**
+ * A pointer to the object that contains the first 64 bytes of
+ * config space
+ */
+ PciConfigData *configData;
- /** The bus number we are on */
- uint32_t busNum;
+ /** The bus number we are on */
+ uint32_t busNum;
- /** The device number we have */
- uint32_t deviceNum;
+ /** The device number we have */
+ uint32_t deviceNum;
- /** The function number */
- uint32_t functionNum;
+ /** The function number */
+ uint32_t functionNum;
+ };
+ const Params *params() const { return _params; }
- /** The current config space. Unlike the PciConfigData this is updated
- * during simulation while continues to refelect what was in the config file.
+ protected:
+ /** The current config space. Unlike the PciConfigData this is
+ * updated during simulation while continues to refelect what was
+ * in the config file.
*/
PCIConfig config;
@@ -110,21 +125,33 @@ class PciDev : public DmaDevice
/** The current address mapping of the BARs */
Addr BARAddrs[6];
+ protected:
+ Platform *plat;
+ PciConfigData *configData;
+
+ public:
+ Addr pciToDma(Addr pciAddr) const
+ { return plat->pciToDma(pciAddr); }
+
+ void
+ intrPost()
+ { plat->postPciInt(configData->config.hdr.pci0.interruptLine); }
+
+ void
+ intrClear()
+ { plat->clearPciInt(configData->config.hdr.pci0.interruptLine); }
+
+ uint8_t
+ interruptLine()
+ { return configData->config.hdr.pci0.interruptLine; }
+
public:
/**
- * Constructor for PCI Dev. This function copies data from the config file
- * object PCIConfigData and registers the device with a PciConfigAll object.
- * @param name name of the object
- * @param mmu a pointer to the memory controller
- * @param cf a pointer to the config space object that this device need to
- * register with
- * @param cd A pointer to the config space values specified in the conig file
- * @param bus the bus this device is on
- * @param dev the device id of this device
- * @param func the function number of this device
+ * Constructor for PCI Dev. This function copies data from the
+ * config file object PCIConfigData and registers the device with
+ * a PciConfigAll object.
*/
- PciDev(const std::string &name, MemoryController *mmu, PciConfigAll *cf,
- PciConfigData *cd, uint32_t bus, uint32_t dev, uint32_t func);
+ PciDev(Params *params);
virtual Fault read(MemReqPtr &req, uint8_t *data) {
return No_Fault;
@@ -168,4 +195,4 @@ class PciDev : public DmaDevice
virtual void unserialize(Checkpoint *cp, const std::string &section);
};
-#endif // __PCI_DEV_HH__
+#endif // __DEV_PCIDEV_HH__
diff --git a/dev/pktfifo.cc b/dev/pktfifo.cc
new file mode 100644
index 000000000..ae82123cf
--- /dev/null
+++ b/dev/pktfifo.cc
@@ -0,0 +1,70 @@
+/*
+ * Copyright (c) 2002-2004 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 "base/misc.hh"
+#include "dev/pktfifo.hh"
+
+using namespace std;
+
+void
+PacketFifo::serialize(const string &base, ostream &os)
+{
+ paramOut(os, base + ".size", _size);
+ paramOut(os, base + ".maxsize", _maxsize);
+ paramOut(os, base + ".reserved", _reserved);
+ paramOut(os, base + ".packets", fifo.size());
+
+ int i = 0;
+ std::list<PacketPtr>::iterator p = fifo.begin();
+ std::list<PacketPtr>::iterator end = fifo.end();
+ while (p != end) {
+ (*p)->serialize(csprintf("%s.packet%d", base, i), os);
+ ++p;
+ ++i;
+ }
+}
+
+void
+PacketFifo::unserialize(const string &base, Checkpoint *cp,
+ const string &section)
+{
+ paramIn(cp, section, base + ".size", _size);
+ paramIn(cp, section, base + ".maxsize", _maxsize);
+ paramIn(cp, section, base + ".reserved", _reserved);
+ int fifosize;
+ paramIn(cp, section, base + ".packets", fifosize);
+
+ fifo.clear();
+ fifo.resize(fifosize);
+
+ for (int i = 0; i < fifosize; ++i) {
+ PacketPtr p = new PacketData(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
new file mode 100644
index 000000000..0c237949c
--- /dev/null
+++ b/dev/pktfifo.hh
@@ -0,0 +1,107 @@
+/*
+ * Copyright (c) 2002-2004 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 __DEV_PKTFIFO_HH__
+#define __DEV_PKTFIFO_HH__
+
+#include <iosfwd>
+#include <list>
+#include <string>
+
+#include "dev/etherpkt.hh"
+#include "sim/serialize.hh"
+
+class Checkpoint;
+class PacketFifo
+{
+ protected:
+ std::list<PacketPtr> fifo;
+ int _maxsize;
+ int _size;
+ int _reserved;
+
+ public:
+ explicit PacketFifo(int max) : _maxsize(max), _size(0), _reserved(0) {}
+ virtual ~PacketFifo() {}
+
+ int packets() const { return fifo.size(); }
+ int maxsize() const { return _maxsize; }
+ int size() const { return _size; }
+ int reserved() const { return _reserved; }
+ int avail() const { return _maxsize - _size - _reserved; }
+ bool empty() const { return size() <= 0; }
+ bool full() const { return avail() <= 0; }
+
+ int reserve(int len = 0)
+ {
+ _reserved += len;
+ assert(avail() >= 0);
+ return _reserved;
+ }
+
+ bool push(PacketPtr ptr)
+ {
+ assert(_reserved <= ptr->length);
+ if (avail() < ptr->length - _reserved)
+ return false;
+
+ _size += ptr->length;
+ fifo.push_back(ptr);
+ _reserved = 0;
+ return true;
+ }
+
+ PacketPtr front() { return fifo.front(); }
+
+ void pop()
+ {
+ if (empty())
+ return;
+
+ _size -= fifo.front()->length;
+ fifo.front() = NULL;
+ fifo.pop_front();
+ }
+
+ void clear()
+ {
+ fifo.clear();
+ _size = 0;
+ _reserved = 0;
+ }
+
+/**
+ * Serialization stuff
+ */
+ public:
+ void serialize(const std::string &base, std::ostream &os);
+ void unserialize(const std::string &base,
+ Checkpoint *cp, const std::string &section);
+};
+
+#endif // __DEV_PKTFIFO_HH__
diff --git a/dev/platform.cc b/dev/platform.cc
index 8515d543a..cf012352b 100644
--- a/dev/platform.cc
+++ b/dev/platform.cc
@@ -32,5 +32,23 @@
using namespace std;
+void
+Platform::postPciInt(int line)
+{
+ panic("No PCI interrupt support in platform.");
+}
+
+void
+Platform::clearPciInt(int line)
+{
+ panic("No PCI interrupt support in platform.");
+}
+
+Addr
+Platform::pciToDma(Addr pciAddr) const
+{
+ panic("No PCI dma support in platform.");
+}
+
DEFINE_SIM_OBJECT_CLASS_NAME("Platform", Platform)
diff --git a/dev/platform.hh b/dev/platform.hh
index 7920480bc..717e49411 100644
--- a/dev/platform.hh
+++ b/dev/platform.hh
@@ -35,6 +35,7 @@
#define __PLATFORM_HH_
#include "sim/sim_object.hh"
+#include "targetarch/isa_traits.hh"
class PciConfigAll;
class IntrControl;
@@ -65,6 +66,9 @@ class Platform : public SimObject
virtual void postConsoleInt() = 0;
virtual void clearConsoleInt() = 0;
virtual Tick intrFrequency() = 0;
+ virtual void postPciInt(int line);
+ virtual void clearPciInt(int line);
+ virtual Addr pciToDma(Addr pciAddr) const;
};
#endif // __PLATFORM_HH_
diff --git a/dev/simconsole.cc b/dev/simconsole.cc
index a15057402..d8d890e15 100644
--- a/dev/simconsole.cc
+++ b/dev/simconsole.cc
@@ -45,12 +45,11 @@
#include "base/misc.hh"
#include "base/socket.hh"
#include "base/trace.hh"
+#include "dev/platform.hh"
#include "dev/simconsole.hh"
+#include "dev/uart.hh"
#include "mem/functional_mem/memory_control.hh"
#include "sim/builder.hh"
-#include "targetarch/ev5.hh"
-#include "dev/uart.hh"
-#include "dev/platform.hh"
using namespace std;
@@ -72,27 +71,22 @@ SimConsole::Event::process(int revent)
cons->detach();
}
-SimConsole::SimConsole(const string &name, const string &file, int num)
+SimConsole::SimConsole(const string &name, std::ostream *os, int num)
: SimObject(name), event(NULL), number(num), in_fd(-1), out_fd(-1),
- listener(NULL), txbuf(16384), rxbuf(16384), outfile(NULL)
+ listener(NULL), txbuf(16384), rxbuf(16384), outfile(os)
#if TRACING_ON == 1
, linebuf(16384)
#endif
{
- if (!file.empty())
- outfile = new ofstream(file.c_str());
-
if (outfile)
outfile->setf(ios::unitbuf);
-
}
SimConsole::~SimConsole()
{
close();
-
if (outfile)
- delete outfile;
+ closeOutputStream(outfile);
}
void
@@ -311,7 +305,7 @@ BEGIN_INIT_SIM_OBJECT_PARAMS(SimConsole)
INIT_PARAM(listener, "console listener"),
INIT_PARAM(intr_control, "interrupt controller"),
- INIT_PARAM_DFLT(output, "file to dump output to", ""),
+ INIT_PARAM(output, "file to dump output to"),
INIT_PARAM_DFLT(append_name, "append name() to filename", true),
INIT_PARAM_DFLT(number, "console number", 0)
@@ -319,18 +313,18 @@ END_INIT_SIM_OBJECT_PARAMS(SimConsole)
CREATE_SIM_OBJECT(SimConsole)
{
- string filename = output;
- if (filename.empty()) {
- if (!outputDirectory.empty())
- filename = outputDirectory + getInstanceName();
+ string filename;
+
+ if (!output.isValid()) {
+ filename = getInstanceName();
+ } else if (append_name) {
+ filename = (string)output + "." + getInstanceName();
} else {
- if (append_name)
- filename += "." + getInstanceName();
- if (!outputDirectory.empty())
- filename = outputDirectory + filename;
+ filename = output;
}
- SimConsole *console = new SimConsole(getInstanceName(), filename, number);
+ SimConsole *console = new SimConsole(getInstanceName(),
+ makeOutputStream(filename), number);
((ConsoleListener *)listener)->add(console);
return console;
diff --git a/dev/simconsole.hh b/dev/simconsole.hh
index 138e2e36a..c5a281834 100644
--- a/dev/simconsole.hh
+++ b/dev/simconsole.hh
@@ -70,7 +70,7 @@ class SimConsole : public SimObject
ConsoleListener *listener;
public:
- SimConsole(const std::string &name, const std::string &file, int num);
+ SimConsole(const std::string &name, std::ostream *os, int num);
~SimConsole();
protected:
diff --git a/dev/sinic.cc b/dev/sinic.cc
new file mode 100644
index 000000000..56782b589
--- /dev/null
+++ b/dev/sinic.cc
@@ -0,0 +1,1433 @@
+/*
+ * Copyright (c) 2004 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 <cstdio>
+#include <deque>
+#include <string>
+
+#include "base/inet.hh"
+#include "cpu/exec_context.hh"
+#include "cpu/intr_control.hh"
+#include "dev/dma.hh"
+#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_mem/memory_control.hh"
+#include "mem/functional_mem/physical_memory.hh"
+#include "sim/builder.hh"
+#include "sim/debug.hh"
+#include "sim/eventq.hh"
+#include "sim/host.hh"
+#include "sim/stats.hh"
+#include "targetarch/vtophys.hh"
+
+using namespace Net;
+
+namespace Sinic {
+
+const char *RxStateStrings[] =
+{
+ "rxIdle",
+ "rxFifoBlock",
+ "rxBeginCopy",
+ "rxCopy",
+ "rxCopyDone"
+};
+
+const char *TxStateStrings[] =
+{
+ "txIdle",
+ "txFifoBlock",
+ "txBeginCopy",
+ "txCopy",
+ "txCopyDone"
+};
+
+
+///////////////////////////////////////////////////////////////////////
+//
+// Sinic PCI Device
+//
+Base::Base(Params *p)
+ : PciDev(p), rxEnable(false), txEnable(false),
+ intrDelay(US2Ticks(p->intr_delay)),
+ intrTick(0), cpuIntrEnable(false), cpuPendingIntr(false), intrEvent(0),
+ interface(NULL)
+{
+}
+
+Device::Device(Params *p)
+ : Base(p), plat(p->plat), physmem(p->physmem),
+ 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),
+ dmaWriteDelay(p->dma_write_delay), dmaWriteFactor(p->dma_write_factor)
+{
+ reset();
+
+ if (p->header_bus) {
+ pioInterface = newPioInterface(p->name, p->hier, p->header_bus, this,
+ &Device::cacheAccess);
+
+ pioLatency = p->pio_latency * p->header_bus->clockRatio;
+
+ if (p->payload_bus)
+ dmaInterface = new DMAInterface<Bus>(p->name + ".dma",
+ p->header_bus, p->payload_bus,
+ 1);
+ else
+ dmaInterface = new DMAInterface<Bus>(p->name + ".dma",
+ p->header_bus, p->header_bus,
+ 1);
+ } else if (p->payload_bus) {
+ pioInterface = newPioInterface(p->name, p->hier, p->payload_bus, this,
+ &Device::cacheAccess);
+
+ pioLatency = p->pio_latency * p->payload_bus->clockRatio;
+
+ dmaInterface = new DMAInterface<Bus>(p->name + ".dma", p->payload_bus,
+ p->payload_bus, 1);
+ }
+}
+
+Device::~Device()
+{}
+
+void
+Device::regStats()
+{
+ rxBytes
+ .name(name() + ".rxBytes")
+ .desc("Bytes Received")
+ .prereq(rxBytes)
+ ;
+
+ rxBandwidth
+ .name(name() + ".rxBandwidth")
+ .desc("Receive Bandwidth (bits/s)")
+ .precision(0)
+ .prereq(rxBytes)
+ ;
+
+ rxPackets
+ .name(name() + ".rxPackets")
+ .desc("Number of Packets Received")
+ .prereq(rxBytes)
+ ;
+
+ rxPacketRate
+ .name(name() + ".rxPPS")
+ .desc("Packet Reception Rate (packets/s)")
+ .precision(0)
+ .prereq(rxBytes)
+ ;
+
+ rxIpPackets
+ .name(name() + ".rxIpPackets")
+ .desc("Number of IP Packets Received")
+ .prereq(rxBytes)
+ ;
+
+ rxTcpPackets
+ .name(name() + ".rxTcpPackets")
+ .desc("Number of Packets Received")
+ .prereq(rxBytes)
+ ;
+
+ rxUdpPackets
+ .name(name() + ".rxUdpPackets")
+ .desc("Number of UDP Packets Received")
+ .prereq(rxBytes)
+ ;
+
+ rxIpChecksums
+ .name(name() + ".rxIpChecksums")
+ .desc("Number of rx IP Checksums done by device")
+ .precision(0)
+ .prereq(rxBytes)
+ ;
+
+ rxTcpChecksums
+ .name(name() + ".rxTcpChecksums")
+ .desc("Number of rx TCP Checksums done by device")
+ .precision(0)
+ .prereq(rxBytes)
+ ;
+
+ rxUdpChecksums
+ .name(name() + ".rxUdpChecksums")
+ .desc("Number of rx UDP Checksums done by device")
+ .precision(0)
+ .prereq(rxBytes)
+ ;
+
+ txBytes
+ .name(name() + ".txBytes")
+ .desc("Bytes Transmitted")
+ .prereq(txBytes)
+ ;
+
+ txBandwidth
+ .name(name() + ".txBandwidth")
+ .desc("Transmit Bandwidth (bits/s)")
+ .precision(0)
+ .prereq(txBytes)
+ ;
+
+ txPackets
+ .name(name() + ".txPackets")
+ .desc("Number of Packets Transmitted")
+ .prereq(txBytes)
+ ;
+
+ txPacketRate
+ .name(name() + ".txPPS")
+ .desc("Packet Tranmission Rate (packets/s)")
+ .precision(0)
+ .prereq(txBytes)
+ ;
+
+ txIpPackets
+ .name(name() + ".txIpPackets")
+ .desc("Number of IP Packets Transmitted")
+ .prereq(txBytes)
+ ;
+
+ txTcpPackets
+ .name(name() + ".txTcpPackets")
+ .desc("Number of TCP Packets Transmitted")
+ .prereq(txBytes)
+ ;
+
+ txUdpPackets
+ .name(name() + ".txUdpPackets")
+ .desc("Number of Packets Transmitted")
+ .prereq(txBytes)
+ ;
+
+ txIpChecksums
+ .name(name() + ".txIpChecksums")
+ .desc("Number of tx IP Checksums done by device")
+ .precision(0)
+ .prereq(txBytes)
+ ;
+
+ txTcpChecksums
+ .name(name() + ".txTcpChecksums")
+ .desc("Number of tx TCP Checksums done by device")
+ .precision(0)
+ .prereq(txBytes)
+ ;
+
+ txUdpChecksums
+ .name(name() + ".txUdpChecksums")
+ .desc("Number of tx UDP Checksums done by device")
+ .precision(0)
+ .prereq(txBytes)
+ ;
+
+ txBandwidth = txBytes * Stats::constant(8) / simSeconds;
+ rxBandwidth = rxBytes * Stats::constant(8) / simSeconds;
+ txPacketRate = txPackets / simSeconds;
+ rxPacketRate = rxPackets / simSeconds;
+}
+
+/**
+ * This is to write to the PCI general configuration registers
+ */
+void
+Device::WriteConfig(int offset, int size, uint32_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);
+ }
+}
+
+/**
+ * This reads the device registers, which are detailed in the NS83820
+ * spec sheet
+ */
+Fault
+Device::read(MemReqPtr &req, uint8_t *data)
+{
+ assert(config.hdr.command & PCI_CMD_MSE);
+
+ //The mask is to give you only the offset into the device register file
+ Addr daddr = req->paddr & 0xfff;
+
+ if (Regs::regSize(daddr) == 0)
+ panic("invalid address: da=%#x pa=%#x va=%#x size=%d",
+ daddr, req->paddr, req->vaddr, req->size);
+
+ if (req->size != Regs::regSize(daddr))
+ panic("invalid size for reg %s: da=%#x pa=%#x va=%#x size=%d",
+ Regs::regName(daddr), daddr, req->paddr, req->vaddr, req->size);
+
+ DPRINTF(EthernetPIO, "read reg=%s da=%#x pa=%#x va=%#x size=%d\n",
+ Regs::regName(daddr), daddr, req->paddr, req->vaddr, req->size);
+
+ uint32_t &reg32 = *(uint32_t *)data;
+ uint64_t &reg64 = *(uint64_t *)data;
+
+ switch (daddr) {
+ case Regs::Config:
+ reg32 = regs.Config;
+ break;
+
+ case Regs::RxMaxCopy:
+ reg32 = regs.RxMaxCopy;
+ break;
+
+ case Regs::TxMaxCopy:
+ reg32 = regs.TxMaxCopy;
+ break;
+
+ case Regs::RxThreshold:
+ reg32 = regs.RxThreshold;
+ break;
+
+ case Regs::TxThreshold:
+ reg32 = regs.TxThreshold;
+ break;
+
+ case Regs::IntrStatus:
+ reg32 = regs.IntrStatus;
+ devIntrClear();
+ break;
+
+ case Regs::IntrMask:
+ reg32 = regs.IntrMask;
+ break;
+
+ case Regs::RxData:
+ reg64 = regs.RxData;
+ break;
+
+ case Regs::RxDone:
+ case Regs::RxWait:
+ reg64 = Regs::set_RxDone_FifoLen(regs.RxDone,
+ min(rxFifo.packets(), 255));
+ break;
+
+ case Regs::TxData:
+ reg64 = regs.TxData;
+ break;
+
+ case Regs::TxDone:
+ case Regs::TxWait:
+ reg64 = Regs::set_TxDone_FifoLen(regs.TxDone,
+ min(txFifo.packets(), 255));
+ break;
+
+ case Regs::HwAddr:
+ reg64 = params()->eaddr;
+ break;
+
+ default:
+ panic("reading write only register %s: da=%#x pa=%#x va=%#x size=%d",
+ Regs::regName(daddr), daddr, req->paddr, req->vaddr, req->size);
+ }
+
+ DPRINTF(EthernetPIO, "read reg=%s done val=%#x\n", Regs::regName(daddr),
+ Regs::regSize(daddr) == 4 ? reg32 : reg64);
+
+ return No_Fault;
+}
+
+Fault
+Device::write(MemReqPtr &req, const uint8_t *data)
+{
+ assert(config.hdr.command & PCI_CMD_MSE);
+ Addr daddr = req->paddr & 0xfff;
+
+ if (Regs::regSize(daddr) == 0)
+ panic("invalid address: da=%#x pa=%#x va=%#x size=%d",
+ daddr, req->paddr, req->vaddr, req->size);
+
+ if (req->size != Regs::regSize(daddr))
+ panic("invalid size: reg=%s da=%#x pa=%#x va=%#x size=%d",
+ Regs::regName(daddr), daddr, req->paddr, req->vaddr, req->size);
+
+ uint32_t reg32 = *(uint32_t *)data;
+ uint64_t reg64 = *(uint64_t *)data;
+
+ DPRINTF(EthernetPIO, "write reg=%s val=%#x da=%#x pa=%#x va=%#x size=%d\n",
+ Regs::regName(daddr), Regs::regSize(daddr) == 4 ? reg32 : reg64,
+ daddr, req->paddr, req->vaddr, req->size);
+
+
+ switch (daddr) {
+ case Regs::Config:
+ changeConfig(reg32);
+ break;
+
+ case Regs::RxThreshold:
+ regs.RxThreshold = reg32;
+ break;
+
+ case Regs::TxThreshold:
+ regs.TxThreshold = reg32;
+ break;
+
+ case Regs::IntrMask:
+ devIntrChangeMask(reg32);
+ break;
+
+ case Regs::RxData:
+ if (rxState != rxIdle)
+ panic("receive machine busy with another request!");
+
+ regs.RxDone = 0;
+ regs.RxData = reg64;
+ if (rxEnable) {
+ rxState = rxFifoBlock;
+ rxKick();
+ }
+ break;
+
+ case Regs::TxData:
+ if (txState != txIdle)
+ panic("transmit machine busy with another request!");
+
+ regs.TxDone = 0;
+ regs.TxData = reg64;
+ if (txEnable) {
+ txState = txFifoBlock;
+ txKick();
+ }
+ break;
+
+ default:
+ panic("writing read only register %s: da=%#x pa=%#x va=%#x size=%d",
+ Regs::regName(daddr), daddr, req->paddr, req->vaddr, req->size);
+ }
+
+ return No_Fault;
+}
+
+void
+Device::devIntrPost(uint32_t interrupts)
+{
+ if ((interrupts & Regs::Intr_Res))
+ panic("Cannot set a reserved interrupt");
+
+ regs.IntrStatus |= interrupts;
+
+ DPRINTF(EthernetIntr,
+ "interrupt written to intStatus: intr=%#x status=%#x mask=%#x\n",
+ interrupts, regs.IntrStatus, regs.IntrMask);
+
+ if ((regs.IntrStatus & regs.IntrMask)) {
+ Tick when = curTick;
+ if ((regs.IntrStatus & regs.IntrMask & Regs::Intr_NoDelay) == 0)
+ when += intrDelay;
+ cpuIntrPost(when);
+ }
+}
+
+void
+Device::devIntrClear(uint32_t interrupts)
+{
+ if ((interrupts & Regs::Intr_Res))
+ panic("Cannot clear a reserved interrupt");
+
+ regs.IntrStatus &= ~interrupts;
+
+ DPRINTF(EthernetIntr,
+ "interrupt cleared from intStatus: intr=%x status=%x mask=%x\n",
+ interrupts, regs.IntrStatus, regs.IntrMask);
+
+ if (!(regs.IntrStatus & regs.IntrMask))
+ cpuIntrClear();
+}
+
+void
+Device::devIntrChangeMask(uint32_t newmask)
+{
+ if (regs.IntrMask == newmask)
+ return;
+
+ regs.IntrMask = newmask;
+
+ DPRINTF(EthernetIntr,
+ "interrupt mask changed: intStatus=%x intMask=%x masked=%x\n",
+ regs.IntrStatus, regs.IntrMask, regs.IntrStatus & regs.IntrMask);
+
+ if (regs.IntrStatus & regs.IntrMask)
+ cpuIntrPost(curTick);
+ else
+ cpuIntrClear();
+}
+
+void
+Base::cpuIntrPost(Tick when)
+{
+ // If the interrupt you want to post is later than an interrupt
+ // already scheduled, just let it post in the coming one and don't
+ // schedule another.
+ // HOWEVER, must be sure that the scheduled intrTick is in the
+ // future (this was formerly the source of a bug)
+ /**
+ * @todo this warning should be removed and the intrTick code should
+ * be fixed.
+ */
+ assert(when >= curTick);
+ assert(intrTick >= curTick || intrTick == 0);
+ if (!cpuIntrEnable) {
+ DPRINTF(EthernetIntr, "interrupts not enabled.\n",
+ intrTick);
+ return;
+ }
+
+ if (when > intrTick && intrTick != 0) {
+ DPRINTF(EthernetIntr, "don't need to schedule event...intrTick=%d\n",
+ intrTick);
+ return;
+ }
+
+ intrTick = when;
+ if (intrTick < curTick) {
+ debug_break();
+ intrTick = curTick;
+ }
+
+ DPRINTF(EthernetIntr, "going to schedule an interrupt for intrTick=%d\n",
+ intrTick);
+
+ if (intrEvent)
+ intrEvent->squash();
+ intrEvent = new IntrEvent(this, true);
+ intrEvent->schedule(intrTick);
+}
+
+void
+Base::cpuInterrupt()
+{
+ assert(intrTick == curTick);
+
+ // Whether or not there's a pending interrupt, we don't care about
+ // it anymore
+ intrEvent = 0;
+ intrTick = 0;
+
+ // Don't send an interrupt if there's already one
+ if (cpuPendingIntr) {
+ DPRINTF(EthernetIntr,
+ "would send an interrupt now, but there's already pending\n");
+ } else {
+ // Send interrupt
+ cpuPendingIntr = true;
+
+ DPRINTF(EthernetIntr, "posting interrupt\n");
+ intrPost();
+ }
+}
+
+void
+Base::cpuIntrClear()
+{
+ if (!cpuPendingIntr)
+ return;
+
+ if (intrEvent) {
+ intrEvent->squash();
+ intrEvent = 0;
+ }
+
+ intrTick = 0;
+
+ cpuPendingIntr = false;
+
+ DPRINTF(EthernetIntr, "clearing cchip interrupt\n");
+ intrClear();
+}
+
+bool
+Base::cpuIntrPending() const
+{ return cpuPendingIntr; }
+
+void
+Device::changeConfig(uint32_t newconf)
+{
+ uint32_t changed = regs.Config ^ newconf;
+ if (!changed)
+ return;
+
+ regs.Config = newconf;
+
+ if ((changed & Regs::Config_Reset)) {
+ assert(regs.Config & Regs::Config_Reset);
+ reset();
+ regs.Config &= ~Regs::Config_Reset;
+ }
+
+ if ((changed & Regs::Config_IntEn)) {
+ cpuIntrEnable = regs.Config & Regs::Config_IntEn;
+ if (cpuIntrEnable) {
+ if (regs.IntrStatus & regs.IntrMask)
+ cpuIntrPost(curTick);
+ } else {
+ cpuIntrClear();
+ }
+ }
+
+ if ((changed & Regs::Config_TxEn)) {
+ txEnable = regs.Config & Regs::Config_TxEn;
+ if (txEnable)
+ txKick();
+ }
+
+ if ((changed & Regs::Config_RxEn)) {
+ rxEnable = regs.Config & Regs::Config_RxEn;
+ if (rxEnable)
+ rxKick();
+ }
+}
+
+void
+Device::reset()
+{
+ using namespace Regs;
+ memset(&regs, 0, sizeof(regs));
+ regs.RxMaxCopy = params()->rx_max_copy;
+ regs.TxMaxCopy = params()->tx_max_copy;
+ regs.IntrMask = Intr_TxFifo | Intr_RxFifo | Intr_RxData;
+
+ rxState = rxIdle;
+ txState = txIdle;
+
+ rxFifo.clear();
+ txFifo.clear();
+}
+
+void
+Device::rxDmaCopy()
+{
+ assert(rxState == rxCopy);
+ rxState = rxCopyDone;
+ physmem->dma_write(rxDmaAddr, (uint8_t *)rxDmaData, rxDmaLen);
+ DPRINTF(EthernetDMA, "rx dma write paddr=%#x len=%d\n",
+ rxDmaAddr, rxDmaLen);
+ DDUMP(EthernetDMA, rxDmaData, rxDmaLen);
+}
+
+void
+Device::rxDmaDone()
+{
+ rxDmaCopy();
+ rxKick();
+}
+
+void
+Device::rxKick()
+{
+ DPRINTF(EthernetSM, "receive kick rxState=%s (rxFifo.size=%d)\n",
+ RxStateStrings[rxState], rxFifo.size());
+
+ if (rxKickTick > curTick) {
+ DPRINTF(EthernetSM, "receive kick exiting, can't run till %d\n",
+ rxKickTick);
+ return;
+ }
+
+ next:
+ switch (rxState) {
+ case rxIdle:
+ if (rxPioRequest) {
+ pioInterface->respond(rxPioRequest, curTick);
+ rxPioRequest = 0;
+ }
+ goto exit;
+
+ case rxFifoBlock:
+ if (rxPacket) {
+ rxState = rxBeginCopy;
+ break;
+ }
+
+ if (rxFifo.empty()) {
+ DPRINTF(EthernetSM, "receive waiting for data. Nothing to do.\n");
+ goto exit;
+ }
+
+ // Grab a new packet from the fifo.
+ rxPacket = rxFifo.front();
+ rxPacketBufPtr = rxPacket->data;
+ rxPktBytes = rxPacket->length;
+ assert(rxPktBytes);
+
+ rxDoneData = 0;
+ /* scope for variables */ {
+ IpPtr ip(rxPacket);
+ if (ip) {
+ rxDoneData |= Regs::RxDone_IpPacket;
+ rxIpChecksums++;
+ if (cksum(ip) != 0) {
+ DPRINTF(EthernetCksum, "Rx IP Checksum Error\n");
+ rxDoneData |= Regs::RxDone_IpError;
+ }
+ TcpPtr tcp(ip);
+ UdpPtr udp(ip);
+ if (tcp) {
+ rxDoneData |= Regs::RxDone_TcpPacket;
+ rxTcpChecksums++;
+ if (cksum(tcp) != 0) {
+ DPRINTF(EthernetCksum, "Rx TCP Checksum Error\n");
+ rxDoneData |= Regs::RxDone_TcpError;
+ }
+ } else if (udp) {
+ rxDoneData |= Regs::RxDone_UdpPacket;
+ rxUdpChecksums++;
+ if (cksum(udp) != 0) {
+ DPRINTF(EthernetCksum, "Rx UDP Checksum Error\n");
+ rxDoneData |= Regs::RxDone_UdpError;
+ }
+ }
+ }
+ }
+ rxState = rxBeginCopy;
+ break;
+
+ case rxBeginCopy:
+ rxDmaAddr = plat->pciToDma(Regs::get_RxData_Addr(regs.RxData));
+ rxDmaLen = min<int>(Regs::get_RxData_Len(regs.RxData), rxPktBytes);
+ rxDmaData = rxPacketBufPtr;
+
+ if (dmaInterface) {
+ if (!dmaInterface->busy()) {
+ dmaInterface->doDMA(WriteInvalidate, rxDmaAddr, rxDmaLen,
+ curTick, &rxDmaEvent, true);
+ rxState = rxCopy;
+ }
+ goto exit;
+ }
+
+ rxState = rxCopy;
+ if (dmaWriteDelay != 0 || dmaWriteFactor != 0) {
+ Tick factor = ((rxDmaLen + ULL(63)) >> ULL(6)) * dmaWriteFactor;
+ Tick start = curTick + dmaWriteDelay + factor;
+ rxDmaEvent.schedule(start);
+ goto exit;
+ }
+
+ rxDmaCopy();
+ break;
+
+ case rxCopy:
+ DPRINTF(EthernetSM, "receive machine still copying\n");
+ goto exit;
+
+ case rxCopyDone:
+ regs.RxDone = rxDoneData | rxDmaLen;
+
+ if (rxPktBytes == rxDmaLen) {
+ rxPacket = NULL;
+ rxFifo.pop();
+ } else {
+ regs.RxDone |= Regs::RxDone_More;
+ rxPktBytes -= rxDmaLen;
+ rxPacketBufPtr += rxDmaLen;
+ }
+
+ regs.RxDone |= Regs::RxDone_Complete;
+ devIntrPost(Regs::Intr_RxData);
+ rxState = rxIdle;
+ break;
+
+ default:
+ panic("Invalid rxState!");
+ }
+
+ DPRINTF(EthernetSM, "entering next rxState=%s\n",
+ RxStateStrings[rxState]);
+
+ goto next;
+
+ exit:
+ /**
+ * @todo do we want to schedule a future kick?
+ */
+ DPRINTF(EthernetSM, "rx state machine exited rxState=%s\n",
+ RxStateStrings[rxState]);
+}
+
+void
+Device::txDmaCopy()
+{
+ 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(EthernetDMA, txDmaData, txDmaLen);
+}
+
+void
+Device::txDmaDone()
+{
+ txDmaCopy();
+ txKick();
+}
+
+void
+Device::transmit()
+{
+ if (txFifo.empty()) {
+ DPRINTF(Ethernet, "nothing to transmit\n");
+ return;
+ }
+
+ PacketPtr packet = txFifo.front();
+ if (!interface->sendPacket(packet)) {
+ DPRINTF(Ethernet, "Packet Transmit: failed txFifo available %d\n",
+ txFifo.avail());
+ goto reschedule;
+ }
+
+ txFifo.pop();
+
+#if TRACING_ON
+ if (DTRACE(Ethernet)) {
+ IpPtr ip(packet);
+ if (ip) {
+ DPRINTF(Ethernet, "ID is %d\n", ip->id());
+ TcpPtr tcp(ip);
+ if (tcp) {
+ DPRINTF(Ethernet, "Src Port=%d, Dest Port=%d\n",
+ tcp->sport(), tcp->dport());
+ }
+ }
+ }
+#endif
+
+ DDUMP(Ethernet, packet->data, packet->length);
+ txBytes += packet->length;
+ txPackets++;
+
+ DPRINTF(Ethernet, "Packet Transmit: successful txFifo Available %d\n",
+ txFifo.avail());
+
+ if (txFifo.size() <= params()->tx_fifo_threshold)
+ devIntrPost(Regs::Intr_TxFifo);
+
+ devIntrPost(Regs::Intr_TxDone);
+
+ reschedule:
+ if (!txFifo.empty() && !txEvent.scheduled()) {
+ DPRINTF(Ethernet, "reschedule transmit\n");
+ txEvent.schedule(curTick + 1000);
+ }
+}
+
+void
+Device::txKick()
+{
+ DPRINTF(EthernetSM, "transmit kick txState=%s (txFifo.size=%d)\n",
+ TxStateStrings[txState], txFifo.size());
+
+ if (txKickTick > curTick) {
+ DPRINTF(EthernetSM, "transmit kick exiting, can't run till %d\n",
+ txKickTick);
+ return;
+ }
+
+ next:
+ switch (txState) {
+ case txIdle:
+ if (txPioRequest) {
+ pioInterface->respond(txPioRequest, curTick + pioLatency);
+ txPioRequest = 0;
+ }
+ goto exit;
+
+ case txFifoBlock:
+ if (!txPacket) {
+ // Grab a new packet from the fifo.
+ txPacket = new PacketData(16384);
+ txPacketBufPtr = txPacket->data;
+ }
+
+ if (txFifo.avail() - txPacket->length <
+ Regs::get_TxData_Len(regs.TxData)) {
+ DPRINTF(EthernetSM, "transmit fifo full. Nothing to do.\n");
+ goto exit;
+ }
+
+ txState = txBeginCopy;
+ break;
+
+ case txBeginCopy:
+ txDmaAddr = plat->pciToDma(Regs::get_TxData_Addr(regs.TxData));
+ txDmaLen = Regs::get_TxData_Len(regs.TxData);
+ txDmaData = txPacketBufPtr;
+
+ if (dmaInterface) {
+ if (!dmaInterface->busy()) {
+ dmaInterface->doDMA(Read, txDmaAddr, txDmaLen,
+ curTick, &txDmaEvent, true);
+ txState = txCopy;
+ }
+
+ goto exit;
+ }
+
+ txState = txCopy;
+ if (dmaReadDelay != 0 || dmaReadFactor != 0) {
+ Tick factor = ((txDmaLen + ULL(63)) >> ULL(6)) * dmaReadFactor;
+ Tick start = curTick + dmaReadDelay + factor;
+ txDmaEvent.schedule(start);
+ goto exit;
+ }
+
+ txDmaCopy();
+ break;
+
+ case txCopy:
+ DPRINTF(EthernetSM, "transmit machine still copying\n");
+ goto exit;
+
+ case txCopyDone:
+ txPacket->length += txDmaLen;
+ if ((regs.TxData & Regs::TxData_More)) {
+ txPacketBufPtr += txDmaLen;
+ } else {
+ assert(txPacket->length <= txFifo.avail());
+ if ((regs.TxData & Regs::TxData_Checksum)) {
+ IpPtr ip(txPacket);
+ if (ip) {
+ TcpPtr tcp(ip);
+ if (tcp) {
+ tcp->sum(0);
+ tcp->sum(cksum(tcp));
+ txTcpChecksums++;
+ }
+
+ UdpPtr udp(ip);
+ if (udp) {
+ udp->sum(0);
+ udp->sum(cksum(udp));
+ txUdpChecksums++;
+ }
+
+ ip->sum(0);
+ ip->sum(cksum(ip));
+ txIpChecksums++;
+ }
+ }
+ txFifo.push(txPacket);
+ txPacket = 0;
+ transmit();
+ }
+
+ regs.TxDone = txDmaLen | Regs::TxDone_Complete;
+ devIntrPost(Regs::Intr_TxData);
+ txState = txIdle;
+ break;
+
+ default:
+ panic("Invalid txState!");
+ }
+
+ DPRINTF(EthernetSM, "entering next txState=%s\n",
+ TxStateStrings[txState]);
+
+ goto next;
+
+ exit:
+ /**
+ * @todo do we want to schedule a future kick?
+ */
+ DPRINTF(EthernetSM, "tx state machine exited txState=%s\n",
+ TxStateStrings[txState]);
+}
+
+void
+Device::transferDone()
+{
+ if (txFifo.empty()) {
+ DPRINTF(Ethernet, "transfer complete: txFifo empty...nothing to do\n");
+ return;
+ }
+
+ DPRINTF(Ethernet, "transfer complete: data in txFifo...schedule xmit\n");
+
+ if (txEvent.scheduled())
+ txEvent.reschedule(curTick + 1);
+ else
+ txEvent.schedule(curTick + 1);
+}
+
+bool
+Device::rxFilter(const PacketPtr &packet)
+{
+ if (!Regs::get_Config_Filter(regs.Config))
+ return false;
+
+ panic("receive filter not implemented\n");
+ bool drop = true;
+
+#if 0
+ string type;
+
+ EthHdr *eth = packet->eth();
+ if (eth->unicast()) {
+ // If we're accepting all unicast addresses
+ if (acceptUnicast)
+ drop = false;
+
+ // If we make a perfect match
+ if (acceptPerfect && params->eaddr == eth.dst())
+ drop = false;
+
+ if (acceptArp && eth->type() == ETH_TYPE_ARP)
+ drop = false;
+
+ } else if (eth->broadcast()) {
+ // if we're accepting broadcasts
+ if (acceptBroadcast)
+ drop = false;
+
+ } else if (eth->multicast()) {
+ // if we're accepting all multicasts
+ if (acceptMulticast)
+ drop = false;
+
+ }
+
+ if (drop) {
+ DPRINTF(Ethernet, "rxFilter drop\n");
+ DDUMP(EthernetData, packet->data, packet->length);
+ }
+#endif
+ return drop;
+}
+
+bool
+Device::recvPacket(PacketPtr packet)
+{
+ rxBytes += packet->length;
+ rxPackets++;
+
+ DPRINTF(Ethernet, "Receiving packet from wire, rxFifo Available is %d\n",
+ rxFifo.avail());
+
+ if (!rxEnable) {
+ DPRINTF(Ethernet, "receive disabled...packet dropped\n");
+ interface->recvDone();
+ return true;
+ }
+
+ if (rxFilter(packet)) {
+ DPRINTF(Ethernet, "packet filtered...dropped\n");
+ interface->recvDone();
+ return true;
+ }
+
+ if (rxFifo.size() >= params()->rx_fifo_threshold)
+ devIntrPost(Regs::Intr_RxFifo);
+
+ if (!rxFifo.push(packet)) {
+ DPRINTF(Ethernet,
+ "packet will not fit in receive buffer...packet dropped\n");
+ return false;
+ }
+
+ interface->recvDone();
+ devIntrPost(Regs::Intr_RxDone);
+ rxKick();
+ return true;
+}
+
+//=====================================================================
+//
+//
+void
+Base::serialize(ostream &os)
+{
+ // Serialize the PciDev base class
+ PciDev::serialize(os);
+
+ SERIALIZE_SCALAR(rxEnable);
+ SERIALIZE_SCALAR(txEnable);
+ SERIALIZE_SCALAR(cpuIntrEnable);
+
+ /*
+ * Keep track of pending interrupt status.
+ */
+ SERIALIZE_SCALAR(intrTick);
+ SERIALIZE_SCALAR(cpuPendingIntr);
+ Tick intrEventTick = 0;
+ if (intrEvent)
+ intrEventTick = intrEvent->when();
+ SERIALIZE_SCALAR(intrEventTick);
+}
+
+void
+Base::unserialize(Checkpoint *cp, const std::string &section)
+{
+ // Unserialize the PciDev base class
+ PciDev::unserialize(cp, section);
+
+ UNSERIALIZE_SCALAR(rxEnable);
+ UNSERIALIZE_SCALAR(txEnable);
+ UNSERIALIZE_SCALAR(cpuIntrEnable);
+
+ /*
+ * Keep track of pending interrupt status.
+ */
+ UNSERIALIZE_SCALAR(intrTick);
+ UNSERIALIZE_SCALAR(cpuPendingIntr);
+ Tick intrEventTick;
+ UNSERIALIZE_SCALAR(intrEventTick);
+ if (intrEventTick) {
+ intrEvent = new IntrEvent(this, true);
+ intrEvent->schedule(intrEventTick);
+ }
+}
+
+void
+Device::serialize(ostream &os)
+{
+ // Serialize the PciDev base class
+ Base::serialize(os);
+
+ if (rxDmaEvent.scheduled())
+ rxDmaCopy();
+
+ if (txDmaEvent.scheduled())
+ txDmaCopy();
+
+ /*
+ * Serialize the device registers
+ */
+ SERIALIZE_SCALAR(regs.Config);
+ SERIALIZE_SCALAR(regs.RxMaxCopy);
+ SERIALIZE_SCALAR(regs.TxMaxCopy);
+ SERIALIZE_SCALAR(regs.RxThreshold);
+ SERIALIZE_SCALAR(regs.TxThreshold);
+ SERIALIZE_SCALAR(regs.IntrStatus);
+ SERIALIZE_SCALAR(regs.IntrMask);
+ SERIALIZE_SCALAR(regs.RxData);
+ SERIALIZE_SCALAR(regs.RxDone);
+ SERIALIZE_SCALAR(regs.TxData);
+ SERIALIZE_SCALAR(regs.TxDone);
+
+ /*
+ * Serialize rx state machine
+ */
+ int rxState = this->rxState;
+ SERIALIZE_SCALAR(rxState);
+ rxFifo.serialize("rxFifo", os);
+ bool rxPacketExists = rxPacket;
+ SERIALIZE_SCALAR(rxPacketExists);
+ if (rxPacketExists) {
+ rxPacket->serialize("rxPacket", os);
+ uint32_t rxPktBufPtr = (uint32_t) (rxPacketBufPtr - rxPacket->data);
+ SERIALIZE_SCALAR(rxPktBufPtr);
+ SERIALIZE_SCALAR(rxPktBytes);
+ }
+ SERIALIZE_SCALAR(rxDoneData);
+
+ /*
+ * Serialize tx state machine
+ */
+ int txState = this->txState;
+ SERIALIZE_SCALAR(txState);
+ txFifo.serialize("txFifo", os);
+ bool txPacketExists = txPacket;
+ SERIALIZE_SCALAR(txPacketExists);
+ if (txPacketExists) {
+ txPacket->serialize("txPacket", os);
+ uint32_t txPktBufPtr = (uint32_t) (txPacketBufPtr - txPacket->data);
+ SERIALIZE_SCALAR(txPktBufPtr);
+ SERIALIZE_SCALAR(txPktBytes);
+ }
+
+ /*
+ * If there's a pending transmit, store the time so we can
+ * reschedule it later
+ */
+ Tick transmitTick = txEvent.scheduled() ? txEvent.when() - curTick : 0;
+ SERIALIZE_SCALAR(transmitTick);
+}
+
+void
+Device::unserialize(Checkpoint *cp, const std::string &section)
+{
+ // Unserialize the PciDev base class
+ Base::unserialize(cp, section);
+
+ /*
+ * Unserialize the device registers
+ */
+ UNSERIALIZE_SCALAR(regs.Config);
+ UNSERIALIZE_SCALAR(regs.RxMaxCopy);
+ UNSERIALIZE_SCALAR(regs.TxMaxCopy);
+ UNSERIALIZE_SCALAR(regs.RxThreshold);
+ UNSERIALIZE_SCALAR(regs.TxThreshold);
+ UNSERIALIZE_SCALAR(regs.IntrStatus);
+ UNSERIALIZE_SCALAR(regs.IntrMask);
+ UNSERIALIZE_SCALAR(regs.RxData);
+ UNSERIALIZE_SCALAR(regs.RxDone);
+ UNSERIALIZE_SCALAR(regs.TxData);
+ UNSERIALIZE_SCALAR(regs.TxDone);
+
+ /*
+ * Unserialize rx state machine
+ */
+ int rxState;
+ UNSERIALIZE_SCALAR(rxState);
+ this->rxState = (RxState) rxState;
+ rxFifo.unserialize("rxFifo", cp, section);
+ bool rxPacketExists;
+ UNSERIALIZE_SCALAR(rxPacketExists);
+ rxPacket = 0;
+ if (rxPacketExists) {
+ rxPacket = new PacketData(16384);
+ rxPacket->unserialize("rxPacket", cp, section);
+ uint32_t rxPktBufPtr;
+ UNSERIALIZE_SCALAR(rxPktBufPtr);
+ this->rxPacketBufPtr = (uint8_t *) rxPacket->data + rxPktBufPtr;
+ UNSERIALIZE_SCALAR(rxPktBytes);
+ }
+ UNSERIALIZE_SCALAR(rxDoneData);
+
+ /*
+ * Unserialize tx state machine
+ */
+ int txState;
+ UNSERIALIZE_SCALAR(txState);
+ this->txState = (TxState) txState;
+ txFifo.unserialize("txFifo", cp, section);
+ bool txPacketExists;
+ UNSERIALIZE_SCALAR(txPacketExists);
+ txPacket = 0;
+ if (txPacketExists) {
+ txPacket = new PacketData(16384);
+ txPacket->unserialize("txPacket", cp, section);
+ uint32_t txPktBufPtr;
+ UNSERIALIZE_SCALAR(txPktBufPtr);
+ this->txPacketBufPtr = (uint8_t *) txPacket->data + txPktBufPtr;
+ UNSERIALIZE_SCALAR(txPktBytes);
+ }
+
+ /*
+ * If there's a pending transmit, reschedule it now
+ */
+ Tick transmitTick;
+ UNSERIALIZE_SCALAR(transmitTick);
+ 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)
+{
+ //The mask is to give you only the offset into the device register file
+ Addr daddr = req->paddr - addr;
+
+ DPRINTF(EthernetPIO, "timing access to paddr=%#x (daddr=%#x)\n",
+ req->paddr, daddr);
+
+ Tick when = curTick + pioLatency;
+
+ switch (daddr) {
+ case Regs::RxDone:
+ if (rxState != rxIdle) {
+ rxPioRequest = req;
+ when = 0;
+ }
+ break;
+
+ case Regs::TxDone:
+ if (txState != txIdle) {
+ txPioRequest = req;
+ when = 0;
+ }
+ break;
+ }
+
+ return when;
+}
+
+BEGIN_DECLARE_SIM_OBJECT_PARAMS(Interface)
+
+ SimObjectParam<EtherInt *> peer;
+ SimObjectParam<Device *> device;
+
+END_DECLARE_SIM_OBJECT_PARAMS(Interface)
+
+BEGIN_INIT_SIM_OBJECT_PARAMS(Interface)
+
+ INIT_PARAM_DFLT(peer, "peer interface", NULL),
+ INIT_PARAM(device, "Ethernet device of this interface")
+
+END_INIT_SIM_OBJECT_PARAMS(Interface)
+
+CREATE_SIM_OBJECT(Interface)
+{
+ Interface *dev_int = new Interface(getInstanceName(), device);
+
+ EtherInt *p = (EtherInt *)peer;
+ if (p) {
+ dev_int->setPeer(p);
+ p->setPeer(dev_int);
+ }
+
+ return dev_int;
+}
+
+REGISTER_SIM_OBJECT("SinicInt", Interface)
+
+
+BEGIN_DECLARE_SIM_OBJECT_PARAMS(Device)
+
+ Param<Tick> tx_delay;
+ Param<Tick> rx_delay;
+ Param<Tick> intr_delay;
+ SimObjectParam<MemoryController *> mmu;
+ SimObjectParam<PhysicalMemory *> physmem;
+ Param<bool> rx_filter;
+ Param<string> hardware_address;
+ SimObjectParam<Bus*> header_bus;
+ SimObjectParam<Bus*> payload_bus;
+ SimObjectParam<HierParams *> hier;
+ Param<Tick> pio_latency;
+ 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<uint32_t> rx_max_copy;
+ Param<uint32_t> tx_max_copy;
+ Param<uint32_t> rx_fifo_size;
+ Param<uint32_t> tx_fifo_size;
+ Param<uint32_t> rx_fifo_threshold;
+ Param<uint32_t> tx_fifo_threshold;
+ Param<Tick> dma_read_delay;
+ Param<Tick> dma_read_factor;
+ Param<Tick> dma_write_delay;
+ Param<Tick> dma_write_factor;
+
+END_DECLARE_SIM_OBJECT_PARAMS(Device)
+
+BEGIN_INIT_SIM_OBJECT_PARAMS(Device)
+
+ INIT_PARAM_DFLT(tx_delay, "Transmit Delay", 1000),
+ INIT_PARAM_DFLT(rx_delay, "Receive Delay", 1000),
+ INIT_PARAM_DFLT(intr_delay, "Interrupt Delay in microseconds", 0),
+ INIT_PARAM(mmu, "Memory Controller"),
+ INIT_PARAM(physmem, "Physical Memory"),
+ INIT_PARAM_DFLT(rx_filter, "Enable Receive Filter", true),
+ INIT_PARAM_DFLT(hardware_address, "Ethernet Hardware Address",
+ "00:99:00:00:00:01"),
+ INIT_PARAM_DFLT(header_bus, "The IO Bus to attach to for headers", NULL),
+ INIT_PARAM_DFLT(payload_bus, "The IO Bus to attach to for payload", NULL),
+ INIT_PARAM_DFLT(hier, "Hierarchy global variables", &defaultHierParams),
+ INIT_PARAM_DFLT(pio_latency, "Programmed IO latency in bus cycles", 1),
+ INIT_PARAM(configspace, "PCI Configspace"),
+ INIT_PARAM(configdata, "PCI Config data"),
+ INIT_PARAM(platform, "Platform"),
+ INIT_PARAM(pci_bus, "PCI bus"),
+ INIT_PARAM(pci_dev, "PCI device number"),
+ INIT_PARAM(pci_func, "PCI function code"),
+ INIT_PARAM_DFLT(rx_max_copy, "rx max copy", 16*1024),
+ INIT_PARAM_DFLT(tx_max_copy, "rx max copy", 16*1024),
+ INIT_PARAM_DFLT(rx_fifo_size, "max size in bytes of rxFifo", 64*1024),
+ INIT_PARAM_DFLT(tx_fifo_size, "max size in bytes of txFifo", 64*1024),
+ INIT_PARAM_DFLT(rx_fifo_threshold, "max size in bytes of rxFifo", 48*1024),
+ INIT_PARAM_DFLT(tx_fifo_threshold, "max size in bytes of txFifo", 16*1024),
+ INIT_PARAM_DFLT(dma_read_delay, "fixed delay for dma reads", 0),
+ INIT_PARAM_DFLT(dma_read_factor, "multiplier for dma reads", 0),
+ INIT_PARAM_DFLT(dma_write_delay, "fixed delay for dma writes", 0),
+ INIT_PARAM_DFLT(dma_write_factor, "multiplier for dma writes", 0)
+
+END_INIT_SIM_OBJECT_PARAMS(Device)
+
+
+CREATE_SIM_OBJECT(Device)
+{
+ Device::Params *params = new Device::Params;
+ params->name = getInstanceName();
+ params->intr_delay = intr_delay;
+ params->physmem = physmem;
+ params->tx_delay = tx_delay;
+ params->rx_delay = rx_delay;
+ params->mmu = mmu;
+ params->hier = hier;
+ params->header_bus = header_bus;
+ params->payload_bus = payload_bus;
+ params->pio_latency = pio_latency;
+ params->configSpace = configspace;
+ params->configData = configdata;
+ params->plat = platform;
+ params->busNum = pci_bus;
+ params->deviceNum = pci_dev;
+ params->functionNum = pci_func;
+ params->rx_filter = rx_filter;
+ params->eaddr = hardware_address;
+ params->rx_max_copy = rx_max_copy;
+ params->tx_max_copy = tx_max_copy;
+ params->rx_fifo_size = rx_fifo_size;
+ params->tx_fifo_size = tx_fifo_size;
+ params->rx_fifo_threshold = rx_fifo_threshold;
+ params->tx_fifo_threshold = tx_fifo_threshold;
+ 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;
+ return new Device(params);
+}
+
+REGISTER_SIM_OBJECT("Sinic", Device)
+
+/* namespace Sinic */ }
diff --git a/dev/sinic.hh b/dev/sinic.hh
new file mode 100644
index 000000000..ef515ffad
--- /dev/null
+++ b/dev/sinic.hh
@@ -0,0 +1,340 @@
+/*
+ * Copyright (c) 2004 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 __DEV_SINIC_HH__
+#define __DEV_SINIC_HH__
+
+#include "base/inet.hh"
+#include "base/statistics.hh"
+#include "dev/etherint.hh"
+#include "dev/etherpkt.hh"
+#include "dev/io_device.hh"
+#include "dev/pcidev.hh"
+#include "dev/pktfifo.hh"
+#include "dev/sinicreg.hh"
+#include "mem/bus/bus.hh"
+#include "sim/eventq.hh"
+
+namespace Sinic {
+
+class Interface;
+class Base : public PciDev
+{
+ protected:
+ bool rxEnable;
+ bool txEnable;
+
+ protected:
+ Tick intrDelay;
+ Tick intrTick;
+ bool cpuIntrEnable;
+ bool cpuPendingIntr;
+ void cpuIntrPost(Tick when);
+ void cpuInterrupt();
+ void cpuIntrClear();
+
+ typedef EventWrapper<Base, &Base::cpuInterrupt> IntrEvent;
+ friend class IntrEvent;
+ IntrEvent *intrEvent;
+ Interface *interface;
+
+ bool cpuIntrPending() const;
+ void cpuIntrAck() { cpuIntrClear(); }
+
+/**
+ * Serialization stuff
+ */
+ public:
+ virtual void serialize(std::ostream &os);
+ virtual void unserialize(Checkpoint *cp, const std::string &section);
+
+/**
+ * Construction/Destruction/Parameters
+ */
+ public:
+ struct Params : public PciDev::Params
+ {
+ Tick intr_delay;
+ };
+
+ Base(Params *p);
+};
+
+class Device : public Base
+{
+ protected:
+ Platform *plat;
+ PhysicalMemory *physmem;
+
+ protected:
+ /** Receive State Machine States */
+ enum RxState {
+ rxIdle,
+ rxFifoBlock,
+ rxBeginCopy,
+ rxCopy,
+ rxCopyDone
+ };
+
+ /** Transmit State Machine states */
+ enum TxState {
+ txIdle,
+ txFifoBlock,
+ txBeginCopy,
+ txCopy,
+ txCopyDone
+ };
+
+ /** device register file */
+ struct {
+ uint32_t Config;
+ uint32_t RxMaxCopy;
+ uint32_t TxMaxCopy;
+ uint32_t RxThreshold;
+ uint32_t TxThreshold;
+ uint32_t IntrStatus;
+ uint32_t IntrMask;
+ uint64_t RxData;
+ uint64_t RxDone;
+ uint64_t TxData;
+ uint64_t TxDone;
+ } regs;
+
+ private:
+ Addr addr;
+ static const Addr size = Regs::Size;
+
+ protected:
+ RxState rxState;
+ PacketFifo rxFifo;
+ PacketPtr rxPacket;
+ uint8_t *rxPacketBufPtr;
+ int rxPktBytes;
+ uint64_t rxDoneData;
+ Addr rxDmaAddr;
+ uint8_t *rxDmaData;
+ int rxDmaLen;
+
+ TxState txState;
+ PacketFifo txFifo;
+ PacketPtr txPacket;
+ uint8_t *txPacketBufPtr;
+ int txPktBytes;
+ Addr txDmaAddr;
+ uint8_t *txDmaData;
+ int txDmaLen;
+
+ protected:
+ void reset();
+
+ void rxKick();
+ Tick rxKickTick;
+ typedef EventWrapper<Device, &Device::rxKick> RxKickEvent;
+ friend class RxKickEvent;
+
+ void txKick();
+ Tick txKickTick;
+ typedef EventWrapper<Device, &Device::txKick> TxKickEvent;
+ friend class TxKickEvent;
+
+ /**
+ * Retransmit event
+ */
+ void transmit();
+ void txEventTransmit()
+ {
+ transmit();
+ if (txState == txFifoBlock)
+ txKick();
+ }
+ typedef EventWrapper<Device, &Device::txEventTransmit> TxEvent;
+ friend class TxEvent;
+ TxEvent txEvent;
+
+ void txDump() const;
+ void rxDump() const;
+
+ /**
+ * receive address filter
+ */
+ bool rxFilter(const PacketPtr &packet);
+
+/**
+ * device configuration
+ */
+ void changeConfig(uint32_t newconfig);
+
+/**
+ * device ethernet interface
+ */
+ public:
+ bool recvPacket(PacketPtr packet);
+ void transferDone();
+ void setInterface(Interface *i) { assert(!interface); interface = i; }
+
+/**
+ * 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::rxDmaDone> txDmaEvent;
+
+ Tick dmaReadDelay;
+ Tick dmaReadFactor;
+ Tick dmaWriteDelay;
+ Tick dmaWriteFactor;
+
+/**
+ * PIO parameters
+ */
+ protected:
+ MemReqPtr rxPioRequest;
+ MemReqPtr txPioRequest;
+
+/**
+ * Interrupt management
+ */
+ protected:
+ void devIntrPost(uint32_t interrupts);
+ void devIntrClear(uint32_t interrupts = Regs::Intr_All);
+ void devIntrChangeMask(uint32_t newmask);
+
+/**
+ * PCI Configuration interface
+ */
+ public:
+ virtual void WriteConfig(int offset, int size, uint32_t data);
+
+/**
+ * Memory Interface
+ */
+ public:
+ virtual Fault read(MemReqPtr &req, uint8_t *data);
+ virtual Fault write(MemReqPtr &req, const uint8_t *data);
+ Tick cacheAccess(MemReqPtr &req);
+
+/**
+ * Statistics
+ */
+ private:
+ Stats::Scalar<> rxBytes;
+ Stats::Formula rxBandwidth;
+ Stats::Scalar<> rxPackets;
+ Stats::Formula rxPacketRate;
+ Stats::Scalar<> rxIpPackets;
+ Stats::Scalar<> rxTcpPackets;
+ Stats::Scalar<> rxUdpPackets;
+ Stats::Scalar<> rxIpChecksums;
+ Stats::Scalar<> rxTcpChecksums;
+ Stats::Scalar<> rxUdpChecksums;
+
+ Stats::Scalar<> txBytes;
+ Stats::Formula txBandwidth;
+ Stats::Scalar<> txPackets;
+ Stats::Formula txPacketRate;
+ Stats::Scalar<> txIpPackets;
+ Stats::Scalar<> txTcpPackets;
+ Stats::Scalar<> txUdpPackets;
+ Stats::Scalar<> txIpChecksums;
+ Stats::Scalar<> txTcpChecksums;
+ Stats::Scalar<> txUdpChecksums;
+
+ public:
+ virtual void regStats();
+
+/**
+ * Serialization stuff
+ */
+ public:
+ virtual void serialize(std::ostream &os);
+ virtual void unserialize(Checkpoint *cp, const std::string &section);
+
+/**
+ * Construction/Destruction/Parameters
+ */
+ public:
+ struct Params : public Base::Params
+ {
+ IntrControl *i;
+ PhysicalMemory *pmem;
+ Tick tx_delay;
+ Tick rx_delay;
+ HierParams *hier;
+ Bus *header_bus;
+ Bus *payload_bus;
+ Tick pio_latency;
+ PhysicalMemory *physmem;
+ IntrControl *intctrl;
+ bool rx_filter;
+ Net::EthAddr eaddr;
+ uint32_t rx_max_copy;
+ uint32_t tx_max_copy;
+ uint32_t rx_fifo_size;
+ uint32_t tx_fifo_size;
+ uint32_t rx_fifo_threshold;
+ uint32_t tx_fifo_threshold;
+ Tick dma_read_delay;
+ Tick dma_read_factor;
+ Tick dma_write_delay;
+ Tick dma_write_factor;
+ };
+
+ protected:
+ const Params *params() const { return (const Params *)_params; }
+
+ public:
+ Device(Params *params);
+ ~Device();
+};
+
+/*
+ * Ethernet Interface for an Ethernet Device
+ */
+class Interface : public EtherInt
+{
+ private:
+ Device *dev;
+
+ public:
+ Interface(const std::string &name, Device *d)
+ : EtherInt(name), dev(d) { dev->setInterface(this); }
+
+ virtual bool recvPacket(PacketPtr pkt) { return dev->recvPacket(pkt); }
+ virtual void sendDone() { dev->transferDone(); }
+};
+
+/* namespace Sinic */ }
+
+#endif // __DEV_SINIC_HH__
diff --git a/dev/sinicreg.hh b/dev/sinicreg.hh
new file mode 100644
index 000000000..9f3412a31
--- /dev/null
+++ b/dev/sinicreg.hh
@@ -0,0 +1,187 @@
+/*
+ * Copyright (c) 2004 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 __DEV_SINICREG_HH__
+#define __DEV_SINICREG_HH__
+
+#define __SINIC_REG32(NAME, VAL) static const uint32_t NAME = (VAL)
+#define __SINIC_REG64(NAME, VAL) static const uint64_t NAME = (VAL)
+
+#define __SINIC_VAL32(NAME, OFFSET, WIDTH) \
+ static const uint32_t NAME##_width = WIDTH; \
+ static const uint32_t NAME##_offset = OFFSET; \
+ static const uint32_t NAME##_mask = (1 << WIDTH) - 1; \
+ static const uint32_t NAME = ((1 << WIDTH) - 1) << OFFSET; \
+ static inline uint32_t get_##NAME(uint32_t reg) \
+ { return (reg & NAME) >> OFFSET; } \
+ static inline uint32_t set_##NAME(uint32_t reg, uint32_t val) \
+ { return (reg & ~NAME) | ((val << OFFSET) & NAME); }
+
+#define __SINIC_VAL64(NAME, OFFSET, WIDTH) \
+ static const uint64_t NAME##_width = WIDTH; \
+ static const uint64_t NAME##_offset = OFFSET; \
+ static const uint64_t NAME##_mask = (ULL(1) << WIDTH) - 1; \
+ static const uint64_t NAME = ((ULL(1) << WIDTH) - 1) << OFFSET; \
+ static inline uint64_t get_##NAME(uint64_t reg) \
+ { return (reg & NAME) >> OFFSET; } \
+ static inline uint64_t set_##NAME(uint64_t reg, uint64_t val) \
+ { return (reg & ~NAME) | ((val << OFFSET) & NAME); }
+
+namespace Sinic {
+namespace Regs {
+
+// Registers
+__SINIC_REG32(Config, 0x00); // 32: configuration register
+__SINIC_REG32(RxMaxCopy, 0x04); // 32: max rx copy
+__SINIC_REG32(TxMaxCopy, 0x08); // 32: max tx copy
+__SINIC_REG32(RxThreshold, 0x0c); // 32: receive fifo threshold
+__SINIC_REG32(TxThreshold, 0x10); // 32: transmit fifo threshold
+__SINIC_REG32(IntrStatus, 0x14); // 32: interrupt status
+__SINIC_REG32(IntrMask, 0x18); // 32: interrupt mask
+__SINIC_REG32(RxData, 0x20); // 64: receive data
+__SINIC_REG32(RxDone, 0x28); // 64: receive done
+__SINIC_REG32(RxWait, 0x30); // 64: receive done (busy wait)
+__SINIC_REG32(TxData, 0x38); // 64: transmit data
+__SINIC_REG32(TxDone, 0x40); // 64: transmit done
+__SINIC_REG32(TxWait, 0x48); // 64: transmit done (busy wait)
+__SINIC_REG32(HwAddr, 0x50); // 64: mac address
+__SINIC_REG32(Size, 0x58);
+
+// Config register bits
+__SINIC_VAL32(Config_Reset, 31, 1); // reset chip
+__SINIC_VAL32(Config_Filter, 7, 1); // enable receive filter
+__SINIC_VAL32(Config_Vlan, 6, 1); // enable vlan tagging
+__SINIC_VAL32(Config_Virtual, 5, 1); // enable virtual addressing
+__SINIC_VAL32(Config_Desc, 4, 1); // enable tx/rx descriptors
+__SINIC_VAL32(Config_Poll, 3, 1); // enable polling
+__SINIC_VAL32(Config_IntEn, 2, 1); // enable interrupts
+__SINIC_VAL32(Config_TxEn, 1, 1); // enable transmit
+__SINIC_VAL32(Config_RxEn, 0, 1); // enable receive
+
+// Interrupt register bits
+__SINIC_VAL32(Intr_TxFifo, 5, 1); // Fifo oflow/uflow/threshold
+__SINIC_VAL32(Intr_TxData, 4, 1); // DMA Completed w/ interrupt
+__SINIC_VAL32(Intr_TxDone, 3, 1); // Packet transmitted
+__SINIC_VAL32(Intr_RxFifo, 2, 1); // Fifo oflow/uflow/threshold
+__SINIC_VAL32(Intr_RxData, 1, 1); // DMA Completed w/ interrupt
+__SINIC_VAL32(Intr_RxDone, 0, 1); // Packet received
+__SINIC_REG32(Intr_All, 0x3f);
+__SINIC_REG32(Intr_NoDelay, 0x24);
+__SINIC_REG32(Intr_Res, ~0x3f);
+
+// RX Data Description
+__SINIC_VAL64(RxData_Len, 40, 20); // 0 - 1M
+__SINIC_VAL64(RxData_Addr, 0, 40); // Address 1TB
+
+// TX Data Description
+__SINIC_VAL64(TxData_More, 63, 1);
+__SINIC_VAL64(TxData_Checksum, 62, 1);
+__SINIC_VAL64(TxData_Len, 40, 20); // 0 - 1M
+__SINIC_VAL64(TxData_Addr, 0, 40); // Address 1TB
+
+// RX Done/Busy Information
+__SINIC_VAL64(RxDone_Complete, 63, 1);
+__SINIC_VAL64(RxDone_IpPacket, 45, 1);
+__SINIC_VAL64(RxDone_TcpPacket, 44, 1);
+__SINIC_VAL64(RxDone_UdpPacket, 43, 1);
+__SINIC_VAL64(RxDone_IpError, 42, 1);
+__SINIC_VAL64(RxDone_TcpError, 41, 1);
+__SINIC_VAL64(RxDone_UdpError, 40, 1);
+__SINIC_VAL64(RxDone_More, 32, 1);
+__SINIC_VAL64(RxDone_FifoLen, 20, 8); // up to 255 packets
+__SINIC_VAL64(RxDone_CopyLen, 0, 20); // up to 256k
+
+// TX Done/Busy Information
+__SINIC_VAL64(TxDone_Complete, 63, 1);
+__SINIC_VAL64(TxDone_FifoLen, 20, 8); // up to 255 packets
+__SINIC_VAL64(TxDone_CopyLen, 0, 20); // up to 256k
+
+inline int
+regSize(int offset)
+{
+ static const char sizes[] = {
+ 4,
+ 4,
+ 4,
+ 4,
+ 4,
+ 4,
+ 4,
+ 0,
+ 8, 0,
+ 8, 0,
+ 8, 0,
+ 8, 0,
+ 8, 0,
+ 8, 0,
+ 8, 0
+ };
+
+ if (offset & 0x3)
+ return 0;
+
+ if (offset >= Size)
+ return 0;
+
+ return sizes[offset / 4];
+}
+
+inline const char *
+regName(int offset)
+{
+ static const char *names[] = {
+ "Config",
+ "RxMaxCopy",
+ "TxMaxCopy",
+ "RxThreshold",
+ "TxThreshold",
+ "IntrStatus",
+ "IntrMask",
+ "invalid",
+ "RxData", "invalid",
+ "RxDone", "invalid",
+ "RxWait", "invalid",
+ "TxData", "invalid",
+ "TxDone", "invalid",
+ "TxWait", "invalid",
+ "HwAddr", "invalid"
+ };
+
+ if (offset & 0x3)
+ return "invalid";
+
+ if (offset >= Size)
+ return "invalid";
+
+ return names[offset / 4];
+}
+
+/* namespace Regs */ }
+/* namespace Sinic */ }
+
+#endif // __DEV_SINICREG_HH__
diff --git a/dev/tsunami.cc b/dev/tsunami.cc
index c44da69b7..f98254354 100644
--- a/dev/tsunami.cc
+++ b/dev/tsunami.cc
@@ -75,6 +75,24 @@ Tsunami::clearConsoleInt()
}
void
+Tsunami::postPciInt(int line)
+{
+ cchip->postDRIR(line);
+}
+
+void
+Tsunami::clearPciInt(int line)
+{
+ cchip->clearDRIR(line);
+}
+
+Addr
+Tsunami::pciToDma(Addr pciAddr) const
+{
+ return pchip->translatePciToDma(pciAddr);
+}
+
+void
Tsunami::serialize(std::ostream &os)
{
SERIALIZE_ARRAY(intr_sum_type, Tsunami::Max_CPUs);
diff --git a/dev/tsunami.hh b/dev/tsunami.hh
index db266d62d..d7c549e90 100644
--- a/dev/tsunami.hh
+++ b/dev/tsunami.hh
@@ -58,16 +58,13 @@ class Tsunami : public Platform
public:
/** Max number of CPUs in a Tsunami */
- static const int Max_CPUs = 4;
+ static const int Max_CPUs = 64;
/** Pointer to the system */
System *system;
+
/** Pointer to the TsunamiIO device which has the RTC */
TsunamiIO *io;
- /** Pointer to the disk controller device */
- IdeController *disk_controller;
- /** Pointer to the ethernet controller device */
- NSGigE *ethernet;
/** Pointer to the Tsunami CChip.
* The chip contains some configuration information and
@@ -112,6 +109,18 @@ class Tsunami : public Platform
virtual void clearConsoleInt();
/**
+ * Cause the chipset to post a cpi interrupt to the CPU.
+ */
+ virtual void postPciInt(int line);
+
+ /**
+ * Clear a posted PCI->CPU interrupt
+ */
+ virtual void clearPciInt(int line);
+
+ virtual Addr pciToDma(Addr pciAddr) const;
+
+ /**
* Serialize this object to the given output stream.
* @param os The stream to serialize to.
*/
diff --git a/dev/tsunami_cchip.cc b/dev/tsunami_cchip.cc
index 870924a2f..a1f900153 100644
--- a/dev/tsunami_cchip.cc
+++ b/dev/tsunami_cchip.cc
@@ -53,25 +53,24 @@ TsunamiCChip::TsunamiCChip(const string &name, Tsunami *t, Addr a,
Tick pio_latency)
: PioDevice(name), addr(a), tsunami(t)
{
- mmu->add_child(this, Range<Addr>(addr, addr + size));
-
- for(int i=0; i < Tsunami::Max_CPUs; i++) {
- dim[i] = 0;
- dir[i] = 0;
- dirInterrupting[i] = false;
- ipiInterrupting[i] = false;
- RTCInterrupting[i] = false;
- }
+ mmu->add_child(this, RangeSize(addr, size));
if (bus) {
pioInterface = newPioInterface(name, hier, bus, this,
&TsunamiCChip::cacheAccess);
- pioInterface->addAddrRange(addr, addr + size - 1);
+ pioInterface->addAddrRange(RangeSize(addr, size));
pioLatency = pio_latency * bus->clockRatio;
}
drir = 0;
- misc = 0;
+ ipint = 0;
+ itint = 0;
+
+ for (int x = 0; x < Tsunami::Max_CPUs; x++)
+ {
+ dim[x] = 0;
+ dir[x] = 0;
+ }
//Put back pointer in tsunami
tsunami->cchip = this;
@@ -80,16 +79,29 @@ TsunamiCChip::TsunamiCChip(const string &name, Tsunami *t, Addr a,
Fault
TsunamiCChip::read(MemReqPtr &req, uint8_t *data)
{
- DPRINTF(Tsunami, "read va=%#x size=%d\n",
- req->vaddr, req->size);
+ DPRINTF(Tsunami, "read va=%#x size=%d\n", req->vaddr, req->size);
+
+ Addr regnum = (req->paddr - (addr & EV5::PAddrImplMask)) >> 6;
+ Addr daddr = (req->paddr - (addr & EV5::PAddrImplMask));
- Addr daddr = (req->paddr - (addr & PA_IMPL_MASK)) >> 6;
ExecContext *xc = req->xc;
switch (req->size) {
case sizeof(uint64_t):
- switch(daddr) {
+ if (daddr & TSDEV_CC_BDIMS)
+ {
+ *(uint64_t*)data = dim[(daddr >> 4) & 0x3F];
+ return No_Fault;
+ }
+
+ if (daddr & TSDEV_CC_BDIRS)
+ {
+ *(uint64_t*)data = dir[(daddr >> 4) & 0x3F];
+ return No_Fault;
+ }
+
+ switch(regnum) {
case TSDEV_CC_CSR:
*(uint64_t*)data = 0x0;
return No_Fault;
@@ -97,7 +109,9 @@ TsunamiCChip::read(MemReqPtr &req, uint8_t *data)
panic("TSDEV_CC_MTR not implemeted\n");
return No_Fault;
case TSDEV_CC_MISC:
- *(uint64_t*)data = misc | (xc->cpu_id & 0x3);
+ *(uint64_t*)data = (ipint << 8) & 0xF |
+ (itint << 4) & 0xF |
+ (xc->cpu_id & 0x3);
return No_Fault;
case TSDEV_CC_AAR0:
case TSDEV_CC_AAR1:
@@ -147,6 +161,12 @@ TsunamiCChip::read(MemReqPtr &req, uint8_t *data)
case TSDEV_CC_MPR3:
panic("TSDEV_CC_MPRx not implemented\n");
return No_Fault;
+ case TSDEV_CC_IPIR:
+ *(uint64_t*)data = ipint;
+ return No_Fault;
+ case TSDEV_CC_ITIR:
+ *(uint64_t*)data = itint;
+ return No_Fault;
default:
panic("default in cchip read reached, accessing 0x%x\n");
} // uint64_t
@@ -158,7 +178,7 @@ TsunamiCChip::read(MemReqPtr &req, uint8_t *data)
default:
panic("invalid access size(?) for tsunami register!\n");
}
- DPRINTFN("Tsunami CChip ERROR: read daddr=%#x size=%d\n", daddr, req->size);
+ DPRINTFN("Tsunami CChip ERROR: read regnum=%#x size=%d\n", regnum, req->size);
return No_Fault;
}
@@ -169,73 +189,95 @@ TsunamiCChip::write(MemReqPtr &req, const uint8_t *data)
DPRINTF(Tsunami, "write - va=%#x value=%#x size=%d \n",
req->vaddr, *(uint64_t*)data, req->size);
- Addr daddr = (req->paddr - (addr & PA_IMPL_MASK)) >> 6;
+ Addr daddr = (req->paddr - (addr & EV5::PAddrImplMask));
+ Addr regnum = (req->paddr - (addr & EV5::PAddrImplMask)) >> 6;
bool supportedWrite = false;
- uint64_t size = tsunami->intrctrl->cpu->system->execContexts.size();
switch (req->size) {
case sizeof(uint64_t):
- switch(daddr) {
- case TSDEV_CC_CSR:
+ 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);
+
+ }
+
+
+ }
+ }
+ return No_Fault;
+ }
+
+ switch(regnum) {
+ case TSDEV_CC_CSR:
panic("TSDEV_CC_CSR write\n");
return No_Fault;
case TSDEV_CC_MTR:
panic("TSDEV_CC_MTR write not implemented\n");
return No_Fault;
case TSDEV_CC_MISC:
- //If it is the 4-7th bit, clear the RTC interrupt
- uint64_t itintr;
- if ((itintr = (*(uint64_t*) data) & (0xf<<4))) {
- //Clear the bits in ITINTR
- misc &= ~(itintr);
- for (int i=0; i < size; i++) {
- if ((itintr & (1 << (i+4))) && RTCInterrupting[i]) {
- tsunami->intrctrl->clear(i, TheISA::INTLEVEL_IRQ2, 0);
- RTCInterrupting[i] = false;
- DPRINTF(Tsunami, "clearing rtc interrupt to cpu=%d\n", i);
- }
- }
- supportedWrite = true;
- }
- //If it is 12th-15th bit, IPI sent to Processor 1
uint64_t ipreq;
- if ((ipreq = (*(uint64_t*) data) & (0xf << 12))) {
- //Set the bits in IPINTR
- misc |= (ipreq >> 4);
- for (int i=0; i < size; i++) {
- if ((ipreq & (1 << (i + 12)))) {
- if (!ipiInterrupting[i])
- tsunami->intrctrl->post(i, TheISA::INTLEVEL_IRQ3, 0);
- ipiInterrupting[i]++;
- DPRINTF(IPI, "send cpu=%d pending=%d from=%d\n", i,
- ipiInterrupting[i], req->cpu_num);
- }
- }
+ ipreq = (*(uint64_t*)data >> 12) & 0xF;
+ //If it is bit 12-15, this is an IPI post
+ if (ipreq) {
+ reqIPI(ipreq);
supportedWrite = true;
}
- //If it is bits 8-11, then clearing IPI's
+
+ //If it is bit 8-11, this is an IPI clear
uint64_t ipintr;
- if ((ipintr = (*(uint64_t*) data) & (0xf << 8))) {
- //Clear the bits in IPINTR
- misc &= ~(ipintr);
- for (int i=0; i < size; i++) {
- if ((ipintr & (1 << (i + 8))) && ipiInterrupting[i]) {
- if (!(--ipiInterrupting[i]))
- tsunami->intrctrl->clear(i, TheISA::INTLEVEL_IRQ3, 0);
- DPRINTF(IPI, "clearing cpu=%d pending=%d from=%d\n", i,
- ipiInterrupting[i] + 1, req->cpu_num);
- }
- }
+ 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;
+ // ignore NXMs
+ if (*(uint64_t*)data & 0x10000000)
+ supportedWrite = true;
+
+ if(!supportedWrite)
+ panic("TSDEV_CC_MISC write not implemented\n");
- if(!supportedWrite) panic("TSDEV_CC_MISC write not implemented\n");
return No_Fault;
case TSDEV_CC_AAR0:
case TSDEV_CC_AAR1:
@@ -248,11 +290,11 @@ TsunamiCChip::write(MemReqPtr &req, const uint8_t *data)
case TSDEV_CC_DIM2:
case TSDEV_CC_DIM3:
int number;
- if(daddr == TSDEV_CC_DIM0)
+ if(regnum == TSDEV_CC_DIM0)
number = 0;
- else if(daddr == TSDEV_CC_DIM1)
+ else if(regnum == TSDEV_CC_DIM1)
number = 1;
- else if(daddr == TSDEV_CC_DIM2)
+ else if(regnum == TSDEV_CC_DIM2)
number = 2;
else
number = 3;
@@ -267,7 +309,7 @@ TsunamiCChip::write(MemReqPtr &req, const uint8_t *data)
dir[number] = dim[number] & drir;
for(int x = 0; x < 64; x++)
{
- bitvector = (uint64_t)1 << x;
+ bitvector = ULL(1) << x;
// Figure out which bits have changed
if ((dim[number] & bitvector) != (olddim & bitvector))
{
@@ -284,7 +326,8 @@ TsunamiCChip::write(MemReqPtr &req, const uint8_t *data)
// 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 0\n");
+ " dir interrupt to cpu %d\n",
+ x);
}
@@ -311,6 +354,15 @@ TsunamiCChip::write(MemReqPtr &req, const uint8_t *data)
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 No_Fault;
+ case TSDEV_CC_ITIR:
+ clearITI(*(uint64_t*)data);
+ return No_Fault;
+ case TSDEV_CC_IPIQ:
+ reqIPI(*(uint64_t*)data);
+ return No_Fault;
default:
panic("default in cchip read reached, accessing 0x%x\n");
}
@@ -329,14 +381,88 @@ TsunamiCChip::write(MemReqPtr &req, const uint8_t *data)
}
void
+TsunamiCChip::clearIPI(uint64_t ipintr)
+{
+ int numcpus = tsunami->intrctrl->cpu->system->execContexts.size();
+ assert(numcpus <= Tsunami::Max_CPUs);
+
+ if (ipintr) {
+ for (int cpunum=0; cpunum < numcpus; cpunum++) {
+ // Check each cpu bit
+ uint64_t cpumask = ULL(1) << cpunum;
+ if (ipintr & cpumask) {
+ // Check if there is a pending ipi
+ if (ipint & cpumask) {
+ ipint &= ~cpumask;
+ tsunami->intrctrl->clear(cpunum, TheISA::INTLEVEL_IRQ3, 0);
+ DPRINTF(IPI, "clear IPI IPI cpu=%d\n", cpunum);
+ }
+ else
+ warn("clear IPI for CPU=%d, but NO IPI\n", cpunum);
+ }
+ }
+ }
+ else
+ panic("Big IPI Clear, but not processors indicated\n");
+}
+
+void
+TsunamiCChip::clearITI(uint64_t itintr)
+{
+ int numcpus = tsunami->intrctrl->cpu->system->execContexts.size();
+ assert(numcpus <= Tsunami::Max_CPUs);
+
+ if (itintr) {
+ for (int i=0; i < numcpus; i++) {
+ uint64_t cpumask = ULL(1) << i;
+ if (itintr & cpumask & itint) {
+ tsunami->intrctrl->clear(i, TheISA::INTLEVEL_IRQ2, 0);
+ itint &= ~cpumask;
+ DPRINTF(Tsunami, "clearing rtc interrupt to cpu=%d\n", i);
+ }
+ }
+ }
+ else
+ panic("Big ITI Clear, but not processors indicated\n");
+}
+
+void
+TsunamiCChip::reqIPI(uint64_t ipreq)
+{
+ int numcpus = tsunami->intrctrl->cpu->system->execContexts.size();
+ assert(numcpus <= Tsunami::Max_CPUs);
+
+ if (ipreq) {
+ for (int cpunum=0; cpunum < numcpus; cpunum++) {
+ // Check each cpu bit
+ uint64_t cpumask = ULL(1) << cpunum;
+ if (ipreq & cpumask) {
+ // Check if there is already an ipi (bits 8:11)
+ if (!(ipint & cpumask)) {
+ ipint |= cpumask;
+ tsunami->intrctrl->post(cpunum, TheISA::INTLEVEL_IRQ3, 0);
+ DPRINTF(IPI, "send IPI cpu=%d\n", cpunum);
+ }
+ else
+ warn("post IPI for CPU=%d, but IPI already\n", cpunum);
+ }
+ }
+ }
+ else
+ panic("Big IPI Request, but not processors indicated\n");
+}
+
+
+void
TsunamiCChip::postRTC()
{
int size = tsunami->intrctrl->cpu->system->execContexts.size();
+ assert(size <= Tsunami::Max_CPUs);
for (int i = 0; i < size; i++) {
- if (!RTCInterrupting[i]) {
- misc |= 16 << i;
- RTCInterrupting[i] = true;
+ 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);
}
@@ -347,9 +473,11 @@ TsunamiCChip::postRTC()
void
TsunamiCChip::postDRIR(uint32_t interrupt)
{
- uint64_t bitvector = (uint64_t)0x1 << interrupt;
- drir |= bitvector;
+ uint64_t bitvector = ULL(1) << interrupt;
uint64_t size = tsunami->intrctrl->cpu->system->execContexts.size();
+ assert(size <= Tsunami::Max_CPUs);
+ drir |= bitvector;
+
for(int i=0; i < size; i++) {
dir[i] = dim[i] & drir;
if (dim[i] & bitvector) {
@@ -363,8 +491,10 @@ TsunamiCChip::postDRIR(uint32_t interrupt)
void
TsunamiCChip::clearDRIR(uint32_t interrupt)
{
- uint64_t bitvector = (uint64_t)0x1 << interrupt;
+ uint64_t bitvector = ULL(1) << interrupt;
uint64_t size = tsunami->intrctrl->cpu->system->execContexts.size();
+ assert(size <= Tsunami::Max_CPUs);
+
if (drir & bitvector)
{
drir &= ~bitvector;
@@ -394,11 +524,9 @@ TsunamiCChip::serialize(std::ostream &os)
{
SERIALIZE_ARRAY(dim, Tsunami::Max_CPUs);
SERIALIZE_ARRAY(dir, Tsunami::Max_CPUs);
- SERIALIZE_ARRAY(dirInterrupting, Tsunami::Max_CPUs);
- SERIALIZE_ARRAY(ipiInterrupting, Tsunami::Max_CPUs);
+ SERIALIZE_SCALAR(ipint);
+ SERIALIZE_SCALAR(itint);
SERIALIZE_SCALAR(drir);
- SERIALIZE_SCALAR(misc);
- SERIALIZE_ARRAY(RTCInterrupting, Tsunami::Max_CPUs);
}
void
@@ -406,11 +534,9 @@ TsunamiCChip::unserialize(Checkpoint *cp, const std::string &section)
{
UNSERIALIZE_ARRAY(dim, Tsunami::Max_CPUs);
UNSERIALIZE_ARRAY(dir, Tsunami::Max_CPUs);
- UNSERIALIZE_ARRAY(dirInterrupting, Tsunami::Max_CPUs);
- UNSERIALIZE_ARRAY(ipiInterrupting, Tsunami::Max_CPUs);
+ UNSERIALIZE_SCALAR(ipint);
+ UNSERIALIZE_SCALAR(itint);
UNSERIALIZE_SCALAR(drir);
- UNSERIALIZE_SCALAR(misc);
- UNSERIALIZE_ARRAY(RTCInterrupting, Tsunami::Max_CPUs);
}
BEGIN_DECLARE_SIM_OBJECT_PARAMS(TsunamiCChip)
diff --git a/dev/tsunami_cchip.hh b/dev/tsunami_cchip.hh
index 3269cf53a..05fafa782 100644
--- a/dev/tsunami_cchip.hh
+++ b/dev/tsunami_cchip.hh
@@ -47,7 +47,7 @@ class TsunamiCChip : public PioDevice
Addr addr;
/** The size of mappad from the above address */
- static const Addr size = 0xfff;
+ static const Addr size = 0xfffffff;
protected:
/**
@@ -68,7 +68,6 @@ class TsunamiCChip : public PioDevice
* One exists for each CPU, the DRIR X DIM = DIR
*/
uint64_t dir[Tsunami::Max_CPUs];
- bool dirInterrupting[Tsunami::Max_CPUs];
/**
* This register contains bits for each PCI interrupt
@@ -76,17 +75,11 @@ class TsunamiCChip : public PioDevice
*/
uint64_t drir;
- /**
- * The MISC register contains the CPU we are currently on
- * as well as bits to ack RTC and IPI interrupts.
- */
- uint64_t misc;
+ /** Indicator of which CPUs have an IPI interrupt */
+ uint64_t ipint;
- /** Count of the number of pending IPIs on a CPU */
- uint64_t ipiInterrupting[Tsunami::Max_CPUs];
-
- /** Indicator of which CPUs have had an RTC interrupt */
- bool RTCInterrupting[Tsunami::Max_CPUs];
+ /** Indicator of which CPUs have an RTC interrupt */
+ uint64_t itint;
public:
/**
@@ -138,6 +131,25 @@ class TsunamiCChip : public PioDevice
void clearDRIR(uint32_t interrupt);
/**
+ * post an ipi interrupt to the CPU.
+ * @param ipintr the cpu number to clear(bitvector)
+ */
+ void clearIPI(uint64_t ipintr);
+
+ /**
+ * clear a timer interrupt previously posted to the CPU.
+ * @param interrupt the cpu number to clear(bitvector)
+ */
+ void clearITI(uint64_t itintr);
+
+ /**
+ * request an interrupt be posted to the CPU.
+ * @param ipreq the cpu number to interrupt(bitvector)
+ */
+ void reqIPI(uint64_t ipreq);
+
+
+ /**
* Serialize this object to the given output stream.
* @param os The stream to serialize to.
*/
diff --git a/dev/tsunami_io.cc b/dev/tsunami_io.cc
index 105e3b5b7..51ff8b81c 100644
--- a/dev/tsunami_io.cc
+++ b/dev/tsunami_io.cc
@@ -164,12 +164,12 @@ TsunamiIO::TsunamiIO(const string &name, Tsunami *t, time_t init_time,
Tick pio_latency)
: PioDevice(name), addr(a), tsunami(t), rtc(t)
{
- mmu->add_child(this, Range<Addr>(addr, addr + size));
+ mmu->add_child(this, RangeSize(addr, size));
if (bus) {
pioInterface = newPioInterface(name, hier, bus, this,
&TsunamiIO::cacheAccess);
- pioInterface->addAddrRange(addr, addr + size - 1);
+ pioInterface->addAddrRange(RangeSize(addr, size));
pioLatency = pio_latency * bus->clockRatio;
}
@@ -196,7 +196,7 @@ TsunamiIO::read(MemReqPtr &req, uint8_t *data)
DPRINTF(Tsunami, "io read va=%#x size=%d IOPorrt=%#x\n",
req->vaddr, req->size, req->vaddr & 0xfff);
- Addr daddr = (req->paddr - (addr & PA_IMPL_MASK));
+ Addr daddr = (req->paddr - (addr & EV5::PAddrImplMask));
switch(req->size) {
@@ -298,7 +298,7 @@ TsunamiIO::write(MemReqPtr &req, const uint8_t *data)
DPRINTF(Tsunami, "io write - va=%#x size=%d IOPort=%#x Data=%#x\n",
req->vaddr, req->size, req->vaddr & 0xfff, dt64);
- Addr daddr = (req->paddr - (addr & PA_IMPL_MASK));
+ Addr daddr = (req->paddr - (addr & EV5::PAddrImplMask));
switch(req->size) {
case sizeof(uint8_t):
diff --git a/dev/tsunami_pchip.cc b/dev/tsunami_pchip.cc
index 89940fb5a..9af19d930 100644
--- a/dev/tsunami_pchip.cc
+++ b/dev/tsunami_pchip.cc
@@ -53,7 +53,7 @@ TsunamiPChip::TsunamiPChip(const string &name, Tsunami *t, Addr a,
Bus *bus, Tick pio_latency)
: PioDevice(name), addr(a), tsunami(t)
{
- mmu->add_child(this, Range<Addr>(addr, addr + size));
+ mmu->add_child(this, RangeSize(addr, size));
for (int i = 0; i < 4; i++) {
wsba[i] = 0;
@@ -64,7 +64,7 @@ TsunamiPChip::TsunamiPChip(const string &name, Tsunami *t, Addr a,
if (bus) {
pioInterface = newPioInterface(name, hier, bus, this,
&TsunamiPChip::cacheAccess);
- pioInterface->addAddrRange(addr, addr + size - 1);
+ pioInterface->addAddrRange(RangeSize(addr, size));
pioLatency = pio_latency * bus->clockRatio;
}
@@ -82,7 +82,7 @@ TsunamiPChip::read(MemReqPtr &req, uint8_t *data)
DPRINTF(Tsunami, "read va=%#x size=%d\n",
req->vaddr, req->size);
- Addr daddr = (req->paddr - (addr & PA_IMPL_MASK)) >> 6;
+ Addr daddr = (req->paddr - (addr & EV5::PAddrImplMask)) >> 6;
switch (req->size) {
@@ -171,7 +171,7 @@ TsunamiPChip::write(MemReqPtr &req, const uint8_t *data)
DPRINTF(Tsunami, "write - va=%#x size=%d \n",
req->vaddr, req->size);
- Addr daddr = (req->paddr - (addr & PA_IMPL_MASK)) >> 6;
+ Addr daddr = (req->paddr - (addr & EV5::PAddrImplMask)) >> 6;
switch (req->size) {
diff --git a/dev/tsunamireg.h b/dev/tsunamireg.h
index 876c6bf18..3304082a5 100644
--- a/dev/tsunamireg.h
+++ b/dev/tsunamireg.h
@@ -60,6 +60,13 @@
#define TSDEV_CC_IIC2 0x1C
#define TSDEV_CC_IIC3 0x1D
+// BigTsunami Registers
+#define TSDEV_CC_BDIMS 0x1000000
+#define TSDEV_CC_BDIRS 0x2000000
+#define TSDEV_CC_IPIQ 0x20 //0xf01a000800
+#define TSDEV_CC_IPIR 0x21 //0xf01a000840
+#define TSDEV_CC_ITIR 0x22 //0xf01a000880
+
// PChip Registers
#define TSDEV_PC_WSBA0 0x00
diff --git a/dev/uart.cc b/dev/uart.cc
index fca856d5d..2ff94dda5 100644
--- a/dev/uart.cc
+++ b/dev/uart.cc
@@ -44,7 +44,6 @@
#include "mem/bus/pio_interface_impl.hh"
#include "mem/functional_mem/memory_control.hh"
#include "sim/builder.hh"
-#include "targetarch/ev5.hh"
using namespace std;
@@ -92,13 +91,13 @@ Uart::Uart(const string &name, SimConsole *c, MemoryController *mmu, Addr a,
: PioDevice(name), addr(a), size(s), cons(c), txIntrEvent(this, TX_INT),
rxIntrEvent(this, RX_INT), platform(p)
{
- mmu->add_child(this, Range<Addr>(addr, addr + size));
+ mmu->add_child(this, RangeSize(addr, size));
if (bus) {
pioInterface = newPioInterface(name, hier, bus, this,
&Uart::cacheAccess);
- pioInterface->addAddrRange(addr, addr + size - 1);
+ pioInterface->addAddrRange(RangeSize(addr, size));
pioLatency = pio_latency * bus->clockRatio;
}
@@ -118,7 +117,7 @@ Uart::Uart(const string &name, SimConsole *c, MemoryController *mmu, Addr a,
Fault
Uart::read(MemReqPtr &req, uint8_t *data)
{
- Addr daddr = req->paddr - (addr & PA_IMPL_MASK);
+ Addr daddr = req->paddr - (addr & EV5::PAddrImplMask);
DPRINTF(Uart, " read register %#x\n", daddr);
@@ -246,7 +245,7 @@ Uart::read(MemReqPtr &req, uint8_t *data)
Fault
Uart::write(MemReqPtr &req, const uint8_t *data)
{
- Addr daddr = req->paddr - (addr & PA_IMPL_MASK);
+ Addr daddr = req->paddr - (addr & EV5::PAddrImplMask);
DPRINTF(Uart, " write register %#x value %#x\n", daddr, *(uint8_t*)data);
@@ -287,7 +286,7 @@ Uart::write(MemReqPtr &req, const uint8_t *data)
switch (daddr) {
case 0x0:
if (!(LCR & 0x80)) { // write byte
- cons->out(*(uint64_t *)data);
+ cons->out(*(uint8_t *)data);
platform->clearConsoleInt();
status &= ~TX_INT;
if (UART_IER_THRI & IER)
diff --git a/kern/kernel_stats.cc b/kern/kernel_stats.cc
index e6bcb4d29..ed0b613ff 100644
--- a/kern/kernel_stats.cc
+++ b/kern/kernel_stats.cc
@@ -30,134 +30,84 @@
#include <stack>
#include <string>
-#include "base/statistics.hh"
+#include "arch/alpha/osfpal.hh"
#include "base/trace.hh"
+#include "base/statistics.hh"
+#include "base/stats/bin.hh"
#include "cpu/exec_context.hh"
+#include "cpu/pc_event.hh"
+#include "cpu/static_inst.hh"
#include "kern/kernel_stats.hh"
-#include "sim/stats.hh"
-#include "sim/sw_context.hh"
-#include "targetarch/isa_traits.hh"
-#include "targetarch/osfpal.hh"
-#include "targetarch/syscalls.hh"
+#include "kern/linux/linux_syscalls.hh"
+#include "kern/tru64/tru64_syscalls.hh"
using namespace std;
using namespace Stats;
-class KSData
-{
- private:
- string _name;
- ExecContext *xc;
- BaseCPU *cpu;
-
- public:
- KSData(ExecContext *_xc, BaseCPU *_cpu)
- : xc(_xc), cpu(_cpu), iplLast(0), iplLastTick(0), lastUser(false),
- lastModeTick(0)
- {}
-
- const string &name() { return _name; }
- void regStats(const string &name);
-
- public:
- Scalar<> _arm;
- Scalar<> _quiesce;
- Scalar<> _ivlb;
- Scalar<> _ivle;
- Scalar<> _hwrei;
-
- Vector<> _iplCount;
- Vector<> _iplGood;
- Vector<> _iplTicks;
- Formula _iplUsed;
-
- Vector<> _callpal;
- Vector<> _syscall;
- Vector<> _faults;
-
- Vector<> _mode;
- Vector<> _modeGood;
- Formula _modeFraction;
- Vector<> _modeTicks;
-
- Scalar<> _swap_context;
-
- private:
- int iplLast;
- Tick iplLastTick;
-
- bool lastUser;
- Tick lastModeTick;
-
- public:
- void swpipl(int ipl);
- void mode(bool user);
- void callpal(int code);
-};
-
-KernelStats::KernelStats(ExecContext *xc, BaseCPU *cpu)
-{ data = new KSData(xc, cpu); }
-
-KernelStats::~KernelStats()
-{ delete data; }
+namespace Kernel {
-void
-KernelStats::regStats(const string &name)
-{ data->regStats(name); }
+const char *modestr[] = { "kernel", "user", "idle", "interrupt" };
+
+Statistics::Statistics(ExecContext *context)
+ : xc(context), idleProcess((Addr)-1), themode(kernel), lastModeTick(0),
+ iplLast(0), iplLastTick(0)
+{
+ bin_int = xc->system->params->bin_int;
+}
void
-KSData::regStats(const string &name)
+Statistics::regStats(const string &_name)
{
- _name = name;
+ myname = _name;
_arm
- .name(name + ".inst.arm")
+ .name(name() + ".inst.arm")
.desc("number of arm instructions executed")
;
_quiesce
- .name(name + ".inst.quiesce")
+ .name(name() + ".inst.quiesce")
.desc("number of quiesce instructions executed")
;
_ivlb
- .name(name + ".inst.ivlb")
+ .name(name() + ".inst.ivlb")
.desc("number of ivlb instructions executed")
;
_ivle
- .name(name + ".inst.ivle")
+ .name(name() + ".inst.ivle")
.desc("number of ivle instructions executed")
;
_hwrei
- .name(name + ".inst.hwrei")
+ .name(name() + ".inst.hwrei")
.desc("number of hwrei instructions executed")
;
_iplCount
.init(32)
- .name(name + ".ipl_count")
+ .name(name() + ".ipl_count")
.desc("number of times we switched to this ipl")
.flags(total | pdf | nozero | nonan)
;
_iplGood
.init(32)
- .name(name + ".ipl_good")
+ .name(name() + ".ipl_good")
.desc("number of times we switched to this ipl from a different ipl")
.flags(total | pdf | nozero | nonan)
;
_iplTicks
.init(32)
- .name(name + ".ipl_ticks")
+ .name(name() + ".ipl_ticks")
.desc("number of cycles we spent at this ipl")
.flags(total | pdf | nozero | nonan)
;
_iplUsed
- .name(name + ".ipl_used")
+ .name(name() + ".ipl_used")
.desc("fraction of swpipl calls that actually changed the ipl")
.flags(total | nozero | nonan)
;
@@ -166,7 +116,7 @@ KSData::regStats(const string &name)
_callpal
.init(256)
- .name(name + ".callpal")
+ .name(name() + ".callpal")
.desc("number of callpals executed")
.flags(total | pdf | nozero | nonan)
;
@@ -179,7 +129,7 @@ KSData::regStats(const string &name)
_syscall
.init(SystemCalls<Tru64>::Number)
- .name(name + ".syscall")
+ .name(name() + ".syscall")
.desc("number of syscalls executed")
.flags(total | pdf | nozero | nonan)
;
@@ -193,7 +143,7 @@ KSData::regStats(const string &name)
_faults
.init(Num_Faults)
- .name(name + ".faults")
+ .name(name() + ".faults")
.desc("number of faults")
.flags(total | pdf | nozero | nonan)
;
@@ -205,85 +155,79 @@ KSData::regStats(const string &name)
}
_mode
- .init(2)
- .name(name + ".mode_switch")
- .subname(0, "kernel")
- .subname(1, "user")
+ .init(cpu_mode_num)
+ .name(name() + ".mode_switch")
.desc("number of protection mode switches")
;
+ for (int i = 0; i < cpu_mode_num; ++i)
+ _mode.subname(i, modestr[i]);
+
_modeGood
- .init(2)
- .name(name + ".mode_good")
+ .init(cpu_mode_num)
+ .name(name() + ".mode_good")
;
+ for (int i = 0; i < cpu_mode_num; ++i)
+ _modeGood.subname(i, modestr[i]);
+
_modeFraction
- .name(name + ".mode_switch_good")
- .subname(0, "kernel")
- .subname(1, "user")
+ .name(name() + ".mode_switch_good")
.desc("fraction of useful protection mode switches")
.flags(total)
;
+
+ for (int i = 0; i < cpu_mode_num; ++i)
+ _modeFraction.subname(i, modestr[i]);
+
_modeFraction = _modeGood / _mode;
_modeTicks
- .init(2)
- .name(name + ".mode_ticks")
- .subname(0, "kernel")
- .subname(1, "user")
+ .init(cpu_mode_num)
+ .name(name() + ".mode_ticks")
.desc("number of ticks spent at the given mode")
.flags(pdf)
;
+ for (int i = 0; i < cpu_mode_num; ++i)
+ _modeTicks.subname(i, modestr[i]);
_swap_context
- .name(name + ".swap_context")
+ .name(name() + ".swap_context")
.desc("number of times the context was actually changed")
;
}
void
-KernelStats::arm()
-{ data->_arm++; }
-
-void
-KernelStats::quiesce()
-{ data->_quiesce++; }
-
-void
-KernelStats::ivlb()
-{ data->_ivlb++; }
-
-void
-KernelStats::ivle()
-{ data->_ivle++; }
-
-void
-KernelStats::hwrei()
-{ data->_hwrei++; }
+Statistics::setIdleProcess(Addr idlepcbb)
+{
+ assert(themode == kernel || themode == interrupt);
+ idleProcess = idlepcbb;
+ themode = idle;
+ changeMode(themode);
+}
void
-KernelStats::fault(Fault fault)
-{ data->_faults[fault]++; }
+Statistics::changeMode(cpu_mode newmode)
+{
+ _mode[newmode]++;
-void
-KernelStats::swpipl(int ipl)
-{ data->swpipl(ipl); }
+ if (newmode == themode)
+ return;
-void
-KernelStats::mode(bool user)
-{ data->mode(user); }
+ DPRINTF(Context, "old mode=%-8s new mode=%-8s\n",
+ modestr[themode], modestr[newmode]);
-void
-KernelStats::context(Addr old_pcbb, Addr new_pcbb)
-{ data->_swap_context++; }
+ _modeGood[newmode]++;
+ _modeTicks[themode] += curTick - lastModeTick;
-void
-KernelStats::callpal(int code)
-{ data->callpal(code); }
+ xc->system->kernelBinning->changeMode(newmode);
+ lastModeTick = curTick;
+ themode = newmode;
+}
void
-KSData::swpipl(int ipl)
+Statistics::swpipl(int ipl)
{
assert(ipl >= 0 && ipl <= 0x1f && "invalid IPL\n");
@@ -299,30 +243,31 @@ KSData::swpipl(int ipl)
}
void
-KSData::mode(bool user)
+Statistics::mode(cpu_mode newmode)
{
- _mode[user]++;
- if (user == lastUser)
- return;
+ Addr pcbb = xc->regs.ipr[AlphaISA::IPR_PALtemp23];
- _modeGood[user]++;
- _modeTicks[lastUser] += curTick - lastModeTick;
+ if ((newmode == kernel || newmode == interrupt) &&
+ pcbb == idleProcess)
+ newmode = idle;
- lastModeTick = curTick;
- lastUser = user;
-
- if (xc->system->bin) {
- if (!xc->swCtx || xc->swCtx->callStack.empty()) {
- if (user)
- xc->system->User->activate();
- else
- xc->system->Kernel->activate();
- }
- }
+ if (bin_int == false && newmode == interrupt)
+ newmode = kernel;
+
+ changeMode(newmode);
}
void
-KSData::callpal(int code)
+Statistics::context(Addr oldpcbb, Addr newpcbb)
+{
+ assert(themode != user);
+
+ _swap_context++;
+ changeMode(newpcbb == idleProcess ? idle : kernel);
+}
+
+void
+Statistics::callpal(int code)
{
if (!PAL::name(code))
return;
@@ -330,63 +275,42 @@ KSData::callpal(int code)
_callpal[code]++;
switch (code) {
- case PAL::callsys:
- {
- int number = xc->regs.intRegFile[0];
- if (SystemCalls<Tru64>::validSyscallNumber(number)) {
- int cvtnum = SystemCalls<Tru64>::convert(number);
- _syscall[cvtnum]++;
- }
- }
+ case PAL::callsys: {
+ int number = xc->regs.intRegFile[0];
+ if (SystemCalls<Tru64>::validSyscallNumber(number)) {
+ int cvtnum = SystemCalls<Tru64>::convert(number);
+ _syscall[cvtnum]++;
+ }
+ } break;
+
+ case PAL::swpctx:
+ if (xc->system->kernelBinning)
+ xc->system->kernelBinning->palSwapContext(xc);
break;
}
+}
- if (code == PAL::swpctx) {
- SWContext *out = xc->swCtx;
- System *sys = xc->system;
- if (!sys->bin)
- return;
- DPRINTF(TCPIP, "swpctx event\n");
- if (out) {
- DPRINTF(TCPIP, "swapping context out with this stack!\n");
- xc->system->dumpState(xc);
- Addr oldPCB = xc->regs.ipr[TheISA::IPR_PALtemp23];
-
- if (out->callStack.empty()) {
- DPRINTF(TCPIP, "but removing it, cuz empty!\n");
- SWContext *find = sys->findContext(oldPCB);
- if (find) {
- assert(sys->findContext(oldPCB) == out);
- sys->remContext(oldPCB);
- }
- delete out;
- } else {
- DPRINTF(TCPIP, "switching out context with pcb %#x, top fn %s\n",
- oldPCB, out->callStack.top()->name);
- if (!sys->findContext(oldPCB)) {
- if (!sys->addContext(oldPCB, out))
- panic("could not add context");
- }
- }
- }
+void
+Statistics::serialize(ostream &os)
+{
+ int exemode = themode;
+ SERIALIZE_SCALAR(exemode);
+ SERIALIZE_SCALAR(idleProcess);
+ SERIALIZE_SCALAR(iplLast);
+ SERIALIZE_SCALAR(iplLastTick);
+ SERIALIZE_SCALAR(lastModeTick);
+}
- Addr newPCB = xc->regs.intRegFile[16];
- SWContext *in = sys->findContext(newPCB);
- xc->swCtx = in;
-
- if (in) {
- assert(!in->callStack.empty() &&
- "should not be switching in empty context");
- DPRINTF(TCPIP, "swapping context in with this callstack!\n");
- xc->system->dumpState(xc);
- sys->remContext(newPCB);
- fnCall *top = in->callStack.top();
- DPRINTF(TCPIP, "switching in to pcb %#x, %s\n", newPCB, top->name);
- assert(top->myBin && "should not switch to context with no Bin");
- top->myBin->activate();
- } else {
- sys->Kernel->activate();
- }
- DPRINTF(TCPIP, "end swpctx\n");
- }
+void
+Statistics::unserialize(Checkpoint *cp, const string &section)
+{
+ int exemode;
+ UNSERIALIZE_SCALAR(exemode);
+ UNSERIALIZE_SCALAR(idleProcess);
+ UNSERIALIZE_SCALAR(iplLast);
+ UNSERIALIZE_SCALAR(iplLastTick);
+ UNSERIALIZE_SCALAR(lastModeTick);
+ themode = (cpu_mode)exemode;
}
+
+/* end namespace Kernel */ }
diff --git a/kern/kernel_stats.hh b/kern/kernel_stats.hh
index 497403762..af93eb95c 100644
--- a/kern/kernel_stats.hh
+++ b/kern/kernel_stats.hh
@@ -29,35 +29,166 @@
#ifndef __KERNEL_STATS_HH__
#define __KERNEL_STATS_HH__
+#include <map>
+#include <stack>
#include <string>
+#include <vector>
+
+#include "base/statistics.hh"
+#include "sim/serialize.hh"
+#include "targetarch/isa_traits.hh"
-class KSData;
-class ExecContext;
class BaseCPU;
+class ExecContext;
+class FnEvent;
enum Fault;
-class KernelStats
+namespace Kernel {
+
+enum cpu_mode { kernel, user, idle, interrupt, cpu_mode_num };
+extern const char *modestr[];
+
+class Binning
{
private:
- KSData *data;
+ std::string myname;
+ System *system;
+
+ private:
+ // lisa's binning stuff
+ struct fnCall
+ {
+ Stats::MainBin *myBin;
+ std::string name;
+ };
+
+ struct SWContext
+ {
+ Counter calls;
+ std::stack<fnCall *> callStack;
+ };
+
+ std::map<const std::string, Stats::MainBin *> fnBins;
+ std::map<const Addr, SWContext *> swCtxMap;
+
+ std::multimap<const std::string, std::string> callerMap;
+ void populateMap(std::string caller, std::string callee);
+
+ std::vector<FnEvent *> fnEvents;
+
+ Stats::Scalar<> fnCalls;
+
+ Stats::MainBin *getBin(const std::string &name);
+ bool findCaller(std::string, std::string) const;
+
+ SWContext *findContext(Addr pcb);
+ bool addContext(Addr pcb, SWContext *ctx)
+ {
+ return (swCtxMap.insert(std::make_pair(pcb, ctx))).second;
+ }
+
+ void remContext(Addr pcb)
+ {
+ swCtxMap.erase(pcb);
+ }
+
+ void dumpState() const;
+
+ SWContext *swctx;
+ std::vector<std::string> binned_fns;
+
+ private:
+ Stats::MainBin *modeBin[cpu_mode_num];
+
+ public:
+ const bool bin;
+ const bool fnbin;
+
+ cpu_mode themode;
+ void palSwapContext(ExecContext *xc);
+ void execute(ExecContext *xc, const StaticInstBase *inst);
+ void call(ExecContext *xc, Stats::MainBin *myBin);
+ void changeMode(cpu_mode mode);
public:
- KernelStats(ExecContext *_xc, BaseCPU *_cpu);
- ~KernelStats();
+ Binning(System *sys);
+ virtual ~Binning();
+ const std::string name() const { return myname; }
void regStats(const std::string &name);
- void arm();
- void quiesce();
- void ivlb();
- void ivle();
- void hwrei();
+ public:
+ virtual void serialize(std::ostream &os);
+ virtual void unserialize(Checkpoint *cp, const std::string &section);
+};
- void fault(Fault fault);
+class Statistics : public Serializable
+{
+ friend class Binning;
+
+ private:
+ std::string myname;
+ ExecContext *xc;
+
+ Addr idleProcess;
+ cpu_mode themode;
+ Tick lastModeTick;
+ bool bin_int;
+
+ void changeMode(cpu_mode newmode);
+
+ private:
+ Stats::Scalar<> _arm;
+ Stats::Scalar<> _quiesce;
+ Stats::Scalar<> _ivlb;
+ Stats::Scalar<> _ivle;
+ Stats::Scalar<> _hwrei;
+
+ Stats::Vector<> _iplCount;
+ Stats::Vector<> _iplGood;
+ Stats::Vector<> _iplTicks;
+ Stats::Formula _iplUsed;
+
+ Stats::Vector<> _callpal;
+ Stats::Vector<> _syscall;
+ Stats::Vector<> _faults;
+
+ Stats::Vector<> _mode;
+ Stats::Vector<> _modeGood;
+ Stats::Formula _modeFraction;
+ Stats::Vector<> _modeTicks;
+
+ Stats::Scalar<> _swap_context;
+
+ private:
+ int iplLast;
+ Tick iplLastTick;
+
+ public:
+ Statistics(ExecContext *context);
+
+ const std::string name() const { return myname; }
+ void regStats(const std::string &name);
+
+ public:
+ void arm() { _arm++; }
+ void quiesce() { _quiesce++; }
+ void ivlb() { _ivlb++; }
+ void ivle() { _ivle++; }
+ void hwrei() { _hwrei++; }
+ void fault(Fault fault) { _faults[fault]++; }
void swpipl(int ipl);
- void mode(bool user);
- void context(Addr old_pcbb, Addr new_pcbb);
+ void mode(cpu_mode newmode);
+ void context(Addr oldpcbb, Addr newpcbb);
void callpal(int code);
+
+ void setIdleProcess(Addr idle);
+
+ public:
+ virtual void serialize(std::ostream &os);
+ virtual void unserialize(Checkpoint *cp, const std::string &section);
};
+/* end namespace Kernel */ }
+
#endif // __KERNEL_STATS_HH__
diff --git a/kern/linux/aligned.hh b/kern/linux/aligned.hh
new file mode 100644
index 000000000..042f0ad2c
--- /dev/null
+++ b/kern/linux/aligned.hh
@@ -0,0 +1,21 @@
+#ifndef __KERN_LINUX_ALIGNED_HH__
+#define __KERN_LINUX_ALIGNED_HH__
+
+#include "sim/host.hh"
+#include "targetarch/isa_traits.hh"
+
+/* GCC 3.3.X has a bug in which attributes+typedefs don't work. 3.2.X is fine
+ * as in 3.4.X, but the bug is marked will not fix in 3.3.X so here is
+ * the work around.
+ */
+#if __GNUC__ == 3 && __GNUC_MINOR__ != 3
+typedef uint64_t uint64_ta __attribute__ ((aligned (8))) ;
+typedef int64_t int64_ta __attribute__ ((aligned (8))) ;
+typedef Addr Addr_a __attribute__ ((aligned (8))) ;
+#else
+#define uint64_ta uint64_t __attribute__ ((aligned (8)))
+#define int64_ta int64_t __attribute__ ((aligned (8)))
+#define Addr_a Addr __attribute__ ((aligned (8)))
+#endif /* __GNUC__ __GNUC_MINOR__ */
+
+#endif /* __KERN_LINUX_ALIGNED_HH__ */
diff --git a/kern/linux/hwrpb.hh b/kern/linux/hwrpb.hh
new file mode 100644
index 000000000..16544f196
--- /dev/null
+++ b/kern/linux/hwrpb.hh
@@ -0,0 +1,18 @@
+#ifndef __KERN_LINUX_HWRPB_HH__
+#define __KERN_LINUX_HWRPB_HH__
+
+#include "kern/linux/aligned.hh"
+
+namespace Linux {
+ struct pcb_struct {
+ uint64_ta ksp;
+ uint64_ta usp;
+ uint64_ta ptbr;
+ uint32_t pcc;
+ uint32_t asn;
+ uint64_ta unique;
+ uint64_ta flags;
+ uint64_ta res1, res2;
+ };
+}
+#endif // __KERN_LINUX_HWRPB_HH__
diff --git a/kern/linux/linux_syscalls.hh b/kern/linux/linux_syscalls.hh
index a729431a0..dee7c5fcd 100644
--- a/kern/linux/linux_syscalls.hh
+++ b/kern/linux/linux_syscalls.hh
@@ -29,11 +29,14 @@
#ifndef __LINUX_SYSCALLS_HH__
#define __LINUX_SYSCALLS_HH__
-#include "targetarch/syscalls.hh"
#include "kern/linux/linux.hh"
-struct SystemCalls<Linux>
+template <class OS>
+class SystemCalls;
+
+class SystemCalls<Linux>
{
+ public:
enum {
syscall = 0,
llseek = 1,
diff --git a/kern/linux/linux_system.cc b/kern/linux/linux_system.cc
index bc2753908..4342463c3 100644
--- a/kern/linux/linux_system.cc
+++ b/kern/linux/linux_system.cc
@@ -35,11 +35,7 @@
* up boot time.
*/
-#include "base/loader/aout_object.hh"
-#include "base/loader/elf_object.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 "cpu/base_cpu.hh"
@@ -54,90 +50,17 @@
#include "targetarch/vtophys.hh"
#include "sim/debug.hh"
-extern SymbolTable *debugSymbolTable;
-
using namespace std;
-LinuxSystem::LinuxSystem(const string _name, const uint64_t _init_param,
- MemoryController *_memCtrl, PhysicalMemory *_physmem,
- const string &kernel_path, const string &console_path,
- const string &palcode, const string &boot_osflags,
- const bool _bin, const vector<string> &_binned_fns)
- : System(_name, _init_param, _memCtrl, _physmem, _bin, _binned_fns),
- bin(_bin), binned_fns(_binned_fns)
+LinuxSystem::LinuxSystem(Params *p)
+ : System(p)
{
- kernelSymtab = new SymbolTable;
- consoleSymtab = new SymbolTable;
-
- /**
- * Load the kernel, pal, and console code into memory
- */
- // Load kernel code
- ObjectFile *kernel = createObjectFile(kernel_path);
- if (kernel == NULL)
- fatal("Could not load kernel file %s", kernel_path);
-
- // Load Console Code
- ObjectFile *console = createObjectFile(console_path);
- if (console == NULL)
- fatal("Could not load console file %s", console_path);
-
- // Load pal file
- ObjectFile *pal = createObjectFile(palcode);
- if (pal == NULL)
- fatal("Could not load PALcode file %s", palcode);
- pal->loadSections(physmem, true);
-
- // Load console file
- console->loadSections(physmem, true);
-
- // Load kernel file
- kernel->loadSections(physmem, true);
- kernelStart = kernel->textBase();
- kernelEnd = kernel->bssBase() + kernel->bssSize();
- kernelEntry = kernel->entryPoint();
-
- // load symbols
- if (!kernel->loadGlobalSymbols(kernelSymtab))
- panic("could not load kernel symbols\n");
- debugSymbolTable = kernelSymtab;
-
- if (!kernel->loadLocalSymbols(kernelSymtab))
- panic("could not load kernel local symbols\n");
-
- if (!console->loadGlobalSymbols(consoleSymtab))
- panic("could not load console symbols\n");
-
- DPRINTF(Loader, "Kernel start = %#x\n"
- "Kernel end = %#x\n"
- "Kernel entry = %#x\n",
- kernelStart, kernelEnd, kernelEntry);
-
- DPRINTF(Loader, "Kernel loaded...\n");
-
-
-#ifdef DEBUG
- kernelPanicEvent = new BreakPCEvent(&pcEventQueue, "kernel panic");
- consolePanicEvent = new BreakPCEvent(&pcEventQueue, "console panic");
-#endif
-
- skipIdeDelay50msEvent = new SkipFuncEvent(&pcEventQueue,
- "ide_delay_50ms");
-
- skipDelayLoopEvent = new LinuxSkipDelayLoopEvent(&pcEventQueue,
- "calibrate_delay");
-
- skipCacheProbeEvent = new SkipFuncEvent(&pcEventQueue,
- "determine_cpu_caches");
-
- debugPrintkEvent = new DebugPrintkEvent(&pcEventQueue, "dprintk");
-
Addr addr = 0;
/**
- * 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.
+ * 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)) {
Addr paddr = vtophys(physmem, addr);
@@ -150,19 +73,6 @@ LinuxSystem::LinuxSystem(const string _name, const uint64_t _init_param,
/**
- * Copy the osflags (kernel arguments) into the consoles memory. Presently
- * Linux does use the console service routine to get these command line
- * arguments, but we might as well make them available just in case.
- */
- 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, boot_osflags.c_str());
- }
-
- /**
* Since we aren't using a bootloader, we have to copy the kernel arguments
* directly into the kernels memory.
*/
@@ -170,32 +80,11 @@ LinuxSystem::LinuxSystem(const string _name, const uint64_t _init_param,
Addr paddr = vtophys(physmem, PARAM_ADDR);
char *commandline = (char*)physmem->dma_addr(paddr, sizeof(uint64_t));
if (commandline)
- strcpy(commandline, boot_osflags.c_str());
+ strcpy(commandline, params->boot_osflags.c_str());
}
/**
- * Set the hardware reset parameter block system type and revision
- * information to Tsunami.
- */
- if (consoleSymtab->findAddress("xxm_rpb", addr)) {
- Addr paddr = vtophys(physmem, addr);
- char *hwprb = (char *)physmem->dma_addr(paddr, sizeof(uint64_t));
-
- if (hwprb) {
- // Tsunami
- *(uint64_t*)(hwprb + 0x50) = htoa(ULL(34));
-
- // Plain DP264
- *(uint64_t*)(hwprb + 0x58) = htoa(ULL(1) << 10);
- }
- else
- panic("could not translate hwprb addr to set system type/variation\n");
-
- } else
- panic("could not find hwprb to set system type/variation\n");
-
- /**
* EV5 only supports 127 ASNs so we are going to tell the kernel that the
* paritiuclar EV6 we have only supports 127 asns.
* @todo At some point we should change ev5.hh and the palcode to support
@@ -208,55 +97,95 @@ LinuxSystem::LinuxSystem(const string _name, const uint64_t _init_param,
if (dp264_mv) {
*(uint32_t*)(dp264_mv+0x18) = htoa((uint32_t)127);
} else
- panic("could not translate dp264_mv addr to set the MAX_ASN to 127\n");
+ panic("could not translate dp264_mv addr\n");
} else
- panic("could not find dp264_mv to set the MAX_ASN to 127\n");
-
-
+ panic("could not find dp264_mv\n");
#ifdef DEBUG
+ kernelPanicEvent = new BreakPCEvent(&pcEventQueue, "kernel panic");
if (kernelSymtab->findAddress("panic", addr))
kernelPanicEvent->schedule(addr);
else
panic("could not find kernel symbol \'panic\'");
-
- if (consoleSymtab->findAddress("panic", addr))
- consolePanicEvent->schedule(addr);
#endif
/**
- * Any time ide_delay_50ms, calibarte_delay or determine_cpu_caches is called
- * just skip the function. Currently determine_cpu_caches only is used put
- * information in proc, however if that changes in the future we will have to
- * fill in the cache size variables appropriately.
+ * Any time ide_delay_50ms, calibarte_delay or
+ * determine_cpu_caches is called just skip the
+ * function. Currently determine_cpu_caches only is used put
+ * information in proc, however if that changes in the future we
+ * will have to fill in the cache size variables appropriately.
*/
+ skipIdeDelay50msEvent = new SkipFuncEvent(&pcEventQueue, "ide_delay_50ms");
if (kernelSymtab->findAddress("ide_delay_50ms", addr))
skipIdeDelay50msEvent->schedule(addr+sizeof(MachInst));
+ skipDelayLoopEvent = new LinuxSkipDelayLoopEvent(&pcEventQueue,
+ "calibrate_delay");
if (kernelSymtab->findAddress("calibrate_delay", addr))
skipDelayLoopEvent->schedule(addr+sizeof(MachInst));
+ skipCacheProbeEvent = new SkipFuncEvent(&pcEventQueue,
+ "determine_cpu_caches");
if (kernelSymtab->findAddress("determine_cpu_caches", addr))
skipCacheProbeEvent->schedule(addr+sizeof(MachInst));
+ debugPrintkEvent = new DebugPrintkEvent(&pcEventQueue, "dprintk");
if (kernelSymtab->findAddress("dprintk", addr))
- debugPrintkEvent->schedule(addr+sizeof(MachInst)*2);
+ debugPrintkEvent->schedule(addr+8);
+
+ idleStartEvent = new IdleStartEvent(&pcEventQueue, "cpu_idle", this);
+ if (kernelSymtab->findAddress("cpu_idle", addr))
+ idleStartEvent->schedule(addr);
+
+ printThreadEvent = new PrintThreadInfo(&pcEventQueue, "threadinfo");
+ if (kernelSymtab->findAddress("alpha_switch_to", addr) && DTRACE(Thread))
+ printThreadEvent->schedule(addr + sizeof(MachInst) * 6);
+
+ intStartEvent = new InterruptStartEvent(&pcEventQueue, "intStartEvent");
+
+ if (params->bin_int) {
+ if (palSymtab->findAddress("sys_int_21", addr))
+ intStartEvent->schedule(addr + sizeof(MachInst) * 2);
+ else
+ panic("could not find symbol: sys_int_21\n");
+
+ intEndEvent = new InterruptEndEvent(&pcEventQueue, "intEndEvent");
+ if (palSymtab->findAddress("rti_to_kern", addr))
+ intEndEvent->schedule(addr) ;
+ else
+ panic("could not find symbol: rti_to_kern\n");
+
+ intEndEvent2 = new InterruptEndEvent(&pcEventQueue, "intEndEvent2");
+ if (palSymtab->findAddress("rti_to_user", addr))
+ intEndEvent2->schedule(addr);
+ else
+ panic("could not find symbol: rti_to_user\n");
+
+
+ intEndEvent3 = new InterruptEndEvent(&pcEventQueue, "intEndEvent3");
+ if (kernelSymtab->findAddress("do_softirq", addr))
+ intEndEvent3->schedule(addr + sizeof(MachInst) * 2);
+ else
+ panic("could not find symbol: do_softirq\n");
+ }
}
LinuxSystem::~LinuxSystem()
{
- delete kernel;
- delete console;
-
- delete kernelSymtab;
- delete consoleSymtab;
-
+#ifdef DEBUG
delete kernelPanicEvent;
- delete consolePanicEvent;
+#endif
delete skipIdeDelay50msEvent;
delete skipDelayLoopEvent;
delete skipCacheProbeEvent;
+ delete debugPrintkEvent;
+ delete idleStartEvent;
+ delete printThreadEvent;
+ delete intStartEvent;
+ delete intEndEvent;
+ delete intEndEvent2;
}
@@ -277,92 +206,66 @@ LinuxSystem::setDelayLoop(ExecContext *xc)
}
}
-int
-LinuxSystem::registerExecContext(ExecContext *xc)
-{
- int xcIndex = System::registerExecContext(xc);
-
- if (xcIndex == 0) {
- // activate with zero delay so that we start ticking right
- // away on cycle 0
- xc->activate(0);
- }
-
- RemoteGDB *rgdb = new RemoteGDB(this, xc);
- GDBListener *gdbl = new GDBListener(rgdb, 7000 + xcIndex);
- gdbl->listen();
- /**
- * Uncommenting this line waits for a remote debugger to connect
- * to the simulator before continuing.
- */
- //gdbl->accept();
-
- if (remoteGDB.size() <= xcIndex) {
- remoteGDB.resize(xcIndex+1);
- }
-
- remoteGDB[xcIndex] = rgdb;
-
- return xcIndex;
-}
-
-
-void
-LinuxSystem::replaceExecContext(ExecContext *xc, int xcIndex)
-{
- System::replaceExecContext(xcIndex, xc);
- remoteGDB[xcIndex]->replaceExecContext(xc);
-}
-
-bool
-LinuxSystem::breakpoint()
-{
- return remoteGDB[0]->trap(ALPHA_KENTRY_IF);
-}
-
BEGIN_DECLARE_SIM_OBJECT_PARAMS(LinuxSystem)
- Param<bool> bin;
SimObjectParam<MemoryController *> mem_ctl;
SimObjectParam<PhysicalMemory *> physmem;
- Param<uint64_t> init_param;
Param<string> kernel_code;
Param<string> console_code;
Param<string> pal_code;
- Param<string> boot_osflags;
- VectorParam<string> binned_fns;
+ Param<string> boot_osflags;
Param<string> readfile;
+ Param<unsigned int> init_param;
+
+ Param<uint64_t> system_type;
+ Param<uint64_t> system_rev;
+
+ Param<bool> bin;
+ VectorParam<string> binned_fns;
+ Param<bool> bin_int;
END_DECLARE_SIM_OBJECT_PARAMS(LinuxSystem)
BEGIN_INIT_SIM_OBJECT_PARAMS(LinuxSystem)
-
- INIT_PARAM_DFLT(bin, "is this system to be binned", false),
INIT_PARAM(mem_ctl, "memory controller"),
INIT_PARAM(physmem, "phsyical memory"),
- INIT_PARAM_DFLT(init_param, "numerical value to pass into simulator", 0),
- INIT_PARAM(kernel_code, "file that contains the code"),
+ INIT_PARAM(kernel_code, "file that contains the kernel code"),
INIT_PARAM(console_code, "file that contains the console code"),
INIT_PARAM(pal_code, "file that contains palcode"),
INIT_PARAM_DFLT(boot_osflags, "flags to pass to the kernel during boot",
- "a"),
+ "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(readfile, "file to read startup script from", "")
-
+ INIT_PARAM_DFLT(bin_int, "is interrupt code binned seperately?", true)
END_INIT_SIM_OBJECT_PARAMS(LinuxSystem)
CREATE_SIM_OBJECT(LinuxSystem)
{
- LinuxSystem *sys = new LinuxSystem(getInstanceName(), init_param, mem_ctl,
- physmem, kernel_code, console_code,
- pal_code, boot_osflags, bin, binned_fns);
-
- sys->readfile = readfile;
- return sys;
+ System::Params *p = new System::Params;
+ p->name = getInstanceName();
+ p->memctrl = mem_ctl;
+ p->physmem = physmem;
+ p->kernel_path = kernel_code;
+ p->console_path = console_code;
+ p->palcode = pal_code;
+ 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 LinuxSystem(p);
}
REGISTER_SIM_OBJECT("LinuxSystem", LinuxSystem)
+
diff --git a/kern/linux/linux_system.hh b/kern/linux/linux_system.hh
index e7cdf140d..5e3cba9b3 100644
--- a/kern/linux/linux_system.hh
+++ b/kern/linux/linux_system.hh
@@ -26,32 +26,28 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#ifndef __LINUX_SYSTEM_HH__
-#define __LINUX_SYSTEM_HH__
+#ifndef __KERN_LINUX_LINUX_SYSTEM_HH__
+#define __KERN_LINUX_LINUX_SYSTEM_HH__
-#include <vector>
-
-#include "sim/system.hh"
#include "sim/host.hh"
+#include "sim/system.hh"
#include "targetarch/isa_traits.hh"
-#include <map>
-
/**
* MAGIC address where the kernel arguments should go. Defined as
* PARAM in linux kernel alpha-asm.
*/
-const Addr PARAM_ADDR = ULL(0xfffffc000030a000);
+const Addr PARAM_ADDR = ULL(0xfffffc000030a000);
class ExecContext;
-class ElfObject;
-class SymbolTable;
+
+class BreakPCEvent;
class DebugPrintkEvent;
class BreakPCEvent;
class LinuxSkipDelayLoopEvent;
class SkipFuncEvent;
-class FnEvent;
-class AlphaArguments;
+class IdleStartEvent;
+class PrintThreadInfo;
/**
* This class contains linux specific system code (Loading, Events, Binning).
@@ -61,94 +57,58 @@ class AlphaArguments;
class LinuxSystem : public System
{
private:
- /** Object pointer for the kernel code */
- ElfObject *kernel;
-
- /** Object pointer for the console code */
- ElfObject *console;
-
- /** kernel Symbol table */
- SymbolTable *kernelSymtab;
-
- /** console symbol table */
- SymbolTable *consoleSymtab;
-
+#ifdef DEBUG
/** Event to halt the simulator if the kernel calls panic() */
BreakPCEvent *kernelPanicEvent;
+#endif
- /** Event to halt the simulator if the console calls panic() */
- BreakPCEvent *consolePanicEvent;
-
- /** Event to skip determine_cpu_caches() because we don't support the
- * IPRs that the code can access to figure out cache sizes
+ /**
+ * Event to skip determine_cpu_caches() because we don't support
+ * the IPRs that the code can access to figure out cache sizes
*/
SkipFuncEvent *skipCacheProbeEvent;
/** PC based event to skip the ide_delay_50ms() call */
SkipFuncEvent *skipIdeDelay50msEvent;
- /** PC based event to skip the dprink() call and emulate its functionality */
+ /**
+ * PC based event to skip the dprink() call and emulate its
+ * functionality
+ */
DebugPrintkEvent *debugPrintkEvent;
- /** Skip calculate_delay_loop() rather than waiting for this to be
+ /**
+ * Skip calculate_delay_loop() rather than waiting for this to be
* calculated
*/
LinuxSkipDelayLoopEvent *skipDelayLoopEvent;
- /** Begining of kernel code */
- Addr kernelStart;
-
- /** End of kernel code */
- Addr kernelEnd;
-
- /** Entry point in the kernel to start at */
- Addr kernelEntry;
-
- bool bin;
- std::vector<string> binned_fns;
-
- public:
- std::vector<RemoteGDB *> remoteGDB;
- std::vector<GDBListener *> gdbListen;
-
- LinuxSystem(const std::string _name,
- const uint64_t _init_param,
- MemoryController *_memCtrl,
- PhysicalMemory *_physmem,
- const std::string &kernel_path,
- const std::string &console_path,
- const std::string &palcode,
- const std::string &boot_osflags,
- const bool _bin,
- const std::vector<std::string> &_binned_fns);
-
- ~LinuxSystem();
-
- void setDelayLoop(ExecContext *xc);
-
- int registerExecContext(ExecContext *xc);
- void replaceExecContext(ExecContext *xc, int xcIndex);
-
/**
- * Returns the addess the kernel starts at.
- * @return address the kernel starts at
+ * Event to print information about thread switches if the trace flag
+ * Thread is set
*/
- Addr getKernelStart() const { return kernelStart; }
+ PrintThreadInfo *printThreadEvent;
/**
- * Returns the addess the kernel ends at.
- * @return address the kernel ends at
+ * Event to bin Interrupts seperately from kernel code
*/
- Addr getKernelEnd() const { return kernelEnd; }
+ InterruptStartEvent *intStartEvent;
/**
- * Returns the addess the entry point to the kernel code.
- * @return entry point of the kernel code
+ * Event to bin Interrupts seperately from kernel code
*/
- Addr getKernelEntry() const { return kernelEntry; }
+ InterruptEndEvent *intEndEvent;
+ InterruptEndEvent *intEndEvent2;
+ InterruptEndEvent *intEndEvent3;
+ /** Grab the PCBB of the idle process when it starts */
+ IdleStartEvent *idleStartEvent;
- bool breakpoint();
+ public:
+ LinuxSystem(Params *p);
+ ~LinuxSystem();
+
+ void setDelayLoop(ExecContext *xc);
};
-#endif // __LINUX_SYSTEM_HH__
+#endif // __KERN_LINUX_LINUX_SYSTEM_HH__
diff --git a/kern/linux/linux_threadinfo.hh b/kern/linux/linux_threadinfo.hh
new file mode 100644
index 000000000..99ce9965a
--- /dev/null
+++ b/kern/linux/linux_threadinfo.hh
@@ -0,0 +1,91 @@
+/*
+ * Copyright (c) 2004 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 __LINUX_TREADNIFO_HH__
+#define __LINUX_TREADNIFO_HH__
+
+
+#include "targetarch/isa_traits.hh"
+#include "targetarch/vptr.hh"
+#include "cpu/exec_context.hh"
+#include "kern/linux/thread_info.hh"
+#include "kern/linux/sched.hh"
+
+
+namespace Linux {
+
+class ThreadInfo
+{
+ private:
+ ExecContext *xc;
+
+ public:
+ ThreadInfo(ExecContext *exec) : xc(exec) {}
+ ~ThreadInfo() {}
+
+ inline VPtr<thread_info>
+ curThreadInfo()
+ {
+ Addr current;
+
+ /* Each kernel stack is only 2 pages, the start of which is the
+ * thread_info struct. So we can get the address by masking off
+ * the lower 14 bits.
+ */
+ current = xc->regs.intRegFile[StackPointerReg] & ~0x3fff;
+ return VPtr<thread_info>(xc, current);
+ }
+
+ inline VPtr<task_struct>
+ curTaskInfo()
+ {
+ Addr task = curThreadInfo()->task;
+ return VPtr<task_struct>(xc, task);
+ }
+
+ std::string
+ curTaskName()
+ {
+ return curTaskInfo()->comm;
+ }
+
+ int32_t
+ curTaskPID()
+ {
+ return curTaskInfo()->pid;
+ }
+
+ uint64_t
+ curTaskStart()
+ {
+ return curTaskInfo()->start_time;
+ }
+};
+}
+
+#endif /* __LINUX_THREADINFO_HH__ */
diff --git a/kern/linux/sched.hh b/kern/linux/sched.hh
new file mode 100644
index 000000000..287214b2b
--- /dev/null
+++ b/kern/linux/sched.hh
@@ -0,0 +1,110 @@
+#ifndef __LINUX_SCHED_H__
+#define __LINUX_SCHED_H__
+
+#include "targetarch/isa_traits.hh"
+#include "kern/linux/atomic.hh"
+#include "kern/linux/list.hh"
+#include "kern/linux/wait.hh"
+#include "kern/linux/timer.hh"
+#include "kern/linux/pid.hh"
+#include "kern/linux/aligned.hh"
+
+namespace Linux {
+
+ struct rlimit {
+ uint64_ta rlim_cur;
+ uint64_ta rlim_max;
+ };
+
+ const uint32_t RLIM_NLIMITS = 11;
+
+ struct task_struct {
+ int64_ta state; /* -1 unrunnable, 0 runnable, >0 stopped */
+ Addr_a thread_info;
+ atomic_t usage;
+
+ uint64_ta flags; /* per process flags, defined below */
+ uint64_ta ptrace;
+
+ int32_t lock_depth; /* Lock depth */
+
+ int32_t prio, static_prio;
+
+ struct list_head run_list;
+ Addr_a array;
+
+ uint64_ta sleep_avg;
+ int64_ta interactive_credit;
+ uint64_ta timestamp;
+ int32_t activated;
+
+ uint64_ta policy;
+ uint64_ta cpus_allowed;
+ uint32_t time_slice, first_time_slice;
+
+ struct list_head tasks;
+ struct list_head ptrace_children;
+ struct list_head ptrace_list;
+
+ Addr_a mm, active_mm;
+
+ /* task state */
+ Addr_a binfmt;
+ int32_t exit_code, exit_signal;
+ int32_t pdeath_signal; /* The signal sent when the parent dies */
+ /* ??? */
+ uint64_ta personality;
+ int32_t did_exec:1;
+ int32_t pid;
+ int32_t __pgrp; /* Accessed via process_group() */
+ int32_t tty_old_pgrp;
+ int32_t session;
+ int32_t tgid;
+ /* boolean value for session group leader */
+ int32_t leader;
+ /*
+ * pointers to (original) parent process, youngest child, younger sibling,
+ * older sibling, respectively. (p->father can be replaced with
+ * p->parent->pid)
+ */
+ Addr_a real_parent; /* real parent process (when being debugged) */
+ Addr_a parent; /* parent process */
+ struct list_head children; /* list of my children */
+ struct list_head sibling; /* linkage in my parent's children list */
+ Addr_a group_leader; /* threadgroup leader */
+
+ /* PID/PID hash table linkage. */
+ struct pid_link pids[PIDTYPE_MAX];
+
+ wait_queue_head_t wait_chldexit; /* for wait4() */
+ Addr_a vfork_done; /* for vfork() */
+ Addr_a set_child_tid; /* CLONE_CHILD_SETTID */
+ Addr_a clear_child_tid; /* CLONE_CHILD_CLEARTID */
+
+ uint64_ta rt_priority;
+ uint64_ta it_real_value, it_prof_value, it_virt_value;
+ uint64_ta it_real_incr, it_prof_incr, it_virt_incr;
+ struct timer_list real_timer;
+ struct list_head posix_timers; /* POSIX.1b Interval Timers */
+ uint64_ta utime, stime, cutime, cstime;
+ uint64_ta nvcsw, nivcsw, cnvcsw, cnivcsw; /* context switch counts */
+ uint64_ta start_time;
+ /* mm fault and swap info: this can arguably be seen as either mm-specific or thread-specific */
+ uint64_ta min_flt, maj_flt, nswap, cmin_flt, cmaj_flt, cnswap;
+ /* process credentials */
+ uint32_t uid,euid,suid,fsuid;
+ uint32_t gid,egid,sgid,fsgid;
+ Addr_a group_info;
+ uint32_t cap_effective, cap_inheritable, cap_permitted;
+ int32_t keep_capabilities:1;
+ Addr user;
+ /* limits */
+ struct rlimit rlim[RLIM_NLIMITS];
+ uint16_t used_math;
+ char comm[16];
+ };
+
+
+}
+
+#endif
diff --git a/kern/linux/thread_info.hh b/kern/linux/thread_info.hh
new file mode 100644
index 000000000..1b4053a78
--- /dev/null
+++ b/kern/linux/thread_info.hh
@@ -0,0 +1,27 @@
+#ifndef __ALPHA_THREAD_INFO_H__
+#define __ALPHA_THREAD_INFO_H__
+
+#include "kern/linux/hwrpb.hh"
+#include "kern/linux/aligned.hh"
+
+namespace Linux {
+ struct thread_info {
+ struct pcb_struct pcb; /* palcode state */
+
+ Addr_a task; /* main task structure */
+ uint32_t flags; /* low level flags */
+ uint32_t ieee_state; /* see fpu.h */
+
+ Addr_a exec_domain; /* execution domain */
+ uint64_ta addr_limit; /* thread address space */
+ int64_ta cpu; /* current CPU */
+ int32_t preempt_count; /* 0 => preemptable, <0 => BUG */
+
+ int32_t bpt_nsaved;
+ uint64_ta bpt_addr[2]; /* breakpoint handling */
+ uint32_t bpt_insn[2];
+
+ /*restart_block;*/
+ };
+}
+#endif /* __ALPHA_THREAD_INFO_H__ */
diff --git a/kern/system_events.cc b/kern/system_events.cc
index 351c3ddb2..9acf2f65a 100644
--- a/kern/system_events.cc
+++ b/kern/system_events.cc
@@ -30,9 +30,9 @@
#include "cpu/base_cpu.hh"
#include "cpu/full_cpu/bpred.hh"
#include "cpu/full_cpu/full_cpu.hh"
+#include "kern/kernel_stats.hh"
#include "kern/system_events.hh"
#include "sim/system.hh"
-#include "sim/sw_context.hh"
void
SkipFuncEvent::process(ExecContext *xc)
@@ -52,11 +52,9 @@ SkipFuncEvent::process(ExecContext *xc)
}
-FnEvent::FnEvent(PCEventQueue *q, const std::string & desc, System *system)
- : PCEvent(q, desc), _name(desc)
+FnEvent::FnEvent(PCEventQueue *q, const std::string &desc, Stats::MainBin *bin)
+ : PCEvent(q, desc), _name(desc), mybin(bin)
{
- myBin = system->getBin(desc);
- assert(myBin);
}
void
@@ -64,46 +62,27 @@ FnEvent::process(ExecContext *xc)
{
if (xc->misspeculating())
return;
- assert(xc->system->bin && "FnEvent must be in a binned system");
- SWContext *ctx = xc->swCtx;
- DPRINTF(TCPIP, "%s: %s Event!!!\n", xc->system->name(), description);
- if (ctx && !ctx->callStack.empty()) {
- DPRINTF(TCPIP, "already a callstack!\n");
- fnCall *last = ctx->callStack.top();
-
- if (last->name == "idle_thread")
- ctx->calls++;
+ xc->system->kernelBinning->call(xc, mybin);
+}
- if (!xc->system->findCaller(myname(), "" ) &&
- !xc->system->findCaller(myname(), last->name)) {
+void
+IdleStartEvent::process(ExecContext *xc)
+{
+ xc->kernelStats->setIdleProcess(xc->regs.ipr[AlphaISA::IPR_PALtemp23]);
+ remove();
+}
- DPRINTF(TCPIP, "but can't find parent %s\n", last->name);
- return;
- }
- ctx->calls--;
+void
+InterruptStartEvent::process(ExecContext *xc)
+{
+ xc->kernelStats->mode(Kernel::interrupt);
+}
- //assert(!ctx->calls && "on a binned fn, calls should == 0 (but can happen in boot)");
- } else {
- DPRINTF(TCPIP, "no callstack yet\n");
- if (!xc->system->findCaller(myname(), "")) {
- DPRINTF(TCPIP, "not the right function, returning\n");
- return;
- }
- if (!ctx) {
- DPRINTF(TCPIP, "creating new context for %s\n", myname());
- ctx = new SWContext;
- xc->swCtx = ctx;
- }
- }
- DPRINTF(TCPIP, "adding fn %s to context\n", myname());
- fnCall *call = new fnCall;
- call->myBin = myBin;
- call->name = myname();
- ctx->callStack.push(call);
- myBin->activate();
- xc->system->fnCalls++;
- DPRINTF(TCPIP, "fnCalls for %s is %d\n", description,
- xc->system->fnCalls.value());
- xc->system->dumpState(xc);
+void
+InterruptEndEvent::process(ExecContext *xc)
+{
+ // We go back to kernel, if we are user, inside the rti
+ // pal code we will get switched to user because of the ICM write
+ xc->kernelStats->mode(Kernel::kernel);
}
diff --git a/kern/system_events.hh b/kern/system_events.hh
index 7f658bde9..8a8549d03 100644
--- a/kern/system_events.hh
+++ b/kern/system_events.hh
@@ -44,13 +44,44 @@ class SkipFuncEvent : public PCEvent
class FnEvent : public PCEvent
{
public:
- FnEvent(PCEventQueue *q, const std::string &desc, System *system);
+ FnEvent(PCEventQueue *q, const std::string &desc, Stats::MainBin *bin);
virtual void process(ExecContext *xc);
std::string myname() const { return _name; }
private:
std::string _name;
- Stats::MainBin *myBin;
+ Stats::MainBin *mybin;
};
+class IdleStartEvent : public PCEvent
+{
+ private:
+ System *system;
+
+ public:
+ IdleStartEvent(PCEventQueue *q, const std::string &desc, System *sys)
+ : PCEvent(q, desc), system(sys)
+ {}
+ virtual void process(ExecContext *xc);
+};
+
+class InterruptStartEvent : public PCEvent
+{
+ public:
+ InterruptStartEvent(PCEventQueue *q, const std::string &desc)
+ : PCEvent(q, desc)
+ {}
+ virtual void process(ExecContext *xc);
+};
+
+class InterruptEndEvent : public PCEvent
+{
+ public:
+ InterruptEndEvent(PCEventQueue *q, const std::string &desc)
+ : PCEvent(q, desc)
+ {}
+ virtual void process(ExecContext *xc);
+};
+
+
#endif // __SYSTEM_EVENTS_HH__
diff --git a/kern/tru64/tru64_events.cc b/kern/tru64/tru64_events.cc
index e96cc9c5d..f4300116e 100644
--- a/kern/tru64/tru64_events.cc
+++ b/kern/tru64/tru64_events.cc
@@ -32,8 +32,9 @@
#include "kern/tru64/tru64_events.hh"
#include "kern/tru64/dump_mbuf.hh"
#include "kern/tru64/printf.hh"
-#include "targetarch/arguments.hh"
#include "mem/functional_mem/memory_control.hh"
+#include "targetarch/arguments.hh"
+#include "targetarch/isa_traits.hh"
//void SkipFuncEvent::process(ExecContext *xc);
@@ -46,8 +47,8 @@ BadAddrEvent::process(ExecContext *xc)
uint64_t a0 = xc->regs.intRegFile[ArgumentReg0];
- if (a0 < ALPHA_K0SEG_BASE || a0 >= ALPHA_K1SEG_BASE ||
- xc->memCtrl->badaddr(ALPHA_K0SEG_TO_PHYS(a0) & PA_IMPL_MASK)) {
+ if (!TheISA::IsK0Seg(a0) ||
+ xc->memctrl->badaddr(TheISA::K0Seg2Phys(a0) & EV5::PAddrImplMask)) {
DPRINTF(BADADDR, "badaddr arg=%#x bad\n", a0);
xc->regs.intRegFile[ReturnValueReg] = 0x1;
diff --git a/kern/tru64/tru64_syscalls.hh b/kern/tru64/tru64_syscalls.hh
index f4853e3f8..7ddc699b1 100644
--- a/kern/tru64/tru64_syscalls.hh
+++ b/kern/tru64/tru64_syscalls.hh
@@ -29,11 +29,14 @@
#ifndef __TRU64_SYSCALLS_HH__
#define __TRU64_SYSCALLS_HH__
-#include "targetarch/syscalls.hh"
#include "kern/tru64/tru64.hh"
-struct SystemCalls<Tru64>
+template <class OS>
+class SystemCalls;
+
+class SystemCalls<Tru64>
{
+ public:
enum {
syscall = 0,
exit = 1,
diff --git a/kern/tru64/tru64_system.cc b/kern/tru64/tru64_system.cc
index 4395162e4..c6435cb18 100644
--- a/kern/tru64/tru64_system.cc
+++ b/kern/tru64/tru64_system.cc
@@ -26,11 +26,7 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#include "base/loader/aout_object.hh"
-#include "base/loader/ecoff_object.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/tru64/tru64_events.hh"
@@ -42,75 +38,11 @@
#include "targetarch/isa_traits.hh"
#include "targetarch/vtophys.hh"
-extern SymbolTable *debugSymbolTable;
-
using namespace std;
-Tru64System::Tru64System(const string _name, const uint64_t _init_param,
- MemoryController *_memCtrl, PhysicalMemory *_physmem,
- const string &kernel_path, const string &console_path,
- const string &palcode, const string &boot_osflags,
- const bool _bin, const vector<string> &_binned_fns,
- const uint64_t system_type, const uint64_t system_rev)
- : System(_name, _init_param, _memCtrl, _physmem, _bin,_binned_fns),
- bin(_bin), binned_fns(_binned_fns)
+Tru64System::Tru64System(Tru64System::Params *p)
+ : System(p)
{
- kernelSymtab = new SymbolTable;
- consoleSymtab = new SymbolTable;
- debugSymbolTable = kernelSymtab;
-
- ObjectFile *kernel = createObjectFile(kernel_path);
- if (kernel == NULL)
- fatal("Could not load kernel file %s", kernel_path);
-
- ObjectFile *console = createObjectFile(console_path);
- if (console == NULL)
- fatal("Could not load console file %s", console_path);
-
- if (!kernel->loadGlobalSymbols(kernelSymtab))
- panic("could not load kernel symbols\n");
-
- if (!console->loadGlobalSymbols(consoleSymtab))
- panic("could not load console symbols\n");
-
- // Load pal file
- ObjectFile *pal = createObjectFile(palcode);
- if (pal == NULL)
- fatal("Could not load PALcode file %s", palcode);
- pal->loadSections(physmem, true);
-
- // Load console file
- console->loadSections(physmem, true);
-
- // Load kernel file
- kernel->loadSections(physmem, true);
- kernelStart = kernel->textBase();
- kernelEnd = kernel->bssBase() + kernel->bssSize();
- kernelEntry = kernel->entryPoint();
-
- DPRINTF(Loader, "Kernel start = %#x\n"
- "Kernel end = %#x\n"
- "Kernel entry = %#x\n",
- kernelStart, kernelEnd, kernelEntry);
-
- DPRINTF(Loader, "Kernel loaded...\n");
-
-#ifdef DEBUG
- kernelPanicEvent = new BreakPCEvent(&pcEventQueue, "kernel panic");
- consolePanicEvent = new BreakPCEvent(&pcEventQueue, "console panic");
-#endif
- badaddrEvent = new BadAddrEvent(&pcEventQueue, "badaddr");
- skipPowerStateEvent = new SkipFuncEvent(&pcEventQueue,
- "tl_v48_capture_power_state");
- skipScavengeBootEvent = new SkipFuncEvent(&pcEventQueue,
- "pmap_scavenge_boot");
- printfEvent = new PrintfEvent(&pcEventQueue, "printf");
- debugPrintfEvent = new DebugPrintfEvent(&pcEventQueue,
- "debug_printf", false);
- debugPrintfrEvent = new DebugPrintfEvent(&pcEventQueue,
- "debug_printfr", true);
- dumpMbufEvent = new DumpMbufEvent(&pcEventQueue, "dump_mbuf");
-
Addr addr = 0;
if (kernelSymtab->findAddress("enable_async_printf", addr)) {
Addr paddr = vtophys(physmem, addr);
@@ -121,180 +53,125 @@ Tru64System::Tru64System(const string _name, const uint64_t _init_param,
*(uint32_t *)enable_async_printf = 0;
}
- 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, boot_osflags.c_str());
- }
-
- if (consoleSymtab->findAddress("xxm_rpb", addr)) {
- Addr paddr = vtophys(physmem, addr);
- char *hwprb = (char *)physmem->dma_addr(paddr, sizeof(uint64_t));
-
- if (hwprb) {
- *(uint64_t*)(hwprb+0x50) = system_type;
- *(uint64_t*)(hwprb+0x58) = system_rev;
- }
- else
- panic("could not translate hwprb addr to set system type/variation\n");
- } else
- panic("could not find hwprb to set system type/variation\n");
-
-
#ifdef DEBUG
+ kernelPanicEvent = new BreakPCEvent(&pcEventQueue, "kernel panic");
if (kernelSymtab->findAddress("panic", addr))
kernelPanicEvent->schedule(addr);
else
panic("could not find kernel symbol \'panic\'");
-
- if (consoleSymtab->findAddress("panic", addr))
- consolePanicEvent->schedule(addr);
#endif
+ badaddrEvent = new BadAddrEvent(&pcEventQueue, "badaddr");
if (kernelSymtab->findAddress("badaddr", addr))
badaddrEvent->schedule(addr);
else
panic("could not find kernel symbol \'badaddr\'");
+ skipPowerStateEvent = new SkipFuncEvent(&pcEventQueue,
+ "tl_v48_capture_power_state");
if (kernelSymtab->findAddress("tl_v48_capture_power_state", addr))
skipPowerStateEvent->schedule(addr);
+ skipScavengeBootEvent = new SkipFuncEvent(&pcEventQueue,
+ "pmap_scavenge_boot");
if (kernelSymtab->findAddress("pmap_scavenge_boot", addr))
skipScavengeBootEvent->schedule(addr);
#if TRACING_ON
+ printfEvent = new PrintfEvent(&pcEventQueue, "printf");
if (kernelSymtab->findAddress("printf", addr))
printfEvent->schedule(addr);
+ debugPrintfEvent = new DebugPrintfEvent(&pcEventQueue, "debug_printf",
+ false);
if (kernelSymtab->findAddress("m5printf", addr))
debugPrintfEvent->schedule(addr);
+ debugPrintfrEvent = new DebugPrintfEvent(&pcEventQueue, "debug_printfr",
+ true);
if (kernelSymtab->findAddress("m5printfr", addr))
debugPrintfrEvent->schedule(addr);
+ dumpMbufEvent = new DumpMbufEvent(&pcEventQueue, "dump_mbuf");
if (kernelSymtab->findAddress("m5_dump_mbuf", addr))
dumpMbufEvent->schedule(addr);
#endif
-
- // BINNING STUFF
- if (bin == true) {
- int end = binned_fns.size();
- Addr address = 0;
-
- for (int i = 0; i < end; i +=2) {
- if (kernelSymtab->findAddress(binned_fns[i], address))
- fnEvents[(i>>1)]->schedule(address);
- else
- panic("could not find kernel symbol %s\n", binned_fns[i]);
- }
- }
- //
}
Tru64System::~Tru64System()
{
- delete kernel;
- delete console;
-
- delete kernelSymtab;
- delete consoleSymtab;
-
#ifdef DEBUG
delete kernelPanicEvent;
- delete consolePanicEvent;
#endif
delete badaddrEvent;
delete skipPowerStateEvent;
delete skipScavengeBootEvent;
+#if TRACING_ON
delete printfEvent;
delete debugPrintfEvent;
delete debugPrintfrEvent;
delete dumpMbufEvent;
-}
-
-int
-Tru64System::registerExecContext(ExecContext *xc)
-{
- int xcIndex = System::registerExecContext(xc);
-
- if (xcIndex == 0) {
- // activate with zero delay so that we start ticking right
- // away on cycle 0
- xc->activate(0);
- }
-
- RemoteGDB *rgdb = new RemoteGDB(this, xc);
- GDBListener *gdbl = new GDBListener(rgdb, 7000 + xcIndex);
- gdbl->listen();
-
- if (remoteGDB.size() <= xcIndex) {
- remoteGDB.resize(xcIndex+1);
- }
-
- remoteGDB[xcIndex] = rgdb;
-
- return xcIndex;
-}
-
-
-void
-Tru64System::replaceExecContext(ExecContext *xc, int xcIndex)
-{
- System::replaceExecContext(xcIndex, xc);
- remoteGDB[xcIndex]->replaceExecContext(xc);
-}
-
-bool
-Tru64System::breakpoint()
-{
- return remoteGDB[0]->trap(ALPHA_KENTRY_INT);
+#endif
}
BEGIN_DECLARE_SIM_OBJECT_PARAMS(Tru64System)
- Param<bool> bin;
SimObjectParam<MemoryController *> mem_ctl;
SimObjectParam<PhysicalMemory *> physmem;
- Param<unsigned int> init_param;
Param<string> kernel_code;
Param<string> console_code;
Param<string> pal_code;
+
Param<string> boot_osflags;
- VectorParam<string> binned_fns;
+ Param<string> readfile;
+ Param<unsigned int> init_param;
+
Param<uint64_t> system_type;
Param<uint64_t> system_rev;
+ Param<bool> bin;
+ VectorParam<string> binned_fns;
+
END_DECLARE_SIM_OBJECT_PARAMS(Tru64System)
BEGIN_INIT_SIM_OBJECT_PARAMS(Tru64System)
- INIT_PARAM_DFLT(bin, "is this system to be binned", false),
INIT_PARAM(mem_ctl, "memory controller"),
INIT_PARAM(physmem, "phsyical memory"),
- INIT_PARAM_DFLT(init_param, "numerical value to pass into simulator", 0),
INIT_PARAM(kernel_code, "file that contains the kernel code"),
INIT_PARAM(console_code, "file that contains the console code"),
INIT_PARAM(pal_code, "file that contains palcode"),
INIT_PARAM_DFLT(boot_osflags, "flags to pass to the kernel during boot",
"a"),
- INIT_PARAM(binned_fns, "functions to be broken down and binned"),
+ 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", 12),
- INIT_PARAM_DFLT(system_rev, "Revision of system we are emulating", 2<<1)
-
+ INIT_PARAM_DFLT(system_rev, "Revision of system we are emulating", 2<<1),
+ INIT_PARAM_DFLT(bin, "is this system to be binned", false),
+ INIT_PARAM(binned_fns, "functions to be broken down and binned")
END_INIT_SIM_OBJECT_PARAMS(Tru64System)
CREATE_SIM_OBJECT(Tru64System)
{
- Tru64System *sys = new Tru64System(getInstanceName(), init_param, mem_ctl,
- physmem, kernel_code, console_code,
- pal_code, boot_osflags, bin,
- binned_fns, system_type, system_rev);
-
- return sys;
+ System::Params *p = new System::Params;
+ p->name = getInstanceName();
+ p->memctrl = mem_ctl;
+ p->physmem = physmem;
+ p->kernel_path = kernel_code;
+ p->console_path = console_code;
+ p->palcode = pal_code;
+ 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 = false;
+
+ return new Tru64System(p);
}
REGISTER_SIM_OBJECT("Tru64System", Tru64System)
diff --git a/kern/tru64/tru64_system.hh b/kern/tru64/tru64_system.hh
index 8dd696b79..13d283fb3 100644
--- a/kern/tru64/tru64_system.hh
+++ b/kern/tru64/tru64_system.hh
@@ -26,18 +26,13 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#ifndef __TRU64_SYSTEM_HH__
-#define __TRU64_SYSTEM_HH__
-
-#include <map>
-#include <vector>
+#ifndef __KERN_TRU64_TRU64_SYSTEM_HH__
+#define __KERN_TRU64_TRU64_SYSTEM_HH__
#include "sim/system.hh"
#include "targetarch/isa_traits.hh"
class ExecContext;
-class EcoffObject;
-class SymbolTable;
class BreakPCEvent;
class BadAddrEvent;
@@ -45,20 +40,16 @@ class SkipFuncEvent;
class PrintfEvent;
class DebugPrintfEvent;
class DumpMbufEvent;
-class FnEvent;
class AlphaArguments;
class Tru64System : public System
{
private:
- EcoffObject *kernel;
- EcoffObject *console;
-
- SymbolTable *kernelSymtab;
- SymbolTable *consoleSymtab;
-
+#ifdef DEBUG
+ /** Event to halt the simulator if the kernel calls panic() */
BreakPCEvent *kernelPanicEvent;
- BreakPCEvent *consolePanicEvent;
+#endif
+
BadAddrEvent *badaddrEvent;
SkipFuncEvent *skipPowerStateEvent;
SkipFuncEvent *skipScavengeBootEvent;
@@ -67,43 +58,12 @@ class Tru64System : public System
DebugPrintfEvent *debugPrintfrEvent;
DumpMbufEvent *dumpMbufEvent;
- private:
-
- Addr kernelStart;
- Addr kernelEnd;
- Addr kernelEntry;
- bool bin;
- std::vector<string> binned_fns;
-
- public:
- std::vector<RemoteGDB *> remoteGDB;
- std::vector<GDBListener *> gdbListen;
-
public:
- Tru64System(const std::string _name,
- const uint64_t _init_param,
- MemoryController *_memCtrl,
- PhysicalMemory *_physmem,
- const std::string &kernel_path,
- const std::string &console_path,
- const std::string &palcode,
- const std::string &boot_osflags,
- const bool _bin,
- const std::vector<string> &binned_fns,
- const uint64_t system_type,
- const uint64_t system_rev);
+ Tru64System(Params *p);
~Tru64System();
- int registerExecContext(ExecContext *xc);
- void replaceExecContext(ExecContext *xc, int xcIndex);
-
- Addr getKernelStart() const { return kernelStart; }
- Addr getKernelEnd() const { return kernelEnd; }
- Addr getKernelEntry() const { return kernelEntry; }
- bool breakpoint();
-
static void Printf(AlphaArguments args);
static void DumpMbuf(AlphaArguments args);
};
-#endif // __TRU64_SYSTEM_HH__
+#endif // __KERN_TRU64_TRU64_SYSTEM_HH__
diff --git a/sim/builder.cc b/sim/builder.cc
index 53e5cf3d8..fa5c113a7 100644
--- a/sim/builder.cc
+++ b/sim/builder.cc
@@ -39,31 +39,11 @@
using namespace std;
-
-ostream &
-builderStream()
-{
- static ofstream file;
- static ostream *stream = NULL;
-
- if (!stream) {
- if (!outputDirectory.empty()) {
- string filename = outputDirectory + "builder.txt";
- file.open(filename.c_str());
- stream = &file;
- } else {
- stream = outputStream;
- }
- }
-
- return *stream;
-}
-
SimObjectBuilder::SimObjectBuilder(const string &_configClass,
const string &_instanceName,
ConfigNode *_configNode,
const string &_simObjClassName)
- : ParamContext(_configClass, true),
+ : ParamContext(_configClass, NoAutoInit),
instanceName(_instanceName),
configNode(_configNode),
simObjClassName(_simObjClassName)
@@ -187,10 +167,10 @@ SimObjectClass::createObject(IniFile &configDB,
// echo object parameters to stats file (for documenting the
// config used to generate the associated stats)
- builderStream() << "[" << object->name() << "]" << endl;
- builderStream() << "type=" << simObjClassName << endl;
- objectBuilder->showParams(builderStream());
- builderStream() << endl;
+ *configStream << "[" << object->name() << "]" << endl;
+ *configStream << "type=" << simObjClassName << endl;
+ objectBuilder->showParams(*configStream);
+ *configStream << endl;
// done with the SimObjectBuilder now
delete objectBuilder;
diff --git a/sim/builder.hh b/sim/builder.hh
index a85c88b76..36e40c2a9 100644
--- a/sim/builder.hh
+++ b/sim/builder.hh
@@ -38,9 +38,6 @@
class SimObject;
-std::ostream &
-builderStream();
-
//
// A SimObjectBuilder serves as an evaluation context for a set of
// parameters that describe a specific instance of a SimObject. This
diff --git a/sim/debug.cc b/sim/debug.cc
index 293edcbe2..3467d1669 100644
--- a/sim/debug.cc
+++ b/sim/debug.cc
@@ -40,13 +40,15 @@
using namespace std;
-#ifdef DEBUG
void
debug_break()
{
+#ifndef NDEBUG
kill(getpid(), SIGTRAP);
-}
+#else
+ cprintf("debug_break suppressed, compiled with NDEBUG\n");
#endif
+}
//
// Debug event: place a breakpoint on the process function and
diff --git a/sim/debug.hh b/sim/debug.hh
index 3ccf1dbd4..5ee77cf28 100644
--- a/sim/debug.hh
+++ b/sim/debug.hh
@@ -29,10 +29,6 @@
#ifndef __DEBUG_HH__
#define __DEBUG_HH__
-#ifdef DEBUG
void debug_break();
-#else
-inline void debug_break() { }
-#endif
#endif // __DEBUG_HH__
diff --git a/sim/main.cc b/sim/main.cc
index 2a0427303..e8ac58786 100644
--- a/sim/main.cc
+++ b/sim/main.cc
@@ -51,7 +51,6 @@
#include "sim/host.hh"
#include "sim/sim_events.hh"
#include "sim/sim_exit.hh"
-#include "sim/sim_init.hh"
#include "sim/sim_object.hh"
#include "sim/stat_control.hh"
#include "sim/stats.hh"
@@ -111,12 +110,15 @@ static void
showBriefHelp(ostream &out)
{
out << "Usage: " << myProgName
- << " [-hn] [-Dname[=def]] [-Uname] [-I[dir]] "
- << "[--<section>:<param>=<value>] [<config file> ...]" << endl
- << " -h: print long help (including parameter listing)" << endl
- << " -n: don't load default.ini" << endl
- << " -u: don't quit on unreferenced parameters" << endl
- << " -D,-U,-I: passed to cpp for preprocessing .ini files" << endl;
+ << " [-hnu] [-Dname[=def]] [-Uname] [-I[dir]] "
+ << "<config-spec> [<config-spec> ...]\n"
+ << "[] [<config file> ...]\n"
+ << " -h: print long help (including parameter listing)\n"
+ << " -u: don't quit on unreferenced parameters\n"
+ << " -D,-U,-I: passed to cpp for preprocessing .ini files\n"
+ << " <config-spec>: config file name (.ini or .py) or\n"
+ << " single param (--<section>:<param>=<value>)"
+ << endl;
}
/// Show verbose help message. Includes parameter listing from
@@ -212,27 +214,6 @@ echoCommandLine(int argc, char **argv, ostream &out)
///
static IniFile simConfigDB;
-/// Check for a default.ini file and load it if necessary.
-static void
-handleDefaultIni(bool &loadIt, vector<char *> &cppArgs)
-{
- struct stat sb;
-
- if (loadIt) {
- if (stat("default.ini", &sb) == 0) {
- if (!simConfigDB.loadCPP("default.ini", cppArgs)) {
- cout << "Error processing file default.ini" << endl;
- exit(1);
- }
- }
-
- // set this whether it actually was found or not, so we don't
- // bother to check again next time
- loadIt = false;
- }
-}
-
-
/// M5 entry point.
int
main(int argc, char **argv)
@@ -254,21 +235,13 @@ main(int argc, char **argv)
vector<char *> cppArgs;
- // Should we use default.ini if it exists? By default, yes. (Use
- // -n to override.)
- bool loadDefaultIni = true;
-
// Should we quit if there are unreferenced parameters? By
// default, yes... it's a good way of catching typos in
// section/parameter names (which otherwise go by silently). Use
// -u to override.
bool quitOnUnreferenced = true;
- // Parse command-line options. The tricky part here is figuring
- // out whether to look for & load default.ini, and if needed,
- // doing so at the right time w.r.t. processing the other
- // parameters.
- //
+ // Parse command-line options.
// Since most of the complex options are handled through the
// config database, we don't mess with getopts, and just parse
// manually.
@@ -286,17 +259,6 @@ main(int argc, char **argv)
showLongHelp(cerr);
exit(1);
- case 'n':
- // -n: don't load default.ini
- if (!loadDefaultIni) {
- cerr << "Warning: -n option needs to precede any "
- << "explicit configuration file name " << endl
- << " or command-line configuration parameter."
- << endl;
- }
- loadDefaultIni = false;
- break;
-
case 'u':
// -u: don't quit on unreferenced parameters
quitOnUnreferenced = false;
@@ -317,11 +279,6 @@ main(int argc, char **argv)
case '-':
// command-line configuration parameter:
// '--<section>:<parameter>=<value>'
-
- // Load default.ini if necessary -- see comment in
- // else clause below.
- handleDefaultIni(loadDefaultIni, cppArgs);
-
if (!simConfigDB.add(arg_str + 2)) {
// parse error
ccprintf(cerr,
@@ -350,13 +307,6 @@ main(int argc, char **argv)
(ext_loc != string::npos) ? filename.substr(ext_loc) : "";
if (ext == ".ini") {
- // If we haven't loaded default.ini yet, and we want to,
- // now is the time. Can't do it sooner because we need to
- // look for '-n', can't do it later since we want
- // default.ini loaded first (so that any other settings
- // override it).
- handleDefaultIni(loadDefaultIni, cppArgs);
-
if (!simConfigDB.loadCPP(filename, cppArgs)) {
cprintf("Error processing file %s\n", filename);
exit(1);
@@ -375,10 +325,6 @@ main(int argc, char **argv)
}
}
- // Final check for default.ini, in case no config files or
- // command-line config parameters were given.
- handleDefaultIni(loadDefaultIni, cppArgs);
-
// The configuration database is now complete; start processing it.
// Parse and check all non-config-hierarchy parameters.
@@ -396,13 +342,16 @@ main(int argc, char **argv)
// Echo command line and all parameter settings to stats file as well.
echoCommandLine(argc, argv, *outputStream);
- ParamContext::showAllContexts(builderStream());
+ ParamContext::showAllContexts(*configStream);
// Now process the configuration hierarchy and create the SimObjects.
ConfigHierarchy configHierarchy(simConfigDB);
configHierarchy.build();
configHierarchy.createSimObjects();
+ // Do a second pass to finish initializing the sim objects
+ SimObject::initAll();
+
// Restore checkpointed state, if any.
configHierarchy.unserializeSimObjects();
@@ -435,9 +384,8 @@ main(int argc, char **argv)
exit(1);
}
- SimInit();
warn("Entering event queue. Starting simulation...\n");
-
+ SimStartup();
while (!mainEventQueue.empty()) {
assert(curTick <= mainEventQueue.nextTick() &&
"event scheduled in the past");
diff --git a/sim/param.cc b/sim/param.cc
index 4f9d0a577..d20be8d33 100644
--- a/sim/param.cc
+++ b/sim/param.cc
@@ -211,6 +211,11 @@ template <class T>
void
VectorParam<T>::parse(const string &s)
{
+ if (s.empty()) {
+ wasSet = true;
+ return;
+ }
+
vector<string> tokens;
tokenize(tokens, s, ' ');
@@ -555,15 +560,27 @@ SimObjectBaseParam::parse(const string &s, vector<SimObject *>&value)
list<ParamContext *> *ParamContext::ctxList = NULL;
-ParamContext::ParamContext(const string &_iniSection, bool noAutoParse)
+ParamContext::ParamContext(const string &_iniSection, InitPhase _initPhase)
: iniFilePtr(NULL), // initialized on call to parseParams()
- iniSection(_iniSection), paramList(NULL)
+ iniSection(_iniSection), paramList(NULL),
+ initPhase(_initPhase)
{
- if (!noAutoParse) {
+ // Put this context on global list for initialization
+ if (initPhase != NoAutoInit) {
if (ctxList == NULL)
ctxList = new list<ParamContext *>();
- (*ctxList).push_back(this);
+ // keep list sorted by ascending initPhase values
+ list<ParamContext *>::iterator i = ctxList->begin();
+ list<ParamContext *>::iterator end = ctxList->end();
+ for (; i != end; ++i) {
+ if (initPhase <= (*i)->initPhase) {
+ // found where we want to insert
+ break;
+ }
+ }
+ // (fall through case: insert at end)
+ ctxList->insert(i, this);
}
}
diff --git a/sim/param.hh b/sim/param.hh
index fe13edc48..ac57afa31 100644
--- a/sim/param.hh
+++ b/sim/param.hh
@@ -34,6 +34,7 @@
#include <vector>
#include "sim/configfile.hh"
+#include "sim/startup.hh"
// forward decls
class BaseParam;
@@ -44,7 +45,7 @@ class SimObject;
// SimObjectBuilder (which derives from ParamContext), but abstracted
// here to support more global simulator control parameters as well.
//
-class ParamContext
+class ParamContext : protected StartupCallback
{
private:
@@ -74,11 +75,30 @@ class ParamContext
public:
- // Second arg, if set to true, says don't put on paramContextList
- // (i.e. don't automatically parse params). Used by derived
- // SimObjectBuilder class, where parsing is done in
- // SimObject::create()
- ParamContext(const std::string &_iniSection, bool noAutoParse = false);
+ /// Initialization phases for ParamContext objects.
+ enum InitPhase {
+ NoAutoInit = -1, ///< Don't initialize at all... params
+ /// will be parsed later (used by
+ /// SimObjectBuilder, which parses
+ /// params in SimObject::create().
+ OutputInitPhase = 0, ///< Output stream initialization
+ TraceInitPhase = 1, ///< Trace context initialization:
+ /// depends on output streams, but
+ /// needs to come before others so we
+ /// can use tracing in other
+ /// ParamContext init code
+ StatsInitPhase = 2, ///< Stats output initialization
+ DefaultInitPhase = 3 ///< Everything else
+ };
+
+ /// Records the initialization phase for this ParamContext.
+ InitPhase initPhase;
+
+ /// Constructor.
+ /// @param _iniSection Name of .ini section corresponding to this context.
+ /// @param _initPhase Initialization phase (see InitPhase).
+ ParamContext(const std::string &_iniSection,
+ InitPhase _initPhase = DefaultInitPhase);
virtual ~ParamContext() {}
diff --git a/sim/process.cc b/sim/process.cc
index 7f93c1d9e..bd1a2d8fd 100644
--- a/sim/process.cc
+++ b/sim/process.cc
@@ -34,6 +34,7 @@
#include "base/intmath.hh"
#include "base/loader/object_file.hh"
+#include "base/loader/symtab.hh"
#include "base/statistics.hh"
#include "cpu/exec_context.hh"
#include "cpu/full_cpu/smt.hh"
@@ -161,7 +162,7 @@ Process::registerExecContext(ExecContext *xc)
void
-Process::replaceExecContext(int xcIndex, ExecContext *xc)
+Process::replaceExecContext(ExecContext *xc, int xcIndex)
{
if (xcIndex >= execContexts.size()) {
panic("replaceExecContext: bad xcIndex, %d >= %d\n",
@@ -263,6 +264,18 @@ LiveProcess::LiveProcess(const string &name, ObjectFile *objFile,
// load object file into target memory
objFile->loadSections(memory);
+ // load up symbols, if any... these may be used for debugging or
+ // profiling.
+ if (!debugSymbolTable) {
+ debugSymbolTable = new SymbolTable();
+ if (!objFile->loadGlobalSymbols(debugSymbolTable) ||
+ !objFile->loadLocalSymbols(debugSymbolTable)) {
+ // didn't load any symbols
+ delete debugSymbolTable;
+ 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);
@@ -392,14 +405,10 @@ CREATE_SIM_OBJECT(LiveProcess)
// dummy for default env
vector<string> null_vec;
- // We do this with "temp" because of the bogus compiler warning
- // you get with g++ 2.95 -O if you just "return new LiveProcess(..."
- LiveProcess *temp = LiveProcess::create(getInstanceName(),
- stdin_fd, stdout_fd, stderr_fd,
- cmd,
- env.isValid() ? env : null_vec);
-
- return temp;
+ return LiveProcess::create(getInstanceName(),
+ stdin_fd, stdout_fd, stderr_fd,
+ cmd,
+ env.isValid() ? env : null_vec);
}
diff --git a/sim/process.hh b/sim/process.hh
index bd6adc55c..bb4829875 100644
--- a/sim/process.hh
+++ b/sim/process.hh
@@ -130,7 +130,7 @@ class Process : public SimObject
int registerExecContext(ExecContext *xc);
- void replaceExecContext(int xcIndex, ExecContext *xc);
+ void replaceExecContext(ExecContext *xc, int xcIndex);
// map simulator fd sim_fd to target fd tgt_fd
void dup_fd(int sim_fd, int tgt_fd);
diff --git a/sim/serialize.cc b/sim/serialize.cc
index 91548f653..2a5e3d398 100644
--- a/sim/serialize.cc
+++ b/sim/serialize.cc
@@ -335,10 +335,7 @@ SerializeParamContext::checkParams()
if (serialize_dir.isValid()) {
checkpointDirBase = serialize_dir;
} else {
- if (outputDirectory.empty())
- checkpointDirBase = "m5.%012d";
- else
- checkpointDirBase = outputDirectory + "cpt.%012d";
+ checkpointDirBase = outputDirectory + "cpt.%012d";
}
// guarantee that directory ends with a '/'
diff --git a/sim/sim_events.cc b/sim/sim_events.cc
index c454fdcf9..99c09f259 100644
--- a/sim/sim_events.cc
+++ b/sim/sim_events.cc
@@ -34,7 +34,7 @@
#include "sim/param.hh"
#include "sim/sim_events.hh"
#include "sim/sim_exit.hh"
-#include "sim/sim_init.hh"
+#include "sim/startup.hh"
#include "sim/stats.hh"
using namespace std;
@@ -210,12 +210,11 @@ ProgressEvent::description()
// Parameter space for execution address tracing options. Derive
// from ParamContext so we can override checkParams() function.
-class ProgressParamContext : public ParamContext
+struct ProgressParamContext : public ParamContext
{
- public:
ProgressParamContext(const string &_iniSection)
: ParamContext(_iniSection) {}
- void checkParams();
+ void startup();
};
ProgressParamContext progessMessageParams("progress");
@@ -223,24 +222,9 @@ ProgressParamContext progessMessageParams("progress");
Param<Tick> progress_interval(&progessMessageParams, "cycle",
"cycle interval for progress messages");
-namespace {
- struct SetupProgress : public Callback
- {
- Tick interval;
- SetupProgress(Tick tick) : interval(tick) {}
-
- virtual void process()
- {
- new ProgressEvent(&mainEventQueue, interval);
- delete this;
- }
- };
-}
-
-/* check execute options */
void
-ProgressParamContext::checkParams()
+ProgressParamContext::startup()
{
if (progress_interval.isValid())
- registerInitCallback(new SetupProgress(progress_interval));
+ new ProgressEvent(&mainEventQueue, progress_interval);
}
diff --git a/sim/sim_object.hh b/sim/sim_object.hh
index dfd70f8ec..f4b316ebb 100644
--- a/sim/sim_object.hh
+++ b/sim/sim_object.hh
@@ -39,13 +39,14 @@
#include <iostream>
#include "sim/serialize.hh"
+#include "sim/startup.hh"
/*
* Abstract superclass for simulation objects. Represents things that
* correspond to physical components and can be specified via the
* config file (CPUs, caches, etc.).
*/
-class SimObject : public Serializable
+class SimObject : public Serializable, protected StartupCallback
{
protected:
std::string objName;
@@ -65,7 +66,8 @@ class SimObject : public Serializable
virtual const std::string name() const { return objName; }
- // initialization pass of all objects. Gets invoked by SimInit()
+ // initialization pass of all objects.
+ // Gets invoked after construction, before unserialize.
virtual void init();
static void initAll();
diff --git a/sim/startup.cc b/sim/startup.cc
new file mode 100644
index 000000000..ebb4c0bc0
--- /dev/null
+++ b/sim/startup.cc
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2004 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 <list>
+
+#include "base/misc.hh"
+#include "sim/startup.hh"
+#include "sim/debug.hh"
+
+typedef std::list<StartupCallback *> startupq_t;
+startupq_t &startupq() { static startupq_t queue; return queue; }
+StartupCallback::StartupCallback() { startupq().push_back(this); }
+StartupCallback::~StartupCallback() { startupq().remove(this); }
+void StartupCallback::startup() { }
+
+void
+SimStartup()
+{
+ startupq_t::iterator i = startupq().begin();
+ startupq_t::iterator end = startupq().end();
+
+ while (i != end) {
+ (*i)->startup();
+ ++i;
+ }
+}
diff --git a/sim/startup.hh b/sim/startup.hh
new file mode 100644
index 000000000..e6c03a500
--- /dev/null
+++ b/sim/startup.hh
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2004 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 __SIM_STARTUP_HH__
+#define __SIM_STARTUP_HH__
+
+struct StartupCallback
+{
+ StartupCallback();
+ virtual ~StartupCallback();
+ virtual void startup();
+};
+
+void SimStartup();
+
+#endif // __SIM_STARTUP_HH__
diff --git a/sim/system.cc b/sim/system.cc
index b5a0e7a56..c6a65f9d9 100644
--- a/sim/system.cc
+++ b/sim/system.cc
@@ -26,7 +26,13 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
+#include "base/loader/object_file.hh"
+#include "base/loader/symtab.hh"
+#include "base/remote_gdb.hh"
#include "cpu/exec_context.hh"
+#include "kern/kernel_stats.hh"
+#include "mem/functional_mem/memory_control.hh"
+#include "mem/functional_mem/physical_memory.hh"
#include "targetarch/vtophys.hh"
#include "sim/param.hh"
#include "sim/system.hh"
@@ -38,237 +44,229 @@ vector<System *> System::systemList;
int System::numSystemsRunning = 0;
-System::System(const std::string _name,
- const uint64_t _init_param,
- MemoryController *_memCtrl,
- PhysicalMemory *_physmem,
- const bool _bin,
- const std::vector<string> &binned_fns)
-
- : SimObject(_name),
- init_param(_init_param),
- memCtrl(_memCtrl),
- physmem(_physmem),
- bin(_bin),
- binned_fns(binned_fns)
+System::System(Params *p)
+ : SimObject(p->name), memctrl(p->memctrl), physmem(p->physmem),
+ init_param(p->init_param), params(p)
{
- // increment the number of running systems
- numSystemsRunning++;
-
// add self to global system list
systemList.push_back(this);
- if (bin == true) {
- Kernel = new Stats::MainBin("non TCPIP Kernel stats");
- Kernel->activate();
- User = new Stats::MainBin("User stats");
- int end = binned_fns.size();
- assert(!(end & 1));
+ kernelSymtab = new SymbolTable;
+ consoleSymtab = new SymbolTable;
+ palSymtab = new SymbolTable;
+ debugSymbolTable = new SymbolTable;
+
+ /**
+ * Load the kernel, pal, and console code into memory
+ */
+ // Load kernel code
+ kernel = createObjectFile(params->kernel_path);
+ if (kernel == NULL)
+ fatal("Could not load kernel file %s", params->kernel_path);
+
+ // Load Console Code
+ console = createObjectFile(params->console_path);
+ if (console == NULL)
+ fatal("Could not load console file %s", params->console_path);
+
+ // Load pal file
+ pal = createObjectFile(params->palcode);
+ if (pal == NULL)
+ fatal("Could not load PALcode file %s", params->palcode);
+
+
+ // Load program sections into memory
+ pal->loadSections(physmem, true);
+ console->loadSections(physmem, true);
+ kernel->loadSections(physmem, true);
+
+ // setup entry points
+ kernelStart = kernel->textBase();
+ kernelEnd = kernel->bssBase() + kernel->bssSize();
+ kernelEntry = kernel->entryPoint();
+
+ // load symbols
+ if (!kernel->loadGlobalSymbols(kernelSymtab))
+ panic("could not load kernel symbols\n");
+
+ if (!kernel->loadLocalSymbols(kernelSymtab))
+ panic("could not load kernel local symbols\n");
+
+ if (!console->loadGlobalSymbols(consoleSymtab))
+ panic("could not load console symbols\n");
+
+ if (!pal->loadGlobalSymbols(palSymtab))
+ panic("could not load pal symbols\n");
+
+ if (!pal->loadLocalSymbols(palSymtab))
+ panic("could not load pal symbols\n");
+
+ if (!kernel->loadGlobalSymbols(debugSymbolTable))
+ panic("could not load kernel symbols\n");
+
+ if (!kernel->loadLocalSymbols(debugSymbolTable))
+ panic("could not load kernel local symbols\n");
+
+ if (!console->loadGlobalSymbols(debugSymbolTable))
+ panic("could not load console symbols\n");
+
+ if (!pal->loadGlobalSymbols(debugSymbolTable))
+ panic("could not load pal symbols\n");
+
+ if (!pal->loadLocalSymbols(debugSymbolTable))
+ panic("could not load pal symbols\n");
+
- Stats::MainBin *Bin;
+ DPRINTF(Loader, "Kernel start = %#x\n", kernelStart);
+ DPRINTF(Loader, "Kernel end = %#x\n", kernelEnd);
+ DPRINTF(Loader, "Kernel entry = %#x\n", kernelEntry);
+ DPRINTF(Loader, "Kernel loaded...\n");
- fnEvents.resize(end>>1);
+ Addr addr = 0;
+#ifdef DEBUG
+ consolePanicEvent = new BreakPCEvent(&pcEventQueue, "console panic");
+ if (consoleSymtab->findAddress("panic", addr))
+ consolePanicEvent->schedule(addr);
+#endif
- for (int i = 0; i < end; i +=2) {
- Bin = new Stats::MainBin(binned_fns[i]);
- fnBins.insert(make_pair(binned_fns[i], Bin));
+ /**
+ * Copy the osflags (kernel arguments) into the consoles
+ * memory. (Presently Linux does not use the console service
+ * routine to get these command line arguments, but Tru64 and
+ * others do.)
+ */
+ if (consoleSymtab->findAddress("env_booted_osflags", addr)) {
+ Addr paddr = vtophys(physmem, addr);
+ char *osflags = (char *)physmem->dma_addr(paddr, sizeof(uint32_t));
- fnEvents[(i>>1)] = new FnEvent(&pcEventQueue, binned_fns[i], this);
+ if (osflags)
+ strcpy(osflags, params->boot_osflags.c_str());
+ }
- if (binned_fns[i+1] == "null")
- populateMap(binned_fns[i], "");
- else
- populateMap(binned_fns[i], binned_fns[i+1]);
- }
+ /**
+ * Set the hardware reset parameter block system type and revision
+ * information to Tsunami.
+ */
+ if (consoleSymtab->findAddress("xxm_rpb", addr)) {
+ Addr paddr = vtophys(physmem, addr);
+ char *hwrpb = (char *)physmem->dma_addr(paddr, sizeof(uint64_t));
- fnCalls
- .name(name() + ":fnCalls")
- .desc("all fn calls being tracked")
- ;
+ if (!hwrpb)
+ panic("could not translate hwrpb addr\n");
+ *(uint64_t*)(hwrpb+0x50) = htoa(params->system_type);
+ *(uint64_t*)(hwrpb+0x58) = htoa(params->system_rev);
} else
- Kernel = NULL;
-}
+ panic("could not find hwrpb\n");
+ // increment the number of running systms
+ numSystemsRunning++;
+
+ kernelBinning = new Kernel::Binning(this);
+}
System::~System()
{
- if (bin == true) {
- int end = fnEvents.size();
- for (int i = 0; i < end; ++i) {
- delete fnEvents[i];
- }
- fnEvents.clear();
- }
+ delete kernelSymtab;
+ delete consoleSymtab;
+ delete kernel;
+ delete console;
+ delete pal;
+
+ delete kernelBinning;
+
+#ifdef DEBUG
+ delete consolePanicEvent;
+#endif
}
+bool
+System::breakpoint()
+{
+ return remoteGDB[0]->trap(ALPHA_KENTRY_INT);
+}
int
System::registerExecContext(ExecContext *xc)
{
- int myIndex = execContexts.size();
+ int xcIndex = execContexts.size();
execContexts.push_back(xc);
- return myIndex;
-}
-
-void
-System::replaceExecContext(int xcIndex, ExecContext *xc)
-{
- if (xcIndex >= execContexts.size()) {
- panic("replaceExecContext: bad xcIndex, %d >= %d\n",
- xcIndex, execContexts.size());
+ RemoteGDB *rgdb = new RemoteGDB(this, xc);
+ GDBListener *gdbl = new GDBListener(rgdb, 7000 + xcIndex);
+ gdbl->listen();
+ /**
+ * Uncommenting this line waits for a remote debugger to connect
+ * to the simulator before continuing.
+ */
+ //gdbl->accept();
+
+ if (remoteGDB.size() <= xcIndex) {
+ remoteGDB.resize(xcIndex+1);
}
- execContexts[xcIndex] = xc;
-}
+ remoteGDB[xcIndex] = rgdb;
+ return xcIndex;
+}
void
-System::printSystems()
+System::startup()
{
- vector<System *>::iterator i = systemList.begin();
- vector<System *>::iterator end = systemList.end();
- for (; i != end; ++i) {
- System *sys = *i;
- cerr << "System " << sys->name() << ": " << hex << sys << endl;
+ if (!execContexts.empty()) {
+ // activate with zero delay so that we start ticking right
+ // away on cycle 0
+ execContexts[0]->activate(0);
}
}
-extern "C"
void
-printSystems()
+System::replaceExecContext(ExecContext *xc, int xcIndex)
{
- System::printSystems();
-}
+ if (xcIndex >= execContexts.size()) {
+ panic("replaceExecContext: bad xcIndex, %d >= %d\n",
+ xcIndex, execContexts.size());
+ }
-void
-System::populateMap(std::string callee, std::string caller)
-{
- multimap<const string, string>::const_iterator i;
- i = callerMap.insert(make_pair(callee, caller));
- assert(i != callerMap.end() && "should not fail populating callerMap");
+ execContexts[xcIndex] = xc;
+ remoteGDB[xcIndex]->replaceExecContext(xc);
}
-bool
-System::findCaller(std::string callee, std::string caller) const
+void
+System::regStats()
{
- typedef multimap<const std::string, std::string>::const_iterator iter;
- pair<iter, iter> range;
-
- range = callerMap.equal_range(callee);
- for (iter i = range.first; i != range.second; ++i) {
- if ((*i).second == caller)
- return true;
- }
- return false;
+ kernelBinning->regStats(name() + ".kern");
}
void
-System::dumpState(ExecContext *xc) const
+System::serialize(ostream &os)
{
- if (xc->swCtx) {
- stack<fnCall *> copy(xc->swCtx->callStack);
- if (copy.empty())
- return;
- DPRINTF(TCPIP, "xc->swCtx, size: %d:\n", copy.size());
- fnCall *top;
- DPRINTF(TCPIP, "|| call : %d\n",xc->swCtx->calls);
- for (top = copy.top(); !copy.empty(); copy.pop() ) {
- top = copy.top();
- DPRINTF(TCPIP, "|| %13s : %s \n", top->name, top->myBin->name());
- }
- }
+ kernelBinning->serialize(os);
}
-Stats::MainBin *
-System::getBin(const std::string &name)
-{
- std::map<const std::string, Stats::MainBin *>::const_iterator i;
- i = fnBins.find(name);
- if (i == fnBins.end())
- panic("trying to getBin %s that is not on system map!", name);
- return (*i).second;
-}
-SWContext *
-System::findContext(Addr pcb)
+void
+System::unserialize(Checkpoint *cp, const string &section)
{
- std::map<Addr, SWContext *>::const_iterator iter;
- iter = swCtxMap.find(pcb);
- if (iter != swCtxMap.end()) {
- SWContext *ctx = (*iter).second;
- assert(ctx != NULL && "should never have a null ctx in ctxMap");
- return ctx;
- } else
- return NULL;
+ kernelBinning->unserialize(cp, section);
}
void
-System::serialize(std::ostream &os)
+System::printSystems()
{
- if (bin == true) {
- map<const Addr, SWContext *>::const_iterator iter, end;
- iter = swCtxMap.begin();
- end = swCtxMap.end();
-
- int numCtxs = swCtxMap.size();
- SERIALIZE_SCALAR(numCtxs);
- SWContext *ctx;
- for (int i = 0; iter != end; ++i, ++iter) {
- paramOut(os, csprintf("Addr[%d]",i), (*iter).first);
- ctx = (*iter).second;
- paramOut(os, csprintf("calls[%d]",i), ctx->calls);
-
- stack<fnCall *> *stack = &(ctx->callStack);
- fnCall *top;
- int size = stack->size();
- paramOut(os, csprintf("stacksize[%d]",i), size);
- for (int j=0; j<size; ++j) {
- top = stack->top();
- paramOut(os, csprintf("ctx[%d].stackpos[%d]",i,j),
- top->name);
- delete top;
- stack->pop();
- }
- }
+ vector<System *>::iterator i = systemList.begin();
+ vector<System *>::iterator end = systemList.end();
+ for (; i != end; ++i) {
+ System *sys = *i;
+ cerr << "System " << sys->name() << ": " << hex << sys << endl;
}
}
+extern "C"
void
-System::unserialize(Checkpoint *cp, const std::string &section)
+printSystems()
{
- if (bin == true) {
- int numCtxs;
- UNSERIALIZE_SCALAR(numCtxs);
-
- SWContext *ctx;
- Addr addr;
- int size;
- for(int i = 0; i < numCtxs; ++i) {
- ctx = new SWContext;
- paramIn(cp, section, csprintf("Addr[%d]",i), addr);
- paramIn(cp, section, csprintf("calls[%d]",i), ctx->calls);
-
- paramIn(cp, section, csprintf("stacksize[%d]",i), size);
-
- vector<fnCall *> calls;
- fnCall *call;
- for (int j = 0; j < size; ++j) {
- call = new fnCall;
- paramIn(cp, section, csprintf("ctx[%d].stackpos[%d]",i,j),
- call->name);
- call->myBin = getBin(call->name);
- calls.push_back(call);
- }
-
- for (int j=size-1; j>=0; --j) {
- ctx->callStack.push(calls[j]);
- }
-
- addContext(addr, ctx);
- }
- }
+ System::printSystems();
}
DEFINE_SIM_OBJECT_CLASS_NAME("System", System)
diff --git a/sim/system.hh b/sim/system.hh
index da974cfdd..07881ff01 100644
--- a/sim/system.hh
+++ b/sim/system.hh
@@ -32,85 +32,123 @@
#include <string>
#include <vector>
-#include "base/loader/symtab.hh"
#include "base/statistics.hh"
#include "cpu/pc_event.hh"
#include "kern/system_events.hh"
#include "sim/sim_object.hh"
-#include "sim/sw_context.hh"
class MemoryController;
class PhysicalMemory;
class Platform;
class RemoteGDB;
class GDBListener;
-
+class SymbolTable;
+class ObjectFile;
class ExecContext;
+namespace Kernel { class Binning; }
class System : public SimObject
{
- // lisa's binning stuff
- private:
- std::map<const std::string, Stats::MainBin *> fnBins;
- std::map<const Addr, SWContext *> swCtxMap;
+ public:
+ MemoryController *memctrl;
+ PhysicalMemory *physmem;
+ Platform *platform;
+ PCEventQueue pcEventQueue;
+ uint64_t init_param;
- protected:
- std::vector<FnEvent *> fnEvents;
+ std::vector<ExecContext *> execContexts;
- public:
- Stats::Scalar<> fnCalls;
- Stats::MainBin *Kernel;
- Stats::MainBin *User;
+ /** kernel Symbol table */
+ SymbolTable *kernelSymtab;
- Stats::MainBin * getBin(const std::string &name);
- bool findCaller(std::string, std::string) const;
+ /** console symbol table */
+ SymbolTable *consoleSymtab;
- SWContext *findContext(Addr pcb);
- bool addContext(Addr pcb, SWContext *ctx) {
- return (swCtxMap.insert(make_pair(pcb, ctx))).second;
- }
- void remContext(Addr pcb) {
- swCtxMap.erase(pcb);
- return;
- }
- void dumpState(ExecContext *xc) const;
+ /** pal symbol table */
+ SymbolTable *palSymtab;
- virtual void serialize(std::ostream &os);
- virtual void unserialize(Checkpoint *cp, const std::string &section);
+ /** Object pointer for the kernel code */
+ ObjectFile *kernel;
+ /** Object pointer for the console code */
+ ObjectFile *console;
- private:
- std::multimap<const std::string, std::string> callerMap;
- void populateMap(std::string caller, std::string callee);
-//
+ /** Object pointer for the PAL code */
+ ObjectFile *pal;
- public:
- const uint64_t init_param;
- MemoryController *memCtrl;
- PhysicalMemory *physmem;
- Platform *platform;
- bool bin;
- std::vector<string> binned_fns;
+ /** Begining of kernel code */
+ Addr kernelStart;
- PCEventQueue pcEventQueue;
+ /** End of kernel code */
+ Addr kernelEnd;
- std::vector<ExecContext *> execContexts;
+ /** Entry point in the kernel to start at */
+ Addr kernelEntry;
- std::string readfile;
+ Kernel::Binning *kernelBinning;
- virtual int registerExecContext(ExecContext *xc);
- virtual void replaceExecContext(int xcIndex, ExecContext *xc);
+#ifdef DEBUG
+ /** Event to halt the simulator if the console calls panic() */
+ BreakPCEvent *consolePanicEvent;
+#endif
public:
- System(const std::string _name, const uint64_t _init_param,
- MemoryController *, PhysicalMemory *, const bool,
- const std::vector<string> &binned_fns);
+ std::vector<RemoteGDB *> remoteGDB;
+ std::vector<GDBListener *> gdbListen;
+ bool breakpoint();
+
+ public:
+ struct Params
+ {
+ std::string name;
+ MemoryController *memctrl;
+ PhysicalMemory *physmem;
+ uint64_t init_param;
+ bool bin;
+ std::vector<std::string> binned_fns;
+ bool bin_int;
+
+ std::string kernel_path;
+ std::string console_path;
+ std::string palcode;
+ std::string boot_osflags;
+
+ std::string readfile;
+ uint64_t system_type;
+ uint64_t system_rev;
+ };
+ Params *params;
+
+ System(Params *p);
~System();
- virtual Addr getKernelStart() const = 0;
- virtual Addr getKernelEnd() const = 0;
- virtual Addr getKernelEntry() const = 0;
- virtual bool breakpoint() = 0;
+ void startup();
+
+ public:
+ /**
+ * Returns the addess the kernel starts at.
+ * @return address the kernel starts at
+ */
+ Addr getKernelStart() const { return kernelStart; }
+
+ /**
+ * Returns the addess the kernel ends at.
+ * @return address the kernel ends at
+ */
+ Addr getKernelEnd() const { return kernelEnd; }
+
+ /**
+ * Returns the addess the entry point to the kernel code.
+ * @return entry point of the kernel code
+ */
+ Addr getKernelEntry() const { return kernelEntry; }
+
+ int registerExecContext(ExecContext *xc);
+ void replaceExecContext(ExecContext *xc, int xcIndex);
+
+ void regStats();
+ void serialize(std::ostream &os);
+ void unserialize(Checkpoint *cp, const std::string &section);
public:
////////////////////////////////////////////
diff --git a/sim/universe.cc b/sim/universe.cc
index 79e32098c..824b985fa 100644
--- a/sim/universe.cc
+++ b/sim/universe.cc
@@ -51,14 +51,13 @@ double __ticksPerPS;
string outputDirectory;
ostream *outputStream;
+ostream *configStream;
class UniverseParamContext : public ParamContext
{
- private:
- ofstream outputFile;
-
public:
- UniverseParamContext(const string &is) : ParamContext(is) {}
+ UniverseParamContext(const string &is)
+ : ParamContext(is, OutputInitPhase) {}
void checkParams();
};
@@ -68,9 +67,14 @@ Param<Tick> universe_freq(&universe, "frequency", "tick frequency",
200000000);
Param<string> universe_output_dir(&universe, "output_dir",
- "directory to output data to");
+ "directory to output data to",
+ ".");
Param<string> universe_output_file(&universe, "output_file",
- "file to dump simulator output to");
+ "file to dump simulator output to",
+ "cout");
+Param<string> universe_config_output_file(&universe, "config_output_file",
+ "file to dump simulator config to",
+ "m5config.out");
void
UniverseParamContext::checkParams()
@@ -97,26 +101,49 @@ UniverseParamContext::checkParams()
}
}
- string filename;
- if (universe_output_file.isValid()) {
- string f = universe_output_file;
- if (f != "stdout" && f != "cout" && f != "stderr" && f != "cerr")
- filename = outputDirectory + f;
- else
- filename = f;
- } else {
- if (outputDirectory.empty())
- filename = "stdout";
- else
- filename = outputDirectory + "output.txt";
- }
+ outputStream = makeOutputStream(universe_output_file);
+ configStream = universe_config_output_file.isValid()
+ ? makeOutputStream(universe_config_output_file)
+ : outputStream;
+}
- if (filename == "stdout" || filename == "cout")
- outputStream = &cout;
- else if (filename == "stderr" || filename == "cerr")
- outputStream = &cerr;
- else {
- outputFile.open(filename.c_str(), ios::trunc);
- outputStream = &outputFile;
- }
+
+std::ostream *
+makeOutputStream(std::string &name)
+{
+ if (name == "cerr" || name == "stderr")
+ return &std::cerr;
+
+ if (name == "cout" || name == "stdout")
+ return &std::cout;
+
+ string path = (name[0] != '/') ? outputDirectory + name : name;
+
+ // have to dynamically allocate a stream since we're going to
+ // return it... though the caller can't easily free it since it
+ // may be cerr or cout. need GC!
+ ofstream *s = new ofstream(path.c_str(), ios::trunc);
+
+ if (!s->is_open())
+ fatal("Cannot open file %s", path);
+
+ return s;
}
+
+
+void
+closeOutputStream(std::ostream *os)
+{
+ // can't close cerr or cout
+ if (os == &std::cerr || os == &std::cout)
+ return;
+
+ // can only close ofstreams, not generic ostreams, so try to
+ // downcast and close only if the downcast succeeds
+ std::ofstream *ofs = dynamic_cast<std::ofstream *>(os);
+ if (ofs)
+ ofs->close();
+}
+
+
+
diff --git a/util/ccdrv/devtime.c b/util/ccdrv/devtime.c
index e487f2fe7..62b0e2592 100644
--- a/util/ccdrv/devtime.c
+++ b/util/ccdrv/devtime.c
@@ -48,6 +48,9 @@
static char *dataAddr = NULL;
static int count = 0;
+#ifdef __alpha__
+static int memTest = 0;
+#endif
static inline uint32_t cycleCounter(uint32_t dep);
@@ -63,6 +66,31 @@ static int __init devtime_start(void)
printk("Devtime Driver Version %s Loaded...\n", DRIVER_VER);
+#ifdef __alpha__
+ if (memTest) {
+ addr = 0xfffffc0000000000;
+// addr += 16*1024*1024;
+
+ printk("Preparing memory test.\n");
+
+ t1 = cycleCounter(trash);
+ for (x = 0; x < count; x++) {
+ trash = readl(addr);
+ t2 = cycleCounter(trash);
+ times[num++] = t2 - t1;
+ t1 = t2;
+ addr += 4096;
+ }
+
+ printk("Measurements:\n");
+ for (x = 0; x < count; x++) {
+ printk("%d ", times[x]);
+ if (((x + 1) % 10) == 0)
+ printk("\n");
+ }
+ printk("\nDone.\n");
+ } else
+#endif
if (dataAddr != 0 && count != 0) {
addr = simple_strtoull(dataAddr, NULL, 0);
@@ -145,7 +173,7 @@ inline uint32_t cycleCounter(uint32_t dep)
return res;
}
#else
-#error Architecture NOT SUPPORTE
+#error Architecture NOT SUPPORTED
#endif
static void __exit devtime_end(void)
@@ -162,3 +190,6 @@ MODULE_AUTHOR(DRIVER_AUTHOR);
MODULE_DESCRIPTION(DRIVER_DESC);
module_param(dataAddr, charp, 0);
module_param(count, int, 0);
+#ifdef __alpha__
+module_param(memTest, int, 0);
+#endif
diff --git a/util/stats/info.py b/util/stats/info.py
index a94563cf9..fa318a650 100644
--- a/util/stats/info.py
+++ b/util/stats/info.py
@@ -47,28 +47,21 @@ def wrapop(op, lv, rv):
return op(lv, rv)
-def same(lv, rv):
- for lrun,rrun in zip(lv.keys(),rv.keys()):
- if lrun != rrun:
- print 'lrun != rrun'
- print lrun, rrun
- print lv.keys()
- print rv.keys()
+def same(lrun, rrun):
+ for lx,rx in zip(lrun.keys(),rrun.keys()):
+ if lx != rx:
+ print 'lx != rx'
+ print lx, rx
+ print lrun.keys()
+ print rrun.keys()
return False
- for lx,rx in zip(lv[lrun].keys(),rv[rrun].keys()):
- if lx != rx:
- print 'lx != rx'
- print lx, rx
- print lv[lrun].keys()
- print rv[rrun].keys()
+ for ly,ry in zip(lrun[lx].keys(),rrun[rx].keys()):
+ if ly != ry:
+ print 'ly != ry'
+ print ly, ry
+ print lrun[lx].keys()
+ print rrun[rx].keys()
return False
- for ly,ry in zip(lv[lrun][lx].keys(),rv[rrun][rx].keys()):
- if ly != ry:
- print 'ly != ry'
- print ly, ry
- print lv[lrun][lx].keys()
- print rv[rrun][rx].keys()
- return False
return True
@@ -79,10 +72,15 @@ def binaryop(op, lf, rf):
lv = lf.value
rv = rf.value
- if not same(lv, rv):
- raise AttributeError, "run,x,y not identical"
+ theruns = []
+ for r in lv.keys():
+ if rv.has_key(r):
+ if same(lv[r], rv[r]):
+ theruns.append(r)
+ else:
+ raise AttributeError
- for run in lv.keys():
+ for run in theruns:
result[run] = {}
for x in lv[run].keys():
result[run][x] = {}
@@ -152,9 +150,8 @@ class Statistic(object):
def __setattr__(self, attr, value):
if attr == 'bins' or attr == 'ticks':
if attr == 'bins':
- global db
if value is not None:
- value = db.getBin(value)
+ value = source.getBin(value)
elif attr == 'samples' and type(value) is str:
value = [ int(x) for x in value.split() ]
diff --git a/util/stats/stats.py b/util/stats/stats.py
index 1d521fd9d..68ba2b8ea 100755
--- a/util/stats/stats.py
+++ b/util/stats/stats.py
@@ -39,26 +39,51 @@ def unique(list):
map(set.__setitem__, list, [])
return set.keys()
-def graphdata(runs, tag, label, value):
+def graphdata(runs, options, tag, label, value):
import info
- configs = ['std', 'csa', 'ht1', 'ht4', 'htx', 'ocm', 'occ', 'ocp' ]
- benchmarks = [ 'm', 's' ]
- dmas = [ 'x', 'd', 'b' ]
- caches = [ '1', '2', '3', '4', '5' ]
- systems = [ 'M' ]
- checkpoints = [ '1' ]
+ configs = ['ste', 'hte', 'htd', 'ocm', 'occ', 'ocp' ]
+ #benchmarks = [ 'm', 's', 'nb1', 'nb2', 'nt1', 'nt2', 'w1', 'w2', 'w3', 'w4', 'ns', 'nm', 'nw1', 'nw2', 'nw3' ]
+ #benchmarks = [ 'm', 's', 'nb1', 'nb2', 'nt1', 'w1', 'w2', 'w3', 'ns', 'nm', 'w1s' ]
+ benchmarks = [ 'm', 's', 'nb1', 'nb2', 'w1', 'w2', 'w3', 'w4', 'ns', 'nm', 'nw1', 'snt' ]
+ #dmas = [ 'x', 'd', 'b' ]
+ dmas = [ 'x' ]
+ caches = [ '2', '4' ]
names = []
+
+ bench_system = {
+ 'm' : 'client',
+ 's' : 'client',
+ 'snt' : 'client',
+ 'nb1' : 'server',
+ 'nb2' : 'server',
+ 'nt1' : 'server',
+ 'nt2' : 'server',
+ 'w1' : 'server',
+ 'w2' : 'server',
+ 'w3' : 'server',
+ 'w4' : 'server',
+ 'w1s' : 'server',
+ 'w2s' : 'server',
+ 'w3s' : 'server',
+ 'ns' : 'natbox',
+ 'nm' : 'natbox',
+ 'nw1' : 'natbox',
+ 'nw2' : 'natbox',
+ 'nw3' : 'natbox'
+ }
+
for bench in benchmarks:
+ if bench_system[bench] != options.system:
+ continue
+
for dma in dmas:
for cache in caches:
- for sys in systems:
- for cpt in checkpoints:
- names.append([bench, dma, cache, sys, cpt])
+ names.append([bench, dma, cache])
- for bench,dma,cache,sys,cpt in names:
- base = '%s.%s.%s.%s.%s' % (bench, dma, cache, sys, cpt)
- fname = '/n/ziff/z/binkertn/graph/data.ibm/%s.%s.dat' % (tag, base)
+ for bench,dma,cache in names:
+ base = '%s.%s.%s' % (bench, dma, cache)
+ fname = 'data/%s.%s.dat' % (tag, base)
f = open(fname, 'w')
print >>f, '#set TITLE = %s' % base
print >>f, '#set xlbl = Configuration'
@@ -68,8 +93,7 @@ def graphdata(runs, tag, label, value):
for speed,freq in zip(['s', 'q'],['4GHz','10GHz']):
print >>f, '"%s"' % freq,
for conf in configs:
- name = '%s.%s.%s.%s.%s.%s.%s' % (conf, bench, dma, speed,
- cache, sys, cpt)
+ name = '%s.%s.%s.%s.%s' % (conf, bench, dma, cache, speed)
run = info.source.allRunNames[name]
info.display_run = run.run;
val = float(value)
@@ -134,8 +158,6 @@ def commands(options, command, args):
info.source.connect()
info.source.update_dict(globals())
- system = info.source.__dict__[options.system]
-
if type(options.get) is str:
info.source.get = options.get
@@ -177,13 +199,66 @@ def commands(options, command, args):
stats = info.source.getStat(args[0])
for stat in stats:
- if graph:
- graphdata(runs, stat.name, stat.name, stat)
+ if options.graph:
+ graphdata(runs, options, stat.name, stat.name, stat)
else:
+ if options.binned:
+ print 'kernel ticks'
+ stat.bins = 'kernel'
+ printdata(runs, stat)
+
+ print 'idle ticks'
+ stat.bins = 'idle'
+ printdata(runs, stat)
+
+ print 'user ticks'
+ stat.bins = 'user'
+ printdata(runs, stat)
+
+ print 'interrupt ticks'
+ stat.bins = 'user'
+ printdata(runs, stat)
+
+ print 'total ticks'
+
+ stat.bins = None
print stat.name
printdata(runs, stat)
return
+ if command == 'formula':
+ if len(args) != 1:
+ raise CommandException
+
+ stats = eval(args[0])
+ for stat in stats:
+ if options.graph:
+ graphdata(runs, options, stat.name, stat.name, stat)
+ else:
+ if options.binned:
+ print 'kernel ticks'
+ stat.bins = 'kernel'
+ printdata(runs, stat)
+
+ print 'idle ticks'
+ stat.bins = 'idle'
+ printdata(runs, stat)
+
+ print 'user ticks'
+ stat.bins = 'user'
+ printdata(runs, stat)
+
+ print 'interrupt ticks'
+ stat.bins = 'user'
+ printdata(runs, stat)
+
+ print 'total ticks'
+
+ stat.bins = None
+ print args[0]
+ printdata(runs, stat)
+ return
+
if command == 'bins':
if len(args) == 0:
info.source.listBins()
@@ -214,6 +289,8 @@ def commands(options, command, args):
if len(args):
raise CommandException
+ system = info.source.__dict__[options.system]
+
if command == 'usertime':
import copy
kernel = copy.copy(system.full_cpu.numCycles)
@@ -222,15 +299,15 @@ def commands(options, command, args):
user = copy.copy(system.full_cpu.numCycles)
user.bins = 'user'
- if graph:
- graphdata(runs, 'usertime', 'User Fraction',
+ if options.graph:
+ graphdata(runs, options, 'usertime', 'User Fraction',
user / system.full_cpu.numCycles)
else:
printdata(runs, user / system.full_cpu.numCycles)
return
if command == 'ticks':
- if binned:
+ if options.binned:
print 'kernel ticks'
system.full_cpu.numCycles.bins = 'kernel'
printdata(runs, system.full_cpu.numCycles)
@@ -250,37 +327,37 @@ def commands(options, command, args):
return
if command == 'packets':
- packets = system.tsunami.nsgige.rxPackets
- if graph:
- graphdata(runs, 'packets', 'Packets', packets)
+ packets = system.tsunami.etherdev.rxPackets
+ if options.graph:
+ graphdata(runs, options, 'packets', 'Packets', packets)
else:
printdata(runs, packets)
return
if command == 'ppt' or command == 'tpp':
- ppt = system.tsunami.nsgige.rxPackets / sim_ticks
+ ppt = system.tsunami.etherdev.rxPackets / sim_ticks
printdata(runs, ppt, command == 'tpp')
return
if command == 'pps':
- pps = system.tsunami.nsgige.rxPackets / sim_seconds
- if graph:
- graphdata(runs, 'pps', 'Packets/s', pps)
+ pps = system.tsunami.etherdev.rxPackets / sim_seconds
+ if options.graph:
+ graphdata(runs, options, 'pps', 'Packets/s', pps)
else:
printdata(runs, pps)
return
if command == 'bpt' or command == 'tpb':
- bytes = system.tsunami.nsgige.rxBytes + system.tsunami.nsgige.txBytes
+ bytes = system.tsunami.etherdev.rxBytes + system.tsunami.etherdev.txBytes
bpt = bytes / sim_ticks * 8
- if graph:
- graphdata(runs, 'bpt', 'bps / Hz', bpt)
+ if options.graph:
+ graphdata(runs, options, 'bpt', 'bps / Hz', bpt)
else:
printdata(runs, bpt, command == 'tpb')
return
if command == 'bptb' or command == 'tpbb':
- bytes = system.tsunami.nsgige.rxBytes + system.tsunami.nsgige.txBytes
+ bytes = system.tsunami.etherdev.rxBytes + system.tsunami.etherdev.txBytes
print 'kernel stats'
bytes.bins = 'kernel'
@@ -297,9 +374,9 @@ def commands(options, command, args):
return
if command == 'bytes':
- stat = system.tsunami.nsgige.rxBytes + system.tsunami.nsgige.txBytes
+ stat = system.tsunami.etherdev.rxBytes + system.tsunami.etherdev.txBytes
- if binned:
+ if options.binned:
print '%s kernel stats' % stat.name
stat.bins = 'kernel'
printdata(runs, stat)
@@ -319,34 +396,34 @@ def commands(options, command, args):
return
if command == 'rxbps':
- gbps = system.tsunami.nsgige.rxBandwidth / 1e9
- if graph:
- graphdata(runs, 'rxbps', 'Bandwidth (Gbps)', gbps)
+ gbps = system.tsunami.etherdev.rxBandwidth / 1e9
+ if options.graph:
+ graphdata(runs, options, 'rxbps', 'Bandwidth (Gbps)', gbps)
else:
printdata(runs, gbps)
return
if command == 'txbps':
- gbps = system.tsunami.nsgige.txBandwidth / 1e9
- if graph:
- graphdata(runs, 'txbps', 'Bandwidth (Gbps)', gbps)
+ gbps = system.tsunami.etherdev.txBandwidth / 1e9
+ if options.graph:
+ graphdata(runs, options, 'txbps', 'Bandwidth (Gbps)', gbps)
else:
printdata(runs, gbps)
return
if command == 'bps':
- rxbps = system.tsunami.nsgige.rxBandwidth
- txbps = system.tsunami.nsgige.txBandwidth
+ rxbps = system.tsunami.etherdev.rxBandwidth
+ txbps = system.tsunami.etherdev.txBandwidth
gbps = (rxbps + txbps) / 1e9
- if graph:
- graphdata(runs, 'bps', 'Bandwidth (Gbps)', gbps)
+ if options.graph:
+ graphdata(runs, options, 'bps', 'Bandwidth (Gbps)', gbps)
else:
printdata(runs, gbps)
return
if command == 'misses':
- stat = system.L3.overall_mshr_misses
- if binned:
+ stat = system.L2.overall_mshr_misses
+ if options.binned:
print '%s kernel stats' % stat.name
stat.bins = 'kernel'
printdata(runs, stat)
@@ -362,18 +439,18 @@ def commands(options, command, args):
print '%s total stats' % stat.name
stat.bins = None
- if graph:
- graphdata(runs, 'misses', 'Overall MSHR Misses', stat)
+ if options.graph:
+ graphdata(runs, options, 'misses', 'Overall MSHR Misses', stat)
else:
printdata(runs, stat)
return
if command == 'mpkb':
- misses = system.L3.overall_mshr_misses
- rxbytes = system.tsunami.nsgige.rxBytes
- txbytes = system.tsunami.nsgige.txBytes
+ misses = system.L2.overall_mshr_misses
+ rxbytes = system.tsunami.etherdev.rxBytes
+ txbytes = system.tsunami.etherdev.txBytes
- if binned:
+ if options.binned:
print 'mpkb kernel stats'
misses.bins = 'kernel'
mpkb = misses / ((rxbytes + txbytes) / 1024)
@@ -393,12 +470,43 @@ def commands(options, command, args):
mpkb = misses / ((rxbytes + txbytes) / 1024)
misses.bins = None
- if graph:
- graphdata(runs, 'mpkb', 'Misses / KB', mpkb)
+ if options.graph:
+ graphdata(runs, options, 'mpkb', 'Misses / KB', mpkb)
else:
printdata(runs, mpkb)
return
+ if command == 'ipkb':
+ interrupts = system.full_cpu.kern.faults[4]
+ rxbytes = system.tsunami.etherdev.rxBytes
+ txbytes = system.tsunami.etherdev.txBytes
+
+ if options.binned:
+ print 'ipkb kernel stats'
+ interrupts.bins = 'kernel'
+ ipkb = interrupts / ((rxbytes + txbytes) / 1024)
+ printdata(runs, ipkb)
+
+ print 'ipkb idle stats'
+ interrupts.bins = 'idle'
+ ipkb = interrupts / ((rxbytes + txbytes) / 1024)
+ printdata(runs, ipkb)
+
+ print 'ipkb user stats'
+ interrupts.bins = 'user'
+ ipkb = interrupts / ((rxbytes + txbytes) / 1024)
+ printdata(runs, ipkb)
+
+ print 'ipkb total stats'
+
+ ipkb = interrupts / ((rxbytes + txbytes) / 1024)
+ interrupts.bins = None
+ if options.graph:
+ graphdata(runs, options, 'ipkb', 'Interrupts / KB', ipkb)
+ else:
+ printdata(runs, ipkb)
+ return
+
if command == 'execute':
printdata(runs, system.full_cpu.ISSUE__count)
return
@@ -411,21 +519,49 @@ def commands(options, command, args):
printdata(runs, system.full_cpu.FETCH__count)
return
+ if command == 'bpp':
+ ed = system.tsunami.etherdev
+ bpp = (ed.rxBytes + ed.txBytes) / (ed.rxPackets + ed.txPackets)
+ if options.graph:
+ graphdata(runs, options, 'bpp', 'Bytes / Packet', bpp)
+ else:
+ printdata(runs, bpp)
+ return
+
if command == 'rxbpp':
- bpp = system.tsunami.nsgige.rxBytes / system.tsunami.nsgige.rxPackets
- printdata(run, 8 * bpp)
+ bpp = system.tsunami.etherdev.rxBytes / system.tsunami.etherdev.rxPackets
+ if options.graph:
+ graphdata(runs, options, 'rxbpp', 'Receive Bytes / Packet', bpp)
+ else:
+ printdata(runs, bpp)
return
if command == 'txbpp':
- bpp = system.tsunami.nsgige.txBytes / system.tsunami.nsgige.txPackets
- printdata(run, 8 * bpp)
+ bpp = system.tsunami.etherdev.txBytes / system.tsunami.etherdev.txPackets
+ if options.graph:
+ graphdata(runs, options, 'txbpp', 'Transmit Bytes / Packet', bpp)
+ else:
+ printdata(runs, bpp)
return
- raise CommandException
+ if command == 'rtp':
+ rtp = system.tsunami.etherdev.rxPackets / system.tsunami.etherdev.txPackets
+ if options.graph:
+ graphdata(runs, options, 'rtp', 'rxPackets / txPackets', rtp)
+ else:
+ printdata(runs, rtp)
+ return
+ if command == 'rtb':
+ rtb = system.tsunami.etherdev.rxBytes / system.tsunami.etherdev.txBytes
+ if options.graph:
+ graphdata(runs, options, 'rtb', 'rxBytes / txBytes', rtb)
+ else:
+ printdata(runs, rtb)
+ return
+
+ raise CommandException
-graph = False
-binned = False
class Options: pass
@@ -440,6 +576,8 @@ if __name__ == '__main__':
options.runs = None
options.system = 'client'
options.get = None
+ options.binned = False
+ options.graph = False
opts, args = getopts(sys.argv[1:], '-BEFGd:g:h:pr:s:u:')
for o,a in opts:
diff --git a/util/tracediff b/util/tracediff
index ed35d5dd7..a95ce8b82 100755
--- a/util/tracediff
+++ b/util/tracediff
@@ -27,10 +27,20 @@
#
# Authors: Steve Reinhardt
-# Script to simplify using rundiff on trace outputs from two invocations of m5.
+# Script to simplify using rundiff on trace outputs from two
+# invocations of m5.
+#
+# Note that you need to enable some trace flags in the args in order
+# to do anything useful!
+#
+# If you want to pass different arguments to the two instances of m5,
+# you can embed them in the simulator arguments like this:
+#
+# % tracediff "m5.opt --foo:bar=1" "m5.opt --foo:bar=2" [common args]
+#
if (@ARGV < 2) {
- die "Usage: tracediff sim1 sim2 [args...]\n";
+ die "Usage: tracediff sim1 sim2 [--trace:flags=X args...]\n";
}
# First two args are the two simulator binaries to compare
@@ -41,6 +51,10 @@ $sim2 = shift;
# be given to both invocations
$simargs = '"' . join('" "', @ARGV) . '"';
+# Redirect config output to cout so that gets diffed too (in case
+# that's the source of the problem).
+$simargs += " --Universe:config_output_file=cout";
+
$cmd1 = "$sim1 $simargs --stats:text_file=tracediff-$$-1.stats 2>&1 |";
$cmd2 = "$sim2 $simargs --stats:text_file=tracediff-$$-2.stats 2>&1 |";