Avoid use of FAPI message buffers in msgDataTx

Note: after this commit, monolithic works but nFAPI operation is broken
and fixed in the next commit, to keep the changes small(er). All
simulators work.

This commit removes the use of msgDataTx's intermediate buffers for FAPI
messages and the call of the "Schedule response". The latter incurs an
additional copy of FAPI messages for the TX chain (for the RX chain, it
is and will remain there) which we can avoid.

Instead, it uses an NR_Sched_Rsp_t-typed variable sched_response to
store the results of the scheduler when called from tx_func(). Thus, the
scheduler remains unchanged (it gets a pointer to where to put FAPI
messages), but we don't call nr_schedule_response() to then copy FAPI
messages into the L1, but have them in a local variable sched_response.
sched_response on on the data segment, as it is big and would overflow
the stack; at the same time, this is ok because only one tx_func() runs
at a time.

Since we don't use allocate_sched_response() anymore, we don't need
deref_sched_response().

clear_slot_beamid() is moved to tx_func(), as it was called in
nr_schedule_response().

Since the "intermediate" NR_gNB_DLSCH_t structure groups both the
DL_tti_pdsch and TX_data.req structures, a pointer has been created to
point to pdsch_pdu. This affects a number of simulators, as they have to
put some messages on the stack:

- nr_dlschsim: put the corresponding variable on the stack
- nr_pbchsim: a new array for the SSB PDUs has been introduced

Further, these changes are now necessary:

- nr_dlsim:  there were variables "rel15" and "pdsch_pdu_rel15" that
  point to the same PDSCH PDU. At least "rel15" would not exist, as the
  corresponding pointer is now populated in phy_procedures_gNB_TX(), and
  we therefore refer to the single PDSCH PDU variable with
  "pdsch_pdu_rel15", but at the place where "rel15" used to be
  initialized.
- nr_ulsim: use nr_save_ul_tti_req() to load PDUs into the RX chain
  instead of nr_schedule_response(), which does not exist anymore.
This commit is contained in:
Robert Schmidt
2025-11-14 18:16:00 +01:00
parent e17c165c9d
commit 2bea71a80a
15 changed files with 206 additions and 195 deletions
+20 -18
View File
@@ -439,10 +439,7 @@ int main(int argc, char **argv)
nr_init_dl_harq_processes(UE->dl_harq_processes, 8, nb_rb);
unsigned char harq_pid = 0; //dlsch->harq_ids[subframe];
processingData_L1tx_t msgDataTx = {0};
msgDataTx.gNB = gNB;
NR_gNB_DLSCH_t *dlsch = &msgDataTx.gNB->dlsch[0];
nfapi_nr_dl_tti_pdsch_pdu_rel15_t *rel15 = &dlsch->pdsch_pdu.pdsch_pdu_rel15;
NR_gNB_DLSCH_t *dlsch = &gNB->dlsch[0];
//time_stats_t *rm_stats, *te_stats, *i_stats;
unsigned int TBS = 8424;
uint8_t nb_re_dmrs = 6; // No data in dmrs symbol
@@ -459,19 +456,24 @@ int main(int argc, char **argv)
TBS = nr_compute_tbs(mod_order,rate, nb_rb, nb_symb_sch, nb_re_dmrs*length_dmrs, 0, 0, Nl);
printf("available bits %u TBS %u mod_order %d\n", available_bits, TBS, mod_order);
//dlsch->harq_ids[subframe]= 0;
rel15->rbSize = nb_rb;
rel15->NrOfSymbols = nb_symb_sch;
rel15->qamModOrder[0] = mod_order;
rel15->nrOfLayers = Nl;
rel15->TBSize[0] = TBS>>3;
rel15->targetCodeRate[0] = rate;
rel15->NrOfCodewords = 1;
rel15->dmrsConfigType = NFAPI_NR_DMRS_TYPE1;
rel15->dlDmrsSymbPos = 4;
rel15->mcsIndex[0] = Imcs;
rel15->numDmrsCdmGrpsNoData = 1;
rel15->maintenance_parms_v3.tbSizeLbrmBytes = Tbslbrm;
rel15->maintenance_parms_v3.ldpcBaseGraph = get_BG(TBS, rate);
nfapi_nr_dl_tti_pdsch_pdu pdsch_pdu = {
.pdsch_pdu_rel15 = {
.rbSize = nb_rb,
.NrOfSymbols = nb_symb_sch,
.qamModOrder[0] = mod_order,
.nrOfLayers = Nl,
.TBSize[0] = TBS >> 3,
.targetCodeRate[0] = rate,
.NrOfCodewords = 1,
.dmrsConfigType = NFAPI_NR_DMRS_TYPE1,
.dlDmrsSymbPos = 4,
.mcsIndex[0] = Imcs,
.numDmrsCdmGrpsNoData = 1,
.maintenance_parms_v3.tbSizeLbrmBytes = Tbslbrm,
.maintenance_parms_v3.ldpcBaseGraph = get_BG(TBS, rate),
},
};
dlsch->pdsch_pdu = &pdsch_pdu;
double modulated_input[16 * 68 * 384]; // [hna] 16 segments, 68*Zc
short channel_output_fixed[16 * 68 * 384];
//unsigned char *estimated_output;
@@ -512,7 +514,7 @@ int main(int argc, char **argv)
//printf("crc32: [0]->0x%08x\n",crc24c(test_input, 32));
// generate signal
unsigned char output[rel15->rbSize * NR_SYMBOLS_PER_SLOT * NR_NB_SC_PER_RB * NR_MAX_NB_LAYERS] __attribute__((aligned(64)));
unsigned char output[nb_rb * NR_SYMBOLS_PER_SLOT * NR_NB_SC_PER_RB * NR_MAX_NB_LAYERS] __attribute__((aligned(64)));
bzero(output, sizeof(output));
if (input_fd == NULL) {
nr_dlsch_encoding(gNB, 1, dlsch, frame, slot, frame_parms, output, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
+28 -42
View File
@@ -62,7 +62,6 @@
#include "PHY/defs_nr_common.h"
#include "PHY/impl_defs_nr.h"
#include "PHY/phy_vars_nr_ue.h"
#include "SCHED_NR/fapi_nr_l1.h"
#include "SCHED_NR/sched_nr.h"
#include "SCHED_NR_UE/defs.h"
#include "SCHED_NR_UE/fapi_nr_ue_l1.h"
@@ -286,7 +285,6 @@ nrUE_params_t *get_nrUE_params(void) {
return &nrUE_params;
}
void validate_input_pmi(nfapi_nr_config_request_scf_t *gNB_config,
nr_pdsch_AntennaPorts_t pdsch_AntennaPorts,
int nrOfLayers,
@@ -974,12 +972,6 @@ int main(int argc, char **argv)
int ret = 1;
initNamedTpool(gNBthreads, &gNB->threadPool, true, "gNB-tpool");
initNotifiedFIFO(&gNB->L1_tx_out);
// we create 2 threads for L1 tx processing
processingData_L1tx_t *msgDataTx = malloc(sizeof(processingData_L1tx_t));
msgDataTx->slot = slot;
msgDataTx->frame = frame;
msgDataTx->gNB = gNB;
gNB->msgDataTx = msgDataTx;
// Buffers to store internal memory of slot process
int rx_size = (((14 * UE->frame_parms.N_RB_DL * 12 * sizeof(int32_t)) + 15) >> 4) << 4;
@@ -1058,8 +1050,13 @@ int main(int argc, char **argv)
n_false_positive = 0;
if (n_trials== 1) num_rounds = 1;
NR_gNB_DLSCH_t *gNB_dlsch = &msgDataTx->gNB->dlsch[0];
nfapi_nr_dl_tti_pdsch_pdu_rel15_t *rel15 = &gNB_dlsch->pdsch_pdu.pdsch_pdu_rel15;
NR_gNB_DLSCH_t *gNB_dlsch = &gNB->dlsch[0];
memset(Sched_INFO, 0, sizeof(*Sched_INFO));
Sched_INFO->sched_response_id = -1;
nfapi_nr_dl_tti_request_body_t *dl_req = &Sched_INFO->DL_req.dl_tti_request_body;
// scheduler will place PDSCH second (after PDCCH), verification below
nfapi_nr_dl_tti_request_pdu_t *dl_tti_pdsch_pdu = &dl_req->dl_tti_pdu_list[1];
nfapi_nr_dl_tti_pdsch_pdu_rel15_t *pdsch_pdu_rel15 = &dl_tti_pdsch_pdu->pdsch_pdu.pdsch_pdu_rel15;
for (trial = 0; trial < n_trials && !stop; trial++) {
@@ -1081,11 +1078,9 @@ int main(int argc, char **argv)
UE_harq_process->DLround = round;
UE_harq_process->first_rx = 1;
memset(Sched_INFO, 0, sizeof(*Sched_INFO));
Sched_INFO->sched_response_id = -1;
while (round < num_rounds && !UE_harq_process->decodeResult && !stop) {
clear_nr_nfapi_information(RC.nrmac[0], 0, frame, slot, &Sched_INFO->DL_req, &Sched_INFO->TX_req, &Sched_INFO->UL_dci_req);
reset_sched_response(Sched_INFO, frame, slot, 0, 0);
clear_nr_nfapi_information(RC.nrmac[0], 0, frame, slot);
UE_info->UE_sched_ctrl.harq_processes[harq_pid].ndi = !(trial&1);
UE_info->UE_sched_ctrl.harq_processes[harq_pid].round = round;
@@ -1093,18 +1088,13 @@ int main(int argc, char **argv)
NR_SCHED_LOCK(&gNB_mac->sched_lock);
nr_schedule_ue_spec(0, frame, slot, &Sched_INFO->DL_req, &Sched_INFO->TX_req);
NR_SCHED_UNLOCK(&gNB_mac->sched_lock);
Sched_INFO->module_id = 0;
Sched_INFO->CC_id = 0;
Sched_INFO->frame = frame;
Sched_INFO->slot = slot;
Sched_INFO->UL_dci_req.numPdus = 0;
nr_schedule_response(Sched_INFO);
/* check that second message is indeed PDSCH */
DevAssert(dl_tti_pdsch_pdu->PDUType == NFAPI_NR_DL_TTI_PDSCH_PDU_TYPE);
/* PTRS values for DLSIM calculations */
nfapi_nr_dl_tti_request_body_t *dl_req = &Sched_INFO->DL_req.dl_tti_request_body;
nfapi_nr_dl_tti_request_pdu_t *dl_tti_pdsch_pdu = &dl_req->dl_tti_pdu_list[1];
nfapi_nr_dl_tti_pdsch_pdu_rel15_t *pdsch_pdu_rel15 = &dl_tti_pdsch_pdu->pdsch_pdu.pdsch_pdu_rel15;
pdu_bit_map = pdsch_pdu_rel15->pduBitmap;
// This is already in DL procedures??
if(pdu_bit_map & 0x1) {
set_ptrs_symb_idx(&dlPtrsSymPos,
pdsch_pdu_rel15->NrOfSymbols,
@@ -1112,16 +1102,12 @@ int main(int argc, char **argv)
1<<pdsch_pdu_rel15->PTRSTimeDensity,
pdsch_pdu_rel15->dlDmrsSymbPos);
ptrsSymbPerSlot = get_ptrs_symbols_in_slot(dlPtrsSymPos, pdsch_pdu_rel15->StartSymbolIndex, pdsch_pdu_rel15->NrOfSymbols);
ptrsRePerSymb = ((rel15->rbSize + rel15->PTRSFreqDensity - 1) / rel15->PTRSFreqDensity);
ptrsRePerSymb = ((pdsch_pdu_rel15->rbSize + pdsch_pdu_rel15->PTRSFreqDensity - 1) / pdsch_pdu_rel15->PTRSFreqDensity);
LOG_D(PHY,"[DLSIM] PTRS Symbols in a slot: %2u, RE per Symbol: %3u, RE in a slot %4d\n", ptrsSymbPerSlot, ptrsRePerSymb, ptrsSymbPerSlot * ptrsRePerSymb);
}
msgDataTx->ssb_pdu[0].ssb_pdu_rel15.bchPayload = 0x001234;
msgDataTx->ssb_pdu[0].ssb_pdu_rel15.SsbBlockIndex = 0;
msgDataTx->gNB = gNB;
start_meas(&gNB->phy_proc_tx);
phy_procedures_gNB_TX(msgDataTx,frame,slot,1);
phy_procedures_gNB_TX(gNB, &Sched_INFO->DL_req, &Sched_INFO->TX_req, &Sched_INFO->UL_dci_req, frame, slot, 1);
stop_meas(&gNB->phy_proc_tx);
int txdataF_offset = slot * frame_parms->samples_per_slot_wCP;
@@ -1196,9 +1182,9 @@ int main(int argc, char **argv)
double ts = 1.0/(frame_parms->subcarrier_spacing * frame_parms->ofdm_symbol_size);
//Compute AWGN variance
sigma2_dB = 10 * log10((double)txlev_sum * ((double)UE->frame_parms.ofdm_symbol_size/(12*rel15->rbSize))) - SNR;
sigma2_dB = 10 * log10((double)txlev_sum * ((double)UE->frame_parms.ofdm_symbol_size/(12*pdsch_pdu_rel15->rbSize))) - SNR;
sigma2 = pow(10, sigma2_dB/10);
if (n_trials==1) printf("sigma2 %f (%f dB), txlev_sum %f (factor %f)\n",sigma2,sigma2_dB,10*log10((double)txlev_sum),(double)(double)UE->frame_parms.ofdm_symbol_size/(12*rel15->rbSize));
if (n_trials==1) printf("sigma2 %f (%f dB), txlev_sum %f (factor %f)\n",sigma2,sigma2_dB,10*log10((double)txlev_sum),(double)(double)UE->frame_parms.ofdm_symbol_size/(12*pdsch_pdu_rel15->rbSize));
for (aa = 0; aa < n_rx; aa++) {
bzero(r_re[aa], slot_length * sizeof(double));
@@ -1240,17 +1226,17 @@ int main(int argc, char **argv)
int16_t *UE_llr = (int16_t*)UE->phy_sim_pdsch_llr;
TBS = dlsch0->dlsch_config.TBS;//rel15->TBSize[0];
TBS = dlsch0->dlsch_config.TBS;
uint16_t length_dmrs = get_num_dmrs(dlsch0->dlsch_config.dlDmrsSymbPos);
uint16_t nb_rb = dlsch0->dlsch_config.number_rbs;
uint8_t nb_re_dmrs = dlsch0->dlsch_config.dmrsConfigType == NFAPI_NR_DMRS_TYPE1 ? 6*dlsch0->dlsch_config.n_dmrs_cdm_groups : 4*dlsch0->dlsch_config.n_dmrs_cdm_groups;
uint8_t mod_order = dlsch0->dlsch_config.qamModOrder;
uint8_t nb_symb_sch = dlsch0->dlsch_config.number_symbols;
uint32_t unav_res = ptrsSymbPerSlot * ptrsRePerSymb;
available_bits = nr_get_G(nb_rb, nb_symb_sch, nb_re_dmrs, length_dmrs, unav_res, mod_order, rel15->nrOfLayers);
available_bits = nr_get_G(nb_rb, nb_symb_sch, nb_re_dmrs, length_dmrs, unav_res, mod_order, pdsch_pdu_rel15->nrOfLayers);
if (pdu_bit_map & 0x1) {
if (trial == 0 && round == 0) {
printf("[DLSIM][PTRS] Available bits are: %5u, removed PTRS bits are: %5u \n", available_bits, (ptrsSymbPerSlot * ptrsRePerSymb * rel15->nrOfLayers * mod_order));
printf("[DLSIM][PTRS] Available bits are: %5u, removed PTRS bits are: %5u \n", available_bits, (ptrsSymbPerSlot * ptrsRePerSymb * pdsch_pdu_rel15->nrOfLayers * mod_order));
}
}
@@ -1269,8 +1255,8 @@ int main(int argc, char **argv)
} // round
if (test_input_bit == NULL) {
test_input_bit = (unsigned char *)malloc16(8 * rel15->TBSize[0]);
estimated_output_bit = (unsigned char *)malloc16(8 * rel15->TBSize[0]);
test_input_bit = (unsigned char *)malloc16(8 * pdsch_pdu_rel15->TBSize[0]);
estimated_output_bit = (unsigned char *)malloc16(8 * pdsch_pdu_rel15->TBSize[0]);
}
for (i = 0; i < TBS; i++) {
@@ -1319,7 +1305,7 @@ int main(int argc, char **argv)
printf("), Channel BER (%e", berStats[0]);
for (int r = 1; r < num_rounds; r++)
printf(",%e", berStats[r]);
printf(") Avg round %.2f, Eff Rate %.4f bits/slot, Eff Throughput %.2f, TBS %u bits/slot\n", roundStats, effRate, effRate / (8 * rel15->TBSize[0]) * 100, 8 * rel15->TBSize[0]);
printf(") Avg round %.2f, Eff Rate %.4f bits/slot, Eff Throughput %.2f, TBS %u bits/slot\n", roundStats, effRate, effRate / (8 * pdsch_pdu_rel15->TBSize[0]) * 100, 8 * pdsch_pdu_rel15->TBSize[0]);
printf("*****************************************\n");
printf("\n");
// writing to csv file
@@ -1327,7 +1313,7 @@ int main(int argc, char **argv)
fprintf(csv_file,"%f,%d/%d,",SNR,n_false_positive,n_trials);
for (int r = 0; r < num_rounds; r++)
fprintf(csv_file,"%d/%d,%u/%u,%f,%e,",n_errors[r], round_trials[r], errors_scrambling[r], available_bits * round_trials[r],blerStats[r],berStats[r]);
fprintf(csv_file,"%.2f,%.4f,%.2f,%u\n", roundStats, effRate, effRate / (8 * rel15->TBSize[0]) * 100, 8 * rel15->TBSize[0]);
fprintf(csv_file,"%.2f,%.4f,%.2f,%u\n", roundStats, effRate, effRate / (8 * pdsch_pdu_rel15->TBSize[0]) * 100, 8 * pdsch_pdu_rel15->TBSize[0]);
}
if (print_perf==1) {
printf("\ngNB TX function statistics (per %d us slot, NPRB %d, mcs %d, C %d, block %d)\n",
@@ -1335,7 +1321,7 @@ int main(int argc, char **argv)
g_rbSize,
g_mcsIndex,
UE->dl_harq_processes[0][slot].C,
8 * rel15->TBSize[0]);
8 * pdsch_pdu_rel15->TBSize[0]);
printDistribution(&gNB->phy_proc_tx,table_tx,"PHY proc tx");
printStatIndent2(&gNB->dci_generation_stats, "DCI encoding time");
printStatIndent2(&gNB->dlsch_encoding_stats,"DLSCH encoding time");
@@ -1377,8 +1363,8 @@ int main(int argc, char **argv)
const uint32_t numReSym = (g_rbSize * 12 + 15) & (~15);
for (int l = 0; l < g_nrOfLayers; l++) {
for (int r = 0; r < n_rx; r++) {
const int s = rel15->StartSymbolIndex;
const int n = rel15->NrOfSymbols;
const int s = pdsch_pdu_rel15->StartSymbolIndex;
const int n = pdsch_pdu_rel15->NrOfSymbols;
for (int i = s; i < s + n; i++) {
const uint32_t dmrsBitMap = phy_data.dlsch[0].dlsch_config.dlDmrsSymbPos;
const uint32_t dmrsCfg = phy_data.dlsch[0].dlsch_config.dmrsConfigType;
@@ -1414,7 +1400,7 @@ int main(int argc, char **argv)
break;
}
if (effRate >= (eff_tp_check * 8 * rel15->TBSize[0])) {
if (effRate >= (eff_tp_check * 8 * pdsch_pdu_rel15->TBSize[0])) {
printf("PDSCH test OK\n");
ret = 0;
break;
+7 -7
View File
@@ -519,10 +519,10 @@ int main(int argc, char **argv)
exit(-1);
}
processingData_L1tx_t msgDataTx;
// generate signal
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];
nfapi_nr_dl_tti_ssb_pdu ssb_pdu[64] = {0};
if (input_fd==NULL) {
for (i=0; i<frame_parms->Lmax; i++) {
@@ -530,10 +530,10 @@ int main(int argc, char **argv)
const int sc_offset = frame_parms->freq_range == FR1 ? ssb_subcarrier_offset<<mu : ssb_subcarrier_offset;
const int prb_offset = frame_parms->freq_range == FR1 ? gNB->gNB_config.ssb_table.ssb_offset_point_a.value<<mu : gNB->gNB_config.ssb_table.ssb_offset_point_a.value << (mu - 2);
msgDataTx.ssb_pdu[i].ssb_pdu_rel15.bchPayload = 0x55dd33;
msgDataTx.ssb_pdu[i].ssb_pdu_rel15.SsbBlockIndex = i;
msgDataTx.ssb_pdu[i].ssb_pdu_rel15.SsbSubcarrierOffset = sc_offset;
msgDataTx.ssb_pdu[i].ssb_pdu_rel15.ssbOffsetPointA = prb_offset;
ssb_pdu[i].ssb_pdu_rel15.bchPayload = 0x55dd33;
ssb_pdu[i].ssb_pdu_rel15.SsbBlockIndex = i;
ssb_pdu[i].ssb_pdu_rel15.SsbSubcarrierOffset = sc_offset;
ssb_pdu[i].ssb_pdu_rel15.ssbOffsetPointA = prb_offset;
start_symbol = nr_get_ssb_start_symbol(frame_parms,i);
int slot = start_symbol/14;
@@ -541,7 +541,7 @@ int main(int argc, char **argv)
for (aa=0; aa<gNB->frame_parms.nb_antennas_tx; aa++)
memset(gNB->common_vars.txdataF[0][aa], 0, frame_parms->samples_per_slot_wCP * sizeof(int32_t));
nr_common_signal_procedures (gNB,frame,slot, &msgDataTx.ssb_pdu[i]);
nr_common_signal_procedures (gNB,frame,slot, &ssb_pdu[i]);
int samp = frame_parms->get_samples_slot_timestamp(slot, frame_parms, 0);
for (aa=0; aa<gNB->frame_parms.nb_antennas_tx; aa++) {
@@ -744,7 +744,7 @@ int main(int argc, char **argv)
gNB->gNB_config.ssb_table.ssb_subcarrier_offset.value,
frame_parms->Lmax);
int payload_ret = (result.xtra_byte == xtra_byte);
nfapi_nr_dl_tti_ssb_pdu_rel15_t *pdu = &msgDataTx.ssb_pdu[ssb_index].ssb_pdu_rel15;
nfapi_nr_dl_tti_ssb_pdu_rel15_t *pdu = &ssb_pdu[ssb_index].ssb_pdu_rel15;
for (int i = 0; i < 3; i++)
payload_ret += (result.decoded_output[i] == ((pdu->bchPayload >> (8 * i)) & 0xff));
// printf("ret %d\n", payload_ret);
+3 -9
View File
@@ -60,7 +60,6 @@
#include "PHY/defs_nr_common.h"
#include "PHY/impl_defs_nr.h"
#include "PHY/phy_vars_nr_ue.h"
#include "SCHED_NR/fapi_nr_l1.h"
#include "SCHED_NR/sched_nr.h"
#include "SCHED_NR_UE/defs.h"
#include "SCHED_NR_UE/fapi_nr_ue_l1.h"
@@ -727,11 +726,6 @@ int main(int argc, char *argv[])
else
initNamedTpool(gNBthreads, &gNB->threadPool, true, "gNB-tpool");
processingData_L1tx_t *msgDataTx = malloc(sizeof(processingData_L1tx_t));
msgDataTx->slot = -1;
gNB->msgDataTx = msgDataTx;
//gNB_config = &gNB->gNB_config;
NR_UL_IND_t UL_INFO = {0};
UL_INFO.crc_ind.crc_list = UL_INFO.crc_pdu_list;
UL_INFO.rx_ind.pdu_list = UL_INFO.rx_pdu_list;
@@ -1284,6 +1278,9 @@ int main(int argc, char *argv[])
srs_pdu->beamforming.prg_size = 1;
}
/* load FAPI into RX of L1 */
nr_save_ul_tti_req(gNB, &Sched_INFO->UL_tti_req);
/// UE UL PDUs
UE->ul_harq_processes[harq_pid].round = round;
@@ -1291,9 +1288,6 @@ int main(int argc, char *argv[])
UE_proc.frame_tx = frame;
UE_proc.gNB_id = 0;
// prepare ULSCH/PUSCH reception
nr_schedule_response(Sched_INFO);
// --------- setting parameters for UE --------
nr_scheduled_response_t scheduled_response = {.ul_config = &ul_config, .phy_data = (void *)&phy_data};