본문 바로가기

프로젝트/↳ STUDY | 실습

MATLAB을 이용한 5G TDD 스케쥴링 구현

본격적인 5G네트워크 스케쥴링에 앞서 Mathworks에서 제공해주는 NR 실험 모델을 통해 스케쥴링이 어떻게 구현되는지에 대해 이해할 필요가 있었다.

 

해당 내용은 다음 링크에서 가져왔다.

https://kr.mathworks.com/help/5g/ug/nr-tdd-symbol-based-scheduling-performance-evaluation.html

 

NR TDD Symbol Based Scheduling Performance Evaluation - MATLAB & Simulink - MathWorks 한국

이 예제의 수정된 버전이 있습니다. 사용자가 편집한 내용을 반영하여 이 예제를 여시겠습니까?

kr.mathworks.com

 

우선 MATLAB설치하고,, 5G Toolbox 설치하고,, 를 진행해야 한다.

MATLAB 설치는 알아서 하도록 한다!

5G Toolbox : https://kr.mathworks.com/help/5g/index.html?s_tid=CRUX_lftnav 

 

5G Toolbox Documentation - MathWorks 한국

다음 MATLAB 명령에 해당하는 링크를 클릭했습니다. 명령을 실행하려면 MATLAB 명령 창에 입력하십시오. 웹 브라우저는 MATLAB 명령을 지원하지 않습니다.

kr.mathworks.com

 

분석


메인에서 스크롤을 내리다 보면 다음과 같은 코드가 보인다.

gNB = hNRGNB(simParameters); 
switch(simParameters.SchedulerStrategy)
    case 'RR' % Round robin scheduler
        scheduler = hNRSchedulerRoundRobin(simParameters);
    case 'PF' % Proportional fair scheduler
        scheduler = hNRSchedulerProportionalFair(simParameters);
    case 'BestCQI' % Best CQI scheduler
        scheduler = hNRSchedulerBestCQI(simParameters);
    case 'MYFDD' 
        scheduler = hCustomScheduler(simParameters);
    case 'MYTDD'
        scheduler = hNRSchedulerMYTDD(simParameters);
end
addScheduler(gNB, scheduler); % Add scheduler to gNB

gNB.PhyEntity = hNRGNBPassThroughPhy(simParameters); % Add passthrough PHY
configurePhy(gNB, simParameters);
setPhyInterface(gNB); % Set the interface to PHY layer

 

MYFDD와 MYTDD는 직접구현 한 것이므로 무시하고 RR, PF, BestCQI가 있는것을 볼 수 있다.

 

또한

simParameters.SchedulerStrategy = 'RR'; % Supported scheduling strategies: 'PF', 'RR' and 'BestCQI'
simParameters.TTIGranularity = 4;
simParameters.RBAllocationLimitUL = 15; % For PUSCH
simParameters.RBAllocationLimitDL = 15; % For PDSCH

이 부분에서 내가 어떤 스케쥴링을 선택할지 정할 수 있다.

현재는 RR(RoundRobin)으로 선택되어 있다.

 

1. Round Robin

라운드로빈 스케쥴링에 대해 모른다면 조금 공부하고 오자.

 

라운드로빈 스케쥴링에 대한 코드는 다음과 같다.

스케쥴러 인풋에 있는 모든 UE에 대해 일정하게 for문을 돌면서 공평하게 자원을 할당한다.

classdef hNRSchedulerRoundRobin < hNRScheduler
    %hNRSchedulerRoundRobin Implements round-robin scheduler

    %   Copyright 2020 The MathWorks, Inc.

    methods
        function obj = hNRSchedulerRoundRobin(simParameters)
           % Construct an instance of this class

            % Invoke the super class constructor to initialize the properties
            obj = obj@hNRScheduler(simParameters);
        end

        function [selectedUE, mcsIndex] = runSchedulingStrategy(obj, schedulerInput)
            %runSchedulingStrategy Implements the round-robin scheduling
            %
            %   [SELECTEDUE, MCSINDEX] = runSchedulingStrategy(~,SCHEDULERINPUT) runs
            %   the round robin algorithm and returns the selected UE for this RBG
            %   (among the eligible ones), along with the suitable MCS index based on
            %   the channel conditions. This function gets called for selecting a UE for
            %   each RBG to be used for new transmission, i.e. once for each of the
            %   remaining RBGs after assignment for retransmissions is completed.
            %
            %   SCHEDULERINPUT structure contains the following fields which scheduler
            %   would use (not necessarily all the information) for selecting the UE to
            %   which RBG would be assigned.
            %
            %       eligibleUEs    -  RNTI of the eligible UEs contending for the RBG
            %       RBGIndex       -  RBG index in the slot which is getting scheduled
            %       slotNum        -  Slot number in the frame whose RBG is getting scheduled
            %       RBGSize        -  RBG Size in terms of number of RBs
            %       cqiRBG         -  Uplink Channel quality on RBG for UEs. This is a
            %                         N-by-P  matrix with uplink CQI values for UEs on
            %                         different RBs of RBG. 'N' is the number of eligible
            %                         UEs and 'P' is the RBG size in RBs
            %       mcsRBG         -  MCS for eligible UEs based on the CQI values of the RBs
            %                         of RBG. This is a N-by-2 matrix where 'N' is number of
            %                         eligible UEs. For each eligible UE it contains, MCS
            %                         index (first column) and efficiency (bits/symbol
            %                         considering both Modulation and Coding scheme)
            %       pastDataRate   -  Served data rate. Vector of N elements containing
            %                         historical served data rate to eligible UEs. 'N' is
            %                         the number of eligible UEs
            %       bufferStatus   -  Buffer-Status of UEs. Vector of N elements where 'N'
            %                         is the number of eligible UEs, containing pending
            %                         buffer status for UEs
            %       ttiDur         -  TTI duration in ms
            %       UEs            -  RNTI of all the UEs (even the non-eligible ones for
            %                         this RBG)
            %       lastSelectedUE - The RNTI of the UE which was assigned the last
            %                        scheduled RBG
            %
            %   SELECTEDUE The UE (among the eligible ones) which gets assigned
            %                   this particular resource block group
            %
            %   MCSINDEX   The suitable MCS index based on the channel conditions

            %   Copyright 2019 The MathWorks, Inc.

            % Select next UE for scheduling. After the last selected UE, go in
            % sequence and find the first UE which is eligible and with non-zero
            % buffer status
            selectedUE = -1;
            mcsIndex = -1;
            scheduledUE = schedulerInput.lastSelectedUE;
           
           

            for i = 1:length(schedulerInput.UEs)
                scheduledUE = mod(scheduledUE, length(schedulerInput.UEs))+1; % Next UE selected in round-robin fashion
                % Selected UE through round-robin strategy must be in eligibility-list
                % and must have something to send, otherwise move to the next UE
                index = find(schedulerInput.eligibleUEs == scheduledUE, 1);
                if(~isempty(index))
                    bufferStatus = schedulerInput.bufferStatus(index);
                    if(bufferStatus > 0) % Check if UE has any data pending
                        % Select the UE and calculate the expected MCS index
                        % for uplink grant, based on the CQI values for the RBs
                        % of this RBG
                        selectedUE = schedulerInput.eligibleUEs(index);
                        mcsIndex = schedulerInput.mcsRBG(index, 1);
                        disp(index);
                        break;
                    end
                end
            end
        end
    end
end

라운드로빈을 선택하고 프로그램을 실행시켜보면 다음과 같은 결과가 나온다.

업링크와 다운링크에서 리소스 할당을 보면 모두 공평하게 받고있는 것을 볼 수 있다.

 

2. PF(ProportionalFair)

PF스케쥴링에 대해 모른다면 역시 공부해보고 오자.

classdef hNRSchedulerProportionalFair < hNRScheduler
    %hNRSchedulerProportionalFair Implements proportional fair scheduler

    %   Copyright 2020-2021 The MathWorks, Inc.

    properties
        % MovingAvgDataRateWeight Moving average parameter to calculate the average data rate
        MovingAvgDataRateWeight (1, 1) {mustBeNumeric, mustBeNonempty,...
                     mustBeGreaterThanOrEqual(MovingAvgDataRateWeight, 0),...
                     mustBeLessThanOrEqual(MovingAvgDataRateWeight, 1)} = 0.5;

        % UEsServedDataRate Stores DL and UL served data rate for each UE 
        % N-by-2 matrix where 'N' is the number of UEs. For each UE, gNB
        % maintains a context which is used in taking scheduling decisions.
        % There is one row for each UE, indexed by their respective RNTI
        % values. Each row has two columns with following information:
        % Served data rate in DL and served data rate in UL direction.
        % Served data rate is the average data rate achieved by UE till now
        % and serves as an important parameter for doing proportional fair
        % scheduling
        UEsServedDataRate
    end
    
    methods
        function obj = hNRSchedulerProportionalFair(simParameters)
            %hNRSchedulerProportionalFair Construct an instance of this class

            % Invoke the super class constructor to initialize the properties
            obj = obj@hNRScheduler(simParameters);

            % Moving average parameter to calculate the average data rate
            if isfield(simParameters, 'MovingAvgDataRateWeight')
                obj.MovingAvgDataRateWeight = simParameters.MovingAvgDataRateWeight;
            end

            obj.UEsServedDataRate = ones(length(obj.UEs), 2);
           
        end

        function [selectedUE, mcsIndex] = runSchedulingStrategy(obj, schedulerInput)
            %runSchedulingStrategy Implements the proportional fair scheduling
            %
            %   [SELECTEDUE, MCSINDEX] = runSchedulingStrategy(OBJ, SCHEDULERINPUT) runs
            %   the proportional fair algorithm and returns the UE (among the eligible
            %   ones) which wins this particular resource block group, along with the
            %   suitable MCS index based on the channel conditions. This function gets
            %   called for selecting a UE for each RBG to be used for new transmission
            %   i.e. once for each of the remaining RBGs after assignment for
            %   retransmissions is completed. According to PF scheduling
            %   strategy, the UE which has maximum value for the PF weightage, i.e. the
            %   ratio: (RBG-Achievable-Data-Rate/Historical-data-rate), gets the RBG.
            %
            %   SCHEDULERINPUT structure contains the following fields which scheduler
            %   would use (not necessarily all the information) for selecting the UE to
            %   which RBG would be assigned.
            %
            %       eligibleUEs    - RNTI of the eligible UEs contending for the RBG
            %       selectedRank   - Selected rank for UEs. It is an array of size eligibleUEs
            %       RBGIndex       - RBG index in the slot which is getting scheduled
            %       slotNum        - Slot number in the frame whose RBG is getting scheduled
            %       RBGSize        - RBG Size in terms of number of RBs
            %       cqiRBG         - Uplink Channel quality on RBG for UEs. This is a
            %                        N-by-P  matrix with uplink CQI values for UEs on
            %                        different RBs of RBG. 'N' is the number of eligible
            %                        UEs and 'P' is the RBG size in RBs
            %       mcsRBG         - MCS for eligible UEs based on the CQI values of the RBs
            %                        of RBG. This is a N-by-2 matrix where 'N' is number of
            %                        eligible UEs. For each eligible UE it contains, MCS
            %                        index (first column) and efficiency (bits/symbol
            %                        considering both Modulation and Coding scheme)
            %       pastDataRate   - Served data rate. Vector of N elements containing
            %                        historical served data rate to eligible UEs. 'N' is
            %                        the number of eligible UEs
            %       bufferStatus   - Buffer-Status of UEs. Vector of N elements where 'N'
            %                        is the number of eligible UEs, containing pending
            %                        buffer status for UEs
            %       linkDir        - Link direction as 0 (DL) or 1 (UL)
            %       ttiDur         - TTI duration in ms
            %       UEs            - RNTI of all the UEs (even the non-eligible ones for
            %                        this RBG)
            %       lastSelectedUE - The RNTI of the UE which was assigned the last
            %                        scheduled RBG
            %
            %   SELECTEDUE The UE (among the eligible ones) which gets assigned
            %   this particular resource block group
            %
            %   MCSINDEX The suitable MCS index based on the channel conditions

            selectedUE = -1;
            maxPFWeightage = 0;
            mcsIndex = -1;
            linkDir = schedulerInput.LinkDir;
            for i = 1:length(schedulerInput.eligibleUEs)
                bufferStatus = schedulerInput.bufferStatus(i);
                pastDataRate = obj.UEsServedDataRate(schedulerInput.eligibleUEs(i), linkDir+1);
                disp(obj.UEsServedDataRate);
                if(bufferStatus > 0) % Check if UE has any data pending
                    bitsPerSym = schedulerInput.mcsRBG(i, 2); % Accounting for both Modulation & Coding scheme
                    numLayers = schedulerInput.selectedRank(i);
                    achievableDataRate = ((numLayers* schedulerInput.RBGSize * bitsPerSym * 14 * 12)*1000)/ ...
                        (schedulerInput.ttiDur); % bits/sec
                    % Calculate UE weightage as per PF strategy
                    pfWeightage = achievableDataRate/pastDataRate;
                    if(pfWeightage > maxPFWeightage)
                        % Update the UE with maximum weightage
                        maxPFWeightage = pfWeightage;
                        selectedUE = schedulerInput.eligibleUEs(i);
                        mcsIndex = schedulerInput.mcsRBG(i, 1);
                    end
                end
            end

        end
    end
    methods(Access = protected)

        function uplinkGrants = scheduleULResourcesSlot(obj, slotNum)
            %scheduleULResourcesSlot Schedule UL resources of a slot
            % Uplink grants are returned as output to convey the way the
            % the uplink scheduler has distributed the resources to
            % different UEs. 'slotNum' is the slot number in the 10 ms
            % frame which is getting scheduled. The output 'uplnkGrants' is
            % a cell array where each cell-element represents an uplink
            % grant and has following fields:
            %
            % RNTI        Uplink grant is for this UE
            %
            % Type        Whether assignment is for new transmission ('newTx'),
            %             retransmission ('reTx')
            %
            % HARQId   Selected uplink UE HARQ process ID
            %
            % RBGAllocationBitmap  Frequency-domain resource assignment. A
            %                      bitmap of resource-block-groups of the PUSCH
            %                      bandwidth. Value 1 indicates RBG is assigned
            %                      to the UE
            %
            % StartSymbol  Start symbol of time-domain resources. Assumed to be
            %              0 as time-domain assignment granularity is kept as
            %              full slot
            %
            % NumSymbols   Number of symbols allotted in time-domain
            %
            % SlotOffset   Slot-offset of PUSCH assignments for upcoming slot
            %              w.r.t the current slot
            %
            % MCS          Selected modulation and coding scheme for UE with
            %              respect to the resource assignment done
            %
            % NDI          New data indicator flag
            %
            % DMRSLength   DM-RS length 
            %
            % MappingType  Mapping type
            %
            % NumLayers    Number of transmission layers
            %
            % NumAntennaPorts     Number of antenna ports
            %
            % TPMI                Transmitted precoding matrix indicator
            %
            % NumCDMGroupsWithoutData    Number of DM-RS code division multiplexing (CDM) groups without data
            

            % Calculate offset of the slot to be scheduled, from the current
            % slot
            if slotNum >= obj.CurrSlot
                slotOffset = slotNum - obj.CurrSlot;
                slotSFN = obj.SFN;
            else
                slotOffset = (obj.NumSlotsFrame + slotNum) - obj.CurrSlot;
                slotSFN = obj.SFN+1;
            end

            % Get start UL symbol and number of UL symbols in the slot
            if obj.DuplexMode == 1 % TDD
                DLULPatternIndex = mod(obj.CurrDLULSlotIndex + slotOffset, obj.NumDLULPatternSlots);
                slotFormat = obj.DLULSlotFormat(DLULPatternIndex + 1, :);
                firstULSym = find(slotFormat == obj.ULType, 1, 'first') - 1; % Index of first UL symbol in the slot
                lastULSym = find(slotFormat == obj.ULType, 1, 'last') - 1; % Index of last UL symbol in the slot
                numULSym = lastULSym - firstULSym + 1;
            else % FDD
                % All symbols are UL symbols
                firstULSym = 0;
                numULSym = 14;
            end
            
            % Check if the current slot has any reserved symbol for SRS
            for i=1:size(obj.ULReservedResource, 1) 
                numSlotFrames = 10*(obj.SCS/15); % Number of slots per 10ms frame
                reservedResourceInfo = obj.ULReservedResource(i, :);
                if (mod(numSlotFrames*slotSFN + slotNum - reservedResourceInfo(3), reservedResourceInfo(2)) == 0) % SRS slot check
                    reservedSymbol = reservedResourceInfo(1);
                    if (reservedSymbol >= firstULSym) && (reservedSymbol <= firstULSym+numULSym-1)
                        numULSym = reservedSymbol - firstULSym; % Allow PUSCH to only span till the symbol before the SRS symbol
                    end
                    break; % Only 1-symbol for SRS per slot
                end
            end
            
            if obj.SchedulingType == 0 % Slot based scheduling
                if(obj.PUSCHMappingType =='A' && (firstULSym~=0 || numULSym<4))
                    % PUSCH Mapping type A transmissions always start at symbol 0 and
                    % number of symbols must be >=4, as per TS 38.214 - Table 6.1.2.1-1
                    uplinkGrants = [];
                    return;
                end
                % Assignments to span all the symbols in the slot
                uplinkGrants = assignULResourceTTI(obj, slotNum, firstULSym, numULSym);
                % Update served data rate for the UEs as per the resource
                % assignments. This affects scheduling decisions for future
                % TTI
                updateUEServedDataRate(obj, obj.ULType, uplinkGrants);
            else % Symbol based scheduling
                numTTIs = floor(numULSym / obj.TTIGranularity); % UL TTIs in the slot

                % UL grant array with maximum size to store grants
                uplinkGrants = cell((ceil(14/obj.TTIGranularity) * length(obj.UEs)), 1);
                numULGrants = 0;

                % Schedule all UL TTIs in the slot one-by-one
                startSym = firstULSym;
                for i = 1 : numTTIs
                    TTIULGrants = assignULResourceTTI(obj, slotNum, startSym, obj.TTIGranularity);
                    uplinkGrants(numULGrants + 1 : numULGrants + length(TTIULGrants)) = TTIULGrants(:);
                    numULGrants = numULGrants + length(TTIULGrants);
                    startSym = startSym + obj.TTIGranularity;

                    % Update served data rate for the UEs as per the resource
                    % assignments. This affects scheduling decisions for future
                    % TTI
                    updateUEServedDataRate(obj, obj.ULType, TTIULGrants);
                end
                
                remULSym = mod(numULSym, obj.TTIGranularity); % Remaining unscheduled UL symbols
                % Schedule the remaining unscheduled UL symbols
                if remULSym >= 1 % Minimum PUSCH granularity is 1 symbol
                    TTIULGrants = assignULResourceTTI(obj, slotNum, startSym, remULSym);
                    uplinkGrants(numULGrants + 1 : numULGrants + length(TTIULGrants)) = TTIULGrants(:);
                    numULGrants = numULGrants + length(TTIULGrants);
                    % Update served data rate for the UEs as per the resource
                    % assignments. This affects scheduling decisions for future
                    % TTI
                    updateUEServedDataRate(obj, obj.ULType, TTIULGrants);
                end
                uplinkGrants = uplinkGrants(1 : numULGrants);
            end
        end
        
        function downlinkGrants = scheduleDLResourcesSlot(obj, slotNum)
            %scheduleDLResourcesSlot Schedule DL resources of a slot
            %   DOWNLINKGRANTS = scheduleDLResourcesSlot(OBJ, SLOTNUM)
            %   assigns DL resources of the slot, SLOTNUM. Based on the DL
            %   assignment done, it also updates the DL HARQ process
            %   context.
            %   
            %   SLOTNUM is the slot number in the 10 ms frame whose DL
            %   resources are getting scheduled. For FDD, all the symbols
            %   can be used for DL. For TDD, the DL resources can stretch
            %   the full slot or might just be limited to few symbols in
            %   the slot.
            %
            %   DOWNLINKGRANTS is a cell array where each cell-element
            %   represents a downlink grant and has following fields:
            %
            %       RNTI                Downlink grant is for this UE
            %
            %       Type                Whether assignment is for new transmission ('newTx'),
            %                           retransmission ('reTx')
            %
            %       HARQID              Selected downlink HARQ process ID
            %
            %       RBGAllocationBitmap Frequency-domain resource assignment. A
            %                           bitmap of resource-block-groups of
            %                           the PDSCH bandwidth. Value 1
            %                           indicates RBG is assigned to the UE
            %
            %       StartSymbol         Start symbol of time-domain resources
            %
            %       NumSymbols          Number of symbols allotted in time-domain
            %
            %       SlotOffset          Slot offset of PDSCH assignment
            %                           w.r.t the current slot
            %
            %       MCS                 Selected modulation and coding scheme for UE with
            %                           respect to the resource assignment done
            %
            %       NDI                 New data indicator flag
            %
            %       FeedbackSlotOffset  Slot offset of PDSCH ACK/NACK from
            %                           PDSCH transmission slot (i.e. k1).
            %                           Currently, only a value >=2 is supported 
            %
            %       DMRSLength          DM-RS length 
            %
            %       MappingType         Mapping type
            %
            %       NumLayers           Number of transmission layers
            %
            %       NumCDMGroupsWithoutData     Number of CDM groups without data (1...3)
            %
            %       PrecodingMatrix     Selected precoding matrix.  
            %                           It is an array of size NumLayers-by-P-by-NPRG, where NPRG is the
            %                           number of PRGs in the carrier and P is the number of CSI-RS
            %                           ports. It defines a different precoding matrix of size
            %                           NumLayers-by-P for each PRG. The effective PRG bundle size
            %                           (precoder granularity) is Pd_BWP = ceil(NRB / NPRG). 
            %                           For SISO, set it to 1
            
            % Calculate offset of the slot to be scheduled, from the current slot
            if slotNum >= obj.CurrSlot  % Slot to be scheduled is in the current frame
                slotOffset = slotNum - obj.CurrSlot;
            else % Slot to be scheduled is in the next frame
                slotOffset = (obj.NumSlotsFrame + slotNum) - obj.CurrSlot;
            end

            % Get start DL symbol and number of DL symbols in the slot
            if obj.DuplexMode == 1 % TDD mode
                DLULPatternIndex = mod(obj.CurrDLULSlotIndex + slotOffset, obj.NumDLULPatternSlots);
                slotFormat = obj.DLULSlotFormat(DLULPatternIndex + 1, :);
                firstDLSym = find(slotFormat == obj.DLType, 1, 'first') - 1; % Location of first DL symbol in the slot
                lastDLSym = find(slotFormat == obj.DLType, 1, 'last') - 1; % Location of last DL symbol in the slot
                numDLSym = lastDLSym - firstDLSym + 1;
            else
                % For FDD, all symbols are DL symbols
                firstDLSym = 0;
                numDLSym = 14;
            end

            if obj.SchedulingType == 0  % Slot based scheduling
                % Assignments to span all the symbols in the slot
                downlinkGrants = assignDLResourceTTI(obj, slotNum, firstDLSym, numDLSym);
                % Update served data rate for the UEs as per the resource
                % assignments. This affects scheduling decisions for future
                % TTI
                updateUEServedDataRate(obj, obj.DLType, downlinkGrants);
            else %Symbol based scheduling
                if numDLSym < 2 % PDSCH requires minimum 2 symbols with mapping type B as per TS 38.214 - Table 5.1.2.1-1
                    downlinkGrants = [];
                    return; % Not enough symbols for minimum TTI granularity
                end
                numTTIs = floor(numDLSym / obj.TTIGranularity); % DL TTIs in the slot

                % DL grant array with maximum size to store grants. Maximum
                % grants possible in a slot is the product of number of
                % TTIs in slot and number of UEs
                downlinkGrants = cell((ceil(14/obj.TTIGranularity) * length(obj.UEs)), 1);
                numDLGrants = 0;

                % Schedule all DL TTIs in the slot one-by-one
                startSym = firstDLSym;
                for i = 1 : numTTIs
                    TTIDLGrants = assignDLResourceTTI(obj, slotNum, startSym, obj.TTIGranularity);
                    downlinkGrants(numDLGrants + 1 : numDLGrants + length(TTIDLGrants)) = TTIDLGrants(:);
                    numDLGrants = numDLGrants + length(TTIDLGrants);
                    startSym = startSym + obj.TTIGranularity;

                    % Update served data rate for the UEs as per the resource
                    % assignments. This affects scheduling decisions for future
                    % TTI
                    updateUEServedDataRate(obj, obj.DLType, TTIDLGrants);
                end
                
                remDLSym = mod(numDLSym, obj.TTIGranularity); % Remaining unscheduled DL symbols
                % Schedule the remaining unscheduled DL symbols with
                % granularity lesser than obj.TTIGranularity
                if remDLSym >= 2 % PDSCH requires minimum 2 symbols with mapping type B as per TS 38.214 - Table 5.1.2.1-1
                    ttiGranularity =  [7 4 2];
                    smallerTTIs = ttiGranularity(ttiGranularity < obj.TTIGranularity); % TTI lengths lesser than obj.TTIGranularity
                    for i = 1:length(smallerTTIs)
                        if(smallerTTIs(i) <= remDLSym)
                            TTIDLGrants = assignDLResourceTTI(obj, slotNum, startSym, smallerTTIs(i));
                            downlinkGrants(numDLGrants + 1 : numDLGrants + length(TTIDLGrants)) = TTIDLGrants(:);
                            numDLGrants = numDLGrants + length(TTIDLGrants);
                            startSym = startSym + smallerTTIs(i);
                            remDLSym = remDLSym - smallerTTIs(i);
                            % Update served data rate for the UEs as per the resource
                            % assignments. This affects scheduling decisions for future
                            % TTI
                            updateUEServedDataRate(obj, obj.DLType, TTIDLGrants);
                        end
                    end
                end
                downlinkGrants = downlinkGrants(1 : numDLGrants);
            end
        end
    end

    methods(Access = private)
        function updateUEServedDataRate(obj, linkType, resourceAssignments)
            %updateUEServedDataRate Update UEs' served data rate based on RB assignments
            
            if linkType % Uplink
                mcsTable = obj.MCSTableUL;
                pusch = obj.PUSCHConfig;
                % UL carrier configuration object
                ulCarrierConfig = obj.CarrierConfigUL;
            else % Downlink
                mcsTable = obj.MCSTableDL;
                pdsch = obj.PDSCHConfig;
                % DL carrier configuration object
                dlCarrierConfig = obj.CarrierConfigDL;
            end
            
            % Store UEs which got grant
            scheduledUEs = zeros(length(obj.UEs), 1);
            % Update served data rate for UEs which got grant
            for i = 1:length(resourceAssignments)
                resourceAssignment = resourceAssignments{i};
                scheduledUEs(i) = resourceAssignment.RNTI;
                averageDataRate = obj.UEsServedDataRate(resourceAssignment.RNTI ,linkType+1);
                mcsInfo = mcsTable(resourceAssignment.MCS + 1, :);
                modSchemeBits = mcsInfo(1); % Bits per symbol for modulation scheme
                codeRate = mcsInfo(2)/1024;
                % Modulation scheme and corresponding bits/symbol
                fullmodlist = ["pi/2-BPSK", "BPSK", "QPSK", "16QAM", "64QAM", "256QAM"]';
                qm = [1 1 2 4 6 8];
                modScheme = fullmodlist((modSchemeBits == qm)); % Get modulation scheme string
               
                if linkType % Uplink
                    pusch.SymbolAllocation = [resourceAssignment.StartSymbol resourceAssignment.NumSymbols];
                    pusch.MappingType = resourceAssignment.MappingType;
                    if pusch.MappingType == 'A'
                        dmrsAdditonalPos = obj.PUSCHDMRSAdditionalPosTypeA;
                    else
                        dmrsAdditonalPos = obj.PUSCHDMRSAdditionalPosTypeB;
                    end
                    pusch.DMRS.DMRSLength = resourceAssignment.DMRSLength;
                    pusch.DMRS.DMRSAdditionalPosition = dmrsAdditonalPos;
                    pusch.PRBSet = convertRBGBitmapToRBs(obj, resourceAssignment.RBGAllocationBitmap, linkType);
                    pusch.Modulation = modScheme(1);
                    [~, puschIndicesInfo] = nrPUSCHIndices(ulCarrierConfig, pusch);
                    nLayers = 1;
                    achievedTxBits = nrTBS(modScheme(1), nLayers, length(pusch.PRBSet), ...
                        puschIndicesInfo.NREPerPRB, codeRate);
                else
                    pdsch.SymbolAllocation = [resourceAssignment.StartSymbol resourceAssignment.NumSymbols];
                    pdsch.MappingType = resourceAssignment.MappingType;
                    if pdsch.MappingType == 'A'
                        dmrsAdditonalPos = obj.PDSCHDMRSAdditionalPosTypeA;
                    else
                        dmrsAdditonalPos = obj.PDSCHDMRSAdditionalPosTypeB;
                    end
                    pdsch.DMRS.DMRSLength = resourceAssignment.DMRSLength;
                    pdsch.DMRS.DMRSAdditionalPosition = dmrsAdditonalPos;
                    pdsch.PRBSet = convertRBGBitmapToRBs(obj, resourceAssignment.RBGAllocationBitmap, linkType);
                    pdsch.Modulation = modScheme(1);
                    [~, pdschIndicesInfo] = nrPDSCHIndices(dlCarrierConfig, pdsch);
                    nLayers = resourceAssignment.NumLayers;
                    achievedTxBits = nrTBS(modScheme(1), nLayers, length(pdsch.PRBSet), ...
                        pdschIndicesInfo.NREPerPRB, codeRate);
                end
                
                ttiDuration = (obj.SlotDuration * resourceAssignment.NumSymbols)/14;
                achievedDataRate = (achievedTxBits*1000)/ttiDuration; % bits/sec
                updatedAverageDataRate = ((1-obj.MovingAvgDataRateWeight) * averageDataRate) + ...
                    (obj.MovingAvgDataRateWeight * achievedDataRate);
                obj.UEsServedDataRate(resourceAssignment.RNTI, linkType+1) = updatedAverageDataRate;
            end
            scheduledUEs = nonzeros(scheduledUEs);
            unScheduledUEs = setdiff(obj.UEs, scheduledUEs);
            
            % Update (decrease) served data rate for each unscheduled UE
            for i=1:length(unScheduledUEs)
                averageDataRate = obj.UEsServedDataRate(unScheduledUEs(i) ,linkType+1);
                updatedAverageDataRate = (1-obj.MovingAvgDataRateWeight) * averageDataRate;
                obj.UEsServedDataRate(unScheduledUEs(i), linkType+1) = updatedAverageDataRate;
            end
        end
    end
end

RR에 비해서 매우 코드가 복잡해졌다. 어차피 PF를 건드려서 수정할 것이 아니기에 적당히 이해하고 넘어가자!

 

PR을 실행해보면 다음과 같다.

 

또한 BestCQI도 존재하는데 그냥 넘어가겠다.

중요한건 내가 직접 스케쥴링을 구현해보는 것이다.

3. MYTDD

classdef hNRSchedulerMYTDD < hNRScheduler
    %hNRSchedulerRoundRobin Implements round-robin scheduler

    %   Copyright 2020 The MathWorks, Inc.
    properties
        % MovingAvgDataRateWeight Moving average parameter to calculate the average data rate
        MovingAvgDataRateWeight (1, 1) {mustBeNumeric, mustBeNonempty,...
                     mustBeGreaterThanOrEqual(MovingAvgDataRateWeight, 0),...
                     mustBeLessThanOrEqual(MovingAvgDataRateWeight, 1)} = 0.5;

        % UEsServedDataRate Stores DL and UL served data rate for each UE 
        % N-by-2 matrix where 'N' is the number of UEs. For each UE, gNB
        % maintains a context which is used in taking scheduling decisions.
        % There is one row for each UE, indexed by their respective RNTI
        % values. Each row has two columns with following information:
        % Served data rate in DL and served data rate in UL direction.
        % Served data rate is the average data rate achieved by UE till now
        % and serves as an important parameter for doing proportional fair
        % scheduling
        UEsServedDataRate
    end
    methods
        function obj = hNRSchedulerMYTDD(simParameters)
            %hNRSchedulerProportionalFair Construct an instance of this class
            
            global UE_RATE
            UE_RATE = [1,10,100,1000];
            global UE_CURR 
            UE_CURR = [0,0,0,0];
            global UE_CNT
            UE_CNT = [0,0,0,0];
            global BIT_RATE
            BIT_RATE = [400000000,400000000,400000000,400000000];
            % Invoke the super class constructor to initialize the properties
            obj = obj@hNRScheduler(simParameters);

            % Moving average parameter to calculate the average data rate
            if isfield(simParameters, 'MovingAvgDataRateWeight')
                obj.MovingAvgDataRateWeight = simParameters.MovingAvgDataRateWeight;
            end

            obj.UEsServedDataRate = ones(length(obj.UEs), 2);
           
        end

        function [selectedUE, mcsIndex] = runSchedulingStrategy(obj, schedulerInput)
            %runSchedulingStrategy Implements the round-robin scheduling
            %
            %   [SELECTEDUE, MCSINDEX] = runSchedulingStrategy(~,SCHEDULERINPUT) runs
            %   the round robin algorithm and returns the selected UE for this RBG
            %   (among the eligible ones), along with the suitable MCS index based on
            %   the channel conditions. This function gets called for selecting a UE for
            %   each RBG to be used for new transmission, i.e. once for each of the
            %   remaining RBGs after assignment for retransmissions is completed.
            %
            %   SCHEDULERINPUT structure contains the following fields which scheduler
            %   would use (not necessarily all the information) for selecting the UE to
            %   which RBG would be assigned.
            %
            %       eligibleUEs    -  RNTI of the eligible UEs contending for the RBG
            %       RBGIndex       -  RBG index in the slot which is getting scheduled
            %       slotNum        -  Slot number in the frame whose RBG is getting scheduled
            %       RBGSize        -  RBG Size in terms of number of RBs
            %       cqiRBG         -  Uplink Channel quality on RBG for UEs. This is a
            %                         N-by-P  matrix with uplink CQI values for UEs on
            %                         different RBs of RBG. 'N' is the number of eligible
            %                         UEs and 'P' is the RBG size in RBs
            %       mcsRBG         -  MCS for eligible UEs based on the CQI values of the RBs
            %                         of RBG. This is a N-by-2 matrix where 'N' is number of
            %                         eligible UEs. For each eligible UE it contains, MCS
            %                         index (first column) and efficiency (bits/symbol
            %                         considering both Modulation and Coding scheme)
            %       pastDataRate   -  Served data rate. Vector of N elements containing
            %                         historical served data rate to eligible UEs. 'N' is
            %                         the number of eligible UEs
            %       bufferStatus   -  Buffer-Status of UEs. Vector of N elements where 'N'
            %                         is the number of eligible UEs, containing pending
            %                         buffer status for UEs
            %       ttiDur         -  TTI duration in ms
            %       UEs            -  RNTI of all the UEs (even the non-eligible ones for
            %                         this RBG)
            %       lastSelectedUE - The RNTI of the UE which was assigned the last
            %                        scheduled RBG
            %
            %   SELECTEDUE The UE (among the eligible ones) which gets assigned
            %                   this particular resource block group
            %
            %   MCSINDEX   The suitable MCS index based on the channel conditions

            %   Copyright 2019 The MathWorks, Inc.

            % Select next UE for scheduling. After the last selected UE, go in
            % sequence and find the first UE which is eligible and with non-zero
            % buffer status
            selectedUE = -1;
            mcsIndex = -1;
            scheduledUE = schedulerInput.lastSelectedUE;
            
            
            %disp(schedulerInput);
            global UE_RATE;
            global UE_CURR;
            global UE_CNT;
            global BIT_RATE;
            maxtmp = 0;
            idx = 0;
            linkDir = schedulerInput.LinkDir;

            for i = 1:length(schedulerInput.eligibleUEs)
                bufferStatus = schedulerInput.bufferStatus(i);
                if(bufferStatus <= 0 || obj.UEsServedDataRate(i,linkDir+1) >=BIT_RATE(i))
         
                    continue;
                end
                tmp = UE_RATE(i)-UE_CURR(i);
                
                if(tmp>maxtmp) 
                    idx = i;
                    
                    maxtmp = tmp;
                end
            end

            if(idx==0)
                for i = 1:length(schedulerInput.eligibleUEs)
                    if(schedulerInput.bufferStatus(i)>0 && obj.UEsServedDataRate(i,linkDir+1) < BIT_RATE(i))
                        idx = i;
                    end
                end
                UE_CURR = [0,0,0,0];
            end

         
            if(idx>0) 
                UE_CURR(idx) = UE_CURR(idx)+1;
                %disp(idx);
                UE_CNT(idx) = UE_CNT(idx) + 1;
                selectedUE = schedulerInput.eligibleUEs(idx);
                mcsIndex = schedulerInput.mcsRBG(idx, 1);
            end
            %disp(UE_CURR);
            %disp(obj.UEsServedDataRate);
            disp("----------------");
            for i = 1:4
                txt = sprintf('%f, %f',obj.UEsServedDataRate(i,1), obj.UEsServedDataRate(i,2));
                disp(txt);
            end
            disp(obj.UEsServedDataRate(1,1)+obj.UEsServedDataRate(2,1)+obj.UEsServedDataRate(3,1)+obj.UEsServedDataRate(4,1));
            disp(obj.UEsServedDataRate(1,2)+obj.UEsServedDataRate(2,2)+obj.UEsServedDataRate(3,2)+obj.UEsServedDataRate(4,2));
            %disp(PAST);
            %disp(obj.UEsServedDataRate);
            %disp(UE_CURR);

            
        end
    end

    methods(Access = protected)

        function uplinkGrants = scheduleULResourcesSlot(obj, slotNum)
            %scheduleULResourcesSlot Schedule UL resources of a slot
            % Uplink grants are returned as output to convey the way the
            % the uplink scheduler has distributed the resources to
            % different UEs. 'slotNum' is the slot number in the 10 ms
            % frame which is getting scheduled. The output 'uplnkGrants' is
            % a cell array where each cell-element represents an uplink
            % grant and has following fields:
            %
            % RNTI        Uplink grant is for this UE
            %
            % Type        Whether assignment is for new transmission ('newTx'),
            %             retransmission ('reTx')
            %
            % HARQId   Selected uplink UE HARQ process ID
            %
            % RBGAllocationBitmap  Frequency-domain resource assignment. A
            %                      bitmap of resource-block-groups of the PUSCH
            %                      bandwidth. Value 1 indicates RBG is assigned
            %                      to the UE
            %
            % StartSymbol  Start symbol of time-domain resources. Assumed to be
            %              0 as time-domain assignment granularity is kept as
            %              full slot
            %
            % NumSymbols   Number of symbols allotted in time-domain
            %
            % SlotOffset   Slot-offset of PUSCH assignments for upcoming slot
            %              w.r.t the current slot
            %
            % MCS          Selected modulation and coding scheme for UE with
            %              respect to the resource assignment done
            %
            % NDI          New data indicator flag
            %
            % DMRSLength   DM-RS length 
            %
            % MappingType  Mapping type
            %
            % NumLayers    Number of transmission layers
            %
            % NumAntennaPorts     Number of antenna ports
            %
            % TPMI                Transmitted precoding matrix indicator
            %
            % NumCDMGroupsWithoutData    Number of DM-RS code division multiplexing (CDM) groups without data
            

            % Calculate offset of the slot to be scheduled, from the current
            % slot
            if slotNum >= obj.CurrSlot
                slotOffset = slotNum - obj.CurrSlot;
                slotSFN = obj.SFN;
            else
                slotOffset = (obj.NumSlotsFrame + slotNum) - obj.CurrSlot;
                slotSFN = obj.SFN+1;
            end

            % Get start UL symbol and number of UL symbols in the slot
            if obj.DuplexMode == 1 % TDD
                DLULPatternIndex = mod(obj.CurrDLULSlotIndex + slotOffset, obj.NumDLULPatternSlots);
                slotFormat = obj.DLULSlotFormat(DLULPatternIndex + 1, :);
                firstULSym = find(slotFormat == obj.ULType, 1, 'first') - 1; % Index of first UL symbol in the slot
                lastULSym = find(slotFormat == obj.ULType, 1, 'last') - 1; % Index of last UL symbol in the slot
                numULSym = lastULSym - firstULSym + 1;
            else % FDD
                % All symbols are UL symbols
                firstULSym = 0;
                numULSym = 14;
            end
            
            % Check if the current slot has any reserved symbol for SRS
            for i=1:size(obj.ULReservedResource, 1) 
                numSlotFrames = 10*(obj.SCS/15); % Number of slots per 10ms frame
                reservedResourceInfo = obj.ULReservedResource(i, :);
                if (mod(numSlotFrames*slotSFN + slotNum - reservedResourceInfo(3), reservedResourceInfo(2)) == 0) % SRS slot check
                    reservedSymbol = reservedResourceInfo(1);
                    if (reservedSymbol >= firstULSym) && (reservedSymbol <= firstULSym+numULSym-1)
                        numULSym = reservedSymbol - firstULSym; % Allow PUSCH to only span till the symbol before the SRS symbol
                    end
                    break; % Only 1-symbol for SRS per slot
                end
            end
            
            if obj.SchedulingType == 0 % Slot based scheduling
                if(obj.PUSCHMappingType =='A' && (firstULSym~=0 || numULSym<4))
                    % PUSCH Mapping type A transmissions always start at symbol 0 and
                    % number of symbols must be >=4, as per TS 38.214 - Table 6.1.2.1-1
                    uplinkGrants = [];
                    return;
                end
                % Assignments to span all the symbols in the slot
                uplinkGrants = assignULResourceTTI(obj, slotNum, firstULSym, numULSym);
                % Update served data rate for the UEs as per the resource
                % assignments. This affects scheduling decisions for future
                % TTI
                updateUEServedDataRate(obj, obj.ULType, uplinkGrants);
            else % Symbol based scheduling
                numTTIs = floor(numULSym / obj.TTIGranularity); % UL TTIs in the slot

                % UL grant array with maximum size to store grants
                uplinkGrants = cell((ceil(14/obj.TTIGranularity) * length(obj.UEs)), 1);
                numULGrants = 0;

                % Schedule all UL TTIs in the slot one-by-one
                startSym = firstULSym;
                for i = 1 : numTTIs
                    TTIULGrants = assignULResourceTTI(obj, slotNum, startSym, obj.TTIGranularity);
                    uplinkGrants(numULGrants + 1 : numULGrants + length(TTIULGrants)) = TTIULGrants(:);
                    numULGrants = numULGrants + length(TTIULGrants);
                    startSym = startSym + obj.TTIGranularity;

                    % Update served data rate for the UEs as per the resource
                    % assignments. This affects scheduling decisions for future
                    % TTI
                    updateUEServedDataRate(obj, obj.ULType, TTIULGrants);
                end
                
                remULSym = mod(numULSym, obj.TTIGranularity); % Remaining unscheduled UL symbols
                % Schedule the remaining unscheduled UL symbols
                if remULSym >= 1 % Minimum PUSCH granularity is 1 symbol
                    TTIULGrants = assignULResourceTTI(obj, slotNum, startSym, remULSym);
                    uplinkGrants(numULGrants + 1 : numULGrants + length(TTIULGrants)) = TTIULGrants(:);
                    numULGrants = numULGrants + length(TTIULGrants);
                    % Update served data rate for the UEs as per the resource
                    % assignments. This affects scheduling decisions for future
                    % TTI
                    updateUEServedDataRate(obj, obj.ULType, TTIULGrants);
                end
                uplinkGrants = uplinkGrants(1 : numULGrants);
            end
        end
        
        function downlinkGrants = scheduleDLResourcesSlot(obj, slotNum)
            %scheduleDLResourcesSlot Schedule DL resources of a slot
            %   DOWNLINKGRANTS = scheduleDLResourcesSlot(OBJ, SLOTNUM)
            %   assigns DL resources of the slot, SLOTNUM. Based on the DL
            %   assignment done, it also updates the DL HARQ process
            %   context.
            %   
            %   SLOTNUM is the slot number in the 10 ms frame whose DL
            %   resources are getting scheduled. For FDD, all the symbols
            %   can be used for DL. For TDD, the DL resources can stretch
            %   the full slot or might just be limited to few symbols in
            %   the slot.
            %
            %   DOWNLINKGRANTS is a cell array where each cell-element
            %   represents a downlink grant and has following fields:
            %
            %       RNTI                Downlink grant is for this UE
            %
            %       Type                Whether assignment is for new transmission ('newTx'),
            %                           retransmission ('reTx')
            %
            %       HARQID              Selected downlink HARQ process ID
            %
            %       RBGAllocationBitmap Frequency-domain resource assignment. A
            %                           bitmap of resource-block-groups of
            %                           the PDSCH bandwidth. Value 1
            %                           indicates RBG is assigned to the UE
            %
            %       StartSymbol         Start symbol of time-domain resources
            %
            %       NumSymbols          Number of symbols allotted in time-domain
            %
            %       SlotOffset          Slot offset of PDSCH assignment
            %                           w.r.t the current slot
            %
            %       MCS                 Selected modulation and coding scheme for UE with
            %                           respect to the resource assignment done
            %
            %       NDI                 New data indicator flag
            %
            %       FeedbackSlotOffset  Slot offset of PDSCH ACK/NACK from
            %                           PDSCH transmission slot (i.e. k1).
            %                           Currently, only a value >=2 is supported 
            %
            %       DMRSLength          DM-RS length 
            %
            %       MappingType         Mapping type
            %
            %       NumLayers           Number of transmission layers
            %
            %       NumCDMGroupsWithoutData     Number of CDM groups without data (1...3)
            %
            %       PrecodingMatrix     Selected precoding matrix.  
            %                           It is an array of size NumLayers-by-P-by-NPRG, where NPRG is the
            %                           number of PRGs in the carrier and P is the number of CSI-RS
            %                           ports. It defines a different precoding matrix of size
            %                           NumLayers-by-P for each PRG. The effective PRG bundle size
            %                           (precoder granularity) is Pd_BWP = ceil(NRB / NPRG). 
            %                           For SISO, set it to 1
            
            % Calculate offset of the slot to be scheduled, from the current slot
            if slotNum >= obj.CurrSlot  % Slot to be scheduled is in the current frame
                slotOffset = slotNum - obj.CurrSlot;
            else % Slot to be scheduled is in the next frame
                slotOffset = (obj.NumSlotsFrame + slotNum) - obj.CurrSlot;
            end

            % Get start DL symbol and number of DL symbols in the slot
            if obj.DuplexMode == 1 % TDD mode
                DLULPatternIndex = mod(obj.CurrDLULSlotIndex + slotOffset, obj.NumDLULPatternSlots);
                slotFormat = obj.DLULSlotFormat(DLULPatternIndex + 1, :);
                firstDLSym = find(slotFormat == obj.DLType, 1, 'first') - 1; % Location of first DL symbol in the slot
                lastDLSym = find(slotFormat == obj.DLType, 1, 'last') - 1; % Location of last DL symbol in the slot
                numDLSym = lastDLSym - firstDLSym + 1;
            else
                % For FDD, all symbols are DL symbols
                firstDLSym = 0;
                numDLSym = 14;
            end

            if obj.SchedulingType == 0  % Slot based scheduling
                % Assignments to span all the symbols in the slot
                downlinkGrants = assignDLResourceTTI(obj, slotNum, firstDLSym, numDLSym);
                % Update served data rate for the UEs as per the resource
                % assignments. This affects scheduling decisions for future
                % TTI
                updateUEServedDataRate(obj, obj.DLType, downlinkGrants);
            else %Symbol based scheduling
                if numDLSym < 2 % PDSCH requires minimum 2 symbols with mapping type B as per TS 38.214 - Table 5.1.2.1-1
                    downlinkGrants = [];
                    return; % Not enough symbols for minimum TTI granularity
                end
                numTTIs = floor(numDLSym / obj.TTIGranularity); % DL TTIs in the slot

                % DL grant array with maximum size to store grants. Maximum
                % grants possible in a slot is the product of number of
                % TTIs in slot and number of UEs
                downlinkGrants = cell((ceil(14/obj.TTIGranularity) * length(obj.UEs)), 1);
                numDLGrants = 0;

                % Schedule all DL TTIs in the slot one-by-one
                startSym = firstDLSym;
                for i = 1 : numTTIs
                    TTIDLGrants = assignDLResourceTTI(obj, slotNum, startSym, obj.TTIGranularity);
                    downlinkGrants(numDLGrants + 1 : numDLGrants + length(TTIDLGrants)) = TTIDLGrants(:);
                    numDLGrants = numDLGrants + length(TTIDLGrants);
                    startSym = startSym + obj.TTIGranularity;

                    % Update served data rate for the UEs as per the resource
                    % assignments. This affects scheduling decisions for future
                    % TTI
                    updateUEServedDataRate(obj, obj.DLType, TTIDLGrants);
                end
                
                remDLSym = mod(numDLSym, obj.TTIGranularity); % Remaining unscheduled DL symbols
                % Schedule the remaining unscheduled DL symbols with
                % granularity lesser than obj.TTIGranularity
                if remDLSym >= 2 % PDSCH requires minimum 2 symbols with mapping type B as per TS 38.214 - Table 5.1.2.1-1
                    ttiGranularity =  [7 4 2];
                    smallerTTIs = ttiGranularity(ttiGranularity < obj.TTIGranularity); % TTI lengths lesser than obj.TTIGranularity
                    for i = 1:length(smallerTTIs)
                        if(smallerTTIs(i) <= remDLSym)
                            TTIDLGrants = assignDLResourceTTI(obj, slotNum, startSym, smallerTTIs(i));
                            downlinkGrants(numDLGrants + 1 : numDLGrants + length(TTIDLGrants)) = TTIDLGrants(:);
                            numDLGrants = numDLGrants + length(TTIDLGrants);
                            startSym = startSym + smallerTTIs(i);
                            remDLSym = remDLSym - smallerTTIs(i);
                            % Update served data rate for the UEs as per the resource
                            % assignments. This affects scheduling decisions for future
                            % TTI
                            updateUEServedDataRate(obj, obj.DLType, TTIDLGrants);
                        end
                    end
                end
                downlinkGrants = downlinkGrants(1 : numDLGrants);
            end
        end
    end

    methods(Access = private)
        function updateUEServedDataRate(obj, linkType, resourceAssignments)
            %updateUEServedDataRate Update UEs' served data rate based on RB assignments
            
            if linkType % Uplink
                mcsTable = obj.MCSTableUL;
                pusch = obj.PUSCHConfig;
                % UL carrier configuration object
                ulCarrierConfig = obj.CarrierConfigUL;
            else % Downlink
                mcsTable = obj.MCSTableDL;
                pdsch = obj.PDSCHConfig;
                % DL carrier configuration object
                dlCarrierConfig = obj.CarrierConfigDL;
            end
            
            % Store UEs which got grant
            scheduledUEs = zeros(length(obj.UEs), 1);
            % Update served data rate for UEs which got grant
            for i = 1:length(resourceAssignments)
                resourceAssignment = resourceAssignments{i};
                scheduledUEs(i) = resourceAssignment.RNTI;
                averageDataRate = obj.UEsServedDataRate(resourceAssignment.RNTI ,linkType+1);
                mcsInfo = mcsTable(resourceAssignment.MCS + 1, :);
                modSchemeBits = mcsInfo(1); % Bits per symbol for modulation scheme
                codeRate = mcsInfo(2)/1024;
                % Modulation scheme and corresponding bits/symbol
                fullmodlist = ["pi/2-BPSK", "BPSK", "QPSK", "16QAM", "64QAM", "256QAM"]';
                qm = [1 1 2 4 6 8];
                modScheme = fullmodlist((modSchemeBits == qm)); % Get modulation scheme string
               
                if linkType % Uplink
                    pusch.SymbolAllocation = [resourceAssignment.StartSymbol resourceAssignment.NumSymbols];
                    pusch.MappingType = resourceAssignment.MappingType;
                    if pusch.MappingType == 'A'
                        dmrsAdditonalPos = obj.PUSCHDMRSAdditionalPosTypeA;
                    else
                        dmrsAdditonalPos = obj.PUSCHDMRSAdditionalPosTypeB;
                    end
                    pusch.DMRS.DMRSLength = resourceAssignment.DMRSLength;
                    pusch.DMRS.DMRSAdditionalPosition = dmrsAdditonalPos;
                    pusch.PRBSet = convertRBGBitmapToRBs(obj, resourceAssignment.RBGAllocationBitmap, linkType);
                    pusch.Modulation = modScheme(1);
                    [~, puschIndicesInfo] = nrPUSCHIndices(ulCarrierConfig, pusch);
                    nLayers = 1;
                    achievedTxBits = nrTBS(modScheme(1), nLayers, length(pusch.PRBSet), ...
                        puschIndicesInfo.NREPerPRB, codeRate);
                else
                    pdsch.SymbolAllocation = [resourceAssignment.StartSymbol resourceAssignment.NumSymbols];
                    pdsch.MappingType = resourceAssignment.MappingType;
                    if pdsch.MappingType == 'A'
                        dmrsAdditonalPos = obj.PDSCHDMRSAdditionalPosTypeA;
                    else
                        dmrsAdditonalPos = obj.PDSCHDMRSAdditionalPosTypeB;
                    end
                    pdsch.DMRS.DMRSLength = resourceAssignment.DMRSLength;
                    pdsch.DMRS.DMRSAdditionalPosition = dmrsAdditonalPos;
                    pdsch.PRBSet = convertRBGBitmapToRBs(obj, resourceAssignment.RBGAllocationBitmap, linkType);
                    pdsch.Modulation = modScheme(1);
                    [~, pdschIndicesInfo] = nrPDSCHIndices(dlCarrierConfig, pdsch);
                    nLayers = resourceAssignment.NumLayers;
                    achievedTxBits = nrTBS(modScheme(1), nLayers, length(pdsch.PRBSet), ...
                        pdschIndicesInfo.NREPerPRB, codeRate);
                end
                
                ttiDuration = (obj.SlotDuration * resourceAssignment.NumSymbols)/14;
                achievedDataRate = (achievedTxBits*1000)/ttiDuration; % bits/sec
                %updatedAverageDataRate = ((1-obj.MovingAvgDataRateWeight) * averageDataRate) + ...
                 %   (obj.MovingAvgDataRateWeight * achievedDataRate);
                updatedAverageDataRate = averageDataRate + achievedDataRate ;
                obj.UEsServedDataRate(resourceAssignment.RNTI, linkType+1) = updatedAverageDataRate;
            end
            scheduledUEs = nonzeros(scheduledUEs);
            unScheduledUEs = setdiff(obj.UEs, scheduledUEs);
            
            % Update (decrease) served data rate for each unscheduled UE
            for i=1:length(unScheduledUEs)
                averageDataRate = obj.UEsServedDataRate(unScheduledUEs(i) ,linkType+1);
                updatedAverageDataRate = averageDataRate ;%* (1-obj.MovingAvgDataRateWeight) ;
                disp(obj.MovingAvgDataRateWeight);
                obj.UEsServedDataRate(unScheduledUEs(i), linkType+1) = updatedAverageDataRate;
            end
        end
    end
end

전체 가중치를 1 : 10 : 100 : 1000 으로 해봤다. 

예상되는 그래프는 가중치가 큰 UE부터 자원을 할당해주어야 한다.

 

예상대로 가중치가 큰 UE부터 차례대로 할당해주는 것을 볼 수 있다.

 

여기에서 구현해본 경험을 바탕으로 직접 5G네트워크 구축할때 스케쥴링에 이용하면 될 것 같다.

 

'프로젝트 > ↳ STUDY | 실습' 카테고리의 다른 글

4G(LTE)와 5G(NR)의 구조  (0) 2022.04.19