feat(nr): implement rank-8 PDSCH

This commit is contained in:
2026-09-15 00:36:01 +09:00
parent 04ee4ea8e5
commit c50fe1af53
42 changed files with 3244 additions and 648 deletions
+41 -3
View File
@@ -362,6 +362,15 @@ static buffer_t *allocCirBuf(rfsimulator_state_t *bridge, int sock)
set_channeldesc_owner(ptr->channel_model, RFSIMU_MODULEID);
set_channeldesc_direction(ptr->channel_model, bridge->role == SIMU_ROLE_SERVER);
// nakaolab Fix 9: ensure RNG is initialized before random_channel runs in this thread
{
static thread_local bool rng_initialized = false;
if (!rng_initialized) {
randominit();
set_taus_seed((unsigned int)(uintptr_t)pthread_self());
rng_initialized = true;
}
}
random_channel(ptr->channel_model, false);
LOG_I(HW, "Random channel %s in rfsimulator activated\n", modelname);
}
@@ -565,7 +574,11 @@ static void rfsimulator_readconfig(rfsimulator_state_t *rfsimulator)
break;
} else if (strcmp(rfsimuParam[p].strlistptr[i], "chanmod") == 0) {
init_channelmod();
load_channellist(rfsimulator->tx_num_channels,
// Channel model nb_tx must cover the peer's TX count, not just ours.
// E.g., UE has tx=1, rx=4, but gNB sends 4 TX streams. Without this fix,
// the UE-side channel model is (1,4) and only 1 TX stream is processed,
// dropping 3 of the 4 layers — RI gets capped at 1 instead of 4.
load_channellist(std::max(rfsimulator->tx_num_channels, rfsimulator->rx_num_channels),
rfsimulator->rx_num_channels,
rfsimulator->sample_rate,
rfsimulator->rx_freq,
@@ -671,7 +684,7 @@ static int rfsimu_setchanmod_cmd(char *buff, int debug, telnet_printfunc_t prnt,
if (b->channel_model->model_name == NULL)
continue;
if (b->conn_sock >= 0 && (strcmp(b->channel_model->model_name, modelname) == 0)) {
channel_desc_t *newmodel = new_channel_desc_scm(t->tx_num_channels,
channel_desc_t *newmodel = new_channel_desc_scm(std::max(t->tx_num_channels, t->rx_num_channels),
t->rx_num_channels,
static_cast<SCM_t>(channelmod),
t->sample_rate,
@@ -1283,6 +1296,15 @@ static void rfsimulator_read_internal(rfsimulator_state_t *t,
int rx_beam_id,
bool is_first_beam)
{
// nakaolab Fix 9: Thread-local RNG init.
// random_channel/gaussZiggurat may run in this thread; randominit() uses
// thread_local storage, so each new RX thread needs its own init.
static thread_local bool rng_initialized = false;
if (!rng_initialized) {
randominit();
set_taus_seed((unsigned int)(uintptr_t)pthread_self());
rng_initialized = true;
}
cf_t temp_array[nbAnt][nsamps];
bool channel_modelling = false;
// Add all input nodes signal in the output buffer
@@ -1306,7 +1328,23 @@ static void rfsimulator_read_internal(rfsimulator_state_t *t,
}
const uint64_t channel_offset = ptr->channel_model->channel_offset;
const uint64_t channel_length = ptr->channel_model->channel_length;
std::vector<std::vector<c16_t>> ant_buffers(ptr->nbAnt, std::vector<c16_t>(nsamps + channel_length - 1, {0, 0}));
// The UE-side channel descriptor is provisioned for the largest peer
// width it may receive (for example 8 TX when the UE has 8 RX). A
// matched experiment can still connect a narrower 4-TX gNB. Keep an
// input buffer for every descriptor TX port and leave absent peer
// ports zero; rxAddInput() iterates channel_model->nb_tx and therefore
// must not be handed the shorter peer-width pointer array.
const uint model_tx = ptr->channel_model->nb_tx;
AssertFatal(ptr->nbAnt <= model_tx,
"RFsim peer has %u TX ports but channel model supports only %u\n",
ptr->nbAnt,
model_tx);
AssertFatal(nbAnt <= ptr->channel_model->nb_rx,
"RFsim receiver has %d RX ports but channel model supports only %u\n",
nbAnt,
ptr->channel_model->nb_rx);
std::vector<std::vector<c16_t>> ant_buffers(model_tx,
std::vector<c16_t>(nsamps + channel_length - 1, {0, 0}));
c16_t *input[ant_buffers.size()];
for (uint aatx = 0; aatx < ant_buffers.size(); aatx++) {
input[aatx] = ant_buffers[aatx].data();