Skip to content

Commit 38da322

Browse files
committed
v1.0.0 add nr_pusch testvectors
1 parent dc71edb commit 38da322

31 files changed

+689
-0
lines changed

tests/nr_pusch/.DS_Store

6 KB
Binary file not shown.
Lines changed: 216 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,216 @@
1+
# -*- coding:utf-8 -*-
2+
3+
import numpy as np
4+
import json
5+
6+
def read_ulsch_testvec_matfile(matfile):
7+
""" read PUSCH test vector matfile
8+
trblk_out, RM_out, layermap_out, fd_slot_data, waveform, pusch_tvcfg =
9+
read_matfile(matfile)
10+
output:
11+
trblk_out: Trblk input bits
12+
RM_out: bit seq after CRC, LDPC, rate matching
13+
layermap_out: output after scrambling, modulation, layer mapping
14+
fd_slot_data: frequency domain IQ data on all slots
15+
waveform: timedomain IQ data on all slots
16+
pusch_tvcfg: PUSCH test vector parameters
17+
"""
18+
pusch_tvcfg = {}
19+
20+
pusch_tvcfg['rv_out'] = matfile["rv_out"][0]
21+
pusch_tvcfg['mcstableidx'] = matfile["mcstableidx"][0][0]
22+
pusch_tvcfg['imcs'] = matfile["imcs"][0][0]
23+
pusch_tvcfg['scs'] = matfile["scs"][0][0]
24+
pusch_tvcfg['BW'] = matfile["BW"][0][0]
25+
pusch_tvcfg['NumLayers'] = matfile["NumLayers"][0][0]
26+
pusch_tvcfg['SymbolAllocation'] = matfile["SymbolAllocation"][0]
27+
pusch_tvcfg['TransmissionScheme'] = matfile["TransmissionScheme"][0]
28+
pusch_tvcfg['NumAntennaPorts'] = matfile["NumAntennaPorts"][0][0]
29+
pusch_tvcfg['TPMI'] = matfile["TPMI"][0][0]
30+
31+
pusch_tvcfg['EnableACK'] = matfile["EnableACK"][0][0]
32+
pusch_tvcfg['NumACKBits'] = matfile["NumACKBits"][0][0]
33+
pusch_tvcfg['BetaOffsetACK'] = matfile["BetaOffsetACK"][0][0]
34+
pusch_tvcfg['EnableCSI1'] = matfile["EnableCSI1"][0][0]
35+
pusch_tvcfg['NumCSI1Bits'] = matfile["NumCSI1Bits"][0][0]
36+
pusch_tvcfg['BetaOffsetCSI1'] = matfile["BetaOffsetCSI1"][0][0]
37+
pusch_tvcfg['EnableCSI2'] = matfile["EnableCSI2"][0][0]
38+
pusch_tvcfg['NumCSI2Bits'] = matfile["NumCSI2Bits"][0][0]
39+
pusch_tvcfg['BetaOffsetCSI2'] = matfile["BetaOffsetCSI2"][0][0]
40+
41+
pusch_tvcfg['DMRSAdditionalPosition'] = matfile["DMRSAdditionalPosition"][0][0]
42+
pusch_tvcfg['NumCDMGroupsWithoutData'] = matfile["NumCDMGroupsWithoutData"][0][0]
43+
pusch_tvcfg['Qm'] = matfile["Qm"][0][0]
44+
pusch_tvcfg['TargetCodeRateby1024'] = matfile["TargetCodeRateby1024"][0][0]
45+
pusch_tvcfg['PRBSet'] = matfile["PRBSet"][0]
46+
pusch_tvcfg['TransformPrecoding'] = matfile["TransformPrecoding"][0][0]
47+
48+
pusch_tvcfg['GroupHopping'] = matfile["GroupHopping"][0][0]
49+
pusch_tvcfg['SequenceHopping'] = matfile["SequenceHopping"][0][0]
50+
if 'SampleRate' in matfile:
51+
pusch_tvcfg['SampleRate'] = matfile["SampleRate"][0][0]
52+
else:
53+
pusch_tvcfg['SampleRate'] = 0
54+
55+
effACK_out = matfile["effACK_out"]
56+
csi1_out = matfile["csi1_out"]
57+
csi2_out = matfile["csi2_out"]
58+
trblk_out = matfile["trblk_out"][0]
59+
GACK_out = matfile["GACK_out"][0]
60+
GCSI1_out = matfile["GCSI1_out"][0]
61+
GCSI2_out = matfile["GCSI2_out"][0]
62+
GULSCH_out = matfile["GULSCH_out"][0]
63+
codedULSCH_out = matfile["codedULSCH_out"]
64+
codedACK_out = matfile["codedACK_out"]
65+
codedCSI1_out = matfile["codedCSI1_out"]
66+
codedCSI2_out = matfile["codedCSI2_out"]
67+
codeword_out = matfile["codeword_out"]
68+
69+
if 'UCIScaling' in matfile:
70+
pusch_tvcfg['UCIScaling'] = matfile["UCIScaling"][0][0]
71+
else:
72+
pusch_tvcfg['UCIScaling'] = 1
73+
74+
if 'EnableULSCH' in matfile:
75+
pusch_tvcfg['EnableULSCH'] = matfile["EnableULSCH"][0][0]
76+
else:
77+
pusch_tvcfg['EnableULSCH'] = 1
78+
79+
if 'layermap_out' in matfile:
80+
layermap_out = matfile["layermap_out"]
81+
else:
82+
layermap_out = []
83+
84+
if 'fd_slot_data' in matfile:
85+
fd_slot_data = matfile['fd_slot_data']
86+
else:
87+
fd_slot_data = []
88+
89+
if 'waveform' in matfile:
90+
waveform = matfile['waveform']
91+
else:
92+
waveform = []
93+
94+
95+
return effACK_out, csi1_out, csi2_out, trblk_out, \
96+
GACK_out, GCSI1_out, GCSI2_out, GULSCH_out, \
97+
codedULSCH_out, codedACK_out, codedCSI1_out, codedCSI2_out, codeword_out, \
98+
layermap_out, fd_slot_data, waveform, pusch_tvcfg
99+
100+
def gen_pusch_testvec_config(pusch_tvcfg):
101+
""" genrate UL carrier config, coreset, search_space and pusch config"""
102+
path = "py5gphy/nr_default_config/"
103+
104+
with open(path + "default_UL_carrier_config.json", 'r') as f:
105+
carrier_config = json.load(f)
106+
with open(path + "default_pusch_config.json", 'r') as f:
107+
pusch_config = json.load(f)
108+
109+
carrier_config['BW'] = pusch_tvcfg['BW']
110+
carrier_config['scs'] = pusch_tvcfg['scs']
111+
carrier_config['num_of_ant'] = pusch_tvcfg['NumAntennaPorts']
112+
carrier_config['maxMIMO_layers'] = pusch_tvcfg['NumLayers']
113+
carrier_config['PCI'] = 1 #fixed value
114+
115+
pusch_config['rnti'] = 1
116+
if pusch_tvcfg['mcstableidx'] == 2:
117+
pusch_config['mcs_table'] = '256QAM'
118+
pusch_config['mcs_index'] = pusch_tvcfg['imcs']
119+
pusch_config['nTpPi2BPSK'] = 0
120+
elif pusch_tvcfg['mcstableidx'] == 3:
121+
pusch_config['mcs_table'] = '64QAMLowSE'
122+
pusch_config['mcs_index'] = pusch_tvcfg['imcs']
123+
pusch_config['nTpPi2BPSK'] = 0
124+
elif pusch_tvcfg['mcstableidx'] == 4:
125+
pusch_config['mcs_table'] = 'MCStable61411'
126+
if pusch_tvcfg['imcs'] > 27:
127+
pusch_config['mcs_index'] = pusch_tvcfg['imcs'] - 28
128+
pusch_config['nTpPi2BPSK'] = 0
129+
else:
130+
pusch_config['mcs_index'] = pusch_tvcfg['imcs']
131+
pusch_config['nTpPi2BPSK'] = 1
132+
elif pusch_tvcfg['mcstableidx'] == 5:
133+
pusch_config['mcs_table'] = 'MCStable61412'
134+
if pusch_tvcfg['imcs'] > 27:
135+
pusch_config['mcs_index'] = pusch_tvcfg['imcs'] - 28
136+
pusch_config['nTpPi2BPSK'] = 0
137+
else:
138+
pusch_config['mcs_index'] = pusch_tvcfg['imcs']
139+
pusch_config['nTpPi2BPSK'] = 1
140+
else:
141+
assert 0
142+
143+
pusch_config['nTransPrecode'] = pusch_tvcfg['TransformPrecoding']
144+
if pusch_tvcfg['TransmissionScheme'] == 'nonCodebook':
145+
pusch_config['nTransmissionScheme'] = 0
146+
else:
147+
pusch_config['nTransmissionScheme'] = 1
148+
pusch_config['num_of_layers'] = pusch_tvcfg['NumLayers']
149+
pusch_config['nNrOfAntennaPorts'] = pusch_tvcfg['NumAntennaPorts']
150+
151+
pusch_config['DMRS']['dmrs_TypeA_Position'] = "pos2"
152+
pusch_config['DMRS']['nSCID'] = 0
153+
pusch_config['DMRS']['DMRSConfigType'] = 1
154+
pusch_config['DMRS']['NrOfDMRSSymbols'] = 1
155+
pusch_config['DMRS']['NumCDMGroupsWithoutData'] = pusch_tvcfg['NumCDMGroupsWithoutData']
156+
pusch_config['DMRS']['DMRSAddPos'] = pusch_tvcfg['DMRSAdditionalPosition']
157+
pusch_config['DMRS']['PUSCHMappintType'] = 'A'
158+
pusch_config['DMRS']['transformPrecodingDisabled']['NID0'] = 10
159+
pusch_config['DMRS']['transformPrecodingDisabled']['NID1'] = 20
160+
pusch_config['DMRS']['transformPrecodingEnabled']["nPuschID"] = 30
161+
if pusch_tvcfg['GroupHopping'] == 1:
162+
pusch_config['DMRS']['transformPrecodingEnabled']["groupOrSequenceHopping"] = "groupHopping"
163+
elif pusch_tvcfg['SequenceHopping'] == 1:
164+
pusch_config['DMRS']['transformPrecodingEnabled']["groupOrSequenceHopping"] = "sequenceHopping"
165+
else:
166+
pusch_config['DMRS']['transformPrecodingEnabled']["groupOrSequenceHopping"] = "neither"
167+
168+
pusch_config['VRBtoPRBMapping'] = "non-interleaved"
169+
170+
pusch_config['nPMI'] = pusch_tvcfg['TPMI']
171+
pusch_config['StartSymbolIndex'] = pusch_tvcfg['SymbolAllocation'][0]
172+
pusch_config['NrOfSymbols'] = pusch_tvcfg['SymbolAllocation'][1]
173+
174+
pusch_config['ResAlloType1']['RBStart'] = pusch_tvcfg['PRBSet'][0]
175+
pusch_config['ResAlloType1']['RBSize'] = len(pusch_tvcfg['PRBSet'])
176+
177+
pusch_config['rv'] = pusch_tvcfg['rv_out']
178+
pusch_config['nNid'] = 1
179+
pusch_config['UCIScaling'] = pusch_tvcfg['UCIScaling']
180+
pusch_config['EnableULSCH'] = pusch_tvcfg['EnableULSCH']
181+
182+
pusch_config['EnableACK'] = pusch_tvcfg['EnableACK']
183+
if pusch_config['EnableACK'] == 1:
184+
pusch_config['NumACKBits'] = pusch_tvcfg['NumACKBits']
185+
else:
186+
pusch_config['NumACKBits'] = 0
187+
#find ACK index
188+
""" 38.213 Table 9.3-1: Mapping of beta_offset values for HARQ-ACK information and the index signalled by
189+
higher layers
190+
"""
191+
acktable = [1.000,2.000,2.500,3.125,4.000,5.000,6.250,8.000,10.000,12.625, 15.875, 20.000, 31.000, 50.000, 80.000, 126.000]
192+
assert pusch_tvcfg['BetaOffsetACK'] in acktable
193+
pusch_config['I_HARQ_ACK_offset'] = acktable.index(pusch_tvcfg['BetaOffsetACK'])
194+
195+
""" 38.213 Table 9.3-1: Mapping of beta_offset values for HARQ-ACK information and the index signalled by
196+
higher layers
197+
"""
198+
csitable = [1.125,1.250,1.375,1.625,1.750,2.000,2.250,2.500,2.875,3.125,
199+
3.500, 4.000, 5.000, 6.250, 8.000, 10.000, 12.625, 15.875, 20.000]
200+
pusch_config['EnableCSI1'] = pusch_tvcfg['EnableCSI1']
201+
if pusch_config['EnableCSI1']:
202+
pusch_config['NumCSI1Bits'] = pusch_tvcfg['NumCSI1Bits']
203+
else:
204+
pusch_config['NumCSI1Bits'] = 0
205+
206+
pusch_config['I_CSI1offset'] = csitable.index(pusch_tvcfg['BetaOffsetCSI1'])
207+
208+
pusch_config['EnableCSI2'] = pusch_tvcfg['EnableCSI2']
209+
if pusch_config['EnableCSI2']:
210+
pusch_config['NumCSI2Bits'] = pusch_tvcfg['NumCSI2Bits']
211+
else:
212+
pusch_config['NumCSI2Bits'] = 0
213+
214+
pusch_config['I_CSI2offset'] = csitable.index(pusch_tvcfg['BetaOffsetCSI2'])
215+
216+
return carrier_config, pusch_config

tests/nr_pusch/test_nr_pusch.py

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
# -*- coding: utf-8 -*-
2+
import pytest
3+
from scipy import io
4+
import os
5+
import numpy as np
6+
import math
7+
from zipfile import ZipFile
8+
9+
from tests.nr_pusch import nr_pusch_testvectors
10+
from py5gphy.nr_pusch import nr_pusch_dmrs
11+
from py5gphy.nr_pusch import nr_pusch
12+
from py5gphy.common import nr_slot
13+
14+
def get_testvectors():
15+
path = "tests/nr_pusch/testvectors_pusch"
16+
if len(os.listdir(path)) < 100: #desn't unzip testvectors
17+
zipfile_lists = []
18+
for f in os.listdir(path):
19+
if f.endswith(".zip"):
20+
zipfile_lists.append(path + '/' + f)
21+
22+
for zipfile in zipfile_lists:
23+
zObject = ZipFile(zipfile, 'r')
24+
zObject.extractall(path)
25+
26+
file_lists = []
27+
for f in os.listdir(path):
28+
if f.endswith(".mat") and f.startswith("nrPUSCH_testvec"):
29+
file_lists.append(path + '/' + f)
30+
31+
return file_lists
32+
33+
@pytest.mark.parametrize('filename', get_testvectors())
34+
def test_nr_pusch(filename):
35+
""" the main pupose this this test is to test PUSCH scrambling, modulation and resurce mapping
36+
37+
"""
38+
#read data
39+
matfile = io.loadmat(filename)
40+
effACK_out, csi1_out, csi2_out, trblk_out, \
41+
GACK_out, GCSI1_out, GCSI2_out, GULSCH_out, \
42+
codedULSCH_out, codedACK_out, codedCSI1_out, codedCSI2_out, codeword_out, \
43+
layermap_out, fd_slot_data_ref, waveform, pusch_tvcfg = \
44+
nr_pusch_testvectors.read_ulsch_testvec_matfile(matfile)
45+
46+
carrier_config, pusch_config = nr_pusch_testvectors.gen_pusch_testvec_config(pusch_tvcfg)
47+
pusch_config["data_source"] = [1,0,0,1]
48+
NumCDMGroupsWithoutData = pusch_config['DMRS']["NumCDMGroupsWithoutData"]
49+
#following to 38.214 Table 6.2.2-1: The ratio of PUSCH EPRE to DM-RS EPRE, get PUSCH DMRS scaling factor
50+
#matlab toolbox didn;t select DMRS_scaling, need compensation
51+
if NumCDMGroupsWithoutData == 1:
52+
DMRS_scaling = 1 #0db EPRE ratio
53+
else:
54+
DMRS_scaling = 10 ** (-3/20) #-3db EPRE ratio
55+
56+
BW = carrier_config['BW']
57+
scs = carrier_config['scs']
58+
if scs == 30:
59+
numofslot = 4
60+
else:
61+
numofslot = 2
62+
carrier_prbsize = nr_slot.get_carrier_prb_size(scs, BW)
63+
slot_size = carrier_prbsize*12*14
64+
65+
nrpusch = nr_pusch.NrPUSCH(carrier_config,pusch_config)
66+
67+
for m in range(numofslot):
68+
slot = m
69+
70+
num_of_ant = nrpusch.carrier_config["num_of_ant"]
71+
carrier_prb_size = nrpusch.carrier_prb_size
72+
fd_slot_data, RE_usage_inslot = nr_slot.init_fd_slot(num_of_ant, carrier_prb_size)
73+
74+
#pdsch processing
75+
fd_slot_data, RE_usage_inslot = nrpusch.process(fd_slot_data,RE_usage_inslot,slot)
76+
77+
sel_ref_fdslot_data = fd_slot_data_ref[:,m*carrier_prb_size*12*14:(m+1)*carrier_prb_size*12*14]
78+
for sym in range(14):
79+
sel_sym = sel_ref_fdslot_data[:,sym*carrier_prb_size*12:(sym+1)*carrier_prb_size*12]
80+
sel_sym[:,RE_usage_inslot[0,sym*carrier_prb_size*12:(sym+1)*carrier_prb_size*12]==nr_slot.get_REusage_value('PUSCH-DMRS')] *= DMRS_scaling
81+
82+
assert np.allclose(fd_slot_data, sel_ref_fdslot_data, atol=1e-5)
83+
print("pass comparison for slot {}".format(m))

tests/nr_pusch/test_nr_pusch_dmrs.py

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
# -*- coding: utf-8 -*-
2+
import pytest
3+
from scipy import io
4+
import os
5+
import numpy as np
6+
import math
7+
8+
from tests.nr_pusch import nr_pusch_testvectors
9+
from py5gphy.nr_pusch import nr_pusch_dmrs
10+
from py5gphy.nr_pusch import nr_pusch
11+
from py5gphy.common import nr_slot
12+
from py5gphy.nr_pusch import nr_pusch_precoding
13+
14+
def get_testvectors():
15+
path = "tests/nr_pusch/testvectors_pusch"
16+
if len(os.listdir(path)) < 100: #desn't unzip testvectors
17+
zipfile_lists = []
18+
for f in os.listdir(path):
19+
if f.endswith(".zip"):
20+
zipfile_lists.append(path + '/' + f)
21+
22+
for zipfile in zipfile_lists:
23+
zObject = ZipFile(zipfile, 'r')
24+
zObject.extractall(path)
25+
26+
file_lists = []
27+
for f in os.listdir(path):
28+
if f.endswith(".mat") and f.startswith("nrPUSCH_testvec"):
29+
file_lists.append(path + '/' + f)
30+
31+
return file_lists
32+
33+
@pytest.mark.parametrize('filename', get_testvectors())
34+
def test_nr_ulsch_dmrs(filename):
35+
"""
36+
"""
37+
#read data
38+
matfile = io.loadmat(filename)
39+
effACK_out, csi1_out, csi2_out, trblk_out, \
40+
GACK_out, GCSI1_out, GCSI2_out, GULSCH_out, \
41+
codedULSCH_out, codedACK_out, codedCSI1_out, codedCSI2_out, codeword_out, \
42+
layermap_out, fd_slot_data_ref, waveform, pusch_tvcfg = \
43+
nr_pusch_testvectors.read_ulsch_testvec_matfile(matfile)
44+
45+
carrier_config, pusch_config = nr_pusch_testvectors.gen_pusch_testvec_config(pusch_tvcfg)
46+
47+
scs = carrier_config['scs']
48+
BW = carrier_config['BW']
49+
num_of_layers = pusch_config['num_of_layers']
50+
nNrOfAntennaPorts = pusch_config['nNrOfAntennaPorts']
51+
nPMI = pusch_config['nPMI']
52+
NumCDMGroupsWithoutData = pusch_config['DMRS']["NumCDMGroupsWithoutData"]
53+
#following to 38.214 Table 6.2.2-1: The ratio of PUSCH EPRE to DM-RS EPRE, get PUSCH DMRS scaling factor
54+
#matlab toolbox didn;t select DMRS_scaling, need compensation
55+
if NumCDMGroupsWithoutData == 1:
56+
DMRS_scaling = 1 #0db EPRE ratio
57+
else:
58+
DMRS_scaling = 10 ** (-3/20) #-3db EPRE ratio
59+
60+
carrier_prbsize = nr_slot.get_carrier_prb_size(scs, BW)
61+
62+
slot_num = fd_slot_data_ref.shape[0]
63+
for slot in range(slot_num):
64+
sel_ref_fdslot_data = fd_slot_data_ref[:,slot*carrier_prbsize*12*14:(slot+1)*carrier_prbsize*12*14]
65+
fd_slot_data, RE_usage_inslot = nr_slot.init_fd_slot(nNrOfAntennaPorts, carrier_prbsize)
66+
67+
fd_slot_data, RE_usage_inslot, DMRSinfo = nr_pusch_dmrs.process(fd_slot_data,RE_usage_inslot, pusch_config, slot)
68+
69+
for ant in range(nNrOfAntennaPorts):
70+
dmrs_indice = fd_slot_data[ant].nonzero()
71+
dmrsdata = fd_slot_data[ant,dmrs_indice]
72+
73+
dmrsdata_ref = sel_ref_fdslot_data[ant,dmrs_indice]
74+
assert np.allclose(dmrsdata, dmrsdata_ref*DMRS_scaling, atol=1e-5)
75+
76+
#print("pass PUSCH DMRS processing")
77+

0 commit comments

Comments
 (0)