Commit 05dd8743 authored by Florian Kaltenberger's avatar Florian Kaltenberger

first version of UE FAPI handling for DLSCH. paramters from DCI are now...

first version of UE FAPI handling for DLSCH. paramters from DCI are now handled by MAC and passed back to the PHY to program PDSCH. Still need to check parameters and take them into account in PHY.
parent f0fe6131
...@@ -52,7 +52,7 @@ ...@@ -52,7 +52,7 @@
//#define DEBUG_DCI //#define DEBUG_DCI
#define NR_PDCCH_DCI_TOOLS #define NR_PDCCH_DCI_TOOLS
//#define NR_PDCCH_DCI_TOOLS_DEBUG #define NR_PDCCH_DCI_TOOLS_DEBUG
typedef unsigned __int128 uint128_t; typedef unsigned __int128 uint128_t;
......
...@@ -1020,7 +1020,7 @@ typedef struct { ...@@ -1020,7 +1020,7 @@ typedef struct {
/// UE FAPI DCI request /// UE FAPI DCI request
nr_dcireq_t dcireq; nr_dcireq_t dcireq;
// CHECK if we need those as they are also included in dl_indictation // pointers to the next 2 strcutres are also included in dl_indictation
/// UE FAPI indication for DLSCH reception /// UE FAPI indication for DLSCH reception
fapi_nr_rx_indication_t rx_ind; fapi_nr_rx_indication_t rx_ind;
/// UE FAPI indication for DCI reception /// UE FAPI indication for DCI reception
......
...@@ -55,7 +55,7 @@ int8_t nr_ue_scheduled_response(nr_scheduled_response_t *scheduled_response){ ...@@ -55,7 +55,7 @@ int8_t nr_ue_scheduled_response(nr_scheduled_response_t *scheduled_response){
// Note: we have to handle the thread IDs for this. To be revisited completely. // Note: we have to handle the thread IDs for this. To be revisited completely.
NR_UE_PDCCH *pdcch_vars2 = PHY_vars_UE_g[module_id][cc_id]->pdcch_vars[thread_id][0]; NR_UE_PDCCH *pdcch_vars2 = PHY_vars_UE_g[module_id][cc_id]->pdcch_vars[thread_id][0];
NR_UE_DLSCH_t *dlsch0 = PHY_vars_UE_g[module_id][cc_id]->dlsch[thread_id][0][0]; NR_UE_DLSCH_t *dlsch0 = PHY_vars_UE_g[module_id][cc_id]->dlsch[thread_id][0][0];
NR_UE_ULSCH_t *ulsch0 = PHY_vars_UE_g[module_id][cc_id]->ulsch[0]; NR_UE_ULSCH_t *ulsch0 = PHY_vars_UE_g[module_id][cc_id]->ulsch[thread_id][0][0];
NR_DL_FRAME_PARMS frame_parms = PHY_vars_UE_g[module_id][cc_id]->frame_parms; NR_DL_FRAME_PARMS frame_parms = PHY_vars_UE_g[module_id][cc_id]->frame_parms;
PRACH_RESOURCES_t *prach_resources = PHY_vars_UE_g[module_id][cc_id]->prach_resources[0]; PRACH_RESOURCES_t *prach_resources = PHY_vars_UE_g[module_id][cc_id]->prach_resources[0];
...@@ -106,32 +106,24 @@ int8_t nr_ue_scheduled_response(nr_scheduled_response_t *scheduled_response){ ...@@ -106,32 +106,24 @@ int8_t nr_ue_scheduled_response(nr_scheduled_response_t *scheduled_response){
uint8_t current_harq_pid = dlsch_config_pdu->harq_process_nbr; uint8_t current_harq_pid = dlsch_config_pdu->harq_process_nbr;
dlsch0->current_harq_pid = current_harq_pid; dlsch0->current_harq_pid = current_harq_pid;
dlsch0->active = 1; dlsch0->active = 1;
dlsch0->rnti = dl_config->dl_config_list[i].dlsch_config_pdu.rnti;
//dlsch0->harq_processes[0]->mcs = &dlsch_config_pdu->mcs; //dlsch0->harq_processes[0]->mcs = &dlsch_config_pdu->mcs;
NR_DL_UE_HARQ_t dlsch0_harq = *(dlsch0->harq_processes[current_harq_pid]); NR_DL_UE_HARQ_t *dlsch0_harq = dlsch0->harq_processes[current_harq_pid];
//dlsch0->harq_processes[current_harq_pid]->nb_rb = dlsch_config_pdu->number_rbs; dlsch0_harq->nb_rb = dlsch_config_pdu->number_rbs;
dlsch0_harq->start_rb = dlsch_config_pdu->start_rb;
dlsch0_harq.nb_rb = dlsch_config_pdu->number_rbs; dlsch0_harq->nb_symbols = dlsch_config_pdu->number_symbols;
dlsch0_harq.start_rb = dlsch_config_pdu->start_rb; dlsch0_harq->start_symbol = dlsch_config_pdu->start_symbol;
dlsch0_harq.nb_symbols = dlsch_config_pdu->number_symbols; dlsch0_harq->mcs = dlsch_config_pdu->mcs;
dlsch0_harq.start_symbol = dlsch_config_pdu->start_symbol; dlsch0_harq->DCINdi = dlsch_config_pdu->ndi;
dlsch0_harq.mcs = dlsch_config_pdu->mcs; dlsch0_harq->rvidx = dlsch_config_pdu->rv;
dlsch0_harq.DCINdi = dlsch_config_pdu->ndi;
dlsch0_harq.rvidx = dlsch_config_pdu->rv;
dlsch0->g_pucch = dlsch_config_pdu->accumulated_delta_PUCCH;
dlsch0_harq.harq_ack.pucch_resource_indicator = dlsch_config_pdu->pucch_resource_id;
dlsch0_harq.harq_ack.slot_for_feedback_ack = dlsch_config_pdu->pdsch_to_harq_feedback_time_ind;
printf(">>>> \tdlsch0->g_pucch=%d\tdlsch0_harq.mcs=%d\n",dlsch0->g_pucch,dlsch0_harq.mcs);
//for (int j = 0 ; j<1000; j++) printf("\nk = %d",j);
#if 0
dlsch0->harq_processes[current_harq_pid]->mcs = dlsch_config_pdu->mcs;
dlsch0->g_pucch = dlsch_config_pdu->accumulated_delta_PUCCH; dlsch0->g_pucch = dlsch_config_pdu->accumulated_delta_PUCCH;
//pdlsch0->rnti = rnti; dlsch0_harq->harq_ack.pucch_resource_indicator = dlsch_config_pdu->pucch_resource_id;
#endif dlsch0_harq->harq_ack.slot_for_feedback_ack = dlsch_config_pdu->pdsch_to_harq_feedback_time_ind;
printf(">>>> \tdlsch0->g_pucch=%d\tdlsch0_harq.mcs=%d\n",dlsch0->g_pucch,dlsch0_harq->mcs);
} }
} }
}else{ }else{
......
...@@ -119,6 +119,7 @@ uint8_t nr_dci_decoding_procedure(int s, ...@@ -119,6 +119,7 @@ uint8_t nr_dci_decoding_procedure(int s,
format_found_t *format_found, format_found_t *format_found,
uint16_t crc_scrambled_values[TOTAL_NBR_SCRAMBLED_VALUES]); uint16_t crc_scrambled_values[TOTAL_NBR_SCRAMBLED_VALUES]);
/*
int nr_generate_ue_ul_dlsch_params_from_dci(PHY_VARS_NR_UE *ue, int nr_generate_ue_ul_dlsch_params_from_dci(PHY_VARS_NR_UE *ue,
uint8_t eNB_id, uint8_t eNB_id,
int frame, int frame,
...@@ -139,7 +140,7 @@ int nr_generate_ue_ul_dlsch_params_from_dci(PHY_VARS_NR_UE *ue, ...@@ -139,7 +140,7 @@ int nr_generate_ue_ul_dlsch_params_from_dci(PHY_VARS_NR_UE *ue,
uint16_t n_RB_DLBWP, uint16_t n_RB_DLBWP,
uint16_t crc_scrambled_values[TOTAL_NBR_SCRAMBLED_VALUES], uint16_t crc_scrambled_values[TOTAL_NBR_SCRAMBLED_VALUES],
NR_DCI_INFO_EXTRACTED_t *nr_dci_info_extracted); NR_DCI_INFO_EXTRACTED_t *nr_dci_info_extracted);
*/
#if defined(EXMIMO) || defined(OAI_USRP) || defined(OAI_BLADERF) || defined(OAI_LMSSDR) || defined(OAI_ADRV9371_ZC706) #if defined(EXMIMO) || defined(OAI_USRP) || defined(OAI_BLADERF) || defined(OAI_LMSSDR) || defined(OAI_ADRV9371_ZC706)
extern uint32_t downlink_frequency[MAX_NUM_CCs][4]; extern uint32_t downlink_frequency[MAX_NUM_CCs][4];
...@@ -3150,7 +3151,6 @@ int nr_ue_pdcch_procedures(uint8_t eNB_id,PHY_VARS_NR_UE *ue,UE_nr_rxtx_proc_t * ...@@ -3150,7 +3151,6 @@ int nr_ue_pdcch_procedures(uint8_t eNB_id,PHY_VARS_NR_UE *ue,UE_nr_rxtx_proc_t *
#endif #endif
ue->dci_ind.number_of_dcis = dci_cnt; ue->dci_ind.number_of_dcis = dci_cnt;
ue->dl_indication.dci_ind = &ue->dci_ind; // hang on rx_ind instance
for (int i=0; i<dci_cnt; i++) { for (int i=0; i<dci_cnt; i++) {
/* /*
...@@ -3198,7 +3198,7 @@ int nr_ue_pdcch_procedures(uint8_t eNB_id,PHY_VARS_NR_UE *ue,UE_nr_rxtx_proc_t * ...@@ -3198,7 +3198,7 @@ int nr_ue_pdcch_procedures(uint8_t eNB_id,PHY_VARS_NR_UE *ue,UE_nr_rxtx_proc_t *
dci_alloc_rx[i].rnti, dci_alloc_rx[i].rnti,
dci_alloc_rx[i].dci_pdu, dci_alloc_rx[i].dci_pdu,
&ue->dci_ind.dci_list[i].dci, &ue->dci_ind.dci_list[i].dci,
dci_fields_sizes, dci_fields_sizes_cnt[i],
dci_alloc_rx[i].format, dci_alloc_rx[i].format,
nr_tti_rx, nr_tti_rx,
pdcch_vars2->n_RB_BWP[nb_searchspace_active], pdcch_vars2->n_RB_BWP[nb_searchspace_active],
...@@ -3238,9 +3238,17 @@ int nr_ue_pdcch_procedures(uint8_t eNB_id,PHY_VARS_NR_UE *ue,UE_nr_rxtx_proc_t * ...@@ -3238,9 +3238,17 @@ int nr_ue_pdcch_procedures(uint8_t eNB_id,PHY_VARS_NR_UE *ue,UE_nr_rxtx_proc_t *
} // end for loop dci_cnt } // end for loop dci_cnt
// TODO: check where should we send up this message. // fill dl_indication message
//ue->if_inst->dl_indication(&ue->dl_indication); ue->dl_indication.module_id = ue->Mod_id;
ue->dl_indication.cc_id = ue->CC_id;
ue->dl_indication.gNB_index = eNB_id;
ue->dl_indication.frame = frame_rx;
ue->dl_indication.slot = nr_tti_rx;
ue->dl_indication.rx_ind = NULL; //no data, only dci for now
ue->dl_indication.dci_ind = &ue->dci_ind;
// send to mac
ue->if_inst->dl_indication(&ue->dl_indication);
#if UE_TIMING_TRACE #if UE_TIMING_TRACE
stop_meas(&ue->dlsch_rx_pdcch_stats); stop_meas(&ue->dlsch_rx_pdcch_stats);
...@@ -4383,7 +4391,7 @@ int phy_procedures_nrUE_RX(PHY_VARS_NR_UE *ue,UE_nr_rxtx_proc_t *proc,uint8_t eN ...@@ -4383,7 +4391,7 @@ int phy_procedures_nrUE_RX(PHY_VARS_NR_UE *ue,UE_nr_rxtx_proc_t *proc,uint8_t eN
LOG_I(PHY,"[UE %d] Frame %d, nr_tti_rx %d: found %d DCIs\n",ue->Mod_id,frame_rx,nr_tti_rx,dci_cnt); LOG_I(PHY,"[UE %d] Frame %d, nr_tti_rx %d: found %d DCIs\n",ue->Mod_id,frame_rx,nr_tti_rx,dci_cnt);
if (0/*ue->no_timing_correction==0*/) { if (ue->no_timing_correction==0) {
LOG_I(PHY,"start adjust sync slot = %d no timing %d\n", nr_tti_rx, ue->no_timing_correction); LOG_I(PHY,"start adjust sync slot = %d no timing %d\n", nr_tti_rx, ue->no_timing_correction);
nr_adjust_synch_ue(&ue->frame_parms, nr_adjust_synch_ue(&ue->frame_parms,
ue, ue,
......
...@@ -527,7 +527,7 @@ int main(int argc, char **argv) ...@@ -527,7 +527,7 @@ int main(int argc, char **argv)
UE->if_inst->ul_indication = dummy_nr_ue_ul_indication; UE->if_inst->ul_indication = dummy_nr_ue_ul_indication;
//mac->if_module = nr_ue_if_module_init(0); UE_mac->if_module = nr_ue_if_module_init(0);
// generate signal // generate signal
......
...@@ -186,8 +186,8 @@ int8_t nr_ue_process_dlsch(module_id_t module_id, int cc_id, uint8_t gNB_index, ...@@ -186,8 +186,8 @@ int8_t nr_ue_process_dlsch(module_id_t module_id, int cc_id, uint8_t gNB_index,
ul_config->ul_config_list[ul_config->number_pdus].pucch_config_pdu.twoPUCCH_PC_AdjustmentStates = 0; ul_config->ul_config_list[ul_config->number_pdus].pucch_config_pdu.twoPUCCH_PC_AdjustmentStates = 0;
} }
if(mac->if_module != NULL && mac->if_module->ul_indication != NULL){ if(mac->if_module != NULL && mac->if_module->scheduled_response != NULL){
mac->if_module->dl_indication(&mac->scheduled_response); mac->if_module->scheduled_response(&mac->scheduled_response);
} }
return 0; return 0;
} }
...@@ -1281,10 +1281,11 @@ int8_t nr_ue_process_dci(module_id_t module_id, int cc_id, uint8_t gNB_index, fa ...@@ -1281,10 +1281,11 @@ int8_t nr_ue_process_dci(module_id_t module_id, int cc_id, uint8_t gNB_index, fa
NR_UE_MAC_INST_t *mac = get_mac_inst(module_id); NR_UE_MAC_INST_t *mac = get_mac_inst(module_id);
fapi_nr_dl_config_request_t *dl_config = &mac->dl_config_request; fapi_nr_dl_config_request_t *dl_config = &mac->dl_config_request;
fapi_nr_ul_config_request_t *ul_config = &mac->ul_config_request; fapi_nr_ul_config_request_t *ul_config = &mac->ul_config_request;
const uint16_t n_RB_ULBWP = 106; const uint16_t n_RB_ULBWP = 106;
const uint16_t n_RB_DLBWP = 106; const uint16_t n_RB_DLBWP = 106;
printf("\n>>> nr_ue_process_dci at MAC layer with dci_format=%d\n",dci_format); printf("\n>>> nr_ue_process_dci at MAC layer with dci_format=%d\n",dci_format);
switch(dci_format){ switch(dci_format){
case format0_0: case format0_0:
...@@ -1741,8 +1742,6 @@ printf("\n>>> nr_ue_process_dci at MAC layer with dci_format=%d\n",dci_format); ...@@ -1741,8 +1742,6 @@ printf("\n>>> nr_ue_process_dci at MAC layer with dci_format=%d\n",dci_format);
/* PDSCH_TO_HARQ_FEEDBACK_TIME_IND (only if CRC scrambled by C-RNTI or CS-RNTI or new-RNTI)*/ /* PDSCH_TO_HARQ_FEEDBACK_TIME_IND (only if CRC scrambled by C-RNTI or CS-RNTI or new-RNTI)*/
dlsch_config_pdu_1_0->pdsch_to_harq_feedback_time_ind = dci->pdsch_to_harq_feedback_time_ind; dlsch_config_pdu_1_0->pdsch_to_harq_feedback_time_ind = dci->pdsch_to_harq_feedback_time_ind;
dl_config->number_pdus = dl_config->number_pdus + 1;
printf("\n>>> (nr_ue_procedures.c) rnti=%d dl_config->number_pdus=%d\n", printf("\n>>> (nr_ue_procedures.c) rnti=%d dl_config->number_pdus=%d\n",
dl_config->dl_config_list[dl_config->number_pdus].dlsch_config_pdu.rnti, dl_config->dl_config_list[dl_config->number_pdus].dlsch_config_pdu.rnti,
dl_config->number_pdus); dl_config->number_pdus);
...@@ -1770,14 +1769,7 @@ printf("\n>>> nr_ue_process_dci at MAC layer with dci_format=%d\n",dci_format); ...@@ -1770,14 +1769,7 @@ printf("\n>>> nr_ue_process_dci at MAC layer with dci_format=%d\n",dci_format);
printf(">>> (nr_ue_procedures.c) pdu_type=%d\n\n",dl_config->dl_config_list[dl_config->number_pdus].pdu_type); printf(">>> (nr_ue_procedures.c) pdu_type=%d\n\n",dl_config->dl_config_list[dl_config->number_pdus].pdu_type);
if(mac->if_module != NULL && mac->if_module->dl_indication != NULL) dl_config->number_pdus = dl_config->number_pdus + 1;
//printf(">>> mac->if_module->dl_indication(&mac->phy_config); \n");
//for (int k=0;k<1000;k++) printf(">>> %d ",k);
//mac->if_module->dl_indication(&mac->dl_info);
//mac->if_module->dl_indication(&mac->dl_config_request);
mac->if_module->dl_indication(&mac->phy_config);
break; break;
case format1_1: case format1_1:
...@@ -1959,14 +1951,12 @@ printf("\n>>> nr_ue_process_dci at MAC layer with dci_format=%d\n",dci_format); ...@@ -1959,14 +1951,12 @@ printf("\n>>> nr_ue_process_dci at MAC layer with dci_format=%d\n",dci_format);
/* DMRS_SEQ_INI */ /* DMRS_SEQ_INI */
//FIXME!!! //FIXME!!!
dl_config->number_pdus = dl_config->number_pdus + 1;
dl_config->dl_config_list[dl_config->number_pdus].pdu_type = FAPI_NR_DL_CONFIG_TYPE_DLSCH; dl_config->dl_config_list[dl_config->number_pdus].pdu_type = FAPI_NR_DL_CONFIG_TYPE_DLSCH;
printf(">>> (nr_ue_procedures.c) pdu_type=%d\n\n",dl_config->dl_config_list[dl_config->number_pdus].pdu_type); printf(">>> (nr_ue_procedures.c) pdu_type=%d\n\n",dl_config->dl_config_list[dl_config->number_pdus].pdu_type);
if(mac->if_module != NULL && mac->if_module->dl_indication != NULL) dl_config->number_pdus = dl_config->number_pdus + 1;
mac->if_module->dl_indication(&mac->phy_config);
break; break;
case format2_0: case format2_0:
...@@ -1986,7 +1976,6 @@ printf("\n>>> nr_ue_process_dci at MAC layer with dci_format=%d\n",dci_format); ...@@ -1986,7 +1976,6 @@ printf("\n>>> nr_ue_process_dci at MAC layer with dci_format=%d\n",dci_format);
} }
if(rnti == SI_RNTI){ if(rnti == SI_RNTI){
}else if(rnti == mac->ra_rnti){ }else if(rnti == mac->ra_rnti){
......
...@@ -34,6 +34,7 @@ ...@@ -34,6 +34,7 @@
#include "mac_proto.h" #include "mac_proto.h"
#include "assertions.h" #include "assertions.h"
#include "LAYER2/NR_MAC_UE/mac_extern.h" #include "LAYER2/NR_MAC_UE/mac_extern.h"
#include "SCHED_NR_UE/fapi_nr_ue_l1.h"
#include <stdio.h> #include <stdio.h>
...@@ -126,16 +127,26 @@ int nr_ue_dl_indication(nr_downlink_indication_t *dl_info){ ...@@ -126,16 +127,26 @@ int nr_ue_dl_indication(nr_downlink_indication_t *dl_info){
uint32_t ret_mask = 0x0; uint32_t ret_mask = 0x0;
module_id_t module_id = dl_info->module_id; module_id_t module_id = dl_info->module_id;
NR_UE_MAC_INST_t *mac = get_mac_inst(module_id); NR_UE_MAC_INST_t *mac = get_mac_inst(module_id);
fapi_nr_dl_config_request_t *dl_config = &mac->dl_config_request;
// clean up scheduled_response structure fapi_nr_ul_config_request_t *ul_config = &mac->ul_config_request;
dl_config->number_pdus = 0;
ul_config->number_pdus = 0;
//hook up pointers
mac->scheduled_response.dl_config = dl_config;
mac->scheduled_response.ul_config = ul_config;
mac->scheduled_response.tx_request = &mac->tx_request;
mac->scheduled_response.module_id = dl_info->module_id;
mac->scheduled_response.CC_id = dl_info->cc_id;
mac->scheduled_response.frame = dl_info->frame;
mac->scheduled_response.slot = dl_info->slot;
if(dl_info->dci_ind != NULL){ if(dl_info->dci_ind != NULL){
printf("[L2][IF MODULE][DL INDICATION][DCI_IND]\n"); printf("[L2][IF MODULE][DL INDICATION][DCI_IND]\n");
for(i=0; i<dl_info->dci_ind->number_of_dcis; ++i){ for(i=0; i<dl_info->dci_ind->number_of_dcis; ++i){
printf(">>>NR_IF_Module i=%d, dl_info->dci_ind->number_of_dcis=%d\n",i,dl_info->dci_ind->number_of_dcis); printf(">>>NR_IF_Module i=%d, dl_info->dci_ind->number_of_dcis=%d\n",i,dl_info->dci_ind->number_of_dcis);
fapi_nr_dci_pdu_rel15_t *dci = &dl_info->dci_ind->dci_list[i].dci; fapi_nr_dci_pdu_rel15_t *dci = &dl_info->dci_ind->dci_list[i].dci;
/*
ret_mask |= (handle_dci( ret_mask |= (handle_dci(
dl_info->module_id, dl_info->module_id,
dl_info->cc_id, dl_info->cc_id,
...@@ -143,7 +154,7 @@ int nr_ue_dl_indication(nr_downlink_indication_t *dl_info){ ...@@ -143,7 +154,7 @@ int nr_ue_dl_indication(nr_downlink_indication_t *dl_info){
dci, dci,
(dl_info->dci_ind->dci_list+i)->rnti, (dl_info->dci_ind->dci_list+i)->rnti,
(dl_info->dci_ind->dci_list+i)->dci_format)) << FAPI_NR_DCI_IND; (dl_info->dci_ind->dci_list+i)->dci_format)) << FAPI_NR_DCI_IND;
*/
/*switch((dl_info->dci_ind->dci_list+i)->dci_type){ /*switch((dl_info->dci_ind->dci_list+i)->dci_type){
case FAPI_NR_DCI_TYPE_0_0: case FAPI_NR_DCI_TYPE_0_0:
...@@ -244,8 +255,8 @@ nr_ue_if_module_t *nr_ue_if_module_init(uint32_t module_id){ ...@@ -244,8 +255,8 @@ nr_ue_if_module_t *nr_ue_if_module_init(uint32_t module_id){
nr_ue_if_module_inst[module_id]->cc_mask=0; nr_ue_if_module_inst[module_id]->cc_mask=0;
nr_ue_if_module_inst[module_id]->current_frame = 0; nr_ue_if_module_inst[module_id]->current_frame = 0;
nr_ue_if_module_inst[module_id]->current_slot = 0; nr_ue_if_module_inst[module_id]->current_slot = 0;
nr_ue_if_module_inst[module_id]->phy_config_request = NULL; nr_ue_if_module_inst[module_id]->phy_config_request = nr_ue_phy_config_request;
nr_ue_if_module_inst[module_id]->scheduled_response = NULL; nr_ue_if_module_inst[module_id]->scheduled_response = nr_ue_scheduled_response;
nr_ue_if_module_inst[module_id]->dl_indication = nr_ue_dl_indication; nr_ue_if_module_inst[module_id]->dl_indication = nr_ue_dl_indication;
nr_ue_if_module_inst[module_id]->ul_indication = nr_ue_ul_indication; nr_ue_if_module_inst[module_id]->ul_indication = nr_ue_ul_indication;
} }
......
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