Changes to add tracing and replaying command-line options
[gem5.git] / src / mem / ruby / recorder / Tracer.cc
1
2 /*
3 * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions are
8 * met: redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer;
10 * redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution;
13 * neither the name of the copyright holders nor the names of its
14 * contributors may be used to endorse or promote products derived from
15 * this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
20 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
21 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
22 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
23 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 */
29
30 /*
31 * $Id$
32 *
33 */
34
35 #include "mem/ruby/recorder/Tracer.hh"
36 #include "mem/ruby/recorder/TraceRecord.hh"
37 #include "mem/ruby/eventqueue/RubyEventQueue.hh"
38 #include "mem/gems_common/PrioHeap.hh"
39 #include "mem/ruby/system/System.hh"
40 #include "mem/ruby/config/RubyConfig.hh"
41
42 //added by SS
43 Tracer::Tracer(const string & name)
44 {
45 m_name = name;
46 m_enabled = false;
47 }
48
49 //commented by SS
50 //Tracer::Tracer()
51 //{
52 // m_enabled = false;
53 //}
54
55 Tracer::~Tracer()
56 {
57 }
58
59 void Tracer::init(const vector<string> & argv)
60 {
61 m_warmup_length = 0;
62
63 for (size_t i=0; i<argv.size(); i+=2) {
64 if ( argv[i] == "warmup_length") {
65 m_warmup_length = atoi(argv[i+1].c_str());
66 }
67 else {
68 cerr << "WARNING: Tracer: Unkown configuration parameter: " << argv[i] << endl;
69 assert(false);
70 }
71 }
72 assert(m_warmup_length > 0);
73 }
74
75 void Tracer::startTrace(string filename)
76 {
77 if (m_enabled) {
78 stopTrace();
79 }
80
81 if (filename != "") {
82 m_trace_file.open(filename.c_str());
83 if (m_trace_file.fail()) {
84 cout << "Error: error opening file '" << filename << "'" << endl;
85 cout << "Trace not enabled." << endl;
86 return;
87 }
88 cout << "Request trace enabled to output file '" << filename << "'" << endl;
89 m_enabled = true;
90 }
91 }
92
93 void Tracer::stopTrace()
94 {
95 if (m_enabled == true) {
96 m_trace_file.close();
97 cout << "Request trace file closed." << endl;
98 m_enabled = false;
99 }
100 }
101
102 void Tracer::traceRequest(const string & sequencer_name, const Address& data_addr, const Address& pc_addr, RubyRequestType type, Time time)
103 {
104 assert(m_enabled == true);
105 TraceRecord tr(sequencer_name, data_addr, pc_addr, type, time);
106 tr.output(m_trace_file);
107 }
108
109 // Class method
110 int Tracer::playbackTrace(string filename)
111 {
112 igzstream in(filename.c_str());
113 if (in.fail()) {
114 cout << "Error: error opening file '" << filename << "'" << endl;
115 return 0;
116 }
117
118 time_t start_time = time(NULL);
119
120 TraceRecord record;
121 int counter = 0;
122 // Read in the next TraceRecord
123 bool ok = record.input(in);
124 while (ok) {
125 // Put it in the right cache
126 record.issueRequest();
127 counter++;
128
129 // Read in the next TraceRecord
130 ok = record.input(in);
131
132 // Clear the statistics after warmup
133 /* if (counter == RubyConfig::getTraceWarmupLength()) {
134 cout << "Clearing stats after warmup of length " << RubyConfig::getTraceWarmupLength() << endl;
135 g_system_ptr->clearStats();
136 }
137 */
138 if (counter == m_warmup_length) {
139 cout << "Clearing stats after warmup of length " << m_warmup_length << endl;
140 g_system_ptr->clearStats();
141 }
142
143 }
144
145 // Flush the prefetches through the system
146 g_eventQueue_ptr->triggerEvents(g_eventQueue_ptr->getTime() + 1000); // FIXME - should be smarter
147
148 time_t stop_time = time(NULL);
149 double seconds = difftime(stop_time, start_time);
150 double minutes = seconds / 60.0;
151 cout << "playbackTrace: " << minutes << " minutes" << endl;
152
153 return counter;
154 }
155
156 void Tracer::print(ostream& out) const
157 {
158 }