summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--configs/dram/sweep.py37
-rw-r--r--src/cpu/testers/traffic_gen/generators.cc194
-rw-r--r--src/cpu/testers/traffic_gen/generators.hh99
-rw-r--r--src/cpu/testers/traffic_gen/traffic_gen.cc52
4 files changed, 318 insertions, 64 deletions
diff --git a/configs/dram/sweep.py b/configs/dram/sweep.py
index 9b7cfd35e..631d82e07 100644
--- a/configs/dram/sweep.py
+++ b/configs/dram/sweep.py
@@ -58,6 +58,20 @@ parser.add_option("--mem-type", type="choice", default="ddr3_1600_x64",
choices=MemConfig.mem_names(),
help = "type of memory to use")
+parser.add_option("--ranks", "-r", type="int", default=1,
+ help = "Number of ranks to iterate across")
+
+parser.add_option("--rd_perc", type="int", default=100,
+ help = "Percentage of read commands")
+
+parser.add_option("--mode", type="choice", default="DRAM",
+ choices=["DRAM", "DRAM_ROTATE"],
+ help = "DRAM: Random traffic; \
+ DRAM_ROTATE: Traffic rotating across banks and ranks")
+
+parser.add_option("--addr_map", type="int", default=1,
+ help = "0: RoCoRaBaCh; 1: RoRaBaCoCh/RoRaBaChCo")
+
(options, args) = parser.parse_args()
if args:
@@ -89,8 +103,17 @@ MemConfig.config_mem(options, system)
if not isinstance(system.mem_ctrls[0], m5.objects.DRAMCtrl):
fatal("This script assumes the memory is a DRAMCtrl subclass")
-# for now the generator assumes a single rank
-system.mem_ctrls[0].ranks_per_channel = 1
+# Set number of ranks based on input argument; default is 1 rank
+system.mem_ctrls[0].ranks_per_channel = options.ranks
+
+# Set the address mapping based on input argument
+# Default to RoRaBaCoCh
+if options.addr_map == 0:
+ system.mem_ctrls[0].addr_mapping = "RoCoRaBaCh"
+elif options.addr_map == 1:
+ system.mem_ctrls[0].addr_mapping = "RoRaBaCoCh"
+else:
+ fatal("Did not specify a valid address map argument")
# stay in each state for 0.25 ms, long enough to warm things up, and
# short enough to avoid hitting a refresh
@@ -134,10 +157,12 @@ max_stride = min(512, page_size)
nxt_state = 0
for bank in range(1, nbr_banks + 1):
for stride_size in range(burst_size, max_stride + 1, burst_size):
- cfg_file.write("STATE %d %d DRAM 100 0 %d "
- "%d %d %d %d %d %d %d %d 1\n" %
- (nxt_state, period, max_addr, burst_size, itt, itt, 0,
- stride_size, page_size, nbr_banks, bank))
+ cfg_file.write("STATE %d %d %s %d 0 %d %d "
+ "%d %d %d %d %d %d %d %d %d\n" %
+ (nxt_state, period, options.mode, options.rd_perc,
+ max_addr, burst_size, itt, itt, 0, stride_size,
+ page_size, nbr_banks, bank, options.addr_map,
+ options.ranks))
nxt_state = nxt_state + 1
cfg_file.write("INIT 0\n")
diff --git a/src/cpu/testers/traffic_gen/generators.cc b/src/cpu/testers/traffic_gen/generators.cc
index 135765fce..5e19384bc 100644
--- a/src/cpu/testers/traffic_gen/generators.cc
+++ b/src/cpu/testers/traffic_gen/generators.cc
@@ -190,56 +190,33 @@ DramGen::getNextPacket()
(readPercent == 100 && isRead) ||
readPercent != 100);
- // start by picking a random address in the range
- addr = random_mt.random(startAddr, endAddr - 1);
-
- // round down to start address of a block, i.e. a DRAM burst
- addr -= addr % blocksize;
-
// pick a random bank
unsigned int new_bank =
random_mt.random<unsigned int>(0, nbrOfBanksUtil - 1);
- // next, inser the bank bits at the right spot, and align the
- // address to achieve the required hit length, this involves
- // finding the appropriate start address such that all
- // sequential packets target successive columns in the same
- // page
-
- // for example, if we have a stride size of 192B, which means
- // for LPDDR3 where burstsize = 32B we have numSeqPkts = 6,
- // the address generated previously can be such that these
- // 192B cross the page boundary, hence it needs to be aligned
- // so that they all belong to the same page for page hit
- unsigned int columns_per_page = pageSize / blocksize;
-
- // pick a random column, but ensure that there is room for
- // numSeqPkts sequential columns in the same page
- unsigned int new_col =
- random_mt.random<unsigned int>(0, columns_per_page - numSeqPkts);
-
- if (addrMapping == 1) {
- // assuming block bits, then page bits, then bank bits
- replaceBits(addr, blockBits + pageBits + bankBits - 1,
- blockBits + pageBits, new_bank);
- replaceBits(addr, blockBits + pageBits - 1, blockBits, new_col);
- } else if (addrMapping == 0) {
- // assuming bank bits in the bottom
- replaceBits(addr, blockBits + bankBits - 1, blockBits, new_bank);
- replaceBits(addr, blockBits + bankBits + pageBits - 1,
- blockBits + bankBits, new_col);
- }
+ // pick a random rank
+ unsigned int new_rank =
+ random_mt.random<unsigned int>(0, nbrOfRanks - 1);
+
+ // Generate the start address of the command series
+ // routine will update addr variable with bank, rank, and col
+ // bits updated for random traffic mode
+ genStartAddr(new_bank, new_rank);
+
} else {
// increment the column by one
if (addrMapping == 1)
- // column bits in the bottom, so just add a block
+ // addrMapping=1: RoRaBaCoCh/RoRaBaChCo
+ // Simply increment addr by blocksize to increment the column by one
addr += blocksize;
+
else if (addrMapping == 0) {
- // column bits are above the bank bits, so increment the column bits
- unsigned int new_col = ((addr / blocksize / nbrOfBanksDRAM) %
+ // addrMapping=0: RoCoRaBaCh
+ // Explicity increment the column bits
+ unsigned int new_col = ((addr / blocksize / nbrOfBanksDRAM / nbrOfRanks) %
(pageSize / blocksize)) + 1;
- replaceBits(addr, blockBits + bankBits + pageBits - 1,
- blockBits + bankBits, new_col);
+ replaceBits(addr, blockBits + bankBits + rankBits + pageBits - 1,
+ blockBits + bankBits + rankBits, new_col);
}
}
@@ -261,6 +238,143 @@ DramGen::getNextPacket()
return pkt;
}
+PacketPtr
+DramRotGen::getNextPacket()
+{
+ // if this is the first of the packets in series to be generated,
+ // start counting again
+ if (countNumSeqPkts == 0) {
+ countNumSeqPkts = numSeqPkts;
+
+ // choose if we generate a read or a write here
+ if (readPercent == 50) {
+ if ((nextSeqCount % nbrOfBanksUtil) == 0) {
+ // Change type after all banks have been rotated
+ // Otherwise, keep current value
+ isRead = !isRead;
+ }
+ } else {
+ // Set randomly based on percentage
+ isRead = readPercent != 0;
+ }
+
+ assert((readPercent == 0 && !isRead) ||
+ (readPercent == 100 && isRead) ||
+ readPercent != 100);
+
+ // Overwrite random bank value
+ // Rotate across banks
+ unsigned int new_bank = nextSeqCount % nbrOfBanksUtil;
+
+ // Overwrite random rank value
+ // Will rotate to the next rank after rotating through all banks,
+ // for each specified command type.
+
+ // Use modular function to ensure that calculated rank is within
+ // system limits after state transition
+ unsigned int new_rank = (nextSeqCount / maxSeqCountPerRank) %
+ nbrOfRanks;
+
+ // Increment nextSeqCount
+ // Roll back to 0 after completing a full rotation across
+ // banks, command type, and ranks
+ nextSeqCount = (nextSeqCount + 1) %
+ (nbrOfRanks * maxSeqCountPerRank);
+
+ DPRINTF(TrafficGen, "DramRotGen::getNextPacket nextSeqCount: %d "
+ "new_rank: %d new_bank: %d\n",
+ nextSeqCount, new_rank, new_bank);
+
+ // Generate the start address of the command series
+ // routine will update addr variable with bank, rank, and col
+ // bits updated for rotation scheme
+ genStartAddr(new_bank, new_rank);
+
+ } else {
+ // increment the column by one
+ if (addrMapping == 1)
+ // addrMapping=1: RoRaBaCoCh/RoRaBaChCo
+ // Simply increment addr by blocksize to increment the column by one
+ addr += blocksize;
+
+ else if (addrMapping == 0) {
+ // addrMapping=0: RoCoRaBaCh
+ // Explicity increment the column bits
+ unsigned int new_col = ((addr / blocksize / nbrOfBanksDRAM / nbrOfRanks) %
+ (pageSize / blocksize)) + 1;
+ replaceBits(addr, blockBits + bankBits + rankBits + pageBits - 1,
+ blockBits + bankBits + rankBits, new_col);
+ }
+ }
+
+ DPRINTF(TrafficGen, "DramRotGen::getNextPacket: %c to addr %x, "
+ "size %d, countNumSeqPkts: %d, numSeqPkts: %d\n",
+ isRead ? 'r' : 'w', addr, blocksize, countNumSeqPkts, numSeqPkts);
+
+ // create a new request packet
+ PacketPtr pkt = getPacket(addr, blocksize,
+ isRead ? MemCmd::ReadReq : MemCmd::WriteReq);
+
+ // add the amount of data manipulated to the total
+ dataManipulated += blocksize;
+
+ // subtract the number of packets remained to be generated
+ --countNumSeqPkts;
+
+ // return the generated packet
+ return pkt;
+}
+
+void
+DramGen::genStartAddr(unsigned int new_bank, unsigned int new_rank)
+{
+ // start by picking a random address in the range
+ addr = random_mt.random<Addr>(startAddr, endAddr - 1);
+
+ // round down to start address of a block, i.e. a DRAM burst
+ addr -= addr % blocksize;
+
+ // insert the bank bits at the right spot, and align the
+ // address to achieve the required hit length, this involves
+ // finding the appropriate start address such that all
+ // sequential packets target successive columns in the same
+ // page
+
+ // for example, if we have a stride size of 192B, which means
+ // for LPDDR3 where burstsize = 32B we have numSeqPkts = 6,
+ // the address generated previously can be such that these
+ // 192B cross the page boundary, hence it needs to be aligned
+ // so that they all belong to the same page for page hit
+ unsigned int columns_per_page = pageSize / blocksize;
+
+ // pick a random column, but ensure that there is room for
+ // numSeqPkts sequential columns in the same page
+ unsigned int new_col =
+ random_mt.random<unsigned int>(0, columns_per_page - numSeqPkts);
+
+ if (addrMapping == 1) {
+ // addrMapping=1: RoRaBaCoCh/RoRaBaChCo
+ // Block bits, then page bits, then bank bits, then rank bits
+ replaceBits(addr, blockBits + pageBits + bankBits - 1,
+ blockBits + pageBits, new_bank);
+ replaceBits(addr, blockBits + pageBits - 1, blockBits, new_col);
+ if (rankBits != 0) {
+ replaceBits(addr, blockBits + pageBits + bankBits +rankBits - 1,
+ blockBits + pageBits + bankBits, new_rank);
+ }
+ } else if (addrMapping == 0) {
+ // addrMapping=0: RoCoRaBaCh
+ // Block bits, then bank bits, then rank bits, then page bits
+ replaceBits(addr, blockBits + bankBits - 1, blockBits, new_bank);
+ replaceBits(addr, blockBits + bankBits + rankBits + pageBits - 1,
+ blockBits + bankBits + rankBits, new_col);
+ if (rankBits != 0) {
+ replaceBits(addr, blockBits + bankBits + rankBits - 1,
+ blockBits + bankBits, new_rank);
+ }
+ }
+}
+
Tick
RandomGen::nextPacketTick(bool elastic, Tick delay) const
{
diff --git a/src/cpu/testers/traffic_gen/generators.hh b/src/cpu/testers/traffic_gen/generators.hh
index a3b7e005a..5604856a9 100644
--- a/src/cpu/testers/traffic_gen/generators.hh
+++ b/src/cpu/testers/traffic_gen/generators.hh
@@ -310,7 +310,7 @@ class RandomGen : public BaseGen
/**
* DRAM specific generator is for issuing request with variable page
* hit length and bank utilization. Currently assumes a single
- * channel, single rank configuration.
+ * channel configuration.
*/
class DramGen : public RandomGen
{
@@ -337,7 +337,7 @@ class DramGen : public RandomGen
* for N banks, we will use banks: 0->(N-1)
* @param addr_mapping Address mapping to be used,
* 0: RoCoRaBaCh, 1: RoRaBaCoCh/RoRaBaChCo
- * assumes single channel and single rank system
+ * assumes single channel system
*/
DramGen(const std::string& _name, MasterID master_id, Tick _duration,
Addr start_addr, Addr end_addr, Addr _blocksize,
@@ -345,7 +345,8 @@ class DramGen : public RandomGen
uint8_t read_percent, Addr data_limit,
unsigned int num_seq_pkts, unsigned int page_size,
unsigned int nbr_of_banks_DRAM, unsigned int nbr_of_banks_util,
- unsigned int addr_mapping)
+ unsigned int addr_mapping,
+ unsigned int nbr_of_ranks)
: RandomGen(_name, master_id, _duration, start_addr, end_addr,
_blocksize, min_period, max_period, read_percent, data_limit),
numSeqPkts(num_seq_pkts), countNumSeqPkts(0), addr(0),
@@ -354,7 +355,9 @@ class DramGen : public RandomGen
bankBits(floorLog2(nbr_of_banks_DRAM)),
blockBits(floorLog2(_blocksize)),
nbrOfBanksDRAM(nbr_of_banks_DRAM),
- nbrOfBanksUtil(nbr_of_banks_util), addrMapping(addr_mapping)
+ nbrOfBanksUtil(nbr_of_banks_util), addrMapping(addr_mapping),
+ rankBits(floorLog2(nbr_of_ranks)),
+ nbrOfRanks(nbr_of_ranks)
{
if (addrMapping != 1 && addrMapping != 0) {
addrMapping = 1;
@@ -364,7 +367,15 @@ class DramGen : public RandomGen
PacketPtr getNextPacket();
- private:
+ /** Insert bank, rank, and column bits into packed
+ * address to create address for 1st command in a
+ * series
+ * @param new_bank Bank number of next packet series
+ * @param new_rank Rank value of next packet series
+ */
+ void genStartAddr(unsigned int new_bank , unsigned int new_rank);
+
+ protected:
/** Number of sequential DRAM packets to be generated per cpu request */
const unsigned int numSeqPkts;
@@ -398,6 +409,84 @@ class DramGen : public RandomGen
/** Address mapping to be used */
unsigned int addrMapping;
+
+ /** Number of rank bits in DRAM address*/
+ const unsigned int rankBits;
+
+ /** Number of ranks to be utilized for a given configuration */
+ const unsigned int nbrOfRanks;
+
+};
+
+class DramRotGen : public DramGen
+{
+
+ public:
+
+ /**
+ * Create a DRAM address sequence generator.
+ * This sequence generator will rotate through:
+ * 1) Banks per rank
+ * 2) Command type (if applicable)
+ * 3) Ranks per channel
+ *
+ * @param _name Name to use for status and debug
+ * @param master_id MasterID set on each request
+ * @param _duration duration of this state before transitioning
+ * @param start_addr Start address
+ * @param end_addr End address
+ * @param _blocksize Size used for transactions injected
+ * @param min_period Lower limit of random inter-transaction time
+ * @param max_period Upper limit of random inter-transaction time
+ * @param read_percent Percent of transactions that are reads
+ * @param data_limit Upper limit on how much data to read/write
+ * @param num_seq_pkts Number of packets per stride, each of _blocksize
+ * @param page_size Page size (bytes) used in the DRAM
+ * @param nbr_of_banks_DRAM Total number of banks in DRAM
+ * @param nbr_of_banks_util Number of banks to utilized,
+ * for N banks, we will use banks: 0->(N-1)
+ * @param nbr_of_ranks Number of ranks utilized,
+ * @param addr_mapping Address mapping to be used,
+ * 0: RoCoRaBaCh, 1: RoRaBaCoCh/RoRaBaChCo
+ * assumes single channel system
+ */
+ DramRotGen(const std::string& _name, MasterID master_id, Tick _duration,
+ Addr start_addr, Addr end_addr, Addr _blocksize,
+ Tick min_period, Tick max_period,
+ uint8_t read_percent, Addr data_limit,
+ unsigned int num_seq_pkts, unsigned int page_size,
+ unsigned int nbr_of_banks_DRAM, unsigned int nbr_of_banks_util,
+ unsigned int addr_mapping,
+ unsigned int nbr_of_ranks,
+ unsigned int max_seq_count_per_rank)
+ : DramGen(_name, master_id, _duration, start_addr, end_addr,
+ _blocksize, min_period, max_period, read_percent, data_limit,
+ num_seq_pkts, page_size, nbr_of_banks_DRAM,
+ nbr_of_banks_util, addr_mapping,
+ nbr_of_ranks),
+ maxSeqCountPerRank(max_seq_count_per_rank),
+ nextSeqCount(0)
+ {
+ // Rotating traffic generation can only support a read
+ // percentage of 0, 50, or 100
+ if (readPercent != 50 && readPercent != 100 && readPercent != 0) {
+ fatal("%s: Unsupported read percentage for DramRotGen: %d",
+ _name, readPercent);
+ }
+ }
+
+ PacketPtr getNextPacket();
+
+ private:
+ /** Number of command series issued before the rank is
+ changed. Should rotate to the next rank after rorating
+ throughall the banks for each specified command type */
+ const unsigned int maxSeqCountPerRank;
+
+ /** Next packet series count used to set rank and bank,
+ and update isRead Incremented at the start of a new
+ packet series */
+ unsigned int nextSeqCount;
};
/**
diff --git a/src/cpu/testers/traffic_gen/traffic_gen.cc b/src/cpu/testers/traffic_gen/traffic_gen.cc
index f865a00b1..9eee7a119 100644
--- a/src/cpu/testers/traffic_gen/traffic_gen.cc
+++ b/src/cpu/testers/traffic_gen/traffic_gen.cc
@@ -268,7 +268,7 @@ TrafficGen::parseConfig()
states[id] = new IdleGen(name(), masterID, duration);
DPRINTF(TrafficGen, "State: %d IdleGen\n", id);
} else if (mode == "LINEAR" || mode == "RANDOM" ||
- mode == "DRAM") {
+ mode == "DRAM" || mode == "DRAM_ROTATE") {
uint32_t read_percent;
Addr start_addr;
Addr end_addr;
@@ -311,7 +311,7 @@ TrafficGen::parseConfig()
min_period, max_period,
read_percent, data_limit);
DPRINTF(TrafficGen, "State: %d RandomGen\n", id);
- } else if (mode == "DRAM") {
+ } else if (mode == "DRAM" || mode == "DRAM_ROTATE") {
// stride size (bytes) of the request for achieving
// required hit length
unsigned int stride_size;
@@ -319,9 +319,11 @@ TrafficGen::parseConfig()
unsigned int nbr_of_banks_DRAM;
unsigned int nbr_of_banks_util;
unsigned int addr_mapping;
+ unsigned int nbr_of_ranks;
is >> stride_size >> page_size >> nbr_of_banks_DRAM >>
- nbr_of_banks_util >> addr_mapping;
+ nbr_of_banks_util >> addr_mapping >>
+ nbr_of_ranks;
if (stride_size > page_size)
warn("DRAM generator stride size (%d) is greater "
@@ -349,16 +351,40 @@ TrafficGen::parseConfig()
stride_size, blocksize, num_seq_pkts);
}
- states[id] = new DramGen(name(), masterID,
- duration, start_addr,
- end_addr, blocksize,
- min_period, max_period,
- read_percent, data_limit,
- num_seq_pkts, page_size,
- nbr_of_banks_DRAM,
- nbr_of_banks_util,
- addr_mapping);
- DPRINTF(TrafficGen, "State: %d DramGen\n", id);
+ if (mode == "DRAM") {
+ states[id] = new DramGen(name(), masterID,
+ duration, start_addr,
+ end_addr, blocksize,
+ min_period, max_period,
+ read_percent, data_limit,
+ num_seq_pkts, page_size,
+ nbr_of_banks_DRAM,
+ nbr_of_banks_util,
+ addr_mapping,
+ nbr_of_ranks);
+ DPRINTF(TrafficGen, "State: %d DramGen\n", id);
+ } else {
+ // Will rotate to the next rank after rotating
+ // through all banks, for each command type.
+ // In the 50% read case, series will be issued
+ // for both RD & WR before the rank in incremented
+ unsigned int max_seq_count_per_rank =
+ (read_percent == 50) ? nbr_of_banks_util * 2
+ : nbr_of_banks_util;
+
+ states[id] = new DramRotGen(name(), masterID,
+ duration, start_addr,
+ end_addr, blocksize,
+ min_period, max_period,
+ read_percent, data_limit,
+ num_seq_pkts, page_size,
+ nbr_of_banks_DRAM,
+ nbr_of_banks_util,
+ addr_mapping,
+ nbr_of_ranks,
+ max_seq_count_per_rank);
+ DPRINTF(TrafficGen, "State: %d DramRotGen\n", id);
+ }
}
} else {
fatal("%s: Unknown traffic generator mode: %s",