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.
33 * Authors: Matthew Poremba
37 #include "mem/token_port.hh"
39 #include "base/trace.hh"
40 #include "debug/TokenPort.hh"
43 TokenMasterPort::bind(Port
&peer
)
45 MasterPort::bind(peer
);
49 TokenMasterPort::recvTokens(int num_tokens
)
51 panic_if(!tokenManager
, "TokenManager not set for %s.\n", name());
53 tokenManager
->recvTokens(num_tokens
);
57 TokenMasterPort::haveTokens(int num_tokens
)
59 panic_if(!tokenManager
, "TokenManager not set for %s.\n", name());
61 return tokenManager
->haveTokens(num_tokens
);
65 TokenMasterPort::acquireTokens(int num_tokens
)
67 panic_if(!tokenManager
, "TokenManager not set for %s.\n", name());
69 tokenManager
->acquireTokens(num_tokens
);
73 TokenMasterPort::setTokenManager(TokenManager
*_tokenManager
)
75 tokenManager
= _tokenManager
;
79 TokenSlavePort::sendTokens(int num_tokens
)
81 fatal_if(!tokenMasterPort
, "Tried sendTokens to non-token master!\n");
83 // Send tokens to a master
84 tokenMasterPort
->recvTokens(num_tokens
);
88 TokenSlavePort::bind(Port
& peer
)
90 // TokenSlavePort is allowed to bind to either TokenMasterPort or a
91 // MasterPort as fallback. If the type is a MasterPort, tokenMasterPort
92 // is set to nullptr to indicate tokens should not be exchanged.
93 auto *token_master_port
= dynamic_cast<TokenMasterPort
*>(&peer
);
94 auto *master_port
= dynamic_cast<MasterPort
*>(&peer
);
95 if (!token_master_port
&& !master_port
) {
96 fatal("Attempt to bind port %s to unsupported slave port %s.",
98 } else if (token_master_port
) {
99 // slave port keeps track of the master port
100 tokenMasterPort
= token_master_port
;
102 // master port also keeps track of slave port
103 tokenMasterPort
->bind(*this);
104 } else if (master_port
) {
105 tokenMasterPort
= nullptr;
110 TokenSlavePort::unbind()
112 SlavePort::slaveUnbind();
113 tokenMasterPort
= nullptr;
117 TokenSlavePort::recvRespRetry()
119 // fallback to QueuedSlavePort-like impl for now
120 panic_if(respQueue
.empty(),
121 "Attempted to retry a response when no retry was queued!\n");
123 PacketPtr pkt
= respQueue
.front();
124 bool success
= SlavePort::sendTimingResp(pkt
);
127 respQueue
.pop_front();
132 TokenSlavePort::sendTimingResp(PacketPtr pkt
)
134 bool success
= SlavePort::sendTimingResp(pkt
);
137 respQueue
.push_back(pkt
);
143 TokenManager::TokenManager(int init_tokens
)
145 availableTokens
= init_tokens
;
146 maxTokens
= init_tokens
;
150 TokenManager::getMaxTokenCount() const
156 TokenManager::recvTokens(int num_tokens
)
158 availableTokens
+= num_tokens
;
160 DPRINTF(TokenPort
, "Received %d tokens, have %d\n",
161 num_tokens
, availableTokens
);
163 panic_if(availableTokens
> maxTokens
,
164 "More tokens available than the maximum after recvTokens!\n");
168 TokenManager::haveTokens(int num_tokens
)
170 return (availableTokens
>= num_tokens
);
174 TokenManager::acquireTokens(int num_tokens
)
176 panic_if(!haveTokens(num_tokens
),
177 "Attempted to acquire more tokens than are available!\n");
179 availableTokens
-= num_tokens
;
181 DPRINTF(TokenPort
, "Acquired %d tokens, have %d\n",
182 num_tokens
, availableTokens
);