public void write(ref BusPacket busPacket) { //TODO: move all the error checking to BusPacket so once we have a bus packet, // we know the fields are all legal if (busPacket.column >= Config.dram_config.NUM_COLS) { if (Config.DEBUG_MEMORY) { DEBUG.WriteLine("== Error - Bus Packet column " + busPacket.column + " out of bounds"); } Environment.Exit(-1); } // head of the list we need to search DataStruct rowHeadNode = rowEntries[(int)busPacket.column]; DataStruct foundNode = null; if ((foundNode = searchForRow((int)busPacket.row, rowHeadNode)) == null) { //not found DataStruct newRowNode = new DataStruct(); //insert at the head for speed //TODO: Optimize this data structure for speedier lookups? newRowNode.row = (int)busPacket.row; newRowNode.data = busPacket.data; rowEntries[(int)busPacket.column].AddFirst(newRowNode); } else { // found it, just plaster in the new data foundNode.data = busPacket.data; if (Config.dram_config.DEBUG_BANKS) { if (Config.DEBUG_MEMORY) { DEBUG.WriteLine(" -- Bank " + busPacket.bank + " writing to physical address 0x" + busPacket.physicalAddress.ToString("x") + ":"); } busPacket.printData(); if (Config.DEBUG_MEMORY) { DEBUG.WriteLine(""); } } } }
public void enqueue(BusPacket newBusPacket) { uint rank = newBusPacket.rank; uint bank = newBusPacket.bank; if (Config.dram_config.queuingStructure == QueuingStructure.PerRank) { queues[(int)rank][0].Add(newBusPacket); if (queues[(int)rank][0].Count() > Config.dram_config.CMD_QUEUE_DEPTH) { if (Config.DEBUG_MEMORY) { DEBUG.WriteLine("== Error - Enqueued more than allowed in command queue"); } if (Config.DEBUG_MEMORY) { DEBUG.WriteLine(" Need to call .hasRoomFor(int numberToEnqueue, unsigned rank, unsigned bank) first"); } Environment.Exit(1); } } else if (Config.dram_config.queuingStructure == QueuingStructure.PerRankPerBank) { queues[(int)rank][(int)bank].Add(newBusPacket); if (queues[(int)rank][(int)bank].Count() > Config.dram_config.CMD_QUEUE_DEPTH) { if (Config.DEBUG_MEMORY) { DEBUG.WriteLine("== Error - Enqueued more than allowed in command queue"); } if (Config.DEBUG_MEMORY) { DEBUG.WriteLine(" Need to call .hasRoomFor(int numberToEnqueue, unsigned rank, unsigned bank) first"); } Environment.Exit(1); } } else { if (Config.DEBUG_MEMORY) { DEBUG.WriteLine("== Error - Unknown queuing structure"); } Environment.Exit(1); } }
public void read(ref BusPacket busPacket) { DataStruct rowHeadNode = rowEntries[(int)busPacket.column]; DataStruct foundNode = null; if ((foundNode = searchForRow((int)busPacket.row, rowHeadNode)) == null) { // the row hasn't been written before, so it isn't in the list UInt64 garbage = (Config.dram_config.BL * (Config.dram_config.JEDEC_DATA_BUS_BITS / 8)); busPacket.data = garbage; } else { // found it busPacket.data = foundNode.data; } //the return packet should be a data packet, not a read packet busPacket.busPacketType = BusPacketType.DATA; }
public bool isIssuable(BusPacket busPacket) { switch (busPacket.busPacketType) { case BusPacketType.REFRESH: break; case BusPacketType.ACTIVATE: if ((bankStates[(int)busPacket.rank][(int)busPacket.bank].currentBankState == CurrentBankState.Idle || bankStates[(int)busPacket.rank][(int)busPacket.bank].currentBankState == CurrentBankState.Refreshing) && currentClockCycle >= bankStates[(int)busPacket.rank][(int)busPacket.bank].nextActivate && tFAWCountdown[(int)busPacket.rank].Count() < 4) { return(true); } else { return(false); } case BusPacketType.WRITE: case BusPacketType.WRITE_P: if (bankStates[(int)busPacket.rank][(int)busPacket.bank].currentBankState == CurrentBankState.RowActive && currentClockCycle >= bankStates[(int)busPacket.rank][(int)busPacket.bank].nextWrite && busPacket.row == bankStates[(int)busPacket.rank][(int)busPacket.bank].openRowAddress && rowAccessCounters[(int)busPacket.rank][(int)busPacket.bank] < Config.dram_config.TOTAL_ROW_ACCESSES) { return(true); } else { return(false); } case BusPacketType.READ_P: case BusPacketType.READ: if (bankStates[(int)busPacket.rank][(int)busPacket.bank].currentBankState == CurrentBankState.RowActive && currentClockCycle >= bankStates[(int)busPacket.rank][(int)busPacket.bank].nextRead && busPacket.row == bankStates[(int)busPacket.rank][(int)busPacket.bank].openRowAddress && rowAccessCounters[(int)busPacket.rank][(int)busPacket.bank] < Config.dram_config.TOTAL_ROW_ACCESSES) { return(true); } else { return(false); } case BusPacketType.PRECHARGE: if (bankStates[(int)busPacket.rank][(int)busPacket.bank].currentBankState == CurrentBankState.RowActive && currentClockCycle >= bankStates[(int)busPacket.rank][(int)busPacket.bank].nextPrecharge) { return(true); } else { return(false); } default: if (Config.DEBUG_MEMORY) { DEBUG.WriteLine("ERROT == Error - Trying to issue a crazy bus packet type : "); } busPacket.print(); Environment.Exit(0); break; } return(false); }
public bool pop(ref BusPacket busPacket) { //this can be done here because pop() is called every clock cycle by the parent MemoryController // figures out the sliding window requirement for tFAW // //deal with tFAW book-keeping // each rank has it's own counter since the restriction is on a device level for (int i = 0; i < Config.dram_config.NUM_RANKS; i++) { //decrement all the counters we have going for (int j = 0; j < tFAWCountdown[i].Count(); j++) { tFAWCountdown[i][j]--; } //the head will always be the smallest counter, so check if it has reached 0 if (tFAWCountdown[i].Count() > 0 && tFAWCountdown[i][0] == 0) { // tFAWCountdown[i].erase(tFAWCountdown[i].begin()); tFAWCountdown[i].RemoveAt(0); } } /* Now we need to find a packet to issue. When the code picks a packet, it will set * busPacket = [some eligible packet] * * First the code looks if any refreshes need to go * Then it looks for data packets * Otherwise, it starts looking for rows to close (in open page) */ if (Config.dram_config.rowBufferPolicy == RowBufferPolicy.ClosePage) { bool sendingREF = false; //if the memory controller set the flags signaling that we need to issue a refresh if (refreshWaiting) { bool foundActiveOrTooEarly = false; //look for an open bank for (uint b = 0; b < Config.dram_config.NUM_BANKS; b++) { List <BusPacket> queue = getCommandQueue(refreshRank, (int)b); //checks to make sure that all banks are idle if (bankStates[(int)refreshRank][(int)b].currentBankState == CurrentBankState.RowActive) { foundActiveOrTooEarly = true; //if the bank is open, make sure there is nothing else // going there before we close it for (int j = 0; j < queue.Count(); j++) { BusPacket packet = queue[j]; if (packet.row == bankStates[(int)refreshRank][(int)b].openRowAddress && packet.bank == b) { if (packet.busPacketType != BusPacketType.ACTIVATE && isIssuable(packet)) { busPacket = packet; //queue.erase(queue.begin() + j); queue.RemoveAt(j); sendingREF = true; } break; } } break; } // NOTE: checks nextActivate time for each bank to make sure tRP is being // satisfied. the next ACT and next REF can be issued at the same // point in the future, so just use nextActivate field instead of // creating a nextRefresh field else if (bankStates[(int)refreshRank][(int)b].nextActivate > currentClockCycle) { foundActiveOrTooEarly = true; break; } } //if there are no open banks and timing has been met, send out the refresh // reset flags and rank pointer if (!foundActiveOrTooEarly && bankStates[(int)refreshRank][0].currentBankState != CurrentBankState.PowerDown) { busPacket = new BusPacket(BusPacketType.REFRESH, 0, 0, 0, refreshRank, 0, 0, null, dramsim_log); refreshRank = -1; refreshWaiting = false; sendingREF = true; } } // refreshWaiting //if we're not sending a REF, proceed as normal if (!sendingREF) { bool foundIssuable = false; uint startingRank = nextRank; uint startingBank = nextBank; do { List <BusPacket> queue = getCommandQueue((int)nextRank, (int)nextBank); //make sure there is something in this queue first // also make sure a rank isn't waiting for a refresh // if a rank is waiting for a refesh, don't issue anything to it until the // refresh logic above has sent one out (ie, letting banks close) if (!(queue.Count() <= 0) && !((nextRank == refreshRank) && refreshWaiting)) { if (Config.dram_config.queuingStructure == QueuingStructure.PerRank) { //search from beginning to find first issuable bus packet for (int i = 0; i < queue.Count(); i++) { if (isIssuable(queue[i])) { //check to make sure we aren't removing a read/write that is paired with an activate if (i > 0 && queue[i - 1].busPacketType == BusPacketType.ACTIVATE && queue[i - 1].physicalAddress == queue[i].physicalAddress) { continue; } busPacket = queue[i]; //queue.erase(queue.begin() + i); queue.RemoveAt(i); foundIssuable = true; break; } } } else { if (isIssuable(queue[0])) { //no need to search because if the front can't be sent, // then no chance something behind it can go instead busPacket = queue[0]; // queue.erase(queue.begin()); queue.RemoveAt(0); foundIssuable = true; } } } //if we found something, break out of do-while if (foundIssuable) { break; } //rank round robin if (Config.dram_config.queuingStructure == QueuingStructure.PerRank) { nextRank = (nextRank + 1) % Config.dram_config.NUM_RANKS; if (startingRank == nextRank) { break; } } else { nextRankAndBank(ref nextRank, ref nextBank); if (startingRank == nextRank && startingBank == nextBank) { break; } } }while (true); //if we couldn't find anything to send, return false if (!foundIssuable) { return(false); } } } else if (Config.dram_config.rowBufferPolicy == RowBufferPolicy.OpenPage) { bool sendingREForPRE = false; if (refreshWaiting) { bool sendREF = true; //make sure all banks idle and timing met for a REF for (int b = 0; b < Config.dram_config.NUM_BANKS; b++) { //if a bank is active we can't send a REF yet if (bankStates[refreshRank][b].currentBankState == CurrentBankState.RowActive) { sendREF = false; bool closeRow = true; //search for commands going to an open row List <BusPacket> refreshQueue = getCommandQueue(refreshRank, b); for (int j = 0; j < refreshQueue.Count(); j++) { BusPacket packet = refreshQueue[j]; //if a command in the queue is going to the same row . . . if (bankStates[refreshRank][b].openRowAddress == packet.row && b == packet.bank) { // . . . and is not an activate . . . if (packet.busPacketType != BusPacketType.ACTIVATE) { closeRow = false; // . . . and can be issued . . . if (isIssuable(packet)) { //send it out busPacket = packet; //refreshQueue.erase(refreshQueue.begin() + j); refreshQueue.RemoveAt(j); sendingREForPRE = true; } break; } else //command is an activate { //if we've encountered another act, no other command will be of interest break; } } } //if the bank is open and we are allowed to close it, then send a PRE if (closeRow && currentClockCycle >= bankStates[refreshRank][b].nextPrecharge) { rowAccessCounters[refreshRank][b] = 0; busPacket = new BusPacket(BusPacketType.PRECHARGE, 0, 0, 0, refreshRank, (uint)b, 0, null, dramsim_log); sendingREForPRE = true; } break; } // NOTE: the next ACT and next REF can be issued at the same // point in the future, so just use nextActivate field instead of // creating a nextRefresh field else if (bankStates[refreshRank][b].nextActivate > currentClockCycle) //and this bank doesn't have an open row { sendREF = false; break; } } //if there are no open banks and timing has been met, send out the refresh // reset flags and rank pointer if (sendREF && bankStates[refreshRank][0].currentBankState != CurrentBankState.PowerDown) { busPacket = new BusPacket(BusPacketType.REFRESH, 0, 0, 0, refreshRank, 0, 0, null, dramsim_log); refreshRank = -1; refreshWaiting = false; sendingREForPRE = true; } } if (!sendingREForPRE) { uint startingRank = nextRank; uint startingBank = nextBank; bool foundIssuable = false; do // round robin over queues { List <BusPacket> queue = getCommandQueue((int)nextRank, (int)nextBank); //make sure there is something there first if (!(queue.Count() <= 0) && !((nextRank == refreshRank) && refreshWaiting)) { //search from the beginning to find first issuable bus packet for (int i = 0; i < queue.Count(); i++) { BusPacket packet = queue[i]; if (isIssuable(packet)) { //check for dependencies bool dependencyFound = false; for (int j = 0; j < i; j++) { BusPacket prevPacket = queue[j]; if (prevPacket.busPacketType != BusPacketType.ACTIVATE && prevPacket.bank == packet.bank && prevPacket.row == packet.row) { dependencyFound = true; break; } } if (dependencyFound) { continue; } busPacket = packet; //if the bus packet before is an activate, that is the act that was // paired with the column access we are removing, so we have to remove // that activate as well (check i>0 because if i==0 then theres nothing before it) if (i > 0 && queue[i - 1].busPacketType == BusPacketType.ACTIVATE) { rowAccessCounters[(int)busPacket.rank][(int)busPacket.bank]++; // i is being returned, but i-1 is being thrown away, so must delete it here // delete(queue[i - 1]); // queue.RemoveAt(i - 1); // remove both i-1 (the activate) and i (we've saved the pointer in *busPacket) //queue.erase(queue.begin() + i - 1, queue.begin() + i + 1); //queue.RemoveRange(i - 1, i + 1); queue.RemoveAt(i); queue.RemoveAt(i - 1); } else // there's no activate before this packet { //or just remove the one bus packet // queue.erase(queue.begin() + i); queue.RemoveAt(i); } foundIssuable = true; break; } } } //if we found something, break out of do-while if (foundIssuable) { break; } //rank round robin if (Config.dram_config.queuingStructure == QueuingStructure.PerRank) { nextRank = (nextRank + 1) % Config.dram_config.NUM_RANKS; if (startingRank == nextRank) { break; } } else { nextRankAndBank(ref nextRank, ref nextBank); if (startingRank == nextRank && startingBank == nextBank) { break; } } }while (true); //if nothing was issuable, see if we can issue a PRE to an open bank // that has no other commands waiting if (!foundIssuable) { //search for banks to close bool sendingPRE = false; uint startingRank1 = nextRankPRE; uint startingBank1 = nextBankPRE; do // round robin over all ranks and banks { List <BusPacket> queue = getCommandQueue((int)nextRankPRE, (int)nextBankPRE); bool found = false; //check if bank is open if (bankStates[(int)nextRankPRE][(int)nextBankPRE].currentBankState == CurrentBankState.RowActive) { for (int i = 0; i < queue.Count(); i++) { //if there is something going to that bank and row, then we don't want to send a PRE if (queue[i].bank == nextBankPRE && queue[i].row == bankStates[(int)nextRankPRE][(int)nextBankPRE].openRowAddress) { found = true; break; } } //if nothing found going to that bank and row or too many accesses have happend, close it if (!found || rowAccessCounters[(int)nextRankPRE][(int)nextBankPRE] == Config.dram_config.TOTAL_ROW_ACCESSES) { if (currentClockCycle >= bankStates[(int)nextRankPRE][(int)nextBankPRE].nextPrecharge) { sendingPRE = true; rowAccessCounters[(int)nextRankPRE][(int)nextBankPRE] = 0; busPacket = new BusPacket(BusPacketType.PRECHARGE, 0, 0, 0, (int)nextRankPRE, nextBankPRE, 0, null, dramsim_log); break; } } } nextRankAndBank(ref nextRankPRE, ref nextBankPRE); }while (!(startingRank1 == nextRankPRE && startingBank1 == nextBankPRE)); //if no PREs could be sent, just return false if (!sendingPRE) { return(false); } } } } //sendAct is flag used for posted-cas // posted-cas is enabled when AL>0 // when sendAct is true, when don't want to increment our indexes // so we send the column access that is paid with this act if (Config.dram_config.AL > 0 && sendAct) { sendAct = false; } else { sendAct = true; nextRankAndBank(ref nextRank, ref nextBank); } //if its an activate, add a tfaw counter if (busPacket.busPacketType == BusPacketType.ACTIVATE) { tFAWCountdown[(int)busPacket.rank].Add(Config.dram_config.tFAW); } return(true); }
public void receiveFromBus(ref BusPacket packet) { if (Config.dram_config.DEBUG_BUS) { if (Config.DEBUG_MEMORY) { DEBUG.WriteLine(" -- R" + this.id + " Receiving On Bus : "); } packet.print(); } if (Config.dram_config.VERIFICATION_OUTPUT) { packet.print(currentClockCycle, false); } switch (packet.busPacketType) { case BusPacketType.READ: //make sure a read is allowed if (bankStates[(int)packet.bank].currentBankState != CurrentBankState.RowActive || currentClockCycle < bankStates[(int)packet.bank].nextRead || packet.row != bankStates[(int)packet.bank].openRowAddress) { packet.print(); if (Config.DEBUG_MEMORY) { DEBUG.WriteLine("== Error - Rank " + id + " received a READ when not allowed"); } Environment.Exit(1); } //update state table bankStates[(int)packet.bank].nextPrecharge = Math.Max(bankStates[(int)packet.bank].nextPrecharge, currentClockCycle + Config.dram_config.READ_TO_PRE_DELAY); for (int i = 0; i < Config.dram_config.NUM_BANKS; i++) { bankStates[i].nextRead = Math.Max(bankStates[i].nextRead, currentClockCycle + Math.Max(Config.dram_config.tCCD, Config.dram_config.BL / 2)); bankStates[i].nextWrite = Math.Max(bankStates[i].nextWrite, currentClockCycle + Config.dram_config.READ_TO_WRITE_DELAY); } //get the read data and put it in the storage which delays until the appropriate time (RL) if (Config.dram_config.NO_STORAGE) { banks[(int)packet.bank].read(ref packet); } else { packet.busPacketType = BusPacketType.DATA; } readReturnPacket.Add(packet); readReturnCountdown.Add(Config.dram_config.RL); break; case BusPacketType.READ_P: //make sure a read is allowed if (bankStates[(int)packet.bank].currentBankState != CurrentBankState.RowActive || currentClockCycle < bankStates[(int)packet.bank].nextRead || packet.row != bankStates[(int)packet.bank].openRowAddress) { if (Config.DEBUG_MEMORY) { DEBUG.WriteLine("ERROR == Error - Rank " + id + " received a READ_P when not allowed"); } Environment.Exit(1); } //update state table bankStates[(int)packet.bank].currentBankState = CurrentBankState.Idle; bankStates[(int)packet.bank].nextActivate = Math.Max(bankStates[(int)packet.bank].nextActivate, currentClockCycle + Config.dram_config.READ_AUTOPRE_DELAY); for (int i = 0; i < Config.dram_config.NUM_BANKS; i++) { //will set next read/write for all banks - including current (which shouldnt matter since its now idle) bankStates[i].nextRead = Math.Max(bankStates[i].nextRead, currentClockCycle + Math.Max(Config.dram_config.BL / 2, Config.dram_config.tCCD)); bankStates[i].nextWrite = Math.Max(bankStates[i].nextWrite, currentClockCycle + Config.dram_config.READ_TO_WRITE_DELAY); } //get the read data and put it in the storage which delays until the appropriate time (RL) if (Config.dram_config.NO_STORAGE) { banks[(int)packet.bank].read(ref packet); } else { packet.busPacketType = BusPacketType.DATA; } readReturnPacket.Add(packet); readReturnCountdown.Add(Config.dram_config.RL); break; case BusPacketType.WRITE: //make sure a write is allowed if (bankStates[(int)packet.bank].currentBankState != CurrentBankState.RowActive || currentClockCycle < bankStates[(int)packet.bank].nextWrite || packet.row != bankStates[(int)packet.bank].openRowAddress) { if (Config.DEBUG_MEMORY) { DEBUG.WriteLine("== Error - Rank " + id + " received a WRITE when not allowed"); } bankStates[(int)packet.bank].print(); Environment.Exit(1); } //update state table bankStates[(int)packet.bank].nextPrecharge = Math.Max(bankStates[(int)packet.bank].nextPrecharge, currentClockCycle + Config.dram_config.WRITE_TO_PRE_DELAY); for (int i = 0; i < Config.dram_config.NUM_BANKS; i++) { bankStates[i].nextRead = Math.Max(bankStates[i].nextRead, currentClockCycle + Config.dram_config.WRITE_TO_READ_DELAY_B); bankStates[i].nextWrite = Math.Max(bankStates[i].nextWrite, currentClockCycle + Math.Max(Config.dram_config.BL / 2, Config.dram_config.tCCD)); } //take note of where data is going when it arrives incomingWriteBank = (int)packet.bank; incomingWriteRow = (int)packet.row; incomingWriteColumn = (int)packet.column; // delete(packet); // packet. break; case BusPacketType.WRITE_P: //make sure a write is allowed if (bankStates[(int)packet.bank].currentBankState != CurrentBankState.RowActive || currentClockCycle < bankStates[(int)packet.bank].nextWrite || packet.row != bankStates[(int)packet.bank].openRowAddress) { if (Config.DEBUG_MEMORY) { DEBUG.WriteLine("== Error - Rank " + id + " received a WRITE_P when not allowed"); } Environment.Exit(1); } //update state table bankStates[(int)packet.bank].currentBankState = CurrentBankState.Idle; bankStates[(int)packet.bank].nextActivate = Math.Max(bankStates[(int)packet.bank].nextActivate, currentClockCycle + Config.dram_config.WRITE_AUTOPRE_DELAY); for (int i = 0; i < Config.dram_config.NUM_BANKS; i++) { bankStates[i].nextWrite = Math.Max(bankStates[i].nextWrite, currentClockCycle + Math.Max(Config.dram_config.tCCD, Config.dram_config.BL / 2)); bankStates[i].nextRead = Math.Max(bankStates[i].nextRead, currentClockCycle + Config.dram_config.WRITE_TO_READ_DELAY_B); } //take note of where data is going when it arrives incomingWriteBank = (int)packet.bank; incomingWriteRow = (int)packet.row; incomingWriteColumn = (int)packet.column; // delete(packet); break; case BusPacketType.ACTIVATE: //make sure activate is allowed if (bankStates[(int)packet.bank].currentBankState != CurrentBankState.Idle || currentClockCycle < bankStates[(int)packet.bank].nextActivate) { if (Config.DEBUG_MEMORY) { DEBUG.WriteLine("== Error - Rank " + id + " received an ACT when not allowed"); } packet.print(); bankStates[(int)packet.bank].print(); Environment.Exit(1); } bankStates[(int)packet.bank].currentBankState = CurrentBankState.RowActive; bankStates[(int)packet.bank].nextActivate = currentClockCycle + Config.dram_config.tRC; bankStates[(int)packet.bank].openRowAddress = (int)packet.row; //if AL is greater than one, then posted-cas is enabled - handle accordingly if (Config.dram_config.AL > 0) { bankStates[(int)packet.bank].nextWrite = currentClockCycle + (Config.dram_config.tRCD - Config.dram_config.AL); bankStates[(int)packet.bank].nextRead = currentClockCycle + (Config.dram_config.tRCD - Config.dram_config.AL); } else { bankStates[(int)packet.bank].nextWrite = currentClockCycle + (Config.dram_config.tRCD - Config.dram_config.AL); bankStates[(int)packet.bank].nextRead = currentClockCycle + (Config.dram_config.tRCD - Config.dram_config.AL); } bankStates[(int)packet.bank].nextPrecharge = currentClockCycle + Config.dram_config.tRAS; for (int i = 0; i < Config.dram_config.NUM_BANKS; i++) { if (i != packet.bank) { bankStates[i].nextActivate = Math.Max(bankStates[i].nextActivate, currentClockCycle + Config.dram_config.tRRD); } } // delete(packet); break; case BusPacketType.PRECHARGE: //make sure precharge is allowed if (bankStates[(int)packet.bank].currentBankState != CurrentBankState.RowActive || currentClockCycle < bankStates[(int)packet.bank].nextPrecharge) { if (Config.DEBUG_MEMORY) { DEBUG.WriteLine("== Error - Rank " + id + " received a PRE when not allowed"); } Environment.Exit(1); } bankStates[(int)packet.bank].currentBankState = CurrentBankState.Idle; bankStates[(int)packet.bank].nextActivate = Math.Max(bankStates[(int)packet.bank].nextActivate, currentClockCycle + Config.dram_config.tRP); // delete(packet); break; case BusPacketType.REFRESH: refreshWaiting = false; for (int i = 0; i < Config.dram_config.NUM_BANKS; i++) { if (bankStates[i].currentBankState != CurrentBankState.Idle) { if (Config.DEBUG_MEMORY) { DEBUG.WriteLine("== Error - Rank " + id + " received a REF when not allowed"); } Environment.Exit(1); } bankStates[i].nextActivate = currentClockCycle + Config.dram_config.tRFC; } // delete(packet); break; case BusPacketType.DATA: // TODO: replace this check with something that works? /* * if(packet->bank != incomingWriteBank || * packet->row != incomingWriteRow || * packet->column != incomingWriteColumn) * { * cout << "== Error - Rank " << id << " received a DATA packet to the wrong place" << endl; * packet->print(); * bankStates[packet->bank].print(); * exit(0); * } */ if (Config.dram_config.NO_STORAGE) { banks[(int)packet.bank].write(ref packet); } // end of the line for the write packet // delete(packet); break; default: if (Config.DEBUG_MEMORY) { DEBUG.WriteLine("== Error - Unknown BusPacketType trying to be sent to Bank"); } Environment.Exit(1); break; } }