23
23
% DMRSAdditionalPosition - Maximum number of DMRS additional positions (0, 1, 2, 3).
24
24
% DMRSLength - Number of consecutive front-loaded DMRS OFDM symbols (1, 2).
25
25
% DMRSConfigurationType - DMRS configuration type (1, 2).
26
- % testLabel - Test label ('dmrs_creation' or 'ch_estimation').
27
26
%
28
27
% srsPUSCHdmrsUnittest Methods (TestTags = {'testvector'}):
29
28
%
97
96
98
97
% DMRS configuration type (1, 2).
99
98
DMRSConfigurationType = {1 , 2 }
100
-
101
- % Test label ('dmrs_creation' or 'ch_estimation').
102
- % 'dmrs_creation' tests only check that the DM-RS pilots are generated correctly
103
- % and placed in the correct location in the resource grid.
104
- % 'ch_estimation' also check that the channel is estimated correctly.
105
- testLabel = {' dmrs_creation' , ' ch_estimation' }
106
99
end
107
100
108
101
methods (Access = protected )
@@ -117,14 +110,9 @@ function addTestIncludesToHeaderFile(~, fileID)
117
110
118
111
function addTestDefinitionToHeaderFile(~, fileID )
119
112
% addTestDetailsToHeaderFile Adds details (e.g., type/variable declarations) to the test header file.
120
- fprintf(fileID , ' enum class test_label {dmrs_creation, ch_estimation};\n\n ' );
121
113
fprintf(fileID , ' struct test_case_t {\n ' );
122
- fprintf(fileID , ' test_label label;\n ' );
123
114
fprintf(fileID , ' dmrs_pusch_estimator::configuration config;\n ' );
124
- fprintf(fileID , ' float est_noise_var;\n ' );
125
- fprintf(fileID , ' float est_rsrp;\n ' );
126
115
fprintf(fileID , ' file_vector<resource_grid_reader_spy::expected_entry_t> rx_symbols;\n ' );
127
- fprintf(fileID , ' file_vector<resource_grid_reader_spy::expected_entry_t> ch_estimates;\n ' );
128
116
fprintf(fileID , ' };\n ' );
129
117
end
130
118
@@ -136,26 +124,21 @@ function initializeClassImpl(obj)
136
124
methods (Test , TestTags = {' testvector' })
137
125
function testvectorGenerationCases(testCase , numerology , NumLayers , ...
138
126
DMRSTypeAPosition , DMRSAdditionalPosition , DMRSLength , ...
139
- DMRSConfigurationType , testLabel )
140
- % testvectorGenerationCases Generates a test vector for the given numerology,
141
- % NumLayers, DMRSTypeAPosition, DMRSAdditionalPosition, DMRSLength,
142
- % DMRSConfigurationType and testLabel. NCellID, NSlot and PRB are randomly generated.
127
+ DMRSConfigurationType )
128
+ % testvectorGenerationCases Generates a test vector for the given
129
+ % numerology, NumLayers, DMRSTypeAPosition,
130
+ % DMRSAdditionalPosition, DMRSLength and DMRSConfigurationType.
131
+ % NCellID, NSlot and PRB are randomly generated.
143
132
144
133
import srsTest .helpers .cellarray2str
145
134
import srsLib.phy.upper.signal_processors.srsPUSCHdmrs
146
- import srsLib.phy.upper.signal_processors.srsChannelEstimator
147
- import srsLib .ran .utils .scs2cps
148
- import srsTest .helpers .approxbf16
149
- import srsTest .helpers .cellarray2str
150
135
import srsTest .helpers .writeResourceGridEntryFile
151
136
import srsTest .helpers .symbolAllocationMask2string
152
137
import srsTest .helpers .RBallocationMask2string
153
138
154
139
% Skip those invalid configuration cases.
155
140
isDMRSLengthOK = (DMRSLength == 1 || DMRSAdditionalPosition < 2 );
156
- isChEstimationOK = strcmp(testLabel , ' dmrs_creation' ) || (NumLayers == 1 ) ...
157
- || ((NumLayers == 2 ) && (DMRSConfigurationType == 1 ) && (DMRSLength == 1 ));
158
- if ~(isDMRSLengthOK && isChEstimationOK )
141
+ if ~isDMRSLengthOK
159
142
return ;
160
143
end
161
144
@@ -246,60 +229,19 @@ function testvectorGenerationCases(testCase, numerology, NumLayers, ...
246
229
% If 'dmrs-creation' test, write each complex symbol and their
247
230
% associated indices into a binary file, and an empty channel
248
231
% coefficients file.
249
- if strcmp(testLabel , ' dmrs_creation' )
250
- if NumLayers == 4
251
- % In creation tests, we assume layer n is received by port n only. Therefore we need to add
252
- % zeros in the REs where DM-RS from other layers would be. Note that this is not needed when
253
- % NumLayers == 2 since the first two layers share DM-RS resources.
254
- DMRSsymbols = [DMRSsymbols zeros(size(DMRSsymbols ))];
255
- symbolIndices = [symbolIndices ; [symbolIndices(: , 1 : 2 ) symbolIndices([(end / 2 + 1 ): end , 1 : end / 2 ], 3 )]];
256
- end
257
- testCase .saveDataFile(' _test_output' , testID , ...
258
- @writeResourceGridEntryFile , DMRSsymbols * amplitude , symbolIndices );
259
- testCase .saveDataFile(' _ch_estimates' , testID , ...
260
- @writeResourceGridEntryFile , [], uint32 .empty(0 ,3 ));
261
- estRSRP = 0 ;
262
- estNoiseVar = 0 ;
263
- PUSCHports = 0 : (NumLayers - 1 );
264
- else
265
- PUSCHports = 0 ;
266
-
267
- channel = createChannel(carrier , NumLayers );
268
-
269
- sizeRG = [nSizeGrid * 12 , 14 ];
270
- symbolIndicesLinear = sub2ind([sizeRG , NumLayers ], symbolIndices(: , 1 ) + 1 , ...
271
- symbolIndices(: , 2 ) + 1 , symbolIndices(: , 3 ) + 1 );
272
- symbolIndicesLinear = reshape(symbolIndicesLinear , [], NumLayers );
273
- receivedRG = channel(: , : , 1 );
274
- receivedRG(symbolIndicesLinear(: , 1 )) = receivedRG(symbolIndicesLinear(: , 1 )) ...
275
- .* DMRSsymbols(: , 1 ) * amplitude ;
276
- for iLayer = 2 : NumLayers
277
- receivedRG(symbolIndicesLinear(: , 1 )) = receivedRG(symbolIndicesLinear(: , 1 )) ...
278
- + channel(symbolIndicesLinear(: , iLayer )) .* DMRSsymbols(: , iLayer ) * amplitude ;
279
- end
280
- noiseVar = 0.1 ; % 10 dB
281
- noiseRG = (randn(sizeRG ) + 1j * randn(sizeRG )) * sqrt(noiseVar / 2 );
282
- receivedRG = receivedRG + noiseRG ;
283
-
284
- hop = configureHop();
285
- % Empty second hop.
286
- hop2.DMRSsymbols = [];
287
- nOFDMSymbols = sum(hop .DMRSsymbols );
288
- pilots = reshape(DMRSsymbols , [], nOFDMSymbols , NumLayers );
289
- cfg.scs = subcarrierSpacing * 1000 ;
290
- cfg.CyclicPrefixDurations = scs2cps(subcarrierSpacing );
291
- receivedRG = approxbf16(receivedRG );
292
- [estChannel , estNoiseVar , estRSRP ] = srsChannelEstimator(receivedRG , ...
293
- pilots , amplitude , hop , hop2 , cfg );
294
-
295
- % Write simulation data.
296
- symbolIndicesMask = (symbolIndices(: , 3 ) == 0 );
297
- testCase .saveDataFile(' _test_output' , testID , ...
298
- @writeResourceGridEntryFile , receivedRG(symbolIndicesLinear(symbolIndicesMask )), symbolIndices(symbolIndicesMask , : ));
299
- [subcarriers , syms , vals ] = find(estChannel );
300
- testCase .saveDataFile(' _ch_estimates' , testID , ...
301
- @writeResourceGridEntryFile , approxbf16(vals ), [subcarriers - 1 , mod(syms - 1 , 14 ), floor((syms - 1 ) / 14 )]);
232
+ if NumLayers == 4
233
+ % We assume layer n is received by port n only. Therefore
234
+ % we need to add zeros in the REs where DM-RS from other
235
+ % layers would be. Note that this is not needed when
236
+ % NumLayers == 2 since the first two layers share DM-RS
237
+ % resources.
238
+ DMRSsymbols = [DMRSsymbols zeros(size(DMRSsymbols ))];
239
+ symbolIndices = [symbolIndices ; [symbolIndices(: , 1 : 2 ) ...
240
+ symbolIndices([(end / 2 + 1 ): end , 1 : end / 2 ], 3 )]];
302
241
end
242
+ testCase .saveDataFile(' _test_input' , testID , ...
243
+ @writeResourceGridEntryFile , DMRSsymbols * amplitude , symbolIndices );
244
+ PUSCHports = 0 : (NumLayers - 1 );
303
245
304
246
% Generate a 'slot_point' configuration string.
305
247
slotPointConfig = cellarray2str({numerology , nFrame , ...
@@ -337,7 +279,6 @@ function testvectorGenerationCases(testCase, numerology, NumLayers, ...
337
279
' )' ];
338
280
end
339
281
340
-
341
282
% Prepare DMRS configuration cell
342
283
dmrsConfigCell = { ...
343
284
slotPointConfig , ... % slot
@@ -351,54 +292,12 @@ function testvectorGenerationCases(testCase, numerology, NumLayers, ...
351
292
{PUSCHports }, ... % rx_ports
352
293
};
353
294
354
- testCell = {[' test_label::' testLabel ], dmrsConfigCell , estNoiseVar , estRSRP };
355
-
356
295
% generate the test case entry
357
- testCaseString = testCase .testCaseToString(testID , testCell , ...
358
- false , ' _test_output ' , ' _ch_estimates ' );
296
+ testCaseString = testCase .testCaseToString(testID , dmrsConfigCell , ...
297
+ true , ' _test_input ' );
359
298
360
299
% add the test to the file header
361
300
testCase .addTestToHeaderFile(testCase .headerFileID , testCaseString );
362
-
363
- % Nested functions
364
- % %%%%%%%%%%%%%%%%%%%%%%%%%%
365
- function hop_ = configureHop
366
- ofdmSymIndices = unique(symbolIndices(: , 2 ) + 1 );
367
- hop_.DMRSsymbols = false(14 , 1 );
368
- hop_ .DMRSsymbols(ofdmSymIndices ) = true ;
369
- hop_.DMRSREmask = false(12 , 1 );
370
- if DMRSConfigurationType == 1
371
- hop_ .DMRSREmask(1 : 2 : end ) = true ;
372
- else
373
- hop_ .DMRSREmask([1 , 2 , 7 , 8 ]) = true ;
374
- end
375
- hop_.PRBstart = PRBstart ;
376
- hop_.nPRBs = length(PRBSet );
377
- hop_.maskPRBs = false(nSizeGrid , 1 );
378
- hop_ .maskPRBs(PRBSet + 1 ) = true ;
379
- hop_.startSymbol = symbolAllocation(1 );
380
- hop_.nAllocatedSymbols = symbolAllocation(2 );
381
- hop_.CHsymbols = false(14 , 1 );
382
- hop_ .CHsymbols((1 : symbolAllocation(2 )) + symbolAllocation(1 )) = true ;
383
- end
384
301
end % of function testvectorGenerationCases
385
302
end % of methods (Test, TestTags = {'testvector'})
386
303
end % of classdef srsPUSCHdmrsUnittest
387
-
388
- function channel = createChannel(carrier , nLayers )
389
- % Generates the frequency-response of single-tap channel that is consistent with
390
- % the simulation setup.
391
- nSubcarriers = carrier .NSizeGrid * 12 ;
392
- nOFDMSymbols = 14 ;
393
- % Compute maximum delay (1/4 CP length) in number of samples.
394
- maxDelay = floor(0.7 * 0.25 * nSubcarriers );
395
-
396
- channel = complex(nan(nSubcarriers , nOFDMSymbols , nLayers ), nan(nSubcarriers , nOFDMSymbols , nLayers ));
397
- for iLayer = 1 : nLayers
398
- % Random delay and random gain.
399
- delay = randi(maxDelay );
400
- gain = randn(1 , 2 ) * [1 ; 1j ] / sqrt(2 * nLayers );
401
- channel(: , : , iLayer ) = repmat(gain * exp(-2j * pi / nSubcarriers * delay ...
402
- * (-nSubcarriers / 2 : nSubcarriers / 2 - 1 ).' ), 1 , nOFDMSymbols );
403
- end
404
- end
0 commit comments