protected virtual void OnInternalRequestServiced(InternalRequest targetRequest) { if (onInternalRequestServiced != null) { onInternalRequestServiced(targetRequest, ChannelID, this); } }
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); } } } }
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; } }
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--; } } } }
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); }
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... }
/// <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);