RubyPort.cc (8232:b28d06a175be) RubyPort.cc (8436:5648986156db)
1/*
2 * Copyright (c) 2009 Advanced Micro Devices, Inc.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are
7 * met: redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer;

--- 17 unchanged lines hidden (view full) ---

26 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29#include "config/the_isa.hh"
30#if THE_ISA == X86_ISA
31#include "arch/x86/insts/microldstop.hh"
32#endif // X86_ISA
33#include "cpu/testers/rubytest/RubyTester.hh"
1/*
2 * Copyright (c) 2009 Advanced Micro Devices, Inc.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are
7 * met: redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer;

--- 17 unchanged lines hidden (view full) ---

26 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29#include "config/the_isa.hh"
30#if THE_ISA == X86_ISA
31#include "arch/x86/insts/microldstop.hh"
32#endif // X86_ISA
33#include "cpu/testers/rubytest/RubyTester.hh"
34#include "debug/MemoryAccess.hh"
35#include "debug/Ruby.hh"
34#include "debug/Ruby.hh"
35#include "mem/protocol/AccessPermission.hh"
36#include "mem/ruby/slicc_interface/AbstractController.hh"
37#include "mem/ruby/system/RubyPort.hh"
38#include "mem/physical.hh"
39
40RubyPort::RubyPort(const Params *p)
41 : MemObject(p)
42{
43 m_version = p->version;

--- 5 unchanged lines hidden (view full) ---

49 m_mandatory_q_ptr = NULL;
50
51 m_request_cnt = 0;
52 pio_port = NULL;
53 physMemPort = NULL;
54
55 m_usingRubyTester = p->using_ruby_tester;
56 access_phys_mem = p->access_phys_mem;
36#include "mem/ruby/slicc_interface/AbstractController.hh"
37#include "mem/ruby/system/RubyPort.hh"
38#include "mem/physical.hh"
39
40RubyPort::RubyPort(const Params *p)
41 : MemObject(p)
42{
43 m_version = p->version;

--- 5 unchanged lines hidden (view full) ---

49 m_mandatory_q_ptr = NULL;
50
51 m_request_cnt = 0;
52 pio_port = NULL;
53 physMemPort = NULL;
54
55 m_usingRubyTester = p->using_ruby_tester;
56 access_phys_mem = p->access_phys_mem;
57
58 ruby_system = p->ruby_system;
57}
58
59void
60RubyPort::init()
61{
62 assert(m_controller != NULL);
63 m_mandatory_q_ptr = m_controller->getMandatoryQueue();
64}
65
66Port *
67RubyPort::getPort(const std::string &if_name, int idx)
68{
69 if (if_name == "port") {
70 return new M5Port(csprintf("%s-port%d", name(), idx), this,
59}
60
61void
62RubyPort::init()
63{
64 assert(m_controller != NULL);
65 m_mandatory_q_ptr = m_controller->getMandatoryQueue();
66}
67
68Port *
69RubyPort::getPort(const std::string &if_name, int idx)
70{
71 if (if_name == "port") {
72 return new M5Port(csprintf("%s-port%d", name(), idx), this,
71 access_phys_mem);
73 ruby_system, access_phys_mem);
72 }
73
74 if (if_name == "pio_port") {
75 // ensure there is only one pio port
76 assert(pio_port == NULL);
77
78 pio_port = new PioPort(csprintf("%s-pio-port%d", name(), idx), this);
79
80 return pio_port;
81 }
82
83 if (if_name == "physMemPort") {
84 // RubyPort should only have one port to physical memory
85 assert (physMemPort == NULL);
86
87 physMemPort = new M5Port(csprintf("%s-physMemPort", name()), this,
74 }
75
76 if (if_name == "pio_port") {
77 // ensure there is only one pio port
78 assert(pio_port == NULL);
79
80 pio_port = new PioPort(csprintf("%s-pio-port%d", name(), idx), this);
81
82 return pio_port;
83 }
84
85 if (if_name == "physMemPort") {
86 // RubyPort should only have one port to physical memory
87 assert (physMemPort == NULL);
88
89 physMemPort = new M5Port(csprintf("%s-physMemPort", name()), this,
88 access_phys_mem);
90 ruby_system, access_phys_mem);
89
90 return physMemPort;
91 }
92
93 if (if_name == "functional") {
94 // Calls for the functional port only want to access
95 // functional memory. Therefore, directly pass these calls
96 // ports to physmem.

--- 7 unchanged lines hidden (view full) ---

104RubyPort::PioPort::PioPort(const std::string &_name,
105 RubyPort *_port)
106 : SimpleTimingPort(_name, _port)
107{
108 DPRINTF(RubyPort, "creating port to ruby sequencer to cpu %s\n", _name);
109 ruby_port = _port;
110}
111
91
92 return physMemPort;
93 }
94
95 if (if_name == "functional") {
96 // Calls for the functional port only want to access
97 // functional memory. Therefore, directly pass these calls
98 // ports to physmem.

--- 7 unchanged lines hidden (view full) ---

106RubyPort::PioPort::PioPort(const std::string &_name,
107 RubyPort *_port)
108 : SimpleTimingPort(_name, _port)
109{
110 DPRINTF(RubyPort, "creating port to ruby sequencer to cpu %s\n", _name);
111 ruby_port = _port;
112}
113
112RubyPort::M5Port::M5Port(const std::string &_name,
113 RubyPort *_port, bool _access_phys_mem)
114RubyPort::M5Port::M5Port(const std::string &_name, RubyPort *_port,
115 RubySystem *_system, bool _access_phys_mem)
114 : SimpleTimingPort(_name, _port)
115{
116 DPRINTF(RubyPort, "creating port from ruby sequcner to cpu %s\n", _name);
117 ruby_port = _port;
116 : SimpleTimingPort(_name, _port)
117{
118 DPRINTF(RubyPort, "creating port from ruby sequcner to cpu %s\n", _name);
119 ruby_port = _port;
120 ruby_system = _system;
118 _onRetryList = false;
119 access_phys_mem = _access_phys_mem;
120}
121
122Tick
123RubyPort::PioPort::recvAtomic(PacketPtr pkt)
124{
125 panic("RubyPort::PioPort::recvAtomic() not implemented!\n");

--- 158 unchanged lines hidden (view full) ---

284 pkt->getAddr(), RequestStatus_to_string(requestStatus));
285
286 SenderState* senderState = safe_cast<SenderState*>(pkt->senderState);
287 pkt->senderState = senderState->saved;
288 delete senderState;
289 return false;
290}
291
121 _onRetryList = false;
122 access_phys_mem = _access_phys_mem;
123}
124
125Tick
126RubyPort::PioPort::recvAtomic(PacketPtr pkt)
127{
128 panic("RubyPort::PioPort::recvAtomic() not implemented!\n");

--- 158 unchanged lines hidden (view full) ---

287 pkt->getAddr(), RequestStatus_to_string(requestStatus));
288
289 SenderState* senderState = safe_cast<SenderState*>(pkt->senderState);
290 pkt->senderState = senderState->saved;
291 delete senderState;
292 return false;
293}
294
295bool
296RubyPort::M5Port::doFunctionalRead(PacketPtr pkt)
297{
298 Address address(pkt->getAddr());
299 Address line_address(address);
300 line_address.makeLineAddress();
301
302 AccessPermission accessPerm = AccessPermission_NotPresent;
303 int num_controllers = ruby_system->m_abs_cntrl_vec.size();
304
305 // In this loop, we try to figure which controller has a read only or
306 // a read write copy of the given address. Any valid copy would suffice
307 // for a functional read.
308
309 DPRINTF(RubyPort, "Functional Read request for %s\n",address);
310 for(int i = 0;i < num_controllers;++i)
311 {
312 accessPerm = ruby_system->m_abs_cntrl_vec[i]
313 ->getAccessPermission(line_address);
314 if(accessPerm == AccessPermission_Read_Only ||
315 accessPerm == AccessPermission_Read_Write)
316 {
317 unsigned startByte = address.getAddress() - line_address.getAddress();
318
319 uint8* data = pkt->getPtr<uint8_t>(true);
320 unsigned int size_in_bytes = pkt->getSize();
321 DataBlock& block = ruby_system->m_abs_cntrl_vec[i]
322 ->getDataBlock(line_address);
323
324 DPRINTF(RubyPort, "reading from %s block %s\n",
325 ruby_system->m_abs_cntrl_vec[i]->name(), block);
326 for (unsigned i = 0; i < size_in_bytes; ++i)
327 {
328 data[i] = block.getByte(i + startByte);
329 }
330 return true;
331 }
332 }
333 return false;
334}
335
336bool
337RubyPort::M5Port::doFunctionalWrite(PacketPtr pkt)
338{
339 Address addr(pkt->getAddr());
340 Address line_addr = line_address(addr);
341 AccessPermission accessPerm = AccessPermission_NotPresent;
342 int num_controllers = ruby_system->m_abs_cntrl_vec.size();
343
344 DPRINTF(RubyPort, "Functional Write request for %s\n",addr);
345
346 unsigned int num_ro = 0;
347 unsigned int num_rw = 0;
348 unsigned int num_busy = 0;
349
350 // In this loop we count the number of controllers that have the given
351 // address in read only, read write and busy states.
352 for(int i = 0;i < num_controllers;++i)
353 {
354 accessPerm = ruby_system->m_abs_cntrl_vec[i]->
355 getAccessPermission(line_addr);
356 if(accessPerm == AccessPermission_Read_Only) num_ro++;
357 else if(accessPerm == AccessPermission_Read_Write) num_rw++;
358 else if(accessPerm == AccessPermission_Busy) num_busy++;
359 }
360
361 // If the number of read write copies is more than 1, then there is bug in
362 // coherence protocol. Otherwise, if all copies are in stable states, i.e.
363 // num_busy == 0, we update all the copies. If there is at least one copy
364 // in busy state, then we check if there is read write copy. If yes, then
365 // also we let the access go through.
366
367 DPRINTF(RubyPort, "num_busy = %d, num_ro = %d, num_rw = %d\n",
368 num_busy, num_ro, num_rw);
369 assert(num_rw <= 1);
370 if((num_busy == 0 && num_ro > 0) || num_rw == 1)
371 {
372 uint8* data = pkt->getPtr<uint8_t>(true);
373 unsigned int size_in_bytes = pkt->getSize();
374 unsigned startByte = addr.getAddress() - line_addr.getAddress();
375
376 for(int i = 0; i < num_controllers;++i)
377 {
378 accessPerm = ruby_system->m_abs_cntrl_vec[i]->
379 getAccessPermission(line_addr);
380 if(accessPerm == AccessPermission_Read_Only ||
381 accessPerm == AccessPermission_Read_Write||
382 accessPerm == AccessPermission_Maybe_Stale)
383 {
384 DataBlock& block = ruby_system->m_abs_cntrl_vec[i]
385 ->getDataBlock(line_addr);
386
387 DPRINTF(RubyPort, "%s\n",block);
388 for (unsigned i = 0; i < size_in_bytes; ++i)
389 {
390 block.setByte(i + startByte, data[i]);
391 }
392 DPRINTF(RubyPort, "%s\n",block);
393 }
394 }
395 return true;
396 }
397 return false;
398}
399
292void
400void
401RubyPort::M5Port::recvFunctional(PacketPtr pkt)
402{
403 DPRINTF(RubyPort, "Functional access caught for address %#x\n",
404 pkt->getAddr());
405
406 // Check for pio requests and directly send them to the dedicated
407 // pio port.
408 if (!isPhysMemAddress(pkt->getAddr())) {
409 assert(ruby_port->pio_port != NULL);
410 DPRINTF(RubyPort, "Request for address 0x%#x is a pio request\n",
411 pkt->getAddr());
412 panic("RubyPort::PioPort::recvFunctional() not implemented!\n");
413 }
414
415 assert(pkt->getAddr() + pkt->getSize() <=
416 line_address(Address(pkt->getAddr())).getAddress() +
417 RubySystem::getBlockSizeBytes());
418
419 bool accessSucceeded = false;
420 bool needsResponse = pkt->needsResponse();
421
422 // Do the functional access on ruby memory
423 if (pkt->isRead()) {
424 accessSucceeded = doFunctionalRead(pkt);
425 } else if (pkt->isWrite()) {
426 accessSucceeded = doFunctionalWrite(pkt);
427 } else {
428 panic("RubyPort: unsupported functional command %s\n",
429 pkt->cmdString());
430 }
431
432 // Unless the requester explicitly said otherwise, generate an error if
433 // the functional request failed
434 if (!accessSucceeded && !pkt->suppressFuncError()) {
435 fatal("Ruby functional %s failed for address %#x\n",
436 pkt->isWrite() ? "write" : "read", pkt->getAddr());
437 }
438
439 if (access_phys_mem) {
440 // The attached physmem contains the official version of data.
441 // The following command performs the real functional access.
442 // This line should be removed once Ruby supplies the official version
443 // of data.
444 ruby_port->physMemPort->sendFunctional(pkt);
445 }
446
447 // turn packet around to go back to requester if response expected
448 if (needsResponse) {
449 pkt->setFunctionalResponseStatus(accessSucceeded);
450 DPRINTF(RubyPort, "Sending packet back over port\n");
451 sendFunctional(pkt);
452 }
453 DPRINTF(RubyPort, "Functional access %s!\n",
454 accessSucceeded ? "successful":"failed");
455}
456
457void
293RubyPort::ruby_hit_callback(PacketPtr pkt)
294{
295 // Retrieve the request port from the sender State
296 RubyPort::SenderState *senderState =
297 safe_cast<RubyPort::SenderState *>(pkt->senderState);
298 M5Port *port = senderState->port;
299 assert(port != NULL);
300

--- 132 unchanged lines hidden ---
458RubyPort::ruby_hit_callback(PacketPtr pkt)
459{
460 // Retrieve the request port from the sender State
461 RubyPort::SenderState *senderState =
462 safe_cast<RubyPort::SenderState *>(pkt->senderState);
463 M5Port *port = senderState->port;
464 assert(port != NULL);
465

--- 132 unchanged lines hidden ---