Commit 4bd30075 authored by ue1's avatar ue1

removal of many debugging logs, added pscch/pssch statistics, TX/RX switching...

removal of many debugging logs, added pscch/pssch statistics, TX/RX switching time increase (3->4 slots
parent dad42400
...@@ -315,7 +315,7 @@ static void *NRUE_phy_stub_standalone_pnf_task(void *arg) ...@@ -315,7 +315,7 @@ static void *NRUE_phy_stub_standalone_pnf_task(void *arg)
uint8_t gNB_id = 0; uint8_t gNB_id = 0;
nr_uplink_indication_t ul_info; nr_uplink_indication_t ul_info;
int slots_per_frame = 20; //30 kHZ subcarrier spacing int slots_per_frame = 20; //30 kHZ subcarrier spacing
int slot_ahead = 2; // TODO: Make this dynamic int slot_ahead = 3; // TODO: Make this dynamic
ul_info.cc_id = CC_id; ul_info.cc_id = CC_id;
ul_info.gNB_index = gNB_id; ul_info.gNB_index = gNB_id;
ul_info.module_id = mod_id; ul_info.module_id = mod_id;
......
...@@ -76,9 +76,9 @@ int nr_ulsch_encoding(PHY_VARS_NR_UE *ue, ...@@ -76,9 +76,9 @@ int nr_ulsch_encoding(PHY_VARS_NR_UE *ue,
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_NR_UE_ULSCH_ENCODING, VCD_FUNCTION_IN); VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_NR_UE_ULSCH_ENCODING, VCD_FUNCTION_IN);
LOG_I(NR_PHY, "%s coding nb_rb %d, Nl = %d\n", pscch_pssch_pdu == NULL ? "ULSCH":"SLSCH",nb_rb, num_layers); LOG_D(NR_PHY, "%s coding nb_rb %d, Nl = %d\n", pscch_pssch_pdu == NULL ? "ULSCH":"SLSCH",nb_rb, num_layers);
LOG_I(NR_PHY, "%s coding A %d G %d mod_order %d Coderate %f\n", pscch_pssch_pdu == NULL ? "ULSCH" : "SLSCH",A, G, mod_order, Coderate); LOG_D(NR_PHY, "%s coding A %d G %d mod_order %d Coderate %f\n", pscch_pssch_pdu == NULL ? "ULSCH" : "SLSCH",A, G, mod_order, Coderate);
LOG_I(NR_PHY, "harq_pid %d harq_process->ndi %d, pusch_data.new_data_indicator %d\n", LOG_D(NR_PHY, "harq_pid %d harq_process->ndi %d, pusch_data.new_data_indicator %d\n",
harq_pid,harq_process->ndi,ndi); harq_pid,harq_process->ndi,ndi);
if (harq_process->first_tx == 1 || if (harq_process->first_tx == 1 ||
...@@ -240,7 +240,7 @@ int nr_ulsch_encoding(PHY_VARS_NR_UE *ue, ...@@ -240,7 +240,7 @@ int nr_ulsch_encoding(PHY_VARS_NR_UE *ue,
} }
LOG_I(PHY,"Rate Matching, Code segment %d (coded bits (G) %u, unpunctured/repeated bits per code segment %d, mod_order %d, nb_rb %d, rvidx %d)...\n", LOG_D(PHY,"Rate Matching, Code segment %d (coded bits (G) %u, unpunctured/repeated bits per code segment %d, mod_order %d, nb_rb %d, rvidx %d)...\n",
r, r,
G, G,
Kr*3, Kr*3,
......
...@@ -247,7 +247,7 @@ void nr_ue_ulsch_procedures(PHY_VARS_NR_UE *UE, ...@@ -247,7 +247,7 @@ void nr_ue_ulsch_procedures(PHY_VARS_NR_UE *UE,
uint32_t sci2_encoded_output[sci2_re*2]; uint32_t sci2_encoded_output[sci2_re*2];
if (pscch_pssch_pdu) { if (pscch_pssch_pdu) {
LOG_I(NR_PHY,"Generating SCI2/PSSCH with %d RE, payload %llx\n",sci2_re,*(unsigned long long*)pscch_pssch_pdu->sci2_payload); LOG_D(NR_PHY,"Generating SCI2/PSSCH with %d RE, payload %llx\n",sci2_re,*(unsigned long long*)pscch_pssch_pdu->sci2_payload);
// do SCI2 encoding // do SCI2 encoding
polar_encoder_fast((uint64_t*)pscch_pssch_pdu->sci2_payload, (void*)sci2_encoded_output, NULL,0, 1, polar_encoder_fast((uint64_t*)pscch_pssch_pdu->sci2_payload, (void*)sci2_encoded_output, NULL,0, 1,
NR_POLAR_SCI2_MESSAGE_TYPE, NR_POLAR_SCI2_MESSAGE_TYPE,
......
...@@ -124,6 +124,47 @@ typedef struct SL_NR_SYNC_PARAMS { ...@@ -124,6 +124,47 @@ typedef struct SL_NR_SYNC_PARAMS {
} SL_NR_SYNC_PARAMS_t; } SL_NR_SYNC_PARAMS_t;
typedef struct SL_NR_UE_PSSCH {
// AVG POWER OF PSSCH DMRS in dB/RE
int16_t rsrp_dB_per_RE;
// AVG POWER OF PSSCH DMRS in dBm/RE
int16_t rsrp_dBm_per_RE;
// STATS - CRC Errors observed during PSSCH reception (per HARQ round)
uint16_t rx_errors[8];
// STATS - CRC Errors observed during PSSCH SCI2 reception
uint16_t rx_sci2_errors;
// STATS - Receptions with CRC OK
uint16_t rx_ok;
// STATS - Receptions with CRC OK
uint16_t rx_sci2_ok;
// STATS - transmissions of PSSCH by the UE
uint16_t num_pssch_tx;
// STATS - transmissions of PSSCH by the UE
uint16_t num_pssch_sci2_tx;
} SL_NR_UE_PSSCH_t;
typedef struct SL_NR_UE_PSCCH {
// AVG POWER OF PSCCH DMRS in dB/RE
int16_t rsrp_dB_per_RE;
// AVG POWER OF PSCCH DMRS in dBm/RE
int16_t rsrp_dBm_per_RE;
// STATS - Receptions with CRC OK
uint16_t rx_ok;
// STATS - transmissions of PSBCH by the UE
uint16_t num_pscch_tx;
} SL_NR_UE_PSCCH_t;
typedef struct SL_NR_UE_PSBCH { typedef struct SL_NR_UE_PSBCH {
// AVG POWER OF PSBCH DMRS in dB/RE // AVG POWER OF PSBCH DMRS in dB/RE
...@@ -148,9 +189,15 @@ typedef struct sl_nr_ue_phy_params { ...@@ -148,9 +189,15 @@ typedef struct sl_nr_ue_phy_params {
SL_NR_SYNC_PARAMS_t sync_params; SL_NR_SYNC_PARAMS_t sync_params;
// Sidelink PHY PARAMETERS USED FOR PSBCH reception/Txn // sidelink phy parameters used for psbch reception/txn
SL_NR_UE_PSBCH_t psbch; SL_NR_UE_PSBCH_t psbch;
// sidelink phy parameters used for pscch reception/txn
SL_NR_UE_PSCCH_t pscch;
// sidelink phy parameters used for pssch reception/txn
SL_NR_UE_PSSCH_t pssch;
//Configuration parameters from MAC //Configuration parameters from MAC
sl_nr_phy_config_request_t sl_config; sl_nr_phy_config_request_t sl_config;
...@@ -164,4 +211,4 @@ typedef struct sl_nr_ue_phy_params { ...@@ -164,4 +211,4 @@ typedef struct sl_nr_ue_phy_params {
} sl_nr_ue_phy_params_t; } sl_nr_ue_phy_params_t;
#endif #endif
\ No newline at end of file
...@@ -270,7 +270,7 @@ ...@@ -270,7 +270,7 @@
/* FFS_NR_TODO it defines ue capability which is the number of slots */ /* FFS_NR_TODO it defines ue capability which is the number of slots */
/* - between reception of pdsch and tarnsmission of its acknowlegment */ /* - between reception of pdsch and tarnsmission of its acknowlegment */
/* - between reception of un uplink grant and its related transmission */ /* - between reception of un uplink grant and its related transmission */
#define NR_UE_CAPABILITY_SLOT_RX_TO_TX (3) #define NR_UE_CAPABILITY_SLOT_RX_TO_TX (4)
#ifndef NO_RAT_NR #ifndef NO_RAT_NR
#define DURATION_RX_TO_TX (NR_UE_CAPABILITY_SLOT_RX_TO_TX) /* for NR this will certainly depends to such UE capability which is not yet defined */ #define DURATION_RX_TO_TX (NR_UE_CAPABILITY_SLOT_RX_TO_TX) /* for NR this will certainly depends to such UE capability which is not yet defined */
......
...@@ -712,12 +712,12 @@ int8_t sl_handle_scheduled_response(nr_scheduled_response_t *scheduled_response) ...@@ -712,12 +712,12 @@ int8_t sl_handle_scheduled_response(nr_scheduled_response_t *scheduled_response)
case SL_NR_CONFIG_TYPE_RX_PSSCH_SCI: case SL_NR_CONFIG_TYPE_RX_PSSCH_SCI:
phy_data->sl_rx_action = SL_NR_CONFIG_TYPE_RX_PSSCH_SCI; phy_data->sl_rx_action = SL_NR_CONFIG_TYPE_RX_PSSCH_SCI;
phy_data->nr_sl_pssch_sci_pdu = sl_rx_config->sl_rx_config_list[0].rx_sci2_config_pdu; phy_data->nr_sl_pssch_sci_pdu = sl_rx_config->sl_rx_config_list[0].rx_sci2_config_pdu;
LOG_I(NR_PHY, "Recvd CONFIG_TYPE_RX_PSSCH\n"); LOG_D(NR_PHY, "Recvd CONFIG_TYPE_RX_PSSCH\n");
break; break;
case SL_NR_CONFIG_TYPE_RX_PSSCH_SLSCH: case SL_NR_CONFIG_TYPE_RX_PSSCH_SLSCH:
phy_data->sl_rx_action = SL_NR_CONFIG_TYPE_RX_PSSCH_SLSCH; phy_data->sl_rx_action = SL_NR_CONFIG_TYPE_RX_PSSCH_SLSCH;
phy_data->nr_sl_pssch_pdu = sl_rx_config->sl_rx_config_list[0].rx_pssch_config_pdu; phy_data->nr_sl_pssch_pdu = sl_rx_config->sl_rx_config_list[0].rx_pssch_config_pdu;
LOG_I(NR_PHY, "Recvd CONFIG_TYPE_RX_PSSCH\n"); LOG_D(NR_PHY, "Recvd CONFIG_TYPE_RX_PSSCH\n");
break; break;
default: default:
AssertFatal(0,"Incorrect sl_rx config req pdutype \n"); AssertFatal(0,"Incorrect sl_rx config req pdutype \n");
...@@ -751,8 +751,8 @@ int8_t sl_handle_scheduled_response(nr_scheduled_response_t *scheduled_response) ...@@ -751,8 +751,8 @@ int8_t sl_handle_scheduled_response(nr_scheduled_response_t *scheduled_response)
case SL_NR_CONFIG_TYPE_TX_PSCCH_PSSCH: case SL_NR_CONFIG_TYPE_TX_PSCCH_PSSCH:
phy_data_tx->sl_tx_action = SL_NR_CONFIG_TYPE_TX_PSCCH_PSSCH; phy_data_tx->sl_tx_action = SL_NR_CONFIG_TYPE_TX_PSCCH_PSSCH;
phy_data_tx->nr_sl_pssch_pscch_pdu = sl_tx_config->tx_config_list[0].tx_pscch_pssch_config_pdu; phy_data_tx->nr_sl_pssch_pscch_pdu = sl_tx_config->tx_config_list[0].tx_pscch_pssch_config_pdu;
LOG_I(NR_PHY,"sl_handle_scheduled_response: Received CONFIG_TYPE_TX_PSCCH_PSSCH, PSCCH startRB %d, PSCCH numRB %d\n",phy_data_tx->nr_sl_pssch_pscch_pdu.startrb,phy_data_tx->nr_sl_pssch_pscch_pdu.pscch_numrbs); LOG_D(NR_PHY,"sl_handle_scheduled_response: Received CONFIG_TYPE_TX_PSCCH_PSSCH, PSCCH startRB %d, PSCCH numRB %d\n",phy_data_tx->nr_sl_pssch_pscch_pdu.startrb,phy_data_tx->nr_sl_pssch_pscch_pdu.pscch_numrbs);
LOG_I(NR_PHY,"format 1A length %d :%llx, format 2x length %d : %llx, PSSCH mcs %d, PSSCH tbslrm %d\n",phy_data_tx->nr_sl_pssch_pscch_pdu.pscch_sci_payload_len, LOG_D(NR_PHY,"format 1A length %d :%llx, format 2x length %d : %llx, PSSCH mcs %d, PSSCH tbslrm %d\n",phy_data_tx->nr_sl_pssch_pscch_pdu.pscch_sci_payload_len,
(unsigned long long)*phy_data_tx->nr_sl_pssch_pscch_pdu.pscch_sci_payload, (unsigned long long)*phy_data_tx->nr_sl_pssch_pscch_pdu.pscch_sci_payload,
phy_data_tx->nr_sl_pssch_pscch_pdu.sci2_payload_len, phy_data_tx->nr_sl_pssch_pscch_pdu.sci2_payload_len,
(unsigned long long)*phy_data_tx->nr_sl_pssch_pscch_pdu.sci2_payload, (unsigned long long)*phy_data_tx->nr_sl_pssch_pscch_pdu.sci2_payload,
......
...@@ -166,7 +166,7 @@ int nr_slsch_procedures(PHY_VARS_NR_UE *ue, int frame_rx, int slot_rx, int SLSCH ...@@ -166,7 +166,7 @@ int nr_slsch_procedures(PHY_VARS_NR_UE *ue, int frame_rx, int slot_rx, int SLSCH
number_dmrs_symbols, // number of dmrs symbols irrespective of single or double symbol dmrs number_dmrs_symbols, // number of dmrs symbols irrespective of single or double symbol dmrs
pssch_pdu->mod_order, pssch_pdu->mod_order,
pssch_pdu->num_layers); pssch_pdu->num_layers);
LOG_I(NR_PHY,"rb_size %d, number_symbols %d, nb_re_dmrs %d, dmrs symbol positions %d, number_dmrs_symbols %d, qam_mod_order %d, nrOfLayer %d\n", LOG_D(NR_PHY,"rb_size %d, number_symbols %d, nb_re_dmrs %d, dmrs symbol positions %d, number_dmrs_symbols %d, qam_mod_order %d, nrOfLayer %d\n",
rb_size, rb_size,
number_symbols, number_symbols,
nb_re_dmrs, nb_re_dmrs,
...@@ -246,7 +246,7 @@ void nr_postDecode_slsch(PHY_VARS_NR_UE *UE, notifiedFIFO_elt_t *req,UE_nr_rxtx_ ...@@ -246,7 +246,7 @@ void nr_postDecode_slsch(PHY_VARS_NR_UE *UE, notifiedFIFO_elt_t *req,UE_nr_rxtx_
nr_sidelink_indication_t sl_indication; nr_sidelink_indication_t sl_indication;
slsch_status_t slsch_status; slsch_status_t slsch_status;
if (!check_abort(&slsch_harq->abort_decode) && !UE->pssch_vars[rdata->ulsch_id].DTX) { if (!check_abort(&slsch_harq->abort_decode) && !UE->pssch_vars[rdata->ulsch_id].DTX) {
LOG_I(NR_PHY, LOG_D(NR_PHY,
"[UE] SLSCH: Setting ACK for SFN/SF %d.%d (pid %d, ndi %d, status %d, round %d, TBS %d, Max interation " "[UE] SLSCH: Setting ACK for SFN/SF %d.%d (pid %d, ndi %d, status %d, round %d, TBS %d, Max interation "
"(all seg) %d)\n", "(all seg) %d)\n",
slsch->frame, slsch->frame,
...@@ -259,12 +259,12 @@ void nr_postDecode_slsch(PHY_VARS_NR_UE *UE, notifiedFIFO_elt_t *req,UE_nr_rxtx_ ...@@ -259,12 +259,12 @@ void nr_postDecode_slsch(PHY_VARS_NR_UE *UE, notifiedFIFO_elt_t *req,UE_nr_rxtx_
rdata->decodeIterations); rdata->decodeIterations);
slsch->active = false; slsch->active = false;
slsch_harq->round = 0; slsch_harq->round = 0;
LOG_I(NR_PHY, "SLSCH received ok \n"); LOG_D(NR_PHY, "SLSCH received ok \n");
slsch_status.rdata = rdata; slsch_status.rdata = rdata;
slsch_status.rxok = true; slsch_status.rxok = true;
//dumpsig=1; //dumpsig=1;
} else { } else {
LOG_I(NR_PHY, LOG_D(NR_PHY,
"[UE] SLSCH: Setting NAK for SFN/SF %d/%d (pid %d, ndi %d, status %d, round %d, RV %d, prb_start %d, prb_size %d, " "[UE] SLSCH: Setting NAK for SFN/SF %d/%d (pid %d, ndi %d, status %d, round %d, RV %d, prb_start %d, prb_size %d, "
"TBS %d) r %d\n", "TBS %d) r %d\n",
slsch->frame, slsch->frame,
...@@ -279,7 +279,7 @@ void nr_postDecode_slsch(PHY_VARS_NR_UE *UE, notifiedFIFO_elt_t *req,UE_nr_rxtx_ ...@@ -279,7 +279,7 @@ void nr_postDecode_slsch(PHY_VARS_NR_UE *UE, notifiedFIFO_elt_t *req,UE_nr_rxtx_
slsch_harq->TBS, slsch_harq->TBS,
r); r);
slsch->handled = 1; slsch->handled = 1;
LOG_I(NR_PHY, "SLSCH %d in error\n",rdata->ulsch_id); LOG_D(NR_PHY, "SLSCH %d in error\n",rdata->ulsch_id);
slsch_status.rdata = rdata; slsch_status.rdata = rdata;
slsch_status.rxok = false; slsch_status.rxok = false;
// dumpsig=1; // dumpsig=1;
...@@ -405,6 +405,36 @@ void psbch_pscch_pssch_processing(PHY_VARS_NR_UE *ue, ...@@ -405,6 +405,36 @@ void psbch_pscch_pssch_processing(PHY_VARS_NR_UE *ue,
const uint32_t rxdataF_sz = fp->samples_per_slot_wCP; const uint32_t rxdataF_sz = fp->samples_per_slot_wCP;
__attribute__ ((aligned(32))) c16_t rxdataF[fp->nb_antennas_rx][rxdataF_sz]; __attribute__ ((aligned(32))) c16_t rxdataF[fp->nb_antennas_rx][rxdataF_sz];
if ((frame_rx&127) == 0 && nr_slot_rx==19) {
LOG_I(NR_PHY,"============================================\n");
LOG_I(NR_PHY,"%s[UE%d] %d:%d PSBCH Stats: TX %d, RX ok %d, RX not ok %d\n",KGRN,
ue->Mod_id, frame_rx, nr_slot_rx,
sl_phy_params->psbch.num_psbch_tx,
sl_phy_params->psbch.rx_ok,
sl_phy_params->psbch.rx_errors);
LOG_I(NR_PHY,"%s[UE%d] %d:%d PSCCH Stats: TX %d, RX ok %d\n",KGRN,
ue->Mod_id, frame_rx, nr_slot_rx,
sl_phy_params->pscch.num_pscch_tx,
sl_phy_params->pscch.rx_ok);
LOG_I(NR_PHY,"%s[UE%d] %d:%d PSSCH/SCI2 Stats: TX %d, RX ok %d, RX not ok %d\n",KGRN,
ue->Mod_id, frame_rx, nr_slot_rx,
sl_phy_params->pssch.num_pssch_sci2_tx,
sl_phy_params->pssch.rx_sci2_ok,
sl_phy_params->pssch.rx_sci2_errors);
LOG_I(NR_PHY,"%s[UE%d] %d:%d PSSCH Stats: TX %d, RX ok %d, RX not ok (%d/%d/%d/%d)\n",KGRN,
ue->Mod_id, frame_rx, nr_slot_rx,
sl_phy_params->pssch.num_pssch_tx,
sl_phy_params->pssch.rx_ok,
sl_phy_params->pssch.rx_errors[0],
sl_phy_params->pssch.rx_errors[1],
sl_phy_params->pssch.rx_errors[2],
sl_phy_params->pssch.rx_errors[3]);
LOG_I(NR_PHY,"============================================\n");
}
if (phy_data->sl_rx_action == SL_NR_CONFIG_TYPE_RX_PSBCH){ if (phy_data->sl_rx_action == SL_NR_CONFIG_TYPE_RX_PSBCH){
const int estimateSz = fp->symbols_per_slot * fp->ofdm_symbol_size; const int estimateSz = fp->symbols_per_slot * fp->ofdm_symbol_size;
...@@ -474,17 +504,6 @@ void psbch_pscch_pssch_processing(PHY_VARS_NR_UE *ue, ...@@ -474,17 +504,6 @@ void psbch_pscch_pssch_processing(PHY_VARS_NR_UE *ue,
// nr_ue_rrc_measurements(ue, proc, rxdataF); // nr_ue_rrc_measurements(ue, proc, rxdataF);
//VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_SLOT_FEP_PSBCH, VCD_FUNCTION_OUT); //VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_SLOT_FEP_PSBCH, VCD_FUNCTION_OUT);
if (frame_rx%128 == 0) {
LOG_I(NR_PHY,"============================================\n");
LOG_I(NR_PHY,"%s[UE%d] %d:%d PSBCH Stats: TX %d, RX ok %d, RX not ok %d\n",KGRN,
ue->Mod_id, frame_rx, nr_slot_rx,
sl_phy_params->psbch.num_psbch_tx,
sl_phy_params->psbch.rx_ok,
sl_phy_params->psbch.rx_errors);
LOG_I(NR_PHY,"============================================\n");
}
} }
else if (phy_data->sl_rx_action == SL_NR_CONFIG_TYPE_RX_PSCCH && !get_nrUE_params()->sync_ref){ else if (phy_data->sl_rx_action == SL_NR_CONFIG_TYPE_RX_PSCCH && !get_nrUE_params()->sync_ref){
...@@ -614,7 +633,7 @@ void psbch_pscch_pssch_processing(PHY_VARS_NR_UE *ue, ...@@ -614,7 +633,7 @@ void psbch_pscch_pssch_processing(PHY_VARS_NR_UE *ue,
} }
if (dB_fixed_x10(pssch_vars->ulsch_power_tot) < dB_fixed_x10(pssch_vars->ulsch_noise_power_tot) + ue->pssch_thres) { if (dB_fixed_x10(pssch_vars->ulsch_power_tot) < dB_fixed_x10(pssch_vars->ulsch_noise_power_tot) + ue->pssch_thres) {
LOG_I(NR_PHY, LOG_D(NR_PHY,
"PSSCH not detected in %d.%d (%d,%d,%d)\n", "PSSCH not detected in %d.%d (%d,%d,%d)\n",
frame_rx, frame_rx,
nr_slot_rx, nr_slot_rx,
...@@ -629,7 +648,7 @@ void psbch_pscch_pssch_processing(PHY_VARS_NR_UE *ue, ...@@ -629,7 +648,7 @@ void psbch_pscch_pssch_processing(PHY_VARS_NR_UE *ue,
//pssch_DTX++; //pssch_DTX++;
// continue; // continue;
} else { } else {
LOG_I(NR_PHY, LOG_D(NR_PHY,
"PSSCH detected in %d.%d (%d,%d,%d)\n", "PSSCH detected in %d.%d (%d,%d,%d)\n",
frame_rx, frame_rx,
nr_slot_rx, nr_slot_rx,
...@@ -681,26 +700,18 @@ int phy_procedures_nrUE_SL_TX(PHY_VARS_NR_UE *ue, ...@@ -681,26 +700,18 @@ int phy_procedures_nrUE_SL_TX(PHY_VARS_NR_UE *ue,
nr_tx_psbch(ue, frame_tx, slot_tx, psbch_vars, txdataF); nr_tx_psbch(ue, frame_tx, slot_tx, psbch_vars, txdataF);
sl_phy_params->psbch.num_psbch_tx ++; sl_phy_params->psbch.num_psbch_tx ++;
if (frame_tx%64 == 0) {
LOG_I(NR_PHY,"============================================\n");
LOG_I(NR_PHY,"[UE%d] %d:%d PSBCH Stats: TX %d, RX ok %d, RX not ok %d\n",
ue->Mod_id, frame_tx, slot_tx,
sl_phy_params->psbch.num_psbch_tx,
sl_phy_params->psbch.rx_ok,
sl_phy_params->psbch.rx_errors);
LOG_I(NR_PHY,"============================================\n");
}
tx_action = 1; tx_action = 1;
} }
else if (phy_data->sl_tx_action == SL_NR_CONFIG_TYPE_TX_PSCCH_PSSCH) { else if (phy_data->sl_tx_action == SL_NR_CONFIG_TYPE_TX_PSCCH_PSSCH) {
LOG_I(NR_PHY,"Generating PSCCH (%d.%d)\n",frame_tx,slot_tx); LOG_D(NR_PHY,"Generating PSCCH (%d.%d)\n",frame_tx,slot_tx);
phy_data->pscch_Nid = nr_generate_sci1(ue,txdataF[0],fp,AMP,slot_tx,&phy_data->nr_sl_pssch_pscch_pdu) &0xFFFF; phy_data->pscch_Nid = nr_generate_sci1(ue,txdataF[0],fp,AMP,slot_tx,&phy_data->nr_sl_pssch_pscch_pdu) &0xFFFF;
nr_ue_ulsch_procedures(ue,0,frame_tx,slot_tx,0,phy_data,txdataF); nr_ue_ulsch_procedures(ue,0,frame_tx,slot_tx,0,phy_data,txdataF);
sl_phy_params->pscch.num_pscch_tx ++;
sl_phy_params->pssch.num_pssch_sci2_tx ++;
sl_phy_params->pssch.num_pssch_tx ++;
tx_action = 1; tx_action = 1;
} }
else if (phy_data->sl_tx_action == SL_NR_CONFIG_TYPE_TX_PSFCH) { else if (phy_data->sl_tx_action == SL_NR_CONFIG_TYPE_TX_PSFCH) {
......
...@@ -41,6 +41,7 @@ ...@@ -41,6 +41,7 @@
/* IF */ /* IF */
#include "NR_IF_Module.h" #include "NR_IF_Module.h"
#include "fapi_nr_ue_interface.h" #include "fapi_nr_ue_interface.h"
#include "time_meas.h"
/* MAC */ /* MAC */
#include "LAYER2/NR_MAC_COMMON/nr_mac.h" #include "LAYER2/NR_MAC_COMMON/nr_mac.h"
...@@ -619,6 +620,7 @@ typedef struct { ...@@ -619,6 +620,7 @@ typedef struct {
nr_sci_pdu_t sci1_pdu; nr_sci_pdu_t sci1_pdu;
nr_sci_pdu_t sci2_pdu; nr_sci_pdu_t sci2_pdu;
uint8_t slsch_payload[16384]; uint8_t slsch_payload[16384];
time_stats_t rlc_data_req;
} NR_UE_MAC_INST_t; } NR_UE_MAC_INST_t;
/*@}*/ /*@}*/
......
...@@ -94,6 +94,7 @@ NR_UE_MAC_INST_t * nr_l2_init_ue(NR_UE_RRC_INST_t* rrc_inst) { ...@@ -94,6 +94,7 @@ NR_UE_MAC_INST_t * nr_l2_init_ue(NR_UE_RRC_INST_t* rrc_inst) {
} }
} }
reset_meas(&nr_ue_mac_inst->rlc_data_req);
return (nr_ue_mac_inst); return (nr_ue_mac_inst);
} }
......
...@@ -44,6 +44,8 @@ bool nr_schedule_slsch(int frameP,int slotP, nr_sci_pdu_t *sci_pdu,nr_sci_pdu_t ...@@ -44,6 +44,8 @@ bool nr_schedule_slsch(int frameP,int slotP, nr_sci_pdu_t *sci_pdu,nr_sci_pdu_t
mac_rlc_status_resp_t rlc_status = mac_rlc_status_ind(0, 0, 0,frameP,slotP,ENB_FLAG_NO,MBMS_FLAG_NO, 4, 0, 0); mac_rlc_status_resp_t rlc_status = mac_rlc_status_ind(0, 0, 0,frameP,slotP,ENB_FLAG_NO,MBMS_FLAG_NO, 4, 0, 0);
// rlc_status.bytes_in_buffer = 0;
*slsch_pdu_length_max = 0;
if (rlc_status.bytes_in_buffer > 0) { if (rlc_status.bytes_in_buffer > 0) {
// Fill SCI1A // Fill SCI1A
......
...@@ -3253,11 +3253,13 @@ bool nr_ue_sl_pssch_scheduler(NR_UE_MAC_INST_t *mac, ...@@ -3253,11 +3253,13 @@ bool nr_ue_sl_pssch_scheduler(NR_UE_MAC_INST_t *mac,
int lcid = 4; int lcid = 4;
int sdu_length = 0; int sdu_length = 0;
if ((frame & 127) == 0 && slot == 0) {
print_meas(&mac->rlc_data_req,"rlc_data_req",NULL,NULL);
}
if (sl_ind->slot_type != SIDELINK_SLOT_TYPE_TX) return false; if (sl_ind->slot_type != SIDELINK_SLOT_TYPE_TX) return false;
/*
if (slot > 9 && get_nrUE_params()->sync_ref) return false; if (slot > 9 && get_nrUE_params()->sync_ref) return false;
/*
if (!get_nrUE_params()->sync_ref) return false; if (!get_nrUE_params()->sync_ref) return false;
if ((frame&127) > 0) return false; if ((frame&127) > 0) return false;
...@@ -3292,13 +3294,13 @@ bool nr_ue_sl_pssch_scheduler(NR_UE_MAC_INST_t *mac, ...@@ -3292,13 +3294,13 @@ bool nr_ue_sl_pssch_scheduler(NR_UE_MAC_INST_t *mac,
int buflen = tx_config->tx_config_list[0].tx_pscch_pssch_config_pdu.tb_size; int buflen = tx_config->tx_config_list[0].tx_pscch_pssch_config_pdu.tb_size;
NR_UE_MAC_CE_INFO mac_ce_info; NR_UE_MAC_CE_INFO mac_ce_info = {0};
NR_UE_MAC_CE_INFO *mac_ce_p=&mac_ce_info; NR_UE_MAC_CE_INFO *mac_ce_p=&mac_ce_info;
mac_ce_p->bsr_len = 0; mac_ce_p->bsr_len = 0;
mac_ce_p->bsr_ce_len = 0; mac_ce_p->bsr_ce_len = 0;
mac_ce_p->bsr_header_len = 0; mac_ce_p->bsr_header_len = 0;
mac_ce_p->phr_len = 0; mac_ce_p->phr_len = 0;
LOG_I(NR_MAC, "[UE%d] TTI-%d:%d TX PSCCH_PSSCH REQ TBS %d\n", sl_ind->module_id,frame, slot,buflen); LOG_D(NR_MAC, "[UE%d] TTI-%d:%d TX PSCCH_PSSCH REQ TBS %d\n", sl_ind->module_id,frame, slot,buflen);
//nr_ue_get_sdu_mac_ce_pre updates all mac_ce related header field related to length //nr_ue_get_sdu_mac_ce_pre updates all mac_ce related header field related to length
...@@ -3308,15 +3310,6 @@ bool nr_ue_sl_pssch_scheduler(NR_UE_MAC_INST_t *mac, ...@@ -3308,15 +3310,6 @@ bool nr_ue_sl_pssch_scheduler(NR_UE_MAC_INST_t *mac,
int buflen_remain = buflen - (mac_ce_p->total_mac_pdu_header_len + mac_ce_p->sdu_length_total + sh_size); int buflen_remain = buflen - (mac_ce_p->total_mac_pdu_header_len + mac_ce_p->sdu_length_total + sh_size);
LOG_I(NR_MAC, "In %s: [UE] [%d.%d] SL-DXCH -> SLSCH, RLC with LCID 0x%02x (TBS %d bytes, sdu_length_total %d bytes, MAC header len %d bytes, buflen_remain %d bytes)\n",
__FUNCTION__,
slot,
frame,
4,
buflen,
mac_ce_p->sdu_length_total,
mac_ce_p->tot_mac_ce_len,
buflen_remain);
int num_sdus=0; int num_sdus=0;
while (buflen_remain > 0){ while (buflen_remain > 0){
...@@ -3325,6 +3318,7 @@ bool nr_ue_sl_pssch_scheduler(NR_UE_MAC_INST_t *mac, ...@@ -3325,6 +3318,7 @@ bool nr_ue_sl_pssch_scheduler(NR_UE_MAC_INST_t *mac,
pdu += sh_size; pdu += sh_size;
start_meas(&mac->rlc_data_req);
sdu_length = mac_rlc_data_req(0, sdu_length = mac_rlc_data_req(0,
0, 0,
0, 0,
...@@ -3337,6 +3331,7 @@ bool nr_ue_sl_pssch_scheduler(NR_UE_MAC_INST_t *mac, ...@@ -3337,6 +3331,7 @@ bool nr_ue_sl_pssch_scheduler(NR_UE_MAC_INST_t *mac,
0, 0,
0); 0);
stop_meas(&mac->rlc_data_req);
AssertFatal(buflen_remain >= sdu_length, "In %s: LCID = 0x%02x RLC has segmented %d bytes but MAC has max %d remaining bytes\n", AssertFatal(buflen_remain >= sdu_length, "In %s: LCID = 0x%02x RLC has segmented %d bytes but MAC has max %d remaining bytes\n",
__FUNCTION__, __FUNCTION__,
lcid, lcid,
......
...@@ -352,7 +352,7 @@ void fill_pssch_pscch_pdu(sl_nr_tx_config_pscch_pssch_pdu_t *nr_sl_pssch_pscch_p ...@@ -352,7 +352,7 @@ void fill_pssch_pscch_pdu(sl_nr_tx_config_pscch_pssch_pdu_t *nr_sl_pssch_pscch_p
N_RE,1+(sci_pdu->number_of_dmrs_port&1))>>3; N_RE,1+(sci_pdu->number_of_dmrs_port&1))>>3;
nr_sl_pssch_pscch_pdu->mcs = sci_pdu->mcs; nr_sl_pssch_pscch_pdu->mcs = sci_pdu->mcs;
nr_sl_pssch_pscch_pdu->num_layers = sci_pdu->number_of_dmrs_port+1; nr_sl_pssch_pscch_pdu->num_layers = sci_pdu->number_of_dmrs_port+1;
LOG_I(NR_MAC,"PSSCH: mcs %d, coderate %d, Nl %d => tbs %d\n",sci_pdu->mcs,nr_sl_pssch_pscch_pdu->target_coderate,nr_sl_pssch_pscch_pdu->num_layers,nr_sl_pssch_pscch_pdu->tb_size); LOG_D(NR_MAC,"PSSCH: mcs %d, coderate %d, Nl %d => tbs %d\n",sci_pdu->mcs,nr_sl_pssch_pscch_pdu->target_coderate,nr_sl_pssch_pscch_pdu->num_layers,nr_sl_pssch_pscch_pdu->tb_size);
nr_sl_pssch_pscch_pdu->tbslbrm = nr_compute_tbslbrm(mcs_tb_ind,NRRIV2BW(sl_bwp->sl_BWP_Generic_r16->sl_BWP_r16->locationAndBandwidth,273),nr_sl_pssch_pscch_pdu->num_layers); nr_sl_pssch_pscch_pdu->tbslbrm = nr_compute_tbslbrm(mcs_tb_ind,NRRIV2BW(sl_bwp->sl_BWP_Generic_r16->sl_BWP_r16->locationAndBandwidth,273),nr_sl_pssch_pscch_pdu->num_layers);
nr_sl_pssch_pscch_pdu->mcs_table=mcs_tb_ind; nr_sl_pssch_pscch_pdu->mcs_table=mcs_tb_ind;
nr_sl_pssch_pscch_pdu->rv_index = sci2_pdu->rv_index; nr_sl_pssch_pscch_pdu->rv_index = sci2_pdu->rv_index;
...@@ -597,11 +597,11 @@ int nr_ue_process_sci1_indication_pdu(NR_UE_MAC_INST_t *mac,module_id_t mod_id,f ...@@ -597,11 +597,11 @@ int nr_ue_process_sci1_indication_pdu(NR_UE_MAC_INST_t *mac,module_id_t mod_id,f
const NR_SL_BWP_ConfigCommon_r16_t *sl_bwp = mac->sl_bwp; const NR_SL_BWP_ConfigCommon_r16_t *sl_bwp = mac->sl_bwp;
const NR_SL_ResourcePool_r16_t *sl_res_pool = mac->sl_rx_res_pool; const NR_SL_ResourcePool_r16_t *sl_res_pool = mac->sl_rx_res_pool;
LOG_I(NR_MAC,"Received sci indication (sci format %d, Nid %x, subChannelIndex %d, payloadSize %d,payload %llx)\n", LOG_D(NR_MAC,"Received sci indication (sci format %d, Nid %x, subChannelIndex %d, payloadSize %d,payload %llx)\n",
sci->sci_format_type,sci->Nid,sci->subch_index,sci->sci_payloadlen,*(unsigned long long*)sci->sci_payloadBits); sci->sci_format_type,sci->Nid,sci->subch_index,sci->sci_payloadlen,*(unsigned long long*)sci->sci_payloadBits);
AssertFatal(sci->sci_format_type == SL_SCI_FORMAT_1A_ON_PSCCH, "need to have format 1A here only\n"); AssertFatal(sci->sci_format_type == SL_SCI_FORMAT_1A_ON_PSCCH, "need to have format 1A here only\n");
extract_pscch_pdu((uint64_t *)sci->sci_payloadBits, sci->sci_payloadlen,sl_bwp, sl_res_pool, sci_pdu); extract_pscch_pdu((uint64_t *)sci->sci_payloadBits, sci->sci_payloadlen,sl_bwp, sl_res_pool, sci_pdu);
LOG_I(NR_MAC,"SCI1A: frequency_resource %d, time_resource %d, dmrs_pattern %d, beta_offset_indicator %d, mcs %d, number_of_dmrs_port %d, 2nd stage SCI format %d\n", LOG_D(NR_MAC,"SCI1A: frequency_resource %d, time_resource %d, dmrs_pattern %d, beta_offset_indicator %d, mcs %d, number_of_dmrs_port %d, 2nd stage SCI format %d\n",
sci_pdu->frequency_resource_assignment.val,sci_pdu->time_resource_assignment.val,sci_pdu->dmrs_pattern.val,sci_pdu->beta_offset_indicator,sci_pdu->mcs,sci_pdu->number_of_dmrs_port,sci_pdu->second_stage_sci_format); sci_pdu->frequency_resource_assignment.val,sci_pdu->time_resource_assignment.val,sci_pdu->dmrs_pattern.val,sci_pdu->beta_offset_indicator,sci_pdu->mcs,sci_pdu->number_of_dmrs_port,sci_pdu->second_stage_sci_format);
// send schedule response // send schedule response
...@@ -622,7 +622,7 @@ int nr_ue_process_sci1_indication_pdu(NR_UE_MAC_INST_t *mac,module_id_t mod_id,f ...@@ -622,7 +622,7 @@ int nr_ue_process_sci1_indication_pdu(NR_UE_MAC_INST_t *mac,module_id_t mod_id,f
memset(&scheduled_response,0, sizeof(nr_scheduled_response_t)); memset(&scheduled_response,0, sizeof(nr_scheduled_response_t));
fill_scheduled_response(&scheduled_response,NULL,NULL,NULL,&rx_config,NULL,mod_id,0,frame,slot,phy_data); fill_scheduled_response(&scheduled_response,NULL,NULL,NULL,&rx_config,NULL,mod_id,0,frame,slot,phy_data);
LOG_I(NR_MAC, "[UE%d] TTI-%d:%d RX PSSCH_SCI REQ \n", mod_id,frame, slot); LOG_D(NR_MAC, "[UE%d] TTI-%d:%d RX PSSCH_SCI REQ \n", mod_id,frame, slot);
if ((mac->if_module != NULL) && (mac->if_module->scheduled_response != NULL)) if ((mac->if_module != NULL) && (mac->if_module->scheduled_response != NULL))
mac->if_module->scheduled_response(&scheduled_response); mac->if_module->scheduled_response(&scheduled_response);
return 1; return 1;
...@@ -776,11 +776,11 @@ int nr_ue_process_sci2_indication_pdu(NR_UE_MAC_INST_t *mac,module_id_t mod_id,f ...@@ -776,11 +776,11 @@ int nr_ue_process_sci2_indication_pdu(NR_UE_MAC_INST_t *mac,module_id_t mod_id,f
nr_sci_pdu_t *sci_pdu = &mac->sci_pdu_rx; //&mac->def_sci_pdu[slot][sci->sci_format_type]; nr_sci_pdu_t *sci_pdu = &mac->sci_pdu_rx; //&mac->def_sci_pdu[slot][sci->sci_format_type];
const NR_SL_BWP_ConfigCommon_r16_t *sl_bwp = mac->sl_bwp; const NR_SL_BWP_ConfigCommon_r16_t *sl_bwp = mac->sl_bwp;
const NR_SL_ResourcePool_r16_t *sl_res_pool = mac->sl_rx_res_pool; const NR_SL_ResourcePool_r16_t *sl_res_pool = mac->sl_rx_res_pool;
LOG_I(NR_MAC,"Received sci indication (sci format %d, Nid %x, subChannelIndex %d, payloadSize %d,payload %llx)\n", LOG_D(NR_MAC,"Received sci indication (sci format %d, Nid %x, subChannelIndex %d, payloadSize %d,payload %llx)\n",
sci->sci_format_type,sci->Nid,sci->subch_index,sci->sci_payloadlen,*(unsigned long long*)sci->sci_payloadBits); sci->sci_format_type,sci->Nid,sci->subch_index,sci->sci_payloadlen,*(unsigned long long*)sci->sci_payloadBits);
AssertFatal(sci->sci_format_type == SL_SCI_FORMAT_2_ON_PSSCH, "need to have format 2 here only\n"); AssertFatal(sci->sci_format_type == SL_SCI_FORMAT_2_ON_PSSCH, "need to have format 2 here only\n");
extract_pssch_sci_pdu((uint64_t *)sci->sci_payloadBits, sci->sci_payloadlen,sl_bwp, sl_res_pool, sci_pdu); extract_pssch_sci_pdu((uint64_t *)sci->sci_payloadBits, sci->sci_payloadlen,sl_bwp, sl_res_pool, sci_pdu);
LOG_I(NR_MAC,"SCI2A: harq_pid %d ndi %d RV %d SRC %x DST %x HARQ_FB %d Cast %d CSI_Req %d\n", sci_pdu->harq_pid,sci_pdu->ndi,sci_pdu->rv_index,sci_pdu->source_id,sci_pdu->dest_id,sci_pdu->harq_feedback,sci_pdu->cast_type,sci_pdu->csi_req); LOG_D(NR_MAC,"SCI2A: harq_pid %d ndi %d RV %d SRC %x DST %x HARQ_FB %d Cast %d CSI_Req %d\n", sci_pdu->harq_pid,sci_pdu->ndi,sci_pdu->rv_index,sci_pdu->source_id,sci_pdu->dest_id,sci_pdu->harq_feedback,sci_pdu->cast_type,sci_pdu->csi_req);
// send schedule response // send schedule response
sl_nr_rx_config_request_t rx_config; sl_nr_rx_config_request_t rx_config;
...@@ -797,7 +797,7 @@ int nr_ue_process_sci2_indication_pdu(NR_UE_MAC_INST_t *mac,module_id_t mod_id,f ...@@ -797,7 +797,7 @@ int nr_ue_process_sci2_indication_pdu(NR_UE_MAC_INST_t *mac,module_id_t mod_id,f
memset(&scheduled_response,0, sizeof(nr_scheduled_response_t)); memset(&scheduled_response,0, sizeof(nr_scheduled_response_t));
fill_scheduled_response(&scheduled_response,NULL,NULL,NULL,&rx_config,NULL,mod_id,0,frame,slot,phy_data); fill_scheduled_response(&scheduled_response,NULL,NULL,NULL,&rx_config,NULL,mod_id,0,frame,slot,phy_data);
LOG_I(NR_MAC, "[UE%d] TTI-%d:%d RX PSSCH_SLSCH REQ \n", mod_id,frame, slot); LOG_D(NR_MAC, "[UE%d] TTI-%d:%d RX PSSCH_SLSCH REQ \n", mod_id,frame, slot);
if ((mac->if_module != NULL) && (mac->if_module->scheduled_response != NULL)) if ((mac->if_module != NULL) && (mac->if_module->scheduled_response != NULL))
mac->if_module->scheduled_response(&scheduled_response); mac->if_module->scheduled_response(&scheduled_response);
return 1; return 1;
......
...@@ -110,6 +110,7 @@ static void *rlc_data_req_thread(void *_) ...@@ -110,6 +110,7 @@ static void *rlc_data_req_thread(void *_)
{ {
int i; int i;
LOG_I(RLC,"rlc_data_req_thread created on core %d\n",sched_getcpu());
pthread_setname_np(pthread_self(), "RLC queue"); pthread_setname_np(pthread_self(), "RLC queue");
while (1) { while (1) {
if (pthread_mutex_lock(&q.m) != 0) abort(); if (pthread_mutex_lock(&q.m) != 0) abort();
...@@ -146,10 +147,12 @@ static void init_nr_rlc_data_req_queue(void) ...@@ -146,10 +147,12 @@ static void init_nr_rlc_data_req_queue(void)
pthread_mutex_init(&q.m, NULL); pthread_mutex_init(&q.m, NULL);
pthread_cond_init(&q.c, NULL); pthread_cond_init(&q.c, NULL);
if (pthread_create(&t, NULL, rlc_data_req_thread, NULL) != 0) { /*if (pthread_create(&t, NULL, rlc_data_req_thread, NULL) != 0) {
LOG_E(PDCP, "%s:%d:%s: fatal\n", __FILE__, __LINE__, __FUNCTION__); LOG_E(PDCP, "%s:%d:%s: fatal\n", __FILE__, __LINE__, __FUNCTION__);
exit(1); exit(1);
} }*/
threadCreate(&t,rlc_data_req_thread,NULL,"rlc_data_req_thread",7,OAI_PRIORITY_RT_MAX-1);
} }
static void enqueue_rlc_data_req(const protocol_ctxt_t *const ctxt_pP, static void enqueue_rlc_data_req(const protocol_ctxt_t *const ctxt_pP,
...@@ -414,7 +417,6 @@ static void *enb_tun_read_thread(void *_) ...@@ -414,7 +417,6 @@ static void *enb_tun_read_thread(void *_)
int rb_id = 1; int rb_id = 1;
pthread_setname_np( pthread_self(),"enb_tun_read"); pthread_setname_np( pthread_self(),"enb_tun_read");
while (1) { while (1) {
len = read(nas_sock_fd[0], &rx_buf, NL_MAX_PAYLOAD); len = read(nas_sock_fd[0], &rx_buf, NL_MAX_PAYLOAD);
if (len == -1) { if (len == -1) {
...@@ -460,6 +462,7 @@ static void *ue_tun_read_thread(void *_) ...@@ -460,6 +462,7 @@ static void *ue_tun_read_thread(void *_)
int rb_id = 1; int rb_id = 1;
pthread_setname_np( pthread_self(),"ue_tun_read"); pthread_setname_np( pthread_self(),"ue_tun_read");
LOG_I(PDCP,"ue_tun_read_thread created on core %d\n",sched_getcpu());
while (1) { while (1) {
len = read(nas_sock_fd[0], &rx_buf, NL_MAX_PAYLOAD); len = read(nas_sock_fd[0], &rx_buf, NL_MAX_PAYLOAD);
if (len == -1) { if (len == -1) {
...@@ -511,11 +514,12 @@ static void start_pdcp_tun_ue(void) ...@@ -511,11 +514,12 @@ static void start_pdcp_tun_ue(void)
pthread_t t; pthread_t t;
reblock_tun_socket(); reblock_tun_socket();
/*
if (pthread_create(&t, NULL, ue_tun_read_thread, NULL) != 0) { if (pthread_create(&t, NULL, ue_tun_read_thread, NULL) != 0) {
LOG_E(PDCP, "%s:%d:%s: fatal\n", __FILE__, __LINE__, __FUNCTION__); LOG_E(PDCP, "%s:%d:%s: fatal\n", __FILE__, __LINE__, __FUNCTION__);
exit(1); exit(1);
} }*/
threadCreate(&t,ue_tun_read_thread,NULL,"ue_tun_read_thread",7,OAI_PRIORITY_RT_MAX-1);
} }
/****************************************************************************/ /****************************************************************************/
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment