RubyPort.cc (7940:d6294150a32e) RubyPort.cc (8161:ebb373fcb206)
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;

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

98
99 return NULL;
100}
101
102RubyPort::PioPort::PioPort(const std::string &_name,
103 RubyPort *_port)
104 : SimpleTimingPort(_name, _port)
105{
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;

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

98
99 return NULL;
100}
101
102RubyPort::PioPort::PioPort(const std::string &_name,
103 RubyPort *_port)
104 : SimpleTimingPort(_name, _port)
105{
106 DPRINTF(Ruby, "creating port to ruby sequencer to cpu %s\n", _name);
106 DPRINTF(RubyPort, "creating port to ruby sequencer to cpu %s\n", _name);
107 ruby_port = _port;
108}
109
110RubyPort::M5Port::M5Port(const std::string &_name,
111 RubyPort *_port, bool _access_phys_mem)
112 : SimpleTimingPort(_name, _port)
113{
107 ruby_port = _port;
108}
109
110RubyPort::M5Port::M5Port(const std::string &_name,
111 RubyPort *_port, bool _access_phys_mem)
112 : SimpleTimingPort(_name, _port)
113{
114 DPRINTF(Ruby, "creating port from ruby sequcner to cpu %s\n", _name);
114 DPRINTF(RubyPort, "creating port from ruby sequcner to cpu %s\n", _name);
115 ruby_port = _port;
116 _onRetryList = false;
117 access_phys_mem = _access_phys_mem;
118}
119
120Tick
121RubyPort::PioPort::recvAtomic(PacketPtr pkt)
122{

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

132}
133
134
135bool
136RubyPort::PioPort::recvTiming(PacketPtr pkt)
137{
138 // In FS mode, ruby memory will receive pio responses from devices
139 // and it must forward these responses back to the particular CPU.
115 ruby_port = _port;
116 _onRetryList = false;
117 access_phys_mem = _access_phys_mem;
118}
119
120Tick
121RubyPort::PioPort::recvAtomic(PacketPtr pkt)
122{

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

132}
133
134
135bool
136RubyPort::PioPort::recvTiming(PacketPtr pkt)
137{
138 // In FS mode, ruby memory will receive pio responses from devices
139 // and it must forward these responses back to the particular CPU.
140 DPRINTF(MemoryAccess, "Pio response for address %#x\n", pkt->getAddr());
140 DPRINTF(RubyPort, "Pio response for address %#x\n", pkt->getAddr());
141
142 assert(pkt->isResponse());
143
144 // First we must retrieve the request port from the sender State
145 RubyPort::SenderState *senderState =
146 safe_cast<RubyPort::SenderState *>(pkt->senderState);
147 M5Port *port = senderState->port;
148 assert(port != NULL);

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

154 port->sendTiming(pkt);
155
156 return true;
157}
158
159bool
160RubyPort::M5Port::recvTiming(PacketPtr pkt)
161{
141
142 assert(pkt->isResponse());
143
144 // First we must retrieve the request port from the sender State
145 RubyPort::SenderState *senderState =
146 safe_cast<RubyPort::SenderState *>(pkt->senderState);
147 M5Port *port = senderState->port;
148 assert(port != NULL);

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

154 port->sendTiming(pkt);
155
156 return true;
157}
158
159bool
160RubyPort::M5Port::recvTiming(PacketPtr pkt)
161{
162 DPRINTF(MemoryAccess,
162 DPRINTF(RubyPort,
163 "Timing access caught for address %#x\n", pkt->getAddr());
164
165 //dsm: based on SimpleTimingPort::recvTiming(pkt);
166
167 // The received packets should only be M5 requests, which should never
168 // get nacked. There used to be code to hanldle nacks here, but
169 // I'm pretty sure it didn't work correctly with the drain code,
170 // so that would need to be fixed if we ever added it back.

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

181 // Save the port in the sender state object to be used later to
182 // route the response
183 pkt->senderState = new SenderState(this, pkt->senderState);
184
185 // Check for pio requests and directly send them to the dedicated
186 // pio port.
187 if (!isPhysMemAddress(pkt->getAddr())) {
188 assert(ruby_port->pio_port != NULL);
163 "Timing access caught for address %#x\n", pkt->getAddr());
164
165 //dsm: based on SimpleTimingPort::recvTiming(pkt);
166
167 // The received packets should only be M5 requests, which should never
168 // get nacked. There used to be code to hanldle nacks here, but
169 // I'm pretty sure it didn't work correctly with the drain code,
170 // so that would need to be fixed if we ever added it back.

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

181 // Save the port in the sender state object to be used later to
182 // route the response
183 pkt->senderState = new SenderState(this, pkt->senderState);
184
185 // Check for pio requests and directly send them to the dedicated
186 // pio port.
187 if (!isPhysMemAddress(pkt->getAddr())) {
188 assert(ruby_port->pio_port != NULL);
189 DPRINTF(MemoryAccess,
189 DPRINTF(RubyPort,
190 "Request for address 0x%#x is assumed to be a pio request\n",
191 pkt->getAddr());
192
193 return ruby_port->pio_port->sendTiming(pkt);
194 }
195
196 // For DMA and CPU requests, translate them to ruby requests before
197 // sending them to our assigned ruby port.
198 RubyRequestType type = RubyRequestType_NULL;
199
200 // If valid, copy the pc to the ruby request
201 Addr pc = 0;
202 if (pkt->req->hasPC()) {
203 pc = pkt->req->getPC();
204 }
205
206 if (pkt->isLLSC()) {
207 if (pkt->isWrite()) {
190 "Request for address 0x%#x is assumed to be a pio request\n",
191 pkt->getAddr());
192
193 return ruby_port->pio_port->sendTiming(pkt);
194 }
195
196 // For DMA and CPU requests, translate them to ruby requests before
197 // sending them to our assigned ruby port.
198 RubyRequestType type = RubyRequestType_NULL;
199
200 // If valid, copy the pc to the ruby request
201 Addr pc = 0;
202 if (pkt->req->hasPC()) {
203 pc = pkt->req->getPC();
204 }
205
206 if (pkt->isLLSC()) {
207 if (pkt->isWrite()) {
208 DPRINTF(MemoryAccess, "Issuing SC\n");
208 DPRINTF(RubyPort, "Issuing SC\n");
209 type = RubyRequestType_Store_Conditional;
210 } else {
209 type = RubyRequestType_Store_Conditional;
210 } else {
211 DPRINTF(MemoryAccess, "Issuing LL\n");
211 DPRINTF(RubyPort, "Issuing LL\n");
212 assert(pkt->isRead());
213 type = RubyRequestType_Load_Linked;
214 }
215 } else if (pkt->req->isLocked()) {
216 if (pkt->isWrite()) {
212 assert(pkt->isRead());
213 type = RubyRequestType_Load_Linked;
214 }
215 } else if (pkt->req->isLocked()) {
216 if (pkt->isWrite()) {
217 DPRINTF(MemoryAccess, "Issuing Locked RMW Write\n");
217 DPRINTF(RubyPort, "Issuing Locked RMW Write\n");
218 type = RubyRequestType_Locked_RMW_Write;
219 } else {
218 type = RubyRequestType_Locked_RMW_Write;
219 } else {
220 DPRINTF(MemoryAccess, "Issuing Locked RMW Read\n");
220 DPRINTF(RubyPort, "Issuing Locked RMW Read\n");
221 assert(pkt->isRead());
222 type = RubyRequestType_Locked_RMW_Read;
223 }
224 } else {
225 if (pkt->isRead()) {
226 if (pkt->req->isInstFetch()) {
227 type = RubyRequestType_IFETCH;
228 } else {

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

258
259 // Submit the ruby request
260 RequestStatus requestStatus = ruby_port->makeRequest(ruby_request);
261
262 // If the request successfully issued then we should return true.
263 // Otherwise, we need to delete the senderStatus we just created and return
264 // false.
265 if (requestStatus == RequestStatus_Issued) {
221 assert(pkt->isRead());
222 type = RubyRequestType_Locked_RMW_Read;
223 }
224 } else {
225 if (pkt->isRead()) {
226 if (pkt->req->isInstFetch()) {
227 type = RubyRequestType_IFETCH;
228 } else {

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

258
259 // Submit the ruby request
260 RequestStatus requestStatus = ruby_port->makeRequest(ruby_request);
261
262 // If the request successfully issued then we should return true.
263 // Otherwise, we need to delete the senderStatus we just created and return
264 // false.
265 if (requestStatus == RequestStatus_Issued) {
266 DPRINTF(MemoryAccess, "Request %x issued\n", pkt->getAddr());
266 DPRINTF(RubyPort, "Request %#x issued\n", pkt->getAddr());
267 return true;
268 }
269
270 //
271 // Unless one is using the ruby tester, record the stalled M5 port for
272 // later retry when the sequencer becomes free.
273 //
274 if (!ruby_port->m_usingRubyTester) {
275 ruby_port->addToRetryList(this);
276 }
277
267 return true;
268 }
269
270 //
271 // Unless one is using the ruby tester, record the stalled M5 port for
272 // later retry when the sequencer becomes free.
273 //
274 if (!ruby_port->m_usingRubyTester) {
275 ruby_port->addToRetryList(this);
276 }
277
278 DPRINTF(MemoryAccess,
278 DPRINTF(RubyPort,
279 "Request for address %#x did not issue because %s\n",
280 pkt->getAddr(), RequestStatus_to_string(requestStatus));
281
282 SenderState* senderState = safe_cast<SenderState*>(pkt->senderState);
283 pkt->senderState = senderState->saved;
284 delete senderState;
285 return false;
286}

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

346 } else {
347 //
348 // All LL packets convert to normal loads so that M5 PhysMem does
349 // not lock the blocks.
350 //
351 pkt->convertLlToRead();
352 }
353 }
279 "Request for address %#x did not issue because %s\n",
280 pkt->getAddr(), RequestStatus_to_string(requestStatus));
281
282 SenderState* senderState = safe_cast<SenderState*>(pkt->senderState);
283 pkt->senderState = senderState->saved;
284 delete senderState;
285 return false;
286}

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

346 } else {
347 //
348 // All LL packets convert to normal loads so that M5 PhysMem does
349 // not lock the blocks.
350 //
351 pkt->convertLlToRead();
352 }
353 }
354 DPRINTF(MemoryAccess, "Hit callback needs response %d\n", needsResponse);
354 DPRINTF(RubyPort, "Hit callback needs response %d\n", needsResponse);
355
356 if (accessPhysMem) {
357 ruby_port->physMemPort->sendAtomic(pkt);
358 } else {
359 pkt->makeResponse();
360 }
361
362 // turn packet around to go back to requester if response expected
363 if (needsResponse) {
355
356 if (accessPhysMem) {
357 ruby_port->physMemPort->sendAtomic(pkt);
358 } else {
359 pkt->makeResponse();
360 }
361
362 // turn packet around to go back to requester if response expected
363 if (needsResponse) {
364 DPRINTF(MemoryAccess, "Sending packet back over port\n");
364 DPRINTF(RubyPort, "Sending packet back over port\n");
365 sendTiming(pkt);
366 } else {
367 delete pkt;
368 }
365 sendTiming(pkt);
366 } else {
367 delete pkt;
368 }
369 DPRINTF(MemoryAccess, "Hit callback done!\n");
369 DPRINTF(RubyPort, "Hit callback done!\n");
370}
371
372bool
373RubyPort::M5Port::sendTiming(PacketPtr pkt)
374{
375 //minimum latency, must be > 0
376 schedSendTiming(pkt, curTick() + (1 * g_eventQueue_ptr->getClock()));
377 return true;

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

390{
391 AddrRangeList physMemAddrList;
392 bool snoop = false;
393 ruby_port->physMemPort->getPeerAddressRanges(physMemAddrList, snoop);
394 for (AddrRangeIter iter = physMemAddrList.begin();
395 iter != physMemAddrList.end();
396 iter++) {
397 if (addr >= iter->start && addr <= iter->end) {
370}
371
372bool
373RubyPort::M5Port::sendTiming(PacketPtr pkt)
374{
375 //minimum latency, must be > 0
376 schedSendTiming(pkt, curTick() + (1 * g_eventQueue_ptr->getClock()));
377 return true;

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

390{
391 AddrRangeList physMemAddrList;
392 bool snoop = false;
393 ruby_port->physMemPort->getPeerAddressRanges(physMemAddrList, snoop);
394 for (AddrRangeIter iter = physMemAddrList.begin();
395 iter != physMemAddrList.end();
396 iter++) {
397 if (addr >= iter->start && addr <= iter->end) {
398 DPRINTF(MemoryAccess, "Request found in %#llx - %#llx range\n",
398 DPRINTF(RubyPort, "Request found in %#llx - %#llx range\n",
399 iter->start, iter->end);
400 return true;
401 }
402 }
403 return false;
404}
405
406unsigned
407RubyPort::M5Port::deviceBlockSize() const
408{
409 return (unsigned) RubySystem::getBlockSizeBytes();
410}
399 iter->start, iter->end);
400 return true;
401 }
402 }
403 return false;
404}
405
406unsigned
407RubyPort::M5Port::deviceBlockSize() const
408{
409 return (unsigned) RubySystem::getBlockSizeBytes();
410}