RubySystem.cc revision 6285
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
61int RubySystem::m_random_seed;
62bool RubySystem::m_randomization;
63int RubySystem::m_tech_nm;
64int RubySystem::m_freq_mhz;
65int RubySystem::m_block_size_bytes;
66int RubySystem::m_block_size_bits;
67uint64 RubySystem::m_memory_size_bytes;
68int RubySystem::m_memory_size_bits;
69
70map< string, RubyPort* > RubySystem::m_ports;
71map< string, CacheMemory* > RubySystem::m_caches;
72map< string, DirectoryMemory* > RubySystem::m_directories;
73map< string, Sequencer* > RubySystem::m_sequencers;
74map< string, DMASequencer* > RubySystem::m_dma_sequencers;
75map< string, AbstractController* > RubySystem::m_controllers;
76map< string, MemoryControl* > RubySystem::m_memorycontrols;
77
78
79Network* RubySystem::m_network_ptr;
80map< string, Topology*> RubySystem::m_topologies;
81Profiler* RubySystem::m_profiler_ptr;
82Tracer* RubySystem::m_tracer_ptr;
83
84MemoryVector* RubySystem::m_mem_vec_ptr;
85
86
87RubySystem* 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
94void 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
125RubySystem::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
280RubySystem::~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
294void 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
308void 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
338void 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
356void 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
369void 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//
395void 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
443