RubyPort.cc (10917:c38f28fad4c3) RubyPort.cc (10919:80069a602c83)
1/*
2 * Copyright (c) 2012-2013 ARM Limited
3 * All rights reserved.
4 *
5 * The license below extends only to copyright in the software and shall
6 * not be construed as granting a license to any other intellectual
7 * property including but not limited to intellectual property relating
8 * to a hardware implementation of the functionality of the software

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

46#include "mem/protocol/AccessPermission.hh"
47#include "mem/ruby/slicc_interface/AbstractController.hh"
48#include "mem/ruby/system/RubyPort.hh"
49#include "mem/simple_mem.hh"
50#include "sim/full_system.hh"
51#include "sim/system.hh"
52
53RubyPort::RubyPort(const Params *p)
1/*
2 * Copyright (c) 2012-2013 ARM Limited
3 * All rights reserved.
4 *
5 * The license below extends only to copyright in the software and shall
6 * not be construed as granting a license to any other intellectual
7 * property including but not limited to intellectual property relating
8 * to a hardware implementation of the functionality of the software

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

46#include "mem/protocol/AccessPermission.hh"
47#include "mem/ruby/slicc_interface/AbstractController.hh"
48#include "mem/ruby/system/RubyPort.hh"
49#include "mem/simple_mem.hh"
50#include "sim/full_system.hh"
51#include "sim/system.hh"
52
53RubyPort::RubyPort(const Params *p)
54 : MemObject(p), m_version(p->version), m_controller(NULL),
55 m_mandatory_q_ptr(NULL), m_usingRubyTester(p->using_ruby_tester),
56 system(p->system),
54 : MemObject(p), m_ruby_system(p->ruby_system), m_version(p->version),
55 m_controller(NULL), m_mandatory_q_ptr(NULL),
56 m_usingRubyTester(p->using_ruby_tester), system(p->system),
57 pioMasterPort(csprintf("%s.pio-master-port", name()), this),
58 pioSlavePort(csprintf("%s.pio-slave-port", name()), this),
59 memMasterPort(csprintf("%s.mem-master-port", name()), this),
60 memSlavePort(csprintf("%s-mem-slave-port", name()), this,
57 pioMasterPort(csprintf("%s.pio-master-port", name()), this),
58 pioSlavePort(csprintf("%s.pio-slave-port", name()), this),
59 memMasterPort(csprintf("%s.mem-master-port", name()), this),
60 memSlavePort(csprintf("%s-mem-slave-port", name()), this,
61 p->ruby_system, p->ruby_system->getAccessBackingStore(), -1),
61 p->ruby_system->getAccessBackingStore(), -1),
62 gotAddrRanges(p->port_master_connection_count)
63{
64 assert(m_version != -1);
65
66 // create the slave ports based on the number of connected ports
67 for (size_t i = 0; i < p->port_slave_connection_count; ++i) {
68 slave_ports.push_back(new MemSlavePort(csprintf("%s.slave%d", name(),
62 gotAddrRanges(p->port_master_connection_count)
63{
64 assert(m_version != -1);
65
66 // create the slave ports based on the number of connected ports
67 for (size_t i = 0; i < p->port_slave_connection_count; ++i) {
68 slave_ports.push_back(new MemSlavePort(csprintf("%s.slave%d", name(),
69 i), this, p->ruby_system,
70 p->ruby_system->getAccessBackingStore(), i));
69 i), this, p->ruby_system->getAccessBackingStore(), i));
71 }
72
73 // create the master ports based on the number of connected ports
74 for (size_t i = 0; i < p->port_master_connection_count; ++i) {
75 master_ports.push_back(new PioMasterPort(csprintf("%s.master%d",
76 name(), i), this));
77 }
78}

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

153 RubyPort *_port)
154 : QueuedMasterPort(_name, _port, reqQueue, snoopRespQueue),
155 reqQueue(*_port, *this), snoopRespQueue(*_port, *this)
156{
157 DPRINTF(RubyPort, "Created master memport on ruby sequencer %s\n", _name);
158}
159
160RubyPort::MemSlavePort::MemSlavePort(const std::string &_name, RubyPort *_port,
70 }
71
72 // create the master ports based on the number of connected ports
73 for (size_t i = 0; i < p->port_master_connection_count; ++i) {
74 master_ports.push_back(new PioMasterPort(csprintf("%s.master%d",
75 name(), i), this));
76 }
77}

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

152 RubyPort *_port)
153 : QueuedMasterPort(_name, _port, reqQueue, snoopRespQueue),
154 reqQueue(*_port, *this), snoopRespQueue(*_port, *this)
155{
156 DPRINTF(RubyPort, "Created master memport on ruby sequencer %s\n", _name);
157}
158
159RubyPort::MemSlavePort::MemSlavePort(const std::string &_name, RubyPort *_port,
161 RubySystem *_system,
162 bool _access_backing_store, PortID id)
163 : QueuedSlavePort(_name, _port, queue, id), queue(*_port, *this),
160 bool _access_backing_store, PortID id)
161 : QueuedSlavePort(_name, _port, queue, id), queue(*_port, *this),
164 ruby_system(_system), access_backing_store(_access_backing_store)
162 access_backing_store(_access_backing_store)
165{
166 DPRINTF(RubyPort, "Created slave memport on ruby sequencer %s\n", _name);
167}
168
169bool
170RubyPort::PioMasterPort::recvTimingResp(PacketPtr pkt)
171{
163{
164 DPRINTF(RubyPort, "Created slave memport on ruby sequencer %s\n", _name);
165}
166
167bool
168RubyPort::PioMasterPort::recvTimingResp(PacketPtr pkt)
169{
172 RubyPort *ruby_port = static_cast<RubyPort *>(&owner);
170 RubyPort *rp = static_cast<RubyPort *>(&owner);
173 DPRINTF(RubyPort, "Response for address: 0x%#x\n", pkt->getAddr());
174
175 // send next cycle
171 DPRINTF(RubyPort, "Response for address: 0x%#x\n", pkt->getAddr());
172
173 // send next cycle
176 ruby_port->pioSlavePort.schedTimingResp(
177 pkt, curTick() + g_system_ptr->clockPeriod());
174 rp->pioSlavePort.schedTimingResp(
175 pkt, curTick() + rp->m_ruby_system->clockPeriod());
178 return true;
179}
180
181bool RubyPort::MemMasterPort::recvTimingResp(PacketPtr pkt)
182{
183 // got a response from a device
184 assert(pkt->isResponse());
185

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

191 delete senderState;
192
193 // In FS mode, ruby memory will receive pio responses from devices
194 // and it must forward these responses back to the particular CPU.
195 DPRINTF(RubyPort, "Pio response for address %#x, going to %s\n",
196 pkt->getAddr(), port->name());
197
198 // attempt to send the response in the next cycle
176 return true;
177}
178
179bool RubyPort::MemMasterPort::recvTimingResp(PacketPtr pkt)
180{
181 // got a response from a device
182 assert(pkt->isResponse());
183

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

189 delete senderState;
190
191 // In FS mode, ruby memory will receive pio responses from devices
192 // and it must forward these responses back to the particular CPU.
193 DPRINTF(RubyPort, "Pio response for address %#x, going to %s\n",
194 pkt->getAddr(), port->name());
195
196 // attempt to send the response in the next cycle
199 port->schedTimingResp(pkt, curTick() + g_system_ptr->clockPeriod());
197 RubyPort *rp = static_cast<RubyPort *>(&owner);
198 port->schedTimingResp(pkt, curTick() + rp->m_ruby_system->clockPeriod());
200
201 return true;
202}
203
204bool
205RubyPort::PioSlavePort::recvTimingReq(PacketPtr pkt)
206{
207 RubyPort *ruby_port = static_cast<RubyPort *>(&owner);

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

239 DPRINTF(RubyPort, "Request address %#x assumed to be a pio address\n",
240 pkt->getAddr());
241
242 // Save the port in the sender state object to be used later to
243 // route the response
244 pkt->pushSenderState(new SenderState(this));
245
246 // send next cycle
199
200 return true;
201}
202
203bool
204RubyPort::PioSlavePort::recvTimingReq(PacketPtr pkt)
205{
206 RubyPort *ruby_port = static_cast<RubyPort *>(&owner);

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

238 DPRINTF(RubyPort, "Request address %#x assumed to be a pio address\n",
239 pkt->getAddr());
240
241 // Save the port in the sender state object to be used later to
242 // route the response
243 pkt->pushSenderState(new SenderState(this));
244
245 // send next cycle
246 RubySystem *rs = ruby_port->m_ruby_system;
247 ruby_port->memMasterPort.schedTimingReq(pkt,
247 ruby_port->memMasterPort.schedTimingReq(pkt,
248 curTick() + g_system_ptr->clockPeriod());
248 curTick() + rs->clockPeriod());
249 return true;
250 }
251
252 assert(Address(pkt->getAddr()).getOffset() + pkt->getSize() <=
253 RubySystem::getBlockSizeBytes());
254
255 // Submit the ruby request
256 RequestStatus requestStatus = ruby_port->makeRequest(pkt);

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

264 pkt->pushSenderState(new SenderState(this));
265
266 DPRINTF(RubyPort, "Request %s 0x%x issued\n", pkt->cmdString(),
267 pkt->getAddr());
268 return true;
269 }
270
271 //
249 return true;
250 }
251
252 assert(Address(pkt->getAddr()).getOffset() + pkt->getSize() <=
253 RubySystem::getBlockSizeBytes());
254
255 // Submit the ruby request
256 RequestStatus requestStatus = ruby_port->makeRequest(pkt);

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

264 pkt->pushSenderState(new SenderState(this));
265
266 DPRINTF(RubyPort, "Request %s 0x%x issued\n", pkt->cmdString(),
267 pkt->getAddr());
268 return true;
269 }
270
271 //
272 // Unless one is using the ruby tester, record the stalled M5 port for
272 // Unless one is using the ruby tester, record the stalled M5 port for
273 // later retry when the sequencer becomes free.
274 //
275 if (!ruby_port->m_usingRubyTester) {
276 ruby_port->addToRetryList(this);
277 }
278
279 DPRINTF(RubyPort, "Request for address %#x did not issued because %s\n",
280 pkt->getAddr(), RequestStatus_to_string(requestStatus));
281
282 return false;
283}
284
285void
286RubyPort::MemSlavePort::recvFunctional(PacketPtr pkt)
287{
288 DPRINTF(RubyPort, "Functional access for address: %#x\n", pkt->getAddr());
289
273 // later retry when the sequencer becomes free.
274 //
275 if (!ruby_port->m_usingRubyTester) {
276 ruby_port->addToRetryList(this);
277 }
278
279 DPRINTF(RubyPort, "Request for address %#x did not issued because %s\n",
280 pkt->getAddr(), RequestStatus_to_string(requestStatus));
281
282 return false;
283}
284
285void
286RubyPort::MemSlavePort::recvFunctional(PacketPtr pkt)
287{
288 DPRINTF(RubyPort, "Functional access for address: %#x\n", pkt->getAddr());
289
290 RubyPort *rp M5_VAR_USED = static_cast<RubyPort *>(&owner);
291 RubySystem *rs = rp->m_ruby_system;
292
290 // Check for pio requests and directly send them to the dedicated
291 // pio port.
292 if (!isPhysMemAddress(pkt->getAddr())) {
293 // Check for pio requests and directly send them to the dedicated
294 // pio port.
295 if (!isPhysMemAddress(pkt->getAddr())) {
293 RubyPort *ruby_port M5_VAR_USED = static_cast<RubyPort *>(&owner);
294 assert(ruby_port->memMasterPort.isConnected());
296 assert(rp->memMasterPort.isConnected());
295 DPRINTF(RubyPort, "Pio Request for address: 0x%#x\n", pkt->getAddr());
296 panic("RubyPort::PioMasterPort::recvFunctional() not implemented!\n");
297 }
298
299 assert(pkt->getAddr() + pkt->getSize() <=
300 line_address(Address(pkt->getAddr())).getAddress() +
301 RubySystem::getBlockSizeBytes());
302
303 if (access_backing_store) {
304 // The attached physmem contains the official version of data.
305 // The following command performs the real functional access.
306 // This line should be removed once Ruby supplies the official version
307 // of data.
297 DPRINTF(RubyPort, "Pio Request for address: 0x%#x\n", pkt->getAddr());
298 panic("RubyPort::PioMasterPort::recvFunctional() not implemented!\n");
299 }
300
301 assert(pkt->getAddr() + pkt->getSize() <=
302 line_address(Address(pkt->getAddr())).getAddress() +
303 RubySystem::getBlockSizeBytes());
304
305 if (access_backing_store) {
306 // The attached physmem contains the official version of data.
307 // The following command performs the real functional access.
308 // This line should be removed once Ruby supplies the official version
309 // of data.
308 ruby_system->getPhysMem()->functionalAccess(pkt);
310 rs->getPhysMem()->functionalAccess(pkt);
309 } else {
310 bool accessSucceeded = false;
311 bool needsResponse = pkt->needsResponse();
312
313 // Do the functional access on ruby memory
314 if (pkt->isRead()) {
311 } else {
312 bool accessSucceeded = false;
313 bool needsResponse = pkt->needsResponse();
314
315 // Do the functional access on ruby memory
316 if (pkt->isRead()) {
315 accessSucceeded = ruby_system->functionalRead(pkt);
317 accessSucceeded = rs->functionalRead(pkt);
316 } else if (pkt->isWrite()) {
318 } else if (pkt->isWrite()) {
317 accessSucceeded = ruby_system->functionalWrite(pkt);
319 accessSucceeded = rs->functionalWrite(pkt);
318 } else {
319 panic("Unsupported functional command %s\n", pkt->cmdString());
320 }
321
322 // Unless the requester explicitly said otherwise, generate an error if
323 // the functional request failed
324 if (!accessSucceeded && !pkt->suppressFuncError()) {
325 fatal("Ruby functional %s failed for address %#x\n",

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

451
452 // Flush requests don't access physical memory
453 if (pkt->isFlush()) {
454 accessPhysMem = false;
455 }
456
457 DPRINTF(RubyPort, "Hit callback needs response %d\n", needsResponse);
458
320 } else {
321 panic("Unsupported functional command %s\n", pkt->cmdString());
322 }
323
324 // Unless the requester explicitly said otherwise, generate an error if
325 // the functional request failed
326 if (!accessSucceeded && !pkt->suppressFuncError()) {
327 fatal("Ruby functional %s failed for address %#x\n",

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

453
454 // Flush requests don't access physical memory
455 if (pkt->isFlush()) {
456 accessPhysMem = false;
457 }
458
459 DPRINTF(RubyPort, "Hit callback needs response %d\n", needsResponse);
460
461 RubyPort *ruby_port = static_cast<RubyPort *>(&owner);
462 RubySystem *rs = ruby_port->m_ruby_system;
459 if (accessPhysMem) {
463 if (accessPhysMem) {
460 ruby_system->getPhysMem()->access(pkt);
464 rs->getPhysMem()->access(pkt);
461 } else if (needsResponse) {
462 pkt->makeResponse();
463 }
464
465 // turn packet around to go back to requester if response expected
466 if (needsResponse) {
467 DPRINTF(RubyPort, "Sending packet back over port\n");
468 // send next cycle
465 } else if (needsResponse) {
466 pkt->makeResponse();
467 }
468
469 // turn packet around to go back to requester if response expected
470 if (needsResponse) {
471 DPRINTF(RubyPort, "Sending packet back over port\n");
472 // send next cycle
469 schedTimingResp(pkt, curTick() + g_system_ptr->clockPeriod());
473 schedTimingResp(pkt, curTick() + rs->clockPeriod());
470 } else {
471 delete pkt;
472 }
473
474 DPRINTF(RubyPort, "Hit callback done!\n");
475}
476
477AddrRangeList

--- 52 unchanged lines hidden ---
474 } else {
475 delete pkt;
476 }
477
478 DPRINTF(RubyPort, "Hit callback done!\n");
479}
480
481AddrRangeList

--- 52 unchanged lines hidden ---