2 * Copyright (c) 2016-2020 Advanced Micro Devices, Inc.
5 * For use for simulation and test purposes only
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions are met:
10 * 1. Redistributions of source code must retain the above copyright notice,
11 * this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright notice,
14 * this list of conditions and the following disclaimer in the documentation
15 * and/or other materials provided with the distribution.
17 * 3. Neither the name of the copyright holder nor the names of its
18 * contributors may be used to endorse or promote products derived from this
19 * software without specific prior written permission.
21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
22 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
25 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
26 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
27 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
28 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
29 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
30 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
31 * POSSIBILITY OF SUCH DAMAGE.
35 #include "mem/token_port.hh"
37 #include "base/trace.hh"
38 #include "debug/TokenPort.hh"
41 TokenRequestPort::bind(Port
&peer
)
43 RequestPort::bind(peer
);
47 TokenRequestPort::recvTokens(int num_tokens
)
49 panic_if(!tokenManager
, "TokenManager not set for %s.\n", name());
51 tokenManager
->recvTokens(num_tokens
);
55 TokenRequestPort::haveTokens(int num_tokens
)
57 panic_if(!tokenManager
, "TokenManager not set for %s.\n", name());
59 return tokenManager
->haveTokens(num_tokens
);
63 TokenRequestPort::acquireTokens(int num_tokens
)
65 panic_if(!tokenManager
, "TokenManager not set for %s.\n", name());
67 tokenManager
->acquireTokens(num_tokens
);
71 TokenRequestPort::setTokenManager(TokenManager
*_tokenManager
)
73 tokenManager
= _tokenManager
;
77 TokenResponsePort::sendTokens(int num_tokens
)
79 fatal_if(!tokenRequestPort
, "Tried sendTokens to non-token requestor!\n");
81 // Send tokens to a requestor
82 tokenRequestPort
->recvTokens(num_tokens
);
86 TokenResponsePort::bind(Port
& peer
)
88 // TokenResponsePort is allowed to bind to either TokenRequestPort or a
89 // RequestPort as fallback. If the type is a RequestPort, tokenRequestPort
90 // is set to nullptr to indicate tokens should not be exchanged.
91 auto *token_request_port
= dynamic_cast<TokenRequestPort
*>(&peer
);
92 auto *request_port
= dynamic_cast<RequestPort
*>(&peer
);
93 if (!token_request_port
&& !request_port
) {
94 fatal("Attempt to bind port %s to unsupported response port %s.",
96 } else if (token_request_port
) {
97 // response port keeps track of the request port
98 tokenRequestPort
= token_request_port
;
100 // request port also keeps track of response port
101 tokenRequestPort
->bind(*this);
102 } else if (request_port
) {
103 tokenRequestPort
= nullptr;
108 TokenResponsePort::unbind()
110 ResponsePort::responderUnbind();
111 tokenRequestPort
= nullptr;
115 TokenResponsePort::recvRespRetry()
117 // fallback to QueuedResponsePort-like impl for now
118 panic_if(respQueue
.empty(),
119 "Attempted to retry a response when no retry was queued!\n");
121 PacketPtr pkt
= respQueue
.front();
122 bool success
= ResponsePort::sendTimingResp(pkt
);
125 respQueue
.pop_front();
130 TokenResponsePort::sendTimingResp(PacketPtr pkt
)
132 bool success
= ResponsePort::sendTimingResp(pkt
);
135 respQueue
.push_back(pkt
);
141 TokenManager::TokenManager(int init_tokens
)
143 availableTokens
= init_tokens
;
144 maxTokens
= init_tokens
;
148 TokenManager::getMaxTokenCount() const
154 TokenManager::recvTokens(int num_tokens
)
156 availableTokens
+= num_tokens
;
158 DPRINTF(TokenPort
, "Received %d tokens, have %d\n",
159 num_tokens
, availableTokens
);
161 panic_if(availableTokens
> maxTokens
,
162 "More tokens available than the maximum after recvTokens!\n");
166 TokenManager::haveTokens(int num_tokens
)
168 return (availableTokens
>= num_tokens
);
172 TokenManager::acquireTokens(int num_tokens
)
174 panic_if(!haveTokens(num_tokens
),
175 "Attempted to acquire more tokens than are available!\n");
177 availableTokens
-= num_tokens
;
179 DPRINTF(TokenPort
, "Acquired %d tokens, have %d\n",
180 num_tokens
, availableTokens
);