From 2f30950143cc70bc42a3c8a4111d7cf8198ec881 Mon Sep 17 00:00:00 2001 From: Nathan Binkert Date: Mon, 11 May 2009 10:38:43 -0700 Subject: ruby: Import ruby and slicc from GEMS We eventually plan to replace the m5 cache hierarchy with the GEMS hierarchy, but for now we will make both live alongside eachother. --- src/mem/ruby/tester/test_framework.cc | 431 ++++++++++++++++++++++++++++++++++ 1 file changed, 431 insertions(+) create mode 100644 src/mem/ruby/tester/test_framework.cc (limited to 'src/mem/ruby/tester/test_framework.cc') diff --git a/src/mem/ruby/tester/test_framework.cc b/src/mem/ruby/tester/test_framework.cc new file mode 100644 index 000000000..0f180409e --- /dev/null +++ b/src/mem/ruby/tester/test_framework.cc @@ -0,0 +1,431 @@ + +/* + * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood + * 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. + */ + +/* + * $Id$ + * + */ + +#include "protocol_name.hh" +#include "test_framework.hh" +#include "System.hh" +#include "OpalInterface.hh" +#include "init.hh" +#include "Tester.hh" +#include "EventQueue.hh" +#include "getopt.hh" +#include "Network.hh" +#include "CacheRecorder.hh" +#include "Tracer.hh" + +using namespace std; +#include +#include + +// Maurice +// extern "C" { +// #include "simics/api.hh" +// }; + +#include "confio.hh" +#include "initvar.hh" + +// A generated file containing the default tester parameters in string form +// The defaults are stored in the variables +// global_default_param and global_default_tester_param +#include "default_param.hh" +#include "tester_param.hh" + +static void parseOptions(int argc, char **argv); +static void usageInstructions(); +static void checkArg(char ch); +static void tester_record_cache(); +static void tester_playback_trace(); +static void tester_initialize(int argc, char **argv); +static void tester_destroy(); + +static string trace_filename; +char * my_default_param; +initvar_t * my_initvar; + +void tester_main(int argc, char **argv) +{ + tester_initialize(argc, argv); + + if (trace_filename != "") { + // playback a trace (for multicast-mask prediction) + tester_playback_trace(); + } else { + // test code to create a trace + if (!(g_SYNTHETIC_DRIVER || g_DETERMINISTIC_DRIVER) && trace_filename == "") { + g_system_ptr->getTracer()->startTrace("ruby.trace.gz"); + g_eventQueue_ptr->triggerEvents(g_eventQueue_ptr->getTime() + 10000); + g_system_ptr->getTracer()->stopTrace(); + } + + g_eventQueue_ptr->triggerAllEvents(); + + // This call is placed here to make sure the cache dump code doesn't fall victim to code rot + if (!(g_SYNTHETIC_DRIVER || g_DETERMINISTIC_DRIVER)) { + tester_record_cache(); + } + } + tester_destroy(); +} + +static void tester_allocate( void ) +{ + init_simulator(); +} + +static void tester_generate_values( void ) +{ +} + +void tester_initialize(int argc, char **argv) +{ + int param_len = strlen( global_default_param ) + strlen( global_default_tester_param ) + 1; + char *default_param = (char *) malloc( sizeof(char) * param_len ); + my_default_param = default_param; + strcpy( default_param, global_default_param ); + strcat( default_param, global_default_tester_param ); + + // when the initvar object is created, it reads the configuration default + // -for the tester, the configuration defaults in config/tester.defaults + + /** note: default_param is included twice in the tester: + * -once in init.C + * -again in this file + */ + initvar_t *ruby_initvar = new initvar_t( "ruby", "../../../ruby/", + default_param, + &tester_allocate, + &tester_generate_values, + NULL, + NULL ); + my_initvar = ruby_initvar; + ruby_initvar->checkInitialization(); + parseOptions(argc, argv); + + ruby_initvar->allocate(); + + g_system_ptr->printConfig(cout); + cout << "Testing clear stats..."; + g_system_ptr->clearStats(); + cout << "Done." << endl; + //free( default_param ); + //delete ruby_initvar; +} + +void tester_destroy() +{ + g_system_ptr->printStats(cout); + g_debug_ptr->closeDebugOutputFile(); + + free(my_default_param); + delete my_initvar; + // Clean up + destroy_simulator(); + cerr << "Success: " << CURRENT_PROTOCOL << endl; +} + +void tester_install_opal(mf_opal_api_t* opal_api, mf_ruby_api_t* ruby_api) +{ + // initialize our api interface + OpalInterface::installInterface(ruby_api); + + // update the OpalInterface object to point to opal's interface + ((OpalInterface *) g_system_ptr->getDriver())->setOpalInterface(opal_api); +} + +void tester_record_cache() +{ + cout << "Testing recording of cache contents" << endl; + CacheRecorder recorder; + g_system_ptr->recordCacheContents(recorder); + int written = recorder.dumpRecords("ruby.caches.gz"); + int read = Tracer::playbackTrace("ruby.caches.gz"); + assert(read == written); + cout << "Testing recording of cache contents completed" << endl; +} + +void tester_playback_trace() +{ + assert(trace_filename != ""); + cout << "Reading trace from file '" << trace_filename << "'..." << endl; + int read = Tracer::playbackTrace(trace_filename); + cout << "(" << read << " requests read)" << endl; + if (read == 0) { + ERROR_MSG("Zero items read from tracefile."); + } +} + +// ************************************************************************ +// *** Functions for parsing the command line parameters for the tester *** +// ************************************************************************ + +static struct option const long_options[] = +{ + {"help", no_argument, NULL, 'h'}, + {"processors", required_argument, NULL, 'p'}, + {"length", required_argument, NULL, 'l'}, + {"random", required_argument, NULL, 'r'}, + {"trace_input", required_argument, NULL, 'z'}, + {"component", required_argument, NULL, 'c'}, + {"verbosity", required_argument, NULL, 'v'}, + {"debug_output_file", required_argument, NULL, 'o'}, + {"start", required_argument, NULL, 's'}, + {"bandwidth", required_argument, NULL, 'b'}, + {"threshold", required_argument, NULL, 't'}, + {"think_time", required_argument, NULL, 'k'}, + {"locks", required_argument, NULL, 'q'}, + {"network", required_argument, NULL, 'n'}, + {"procs_per_chip", required_argument, NULL, 'a'}, + {"l2_caches", required_argument, NULL, 'e'}, + {"memories", required_argument, NULL, 'm'}, + {NULL, 0, NULL, 0} +}; + +static void parseOptions(int argc, char **argv) +{ + cout << "Parsing command line arguments:" << endl; + + // construct the short arguments string + int counter = 0; + string short_options; + while (long_options[counter].name != NULL) { + short_options += char(long_options[counter].val); + if (long_options[counter].has_arg == required_argument) { + short_options += char(':'); + } + counter++; + } + + char c; + /* Parse command line options. */ + bool error; + while ((c = getopt_long (argc, argv, short_options.c_str(), long_options, (int *) 0)) != EOF) { + switch (c) { + case 0: + break; + + case 'c': + checkArg(c); + cout << " component filter string = " << optarg << endl; + error = Debug::checkFilterString( optarg ); + if (error) { + usageInstructions(); + } + DEBUG_FILTER_STRING = strdup( optarg ); + break; + + case 'h': + usageInstructions(); + break; + + case 'v': + checkArg(c); + cout << " verbosity string = " << optarg << endl; + error = Debug::checkVerbosityString(optarg); + if (error) { + usageInstructions(); + } + DEBUG_VERBOSITY_STRING = strdup( optarg ); + break; + + case 'r': { + checkArg(c); + if (string(optarg) == "random") { + g_RANDOM_SEED = time(NULL); + } else { + g_RANDOM_SEED = atoi(optarg); + if (g_RANDOM_SEED == 0) { + usageInstructions(); + } + } + break; + } + + case 'l': { + checkArg(c); + g_tester_length = atoi(optarg); + cout << " length of run = " << g_tester_length << endl; + if (g_tester_length == 0) { + usageInstructions(); + } + break; + } + + case 'q': { + checkArg(c); + g_synthetic_locks = atoi(optarg); + cout << " locks in synthetic workload = " << g_synthetic_locks << endl; + if (g_synthetic_locks == 0) { + usageInstructions(); + } + break; + } + + case 'p': { + checkArg(c); + g_NUM_PROCESSORS = atoi(optarg); + break; + } + + case 'a': { + checkArg(c); + g_PROCS_PER_CHIP = atoi(optarg); + cout << " g_PROCS_PER_CHIP: " << g_PROCS_PER_CHIP << endl; + break; + } + + case 'e': { + checkArg(c); + g_NUM_L2_BANKS = atoi(optarg); + cout << " g_NUM_L2_BANKS: " << g_NUM_L2_BANKS << endl; + break; + } + + case 'm': { + checkArg(c); + g_NUM_MEMORIES = atoi(optarg); + cout << " g_NUM_MEMORIES: " << g_NUM_MEMORIES << endl; + break; + } + + case 's': { + checkArg(c); + long long start_time = atoll(optarg); + cout << " debug start cycle = " << start_time << endl; + if (start_time == 0) { + usageInstructions(); + } + DEBUG_START_TIME = start_time; + break; + } + + case 'b': { + checkArg(c); + int bandwidth = atoi(optarg); + cout << " bandwidth per link (MB/sec) = " << bandwidth << endl; + g_endpoint_bandwidth = bandwidth; + if (bandwidth == 0) { + usageInstructions(); + } + break; + } + + case 't': { + checkArg(c); + g_bash_bandwidth_adaptive_threshold = atof(optarg); + if ((g_bash_bandwidth_adaptive_threshold > 1.1) || (g_bash_bandwidth_adaptive_threshold < -0.1)) { + cerr << "Error: Bandwidth adaptive threshold must be between 0.0 and 1.0" << endl; + usageInstructions(); + } + + break; + } + + case 'k': { + checkArg(c); + g_think_time = atoi(optarg); + break; + } + + case 'o': + checkArg(c); + cout << " output file = " << optarg << endl; + DEBUG_OUTPUT_FILENAME = strdup( optarg ); + break; + + case 'z': + checkArg(c); + trace_filename = string(optarg); + cout << " tracefile = " << trace_filename << endl; + break; + + case 'n': + checkArg(c); + cout << " topology = " << string(optarg) << endl; + g_NETWORK_TOPOLOGY = strdup(optarg); + break; + + default: + cerr << "parameter '" << c << "' unknown" << endl; + usageInstructions(); + } + } + + if ((trace_filename != "") || (g_tester_length != 0)) { + if ((trace_filename != "") && (g_tester_length != 0)) { + cerr << "Error: both a run length (-l) and a trace file (-z) have been specified." << endl; + usageInstructions(); + } + } else { + cerr << "Error: either run length (-l) must be > 0 or a trace file (-z) must be specified." << endl; + usageInstructions(); + } +} + +static void usageInstructions() +{ + cerr << endl; + cerr << "Options:" << endl; + + // print options + int counter = 0; + while (long_options[counter].name != NULL) { + cerr << " -" << char(long_options[counter].val); + if (long_options[counter].has_arg == required_argument) { + cerr << " "; + } + cerr << " --" << long_options[counter].name; + if (long_options[counter].has_arg == required_argument) { + cerr << " "; + } + cerr << endl; + counter++; + } + + cerr << "Option --processors (-p) is required." << endl; + cerr << "Either option --length (-l) or --trace_input (-z) must be specified." << endl; + cerr << endl; + g_debug_ptr->usageInstructions(); + cerr << endl; + + exit(1); +} + +static void checkArg(char ch) +{ + if (optarg == NULL) { + cerr << "Error: parameter '" << ch << "' missing required argument" << endl; + usageInstructions(); + } +} -- cgit v1.2.3 From 6e8373fad6f5faac0648c814f8c7ddc21023dc6c Mon Sep 17 00:00:00 2001 From: Derek Hower Date: Mon, 11 May 2009 10:38:45 -0700 Subject: ruby: Renamed Ruby's EventQueue to RubyEventQueue --HG-- rename : src/mem/ruby/eventqueue/EventQueue.cc => src/mem/ruby/eventqueue/RubyEventQueue.cc rename : src/mem/ruby/eventqueue/EventQueue.hh => src/mem/ruby/eventqueue/RubyEventQueue.hh rename : src/mem/ruby/eventqueue/EventQueueNode.cc => src/mem/ruby/eventqueue/RubyEventQueueNode.cc rename : src/mem/ruby/eventqueue/EventQueueNode.hh => src/mem/ruby/eventqueue/RubyEventQueueNode.hh --- src/mem/ruby/tester/test_framework.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/mem/ruby/tester/test_framework.cc') diff --git a/src/mem/ruby/tester/test_framework.cc b/src/mem/ruby/tester/test_framework.cc index 0f180409e..02320c871 100644 --- a/src/mem/ruby/tester/test_framework.cc +++ b/src/mem/ruby/tester/test_framework.cc @@ -38,7 +38,7 @@ #include "OpalInterface.hh" #include "init.hh" #include "Tester.hh" -#include "EventQueue.hh" +#include "RubyEventQueue.hh" #include "getopt.hh" #include "Network.hh" #include "CacheRecorder.hh" -- cgit v1.2.3 From d8c592a05d884560b3cbbe04d9e1ed9cf6575eaa Mon Sep 17 00:00:00 2001 From: Dan Gibson Date: Mon, 11 May 2009 10:38:45 -0700 Subject: ruby: remove unnecessary code. 1) Removing files from the ruby build left some unresovled symbols. Those have been fixed. 2) Most of the dependencies on Simics data types and the simics interface files have been removed. 3) Almost all mention of opal is gone. 4) Huge chunks of LogTM are now gone. 5) Handling 1-4 left ~hundreds of unresolved references, which were fixed, yielding a snowball effect (and the massive size of this delta). --- src/mem/ruby/tester/test_framework.cc | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) (limited to 'src/mem/ruby/tester/test_framework.cc') diff --git a/src/mem/ruby/tester/test_framework.cc b/src/mem/ruby/tester/test_framework.cc index 02320c871..e3a16920b 100644 --- a/src/mem/ruby/tester/test_framework.cc +++ b/src/mem/ruby/tester/test_framework.cc @@ -35,7 +35,6 @@ #include "protocol_name.hh" #include "test_framework.hh" #include "System.hh" -#include "OpalInterface.hh" #include "init.hh" #include "Tester.hh" #include "RubyEventQueue.hh" @@ -157,11 +156,7 @@ void tester_destroy() void tester_install_opal(mf_opal_api_t* opal_api, mf_ruby_api_t* ruby_api) { - // initialize our api interface - OpalInterface::installInterface(ruby_api); - - // update the OpalInterface object to point to opal's interface - ((OpalInterface *) g_system_ptr->getDriver())->setOpalInterface(opal_api); + std::cout << __FILE__ << "(" << __LINE__ << "): Not implemented" << std::endl; } void tester_record_cache() -- cgit v1.2.3 From 24da30e317cdbf4b628141d69b2d17dac5ae3822 Mon Sep 17 00:00:00 2001 From: Nathan Binkert Date: Mon, 11 May 2009 10:38:45 -0700 Subject: ruby: Make ruby #includes use full paths to the files they're including. This basically means changing all #include statements and changing autogenerated code so that it generates the correct paths. Because slicc generates #includes, I had to hard code the include paths to mem/protocol. --- src/mem/ruby/tester/test_framework.cc | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) (limited to 'src/mem/ruby/tester/test_framework.cc') diff --git a/src/mem/ruby/tester/test_framework.cc b/src/mem/ruby/tester/test_framework.cc index e3a16920b..9886adc8d 100644 --- a/src/mem/ruby/tester/test_framework.cc +++ b/src/mem/ruby/tester/test_framework.cc @@ -32,16 +32,16 @@ * */ -#include "protocol_name.hh" -#include "test_framework.hh" -#include "System.hh" -#include "init.hh" -#include "Tester.hh" -#include "RubyEventQueue.hh" +#include "mem/protocol/protocol_name.hh" +#include "mem/ruby/tester/test_framework.hh" +#include "mem/ruby/system/System.hh" +#include "mem/ruby/init.hh" +#include "mem/ruby/tester/Tester.hh" +#include "mem/ruby/eventqueue/RubyEventQueue.hh" #include "getopt.hh" -#include "Network.hh" -#include "CacheRecorder.hh" -#include "Tracer.hh" +#include "mem/ruby/network/Network.hh" +#include "mem/ruby/recorder/CacheRecorder.hh" +#include "mem/ruby/recorder/Tracer.hh" using namespace std; #include @@ -52,14 +52,14 @@ using namespace std; // #include "simics/api.hh" // }; -#include "confio.hh" -#include "initvar.hh" +#include "mem/gems_common/ioutil/confio.hh" +#include "mem/gems_common/ioutil/initvar.hh" // A generated file containing the default tester parameters in string form // The defaults are stored in the variables // global_default_param and global_default_tester_param -#include "default_param.hh" -#include "tester_param.hh" +#include "mem/ruby/default_param.hh" +#include "mem/ruby/tester_param.hh" static void parseOptions(int argc, char **argv); static void usageInstructions(); -- cgit v1.2.3