mem: Add support for multi-channel DRAM configurations
This patch adds support for multi-channel instances of the DRAM controller model by stripping away the channel bits in the address decoding. The patch relies on the availiability of address interleaving and, at this time, it is up to the user to configure the interleaving appropriately. At the moment it is assumed that the channel interleaving bits are immediately following the column bits (smallest sensible interleaving). Convenience methods for building multi-channel configurations will be added later.
This commit is contained in:
parent
1a58362e25
commit
3ba131f4d5
|
@ -80,6 +80,10 @@ class SimpleDRAM(AbstractMemory):
|
||||||
lines_per_rowbuffer = Param.Unsigned("Row buffer size in cache lines")
|
lines_per_rowbuffer = Param.Unsigned("Row buffer size in cache lines")
|
||||||
ranks_per_channel = Param.Unsigned("Number of ranks per channel")
|
ranks_per_channel = Param.Unsigned("Number of ranks per channel")
|
||||||
banks_per_rank = Param.Unsigned("Number of banks per rank")
|
banks_per_rank = Param.Unsigned("Number of banks per rank")
|
||||||
|
# only used for the address mapping as the controller by
|
||||||
|
# construction is a single channel and multiple controllers have
|
||||||
|
# to be instantiated for a multi-channel configuration
|
||||||
|
channels = Param.Unsigned(1, "Number of channels")
|
||||||
|
|
||||||
# timing behaviour and constraints - all in nanoseconds
|
# timing behaviour and constraints - all in nanoseconds
|
||||||
|
|
||||||
|
|
|
@ -57,7 +57,7 @@ SimpleDRAM::SimpleDRAM(const SimpleDRAMParams* p) :
|
||||||
bytesPerCacheLine(0),
|
bytesPerCacheLine(0),
|
||||||
linesPerRowBuffer(p->lines_per_rowbuffer),
|
linesPerRowBuffer(p->lines_per_rowbuffer),
|
||||||
ranksPerChannel(p->ranks_per_channel),
|
ranksPerChannel(p->ranks_per_channel),
|
||||||
banksPerRank(p->banks_per_rank), rowsPerBank(0),
|
banksPerRank(p->banks_per_rank), channels(p->channels), rowsPerBank(0),
|
||||||
readBufferSize(p->read_buffer_size),
|
readBufferSize(p->read_buffer_size),
|
||||||
writeBufferSize(p->write_buffer_size),
|
writeBufferSize(p->write_buffer_size),
|
||||||
writeThresholdPerc(p->write_thresh_perc),
|
writeThresholdPerc(p->write_thresh_perc),
|
||||||
|
@ -115,6 +115,23 @@ SimpleDRAM::init()
|
||||||
rowsPerBank = capacity / (bytesPerCacheLine * linesPerRowBuffer *
|
rowsPerBank = capacity / (bytesPerCacheLine * linesPerRowBuffer *
|
||||||
banksPerRank * ranksPerChannel);
|
banksPerRank * ranksPerChannel);
|
||||||
|
|
||||||
|
if (range.interleaved()) {
|
||||||
|
if (channels != range.stripes())
|
||||||
|
panic("%s has %d interleaved address stripes but %d channel(s)\n",
|
||||||
|
name(), range.stripes(), channels);
|
||||||
|
|
||||||
|
if (addrMapping == Enums::openmap) {
|
||||||
|
if (bytesPerCacheLine * linesPerRowBuffer !=
|
||||||
|
range.granularity()) {
|
||||||
|
panic("Interleaving of %s doesn't match open address map\n",
|
||||||
|
name());
|
||||||
|
}
|
||||||
|
} else if (addrMapping == Enums::closemap) {
|
||||||
|
if (bytesPerCacheLine != range.granularity())
|
||||||
|
panic("Interleaving of %s doesn't match closed address map\n",
|
||||||
|
name());
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -190,6 +207,11 @@ SimpleDRAM::decodeAddr(PacketPtr pkt)
|
||||||
// sequential cache lines occupy the same row
|
// sequential cache lines occupy the same row
|
||||||
addr = addr / linesPerRowBuffer;
|
addr = addr / linesPerRowBuffer;
|
||||||
|
|
||||||
|
// take out the channel part of the address, note that this has
|
||||||
|
// to match with how accesses are interleaved between the
|
||||||
|
// controllers in the address mapping
|
||||||
|
addr = addr / channels;
|
||||||
|
|
||||||
// after the column bits, we get the bank bits to interleave
|
// after the column bits, we get the bank bits to interleave
|
||||||
// over the banks
|
// over the banks
|
||||||
bank = addr % banksPerRank;
|
bank = addr % banksPerRank;
|
||||||
|
@ -207,6 +229,11 @@ SimpleDRAM::decodeAddr(PacketPtr pkt)
|
||||||
// optimise for closed page mode and utilise maximum
|
// optimise for closed page mode and utilise maximum
|
||||||
// parallelism of the DRAM (at the cost of power)
|
// parallelism of the DRAM (at the cost of power)
|
||||||
|
|
||||||
|
// take out the channel part of the address, not that this has
|
||||||
|
// to match with how accesses are interleaved between the
|
||||||
|
// controllers in the address mapping
|
||||||
|
addr = addr / channels;
|
||||||
|
|
||||||
// start with the bank bits, as this provides the maximum
|
// start with the bank bits, as this provides the maximum
|
||||||
// opportunity for parallelism between requests
|
// opportunity for parallelism between requests
|
||||||
bank = addr % banksPerRank;
|
bank = addr % banksPerRank;
|
||||||
|
|
|
@ -378,6 +378,7 @@ class SimpleDRAM : public AbstractMemory
|
||||||
const uint32_t linesPerRowBuffer;
|
const uint32_t linesPerRowBuffer;
|
||||||
const uint32_t ranksPerChannel;
|
const uint32_t ranksPerChannel;
|
||||||
const uint32_t banksPerRank;
|
const uint32_t banksPerRank;
|
||||||
|
const uint32_t channels;
|
||||||
uint32_t rowsPerBank;
|
uint32_t rowsPerBank;
|
||||||
const uint32_t readBufferSize;
|
const uint32_t readBufferSize;
|
||||||
const uint32_t writeBufferSize;
|
const uint32_t writeBufferSize;
|
||||||
|
|
Loading…
Reference in a new issue