blob: 3ca1abd3b7b09fe5699f458d0d63b6454bb0d3a6 [file] [log] [blame]
/*
* Copyright (c) 2016 Advanced Micro Devices, Inc.
* All rights reserved.
*
* For use for simulation and test purposes only
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* 3. Neither the name of the copyright holder nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Author: Matthew Poremba
*/
#include "mem/token_port.hh"
#include "base/trace.hh"
#include "debug/TokenPort.hh"
void
TokenMasterPort::recvTokens(int num_tokens)
{
panic_if(!tokenManager, "TokenManager not set for %s.\n", name());
tokenManager->recvTokens(num_tokens);
}
bool
TokenMasterPort::haveTokens(int num_tokens)
{
panic_if(!tokenManager, "TokenManager not set for %s.\n", name());
return tokenManager->haveTokens(num_tokens);
}
void
TokenMasterPort::acquireTokens(int num_tokens)
{
panic_if(!tokenManager, "TokenManager not set for %s.\n", name());
panic_if(!haveTokens(num_tokens),
"Attempted to acquire more tokens than are available!\n");
tokenManager->acquireTokens(num_tokens);
}
void
TokenMasterPort::bind(BaseSlavePort& slave_port)
{
MasterPort::bind(slave_port);
TokenSlavePort* cast_slave_port =
dynamic_cast<TokenSlavePort*>(&slave_port);
if (cast_slave_port != nullptr) {
_tokenSlavePort = cast_slave_port;
}
}
void
TokenMasterPort::setTokenManager(TokenManager *_tokenManager)
{
tokenManager = _tokenManager;
}
void
TokenSlavePort::sendTokens(int num_tokens)
{
// Send tokens to a master
if (_tokenMasterPort)
_tokenMasterPort->recvTokens(num_tokens);
}
void
TokenSlavePort::bind(MasterPort& master_port)
{
SlavePort::bind(master_port);
TokenMasterPort* cast_master_port =
dynamic_cast<TokenMasterPort*>(&master_port);
// if this port is compatible, then proceed with the binding
if (cast_master_port != nullptr) {
// slave port keeps track of the master port
_tokenMasterPort = cast_master_port;
}
}
void
TokenSlavePort::recvRespRetry()
{
// fallback to QueuedSlavePort-like impl for now
panic_if(respQueue.empty(),
"Attempted to retry a response when no retry was queued!\n");
PacketPtr pkt = respQueue.front();
bool success = SlavePort::sendTimingResp(pkt);
if (success) {
respQueue.pop_front();
}
}
bool
TokenSlavePort::sendTimingResp(PacketPtr pkt)
{
bool success = SlavePort::sendTimingResp(pkt);
if (!success) {
respQueue.push_back(pkt);
}
return success;
}
TokenManager::TokenManager(int init_tokens)
{
availableTokens = init_tokens;
maxTokens = init_tokens;
}
int
TokenManager::getMaxTokenCount() const
{
return maxTokens;
}
void
TokenManager::recvTokens(int num_tokens)
{
availableTokens += num_tokens;
DPRINTF(TokenPort, "Received %d tokens, have %d\n",
num_tokens, availableTokens);
}
bool
TokenManager::haveTokens(int num_tokens)
{
return (availableTokens >= num_tokens);
}
void
TokenManager::acquireTokens(int num_tokens)
{
panic_if(!haveTokens(num_tokens),
"Attempted to acquire more tokens than are available!\n");
availableTokens -= num_tokens;
DPRINTF(TokenPort, "Acquired %d tokens, have %d\n",
num_tokens, availableTokens);
}