3 * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood
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.
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.
33 * Description: See System.hh
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"
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
;
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
;
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
;
84 MemoryVector
* RubySystem::m_mem_vec_ptr
;
87 RubySystem
* RubySystem::create(const vector
<RubyObjConf
> & sys_conf
)
89 if (g_system_ptr
== NULL
)
90 return new RubySystem(sys_conf
);
94 void RubySystem::init(const vector
<string
> & argv
)
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") {
112 } else if (argv
[i
] == "tracer") {
114 } else if (argv
[i
] == "profiler") {
116 // } else if (argv[i] == "MI_example") {
119 cerr
<< "Error: Unknown RubySystem config parameter -- " << argv
[i
] << endl
;
125 RubySystem::RubySystem(const vector
<RubyObjConf
> & sys_conf
)
127 // DEBUG_MSG(SYSTEM_COMP, MedPrio,"initializing");
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
);
140 assert( g_debug_ptr
!= NULL
);
141 g_eventQueue_ptr
= new RubyEventQueue
;
143 m_mem_vec_ptr
= new MemoryVector
;
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
149 vector
<string
> memory_control_names
;
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")
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);
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
);
193 cerr
<< "Error: Unknown object type -- " << type
<< endl
;
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
);
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
);
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
);
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")
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")
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")
242 else if (type
== "SimpleNetwork" || type
== "GarnetNetwork" || type
== "GarnetNetwork_d")
244 else if (type
.find("generated") == 0) {
245 string controller_type
= type
.substr(11);
246 m_controllers
[name
]->init(m_network_ptr
, argv
);
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"){
260 // m_profiler_ptr = new Profiler;
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
++) {
268 assert((*it
).second
->getSize() == prev
->getSize()); // must be equal for proper address mapping
269 m_memory_size_bytes
+= (*it
).second
->getSize();
272 m_mem_vec_ptr
->setSize(m_memory_size_bytes
);
273 m_memory_size_bits
= log_int(m_memory_size_bytes
);
275 // m_tracer_ptr = new Tracer;
276 DEBUG_MSG(SYSTEM_COMP
, MedPrio
,"finished initializing");
277 DEBUG_NEWLINE(SYSTEM_COMP
, MedPrio
);
280 RubySystem::~RubySystem()
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];
288 delete m_network_ptr;
289 delete m_profiler_ptr;
294 void RubySystem::printSystemConfig(ostream
& out
)
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
;
308 void RubySystem::printConfig(ostream
& out
)
310 out
<< "\n================ Begin RubySystem Configuration Print ================\n\n";
311 // RubyConfig::printConfiguration(out);
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
);
318 for (map
<string
, CacheMemory
*>::const_iterator it
= m_caches
.begin();
319 it
!= m_caches
.end(); it
++) {
320 (*it
).second
->printConfig(out
);
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
);
327 for (map
<string
, Sequencer
*>::const_iterator it
= m_sequencers
.begin();
328 it
!= m_sequencers
.end(); it
++) {
329 (*it
).second
->printConfig(out
);
332 m_network_ptr
->printConfig(out
);
333 m_profiler_ptr
->printConfig(out
);
335 out
<< "\n================ End RubySystem Configuration Print ================\n\n";
338 void RubySystem::printStats(ostream
& out
)
341 const time_t T
= time(NULL
);
342 tm
*localTime
= localtime(&T
);
344 strftime(buf
, 100, "%b/%d/%Y %H:%M:%S", localTime
);
346 out
<< "Real time: " << buf
<< endl
;
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
);
356 void RubySystem::clearStats() const
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();
369 void RubySystem::recordCacheContents(CacheRecorder
& tr
) const
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);
378 m_chip_vector[i]->m_L1Cache_cacheMemory_vec[m_version]->setAsInstructionCache(false);
381 m_chip_vector[i]->recordCacheContents(tr);
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
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
395 void RubySystem::checkGlobalCoherenceInvariant(const Address
& addr
) {
397 NodeID exclusive = -1;
398 bool sharedDetected = false;
399 NodeID lastShared = -1;
401 for (int i = 0; i < m_chip_vector.size(); i++) {
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());
409 WARN_EXPR(g_eventQueue_ptr->getTime());
410 ERROR_MSG("Coherence Violation Detected -- 2 exclusive chips");
412 else if (sharedDetected) {
413 WARN_EXPR(lastShared);
414 WARN_EXPR(m_chip_vector[i]->getID());
416 WARN_EXPR(g_eventQueue_ptr->getTime());
417 ERROR_MSG("Coherence Violation Detected -- exclusive chip with >=1 shared");
420 exclusive = m_chip_vector[i]->getID();
423 else if (m_chip_vector[i]->isBlockShared(addr)) {
424 sharedDetected = true;
425 lastShared = m_chip_vector[i]->getID();
427 if (exclusive != -1) {
428 WARN_EXPR(lastShared);
429 WARN_EXPR(exclusive);
431 WARN_EXPR(g_eventQueue_ptr->getTime());
432 ERROR_MSG("Coherence Violation Detected -- exclusive chip with >=1 shared");