diff options
66 files changed, 1321 insertions, 505 deletions
@@ -1,4 +1,4 @@ -Copyright (c) 2000-2003 The Regents of The University of Michigan +Copyright (c) 2000-2004 The Regents of The University of Michigan All rights reserved. Redistribution and use in source and binary forms, with or without @@ -1,4 +1,3 @@ - This is release m5_1.0_beta1 of the M5 simulator. This file contains brief "getting started" information and release @@ -13,13 +12,23 @@ distribution. The archive you've unpacked has three subdirectories: - m5: the simulator itself - m5-test: regression tests and scripts to run them - ext: less-common external packages needed to build m5 - (currently just "ply") + (currently ply and libelf) + +M5 is a capable, full-system simulator that current supports both Linux +2.4/2.6 and the proprietary Compaq/HP Tru64 version of Unix. We are able +to distribute Linux bootdisks, but we are unable to distribute bootable +disk images of Tru64 Unix. If you have a Tru64 license and are interested +in obtaining disk images, contact us at m5-dev@eecs.umich.edu. + +WHAT'S NEEDED +------------- +-GCC(3.X) +-Python(2.2.2+) -Although M5 is capable of full-system simulation, the only OS it -currently supports is the proprietary Compaq/HP Tru64 version of Unix. -We are thus unable to distribute bootable disk images freely. If you -have a Tru64 license and are interested in obtaining disk images, -contact us at m5-dev@eecs.umich.edu. +WHAT'S RECOMMENDED +------------------ +-MySQL (for statistics complex statistics storage/retrieval) +-Python-MysqlDB (for statistics analysis) GETTING STARTED --------------- @@ -28,24 +37,23 @@ The following steps will build and test the simulator. The variable "$top" refers to the top directory where you've unpacked the files, i.e., the one containing the m5, m5-test, and ext directories. -cd $top/m5/setup -./setup ALPHA # set up build/ALPHA directory -cd $top/m5/build/ALPHA -make m5.opt # use "-j N" if you've got an MP system -# wait for build... +There are three different build targets and three optimizations in each level: +Target: +------- +ALPHA - Syscall emulation simulation +KERNEL - Linux full system simulation +KERNEL_TLASER - Tru64 Unix full system simulation + +Optimization: +------------- +m5.debug - debug version of the code with tracing and without optimization +m5.opt - optimized version of code with tracing +m5.fast - optimized version of the code without tracing and asserts + +cd $top/m5/build +scons TARGET/OPTLEVL # e.g. KERNEL/m5.opt, use -j N if you have a MP system cd $top/m5-test ./do-tests.pl -B ALPHA # test what you just built +./do-tests.pl -B KERNEL # test what you just built # wait for tests to run... # should end with "finished do-tests successfully!" - -If you run into errors regarding m5/arch/alpha/decoder.cc, just -"touch" that file to update its timestamp. This file is generated -from a compact ISA description using a program written in Python. If -you have Python 2.2.2 or later installed on your system, you should be -able to generate it yourself, but if you don't have Python (or have an -older version), you may run in to trouble. Since we've shipped a -working copy of decoder.cc, it's not necessary to have Python to build -M5 (unless you start modifying the ISA decription). Unfortunately, -sometimes make gets confused and tries to do so anyway. The "touch" -should convince make to stop trying. - diff --git a/SConscript b/SConscript index 7d8d9f50e..60e703e9b 100644 --- a/SConscript +++ b/SConscript @@ -59,6 +59,7 @@ base_sources = Split(''' base/hybrid_pred.cc base/inifile.cc base/intmath.cc + base/match.cc base/misc.cc base/pollevent.cc base/python.cc @@ -162,6 +163,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 +220,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 @@ -254,6 +259,7 @@ full_system_sources = Split(''' kern/linux/linux_events.cc kern/linux/linux_syscalls.cc kern/linux/linux_system.cc + kern/linux/printk.cc kern/tru64/dump_mbuf.cc kern/tru64/printf.cc kern/tru64/tru64_events.cc @@ -310,7 +316,8 @@ env.Command(Split('''arch/alpha/decoder.cc arch/alpha/fast_cpu_exec.cc arch/alpha/simple_cpu_exec.cc arch/alpha/full_cpu_exec.cc'''), - 'arch/alpha/isa_desc', + Split('''arch/alpha/isa_desc + arch/isa_parser.py'''), '$SRCDIR/arch/isa_parser.py $SOURCE $TARGET.dir arch/alpha') diff --git a/arch/alpha/ev5.hh b/arch/alpha/ev5.hh index 5b27dd3dc..f49eadeb0 100644 --- a/arch/alpha/ev5.hh +++ b/arch/alpha/ev5.hh @@ -123,5 +123,6 @@ #define PAL_BASE 0x4000 +#define PAL_MAX 0x10000 #endif //__EV5_H__ diff --git a/arch/alpha/vtophys.cc b/arch/alpha/vtophys.cc index 464ed41e6..5468d4b07 100644 --- a/arch/alpha/vtophys.cc +++ b/arch/alpha/vtophys.cc @@ -98,7 +98,7 @@ vtophys(ExecContext *xc, Addr vaddr) Addr paddr = 0; //@todo Andrew couldn't remember why he commented some of this code //so I put it back in. Perhaps something to do with gdb debugging? - if (PC_PAL(vaddr)) { + if (PC_PAL(vaddr) && (vaddr < PAL_MAX)) { paddr = vaddr & ~ULL(1); } else { if (vaddr >= ALPHA_K0SEG_BASE && vaddr <= ALPHA_K0SEG_END) { diff --git a/base/match.cc b/base/match.cc new file mode 100644 index 000000000..ba5c2181c --- /dev/null +++ b/base/match.cc @@ -0,0 +1,96 @@ +/* + * Copyright (c) 2001-2004 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "base/match.hh" +#include "base/str.hh" + +using namespace std; + +ObjectMatch::ObjectMatch() +{ +} + +ObjectMatch::ObjectMatch(const string &expr) +{ + setExpression(expr); +} + +void +ObjectMatch::setExpression(const string &expr) +{ + tokens.resize(1); + tokenize(tokens[0], expr, '.'); +} + +void +ObjectMatch::setExpression(const vector<string> &expr) +{ + if (expr.empty()) { + tokens.resize(0); + } else { + tokens.resize(expr.size()); + for (int i = 0; i < expr.size(); ++i) + tokenize(tokens[i], expr[i], '.'); + } +} + +/** + * @todo this should probably be changed to just use regular + * expression code + */ +bool +ObjectMatch::domatch(const string &name) const +{ + vector<string> name_tokens; + tokenize(name_tokens, name, '.'); + int ntsize = name_tokens.size(); + + int num_expr = tokens.size(); + for (int i = 0; i < num_expr; ++i) { + const vector<string> &token = tokens[i]; + int jstop = token.size(); + + bool match = true; + for (int j = 0; j < jstop; ++j) { + if (j >= ntsize) + break; + + const string &var = token[j]; + if (var != "*" && var != name_tokens[j]) { + match = false; + break; + } + } + + if (match == true) + return true; + } + + return false; +} + diff --git a/base/match.hh b/base/match.hh new file mode 100644 index 000000000..8831ed424 --- /dev/null +++ b/base/match.hh @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2001-2004 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* @file + * User Console Definitions + */ + +#ifndef __BASE_MATCH_HH__ +#define __BASE_MATCH_HH__ + +#include <string> +#include <vector> + +class ObjectMatch +{ + protected: + std::vector<std::vector<std::string> > tokens; + bool domatch(const std::string &name) const; + + public: + ObjectMatch(); + ObjectMatch(const std::string &expression); + void setExpression(const std::string &expression); + void setExpression(const std::vector<std::string> &expression); + bool match(const std::string &name) const + { + return tokens.empty() ? false : domatch(name); + } +}; + +#endif // __BASE_MATCH_HH__ + diff --git a/base/mysql.cc b/base/mysql.cc index 8481e74e2..15e12fdeb 100644 --- a/base/mysql.cc +++ b/base/mysql.cc @@ -29,6 +29,7 @@ #include <iostream> #include "base/mysql.hh" +#include "base/trace.hh" using namespace std; @@ -94,4 +95,16 @@ Connection::close() mysql_close(&mysql); } +bool +Connection::query(const string &sql) +{ + DPRINTF(SQL, "Sending SQL query to server:\n%s", sql); + error.clear(); + if (mysql_real_query(&mysql, sql.c_str(), sql.size())) + error.set(mysql_error(&mysql)); + + return error; +} + + /* namespace MySQL */ } diff --git a/base/mysql.hh b/base/mysql.hh index 89bec73d0..58a1bf7c2 100644 --- a/base/mysql.hh +++ b/base/mysql.hh @@ -177,15 +177,7 @@ class Connection operator MYSQL *() { return &mysql; } public: - bool - query(const std::string &sql) - { - error.clear(); - if (mysql_real_query(&mysql, sql.c_str(), sql.size())) - error.set(mysql_error(&mysql)); - - return error; - } + bool query(const std::string &sql); bool query(const std::stringstream &sql) diff --git a/base/statistics.cc b/base/statistics.cc index 78012bff7..6e3dae1ef 100644 --- a/base/statistics.cc +++ b/base/statistics.cc @@ -273,7 +273,8 @@ check() for (i = Database::stats().begin(); i != end; ++i) { StatData *data = *i; assert(data); - data->check(); + if (!data->check() || !data->baseCheck()) + panic("stat check failed for %s\n", data->name); } int j = 0; diff --git a/base/stats/events.cc b/base/stats/events.cc index ed25e2423..e5efceabe 100644 --- a/base/stats/events.cc +++ b/base/stats/events.cc @@ -35,50 +35,21 @@ #include "base/stats/events.hh" #include "base/stats/mysql.hh" #include "base/stats/mysql_run.hh" +#include "base/str.hh" #endif -#include "base/str.hh" +#include "base/match.hh" #include "sim/host.hh" +#include "sim/sim_object.hh" #include "sim/universe.hh" using namespace std; namespace Stats { -Tick EventStart = ULL(0xffffffffffffffff); - -vector<string> event_ignore; -vector<vector<string> > ignore_tokens; -vector<int> ignore_size; -int event_ignore_size; +Tick EventStart = ULL(0x7fffffffffffffff); -bool -ignoreEvent(const string &name) -{ - vector<string> name_tokens; - tokenize(name_tokens, name, '.'); - int ntsize = name_tokens.size(); - - for (int i = 0; i < event_ignore_size; ++i) { - bool match = true; - int jstop = ignore_size[i]; - for (int j = 0; j < jstop; ++j) { - if (j >= ntsize) - break; - - const string &ignore = ignore_tokens[i][j]; - if (ignore != "*" && ignore != name_tokens[j]) { - match = false; - break; - } - } - - if (match == true) - return true; - } - - return false; -} +ObjectMatch event_ignore; #ifdef USE_MYSQL class InsertEvent diff --git a/base/stats/mysql.cc b/base/stats/mysql.cc index 4c2a60127..523494743 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)); - return mysql.insert_id(); + exit: + mysql.query("UNLOCK TABLES"); + if (mysql.error) + panic("could not unlock tables\n%s\n", mysql.error); + + 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,11 +478,15 @@ MySql::configure() } } + mysql.query("UNLOCK TABLES"); + if (mysql.error) + panic("could not unlock tables\n%s\n", mysql.error); + configured = true; } -void +bool MySql::configure(const StatData &data, string type) { stat.init(); @@ -447,19 +500,25 @@ MySql::configure(const StatData &data, string type) stat.total = data.flags & total; stat.pdf = data.flags & pdf; stat.cdf = data.flags & cdf; + + return stat.print; } void MySql::configure(const ScalarData &data) { - configure(data, "SCALAR"); + if (!configure(data, "SCALAR")) + return; + insert(data.id, stat.setup()); } void MySql::configure(const VectorData &data) { - configure(data, "VECTOR"); + if (!configure(data, "VECTOR")) + return; + uint16_t statid = stat.setup(); if (!data.subnames.empty()) { @@ -482,7 +541,9 @@ MySql::configure(const VectorData &data) void MySql::configure(const DistData &data) { - configure(data, "DIST"); + if (!configure(data, "DIST")) + return; + if (!data.data.fancy) { stat.size = data.data.size; stat.min = data.data.min; @@ -495,7 +556,8 @@ MySql::configure(const DistData &data) void MySql::configure(const VectorDistData &data) { - configure(data, "VECTORDIST"); + if (!configure(data, "VECTORDIST")) + return; if (!data.data[0].fancy) { stat.size = data.data[0].size; @@ -525,13 +587,15 @@ MySql::configure(const VectorDistData &data) void MySql::configure(const Vector2dData &data) { - configure(data, "VECTOR2D"); + if (!configure(data, "VECTOR2D")) + return; + uint16_t statid = stat.setup(); 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 +608,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,17 +626,25 @@ MySql::configure(const FormulaData &data) { configure(data, "FORMULA"); insert(data.id, stat.setup()); + InsertFormula(find(data.id), data.str()); } void -MySql::output(const string &bin) +MySql::output(MainBin *bin) { - // set up new bin in database if there is a bin name - newdata.bin = bin.empty() ? 0 : SetupBin(bin); + if (bin) { + bin->activate(); + newdata.bin = SetupBin(bin->name()); + } else { + newdata.bin = 0; + } Database::stat_list_t::const_iterator i, end = Database::stats().end(); - for (i = Database::stats().begin(); i != end; ++i) - (*i)->visit(*this); + for (i = Database::stats().begin(); i != end; ++i) { + StatData *stat = *i; + if (bin && stat->binned() || !bin && !stat->binned()) + stat->visit(*this); + } } bool @@ -591,17 +663,13 @@ MySql::output() configure(); // store sample # - newdata.sample = curTick; + newdata.tick = curTick; - if (bins().empty()) { - output(string("")); - } else { + output(NULL); + if (!bins().empty()) { bin_list_t::iterator i, end = bins().end(); - for (i = bins().begin(); i != end; ++i) { - MainBin *bin = *i; - bin->activate(); - output(bin->name()); - } + for (i = bins().begin(); i != end; ++i) + output(*i); } newdata.flush(); @@ -610,6 +678,9 @@ MySql::output() void MySql::output(const ScalarData &data) { + if (!(data.flags & print)) + return; + newdata.stat = find(data.id); newdata.x = 0; newdata.y = 0; @@ -621,6 +692,9 @@ MySql::output(const ScalarData &data) void MySql::output(const VectorData &data) { + if (!(data.flags & print)) + return; + newdata.stat = find(data.id); newdata.y = 0; @@ -686,6 +760,9 @@ MySql::output(const DistDataData &data) void MySql::output(const DistData &data) { + if (!(data.flags & print)) + return; + newdata.stat = find(data.id); newdata.y = 0; output(data.data); @@ -694,6 +771,9 @@ MySql::output(const DistData &data) void MySql::output(const VectorDistData &data) { + if (!(data.flags & print)) + return; + newdata.stat = find(data.id); int size = data.data.size(); @@ -706,6 +786,9 @@ MySql::output(const VectorDistData &data) void MySql::output(const Vector2dData &data) { + if (!(data.flags & print)) + return; + newdata.stat = find(data.id); int index = 0; @@ -722,7 +805,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..5b6d8a138 100644 --- a/base/stats/mysql.hh +++ b/base/stats/mysql.hh @@ -37,6 +37,7 @@ namespace MySQL { class Connection; } namespace Stats { +class MainBin; class DistDataData; class MySqlRun; bool MySqlConnected(); @@ -76,7 +77,7 @@ class InsertData MySqlRun *run; public: - uint64_t sample; + uint64_t tick; double data; uint16_t stat; uint16_t bin; @@ -130,7 +131,7 @@ class MySql : public Output protected: // Output helper - void output(const std::string &bin); + void output(MainBin *bin); void output(const DistDataData &data); void output(const ScalarData &data); void output(const VectorData &data); @@ -140,7 +141,7 @@ class MySql : public Output void output(const FormulaData &data); void configure(); - void configure(const StatData &data, std::string type); + bool configure(const StatData &data, std::string type); void configure(const ScalarData &data); void configure(const VectorData &data); void configure(const DistData &data); diff --git a/base/stats/statdb.cc b/base/stats/statdb.cc index eed3d6296..66871b9f7 100644 --- a/base/stats/statdb.cc +++ b/base/stats/statdb.cc @@ -51,6 +51,10 @@ find(void *stat) void regBin(MainBin *bin, const std::string &_name) { + bin_list_t::iterator i, end = bins().end(); + for (i = bins().begin(); i != end; ++i) + if ((*i)->name() == _name) + panic("re-registering bin %s", _name); bins().push_back(bin); DPRINTF(Stats, "registering %s\n", _name); } diff --git a/base/trace.cc b/base/trace.cc index aa82ee403..bc6c9aa7a 100644 --- a/base/trace.cc +++ b/base/trace.cc @@ -51,39 +51,7 @@ FlagVec flags(NumFlags, false); // ostream *dprintf_stream = &cerr; -int dprintf_ignore_size; -vector<string> dprintf_ignore; -vector<vector<string> > ignore_tokens; -vector<int> ignore_size; - -bool -dprintf_ignore_name(const string &name) -{ - vector<string> name_tokens; - tokenize(name_tokens, name, '.'); - int ntsize = name_tokens.size(); - - for (int i = 0; i < dprintf_ignore_size; ++i) { - bool match = true; - int jstop = ignore_size[i]; - for (int j = 0; j < jstop; ++j) { - if (j >= ntsize) - break; - - const string &ignore = ignore_tokens[i][j]; - if (ignore != "*" && ignore != name_tokens[j]) { - match = false; - break; - } - } - - if (match == true) - return true; - } - - return false; -} - +ObjectMatch ignore; Log theLog; @@ -184,7 +152,6 @@ PrintfRecord::~PrintfRecord() delete &args; } - void PrintfRecord::dump(ostream &os) { @@ -206,29 +173,26 @@ PrintfRecord::dump(ostream &os) os.flush(); } - - -RawDataRecord::RawDataRecord(Tick _cycle, const void *_data, int _len) - : Record(_cycle), len(_len) +DataRecord::DataRecord(Tick _cycle, const string &_name, + const void *_data, int _len) + : Record(_cycle), name(_name), len(_len) { data = new uint8_t[len]; memcpy(data, _data, len); } - -RawDataRecord::~RawDataRecord() +DataRecord::~DataRecord() { delete [] data; } - void -RawDataRecord::dump(ostream &os) +DataRecord::dump(ostream &os) { int c, i, j; for (i = 0; i < len; i += 16) { - ccprintf(os, "%08x ", i); + ccprintf(os, "%d: %s: %08x ", cycle, name, i); c = len - i; if (c > 16) c = 16; diff --git a/base/trace.hh b/base/trace.hh index 60ea015ea..1aadb36cf 100644 --- a/base/trace.hh +++ b/base/trace.hh @@ -32,6 +32,7 @@ #include <vector> #include "base/cprintf.hh" +#include "base/match.hh" #include "sim/host.hh" #include "sim/universe.hh" @@ -69,7 +70,7 @@ namespace Trace { class Record { protected: - Tick cycle; + Tick cycle; Record(Tick _cycle) : cycle(_cycle) @@ -101,15 +102,17 @@ namespace Trace { virtual void dump(std::ostream &); }; - class RawDataRecord : public Record + class DataRecord : public Record { private: + const std::string &name; uint8_t *data; int len; public: - RawDataRecord(Tick cycle, const void *_data, int _len); - virtual ~RawDataRecord(); + DataRecord(Tick cycle, const std::string &name, + const void *_data, int _len); + virtual ~DataRecord(); virtual void dump(std::ostream &); }; @@ -135,23 +138,20 @@ namespace Trace { extern Log theLog; - extern int dprintf_ignore_size; - - bool - dprintf_ignore_name(const std::string &name); + extern ObjectMatch ignore; inline void dprintf(const char *format, cp::ArgList &args, Tick cycle, const std::string &name) { - if (!dprintf_ignore_size || name.empty() || !dprintf_ignore_name(name)) + if (name.empty() || !ignore.match(name)) theLog.append(new Trace::PrintfRecord(format, args, cycle, name)); } inline void - rawDump(const void *data, int len) + dataDump(Tick cycle, const std::string &name, const void *data, int len) { - theLog.append(new Trace::RawDataRecord(curTick, data, len)); + theLog.append(new Trace::DataRecord(cycle, name, data, len)); } extern const std::string DefaultName; @@ -180,7 +180,7 @@ std::ostream &DebugOut(); #define DDUMP(x, data, count) \ do { \ if (Trace::IsOn(Trace::x)) \ - Trace::rawDump(data, count); \ + Trace::dataDump(curTick, name(), data, count); \ } while (0) #define __dprintf(cycle, name, format, args...) \ diff --git a/base/traceflags.py b/base/traceflags.py index 8e1594b24..4be61d7ee 100644 --- a/base/traceflags.py +++ b/base/traceflags.py @@ -120,7 +120,9 @@ baseFlags = [ 'IdeCtrl', 'IdeDisk', 'Tsunami', - 'Uart' + 'Uart', + 'Split', + 'SQL' ] # 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/simple_cpu/simple_cpu.cc b/cpu/simple_cpu/simple_cpu.cc index d70f0ccfa..6c22d7c81 100644 --- a/cpu/simple_cpu/simple_cpu.cc +++ b/cpu/simple_cpu/simple_cpu.cc @@ -75,14 +75,17 @@ using namespace std; SimpleCPU::TickEvent::TickEvent(SimpleCPU *c) - : Event(&mainEventQueue, CPU_Tick_Pri), cpu(c) + : Event(&mainEventQueue, CPU_Tick_Pri), cpu(c), multiplier(1) { } void SimpleCPU::TickEvent::process() { - cpu->tick(); + int count = multiplier; + do { + cpu->tick(); + } while (--count > 0 && cpu->status() == Running); } const char * @@ -269,6 +272,11 @@ SimpleCPU::regStats() .desc("Number of memory references") ; + notIdleFraction + .name(name() + ".not_idle_fraction") + .desc("Percentage of non-idle cycles") + ; + idleFraction .name(name() + ".idle_fraction") .desc("Percentage of idle cycles") @@ -799,6 +807,7 @@ BEGIN_DECLARE_SIM_OBJECT_PARAMS(SimpleCPU) SimObjectParam<BaseMem *> dcache; Param<bool> defer_registration; + Param<int> multiplier; END_DECLARE_SIM_OBJECT_PARAMS(SimpleCPU) @@ -830,7 +839,9 @@ BEGIN_INIT_SIM_OBJECT_PARAMS(SimpleCPU) INIT_PARAM_DFLT(icache, "L1 instruction cache object", NULL), INIT_PARAM_DFLT(dcache, "L1 data cache object", NULL), INIT_PARAM_DFLT(defer_registration, "defer registration with system " - "(for sampling)", false) + "(for sampling)", false), + + INIT_PARAM_DFLT(multiplier, "clock multiplier", 1) END_INIT_SIM_OBJECT_PARAMS(SimpleCPU) @@ -861,6 +872,8 @@ CREATE_SIM_OBJECT(SimpleCPU) #endif // FULL_SYSTEM + cpu->setTickMultiplier(multiplier); + return cpu; } diff --git a/cpu/simple_cpu/simple_cpu.hh b/cpu/simple_cpu/simple_cpu.hh index 3692ab511..6ab231e7e 100644 --- a/cpu/simple_cpu/simple_cpu.hh +++ b/cpu/simple_cpu/simple_cpu.hh @@ -68,12 +68,11 @@ class SimpleCPU : public BaseCPU void tick(); private: - class TickEvent : public Event + struct TickEvent : public Event { - private: SimpleCPU *cpu; + int multiplier; - public: TickEvent(SimpleCPU *c); void process(); const char *description(); @@ -97,6 +96,12 @@ class SimpleCPU : public BaseCPU tickEvent.squash(); } + public: + void setTickMultiplier(int multiplier) + { + tickEvent.multiplier = multiplier; + } + private: Trace::InstRecord *traceData; template<typename T> diff --git a/cpu/trace/reader/ibm_reader.cc b/cpu/trace/reader/ibm_reader.cc index 439931dba..7ca32fe21 100644 --- a/cpu/trace/reader/ibm_reader.cc +++ b/cpu/trace/reader/ibm_reader.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003-2004 The Regents of The University of Michigan + * Copyright (c) 2004 The Regents of The University of Michigan * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/cpu/trace/reader/ibm_reader.hh b/cpu/trace/reader/ibm_reader.hh index 0f14da24d..f7e3ae149 100644 --- a/cpu/trace/reader/ibm_reader.hh +++ b/cpu/trace/reader/ibm_reader.hh @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003-2004 The Regents of The University of Michigan + * Copyright (c) 2004 The Regents of The University of Michigan * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/cpu/trace/reader/itx_reader.cc b/cpu/trace/reader/itx_reader.cc index 54bbbc4ea..593d383ec 100644 --- a/cpu/trace/reader/itx_reader.cc +++ b/cpu/trace/reader/itx_reader.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003-2004 The Regents of The University of Michigan + * Copyright (c) 2004 The Regents of The University of Michigan * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/cpu/trace/reader/itx_reader.hh b/cpu/trace/reader/itx_reader.hh index ff74062ea..0e08d5db5 100644 --- a/cpu/trace/reader/itx_reader.hh +++ b/cpu/trace/reader/itx_reader.hh @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003-2004 The Regents of The University of Michigan + * Copyright (c) 2004 The Regents of The University of Michigan * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/cpu/trace/reader/m5_reader.cc b/cpu/trace/reader/m5_reader.cc index d081f0bc0..c5b807824 100644 --- a/cpu/trace/reader/m5_reader.cc +++ b/cpu/trace/reader/m5_reader.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003-2004 The Regents of The University of Michigan + * Copyright (c) 2004 The Regents of The University of Michigan * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/cpu/trace/reader/m5_reader.hh b/cpu/trace/reader/m5_reader.hh index d78787461..296c99ccf 100644 --- a/cpu/trace/reader/m5_reader.hh +++ b/cpu/trace/reader/m5_reader.hh @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003-2004 The Regents of The University of Michigan + * Copyright (c) 2004 The Regents of The University of Michigan * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/cpu/trace/reader/mem_trace_reader.cc b/cpu/trace/reader/mem_trace_reader.cc index c6fc53f51..441e72b80 100644 --- a/cpu/trace/reader/mem_trace_reader.cc +++ b/cpu/trace/reader/mem_trace_reader.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003-2004 The Regents of The University of Michigan + * Copyright (c) 2004 The Regents of The University of Michigan * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/cpu/trace/reader/mem_trace_reader.hh b/cpu/trace/reader/mem_trace_reader.hh index 5da99a498..6b6f804af 100644 --- a/cpu/trace/reader/mem_trace_reader.hh +++ b/cpu/trace/reader/mem_trace_reader.hh @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003-2004 The Regents of The University of Michigan + * Copyright (c) 2004 The Regents of The University of Michigan * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/cpu/trace/trace_cpu.cc b/cpu/trace/trace_cpu.cc index 6122fc786..94f311d4b 100644 --- a/cpu/trace/trace_cpu.cc +++ b/cpu/trace/trace_cpu.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003 The Regents of The University of Michigan + * Copyright (c) 2004 The Regents of The University of Michigan * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/cpu/trace/trace_cpu.hh b/cpu/trace/trace_cpu.hh index 13a204f4e..6f3ef50a6 100644 --- a/cpu/trace/trace_cpu.hh +++ b/cpu/trace/trace_cpu.hh @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003 The Regents of The University of Michigan + * Copyright (c) 2004 The Regents of The University of Michigan * All rights reserved. * * Redistribution and use in source and binary forms, with or without 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/etherdump.cc b/dev/etherdump.cc index 54e573be4..27817d456 100644 --- a/dev/etherdump.cc +++ b/dev/etherdump.cc @@ -32,6 +32,7 @@ #include <sys/time.h> +#include <algorithm> #include <string> #include "base/misc.hh" @@ -41,8 +42,8 @@ using std::string; -EtherDump::EtherDump(const string &name, const string &file) - : SimObject(name) +EtherDump::EtherDump(const string &name, const string &file, int max) + : SimObject(name), maxlen(max) { if (!file.empty()) stream.open(file.c_str()); @@ -113,22 +114,24 @@ EtherDump::dumpPacket(PacketPtr &packet) pcap_pkthdr pkthdr; pkthdr.seconds = curtime + (curTick / s_freq); pkthdr.microseconds = (curTick / us_freq) % ULL(1000000); - pkthdr.caplen = packet->length; + pkthdr.caplen = std::min(packet->length, maxlen); pkthdr.len = packet->length; stream.write(reinterpret_cast<char *>(&pkthdr), sizeof(pkthdr)); - stream.write(reinterpret_cast<char *>(packet->data), packet->length); + stream.write(reinterpret_cast<char *>(packet->data), pkthdr.caplen); stream.flush(); } BEGIN_DECLARE_SIM_OBJECT_PARAMS(EtherDump) Param<string> file; + Param<int> maxlen; END_DECLARE_SIM_OBJECT_PARAMS(EtherDump) BEGIN_INIT_SIM_OBJECT_PARAMS(EtherDump) - INIT_PARAM(file, "file to dump packets to") + INIT_PARAM(file, "file to dump packets to"), + INIT_PARAM_DFLT(maxlen, "max portion of packet data to dump", 96) END_INIT_SIM_OBJECT_PARAMS(EtherDump) @@ -148,7 +151,7 @@ CREATE_SIM_OBJECT(EtherDump) } } - return new EtherDump(getInstanceName(), filename); + return new EtherDump(getInstanceName(), filename, maxlen); } REGISTER_SIM_OBJECT("EtherDump", EtherDump) diff --git a/dev/etherdump.hh b/dev/etherdump.hh index ef4399e1a..62364359e 100644 --- a/dev/etherdump.hh +++ b/dev/etherdump.hh @@ -44,6 +44,7 @@ class EtherDump : public SimObject { private: std::ofstream stream; + const int maxlen; void dumpPacket(PacketPtr &packet); void init(); @@ -52,7 +53,7 @@ class EtherDump : public SimObject Tick us_freq; public: - EtherDump(const std::string &name, const std::string &file); + EtherDump(const std::string &name, const std::string &file, int max); inline void dump(PacketPtr &pkt) { if (stream.is_open()) dumpPacket(pkt); } }; diff --git a/dev/etherlink.hh b/dev/etherlink.hh index 4f227fac5..204348c6d 100644 --- a/dev/etherlink.hh +++ b/dev/etherlink.hh @@ -105,7 +105,7 @@ class EtherLink : public SimObject public: Interface(const std::string &name, Link *txlink, Link *rxlink); bool recvPacket(PacketPtr &packet) { return txlink->transmit(packet); } - void sendDone() { } + void sendDone() { peer->sendDone(); } }; Link *link1; 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 f88fc507f..22c0ba35d 100644 --- a/dev/ns_gige.cc +++ b/dev/ns_gige.cc @@ -38,8 +38,10 @@ #include "cpu/exec_context.hh" #include "cpu/intr_control.hh" #include "dev/dma.hh" -#include "dev/ns_gige.hh" #include "dev/etherlink.hh" +#include "dev/ns_gige.hh" +#include "dev/pciconfigall.hh" +#include "dev/tsunami_cchip.hh" #include "mem/bus/bus.hh" #include "mem/bus/dma_interface.hh" #include "mem/bus/pio_interface.hh" @@ -47,11 +49,10 @@ #include "mem/functional_mem/memory_control.hh" #include "mem/functional_mem/physical_memory.hh" #include "sim/builder.hh" +#include "sim/debug.hh" #include "sim/host.hh" #include "sim/sim_stats.hh" #include "targetarch/vtophys.hh" -#include "dev/pciconfigall.hh" -#include "dev/tsunami_cchip.hh" const char *NsRxStateStrings[] = { @@ -86,8 +87,9 @@ const char *NsDmaState[] = using namespace std; -//helper function declarations -//These functions reverse Endianness so we can evaluate network data correctly +// helper function declarations +// These functions reverse Endianness so we can evaluate network data +// correctly uint16_t reverseEnd16(uint16_t); uint32_t reverseEnd32(uint32_t); @@ -96,19 +98,21 @@ 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), + txXferLen(0), rxXferLen(0), txState(txIdle), txEnable(false), + CTDD(false), txFifoAvail(tx_fifo_size), txFragPtr(0), txDescCnt(0), txDmaState(dmaIdle), rxState(rxIdle), - CRDD(false), rxPktBytes(0), rxFifoCnt(0), rxHalt(false), + rxEnable(false), CRDD(false), rxPktBytes(0), rxFifoCnt(0), rxFragPtr(0), rxDescCnt(0), rxDmaState(dmaIdle), extstsEnable(false), rxDmaReadEvent(this), rxDmaWriteEvent(this), txDmaReadEvent(this), txDmaWriteEvent(this), @@ -118,7 +122,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 +130,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 +142,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); - } @@ -299,9 +306,9 @@ NSGigE::WriteConfig(int offset, int size, uint32_t data) // Need to catch writes to BARs to update the PIO interface switch (offset) { - //seems to work fine without all these PCI settings, but i put in the IO - //to double check, an assertion will fail if we need to properly - // implement it + // seems to work fine without all these PCI settings, but i + // put in the IO to double check, an assertion will fail if we + // need to properly implement it case PCI_COMMAND: if (config.data[offset] & PCI_CMD_IOSE) ioEnable = true; @@ -327,22 +334,20 @@ NSGigE::WriteConfig(int offset, int size, uint32_t data) case PCI0_BASE_ADDR0: if (BARAddrs[0] != 0) { - if (pioInterface) - pioInterface->addAddrRange(BARAddrs[0], BARAddrs[0] + BARSize[0] - 1); + pioInterface->addAddrRange(BARAddrs[0], + BARAddrs[0] + BARSize[0] - 1); BARAddrs[0] &= PA_UNCACHED_MASK; - } break; case PCI0_BASE_ADDR1: if (BARAddrs[1] != 0) { - if (pioInterface) - pioInterface->addAddrRange(BARAddrs[1], BARAddrs[1] + BARSize[1] - 1); + pioInterface->addAddrRange(BARAddrs[1], + BARAddrs[1] + BARSize[1] - 1); BARAddrs[1] &= PA_UNCACHED_MASK; - } break; } @@ -363,8 +368,8 @@ NSGigE::read(MemReqPtr &req, uint8_t *data) daddr, req->paddr, req->vaddr, req->size); - //there are some reserved registers, you can see ns_gige_reg.h and - //the spec sheet for details + // there are some reserved registers, you can see ns_gige_reg.h and + // the spec sheet for details if (daddr > LAST && daddr <= RESERVED) { panic("Accessing reserved register"); } else if (daddr > RESERVED && daddr <= 0x3FC) { @@ -461,10 +466,11 @@ NSGigE::read(MemReqPtr &req, uint8_t *data) reg = regs.pcr; break; - //see the spec sheet for how RFCR and RFDR work - //basically, you write to RFCR to tell the machine what you want to do next - //then you act upon RFDR, and the device will be prepared b/c - //of what you wrote to RFCR + // see the spec sheet for how RFCR and RFDR work + // basically, you write to RFCR to tell the machine + // what you want to do next, then you act upon RFDR, + // and the device will be prepared b/c of what you + // wrote to RFCR case RFCR: reg = regs.rfcr; break; @@ -485,8 +491,9 @@ NSGigE::read(MemReqPtr &req, uint8_t *data) reg += rom.perfectMatch[4]; break; default: - panic("reading from RFDR for something for other than PMATCH!\n"); - //didn't implement other RFDR functionality b/c driver didn't use + panic("reading RFDR for something other than PMATCH!\n"); + // didn't implement other RFDR functionality b/c + // driver didn't use it } break; @@ -540,7 +547,7 @@ NSGigE::read(MemReqPtr &req, uint8_t *data) break; default: - panic("reading unimplemented register: addr = %#x", daddr); + panic("reading unimplemented register: addr=%#x", daddr); } DPRINTF(EthernetPIO, "read from %#x: data=%d data=%#x\n", @@ -580,24 +587,23 @@ NSGigE::write(MemReqPtr &req, const uint8_t *data) switch (daddr) { case CR: regs.command = reg; - if ((reg & (CR_TXE | CR_TXD)) == (CR_TXE | CR_TXD)) { - txHalt = true; + if (reg & CR_TXD) { + txEnable = false; } else if (reg & CR_TXE) { - //the kernel is enabling the transmit machine + txEnable = true; + + // the kernel is enabling the transmit machine if (txState == txIdle) txKick(); - } else if (reg & CR_TXD) { - txHalt = true; } - if ((reg & (CR_RXE | CR_RXD)) == (CR_RXE | CR_RXD)) { - rxHalt = true; + if (reg & CR_RXD) { + rxEnable = false; } else if (reg & CR_RXE) { - if (rxState == rxIdle) { + rxEnable = true; + + if (rxState == rxIdle) rxKick(); - } - } else if (reg & CR_RXD) { - rxHalt = true; } if (reg & CR_TXR) @@ -618,26 +624,34 @@ NSGigE::write(MemReqPtr &req, const uint8_t *data) break; case CFG: - if (reg & CFG_LNKSTS || reg & CFG_SPDSTS || reg & CFG_DUPSTS - || reg & CFG_RESERVED || reg & CFG_T64ADDR - || reg & CFG_PCI64_DET) + if (reg & CFG_LNKSTS || + reg & CFG_SPDSTS || + reg & CFG_DUPSTS || + reg & CFG_RESERVED || + reg & CFG_T64ADDR || + reg & CFG_PCI64_DET) panic("writing to read-only or reserved CFG bits!\n"); - regs.config |= reg & ~(CFG_LNKSTS | CFG_SPDSTS | CFG_DUPSTS | CFG_RESERVED | - CFG_T64ADDR | CFG_PCI64_DET); + regs.config |= reg & ~(CFG_LNKSTS | CFG_SPDSTS | CFG_DUPSTS | + CFG_RESERVED | CFG_T64ADDR | CFG_PCI64_DET); -// all these #if 0's are because i don't THINK the kernel needs to have these implemented -// if there is a problem relating to one of these, you may need to add functionality in +// all these #if 0's are because i don't THINK the kernel needs to +// have these implemented. if there is a problem relating to one of +// these, you may need to add functionality in. #if 0 - if (reg & CFG_TBI_EN) ; - if (reg & CFG_MODE_1000) ; + if (reg & CFG_TBI_EN) ; + if (reg & CFG_MODE_1000) ; #endif if (reg & CFG_AUTO_1000) panic("CFG_AUTO_1000 not implemented!\n"); #if 0 - if (reg & CFG_PINT_DUPSTS || reg & CFG_PINT_LNKSTS || reg & CFG_PINT_SPDSTS) ; + if (reg & CFG_PINT_DUPSTS || + reg & CFG_PINT_LNKSTS || + reg & CFG_PINT_SPDSTS) + ; + if (reg & CFG_TMRTEST) ; if (reg & CFG_MRM_DIS) ; if (reg & CFG_MWI_DIS) ; @@ -673,11 +687,12 @@ NSGigE::write(MemReqPtr &req, const uint8_t *data) case MEAR: regs.mear = reg; - /* since phy is completely faked, MEAR_MD* don't matter - and since the driver never uses MEAR_EE*, they don't matter */ + // since phy is completely faked, MEAR_MD* don't matter + // and since the driver never uses MEAR_EE*, they don't + // matter #if 0 if (reg & MEAR_EEDI) ; - if (reg & MEAR_EEDO) ; //this one is read only + if (reg & MEAR_EEDO) ; // this one is read only if (reg & MEAR_EECLK) ; if (reg & MEAR_EESEL) ; if (reg & MEAR_MDIO) ; @@ -688,8 +703,8 @@ NSGigE::write(MemReqPtr &req, const uint8_t *data) case PTSCR: regs.ptscr = reg & ~(PTSCR_RBIST_RDONLY); - /* these control BISTs for various parts of chip - we don't care or do - just fake that the BIST is done */ + // these control BISTs for various parts of chip - we + // don't care or do just fake that the BIST is done if (reg & PTSCR_RBIST_EN) regs.ptscr |= PTSCR_RBIST_DONE; if (reg & PTSCR_EEBIST_EN) @@ -732,20 +747,26 @@ NSGigE::write(MemReqPtr &req, const uint8_t *data) if (reg & TXCFG_HBI) ; if (reg & TXCFG_MLB) ; if (reg & TXCFG_ATP) ; - if (reg & TXCFG_ECRETRY) ; /* this could easily be implemented, but - considering the network is just a fake - pipe, wouldn't make sense to do this */ + if (reg & TXCFG_ECRETRY) { + /* + * this could easily be implemented, but considering + * the network is just a fake pipe, wouldn't make + * sense to do this + */ + } if (reg & TXCFG_BRST_DIS) ; #endif - +#if 0 /* we handle our own DMA, ignore the kernel's exhortations */ - //if (reg & TXCFG_MXDMA) ; + if (reg & TXCFG_MXDMA) ; +#endif - //also, we currently don't care about fill/drain thresholds - //though this may change in the future with more realistic - //networks or a driver which changes it according to feedback + // also, we currently don't care about fill/drain + // thresholds though this may change in the future with + // more realistic networks or a driver which changes it + // according to feedback break; @@ -756,6 +777,7 @@ NSGigE::write(MemReqPtr &req, const uint8_t *data) case RXDP: regs.rxdp = reg; + CRDD = false; break; case RXDP_HI: @@ -771,12 +793,10 @@ NSGigE::write(MemReqPtr &req, const uint8_t *data) if (reg & RXCFG_RX_RD) ; if (reg & RXCFG_ALP) ; if (reg & RXCFG_AIRL) ; -#endif /* we handle our own DMA, ignore what kernel says about it */ - //if (reg & RXCFG_MXDMA) ; + if (reg & RXCFG_MXDMA) ; -#if 0 //also, we currently don't care about fill/drain thresholds //though this may change in the future with more realistic //networks or a driver which changes it according to feedback @@ -809,8 +829,10 @@ NSGigE::write(MemReqPtr &req, const uint8_t *data) acceptPerfect = (reg & RFCR_APM) ? true : false; acceptArp = (reg & RFCR_AARP) ? true : false; - if (reg & RFCR_APAT) ; -// panic("RFCR_APAT not implemented!\n"); +#if 0 + if (reg & RFCR_APAT) + panic("RFCR_APAT not implemented!\n"); +#endif if (reg & RFCR_MHEN || reg & RFCR_UHEN) panic("hash filtering not implemented!\n"); @@ -891,11 +913,11 @@ NSGigE::write(MemReqPtr &req, const uint8_t *data) break; default: - panic("thought i covered all the register, what is this? addr=%#x", - daddr); + panic("invalid register access daddr=%#x", daddr); } - } else + } else { panic("Invalid Request Size"); + } return No_Fault; } @@ -968,7 +990,8 @@ NSGigE::devIntrPost(uint32_t interrupts) cpuIntrPost(when); } - DPRINTF(EthernetIntr, "**interrupt written to ISR: intr=%#x isr=%#x imr=%#x\n", + DPRINTF(EthernetIntr, + "interrupt written to ISR: intr=%#x isr=%#x imr=%#x\n", interrupts, regs.isr, regs.imr); } @@ -1027,17 +1050,19 @@ NSGigE::devIntrClear(uint32_t interrupts) if (interrupts & ISR_RXOK) regs.isr &= ~ISR_RXOK; + DPRINTF(EthernetIntr, + "interrupt cleared from ISR: intr=%x isr=%x imr=%x\n", + interrupts, regs.isr, regs.imr); + if (!(regs.isr & regs.imr)) cpuIntrClear(); - - DPRINTF(EthernetIntr, "**interrupt cleared from ISR: intr=%x isr=%x imr=%x\n", - interrupts, regs.isr, regs.imr); } void NSGigE::devIntrChangeMask() { - DPRINTF(EthernetIntr, "interrupt mask changed\n"); + DPRINTF(EthernetIntr, "interrupt mask changed: isr=%x imr=%x masked=%x\n", + regs.isr, regs.imr, regs.isr & regs.imr); if (regs.isr & regs.imr) cpuIntrPost(curTick); @@ -1048,11 +1073,20 @@ NSGigE::devIntrChangeMask() void NSGigE::cpuIntrPost(Tick when) { - //If the interrupt you want to post is later than an - //interrupt already scheduled, just let it post in the coming one and - //don't schedule another. - //HOWEVER, must be sure that the scheduled intrTick is in the future - //(this was formerly the source of a bug) + // If the interrupt you want to post is later than an interrupt + // already scheduled, just let it post in the coming one and don't + // schedule another. + // HOWEVER, must be sure that the scheduled intrTick is in the + // future (this was formerly the source of a bug) + /** + * @todo this warning should be removed and the intrTick code should + * be fixed. + */ + if (intrTick < curTick && intrTick != 0) { + warn("intrTick < curTick !!! intrTick=%d curTick=%d\n", + intrTick, curTick); + intrTick = 0; + } assert((intrTick >= curTick) || (intrTick == 0)); if (when > intrTick && intrTick != 0) return; @@ -1067,7 +1101,8 @@ NSGigE::cpuIntrPost(Tick when) if (when < curTick) { cpuInterrupt(); } else { - DPRINTF(EthernetIntr, "going to schedule an interrupt for intrTick=%d\n", + DPRINTF(EthernetIntr, + "going to schedule an interrupt for intrTick=%d\n", intrTick); intrEvent = new IntrEvent(this, true); intrEvent->schedule(intrTick); @@ -1086,7 +1121,8 @@ NSGigE::cpuInterrupt() } // Don't send an interrupt if it's supposed to be delayed if (intrTick > curTick) { - DPRINTF(EthernetIntr, "an interrupt is scheduled for %d, wait til then\n", + DPRINTF(EthernetIntr, + "an interrupt is scheduled for %d, wait til then\n", intrTick); return; } @@ -1107,13 +1143,14 @@ NSGigE::cpuInterrupt() void NSGigE::cpuIntrClear() { - if (cpuPendingIntr) { - cpuPendingIntr = false; - /** @todo rework the intctrl to be tsunami ok */ - //intctrl->clear(TheISA::INTLEVEL_IRQ1, TheISA::INTINDEX_ETHERNET); - DPRINTF(EthernetIntr, "clearing all interrupts from cchip\n"); - tsunami->cchip->clearDRIR(configData->config.hdr.pci0.interruptLine); - } + if (!cpuPendingIntr) + return; + + cpuPendingIntr = false; + /** @todo rework the intctrl to be tsunami ok */ + //intctrl->clear(TheISA::INTLEVEL_IRQ1, TheISA::INTINDEX_ETHERNET); + DPRINTF(EthernetIntr, "clearing all interrupts from cchip\n"); + tsunami->cchip->clearDRIR(configData->config.hdr.pci0.interruptLine); } bool @@ -1127,12 +1164,11 @@ NSGigE::txReset() DPRINTF(Ethernet, "transmit reset\n"); CTDD = false; - txFifoAvail = MAX_TX_FIFO_SIZE; - txHalt = false; + txFifoAvail = maxTxFifoSize; + txEnable = false;; txFragPtr = 0; assert(txDescCnt == 0); txFifo.clear(); - regs.command &= ~CR_TXE; txState = txIdle; assert(txDmaState == dmaIdle); } @@ -1145,16 +1181,16 @@ NSGigE::rxReset() CRDD = false; assert(rxPktBytes == 0); rxFifoCnt = 0; - rxHalt = false; + rxEnable = false; rxFragPtr = 0; assert(rxDescCnt == 0); assert(rxDmaState == dmaIdle); rxFifo.clear(); - regs.command &= ~CR_RXE; rxState = rxIdle; } -void NSGigE::regsReset() +void +NSGigE::regsReset() { memset(®s, 0, sizeof(regs)); regs.config = 0x80000000; @@ -1180,7 +1216,7 @@ NSGigE::rxDmaReadCopy() { assert(rxDmaState == dmaReading); - memcpy(rxDmaData, physmem->dma_addr(rxDmaAddr, rxDmaLen), rxDmaLen); + physmem->dma_read((uint8_t *)rxDmaData, rxDmaAddr, rxDmaLen); rxDmaState = dmaIdle; DPRINTF(EthernetDMA, "rx dma read paddr=%#x len=%d\n", @@ -1232,7 +1268,7 @@ NSGigE::rxDmaWriteCopy() { assert(rxDmaState == dmaWriting); - memcpy(physmem->dma_addr(rxDmaAddr, rxDmaLen), rxDmaData, rxDmaLen); + physmem->dma_write(rxDmaAddr, (uint8_t *)rxDmaData, rxDmaLen); rxDmaState = dmaIdle; DPRINTF(EthernetDMA, "rx dma write paddr=%#x len=%d\n", @@ -1282,7 +1318,7 @@ NSGigE::rxDmaWriteDone() void NSGigE::rxKick() { - DPRINTF(EthernetSM, "receive kick state=%s (rxBuf.size=%d)\n", + DPRINTF(EthernetSM, "receive kick rxState=%s (rxBuf.size=%d)\n", NsRxStateStrings[rxState], rxFifo.size()); if (rxKickTick > curTick) { @@ -1306,14 +1342,15 @@ NSGigE::rxKick() } // see state machine from spec for details - // the way this works is, if you finish work on one state and can go directly to - // another, you do that through jumping to the label "next". however, if you have - // intermediate work, like DMA so that you can't go to the next state yet, you go to - // exit and exit the loop. however, when the DMA is done it will trigger an - // event and come back to this loop. + // the way this works is, if you finish work on one state and can + // go directly to another, you do that through jumping to the + // label "next". however, if you have intermediate work, like DMA + // so that you can't go to the next state yet, you go to exit and + // exit the loop. however, when the DMA is done it will trigger + // an event and come back to this loop. switch (rxState) { case rxIdle: - if (!regs.command & CR_RXE) { + if (!rxEnable) { DPRINTF(EthernetSM, "Receive Disabled! Nothing to do.\n"); goto exit; } @@ -1359,12 +1396,17 @@ NSGigE::rxKick() goto exit; DPRINTF(EthernetDesc, - "rxDescCache:\n\tlink=%08x\n\tbufptr=%08x\n\tcmdsts=%08x\n\textsts=%08x\n" - ,rxDescCache.link, rxDescCache.bufptr, rxDescCache.cmdsts, + "rxDescCache: addr=%08x read descriptor\n", + regs.rxdp & 0x3fffffff); + DPRINTF(EthernetDesc, + "rxDescCache: link=%08x bufptr=%08x cmdsts=%08x extsts=%08x\n", + rxDescCache.link, rxDescCache.bufptr, rxDescCache.cmdsts, rxDescCache.extsts); if (rxDescCache.cmdsts & CMDSTS_OWN) { + devIntrPost(ISR_RXIDLE); rxState = rxIdle; + goto exit; } else { rxState = rxFifoBlock; rxFragPtr = rxDescCache.bufptr; @@ -1382,25 +1424,27 @@ NSGigE::rxKick() if (rxFifo.empty()) goto exit; - DPRINTF(EthernetSM, "\n\n*****processing receive of new packet\n"); + DPRINTF(EthernetSM, "****processing receive of new packet****\n"); // If we don't have a packet, grab a new one from the fifo. rxPacket = rxFifo.front(); rxPktBytes = rxPacket->length; rxPacketBufPtr = rxPacket->data; +#if TRACING_ON if (DTRACE(Ethernet)) { if (rxPacket->isIpPkt()) { ip_header *ip = rxPacket->getIpHdr(); DPRINTF(Ethernet, "ID is %d\n", reverseEnd16(ip->ID)); if (rxPacket->isTcpPkt()) { tcp_header *tcp = rxPacket->getTcpHdr(ip); - DPRINTF(Ethernet, "Src Port = %d, Dest Port = %d\n", + DPRINTF(Ethernet, "Src Port=%d, Dest Port=%d\n", reverseEnd16(tcp->src_port_num), reverseEnd16(tcp->dest_port_num)); } } } +#endif // sanity check - i think the driver behaves like this assert(rxDescCnt >= rxPktBytes); @@ -1413,10 +1457,12 @@ NSGigE::rxKick() } - // dont' need the && rxDescCnt > 0 if driver sanity check above holds + // dont' need the && rxDescCnt > 0 if driver sanity check + // above holds if (rxPktBytes > 0) { rxState = rxFragWrite; - // don't need min<>(rxPktBytes,rxDescCnt) if above sanity check holds + // don't need min<>(rxPktBytes,rxDescCnt) if above sanity + // check holds rxXferLen = rxPktBytes; rxDmaAddr = rxFragPtr & 0x3fffffff; @@ -1441,11 +1487,13 @@ NSGigE::rxKick() rxDescCache.cmdsts += rxPacket->length; //i.e. set CMDSTS_SIZE #if 0 - /* all the driver uses these are for its own stats keeping - which we don't care about, aren't necessary for functionality - and doing this would just slow us down. if they end up using - this in a later version for functional purposes, just undef - */ + /* + * all the driver uses these are for its own stats keeping + * which we don't care about, aren't necessary for + * functionality and doing this would just slow us down. + * if they end up using this in a later version for + * functional purposes, just undef + */ if (rxFilterEnable) { rxDescCache.cmdsts &= ~CMDSTS_DEST_MASK; if (rxFifo.front()->IsUnicast()) @@ -1482,14 +1530,20 @@ NSGigE::rxKick() } rxPacket = 0; - /* the driver seems to always receive into desc buffers - of size 1514, so you never have a pkt that is split - into multiple descriptors on the receive side, so - i don't implement that case, hence the assert above. - */ + /* + * the driver seems to always receive into desc buffers + * of size 1514, so you never have a pkt that is split + * into multiple descriptors on the receive side, so + * i don't implement that case, hence the assert above. + */ - DPRINTF(EthernetDesc, "rxDesc writeback:\n\tcmdsts=%08x\n\textsts=%08x\n", - rxDescCache.cmdsts, rxDescCache.extsts); + DPRINTF(EthernetDesc, + "rxDescCache: addr=%08x writeback cmdsts extsts\n", + regs.rxdp & 0x3fffffff); + DPRINTF(EthernetDesc, + "rxDescCache: link=%08x bufptr=%08x cmdsts=%08x extsts=%08x\n", + rxDescCache.link, rxDescCache.bufptr, rxDescCache.cmdsts, + rxDescCache.extsts); rxDmaAddr = (regs.rxdp + offsetof(ns_desc, cmdsts)) & 0x3fffffff; rxDmaData = &(rxDescCache.cmdsts); @@ -1527,18 +1581,20 @@ NSGigE::rxKick() if (rxDescCache.cmdsts & CMDSTS_INTR) devIntrPost(ISR_RXDESC); - if (rxHalt) { + if (!rxEnable) { DPRINTF(EthernetSM, "Halting the RX state machine\n"); rxState = rxIdle; - rxHalt = false; + goto exit; } else rxState = rxAdvance; break; case rxAdvance: if (rxDescCache.link == 0) { + devIntrPost(ISR_RXIDLE); rxState = rxIdle; - return; + CRDD = true; + goto exit; } else { rxState = rxDescRead; regs.rxdp = rxDescCache.link; @@ -1558,23 +1614,16 @@ NSGigE::rxKick() panic("Invalid rxState!"); } - - DPRINTF(EthernetSM, "entering next rx state = %s\n", + DPRINTF(EthernetSM, "entering next rxState=%s\n", NsRxStateStrings[rxState]); - if (rxState == rxIdle) { - regs.command &= ~CR_RXE; - devIntrPost(ISR_RXIDLE); - return; - } - goto next; exit: /** * @todo do we want to schedule a future kick? */ - DPRINTF(EthernetSM, "rx state machine exited state=%s\n", + DPRINTF(EthernetSM, "rx state machine exited rxState=%s\n", NsRxStateStrings[rxState]); } @@ -1586,21 +1635,23 @@ NSGigE::transmit() return; } - DPRINTF(Ethernet, "\n\nAttempt Pkt Transmit: txFifo length = %d\n", - MAX_TX_FIFO_SIZE - txFifoAvail); + DPRINTF(Ethernet, "Attempt Pkt Transmit: txFifo length=%d\n", + maxTxFifoSize - txFifoAvail); if (interface->sendPacket(txFifo.front())) { +#if TRACING_ON if (DTRACE(Ethernet)) { if (txFifo.front()->isIpPkt()) { ip_header *ip = txFifo.front()->getIpHdr(); DPRINTF(Ethernet, "ID is %d\n", reverseEnd16(ip->ID)); if (txFifo.front()->isTcpPkt()) { tcp_header *tcp = txFifo.front()->getTcpHdr(ip); - DPRINTF(Ethernet, "Src Port = %d, Dest Port = %d\n", + DPRINTF(Ethernet, "Src Port=%d, Dest Port=%d\n", reverseEnd16(tcp->src_port_num), reverseEnd16(tcp->dest_port_num)); } } } +#endif DDUMP(Ethernet, txFifo.front()->data, txFifo.front()->length); txBytes += txFifo.front()->length; @@ -1608,18 +1659,23 @@ NSGigE::transmit() txFifoAvail += txFifo.front()->length; - DPRINTF(Ethernet, "Successful Xmit! now txFifoAvail is %d\n", txFifoAvail); + DPRINTF(Ethernet, "Successful Xmit! now txFifoAvail is %d\n", + txFifoAvail); txFifo.front() = NULL; txFifo.pop_front(); - /* normally do a writeback of the descriptor here, and ONLY after that is - done, send this interrupt. but since our stuff never actually fails, - just do this interrupt here, otherwise the code has to stray from this - nice format. besides, it's functionally the same. - */ + /* + * normally do a writeback of the descriptor here, and ONLY + * after that is done, send this interrupt. but since our + * stuff never actually fails, just do this interrupt here, + * otherwise the code has to stray from this nice format. + * besides, it's functionally the same. + */ devIntrPost(ISR_TXOK); - } else - DPRINTF(Ethernet, "May need to rethink always sending the descriptors back?\n"); + } else { + DPRINTF(Ethernet, + "May need to rethink always sending the descriptors back?\n"); + } if (!txFifo.empty() && !txEvent.scheduled()) { DPRINTF(Ethernet, "reschedule transmit\n"); @@ -1632,7 +1688,7 @@ NSGigE::txDmaReadCopy() { assert(txDmaState == dmaReading); - memcpy(txDmaData, physmem->dma_addr(txDmaAddr, txDmaLen), txDmaLen); + physmem->dma_read((uint8_t *)txDmaData, txDmaAddr, txDmaLen); txDmaState = dmaIdle; DPRINTF(EthernetDMA, "tx dma read paddr=%#x len=%d\n", @@ -1684,7 +1740,7 @@ NSGigE::txDmaWriteCopy() { assert(txDmaState == dmaWriting); - memcpy(physmem->dma_addr(txDmaAddr, txDmaLen), txDmaData, txDmaLen); + physmem->dma_write(txDmaAddr, (uint8_t *)txDmaData, txDmaLen); txDmaState = dmaIdle; DPRINTF(EthernetDMA, "tx dma write paddr=%#x len=%d\n", @@ -1734,7 +1790,8 @@ NSGigE::txDmaWriteDone() void NSGigE::txKick() { - DPRINTF(EthernetSM, "transmit kick state=%s\n", NsTxStateStrings[txState]); + DPRINTF(EthernetSM, "transmit kick txState=%s\n", + NsTxStateStrings[txState]); if (txKickTick > curTick) { DPRINTF(EthernetSM, "transmit kick exiting, can't run till %d\n", @@ -1759,7 +1816,7 @@ NSGigE::txKick() switch (txState) { case txIdle: - if (!regs.command & CR_TXE) { + if (!txEnable) { DPRINTF(EthernetSM, "Transmit disabled. Nothing to do.\n"); goto exit; } @@ -1806,8 +1863,8 @@ NSGigE::txKick() goto exit; DPRINTF(EthernetDesc, - "txDescCache data:\n\tlink=%08x\n\tbufptr=%08x\n\tcmdsts=%08x\n\textsts=%08x\n" - ,txDescCache.link, txDescCache.bufptr, txDescCache.cmdsts, + "txDescCache: link=%08x bufptr=%08x cmdsts=%08x extsts=%08x\n", + txDescCache.link, txDescCache.bufptr, txDescCache.cmdsts, txDescCache.extsts); if (txDescCache.cmdsts & CMDSTS_OWN) { @@ -1815,13 +1872,15 @@ NSGigE::txKick() txFragPtr = txDescCache.bufptr; txDescCnt = txDescCache.cmdsts & CMDSTS_LEN_MASK; } else { + devIntrPost(ISR_TXIDLE); txState = txIdle; + goto exit; } break; case txFifoBlock: if (!txPacket) { - DPRINTF(EthernetSM, "\n\n*****starting the tx of a new packet\n"); + DPRINTF(EthernetSM, "****starting the tx of a new packet****\n"); txPacket = new EtherPacket; txPacket->data = new uint8_t[16384]; txPacketBufPtr = txPacket->data; @@ -1835,7 +1894,8 @@ NSGigE::txKick() txDescCache.cmdsts &= ~CMDSTS_OWN; - txDmaAddr = (regs.txdp + offsetof(ns_desc, cmdsts)) & 0x3fffffff; + txDmaAddr = regs.txdp + offsetof(ns_desc, cmdsts); + txDmaAddr &= 0x3fffffff; txDmaData = &(txDescCache.cmdsts); txDmaLen = sizeof(txDescCache.cmdsts); txDmaFree = dmaDescFree; @@ -1860,66 +1920,80 @@ NSGigE::txKick() } txPacket->length = txPacketBufPtr - txPacket->data; - /* this is just because the receive can't handle a packet bigger - want to make sure */ + // this is just because the receive can't handle a + // packet bigger want to make sure assert(txPacket->length <= 1514); txFifo.push_back(txPacket); - /* this following section is not to spec, but functionally shouldn't - be any different. normally, the chip will wait til the transmit has - occurred before writing back the descriptor because it has to wait - to see that it was successfully transmitted to decide whether to set - CMDSTS_OK or not. however, in the simulator since it is always - successfully transmitted, and writing it exactly to spec would - complicate the code, we just do it here - */ + /* + * this following section is not tqo spec, but + * functionally shouldn't be any different. normally, + * the chip will wait til the transmit has occurred + * before writing back the descriptor because it has + * to wait to see that it was successfully transmitted + * to decide whether to set CMDSTS_OK or not. + * however, in the simulator since it is always + * successfully transmitted, and writing it exactly to + * spec would complicate the code, we just do it here + */ txDescCache.cmdsts &= ~CMDSTS_OWN; txDescCache.cmdsts |= CMDSTS_OK; DPRINTF(EthernetDesc, - "txDesc writeback:\n\tcmdsts=%08x\n\textsts=%08x\n", + "txDesc writeback: cmdsts=%08x extsts=%08x\n", txDescCache.cmdsts, txDescCache.extsts); - txDmaAddr = (regs.txdp + offsetof(ns_desc, cmdsts)) & 0x3fffffff; + txDmaAddr = regs.txdp + offsetof(ns_desc, cmdsts); + txDmaAddr &= 0x3fffffff; txDmaData = &(txDescCache.cmdsts); - txDmaLen = sizeof(txDescCache.cmdsts) + sizeof(txDescCache.extsts); + txDmaLen = sizeof(txDescCache.cmdsts) + + sizeof(txDescCache.extsts); txDmaFree = dmaDescFree; descDmaWrites++; descDmaWrBytes += txDmaLen; - if (doTxDmaWrite()) - goto exit; - transmit(); - txPacket = 0; - if (txHalt) { + if (!txEnable) { DPRINTF(EthernetSM, "halting TX state machine\n"); txState = txIdle; - txHalt = false; + goto exit; } else txState = txAdvance; + + if (doTxDmaWrite()) + goto exit; } } else { DPRINTF(EthernetSM, "this descriptor isn't done yet\n"); - 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); - - txDmaAddr = txFragPtr & 0x3fffffff; - txDmaData = txPacketBufPtr; - txDmaLen = txXferLen; - txDmaFree = dmaDataFree; + 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); + + txDmaAddr = txFragPtr & 0x3fffffff; + txDmaData = txPacketBufPtr; + txDmaLen = txXferLen; + txDmaFree = dmaDataFree; + + if (doTxDmaRead()) + goto exit; + } else { + txState = txFifoBlock; + transmit(); - if (doTxDmaRead()) goto exit; + } + } break; @@ -1939,16 +2013,17 @@ NSGigE::txKick() if (txDmaState != dmaIdle) goto exit; - if (txDescCache.cmdsts & CMDSTS_INTR) { + if (txDescCache.cmdsts & CMDSTS_INTR) devIntrPost(ISR_TXDESC); - } txState = txAdvance; break; case txAdvance: if (txDescCache.link == 0) { + devIntrPost(ISR_TXIDLE); txState = txIdle; + goto exit; } else { txState = txDescRead; regs.txdp = txDescCache.link; @@ -1968,30 +2043,28 @@ NSGigE::txKick() panic("invalid state"); } - DPRINTF(EthernetSM, "entering next tx state=%s\n", + DPRINTF(EthernetSM, "entering next txState=%s\n", NsTxStateStrings[txState]); - if (txState == txIdle) { - regs.command &= ~CR_TXE; - devIntrPost(ISR_TXIDLE); - return; - } - goto next; exit: /** * @todo do we want to schedule a future kick? */ - DPRINTF(EthernetSM, "tx state machine exited state=%s\n", + DPRINTF(EthernetSM, "tx state machine exited txState=%s\n", NsTxStateStrings[txState]); } void NSGigE::transferDone() { - if (txFifo.empty()) + if (txFifo.empty()) { + DPRINTF(Ethernet, "transfer complete: txFifo empty...nothing to do\n"); return; + } + + DPRINTF(Ethernet, "transfer complete: data in txFifo...schedule xmit\n"); if (txEvent.scheduled()) txEvent.reschedule(curTick + 1); @@ -2013,8 +2086,8 @@ NSGigE::rxFilter(PacketPtr packet) drop = false; // If we make a perfect match - if ((acceptPerfect) - && (memcmp(rom.perfectMatch, packet->data, sizeof(rom.perfectMatch)) == 0)) + if (acceptPerfect && + memcmp(rom.perfectMatch, packet->data, EADDR_LEN) == 0) drop = false; eth_header *eth = (eth_header *) packet->data; @@ -2055,10 +2128,12 @@ 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, "Receiving packet from wire, rxFifoAvail=%d\n", + maxRxFifoSize - rxFifoCnt); - if (rxState == rxIdle) { + if (!rxEnable) { DPRINTF(Ethernet, "receive disabled...packet dropped\n"); + debug_break(); interface->recvDone(); return true; } @@ -2069,7 +2144,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); @@ -2085,8 +2160,9 @@ NSGigE::recvPacket(PacketPtr packet) } /** - * does a udp checksum. if gen is true, then it generates it and puts it in the right place - * else, it just checks what it calculates against the value in the header in packet + * does a udp checksum. if gen is true, then it generates it and puts + * it in the right place else, it just checks what it calculates + * against the value in the header in packet */ bool NSGigE::udpChecksum(PacketPtr packet, bool gen) @@ -2126,10 +2202,11 @@ NSGigE::tcpChecksum(PacketPtr packet, bool gen) pseudo->src_ip_addr = ip->src_ip_addr; pseudo->dest_ip_addr = ip->dest_ip_addr; pseudo->protocol = reverseEnd16(ip->protocol); - pseudo->len = reverseEnd16(reverseEnd16(ip->dgram_len) - (ip->vers_len & 0xf)*4); + pseudo->len = reverseEnd16(reverseEnd16(ip->dgram_len) - + (ip->vers_len & 0xf)*4); cksum = checksumCalc((uint16_t *) pseudo, (uint16_t *) hdr, - (uint32_t) reverseEnd16(pseudo->len)); + (uint32_t) reverseEnd16(pseudo->len)); } else { pseudo->src_ip_addr = 0; pseudo->dest_ip_addr = 0; @@ -2137,7 +2214,8 @@ NSGigE::tcpChecksum(PacketPtr packet, bool gen) pseudo->len = 0; hdr->chksum = 0; cksum = checksumCalc((uint16_t *) pseudo, (uint16_t *) hdr, - (uint32_t) (reverseEnd16(ip->dgram_len) - (ip->vers_len & 0xf)*4)); + (uint32_t) (reverseEnd16(ip->dgram_len) - + (ip->vers_len & 0xf)*4)); } delete pseudo; @@ -2155,7 +2233,8 @@ NSGigE::ipChecksum(PacketPtr packet, bool gen) { ip_header *hdr = packet->getIpHdr(); - uint16_t cksum = checksumCalc(NULL, (uint16_t *) hdr, (hdr->vers_len & 0xf)*4); + uint16_t cksum = checksumCalc(NULL, (uint16_t *) hdr, + (hdr->vers_len & 0xf)*4); if (gen) { DPRINTF(EthernetCksum, "generated checksum: %#x\n", cksum); @@ -2318,9 +2397,9 @@ NSGigE::serialize(ostream &os) */ int txState = this->txState; SERIALIZE_SCALAR(txState); + SERIALIZE_SCALAR(txEnable); SERIALIZE_SCALAR(CTDD); SERIALIZE_SCALAR(txFifoAvail); - SERIALIZE_SCALAR(txHalt); SERIALIZE_SCALAR(txFragPtr); SERIALIZE_SCALAR(txDescCnt); int txDmaState = this->txDmaState; @@ -2331,10 +2410,10 @@ NSGigE::serialize(ostream &os) */ int rxState = this->rxState; SERIALIZE_SCALAR(rxState); + SERIALIZE_SCALAR(rxEnable); SERIALIZE_SCALAR(CRDD); SERIALIZE_SCALAR(rxPktBytes); SERIALIZE_SCALAR(rxFifoCnt); - SERIALIZE_SCALAR(rxHalt); SERIALIZE_SCALAR(rxDescCnt); int rxDmaState = this->rxDmaState; SERIALIZE_SCALAR(rxDmaState); @@ -2480,9 +2559,9 @@ NSGigE::unserialize(Checkpoint *cp, const std::string §ion) int txState; UNSERIALIZE_SCALAR(txState); this->txState = (TxState) txState; + UNSERIALIZE_SCALAR(txEnable); UNSERIALIZE_SCALAR(CTDD); UNSERIALIZE_SCALAR(txFifoAvail); - UNSERIALIZE_SCALAR(txHalt); UNSERIALIZE_SCALAR(txFragPtr); UNSERIALIZE_SCALAR(txDescCnt); int txDmaState; @@ -2495,10 +2574,10 @@ NSGigE::unserialize(Checkpoint *cp, const std::string §ion) int rxState; UNSERIALIZE_SCALAR(rxState); this->rxState = (RxState) rxState; + UNSERIALIZE_SCALAR(rxEnable); UNSERIALIZE_SCALAR(CRDD); UNSERIALIZE_SCALAR(rxPktBytes); UNSERIALIZE_SCALAR(rxFifoCnt); - UNSERIALIZE_SCALAR(rxHalt); UNSERIALIZE_SCALAR(rxDescCnt); int rxDmaState; UNSERIALIZE_SCALAR(rxDmaState); @@ -2631,6 +2710,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) @@ -2648,7 +2729,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), @@ -2660,7 +2741,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) @@ -2676,7 +2759,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 a8d8d1f18..82f640db1 100644 --- a/dev/ns_gige.hh +++ b/dev/ns_gige.hh @@ -34,20 +34,15 @@ #ifndef __NS_GIGE_HH__ #define __NS_GIGE_HH__ -//#include "base/range.hh" +#include "base/statistics.hh" #include "dev/etherint.hh" #include "dev/etherpkt.hh" -#include "sim/eventq.hh" +#include "dev/io_device.hh" #include "dev/ns_gige_reg.h" -#include "base/statistics.hh" #include "dev/pcidev.hh" #include "dev/tsunami.hh" -#include "dev/io_device.hh" #include "mem/bus/bus.hh" - -/** defined by the NS83820 data sheet */ -#define MAX_TX_FIFO_SIZE 8192 -#define MAX_RX_FIFO_SIZE 32768 +#include "sim/eventq.hh" /** length of ethernet address in bytes */ #define EADDR_LEN 6 @@ -91,7 +86,10 @@ struct dp_regs { }; struct dp_rom { - /** for perfect match memory. the linux driver doesn't use any other ROM */ + /** + * for perfect match memory. + * the linux driver doesn't use any other ROM + */ uint8_t perfectMatch[EADDR_LEN]; }; @@ -168,7 +166,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; @@ -186,6 +186,8 @@ class NSGigE : public PciDev /* tx State Machine */ TxState txState; + bool txEnable; + /** Current Transmit Descriptor Done */ bool CTDD; /** current amt of free space in txDataFifo in bytes */ @@ -200,6 +202,8 @@ class NSGigE : public PciDev /** rx State Machine */ RxState rxState; + bool rxEnable; + /** Current Receive Descriptor Done */ bool CRDD; /** num of bytes in the current packet being drained from rxDataFifo */ @@ -281,7 +285,13 @@ class NSGigE : public PciDev * Retransmit event */ void transmit(); - typedef EventWrapper<NSGigE, &NSGigE::transmit> TxEvent; + void txEventTransmit() + { + transmit(); + if (txState == txFifoBlock) + txKick(); + } + typedef EventWrapper<NSGigE, &NSGigE::txEventTransmit> TxEvent; friend class TxEvent; TxEvent txEvent; @@ -332,13 +342,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); @@ -379,9 +390,6 @@ class NSGigE : public PciDev 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..fca856d5d 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 @@ -394,7 +395,7 @@ Uart::serialize(ostream &os) if (txIntrEvent.scheduled()) txintrwhen = txIntrEvent.when(); else - rxintrwhen = 0; + txintrwhen = 0; SERIALIZE_SCALAR(rxintrwhen); SERIALIZE_SCALAR(txintrwhen); #endif @@ -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/kern/kernel_stats.cc b/kern/kernel_stats.cc index de944329a..e6bcb4d29 100644 --- a/kern/kernel_stats.cc +++ b/kern/kernel_stats.cc @@ -214,6 +214,7 @@ KSData::regStats(const string &name) _modeGood .init(2) + .name(name + ".mode_good") ; _modeFraction diff --git a/kern/linux/linux_system.cc b/kern/linux/linux_system.cc index 70f5fb783..bc2753908 100644 --- a/kern/linux/linux_system.cc +++ b/kern/linux/linux_system.cc @@ -28,10 +28,11 @@ /** * @file - * linux_system.cc loads the linux kernel, console, pal and patches certain functions. - * The symbol tables are loaded so that traces can show the executing function and we can - * skip functions. Various delay loops are skipped and their final values manually computed to - * speed up boot time. + * This code loads the linux kernel, console, pal and patches certain + * functions. The symbol tables are loaded so that traces can show + * the executing function and we can skip functions. Various delay + * loops are skipped and their final values manually computed to speed + * up boot time. */ #include "base/loader/aout_object.hh" @@ -121,13 +122,15 @@ LinuxSystem::LinuxSystem(const string _name, const uint64_t _init_param, #endif skipIdeDelay50msEvent = new SkipFuncEvent(&pcEventQueue, - "ide_delay_50ms"); + "ide_delay_50ms"); skipDelayLoopEvent = new LinuxSkipDelayLoopEvent(&pcEventQueue, "calibrate_delay"); skipCacheProbeEvent = new SkipFuncEvent(&pcEventQueue, - "determine_cpu_caches"); + "determine_cpu_caches"); + + debugPrintkEvent = new DebugPrintkEvent(&pcEventQueue, "dprintk"); Addr addr = 0; @@ -236,6 +239,9 @@ LinuxSystem::LinuxSystem(const string _name, const uint64_t _init_param, if (kernelSymtab->findAddress("determine_cpu_caches", addr)) skipCacheProbeEvent->schedule(addr+sizeof(MachInst)); + + if (kernelSymtab->findAddress("dprintk", addr)) + debugPrintkEvent->schedule(addr+sizeof(MachInst)*2); } LinuxSystem::~LinuxSystem() diff --git a/kern/linux/linux_system.hh b/kern/linux/linux_system.hh index 4f5a74259..e7cdf140d 100644 --- a/kern/linux/linux_system.hh +++ b/kern/linux/linux_system.hh @@ -46,7 +46,7 @@ const Addr PARAM_ADDR = ULL(0xfffffc000030a000); class ExecContext; class ElfObject; class SymbolTable; - +class DebugPrintkEvent; class BreakPCEvent; class LinuxSkipDelayLoopEvent; class SkipFuncEvent; @@ -87,6 +87,9 @@ class LinuxSystem : public System /** PC based event to skip the ide_delay_50ms() call */ SkipFuncEvent *skipIdeDelay50msEvent; + /** PC based event to skip the dprink() call and emulate its functionality */ + DebugPrintkEvent *debugPrintkEvent; + /** Skip calculate_delay_loop() rather than waiting for this to be * calculated */ diff --git a/kern/linux/printk.cc b/kern/linux/printk.cc new file mode 100644 index 000000000..fc7c171bc --- /dev/null +++ b/kern/linux/printk.cc @@ -0,0 +1,265 @@ +/* + * Copyright (c) 2003 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include <sys/types.h> +#include <algorithm> + +#include "base/cprintf.hh" +#include "base/trace.hh" +#include "sim/host.hh" +#include "targetarch/arguments.hh" +#include "targetarch/vtophys.hh" +#include "kern/linux/printk.hh" + +using namespace std; + + +void +Printk(AlphaArguments args) +{ + char *p = (char *)args++; + + ios::fmtflags saved_flags = DebugOut().flags(); + char old_fill = DebugOut().fill(); + int old_precision = DebugOut().precision(); + + while (*p) { + switch (*p) { + case '%': { + bool more = true; + bool islong = false; + bool leftjustify = false; + bool format = false; + bool zero = false; + int width = 0; + while (more && *++p) { + switch (*p) { + case 'l': + case 'L': + islong = true; + break; + case '-': + leftjustify = true; + break; + case '#': + format = true; + break; + case '0': + if (width) + width *= 10; + else + zero = true; + break; + default: + if (*p >= '1' && *p <= '9') + width = 10 * width + *p - '0'; + else + more = false; + break; + } + } + + bool hexnum = false; + bool octal = false; + bool sign = false; + switch (*p) { + case 'X': + case 'x': + hexnum = true; + break; + case 'O': + case 'o': + octal = true; + break; + case 'D': + case 'd': + sign = true; + break; + case 'P': + format = true; + case 'p': + hexnum = true; + break; + } + + switch (*p) { + case 'D': + case 'd': + case 'U': + case 'u': + case 'X': + case 'x': + case 'O': + case 'o': + case 'P': + case 'p': { + if (hexnum) + DebugOut() << hex; + + if (octal) + DebugOut() << oct; + + if (format) { + if (!zero) + DebugOut().setf(ios::showbase); + else { + if (hexnum) { + DebugOut() << "0x"; + width -= 2; + } else if (octal) { + DebugOut() << "0"; + width -= 1; + } + } + } + + if (zero) + DebugOut().fill('0'); + + if (width > 0) + DebugOut().width(width); + + if (leftjustify && !zero) + DebugOut().setf(ios::left); + + if (sign) { + if (islong) + DebugOut() << (int64_t)args; + else + DebugOut() << (int32_t)args; + } else { + if (islong) + DebugOut() << (uint64_t)args; + else + DebugOut() << (uint32_t)args; + } + + if (zero) + DebugOut().fill(' '); + + if (width > 0) + DebugOut().width(0); + + DebugOut() << dec; + + ++args; + } + break; + + case 's': { + char *s = (char *)args; + if (!s) + s = "<NULL>"; + + if (width > 0) + DebugOut().width(width); + if (leftjustify) + DebugOut().setf(ios::left); + + DebugOut() << s; + ++args; + } + break; + case 'C': + case 'c': { + uint64_t mask = (*p == 'C') ? 0xffL : 0x7fL; + uint64_t num; + int width; + + if (islong) { + num = (uint64_t)args; + width = sizeof(uint64_t); + } else { + num = (uint32_t)args; + width = sizeof(uint32_t); + } + + while (width-- > 0) { + char c = (char)(num & mask); + if (c) + DebugOut() << c; + num >>= 8; + } + + ++args; + } + break; + case 'b': { + uint64_t n = (uint64_t)args++; + char *s = (char *)args++; + DebugOut() << s << ": " << n; + } + break; + case 'n': + case 'N': { + args += 2; +#if 0 + uint64_t n = (uint64_t)args++; + struct reg_values *rv = (struct reg_values *)args++; +#endif + } + break; + case 'r': + case 'R': { + args += 2; +#if 0 + uint64_t n = (uint64_t)args++; + struct reg_desc *rd = (struct reg_desc *)args++; +#endif + } + break; + case '%': + DebugOut() << '%'; + break; + } + ++p; + } + break; + case '\n': + DebugOut() << endl; + ++p; + break; + case '\r': + ++p; + if (*p != '\n') + DebugOut() << endl; + break; + + default: { + size_t len = strcspn(p, "%\n\r\0"); + DebugOut().write(p, len); + p += len; + } + } + } + + DebugOut().flags(saved_flags); + DebugOut().fill(old_fill); + DebugOut().precision(old_precision); +} + diff --git a/kern/linux/printk.hh b/kern/linux/printk.hh new file mode 100644 index 000000000..98493b753 --- /dev/null +++ b/kern/linux/printk.hh @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2003-2004 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef __PRINTK_HH__ +#define __PRINTK_HH__ + +class AlphaArguments; + +void Printk(AlphaArguments args); + +#endif // __PRINTK_HH__ diff --git a/kern/tru64/dump_mbuf.cc b/kern/tru64/dump_mbuf.cc index 9121e823d..5dd8e64c3 100644 --- a/kern/tru64/dump_mbuf.cc +++ b/kern/tru64/dump_mbuf.cc @@ -31,6 +31,7 @@ #include "base/cprintf.hh" #include "base/trace.hh" +#include "cpu/exec_context.hh" #include "kern/tru64/mbuf.hh" #include "sim/host.hh" #include "targetarch/arguments.hh" @@ -58,7 +59,8 @@ DumpMbuf(AlphaArguments args) addr, m.m_data, m.m_len); char *buffer = new char[m.m_len]; CopyOut(xc, buffer, m.m_data, m.m_len); - Trace::rawDump((uint8_t *)buffer, m.m_len); + Trace::dataDump(curTick, xc->system->name(), (uint8_t *)buffer, + m.m_len); delete [] buffer; count -= m.m_len; diff --git a/sim/eventq.cc b/sim/eventq.cc index 6b4ccc827..f975c5e97 100644 --- a/sim/eventq.cc +++ b/sim/eventq.cc @@ -208,6 +208,13 @@ EventQueue::dump() cprintf("============================================================\n"); } +extern "C" +void +dumpMainQueue() +{ + mainEventQueue.dump(); +} + const char * Event::description() @@ -235,16 +242,18 @@ Event::trace(const char *action) void Event::dump() { + cprintf("Event (%s)\n", description()); + cprintf("Flags: %#x\n", _flags); #if TRACING_ON - cprintf(" Created: %d\n", when_created); + cprintf("Created: %d\n", when_created); #endif if (scheduled()) { #if TRACING_ON - cprintf(" Scheduled at %d\n", when_scheduled); + cprintf("Scheduled at %d\n", when_scheduled); #endif - cprintf(" Scheduled for %d\n", when()); + cprintf("Scheduled for %d, priority %d\n", when(), _priority); } else { - cprintf(" Not Scheduled\n"); + cprintf("Not Scheduled\n"); } } diff --git a/sim/sim_object.cc b/sim/sim_object.cc index 39219b500..818648b98 100644 --- a/sim/sim_object.cc +++ b/sim/sim_object.cc @@ -30,6 +30,7 @@ #include "base/callback.hh" #include "base/inifile.hh" +#include "base/match.hh" #include "base/misc.hh" #include "base/trace.hh" #include "base/stats/events.hh" @@ -53,13 +54,21 @@ using namespace std; // SimObject::SimObjectList SimObject::simObjectList; +namespace Stats { + extern ObjectMatch event_ignore; +} + // // SimObject constructor: used to maintain static simObjectList // SimObject::SimObject(const string &_name) : objName(_name) { - doRecordEvent = !Stats::ignoreEvent(_name); +#ifdef DEBUG + doDebugBreak = false; +#endif + + doRecordEvent = !Stats::event_ignore.match(_name); simObjectList.push_back(this); } @@ -172,6 +181,31 @@ SimObject::serializeAll(ostream &os) } } +#ifdef DEBUG +// +// static function: flag which objects should have the debugger break +// +void +SimObject::debugObjectBreak(const string &objs) +{ + SimObjectList::const_iterator i = simObjectList.begin(); + SimObjectList::const_iterator end = simObjectList.end(); + + ObjectMatch match(objs); + for (; i != end; ++i) { + SimObject *obj = *i; + obj->doDebugBreak = match.match(obj->name()); + } +} + +extern "C" +void +debugObjectBreak(const char *objs) +{ + SimObject::debugObjectBreak(string(objs)); +} +#endif + void SimObject::recordEvent(const std::string &stat) { diff --git a/sim/sim_object.hh b/sim/sim_object.hh index 770cd558e..dfd70f8ec 100644 --- a/sim/sim_object.hh +++ b/sim/sim_object.hh @@ -83,6 +83,12 @@ class SimObject : public Serializable // static: call nameOut() & serialize() on all SimObjects static void serializeAll(std::ostream &); +#ifdef DEBUG + public: + bool doDebugBreak; + static void debugObjectBreak(const std::string &objs); +#endif + public: bool doRecordEvent; void recordEvent(const std::string &stat); diff --git a/sim/stat_control.cc b/sim/stat_control.cc index 9a4313a61..8a8eaa790 100644 --- a/sim/stat_control.cc +++ b/sim/stat_control.cc @@ -80,6 +80,12 @@ statElapsedTime() return elapsed(); } +Tick +statElapsedTicks() +{ + return curTick - startTick; +} + SimTicksReset simTicksReset; void @@ -105,7 +111,7 @@ InitSimStats() ; simTicks - .scalar(curTick) + .functor(statElapsedTicks) .name("sim_ticks") .desc("Number of ticks simulated") ; diff --git a/util/ccdrv/devtime.c b/util/ccdrv/devtime.c index c3897e597..e487f2fe7 100644 --- a/util/ccdrv/devtime.c +++ b/util/ccdrv/devtime.c @@ -54,18 +54,16 @@ static inline uint32_t cycleCounter(uint32_t dep); static int __init devtime_start(void) { uint64_t addr; - uint32_t t1, t2; + 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)) - { + if (dataAddr != 0 && count != 0) { addr = simple_strtoull(dataAddr, NULL, 0); addr = ioremap(addr, PAGE_SIZE); @@ -75,19 +73,16 @@ static int __init devtime_start(void) * if physical memory is mapped to this address. */ times = kmalloc(sizeof(uint32_t) * count, GFP_USER); - if (!times) - { + if (!times) { printk("Could not allocate memory... Try again later.\n"); return -1; } - if (addr) - { + if (addr) { printk("Preparing to read %#llx %d times.\n", addr, count); t1 = cycleCounter(trash); - for (x=0; x < count; x++) - { + for (x = 0; x < count; x++) { trash = readl(addr); t2 = cycleCounter(trash); times[num++] = t2 - t1; @@ -100,36 +95,30 @@ static int __init devtime_start(void) iounmap(addr); printk("Measurements:\n"); - for (x = 0; x < count; x++) - { + for (x = 0; x < count; x++) { printk("%d ", times[x]); - if (((x+1) % 10) == 0) + if (((x + 1) % 10) == 0) printk("\n"); } printk("\nDone.\n"); - - - } - else + } 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); + 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); + 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"); } @@ -159,7 +148,8 @@ inline uint32_t cycleCounter(uint32_t dep) #error Architecture NOT SUPPORTE #endif -static void __exit devtime_end(void) { +static void __exit devtime_end(void) +{ printk("Devtime Driver Version %s Unloaded...\n", DRIVER_VER); } |