diff --git a/src/constants.h b/src/constants.h index fbc39cc04cb0bd3581a00ffd7807693b4fc9ebf6..bc4d7344d83bfdc87d038a76b96e57d5d6b101f8 100644 --- a/src/constants.h +++ b/src/constants.h @@ -52,5 +52,5 @@ #define C_A_pn 6 // Number of dual polarization antennas per Processing Node (PN) FPGA. #define C_N_beamlets 976 // Number of beamlets per antenna band 488, 976 - +#define C_200MHZ_1_CNT_NS 5 // Time of one cnt in nS #endif diff --git a/src/fpga.cpp b/src/fpga.cpp index 7b36d9c4cfc1afcdbe8296f0f9678e82df25bdb9..e447b5ba84b4e66a84e2ff5d1dadbbdd0b842f1e 100644 --- a/src/fpga.cpp +++ b/src/fpga.cpp @@ -54,9 +54,6 @@ Fpga::Fpga(list<class Node*>& nodelist) // Add points: vector<int> nodes = get_all_nodes(); - pointMap->add_register("FPGA_mask_R", "fpga/enable_mask", nodes.size(), 1, "RO", REG_FORMAT_BOOLEAN); - pointMap->add_register("FPGA_mask_RW", "fpga/enable_mask", nodes.size(), 1, "RW", REG_FORMAT_BOOLEAN); - pointMap->add_register("FPGA_status_R", "fpga/status", nodes.size(), 1, "RO", REG_FORMAT_BOOLEAN); pointMap->add_register("FPGA_temp_R", "fpga/temp", nodes.size(), 1, "RO", REG_FORMAT_DOUBLE); pointMap->add_register("FPGA_firmware_version_R", "fpga/firmware_version", nodes.size(), 1, "RO", REG_FORMAT_STRING); pointMap->add_register("FPGA_hardware_version_R", "fpga/hardware_version", nodes.size(), 1, "RO", REG_FORMAT_STRING); @@ -173,11 +170,48 @@ vector<bool> Fpga::get_all_enabled_nodes(void) { vector<bool> enabled; for (auto node : FPGA) { - enabled.push_back(node->GetEnabled()); + enabled.push_back(node->isEnabled()); } return enabled; } +vector<bool> Fpga::get_all_masked_nodes(void) +{ + vector<bool> masked; + for (auto node : FPGA) { + masked.push_back(node->isMasked()); + } + return masked; +} + +vector<bool> Fpga::get_all_offline_nodes(void) +{ + vector<bool> online; + for (auto node : FPGA) { + online.push_back(!node->isOnline()); + } + return online; +} + +void Fpga::set_all_masked_nodes(std::vector<bool> masked) +{ + vector<int> nodes = get_all_nodes(); + for (uint idx = 0; idx<nodes.size(); idx++) { + auto node = select_node(nodes[idx]); + node->setMasked(masked[idx]); + } +} + +vector<uint32_t> Fpga::get_all_pps_offset_cnt(void) +{ + vector<uint32_t> pps_offset_cnt; + for (auto node : FPGA) { + pps_offset_cnt.push_back(node->ppsOffsetCnt()); + } + return pps_offset_cnt; +} + + uint Fpga::node_number(Node *node) { return (node->GetUniboardNr() * 4) + node->GetLocalNr(); diff --git a/src/fpga.h b/src/fpga.h index cfa1ca83854e199b808d271100ba2e7b397b2c20..14f62ec1d3a79dc84cdcfaf38e264d6f10b14ba5 100644 --- a/src/fpga.h +++ b/src/fpga.h @@ -54,6 +54,11 @@ public: Node * select_node(const int nr); std::vector<int> get_all_nodes(void); std::vector<bool> get_all_enabled_nodes(void); + std::vector<bool> get_all_masked_nodes(void); + std::vector<bool> get_all_offline_nodes(void); + void set_all_masked_nodes(std::vector<bool> masked); + std::vector<uint32_t> get_all_pps_offset_cnt(void); + CPointMap * get_pointMap(void); uint node_number(Node *node); bool is_fpga(const std::string addr); diff --git a/src/map.cpp b/src/map.cpp index eb605595025d9d4078909d2516c43027cbae2659..d584a8111c5feb41cb2abb7e2b36a51165a0b053 100644 --- a/src/map.cpp +++ b/src/map.cpp @@ -64,7 +64,6 @@ bool UniboardMap::read(TermOutput& termout, return retval; } - bool UniboardMap::write(TermOutput& termout, const string addr, const unsigned int *data, diff --git a/src/node.cpp b/src/node.cpp index 270a87d483f4cfcfcdee8de50c5479372267267f..64cbe881e456f63fc982798ac02ed1c29832bb3a 100644 --- a/src/node.cpp +++ b/src/node.cpp @@ -161,13 +161,13 @@ Node::Node(const string ipaddr, const uint unb, const uint localnr, const string const string firmware, const uint firmware_version, const bool enabled) { // int ret; - myIPaddr = ipaddr; - - periph_fpga = new Periph_fpga(ipaddr, firmware, firmware_version, enabled); - UniboardNr = unb; LocalNr = localnr; GlobalNr = localnr + 4 * unb; + + myIPaddr = ipaddr; + periph_fpga = new Periph_fpga(GlobalNr, ipaddr, firmware, firmware_version, enabled); + if (type != "pn") { throw runtime_error("invalid node type: \"" + type + "\""); @@ -233,11 +233,31 @@ CMMap * Node::get_MMap(void) return periph_fpga->getMMap(); } -bool Node::GetEnabled(void) +bool Node::isEnabled(void) { - return periph_fpga->getEnabled(); + return periph_fpga->isEnabled(); } +bool Node::isOnline(void) +{ + return periph_fpga->isOnline(); +} + +bool Node::isMasked() +{ + return periph_fpga->isMasked(); +} + +void Node::setMasked(bool mask) +{ + periph_fpga->setMasked(mask); +} + +uint32_t Node::ppsOffsetCnt(void) { + return periph_fpga->ppsOffsetCnt(); +} + + bool Node::exec_cmd(const char cmd, const string relative_addr, const string type, const string instance, const unsigned int *data, const int nvalues, const int format) @@ -280,7 +300,7 @@ bool Node::exec_reply(TermOutput& termout) // cout << "received " << r->nof_vals << " bytes from worker node=" << GlobalNr // << " retval=" << r->retval << " datatype=" << r->datatype << endl; - if (GetEnabled() && !r->retval) { + if (isEnabled() && !r->retval) { //cout << "no retval" << endl; throw runtime_error("no retval"); } diff --git a/src/node.h b/src/node.h index 52ce52b8b364a2bf0bff15f8a5fce39ffc4bc678..4006e2924fa4eb044d7c24013f3a68adf862a0d7 100644 --- a/src/node.h +++ b/src/node.h @@ -91,7 +91,11 @@ class Node { const uint GetGlobalNr() { return GlobalNr; } const uint GetNr() { return LocalNr; } const std::string GetType() { return Type; } - bool GetEnabled(void); + bool isEnabled(void); + bool isOnline(void); + bool isMasked(); + void setMasked(bool mask); + uint32_t ppsOffsetCnt(void); bool monitor(TermOutput& t); diff --git a/src/opcua/ua_server.cpp b/src/opcua/ua_server.cpp index 8a9faecebf84098aecfabb55359bf07083e4dea2..e56d50cdb3dc39efee93ad82505412bf38a5a1fb 100644 --- a/src/opcua/ua_server.cpp +++ b/src/opcua/ua_server.cpp @@ -78,7 +78,9 @@ void ua_print_nodeid(UA_NodeId *nd) } - +/* +* ua_read_DataSource(), this function is called by the opc-ua server to read a point. +*/ static UA_StatusCode ua_read_DataSource(UA_Server *server, const UA_NodeId *sessionId, void *sessionContext, const UA_NodeId *nodeId, void *nodeContext, @@ -90,7 +92,7 @@ static UA_StatusCode ua_read_DataSource(UA_Server *server, regname[nodeId->identifier.string.length] = 0; // add end of string char UA_LOG_INFO(UA_Log_Stdout, UA_LOGCATEGORY_USERLAND, - "ua_read_DataSource: from node %s",regname); + "ua_read_DataSource: reading from %s",regname); UA_NodeId currentNodeId = UA_NODEID_STRING(mUaLofarNameSpace, (char *)regname); UA_NodeId ntype; @@ -109,24 +111,25 @@ static UA_StatusCode ua_read_DataSource(UA_Server *server, // weird... must do -1 // see: https://open62541.org/doc/current/types.html - // Translator regnames start with "TR_" others "FPGA_" - bool regname_is_for_translator = false; - if (strncmp(regname,"TR_", 3) == 0) { - regname_is_for_translator = true; - UA_LOG_INFO(UA_Log_Stdout, UA_LOGCATEGORY_USERLAND,"ua_read_DataSource: for translator class"); - } - TermOutput termout; - if (regname_is_for_translator) { - try { + // read values for point + try { + // Translator regnames start with "TR_" others "FPGA_" + if (strncmp(regname,"TR_", 3) == 0) { + // UA_LOG_INFO(UA_Log_Stdout, UA_LOGCATEGORY_USERLAND,"ua_read_DataSource: for translator class"); SD.tr->read(termout, regname, -1); - } catch (runtime_error& e) { - cerr << "ua_read_DataSource error: " << e.what() << endl; } + else { + // UA_LOG_INFO(UA_Log_Stdout, UA_LOGCATEGORY_USERLAND,"ua_read_DataSource: for fpga class"); + SD.unb->read(termout, regname, -1); + } + } catch (runtime_error& e) { + cerr << "ua_read_DataSource error: " << e.what() << endl; + } - - // TR_* has only scalars + // if scalar (only TR_* points) + if (termout.nof_vals == 1) { switch (ntype.identifier.numeric - 1) { case UA_TYPES_STRING: { char *ptr = (char *)termout.val; @@ -193,14 +196,8 @@ static UA_StatusCode ua_read_DataSource(UA_Server *server, } break; } } + // else array else { - try { - SD.unb->read(termout, regname, -1); - } catch (runtime_error& e) { - cerr << "ua_read_DataSource: error: " << e.what() << endl; - } - - // FPGA_* has only arrays switch (ntype.identifier.numeric - 1) { case UA_TYPES_STRING: { UA_String *values = (UA_String *) UA_Array_new(termout.nof_vals, &UA_TYPES[UA_TYPES_STRING]); @@ -297,6 +294,9 @@ static UA_StatusCode ua_read_DataSource(UA_Server *server, return UA_STATUSCODE_GOOD; } +/* +* ua_write_DataSource(), this function is called by the opc-ua server to write a point. +*/ static UA_StatusCode ua_write_DataSource(UA_Server *server, const UA_NodeId *sessionId, void *sessionContext, const UA_NodeId *nodeId, void *nodeContext, @@ -314,207 +314,119 @@ static UA_StatusCode ua_write_DataSource(UA_Server *server, UA_NodeId ntype; UA_Server_readDataType(server, currentNodeId, &ntype); + // TODO: can this be removed. + // UA_Variant nv_dims; + // https://open62541.org/doc/0.2/server.html + // UA_Server_readArrayDimensions(server, currentNodeId, &nv_dims); + + // check if there is data to write, if not retval remains false. + if (data->hasValue && data->value.arrayLength > 0) { + //data.value is of type UA_Variant. + uint type = ntype.identifier.numeric - 1; + uint32_t *data_sdp; + uint32_t sz; + if ((type == UA_TYPES_DOUBLE) || (type == UA_TYPES_INT64) || (type == UA_TYPES_UINT64)) { + sz = data->value.arrayLength * 2; + } else if (type == UA_TYPES_STRING) { + sz = data->value.arrayLength * (SIZE1STRING / 4); + } else { + sz = data->value.arrayLength; + } + data_sdp = new uint32_t[sz]; + memset((void *)data_sdp, 0, sizeof(uint32_t)*sz); - // Translator regnames start with "TR_" others "FPGA_" - bool regname_is_for_translator = false; - if (strncmp(regname,"TR_",3) == 0) { - regname_is_for_translator = true; - UA_LOG_INFO(UA_Log_Stdout, UA_LOGCATEGORY_USERLAND,"ua_write_DataSource: for translator class"); - } - - if (regname_is_for_translator) { - // TR_* has only scalars - if (data->hasValue) { - unsigned int array_length = 1; - uint32_t *data_sdp = new uint32_t[array_length]; - - switch (ntype.identifier.numeric - 1) { - case UA_TYPES_STRING: { - retval = false; - } break; - case UA_TYPES_FLOAT: { - retval = false; - } break; - case UA_TYPES_DOUBLE: { - retval = false; - } break; - case UA_TYPES_INT16: { - retval = true; - int16_t *dptr = (int16_t *)data->value.data; - for (uint i=0; i<array_length; i++) { - data_sdp[i] = (uint32_t)dptr[i]; - } - } break; - case UA_TYPES_UINT16: { - retval = true; - uint16_t *dptr = (uint16_t *)data->value.data; - for (uint i=0; i<array_length; i++) { - data_sdp[i] = (uint32_t)dptr[i]; - } - } break; - case UA_TYPES_INT32: { - retval = true; - int32_t *dptr = (int32_t *)data->value.data; - for (uint i=0; i<array_length; i++) { - data_sdp[i] = (uint32_t)dptr[i]; - } - } break; - case UA_TYPES_UINT32: { - retval = true; - uint32_t *dptr = (uint32_t *)data->value.data; - for (uint i=0; i<array_length; i++) { - data_sdp[i] = (uint32_t)dptr[i]; - } - } break; - case UA_TYPES_INT64: { - retval = true; - int64_t *dptr = (int64_t *)data->value.data; - for (uint i=0; i<array_length; i++) { - data_sdp[i] = (uint64_t)dptr[i]; - } - } break; - case UA_TYPES_UINT64: { - retval = true; - uint64_t *dptr = (uint64_t *)data->value.data; - for (uint i=0; i<array_length; i++) { - data_sdp[i] = (uint64_t)dptr[i]; - } - } break; - case UA_TYPES_BOOLEAN: { - retval = true; - bool *dptr = (bool *)data->value.data; - for (unsigned int i=0; i<array_length; i++) { - data_sdp[i] = (uint32_t)dptr[i]; - } - } break; - default: { - retval = false; - } break; - } - if (retval) { - TermOutput termout; - - try { - SD.tr->write(termout, regname, data_sdp, array_length); - } catch (runtime_error& e) { - cerr << "write_TR_DataSource error: " << e.what() << endl; - retval = false; + retval = true; + switch (ntype.identifier.numeric - 1) { + case UA_TYPES_STRING: { + UA_String *dptr = (UA_String *)data->value.data; + UA_String str_data; + for (int i=0; i<(int)data->value.arrayLength; i++){ + str_data = dptr[i]; + memcpy((void *)&(data_sdp[i*(SIZE1STRING/4)]), (void *)str_data.data, str_data.length); } - } - delete[] data_sdp; + } break; + case UA_TYPES_FLOAT: { + memcpy(data_sdp, data->value.data, data->value.arrayLength*sizeof(UA_Float)); + } break; + case UA_TYPES_DOUBLE: { + memcpy(data_sdp, data->value.data, data->value.arrayLength*sizeof(UA_Double)); + } break; + case UA_TYPES_INT16: { + int16_t *dptr = (int16_t *)data->value.data; + for (uint i=0; i<data->value.arrayLength; i++) { + data_sdp[i] = (uint32_t)dptr[i]; + } + } break; + case UA_TYPES_UINT16: { + uint16_t *dptr = (uint16_t *)data->value.data; + for (uint i=0; i<data->value.arrayLength; i++) { + data_sdp[i] = (uint32_t)dptr[i]; + } + } break; + case UA_TYPES_INT32: { + int32_t *dptr = (int32_t *)data->value.data; + for (uint i=0; i<data->value.arrayLength; i++) { + data_sdp[i] = (uint32_t)dptr[i]; + } + } break; + case UA_TYPES_UINT32: { + uint32_t *dptr = (uint32_t *)data->value.data; + for (uint i=0; i<data->value.arrayLength; i++) { + data_sdp[i] = (uint32_t)dptr[i]; + } + } break; + case UA_TYPES_INT64: { // TODO: 64b -> 32b, not used yet but should give an error + int64_t *dptr = (int64_t *)data->value.data; + for (uint i=0; i<data->value.arrayLength; i++) { + data_sdp[i] = (uint64_t)dptr[i]; + } + } break; + case UA_TYPES_UINT64: { // TODO: 64b -> 32b, not used yet but should give an error + uint64_t *dptr = (uint64_t *)data->value.data; + for (uint i=0; i<data->value.arrayLength; i++) { + data_sdp[i] = (uint64_t)dptr[i]; + } + } break; + case UA_TYPES_BOOLEAN: { + bool *dptr = (bool *)data->value.data; + for (unsigned int i=0; i<data->value.arrayLength; i++) { + data_sdp[i] = (uint32_t)dptr[i]; + } + } break; + default: { + cout << "UA_TYPES_?: not implemented yet" << endl; + retval = false; + } break; } - } - else { - // FPGA_* has only arrays - UA_Variant nv_dims; - /*https://open62541.org/doc/0.2/server.html */ - UA_Server_readArrayDimensions(server, currentNodeId, &nv_dims); - - if (data->hasValue && data->value.arrayLength > 0) { - //data.value is a UA_Variant - uint type = ntype.identifier.numeric - 1; - uint32_t *data_sdp; - uint32_t sz; - if ((type == UA_TYPES_DOUBLE) || (type == UA_TYPES_INT64) || (type == UA_TYPES_UINT64)) { - sz = data->value.arrayLength * 2; - } else if (type == UA_TYPES_STRING) { - sz = data->value.arrayLength * (SIZE1STRING / 4); - } else { - sz = data->value.arrayLength; - } - data_sdp = new uint32_t[sz]; - memset((void *)data_sdp, 0, sizeof(uint32_t)*sz); - - switch (ntype.identifier.numeric - 1) { - case UA_TYPES_STRING: { - UA_String *dptr = (UA_String *)data->value.data; - UA_String str_data; - for (int i=0; i<(int)data->value.arrayLength; i++){ - str_data = dptr[i]; - memcpy((void *)&(data_sdp[i*(SIZE1STRING/4)]), (void *)str_data.data, str_data.length); - } - retval = true; - } break; - case UA_TYPES_FLOAT: { - retval = true; - memcpy(data_sdp, data->value.data, data->value.arrayLength*sizeof(UA_Float)); - } break; - case UA_TYPES_DOUBLE: { - retval = true; - memcpy(data_sdp, data->value.data, data->value.arrayLength*sizeof(UA_Double)); - } break; - case UA_TYPES_INT16: { - retval = true; - int16_t *dptr = (int16_t *)data->value.data; - for (uint i=0; i<data->value.arrayLength; i++) { - data_sdp[i] = (uint32_t)dptr[i]; - } - } break; - case UA_TYPES_UINT16: { - retval = true; - uint16_t *dptr = (uint16_t *)data->value.data; - for (uint i=0; i<data->value.arrayLength; i++) { - data_sdp[i] = (uint32_t)dptr[i]; - } - } break; - case UA_TYPES_INT32: { - retval = true; - int32_t *dptr = (int32_t *)data->value.data; - for (uint i=0; i<data->value.arrayLength; i++) { - data_sdp[i] = (uint32_t)dptr[i]; - } - } break; - case UA_TYPES_UINT32: { - retval = true; - uint32_t *dptr = (uint32_t *)data->value.data; - for (uint i=0; i<data->value.arrayLength; i++) { - data_sdp[i] = (uint32_t)dptr[i]; - } - } break; - case UA_TYPES_INT64: { - retval = true; - int64_t *dptr = (int64_t *)data->value.data; - for (uint i=0; i<data->value.arrayLength; i++) { - data_sdp[i] = (uint64_t)dptr[i]; - } - } break; - case UA_TYPES_UINT64: { - retval = true; - uint64_t *dptr = (uint64_t *)data->value.data; - for (uint i=0; i<data->value.arrayLength; i++) { - data_sdp[i] = (uint64_t)dptr[i]; - } - } break; - case UA_TYPES_BOOLEAN: { - retval = true; - bool *dptr = (bool *)data->value.data; - for (unsigned int i=0; i<data->value.arrayLength; i++) { - data_sdp[i] = (uint32_t)dptr[i]; - } - } break; - default: { - cout << "UA_TYPES_?: not implemented yet" << endl; - retval = false; - } break; - } - if (retval) { - TermOutput termout; - try { + if (retval) { + TermOutput termout; + try { + if (strncmp(regname,"TR_",3) == 0) { + // UA_LOG_INFO(UA_Log_Stdout, UA_LOGCATEGORY_USERLAND,"ua_write_DataSource: for translator class"); + SD.tr->write(termout, regname, data_sdp, data->value.arrayLength); + } + else { + // UA_LOG_INFO(UA_Log_Stdout, UA_LOGCATEGORY_USERLAND,"ua_write_DataSource: for fpga class"); SD.unb->write(termout, regname, data_sdp, data->value.arrayLength); - } catch (runtime_error& e) { - cerr << "ua_write_DataSource error: " << e.what() << endl; - retval = false; } + } catch (runtime_error& e) { + cerr << "ua_write_DataSource error: " << e.what() << endl; + retval = false; } - delete[] data_sdp; } + delete[] data_sdp; } delete[] regname; return UA_STATUSCODE_GOOD; } + +/* +* ua_add_Variable_[data_type]() functions to add a UA_Variant variabel (point) to the server +*/ + static void ua_add_Variable_string(UA_Server *server, string regname, unsigned int size, string perm, bool is_scalar) { UA_LOG_INFO(UA_Log_Stdout, UA_LOGCATEGORY_USERLAND, "ua_add_Variable_string: %s", (char *)regname.c_str()); @@ -1077,7 +989,14 @@ static void ua_add_Variable_boolean(UA_Server *server, string regname, unsigned cout << "Error adding node" << endl; } } +/* end of ua_add_Variable_[data_type]() functions */ + +/* +* ua_add_Variable(), main function to add variabel(point) for given format(data_type) to +* the opc-ua server by calling an ua_add_Variable_[data_type]() functions. +* if data size is 1, its a scalar. +*/ static void ua_add_Variable(UA_Server *server, string regname, int format, unsigned int size, string perm) { cout << "regname=" << regname << " format=" << format << " size=" << size << endl; @@ -1121,6 +1040,12 @@ static void ua_add_Variable(UA_Server *server, string regname, int format, unsig } } +/* +* ua_server_init(), get all FPGA_ and TR_ poins and add them to the opc-ua server. +* +* SD.unb->get_pointMap() --> FPGA_* (points defined in src/fpga.cpp) +* SD.tr->getTranslatorMap() --> TR_* (points defined in src/tr.cpp) +*/ int ua_server_init(bool warm_start) { if (!warm_start) { @@ -1154,6 +1079,9 @@ int ua_server_init(bool warm_start) return 0; } +/* +* ua_server(), start opc-ua server, called from sdptr.cpp +*/ int ua_server(void) { UA_StatusCode retval = UA_Server_run(mUaServer, &ServerRunning); diff --git a/src/periph/fpga.cpp b/src/periph/fpga.cpp index e49bed6b40e68204c6a78da092ec0d31bdae98fb..5c3a1c2c483d4d02b682ae37a882f5bab512d3d0 100644 --- a/src/periph/fpga.cpp +++ b/src/periph/fpga.cpp @@ -58,12 +58,14 @@ extern int debug; #define R_MEM 0 // read mem value #define R_UCP 1 // read value from hardware -Periph_fpga::Periph_fpga(string ipaddr, string expected_design_name, uint expected_firmware_version, bool enabled): +Periph_fpga::Periph_fpga(uint global_nr, string ipaddr, string expected_design_name, uint expected_firmware_version, bool enabled): + GlobalNr(global_nr), Enabled(enabled), + Masked(enabled), + Online(enabled), my_expected_design_name(expected_design_name), my_expected_firmware_version(expected_firmware_version), my_current_design_name("-"), - my_current_status("offline"), my_current_hw_version(0), my_current_fw_version("-.-"), my_bsn_input_sync_timeout(false), @@ -75,15 +77,19 @@ Periph_fpga::Periph_fpga(string ipaddr, string expected_design_name, uint expect my_jesd_csr_dev_syncn {0}, my_jesd_rx_err0 {0}, my_jesd_rx_err1 {0}, - my_xst_processing_enable(false) + my_xst_processing_enable(false), + my_pps_offset_cnt(0) { ucp = new UCP(ipaddr); if (Enabled) { mmap = new CMMap(read_reg_map()); + cout << "mmap for node " << GlobalNr << endl; + mmap->print_screen(); } else { mmap = new CMMap(); + cout << "empty mmap for node " << GlobalNr << endl; } // Test FPGA by reading system info: @@ -121,183 +127,30 @@ Periph_fpga::~Periph_fpga() if (mmap != NULL) delete mmap; } -bool Periph_fpga::Read(const string addr_str, uint32_t *data_ptr, bool use_mask_shift=true) -{ - bool ret; - if (!Enabled) { - return false; - // throw runtime_error("disabled: " + addr_str); - } - if (!mmap->find_register(addr_str)) { - return false; - } - - uint32_t addr = mmap->getAddr((addr_str)); - - mmap->getReadPermission((addr_str)); - - uint32_t nvalues = mmap->getSpan((addr_str)); - bool isfifo = mmap->type_isfifo((addr_str)); - - ret = ucp->readRegister(addr, nvalues, data_ptr, isfifo); - if (use_mask_shift) { - for (uint32_t i=0; i<nvalues; i++) { - data_ptr[i] = mask_shift(addr_str, data_ptr[i]); - } - } - return ret; -} - -bool Periph_fpga::Write(const string addr_str, uint32_t *data_ptr, bool use_shift_mask=true) -{ - if (!Enabled) { - return false; - // throw runtime_error("disabled " + addr_str); - } - if (!mmap->find_register(addr_str)) { - return false; - } - uint32_t addr = mmap->getValidAddr((addr_str), 1); - uint32_t span = mmap->getSpan((addr_str)); - //cout << "addr=" << addr_str << " span=" << to_string(span) << endl; - mmap->getWritePermission((addr_str)); - - bool isfifo = mmap->type_isfifo((addr_str)); - if (use_shift_mask) { - for (uint32_t i=0; i<span; i++) { - data_ptr[i] = shift_mask(addr_str, data_ptr[i]); - } - } - return ucp->writeRegister(addr, span, data_ptr, isfifo); -} - -// for reading -uint32_t Periph_fpga::mask_shift(const string addr_str, uint32_t data) -{ - uint32_t shift = mmap->getShift((addr_str)); - uint32_t mask = mmap->getMask((addr_str)); - uint32_t _data = data; - - if (shift != 0 || mask != 0xffffffff) { - _data &= mask; - _data = _data >> shift; - } - return _data; -} - -// for writing -uint32_t Periph_fpga::shift_mask(const string addr_str, uint32_t data) -{ - uint32_t shift = mmap->getShift((addr_str)); - uint32_t mask = mmap->getMask((addr_str)); - uint32_t _data = data; - - if (shift != 0 || mask != 0xffffffff) { - _data = _data << shift; - _data &= mask; - } - return _data; -} - - -bool Periph_fpga::read_fpga_status(TermOutput& termout, int format) -{ - if (my_current_status == "online") { - termout.val[0] = 1; - } - else { - termout.val[0] = 0; - } - termout.nof_vals = 1; - termout.datatype = format; - return true; -} - -bool Periph_fpga::write_fpga_enable_mask(const char *data) -{ - Enabled = (bool)*data; - return true; -} - -bool Periph_fpga::read_fpga_enable_mask(TermOutput& termout, int format) -{ - termout.val[0] = Enabled; - termout.nof_vals = 1; - termout.datatype = format; - return true; -} - /* -"""Peripheral system_info - Register map: - 31 24 23 16 15 8 7 0 wi - |-----------------|-----------------|-----------------|-----------------| - | use_phy[7:0] | 1 - |-----------------------------------------------------------------------| - | system_info[31:0] | 0 - |-----------------------------------------------------------------------| - - system_info[23:20] = firmware version high[3:0] - system_info[19:16] = firmware version low[3:0] - system_info[10] = cs_sim (= g_sim, 0 on HW, 1 in VHDL simulation) - system_info[9:8] = hardware version [1:0] (= 0 for UniBoard 1A and 1B) - system_info[7:0] = node id[7;0] +* read(), this function is called from Node::worker() thread. */ -bool Periph_fpga::read_system_info(TermOutput& termout) -{ - // cout << "read system info" << endl; - uint32_t data; - bool retval = Read("mm/0/PIO_SYSTEM_INFO/info", &data); - if (retval == false) { return false; } - - // string design_name = read_design_name(); - my_current_design_name = read_design_name(); - - // FIXME: get rid of magic constants in masks, should be in CCFG: - uint firmware_version = (data & 0x00F00000) >> 20; - uint firmware_subversion = (data & 0x000F0000) >> 16; - my_current_fw_version = to_string(firmware_version) + "." + to_string(firmware_subversion); - - my_current_hw_version = (data & 0x0000300) >> 8; - - if (my_current_design_name == my_expected_design_name && firmware_version >= my_expected_firmware_version) { - my_current_status = "online"; - retval = true; - } - else { - retval = false; - cerr << "Warning: Node configuration mismatch!! (read_design_name/version=" << my_current_design_name - << "/" << firmware_version << "), expected=" << my_expected_design_name - << "/" << my_expected_firmware_version << ")" << endl; - //syslog(LOG_WARNING,"Node configuration mismatch!! (read_design_name/version=%s/%d, expected=%s/%d)\n", - // my_current_design_name.c_str(), firmware_version, - // my_expected_design_name.c_str(), my_expected_firmware_version); - - my_current_status = "offline"; - // registerMap->setAllPermission_NA(); - } - return retval; -} - bool Periph_fpga::read(TermOutput& termout, const string addr, const string type, char *data, const uint nvalues, const int format) { + // cout << "node " << GlobalNr << " read: Enabled=" << Enabled << ", Online=" << Online << ", Masked=" << Masked << endl; bool retval = false; termout.datatype = format; termout.nof_vals = 0; - if (addr == "fpga/enable_mask") { - retval = read_fpga_enable_mask(termout, format); - return retval; + if (!Masked) { // Not selected + return false; + } + if ((!Enabled) || (!Online)) { // Selected but not possible + cout << "read() error node " << GlobalNr << " not enabled or not online" << endl; + return false; } - - if (!Enabled) { return false; } if (type == "mm") { uint32_t *data_ptr = (uint32_t *)data; - retval = Read(addr, data_ptr); + retval = Read(addr, data_ptr, true); termout.datatype = format; } else { // "fpga/..." @@ -331,12 +184,6 @@ bool Periph_fpga::read(TermOutput& termout, const string addr, else if (addr == "fpga/epcs_wait_busy") { retval = wait_while_epcs_busy(1000); } - else if (addr == "fpga/status") { - retval = read_fpga_status(termout, format); - } - else if (addr == "fpga/enable_mask") { - retval = read_fpga_enable_mask(termout, format); - } else if (addr == "fpga/scrap") { retval = read_fpga_scrap(termout, format); } @@ -468,22 +315,27 @@ bool Periph_fpga::read(TermOutput& termout, const string addr, return retval; } +/* +* write(), this function is called from Node::worker() thread. +*/ bool Periph_fpga::write(TermOutput& termout, const string addr, const string type, char *data, const uint nvalues, const int format) { + // cout << "node " << GlobalNr << " write: Enabled=" << Enabled << ", Online=" << Online << ", Masked=" << Masked << endl; bool retval = false; - if (addr == "fpga/enable_mask") { - retval = write_fpga_enable_mask(data); - return retval; + if (!Masked) { // Not selected + return false; + } + if ((!Enabled) || (!Online)) { // Selected but not possible + cout << "write() error node " << GlobalNr << " not enabled or not online" << endl; + return false; } - - if (!Enabled) { return false; } uint32_t *data_ptr = (uint32_t *)data; if (type == "mm") { - retval = Write(addr, data_ptr); + retval = Write(addr, data_ptr, true); } else { // "fpga/..." // if (addr == "fpga/rbf") { @@ -515,7 +367,7 @@ bool Periph_fpga::write(TermOutput& termout, const string addr, const string typ } else if (addr == "fpga/epcs_mmdp_data") { // write to FIFO - retval = Write("mm/0/REG_MMDP_DATA/data", data_ptr); + retval = Write("mm/0/REG_MMDP_DATA/0/data", data_ptr, true); } else if (addr == "fpga/scrap") { retval = write_fpga_scrap(data_ptr); @@ -611,28 +463,194 @@ bool Periph_fpga::write(TermOutput& termout, const string addr, const string typ return retval; } +/* +* monitor(), this function is called from Node::worker() thread. +*/ bool Periph_fpga::monitor(TermOutput& termout) { if (!Enabled) { return false; } // use tictoc, tic(start) toc(stop) to see how long this function takes // first 9 read functions on 4 nodes will take 6 msec. - tictoc.tic("periph.fpga.monitor"); + string name = "periph.fpga.monitor node " + to_string(GlobalNr); + tictoc.tic(name.c_str()); read_system_info(termout); - read_bsn_monitor_input_sync_timeout(termout, REG_FORMAT_INT64, R_UCP); - read_bsn_monitor_input_bsn(termout, REG_FORMAT_INT64, R_UCP); - read_bsn_monitor_input_nof_packets(termout, REG_FORMAT_INT32, R_UCP); - read_bsn_monitor_input_nof_valid(termout, REG_FORMAT_INT32, R_UCP); - read_bsn_monitor_input_nof_err(termout, REG_FORMAT_INT32, R_UCP); - read_jesd204b_csr_rbd_count(termout, REG_FORMAT_UINT32, R_UCP); - read_jesd204b_csr_dev_syncn(termout, REG_FORMAT_UINT32, R_UCP); - read_jesd204b_rx_err0(termout, REG_FORMAT_UINT32, R_UCP); - read_jesd204b_rx_err1(termout, REG_FORMAT_UINT32, R_UCP); - + if (Online) { + read_time_since_last_pps(termout, REG_FORMAT_INT64, R_UCP); + read_bsn_monitor_input_sync_timeout(termout, REG_FORMAT_INT64, R_UCP); + read_bsn_monitor_input_bsn(termout, REG_FORMAT_INT64, R_UCP); + read_bsn_monitor_input_nof_packets(termout, REG_FORMAT_INT32, R_UCP); + read_bsn_monitor_input_nof_valid(termout, REG_FORMAT_INT32, R_UCP); + read_bsn_monitor_input_nof_err(termout, REG_FORMAT_INT32, R_UCP); + read_jesd204b_csr_rbd_count(termout, REG_FORMAT_UINT32, R_UCP); + read_jesd204b_csr_dev_syncn(termout, REG_FORMAT_UINT32, R_UCP); + read_jesd204b_rx_err0(termout, REG_FORMAT_UINT32, R_UCP); + read_jesd204b_rx_err1(termout, REG_FORMAT_UINT32, R_UCP); + } termout.clear(); tictoc.toc(); return true; } + +/************************************************ + from here only intern (private) used functions +************************************************/ + +/* +* Read(), do a read to an UCP register +* - check if addr_str is available. +* - get information for reading. +* - put read data in 'data_ptr' (masked and shifted on request). +* - return true on succes else false. +*/ +bool Periph_fpga::Read(const string addr_str, uint32_t *data_ptr, bool use_mask_shift=true) +{ + bool ret; + if ((!Enabled) || (!Masked)) { + return false; + } + if (!mmap->find_register(addr_str)) { + cout << addr_str << " not found" << endl; + return false; + } + + uint32_t addr = mmap->getAddr((addr_str)); + + mmap->getReadPermission((addr_str)); + + uint32_t nvalues = mmap->getSpan((addr_str)); + bool isfifo = mmap->type_isfifo((addr_str)); + + ret = ucp->readRegister(addr, nvalues, data_ptr, isfifo); + if (use_mask_shift) { + for (uint32_t i=0; i<nvalues; i++) { + data_ptr[i] = mask_shift(addr_str, data_ptr[i]); + } + } + return ret; +} + +/* +* Write(), do a write to an UCP register +* - check if addr_str is available. +* - get information for writing. +* - write data from 'data_ptr' (shifted and masked on request) +* - return true on succes else false. +*/ +bool Periph_fpga::Write(const string addr_str, uint32_t *data_ptr, bool use_shift_mask=true) +{ + if ((!Enabled) || (!Masked)) { + return false; + } + if (!mmap->find_register(addr_str)) { + return false; + } + uint32_t addr = mmap->getValidAddr((addr_str), 1); + uint32_t span = mmap->getSpan((addr_str)); + //cout << "addr=" << addr_str << " span=" << to_string(span) << endl; + mmap->getWritePermission((addr_str)); + + bool isfifo = mmap->type_isfifo((addr_str)); + if (use_shift_mask) { + for (uint32_t i=0; i<span; i++) { + data_ptr[i] = shift_mask(addr_str, data_ptr[i]); + } + } + return ucp->writeRegister(addr, span, data_ptr, isfifo); +} + +/* +* mask_shift (for reading) +* mask data and shift bits using information from the mmap. +*/ +uint32_t Periph_fpga::mask_shift(const string addr_str, uint32_t data) +{ + uint32_t shift = mmap->getShift((addr_str)); + uint32_t mask = mmap->getMask((addr_str)); + uint32_t _data = data; + + if (shift != 0 || mask != 0xffffffff) { + _data &= mask; + _data = _data >> shift; + } + return _data; +} + +/* +* shift_mask (for writing) +* shift data and mask bits using information from the mmap. +*/ +uint32_t Periph_fpga::shift_mask(const string addr_str, uint32_t data) +{ + uint32_t shift = mmap->getShift((addr_str)); + uint32_t mask = mmap->getMask((addr_str)); + uint32_t _data = data; + + if (shift != 0 || mask != 0xffffffff) { + _data = _data << shift; + _data &= mask; + } + return _data; +} + + +/* +"""Peripheral system_info + Register map: + 31 24 23 16 15 8 7 0 wi + |-----------------|-----------------|-----------------|-----------------| + | use_phy[7:0] | 1 + |-----------------------------------------------------------------------| + | system_info[31:0] | 0 + |-----------------------------------------------------------------------| + + system_info[23:20] = firmware version high[3:0] + system_info[19:16] = firmware version low[3:0] + system_info[10] = cs_sim (= g_sim, 0 on HW, 1 in VHDL simulation) + system_info[9:8] = hardware version [1:0] (= 0 for UniBoard 1A and 1B) + system_info[7:0] = node id[7;0] +*/ +bool Periph_fpga::read_system_info(TermOutput& termout) +{ + // cout << "node " << GlobalNr << " read system info" << endl; + uint32_t data; + bool retval = Read("mm/0/PIO_SYSTEM_INFO/0/info", &data); + if (retval == false) { + cout << "node " << GlobalNr << " no response" << endl; + Online = false; + return false; + } + + // string design_name = read_design_name(); + my_current_design_name = read_design_name(); + cout << "node " << GlobalNr << " design_name= " << my_current_design_name << endl; + + // FIXME: get rid of magic constants in masks, should be in CCFG: + uint firmware_version = (data & 0x00F00000) >> 20; + uint firmware_subversion = (data & 0x000F0000) >> 16; + my_current_fw_version = to_string(firmware_version) + "." + to_string(firmware_subversion); + + my_current_hw_version = (data & 0x0000300) >> 8; + + if (my_current_design_name == my_expected_design_name && firmware_version >= my_expected_firmware_version) { + Online = true; + retval = true; + } + else { + retval = false; + cerr << "Warning: Node configuration mismatch!! (read_design_name/version=" << my_current_design_name + << "/" << firmware_version << "), expected=" << my_expected_design_name + << "/" << my_expected_firmware_version << ")" << endl; + //syslog(LOG_WARNING,"Node configuration mismatch!! (read_design_name/version=%s/%d, expected=%s/%d)\n", + // my_current_design_name.c_str(), firmware_version, + // my_expected_design_name.c_str(), my_expected_firmware_version); + + Online = false; + // registerMap->setAllPermission_NA(); + } + return retval; +} + bool Periph_fpga::flash_prot(uint32_t *data) { bool retval = false; @@ -640,10 +658,10 @@ bool Periph_fpga::flash_prot(uint32_t *data) uint32_t passphrase_unprotect = 0xBEDA221E; if (*data == 0) { // unprotect - retval = Write("mm/0/REG_EPCS/unprotect", &passphrase_unprotect); + retval = Write("mm/0/REG_EPCS/0/unprotect", &passphrase_unprotect); } else { // protect - retval = Write("mm/0/REG_EPCS/unprotect", &passphrase_protect); + retval = Write("mm/0/REG_EPCS/0/unprotect", &passphrase_protect); } return retval; } @@ -655,14 +673,14 @@ bool Periph_fpga::flash_page(uint32_t *data) wait_while_epcs_busy(1); // write address uint32_t addr = Flash_page_start * Flash_page_size_bytes; - retval = Write("mm/0/REG_EPCS/addr", &addr); + retval = Write("mm/0/REG_EPCS/0/addr", &addr); // write to FIFO - retval = Write("mm/0/REG_MMDP_DATA/data", data); + retval = Write("mm/0/REG_MMDP_DATA/0/data", data); // write_write uint32_t d = 1; - retval = Write("mm/0/REG_EPCS/write", &d); + retval = Write("mm/0/REG_EPCS/0/write", &d); return retval; } @@ -688,7 +706,7 @@ bool Periph_fpga::wait_while_epcs_busy(uint sleeptime) bool retval; //cout << "wait_while_epcs_busy:"; for (int i=0; i<100; i++) { - retval = Read("mm/0/REG_EPCS/busy", &data); + retval = Read("mm/0/REG_EPCS/0/busy", &data); if (!retval) break; if (data == 0) break; usleep(sleeptime); @@ -715,10 +733,10 @@ bool Periph_fpga::flash_erase_sector(uint32_t sector) for (uint i=0; i<s_list.size(); i++) { s = sector * 0x40000 + s_list[i]; // write address - retval = Write("mm/0/REG_EPCS/addr", &s); + retval = Write("mm/0/REG_EPCS/0/addr", &s); // sector erase d = 1; - retval = Write("mm/0/REG_EPCS/sector_erase", &d); + retval = Write("mm/0/REG_EPCS/0/sector_erase", &d); wait_while_epcs_busy(50000); } return retval; @@ -2280,6 +2298,22 @@ bool Periph_fpga::read_subband_weights(TermOutput& termout, int format) { return retval; } +bool Periph_fpga::read_time_since_last_pps(TermOutput& termout, int format, int mode) { + bool retval = true; + if (mode == R_UCP) { + uint32_t data = 0; + retval = Read("mm/0/PIO_PPS/0/offset_cnt", &data); + my_pps_offset_cnt = data; + } + + uint32_t *_ptr = (uint32_t *)termout.val; + *_ptr = my_pps_offset_cnt; + termout.nof_vals = 1; + termout.datatype = format; + return retval; +} + + bool Periph_fpga::write_wdi_override(TermOutput& termout) { uint32_t data = 0xB007FAC7; @@ -2319,7 +2353,7 @@ CMMap Periph_fpga::read_reg_map() char *str_ptr = (char *)data; string reg_map_str(str_ptr); - cout << "Periph_fpga::read_reg_map:\n" << reg_map_str << endl; + // cout << "Periph_fpga::read_reg_map:\n" << reg_map_str << endl; if (data != NULL) { delete[] data; } diff --git a/src/periph/fpga.h b/src/periph/fpga.h index b66d47d27acfbb8a7a2d15a32968330ecc21c762..eea3a2415f2c30c97388334cdfcaaa2c35d89466 100644 --- a/src/periph/fpga.h +++ b/src/periph/fpga.h @@ -46,12 +46,14 @@ private: Tictoc tictoc; // used to get some timing information UCP *ucp; CMMap *mmap; - + uint32_t GlobalNr; bool Enabled; + bool Masked; + bool Online; + std::string my_expected_design_name; uint my_expected_firmware_version; std::string my_current_design_name; - std::string my_current_status; uint my_current_hw_version; std::string my_current_fw_version; @@ -66,6 +68,7 @@ private: uint32_t my_jesd_rx_err0[C_S_pn]; uint32_t my_jesd_rx_err1[C_S_pn]; bool my_xst_processing_enable; + uint32_t my_pps_offset_cnt; std::ofstream rbf_wf; uint32_t Flash_page_start, Flash_page_size_bytes, Flash_user_sector_start, @@ -85,10 +88,6 @@ private: bool wait_while_epcs_busy(uint sleeptime); std::string read_design_name(); std::string read_design_note(); - bool read_fpga_status(TermOutput& termout, int format); - - bool read_fpga_enable_mask(TermOutput& termout, int format); - bool write_fpga_enable_mask(const char *data); bool read_system_info(TermOutput& termout); bool read_hardware_version(TermOutput& termout, int format); @@ -181,12 +180,13 @@ private: bool read_sdp_info_block_period(TermOutput& termout, int format); + bool read_time_since_last_pps(TermOutput& termout, int format, int mode); bool write_wdi_override(TermOutput& termout); CMMap read_reg_map(); public: - Periph_fpga(std::string ipaddr, std::string expected_design_name, uint expected_firmware_version, bool enabled); + Periph_fpga(uint global_nr, std::string ipaddr, std::string expected_design_name, uint expected_firmware_version, bool enabled); ~Periph_fpga(); @@ -197,7 +197,11 @@ public: bool monitor(TermOutput& termout); CMMap* getMMap(void) { return mmap; }; - bool getEnabled(void) { return Enabled; } + bool isEnabled(void) { return Enabled; } + bool isOnline(void) { return Online; } + bool isMasked(void) { return Masked; } + void setMasked(bool mask) { Masked = mask; } + uint32_t ppsOffsetCnt(void) { return my_pps_offset_cnt; } }; #endif // __PERIPH_FPGA_H__ diff --git a/src/registers.cpp b/src/registers.cpp index 124b3501950f586b65dfcbfd0a669724d4b5a6df..1639254c44243ee5e5189b33aa9d18ef636f67b5 100644 --- a/src/registers.cpp +++ b/src/registers.cpp @@ -99,7 +99,7 @@ bool CMMap::add_register(const string name, const uint32_t base, const uint32_t const uint32_t shift, const string access, const string type, const uint32_t peripheral_span, const uint32_t mm_port_span) { - cout << "CMMap::add_register: " << name << endl; + // cout << "CMMap::add_register: " << name << endl; if (find_register(name)) { cerr << "CMMap::add_register: " << name << " already exist!" << endl; return false; @@ -114,7 +114,7 @@ bool CMMap::update_register(const string name, const uint32_t base, const uint32 const uint32_t shift, const string access, const string type, const uint32_t peripheral_span, const uint32_t mm_port_span) { - cout << "CMMap::update_register: " << name << endl; + // cout << "CMMap::update_register: " << name << endl; if (!find_register(name)) { cerr << "CMMap::update_register: " << name << " not exist!" << endl; return false; diff --git a/src/sdptr.cpp b/src/sdptr.cpp index 80353e041c3fd22b90b785ccef91b39287004921..8357050624a378a51c520caa520653b3f0e8bdbb 100644 --- a/src/sdptr.cpp +++ b/src/sdptr.cpp @@ -62,6 +62,10 @@ void monitor() string line; string cmdname = ""; TermOutput termout; + struct timeval current_time; + time_t secs; + struct tm * now; + char time_str[50]; SD.timetick = SECONDS_PER_TICK; clock_gettime(CLOCK_REALTIME, (struct timespec *)&SD.t0); @@ -69,21 +73,27 @@ void monitor() pthread_cond_init(&SD.newpoint_cond, NULL); SD.uptime = 0; + + gettimeofday(¤t_time, NULL); + SD.start_time = current_time.tv_sec; - while (ServerRunning) { - struct timeval current_time; + while (ServerRunning) { SD.t0.tv_sec = SD.t0.tv_sec + SD.timetick; // specify next position in time SD.t0.tv_nsec = 10000000L; // 0..999999999 // offset 10ms in a new second pthread_mutex_lock(&SD.newpoint_lock); pthread_cond_timedwait(&SD.newpoint_cond, &SD.newpoint_lock, (const struct timespec *)&SD.t0); pthread_mutex_unlock(&SD.newpoint_lock); - SD.uptime++; gettimeofday(¤t_time, NULL); - cout << "MONITOR THREAD. now=" << current_time.tv_sec << "." << current_time.tv_usec - << " uptime=" << SD.uptime << " seconds" << endl; SD.tod = current_time.tv_sec; + SD.uptime++; + + secs = current_time.tv_sec; + now = gmtime(&secs); + sprintf(time_str, "%02d:%02d:%02d.%06ld", now->tm_hour, now->tm_min, now->tm_sec, current_time.tv_usec); + + cout << "[" << time_str << " (UTC)] " << "MONITOR THREAD: uptime=" << SD.uptime << " seconds" << endl; if (SD.unb != NULL) { // cout << "sdptr_monitor start" << endl; @@ -229,7 +239,6 @@ int main (int argc, char* argv[]) //openlog(basename(argv[0]), 0, LOG_LOCAL0); //syslog(LOG_INFO,"Starting server %s\n", SDPTR_VERSION); - if (!nodaemon) { if (daemon(1, 0) < 0) cerr << "Error fork as daemon: " << strerror(errno) << endl; } diff --git a/src/sdptr.h b/src/sdptr.h index b112ea7be397b63987a9845d46cbbacefb36e6b4..ebfc4c3329de2567171f509e573c5cb2b7400963 100644 --- a/src/sdptr.h +++ b/src/sdptr.h @@ -56,6 +56,7 @@ public: pthread_mutex_t newpoint_lock; std::atomic<uint32_t> uptime; + std::atomic<uint32_t> start_time; std::atomic<uint32_t> tod; std::atomic<bool> busy; }; diff --git a/src/tools/mmap.cpp b/src/tools/mmap.cpp index eed1055d5ecc9a67a0625edfa30f1b1d44483749..a14315eb00451ea62076cffa30885e2056ab7b2c 100644 --- a/src/tools/mmap.cpp +++ b/src/tools/mmap.cpp @@ -255,8 +255,8 @@ CMMap mmap_to_regmap(istringstream& iss) } } - cout << "regmap:" << endl; - regmap.print_screen(); + // cout << "regmap:" << endl; + // regmap.print_screen(); return regmap; } diff --git a/src/tools/util.cpp b/src/tools/util.cpp index a56aae66d4fa4569a16cffd1d621ae04bca45f52..538ec1d6d3860cb1dfc4499b0e95b1171bb24b33 100644 --- a/src/tools/util.cpp +++ b/src/tools/util.cpp @@ -29,6 +29,8 @@ #include <cmath> #include <iostream> #include <algorithm> +#include <ctime> +#include <sys/time.h> #include "util.h" @@ -94,10 +96,12 @@ vector<uint> unique_and_sort(vector<uint> v) return new_v; } +#define TIME_STR_LEN 20 + void Tictoc::tic(string idstr) { name = idstr; - cout << "tic: start [" << name << "]" << endl; + // cout << "tic: start [" << name << "]" << endl; c_start = clock(); t_start = chrono::high_resolution_clock::now(); } @@ -106,6 +110,15 @@ void Tictoc::toc(void) { clock_t c_end = clock(); auto t_end = chrono::high_resolution_clock::now(); + + struct timeval tv; + gettimeofday(&tv, NULL); + time_t secs = tv.tv_sec; + struct tm * now = gmtime(&secs); + char time_str[TIME_STR_LEN]; + sprintf(time_str, "%02d:%02d:%02d.%06ld", now->tm_hour, now->tm_min, now->tm_sec, tv.tv_usec); + + cout << "[" << time_str << " (UTC)] "; cout << "toc-tic (" << name << ") CPU time: " << 1000.0 * (c_end-c_start) / CLOCKS_PER_SEC << " ms. "; cout << "Real time: " << chrono::duration_cast<chrono::milliseconds>(t_end - t_start).count() diff --git a/src/tr.cpp b/src/tr.cpp index 9938d86b5650853bda298391d1ecfb20d31ffb77..f63ce90be75573e2d748e63547d180a69ca6cbd6 100644 --- a/src/tr.cpp +++ b/src/tr.cpp @@ -36,6 +36,7 @@ #include "tr.h" #include "sdptr.h" +#include "constants.h" using namespace std; @@ -48,14 +49,17 @@ TranslatorMap::TranslatorMap() { translatorMap = new CPointMap(); - translatorMap->add_register("TR_reload_RW", "-", 1, 1, "RW", REG_FORMAT_BOOLEAN); - translatorMap->add_register("TR_software_version_R", "-", 1, 1, "RO", REG_FORMAT_STRING); - translatorMap->add_register("TR_busy_R", "-", 1, 1, "RO", REG_FORMAT_BOOLEAN); - translatorMap->add_register("TR_tod_R", "-", 1, 1, "RO", REG_FORMAT_UINT32); - translatorMap->add_register("TR_uptime_R", "-", 1, 1, "RO", REG_FORMAT_UINT32); + translatorMap->add_register("TR_fpga_mask_R", "-", C_N_pn, 1, "RO", REG_FORMAT_BOOLEAN); + translatorMap->add_register("TR_fpga_mask_RW", "-", C_N_pn, 1, "RW", REG_FORMAT_BOOLEAN); + translatorMap->add_register("TR_software_version_R", "-", 1, 1, "RO", REG_FORMAT_STRING); + translatorMap->add_register("TR_start_time_R", "-", 1, 1, "RO", REG_FORMAT_UINT32); + // translatorMap->add_register("TR_tod_client_status_R", "-", 1, 1, "RO", REG_FORMAT_BOOLEAN); // TODO: PTP client is part of linux, can I get a status? + translatorMap->add_register("TR_tod_R", "-", 1, 1, "RO", REG_FORMAT_UINT32); + translatorMap->add_register("TR_tod_pps_delta_R", "-", 1, 1, "RO", REG_FORMAT_DOUBLE); + translatorMap->add_register("TR_fpga_communication_error_R", "-", C_N_pn, 1, "RO", REG_FORMAT_BOOLEAN); + // translatorMap->add_register("TR_reload_RW", "-", 1, 1, "RW", REG_FORMAT_BOOLEAN); // Maybe for future. } - TranslatorMap::~TranslatorMap() { if (translatorMap != NULL) { @@ -79,28 +83,78 @@ bool TranslatorMap::translator(TermOutput& termout, const char cmd, const string } int format = (int)translatorMap->getFormat(addr); - termout.nof_vals = translatorMap->getDataSize(addr); + uint32_t n_nodes = translatorMap->getNodesSize(addr); + uint32_t n_values = translatorMap->getDataSize(addr); + termout.nof_vals = n_nodes * n_values; termout.datatype = format; retval = true; - if (addr == "TR_reload_W") { + // reload is not used now, but maybe needed in future + // if (addr == "TR_reload_W") { + // if (cmd == 'W') { + // cout << "Tr: tr_reload_W: initiate RELOAD now" << endl; + // raise(SIGHUP); + // } + // } + // else + if (addr == "TR_fpga_mask_R") { + bool *ptr_out = (bool *)termout.val; + vector<bool> masked = SD.unb->get_all_masked_nodes(); + for (auto val : masked) { + *ptr_out = val; + ptr_out++; + } + } + else if (addr == "TR_fpga_mask_RW") { if (cmd == 'W') { - cout << "Tr: tr_reload_W: initiate RELOAD now" << endl; - raise(SIGHUP); + bool *ptr_in = (bool *)data; + vector<bool> masked; + for (uint i=0; i<n_nodes; i++) { + masked.push_back(*ptr_in); + ptr_in++; + } + SD.unb->set_all_masked_nodes(masked); + } + else { + bool *ptr_out = (bool *)termout.val; + vector<bool> masked = SD.unb->get_all_masked_nodes(); + for (auto val : masked) { + *ptr_out = val; + ptr_out++; + } } } else if (addr == "TR_software_version_R") { strcpy(termout.val, SDPTR_VERSION); } - else if (addr == "TR_busy_R") { - bool *ptr_out = (bool *)termout.val; - *ptr_out = (bool)SD.busy; - } else if (addr == "TR_tod_R") { uint32_t *ptr_out = (uint32_t *)termout.val; *ptr_out = (uint32_t)SD.tod; } + else if (addr == "TR_tod_pps_delta_R") { + double *ptr_out = (double *)termout.val; + vector<uint32_t> pps_offset_cnt = SD.unb->get_all_pps_offset_cnt(); + cout << "pps_offset_cnt=" << pps_offset_cnt[0] << endl; + double pps_delta = (double)(pps_offset_cnt[0] * C_200MHZ_1_CNT_NS); + *ptr_out = pps_delta; + } + else if (addr == "TR_start_time_R") { + uint32_t *ptr_out = (uint32_t *)termout.val; + *ptr_out = (uint32_t)SD.start_time; + } + else if (addr == "TR_fpga_communication_error_R") { + bool *ptr_out = (bool *)termout.val; + vector<bool> offline = SD.unb->get_all_offline_nodes(); + for (auto val : offline) { + *ptr_out = val; + ptr_out++; + } + } + else if (addr == "TR_busy_R") { + bool *ptr_out = (bool *)termout.val; + *ptr_out = (bool)SD.busy; + } else if (addr == "TR_uptime_R") { uint32_t *ptr_out = (uint32_t *)termout.val; *ptr_out = (uint32_t)SD.uptime; diff --git a/test/py/Client.py b/test/py/Client.py index aa4e99d2fc65d7038bb8c1e53619614828397708..7a019e3920f5b0b67b15985563ec89ba73c56bd1 100644 --- a/test/py/Client.py +++ b/test/py/Client.py @@ -23,18 +23,6 @@ # Purpose: # . script to test (control/monitor) opc-ua server # Description: -# Client.py is used to connect (TCP/IP) to an opc-ua server and test (read/write) -# opc-ua points (registers on a fpga). -# For LTS the server is running on DOP36 port 4840, this client can not run -# on DOP36 itself (too old system). -# -# In this version the following is working: -# . --info, read info from server, list all available points on the server. -# . --all, read all *_R point and print needed time. -# . --wg, turn off WG or setup for XST (to generate crosslets plot). -# . --setup, setup SST, BST and XST stream. -# . --stream, turn off or on SST, BST or XST stream. -# # . run ./Client.py -h for help # ########################################################################## @@ -53,6 +41,12 @@ N_NODES = 16 S_PN = 12 N_SUB = 512 + +# +# '2:' in child name is space it belongs to. 2: is "http://lofar.eu". +# + + # timing decorator # put @timing for the function to time def timing(f): @@ -132,6 +126,7 @@ def explore_temp(node): @timing def check_get_all_R_time(obj): + # '2:' = space 2 is "http://lofar.eu". info = [] info.append(str(obj.get_child("2:FPGA_bsn_monitor_input_bsn_R").get_value())) info.append(str(obj.get_child("2:FPGA_bsn_monitor_input_nof_err_R").get_value())) @@ -143,7 +138,6 @@ def check_get_all_R_time(obj): info.append(str(obj.get_child("2:FPGA_jesd204b_csr_rbd_count_R").get_value())) info.append(str(obj.get_child("2:FPGA_jesd204b_rx_err0_R").get_value())) info.append(str(obj.get_child("2:FPGA_jesd204b_rx_err1_R").get_value())) - info.append(str(obj.get_child("2:FPGA_mask_R").get_value())) info.append(str(obj.get_child("2:FPGA_processing_enable_R").get_value())) info.append(str(obj.get_child("2:FPGA_sdp_info_antenna_band_index_R").get_value())) info.append(str(obj.get_child("2:FPGA_sdp_info_block_period_R").get_value())) @@ -170,7 +164,6 @@ def check_get_all_R_time(obj): info.append(str(obj.get_child("2:FPGA_xst_offload_hdr_eth_destination_mac_R").get_value())) info.append(str(obj.get_child("2:FPGA_xst_offload_hdr_ip_destination_address_R").get_value())) info.append(str(obj.get_child("2:FPGA_xst_offload_hdr_udp_destination_port_R").get_value())) - info.append(str(obj.get_child("2:FPGA_status_R").get_value())) info.append(str(obj.get_child("2:FPGA_subband_weights_R").get_value())) info.append(str(obj.get_child("2:FPGA_temp_R").get_value())) info.append(str(obj.get_child("2:FPGA_weights_R").get_value())) @@ -178,10 +171,12 @@ def check_get_all_R_time(obj): info.append(str(obj.get_child("2:FPGA_wg_enable_R").get_value())) info.append(str(obj.get_child("2:FPGA_wg_frequency_R").get_value())) info.append(str(obj.get_child("2:FPGA_wg_phase_R").get_value())) - info.append(str(obj.get_child("2:TR_busy_R").get_value())) + info.append(str(obj.get_child("2:TR_fpga_mask_R").get_value())) info.append(str(obj.get_child("2:TR_software_version_R").get_value())) + info.append(str(obj.get_child("2:TR_start_time_R").get_value())) info.append(str(obj.get_child("2:TR_tod_R").get_value())) - info.append(str(obj.get_child("2:TR_uptime_R").get_value())) + info.append(str(obj.get_child("2:TR_tod_pps_delta_R").get_value())) + #info.append(str(obj.get_child("2:TR_uptime_R").get_value())) print(f"checked {len(info)} FPGA_*_R points") # print('\n'.join(info)) @@ -194,12 +189,12 @@ def write_fpga_mask(obj, nodes=None, mask=None): for node in list(nodes): enable_mask[node] = True #print(enable_mask) - var = obj.get_child("2:FPGA_mask_RW") + var = obj.get_child("2:TR_fpga_mask_RW") var.set_value(ua.Variant(value=list(enable_mask), varianttype=ua.VariantType.Boolean)) def get_fpga_mask(obj): - var = obj.get_child("2:FPGA_mask_R") + var = obj.get_child("2:TR_fpga_mask_R") enable_mask = var.get_value() #print(enable_mask) return enable_mask @@ -411,7 +406,7 @@ if __name__ == "__main__": if args.wg_mode is not None: if args.wg_mode == 'OFF': - turn_wg_off(obj) + turn_wg_off(Object) elif args.wg_mode == 'XST': setup_wg_xst_mode(Object)