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 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/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__ 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 c650c7943..208d87234 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 90711d63f..8d6016126 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 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 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 15a4a7d73..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] = {} diff --git a/util/stats/stats.py b/util/stats/stats.py index 8ec889f09..68ba2b8ea 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 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 1e2be41fe..d637e152a 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 03f2724b1..1603a9bd3 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 c650c7943..c5489d5ee 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 00c12ce68..ae82123cf 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 4dff59a5a..56782b589 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 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 d5302d9ad..609763e92 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 d6b37b9b1..9cf2cf972 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 73d2e3c44..4b947b560 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 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 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/dev/tsunami.hh b/dev/tsunami.hh index 05563f80b..d7c549e90 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 c389063d0..a1f900153 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 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: /** @@ -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 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