2 * Copyright (c) 2018, 2020 ARM Limited
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
9 * licensed hereunder. You may use the software subject to the license
10 * terms below provided that you ensure that this notice is replicated
11 * unmodified and in its entirety in all distributions of the software,
12 * modified or unmodified, in source code or in binary form.
14 * Redistribution and use in source and binary forms, with or without
15 * modification, are permitted provided that the following conditions are
16 * met: redistributions of source code must retain the above copyright
17 * notice, this list of conditions and the following disclaimer;
18 * redistributions in binary form must reproduce the above copyright
19 * notice, this list of conditions and the following disclaimer in the
20 * documentation and/or other materials provided with the distribution;
21 * neither the name of the copyright holders nor the names of its
22 * contributors may be used to endorse or promote products derived from
23 * this software without specific prior written permission.
25 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
26 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
27 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
28 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
29 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
30 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
31 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
32 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
33 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
34 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
35 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
38 #include "mem/mem_delay.hh"
40 #include "params/MemDelay.hh"
41 #include "params/SimpleMemDelay.hh"
43 MemDelay::MemDelay(const MemDelayParams
*p
)
45 requestPort(name() + "-mem_side_port", *this),
46 responsePort(name() + "-cpu_side_port", *this),
47 reqQueue(*this, requestPort
),
48 respQueue(*this, responsePort
),
49 snoopRespQueue(*this, requestPort
)
56 if (!responsePort
.isConnected() || !requestPort
.isConnected())
57 fatal("Memory delay is not connected on both sides.\n");
62 MemDelay::getPort(const std::string
&if_name
, PortID idx
)
64 if (if_name
== "mem_side_port") {
66 } else if (if_name
== "cpu_side_port") {
69 return ClockedObject::getPort(if_name
, idx
);
74 MemDelay::trySatisfyFunctional(PacketPtr pkt
)
76 return responsePort
.trySatisfyFunctional(pkt
) ||
77 requestPort
.trySatisfyFunctional(pkt
);
80 MemDelay::RequestPort::RequestPort(const std::string
&_name
, MemDelay
&_parent
)
81 : QueuedRequestPort(_name
, &_parent
,
82 _parent
.reqQueue
, _parent
.snoopRespQueue
),
88 MemDelay::RequestPort::recvTimingResp(PacketPtr pkt
)
90 // technically the packet only reaches us after the header delay,
91 // and typically we also need to deserialise any payload
92 const Tick receive_delay
= pkt
->headerDelay
+ pkt
->payloadDelay
;
93 pkt
->headerDelay
= pkt
->payloadDelay
= 0;
95 const Tick when
= curTick() + parent
.delayResp(pkt
) + receive_delay
;
97 parent
.responsePort
.schedTimingResp(pkt
, when
);
103 MemDelay::RequestPort::recvFunctionalSnoop(PacketPtr pkt
)
105 if (parent
.trySatisfyFunctional(pkt
)) {
108 parent
.responsePort
.sendFunctionalSnoop(pkt
);
113 MemDelay::RequestPort::recvAtomicSnoop(PacketPtr pkt
)
115 const Tick delay
= parent
.delaySnoopResp(pkt
);
117 return delay
+ parent
.responsePort
.sendAtomicSnoop(pkt
);
121 MemDelay::RequestPort::recvTimingSnoopReq(PacketPtr pkt
)
123 parent
.responsePort
.sendTimingSnoopReq(pkt
);
127 MemDelay::ResponsePort::
128 ResponsePort(const std::string
&_name
, MemDelay
&_parent
)
129 : QueuedResponsePort(_name
, &_parent
, _parent
.respQueue
),
135 MemDelay::ResponsePort::recvAtomic(PacketPtr pkt
)
137 const Tick delay
= parent
.delayReq(pkt
) + parent
.delayResp(pkt
);
139 return delay
+ parent
.requestPort
.sendAtomic(pkt
);
143 MemDelay::ResponsePort::recvTimingReq(PacketPtr pkt
)
145 // technically the packet only reaches us after the header
146 // delay, and typically we also need to deserialise any
148 Tick receive_delay
= pkt
->headerDelay
+ pkt
->payloadDelay
;
149 pkt
->headerDelay
= pkt
->payloadDelay
= 0;
151 const Tick when
= curTick() + parent
.delayReq(pkt
) + receive_delay
;
153 parent
.requestPort
.schedTimingReq(pkt
, when
);
159 MemDelay::ResponsePort::recvFunctional(PacketPtr pkt
)
161 if (parent
.trySatisfyFunctional(pkt
)) {
164 parent
.requestPort
.sendFunctional(pkt
);
169 MemDelay::ResponsePort::recvTimingSnoopResp(PacketPtr pkt
)
171 const Tick when
= curTick() + parent
.delaySnoopResp(pkt
);
173 parent
.requestPort
.schedTimingSnoopResp(pkt
, when
);
180 SimpleMemDelay::SimpleMemDelay(const SimpleMemDelayParams
*p
)
182 readReqDelay(p
->read_req
),
183 readRespDelay(p
->read_resp
),
184 writeReqDelay(p
->write_req
),
185 writeRespDelay(p
->write_resp
)
190 SimpleMemDelay::delayReq(PacketPtr pkt
)
194 } else if (pkt
->isWrite()) {
195 return writeReqDelay
;
202 SimpleMemDelay::delayResp(PacketPtr pkt
)
205 return readRespDelay
;
206 } else if (pkt
->isWrite()) {
207 return writeRespDelay
;
215 SimpleMemDelayParams::create()
217 return new SimpleMemDelay(this);