ruby: moved cache stats from Profiler to CacheMemory
[gem5.git] / src / mem / ruby / system / System.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 * RubySystem.cc
32 *
33 * Description: See System.hh
34 *
35 * $Id$
36 *
37 */
38
39
40 #include "mem/ruby/system/System.hh"
41 #include "mem/ruby/common/Address.hh"
42 #include "mem/ruby/profiler/Profiler.hh"
43 #include "mem/ruby/network/Network.hh"
44 #include "mem/ruby/recorder/Tracer.hh"
45 #include "mem/protocol/Protocol.hh"
46 #include "mem/ruby/buffers/MessageBuffer.hh"
47 #include "mem/ruby/system/Sequencer.hh"
48 #include "mem/ruby/system/DMASequencer.hh"
49 #include "mem/ruby/system/MemoryVector.hh"
50 #include "mem/protocol/ControllerFactory.hh"
51 #include "mem/ruby/slicc_interface/AbstractController.hh"
52 #include "mem/ruby/system/CacheMemory.hh"
53 #include "mem/ruby/system/DirectoryMemory.hh"
54 #include "mem/ruby/network/simple/Topology.hh"
55 #include "mem/ruby/network/simple/SimpleNetwork.hh"
56 #include "mem/ruby/system/RubyPort.hh"
57 #include "mem/ruby/network/garnet-flexible-pipeline/GarnetNetwork.hh"
58 #include "mem/ruby/network/garnet-fixed-pipeline/GarnetNetwork_d.hh"
59 #include "mem/ruby/system/MemoryControl.hh"
60
61 int RubySystem::m_random_seed;
62 bool RubySystem::m_randomization;
63 int RubySystem::m_tech_nm;
64 int RubySystem::m_freq_mhz;
65 int RubySystem::m_block_size_bytes;
66 int RubySystem::m_block_size_bits;
67 uint64 RubySystem::m_memory_size_bytes;
68 int RubySystem::m_memory_size_bits;
69
70 map< string, RubyPort* > RubySystem::m_ports;
71 map< string, CacheMemory* > RubySystem::m_caches;
72 map< string, DirectoryMemory* > RubySystem::m_directories;
73 map< string, Sequencer* > RubySystem::m_sequencers;
74 map< string, DMASequencer* > RubySystem::m_dma_sequencers;
75 map< string, AbstractController* > RubySystem::m_controllers;
76 map< string, MemoryControl* > RubySystem::m_memorycontrols;
77
78
79 Network* RubySystem::m_network_ptr;
80 map< string, Topology*> RubySystem::m_topologies;
81 Profiler* RubySystem::m_profiler_ptr;
82 Tracer* RubySystem::m_tracer_ptr;
83
84 MemoryVector* RubySystem::m_mem_vec_ptr;
85
86
87 RubySystem* RubySystem::create(const vector <RubyObjConf> & sys_conf)
88 {
89 if (g_system_ptr == NULL)
90 return new RubySystem(sys_conf);
91 return g_system_ptr;
92 }
93
94 void RubySystem::init(const vector<string> & argv)
95 {
96 for (size_t i=0; i < argv.size(); i+=2) {
97 if (argv[i] == "random_seed") {
98 m_random_seed = atoi(argv[i+1].c_str());
99 srandom(m_random_seed);
100 } else if (argv[i] == "randomization") {
101 m_randomization = string_to_bool(argv[i+1]);
102 } else if (argv[i] == "tech_nm") {
103 m_tech_nm = atoi(argv[i+1].c_str());
104 } else if (argv[i] == "freq_mhz") {
105 m_freq_mhz = atoi(argv[i+1].c_str());
106 } else if (argv[i] == "block_size_bytes") {
107 m_block_size_bytes = atoi(argv[i+1].c_str());
108 assert(is_power_of_2(m_block_size_bytes));
109 m_block_size_bits = log_int(m_block_size_bytes);
110 } else if (argv[i] == "debug") {
111
112 } else if (argv[i] == "tracer") {
113
114 } else if (argv[i] == "profiler") {
115
116 // } else if (argv[i] == "MI_example") {
117
118 } else {
119 cerr << "Error: Unknown RubySystem config parameter -- " << argv[i] << endl;
120 assert(0);
121 }
122 }
123 }
124
125 RubySystem::RubySystem(const vector <RubyObjConf> & sys_conf)
126 {
127 // DEBUG_MSG(SYSTEM_COMP, MedPrio,"initializing");
128
129 for (size_t i=0;i<sys_conf.size(); i++) {
130 const string & type = sys_conf[i].type;
131 const string & name = sys_conf[i].name;
132 const vector<string> & argv = sys_conf[i].argv;
133 if (type == "System") {
134 init(argv); // initialize system-wide variables before doing anything else!
135 } else if (type == "Debug") {
136 g_debug_ptr = new Debug(name, argv);
137 }
138 }
139
140 assert( g_debug_ptr != NULL);
141 g_eventQueue_ptr = new RubyEventQueue;
142 g_system_ptr = this;
143 m_mem_vec_ptr = new MemoryVector;
144
145 /* object contruction is broken into two steps (Constructor and init) to avoid cyclic dependencies
146 * e.g. a sequencer needs a pointer to a controller and a controller needs a pointer to a sequencer
147 */
148
149 vector<string> memory_control_names;
150
151 for (size_t i=0;i<sys_conf.size(); i++) {
152 const string & type = sys_conf[i].type;
153 const string & name = sys_conf[i].name;
154 if (type == "System" || type == "Debug")
155 continue;
156 else if (type == "SetAssociativeCache")
157 m_caches[name] = new CacheMemory(name);
158 else if (type == "DirectoryMemory")
159 m_directories[name] = new DirectoryMemory(name);
160 else if (type == "Sequencer") {
161 m_sequencers[name] = new Sequencer(name);
162 m_ports[name] = m_sequencers[name];
163 } else if (type == "DMASequencer") {
164 m_dma_sequencers[name] = new DMASequencer(name);
165 m_ports[name] = m_dma_sequencers[name];
166 } else if (type == "Topology") {
167 assert(m_topologies.size() == 0); // only one toplogy at a time is supported right now
168 m_topologies[name] = new Topology(name);
169 } else if (type == "SimpleNetwork") {
170 assert(m_network_ptr == NULL); // only one network at a time is supported right now
171 m_network_ptr = new SimpleNetwork(name);
172 } else if (type.find("generated") == 0) {
173 string controller_type = type.substr(10);
174 m_controllers[name] = ControllerFactory::createController(controller_type, name);
175 // printf ("ss: generated %s \n", controller_type);
176 //added by SS
177 } else if (type == "Tracer") {
178 //m_tracers[name] = new Tracer(name);
179 m_tracer_ptr = new Tracer(name);
180 } else if (type == "Profiler") {
181 m_profiler_ptr = new Profiler(name);
182 } else if (type == "GarnetNetwork") {
183 assert(m_network_ptr == NULL); // only one network at a time is supported right now
184 m_network_ptr = new GarnetNetwork(name);
185 } else if (type == "GarnetNetwork_d") {
186 assert(m_network_ptr == NULL); // only one network at a time is supported right now
187 m_network_ptr = new GarnetNetwork_d(name);
188 } else if (type == "MemoryControl") {
189 m_memorycontrols[name] = new MemoryControl(name);
190 memory_control_names.push_back (name);
191 } else {
192 cerr << "Error: Unknown object type -- " << type << endl;
193 assert(0);
194 }
195 }
196
197 for (size_t i=0;i<sys_conf.size(); i++) {
198 string type = sys_conf[i].type;
199 string name = sys_conf[i].name;
200 const vector<string> & argv = sys_conf[i].argv;
201 if (type == "Topology")
202 m_topologies[name]->init(argv);
203 }
204
205 for (size_t i=0;i<sys_conf.size(); i++) {
206 string type = sys_conf[i].type;
207 string name = sys_conf[i].name;
208 const vector<string> & argv = sys_conf[i].argv;
209 if (type == "SimpleNetwork" || type == "GarnetNetwork" || type == "GarnetNetwork_d"){
210 m_network_ptr->init(argv);
211 }
212 }
213
214 for (size_t i=0;i<sys_conf.size(); i++) {
215 string type = sys_conf[i].type;
216 string name = sys_conf[i].name;
217 const vector<string> & argv = sys_conf[i].argv;
218 if (type == "MemoryControl" ){
219 m_memorycontrols[name]->init(argv);
220 }
221 }
222
223 for (size_t i=0;i<sys_conf.size(); i++) {
224 string type = sys_conf[i].type;
225 string name = sys_conf[i].name;
226 const vector<string> & argv = sys_conf[i].argv;
227 if (type == "System" || type == "Debug")
228 continue;
229 else if (type == "SetAssociativeCache")
230 m_caches[name]->init(argv);
231 else if (type == "DirectoryMemory")
232 m_directories[name]->init(argv);
233 else if (type == "MemoryControl")
234 continue;
235 else if (type == "Sequencer")
236 m_sequencers[name]->init(argv);
237 else if (type == "DMASequencer")
238 m_dma_sequencers[name]->init(argv);
239 else if (type == "Topology")
240 continue;
241 else if (type == "SimpleNetwork" || type == "GarnetNetwork" || type == "GarnetNetwork_d")
242 continue;
243 else if (type.find("generated") == 0) {
244 string controller_type = type.substr(11);
245 m_controllers[name]->init(m_network_ptr, argv);
246 }
247 //added by SS
248 else if (type == "Tracer")
249 //m_tracers[name]->init(argv);
250 m_tracer_ptr->init(argv);
251 else if (type == "Profiler")
252 m_profiler_ptr->init(argv, memory_control_names);
253 // else if (type == "MI_example"){
254 // }
255 else
256 assert(0);
257 }
258
259 // m_profiler_ptr = new Profiler;
260
261 // calculate system-wide parameters
262 m_memory_size_bytes = 0;
263 DirectoryMemory* prev = NULL;
264 for (map< string, DirectoryMemory*>::const_iterator it = m_directories.begin();
265 it != m_directories.end(); it++) {
266 if (prev != NULL)
267 assert((*it).second->getSize() == prev->getSize()); // must be equal for proper address mapping
268 m_memory_size_bytes += (*it).second->getSize();
269 prev = (*it).second;
270 }
271 m_mem_vec_ptr->setSize(m_memory_size_bytes);
272 m_memory_size_bits = log_int(m_memory_size_bytes);
273
274 // m_tracer_ptr = new Tracer;
275 DEBUG_MSG(SYSTEM_COMP, MedPrio,"finished initializing");
276 DEBUG_NEWLINE(SYSTEM_COMP, MedPrio);
277 }
278
279 RubySystem::~RubySystem()
280 {
281
282 }
283
284 void RubySystem::printSystemConfig(ostream & out)
285 {
286 out << "RubySystem config:" << endl;
287 out << " random_seed: " << m_random_seed << endl;
288 out << " randomization: " << m_randomization << endl;
289 out << " tech_nm: " << m_tech_nm << endl;
290 out << " freq_mhz: " << m_freq_mhz << endl;
291 out << " block_size_bytes: " << m_block_size_bytes << endl;
292 out << " block_size_bits: " << m_block_size_bits << endl;
293 out << " memory_size_bytes: " << m_memory_size_bytes << endl;
294 out << " memory_size_bits: " << m_memory_size_bits << endl;
295
296 }
297
298 void RubySystem::printConfig(ostream& out)
299 {
300 out << "\n================ Begin RubySystem Configuration Print ================\n\n";
301 printSystemConfig(out);
302 for (map<string, AbstractController*>::const_iterator it = m_controllers.begin();
303 it != m_controllers.end(); it++) {
304 (*it).second->printConfig(out);
305 }
306 for (map<string, CacheMemory*>::const_iterator it = m_caches.begin();
307 it != m_caches.end(); it++) {
308 (*it).second->printConfig(out);
309 }
310 DirectoryMemory::printGlobalConfig(out);
311 for (map<string, DirectoryMemory*>::const_iterator it = m_directories.begin();
312 it != m_directories.end(); it++) {
313 (*it).second->printConfig(out);
314 }
315 for (map<string, Sequencer*>::const_iterator it = m_sequencers.begin();
316 it != m_sequencers.end(); it++) {
317 (*it).second->printConfig(out);
318 }
319
320 m_network_ptr->printConfig(out);
321 m_profiler_ptr->printConfig(out);
322
323 out << "\n================ End RubySystem Configuration Print ================\n\n";
324 }
325
326 void RubySystem::printStats(ostream& out)
327 {
328
329 const time_t T = time(NULL);
330 tm *localTime = localtime(&T);
331 char buf[100];
332 strftime(buf, 100, "%b/%d/%Y %H:%M:%S", localTime);
333
334 out << "Real time: " << buf << endl;
335
336 m_profiler_ptr->printStats(out);
337 m_network_ptr->printStats(out);
338 for (map<string, CacheMemory*>::const_iterator it = m_caches.begin();
339 it != m_caches.end(); it++) {
340 (*it).second->printStats(out);
341 }
342 for (map<string, AbstractController*>::const_iterator it = m_controllers.begin();
343 it != m_controllers.end(); it++) {
344 (*it).second->printStats(out);
345 }
346 }
347
348 void RubySystem::clearStats() const
349 {
350 /*
351 m_profiler_ptr->clearStats();
352 for (int i=0; i<m_rubyRequestQueues.size(); i++)
353 for (int j=0;j<m_rubyRequestQueues[i].size(); j++)
354 m_rubyRequestQueues[i][j]->clearStats();
355 m_network_ptr->clearStats();
356 for (int i=0; i < MachineType_base_level(MachineType_NUM); i++)
357 m_controllers[i][0]->clearStats();
358 */
359 }
360
361 void RubySystem::recordCacheContents(CacheRecorder& tr) const
362 {
363
364 }
365
366 #ifdef CHECK_COHERENCE
367 // This code will check for cases if the given cache block is exclusive in
368 // one node and shared in another-- a coherence violation
369 //
370 // To use, the SLICC specification must call sequencer.checkCoherence(address)
371 // when the controller changes to a state with new permissions. Do this
372 // in setState. The SLICC spec must also define methods "isBlockShared"
373 // and "isBlockExclusive" that are specific to that protocol
374 //
375 void RubySystem::checkGlobalCoherenceInvariant(const Address& addr ) {
376 /*
377 NodeID exclusive = -1;
378 bool sharedDetected = false;
379 NodeID lastShared = -1;
380
381 for (int i = 0; i < m_chip_vector.size(); i++) {
382
383 if (m_chip_vector[i]->isBlockExclusive(addr)) {
384 if (exclusive != -1) {
385 // coherence violation
386 WARN_EXPR(exclusive);
387 WARN_EXPR(m_chip_vector[i]->getID());
388 WARN_EXPR(addr);
389 WARN_EXPR(g_eventQueue_ptr->getTime());
390 ERROR_MSG("Coherence Violation Detected -- 2 exclusive chips");
391 }
392 else if (sharedDetected) {
393 WARN_EXPR(lastShared);
394 WARN_EXPR(m_chip_vector[i]->getID());
395 WARN_EXPR(addr);
396 WARN_EXPR(g_eventQueue_ptr->getTime());
397 ERROR_MSG("Coherence Violation Detected -- exclusive chip with >=1 shared");
398 }
399 else {
400 exclusive = m_chip_vector[i]->getID();
401 }
402 }
403 else if (m_chip_vector[i]->isBlockShared(addr)) {
404 sharedDetected = true;
405 lastShared = m_chip_vector[i]->getID();
406
407 if (exclusive != -1) {
408 WARN_EXPR(lastShared);
409 WARN_EXPR(exclusive);
410 WARN_EXPR(addr);
411 WARN_EXPR(g_eventQueue_ptr->getTime());
412 ERROR_MSG("Coherence Violation Detected -- exclusive chip with >=1 shared");
413 }
414 }
415 }
416 */
417 }
418 #endif
419
420
421
422