Use think delay as miminum END_REQ delay

When the controller accepts requests in the same clock cycle as it
handles them, undeterministic simulations can occur as the outcome
depends on if the new request is accepted before the controllerMethod
is called or not.

Therefore, a minimum delay of one clock cylce should be used to always
handle request only in the next clock cycle, removing the disambiguity.
This commit is contained in:
2025-01-17 15:20:07 +01:00
parent 1b50709591
commit 007c55e878
5 changed files with 38 additions and 46 deletions

View File

@@ -313,3 +313,21 @@ An example follows.
- maximum number of active transactions per initiator (only applies to "Fifo" and "Reorder" arbiter policy)
- *RefreshManagement* (boolean)
- enable the sending of refresh management commands when the number of activates to one bank exceeds a certain management threshold (only supported in DDR5 and LPDDR5)
- *ArbitrationDelayFw* (unsigned int)
- number of clock cycles spent in forward arbitration to channel controllers
- *ArbitrationDelayBw* (unsigned int)
- number of clock cycles spent in backward arbitration to initiator
- *ThinkDelayFw* (unsigned int)
- minimum number of clock cycles between acceptance of a request to command issuance
- *ThinkDelayBw* (unsigned int)
- minimum number of clock cycles until response is forwarded to the arbiter
- *PhyDelayFw* (unsigned int)
- number of clock cycles between command issuance and occupation on the command/data bus
- *PhyDelayBw* (unsigned int)
- number of clock cycles between read data on the data bus and arrival in the channel controller
- *BlockingReadDelay* (unsigned int)
- constant number of clock cycles spent reading data in blocking mode
- **warning**: usage of blocking transport produces in inaccurate simulation results
- *BlockingWriteDelay* (unsigned int)
- constant number of clock cycles spent writing data in blocking mode
- **warning**: usage of blocking transport produces in inaccurate simulation results

View File

@@ -422,7 +422,7 @@ void Controller::controllerMethod()
scheduler->removeRequest(*trans);
manageRequests(config.thinkDelayFw);
respQueue->insertPayload(trans,
sc_time_stamp() + config.thinkDelayFw + config.phyDelayFw +
sc_time_stamp() + config.phyDelayFw +
memSpec.getIntervalOnDataStrobe(command, *trans).end +
config.phyDelayBw + config.thinkDelayBw);
@@ -435,7 +435,7 @@ void Controller::controllerMethod()
if (ranksNumberOfPayloads[rank] == 0)
powerDownManagers[rank]->triggerEntry();
sc_time fwDelay = config.thinkDelayFw + config.phyDelayFw;
sc_time fwDelay = config.phyDelayFw;
tlm_phase phase = command.toPhase();
iSocket->nb_transport_fw(*trans, phase, fwDelay);
}
@@ -501,8 +501,8 @@ Controller::nb_transport_fw(tlm_generic_payload& trans, tlm_phase& phase, sc_tim
if (phase == BEGIN_REQ)
{
transToAcquire.payload = &trans;
transToAcquire.arrival = sc_time_stamp() + delay;
beginReqEvent.notify(delay);
transToAcquire.arrival = sc_time_stamp() + delay + config.thinkDelayFw;
beginReqEvent.notify(delay + config.thinkDelayFw);
}
else if (phase == END_RESP)
{

View File

@@ -57,23 +57,14 @@ McConfig::McConfig(const Config::McConfig& config, const MemSpec& memSpec) :
powerDownPolicy(config.PowerDownPolicy.value_or(DEFAULT_POWER_DOWN_POLICY)),
maxActiveTransactions(config.MaxActiveTransactions.value_or(DEFAULT_MAX_ACTIVE_TRANSACTIONS)),
refreshManagement(config.RefreshManagement.value_or(DEFAULT_REFRESH_MANAGEMENT)),
arbitrationDelayFw(sc_core::sc_time(
config.ArbitrationDelayFw.value_or(DEFAULT_ARBITRATION_DELAY_FW_NS), sc_core::SC_NS)),
arbitrationDelayBw(sc_core::sc_time(
config.ArbitrationDelayBw.value_or(DEFAULT_ARBITRATION_DELAY_BW_NS), sc_core::SC_NS)),
thinkDelayFw(
sc_core::sc_time(config.ThinkDelayFw.value_or(DEFAULT_THINK_DELAY_FW_NS), sc_core::SC_NS)),
thinkDelayBw(
sc_core::sc_time(config.ThinkDelayBw.value_or(DEFAULT_THINK_DELAY_BW_NS), sc_core::SC_NS)),
phyDelayFw(
sc_core::sc_time(config.PhyDelayFw.value_or(DEFAULT_PHY_DELAY_FW_NS), sc_core::SC_NS)),
phyDelayBw(
sc_core::sc_time(config.PhyDelayBw.value_or(DEFAULT_PHY_DELAY_BW_NS), sc_core::SC_NS)),
blockingReadDelay(sc_core::sc_time(
config.BlockingReadDelay.value_or(DEFAULT_BLOCKING_READ_DELAY_NS), sc_core::SC_NS)),
blockingWriteDelay(sc_core::sc_time(
config.BlockingWriteDelay.value_or(DEFAULT_BLOCKING_WRITE_DELAY_NS), sc_core::SC_NS))
arbitrationDelayFw(config.ArbitrationDelayFw.value_or(DEFAULT_ARBITRATION_DELAY_FW) * memSpec.tCK),
arbitrationDelayBw(config.ArbitrationDelayBw.value_or(DEFAULT_ARBITRATION_DELAY_BW) * memSpec.tCK),
thinkDelayFw(config.ThinkDelayFw.value_or(DEFAULT_THINK_DELAY_FW) * memSpec.tCK),
thinkDelayBw(config.ThinkDelayBw.value_or(DEFAULT_THINK_DELAY_BW) * memSpec.tCK),
phyDelayFw(config.PhyDelayFw.value_or(DEFAULT_PHY_DELAY_FW) * memSpec.tCK),
phyDelayBw(config.PhyDelayBw.value_or(DEFAULT_PHY_DELAY_BW) * memSpec.tCK),
blockingReadDelay(config.BlockingReadDelay.value_or(DEFAULT_BLOCKING_READ_DELAY) * memSpec.tCK),
blockingWriteDelay(config.BlockingWriteDelay.value_or(DEFAULT_BLOCKING_WRITE_DELAY) * memSpec.tCK)
{
if (schedulerBuffer == Config::SchedulerBufferType::ReadWrite &&
config.RequestBufferSize.has_value())
@@ -115,18 +106,6 @@ McConfig::McConfig(const Config::McConfig& config, const MemSpec& memSpec) :
if (requestBufferSizeWrite < 1)
SC_REPORT_FATAL("Configuration", "Minimum request buffer size is 1!");
arbitrationDelayFw = std::round(arbitrationDelayFw / memSpec.tCK) * memSpec.tCK;
arbitrationDelayBw = std::round(arbitrationDelayBw / memSpec.tCK) * memSpec.tCK;
thinkDelayFw = std::round(thinkDelayFw / memSpec.tCK) * memSpec.tCK;
thinkDelayBw = std::round(thinkDelayBw / memSpec.tCK) * memSpec.tCK;
phyDelayFw = std::round(phyDelayFw / memSpec.tCK) * memSpec.tCK;
phyDelayBw = std::round(phyDelayBw / memSpec.tCK) * memSpec.tCK;
blockingReadDelay = std::round(blockingReadDelay / memSpec.tCK) * memSpec.tCK;
blockingWriteDelay = std::round(blockingWriteDelay / memSpec.tCK) * memSpec.tCK;
}
} // namespace DRAMSys

View File

@@ -100,14 +100,14 @@ struct McConfig
Config::PowerDownPolicyType::NoPowerDown;
static constexpr unsigned int DEFAULT_MAX_ACTIVE_TRANSACTIONS = 64;
static constexpr bool DEFAULT_REFRESH_MANAGEMENT = false;
static constexpr unsigned DEFAULT_ARBITRATION_DELAY_FW_NS = 0;
static constexpr unsigned DEFAULT_ARBITRATION_DELAY_BW_NS = 0;
static constexpr unsigned DEFAULT_THINK_DELAY_FW_NS = 0;
static constexpr unsigned DEFAULT_THINK_DELAY_BW_NS = 0;
static constexpr unsigned DEFAULT_PHY_DELAY_FW_NS = 0;
static constexpr unsigned DEFAULT_PHY_DELAY_BW_NS = 0;
static constexpr unsigned DEFAULT_BLOCKING_READ_DELAY_NS = 60;
static constexpr unsigned DEFAULT_BLOCKING_WRITE_DELAY_NS = 60;
static constexpr unsigned DEFAULT_ARBITRATION_DELAY_FW = 0;
static constexpr unsigned DEFAULT_ARBITRATION_DELAY_BW = 0;
static constexpr unsigned DEFAULT_THINK_DELAY_FW = 1;
static constexpr unsigned DEFAULT_THINK_DELAY_BW = 1;
static constexpr unsigned DEFAULT_PHY_DELAY_FW = 0;
static constexpr unsigned DEFAULT_PHY_DELAY_BW = 0;
static constexpr unsigned DEFAULT_BLOCKING_READ_DELAY = 60;
static constexpr unsigned DEFAULT_BLOCKING_WRITE_DELAY = 60;
};
} // namespace DRAMSys

View File

@@ -92,11 +92,6 @@ void RequestIssuer::sendNextRequest()
sendingTime -= sendingTime % clkPeriod;
}
if (sendingTime == lastEndRequest)
{
sendingTime += clkPeriod;
}
delay = sendingTime - sc_core::sc_time_stamp();
iSocket->nb_transport_fw(payload, phase, delay);