├── AddressMapping.cpp ├── AddressMapping.h ├── Bank.cpp ├── Bank.h ├── BankState.cpp ├── BankState.h ├── BusPacket.cpp ├── BusPacket.h ├── CSVWriter.h ├── Callback.h ├── ClockDomain.cpp ├── ClockDomain.h ├── CommandQueue.cpp ├── CommandQueue.h ├── DRAMSim.h ├── IniReader.cpp ├── IniReader.h ├── Makefile ├── MemoryController.cpp ├── MemoryController.h ├── MemorySystem.cpp ├── MemorySystem.h ├── MultiChannelMemorySystem.cpp ├── MultiChannelMemorySystem.h ├── PrintMacros.h ├── README.md ├── Rank.cpp ├── Rank.h ├── SimulatorObject.cpp ├── SimulatorObject.h ├── SystemConfiguration.h ├── TraceBasedSim.cpp ├── Transaction.cpp ├── Transaction.h ├── conf ├── DDR3_micron_32M_8B_x8_sg25E.ini ├── PCM_micron_16M_8B_x16_sg25E.ini ├── debug_config.ini ├── systemdram.ini └── systempcm.ini ├── rlt.vis ├── run.sh └── traces └── input /AddressMapping.cpp: -------------------------------------------------------------------------------- 1 | /********************************************************************************* 2 | * Copyright (c) 2010-2011, Elliott Cooper-Balis 3 | * Paul Rosenfeld 4 | * Bruce Jacob 5 | * University of Maryland 6 | * dramninjas [at] gmail [dot] com 7 | * All rights reserved. 8 | * 9 | * Redistribution and use in source and binary forms, with or without 10 | * modification, are permitted provided that the following conditions are met: 11 | * 12 | * * Redistributions of source code must retain the above copyright notice, 13 | * this list of conditions and the following disclaimer. 14 | * 15 | * * Redistributions in binary form must reproduce the above copyright notice, 16 | * this list of conditions and the following disclaimer in the documentation 17 | * and/or other materials provided with the distribution. 18 | * 19 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 20 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 21 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 22 | * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 23 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 25 | * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 26 | * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 27 | * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | *********************************************************************************/ 30 | #include "SystemConfiguration.h" 31 | #include "AddressMapping.h" 32 | 33 | namespace DRAMSim 34 | { 35 | 36 | void addressMapping(uint64_t physicalAddress, unsigned &newTransactionChan, unsigned &newTransactionRank, unsigned &newTransactionBank, unsigned &newTransactionRow, unsigned &newTransactionColumn, std::vectorallIniReaders) 37 | { 38 | //xf 39 | unsigned SystemType; 40 | uint64_t physicalAddr=0; 41 | if (physicalAddress < allIniReaders[TYPE_DRAM]->TOTAL_STORAGE<<20) 42 | { 43 | SystemType = TYPE_DRAM; 44 | physicalAddr = physicalAddress; 45 | } 46 | else if (physicalAddress >= (allIniReaders[TYPE_DRAM]->TOTAL_STORAGE<<20) && physicalAddress < ((allIniReaders[TYPE_DRAM]->TOTAL_STORAGE<<20) + (allIniReaders[TYPE_NVM]->TOTAL_STORAGE<<20))) 47 | { 48 | SystemType = TYPE_NVM; 49 | physicalAddr = physicalAddress - allIniReaders[TYPE_DRAM]->TOTAL_STORAGE; 50 | } 51 | else 52 | { 53 | ERROR("== Error - Unknown Physical Address, physical address is larger than total storage."); 54 | exit(-1); 55 | } 56 | newTransactionChan = SystemType; 57 | 58 | uint64_t tempA, tempB; 59 | unsigned transactionSize = (allIniReaders[SystemType]->JEDEC_DATA_BUS_BITS/8)*allIniReaders[SystemType]->BL; 60 | uint64_t transactionMask = transactionSize - 1; //ex: (64 bit bus width) x (8 Burst Length) - 1 = 64 bytes - 1 = 63 = 0x3f mask 61 | //unsigned channelBitWidth = dramsim_log2(NUM_CHANS); 62 | unsigned rankBitWidth = dramsim_log2(allIniReaders[SystemType]->NUM_RANKS); 63 | unsigned bankBitWidth = dramsim_log2(allIniReaders[SystemType]->NUM_BANKS); 64 | unsigned rowBitWidth = dramsim_log2(allIniReaders[SystemType]->NUM_ROWS); 65 | unsigned colBitWidth = dramsim_log2(allIniReaders[SystemType]->NUM_COLS); 66 | // this forces the alignment to the width of a single burst (64 bits = 8 bytes = 3 address bits for DDR parts) 67 | unsigned byteOffsetWidth = dramsim_log2((allIniReaders[SystemType]->JEDEC_DATA_BUS_BITS/8)); 68 | // Since we're assuming that a request is for BL*BUS_WIDTH, the bottom bits 69 | // of this address *should* be all zeros if it's not, issue a warning 70 | 71 | if ((physicalAddr & transactionMask) != 0) 72 | { 73 | //DEBUG("WARNING: address 0x"<>= byteOffsetWidth; 79 | 80 | // The next thing we have to consider is that when a request is made for a 81 | // we've taken into account the granulaity of a single burst by shifting 82 | // off the bottom 3 bits, but a transaction has to take into account the 83 | // burst length (i.e. the requests will be aligned to cache line sizes which 84 | // should be equal to transactionSize above). 85 | // 86 | // Since the column address increments internally on bursts, the bottom n 87 | // bits of the column (colLow) have to be zero in order to account for the 88 | // total size of the transaction. These n bits should be shifted off the 89 | // address and also subtracted from the total column width. 90 | // 91 | // I am having a hard time explaining the reasoning here, but it comes down 92 | // this: for a 64 byte transaction, the bottom 6 bits of the address must be 93 | // zero. These zero bits must be made up of the byte offset (3 bits) and also 94 | // from the bottom bits of the column 95 | // 96 | // For example: cowLowBits = log2(64bytes) - 3 bits = 3 bits 97 | unsigned colLowBitWidth = dramsim_log2(transactionSize) - byteOffsetWidth; 98 | 99 | physicalAddr >>= colLowBitWidth; 100 | unsigned colHighBitWidth = colBitWidth - colLowBitWidth; 101 | if (DEBUG_ADDR_MAP) 102 | { 103 | DEBUG("Bit widths: r:"<addressMappingScheme == Scheme1) 111 | { 112 | //chan:rank:row:col:bank 113 | tempA = physicalAddr; 114 | physicalAddr = physicalAddr >> bankBitWidth; 115 | tempB = physicalAddr << bankBitWidth; 116 | newTransactionBank = tempA ^ tempB; 117 | 118 | tempA = physicalAddr; 119 | physicalAddr = physicalAddr >> colHighBitWidth; 120 | tempB = physicalAddr << colHighBitWidth; 121 | newTransactionColumn = tempA ^ tempB; 122 | 123 | tempA = physicalAddr; 124 | physicalAddr = physicalAddr >> rowBitWidth; 125 | tempB = physicalAddr << rowBitWidth; 126 | newTransactionRow = tempA ^ tempB; 127 | 128 | tempA = physicalAddr; 129 | physicalAddr = physicalAddr >> rankBitWidth; 130 | tempB = physicalAddr << rankBitWidth; 131 | newTransactionRank = tempA ^ tempB; 132 | /* 133 | tempA = physicalAddr; 134 | physicalAddr = physicalAddr >> channelBitWidth; 135 | tempB = physicalAddr << channelBitWidth; 136 | newTransactionChan = tempA ^ tempB; 137 | */ 138 | } 139 | else if (allIniReaders[SystemType]->addressMappingScheme == Scheme2) 140 | { 141 | //chan:row:col:bank:rank 142 | tempA = physicalAddr; 143 | physicalAddr = physicalAddr >> rankBitWidth; 144 | tempB = physicalAddr << rankBitWidth; 145 | newTransactionRank = tempA ^ tempB; 146 | 147 | tempA = physicalAddr; 148 | physicalAddr = physicalAddr >> bankBitWidth; 149 | tempB = physicalAddr << bankBitWidth; 150 | newTransactionBank = tempA ^ tempB; 151 | 152 | tempA = physicalAddr; 153 | physicalAddr = physicalAddr >> colHighBitWidth; 154 | tempB = physicalAddr << colHighBitWidth; 155 | newTransactionColumn = tempA ^ tempB; 156 | 157 | tempA = physicalAddr; 158 | physicalAddr = physicalAddr >> rowBitWidth; 159 | tempB = physicalAddr << rowBitWidth; 160 | newTransactionRow = tempA ^ tempB; 161 | /* 162 | tempA = physicalAddr; 163 | physicalAddr = physicalAddr >> channelBitWidth; 164 | tempB = physicalAddr << channelBitWidth; 165 | newTransactionChan = tempA ^ tempB; 166 | */ 167 | } 168 | else if (allIniReaders[SystemType]->addressMappingScheme == Scheme3) 169 | { 170 | //chan:rank:bank:col:row 171 | tempA = physicalAddr; 172 | physicalAddr = physicalAddr >> rowBitWidth; 173 | tempB = physicalAddr << rowBitWidth; 174 | newTransactionRow = tempA ^ tempB; 175 | 176 | tempA = physicalAddr; 177 | physicalAddr = physicalAddr >> colHighBitWidth; 178 | tempB = physicalAddr << colHighBitWidth; 179 | newTransactionColumn = tempA ^ tempB; 180 | 181 | tempA = physicalAddr; 182 | physicalAddr = physicalAddr >> bankBitWidth; 183 | tempB = physicalAddr << bankBitWidth; 184 | newTransactionBank = tempA ^ tempB; 185 | 186 | tempA = physicalAddr; 187 | physicalAddr = physicalAddr >> rankBitWidth; 188 | tempB = physicalAddr << rankBitWidth; 189 | newTransactionRank = tempA ^ tempB; 190 | /* 191 | tempA = physicalAddr; 192 | physicalAddr = physicalAddr >> channelBitWidth; 193 | tempB = physicalAddr << channelBitWidth; 194 | newTransactionChan = tempA ^ tempB; 195 | */ 196 | } 197 | else if (allIniReaders[SystemType]->addressMappingScheme == Scheme4) 198 | { 199 | //chan:rank:bank:row:col 200 | tempA = physicalAddr; 201 | physicalAddr = physicalAddr >> colHighBitWidth; 202 | tempB = physicalAddr << colHighBitWidth; 203 | newTransactionColumn = tempA ^ tempB; 204 | 205 | tempA = physicalAddr; 206 | physicalAddr = physicalAddr >> rowBitWidth; 207 | tempB = physicalAddr << rowBitWidth; 208 | newTransactionRow = tempA ^ tempB; 209 | 210 | tempA = physicalAddr; 211 | physicalAddr = physicalAddr >> bankBitWidth; 212 | tempB = physicalAddr << bankBitWidth; 213 | newTransactionBank = tempA ^ tempB; 214 | 215 | tempA = physicalAddr; 216 | physicalAddr = physicalAddr >> rankBitWidth; 217 | tempB = physicalAddr << rankBitWidth; 218 | newTransactionRank = tempA ^ tempB; 219 | /* 220 | tempA = physicalAddr; 221 | physicalAddr = physicalAddr >> channelBitWidth; 222 | tempB = physicalAddr << channelBitWidth; 223 | newTransactionChan = tempA ^ tempB; 224 | */ 225 | } 226 | else if (allIniReaders[SystemType]->addressMappingScheme == Scheme5) 227 | { 228 | //chan:row:col:rank:bank 229 | 230 | tempA = physicalAddr; 231 | physicalAddr = physicalAddr >> bankBitWidth; 232 | tempB = physicalAddr << bankBitWidth; 233 | newTransactionBank = tempA ^ tempB; 234 | 235 | tempA = physicalAddr; 236 | physicalAddr = physicalAddr >> rankBitWidth; 237 | tempB = physicalAddr << rankBitWidth; 238 | newTransactionRank = tempA ^ tempB; 239 | 240 | tempA = physicalAddr; 241 | physicalAddr = physicalAddr >> colHighBitWidth; 242 | tempB = physicalAddr << colHighBitWidth; 243 | newTransactionColumn = tempA ^ tempB; 244 | 245 | tempA = physicalAddr; 246 | physicalAddr = physicalAddr >> rowBitWidth; 247 | tempB = physicalAddr << rowBitWidth; 248 | newTransactionRow = tempA ^ tempB; 249 | /* 250 | tempA = physicalAddr; 251 | physicalAddr = physicalAddr >> channelBitWidth; 252 | tempB = physicalAddr << channelBitWidth; 253 | newTransactionChan = tempA ^ tempB; 254 | */ 255 | 256 | } 257 | else if (allIniReaders[SystemType]->addressMappingScheme == Scheme6) 258 | { 259 | //chan:row:bank:rank:col 260 | 261 | tempA = physicalAddr; 262 | physicalAddr = physicalAddr >> colHighBitWidth; 263 | tempB = physicalAddr << colHighBitWidth; 264 | newTransactionColumn = tempA ^ tempB; 265 | 266 | tempA = physicalAddr; 267 | physicalAddr = physicalAddr >> rankBitWidth; 268 | tempB = physicalAddr << rankBitWidth; 269 | newTransactionRank = tempA ^ tempB; 270 | 271 | tempA = physicalAddr; 272 | physicalAddr = physicalAddr >> bankBitWidth; 273 | tempB = physicalAddr << bankBitWidth; 274 | newTransactionBank = tempA ^ tempB; 275 | 276 | tempA = physicalAddr; 277 | physicalAddr = physicalAddr >> rowBitWidth; 278 | tempB = physicalAddr << rowBitWidth; 279 | newTransactionRow = tempA ^ tempB; 280 | /* 281 | tempA = physicalAddr; 282 | physicalAddr = physicalAddr >> channelBitWidth; 283 | tempB = physicalAddr << channelBitWidth; 284 | newTransactionChan = tempA ^ tempB; 285 | */ 286 | 287 | } 288 | // clone of scheme 5, but channel moved to lower bits 289 | /* 290 | else if (addressMappingScheme == Scheme7) 291 | { 292 | //row:col:rank:bank:chan 293 | tempA = physicalAddr; 294 | physicalAddr = physicalAddr >> channelBitWidth; 295 | tempB = physicalAddr << channelBitWidth; 296 | newTransactionChan = tempA ^ tempB; 297 | 298 | tempA = physicalAddr; 299 | physicalAddr = physicalAddr >> bankBitWidth; 300 | tempB = physicalAddr << bankBitWidth; 301 | newTransactionBank = tempA ^ tempB; 302 | 303 | tempA = physicalAddr; 304 | physicalAddr = physicalAddr >> rankBitWidth; 305 | tempB = physicalAddr << rankBitWidth; 306 | newTransactionRank = tempA ^ tempB; 307 | 308 | tempA = physicalAddr; 309 | physicalAddr = physicalAddr >> colHighBitWidth; 310 | tempB = physicalAddr << colHighBitWidth; 311 | newTransactionColumn = tempA ^ tempB; 312 | 313 | tempA = physicalAddr; 314 | physicalAddr = physicalAddr >> rowBitWidth; 315 | tempB = physicalAddr << rowBitWidth; 316 | newTransactionRow = tempA ^ tempB; 317 | 318 | } 319 | */ 320 | else 321 | { 322 | ERROR("== Error - Unknown Address Mapping Scheme"); 323 | exit(-1); 324 | } 325 | if (DEBUG_ADDR_MAP) 326 | { 327 | DEBUG("Mapped Ch="<iniReader); 37 | } 38 | 39 | #endif 40 | -------------------------------------------------------------------------------- /Bank.cpp: -------------------------------------------------------------------------------- 1 | /********************************************************************************* 2 | * Copyright (c) 2010-2011, Elliott Cooper-Balis 3 | * Paul Rosenfeld 4 | * Bruce Jacob 5 | * University of Maryland 6 | * dramninjas [at] gmail [dot] com 7 | * All rights reserved. 8 | * 9 | * Redistribution and use in source and binary forms, with or without 10 | * modification, are permitted provided that the following conditions are met: 11 | * 12 | * * Redistributions of source code must retain the above copyright notice, 13 | * this list of conditions and the following disclaimer. 14 | * 15 | * * Redistributions in binary form must reproduce the above copyright notice, 16 | * this list of conditions and the following disclaimer in the documentation 17 | * and/or other materials provided with the distribution. 18 | * 19 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 20 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 21 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 22 | * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 23 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 25 | * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 26 | * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 27 | * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | *********************************************************************************/ 30 | 31 | //Bank.cpp 32 | // 33 | //Class file for bank object 34 | // 35 | 36 | #include "Bank.h" 37 | #include "BusPacket.h" 38 | 39 | using namespace std; 40 | using namespace DRAMSim; 41 | 42 | Bank::Bank(ostream &dramsim_log_,IniReader * iniReader_): 43 | iniReader(iniReader_), 44 | currentState(dramsim_log_), 45 | rowEntries(iniReader_->NUM_COLS), 46 | dramsim_log(dramsim_log_) 47 | {} 48 | 49 | /* The bank class is just a glorified sparse storage data structure 50 | * that keeps track of written data in case the simulator wants a 51 | * function DRAM model 52 | * 53 | * A vector of size NUM_COLS keeps a linked list of rows and their 54 | * associated values. 55 | * 56 | * write() adds an entry to the proper linked list or replaces the 57 | * value in a row that was already written 58 | * 59 | * read() searches for a node with the right row value, if not found 60 | * returns the tracer value 0xDEADBEEF 61 | * 62 | * TODO: if anyone wants to actually store data, see the 'data_storage' branch and perhaps try to merge that into master 63 | */ 64 | 65 | 66 | 67 | Bank::DataStruct *Bank::searchForRow(unsigned row, DataStruct *head) 68 | { 69 | while (head != NULL) 70 | { 71 | if (head->row == row) 72 | { 73 | //found it 74 | return head; 75 | } 76 | //keep looking 77 | head = head->next; 78 | } 79 | //if we get here, didn't find it 80 | return NULL; 81 | } 82 | 83 | void Bank::read(BusPacket *busPacket) 84 | { 85 | DataStruct *rowHeadNode = rowEntries[busPacket->column]; 86 | DataStruct *foundNode = NULL; 87 | 88 | if ((foundNode = Bank::searchForRow(busPacket->row, rowHeadNode)) == NULL) 89 | { 90 | // the row hasn't been written before, so it isn't in the list 91 | //if(SHOW_SIM_OUTPUT) DEBUG("== Warning - Read from previously unwritten row " << busPacket->row); 92 | void *garbage = calloc(iniReader->BL * (iniReader->JEDEC_DATA_BUS_BITS/8),1); 93 | ((long *)garbage)[0] = 0xdeadbeef; // tracer value 94 | busPacket->data = garbage; 95 | } 96 | else // found it 97 | { 98 | busPacket->data = foundNode->data; 99 | } 100 | 101 | //the return packet should be a data packet, not a read packet 102 | busPacket->busPacketType = DATA; 103 | } 104 | 105 | 106 | void Bank::write(const BusPacket *busPacket) 107 | { 108 | //TODO: move all the error checking to BusPacket so once we have a bus packet, 109 | // we know the fields are all legal 110 | 111 | if (busPacket->column >= iniReader->NUM_COLS) 112 | { 113 | ERROR("== Error - Bus Packet column "<< busPacket->column <<" out of bounds"); 114 | exit(-1); 115 | } 116 | 117 | // head of the list we need to search 118 | DataStruct *rowHeadNode = rowEntries[busPacket->column]; 119 | DataStruct *foundNode = NULL; 120 | 121 | if ((foundNode = Bank::searchForRow(busPacket->row, rowHeadNode)) == NULL) 122 | { 123 | //not found 124 | DataStruct *newRowNode = (DataStruct *)malloc(sizeof(DataStruct)); 125 | 126 | //insert at the head for speed 127 | //TODO: Optimize this data structure for speedier lookups? 128 | newRowNode->row = busPacket->row; 129 | newRowNode->data = busPacket->data; 130 | newRowNode->next = rowHeadNode; 131 | rowEntries[busPacket->column] = newRowNode; 132 | } 133 | else 134 | { 135 | // found it, just plaster in the new data 136 | foundNode->data = busPacket->data; 137 | if (DEBUG_BANKS) 138 | { 139 | PRINTN(" -- Bank "<bank<<" writing to physical address 0x" << hex << busPacket->physicalAddress<printData(); 141 | PRINT(""); 142 | } 143 | } 144 | } 145 | 146 | -------------------------------------------------------------------------------- /Bank.h: -------------------------------------------------------------------------------- 1 | /********************************************************************************* 2 | * Copyright (c) 2010-2011, Elliott Cooper-Balis 3 | * Paul Rosenfeld 4 | * Bruce Jacob 5 | * University of Maryland 6 | * dramninjas [at] gmail [dot] com 7 | * All rights reserved. 8 | * 9 | * Redistribution and use in source and binary forms, with or without 10 | * modification, are permitted provided that the following conditions are met: 11 | * 12 | * * Redistributions of source code must retain the above copyright notice, 13 | * this list of conditions and the following disclaimer. 14 | * 15 | * * Redistributions in binary form must reproduce the above copyright notice, 16 | * this list of conditions and the following disclaimer in the documentation 17 | * and/or other materials provided with the distribution. 18 | * 19 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 20 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 21 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 22 | * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 23 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 25 | * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 26 | * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 27 | * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | *********************************************************************************/ 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | #ifndef BANK_H 39 | #define BANK_H 40 | 41 | //Bank.h 42 | // 43 | //Header file for bank class 44 | // 45 | 46 | #include "SystemConfiguration.h" 47 | #include "SimulatorObject.h" 48 | #include "BankState.h" 49 | #include "BusPacket.h" 50 | #include 51 | #include "IniReader.h" 52 | 53 | namespace DRAMSim 54 | { 55 | class Bank 56 | { 57 | typedef struct _DataStruct 58 | { 59 | unsigned row; 60 | void *data; 61 | struct _DataStruct *next; 62 | } DataStruct; 63 | 64 | public: 65 | //functions 66 | Bank(ostream &dramsim_log_,IniReader * iniReader); 67 | void read(BusPacket *busPacket); 68 | void write(const BusPacket *busPacket); 69 | 70 | //fields 71 | IniReader * iniReader; 72 | BankState currentState; 73 | 74 | private: 75 | // private member 76 | std::vector rowEntries; 77 | ostream &dramsim_log; 78 | 79 | static DataStruct *searchForRow(unsigned row, DataStruct *head); 80 | }; 81 | } 82 | 83 | #endif 84 | 85 | -------------------------------------------------------------------------------- /BankState.cpp: -------------------------------------------------------------------------------- 1 | /********************************************************************************* 2 | * Copyright (c) 2010-2011, Elliott Cooper-Balis 3 | * Paul Rosenfeld 4 | * Bruce Jacob 5 | * University of Maryland 6 | * dramninjas [at] gmail [dot] com 7 | * All rights reserved. 8 | * 9 | * Redistribution and use in source and binary forms, with or without 10 | * modification, are permitted provided that the following conditions are met: 11 | * 12 | * * Redistributions of source code must retain the above copyright notice, 13 | * this list of conditions and the following disclaimer. 14 | * 15 | * * Redistributions in binary form must reproduce the above copyright notice, 16 | * this list of conditions and the following disclaimer in the documentation 17 | * and/or other materials provided with the distribution. 18 | * 19 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 20 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 21 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 22 | * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 23 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 25 | * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 26 | * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 27 | * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | *********************************************************************************/ 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | //BankState.cpp 39 | // 40 | //Class file for bank state object 41 | // 42 | 43 | #include "BankState.h" 44 | 45 | using namespace std; 46 | using namespace DRAMSim; 47 | 48 | //All banks start precharged 49 | BankState::BankState(ostream &dramsim_log_): 50 | dramsim_log(dramsim_log_), 51 | currentBankState(Idle), 52 | openRowAddress(0), 53 | nextRead(0), 54 | nextWrite(0), 55 | nextActivate(0), 56 | nextPrecharge(0), 57 | nextPowerUp(0), 58 | lastCommand(READ), 59 | stateChangeCountdown(0) 60 | {} 61 | 62 | void BankState::print() 63 | { 64 | PRINT(" == Bank State "); 65 | if (currentBankState == Idle) 66 | { 67 | PRINT(" State : Idle" ); 68 | } 69 | else if (currentBankState == RowActive) 70 | { 71 | PRINT(" State : Active" ); 72 | } 73 | else if (currentBankState == Refreshing) 74 | { 75 | PRINT(" State : Refreshing" ); 76 | } 77 | else if (currentBankState == PowerDown) 78 | { 79 | PRINT(" State : Power Down" ); 80 | } 81 | 82 | PRINT(" OpenRowAddress : " << openRowAddress ); 83 | PRINT(" nextRead : " << nextRead ); 84 | PRINT(" nextWrite : " << nextWrite ); 85 | PRINT(" nextActivate : " << nextActivate ); 86 | PRINT(" nextPrecharge : " << nextPrecharge ); 87 | PRINT(" nextPowerUp : " << nextPowerUp ); 88 | } 89 | -------------------------------------------------------------------------------- /BankState.h: -------------------------------------------------------------------------------- 1 | /********************************************************************************* 2 | * Copyright (c) 2010-2011, Elliott Cooper-Balis 3 | * Paul Rosenfeld 4 | * Bruce Jacob 5 | * University of Maryland 6 | * dramninjas [at] gmail [dot] com 7 | * All rights reserved. 8 | * 9 | * Redistribution and use in source and binary forms, with or without 10 | * modification, are permitted provided that the following conditions are met: 11 | * 12 | * * Redistributions of source code must retain the above copyright notice, 13 | * this list of conditions and the following disclaimer. 14 | * 15 | * * Redistributions in binary form must reproduce the above copyright notice, 16 | * this list of conditions and the following disclaimer in the documentation 17 | * and/or other materials provided with the distribution. 18 | * 19 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 20 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 21 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 22 | * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 23 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 25 | * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 26 | * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 27 | * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | *********************************************************************************/ 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | #ifndef BANKSTATE_H 39 | #define BANKSTATE_H 40 | 41 | //BankState.h 42 | // 43 | //Header file for bank state class 44 | // 45 | 46 | #include "SystemConfiguration.h" 47 | #include "BusPacket.h" 48 | 49 | namespace DRAMSim 50 | { 51 | enum CurrentBankState 52 | { 53 | Idle, 54 | RowActive, 55 | Precharging, 56 | Refreshing, 57 | PowerDown 58 | }; 59 | 60 | class BankState 61 | { 62 | ostream &dramsim_log; 63 | public: 64 | //Fields 65 | CurrentBankState currentBankState; 66 | unsigned openRowAddress; 67 | uint64_t nextRead; 68 | uint64_t nextWrite; 69 | uint64_t nextActivate; 70 | uint64_t nextPrecharge; 71 | uint64_t nextPowerUp; 72 | 73 | BusPacketType lastCommand; 74 | unsigned stateChangeCountdown; 75 | 76 | //Functions 77 | BankState(ostream &dramsim_log_); 78 | void print(); 79 | }; 80 | } 81 | 82 | #endif 83 | 84 | -------------------------------------------------------------------------------- /BusPacket.cpp: -------------------------------------------------------------------------------- 1 | /********************************************************************************* 2 | * Copyright (c) 2010-2011, Elliott Cooper-Balis 3 | * Paul Rosenfeld 4 | * Bruce Jacob 5 | * University of Maryland 6 | * dramninjas [at] gmail [dot] com 7 | * All rights reserved. 8 | * 9 | * Redistribution and use in source and binary forms, with or without 10 | * modification, are permitted provided that the following conditions are met: 11 | * 12 | * * Redistributions of source code must retain the above copyright notice, 13 | * this list of conditions and the following disclaimer. 14 | * 15 | * * Redistributions in binary form must reproduce the above copyright notice, 16 | * this list of conditions and the following disclaimer in the documentation 17 | * and/or other materials provided with the distribution. 18 | * 19 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 20 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 21 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 22 | * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 23 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 25 | * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 26 | * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 27 | * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | *********************************************************************************/ 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | //BusPacket.cpp 39 | // 40 | //Class file for bus packet object 41 | // 42 | 43 | #include "BusPacket.h" 44 | 45 | using namespace DRAMSim; 46 | using namespace std; 47 | 48 | BusPacket::BusPacket(BusPacketType packtype, uint64_t physicalAddr, 49 | unsigned col, unsigned rw, unsigned r, unsigned b, void *dat, 50 | ostream &dramsim_log_) : 51 | dramsim_log(dramsim_log_), 52 | busPacketType(packtype), 53 | column(col), 54 | row(rw), 55 | bank(b), 56 | rank(r), 57 | physicalAddress(physicalAddr), 58 | data(dat) 59 | {} 60 | 61 | void BusPacket::print(uint64_t currentClockCycle, bool dataStart) 62 | { 63 | if (this == NULL) 64 | { 65 | return; 66 | } 67 | 68 | if (VERIFICATION_OUTPUT) 69 | { 70 | switch (busPacketType) 71 | { 72 | case READ: 73 | cmd_verify_out << currentClockCycle << ": read ("< 34 | #include 35 | #include 36 | #include 37 | #include 38 | 39 | #include 40 | 41 | using std::vector; 42 | using std::ostream; 43 | using std::string; 44 | /* 45 | * CSVWriter: Writes CSV data with headers to an underlying ofstream 46 | * This wrapper is meant to look like an ofstream, but it captures 47 | * the names of each field and prints it out to a header before printing 48 | * the CSV data below. 49 | * 50 | * Note: the first finalize() will not print the values out, only the headers. 51 | * One way to fix this problem would be to use a sstringstream (or something) 52 | * to buffer out the values and flush them all in one go instead of passing them 53 | * directly to the underlying stream as is the case now. 54 | * 55 | * Example usage: 56 | * 57 | * CSVWriter sw(cout); // send output to cout 58 | * sw <<"Bandwidth" << 0.5; // value ignored 59 | * sw <<"Latency" << 5; // value ignored 60 | * sw.finalize(); // flush the header 61 | * sw <<"Bandwidth" << 1.5; // field name ignored 62 | * sw <<"Latency" << 15; // field name ignored 63 | * sw.finalize(); // values printed to csv line 64 | * sw <<"Bandwidth" << 2.5; // field name ignored 65 | * sw <<"Latency" << 25; // field name ignored 66 | * sw.finalize(); // values printed to csv line 67 | * 68 | * The output of this example will be: 69 | * 70 | * Bandwidth,Latency 71 | * 1.5,15 72 | * 2.5,25 73 | * 74 | */ 75 | 76 | 77 | namespace DRAMSim { 78 | 79 | class CSVWriter { 80 | public : 81 | struct IndexedName { 82 | static const size_t MAX_TMP_STR = 64; 83 | static const unsigned SINGLE_INDEX_LEN = 4; 84 | string str; 85 | 86 | // functions 87 | static bool isNameTooLong(const char *baseName, unsigned numIndices) 88 | { 89 | return (strlen(baseName)+(numIndices*SINGLE_INDEX_LEN)) > MAX_TMP_STR; 90 | } 91 | static void checkNameLength(const char *baseName, unsigned numIndices) 92 | { 93 | if (isNameTooLong(baseName, numIndices)) 94 | { 95 | ERROR("Your string "< fieldNames; 125 | bool finalized; 126 | unsigned idx; 127 | public: 128 | 129 | // Functions 130 | void finalize() 131 | {/* 132 | //TODO: tag unlikely 133 | if (!finalized) 134 | { 135 | for (unsigned i=0; i // uint64_t 34 | 35 | #ifndef CALLBACK_H 36 | #define CALLBACK_H 37 | 38 | namespace DRAMSim 39 | { 40 | 41 | template 43 | class CallbackBase 44 | { 45 | public: 46 | virtual ~CallbackBase() = 0; 47 | virtual ReturnT operator()(Param1T, Param2T, Param3T) = 0; 48 | }; 49 | 50 | template 51 | DRAMSim::CallbackBase::~CallbackBase() {} 52 | 53 | template 55 | class Callback: public CallbackBase 56 | { 57 | private: 58 | typedef ReturnT (ConsumerT::*PtrMember)(Param1T,Param2T,Param3T); 59 | 60 | public: 61 | Callback( ConsumerT* const object, PtrMember member) : 62 | object(object), member(member) 63 | { 64 | } 65 | 66 | Callback( const Callback& e ) : 67 | object(e.object), member(e.member) 68 | { 69 | } 70 | 71 | ReturnT operator()(Param1T param1, Param2T param2, Param3T param3) 72 | { 73 | return (const_cast(object)->*member) 74 | (param1,param2,param3); 75 | } 76 | 77 | private: 78 | 79 | ConsumerT* const object; 80 | const PtrMember member; 81 | }; 82 | 83 | typedef CallbackBase TransactionCompleteCB; 84 | } // namespace DRAMSim 85 | 86 | #endif 87 | -------------------------------------------------------------------------------- /ClockDomain.cpp: -------------------------------------------------------------------------------- 1 | #include "ClockDomain.h" 2 | 3 | using namespace std; 4 | 5 | 6 | 7 | namespace ClockDomain 8 | { 9 | // "Default" crosser with a 1:1 ratio 10 | ClockDomainCrosser::ClockDomainCrosser(ClockUpdateCB *_callback) 11 | : callback(_callback), clock1(1UL), clock2(1UL), counter1(0UL), counter2(0UL) 12 | { 13 | } 14 | ClockDomainCrosser::ClockDomainCrosser(uint64_t _clock1, uint64_t _clock2, ClockUpdateCB *_callback) 15 | : callback(_callback), clock1(_clock1), clock2(_clock2), counter1(0), counter2(0) 16 | { 17 | //cout << "CTOR: callback address: " << (uint64_t)(this->callback) << "\t ratio="<= 0.5 ? ceil(tmp) : floor(tmp); // ghetto implementation of a rounding function 49 | //printf("i=%lu, z=%20f n=%5u d=%5u\n",i,zs[i],ns[i],ds[i]); 50 | } 51 | 52 | //printf("APPROXIMATION= %u/%d\n",ns[i],ds[i]); 53 | this->clock1=ns[i]; 54 | this->clock2=ds[i]; 55 | 56 | //cout << "CTOR: callback address: " << (uint64_t)(this->callback) << "\t ratio="<(this, &TestObj::cb); 100 | 101 | //ClockDomainCrosser x(5,2,&cb); 102 | //ClockDomainCrosser x(2,5,NULL); 103 | //ClockDomainCrosser x(37,41,NULL); 104 | //ClockDomainCrosser x(41,37,NULL); 105 | //cout << "(main) callback address: " << (uint64_t)&cb << endl; 106 | ClockDomainCrosser x(0.5, callback); 107 | cout <<"------------------------------------------\n"; 108 | ClockDomainCrosser y(0.3333, callback); 109 | cout <<"------------------------------------------\n"; 110 | ClockDomainCrosser z(0.9, callback); 111 | cout <<"------------------------------------------\n"; 112 | 113 | 114 | for (int i=0; i<10; i++) 115 | { 116 | 117 | x.update(); 118 | cout << "UPDATE: counter1= " << x.counter1 << "; counter2= " << x.counter2 << "; " << endl; 119 | } 120 | 121 | return 0; 122 | } 123 | 124 | 125 | } 126 | -------------------------------------------------------------------------------- /ClockDomain.h: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | #include 5 | 6 | namespace ClockDomain 7 | { 8 | 9 | template 10 | class CallbackBase 11 | { 12 | public: 13 | virtual ReturnT operator()() = 0; 14 | }; 15 | 16 | 17 | template 18 | class Callback: public CallbackBase 19 | { 20 | private: 21 | typedef ReturnT (ConsumerT::*PtrMember)(); 22 | 23 | public: 24 | Callback(ConsumerT* const object, PtrMember member) : object(object), member(member) {} 25 | 26 | Callback(const Callback &e) : object(e.object), member(e.member) {} 27 | 28 | ReturnT operator()() 29 | { 30 | return (const_cast(object)->*member)(); 31 | } 32 | 33 | private: 34 | ConsumerT* const object; 35 | const PtrMember member; 36 | }; 37 | 38 | typedef CallbackBase ClockUpdateCB; 39 | 40 | 41 | class ClockDomainCrosser 42 | { 43 | public: 44 | ClockUpdateCB *callback; 45 | uint64_t clock1, clock2; 46 | uint64_t counter1, counter2; 47 | ClockDomainCrosser(ClockUpdateCB *_callback); 48 | ClockDomainCrosser(uint64_t _clock1, uint64_t _clock2, ClockUpdateCB *_callback); 49 | ClockDomainCrosser(double ratio, ClockUpdateCB *_callback); 50 | void update(); 51 | }; 52 | 53 | 54 | class TestObj 55 | { 56 | public: 57 | TestObj() {} 58 | void cb(); 59 | int test(); 60 | }; 61 | } 62 | -------------------------------------------------------------------------------- /CommandQueue.cpp: -------------------------------------------------------------------------------- 1 | /********************************************************************************* 2 | * Copyright (c) 2010-2011, Elliott Cooper-Balis 3 | * Paul Rosenfeld 4 | * Bruce Jacob 5 | * University of Maryland 6 | * dramninjas [at] gmail [dot] com 7 | * All rights reserved. 8 | * 9 | * Redistribution and use in source and binary forms, with or without 10 | * modification, are permitted provided that the following conditions are met: 11 | * 12 | * * Redistributions of source code must retain the above copyright notice, 13 | * this list of conditions and the following disclaimer. 14 | * 15 | * * Redistributions in binary form must reproduce the above copyright notice, 16 | * this list of conditions and the following disclaimer in the documentation 17 | * and/or other materials provided with the distribution. 18 | * 19 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 20 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 21 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 22 | * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 23 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 25 | * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 26 | * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 27 | * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | *********************************************************************************/ 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | //CommandQueue.cpp 39 | // 40 | //Class file for command queue object 41 | // 42 | 43 | #include "CommandQueue.h" 44 | #include "MemoryController.h" 45 | #include 46 | 47 | using namespace DRAMSim; 48 | 49 | 50 | extern uint64_t rowBufferHitCount_dram; 51 | extern uint64_t rowBufferHitCount_pcm; 52 | 53 | 54 | CommandQueue::CommandQueue(vector< vector > &states, ostream &dramsim_log_,IniReader * iniReader_) : 55 | dramsim_log(dramsim_log_), 56 | iniReader(iniReader_), 57 | bankStates(states), 58 | nextBank(0), 59 | nextRank(0), 60 | nextBankPRE(0), 61 | nextRankPRE(0), 62 | refreshRank(0), 63 | refreshWaiting(false), 64 | sendAct(true) 65 | { 66 | if(iniReader->SystemType==TYPE_DRAM) 67 | { 68 | refreshRank=0; 69 | }else if(iniReader->SystemType==TYPE_NVM) 70 | { 71 | refreshRank=-1; 72 | }else { 73 | //TODO print some error message 74 | exit(-1); 75 | } 76 | 77 | 78 | //set here to avoid compile errors 79 | currentClockCycle = 0; 80 | 81 | //use numBankQueus below to create queue structure 82 | size_t numBankQueues; 83 | if (iniReader->queuingStructure==PerRank) 84 | { 85 | numBankQueues = 1; 86 | } 87 | else if (iniReader->queuingStructure==PerRankPerBank) 88 | { 89 | numBankQueues = iniReader->NUM_BANKS; 90 | } 91 | else 92 | { 93 | ERROR("== Error - Unknown queuing structure"); 94 | exit(0); 95 | } 96 | 97 | //vector of counters used to ensure rows don't stay open too long 98 | rowAccessCounters = vector< vector >(iniReader->NUM_RANKS, vector(iniReader->NUM_BANKS,0)); 99 | 100 | //create queue based on the structure we want 101 | BusPacket1D actualQueue; 102 | BusPacket2D perBankQueue = BusPacket2D(); 103 | queues = BusPacket3D(); 104 | for (size_t rank=0; rankNUM_RANKS; rank++) 105 | { 106 | //this loop will run only once for per-rank and NUM_BANKS times for per-rank-per-bank 107 | for (size_t bank=0; bankNUM_RANKS); 123 | for (size_t i=0;iNUM_RANKS;i++) 124 | { 125 | //init the empty vectors here so we don't seg fault later 126 | tFAWCountdown.push_back(vector()); 127 | } 128 | } 129 | CommandQueue::~CommandQueue() 130 | { 131 | //ERROR("COMMAND QUEUE destructor"); 132 | size_t bankMax = iniReader->NUM_RANKS; 133 | if (iniReader->queuingStructure == PerRank) { 134 | bankMax = 1; 135 | } 136 | for (size_t r=0; r< iniReader->NUM_RANKS; r++) 137 | { 138 | for (size_t b=0; brank; 152 | unsigned bank = newBusPacket->bank; 153 | if (iniReader->queuingStructure==PerRank) 154 | { 155 | queues[rank][0].push_back(newBusPacket); 156 | if (queues[rank][0].size()>iniReader->CMD_QUEUE_DEPTH) 157 | { 158 | ERROR("== Error - Enqueued more than allowed in command queue"); 159 | ERROR(" Need to call .hasRoomFor(int numberToEnqueue, unsigned rank, unsigned bank) first"); 160 | exit(0); 161 | } 162 | } 163 | else if (iniReader->queuingStructure==PerRankPerBank) 164 | { 165 | queues[rank][bank].push_back(newBusPacket); 166 | if (queues[rank][bank].size()>iniReader->CMD_QUEUE_DEPTH) 167 | { 168 | ERROR("== Error - Enqueued more than allowed in command queue"); 169 | ERROR(" Need to call .hasRoomFor(int numberToEnqueue, unsigned rank, unsigned bank) first"); 170 | exit(0); 171 | } 172 | } 173 | else 174 | { 175 | ERROR("== Error - Unknown queuing structure"); 176 | exit(0); 177 | } 178 | } 179 | 180 | //Removes the next item from the command queue based on the system's 181 | //command scheduling policy 182 | bool CommandQueue::pop(BusPacket **busPacket) 183 | { 184 | //this can be done here because pop() is called every clock cycle by the parent MemoryController 185 | // figures out the sliding window requirement for tFAW 186 | // 187 | //deal with tFAW book-keeping 188 | // each rank has it's own counter since the restriction is on a device level 189 | for (size_t i=0;iNUM_RANKS;i++) 190 | { 191 | //decrement all the counters we have going 192 | for (size_t j=0;j0 && tFAWCountdown[i][0]==0) 199 | { 200 | tFAWCountdown[i].erase(tFAWCountdown[i].begin()); 201 | } 202 | } 203 | 204 | /* Now we need to find a packet to issue. When the code picks a packet, it will set 205 | *busPacket = [some eligible packet] 206 | 207 | First the code looks if any refreshes need to go 208 | Then it looks for data packets 209 | Otherwise, it starts looking for rows to close (in open page) 210 | */ 211 | 212 | if (iniReader->rowBufferPolicy==ClosePage) 213 | { 214 | bool sendingREF = false; 215 | //if the memory controller set the flags signaling that we need to issue a refresh 216 | if (refreshWaiting) 217 | { 218 | bool foundActiveOrTooEarly = false; 219 | //look for an open bank 220 | for (size_t b=0;bNUM_BANKS;b++) 221 | { 222 | vector &queue = getCommandQueue(refreshRank,b); 223 | //checks to make sure that all banks are idle 224 | if (bankStates[refreshRank][b].currentBankState == RowActive) 225 | { 226 | foundActiveOrTooEarly = true; 227 | //if the bank is open, make sure there is nothing else 228 | // going there before we close it 229 | for (size_t j=0;jrow == bankStates[refreshRank][b].openRowAddress && 233 | packet->bank == b) 234 | { 235 | if (packet->busPacketType != ACTIVATE && isIssuable(packet)) 236 | { 237 | *busPacket = packet; 238 | queue.erase(queue.begin() + j); 239 | sendingREF = true; 240 | } 241 | break; 242 | } 243 | } 244 | 245 | break; 246 | } 247 | // NOTE: checks nextActivate time for each bank to make sure tRP is being 248 | // satisfied. the next ACT and next REF can be issued at the same 249 | // point in the future, so just use nextActivate field instead of 250 | // creating a nextRefresh field 251 | else if (bankStates[refreshRank][b].nextActivate > currentClockCycle) 252 | { 253 | foundActiveOrTooEarly = true; 254 | break; 255 | } 256 | } 257 | 258 | //if there are no open banks and timing has been met, send out the refresh 259 | // reset flags and rank pointer 260 | if (!foundActiveOrTooEarly && bankStates[refreshRank][0].currentBankState != PowerDown) 261 | { 262 | *busPacket = new BusPacket(REFRESH, 0, 0, 0, refreshRank, 0, 0, dramsim_log); 263 | refreshRank = -1; 264 | refreshWaiting = false; 265 | sendingREF = true; 266 | } 267 | } // refreshWaiting 268 | 269 | //if we're not sending a REF, proceed as normal 270 | if (!sendingREF) 271 | { 272 | bool foundIssuable = false; 273 | unsigned startingRank = nextRank; 274 | unsigned startingBank = nextBank; 275 | do 276 | { 277 | vector &queue = getCommandQueue(nextRank, nextBank); 278 | //make sure there is something in this queue first 279 | // also make sure a rank isn't waiting for a refresh 280 | // if a rank is waiting for a refesh, don't issue anything to it until the 281 | // refresh logic above has sent one out (ie, letting banks close) 282 | if (!queue.empty() && !((nextRank == refreshRank) && refreshWaiting)) 283 | { 284 | if (iniReader->queuingStructure == PerRank) 285 | { 286 | 287 | //search from beginning to find first issuable bus packet 288 | for (size_t i=0;i0 && queue[i-1]->busPacketType==ACTIVATE && 294 | queue[i-1]->physicalAddress == queue[i]->physicalAddress) 295 | continue; 296 | 297 | *busPacket = queue[i]; 298 | queue.erase(queue.begin()+i); 299 | foundIssuable = true; 300 | break; 301 | } 302 | } 303 | } 304 | else 305 | { 306 | if (isIssuable(queue[0])) 307 | { 308 | 309 | //no need to search because if the front can't be sent, 310 | // then no chance something behind it can go instead 311 | *busPacket = queue[0]; 312 | queue.erase(queue.begin()); 313 | foundIssuable = true; 314 | } 315 | } 316 | 317 | } 318 | 319 | //if we found something, break out of do-while 320 | if (foundIssuable) break; 321 | 322 | //rank round robin 323 | if (iniReader->queuingStructure == PerRank) 324 | { 325 | nextRank = (nextRank + 1) % iniReader->NUM_RANKS; 326 | if (startingRank == nextRank) 327 | { 328 | break; 329 | } 330 | } 331 | else 332 | { 333 | nextRankAndBank(nextRank, nextBank); 334 | if (startingRank == nextRank && startingBank == nextBank) 335 | { 336 | break; 337 | } 338 | } 339 | } 340 | while (true); 341 | 342 | //if we couldn't find anything to send, return false 343 | if (!foundIssuable) return false; 344 | } 345 | } 346 | else if (iniReader->rowBufferPolicy==OpenPage) 347 | { 348 | bool sendingREForPRE = false; 349 | if (refreshWaiting) 350 | { 351 | bool sendREF = true; 352 | //make sure all banks idle and timing met for a REF 353 | for (size_t b=0;bNUM_BANKS;b++) 354 | { 355 | //if a bank is active we can't send a REF yet 356 | if (bankStates[refreshRank][b].currentBankState == RowActive) 357 | { 358 | sendREF = false; 359 | bool closeRow = true; 360 | //search for commands going to an open row 361 | vector &refreshQueue = getCommandQueue(refreshRank,b); 362 | 363 | for (size_t j=0;jrow && 368 | b == packet->bank) 369 | { 370 | // . . . and is not an activate . . . 371 | if (packet->busPacketType != ACTIVATE) 372 | { 373 | closeRow = false; 374 | // . . . and can be issued . . . 375 | if (isIssuable(packet)) 376 | { 377 | //send it out 378 | *busPacket = packet; 379 | refreshQueue.erase(refreshQueue.begin()+j); 380 | sendingREForPRE = true; 381 | } 382 | break; 383 | } 384 | else //command is an activate 385 | { 386 | //if we've encountered another act, no other command will be of interest 387 | break; 388 | } 389 | } 390 | } 391 | 392 | //if the bank is open and we are allowed to close it, then send a PRE 393 | if (closeRow && currentClockCycle >= bankStates[refreshRank][b].nextPrecharge) 394 | { 395 | rowAccessCounters[refreshRank][b]=0; 396 | *busPacket = new BusPacket(PRECHARGE, 0, 0, 0, refreshRank, b, 0, dramsim_log); 397 | sendingREForPRE = true; 398 | } 399 | break; 400 | } 401 | // NOTE: the next ACT and next REF can be issued at the same 402 | // point in the future, so just use nextActivate field instead of 403 | // creating a nextRefresh field 404 | else if (bankStates[refreshRank][b].nextActivate > currentClockCycle) //and this bank doesn't have an open row 405 | { 406 | sendREF = false; 407 | break; 408 | } 409 | } 410 | 411 | //if there are no open banks and timing has been met, send out the refresh 412 | // reset flags and rank pointer 413 | if (sendREF && bankStates[refreshRank][0].currentBankState != PowerDown) 414 | { 415 | *busPacket = new BusPacket(REFRESH, 0, 0, 0, refreshRank, 0, 0, dramsim_log); 416 | refreshRank = -1; 417 | refreshWaiting = false; 418 | sendingREForPRE = true; 419 | } 420 | } 421 | 422 | if (!sendingREForPRE) 423 | { 424 | unsigned startingRank = nextRank; 425 | unsigned startingBank = nextBank; 426 | bool foundIssuable = false; 427 | do // round robin over queues 428 | { 429 | vector &queue = getCommandQueue(nextRank,nextBank); 430 | //make sure there is something there first 431 | if (!queue.empty() && !((nextRank == refreshRank) && refreshWaiting)) 432 | { 433 | //search from the beginning to find first issuable bus packet 434 | for (size_t i=0;ibusPacketType != ACTIVATE && 445 | prevPacket->bank == packet->bank && 446 | prevPacket->row == packet->row) 447 | { 448 | dependencyFound = true; 449 | break; 450 | } 451 | } 452 | if (dependencyFound) continue; 453 | 454 | *busPacket = packet; 455 | 456 | //if the bus packet before is an activate, that is the act that was 457 | // paired with the column access we are removing, so we have to remove 458 | // that activate as well (check i>0 because if i==0 then theres nothing before it) 459 | if (i>0 && queue[i-1]->busPacketType == ACTIVATE) 460 | { 461 | rowAccessCounters[(*busPacket)->rank][(*busPacket)->bank]++; 462 | // i is being returned, but i-1 is being thrown away, so must delete it here 463 | delete (queue[i-1]); 464 | 465 | // remove both i-1 (the activate) and i (we've saved the pointer in *busPacket) 466 | queue.erase(queue.begin()+i-1,queue.begin()+i+1); 467 | if(iniReader->SystemType==TYPE_DRAM) 468 | { 469 | rowBufferHitCount_dram++; 470 | } 471 | else 472 | { 473 | rowBufferHitCount_pcm++; 474 | } 475 | } 476 | else // there's no activate before this packet 477 | { 478 | //or just remove the one bus packet 479 | queue.erase(queue.begin()+i); 480 | } 481 | 482 | foundIssuable = true; 483 | break; 484 | } 485 | } 486 | } 487 | 488 | //if we found something, break out of do-while 489 | if (foundIssuable) break; 490 | 491 | //rank round robin 492 | if (iniReader->queuingStructure == PerRank) 493 | { 494 | nextRank = (nextRank + 1) % iniReader->NUM_RANKS; 495 | if (startingRank == nextRank) 496 | { 497 | break; 498 | } 499 | } 500 | else 501 | { 502 | nextRankAndBank(nextRank, nextBank); 503 | if (startingRank == nextRank && startingBank == nextBank) 504 | { 505 | break; 506 | } 507 | } 508 | } 509 | while (true); 510 | 511 | //if nothing was issuable, see if we can issue a PRE to an open bank 512 | // that has no other commands waiting 513 | if (!foundIssuable) 514 | { 515 | //search for banks to close 516 | bool sendingPRE = false; 517 | unsigned startingRank = nextRankPRE; 518 | unsigned startingBank = nextBankPRE; 519 | 520 | do // round robin over all ranks and banks 521 | { 522 | vector &queue = getCommandQueue(nextRankPRE, nextBankPRE); 523 | bool found = false; 524 | //check if bank is open 525 | if (bankStates[nextRankPRE][nextBankPRE].currentBankState == RowActive) 526 | { 527 | for (size_t i=0;ibank == nextBankPRE && 531 | queue[i]->row == bankStates[nextRankPRE][nextBankPRE].openRowAddress) 532 | { 533 | found = true; 534 | break; 535 | } 536 | } 537 | 538 | //if nothing found going to that bank and row or too many accesses have happend, close it 539 | if (!found || rowAccessCounters[nextRankPRE][nextBankPRE]==iniReader->TOTAL_ROW_ACCESSES) 540 | { 541 | if (currentClockCycle >= bankStates[nextRankPRE][nextBankPRE].nextPrecharge) 542 | { 543 | sendingPRE = true; 544 | rowAccessCounters[nextRankPRE][nextBankPRE] = 0; 545 | *busPacket = new BusPacket(PRECHARGE, 0, 0, 0, nextRankPRE, nextBankPRE, 0, dramsim_log); 546 | break; 547 | } 548 | } 549 | } 550 | nextRankAndBank(nextRankPRE, nextBankPRE); 551 | } 552 | while (!(startingRank == nextRankPRE && startingBank == nextBankPRE)); 553 | 554 | //if no PREs could be sent, just return false 555 | if (!sendingPRE) return false; 556 | } 557 | } 558 | } 559 | 560 | //sendAct is flag used for posted-cas 561 | // posted-cas is enabled when AL>0 562 | // when sendAct is true, when don't want to increment our indexes 563 | // so we send the column access that is paid with this act 564 | if (iniReader->AL>0 && sendAct) 565 | { 566 | sendAct = false; 567 | } 568 | else 569 | { 570 | sendAct = true; 571 | nextRankAndBank(nextRank, nextBank); 572 | } 573 | 574 | //if its an activate, add a tfaw counter 575 | if ((*busPacket)->busPacketType==ACTIVATE) 576 | { 577 | tFAWCountdown[(*busPacket)->rank].push_back(iniReader->tFAW); 578 | } 579 | 580 | return true; 581 | } 582 | 583 | //check if a rank/bank queue has room for a certain number of bus packets 584 | bool CommandQueue::hasRoomFor(unsigned numberToEnqueue, unsigned rank, unsigned bank) 585 | { 586 | vector &queue = getCommandQueue(rank, bank); 587 | return (iniReader->CMD_QUEUE_DEPTH - queue.size() >= numberToEnqueue); 588 | } 589 | 590 | //prints the contents of the command queue 591 | void CommandQueue::print() 592 | { 593 | if (iniReader->queuingStructure==PerRank) 594 | { 595 | PRINT(endl << "== Printing Per Rank Queue" ); 596 | for (size_t i=0;iNUM_RANKS;i++) 597 | { 598 | PRINT(" = Rank " << i << " size : " << queues[i][0].size() ); 599 | for (size_t j=0;jprint(); 603 | } 604 | } 605 | } 606 | else if (iniReader->queuingStructure==PerRankPerBank) 607 | { 608 | PRINT("\n== Printing Per Rank, Per Bank Queue" ); 609 | 610 | for (size_t i=0;iNUM_RANKS;i++) 611 | { 612 | PRINT(" = Rank " << i ); 613 | for (size_t j=0;jNUM_BANKS;j++) 614 | { 615 | PRINT(" Bank "<< j << " size : " << queues[i][j].size() ); 616 | 617 | for (size_t k=0;kprint(); 621 | } 622 | } 623 | } 624 | } 625 | } 626 | 627 | /** 628 | * return a reference to the queue for a given rank, bank. Since we 629 | * don't always have a per bank queuing structure, sometimes the bank 630 | * argument is ignored (and the 0th index is returned 631 | */ 632 | vector &CommandQueue::getCommandQueue(unsigned rank, unsigned bank) 633 | { 634 | if (iniReader->queuingStructure == PerRankPerBank) 635 | { 636 | return queues[rank][bank]; 637 | } 638 | else if (iniReader->queuingStructure == PerRank) 639 | { 640 | return queues[rank][0]; 641 | } 642 | else 643 | { 644 | ERROR("Unknown queue structure"); 645 | abort(); 646 | } 647 | 648 | } 649 | 650 | //checks if busPacket is allowed to be issued 651 | bool CommandQueue::isIssuable(BusPacket *busPacket) 652 | { 653 | switch (busPacket->busPacketType) 654 | { 655 | case REFRESH: 656 | 657 | break; 658 | case ACTIVATE: 659 | if ((bankStates[busPacket->rank][busPacket->bank].currentBankState == Idle || 660 | bankStates[busPacket->rank][busPacket->bank].currentBankState == Refreshing) && 661 | currentClockCycle >= bankStates[busPacket->rank][busPacket->bank].nextActivate && 662 | tFAWCountdown[busPacket->rank].size() < 4) 663 | { 664 | return true; 665 | } 666 | else 667 | { 668 | return false; 669 | } 670 | break; 671 | case WRITE: 672 | case WRITE_P: 673 | if (bankStates[busPacket->rank][busPacket->bank].currentBankState == RowActive && 674 | currentClockCycle >= bankStates[busPacket->rank][busPacket->bank].nextWrite && 675 | busPacket->row == bankStates[busPacket->rank][busPacket->bank].openRowAddress && 676 | rowAccessCounters[busPacket->rank][busPacket->bank] < iniReader->TOTAL_ROW_ACCESSES) 677 | { 678 | return true; 679 | } 680 | else 681 | { 682 | return false; 683 | } 684 | break; 685 | case READ_P: 686 | case READ: 687 | if (bankStates[busPacket->rank][busPacket->bank].currentBankState == RowActive && 688 | currentClockCycle >= bankStates[busPacket->rank][busPacket->bank].nextRead && 689 | busPacket->row == bankStates[busPacket->rank][busPacket->bank].openRowAddress && 690 | rowAccessCounters[busPacket->rank][busPacket->bank] < iniReader->TOTAL_ROW_ACCESSES) 691 | { 692 | return true; 693 | } 694 | else 695 | { 696 | return false; 697 | } 698 | break; 699 | case PRECHARGE: 700 | if (bankStates[busPacket->rank][busPacket->bank].currentBankState == RowActive && 701 | currentClockCycle >= bankStates[busPacket->rank][busPacket->bank].nextPrecharge) 702 | { 703 | return true; 704 | } 705 | else 706 | { 707 | return false; 708 | } 709 | break; 710 | default: 711 | ERROR("== Error - Trying to issue a crazy bus packet type : "); 712 | busPacket->print(); 713 | exit(0); 714 | } 715 | return false; 716 | } 717 | 718 | //figures out if a rank's queue is empty 719 | bool CommandQueue::isEmpty(unsigned rank) 720 | { 721 | if (iniReader->queuingStructure == PerRank) 722 | { 723 | return queues[rank][0].empty(); 724 | } 725 | else if (iniReader->queuingStructure == PerRankPerBank) 726 | { 727 | for (size_t i=0;iNUM_BANKS;i++) 728 | { 729 | if (!queues[rank][i].empty()) return false; 730 | } 731 | return true; 732 | } 733 | else 734 | { 735 | DEBUG("Invalid Queueing Stucture"); 736 | abort(); 737 | } 738 | } 739 | 740 | //tells the command queue that a particular rank is in need of a refresh 741 | void CommandQueue::needRefresh(unsigned rank) 742 | { 743 | refreshWaiting = true; 744 | refreshRank = rank; 745 | } 746 | 747 | void CommandQueue::nextRankAndBank(unsigned &rank, unsigned &bank) 748 | { 749 | if (iniReader->schedulingPolicy == RankThenBankRoundRobin) 750 | { 751 | rank++; 752 | if (rank == iniReader->NUM_RANKS) 753 | { 754 | rank = 0; 755 | bank++; 756 | if (bank == iniReader->NUM_BANKS) 757 | { 758 | bank = 0; 759 | } 760 | } 761 | } 762 | //bank-then-rank round robin 763 | else if (iniReader->schedulingPolicy == BankThenRankRoundRobin) 764 | { 765 | bank++; 766 | if (bank == iniReader->NUM_BANKS) 767 | { 768 | bank = 0; 769 | rank++; 770 | if (rank == iniReader->NUM_RANKS) 771 | { 772 | rank = 0; 773 | } 774 | } 775 | } 776 | else 777 | { 778 | ERROR("== Error - Unknown scheduling policy"); 779 | exit(0); 780 | } 781 | 782 | } 783 | 784 | void CommandQueue::update() 785 | { 786 | //do nothing since pop() is effectively update(), 787 | //needed for SimulatorObject 788 | //TODO: make CommandQueue not a SimulatorObject 789 | } 790 | -------------------------------------------------------------------------------- /CommandQueue.h: -------------------------------------------------------------------------------- 1 | /********************************************************************************* 2 | * Copyright (c) 2010-2011, Elliott Cooper-Balis 3 | * Paul Rosenfeld 4 | * Bruce Jacob 5 | * University of Maryland 6 | * dramninjas [at] gmail [dot] com 7 | * All rights reserved. 8 | * 9 | * Redistribution and use in source and binary forms, with or without 10 | * modification, are permitted provided that the following conditions are met: 11 | * 12 | * * Redistributions of source code must retain the above copyright notice, 13 | * this list of conditions and the following disclaimer. 14 | * 15 | * * Redistributions in binary form must reproduce the above copyright notice, 16 | * this list of conditions and the following disclaimer in the documentation 17 | * and/or other materials provided with the distribution. 18 | * 19 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 20 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 21 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 22 | * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 23 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 25 | * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 26 | * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 27 | * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | *********************************************************************************/ 30 | 31 | 32 | 33 | 34 | 35 | 36 | #ifndef CMDQUEUE_H 37 | #define CMDQUEUE_H 38 | 39 | //CommandQueue.h 40 | // 41 | //Header 42 | // 43 | 44 | #include "BusPacket.h" 45 | #include "BankState.h" 46 | #include "Transaction.h" 47 | #include "SystemConfiguration.h" 48 | #include "SimulatorObject.h" 49 | #include "IniReader.h" 50 | 51 | using namespace std; 52 | 53 | namespace DRAMSim 54 | { 55 | class CommandQueue : public SimulatorObject 56 | { 57 | CommandQueue(); 58 | ostream &dramsim_log; 59 | public: 60 | IniReader * iniReader; 61 | //typedefs 62 | typedef vector BusPacket1D; 63 | typedef vector BusPacket2D; 64 | typedef vector BusPacket3D; 65 | 66 | //functions 67 | CommandQueue(vector< vector > &states, ostream &dramsim_log_,IniReader * iniReader_); 68 | virtual ~CommandQueue(); 69 | 70 | void enqueue(BusPacket *newBusPacket); 71 | bool pop(BusPacket **busPacket); 72 | bool hasRoomFor(unsigned numberToEnqueue, unsigned rank, unsigned bank); 73 | bool isIssuable(BusPacket *busPacket); 74 | bool isEmpty(unsigned rank); 75 | void needRefresh(unsigned rank); 76 | void print(); 77 | void update(); //SimulatorObject requirement 78 | vector &getCommandQueue(unsigned rank, unsigned bank); 79 | 80 | //fields 81 | 82 | BusPacket3D queues; // 3D array of BusPacket pointers 83 | vector< vector > &bankStates; 84 | private: 85 | void nextRankAndBank(unsigned &rank, unsigned &bank); 86 | //fields 87 | unsigned nextBank; 88 | unsigned nextRank; 89 | 90 | unsigned nextBankPRE; 91 | unsigned nextRankPRE; 92 | 93 | unsigned refreshRank; 94 | bool refreshWaiting; 95 | 96 | vector< vector > tFAWCountdown; 97 | vector< vector > rowAccessCounters; 98 | 99 | bool sendAct; 100 | }; 101 | } 102 | 103 | #endif 104 | 105 | -------------------------------------------------------------------------------- /DRAMSim.h: -------------------------------------------------------------------------------- 1 | /********************************************************************************* 2 | * Copyright (c) 2010-2011, Elliott Cooper-Balis 3 | * Paul Rosenfeld 4 | * Bruce Jacob 5 | * University of Maryland 6 | * dramninjas [at] gmail [dot] com 7 | * All rights reserved. 8 | * 9 | * Redistribution and use in source and binary forms, with or without 10 | * modification, are permitted provided that the following conditions are met: 11 | * 12 | * * Redistributions of source code must retain the above copyright notice, 13 | * this list of conditions and the following disclaimer. 14 | * 15 | * * Redistributions in binary form must reproduce the above copyright notice, 16 | * this list of conditions and the following disclaimer in the documentation 17 | * and/or other materials provided with the distribution. 18 | * 19 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 20 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 21 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 22 | * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 23 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 25 | * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 26 | * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 27 | * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | *********************************************************************************/ 30 | 31 | 32 | #ifndef DRAMSIM_H 33 | #define DRAMSIM_H 34 | /* 35 | * This is a public header for DRAMSim including this along with libdramsim.so should 36 | * provide all necessary functionality to talk to an external simulator 37 | */ 38 | #include "Callback.h" 39 | #include 40 | using std::string; 41 | 42 | namespace DRAMSim 43 | { 44 | 45 | class MultiChannelMemorySystem { 46 | public: 47 | bool addTransaction(bool isWrite, uint64_t addr); 48 | void setCPUClockSpeed(uint64_t cpuClkFreqHz); 49 | void update(); 50 | void printStats(bool finalStats); 51 | bool willAcceptTransaction(); 52 | bool willAcceptTransaction(uint64_t addr); 53 | std::ostream &getLogFile(); 54 | 55 | void RegisterCallbacks( 56 | TransactionCompleteCB *readDone, 57 | TransactionCompleteCB *writeDone, 58 | void (*reportPower)(double bgpower, double burstpower, double refreshpower, double actprepower)); 59 | }; 60 | MultiChannelMemorySystem *getMemorySystemInstance(const string &dev, const string &sys, const string &pwd, const string &trc, unsigned megsOfMemory); 61 | } 62 | 63 | #endif 64 | -------------------------------------------------------------------------------- /IniReader.cpp: -------------------------------------------------------------------------------- 1 | /********************************************************************************* 2 | * Copyright (c) 2010-2011, Elliott Cooper-Balis 3 | * Paul Rosenfeld 4 | * Bruce Jacob 5 | * University of Maryland 6 | * dramninjas [at] gmail [dot] com 7 | * All rights reserved. 8 | * 9 | * Redistribution and use in source and binary forms, with or without 10 | * modification, are permitted provided that the following conditions are met: 11 | * 12 | * * Redistributions of source code must retain the above copyright notice, 13 | * this list of conditions and the following disclaimer. 14 | * 15 | * * Redistributions in binary form must reproduce the above copyright notice, 16 | * this list of conditions and the following disclaimer in the documentation 17 | * and/or other materials provided with the distribution. 18 | * 19 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 20 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 21 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 22 | * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 23 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 25 | * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 26 | * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 27 | * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | *********************************************************************************/ 30 | 31 | #include "IniReader.h" 32 | 33 | using namespace std; 34 | 35 | unsigned NUM_CHANS; 36 | bool DEBUG_TRANS_Q; 37 | bool DEBUG_CMD_Q; 38 | bool DEBUG_ADDR_MAP; 39 | bool DEBUG_BANKSTATE; 40 | bool DEBUG_BUS; 41 | bool DEBUG_BANKS; 42 | bool DEBUG_POWER; 43 | bool VIS_FILE_OUTPUT; 44 | bool VERIFICATION_OUTPUT; 45 | bool DEBUG_INI_READER=false; 46 | 47 | namespace DRAMSim 48 | { 49 | 50 | IniReader::IniReader(unsigned SystemType_, unsigned totalStorage_):SystemType(SystemType_),TOTAL_STORAGE(totalStorage_) 51 | { 52 | configMap[0]=DEFINE_UINT_PARAM(NUM_BANKS,DEV_PARAM); 53 | configMap[1]=DEFINE_UINT_PARAM(NUM_ROWS,DEV_PARAM); 54 | configMap[2]=DEFINE_UINT_PARAM(NUM_COLS,DEV_PARAM); 55 | configMap[3]=DEFINE_UINT_PARAM(DEVICE_WIDTH,DEV_PARAM); 56 | 57 | configMap[4]=DEFINE_UINT_PARAM(REFRESH_PERIOD,DEV_PARAM); 58 | configMap[5]=DEFINE_FLOAT_PARAM(tCK,DEV_PARAM); 59 | configMap[6]=DEFINE_UINT_PARAM(CL,DEV_PARAM); 60 | configMap[7]=DEFINE_UINT_PARAM(AL,DEV_PARAM); 61 | configMap[8]=DEFINE_UINT_PARAM(BL,DEV_PARAM); 62 | //RL is calculated 63 | //WL is calculated 64 | configMap[9]=DEFINE_UINT_PARAM(tRAS,DEV_PARAM); 65 | configMap[10]=DEFINE_UINT_PARAM(tRCD,DEV_PARAM); 66 | configMap[11]=DEFINE_UINT_PARAM(tRRD,DEV_PARAM); 67 | configMap[12]=DEFINE_UINT_PARAM(tRC,DEV_PARAM); 68 | configMap[13]=DEFINE_UINT_PARAM(tRP,DEV_PARAM); 69 | configMap[14]=DEFINE_UINT_PARAM(tCCD,DEV_PARAM); 70 | configMap[15]=DEFINE_UINT_PARAM(tRTP,DEV_PARAM); 71 | configMap[16]=DEFINE_UINT_PARAM(tWTR,DEV_PARAM); 72 | configMap[17]=DEFINE_UINT_PARAM(tWR,DEV_PARAM); 73 | configMap[18]=DEFINE_UINT_PARAM(tRTRS,DEV_PARAM); 74 | configMap[19]=DEFINE_UINT_PARAM(tRFC,DEV_PARAM); 75 | configMap[20]=DEFINE_UINT_PARAM(tFAW,DEV_PARAM); 76 | configMap[21]=DEFINE_UINT_PARAM(tCKE,DEV_PARAM); 77 | configMap[22]=DEFINE_UINT_PARAM(tXP,DEV_PARAM); 78 | configMap[23]=DEFINE_UINT_PARAM(tCMD,DEV_PARAM); 79 | 80 | configMap[24]=DEFINE_UINT_PARAM(IDD0,DEV_PARAM); 81 | configMap[25]=DEFINE_UINT_PARAM(IDD1,DEV_PARAM); 82 | configMap[26]=DEFINE_UINT_PARAM(IDD2P,DEV_PARAM); 83 | configMap[27]=DEFINE_UINT_PARAM(IDD2Q,DEV_PARAM); 84 | configMap[28]=DEFINE_UINT_PARAM(IDD2N,DEV_PARAM); 85 | configMap[29]=DEFINE_UINT_PARAM(IDD3Pf,DEV_PARAM); 86 | configMap[30]=DEFINE_UINT_PARAM(IDD3Ps,DEV_PARAM); 87 | configMap[31]=DEFINE_UINT_PARAM(IDD3N,DEV_PARAM); 88 | configMap[32]=DEFINE_UINT_PARAM(IDD4W,DEV_PARAM); 89 | configMap[33]=DEFINE_UINT_PARAM(IDD4R,DEV_PARAM); 90 | configMap[34]=DEFINE_UINT_PARAM(IDD5,DEV_PARAM); 91 | configMap[35]=DEFINE_UINT_PARAM(IDD6,DEV_PARAM); 92 | configMap[36]=DEFINE_UINT_PARAM(IDD6L,DEV_PARAM); 93 | configMap[37]=DEFINE_UINT_PARAM(IDD7,DEV_PARAM); 94 | configMap[38]=DEFINE_FLOAT_PARAM(Vdd,DEV_PARAM); 95 | 96 | //in bytes 97 | configMap[39]=DEFINE_UINT_PARAM(NUM_CHANS,SYS_PARAM); 98 | configMap[40]=DEFINE_UINT_PARAM(JEDEC_DATA_BUS_BITS,SYS_PARAM); 99 | //Memory Controller related parameters 100 | configMap[41]=DEFINE_UINT_PARAM(TRANS_QUEUE_DEPTH,SYS_PARAM); 101 | configMap[42]=DEFINE_UINT_PARAM(CMD_QUEUE_DEPTH,SYS_PARAM); 102 | //cycles within an epoch 103 | configMap[43]=DEFINE_UINT_PARAM(EPOCH_LENGTH,SYS_PARAM); 104 | //Power 105 | configMap[44]=DEFINE_BOOL_PARAM(USE_LOW_POWER,SYS_PARAM); 106 | // strings and their associated enums 107 | configMap[45]=DEFINE_UINT_PARAM(TOTAL_ROW_ACCESSES,SYS_PARAM); 108 | configMap[46]=DEFINE_STRING_PARAM(ROW_BUFFER_POLICY,SYS_PARAM); 109 | configMap[47]=DEFINE_STRING_PARAM(SCHEDULING_POLICY,SYS_PARAM); 110 | configMap[48]=DEFINE_STRING_PARAM(ADDRESS_MAPPING_SCHEME,SYS_PARAM); 111 | configMap[49]=DEFINE_STRING_PARAM(QUEUING_STRUCTURE,SYS_PARAM); 112 | // debug flag, debugs flags are global variables 113 | configMap[50]=DEFINE_BOOL_PARAM(DEBUG_TRANS_Q,SYS_PARAM); 114 | configMap[51]=DEFINE_BOOL_PARAM(DEBUG_CMD_Q,SYS_PARAM); 115 | configMap[52]=DEFINE_BOOL_PARAM(DEBUG_ADDR_MAP,SYS_PARAM); 116 | configMap[53]=DEFINE_BOOL_PARAM(DEBUG_BANKSTATE,SYS_PARAM); 117 | configMap[54]=DEFINE_BOOL_PARAM(DEBUG_BUS,SYS_PARAM); 118 | configMap[55]=DEFINE_BOOL_PARAM(DEBUG_BANKS,SYS_PARAM); 119 | configMap[56]=DEFINE_BOOL_PARAM(DEBUG_POWER,SYS_PARAM); 120 | configMap[57]=DEFINE_BOOL_PARAM(VIS_FILE_OUTPUT,SYS_PARAM); 121 | configMap[58]=DEFINE_BOOL_PARAM(VERIFICATION_OUTPUT,SYS_PARAM); 122 | 123 | //power 124 | configMap[59]=DEFINE_FLOAT_PARAM(ArrayReadEnergy,DEV_PARAM); 125 | configMap[60]=DEFINE_FLOAT_PARAM(ArrayWriteEnergy,DEV_PARAM); 126 | configMap[61]=DEFINE_FLOAT_PARAM(RowBufferReadEnergy,DEV_PARAM); 127 | configMap[62]=DEFINE_FLOAT_PARAM(RowBufferWriteEnergy,DEV_PARAM); 128 | 129 | configMap[63]={"", NULL, UINT, SYS_PARAM, false}; // tracer value to signify end of list; if you delete it, epic fail will resul; 130 | 131 | } 132 | 133 | void IniReader::WriteParams(std::ofstream &visDataOut, paramType type) 134 | { 135 | for (size_t i=0; configMap[i].variablePtr != NULL; i++) 136 | { 137 | if (configMap[i].parameterType == type) 138 | { 139 | visDataOut<> dec >> intValue).fail()) 204 | { 205 | ERROR("could not parse line "< 0) 255 | { 256 | if (isSystemParam && configMap[i].parameterType == DEV_PARAM) 257 | { 258 | DEBUG("WARNING: Found device parameter "<SetKey(key, valueString, isSystemFile, lineNumber); 341 | // got to the end of the config map without finding the key 342 | } 343 | } 344 | else 345 | { 346 | ERROR ("Unable to load ini file "<begin(); 357 | DEBUG("Key overrides from command line:"); 358 | for (it=map->begin(); it != map->end(); it++) 359 | { 360 | string key = it->first; 361 | string value = it->second; 362 | DEBUG("\t'"<< key <<"'->'"<< value<< "'"); 363 | this->SetKey(key,value); 364 | } 365 | } 366 | 367 | bool IniReader::CheckIfAllSet() 368 | { 369 | // check to make sure all parameters that we exepected were set 370 | for (size_t i=0; configMap[i].variablePtr != NULL; i++) 371 | { 372 | if (!configMap[i].wasSet) 373 | { 374 | DEBUG("WARNING: KEY "<> 20; 395 | // If this is set, effectively override the number of ranks 396 | if (TOTAL_STORAGE != 0) 397 | { 398 | NUM_RANKS =TOTAL_STORAGE / megsOfStoragePerRank; 399 | if (NUM_RANKS == 0) 400 | { 401 | PRINT("WARNING: Cannot create memory system with "< 35 | #include 36 | #include 37 | #include 38 | #include 39 | #include "SystemConfiguration.h" 40 | 41 | using namespace std; 42 | 43 | #define DEFINE_UINT_PARAM(name, paramtype) {#name, &name, UINT, paramtype, false} 44 | #define DEFINE_STRING_PARAM(name, paramtype) {#name, &name, STRING, paramtype, false} 45 | #define DEFINE_FLOAT_PARAM(name,paramtype) {#name, &name, FLOAT, paramtype, false} 46 | #define DEFINE_BOOL_PARAM(name, paramtype) {#name, &name, BOOL, paramtype, false} 47 | #define DEFINE_UINT64_PARAM(name, paramtype) {#name, &name, UINT64, paramtype, false} 48 | 49 | namespace DRAMSim 50 | { 51 | 52 | typedef enum _variableType {STRING, UINT, UINT64, FLOAT, BOOL} varType; 53 | typedef enum _paramType {SYS_PARAM, DEV_PARAM} paramType; 54 | typedef struct _configMap 55 | { 56 | string iniKey; //for example "tRCD" 57 | 58 | void *variablePtr; 59 | varType variableType; 60 | paramType parameterType; 61 | bool wasSet; 62 | } ConfigMap; 63 | 64 | class IniReader 65 | { 66 | 67 | public: 68 | unsigned SystemType; 69 | //Device.ini parameters 70 | 71 | unsigned NUM_BANKS; 72 | unsigned NUM_ROWS; 73 | unsigned NUM_COLS; 74 | unsigned DEVICE_WIDTH; 75 | 76 | unsigned REFRESH_PERIOD; 77 | float tCK; 78 | unsigned CL; 79 | unsigned AL; 80 | unsigned BL; 81 | unsigned RL; 82 | unsigned WL; 83 | unsigned tRAS; 84 | unsigned tRCD; 85 | unsigned tRRD; 86 | unsigned tRC; 87 | unsigned tRP; 88 | unsigned tCCD; 89 | unsigned tRTP; 90 | unsigned tWTR; 91 | unsigned tWR; 92 | unsigned tRTRS; 93 | unsigned tRFC; 94 | unsigned tFAW; 95 | unsigned tCKE; 96 | unsigned tXP; 97 | unsigned tCMD; 98 | 99 | float ArrayReadEnergy; 100 | float ArrayWriteEnergy; 101 | float RowBufferReadEnergy; 102 | float RowBufferWriteEnergy; 103 | 104 | 105 | unsigned IDD0; 106 | unsigned IDD1; 107 | unsigned IDD2P; 108 | unsigned IDD2Q; 109 | unsigned IDD2N; 110 | unsigned IDD3Pf; 111 | unsigned IDD3Ps; 112 | unsigned IDD3N; 113 | unsigned IDD4W; 114 | unsigned IDD4R; 115 | unsigned IDD5; 116 | unsigned IDD6; 117 | unsigned IDD6L; 118 | unsigned IDD7; 119 | float Vdd; 120 | 121 | //in bytes 122 | unsigned JEDEC_DATA_BUS_BITS; 123 | //Memory Controller related parameters 124 | unsigned TRANS_QUEUE_DEPTH; 125 | unsigned CMD_QUEUE_DEPTH; 126 | //cycles within an epoch 127 | unsigned EPOCH_LENGTH; 128 | //Power 129 | bool USE_LOW_POWER; 130 | // strings and their associated enums 131 | unsigned TOTAL_ROW_ACCESSES; 132 | string ROW_BUFFER_POLICY; 133 | string SCHEDULING_POLICY; 134 | string ADDRESS_MAPPING_SCHEME; 135 | string QUEUING_STRUCTURE; 136 | //******************The above variables get their values from ini files**** 137 | 138 | unsigned NUM_DEVICES; //set in MemorySystem::MemorySystem 139 | unsigned NUM_RANKS; //set in MemorySystem::MemorySystem 140 | uint64_t TOTAL_STORAGE;//set in MemorySystem::MemorySystem 141 | 142 | RowBufferPolicy rowBufferPolicy; 143 | SchedulingPolicy schedulingPolicy; 144 | AddressMappingScheme addressMappingScheme; 145 | QueuingStructure queuingStructure; 146 | 147 | //Map the string names to the variables they set 148 | ConfigMap configMap[64]; 149 | 150 | typedef std::map OverrideMap; 151 | typedef OverrideMap::const_iterator OverrideIterator; 152 | //functions 153 | IniReader(unsigned SystemType,unsigned totalStorage_); 154 | void SetKey(string key, string value, bool isSystemParam = false, size_t lineNumber = 0); 155 | void OverrideKeys(const OverrideMap *map); 156 | void ReadIniFile(string filename, bool isSystemParam); 157 | void InitEnumsFromStrings(); 158 | bool CheckIfAllSet(); 159 | void WriteValuesOut(std::ofstream &visDataOut); 160 | 161 | private: 162 | void WriteParams(std::ofstream &visDataOut, paramType t); 163 | void Trim(string &str); 164 | }; 165 | } 166 | 167 | 168 | #endif 169 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | CXXFLAGS=-DNO_STORAGE -Wall -DDEBUG_BUILD --std=gnu++0x 2 | OPTFLAGS=-O3 3 | 4 | 5 | ifdef DEBUG 6 | ifeq ($(DEBUG), 1) 7 | OPTFLAGS= -O0 -g 8 | endif 9 | endif 10 | CXXFLAGS+=$(OPTFLAGS) 11 | 12 | EXE_NAME=HMSim1 13 | LIB_NAME=libdramsim.so 14 | LIB_NAME_MACOS=libdramsim.dylib 15 | 16 | SRC = $(wildcard *.cpp) 17 | OBJ = $(addsuffix .o, $(basename $(SRC))) 18 | 19 | #build portable objects (i.e. with -fPIC) 20 | POBJ = $(addsuffix .po, $(basename $(SRC))) 21 | 22 | REBUILDABLES=$(OBJ) ${POBJ} $(EXE_NAME) $(LIB_NAME) 23 | 24 | all: ${EXE_NAME} 25 | 26 | # $@ target name, $^ target deps, $< matched pattern 27 | $(EXE_NAME): $(OBJ) 28 | $(CXX) $(CXXFLAGS) -o $@ $^ 29 | @echo "Built $@ successfully" 30 | 31 | $(LIB_NAME): $(POBJ) 32 | g++ -g -shared -Wl,-soname,$@ -o $@ $^ 33 | @echo "Built $@ successfully" 34 | 35 | $(LIB_NAME_MACOS): $(POBJ) 36 | g++ -dynamiclib -o $@ $^ 37 | @echo "Built $@ successfully" 38 | 39 | #include the autogenerated dependency files for each .o file 40 | -include $(OBJ:.o=.dep) 41 | -include $(POBJ:.po=.deppo) 42 | 43 | # build dependency list via gcc -M and save to a .dep file 44 | %.dep : %.cpp 45 | @$(CXX) -M $(CXXFLAGS) $< > $@ 46 | 47 | %.deppo : %.cpp 48 | @$(CXX) -M $(CXXFLAGS) -MT"$*.po" $< > $@ 49 | 50 | # build all .cpp files to .o files 51 | %.o : %.cpp 52 | g++ $(CXXFLAGS) -o $@ -c $< 53 | 54 | #po = portable object .. for lack of a better term 55 | %.po : %.cpp 56 | g++ $(CXXFLAGS) -DLOG_OUTPUT -fPIC -o $@ -c $< 57 | 58 | clean: 59 | -rm -f $(REBUILDABLES) *.dep *.deppo 60 | -------------------------------------------------------------------------------- /MemoryController.h: -------------------------------------------------------------------------------- 1 | /********************************************************************************* 2 | * Copyright (c) 2010-2011, Elliott Cooper-Balis 3 | * Paul Rosenfeld 4 | * Bruce Jacob 5 | * University of Maryland 6 | * dramninjas [at] gmail [dot] com 7 | * All rights reserved. 8 | * 9 | * Redistribution and use in source and binary forms, with or without 10 | * modification, are permitted provided that the following conditions are met: 11 | * 12 | * * Redistributions of source code must retain the above copyright notice, 13 | * this list of conditions and the following disclaimer. 14 | * 15 | * * Redistributions in binary form must reproduce the above copyright notice, 16 | * this list of conditions and the following disclaimer in the documentation 17 | * and/or other materials provided with the distribution. 18 | * 19 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 20 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 21 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 22 | * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 23 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 25 | * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 26 | * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 27 | * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | *********************************************************************************/ 30 | 31 | 32 | #ifndef MEMORYCONTROLLER_H 33 | #define MEMORYCONTROLLER_H 34 | 35 | //MemoryController.h 36 | // 37 | //Header file for memory controller object 38 | // 39 | 40 | #include "SimulatorObject.h" 41 | #include "Transaction.h" 42 | #include "SystemConfiguration.h" 43 | #include "CommandQueue.h" 44 | #include "BusPacket.h" 45 | #include "BankState.h" 46 | #include "Rank.h" 47 | #include "CSVWriter.h" 48 | #include "IniReader.h" 49 | #include 50 | 51 | using namespace std; 52 | 53 | namespace DRAMSim 54 | { 55 | class MemorySystem; 56 | class IniReader; 57 | class MemoryController : public SimulatorObject 58 | { 59 | 60 | public: 61 | //functions 62 | MemoryController(MemorySystem* ms, CSVWriter &csvOut_, ostream &dramsim_log_); 63 | virtual ~MemoryController(); 64 | 65 | bool addTransaction(Transaction *trans); 66 | bool WillAcceptTransaction(); 67 | void returnReadData(const Transaction *trans); 68 | void receiveFromBus(BusPacket *bpacket); 69 | void attachRanks(vector *ranks); 70 | void update(); 71 | void printStats(bool finalStats = false); 72 | void resetStats(); 73 | 74 | 75 | //fields 76 | vector transactionQueue; 77 | private: 78 | vector allIniReaders; 79 | IniReader * iniReader; 80 | ostream &dramsim_log; 81 | vector< vector > bankStates; 82 | //functions 83 | void insertHistogram(unsigned latencyValue, unsigned rank, unsigned bank); 84 | 85 | //fields 86 | MemorySystem *parentMemorySystem; 87 | 88 | CommandQueue commandQueue; 89 | BusPacket *poppedBusPacket; 90 | vectorrefreshCountdown; 91 | vector writeDataToSend; 92 | vector writeDataCountdown; 93 | vector returnTransaction; 94 | vector pendingReadTransactions; 95 | vector pendingWriteTransactions; 96 | map latencies; // latencyValue -> latencyCount 97 | vector powerDown; 98 | 99 | vector *ranks; 100 | 101 | //output file 102 | CSVWriter &csvOut; 103 | 104 | // these packets are counting down waiting to be transmitted on the "bus" 105 | BusPacket *outgoingCmdPacket; 106 | unsigned cmdCyclesLeft; 107 | BusPacket *outgoingDataPacket; 108 | unsigned dataCyclesLeft; 109 | 110 | uint64_t totalTransactions; 111 | 112 | vector grandTotalBankAccesses; 113 | vector totalReadsPerBank; 114 | vector totalWritesPerBank; 115 | 116 | vector totalReadsPerRank; 117 | vector totalWritesPerRank; 118 | 119 | vector totalReadsPerRank_Receive; 120 | vector totalWritesPerRank_Receive; 121 | 122 | vector< uint64_t > totalEpochLatency; 123 | vector< uint64_t > totalEpochLatency_Write; 124 | 125 | unsigned channelBitWidth; 126 | unsigned rankBitWidth; 127 | unsigned bankBitWidth; 128 | unsigned rowBitWidth; 129 | unsigned colBitWidth; 130 | unsigned byteOffsetWidth; 131 | 132 | 133 | signed refreshRank; 134 | bool needPrecharge; 135 | 136 | public: 137 | // energy values are per rank -- SST uses these directly, so make these public 138 | vector< double > backgroundEnergy; 139 | vector< double > burstEnergy; 140 | vector< double > actpreEnergy; 141 | vector< double > refreshEnergy; 142 | 143 | }; 144 | } 145 | 146 | #endif 147 | 148 | -------------------------------------------------------------------------------- /MemorySystem.cpp: -------------------------------------------------------------------------------- 1 | /********************************************************************************* 2 | * Copyright (c) 2010-2011, Elliott Cooper-Balis 3 | * Paul Rosenfeld 4 | * Bruce Jacob 5 | * University of Maryland 6 | * dramninjas [at] gmail [dot] com 7 | * All rights reserved. 8 | * 9 | * Redistribution and use in source and binary forms, with or without 10 | * modification, are permitted provided that the following conditions are met: 11 | * 12 | * * Redistributions of source code must retain the above copyright notice, 13 | * this list of conditions and the following disclaimer. 14 | * 15 | * * Redistributions in binary form must reproduce the above copyright notice, 16 | * this list of conditions and the following disclaimer in the documentation 17 | * and/or other materials provided with the distribution. 18 | * 19 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 20 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 21 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 22 | * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 23 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 25 | * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 26 | * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 27 | * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | *********************************************************************************/ 30 | 31 | 32 | 33 | 34 | //MemorySystem.cpp 35 | // 36 | //Class file for JEDEC memory system wrapper 37 | // 38 | 39 | #include "MemorySystem.h" 40 | #include "IniReader.h" 41 | #include 42 | 43 | using namespace std; 44 | 45 | 46 | ofstream cmd_verify_out; //used in Rank.cpp and MemoryController.cpp if VERIFICATION_OUTPUT is set 47 | 48 | 49 | namespace DRAMSim { 50 | 51 | powerCallBack_t MemorySystem::ReportPower = NULL; 52 | 53 | MemorySystem::MemorySystem(unsigned id, CSVWriter &csvOut_, ostream &dramsim_log_, vector allIniReaders_) : 54 | allIniReaders(allIniReaders_), 55 | dramsim_log(dramsim_log_), 56 | ReturnReadData(NULL), 57 | WriteDataDone(NULL), 58 | systemID(id), 59 | csvOut(csvOut_) 60 | { 61 | currentClockCycle = 0; 62 | //one iniReader for each channel, so each id 63 | iniReader=allIniReaders[systemID]; 64 | 65 | DEBUG("===== MemorySystem "<1 will be valid). 82 | 83 | However, users don't care (or know) about ranks, they care about total 84 | storage, so maybe it's better to let them choose and just throw an error 85 | if they choose something invalid. 86 | 87 | A bit of background: 88 | 89 | Each column contains DEVICE_WIDTH bits. A row contains NUM_COLS columns. 90 | Each bank contains NUM_ROWS rows. Therefore, the total storage per DRAM device is: 91 | PER_DEVICE_STORAGE = NUM_ROWS*NUM_COLS*DEVICE_WIDTH*NUM_BANKS (in bits) 92 | 93 | A rank *must* have a 64 bit output bus (JEDEC standard), so each rank must have: 94 | NUM_DEVICES_PER_RANK = 64/DEVICE_WIDTH 95 | (note: if you have multiple channels ganged together, the bus width is 96 | effectively NUM_CHANS * 64/DEVICE_WIDTH) 97 | 98 | If we multiply these two numbers to get the storage per rank (in bits), we get: 99 | PER_RANK_STORAGE = PER_DEVICE_STORAGE*NUM_DEVICES_PER_RANK = NUM_ROWS*NUM_COLS*NUM_BANKS*64 100 | 101 | Finally, to get TOTAL_STORAGE, we need to multiply by NUM_RANKS 102 | TOTAL_STORAGE = PER_RANK_STORAGE*NUM_RANKS (total storage in bits) 103 | 104 | So one could compute this in reverse -- compute NUM_DEVICES, 105 | PER_DEVICE_STORAGE, and PER_RANK_STORAGE first since all these parameters 106 | are set by the device ini. Then, TOTAL_STORAGE/PER_RANK_STORAGE = NUM_RANKS 107 | 108 | The only way this could run into problems is if TOTAL_STORAGE < PER_RANK_STORAGE, 109 | which could happen for very dense parts. 110 | *********************/ 111 | 112 | DEBUG("CH. " <TOTAL_STORAGE << "MB | "<NUM_RANKS<<" Ranks | "<< iniReader->NUM_DEVICES <<" Devices per rank"); 113 | 114 | 115 | memoryController = new MemoryController(this, csvOut, dramsim_log); 116 | 117 | // TODO: change to other vector constructor? 118 | ranks = new vector(); 119 | 120 | for (size_t i=0; iNUM_RANKS; i++) 121 | { 122 | Rank *r = new Rank(dramsim_log,iniReader); 123 | r->setId(i); 124 | r->attachMemoryController(memoryController); 125 | ranks->push_back(r); 126 | } 127 | 128 | memoryController->attachRanks(ranks); 129 | 130 | } 131 | 132 | 133 | 134 | MemorySystem::~MemorySystem() 135 | { 136 | /* the MemorySystem should exist for all time, nothing should be destroying it */ 137 | // ERROR("MEMORY SYSTEM DESTRUCTOR with ID "<NUM_RANKS; i++) 143 | { 144 | delete (*ranks)[i]; 145 | } 146 | ranks->clear(); 147 | delete(ranks); 148 | 149 | if (VERIFICATION_OUTPUT) 150 | { 151 | cmd_verify_out.flush(); 152 | cmd_verify_out.close(); 153 | } 154 | } 155 | 156 | bool MemorySystem::WillAcceptTransaction() 157 | { 158 | return memoryController->WillAcceptTransaction(); 159 | } 160 | 161 | bool MemorySystem::addTransaction(bool isWrite, uint64_t addr) 162 | { 163 | TransactionType type = isWrite ? DATA_WRITE : DATA_READ; 164 | Transaction *trans = new Transaction(type,addr,NULL); 165 | // push_back in memoryController will make a copy of this during 166 | // addTransaction so it's kosher for the reference to be local 167 | 168 | if (memoryController->WillAcceptTransaction()) 169 | { 170 | return memoryController->addTransaction(trans); 171 | } 172 | else 173 | { 174 | pendingTransactions.push_back(trans); 175 | return true; 176 | } 177 | } 178 | 179 | bool MemorySystem::addTransaction(Transaction *trans) 180 | { 181 | return memoryController->addTransaction(trans); 182 | } 183 | 184 | //prints statistics 185 | void MemorySystem::printStats(bool finalStats) 186 | { 187 | memoryController->printStats(finalStats); 188 | } 189 | 190 | 191 | //update the memory systems state 192 | void MemorySystem::update() 193 | { 194 | 195 | //PRINT(" ----------------- Memory System Update ------------------"); 196 | 197 | //updates the state of each of the objects 198 | // NOTE - do not change order 199 | for (size_t i=0;iNUM_RANKS;i++) 200 | { 201 | (*ranks)[i]->update(); 202 | } 203 | 204 | //pendingTransactions will only have stuff in it if MARSS is adding stuff 205 | if (pendingTransactions.size() > 0 && memoryController->WillAcceptTransaction()) 206 | { 207 | memoryController->addTransaction(pendingTransactions.front()); 208 | pendingTransactions.pop_front(); 209 | } 210 | memoryController->update(); 211 | 212 | //simply increments the currentClockCycle field for each object 213 | for (size_t i=0;iNUM_RANKS;i++) 214 | { 215 | (*ranks)[i]->step(); 216 | } 217 | memoryController->step(); 218 | this->step(); 219 | 220 | //PRINT("\n"); // two new lines 221 | } 222 | 223 | void MemorySystem::RegisterCallbacks( Callback_t* readCB, Callback_t* writeCB, 224 | void (*reportPower)(double bgpower, double burstpower, 225 | double refreshpower, double actprepower)) 226 | { 227 | ReturnReadData = readCB; 228 | WriteDataDone = writeCB; 229 | ReportPower = reportPower; 230 | } 231 | 232 | } /*namespace DRAMSim */ 233 | 234 | 235 | 236 | // This function can be used by autoconf AC_CHECK_LIB since 237 | // apparently it can't detect C++ functions. 238 | // Basically just an entry in the symbol table 239 | extern "C" 240 | { 241 | void libdramsim_is_present(void) 242 | { 243 | ; 244 | } 245 | } 246 | 247 | -------------------------------------------------------------------------------- /MemorySystem.h: -------------------------------------------------------------------------------- 1 | /********************************************************************************* 2 | * Copyright (c) 2010-2011, Elliott Cooper-Balis 3 | * Paul Rosenfeld 4 | * Bruce Jacob 5 | * University of Maryland 6 | * dramninjas [at] gmail [dot] com 7 | * All rights reserved. 8 | * 9 | * Redistribution and use in source and binary forms, with or without 10 | * modification, are permitted provided that the following conditions are met: 11 | * 12 | * * Redistributions of source code must retain the above copyright notice, 13 | * this list of conditions and the following disclaimer. 14 | * 15 | * * Redistributions in binary form must reproduce the above copyright notice, 16 | * this list of conditions and the following disclaimer in the documentation 17 | * and/or other materials provided with the distribution. 18 | * 19 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 20 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 21 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 22 | * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 23 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 25 | * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 26 | * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 27 | * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | *********************************************************************************/ 30 | 31 | 32 | 33 | #ifndef MEMORYSYSTEM_H 34 | #define MEMORYSYSTEM_H 35 | 36 | //MemorySystem.h 37 | // 38 | //Header file for JEDEC memory system wrapper 39 | // 40 | 41 | #include "SimulatorObject.h" 42 | #include "SystemConfiguration.h" 43 | #include "MemoryController.h" 44 | #include "Rank.h" 45 | #include "Transaction.h" 46 | #include "Callback.h" 47 | #include "CSVWriter.h" 48 | #include 49 | 50 | namespace DRAMSim 51 | { 52 | typedef CallbackBase Callback_t; 53 | class MemorySystem : public SimulatorObject 54 | { 55 | public: 56 | //functions 57 | MemorySystem(unsigned id, CSVWriter &csvOut_, ostream &dramsim_log_, vector allIniReaders); 58 | virtual ~MemorySystem(); 59 | void update(); 60 | bool addTransaction(Transaction *trans); 61 | bool addTransaction(bool isWrite, uint64_t addr); 62 | void printStats(bool finalStats); 63 | bool WillAcceptTransaction(); 64 | void RegisterCallbacks( 65 | Callback_t *readDone, 66 | Callback_t *writeDone, 67 | void (*reportPower)(double bgpower, double burstpower, double refreshpower, double actprepower)); 68 | 69 | //fields 70 | vector allIniReaders; 71 | IniReader * iniReader; 72 | ostream &dramsim_log; 73 | MemoryController *memoryController; 74 | vector *ranks; 75 | deque pendingTransactions; 76 | 77 | 78 | //function pointers 79 | Callback_t* ReturnReadData; 80 | Callback_t* WriteDataDone; 81 | //TODO: make this a functor as well? 82 | static powerCallBack_t ReportPower; 83 | unsigned systemID; 84 | 85 | private: 86 | CSVWriter &csvOut; 87 | }; 88 | } 89 | 90 | #endif 91 | 92 | -------------------------------------------------------------------------------- /MultiChannelMemorySystem.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xiafei2011/HMSim1/d28ac72f652e3041dd45f52864a9c7c765edc6a1/MultiChannelMemorySystem.cpp -------------------------------------------------------------------------------- /MultiChannelMemorySystem.h: -------------------------------------------------------------------------------- 1 | /********************************************************************************* 2 | * Copyright (c) 2010-2011, Elliott Cooper-Balis 3 | * Paul Rosenfeld 4 | * Bruce Jacob 5 | * University of Maryland 6 | * dramninjas [at] gmail [dot] com 7 | * All rights reserved. 8 | * 9 | * Redistribution and use in source and binary forms, with or without 10 | * modification, are permitted provided that the following conditions are met: 11 | * 12 | * * Redistributions of source code must retain the above copyright notice, 13 | * this list of conditions and the following disclaimer. 14 | * 15 | * * Redistributions in binary form must reproduce the above copyright notice, 16 | * this list of conditions and the following disclaimer in the documentation 17 | * and/or other materials provided with the distribution. 18 | * 19 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 20 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 21 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 22 | * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 23 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 25 | * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 26 | * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 27 | * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | *********************************************************************************/ 30 | #include "SimulatorObject.h" 31 | #include "Transaction.h" 32 | #include "SystemConfiguration.h" 33 | #include "MemorySystem.h" 34 | #include "IniReader.h" 35 | #include "ClockDomain.h" 36 | #include "CSVWriter.h" 37 | 38 | 39 | namespace DRAMSim { 40 | 41 | 42 | class MultiChannelMemorySystem : public SimulatorObject 43 | { 44 | public: 45 | MultiChannelMemorySystem( 46 | const string &debugIniFilename_, 47 | const string &deviceIniFilename_, 48 | const string &deviceIniFilenamePcm_, 49 | const string &systemIniFilename_, 50 | const string &systemIniFilenamePcm_, 51 | const string &pwd_, 52 | const string &traceFilename_, 53 | unsigned megsOfMemory_, 54 | unsigned megsOfMemoryPcm_, 55 | string *visFilename_ 56 | // const IniReader::OverrideMap *paramOverrides, 57 | // const IniReader::OverrideMap *paramOverridesPcm 58 | ); 59 | virtual ~MultiChannelMemorySystem(); 60 | bool addTransaction(Transaction *trans); 61 | bool addTransaction(const Transaction &trans); 62 | bool addTransaction(bool isWrite, uint64_t addr); 63 | bool willAcceptTransaction(); 64 | bool willAcceptTransaction(uint64_t addr); 65 | void update(); 66 | void printStats(bool finalStats=false); 67 | ostream &getLogFile(); 68 | void RegisterCallbacks( 69 | TransactionCompleteCB *readDone, 70 | TransactionCompleteCB *writeDone, 71 | void (*reportPower)(double bgpower, double burstpower, double refreshpower, double actprepower)); 72 | 73 | void InitOutputFiles(string tracefilename); 74 | void setCPUClockSpeed(uint64_t cpuClkFreqHz); 75 | 76 | //output file 77 | std::ofstream visDataOut; 78 | ofstream dramsim_log; 79 | 80 | private: 81 | unsigned findChannelNumber(uint64_t addr); 82 | unsigned megsOfMemory; 83 | unsigned megsOfMemoryPcm; 84 | string debugIniFilename; 85 | string deviceIniFilename; 86 | string deviceIniFilenamePcm; 87 | string systemIniFilename; 88 | string systemIniFilenamePcm; 89 | string traceFilename; 90 | string pwd; 91 | string *visFilename; 92 | static void mkdirIfNotExist(string path); 93 | static bool fileExists(string path); 94 | vector channels; 95 | vector allIniReaders; 96 | vector deviceIniFilenames; 97 | vector deviceIniFilenamesPcm; 98 | ClockDomain::ClockDomainCrosser clockDomainCrosser; 99 | ClockDomain::ClockDomainCrosser clockDomainCrosserPcm; 100 | CSVWriter *csvOut; 101 | void actual_update(); 102 | void actual_update_pcm(); 103 | 104 | }; 105 | } 106 | -------------------------------------------------------------------------------- /PrintMacros.h: -------------------------------------------------------------------------------- 1 | /********************************************************************************* 2 | * Copyright (c) 2010-2011, Elliott Cooper-Balis 3 | * Paul Rosenfeld 4 | * Bruce Jacob 5 | * University of Maryland 6 | * dramninjas [at] gmail [dot] com 7 | * All rights reserved. 8 | * 9 | * Redistribution and use in source and binary forms, with or without 10 | * modification, are permitted provided that the following conditions are met: 11 | * 12 | * * Redistributions of source code must retain the above copyright notice, 13 | * this list of conditions and the following disclaimer. 14 | * 15 | * * Redistributions in binary form must reproduce the above copyright notice, 16 | * this list of conditions and the following disclaimer in the documentation 17 | * and/or other materials provided with the distribution. 18 | * 19 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 20 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 21 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 22 | * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 23 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 25 | * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 26 | * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 27 | * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | *********************************************************************************/ 30 | 31 | 32 | 33 | 34 | 35 | #ifndef PRINT_MACROS_H 36 | #define PRINT_MACROS_H 37 | 38 | extern int SHOW_SIM_OUTPUT; //enable or disable PRINT() statements -- set by flag in TraceBasedSim.cpp 39 | 40 | #define ERROR(str) std::cerr<<"[ERROR ("<<__FILE__<<":"<<__LINE__<<")]: "<NUM_BANKS, Bank(dramsim_log_,iniReader_)), 47 | bankStates(iniReader_->NUM_BANKS, BankState(dramsim_log_)), 48 | iniReader(iniReader_) 49 | 50 | { 51 | 52 | memoryController = NULL; 53 | outgoingDataPacket = NULL; 54 | dataCyclesLeft = 0; 55 | currentClockCycle = 0; 56 | 57 | #ifndef NO_STORAGE 58 | #endif 59 | 60 | } 61 | 62 | // mutators 63 | void Rank::setId(int id) 64 | { 65 | this->id = id; 66 | } 67 | 68 | // attachMemoryController() must be called before any other Rank functions 69 | // are called 70 | void Rank::attachMemoryController(MemoryController *memoryController) 71 | { 72 | this->memoryController = memoryController; 73 | } 74 | Rank::~Rank() 75 | { 76 | for (size_t i=0; iid << " Receiving On Bus : "); 88 | packet->print(); 89 | } 90 | if (VERIFICATION_OUTPUT) 91 | { 92 | packet->print(currentClockCycle,false); 93 | } 94 | 95 | switch (packet->busPacketType) 96 | { 97 | case READ: 98 | //make sure a read is allowed 99 | if (bankStates[packet->bank].currentBankState != RowActive || 100 | currentClockCycle < bankStates[packet->bank].nextRead || 101 | packet->row != bankStates[packet->bank].openRowAddress) 102 | { 103 | packet->print(); 104 | ERROR("== Error - Rank " << id << " received a READ when not allowed"); 105 | exit(0); 106 | } 107 | 108 | //update state table 109 | bankStates[packet->bank].nextPrecharge = max(bankStates[packet->bank].nextPrecharge, currentClockCycle + READ_TO_PRE_DELAY); 110 | for (size_t i=0;iNUM_BANKS;i++) 111 | { 112 | bankStates[i].nextRead = max(bankStates[i].nextRead, currentClockCycle + max(iniReader->tCCD, iniReader->BL/2)); 113 | bankStates[i].nextWrite = max(bankStates[i].nextWrite, currentClockCycle + READ_TO_WRITE_DELAY); 114 | } 115 | 116 | if(iniReader->SystemType == TYPE_NVM && iniReader->rowBufferPolicy == ClosePage) 117 | { 118 | bankStates[packet->bank].currentBankState = Idle; 119 | bankStates[packet->bank].nextActivate = iniReader->AL+iniReader->tRTP; 120 | } 121 | 122 | 123 | //get the read data and put it in the storage which delays until the appropriate time (RL) 124 | #ifndef NO_STORAGE 125 | banks[packet->bank].read(packet); 126 | #else 127 | packet->busPacketType = DATA; 128 | #endif 129 | readReturnPacket.push_back(packet); 130 | readReturnCountdown.push_back(iniReader->RL); 131 | break; 132 | case READ_P: 133 | //make sure a read is allowed 134 | if (bankStates[packet->bank].currentBankState != RowActive || 135 | currentClockCycle < bankStates[packet->bank].nextRead || 136 | packet->row != bankStates[packet->bank].openRowAddress) 137 | { 138 | ERROR("== Error - Rank " << id << " received a READ_P when not allowed"); 139 | exit(-1); 140 | } 141 | 142 | //update state table 143 | bankStates[packet->bank].currentBankState = Idle; 144 | bankStates[packet->bank].nextActivate = max(bankStates[packet->bank].nextActivate, currentClockCycle + READ_AUTOPRE_DELAY); 145 | for (size_t i=0;iNUM_BANKS;i++) 146 | { 147 | //will set next read/write for all banks - including current (which shouldnt matter since its now idle) 148 | bankStates[i].nextRead = max(bankStates[i].nextRead, currentClockCycle + max(iniReader->BL/2, iniReader->tCCD)); 149 | bankStates[i].nextWrite = max(bankStates[i].nextWrite, currentClockCycle + READ_TO_WRITE_DELAY); 150 | } 151 | 152 | //get the read data and put it in the storage which delays until the appropriate time (RL) 153 | #ifndef NO_STORAGE 154 | banks[packet->bank].read(packet); 155 | #else 156 | packet->busPacketType = DATA; 157 | #endif 158 | 159 | readReturnPacket.push_back(packet); 160 | readReturnCountdown.push_back(iniReader->RL); 161 | break; 162 | case WRITE: 163 | //make sure a write is allowed 164 | if (bankStates[packet->bank].currentBankState != RowActive || 165 | currentClockCycle < bankStates[packet->bank].nextWrite || 166 | packet->row != bankStates[packet->bank].openRowAddress) 167 | { 168 | ERROR("== Error - Rank " << id << " received a WRITE when not allowed"); 169 | bankStates[packet->bank].print(); 170 | exit(0); 171 | } 172 | 173 | //update state table 174 | bankStates[packet->bank].nextPrecharge = max(bankStates[packet->bank].nextPrecharge, currentClockCycle + WRITE_TO_PRE_DELAY); 175 | for (size_t i=0;iNUM_BANKS;i++) 176 | { 177 | bankStates[i].nextRead = max(bankStates[i].nextRead, currentClockCycle + WRITE_TO_READ_DELAY_B); 178 | bankStates[i].nextWrite = max(bankStates[i].nextWrite, currentClockCycle + max(iniReader->BL/2, iniReader->tCCD)); 179 | } 180 | 181 | //take note of where data is going when it arrives 182 | incomingWriteBank = packet->bank; 183 | incomingWriteRow = packet->row; 184 | incomingWriteColumn = packet->column; 185 | delete(packet); 186 | break; 187 | case WRITE_P: 188 | //make sure a write is allowed 189 | if (bankStates[packet->bank].currentBankState != RowActive || 190 | currentClockCycle < bankStates[packet->bank].nextWrite || 191 | packet->row != bankStates[packet->bank].openRowAddress) 192 | { 193 | ERROR("== Error - Rank " << id << " received a WRITE_P when not allowed"); 194 | exit(0); 195 | } 196 | 197 | //update state table 198 | bankStates[packet->bank].currentBankState = Idle; 199 | bankStates[packet->bank].nextActivate = max(bankStates[packet->bank].nextActivate, currentClockCycle + WRITE_AUTOPRE_DELAY); 200 | for (size_t i=0;iNUM_BANKS;i++) 201 | { 202 | bankStates[i].nextWrite = max(bankStates[i].nextWrite, currentClockCycle + max(iniReader->tCCD, iniReader->BL/2)); 203 | bankStates[i].nextRead = max(bankStates[i].nextRead, currentClockCycle + WRITE_TO_READ_DELAY_B); 204 | } 205 | 206 | //take note of where data is going when it arrives 207 | incomingWriteBank = packet->bank; 208 | incomingWriteRow = packet->row; 209 | incomingWriteColumn = packet->column; 210 | delete(packet); 211 | break; 212 | case ACTIVATE: 213 | //make sure activate is allowed 214 | if (bankStates[packet->bank].currentBankState != Idle || 215 | currentClockCycle < bankStates[packet->bank].nextActivate) 216 | { 217 | ERROR("== Error - Rank " << id << " received an ACT when not allowed"); 218 | packet->print(); 219 | bankStates[packet->bank].print(); 220 | exit(0); 221 | } 222 | 223 | bankStates[packet->bank].currentBankState = RowActive; 224 | bankStates[packet->bank].nextActivate = currentClockCycle + iniReader->tRC; 225 | bankStates[packet->bank].openRowAddress = packet->row; 226 | 227 | //if AL is greater than one, then posted-cas is enabled - handle accordingly 228 | if (iniReader->AL>0) 229 | { 230 | bankStates[packet->bank].nextWrite = currentClockCycle + (iniReader->tRCD-iniReader->AL); 231 | bankStates[packet->bank].nextRead = currentClockCycle + (iniReader->tRCD-iniReader->AL); 232 | } 233 | else 234 | { 235 | bankStates[packet->bank].nextWrite = currentClockCycle + (iniReader->tRCD-iniReader->AL); 236 | bankStates[packet->bank].nextRead = currentClockCycle + (iniReader->tRCD-iniReader->AL); 237 | } 238 | 239 | bankStates[packet->bank].nextPrecharge = currentClockCycle + iniReader->tRAS; 240 | for (size_t i=0;iNUM_BANKS;i++) 241 | { 242 | if (i != packet->bank) 243 | { 244 | bankStates[i].nextActivate = max(bankStates[i].nextActivate, currentClockCycle + iniReader->tRRD); 245 | } 246 | } 247 | delete(packet); 248 | break; 249 | case PRECHARGE: 250 | //make sure precharge is allowed 251 | if (bankStates[packet->bank].currentBankState != RowActive || 252 | currentClockCycle < bankStates[packet->bank].nextPrecharge) 253 | { 254 | ERROR("== Error - Rank " << id << " received a PRE when not allowed"); 255 | exit(0); 256 | } 257 | 258 | bankStates[packet->bank].currentBankState = Idle; 259 | bankStates[packet->bank].nextActivate = max(bankStates[packet->bank].nextActivate, currentClockCycle + iniReader->tRP); 260 | delete(packet); 261 | break; 262 | case REFRESH: 263 | refreshWaiting = false; 264 | for (size_t i=0;iNUM_BANKS;i++) 265 | { 266 | if (bankStates[i].currentBankState != Idle) 267 | { 268 | ERROR("== Error - Rank " << id << " received a REF when not allowed"); 269 | exit(0); 270 | } 271 | bankStates[i].nextActivate = currentClockCycle + iniReader->tRFC; 272 | } 273 | delete(packet); 274 | break; 275 | case DATA: 276 | // TODO: replace this check with something that works? 277 | /* 278 | if(packet->bank != incomingWriteBank || 279 | packet->row != incomingWriteRow || 280 | packet->column != incomingWriteColumn) 281 | { 282 | cout << "== Error - Rank " << id << " received a DATA packet to the wrong place" << endl; 283 | packet->print(); 284 | bankStates[packet->bank].print(); 285 | exit(0); 286 | } 287 | */ 288 | #ifndef NO_STORAGE 289 | banks[packet->bank].write(packet); 290 | #else 291 | // end of the line for the write packet 292 | #endif 293 | delete(packet); 294 | break; 295 | default: 296 | ERROR("== Error - Unknown BusPacketType trying to be sent to Bank"); 297 | exit(0); 298 | break; 299 | } 300 | } 301 | 302 | int Rank::getId() const 303 | { 304 | return this->id; 305 | } 306 | 307 | void Rank::update() 308 | { 309 | 310 | // An outgoing packet is one that is currently sending on the bus 311 | // do the book keeping for the packet's time left on the bus 312 | if (outgoingDataPacket != NULL) 313 | { 314 | dataCyclesLeft--; 315 | if (dataCyclesLeft == 0) 316 | { 317 | //if the packet is done on the bus, call receiveFromBus and free up the bus 318 | memoryController->receiveFromBus(outgoingDataPacket); 319 | outgoingDataPacket = NULL; 320 | } 321 | } 322 | 323 | // decrement the counter for all packets waiting to be sent back 324 | for (size_t i=0;i 0 && readReturnCountdown[0]==0) 331 | { 332 | // RL time has passed since the read was issued; this packet is 333 | // ready to go out on the bus 334 | 335 | outgoingDataPacket = readReturnPacket[0]; 336 | dataCyclesLeft = iniReader->BL/2; 337 | 338 | // remove the packet from the ranks 339 | readReturnPacket.erase(readReturnPacket.begin()); 340 | readReturnCountdown.erase(readReturnCountdown.begin()); 341 | 342 | if (DEBUG_BUS) 343 | { 344 | PRINTN(" -- R" << this->id << " Issuing On Data Bus : "); 345 | outgoingDataPacket->print(); 346 | PRINT(""); 347 | } 348 | 349 | } 350 | } 351 | 352 | //power down the rank 353 | void Rank::powerDown() 354 | { 355 | //perform checks 356 | for (size_t i=0;iNUM_BANKS;i++) 357 | { 358 | if (bankStates[i].currentBankState != Idle) 359 | { 360 | ERROR("== Error - Trying to power down rank " << id << " while not all banks are idle"); 361 | exit(0); 362 | } 363 | 364 | bankStates[i].nextPowerUp = currentClockCycle + iniReader->tCKE; 365 | bankStates[i].currentBankState = PowerDown; 366 | } 367 | 368 | isPowerDown = true; 369 | } 370 | 371 | //power up the rank 372 | void Rank::powerUp() 373 | { 374 | if (!isPowerDown) 375 | { 376 | ERROR("== Error - Trying to power up rank " << id << " while it is not already powered down"); 377 | exit(0); 378 | } 379 | 380 | isPowerDown = false; 381 | 382 | for (size_t i=0;iNUM_BANKS;i++) 383 | { 384 | if (bankStates[i].nextPowerUp > currentClockCycle) 385 | { 386 | ERROR("== Error - Trying to power up rank " << id << " before we're allowed to"); 387 | ERROR(bankStates[i].nextPowerUp << " " << currentClockCycle); 388 | exit(0); 389 | } 390 | bankStates[i].nextActivate = currentClockCycle + iniReader->tXP; 391 | bankStates[i].currentBankState = Idle; 392 | } 393 | } 394 | -------------------------------------------------------------------------------- /Rank.h: -------------------------------------------------------------------------------- 1 | /********************************************************************************* 2 | * Copyright (c) 2010-2011, Elliott Cooper-Balis 3 | * Paul Rosenfeld 4 | * Bruce Jacob 5 | * University of Maryland 6 | * dramninjas [at] gmail [dot] com 7 | * All rights reserved. 8 | * 9 | * Redistribution and use in source and binary forms, with or without 10 | * modification, are permitted provided that the following conditions are met: 11 | * 12 | * * Redistributions of source code must retain the above copyright notice, 13 | * this list of conditions and the following disclaimer. 14 | * 15 | * * Redistributions in binary form must reproduce the above copyright notice, 16 | * this list of conditions and the following disclaimer in the documentation 17 | * and/or other materials provided with the distribution. 18 | * 19 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 20 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 21 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 22 | * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 23 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 25 | * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 26 | * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 27 | * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | *********************************************************************************/ 30 | 31 | 32 | 33 | 34 | #ifndef RANK_H 35 | #define RANK_H 36 | 37 | #include "SimulatorObject.h" 38 | #include "BusPacket.h" 39 | #include "SystemConfiguration.h" 40 | #include "Bank.h" 41 | #include "BankState.h" 42 | #include "IniReader.h" 43 | 44 | using namespace std; 45 | using namespace DRAMSim; 46 | 47 | namespace DRAMSim 48 | { 49 | class MemoryController; //forward declaration 50 | class Rank : public SimulatorObject 51 | { 52 | private: 53 | int id; 54 | ostream &dramsim_log; 55 | unsigned incomingWriteBank; 56 | unsigned incomingWriteRow; 57 | unsigned incomingWriteColumn; 58 | bool isPowerDown; 59 | 60 | public: 61 | //functions 62 | Rank(ostream &dramsim_log_,IniReader * iniReader); 63 | virtual ~Rank(); 64 | void receiveFromBus(BusPacket *packet); 65 | void attachMemoryController(MemoryController *mc); 66 | int getId() const; 67 | void setId(int id); 68 | void update(); 69 | void powerUp(); 70 | void powerDown(); 71 | 72 | //fields 73 | MemoryController *memoryController; 74 | BusPacket *outgoingDataPacket; 75 | unsigned dataCyclesLeft; 76 | bool refreshWaiting; 77 | 78 | //these are vectors so that each element is per-bank 79 | vector readReturnPacket; 80 | vector readReturnCountdown; 81 | vector banks; 82 | vector bankStates; 83 | IniReader * iniReader; 84 | 85 | }; 86 | } 87 | #endif 88 | 89 | -------------------------------------------------------------------------------- /SimulatorObject.cpp: -------------------------------------------------------------------------------- 1 | /********************************************************************************* 2 | * Copyright (c) 2010-2011, Elliott Cooper-Balis 3 | * Paul Rosenfeld 4 | * Bruce Jacob 5 | * University of Maryland 6 | * dramninjas [at] gmail [dot] com 7 | * All rights reserved. 8 | * 9 | * Redistribution and use in source and binary forms, with or without 10 | * modification, are permitted provided that the following conditions are met: 11 | * 12 | * * Redistributions of source code must retain the above copyright notice, 13 | * this list of conditions and the following disclaimer. 14 | * 15 | * * Redistributions in binary form must reproduce the above copyright notice, 16 | * this list of conditions and the following disclaimer in the documentation 17 | * and/or other materials provided with the distribution. 18 | * 19 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 20 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 21 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 22 | * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 23 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 25 | * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 26 | * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 27 | * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | *********************************************************************************/ 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | //SimulatorObject.cpp 39 | // 40 | //Base class for all classes in the simulator 41 | // 42 | 43 | #include 44 | #include "SimulatorObject.h" 45 | 46 | using namespace DRAMSim; 47 | using namespace std; 48 | 49 | void SimulatorObject::step() 50 | { 51 | currentClockCycle++; 52 | } 53 | 54 | 55 | -------------------------------------------------------------------------------- /SimulatorObject.h: -------------------------------------------------------------------------------- 1 | /********************************************************************************* 2 | * Copyright (c) 2010-2011, Elliott Cooper-Balis 3 | * Paul Rosenfeld 4 | * Bruce Jacob 5 | * University of Maryland 6 | * dramninjas [at] gmail [dot] com 7 | * All rights reserved. 8 | * 9 | * Redistribution and use in source and binary forms, with or without 10 | * modification, are permitted provided that the following conditions are met: 11 | * 12 | * * Redistributions of source code must retain the above copyright notice, 13 | * this list of conditions and the following disclaimer. 14 | * 15 | * * Redistributions in binary form must reproduce the above copyright notice, 16 | * this list of conditions and the following disclaimer in the documentation 17 | * and/or other materials provided with the distribution. 18 | * 19 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 20 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 21 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 22 | * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 23 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 25 | * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 26 | * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 27 | * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | *********************************************************************************/ 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | #ifndef SIMULATOROBJ_H 39 | #define SIMULATOROBJ_H 40 | 41 | //SimulatorObject.h 42 | // 43 | //Header file for simulator object class 44 | // 45 | 46 | #include 47 | 48 | namespace DRAMSim 49 | { 50 | class SimulatorObject 51 | { 52 | public: 53 | uint64_t currentClockCycle; 54 | 55 | void step(); 56 | virtual void update()=0; 57 | }; 58 | } 59 | 60 | #endif 61 | 62 | -------------------------------------------------------------------------------- /SystemConfiguration.h: -------------------------------------------------------------------------------- 1 | /********************************************************************************* 2 | * Copyright (c) 2010-2011, Elliott Cooper-Balis 3 | * Paul Rosenfeld 4 | * Bruce Jacob 5 | * University of Maryland 6 | * dramninjas [at] gmail [dot] com 7 | * All rights reserved. 8 | * 9 | * Redistribution and use in source and binary forms, with or without 10 | * modification, are permitted provided that the following conditions are met: 11 | * 12 | * * Redistributions of source code must retain the above copyright notice, 13 | * this list of conditions and the following disclaimer. 14 | * 15 | * * Redistributions in binary form must reproduce the above copyright notice, 16 | * this list of conditions and the following disclaimer in the documentation 17 | * and/or other materials provided with the distribution. 18 | * 19 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 20 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 21 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 22 | * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 23 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 25 | * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 26 | * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 27 | * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | *********************************************************************************/ 30 | 31 | 32 | 33 | #ifndef SYSCONFIG_H 34 | #define SYSCONFIG_H 35 | 36 | #include 37 | #include 38 | #include 39 | #include 40 | #include 41 | #include 42 | #include "PrintMacros.h" 43 | 44 | #ifdef __APPLE__ 45 | #include 46 | #endif 47 | 48 | //SystemConfiguration.h 49 | // 50 | //Configuration values for the current system 51 | 52 | 53 | 54 | //number of latencies per bucket in the latency histogram 55 | //TODO: move to system ini file 56 | #define HISTOGRAM_BIN_SIZE 10 57 | 58 | extern std::ofstream cmd_verify_out; //used by BusPacket.cpp if VERIFICATION_OUTPUT is enabled 59 | //extern std::ofstream visDataOut; 60 | 61 | //TODO: namespace these to DRAMSim:: 62 | extern bool VERIFICATION_OUTPUT; // output suitable to feed to modelsim 63 | 64 | //#define NUM_MEMTYPES 2 // never used 65 | #define TYPE_DRAM 0 66 | #define TYPE_NVM 1 67 | #define TYPE_NODEV 9999 68 | 69 | extern unsigned NUM_CHANS; 70 | extern bool DEBUG_TRANS_Q; 71 | extern bool DEBUG_CMD_Q; 72 | extern bool DEBUG_ADDR_MAP; 73 | extern bool DEBUG_BANKSTATE; 74 | extern bool DEBUG_BUS; 75 | extern bool DEBUG_BANKS; 76 | extern bool DEBUG_POWER; 77 | extern bool USE_LOW_POWER; 78 | extern bool VIS_FILE_OUTPUT; 79 | 80 | //same bank 81 | #define READ_TO_PRE_DELAY (iniReader->AL+iniReader->BL/2+ max(iniReader->tRTP,iniReader->tCCD)-iniReader->tCCD) 82 | #define WRITE_TO_PRE_DELAY (iniReader->WL+iniReader->BL/2+iniReader->tWR) 83 | #define READ_TO_WRITE_DELAY (iniReader->RL+iniReader->BL/2+iniReader->tRTRS-iniReader->WL) 84 | #define READ_AUTOPRE_DELAY (iniReader->AL+iniReader->tRTP+iniReader->tRP) 85 | #define WRITE_AUTOPRE_DELAY (iniReader->WL+iniReader->BL/2+iniReader->tWR+iniReader->tRP) 86 | #define WRITE_TO_READ_DELAY_B (iniReader->WL+iniReader->BL/2+iniReader->tWTR) //interbank 87 | #define WRITE_TO_READ_DELAY_R (iniReader->WL+iniReader->BL/2+iniReader->tRTRS-iniReader->RL) //interrank 88 | 89 | /* 90 | extern unsigned JEDEC_DATA_BUS_BITS; 91 | 92 | //Memory Controller related parameters 93 | extern unsigned TRANS_QUEUE_DEPTH; 94 | extern unsigned CMD_QUEUE_DEPTH; 95 | 96 | extern unsigned EPOCH_LENGTH; 97 | 98 | extern unsigned TOTAL_ROW_ACCESSES; 99 | 100 | extern std::string ROW_BUFFER_POLICY; 101 | extern std::string SCHEDULING_POLICY; 102 | extern std::string ADDRESS_MAPPING_SCHEME; 103 | extern std::string QUEUING_STRUCTURE; 104 | */ 105 | 106 | enum TraceType 107 | { 108 | k6, 109 | mase, 110 | misc 111 | }; 112 | 113 | enum AddressMappingScheme 114 | { 115 | Scheme1, 116 | Scheme2, 117 | Scheme3, 118 | Scheme4, 119 | Scheme5, 120 | Scheme6, 121 | Scheme7 122 | }; 123 | 124 | // used in MemoryController and CommandQueue 125 | enum RowBufferPolicy 126 | { 127 | OpenPage, 128 | ClosePage 129 | }; 130 | 131 | // Only used in CommandQueue 132 | enum QueuingStructure 133 | { 134 | PerRank, 135 | PerRankPerBank 136 | }; 137 | 138 | enum SchedulingPolicy 139 | { 140 | RankThenBankRoundRobin, 141 | BankThenRankRoundRobin 142 | }; 143 | 144 | 145 | // set by IniReader.cpp 146 | 147 | 148 | namespace DRAMSim 149 | { 150 | typedef void (*returnCallBack_t)(unsigned id, uint64_t addr, uint64_t clockcycle); 151 | typedef void (*powerCallBack_t)(double bgpower, double burstpower, double refreshpower, double actprepower); 152 | 153 | /* 154 | extern RowBufferPolicy rowBufferPolicy; 155 | extern SchedulingPolicy schedulingPolicy; 156 | extern AddressMappingScheme addressMappingScheme; 157 | extern QueuingStructure queuingStructure; 158 | */ 159 | // 160 | //FUNCTIONS 161 | // 162 | 163 | unsigned inline dramsim_log2(unsigned value) 164 | { 165 | unsigned logbase2 = 0; 166 | unsigned orig = value; 167 | value>>=1; 168 | while (value>0) 169 | { 170 | value >>= 1; 171 | logbase2++; 172 | } 173 | if ((unsigned)1< 39 | #include 40 | #include 41 | #include 42 | #include 43 | #include 44 | #include 45 | 46 | 47 | #include "SystemConfiguration.h" 48 | #include "MemorySystem.h" 49 | #include "MultiChannelMemorySystem.h" 50 | #include "Transaction.h" 51 | #include "IniReader.h" 52 | 53 | 54 | using namespace DRAMSim; 55 | using namespace std; 56 | 57 | 58 | time_t begin; 59 | time_t end; 60 | 61 | size_t cpuCycle=0; 62 | 63 | 64 | int64_t *buf; 65 | unsigned int timer; 66 | unsigned int r_w; 67 | unsigned long timerActual = 0; 68 | unsigned int oldTimer; 69 | int flag = 1; 70 | FILE *fpTrace; 71 | unsigned long currentNum = 0; 72 | unsigned long NUM = 100000; 73 | 74 | 75 | 76 | 77 | //#define RETURN_TRANSACTIONS 1 78 | 79 | #ifndef _SIM_ 80 | int SHOW_SIM_OUTPUT = 1; 81 | ofstream visDataOut; //mostly used in MemoryController 82 | 83 | #ifdef RETURN_TRANSACTIONS 84 | class TransactionReceiver 85 | { 86 | private: 87 | map > pendingReadRequests; 88 | map > pendingWriteRequests; 89 | 90 | public: 91 | void add_pending(const Transaction &t, uint64_t cycle) 92 | { 93 | // C++ lists are ordered, so the list will always push to the back and 94 | // remove at the front to ensure ordering 95 | if (t.transactionType == DATA_READ) 96 | { 97 | pendingReadRequests[t.address].push_back(cycle); 98 | } 99 | else if (t.transactionType == DATA_WRITE) 100 | { 101 | pendingWriteRequests[t.address].push_back(cycle); 102 | } 103 | else 104 | { 105 | ERROR("This should never happen"); 106 | exit(-1); 107 | } 108 | } 109 | 110 | void read_complete(unsigned id, uint64_t address, uint64_t done_cycle) 111 | { 112 | map >::iterator it; 113 | it = pendingReadRequests.find(address); 114 | if (it == pendingReadRequests.end()) 115 | { 116 | ERROR("Cant find a pending read for this one"); 117 | exit(-1); 118 | } 119 | else 120 | { 121 | if (it->second.size() == 0) 122 | { 123 | ERROR("Nothing here, either"); 124 | exit(-1); 125 | } 126 | } 127 | 128 | uint64_t added_cycle = pendingReadRequests[address].front(); 129 | uint64_t latency = done_cycle - added_cycle; 130 | 131 | pendingReadRequests[address].pop_front(); 132 | cout << "Read Callback: 0x"<< std::hex << address << std::dec << " latency="<"< >::iterator it; 137 | it = pendingWriteRequests.find(address); 138 | if (it == pendingWriteRequests.end()) 139 | { 140 | ERROR("Cant find a pending read for this one"); 141 | exit(-1); 142 | } 143 | else 144 | { 145 | if (it->second.size() == 0) 146 | { 147 | ERROR("Nothing here, either"); 148 | exit(-1); 149 | } 150 | } 151 | 152 | uint64_t added_cycle = pendingWriteRequests[address].front(); 153 | uint64_t latency = done_cycle - added_cycle; 154 | 155 | pendingWriteRequests[address].pop_front(); 156 | cout << "Write Callback: 0x"<< std::hex << address << std::dec << " latency="<"<>30) & 0xfffffULL); 191 | r_w = (unsigned int)( ((buf[currentNum])>>29) & 0x1ULL ); 192 | addr = (uint64_t)( (buf[currentNum]<<3) & 0xffffffffULL ); 193 | if(flag) 194 | { 195 | flag = 0; 196 | } 197 | else 198 | { 199 | timerActual += oldTimer; 200 | } 201 | 202 | 203 | if(r_w == 1) 204 | { 205 | transType = DATA_READ; 206 | } 207 | else if(r_w == 0) 208 | { 209 | transType = DATA_WRITE; 210 | } 211 | else 212 | { 213 | ERROR("== Unknown Command : "<>hex>>addr; 220 | 221 | //if this is set to false, clockCycle will remain at 0, and every line read from the trace 222 | // will be allowed to be issued 223 | if (useClockCycle) 224 | { 225 | clockCycle = timerActual; 226 | } 227 | 228 | oldTimer = timer*5; 229 | 230 | 231 | return dataBuffer; 232 | } 233 | 234 | 235 | #ifndef _SIM_ 236 | 237 | void alignTransactionAddress(Transaction &trans) 238 | { 239 | // zero out the low order bits which correspond to the size of a transaction 240 | /* 241 | 242 | unsigned throwAwayBits = dramsim_log2((BL*JEDEC_DATA_BUS_BITS/8)); 243 | 244 | trans.address >>= throwAwayBits; 245 | trans.address <<= throwAwayBits; 246 | */ 247 | } 248 | 249 | /** 250 | * Override options can be specified on the command line as -o key1=value1,key2=value2 251 | * this method should parse the key-value pairs and put them into a map 252 | **/ 253 | IniReader::OverrideMap *parseParamOverrides(const string &kv_str) 254 | { 255 | IniReader::OverrideMap *kv_map = new IniReader::OverrideMap(); 256 | size_t start = 0, comma=0, equal_sign=0; 257 | // split the commas if they are there 258 | while (1) 259 | { 260 | equal_sign = kv_str.find('=', start); 261 | if (equal_sign == string::npos) 262 | { 263 | break; 264 | } 265 | 266 | comma = kv_str.find(',', equal_sign); 267 | if (comma == string::npos) 268 | { 269 | comma = kv_str.length(); 270 | } 271 | 272 | string key = kv_str.substr(start, equal_sign-start); 273 | string value = kv_str.substr(equal_sign+1, comma-equal_sign-1); 274 | 275 | (*kv_map)[key] = value; 276 | start = comma+1; 277 | 278 | } 279 | return kv_map; 280 | } 281 | 282 | int main(int argc, char **argv) 283 | { 284 | 285 | begin = clock(); 286 | 287 | int c; 288 | TraceType traceType; 289 | string traceFileName; 290 | string debugIniFilename; 291 | string systemIniFilename("systemdram.ini"); 292 | string deviceIniFilename; 293 | string systemIniFilenamePcm("systempcm.ini"); 294 | string deviceIniFilenamePcm; 295 | string pwdString; 296 | string *visFilename = new string("xxx.vis"); 297 | unsigned megsOfMemory=2048; 298 | unsigned megsOfMemoryPcm=2048; 299 | bool useClockCycle=true; 300 | 301 | IniReader::OverrideMap *paramOverrides = NULL; 302 | 303 | 304 | //getopt stuff 305 | while (1) 306 | { 307 | static struct option long_options[] = 308 | { 309 | {"deviceini", required_argument, 0, 'd'}, 310 | {"deviceiniPcm", required_argument, 0, 'e'}, 311 | {"tracefile", required_argument, 0, 't'}, 312 | {"systemini", required_argument, 0, 's'}, 313 | {"systeminiPcm", required_argument, 0, 'x'}, 314 | {"debug", required_argument, 0, 'b'}, 315 | {"pwd", required_argument, 0, 'p'}, 316 | {"numInstructions", required_argument, 0, 'c'}, 317 | {"option", required_argument, 0, 'o'}, 318 | {"quiet", no_argument, &SHOW_SIM_OUTPUT, 'q'}, 319 | {"help", no_argument, 0, 'h'}, 320 | {"size", required_argument, 0, 'S'}, 321 | {"sizePcm", required_argument, 0, 'X'}, 322 | {"visfile", required_argument, 0, 'v'}, 323 | {0, 0, 0, 0} 324 | }; 325 | int option_index=0; //for getopt 326 | c = getopt_long (argc, argv, "t:b:s:x:c:d:e:o:p:X:S:v:qn", long_options, &option_index); 327 | if (c == -1) 328 | { 329 | break; 330 | } 331 | switch (c) 332 | { 333 | case 0: //TODO: figure out what the hell this does, cuz it never seems to get called 334 | if (long_options[option_index].flag != 0) //do nothing on a flag 335 | { 336 | printf("setting flag\n"); 337 | break; 338 | } 339 | printf("option %s",long_options[option_index].name); 340 | if (optarg) 341 | { 342 | printf(" with arg %s", optarg); 343 | } 344 | printf("\n"); 345 | break; 346 | case 'h': 347 | usage(); 348 | exit(0); 349 | break; 350 | case 't': 351 | traceFileName = string(optarg); 352 | break; 353 | case 'b': 354 | debugIniFilename = string(optarg); 355 | break; 356 | case 's': 357 | systemIniFilename = string(optarg); 358 | break; 359 | case 'x': 360 | systemIniFilenamePcm = string(optarg); 361 | break; 362 | case 'd': 363 | deviceIniFilename = string(optarg); 364 | break; 365 | case 'e': 366 | deviceIniFilenamePcm = string(optarg); 367 | break; 368 | case 'c': 369 | NUM = atol(optarg); 370 | break; 371 | case 'X': 372 | megsOfMemoryPcm=atoi(optarg); 373 | break; 374 | case 'S': 375 | megsOfMemory=atoi(optarg); 376 | break; 377 | case 'p': 378 | pwdString = string(optarg); 379 | break; 380 | case 'q': 381 | SHOW_SIM_OUTPUT=false; 382 | break; 383 | case 'n': 384 | useClockCycle=false; 385 | break; 386 | case 'o': 387 | paramOverrides = parseParamOverrides(string(optarg)); 388 | break; 389 | case 'v': 390 | visFilename = new string(optarg); 391 | break; 392 | case '?': 393 | usage(); 394 | exit(-1); 395 | break; 396 | } 397 | } 398 | 399 | // get the trace filename 400 | // string temp = traceFileName.substr(traceFileName.find_last_of("/")+1); 401 | 402 | //get the prefix of the trace name 403 | /* 404 | temp = temp.substr(0,temp.find_first_of("_")); 405 | if (temp=="mase") 406 | { 407 | traceType = mase; 408 | } 409 | else if (temp=="k6") 410 | { 411 | traceType = k6; 412 | } 413 | else if (temp=="misc") 414 | { 415 | traceType = misc; 416 | } 417 | else 418 | { 419 | ERROR("== Unknown Tracefile Type : "< 0 && traceFileName[0] != '/') 436 | { 437 | traceFileName = pwdString + "/" +traceFileName; 438 | } 439 | 440 | DEBUG("== Loading trace file '"<=clockCycle) 512 | { 513 | if (!(*memorySystem).addTransaction(trans)) 514 | { 515 | pendingTrans = true; 516 | } 517 | else 518 | { 519 | #ifdef RETURN_TRANSACTIONS 520 | transactionReceiver.add_pending(trans, cpuCycle); 521 | #endif 522 | // the memory system accepted our request so now it takes ownership of it 523 | trans = NULL; 524 | currentNum++; 525 | 526 | } 527 | } 528 | else 529 | { 530 | pendingTrans = true; 531 | } 532 | 533 | } 534 | else 535 | { 536 | //we're out of trace, set pending=false and let the thing spin without adding transactions 537 | pendingTrans = false; 538 | } 539 | } 540 | 541 | else if (pendingTrans && cpuCycle >= clockCycle) 542 | { 543 | pendingTrans = !(*memorySystem).addTransaction(trans); 544 | if (!pendingTrans) 545 | { 546 | #ifdef RETURN_TRANSACTIONS 547 | transactionReceiver.add_pending(trans, cpuCycle); 548 | #endif 549 | trans=NULL; 550 | currentNum++; 551 | 552 | } 553 | } 554 | 555 | (*memorySystem).update(); 556 | } 557 | 558 | //traceFile.close(); 559 | fclose(fpTrace); 560 | memorySystem->printStats(true); 561 | // make valgrind happy 562 | if (trans) 563 | { 564 | delete trans; 565 | } 566 | delete(memorySystem); 567 | 568 | end = clock(); 569 | 570 | cout<<"clock:"<(end-begin)/CLOCKS_PER_SEC/60<<"min"<(end-begin)/CLOCKS_PER_SEC*1000<<"ms"<SystemType == TYPE_NVM) 76 | { 77 | return READ; 78 | } 79 | else 80 | { 81 | if (iniReader->rowBufferPolicy == ClosePage) 82 | { 83 | return READ_P; 84 | } 85 | else if (iniReader->rowBufferPolicy == OpenPage) 86 | { 87 | return READ; 88 | } 89 | } 90 | 91 | ERROR("Unknown row buffer policy"); 92 | abort(); 93 | 94 | break; 95 | case DATA_WRITE: 96 | if (iniReader->rowBufferPolicy == ClosePage) 97 | { 98 | return WRITE_P; 99 | } 100 | else if (iniReader->rowBufferPolicy == OpenPage) 101 | { 102 | return WRITE; 103 | } 104 | else 105 | { 106 | ERROR("Unknown row buffer policy"); 107 | abort(); 108 | } 109 | break; 110 | default: 111 | ERROR("This transaction type doesn't have a corresponding bus packet type"); 112 | abort(); 113 | } 114 | } 115 | }; 116 | 117 | } 118 | 119 | #endif 120 | 121 | -------------------------------------------------------------------------------- /conf/DDR3_micron_32M_8B_x8_sg25E.ini: -------------------------------------------------------------------------------- 1 | NUM_BANKS=8 2 | NUM_ROWS=32768 3 | NUM_COLS=1024 4 | DEVICE_WIDTH=8 5 | 6 | ;in nanoseconds 7 | ;#define REFRESH_PERIOD 7800 8 | REFRESH_PERIOD=7800 9 | tCK=2.5 ;* 10 | 11 | CL=5 ;* 12 | AL=0 ;* 13 | ;AL=3; needs to be tRCD-1 or 0 14 | ;RL=(CL+AL) 15 | ;WL=(RL-1) 16 | BL=8 ;* 17 | tRAS=15;* 18 | tRCD=5 ;* 19 | tRRD=4 ;* 20 | tRC=20 ;* 21 | tRP=5 ;* 22 | tCCD=4 ;* 23 | tRTP=4 ;* 24 | tWTR=4 ;* 25 | tWR=6 ;* 26 | tRTRS=1; -- RANK PARAMETER, TODO 27 | tRFC=64;* 28 | tFAW=16;* 29 | tCKE=3 ;* 30 | tXP=3 ;* 31 | 32 | tCMD=1 ;* 33 | 34 | ArrayReadEnergy=1.17; 35 | ArrayWriteEnergy=0.39; 36 | RowBufferReadEnergy=0.93; 37 | RowBufferWriteEnergy=1.02; 38 | 39 | IDD0=100; 40 | IDD1=115; 41 | IDD2P=10; 42 | IDD2Q=50; 43 | IDD2N=50; 44 | IDD3Pf=45; 45 | IDD3Ps=45; 46 | IDD3N=65; 47 | IDD4W=230; 48 | IDD4R=195; 49 | IDD5=275; 50 | IDD6=9; 51 | IDD6L=12; 52 | IDD7=400; 53 | 54 | ;same bank 55 | ;READ_TO_PRE_DELAY=(AL+BL/2+max(tRTP,2)-2) 56 | ;WRITE_TO_PRE_DELAY=(WL+BL/2+tWR) 57 | ;READ_TO_WRITE_DELAY=(RL+BL/2+tRTRS-WL) 58 | ;READ_AUTOPRE_DELAY=(AL+tRTP+tRP) 59 | ;WRITE_AUTOPRE_DELAY=(WL+BL/2+tWR+tRP) 60 | ;WRITE_TO_READ_DELAY_B=(WL+BL/2+tWTR);interbank 61 | ;WRITE_TO_READ_DELAY_R=(WL+BL/2+tRTRS-RL);interrank 62 | 63 | Vdd=1.5 ; TODO: double check this 64 | -------------------------------------------------------------------------------- /conf/PCM_micron_16M_8B_x16_sg25E.ini: -------------------------------------------------------------------------------- 1 | NUM_BANKS=8 2 | NUM_ROWS=8192 3 | NUM_COLS=1024 4 | DEVICE_WIDTH=16 5 | 6 | ;in nanoseconds 7 | ;#define REFRESH_PERIOD 7800 8 | REFRESH_PERIOD=7800 9 | tCK=2.5 ;* 10 | 11 | CL=5 ;* 12 | AL=0 ;* 13 | ;AL=3; needs to be tRCD-1 or 0 14 | ;RL=(CL+AL) 15 | ;WL=(RL-1) 16 | BL=8 ;* 17 | tRAS=36;* tRAS = tRCD + tCWD + tBURST + tWR 18 | tRCD=22 ;* 19 | tRRD=4 ;* 20 | tRC=96 ;* tRC = tRAS + tRP 21 | tRP=60 ;* 22 | tCCD=4 ;* 23 | tRTP=4 ;* 24 | tWTR=4 ;* 25 | tWR=6 ;* 26 | tRTRS=1; -- RANK PARAMETER, TODO 27 | tRFC=64;* 28 | tFAW=16;* 29 | tCKE=3 ;* 30 | tXP=3 ;* 31 | 32 | tCMD=1 ;* 33 | 34 | ArrayReadEnergy=2.47; 35 | ArrayWriteEnergy=16.82; 36 | RowBufferReadEnergy=0.93; 37 | RowBufferWriteEnergy=1.02; 38 | 39 | IDD0=100; 40 | IDD1=115; 41 | IDD2P=10; 42 | IDD2Q=50; 43 | IDD2N=50; 44 | IDD3Pf=45; 45 | IDD3Ps=45; 46 | IDD3N=65; 47 | IDD4W=230; 48 | IDD4R=195; 49 | IDD5=275; 50 | IDD6=9; 51 | IDD6L=12; 52 | IDD7=400; 53 | 54 | ;same bank 55 | ;READ_TO_PRE_DELAY=(AL+BL/2+max(tRTP,2)-2) 56 | ;WRITE_TO_PRE_DELAY=(WL+BL/2+tWR) 57 | ;READ_TO_WRITE_DELAY=(RL+BL/2+tRTRS-WL) 58 | ;READ_AUTOPRE_DELAY=(AL+tRTP+tRP) 59 | ;WRITE_AUTOPRE_DELAY=(WL+BL/2+tWR+tRP) 60 | ;WRITE_TO_READ_DELAY_B=(WL+BL/2+tWTR);interbank 61 | ;WRITE_TO_READ_DELAY_R=(WL+BL/2+tRTRS-RL);interrank 62 | 63 | Vdd=1.5 ; TODO: double check this 64 | -------------------------------------------------------------------------------- /conf/debug_config.ini: -------------------------------------------------------------------------------- 1 | NUM_CHANS=2 2 | DEBUG_TRANS_Q=false 3 | DEBUG_CMD_Q=false 4 | DEBUG_ADDR_MAP=false 5 | DEBUG_BUS=false 6 | DEBUG_BANKSTATE=false 7 | DEBUG_BANKS=false 8 | DEBUG_POWER=false 9 | VIS_FILE_OUTPUT=true 10 | USE_LOW_POWER=true ; go into low power mode when idle? 11 | VERIFICATION_OUTPUT=false ; should be false for normal operation 12 | -------------------------------------------------------------------------------- /conf/systemdram.ini: -------------------------------------------------------------------------------- 1 | ; COPY THIS FILE AND MODIFY IT TO SUIT YOUR NEEDS 2 | 3 | ;NUM_CHANS=1 ; number of *logically independent* channels (i.e. each with a separate memory controller); should be a power of 2 4 | JEDEC_DATA_BUS_BITS=64 ; Always 64 for DDRx; if you want multiple *ganged* channels, set this to N*64 5 | TRANS_QUEUE_DEPTH=32 ; transaction queue, i.e., CPU-level commands such as: READ 0xbeef 6 | CMD_QUEUE_DEPTH=32 ; command queue, i.e., DRAM-level commands such as: CAS 544, RAS 4 7 | EPOCH_LENGTH=100000000 ; length of an epoch in cycles (granularity of simulation) 8 | ROW_BUFFER_POLICY=close_page ; close_page or open_page 9 | ADDRESS_MAPPING_SCHEME=scheme4 ;valid schemes 1-7; For multiple independent channels, use scheme7 since it has the most parallelism 10 | SCHEDULING_POLICY=rank_then_bank_round_robin ; bank_then_rank_round_robin or rank_then_bank_round_robin 11 | QUEUING_STRUCTURE=per_rank_per_bank ;per_rank or per_rank_per_bank 12 | TOTAL_ROW_ACCESSES=4 ; maximum number of open page requests to send to the same row before forcing a row close (to prevent starvation) 13 | 14 | -------------------------------------------------------------------------------- /conf/systempcm.ini: -------------------------------------------------------------------------------- 1 | ; COPY THIS FILE AND MODIFY IT TO SUIT YOUR NEEDS 2 | 3 | ;NUM_CHANS=1 ; number of *logically independent* channels (i.e. each with a separate memory controller); should be a power of 2 4 | JEDEC_DATA_BUS_BITS=64 ; Always 64 for DDRx; if you want multiple *ganged* channels, set this to N*64 5 | TRANS_QUEUE_DEPTH=32 ; transaction queue, i.e., CPU-level commands such as: READ 0xbeef 6 | CMD_QUEUE_DEPTH=32 ; command queue, i.e., DRAM-level commands such as: CAS 544, RAS 4 7 | EPOCH_LENGTH=100000000 ; length of an epoch in cycles (granularity of simulation) 8 | ROW_BUFFER_POLICY=close_page ; close_page or open_page 9 | ADDRESS_MAPPING_SCHEME=scheme4 ;valid schemes 1-7; For multiple independent channels, use scheme7 since it has the most parallelism 10 | SCHEDULING_POLICY=rank_then_bank_round_robin ; bank_then_rank_round_robin or rank_then_bank_round_robin 11 | QUEUING_STRUCTURE=per_rank_per_bank ;per_rank or per_rank_per_bank 12 | TOTAL_ROW_ACCESSES=4 ; maximum number of open page requests to send to the same row before forcing a row close (to prevent starvation) 13 | 14 | -------------------------------------------------------------------------------- /rlt.vis: -------------------------------------------------------------------------------- 1 | totalReadsPerRank_R_C[0]: 1440, 1440 totalWritesPerRank_R_C[0]: 217, 217 2 | totalReadsPerRank_R_C[1]: 8253, 8236 totalWritesPerRank_R_C[1]: 58, 58 3 | totalPowerPerRank: 0.715292 actprePower: 0.397089 burstPower: 0.00187286 refreshPower: 0.31633 4 | totalEnergyPerRank: 0.305156 actpreEnergy: 0.169405 burstEnergy: 0.000798996 refreshEnergy: 0.134952 5 | totalPowerPerRank: 2.30769 actprePower: 1.98784 burstPower: 0.00926455 refreshPower: 0.310578 6 | totalEnergyPerRank: 0.984499 actpreEnergy: 0.848049 burstEnergy: 0.00395242 refreshEnergy: 0.132498 7 | bandWidth_channel[0]: 1.3903 8 | readsBandwidth[0]: 1.35188 9 | writesBandwidth[0]: 0.0384215 10 | latency_read_channel[0]: 2154.34 11 | totalReadsPerChannel[0]: 9676 12 | totalWritesPerChannel[0]: 275 13 | totalPowerPerChannel[0]: 4.781 14 | totalEnergyPerChannel[0]: 2.03966e+09 15 | 16 | totalReadsPerRank_R_C[0]: 0, 0 totalWritesPerRank_R_C[0]: 0, 0 17 | totalReadsPerRank_R_C[1]: 0, 0 totalWritesPerRank_R_C[1]: 0, 0 18 | totalReadsPerRank_R_C[2]: 0, 0 totalWritesPerRank_R_C[2]: 0, 0 19 | totalReadsPerRank_R_C[3]: 0, 0 totalWritesPerRank_R_C[3]: 0, 0 20 | totalPowerPerRank: 0 actprePower: 0 burstPower: 0 refreshPower: 0 21 | totalEnergyPerRank: 0 actpreEnergy: 0 burstEnergy: 0 refreshEnergy: 0 22 | totalPowerPerRank: 0 actprePower: 0 burstPower: 0 refreshPower: 0 23 | totalEnergyPerRank: 0 actpreEnergy: 0 burstEnergy: 0 refreshEnergy: 0 24 | totalPowerPerRank: 0 actprePower: 0 burstPower: 0 refreshPower: 0 25 | totalEnergyPerRank: 0 actpreEnergy: 0 burstEnergy: 0 refreshEnergy: 0 26 | totalPowerPerRank: 0 actprePower: 0 burstPower: 0 refreshPower: 0 27 | totalEnergyPerRank: 0 actpreEnergy: 0 burstEnergy: 0 refreshEnergy: 0 28 | bandWidth_channel[1]: 0 29 | readsBandwidth[1]: 0 30 | writesBandwidth[1]: 0 31 | latency_read_channel[1]: -nan 32 | totalReadsPerChannel[1]: 0 33 | totalWritesPerChannel[1]: 0 34 | totalPowerPerChannel[1]: 0 35 | totalEnergyPerChannel[1]: 0 36 | 37 | bandWidth_MS: 1.3903 38 | totalReadsBandwidth_MS: 1.35188 39 | totalWritesBandwidth_MS: 0.0384215 40 | latency_MS_Read: 2154.34 41 | latency_MS_Write: 803.127 42 | totalReads_MS: 9676 43 | totalWrites_MS: 275 44 | currentClockCycle: 170647 45 | cpuCycle: 853232 46 | trasactionCycle: 330400 47 | dram: 10000 48 | pcm: 0 49 | dram_read: 9725 50 | dram_write: 275 51 | pcm_read: 0 52 | pcm_write: 0 53 | rowBufferHitCount_dram: 0 54 | rowBufferHitCount_pcm: 0 55 | actpreNum: 19904 56 | burstNum: 9952 57 | refreshNum: 109 58 | actpreNum_dram: 19904 59 | burstNum_dram: 9952 60 | refreshNum_dram: 109 61 | actpreNum_pcm: 0 62 | burstNum_pcm: 0 63 | refreshNum_pcm: 0 64 | totalPower_MS: 3.02298 65 | totalActprePower_MS: 2.38493 66 | totalBurstPower_MS: 0.0111374 67 | totalRefreshPower_MS: 0.626908 68 | totalEnergy_MS: 1.28966 69 | totalActpreEnergy_MS: 1.01745 70 | totalBurstEnergy_MS: 0.00475142 71 | totalRefreshEnergy_MS: 0.26745 72 | readLatency1: 133 73 | readLatency2: 968 74 | readLatency3: 969 75 | readLatency4: 969 76 | readLatency5: 969 77 | readLatency6: 969 78 | readLatency7: 970 79 | readLatency8: 1033 80 | readLatency9: 1033 81 | readLatency10: 1120 82 | writeLatency1: 12 83 | writeLatency2: 31 84 | writeLatency3: 49 85 | writeLatency4: 77 86 | writeLatency5: 115 87 | writeLatency6: 216 88 | writeLatency7: 421 89 | writeLatency8: 707 90 | writeLatency9: 1003 91 | writeLatency10: 1111 92 | end 93 | -------------------------------------------------------------------------------- /run.sh: -------------------------------------------------------------------------------- 1 | #This is an example of running the HMSim1. 2 | # -c: number of memory requests. 3 | # -S: DRAM capacity 4 | # -X: NVM capacity 5 | 6 | ./HMSim1 \ 7 | -t traces/input \ 8 | -b conf/debug_config.ini \ 9 | -s conf/systemdram.ini \ 10 | -x conf/systempcm.ini \ 11 | -d conf/DDR3_micron_32M_8B_x8_sg25E.ini \ 12 | -e conf/PCM_micron_16M_8B_x16_sg25E.ini \ 13 | -c 10000 \ 14 | -S 2048 \ 15 | -X 2048 \ 16 | -v rlt 17 | -------------------------------------------------------------------------------- /traces/input: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xiafei2011/HMSim1/d28ac72f652e3041dd45f52864a9c7c765edc6a1/traces/input --------------------------------------------------------------------------------