このページの内容は最新ではありません。最新版の英語を参照するには、ここをクリックします。
6G リンクレベル シミュレーション
この参照シミュレーションでは、pre-6G リンクのスループットを測定する方法を示します。これは 5G に基づいていますが、5G システムよりも広い帯域幅とサブキャリア間隔を調査できます。また、並列処理を使用し、デスクトップまたはクラウドの複数のワーカーを使ってシミュレーションを高速化します。
はじめに
この例では、pre-6G リンクの物理ダウンリンク共有チャネル (PDSCH) のスループットを測定します。この例では、5G NR の 3GPP 仕様で定義されている範囲を超えるいくつかのパラメーター範囲を使用できます。Get Started with 6G Exploration Libraryの例で説明されているように、275 個よりも多いリソース ブロックと 960 kHz よりも大きいサブキャリア間隔を使用できます。
この例では、次の機能をモデル化します。
ダウンリンク共有チャネル (DL-SCH) トランスポート チャネルの符号化
レイヤー数に応じた複数のコードワード
PDSCH および PDSCH の復調基準信号 (DM-RS) の生成
可変サブキャリア間隔とフレーム numerology ( kHz)
ノーマル サイクリック プレフィックスと拡張サイクリック プレフィックス
クラスター遅延線 (CDL) 伝播チャネル モデル
特異値分解 (SVD) を使用した PDSCH サブバンド プリコーディング
完全なチャネル推定または実用的なチャネル推定
最大 32 個のプロセスを使用する HARQ 操作
広帯域およびサブバンドのプリコーディング
キャリア全体にまたがる単一の bandwidth part
実行速度を高める並列処理
次の図は、実装される処理チェーンを示しています。

シミュレーション パラメーターの設定
シミュレーションの長さを 10 ms のフレームの数 (NFrames) で設定します。有意なスループット結果を得るには、多数のフレームを使用します。シミュレーションを行うための SNR 点を設定します。各レイヤーの SNR はリソース エレメント (RE) ごとに定義され、すべてのアンテナにおける信号とノイズの影響が含まれます。この例で使用している SNR 定義の説明については、リンク シミュレーションで使用する SNR の定義の例を参照してください。
simParameters = struct(); % Simulation parameters structure simParameters.NFrames = 2; % Number of 10 ms frames simParameters.SNRdB = -10:2:-6; % SNR range (dB)
enableParallelism 変数は、シミュレーションを単一のワーカーで実行するか、複数のワーカーを使用して並列に実行するかを制御します。並列処理を使用するには、Parallel Computing Toolbox™ のライセンスが必要です。
simParameters.enableParallelism = true;
DisplayDiagnostics フラグを有効にしたり、pdschLink 関数にブレークポイントを設定したり、コードをプロファイリングしたりする場合は、並列処理を無効にします。
チャネル推定器の構成
logical 変数 PerfectChannelEstimator は、チャネル推定の動作を制御します。true に設定すると、シミュレーションでは完全なチャネル推定が使用されます。そうでない場合、実用的なチャネル推定のために PDSCH DM-RS が使用されます。
simParameters.PerfectChannelEstimator = false;
シミュレーション診断の構成
この例では、実行時にシミュレーションの進行を監視するのに役立つ 2 つの診断フラグが提供されています。両方のフラグは、enableParallelism が false に設定されている場合にのみ適用されます。
DisplaySimulationInformation 変数は、各サブフレームの HARQ プロセス ID などのシミュレーション情報の表示を制御します。CRC エラーの場合、冗長バージョン (RV) シーケンスのインデックスの値も表示されます。
simParameters.DisplaySimulationInformation = true;
DisplayDiagnostics フラグを使用すると、レイヤーごとに EVM をプロットできます。このプロットは、イコライズ後の受信信号の品質を監視します。レイヤーごとの EVM の Figure は以下を表示します。
スロット単位でのレイヤーごとの EVM。これは時間とともに変化する EVM を表示します。
リソース ブロック単位でのレイヤーごとの EVM。これは EVM の周波数を示します。
simParameters.DisplayDiagnostics = false;
キャリア、PDSCH、および伝播チャネルの構成
% Set carrier parameters simParameters.Carrier = pre6GCarrierConfig; % Carrier resource grid configuration simParameters.Carrier.NSizeGrid = 330; % Bandwidth in number of resource blocks simParameters.Carrier.SubcarrierSpacing = 120; % Subcarrier spacing % Set PDSCH parameters simParameters.PDSCH = pre6GPDSCHConfig; % PDSCH definition for all PDSCH transmissions in the BLER simulation % Define PDSCH time-frequency resource allocation per slot to be full grid (single full grid BWP) and number of layers simParameters.PDSCH.PRBSet = 0:simParameters.Carrier.NSizeGrid-1; % PDSCH PRB allocation simParameters.PDSCH.SymbolAllocation = [0,simParameters.Carrier.SymbolsPerSlot]; % Starting symbol and number of symbols of each PDSCH allocation simParameters.PDSCH.NumLayers = 1; % Number of PDSCH transmission layers % This structure is to hold additional simulation parameters for the DL-SCH and PDSCH simParameters.PDSCHExtension = struct(); % Define codeword modulation and target coding rate % The number of codewords is directly dependent on the number of layers so ensure that layers are set first before getting the codeword number if simParameters.PDSCH.NumCodewords > 1 % Multicodeword transmission (when number of layers is > 4) simParameters.PDSCH.Modulation = {'16QAM','16QAM'}; % 'QPSK', '16QAM', '64QAM', '256QAM', '1024QAM', '4096QAM', 'Custom' simParameters.PDSCHExtension.TargetCodeRate = [490 490]/1024; % Code rate used to calculate transport block sizes else simParameters.PDSCH.Modulation = '16QAM'; % 'QPSK', '16QAM', '64QAM', '256QAM', '1024QAM', '4096QAM', 'Custom' simParameters.PDSCHExtension.TargetCodeRate = 490/1024; % Code rate used to calculate transport block sizes end % Disable PT-RS simParameters.PDSCH.EnablePTRS = false; % PDSCH PRB bundling (TS 38.214 Section 5.1.2.3) simParameters.PDSCHExtension.PRGBundleSize = []; % Any positive power of 2, or [] to signify "wideband" % HARQ process parameters simParameters.PDSCHExtension.NHARQProcesses = 16; % Number of parallel HARQ processes to use simParameters.PDSCHExtension.EnableHARQ = true; % Enable retransmissions for each process, using RV sequence [0,2,3,1] % LDPC decoder parameters simParameters.PDSCHExtension.LDPCDecodingAlgorithm = 'Normalized min-sum'; simParameters.PDSCHExtension.MaximumLDPCIterationCount = 20; % Number of antennas simParameters.NTxAnts = 32; % Number of antennas (1,2,4,8,16,32,64,128,256,512,1024) >= NumLayers simParameters.NRxAnts = 2; % Define the general CDL propagation channel parameters simParameters.DelayProfile = 'CDL-A'; simParameters.DelaySpread = 10e-9; simParameters.MaximumDopplerShift = 70; % Cross-check the PDSCH configuration parameters against the channel geometry validateParameters(simParameters);
並列実行の構成
並列実行を有効にしている場合は、並列クラスターを構成します。この例の並列実行モデルの詳細な説明については、Accelerate Link-Level Simulations with Parallel Processingの例を参照してください。
if (simParameters.enableParallelism && canUseParallelPool) pool = gcp; % create parallel pool, requires PCT numWorkers = pool.NumWorkers; maxNumWorkers = pool.NumWorkers; else if (~canUseParallelPool && simParameters.enableParallelism) warning("Ignoring the value of enableParallelism ("+simParameters.enableParallelism+")"+newline+ ... "The simulation will run using serial execution."+newline+"You need a license of Parallel Computing Toolbox to use parallelism.") end numWorkers = 1; % No parallelism maxNumWorkers = 0; % Used to convert the parfor-loop into a for-loop end
各ワーカーに対して乱数ストリームを何度も不必要にコピーすることを避けるために、一定の乱数ストリームを作成します。サブストリームは、各ワーカーに対して互いに独立した乱数ストリームを提供します。
str1 = RandStream('Threefry','Seed',1); constantStream = parallel.pool.Constant(str1);
ワーカーごとのスロット数を計算します。使用可能なすべてのワーカーを最大限に活用するため、例では、NFrames で指定した値よりも多くのスロットがシミュレーションされる場合があります。
numSlotsPerWorker = ceil((simParameters.NFrames*simParameters.Carrier.SlotsPerFrame)/numWorkers); disp("Parallelism: "+simParameters.enableParallelism) disp("Number of workers: "+numWorkers) disp("Number of slots per worker: "+numSlotsPerWorker) disp("Total number of frames: "+(numSlotsPerWorker*numWorkers)/simParameters.Carrier.SlotsPerFrame)
PDSCH リンクレベル シミュレーション
このセクションでは、 個の PDSCH リンクを並列にシミュレーションします。ここで、 は使用可能なワーカーの数です。各ワーカーはすべての SNR 点をシミュレーションします。parfor ループでは、構文 parfor (pforIdx = 1:numWorkers,maxNumWorkers) が使用されます。コードをデバッグするには、maxNumWorkers を 0 に設定して、シミュレーションを並列実行から逐次的実行に切り替えます。maxNumWorkers の値に関係なく、parfor ループの本体にブレークポイントを設定することはできません。ただし、maxNumWorkers = 0 の場合は、parfor ループの本体から呼び出される関数内にブレークポイントを設定できます。
% Results storage result = struct(NumSlots=0,NumBits=0,NumCorrectBits=0); results = repmat(result,numWorkers,numel(simParameters.SNRdB)); % Parallel processing, worker parfor-loop parfor (pforIdx = 1:numWorkers,maxNumWorkers) % Set random streams to ensure repeatability % Use substreams in the generator so each worker uses mutually independent streams stream = constantStream.Value; % Extract the stream from the Constant stream.Substream = pforIdx; % Set substream value = parfor index RandStream.setGlobalStream(stream); % Set global stream per worker % Per worker processing results(pforIdx,:) = pdschLink(simParameters,numSlotsPerWorker,pforIdx); end
結果
測定したスループットを表示します。これは、使用可能なリソースを所与とするリンクの最大スループットがデータ伝送に占める割合として計算されます。
[throughput,throughputMbps,summaryTable] = processResults(simParameters,results); disp(summaryTable) figure; plot(simParameters.SNRdB,throughput,'o-.') xlabel('SNR (dB)'); ylabel('Throughput (%)'); grid on; title(sprintf('%s (%dx%d) / NRB=%d / SCS=%dkHz', ... simParameters.DelayProfile,simParameters.NTxAnts,simParameters.NRxAnts, ... simParameters.Carrier.NSizeGrid,simParameters.Carrier.SubcarrierSpacing));
ローカル関数
function [throughput,throughputMbps,summaryTable] = processResults(simParameters,results) % Process multi-worker and multi-SNR results numSNRPts = size(results,2); totalSimulatedSlots = sum(reshape([results(:).NumSlots].',[],numSNRPts),1); totalSimulatedBits = sum(reshape([results(:).NumBits].',[],numSNRPts),1); totalCorrectBits = sum(reshape([results(:).NumCorrectBits].',[],numSNRPts),1); totalSimulatedFrames = totalSimulatedSlots/simParameters.Carrier.SlotsPerFrame; % Throughput results calculation throughput = 100*(totalCorrectBits./totalSimulatedBits); throughputMbps = 1e-6*totalCorrectBits/(simParameters.NFrames*10e-3); summaryTable = table(simParameters.SNRdB.',totalSimulatedBits.',totalSimulatedSlots.', ... totalSimulatedFrames.',throughput.',throughputMbps.'); summaryTable.Properties.VariableNames = ["SNR" "Simulated bits" "Number of Tr Blocks" ... "Number of frames" "Throughput (%)" "Throughput (Mbps)"]; end function resultsPerWorker = pdschLink(simParameters,totalNumSlots,workerId) % PDSCH link simulation % Take copies of channel-level parameters to simplify subsequent parameter referencing carrier = simParameters.Carrier; pdsch = simParameters.PDSCH; pdschextra = simParameters.PDSCHExtension; % Results storage result = struct(NumSlots=0,NumBits=0,NumCorrectBits=0); resultsPerWorker = repmat(result,1,numel(simParameters.SNRdB)); % Create DL-SCH encoder/decoder [encodeDLSCH,decodeDLSCH] = dlschEncoderDecoder(pdschextra); % OFDM waveform information ofdmInfo = hpre6GOFDMInfo(carrier); % Create CDL channel channel = nrCDLChannel; channel = hArrayGeometry(channel,simParameters.NTxAnts,simParameters.NRxAnts); nTxAnts = prod(channel.TransmitAntennaArray.Size); nRxAnts = prod(channel.ReceiveAntennaArray.Size); channel.DelayProfile = simParameters.DelayProfile; channel.DelaySpread = simParameters.DelaySpread; channel.MaximumDopplerShift = simParameters.MaximumDopplerShift; channel.SampleRate = ofdmInfo.SampleRate; % New seed for each worker, but the same for each SNR point so they all % experience the same channel realization. channel.Seed = randi([0 2^32-1]); chInfo = info(channel); maxChDelay = chInfo.MaximumChannelDelay; % Set up redundancy version (RV) sequence for all HARQ processes if simParameters.PDSCHExtension.EnableHARQ rvSeq = [0 2 3 1]; else % HARQ disabled - single transmission with RV=0, no retransmissions rvSeq = 0; end % for all SNR points for snrIdx = 1:length(simParameters.SNRdB) % Noise power calculation SNR = 10^(simParameters.SNRdB(snrIdx)/10); % Calculate linear noise gain N0 = 1/sqrt(double(ofdmInfo.Nfft)*SNR*nRxAnts); % Get noise power per resource element (RE) from noise power in the % time domain (N0^2) nPowerPerRE = N0^2*ofdmInfo.Nfft; % Reset the channel and DL-SCH decoder at the start of each SNR simulation reset(channel); reset(decodeDLSCH); % Specify the fixed order in which we cycle through the HARQ process IDs harqSequence = 0:pdschextra.NHARQProcesses-1; % Initialize the state of all HARQ processes harqEntity = HARQEntity(harqSequence,rvSeq,pdsch.NumCodewords); % Obtain a precoding matrix (wtx) to be used in the transmission of the % first transport block estChannelGrid = getInitialChannelEstimate(carrier,nTxAnts,channel); wtx = hSVDPrecoders(carrier,pdsch,estChannelGrid,pdschextra.PRGBundleSize); % Progress when parallel processing is enabled if (simParameters.enableParallelism && workerId==1) fprintf('Simulating SNR=%.2f dB, progress: \n0%% \n',simParameters.SNRdB(snrIdx)) end % Process all the slots per worker for nSlot = 0:totalNumSlots-1 % New slot number carrier.NSlot = nSlot; % Calculate the transport block sizes for the transmission in the slot [pdschIndices,pdschIndicesInfo] = hpre6GPDSCHIndices(carrier,pdsch); trBlkSizes = hpre6GTBS(pdsch,pdschextra.TargetCodeRate); % Generate new data and DL-SCH encode codedTrBlocks = getDLSCHCodeword(encodeDLSCH,trBlkSizes,pdschIndicesInfo.Qm,pdsch.NumLayers,pdschIndicesInfo.G,harqEntity); % PDSCH modulation of codeword(s), MIMO precoding and OFDM [txWaveform,pdschSymbols]= hPDSCHTransmit(carrier,pdsch,codedTrBlocks,wtx); % Pass data through channel model txWaveform = [txWaveform; zeros(maxChDelay,size(txWaveform,2))]; [rxWaveform,pathGains,sampleTimes] = channel(txWaveform); % Add noise noise = N0*randn(size(rxWaveform),"like",rxWaveform); rxWaveform = rxWaveform + noise; % Synchronization, OFDM demodulation, channel estimation, % equalization, and PDSCH demodulation pathFilters = getPathFilters(channel); perfEstConfig = perfectEstimatorConfig(pathGains,sampleTimes,pathFilters,nPowerPerRE,simParameters.PerfectChannelEstimator); [dlschLLRs,wtx,pdschEq] = hPDSCHReceive(carrier,pdsch,pdschextra,rxWaveform,wtx,perfEstConfig); % Display EVM per layer, per slot and per RB if (simParameters.DisplayDiagnostics) gridSize = [carrier.NSizeGrid*12 carrier.SymbolsPerSlot nTxAnts]; plotLayerEVM(totalNumSlots,nSlot,pdsch,gridSize,pdschIndices,pdschSymbols,pdschEq,simParameters.SNRdB(snrIdx)); end % Decode the DL-SCH transport channel % If new data because of previous RV sequence time out then flush decoder soft buffer explicitly for cwIdx = 1:pdsch.NumCodewords if harqEntity.NewData(cwIdx) && harqEntity.SequenceTimeout(cwIdx) resetSoftBuffer(decodeDLSCH,cwIdx-1,harqEntity.HARQProcessID); end end decodeDLSCH.TransportBlockLength = trBlkSizes; [~,blkerr] = decodeDLSCH(dlschLLRs,pdschIndicesInfo.Qm,pdsch.NumLayers,harqEntity.RedundancyVersion,harqEntity.HARQProcessID); % Update current process with CRC error and advance to next process procstatus = updateAndAdvance(harqEntity,blkerr,trBlkSizes,pdschIndicesInfo.G); if (simParameters.DisplaySimulationInformation && ~simParameters.enableParallelism) fprintf('(%3.2f%%), SNR=%.2f dB, NSlot=%d, %s\n',100*(nSlot+1)/totalNumSlots,simParameters.SNRdB(snrIdx),nSlot,procstatus); elseif (simParameters.enableParallelism && workerId==1 && ~mod((nSlot+1),ceil((10*totalNumSlots)/100))) % Progress when parallel processing is enabled % Update progress with approximately 10% steps fprintf('%3.2f%% \n',100*(nSlot+1)/totalNumSlots) end % SNR point simulation results resultsPerWorker(snrIdx).NumSlots = resultsPerWorker(snrIdx).NumSlots+1; resultsPerWorker(snrIdx).NumBits = resultsPerWorker(snrIdx).NumBits+sum(trBlkSizes); resultsPerWorker(snrIdx).NumCorrectBits = resultsPerWorker(snrIdx).NumCorrectBits+sum(~blkerr .* trBlkSizes); end % for nSlot = 0:totalNumSlots end % for all SNR points end function [encodeDLSCH,decodeDLSCH] = dlschEncoderDecoder(PDSCHExtension) % Create and parameterize the DL-SCH encoder and decoder objects % Create DL-SCH encoder object encodeDLSCH = hpre6GDLSCH; encodeDLSCH.MultipleHARQProcesses = true; encodeDLSCH.TargetCodeRate = PDSCHExtension.TargetCodeRate; % Create DL-SCH decoder object decodeDLSCH = hpre6GDLSCHDecoder; decodeDLSCH.MultipleHARQProcesses = true; decodeDLSCH.TargetCodeRate = PDSCHExtension.TargetCodeRate; decodeDLSCH.LDPCDecodingAlgorithm = PDSCHExtension.LDPCDecodingAlgorithm; decodeDLSCH.MaximumLDPCIterationCount = PDSCHExtension.MaximumLDPCIterationCount; end function codedTrBlocks = getDLSCHCodeword(encodeDLSCH,trBlkSizes,Qm,NumLayers,G,harqEntity) % Get DL-SCH codeword % HARQ processing for cwIdx = 1:length(G) % If new data for current process and codeword then create a new DL-SCH transport block if harqEntity.NewData(cwIdx) trBlk = randi([0 1],trBlkSizes(cwIdx),1); setTransportBlock(encodeDLSCH,trBlk,cwIdx-1,harqEntity.HARQProcessID); end end % Encode the DL-SCH transport blocks codedTrBlocks = encodeDLSCH(Qm,NumLayers,G,harqEntity.RedundancyVersion,harqEntity.HARQProcessID); end function perfEstInfo = perfectEstimatorConfig(pathGains,sampleTimes,pathFilters,noiseEst,perfChEst) % Perfect channel estimator configuration perfEstInfo.PathGains = pathGains; perfEstInfo.PathFilters = pathFilters; perfEstInfo.SampleTimes = sampleTimes; perfEstInfo.NoiseEstimate = noiseEst; perfEstInfo.PerfectChannelEstimator = perfChEst; end function estChannelGrid = getInitialChannelEstimate(carrier,nTxAnts,propchannel) % Obtain channel estimate before first transmission. This can be used to % obtain a precoding matrix for the first slot. ofdmInfo = hpre6GOFDMInfo(carrier); chInfo = info(propchannel); maxChDelay = chInfo.MaximumChannelDelay; % Temporary waveform (only needed for the sizes) tmpWaveform = zeros((ofdmInfo.SampleRate/1000/carrier.SlotsPerSubframe)+maxChDelay,nTxAnts,"single"); % Filter through channel [~,pathGains,sampleTimes] = propchannel(tmpWaveform); % Perfect timing synch pathFilters = getPathFilters(propchannel); offset = nrPerfectTimingEstimate(pathGains,pathFilters); % Perfect channel estimate estChannelGrid = hpre6GPerfectChannelEstimate(carrier,pathGains,pathFilters,offset,sampleTimes); end function plotLayerEVM(NSlots,nslot,pdsch,siz,pdschIndices,pdschSymbols,pdschEq,SNRdB) % Plot EVM information persistent slotEVM; persistent rbEVM; persistent evmPerSlot; if (nslot==0) slotEVM = comm.EVM; rbEVM = comm.EVM; evmPerSlot = NaN(NSlots,pdsch.NumLayers); figure; end evmPerSlot(nslot+1,:) = slotEVM(pdschSymbols,pdschEq); subplot(2,1,1); plot(0:(NSlots-1),evmPerSlot,'o-'); xlabel("Slot number"); ylabel("EVM (%)"); legend("layer " + (1:pdsch.NumLayers),'Location','EastOutside'); title("EVM per layer per slot. SNR = "+SNRdB+" dB"); subplot(2,1,2); [k,~,p] = ind2sub(siz,pdschIndices); rbsubs = floor((k-1) / 12); NRB = siz(1) / 12; evmPerRB = NaN(NRB,pdsch.NumLayers); for nu = 1:pdsch.NumLayers for rb = unique(rbsubs).' this = (rbsubs==rb & p==nu); evmPerRB(rb+1,nu) = rbEVM(pdschSymbols(this),pdschEq(this)); end end plot(0:(NRB-1),evmPerRB,'x-'); xlabel("Resource block"); ylabel("EVM (%)"); legend("layer " + (1:pdsch.NumLayers),'Location','EastOutside'); title("EVM per layer per resource block, slot #"+num2str(nslot)+". SNR = "+SNRdB+" dB"); drawnow; end function validateParameters(simParameters) % Validate the number of layers, relative to the antenna geometry numlayers = simParameters.PDSCH.NumLayers; ntxants = simParameters.NTxAnts; nrxants = simParameters.NRxAnts; antennaDescription = sprintf('min(NTxAnts,NRxAnts) = min(%d,%d) = %d',ntxants,nrxants,min(ntxants,nrxants)); if numlayers > min(ntxants,nrxants) error('The number of layers (%d) must satisfy NumLayers <= %s', ... numlayers,antennaDescription); end % Display a warning if the maximum possible rank of the channel equals % the number of layers if (numlayers > 2) && (numlayers == min(ntxants,nrxants)) warning(['The maximum possible rank of the channel, given by %s, is equal to NumLayers (%d).' ... ' This may result in a decoding failure under some channel conditions.' ... ' Try decreasing the number of layers or increasing the channel rank' ... ' (use more transmit or receive antennas).'],antennaDescription,numlayers); %#ok<SPWRN> end end
参考
pre6GCarrierConfig | pre6GPDSCHConfig