File banked_memory.h
File List > mem > banked_memory.h
Go to the documentation of this file
#pragma once
#include <simtix/mem.h>
#include <deque>
#include <string>
#include <vector>
namespace simtix {
namespace mem {
// Class: mem::BankedMemory::Impl
// The implementation class for BankedMemory.
class BankedMemory::Impl {
public:
explicit Impl(const std::string &name, const Param ¶m = kDefaultParam)
: stat_(name),
kBanks(param.kBanks),
kInterleaveGranularity(param.kInterleaveGranularity),
kLatencyCycles(param.kLatencyCycles),
name_(name),
bank_occupied_(param.kBanks, false) {
SimpleMemory::Param bank_param = {
.kSizeBytes = param.kSizeBytes / param.kBanks,
.kLatencyCycles = param.kLatencyCycles,
.kOutputFifoDepth = param.kOutputFifoDepth,
};
for (size_t i = 0; i < param.kBanks; i++) {
banks_.emplace_back(fmt::format("{}.bank[{}]", name, i), bank_param);
}
}
~Impl() = default;
protected:
struct Stat : stat::Group {
explicit Stat(const std::string &s)
: Group(s),
STAT(bank_conflict, "Number of bank conflicts", "N/A"),
STAT(bank_available, "Number of available banks when request is sent",
"N/A"),
STAT(total_write_requests,
"Total number of write requests send to banked memory", "N/A"),
STAT(total_read_requests,
"Total number of read requests send to banked memory", "N/A"),
STAT(forwarded_requests, "Number of forwarded requests", "N/A"),
STAT(total_requests, "Total number of requests send to banked memory",
"N/A"),
STAT(bank_utilization, "Bank utilization of banked memory", "N/A") {
total_requests = total_write_requests + total_read_requests;
bank_utilization = forwarded_requests / bank_available;
}
stat::Integer bank_conflict;
stat::Integer bank_available;
stat::Integer total_write_requests;
stat::Integer total_read_requests;
stat::Integer forwarded_requests;
stat::Formula<stat::Integer> total_requests;
stat::Formula<stat::Real> bank_utilization;
} stat_;
inline uint32_t ToBankIndex(uint64_t addr) const {
return (addr / kInterleaveGranularity) % kBanks;
}
inline uint64_t ToBankedAddrOffset(uint64_t addr) const {
return addr % kInterleaveGranularity;
}
inline uint64_t ToBankedAddr(uint64_t addr) const {
return addr / kBanks / kInterleaveGranularity * kInterleaveGranularity +
ToBankedAddrOffset(addr);
}
// Function: mem::BankedMemory::Impl::ForwardRequest
// Forward a memory request to a bank. Return false if the bank is occupied.
bool ForwardRequest(const Payload &payload, OnResp on_resp, bool is_write);
const size_t kBanks;
const uint32_t kInterleaveGranularity;
const uint32_t kLatencyCycles;
std::string name_;
std::deque<SimpleMemory> banks_;
std::vector<bool> bank_occupied_;
friend class BankedMemory;
};
} // namespace mem
} // namespace simtix