/* * Copyright (c) 2019, University of Kaiserslautern * All rights reserved. * * 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: Lukas Steiner */ #include "BankMachine.h" BankMachine::BankMachine(SchedulerIF *scheduler, CheckerIF *checker, Bank bank) : scheduler(scheduler), checker(checker), bank(bank) {} sc_time BankMachine::startBankMachine() { if (currentPayload == nullptr) { currentPayload = scheduler->getNextRequest(bank, this); if (currentPayload == nullptr) return SC_ZERO_TIME; } sc_time delay; DramExtension extension = DramExtension::getExtension(currentPayload); if (currentState == BmState::Precharged) // row miss { delay = checker->delayToSatisfyConstraints(Command::ACT, bank); nextCommand = Command::ACT; nextRow = extension.getRow(); timeToSchedule = sc_time_stamp() + delay; } else if (currentState == BmState::Activated) { if (extension.getRow() == currentRow) // row hit { if (currentPayload->get_command() == TLM_READ_COMMAND) { delay = checker->delayToSatisfyConstraints(Command::RD, bank); nextCommand = Command::RD; timeToSchedule = sc_time_stamp() + delay; } else if (currentPayload->get_command() == TLM_WRITE_COMMAND) { delay = checker->delayToSatisfyConstraints(Command::WR, bank); nextCommand = Command::WR; timeToSchedule = sc_time_stamp() + delay; } else SC_REPORT_FATAL("BankMachine", "Wrong TLM command"); } else // row miss { delay = checker->delayToSatisfyConstraints(Command::PRE, bank); nextCommand = Command::PRE; nextRow = extension.getRow(); timeToSchedule = sc_time_stamp() + delay; } } return delay; } std::pair BankMachine::getNextCommand() { if (timeToSchedule == sc_time_stamp()) return std::pair(nextCommand, currentPayload); else return std::pair(Command::NOP, nullptr); } void BankMachine::updateState(Command command) { if (command == Command::ACT) { currentState = BmState::Activated; currentRow = nextRow; } else if (command == Command::PRE) currentState = BmState::Precharged; else if (command == Command::RD || command == Command::WR) currentPayload = nullptr; else SC_REPORT_FATAL("BankMachine", "Unknown phase"); } Row BankMachine::getOpenRow() { return currentRow; } BmState BankMachine::getState() { return currentState; }