diff options
34 files changed, 620 insertions, 102 deletions
diff --git a/SConscript b/SConscript index b159d3e36..3c6bbf83e 100644 --- a/SConscript +++ b/SConscript @@ -162,6 +162,9 @@ base_sources = Split(''' mem/cache/tags/fa_lru.cc mem/cache/tags/iic.cc mem/cache/tags/lru.cc + mem/cache/tags/split.cc + mem/cache/tags/split_lifo.cc + mem/cache/tags/split_lru.cc mem/cache/tags/repl/gen.cc mem/cache/tags/repl/repl.cc mem/functional_mem/functional_memory.cc @@ -216,6 +219,7 @@ full_system_sources = Split(''' dev/simconsole.cc dev/disk_image.cc dev/dma.cc + dev/etherbus.cc dev/etherdump.cc dev/etherint.cc dev/etherlink.cc diff --git a/arch/alpha/vtophys.cc b/arch/alpha/vtophys.cc index f4b2c7ed3..464ed41e6 100644 --- a/arch/alpha/vtophys.cc +++ b/arch/alpha/vtophys.cc @@ -100,11 +100,11 @@ vtophys(ExecContext *xc, Addr vaddr) //so I put it back in. Perhaps something to do with gdb debugging? if (PC_PAL(vaddr)) { paddr = vaddr & ~ULL(1); - } else if (!ptbr) { - paddr = vaddr; } else { if (vaddr >= ALPHA_K0SEG_BASE && vaddr <= ALPHA_K0SEG_END) { paddr = ALPHA_K0SEG_TO_PHYS(vaddr); + } else if (!ptbr) { + paddr = vaddr; } else { Addr pte = kernel_pte_lookup(xc->physmem, ptbr, vaddr); uint64_t entry = xc->physmem->phys_read_qword(pte); diff --git a/base/statistics.hh b/base/statistics.hh index bd1698ae7..f3b8a3922 100644 --- a/base/statistics.hh +++ b/base/statistics.hh @@ -2184,7 +2184,7 @@ class SumNode : public Node * binned. If the typedef is NoBin, nothing is binned. If it is * MainBin, then all stats are binned under that Bin. */ -#if defined(FS_MEASURE) +#if defined(FS_MEASURE) || defined(STATS_BINNING) typedef MainBin DefaultBin; #else typedef NoBin DefaultBin; diff --git a/base/stats/events.cc b/base/stats/events.cc index ed25e2423..771927564 100644 --- a/base/stats/events.cc +++ b/base/stats/events.cc @@ -45,7 +45,7 @@ using namespace std; namespace Stats { -Tick EventStart = ULL(0xffffffffffffffff); +Tick EventStart = ULL(0x7fffffffffffffff); vector<string> event_ignore; vector<vector<string> > ignore_tokens; diff --git a/base/stats/mysql.cc b/base/stats/mysql.cc index 4c2a60127..a749b573a 100644 --- a/base/stats/mysql.cc +++ b/base/stats/mysql.cc @@ -67,9 +67,16 @@ MySqlRun::connect(const string &host, const string &user, const string &passwd, if (mysql.error) panic("could not connect to database server\n%s\n", mysql.error); + mysql.query("LOCK TABLES runs WRITE"); + if (mysql.error) + panic("could not lock tables\n%s\n", mysql.error); + remove(name); - cleanup(); +// cleanup(); setup(name, sample, user, project); + mysql.query("UNLOCK TABLES"); + if (mysql.error) + panic("could not unlock tables\n%s\n", mysql.error); } void @@ -100,6 +107,8 @@ MySqlRun::remove(const string &name) stringstream sql; ccprintf(sql, "DELETE FROM runs WHERE rn_name=\"%s\"", name); mysql.query(sql); + if (mysql.error) + panic("could not delete run\n%s\n", mysql.error); } void @@ -195,13 +204,13 @@ SetupStat::setup() mysql.query(select); MySQL::Result result = mysql.store_result(); if (!result) - panic("could not get a run\n%s\n", mysql.error); + panic("could not find stat\n%s\n", mysql.error); assert(result.num_fields() == 16); MySQL::Row row = result.fetch_row(); if (!row) - panic("could not get a run\n%s\n", mysql.error); + panic("could not get stat row\n%s\n", mysql.error); bool tb; int8_t ti8; @@ -274,33 +283,52 @@ SetupStat::setup() unsigned SetupBin(const string &bin) { - MySQL::Connection &mysql = MySqlDB.conn(); - assert(mysql.connected()); + static map<string, int> binmap; using namespace MySQL; + map<string,int>::const_iterator i = binmap.find(bin); + if (i != binmap.end()) + return (*i).second; + + Connection &mysql = MySqlDB.conn(); + assert(mysql.connected()); + + mysql.query("LOCK TABLES bins WRITE"); + if (mysql.error) + panic("could not lock bin table\n%s\n", mysql.error); + + uint16_t bin_id; + stringstream select; + stringstream insert; ccprintf(select, "SELECT bn_id FROM bins WHERE bn_name=\"%s\"", bin); mysql.query(select); MySQL::Result result = mysql.store_result(); if (result) { assert(result.num_fields() == 1); - Row row = result.fetch_row(); + MySQL::Row row = result.fetch_row(); if (row) { - uint16_t bin_id; to_number(row[0], bin_id); - return bin_id; + goto exit; } } - stringstream insert; ccprintf(insert, "INSERT INTO bins(bn_name) values(\"%s\")", bin); mysql.query(insert); if (mysql.error) - panic("could not get a run\n%s\n", mysql.error); + panic("could not get a bin\n%s\n", mysql.error); + + bin_id = mysql.insert_id(); + binmap.insert(make_pair(bin, bin_id)); + + exit: + mysql.query("UNLOCK TABLES"); + if (mysql.error) + panic("could not unlock tables\n%s\n", mysql.error); - return mysql.insert_id(); + return bin_id; } InsertData::InsertData() @@ -322,13 +350,15 @@ InsertData::flush() MySQL::Connection &mysql = MySqlDB.conn(); assert(mysql.connected()); mysql.query(query); + if (mysql.error) + panic("could not insert data\n%s\n", mysql.error); } query[0] = '\0'; size = 0; first = true; strcpy(query, "INSERT INTO " - "data(dt_stat,dt_x,dt_y,dt_run,dt_sample,dt_bin,dt_data) " + "data(dt_stat,dt_x,dt_y,dt_run,dt_tick,dt_bin,dt_data) " "values"); size = strlen(query); } @@ -347,7 +377,7 @@ InsertData::insert() first = false; size += sprintf(query + size, "(%u,%d,%d,%u,%llu,%u,\"%f\")", - stat, x, y, MySqlDB.run(), (unsigned long long)sample, + stat, x, y, MySqlDB.run(), (unsigned long long)tick, bin, data); } @@ -374,6 +404,8 @@ InsertSubData::setup() stat, x, y, name, descr); mysql.query(insert); +// if (mysql.error) +// panic("could not insert subdata\n%s\n", mysql.error); } void @@ -387,13 +419,17 @@ InsertFormula(uint16_t stat, const string &formula) stat, formula); mysql.query(insert_formula); +// if (mysql.error) +// panic("could not insert formula\n%s\n", mysql.error); stringstream insert_ref; ccprintf(insert_ref, "INSERT INTO formula_ref(fr_stat,fr_run) values(%d, %d)", stat, MySqlDB.run()); - mysql.query(insert_ref); + mysql.query(insert_ref); +// if (mysql.error) +// panic("could not insert formula reference\n%s\n", mysql.error); } void @@ -405,6 +441,8 @@ UpdatePrereq(uint16_t stat, uint16_t prereq) ccprintf(update, "UPDATE stats SET st_prereq=%d WHERE st_id=%d", prereq, stat); mysql.query(update); + if (mysql.error) + panic("could not update prereq\n%s\n", mysql.error); } void @@ -414,6 +452,17 @@ MySql::configure() * set up all stats! */ using namespace Database; + + MySQL::Connection &mysql = MySqlDB.conn(); + mysql.query("LOCK TABLES " + "stats WRITE, " + "bins WRITE, " + "subdata WRITE, " + "formulas WRITE, " + "formula_ref WRITE"); + if (mysql.error) + panic("could not lock tables\n%s\n", mysql.error); + stat_list_t::const_iterator i, end = stats().end(); for (i = stats().begin(); i != end; ++i) (*i)->visit(*this); @@ -429,6 +478,10 @@ MySql::configure() } } + mysql.query("UNLOCK TABLES"); + if (mysql.error) + panic("could not unlock tables\n%s\n", mysql.error); + configured = true; } @@ -531,7 +584,7 @@ MySql::configure(const Vector2dData &data) if (!data.subnames.empty()) { InsertSubData subdata; subdata.stat = statid; - subdata.y = 0; + subdata.y = -1; for (int i = 0; i < data.subnames.size(); ++i) { subdata.x = i; subdata.name = data.subnames[i]; @@ -544,7 +597,7 @@ MySql::configure(const Vector2dData &data) if (!data.y_subnames.empty()) { InsertSubData subdata; subdata.stat = statid; - subdata.x = 0; + subdata.x = -1; subdata.descr = ""; for (int i = 0; i < data.y_subnames.size(); ++i) { subdata.y = i; @@ -562,6 +615,7 @@ MySql::configure(const FormulaData &data) { configure(data, "FORMULA"); insert(data.id, stat.setup()); + InsertFormula(find(data.id), data.str()); } void @@ -591,7 +645,7 @@ MySql::output() configure(); // store sample # - newdata.sample = curTick; + newdata.tick = curTick; if (bins().empty()) { output(string("")); @@ -722,7 +776,6 @@ MySql::output(const Vector2dData &data) void MySql::output(const FormulaData &data) { - InsertFormula(find(data.id), data.str()); } /* diff --git a/base/stats/mysql.hh b/base/stats/mysql.hh index 5780009d7..fcbe8c5e0 100644 --- a/base/stats/mysql.hh +++ b/base/stats/mysql.hh @@ -76,7 +76,7 @@ class InsertData MySqlRun *run; public: - uint64_t sample; + uint64_t tick; double data; uint16_t stat; uint16_t bin; diff --git a/base/traceflags.py b/base/traceflags.py index 8e1594b24..e073f96c1 100644 --- a/base/traceflags.py +++ b/base/traceflags.py @@ -120,7 +120,8 @@ baseFlags = [ 'IdeCtrl', 'IdeDisk', 'Tsunami', - 'Uart' + 'Uart', + 'Split' ] # diff --git a/configs/boot/client.netperf.maerts b/configs/boot/client.netperf.maerts new file mode 100644 index 000000000..f1335c020 --- /dev/null +++ b/configs/boot/client.netperf.maerts @@ -0,0 +1,33 @@ +#!/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 + +echo -n "waiting for server..." +/usr/bin/netcat -c -l -p 8000 + +BINARY=/benchmarks/netperf/netperf +TEST="TCP_MAERTS" +SHORT_ARGS="-l -100k" +LONG_ARGS="-k16384,0 -K16384,0 -- -m 65536 -M 65536 -s 262144 -S 262144" + + +SHORT="$BINARY -H $SERVER -t $TEST $SHORT_ARGS" +LONG="$BINARY -H $SERVER -t $TEST $LONG_ARGS" + +echo "starting test..." +echo "netperf warmup" +echo $SHORT +eval $SHORT + +echo "netperf benchmark" +echo $LONG +/sbin/m5 ivlb 1 +/sbin/m5 resetstats +/sbin/m5 dumpresetstats 2000000000 2000000000 +/sbin/m5 checkpoint 2000000000 2000000000 +eval $LONG +/sbin/m5 exit diff --git a/configs/boot/client.netperf.rr b/configs/boot/client.netperf.rr new file mode 100644 index 000000000..aafc569e7 --- /dev/null +++ b/configs/boot/client.netperf.rr @@ -0,0 +1,33 @@ +#!/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 + +echo -n "waiting for server..." +/usr/bin/netcat -c -l -p 8000 + +BINARY=/benchmarks/netperf/netperf +TEST="TCP_RR" +SHORT_ARGS="-l -1k" +LONG_ARGS="-k10000,0 -K10000,0" + + +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 2000000000 2000000000 +/sbin/m5 checkpoint 2000000000 2000000000 +eval $LONG +/sbin/m5 exit diff --git a/configs/boot/client.netperf.stream b/configs/boot/client.netperf.stream new file mode 100644 index 000000000..f04228cd4 --- /dev/null +++ b/configs/boot/client.netperf.stream @@ -0,0 +1,33 @@ +#!/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 + +echo -n "waiting for server..." +/usr/bin/netcat -c -l -p 8000 + +BINARY=/benchmarks/netperf/netperf +TEST="TCP_STREAM" +SHORT_ARGS="-l -100k" +LONG_ARGS="-k16384,0 -K16384,0 -- -m 65536 -M 65536 -s 262144 -S 262144" + + +SHORT="$BINARY -H $SERVER -t $TEST $SHORT_ARGS" +LONG="$BINARY -H $SERVER -t $TEST $LONG_ARGS" + +echo "starting test..." +echo "netperf warmup" +echo $SHORT +eval $SHORT + +echo "netperf benchmark" +echo $LONG +/sbin/m5 ivlb 1 +/sbin/m5 resetstats +/sbin/m5 dumpresetstats 2000000000 2000000000 +/sbin/m5 checkpoint 2000000000 2000000000 +eval $LONG +/sbin/m5 exit diff --git a/configs/boot/server.netperf b/configs/boot/server.netperf new file mode 100644 index 000000000..a62bc171e --- /dev/null +++ b/configs/boot/server.netperf @@ -0,0 +1,17 @@ +#!/bin/sh +SERVER=10.0.0.1 +CLIENT=10.0.0.2 + +echo "setting up network..." +ifconfig lo 127.0.0.1 +ifconfig eth0 $SERVER + +echo "running netserver..." +/benchmarks/netperf/netserver + +echo -n "signal client to begin..." +echo "server ready" | /usr/bin/netcat -c $CLIENT 8000 +echo "done." + +echo "starting bash..." +exec /bin/bash diff --git a/cpu/trace/reader/m5_reader.cc b/cpu/trace/reader/m5_reader.cc index a1ada38a2..d081f0bc0 100644 --- a/cpu/trace/reader/m5_reader.cc +++ b/cpu/trace/reader/m5_reader.cc @@ -54,10 +54,12 @@ M5Reader::getNextReq(MemReqPtr &req) traceFile.read((char*) &ref, sizeof(ref)); if (!traceFile.eof()) { //traceFile.read((char*) &ref, sizeof(ref)); +#ifndef NDEBUG int gcount = traceFile.gcount(); assert(gcount != 0 || traceFile.eof()); assert(gcount == sizeof(ref)); assert(ref.cmd < 12); +#endif tmp_req = new MemReq(); tmp_req->paddr = ref.paddr; tmp_req->asid = ref.asid; diff --git a/dev/baddev.cc b/dev/baddev.cc index 8b552e989..7c563e80a 100644 --- a/dev/baddev.cc +++ b/dev/baddev.cc @@ -78,7 +78,7 @@ BadDevice::write(MemReqPtr &req, const uint8_t *data) Tick BadDevice::cacheAccess(MemReqPtr &req) { - return curTick + 1000; + return curTick; } BEGIN_DECLARE_SIM_OBJECT_PARAMS(BadDevice) @@ -103,7 +103,8 @@ END_INIT_SIM_OBJECT_PARAMS(BadDevice) CREATE_SIM_OBJECT(BadDevice) { - return new BadDevice(getInstanceName(), addr, mmu, hier, io_bus, devicename); + return new BadDevice(getInstanceName(), addr, mmu, hier, io_bus, + devicename); } REGISTER_SIM_OBJECT("BadDevice", BadDevice) diff --git a/dev/disk_image.cc b/dev/disk_image.cc index f9e1c2fe3..20e693d0d 100644 --- a/dev/disk_image.cc +++ b/dev/disk_image.cc @@ -427,7 +427,7 @@ CowDiskImage::serialize(ostream &os) { string cowFilename = name() + ".cow"; SERIALIZE_SCALAR(cowFilename); - save(cowFilename); + save(Checkpoint::dir() + "/" + cowFilename); } void diff --git a/dev/ide_ctrl.cc b/dev/ide_ctrl.cc index 4805570d2..e40248461 100644 --- a/dev/ide_ctrl.cc +++ b/dev/ide_ctrl.cc @@ -60,7 +60,7 @@ IdeController::IdeController(const string &name, IntrControl *ic, MemoryController *mmu, PciConfigAll *cf, PciConfigData *cd, Tsunami *t, uint32_t bus_num, uint32_t dev_num, uint32_t func_num, - Bus *host_bus, HierParams *hier) + Bus *host_bus, Tick pio_latency, HierParams *hier) : PciDev(name, mmu, cf, cd, bus_num, dev_num, func_num), tsunami(t) { // put back pointer into Tsunami @@ -105,6 +105,7 @@ IdeController::IdeController(const string &name, IntrControl *ic, dmaInterface = new DMAInterface<Bus>(name + ".dma", host_bus, host_bus, 1); + pioLatency = pio_latency * host_bus->clockRatio; } // setup the disks attached to controller @@ -261,7 +262,7 @@ Tick IdeController::cacheAccess(MemReqPtr &req) { // @todo Add more accurate timing to cache access - return curTick + 1000; + return curTick + pioLatency; } //// @@ -700,6 +701,7 @@ BEGIN_DECLARE_SIM_OBJECT_PARAMS(IdeController) Param<uint32_t> pci_dev; Param<uint32_t> pci_func; SimObjectParam<Bus *> io_bus; + Param<Tick> pio_latency; SimObjectParam<HierParams *> hier; END_DECLARE_SIM_OBJECT_PARAMS(IdeController) @@ -716,6 +718,7 @@ BEGIN_INIT_SIM_OBJECT_PARAMS(IdeController) INIT_PARAM(pci_dev, "PCI device number"), INIT_PARAM(pci_func, "PCI function code"), INIT_PARAM_DFLT(io_bus, "Host bus to attach to", NULL), + INIT_PARAM_DFLT(pio_latency, "Programmed IO latency in bus cycles", 1), INIT_PARAM_DFLT(hier, "Hierarchy global variables", &defaultHierParams) END_INIT_SIM_OBJECT_PARAMS(IdeController) @@ -724,7 +727,7 @@ CREATE_SIM_OBJECT(IdeController) { return new IdeController(getInstanceName(), intr_ctrl, disks, mmu, configspace, configdata, tsunami, pci_bus, - pci_dev, pci_func, io_bus, hier); + pci_dev, pci_func, io_bus, pio_latency, hier); } REGISTER_SIM_OBJECT("IdeController", IdeController) diff --git a/dev/ide_ctrl.hh b/dev/ide_ctrl.hh index 39c64eb30..b29e5ae9a 100644 --- a/dev/ide_ctrl.hh +++ b/dev/ide_ctrl.hh @@ -167,7 +167,7 @@ class IdeController : public PciDev MemoryController *mmu, PciConfigAll *cf, PciConfigData *cd, Tsunami *t, uint32_t bus_num, uint32_t dev_num, uint32_t func_num, - Bus *host_bus, HierParams *hier); + Bus *host_bus, Tick pio_latency, HierParams *hier); /** * Deletes the connected devices. diff --git a/dev/ide_disk.cc b/dev/ide_disk.cc index ee21feaea..99724f077 100644 --- a/dev/ide_disk.cc +++ b/dev/ide_disk.cc @@ -341,8 +341,8 @@ IdeDisk::dmaPrdReadDone() curPrd.getByteCount(), (cmdBytesLeft/SectorSize), curPrd.getEOT(), curSector); - // make sure the new curPrdAddr is properly translated from PCI to system - curPrdAddr = pciToDma(curPrdAddr + sizeof(PrdEntry_t)); + // the prd pointer has already been translated, so just do an increment + curPrdAddr = curPrdAddr + sizeof(PrdEntry_t); if (dmaRead) doDmaRead(); diff --git a/dev/io_device.cc b/dev/io_device.cc index b39efa1f5..7703ad5e3 100644 --- a/dev/io_device.cc +++ b/dev/io_device.cc @@ -32,7 +32,7 @@ #include "sim/builder.hh" PioDevice::PioDevice(const std::string &name) - : FunctionalMemory(name), pioInterface(NULL) + : FunctionalMemory(name), pioInterface(NULL), pioLatency(0) {} PioDevice::~PioDevice() diff --git a/dev/io_device.hh b/dev/io_device.hh index e6014e73d..f49afc0a6 100644 --- a/dev/io_device.hh +++ b/dev/io_device.hh @@ -40,6 +40,7 @@ class PioDevice : public FunctionalMemory { protected: BaseInterface *pioInterface; + Tick pioLatency; public: PioDevice(const std::string &name); diff --git a/dev/ns_gige.cc b/dev/ns_gige.cc index 64f255e6b..b0b093cf4 100644 --- a/dev/ns_gige.cc +++ b/dev/ns_gige.cc @@ -96,17 +96,19 @@ uint32_t reverseEnd32(uint32_t); // NSGigE PCI Device // NSGigE::NSGigE(const std::string &name, IntrControl *i, Tick intr_delay, - PhysicalMemory *pmem, Tick tx_delay, Tick rx_delay, - MemoryController *mmu, HierParams *hier, Bus *header_bus, - Bus *payload_bus, Tick pio_latency, bool dma_desc_free, - bool dma_data_free, Tick dma_read_delay, Tick dma_write_delay, - Tick dma_read_factor, Tick dma_write_factor, PciConfigAll *cf, - PciConfigData *cd, Tsunami *t, uint32_t bus, uint32_t dev, - uint32_t func, bool rx_filter, const int eaddr[6]) + PhysicalMemory *pmem, Tick tx_delay, Tick rx_delay, + MemoryController *mmu, HierParams *hier, Bus *header_bus, + Bus *payload_bus, Tick pio_latency, bool dma_desc_free, + bool dma_data_free, Tick dma_read_delay, Tick dma_write_delay, + Tick dma_read_factor, Tick dma_write_factor, PciConfigAll *cf, + PciConfigData *cd, Tsunami *t, uint32_t bus, uint32_t dev, + uint32_t func, bool rx_filter, const int eaddr[6], + uint32_t tx_fifo_size, uint32_t rx_fifo_size) : PciDev(name, mmu, cf, cd, bus, dev, func), tsunami(t), ioEnable(false), + maxTxFifoSize(tx_fifo_size), maxRxFifoSize(rx_fifo_size), txPacket(0), rxPacket(0), txPacketBufPtr(NULL), rxPacketBufPtr(NULL), txXferLen(0), rxXferLen(0), txState(txIdle), CTDD(false), - txFifoAvail(MAX_TX_FIFO_SIZE), txHalt(false), + txFifoAvail(tx_fifo_size), txHalt(false), txFragPtr(0), txDescCnt(0), txDmaState(dmaIdle), rxState(rxIdle), CRDD(false), rxPktBytes(0), rxFifoCnt(0), rxHalt(false), rxFragPtr(0), rxDescCnt(0), rxDmaState(dmaIdle), extstsEnable(false), @@ -118,7 +120,7 @@ NSGigE::NSGigE(const std::string &name, IntrControl *i, Tick intr_delay, acceptMulticast(false), acceptUnicast(false), acceptPerfect(false), acceptArp(false), physmem(pmem), intctrl(i), intrTick(0), cpuPendingIntr(false), - intrEvent(0), interface(0), pioLatency(pio_latency) + intrEvent(0), interface(0) { tsunami->ethernet = this; @@ -126,6 +128,8 @@ NSGigE::NSGigE(const std::string &name, IntrControl *i, Tick intr_delay, pioInterface = newPioInterface(name, hier, header_bus, this, &NSGigE::cacheAccess); + pioLatency = pio_latency * header_bus->clockRatio; + if (payload_bus) dmaInterface = new DMAInterface<Bus>(name + ".dma", header_bus, payload_bus, 1); @@ -136,9 +140,10 @@ NSGigE::NSGigE(const std::string &name, IntrControl *i, Tick intr_delay, pioInterface = newPioInterface(name, hier, payload_bus, this, &NSGigE::cacheAccess); + pioLatency = pio_latency * payload_bus->clockRatio; + dmaInterface = new DMAInterface<Bus>(name + ".dma", payload_bus, payload_bus, 1); - } @@ -187,6 +192,59 @@ NSGigE::regStats() .prereq(rxBytes) ; + txIPChecksums + .name(name() + ".txIPChecksums") + .desc("Number of tx IP Checksums done by device") + .precision(0) + .prereq(txBytes) + ; + + rxIPChecksums + .name(name() + ".rxIPChecksums") + .desc("Number of rx IP Checksums done by device") + .precision(0) + .prereq(rxBytes) + ; + + txTCPChecksums + .name(name() + ".txTCPChecksums") + .desc("Number of tx TCP Checksums done by device") + .precision(0) + .prereq(txBytes) + ; + + rxTCPChecksums + .name(name() + ".rxTCPChecksums") + .desc("Number of rx TCP Checksums done by device") + .precision(0) + .prereq(rxBytes) + ; + + descDmaReads + .name(name() + ".descDMAReads") + .desc("Number of descriptors the device read w/ DMA") + .precision(0) + ; + + descDmaWrites + .name(name() + ".descDMAWrites") + .desc("Number of descriptors the device wrote w/ DMA") + .precision(0) + ; + + descDmaRdBytes + .name(name() + ".descDmaReadBytes") + .desc("number of descriptor bytes read w/ DMA") + .precision(0) + ; + + descDmaWrBytes + .name(name() + ".descDmaWriteBytes") + .desc("number of descriptor bytes write w/ DMA") + .precision(0) + ; + + txBandwidth .name(name() + ".txBandwidth") .desc("Transmit Bandwidth (bits/s)") @@ -1074,7 +1132,7 @@ NSGigE::txReset() DPRINTF(Ethernet, "transmit reset\n"); CTDD = false; - txFifoAvail = MAX_TX_FIFO_SIZE; + txFifoAvail = maxTxFifoSize; txHalt = false; txFragPtr = 0; assert(txDescCnt == 0); @@ -1146,7 +1204,7 @@ NSGigE::doRxDmaRead() rxDmaState = dmaReadWaiting; else dmaInterface->doDMA(Read, rxDmaAddr, rxDmaLen, curTick, - &rxDmaReadEvent); + &rxDmaReadEvent, true); return true; } @@ -1198,7 +1256,7 @@ NSGigE::doRxDmaWrite() rxDmaState = dmaWriteWaiting; else dmaInterface->doDMA(WriteInvalidate, rxDmaAddr, rxDmaLen, curTick, - &rxDmaWriteEvent); + &rxDmaWriteEvent, true); return true; } @@ -1273,6 +1331,9 @@ NSGigE::rxKick() rxDmaLen = sizeof(rxDescCache.link); rxDmaFree = dmaDescFree; + descDmaReads++; + descDmaRdBytes += rxDmaLen; + if (doRxDmaRead()) goto exit; } else { @@ -1283,6 +1344,9 @@ NSGigE::rxKick() rxDmaLen = sizeof(ns_desc); rxDmaFree = dmaDescFree; + descDmaReads++; + descDmaRdBytes += rxDmaLen; + if (doRxDmaRead()) goto exit; } @@ -1400,15 +1464,18 @@ NSGigE::rxKick() if (rxPacket->isIpPkt() && extstsEnable) { rxDescCache.extsts |= EXTSTS_IPPKT; + rxIPChecksums++; if (!ipChecksum(rxPacket, false)) { DPRINTF(EthernetCksum, "Rx IP Checksum Error\n"); rxDescCache.extsts |= EXTSTS_IPERR; } if (rxPacket->isTcpPkt()) { rxDescCache.extsts |= EXTSTS_TCPPKT; + rxTCPChecksums++; if (!tcpChecksum(rxPacket, false)) { DPRINTF(EthernetCksum, "Rx TCP Checksum Error\n"); rxDescCache.extsts |= EXTSTS_TCPERR; + } } else if (rxPacket->isUdpPkt()) { rxDescCache.extsts |= EXTSTS_UDPPKT; @@ -1434,6 +1501,9 @@ NSGigE::rxKick() rxDmaLen = sizeof(rxDescCache.cmdsts) + sizeof(rxDescCache.extsts); rxDmaFree = dmaDescFree; + descDmaWrites++; + descDmaWrBytes += rxDmaLen; + if (doRxDmaWrite()) goto exit; } @@ -1522,7 +1592,7 @@ NSGigE::transmit() } DPRINTF(Ethernet, "\n\nAttempt Pkt Transmit: txFifo length = %d\n", - MAX_TX_FIFO_SIZE - txFifoAvail); + maxTxFifoSize - txFifoAvail); if (interface->sendPacket(txFifo.front())) { if (DTRACE(Ethernet)) { if (txFifo.front()->isIpPkt()) { @@ -1586,7 +1656,7 @@ NSGigE::doTxDmaRead() txDmaState = dmaReadWaiting; else dmaInterface->doDMA(Read, txDmaAddr, txDmaLen, curTick, - &txDmaReadEvent); + &txDmaReadEvent, true); return true; } @@ -1638,7 +1708,7 @@ NSGigE::doTxDmaWrite() txDmaState = dmaWriteWaiting; else dmaInterface->doDMA(WriteInvalidate, txDmaAddr, txDmaLen, curTick, - &txDmaWriteEvent); + &txDmaWriteEvent, true); return true; } @@ -1707,6 +1777,9 @@ NSGigE::txKick() txDmaLen = sizeof(txDescCache.link); txDmaFree = dmaDescFree; + descDmaReads++; + descDmaRdBytes += txDmaLen; + if (doTxDmaRead()) goto exit; @@ -1718,6 +1791,9 @@ NSGigE::txKick() txDmaLen = sizeof(ns_desc); txDmaFree = dmaDescFree; + descDmaReads++; + descDmaRdBytes += txDmaLen; + if (doTxDmaRead()) goto exit; } @@ -1780,9 +1856,11 @@ NSGigE::txKick() udpChecksum(txPacket, true); } else if (txDescCache.extsts & EXTSTS_TCPPKT) { tcpChecksum(txPacket, true); + txTCPChecksums++; } if (txDescCache.extsts & EXTSTS_IPPKT) { ipChecksum(txPacket, true); + txIPChecksums++; } } @@ -1813,11 +1891,10 @@ NSGigE::txKick() txDmaLen = sizeof(txDescCache.cmdsts) + sizeof(txDescCache.extsts); txDmaFree = dmaDescFree; - if (doTxDmaWrite()) - goto exit; + descDmaWrites++; + descDmaWrBytes += txDmaLen; transmit(); - txPacket = 0; if (txHalt) { @@ -1826,24 +1903,35 @@ NSGigE::txKick() txHalt = false; } else txState = txAdvance; + + if (doTxDmaWrite()) + goto exit; } } else { DPRINTF(EthernetSM, "this descriptor isn't done yet\n"); - txState = txFragRead; + if (txFifoAvail) { + txState = txFragRead; - /* The number of bytes transferred is either whatever is left - in the descriptor (txDescCnt), or if there is not enough - room in the fifo, just whatever room is left in the fifo - */ - txXferLen = min<uint32_t>(txDescCnt, txFifoAvail); + /* The number of bytes transferred is either whatever is left + in the descriptor (txDescCnt), or if there is not enough + room in the fifo, just whatever room is left in the fifo + */ + txXferLen = min<uint32_t>(txDescCnt, txFifoAvail); - txDmaAddr = txFragPtr & 0x3fffffff; - txDmaData = txPacketBufPtr; - txDmaLen = txXferLen; - txDmaFree = dmaDataFree; + txDmaAddr = txFragPtr & 0x3fffffff; + txDmaData = txPacketBufPtr; + txDmaLen = txXferLen; + txDmaFree = dmaDataFree; + + if (doTxDmaRead()) + goto exit; + } else { + txState = txFifoBlock; + transmit(); - if (doTxDmaRead()) goto exit; + } + } break; @@ -1979,7 +2067,7 @@ NSGigE::recvPacket(PacketPtr packet) rxBytes += packet->length; rxPackets++; - DPRINTF(Ethernet, "\n\nReceiving packet from wire, rxFifoAvail = %d\n", MAX_RX_FIFO_SIZE - rxFifoCnt); + DPRINTF(Ethernet, "\n\nReceiving packet from wire, rxFifoAvail = %d\n", maxRxFifoSize - rxFifoCnt); if (rxState == rxIdle) { DPRINTF(Ethernet, "receive disabled...packet dropped\n"); @@ -1993,7 +2081,7 @@ NSGigE::recvPacket(PacketPtr packet) return true; } - if ((rxFifoCnt + packet->length) >= MAX_RX_FIFO_SIZE) { + if ((rxFifoCnt + packet->length) >= maxRxFifoSize) { DPRINTF(Ethernet, "packet will not fit in receive buffer...packet dropped\n"); devIntrPost(ISR_RXORN); @@ -2555,6 +2643,8 @@ BEGIN_DECLARE_SIM_OBJECT_PARAMS(NSGigE) Param<uint32_t> pci_bus; Param<uint32_t> pci_dev; Param<uint32_t> pci_func; + Param<uint32_t> tx_fifo_size; + Param<uint32_t> rx_fifo_size; END_DECLARE_SIM_OBJECT_PARAMS(NSGigE) @@ -2572,7 +2662,7 @@ BEGIN_INIT_SIM_OBJECT_PARAMS(NSGigE) INIT_PARAM_DFLT(header_bus, "The IO Bus to attach to for headers", NULL), INIT_PARAM_DFLT(payload_bus, "The IO Bus to attach to for payload", NULL), INIT_PARAM_DFLT(hier, "Hierarchy global variables", &defaultHierParams), - INIT_PARAM_DFLT(pio_latency, "Programmed IO latency", 1000), + INIT_PARAM_DFLT(pio_latency, "Programmed IO latency in bus cycles", 1), INIT_PARAM_DFLT(dma_desc_free, "DMA of Descriptors is free", false), INIT_PARAM_DFLT(dma_data_free, "DMA of Data is free", false), INIT_PARAM_DFLT(dma_read_delay, "fixed delay for dma reads", 0), @@ -2584,7 +2674,9 @@ BEGIN_INIT_SIM_OBJECT_PARAMS(NSGigE) INIT_PARAM(tsunami, "Tsunami"), INIT_PARAM(pci_bus, "PCI bus"), INIT_PARAM(pci_dev, "PCI device number"), - INIT_PARAM(pci_func, "PCI function code") + INIT_PARAM(pci_func, "PCI function code"), + INIT_PARAM_DFLT(tx_fifo_size, "max size in bytes of txFifo", 131072), + INIT_PARAM_DFLT(rx_fifo_size, "max size in bytes of rxFifo", 131072) END_INIT_SIM_OBJECT_PARAMS(NSGigE) @@ -2600,7 +2692,8 @@ CREATE_SIM_OBJECT(NSGigE) payload_bus, pio_latency, dma_desc_free, dma_data_free, dma_read_delay, dma_write_delay, dma_read_factor, dma_write_factor, configspace, configdata, - tsunami, pci_bus, pci_dev, pci_func, rx_filter, eaddr); + tsunami, pci_bus, pci_dev, pci_func, rx_filter, eaddr, + tx_fifo_size, rx_fifo_size); } REGISTER_SIM_OBJECT("NSGigE", NSGigE) diff --git a/dev/ns_gige.hh b/dev/ns_gige.hh index 191c867ce..79ae00e64 100644 --- a/dev/ns_gige.hh +++ b/dev/ns_gige.hh @@ -46,8 +46,9 @@ #include "mem/bus/bus.hh" /** defined by the NS83820 data sheet */ -#define MAX_TX_FIFO_SIZE 8192 -#define MAX_RX_FIFO_SIZE 32768 +//these are now params for the device +//#define MAX_TX_FIFO_SIZE 8192 +//#define MAX_RX_FIFO_SIZE 32768 /** length of ethernet address in bytes */ #define EADDR_LEN 6 @@ -168,7 +169,9 @@ class NSGigE : public PciDev /*** BASIC STRUCTURES FOR TX/RX ***/ /* Data FIFOs */ pktbuf_t txFifo; + uint32_t maxTxFifoSize; pktbuf_t rxFifo; + uint32_t maxRxFifoSize; /** various helper vars */ PacketPtr txPacket; @@ -332,13 +335,14 @@ class NSGigE : public PciDev public: NSGigE(const std::string &name, IntrControl *i, Tick intr_delay, - PhysicalMemory *pmem, Tick tx_delay, Tick rx_delay, - MemoryController *mmu, HierParams *hier, Bus *header_bus, - Bus *payload_bus, Tick pio_latency, bool dma_desc_free, - bool dma_data_free, Tick dma_read_delay, Tick dma_write_delay, - Tick dma_read_factor, Tick dma_write_factor, PciConfigAll *cf, - PciConfigData *cd, Tsunami *t, uint32_t bus, uint32_t dev, - uint32_t func, bool rx_filter, const int eaddr[6]); + PhysicalMemory *pmem, Tick tx_delay, Tick rx_delay, + MemoryController *mmu, HierParams *hier, Bus *header_bus, + Bus *payload_bus, Tick pio_latency, bool dma_desc_free, + bool dma_data_free, Tick dma_read_delay, Tick dma_write_delay, + Tick dma_read_factor, Tick dma_write_factor, PciConfigAll *cf, + PciConfigData *cd, Tsunami *t, uint32_t bus, uint32_t dev, + uint32_t func, bool rx_filter, const int eaddr[6], + uint32_t tx_fifo_size, uint32_t rx_fifo_size); ~NSGigE(); virtual void WriteConfig(int offset, int size, uint32_t data); @@ -366,14 +370,19 @@ class NSGigE : public PciDev Stats::Scalar<> rxBytes; Stats::Scalar<> txPackets; Stats::Scalar<> rxPackets; + Stats::Scalar<> txIPChecksums; + Stats::Scalar<> rxIPChecksums; + Stats::Scalar<> txTCPChecksums; + Stats::Scalar<> rxTCPChecksums; + Stats::Scalar<> descDmaReads; + Stats::Scalar<> descDmaWrites; + Stats::Scalar<> descDmaRdBytes; + Stats::Scalar<> descDmaWrBytes; Stats::Formula txBandwidth; Stats::Formula rxBandwidth; Stats::Formula txPacketRate; Stats::Formula rxPacketRate; - private: - Tick pioLatency; - public: Tick cacheAccess(MemReqPtr &req); }; diff --git a/dev/pciconfigall.cc b/dev/pciconfigall.cc index 8937b8e67..740a9b4ac 100644 --- a/dev/pciconfigall.cc +++ b/dev/pciconfigall.cc @@ -47,7 +47,7 @@ using namespace std; PciConfigAll::PciConfigAll(const string &name, Addr a, MemoryController *mmu, - HierParams *hier, Bus *bus) + HierParams *hier, Bus *bus, Tick pio_latency) : PioDevice(name), addr(a) { mmu->add_child(this, Range<Addr>(addr, addr + size)); @@ -56,6 +56,7 @@ PciConfigAll::PciConfigAll(const string &name, Addr a, MemoryController *mmu, pioInterface = newPioInterface(name, hier, bus, this, &PciConfigAll::cacheAccess); pioInterface->addAddrRange(addr, addr + size - 1); + pioLatency = pio_latency * bus->clockRatio; } // Make all the pointers to devices null @@ -175,7 +176,7 @@ PciConfigAll::unserialize(Checkpoint *cp, const std::string §ion) Tick PciConfigAll::cacheAccess(MemReqPtr &req) { - return curTick + 1000; + return curTick + pioLatency; } #ifndef DOXYGEN_SHOULD_SKIP_THIS @@ -186,6 +187,7 @@ BEGIN_DECLARE_SIM_OBJECT_PARAMS(PciConfigAll) Param<Addr> addr; Param<Addr> mask; SimObjectParam<Bus*> io_bus; + Param<Tick> pio_latency; SimObjectParam<HierParams *> hier; END_DECLARE_SIM_OBJECT_PARAMS(PciConfigAll) @@ -196,13 +198,15 @@ BEGIN_INIT_SIM_OBJECT_PARAMS(PciConfigAll) INIT_PARAM(addr, "Device Address"), INIT_PARAM(mask, "Address Mask"), INIT_PARAM_DFLT(io_bus, "The IO Bus to attach to", NULL), + INIT_PARAM_DFLT(pio_latency, "Programmed IO latency in bus cycles", 1), INIT_PARAM_DFLT(hier, "Hierarchy global variables", &defaultHierParams) END_INIT_SIM_OBJECT_PARAMS(PciConfigAll) CREATE_SIM_OBJECT(PciConfigAll) { - return new PciConfigAll(getInstanceName(), addr, mmu, hier, io_bus); + return new PciConfigAll(getInstanceName(), addr, mmu, hier, io_bus, + pio_latency); } REGISTER_SIM_OBJECT("PciConfigAll", PciConfigAll) diff --git a/dev/pciconfigall.hh b/dev/pciconfigall.hh index 356e62a3c..d6b37b9b1 100644 --- a/dev/pciconfigall.hh +++ b/dev/pciconfigall.hh @@ -73,7 +73,7 @@ class PciConfigAll : public PioDevice * @param bus The bus that this device is attached to */ PciConfigAll(const std::string &name, Addr a, MemoryController *mmu, - HierParams *hier, Bus *bus); + HierParams *hier, Bus *bus, Tick pio_latency); /** diff --git a/dev/tsunami_cchip.cc b/dev/tsunami_cchip.cc index 0fbfcb56f..870924a2f 100644 --- a/dev/tsunami_cchip.cc +++ b/dev/tsunami_cchip.cc @@ -49,7 +49,8 @@ using namespace std; TsunamiCChip::TsunamiCChip(const string &name, Tsunami *t, Addr a, - MemoryController *mmu, HierParams *hier, Bus* bus) + MemoryController *mmu, HierParams *hier, Bus* bus, + Tick pio_latency) : PioDevice(name), addr(a), tsunami(t) { mmu->add_child(this, Range<Addr>(addr, addr + size)); @@ -66,6 +67,7 @@ TsunamiCChip::TsunamiCChip(const string &name, Tsunami *t, Addr a, pioInterface = newPioInterface(name, hier, bus, this, &TsunamiCChip::cacheAccess); pioInterface->addAddrRange(addr, addr + size - 1); + pioLatency = pio_latency * bus->clockRatio; } drir = 0; @@ -383,7 +385,7 @@ TsunamiCChip::clearDRIR(uint32_t interrupt) Tick TsunamiCChip::cacheAccess(MemReqPtr &req) { - return curTick + 1000; + return curTick + pioLatency; } @@ -417,6 +419,7 @@ BEGIN_DECLARE_SIM_OBJECT_PARAMS(TsunamiCChip) SimObjectParam<MemoryController *> mmu; Param<Addr> addr; SimObjectParam<Bus*> io_bus; + Param<Tick> pio_latency; SimObjectParam<HierParams *> hier; END_DECLARE_SIM_OBJECT_PARAMS(TsunamiCChip) @@ -427,13 +430,15 @@ BEGIN_INIT_SIM_OBJECT_PARAMS(TsunamiCChip) INIT_PARAM(mmu, "Memory Controller"), INIT_PARAM(addr, "Device Address"), INIT_PARAM_DFLT(io_bus, "The IO Bus to attach to", NULL), + INIT_PARAM_DFLT(pio_latency, "Programmed IO latency in bus cycles", 1), INIT_PARAM_DFLT(hier, "Hierarchy global variables", &defaultHierParams) END_INIT_SIM_OBJECT_PARAMS(TsunamiCChip) CREATE_SIM_OBJECT(TsunamiCChip) { - return new TsunamiCChip(getInstanceName(), tsunami, addr, mmu, hier, io_bus); + return new TsunamiCChip(getInstanceName(), tsunami, addr, mmu, hier, + io_bus, pio_latency); } REGISTER_SIM_OBJECT("TsunamiCChip", TsunamiCChip) diff --git a/dev/tsunami_cchip.hh b/dev/tsunami_cchip.hh index a358c98ba..3269cf53a 100644 --- a/dev/tsunami_cchip.hh +++ b/dev/tsunami_cchip.hh @@ -100,7 +100,8 @@ class TsunamiCChip : public PioDevice * @param bus The bus that this device is attached to */ TsunamiCChip(const std::string &name, Tsunami *t, Addr a, - MemoryController *mmu, HierParams *hier, Bus *bus); + MemoryController *mmu, HierParams *hier, Bus *bus, + Tick pio_latency); /** * Process a read to the CChip. diff --git a/dev/tsunami_io.cc b/dev/tsunami_io.cc index 4c798a852..105e3b5b7 100644 --- a/dev/tsunami_io.cc +++ b/dev/tsunami_io.cc @@ -160,7 +160,8 @@ TsunamiIO::ClockEvent::unserialize(Checkpoint *cp, const std::string §ion) } TsunamiIO::TsunamiIO(const string &name, Tsunami *t, time_t init_time, - Addr a, MemoryController *mmu, HierParams *hier, Bus *bus) + Addr a, MemoryController *mmu, HierParams *hier, Bus *bus, + Tick pio_latency) : PioDevice(name), addr(a), tsunami(t), rtc(t) { mmu->add_child(this, Range<Addr>(addr, addr + size)); @@ -169,6 +170,7 @@ TsunamiIO::TsunamiIO(const string &name, Tsunami *t, time_t init_time, pioInterface = newPioInterface(name, hier, bus, this, &TsunamiIO::cacheAccess); pioInterface->addAddrRange(addr, addr + size - 1); + pioLatency = pio_latency * bus->clockRatio; } // set the back pointer from tsunami to myself @@ -425,7 +427,7 @@ TsunamiIO::clearPIC(uint8_t bitvector) Tick TsunamiIO::cacheAccess(MemReqPtr &req) { - return curTick + 1000; + return curTick + pioLatency; } void @@ -476,6 +478,7 @@ BEGIN_DECLARE_SIM_OBJECT_PARAMS(TsunamiIO) SimObjectParam<MemoryController *> mmu; Param<Addr> addr; SimObjectParam<Bus*> io_bus; + Param<Tick> pio_latency; SimObjectParam<HierParams *> hier; END_DECLARE_SIM_OBJECT_PARAMS(TsunamiIO) @@ -488,6 +491,7 @@ BEGIN_INIT_SIM_OBJECT_PARAMS(TsunamiIO) INIT_PARAM(mmu, "Memory Controller"), INIT_PARAM(addr, "Device Address"), INIT_PARAM_DFLT(io_bus, "The IO Bus to attach to", NULL), + INIT_PARAM_DFLT(pio_latency, "Programmed IO latency in bus cycles", 1), INIT_PARAM_DFLT(hier, "Hierarchy global variables", &defaultHierParams) END_INIT_SIM_OBJECT_PARAMS(TsunamiIO) @@ -495,7 +499,7 @@ END_INIT_SIM_OBJECT_PARAMS(TsunamiIO) CREATE_SIM_OBJECT(TsunamiIO) { return new TsunamiIO(getInstanceName(), tsunami, time, addr, mmu, hier, - io_bus); + io_bus, pio_latency); } REGISTER_SIM_OBJECT("TsunamiIO", TsunamiIO) diff --git a/dev/tsunami_io.hh b/dev/tsunami_io.hh index 75e5d764c..d507355c3 100644 --- a/dev/tsunami_io.hh +++ b/dev/tsunami_io.hh @@ -237,7 +237,8 @@ class TsunamiIO : public PioDevice * @param mmu pointer to the memory controller that sends us events. */ TsunamiIO(const std::string &name, Tsunami *t, time_t init_time, - Addr a, MemoryController *mmu, HierParams *hier, Bus *bus); + Addr a, MemoryController *mmu, HierParams *hier, Bus *bus, + Tick pio_latency); /** * Create the tm struct from seconds since 1970 diff --git a/dev/tsunami_pchip.cc b/dev/tsunami_pchip.cc index b1346bb1a..89940fb5a 100644 --- a/dev/tsunami_pchip.cc +++ b/dev/tsunami_pchip.cc @@ -50,7 +50,7 @@ using namespace std; TsunamiPChip::TsunamiPChip(const string &name, Tsunami *t, Addr a, MemoryController *mmu, HierParams *hier, - Bus *bus) + Bus *bus, Tick pio_latency) : PioDevice(name), addr(a), tsunami(t) { mmu->add_child(this, Range<Addr>(addr, addr + size)); @@ -65,6 +65,7 @@ TsunamiPChip::TsunamiPChip(const string &name, Tsunami *t, Addr a, pioInterface = newPioInterface(name, hier, bus, this, &TsunamiPChip::cacheAccess); pioInterface->addAddrRange(addr, addr + size - 1); + pioLatency = pio_latency * bus->clockRatio; } @@ -351,7 +352,7 @@ TsunamiPChip::unserialize(Checkpoint *cp, const std::string §ion) Tick TsunamiPChip::cacheAccess(MemReqPtr &req) { - return curTick + 1000; + return curTick + pioLatency; } BEGIN_DECLARE_SIM_OBJECT_PARAMS(TsunamiPChip) @@ -360,6 +361,7 @@ BEGIN_DECLARE_SIM_OBJECT_PARAMS(TsunamiPChip) SimObjectParam<MemoryController *> mmu; Param<Addr> addr; SimObjectParam<Bus*> io_bus; + Param<Tick> pio_latency; SimObjectParam<HierParams *> hier; END_DECLARE_SIM_OBJECT_PARAMS(TsunamiPChip) @@ -370,13 +372,15 @@ BEGIN_INIT_SIM_OBJECT_PARAMS(TsunamiPChip) INIT_PARAM(mmu, "Memory Controller"), INIT_PARAM(addr, "Device Address"), INIT_PARAM_DFLT(io_bus, "The IO Bus to attach to", NULL), + INIT_PARAM_DFLT(pio_latency, "Programmed IO latency in bus cycles", 1), INIT_PARAM_DFLT(hier, "Hierarchy global variables", &defaultHierParams) END_INIT_SIM_OBJECT_PARAMS(TsunamiPChip) CREATE_SIM_OBJECT(TsunamiPChip) { - return new TsunamiPChip(getInstanceName(), tsunami, addr, mmu, hier, io_bus); + return new TsunamiPChip(getInstanceName(), tsunami, addr, mmu, hier, + io_bus, pio_latency); } REGISTER_SIM_OBJECT("TsunamiPChip", TsunamiPChip) diff --git a/dev/tsunami_pchip.hh b/dev/tsunami_pchip.hh index af50872a0..f88098d58 100644 --- a/dev/tsunami_pchip.hh +++ b/dev/tsunami_pchip.hh @@ -80,7 +80,8 @@ class TsunamiPChip : public PioDevice * @param bus The bus that this device is attached to */ TsunamiPChip(const std::string &name, Tsunami *t, Addr a, - MemoryController *mmu, HierParams *hier, Bus *bus); + MemoryController *mmu, HierParams *hier, Bus *bus, + Tick pio_latency); /** * Translate a PCI bus address to a memory address for DMA. diff --git a/dev/uart.cc b/dev/uart.cc index 4784ad640..8ba59579d 100644 --- a/dev/uart.cc +++ b/dev/uart.cc @@ -88,7 +88,7 @@ Uart::IntrEvent::scheduleIntr() } Uart::Uart(const string &name, SimConsole *c, MemoryController *mmu, Addr a, - Addr s, HierParams *hier, Bus *bus, Platform *p) + Addr s, HierParams *hier, Bus *bus, Tick pio_latency, Platform *p) : PioDevice(name), addr(a), size(s), cons(c), txIntrEvent(this, TX_INT), rxIntrEvent(this, RX_INT), platform(p) { @@ -98,7 +98,8 @@ Uart::Uart(const string &name, SimConsole *c, MemoryController *mmu, Addr a, if (bus) { pioInterface = newPioInterface(name, hier, bus, this, &Uart::cacheAccess); - pioInterface->addAddrRange(addr, addr + size - 1); + pioInterface->addAddrRange(addr, addr + size - 1); + pioLatency = pio_latency * bus->clockRatio; } readAddr = 0; @@ -370,7 +371,7 @@ Uart::dataAvailable() Tick Uart::cacheAccess(MemReqPtr &req) { - return curTick + 1000; + return curTick + pioLatency; } void @@ -432,6 +433,7 @@ BEGIN_DECLARE_SIM_OBJECT_PARAMS(Uart) Param<Addr> addr; Param<Addr> size; SimObjectParam<Bus*> io_bus; + Param<Tick> pio_latency; SimObjectParam<HierParams *> hier; @@ -445,6 +447,7 @@ BEGIN_INIT_SIM_OBJECT_PARAMS(Uart) INIT_PARAM(addr, "Device Address"), INIT_PARAM_DFLT(size, "Device size", 0x8), INIT_PARAM_DFLT(io_bus, "The IO Bus to attach to", NULL), + INIT_PARAM_DFLT(pio_latency, "Programmed IO latency in bus cycles", 1), INIT_PARAM_DFLT(hier, "Hierarchy global variables", &defaultHierParams) END_INIT_SIM_OBJECT_PARAMS(Uart) @@ -452,7 +455,7 @@ END_INIT_SIM_OBJECT_PARAMS(Uart) CREATE_SIM_OBJECT(Uart) { return new Uart(getInstanceName(), console, mmu, addr, size, hier, io_bus, - platform); + pio_latency, platform); } REGISTER_SIM_OBJECT("Uart", Uart) diff --git a/dev/uart.hh b/dev/uart.hh index 07ad4d0c8..ac8ed7d73 100644 --- a/dev/uart.hh +++ b/dev/uart.hh @@ -76,7 +76,8 @@ class Uart : public PioDevice public: Uart(const string &name, SimConsole *c, MemoryController *mmu, - Addr a, Addr s, HierParams *hier, Bus *bus, Platform *p); + Addr a, Addr s, HierParams *hier, Bus *bus, Tick pio_latency, + Platform *p); Fault read(MemReqPtr &req, uint8_t *data); Fault write(MemReqPtr &req, const uint8_t *data); diff --git a/util/ccdrv/Makefile b/util/ccdrv/Makefile new file mode 100644 index 000000000..123333533 --- /dev/null +++ b/util/ccdrv/Makefile @@ -0,0 +1,29 @@ +# Copyright (c) 2004 The Regents of The University of Michigan +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer; +# redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution; +# neither the name of the copyright holders nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# Authors: Ali Saidi + +obj-m := devtime.o diff --git a/util/ccdrv/devtime.c b/util/ccdrv/devtime.c new file mode 100644 index 000000000..e487f2fe7 --- /dev/null +++ b/util/ccdrv/devtime.c @@ -0,0 +1,164 @@ +/* + * Copyright (c) 2004 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include <linux/module.h> +#include <linux/config.h> +#include <linux/moduleparam.h> +#include <linux/init.h> +#include <linux/fs.h> +#include <asm/uaccess.h> +#include <linux/kernel.h> +#include <asm/io.h> +#include <asm/page.h> +#include <linux/netdevice.h> + +#ifdef __i386__ +#include <asm/processor.h> +#include <asm/msr.h> +#endif + +#define DRIVER_AUTHOR "Ali Saidi" +#define DRIVER_DESC "Interface to time uncacachable read and writes to device registers" +#define DRIVER_VER "0.1" + +static char *dataAddr = NULL; +static int count = 0; + +static inline uint32_t cycleCounter(uint32_t dep); + +static int __init devtime_start(void) +{ + uint64_t addr; + uint32_t t1, t2; + uint32_t trash; + int x; + uint32_t *times; + uint32_t num = 0; + struct net_device *dev; + + printk("Devtime Driver Version %s Loaded...\n", DRIVER_VER); + + if (dataAddr != 0 && count != 0) { + addr = simple_strtoull(dataAddr, NULL, 0); + + addr = ioremap(addr, PAGE_SIZE); + /** + * Make sure that the remapping actually worked. On alpha we have + * linear addressing, so its not a problem. But it can fail in x86 + * if physical memory is mapped to this address. + */ + times = kmalloc(sizeof(uint32_t) * count, GFP_USER); + if (!times) { + printk("Could not allocate memory... Try again later.\n"); + return -1; + } + + if (addr) { + printk("Preparing to read %#llx %d times.\n", addr, count); + + t1 = cycleCounter(trash); + for (x = 0; x < count; x++) { + trash = readl(addr); + t2 = cycleCounter(trash); + times[num++] = t2 - t1; + t1 = t2; + } + + /** + * Unmap the address. + */ + iounmap(addr); + + printk("Measurements:\n"); + for (x = 0; x < count; x++) { + printk("%d ", times[x]); + if (((x + 1) % 10) == 0) + printk("\n"); + } + printk("\nDone.\n"); + } else { + printk("Unable to remap address. Please try again later.\n"); + } + } else { + dev = dev_get_by_name("eth0"); + if (dev) { + printk("Eth0: MemStart: %#lx MemEnd: %#lx I/O Addr: %#lx\n", + dev->mem_start, dev->mem_end, dev->base_addr); + dev_put(dev); + } + dev = 0; + dev = dev_get_by_name("eth1"); + if (dev) { + printk("Eth1: MemStart: %#lx MemEnd: %#lx I/O Addr: %#lx\n", + dev->mem_start, dev->mem_end, dev->base_addr); + dev_put(dev); + } + + printk("Required information not supplied.\n"); + } + + return 0; +} + +#ifdef __i386__ + +static inline uint32_t cycleCounter(uint32_t dep) +{ + uint32_t time; + cpuid_eax(0); + rdtscl(time); + cpuid_eax(0); + return time; +} + +#elif __alpha__ + +inline uint32_t cycleCounter(uint32_t dep) +{ + uint32_t res; + asm volatile ("rpcc %0, %1" : "=r"(res) : "r" (dep) : "memory"); + return res; +} +#else +#error Architecture NOT SUPPORTE +#endif + +static void __exit devtime_end(void) +{ + printk("Devtime Driver Version %s Unloaded...\n", DRIVER_VER); +} + + +module_init(devtime_start); +module_exit(devtime_end); + +MODULE_LICENSE("Dual BSD/GPL"); +MODULE_AUTHOR(DRIVER_AUTHOR); +MODULE_DESCRIPTION(DRIVER_DESC); +module_param(dataAddr, charp, 0); +module_param(count, int, 0); diff --git a/util/ccdrv/readme.txt b/util/ccdrv/readme.txt new file mode 100644 index 000000000..4b9892f69 --- /dev/null +++ b/util/ccdrv/readme.txt @@ -0,0 +1,18 @@ +This driver will read the address you point it to [count] times and +print the results to the systemlog. + +To build the driver (Linux 2.6.X only) execute: +make -C /path/to/linux-2.6.X/ SUBDIRS=$PWD modules + + +Insmodding the kernel module without options will print +the device addresses of eth0 and eth1 if they exist. + +Insmodding the kernel module with the options: +dataAddr=0xXXXXXXXXX and count=XXXXX + +will read a long at addr dataAddr count times and return. + +Between runs you need to rmmod the module from the kernel. + + |