ruby: Import the latest ruby changes from gems.
[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 == "RubySystem") {
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 const vector<string> & argv = sys_conf[i].argv;
155 if (type == "RubySystem" || type == "Debug")
156 continue;
157 else if (type == "SetAssociativeCache")
158 m_caches[name] = new CacheMemory(name);
159 else if (type == "DirectoryMemory")
160 m_directories[name] = new DirectoryMemory(name);
161 else if (type == "Sequencer") {
162 m_sequencers[name] = new Sequencer(name);
163 m_ports[name] = m_sequencers[name];
164 } else if (type == "DMASequencer") {
165 m_dma_sequencers[name] = new DMASequencer(name);
166 m_ports[name] = m_dma_sequencers[name];
167 } else if (type == "Topology") {
168 assert(m_topologies.size() == 0); // only one toplogy at a time is supported right now
169 m_topologies[name] = new Topology(name);
170 } else if (type == "SimpleNetwork") {
171 assert(m_network_ptr == NULL); // only one network at a time is supported right now
172 m_network_ptr = new SimpleNetwork(name);
173 } else if (type.find("generated") == 0) {
174 string controller_type = type.substr(10);
175 m_controllers[name] = ControllerFactory::createController(controller_type, name);
176 // printf ("ss: generated %s \n", controller_type);
177 //added by SS
178 } else if (type == "Tracer") {
179 //m_tracers[name] = new Tracer(name);
180 m_tracer_ptr = new Tracer(name);
181 } else if (type == "Profiler") {
182 m_profiler_ptr = new Profiler(name);
183 } else if (type == "GarnetNetwork") {
184 assert(m_network_ptr == NULL); // only one network at a time is supported right now
185 m_network_ptr = new GarnetNetwork(name);
186 } else if (type == "GarnetNetwork_d") {
187 assert(m_network_ptr == NULL); // only one network at a time is supported right now
188 m_network_ptr = new GarnetNetwork_d(name);
189 } else if (type == "MemoryControl") {
190 m_memorycontrols[name] = new MemoryControl(name);
191 memory_control_names.push_back (name);
192 } else {
193 cerr << "Error: Unknown object type -- " << type << endl;
194 assert(0);
195 }
196 }
197
198 for (size_t i=0;i<sys_conf.size(); i++) {
199 string type = sys_conf[i].type;
200 string name = sys_conf[i].name;
201 const vector<string> & argv = sys_conf[i].argv;
202 if (type == "Topology")
203 m_topologies[name]->init(argv);
204 }
205
206 for (size_t i=0;i<sys_conf.size(); i++) {
207 string type = sys_conf[i].type;
208 string name = sys_conf[i].name;
209 const vector<string> & argv = sys_conf[i].argv;
210 if (type == "SimpleNetwork" || type == "GarnetNetwork" || type == "GarnetNetwork_d"){
211 m_network_ptr->init(argv);
212 }
213 }
214
215 for (size_t i=0;i<sys_conf.size(); i++) {
216 string type = sys_conf[i].type;
217 string name = sys_conf[i].name;
218 const vector<string> & argv = sys_conf[i].argv;
219 if (type == "MemoryControl" ){
220 m_memorycontrols[name]->init(argv);
221 }
222 }
223
224 for (size_t i=0;i<sys_conf.size(); i++) {
225 string type = sys_conf[i].type;
226 string name = sys_conf[i].name;
227 const vector<string> & argv = sys_conf[i].argv;
228 if (type == "RubySystem" || type == "Debug")
229 continue;
230 else if (type == "SetAssociativeCache")
231 m_caches[name]->init(argv);
232 else if (type == "DirectoryMemory")
233 m_directories[name]->init(argv);
234 else if (type == "MemoryControl")
235 continue;
236 else if (type == "Sequencer")
237 m_sequencers[name]->init(argv);
238 else if (type == "DMASequencer")
239 m_dma_sequencers[name]->init(argv);
240 else if (type == "Topology")
241 continue;
242 else if (type == "SimpleNetwork" || type == "GarnetNetwork" || type == "GarnetNetwork_d")
243 continue;
244 else if (type.find("generated") == 0) {
245 string controller_type = type.substr(11);
246 m_controllers[name]->init(m_network_ptr, argv);
247 }
248 //added by SS
249 else if (type == "Tracer")
250 //m_tracers[name]->init(argv);
251 m_tracer_ptr->init(argv);
252 else if (type == "Profiler")
253 m_profiler_ptr->init(argv, memory_control_names);
254 // else if (type == "MI_example"){
255 // }
256 else
257 assert(0);
258 }
259
260 // m_profiler_ptr = new Profiler;
261
262 // calculate system-wide parameters
263 m_memory_size_bytes = 0;
264 DirectoryMemory* prev = NULL;
265 for (map< string, DirectoryMemory*>::const_iterator it = m_directories.begin();
266 it != m_directories.end(); it++) {
267 if (prev != NULL)
268 assert((*it).second->getSize() == prev->getSize()); // must be equal for proper address mapping
269 m_memory_size_bytes += (*it).second->getSize();
270 prev = (*it).second;
271 }
272 m_mem_vec_ptr->setSize(m_memory_size_bytes);
273 m_memory_size_bits = log_int(m_memory_size_bytes);
274
275 // m_tracer_ptr = new Tracer;
276 DEBUG_MSG(SYSTEM_COMP, MedPrio,"finished initializing");
277 DEBUG_NEWLINE(SYSTEM_COMP, MedPrio);
278 }
279
280 RubySystem::~RubySystem()
281 {
282 /*
283 for (int i=0; i < MachineType_base_level(MachineType_NUM); i++) {
284 for (int j=0; j < RubyConfig::getNumberOfControllersPerType(i); j++ ) {
285 delete m_controllers[i][j];
286 }
287 }
288 delete m_network_ptr;
289 delete m_profiler_ptr;
290 delete m_tracer_ptr;
291 */
292 }
293
294 void RubySystem::printSystemConfig(ostream & out)
295 {
296 out << "RubySystem config:" << endl;
297 out << " random_seed: " << m_random_seed << endl;
298 out << " randomization: " << m_randomization << endl;
299 out << " tech_nm: " << m_tech_nm << endl;
300 out << " freq_mhz: " << m_freq_mhz << endl;
301 out << " block_size_bytes: " << m_block_size_bytes << endl;
302 out << " block_size_bits: " << m_block_size_bits << endl;
303 out << " memory_size_bytes: " << m_memory_size_bytes << endl;
304 out << " memory_size_bits: " << m_memory_size_bits << endl;
305
306 }
307
308 void RubySystem::printConfig(ostream& out)
309 {
310 out << "\n================ Begin RubySystem Configuration Print ================\n\n";
311 // RubyConfig::printConfiguration(out);
312 // out << endl;
313 printSystemConfig(out);
314 for (map<string, AbstractController*>::const_iterator it = m_controllers.begin();
315 it != m_controllers.end(); it++) {
316 (*it).second->printConfig(out);
317 }
318 for (map<string, CacheMemory*>::const_iterator it = m_caches.begin();
319 it != m_caches.end(); it++) {
320 (*it).second->printConfig(out);
321 }
322 DirectoryMemory::printGlobalConfig(out);
323 for (map<string, DirectoryMemory*>::const_iterator it = m_directories.begin();
324 it != m_directories.end(); it++) {
325 (*it).second->printConfig(out);
326 }
327 for (map<string, Sequencer*>::const_iterator it = m_sequencers.begin();
328 it != m_sequencers.end(); it++) {
329 (*it).second->printConfig(out);
330 }
331
332 m_network_ptr->printConfig(out);
333 m_profiler_ptr->printConfig(out);
334
335 out << "\n================ End RubySystem Configuration Print ================\n\n";
336 }
337
338 void RubySystem::printStats(ostream& out)
339 {
340
341 const time_t T = time(NULL);
342 tm *localTime = localtime(&T);
343 char buf[100];
344 strftime(buf, 100, "%b/%d/%Y %H:%M:%S", localTime);
345
346 out << "Real time: " << buf << endl;
347
348 m_profiler_ptr->printStats(out);
349 m_network_ptr->printStats(out);
350 for (map<string, AbstractController*>::const_iterator it = m_controllers.begin();
351 it != m_controllers.end(); it++) {
352 (*it).second->printStats(out);
353 }
354 }
355
356 void RubySystem::clearStats() const
357 {
358 /*
359 m_profiler_ptr->clearStats();
360 for (int i=0; i<m_rubyRequestQueues.size(); i++)
361 for (int j=0;j<m_rubyRequestQueues[i].size(); j++)
362 m_rubyRequestQueues[i][j]->clearStats();
363 m_network_ptr->clearStats();
364 for (int i=0; i < MachineType_base_level(MachineType_NUM); i++)
365 m_controllers[i][0]->clearStats();
366 */
367 }
368
369 void RubySystem::recordCacheContents(CacheRecorder& tr) const
370 {
371 /*
372 for (int i = 0; i < m_chip_vector.size(); i++) {
373 for (int m_version = 0; m_version < RubyConfig::numberOfProcsPerChip(); m_version++) {
374 if (Protocol::m_TwoLevelCache) {
375 m_chip_vector[i]->m_L1Cache_L1IcacheMemory_vec[m_version]->setAsInstructionCache(true);
376 m_chip_vector[i]->m_L1Cache_L1DcacheMemory_vec[m_version]->setAsInstructionCache(false);
377 } else {
378 m_chip_vector[i]->m_L1Cache_cacheMemory_vec[m_version]->setAsInstructionCache(false);
379 }
380 }
381 m_chip_vector[i]->recordCacheContents(tr);
382 }
383 */
384 }
385
386 #ifdef CHECK_COHERENCE
387 // This code will check for cases if the given cache block is exclusive in
388 // one node and shared in another-- a coherence violation
389 //
390 // To use, the SLICC specification must call sequencer.checkCoherence(address)
391 // when the controller changes to a state with new permissions. Do this
392 // in setState. The SLICC spec must also define methods "isBlockShared"
393 // and "isBlockExclusive" that are specific to that protocol
394 //
395 void RubySystem::checkGlobalCoherenceInvariant(const Address& addr ) {
396 /*
397 NodeID exclusive = -1;
398 bool sharedDetected = false;
399 NodeID lastShared = -1;
400
401 for (int i = 0; i < m_chip_vector.size(); i++) {
402
403 if (m_chip_vector[i]->isBlockExclusive(addr)) {
404 if (exclusive != -1) {
405 // coherence violation
406 WARN_EXPR(exclusive);
407 WARN_EXPR(m_chip_vector[i]->getID());
408 WARN_EXPR(addr);
409 WARN_EXPR(g_eventQueue_ptr->getTime());
410 ERROR_MSG("Coherence Violation Detected -- 2 exclusive chips");
411 }
412 else if (sharedDetected) {
413 WARN_EXPR(lastShared);
414 WARN_EXPR(m_chip_vector[i]->getID());
415 WARN_EXPR(addr);
416 WARN_EXPR(g_eventQueue_ptr->getTime());
417 ERROR_MSG("Coherence Violation Detected -- exclusive chip with >=1 shared");
418 }
419 else {
420 exclusive = m_chip_vector[i]->getID();
421 }
422 }
423 else if (m_chip_vector[i]->isBlockShared(addr)) {
424 sharedDetected = true;
425 lastShared = m_chip_vector[i]->getID();
426
427 if (exclusive != -1) {
428 WARN_EXPR(lastShared);
429 WARN_EXPR(exclusive);
430 WARN_EXPR(addr);
431 WARN_EXPR(g_eventQueue_ptr->getTime());
432 ERROR_MSG("Coherence Violation Detected -- exclusive chip with >=1 shared");
433 }
434 }
435 }
436 */
437 }
438 #endif
439
440
441
442