dram_gen.cc revision 12811:269967d5b4e4
1/*
2 * Copyright (c) 2012-2013, 2016-2018 ARM Limited
3 * All rights reserved
4 *
5 * The license below extends only to copyright in the software and shall
6 * not be construed as granting a license to any other intellectual
7 * property including but not limited to intellectual property relating
8 * to a hardware implementation of the functionality of the software
9 * licensed here under.  You may use the software subject to the license
10 * terms below provided that you ensure that this notice is replicated
11 * unmodified and in its entirety in all distributions of the software,
12 * modified or unmodified, in source code or in binary form.
13 *
14 * Redistribution and use in source and binary forms, with or without
15 * modification, are permitted provided that the following conditions are
16 * met: redistributions of source code must retain the above copyright
17 * notice, this list of conditions and the following disclaimer;
18 * redistributions in binary form must reproduce the above copyright
19 * notice, this list of conditions and the following disclaimer in the
20 * documentation and/or other materials provided with the distribution;
21 * neither the name of the copyright holders nor the names of its
22 * contributors may be used to endorse or promote products derived from
23 * this software without specific prior written permission.
24 *
25 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
26 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
27 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
28 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
29 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
30 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
31 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
32 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
33 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
34 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
35 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36 *
37 * Authors: Thomas Grass
38 *          Andreas Hansson
39 *          Sascha Bischoff
40 *          Neha Agarwal
41 */
42
43#include "cpu/testers/traffic_gen/dram_gen.hh"
44
45#include <algorithm>
46
47#include "base/random.hh"
48#include "base/trace.hh"
49#include "debug/TrafficGen.hh"
50
51
52DramGen::DramGen(BaseTrafficGen &gen, Tick _duration,
53                 Addr start_addr, Addr end_addr, Addr _blocksize,
54                 Tick min_period, Tick max_period,
55                 uint8_t read_percent, Addr data_limit,
56                 unsigned int num_seq_pkts, unsigned int page_size,
57                 unsigned int nbr_of_banks_DRAM,
58                 unsigned int nbr_of_banks_util,
59                 unsigned int addr_mapping,
60                 unsigned int nbr_of_ranks)
61        : RandomGen(gen, _duration, start_addr, end_addr,
62          _blocksize, min_period, max_period, read_percent, data_limit),
63          numSeqPkts(num_seq_pkts), countNumSeqPkts(0), addr(0),
64          isRead(true), pageSize(page_size),
65          pageBits(floorLog2(page_size / _blocksize)),
66          bankBits(floorLog2(nbr_of_banks_DRAM)),
67          blockBits(floorLog2(_blocksize)),
68          nbrOfBanksDRAM(nbr_of_banks_DRAM),
69          nbrOfBanksUtil(nbr_of_banks_util), addrMapping(addr_mapping),
70          rankBits(floorLog2(nbr_of_ranks)),
71          nbrOfRanks(nbr_of_ranks)
72{
73    if (addrMapping != 1 && addrMapping != 0) {
74        addrMapping = 1;
75        warn("Unknown address mapping specified, using RoRaBaCoCh\n");
76    }
77
78    if (nbr_of_banks_util > nbr_of_banks_DRAM)
79        fatal("Attempting to use more banks (%d) than "
80              "what is available (%d)\n",
81              nbr_of_banks_util, nbr_of_banks_DRAM);
82}
83
84PacketPtr
85DramGen::getNextPacket()
86{
87    // if this is the first of the packets in series to be generated,
88    // start counting again
89    if (countNumSeqPkts == 0) {
90        countNumSeqPkts = numSeqPkts;
91
92        // choose if we generate a read or a write here
93        isRead = readPercent != 0 &&
94            (readPercent == 100 || random_mt.random(0, 100) < readPercent);
95
96        assert((readPercent == 0 && !isRead) ||
97               (readPercent == 100 && isRead) ||
98               readPercent != 100);
99
100        // pick a random bank
101        unsigned int new_bank =
102            random_mt.random<unsigned int>(0, nbrOfBanksUtil - 1);
103
104        // pick a random rank
105        unsigned int new_rank =
106            random_mt.random<unsigned int>(0, nbrOfRanks - 1);
107
108        // Generate the start address of the command series
109        // routine will update addr variable with bank, rank, and col
110        // bits updated for random traffic mode
111        genStartAddr(new_bank, new_rank);
112
113    } else {
114        // increment the column by one
115        if (addrMapping == 1)
116            // addrMapping=1: RoRaBaCoCh/RoRaBaChCo
117            // Simply increment addr by blocksize to increment
118            // the column by one
119            addr += blocksize;
120
121        else if (addrMapping == 0) {
122            // addrMapping=0: RoCoRaBaCh
123            // Explicity increment the column bits
124            unsigned int new_col = ((addr / blocksize /
125                                       nbrOfBanksDRAM / nbrOfRanks) %
126                                   (pageSize / blocksize)) + 1;
127            replaceBits(addr, blockBits + bankBits + rankBits + pageBits - 1,
128                        blockBits + bankBits + rankBits, new_col);
129        }
130    }
131
132    DPRINTF(TrafficGen, "DramGen::getNextPacket: %c to addr %x, "
133            "size %d, countNumSeqPkts: %d, numSeqPkts: %d\n",
134            isRead ? 'r' : 'w', addr, blocksize, countNumSeqPkts, numSeqPkts);
135
136    // create a new request packet
137    PacketPtr pkt = getPacket(addr, blocksize,
138                              isRead ? MemCmd::ReadReq : MemCmd::WriteReq);
139
140    // add the amount of data manipulated to the total
141    dataManipulated += blocksize;
142
143    // subtract the number of packets remained to be generated
144    --countNumSeqPkts;
145
146    // return the generated packet
147    return pkt;
148}
149
150void
151DramGen::genStartAddr(unsigned int new_bank, unsigned int new_rank)
152{
153    // start by picking a random address in the range
154    addr = random_mt.random<Addr>(startAddr, endAddr - 1);
155
156    // round down to start address of a block, i.e. a DRAM burst
157    addr -= addr % blocksize;
158
159    // insert the bank bits at the right spot, and align the
160    // address to achieve the required hit length, this involves
161    // finding the appropriate start address such that all
162    // sequential packets target successive columns in the same
163    // page
164
165    // for example, if we have a stride size of 192B, which means
166    // for LPDDR3 where burstsize = 32B we have numSeqPkts = 6,
167    // the address generated previously can be such that these
168    // 192B cross the page boundary, hence it needs to be aligned
169    // so that they all belong to the same page for page hit
170    unsigned int columns_per_page = pageSize / blocksize;
171
172    // pick a random column, but ensure that there is room for
173    // numSeqPkts sequential columns in the same page
174    unsigned int new_col =
175        random_mt.random<unsigned int>(0, columns_per_page - numSeqPkts);
176
177    if (addrMapping == 1) {
178        // addrMapping=1: RoRaBaCoCh/RoRaBaChCo
179        // Block bits, then page bits, then bank bits, then rank bits
180        replaceBits(addr, blockBits + pageBits + bankBits - 1,
181                    blockBits + pageBits, new_bank);
182        replaceBits(addr, blockBits + pageBits - 1, blockBits, new_col);
183        if (rankBits != 0) {
184            replaceBits(addr, blockBits + pageBits + bankBits +rankBits - 1,
185                        blockBits + pageBits + bankBits, new_rank);
186        }
187    } else if (addrMapping == 0) {
188        // addrMapping=0: RoCoRaBaCh
189        // Block bits, then bank bits, then rank bits, then page bits
190        replaceBits(addr, blockBits + bankBits - 1, blockBits, new_bank);
191        replaceBits(addr, blockBits + bankBits + rankBits + pageBits - 1,
192                    blockBits + bankBits + rankBits, new_col);
193        if (rankBits != 0) {
194            replaceBits(addr, blockBits + bankBits + rankBits - 1,
195                        blockBits + bankBits, new_rank);
196        }
197    }
198}
199