Example #1
0
 protected virtual void OnInternalRequestServiced(InternalRequest targetRequest)
 {
     if (onInternalRequestServiced != null)
     {
         onInternalRequestServiced(targetRequest, ChannelID, this);
     }
 }
Example #2
0
        public void Resume()
        {
            if (!Suspended)
            {
                throw new Exception("Resume requested but there is no suspended Flash transaction!");
            }
            Suspended = false;
            TotalResumeCount++;

            foreach (FlashChipDie die in Dies)
            {
                foreach (FlashChipPlane plane in die.Planes)
                {
                    if (plane.SuspendedExecutingRequest != null)
                    {
                        InternalRequest targetRequest = plane.SuspendedExecutingRequest;
                        if (die.Status != DieStatus.Idle &&
                            (targetRequest.ExecutionType != InternalRequestExecutionType.Multiplane) &&
                            (targetRequest.ExecutionType != InternalRequestExecutionType.InterleavedMultiplane))
                        {
                            throw new Exception("Executing operation on a busy die");
                        }
                        if (plane.Status == PlaneStatus.Busy)
                        {
                            throw new Exception("Executing operation on a busy plane");
                        }

                        die.CurrentExecutingOperationCount++;
                        die.Status   = DieStatus.Busy;
                        plane.Status = PlaneStatus.Busy;
                        plane.CurrentExecutingRequest   = targetRequest;
                        plane.SuspendedExecutingRequest = null;

                        CurrentExecutingOperationCount++;
                        switch (targetRequest.Type)
                        {
                        case InternalRequestType.Read:
                            this.Status = FlashChipStatus.Reading;
                            break;

                        case InternalRequestType.Write:
                            this.Status = FlashChipStatus.Writing;
                            break;

                        case InternalRequestType.Clean:
                            this.Status = FlashChipStatus.Erasing;
                            break;

                        default:
                            throw new Exception("Unhandled operation type");
                        }
                        targetRequest.ExpectedFinishTime      = XEngineFactory.XEngine.Time + targetRequest.RemainingExecutionTime;
                        targetRequest.FlashChipExecutionEvent = new XEvent(targetRequest.ExpectedFinishTime, this, targetRequest, 0);
                        XEngineFactory.XEngine.EventList.InsertXEvent(targetRequest.FlashChipExecutionEvent);
                    }
                }
            }
        }
Example #3
0
        public virtual void PerformOperation(InternalRequest internalReq)
        {
            FlashChipDie targetDie = this.Dies[internalReq.TargetPageAddress.DieID];

            if (targetDie.Status != DieStatus.Idle &&
                (internalReq.ExecutionType != InternalRequestExecutionType.Multiplane) &&
                (internalReq.ExecutionType != InternalRequestExecutionType.InterleavedMultiplane))
            {
                throw new Exception("Executing operation on a busy die");
            }
            if (targetDie.Planes[internalReq.TargetPageAddress.PlaneID].Status == PlaneStatus.Busy)
            {
                throw new Exception("Executing operation on a busy plane");
            }

            targetDie.CurrentExecutingOperationCount++;
            targetDie.Status = DieStatus.Busy;
            targetDie.Planes[internalReq.TargetPageAddress.PlaneID].Status = PlaneStatus.Busy;
            targetDie.Planes[internalReq.TargetPageAddress.PlaneID].CurrentExecutingRequest = internalReq;
            ulong executionTime = 0;

            switch (internalReq.Type)
            {
            case InternalRequestType.Read:
                this.Status = FlashChipStatus.Reading;

                /* tR + tRR
                 * According to micron's manual, after read operation accomplishment, we have to wait for ready signals to be driven*/
                executionTime = readLatency + readDataOutputReadyTime;
                break;

            case InternalRequestType.Write:
                this.Status   = FlashChipStatus.Writing;
                executionTime = programLatency;
                break;

            case InternalRequestType.Clean:
                this.Status   = FlashChipStatus.Erasing;
                executionTime = eraseLatency;    //This is a normal erase requeset
                break;

            default:
                throw new Exception("Unhandled operation type");
            }
            internalReq.ExpectedFinishTime      = XEngineFactory.XEngine.Time + executionTime;
            internalReq.FlashChipExecutionEvent = new XEvent(internalReq.ExpectedFinishTime, this, internalReq, 0);
            XEngineFactory.XEngine.EventList.InsertXEvent(internalReq.FlashChipExecutionEvent);
            CurrentExecutingOperationCount++;
            if (CurrentExecutingOperationCount == 1)
            {
                ThisRoundExecutionStart     = XEngineFactory.XEngine.Time;
                ThisRoundExecutionFinish    = ulong.MaxValue;
                ExpectedFinishTime          = internalReq.ExpectedFinishTime;
                IssueTimeOfExecutingRequest = internalReq.IssueTime;
            }
        }
Example #4
0
        public void Suspend()
        {
            if (Suspended)
            {
                throw new Exception("Suspending a previously suspended chip!");
            }
            Suspended = true;
            TotalSuspensionCount++;

            foreach (FlashChipDie die in Dies)
            {
                foreach (FlashChipPlane plane in die.Planes)
                {
                    if (plane.CurrentExecutingRequest != null)
                    {
                        InternalRequest targetRequest = plane.CurrentExecutingRequest;
                        if (targetRequest.Type == InternalRequestType.Read)
                        {
                            throw new Exception("Suspend is not supported for read operations!");
                        }

                        targetRequest.RemainingExecutionTime = targetRequest.ExpectedFinishTime - XEngineFactory.XEngine.Time;
                        if (targetRequest.RemainingExecutionTime < 0)
                        {
                            throw new Exception("Strange command suspension time occured!");
                        }
                        targetRequest.FlashChipExecutionEvent.Removed = true;
                        targetRequest.FlashChipExecutionEvent         = null;

                        plane.CurrentExecutingRequest   = null;
                        plane.SuspendedExecutingRequest = targetRequest;

                        die.CurrentExecutingOperationCount--;
                        if (die.CurrentExecutingOperationCount == 0)
                        {
                            die.Status = DieStatus.Idle;
                        }
                        die.Planes[targetRequest.TargetPageAddress.PlaneID].Status = PlaneStatus.Idle;

                        CurrentExecutingOperationCount--;
                    }
                }
            }
        }
Example #5
0
        public override void ProcessXEvent(XEvent e)
        {
            if (e.Removed)
            {
                return;
            }
            //Just only one xevent: OperationFinished
            InternalRequest targetRequest = e.Parameters as InternalRequest;
            FlashChipDie    targetDie     = this.Dies[targetRequest.TargetPageAddress.DieID];

            targetDie.CurrentExecutingOperationCount--;
            if (targetDie.CurrentExecutingOperationCount == 0)
            {
                targetDie.Status = DieStatus.Idle;
            }
            targetDie.Planes[targetRequest.TargetPageAddress.PlaneID].Status = PlaneStatus.Idle;
            targetDie.Planes[targetRequest.TargetPageAddress.PlaneID].CurrentExecutingRequest = null;

            CurrentExecutingOperationCount--;
            if (CurrentExecutingOperationCount == 0)
            {
                Status = FlashChipStatus.Idle;
                totalCommandExecutionPeriod += XEngineFactory.XEngine.Time - ThisRoundExecutionStart;
                ThisRoundExecutionFinish     = XEngineFactory.XEngine.Time;
            }

            switch (targetRequest.Type)
            {
            case InternalRequestType.Read:
                this.ReadCount++;
                targetDie.Planes[targetRequest.TargetPageAddress.PlaneID].ReadCount++;
                targetRequest.ExecutionTime += this.readLatency;
                this.Status = FlashChipStatus.Waiting;

                //Either a normal read (waiting for read data transfer) or a copyback read (waiting for write execution)
                this.CurrentWaitingTransfers++;

                if (targetDie.Status == DieStatus.Idle)
                {
                    targetDie.TotalReadExecutionPeriod += readLatency;
                }
                break;

            case InternalRequestType.Write:
                this.ProgamCount++;
                targetDie.Planes[targetRequest.TargetPageAddress.PlaneID].ProgamCount++;
                targetRequest.ExecutionTime += this.programLatency;

                if (targetDie.Status == DieStatus.Idle)
                {
                    targetDie.TotalProgramExecutionPeriod += programLatency;
                }
                break;

            case InternalRequestType.Clean:
                this.EraseCount++;
                targetDie.Planes[targetRequest.TargetPageAddress.PlaneID].EraseCount++;
                targetRequest.ExecutionTime += this.eraseLatency;
                FlashChipBlock targetBlock = this.Dies[targetRequest.TargetPageAddress.DieID].Planes[targetRequest.TargetPageAddress.PlaneID].Blocks[targetRequest.TargetPageAddress.BlockID];
                targetDie.Planes[targetRequest.TargetPageAddress.PlaneID].FreePagesNo += (PageNoPerBlock - targetBlock.FreePageNo);
                targetBlock.FreePageNo        = PageNoPerBlock;
                targetBlock.InvalidPageNo     = 0;
                targetBlock.LastWrittenPageNo = -1;
                targetBlock.EraseCount++;
                for (int i = 0; i < PageNoPerBlock; i++)
                {
                    targetBlock.Pages[i].StreamID    = FlashChipPage.PG_NOSTREAM;
                    targetBlock.Pages[i].ValidStatus = FlashChipPage.PG_FREE;
                    targetBlock.Pages[i].LPN         = ulong.MaxValue;
                }

                #region UpdateFastGCData
                targetDie.BlockInfoAbstract[targetBlock.BlockID].FreePageNo   += PageNoPerBlock;
                targetDie.BlockInfoAbstract[targetBlock.BlockID].InvalidPageNo = 0;
                targetDie.BlockInfoAbstract[targetBlock.BlockID].EraseCount++;
                #endregion

                if (targetDie.Status == DieStatus.Idle)
                {
                    targetDie.TotalEraseExecutionPeriod += eraseLatency;
                }
                break;

            default:
                break;
            }
            OnInternalRequestServiced(targetRequest);
        }
Example #6
0
        public override void SendResponseToHost(InternalRequest internalReq)
        {
            sumOfInternalRequestLifeTime      += (XEngineFactory.XEngine.Time - internalReq.IssueTime) / 1000;                                                          //Nanoseconds is converted to microseconds
            sumOfInternalRequestExecutionTime += internalReq.ExecutionTime / 1000;                                                                                      //Nanoseconds is converted to microseconds
            sumOfInternalRequestTransferTime  += internalReq.TransferTime / 1000;                                                                                       //Nanoseconds is converted to microseconds
            sumOfInternalRequestWaitingTime   += (XEngineFactory.XEngine.Time - (internalReq.IssueTime + internalReq.ExecutionTime + internalReq.TransferTime)) / 1000; //Nanoseconds is converted to microseconds
            totalFlashOperations++;

            if (gcStarted)
            {
                sumOfInternalRequestLifeTime_AGC      += (XEngineFactory.XEngine.Time - internalReq.IssueTime) / 1000;
                sumOfInternalRequestExecutionTime_AGC += internalReq.ExecutionTime / 1000;
                sumOfInternalRequestTransferTime_AGC  += internalReq.TransferTime / 1000;
                sumOfInternalRequestWaitingTime_AGC   += (XEngineFactory.XEngine.Time - (internalReq.IssueTime + internalReq.ExecutionTime + internalReq.TransferTime)) / 1000;
                totalFlashOperations_AGC++;
            }

            if (internalReq.Type == InternalRequestType.Read)
            {
                sumOfReadRequestLifeTime      += (XEngineFactory.XEngine.Time - internalReq.IssueTime) / 1000;
                sumOfReadRequestExecutionTime += internalReq.ExecutionTime / 1000;
                sumOfReadRequestTransferTime  += internalReq.TransferTime / 1000;
                sumOfReadRequestWaitingTime   += (XEngineFactory.XEngine.Time - (internalReq.IssueTime + internalReq.ExecutionTime + internalReq.TransferTime)) / 1000;
                totalReadOperations++;
                if (gcStarted)
                {
                    sumOfReadRequestLifeTime_AGC      += (XEngineFactory.XEngine.Time - internalReq.IssueTime) / 1000;
                    sumOfReadRequestExecutionTime_AGC += internalReq.ExecutionTime / 1000;
                    sumOfReadRequestTransferTime_AGC  += internalReq.TransferTime / 1000;
                    sumOfReadRequestWaitingTime_AGC   += (XEngineFactory.XEngine.Time - (internalReq.IssueTime + internalReq.ExecutionTime + internalReq.TransferTime)) / 1000;
                    totalReadOperations_AGC++;
                }
            }
            else
            {
                FTL.OnLPNServiced(internalReq.RelatedIORequest.StreamID, internalReq.LPN);
                sumOfProgramRequestLifeTime      += (XEngineFactory.XEngine.Time - internalReq.IssueTime) / 1000;
                sumOfProgramRequestExecutionTime += internalReq.ExecutionTime / 1000;
                sumOfProgramRequestTransferTime  += internalReq.TransferTime / 1000;
                sumOfProgramRequestWaitingTime   += (XEngineFactory.XEngine.Time - (internalReq.IssueTime + internalReq.ExecutionTime + internalReq.TransferTime)) / 1000;
                totalProgramOperations++;
                if (gcStarted)
                {
                    sumOfProgramRequestLifeTime_AGC      += (XEngineFactory.XEngine.Time - internalReq.IssueTime) / 1000;
                    sumOfProgramRequestExecutionTime_AGC += internalReq.ExecutionTime / 1000;
                    sumOfProgramRequestTransferTime_AGC  += internalReq.TransferTime / 1000;
                    sumOfProgramRequestWaitingTime_AGC   += (XEngineFactory.XEngine.Time - (internalReq.IssueTime + internalReq.ExecutionTime + internalReq.TransferTime)) / 1000;
                    totalProgramOperations_AGC++;
                }
            }
            IORequest targetIORequest = internalReq.RelatedIORequest;

            if (_inputStreams[targetIORequest.StreamID].WriteToCompletionQueue(internalReq, requestProcessingTime))
            {
                checked
                {
                    try
                    {
                        sumResponseTime += (targetIORequest.ResponseTime / 1000);
                    }
                    catch (OverflowException ex)
                    {
                        Console.WriteLine("Overflow exception occured while calculating statistics in HostInterface.");
                        if (overflowOccured)
                        {
                            throw new Exception("I can just handle one overflow event, but I received the second one!");
                        }
                        overflowOccured = true;
                        XEngineFactory.XEngine.StopSimulation();
                        return;
                    }
                }
                thisRoundSumResponseTime += targetIORequest.ResponseTime / 1000;
                if (minResponseTime > targetIORequest.ResponseTime)
                {
                    minResponseTime = targetIORequest.ResponseTime;
                }
                else if (maxResponseTime < targetIORequest.ResponseTime)
                {
                    maxResponseTime = targetIORequest.ResponseTime;
                }
                transferredBytesCount += targetIORequest.SizeInByte;
                handledRequestsCount++;          //used for general statistics
                thisRoundHandledRequestsCount++; //used in replay
                if (gcStarted)
                {
                    sumResponseTime_AGC += (targetIORequest.ResponseTime / 1000);
                    if (minResponseTime_AGC > targetIORequest.ResponseTime)
                    {
                        minResponseTime_AGC = targetIORequest.ResponseTime;
                    }
                    else if (maxResponseTime_AGC < targetIORequest.ResponseTime)
                    {
                        maxResponseTime_AGC = targetIORequest.ResponseTime;
                    }
                    transferredBytesCount_AGC += targetIORequest.SizeInByte;
                    handledRequestsCount_AGC++;//used for general statistics
                }
                if (targetIORequest.Type == IORequestType.Write)
                {
                    sumResponseTimeW          += (targetIORequest.ResponseTime / 1000);
                    thisRoundSumResponseTimeW += (targetIORequest.ResponseTime / 1000);
                    transferredBytesCountW    += targetIORequest.SizeInByte;
                    handledWriteRequestsCount++;
                    thisRoundHandledWriteRequestsCount++;
                    if (minResponseTimeW > targetIORequest.ResponseTime)
                    {
                        minResponseTimeW = targetIORequest.ResponseTime;
                    }
                    else if (maxResponseTimeW < targetIORequest.ResponseTime)
                    {
                        maxResponseTimeW = targetIORequest.ResponseTime;
                    }
                    if (gcStarted)
                    {
                        sumResponseTimeW_AGC       += (targetIORequest.ResponseTime / 1000);
                        transferredBytesCountW_AGC += targetIORequest.SizeInByte;
                        handledWriteRequestsCount_AGC++;
                        if (minResponseTimeW_AGC > targetIORequest.ResponseTime)
                        {
                            minResponseTimeW_AGC = targetIORequest.ResponseTime;
                        }
                        else if (maxResponseTimeW_AGC < targetIORequest.ResponseTime)
                        {
                            maxResponseTimeW_AGC = targetIORequest.ResponseTime;
                        }
                    }
                }
                else
                {
                    sumResponseTimeR          += (targetIORequest.ResponseTime / 1000);
                    thisRoundSumResponseTimeR += (targetIORequest.ResponseTime / 1000);
                    transferredBytesCountR    += targetIORequest.SizeInByte;
                    handledReadRequestsCount++;
                    thisRoundHandledReadRequestsCount++;
                    if (minResponseTimeR > targetIORequest.ResponseTime)
                    {
                        minResponseTimeR = targetIORequest.ResponseTime;
                    }
                    else if (maxResponseTimeR < targetIORequest.ResponseTime)
                    {
                        maxResponseTimeR = targetIORequest.ResponseTime;
                    }
                    if (gcStarted)
                    {
                        sumResponseTimeR_AGC       += (targetIORequest.ResponseTime / 1000);
                        transferredBytesCountR_AGC += targetIORequest.SizeInByte;
                        handledReadRequestsCount_AGC++;
                        if (minResponseTimeR_AGC > targetIORequest.ResponseTime)
                        {
                            minResponseTimeR_AGC = targetIORequest.ResponseTime;
                        }
                        else if (maxResponseTimeR_AGC < targetIORequest.ResponseTime)
                        {
                            maxResponseTimeR_AGC = targetIORequest.ResponseTime;
                        }
                    }
                }

                if ((handledRequestsCount / (double)totalRequestsToGenerate) > nextAnnouncementMilestone)
                {
                    nextAnnouncementMilestone += announcementStep;
                    OnStatReady();
                }

                OnIORequestCompleted(targetIORequest.StreamID);
            }//_inputStreams[targetIORequest.StreamID].WriteToCompletionQueue...
        }
Example #7
0
 /// <summary>
 /// Provides communication between controller and flash chip for a simple read/write/erase command.
 /// </summary>
 /// <param name="internalReq">The internal request that should be sent to the target flash chip.</param>
 public abstract void SendSimpleCommandToChip(InternalRequest internalReq);