コード例 #1
0
ファイル: Bank.cs プロジェクト: hoangt/PIMSim
        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("");
                    }
                }
            }
        }
コード例 #2
0
ファイル: CommandQueue.cs プロジェクト: hoangt/PIMSim
        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);
            }
        }
コード例 #3
0
ファイル: Bank.cs プロジェクト: hoangt/PIMSim
        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;
        }
コード例 #4
0
ファイル: CommandQueue.cs プロジェクト: hoangt/PIMSim
        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);
        }
コード例 #5
0
ファイル: CommandQueue.cs プロジェクト: hoangt/PIMSim
        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);
        }
コード例 #6
0
        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;
            }
        }