From 7bac427874d2999073074354d0b2cc6fc95487e9 Mon Sep 17 00:00:00 2001 From: Steve Reinhardt Date: Thu, 18 Nov 2004 10:52:56 -0500 Subject: [PATCH 01/21] Minor fixes. base/loader/ecoff_object.cc: Only warn (not die) if we can't load symbols from an ecoff object. sim/debug.cc: Compile in functioning debug_break unless NDEBUG, not only if DEBUG. Print warning if we hit breakpoint when compiled with NDEBUG. sim/debug.hh: Compile in functioning debug_break unless NDEBUG, not only if DEBUG. --HG-- extra : convert_revision : baef2caac4a9c88e1389660823eaa7c42b1d19c8 --- base/loader/ecoff_object.cc | 12 ++++++------ sim/debug.cc | 6 ++++-- sim/debug.hh | 4 ---- 3 files changed, 10 insertions(+), 12 deletions(-) diff --git a/base/loader/ecoff_object.cc b/base/loader/ecoff_object.cc index bab75944da..714f1d7b8d 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/sim/debug.cc b/sim/debug.cc index 293edcbe27..3467d16695 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 3ccf1dbd4d..5ee77cf280 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__ From e78b455cf646cdfa55cb746290b28dda0a73d6e3 Mon Sep 17 00:00:00 2001 From: Steve Reinhardt Date: Thu, 18 Nov 2004 10:53:25 -0500 Subject: [PATCH 02/21] Add PC to MemReq for tracing/debugging. --HG-- extra : convert_revision : c3fe4872698f6d46d6fe1db10fdde92c2b8d772c From a8a7eb1c2feaf09a10ff9447c5fa4b272cdee2c7 Mon Sep 17 00:00:00 2001 From: Lisa Hsu Date: Thu, 18 Nov 2004 15:46:01 -0500 Subject: [PATCH 03/21] add a bunch of stats for interrupt classification, coalescing characterization, and dropped packets. --HG-- extra : convert_revision : 421af424ec104afc352c073408a166fce6a31c70 --- dev/ns_gige.cc | 236 +++++++++++++++++++++++++++++++++++++++++++++++++ dev/ns_gige.hh | 27 ++++++ 2 files changed, 263 insertions(+) diff --git a/dev/ns_gige.cc b/dev/ns_gige.cc index c650c79439..208d87234c 100644 --- a/dev/ns_gige.cc +++ b/dev/ns_gige.cc @@ -274,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; @@ -931,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); @@ -943,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; @@ -2034,6 +2269,7 @@ NSGigE::recvPacket(PacketPtr packet) if (rxFifo.avail() < packet->length) { DPRINTF(Ethernet, "packet will not fit in receive buffer...packet dropped\n"); + droppedPackets++; devIntrPost(ISR_RXORN); return false; } diff --git a/dev/ns_gige.hh b/dev/ns_gige.hh index 90711d63fc..8d60161265 100644 --- a/dev/ns_gige.hh +++ b/dev/ns_gige.hh @@ -385,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); From ceec8419807fe05a0b298e6af64d4dc4cf3df229 Mon Sep 17 00:00:00 2001 From: Nathan Binkert Date: Thu, 18 Nov 2004 16:23:28 -0500 Subject: [PATCH 04/21] add a no touch stream benchmark clean up a little --HG-- extra : convert_revision : 41ff3dc85492e1d57fc30389f923d564156b4237 --- configs/boot/netperf-stream-nt-client.rcS | 45 +++++++++++++++++++++++ 1 file changed, 45 insertions(+) create mode 100644 configs/boot/netperf-stream-nt-client.rcS diff --git a/configs/boot/netperf-stream-nt-client.rcS b/configs/boot/netperf-stream-nt-client.rcS new file mode 100644 index 0000000000..96b6b38c3f --- /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 From ab10712341f610cb528d23fa7208203da5f7d294 Mon Sep 17 00:00:00 2001 From: Nathan Binkert Date: Thu, 18 Nov 2004 16:23:29 -0500 Subject: [PATCH 05/21] stats python fixes for dealing with vectors better. graph tweaking ipkb stat and formulas from the command line. util/stats/info.py: no need to raise an attribute error if two values aren't found in the exact same set of runs. Would be good to check that each run is the same though. util/stats/stats.py: more graph tweaking command to execute a formula from the command line. add interrupts per kilobyte of data --HG-- extra : convert_revision : 78d6b14d340d08edcbc69e4c1c5a4c1dd9bb10dd --- util/stats/info.py | 44 +++++++------- util/stats/stats.py | 142 ++++++++++++++++++++++++++++++++++++-------- 2 files changed, 137 insertions(+), 49 deletions(-) diff --git a/util/stats/info.py b/util/stats/info.py index 15a4a7d737..fa318a6506 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] = {} diff --git a/util/stats/stats.py b/util/stats/stats.py index 8ec889f09b..68ba2b8ea9 100755 --- a/util/stats/stats.py +++ b/util/stats/stats.py @@ -39,23 +39,50 @@ 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 = ['stx', 'ste', 'hte', 'htd', 'ocm', 'occ', 'ocp' ] - benchmarks = [ 'm', 's' ] - dmas = [ 'x', 'd', 'b' ] + 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' ] - checkpoints = [ '1' ] 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 cpt in checkpoints: - names.append([bench, dma, cache, cpt]) + names.append([bench, dma, cache]) - for bench,dma,cache,cpt in names: - base = '%s.%s.%s.%s' % (bench, dma, cache, cpt) + 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 @@ -66,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' % (conf, bench, dma, speed, cache, - 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) @@ -174,7 +200,7 @@ def commands(options, command, args): stats = info.source.getStat(args[0]) for stat in stats: if options.graph: - graphdata(runs, stat.name, stat.name, stat) + graphdata(runs, options, stat.name, stat.name, stat) else: if options.binned: print 'kernel ticks' @@ -200,6 +226,39 @@ def commands(options, command, args): 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() @@ -241,7 +300,7 @@ def commands(options, command, args): user.bins = 'user' if options.graph: - graphdata(runs, 'usertime', 'User Fraction', + graphdata(runs, options, 'usertime', 'User Fraction', user / system.full_cpu.numCycles) else: printdata(runs, user / system.full_cpu.numCycles) @@ -270,7 +329,7 @@ def commands(options, command, args): if command == 'packets': packets = system.tsunami.etherdev.rxPackets if options.graph: - graphdata(runs, 'packets', 'Packets', packets) + graphdata(runs, options, 'packets', 'Packets', packets) else: printdata(runs, packets) return @@ -283,7 +342,7 @@ def commands(options, command, args): if command == 'pps': pps = system.tsunami.etherdev.rxPackets / sim_seconds if options.graph: - graphdata(runs, 'pps', 'Packets/s', pps) + graphdata(runs, options, 'pps', 'Packets/s', pps) else: printdata(runs, pps) return @@ -292,7 +351,7 @@ def commands(options, command, args): bytes = system.tsunami.etherdev.rxBytes + system.tsunami.etherdev.txBytes bpt = bytes / sim_ticks * 8 if options.graph: - graphdata(runs, 'bpt', 'bps / Hz', bpt) + graphdata(runs, options, 'bpt', 'bps / Hz', bpt) else: printdata(runs, bpt, command == 'tpb') return @@ -339,7 +398,7 @@ def commands(options, command, args): if command == 'rxbps': gbps = system.tsunami.etherdev.rxBandwidth / 1e9 if options.graph: - graphdata(runs, 'rxbps', 'Bandwidth (Gbps)', gbps) + graphdata(runs, options, 'rxbps', 'Bandwidth (Gbps)', gbps) else: printdata(runs, gbps) return @@ -347,7 +406,7 @@ def commands(options, command, args): if command == 'txbps': gbps = system.tsunami.etherdev.txBandwidth / 1e9 if options.graph: - graphdata(runs, 'txbps', 'Bandwidth (Gbps)', gbps) + graphdata(runs, options, 'txbps', 'Bandwidth (Gbps)', gbps) else: printdata(runs, gbps) return @@ -357,7 +416,7 @@ def commands(options, command, args): txbps = system.tsunami.etherdev.txBandwidth gbps = (rxbps + txbps) / 1e9 if options.graph: - graphdata(runs, 'bps', 'Bandwidth (Gbps)', gbps) + graphdata(runs, options, 'bps', 'Bandwidth (Gbps)', gbps) else: printdata(runs, gbps) return @@ -381,7 +440,7 @@ def commands(options, command, args): stat.bins = None if options.graph: - graphdata(runs, 'misses', 'Overall MSHR Misses', stat) + graphdata(runs, options, 'misses', 'Overall MSHR Misses', stat) else: printdata(runs, stat) return @@ -412,11 +471,42 @@ def commands(options, command, args): mpkb = misses / ((rxbytes + txbytes) / 1024) misses.bins = None if options.graph: - graphdata(runs, 'mpkb', 'Misses / KB', mpkb) + 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 @@ -433,7 +523,7 @@ def commands(options, command, args): ed = system.tsunami.etherdev bpp = (ed.rxBytes + ed.txBytes) / (ed.rxPackets + ed.txPackets) if options.graph: - graphdata(runs, 'bpp', 'Bytes / Packet', bpp) + graphdata(runs, options, 'bpp', 'Bytes / Packet', bpp) else: printdata(runs, bpp) return @@ -441,7 +531,7 @@ def commands(options, command, args): if command == 'rxbpp': bpp = system.tsunami.etherdev.rxBytes / system.tsunami.etherdev.rxPackets if options.graph: - graphdata(runs, 'rxbpp', 'Receive Bytes / Packet', bpp) + graphdata(runs, options, 'rxbpp', 'Receive Bytes / Packet', bpp) else: printdata(runs, bpp) return @@ -449,7 +539,7 @@ def commands(options, command, args): if command == 'txbpp': bpp = system.tsunami.etherdev.txBytes / system.tsunami.etherdev.txPackets if options.graph: - graphdata(runs, 'txbpp', 'Transmit Bytes / Packet', bpp) + graphdata(runs, options, 'txbpp', 'Transmit Bytes / Packet', bpp) else: printdata(runs, bpp) return @@ -457,7 +547,7 @@ def commands(options, command, args): if command == 'rtp': rtp = system.tsunami.etherdev.rxPackets / system.tsunami.etherdev.txPackets if options.graph: - graphdata(runs, 'rtp', 'rxPackets / txPackets', rtp) + graphdata(runs, options, 'rtp', 'rxPackets / txPackets', rtp) else: printdata(runs, rtp) return @@ -465,7 +555,7 @@ def commands(options, command, args): if command == 'rtb': rtb = system.tsunami.etherdev.rxBytes / system.tsunami.etherdev.txBytes if options.graph: - graphdata(runs, 'rtb', 'rxBytes / txBytes', rtb) + graphdata(runs, options, 'rtb', 'rxBytes / txBytes', rtb) else: printdata(runs, rtb) return From e3c3e44ac15f030ca5b76dbdb85584e20932ee94 Mon Sep 17 00:00:00 2001 From: Nathan Binkert Date: Thu, 18 Nov 2004 16:23:30 -0500 Subject: [PATCH 06/21] fixup natbox configuration --HG-- extra : convert_revision : 9744ff67691f6a8fd7c20f1b84d899acdfcd1cf8 From 86836124ed272945e9d360c068728cd03917398d Mon Sep 17 00:00:00 2001 From: Nathan Binkert Date: Thu, 18 Nov 2004 16:23:31 -0500 Subject: [PATCH 07/21] always initalize the size of a packet (forgotten on checkpoints in some places). use the constructor for setting the size. --HG-- extra : convert_revision : fad322c1d45b1952804cf35942b5685d70128e59 --- dev/etherlink.cc | 4 ++-- dev/ethertap.cc | 3 +-- dev/ns_gige.cc | 7 +++---- dev/pktfifo.cc | 2 +- dev/sinic.cc | 4 ++-- 5 files changed, 9 insertions(+), 11 deletions(-) diff --git a/dev/etherlink.cc b/dev/etherlink.cc index 1e2be41fe4..d637e152ad 100644 --- a/dev/etherlink.cc +++ b/dev/etherlink.cc @@ -195,7 +195,7 @@ EtherLink::Link::unserialize(Checkpoint *cp, const string §ion) bool packet_exists; UNSERIALIZE_SCALAR(packet_exists); if (packet_exists) { - packet = new PacketData; + packet = new PacketData(16384); packet->unserialize("packet", cp, section); } @@ -244,7 +244,7 @@ void LinkDelayEvent::unserialize(Checkpoint *cp, const string §ion) { Event::unserialize(cp, section); - packet = new PacketData; + packet = new PacketData(16384); packet->unserialize("packet", cp, section); } diff --git a/dev/ethertap.cc b/dev/ethertap.cc index 03f2724b1d..1603a9bd3a 100644 --- a/dev/ethertap.cc +++ b/dev/ethertap.cc @@ -219,8 +219,7 @@ EtherTap::process(int revent) while (data_len != 0 && buffer_offset >= data_len + sizeof(u_int32_t)) { PacketPtr packet; - packet = new PacketData; - 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/ns_gige.cc b/dev/ns_gige.cc index c650c79439..c5489d5ee2 100644 --- a/dev/ns_gige.cc +++ b/dev/ns_gige.cc @@ -1767,8 +1767,7 @@ NSGigE::txKick() case txFifoBlock: if (!txPacket) { DPRINTF(EthernetSM, "****starting the tx of a new packet****\n"); - txPacket = new PacketData; - txPacket->data = new uint8_t[16384]; + txPacket = new PacketData(16384); txPacketBufPtr = txPacket->data; } @@ -2257,7 +2256,7 @@ NSGigE::unserialize(Checkpoint *cp, const std::string §ion) bool txPacketExists; UNSERIALIZE_SCALAR(txPacketExists); if (txPacketExists) { - txPacket = new PacketData; + txPacket = new PacketData(16384); txPacket->unserialize("txPacket", cp, section); uint32_t txPktBufPtr; UNSERIALIZE_SCALAR(txPktBufPtr); @@ -2269,7 +2268,7 @@ NSGigE::unserialize(Checkpoint *cp, const std::string §ion) UNSERIALIZE_SCALAR(rxPacketExists); rxPacket = 0; if (rxPacketExists) { - rxPacket = new PacketData; + rxPacket = new PacketData(16384); rxPacket->unserialize("rxPacket", cp, section); uint32_t rxPktBufPtr; UNSERIALIZE_SCALAR(rxPktBufPtr); diff --git a/dev/pktfifo.cc b/dev/pktfifo.cc index 00c12ce681..ae82123cf6 100644 --- a/dev/pktfifo.cc +++ b/dev/pktfifo.cc @@ -63,7 +63,7 @@ PacketFifo::unserialize(const string &base, Checkpoint *cp, fifo.resize(fifosize); for (int i = 0; i < fifosize; ++i) { - PacketPtr p = new PacketData; + PacketPtr p = new PacketData(16384); p->unserialize(csprintf("%s.packet%d", base, i), cp, section); fifo.push_back(p); } diff --git a/dev/sinic.cc b/dev/sinic.cc index 4dff59a5a8..56782b589d 100644 --- a/dev/sinic.cc +++ b/dev/sinic.cc @@ -1225,7 +1225,7 @@ Device::unserialize(Checkpoint *cp, const std::string §ion) UNSERIALIZE_SCALAR(rxPacketExists); rxPacket = 0; if (rxPacketExists) { - rxPacket = new PacketData; + rxPacket = new PacketData(16384); rxPacket->unserialize("rxPacket", cp, section); uint32_t rxPktBufPtr; UNSERIALIZE_SCALAR(rxPktBufPtr); @@ -1245,7 +1245,7 @@ Device::unserialize(Checkpoint *cp, const std::string §ion) UNSERIALIZE_SCALAR(txPacketExists); txPacket = 0; if (txPacketExists) { - txPacket = new PacketData; + txPacket = new PacketData(16384); txPacket->unserialize("txPacket", cp, section); uint32_t txPktBufPtr; UNSERIALIZE_SCALAR(txPktBufPtr); From 50490ee449e41f77865b41bcdecc3ce5b7b05628 Mon Sep 17 00:00:00 2001 From: Nathan Binkert Date: Thu, 18 Nov 2004 16:23:33 -0500 Subject: [PATCH 08/21] don't share the PCI Header data among all devices. Make them independent. --HG-- extra : convert_revision : 2aeb7db098f4fcdaea2a37d0a55ee2dbc08c853c From 9291ec40adfa6407c6e0062a955020082e82cc7d Mon Sep 17 00:00:00 2001 From: Ali Saidi Date: Thu, 18 Nov 2004 18:29:58 -0500 Subject: [PATCH 09/21] graphing updates --HG-- extra : convert_revision : 8264cdb40f3679189e9c343b3a376e5938c3e13c From 574caca0588fdd226b57eeb04893eaf897700129 Mon Sep 17 00:00:00 2001 From: Ali Saidi Date: Thu, 18 Nov 2004 19:44:54 -0500 Subject: [PATCH 10/21] small tweaks to label positions --HG-- extra : convert_revision : 6bfbb6500fa3f2e46be06cfdb32bf7f7713d5999 From 9590ca68442afdb1f4d8f1414bc6a9da18a76484 Mon Sep 17 00:00:00 2001 From: Ali Saidi Date: Thu, 18 Nov 2004 19:57:24 -0500 Subject: [PATCH 11/21] move y axis label closer --HG-- extra : convert_revision : 329c2f4553febf70f346debcd8f71f275576dc17 From eefd60f17534c1adfc598d7fd91afd95c0b4400f Mon Sep 17 00:00:00 2001 From: Nathan Binkert Date: Mon, 22 Nov 2004 19:10:36 -0500 Subject: [PATCH 12/21] Make it so we can easily disable compiling of some of the caches. All that needs to be done is comment out the stuff you don't care about in the header files in the mem/config. For now, the default is to leave everything on. --HG-- extra : convert_revision : a3638ab3927339d92803479bc0c30728f0b977ad From 244ce7fb29cbd7107a5dc0fb640a6154a091ec6e Mon Sep 17 00:00:00 2001 From: Ali Saidi Date: Mon, 22 Nov 2004 22:32:37 -0500 Subject: [PATCH 13/21] Print a warning if two devices are sharing the same interrupt Update profile-top to print 2 or 4 graphs depending on a command line option dev/pciconfigall.cc: dev/pciconfigall.hh: dev/pcidev.hh: Print a warning if two devices are sharing the same interrupt --HG-- extra : convert_revision : 0ef99cac92fbf2916ab8e5b1125d520eb4b5ac7d --- dev/pciconfigall.cc | 29 +++++++++++++++++++++++++++++ dev/pciconfigall.hh | 7 +++++++ dev/pcidev.hh | 4 ++++ 3 files changed, 40 insertions(+) diff --git a/dev/pciconfigall.cc b/dev/pciconfigall.cc index d5302d9ad7..609763e928 100644 --- a/dev/pciconfigall.cc +++ b/dev/pciconfigall.cc @@ -33,10 +33,12 @@ #include #include #include +#include #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" @@ -65,6 +67,33 @@ 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) { diff --git a/dev/pciconfigall.hh b/dev/pciconfigall.hh index d6b37b9b15..9cf2cf9722 100644 --- a/dev/pciconfigall.hh +++ b/dev/pciconfigall.hh @@ -115,6 +115,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.hh b/dev/pcidev.hh index 73d2e3c449..4b947b5605 100644 --- a/dev/pcidev.hh +++ b/dev/pcidev.hh @@ -141,6 +141,10 @@ class PciDev : public DmaDevice 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 From d1d1cbdd0e230ea05b06248ac85f34b301416407 Mon Sep 17 00:00:00 2001 From: Steve Reinhardt Date: Tue, 23 Nov 2004 00:13:11 -0500 Subject: [PATCH 14/21] Fix typo (from Nate's commit, I believe) --HG-- extra : convert_revision : 87e1a3ac1b5fcd53a6ed7fa63d5323ae33423f56 From 433d0a12de25a80376c3e333a58ecfd5cc36220e Mon Sep 17 00:00:00 2001 From: Ron Dreslinski Date: Wed, 24 Nov 2004 13:34:47 -0500 Subject: [PATCH 15/21] Fix duplicate statistic name and description Uncacheables don't change the request cmd, so use req->cmd instead of mshr->originalCmd] --HG-- extra : convert_revision : 2f31df4911e29cb941138ed493f01f11b1109722 From 7017707a6832b6142c7350437e6cb8d350255c49 Mon Sep 17 00:00:00 2001 From: Nathan Binkert Date: Wed, 24 Nov 2004 13:34:48 -0500 Subject: [PATCH 16/21] Add a #define option for setting the sampling periods --HG-- extra : convert_revision : 29163dc72e7e677b4cfafa76cb33a755ee2c50b2 From 41411ff8d9a5be611027b9aff37559e29dc8d0a0 Mon Sep 17 00:00:00 2001 From: Ali Saidi Date: Wed, 1 Dec 2004 17:00:39 -0500 Subject: [PATCH 17/21] updated colors, and font adjustments --HG-- extra : convert_revision : a4ce055c73ec12a26c70d03bd833ee9d429adc23 From 0d31aacde0125919a471703f0495f216ac307c03 Mon Sep 17 00:00:00 2001 From: Lisa Hsu Date: Fri, 3 Dec 2004 15:29:33 -0500 Subject: [PATCH 18/21] system.ini: Fix the Boot Detailed case so that IntrControl and AlphaConsole's cpu's are defined. --HG-- extra : convert_revision : d6e5073af27d5554b2bea719a0790ef891bf57be From e6d7d9de05392bf6f3ab7d6fe850a3ef55a72505 Mon Sep 17 00:00:00 2001 From: Lisa Hsu Date: Fri, 3 Dec 2004 15:42:26 -0500 Subject: [PATCH 19/21] boot_detail.ini: now that we've changed the memory system defined names, fix this file --HG-- extra : convert_revision : 1ce3881c9d21ba0b37f17f802641b5029a042d17 From 45eb722566670aa9a1c282859310c5969f9d500e Mon Sep 17 00:00:00 2001 From: Lisa Hsu Date: Fri, 3 Dec 2004 15:49:37 -0500 Subject: [PATCH 20/21] system.ini: the SYSTEM_DETAIL configuration assumes that it's a TWO_SYSTEM. make it not do that --HG-- extra : convert_revision : 4f630a06b333acd727c57a82bc7a9595b231c037 From 34260bbf0da0aa735ddcc701441cac71fee1e5b0 Mon Sep 17 00:00:00 2001 From: Ali Saidi Date: Mon, 6 Dec 2004 12:06:16 -0500 Subject: [PATCH 21/21] Add support for Tsunami with 64 processors base/socket.cc: Make panic print a more worthwhile message dev/tsunami.hh: Change max number of tsunami cpus to be 64 dev/tsunamireg.h: Add new registers and register blocks for 64 cpu tsunami --HG-- extra : convert_revision : 3ceaaa998518ded8613bc64edc04cb9120fd3d15 --- base/socket.cc | 2 +- dev/tsunami.hh | 2 +- dev/tsunami_cchip.cc | 265 ++++++++++++++++++++++++++++++------------- dev/tsunami_cchip.hh | 36 ++++-- dev/tsunamireg.h | 7 ++ 5 files changed, 222 insertions(+), 90 deletions(-) diff --git a/base/socket.cc b/base/socket.cc index aa6a183a9c..ee87dc057f 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/dev/tsunami.hh b/dev/tsunami.hh index 05563f80b1..d7c549e902 100644 --- a/dev/tsunami.hh +++ b/dev/tsunami.hh @@ -58,7 +58,7 @@ 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; diff --git a/dev/tsunami_cchip.cc b/dev/tsunami_cchip.cc index c389063d01..a1f9001537 100644 --- a/dev/tsunami_cchip.cc +++ b/dev/tsunami_cchip.cc @@ -55,14 +55,6 @@ TsunamiCChip::TsunamiCChip(const string &name, Tsunami *t, Addr a, { mmu->add_child(this, RangeSize(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; - } - if (bus) { pioInterface = newPioInterface(name, hier, bus, this, &TsunamiCChip::cacheAccess); @@ -71,7 +63,14 @@ TsunamiCChip::TsunamiCChip(const string &name, Tsunami *t, Addr a, } 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 & EV5::PAddrImplMask)) >> 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,16 +189,58 @@ 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 & EV5::PAddrImplMask)) >> 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: @@ -189,19 +251,7 @@ TsunamiCChip::write(MemReqPtr &req, const uint8_t *data) ipreq = (*(uint64_t*)data >> 12) & 0xF; //If it is bit 12-15, this is an IPI post if (ipreq) { - for (int cpunum=0; cpunum < Tsunami::Max_CPUs; cpunum++) { - // Check each cpu bit - if (ipreq & (1 << cpunum)) { - // Check if there is already an ipi (bits 8:11) - if (!(misc & (0x100 << cpunum))) { - misc |= (0x100 << cpunum); - tsunami->intrctrl->post(cpunum, - TheISA::INTLEVEL_IRQ3, 0); - DPRINTF(IPI, "send IPI cpu=%d from=%d\n", - cpunum, req->cpu_num); - } - } - } + reqIPI(ipreq); supportedWrite = true; } @@ -209,36 +259,15 @@ TsunamiCChip::write(MemReqPtr &req, const uint8_t *data) uint64_t ipintr; ipintr = (*(uint64_t*)data >> 8) & 0xF; if (ipintr) { - for (int cpunum=0; cpunum < Tsunami::Max_CPUs; cpunum++) { - // Check each cpu bit - if (ipintr & (1 << cpunum)) { - // Check if there is a pending ipi (bits 8:11) - if (misc & (0x100 << cpunum)) { - misc &= ~(0x100 << cpunum); - tsunami->intrctrl->clear(cpunum, - TheISA::INTLEVEL_IRQ3, 0); - DPRINTF(IPI, "clear IPI IPI cpu=%d from=%d\n", - cpunum, req->cpu_num); - } - } - } + clearIPI(ipintr); supportedWrite = true; } - - //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); - } - } + itintr = (*(uint64_t*)data >> 4) & 0xF; + if (itintr) { + clearITI(itintr); supportedWrite = true; } @@ -261,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; @@ -280,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)) { @@ -297,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); } @@ -324,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"); } @@ -341,15 +380,89 @@ TsunamiCChip::write(MemReqPtr &req, const uint8_t *data) return No_Fault; } +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); } @@ -360,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) { @@ -376,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; @@ -407,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 @@ -419,11 +534,9 @@ TsunamiCChip::unserialize(Checkpoint *cp, const std::string §ion) { 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 3269cf53a1..05fafa7825 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: /** @@ -137,6 +130,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/tsunamireg.h b/dev/tsunamireg.h index 876c6bf18f..3304082a57 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