mirror of
https://gitlab.eurecom.fr/oai/openairinterface5g.git
synced 2026-07-14 13:10:28 +00:00
Compare commits
531 Commits
ntpool
...
sl-eurecom
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
149034887c | ||
|
|
5917f0f2b8 | ||
|
|
6832959b0b | ||
|
|
e7b42f419b | ||
|
|
d629498b98 | ||
|
|
1c01343d49 | ||
|
|
f633fc8d96 | ||
|
|
5e28985954 | ||
|
|
af662183f4 | ||
|
|
efccb416cc | ||
|
|
4232baec52 | ||
|
|
2f19c2de4d | ||
|
|
b17e862742 | ||
|
|
d680bb83b2 | ||
|
|
50923c7f80 | ||
|
|
90e5db3728 | ||
|
|
c9bc86312f | ||
|
|
7221a5f736 | ||
|
|
629b2c9fe3 | ||
|
|
9f91dbd9bb | ||
|
|
a354ce01cf | ||
|
|
93d32eca45 | ||
|
|
053d8d938f | ||
|
|
cf4a22b58a | ||
|
|
75e9db0633 | ||
|
|
24bf0d8046 | ||
|
|
d8627c91f3 | ||
|
|
ad8da84671 | ||
|
|
f0f1121e9c | ||
|
|
9b8eae2256 | ||
|
|
e9e347043e | ||
|
|
28741ed967 | ||
|
|
608aa3ebc4 | ||
|
|
a6e18fe06a | ||
|
|
aa6468f95e | ||
|
|
f09fffdb2b | ||
|
|
376a9beb80 | ||
|
|
0b892acef3 | ||
|
|
73907e5ee2 | ||
|
|
703047eca9 | ||
|
|
5cbad19d19 | ||
|
|
d1e1f56199 | ||
|
|
61435e9066 | ||
|
|
ee8af9dcfb | ||
|
|
b7f47aa70a | ||
|
|
066de7c3c5 | ||
|
|
fec2a15bdf | ||
|
|
8cbe4bb1d1 | ||
|
|
a54ca2c6e3 | ||
|
|
e79756d7ab | ||
|
|
39b73391d4 | ||
|
|
784be9d241 | ||
|
|
5d378b6416 | ||
|
|
b6e5b3594c | ||
|
|
f79ab7e087 | ||
|
|
c6c004b8aa | ||
|
|
2b193cded0 | ||
|
|
a07d4376d6 | ||
|
|
2f23bf1ea4 | ||
|
|
d8e92e93b3 | ||
|
|
6db9c37e47 | ||
|
|
f596c6907a | ||
|
|
d22d11d003 | ||
|
|
8bf5a0acf6 | ||
|
|
95fc447472 | ||
|
|
5a61145948 | ||
|
|
751f06b15e | ||
|
|
98d5c1691c | ||
|
|
678e3f9a01 | ||
|
|
ec1d5ead6a | ||
|
|
7cbfbd6c92 | ||
|
|
9338925b93 | ||
|
|
64b65cb5d9 | ||
|
|
7b2d0dbf39 | ||
|
|
ac4c4defd3 | ||
|
|
816532d86c | ||
|
|
a96d727409 | ||
|
|
624fc5353e | ||
|
|
d609f3f5ae | ||
|
|
bb525dc0ee | ||
|
|
1f432be612 | ||
|
|
b47cb76977 | ||
|
|
528e1d99d2 | ||
|
|
aba645dc93 | ||
|
|
468e7330de | ||
|
|
e7d04ec14f | ||
|
|
600399aa63 | ||
|
|
56b87424db | ||
|
|
7a1928dfd0 | ||
|
|
6c8112581b | ||
|
|
7e473ca971 | ||
|
|
7f40b90ceb | ||
|
|
7feb6ed41f | ||
|
|
6fbb4df0a3 | ||
|
|
89f11abe68 | ||
|
|
3362fa991f | ||
|
|
3614c221c4 | ||
|
|
298d822bd1 | ||
|
|
6775b577fd | ||
|
|
1283065946 | ||
|
|
50f4890faa | ||
|
|
03b75ed679 | ||
|
|
a91839e69c | ||
|
|
2e34ab0190 | ||
|
|
e6abb12fb1 | ||
|
|
a93da4a886 | ||
|
|
27e14a06c2 | ||
|
|
028f92a3e2 | ||
|
|
bf6b8442f1 | ||
|
|
0f90a7c24c | ||
|
|
0e84775e29 | ||
|
|
0e0fc7eab4 | ||
|
|
323f52aeb1 | ||
|
|
334fbb8879 | ||
|
|
39d54215bd | ||
|
|
bb580fae58 | ||
|
|
783e3d0da6 | ||
|
|
3fc1825e44 | ||
|
|
c0bf78efa0 | ||
|
|
c4f4a5d793 | ||
|
|
b6247b075b | ||
|
|
cfdfe6aaa7 | ||
|
|
709efd5da5 | ||
|
|
d9e487359d | ||
|
|
500069fcf0 | ||
|
|
99fb046474 | ||
|
|
c8ace3b540 | ||
|
|
6fc62b0184 | ||
|
|
085e84dc38 | ||
|
|
b1407040b6 | ||
|
|
88accf144e | ||
|
|
a7c5a0bb29 | ||
|
|
2949d00083 | ||
|
|
8378127c2c | ||
|
|
e1d9d15b2c | ||
|
|
53eb37e674 | ||
|
|
682b1be022 | ||
|
|
f4047b7aa4 | ||
|
|
34d80d4754 | ||
|
|
5dc3663f16 | ||
|
|
de54ec5b8b | ||
|
|
ce07b567d0 | ||
|
|
4ee9a6d8c6 | ||
|
|
39726e3274 | ||
|
|
0d5dcbbccb | ||
|
|
684f762fd9 | ||
|
|
b95722b670 | ||
|
|
b431e042fc | ||
|
|
43e8dcd7b6 | ||
|
|
5ea2e6d029 | ||
|
|
7cdf6847f1 | ||
|
|
1483d53e28 | ||
|
|
8727d12d18 | ||
|
|
6f6a314ab6 | ||
|
|
77f069c1af | ||
|
|
6a2f5664b8 | ||
|
|
6d51179357 | ||
|
|
720b2669fd | ||
|
|
9ffe2b7851 | ||
|
|
6befa6b3b0 | ||
|
|
d497806c6c | ||
|
|
475f99195e | ||
|
|
e1c152fbcf | ||
|
|
0db28d4f5a | ||
|
|
e344d531f9 | ||
|
|
433f3d1507 | ||
|
|
7e7b00e58b | ||
|
|
9b03282972 | ||
|
|
b5a2dab4e9 | ||
|
|
0f22e2a2d8 | ||
|
|
9fe8a273f2 | ||
|
|
e95d6e28fc | ||
|
|
71f52d180f | ||
|
|
0c048b28bd | ||
|
|
0a38dbb7be | ||
|
|
40a2ee85aa | ||
|
|
c61ab7fb7e | ||
|
|
9591a5bef5 | ||
|
|
f95c3f92ed | ||
|
|
0a6e7eb898 | ||
|
|
26a52906df | ||
|
|
0f8bb964a4 | ||
|
|
937c7119ae | ||
|
|
3e028a43b5 | ||
|
|
c501e448ca | ||
|
|
8313896093 | ||
|
|
87436a1884 | ||
|
|
34d508ae23 | ||
|
|
ffb6ca5934 | ||
|
|
682721cf57 | ||
|
|
1a627782dd | ||
|
|
28688065e2 | ||
|
|
21b766912b | ||
|
|
774b8ef6e9 | ||
|
|
aefe918f9f | ||
|
|
1dbe99316a | ||
|
|
b0ca489e60 | ||
|
|
5d270d63ac | ||
|
|
22063a35ec | ||
|
|
d39997d8b0 | ||
|
|
74998221e8 | ||
|
|
c468bd519b | ||
|
|
385243f521 | ||
|
|
0453ef25dd | ||
|
|
a909589185 | ||
|
|
064b05aee8 | ||
|
|
4f34b5f97a | ||
|
|
9c2c8067ef | ||
|
|
ca86a8a5ac | ||
|
|
4708a7d81c | ||
|
|
1d730cd8e2 | ||
|
|
e20bd2edaa | ||
|
|
fc236e4bd3 | ||
|
|
2ebef66785 | ||
|
|
4cd71874c0 | ||
|
|
c19ffff075 | ||
|
|
1c50671296 | ||
|
|
611c98f6f1 | ||
|
|
a66d7fcafc | ||
|
|
c6a972f65e | ||
|
|
28290c792d | ||
|
|
aa2e0319d0 | ||
|
|
0cce63fae9 | ||
|
|
f4bd344b9b | ||
|
|
565f6e13b0 | ||
|
|
30e6cc01c6 | ||
|
|
f9f8e21b55 | ||
|
|
bb1699e4d6 | ||
|
|
853f2737a4 | ||
|
|
7f3242a2b4 | ||
|
|
f2e678375b | ||
|
|
6444ee9aee | ||
|
|
5fc0e53cc8 | ||
|
|
147b5af7fe | ||
|
|
fa5fb4e49b | ||
|
|
d98f09825f | ||
|
|
74c075a751 | ||
|
|
f6815c381a | ||
|
|
7268877512 | ||
|
|
9114cd36cd | ||
|
|
530a5a3f01 | ||
|
|
1a9148ae2f | ||
|
|
e74d9c8aea | ||
|
|
662d453bf5 | ||
|
|
00885ccfd6 | ||
|
|
2e17b65004 | ||
|
|
df3a7bab95 | ||
|
|
c96851dc0d | ||
|
|
8c528798ad | ||
|
|
c065dc89bb | ||
|
|
f339b8b1e7 | ||
|
|
24cec4d5ba | ||
|
|
0d769760fd | ||
|
|
8fb5f5a350 | ||
|
|
9ffc7359b4 | ||
|
|
e6d200befe | ||
|
|
e079c43485 | ||
|
|
5f200844a4 | ||
|
|
6a4aa58c2e | ||
|
|
679bcc4365 | ||
|
|
9f056450d6 | ||
|
|
27994e444d | ||
|
|
9d11486431 | ||
|
|
e6ed641079 | ||
|
|
99bdc94279 | ||
|
|
a86559bdce | ||
|
|
971bb3bfc0 | ||
|
|
c387aa0f0d | ||
|
|
10ec942d67 | ||
|
|
91338a7439 | ||
|
|
a5ff057b69 | ||
|
|
d04291d66d | ||
|
|
4b9bc61748 | ||
|
|
a0a0e32f68 | ||
|
|
8167d64bcb | ||
|
|
e6b101d7da | ||
|
|
3689def55f | ||
|
|
a8c79ebf3b | ||
|
|
12f240c7e5 | ||
|
|
e1fc0a4d6b | ||
|
|
1c602f0e92 | ||
|
|
f5ad65cd2e | ||
|
|
4fe865a30f | ||
|
|
4ba390adfc | ||
|
|
ebfa50dce4 | ||
|
|
3d1631a673 | ||
|
|
7ea1501058 | ||
|
|
6fe163f4c4 | ||
|
|
38cccc73f0 | ||
|
|
75d0b6116e | ||
|
|
acb3a50768 | ||
|
|
e51ce1d232 | ||
|
|
e23e81425c | ||
|
|
14234e9eca | ||
|
|
5dd561743e | ||
|
|
264ab2ddd2 | ||
|
|
1e3932fbe1 | ||
|
|
51b8271ee9 | ||
|
|
c6d13e8d73 | ||
|
|
8a8c5275b0 | ||
|
|
a884e37625 | ||
|
|
dc84deafea | ||
|
|
23adfc132a | ||
|
|
be8bed3602 | ||
|
|
a8cb993e56 | ||
|
|
43da8296cf | ||
|
|
3462053a08 | ||
|
|
5e21c904ae | ||
|
|
26395fa2c2 | ||
|
|
f62ea2b3e0 | ||
|
|
f70097d9c9 | ||
|
|
47c400da03 | ||
|
|
a01a5f06ed | ||
|
|
d8a53795fe | ||
|
|
42991ff0ca | ||
|
|
087318f333 | ||
|
|
c2c574f153 | ||
|
|
96b7930292 | ||
|
|
789b639bbe | ||
|
|
7b5eb7e1b7 | ||
|
|
04d35e8d7e | ||
|
|
bef8362087 | ||
|
|
d80ba9b649 | ||
|
|
fdd75c4a36 | ||
|
|
31beafbd04 | ||
|
|
b203c79d87 | ||
|
|
18188b6f39 | ||
|
|
3e8ad6e26c | ||
|
|
6ef808cae1 | ||
|
|
bc2fe3db05 | ||
|
|
400447825a | ||
|
|
75f52cef4a | ||
|
|
4bec2f496d | ||
|
|
39c6b07820 | ||
|
|
f2cf9f0bd1 | ||
|
|
38b1b41682 | ||
|
|
68638ae67c | ||
|
|
9000f91f7e | ||
|
|
46b1cf6dc9 | ||
|
|
a74d7fa54f | ||
|
|
cdec2dd204 | ||
|
|
f98be66eda | ||
|
|
af5c062638 | ||
|
|
6ca28a9931 | ||
|
|
ce10596a13 | ||
|
|
d9a8108a15 | ||
|
|
1b5005277c | ||
|
|
ee9b35bec7 | ||
|
|
d82ab58c24 | ||
|
|
dbcc558f04 | ||
|
|
54f8add2de | ||
|
|
6e11362b75 | ||
|
|
59310feb4b | ||
|
|
8017cb16f3 | ||
|
|
be32f71b1a | ||
|
|
193720a376 | ||
|
|
865dd7984d | ||
|
|
d31d050dd5 | ||
|
|
3ae4e95775 | ||
|
|
1450ffd015 | ||
|
|
0ff5045410 | ||
|
|
e6a68d8cf2 | ||
|
|
a093745aa1 | ||
|
|
0af95f24fc | ||
|
|
6d1462712c | ||
|
|
048782bbec | ||
|
|
7397fca459 | ||
|
|
3dfb02e876 | ||
|
|
7e31ec9994 | ||
|
|
594811b9e6 | ||
|
|
c18da15703 | ||
|
|
c7c30d26b5 | ||
|
|
b2cf3f5270 | ||
|
|
1ebc4643e9 | ||
|
|
e77818daf8 | ||
|
|
eb6068cc1f | ||
|
|
fbec6c1261 | ||
|
|
2b05e90a57 | ||
|
|
028166428d | ||
|
|
fccae8a158 | ||
|
|
9e8f3f8c67 | ||
|
|
5886bb2b6a | ||
|
|
a999ce41ce | ||
|
|
d911c83c56 | ||
|
|
471df37f73 | ||
|
|
fab708d74e | ||
|
|
96583ee109 | ||
|
|
d3dd8af4cc | ||
|
|
f9642228af | ||
|
|
7a30b607e5 | ||
|
|
042b9e3c85 | ||
|
|
e57d62184e | ||
|
|
0139c38786 | ||
|
|
81c5c06414 | ||
|
|
8e702ad0d0 | ||
|
|
8a06717f95 | ||
|
|
123bf7e339 | ||
|
|
0bfaeac94b | ||
|
|
81a2d3854b | ||
|
|
e6bcd4e559 | ||
|
|
0d78000ca3 | ||
|
|
175579f8e2 | ||
|
|
05d2c538ea | ||
|
|
28a78f02a8 | ||
|
|
9de72b2e7e | ||
|
|
c6a892c15d | ||
|
|
618ea544c2 | ||
|
|
4ed69e515e | ||
|
|
124715d93e | ||
|
|
26553dfdad | ||
|
|
844d683915 | ||
|
|
47c429e8c3 | ||
|
|
33d9f68cda | ||
|
|
8618b6ad60 | ||
|
|
893ca2a4cb | ||
|
|
ef09160447 | ||
|
|
1ab09a6fa8 | ||
|
|
0134d8c914 | ||
|
|
ac0ec7b314 | ||
|
|
9350e05ad6 | ||
|
|
76797a5e86 | ||
|
|
6163143cfe | ||
|
|
60bcbb230f | ||
|
|
57824f4f02 | ||
|
|
9642337729 | ||
|
|
c265a6ec6a | ||
|
|
0558d55259 | ||
|
|
c2328793a3 | ||
|
|
e1300914da | ||
|
|
713f6632f9 | ||
|
|
9e8bd87501 | ||
|
|
b508ea71f8 | ||
|
|
be5a93b29a | ||
|
|
972256cd6e | ||
|
|
b5c2634151 | ||
|
|
992aa392a9 | ||
|
|
6b751b2874 | ||
|
|
034b64c895 | ||
|
|
61a93c2374 | ||
|
|
73c8012b52 | ||
|
|
eca4415287 | ||
|
|
a5c67fac57 | ||
|
|
b0d1b9d44f | ||
|
|
4d7958414e | ||
|
|
4d122d5d7c | ||
|
|
5228c18981 | ||
|
|
7b39aa61a9 | ||
|
|
d785a95a5f | ||
|
|
ff43319fdb | ||
|
|
4167066f04 | ||
|
|
61232c4557 | ||
|
|
5f8b20761b | ||
|
|
4ad9d66a3c | ||
|
|
5d4ad105b7 | ||
|
|
fa8bc0b57c | ||
|
|
1341cc35b9 | ||
|
|
173b4722fc | ||
|
|
515093ca29 | ||
|
|
013e70d22d | ||
|
|
640ce7beed | ||
|
|
d704dbec15 | ||
|
|
33989c3551 | ||
|
|
6470165730 | ||
|
|
fc33a75f22 | ||
|
|
0645690f3d | ||
|
|
e9a541a096 | ||
|
|
ec253251bc | ||
|
|
ae72632b85 | ||
|
|
b69a4aaa9b | ||
|
|
fc56972a35 | ||
|
|
f898a1724c | ||
|
|
ef37bcf170 | ||
|
|
31437e3185 | ||
|
|
fb98755a48 | ||
|
|
b2c07b620d | ||
|
|
d3cda4816d | ||
|
|
8aaa384193 | ||
|
|
2eed6f18e4 | ||
|
|
c79b681480 | ||
|
|
15b6259dcc | ||
|
|
d3e96c6769 | ||
|
|
eef2fb907b | ||
|
|
29a68836fa | ||
|
|
4b5cf91125 | ||
|
|
e66640f5ab | ||
|
|
01921cf9f0 | ||
|
|
d30b232aeb | ||
|
|
f9d93403d0 | ||
|
|
2c84fdbea3 | ||
|
|
61ebbc3403 | ||
|
|
4d8615c4fa | ||
|
|
55eb112ab0 | ||
|
|
9fa16cd5b9 | ||
|
|
6101792f4a | ||
|
|
b931c1b008 | ||
|
|
6aa1ad83a6 | ||
|
|
634f7dc1e6 | ||
|
|
80420d7cba | ||
|
|
b62d2fcf08 | ||
|
|
e5f851b01e | ||
|
|
12cecf668a | ||
|
|
f92a972aa5 | ||
|
|
756ff02fb7 | ||
|
|
1acb2fe894 | ||
|
|
4694664470 | ||
|
|
10c992bb27 | ||
|
|
5c443ee7a5 | ||
|
|
2785c83a90 | ||
|
|
a7f35bba02 | ||
|
|
cb5f8919e4 | ||
|
|
16371a8f5d | ||
|
|
98ac49f1bb | ||
|
|
5006fd48d8 | ||
|
|
a389eb8fd6 | ||
|
|
c68640f6f7 | ||
|
|
2695df5f31 | ||
|
|
fd4dbbfb35 | ||
|
|
5902aaf138 | ||
|
|
fc2ba4f4bd | ||
|
|
d50dae5005 | ||
|
|
e883528dd1 | ||
|
|
b1f721503e | ||
|
|
c0e71341a5 | ||
|
|
f2b9d369bd | ||
|
|
b1a1d1d0dd | ||
|
|
51e56f74d8 | ||
|
|
a34ce559a4 | ||
|
|
8bf7e77b0e | ||
|
|
7b633b141f | ||
|
|
95dbe3089e | ||
|
|
ee2f7c8a5c |
@@ -244,7 +244,7 @@ set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -ggdb2 -Wl,-rpath -Wl,${C
|
||||
# these changes are related to hardcoded path to include .h files
|
||||
set(debugOpt "-ggdb2 -DMALLOC_CHECK_=3 -fno-delete-null-pointer-checks")
|
||||
set(CMAKE_C_FLAGS_DEBUG "${debugOpt} -O0")
|
||||
set(CMAKE_C_FLAGS_RELWITHDEBINFO "${debugOpt} -O3")
|
||||
set(CMAKE_C_FLAGS_RELWITHDEBINFO "${debugOpt} -O2")
|
||||
set(CMAKE_C_FLAGS_RELEASE "-O3")
|
||||
|
||||
# Enable assert() for RelWithDebInfo builds
|
||||
@@ -773,25 +773,33 @@ add_library(UTIL
|
||||
${OPENAIR_DIR}/common/utils/time_stat.c
|
||||
)
|
||||
|
||||
set(SECURITY_SRC
|
||||
set(SECU_OSA_SRC
|
||||
${OPENAIR2_DIR}/UTIL/OSA/osa_key_deriver.c
|
||||
${OPENAIR2_DIR}/UTIL/OSA/osa_snow3g.c
|
||||
${OPENAIR2_DIR}/UTIL/OSA/osa_stream_eea.c
|
||||
${OPENAIR2_DIR}/UTIL/OSA/osa_stream_eia.c
|
||||
)
|
||||
add_library(SECU_OSA ${SECU_OSA_SRC} $<TARGET_OBJECTS:ds> )
|
||||
|
||||
target_include_directories(SECU_OSA PRIVATE ${OPENAIR_DIR}/common/utils/ds/)
|
||||
|
||||
set(SECU_CN_SRC
|
||||
${OPENAIR3_DIR}/SECU/secu_defs.c
|
||||
${OPENAIR3_DIR}/SECU/kdf.c
|
||||
${OPENAIR3_DIR}/SECU/aes_128_ctr.c
|
||||
${OPENAIR3_DIR}/SECU/aes_128_cbc_cmac.c
|
||||
${OPENAIR3_DIR}/SECU/aes_128_ecb.c
|
||||
${OPENAIR3_DIR}/SECU/sha_256_hmac.c
|
||||
${OPENAIR3_DIR}/SECU/rijndael.c
|
||||
${OPENAIR3_DIR}/SECU/snow3g.c
|
||||
${OPENAIR3_DIR}/SECU/key_nas_deriver.c
|
||||
${OPENAIR3_DIR}/SECU/nas_stream_eea0.c
|
||||
${OPENAIR3_DIR}/SECU/nas_stream_eea1.c
|
||||
${OPENAIR3_DIR}/SECU/nas_stream_eia1.c
|
||||
${OPENAIR3_DIR}/SECU/nas_stream_eea2.c
|
||||
${OPENAIR3_DIR}/SECU/nas_stream_eia2.c
|
||||
)
|
||||
|
||||
add_library(SECURITY ${SECURITY_SRC} $<TARGET_OBJECTS:ds>)
|
||||
target_include_directories(SECURITY PRIVATE ${OPENAIR_DIR}/common/utils/ds/)
|
||||
add_library(SECU_CN ${SECU_CN_SRC} $<TARGET_OBJECTS:ds>)
|
||||
target_include_directories(SECU_CN PRIVATE ${OPENAIR_DIR}/common/utils/ds/)
|
||||
|
||||
# Physical Channel Procedures Scheduling
|
||||
################################"
|
||||
@@ -1195,10 +1203,15 @@ set(PHY_SRC_UE
|
||||
${OPENAIR1_DIR}/PHY/MODULATION/slot_fep_nr.c
|
||||
${OPENAIR1_DIR}/PHY/NR_UE_TRANSPORT/pss_nr.c
|
||||
${OPENAIR1_DIR}/PHY/NR_UE_TRANSPORT/sss_nr.c
|
||||
${OPENAIR1_DIR}/PHY/NR_UE_TRANSPORT/pss_nr_sl.c
|
||||
${OPENAIR1_DIR}/PHY/NR_UE_TRANSPORT/sss_nr_sl.c
|
||||
${OPENAIR1_DIR}/PHY/NR_UE_TRANSPORT/nr_generate_psbch_dmrs_sl.c
|
||||
${OPENAIR1_DIR}/PHY/NR_UE_TRANSPORT/psbch_nr_sl.c
|
||||
${OPENAIR1_DIR}/PHY/NR_UE_TRANSPORT/cic_filter_nr.c
|
||||
${OPENAIR1_DIR}/PHY/NR_UE_TRANSPORT/nr_initial_sync.c
|
||||
${OPENAIR1_DIR}/PHY/NR_UE_TRANSPORT/nr_ue_rf_helpers.c
|
||||
${OPENAIR1_DIR}/PHY/NR_UE_TRANSPORT/nr_pbch.c
|
||||
${OPENAIR1_DIR}/PHY/NR_UE_TRANSPORT/nr_psbch.c
|
||||
${OPENAIR1_DIR}/PHY/NR_UE_TRANSPORT/nr_dlsch_demodulation.c
|
||||
${OPENAIR1_DIR}/PHY/NR_UE_TRANSPORT/nr_ulsch_coding.c
|
||||
${OPENAIR1_DIR}/PHY/NR_UE_TRANSPORT/nr_dlsch_decoding.c
|
||||
@@ -1342,8 +1355,8 @@ set(NR_PDCP_SRC
|
||||
#these files should not be here, will be removed at some point when the
|
||||
#computation is done directly inside nr_pdcp_integrity_nia1.c instead
|
||||
#of reusing code of osa_stream_eia.c
|
||||
#${OPENAIR2_DIR}/UTIL/OSA/osa_stream_eia.c
|
||||
#${OPENAIR2_DIR}/UTIL/OSA/osa_snow3g.c
|
||||
${OPENAIR2_DIR}/UTIL/OSA/osa_stream_eia.c
|
||||
${OPENAIR2_DIR}/UTIL/OSA/osa_snow3g.c
|
||||
)
|
||||
|
||||
set(NR_SDAP_SRC
|
||||
@@ -1985,7 +1998,7 @@ add_library(LIB_5GNAS_GNB
|
||||
)
|
||||
|
||||
target_include_directories(LIB_5GNAS_GNB PRIVATE ${OPENAIR_DIR}/common/utils/ds/)
|
||||
target_link_libraries(LIB_5GNAS_GNB PRIVATE SECURITY ${CRYPTO_LIBRARIES})
|
||||
target_link_libraries(LIB_5GNAS_GNB PRIVATE SECU_CN ${CRYPTO_LIBRARIES})
|
||||
target_link_libraries(LIB_5GNAS_GNB PRIVATE asn1_nr_rrc_hdrs asn1_lte_rrc_hdrs)
|
||||
|
||||
# Simulation library
|
||||
@@ -2148,7 +2161,7 @@ add_dependencies(lte-softmodem oai_iqplayer)
|
||||
|
||||
target_link_libraries(lte-softmodem PRIVATE
|
||||
-Wl,--start-group
|
||||
lte_rrc nr_rrc s1ap m2ap x2ap m3ap GTPV1U SECURITY UTIL HASHTABLE SCTP_CLIENT MME_APP SCHED_LIB SCHED_RU_LIB
|
||||
lte_rrc nr_rrc s1ap m2ap x2ap m3ap GTPV1U SECU_CN SECU_OSA UTIL HASHTABLE SCTP_CLIENT MME_APP SCHED_LIB SCHED_RU_LIB
|
||||
PHY_COMMON PHY PHY_RU L2 L2_LTE NFAPI_COMMON_LIB NFAPI_LIB NFAPI_VNF_LIB NFAPI_PNF_LIB NFAPI_USER_LIB MISC_NFAPI_LTE_LIB
|
||||
${NAS_UE_LIB} ITTI SIMU SIMU_ETH
|
||||
-Wl,--end-group z dl)
|
||||
@@ -2157,6 +2170,7 @@ target_link_libraries(lte-softmodem PRIVATE pthread m CONFIG_LIB rt crypt ${CRYP
|
||||
target_link_libraries(lte-softmodem PRIVATE ${T_LIB})
|
||||
target_link_libraries(lte-softmodem PRIVATE asn1_nr_rrc_hdrs asn1_lte_rrc_hdrs)
|
||||
|
||||
|
||||
add_executable(oairu
|
||||
${OPENAIR_DIR}/executables/lte-ru.c
|
||||
${OPENAIR_DIR}/executables/ru_control.c
|
||||
@@ -2209,7 +2223,7 @@ endif()
|
||||
target_link_libraries(lte-uesoftmodem PRIVATE
|
||||
-Wl,--start-group
|
||||
lte_rrc nr_rrc s1ap x2ap m2ap m3ap
|
||||
SECURITY UTIL HASHTABLE SCTP_CLIENT MME_APP SCHED_RU_LIB SCHED_UE_LIB PHY_COMMON
|
||||
SECU_CN SECU_OSA UTIL HASHTABLE SCTP_CLIENT MME_APP SCHED_RU_LIB SCHED_UE_LIB PHY_COMMON
|
||||
PHY_UE PHY_RU L2_UE L2_LTE SIMU SIMU_ETH NFAPI_COMMON_LIB NFAPI_LIB NFAPI_PNF_LIB NFAPI_USER_LIB MISC_NFAPI_LTE_LIB
|
||||
${NAS_UE_LIB} ITTI ${ATLAS_LIBRARIES}
|
||||
-Wl,--end-group z dl)
|
||||
@@ -2230,8 +2244,6 @@ add_executable(nr-softmodem
|
||||
${nr_rrc_h}
|
||||
${s1ap_h}
|
||||
# ${OPENAIR_BIN_DIR}/messages_xml.h
|
||||
${OPENAIR_DIR}/common/utils/thread_pool/task_manager.c
|
||||
|
||||
${OPENAIR_DIR}/executables/nr-gnb.c
|
||||
${OPENAIR_DIR}/executables/nr-ru.c
|
||||
${OPENAIR_DIR}/executables/nr-softmodem.c
|
||||
@@ -2251,7 +2263,7 @@ add_executable(nr-softmodem
|
||||
|
||||
target_link_libraries(nr-softmodem PRIVATE
|
||||
-Wl,--start-group
|
||||
UTIL HASHTABLE SCTP_CLIENT SCHED_LIB SCHED_RU_LIB SCHED_NR_LIB PHY_NR PHY PHY_COMMON PHY_NR_COMMON PHY_RU GTPV1U SECURITY
|
||||
UTIL HASHTABLE SCTP_CLIENT SCHED_LIB SCHED_RU_LIB SCHED_NR_LIB PHY_NR PHY PHY_COMMON PHY_NR_COMMON PHY_RU GTPV1U SECU_CN SECU_OSA
|
||||
ITTI ${NAS_UE_LIB} lte_rrc nr_rrc
|
||||
ngap s1ap L2_LTE_NR L2_NR MAC_NR_COMMON NFAPI_COMMON_LIB NFAPI_LIB NFAPI_VNF_LIB NFAPI_PNF_LIB NFAPI_USER_LIB SIMU SIMU_ETH
|
||||
x2ap f1ap m2ap m3ap e1ap
|
||||
@@ -2286,9 +2298,9 @@ add_executable(nr-cuup
|
||||
target_link_libraries(nr-cuup PRIVATE
|
||||
CONFIG_LIB ITTI SCTP_CLIENT
|
||||
GTPV1U e1ap e1_pdcp_if f1ap SIMU_ETH
|
||||
SECURITY ${OPENSSL_LIBRARIES} crypt z sctp dl pthread)
|
||||
SECU_OSA SECU_CN ${OPENSSL_LIBRARIES} crypt z sctp dl pthread)
|
||||
target_link_libraries(nr-cuup PRIVATE asn1_lte_rrc_hdrs asn1_nr_rrc_hdrs)
|
||||
|
||||
|
||||
# nr-uesoftmodem is UE implementation
|
||||
#######################################
|
||||
|
||||
@@ -2313,7 +2325,7 @@ add_executable(nr-uesoftmodem
|
||||
|
||||
target_link_libraries(nr-uesoftmodem PRIVATE
|
||||
-Wl,--start-group
|
||||
nr_rrc SECURITY UTIL HASHTABLE SCHED_RU_LIB SCHED_NR_UE_LIB
|
||||
nr_rrc SECU_CN SECU_OSA UTIL HASHTABLE SCHED_RU_LIB SCHED_NR_UE_LIB
|
||||
PHY_COMMON PHY_NR_COMMON PHY_NR_UE NR_L2_UE L2_UE_LTE_NR MAC_NR_COMMON NFAPI_COMMON_LIB NFAPI_LIB NFAPI_PNF_LIB
|
||||
NFAPI_USER_LIB MISC_NFAPI_NR_LIB
|
||||
ITTI ${ATLAS_LIBRARIES} LIB_5GNAS_GNB LIB_NAS_SIMUE ${NAS_SIM_LIB} SIMU SIMU_ETH
|
||||
@@ -2403,7 +2415,6 @@ target_link_libraries(ldpctest PRIVATE
|
||||
)
|
||||
|
||||
add_executable(nr_dlschsim
|
||||
${OPENAIR_DIR}/common/utils/thread_pool/task_manager.c
|
||||
${OPENAIR1_DIR}/SIMULATION/NR_PHY/dlschsim.c
|
||||
${OPENAIR1_DIR}/SIMULATION/NR_PHY/nr_dummy_functions.c
|
||||
${OPENAIR_DIR}/common/utils/nr/nr_common.c
|
||||
@@ -2430,7 +2441,19 @@ target_link_libraries(nr_pbchsim PRIVATE
|
||||
target_link_libraries(nr_pbchsim PRIVATE asn1_nr_rrc_hdrs asn1_lte_rrc_hdrs)
|
||||
|
||||
|
||||
#PUCCH ---> Prashanth
|
||||
add_executable(nr_psbchsim
|
||||
${OPENAIR1_DIR}/SIMULATION/NR_PHY/psbchsim.c
|
||||
${OPENAIR_DIR}/common/utils/nr/nr_common.c
|
||||
${T_SOURCE}
|
||||
${SHLIB_LOADER_SOURCES}
|
||||
)
|
||||
target_link_libraries(nr_psbchsim PRIVATE
|
||||
-Wl,--start-group UTIL SIMU PHY_COMMON PHY_NR_COMMON PHY_NR PHY_NR_UE SCHED_NR_LIB CONFIG_LIB MAC_NR_COMMON -Wl,--end-group
|
||||
m pthread ${ATLAS_LIBRARIES} ${T_LIB} ITTI dl
|
||||
)
|
||||
target_link_libraries(nr_psbchsim PRIVATE asn1_nr_rrc asn1_lte_rrc)
|
||||
|
||||
|
||||
add_executable(nr_pucchsim
|
||||
${OPENAIR1_DIR}/SIMULATION/NR_PHY/pucchsim.c
|
||||
${OPENAIR1_DIR}/SIMULATION/NR_PHY/nr_dummy_functions.c
|
||||
@@ -2458,13 +2481,12 @@ add_executable(nr_dlsim
|
||||
${SHLIB_LOADER_SOURCES}
|
||||
)
|
||||
target_link_libraries(nr_dlsim PRIVATE
|
||||
-Wl,--start-group UTIL SIMU SIMU_ETH PHY_COMMON PHY_NR_COMMON PHY_NR PHY_NR_UE SCHED_NR_LIB SCHED_NR_UE_LIB MAC_NR MAC_UE_NR MAC_NR_COMMON nr_rrc CONFIG_LIB L2_NR HASHTABLE x2ap SECURITY ngap -lz -Wl,--end-group
|
||||
-Wl,--start-group UTIL SIMU SIMU_ETH PHY_COMMON PHY_NR_COMMON PHY_NR PHY_NR_UE SCHED_NR_LIB SCHED_NR_UE_LIB MAC_NR MAC_UE_NR MAC_NR_COMMON nr_rrc CONFIG_LIB L2_NR HASHTABLE x2ap SECU_CN ngap -lz -Wl,--end-group
|
||||
m pthread ${ATLAS_LIBRARIES} ${T_LIB} ITTI ${OPENSSL_LIBRARIES} dl
|
||||
)
|
||||
target_link_libraries(nr_dlsim PRIVATE asn1_nr_rrc_hdrs asn1_lte_rrc_hdrs)
|
||||
|
||||
add_executable(nr_prachsim
|
||||
${OPENAIR_DIR}/common/utils/thread_pool/task_manager.c
|
||||
${OPENAIR1_DIR}/SIMULATION/NR_PHY/prachsim.c
|
||||
${OPENAIR1_DIR}/SIMULATION/NR_PHY/nr_dummy_functions.c
|
||||
${OPENAIR_DIR}/common/utils/nr/nr_common.c
|
||||
@@ -2490,7 +2512,6 @@ target_link_libraries(nr_ulschsim PRIVATE
|
||||
target_link_libraries(nr_ulschsim PRIVATE asn1_nr_rrc_hdrs asn1_lte_rrc_hdrs)
|
||||
|
||||
add_executable(nr_ulsim
|
||||
${OPENAIR_DIR}/common/utils/thread_pool/task_manager.c
|
||||
${OPENAIR1_DIR}/SIMULATION/NR_PHY/ulsim.c
|
||||
${OPENAIR1_DIR}/SIMULATION/NR_PHY/nr_dummy_functions.c
|
||||
${OPENAIR_DIR}/common/utils/nr/nr_common.c
|
||||
@@ -2509,7 +2530,7 @@ if (ENABLE_LDPC_T1)
|
||||
endif()
|
||||
|
||||
target_link_libraries(nr_ulsim PRIVATE
|
||||
-Wl,--start-group UTIL SIMU SIMU_ETH PHY_COMMON PHY_NR_COMMON PHY_NR PHY_NR_UE SCHED_NR_LIB SCHED_NR_UE_LIB MAC_NR MAC_UE_NR MAC_NR_COMMON nr_rrc CONFIG_LIB L2_NR HASHTABLE x2ap SECURITY ngap -lz -Wl,--end-group
|
||||
-Wl,--start-group UTIL SIMU SIMU_ETH PHY_COMMON PHY_NR_COMMON PHY_NR PHY_NR_UE SCHED_NR_LIB SCHED_NR_UE_LIB MAC_NR MAC_UE_NR MAC_NR_COMMON nr_rrc CONFIG_LIB L2_NR HASHTABLE x2ap SECU_CN ngap -lz -Wl,--end-group
|
||||
m pthread ${ATLAS_LIBRARIES} ${T_LIB} ITTI ${OPENSSL_LIBRARIES} dl
|
||||
)
|
||||
target_link_libraries(nr_ulsim PRIVATE asn1_nr_rrc_hdrs asn1_lte_rrc_hdrs)
|
||||
@@ -2548,7 +2569,7 @@ foreach(myExe s1ap
|
||||
${OPENAIR3_DIR}/TEST/test_${myExe}.c
|
||||
)
|
||||
target_link_libraries (test_${myExe}
|
||||
-Wl,--start-group SECURITY UTIL -Wl,--end-group m rt crypt ${CRYPTO_LIBRARIES} ${OPENSSL_LIBRARIES} CONFIG_LIB
|
||||
-Wl,--start-group SECU_CN UTIL -Wl,--end-group m rt crypt ${CRYPTO_LIBRARIES} ${OPENSSL_LIBRARIES} CONFIG_LIB
|
||||
)
|
||||
endforeach(myExe)
|
||||
|
||||
@@ -2563,13 +2584,13 @@ if (${T_TRACER})
|
||||
lte-softmodem lte-uesoftmodem nr-softmodem
|
||||
nr-uesoftmodem dlsim dlsim_tm4 dlsim_tm7
|
||||
ulsim pbchsim scansim mbmssim pdcchsim pucchsim prachsim
|
||||
syncsim nr_ulsim nr_dlsim nr_dlschsim nr_pbchsim nr_pucchsim
|
||||
syncsim nr_ulsim nr_dlsim nr_dlschsim nr_pbchsim nr_psbchsim nr_pucchsim
|
||||
nr_ulschsim ldpctest polartest smallblocktest cu_test du_test
|
||||
#all "add_library" definitions
|
||||
ITTI lte_rrc nr_rrc s1ap x2ap m2ap m3ap f1ap
|
||||
params_libconfig oai_usrpdevif oai_bladerfdevif oai_lmssdrdevif oai_iqplayer
|
||||
oai_eth_transpro oai_mobipass coding HASHTABLE UTIL OMG_SUMO
|
||||
SECURITY SCHED_LIB SCHED_NR_LIB SCHED_RU_LIB SCHED_UE_LIB SCHED_NR_UE_LIB default_sched remote_sched RAL
|
||||
SECU_OSA SECU_CN SCHED_LIB SCHED_NR_LIB SCHED_RU_LIB SCHED_UE_LIB SCHED_NR_UE_LIB default_sched remote_sched RAL
|
||||
NFAPI_COMMON_LIB NFAPI_LIB NFAPI_PNF_LIB NFAPI_VNF_LIB NFAPI_USER_LIB
|
||||
PHY_COMMON PHY PHY_UE PHY_NR PHY_NR_COMMON PHY_NR_UE PHY_RU PHY_MEX
|
||||
L2 L2_LTE L2_NR L2_LTE_NR L2_UE NR_L2_UE L2_UE_LTE_NR MAC_NR_COMMON MAC_NR MAC_UE_NR ngap
|
||||
|
||||
@@ -227,6 +227,14 @@ def ArgsParse(argvs,CiTestObj,RAN,HTML,EPC,ldpc,CONTAINERS,HELP,SCA,PHYSIM,CLUST
|
||||
elif re.match('^\-\-EPCContainerPrefix=(.+)$', myArgv, re.IGNORECASE):
|
||||
matchReg = re.match('^\-\-EPCContainerPrefix=(.+)$', myArgv, re.IGNORECASE)
|
||||
EPC.ContainerPrefix=matchReg.group(1)
|
||||
elif re.match('^\-\-ADBIPAddress=(.+)$', myArgv, re.IGNORECASE):
|
||||
print("ignoring --ADBIPAddress parameter")
|
||||
elif re.match('^\-\-ADBUserName=(.+)$', myArgv, re.IGNORECASE):
|
||||
print("ignoring --ADBUserName parameter")
|
||||
elif re.match('^\-\-ADBType=(.+)$', myArgv, re.IGNORECASE):
|
||||
print("ignoring --ADBType parameter")
|
||||
elif re.match('^\-\-ADBPassword=(.+)$', myArgv, re.IGNORECASE):
|
||||
print("ignoring --ADBPassword parameter")
|
||||
elif re.match('^\-\-XMLTestFile=(.+)$', myArgv, re.IGNORECASE):
|
||||
matchReg = re.match('^\-\-XMLTestFile=(.+)$', myArgv, re.IGNORECASE)
|
||||
CiTestObj.testXMLfiles.append(matchReg.group(1))
|
||||
|
||||
@@ -49,7 +49,7 @@ adb_ue_2:
|
||||
|
||||
amarisoft_ue:
|
||||
Host: amariue
|
||||
InitScript: /root/NV18-06-2022/lteue-linux-2023-03-17/lteue /root/oaicicd/ran_sa_aw2s_asue/aw2s-multi-20897-2x2.cfg &
|
||||
InitScript: /root/NV18-06-2022/lteue-linux-2023-03-17/lteue /root/oaicicd/ran_sa_aw2s_asue/aw2s-multi-20897.cfg &
|
||||
TermScript: /root/NV18-06-2022/lteue-linux-2023-03-17/doc/ws.js 127.0.0.1:9002 '{"message":"quit"}'
|
||||
amarisoft_ue_1:
|
||||
Host: amariue
|
||||
|
||||
@@ -42,8 +42,7 @@ IMAGE_REGISTRY_SERVICE_NAME = "image-registry.openshift-image-registry.svc"
|
||||
NAMESPACE = "oaicicd-ran"
|
||||
OCUrl = "https://api.oai.cs.eurecom.fr:6443"
|
||||
OCRegistry = "default-route-openshift-image-registry.apps.oai.cs.eurecom.fr/"
|
||||
CI_OC_RAN_NAMESPACE = "oaicicd-ran"
|
||||
CI_OC_CORE_NAMESPACE = "oaicicd-core-for-ci-ran"
|
||||
|
||||
|
||||
def OC_login(cmd, ocUserName, ocPassword, ocProjectName):
|
||||
if ocUserName == '' or ocPassword == '' or ocProjectName == '':
|
||||
@@ -199,22 +198,23 @@ class Cluster:
|
||||
HELP.GenericHelp(CONST.Version)
|
||||
HELP.EPCSrvHelp(self.imageToPull)
|
||||
sys.exit('Insufficient eNB Parameters')
|
||||
lIpAddr = self.eNBIPAddress
|
||||
self.testCase_id = HTML.testCase_id
|
||||
cmd = cls_cmd.getConnection(self.eNBIPAddress)
|
||||
succeeded = OC_login(cmd, self.OCUserName, self.OCPassword, CI_OC_RAN_NAMESPACE)
|
||||
cmd = cls_cmd.getConnection(lIpAddr)
|
||||
succeeded = OC_login(cmd, self.OCUserName, self.OCPassword, self.OCProjectName)
|
||||
if not succeeded:
|
||||
logging.error('\u001B[1m OC Cluster Login Failed\u001B[0m')
|
||||
HTML.CreateHtmlTestRow('N/A', 'KO', CONST.OC_LOGIN_FAIL)
|
||||
return False
|
||||
ret = cmd.run(f'oc whoami -t | docker login -u oaicicd --password-stdin {self.OCRegistry}')
|
||||
if ret.returncode != 0:
|
||||
logging.error(f'\u001B[1m Unable to access OC project {CI_OC_RAN_NAMESPACE}\u001B[0m')
|
||||
logging.error(f'\u001B[1m Unable to access OC project {ocProjectName}\u001B[0m')
|
||||
OC_logout(cmd)
|
||||
cmd.close()
|
||||
HTML.CreateHtmlTestRow('N/A', 'KO', CONST.OC_LOGIN_FAIL)
|
||||
return False
|
||||
for image in self.imageToPull:
|
||||
imagePrefix = f'{self.OCRegistry}{CI_OC_RAN_NAMESPACE}'
|
||||
imagePrefix = f'{self.OCRegistry}{self.OCProjectName}'
|
||||
imageTag = cls_containerize.ImageTagToUse(image, self.ranCommitID, self.ranBranch, self.ranAllowMerge)
|
||||
ret = cmd.run(f'docker pull {imagePrefix}/{imageTag}')
|
||||
if ret.returncode != 0:
|
||||
|
||||
@@ -800,7 +800,7 @@ class Containerize():
|
||||
logging.debug('Removing test images locally')
|
||||
myCmd = cls_cmd.LocalCmd()
|
||||
|
||||
imageNames = ['oai-enb', 'oai-gnb', 'oai-lte-ue', 'oai-nr-ue', 'oai-lte-ru', 'oai-nr-cuup', 'oai-gnb-aw2s']
|
||||
imageNames = ['oai-enb', 'oai-gnb', 'oai-lte-ue', 'oai-nr-ue', 'oai-lte-ru', 'oai-nr-cuup']
|
||||
for image in imageNames:
|
||||
imageTag = ImageTagToUse(image, self.ranCommitID, self.ranBranch, self.ranAllowMerge)
|
||||
cmd = f'docker rmi oai-ci/{imageTag}'
|
||||
@@ -879,8 +879,8 @@ class Containerize():
|
||||
cnt += 1
|
||||
mySSH.command('docker inspect --format="ImageUsed: {{.Config.Image}}" ' + containerName, '\$', 5)
|
||||
for stdoutLine in mySSH.getBefore().split('\n'):
|
||||
if stdoutLine.count('ImageUsed: oai-ci'):
|
||||
usedImage = stdoutLine.replace('ImageUsed: oai-ci', 'oai-ci').strip()
|
||||
if stdoutLine.count('ImageUsed: porcepix'):
|
||||
usedImage = stdoutLine.replace('ImageUsed: porcepix', 'porcepix').strip()
|
||||
logging.debug('Used image is ' + usedImage)
|
||||
if usedImage != '':
|
||||
mySSH.command('docker image inspect --format "* Size = {{.Size}} bytes\n* Creation = {{.Created}}\n* Id = {{.Id}}" ' + usedImage, '\$', 5, silent=True)
|
||||
|
||||
@@ -49,7 +49,6 @@ import concurrent.futures
|
||||
#import our libs
|
||||
import helpreadme as HELP
|
||||
import constants as CONST
|
||||
import cls_cluster as OC
|
||||
import sshconnection
|
||||
|
||||
import cls_module_ue
|
||||
@@ -59,6 +58,79 @@ logging.getLogger("matplotlib").setLevel(logging.WARNING)
|
||||
import matplotlib.pyplot as plt
|
||||
import numpy as np
|
||||
|
||||
#-----------------------------------------------------------
|
||||
# Utility functions
|
||||
#-----------------------------------------------------------
|
||||
|
||||
def GetPingTimeAnalysis(RAN,ping_log_file,ping_rttavg_threshold):
|
||||
#ping time values read from file
|
||||
t_ping=[]
|
||||
#ping stats (dictionary) to be returned by the function
|
||||
ping_stat={}
|
||||
if (os.path.isfile(ping_log_file)):
|
||||
with open(ping_log_file,"r") as f:
|
||||
for line in f:
|
||||
#looking for time=xxx ms field
|
||||
result=re.match('^.+time=(?P<ping_time>[0-9\.]+)',line)
|
||||
if result != None:
|
||||
t_ping.append(float(result.group('ping_time')))
|
||||
|
||||
#initial stats
|
||||
ping_stat['min_0']=min(t_ping)
|
||||
ping_stat['mean_0']=stat.mean(t_ping)
|
||||
ping_stat['median_0']=stat.median(t_ping)
|
||||
ping_stat['max_0']=max(t_ping)
|
||||
|
||||
#get index of max value
|
||||
|
||||
max_loc=t_ping.index(max(t_ping))
|
||||
ping_stat['max_loc']=max_loc
|
||||
#remove it
|
||||
t_ping_post=t_ping.copy()
|
||||
t_ping_post.pop(max_loc)
|
||||
#new stats after removing max value
|
||||
ping_stat['min_1']=min(t_ping_post)
|
||||
ping_stat['mean_1']=stat.mean(t_ping_post)
|
||||
ping_stat['median_1']=stat.median(t_ping_post)
|
||||
ping_stat['max_1']=max(t_ping_post)
|
||||
|
||||
#plot ping over time and save png for artifacts
|
||||
ticks = np.arange(0, len(t_ping), 1)
|
||||
figure, axis = plt.subplots(figsize=(10, 10))
|
||||
axis.plot(ticks,t_ping,marker='o')
|
||||
axis.set_xlabel('Ping Events')
|
||||
axis.set_ylabel("Ping RTT (in ms)")
|
||||
axis.set_title(ping_log_file)
|
||||
axis.set_xticks(ticks)
|
||||
axis.set_xticklabels([])
|
||||
YMAX=20 #base scale
|
||||
if max(t_ping) > YMAX:
|
||||
y_max=max(t_ping)+1
|
||||
else:
|
||||
y_max=YMAX+1
|
||||
plt.ylim(0,y_max)
|
||||
if ping_rttavg_threshold != '':
|
||||
th_label="AVG Ping Fail Threshold="+ping_rttavg_threshold
|
||||
plt.axhline(y=float(ping_rttavg_threshold), color='r', linestyle='-',label=th_label)
|
||||
axis.legend()
|
||||
plt.savefig(ping_log_file+'.png')
|
||||
|
||||
#copy the png file already to enb to move it move it later into the artifacts
|
||||
try:
|
||||
mySSH = sshconnection.SSHConnection()
|
||||
mySSH.copyout(RAN.eNBIPAddress, RAN.eNBUserName, RAN.eNBPassword, ping_log_file+'.png', RAN.eNBSourceCodePath + '/cmake_targets/')
|
||||
mySSH.copyout(RAN.eNBIPAddress, RAN.eNBUserName, RAN.eNBPassword, ping_log_file, RAN.eNBSourceCodePath + '/cmake_targets/')
|
||||
except:
|
||||
logging.debug('\u001B[1;37;41m Ping PNG SCP to eNB FAILED\u001B[0m')
|
||||
|
||||
return ping_stat
|
||||
|
||||
else:
|
||||
logging.error("GetPingTimeAnalysis : Ping log file does not exist")
|
||||
return -1
|
||||
|
||||
|
||||
|
||||
#-----------------------------------------------------------
|
||||
# OaiCiTest Class Definition
|
||||
#-----------------------------------------------------------
|
||||
@@ -232,6 +304,7 @@ class OaiCiTest():
|
||||
[f.result() for f in futures]
|
||||
HTML.CreateHtmlTestRowQueue('N/A', 'OK', messages)
|
||||
|
||||
|
||||
def InitializeOAIUE(self,HTML,RAN,EPC,CONTAINERS):
|
||||
if self.UEIPAddress == '' or self.UEUserName == '' or self.UEPassword == '' or self.UESourceCodePath == '':
|
||||
HELP.GenericHelp(CONST.Version)
|
||||
@@ -503,133 +576,298 @@ class OaiCiTest():
|
||||
statusQueue.put(message)
|
||||
lock.release()
|
||||
|
||||
def Ping_common(self, EPC, ue, RAN):
|
||||
# Launch ping on the EPC side (true for ltebox and old open-air-cn)
|
||||
# But for OAI-Rel14-CUPS, we launch from python executor
|
||||
ping_status = 0
|
||||
ueIP = ue.getIP()
|
||||
if not ueIP:
|
||||
return (False, f"UE {ue.getName()} has no IP address")
|
||||
launchFromEpc = False
|
||||
ping_log_file = f'ping_{self.testCase_id}_{ue.getName()}.log'
|
||||
if re.match('OAI-Rel14-CUPS', EPC.Type, re.IGNORECASE):
|
||||
def Ping_common(self, lock, statusQueue,EPC, ue, RAN):
|
||||
try:
|
||||
# Launch ping on the EPC side (true for ltebox and old open-air-cn)
|
||||
# But for OAI-Rel14-CUPS, we launch from python executor
|
||||
ping_status = 0
|
||||
launchFromEpc = False
|
||||
ping_time = re.findall("-c *(\d+)",str(self.ping_args))
|
||||
if launchFromEpc:
|
||||
SSH = sshconnection.SSHConnection()
|
||||
SSH.open(EPC.IPAddress, EPC.UserName, EPC.Password)
|
||||
SSH.command('cd ' + EPC.SourceCodePath, '\$', 5)
|
||||
SSH.command('cd scripts', '\$', 5)
|
||||
# In case of a docker-based deployment, we need to ping from the trf-gen container
|
||||
launchFromTrfContainer = False
|
||||
if (re.match('OAI-Rel14-Docker', EPC.Type, re.IGNORECASE)) or (re.match('OAICN5G', EPC.Type, re.IGNORECASE)):
|
||||
launchFromTrfContainer = True
|
||||
if launchFromTrfContainer:
|
||||
ping_status = SSH.command(f'docker exec -it prod-trf-gen /bin/bash -c "ping {self.ping_args} {ueIP}" 2>&1 | tee {ping_log_file}', '\$', int(ping_time[0])*1.5)
|
||||
else:
|
||||
ping_status = SSH.command(f'stdbuf -o0 ping {self.ping_args} {ueIP} 2>&1 | stdbuf -o0 tee {ping_log_file}', '\$', int(ping_time[0])*1.5)
|
||||
#copy the ping log file to have it locally for analysis (ping stats)
|
||||
SSH.copyin(EPC.IPAddress, EPC.UserName, EPC.Password, EPC.SourceCodePath + '/scripts/{ping_log_file}', '.')
|
||||
SSH.close()
|
||||
else:
|
||||
#target address is different depending on EPC type
|
||||
if re.match('OAI-Rel14-Docker', EPC.Type, re.IGNORECASE):
|
||||
Target = EPC.MmeIPAddress
|
||||
elif re.match('OAICN5G', EPC.Type, re.IGNORECASE):
|
||||
Target = EPC.MmeIPAddress
|
||||
elif re.match('OC-OAI-CN5G', EPC.Type, re.IGNORECASE):
|
||||
Target = "172.21.6.100"
|
||||
else:
|
||||
Target = EPC.IPAddress
|
||||
#ping from module NIC rather than IP address to make sure round trip is over the air
|
||||
interface = f'-I {ue.getIFName()}' if ue.getIFName() else ''
|
||||
ping_cmd = f'{ue.getCmdPrefix()} ping {interface} {self.ping_args} {Target} &> /tmp/{ping_log_file}'
|
||||
cmd = cls_cmd.getConnection(ue.getHost())
|
||||
response = cmd.run(ping_cmd, timeout=int(ping_time[0])*1.5)
|
||||
if response.returncode != 0:
|
||||
ping_status = -1
|
||||
else:
|
||||
ping_log_file = f'ping_{self.testCase_id}_{ue.getName()}.log'
|
||||
if re.match('OAI-Rel14-CUPS', EPC.Type, re.IGNORECASE):
|
||||
launchFromEpc = False
|
||||
ping_time = re.findall("-c *(\d+)",str(self.ping_args))
|
||||
if launchFromEpc:
|
||||
SSH = sshconnection.SSHConnection()
|
||||
SSH.open(EPC.IPAddress, EPC.UserName, EPC.Password)
|
||||
SSH.command('cd ' + EPC.SourceCodePath, '\$', 5)
|
||||
SSH.command('cd scripts', '\$', 5)
|
||||
# In case of a docker-based deployment, we need to ping from the trf-gen container
|
||||
launchFromTrfContainer = False
|
||||
if (re.match('OAI-Rel14-Docker', EPC.Type, re.IGNORECASE)) or (re.match('OAICN5G', EPC.Type, re.IGNORECASE)):
|
||||
launchFromTrfContainer = True
|
||||
if launchFromTrfContainer:
|
||||
ping_status = SSH.command(f'docker exec -it prod-trf-gen /bin/bash -c "ping {self.ping_args} {ue.getIP()}" 2>&1 | tee {ping_log_file}', '\$', int(ping_time[0])*1.5)
|
||||
else:
|
||||
ping_status = SSH.command(f'stdbuf -o0 ping {self.ping_args} {ue.getIP()} 2>&1 | stdbuf -o0 tee {ping_log_file}', '\$', int(ping_time[0])*1.5)
|
||||
#copy the ping log file to have it locally for analysis (ping stats)
|
||||
cmd.copyin(src=f'/tmp/{ping_log_file}', tgt=ping_log_file)
|
||||
SSH.copyin(EPC.IPAddress, EPC.UserName, EPC.Password, EPC.SourceCodePath + '/scripts/{ping_log_file}', '.')
|
||||
SSH.close()
|
||||
else:
|
||||
#target address is different depending on EPC type
|
||||
if re.match('OAI-Rel14-Docker', EPC.Type, re.IGNORECASE):
|
||||
Target = EPC.MmeIPAddress
|
||||
elif re.match('OAICN5G', EPC.Type, re.IGNORECASE):
|
||||
Target = EPC.MmeIPAddress
|
||||
elif re.match('OC-OAI-CN5G', EPC.Type, re.IGNORECASE):
|
||||
Target = "172.21.6.100"
|
||||
else:
|
||||
Target = EPC.IPAddress
|
||||
#ping from module NIC rather than IP address to make sure round trip is over the air
|
||||
interface = f'-I {ue.getIFName()}' if ue.getIFName() else ''
|
||||
ping_cmd = f'{ue.getCmdPrefix()} ping {interface} {self.ping_args} {Target} &> /tmp/{ping_log_file}'
|
||||
cmd = cls_cmd.getConnection(ue.getHost())
|
||||
response = cmd.run(ping_cmd, timeout=int(ping_time[0])*1.5)
|
||||
if response.returncode != 0:
|
||||
ping_status = -1
|
||||
else:
|
||||
#copy the ping log file to have it locally for analysis (ping stats)
|
||||
cmd.copyin(src=f'/tmp/{ping_log_file}', tgt=ping_log_file)
|
||||
|
||||
cmd.close()
|
||||
cmd.close()
|
||||
|
||||
# TIMEOUT CASE
|
||||
ue_header = f'UE {ue.getName()} ({ueIP})'
|
||||
if ping_status < 0:
|
||||
message = ue_header + ': ping crashed: TIMEOUT?'
|
||||
logging.error('\u001B[1;37;41m ' + message + ' \u001B[0m')
|
||||
return (False, message)
|
||||
#search is done on cat result
|
||||
logging.debug('Analyzing Ping log file : ' + os.getcwd() + '/' + ping_log_file)
|
||||
with open(ping_log_file, 'r') as f:
|
||||
ping_output = "".join(f.readlines())
|
||||
result = re.search(', (?P<packetloss>[0-9\.]+)% packet loss, time [0-9\.]+ms', ping_output)
|
||||
if result is None:
|
||||
message = ue_header + ': Packet Loss Not Found!'
|
||||
logging.error('\u001B[1;37;41m ' + message + ' \u001B[0m')
|
||||
return (False, message)
|
||||
packetloss = result.group('packetloss')
|
||||
result = re.search('rtt min\/avg\/max\/mdev = (?P<rtt_min>[0-9\.]+)\/(?P<rtt_avg>[0-9\.]+)\/(?P<rtt_max>[0-9\.]+)\/[0-9\.]+ ms', ping_output)
|
||||
if result is None:
|
||||
message = ue_header + ': Ping RTT_Min RTT_Avg RTT_Max Not Found!'
|
||||
logging.error('\u001B[1;37;41m ' + message + ' \u001B[0m')
|
||||
return (False, message)
|
||||
rtt_min = result.group('rtt_min')
|
||||
rtt_avg = result.group('rtt_avg')
|
||||
rtt_max = result.group('rtt_max')
|
||||
# TIMEOUT CASE
|
||||
if ping_status < 0:
|
||||
message = 'Ping with UE (' + str(ue.getIP()) + ') crashed due to TIMEOUT!'
|
||||
logging.debug('\u001B[1;37;41m ' + message + ' \u001B[0m')
|
||||
self.ping_iperf_wrong_exit(lock, ue.getIP(), ue.getName(), statusQueue, message)
|
||||
return
|
||||
#search is done on cat result
|
||||
with open(ping_log_file, 'r') as f:
|
||||
ping_output = "".join(f.readlines())
|
||||
result = re.search(', (?P<packetloss>[0-9\.]+)% packet loss, time [0-9\.]+ms', ping_output)
|
||||
if result is None:
|
||||
message = 'Packet Loss Not Found!'
|
||||
logging.debug('\u001B[1;37;41m ' + message + ' \u001B[0m')
|
||||
self.ping_iperf_wrong_exit(lock, ue.getIP(), ue.getName(), statusQueue, message)
|
||||
return
|
||||
packetloss = result.group('packetloss')
|
||||
if float(packetloss) == 100:
|
||||
message = 'Packet Loss is 100%'
|
||||
logging.debug('\u001B[1;37;41m ' + message + ' \u001B[0m')
|
||||
self.ping_iperf_wrong_exit(lock, ue.getIP(), ue.getName(), statusQueue, message)
|
||||
return
|
||||
result = re.search('rtt min\/avg\/max\/mdev = (?P<rtt_min>[0-9\.]+)\/(?P<rtt_avg>[0-9\.]+)\/(?P<rtt_max>[0-9\.]+)\/[0-9\.]+ ms', ping_output)
|
||||
if result is None:
|
||||
message = 'Ping RTT_Min RTT_Avg RTT_Max Not Found!'
|
||||
logging.debug('\u001B[1;37;41m ' + message + ' \u001B[0m')
|
||||
self.ping_iperf_wrong_exit(lock, ue.getIP(), ue.getName(), statusQueue, message)
|
||||
return
|
||||
rtt_min = result.group('rtt_min')
|
||||
rtt_avg = result.group('rtt_avg')
|
||||
rtt_max = result.group('rtt_max')
|
||||
pal_msg = 'Packet Loss : ' + packetloss + '%'
|
||||
min_msg = 'RTT(Min) : ' + rtt_min + ' ms'
|
||||
avg_msg = 'RTT(Avg) : ' + rtt_avg + ' ms'
|
||||
max_msg = 'RTT(Max) : ' + rtt_max + ' ms'
|
||||
|
||||
pal_msg = f'Packet Loss: {packetloss}%'
|
||||
min_msg = f'RTT(Min) : {rtt_min} ms'
|
||||
avg_msg = f'RTT(Avg) : {rtt_avg} ms'
|
||||
max_msg = f'RTT(Max) : {rtt_max} ms'
|
||||
lock.acquire()
|
||||
logging.debug('\u001B[1;37;44m ping result (' + ue.getIP() + ') \u001B[0m')
|
||||
logging.debug('\u001B[1;34m ' + pal_msg + '\u001B[0m')
|
||||
logging.debug('\u001B[1;34m ' + min_msg + '\u001B[0m')
|
||||
logging.debug('\u001B[1;34m ' + avg_msg + '\u001B[0m')
|
||||
logging.debug('\u001B[1;34m ' + max_msg + '\u001B[0m')
|
||||
|
||||
logging.info(f'\u001B[1;37;44m ping result for {ue_header} \u001B[0m')
|
||||
logging.info(f'\u001B[1;34m ' + pal_msg + '\u001B[0m')
|
||||
logging.info(f'\u001B[1;34m ' + min_msg + '\u001B[0m')
|
||||
logging.info(f'\u001B[1;34m ' + avg_msg + '\u001B[0m')
|
||||
logging.info(f'\u001B[1;34m ' + max_msg + '\u001B[0m')
|
||||
#adding extra ping stats from local file
|
||||
#ping_log_file variable is defined above in this function, depending on device/ue
|
||||
ping_stat_msg=''
|
||||
logging.debug('Analyzing Ping log file : ' + os.getcwd() + '/' + ping_log_file)
|
||||
ping_stat=GetPingTimeAnalysis(RAN,ping_log_file,self.ping_rttavg_threshold)
|
||||
|
||||
message = f'{ue_header}\n{pal_msg}\n{min_msg}\n{avg_msg}\n{max_msg}'
|
||||
if (ping_stat!=-1) and (len(ping_stat)!=0):
|
||||
ping_stat_msg+='Ping stats before removing largest value : \n'
|
||||
ping_stat_msg+='RTT(Min) : ' + str("{:.2f}".format(ping_stat['min_0'])) + 'ms \n'
|
||||
ping_stat_msg+='RTT(Mean) : ' + str("{:.2f}".format(ping_stat['mean_0'])) + 'ms \n'
|
||||
ping_stat_msg+='RTT(Median) : ' + str("{:.2f}".format(ping_stat['median_0'])) + 'ms \n'
|
||||
ping_stat_msg+='RTT(Max) : ' + str("{:.2f}".format(ping_stat['max_0'])) + 'ms \n'
|
||||
ping_stat_msg+='Max Index : ' + str(ping_stat['max_loc']) + '\n'
|
||||
ping_stat_msg+='Ping stats after removing largest value : \n'
|
||||
ping_stat_msg+='RTT(Min) : ' + str("{:.2f}".format(ping_stat['min_1'])) + 'ms \n'
|
||||
ping_stat_msg+='RTT(Mean) : ' + str("{:.2f}".format(ping_stat['mean_1'])) + 'ms \n'
|
||||
ping_stat_msg+='RTT(Median) : ' + str("{:.2f}".format(ping_stat['median_1'])) + 'ms \n'
|
||||
ping_stat_msg+='RTT(Max) : ' + str("{:.2f}".format(ping_stat['max_1'])) + 'ms \n'
|
||||
|
||||
#checking packet loss compliance
|
||||
if float(packetloss) > float(self.ping_packetloss_threshold):
|
||||
message += '\nPacket Loss too high'
|
||||
logging.error(f'\u001B[1;37;41m Packet Loss too high; Target: {self.ping_packetloss_threshold}%\u001B[0m')
|
||||
return (False, message)
|
||||
elif float(packetloss) > 0:
|
||||
message += '\nPacket Loss is not 0%'
|
||||
logging.info('\u001B[1;30;43m Packet Loss is not 0% \u001B[0m')
|
||||
#building html message
|
||||
qMsg = pal_msg + '\n' + min_msg + '\n' + avg_msg + '\n' + max_msg + '\n' + ping_stat_msg
|
||||
|
||||
if self.ping_rttavg_threshold != '':
|
||||
if float(rtt_avg) > float(self.ping_rttavg_threshold):
|
||||
ping_rttavg_error_msg = f'RTT(Avg) too high: {rtt_avg} ms; Target: {self.ping_rttavg_threshold} ms'
|
||||
message += '\n' + ping_rttavg_error_msg
|
||||
logging.error('\u001B[1;37;41m'+ ping_rttavg_error_msg +' \u001B[0m')
|
||||
return (False, message)
|
||||
#checking packet loss compliance
|
||||
packetLossOK = True
|
||||
if (packetloss is not None) :
|
||||
if float(packetloss) > float(self.ping_packetloss_threshold):
|
||||
qMsg += '\nPacket Loss too high'
|
||||
logging.debug('\u001B[1;37;41m Packet Loss too high; Target: '+ self.ping_packetloss_threshold + '%\u001B[0m')
|
||||
packetLossOK = False
|
||||
elif float(packetloss) > 0:
|
||||
qMsg += '\nPacket Loss is not 0%'
|
||||
logging.debug('\u001B[1;30;43m Packet Loss is not 0% \u001B[0m')
|
||||
|
||||
return (True, message)
|
||||
#checking RTT avg compliance
|
||||
rttavgOK = True
|
||||
if self.ping_rttavg_threshold != '':
|
||||
if float(rtt_avg)>float(self.ping_rttavg_threshold):
|
||||
ping_rttavg_error_msg = 'RTT(Avg) too high: ' + rtt_avg + ' ms; Target: '+ self.ping_rttavg_threshold+ ' ms'
|
||||
qMsg += '\n'+ping_rttavg_error_msg
|
||||
logging.debug('\u001B[1;37;41m'+ ping_rttavg_error_msg +' \u001B[0m')
|
||||
rttavgOK = False
|
||||
|
||||
if packetLossOK and rttavgOK:
|
||||
statusQueue.put(0)
|
||||
else:
|
||||
statusQueue.put(-1)
|
||||
statusQueue.put(ue.getName())
|
||||
statusQueue.put(ue.getIP())
|
||||
statusQueue.put(qMsg)
|
||||
lock.release()
|
||||
except:
|
||||
logging.debug('exit from Ping_Common except')
|
||||
os.kill(os.getppid(),signal.SIGUSR1)
|
||||
|
||||
def PingNoS1_wrong_exit(self, qMsg,HTML):
|
||||
message = 'OAI UE ping result\n{qMsg}'
|
||||
HTML.CreateHtmlTestRowQueue(self.ping_args, 'KO', [message])
|
||||
|
||||
def PingNoS1(self,HTML,RAN,EPC,CONTAINERS):
|
||||
SSH=sshconnection.SSHConnection()
|
||||
check_eNB = True
|
||||
check_OAI_UE = True
|
||||
ping_from_eNB = re.search('oaitun_enb1', str(self.ping_args))
|
||||
if ping_from_eNB is not None:
|
||||
if RAN.eNBIPAddress == '' or RAN.eNBUserName == '' or RAN.eNBPassword == '':
|
||||
HELP.GenericHelp(CONST.Version)
|
||||
sys.exit('Insufficient Parameter')
|
||||
else:
|
||||
if self.UEIPAddress == '' or self.UEUserName == '' or self.UEPassword == '':
|
||||
HELP.GenericHelp(CONST.Version)
|
||||
sys.exit('Insufficient Parameter')
|
||||
try:
|
||||
if ping_from_eNB is not None:
|
||||
SSH.open(RAN.eNBIPAddress, RAN.eNBUserName, RAN.eNBPassword)
|
||||
SSH.command('cd ' + RAN.eNBSourceCodePath + '/cmake_targets/', '\$', 5)
|
||||
else:
|
||||
SSH.open(self.UEIPAddress, self.UEUserName, self.UEPassword)
|
||||
SSH.command('cd ' + self.UESourceCodePath + '/cmake_targets/', '\$', 5)
|
||||
ping_time = re.findall("-c (\d+)",str(self.ping_args))
|
||||
ping_status = SSH.command('stdbuf -o0 ping ' + self.ping_args + ' 2>&1 | stdbuf -o0 tee ping_' + self.testCase_id + '.log', '\$', int(ping_time[0])*1.5)
|
||||
# TIMEOUT CASE
|
||||
if ping_status < 0:
|
||||
message = 'Ping with OAI UE crashed due to TIMEOUT!'
|
||||
logging.debug('\u001B[1;37;41m ' + message + ' \u001B[0m')
|
||||
self.PingNoS1_wrong_exit(message,HTML)
|
||||
return
|
||||
result = re.search(', (?P<packetloss>[0-9\.]+)% packet loss, time [0-9\.]+ms', SSH.getBefore())
|
||||
if result is None:
|
||||
message = 'Packet Loss Not Found!'
|
||||
logging.debug('\u001B[1;37;41m ' + message + ' \u001B[0m')
|
||||
self.PingNoS1_wrong_exit(message,HTML)
|
||||
return
|
||||
packetloss = result.group('packetloss')
|
||||
if float(packetloss) == 100:
|
||||
message = 'Packet Loss is 100%'
|
||||
logging.debug('\u001B[1;37;41m ' + message + ' \u001B[0m')
|
||||
self.PingNoS1_wrong_exit(message,HTML)
|
||||
return
|
||||
result = re.search('rtt min\/avg\/max\/mdev = (?P<rtt_min>[0-9\.]+)\/(?P<rtt_avg>[0-9\.]+)\/(?P<rtt_max>[0-9\.]+)\/[0-9\.]+ ms', SSH.getBefore())
|
||||
if result is None:
|
||||
message = 'Ping RTT_Min RTT_Avg RTT_Max Not Found!'
|
||||
logging.debug('\u001B[1;37;41m ' + message + ' \u001B[0m')
|
||||
self.PingNoS1_wrong_exit(message,HTML)
|
||||
return
|
||||
rtt_min = result.group('rtt_min')
|
||||
rtt_avg = result.group('rtt_avg')
|
||||
rtt_max = result.group('rtt_max')
|
||||
pal_msg = 'Packet Loss : ' + packetloss + '%'
|
||||
min_msg = 'RTT(Min) : ' + rtt_min + ' ms'
|
||||
avg_msg = 'RTT(Avg) : ' + rtt_avg + ' ms'
|
||||
max_msg = 'RTT(Max) : ' + rtt_max + ' ms'
|
||||
logging.debug('\u001B[1;37;44m OAI UE ping result \u001B[0m')
|
||||
logging.debug('\u001B[1;34m ' + pal_msg + '\u001B[0m')
|
||||
logging.debug('\u001B[1;34m ' + min_msg + '\u001B[0m')
|
||||
logging.debug('\u001B[1;34m ' + avg_msg + '\u001B[0m')
|
||||
logging.debug('\u001B[1;34m ' + max_msg + '\u001B[0m')
|
||||
qMsg = pal_msg + '\n' + min_msg + '\n' + avg_msg + '\n' + max_msg
|
||||
packetLossOK = True
|
||||
if packetloss is not None:
|
||||
if float(packetloss) > float(self.ping_packetloss_threshold):
|
||||
qMsg += '\nPacket Loss too high'
|
||||
logging.debug('\u001B[1;37;41m Packet Loss too high \u001B[0m')
|
||||
packetLossOK = False
|
||||
elif float(packetloss) > 0:
|
||||
qMsg += '\nPacket Loss is not 0%'
|
||||
logging.debug('\u001B[1;30;43m Packet Loss is not 0% \u001B[0m')
|
||||
SSH.close()
|
||||
message = f'OAI UE ping result\n{qMsg}'
|
||||
if packetLossOK:
|
||||
HTML.CreateHtmlTestRowQueue(self.ping_args, 'OK', [message])
|
||||
else:
|
||||
HTML.CreateHtmlTestRowQueue(self.ping_args, 'KO', [message])
|
||||
|
||||
# copying on the EPC server for logCollection
|
||||
if ping_from_eNB is not None:
|
||||
copyin_res = SSH.copyin(RAN.eNBIPAddress, RAN.eNBUserName, RAN.eNBPassword, RAN.eNBSourceCodePath + '/cmake_targets/ping_' + self.testCase_id + '.log', '.')
|
||||
else:
|
||||
copyin_res = SSH.copyin(self.UEIPAddress, self.UEUserName, self.UEPassword, self.UESourceCodePath + '/cmake_targets/ping_' + self.testCase_id + '.log', '.')
|
||||
if (copyin_res == 0):
|
||||
SSH.copyout(EPC.IPAddress, EPC.UserName, EPC.Password, 'ping_' + self.testCase_id + '.log', EPC.SourceCodePath + '/scripts')
|
||||
except:
|
||||
os.kill(os.getppid(),signal.SIGUSR1)
|
||||
|
||||
def Ping(self,HTML,RAN,EPC,CONTAINERS):
|
||||
result = re.search('noS1', str(RAN.Initialize_eNB_args))
|
||||
if result is not None:
|
||||
self.PingNoS1(HTML,RAN,EPC,CONTAINERS)
|
||||
return
|
||||
if EPC.IPAddress == '' or EPC.UserName == '' or EPC.Password == '' or EPC.SourceCodePath == '':
|
||||
HELP.GenericHelp(CONST.Version)
|
||||
sys.exit('Insufficient Parameter')
|
||||
check_eNB = True
|
||||
if (len(self.UEDevices) == 1) and (self.UEDevices[0] == 'OAI-UE'):
|
||||
check_OAI_UE = True
|
||||
else:
|
||||
check_OAI_UE = False
|
||||
|
||||
if self.ue_ids == []:
|
||||
raise Exception("no module names in self.ue_ids provided")
|
||||
|
||||
ues = [cls_module_ue.Module_UE(n.strip()) for n in self.ue_ids]
|
||||
ues = []
|
||||
for ue_id in self.ue_ids:
|
||||
ue = cls_module_ue.Module_UE(ue_id)
|
||||
if not ue.getIP():
|
||||
logging.error("no IP addresses returned")
|
||||
HTML.CreateHtmlTestRow(self.ping_args, 'KO', len(self.UEDevices), html_queue)
|
||||
self.AutoTerminateUEandeNB(HTML,RAN,EPC,CONTAINERS)
|
||||
ues.append(ue)
|
||||
logging.debug(ues)
|
||||
with concurrent.futures.ThreadPoolExecutor() as executor:
|
||||
futures = [executor.submit(self.Ping_common, EPC, ue, RAN) for ue in ues]
|
||||
results = [f.result() for f in futures]
|
||||
# each result in results is a tuple, first member goes to successes, second to messages
|
||||
successes, messages = map(list, zip(*results))
|
||||
if len(successes) == len(ues) and all(successes):
|
||||
HTML.CreateHtmlTestRowQueue(self.ping_args, 'OK', messages)
|
||||
else:
|
||||
HTML.CreateHtmlTestRowQueue(self.ping_args, 'KO', messages)
|
||||
|
||||
multi_jobs = []
|
||||
i = 0
|
||||
lock = Lock()
|
||||
status_queue = SimpleQueue()
|
||||
for ue in ues:
|
||||
p = Process(target = self.Ping_common, args = (lock,status_queue,EPC,ue,RAN,))
|
||||
p.daemon = True
|
||||
p.start()
|
||||
multi_jobs.append(p)
|
||||
i = i + 1
|
||||
for job in multi_jobs:
|
||||
job.join()
|
||||
|
||||
if (status_queue.empty()):
|
||||
HTML.CreateHtmlTestRow(self.ping_args, 'KO', CONST.ALL_PROCESSES_OK)
|
||||
self.AutoTerminateUEandeNB(HTML,RAN,EPC,CONTAINERS)
|
||||
else:
|
||||
ping_status = True
|
||||
messages = []
|
||||
while (not status_queue.empty()):
|
||||
count = status_queue.get()
|
||||
if (count < 0):
|
||||
ping_status = False
|
||||
device_id = status_queue.get()
|
||||
ip_addr = status_queue.get()
|
||||
message = status_queue.get()
|
||||
messages.append(f'UE ({device_id})\nIP Address : {ip_addr}\n{message}')
|
||||
if (ping_status):
|
||||
HTML.CreateHtmlTestRowQueue(self.ping_args, 'OK', messages)
|
||||
else:
|
||||
HTML.CreateHtmlTestRowQueue(self.ping_args, 'KO', messages)
|
||||
self.AutoTerminateUEandeNB(HTML,RAN,EPC,CONTAINERS)
|
||||
|
||||
def Iperf_ComputeTime(self):
|
||||
result = re.search('-t (?P<iperf_time>\d+)', str(self.iperf_args))
|
||||
@@ -995,9 +1233,7 @@ class OaiCiTest():
|
||||
cn_target_ip = result.group('trf_ip_addr')
|
||||
SSH.close()
|
||||
cn_iperf_prefix = "docker exec prod-trf-gen" # -w /iperf-2.0.13 necessary?
|
||||
if (re.match('OC-OAI-CN5G', EPC.Type, re.IGNORECASE)):
|
||||
cn_target_ip = "172.21.6.102"
|
||||
else: # lteboix, sabox
|
||||
else: # ltebox, sabox
|
||||
cn_target_ip = "192.172.0.1"
|
||||
cn_iperf_prefix = ""
|
||||
|
||||
@@ -1079,20 +1315,6 @@ class OaiCiTest():
|
||||
|
||||
self.Iperf_analyzeV2BIDIR(lock, ue.getHost(), ue.getName(), statusQueue, server_filename, client_filename)
|
||||
|
||||
elif self.iperf_direction == "IPERF3":
|
||||
cmd = cls_cmd.getConnection(ue.getHost())
|
||||
cmd.run(f'rm /tmp/{server_filename}', reportNonZero=False)
|
||||
port = f'{5002+idx}'
|
||||
cmd.run(f'{ue.getCmdPrefix()} iperf3 -c {cn_target_ip} -p {port} {iperf_opt} --get-server-output &> /tmp/{server_filename}', timeout=iperf_time*1.5)
|
||||
cmd.copyin(f'/tmp/{server_filename}', server_filename)
|
||||
cmd.close()
|
||||
if udpIperf:
|
||||
self.Iperf_analyzeV2Server(lock, ue.getIP(), ue.getName(), statusQueue, iperf_opt, server_filename, 1)
|
||||
else:
|
||||
cmd = cls_cmd.getConnection(EPC.IPAddress)
|
||||
self.Iperf_analyzeV2TCPOutput(lock, ue.getIP(), ue.getName(), statusQueue, iperf_opt, EPC, cmd, f'/tmp/{server_filename}')
|
||||
cmd.close()
|
||||
|
||||
else :
|
||||
raise Exception("Incorrect or missing IPERF direction in XML")
|
||||
|
||||
@@ -1232,6 +1454,7 @@ class OaiCiTest():
|
||||
#result = re.search('iperf version 2.0.10', str(iperfStdout.strip()))
|
||||
#if result is not None:
|
||||
# dummyIperfVersion = '2.0.10'
|
||||
|
||||
multi_jobs = []
|
||||
ue_num = len(ues)
|
||||
i = 0
|
||||
|
||||
@@ -200,7 +200,7 @@ MACRLCs = (
|
||||
pusch_TargetSNRx10 = 200;
|
||||
pucch_TargetSNRx10 = 200;
|
||||
ulsch_max_frame_inactivity = 10;
|
||||
ul_max_mcs = 28;
|
||||
ul_max_mcs = 15;
|
||||
}
|
||||
);
|
||||
|
||||
|
||||
@@ -75,6 +75,7 @@ class EPCManagement():
|
||||
self.OCRegistry = "default-route-openshift-image-registry.apps.oai.cs.eurecom.fr/"
|
||||
self.OCUserName = ''
|
||||
self.OCPassword = ''
|
||||
self.OCProjectName = ''
|
||||
self.imageToPull = ''
|
||||
self.eNBSourceCodePath = ''
|
||||
|
||||
@@ -239,9 +240,9 @@ class EPCManagement():
|
||||
HTML.CreateHtmlTestRow(self.Type, 'OK', CONST.ALL_PROCESSES_OK)
|
||||
|
||||
def Initialize5GCN(self, HTML):
|
||||
if self.IPAddress == '' or self.UserName == '' or self.Password == '' or self.Type == '':
|
||||
if self.IPAddress == '' or self.UserName == '' or self.Password == '' or self.SourceCodePath == '' or self.Type == '':
|
||||
HELP.GenericHelp(CONST.Version)
|
||||
HELP.EPCSrvHelp(self.IPAddress, self.UserName, self.Password, self.Type)
|
||||
HELP.EPCSrvHelp(self.IPAddress, self.UserName, self.Password, self.SourceCodePath, self.Type)
|
||||
sys.exit('Insufficient EPC Parameters')
|
||||
mySSH = cls_cmd.getConnection(self.IPAddress)
|
||||
html_cell = ''
|
||||
@@ -298,8 +299,8 @@ class EPCManagement():
|
||||
imageNames = ["oai-nrf", "oai-amf", "oai-smf", "oai-spgwu-tiny", "oai-ausf", "oai-udm", "oai-udr", "mysql","oai-traffic-server"]
|
||||
logging.debug('Deploying OAI CN5G on Openshift Cluster')
|
||||
lIpAddr = self.IPAddress
|
||||
lSourcePath = "/opt/oai-cn5g-fed-develop-2023-04-28-20897"
|
||||
succeeded = OC.OC_login(mySSH, self.OCUserName, self.OCPassword, OC.CI_OC_CORE_NAMESPACE)
|
||||
lSourcePath = self.SourceCodePath
|
||||
succeeded = OC.OC_login(mySSH, self.OCUserName, self.OCPassword, self.OCProjectName)
|
||||
if not succeeded:
|
||||
logging.error('\u001B[1m OC Cluster Login Failed\u001B[0m')
|
||||
HTML.CreateHtmlTestRow('N/A', 'KO', CONST.OC_LOGIN_FAIL)
|
||||
@@ -598,7 +599,7 @@ class EPCManagement():
|
||||
mySSH.run(f'rm -Rf {lSourcePath}/logs')
|
||||
mySSH.run(f'mkdir -p {lSourcePath}/logs')
|
||||
logging.debug('OC OAI CN5G - Collecting Log files to workspace')
|
||||
succeeded = OC.OC_login(mySSH, self.OCUserName, self.OCPassword, OC.CI_OC_CORE_NAMESPACE)
|
||||
succeeded = OC.OC_login(mySSH, self.OCUserName, self.OCPassword, self.OCProjectName)
|
||||
if not succeeded:
|
||||
logging.error('\u001B[1m OC Cluster Login Failed\u001B[0m')
|
||||
HTML.CreateHtmlTestRow('N/A', 'KO', CONST.OC_LOGIN_FAIL)
|
||||
@@ -617,7 +618,7 @@ class EPCManagement():
|
||||
mySSH.run(f'cd {lSourcePath}/logs && zip -r -qq test_logs_CN.zip *.log')
|
||||
mySSH.copyin(f'{lSourcePath}/logs/test_logs_CN.zip','test_logs_CN.zip')
|
||||
ret = mySSH.run(f'oc get pods', silent=True)
|
||||
res = re.search(f'No resources found in {OC.CI_OC_CORE_NAMESPACE} namespace.', ret.stdout)
|
||||
res = re.search('No resources found in oaicicd-ran namespace.', ret.stdout)
|
||||
if res is not None:
|
||||
logging.debug('OC OAI CN5G components uninstalled')
|
||||
message = 'OC OAI CN5G components uninstalled'
|
||||
|
||||
341
ci-scripts/run_sl_test.py
Executable file
341
ci-scripts/run_sl_test.py
Executable file
@@ -0,0 +1,341 @@
|
||||
#!/usr/bin/env python3
|
||||
#
|
||||
# Automated tests for running 5G NR Sidelink SyncRef UE and/or Nearby UE.
|
||||
# The following is an example to run remote machine (nearby) three times.
|
||||
# The syncref UE is launched on the current machine, and a single
|
||||
# nearby UE is launched on the machine specified by the --host and
|
||||
# --user flags. The -r will enable this simulation to be repeated
|
||||
# three times.
|
||||
#
|
||||
# python3 run_sl_test.py --user account --host 10.1.1.68 -r 3
|
||||
#
|
||||
# The following is an example to run just a Sidelink Nearby UE.
|
||||
# By specifying -l nearby, only the nearby UE will be launched
|
||||
# on the machine specified by the --host and --user flags.
|
||||
# The -r will enable this simulation to be repeated two times.
|
||||
#
|
||||
# python3 run_sl_test.py -l nearby --user account --host 10.1.1.68 -r 2
|
||||
#
|
||||
# See `--help` for more information.
|
||||
#
|
||||
|
||||
import os
|
||||
import sys
|
||||
import argparse
|
||||
import logging
|
||||
import time
|
||||
import re
|
||||
import glob
|
||||
import subprocess
|
||||
from subprocess import Popen
|
||||
import threading
|
||||
from typing import Dict
|
||||
from queue import *
|
||||
from sl_check_log import LogChecker
|
||||
|
||||
HOME_DIR = os.path.expanduser( '~' )
|
||||
|
||||
# ----------------------------------------------------------------------------
|
||||
# Command line argument parsing
|
||||
|
||||
parser = argparse.ArgumentParser(description="""
|
||||
Automated tests for 5G NR Sidelink simulations
|
||||
""")
|
||||
|
||||
parser.add_argument('--launch', '-l', default='both', choices='syncref nearby both'.split(), help="""
|
||||
Sidelink UE type to launch test scenario (default: %(default)s)
|
||||
""")
|
||||
|
||||
parser.add_argument('--host', default='10.1.1.80', type=str, help="""
|
||||
Nearby Host IP (default: %(default)s)
|
||||
""")
|
||||
|
||||
parser.add_argument('--user', '-u', default='zaid', type=str, help="""
|
||||
User id in Nearby Host (default: %(default)s)
|
||||
""")
|
||||
|
||||
parser.add_argument('--repeat', '-r', default=1, type=int, help="""
|
||||
The number of repeated test iterations (default: %(default)s)
|
||||
""")
|
||||
|
||||
parser.add_argument('--basic', '-b', action='store_true', help="""
|
||||
Basic test with basic shell commands
|
||||
""")
|
||||
|
||||
parser.add_argument('--commands', default='sl_cmds.txt', help="""
|
||||
The USRP Commands .txt file (default: %(default)s)
|
||||
""")
|
||||
|
||||
parser.add_argument('--duration', '-d', metavar='SECONDS', type=int, default=30, help="""
|
||||
How long to run the test before stopping to examine the logs
|
||||
""")
|
||||
|
||||
parser.add_argument('--nid1', type=int, default=10, help="""
|
||||
Nid1 value
|
||||
""")
|
||||
|
||||
parser.add_argument('--nid2', type=int, default=1, help="""
|
||||
Nid2 value
|
||||
""")
|
||||
|
||||
parser.add_argument('--log-dir', default=HOME_DIR, help="""
|
||||
Where to store log files
|
||||
""")
|
||||
|
||||
parser.add_argument('--compress', action='store_true', help="""
|
||||
Compress the log files in the --log-dir
|
||||
""")
|
||||
|
||||
parser.add_argument('--no-run', '-n', action='store_true', help="""
|
||||
Don't run the test, only examine the logs in the --log-dir
|
||||
directory from a previous run of the test
|
||||
""")
|
||||
|
||||
parser.add_argument('--debug', action='store_true', help="""
|
||||
Enable debug logging (for this script only)
|
||||
""")
|
||||
|
||||
parser.add_argument('--test', '-t', default='usrp', choices='psbchsim rfsim usrp'.split(), help="""
|
||||
The kind of test scenario to run. The options include psbchsim, rfsim, or usrp. (default: %(default)s)
|
||||
""")
|
||||
|
||||
OPTS = parser.parse_args()
|
||||
del parser
|
||||
|
||||
logging.basicConfig(level=logging.DEBUG if OPTS.debug else logging.INFO,
|
||||
format='>>> %(name)s: %(levelname)s: %(message)s')
|
||||
LOGGER = logging.getLogger(os.path.basename(sys.argv[0]))
|
||||
|
||||
# ----------------------------------------------------------------------------
|
||||
def redirect_output(cmd: str, filename: str) -> str:
|
||||
cmd += ' >{} 2>&1'.format(filename)
|
||||
return cmd
|
||||
|
||||
def thread_delay(thread_name: str, delay: int) -> None:
|
||||
count = 0
|
||||
while count < 1:
|
||||
time.sleep(delay)
|
||||
count += 1
|
||||
|
||||
class Command:
|
||||
"""
|
||||
Parsing USRP commands file
|
||||
"""
|
||||
def __init__(self, filename) -> None:
|
||||
self.check_user()
|
||||
self.filename = self.check_file(filename)
|
||||
self.parse_commands()
|
||||
|
||||
def check_user(self) -> None:
|
||||
if OPTS.test != 'usrp': return
|
||||
if OPTS.launch != 'syncref' and OPTS.user == '':
|
||||
LOGGER.error("--user followed by [user id] is mandatory to connect to remote machine")
|
||||
sys.exit(1)
|
||||
|
||||
def check_file(self, filename) -> str:
|
||||
data_file = glob.glob(filename)
|
||||
if data_file:
|
||||
return filename
|
||||
else:
|
||||
LOGGER.error(f'The file {filename} does not exist!')
|
||||
sys.exit(1)
|
||||
|
||||
def parse_commands(self) -> None:
|
||||
"""
|
||||
Scan the provided commands file.
|
||||
"""
|
||||
self.launch_cmds: Dict[str, str] = {}
|
||||
if OPTS.test == 'usrp':
|
||||
launch_cmds_re = re.compile(r'^\s*(\S*)usrp\S*\s*=\s*((\S+\s*)*)')
|
||||
elif OPTS.test == 'rfsim':
|
||||
launch_cmds_re = re.compile(r'^\s*(\S*)rfsim\S*\s*=\s*((\S+\s*)*)')
|
||||
elif OPTS.test == 'psbchsim':
|
||||
launch_cmds_re = re.compile(r'^\s*(\S*)psbchsim\S*\s*=\s*((\S+\s*)*)')
|
||||
else:
|
||||
LOGGER.error("Provided test option not valid! %s", OPTS.test)
|
||||
exit(1)
|
||||
|
||||
with open(self.filename, 'rt') as fh:
|
||||
nearby_cmd_continued = False
|
||||
syncref_cmd_continued = False
|
||||
for line in fh:
|
||||
if line == '\n': continue
|
||||
match = launch_cmds_re.match(line)
|
||||
if match:
|
||||
host_role = match.group(1)
|
||||
launch_cmds = match.group(2)
|
||||
if host_role.lower().startswith('nearby'):
|
||||
nearby_cmd_continued = True
|
||||
continue
|
||||
if host_role.lower().startswith('syncref'):
|
||||
syncref_cmd_continued = True
|
||||
continue
|
||||
elif nearby_cmd_continued:
|
||||
launch_cmds += line
|
||||
if not line.strip().endswith('\\'):
|
||||
self.launch_cmds['nearby'] = launch_cmds
|
||||
LOGGER.debug('Nearby cmd is %s', launch_cmds)
|
||||
nearby_cmd_continued = False
|
||||
continue
|
||||
elif syncref_cmd_continued:
|
||||
launch_cmds += line
|
||||
if not line.strip().endswith('\\'):
|
||||
self.launch_cmds['syncref'] = launch_cmds
|
||||
LOGGER.debug('Syncref cmd is %s', launch_cmds)
|
||||
syncref_cmd_continued = False
|
||||
continue
|
||||
else:
|
||||
LOGGER.debug('Unmatched line %r', line)
|
||||
continue
|
||||
if self.launch_cmds == {}:
|
||||
LOGGER.error(f'usrp commands are not found in file: {self.filename} ')
|
||||
exit()
|
||||
|
||||
class TestThread(threading.Thread):
|
||||
"""
|
||||
Represents TestThread
|
||||
"""
|
||||
def __init__(self, queue, commands, passed, log_agent):
|
||||
threading.Thread.__init__(self)
|
||||
self.queue = queue
|
||||
self.commands = commands
|
||||
self.passed = passed
|
||||
self.delay = 0
|
||||
self.log_file = log_agent.txlog_file_path
|
||||
self.log_agent = log_agent
|
||||
|
||||
def run(self):
|
||||
if self.queue.empty() == True:
|
||||
LOGGER.error("Queue is empty!")
|
||||
sys.exit(1)
|
||||
try:
|
||||
while not self.queue.empty():
|
||||
job = self.queue.get()
|
||||
if "nearby" == job:
|
||||
thread_delay(job, delay = 0)
|
||||
self.launch_nearby(job)
|
||||
if "syncref" == job and not OPTS.no_run:
|
||||
thread_delay(job, delay = self.delay)
|
||||
self.launch_syncref(job)
|
||||
self.queue.task_done()
|
||||
except Exception as inst:
|
||||
LOGGER.info(f"Failed to operate on job with type {type(inst)} and args {inst.args}")
|
||||
|
||||
def launch_syncref(self, job) -> Popen:
|
||||
LOGGER.info('Launching SyncRef UE')
|
||||
if OPTS.basic: cmd = redirect_output('uname -a', self.log_file)
|
||||
else: cmd = self.commands.launch_cmds[job]
|
||||
proc = Popen(cmd, shell=True)
|
||||
LOGGER.info(f"syncref_proc = {proc}")
|
||||
if not OPTS.basic and not OPTS.no_run:
|
||||
LOGGER.info(f"Process running... {job}")
|
||||
time.sleep(OPTS.duration)
|
||||
self.kill_process("syncref", proc)
|
||||
|
||||
def launch_nearby(self, job, host=OPTS.host, user=OPTS.user) -> Popen:
|
||||
LOGGER.info('#' * 42)
|
||||
LOGGER.info('Launching Nearby UE')
|
||||
if OPTS.basic: cmd = redirect_output('uname -a', self.log_file)
|
||||
else: cmd = self.commands.launch_cmds[job]
|
||||
if OPTS.test == 'usrp':
|
||||
cmd = cmd[:-1] + f' -d {OPTS.duration} --nid1 {OPTS.nid1} --nid2 {OPTS.nid2}'
|
||||
proc = Popen(["ssh", f"{user}@{host}", cmd],
|
||||
shell=False,
|
||||
stdout=subprocess.PIPE,
|
||||
stderr=subprocess.PIPE)
|
||||
LOGGER.info(f"nearby_proc = {proc}")
|
||||
remote_output = proc.stdout.readlines()
|
||||
if remote_output == []:
|
||||
nearby_result = proc.stderr.readlines()
|
||||
else:
|
||||
nearby_result = remote_output
|
||||
self.kill_process("nearby", proc)
|
||||
if nearby_result:
|
||||
self.find_nearby_result_metric(nearby_result)
|
||||
else:
|
||||
proc = Popen(cmd, shell=True)
|
||||
LOGGER.info(f"nearby_proc = {proc}")
|
||||
if not OPTS.basic and not OPTS.no_run:
|
||||
LOGGER.info(f"Process running... {job}")
|
||||
time.sleep(OPTS.duration)
|
||||
self.kill_process("nearby", proc)
|
||||
nearby_result = self.log_agent.analyze_nearby_logs(OPTS.nid1, OPTS.nid2)
|
||||
if nearby_result:
|
||||
self.find_nearby_result_metric(nearby_result)
|
||||
|
||||
def find_nearby_result_metric(self, remote_log):
|
||||
result_metric = None
|
||||
for line in remote_log:
|
||||
if type(line) is not str:
|
||||
line = line.decode()
|
||||
if OPTS.test == 'usrp':
|
||||
LOGGER.info(line.strip())
|
||||
# 'SyncRef UE found. RSRP: -100 dBm/RE. It took {delta_time_s} seconds'
|
||||
if 'SyncRef UE found' in line:
|
||||
fields = line.split(maxsplit=12)
|
||||
if len(fields) > 6:
|
||||
ssb_rsrp = float(fields[-6])
|
||||
sync_duration = float(fields[-2])
|
||||
counting_duration = sync_duration - self.delay
|
||||
result_metric = (ssb_rsrp, sync_duration, counting_duration)
|
||||
self.passed += [result_metric]
|
||||
return
|
||||
|
||||
def kill_process(self, job: str, proc: Popen) -> None:
|
||||
# Wait for the processes to end
|
||||
LOGGER.info(f'kill main simulation processes... {job}')
|
||||
cmd = ['sudo', 'killall']
|
||||
cmd.append('-KILL')
|
||||
if proc:
|
||||
cmd.append('nr-uesoftmodem')
|
||||
if "syncref" == job:
|
||||
subprocess.run(cmd)
|
||||
LOGGER.info(f'Waiting for PID proc.pid for {job}')
|
||||
proc.kill()
|
||||
proc.wait()
|
||||
LOGGER.info(f'kill main simulation processes...done for {job}')
|
||||
|
||||
# ----------------------------------------------------------------------------
|
||||
|
||||
def main() -> int:
|
||||
commands = Command(OPTS.commands)
|
||||
log_agent = LogChecker(OPTS, LOGGER)
|
||||
LOGGER.debug(f'Number of iterations {OPTS.repeat}')
|
||||
if commands.launch_cmds is not None:
|
||||
for role, cmd in commands.launch_cmds.items():
|
||||
LOGGER.debug(f'{role} UE: {cmd}')
|
||||
jobs = ['nearby', 'syncref'] if OPTS.launch == 'both' else [OPTS.launch]
|
||||
passed_metric = []
|
||||
num_tx_ssb = []
|
||||
num_passed = 0
|
||||
for i in range(OPTS.repeat):
|
||||
threads = []
|
||||
queue = Queue()
|
||||
for job in jobs:
|
||||
queue.put(job)
|
||||
th = TestThread(queue, commands, passed_metric, log_agent)
|
||||
th.setDaemon(True)
|
||||
th.start()
|
||||
threads.append(th)
|
||||
for th in threads:
|
||||
th.join()
|
||||
if num_passed != len(passed_metric):
|
||||
# Examine the logs to determine if the test passed
|
||||
(ssb_rsrp, sync_duration, counting_duration) = passed_metric[-1]
|
||||
num_ssb = log_agent.analyze_syncref_logs(counting_duration)
|
||||
num_tx_ssb += [num_ssb]
|
||||
LOGGER.info(f"Trial {i+1}/{OPTS.repeat} PASSED. {num_ssb} SSB(s) were generated. Measured {ssb_rsrp} RSRP (dbm/RE)")
|
||||
else:
|
||||
LOGGER.info(f"Failure detected during {i+1}/{OPTS.repeat} trial(s).")
|
||||
num_passed = len(passed_metric)
|
||||
|
||||
LOGGER.info('#' * 42)
|
||||
LOGGER.info(f"Number of passed = {len(passed_metric)}/{OPTS.repeat}")
|
||||
if len(num_tx_ssb) > 0:
|
||||
LOGGER.info(f"Avg number of SSB = {sum(num_tx_ssb) / len(num_tx_ssb)} ({num_tx_ssb})")
|
||||
if len(passed_metric) > 0:
|
||||
LOGGER.info(f"Avg SSB RSRP = {sum([result[0] for result in passed_metric]) / len(passed_metric)}")
|
||||
LOGGER.info(f"Avg Sync duration (seconds) = {sum([result[1] for result in passed_metric]) / len(passed_metric)}")
|
||||
return 0
|
||||
|
||||
sys.exit(main())
|
||||
112
ci-scripts/sl_check_log.py
Executable file
112
ci-scripts/sl_check_log.py
Executable file
@@ -0,0 +1,112 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
import os
|
||||
import bz2
|
||||
import logging
|
||||
from typing import Optional, List, Generator
|
||||
|
||||
class LogChecker():
|
||||
def __init__(self, OPTS, LOGGER):
|
||||
self.OPTS = OPTS
|
||||
self.LOGGER = LOGGER
|
||||
self.rxlog_file_path = os.path.join(OPTS.log_dir, 'rx.log')
|
||||
self.txlog_file_path = os.path.join(OPTS.log_dir, 'tx.log')
|
||||
|
||||
def get_lines(self, filename: str) -> Generator[str, None, None]:
|
||||
"""
|
||||
Yield each line of the given log file (.bz2 compressed log file if -c flag is used.)
|
||||
"""
|
||||
fh = bz2.open(filename, 'rb') if self.OPTS.compress else open(filename, 'rb')
|
||||
for line_bytes in fh:
|
||||
line = line_bytes.decode('utf-8', 'backslashreplace')
|
||||
line = line.rstrip('\r\n')
|
||||
yield line
|
||||
|
||||
def get_analysis_messages_nearby(self, filename: str) -> Generator[str, None, None]:
|
||||
"""
|
||||
Finding all logs in the log file with X fields for log parsing optimization
|
||||
"""
|
||||
self.LOGGER.info('Scanning %s', filename)
|
||||
for line in self.get_lines(filename):
|
||||
#796821.854505 [NR_PHY] SyncRef UE found with Nid1 10 and Nid2 1 SS-RSRP 100 dBm/RE
|
||||
#796811.532881 [NR_PHY] nrUE configured
|
||||
fields = line.split(maxsplit=10)
|
||||
if len(fields) == 11 or len(fields) == 4:
|
||||
yield line
|
||||
|
||||
def analyze_nearby_logs(self, exp_nid1: int, exp_nid2: int) -> bool:
|
||||
found = set()
|
||||
est_nid1, est_nid2, time_start_s, time_end_s = -1, -1, -1, -1
|
||||
ssb_rsrp = 0
|
||||
log_file = self.rxlog_file_path
|
||||
result = None
|
||||
|
||||
if self.OPTS.compress:
|
||||
log_file = f'{log_file}.bz2'
|
||||
for line in self.get_analysis_messages_nearby(log_file):
|
||||
#796821.854505 [NR_PHY] SyncRef UE found with Nid1 10 and Nid2 1 SS-RSRP -100 dBm/RE
|
||||
#796811.532881 [NR_PHY] nrUE configured
|
||||
if 'SyncRef UE found' in line and 'Nid1' in line and 'Nid2' in line:
|
||||
num_split = 13 if 'RSRP' in line else 10
|
||||
fields = line.split(maxsplit=num_split)
|
||||
est_nid1 = int(fields[7])
|
||||
est_nid2 = int(fields[10])
|
||||
if 'RSRP' in line:
|
||||
ssb_rsrp = int(fields[12])
|
||||
found.add('found')
|
||||
time_end_s = float(fields[0])
|
||||
break
|
||||
if time_start_s == -1 and 'nrUE configured' in line:
|
||||
fields = line.split(maxsplit=3)
|
||||
time_start_s = float(fields[0])
|
||||
|
||||
|
||||
self.LOGGER.debug('found: %r', found)
|
||||
if len(found) != 1:
|
||||
self.LOGGER.error(f'Failed -- No SyncRef UE found.')
|
||||
return
|
||||
elif exp_nid1 != est_nid1 or exp_nid2 != est_nid2:
|
||||
self.LOGGER.error(f'Failed -- found SyncRef UE Nid1 {est_nid1}, Ni2 {est_nid2}, expecting Nid1 {exp_nid1}, Nid2 {exp_nid2}')
|
||||
return
|
||||
if time_start_s == -1:
|
||||
self.LOGGER.error(f'Failed -- No start time found! Fix log and re-run!')
|
||||
return
|
||||
|
||||
delta_time_s = time_end_s - time_start_s
|
||||
result = f'SyncRef UE found. RSRP: {ssb_rsrp} dBm/RE. It took {delta_time_s} seconds'
|
||||
self.LOGGER.info(result)
|
||||
return [result]
|
||||
|
||||
|
||||
def get_analysis_messages_syncref(self, filename: str) -> Generator[str, None, None]:
|
||||
"""
|
||||
Finding all logs in the log file with X fields for log parsing optimization
|
||||
"""
|
||||
self.LOGGER.info('Scanning %s', filename)
|
||||
for line in self.get_lines(filename):
|
||||
#796811.532881 [NR_PHY] nrUE configured
|
||||
#796821.854505 [NR_PHY] PSBCH SL generation started
|
||||
fields = line.split(maxsplit=5)
|
||||
if len(fields) == 4 or len(fields) == 6 :
|
||||
yield line
|
||||
|
||||
def analyze_syncref_logs(self, counting_delta: float) -> int:
|
||||
time_start_s, time_end_s = -1, -1
|
||||
log_file = self.txlog_file_path
|
||||
sum_ssb = 0
|
||||
|
||||
if self.OPTS.compress:
|
||||
tx_log_file = f'{log_file}.bz2'
|
||||
for line in self.get_analysis_messages_syncref(log_file):
|
||||
#796811.532881 [NR_PHY] nrUE configured
|
||||
#796821.854505 [NR_PHY] PSBCH SL generation started
|
||||
if time_start_s == -1 and 'nrUE configured' in line:
|
||||
fields = line.split(maxsplit=2)
|
||||
time_start_s = float(fields[0])
|
||||
time_end_s = time_start_s + counting_delta
|
||||
if 'PSBCH SL generation started' in line:
|
||||
fields = line.split(maxsplit=2)
|
||||
time_st = float(''.join([ch for ch in fields[0] if ch.isnumeric() or ch =='.']))
|
||||
if time_st < time_end_s:
|
||||
sum_ssb += 1
|
||||
return sum_ssb
|
||||
45
ci-scripts/sl_cmds.txt
Normal file
45
ci-scripts/sl_cmds.txt
Normal file
@@ -0,0 +1,45 @@
|
||||
# The lines containing 'usrp' and starts with 'syncref' or 'nearby' will be valid until it does not contain backspace.
|
||||
|
||||
####################
|
||||
#### USRP ####
|
||||
####################
|
||||
|
||||
### RX Nearby UE ###
|
||||
nearby_usrp_cmd = cd $HOME/openairinterface5g/ci-scripts; \
|
||||
python3 sl_rx_agent.py --cmd \
|
||||
'sudo -E LD_LIBRARY_PATH=$HOME/openairinterface5g/cmake_targets/ran_build/build:$LD_LIBRARY_PATH \
|
||||
$HOME/openairinterface5g/cmake_targets/ran_build/build/nr-uesoftmodem \
|
||||
--sl-mode 2 -r 106 --numerology 1 --band 38 --SLC 2600000000 --ue-rxgain 90 \
|
||||
--usrp-args "type=n3xx,addr=192.168.20.2,subdev=A:0,master_clock_rate=122.88e6" \
|
||||
--log_config.global_log_options time,nocolor \
|
||||
> ~/rx.log 2>&1'
|
||||
|
||||
### TX SyncRef UE ###
|
||||
|
||||
syncref_usrp_cmd = \
|
||||
sudo -E LD_LIBRARY_PATH=$HOME/openairinterface5g/cmake_targets/ran_build/build:$LD_LIBRARY_PATH \
|
||||
$HOME/openairinterface5g/cmake_targets/ran_build/build/nr-uesoftmodem \
|
||||
--sl-mode 2 --sync-ref -r 106 --numerology 1 --band 38 --SLC 2600000000 --ue-txgain 8 \
|
||||
--usrp-args "type=n3xx,addr=192.168.10.2,subdev=A:0,master_clock_rate=122.88e6" \
|
||||
--log_config.global_log_options time,nocolor\
|
||||
> ~/tx.log 2>&1
|
||||
|
||||
####################
|
||||
#### RFSIM ####
|
||||
####################
|
||||
|
||||
### RX Nearby UE ###
|
||||
nearby_rfsim_cmd = \
|
||||
sudo -E RFSIMULATOR=127.0.0.1 \
|
||||
$HOME/openairinterface5g/cmake_targets/ran_build/build/nr-uesoftmodem \
|
||||
--rfsim --sl-mode 2 --rfsimulator.serverport 4048 \
|
||||
--log_config.global_log_options time,nocolor \
|
||||
> ~/rx.log 2>&1
|
||||
|
||||
### TX SyncRef UE ###
|
||||
syncref_rfsim_cmd = \
|
||||
sudo -E RFSIMULATOR=server \
|
||||
$HOME/openairinterface5g/cmake_targets/ran_build/build/nr-uesoftmodem \
|
||||
--sync-ref --rfsim --sl-mode 2 --rfsimulator.serverport 4048 \
|
||||
--log_config.global_log_options time,nocolor \
|
||||
> ~/tx.log 2>&1
|
||||
218
ci-scripts/sl_rx_agent.py
Executable file
218
ci-scripts/sl_rx_agent.py
Executable file
@@ -0,0 +1,218 @@
|
||||
#!/usr/bin/env python3
|
||||
#
|
||||
# Automated tests for running 5G NR Sidelink Nearby UE.
|
||||
# The following is an example to run this script.
|
||||
#
|
||||
# python3 sl_rx_agent.py \
|
||||
# --cmd 'sudo -E LD_LIBRARY_PATH=$HOME/openairinterface5g/cmake_targets/ran_build/build:$LD_LIBRARY_PATH \
|
||||
# $HOME/openairinterface5g/cmake_targets/ran_build/build/nr-uesoftmodem \
|
||||
# --sl-mode 2 -r 106 --numerology 1 --band 38 -C 2600000000 --ue-rxgain 90 \
|
||||
# --usrp-args "type=n3xx,addr=192.168.20.2,subdev=A:0,master_clock_rate=122.88e6" \
|
||||
# > ~/rx.log 2>&1' \
|
||||
# --nid1 10 --nid2 1
|
||||
#
|
||||
# See `--help` for more information.
|
||||
#
|
||||
|
||||
import os
|
||||
import sys
|
||||
import argparse
|
||||
import logging
|
||||
import time
|
||||
import glob
|
||||
import bz2
|
||||
import subprocess
|
||||
from subprocess import Popen
|
||||
from typing import Optional, List
|
||||
from sl_check_log import LogChecker
|
||||
|
||||
HOME_DIR = os.path.expanduser( '~' )
|
||||
# ----------------------------------------------------------------------------
|
||||
# Command line argument parsing
|
||||
|
||||
parser = argparse.ArgumentParser(description="""
|
||||
Automated tests for 5G NR Sidelink Rx simulations
|
||||
""")
|
||||
|
||||
parser.add_argument('--duration', '-d', metavar='SECONDS', type=int, default=30, help="""
|
||||
How long to run the test before stopping to examine the logs
|
||||
""")
|
||||
|
||||
parser.add_argument('--cmd', type=str, default='', help="""
|
||||
Commands
|
||||
""")
|
||||
|
||||
parser.add_argument('--nid1', type=int, default=10, help="""
|
||||
Nid1 value
|
||||
""")
|
||||
|
||||
parser.add_argument('--nid2', type=int, default=1, help="""
|
||||
Nid2 value
|
||||
""")
|
||||
|
||||
parser.add_argument('--log-dir', default=HOME_DIR, help="""
|
||||
Where to store log files
|
||||
""")
|
||||
|
||||
parser.add_argument('--compress', '-c', action='store_true', help="""
|
||||
Compress the log files in the --log-dir
|
||||
""")
|
||||
|
||||
parser.add_argument('--no-run', '-n', action='store_true', help="""
|
||||
Don't run the test, only examine the logs in the --log-dir
|
||||
directory from a previous run of the test
|
||||
""")
|
||||
|
||||
parser.add_argument('--debug', action='store_true', help="""
|
||||
Enable debug logging (for this script only)
|
||||
""")
|
||||
|
||||
OPTS = parser.parse_args()
|
||||
del parser
|
||||
|
||||
logging.basicConfig(level=logging.DEBUG if OPTS.debug else logging.INFO,
|
||||
format='>>> %(name)s: %(levelname)s: %(message)s')
|
||||
LOGGER = logging.getLogger(os.path.basename(sys.argv[0]))
|
||||
|
||||
log_file_path = os.path.join(OPTS.log_dir, 'rx.log')
|
||||
|
||||
# ----------------------------------------------------------------------------
|
||||
|
||||
def compress(from_name: str, to_name: Optional[str]=None, remove_original: bool=False) -> None:
|
||||
"""
|
||||
Compress the file `from_name` and store it as `to_name`.
|
||||
`to_name` defaults to `from_name` with `.bz2` appended.
|
||||
If `remove_original` is True, removes `from_name` when the compress finishes.
|
||||
"""
|
||||
if to_name is None:
|
||||
to_name = from_name
|
||||
if not to_name.endswith('.bz2'):
|
||||
to_name += '.bz2'
|
||||
LOGGER.info('Compress %s to %s', from_name, to_name)
|
||||
with bz2.open(to_name, 'w') as outh, \
|
||||
open(from_name, 'rb') as inh:
|
||||
while True:
|
||||
data = inh.read(10240)
|
||||
if not data:
|
||||
break
|
||||
outh.write(data)
|
||||
if remove_original:
|
||||
LOGGER.debug('Remove %s', from_name)
|
||||
os.remove(from_name)
|
||||
|
||||
|
||||
class CompressJobs:
|
||||
"""
|
||||
Allow multiple invocations of `compress` to run in parallel
|
||||
"""
|
||||
|
||||
def __init__(self) -> None:
|
||||
self.kids: List[int] = []
|
||||
|
||||
def compress(self, from_name: str, to_name: Optional[str]=None, remove_original: bool=False) -> None:
|
||||
if not os.path.exists(from_name):
|
||||
# It's not necessarily an error if the log file does not exist.
|
||||
# For example, if nfapi_trace never gets invoked (e.g., because
|
||||
# NFAPI_TRACE_LEVEL is set to none), then the log file nfapi.log
|
||||
# will not get created.
|
||||
LOGGER.warning('No file: %s', from_name)
|
||||
return
|
||||
kid = os.fork()
|
||||
if kid != 0:
|
||||
self.kids.append(kid)
|
||||
else:
|
||||
LOGGER.debug('in pid %d compress %s...', os.getpid(), from_name)
|
||||
compress(from_name, to_name, remove_original)
|
||||
LOGGER.debug('in pid %d compress %s...done', os.getpid(), from_name)
|
||||
sys.exit()
|
||||
|
||||
def wait(self) -> None:
|
||||
LOGGER.debug('wait %s...', self.kids)
|
||||
failed = []
|
||||
for kid in self.kids:
|
||||
LOGGER.debug('waitpid %d', kid)
|
||||
_pid, status = os.waitpid(kid, 0)
|
||||
if status != 0:
|
||||
failed.append(kid)
|
||||
if failed:
|
||||
raise Exception('compression failed: %s', failed)
|
||||
LOGGER.debug('wait...done')
|
||||
|
||||
|
||||
class TestNearby():
|
||||
"""
|
||||
Represents TestNearby
|
||||
"""
|
||||
def __init__(self):
|
||||
self.cmd = None
|
||||
self.delay = 0 # seconds
|
||||
|
||||
def run(self, cmd: str) -> bool:
|
||||
self.cmd = cmd
|
||||
job = "nearby"
|
||||
time.sleep(self.delay)
|
||||
proc = self.launch_nearby(job)
|
||||
LOGGER.info(f"nearby_proc = {proc}")
|
||||
LOGGER.info(f"Process running... {job}")
|
||||
time.sleep(OPTS.duration)
|
||||
passed = self.kill_process("nearby", proc)
|
||||
if OPTS.compress:
|
||||
self.compress_log_file(proc)
|
||||
return passed
|
||||
|
||||
def launch_nearby(self, job) -> Popen:
|
||||
LOGGER.info('Launching Nearby UE: %s', log_file_path)
|
||||
cmd = self.cmd
|
||||
proc = Popen(cmd, shell=True)
|
||||
time.sleep(1)
|
||||
return proc
|
||||
|
||||
def kill_process(self, job: str, proc: Popen) -> bool:
|
||||
passed = True
|
||||
if proc:
|
||||
status = proc.poll()
|
||||
if status is None:
|
||||
LOGGER.info('process is still running, which is good')
|
||||
else:
|
||||
#passed = False
|
||||
LOGGER.info('process ended early: %r', status)
|
||||
LOGGER.info(f'kill main simulation processes... {job}')
|
||||
cmd = ['sudo', 'killall']
|
||||
cmd.append('-KILL')
|
||||
if proc:
|
||||
cmd.append('nr-uesoftmodem')
|
||||
if "nearby" == job:
|
||||
subprocess.run(cmd)
|
||||
LOGGER.info(f'Waiting for PID proc.pid for {job}')
|
||||
proc.kill()
|
||||
proc.wait()
|
||||
LOGGER.info(f'kill main simulation processes...done for {job}')
|
||||
return passed
|
||||
|
||||
def compress_log_file(self, proc: Popen):
|
||||
jobs = CompressJobs()
|
||||
jobs.compress(log_file_path)
|
||||
jobs.wait()
|
||||
|
||||
# ----------------------------------------------------------------------------
|
||||
|
||||
def main(argv) -> int:
|
||||
test_agent = TestNearby()
|
||||
log_agent = LogChecker(OPTS, LOGGER)
|
||||
|
||||
passed = True
|
||||
if not OPTS.no_run:
|
||||
passed = test_agent.run(OPTS.cmd)
|
||||
|
||||
# Examine the logs to determine if the test passed
|
||||
if not log_agent.analyze_nearby_logs(exp_nid1=OPTS.nid1, exp_nid2=OPTS.nid2):
|
||||
passed = False
|
||||
|
||||
if not passed:
|
||||
LOGGER.critical('FAILED')
|
||||
return 1
|
||||
|
||||
LOGGER.info('PASSED')
|
||||
return 0
|
||||
|
||||
sys.exit(main(sys.argv))
|
||||
@@ -228,8 +228,8 @@
|
||||
<yaml_path>ci-scripts/yaml_files/nsa_b200_gnb</yaml_path>
|
||||
<eNB_instance>1</eNB_instance>
|
||||
<eNB_serverId>1</eNB_serverId>
|
||||
<d_retx_th>10,100,100,100</d_retx_th>
|
||||
<u_retx_th>10,100,100,100</u_retx_th>
|
||||
<d_retx_th>1,100,100,100</d_retx_th>
|
||||
<u_retx_th>1,100,100,100</u_retx_th>
|
||||
</testCase>
|
||||
|
||||
</testCaseList>
|
||||
|
||||
@@ -30,14 +30,8 @@
|
||||
001000
|
||||
020000
|
||||
002000
|
||||
002001
|
||||
002002
|
||||
002003
|
||||
002004
|
||||
002005
|
||||
000100
|
||||
000010
|
||||
000020
|
||||
000200
|
||||
003000
|
||||
004000
|
||||
@@ -49,7 +43,6 @@
|
||||
<testCase id="010000">
|
||||
<class>Pull_Cluster_Image</class>
|
||||
<desc>Pull Images from Cluster</desc>
|
||||
<oc_project>oaicicd-ran</oc_project>
|
||||
<images_to_pull>oai-gnb-aw2s</images_to_pull>
|
||||
</testCase>
|
||||
|
||||
@@ -67,7 +60,7 @@
|
||||
<id>amarisoft_ue</id>
|
||||
</testCase>
|
||||
|
||||
<testCase id="002001">
|
||||
<testCase id="002000">
|
||||
<class>Attach_UE</class>
|
||||
<desc>Attach UE</desc>
|
||||
<id>amarisoft_ue_1</id>
|
||||
@@ -79,68 +72,28 @@
|
||||
<id>amarisoft_ue_2</id>
|
||||
</testCase>
|
||||
|
||||
<testCase id="002003">
|
||||
<class>Attach_UE</class>
|
||||
<desc>Attach UE</desc>
|
||||
<id>amarisoft_ue_3</id>
|
||||
</testCase>
|
||||
|
||||
<testCase id="002004">
|
||||
<class>Attach_UE</class>
|
||||
<desc>Attach UE</desc>
|
||||
<id>amarisoft_ue_4</id>
|
||||
</testCase>
|
||||
|
||||
<testCase id="002005">
|
||||
<class>Attach_UE</class>
|
||||
<desc>Attach UE</desc>
|
||||
<id>amarisoft_ue_5</id>
|
||||
</testCase>
|
||||
|
||||
<testCase id="000010">
|
||||
<class>Iperf</class>
|
||||
<desc>iperf (DL/20Mbps/UDP)(30 sec)(multi-ue profile)</desc>
|
||||
<iperf_args>-u -b 60M -t 30 -i 1 -R</iperf_args>
|
||||
<direction>IPERF3</direction>
|
||||
<id>amarisoft_ue_1 amarisoft_ue_2 amarisoft_ue_3</id>
|
||||
<iperf_packetloss_threshold>25</iperf_packetloss_threshold>
|
||||
<iperf_bitrate_threshold>80</iperf_bitrate_threshold>
|
||||
<iperf_profile>balanced</iperf_profile>
|
||||
</testCase>
|
||||
|
||||
<testCase id="000020">
|
||||
<class>Iperf</class>
|
||||
<desc>iperf (UL/5Mbps/UDP)(30 sec)(multi-ue profile)</desc>
|
||||
<iperf_args>-u -b 15M -t 30 -i 1 </iperf_args>
|
||||
<direction>IPERF3</direction>
|
||||
<id>amarisoft_ue_1 amarisoft_ue_2 amarisoft_ue_3</id>
|
||||
<iperf_packetloss_threshold>25</iperf_packetloss_threshold>
|
||||
<iperf_bitrate_threshold>80</iperf_bitrate_threshold>
|
||||
<iperf_profile>balanced</iperf_profile>
|
||||
</testCase>
|
||||
|
||||
<testCase id="000100">
|
||||
<class>Ping</class>
|
||||
<desc>Ping: 20pings in 20sec, multi-ue</desc>
|
||||
<id>amarisoft_ue_1 amarisoft_ue_2 amarisoft_ue_3 amarisoft_ue_4 amarisoft_ue_5</id>
|
||||
<desc>Ping: 20pings in 20sec</desc>
|
||||
<id>amarisoft_ue_1 amarisoft_ue_2</id>
|
||||
<ping_args>-c 20</ping_args>
|
||||
<ping_packetloss_threshold>1</ping_packetloss_threshold>
|
||||
<ping_rttavg_threshold>25</ping_rttavg_threshold>
|
||||
<ping_rttavg_threshold>15</ping_rttavg_threshold>
|
||||
</testCase>
|
||||
|
||||
<testCase id="000200">
|
||||
<class>Ping</class>
|
||||
<desc>Ping: 100pings in 20sec, multi-ue</desc>
|
||||
<id>amarisoft_ue_1 amarisoft_ue_2 amarisoft_ue_3 amarisoft_ue_4 amarisoft_ue_5</id>
|
||||
<desc>Ping: 100pings in 20sec</desc>
|
||||
<id>amarisoft_ue_1 amarisoft_ue_2</id>
|
||||
<ping_args>-c 100 -i 0.2</ping_args>
|
||||
<ping_packetloss_threshold>1</ping_packetloss_threshold>
|
||||
<ping_rttavg_threshold>30</ping_rttavg_threshold>
|
||||
<ping_rttavg_threshold>15</ping_rttavg_threshold>
|
||||
</testCase>
|
||||
|
||||
<testCase id="003000">
|
||||
<class>Detach_UE</class>
|
||||
<desc>Detach UE</desc>
|
||||
<id>amarisoft_ue_1 amarisoft_ue_2 amarisoft_ue_3 amarisoft_ue_4 amarisoft_ue_5</id>
|
||||
<id>amarisoft_ue_1 amarisoft_ue_2</id>
|
||||
</testCase>
|
||||
|
||||
<testCase id="004000">
|
||||
@@ -166,3 +119,4 @@
|
||||
</testCase>
|
||||
|
||||
</testCaseList>
|
||||
|
||||
|
||||
@@ -1,46 +0,0 @@
|
||||
<!--
|
||||
|
||||
Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
|
||||
contributor license agreements. See the NOTICE file distributed with
|
||||
this work for additional information regarding copyright ownership.
|
||||
The OpenAirInterface Software Alliance licenses this file to You under
|
||||
the OAI Public License, Version 1.1 (the "License"); you may not use this file
|
||||
except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.openairinterface.org/?page_id=698
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
|
||||
For more information about the OpenAirInterface (OAI) Software Alliance:
|
||||
contact@openairinterface.org
|
||||
|
||||
-->
|
||||
<testCaseList>
|
||||
<htmlTabRef>test-aw2s-cleanup</htmlTabRef>
|
||||
<htmlTabName>CleanUp AW2S ASUE</htmlTabName>
|
||||
<htmlTabIcon>trash</htmlTabIcon>
|
||||
<TestCaseRequestedList>
|
||||
111111
|
||||
222222
|
||||
</TestCaseRequestedList>
|
||||
<TestCaseExclusionList></TestCaseExclusionList>
|
||||
|
||||
<testCase id="111111">
|
||||
<class>Clean_Test_Server_Images</class>
|
||||
<desc>Clean Test Images on Test Server</desc>
|
||||
<test_svr_id>0</test_svr_id>
|
||||
</testCase>
|
||||
|
||||
<testCase id="222222">
|
||||
<class>Terminate_UE</class>
|
||||
<desc>Terminate UE</desc>
|
||||
<id>amarisoft_ue</id>
|
||||
</testCase>
|
||||
|
||||
</testCaseList>
|
||||
|
||||
@@ -179,8 +179,8 @@
|
||||
<yaml_path>ci-scripts/yaml_files/sa_b200_gnb</yaml_path>
|
||||
<eNB_instance>0</eNB_instance>
|
||||
<eNB_serverId>0</eNB_serverId>
|
||||
<d_retx_th>10,100,100,100</d_retx_th>
|
||||
<u_retx_th>10,100,100,100</u_retx_th>
|
||||
<d_retx_th>1,100,100,100</d_retx_th>
|
||||
<u_retx_th>1,100,100,100</u_retx_th>
|
||||
</testCase>
|
||||
|
||||
</testCaseList>
|
||||
|
||||
@@ -147,6 +147,18 @@
|
||||
<nruns>3</nruns>
|
||||
</testCase>
|
||||
|
||||
<testCase id="nr_psbchsim.106rb">
|
||||
<desc>nr_psbchsim Test cases. (Test1: PSBCH and synchronization, 106PBR),
|
||||
(Test2: PSBCH and synchronization, 106PBR, SSB SC OFFSET 6)</desc>
|
||||
<main_exec>nr_psbchsim</main_exec>
|
||||
<main_exec_args>-s-11 -S2 -n1 -I -R106
|
||||
-s-11 -S2 -n1 -I -R106 -O6</main_exec_args>
|
||||
<tags>test1 test2 test3</tags>
|
||||
<search_expr_true>PSBCH test OK</search_expr_true>
|
||||
<search_expr_false>segmentation fault|assertion|exiting|fatal</search_expr_false>
|
||||
<nruns>3</nruns>
|
||||
</testCase>
|
||||
|
||||
<testCase id="nr_dlsim.basic">
|
||||
<desc>nr_dlsim Test cases. (Test1: 106 PRB),
|
||||
(Test2: 217 PRB),
|
||||
|
||||
@@ -508,7 +508,7 @@ function main() {
|
||||
[[ "$UE" == 1 ]] && execlist="$execlist lte-uesoftmodem"
|
||||
[[ "$nrUE" == 1 ]] && execlist="$execlist nr-uesoftmodem"
|
||||
# TODO: fix: dlsim_tm4 pucchsim prachsim pdcchsim pbchsim mbmssim
|
||||
[[ "$SIMUS_PHY" == "1" ]] && execlist="$execlist dlsim ulsim ldpctest polartest smallblocktest nr_pbchsim nr_dlschsim nr_ulschsim nr_dlsim nr_ulsim nr_pucchsim nr_prachsim"
|
||||
[[ "$SIMUS_PHY" == "1" ]] && execlist="$execlist dlsim ulsim ldpctest polartest smallblocktest nr_pbchsim nr_psbchsim nr_dlschsim nr_ulschsim nr_dlsim nr_ulsim nr_pucchsim nr_prachsim"
|
||||
[[ "$BUILD_OPTLIB" != "" ]] && execlist="$execlist $BUILD_OPTLIB"
|
||||
[[ "$execlist" != "" ]] && execlist="$execlist params_libconfig coding rfsimulator"
|
||||
|
||||
|
||||
@@ -121,8 +121,6 @@ check_supported_distribution() {
|
||||
"rhel8.5") return 0 ;;
|
||||
"rhel8.6") return 0 ;;
|
||||
"rhel8.7") return 0 ;;
|
||||
"rhel8.8") return 0 ;;
|
||||
"rhel8.9") return 0 ;;
|
||||
"rhel9.0") return 0 ;;
|
||||
"rhel9.1") return 0 ;;
|
||||
"rhel9.2") return 0 ;;
|
||||
|
||||
@@ -449,7 +449,6 @@ void get_samplerate_and_bw(int mu,
|
||||
*tx_bw = 50e6;
|
||||
*rx_bw = 50e6;
|
||||
}
|
||||
break;
|
||||
case 216:
|
||||
if (threequarter_fs) {
|
||||
*sample_rate=46.08e6;
|
||||
@@ -475,7 +474,6 @@ void get_samplerate_and_bw(int mu,
|
||||
*tx_bw = 20e6;
|
||||
*rx_bw = 20e6;
|
||||
}
|
||||
break;
|
||||
case 106:
|
||||
if (threequarter_fs) {
|
||||
*sample_rate=23.04e6;
|
||||
@@ -503,7 +501,6 @@ void get_samplerate_and_bw(int mu,
|
||||
*tx_bw = 10e6;
|
||||
*rx_bw = 10e6;
|
||||
}
|
||||
break;
|
||||
case 25:
|
||||
if (threequarter_fs) {
|
||||
*sample_rate=5.76e6;
|
||||
|
||||
@@ -231,9 +231,7 @@ void threadCreate(pthread_t* t, void * (*func)(void*), void * param, char* name,
|
||||
int settingPriority = 1;
|
||||
ret=pthread_attr_init(&attr);
|
||||
AssertFatal(ret==0,"ret: %d, errno: %d\n",ret, errno);
|
||||
|
||||
LOG_I(UTIL,"Creating thread %s with affinity %d and priority %d\n",name,affinity,priority);
|
||||
|
||||
|
||||
if (checkIfFedoraDistribution())
|
||||
if (checkIfGenericKernelOnFedora())
|
||||
if (checkIfInsideContainer())
|
||||
|
||||
@@ -1,2 +0,0 @@
|
||||
Thread Pool implemented in C following the talk of Sean Parent "Better Code: Concurrency" from 2016
|
||||
|
||||
@@ -1,107 +0,0 @@
|
||||
#include <assert.h>
|
||||
#include <fcntl.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "task_manager.h"
|
||||
|
||||
#define NUM_THREADS 4
|
||||
#define NUM_JOBS 1024
|
||||
|
||||
|
||||
int64_t time_now_us(void)
|
||||
{
|
||||
struct timespec tms;
|
||||
|
||||
/* The C11 way */
|
||||
/* if (! timespec_get(&tms, TIME_UTC)) */
|
||||
|
||||
/* POSIX.1-2008 way */
|
||||
if (clock_gettime(CLOCK_MONOTONIC_RAW,&tms)) {
|
||||
return -1;
|
||||
}
|
||||
/* seconds, multiplied with 1 million */
|
||||
int64_t micros = tms.tv_sec * 1000000;
|
||||
/* Add full microseconds */
|
||||
int64_t const tv_nsec = tms.tv_nsec;
|
||||
micros += tv_nsec/1000;
|
||||
/* round up if necessary */
|
||||
if (tv_nsec % 1000 >= 500) {
|
||||
++micros;
|
||||
}
|
||||
return micros;
|
||||
}
|
||||
|
||||
typedef struct{
|
||||
int64_t a;
|
||||
int64_t time;
|
||||
} pair_t;
|
||||
|
||||
|
||||
static inline
|
||||
int64_t naive_fibonnacci(int64_t a)
|
||||
{
|
||||
assert(a < 1000);
|
||||
if(a < 2)
|
||||
return a;
|
||||
|
||||
return naive_fibonnacci(a-1) + naive_fibonnacci(a-2);
|
||||
}
|
||||
|
||||
//static _Thread_local int64_t counter = 0;
|
||||
|
||||
static
|
||||
int marker_fd;
|
||||
|
||||
void do_work(void* arg)
|
||||
{
|
||||
int64_t now = time_now_us();
|
||||
|
||||
pair_t* a = (pair_t*)arg;
|
||||
|
||||
naive_fibonnacci(23 + a->a);
|
||||
int64_t stop = time_now_us();
|
||||
|
||||
char buffer[100] = {0};
|
||||
int ret = snprintf(buffer, 100, "ID %lu Fib elapsed %ld start-stop %ld - %ld \n", pthread_self(), stop - now, now, stop);
|
||||
assert(ret > 0 && ret < 100);
|
||||
|
||||
// write_marker_ft_mir(marker_fd, buffer);
|
||||
// puts(buffer);
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
task_manager_t man = {0};
|
||||
init_task_manager(&man, NUM_THREADS);
|
||||
usleep(100);
|
||||
|
||||
pair_t* arr = calloc(NUM_JOBS, sizeof(pair_t));
|
||||
assert(arr != NULL);
|
||||
|
||||
int64_t now = time_now_us();
|
||||
|
||||
for(int k = 0; k < NUM_JOBS/8; ++k){
|
||||
for(int i = 0; i < 8; ++i){
|
||||
pair_t* pa = &arr[i];
|
||||
pa->a = 0; //i%10;
|
||||
pa->time = 0;
|
||||
task_t t = {.args = pa, t.func = do_work};
|
||||
async_task_manager(&man, t);
|
||||
}
|
||||
printf("Waiting %ld \n", time_now_us());
|
||||
trigger_and_wait_all_task_manager(&man);
|
||||
printf("Done %ld \n", time_now_us());
|
||||
//usleep(1024);
|
||||
}
|
||||
|
||||
free_task_manager(&man, NULL);
|
||||
|
||||
printf("Total elapsed %ld \n", time_now_us() - now);
|
||||
|
||||
free(arr);
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
@@ -1,63 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Full dyntick CPU on which we'll run the user loop,
|
||||
# it must be part of nohz_full kernel parameter
|
||||
TARGET=4
|
||||
|
||||
# Migrate all possible tasks to CPU 0
|
||||
for P in $(ls /proc)
|
||||
do
|
||||
if [ -x "/proc/$P/task/" ]
|
||||
then
|
||||
echo $P
|
||||
taskset -acp 0 $P
|
||||
fi
|
||||
done
|
||||
|
||||
# Migrate irqs to CPU 0
|
||||
for D in $(ls /proc/irq)
|
||||
do
|
||||
if [[ -x "/proc/irq/$D" && $D != "0" ]]
|
||||
then
|
||||
echo $D
|
||||
echo 1 > /proc/irq/$D/smp_affinity
|
||||
fi
|
||||
done
|
||||
|
||||
# Delay the annoying vmstat timer far away
|
||||
sysctl vm.stat_interval=120
|
||||
|
||||
# Shutdown nmi watchdog as it uses perf events
|
||||
sysctl -w kernel.watchdog=0
|
||||
|
||||
# Remove -rt task runtime limit
|
||||
echo -1 > /proc/sys/kernel/sched_rt_runtime_us
|
||||
|
||||
# Pin the writeback workqueue to CPU0
|
||||
echo 1 > /sys/bus/workqueue/devices/writeback/cpumask
|
||||
|
||||
DIR=/sys/kernel/debug/tracing
|
||||
echo > $DIR/trace
|
||||
echo 0 > $DIR/tracing_on
|
||||
# Uncomment the below for more details on what disturbs the CPU
|
||||
echo 0 > $DIR/events/irq/enable
|
||||
echo 1 > $DIR/events/sched/sched_switch/enable
|
||||
echo 1 > $DIR/events/workqueue/workqueue_queue_work/enable
|
||||
echo 1 > $DIR/events/workqueue/workqueue_execute_start/enable
|
||||
echo 1 > $DIR/events/timer/hrtimer_expire_entry/enable
|
||||
echo 1 > $DIR/events/timer/tick_stop/enable
|
||||
echo nop > $DIR/current_tracer
|
||||
echo 1 > $DIR/tracing_on
|
||||
|
||||
# Run a 10 secs user loop on target
|
||||
taskset -c 3-7 ./a.out
|
||||
#sleep 20
|
||||
#killall a.out
|
||||
|
||||
# Checkout the trace in trace.* file
|
||||
cat /sys/kernel/debug/tracing/per_cpu/cpu4/trace > trace.4
|
||||
cat /sys/kernel/debug/tracing/per_cpu/cpu5/trace > trace.5
|
||||
cat /sys/kernel/debug/tracing/per_cpu/cpu6/trace > trace.6
|
||||
cat /sys/kernel/debug/tracing/per_cpu/cpu7/trace > trace.7
|
||||
|
||||
|
||||
@@ -1,10 +0,0 @@
|
||||
#ifndef TASK_WORK_STEALING_THREAD_POOL_H
|
||||
#define TASK_WORK_STEALING_THREAD_POOL_H
|
||||
|
||||
typedef struct{
|
||||
void* args;
|
||||
void (*func)(void* args);
|
||||
} task_t;
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,615 +0,0 @@
|
||||
#define _GNU_SOURCE
|
||||
#include <unistd.h>
|
||||
|
||||
#include "task_manager.h"
|
||||
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
#include <limits.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <poll.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/sysinfo.h>
|
||||
|
||||
#include <fcntl.h>
|
||||
|
||||
#include <linux/futex.h> /* Definition of FUTEX_* constants */
|
||||
#include <sys/syscall.h> /* Definition of SYS_* constants */
|
||||
#include <unistd.h>
|
||||
|
||||
#if defined (__i386__) || defined(__x86_64__)
|
||||
#define pause_or_yield __builtin_ia32_pause
|
||||
#elif __aarch64__
|
||||
#define pause_or_yield() asm volatile("yield" ::: "memory")
|
||||
#else
|
||||
static_assert(0!=0, "Unknown CPU architecture");
|
||||
#endif
|
||||
|
||||
|
||||
static
|
||||
int64_t time_now_us(void)
|
||||
{
|
||||
struct timespec tms;
|
||||
|
||||
/* The C11 way */
|
||||
/* if (! timespec_get(&tms, TIME_UTC)) */
|
||||
|
||||
/* POSIX.1-2008 way */
|
||||
if (clock_gettime(CLOCK_MONOTONIC_RAW, &tms)) {
|
||||
return -1;
|
||||
}
|
||||
/* seconds, multiplied with 1 million */
|
||||
int64_t micros = tms.tv_sec * 1000000;
|
||||
/* Add full microseconds */
|
||||
int64_t const tv_nsec = tms.tv_nsec;
|
||||
micros += tv_nsec/1000;
|
||||
/* round up if necessary */
|
||||
if (tv_nsec % 1000 >= 500) {
|
||||
++micros;
|
||||
}
|
||||
return micros;
|
||||
}
|
||||
|
||||
static
|
||||
void pin_thread_to_core(int core_num)
|
||||
{
|
||||
cpu_set_t set = {0};
|
||||
CPU_ZERO(&set);
|
||||
CPU_SET(core_num, &set);
|
||||
int ret = sched_setaffinity(gettid(), sizeof(set), &set);
|
||||
assert(ret != -1);
|
||||
printf("Pining into core %d id %ld \n", core_num, pthread_self());
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////
|
||||
//////////////////////////////
|
||||
////////// RING //
|
||||
//////////////////////////////
|
||||
//////////////////////////////
|
||||
//////////////////////////////
|
||||
|
||||
|
||||
|
||||
typedef struct seq_ring_buf_s
|
||||
{
|
||||
// const size_t elt_size;
|
||||
task_t* array;
|
||||
|
||||
size_t cap;
|
||||
uint32_t head;
|
||||
uint32_t tail;
|
||||
|
||||
_Atomic uint64_t sz;
|
||||
|
||||
} seq_ring_task_t;
|
||||
|
||||
typedef void (*seq_free_func)(task_t*);
|
||||
|
||||
// For working correctly, maintain the default elements to a multiple of 2
|
||||
#define DEFAULT_ELM 32
|
||||
|
||||
static
|
||||
size_t size_seq_ring_task(seq_ring_task_t* r)
|
||||
{
|
||||
assert(r != NULL);
|
||||
|
||||
return r->head - r->tail;
|
||||
}
|
||||
|
||||
inline static
|
||||
uint32_t mask(uint32_t cap, uint32_t val)
|
||||
{
|
||||
return val & (cap-1);
|
||||
}
|
||||
|
||||
static
|
||||
bool full(seq_ring_task_t* r)
|
||||
{
|
||||
return size_seq_ring_task(r) == r->cap -1;
|
||||
}
|
||||
|
||||
static
|
||||
void enlarge_buffer(seq_ring_task_t* r)
|
||||
{
|
||||
assert(r != NULL);
|
||||
assert(full(r));
|
||||
|
||||
const uint32_t factor = 2;
|
||||
task_t* tmp_buffer = calloc(r->cap * factor, sizeof(task_t) );
|
||||
assert(tmp_buffer != NULL);
|
||||
|
||||
const uint32_t head_pos = mask(r->cap, r->head);
|
||||
const uint32_t tail_pos = mask(r->cap, r->tail);
|
||||
|
||||
if(head_pos > tail_pos){
|
||||
memcpy(tmp_buffer, r->array + tail_pos , (head_pos-tail_pos)*sizeof(task_t) );
|
||||
} else {
|
||||
memcpy(tmp_buffer, r->array + tail_pos, (r->cap-tail_pos)*sizeof(task_t));
|
||||
memcpy(tmp_buffer + (r->cap-tail_pos), r->array, head_pos*sizeof(task_t));
|
||||
}
|
||||
r->cap *= factor;
|
||||
free(r->array);
|
||||
r->array = tmp_buffer;
|
||||
r->tail = 0;
|
||||
r->head = r->cap/2 - 1;
|
||||
}
|
||||
|
||||
static
|
||||
void init_seq_ring_task(seq_ring_task_t* r)
|
||||
{
|
||||
assert(r != NULL);
|
||||
task_t* tmp_buffer = calloc(DEFAULT_ELM, sizeof(task_t));
|
||||
assert(tmp_buffer != NULL);
|
||||
seq_ring_task_t tmp = {.array = tmp_buffer, .head = 0, .tail = 0, .cap = DEFAULT_ELM};
|
||||
memcpy(r, &tmp, sizeof(seq_ring_task_t));
|
||||
r->sz = 0;
|
||||
}
|
||||
|
||||
static
|
||||
void free_seq_ring_task(seq_ring_task_t* r, seq_free_func fp)
|
||||
{
|
||||
assert(r != NULL);
|
||||
assert(fp == NULL);
|
||||
free(r->array);
|
||||
}
|
||||
|
||||
|
||||
static
|
||||
void push_back_seq_ring_task(seq_ring_task_t* r, task_t t)
|
||||
{
|
||||
assert(r != NULL);
|
||||
|
||||
if(full(r))
|
||||
enlarge_buffer(r);
|
||||
|
||||
const uint32_t pos = mask(r->cap, r->head);
|
||||
r->array[pos] = t;
|
||||
r->head += 1;
|
||||
r->sz += 1;
|
||||
}
|
||||
|
||||
static
|
||||
task_t pop_seq_ring_task(seq_ring_task_t* r )
|
||||
{
|
||||
assert(r != NULL);
|
||||
assert(size_seq_ring_task(r) > 0);
|
||||
|
||||
const uint32_t pos = mask(r->cap, r->tail);
|
||||
task_t t = r->array[pos];
|
||||
r->tail += 1;
|
||||
r->sz -= 1;
|
||||
return t;
|
||||
}
|
||||
|
||||
//////////////////////////////
|
||||
//////////////////////////////
|
||||
////////// END RING //
|
||||
//////////////////////////////
|
||||
//////////////////////////////
|
||||
//////////////////////////////
|
||||
|
||||
|
||||
|
||||
//////////////////////////////
|
||||
//////////////////////////////
|
||||
////////// Start Notification Queue //
|
||||
//////////////////////////////
|
||||
//////////////////////////////
|
||||
//////////////////////////////
|
||||
|
||||
typedef struct {
|
||||
pthread_mutex_t mtx;
|
||||
pthread_cond_t cv;
|
||||
seq_ring_task_t r;
|
||||
_Atomic int32_t* futex;
|
||||
_Atomic bool* waiting;
|
||||
_Atomic int done;
|
||||
} not_q_t;
|
||||
|
||||
typedef struct{
|
||||
task_t t;
|
||||
bool success;
|
||||
} ret_try_t;
|
||||
|
||||
|
||||
static
|
||||
void init_not_q(not_q_t* q, _Atomic int32_t* futex, _Atomic bool* waiting)
|
||||
{
|
||||
assert(q != NULL);
|
||||
|
||||
q->done = 0;
|
||||
q->waiting = waiting;
|
||||
init_seq_ring_task(&q->r);
|
||||
|
||||
pthread_mutexattr_t attr = {0};
|
||||
#ifdef _DEBUG
|
||||
int const rc_mtx = pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_ERRORCHECK);
|
||||
assert(rc_mtx == 0);
|
||||
#endif
|
||||
int rc = pthread_mutex_init(&q->mtx, &attr);
|
||||
assert(rc == 0 && "Error while creating the mtx");
|
||||
|
||||
pthread_condattr_t* c_attr = NULL;
|
||||
rc = pthread_cond_init(&q->cv, c_attr);
|
||||
assert(rc == 0);
|
||||
|
||||
q->futex = futex;
|
||||
}
|
||||
|
||||
static
|
||||
void free_not_q(not_q_t* q, void (*clean)(task_t*) )
|
||||
{
|
||||
assert(q != NULL);
|
||||
assert(q->done == 1);
|
||||
|
||||
free_seq_ring_task(&q->r, clean);
|
||||
|
||||
int rc = pthread_mutex_destroy(&q->mtx);
|
||||
assert(rc == 0);
|
||||
|
||||
rc = pthread_cond_destroy(&q->cv);
|
||||
assert(rc == 0);
|
||||
}
|
||||
|
||||
static
|
||||
bool try_push_not_q(not_q_t* q, task_t t)
|
||||
{
|
||||
assert(q != NULL);
|
||||
assert(q->done == 0 || q->done ==1);
|
||||
assert(t.func != NULL);
|
||||
assert(t.args != NULL);
|
||||
|
||||
if(pthread_mutex_trylock(&q->mtx ) != 0)
|
||||
return false;
|
||||
|
||||
push_back_seq_ring_task(&q->r, t);
|
||||
|
||||
int const rc = pthread_mutex_unlock(&q->mtx);
|
||||
assert(rc == 0);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static
|
||||
void push_not_q(not_q_t* q, task_t t)
|
||||
{
|
||||
assert(q != NULL);
|
||||
assert(q->done == 0 || q->done ==1);
|
||||
assert(t.func != NULL);
|
||||
|
||||
int const rc = pthread_mutex_lock(&q->mtx);
|
||||
assert(rc == 0);
|
||||
|
||||
push_back_seq_ring_task(&q->r, t);
|
||||
|
||||
pthread_mutex_unlock(&q->mtx);
|
||||
}
|
||||
|
||||
|
||||
static
|
||||
ret_try_t try_pop_not_q(not_q_t* q)
|
||||
{
|
||||
assert(q != NULL);
|
||||
|
||||
ret_try_t ret = {.success = false};
|
||||
|
||||
int rc = pthread_mutex_trylock(&q->mtx);
|
||||
assert(rc == 0 || rc == EBUSY);
|
||||
|
||||
if(rc == EBUSY)
|
||||
return ret;
|
||||
|
||||
assert(q->done == 0 || q->done ==1);
|
||||
|
||||
size_t sz = size_seq_ring_task(&q->r);
|
||||
if(sz == 0){
|
||||
rc = pthread_mutex_unlock(&q->mtx);
|
||||
assert(rc == 0);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret.t = pop_seq_ring_task(&q->r);
|
||||
|
||||
rc = pthread_mutex_unlock(&q->mtx);
|
||||
assert(rc == 0);
|
||||
ret.success = true;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static
|
||||
bool pop_not_q(not_q_t* q, ret_try_t* out)
|
||||
{
|
||||
assert(q != NULL);
|
||||
assert(out != NULL);
|
||||
assert(q->done == 0 || q->done ==1);
|
||||
|
||||
label:
|
||||
// Let's be conservative and not use memory_order_relaxed
|
||||
while (atomic_load_explicit(q->waiting, memory_order_seq_cst) == true){ //
|
||||
// Issue X86 PAUSE or ARM YIELD instruction to reduce contention between
|
||||
// hyper-threads
|
||||
pause_or_yield();
|
||||
}
|
||||
|
||||
pthread_mutex_lock(&q->mtx);
|
||||
|
||||
if(size_seq_ring_task(&q->r) == 0 && q->done == 0){
|
||||
int rc = pthread_mutex_unlock(&q->mtx);
|
||||
assert(rc == 0);
|
||||
|
||||
int val = *q->futex; // atomic_load_explicit(q->futex, memory_order_acquire);
|
||||
long r = syscall(SYS_futex, q->futex, FUTEX_WAIT_PRIVATE, val, NULL, 0);
|
||||
assert(r != -1);
|
||||
goto label;
|
||||
}
|
||||
|
||||
assert(q->done == 0 || q->done ==1);
|
||||
|
||||
//printf("Waking %ld id %ld \n", time_now_us(), pthread_self());
|
||||
|
||||
if(q->done == 1){
|
||||
//printf("Done, returning \n");
|
||||
int rc = pthread_mutex_unlock(&q->mtx);
|
||||
assert(rc == 0);
|
||||
return false;
|
||||
}
|
||||
|
||||
out->t = pop_seq_ring_task(&q->r);
|
||||
|
||||
int rc = pthread_mutex_unlock(&q->mtx);
|
||||
assert(rc == 0);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static
|
||||
void done_not_q(not_q_t* q)
|
||||
{
|
||||
assert(q != NULL);
|
||||
|
||||
int rc = pthread_mutex_lock(&q->mtx);
|
||||
assert(rc == 0);
|
||||
|
||||
q->done = 1;
|
||||
long r = syscall(SYS_futex, q->futex, FUTEX_WAKE_PRIVATE, 1 , NULL, NULL, 0);
|
||||
assert(r != -1);
|
||||
rc = pthread_mutex_unlock(&q->mtx);
|
||||
assert(rc == 0);
|
||||
|
||||
// rc = pthread_cond_signal(&q->cv);
|
||||
// assert(rc == 0);
|
||||
|
||||
// q->futex++;
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////
|
||||
//////////////////////////////
|
||||
////////// END Notification Queue //
|
||||
//////////////////////////////
|
||||
//////////////////////////////
|
||||
//////////////////////////////
|
||||
|
||||
|
||||
//static int marker_fd;
|
||||
|
||||
typedef struct{
|
||||
task_manager_t* man;
|
||||
int idx;
|
||||
} task_thread_args_t;
|
||||
|
||||
|
||||
|
||||
static
|
||||
void* worker_thread(void* arg)
|
||||
{
|
||||
assert(arg != NULL);
|
||||
|
||||
task_thread_args_t* args = (task_thread_args_t*)arg;
|
||||
int const idx = args->idx;
|
||||
|
||||
int const log_cores = get_nprocs_conf();
|
||||
assert(log_cores > 0);
|
||||
// Assuming: 2 x Physical cores = Logical cores
|
||||
pin_thread_to_core(idx+log_cores/2);
|
||||
|
||||
task_manager_t* man = args->man;
|
||||
|
||||
uint32_t const len = man->len_thr;
|
||||
uint32_t const num_it = 2*(man->len_thr + idx);
|
||||
|
||||
not_q_t* q_arr = (not_q_t*)man->q_arr;
|
||||
|
||||
int acc_num_task = 0;
|
||||
for(;;){
|
||||
|
||||
ret_try_t ret = {.success = false};
|
||||
|
||||
for(uint32_t i = idx; i < num_it; ++i){
|
||||
ret = try_pop_not_q(&q_arr[i%len]);
|
||||
if(ret.success == true){
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(ret.success == false){
|
||||
man->num_task -= acc_num_task;
|
||||
acc_num_task = 0;
|
||||
if(pop_not_q(&q_arr[idx], &ret) == false)
|
||||
break;
|
||||
}
|
||||
|
||||
//int64_t now = time_now_us();
|
||||
//printf("Calling fuinc \n");
|
||||
ret.t.func(ret.t.args);
|
||||
//printf("Returning from func \n");
|
||||
//int64_t stop = time_now_us();
|
||||
|
||||
acc_num_task +=1;
|
||||
}
|
||||
|
||||
free(args);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
void init_task_manager(task_manager_t* man, uint32_t num_threads)
|
||||
{
|
||||
assert(man != NULL);
|
||||
assert(num_threads > 0 && num_threads < 33 && "Do you have zero or more than 32 processors??");
|
||||
|
||||
man->q_arr = calloc(num_threads, sizeof(not_q_t));
|
||||
assert(man->q_arr != NULL && "Memory exhausted");
|
||||
man->futex = 0;
|
||||
|
||||
man->waiting = false;
|
||||
|
||||
not_q_t* q_arr = (not_q_t*)man->q_arr;
|
||||
for(uint32_t i = 0; i < num_threads; ++i){
|
||||
init_not_q(&q_arr[i], &man->futex, &man->waiting);
|
||||
}
|
||||
|
||||
man->t_arr = calloc(num_threads, sizeof(pthread_t));
|
||||
assert(man->t_arr != NULL && "Memory exhausted" );
|
||||
man->len_thr = num_threads;
|
||||
|
||||
for(uint32_t i = 0; i < num_threads; ++i){
|
||||
task_thread_args_t* args = malloc(sizeof(task_thread_args_t) );
|
||||
args->idx = i;
|
||||
args->man = man;
|
||||
|
||||
pthread_attr_t attr = {0};
|
||||
int ret=pthread_attr_init(&attr);
|
||||
assert(ret == 0);
|
||||
ret=pthread_attr_setinheritsched(&attr, PTHREAD_EXPLICIT_SCHED);
|
||||
assert(ret == 0);
|
||||
ret=pthread_attr_setschedpolicy(&attr, SCHED_RR);
|
||||
assert(ret == 0);
|
||||
struct sched_param sparam={0};
|
||||
sparam.sched_priority = 94;
|
||||
ret=pthread_attr_setschedparam(&attr, &sparam);
|
||||
|
||||
int rc = pthread_create(&man->t_arr[i], &attr, worker_thread, args);
|
||||
assert(rc == 0);
|
||||
}
|
||||
|
||||
man->index = 0;
|
||||
|
||||
pthread_mutexattr_t attr = {0};
|
||||
#ifdef _DEBUG
|
||||
int const rc_mtx = pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_ERRORCHECK);
|
||||
assert(rc_mtx == 0);
|
||||
#endif
|
||||
int rc = pthread_mutex_init(&man->wait_mtx, &attr);
|
||||
assert(rc == 0 && "Error while creating the mtx");
|
||||
|
||||
pthread_condattr_t* c_attr = NULL;
|
||||
rc = pthread_cond_init(&man->wait_cv, c_attr);
|
||||
assert(rc == 0);
|
||||
|
||||
//pin_thread_to_core(3);
|
||||
}
|
||||
|
||||
void free_task_manager(task_manager_t* man, void (*clean)(task_t*))
|
||||
{
|
||||
not_q_t* q_arr = (not_q_t*)man->q_arr;
|
||||
atomic_store(&man->waiting, false);
|
||||
for(uint32_t i = 0; i < man->len_thr; ++i){
|
||||
done_not_q(&q_arr[i]);
|
||||
}
|
||||
|
||||
for(uint32_t i = 0; i < man->len_thr; ++i){
|
||||
int rc = pthread_join(man->t_arr[i], NULL);
|
||||
assert(rc == 0);
|
||||
}
|
||||
|
||||
for(uint32_t i = 0; i < man->len_thr; ++i){
|
||||
free_not_q(&q_arr[i], clean);
|
||||
}
|
||||
|
||||
free(man->q_arr);
|
||||
|
||||
free(man->t_arr);
|
||||
|
||||
int rc = pthread_mutex_destroy(&man->wait_mtx);
|
||||
assert(rc == 0);
|
||||
|
||||
rc = pthread_cond_destroy(&man->wait_cv);
|
||||
assert(rc == 0);
|
||||
}
|
||||
|
||||
void async_task_manager(task_manager_t* man, task_t t)
|
||||
{
|
||||
assert(man != NULL);
|
||||
assert(t.func != NULL);
|
||||
//assert(t.args != NULL);
|
||||
|
||||
uint64_t const index = man->index++;
|
||||
const uint32_t len_thr = man->len_thr;
|
||||
|
||||
not_q_t* q_arr = (not_q_t*)man->q_arr;
|
||||
for(uint32_t i = 0; i < len_thr ; ++i){
|
||||
if(try_push_not_q(&q_arr[(i+index) % len_thr], t)){
|
||||
man->num_task +=1;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
push_not_q(&q_arr[index%len_thr], t);
|
||||
man->num_task +=1;
|
||||
}
|
||||
|
||||
void trigger_and_spin(task_manager_t* man)
|
||||
{
|
||||
assert(man != NULL);
|
||||
|
||||
atomic_store(&man->waiting, true);
|
||||
|
||||
// FUTEX_WAKE_PRIVATE
|
||||
man->futex = 0;
|
||||
long r = syscall(SYS_futex, &man->futex, FUTEX_WAKE_PRIVATE, INT_MAX, NULL, NULL, 0);
|
||||
//printf("Number of threads woken %ld \n", r);
|
||||
if(r == -1){
|
||||
printf("%d errno \n", errno);
|
||||
}
|
||||
assert(r != -1);
|
||||
}
|
||||
|
||||
void trigger_and_wait_all_task_manager(task_manager_t* man)
|
||||
{
|
||||
assert(man != NULL);
|
||||
|
||||
trigger_and_spin(man);
|
||||
atomic_store(&man->waiting, false);
|
||||
|
||||
// GCC thread sanitizer complains, while Clang does not. Let's be conservative and pay some cycles
|
||||
// memory_order_relaxed
|
||||
//printf("Main func waiting \n");
|
||||
while (atomic_load_explicit(&man->num_task, memory_order_relaxed)){
|
||||
// Issue X86 PAUSE or ARM YIELD instruction to reduce contention between
|
||||
// hyper-threads
|
||||
pause_or_yield();
|
||||
}
|
||||
|
||||
//printf("Main func returnning \n");
|
||||
|
||||
atomic_store(&man->waiting, true);
|
||||
}
|
||||
|
||||
void wait_all_task_manager(task_manager_t* man)
|
||||
{
|
||||
assert(man != NULL);
|
||||
|
||||
while (atomic_load_explicit(&man->num_task, memory_order_relaxed)){
|
||||
// Issue X86 PAUSE or ARM YIELD instruction to reduce contention between
|
||||
// hyper-threads
|
||||
pause_or_yield();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,48 +0,0 @@
|
||||
#ifndef TASK_MANAGER_WORKING_STEALING_H
|
||||
#define TASK_MANAGER_WORKING_STEALING_H
|
||||
|
||||
// Comment for deactivating ws tpool
|
||||
#define TASK_MANAGER
|
||||
|
||||
|
||||
#include "task.h"
|
||||
|
||||
#include <pthread.h>
|
||||
#include <stdatomic.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
|
||||
typedef struct{
|
||||
|
||||
pthread_t* t_arr;
|
||||
size_t len_thr;
|
||||
|
||||
atomic_uint_fast64_t index;
|
||||
|
||||
void* q_arr;
|
||||
|
||||
atomic_uint_fast64_t num_task;
|
||||
|
||||
pthread_cond_t wait_cv;
|
||||
pthread_mutex_t wait_mtx;
|
||||
|
||||
_Atomic int32_t futex;
|
||||
|
||||
_Atomic bool waiting;
|
||||
|
||||
} task_manager_t;
|
||||
|
||||
void init_task_manager(task_manager_t* man, uint32_t num_threads);
|
||||
|
||||
void free_task_manager(task_manager_t* man, void (*clean)(task_t* args) );
|
||||
|
||||
void async_task_manager(task_manager_t* man, task_t t);
|
||||
|
||||
void trigger_and_spin(task_manager_t* man);
|
||||
|
||||
void trigger_and_wait_all_task_manager(task_manager_t* man);
|
||||
|
||||
void wait_all_task_manager(task_manager_t* man);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -30,7 +30,7 @@ The main oai binaries, which are tested by the Continuous Integration process ar
|
||||
- The 5G gNodeB: `nr-softmodem`
|
||||
- The 5G CU-UP: `nr-cuup`
|
||||
- The LTE PHY simulators: `dlsim` and `ulsim`
|
||||
- The 5G PHY simulators: `nr_dlschsim`, `nr_dlsim`, `nr_pbchsim`, `nr_pucchsim`, `nr_ulschsim`, `nr_ulsim`, `polartest`, `smallblocktest`, `nr _ulsim`, `ldpctest`
|
||||
- The 5G PHY simulators: `nr_dlschsim`, `nr_dlsim`, `nr_pbchsim`, `nr_psbchsim`, `nr_pucchsim`, `nr_ulschsim`, `nr_ulsim`, `polartest`, `smallblocktest`, `nr _ulsim`, `ldpctest`
|
||||
|
||||
Running the [build_oai](../cmake_targets/build_oai) script also generates some utilities required to build and/or run the oai softmodem binaries:
|
||||
|
||||
|
||||
@@ -21,14 +21,14 @@ In this tutorial we describe how to configure and run a 5G end-to-end setup with
|
||||
|
||||
Minimum hardware requirements:
|
||||
- Laptop/Desktop/Server for OAI CN5G and OAI gNB
|
||||
- Operating System: [Ubuntu 22.04 LTS](https://releases.ubuntu.com/22.04/ubuntu-22.04.2-desktop-amd64.iso)
|
||||
- Operating System: [Ubuntu 22.04 LTS](https://releases.ubuntu.com/22.04/ubuntu-22.04.1-desktop-amd64.iso)
|
||||
- CPU: 8 cores x86_64 @ 3.5 GHz
|
||||
- RAM: 32 GB
|
||||
- Laptop for UE
|
||||
- Operating System: Microsoft Windows 10 x64
|
||||
- CPU: 4 cores x86_64
|
||||
- RAM: 8 GB
|
||||
- Windows driver for Quectel MUST be equal or higher than version **2.4.6**
|
||||
- Windows driver for Quectel MUST be equal or higher than version **2.2.4**
|
||||
- [USRP B210](https://www.ettus.com/all-products/ub210-kit/), [USRP N300](https://www.ettus.com/all-products/USRP-N300/) or [USRP X300](https://www.ettus.com/all-products/x300-kit/)
|
||||
- Please identify the network interface(s) on which the USRP is connected and update the gNB configuration file
|
||||
- Quectel RM500Q
|
||||
|
||||
@@ -21,7 +21,7 @@ In this tutorial we describe how to configure and run a 5G end-to-end setup with
|
||||
|
||||
Minimum hardware requirements:
|
||||
- Laptop/Desktop/Server for OAI CN5G and OAI gNB
|
||||
- Operating System: [Ubuntu 22.04 LTS](https://releases.ubuntu.com/22.04/ubuntu-22.04.2-desktop-amd64.iso)
|
||||
- Operating System: [Ubuntu 22.04 LTS](https://releases.ubuntu.com/22.04/ubuntu-22.04.1-desktop-amd64.iso)
|
||||
- CPU: 8 cores x86_64 @ 3.5 GHz
|
||||
- RAM: 32 GB
|
||||
|
||||
|
||||
@@ -21,11 +21,11 @@ In this tutorial we describe how to configure and run a 5G end-to-end setup with
|
||||
|
||||
Minimum hardware requirements:
|
||||
- Laptop/Desktop/Server for OAI CN5G and OAI gNB
|
||||
- Operating System: [Ubuntu 22.04 LTS](https://releases.ubuntu.com/22.04/ubuntu-22.04.2-desktop-amd64.iso)
|
||||
- Operating System: [Ubuntu 22.04 LTS](https://releases.ubuntu.com/22.04/ubuntu-22.04.1-desktop-amd64.iso)
|
||||
- CPU: 8 cores x86_64 @ 3.5 GHz
|
||||
- RAM: 32 GB
|
||||
- Laptop for UE
|
||||
- Operating System: [Ubuntu 22.04 LTS](https://releases.ubuntu.com/22.04/ubuntu-22.04.2-desktop-amd64.iso)
|
||||
- Operating System: [Ubuntu 22.04 LTS](https://releases.ubuntu.com/22.04/ubuntu-22.04.1-desktop-amd64.iso)
|
||||
- CPU: 8 cores x86_64 @ 3.5 GHz
|
||||
- RAM: 8 GB
|
||||
- [USRP B210](https://www.ettus.com/all-products/ub210-kit/), [USRP N300](https://www.ettus.com/all-products/USRP-N300/) or [USRP X300](https://www.ettus.com/all-products/x300-kit/)
|
||||
@@ -155,7 +155,7 @@ Run OAI nrUE
|
||||
cd ~/openairinterface5g
|
||||
source oaienv
|
||||
cd cmake_targets/ran_build/build
|
||||
sudo ./nr-uesoftmodem -r 106 --numerology 1 --band 78 -C 3619200000 --ue-fo-compensation --sa -E --uicc0.imsi 001010000000001
|
||||
sudo ./nr-uesoftmodem -r 106 --numerology 1 --band 78 -C 3619200000 --nokrnmod --ue-fo-compensation --sa -E --uicc0.imsi 001010000000001
|
||||
```
|
||||
|
||||
## 5.2 Testing OAI nrUE with RFsimulator
|
||||
@@ -168,7 +168,7 @@ Run OAI nrUE with RFsimulator
|
||||
cd ~/openairinterface5g
|
||||
source oaienv
|
||||
cd cmake_targets/ran_build/build
|
||||
sudo RFSIMULATOR=127.0.0.1 ./nr-uesoftmodem -r 106 --numerology 1 --band 78 -C 3619200000 --rfsim --sa --uicc0.imsi 001010000000001
|
||||
sudo RFSIMULATOR=127.0.0.1 ./nr-uesoftmodem -r 106 --numerology 1 --band 78 -C 3619200000 --nokrnmod --rfsim --sa --uicc0.imsi 001010000000001
|
||||
```
|
||||
|
||||
### 5.2.1 Ping test
|
||||
|
||||
@@ -36,6 +36,7 @@ There is some general information in the [OpenAirInterface Gitlab Wiki](https://
|
||||
* (5G) Using SDAP and custom DRBs
|
||||
* IF setups and arbitrary frequencies
|
||||
* MIMO
|
||||
- [How to run a 5G-SA setup](./TESTING_5GSA_setup.md)
|
||||
- [How to run a 5G-NSA setup](./TESTING_GNB_W_COTS_UE.md)
|
||||
- [How to run a 4G setup using L1 simulator](./L1SIM.md) _Note: we recommend the RFsimulator_
|
||||
- [How to use the L2 simulator](./L2NFAPI.md)
|
||||
|
||||
@@ -31,6 +31,7 @@ rx_func_implem[rx_func]
|
||||
--> handle_nr_ulsch
|
||||
subgraph gNB_dlsch_ulsch_scheduler
|
||||
run_pdcp
|
||||
--> nr_rrc_trigger
|
||||
--> schedule_xxxx
|
||||
end
|
||||
handle_nr_ulsch --> gNB_dlsch_ulsch_scheduler
|
||||
|
||||
230
doc/TESTING_5GSA_setup.md
Normal file
230
doc/TESTING_5GSA_setup.md
Normal file
@@ -0,0 +1,230 @@
|
||||
<table style="border-collapse: collapse; border: none;">
|
||||
<tr style="border-collapse: collapse; border: none;">
|
||||
<td style="border-collapse: collapse; border: none;">
|
||||
<a href="http://www.openairinterface.org/">
|
||||
<img src="./images/oai_final_logo.png" alt="" border=3 height=50 width=150>
|
||||
</img>
|
||||
</a>
|
||||
</td>
|
||||
<td style="border-collapse: collapse; border: none; vertical-align: center;">
|
||||
<b><font size = "5">OAI 5G SA tutorial</font></b>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
**Table of Contents**
|
||||
|
||||
[[_TOC_]]
|
||||
|
||||
In the following tutorial we describe how to deploy configure and test the two SA OAI setups:
|
||||
|
||||
- SA setup with OAI gNB and COTS UE
|
||||
- SA setup with OAI gNB and OAI UE
|
||||
|
||||
The operating system and hardware requirements to support OAI 5G NR are described [here](https://gitlab.eurecom.fr/oai/openairinterface5g/-/wikis/5g-nr-development-and-setup).
|
||||
|
||||
# 1. SA setup with COTS UE
|
||||
At the moment of writing this document interoperability with the following COTS UE devices is being tested:
|
||||
|
||||
- [Quectel RM500Q-GL](https://www.quectel.com/product/5g-rm500q-gl/)
|
||||
- [Simcom SIMCOM8200EA](https://www.simcom.com/product/SIM8200EA_M2.html)
|
||||
- Huawei Mate 30 Pro
|
||||
- Oneplus 8
|
||||
- Google Pixel 5
|
||||
|
||||
End-to-end control plane signaling to achieve a 5G SA connection, UE registration and PDU session establishment with the CN, as well as some basic user-plane traffic tests have been validated so far using SIMCOM/Quectel modules and Huawei Mate 30 pro. In terms of interoperability with different 5G Core Networks, so far this setup has been tested with:
|
||||
|
||||
|
||||
- [OAI CN](https://openairinterface.org/oai-5g-core-network-project/)
|
||||
- Nokia SA Box
|
||||
- [Free CN](https://www.free5gc.org/)
|
||||
|
||||
|
||||
## 1.1 gNB build and configuration
|
||||
To get the code and build the gNB executable:
|
||||
|
||||
### Build gNB
|
||||
```bash
|
||||
git clone https://gitlab.eurecom.fr/oai/openairinterface5g.git
|
||||
git checkout develop
|
||||
cd openairinterface5g/
|
||||
source oaienv
|
||||
cd cmake_targets/
|
||||
./build_oai -I -w USRP #For OAI first time installation only to install software dependencies
|
||||
./build_oai --gNB -w USRP
|
||||
```
|
||||
|
||||
A reference configuration file for the **monolithic** gNB is provided [here](https://gitlab.eurecom.fr/oai/openairinterface5g/-/blob/develop/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.fr1.106PRB.usrpb210.conf).
|
||||
|
||||
|
||||
In the following, we highlight the fields of the file that have to be configured according to the configuration and interfaces of the Core Network. First, the PLMN section has to be filled with the proper values that match the configuration of the AMF and the UE USIM.
|
||||
```bash
|
||||
// Tracking area code, 0x0000 and 0xfffe are reserved values
|
||||
tracking_area_code = 1;
|
||||
plmn_list = ({ mcc = 208; mnc = 99; mnc_length = 2; snssaiList = ({ sst = 1 }) });
|
||||
```
|
||||
Then, the source and destination IP interfaces for the communication with
|
||||
the Core Network also need to be set as shown below.
|
||||
|
||||
```bash
|
||||
////////// AMF parameters:
|
||||
amf_ip_address = ( { ipv4 = "192.168.70.132";
|
||||
ipv6 = "192:168:30::17";
|
||||
active = "yes";
|
||||
preference = "ipv4";
|
||||
}
|
||||
);
|
||||
|
||||
|
||||
NETWORK_INTERFACES :
|
||||
{
|
||||
GNB_INTERFACE_NAME_FOR_NG_AMF = "demo-oai";
|
||||
GNB_IPV4_ADDRESS_FOR_NG_AMF = "192.168.70.129/24";
|
||||
GNB_INTERFACE_NAME_FOR_NGU = "demo-oai";
|
||||
GNB_IPV4_ADDRESS_FOR_NGU = "192.168.70.129/24";
|
||||
GNB_PORT_FOR_S1U = 2152; # Spec 2152
|
||||
};
|
||||
```
|
||||
In the first part (*amf_ip_address*) we specify the IP of the AMF and in the second part (*NETWORK_INTERFACES*) we specify the gNB local interface with AMF (N2 interface) and the UPF (N3 interface).
|
||||
|
||||
**CAUTION:** the `192.168.70.132` AMF IF address is the OAI-CN5G `AMF` Container IP address. You certainly will need to do some networking manipulations for the `gNB` server to be able to see this AMF container.
|
||||
|
||||
Please read [CN5G tutorial for more details](https://gitlab.eurecom.fr/oai/cn5g/oai-cn5g-fed/-/blob/master/README.md).
|
||||
|
||||
### gNB configuration in F1 (CU/DU split mode)
|
||||
|
||||
For the configuration of the gNB in CU and DU blocks, the following sample configuration files are provided for the [CU](https://gitlab.eurecom.fr/oai/openairinterface5g/-/blob/develop/targets/PROJECTS/GENERIC-NR-5GC/CONF/cu_gnb.conf) and the [DU](https://gitlab.eurecom.fr/oai/openairinterface5g/-/blob/develop/targets/PROJECTS/GENERIC-NR-5GC/CONF/du_gnb.conf) entities respectively. These configuration files have to be updated with the IP addresses of the CU and the DU over the F1 interface. For example, in the following section from the DU configuration file, *local_n_address* corresponds to the DU address and *remote_n_address* corresponds to the CU address:
|
||||
|
||||
```bash
|
||||
MACRLCs = (
|
||||
{
|
||||
num_cc = 1;
|
||||
tr_s_preference = "local_L1";
|
||||
tr_n_preference = "f1";
|
||||
local_n_if_name = "lo";
|
||||
local_n_address = "127.0.0.3";
|
||||
remote_n_address = "127.0.0.4";
|
||||
local_n_portc = 601;
|
||||
local_n_portd = 2152;
|
||||
remote_n_portc = 600;
|
||||
remote_n_portd = 2152;
|
||||
|
||||
}
|
||||
);
|
||||
```
|
||||
|
||||
At the point of writing this document the control-plane exchanges between the CU and the DU over *F1-C* interface, as well as some IP traffic tests over *F1-U* have been validated using the OAI gNB/nrUE in RFSIMULATOR mode.
|
||||
|
||||
### gNB configuration with F1 and E1
|
||||
|
||||
Please refer to [E1-design](E1-design) for more information.
|
||||
|
||||
## 1.2 OAI 5G Core Network installation and configuration
|
||||
The instructions for the installation of OAI CN components (AMF, SMF, NRF, UPF) using `docker-compose` can be found [here](https://gitlab.eurecom.fr/oai/cn5g/oai-cn5g-fed/-/blob/master/README.md).
|
||||
|
||||
## 1.3 Execution of SA scenario
|
||||
|
||||
After having configured the gNB, we can start the individual components in the following sequence:
|
||||
|
||||
- Launch 5G Core Network
|
||||
- Launch gNB
|
||||
- Launch COTS UE (disable airplane mode)
|
||||
|
||||
The execution command to start the gNB (in monolithic mode) is the following:
|
||||
```bash
|
||||
cd cmake_targets/ran_build/build
|
||||
sudo ./nr-softmodem -E --sa -O ../../../targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.fr1.106PRB.usrpb210.conf
|
||||
```
|
||||
|
||||
# 2. SA Setup with OAI NR UE Softmodem
|
||||
The SA setup with OAI UE has been validated with **RFSIMULATOR**. Both control plane and user plane for the successful UE registration and PDU Session establishment has been verified with OAI and Nokia SA Box CNs.
|
||||
|
||||
In the following, we provide the instructions on how to build, configure and execute this SA setup.
|
||||
|
||||
As another option, if you do not want to build anything and instead deploy the OAI RAN (RFSIMULATOR) and Core Network components directly using docker images and docker-compose, please have a look at [this tutorial](https://gitlab.eurecom.fr/oai/openairinterface5g/-/blob/develop/ci-scripts/yaml_files/5g_rfsimulator/README.md).
|
||||
|
||||
### NAS configuration for the OAI UE
|
||||
The NAS configuration parameters of the OAI UE can be set as input parameters, configuration file or can be hardcoded. More specifically:
|
||||
- SUCI (*Subscription Concealed Identifier*)
|
||||
- USIM_API_K and OPc keys
|
||||
- NSSAI (*Network Slice Assistance Information*)
|
||||
- DNN (*Data Network Name*)
|
||||
|
||||
Below is a sample configuration file that can be parsed through the execution command ([section 2.3](#23-execution-of-sa-scenario)).
|
||||
|
||||
```bash
|
||||
uicc0 = {
|
||||
imsi = "208990000007487";
|
||||
key = "fec86ba6eb707ed08905757b1bb44b8f";
|
||||
opc= "C42449363BBAD02B66D16BC975D77CC1";
|
||||
dnn= "oai";
|
||||
nssai_sst=1;
|
||||
nssai_sd=1;
|
||||
}
|
||||
```
|
||||
|
||||
For interoperability with OAI or other CNs, it should be ensured that the configuration of the aforementioned parameters match the configuration of the corresponding subscribed user at the core network.
|
||||
|
||||
|
||||
## 2.1 Build and configuration
|
||||
To build the gNB and OAI UE executables:
|
||||
|
||||
```bash
|
||||
cd cmake_targets
|
||||
# Note: For OAI first time installation please install software dependencies as described in 1.1.
|
||||
./build_oai --gNB --nrUE -w SIMU
|
||||
```
|
||||
The gNB configuration can be performed according to what is described in [section 1.1](#11--gnb-build-and-configuration), using the same reference configuration file as with the RF scenario.
|
||||
|
||||
## 2.2 OAI 5G Core Network installation and configuration
|
||||
The instructions for the installation of OAI CN components (AMF, SMF, NRF, UPF) using `docker-compose` can be found [here](https://gitlab.eurecom.fr/oai/cn5g/oai-cn5g-fed/-/blob/master/README.md).
|
||||
|
||||
|
||||
## 2.3 Execution of SA scenario
|
||||
|
||||
The order of starting the different components should be the same as the one described in [section 1.3](#13--execution-of-sa-scenario).
|
||||
|
||||
the gNB can be launched in 2 modes:
|
||||
|
||||
- To launch the gNB in `monolithic` mode:
|
||||
```bash
|
||||
sudo RFSIMULATOR=server ./nr-softmodem --rfsim --sa \
|
||||
-O ../../../targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.fr1.106PRB.usrpb210.conf
|
||||
```
|
||||
- To launch the gNB in `CU/DU split` mode:
|
||||
|
||||
1. Launch the CU component:
|
||||
```bash
|
||||
sudo RFSIMULATOR=server ./nr-softmodem --rfsim --sa \
|
||||
-O ../../../ci-scripts/conf_files/gNB_SA_CU.conf
|
||||
```
|
||||
2. Launch the DU component:
|
||||
```bash
|
||||
sudo RFSIMULATOR=server ./nr-softmodem --rfsim --sa \
|
||||
-O ../../../ci-scripts/conf_files/gNB_SA_DU.conf
|
||||
```
|
||||
|
||||
- To launch the OAI UE (valid in `monolithic` gNB and `CU/DU split` gNB):
|
||||
```bash
|
||||
sudo RFSIMULATOR=127.0.0.1 ./nr-uesoftmodem -r 106 --numerology 1 --band 78 -C 3619200000 \
|
||||
--rfsim --sa -O <PATH_TO_UE_CONF_FILE>
|
||||
```
|
||||
|
||||
If you get the following error:
|
||||
|
||||
```bash
|
||||
Assertion (k2 >= ((5))) failed!
|
||||
In get_k2() /home/mir/workspace/openairinterface5g/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c:147
|
||||
Slot offset K2 (2) cannot be less than DURATION_RX_TO_TX (5). K2 set according to min_rxtxtime in config file.
|
||||
```
|
||||
|
||||
Add the following parameter (i.e., min_rxtxtime) in the gNB configuration file, just after nr_cellid.
|
||||
|
||||
```bash
|
||||
nr_cellid = 12345678L;
|
||||
min_rxtxtime=6;
|
||||
```
|
||||
or --gNBs.[0].min_rxtxtime 6 to the gNB command line
|
||||
|
||||
|
||||
The IP address at the execution command of the OAI UE corresponds to the target IP of the gNB host that the RFSIMULATOR at the UE will connect to. In the above example, we assume that the gNB and UE are running on the same host so the specified address (127.0.0.1) is the one of the loopback interface.
|
||||
@@ -84,7 +84,7 @@ int nr_rlc_get_available_tx_space(const rnti_t rntiP, const logical_chan_id_t ch
|
||||
return 0;
|
||||
}
|
||||
|
||||
void rrc_gNB_generate_dedicatedRRCReconfiguration(const protocol_ctxt_t *const ctxt_pP, rrc_gNB_ue_context_t *ue_context_pP)
|
||||
void rrc_gNB_generate_dedicatedRRCReconfiguration(const protocol_ctxt_t *const ctxt_pP, rrc_gNB_ue_context_t *ue_context_pP, NR_CellGroupConfig_t *cell_groupConfig_from_DU)
|
||||
{
|
||||
abort();
|
||||
}
|
||||
|
||||
@@ -52,11 +52,6 @@
|
||||
#include "PHY/MODULATION/nr_modulation.h"
|
||||
#include "PHY/NR_TRANSPORT/nr_dlsch.h"
|
||||
#include "openair2/NR_PHY_INTERFACE/nr_sched_response.h"
|
||||
#include "common/utils/thread_pool/task_manager.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <sys/sysinfo.h>
|
||||
|
||||
#undef MALLOC //there are two conflicting definitions, so we better make sure we don't use it at all
|
||||
//#undef FRAME_LENGTH_COMPLEX_SAMPLES //there are two conflicting definitions, so we better make sure we don't use it at all
|
||||
@@ -93,7 +88,6 @@
|
||||
#include <openair1/PHY/NR_TRANSPORT/nr_dlsch.h>
|
||||
#include <PHY/NR_ESTIMATION/nr_ul_estimation.h>
|
||||
|
||||
|
||||
//#define USRP_DEBUG 1
|
||||
// Fix per CC openair rf/if device update
|
||||
// extern openair0_device openair0;
|
||||
@@ -116,8 +110,7 @@ time_stats_t softmodem_stats_rx_sf; // total rx time
|
||||
#define L1STATSSTRLEN 16384
|
||||
|
||||
|
||||
void tx_func(void *param)
|
||||
{
|
||||
void tx_func(void *param) {
|
||||
|
||||
processingData_L1tx_t *info = (processingData_L1tx_t *) param;
|
||||
int frame_tx = info->frame;
|
||||
@@ -126,7 +119,6 @@ void tx_func(void *param)
|
||||
int absslot_tx = info->timestamp_tx/info->gNB->frame_parms.get_samples_per_slot(slot_tx,&info->gNB->frame_parms);
|
||||
int absslot_rx = absslot_tx-info->gNB->RU_list[0]->sl_ahead;
|
||||
int rt_prof_idx = absslot_rx % RT_PROF_DEPTH;
|
||||
start_meas(&info->gNB->phy_proc_tx);
|
||||
|
||||
clock_gettime(CLOCK_MONOTONIC,&info->gNB->rt_L1_profiling.start_L1_TX[rt_prof_idx]);
|
||||
phy_procedures_gNB_TX(info,
|
||||
@@ -135,47 +127,10 @@ void tx_func(void *param)
|
||||
1);
|
||||
clock_gettime(CLOCK_MONOTONIC,&info->gNB->rt_L1_profiling.return_L1_TX[rt_prof_idx]);
|
||||
|
||||
if (get_softmodem_params()->reorder_thread_disable) {
|
||||
PHY_VARS_gNB *gNB = info->gNB;
|
||||
processingData_RU_t syncMsgRU;
|
||||
syncMsgRU.frame_tx = frame_tx;
|
||||
syncMsgRU.slot_tx = slot_tx;
|
||||
syncMsgRU.ru = gNB->RU_list[0];
|
||||
syncMsgRU.timestamp_tx = info->timestamp_tx;
|
||||
LOG_D(PHY,"gNB: %d.%d : calling RU TX function\n",syncMsgRU.frame_tx,syncMsgRU.slot_tx);
|
||||
ru_tx_func((void*)&syncMsgRU);
|
||||
}
|
||||
/* this thread is done with the sched_info, decrease the reference counter */
|
||||
deref_sched_response(info->sched_response_id);
|
||||
stop_meas(&info->gNB->phy_proc_tx);
|
||||
}
|
||||
|
||||
|
||||
void *L1_rx_thread(void *arg)
|
||||
{
|
||||
PHY_VARS_gNB *gNB = (PHY_VARS_gNB*)arg;
|
||||
|
||||
while (oai_exit == 0) {
|
||||
notifiedFIFO_elt_t *res = pullNotifiedFIFO(&gNB->resp_L1);
|
||||
processingData_L1_t *info = (processingData_L1_t *)NotifiedFifoData(res);
|
||||
rx_func(info);
|
||||
delNotifiedFIFO_elt(res);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
/* to be added for URLLC, requires MAC scheduling to be split from UL indication
|
||||
void *L1_tx_thread(void *arg) {
|
||||
PHY_VARS_gNB *gNB = (PHY_VARS_gNB*)arg;
|
||||
|
||||
while (oai_exit == 0) {
|
||||
notifiedFIFO_elt_t *res = pullNotifiedFIFO(&gNB->L1_tx_out);
|
||||
processingData_L1tx_t *info = (processingData_L1tx_t *)NotifiedFifoData(res);
|
||||
tx_func(info);
|
||||
delNotifiedFIFO_elt(res);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
*/
|
||||
void rx_func(void *param)
|
||||
{
|
||||
processingData_L1_t *info = (processingData_L1_t *) param;
|
||||
@@ -234,16 +189,14 @@ void rx_func(void *param)
|
||||
// Do PRACH RU processing
|
||||
L1_nr_prach_procedures(gNB,frame_rx,slot_rx);
|
||||
|
||||
//WA: comment rotation in tx/rx
|
||||
if((gNB->num_RU == 1) && (gNB->RU_list[0]->if_south != REMOTE_IF4p5)) {
|
||||
//apply the rx signal rotation here
|
||||
for (int aa = 0; aa < gNB->frame_parms.nb_antennas_rx; aa++) {
|
||||
apply_nr_rotation_ul(&gNB->frame_parms,
|
||||
gNB->common_vars.rxdataF[aa],
|
||||
slot_rx,
|
||||
0,
|
||||
gNB->frame_parms.Ncp==EXTENDED?12:14);
|
||||
}
|
||||
//apply the rx signal rotation here
|
||||
for (int aa = 0; aa < gNB->frame_parms.nb_antennas_rx; aa++) {
|
||||
apply_nr_rotation_ul(&gNB->frame_parms,
|
||||
gNB->common_vars.rxdataF[aa],
|
||||
slot_rx,
|
||||
0,
|
||||
gNB->frame_parms.Ncp==EXTENDED?12:14,
|
||||
NR_LINK_TYPE_UL);
|
||||
}
|
||||
phy_procedures_gNB_uespec_RX(gNB, frame_rx, slot_rx);
|
||||
}
|
||||
@@ -254,37 +207,29 @@ void rx_func(void *param)
|
||||
|
||||
// Call the scheduler
|
||||
start_meas(&gNB->ul_indication_stats);
|
||||
// pthread_mutex_lock(&gNB->UL_INFO_mutex);
|
||||
pthread_mutex_lock(&gNB->UL_INFO_mutex);
|
||||
gNB->UL_INFO.frame = frame_rx;
|
||||
gNB->UL_INFO.slot = slot_rx;
|
||||
gNB->UL_INFO.module_id = gNB->Mod_id;
|
||||
gNB->UL_INFO.CC_id = gNB->CC_id;
|
||||
gNB->if_inst->NR_UL_indication(&gNB->UL_INFO);
|
||||
// pthread_mutex_unlock(&gNB->UL_INFO_mutex);
|
||||
pthread_mutex_unlock(&gNB->UL_INFO_mutex);
|
||||
stop_meas(&gNB->ul_indication_stats);
|
||||
|
||||
int tx_slot_type = nr_slot_select(cfg,frame_tx,slot_tx);
|
||||
int tx_slot_type = nr_slot_select(cfg,frame_rx,slot_tx);
|
||||
if ((tx_slot_type == NR_DOWNLINK_SLOT || tx_slot_type == NR_MIXED_SLOT) && NFAPI_MODE != NFAPI_MODE_PNF) {
|
||||
notifiedFIFO_elt_t *res;
|
||||
processingData_L1tx_t *syncMsg;
|
||||
// Its a FIFO so it maitains the order in which the MAC fills the messages
|
||||
// so no need for checking for right slot
|
||||
if (get_softmodem_params()->reorder_thread_disable) {
|
||||
// call the TX function directly from this thread
|
||||
syncMsg = gNB->msgDataTx;
|
||||
syncMsg->gNB = gNB;
|
||||
syncMsg->timestamp_tx = info->timestamp_tx;
|
||||
tx_func(syncMsg);
|
||||
} else {
|
||||
res = pullTpool(&gNB->L1_tx_filled, &gNB->threadPool);
|
||||
if (res == NULL)
|
||||
return; // Tpool has been stopped
|
||||
syncMsg = (processingData_L1tx_t *)NotifiedFifoData(res);
|
||||
syncMsg->gNB = gNB;
|
||||
syncMsg->timestamp_tx = info->timestamp_tx;
|
||||
res->key = slot_tx;
|
||||
pushTpool(&gNB->threadPool, res);
|
||||
}
|
||||
res = pullTpool(&gNB->L1_tx_filled, &gNB->threadPool);
|
||||
if (res == NULL)
|
||||
return; // Tpool has been stopped
|
||||
syncMsg = (processingData_L1tx_t *)NotifiedFifoData(res);
|
||||
syncMsg->gNB = gNB;
|
||||
syncMsg->timestamp_tx = info->timestamp_tx;
|
||||
res->key = slot_tx;
|
||||
pushTpool(&gNB->threadPool, res);
|
||||
} else if (get_softmodem_params()->continuous_tx) {
|
||||
notifiedFIFO_elt_t *res = pullTpool(&gNB->L1_tx_free, &gNB->threadPool);
|
||||
if (res == NULL)
|
||||
@@ -343,11 +288,6 @@ static size_t dump_L1_meas_stats(PHY_VARS_gNB *gNB, RU_t *ru, char *output, size
|
||||
const char *end = output + outputlen;
|
||||
output += print_meas_log(&gNB->phy_proc_tx, "L1 Tx processing", NULL, NULL, output, end - output);
|
||||
output += print_meas_log(&gNB->dlsch_encoding_stats, "DLSCH encoding", NULL, NULL, output, end - output);
|
||||
output += print_meas_log(&gNB->dlsch_scrambling_stats, "DLSCH scrambling", NULL, NULL, output, end-output);
|
||||
output += print_meas_log(&gNB->dlsch_modulation_stats, "DLSCH modulation", NULL, NULL, output, end-output);
|
||||
output += print_meas_log(&gNB->dlsch_layer_mapping_stats, "DLSCH layer mapping", NULL, NULL, output,end-output);
|
||||
output += print_meas_log(&gNB->dlsch_resource_mapping_stats, "DLSCH resource mapping", NULL, NULL, output,end-output);
|
||||
output += print_meas_log(&gNB->dlsch_precoding_stats, "DLSCH precoding", NULL, NULL, output,end-output);
|
||||
output += print_meas_log(&gNB->phy_proc_rx, "L1 Rx processing", NULL, NULL, output, end - output);
|
||||
output += print_meas_log(&gNB->ul_indication_stats, "UL Indication", NULL, NULL, output, end - output);
|
||||
output += print_meas_log(&gNB->rx_pusch_stats, "PUSCH inner-receiver", NULL, NULL, output, end - output);
|
||||
@@ -392,11 +332,7 @@ void *nrL1_stats_thread(void *param) {
|
||||
reset_meas(&gNB->rx_pusch_stats);
|
||||
reset_meas(&gNB->ulsch_decoding_stats);
|
||||
reset_meas(&gNB->schedule_response_stats);
|
||||
reset_meas(&gNB->dlsch_scrambling_stats);
|
||||
reset_meas(&gNB->dlsch_modulation_stats);
|
||||
reset_meas(&gNB->dlsch_layer_mapping_stats);
|
||||
reset_meas(&gNB->dlsch_resource_mapping_stats);
|
||||
reset_meas(&gNB->dlsch_precoding_stats);
|
||||
|
||||
while (!oai_exit) {
|
||||
sleep(1);
|
||||
dump_nr_I0_stats(fd,gNB);
|
||||
@@ -472,13 +408,6 @@ void init_gNB_Tpool(int inst) {
|
||||
gNB = RC.gNB[inst];
|
||||
gNB_L1_proc_t *proc = &gNB->proc;
|
||||
|
||||
#ifdef TASK_MANAGER
|
||||
int log_cores = get_nprocs_conf();
|
||||
assert(log_cores > 0);
|
||||
// Assuming: 2 x Physical cores = Logical cores
|
||||
init_task_manager(&gNB->man, log_cores/2);
|
||||
#endif
|
||||
|
||||
// ULSCH decoding threadpool
|
||||
initTpool(get_softmodem_params()->threadPoolConfig, &gNB->threadPool, cpumeas(CPUMEAS_GETSTATE));
|
||||
// ULSCH decoder result FIFO
|
||||
@@ -486,49 +415,31 @@ void init_gNB_Tpool(int inst) {
|
||||
|
||||
// L1 RX result FIFO
|
||||
initNotifiedFIFO(&gNB->resp_L1);
|
||||
if (!get_softmodem_params()->reorder_thread_disable) {
|
||||
notifiedFIFO_elt_t *msg = newNotifiedFIFO_elt(sizeof(processingData_L1_t), 0, &gNB->resp_L1, rx_func);
|
||||
pushNotifiedFIFO(&gNB->resp_L1, msg); // to unblock the process in the beginning
|
||||
}
|
||||
notifiedFIFO_elt_t *msg = newNotifiedFIFO_elt(sizeof(processingData_L1_t), 0, &gNB->resp_L1, rx_func);
|
||||
pushNotifiedFIFO(&gNB->resp_L1, msg); // to unblock the process in the beginning
|
||||
|
||||
// L1 TX result FIFO
|
||||
initNotifiedFIFO(&gNB->L1_tx_free);
|
||||
initNotifiedFIFO(&gNB->L1_tx_filled);
|
||||
initNotifiedFIFO(&gNB->L1_tx_out);
|
||||
|
||||
if (get_softmodem_params()->reorder_thread_disable) {
|
||||
// create the RX thread responsible for triggering RX processing and then TX processing if a single thread is used
|
||||
threadCreate(&gNB->L1_rx_thread, L1_rx_thread, (void *)gNB, "L1_rx_thread",
|
||||
gNB->L1_rx_thread_core, OAI_PRIORITY_RT_MAX);
|
||||
// if separate threads are used for RX and TX, create the TX thread
|
||||
// threadCreate(&gNB->L1_tx_thread, L1_tx_thread, (void *)gNB, "L1_tx_thread",
|
||||
// gNB->L1_tx_thread_core, OAI_PRIORITY_RT_MAX);
|
||||
|
||||
|
||||
// we create 2 threads for L1 tx processing
|
||||
for (int i=0; i < 2; i++) {
|
||||
notifiedFIFO_elt_t *msgL1Tx = newNotifiedFIFO_elt(sizeof(processingData_L1tx_t), 0, &gNB->L1_tx_out, tx_func);
|
||||
processingData_L1tx_t *msgDataTx = (processingData_L1tx_t *)NotifiedFifoData(msgL1Tx);
|
||||
memset(msgDataTx, 0, sizeof(processingData_L1tx_t));
|
||||
init_DLSCH_struct(gNB, msgDataTx);
|
||||
memset(msgDataTx->ssb, 0, 64*sizeof(NR_gNB_SSB_t));
|
||||
// this will be removed when the msgDataTx is not necessary anymore
|
||||
gNB->msgDataTx = msgDataTx;
|
||||
} else {
|
||||
// we create 2 threads for L1 tx processing
|
||||
for (int i=0; i < 2; i++) {
|
||||
notifiedFIFO_elt_t *msgL1Tx = newNotifiedFIFO_elt(sizeof(processingData_L1tx_t), 0, &gNB->L1_tx_out, tx_func);
|
||||
processingData_L1tx_t *msgDataTx = (processingData_L1tx_t *)NotifiedFifoData(msgL1Tx);
|
||||
memset(msgDataTx, 0, sizeof(processingData_L1tx_t));
|
||||
init_DLSCH_struct(gNB, msgDataTx);
|
||||
memset(msgDataTx->ssb, 0, 64*sizeof(NR_gNB_SSB_t));
|
||||
pushNotifiedFIFO(&gNB->L1_tx_free, msgL1Tx); // to unblock the process in the beginning
|
||||
}
|
||||
|
||||
LOG_I(PHY,"Creating thread for TX reordering and dispatching to RU\n");
|
||||
threadCreate(&proc->pthread_tx_reorder, tx_reorder_thread, (void *)gNB, "thread_tx_reorder",
|
||||
gNB->RU_list[0] ? gNB->RU_list[0]->tpcores[1] : -1, OAI_PRIORITY_RT_MAX);
|
||||
pushNotifiedFIFO(&gNB->L1_tx_free, msgL1Tx); // to unblock the process in the beginning
|
||||
}
|
||||
|
||||
if ((!get_softmodem_params()->emulate_l1) && (!IS_SOFTMODEM_NOSTATS_BIT) && (NFAPI_MODE!=NFAPI_MODE_VNF))
|
||||
threadCreate(&proc->L1_stats_thread,nrL1_stats_thread,(void*)gNB,"L1_stats",-1,OAI_PRIORITY_RT_LOW);
|
||||
|
||||
LOG_I(PHY,"Creating thread for TX reordering and dispatching to RU\n");
|
||||
threadCreate(&proc->pthread_tx_reorder, tx_reorder_thread, (void *)gNB, "thread_tx_reorder",
|
||||
gNB->RU_list[0] ? gNB->RU_list[0]->tpcores[1] : -1, OAI_PRIORITY_RT_MAX);
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -597,7 +508,6 @@ void init_eNB_afterRU(void) {
|
||||
|
||||
gNB = RC.gNB[inst];
|
||||
gNB->ldpc_offload_flag = ldpc_offload_flag;
|
||||
gNB->reorder_thread_disable = get_softmodem_params()->reorder_thread_disable;
|
||||
|
||||
phy_init_nr_gNB(gNB);
|
||||
|
||||
@@ -676,7 +586,6 @@ void init_gNB(int single_thread_flag,int wait_for_sync) {
|
||||
gNB->prach_energy_counter = 0;
|
||||
gNB->chest_time = get_softmodem_params()->chest_time;
|
||||
gNB->chest_freq = get_softmodem_params()->chest_freq;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -60,7 +60,6 @@ unsigned short config_frames[4] = {2,9,11,13};
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
/* these variables have to be defined before including ENB_APP/enb_paramdef.h and GNB_APP/gnb_paramdef.h */
|
||||
static int DEFBANDS[] = {7};
|
||||
static int DEFENBS[] = {0};
|
||||
@@ -84,8 +83,6 @@ static int DEFRUTPCORES[] = {-1,-1,-1,-1};
|
||||
|
||||
extern int oai_exit;
|
||||
|
||||
uint16_t sl_ahead;
|
||||
|
||||
extern struct timespec timespec_sub(struct timespec lhs, struct timespec rhs);
|
||||
extern struct timespec timespec_add(struct timespec lhs, struct timespec rhs);
|
||||
extern void nr_phy_free_RU(RU_t *);
|
||||
@@ -1088,7 +1085,7 @@ void *ru_thread( void *param ) {
|
||||
ru_thread_status = 0;
|
||||
// set default return value
|
||||
sprintf(threadname,"ru_thread %u",ru->idx);
|
||||
LOG_I(PHY,"Starting RU %d (%s,%s) on cpu %d\n",ru->idx,NB_functions[ru->function],NB_timing[ru->if_timing],sched_getcpu());
|
||||
LOG_I(PHY,"Starting RU %d (%s,%s),\n",ru->idx,NB_functions[ru->function],NB_timing[ru->if_timing]);
|
||||
memcpy((void *)&ru->config,(void *)&RC.gNB[0]->gNB_config,sizeof(ru->config));
|
||||
|
||||
if(emulate_rf) {
|
||||
@@ -1284,13 +1281,9 @@ void *ru_thread( void *param ) {
|
||||
} // end if (slot_type == NR_UPLINK_SLOT || slot_type == NR_MIXED_SLOT) {
|
||||
|
||||
// At this point, all information for subframe has been received on FH interface
|
||||
if (!get_softmodem_params()->reorder_thread_disable) {
|
||||
res = pullTpool(&gNB->resp_L1, &gNB->threadPool);
|
||||
if (res == NULL)
|
||||
break; // Tpool has been stopped
|
||||
} else {
|
||||
res=newNotifiedFIFO_elt(sizeof(processingData_L1_t),0, &gNB->resp_L1,NULL);
|
||||
}
|
||||
res = pullTpool(&gNB->resp_L1, &gNB->threadPool);
|
||||
if (res == NULL)
|
||||
break; // Tpool has been stopped
|
||||
syncMsg = (processingData_L1_t *)NotifiedFifoData(res);
|
||||
syncMsg->gNB = gNB;
|
||||
syncMsg->frame_rx = proc->frame_rx;
|
||||
@@ -1299,10 +1292,7 @@ void *ru_thread( void *param ) {
|
||||
syncMsg->slot_tx = proc->tti_tx;
|
||||
syncMsg->timestamp_tx = proc->timestamp_tx;
|
||||
res->key = proc->tti_rx;
|
||||
if (!get_softmodem_params()->reorder_thread_disable)
|
||||
pushTpool(&gNB->threadPool, res);
|
||||
else
|
||||
pushNotifiedFIFO(&gNB->resp_L1, res);
|
||||
pushTpool(&gNB->threadPool, res);
|
||||
}
|
||||
|
||||
printf( "Exiting ru_thread \n");
|
||||
@@ -1317,8 +1307,7 @@ int start_streaming(RU_t *ru) {
|
||||
}
|
||||
|
||||
int nr_start_if(struct RU_t_s *ru, struct PHY_VARS_gNB_s *gNB) {
|
||||
if (ru->if_south <= REMOTE_IF5)
|
||||
for (int i=0;i<ru->nb_rx;i++) ru->openair0_cfg.rxbase[i] = ru->common.rxdata[i];
|
||||
for (int i=0;i<ru->nb_rx;i++) ru->openair0_cfg.rxbase[i] = ru->common.rxdata[i];
|
||||
ru->openair0_cfg.rxsize = ru->nr_frame_parms->samples_per_subframe*10;
|
||||
reset_meas(&ru->ifdevice.tx_fhaul);
|
||||
return(ru->ifdevice.trx_start_func(&ru->ifdevice));
|
||||
@@ -1355,7 +1344,7 @@ void init_RU_proc(RU_t *ru) {
|
||||
|
||||
pthread_mutex_init( &proc->mutex_emulateRF,NULL);
|
||||
pthread_cond_init( &proc->cond_emulateRF, NULL);
|
||||
threadCreate( &proc->pthread_FH, ru_thread, (void *)ru, "ru_thread", ru->ru_thread_core, OAI_PRIORITY_RT_MAX );
|
||||
threadCreate( &proc->pthread_FH, ru_thread, (void *)ru, "ru_thread", ru->tpcores[0], OAI_PRIORITY_RT_MAX );
|
||||
|
||||
if(emulate_rf)
|
||||
threadCreate( &proc->pthread_emulateRF, emulatedRF_thread, (void *)proc, "emulateRF", -1, OAI_PRIORITY_RT );
|
||||
@@ -1681,7 +1670,7 @@ void set_function_spec_param(RU_t *ru) {
|
||||
case REMOTE_IF4p5:
|
||||
ru->do_prach = 0;
|
||||
ru->feprx = NULL; // DFTs
|
||||
ru->feptx_prec = nr_feptx_prec; // Precoding operation
|
||||
ru->feptx_prec = NULL; // Precoding operation
|
||||
ru->feptx_ofdm = NULL; // no OFDM mod
|
||||
ru->fh_south_in = fh_if4p5_south_in; // synchronous IF4p5 reception
|
||||
ru->fh_south_out = fh_if4p5_south_out; // synchronous IF4p5 transmission
|
||||
@@ -1793,25 +1782,23 @@ void init_NR_RU(char *rf_config_file) {
|
||||
set_function_spec_param(ru);
|
||||
LOG_I(PHY,"Starting ru_thread %d\n",ru_id);
|
||||
init_RU_proc(ru);
|
||||
if (ru->if_south != REMOTE_IF4p5) {
|
||||
int threadCnt = ru->num_tpcores;
|
||||
if (threadCnt < 2) LOG_E(PHY,"Number of threads for gNB should be more than 1. Allocated only %d\n",threadCnt);
|
||||
else LOG_I(PHY,"RU Thread pool size %d\n",threadCnt);
|
||||
char pool[80];
|
||||
int s_offset = sprintf(pool,"%d",ru->tpcores[0]);
|
||||
for (int icpu=1; icpu<threadCnt; icpu++) {
|
||||
s_offset+=sprintf(pool+s_offset,",%d",ru->tpcores[icpu]);
|
||||
}
|
||||
LOG_I(PHY,"RU thread-pool core string %s\n",pool);
|
||||
ru->threadPool = (tpool_t*)malloc(sizeof(tpool_t));
|
||||
initTpool(pool, ru->threadPool, cpumeas(CPUMEAS_GETSTATE));
|
||||
// FEP RX result FIFO
|
||||
ru->respfeprx = (notifiedFIFO_t*) malloc(sizeof(notifiedFIFO_t));
|
||||
initNotifiedFIFO(ru->respfeprx);
|
||||
// FEP TX result FIFO
|
||||
ru->respfeptx = (notifiedFIFO_t*) malloc(sizeof(notifiedFIFO_t));
|
||||
initNotifiedFIFO(ru->respfeptx);
|
||||
int threadCnt = ru->num_tpcores;
|
||||
if (threadCnt < 2) LOG_E(PHY,"Number of threads for gNB should be more than 1. Allocated only %d\n",threadCnt);
|
||||
else LOG_I(PHY,"RU Thread pool size %d\n",threadCnt);
|
||||
char pool[80];
|
||||
int s_offset = sprintf(pool,"%d",ru->tpcores[0]);
|
||||
for (int icpu=1; icpu<threadCnt; icpu++) {
|
||||
s_offset+=sprintf(pool+s_offset,",%d",ru->tpcores[icpu]);
|
||||
}
|
||||
LOG_I(PHY,"RU thread-pool core string %s\n",pool);
|
||||
ru->threadPool = (tpool_t*)malloc(sizeof(tpool_t));
|
||||
initTpool(pool, ru->threadPool, cpumeas(CPUMEAS_GETSTATE));
|
||||
// FEP RX result FIFO
|
||||
ru->respfeprx = (notifiedFIFO_t*) malloc(sizeof(notifiedFIFO_t));
|
||||
initNotifiedFIFO(ru->respfeprx);
|
||||
// FEP TX result FIFO
|
||||
ru->respfeptx = (notifiedFIFO_t*) malloc(sizeof(notifiedFIFO_t));
|
||||
initNotifiedFIFO(ru->respfeptx);
|
||||
} // for ru_id
|
||||
|
||||
// sleep(1);
|
||||
@@ -1829,30 +1816,18 @@ void stop_RU(int nb_ru) {
|
||||
|
||||
/* --------------------------------------------------------*/
|
||||
/* from here function to use configuration module */
|
||||
static void NRRCconfig_RU(void)
|
||||
{
|
||||
static void NRRCconfig_RU(void) {
|
||||
int i = 0, j = 0;
|
||||
paramdef_t RUParams[] = RUPARAMS_DESC;
|
||||
paramlist_def_t RUParamList = {CONFIG_STRING_RU_LIST,NULL,0};
|
||||
config_getlist(&RUParamList, RUParams, sizeof(RUParams)/sizeof(paramdef_t), NULL);
|
||||
config_getlist( &RUParamList, RUParams, sizeof(RUParams)/sizeof(paramdef_t), NULL);
|
||||
|
||||
paramdef_t GNBSParams[] = GNBSPARAMS_DESC;
|
||||
paramdef_t GNBParams[] = GNBPARAMS_DESC;
|
||||
paramlist_def_t GNBParamList = {GNB_CONFIG_STRING_GNB_LIST, NULL, 0};
|
||||
config_get(GNBSParams, sizeof(GNBSParams) / sizeof(paramdef_t), NULL);
|
||||
int num_gnbs = GNBSParams[GNB_ACTIVE_GNBS_IDX].numelt;
|
||||
AssertFatal(num_gnbs > 0, "Failed to parse config file no gnbs %s \n", GNB_CONFIG_STRING_ACTIVE_GNBS);
|
||||
config_getlist(&GNBParamList, GNBParams, sizeof(GNBParams) / sizeof(paramdef_t), NULL);
|
||||
int N1 = *GNBParamList.paramarray[0][GNB_PDSCH_ANTENNAPORTS_N1_IDX].iptr;
|
||||
int N2 = *GNBParamList.paramarray[0][GNB_PDSCH_ANTENNAPORTS_N2_IDX].iptr;
|
||||
int XP = *GNBParamList.paramarray[0][GNB_PDSCH_ANTENNAPORTS_XP_IDX].iptr;
|
||||
int num_logical_antennas = N1 * N2 * XP;
|
||||
|
||||
if (RUParamList.numelt > 0) {
|
||||
if ( RUParamList.numelt > 0) {
|
||||
RC.ru = (RU_t **)malloc(RC.nb_RU*sizeof(RU_t *));
|
||||
RC.ru_mask = (1 << NB_RU) - 1;
|
||||
RC.ru_mask=(1<<NB_RU) - 1;
|
||||
printf("Set RU mask to %lx\n",RC.ru_mask);
|
||||
|
||||
for (int j = 0; j < RC.nb_RU; j++) {
|
||||
for (j = 0; j < RC.nb_RU; j++) {
|
||||
RC.ru[j] = (RU_t *)malloc(sizeof(RU_t));
|
||||
memset((void *)RC.ru[j],0,sizeof(RU_t));
|
||||
RC.ru[j]->idx = j;
|
||||
@@ -1861,13 +1836,12 @@ static void NRRCconfig_RU(void)
|
||||
printf("Creating RC.ru[%d]:%p\n", j, RC.ru[j]);
|
||||
RC.ru[j]->if_timing = synch_to_ext_device;
|
||||
|
||||
if (RC.nb_nr_L1_inst > 0)
|
||||
if (RC.nb_nr_L1_inst >0)
|
||||
RC.ru[j]->num_gNB = RUParamList.paramarray[j][RU_ENB_LIST_IDX].numelt;
|
||||
else
|
||||
RC.ru[j]->num_gNB = 0;
|
||||
|
||||
for (int i = 0; i < RC.ru[j]->num_gNB; i++)
|
||||
RC.ru[j]->gNB_list[i] = RC.gNB[RUParamList.paramarray[j][RU_ENB_LIST_IDX].iptr[i]];
|
||||
for (i=0; i<RC.ru[j]->num_gNB; i++) RC.ru[j]->gNB_list[i] = RC.gNB[RUParamList.paramarray[j][RU_ENB_LIST_IDX].iptr[i]];
|
||||
|
||||
if (config_isparamset(RUParamList.paramarray[j], RU_SDR_ADDRS)) {
|
||||
RC.ru[j]->openair0_cfg.sdr_addrs = strdup(*(RUParamList.paramarray[j][RU_SDR_ADDRS].strptr));
|
||||
@@ -1922,7 +1896,7 @@ static void NRRCconfig_RU(void)
|
||||
RC.ru[j]->openair0_cfg.tune_offset = get_softmodem_params()->tune_offset;
|
||||
|
||||
if (strcmp(*(RUParamList.paramarray[j][RU_LOCAL_RF_IDX].strptr), "yes") == 0) {
|
||||
if (!(config_isparamset(RUParamList.paramarray[j],RU_LOCAL_IF_NAME_IDX))) {
|
||||
if ( !(config_isparamset(RUParamList.paramarray[j],RU_LOCAL_IF_NAME_IDX)) ) {
|
||||
RC.ru[j]->if_south = LOCAL_RF;
|
||||
RC.ru[j]->function = gNodeB_3GPP;
|
||||
printf("Setting function for RU %d to gNodeB_3GPP\n",j);
|
||||
@@ -1996,8 +1970,6 @@ static void NRRCconfig_RU(void)
|
||||
} /* strcmp(local_rf, "yes") != 0 */
|
||||
|
||||
RC.ru[j]->nb_tx = *(RUParamList.paramarray[j][RU_NB_TX_IDX].uptr);
|
||||
AssertFatal(RC.ru[j]->nb_tx >= num_logical_antennas,
|
||||
"Number of logical antenna ports (set in config file with pdsch_AntennaPorts) cannot be larger than physical antennas (nb_tx)\n");
|
||||
RC.ru[j]->nb_rx = *(RUParamList.paramarray[j][RU_NB_RX_IDX].uptr);
|
||||
RC.ru[j]->att_tx = *(RUParamList.paramarray[j][RU_ATT_TX_IDX].uptr);
|
||||
RC.ru[j]->att_rx = *(RUParamList.paramarray[j][RU_ATT_RX_IDX].uptr);
|
||||
@@ -2006,8 +1978,7 @@ static void NRRCconfig_RU(void)
|
||||
RC.ru[j]->do_precoding = *(RUParamList.paramarray[j][RU_DO_PRECODING].iptr);
|
||||
RC.ru[j]->sl_ahead = *(RUParamList.paramarray[j][RU_SL_AHEAD].iptr);
|
||||
RC.ru[j]->num_bands = RUParamList.paramarray[j][RU_BAND_LIST_IDX].numelt;
|
||||
for (int i = 0; i < RC.ru[j]->num_bands; i++)
|
||||
RC.ru[j]->band[i] = RUParamList.paramarray[j][RU_BAND_LIST_IDX].iptr[i];
|
||||
for (i=0; i<RC.ru[j]->num_bands; i++) RC.ru[j]->band[i] = RUParamList.paramarray[j][RU_BAND_LIST_IDX].iptr[i];
|
||||
RC.ru[j]->openair0_cfg.nr_flag = *(RUParamList.paramarray[j][RU_NR_FLAG].iptr);
|
||||
RC.ru[j]->openair0_cfg.nr_band = RC.ru[j]->band[0];
|
||||
RC.ru[j]->openair0_cfg.nr_scs_for_raster = *(RUParamList.paramarray[j][RU_NR_SCS_FOR_RASTER].iptr);
|
||||
@@ -2016,18 +1987,16 @@ static void NRRCconfig_RU(void)
|
||||
RC.ru[j]->openair0_cfg.txfh_cores[0] = *(RUParamList.paramarray[j][RU_TXFH_CORE_ID].iptr);
|
||||
RC.ru[j]->num_tpcores = *(RUParamList.paramarray[j][RU_NUM_TP_CORES].iptr);
|
||||
RC.ru[j]->half_slot_parallelization = *(RUParamList.paramarray[j][RU_HALF_SLOT_PARALLELIZATION].iptr);
|
||||
RC.ru[j]->ru_thread_core = *(RUParamList.paramarray[j][RU_RU_THREAD_CORE].iptr);
|
||||
printf("[RU %d] Setting half-slot parallelization to %d\n",j,RC.ru[j]->half_slot_parallelization);
|
||||
AssertFatal(RC.ru[j]->num_tpcores <= RUParamList.paramarray[j][RU_TP_CORES].numelt, "Number of TP cores should be <=16\n");
|
||||
for (int i = 0; i < RC.ru[j]->num_tpcores; i++)
|
||||
RC.ru[j]->tpcores[i] = RUParamList.paramarray[j][RU_TP_CORES].iptr[i];
|
||||
for (i=0; i<RC.ru[j]->num_tpcores; i++) RC.ru[j]->tpcores[i] = RUParamList.paramarray[j][RU_TP_CORES].iptr[i];
|
||||
if (config_isparamset(RUParamList.paramarray[j], RU_BF_WEIGHTS_LIST_IDX)) {
|
||||
RC.ru[j]->nb_bfw = RUParamList.paramarray[j][RU_BF_WEIGHTS_LIST_IDX].numelt;
|
||||
|
||||
for (int i = 0; i < RC.ru[j]->num_gNB; i++) {
|
||||
for (i=0; i<RC.ru[j]->num_gNB; i++) {
|
||||
RC.ru[j]->bw_list[i] = (int32_t *)malloc16_clear((RC.ru[j]->nb_bfw)*sizeof(int32_t));
|
||||
for (int b = 0; b < RC.ru[j]->nb_bfw; b++)
|
||||
RC.ru[j]->bw_list[i][b] = RUParamList.paramarray[j][RU_BF_WEIGHTS_LIST_IDX].iptr[b];
|
||||
|
||||
for (int b=0; b<RC.ru[j]->nb_bfw; b++) RC.ru[j]->bw_list[i][b] = RUParamList.paramarray[j][RU_BF_WEIGHTS_LIST_IDX].iptr[b];
|
||||
}
|
||||
}
|
||||
}// j=0..num_rus
|
||||
|
||||
@@ -33,6 +33,13 @@
|
||||
#include "executables/softmodem-common.h"
|
||||
#include "PHY/NR_REFSIG/refsig_defs_ue.h"
|
||||
#include "radio/COMMON/common_lib.h"
|
||||
#include "LAYER2/nr_pdcp/nr_pdcp_entity.h"
|
||||
#include "SCHED_NR_UE/pucch_uci_ue_nr.h"
|
||||
#include "openair2/NR_UE_PHY_INTERFACE/NR_IF_Module.h"
|
||||
#include "openair1/PHY/NR_REFSIG/sss_nr.h"
|
||||
#include "common/utils/nr/nr_common.h"
|
||||
//#define DEBUG_PHY_SL_PROC
|
||||
#include "pdcp.h"
|
||||
#include "LAYER2/nr_pdcp/nr_pdcp_oai_api.h"
|
||||
|
||||
/*
|
||||
@@ -99,7 +106,8 @@
|
||||
typedef enum {
|
||||
pss = 0,
|
||||
pbch = 1,
|
||||
si = 2
|
||||
si = 2,
|
||||
psbch = 3,
|
||||
} sync_mode_t;
|
||||
|
||||
static void *NRUE_phy_stub_standalone_pnf_task(void *arg);
|
||||
@@ -160,12 +168,13 @@ void init_nr_ue_vars(PHY_VARS_NR_UE *ue,
|
||||
|
||||
// initialize all signal buffers
|
||||
init_nr_ue_signal(ue, nb_connected_gNB);
|
||||
if (get_softmodem_params()->sl_mode != 2) {
|
||||
// intialize transport
|
||||
init_nr_ue_transport(ue);
|
||||
|
||||
// intialize transport
|
||||
init_nr_ue_transport(ue);
|
||||
|
||||
// init N_TA offset
|
||||
init_N_TA_offset(ue);
|
||||
// init N_TA offset
|
||||
init_N_TA_offset(ue);
|
||||
}
|
||||
}
|
||||
|
||||
void init_nrUE_standalone_thread(int ue_idx)
|
||||
@@ -376,7 +385,12 @@ static void UE_synch(void *arg) {
|
||||
sync_mode_t sync_mode = pbch;
|
||||
//int CC_id = UE->CC_id;
|
||||
static int freq_offset=0;
|
||||
UE->is_synchronized = 0;
|
||||
if (get_softmodem_params()->sl_mode == 2) {
|
||||
UE->is_synchronized_sl = 0;
|
||||
sync_mode = psbch;
|
||||
} else {
|
||||
UE->is_synchronized = 0;
|
||||
}
|
||||
|
||||
if (UE->UE_scan == 0) {
|
||||
|
||||
@@ -392,7 +406,6 @@ static void UE_synch(void *arg) {
|
||||
|
||||
}
|
||||
|
||||
sync_mode = pbch;
|
||||
} else {
|
||||
LOG_E(PHY,"Fixme!\n");
|
||||
/*
|
||||
@@ -492,9 +505,44 @@ static void UE_synch(void *arg) {
|
||||
break;
|
||||
|
||||
case si:
|
||||
|
||||
case psbch: {
|
||||
int initial_synch_sl = nr_sl_initial_sync(&syncD->proc, UE, 2);
|
||||
if (initial_synch_sl >= 0) { // gNB will work as SyncRef UE in simulation.
|
||||
|
||||
// rerun with new cell parameters and frequency-offset
|
||||
freq_offset = UE->common_vars.freq_offset; // frequency offset computed with pss in initial sync
|
||||
nr_sl_rf_card_config_freq(UE, &openair0_cfg[UE->rf_map.card], freq_offset);
|
||||
UE->rfdevice.trx_set_freq_func(&UE->rfdevice,&openair0_cfg[0]);
|
||||
|
||||
if (UE->UE_scan_carrier == 1) {
|
||||
UE->UE_scan_carrier = 0;
|
||||
} else {
|
||||
if (initial_synch_sl == 0) {
|
||||
UE->is_synchronized_sl = 1;
|
||||
LOG_I(NR_PHY, "SyncRef UE found with Nid1 %d and Nid2 %d SSS-RSRP %d dBm/RE\n",
|
||||
GET_NID1_SL(UE->frame_parms.Nid_SL), GET_NID2_SL(UE->frame_parms.Nid_SL),
|
||||
UE->measurements.ssb_rsrp_dBm[0]);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
LOG_I(NR_PHY, "No SyncRef UE found\n");
|
||||
if (UE->UE_scan_carrier == 1) {
|
||||
LOG_I(PHY, "Initial sync failed: trying carrier off %d Hz\n", freq_offset);
|
||||
|
||||
if (freq_offset >= 0)
|
||||
freq_offset += 100;
|
||||
freq_offset *= -1;
|
||||
nr_sl_rf_card_config_freq(UE, &openair0_cfg[UE->rf_map.card], freq_offset);
|
||||
UE->rfdevice.trx_set_freq_func(&UE->rfdevice, &openair0_cfg[0]);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
break;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -561,6 +609,8 @@ void processSlotTX(void *arg) {
|
||||
nr_phy_data_tx_t phy_data = {0};
|
||||
|
||||
LOG_D(PHY,"%d.%d => slot type %d\n", proc->frame_tx, proc->nr_slot_tx, proc->tx_slot_type);
|
||||
if (UE->sync_ref && get_softmodem_params()->sl_mode != 0)
|
||||
proc->tx_slot_type = NR_UPLINK_SLOT;
|
||||
if (proc->tx_slot_type == NR_UPLINK_SLOT || proc->tx_slot_type == NR_MIXED_SLOT){
|
||||
|
||||
// wait for rx slots to send indication (if any) that DLSCH decoding is finished
|
||||
@@ -571,7 +621,7 @@ void processSlotTX(void *arg) {
|
||||
|
||||
// trigger L2 to run ue_scheduler thru IF module
|
||||
// [TODO] mapping right after NR initial sync
|
||||
if(UE->if_inst != NULL && UE->if_inst->ul_indication != NULL) {
|
||||
if (get_softmodem_params()->sl_mode != 2 && UE->if_inst != NULL && UE->if_inst->ul_indication != NULL) {
|
||||
start_meas(&UE->ue_ul_indication_stats);
|
||||
nr_uplink_indication_t ul_indication;
|
||||
memset((void*)&ul_indication, 0, sizeof(ul_indication));
|
||||
@@ -589,10 +639,20 @@ void processSlotTX(void *arg) {
|
||||
stop_meas(&UE->ue_ul_indication_stats);
|
||||
}
|
||||
|
||||
phy_procedures_nrUE_TX(UE, proc, &phy_data);
|
||||
if (get_softmodem_params()->sl_mode == 0) {
|
||||
phy_procedures_nrUE_TX(UE, proc, &phy_data);
|
||||
} else {
|
||||
phy_procedures_nrUE_SL_TX(UE, proc, 0);
|
||||
}
|
||||
}
|
||||
if (get_softmodem_params()->sl_mode == 0) {
|
||||
RU_write(rxtxD);
|
||||
}
|
||||
}
|
||||
|
||||
RU_write(rxtxD);
|
||||
void processSlotRX_SL(void *arg) {
|
||||
nr_rxtx_thread_data_t *rxtxD = (nr_rxtx_thread_data_t *) arg;
|
||||
processSlotTX(rxtxD);
|
||||
}
|
||||
|
||||
nr_phy_data_t UE_dl_preprocessing(PHY_VARS_NR_UE *UE, UE_nr_rxtx_proc_t *proc) {
|
||||
@@ -703,11 +763,11 @@ void readFrame(PHY_VARS_NR_UE *UE, openair0_timestamp *timestamp, bool toTrash)
|
||||
|
||||
void syncInFrame(PHY_VARS_NR_UE *UE, openair0_timestamp *timestamp) {
|
||||
|
||||
LOG_I(PHY,"Resynchronizing RX by %d samples\n",UE->rx_offset);
|
||||
int rx_offset = (get_softmodem_params()->sl_mode != 0) ? UE->rx_offset_sl : UE->rx_offset;
|
||||
|
||||
if (IS_SOFTMODEM_IQPLAYER || IS_SOFTMODEM_IQRECORDER) {
|
||||
// Resynchonize by slot (will work with numerology 1 only)
|
||||
for ( int size=UE->rx_offset ; size > 0 ; size -= UE->frame_parms.samples_per_subframe/2 ) {
|
||||
for (int size = rx_offset; size > 0; size -= UE->frame_parms.samples_per_subframe / 2) {
|
||||
int unitTransfer=size>UE->frame_parms.samples_per_subframe/2 ? UE->frame_parms.samples_per_subframe/2 : size ;
|
||||
AssertFatal(unitTransfer ==
|
||||
UE->rfdevice.trx_read_func(&UE->rfdevice,
|
||||
@@ -718,11 +778,11 @@ void syncInFrame(PHY_VARS_NR_UE *UE, openair0_timestamp *timestamp) {
|
||||
}
|
||||
} else {
|
||||
*timestamp += UE->frame_parms.get_samples_per_slot(1,&UE->frame_parms);
|
||||
for ( int size=UE->rx_offset ; size > 0 ; size -= UE->frame_parms.samples_per_subframe ) {
|
||||
for (int size = rx_offset; size > 0; size -= UE->frame_parms.samples_per_subframe) {
|
||||
int unitTransfer=size>UE->frame_parms.samples_per_subframe ? UE->frame_parms.samples_per_subframe : size ;
|
||||
// we write before read because gNB waits for UE to write and both executions halt
|
||||
// this happens here as the read size is samples_per_subframe which is very much larger than samp_per_slot
|
||||
if (IS_SOFTMODEM_RFSIM) dummyWrite(UE,*timestamp, unitTransfer);
|
||||
if (IS_SOFTMODEM_RFSIM) dummyWrite(UE,*timestamp, unitTransfer);
|
||||
AssertFatal(unitTransfer ==
|
||||
UE->rfdevice.trx_read_func(&UE->rfdevice,
|
||||
timestamp,
|
||||
@@ -734,22 +794,309 @@ void syncInFrame(PHY_VARS_NR_UE *UE, openair0_timestamp *timestamp) {
|
||||
}
|
||||
}
|
||||
|
||||
static inline int get_firstSymSamp(uint16_t slot, NR_DL_FRAME_PARMS *fp) {
|
||||
int computeSamplesShift(PHY_VARS_NR_UE *UE) {
|
||||
int samples_shift = -(UE->rx_offset>>1);
|
||||
if (samples_shift != 0) {
|
||||
LOG_I(NR_PHY,"Adjusting frame in time by %i samples\n", samples_shift);
|
||||
if (get_softmodem_params()->sl_mode == 0) {
|
||||
UE->rx_offset = 0; // reset so that it is not applied falsely in case of SSB being only in every second frame
|
||||
} else {
|
||||
UE->rx_offset_sl = 0; // reset so that it is not applied falsely in case of SSB being only in every second frame
|
||||
}
|
||||
UE->max_pos_fil += samples_shift << 15; // reset IIR filter when sample shift is applied
|
||||
}
|
||||
return samples_shift;
|
||||
}
|
||||
|
||||
static inline int get_firstSymSamp(uint16_t slot, NR_DL_FRAME_PARMS *fp, bool sync) {
|
||||
uint16_t nb_prefix_samples0 = fp->nb_prefix_samples0;
|
||||
if (get_softmodem_params()->sl_mode != 0) {
|
||||
nb_prefix_samples0 = sync ? fp->nb_prefix_samples0 : fp->nb_prefix_samples;
|
||||
}
|
||||
if (fp->numerology_index == 0)
|
||||
return fp->nb_prefix_samples0 + fp->ofdm_symbol_size;
|
||||
int num_samples = (slot%(fp->slots_per_subframe/2)) ? fp->nb_prefix_samples : fp->nb_prefix_samples0;
|
||||
int num_samples = (slot % (fp->slots_per_subframe / 2)) ? fp->nb_prefix_samples : nb_prefix_samples0;
|
||||
num_samples += fp->ofdm_symbol_size;
|
||||
return num_samples;
|
||||
}
|
||||
|
||||
static inline int get_readBlockSize(uint16_t slot, NR_DL_FRAME_PARMS *fp) {
|
||||
int rem_samples = fp->get_samples_per_slot(slot, fp) - get_firstSymSamp(slot, fp);
|
||||
static inline int get_readBlockSize(uint16_t slot, NR_DL_FRAME_PARMS *fp, bool sync) {
|
||||
int rem_samples = fp->get_samples_per_slot(slot, fp) - get_firstSymSamp(slot, fp, sync);
|
||||
int next_slot_first_symbol = 0;
|
||||
if (slot < (fp->slots_per_frame-1))
|
||||
next_slot_first_symbol = get_firstSymSamp(slot+1, fp);
|
||||
next_slot_first_symbol = get_firstSymSamp(slot+1, fp, sync);
|
||||
return rem_samples + next_slot_first_symbol;
|
||||
}
|
||||
|
||||
int slot_to_flag_sl(uint8_t tdd_period, int slot, uint16_t slot_config, uint16_t num_slot_frame) {
|
||||
int flag, isUL, isULnext, isULbefore;
|
||||
int num_period_slot = get_nb_periods_per_frame(tdd_period);
|
||||
slot = slot % (num_slot_frame / num_period_slot);
|
||||
isUL = (slot_config >> slot) & 0x1;// indicator to show if the slot is UL or DL
|
||||
|
||||
if (slot > 0) {
|
||||
//checking if previous slot is UL
|
||||
isULbefore = (slot_config >> (slot - 1)) & 0x1;
|
||||
} else {
|
||||
isULbefore = 0;
|
||||
}
|
||||
if (slot < (num_slot_frame / num_period_slot) - 1) {
|
||||
// checking if next slot is UL
|
||||
isULnext = (slot_config >> (slot+1)) & 0x1;
|
||||
} else {
|
||||
isULnext = 0;
|
||||
}
|
||||
|
||||
if (isUL) {
|
||||
if (slot == 0 || !isULbefore) {
|
||||
flag = 2; // first slot should start transmission
|
||||
} else if (slot == (num_slot_frame / num_period_slot) - 1 || !isULnext) {
|
||||
flag = 3; // last slot that should stop transmission
|
||||
} else {
|
||||
flag = 1; // it is niether first nor last slot.
|
||||
}
|
||||
} else {
|
||||
flag = 0; // don't transmit at all
|
||||
}
|
||||
LOG_D(NR_PHY, "### slot(%d), UL(%d), flag(%d)\n", slot, isUL, flag);
|
||||
return flag;
|
||||
}
|
||||
|
||||
void *UE_thread_SL(void *arg) {
|
||||
PHY_VARS_NR_UE *UE = (PHY_VARS_NR_UE *) arg;
|
||||
openair0_timestamp timestamp, writeTimestamp;
|
||||
void *rxp[NB_ANTENNAS_RX], *txp[NB_ANTENNAS_TX];
|
||||
AssertFatal(0 == openair0_device_load(&(UE->rfdevice), &openair0_cfg[0]), "");
|
||||
UE->rfdevice.host_type = RAU_HOST;
|
||||
AssertFatal(UE->rfdevice.trx_start_func(&UE->rfdevice) == 0, "Could not start the device\n");
|
||||
|
||||
notifiedFIFO_t nf;
|
||||
initNotifiedFIFO(&nf);
|
||||
notifiedFIFO_t freeBlocks;
|
||||
initNotifiedFIFO_nothreadSafe(&freeBlocks);
|
||||
int nbSlotProcessing = 0;
|
||||
|
||||
NR_UE_MAC_INST_t *mac = get_mac_inst(0);
|
||||
int timing_advance = UE->timing_advance;
|
||||
|
||||
UE->lost_sync_sl = 0;
|
||||
UE->is_synchronized_sl = 0;
|
||||
UE->sync_ref = get_softmodem_params()->sync_ref;
|
||||
bool sync_running_sl = false;
|
||||
const int nb_slot_frame = UE->frame_parms.slots_per_frame;
|
||||
int absolute_slot = 0, decoded_frame_rx = INT_MAX, trashed_frames = 0, start_rx_stream = 0;
|
||||
|
||||
for (int i = 0; i < NR_RX_NB_TH + 1; i++) {// NR_RX_NB_TH working + 1 we are making to be pushed
|
||||
notifiedFIFO_elt_t *newElt = newNotifiedFIFO_elt(sizeof(nr_rxtx_thread_data_t), RX_JOB_ID, &nf, processSlotRX_SL);
|
||||
nr_rxtx_thread_data_t *curMsg=(nr_rxtx_thread_data_t *)NotifiedFifoData(newElt);
|
||||
initNotifiedFIFO(&curMsg->txFifo);
|
||||
pushNotifiedFIFO_nothreadSafe(&freeBlocks, newElt);
|
||||
}
|
||||
|
||||
while (!oai_exit) {
|
||||
if (UE->lost_sync_sl && UE->sync_ref == 0) {
|
||||
LOG_I(NR_PHY, "Sync UE: lost_sync status\n");
|
||||
int nb = abortTpoolJob(&(get_nrUE_params()->Tpool),RX_JOB_ID);
|
||||
nb += abortNotifiedFIFOJob(&nf, RX_JOB_ID);
|
||||
LOG_I(PHY,"Number of aborted slots %d\n",nb);
|
||||
for (int i=0; i<nb; i++)
|
||||
pushNotifiedFIFO_nothreadSafe(&freeBlocks, newNotifiedFIFO_elt(sizeof(nr_rxtx_thread_data_t), RX_JOB_ID, &nf, processSlotRX_SL));
|
||||
nbSlotProcessing = 0;
|
||||
UE->is_synchronized_sl = 0;
|
||||
UE->lost_sync_sl = 0;
|
||||
}
|
||||
|
||||
if (sync_running_sl && UE->sync_ref == 0) {
|
||||
LOG_I(NR_PHY, "Nearby UE: sync_running status.\n");
|
||||
notifiedFIFO_elt_t *res=tryPullTpool(&nf,&(get_nrUE_params()->Tpool));
|
||||
if (res) {
|
||||
sync_running_sl = false;
|
||||
LOG_I(NR_PHY, "Nearby UE: sync_running was set to false due to valid res.\n");
|
||||
syncData_t *tmp=(syncData_t *)NotifiedFifoData(res);
|
||||
LOG_I(NR_PHY, "Nearby UE: UE->is_synchronized_sl = %d\n", UE->is_synchronized_sl);
|
||||
if (UE->is_synchronized_sl && get_softmodem_params()->sl_mode < 2) {
|
||||
decoded_frame_rx=(((mac->mib->systemFrameNumber.buf[0] >> mac->mib->systemFrameNumber.bits_unused)<<4) | tmp->proc.decoded_frame_rx);
|
||||
// shift the frame index with all the frames we trashed meanwhile we perform the synch search
|
||||
decoded_frame_rx=(decoded_frame_rx + UE->init_sync_frame + trashed_frames) % MAX_FRAME_NUMBER;
|
||||
}
|
||||
delNotifiedFIFO_elt(res);
|
||||
start_rx_stream = 0;
|
||||
} else {
|
||||
LOG_I(PHY, "Nearby UE: sync_running_sl still in readFrame due to INVALID res.\n");
|
||||
readFrame(UE, ×tamp, true);
|
||||
trashed_frames += 2;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
AssertFatal(!sync_running_sl, "At this point synchronization can't be running\n");
|
||||
|
||||
if (UE->is_synchronized_sl == 0 && UE->sync_ref == 0) {
|
||||
LOG_I(NR_PHY, "Sync UE: UE->is_synchronized_sl == 0 && UE->sync_ref == 0)\n");
|
||||
readFrame(UE, ×tamp, false);
|
||||
notifiedFIFO_elt_t *Msg=newNotifiedFIFO_elt(sizeof(syncData_t), 0, &nf, UE_synch);
|
||||
syncData_t *syncMsg = (syncData_t *)NotifiedFifoData(Msg);
|
||||
syncMsg->UE = UE;
|
||||
memset(&syncMsg->proc, 0, sizeof(syncMsg->proc));
|
||||
pushTpool(&(get_nrUE_params()->Tpool), Msg);
|
||||
trashed_frames=0;
|
||||
sync_running_sl =true;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (start_rx_stream == 0 && UE->sync_ref == 0) {
|
||||
start_rx_stream = 1;
|
||||
syncInFrame(UE, ×tamp);
|
||||
LOG_I(NR_PHY, "Sync UE: rx_stream = 1 and timestamp %ld\n", timestamp);
|
||||
UE->rx_offset_sl = 0;
|
||||
UE->time_sync_cell = 0;
|
||||
uint16_t nb_prefix_samples0 = UE->is_synchronized_sl ? UE->frame_parms.nb_prefix_samples0 :
|
||||
UE->frame_parms.nb_prefix_samples;
|
||||
AssertFatal (UE->frame_parms.ofdm_symbol_size + nb_prefix_samples0 ==
|
||||
UE->rfdevice.trx_read_func(&UE->rfdevice,
|
||||
×tamp,
|
||||
(void **)UE->common_vars.rxdata,
|
||||
UE->frame_parms.ofdm_symbol_size + nb_prefix_samples0,
|
||||
UE->frame_parms.nb_antennas_rx), "Could not read in first symbol");
|
||||
// we have the decoded frame index in the return of the synch process
|
||||
// and we shifted above to the first slot of next frame
|
||||
decoded_frame_rx++;
|
||||
// we do ++ first in the regular processing, so it will be begin of frame;
|
||||
absolute_slot = decoded_frame_rx * nb_slot_frame - 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
absolute_slot++;
|
||||
// Fix me: will be wrong when slot 1 is slow, as slot 2 finishes
|
||||
// Slot 3 will overlap if NR_RX_NB_TH is 2
|
||||
// this is general failure in UE !!
|
||||
int slot_nr = absolute_slot % nb_slot_frame;
|
||||
|
||||
notifiedFIFO_elt_t *msgToPush;
|
||||
AssertFatal((msgToPush=pullNotifiedFIFO_nothreadSafe(&freeBlocks)) != NULL,"chained list failure");
|
||||
nr_rxtx_thread_data_t *curMsg=(nr_rxtx_thread_data_t *)NotifiedFifoData(msgToPush);
|
||||
curMsg->UE = UE;
|
||||
// update thread index for received subframe
|
||||
curMsg->proc.CC_id = UE->CC_id;
|
||||
curMsg->proc.nr_slot_rx = slot_nr;
|
||||
curMsg->proc.nr_slot_tx = (absolute_slot + DURATION_RX_TO_TX) % nb_slot_frame;
|
||||
curMsg->proc.frame_rx = (absolute_slot/nb_slot_frame) % MAX_FRAME_NUMBER;
|
||||
curMsg->proc.frame_tx = ((absolute_slot+DURATION_RX_TO_TX)/nb_slot_frame) % MAX_FRAME_NUMBER;
|
||||
curMsg->proc.decoded_frame_rx=-1;
|
||||
LOG_D(NR_PHY, "Process slot %d total gain %d\n", slot_nr, UE->rx_total_gain_dB);
|
||||
|
||||
int firstSymSamp = get_firstSymSamp(slot_nr, &UE->frame_parms, UE->is_synchronized_sl);
|
||||
uint64_t write_time_stamp = UE->frame_parms.get_samples_slot_timestamp(slot_nr, &UE->frame_parms, 0);
|
||||
uint64_t read_time_stamp = UE->frame_parms.get_samples_slot_timestamp(slot_nr, &UE->frame_parms, 0);
|
||||
for (int i = 0; i<UE->frame_parms.nb_antennas_rx; i++)
|
||||
rxp[i] = (void *)&UE->common_vars.rxdata[i][read_time_stamp];
|
||||
for (int i = 0; i < UE->frame_parms.nb_antennas_tx; i++)
|
||||
txp[i] = (void *)&UE->common_vars.txdata[i][write_time_stamp];
|
||||
|
||||
int readBlockSize, writeBlockSize;
|
||||
if (slot_nr < (nb_slot_frame - 1)) {
|
||||
readBlockSize = get_readBlockSize(slot_nr, &UE->frame_parms, UE->is_synchronized_sl);
|
||||
writeBlockSize = UE->frame_parms.get_samples_per_slot(slot_nr, &UE->frame_parms);
|
||||
} else {
|
||||
UE->rx_offset_diff = computeSamplesShift(UE);
|
||||
readBlockSize = get_readBlockSize(slot_nr, &UE->frame_parms, UE->is_synchronized_sl) - UE->rx_offset_diff;
|
||||
writeBlockSize = UE->frame_parms.get_samples_per_slot(slot_nr, &UE->frame_parms) - UE->rx_offset_diff;
|
||||
}
|
||||
|
||||
AssertFatal(readBlockSize ==
|
||||
UE->rfdevice.trx_read_func(&UE->rfdevice,
|
||||
×tamp,
|
||||
rxp,
|
||||
readBlockSize,
|
||||
UE->frame_parms.nb_antennas_rx), "");
|
||||
|
||||
if (slot_nr == (nb_slot_frame - 1)) {
|
||||
// read in first symbol of next frame and adjust for timing drift
|
||||
uint16_t nb_prefix_samples0 = UE->is_synchronized_sl ? UE->frame_parms.nb_prefix_samples0 :
|
||||
UE->frame_parms.nb_prefix_samples;
|
||||
int first_symbols = UE->frame_parms.ofdm_symbol_size + nb_prefix_samples0;
|
||||
if (first_symbols > 0) {
|
||||
openair0_timestamp ignore_timestamp;
|
||||
AssertFatal(first_symbols ==
|
||||
UE->rfdevice.trx_read_func(&UE->rfdevice,
|
||||
&ignore_timestamp,
|
||||
(void **)UE->common_vars.rxdata,
|
||||
first_symbols,
|
||||
UE->frame_parms.nb_antennas_rx),"");
|
||||
} else {
|
||||
LOG_E(NR_PHY, "Can't compensate: diff =%d\n", first_symbols);
|
||||
}
|
||||
}
|
||||
|
||||
curMsg->proc.timestamp_tx = timestamp +
|
||||
UE->frame_parms.get_samples_slot_timestamp(slot_nr, &UE->frame_parms, DURATION_RX_TO_TX) -
|
||||
firstSymSamp;
|
||||
|
||||
while (nbSlotProcessing >= NR_RX_NB_TH) {
|
||||
notifiedFIFO_elt_t *res = pullTpool(&nf, &(get_nrUE_params()->Tpool));
|
||||
if (res == NULL)
|
||||
break; // Tpool has been stopped
|
||||
nbSlotProcessing--;
|
||||
nr_rxtx_thread_data_t *tmp = (nr_rxtx_thread_data_t *)res->msgData;
|
||||
if (tmp->proc.decoded_frame_rx != -1)
|
||||
decoded_frame_rx=(((mac->mib->systemFrameNumber.buf[0] >>
|
||||
mac->mib->systemFrameNumber.bits_unused) << 4) |
|
||||
tmp->proc.decoded_frame_rx);
|
||||
else
|
||||
decoded_frame_rx=-1;
|
||||
pushNotifiedFIFO_nothreadSafe(&freeBlocks,res);
|
||||
}
|
||||
|
||||
if (UE->sync_ref == 0 && decoded_frame_rx > 0 && decoded_frame_rx != curMsg->proc.frame_rx)
|
||||
LOG_E(NR_PHY, "Sync UE: Decoded frame index (%d) is not compatible with current context (%d), "
|
||||
"UE should go back to synch mode\n", decoded_frame_rx, curMsg->proc.frame_rx);
|
||||
|
||||
// use previous timing_advance value to compute writeTimestamp
|
||||
writeTimestamp = timestamp +
|
||||
UE->frame_parms.get_samples_slot_timestamp(slot_nr, &UE->frame_parms, DURATION_RX_TO_TX - NR_RX_NB_TH) -
|
||||
firstSymSamp - openair0_cfg[0].tx_sample_advance - UE->N_TA_offset - timing_advance;
|
||||
|
||||
// but use current UE->timing_advance value to compute writeBlockSize
|
||||
if (UE->timing_advance != timing_advance) {
|
||||
writeBlockSize -= UE->timing_advance - timing_advance;
|
||||
timing_advance = UE->timing_advance;
|
||||
}
|
||||
|
||||
int flags = 1;
|
||||
NR_DL_FRAME_PARMS *fp = &UE->frame_parms;
|
||||
flags = slot_to_flag_sl(fp->tdd_period, slot_nr, fp->tdd_slot_config, fp->slots_per_frame);
|
||||
|
||||
if (flags || IS_SOFTMODEM_RFSIM) {
|
||||
LOG_D(NR_PHY, "current slot goring to write USRP: %d\n", slot_nr);
|
||||
AssertFatal(writeBlockSize ==
|
||||
UE->rfdevice.trx_write_func(&UE->rfdevice,
|
||||
writeTimestamp,
|
||||
txp,
|
||||
writeBlockSize,
|
||||
UE->frame_parms.nb_antennas_tx,
|
||||
flags), "");
|
||||
}
|
||||
#ifdef DEBUG_PHY_SL_PROC
|
||||
char buffer[UE->frame_parms.ofdm_symbol_size];
|
||||
for (int i = 0; i < 13; i++) {
|
||||
bzero(buffer, sizeof(buffer));
|
||||
LOG_I(NR_PHY, "Transmitted SSB %d = %s\n",
|
||||
i, hexdump(&txp[0][UE->frame_parms.ofdm_symbol_size*i],
|
||||
UE->frame_parms.ofdm_symbol_size, buffer, sizeof(buffer)));
|
||||
}
|
||||
#endif
|
||||
for (int i = 0; i < UE->frame_parms.nb_antennas_tx; i++) {
|
||||
memset(txp[i], 0, writeBlockSize);
|
||||
}
|
||||
nbSlotProcessing++;
|
||||
LOG_D(NR_PHY, "Number of slots being processed at the moment: %d\n", nbSlotProcessing);
|
||||
pushTpool(&(get_nrUE_params()->Tpool), msgToPush);
|
||||
} // while !oai_exit
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void *UE_thread(void *arg) {
|
||||
//this thread should be over the processing thread to keep in real time
|
||||
PHY_VARS_NR_UE *UE = (PHY_VARS_NR_UE *) arg;
|
||||
@@ -887,20 +1234,21 @@ void *UE_thread(void *arg) {
|
||||
}*/
|
||||
#endif
|
||||
|
||||
int firstSymSamp = get_firstSymSamp(slot_nr, &UE->frame_parms);
|
||||
int firstSymSamp = get_firstSymSamp(slot_nr, &UE->frame_parms, UE->is_synchronized);
|
||||
for (int i=0; i<UE->frame_parms.nb_antennas_rx; i++)
|
||||
rxp[i] = (void *)&UE->common_vars.rxdata[i][firstSymSamp+
|
||||
UE->frame_parms.get_samples_slot_timestamp(slot_nr,&UE->frame_parms,0)];
|
||||
|
||||
int readBlockSize, writeBlockSize;
|
||||
|
||||
readBlockSize=get_readBlockSize(slot_nr, &UE->frame_parms);
|
||||
writeBlockSize=UE->frame_parms.get_samples_per_slot((slot_nr + DURATION_RX_TO_TX) % nb_slot_frame, &UE->frame_parms);
|
||||
if (UE->apply_timing_offset && (slot_nr == nb_slot_frame-1)) {
|
||||
const int sampShift = -(UE->rx_offset>>1);
|
||||
readBlockSize -= sampShift;
|
||||
writeBlockSize -= sampShift;
|
||||
UE->apply_timing_offset = false;
|
||||
if (slot_nr<(nb_slot_frame - 1)) {
|
||||
readBlockSize=get_readBlockSize(slot_nr, &UE->frame_parms, UE->is_synchronized);
|
||||
writeBlockSize=UE->frame_parms.get_samples_per_slot((slot_nr + DURATION_RX_TO_TX) % nb_slot_frame, &UE->frame_parms);
|
||||
} else {
|
||||
UE->rx_offset_diff = computeSamplesShift(UE);
|
||||
readBlockSize=get_readBlockSize(slot_nr, &UE->frame_parms, UE->is_synchronized) -
|
||||
UE->rx_offset_diff;
|
||||
writeBlockSize=UE->frame_parms.get_samples_per_slot((slot_nr + DURATION_RX_TO_TX) % nb_slot_frame, &UE->frame_parms)- UE->rx_offset_diff;
|
||||
}
|
||||
|
||||
AssertFatal(readBlockSize ==
|
||||
@@ -993,18 +1341,27 @@ void init_NR_UE(int nb_inst,
|
||||
}
|
||||
|
||||
void init_NR_UE_threads(int nb_inst) {
|
||||
int inst;
|
||||
|
||||
pthread_t threads[nb_inst];
|
||||
pthread_t threadsSL[nb_inst];
|
||||
|
||||
for (inst=0; inst < nb_inst; inst++) {
|
||||
for (int inst = 0; inst < nb_inst; inst++) {
|
||||
PHY_VARS_NR_UE *UE = PHY_vars_UE_g[inst][0];
|
||||
|
||||
LOG_I(PHY,"Intializing UE Threads for instance %d (%p,%p)...\n",inst,PHY_vars_UE_g[inst],PHY_vars_UE_g[inst][0]);
|
||||
threadCreate(&threads[inst], UE_thread, (void *)UE, "UEthread", -1, OAI_PRIORITY_RT_MAX);
|
||||
if (!IS_SOFTMODEM_NOSTATS_BIT) {
|
||||
pthread_t stat_pthread;
|
||||
threadCreate(&stat_pthread, nrL1_UE_stats_thread, UE, "L1_UE_stats", -1, OAI_PRIORITY_RT_LOW);
|
||||
if (get_softmodem_params()->sl_mode == 0) {
|
||||
LOG_I(NR_PHY, "Intializing UE Threads for instance %d (%p,%p)...\n", inst, PHY_vars_UE_g[inst], PHY_vars_UE_g[inst][0]);
|
||||
threadCreate(&threads[inst], UE_thread, (void *)UE, "UEthread", -1, OAI_PRIORITY_RT_MAX);
|
||||
if (!IS_SOFTMODEM_NOSTATS_BIT) {
|
||||
pthread_t stat_pthread;
|
||||
threadCreate(&stat_pthread, nrL1_UE_stats_thread, UE, "L1_UE_stats", -1, OAI_PRIORITY_RT_LOW);
|
||||
}
|
||||
}
|
||||
else if (get_softmodem_params()->sl_mode == 2) {
|
||||
LOG_I(NR_PHY, "Intializing Sidelink UE Threads for instance %d (%p,%p)...\n", inst, PHY_vars_UE_g[inst], PHY_vars_UE_g[inst][0]);
|
||||
threadCreate(&threadsSL[inst], UE_thread_SL, (void *)UE, "UEthreadSL", -1, OAI_PRIORITY_RT_MAX);
|
||||
}
|
||||
else {
|
||||
LOG_I(NR_PHY,"Need implementation...\n");
|
||||
abort();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -86,6 +86,7 @@ unsigned short config_frames[4] = {2,9,11,13};
|
||||
#include "nr_nas_msg_sim.h"
|
||||
#include <openair1/PHY/MODULATION/nr_modulation.h>
|
||||
#include "openair2/GNB_APP/gnb_paramdef.h"
|
||||
#include <openair1/PHY/NR_REFSIG/sss_nr.h>
|
||||
|
||||
extern const char *duplex_mode[];
|
||||
THREAD_STRUCT thread_struct;
|
||||
@@ -128,6 +129,7 @@ int dumpframe = 0;
|
||||
|
||||
uint64_t downlink_frequency[MAX_NUM_CCs][4];
|
||||
int32_t uplink_frequency_offset[MAX_NUM_CCs][4];
|
||||
uint64_t sidelink_frequency[MAX_NUM_CCs][4];
|
||||
int rx_input_level_dBm;
|
||||
|
||||
#if MAX_NUM_CCs == 1
|
||||
@@ -143,7 +145,6 @@ double rx_gain[MAX_NUM_CCs][4] = {{110,0,0,0},{20,0,0,0}};
|
||||
// UE and OAI config variables
|
||||
|
||||
openair0_config_t openair0_cfg[MAX_CARDS];
|
||||
int16_t node_synch_ref[MAX_NUM_CCs];
|
||||
int otg_enabled;
|
||||
double cpuf;
|
||||
|
||||
@@ -163,6 +164,7 @@ uint32_t N_RB_DL = 106;
|
||||
uint8_t abstraction_flag=0;
|
||||
|
||||
nr_bler_struct nr_bler_data[NR_NUM_MCS];
|
||||
nr_bler_struct nr_mimo_bler_data[NR_NUM_MCS];
|
||||
|
||||
static void init_bler_table(char*);
|
||||
|
||||
@@ -259,6 +261,81 @@ nrUE_params_t *get_nrUE_params(void) {
|
||||
return &nrUE_params;
|
||||
}
|
||||
|
||||
static void nr_phy_config_request_sl(PHY_VARS_NR_UE *ue,
|
||||
int N_RB_DL,
|
||||
int N_RB_UL,
|
||||
int CC_id)
|
||||
{
|
||||
uint64_t rev_burst = 0;
|
||||
uint64_t SSB_positions = 0x01;
|
||||
int mu = 1;
|
||||
uint8_t n_tx = 1;
|
||||
uint8_t n_rx = 1;
|
||||
uint16_t Nid_cell = 0;
|
||||
int ssb_subcarrier_offset = 0;
|
||||
for (int i = 0; i < 64; i++)
|
||||
rev_burst |= (((SSB_positions >> (63-i))&0x01) << i);
|
||||
|
||||
NR_DL_FRAME_PARMS *fp = &ue->frame_parms;
|
||||
fapi_nr_config_request_t *nrUE_config = &ue->nrUE_config;
|
||||
nrUE_config->cell_config.phy_cell_id = get_softmodem_params()->nid1 + get_softmodem_params()->nid2 * NUMBER_SSS_SEQUENCE;
|
||||
nrUE_config->ssb_config.scs_common = mu;
|
||||
nrUE_config->ssb_table.ssb_subcarrier_offset = 0;
|
||||
nrUE_config->ssb_table.ssb_offset_point_a = 0;
|
||||
nrUE_config->ssb_table.ssb_mask_list[1].ssb_mask = (rev_burst)&(0xFFFFFFFF);
|
||||
nrUE_config->ssb_table.ssb_mask_list[0].ssb_mask = (rev_burst>>32)&(0xFFFFFFFF);
|
||||
nrUE_config->cell_config.frame_duplex_type = TDD;
|
||||
nrUE_config->ssb_table.ssb_period = 1; //10ms
|
||||
nrUE_config->carrier_config.dl_grid_size[mu] = N_RB_DL;
|
||||
nrUE_config->carrier_config.ul_grid_size[mu] = N_RB_UL;
|
||||
nrUE_config->carrier_config.num_tx_ant = fp->nb_antennas_tx;
|
||||
nrUE_config->carrier_config.num_rx_ant = fp->nb_antennas_rx;
|
||||
nrUE_config->tdd_table.tdd_period = 0;
|
||||
nrUE_config->carrier_config.dl_frequency = downlink_frequency[CC_id][0] / 1000;
|
||||
nrUE_config->carrier_config.uplink_frequency = downlink_frequency[CC_id][0] / 1000;
|
||||
nrUE_config->carrier_config.sl_frequency = sidelink_frequency[CC_id][0] / 1000;
|
||||
LOG_D(NR_PHY, "SL Frequency %u\n", nrUE_config->carrier_config.sl_frequency);
|
||||
fp->tdd_period = 6; // 6 indicates 5ms (see get_nb_periods_per_frame())
|
||||
fp->tdd_slot_config = 0b0000111111; // 1 -> UL, 0-> DL for each slot , LSB is the slot 0
|
||||
fp->dl_CarrierFreq = 2600000000;
|
||||
fp->ul_CarrierFreq = 2600000000;
|
||||
fp->nb_antennas_tx = n_tx;
|
||||
fp->nb_antennas_rx = n_rx;
|
||||
fp->nb_antenna_ports_gNB = n_tx;
|
||||
fp->N_RB_DL = N_RB_DL;
|
||||
fp->Nid_cell = Nid_cell;
|
||||
fp->Nid_SL = get_softmodem_params()->nid1 + get_softmodem_params()->nid2 * NUMBER_SSS_SEQUENCE;;
|
||||
fp->nushift = 0; //No nushift in SL
|
||||
fp->ssb_type = nr_ssb_type_C; //Note: case c for NR SL???
|
||||
fp->freq_range = mu < 2 ? nr_FR1 : nr_FR2;
|
||||
fp->nr_band = get_softmodem_params()->band; //Note: NR SL uses for n38 and n47
|
||||
fp->threequarter_fs = 0;
|
||||
fp->ofdm_offset_divisor = UINT_MAX;
|
||||
fp->first_carrier_offset = 0;
|
||||
fp->ssb_start_subcarrier = 12 * ue->nrUE_config.ssb_table.ssb_offset_point_a + ssb_subcarrier_offset;
|
||||
int bw_index = get_supported_band_index(mu, fp->nr_band, N_RB_DL);
|
||||
nrUE_config->carrier_config.dl_bandwidth = get_supported_bw_mhz(fp->nr_band > 256 ? FR2 : FR1, bw_index);
|
||||
|
||||
ue->slss = calloc(1, sizeof(*ue->slss));
|
||||
int len = sizeof(ue->slss->sl_mib) / sizeof(ue->slss->sl_mib[0]);
|
||||
for (int i = 0; i < len; i++) {
|
||||
ue->slss->sl_mib[i] = 0;
|
||||
}
|
||||
ue->slss->sl_mib_length = 32;
|
||||
ue->slss->sl_numssb_withinperiod_r16 = 16;
|
||||
ue->slss->sl_timeinterval_r16 = 20;
|
||||
ue->slss->sl_timeoffsetssb_r16 = 0;
|
||||
ue->slss->sl_numssb_withinperiod_r16_copy = 16;
|
||||
ue->slss->sl_timeinterval_r16_copy = 20;
|
||||
ue->slss->sl_timeoffsetssb_r16_copy = 0;
|
||||
ue->slss->slss_id = get_softmodem_params()->nid1 + get_softmodem_params()->nid2 * NUMBER_SSS_SEQUENCE;;
|
||||
ue->is_synchronized_sl = 0;
|
||||
ue->UE_fo_compensation = 0;
|
||||
ue->sync_ref = get_softmodem_params()->sync_ref;
|
||||
LOG_I(NR_PHY, "nrUE configured\n");
|
||||
}
|
||||
|
||||
|
||||
static void get_options(void) {
|
||||
|
||||
paramdef_t cmdline_params[] =CMDLINE_NRUEPARAMS_DESC ;
|
||||
@@ -321,7 +398,7 @@ void init_openair0(void) {
|
||||
NR_DL_FRAME_PARMS *frame_parms = &PHY_vars_UE_g[0][0]->frame_parms;
|
||||
|
||||
for (card=0; card<MAX_CARDS; card++) {
|
||||
uint64_t dl_carrier, ul_carrier;
|
||||
uint64_t dl_carrier, ul_carrier, sl_carrier;
|
||||
openair0_cfg[card].configFilename = NULL;
|
||||
openair0_cfg[card].threequarter_fs = frame_parms->threequarter_fs;
|
||||
openair0_cfg[card].sample_rate = frame_parms->samples_per_subframe * 1e3;
|
||||
@@ -348,8 +425,15 @@ void init_openair0(void) {
|
||||
duplex_mode[openair0_cfg[card].duplex_mode]);
|
||||
|
||||
nr_get_carrier_frequencies(PHY_vars_UE_g[0][0], &dl_carrier, &ul_carrier);
|
||||
|
||||
LOG_I(NR_PHY,"Configuring SL carrier for %llu Hz \n",sl_carrier);
|
||||
nr_rf_card_config_freq(&openair0_cfg[card], ul_carrier, dl_carrier, freq_off);
|
||||
|
||||
if (get_softmodem_params()->sl_mode != 0) {
|
||||
nr_get_carrier_frequencies_sl(PHY_vars_UE_g[0][0], &sl_carrier);
|
||||
LOG_I(NR_PHY,"Configuring SL carrier for %llu Hz \n",sl_carrier);
|
||||
nr_rf_card_config_freq(&openair0_cfg[card], sl_carrier, sl_carrier, freq_off);
|
||||
}
|
||||
|
||||
nr_rf_card_config_gain(&openair0_cfg[card], rx_gain_off);
|
||||
|
||||
openair0_cfg[card].configFilename = get_softmodem_params()->rf_config_file;
|
||||
@@ -508,8 +592,14 @@ int main( int argc, char **argv ) {
|
||||
|
||||
set_options(CC_id, UE[CC_id]);
|
||||
NR_UE_MAC_INST_t *mac = get_mac_inst(0);
|
||||
|
||||
if (get_softmodem_params()->sa) { // set frame config to initial values from command line and assume that the SSB is centered on the grid
|
||||
if (get_softmodem_params()->sl_mode != 0) {
|
||||
uint16_t nr_band = get_band(sidelink_frequency[CC_id][0],0);
|
||||
mac->if_module = NULL;
|
||||
LOG_I(HW, "Setting mac->if_module = NULL b/c we config PHY in nr_phy_config_request_sl (for now - TODO)\n");
|
||||
nr_phy_config_request_sl(UE[CC_id], N_RB_DL, N_RB_DL, CC_id);
|
||||
nr_init_frame_parms_ue_sl(&UE[CC_id]->frame_parms,sidelink_frequency[CC_id][0],nr_band);
|
||||
}
|
||||
if (get_softmodem_params()->sa) {
|
||||
uint16_t nr_band = get_band(downlink_frequency[CC_id][0],uplink_frequency_offset[CC_id][0]);
|
||||
mac->nr_band = nr_band;
|
||||
nr_init_frame_parms_ue_sa(&UE[CC_id]->frame_parms,
|
||||
@@ -517,15 +607,15 @@ int main( int argc, char **argv ) {
|
||||
uplink_frequency_offset[CC_id][0],
|
||||
get_softmodem_params()->numerology,
|
||||
nr_band);
|
||||
}
|
||||
else{
|
||||
DevAssert(mac->if_module != NULL && mac->if_module->phy_config_request != NULL);
|
||||
mac->if_module->phy_config_request(&mac->phy_config);
|
||||
mac->phy_config_request_sent = true;
|
||||
fapi_nr_config_request_t *nrUE_config = &UE[CC_id]->nrUE_config;
|
||||
|
||||
nr_init_frame_parms_ue(&UE[CC_id]->frame_parms, nrUE_config,
|
||||
*mac->scc->downlinkConfigCommon->frequencyInfoDL->frequencyBandList.list.array[0]);
|
||||
} else {
|
||||
if (mac->if_module != NULL && mac->if_module->phy_config_request != NULL) {
|
||||
mac->if_module->phy_config_request(&mac->phy_config);
|
||||
mac->phy_config_request_sent = true;
|
||||
}
|
||||
nr_init_frame_parms_ue(&UE[CC_id]->frame_parms, &UE[CC_id]->nrUE_config,
|
||||
((get_softmodem_params()->sl_mode == 0) ?
|
||||
*mac->scc->downlinkConfigCommon->frequencyInfoDL->frequencyBandList.list.array[0] :
|
||||
UE[CC_id]->frame_parms.nr_band));
|
||||
}
|
||||
|
||||
init_nr_ue_vars(UE[CC_id], 0, abstraction_flag);
|
||||
@@ -636,3 +726,56 @@ static void init_bler_table(char *env_string) {
|
||||
fclose(pFile);
|
||||
}
|
||||
}
|
||||
|
||||
// Read in each MCS file and build BLER-SINR-TB table
|
||||
static void init_mimo_bler_table(void) {
|
||||
memset(nr_mimo_bler_data, 0, sizeof(nr_mimo_bler_data));
|
||||
|
||||
const char *awgn_results_dir = getenv("NR_MIMO2x2_AWGN_RESULTS_DIR");
|
||||
if (!awgn_results_dir) {
|
||||
LOG_W(NR_MAC, "No $NR_MIMO2x2_AWGN_RESULTS_DIR\n");
|
||||
return;
|
||||
}
|
||||
|
||||
for (unsigned int i = 0; i < NR_NUM_MCS; i++) {
|
||||
char fName[1024];
|
||||
snprintf(fName, sizeof(fName), "%s/mcs%d_cdlc_mimo2x2_dl.csv", awgn_results_dir, i);
|
||||
FILE *pFile = fopen(fName, "r");
|
||||
if (!pFile) {
|
||||
LOG_E(NR_MAC, "open %s: %s\n", fName, strerror(errno));
|
||||
continue;
|
||||
}
|
||||
size_t bufSize = 1024;
|
||||
char * line = NULL;
|
||||
char * token;
|
||||
char * temp = NULL;
|
||||
int nlines = 0;
|
||||
while (getline(&line, &bufSize, pFile) > 0) {
|
||||
if (!strncmp(line, "SNR", 3)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (nlines > NR_NUM_SINR) {
|
||||
LOG_E(NR_MAC, "BLER FILE ERROR - num lines greater than expected - file: %s\n", fName);
|
||||
abort();
|
||||
}
|
||||
|
||||
token = strtok_r(line, ";", &temp);
|
||||
int ncols = 0;
|
||||
while (token != NULL) {
|
||||
if (ncols > NUM_BLER_COL) {
|
||||
LOG_E(NR_MAC, "BLER FILE ERROR - num of cols greater than expected\n");
|
||||
abort();
|
||||
}
|
||||
|
||||
nr_mimo_bler_data[i].bler_table[nlines][ncols] = strtof(token, NULL);
|
||||
ncols++;
|
||||
|
||||
token = strtok_r(NULL, ";", &temp);
|
||||
}
|
||||
nlines++;
|
||||
}
|
||||
nr_mimo_bler_data[i].length = nlines;
|
||||
fclose(pFile);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -42,6 +42,7 @@
|
||||
{"uecap_file", CONFIG_HLP_UECAP_FILE, 0, .strptr=&uecap_file, .defstrval="./uecap_ports1.xml", TYPE_STRING, 0}, \
|
||||
{"rrc_config_path", CONFIG_HLP_RRC_CFG_PATH, 0, .strptr=&rrc_config_path, .defstrval="./", TYPE_STRING, 0}, \
|
||||
{"ue-idx-standalone", NULL, 0, .u16ptr=&ue_idx_standalone, .defuintval=0xFFFF, TYPE_UINT16, 0}, \
|
||||
{"SLC", CONFIG_HLP_SLF, 0, .u64ptr=&(sidelink_frequency[0][0]), .defuintval=2600000000, TYPE_UINT64, 0}, \
|
||||
{"ue-rxgain", CONFIG_HLP_UERXG, 0, .dblptr=&(rx_gain[0][0]), .defdblval=110, TYPE_DOUBLE, 0}, \
|
||||
{"ue-rxgain-off", CONFIG_HLP_UERXGOFF, 0, .dblptr=&rx_gain_off, .defdblval=0, TYPE_DOUBLE, 0}, \
|
||||
{"ue-txgain", CONFIG_HLP_UETXG, 0, .dblptr=&(tx_gain[0][0]), .defdblval=0, TYPE_DOUBLE, 0}, \
|
||||
|
||||
@@ -46,7 +46,6 @@ static softmodem_params_t softmodem_params;
|
||||
char *parallel_config=NULL;
|
||||
char *worker_config=NULL;
|
||||
int usrp_tx_thread = 0;
|
||||
char *nfapi_str=NULL;
|
||||
int ldpc_offload_flag=0;
|
||||
uint8_t nfapi_mode=0;
|
||||
|
||||
|
||||
@@ -44,7 +44,6 @@ extern "C"
|
||||
example: -1,3 launches two working threads one floating, the second set on core 3\n\
|
||||
default 8 floating threads\n\
|
||||
use N for no pool (runs in calling thread) recommended with rfsim.\n"
|
||||
#define CONFIG_HLP_REORDER "Disable reorder thread\n"
|
||||
#define CONFIG_HLP_ULMAXE "set the eNodeB max ULSCH erros\n"
|
||||
#define CONFIG_HLP_CALUER "set UE RX calibration\n"
|
||||
#define CONFIG_HLP_CALUERM ""
|
||||
@@ -56,8 +55,10 @@ extern "C"
|
||||
|
||||
#define CONFIG_HLP_DUMPFRAME "dump UE received frame to rxsig_frame0.dat and exit\n"
|
||||
#define CONFIG_HLP_PHYTST "test UE phy layer, mac disabled\n"
|
||||
#define CONFIG_HLP_SL_PHYTST "test SL UE phy layer, mac disabled\n"
|
||||
#define CONFIG_HLP_DORA "test gNB and UE with RA procedures\n"
|
||||
#define CONFIG_HLP_SA "run gNB in standalone mode\n"
|
||||
#define CONFIG_HLP_SL_MODE "sets the NR sidelink mode (0: not in sidelink mode, 1: in-coverage/gNB, 2: out-of-coverage/no gNB)"
|
||||
#define CONFIG_HLP_EXTS "tells hardware to use an external timing reference\n"
|
||||
#define CONFIG_HLP_DMRSSYNC "tells RU to insert DMRS in subframe 1 slot 0"
|
||||
#define CONFIG_HLP_CLK "tells hardware to use a clock reference (0:internal, 1:external, 2:gpsdo)\n"
|
||||
@@ -67,6 +68,7 @@ extern "C"
|
||||
#define CONFIG_HLP_NOSNGLT "Disables single-thread mode in lte-softmodem\n"
|
||||
#define CONFIG_HLP_DLF "Set the downlink frequency for all component carriers\n"
|
||||
#define CONFIG_HLP_ULF "Set the uplink frequency offset for all component carriers\n"
|
||||
#define CONFIG_HLP_SLF "Set the sidelink frequency for all component carriers\n"
|
||||
#define CONFIG_HLP_CHOFF "Channel id offset\n"
|
||||
#define CONFIG_HLP_SOFTS "Enable soft scope and L1 and L2 stats (Xforms)\n"
|
||||
#define CONFIG_HLP_SOFTS_QT "Enable soft scope and L1 and L2 stats (QT)\n"
|
||||
@@ -104,6 +106,9 @@ extern "C"
|
||||
#define CONFIG_L1_EMULATOR "Run in L1 emulated mode (disable PHY layer)\n"
|
||||
#define CONFIG_HLP_CONTINUOUS_TX "perform continuous transmission, even in TDD mode (to work around USRP issues)\n"
|
||||
#define CONFIG_HLP_STATS_DISABLE "disable globally the stats generation and persistence"
|
||||
#define CONFIG_HLP_SYNC_REF "Sync Reference in Sidelink\n"
|
||||
#define CONFIG_HLP_NID1 "Set NID1 value in Sidelink\n"
|
||||
#define CONFIG_HLP_NID2 "Set NID2 value in Sidelink\n"
|
||||
|
||||
/*-----------------------------------------------------------------------------------------------------------------------------------------------------*/
|
||||
/* command line parameters common to eNodeB and UE */
|
||||
@@ -111,10 +116,11 @@ extern "C"
|
||||
/*-----------------------------------------------------------------------------------------------------------------------------------------------------*/
|
||||
#define RF_CONFIG_FILE softmodem_params.rf_config_file
|
||||
#define TP_CONFIG softmodem_params.threadPoolConfig
|
||||
#define CONTINUOUS_TX softmodem_params.continuous_tx
|
||||
#define PHY_TEST softmodem_params.phy_test
|
||||
#define SL_PHY_TEST softmodem_params.sl_phy_test
|
||||
#define DO_RA softmodem_params.do_ra
|
||||
#define SA softmodem_params.sa
|
||||
#define SL_MODE softmodem_params.sl_mode
|
||||
#define WAIT_FOR_SYNC softmodem_params.wait_for_sync
|
||||
#define SINGLE_THREAD_FLAG softmodem_params.single_thread_flag
|
||||
#define CHAIN_OFFSET softmodem_params.chain_offset
|
||||
@@ -134,7 +140,10 @@ extern "C"
|
||||
#define NON_STOP softmodem_params.non_stop
|
||||
#define EMULATE_L1 softmodem_params.emulate_l1
|
||||
#define CONTINUOUS_TX softmodem_params.continuous_tx
|
||||
#define REORDER_THREAD_DISABLE softmodem_params.reorder_thread_disable
|
||||
#define SYNC_REF softmodem_params.sync_ref
|
||||
#define NID1 softmodem_params.nid1
|
||||
#define NID2 softmodem_params.nid2
|
||||
|
||||
#define DEFAULT_RFCONFIG_FILE "/usr/local/etc/syriq/ue.band7.tm1.PRB100.NR40.dat";
|
||||
|
||||
extern int usrp_tx_thread;
|
||||
@@ -142,10 +151,11 @@ extern int usrp_tx_thread;
|
||||
#define CMDLINE_PARAMS_DESC { \
|
||||
{"rf-config-file", CONFIG_HLP_RFCFGF, 0, .strptr=&RF_CONFIG_FILE, .defstrval=NULL, TYPE_STRING, 0}, \
|
||||
{"thread-pool", CONFIG_HLP_TPOOL, 0, .strptr=&TP_CONFIG, .defstrval="-1,-1,-1,-1,-1,-1,-1,-1", TYPE_STRING, 0}, \
|
||||
{"reorder-thread-disable",CONFIG_HLP_REORDER, PARAMFLAG_BOOL, .iptr=&REORDER_THREAD_DISABLE, .defintval=0, TYPE_INT, 0}, \
|
||||
{"phy-test", CONFIG_HLP_PHYTST, PARAMFLAG_BOOL, .iptr=&PHY_TEST, .defintval=0, TYPE_INT, 0}, \
|
||||
{"do-ra", CONFIG_HLP_DORA, PARAMFLAG_BOOL, .iptr=&DO_RA, .defintval=0, TYPE_INT, 0}, \
|
||||
{"sa", CONFIG_HLP_SA, PARAMFLAG_BOOL, .iptr=&SA, .defintval=0, TYPE_INT, 0}, \
|
||||
{"sl-mode", CONFIG_HLP_SL_MODE, 0, .u8ptr=&SL_MODE, .defintval=0, TYPE_UINT8, 0}, \
|
||||
{"sync-ref", CONFIG_HLP_SYNC_REF, PARAMFLAG_BOOL, .iptr=&SYNC_REF, .defintval=0, TYPE_INT, 0}, \
|
||||
{"usim-test", CONFIG_HLP_USIM, PARAMFLAG_BOOL, .u8ptr=&USIM_TEST, .defintval=0, TYPE_UINT8, 0}, \
|
||||
{"clock-source", CONFIG_HLP_CLK, 0, .uptr=&CLOCK_SOURCE, .defintval=0, TYPE_UINT, 0}, \
|
||||
{"time-source", CONFIG_HLP_TME, 0, .uptr=&TIMING_SOURCE, .defintval=0, TYPE_UINT, 0}, \
|
||||
@@ -177,6 +187,8 @@ extern int usrp_tx_thread;
|
||||
{"emulate-l1", CONFIG_L1_EMULATOR, PARAMFLAG_BOOL, .iptr=&EMULATE_L1, .defintval=0, TYPE_INT, 0}, \
|
||||
{"continuous-tx", CONFIG_HLP_CONTINUOUS_TX, PARAMFLAG_BOOL, .iptr=&CONTINUOUS_TX, .defintval=0, TYPE_INT, 0}, \
|
||||
{"disable-stats", CONFIG_HLP_STATS_DISABLE, PARAMFLAG_BOOL, .iptr=&stats_disabled, .defintval=0, TYPE_INT, 0}, \
|
||||
{"nid1", CONFIG_HLP_NID1, 0, .iptr=&NID1, .defintval=10, TYPE_INT, 0}, \
|
||||
{"nid2", CONFIG_HLP_NID2, 0, .iptr=&NID2, .defintval=1, TYPE_INT, 0}, \
|
||||
}
|
||||
// clang-format on
|
||||
|
||||
@@ -214,6 +226,7 @@ extern int usrp_tx_thread;
|
||||
{ .s5 = { NULL } }, \
|
||||
{ .s5 = { NULL } }, \
|
||||
{ .s5 = { NULL } }, \
|
||||
{ .s5 = { NULL } }, \
|
||||
{ .s3a = { config_checkstr_assign_integer, \
|
||||
{"MONOLITHIC", "PNF", "VNF","UE_STUB_PNF","UE_STUB_OFFNET","STANDALONE_PNF"}, \
|
||||
{NFAPI_MONOLITHIC, NFAPI_MODE_PNF, NFAPI_MODE_VNF,NFAPI_UE_STUB_PNF,NFAPI_UE_STUB_OFFNET,NFAPI_MODE_STANDALONE_PNF}, \
|
||||
@@ -222,6 +235,8 @@ extern int usrp_tx_thread;
|
||||
{ .s5 = { NULL } }, \
|
||||
{ .s5 = { NULL } }, \
|
||||
{ .s5 = { NULL } }, \
|
||||
{ .s5 = { NULL } }, \
|
||||
{ .s5 = { NULL } }, \
|
||||
}
|
||||
// clang-format on
|
||||
|
||||
@@ -304,10 +319,11 @@ typedef struct {
|
||||
//THREAD_STRUCT thread_struct;
|
||||
char *rf_config_file;
|
||||
char *threadPoolConfig;
|
||||
int reorder_thread_disable;
|
||||
int phy_test;
|
||||
int sl_phy_test;
|
||||
int do_ra;
|
||||
int sa;
|
||||
uint8_t sl_mode;
|
||||
uint8_t usim_test;
|
||||
int emulate_rf;
|
||||
int wait_for_sync; //eNodeB only
|
||||
@@ -329,6 +345,9 @@ typedef struct {
|
||||
int non_stop;
|
||||
int emulate_l1;
|
||||
int continuous_tx;
|
||||
int sync_ref;
|
||||
int nid1;
|
||||
int nid2;
|
||||
} softmodem_params_t;
|
||||
|
||||
extern uint64_t get_softmodem_optmask(void);
|
||||
|
||||
@@ -559,7 +559,9 @@ typedef struct {
|
||||
typedef struct
|
||||
{
|
||||
uint16_t dl_bandwidth;//Carrier bandwidth for DL in MHz [38.104, sec 5.3.2] Values: 5, 10, 15, 20, 25, 30, 40,50, 60, 70, 80,90,100,200,400
|
||||
uint16_t sl_bandwidth; //Carrier bandwidth for SL in MHz [38.101, sec 5.3.5] Values: 10, 20, 30, and 40
|
||||
uint32_t dl_frequency; //Absolute frequency of DL point A in KHz [38.104, sec5.2 and 38.211 sec 4.4.4.2] Value: 450000 -> 52600000
|
||||
uint32_t sl_frequency; //Absolute frequency of SL point A in KHz [38.331, sec6.3.5 and 38.211 sec 8.2.7]
|
||||
uint16_t dl_k0[5];//𝑘_{0}^{𝜇} for each of the numerologies [38.211, sec 5.3.1] Value: 0 ->23699
|
||||
uint16_t dl_grid_size[5];//Grid size 𝑁_{𝑔𝑟𝑖𝑑}^{𝑠𝑖𝑧𝑒,𝜇} for each of the numerologies [38.211, sec 4.4.2] Value: 0->275 0 = this numerology not used
|
||||
uint16_t num_tx_ant;//Number of Tx antennas
|
||||
|
||||
@@ -56,13 +56,13 @@ __device__ char dev_dt [46*68*384];
|
||||
__device__ char dev_llr[68*384];
|
||||
__device__ unsigned char dev_tmp[68*384];
|
||||
|
||||
h_element h_compact1 [46*23] = {};
|
||||
h_element h_compact1 [46*19] = {};
|
||||
h_element h_compact2 [68*30] = {};
|
||||
|
||||
__device__ h_element dev_h_compact1[46*23]; // used in kernel 1
|
||||
__device__ h_element dev_h_compact1[46*19]; // used in kernel 1
|
||||
__device__ h_element dev_h_compact2[68*30]; // used in kernel 2
|
||||
|
||||
// __device__ __constant__ h_element dev_h_compact1[46*23]; // used in kernel 1
|
||||
// __device__ __constant__ h_element dev_h_compact1[46*19]; // used in kernel 1
|
||||
// __device__ __constant__ h_element dev_h_compact2[68*30]; // used in kernel 2
|
||||
|
||||
// row and col element count
|
||||
|
||||
@@ -351,9 +351,17 @@ void applyGtoright(const t_nrPolar_params *pp,decoder_node_t *node) {
|
||||
((__m64 *)alpha_r)[0] = _mm_subs_pi16(((__m64 *)alpha_v)[1],_mm_sign_pi16(((__m64 *)alpha_v)[0],((__m64 *)betal)[0]));
|
||||
}
|
||||
else
|
||||
{// equivalent scalar code to above, activated only on non x86/ARM architectures or Nv=1,2
|
||||
for (int i=0;i<node->Nv/2;i++) {
|
||||
alpha_r[i] = alpha_v[i+(node->Nv/2)] - (betal[i]*alpha_v[i]);
|
||||
{
|
||||
int temp_alpha_r;
|
||||
for (int i = 0; i < node->Nv / 2; i++) {
|
||||
temp_alpha_r = alpha_v[i + (node->Nv / 2)] - (betal[i] * alpha_v[i]);
|
||||
if (temp_alpha_r > SHRT_MAX) {
|
||||
alpha_r[i] = SHRT_MAX;
|
||||
} else if (temp_alpha_r < -SHRT_MAX) {
|
||||
alpha_r[i] = -SHRT_MAX;
|
||||
} else {
|
||||
alpha_r[i] = temp_alpha_r;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (node->Nv == 2) { // apply hard decision on right node
|
||||
|
||||
@@ -42,6 +42,7 @@
|
||||
#include "PHY/CODING/nrPolar_tools/nr_polar_dci_defs.h"
|
||||
#include "PHY/CODING/nrPolar_tools/nr_polar_uci_defs.h"
|
||||
#include "PHY/CODING/nrPolar_tools/nr_polar_pbch_defs.h"
|
||||
#include "PHY/CODING/nrPolar_tools/nr_polar_psbch_defs.h"
|
||||
#include "PHY/CODING/coding_defs.h"
|
||||
//#include "SIMULATION/TOOLS/sim.h"
|
||||
|
||||
|
||||
@@ -35,6 +35,7 @@
|
||||
|
||||
#define NR_POLAR_PBCH_AGGREGATION_LEVEL 0 //uint8_t
|
||||
#define NR_POLAR_PBCH_MESSAGE_TYPE 0 //int8_t
|
||||
#define NR_POLAR_PSBCH_MESSAGE_TYPE 3 //int8_t
|
||||
#define NR_POLAR_PBCH_PAYLOAD_BITS 32 //uint16_t
|
||||
#define NR_POLAR_PBCH_CRC_PARITY_BITS 24
|
||||
#define NR_POLAR_PBCH_CRC_ERROR_CORRECTION_BITS 3
|
||||
@@ -52,6 +53,8 @@
|
||||
#define NR_POLAR_PBCH_I_BIL 0 //uint8_t
|
||||
#define NR_POLAR_PBCH_E 864 //uint16_t
|
||||
#define NR_POLAR_PBCH_E_DWORD 27 // NR_POLAR_PBCH_E/32
|
||||
#define NR_POLAR_PSBCH_E 1792 //uint16_t
|
||||
#define NR_POLAR_PSBCH_E_DWORD 56 // NR_POLAR_PSBCH_E/32
|
||||
|
||||
/*
|
||||
* TEST CODE
|
||||
|
||||
70
openair1/PHY/CODING/nrPolar_tools/nr_polar_psbch_defs.h
Normal file
70
openair1/PHY/CODING/nrPolar_tools/nr_polar_psbch_defs.h
Normal file
@@ -0,0 +1,70 @@
|
||||
/*
|
||||
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The OpenAirInterface Software Alliance licenses this file to You under
|
||||
* the OAI Public License, Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.openairinterface.org/?page_id=698
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*-------------------------------------------------------------------------------
|
||||
* For more information about the OpenAirInterface (OAI) Software Alliance:
|
||||
* contact@openairinterface.org
|
||||
*/
|
||||
|
||||
/*!\file PHY/CODING/nrPolar_tools/nr_polar_psbch_defs.h
|
||||
* \brief Defines the constant variables for polar coding of the PSBCH from 38-212, V15.1.1 2018-04.
|
||||
* \author Turker Yilmaz
|
||||
* \date 2018
|
||||
* \version 0.1
|
||||
* \company EURECOM
|
||||
* \email turker.yilmaz@eurecom.fr
|
||||
* \note
|
||||
* \warning
|
||||
*/
|
||||
|
||||
#ifndef __NR_POLAR_PSBCH_DEFS__H__
|
||||
#define __NR_POLAR_PSBCH_DEFS__H__
|
||||
|
||||
#define NR_POLAR_PSBCH_AGGREGATION_LEVEL 0 //uint8_t
|
||||
#define NR_POLAR_PSBCH_MESSAGE_TYPE 3 //int8_t
|
||||
#define NR_POLAR_PSBCH_PAYLOAD_BITS 32 //uint16_t
|
||||
#define NR_POLAR_PSBCH_CRC_PARITY_BITS 24
|
||||
#define NR_POLAR_PSBCH_CRC_ERROR_CORRECTION_BITS 3
|
||||
//Assumed 3 by 3GPP when NR_POLAR_PSBCH_L>8 to meet false alarm rate requirements.
|
||||
|
||||
//Sec. 7.1.4: Channel Coding
|
||||
#define NR_POLAR_PSBCH_N_MAX 9 //uint8_t
|
||||
#define NR_POLAR_PSBCH_I_IL 1 //uint8_t
|
||||
#define NR_POLAR_PSBCH_I_SEG 0 //uint8_t
|
||||
#define NR_POLAR_PSBCH_N_PC 0 //uint8_t
|
||||
#define NR_POLAR_PSBCH_N_PC_WM 0 //uint8_t
|
||||
//#define NR_POLAR_PSBCH_N 512 //uint16_t
|
||||
|
||||
//Sec. 7.1.5: Rate Matching
|
||||
#define NR_POLAR_PSBCH_I_BIL 0 //uint8_t
|
||||
#define NR_POLAR_PSBCH_E 1792 //uint16_t
|
||||
#define NR_POLAR_PSBCH_E_DWORD 56 // NR_POLAR_PSBCH_E/32
|
||||
|
||||
/*
|
||||
* TEST CODE
|
||||
*/
|
||||
//#define DEBUG_POLAR
|
||||
// Usage in code:
|
||||
//#ifdef DEBUG_POLAR
|
||||
//...
|
||||
//#endif
|
||||
|
||||
//unsigned int testPayload0=0x00000000, testPayload1=0xffffffff; //payload1=~payload0;
|
||||
//unsigned int testPayload2=0xa5a5a5a5; //testPayload3=0xb3f02c82;
|
||||
|
||||
//double testReceivedPayload3[NR_POLAR_PSBCH_E] = {-1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, 1, 1, 1, 1, -1, -1, -1, 1, 1, 1, 1, -1, -1, -1, 1, -1, 1, -1, 1, -1, 1, 1, -1, 1, 1, 1, -1, -1, -1, 1, 1, 1, -1, 1, 1, -1, 1, 1, -1, 1, -1, -1, 1, 1, -1, 1, 1, -1, -1, -1, -1, -1, -1, 1, 1, 1, 1, 1, 1, -1, -1, 1, -1, 1, -1, -1, 1, 1, -1, -1, -1, -1, 1, 1, 1, -1, 1, -1, 1, 1, 1, -1, 1, -1, -1, 1, -1, -1, 1, 1, -1, -1, 1, 1, 1, -1, -1, 1, 1, -1, -1, -1, -1, 1, -1, -1, -1, 1, -1, -1, 1, 1, 1, 1, -1, -1, -1, -1, 1, -1, -1, 1, -1, 1, 1, 1, 1, -1, 1, -1, -1, 1, -1, 1, -1, -1, -1, -1, 1, 1, 1, -1, -1, -1, 1, 1, 1, 1, -1, -1, -1, -1, -1, 1, 1, 1, 1, 1, -1, -1, 1, 1, -1, -1, 1, 1, 1, -1, -1, -1, -1, 1, 1, -1, 1, -1, 1, -1, 1, -1, 1, 1, -1, -1, -1, 1, -1, 1, 1, -1, -1, 1, -1, -1, -1, -1, 1, -1, 1, -1, -1, -1, 1, 1, 1, 1, 1, 1, -1, 1, 1, -1, 1, 1, 1, -1, -1, 1, 1, 1, 1, -1, 1, 1, -1, 1, -1, 1, -1, -1, -1, -1, -1, -1, -1, 1, 1, 1, -1, 1, -1, -1, 1, 1, -1, 1, -1, -1, 1, -1, 1, -1, 1, -1, -1, -1, -1, 1, 1, -1, -1, -1, 1, -1, 1, 1, -1, -1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1, 1, -1, 1, 1, 1, -1, 1, -1, 1, 1, 1, -1, -1, -1, 1, 1, 1, -1, -1, -1, 1, -1, -1, 1, 1, 1, -1, 1, -1, -1, 1, -1, 1, -1, 1, -1, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 1, 1, -1, -1, 1, 1, -1, 1, 1, -1, -1, 1, 1, -1, -1, -1, -1, -1, 1, -1, -1, -1, 1, 1, -1, 1, 1, -1, 1, -1, -1, 1, 1, -1, 1, 1, 1, -1, 1, -1, 1, 1, 1, 1, -1, -1, -1, 1, -1, 1, 1, -1, 1, -1, -1, 1, 1, -1, 1, -1, -1, 1, -1, 1, 1, 1, 1, -1, -1, -1, -1, 1, -1, -1, 1, 1, -1, -1, 1, -1, 1, 1, 1, -1, 1, -1, -1, -1, -1, 1, -1, -1, -1, -1, 1, -1, 1, 1, -1, 1, -1, 1, -1, -1, -1, -1, -1, 1, 1, -1, -1, -1, -1, 1, 1, -1, -1, -1, -1, -1, 1, 1, -1, 1, -1, 1, -1, 1, 1, -1, 1, -1, -1, -1, 1, 1, -1, 1, 1, 1, -1, -1, -1, -1, 1, -1, 1, -1, 1, -1, 1, -1, -1, -1, -1, -1, -1, -1, -1, 1, 1, 1, -1, 1, 1, 1, -1, 1, -1, 1, 1, -1, 1, -1, -1, -1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, 1, 1, 1, 1, -1, -1, -1, 1, 1, 1, 1, -1, -1, -1, 1, -1, 1, -1, 1, -1, 1, 1, -1, 1, 1, 1, -1, -1, -1, 1, 1, 1, -1, 1, 1, -1, 1, 1, -1, 1, -1, -1, 1, 1, -1, 1, 1, -1, -1, -1, -1, -1, -1, 1, 1, 1, 1, 1, 1, -1, -1, 1, -1, 1, -1, -1, 1, 1, -1, -1, -1, -1, 1, 1, 1, -1, 1, -1, 1, 1, 1, -1, 1, -1, -1, 1, -1, -1, 1, 1, -1, -1, 1, 1, 1, -1, -1, 1, 1, -1, -1, -1, -1, 1, -1, -1, -1, 1, -1, -1, 1, 1, 1, 1, -1, -1, -1, -1, 1, -1, -1, 1, -1, 1, 1, 1, 1, -1, 1, -1, -1, 1, -1, 1, -1, -1, -1, -1, 1, 1, 1, -1, -1, -1, 1, 1, 1, 1, -1, -1, -1, -1, -1, 1, 1, 1, 1, 1, -1, -1, 1, 1, -1, -1, 1, 1, 1, -1, -1, -1, -1, 1, 1, -1, 1, -1, 1, -1, 1, -1, 1, 1, -1, -1, -1, 1, -1, 1, 1, -1, -1, 1, -1, -1, -1, -1, 1, -1, 1, -1, -1, -1, 1, 1, 1, 1, 1, 1, -1, 1, 1, -1, 1, 1, 1, -1, -1, 1, 1, 1, 1, -1, 1, 1, -1, 1, -1, 1, -1, -1, -1, -1, -1, -1, -1, 1, 1, 1, -1, 1, -1, -1, 1, 1, -1, 1, -1, -1, 1, -1, 1, -1, 1, -1, -1, -1, -1, 1, 1, -1, -1, -1, 1, -1, 1, 1, -1, -1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1, 1, -1, 1, 1, 1, -1, 1, -1, 1, 1, 1, -1, -1, -1, 1, 1, 1, -1, -1, -1, 1, -1, -1, 1, 1, 1, -1, 1, -1, -1, 1, -1, 1, -1, 1, -1, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 1, 1, -1, -1, 1, 1, -1, 1, 1, -1, -1, 1, 1, -1, -1};
|
||||
|
||||
#endif
|
||||
@@ -193,7 +193,18 @@ t_nrPolar_params *nr_polar_params(int8_t messageType, uint16_t messageLength, ui
|
||||
newPolarInitNode->payloadBits = messageLength;
|
||||
newPolarInitNode->crcCorrectionBits = NR_POLAR_PUCCH_CRC_ERROR_CORRECTION_BITS;
|
||||
//LOG_D(PHY,"New polar node, encoderLength %d, aggregation_level %d\n",newPolarInitNode->encoderLength,aggregation_level);
|
||||
|
||||
} else if (messageType == 3) { // PSBCH
|
||||
newPolarInitNode->n_max = NR_POLAR_PSBCH_N_MAX;
|
||||
newPolarInitNode->i_il = NR_POLAR_PSBCH_I_IL;
|
||||
newPolarInitNode->i_seg = NR_POLAR_PSBCH_I_SEG;
|
||||
newPolarInitNode->n_pc = NR_POLAR_PSBCH_N_PC;
|
||||
newPolarInitNode->n_pc_wm = NR_POLAR_PSBCH_N_PC_WM;
|
||||
newPolarInitNode->i_bil = NR_POLAR_PSBCH_I_BIL;
|
||||
newPolarInitNode->crcParityBits = NR_POLAR_PSBCH_CRC_PARITY_BITS;
|
||||
newPolarInitNode->payloadBits = NR_POLAR_PSBCH_PAYLOAD_BITS;
|
||||
newPolarInitNode->encoderLength = NR_POLAR_PSBCH_E;
|
||||
newPolarInitNode->crcCorrectionBits = NR_POLAR_PSBCH_CRC_ERROR_CORRECTION_BITS;
|
||||
newPolarInitNode->crc_generator_matrix = crc24c_generator_matrix(newPolarInitNode->payloadBits);//G_P
|
||||
} else {
|
||||
AssertFatal(1 == 0, "[nr_polar_init] Incorrect Message Type(%d)", messageType);
|
||||
}
|
||||
|
||||
@@ -26,6 +26,7 @@
|
||||
#include "PHY/NR_REFSIG/nr_refsig.h"
|
||||
#include "PHY/INIT/nr_phy_init.h"
|
||||
#include "PHY/CODING/nrPolar_tools/nr_polar_pbch_defs.h"
|
||||
#include "PHY/CODING/nrPolar_tools/nr_polar_psbch_defs.h"
|
||||
#include "PHY/NR_TRANSPORT/nr_transport_proto.h"
|
||||
#include "PHY/NR_TRANSPORT/nr_transport_common_proto.h"
|
||||
#include "openair1/PHY/MODULATION/nr_modulation.h"
|
||||
@@ -38,7 +39,7 @@
|
||||
#include "PHY/NR_REFSIG/nr_refsig.h"
|
||||
#include "SCHED_NR/fapi_nr_l1.h"
|
||||
#include "nfapi_nr_interface.h"
|
||||
|
||||
#include "executables/softmodem-common.h"
|
||||
#include "PHY/NR_REFSIG/ul_ref_seq_nr.h"
|
||||
|
||||
|
||||
@@ -554,8 +555,7 @@ int phy_init_nr_gNB(PHY_VARS_gNB *gNB)
|
||||
AssertFatal(pdcch_dmrs!=NULL, "NR init: pdcch_dmrs malloc failed\n");
|
||||
|
||||
gNB->bad_pucch = 0;
|
||||
if (gNB->TX_AMP == 0)
|
||||
gNB->TX_AMP = AMP;
|
||||
|
||||
// ceil(((NB_RB<<1)*3)/32) // 3 RE *2(QPSK)
|
||||
int pdcch_dmrs_init_length = (((fp->N_RB_DL<<1)*3)>>5)+1;
|
||||
|
||||
|
||||
@@ -35,6 +35,9 @@
|
||||
#include "PHY/MODULATION/nr_modulation.h"
|
||||
#include "openair2/COMMON/prs_nr_paramdef.h"
|
||||
#include "SCHED_NR_UE/harq_nr.h"
|
||||
#include <nr-uesoftmodem.h>
|
||||
|
||||
|
||||
|
||||
void RCconfig_nrUE_prs(void *cfg)
|
||||
{
|
||||
@@ -199,6 +202,7 @@ int init_nr_ue_signal(PHY_VARS_NR_UE *ue, int nb_connected_gNB)
|
||||
// create shortcuts
|
||||
NR_DL_FRAME_PARMS *const fp = &ue->frame_parms;
|
||||
NR_UE_COMMON *const common_vars = &ue->common_vars;
|
||||
NR_UE_PSBCH **const psbch_vars = ue->psbch_vars;
|
||||
NR_UE_PRACH **const prach_vars = ue->prach_vars;
|
||||
NR_UE_CSI_IM **const csiim_vars = ue->csiim_vars;
|
||||
NR_UE_CSI_RS **const csirs_vars = ue->csirs_vars;
|
||||
@@ -350,6 +354,7 @@ int init_nr_ue_signal(PHY_VARS_NR_UE *ue, int nb_connected_gNB)
|
||||
// DLSCH
|
||||
for (gNB_id = 0; gNB_id < ue->n_connected_gNB; gNB_id++) {
|
||||
prach_vars[gNB_id] = (NR_UE_PRACH *)malloc16_clear(sizeof(NR_UE_PRACH));
|
||||
psbch_vars[gNB_id] = (NR_UE_PSBCH *)malloc16_clear(sizeof(NR_UE_PSBCH));
|
||||
csiim_vars[gNB_id] = (NR_UE_CSI_IM *)malloc16_clear(sizeof(NR_UE_CSI_IM));
|
||||
csirs_vars[gNB_id] = (NR_UE_CSI_RS *)malloc16_clear(sizeof(NR_UE_CSI_RS));
|
||||
srs_vars[gNB_id] = (NR_UE_SRS *)malloc16_clear(sizeof(NR_UE_SRS));
|
||||
@@ -468,6 +473,7 @@ void term_nr_ue_signal(PHY_VARS_NR_UE *ue, int nb_connected_gNB)
|
||||
free_and_zero(ue->csirs_vars[gNB_id]);
|
||||
free_and_zero(ue->srs_vars[gNB_id]);
|
||||
|
||||
free_and_zero(ue->psbch_vars[gNB_id]);
|
||||
free_and_zero(ue->prach_vars[gNB_id]);
|
||||
}
|
||||
|
||||
@@ -697,7 +703,12 @@ void phy_init_nr_top(PHY_VARS_NR_UE *ue) {
|
||||
crcTableInit();
|
||||
init_scrambling_luts();
|
||||
load_dftslib();
|
||||
frame_parms->Nid_SL = 0;
|
||||
init_context_synchro_nr(frame_parms);
|
||||
if (get_softmodem_params()->sl_mode>0) {
|
||||
frame_parms->Nid_SL = 336;
|
||||
init_context_synchro_nr(frame_parms);
|
||||
}
|
||||
generate_ul_reference_signal_sequences(SHRT_MAX);
|
||||
}
|
||||
|
||||
|
||||
@@ -22,6 +22,7 @@
|
||||
#include "nr_phy_init.h"
|
||||
#include "common/utils/nr/nr_common.h"
|
||||
#include "common/utils/LOG/log.h"
|
||||
#include "executables/softmodem-common.h"
|
||||
|
||||
/// Subcarrier spacings in Hz indexed by numerology index
|
||||
static const uint32_t nr_subcarrier_spacing[MAX_NUM_SUBCARRIER_SPACING] = {15e3, 30e3, 60e3, 120e3, 240e3};
|
||||
@@ -41,6 +42,11 @@ static const int nr_ssb_table[48][3] = {
|
||||
{93, 15, nr_ssb_type_A}, {94, 15, nr_ssb_type_A}, {96, 30, nr_ssb_type_C}};
|
||||
|
||||
void set_Lmax(NR_DL_FRAME_PARMS *fp) {
|
||||
|
||||
if (get_softmodem_params()->sl_mode == 2) {
|
||||
fp->Lmax = 1;
|
||||
return;
|
||||
}
|
||||
// definition of Lmax according to ts 38.213 section 4.1
|
||||
if (fp->dl_CarrierFreq < 6e9) {
|
||||
if(fp->frame_type && (fp->ssb_type==2))
|
||||
@@ -150,7 +156,10 @@ void set_scs_parameters (NR_DL_FRAME_PARMS *fp, int mu, int N_RB_DL)
|
||||
while(fp->ofdm_symbol_size < N_RB_DL * 12)
|
||||
fp->ofdm_symbol_size <<= 1;
|
||||
|
||||
fp->first_carrier_offset = fp->ofdm_symbol_size - (N_RB_DL * 12 / 2);
|
||||
if (get_softmodem_params()->sl_mode == 2)
|
||||
fp->first_carrier_offset = 0;
|
||||
else
|
||||
fp->first_carrier_offset = fp->ofdm_symbol_size - (N_RB_DL * 12 / 2);
|
||||
fp->nb_prefix_samples = fp->ofdm_symbol_size / 128 * 9;
|
||||
fp->nb_prefix_samples0 = fp->ofdm_symbol_size / 128 * (9 + (1 << mu));
|
||||
LOG_W(PHY,"Init: N_RB_DL %d, first_carrier_offset %d, nb_prefix_samples %d,nb_prefix_samples0 %d, ofdm_symbol_size %d\n",
|
||||
@@ -283,6 +292,10 @@ int nr_init_frame_parms_ue(NR_DL_FRAME_PARMS *fp,
|
||||
LOG_D(PHY,"dl_bw_kHz %lu\n",dl_bw_khz);
|
||||
LOG_D(PHY,"dl_CarrierFreq %lu\n",fp->dl_CarrierFreq);
|
||||
|
||||
if (get_softmodem_params()->sl_mode != 0) {
|
||||
fp->sl_CarrierFreq = ((dl_bw_khz >> 1) + config->carrier_config.sl_frequency) * 1000;
|
||||
}
|
||||
|
||||
uint64_t ul_bw_khz = (12*config->carrier_config.ul_grid_size[config->ssb_config.scs_common])*(15<<config->ssb_config.scs_common);
|
||||
fp->ul_CarrierFreq = ((ul_bw_khz>>1) + config->carrier_config.uplink_frequency)*1000 ;
|
||||
|
||||
@@ -332,6 +345,9 @@ int nr_init_frame_parms_ue(NR_DL_FRAME_PARMS *fp,
|
||||
}
|
||||
|
||||
fp->ssb_start_subcarrier = (12 * config->ssb_table.ssb_offset_point_a + sco);
|
||||
if (get_softmodem_params()->sl_mode == 2) {
|
||||
fp->ssb_start_subcarrier = 0;
|
||||
}
|
||||
set_Lmax(fp);
|
||||
|
||||
fp->L_ssb = (((uint64_t) config->ssb_table.ssb_mask_list[0].ssb_mask)<<32) | config->ssb_table.ssb_mask_list[1].ssb_mask;
|
||||
@@ -381,6 +397,11 @@ void nr_init_frame_parms_ue_sa(NR_DL_FRAME_PARMS *frame_parms, uint64_t downlink
|
||||
|
||||
}
|
||||
|
||||
void nr_init_frame_parms_ue_sl(NR_DL_FRAME_PARMS *frame_parms, uint64_t sidelink_frequency, uint16_t nr_band) {
|
||||
LOG_D(NR_PHY, "SL init parameters. SL freq %lu\n", sidelink_frequency);
|
||||
frame_parms->sl_CarrierFreq = sidelink_frequency;
|
||||
frame_parms->nr_band = nr_band;
|
||||
}
|
||||
|
||||
void nr_dump_frame_parms(NR_DL_FRAME_PARMS *fp)
|
||||
{
|
||||
|
||||
@@ -29,6 +29,7 @@ int nr_get_ssb_start_symbol(NR_DL_FRAME_PARMS *fp,uint8_t i_ssb);
|
||||
int nr_init_frame_parms(nfapi_nr_config_request_scf_t *config, NR_DL_FRAME_PARMS *frame_parms);
|
||||
int nr_init_frame_parms_ue(NR_DL_FRAME_PARMS *frame_parms, fapi_nr_config_request_t *config, uint16_t nr_band);
|
||||
void nr_init_frame_parms_ue_sa(NR_DL_FRAME_PARMS *frame_parms, uint64_t downlink_frequency, int32_t uplink_frequency_offset, uint8_t mu, uint16_t nr_band);
|
||||
void nr_init_frame_parms_ue_sl(NR_DL_FRAME_PARMS *frame_parms, uint64_t sidelink_frequency, uint16_t nr_band);
|
||||
int init_nr_ue_signal(PHY_VARS_NR_UE *ue,int nb_connected_eNB);
|
||||
void term_nr_ue_signal(PHY_VARS_NR_UE *ue, int nb_connected_gNB);
|
||||
void init_nr_ue_transport(PHY_VARS_NR_UE *ue);
|
||||
@@ -55,5 +56,5 @@ void free_nr_ue_ul_harq(NR_UL_UE_HARQ_t harq_list[NR_MAX_ULSCH_HARQ_PROCESSES],
|
||||
|
||||
void phy_init_nr_top(PHY_VARS_NR_UE *ue);
|
||||
void phy_term_nr_top(void);
|
||||
|
||||
void init_dfts(void);
|
||||
#endif
|
||||
|
||||
@@ -599,7 +599,8 @@ void init_symbol_rotation(NR_DL_FRAME_PARMS *fp) {
|
||||
|
||||
uint64_t dl_CarrierFreq = fp->dl_CarrierFreq;
|
||||
uint64_t ul_CarrierFreq = fp->ul_CarrierFreq;
|
||||
double f[2] = {(double)dl_CarrierFreq, (double)ul_CarrierFreq};
|
||||
uint64_t sl_CarrierFreq = fp->sl_CarrierFreq;
|
||||
double f[3] = {(double)dl_CarrierFreq, (double)ul_CarrierFreq, (double)sl_CarrierFreq};
|
||||
|
||||
const int nsymb = fp->symbols_per_slot * fp->slots_per_frame/10;
|
||||
const double Tc=(1/480e3/4096);
|
||||
@@ -607,10 +608,10 @@ void init_symbol_rotation(NR_DL_FRAME_PARMS *fp) {
|
||||
const double Ncp0=16*64 + (144*64*(1/(float)(1<<fp->numerology_index)));
|
||||
const double Ncp1=(144*64*(1/(float)(1<<fp->numerology_index)));
|
||||
|
||||
for (uint8_t ll = 0; ll < 2; ll++){
|
||||
for (uint8_t ll = 0; ll < sizeof(f)/sizeof(f[0]); ll++){
|
||||
|
||||
double f0 = f[ll];
|
||||
LOG_D(PHY, "Doing symbol rotation calculation for gNB TX/RX, f0 %f Hz, Nsymb %d\n", f0, nsymb);
|
||||
LOG_I(PHY, "Doing symbol rotation calculation for gNB TX/RX, f0 %f Hz, Nsymb %d\n", f0, nsymb);
|
||||
c16_t *symbol_rotation = fp->symbol_rotation[ll];
|
||||
|
||||
double tl = 0.0;
|
||||
|
||||
@@ -112,7 +112,8 @@ void apply_nr_rotation(NR_DL_FRAME_PARMS *fp,
|
||||
c16_t* txdata,
|
||||
int slot,
|
||||
int first_symbol,
|
||||
int nsymb);
|
||||
int nsymb,
|
||||
int link_type);
|
||||
|
||||
void init_symbol_rotation(NR_DL_FRAME_PARMS *fp);
|
||||
|
||||
@@ -122,7 +123,8 @@ void apply_nr_rotation_ul(NR_DL_FRAME_PARMS *frame_parms,
|
||||
c16_t *rxdataF,
|
||||
int slot,
|
||||
int first_symbol,
|
||||
int nsymb);
|
||||
int nsymb,
|
||||
int link_type);
|
||||
|
||||
/*! \brief Perform NR precoding. TS 38.211 V15.4.0 subclause 6.3.1.5
|
||||
@param[in] datatx_F_precoding, Pointer to n_layers*re data array
|
||||
|
||||
@@ -37,6 +37,7 @@ This section deals with basic functions for OFDM Modulation.
|
||||
#include "common/utils/LOG/vcd_signal_dumper.h"
|
||||
#include "modulation_common.h"
|
||||
#include "PHY/LTE_TRANSPORT/transport_common_proto.h"
|
||||
#include "../executables/softmodem-common.h"
|
||||
//#define DEBUG_OFDM_MOD
|
||||
|
||||
|
||||
@@ -47,14 +48,14 @@ void normal_prefix_mod(int32_t *txdataF,int32_t *txdata,uint8_t nsymb,LTE_DL_FRA
|
||||
|
||||
PHY_ofdm_mod((int *)txdataF, // input
|
||||
(int *)txdata, // output
|
||||
frame_parms->ofdm_symbol_size,
|
||||
frame_parms->ofdm_symbol_size,
|
||||
|
||||
1, // number of symbols
|
||||
frame_parms->nb_prefix_samples0, // number of prefix samples
|
||||
CYCLIC_PREFIX);
|
||||
PHY_ofdm_mod((int *)txdataF+frame_parms->ofdm_symbol_size, // input
|
||||
(int *)txdata+OFDM_SYMBOL_SIZE_COMPLEX_SAMPLES0, // output
|
||||
frame_parms->ofdm_symbol_size,
|
||||
frame_parms->ofdm_symbol_size,
|
||||
nsymb-1,
|
||||
frame_parms->nb_prefix_samples, // number of prefix samples
|
||||
CYCLIC_PREFIX);
|
||||
@@ -337,17 +338,18 @@ void apply_nr_rotation(NR_DL_FRAME_PARMS *fp,
|
||||
c16_t *txdataF,
|
||||
int slot,
|
||||
int first_symbol,
|
||||
int nsymb)
|
||||
int nsymb,
|
||||
int link_type)
|
||||
{
|
||||
int symb_offset = (slot%fp->slots_per_subframe)*fp->symbols_per_slot;
|
||||
|
||||
c16_t *symbol_rotation = fp->symbol_rotation[0] + symb_offset;
|
||||
c16_t *symbol_rotation = fp->symbol_rotation[link_type] + symb_offset;
|
||||
|
||||
for (int sidx = first_symbol; sidx < first_symbol + nsymb; sidx++) {
|
||||
c16_t *this_rotation = symbol_rotation + sidx;
|
||||
c16_t *this_symbol = (txdataF) + sidx * fp->ofdm_symbol_size;
|
||||
|
||||
LOG_D(PHY,"Rotating symbol %d, slot %d, symbol_subframe_index %d (%d,%d)\n",
|
||||
LOG_I(PHY,"Rotating symbol %d, slot %d, symbol_subframe_index %d (%d,%d)\n",
|
||||
sidx,
|
||||
slot,
|
||||
sidx + symb_offset,
|
||||
@@ -371,4 +373,4 @@ void apply_nr_rotation(NR_DL_FRAME_PARMS *fp,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -26,6 +26,7 @@
|
||||
#include "PHY/LTE_ESTIMATION/lte_estimation.h"
|
||||
#include "PHY/NR_UE_ESTIMATION/nr_estimation.h"
|
||||
#include <common/utils/LOG/log.h>
|
||||
#include "executables/softmodem-common.h"
|
||||
|
||||
//#define DEBUG_FEP
|
||||
|
||||
@@ -48,7 +49,11 @@ int nr_slot_fep(PHY_VARS_NR_UE *ue,
|
||||
|
||||
unsigned int nb_prefix_samples;
|
||||
unsigned int nb_prefix_samples0;
|
||||
if (ue->is_synchronized) {
|
||||
bool is_synced = ue->is_synchronized;
|
||||
if(get_softmodem_params()->sl_mode == 2) {
|
||||
is_synced = ue->is_synchronized_sl;
|
||||
}
|
||||
if (is_synced) {
|
||||
nb_prefix_samples = frame_parms->nb_prefix_samples;
|
||||
nb_prefix_samples0 = frame_parms->nb_prefix_samples0;
|
||||
} else {
|
||||
@@ -161,13 +166,19 @@ int nr_slot_fep_init_sync(PHY_VARS_NR_UE *ue,
|
||||
|
||||
unsigned int nb_prefix_samples;
|
||||
unsigned int nb_prefix_samples0;
|
||||
if (get_softmodem_params()->sl_mode == 2) {
|
||||
if (ue->is_synchronized_sl) {
|
||||
nb_prefix_samples = frame_parms->nb_prefix_samples;
|
||||
nb_prefix_samples0 = frame_parms->nb_prefix_samples0;
|
||||
}
|
||||
}
|
||||
if (pbch_decoded) {
|
||||
nb_prefix_samples = frame_parms->nb_prefix_samples;
|
||||
nb_prefix_samples0 = frame_parms->nb_prefix_samples0;
|
||||
}
|
||||
else {
|
||||
nb_prefix_samples = frame_parms->nb_prefix_samples;
|
||||
nb_prefix_samples0 = frame_parms->nb_prefix_samples;
|
||||
nb_prefix_samples0 = frame_parms->nb_prefix_samples0;
|
||||
}
|
||||
unsigned int frame_length_samples = frame_parms->samples_per_frame;
|
||||
|
||||
@@ -178,8 +189,8 @@ int nr_slot_fep_init_sync(PHY_VARS_NR_UE *ue,
|
||||
unsigned int slot_offset = frame_parms->get_samples_slot_timestamp(Ns,frame_parms,0);
|
||||
unsigned int rx_offset = sample_offset + slot_offset;
|
||||
unsigned int abs_symbol = Ns * frame_parms->symbols_per_slot + symbol;
|
||||
for (int idx_symb = Ns*frame_parms->symbols_per_slot; idx_symb <= abs_symbol; idx_symb++)
|
||||
rx_offset += (abs_symbol%(0x7<<frame_parms->numerology_index)) ? nb_prefix_samples : nb_prefix_samples0;
|
||||
for (int idx_symb = Ns*frame_parms->symbols_per_slot; idx_symb <= abs_symbol; idx_symb++)
|
||||
rx_offset += (idx_symb%(0x7<<frame_parms->numerology_index)) ? nb_prefix_samples : nb_prefix_samples0;
|
||||
rx_offset += frame_parms->ofdm_symbol_size * symbol;
|
||||
|
||||
#ifdef DEBUG_FEP
|
||||
@@ -230,7 +241,7 @@ int nr_slot_fep_init_sync(PHY_VARS_NR_UE *ue,
|
||||
stop_meas(&ue->rx_dft_stats);
|
||||
|
||||
int symb_offset = (Ns%frame_parms->slots_per_subframe)*frame_parms->symbols_per_slot;
|
||||
c16_t rot2 = frame_parms->symbol_rotation[0][symbol + symb_offset];
|
||||
c16_t rot2 = frame_parms->symbol_rotation[get_softmodem_params()->sl_mode == 2 ? NR_LINK_TYPE_SL : 0][symbol + symb_offset];
|
||||
rot2.i=-rot2.i;
|
||||
|
||||
#ifdef DEBUG_FEP
|
||||
@@ -240,7 +251,7 @@ int nr_slot_fep_init_sync(PHY_VARS_NR_UE *ue,
|
||||
#endif
|
||||
|
||||
c16_t *this_symbol = &rxdataF[aa][frame_parms->ofdm_symbol_size*symbol];
|
||||
rotate_cpx_vector(this_symbol, &rot2, this_symbol, frame_parms->ofdm_symbol_size, 15);
|
||||
//rotate_cpx_vector(this_symbol, &rot2, this_symbol, frame_parms->ofdm_symbol_size, 15);
|
||||
}
|
||||
|
||||
#ifdef DEBUG_FEP
|
||||
@@ -314,14 +325,15 @@ void apply_nr_rotation_ul(NR_DL_FRAME_PARMS *frame_parms,
|
||||
c16_t *rxdataF,
|
||||
int slot,
|
||||
int first_symbol,
|
||||
int nsymb)
|
||||
int nsymb,
|
||||
int link_type)
|
||||
{
|
||||
int symb_offset = (slot%frame_parms->slots_per_subframe)*frame_parms->symbols_per_slot;
|
||||
int soffset = (slot&3)*frame_parms->symbols_per_slot*frame_parms->ofdm_symbol_size;
|
||||
|
||||
for (int symbol=first_symbol;symbol<nsymb;symbol++) {
|
||||
|
||||
c16_t rot2 = frame_parms->symbol_rotation[1][symbol + symb_offset];
|
||||
|
||||
c16_t rot2 = frame_parms->symbol_rotation[link_type][symbol + symb_offset];
|
||||
rot2.i=-rot2.i;
|
||||
LOG_D(PHY,"slot %d, symb_offset %d rotating by %d.%d\n",slot,symb_offset,rot2.r,rot2.i);
|
||||
|
||||
|
||||
@@ -72,6 +72,10 @@ void nr_chest_time_domain_avg(NR_DL_FRAME_PARMS *frame_parms,
|
||||
uint16_t dmrs_bitmap,
|
||||
uint16_t num_rbs);
|
||||
|
||||
int nr_psbch_dmrs_rx(int symbol,
|
||||
unsigned int *nr_gold_psbch,
|
||||
int32_t *output);
|
||||
|
||||
static inline uint8_t is_dmrs_symbol(uint8_t l, uint16_t dmrsSymbMask)
|
||||
{
|
||||
DevAssert(l < 32);
|
||||
|
||||
@@ -232,6 +232,38 @@ int nr_pbch_dmrs_rx(int symbol,
|
||||
return(0);
|
||||
}
|
||||
|
||||
int nr_psbch_dmrs_rx(int symbol,
|
||||
unsigned int *nr_gold_psbch,
|
||||
int32_t *output)
|
||||
{
|
||||
AssertFatal(symbol >= 0 && symbol < 14, "Illegal symbol %d\n", symbol);
|
||||
int offset = (symbol == 0) ? 0 : 4;
|
||||
int m0 = (symbol - offset) * 33;
|
||||
int m1 = ((symbol - offset) + 1) * 33;
|
||||
/// QPSK modulation
|
||||
for (int m = m0; m < m1; m++) {
|
||||
AssertFatal(((m << 1) >> 5) < NR_PSBCH_DMRS_LENGTH_DWORD, "Index in output is invalid %d >= %d\n",
|
||||
((m << 1) >> 5), NR_PSBCH_DMRS_LENGTH_DWORD);
|
||||
AssertFatal((((m << 1) + 1) >> 5) < NR_PSBCH_DMRS_LENGTH_DWORD, "Index in output is invalid %d >= %d\n",
|
||||
(((m << 1) + 1) >> 5), NR_PSBCH_DMRS_LENGTH_DWORD);
|
||||
uint8_t idx = ((((nr_gold_psbch[(m << 1) >> 5]) >> ((m << 1) & 0x1f)) & 1) << 1) ^ (((nr_gold_psbch[((m << 1) + 1) >> 5]) >> (((m << 1) + 1) & 0x1f)) & 1);
|
||||
AssertFatal(((m - m0) << 1) + 1 < 200, "Index in output is invalid %d >= %d\n",
|
||||
((m - m0) << 1) + 1, 200);
|
||||
AssertFatal(((NR_MOD_TABLE_QPSK_OFFSET + idx) << 1) + 1 < 14, "Index in output is invalid %d >= 14\n",
|
||||
((NR_MOD_TABLE_QPSK_OFFSET + idx) << 1) + 1);
|
||||
((int16_t*)output)[(m - m0) << 1] = nr_rx_mod_table[(NR_MOD_TABLE_QPSK_OFFSET + idx) << 1];
|
||||
((int16_t*)output)[((m - m0) << 1) + 1] = nr_rx_mod_table[((NR_MOD_TABLE_QPSK_OFFSET + idx) << 1) + 1];
|
||||
#ifdef DEBUG_PSBCH
|
||||
printf("%d %d\n", (m - m0) << 1, nr_rx_mod_table[(NR_MOD_TABLE_QPSK_OFFSET + idx) << 1]);
|
||||
if (m < 16) {
|
||||
printf("nr_gold_psbch[(m << 1) >> 5] %x\n", nr_gold_psbch[(m << 1) >> 5]);
|
||||
printf("m %d output %d %d addr %p\n", m, ((int16_t*)output)[m << 1], ((int16_t*)output)[(m << 1) + 1], &output[0]);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief This function generate gold ptrs sequence for each OFDM symbol
|
||||
\param *in gold sequence for ptrs per OFDM symbol
|
||||
|
||||
@@ -51,6 +51,20 @@ void nr_gold_pbch(PHY_VARS_NR_UE* ue)
|
||||
|
||||
}
|
||||
|
||||
void nr_gold_psbch(PHY_VARS_NR_UE* ue)
|
||||
{
|
||||
uint8_t reset = 1;
|
||||
unsigned int x1;
|
||||
unsigned int x2 = ue->frame_parms.Nid_SL;
|
||||
|
||||
for (int n = 0; n < NR_PSBCH_DMRS_LENGTH_DWORD; n++) {
|
||||
AssertFatal(n < sizeof(ue->nr_gold_psbch) / sizeof(ue->nr_gold_psbch[0]),
|
||||
"Invalid nr_gold_psbch index %d > %d\n", n, NR_PSBCH_DMRS_LENGTH_DWORD);
|
||||
ue->nr_gold_psbch[n] = lte_gold_generic(&x1, &x2, reset);
|
||||
reset = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void nr_gold_pdcch(PHY_VARS_NR_UE* ue,
|
||||
unsigned short nid)
|
||||
{
|
||||
|
||||
@@ -66,7 +66,7 @@
|
||||
#define SYNCHRO_FFT_SIZE_MAX (8192) /* maximum size of fft for synchronisation */
|
||||
|
||||
#define NO_RATE_CHANGE (1)
|
||||
|
||||
#define INITIAL_PSS_NR (7)
|
||||
#ifdef PSS_DECIMATOR
|
||||
#define RATE_CHANGE (SYNCHRO_FFT_SIZE_MAX/SYNCHRO_FFT_SIZE_PSS)
|
||||
#define SYNCHRO_FFT_SIZE_PSS (256)
|
||||
@@ -86,33 +86,26 @@
|
||||
|
||||
/************** VARIABLES *****************************************/
|
||||
|
||||
//#define STATIC_SYNC_BUFFER
|
||||
|
||||
#ifdef STATIC_SYNC_BUFFER
|
||||
/* buffer defined in file lte_sync_time */
|
||||
EXTERN int16_t synchro_tmp[SYNC_TMP_SIZE] __attribute__((aligned(32)));
|
||||
EXTERN int16_t synchroF_tmp[SYNCF_TMP_SIZE] __attribute__((aligned(32)));
|
||||
#else
|
||||
EXTERN int16_t *synchro_tmp;
|
||||
EXTERN int16_t *synchroF_tmp;
|
||||
#endif
|
||||
|
||||
EXTERN int16_t *primary_synchro_nr[NUMBER_PSS_SEQUENCE]
|
||||
EXTERN c16_t *primary_synchro_nr[NUMBER_PSS_SEQUENCE] __attribute__((aligned(32)));
|
||||
#ifdef INIT_VARIABLES_PSS_NR_H
|
||||
= { NULL, NULL, NULL}
|
||||
#endif
|
||||
;
|
||||
EXTERN int16_t *primary_synchro_nr2[NUMBER_PSS_SEQUENCE]
|
||||
EXTERN c16_t *primary_synchro_nr2[NUMBER_PSS_SEQUENCE] __attribute__((aligned(32)));
|
||||
#ifdef INIT_VARIABLES_PSS_NR_H
|
||||
= { NULL, NULL, NULL}
|
||||
#endif
|
||||
;
|
||||
EXTERN int16_t *primary_synchro_time_nr[NUMBER_PSS_SEQUENCE]
|
||||
EXTERN c16_t *primary_synchro_time_nr[NUMBER_PSS_SEQUENCE] __attribute__((aligned(32)));
|
||||
#ifdef INIT_VARIABLES_PSS_NR_H
|
||||
= { NULL, NULL, NULL}
|
||||
#endif
|
||||
;
|
||||
|
||||
EXTERN int16_t *primary_synchro_time_nr_sl[NUMBER_PSS_SEQUENCE_SL]
|
||||
#ifdef INIT_VARIABLES_PSS_NR_H
|
||||
= { NULL, NULL}
|
||||
#endif
|
||||
;
|
||||
/* profiling structure */
|
||||
EXTERN time_stats_t generic_time[TIME_LAST];
|
||||
|
||||
@@ -123,7 +116,6 @@ EXTERN time_stats_t generic_time[TIME_LAST];
|
||||
void init_context_synchro_nr(NR_DL_FRAME_PARMS *frame_parms_ue);
|
||||
void free_context_synchro_nr(void);
|
||||
void init_context_pss_nr(NR_DL_FRAME_PARMS *frame_parms_ue);
|
||||
void free_context_pss_nr(void);
|
||||
int set_pss_nr(int ofdm_symbol_size);
|
||||
int pss_synchro_nr(PHY_VARS_NR_UE *PHY_vars_UE, int is, int rate_change);
|
||||
int pss_search_time_nr(c16_t **rxdata, PHY_VARS_NR_UE *ue, int fo_flag, int is);
|
||||
|
||||
@@ -56,6 +56,8 @@ int nr_pdsch_dmrs_rx(PHY_VARS_NR_UE *ue,
|
||||
|
||||
void nr_gold_pbch(PHY_VARS_NR_UE* ue);
|
||||
|
||||
void nr_gold_psbch(PHY_VARS_NR_UE* ue);
|
||||
|
||||
void nr_gold_pdcch(PHY_VARS_NR_UE* ue,
|
||||
unsigned short n_idDMRS);
|
||||
|
||||
|
||||
@@ -41,7 +41,13 @@
|
||||
|
||||
/* PSS parameters */
|
||||
#define NUMBER_PSS_SEQUENCE (3)
|
||||
#define NUMBER_PSS_SEQUENCE_SL (2)
|
||||
#define PSS_SEQ_OFFSET (0)
|
||||
#define PSS_SEQ_OFFSET_SL (22)
|
||||
#define PSS_SSS_SUB_CARRIER_START (56)
|
||||
#define PSS_SSS_SUB_CARRIER_START_SL (2)
|
||||
#define INVALID_PSS_SEQUENCE (NUMBER_PSS_SEQUENCE)
|
||||
#define INVALID_PSS_SEQUENCE_SL (NUMBER_PSS_SEQUENCE_SL)
|
||||
#define LENGTH_PSS_NR (127)
|
||||
#define N_SC_RB (12) /* Resource block size in frequency domain expressed as a number if subcarriers */
|
||||
#define SCALING_PSS_NR (3)
|
||||
@@ -62,6 +68,12 @@
|
||||
#define SSS_SYMBOL_NB ((2) + OFFSET_SS_PBCH)
|
||||
#define PBCH_LAST_SYMBOL_NB ((3) + OFFSET_SS_PBCH)
|
||||
|
||||
#define OFFSET_SS_PSBCH 0//-1
|
||||
#define PSS0_SL_SYMBOL_NB ((1) + OFFSET_SS_PSBCH)
|
||||
#define PSS1_SL_SYMBOL_NB ((2) + OFFSET_SS_PSBCH)
|
||||
#define SSS0_SL_SYMBOL_NB ((3) + OFFSET_SS_PSBCH)
|
||||
#define SSS1_SL_SYMBOL_NB ((4) + OFFSET_SS_PSBCH)
|
||||
|
||||
/* SS/PBCH parameters */
|
||||
#define N_RB_SS_PBCH_BLOCK (20)
|
||||
#define NB_SYMBOLS_PBCH (3)
|
||||
|
||||
@@ -51,15 +51,26 @@
|
||||
#define NUMBER_SSS_SEQUENCE (336)
|
||||
#define INVALID_SSS_SEQUENCE (NUMBER_SSS_SEQUENCE)
|
||||
#define LENGTH_SSS_NR (127)
|
||||
#define SCALING_METRIC_SSS_NR (15)//(19)
|
||||
#define SCALING_METRIC_SSS_NR (19)//(15)
|
||||
|
||||
#define N_ID_2_NUMBER (NUMBER_PSS_SEQUENCE)
|
||||
#define N_ID_2_NUMBER_SL (NUMBER_PSS_SEQUENCE_SL)
|
||||
#define N_ID_1_NUMBER (NUMBER_SSS_SEQUENCE)
|
||||
|
||||
#define GET_NID2(Nid_cell) (Nid_cell%3)
|
||||
#define GET_NID1(Nid_cell) (Nid_cell/3)
|
||||
|
||||
#define GET_NID2_SL(Nid_SL) (Nid_SL/NUMBER_SSS_SEQUENCE)
|
||||
#define GET_NID1_SL(Nid_SL) (Nid_SL%NUMBER_SSS_SEQUENCE)
|
||||
|
||||
#define PSS_SC_START_NR (52) /* see from TS 38.211 table 7.4.3.1-1: Resources within an SS/PBCH block for PSS... */
|
||||
#define SSS_START_IDX (3) /* [0:PSBCH 1:PSS0 2:PSS1 3:SSS0 4:SSS1] */
|
||||
#define NUM_SSS_SYMBOLS (2)
|
||||
|
||||
#define SSS_START_IDX (3) /* [0:PSBCH 1:PSS0 2:PSS1 3:SSS0 4:SSS1] */
|
||||
#define NUM_SSS_SYMBOLS (2)
|
||||
|
||||
#define SSS_METRIC_FLOOR_NR (30000)
|
||||
|
||||
/************** VARIABLES *****************************************/
|
||||
|
||||
@@ -89,15 +100,17 @@ EXTERN int16_t d_sss[N_ID_2_NUMBER][N_ID_1_NUMBER][LENGTH_SSS_NR];
|
||||
void init_context_sss_nr(int amp);
|
||||
void free_context_sss_nr(void);
|
||||
|
||||
void insert_sss_nr(int16_t *sss_time,
|
||||
void insert_sss_nr(c16_t *sss_time,
|
||||
NR_DL_FRAME_PARMS *frame_parms);
|
||||
|
||||
int pss_ch_est_nr(PHY_VARS_NR_UE *ue,
|
||||
int32_t pss_ext[NB_ANTENNAS_RX][LENGTH_PSS_NR],
|
||||
int32_t sss_ext[NB_ANTENNAS_RX][LENGTH_SSS_NR]);
|
||||
c16_t pss_ext[NB_ANTENNAS_RX][LENGTH_PSS_NR],
|
||||
c16_t sss_ext[NB_ANTENNAS_RX][LENGTH_SSS_NR]);
|
||||
|
||||
int rx_sss_nr(PHY_VARS_NR_UE *ue, UE_nr_rxtx_proc_t *proc, int32_t *tot_metric, uint8_t *phase_max, int *freq_offset_sss, c16_t rxdataF[][ue->frame_parms.samples_per_slot_wCP]);
|
||||
|
||||
int rx_sss_sl_nr(PHY_VARS_NR_UE *ue, UE_nr_rxtx_proc_t *proc, int32_t *tot_metric, uint8_t *phase_max, int *freq_offset_sss);
|
||||
|
||||
#undef INIT_VARIABLES_SSS_NR_H
|
||||
#undef EXTERN
|
||||
|
||||
|
||||
@@ -60,7 +60,7 @@ void nr_generate_pdsch(processingData_L1tx_t *msgTx,
|
||||
PHY_VARS_gNB *gNB = msgTx->gNB;
|
||||
NR_gNB_DLSCH_t *dlsch;
|
||||
c16_t** txdataF = gNB->common_vars.txdataF;
|
||||
int16_t amp = gNB->TX_AMP;
|
||||
int16_t amp = AMP;
|
||||
int xOverhead = 0;
|
||||
NR_DL_FRAME_PARMS *frame_parms = &gNB->frame_parms;
|
||||
time_stats_t *dlsch_encoding_stats=&gNB->dlsch_encoding_stats;
|
||||
@@ -491,7 +491,7 @@ void nr_generate_pdsch(processingData_L1tx_t *msgTx,
|
||||
for (int rb=0; rb<rel15->rbSize; rb++) {
|
||||
//get pmi info
|
||||
uint8_t pmi;
|
||||
if (0 /*rel15->precodingAndBeamforming.prg_size > 0*/)
|
||||
if (rel15->precodingAndBeamforming.prg_size > 0)
|
||||
pmi = rel15->precodingAndBeamforming.prgs_list[(int)rb/rel15->precodingAndBeamforming.prg_size].pm_idx;
|
||||
else
|
||||
pmi = 0;//no precoding
|
||||
|
||||
@@ -47,41 +47,6 @@
|
||||
#include "common/utils/LOG/vcd_signal_dumper.h"
|
||||
#include "common/utils/LOG/log.h"
|
||||
#include <syscall.h>
|
||||
|
||||
//#include "SCHED_NR/phy_procedures_nr_gNB.h"
|
||||
#include "common/utils/thread_pool/task_manager.h"
|
||||
#include <stdint.h>
|
||||
#include <time.h>
|
||||
|
||||
#include <stdalign.h>
|
||||
|
||||
//#include "nr_ulsch_decoding.h"
|
||||
|
||||
static inline
|
||||
int64_t time_now_us(void)
|
||||
{
|
||||
struct timespec tms;
|
||||
|
||||
/* The C11 way */
|
||||
/* if (! timespec_get(&tms, TIME_UTC)) */
|
||||
|
||||
/* POSIX.1-2008 way */
|
||||
if (clock_gettime(CLOCK_REALTIME,&tms)) {
|
||||
return -1;
|
||||
}
|
||||
/* seconds, multiplied with 1 million */
|
||||
int64_t micros = tms.tv_sec * 1000000;
|
||||
/* Add full microseconds */
|
||||
micros += tms.tv_nsec/1000;
|
||||
/* round up if necessary */
|
||||
if (tms.tv_nsec % 1000 >= 500) {
|
||||
++micros;
|
||||
}
|
||||
return micros;
|
||||
}
|
||||
|
||||
|
||||
|
||||
//#define DEBUG_ULSCH_DECODING
|
||||
//#define gNB_DEBUG_TRACE
|
||||
|
||||
@@ -152,148 +117,142 @@ NR_gNB_ULSCH_t new_gNB_ulsch(uint8_t max_ldpc_iterations, uint16_t N_RB_UL)
|
||||
static uint32_t prnt_crc_cnt = 0;
|
||||
#endif
|
||||
|
||||
void nr_processULSegment(void *arg)
|
||||
{
|
||||
ldpcDecode_t *rdata = (ldpcDecode_t *)arg;
|
||||
void nr_processULSegment(void *arg)
|
||||
{
|
||||
ldpcDecode_t *rdata = (ldpcDecode_t *)arg;
|
||||
PHY_VARS_gNB *phy_vars_gNB = rdata->gNB;
|
||||
NR_UL_gNB_HARQ_t *ulsch_harq = rdata->ulsch_harq;
|
||||
t_nrLDPC_dec_params *p_decoderParms = &rdata->decoderParms;
|
||||
int length_dec;
|
||||
int no_iteration_ldpc;
|
||||
int Kr;
|
||||
int Kr_bytes;
|
||||
int K_bits_F;
|
||||
uint8_t crc_type;
|
||||
int i;
|
||||
int j;
|
||||
int r = rdata->segment_r;
|
||||
int A = rdata->A;
|
||||
int E = rdata->E;
|
||||
int Qm = rdata->Qm;
|
||||
int rv_index = rdata->rv_index;
|
||||
int r_offset = rdata->r_offset;
|
||||
uint8_t kc = rdata->Kc;
|
||||
short *ulsch_llr = rdata->ulsch_llr;
|
||||
int max_ldpc_iterations = p_decoderParms->numMaxIter;
|
||||
int8_t llrProcBuf[OAI_UL_LDPC_MAX_NUM_LLR] __attribute__((aligned(32)));
|
||||
|
||||
#ifdef TASK_MANAGER
|
||||
if(*rdata->cancel == true)
|
||||
int16_t z[68 * 384 + 16] __attribute__((aligned(16)));
|
||||
int8_t l[68 * 384 + 16] __attribute__((aligned(16)));
|
||||
|
||||
__m128i *pv = (__m128i *)&z;
|
||||
__m128i *pl = (__m128i *)&l;
|
||||
|
||||
Kr = ulsch_harq->K;
|
||||
Kr_bytes = Kr >> 3;
|
||||
K_bits_F = Kr - ulsch_harq->F;
|
||||
|
||||
t_nrLDPC_time_stats procTime = {0};
|
||||
t_nrLDPC_time_stats *p_procTime = &procTime;
|
||||
|
||||
// start_meas(&phy_vars_gNB->ulsch_deinterleaving_stats);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////
|
||||
///////////////////////////////// nr_deinterleaving_ldpc ///////////////////////////////////
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
//////////////////////////// ulsch_llr =====> ulsch_harq->e //////////////////////////////
|
||||
|
||||
/// code blocks after bit selection in rate matching for LDPC code (38.212 V15.4.0 section 5.4.2.1)
|
||||
int16_t harq_e[E];
|
||||
|
||||
nr_deinterleaving_ldpc(E, Qm, harq_e, ulsch_llr + r_offset);
|
||||
|
||||
// for (int i =0; i<16; i++)
|
||||
// printf("rx output deinterleaving w[%d]= %d r_offset %d\n", i,ulsch_harq->w[r][i], r_offset);
|
||||
|
||||
stop_meas(&phy_vars_gNB->ulsch_deinterleaving_stats);
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
//////////////////////////////// nr_rate_matching_ldpc_rx ////////////////////////////////
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
///////////////////////// ulsch_harq->e =====> ulsch_harq->d /////////////////////////
|
||||
|
||||
// start_meas(&phy_vars_gNB->ulsch_rate_unmatching_stats);
|
||||
|
||||
if (nr_rate_matching_ldpc_rx(rdata->tbslbrm,
|
||||
p_decoderParms->BG,
|
||||
p_decoderParms->Z,
|
||||
ulsch_harq->d[r],
|
||||
harq_e,
|
||||
ulsch_harq->C,
|
||||
rv_index,
|
||||
ulsch_harq->d_to_be_cleared[r],
|
||||
E,
|
||||
ulsch_harq->F,
|
||||
Kr - ulsch_harq->F - 2 * (p_decoderParms->Z))
|
||||
== -1) {
|
||||
stop_meas(&phy_vars_gNB->ulsch_rate_unmatching_stats);
|
||||
|
||||
LOG_E(PHY, "ulsch_decoding.c: Problem in rate_matching\n");
|
||||
rdata->decodeIterations = max_ldpc_iterations + 1;
|
||||
return;
|
||||
#endif
|
||||
} else {
|
||||
stop_meas(&phy_vars_gNB->ulsch_rate_unmatching_stats);
|
||||
}
|
||||
|
||||
PHY_VARS_gNB *phy_vars_gNB = rdata->gNB;
|
||||
NR_UL_gNB_HARQ_t *ulsch_harq = rdata->ulsch_harq;
|
||||
t_nrLDPC_dec_params *p_decoderParms = &rdata->decoderParms;
|
||||
int length_dec;
|
||||
int no_iteration_ldpc;
|
||||
int Kr;
|
||||
int Kr_bytes;
|
||||
int K_bits_F;
|
||||
uint8_t crc_type;
|
||||
int i;
|
||||
int j;
|
||||
int r = rdata->segment_r;
|
||||
int A = rdata->A;
|
||||
int E = rdata->E;
|
||||
int Qm = rdata->Qm;
|
||||
int rv_index = rdata->rv_index;
|
||||
int r_offset = rdata->r_offset;
|
||||
uint8_t kc = rdata->Kc;
|
||||
short *ulsch_llr = rdata->ulsch_llr;
|
||||
int max_ldpc_iterations = p_decoderParms->numMaxIter;
|
||||
int8_t llrProcBuf[OAI_UL_LDPC_MAX_NUM_LLR] __attribute__((aligned(32)));
|
||||
ulsch_harq->d_to_be_cleared[r] = false;
|
||||
|
||||
int16_t z[68 * 384 + 16] __attribute__((aligned(16)));
|
||||
int8_t l[68 * 384 + 16] __attribute__((aligned(16)));
|
||||
memset(ulsch_harq->c[r], 0, Kr_bytes);
|
||||
|
||||
__m128i *pv = (__m128i *)&z;
|
||||
__m128i *pl = (__m128i *)&l;
|
||||
if (ulsch_harq->C == 1) {
|
||||
if (A > 3824)
|
||||
crc_type = CRC24_A;
|
||||
else
|
||||
crc_type = CRC16;
|
||||
|
||||
Kr = ulsch_harq->K;
|
||||
Kr_bytes = Kr >> 3;
|
||||
K_bits_F = Kr - ulsch_harq->F;
|
||||
length_dec = ulsch_harq->B;
|
||||
} else {
|
||||
crc_type = CRC24_B;
|
||||
length_dec = (ulsch_harq->B + 24 * ulsch_harq->C) / ulsch_harq->C;
|
||||
}
|
||||
|
||||
t_nrLDPC_time_stats procTime = {0};
|
||||
t_nrLDPC_time_stats *p_procTime = &procTime;
|
||||
// start_meas(&phy_vars_gNB->ulsch_ldpc_decoding_stats);
|
||||
|
||||
// start_meas(&phy_vars_gNB->ulsch_deinterleaving_stats);
|
||||
// set first 2*Z_c bits to zeros
|
||||
memset(&z[0], 0, 2 * ulsch_harq->Z * sizeof(int16_t));
|
||||
// set Filler bits
|
||||
memset((&z[0] + K_bits_F), 127, ulsch_harq->F * sizeof(int16_t));
|
||||
// Move coded bits before filler bits
|
||||
memcpy((&z[0] + 2 * ulsch_harq->Z), ulsch_harq->d[r], (K_bits_F - 2 * ulsch_harq->Z) * sizeof(int16_t));
|
||||
// skip filler bits
|
||||
memcpy((&z[0] + Kr), ulsch_harq->d[r] + (Kr - 2 * ulsch_harq->Z), (kc * ulsch_harq->Z - Kr) * sizeof(int16_t));
|
||||
// Saturate coded bits before decoding into 8 bits values
|
||||
for (i = 0, j = 0; j < ((kc * ulsch_harq->Z) >> 4) + 1; i += 2, j++) {
|
||||
pl[j] = _mm_packs_epi16(pv[i], pv[i + 1]);
|
||||
}
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////
|
||||
///////////////////////////////// nr_deinterleaving_ldpc ///////////////////////////////////
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
///////////////////////////////////// nrLDPC_decoder /////////////////////////////////////
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
//////////////////////////// ulsch_llr =====> ulsch_harq->e //////////////////////////////
|
||||
////////////////////////////////// pl =====> llrProcBuf //////////////////////////////////
|
||||
p_decoderParms->block_length = length_dec;
|
||||
no_iteration_ldpc = nrLDPC_decoder(p_decoderParms, (int8_t *)&pl[0], llrProcBuf, p_procTime);
|
||||
|
||||
/// code blocks after bit selection in rate matching for LDPC code (38.212 V15.4.0 section 5.4.2.1)
|
||||
int16_t harq_e[E];
|
||||
|
||||
nr_deinterleaving_ldpc(E, Qm, harq_e, ulsch_llr + r_offset);
|
||||
|
||||
// for (int i =0; i<16; i++)
|
||||
// printf("rx output deinterleaving w[%d]= %d r_offset %d\n", i,ulsch_harq->w[r][i], r_offset);
|
||||
|
||||
stop_meas(&phy_vars_gNB->ulsch_deinterleaving_stats);
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
//////////////////////////////// nr_rate_matching_ldpc_rx ////////////////////////////////
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
///////////////////////// ulsch_harq->e =====> ulsch_harq->d /////////////////////////
|
||||
|
||||
// start_meas(&phy_vars_gNB->ulsch_rate_unmatching_stats);
|
||||
|
||||
if (nr_rate_matching_ldpc_rx(rdata->tbslbrm,
|
||||
p_decoderParms->BG,
|
||||
p_decoderParms->Z,
|
||||
ulsch_harq->d[r],
|
||||
harq_e,
|
||||
ulsch_harq->C,
|
||||
rv_index,
|
||||
ulsch_harq->d_to_be_cleared[r],
|
||||
E,
|
||||
ulsch_harq->F,
|
||||
Kr - ulsch_harq->F - 2 * (p_decoderParms->Z))
|
||||
== -1) {
|
||||
stop_meas(&phy_vars_gNB->ulsch_rate_unmatching_stats);
|
||||
|
||||
LOG_E(PHY, "ulsch_decoding.c: Problem in rate_matching\n");
|
||||
rdata->decodeIterations = max_ldpc_iterations + 1;
|
||||
return;
|
||||
} else {
|
||||
stop_meas(&phy_vars_gNB->ulsch_rate_unmatching_stats);
|
||||
}
|
||||
|
||||
ulsch_harq->d_to_be_cleared[r] = false;
|
||||
|
||||
memset(ulsch_harq->c[r], 0, Kr_bytes);
|
||||
|
||||
if (ulsch_harq->C == 1) {
|
||||
if (A > 3824)
|
||||
crc_type = CRC24_A;
|
||||
else
|
||||
crc_type = CRC16;
|
||||
|
||||
length_dec = ulsch_harq->B;
|
||||
} else {
|
||||
crc_type = CRC24_B;
|
||||
length_dec = (ulsch_harq->B + 24 * ulsch_harq->C) / ulsch_harq->C;
|
||||
}
|
||||
|
||||
// start_meas(&phy_vars_gNB->ulsch_ldpc_decoding_stats);
|
||||
|
||||
// set first 2*Z_c bits to zeros
|
||||
memset(&z[0], 0, 2 * ulsch_harq->Z * sizeof(int16_t));
|
||||
// set Filler bits
|
||||
memset((&z[0] + K_bits_F), 127, ulsch_harq->F * sizeof(int16_t));
|
||||
// Move coded bits before filler bits
|
||||
memcpy((&z[0] + 2 * ulsch_harq->Z), ulsch_harq->d[r], (K_bits_F - 2 * ulsch_harq->Z) * sizeof(int16_t));
|
||||
// skip filler bits
|
||||
memcpy((&z[0] + Kr), ulsch_harq->d[r] + (Kr - 2 * ulsch_harq->Z), (kc * ulsch_harq->Z - Kr) * sizeof(int16_t));
|
||||
// Saturate coded bits before decoding into 8 bits values
|
||||
for (i = 0, j = 0; j < ((kc * ulsch_harq->Z) >> 4) + 1; i += 2, j++) {
|
||||
pl[j] = _mm_packs_epi16(pv[i], pv[i + 1]);
|
||||
}
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
///////////////////////////////////// nrLDPC_decoder /////////////////////////////////////
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////// pl =====> llrProcBuf //////////////////////////////////
|
||||
p_decoderParms->block_length = length_dec;
|
||||
no_iteration_ldpc = nrLDPC_decoder(p_decoderParms, (int8_t *)&pl[0], llrProcBuf, p_procTime);
|
||||
|
||||
if (check_crc((uint8_t *)llrProcBuf, length_dec, ulsch_harq->F, crc_type)) {
|
||||
if (check_crc((uint8_t *)llrProcBuf, length_dec, ulsch_harq->F, crc_type)) {
|
||||
#ifdef PRINT_CRC_CHECK
|
||||
LOG_I(PHY,"Segment %d CRC OK, iterations %d/%d\n",r,no_iteration_ldpc,max_ldpc_iterations);
|
||||
LOG_I(PHY,"Segment %d CRC OK, iterations %d/%d\n",r,no_iteration_ldpc,max_ldpc_iterations);
|
||||
#endif
|
||||
rdata->decodeIterations = no_iteration_ldpc;
|
||||
if (rdata->decodeIterations > p_decoderParms->numMaxIter) rdata->decodeIterations--;
|
||||
} else {
|
||||
#ifdef PRINT_CRC_CHECK
|
||||
LOG_I(PHY,"CRC NOK\n");
|
||||
LOG_I(PHY,"CRC NOK\n");
|
||||
#endif
|
||||
rdata->decodeIterations = max_ldpc_iterations + 1;
|
||||
}
|
||||
@@ -302,13 +261,8 @@ void nr_processULSegment(void *arg)
|
||||
ulsch_harq->c[r][m]= (uint8_t) llrProcBuf[m];
|
||||
}
|
||||
|
||||
#ifdef TASK_MANAGER
|
||||
if(phy_vars_gNB->ldpc_offload_flag == 0)
|
||||
nr_postDecode(rdata->gNB, rdata);
|
||||
#endif
|
||||
|
||||
//stop_meas(&phy_vars_gNB->ulsch_ldpc_decoding_stats);
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t nr_ulsch_decoding(PHY_VARS_gNB *phy_vars_gNB,
|
||||
uint8_t ULSCH_id,
|
||||
@@ -336,10 +290,8 @@ uint32_t nr_ulsch_decoding(PHY_VARS_gNB *phy_vars_gNB,
|
||||
|
||||
int Kr;
|
||||
int Kr_bytes;
|
||||
|
||||
#ifndef TASK_MANAGER
|
||||
|
||||
phy_vars_gNB->nbDecode = 0;
|
||||
#endif
|
||||
harq_process->processedSegments = 0;
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
@@ -614,23 +566,11 @@ uint32_t nr_ulsch_decoding(PHY_VARS_gNB *phy_vars_gNB,
|
||||
else {
|
||||
dtx_det = 0;
|
||||
|
||||
#ifdef TASK_MANAGER
|
||||
ldpcDecode_t* arr = calloc(harq_process->C, sizeof(ldpcDecode_t));
|
||||
_Atomic bool cancel = false;
|
||||
int idx_arr = 0;
|
||||
#endif
|
||||
|
||||
for (int r = 0; r < harq_process->C; r++) {
|
||||
int E = nr_get_E(G, harq_process->C, Qm, n_layers, r);
|
||||
#ifdef TASK_MANAGER
|
||||
ldpcDecode_t* rdata = &arr[idx_arr];
|
||||
rdata->cancel = &cancel;
|
||||
++idx_arr;
|
||||
#else
|
||||
union ldpcReqUnion id = {.s = {ulsch->rnti, frame, nr_tti_rx, 0, 0}};
|
||||
notifiedFIFO_elt_t *req = newNotifiedFIFO_elt(sizeof(ldpcDecode_t), id.p, &phy_vars_gNB->respDecode, &nr_processULSegment);
|
||||
ldpcDecode_t *rdata = (ldpcDecode_t *)NotifiedFifoData(req);
|
||||
#endif
|
||||
decParams.R = nr_get_R_ldpc_decoder(pusch_pdu->pusch_data.rv_index, E, decParams.BG, decParams.Z, &harq_process->llrLen, harq_process->round);
|
||||
rdata->gNB = phy_vars_gNB;
|
||||
rdata->ulsch_harq = harq_process;
|
||||
@@ -650,24 +590,13 @@ uint32_t nr_ulsch_decoding(PHY_VARS_gNB *phy_vars_gNB,
|
||||
rdata->ulsch = ulsch;
|
||||
rdata->ulsch_id = ULSCH_id;
|
||||
rdata->tbslbrm = pusch_pdu->maintenance_parms_v3.tbSizeLbrmBytes;
|
||||
#ifdef TASK_MANAGER
|
||||
task_t t = { .args = rdata, .func = &nr_processULSegment };
|
||||
async_task_manager(&phy_vars_gNB->man, t);
|
||||
#else
|
||||
pushTpool(&phy_vars_gNB->threadPool, req);
|
||||
phy_vars_gNB->nbDecode++;
|
||||
LOG_D(PHY, "Added a block to decode, in pipe: %d\n", phy_vars_gNB->nbDecode);
|
||||
#endif
|
||||
r_offset += E;
|
||||
offset += (Kr_bytes - (harq_process->F >> 3) - ((harq_process->C > 1) ? 3 : 0));
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
}
|
||||
|
||||
#ifdef TASK_MANAGER
|
||||
trigger_and_wait_all_task_manager(&phy_vars_gNB->man);
|
||||
free(arr);
|
||||
#endif
|
||||
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -54,7 +54,8 @@ void nr_adjust_synch_ue(NR_DL_FRAME_PARMS *frame_parms,
|
||||
|
||||
short ncoef = 32767 - coef;
|
||||
|
||||
LOG_D(PHY,"AbsSubframe %d: rx_offset (before) = %d\n",subframe,ue->rx_offset);
|
||||
LOG_D(NR_PHY, "AbsSubframe %d: rx_offset (before) = %d\n", subframe,
|
||||
get_softmodem_params()->sl_mode != 2 ? ue->rx_offset : ue->rx_offset_sl);
|
||||
|
||||
// search for maximum position within the cyclic prefix
|
||||
for (int i = -frame_parms->nb_prefix_samples/2; i < frame_parms->nb_prefix_samples/2; i++) {
|
||||
@@ -89,14 +90,17 @@ void nr_adjust_synch_ue(NR_DL_FRAME_PARMS *frame_parms,
|
||||
else
|
||||
sync_offset = 0;
|
||||
|
||||
if ( abs(diff) < (SYNCH_HYST+sync_offset) )
|
||||
ue->rx_offset = 0;
|
||||
else
|
||||
ue->rx_offset = diff;
|
||||
|
||||
const int sample_shift = -(ue->rx_offset>>1);
|
||||
// reset IIR filter for next offset calculation
|
||||
ue->max_pos_fil += sample_shift << 15;
|
||||
if ( abs(diff) < (SYNCH_HYST+sync_offset) ) {
|
||||
if (get_softmodem_params()->sl_mode == 0)
|
||||
ue->rx_offset = 0;
|
||||
else
|
||||
ue->rx_offset_sl = 0;
|
||||
} else {
|
||||
if (get_softmodem_params()->sl_mode == 0)
|
||||
ue->rx_offset = diff;
|
||||
else
|
||||
ue->rx_offset_sl = diff;
|
||||
}
|
||||
|
||||
if(abs(diff)<5)
|
||||
count_max_pos_ok ++;
|
||||
|
||||
@@ -723,6 +723,94 @@ int nr_pbch_dmrs_correlation(PHY_VARS_NR_UE *ue,
|
||||
return(0);
|
||||
}
|
||||
|
||||
int nr_psbch_dmrs_correlation(PHY_VARS_NR_UE *ue,
|
||||
UE_nr_rxtx_proc_t *proc,
|
||||
uint8_t gNB_id,
|
||||
unsigned char Ns,
|
||||
unsigned char symbol,
|
||||
int dmrss,
|
||||
NR_UE_SSB *current_ssb)
|
||||
{
|
||||
ue->frame_parms.nushift = 0;
|
||||
unsigned int ssb_offset = ue->frame_parms.first_carrier_offset + ue->frame_parms.ssb_start_subcarrier;
|
||||
if (ssb_offset>= ue->frame_parms.ofdm_symbol_size)
|
||||
ssb_offset-=ue->frame_parms.ofdm_symbol_size;
|
||||
|
||||
#ifdef DEBUG_CH
|
||||
printf("PSBCH DMRS Correlation : ThreadId %d, gNB_id %d , OFDM size %d, Ncp=%d, Ns=%d, symbol %d, ssb_offset %d\n",
|
||||
proc->thread_id, gNB_id, ue->frame_parms.ofdm_symbol_size, ue->frame_parms.Ncp, Ns, symbol, ssb_offset);
|
||||
#endif
|
||||
|
||||
AssertFatal(dmrss >= 0 && dmrss <= 12, "symbol %d is illegal for PSBCH DM-RS \n", dmrss);
|
||||
int pilot[300] __attribute__((aligned(16)));
|
||||
nr_psbch_dmrs_rx(dmrss, &ue->nr_gold_psbch[current_ssb->i_ssb], &pilot[0]);
|
||||
if (0 < dmrss && dmrss < 5)
|
||||
return 0;
|
||||
|
||||
int16_t ch[2], *pil, *rxF;
|
||||
c16_t **rxdataF = ue->common_vars.rxdataF;
|
||||
int symbol_offset = ue->frame_parms.ofdm_symbol_size * symbol;
|
||||
unsigned short k = 0;
|
||||
for (int aarx = 0; aarx < ue->frame_parms.nb_antennas_rx; aarx++) {
|
||||
int re_offset = ssb_offset;
|
||||
pil = (int16_t *)&pilot[0];
|
||||
rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+k+re_offset)];
|
||||
ch[0] = (int16_t)(((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15);
|
||||
ch[1] = (int16_t)(((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15);
|
||||
current_ssb->c_re += ch[0];
|
||||
current_ssb->c_im += ch[1];
|
||||
|
||||
pil += 2;
|
||||
re_offset = (re_offset+4) % ue->frame_parms.ofdm_symbol_size;
|
||||
rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+k+re_offset)];
|
||||
ch[0] = (int16_t)(((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15);
|
||||
ch[1] = (int16_t)(((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15);
|
||||
current_ssb->c_re += ch[0];
|
||||
current_ssb->c_im += ch[1];
|
||||
|
||||
pil += 2;
|
||||
re_offset = (re_offset+4) % ue->frame_parms.ofdm_symbol_size;
|
||||
rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+k+re_offset)];
|
||||
ch[0] = (int16_t)(((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15);
|
||||
ch[1] = (int16_t)(((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15);
|
||||
current_ssb->c_re += ch[0];
|
||||
current_ssb->c_im += ch[1];
|
||||
|
||||
pil += 2;
|
||||
re_offset = (re_offset+4) % ue->frame_parms.ofdm_symbol_size;
|
||||
rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+k+re_offset)];
|
||||
|
||||
for (int pilot_cnt = 3; pilot_cnt < (3 * 11); pilot_cnt += 3) {
|
||||
ch[0] = (int16_t)(((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15);
|
||||
ch[1] = (int16_t)(((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15);
|
||||
current_ssb->c_re += ch[0];
|
||||
current_ssb->c_im += ch[1];
|
||||
|
||||
pil += 2;
|
||||
re_offset = (re_offset+4) % ue->frame_parms.ofdm_symbol_size;
|
||||
rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+k+re_offset)];
|
||||
ch[0] = (int16_t)(((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15);
|
||||
ch[1] = (int16_t)(((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15);
|
||||
current_ssb->c_re += ch[0];
|
||||
current_ssb->c_im += ch[1];
|
||||
|
||||
pil += 2;
|
||||
re_offset = (re_offset+4) % ue->frame_parms.ofdm_symbol_size;
|
||||
rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+k+re_offset)];
|
||||
ch[0] = (int16_t)(((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15);
|
||||
ch[1] = (int16_t)(((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15);
|
||||
current_ssb->c_re += ch[0];
|
||||
current_ssb->c_im += ch[1];
|
||||
|
||||
pil += 2;
|
||||
re_offset = (re_offset+4) % ue->frame_parms.ofdm_symbol_size;
|
||||
rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+k+re_offset)];
|
||||
}
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
|
||||
|
||||
int nr_pbch_channel_estimation(PHY_VARS_NR_UE *ue,
|
||||
int estimateSz,
|
||||
struct complex16 dl_ch_estimates[][estimateSz],
|
||||
@@ -989,6 +1077,223 @@ int nr_pbch_channel_estimation(PHY_VARS_NR_UE *ue,
|
||||
return(0);
|
||||
}
|
||||
|
||||
int nr_psbch_channel_estimation(PHY_VARS_NR_UE *ue,
|
||||
int estimateSz,
|
||||
struct complex16 dl_ch_estimates [][estimateSz],
|
||||
struct complex16 dl_ch_estimates_time [][ue->frame_parms.ofdm_symbol_size],
|
||||
UE_nr_rxtx_proc_t *proc,
|
||||
uint8_t gNB_id,
|
||||
unsigned char Ns,
|
||||
unsigned char symbol,
|
||||
int dmrss,
|
||||
uint8_t ssb_index,
|
||||
uint8_t n_hf)
|
||||
{
|
||||
int pilot[200] __attribute__((aligned(16)));
|
||||
unsigned short k;
|
||||
unsigned int pilot_cnt;
|
||||
int16_t *pil,*rxF,*dl_ch,*fl,*fm,*fr;
|
||||
int ch_offset,symbol_offset;
|
||||
|
||||
uint8_t nushift;
|
||||
c16_t **rxdataF=ue->common_vars.rxdataF;
|
||||
|
||||
nushift = 0;// ue->frame_parms.Nid_cell%4;
|
||||
ue->frame_parms.nushift = nushift;
|
||||
unsigned int ssb_offset = ue->frame_parms.first_carrier_offset + ue->frame_parms.ssb_start_subcarrier;
|
||||
if (ssb_offset>= ue->frame_parms.ofdm_symbol_size) ssb_offset-=ue->frame_parms.ofdm_symbol_size;
|
||||
|
||||
ch_offset = ue->frame_parms.ofdm_symbol_size*symbol;
|
||||
|
||||
AssertFatal(dmrss >= 0 && dmrss <= 13,
|
||||
"symbol %d is illegal for PSBCH DM-RS \n",
|
||||
dmrss);
|
||||
|
||||
symbol_offset = ue->frame_parms.ofdm_symbol_size*symbol;
|
||||
|
||||
k = nushift;
|
||||
|
||||
#ifdef DEBUG_CH
|
||||
printf("PSBCH Channel Estimation : ThreadId %d, gNB_id %d ch_offset %d, OFDM size %d, Ncp=%d, Ns=%d, k=%d symbol %d\n",proc->thread_id, gNB_id,ch_offset,ue->frame_parms.ofdm_symbol_size,
|
||||
ue->frame_parms.Ncp,Ns,k, symbol);
|
||||
#endif
|
||||
|
||||
fl = filt16a_l0;
|
||||
fm = filt16a_m0;
|
||||
fr = filt16a_r0;
|
||||
|
||||
idft_size_idx_t idftsizeidx;
|
||||
|
||||
switch (ue->frame_parms.ofdm_symbol_size) {
|
||||
case 128:
|
||||
idftsizeidx = IDFT_128;
|
||||
break;
|
||||
|
||||
case 256:
|
||||
idftsizeidx = IDFT_256;
|
||||
break;
|
||||
|
||||
case 512:
|
||||
idftsizeidx = IDFT_512;
|
||||
break;
|
||||
|
||||
case 1024:
|
||||
idftsizeidx = IDFT_1024;
|
||||
break;
|
||||
|
||||
case 1536:
|
||||
idftsizeidx = IDFT_1536;
|
||||
break;
|
||||
|
||||
case 2048:
|
||||
idftsizeidx = IDFT_2048;
|
||||
break;
|
||||
|
||||
case 3072:
|
||||
idftsizeidx = IDFT_3072;
|
||||
break;
|
||||
|
||||
case 4096:
|
||||
idftsizeidx = IDFT_4096;
|
||||
break;
|
||||
|
||||
default:
|
||||
printf("unsupported ofdm symbol size \n");
|
||||
assert(0);
|
||||
}
|
||||
|
||||
// generate pilot
|
||||
nr_psbch_dmrs_rx(dmrss, &ue->nr_gold_psbch[ssb_index], &pilot[0]);
|
||||
|
||||
for (int aarx = 0; aarx < ue->frame_parms.nb_antennas_rx; aarx++) {
|
||||
|
||||
int re_offset = ssb_offset;
|
||||
pil = (int16_t *)&pilot[0];
|
||||
rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+k+re_offset)];
|
||||
dl_ch = (int16_t *)&dl_ch_estimates[aarx][ch_offset];
|
||||
|
||||
memset(dl_ch,0,sizeof(struct complex16)*(ue->frame_parms.ofdm_symbol_size));
|
||||
|
||||
#ifdef DEBUG_CH
|
||||
printf("psbch ch est pilot addr %p RB_DL %d\n",&pilot[0], ue->frame_parms.N_RB_DL);
|
||||
printf("k %d, first_carrier %d\n",k,ue->frame_parms.first_carrier_offset);
|
||||
printf("rxF addr %p\n", rxF);
|
||||
printf("dl_ch addr %p\n",dl_ch);
|
||||
#endif
|
||||
|
||||
// Treat first 2 pilots specially (left edge)
|
||||
int16_t ch[2];
|
||||
ch[0] = (int16_t)(((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15);
|
||||
ch[1] = (int16_t)(((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15);
|
||||
|
||||
#ifdef DEBUG_CH
|
||||
printf("ch 0 %d\n",((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1]));
|
||||
printf("pilot 0 : rxF - > (%d,%d) addr %p ch -> (%d,%d), pil -> (%d,%d) \n",rxF[0],rxF[1],&rxF[0],ch[0],ch[1],pil[0],pil[1]);
|
||||
#endif
|
||||
multadd_real_vector_complex_scalar(fl, ch, dl_ch, 16);
|
||||
pil += 2;
|
||||
re_offset = (re_offset+4) % ue->frame_parms.ofdm_symbol_size;
|
||||
rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+k+re_offset)];
|
||||
|
||||
//for (int i= 0; i<8; i++)
|
||||
//printf("dl_ch addr %p %d\n", dl_ch+i, *(dl_ch+i));
|
||||
|
||||
ch[0] = (int16_t)(((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15);
|
||||
ch[1] = (int16_t)(((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15);
|
||||
|
||||
#ifdef DEBUG_CH
|
||||
printf("pilot 1 : rxF - > (%d,%d) ch -> (%d,%d), pil -> (%d,%d) \n",rxF[0],rxF[1],ch[0],ch[1],pil[0],pil[1]);
|
||||
#endif
|
||||
multadd_real_vector_complex_scalar(fm, ch, dl_ch, 16);
|
||||
pil += 2;
|
||||
re_offset = (re_offset+4) % ue->frame_parms.ofdm_symbol_size;
|
||||
rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+k+re_offset)];
|
||||
ch[0] = (int16_t)(((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15);
|
||||
ch[1] = (int16_t)(((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15);
|
||||
|
||||
#ifdef DEBUG_CH
|
||||
printf("pilot 2 : rxF - > (%d,%d) ch -> (%d,%d), pil -> (%d,%d) \n",rxF[0],rxF[1],ch[0],ch[1],pil[0],pil[1]);
|
||||
#endif
|
||||
|
||||
multadd_real_vector_complex_scalar(fr,
|
||||
ch,
|
||||
dl_ch,
|
||||
16);
|
||||
pil += 2;
|
||||
re_offset = (re_offset+4) % ue->frame_parms.ofdm_symbol_size;
|
||||
rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+k+re_offset)];
|
||||
dl_ch += 24;
|
||||
|
||||
for (pilot_cnt = 3; pilot_cnt < (3 * 11); pilot_cnt += 3) {
|
||||
ch[0] = (int16_t)(((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15);
|
||||
ch[1] = (int16_t)(((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15);
|
||||
|
||||
#ifdef DEBUG_CH
|
||||
printf("pilot %u : rxF - > (%d,%d) ch -> (%d,%d), pil -> (%d,%d) \n",pilot_cnt,rxF[0],rxF[1],ch[0],ch[1],pil[0],pil[1]);
|
||||
#endif
|
||||
multadd_real_vector_complex_scalar(fl,
|
||||
ch,
|
||||
dl_ch,
|
||||
16);
|
||||
|
||||
//for (int i= 0; i<8; i++)
|
||||
// printf("pilot_cnt %d dl_ch %d %d\n", pilot_cnt, dl_ch+i, *(dl_ch+i));
|
||||
|
||||
pil += 2;
|
||||
re_offset = (re_offset+4) % ue->frame_parms.ofdm_symbol_size;
|
||||
rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+k+re_offset)];
|
||||
|
||||
|
||||
ch[0] = (int16_t)(((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15);
|
||||
ch[1] = (int16_t)(((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15);
|
||||
|
||||
#ifdef DEBUG_CH
|
||||
printf("pilot %u : rxF - > (%d,%d) ch -> (%d,%d), pil -> (%d,%d) \n",pilot_cnt+1,rxF[0],rxF[1],ch[0],ch[1],pil[0],pil[1]);
|
||||
#endif
|
||||
multadd_real_vector_complex_scalar(fm,
|
||||
ch,
|
||||
dl_ch,
|
||||
16);
|
||||
pil += 2;
|
||||
re_offset = (re_offset+4) % ue->frame_parms.ofdm_symbol_size;
|
||||
rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+k+re_offset)];
|
||||
|
||||
|
||||
ch[0] = (int16_t)(((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15);
|
||||
ch[1] = (int16_t)(((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15);
|
||||
|
||||
#ifdef DEBUG_CH
|
||||
printf("pilot %u : rxF - > (%d,%d) ch -> (%d,%d), pil -> (%d,%d) \n",pilot_cnt+2,rxF[0],rxF[1],ch[0],ch[1],pil[0],pil[1]);
|
||||
#endif
|
||||
|
||||
multadd_real_vector_complex_scalar(fr,
|
||||
ch,
|
||||
dl_ch,
|
||||
16);
|
||||
pil += 2;
|
||||
re_offset = (re_offset+4) % ue->frame_parms.ofdm_symbol_size;
|
||||
rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+k+re_offset)];
|
||||
dl_ch += 24;
|
||||
|
||||
}
|
||||
|
||||
if( dmrss == 12) // update time statistics for last PSBCH symbol
|
||||
{
|
||||
// do ifft of channel estimate
|
||||
LOG_D(PHY,"Channel Impulse Computation Slot %d Symbol %d ch_offset %d\n", Ns, symbol, ch_offset);
|
||||
idft(idftsizeidx,
|
||||
(int16_t*) &dl_ch_estimates[aarx][ch_offset],
|
||||
(int16_t*) dl_ch_estimates_time[aarx],
|
||||
1);
|
||||
}
|
||||
}
|
||||
|
||||
if (dmrss == 12)
|
||||
UEscopeCopy(ue, psbchDlChEstimateTime, (void*)dl_ch_estimates_time, sizeof(struct complex16), ue->frame_parms.nb_antennas_rx, idftsizeidx);
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
void nr_pdcch_channel_estimation(PHY_VARS_NR_UE *ue,
|
||||
UE_nr_rxtx_proc_t *proc,
|
||||
unsigned char symbol,
|
||||
|
||||
@@ -67,6 +67,14 @@ int nr_pbch_dmrs_correlation(PHY_VARS_NR_UE *ue,
|
||||
NR_UE_SSB *current_ssb,
|
||||
c16_t rxdataF[][ue->frame_parms.samples_per_slot_wCP]);
|
||||
|
||||
int nr_psbch_dmrs_correlation(PHY_VARS_NR_UE *ue,
|
||||
UE_nr_rxtx_proc_t *proc,
|
||||
uint8_t gNB_id,
|
||||
unsigned char Ns,
|
||||
unsigned char symbol,
|
||||
int dmrss,
|
||||
NR_UE_SSB *current_ssb);
|
||||
|
||||
int nr_pbch_channel_estimation(PHY_VARS_NR_UE *ue,
|
||||
int estimateSz,
|
||||
struct complex16 dl_ch_estimates[][estimateSz],
|
||||
@@ -78,6 +86,18 @@ int nr_pbch_channel_estimation(PHY_VARS_NR_UE *ue,
|
||||
uint8_t n_hf,
|
||||
c16_t rxdataF[][ue->frame_parms.samples_per_slot_wCP]);
|
||||
|
||||
int nr_psbch_channel_estimation(PHY_VARS_NR_UE *ue,
|
||||
int estimateSz,
|
||||
struct complex16 dl_ch_estimates [][estimateSz],
|
||||
struct complex16 dl_ch_estimates_time [][estimateSz],
|
||||
UE_nr_rxtx_proc_t *proc,
|
||||
uint8_t gNB_id,
|
||||
unsigned char Ns,
|
||||
unsigned char symbol,
|
||||
int dmrss,
|
||||
uint8_t ssb_index,
|
||||
uint8_t n_hf);
|
||||
|
||||
int nr_pdsch_channel_estimation(PHY_VARS_NR_UE *ue,
|
||||
UE_nr_rxtx_proc_t *proc,
|
||||
bool is_SI,
|
||||
@@ -115,6 +135,10 @@ void nr_ue_ssb_rsrp_measurements(PHY_VARS_NR_UE *ue,
|
||||
UE_nr_rxtx_proc_t *proc,
|
||||
c16_t rxdataF[][ue->frame_parms.samples_per_slot_wCP]);
|
||||
|
||||
void nr_ue_sl_ssb_rsrp_measurements(PHY_VARS_NR_UE *ue,
|
||||
int ssb_index,
|
||||
UE_nr_rxtx_proc_t *proc);
|
||||
|
||||
void nr_ue_rrc_measurements(PHY_VARS_NR_UE *ue,
|
||||
UE_nr_rxtx_proc_t *proc,
|
||||
c16_t rxdataF[][ue->frame_parms.samples_per_slot_wCP]);
|
||||
|
||||
@@ -37,6 +37,8 @@
|
||||
#include "PHY/phy_extern_nr_ue.h"
|
||||
#include "common/utils/LOG/log.h"
|
||||
#include "PHY/sse_intrin.h"
|
||||
#include "openair1/PHY/NR_REFSIG/sss_nr.h"
|
||||
#include "openair1/PHY/NR_REFSIG/ss_pbch_nr.h"
|
||||
|
||||
//#define k1 1000
|
||||
#define k1 ((long long int) 1000)
|
||||
@@ -236,6 +238,40 @@ void nr_ue_ssb_rsrp_measurements(PHY_VARS_NR_UE *ue,
|
||||
rsrp);
|
||||
}
|
||||
|
||||
// This function implements:
|
||||
// - Sidelink SS reference signal received power (SSS-RSRP)
|
||||
// Measurement units:
|
||||
// - RSRP: W (dBW)
|
||||
// - RX Gain dB
|
||||
void nr_ue_sl_ssb_rsrp_measurements(PHY_VARS_NR_UE *ue,
|
||||
int ssb_index,
|
||||
UE_nr_rxtx_proc_t *proc) {
|
||||
uint32_t rsrp = 0;
|
||||
int nb_re = 0;
|
||||
for (int aarx = 0; aarx < ue->frame_parms.nb_antennas_rx; aarx++) {
|
||||
for (int i = 0; i < NUM_SSS_SYMBOLS; i++) {
|
||||
uint8_t l_sss = (SSS_START_IDX + i) % ue->frame_parms.symbols_per_slot;
|
||||
int16_t *rxF_sss = (int16_t *)&ue->common_vars.rxdataF[aarx][(l_sss * ue->frame_parms.ofdm_symbol_size)];
|
||||
for (int k = PSS_SSS_SUB_CARRIER_START_SL; k < (PSS_SSS_SUB_CARRIER_START_SL + LENGTH_SSS_NR); k++) {
|
||||
#ifdef DEBUG_MEAS_UE
|
||||
LOG_I(NR_PHY, "In %s rxF_sss %d %d\n", __FUNCTION__, rxF_sss[k * 2], rxF_sss[k * 2 + 1]);
|
||||
#endif
|
||||
rsrp += (((int32_t)rxF_sss[k * 2] * rxF_sss[k * 2]) + ((int32_t)rxF_sss[k * 2 + 1] * rxF_sss[k * 2 + 1]));
|
||||
nb_re++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
rsrp /= nb_re;
|
||||
ue->measurements.ssb_rsrp_dBm[ssb_index] = 10 * log10(rsrp) +
|
||||
30 - 10 * log10(pow(2, 30)) -
|
||||
((int)openair0_cfg[0].rx_gain[0] - (int)openair0_cfg[0].rx_gain_offset[0]) -
|
||||
dB_fixed(ue->frame_parms.ofdm_symbol_size);
|
||||
|
||||
LOG_I(NR_PHY, "In %s: [UE %d] ssb %d SS-RSRP: %d dBm/RE (%d)\n",
|
||||
__FUNCTION__, ue->Mod_id, ssb_index, ue->measurements.ssb_rsrp_dBm[ssb_index], rsrp);
|
||||
}
|
||||
|
||||
// This function computes the received noise power
|
||||
// Measurement units:
|
||||
// - psd_awgn (AWGN power spectral density): dBm/Hz
|
||||
|
||||
@@ -284,7 +284,7 @@ void nr_processDLSegment(void* arg) {
|
||||
if (no_iteration_ldpc > dlsch->max_ldpc_iterations)
|
||||
no_iteration_ldpc = dlsch->max_ldpc_iterations;
|
||||
} else {
|
||||
LOG_D(PHY,"%d.%d CRC NOT OK\n",rdata->proc->frame_rx,rdata->proc->nr_slot_rx);
|
||||
LOG_I(PHY,"%d.%d CRC NOT OK\n",rdata->proc->frame_rx,rdata->proc->nr_slot_rx);
|
||||
no_iteration_ldpc = dlsch->max_ldpc_iterations + 1;
|
||||
}
|
||||
|
||||
|
||||
119
openair1/PHY/NR_UE_TRANSPORT/nr_generate_psbch_dmrs_sl.c
Normal file
119
openair1/PHY/NR_UE_TRANSPORT/nr_generate_psbch_dmrs_sl.c
Normal file
@@ -0,0 +1,119 @@
|
||||
/*
|
||||
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The OpenAirInterface Software Alliance licenses this file to You under
|
||||
* the OAI Public License, Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.openairinterface.org/?page_id=698
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*-------------------------------------------------------------------------------
|
||||
* For more information about the OpenAirInterface (OAI) Software Alliance:
|
||||
* contact@openairinterface.org
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
#include <math.h>
|
||||
#include <nr-uesoftmodem.h>
|
||||
|
||||
#include "PHY/defs_nr_UE.h"
|
||||
#include "PHY/phy_extern.h"
|
||||
#include "PHY/NR_UE_TRANSPORT/nr_transport_proto_ue.h"
|
||||
#include "executables/softmodem-common.h"
|
||||
|
||||
//#define DEBUG_PSBCH
|
||||
//#define DEBUG_PSBCH_ENCODING
|
||||
//#define DEBUG_PSBCH_DMRS
|
||||
|
||||
|
||||
int nr_sl_generate_psbch_dmrs(uint32_t *gold_psbch_dmrs,
|
||||
c16_t *txdataF,
|
||||
int16_t amp,
|
||||
uint8_t ssb_start_symbol,
|
||||
NR_DL_FRAME_PARMS *frame_parms) {
|
||||
int dmrs_modulations_per_symbol = 33;
|
||||
int16_t mod_dmrs[NR_PSBCH_DMRS_LENGTH << 1];
|
||||
LOG_D(NR_PHY, "PSBCH DMRS mapping started at symbol %d\n", ssb_start_symbol);
|
||||
|
||||
/// QPSK modulation
|
||||
for (int m = 0; m < NR_PSBCH_DMRS_LENGTH; m++) {
|
||||
AssertFatal(((m << 1) >> 5) < NR_PSBCH_DMRS_LENGTH_DWORD, "Invalid index size %d\n", (m << 1) >> 5);
|
||||
int idx = (((gold_psbch_dmrs[(m << 1) >> 5]) >> ((m << 1) & 0x1f)) & 3);
|
||||
AssertFatal(((idx << 1) + 1) < (sizeof(nr_qpsk_mod_table) / sizeof(nr_qpsk_mod_table[0])), "Invalid index size %d\n", (idx << 1) + 1);
|
||||
AssertFatal((m << 1) + 1 < (sizeof(mod_dmrs) / sizeof(mod_dmrs[0])), "Invalid index size %d\n", (idx << 1) + 1);
|
||||
mod_dmrs[m << 1] = nr_qpsk_mod_table[idx << 1];
|
||||
mod_dmrs[(m << 1) + 1] = nr_qpsk_mod_table[(idx << 1) + 1];
|
||||
#ifdef DEBUG_PSBCH_DMRS
|
||||
printf("m %d idx %d gold seq %d b0-b1 %d-%d mod_dmrs %d %d\n", m, idx, gold_psbch_dmrs[(m << 1) >> 5], (((gold_psbch_dmrs[(m << 1) >> 5]) >> ((m << 1) & 0x1f)) & 1),
|
||||
(((gold_psbch_dmrs[((m << 1) + 1) >> 5]) >> (((m << 1)+1) & 0x1f)) & 1), mod_dmrs[(m << 1)], mod_dmrs[(m << 1)+1]);
|
||||
#endif
|
||||
}
|
||||
|
||||
/// Resource mapping
|
||||
// PSBCH DMRS are mapped within the SSB block on every fourth subcarrier starting from nushift of symbols 1, 2, 3
|
||||
///symbol 0 [0+nushift:4:236+nushift] -- 33 mod symbols
|
||||
int k = frame_parms->first_carrier_offset + frame_parms->ssb_start_subcarrier;
|
||||
int l = ssb_start_symbol;
|
||||
int m = 0;
|
||||
for (; m < dmrs_modulations_per_symbol; m++) {
|
||||
#ifdef DEBUG_PSBCH_DMRS
|
||||
printf("m %d at k %d of l %d\n", m, k, l);
|
||||
#endif
|
||||
AssertFatal(((m << 1) + 1) < (sizeof(mod_dmrs) / sizeof(mod_dmrs[0])), "Invalid index into mod_dmrs. Index %d > %lu\n",
|
||||
(m << 1) + 1, (sizeof(mod_dmrs) / sizeof(mod_dmrs[0])));
|
||||
txdataF[(l * frame_parms->ofdm_symbol_size + k)].r = (amp * mod_dmrs[m << 1]) >> 15;
|
||||
txdataF[(l * frame_parms->ofdm_symbol_size + k)].i = (amp * mod_dmrs[(m << 1) + 1]) >> 15;
|
||||
#ifdef DEBUG_PSBCH_DMRS
|
||||
printf("(%d,%d)\n",
|
||||
((int16_t *)txdataF)[(l * frame_parms->ofdm_symbol_size + k)].r,
|
||||
((int16_t *)txdataF)[(l * frame_parms->ofdm_symbol_size + k)].i);
|
||||
#endif
|
||||
k+=4;
|
||||
if (k >= frame_parms->ofdm_symbol_size)
|
||||
k-=frame_parms->ofdm_symbol_size;
|
||||
}
|
||||
|
||||
int N_SSSB_Symb = 13;
|
||||
l = ssb_start_symbol + 5;
|
||||
while (l < N_SSSB_Symb)
|
||||
{
|
||||
k = frame_parms->first_carrier_offset + frame_parms->ssb_start_subcarrier;
|
||||
int mod_count = 0;
|
||||
while (m < NR_PSBCH_DMRS_LENGTH) {
|
||||
#ifdef DEBUG_PSBCH_DMRS
|
||||
printf("m %d at k %d of l %d\n", m, k, l);
|
||||
#endif
|
||||
AssertFatal(((m << 1) + 1) < (sizeof(mod_dmrs) / sizeof(mod_dmrs[0])), "Invalid index into mod_dmrs. Index %d > %lu\n",
|
||||
(m << 1) + 1, (sizeof(mod_dmrs) / sizeof(mod_dmrs[0])));
|
||||
txdataF[(l * frame_parms->ofdm_symbol_size + k)].r = (amp * mod_dmrs[m << 1]) >> 15;
|
||||
txdataF[(l * frame_parms->ofdm_symbol_size + k)].i = (amp * mod_dmrs[(m << 1) + 1]) >> 15;
|
||||
#ifdef DEBUG_PSBCH_DMRS
|
||||
printf("%d (%d,%d)\n", m,
|
||||
((int16_t *)txdataF)[(l * frame_parms->ofdm_symbol_size + k)].r,
|
||||
((int16_t *)txdataF)[(l * frame_parms->ofdm_symbol_size + k)].i);
|
||||
#endif
|
||||
k+=4;
|
||||
if (k >= frame_parms->ofdm_symbol_size)
|
||||
k-=frame_parms->ofdm_symbol_size;
|
||||
mod_count++;
|
||||
m++;
|
||||
if (mod_count == dmrs_modulations_per_symbol)
|
||||
break;
|
||||
}
|
||||
l++;
|
||||
}
|
||||
|
||||
#ifdef DEBUG_PSBCH_DMRS
|
||||
write_output("txdataF_psbch_dmrs.m", "txdataF_psbch_dmrs", txdataF[0], frame_parms->samples_per_frame_wCP>>1, 1, 1);
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
@@ -44,13 +44,14 @@
|
||||
#include "PHY/NR_REFSIG/pss_nr.h"
|
||||
#include "PHY/NR_REFSIG/sss_nr.h"
|
||||
#include "PHY/NR_REFSIG/refsig_defs_ue.h"
|
||||
#include "executables/softmodem-common.h"
|
||||
|
||||
extern openair0_config_t openair0_cfg[];
|
||||
//static nfapi_nr_config_request_t config_t;
|
||||
//static nfapi_nr_config_request_t* config =&config_t;
|
||||
int cnt=0;
|
||||
|
||||
#define DEBUG_INITIAL_SYNCH
|
||||
#define DEBUG_INITIAL_SYNCH 1
|
||||
#define DUMP_PBCH_CH_ESTIMATES 0
|
||||
|
||||
// create a new node of SSB structure
|
||||
@@ -197,9 +198,169 @@ int nr_pbch_detection(UE_nr_rxtx_proc_t * proc, PHY_VARS_NR_UE *ue, int pbch_ini
|
||||
|
||||
}
|
||||
|
||||
int nr_psbch_detection(UE_nr_rxtx_proc_t * proc, PHY_VARS_NR_UE *ue, int psbch_initial_symbol, NR_UE_PDCCH_CONFIG *phy_pdcch_config)
|
||||
{
|
||||
NR_DL_FRAME_PARMS *frame_parms = &ue->frame_parms;
|
||||
int ret = -1;
|
||||
NR_UE_SSB *best_ssb = NULL;
|
||||
NR_UE_SSB *current_ssb;
|
||||
uint8_t N_L = 2;
|
||||
uint8_t N_hf = 0;
|
||||
for (int l = 0; l < N_L; l++) {
|
||||
current_ssb = create_ssb_node(l, N_hf);
|
||||
start_meas(&ue->dlsch_channel_estimation_stats);
|
||||
// computing correlation between received DMRS symbols and transmitted sequence for current i_ssb and n_hf
|
||||
for (int i = psbch_initial_symbol; i < 13; i++) {
|
||||
if (i >= 1 && i <= 4)
|
||||
continue;
|
||||
nr_psbch_dmrs_correlation(ue, proc, 0, 0, i, i - psbch_initial_symbol, current_ssb);
|
||||
}
|
||||
stop_meas(&ue->dlsch_channel_estimation_stats);
|
||||
|
||||
current_ssb->metric = current_ssb->c_re*current_ssb->c_re + current_ssb->c_im*current_ssb->c_im;
|
||||
|
||||
// generate a list of SSB structures
|
||||
if (best_ssb == NULL)
|
||||
best_ssb = current_ssb;
|
||||
else
|
||||
best_ssb = insert_into_list(best_ssb, current_ssb);
|
||||
|
||||
}
|
||||
NR_UE_SSB *temp_ptr = best_ssb;
|
||||
while (ret != 0 && temp_ptr != NULL) {
|
||||
start_meas(&ue->dlsch_channel_estimation_stats);
|
||||
const int estimateSz = frame_parms->symbols_per_slot * frame_parms->ofdm_symbol_size;
|
||||
__attribute__ ((aligned(32))) struct complex16 dl_ch_estimates[frame_parms->nb_antennas_rx][estimateSz];
|
||||
__attribute__ ((aligned(32))) struct complex16 dl_ch_estimates_time[frame_parms->nb_antennas_rx][frame_parms->ofdm_symbol_size];
|
||||
|
||||
for (int i = psbch_initial_symbol; i < 13; i++) {
|
||||
if (i >= 1 && i <= 4)
|
||||
continue;
|
||||
nr_psbch_channel_estimation(ue, estimateSz, dl_ch_estimates, dl_ch_estimates_time,
|
||||
proc, 0, 0, i, i - psbch_initial_symbol, temp_ptr->i_ssb, temp_ptr->n_hf);
|
||||
}
|
||||
stop_meas(&ue->dlsch_channel_estimation_stats);
|
||||
nr_ue_sl_ssb_rsrp_measurements(ue, temp_ptr->i_ssb, proc);
|
||||
fapiPsbch_t result;
|
||||
ret = nr_rx_psbch(ue, proc, estimateSz, dl_ch_estimates, ue->psbch_vars[0], frame_parms,
|
||||
0, temp_ptr->i_ssb, SISO, phy_pdcch_config, &result);
|
||||
temp_ptr = temp_ptr->next_ssb;
|
||||
}
|
||||
free_list(best_ssb);
|
||||
return ret;
|
||||
}
|
||||
|
||||
char duplex_string[2][4] = {"FDD","TDD"};
|
||||
char prefix_string[2][9] = {"NORMAL","EXTENDED"};
|
||||
|
||||
int nr_sl_initial_sync(UE_nr_rxtx_proc_t *proc,
|
||||
PHY_VARS_NR_UE *ue,
|
||||
int n_frames)
|
||||
{
|
||||
/* Initial synchronisation
|
||||
*
|
||||
* 1 radio frame = 10 ms
|
||||
* <--------------------------------------------------------------------------->
|
||||
* -----------------------------------------------------------------------------
|
||||
* | Received UE data buffer |
|
||||
* ----------------------------------------------------------------------------
|
||||
* -------------------------------------------------
|
||||
* <-------------->| psbch | spss | spss | ssss | ssss | psbch |....
|
||||
* -------------------------------------------------
|
||||
* sync_pos SL S-SSB/PSBCH block
|
||||
*/
|
||||
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_NR_INITIAL_UE_SYNC, VCD_FUNCTION_IN);
|
||||
NR_DL_FRAME_PARMS *fp = &ue->frame_parms;
|
||||
LOG_I(NR_PHY, "nr_initial SL sync ue RB_DL %d prefix 0 %d\n", fp->N_RB_DL, fp->nb_prefix_samples0);
|
||||
int ret = -1;
|
||||
int32_t sync_pos = 0;
|
||||
for (int is = 0; is < n_frames; is++) {
|
||||
sync_pos = pss_synchro_nr(ue, is, NO_RATE_CHANGE);
|
||||
if (sync_pos >= fp->nb_prefix_samples) {
|
||||
// In 5G SL, the first SSB symbol is the PSBCH, so we need adjust the SSB
|
||||
// offset accordingly (psbch_plus_prefix_size). Additionally, there are 2
|
||||
// PSS symbols. So in the case where we correlate on the second PSS,
|
||||
// we need to adjust the SSB offset accordingly (subtracting first PSS prefix).
|
||||
// However, if we correlated on the second PSS, we do not need to include
|
||||
// the size of the first PSS0, becasue the correlation occurs on each individual PSS.
|
||||
// The sync position (sync_pos) is the start of the found PSS + nb_prefix_samples.
|
||||
// PSBCH PREFIX | PSBCH 0 | PSS 0 PREFIX | PSS 0 | PSS 1 PREFIX | PSS 1 |
|
||||
// 176 | 2048 | 144 | 2048 | 144 | 2048 |
|
||||
// ----------------------------------------------------------------------
|
||||
// 176 | 2048 | 144 | - | 144 | X | SSB Offset = X - (144 + 144 + 2048 + 144)
|
||||
// 176 | 2048 | 144 | X | 144 | 2048 | SSB Offset = X - (144 + 2048 + 144)
|
||||
uint32_t psbch_plus_prefix_size = fp->ofdm_symbol_size + fp->nb_prefix_samples0;
|
||||
uint32_t num_pss_prefix_samples_size = fp->nb_prefix_samples;/*(ue->common_vars.N2_id + 1) * fp->nb_prefix_samples;*/
|
||||
LOG_I(NR_PHY, "This is num_pss_prefix_samples_size %d, psbch_plus_prefix_size %d, sync_pos %d, N2_id %d\n",
|
||||
num_pss_prefix_samples_size, psbch_plus_prefix_size, sync_pos, ue->common_vars.N2_id);
|
||||
ue->ssb_offset = sync_pos - num_pss_prefix_samples_size - psbch_plus_prefix_size;
|
||||
} else {
|
||||
ue->ssb_offset = sync_pos + (fp->samples_per_subframe * 10) - fp->nb_prefix_samples;
|
||||
}
|
||||
LOG_I(NR_PHY, "[UE%d] Initial SL sync : n_frames %d Estimated PSS position %d, Nid2 %d ssb_offset %d prefix0 %d\n",
|
||||
ue->Mod_id, n_frames, sync_pos, ue->common_vars.N2_id, ue->ssb_offset,ue->frame_parms.nb_prefix_samples0);
|
||||
if (sync_pos < (NR_NUMBER_OF_SUBFRAMES_PER_FRAME * fp->samples_per_subframe - (NB_SYMBOLS_PBCH * fp->ofdm_symbol_size))) {
|
||||
uint8_t phase_tdd_ncp;
|
||||
int32_t metric_tdd_ncp = 0;
|
||||
const uint32_t rxdataF_sz = ue->frame_parms.samples_per_slot_wCP;
|
||||
__attribute__ ((aligned(32))) c16_t rxdataF[ue->frame_parms.nb_antennas_rx][rxdataF_sz];
|
||||
for (int i = 0; i < 13; i++)
|
||||
nr_slot_fep_init_sync(ue, proc, i, is * fp->samples_per_frame + ue->ssb_offset,
|
||||
false, rxdataF);
|
||||
memcpy(ue->common_vars.rxdataF[0], rxdataF[0], rxdataF_sz * sizeof(int32_t));
|
||||
LOG_I(NR_PHY, "Calling sss detection (normal CP) prefix0 %d\n",ue->frame_parms.nb_prefix_samples0);
|
||||
int freq_offset_sss = 0;
|
||||
ret = rx_sss_sl_nr(ue, proc, &metric_tdd_ncp, &phase_tdd_ncp, &freq_offset_sss);
|
||||
if (ue->UE_fo_compensation) {
|
||||
double sampling_time = 1 / (1.0e3 * fp->samples_per_subframe);
|
||||
double off_angle = -2 * M_PI * sampling_time * freq_offset_sss;
|
||||
int start = is * fp->samples_per_frame + ue->ssb_offset;
|
||||
int end = start + NR_N_SYMBOLS_SSB * (fp->ofdm_symbol_size + fp->nb_prefix_samples);
|
||||
for (int n = start; n < end; n++) {
|
||||
for (int ar = 0; ar < fp->nb_antennas_rx; ar++) {
|
||||
double re = ((double)(((short *)ue->common_vars.rxdata[ar]))[2 * n]);
|
||||
double im = ((double)(((short *)ue->common_vars.rxdata[ar]))[2 * n + 1]);
|
||||
((short *)ue->common_vars.rxdata[ar])[2 * n] = (short)(round(re * cos(n * off_angle) - im * sin(n * off_angle)));
|
||||
((short *)ue->common_vars.rxdata[ar])[2 * n + 1] = (short)(round(re * sin(n * off_angle) + im *cos(n * off_angle)));
|
||||
}
|
||||
}
|
||||
ue->common_vars.freq_offset += freq_offset_sss;
|
||||
}
|
||||
if (ret == 0) {
|
||||
nr_gold_psbch(ue);
|
||||
NR_UE_PDCCH_CONFIG phy_pdcch_config = {0};
|
||||
ret = nr_psbch_detection(proc, ue, 0, &phy_pdcch_config);
|
||||
}
|
||||
LOG_I(NR_PHY, "TDD Normal prefix: CellId %d metric %d, phase %d, psbch %d\n",
|
||||
fp->Nid_cell, metric_tdd_ncp, phase_tdd_ncp, ret);
|
||||
} else {
|
||||
LOG_I(NR_PHY, "TDD Normal prefix: SSS error condition: sync_pos %d\n", sync_pos);
|
||||
}
|
||||
if (ret == 0) break;
|
||||
if (ret < 0) exit(-1);
|
||||
}
|
||||
if (ret == 0) {
|
||||
LOG_I(NR_PHY, "[UE %d] rx_offset %d Measured Carrier Frequency %.0f Hz (offset %d Hz) prefix0 %d\n",
|
||||
ue->Mod_id, ue->rx_offset_sl, openair0_cfg[0].rx_freq[0] + ue->common_vars.freq_offset, ue->common_vars.freq_offset,ue->frame_parms.nb_prefix_samples0);
|
||||
if (ue->UE_scan_carrier == 0) {
|
||||
ue->psbch_vars[0]->pdu_errors_conseq = 0;
|
||||
}
|
||||
} else {
|
||||
LOG_I(NR_PHY, "[UE%d] Initial sync : PSBCH not ok. Estimated PSS position %d, Nid1 %d, Nid2 %d, Frame_type %d\n",
|
||||
ue->Mod_id, sync_pos, GET_NID1_SL(fp->Nid_SL), GET_NID2_SL(fp->Nid_SL), fp->frame_type);
|
||||
ue->psbch_vars[0]->pdu_errors_last = ue->psbch_vars[0]->pdu_errors;
|
||||
ue->psbch_vars[0]->pdu_errors++;
|
||||
ue->psbch_vars[0]->pdu_errors_conseq++;
|
||||
int rx_power = 0;
|
||||
ue->measurements.rx_power_avg[0] = rx_power / fp->nb_antennas_rx;
|
||||
ue->measurements.rx_power_avg_dB[0] = dB_fixed(ue->measurements.rx_power_avg[0]);
|
||||
LOG_I(NR_PHY, "[UE%d] Gain Control - Initial sync : Estimated power: %d dB\n", ue->Mod_id, ue->measurements.rx_power_avg_dB[0]);
|
||||
}
|
||||
|
||||
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_NR_INITIAL_UE_SYNC, VCD_FUNCTION_OUT);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int nr_initial_sync(UE_nr_rxtx_proc_t *proc,
|
||||
PHY_VARS_NR_UE *ue,
|
||||
int n_frames, int sa)
|
||||
|
||||
@@ -450,7 +450,7 @@ int32_t generate_nr_prach(PHY_VARS_NR_UE *ue, uint8_t gNB_id, int frame, uint8_t
|
||||
memcpy(prach, prach+(dftlen<<1), (Ncp<<2));
|
||||
// here we have | Prefix | Prach | Prach |
|
||||
prach_len = (dftlen*2)+Ncp;
|
||||
} else if (prach_fmt_id == 5 || prach_fmt_id == 10) { // 4xdftlen
|
||||
} else if (prach_fmt_id == 5) { // 4xdftlen
|
||||
// here we have | empty | Prach | empty | empty | empty |
|
||||
memcpy(prach2+(dftlen<<1), prach2, (dftlen<<2));
|
||||
// here we have | empty | Prach | Prach | empty | empty |
|
||||
|
||||
450
openair1/PHY/NR_UE_TRANSPORT/nr_psbch.c
Normal file
450
openair1/PHY/NR_UE_TRANSPORT/nr_psbch.c
Normal file
@@ -0,0 +1,450 @@
|
||||
/*
|
||||
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The OpenAirInterface Software Alliance licenses this file to You under
|
||||
* the OAI Public License, Version 1.0 (the "License"); you may not use this file
|
||||
* except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.openairinterface.org/?page_id=698
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*-------------------------------------------------------------------------------
|
||||
* For more information about the OpenAirInterface (OAI) Software Alliance:
|
||||
* contact@openairinterface.org
|
||||
*/
|
||||
|
||||
/*! \file PHY/LTE_TRANSPORT/psbch.c
|
||||
* \brief Top-level routines for generating and decoding the PSBCH/BCH physical/transport channel V8.6 2009-03
|
||||
* \author R. Knopp, F. Kaltenberger
|
||||
* \date 2011
|
||||
* \version 0.1
|
||||
* \company Eurecom
|
||||
* \email: knopp@eurecom.fr,florian.kaltenberger.fr
|
||||
* \note
|
||||
* \warning
|
||||
*/
|
||||
#include "PHY/defs_nr_UE.h"
|
||||
#include "PHY/CODING/coding_extern.h"
|
||||
#include "PHY/phy_extern_nr_ue.h"
|
||||
#include "PHY/sse_intrin.h"
|
||||
#include "PHY/LTE_REFSIG/lte_refsig.h"
|
||||
#include "openair1/SCHED_NR_UE/defs.h"
|
||||
#include <openair1/PHY/NR_UE_TRANSPORT/nr_transport_proto_ue.h>
|
||||
#include <openair1/PHY/TOOLS/phy_scope_interface.h>
|
||||
#include "openair1/PHY/NR_REFSIG/refsig_defs_ue.h"
|
||||
|
||||
// #define DEBUG_PSBCH
|
||||
//#define DEBUG_PSBCH_ENCODING
|
||||
|
||||
//#include "PHY_INTERFACE/defs.h"
|
||||
|
||||
|
||||
static void nr_psbch_quantize(int16_t *psbch_llr8,
|
||||
int16_t *psbch_llr,
|
||||
uint16_t len) {
|
||||
for (int i = 0; i < len; i++) {
|
||||
if (psbch_llr[i] > 31)
|
||||
psbch_llr8[i] = 32;
|
||||
else if (psbch_llr[i] < -31)
|
||||
psbch_llr8[i] = -32;
|
||||
else
|
||||
psbch_llr8[i] = psbch_llr[i];
|
||||
}
|
||||
}
|
||||
|
||||
static uint16_t nr_psbch_extract(c16_t **rxdataF,
|
||||
const int estimateSz,
|
||||
struct complex16 dl_ch_estimates[][estimateSz],
|
||||
struct complex16 rxdataF_ext[][PSBCH_MAX_RE_PER_SYMBOL],
|
||||
struct complex16 dl_ch_estimates_ext[][PSBCH_MAX_RE_PER_SYMBOL],
|
||||
uint32_t symbol,
|
||||
uint32_t s_offset,
|
||||
NR_DL_FRAME_PARMS *frame_parms) {
|
||||
uint16_t rb;
|
||||
uint8_t i,j,aarx;
|
||||
int nushiftmod4 = 0;//frame_parms->nushift;
|
||||
AssertFatal(symbol == 0 || symbol < 14,
|
||||
"symbol %d illegal for PSBCH extraction\n",
|
||||
symbol);
|
||||
|
||||
for (aarx=0; aarx<frame_parms->nb_antennas_rx; aarx++) {
|
||||
unsigned int rx_offset = frame_parms->first_carrier_offset + frame_parms->ssb_start_subcarrier;
|
||||
rx_offset = (rx_offset)%(frame_parms->ofdm_symbol_size);
|
||||
struct complex16 *rxF = (struct complex16 *)&rxdataF[aarx][(symbol+s_offset)*frame_parms->ofdm_symbol_size];
|
||||
struct complex16 *rxF_ext = rxdataF_ext[aarx];
|
||||
#ifdef DEBUG_PSBCH
|
||||
LOG_I(NR_PHY,"extract_rbs (nushift %d): rx_offset=%d, symbol %u\n",frame_parms->nushift,
|
||||
(rx_offset + ((symbol+s_offset)*(frame_parms->ofdm_symbol_size))),symbol);
|
||||
int16_t *p = (int16_t *)rxF;
|
||||
|
||||
for (int i =0; i<8; i++) {
|
||||
LOG_I(NR_PHY,"rxF [%d]= %d\n",i,rxF[i]);
|
||||
LOG_I(NR_PHY,"psbch extract rxF %d %d addr %p\n", p[2*i], p[2*i+1], &p[2*i]);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
for (rb=0; rb<11; rb++) {
|
||||
j=0;
|
||||
|
||||
if (symbol == 0 || ((symbol > 4) && (symbol <= 13))) {
|
||||
for (i=0; i<12; i++) {
|
||||
if ((i!=nushiftmod4) &&
|
||||
(i!=(nushiftmod4+4)) &&
|
||||
(i!=(nushiftmod4+8))) {
|
||||
rxF_ext[j]=rxF[rx_offset];
|
||||
#ifdef DEBUG_PSBCH
|
||||
LOG_I(NR_PHY,"rxF ext[%d] = (%d,%d) rxF [%u]= (%d,%d)\n", (9*rb) + j,
|
||||
rxF_ext[j].r, rxF_ext[j].i,
|
||||
rx_offset,
|
||||
rxF[rx_offset].r,rxF[rx_offset].i);
|
||||
#endif
|
||||
j++;
|
||||
}
|
||||
|
||||
rx_offset=(rx_offset+1)%(frame_parms->ofdm_symbol_size);
|
||||
//rx_offset = (rx_offset >= frame_parms->ofdm_symbol_size) ? (rx_offset - frame_parms->ofdm_symbol_size + 1) : (rx_offset+1);
|
||||
}
|
||||
|
||||
rxF_ext+=9;
|
||||
}
|
||||
}
|
||||
|
||||
struct complex16 *dl_ch0 = &dl_ch_estimates[aarx][((symbol+s_offset)*(frame_parms->ofdm_symbol_size))];
|
||||
|
||||
//printf("dl_ch0 addr %p\n",dl_ch0);
|
||||
struct complex16 *dl_ch0_ext = dl_ch_estimates_ext[aarx];
|
||||
|
||||
for (rb=0; rb<11; rb++) {
|
||||
j=0;
|
||||
|
||||
if (symbol == 0 || ((symbol > 4) && (symbol <= 13))) {
|
||||
for (i=0; i<12; i++) {
|
||||
if ((i!=nushiftmod4) &&
|
||||
(i!=(nushiftmod4+4)) &&
|
||||
(i!=(nushiftmod4+8))) {
|
||||
dl_ch0_ext[j]=dl_ch0[i];
|
||||
#ifdef DEBUG_PSBCH
|
||||
if ((rb==0) && (i<2))
|
||||
printf("dl ch0 ext[%d] = (%d,%d) dl_ch0 [%d]= (%d,%d)\n",j,
|
||||
dl_ch0_ext[j].r, dl_ch0_ext[j].i,
|
||||
i,
|
||||
dl_ch0[j].r, dl_ch0[j].i);
|
||||
#endif
|
||||
j++;
|
||||
}
|
||||
}
|
||||
|
||||
dl_ch0+=12;
|
||||
dl_ch0_ext+=9;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
//__m128i avg128;
|
||||
|
||||
//compute average channel_level on each (TX,RX) antenna pair
|
||||
int nr_psbch_channel_level(struct complex16 dl_ch_estimates_ext[][PSBCH_MAX_RE_PER_SYMBOL],
|
||||
NR_DL_FRAME_PARMS *frame_parms,
|
||||
int nb_re) {
|
||||
int16_t nb_rb=nb_re/12;
|
||||
#if defined(__x86_64__) || defined(__i386__)
|
||||
__m128i avg128;
|
||||
__m128i *dl_ch128;
|
||||
#elif defined(__arm__)
|
||||
int32x4_t avg128;
|
||||
int16x8_t *dl_ch128;
|
||||
#endif
|
||||
int avg1=0,avg2=0;
|
||||
|
||||
for (int aarx=0; aarx<frame_parms->nb_antennas_rx; aarx++) {
|
||||
//clear average level
|
||||
#if defined(__x86_64__) || defined(__i386__)
|
||||
avg128 = _mm_setzero_si128();
|
||||
dl_ch128=(__m128i *)dl_ch_estimates_ext[aarx];
|
||||
#elif defined(__arm__)
|
||||
avg128 = vdupq_n_s32(0);
|
||||
dl_ch128=(int16x8_t *)dl_ch_estimates_ext[aarx];
|
||||
#endif
|
||||
|
||||
for (int rb=0; rb<nb_rb; rb++) {
|
||||
#if defined(__x86_64__) || defined(__i386__)
|
||||
avg128 = _mm_add_epi32(avg128,_mm_madd_epi16(dl_ch128[0],dl_ch128[0]));
|
||||
avg128 = _mm_add_epi32(avg128,_mm_madd_epi16(dl_ch128[1],dl_ch128[1]));
|
||||
avg128 = _mm_add_epi32(avg128,_mm_madd_epi16(dl_ch128[2],dl_ch128[2]));
|
||||
#elif defined(__arm__)
|
||||
abort();
|
||||
// to be filled in
|
||||
#endif
|
||||
dl_ch128+=3;
|
||||
/*
|
||||
if (rb==0) {
|
||||
print_shorts("dl_ch128",&dl_ch128[0]);
|
||||
print_shorts("dl_ch128",&dl_ch128[1]);
|
||||
print_shorts("dl_ch128",&dl_ch128[2]);
|
||||
}*/
|
||||
}
|
||||
|
||||
avg1 = (((int *)&avg128)[0] +
|
||||
((int *)&avg128)[1] +
|
||||
((int *)&avg128)[2] +
|
||||
((int *)&avg128)[3])/(nb_rb*12);
|
||||
|
||||
if (avg1>avg2)
|
||||
avg2 = avg1;
|
||||
|
||||
//LOG_I(PHY,"Channel level : %d, %d\n",avg1, avg2);
|
||||
}
|
||||
|
||||
return(avg2);
|
||||
}
|
||||
|
||||
static void nr_psbch_channel_compensation(struct complex16 rxdataF_ext[][PSBCH_MAX_RE_PER_SYMBOL],
|
||||
struct complex16 dl_ch_estimates_ext[][PSBCH_MAX_RE_PER_SYMBOL],
|
||||
int nb_re,
|
||||
struct complex16 rxdataF_comp[][PSBCH_MAX_RE_PER_SYMBOL],
|
||||
NR_DL_FRAME_PARMS *frame_parms,
|
||||
uint8_t output_shift) {
|
||||
for (int aarx=0; aarx<frame_parms->nb_antennas_rx; aarx++) {
|
||||
vect128 *dl_ch128 = (vect128 *)dl_ch_estimates_ext[aarx];
|
||||
vect128 *rxdataF128 = (vect128 *)rxdataF_ext[aarx];
|
||||
vect128 *rxdataF_comp128 = (vect128 *)rxdataF_comp[aarx];
|
||||
|
||||
for (int re=0; re<nb_re; re+=12) {
|
||||
*rxdataF_comp128++ = mulByConjugate128(rxdataF128++, dl_ch128++, output_shift);
|
||||
*rxdataF_comp128++ = mulByConjugate128(rxdataF128++, dl_ch128++, output_shift);
|
||||
*rxdataF_comp128++ = mulByConjugate128(rxdataF128++, dl_ch128++, output_shift);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void nr_psbch_unscrambling(NR_UE_PSBCH *psbch,
|
||||
int16_t *demod_psbch_e,
|
||||
uint16_t Nid,
|
||||
uint8_t nushift,
|
||||
uint16_t M,
|
||||
uint16_t length,
|
||||
uint8_t bitwise,
|
||||
uint32_t unscrambling_mask,
|
||||
uint32_t psbch_a_prime,
|
||||
uint32_t *psbch_a_interleaved) {
|
||||
uint8_t reset, offset;
|
||||
uint32_t x1, x2, s=0;
|
||||
uint8_t k=0;
|
||||
reset = 1;
|
||||
// x1 is set in first call to lte_gold_generic
|
||||
x2 = Nid; //this is c_init
|
||||
|
||||
// The Gold sequence is shifted by nushift* M, so we skip (nushift*M /32) double words
|
||||
for (int i=0; i<(uint16_t)ceil(((float)M)/32); i++) {
|
||||
s = lte_gold_generic(&x1, &x2, reset);
|
||||
reset = 0;
|
||||
}
|
||||
|
||||
// Scrambling is now done with offset (nushift*M)%32
|
||||
offset = 0; //(nushift*M)&0x1f;
|
||||
|
||||
for (int i=0; i<length; i++) {
|
||||
/*if (((i+offset)&0x1f)==0) {
|
||||
s = lte_gold_generic(&x1, &x2, reset);
|
||||
reset = 0;
|
||||
}*/
|
||||
if (bitwise) {
|
||||
if (((k+offset)&0x1f)==0 && (!((unscrambling_mask>>i)&1))) {
|
||||
s = lte_gold_generic(&x1, &x2, reset);
|
||||
reset = 0;
|
||||
}
|
||||
|
||||
*psbch_a_interleaved ^= ((unscrambling_mask>>i)&1)? ((psbch_a_prime>>i)&1)<<i : (((psbch_a_prime>>i)&1) ^ ((s>>((k+offset)&0x1f))&1))<<i;
|
||||
k += (!((unscrambling_mask>>i)&1));
|
||||
#ifdef DEBUG_PSBCH_ENCODING
|
||||
printf("i %d k %d offset %d (unscrambling_mask>>i)&1) %d s: %08x\t psbch_a_interleaved 0x%08x (!((unscrambling_mask>>i)&1)) %d\n", i, k, offset, (unscrambling_mask>>i)&1, s, *psbch_a_interleaved,
|
||||
(!((unscrambling_mask>>i)&1)));
|
||||
#endif
|
||||
} else {
|
||||
if (((i+offset)&0x1f)==0) {
|
||||
s = lte_gold_generic(&x1, &x2, reset);
|
||||
reset = 0;
|
||||
}
|
||||
|
||||
if (((s>>((i+offset)&0x1f))&1)==1)
|
||||
demod_psbch_e[i] = -demod_psbch_e[i];
|
||||
|
||||
#ifdef DEBUG_PSBCH_ENCODING
|
||||
|
||||
if (i<8)
|
||||
printf("s %d demod_psbch_e[i] %d\n", ((s>>((i+offset)&0x1f))&1), demod_psbch_e[i]);
|
||||
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void nr_sl_common_signal_procedures(PHY_VARS_NR_UE *ue, int frame, int slot)
|
||||
{
|
||||
NR_DL_FRAME_PARMS *fp = &ue->frame_parms;
|
||||
c16_t **txdataF = ue->common_vars.txdataF;
|
||||
uint8_t ssb_index = 0; //TODO: Need update to get 0 or 1 from parameter in case of mu = 1.
|
||||
int txdataF_offset = slot * fp->samples_per_slot_wCP;
|
||||
|
||||
uint16_t ssb_start_symbol = 0;
|
||||
LOG_D(NR_PHY, "common_signal_procedures: frame %d, slot %d ssb index %d, ssb_start_symbol %d, txdataF_offset %d\n",
|
||||
frame, slot, ssb_index, ssb_start_symbol, txdataF_offset);
|
||||
|
||||
const int prb_offset = 0; //TODO: Need to properly get these values.
|
||||
const int sc_offset = 0; //TODO: Need to properly get these values.
|
||||
fp->ssb_start_subcarrier = prb_offset * 12 + sc_offset;
|
||||
LOG_D(NR_PHY, "SSB first subcarrier %d (%d,%d)\n", fp->ssb_start_subcarrier, prb_offset, sc_offset);
|
||||
nr_gold_psbch(ue);
|
||||
nr_sl_generate_pss(&txdataF[0][txdataF_offset], AMP, ssb_start_symbol, fp);
|
||||
nr_sl_generate_sss(&txdataF[0][txdataF_offset], AMP, ssb_start_symbol, fp);
|
||||
nr_sl_generate_psbch_dmrs(&ue->nr_gold_psbch[ssb_index & 7], &txdataF[0][txdataF_offset], AMP, ssb_start_symbol, fp);
|
||||
uint8_t n_hf = 0;
|
||||
nr_generate_sl_psbch(ue, &txdataF[0][txdataF_offset], AMP, ssb_start_symbol, n_hf, frame, fp);
|
||||
}
|
||||
|
||||
int nr_rx_psbch( PHY_VARS_NR_UE *ue,
|
||||
UE_nr_rxtx_proc_t *proc,
|
||||
int estimateSz, struct complex16 dl_ch_estimates [][estimateSz],
|
||||
NR_UE_PSBCH *nr_ue_psbch_vars,
|
||||
NR_DL_FRAME_PARMS *frame_parms,
|
||||
uint8_t gNB_id,
|
||||
uint8_t i_ssb,
|
||||
MIMO_mode_t mimo_mode,
|
||||
NR_UE_PDCCH_CONFIG *phy_pdcch_config,
|
||||
fapiPsbch_t *result) {
|
||||
|
||||
NR_UE_COMMON *nr_ue_common_vars = &ue->common_vars;
|
||||
uint8_t ssb_index = 0; //TODO: Need update to get 0 or 1 from parameter in case of mu = 1.
|
||||
int symbol_offset = ue->is_synchronized > 0 ? (ue->slss->sl_timeoffsetssb_r16 + ue->slss->sl_timeinterval_r16 * ssb_index) * frame_parms->symbols_per_slot : 0;
|
||||
int psbch_e_rx_idx = 0;
|
||||
int16_t psbch_unClipped[NR_POLAR_PSBCH_E] = {0};
|
||||
int16_t psbch_e_rx[NR_POLAR_PSBCH_E] = {0};
|
||||
// symbol refers to symbol within SSB. symbol_offset is the offset of the SSB wrt start of slot
|
||||
for (int symbol = 0; symbol < 13; symbol++) {
|
||||
const uint16_t nb_re = 99;
|
||||
__attribute__ ((aligned(32))) struct complex16 rxdataF_ext[frame_parms->nb_antennas_rx][PSBCH_MAX_RE_PER_SYMBOL];
|
||||
__attribute__ ((aligned(32))) struct complex16 dl_ch_estimates_ext[frame_parms->nb_antennas_rx][PSBCH_MAX_RE_PER_SYMBOL];
|
||||
memset(dl_ch_estimates_ext,0, sizeof dl_ch_estimates_ext);
|
||||
nr_psbch_extract(nr_ue_common_vars->rxdataF,
|
||||
estimateSz,
|
||||
dl_ch_estimates,
|
||||
rxdataF_ext,
|
||||
dl_ch_estimates_ext,
|
||||
symbol,
|
||||
symbol_offset,
|
||||
frame_parms);
|
||||
|
||||
int log2_maxh = 0;
|
||||
if (symbol == 0) {
|
||||
int max_h = nr_psbch_channel_level(dl_ch_estimates_ext,
|
||||
frame_parms,
|
||||
nb_re);
|
||||
log2_maxh = 3 + (log2_approx(max_h) / 2);
|
||||
#ifdef DEBUG_PSBCH
|
||||
LOG_I(NR_PHY, "PSBCH Symbol %d ofdm size %d\n", symbol, frame_parms->ofdm_symbol_size );
|
||||
LOG_I(NR_PHY,"PSBCH log2_maxh = %d (%d)\n", log2_maxh, max_h);
|
||||
#endif
|
||||
}
|
||||
|
||||
__attribute__ ((aligned(32))) struct complex16 rxdataF_comp[frame_parms->nb_antennas_rx][PSBCH_MAX_RE_PER_SYMBOL];
|
||||
nr_psbch_channel_compensation(rxdataF_ext,
|
||||
dl_ch_estimates_ext,
|
||||
nb_re,
|
||||
rxdataF_comp,
|
||||
frame_parms,
|
||||
log2_maxh); // log2_maxh+I0_shift
|
||||
|
||||
int nb = 198; // QPSK 2 bits 99*2 (m from TX side)
|
||||
nr_psbch_quantize(psbch_e_rx + psbch_e_rx_idx, (short *)rxdataF_comp[0], nb);
|
||||
memcpy(psbch_unClipped + psbch_e_rx_idx, rxdataF_comp[0], nb*sizeof(int16_t));
|
||||
psbch_e_rx_idx += nb;
|
||||
|
||||
if (symbol == 0)
|
||||
symbol += 4; // skip to accommodate PSS and SSS
|
||||
}
|
||||
// legacy code use int16, but it is complex16
|
||||
UEscopeCopy(ue, psbchRxdataF_comp, psbch_unClipped, sizeof(struct complex16), frame_parms->nb_antennas_rx, psbch_e_rx_idx/2);
|
||||
UEscopeCopy(ue, psbchLlr, psbch_e_rx, sizeof(int16_t), frame_parms->nb_antennas_rx, psbch_e_rx_idx);
|
||||
#ifdef DEBUG_PSBCH
|
||||
for (int cnt = 0; cnt < NR_POLAR_PSBCH_E; cnt++)
|
||||
printf("psbch rx llr %d\n",*(psbch_e_rx + cnt));
|
||||
|
||||
#endif
|
||||
//un-scrambling
|
||||
uint16_t M = NR_POLAR_PSBCH_E;
|
||||
uint8_t nushift = 0; //(Lmax==4)? i_ssb&3 : i_ssb&7;
|
||||
uint32_t psbch_a_interleaved = 0;
|
||||
uint32_t psbch_a_prime = 0;
|
||||
nr_psbch_unscrambling(nr_ue_psbch_vars, psbch_e_rx, frame_parms->Nid_SL, nushift, M, NR_POLAR_PSBCH_E,
|
||||
0, 0, psbch_a_prime, &psbch_a_interleaved);
|
||||
//polar decoding de-rate matching
|
||||
uint64_t tmp = 0;
|
||||
uint32_t decoderState = polar_decoder_int16(psbch_e_rx, (uint64_t *)&tmp, 0,
|
||||
NR_POLAR_PSBCH_MESSAGE_TYPE,
|
||||
NR_POLAR_PSBCH_PAYLOAD_BITS,
|
||||
NR_POLAR_PSBCH_AGGREGATION_LEVEL);
|
||||
psbch_a_prime = tmp;
|
||||
if(decoderState)
|
||||
return(decoderState);
|
||||
|
||||
uint32_t payload = 0;
|
||||
for (int i = 0; i < NR_POLAR_PSBCH_PAYLOAD_BITS; i++)
|
||||
payload |= (((uint64_t)psbch_a_prime >> i) & 1) << (31 - i);
|
||||
LOG_I(NR_PHY, "PSBCH payload received 0x%x \n", payload);
|
||||
|
||||
for (int i = 0; i < 4; i++)
|
||||
result->decoded_output[i] = (uint8_t)((payload >> ((3 - i) << 3)) & 0xff);
|
||||
|
||||
frame_parms->half_frame_bit = (result->xtra_byte >> 4) & 0x01; // computing the half frame index from the extra byte
|
||||
frame_parms->ssb_index = i_ssb; // ssb index corresponds to i_ssb for Lmax = 4,8
|
||||
|
||||
if (frame_parms->Lmax == 64) { // for Lmax = 64 ssb index 4th,5th and 6th bits are in extra byte
|
||||
for (int i = 0; i < 3; i++)
|
||||
frame_parms->ssb_index += (((result->xtra_byte >> (7 - i)) & 0x01) << (3 + i));
|
||||
}
|
||||
|
||||
ue->symbol_offset = 0;
|
||||
if (frame_parms->half_frame_bit)
|
||||
ue->symbol_offset += (frame_parms->slots_per_frame>>1)*frame_parms->symbols_per_slot;
|
||||
|
||||
uint8_t frame_number_4lsb = 0;
|
||||
|
||||
for (int i = 0; i < 4; i++)
|
||||
frame_number_4lsb |= ((result->xtra_byte >> i) & 1) << (3 - i);
|
||||
|
||||
proc->decoded_frame_rx = frame_number_4lsb;
|
||||
#ifdef DEBUG_PSBCH
|
||||
printf("xtra_byte %x payload %x\n", result->xtra_byte, payload);
|
||||
|
||||
for (int i=0; i<(NR_POLAR_PSBCH_PAYLOAD_BITS>>3); i++) {
|
||||
// printf("unscrambling psbch_a[%d] = %x \n", i,psbch_a[i]);
|
||||
printf("[PSBCH] decoder payload[%d] = %x\n",i,result->decoded_output[i]);
|
||||
}
|
||||
// TODO: Handle MAC Layer on RX
|
||||
|
||||
nr_downlink_indication_t dl_indication;
|
||||
fapi_nr_rx_indication_t *rx_ind = calloc(1, sizeof(*rx_ind));
|
||||
uint16_t number_pdus = 1;
|
||||
|
||||
nr_fill_dl_indication(&dl_indication, NULL, rx_ind, proc, ue, gNB_id, phy_pdcch_config);
|
||||
nr_fill_rx_indication(rx_ind, FAPI_NR_RX_PDU_TYPE_SSB, gNB_id, ue, NULL, NULL, number_pdus, proc,(void *)result);
|
||||
|
||||
if (ue->if_inst && ue->if_inst->dl_indication)
|
||||
ue->if_inst->dl_indication(&dl_indication, NULL);
|
||||
else
|
||||
free(rx_ind); // dl_indication would free(), so free() here if not called
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -41,6 +41,7 @@
|
||||
#define NR_PUSCH_x 2 // UCI placeholder bit TS 38.212 V15.4.0 subclause 5.3.3.1
|
||||
#define NR_PUSCH_y 3 // UCI placeholder bit
|
||||
|
||||
extern short nr_qpsk_mod_table[8];
|
||||
// Functions below implement 36-211 and 36-212
|
||||
|
||||
/** @addtogroup _PHY_TRANSPORT_
|
||||
@@ -280,6 +281,54 @@ int32_t nr_rx_pdcch(PHY_VARS_NR_UE *ue,
|
||||
*/
|
||||
int rx_sss(PHY_VARS_NR_UE *phy_vars_ue,int32_t *tot_metric,uint8_t *flip_max,uint8_t *phase_max);
|
||||
|
||||
/*!
|
||||
\fn int nr_sl_generate_psbch_dmrs
|
||||
\brief Generation of the DMRS for the PSBCH
|
||||
@param
|
||||
@returns 0 on success
|
||||
*/
|
||||
int nr_sl_generate_psbch_dmrs(uint32_t *gold_pbch_dmrs,
|
||||
c16_t *txdataF,
|
||||
int16_t amp,
|
||||
uint8_t ssb_start_symbol,
|
||||
NR_DL_FRAME_PARMS *frame_parms);
|
||||
|
||||
/*!
|
||||
\fn int nr_generate_pss
|
||||
\brief Generation of the NR PSS
|
||||
@param
|
||||
@returns 0 on success
|
||||
*/
|
||||
int nr_sl_generate_pss(c16_t *txdataF,
|
||||
int16_t amp,
|
||||
uint8_t ssb_start_symbol,
|
||||
NR_DL_FRAME_PARMS *frame_parms);
|
||||
|
||||
/*!
|
||||
\fn int nr_generate_sss
|
||||
\brief Generation of the NR SSS
|
||||
@param
|
||||
@returns 0 on success
|
||||
*/
|
||||
int nr_sl_generate_sss(c16_t *txdataF,
|
||||
int16_t amp,
|
||||
uint8_t ssb_start_symbol,
|
||||
NR_DL_FRAME_PARMS *frame_parms);
|
||||
|
||||
/*!
|
||||
\fn int nr_generate_sl_pbch
|
||||
\brief Generation of the PBCH
|
||||
@param
|
||||
@returns 0 on success
|
||||
*/
|
||||
int nr_generate_sl_psbch(PHY_VARS_NR_UE *ue,
|
||||
c16_t *txdataF,
|
||||
int16_t amp,
|
||||
uint8_t ssb_start_symbol,
|
||||
uint8_t n_hf,
|
||||
int sfn,
|
||||
NR_DL_FRAME_PARMS *frame_parms);
|
||||
|
||||
/*! \brief receiver for the PBCH
|
||||
\returns number of tx antennas or -1 if error
|
||||
*/
|
||||
@@ -294,12 +343,34 @@ int nr_rx_pbch(PHY_VARS_NR_UE *ue,
|
||||
fapiPbch_t* result,
|
||||
c16_t rxdataF[][ue->frame_parms.samples_per_slot_wCP]);
|
||||
|
||||
/*! \brief receiver for the PBCH
|
||||
\returns number of tx antennas or -1 if error
|
||||
*/
|
||||
|
||||
void nr_sl_common_signal_procedures(PHY_VARS_NR_UE *ue, int frame, int slot);
|
||||
|
||||
int nr_rx_psbch(PHY_VARS_NR_UE *ue,
|
||||
UE_nr_rxtx_proc_t *proc,
|
||||
const int estimateSz,
|
||||
struct complex16 dl_ch_estimates[][estimateSz],
|
||||
NR_UE_PSBCH *nr_ue_psbch_vars,
|
||||
NR_DL_FRAME_PARMS *frame_parms,
|
||||
uint8_t eNB_id,
|
||||
uint8_t i_ssb,
|
||||
MIMO_mode_t mimo_mode,
|
||||
NR_UE_PDCCH_CONFIG *phy_pdcch_config,
|
||||
fapiPsbch_t* result);
|
||||
|
||||
int nr_pbch_detection(UE_nr_rxtx_proc_t *proc,
|
||||
PHY_VARS_NR_UE *ue,
|
||||
int pbch_initial_symbol,
|
||||
nr_phy_data_t *phy_data,
|
||||
c16_t rxdataF[][ue->frame_parms.samples_per_slot_wCP]);
|
||||
|
||||
int nr_psbch_detection(UE_nr_rxtx_proc_t *proc,
|
||||
PHY_VARS_NR_UE *ue,
|
||||
int psbch_initial_symbol,
|
||||
NR_UE_PDCCH_CONFIG *phy_pdcch_config);
|
||||
|
||||
#ifndef modOrder
|
||||
#define modOrder(I_MCS,I_TBS) ((I_MCS-I_TBS)*2+2) // Find modulation order from I_TBS and I_MCS
|
||||
@@ -307,6 +378,10 @@ int nr_pbch_detection(UE_nr_rxtx_proc_t *proc,
|
||||
|
||||
int dump_ue_stats(PHY_VARS_NR_UE *phy_vars_ue, UE_nr_rxtx_proc_t *proc, char* buffer, int length, runmode_t mode, int input_level_dBm);
|
||||
|
||||
int nr_sl_initial_sync(UE_nr_rxtx_proc_t *proc,
|
||||
PHY_VARS_NR_UE *phy_vars_ue,
|
||||
int n_frames);
|
||||
|
||||
/*!
|
||||
\brief This function performs the initial cell search procedure - PSS detection, SSS detection and PBCH detection. At the
|
||||
end, the basic frame parameters are known (Frame configuration - TDD/FDD and cyclic prefix length,
|
||||
@@ -330,6 +405,13 @@ void nr_get_carrier_frequencies(PHY_VARS_NR_UE *ue,
|
||||
uint64_t *dl_Carrier,
|
||||
uint64_t *ul_Carrier);
|
||||
|
||||
/*!
|
||||
\brief This function gets the carrier frequencies either from FP or command-line-set global variables, depending on the availability of the latter
|
||||
@param fp Pointer to frame params
|
||||
@param sl_Carrier Pointer to SL carrier to be set
|
||||
*/
|
||||
void nr_get_carrier_frequencies_sl(PHY_VARS_NR_UE *ue,
|
||||
uint64_t *sl_Carrier);
|
||||
/*!
|
||||
\brief This function sets the OAI RF card rx/tx params
|
||||
@param openair0_cfg Pointer OAI config for a specific card
|
||||
@@ -347,6 +429,10 @@ void nr_rf_card_config_freq(openair0_config_t *openair0_cfg,
|
||||
uint64_t dl_Carrier,
|
||||
int freq_offset);
|
||||
|
||||
void nr_sl_rf_card_config_freq(PHY_VARS_NR_UE *ue,
|
||||
openair0_config_t *openair0_cfg,
|
||||
int freq_offset);
|
||||
|
||||
void nr_pdcch_unscrambling(int16_t *z,
|
||||
uint16_t scrambling_RNTI,
|
||||
uint32_t length,
|
||||
|
||||
@@ -166,6 +166,17 @@ typedef struct {
|
||||
uint8_t ptrs_symbol_index;
|
||||
} NR_UE_DLSCH_t;
|
||||
|
||||
typedef struct {
|
||||
long sl_numssb_withinperiod_r16;
|
||||
long sl_timeoffsetssb_r16;
|
||||
long sl_timeinterval_r16;
|
||||
long sl_numssb_withinperiod_r16_copy;
|
||||
long sl_timeinterval_r16_copy;
|
||||
long sl_timeoffsetssb_r16_copy;
|
||||
uint16_t slss_id;
|
||||
uint8_t sl_mib_length;
|
||||
uint8_t sl_mib[5];
|
||||
} NR_SLSS_t;
|
||||
|
||||
/**@}*/
|
||||
#endif
|
||||
|
||||
@@ -46,6 +46,15 @@ void nr_get_carrier_frequencies(PHY_VARS_NR_UE *ue, uint64_t *dl_carrier, uint64
|
||||
}
|
||||
}
|
||||
|
||||
void nr_get_carrier_frequencies_sl(PHY_VARS_NR_UE *ue, uint64_t *sl_carrier) {
|
||||
|
||||
NR_DL_FRAME_PARMS *fp = &ue->frame_parms;
|
||||
if (ue->if_freq!=0) {
|
||||
*sl_carrier = ue->if_freq;
|
||||
} else {
|
||||
*sl_carrier = fp->sl_CarrierFreq;
|
||||
}
|
||||
}
|
||||
|
||||
void nr_rf_card_config_gain(openair0_config_t *openair0_cfg,
|
||||
double rx_gain_off){
|
||||
@@ -113,3 +122,17 @@ void nr_rf_card_config_freq(openair0_config_t *openair0_cfg,
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
void nr_sl_rf_card_config_freq(PHY_VARS_NR_UE *ue, openair0_config_t *openair0_cfg, int freq_offset) {
|
||||
|
||||
for (int i = 0; i < openair0_cfg->rx_num_channels; i++) {
|
||||
openair0_cfg->rx_gain[ue->rf_map.chain + i] = ue->rx_total_gain_dB;
|
||||
if (ue->UE_scan_carrier == 1) {
|
||||
if (freq_offset >= 0)
|
||||
openair0_cfg->rx_freq[ue->rf_map.chain + i] += abs(freq_offset);
|
||||
else
|
||||
openair0_cfg->rx_freq[ue->rf_map.chain + i] -= abs(freq_offset);
|
||||
freq_offset=0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
254
openair1/PHY/NR_UE_TRANSPORT/psbch_nr_sl.c
Normal file
254
openair1/PHY/NR_UE_TRANSPORT/psbch_nr_sl.c
Normal file
@@ -0,0 +1,254 @@
|
||||
/*
|
||||
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The OpenAirInterface Software Alliance licenses this file to You under
|
||||
* the OAI Public License, Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.openairinterface.org/?page_id=698
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*-------------------------------------------------------------------------------
|
||||
* For more information about the OpenAirInterface (OAI) Software Alliance:
|
||||
* contact@openairinterface.org
|
||||
*/
|
||||
|
||||
/*! \file PHY/NR_TRANSPORT/nr_psbch.c
|
||||
* \brief Top-level routines for generating the PSBCH/BCH physical/transport channel V15.1 03/2018
|
||||
* \author Guy De Souza
|
||||
* \thanks Special Thanks to Son Dang for helpful contributions and testing
|
||||
* \date 2018
|
||||
* \version 0.1
|
||||
* \company Eurecom
|
||||
* \email: desouza@eurecom.fr
|
||||
* \note
|
||||
* \warning
|
||||
*/
|
||||
|
||||
#include "PHY/defs_gNB.h"
|
||||
#include "PHY/defs_nr_UE.h"
|
||||
#include "PHY/NR_TRANSPORT/nr_transport_proto.h"
|
||||
#include "PHY/LTE_REFSIG/lte_refsig.h"
|
||||
#include "PHY/sse_intrin.h"
|
||||
#include "executables/softmodem-common.h"
|
||||
|
||||
//#define DEBUG_PSBCH
|
||||
//#define DEBUG_PSBCH_ENCODING
|
||||
//#define DEBUG_PSBCH_DMRS
|
||||
|
||||
extern short nr_qpsk_mod_table[8];
|
||||
|
||||
static void nr_psbch_scrambling(NR_UE_PSBCH *psbch,
|
||||
uint32_t Nid,
|
||||
uint8_t nushift,
|
||||
uint16_t M,
|
||||
uint16_t length,
|
||||
uint8_t encoded,
|
||||
uint32_t unscrambling_mask) {
|
||||
uint32_t *psbch_e = psbch->psbch_e;
|
||||
uint8_t reset = 1;
|
||||
uint32_t x1, s = 0;
|
||||
uint32_t x2 = Nid;
|
||||
// The Gold sequence is shifted by nushift* M, so we skip (nushift*M /32) double words
|
||||
for (int i = 0; i < (uint16_t)ceil(((float)M) / 32); i++) {
|
||||
s = lte_gold_generic(&x1, &x2, reset);
|
||||
reset = 0;
|
||||
}
|
||||
|
||||
// Scrambling is now done with offset (nushift*M)%32
|
||||
uint8_t offset = 0; //(nushift*M)&0x1f;
|
||||
#ifdef DEBUG_PSBCH_ENCODING
|
||||
printf("Scrambling params: nushift %d M %d length %d encoded %d offset %d\n", nushift, M, length, encoded, offset);
|
||||
#endif
|
||||
#ifdef DEBUG_PSBCH_ENCODING
|
||||
printf("s: %04x\t", s);
|
||||
#endif
|
||||
|
||||
int k = 0;
|
||||
if (!encoded) {
|
||||
/// 1st Scrambling
|
||||
for (int i = 0; i < length; ++i) {
|
||||
if ((unscrambling_mask>>i)&1)
|
||||
psbch->psbch_a_prime ^= ((psbch->psbch_a_interleaved >> i) & 1) << i;
|
||||
else {
|
||||
if (((k + offset) & 0x1f) == 0) {
|
||||
s = lte_gold_generic(&x1, &x2, reset);
|
||||
reset = 0;
|
||||
}
|
||||
|
||||
psbch->psbch_a_prime ^= (((psbch->psbch_a_interleaved >> i) & 1) ^ ((s >> ((k + offset) & 0x1f)) & 1)) << i;
|
||||
k++; /// k increase only when payload bit is not special bit
|
||||
}
|
||||
}
|
||||
} else {
|
||||
/// 2nd Scrambling
|
||||
for (int i = 0; i < length; ++i) {
|
||||
if (((i + offset) & 0x1f) == 0) {
|
||||
s = lte_gold_generic(&x1, &x2, reset);
|
||||
reset = 0;
|
||||
}
|
||||
AssertFatal((i >> 5) < NR_POLAR_PSBCH_E_DWORD, "Invalid index into psbch->psbch_e. Index %d > %d\n",
|
||||
(i >> 5), NR_POLAR_PSBCH_E_DWORD);
|
||||
psbch_e[i >> 5] ^= (((s >> ((i + offset) & 0x1f)) & 1) << (i & 0x1f));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int nr_generate_sl_psbch(PHY_VARS_NR_UE *ue,
|
||||
c16_t *txdataF,
|
||||
int16_t amp,
|
||||
uint8_t ssb_start_symbol,
|
||||
uint8_t n_hf,
|
||||
int sfn,
|
||||
NR_DL_FRAME_PARMS *frame_parms) {
|
||||
LOG_I(NR_PHY, "PSBCH SL generation started\n");
|
||||
|
||||
/* payload is 56 bits */
|
||||
PSBCH_payload psbch_payload; // NR Side Link Payload for Rel 16
|
||||
psbch_payload.coverageIndicator = 0; // 1 bit
|
||||
psbch_payload.tddConfig = 0xFFF; // 12 bits for TDD configuration
|
||||
psbch_payload.DFN = 0x3FF; // 10 bits for DFN
|
||||
psbch_payload.slotIndex = 0x2A; // 7 bits for Slot Index //frame_parms->p_TDD_UL_DL_ConfigDedicated->slotIndex;
|
||||
psbch_payload.reserved = 0; // 2 bits reserved
|
||||
|
||||
NR_UE_PSBCH m_psbch;
|
||||
ue->psbch_vars[0] = &m_psbch;
|
||||
NR_UE_PSBCH *psbch = ue->psbch_vars[0];
|
||||
memset((void *)psbch, 0, sizeof(NR_UE_PSBCH));
|
||||
psbch->psbch_a = *((uint32_t *)&psbch_payload);
|
||||
psbch->psbch_a_interleaved = psbch->psbch_a; // skip interlevaing for Sidelink
|
||||
|
||||
psbch->psbch_a_prime = 0;
|
||||
|
||||
#ifdef DEBUG_PSBCH_ENCODING
|
||||
printf("PSBCH payload = 0x%08x\n",psbch->psbch_a);
|
||||
#endif
|
||||
|
||||
// Encoder reversal
|
||||
uint64_t a_reversed = 0;
|
||||
for (int i = 0; i < NR_POLAR_PSBCH_PAYLOAD_BITS; i++)
|
||||
a_reversed |= (((uint64_t)psbch->psbch_a_interleaved >> i) & 1) << (31 - i);
|
||||
|
||||
/// CRC, coding and rate matching
|
||||
polar_encoder_fast(&a_reversed, (void*)psbch->psbch_e, 0, 0,
|
||||
NR_POLAR_PSBCH_MESSAGE_TYPE, NR_POLAR_PSBCH_PAYLOAD_BITS, NR_POLAR_PSBCH_AGGREGATION_LEVEL);
|
||||
|
||||
#ifdef DEBUG_PSBCH_ENCODING
|
||||
printf("PSBCH SL generation started\n");
|
||||
printf("Channel coding:\n");
|
||||
for (int i=0; i<NR_POLAR_PSBCH_E_DWORD; i++)
|
||||
printf("sl_psbch_e[%d]: 0x%08x\n", i, psbch->psbch_e[i]);
|
||||
printf("\n");
|
||||
#endif
|
||||
|
||||
/// Scrambling
|
||||
uint16_t M = NR_POLAR_PSBCH_E;
|
||||
uint8_t nushift = 0;
|
||||
nr_psbch_scrambling(psbch, (uint32_t)frame_parms->Nid_SL, nushift, M, NR_POLAR_PSBCH_E, 1, 0);
|
||||
#ifdef DEBUG_PSBCH_ENCODING
|
||||
printf("Scrambling:\n");
|
||||
|
||||
for (int i=0; i<NR_POLAR_PSBCH_E_DWORD; i++) {
|
||||
printf("sl_psbch_e[%d]: 0x%08x\n", i, psbch->psbch_e[i]);
|
||||
}
|
||||
printf("\n");
|
||||
#endif
|
||||
|
||||
/// QPSK modulation
|
||||
int16_t mod_psbch_e[NR_POLAR_PSBCH_E];
|
||||
for (int i = 0; i < NR_POLAR_PSBCH_E >> 1; i++) {
|
||||
AssertFatal(((i << 1) >> 5) < NR_POLAR_PSBCH_E_DWORD, "Invalid index into psbch->psbch_e. Index %d > %d\n",
|
||||
((i << 1) >> 5), NR_POLAR_PSBCH_E_DWORD);
|
||||
uint8_t idx = ((psbch->psbch_e[(i << 1) >> 5] >> ((i << 1) & 0x1f)) & 3);
|
||||
AssertFatal(((idx << 1) + 1) < 8, "Invalid index into nr_qpsk_mod_table. Index %d > 8\n",
|
||||
(idx << 1) + 1);
|
||||
AssertFatal(((i << 1) + 1) < (sizeof(mod_psbch_e) / sizeof(mod_psbch_e[0])), "Invalid index into mod_psbch_e. Index %d > %lu\n",
|
||||
(i << 1) + 1, sizeof(mod_psbch_e) / sizeof(mod_psbch_e[0]));
|
||||
mod_psbch_e[i << 1] = nr_qpsk_mod_table[idx << 1];
|
||||
mod_psbch_e[(i << 1) + 1] = nr_qpsk_mod_table[(idx << 1) + 1];
|
||||
#ifdef DEBUG_PSBCH
|
||||
printf("i %d idx %d mod_psbch %d %d\n", i, idx, mod_psbch_e[2*i], mod_psbch_e[2*i+1]);
|
||||
#endif
|
||||
}
|
||||
|
||||
/// Resource mapping
|
||||
nushift = 0; //config->cell_config.phy_cell_id.value &3;
|
||||
// PSBCH modulated symbols are mapped within the SSB block on symbols 1, 2, 3 excluding the subcarriers used for the PSBCH DMRS
|
||||
///symbol 1 [0:132] -- 99 mod symbols
|
||||
int k = frame_parms->first_carrier_offset + frame_parms->ssb_start_subcarrier;
|
||||
int l = ssb_start_symbol;
|
||||
int m = 0;
|
||||
|
||||
for (int ssb_sc_idx = 0; ssb_sc_idx < NR_PSBCH_MAX_NB_CARRIERS; ssb_sc_idx++) {
|
||||
if ((ssb_sc_idx & 3) == nushift) { //skip DMRS
|
||||
k++;
|
||||
continue;
|
||||
} else {
|
||||
#ifdef DEBUG_PSBCH
|
||||
printf("m %d ssb_sc_idx %d at k %d of l %d\n", m, ssb_sc_idx, k, l);
|
||||
#endif
|
||||
AssertFatal(((m << 1) + 1) < (sizeof(mod_psbch_e) / sizeof(mod_psbch_e[0])), "Invalid index into mod_psbch_e. Index %d > %lu\n",
|
||||
(m << 1) + 1, sizeof(mod_psbch_e) / sizeof(mod_psbch_e[0]));
|
||||
int idx = (l * frame_parms->ofdm_symbol_size + k);
|
||||
AssertFatal((idx + 1) < frame_parms->samples_per_frame_wCP, "txdataF index %d invalid!\n", idx + 1);
|
||||
txdataF[idx].r = (amp * mod_psbch_e[m << 1]) >> 15;
|
||||
txdataF[idx].i = (amp * mod_psbch_e[(m << 1) + 1]) >> 15;
|
||||
k++;
|
||||
m++;
|
||||
}
|
||||
|
||||
if (k >= frame_parms->ofdm_symbol_size)
|
||||
k-=frame_parms->ofdm_symbol_size;
|
||||
}
|
||||
|
||||
int N_SSSB_Symb = 14;
|
||||
///symbol 5 to N_SSSB_Symb [0:132] -- 99 mod symbols
|
||||
l = ssb_start_symbol + 5;
|
||||
AssertFatal(m == 99, "m does not equal 99");
|
||||
m = 99;
|
||||
while (l < N_SSSB_Symb - 1)
|
||||
{
|
||||
k = frame_parms->first_carrier_offset + frame_parms->ssb_start_subcarrier;
|
||||
|
||||
for (int ssb_sc_idx = 0; ssb_sc_idx < NR_PSBCH_MAX_NB_CARRIERS; ssb_sc_idx++) {
|
||||
if ((ssb_sc_idx & 3) == nushift) { //skip DMRS
|
||||
k++;
|
||||
continue;
|
||||
} else {
|
||||
#ifdef DEBUG_PSBCH
|
||||
printf("m %d ssb_sc_idx %d at k %d of l %d\n", m, ssb_sc_idx, k, l);
|
||||
#endif
|
||||
|
||||
AssertFatal((m << 1) + 1 < (sizeof(mod_psbch_e) / sizeof(mod_psbch_e[0])),
|
||||
"Indexing outside of mod_psbch_e bounds. %d > %lu",
|
||||
(m << 1) + 1 , (sizeof(mod_psbch_e) / sizeof(mod_psbch_e[0])));
|
||||
|
||||
txdataF[(l * frame_parms->ofdm_symbol_size + k)].r = (amp * mod_psbch_e[m << 1]) >> 15;
|
||||
txdataF[(l * frame_parms->ofdm_symbol_size + k)].i = (amp * mod_psbch_e[(m << 1) + 1]) >> 15;
|
||||
k++;
|
||||
m++;
|
||||
}
|
||||
|
||||
if (k >= frame_parms->ofdm_symbol_size)
|
||||
k-=frame_parms->ofdm_symbol_size;
|
||||
}
|
||||
l++;
|
||||
}
|
||||
#ifdef DEBUG_PSBCH
|
||||
char buffer[frame_parms->ofdm_symbol_size];
|
||||
for (int i = 0; i < 13; i++) {
|
||||
if (i >= 1 && i <= 4)
|
||||
continue;
|
||||
bzero(buffer, sizeof(buffer));
|
||||
LOG_I(NR_PHY, "PSBCH %d = %s\n", i, hexdump(&txdataF[frame_parms->ofdm_symbol_size*i],
|
||||
frame_parms->ofdm_symbol_size, buffer, sizeof(buffer)));
|
||||
}
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
@@ -64,69 +64,33 @@
|
||||
*
|
||||
*********************************************************************/
|
||||
|
||||
void generate_pss_nr(NR_DL_FRAME_PARMS *fp,int N_ID_2)
|
||||
void generate_pss_nr(NR_DL_FRAME_PARMS *fp, int N_ID_2, int pss_seq_offset)
|
||||
{
|
||||
AssertFatal(fp->ofdm_symbol_size > 127,"Illegal ofdm_symbol_size %d\n",fp->ofdm_symbol_size);
|
||||
AssertFatal(N_ID_2>=0 && N_ID_2 <=2,"Illegal N_ID_2 %d\n",N_ID_2);
|
||||
int16_t d_pss[LENGTH_PSS_NR];
|
||||
const int x_initial[INITIAL_PSS_NR] = {0, 1, 1, 0, 1, 1, 1};
|
||||
int16_t x[LENGTH_PSS_NR];
|
||||
int16_t *primary_synchro_time = primary_synchro_time_nr[N_ID_2];
|
||||
unsigned int length = fp->ofdm_symbol_size;
|
||||
unsigned int size = length * IQ_SIZE; /* i & q */
|
||||
int16_t *primary_synchro = primary_synchro_nr[N_ID_2]; /* pss in complex with alternatively i then q */
|
||||
int16_t *primary_synchro2 = primary_synchro_nr2[N_ID_2]; /* pss in complex with alternatively i then q */
|
||||
|
||||
|
||||
#define INITIAL_PSS_NR (7)
|
||||
const int x_initial[INITIAL_PSS_NR] = {0, 1, 1 , 0, 1, 1, 1};
|
||||
|
||||
assert(N_ID_2 < NUMBER_PSS_SEQUENCE);
|
||||
assert(size <= SYNCF_TMP_SIZE);
|
||||
assert(size <= SYNC_TMP_SIZE);
|
||||
|
||||
bzero(synchroF_tmp, size);
|
||||
bzero(synchro_tmp, size);
|
||||
|
||||
for (int i=0; i < INITIAL_PSS_NR; i++) {
|
||||
for (int i = 0; i < INITIAL_PSS_NR; i++)
|
||||
x[i] = x_initial[i];
|
||||
|
||||
for (int i = 0; i < (LENGTH_PSS_NR - INITIAL_PSS_NR); i++)
|
||||
x[i + INITIAL_PSS_NR] = (x[i + 4] + x[i]) % (2);
|
||||
|
||||
int16_t d_pss[LENGTH_PSS_NR];
|
||||
for (int n = 0; n < LENGTH_PSS_NR; n++) {
|
||||
int m = (n + 43 * N_ID_2) % (LENGTH_PSS_NR);
|
||||
d_pss[n] = 1 - 2 * x[m];
|
||||
}
|
||||
|
||||
for (int i=0; i < (LENGTH_PSS_NR - INITIAL_PSS_NR); i++) {
|
||||
x[i+INITIAL_PSS_NR] = (x[i + 4] + x[i])%(2);
|
||||
c16_t *primary_synchro = primary_synchro_nr[N_ID_2];
|
||||
c16_t *primary_synchro2 = primary_synchro_nr2[N_ID_2];
|
||||
for (int i = 0; i < LENGTH_PSS_NR; i++) {
|
||||
primary_synchro[i].r = (d_pss[i] * SHRT_MAX) >> SCALING_PSS_NR;
|
||||
primary_synchro[i].i = 0;
|
||||
primary_synchro2[i].r = d_pss[i];
|
||||
primary_synchro2[i].i = d_pss[i];
|
||||
}
|
||||
|
||||
for (int n=0; n < LENGTH_PSS_NR; n++) {
|
||||
int m = (n + 43*N_ID_2)%(LENGTH_PSS_NR);
|
||||
d_pss[n] = 1 - 2*x[m];
|
||||
}
|
||||
|
||||
/* PSS is directly mapped to subcarrier without modulation 38.211 */
|
||||
for (int i=0; i < LENGTH_PSS_NR; i++) {
|
||||
#if 1
|
||||
primary_synchro[2*i] = (d_pss[i] * SHRT_MAX)>>SCALING_PSS_NR; /* Maximum value for type short int ie int16_t */
|
||||
primary_synchro[2*i+1] = 0;
|
||||
primary_synchro2[i] = d_pss[i];
|
||||
#else
|
||||
primary_synchro[2*i] = d_pss[i] * AMP;
|
||||
primary_synchro[2*i+1] = 0;
|
||||
primary_synchro2[i] = d_pss[i];
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef DBG_PSS_NR
|
||||
|
||||
if (N_ID_2 == 0) {
|
||||
char output_file[255];
|
||||
char sequence_name[255];
|
||||
sprintf(output_file, "pss_seq_%d_%u.m", N_ID_2, length);
|
||||
sprintf(sequence_name, "pss_seq_%d_%u", N_ID_2, length);
|
||||
printf("file %s sequence %s\n", output_file, sequence_name);
|
||||
|
||||
LOG_M(output_file, sequence_name, primary_synchro, LENGTH_PSS_NR, 1, 1);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/* call of IDFT should be done with ordered input as below
|
||||
*
|
||||
* n input samples
|
||||
@@ -149,99 +113,27 @@ void generate_pss_nr(NR_DL_FRAME_PARMS *fp,int N_ID_2)
|
||||
* sample 0 is for continuous frequency which is used here
|
||||
*/
|
||||
|
||||
unsigned int k = fp->first_carrier_offset + fp->ssb_start_subcarrier + 56; //and
|
||||
unsigned int subcarrier_start = get_softmodem_params()->sl_mode == 0 ? PSS_SSS_SUB_CARRIER_START : PSS_SSS_SUB_CARRIER_START_SL;
|
||||
unsigned int k = fp->first_carrier_offset + fp->ssb_start_subcarrier + subcarrier_start;
|
||||
if (k>= fp->ofdm_symbol_size) k-=fp->ofdm_symbol_size;
|
||||
|
||||
|
||||
for (int i=0; i < LENGTH_PSS_NR; i++) {
|
||||
synchroF_tmp[2*k] = primary_synchro[2*i];
|
||||
synchroF_tmp[2*k+1] = primary_synchro[2*i+1];
|
||||
|
||||
LOG_I(NR_PHY,"generate_pss_nr: subcarrier_start %d, k %d\n",subcarrier_start,k);
|
||||
c16_t in[sizeof(int16_t) * fp->ofdm_symbol_size] __attribute__((aligned(32)));
|
||||
memset(in, 0, sizeof(in));
|
||||
for (int i = 0; i < LENGTH_PSS_NR; i++) {
|
||||
in[k]= primary_synchro[i];
|
||||
k++;
|
||||
|
||||
if (k == length) k=0;
|
||||
|
||||
if (k == fp->ofdm_symbol_size) k = 0;
|
||||
}
|
||||
|
||||
/* IFFT will give temporal signal of Pss */
|
||||
|
||||
|
||||
|
||||
idft((int16_t)get_idft(length),
|
||||
synchroF_tmp, /* complex input */
|
||||
synchro_tmp, /* complex output */
|
||||
1); /* scaling factor */
|
||||
|
||||
/* then get final pss in time */
|
||||
for (unsigned int i=0; i<length; i++) {
|
||||
((int32_t *)primary_synchro_time)[i] = ((int32_t *)synchro_tmp)[i];
|
||||
c16_t out[sizeof(int16_t) * fp->ofdm_symbol_size] __attribute__((aligned(32)));
|
||||
memset(out, 0, sizeof(out));
|
||||
memset(primary_synchro_time_nr[N_ID_2], 0, sizeof(int16_t) * fp->ofdm_symbol_size);
|
||||
idft((int16_t)get_idft(fp->ofdm_symbol_size), (int16_t *)in, (int16_t *)out, 1);
|
||||
for (unsigned int i = 0; i < fp->ofdm_symbol_size; i++) {
|
||||
primary_synchro_time_nr[N_ID_2][i] = out[i];
|
||||
}
|
||||
|
||||
#ifdef DBG_PSS_NR
|
||||
|
||||
if (N_ID_2 == 0) {
|
||||
char output_file[255];
|
||||
char sequence_name[255];
|
||||
sprintf(output_file, "%s%d_%u%s","pss_seq_t_", N_ID_2, length, ".m");
|
||||
sprintf(sequence_name, "%s%d_%u","pss_seq_t_", N_ID_2, length);
|
||||
|
||||
printf("file %s sequence %s\n", output_file, sequence_name);
|
||||
|
||||
LOG_M(output_file, sequence_name, primary_synchro_time, length, 1, 1);
|
||||
sprintf(output_file, "%s%d_%u%s","pss_seq_f_", N_ID_2, length, ".m");
|
||||
sprintf(sequence_name, "%s%d_%u","pss_seq_f_", N_ID_2, length);
|
||||
LOG_M(output_file, sequence_name, synchroF_tmp, length, 1, 1);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
#if 0
|
||||
|
||||
/* it allows checking that process of idft on a signal and then dft gives same signal with limited errors */
|
||||
|
||||
if ((N_ID_2 == 0) && (length == 256)) {
|
||||
|
||||
LOG_M("pss_f00.m","pss_f00",synchro_tmp,length,1,1);
|
||||
|
||||
|
||||
bzero(synchroF_tmp, size);
|
||||
|
||||
|
||||
|
||||
/* get pss in the time domain by applying an inverse FFT */
|
||||
dft((int16_t)get_dft(length),
|
||||
synchro_tmp, /* complex input */
|
||||
synchroF_tmp, /* complex output */
|
||||
1); /* scaling factor */
|
||||
|
||||
if ((N_ID_2 == 0) && (length == 256)) {
|
||||
LOG_M("pss_f_0.m","pss_f_0",synchroF_tmp,length,1,1);
|
||||
}
|
||||
|
||||
/* check Pss */
|
||||
k = length - (LENGTH_PSS_NR/2);
|
||||
|
||||
#define LIMIT_ERROR_FFT (10)
|
||||
|
||||
for (int i=0; i < LENGTH_PSS_NR; i++) {
|
||||
if (abs(synchroF_tmp[2*k] - primary_synchro[2*i]) > LIMIT_ERROR_FFT) {
|
||||
printf("Pss Error[%d] Compute %d Reference %d \n", k, synchroF_tmp[2*k], primary_synchro[2*i]);
|
||||
}
|
||||
|
||||
if (abs(synchroF_tmp[2*k+1] - primary_synchro[2*i+1]) > LIMIT_ERROR_FFT) {
|
||||
printf("Pss Error[%d] Compute %d Reference %d\n", (2*k+1), synchroF_tmp[2*k+1], primary_synchro[2*i+1]);
|
||||
}
|
||||
|
||||
k++;
|
||||
|
||||
if (k >= length) {
|
||||
k-=length;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/*******************************************************************
|
||||
@@ -259,60 +151,47 @@ void generate_pss_nr(NR_DL_FRAME_PARMS *fp,int N_ID_2)
|
||||
|
||||
void init_context_pss_nr(NR_DL_FRAME_PARMS *frame_parms_ue)
|
||||
{
|
||||
int ofdm_symbol_size = frame_parms_ue->ofdm_symbol_size;
|
||||
int sizePss = LENGTH_PSS_NR * IQ_SIZE; /* complex value i & q signed 16 bits */
|
||||
int size = ofdm_symbol_size * IQ_SIZE; /* i and q samples signed 16 bits */
|
||||
int16_t *p = NULL;
|
||||
|
||||
AssertFatal(ofdm_symbol_size > 127, "illegal ofdm_symbol_size %d\n",ofdm_symbol_size);
|
||||
for (int i = 0; i < NUMBER_PSS_SEQUENCE; i++) {
|
||||
|
||||
p = malloc16(sizePss); /* pss in complex with alternatively i then q */
|
||||
LOG_I(NR_PHY,"Calling init_context_pss_nr\n");
|
||||
AssertFatal(frame_parms_ue->ofdm_symbol_size > 127, "illegal frame_parms_ue->ofdm_symbol_size %d\n",
|
||||
frame_parms_ue->ofdm_symbol_size);
|
||||
c16_t *p = NULL;
|
||||
int pss_sequence = get_softmodem_params()->sl_mode == 0 ? NUMBER_PSS_SEQUENCE : NUMBER_PSS_SEQUENCE_SL;
|
||||
c16_t txdataF[3*4096];
|
||||
for (int i = 0; i < pss_sequence; i++) {
|
||||
LOG_I(NR_PHY,"Initializing PSS %d\n",i);
|
||||
p = malloc(LENGTH_PSS_NR * sizeof(c16_t));
|
||||
if (p != NULL) {
|
||||
primary_synchro_nr[i] = p;
|
||||
bzero( primary_synchro_nr[i], sizePss);
|
||||
}
|
||||
else {
|
||||
bzero(primary_synchro_nr[i], LENGTH_PSS_NR * sizeof(c16_t));
|
||||
} else {
|
||||
LOG_E(PHY,"Fatal memory allocation problem \n");
|
||||
assert(0);
|
||||
}
|
||||
p = malloc(LENGTH_PSS_NR*2);
|
||||
p = malloc(LENGTH_PSS_NR * sizeof(c16_t));
|
||||
if (p != NULL) {
|
||||
primary_synchro_nr2[i] = p;
|
||||
bzero( primary_synchro_nr2[i],LENGTH_PSS_NR*2);
|
||||
bzero(primary_synchro_nr2[i], LENGTH_PSS_NR * sizeof(c16_t));
|
||||
} else {
|
||||
LOG_E(PHY,"Fatal memory allocation problem \n");
|
||||
assert(0);
|
||||
}
|
||||
p = malloc16(size);
|
||||
p = malloc(sizeof(c16_t) * frame_parms_ue->ofdm_symbol_size);
|
||||
if (p != NULL) {
|
||||
primary_synchro_time_nr[i] = p;
|
||||
bzero( primary_synchro_time_nr[i], size);
|
||||
}
|
||||
else {
|
||||
bzero(primary_synchro_time_nr[i], sizeof(c16_t) * frame_parms_ue->ofdm_symbol_size);
|
||||
} else {
|
||||
LOG_E(PHY,"Fatal memory allocation problem \n");
|
||||
assert(0);
|
||||
}
|
||||
|
||||
generate_pss_nr(frame_parms_ue,i);
|
||||
}
|
||||
}
|
||||
|
||||
/*******************************************************************
|
||||
*
|
||||
* NAME : free_context_pss_nr
|
||||
*
|
||||
* PARAMETERS : none
|
||||
*
|
||||
* RETURN : none
|
||||
*
|
||||
* DESCRIPTION : free context related to pss
|
||||
*
|
||||
*********************************************************************/
|
||||
|
||||
void free_context_pss_nr(void)
|
||||
{
|
||||
for (int i = 0; i < NUMBER_PSS_SEQUENCE; i++) {
|
||||
free_and_zero(primary_synchro_nr[i]);
|
||||
free_and_zero(primary_synchro_nr2[i]);
|
||||
free_and_zero(primary_synchro_time_nr[i]);
|
||||
if (get_softmodem_params()->sl_mode==0 || get_softmodem_params()->sync_ref) generate_pss_nr(frame_parms_ue, i, pss_sequence);
|
||||
else {
|
||||
int tmp=frame_parms_ue->Nid_SL;
|
||||
frame_parms_ue->Nid_SL = 336*i;
|
||||
nr_sl_generate_pss(txdataF,AMP,0,frame_parms_ue);
|
||||
frame_parms_ue->Nid_SL = tmp;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -330,25 +209,7 @@ void free_context_pss_nr(void)
|
||||
|
||||
void init_context_synchro_nr(NR_DL_FRAME_PARMS *frame_parms_ue)
|
||||
{
|
||||
#ifndef STATIC_SYNC_BUFFER
|
||||
|
||||
/* initialise global buffers for synchronisation */
|
||||
synchroF_tmp = malloc16(SYNCF_TMP_SIZE);
|
||||
if (synchroF_tmp == NULL) {
|
||||
LOG_E(PHY,"Fatal memory allocation problem \n");
|
||||
assert(0);
|
||||
}
|
||||
|
||||
synchro_tmp = malloc16(SYNC_TMP_SIZE);
|
||||
if (synchro_tmp == NULL) {
|
||||
LOG_E(PHY,"Fatal memory allocation problem \n");
|
||||
assert(0);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
init_context_pss_nr(frame_parms_ue);
|
||||
|
||||
init_context_sss_nr(AMP);
|
||||
}
|
||||
|
||||
@@ -366,29 +227,11 @@ void init_context_synchro_nr(NR_DL_FRAME_PARMS *frame_parms_ue)
|
||||
|
||||
void free_context_synchro_nr(void)
|
||||
{
|
||||
#ifndef STATIC_SYNC_BUFFER
|
||||
|
||||
if (synchroF_tmp != NULL) {
|
||||
free(synchroF_tmp);
|
||||
synchroF_tmp = NULL;
|
||||
for (int i = 0; i < NUMBER_PSS_SEQUENCE; i++) {
|
||||
free_and_zero(primary_synchro_nr[i]);
|
||||
free_and_zero(primary_synchro_nr2[i]);
|
||||
free_and_zero(primary_synchro_time_nr[i]);
|
||||
}
|
||||
else {
|
||||
LOG_E(PHY,"Fatal memory deallocation problem \n");
|
||||
assert(0);
|
||||
}
|
||||
|
||||
if (synchro_tmp != NULL) {
|
||||
free(synchro_tmp);
|
||||
synchro_tmp = NULL;
|
||||
}
|
||||
else {
|
||||
LOG_E(PHY,"Fatal memory deallocation problem \n");
|
||||
assert(0);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
free_context_pss_nr();
|
||||
}
|
||||
|
||||
/*******************************************************************
|
||||
@@ -408,42 +251,10 @@ void set_frame_context_pss_nr(NR_DL_FRAME_PARMS *frame_parms_ue, int rate_change
|
||||
/* set new value according to rate_change */
|
||||
frame_parms_ue->ofdm_symbol_size = (frame_parms_ue->ofdm_symbol_size / rate_change);
|
||||
frame_parms_ue->samples_per_subframe = (frame_parms_ue->samples_per_subframe / rate_change);
|
||||
|
||||
free_context_pss_nr();
|
||||
|
||||
/* pss reference have to be rebuild with new parameters ie ofdm symbol size */
|
||||
init_context_synchro_nr(frame_parms_ue);
|
||||
|
||||
#ifdef SYNCHRO_DECIMAT
|
||||
set_pss_nr(frame_parms_ue->ofdm_symbol_size);
|
||||
#endif
|
||||
init_context_pss_nr(frame_parms_ue);
|
||||
init_context_sss_nr(AMP);
|
||||
}
|
||||
|
||||
/*******************************************************************
|
||||
*
|
||||
* NAME : restore_frame_context_pss_nr
|
||||
*
|
||||
* PARAMETERS : configuration for UE and eNB with new FFT size
|
||||
*
|
||||
* RETURN : 0 if OK else error
|
||||
*
|
||||
* DESCRIPTION : initialisation of UE and eNode contexts
|
||||
*
|
||||
*********************************************************************/
|
||||
|
||||
void restore_frame_context_pss_nr(NR_DL_FRAME_PARMS *frame_parms_ue, int rate_change)
|
||||
{
|
||||
frame_parms_ue->ofdm_symbol_size = frame_parms_ue->ofdm_symbol_size * rate_change;
|
||||
frame_parms_ue->samples_per_subframe = frame_parms_ue->samples_per_subframe * rate_change;
|
||||
|
||||
free_context_pss_nr();
|
||||
|
||||
/* pss reference have to be rebuild with new parameters ie ofdm symbol size */
|
||||
init_context_synchro_nr(frame_parms_ue);
|
||||
#ifdef SYNCHRO_DECIMAT
|
||||
set_pss_nr(frame_parms_ue->ofdm_symbol_size);
|
||||
#endif
|
||||
}
|
||||
|
||||
/********************************************************************
|
||||
*
|
||||
@@ -555,9 +366,7 @@ int pss_synchro_nr(PHY_VARS_NR_UE *PHY_vars_UE, int is, int rate_change)
|
||||
#endif
|
||||
|
||||
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PSS_SEARCH_TIME_NR, VCD_FUNCTION_IN);
|
||||
|
||||
synchro_position = pss_search_time_nr(rxdata, PHY_vars_UE, fo_flag, is);
|
||||
|
||||
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PSS_SEARCH_TIME_NR, VCD_FUNCTION_OUT);
|
||||
|
||||
#if TEST_SYNCHRO_TIMING_PSS
|
||||
@@ -650,133 +459,109 @@ int pss_synchro_nr(PHY_VARS_NR_UE *PHY_vars_UE, int is, int rate_change)
|
||||
int pss_search_time_nr(c16_t **rxdata, PHY_VARS_NR_UE *ue, int fo_flag, int is)
|
||||
{
|
||||
NR_DL_FRAME_PARMS *frame_parms = &ue->frame_parms;
|
||||
int *eNB_id = (int *)&ue->common_vars.eNb_id;
|
||||
int *f_off = (int *)&ue->common_vars.freq_offset;
|
||||
unsigned int n, ar, peak_position, pss_source;
|
||||
int64_t peak_value;
|
||||
int64_t avg[NUMBER_PSS_SEQUENCE] = {0};
|
||||
double ffo_est = 0;
|
||||
unsigned int length = is == 0 ? frame_parms->samples_per_frame + (2 * frame_parms->ofdm_symbol_size) :
|
||||
frame_parms->samples_per_frame;
|
||||
AssertFatal(length > 0, "illegal length %d\n", length);
|
||||
|
||||
// performing the correlation on a frame length plus one symbol for the first of the two frame
|
||||
// to take into account the possibility of PSS in between the two frames
|
||||
unsigned int length;
|
||||
if (is==0)
|
||||
length = frame_parms->samples_per_frame + (2*frame_parms->ofdm_symbol_size);
|
||||
else
|
||||
length = frame_parms->samples_per_frame;
|
||||
|
||||
|
||||
AssertFatal(length>0,"illegal length %d\n",length);
|
||||
peak_value = 0;
|
||||
peak_position = 0;
|
||||
pss_source = 0;
|
||||
|
||||
int maxval=0;
|
||||
for (int i=0;i<2*(frame_parms->ofdm_symbol_size);i++) {
|
||||
maxval = max(maxval,primary_synchro_time_nr[0][i]);
|
||||
maxval = max(maxval,-primary_synchro_time_nr[0][i]);
|
||||
maxval = max(maxval,primary_synchro_time_nr[1][i]);
|
||||
maxval = max(maxval,-primary_synchro_time_nr[1][i]);
|
||||
maxval = max(maxval,primary_synchro_time_nr[2][i]);
|
||||
maxval = max(maxval,-primary_synchro_time_nr[2][i]);
|
||||
int maxval = 0;
|
||||
for (int i = 0; i < frame_parms->ofdm_symbol_size; i++) {
|
||||
maxval = max(maxval, primary_synchro_time_nr[0][i].r);
|
||||
maxval = max(maxval, primary_synchro_time_nr[0][i].i);
|
||||
maxval = max(maxval, -primary_synchro_time_nr[0][i].r);
|
||||
maxval = max(maxval, -primary_synchro_time_nr[0][i].i);
|
||||
maxval = max(maxval, primary_synchro_time_nr[1][i].r);
|
||||
maxval = max(maxval, primary_synchro_time_nr[1][i].i);
|
||||
maxval = max(maxval, -primary_synchro_time_nr[1][i].r);
|
||||
maxval = max(maxval, -primary_synchro_time_nr[1][i].i);
|
||||
if (get_softmodem_params()->sl_mode == 0) {
|
||||
maxval = max(maxval, primary_synchro_time_nr[2][i].r);
|
||||
maxval = max(maxval, primary_synchro_time_nr[2][i].i);
|
||||
maxval = max(maxval, -primary_synchro_time_nr[2][i].r);
|
||||
maxval = max(maxval, -primary_synchro_time_nr[2][i].i);
|
||||
}
|
||||
}
|
||||
int shift = log2_approx(maxval);//*(frame_parms->ofdm_symbol_size+frame_parms->nb_prefix_samples)*2);
|
||||
|
||||
int avg_size = get_softmodem_params()->sl_mode == 0 ? NUMBER_PSS_SEQUENCE : NUMBER_PSS_SEQUENCE_SL;
|
||||
int64_t avg[avg_size];
|
||||
bzero(avg, avg_size);
|
||||
|
||||
int shift = log2_approx(maxval);
|
||||
int64_t peak_value = 0;
|
||||
unsigned int peak_position = 0;
|
||||
unsigned int pss_source = 0;
|
||||
/* Search pss in the received buffer each 4 samples which ensures a memory alignment on 128 bits (32 bits x 4 ) */
|
||||
/* This is required by SIMD (single instruction Multiple Data) Extensions of Intel processors. */
|
||||
/* Correlation computation is based on a a dot product which is realized thank to SIMS extensions */
|
||||
|
||||
uint16_t pss_index_start = 0;
|
||||
uint16_t pss_index_end = NUMBER_PSS_SEQUENCE;
|
||||
uint16_t pss_index_end = get_softmodem_params()->sl_mode == 0 ? NUMBER_PSS_SEQUENCE : NUMBER_PSS_SEQUENCE_SL;
|
||||
if (ue->target_Nid_cell != -1) {
|
||||
pss_index_start = GET_NID2(ue->target_Nid_cell);
|
||||
pss_index_end = pss_index_start + 1;
|
||||
}
|
||||
|
||||
unsigned int step = get_softmodem_params()->sl_mode == 0 ? 8 : 4;
|
||||
for (int pss_index = pss_index_start; pss_index < pss_index_end; pss_index++) {
|
||||
for (n = 0; n < length; n += 8) { //
|
||||
|
||||
int64_t pss_corr_ue=0;
|
||||
/* calculate dot product of primary_synchro_time_nr and rxdata[ar][n]
|
||||
* (ar=0..nb_ant_rx) and store the sum in temp[n]; */
|
||||
for (ar=0; ar<frame_parms->nb_antennas_rx; ar++) {
|
||||
|
||||
for (unsigned int n = 0; n < length; n += step) {
|
||||
int64_t pss_corr_ue = 0;
|
||||
for (unsigned int ar = 0; ar < frame_parms->nb_antennas_rx; ar++) {
|
||||
/* perform correlation of rx data and pss sequence ie it is a dot product */
|
||||
const c32_t result = dot_product((c16_t *)primary_synchro_time_nr[pss_index], &(rxdata[ar][n + is * frame_parms->samples_per_frame]), frame_parms->ofdm_symbol_size, shift);
|
||||
const c32_t result = dot_product(primary_synchro_time_nr[pss_index],
|
||||
&(rxdata[ar][n + is * frame_parms->samples_per_frame]),
|
||||
frame_parms->ofdm_symbol_size,
|
||||
shift);
|
||||
const c64_t r64 = {.r = result.r, .i = result.i};
|
||||
pss_corr_ue += squaredMod(r64);
|
||||
//((short*)pss_corr_ue[pss_index])[2*n] += ((short*) &result)[0]; /* real part */
|
||||
//((short*)pss_corr_ue[pss_index])[2*n+1] += ((short*) &result)[1]; /* imaginary part */
|
||||
//((short*)&synchro_out)[0] += ((int*) &result)[0]; /* real part */
|
||||
//((short*)&synchro_out)[1] += ((int*) &result)[1]; /* imaginary part */
|
||||
|
||||
if (get_softmodem_params()->sl_mode > 0) {
|
||||
//non-coherentely combine repeition of PSS
|
||||
const c32_t result = dot_product(primary_synchro_time_nr[pss_index],
|
||||
&(rxdata[ar][n + is * frame_parms->samples_per_frame + frame_parms->ofdm_symbol_size+frame_parms->nb_prefix_samples]),
|
||||
frame_parms->ofdm_symbol_size,
|
||||
shift);
|
||||
const c64_t r64 = {.r = result.r, .i = result.i};
|
||||
pss_corr_ue += squaredMod(r64);
|
||||
}
|
||||
}
|
||||
|
||||
/* calculate the absolute value of sync_corr[n] */
|
||||
avg[pss_index]+=pss_corr_ue;
|
||||
if (pss_corr_ue > peak_value) {
|
||||
peak_value = pss_corr_ue;
|
||||
peak_position = n;
|
||||
pss_source = pss_index;
|
||||
|
||||
#ifdef DEBUG_PSS_NR
|
||||
printf("pss_index %d: n %6u peak_value %15llu\n", pss_index, n, (unsigned long long)pss_corr_ue[n]);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (fo_flag){
|
||||
|
||||
double ffo_est = 0;
|
||||
if (fo_flag) {
|
||||
// fractional frequency offset computation according to Cross-correlation Synchronization Algorithm Using PSS
|
||||
// Shoujun Huang, Yongtao Su, Ying He and Shan Tang, "Joint time and frequency offset estimation in LTE downlink," 7th International Conference on Communications and Networking in China, 2012.
|
||||
|
||||
// Computing cross-correlation at peak on half the symbol size for first half of data
|
||||
c32_t r1 = dot_product((c16_t *)primary_synchro_time_nr[pss_source], &(rxdata[0][peak_position + is * frame_parms->samples_per_frame]), frame_parms->ofdm_symbol_size >> 1, shift);
|
||||
c32_t r1 = dot_product(primary_synchro_time_nr[pss_source],
|
||||
&(rxdata[0][peak_position + is * frame_parms->samples_per_frame]),
|
||||
frame_parms->ofdm_symbol_size >> 1,
|
||||
shift);
|
||||
// Computing cross-correlation at peak on half the symbol size for data shifted by half symbol size
|
||||
// as it is real and complex it is necessary to shift by a value equal to symbol size to obtain such shift
|
||||
c32_t r2 = dot_product((c16_t *)primary_synchro_time_nr[pss_source] + (frame_parms->ofdm_symbol_size >> 1),
|
||||
c32_t r2 = dot_product(primary_synchro_time_nr[pss_source] + (frame_parms->ofdm_symbol_size >> 1),
|
||||
&(rxdata[0][peak_position + is * frame_parms->samples_per_frame]) + (frame_parms->ofdm_symbol_size >> 1),
|
||||
frame_parms->ofdm_symbol_size >> 1,
|
||||
shift);
|
||||
cd_t r1d = {r1.r, r1.i}, r2d = {r2.r, r2.i};
|
||||
// estimation of fractional frequency offset: angle[(result1)'*(result2)]/pi
|
||||
ffo_est = atan2(r1d.r * r2d.i - r2d.r * r1d.i, r1d.r * r2d.r + r1d.i * r2d.i) / M_PI;
|
||||
|
||||
#ifdef DBG_PSS_NR
|
||||
printf("ffo %lf\n",ffo_est);
|
||||
#endif
|
||||
}
|
||||
|
||||
// computing absolute value of frequency offset
|
||||
*f_off = ffo_est*frame_parms->subcarrier_spacing;
|
||||
ue->common_vars.freq_offset = ffo_est * frame_parms->subcarrier_spacing;
|
||||
int *id = get_softmodem_params()->sl_mode == 0 ? (int *)&ue->common_vars.eNb_id : (int *)&ue->common_vars.N2_id;
|
||||
*id = pss_source;
|
||||
|
||||
for (int pss_index = pss_index_start; pss_index < pss_index_end; pss_index++)
|
||||
avg[pss_index] /= (length / 4);
|
||||
|
||||
*eNB_id = pss_source;
|
||||
LOG_I(NR_PHY, "[UE] nr_synchro_time: Sync source = %d, Peak found at pos %d, val = %llu (%d dB) avg %d dB, ffo %lf\n",
|
||||
pss_source, peak_position, (unsigned long long)peak_value, dB_fixed64(peak_value), dB_fixed64(avg[pss_source]), ffo_est);
|
||||
|
||||
LOG_I(PHY,"[UE] nr_synchro_time: Sync source = %d, Peak found at pos %d, val = %llu (%d dB) avg %d dB, ffo %lf\n", pss_source, peak_position, (unsigned long long)peak_value, dB_fixed64(peak_value),dB_fixed64(avg[pss_source]),ffo_est);
|
||||
|
||||
if (peak_value < 5*avg[pss_source])
|
||||
if (peak_value < 5 * avg[pss_source])
|
||||
return(-1);
|
||||
|
||||
|
||||
#ifdef DBG_PSS_NR
|
||||
|
||||
static int debug_cnt = 0;
|
||||
|
||||
if (debug_cnt == 0) {
|
||||
if (is)
|
||||
LOG_M("rxdata1.m","rxd0",rxdata[frame_parms->samples_per_frame],length,1,1);
|
||||
else
|
||||
LOG_M("rxdata0.m","rxd0",rxdata[0],length,1,1);
|
||||
} else {
|
||||
debug_cnt++;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
return peak_position;
|
||||
return(peak_position);
|
||||
}
|
||||
|
||||
|
||||
127
openair1/PHY/NR_UE_TRANSPORT/pss_nr_sl.c
Normal file
127
openair1/PHY/NR_UE_TRANSPORT/pss_nr_sl.c
Normal file
@@ -0,0 +1,127 @@
|
||||
/*
|
||||
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The OpenAirInterface Software Alliance licenses this file to You under
|
||||
* the OAI Public License, Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.openairinterface.org/?page_id=698
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*-------------------------------------------------------------------------------
|
||||
* For more information about the OpenAirInterface (OAI) Software Alliance:
|
||||
* contact@openairinterface.org
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
#include <math.h>
|
||||
#include <nr-uesoftmodem.h>
|
||||
|
||||
#include "PHY/defs_nr_UE.h"
|
||||
#include "PHY/phy_extern.h"
|
||||
#include "PHY/NR_UE_TRANSPORT/nr_transport_proto_ue.h"
|
||||
#include "PHY/NR_REFSIG/ss_pbch_nr.h"
|
||||
#include "openair1/PHY/NR_REFSIG/pss_nr.h"
|
||||
|
||||
int nr_sl_generate_pss(c16_t *txdataF,
|
||||
int16_t amp,
|
||||
uint8_t ssb_start_symbol,
|
||||
NR_DL_FRAME_PARMS *frame_parms)
|
||||
{
|
||||
const int x_initial[INITIAL_PSS_NR] = {0, 1, 1, 0, 1, 1, 1};
|
||||
int16_t x[LENGTH_PSS_NR];
|
||||
for (int i = 0; i < INITIAL_PSS_NR; i++)
|
||||
x[i] = x_initial[i];
|
||||
|
||||
for (int i = 0; i < (LENGTH_PSS_NR - INITIAL_PSS_NR); i++)
|
||||
x[i + INITIAL_PSS_NR] = (x[i + 4] + x[i]) % (2);
|
||||
|
||||
#ifdef NR_PSS_DEBUG
|
||||
write_output("d_pss.m", "d_pss", (void*)d_pss, NR_PSS_LENGTH, 1, 0);
|
||||
printf("PSS: ofdm_symbol_size %d, first_carrier_offset %d\n",frame_parms->ofdm_symbol_size,frame_parms->first_carrier_offset);
|
||||
#endif
|
||||
|
||||
/// Resource mapping
|
||||
uint8_t Nid2 = frame_parms->Nid_SL / 336;
|
||||
int16_t d_pss[LENGTH_PSS_NR];
|
||||
c16_t *primary_synchro = primary_synchro_nr[Nid2];
|
||||
c16_t *primary_synchro2 = primary_synchro_nr2[Nid2];
|
||||
|
||||
// PSS occupies a predefined position (subcarriers 2-128, symbol 0) within the SSB block starting from
|
||||
int k = frame_parms->first_carrier_offset + frame_parms->ssb_start_subcarrier + PSS_SSS_SUB_CARRIER_START_SL;
|
||||
if (k >= frame_parms->ofdm_symbol_size) k -= frame_parms->ofdm_symbol_size;
|
||||
|
||||
int l = ssb_start_symbol + 1;
|
||||
for (int i = 0; i < NR_PSS_LENGTH; i++) {
|
||||
int m = (i + 22 + 43 * Nid2) % (NR_PSS_LENGTH);
|
||||
d_pss[i] = (1 - 2 * x[m]) * 23170;
|
||||
txdataF[(l * frame_parms->ofdm_symbol_size + k)].r = (((int16_t)amp) * d_pss[i]) >> 15;
|
||||
txdataF[(l * frame_parms->ofdm_symbol_size + k)].i = 0;
|
||||
primary_synchro[i].r = (d_pss[i] * SHRT_MAX) >> SCALING_PSS_NR;
|
||||
primary_synchro[i].i = 0;
|
||||
primary_synchro2[i].r = d_pss[i];
|
||||
primary_synchro2[i].i = d_pss[i];
|
||||
k++;
|
||||
|
||||
if (k >= frame_parms->ofdm_symbol_size)
|
||||
k-=frame_parms->ofdm_symbol_size;
|
||||
}
|
||||
|
||||
// PSS occupies a predefined position (subcarriers 2-128, symbol 0) within the SSB block starting from
|
||||
k = frame_parms->first_carrier_offset + frame_parms->ssb_start_subcarrier + PSS_SSS_SUB_CARRIER_START_SL;
|
||||
if (k >= frame_parms->ofdm_symbol_size) k-=frame_parms->ofdm_symbol_size;
|
||||
|
||||
l = ssb_start_symbol + 2;
|
||||
|
||||
for (int i = 0; i < NR_PSS_LENGTH; i++) {
|
||||
int m = (i + 22 + 43 * Nid2) % (NR_PSS_LENGTH);
|
||||
d_pss[i] = (1 - 2 * x[m]) * 23170;
|
||||
// printf("pss: writing position k %d / %d\n",k,frame_parms->ofdm_symbol_size);
|
||||
txdataF[(l * frame_parms->ofdm_symbol_size + k)].r = (((int16_t)amp) * d_pss[i]) >> 15;
|
||||
txdataF[(l * frame_parms->ofdm_symbol_size + k)].i = 0;
|
||||
k++;
|
||||
|
||||
if (k >= frame_parms->ofdm_symbol_size)
|
||||
k-=frame_parms->ofdm_symbol_size;
|
||||
}
|
||||
|
||||
#ifdef NR_PSS_DEBUG
|
||||
LOG_M("pss_0.m", "pss_0",
|
||||
(void*)&txdataF[0][ssb_start_symbol*frame_parms->ofdm_symbol_size],
|
||||
frame_parms->ofdm_symbol_size, 1, 1);
|
||||
char buffer[frame_parms->ofdm_symbol_size];
|
||||
for (int i = 1; i < 3; i++) {
|
||||
bzero(buffer, sizeof(buffer));
|
||||
LOG_I(NR_PHY, "PSS %d = %s\n", i, hexdump(&txdataF[frame_parms->ofdm_symbol_size*i],
|
||||
frame_parms->ofdm_symbol_size, buffer, sizeof(buffer)));
|
||||
}
|
||||
#endif
|
||||
LOG_I(NR_PHY,"nr_sl_generate_pss : ssb_start_subcarrier %d, k %d\n",frame_parms->ssb_start_subcarrier,k);
|
||||
|
||||
k = frame_parms->first_carrier_offset + frame_parms->ssb_start_subcarrier + PSS_SSS_SUB_CARRIER_START_SL;
|
||||
if (k >= frame_parms->ofdm_symbol_size) k-=frame_parms->ofdm_symbol_size;
|
||||
c16_t in[sizeof(int16_t) * frame_parms->ofdm_symbol_size] __attribute__((aligned(32)));
|
||||
memset(in, 0, sizeof(in));
|
||||
for (int i = 0; i < LENGTH_PSS_NR; i++) {
|
||||
in[k]= primary_synchro[i];
|
||||
k++;
|
||||
if (k == frame_parms->ofdm_symbol_size) k = 0;
|
||||
}
|
||||
|
||||
c16_t out[sizeof(int16_t) * frame_parms->ofdm_symbol_size] __attribute__((aligned(32)));
|
||||
memset(out, 0, sizeof(out));
|
||||
memset(primary_synchro_time_nr[Nid2], 0, sizeof(int16_t) * frame_parms->ofdm_symbol_size);
|
||||
idft((int16_t)get_idft(frame_parms->ofdm_symbol_size), (int16_t *)in, (int16_t *)out, 1);
|
||||
for (unsigned int i = 0; i < frame_parms->ofdm_symbol_size; i++) {
|
||||
primary_synchro_time_nr[Nid2][i] = out[i];
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@@ -36,7 +36,7 @@
|
||||
|
||||
#include "PHY/defs_nr_UE.h"
|
||||
#include "PHY/MODULATION/modulation_UE.h"
|
||||
|
||||
#include "executables/softmodem-common.h"
|
||||
#include "PHY/NR_REFSIG/ss_pbch_nr.h"
|
||||
|
||||
#define DEFINE_VARIABLES_SSS_NR_H
|
||||
@@ -67,50 +67,32 @@ void init_context_sss_nr(int amp)
|
||||
{
|
||||
int16_t x0[LENGTH_SSS_NR];
|
||||
int16_t x1[LENGTH_SSS_NR];
|
||||
int16_t dss_current;
|
||||
int m0, m1;
|
||||
|
||||
const int x0_initial[INITIAL_SSS_NR] = { 1, 0, 0, 0, 0, 0, 0 };
|
||||
const int x1_initial[INITIAL_SSS_NR] = { 1, 0, 0, 0, 0, 0, 0 };
|
||||
|
||||
for (int i=0; i < INITIAL_SSS_NR; i++) {
|
||||
for (int i = 0; i < INITIAL_SSS_NR; i++) {
|
||||
x0[i] = x0_initial[i];
|
||||
x1[i] = x1_initial[i];
|
||||
}
|
||||
|
||||
for (int i=0; i < (LENGTH_SSS_NR - INITIAL_SSS_NR); i++) {
|
||||
x0[i+7] = (x0[i + 4] + x0[i])%(2);
|
||||
x1[i+7] = (x1[i + 1] + x1[i])%(2);
|
||||
for (int i = 0; i < (LENGTH_SSS_NR - INITIAL_SSS_NR); i++) {
|
||||
x0[i + 7] = (x0[i + 4] + x0[i]) % (2);
|
||||
x1[i + 7] = (x1[i + 1] + x1[i]) % (2);
|
||||
}
|
||||
|
||||
for (int N_ID_2 = 0; N_ID_2 < N_ID_2_NUMBER; N_ID_2++) {
|
||||
|
||||
int nid_2_num = get_softmodem_params()->sl_mode == 0 ? N_ID_2_NUMBER : N_ID_2_NUMBER_SL;
|
||||
int dss_current;
|
||||
int m0, m1;
|
||||
for (int N_ID_2 = 0; N_ID_2 < nid_2_num; N_ID_2++) {
|
||||
for (int N_ID_1 = 0; N_ID_1 < N_ID_1_NUMBER; N_ID_1++) {
|
||||
|
||||
m0 = 15*(N_ID_1/112) + (5*N_ID_2);
|
||||
m1 = N_ID_1%112;
|
||||
|
||||
m0 = 15 * (N_ID_1 / 112) + (5 * N_ID_2);
|
||||
m1 = N_ID_1 % 112;
|
||||
for (int n = 0; n < LENGTH_SSS_NR; n++) {
|
||||
|
||||
dss_current = (1 - 2*x0[(n + m0)%(LENGTH_SSS_NR)])*(1 - 2*x1[(n + m1)%(LENGTH_SSS_NR)]);
|
||||
|
||||
dss_current = (1 - 2 * x0 [(n + m0) % (LENGTH_SSS_NR)]) * (1 - 2 * x1[(n + m1) % (LENGTH_SSS_NR)]);
|
||||
/* Modulation of SSS is a BPSK TS 36.211 chapter 5.1.2 BPSK */
|
||||
#if 1
|
||||
d_sss[N_ID_2][N_ID_1][n] = dss_current;// * amp;
|
||||
(void) amp;
|
||||
#else
|
||||
(void) amp;
|
||||
d_sss[N_ID_2][N_ID_1][n] = (dss_current * SHRT_MAX)>>SCALING_PSS_NR;
|
||||
#endif
|
||||
d_sss[N_ID_2][N_ID_1][n] = dss_current;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#if 0
|
||||
for (int i = 0; i < LENGTH_SSS_NR; i++) {
|
||||
printf("sss ref[%i] : %d %d \n", i, d_sss[0][0][i], d_sss[0][0][i]);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/*******************************************************************
|
||||
@@ -129,18 +111,10 @@ void init_context_sss_nr(int amp)
|
||||
|
||||
//#define DEBUG_SSS_NR
|
||||
//#define DEBUG_PLOT_SSS
|
||||
void insert_sss_nr(int16_t *sss_time,
|
||||
void insert_sss_nr(c16_t *sss_time,
|
||||
NR_DL_FRAME_PARMS *frame_parms)
|
||||
{
|
||||
unsigned int ofdm_symbol_size = frame_parms->ofdm_symbol_size;
|
||||
unsigned int size = ofdm_symbol_size * IQ_SIZE; /* i & q */
|
||||
|
||||
assert(size <= SYNCF_TMP_SIZE);
|
||||
assert(size <= SYNC_TMP_SIZE);
|
||||
|
||||
bzero(synchroF_tmp, size);
|
||||
bzero(synchro_tmp, size);
|
||||
|
||||
int Nid2 = GET_NID2(frame_parms->Nid_cell);
|
||||
int Nid1 = GET_NID1(frame_parms->Nid_cell);
|
||||
|
||||
@@ -169,12 +143,12 @@ void insert_sss_nr(int16_t *sss_time,
|
||||
unsigned int k = ofdm_symbol_size - ((LENGTH_SSS_NR/2)+1);
|
||||
|
||||
/* SSS is directly mapped to subcarrier */
|
||||
for (int i=0; i<LENGTH_SSS_NR; i++) {
|
||||
synchroF_tmp[2*k] = d_sss[Nid2][Nid1][i];
|
||||
synchroF_tmp[2*k+1] = 0;
|
||||
|
||||
c16_t in[sizeof(int16_t) * ofdm_symbol_size] __attribute__((aligned(32)));
|
||||
memset(in, 0, sizeof(in));
|
||||
for (int i = 0; i < LENGTH_SSS_NR; i++) {
|
||||
in[i].r = d_sss[Nid2][Nid1][i];
|
||||
in[i].i = 0;
|
||||
k++;
|
||||
|
||||
if (k >= ofdm_symbol_size) {
|
||||
k++;
|
||||
k-=ofdm_symbol_size;
|
||||
@@ -182,13 +156,12 @@ void insert_sss_nr(int16_t *sss_time,
|
||||
}
|
||||
|
||||
/* get sss in the frequency domain by applying an inverse FFT */
|
||||
idft(IDFT_2048,synchroF_tmp, /* complex input */
|
||||
synchro_tmp, /* complex output */
|
||||
1); /* scaling factor */
|
||||
|
||||
/* then get final sss in time */
|
||||
for (unsigned int i=0; i<ofdm_symbol_size; i++) {
|
||||
((int32_t *)sss_time)[i] = ((int32_t *)synchro_tmp)[i];
|
||||
c16_t out[sizeof(int16_t) * ofdm_symbol_size] __attribute__((aligned(32)));
|
||||
memset(out, 0, sizeof(out));
|
||||
memset(sss_time, 0, sizeof(int16_t) * ofdm_symbol_size);
|
||||
idft(IDFT_2048, (int16_t *)&in, (int16_t *)&out, 1);
|
||||
for (unsigned int i = 0; i < ofdm_symbol_size; i++) {
|
||||
sss_time[i] = out[i];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -205,99 +178,35 @@ void insert_sss_nr(int16_t *sss_time,
|
||||
*********************************************************************/
|
||||
|
||||
int pss_ch_est_nr(PHY_VARS_NR_UE *ue,
|
||||
int32_t pss_ext[NB_ANTENNAS_RX][LENGTH_PSS_NR],
|
||||
int32_t sss_ext[NB_ANTENNAS_RX][LENGTH_SSS_NR])
|
||||
c16_t pss_ext[NB_ANTENNAS_RX][LENGTH_PSS_NR],
|
||||
c16_t sss_ext[NB_ANTENNAS_RX][LENGTH_SSS_NR])
|
||||
{
|
||||
int16_t *pss;
|
||||
int16_t *pss_ext2,*sss_ext2,*sss_ext3,tmp_re,tmp_im,tmp_re2,tmp_im2;
|
||||
uint8_t aarx,i;
|
||||
NR_DL_FRAME_PARMS *frame_parms = &ue->frame_parms;
|
||||
|
||||
pss = primary_synchro_nr2[ue->common_vars.eNb_id];
|
||||
|
||||
sss_ext3 = (int16_t*)&sss_ext[0][0];
|
||||
|
||||
#if 0
|
||||
int16_t chest[2*LENGTH_PSS_NR];
|
||||
#endif
|
||||
|
||||
for (aarx=0; aarx<frame_parms->nb_antennas_rx; aarx++) {
|
||||
|
||||
sss_ext2 = (int16_t*)&sss_ext[aarx][0];
|
||||
pss_ext2 = (int16_t*)&pss_ext[aarx][0];
|
||||
|
||||
|
||||
#if 0
|
||||
|
||||
int16_t *p = pss;
|
||||
|
||||
for (int i = 0; i < LENGTH_PSS_NR; i++) {
|
||||
printf(" pss ref [%d] %d %d at address %p\n", i, p[2*i], p[2*i+1], &p[2*i]);
|
||||
printf(" pss ext [%d] %d %d at address %p\n", i, pss_ext2[2*i], pss_ext2[2*i+1], &pss_ext2[2*i]);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#if 0
|
||||
|
||||
for (int i = 0; i < LENGTH_PSS_NR; i++) {
|
||||
printf(" sss ext 2 [%d] %d %d at address %p\n", i, sss_ext2[2*i], sss_ext2[2*i+1], &sss_ext2[2*i]);
|
||||
printf(" sss ref [%d] %d %d at address %p\n", i, d_sss[0][0][i], d_sss[0][0][i], &d_sss[0][0][i]);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
int32_t amp;
|
||||
int shift;
|
||||
for (i = 0; i < LENGTH_PSS_NR; i++) {
|
||||
|
||||
// This is H*(PSS) = R* \cdot PSS
|
||||
tmp_re = pss_ext2[i*2] * pss[i];
|
||||
tmp_im = -pss_ext2[i*2+1] * pss[i];
|
||||
|
||||
amp = (((int32_t)tmp_re)*tmp_re) + ((int32_t)tmp_im)*tmp_im;
|
||||
shift = log2_approx(amp)/2;
|
||||
#if 0
|
||||
printf("H*(%d,%d) : (%d,%d)\n",aarx,i,tmp_re,tmp_im);
|
||||
printf("pss(%d,%d) : (%d,%d)\n",aarx,i,pss[2*i],pss[2*i+1]);
|
||||
printf("pss_ext(%d,%d) : (%d,%d)\n",aarx,i,pss_ext2[2*i],pss_ext2[2*i+1]);
|
||||
if (aarx==0) {
|
||||
chest[i<<1]=tmp_re;
|
||||
chest[1+(i<<1)]=tmp_im;
|
||||
}
|
||||
#endif
|
||||
// This is R(SSS) \cdot H*(PSS)
|
||||
tmp_re2 = (int16_t)(((tmp_re * (int32_t)sss_ext2[i*2])>>shift) - ((tmp_im * (int32_t)sss_ext2[i*2+1]>>shift)));
|
||||
tmp_im2 = (int16_t)(((tmp_re * (int32_t)sss_ext2[i*2+1])>>shift) + ((tmp_im * (int32_t)sss_ext2[i*2]>>shift)));
|
||||
|
||||
// printf("SSSi(%d,%d) : (%d,%d)\n",aarx,i,sss_ext2[i<<1],sss_ext2[1+(i<<1)]);
|
||||
// printf("SSSo(%d,%d) : (%d,%d)\n",aarx,i,tmp_re2,tmp_im2);
|
||||
// MRC on RX antennas
|
||||
if (aarx==0) {
|
||||
sss_ext3[i<<1] = tmp_re2;
|
||||
sss_ext3[1+(i<<1)] = tmp_im2;
|
||||
int id = get_softmodem_params()->sl_mode == 0 ? ue->common_vars.eNb_id : ue->common_vars.N2_id;
|
||||
c16_t *pss = primary_synchro_nr2[id];
|
||||
c16_t tmp, tmp2;
|
||||
c16_t *sss_ext3 = &sss_ext[0][0];
|
||||
for (uint8_t aarx = 0; aarx < ue->frame_parms.nb_antennas_rx; aarx++) {
|
||||
c16_t *sss_ext2 = &sss_ext[aarx][0];
|
||||
c16_t *pss_ext2 = &pss_ext[aarx][0];
|
||||
int32_t amp;
|
||||
int shift;
|
||||
for (uint8_t i = 0; i < LENGTH_PSS_NR; i++) {
|
||||
tmp.r = pss_ext2[i].r * pss[i].r;
|
||||
tmp.i = -pss_ext2[i].i * pss[i].i;
|
||||
amp = (((int32_t)tmp.r) * tmp.r) + ((int32_t)tmp.i) * tmp.i;
|
||||
shift = log2_approx(amp) / 2;
|
||||
tmp2.r = (int16_t)(((tmp.r * (int32_t)sss_ext2[i].r) >> shift) - ((tmp.i * (int32_t)sss_ext2[i].i >> shift)));
|
||||
tmp2.i = (int16_t)(((tmp.r * (int32_t)sss_ext2[i].i) >> shift) + ((tmp.i * (int32_t)sss_ext2[i].r >> shift)));
|
||||
if (aarx == 0) {
|
||||
sss_ext3[i].r = tmp2.r;
|
||||
sss_ext3[i].i = tmp2.i;
|
||||
} else {
|
||||
sss_ext3[i<<1] += tmp_re2;
|
||||
sss_ext3[1+(i<<1)] += tmp_im2;
|
||||
sss_ext3[i].r += tmp2.r;
|
||||
sss_ext3[i].i += tmp2.i;
|
||||
}
|
||||
}
|
||||
}
|
||||
#if 0
|
||||
LOG_M("pssrx.m","pssrx",pss,LENGTH_PSS_NR,1,1);
|
||||
LOG_M("pss_ext.m","pssext",pss_ext2,LENGTH_PSS_NR,1,1);
|
||||
LOG_M("psschest.m","pssch",chest,LENGTH_PSS_NR,1,1);
|
||||
#endif
|
||||
#if 0
|
||||
|
||||
for (int i = 0; i < LENGTH_PSS_NR; i++) {
|
||||
printf(" sss ext 2 [%d] %d %d at address %p\n", i, sss_ext2[2*i], sss_ext2[2*i+1]);
|
||||
printf(" sss ref [%d] %d %d at address %p\n", i, d_sss[0][0][i], d_sss[0][0][i]);
|
||||
printf(" sss ext 3 [%d] %d %d at address %p\n", i, sss_ext3[2*i], sss_ext3[2*i+1]);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
// sss_ext now contains the compensated SSS
|
||||
return(0);
|
||||
}
|
||||
|
||||
@@ -315,97 +224,49 @@ int pss_ch_est_nr(PHY_VARS_NR_UE *ue,
|
||||
|
||||
int do_pss_sss_extract_nr(PHY_VARS_NR_UE *ue,
|
||||
UE_nr_rxtx_proc_t *proc,
|
||||
int32_t pss_ext[NB_ANTENNAS_RX][LENGTH_PSS_NR],
|
||||
int32_t sss_ext[NB_ANTENNAS_RX][LENGTH_SSS_NR],
|
||||
c16_t pss_ext[NB_ANTENNAS_RX][LENGTH_PSS_NR],
|
||||
c16_t sss_ext[NB_ANTENNAS_RX][LENGTH_SSS_NR],
|
||||
uint8_t doPss, uint8_t doSss,
|
||||
uint8_t subframe,
|
||||
c16_t rxdataF[][ue->frame_parms.samples_per_slot_wCP]) // add flag to indicate extracting only PSS, only SSS, or both
|
||||
{
|
||||
uint8_t aarx;
|
||||
int32_t *pss_rxF,*pss_rxF_ext;
|
||||
int32_t *sss_rxF,*sss_rxF_ext;
|
||||
uint8_t pss_symbol, sss_symbol;
|
||||
c16_t *pss_rxF,*pss_rxF_ext;
|
||||
c16_t *sss_rxF,*sss_rxF_ext;
|
||||
uint8_t pss_symbol = 0;
|
||||
uint8_t sss_symbol = get_softmodem_params()->sl_mode == 0 ?
|
||||
(SSS_SYMBOL_NB - PSS_SYMBOL_NB) :
|
||||
(SSS0_SL_SYMBOL_NB - PSS0_SL_SYMBOL_NB) ;
|
||||
NR_DL_FRAME_PARMS *frame_parms = &ue->frame_parms;
|
||||
|
||||
for (aarx=0; aarx<frame_parms->nb_antennas_rx; aarx++) {
|
||||
|
||||
pss_symbol = 0;
|
||||
sss_symbol = SSS_SYMBOL_NB-PSS_SYMBOL_NB;
|
||||
|
||||
unsigned int ofdm_symbol_size = frame_parms->ofdm_symbol_size;
|
||||
|
||||
pss_rxF = (int32_t *)&rxdataF[aarx][pss_symbol*ofdm_symbol_size];
|
||||
sss_rxF = (int32_t *)&rxdataF[aarx][sss_symbol*ofdm_symbol_size];
|
||||
|
||||
pss_rxF = &rxdataF[aarx][pss_symbol * frame_parms->ofdm_symbol_size];
|
||||
sss_rxF = &rxdataF[aarx][sss_symbol * frame_parms->ofdm_symbol_size];
|
||||
pss_rxF_ext = &pss_ext[aarx][0];
|
||||
sss_rxF_ext = &sss_ext[aarx][0];
|
||||
|
||||
unsigned int k = frame_parms->first_carrier_offset + frame_parms->ssb_start_subcarrier + 56;
|
||||
unsigned int k = frame_parms->first_carrier_offset +
|
||||
frame_parms->ssb_start_subcarrier +
|
||||
((get_softmodem_params()->sl_mode == 0) ?
|
||||
PSS_SSS_SUB_CARRIER_START :
|
||||
PSS_SSS_SUB_CARRIER_START_SL);
|
||||
|
||||
if (k>= frame_parms->ofdm_symbol_size) k-=frame_parms->ofdm_symbol_size;
|
||||
|
||||
for (int i=0; i < LENGTH_PSS_NR; i++) {
|
||||
if (doPss) {
|
||||
if (doPss) {
|
||||
pss_rxF_ext[i] = pss_rxF[k];
|
||||
}
|
||||
|
||||
if (doSss) {
|
||||
sss_rxF_ext[i] = sss_rxF[k];
|
||||
}
|
||||
|
||||
k++;
|
||||
|
||||
if (k == ofdm_symbol_size) k=0;
|
||||
|
||||
if (k == frame_parms->ofdm_symbol_size) k = 0;
|
||||
}
|
||||
}
|
||||
|
||||
#if 0
|
||||
|
||||
int16_t *p = (int16_t *)sss_rxF_ext;
|
||||
|
||||
for (int i = 0; i < LENGTH_PSS_NR; i++) {
|
||||
printf(" sss ext 2 [%d] %d %d at address %p\n", i, p[2*i], p[2*i+1], &p[2*i]);
|
||||
printf(" sss ref [%d] %d %d at address %p\n", i, d_sss[0][0][i], d_sss[0][0][i], &d_sss[0][0][i]);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#if 0
|
||||
|
||||
int16_t *p2 = (int16_t *)pss_rxF_ext;
|
||||
|
||||
for (int i = 0; i < LENGTH_PSS_NR; i++) {
|
||||
printf(" pss_rxF_ext [%d] %d %d at address %p\n", i, p2[2*i], p2[2*i+1], &p2[2*i]);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
/*******************************************************************
|
||||
*
|
||||
* NAME : pss_sss_extract_nr
|
||||
*
|
||||
* PARAMETERS : none
|
||||
*
|
||||
* RETURN : none
|
||||
*
|
||||
* DESCRIPTION :
|
||||
*
|
||||
*********************************************************************/
|
||||
|
||||
int pss_sss_extract_nr(PHY_VARS_NR_UE *phy_vars_ue,
|
||||
UE_nr_rxtx_proc_t *proc,
|
||||
int32_t pss_ext[NB_ANTENNAS_RX][LENGTH_PSS_NR],
|
||||
int32_t sss_ext[NB_ANTENNAS_RX][LENGTH_SSS_NR],
|
||||
uint8_t subframe,
|
||||
c16_t rxdataF[][phy_vars_ue->frame_parms.samples_per_slot_wCP])
|
||||
{
|
||||
return do_pss_sss_extract_nr(phy_vars_ue, proc, pss_ext, sss_ext, 1 /* doPss */, 1 /* doSss */, subframe, rxdataF);
|
||||
}
|
||||
|
||||
/*******************************************************************
|
||||
*
|
||||
* NAME : rx_sss_nr
|
||||
@@ -419,170 +280,63 @@ int pss_sss_extract_nr(PHY_VARS_NR_UE *phy_vars_ue,
|
||||
*
|
||||
*********************************************************************/
|
||||
|
||||
int rx_sss_nr(PHY_VARS_NR_UE *ue, UE_nr_rxtx_proc_t *proc, int32_t *tot_metric, uint8_t *phase_max, int *freq_offset_sss, c16_t rxdataF[][ue->frame_parms.samples_per_slot_wCP])
|
||||
int rx_sss_nr(PHY_VARS_NR_UE *ue,
|
||||
UE_nr_rxtx_proc_t *proc,
|
||||
int32_t *tot_metric,
|
||||
uint8_t *phase_max,
|
||||
int *freq_offset_sss,
|
||||
c16_t rxdataF[][ue->frame_parms.samples_per_slot_wCP])
|
||||
{
|
||||
uint8_t i;
|
||||
int32_t pss_ext[NB_ANTENNAS_RX][LENGTH_PSS_NR];
|
||||
int32_t sss_ext[NB_ANTENNAS_RX][LENGTH_SSS_NR];
|
||||
uint8_t Nid2 = GET_NID2(ue->common_vars.eNb_id);
|
||||
uint16_t Nid1;
|
||||
uint8_t phase;
|
||||
int16_t *sss;
|
||||
NR_DL_FRAME_PARMS *frame_parms=&ue->frame_parms;
|
||||
int32_t metric, metric_re;
|
||||
int16_t *d;
|
||||
c16_t pss_ext[NB_ANTENNAS_RX][LENGTH_PSS_NR];
|
||||
c16_t sss_ext[NB_ANTENNAS_RX][LENGTH_SSS_NR];
|
||||
do_pss_sss_extract_nr(ue, proc, pss_ext, sss_ext, 1 /* doPss */, 1 /* doSss */, 0 /* subframe */, rxdataF);
|
||||
pss_ch_est_nr(ue, pss_ext, sss_ext);
|
||||
|
||||
|
||||
// pss sss extraction
|
||||
pss_sss_extract_nr(ue,
|
||||
proc,
|
||||
pss_ext,
|
||||
sss_ext,
|
||||
0,
|
||||
rxdataF); /* subframe */
|
||||
|
||||
#ifdef DEBUG_PLOT_SSS
|
||||
|
||||
write_output("rxsig0.m","rxs0",&ue->common_vars.rxdata[0][0],ue->frame_parms.samples_per_subframe,1,1);
|
||||
write_output("rxdataF0_pss.m","rxF0_pss",&ue->common_vars.rxdataF[0][0],frame_parms->ofdm_symbol_size,1,1);
|
||||
write_output("rxdataF0_sss.m","rxF0_sss",&ue->common_vars.rxdataF[0][(SSS_SYMBOL_NB-PSS_SYMBOL_NB)*frame_parms->ofdm_symbol_size],frame_parms->ofdm_symbol_size,1,1);
|
||||
write_output("pss_ext.m","pss_ext",pss_ext,LENGTH_PSS_NR,1,1);
|
||||
|
||||
#endif
|
||||
|
||||
#if 0
|
||||
int16_t *p = (int16_t *)sss_ext[0];
|
||||
int16_t *p2 = (int16_t *)pss_ext[0];
|
||||
|
||||
for (int i = 0; i < LENGTH_SSS_NR; i++) {
|
||||
printf("sss ref [%i] : %d %d \n", i, d_sss[0][0][i], d_sss[0][0][i]);
|
||||
printf("sss ext [%i] : %d %d \n", i, p[2*i], p[2*i+1]);
|
||||
|
||||
printf("pss ref [%i] : %d %d \n", i, primary_synchro_nr2[0][2*i], primary_synchro_nr2[0][2*i+1]);
|
||||
printf("pss ext [%i] : %d %d \n", i, p2[2*i], p2[2*i+1]);
|
||||
}
|
||||
#endif
|
||||
|
||||
// get conjugated channel estimate from PSS, H* = R* \cdot PSS
|
||||
// and do channel estimation and compensation based on PSS
|
||||
|
||||
pss_ch_est_nr(ue,
|
||||
pss_ext,
|
||||
sss_ext);
|
||||
|
||||
// now do the SSS detection based on the precomputed sequences in PHY/LTE_TRANSPORT/sss.h
|
||||
*tot_metric = INT_MIN;
|
||||
|
||||
sss = (int16_t*)&sss_ext[0][0];
|
||||
|
||||
#ifdef DEBUG_PLOT_SSS
|
||||
|
||||
write_output("sss_ext.m","sss_ext",sss_ext[0],LENGTH_SSS_NR,1,1);
|
||||
write_output("sss_ref.m","sss_ref", d_sss,LENGTH_SSS_NR,1,1);
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
#if 0
|
||||
|
||||
/* simulate of a phase shift on the signal */
|
||||
|
||||
int phase_shift_index = 0;
|
||||
|
||||
phase_shift_samples(sss, LENGTH_SSS_NR, phase_re_nr[phase_shift_index], phase_im_nr[phase_shift_index]);
|
||||
|
||||
#endif
|
||||
|
||||
#if 0
|
||||
int16_t *ps = (int16_t *)pss_ext;
|
||||
|
||||
for (int i = 0; i < LENGTH_SSS_NR; i++) {
|
||||
printf("sss ref [%i] : %d \n", i, d_sss[0][0][i]);
|
||||
printf("sss ext [%i] : %d %d \n", i, sss[2*i], sss[2*i+1]);
|
||||
|
||||
printf("pss ref [%i] : %d %d \n", i, primary_synchro_nr2[0][2*i], primary_synchro_nr2[0][2*i+1]);
|
||||
printf("pss ext [%i] : %d %d \n", i, ps[2*i], ps[2*i+1]);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* for phase evaluation, one uses an array of possible phase shifts */
|
||||
/* then a correlation is done between received signal with a shift pĥase and the reference signal */
|
||||
/* Computation of signal with shift phase is based on below formula */
|
||||
/* cosinus cos(x + y) = cos(x)cos(y) - sin(x)sin(y) */
|
||||
/* sinus sin(x + y) = sin(x)cos(y) + cos(x)sin(y) */
|
||||
|
||||
uint16_t Nid1_start = 0;
|
||||
uint16_t Nid1_end = N_ID_1_NUMBER;
|
||||
if (ue->target_Nid_cell != -1) {
|
||||
Nid1_start = GET_NID1(ue->target_Nid_cell);
|
||||
Nid1_end = Nid1_start + 1;
|
||||
}
|
||||
|
||||
for (Nid1 = Nid1_start; Nid1 < Nid1_end; Nid1++) { // all possible Nid1 values
|
||||
for (phase = 0; phase < PHASE_HYPOTHESIS_NUMBER; phase++) { // phase offset between PSS and SSS
|
||||
|
||||
metric = 0;
|
||||
metric_re = 0;
|
||||
|
||||
c16_t *sss = &sss_ext[0][0];
|
||||
uint16_t Nid1;
|
||||
uint8_t Nid2 = get_softmodem_params()->sl_mode == 0 ? ue->common_vars.eNb_id : ue->common_vars.N2_id;
|
||||
int16_t *d;
|
||||
for (Nid1 = 0; Nid1 < N_ID_1_NUMBER; Nid1++) {
|
||||
for (uint8_t phase = 0; phase < PHASE_HYPOTHESIS_NUMBER; phase++) {
|
||||
int32_t metric = 0;
|
||||
int32_t metric_re = 0;
|
||||
d = (int16_t *)&d_sss[Nid2][Nid1];
|
||||
|
||||
// This is the inner product using one particular value of each unknown parameter
|
||||
for (i=0; i < LENGTH_SSS_NR; i++) {
|
||||
|
||||
metric_re += d[i]*(((phase_re_nr[phase]*sss[2*i])>>SCALING_METRIC_SSS_NR) - ((phase_im_nr[phase]*sss[2*i+1])>>SCALING_METRIC_SSS_NR));
|
||||
|
||||
#if 0
|
||||
printf("i %d, phase %d/%d: metric %d, phase (%d,%d) sss (%d,%d) d %d\n",i,phase,PHASE_HYPOTHESIS_NUMBER,metric_re,phase_re_nr[phase],phase_im_nr[phase],sss[2*i],sss[1+(2*i)],d[i]);
|
||||
#endif
|
||||
for (uint8_t i = 0; i < LENGTH_SSS_NR; i++) {
|
||||
metric_re += d[i] * (((phase_re_nr[phase] * sss[i].r) >> SCALING_METRIC_SSS_NR) - ((phase_im_nr[phase] * sss[i].i) >> SCALING_METRIC_SSS_NR));
|
||||
}
|
||||
|
||||
metric = metric_re;
|
||||
|
||||
// if the current metric is better than the last save it
|
||||
if (metric > *tot_metric) {
|
||||
*tot_metric = metric;
|
||||
ue->frame_parms.Nid_cell = Nid2+(3*Nid1);
|
||||
*phase_max = phase;
|
||||
|
||||
#ifdef DEBUG_SSS_NR
|
||||
|
||||
LOG_D(PHY,"(phase,Nid1) (%d,%d), metric_phase %d tot_metric %d, phase_max %d \n",phase, Nid1, metric, *tot_metric, *phase_max);
|
||||
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//#ifdef DEBUG_SSS_NR
|
||||
|
||||
#define SSS_METRIC_FLOOR_NR (30000)
|
||||
if (*tot_metric > SSS_METRIC_FLOOR_NR) {
|
||||
Nid2 = GET_NID2(frame_parms->Nid_cell);
|
||||
Nid1 = GET_NID1(frame_parms->Nid_cell);
|
||||
LOG_D(PHY,"Nid2 %d Nid1 %d tot_metric %d, phase_max %d \n", Nid2, Nid1, *tot_metric, *phase_max);
|
||||
if (*tot_metric > SSS_METRIC_FLOOR_NR) {
|
||||
Nid2 = GET_NID2(ue->frame_parms.Nid_cell);
|
||||
Nid1 = GET_NID1(ue->frame_parms.Nid_cell);
|
||||
LOG_I(NR_PHY,"Nid2 %d Nid1 %d tot_metric %d, phase_max %d \n", Nid2, Nid1, *tot_metric, *phase_max);
|
||||
}
|
||||
//#endif
|
||||
|
||||
if (Nid1==N_ID_1_NUMBER)
|
||||
if (Nid1 == N_ID_1_NUMBER) {
|
||||
LOG_I(NR_PHY,"Failed to detect SSS after PSS\n");
|
||||
return -1;
|
||||
|
||||
}
|
||||
|
||||
int re = 0;
|
||||
int im = 0;
|
||||
if (Nid1 == N_ID_1_NUMBER) {
|
||||
LOG_I(PHY,"Failed to detect SSS after PSS\n");
|
||||
return -1;
|
||||
for(int i = 0; i < LENGTH_SSS_NR; i++) {
|
||||
re += d[i] * sss[i].r;
|
||||
im += d[i] * sss[i].i;
|
||||
}
|
||||
d = (int16_t *)&d_sss[Nid2][Nid1];
|
||||
for(i = 0; i<LENGTH_SSS_NR; i++) {
|
||||
re += d[i]*sss[2*i];
|
||||
im += d[i]*sss[2*i+1];
|
||||
}
|
||||
double ffo_sss = atan2(im,re)/M_PI/4.3;
|
||||
*freq_offset_sss = (int)(ffo_sss*frame_parms->subcarrier_spacing);
|
||||
|
||||
double ffo_pss = ((double)ue->common_vars.freq_offset)/frame_parms->subcarrier_spacing;
|
||||
double ffo_sss = atan2(im,re)/M_PI/4.3;
|
||||
*freq_offset_sss = (int)(ffo_sss * ue->frame_parms.subcarrier_spacing);
|
||||
double ffo_pss = ((double)ue->common_vars.freq_offset)/ue->frame_parms.subcarrier_spacing;
|
||||
LOG_I(NR_PHY, "ffo_pss %f (%i Hz), ffo_sss %f (%i Hz), ffo_pss+ffo_sss %f (%i Hz)\n",
|
||||
ffo_pss, (int)(ffo_pss*frame_parms->subcarrier_spacing), ffo_sss, *freq_offset_sss, ffo_pss+ffo_sss, (int)((ffo_pss+ffo_sss)*frame_parms->subcarrier_spacing));
|
||||
ffo_pss, (int)(ffo_pss*ue->frame_parms.subcarrier_spacing), ffo_sss, *freq_offset_sss, ffo_pss+ffo_sss, (int)((ffo_pss+ffo_sss)*ue->frame_parms.subcarrier_spacing));
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
357
openair1/PHY/NR_UE_TRANSPORT/sss_nr_sl.c
Normal file
357
openair1/PHY/NR_UE_TRANSPORT/sss_nr_sl.c
Normal file
@@ -0,0 +1,357 @@
|
||||
/*
|
||||
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The OpenAirInterface Software Alliance licenses this file to You under
|
||||
* the OAI Public License, Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.openairinterface.org/?page_id=698
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*-------------------------------------------------------------------------------
|
||||
* For more information about the OpenAirInterface (OAI) Software Alliance:
|
||||
* contact@openairinterface.org
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
#include <math.h>
|
||||
#include <nr-uesoftmodem.h>
|
||||
|
||||
#include "PHY/defs_nr_UE.h"
|
||||
#include "PHY/phy_extern.h"
|
||||
#include "PHY/NR_UE_TRANSPORT/nr_transport_proto_ue.h"
|
||||
#include "PHY/NR_REFSIG/ss_pbch_nr.h"
|
||||
#include "PHY/NR_REFSIG/sss_nr.h"
|
||||
|
||||
//#define DEBUG_PLOT_SSS 1
|
||||
|
||||
int nr_sl_generate_sss(c16_t *txdataF,
|
||||
int16_t amp,
|
||||
uint8_t ssb_start_symbol,
|
||||
NR_DL_FRAME_PARMS *frame_parms)
|
||||
{
|
||||
int16_t x0[NR_SSS_LENGTH];
|
||||
int16_t x1[NR_SSS_LENGTH];
|
||||
const int x0_initial[7] = { 1, 0, 0, 0, 0, 0, 0 };
|
||||
const int x1_initial[7] = { 1, 0, 0, 0, 0, 0, 0 };
|
||||
|
||||
|
||||
|
||||
/// Sequence generation
|
||||
int Nid = frame_parms->Nid_SL;
|
||||
int Nid1 = GET_NID1_SL(Nid);
|
||||
int Nid2 = GET_NID2_SL(Nid);
|
||||
|
||||
for (int i=0; i < 7; i++) {
|
||||
x0[i] = x0_initial[i];
|
||||
x1[i] = x1_initial[i];
|
||||
}
|
||||
|
||||
for (int i=0; i < NR_SSS_LENGTH - 7; i++) {
|
||||
x0[i+7] = (x0[i + 4] + x0[i]) % 2;
|
||||
x1[i+7] = (x1[i + 1] + x1[i]) % 2;
|
||||
}
|
||||
|
||||
int m0 = 15 * (Nid1 / 112) + (5 * Nid2);
|
||||
int m1 = Nid1 % 112;
|
||||
|
||||
#ifdef NR_SSS_DEBUG
|
||||
write_output("d_sss.m", "d_sss", (void*)d_sss, NR_SSS_LENGTH, 1, 1);
|
||||
#endif
|
||||
|
||||
/// Resource mapping
|
||||
|
||||
// SSS occupies a predefined position (subcarriers 2-129, symbol 3) within the SSB block starting from
|
||||
int k = frame_parms->first_carrier_offset + frame_parms->ssb_start_subcarrier + PSS_SSS_SUB_CARRIER_START_SL;
|
||||
int l = ssb_start_symbol + 3;
|
||||
|
||||
for (int i = 0; i < NR_SSS_LENGTH; i++) {
|
||||
int16_t dss_current = (1 - 2 * x0[(i + m0) % NR_SSS_LENGTH] ) * (1 - 2 * x1[(i + m1) % NR_SSS_LENGTH] ) * 23170;
|
||||
d_sss[Nid2][Nid1][i] = dss_current;
|
||||
txdataF[(l * frame_parms->ofdm_symbol_size + k)].r = (((int16_t)amp) * dss_current) >> 15;
|
||||
txdataF[(l * frame_parms->ofdm_symbol_size + k)].i = 0;
|
||||
k++;
|
||||
|
||||
if (k >= frame_parms->ofdm_symbol_size)
|
||||
k-=frame_parms->ofdm_symbol_size;
|
||||
}
|
||||
|
||||
// SSS occupies a predefined position (subcarriers 2 to 129, symbol 4) within the SSB block starting from
|
||||
k = frame_parms->first_carrier_offset + frame_parms->ssb_start_subcarrier + PSS_SSS_SUB_CARRIER_START_SL;
|
||||
l = ssb_start_symbol + 4;
|
||||
|
||||
for (int i = 0; i < NR_SSS_LENGTH; i++) {
|
||||
int16_t dss_current = (1 - 2 * x0[(i + m0) % NR_SSS_LENGTH]) * (1 - 2 * x1[(i + m1) % NR_SSS_LENGTH] ) * 23170;
|
||||
d_sss[Nid2][Nid1][i] = dss_current;
|
||||
txdataF[(l*frame_parms->ofdm_symbol_size + k)].r = (((int16_t)amp) * dss_current) >> 15;
|
||||
txdataF[(l*frame_parms->ofdm_symbol_size + k)].i = 0;
|
||||
k++;
|
||||
|
||||
if (k >= frame_parms->ofdm_symbol_size)
|
||||
k-=frame_parms->ofdm_symbol_size;
|
||||
}
|
||||
#ifdef NR_SSS_DEBUG
|
||||
// write_output("sss_0.m", "sss_0", (void*)txdataF[0][l*frame_parms->ofdm_symbol_size], frame_parms->ofdm_symbol_size, 1, 1);
|
||||
char buffer[frame_parms->ofdm_symbol_size];
|
||||
for (int i = 3; i < 5; i++) {
|
||||
bzero(buffer, sizeof(buffer));
|
||||
LOG_I(NR_PHY, "SSS %d = %s\n", i, hexdump(&txdataF[frame_parms->ofdm_symbol_size*i],
|
||||
frame_parms->ofdm_symbol_size, buffer, sizeof(buffer)));
|
||||
}
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*******************************************************************
|
||||
*
|
||||
* NAME : pss_sss_sl_extract_nr
|
||||
*
|
||||
* PARAMETERS : none
|
||||
*
|
||||
* RETURN : none
|
||||
*
|
||||
* DESCRIPTION :
|
||||
*
|
||||
*********************************************************************/
|
||||
|
||||
static int pss_sss_sl_extract_nr(PHY_VARS_NR_UE *ue,
|
||||
UE_nr_rxtx_proc_t *proc,
|
||||
c16_t pss0_ext[NB_ANTENNAS_RX][LENGTH_PSS_NR],
|
||||
c16_t sss0_ext[NB_ANTENNAS_RX][LENGTH_SSS_NR],
|
||||
c16_t pss1_ext[NB_ANTENNAS_RX][LENGTH_PSS_NR],
|
||||
c16_t sss1_ext[NB_ANTENNAS_RX][LENGTH_SSS_NR])
|
||||
{
|
||||
c16_t **rxdataF = ue->common_vars.rxdataF;
|
||||
NR_DL_FRAME_PARMS *frame_parms = &ue->frame_parms;
|
||||
unsigned int ofdm_symbol_size = frame_parms->ofdm_symbol_size;
|
||||
|
||||
c16_t *pss0_rxF, *pss0_rxF_ext;
|
||||
c16_t *sss0_rxF, *sss0_rxF_ext;
|
||||
for (uint8_t aarx = 0; aarx < frame_parms->nb_antennas_rx; aarx++) {
|
||||
pss0_rxF = &rxdataF[aarx][PSS0_SL_SYMBOL_NB * ofdm_symbol_size];
|
||||
sss0_rxF = &rxdataF[aarx][SSS0_SL_SYMBOL_NB * ofdm_symbol_size];
|
||||
pss0_rxF_ext = &pss0_ext[aarx][0];
|
||||
sss0_rxF_ext = &sss0_ext[aarx][0];
|
||||
unsigned int k = frame_parms->first_carrier_offset + frame_parms->ssb_start_subcarrier + PSS_SSS_SUB_CARRIER_START_SL;
|
||||
if (k >= ofdm_symbol_size)
|
||||
k-=ofdm_symbol_size;
|
||||
|
||||
for (int i = 0; i < LENGTH_PSS_NR; i++) {
|
||||
pss0_rxF_ext[i] = pss0_rxF[k];
|
||||
sss0_rxF_ext[i] = sss0_rxF[k];
|
||||
k++;
|
||||
if (k == ofdm_symbol_size) k = 0;
|
||||
}
|
||||
}
|
||||
|
||||
c16_t *pss1_rxF, *pss1_rxF_ext;
|
||||
c16_t *sss1_rxF, *sss1_rxF_ext;
|
||||
for (uint8_t aarx = 0; aarx < frame_parms->nb_antennas_rx; aarx++) {
|
||||
pss1_rxF = &rxdataF[aarx][PSS1_SL_SYMBOL_NB * ofdm_symbol_size];
|
||||
sss1_rxF = &rxdataF[aarx][SSS1_SL_SYMBOL_NB * ofdm_symbol_size];
|
||||
pss1_rxF_ext = &pss1_ext[aarx][0];
|
||||
sss1_rxF_ext = &sss1_ext[aarx][0];
|
||||
unsigned int k = frame_parms->first_carrier_offset + frame_parms->ssb_start_subcarrier + PSS_SSS_SUB_CARRIER_START_SL;
|
||||
if (k >= frame_parms->ofdm_symbol_size)
|
||||
k-=frame_parms->ofdm_symbol_size;
|
||||
|
||||
for (int i=0; i < LENGTH_PSS_NR; i++) {
|
||||
pss1_rxF_ext[i] = pss1_rxF[k];
|
||||
sss1_rxF_ext[i] = sss1_rxF[k];
|
||||
k++;
|
||||
if (k == ofdm_symbol_size) k = 0;
|
||||
}
|
||||
}
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
|
||||
/*******************************************************************
|
||||
*
|
||||
* NAME : pss_ch_est
|
||||
*
|
||||
* PARAMETERS : none
|
||||
*
|
||||
* RETURN : none
|
||||
*
|
||||
* DESCRIPTION : pss channel estimation
|
||||
*
|
||||
*********************************************************************/
|
||||
|
||||
int pss_sl_ch_est_nr(PHY_VARS_NR_UE *ue,
|
||||
c16_t pss0_ext[NB_ANTENNAS_RX][LENGTH_PSS_NR],
|
||||
c16_t sss0_ext[NB_ANTENNAS_RX][LENGTH_SSS_NR],
|
||||
c16_t pss1_ext[NB_ANTENNAS_RX][LENGTH_PSS_NR],
|
||||
c16_t sss1_ext[NB_ANTENNAS_RX][LENGTH_SSS_NR])
|
||||
{
|
||||
int id = get_softmodem_params()->sl_mode == 0 ? ue->common_vars.eNb_id : ue->common_vars.N2_id;
|
||||
c16_t *pss = primary_synchro_nr[id];
|
||||
c16_t tmp, tmp2;
|
||||
c16_t *sss0_ext3 = &sss0_ext[0][0];
|
||||
for (uint8_t aarx = 0; aarx < ue->frame_parms.nb_antennas_rx; aarx++) {
|
||||
c16_t *sss0_ext2 = &sss0_ext[aarx][0];
|
||||
c16_t *pss0_ext2 = &pss0_ext[aarx][0];
|
||||
for (uint8_t i = 0; i < LENGTH_PSS_NR; i++) {
|
||||
// This is H*(PSS) = R* \cdot PSS
|
||||
tmp.r = (int16_t)((((int32_t)pss0_ext2[i].r) * pss[i].r)>>15);
|
||||
tmp.i = -(int16_t)((((int32_t)pss0_ext2[i].i) * pss[i].r)>>15);
|
||||
|
||||
int32_t amp = (((int32_t)tmp.r) * tmp.r) + ((int32_t)tmp.i) * tmp.i;
|
||||
int shift = log2_approx(amp) / 2;
|
||||
// This is R(SSS) \cdot H*(PSS)
|
||||
tmp2.r = (int16_t)(((tmp.r * (int32_t)sss0_ext2[i].r) >> shift) - ((tmp.i * (int32_t)sss0_ext2[i].i >> shift)));
|
||||
tmp2.i = (int16_t)(((tmp.r * (int32_t)sss0_ext2[i].i) >> shift) + ((tmp.i * (int32_t)sss0_ext2[i].r >> shift)));
|
||||
// MRC on RX antennas
|
||||
if (aarx==0) {
|
||||
sss0_ext3[i].r = tmp2.r;
|
||||
sss0_ext3[i].i = tmp2.i;
|
||||
} else {
|
||||
sss0_ext3[i].r += tmp2.r;
|
||||
sss0_ext3[i].i += tmp2.i;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
c16_t *sss1_ext3 = &sss1_ext[0][0];
|
||||
for (uint8_t aarx = 0; aarx < ue->frame_parms.nb_antennas_rx; aarx++) {
|
||||
c16_t *sss1_ext2 = &sss1_ext[aarx][0];
|
||||
c16_t *pss1_ext2 = &pss1_ext[aarx][0];
|
||||
for (uint8_t i = 0; i < LENGTH_PSS_NR; i++) {
|
||||
// This is H*(PSS) = R* \cdot PSS
|
||||
tmp.r = (int16_t)((((int32_t)pss1_ext2[i].r) * pss[i].r)>>15);
|
||||
tmp.i = -(int16_t)((((int32_t)pss1_ext2[i].i) * pss[i].r)>>15);
|
||||
int32_t amp = (((int32_t)tmp.r) * tmp.r) + ((int32_t)tmp.i) * tmp.i;
|
||||
int shift = log2_approx(amp) / 2;
|
||||
// This is R(SSS) \cdot H*(PSS)
|
||||
tmp2.r = (int16_t)(((tmp.r * (int32_t)sss1_ext2[i].r) >> shift) - ((tmp.i * (int32_t)sss1_ext2[i].i >> shift)));
|
||||
tmp2.i = (int16_t)(((tmp.r * (int32_t)sss1_ext2[i].i) >> shift) + ((tmp.i * (int32_t)sss1_ext2[i].r >> shift)));
|
||||
|
||||
// MRC on RX antennas
|
||||
if (aarx == 0) {
|
||||
sss1_ext3[i].r = tmp2.r;
|
||||
sss1_ext3[i].i = tmp2.i;
|
||||
} else {
|
||||
sss1_ext3[i].r += tmp2.r;
|
||||
sss1_ext3[i].i += tmp2.i;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
/*******************************************************************
|
||||
*
|
||||
* NAME : rx_sss_sl_nr
|
||||
*
|
||||
* PARAMETERS : none
|
||||
*
|
||||
* RETURN : Set Nid_cell in ue context
|
||||
*
|
||||
* DESCRIPTION : Determine element Nid1 of cell identity
|
||||
* so Nid_cell in ue context is set according to Nid1 & Nid2
|
||||
*
|
||||
*********************************************************************/
|
||||
|
||||
int rx_sss_sl_nr(PHY_VARS_NR_UE *ue, UE_nr_rxtx_proc_t *proc, int32_t *tot_metric, uint8_t *phase_max, int *freq_offset_sss)
|
||||
{
|
||||
c16_t pss0_ext[NB_ANTENNAS_RX][LENGTH_PSS_NR];
|
||||
c16_t sss0_ext[NB_ANTENNAS_RX][LENGTH_SSS_NR];
|
||||
c16_t pss1_ext[NB_ANTENNAS_RX][LENGTH_PSS_NR];
|
||||
c16_t sss1_ext[NB_ANTENNAS_RX][LENGTH_SSS_NR];
|
||||
NR_DL_FRAME_PARMS *frame_parms = &ue->frame_parms;
|
||||
|
||||
pss_sss_sl_extract_nr(ue, proc, pss0_ext, sss0_ext, pss1_ext, sss1_ext);
|
||||
|
||||
#ifdef DEBUG_PLOT_SSS
|
||||
write_output("rxsig0.m","rxs0",&ue->common_vars.rxdata[0][0],ue->frame_parms.samples_per_frame,1,1);
|
||||
write_output("rxdataF0_pss.m","rxF0_pss",&ue->common_vars.rxdataF[0][0],frame_parms->ofdm_symbol_size,1,1);
|
||||
write_output("rxdataF0_sss.m","rxF0_sss",&ue->common_vars.rxdataF[0][(SSS_SYMBOL_NB-PSS_SYMBOL_NB)*frame_parms->ofdm_symbol_size],frame_parms->ofdm_symbol_size,1,1);
|
||||
write_output("pss0_ext.m","pss0_ext",pss0_ext,LENGTH_PSS_NR,1,1);
|
||||
write_output("pss1_ext.m","pss1_ext",pss1_ext,LENGTH_PSS_NR,1,1);
|
||||
write_output("sss0_ext.m","sss0_ext",sss0_ext,LENGTH_PSS_NR,1,1);
|
||||
write_output("sss1_ext.m","sss1_ext",sss1_ext,LENGTH_PSS_NR,1,1);
|
||||
write_output("pss0_time.m","pss0_time",primary_synchro_time_nr[0],frame_parms->ofdm_symbol_size,1,1);
|
||||
write_output("pss1_time.m","pss1_time",primary_synchro_time_nr[1],frame_parms->ofdm_symbol_size,1,1);
|
||||
#endif
|
||||
|
||||
// get conjugated channel estimate from PSS, H* = R* \cdot PSS
|
||||
// and do channel estimation and compensation based on PSS
|
||||
pss_sl_ch_est_nr(ue, pss0_ext, sss0_ext, pss1_ext, sss1_ext);
|
||||
|
||||
write_output("sss0_comp.m","sss0_comp",sss0_ext,LENGTH_PSS_NR,1,1);
|
||||
write_output("sss1_comp.m","sss1_comp",sss1_ext,LENGTH_PSS_NR,1,1);
|
||||
/* now do the SSS detection based on the precomputed sequences in PHY/LTE_TRANSPORT/sss.
|
||||
for phase evaluation, one uses an array of possible phase shifts
|
||||
then a correlation is done between received signal with a shift pĥase and the reference signal
|
||||
Computation of signal with shift phase is based on below formula
|
||||
cosinus cos(x + y) = cos(x)cos(y) - sin(x)sin(y)
|
||||
sinus sin(x + y) = sin(x)cos(y) + cos(x)sin(y) */
|
||||
uint16_t Nid1;
|
||||
uint8_t Nid2 = ue->common_vars.N2_id;
|
||||
*tot_metric = INT_MIN;
|
||||
c16_t *sss0 = &sss0_ext[0][0];
|
||||
c16_t *sss1 = &sss1_ext[0][0];
|
||||
int16_t *d;
|
||||
for (Nid1 = 0; Nid1 < N_ID_1_NUMBER; Nid1++) { // all possible Nid1 values
|
||||
for (uint8_t phase = 0; phase < PHASE_HYPOTHESIS_NUMBER; phase++) { // phase offset between PSS and SSS
|
||||
int32_t metric = 0;
|
||||
int32_t metric_re = 0;
|
||||
d = (int16_t *)&d_sss[Nid2][Nid1];
|
||||
// This is the inner product using one particular value of each unknown parameter
|
||||
for (int i = 0; i < LENGTH_SSS_NR; i++) {
|
||||
metric_re += d[i] * (((phase_re_nr[phase] * sss0[i].r) >> SCALING_METRIC_SSS_NR) - ((phase_im_nr[phase] * sss0[i].i) >> SCALING_METRIC_SSS_NR)) +
|
||||
d[i] * (((phase_re_nr[phase] * sss1[i].r) >> SCALING_METRIC_SSS_NR) - ((phase_im_nr[phase] * sss1[i].i) >> SCALING_METRIC_SSS_NR));
|
||||
}
|
||||
metric = metric_re;
|
||||
if (metric > *tot_metric) {
|
||||
*tot_metric = metric;
|
||||
ue->frame_parms.Nid_SL = Nid1 + NUMBER_SSS_SEQUENCE * Nid2;
|
||||
*phase_max = phase;
|
||||
#ifdef DEBUG_SSS_NR
|
||||
LOG_I(NR_PHY,"(phase, Nid1) (%d,%d), metric_phase = %d, tot_metric = %d, phase_max = %d \n", phase, Nid1, metric, *tot_metric, *phase_max);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Nid2 = GET_NID2_SL(frame_parms->Nid_SL);
|
||||
Nid1 = GET_NID1_SL(frame_parms->Nid_SL);
|
||||
#if 1
|
||||
LOG_I(NR_PHY, "Nid2 %d Nid1 %d tot_metric %d, phase_max %d \n", Nid2, Nid1, *tot_metric, *phase_max);
|
||||
#endif
|
||||
|
||||
if (Nid1 == N_ID_1_NUMBER) {
|
||||
LOG_I(PHY,"Failled to detect SL SSS after PSS\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
int re = 0;
|
||||
int im = 0;
|
||||
d = (int16_t *)&d_sss[Nid2][Nid1];
|
||||
for(int i = 0; i < LENGTH_SSS_NR; i++) {
|
||||
re += d[i] * sss0[i].r;
|
||||
im += d[i] * sss0[i].i;
|
||||
re += d[i] * sss1[i].r;
|
||||
im += d[i] * sss1[i].i;
|
||||
}
|
||||
|
||||
double ffo_sss = atan2(im, re) / M_PI / 4.3;
|
||||
*freq_offset_sss = (int)(ffo_sss * frame_parms->subcarrier_spacing);
|
||||
double ffo_pss = ((double)ue->common_vars.freq_offset) / frame_parms->subcarrier_spacing;
|
||||
LOG_I(NR_PHY, "ffo_pss %f (%i Hz), ffo_sss %f (%i Hz), ffo_pss+ffo_sss %f (%i Hz)\n",
|
||||
ffo_pss, (int)(ffo_pss * frame_parms->subcarrier_spacing), ffo_sss, *freq_offset_sss, ffo_pss + ffo_sss,
|
||||
(int)((ffo_pss + ffo_sss) * frame_parms->subcarrier_spacing));
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
@@ -61,10 +61,13 @@ enum UEdataType {
|
||||
pbchRxdataF_comp,
|
||||
pdcchLlr,
|
||||
pdcchRxdataF_comp,
|
||||
UEdataTypeNumberOfItems,
|
||||
psbchDlChEstimateTime,
|
||||
psbchLlr,
|
||||
psbchRxdataF_comp,
|
||||
pdschLlr,
|
||||
pdschRxdataF_comp,
|
||||
commonRxdataF,
|
||||
UEdataTypeNumberOfItems
|
||||
};
|
||||
|
||||
typedef struct scopeData_s {
|
||||
|
||||
@@ -655,8 +655,6 @@ typedef struct RU_t_s {
|
||||
int txfh_core_id;
|
||||
/// number of RU interfaces
|
||||
int num_fd;
|
||||
/// Core id of ru_thread
|
||||
int ru_thread_core;
|
||||
/// list of cores for RU ThreadPool
|
||||
int tpcores[16];
|
||||
/// number of cores for RU ThreadPool
|
||||
|
||||
@@ -44,9 +44,6 @@
|
||||
#include "executables/rt_profiling.h"
|
||||
#include "nfapi_nr_interface_scf.h"
|
||||
|
||||
#include "common/utils/thread_pool/task_manager.h"
|
||||
|
||||
|
||||
#define MAX_NUM_RU_PER_gNB 8
|
||||
#define MAX_PUCCH0_NID 8
|
||||
|
||||
@@ -647,8 +644,6 @@ typedef struct PHY_VARS_gNB_s {
|
||||
/// CSI variables
|
||||
nr_csi_info_t *nr_csi_info;
|
||||
|
||||
// reference amplitude for TX
|
||||
int16_t TX_AMP;
|
||||
// PUCCH0 Look-up table for cyclic-shifts
|
||||
NR_gNB_PUCCH0_LUT_t pucch0_lut;
|
||||
|
||||
@@ -688,8 +683,6 @@ typedef struct PHY_VARS_gNB_s {
|
||||
|
||||
int ldpc_offload_flag;
|
||||
|
||||
int reorder_thread_disable;
|
||||
|
||||
int max_ldpc_iterations;
|
||||
/// indicate the channel estimation technique in time domain
|
||||
int chest_time;
|
||||
@@ -772,22 +765,10 @@ typedef struct PHY_VARS_gNB_s {
|
||||
notifiedFIFO_t L1_tx_out;
|
||||
notifiedFIFO_t resp_RU_tx;
|
||||
tpool_t threadPool;
|
||||
pthread_t L1_rx_thread;
|
||||
int L1_rx_thread_core;
|
||||
pthread_t L1_tx_thread;
|
||||
int L1_tx_thread_core;
|
||||
struct processingData_L1tx *msgDataTx;
|
||||
#ifndef TASK_MANAGER
|
||||
int nbDecode;
|
||||
#endif
|
||||
void *scopeData;
|
||||
/// structure for analyzing high-level RT measurements
|
||||
rt_L1_profiling_t rt_L1_profiling;
|
||||
|
||||
#ifdef TASK_MANAGER
|
||||
task_manager_t man;
|
||||
#endif
|
||||
|
||||
} PHY_VARS_gNB;
|
||||
|
||||
typedef struct LDPCDecode_s {
|
||||
@@ -810,9 +791,6 @@ typedef struct LDPCDecode_s {
|
||||
int offset;
|
||||
int decodeIterations;
|
||||
uint32_t tbslbrm;
|
||||
#ifdef TASK_MANAGER
|
||||
_Atomic bool* cancel;
|
||||
#endif
|
||||
} ldpcDecode_t;
|
||||
|
||||
struct ldpcReqId {
|
||||
|
||||
@@ -39,6 +39,7 @@
|
||||
|
||||
#include "defs_nr_common.h"
|
||||
#include "CODING/nrPolar_tools/nr_polar_pbch_defs.h"
|
||||
#include "CODING/nrPolar_tools/nr_polar_psbch_defs.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
@@ -233,17 +234,18 @@ typedef struct {
|
||||
/// - first index: rx antenna [0..nb_antennas_rx[
|
||||
/// - second index: sample [0..2*FRAME_LENGTH_COMPLEX_SAMPLES+2048[
|
||||
c16_t **rxdata;
|
||||
|
||||
/// \brief Holds the received data in time domain.
|
||||
/// Should point to the same memory as PHY_vars->rx_vars[a].RX_DMA_BUFFER.
|
||||
/// - first index: rx antenna [0..nb_antennas_rx[
|
||||
/// - second index: sample [0..2*FRAME_LENGTH_COMPLEX_SAMPLES+2048[
|
||||
/// \brief Holds the received data in the frequency domain.
|
||||
/// For IFFT_FPGA this points to the same memory as PHY_vars->rx_vars[a].RX_DMA_BUFFER.
|
||||
/// - first index: tx antenna [0..nb_antennas_tx[
|
||||
/// - second index: sample [0..FRAME_LENGTH_COMPLEX_SAMPLES_NO_PREFIX[
|
||||
c16_t **rxdataF;
|
||||
|
||||
/// holds output of the sync correlator
|
||||
int32_t *sync_corr;
|
||||
/// estimated frequency offset (in radians) for all subcarriers
|
||||
int32_t freq_offset;
|
||||
// N2_id - assigned based on in coverage status received in pss
|
||||
int32_t N2_id;
|
||||
/// eNb_id user is synched to
|
||||
int32_t eNb_id;
|
||||
} NR_UE_COMMON;
|
||||
@@ -318,7 +320,24 @@ typedef struct {
|
||||
fapi_nr_dl_config_dci_dl_pdu_rel15_t pdcch_config[FAPI_NR_MAX_SS];
|
||||
} NR_UE_PDCCH_CONFIG;
|
||||
|
||||
#define PBCH_A 24
|
||||
#define PSBCH_A 32
|
||||
#define PSBCH_MAX_RE_PER_SYMBOL (11*12)
|
||||
#define PSBCH_MAX_RE (PSBCH_MAX_RE_PER_SYMBOL*14)
|
||||
|
||||
typedef struct {
|
||||
/// \brief Total number of PDU errors.
|
||||
uint32_t pdu_errors;
|
||||
/// \brief Total number of PDU errors 128 frames ago.
|
||||
uint32_t pdu_errors_last;
|
||||
/// \brief Total number of consecutive PDU errors.
|
||||
uint32_t pdu_errors_conseq;
|
||||
/// \brief FER (in percent) .
|
||||
//uint32_t pdu_fer;
|
||||
uint32_t psbch_a;
|
||||
uint32_t psbch_a_interleaved;
|
||||
uint32_t psbch_a_prime;
|
||||
uint32_t psbch_e[NR_POLAR_PSBCH_E_DWORD];
|
||||
} NR_UE_PSBCH;
|
||||
|
||||
typedef struct {
|
||||
int16_t amp;
|
||||
@@ -378,8 +397,14 @@ typedef struct {
|
||||
int if_freq_off;
|
||||
/// \brief Indicator that UE is synchronized to a gNB
|
||||
int is_synchronized;
|
||||
/// \brief Indicator that UE is synchronized to a SyncRef UE on Sidelink
|
||||
int is_synchronized_sl;
|
||||
/// \brief Indicator that UE lost frame synchronization on Sidelink
|
||||
int lost_sync_sl;
|
||||
/// \brief Target gNB Nid_cell when UE is resynchronizing
|
||||
int target_Nid_cell;
|
||||
/// \brief Indicator that UE is an SynchRef UE
|
||||
int sync_ref;
|
||||
/// Data structure for UE process scheduling
|
||||
UE_nr_proc_t proc;
|
||||
/// Flag to indicate the UE shouldn't do timing correction at all
|
||||
@@ -420,10 +445,13 @@ typedef struct {
|
||||
fapi_nr_config_request_t nrUE_config;
|
||||
nr_synch_request_t synch_request;
|
||||
|
||||
NR_UE_PSBCH *psbch_vars[NUMBER_OF_CONNECTED_gNB_MAX];
|
||||
NR_UE_PRACH *prach_vars[NUMBER_OF_CONNECTED_gNB_MAX];
|
||||
NR_UE_CSI_IM *csiim_vars[NUMBER_OF_CONNECTED_gNB_MAX];
|
||||
NR_UE_CSI_RS *csirs_vars[NUMBER_OF_CONNECTED_gNB_MAX];
|
||||
NR_UE_SRS *srs_vars[NUMBER_OF_CONNECTED_gNB_MAX];
|
||||
NR_SLSS_t *slss;
|
||||
|
||||
NR_UE_PRS *prs_vars[NR_MAX_PRS_COMB_SIZE];
|
||||
uint8_t prs_active_gNBs;
|
||||
NR_DL_UE_HARQ_t dl_harq_processes[2][NR_MAX_DLSCH_HARQ_PROCESSES];
|
||||
@@ -445,7 +473,10 @@ typedef struct {
|
||||
/// PBCH DMRS sequence
|
||||
uint32_t nr_gold_pbch[2][64][NR_PBCH_DMRS_LENGTH_DWORD];
|
||||
|
||||
/// PDSCH DMRS
|
||||
/// PSBCH DMRS sequence
|
||||
uint32_t nr_gold_psbch[NR_PSBCH_DMRS_LENGTH_DWORD];
|
||||
|
||||
/// PDSCH DMRS
|
||||
uint32_t ****nr_gold_pdsch[NUMBER_OF_CONNECTED_eNB_MAX];
|
||||
|
||||
// Scrambling IDs used in PDSCH DMRS
|
||||
@@ -514,9 +545,9 @@ typedef struct {
|
||||
int ssb_offset;
|
||||
uint16_t symbol_offset; /// offset in terms of symbols for detected ssb in sync
|
||||
int rx_offset; /// Timing offset
|
||||
int rx_offset_sl; /// Timing offset for Sidelink
|
||||
int rx_offset_diff; /// Timing adjustment for ofdm symbol0 on HW USRP
|
||||
int max_pos_fil; /// Timing offset IIR filter
|
||||
bool apply_timing_offset; /// Do time sync for current frame
|
||||
int time_sync_cell;
|
||||
|
||||
/// Timing Advance updates variables
|
||||
@@ -660,6 +691,7 @@ typedef struct nr_rxtx_thread_data_s {
|
||||
UE_nr_rxtx_proc_t proc;
|
||||
PHY_VARS_NR_UE *UE;
|
||||
int writeBlockSize;
|
||||
notifiedFIFO_t txFifo;
|
||||
nr_phy_data_t phy_data;
|
||||
int tx_wait_for_dlsch;
|
||||
} nr_rxtx_thread_data_t;
|
||||
|
||||
@@ -69,6 +69,10 @@
|
||||
|
||||
#define NR_PBCH_DMRS_LENGTH 144 // in mod symbols
|
||||
#define NR_PBCH_DMRS_LENGTH_DWORD 10 // ceil(2(QPSK)*NR_PBCH_DMRS_LENGTH/32)
|
||||
#define NR_PSBCH_MAX_NB_CARRIERS 132
|
||||
#define NR_PSBCH_MAX_NB_MOD_SYMBOLS 99
|
||||
#define NR_PSBCH_DMRS_LENGTH 297 // in mod symbols
|
||||
#define NR_PSBCH_DMRS_LENGTH_DWORD 20 // ceil(2(QPSK)*NR_PBCH_DMRS_LENGTH/32)
|
||||
|
||||
/*used for the resource mapping*/
|
||||
#define NR_MAX_PDCCH_DMRS_LENGTH 576 // 16(L)*2(QPSK)*3(3 DMRS symbs per REG)*6(REG per CCE)
|
||||
@@ -95,6 +99,8 @@
|
||||
|
||||
#define NR_NB_NSCID 2
|
||||
|
||||
#define NR_RX_NB_TH 1
|
||||
|
||||
#define MAX_UL_DELAY_COMP 20
|
||||
|
||||
typedef enum {
|
||||
@@ -157,6 +163,8 @@ struct NR_DL_FRAME_PARMS {
|
||||
uint64_t dl_CarrierFreq;
|
||||
/// UL carrier frequency
|
||||
uint64_t ul_CarrierFreq;
|
||||
/// SL carrier frequency
|
||||
uint64_t sl_CarrierFreq;
|
||||
/// TX attenuation
|
||||
uint32_t att_tx;
|
||||
/// RX attenuation
|
||||
@@ -164,7 +172,12 @@ struct NR_DL_FRAME_PARMS {
|
||||
/// total Number of Resource Block Groups: this is ceil(N_PRB/P)
|
||||
/// Frame type (0 FDD, 1 TDD)
|
||||
frame_type_t frame_type;
|
||||
|
||||
uint16_t tdd_slot_config;
|
||||
uint8_t tdd_period;
|
||||
uint8_t tdd_config;
|
||||
/// Sidelink Cell ID
|
||||
uint16_t Nid_SL;
|
||||
/// Cell ID
|
||||
uint16_t Nid_cell;
|
||||
/// subcarrier spacing (15,30,60,120)
|
||||
@@ -216,8 +229,8 @@ struct NR_DL_FRAME_PARMS {
|
||||
/// Cyclic Prefix for DL (0=Normal CP, 1=Extended CP)
|
||||
lte_prefix_type_t Ncp;
|
||||
/// sequence which is computed based on carrier frequency and numerology to rotate/derotate each OFDM symbol according to Section 5.3 in 38.211
|
||||
/// First dimension is for the direction of the link (0 DL, 1 UL)
|
||||
c16_t symbol_rotation[2][224];
|
||||
/// First dimension is for the direction of the link (0 DL, 1 UL, 2 SL)
|
||||
c16_t symbol_rotation[3][224];
|
||||
/// sequence used to compensate the phase rotation due to timeshifted OFDM symbols
|
||||
/// First dimenstion is for different CP lengths
|
||||
c16_t timeshift_symbol_rotation[4096*2] __attribute__ ((aligned (16)));
|
||||
@@ -258,6 +271,17 @@ struct NR_DL_FRAME_PARMS {
|
||||
uint32_t ofdm_offset_divisor;
|
||||
};
|
||||
|
||||
/* NR Sidelink PSBCH payload fields
|
||||
TODO: This will be removed in the future and
|
||||
filled in by the upper layers once developed. */
|
||||
typedef struct {
|
||||
uint32_t coverageIndicator : 1;
|
||||
uint32_t tddConfig : 12;
|
||||
uint32_t DFN : 10;
|
||||
uint32_t slotIndex : 7;
|
||||
uint32_t reserved : 2;
|
||||
} PSBCH_payload;
|
||||
|
||||
// PRS config structures
|
||||
typedef struct {
|
||||
uint16_t PRSResourceSetPeriod[2]; // [slot period, slot offset] of a PRS resource set
|
||||
|
||||
@@ -99,6 +99,10 @@ SystemInformationBlockType1_nr_t;
|
||||
#define NR_UPLINK_SLOT (0x02)
|
||||
#define NR_MIXED_SLOT (0x03)
|
||||
|
||||
#define NR_LINK_TYPE_DL (0x00)
|
||||
#define NR_LINK_TYPE_UL (0x01)
|
||||
#define NR_LINK_TYPE_SL (0x02)
|
||||
|
||||
#define FRAME_DURATION_MICRO_SEC (10000) /* frame duration in microsecond */
|
||||
|
||||
typedef enum {
|
||||
|
||||
@@ -23,6 +23,10 @@
|
||||
#define __PHY_EXTERN_NR_UE__H__
|
||||
|
||||
#include "PHY/defs_nr_UE.h"
|
||||
|
||||
extern uint64_t downlink_frequency[MAX_NUM_CCs][4];
|
||||
extern int32_t uplink_frequency_offset[MAX_NUM_CCs][4];
|
||||
extern uint64_t sidelink_frequency[MAX_NUM_CCs][4];
|
||||
extern PHY_VARS_NR_UE ***PHY_vars_UE_g;
|
||||
|
||||
#endif /*__PHY_EXTERN_H__ */
|
||||
|
||||
@@ -37,7 +37,6 @@
|
||||
#include "nfapi/oai_integration/vendor_ext.h"
|
||||
#include "openair2/NR_PHY_INTERFACE/nr_sched_response.h"
|
||||
|
||||
|
||||
extern int oai_nfapi_dl_tti_req(nfapi_nr_dl_tti_request_t *dl_config_req);
|
||||
extern int oai_nfapi_tx_data_req(nfapi_nr_tx_data_request_t *tx_data_req);
|
||||
extern int oai_nfapi_ul_dci_req(nfapi_nr_ul_dci_request_t *ul_dci_req);
|
||||
@@ -158,19 +157,14 @@ void nr_schedule_response(NR_Sched_Rsp_t *Sched_INFO)
|
||||
if (NFAPI_MODE == NFAPI_MONOLITHIC){
|
||||
|
||||
if (slot_type == NR_DOWNLINK_SLOT || slot_type == NR_MIXED_SLOT) {
|
||||
notifiedFIFO_elt_t *res=NULL;
|
||||
processingData_L1tx_t *msgTx=NULL;
|
||||
if (!gNB->reorder_thread_disable) {
|
||||
res = pullTpool(&gNB->L1_tx_free, &gNB->threadPool);
|
||||
if (res == NULL)
|
||||
return; // Tpool has been stopped, nothing to process
|
||||
msgTx = (processingData_L1tx_t *)NotifiedFifoData(res);
|
||||
} else {
|
||||
msgTx = gNB->msgDataTx; //newNotifiedFIFO_elt(sizeof(processingData_L1tx_t),0, &gNB->L1_tx_out,NULL);
|
||||
}
|
||||
/*const time_stats_t ts = exec_time_stats_NotifiedFIFO(res);
|
||||
notifiedFIFO_elt_t *res;
|
||||
res = pullTpool(&gNB->L1_tx_free, &gNB->threadPool);
|
||||
if (res == NULL)
|
||||
return; // Tpool has been stopped, nothing to process
|
||||
processingData_L1tx_t *msgTx = (processingData_L1tx_t *)NotifiedFifoData(res);
|
||||
const time_stats_t ts = exec_time_stats_NotifiedFIFO(res);
|
||||
merge_meas(&gNB->phy_proc_tx, &ts);
|
||||
*/
|
||||
|
||||
msgTx->num_pdsch_slot = 0;
|
||||
msgTx->num_dl_pdcch = 0;
|
||||
msgTx->num_ul_pdcch = number_ul_dci_pdu;
|
||||
@@ -222,8 +216,7 @@ void nr_schedule_response(NR_Sched_Rsp_t *Sched_INFO)
|
||||
* released only when both threads are done with it.
|
||||
*/
|
||||
inc_ref_sched_response(Sched_INFO->sched_response_id);
|
||||
if (!gNB->reorder_thread_disable)
|
||||
pushNotifiedFIFO(&gNB->L1_tx_filled,res);
|
||||
pushNotifiedFIFO(&gNB->L1_tx_filled,res);
|
||||
}
|
||||
|
||||
for (int i = 0; i < number_ul_tti_pdu; i++) {
|
||||
|
||||
@@ -166,7 +166,7 @@ void nr_feptx_ofdm(RU_t *ru,int frame_tx,int tti_tx) {
|
||||
|
||||
LOG_D(PHY,"feptx_ofdm (TXPATH): frame %d, slot %d: txp (time %p) %d dB, txp (freq) %d dB\n",
|
||||
frame_tx,slot,txdata,dB_fixed(signal_energy((int32_t*)txdata,fp->get_samples_per_slot(
|
||||
slot,fp))),dB_fixed(signal_energy_nodc(ru->common.txdataF_BF[aa],2*slot_sizeF)));
|
||||
slot,fp))),dB_fixed(signal_energy_nodc(ru->common.txdataF_BF[aa],2*slot_sizeF)));
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -39,8 +39,6 @@
|
||||
#include "executables/softmodem-common.h"
|
||||
#include "nfapi/oai_integration/vendor_ext.h"
|
||||
#include "NR_SRS-ResourceSet.h"
|
||||
#include "common/utils/thread_pool/task_manager.h"
|
||||
|
||||
|
||||
#include "assertions.h"
|
||||
|
||||
@@ -83,23 +81,13 @@ void nr_common_signal_procedures (PHY_VARS_gNB *gNB,int frame,int slot,nfapi_nr_
|
||||
LOG_D(PHY, "SSB first subcarrier %d (%d,%d)\n", fp->ssb_start_subcarrier, prb_offset, sc_offset);
|
||||
|
||||
LOG_D(PHY,"SS TX: frame %d, slot %d, start_symbol %d\n",frame,slot, ssb_start_symbol);
|
||||
nr_generate_pss(&txdataF[0][txdataF_offset], gNB->TX_AMP, ssb_start_symbol, cfg, fp);
|
||||
nr_generate_sss(&txdataF[0][txdataF_offset], gNB->TX_AMP, ssb_start_symbol, cfg, fp);
|
||||
nr_generate_pss(&txdataF[0][txdataF_offset], AMP, ssb_start_symbol, cfg, fp);
|
||||
nr_generate_sss(&txdataF[0][txdataF_offset], AMP, ssb_start_symbol, cfg, fp);
|
||||
|
||||
if (fp->Lmax == 4)
|
||||
nr_generate_pbch_dmrs(gNB->nr_gold_pbch_dmrs[n_hf][ssb_index & 7],
|
||||
&txdataF[0][txdataF_offset],
|
||||
gNB->TX_AMP,
|
||||
ssb_start_symbol,
|
||||
cfg,
|
||||
fp);
|
||||
nr_generate_pbch_dmrs(gNB->nr_gold_pbch_dmrs[n_hf][ssb_index&7],&txdataF[0][txdataF_offset], AMP, ssb_start_symbol, cfg, fp);
|
||||
else
|
||||
nr_generate_pbch_dmrs(gNB->nr_gold_pbch_dmrs[0][ssb_index & 7],
|
||||
&txdataF[0][txdataF_offset],
|
||||
gNB->TX_AMP,
|
||||
ssb_start_symbol,
|
||||
cfg,
|
||||
fp);
|
||||
nr_generate_pbch_dmrs(gNB->nr_gold_pbch_dmrs[0][ssb_index&7],&txdataF[0][txdataF_offset], AMP, ssb_start_symbol, cfg, fp);
|
||||
|
||||
if (T_ACTIVE(T_GNB_PHY_MIB)) {
|
||||
unsigned char bch[3];
|
||||
@@ -119,12 +107,9 @@ void nr_common_signal_procedures (PHY_VARS_gNB *gNB,int frame,int slot,nfapi_nr_
|
||||
nr_generate_pbch(&ssb_pdu,
|
||||
gNB->nr_pbch_interleaver,
|
||||
&txdataF[0][txdataF_offset],
|
||||
gNB->TX_AMP,
|
||||
AMP,
|
||||
ssb_start_symbol,
|
||||
n_hf,
|
||||
frame,
|
||||
cfg,
|
||||
fp);
|
||||
n_hf, frame, cfg, fp);
|
||||
}
|
||||
|
||||
|
||||
@@ -185,7 +170,9 @@ void phy_procedures_gNB_TX(processingData_L1tx_t *msgTx,
|
||||
|
||||
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_gNB_PDCCH_TX,1);
|
||||
|
||||
nr_generate_dci_top(msgTx, slot, (int32_t *)&gNB->common_vars.txdataF[0][txdataF_offset], gNB->TX_AMP, fp);
|
||||
nr_generate_dci_top(msgTx, slot,
|
||||
(int32_t *)&gNB->common_vars.txdataF[0][txdataF_offset],
|
||||
AMP, fp);
|
||||
|
||||
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_gNB_PDCCH_TX,0);
|
||||
}
|
||||
@@ -202,20 +189,7 @@ void phy_procedures_gNB_TX(processingData_L1tx_t *msgTx,
|
||||
if (csirs->active == 1) {
|
||||
LOG_D(PHY, "CSI-RS generation started in frame %d.%d\n",frame,slot);
|
||||
nfapi_nr_dl_tti_csi_rs_pdu_rel15_t *csi_params = &csirs->csirs_pdu.csi_rs_pdu_rel15;
|
||||
nr_generate_csi_rs(&gNB->frame_parms,
|
||||
(int32_t **)gNB->common_vars.txdataF,
|
||||
gNB->TX_AMP,
|
||||
gNB->nr_csi_info,
|
||||
csi_params,
|
||||
slot,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL);
|
||||
nr_generate_csi_rs(&gNB->frame_parms, (int32_t **)gNB->common_vars.txdataF, AMP, gNB->nr_csi_info, csi_params, slot, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
|
||||
csirs->active = 0;
|
||||
}
|
||||
}
|
||||
@@ -224,7 +198,7 @@ void phy_procedures_gNB_TX(processingData_L1tx_t *msgTx,
|
||||
|
||||
//apply the OFDM symbol rotation here
|
||||
for (aa=0; aa<cfg->carrier_config.num_tx_ant.value; aa++) {
|
||||
apply_nr_rotation(fp, &gNB->common_vars.txdataF[aa][txdataF_offset], slot, 0, fp->Ncp == EXTENDED ? 12 : 14);
|
||||
apply_nr_rotation(fp, &gNB->common_vars.txdataF[aa][txdataF_offset], slot, 0, fp->Ncp == EXTENDED ? 12 : 14, NR_LINK_TYPE_DL);
|
||||
|
||||
T(T_GNB_PHY_DL_OUTPUT_SIGNAL, T_INT(0),
|
||||
T_INT(frame), T_INT(slot),
|
||||
@@ -234,15 +208,9 @@ void phy_procedures_gNB_TX(processingData_L1tx_t *msgTx,
|
||||
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_gNB_TX+offset,0);
|
||||
}
|
||||
|
||||
#ifdef TASK_MANAGER
|
||||
void nr_postDecode(PHY_VARS_gNB *gNB, ldpcDecode_t *rdata)
|
||||
{
|
||||
#else
|
||||
void nr_postDecode(PHY_VARS_gNB *gNB, notifiedFIFO_elt_t *req)
|
||||
{
|
||||
ldpcDecode_t *rdata = (ldpcDecode_t*) NotifiedFifoData(req);
|
||||
#endif
|
||||
|
||||
NR_UL_gNB_HARQ_t *ulsch_harq = rdata->ulsch_harq;
|
||||
NR_gNB_ULSCH_t *ulsch = rdata->ulsch;
|
||||
int r = rdata->segment_r;
|
||||
@@ -251,22 +219,15 @@ void nr_postDecode(PHY_VARS_gNB *gNB, notifiedFIFO_elt_t *req)
|
||||
ulsch_harq->processedSegments++;
|
||||
LOG_D(PHY, "processing result of segment: %d, processed %d/%d\n",
|
||||
rdata->segment_r, ulsch_harq->processedSegments, rdata->nbSegments);
|
||||
|
||||
#ifndef TASK_MANAGER
|
||||
gNB->nbDecode--;
|
||||
LOG_D(PHY,"remain to decoded in subframe: %d\n", gNB->nbDecode);
|
||||
#endif
|
||||
if (decodeSuccess) {
|
||||
memcpy(ulsch_harq->b+rdata->offset,
|
||||
ulsch_harq->c[r],
|
||||
rdata->Kr_bytes - (ulsch_harq->F>>3) -((ulsch_harq->C>1)?3:0));
|
||||
|
||||
} else {
|
||||
if (rdata->nbSegments != ulsch_harq->processedSegments){
|
||||
#ifdef TASK_MANAGER
|
||||
printf("openair1/SCHED_NR/phy_procedures_nr_gNB.c:267 \n");
|
||||
*rdata->cancel = true;
|
||||
#else
|
||||
if ( rdata->nbSegments != ulsch_harq->processedSegments ) {
|
||||
int nb = abortTpoolJob(&gNB->threadPool, req->key);
|
||||
nb += abortNotifiedFIFOJob(&gNB->respDecode, req->key);
|
||||
gNB->nbDecode-=nb;
|
||||
@@ -275,7 +236,6 @@ void nr_postDecode(PHY_VARS_gNB *gNB, notifiedFIFO_elt_t *req)
|
||||
AssertFatal(ulsch_harq->processedSegments+nb == rdata->nbSegments,"processed: %d, aborted: %d, total %d\n",
|
||||
ulsch_harq->processedSegments, nb, rdata->nbSegments);
|
||||
ulsch_harq->processedSegments=rdata->nbSegments;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
@@ -366,12 +326,6 @@ void nr_postDecode(PHY_VARS_gNB *gNB, notifiedFIFO_elt_t *req)
|
||||
|
||||
void nr_ulsch_procedures(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx, int ULSCH_id, uint8_t harq_pid)
|
||||
{
|
||||
|
||||
#ifdef TASK_MANAGER
|
||||
trigger_and_spin(&gNB->man);
|
||||
#endif
|
||||
|
||||
|
||||
NR_DL_FRAME_PARMS *frame_parms = &gNB->frame_parms;
|
||||
nfapi_nr_pusch_pdu_t *pusch_pdu = &gNB->ulsch[ULSCH_id].harq_process->ulsch_pdu;
|
||||
|
||||
@@ -430,27 +384,21 @@ void nr_ulsch_procedures(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx, int ULSCH
|
||||
|
||||
start_meas(&gNB->ulsch_decoding_stats);
|
||||
nr_ulsch_decoding(gNB, ULSCH_id, gNB->pusch_vars[ULSCH_id].llr, frame_parms, pusch_pdu, frame_rx, slot_rx, harq_pid, G);
|
||||
|
||||
#ifndef TASK_MANAGER
|
||||
if (enable_ldpc_offload == 0) {
|
||||
while (gNB->nbDecode > 0) {
|
||||
notifiedFIFO_elt_t *req = pullTpool(&gNB->respDecode, &gNB->threadPool);
|
||||
if (req == NULL)
|
||||
break; // Tpool has been stopped
|
||||
break; // Tpool has been stopped
|
||||
nr_postDecode(gNB, req);
|
||||
delNotifiedFIFO_elt(req);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
stop_meas(&gNB->ulsch_decoding_stats);
|
||||
}
|
||||
|
||||
|
||||
void nr_fill_indication(PHY_VARS_gNB *gNB, int frame, int slot_rx, int ULSCH_id, uint8_t harq_pid, uint8_t crc_flag, int dtx_flag)
|
||||
{
|
||||
if (!get_softmodem_params()->reorder_thread_disable)
|
||||
pthread_mutex_lock(&gNB->UL_INFO_mutex);
|
||||
pthread_mutex_lock(&gNB->UL_INFO_mutex);
|
||||
|
||||
NR_gNB_ULSCH_t *ulsch = &gNB->ulsch[ULSCH_id];
|
||||
NR_UL_gNB_HARQ_t *harq_process = ulsch->harq_process;
|
||||
@@ -609,8 +557,7 @@ void nr_fill_indication(PHY_VARS_gNB *gNB, int frame, int slot_rx, int ULSCH_id,
|
||||
|
||||
gNB->UL_INFO.rx_ind.number_of_pdus++;
|
||||
|
||||
if (!get_softmodem_params()->reorder_thread_disable)
|
||||
pthread_mutex_unlock(&gNB->UL_INFO_mutex);
|
||||
pthread_mutex_unlock(&gNB->UL_INFO_mutex);
|
||||
}
|
||||
|
||||
// Function to fill UL RB mask to be used for N0 measurements
|
||||
|
||||
@@ -87,6 +87,11 @@ typedef struct {
|
||||
uint8_t xtra_byte;
|
||||
} fapiPbch_t;
|
||||
|
||||
typedef struct {
|
||||
uint8_t decoded_output[NR_POLAR_PSBCH_PAYLOAD_BITS];
|
||||
uint8_t xtra_byte;
|
||||
} fapiPsbch_t;
|
||||
|
||||
/** @addtogroup _PHY_PROCEDURES_
|
||||
* @{
|
||||
*/
|
||||
@@ -98,6 +103,28 @@ typedef struct {
|
||||
*/
|
||||
void phy_procedures_nrUE_TX(PHY_VARS_NR_UE *ue, UE_nr_rxtx_proc_t *proc, nr_phy_data_tx_t *phy_data);
|
||||
|
||||
/*! \brief Scheduling for UE SL TX procedures in normal slots.
|
||||
@param ue Pointer to UE variables on which to act
|
||||
@param proc Pointer to RXn-TXnp4 proc information
|
||||
@param gNB_id Local id of gNB on which to act, 0 in case of sidelink
|
||||
*/
|
||||
void phy_procedures_nrUE_SL_TX(PHY_VARS_NR_UE *ue, UE_nr_rxtx_proc_t *proc, uint8_t gNB_id);
|
||||
|
||||
/*! \brief check weather if current slot in current frame is suitable for SL SSB time slot allocation.
|
||||
@param ue Pointer to UE variables on which to act
|
||||
@param frame frame number
|
||||
@param slot slot number
|
||||
*/
|
||||
bool phy_ssb_slot_allocation_sl(PHY_VARS_NR_UE *ue, int frame, int slot);
|
||||
|
||||
/*! \brief Scheduling for UE RX procedures in normal subframes.
|
||||
@param ue Pointer to UE variables on which to act
|
||||
@param proc Pointer to proc information
|
||||
@param dlsch_parallel use multithreaded dlsch processing
|
||||
@param phy_pdcch_config PDCCH Config for this slot
|
||||
@param txFifo Result fifo if PDSCH is run in parallel
|
||||
*/
|
||||
|
||||
void send_slot_ind(notifiedFIFO_t *nf, int slot);
|
||||
|
||||
void pbch_pdcch_processing(PHY_VARS_NR_UE *ue,
|
||||
|
||||
@@ -50,6 +50,8 @@
|
||||
#endif
|
||||
#include "executables/softmodem-common.h"
|
||||
#include "executables/nr-uesoftmodem.h"
|
||||
#include "LAYER2/NR_MAC_UE/mac_proto.h"
|
||||
#include "openair1/PHY/MODULATION/nr_modulation.h"
|
||||
#include "SCHED_NR_UE/pucch_uci_ue_nr.h"
|
||||
#include <openair1/PHY/TOOLS/phy_scope_interface.h>
|
||||
|
||||
@@ -256,6 +258,99 @@ void ue_ta_procedures(PHY_VARS_NR_UE *ue, int slot_tx, int frame_tx)
|
||||
}
|
||||
}
|
||||
|
||||
bool phy_ssb_slot_allocation_sl(PHY_VARS_NR_UE *ue, int frame, int slot)
|
||||
{
|
||||
NR_DL_FRAME_PARMS *fp = &ue->frame_parms;
|
||||
|
||||
if ((frame * fp->slots_per_frame + slot) % (16 * fp->slots_per_frame) == 0) {
|
||||
ue->slss->sl_numssb_withinperiod_r16 = ue->slss->sl_numssb_withinperiod_r16_copy;
|
||||
ue->slss->sl_timeoffsetssb_r16 = frame * fp->slots_per_frame + ue->slss->sl_timeoffsetssb_r16_copy;
|
||||
}
|
||||
|
||||
if (ue->slss->sl_numssb_withinperiod_r16 > 0) {
|
||||
if (frame * fp->slots_per_frame + slot == ue->slss->sl_timeoffsetssb_r16) {
|
||||
ue->slss->sl_timeoffsetssb_r16 = ue->slss->sl_timeoffsetssb_r16 + ue->slss->sl_timeinterval_r16;
|
||||
ue->slss->sl_numssb_withinperiod_r16 = ue->slss->sl_numssb_withinperiod_r16 - 1;
|
||||
LOG_I(PHY,"*** SL-SSB slot allocation %d.%d ***\n", frame, slot);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void phy_procedures_nrUE_SL_TX(PHY_VARS_NR_UE *ue,
|
||||
UE_nr_rxtx_proc_t *proc,
|
||||
uint8_t gNB_id)
|
||||
{
|
||||
int slot_tx = proc->nr_slot_tx;
|
||||
int frame_tx = proc->frame_tx;
|
||||
AssertFatal(frame_tx >= 0 && frame_tx < 1024, "frame_tx %d is not in 0...1023\n",frame_tx);
|
||||
AssertFatal(slot_tx >= 0 && slot_tx < 20, "slot_tx %d is not in 0...19\n", slot_tx);
|
||||
|
||||
LOG_D(PHY,"****** start Sidelink TX-Chain for AbsSlot %d.%d ******\n", frame_tx, slot_tx);
|
||||
|
||||
if (get_softmodem_params()->sl_mode == 2) {
|
||||
ue->tx_power_dBm[slot_tx] = -127;
|
||||
int num_samples_per_slot = ue->frame_parms.slots_per_frame * ue->frame_parms.samples_per_slot_wCP;
|
||||
for(int i = 0; i < ue->frame_parms.nb_antennas_tx; ++i) {
|
||||
AssertFatal(i < sizeof(ue->common_vars.txdataF), "Array index %d is over the Array size %lu\n", i, sizeof(ue->common_vars.txdataF));
|
||||
memset(ue->common_vars.txdataF[i], 0, sizeof(int32_t) * num_samples_per_slot);
|
||||
}
|
||||
}
|
||||
|
||||
if (ue->sync_ref && phy_ssb_slot_allocation_sl(ue, frame_tx, slot_tx)) {
|
||||
nr_sl_common_signal_procedures(ue, frame_tx, slot_tx);
|
||||
const int txdataF_offset = slot_tx * ue->frame_parms.samples_per_slot_wCP;
|
||||
LOG_D(NR_PHY, "%s() %d. slot %d txdataF_offset %d\n", __FUNCTION__, __LINE__, slot_tx, txdataF_offset);
|
||||
//ue->frame_parms.nb_prefix_samples0 = ue->is_synchronized_sl ? ue->frame_parms.nb_prefix_samples0 : ue->frame_parms.nb_prefix_samples;
|
||||
int slot_timestamp = ue->frame_parms.get_samples_slot_timestamp(slot_tx, &ue->frame_parms, 0);
|
||||
LOG_D(NR_PHY,"slot_timestamp %d\n",slot_timestamp);
|
||||
for (int aa = 0; aa < ue->frame_parms.nb_antennas_tx; aa++) {
|
||||
/* apply_nr_rotation(&ue->frame_parms,
|
||||
&ue->common_vars.txdataF[aa][txdataF_offset],
|
||||
slot_tx, 0, 1, NR_LINK_TYPE_SL); // Conducts rotation on 0th symbol*/
|
||||
PHY_ofdm_mod((int*)&ue->common_vars.txdataF[aa][txdataF_offset],
|
||||
(int*)&ue->common_vars.txdata[aa][slot_timestamp],
|
||||
ue->frame_parms.ofdm_symbol_size,
|
||||
1, // Takes IDFT of 1st symbol (first PSBCH)ue->frame_parms.nb_prefix_samples
|
||||
ue->frame_parms.nb_prefix_samples0,
|
||||
CYCLIC_PREFIX);
|
||||
/* apply_nr_rotation(&ue->frame_parms,
|
||||
&ue->common_vars.txdataF[aa][txdataF_offset],
|
||||
slot_tx, 1, 13, NR_LINK_TYPE_SL); // Conducts rotation on symbols located 1 (PSS) to 13 (guard)*/
|
||||
PHY_ofdm_mod((int*)&ue->common_vars.txdataF[aa][ue->frame_parms.ofdm_symbol_size + txdataF_offset], // Starting at PSS (in freq)
|
||||
(int*)&ue->common_vars.txdata[aa][ue->frame_parms.ofdm_symbol_size +
|
||||
ue->frame_parms.nb_prefix_samples0 + /*
|
||||
ue->frame_parms.nb_prefix_samples +*/
|
||||
slot_timestamp], // Starting output offset at CP0 + PSBCH0 + CP1
|
||||
ue->frame_parms.ofdm_symbol_size,
|
||||
13, // Takes IDFT of remaining 13 symbols (PSS to guard)... Notice the offset of the input and output above
|
||||
ue->frame_parms.nb_prefix_samples,
|
||||
CYCLIC_PREFIX);
|
||||
}
|
||||
#ifdef DEBUG_PHY_PROC
|
||||
char buffer1[ue->frame_parms.ofdm_symbol_size];
|
||||
for (int i = 0; i < 13; i++) {
|
||||
bzero(buffer1, sizeof(buffer1));
|
||||
LOG_I(NR_PHY, "%s(): %d After rotation txdataF[%d] = %s\n",
|
||||
__FUNCTION__, __LINE__, txdataF_offset + (ue->frame_parms.ofdm_symbol_size * i),
|
||||
hexdump((void *)&ue->common_vars.txdataF[0][txdataF_offset + (ue->frame_parms.ofdm_symbol_size * i)], ue->frame_parms.ofdm_symbol_size, buffer1, sizeof(buffer1)));
|
||||
}
|
||||
char buffer0[ue->frame_parms.ofdm_symbol_size];
|
||||
for (int i = 0; i < 13; i++) {
|
||||
bzero(buffer0, sizeof(buffer0));
|
||||
LOG_I(NR_PHY, "%s(): %d Time domain txdata[%d] = %s\n",
|
||||
__FUNCTION__, __LINE__, slot_timestamp + ue->frame_parms.ofdm_symbol_size * i,
|
||||
hexdump((void *)&ue->common_vars.txdata[0][slot_timestamp + ue->frame_parms.ofdm_symbol_size * i], ue->frame_parms.ofdm_symbol_size, buffer0, sizeof(buffer0)));
|
||||
}
|
||||
#endif
|
||||
}
|
||||
LOG_D(PHY,"****** end Sidelink TX-Chain for AbsSlot %d.%d ******\n", frame_tx, slot_tx);
|
||||
}
|
||||
|
||||
void phy_procedures_nrUE_TX(PHY_VARS_NR_UE *ue,
|
||||
UE_nr_rxtx_proc_t *proc,
|
||||
nr_phy_data_tx_t *phy_data) {
|
||||
@@ -352,12 +447,12 @@ void nr_ue_measurement_procedures(uint16_t l,
|
||||
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_MEASUREMENT_PROCEDURES, VCD_FUNCTION_OUT);
|
||||
}
|
||||
|
||||
static int nr_ue_pbch_procedures(PHY_VARS_NR_UE *ue,
|
||||
UE_nr_rxtx_proc_t *proc,
|
||||
int estimateSz,
|
||||
struct complex16 dl_ch_estimates[][estimateSz],
|
||||
nr_phy_data_t *phy_data,
|
||||
c16_t rxdataF[][ue->frame_parms.samples_per_slot_wCP]) {
|
||||
static void nr_ue_pbch_procedures(PHY_VARS_NR_UE *ue,
|
||||
UE_nr_rxtx_proc_t *proc,
|
||||
int estimateSz,
|
||||
struct complex16 dl_ch_estimates[][estimateSz],
|
||||
nr_phy_data_t *phy_data,
|
||||
c16_t rxdataF[][ue->frame_parms.samples_per_slot_wCP]) {
|
||||
|
||||
int ret = 0;
|
||||
DevAssert(ue);
|
||||
@@ -420,7 +515,6 @@ static int nr_ue_pbch_procedures(PHY_VARS_NR_UE *ue,
|
||||
|
||||
}
|
||||
|
||||
return ret;
|
||||
|
||||
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_PBCH_PROCEDURES, VCD_FUNCTION_OUT);
|
||||
}
|
||||
@@ -930,9 +1024,9 @@ void pbch_pdcch_processing(PHY_VARS_NR_UE *ue,
|
||||
if(ssb_index == fp->ssb_index) {
|
||||
|
||||
LOG_D(PHY," ------ Decode MIB: frame.slot %d.%d ------ \n", frame_rx%1024, nr_slot_rx);
|
||||
const int pbchSuccess = nr_ue_pbch_procedures(ue, proc, estimateSz, dl_ch_estimates, phy_data, rxdataF);
|
||||
nr_ue_pbch_procedures(ue, proc, estimateSz, dl_ch_estimates, phy_data, rxdataF);
|
||||
|
||||
if (ue->no_timing_correction==0 && pbchSuccess == 0) {
|
||||
if (ue->no_timing_correction==0) {
|
||||
LOG_D(PHY,"start adjust sync slot = %d no timing %d\n", nr_slot_rx, ue->no_timing_correction);
|
||||
nr_adjust_synch_ue(fp,
|
||||
ue,
|
||||
@@ -944,7 +1038,6 @@ void pbch_pdcch_processing(PHY_VARS_NR_UE *ue,
|
||||
0,
|
||||
16384);
|
||||
}
|
||||
ue->apply_timing_offset = true;
|
||||
}
|
||||
LOG_D(PHY, "Doing N0 measurements in %s\n", __FUNCTION__);
|
||||
nr_ue_rrc_measurements(ue, proc, rxdataF);
|
||||
|
||||
@@ -98,8 +98,9 @@ nfapi_ue_release_request_body_t release_rntis;
|
||||
instance_t DUuniqInstance=0;
|
||||
instance_t CUuniqInstance=0;
|
||||
|
||||
void nr_derive_key_ng_ran_star(uint16_t pci, uint64_t nr_arfcn_dl, const uint8_t key[32], uint8_t *key_ng_ran_star)
|
||||
int nr_derive_key_ng_ran_star(uint16_t pci, uint64_t nr_arfcn_dl, const uint8_t key[32], uint8_t *key_ng_ran_star)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int dummy_nr_ue_ul_indication(nr_uplink_indication_t *ul_info) { return(0); }
|
||||
@@ -123,9 +124,10 @@ int8_t nr_rrc_RA_succeeded(const module_id_t mod_id, const uint8_t gNB_index) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
void nr_derive_key(int alg_type, uint8_t alg_id, const uint8_t key[32], uint8_t out[16])
|
||||
int nr_derive_key(int alg_type, uint8_t alg_id,
|
||||
const uint8_t key[32], uint8_t **out)
|
||||
{
|
||||
(void)alg_type;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void processSlotTX(void *arg) {}
|
||||
|
||||
@@ -29,7 +29,8 @@
|
||||
* \note
|
||||
* \warning
|
||||
*/
|
||||
|
||||
#include "NR_ServingCellConfigCommon.h"
|
||||
#include "NR_ServingCellConfig.h"
|
||||
#ifndef __NR_UNITARY_DEFS__H__
|
||||
#define __NR_UNITARY_DEFS__H__
|
||||
|
||||
|
||||
@@ -652,10 +652,11 @@ int main(int argc, char **argv)
|
||||
gNB->common_vars.txdataF[aa],
|
||||
slot,
|
||||
0,
|
||||
12);
|
||||
12,
|
||||
NR_LINK_TYPE_DL);
|
||||
|
||||
PHY_ofdm_mod((int *)gNB->common_vars.txdataF[aa],
|
||||
(int *)&txdata[aa][frame_parms->get_samples_slot_timestamp(slot,frame_parms,0)],
|
||||
(int *)&txdata[aa][frame_parms->get_samples_slot_timestamp(slot, frame_parms, 0)],
|
||||
frame_parms->ofdm_symbol_size,
|
||||
12,
|
||||
frame_parms->nb_prefix_samples,
|
||||
@@ -665,7 +666,8 @@ int main(int argc, char **argv)
|
||||
gNB->common_vars.txdataF[aa],
|
||||
slot,
|
||||
0,
|
||||
14);
|
||||
14,
|
||||
NR_LINK_TYPE_DL);
|
||||
|
||||
/*nr_normal_prefix_mod(gNB->common_vars.txdataF[aa],
|
||||
&txdata[aa][frame_parms->get_samples_slot_timestamp(slot,frame_parms,0)],
|
||||
|
||||
@@ -80,7 +80,10 @@ void init_downlink_harq_status(NR_DL_UE_HARQ_t *dl_harq) { }
|
||||
|
||||
/* temporary dummy implem of get_softmodem_optmask, till basic simulators implemented as device */
|
||||
uint64_t get_softmodem_optmask(void) {return 0;}
|
||||
softmodem_params_t *get_softmodem_params(void) {return 0;}
|
||||
static softmodem_params_t softmodem_params;
|
||||
softmodem_params_t *get_softmodem_params(void) {
|
||||
return &softmodem_params;
|
||||
}
|
||||
//Fixme: Uniq dirty DU instance, by global var, datamodel need better management
|
||||
instance_t DUuniqInstance=0;
|
||||
instance_t CUuniqInstance=0;
|
||||
@@ -96,8 +99,9 @@ void deref_sched_response(int _)
|
||||
exit(1);
|
||||
}
|
||||
|
||||
void nr_derive_key_ng_ran_star(uint16_t pci, uint64_t nr_arfcn_dl, const uint8_t key[32], uint8_t *key_ng_ran_star)
|
||||
int nr_derive_key_ng_ran_star(uint16_t pci, uint64_t nr_arfcn_dl, const uint8_t key[32], uint8_t *key_ng_ran_star)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
void nr_rrc_ue_generate_RRCSetupRequest(module_id_t module_id, const uint8_t gNB_index)
|
||||
@@ -119,9 +123,10 @@ int8_t nr_rrc_RA_succeeded(const module_id_t mod_id, const uint8_t gNB_index) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
void nr_derive_key(int alg_type, uint8_t alg_id, const uint8_t key[32], uint8_t out[16])
|
||||
int nr_derive_key(int alg_type, uint8_t alg_id,
|
||||
const uint8_t key[32], uint8_t **out)
|
||||
{
|
||||
(void)alg_type;
|
||||
return 0;
|
||||
}
|
||||
|
||||
nrUE_params_t nrUE_params;
|
||||
@@ -136,13 +141,12 @@ void processSlotTX(void *arg) {}
|
||||
int NB_UE_INST = 1;
|
||||
|
||||
int main(int argc, char **argv){
|
||||
|
||||
get_softmodem_params()->sl_mode = 0;
|
||||
char c;
|
||||
|
||||
double sigma2, sigma2_dB = 0, SNR, snr0 = -2.0, snr1 = 0.0, ue_speed0 = 0.0, ue_speed1 = 0.0;
|
||||
double **s_re, **s_im, **r_re, **r_im, iqim = 0.0, delay_avg = 0, ue_speed = 0, fs=-1, bw;
|
||||
int i, l, aa, aarx, trial, n_frames = 1, prach_start, rx_prach_start; //, ntrials=1;
|
||||
c16_t **txdata;
|
||||
int N_RB_UL = 106, delay = 0, NCS_config = 13, rootSequenceIndex = 1, threequarter_fs = 0, mu = 1, fd_occasion = 0, loglvl = OAILOG_INFO, numRA = 0, prachStartSymbol = 0;
|
||||
uint8_t snr1set = 0, ue_speed1set = 0, transmission_mode = 1, n_tx = 1, n_rx = 1, awgn_flag = 0, msg1_frequencystart = 0, num_prach_fd_occasions = 1, prach_format=0;
|
||||
uint8_t config_index = 98, prach_sequence_length = 1, restrictedSetConfig = 0, N_dur, N_t_slot, start_symbol;
|
||||
@@ -594,7 +598,7 @@ int main(int argc, char **argv){
|
||||
|
||||
ue_prach_pdu = &UE->prach_vars[0]->prach_pdu;
|
||||
ue_prach_config = &UE->nrUE_config.prach_config;
|
||||
txdata = UE->common_vars.txdata;
|
||||
c16_t **txdata = UE->common_vars.txdata;
|
||||
|
||||
UE->prach_vars[0]->amp = AMP;
|
||||
ue_prach_pdu->root_seq_id = rootSequenceIndex;
|
||||
|
||||
645
openair1/SIMULATION/NR_PHY/psbchsim.c
Normal file
645
openair1/SIMULATION/NR_PHY/psbchsim.c
Normal file
@@ -0,0 +1,645 @@
|
||||
/*
|
||||
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The OpenAirInterface Software Alliance licenses this file to You under
|
||||
* the OAI Public License, Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.openairinterface.org/?page_id=698
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*-------------------------------------------------------------------------------
|
||||
* For more information about the OpenAirInterface (OAI) Software Alliance:
|
||||
* contact@openairinterface.org
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include <math.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/mman.h>
|
||||
#include "common/config/config_userapi.h"
|
||||
#include "common/utils/LOG/log.h"
|
||||
#include "common/utils/load_module_shlib.h"
|
||||
#include "common/utils/nr/nr_common.h"
|
||||
#include "PHY/types.h"
|
||||
#include "PHY/defs_nr_common.h"
|
||||
#include "PHY/defs_nr_UE.h"
|
||||
#include "openair1/PHY/NR_REFSIG/refsig_defs_ue.h"
|
||||
#include "PHY/MODULATION/modulation_eNB.h"
|
||||
#include "PHY/MODULATION/modulation_UE.h"
|
||||
#include "PHY/MODULATION/nr_modulation.h"
|
||||
#include "PHY/INIT/nr_phy_init.h"
|
||||
#include "PHY/NR_TRANSPORT/nr_transport_proto.h"
|
||||
#include "PHY/NR_UE_TRANSPORT/nr_transport_proto_ue.h"
|
||||
#include "PHY/NR_UE_ESTIMATION/nr_estimation.h"
|
||||
#include "PHY/phy_vars.h"
|
||||
#include "SCHED_NR/sched_nr.h"
|
||||
#include "openair1/SIMULATION/TOOLS/sim.h"
|
||||
#include "openair1/SIMULATION/RF/rf.h"
|
||||
#include "openair1/SIMULATION/NR_PHY/nr_unitary_defs.h"
|
||||
#include "openair1/SIMULATION/NR_PHY/nr_dummy_functions.c"
|
||||
#include "openair1/PHY/MODULATION/nr_modulation.h"
|
||||
#include "openair1/PHY/NR_REFSIG/pss_nr.h"
|
||||
#include <executables/softmodem-common.h>
|
||||
#include <executables/nr-uesoftmodem.h>
|
||||
#include "openair1/SCHED_NR_UE/defs.h"
|
||||
|
||||
//#define DEBUG_NR_PSBCHSIM
|
||||
double cpuf;
|
||||
uint16_t NB_UE_INST = 1;
|
||||
openair0_config_t openair0_cfg[MAX_CARDS];
|
||||
uint8_t const nr_rv_round_map[4] = {0, 2, 3, 1};
|
||||
|
||||
uint64_t get_softmodem_optmask(void) {return 0;}
|
||||
static softmodem_params_t softmodem_params;
|
||||
softmodem_params_t *get_softmodem_params(void) {
|
||||
return &softmodem_params;
|
||||
}
|
||||
|
||||
nrUE_params_t nrUE_params={0};
|
||||
nrUE_params_t *get_nrUE_params(void) {
|
||||
return &nrUE_params;
|
||||
}
|
||||
|
||||
void init_downlink_harq_status(NR_DL_UE_HARQ_t *dl_harq) {}
|
||||
|
||||
bool nr_ue_dlsch_procedures(PHY_VARS_NR_UE *ue,
|
||||
UE_nr_rxtx_proc_t *proc,
|
||||
NR_UE_DLSCH_t dlsch[2],
|
||||
int16_t* llr[2]) {
|
||||
return false;
|
||||
}
|
||||
|
||||
int nr_ue_pdsch_procedures(PHY_VARS_NR_UE *ue,
|
||||
UE_nr_rxtx_proc_t *proc,
|
||||
NR_UE_DLSCH_t dlsch[2],
|
||||
int16_t *llr[2],
|
||||
c16_t rxdataF[][ue->frame_parms.samples_per_slot_wCP]) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int nr_ue_pdcch_procedures(PHY_VARS_NR_UE *ue,
|
||||
UE_nr_rxtx_proc_t *proc,
|
||||
int32_t pdcch_est_size,
|
||||
int32_t pdcch_dl_ch_estimates[][pdcch_est_size],
|
||||
nr_phy_data_t *phy_data,
|
||||
int n_ss,
|
||||
c16_t rxdataF[][ue->frame_parms.samples_per_slot_wCP]) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void nr_fill_dl_indication(nr_downlink_indication_t *dl_ind,
|
||||
fapi_nr_dci_indication_t *dci_ind,
|
||||
fapi_nr_rx_indication_t *rx_ind,
|
||||
UE_nr_rxtx_proc_t *proc,
|
||||
PHY_VARS_NR_UE *ue,
|
||||
void *phy_data) {}
|
||||
void nr_fill_rx_indication(fapi_nr_rx_indication_t *rx_ind,
|
||||
uint8_t pdu_type,
|
||||
PHY_VARS_NR_UE *ue,
|
||||
NR_UE_DLSCH_t *dlsch0,
|
||||
NR_UE_DLSCH_t *dlsch1,
|
||||
uint16_t n_pdus,
|
||||
UE_nr_rxtx_proc_t *proc,
|
||||
void *typeSpecific,
|
||||
uint8_t *b) {}
|
||||
|
||||
double cfo = 0;
|
||||
double snr0 =- 2.0;
|
||||
double snr1 = 2.0;
|
||||
uint8_t snr1set = 0;
|
||||
int n_trials = 1;
|
||||
uint8_t n_tx = 1;
|
||||
uint8_t n_rx = 1;
|
||||
uint16_t Nid_cell = 0;
|
||||
uint16_t Nid_SL = 336 + 10;
|
||||
uint64_t SSB_positions = 0x01;
|
||||
int ssb_subcarrier_offset = 0;
|
||||
FILE *input_fd = NULL;
|
||||
SCM_t channel_model = AWGN;
|
||||
int N_RB_DL = 273;
|
||||
int mu = 1;
|
||||
unsigned char psbch_phase = 0;
|
||||
int run_initial_sync = 0;
|
||||
int loglvl = OAILOG_WARNING;
|
||||
float target_error_rate = 0.01;
|
||||
int seed = 0;
|
||||
|
||||
void free_psbchsim_members(PHY_VARS_NR_UE *UE,
|
||||
double **s_re,
|
||||
double **s_im,
|
||||
double **r_re,
|
||||
double **r_im,
|
||||
c16_t **txdata,
|
||||
FILE *input_fd)
|
||||
{
|
||||
term_nr_ue_signal(UE, 1);
|
||||
if (UE->slss) free(UE->slss);
|
||||
if (UE) free(UE);
|
||||
|
||||
for (int i = 0; i < 2; i++) {
|
||||
if (s_re[i]) free(s_re[i]);
|
||||
if (s_im[i]) free(s_im[i]);
|
||||
if (r_re[i]) free(r_re[i]);
|
||||
if (r_im[i]) free(r_im[i]);
|
||||
if (txdata[i]) free(txdata[i]);
|
||||
}
|
||||
if (s_re) free(s_re);
|
||||
if (s_im) free(s_im);
|
||||
if (r_re) free(r_re);
|
||||
if (r_im) free(r_im);
|
||||
if (txdata) free(txdata);
|
||||
|
||||
if (input_fd)
|
||||
fclose(input_fd);
|
||||
|
||||
loader_reset();
|
||||
logTerm();
|
||||
}
|
||||
|
||||
void nr_phy_config_request_sim_psbchsim(PHY_VARS_NR_UE *ue,
|
||||
int N_RB_DL,
|
||||
int N_RB_UL,
|
||||
int mu,
|
||||
int Nid_SL,
|
||||
uint64_t position_in_burst)
|
||||
{
|
||||
uint64_t rev_burst = 0;
|
||||
for (int i = 0; i < 64; i++)
|
||||
rev_burst |= (((SSB_positions >> (63-i))&0x01) << i);
|
||||
|
||||
NR_DL_FRAME_PARMS *fp = &ue->frame_parms;
|
||||
fapi_nr_config_request_t *nrUE_config = &ue->nrUE_config;
|
||||
nrUE_config->cell_config.phy_cell_id = Nid_SL; // TODO
|
||||
nrUE_config->ssb_config.scs_common = mu;
|
||||
nrUE_config->ssb_table.ssb_subcarrier_offset = 0;
|
||||
nrUE_config->ssb_table.ssb_offset_point_a = 0;
|
||||
nrUE_config->ssb_table.ssb_mask_list[1].ssb_mask = (rev_burst)&(0xFFFFFFFF);
|
||||
nrUE_config->ssb_table.ssb_mask_list[0].ssb_mask = (rev_burst>>32)&(0xFFFFFFFF);
|
||||
nrUE_config->cell_config.frame_duplex_type = TDD;
|
||||
nrUE_config->ssb_table.ssb_period = 1; //10ms
|
||||
nrUE_config->carrier_config.dl_grid_size[mu] = N_RB_DL;
|
||||
nrUE_config->carrier_config.ul_grid_size[mu] = N_RB_UL;
|
||||
nrUE_config->carrier_config.num_tx_ant = fp->nb_antennas_tx;
|
||||
nrUE_config->carrier_config.num_rx_ant = fp->nb_antennas_rx;
|
||||
nrUE_config->tdd_table.tdd_period = 0;
|
||||
nrUE_config->carrier_config.dl_frequency = 450000;
|
||||
nrUE_config->carrier_config.uplink_frequency = 450000;
|
||||
nrUE_config->carrier_config.sl_frequency = 450000;
|
||||
fp->dl_CarrierFreq = 2600000000;
|
||||
fp->ul_CarrierFreq = 2600000000;
|
||||
fp->nb_antennas_tx = n_tx;
|
||||
fp->nb_antennas_rx = n_rx;
|
||||
fp->nb_antenna_ports_gNB = n_tx;
|
||||
fp->N_RB_DL = N_RB_DL;
|
||||
fp->Nid_cell = Nid_cell;
|
||||
fp->Nid_SL = Nid_SL;
|
||||
fp->nushift = 0; //No nushift in SL
|
||||
fp->ssb_type = nr_ssb_type_C; //Note: case c for NR SL???
|
||||
fp->freq_range = mu < 2 ? nr_FR1 : nr_FR2;
|
||||
fp->nr_band = 38; //Note: NR SL uses for n38 and n47
|
||||
fp->threequarter_fs = 0;
|
||||
fp->ofdm_offset_divisor = UINT_MAX;
|
||||
fp->first_carrier_offset = 0;
|
||||
fp->ssb_start_subcarrier = 12 * ue->nrUE_config.ssb_table.ssb_offset_point_a + ssb_subcarrier_offset;
|
||||
int bw_index = get_supported_band_index(mu, fp->nr_band, N_RB_DL);
|
||||
nrUE_config->carrier_config.dl_bandwidth = get_supported_bw_mhz(fp->nr_band > 256 ? FR2 : FR1, bw_index);
|
||||
nr_init_frame_parms_ue(fp, nrUE_config, fp->nr_band);
|
||||
init_timeshift_rotation(fp);
|
||||
init_symbol_rotation(fp);
|
||||
LOG_I(NR_PHY, "nrUE configured\n");
|
||||
}
|
||||
|
||||
|
||||
static void get_sim_cl_opts(int argc, char **argv)
|
||||
{
|
||||
char c;
|
||||
while ((c = getopt(argc, argv, "F:g:hIL:m:M:n:N:o:O:p:P:r:R:s:S:x:y:z:")) != -1) {
|
||||
switch (c) {
|
||||
case 'F':
|
||||
input_fd = fopen(optarg, "r");
|
||||
if (input_fd == NULL) {
|
||||
printf("Problem with filename %s. Exiting.\n", optarg);
|
||||
exit(-1);
|
||||
}
|
||||
break;
|
||||
|
||||
case 'g':
|
||||
switch((char)*optarg) {
|
||||
case 'A':
|
||||
channel_model=SCM_A;
|
||||
break;
|
||||
|
||||
case 'B':
|
||||
channel_model=SCM_B;
|
||||
break;
|
||||
|
||||
case 'C':
|
||||
channel_model=SCM_C;
|
||||
break;
|
||||
|
||||
case 'D':
|
||||
channel_model=SCM_D;
|
||||
break;
|
||||
|
||||
case 'E':
|
||||
channel_model=EPA;
|
||||
break;
|
||||
|
||||
case 'F':
|
||||
channel_model=EVA;
|
||||
break;
|
||||
|
||||
case 'G':
|
||||
channel_model=ETU;
|
||||
break;
|
||||
|
||||
default:
|
||||
printf("Unsupported channel model! Exiting.\n");
|
||||
exit(-1);
|
||||
}
|
||||
break;
|
||||
|
||||
case 'I':
|
||||
run_initial_sync = 1;
|
||||
target_error_rate = 0.1;
|
||||
break;
|
||||
|
||||
case 'L':
|
||||
loglvl = atoi(optarg);
|
||||
break;
|
||||
|
||||
case 'm':
|
||||
mu = atoi(optarg);
|
||||
break;
|
||||
|
||||
case 'M':
|
||||
SSB_positions = atoi(optarg);
|
||||
break;
|
||||
|
||||
case 'n':
|
||||
n_trials = atoi(optarg);
|
||||
break;
|
||||
|
||||
case 'N':
|
||||
Nid_cell = atoi(optarg);
|
||||
break;
|
||||
|
||||
case 'O':
|
||||
ssb_subcarrier_offset = atoi(optarg);
|
||||
break;
|
||||
|
||||
case 'o':
|
||||
cfo = atof(optarg);
|
||||
break;
|
||||
|
||||
case 'P':
|
||||
psbch_phase = atoi(optarg);
|
||||
if (psbch_phase > 3)
|
||||
printf("Illegal PSBCH phase (0-3) got %d\n", psbch_phase);
|
||||
break;
|
||||
|
||||
case 'r':
|
||||
seed = atoi(optarg);
|
||||
break;
|
||||
|
||||
case 'R':
|
||||
N_RB_DL = atoi(optarg);
|
||||
break;
|
||||
|
||||
case 's':
|
||||
snr0 = atof(optarg);
|
||||
break;
|
||||
|
||||
case 'S':
|
||||
snr1 = atof(optarg);
|
||||
snr1set = 1;
|
||||
break;
|
||||
|
||||
case 'y':
|
||||
n_tx = atoi(optarg);
|
||||
if ((n_tx == 0) || (n_tx > 2)) {
|
||||
printf("Unsupported number of TX antennas %d. Exiting.\n", n_tx);
|
||||
exit(-1);
|
||||
}
|
||||
break;
|
||||
|
||||
case 'z':
|
||||
n_rx = atoi(optarg);
|
||||
if ((n_rx == 0) || (n_rx > 2)) {
|
||||
printf("Unsupported number of RX antennas %d. Exiting.\n", n_rx);
|
||||
exit(-1);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
case 'h':
|
||||
printf("%s -F input_filename -g channel_mod -h(elp) -I(nitial sync) -L log_lvl -n n_frames -M SSBs -n frames -N cell_id -o FO -P phase -r seed -R RBs -s snr0 -S snr1 -y TXant -z RXant\n",
|
||||
argv[0]);
|
||||
printf("-F Input filename (.txt format) for RX conformance testing\n");
|
||||
printf("-g [A,B,C,D,E,F,G] Use 3GPP SCM (A,B,C,D) or 36-101 (E-EPA,F-EVA,G-ETU) models (ignores delay spread and Ricean factor)\n");
|
||||
printf("-h This message\n");
|
||||
printf("-I run initial sync with target error rate 0.1\n");
|
||||
printf("-L set the log level (-1 disable, 0 error, 1 warning, 2 info, 3 debug, 4 trace)\n");
|
||||
printf("-m Numerology index\n");
|
||||
printf("-M Multiple SSB positions in burst\n");
|
||||
printf("-n Number of frames to simulate\n");
|
||||
printf("-N Nid_cell\n");
|
||||
printf("-o Carrier frequency offset in Hz\n");
|
||||
printf("-O SSB subcarrier offset\n");
|
||||
printf("-p Conducting PSS and SSS testing\n");
|
||||
printf("-P PSBCH phase, allowed values 0-3\n");
|
||||
printf("-r set the random number generator seed (default: 0 = current time)\n");
|
||||
printf("-R N_RB_DL\n");
|
||||
printf("-s Starting SNR, runs from SNR0 to SNR0 + 10 dB if not -S given. If -n 1, then just SNR is simulated\n");
|
||||
printf("-S Ending SNR, runs from SNR0 to SNR1\n");
|
||||
printf("-x Transmission mode (1,2,6 for the moment)\n");
|
||||
printf("-y Number of TX antennas used in eNB\n");
|
||||
printf("-z Number of RX antennas used in UE\n");
|
||||
exit (-1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
get_softmodem_params()->sa = 1;
|
||||
get_softmodem_params()->sl_mode = 2;
|
||||
if (load_configmodule(argc, argv, CONFIG_ENABLECMDLINEONLY) == 0) {
|
||||
exit_fun("[NR_PSBCHSIM] Error, configuration module init failed\n");
|
||||
}
|
||||
get_sim_cl_opts(argc, argv);
|
||||
randominit(seed);
|
||||
logInit();
|
||||
set_glog(loglvl);
|
||||
|
||||
PHY_VARS_NR_UE *UE = malloc16_clear(sizeof(*UE));
|
||||
|
||||
printf("Initializing UE for mu %d, N_RB_DL %d\n", mu, N_RB_DL);
|
||||
snr1 = snr1set == 0 ? snr0 + 10 : snr1;
|
||||
nr_phy_config_request_sim_psbchsim(UE, N_RB_DL, N_RB_DL, mu, Nid_SL, SSB_positions);
|
||||
|
||||
double fs = 0;
|
||||
double scs = 30000;
|
||||
switch (mu) {
|
||||
case 1:
|
||||
scs = 30000;
|
||||
UE->frame_parms.Lmax = 1;
|
||||
if (N_RB_DL == 217) {
|
||||
fs = 122.88e6;
|
||||
}
|
||||
else if (N_RB_DL == 245) {
|
||||
fs = 122.88e6;
|
||||
}
|
||||
else if (N_RB_DL == 273) {
|
||||
fs = 122.88e6;
|
||||
}
|
||||
else if (N_RB_DL == 106) {
|
||||
fs = 61.44e6;
|
||||
}
|
||||
else AssertFatal(1==0,"Unsupported numerology for mu %d, N_RB %d\n",mu, N_RB_DL);
|
||||
break;
|
||||
case 3:
|
||||
UE->frame_parms.Lmax = 64;
|
||||
scs = 120000;
|
||||
if (N_RB_DL == 66) {
|
||||
fs = 122.88e6;
|
||||
}
|
||||
else AssertFatal(1 == 0,"Unsupported numerology for mu %d, N_RB %d\n", mu, N_RB_DL);
|
||||
break;
|
||||
}
|
||||
|
||||
int frame_length_complex_samples = UE->frame_parms.samples_per_subframe * NR_NUMBER_OF_SUBFRAMES_PER_FRAME;
|
||||
double **s_re = malloc(2 * sizeof(double*));
|
||||
double **s_im = malloc(2 * sizeof(double*));
|
||||
double **r_re = malloc(2 * sizeof(double*));
|
||||
double **r_im = malloc(2 * sizeof(double*));
|
||||
c16_t **txdata = calloc(2, sizeof(c16_t*));
|
||||
for (int i = 0; i < 2; i++) {
|
||||
s_re[i] = malloc16_clear(frame_length_complex_samples * sizeof(double));
|
||||
s_im[i] = malloc16_clear(frame_length_complex_samples * sizeof(double));
|
||||
r_re[i] = malloc16_clear(frame_length_complex_samples * sizeof(double));
|
||||
r_im[i] = malloc16_clear(frame_length_complex_samples * sizeof(double));
|
||||
printf("Allocating %d samples for txdata\n", frame_length_complex_samples);
|
||||
txdata[i] = malloc16_clear(2 * frame_length_complex_samples * sizeof(c16_t));
|
||||
}
|
||||
|
||||
UE->slss = calloc(1, sizeof(*UE->slss));
|
||||
int len = sizeof(UE->slss->sl_mib) / sizeof(UE->slss->sl_mib[0]);
|
||||
for (int i = 0; i < len; i++) {
|
||||
UE->slss->sl_mib[i] = 0;
|
||||
}
|
||||
UE->slss->sl_mib_length = 32;
|
||||
UE->slss->sl_numssb_withinperiod_r16 = 1;
|
||||
UE->slss->sl_timeinterval_r16 = 0;
|
||||
UE->slss->sl_timeoffsetssb_r16 = 0;
|
||||
UE->slss->slss_id = Nid_SL;
|
||||
UE->target_Nid_cell = -1;
|
||||
UE->is_synchronized_sl = run_initial_sync ? 0 : 1;
|
||||
UE->UE_fo_compensation = (cfo / scs) != 0.0 ? 1 : 0; // if a frequency offset is set then perform fo estimation and compensation
|
||||
|
||||
if (init_nr_ue_signal(UE, 1) != 0) {
|
||||
printf("Error at UE NR initialisation\n");
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
nr_gold_psbch(UE);
|
||||
processingData_L1tx_t msgDataTx;
|
||||
AssertFatal(UE->frame_parms.Lmax < sizeof(msgDataTx.ssb) / sizeof(msgDataTx.ssb[0]), "Invalid index %d\n",
|
||||
UE->frame_parms.Lmax);
|
||||
AssertFatal(UE->frame_parms.nb_antennas_tx < 2, "Invalid index %d\n", UE->frame_parms.nb_antennas_tx);
|
||||
for (int i = 0; i < UE->frame_parms.Lmax; i++) {
|
||||
if((SSB_positions >> i) & 0x01) {
|
||||
for (int aa = 0; aa < UE->frame_parms.nb_antennas_tx; aa++)
|
||||
memset(UE->common_vars.txdataF[aa], 0, sizeof(*UE->common_vars.txdataF[aa]));
|
||||
|
||||
int frame = 0;
|
||||
int ssb_start_symbol_abs = (UE->slss->sl_timeoffsetssb_r16 + UE->slss->sl_timeinterval_r16 * i) * UE->frame_parms.symbols_per_slot;
|
||||
int slot = ssb_start_symbol_abs / 14;
|
||||
nr_sl_common_signal_procedures(UE, frame, slot);
|
||||
|
||||
const int sc_offset = UE->frame_parms.freq_range == nr_FR1 ? ssb_subcarrier_offset << mu : ssb_subcarrier_offset;
|
||||
const int prb_offset = UE->frame_parms.freq_range == nr_FR1 ? UE->nrUE_config.ssb_table.ssb_offset_point_a<<mu : UE->nrUE_config.ssb_table.ssb_offset_point_a << (mu - 2);
|
||||
msgDataTx.ssb[i].ssb_pdu.ssb_pdu_rel15.bchPayload = UE->psbch_vars[0]->psbch_a;
|
||||
msgDataTx.ssb[i].ssb_pdu.ssb_pdu_rel15.SsbBlockIndex = i;
|
||||
msgDataTx.ssb[i].ssb_pdu.ssb_pdu_rel15.SsbSubcarrierOffset = sc_offset;
|
||||
msgDataTx.ssb[i].ssb_pdu.ssb_pdu_rel15.ssbOffsetPointA = prb_offset;
|
||||
|
||||
int slot_timestamp = UE->frame_parms.get_samples_slot_timestamp(slot, &UE->frame_parms, 0);
|
||||
// UE->frame_parms.nb_prefix_samples0 = UE->is_synchronized_sl ? UE->frame_parms.nb_prefix_samples0 : UE->frame_parms.nb_prefix_samples;
|
||||
int max_symbol_size = slot_timestamp + UE->frame_parms.nb_prefix_samples0 + UE->frame_parms.ofdm_symbol_size;
|
||||
AssertFatal(max_symbol_size < frame_length_complex_samples, "Invalid index %d\n", max_symbol_size);
|
||||
for (int aa = 0; aa < UE->frame_parms.nb_antennas_tx; aa++) {
|
||||
apply_nr_rotation(&UE->frame_parms,
|
||||
UE->common_vars.txdataF[aa],
|
||||
slot, 0, 1, NR_LINK_TYPE_SL); // Conducts rotation on 0th symbol
|
||||
LOG_I(NR_PHY,"slot %d, symbol 0, nb_prefix_samples0 %d\n",slot,UE->frame_parms.nb_prefix_samples0);
|
||||
PHY_ofdm_mod((int*)UE->common_vars.txdataF[aa],
|
||||
(int*)&txdata[aa][slot_timestamp],
|
||||
UE->frame_parms.ofdm_symbol_size,
|
||||
1, // Takes IDFT of 1st symbol (first PSBCH)
|
||||
UE->frame_parms.nb_prefix_samples0,
|
||||
CYCLIC_PREFIX);
|
||||
|
||||
apply_nr_rotation(&UE->frame_parms,
|
||||
UE->common_vars.txdataF[aa],
|
||||
slot, 1, 13, NR_LINK_TYPE_SL); // Conducts rotation on symbols located 1 (PSS) to 13 (guard)
|
||||
|
||||
LOG_I(NR_PHY,"slot %d, symbols 1...13, nb_prefix_samples %d\n",slot,UE->frame_parms.nb_prefix_samples);
|
||||
PHY_ofdm_mod((int*)&UE->common_vars.txdataF[aa][UE->frame_parms.ofdm_symbol_size], // Starting at PSS (in freq)
|
||||
(int*)&txdata[aa][UE->frame_parms.ofdm_symbol_size +
|
||||
UE->frame_parms.nb_prefix_samples0 /*+
|
||||
UE->frame_parms.nb_prefix_samples*/], // Starting output offset at CP0 + PSBCH0 + CP1
|
||||
UE->frame_parms.ofdm_symbol_size,
|
||||
13, // Takes IDFT of remaining 13 symbols (PSS to guard)... Notice the offset of the input and output above
|
||||
UE->frame_parms.nb_prefix_samples,
|
||||
CYCLIC_PREFIX);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
char buffer[1024];
|
||||
printf("txdataF[0] = %s\n", hexdump(UE->common_vars.txdataF[0], sizeof(UE->common_vars.txdataF[0]), buffer, sizeof(buffer)));
|
||||
if (UE->frame_parms.nb_antennas_tx > 1)
|
||||
printf("txdataF[1] = %s\n", hexdump(UE->common_vars.txdataF[1], sizeof(UE->common_vars.txdataF[1]), buffer, sizeof(buffer)));
|
||||
|
||||
printf("txdata[0] = %s\n", hexdump(txdata[0], sizeof(txdata[0]), buffer, sizeof(buffer)));
|
||||
if (UE->frame_parms.nb_antennas_tx > 1)
|
||||
printf("txdata[0] = %s\n", hexdump(txdata[1], sizeof(txdata[1]), buffer, sizeof(buffer)));
|
||||
|
||||
AssertFatal((((frame_length_complex_samples - 1) << 1) + 1) < 2 * frame_length_complex_samples,
|
||||
"Invalid index %d >= %d\n", (((frame_length_complex_samples - 1)<< 1) + 1), 2 * frame_length_complex_samples);
|
||||
int n_errors = 0;
|
||||
int exitsim =0;
|
||||
for (double SNR = snr0; SNR < snr1; SNR += 0.2) {
|
||||
n_errors = 0;
|
||||
int n_errors_payload = 0;
|
||||
|
||||
for (int trial = 0; trial < n_trials; trial++) {
|
||||
for (int i = 0; i < frame_length_complex_samples; i++) {
|
||||
for (int aa = 0; aa < UE->frame_parms.nb_antennas_tx; aa++) {
|
||||
r_re[aa][i] = ((double)txdata[aa][i].r);
|
||||
r_im[aa][i] = ((double)txdata[aa][i].i);
|
||||
}
|
||||
}
|
||||
|
||||
//AWGN
|
||||
double ip = 0.0;
|
||||
if ((cfo / scs) != 0.0) {
|
||||
rf_rx(r_re, // real part of txdata
|
||||
r_im, // imag part of txdata
|
||||
NULL, // interference real part
|
||||
NULL, // interference imag part
|
||||
0, // interference power
|
||||
UE->frame_parms.nb_antennas_rx, // number of rx antennas
|
||||
frame_length_complex_samples, // number of samples in frame
|
||||
1.0e9/fs, //sampling time (ns)
|
||||
cfo, // frequency offset in Hz
|
||||
0.0, // drift (not implemented)
|
||||
0.0, // noise figure (not implemented)
|
||||
0.0, // rx gain in dB ?
|
||||
200, // 3rd order non-linearity in dB ?
|
||||
&ip, // initial phase
|
||||
30.0e3, // phase noise cutoff in kHz
|
||||
-500.0, // phase noise amplitude in dBc
|
||||
0.0, // IQ imbalance (dB),
|
||||
0.0); // IQ phase imbalance (rad)
|
||||
}
|
||||
|
||||
for (int i = 0; i < frame_length_complex_samples; i++) {
|
||||
double sigma2_dB = 20 * log10((double)AMP / 4) - SNR;
|
||||
double sigma2 = pow(10, sigma2_dB / 10);
|
||||
for (int aa = 0; aa < UE->frame_parms.nb_antennas_rx; aa++) {
|
||||
UE->common_vars.rxdata[aa][i].r = (short) (r_re[aa][i] + sqrt(sigma2 / 2) * gaussdouble(0.0,1.0));
|
||||
UE->common_vars.rxdata[aa][i].i = (short) (r_im[aa][i] + sqrt(sigma2 / 2) * gaussdouble(0.0,1.0));
|
||||
}
|
||||
}
|
||||
|
||||
int ret = 0;
|
||||
int n_frames = 1;
|
||||
if (UE->is_synchronized_sl == 0) {
|
||||
UE_nr_rxtx_proc_t proc = {0};
|
||||
LOG_I(NR_PHY,"Running initial synch\n");
|
||||
ret = nr_sl_initial_sync(&proc, UE, n_frames);
|
||||
if (ret != 0) {
|
||||
n_errors++;
|
||||
}
|
||||
} else {
|
||||
LOG_I(NR_PHY,"Already synched, running PSBCH receiver directly\n");
|
||||
UE_nr_rxtx_proc_t proc = {0};
|
||||
UE->rx_offset_sl = 0;
|
||||
uint8_t ssb_index = 0;
|
||||
const int estimateSz = 7 * 2 * sizeof(int) * UE->frame_parms.ofdm_symbol_size;
|
||||
__attribute__ ((aligned(32))) struct complex16 dl_ch_estimates[UE->frame_parms.nb_antennas_rx][estimateSz];
|
||||
__attribute__ ((aligned(32))) struct complex16 dl_ch_estimates_time[UE->frame_parms.nb_antennas_rx][estimateSz];
|
||||
while (!((SSB_positions >> ssb_index) & 0x01)) {
|
||||
ssb_index++; // to select the first transmitted ssb
|
||||
}
|
||||
UE->symbol_offset = (UE->slss->sl_timeoffsetssb_r16 + UE->slss->sl_timeinterval_r16 * ssb_index) * UE->frame_parms.symbols_per_slot;
|
||||
uint8_t n_hf = 0;
|
||||
int ssb_slot = (UE->symbol_offset / 14) + (n_hf * (UE->frame_parms.slots_per_frame >> 1));
|
||||
const uint32_t rxdataF_sz = UE->frame_parms.samples_per_slot_wCP;
|
||||
__attribute__ ((aligned(32))) c16_t rxdataF[UE->frame_parms.nb_antennas_rx][rxdataF_sz];
|
||||
for (int i = UE->symbol_offset; i < UE->symbol_offset + 13; i++) {
|
||||
nr_slot_fep(UE, &proc, i % UE->frame_parms.symbols_per_slot, rxdataF);
|
||||
for (int aa=0;aa<UE->frame_parms.nb_antennas_rx;aa++)
|
||||
memcpy(UE->common_vars.rxdataF[aa],rxdataF,4*rxdataF_sz);
|
||||
nr_psbch_channel_estimation(UE, estimateSz, dl_ch_estimates, dl_ch_estimates_time, &proc,
|
||||
0, ssb_slot, i % UE->frame_parms.symbols_per_slot,
|
||||
i - (UE->symbol_offset), ssb_index % 8, n_hf);
|
||||
if (i==0) i=4;
|
||||
}
|
||||
fapiPsbch_t result;
|
||||
NR_UE_PDCCH_CONFIG phy_pdcch_config = {0};
|
||||
/* Side link rx PSBCH */
|
||||
ret = 0;
|
||||
ret = nr_rx_psbch(UE,
|
||||
&proc,
|
||||
estimateSz,
|
||||
dl_ch_estimates,
|
||||
UE->psbch_vars[0],
|
||||
&UE->frame_parms,
|
||||
0,
|
||||
ssb_index % 8,
|
||||
SISO,
|
||||
&phy_pdcch_config,
|
||||
&result);
|
||||
|
||||
if (ret == 0) {
|
||||
int payload_ret = 0;
|
||||
for (int i = 0; i < NR_POLAR_PSBCH_PAYLOAD_BITS >> 3; i++) {
|
||||
LOG_I(NR_PHY,"result.decoded_output[i] %d, msgDataTx.ssb[ssb_index].ssb_pdu.ssb_pdu_rel15.bchPayload %d,\n",
|
||||
result.decoded_output[i], ((msgDataTx.ssb[ssb_index].ssb_pdu.ssb_pdu_rel15.bchPayload >> (8 * (3-i))) & 0xff));
|
||||
payload_ret += (result.decoded_output[i] == ((msgDataTx.ssb[ssb_index].ssb_pdu.ssb_pdu_rel15.bchPayload >> (8 * (3-i))) & 0xff));
|
||||
}
|
||||
if (payload_ret != (NR_POLAR_PSBCH_PAYLOAD_BITS >> 3))
|
||||
n_errors_payload++;
|
||||
}
|
||||
if (ret != 0) {
|
||||
n_errors++;
|
||||
}
|
||||
}
|
||||
} //noise trials
|
||||
printf("SNR %f: trials %d, n_errors_crc = %d, n_errors_payload %d\n", SNR, n_trials, n_errors, n_errors_payload);
|
||||
if (((float)n_errors / (float)n_trials <= target_error_rate) && (n_errors_payload == 0)) {
|
||||
printf("PSBCH test OK\n");
|
||||
exitsim=1;
|
||||
break;
|
||||
}
|
||||
if (exitsim == 1) break;
|
||||
} // NSR
|
||||
|
||||
free_psbchsim_members(UE, s_re, s_im, r_re, r_im, txdata, input_fd);
|
||||
|
||||
return 0;
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user