refactor(controller): clean up splitting logic
To support non-power-of-two burst lengths, clean up the logic on deciding which BL to use depending on the request size.
This commit is contained in:
@@ -33,6 +33,7 @@
|
||||
* Lukas Steiner
|
||||
* Derek Christ
|
||||
* Marco Mörz
|
||||
* Thomas Zimmermann
|
||||
*/
|
||||
|
||||
#include "Controller.h"
|
||||
@@ -101,8 +102,6 @@ Controller::Controller(const sc_module_name& name,
|
||||
windowSizeTime(simConfig.windowSize * memSpec.tCK),
|
||||
nextWindowEventTime(windowSizeTime),
|
||||
numberOfBeatsServed(memSpec.ranksPerChannel, 0),
|
||||
minBytesPerBurst(memSpec.defaultBytesPerBurst),
|
||||
maxBytesPerBurst(memSpec.maxBytesPerBurst),
|
||||
memoryManager(simConfig.storeMode == Config::StoreModeType::Store)
|
||||
{
|
||||
if (simConfig.databaseRecording && tlmRecorder != nullptr)
|
||||
@@ -604,9 +603,20 @@ void Controller::manageRequests(const sc_time& delay)
|
||||
assert((dataLength & (dataLength - 1)) == 0); // Data length must be a power of 2
|
||||
assert(address % dataLength == 0); // Check if naturally aligned
|
||||
|
||||
if ((address / maxBytesPerBurst) ==
|
||||
((address + transToAcquire.payload->get_data_length() - 1) / maxBytesPerBurst))
|
||||
// When to use which burstlength:
|
||||
// - If the default BL is enough to serve the request, use the default BL
|
||||
// - If the maximum BL is enough to serve the request, but not the default BL, use the
|
||||
// maximum BL
|
||||
// - If the maximum BL is not enough to to serve the request, split the transaction up
|
||||
// and use the maximum BL
|
||||
|
||||
bool splitTransactions = dataLength > memSpec.maxBytesPerBurst;
|
||||
if (!splitTransactions)
|
||||
{
|
||||
const unsigned burstLength = dataLength == memSpec.maxDataBytesPerBurst
|
||||
? memSpec.maxBurstLength
|
||||
: memSpec.defaultBurstLength;
|
||||
|
||||
// continuous block of data that can be fetched with a single burst
|
||||
DecodedAddress decodedAddress =
|
||||
addressDecoder.decodeAddress(transToAcquire.payload->get_address());
|
||||
@@ -619,7 +629,7 @@ void Controller::manageRequests(const sc_time& delay)
|
||||
Bank(decodedAddress.bank),
|
||||
Row(decodedAddress.row),
|
||||
Column(decodedAddress.column),
|
||||
(transToAcquire.payload->get_data_length() * 8) / memSpec.dataBusWidth);
|
||||
burstLength);
|
||||
|
||||
Rank rank = Rank(decodedAddress.rank);
|
||||
if (ranksNumberOfPayloads[rank] == 0)
|
||||
@@ -746,39 +756,30 @@ void Controller::createChildTranses(tlm::tlm_generic_payload& parentTrans)
|
||||
{
|
||||
std::vector<tlm_generic_payload*> childTranses;
|
||||
|
||||
uint64_t startAddress = parentTrans.get_address() & ~(maxBytesPerBurst - UINT64_C(1));
|
||||
unsigned char* startDataPtr = parentTrans.get_data_ptr();
|
||||
unsigned numChildTranses = parentTrans.get_data_length() / maxBytesPerBurst;
|
||||
const uint64_t startAddress = parentTrans.get_address();
|
||||
unsigned char* const startDataPtr = parentTrans.get_data_ptr();
|
||||
|
||||
const unsigned numChildTranses = parentTrans.get_data_length() / memSpec.maxDataBytesPerBurst;
|
||||
|
||||
for (unsigned childId = 0; childId < numChildTranses; childId++)
|
||||
{
|
||||
tlm_generic_payload* childTrans = memoryManager.allocate();
|
||||
childTrans->acquire();
|
||||
|
||||
// TODO:
|
||||
// The generated child transcations here are not naturally aligned.
|
||||
// Actually you would need to take into account the gaps introduced by the in-line metadata.
|
||||
// But this is not trivial.
|
||||
// This problem solves itself when the transaction splitting is moved out of the controller.
|
||||
childTrans->set_command(parentTrans.get_command());
|
||||
childTrans->set_address(startAddress + childId * maxBytesPerBurst);
|
||||
childTrans->set_data_length(maxBytesPerBurst);
|
||||
childTrans->set_data_ptr(startDataPtr + childId * maxBytesPerBurst);
|
||||
childTrans->set_address(startAddress + childId * memSpec.maxBytesPerBurst);
|
||||
childTrans->set_data_length(memSpec.maxDataBytesPerBurst);
|
||||
childTrans->set_data_ptr(startDataPtr + childId * memSpec.maxBytesPerBurst);
|
||||
|
||||
ChildExtension::setExtension(*childTrans, parentTrans);
|
||||
childTranses.push_back(childTrans);
|
||||
}
|
||||
|
||||
if (startAddress != parentTrans.get_address())
|
||||
{
|
||||
tlm_generic_payload& firstChildTrans = *childTranses.front();
|
||||
firstChildTrans.set_address(firstChildTrans.get_address() + minBytesPerBurst);
|
||||
firstChildTrans.set_data_ptr(firstChildTrans.get_data_ptr() + minBytesPerBurst);
|
||||
firstChildTrans.set_data_length(minBytesPerBurst);
|
||||
|
||||
tlm_generic_payload* lastChildTrans = memoryManager.allocate();
|
||||
lastChildTrans->acquire();
|
||||
lastChildTrans->set_command(parentTrans.get_command());
|
||||
lastChildTrans->set_address(startAddress + numChildTranses * maxBytesPerBurst);
|
||||
lastChildTrans->set_data_length(minBytesPerBurst);
|
||||
lastChildTrans->set_data_ptr(startDataPtr + numChildTranses * maxBytesPerBurst);
|
||||
ChildExtension::setExtension(*lastChildTrans, parentTrans);
|
||||
childTranses.push_back(lastChildTrans);
|
||||
}
|
||||
|
||||
for (auto* childTrans : childTranses)
|
||||
{
|
||||
DecodedAddress decodedAddress = addressDecoder.decodeAddress(childTrans->get_address());
|
||||
@@ -792,6 +793,7 @@ void Controller::createChildTranses(tlm::tlm_generic_payload& parentTrans)
|
||||
Column(decodedAddress.column),
|
||||
memSpec.maxBurstLength);
|
||||
}
|
||||
|
||||
nextChannelPayloadIDToAppend++;
|
||||
ParentExtension::setExtension(parentTrans, std::move(childTranses));
|
||||
}
|
||||
|
||||
@@ -32,6 +32,7 @@
|
||||
* Authors:
|
||||
* Lukas Steiner
|
||||
* Derek Christ
|
||||
* Thomas Zimmermann
|
||||
*/
|
||||
|
||||
#ifndef CONTROLLER_H
|
||||
@@ -145,9 +146,6 @@ private:
|
||||
|
||||
sc_core::sc_event beginReqEvent, endRespEvent, controllerEvent, dataResponseEvent;
|
||||
|
||||
const unsigned minBytesPerBurst;
|
||||
const unsigned maxBytesPerBurst;
|
||||
|
||||
MemoryManager memoryManager;
|
||||
|
||||
void createChildTranses(tlm::tlm_generic_payload& parentTrans);
|
||||
|
||||
Reference in New Issue
Block a user