public override IORequest SaturatedMode_GetNextRequest()
        {
            if (ReceivedRequestCount == numberOfRequestsToBeSeen)
            {
                return(null);
            }

            ulong lsn = 0;

            switch (addressDistributionType)
            {
            case InputStreamSynthetic.DistributionType.Uniform:
                lsn = randomAddressGenerator1.UniformULong(addressDistributionParam1, addressDistributionParam2);
                break;

            case InputStreamSynthetic.DistributionType.Normal:
                double templsn = randomAddressGenerator1.Normal(addressDistributionParam1, addressDistributionParam2);
                lsn = (uint)templsn;
                if (templsn < 0)
                {
                    lsn = 0;
                }
                else if (templsn > this.FTL.AddressMapper.LargestLSN)
                {
                    lsn = this.FTL.AddressMapper.LargestLSN;
                }
                break;

            case InputStreamSynthetic.DistributionType.Fixed:
                lsn = addressDistributionParam1;
                break;

            case InputStreamSynthetic.DistributionType.HotCold:
                if (randomHotColdRatioGenerator.Uniform(0, 1) < hotTrafficRate)
                {
                    lsn = addressDistributionParam1 + randomHotAddressGenerator.UniformULong(0, hotAddressRange);
                }
                else
                {
                    lsn = randomAddressGenerator1.UniformULong(0, this.FTL.AddressMapper.LargestLSN - hotAddressRange);
                    if (lsn > addressDistributionParam1)
                    {
                        lsn += hotAddressRange;
                    }
                }
                break;

            default:
                throw new Exception("Unknown distribution type for address.");
            }

            uint reqSize = 0;

            switch (requestSizeDistributionType)
            {
            case InputStreamSynthetic.DistributionType.Uniform:
                double tempReqSize = randomRequestSizeGenerator.Uniform(requestSizeDistributionParam1B, requestSizeDistributionParam2B);
                reqSize = (uint)(Math.Ceiling(tempReqSize / (double)FTL.SubPageCapacity));
                if (reqSize == 0)
                {
                    reqSize = 1;
                }
                break;

            case InputStreamSynthetic.DistributionType.Normal:
                tempReqSize = randomRequestSizeGenerator.Normal(requestSizeDistributionParam1B, requestSizeDistributionParam2B);
                reqSize     = (uint)(Math.Ceiling(tempReqSize / (double)FTL.SubPageCapacity));
                if (tempReqSize < 0)
                {
                    reqSize = 1;
                }
                break;

            case InputStreamSynthetic.DistributionType.Fixed:
                reqSize = (uint)(Math.Ceiling(requestSizeDistributionParam1B / (double)FTL.SubPageCapacity));
                break;

            default:
                throw new Exception("Uknown distribution type for requset size.");
            }
            IORequest request = null;

            if (randomRequestTypeGenerator.Uniform(0, 1) < readRatio)
            {
                request = new IORequest(XEngineFactory.XEngine.Time, lsn, reqSize, IORequestType.Read);
                ReceivedReadRequestCount++;
            }
            else
            {
                request = new IORequest(XEngineFactory.XEngine.Time, lsn, reqSize, IORequestType.Write);
                ReceivedWriteRequestCount++;
            }

            ReceivedRequestCount++;
            if (ReceivedRequestCount == numberOfRequestsToBeSeen)
            {
                reqExists = false;
            }

            request.RelatedNodeInList = NCQ.AddLast(request);

            return(request);
        }
        public override void ProcessXEvent(XEvent e)
        {
            switch ((HostInterfaceEventType)e.Type)
            {
            case HostInterfaceEventType.GenerateNextIORequest:
                IORequest request = null;

                IORequestType reqType = IORequestType.Write;
                if (randomRequestTypeGenerator.Uniform(0, 1) < readRatio)
                {
                    reqType = IORequestType.Read;
                    ReceivedReadRequestCount++;
                }
                else
                {
                    ReceivedWriteRequestCount++;
                }


                ulong lsn = 0;
                switch (addressDistributionType)
                {
                case InputStreamSynthetic.DistributionType.Uniform:
                    lsn = randomAddressGenerator1.UniformULong(addressDistributionParam1, addressDistributionParam2);
                    break;

                case InputStreamSynthetic.DistributionType.Normal:
                    double templsn = randomAddressGenerator1.Normal(addressDistributionParam1, addressDistributionParam2);
                    lsn = (uint)templsn;
                    if (templsn < 0)
                    {
                        lsn = 0;
                    }
                    else if (templsn > this.FTL.AddressMapper.LargestLSN)
                    {
                        lsn = this.FTL.AddressMapper.LargestLSN;
                    }
                    break;

                case InputStreamSynthetic.DistributionType.Fixed:
                    lsn = addressDistributionParam1;
                    break;

                case InputStreamSynthetic.DistributionType.HotCold:
                    if (randomHotColdRatioGenerator.Uniform(0, 1) < hotTrafficRate)
                    {
                        lsn = addressDistributionParam1 + randomHotAddressGenerator.UniformULong(0, hotAddressRange);
                    }
                    else
                    {
                        lsn = randomAddressGenerator1.UniformULong(0, this.FTL.AddressMapper.LargestLSN - hotAddressRange);
                        if (lsn > addressDistributionParam1)
                        {
                            lsn += hotAddressRange;
                        }
                    }
                    break;

                default:
                    throw new Exception("Unknown distribution type for address.");
                }

                uint reqSize = 0;
                switch (requestSizeDistributionType)
                {
                case InputStreamSynthetic.DistributionType.Uniform:
                    double tempReqSize = randomRequestSizeGenerator.Uniform(requestSizeDistributionParam1B, requestSizeDistributionParam2B);
                    reqSize = (uint)(Math.Ceiling(tempReqSize / (double)FTL.SubPageCapacity));
                    if (reqSize == 0)
                    {
                        reqSize = 1;
                    }
                    break;

                case InputStreamSynthetic.DistributionType.Normal:
                    tempReqSize = randomRequestSizeGenerator.Normal(requestSizeDistributionParam1B, requestSizeDistributionParam2B);
                    reqSize     = (uint)(Math.Ceiling(tempReqSize / (double)FTL.SubPageCapacity));
                    if (tempReqSize < 0)
                    {
                        reqSize = 1;
                    }
                    break;

                case InputStreamSynthetic.DistributionType.Fixed:
                    reqSize = (uint)(Math.Ceiling(requestSizeDistributionParam1B / (double)FTL.SubPageCapacity));
                    break;

                default:
                    throw new Exception("Uknown distribution type for requset size.");
                }

                request = new IORequest(XEngineFactory.XEngine.Time, lsn, reqSize, reqType);

                ReceivedRequestCount++;
                if (NCQ.Count < NCQSize)
                {
                    request.RelatedNodeInList = NCQ.AddLast(request);
                    SegmentIORequestNoCache_Sprinkler(request);
                    FTL.IOScheduler.Schedule((uint)StreamPriorityClass.Urgent, AddressMappingModule.DefaultStreamID);
                    //FTL.ServiceIORequest();
                }
                else
                {
                    HostQueue.AddLast(request);
                }

                if (ReceivedRequestCount < numberOfRequestsToBeSeen)
                {
                    nextRequetArrivalTime = XEngineFactory.XEngine.Time + (ulong)(randomTimeIntervalGenerator.Exponential(averageRequestInterArrivalTime));
                    XEngineFactory.XEngine.EventList.InsertXEvent(new XEvent(nextRequetArrivalTime, this, null, 0));
                }
                break;

            case HostInterfaceEventType.RequestCompletedByDRAM:
                IORequest targetRequest = e.Parameters as IORequest;
                SendEarlyResponseToHost(targetRequest);
                break;

            default:
                throw new Exception("Unhandled XEvent type");
            }
        }