75a76
> #include "params/WriteAllocator.hh"
331a333,348
> * The writeAllocator drive optimizations for streaming writes.
> * It first determines whether a WriteReq MSHR should be delayed,
> * thus ensuring that we wait longer in cases when we are write
> * coalescing and allowing all the bytes of the line to be written
> * before the MSHR packet is sent downstream. This works in unison
> * with the tracking in the MSHR to check if the entire line is
> * written. The write mode also affects the behaviour on filling
> * any whole-line writes. Normally the cache allocates the line
> * when receiving the InvalidateResp, but after seeing enough
> * consecutive lines we switch to using the tempBlock, and thus
> * end up not allocating the line, and instead turning the
> * whole-line write into a writeback straight away.
> */
> WriteAllocator * const writeAllocator;
>
> /**
1163a1181,1312
> /**
> * The write allocator inspects write packets and detects streaming
> * patterns. The write allocator supports a single stream where writes
> * are expected to access consecutive locations and keeps track of
> * size of the area covered by the concecutive writes in byteCount.
> *
> * 1) When byteCount has surpassed the coallesceLimit the mode
> * switches from ALLOCATE to COALESCE where writes should be delayed
> * until the whole block is written at which point a single packet
> * (whole line write) can service them.
> *
> * 2) When byteCount has also exceeded the noAllocateLimit (whole
> * line) we switch to NO_ALLOCATE when writes should not allocate in
> * the cache but rather send a whole line write to the memory below.
> */
> class WriteAllocator : public SimObject {
> public:
> WriteAllocator(const WriteAllocatorParams *p) :
> SimObject(p),
> coalesceLimit(p->coalesce_limit * p->block_size),
> noAllocateLimit(p->no_allocate_limit * p->block_size),
> delayThreshold(p->delay_threshold)
> {
> reset();
> }
>
> /**
> * Should writes be coalesced? This is true if the mode is set to
> * NO_ALLOCATE.
> *
> * @return return true if the cache should coalesce writes.
> */
> bool coalesce() const {
> return mode != WriteMode::ALLOCATE;
> }
>
> /**
> * Should writes allocate?
> *
> * @return return true if the cache should not allocate for writes.
> */
> bool allocate() const {
> return mode != WriteMode::NO_ALLOCATE;
> }
>
> /**
> * Reset the write allocator state, meaning that it allocates for
> * writes and has not recorded any information about qualifying
> * writes that might trigger a switch to coalescing and later no
> * allocation.
> */
> void reset() {
> mode = WriteMode::ALLOCATE;
> byteCount = 0;
> nextAddr = 0;
> }
>
> /**
> * Access whether we need to delay the current write.
> *
> * @param blk_addr The block address the packet writes to
> * @return true if the current packet should be delayed
> */
> bool delay(Addr blk_addr) {
> if (delayCtr[blk_addr] > 0) {
> --delayCtr[blk_addr];
> return true;
> } else {
> return false;
> }
> }
>
> /**
> * Clear delay counter for the input block
> *
> * @param blk_addr The accessed cache block
> */
> void resetDelay(Addr blk_addr) {
> delayCtr.erase(blk_addr);
> }
>
> /**
> * Update the write mode based on the current write
> * packet. This method compares the packet's address with any
> * current stream, and updates the tracking and the mode
> * accordingly.
> *
> * @param write_addr Start address of the write request
> * @param write_size Size of the write request
> * @param blk_addr The block address that this packet writes to
> */
> void updateMode(Addr write_addr, unsigned write_size, Addr blk_addr);
>
> private:
> /**
> * The current mode for write coalescing and allocation, either
> * normal operation (ALLOCATE), write coalescing (COALESCE), or
> * write coalescing without allocation (NO_ALLOCATE).
> */
> enum class WriteMode : char {
> ALLOCATE,
> COALESCE,
> NO_ALLOCATE,
> };
> WriteMode mode;
>
> /** Address to match writes against to detect streams. */
> Addr nextAddr;
>
> /**
> * Bytes written contiguously. Saturating once we no longer
> * allocate.
> */
> uint32_t byteCount;
>
> /**
> * Limits for when to switch between the different write modes.
> */
> const uint32_t coalesceLimit;
> const uint32_t noAllocateLimit;
> /**
> * The number of times the allocator will delay an WriteReq MSHR.
> */
> const uint32_t delayThreshold;
>
> /**
> * Keep track of the number of times the allocator has delayed an
> * WriteReq MSHR.
> */
> std::unordered_map<Addr, Counter> delayCtr;
> };
>