Commit 6f50731b authored by Carlo Alberto Gottardo's avatar Carlo Alberto Gottardo
Browse files

Updated from master

parents 496b01db 0c2fc7b8
Pipeline #2428474 failed with stages
in 2 seconds
image: gitlab-registry.cern.ch/atlas-dcs-common-software/docker-runners:sca-software
variables:
FELIX_VERSION: 04-01-00-stand-alone
FELIX_VERSION: felix-04-01-01-stand-alone
COMPILER: gcc8-opt
GIT_STRATEGY: fetch
GIT_SUBMODULE_STRATEGY: recursive
......@@ -14,15 +14,14 @@ stages:
setup:
stage: setup
script:
- source /felix-${FELIX_VERSION}/x86_64-centos7-${COMPILER}/setup.sh
- source /${FELIX_VERSION}/x86_64-centos7-${COMPILER}/setup.sh
- source setup_paths.sh
build:
stage: build
script:
- source /felix-${FELIX_VERSION}/x86_64-centos7-${COMPILER}/setup.sh
- source setup_paths.sh
- ./build_standalone.sh
- source /${FELIX_VERSION}/x86_64-centos7-${COMPILER}/setup.sh
- ./build_sca_next.sh
artifacts:
name: "ScaSoftwareTools-$CI_COMMIT_REF_NAME"
paths:
......@@ -35,13 +34,14 @@ build:
- build/Demonstrators/StandaloneSpiSimulation/standalone_spi
- build/Demonstrators/SimulatorOverNetIo/simulator_netio
- build/Demonstrators/Timing/timing
- Demonstrators/README.md
package:
stage: package
dependencies:
- build
script:
- sh package_tools.sh $CI_COMMIT_REF_NAME
- ./package_tools.sh $CI_COMMIT_REF_NAME
environment:
name: debug
artifacts:
......
......@@ -53,7 +53,6 @@ if (HAVE_NETIO_NEXT)
include_directories( $ENV{TBB_HEADERS} )
link_directories( $ENV{TBB_LIB_DIRECTORIES} )
endif()
if( STANDALONE_SCA_SOFTWARE )
......@@ -83,7 +82,7 @@ if (HAVE_NETIO)
endif()
if (HAVE_NETIO_NEXT)
message(AUTHOR_WARNING "Adding netio-next backend")
message(STATUS "Adding netio-next backend")
add_definitions( -DHAVE_NETIO_NEXT )
file(GLOB NETIO_NEXT_BACKEND_SRCS
NetioNextBackend/*.cpp
......
......@@ -20,6 +20,7 @@ constexpr char helpForAddress[] =
"sca-simulator://<1> (for pure simulation) \n\n"
"simple-netio://direct/<hostname>/<portFromHost>/<portToHost>/<elink> (via felixcore, same elink for TX and RX; elink in hex) \n\n"
"simple-netio://direct/<hostname>/<portFromHost>/<portToHost>/<elinkTx>/<elinkRx> (via felixcore, elinks differ for TX and RX; elinks in hex) \n\n"
"netio-next://fid/<hostname>/<FromHostFid>/<ToHostFid> \n\n"
"Triangle brackets <> indicate variable parts\n\n";
}
......
Standalone Demonstrators
------------------------
The standalone demonstrators do not rely on the OPC UA stack and for that are lightweight C++ applications to communicate with SCAs over netIO.
They can run on a felix or a non-felix machine and communicate over the network with a running felixcore.
Why am I failing to run a demonstrator?
The basic dependencies that the SCA standalone demonstrators require in order to run are:
1. Boost libraries: Having cvmfs available is enough. There is nothing else to do.
2. Felix libraries: This can be done by sourcing the setup.sh script provided with every FELIX release.
Note: Always use the demonstrators with their corresponding FELIX release to avoid incompatibilities. The correspondence is currently mentioned in every release of the SCA OPC UA server here: https://gitlab.cern.ch/atlas-dcs-opcua-servers/ScaOpcUa/-/releases. The tags of SCA OPC UA match the ones of ScaSoftware.
......@@ -72,4 +72,13 @@ std::string Payload::toString() const
return out.str();
}
uint8_t Payload::operator[](unsigned int index) const
{
if ( index >= m_dataSize )
THROW_WITH_ORIGIN(
std::runtime_error,
"out-of-bounds, payload size is " + std::to_string(m_dataSize) + " while requested index was " + std::to_string(index));
return m_data[ index ];
}
}
/*
* HdlcBackend.cpp
*
* Created on: Oct 13, 2020, pmoschov
* Created on: Oct 13, 2020
* Author: Paris Moschovakos (paris.moschovakos@cern.ch)
*
* Description : Backend implementation for netio-next
*
* 1. netio-next documentation
* https://atlas-project-felix.web.cern.ch/atlas-project-felix/dev/staging/www/netio/topic/docs/index.html
*
* 2. felix-client-interface documentation
* https://atlas-project-felix.web.cern.ch/atlas-project-felix/user/felix-user-manual/versions/Latest/8_felix_star.html#_8_9_connecting_to_felix_star_using_the_felix_client_interface
*
*/
#include <algorithm>
......@@ -18,21 +28,17 @@
#include "felix/felix_client_properties.h"
// 1. netio-next documentation
// https://atlas-project-felix.web.cern.ch/atlas-project-felix/dev/staging/www/netio/topic/docs/index.html
//
// 2. felix-client-interface documentation
// https://atlas-project-felix.web.cern.ch/atlas-project-felix/user/felix-user-manual/versions/Latest/8_felix_star.html#_8_9_connecting_to_felix_star_using_the_felix_client_interface
using Sca::LogComponentLevels;
using namespace std::chrono_literals;
namespace NetioNextBackend
{
HdlcBackend::HdlcBackend (const std::string& netioNextAddress):
m_originalNetioNextAddress(netioNextAddress),
m_netioNextAddress( std::make_shared<NetioNextAddress>(netioNextAddress) ),
m_seqnr(7), // will be incremented before 1st use, and it is modulo 8,
m_netioNextAddress( std::make_shared<NetioNextAddress>(netioNextAddress) ),
m_seqnr(7), // will be incremented before 1st use, and it is modulo 8,
m_clientSubscribed(false),
m_felixConfigOnData( std::bind( &HdlcBackend::on_data, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3, std::placeholders::_4 ) ),
m_felixConfigOnInit( std::bind( &HdlcBackend::on_init, this) ),
m_felixConfigOnConnect( std::bind( &HdlcBackend::on_connect, this, std::placeholders::_1 ) ),
......@@ -56,30 +62,38 @@ HdlcBackend::HdlcBackend (const std::string& netioNextAddress):
m_felixClient(m_felixConfig)
{
LOG(Log::INF, LogComponentLevels::netioNext()) << "Connecting to felixBus at " << m_netioNextAddress->felixbusAddess()
LOG(Log::INF, LogComponentLevels::netioNext()) << "Connecting to felixBus at " << m_netioNextAddress->felixbusAddess()
<< " using felix ID from SCA: 0x" << std::hex << m_netioNextAddress->fidRx()
<< " and felix ID to SCA: 0x" << m_netioNextAddress->fidTx();
<< " and felix ID to SCA: 0x" << m_netioNextAddress->fidTx();
try
{
LOG(Log::DBG, LogComponentLevels::netioNext()) << "Subscribing to felix ID: 0x" << std::hex << m_netioNextAddress->fidRx();
{
LOG(Log::DBG, LogComponentLevels::netioNext()) << "Subscribing to felix ID: 0x" << std::hex << m_netioNextAddress->fidRx();
// Wait until subscribed, when so continue
std::unique_lock<decltype(m_subscribeSynchronizationMutex)> uniqueLock(m_subscribeSynchronizationMutex);
m_felixClient.subscribe(m_netioNextAddress->fidRx());
m_clientSubscribed = true;
// TODO: Since subscription takes quite some time, we should wait here
// That should be removed when felix-star is in better shape
usleep(1000000);
m_subscribedConditionVariable.wait_for(uniqueLock, 1000ms, [&](){ return m_clientSubscribed; });
sendHdlcControl( Hdlc::HdlcControlCodes::RESET );
if (m_clientSubscribed)
{
sendHdlcControl( Hdlc::HdlcControlCodes::RESET );
}
else
{
std::stringstream stream;
stream << std::hex << m_netioNextAddress->fidRx();
LOG(Log::ERR, LogComponentLevels::netioNext()) << std::string("Timeout while subscribing fid: 0x") + stream.str() << ". netio-next subscription might have failed.";
sendHdlcControl( Hdlc::HdlcControlCodes::RESET );
}
}
catch (const std::exception &e )
{
LOG(Log::ERR, LogComponentLevels::netioNext()) << "Exception: " << e.what();
cleanUp();
throw e;
}
}
catch (const std::exception &e )
{
LOG(Log::ERR, LogComponentLevels::netioNext()) << "Exception: " << e.what();
cleanUp();
throw e;
}
}
HdlcBackend::~HdlcBackend ()
......@@ -177,7 +191,7 @@ void HdlcBackend::sendHdlcControl (uint8_t hdlcControl)
void HdlcBackend::cleanUp ()
{
LOG(Log::INF, LogComponentLevels::netioNext()) << "Unsubscribing from felix ID 0x" << m_netioNextAddress->fidRx();
LOG(Log::INF, LogComponentLevels::netioNext()) << "Cleaning up felix ID 0x" << std::hex << m_netioNextAddress->fidRx();
if (m_clientSubscribed)
{
......@@ -201,17 +215,38 @@ void HdlcBackend::cleanUp ()
void HdlcBackend::on_init()
{
LOG(Log::DBG, LogComponentLevels::netioNext()) << "Felix client initializing...";
}
void HdlcBackend::on_connect(uint64_t fid)
{
LOG(Log::DBG, LogComponentLevels::netioNext()) << "0x" << std::hex << fid << " connected";
LOG(Log::DBG, LogComponentLevels::netioNext()) << "Connection established for felix ID 0x" << std::hex << fid;
if ( fid == m_netioNextAddress->fidRx() )
{
std::lock_guard<decltype(m_subscribeSynchronizationMutex)> lockGuard(m_subscribeSynchronizationMutex);
m_clientSubscribed = true;
m_subscribedConditionVariable.notify_one();
}
}
void HdlcBackend::on_disconnect(uint64_t fid)
{
LOG(Log::DBG, LogComponentLevels::netioNext()) << "0x" << std::hex << fid << " disconnected";
LOG(Log::DBG, LogComponentLevels::netioNext()) << "felix ID 0x" << std::hex << fid << " was disconnected";
if ( fid == m_netioNextAddress->fidRx() )
{
std::lock_guard<decltype(m_subscribeSynchronizationMutex)> lockGuard(m_subscribeSynchronizationMutex);
m_clientSubscribed = false;
}
}
void HdlcBackend::on_data(uint64_t fid, const uint8_t* data, size_t size, uint8_t status)
......@@ -220,38 +255,38 @@ void HdlcBackend::on_data(uint64_t fid, const uint8_t* data, size_t size, uint8_
LOG(Log::TRC, LogComponentLevels::netioNext()) << "At SCA with address: '" + getAddress() + "' received reply";
if ( size > 20 )
{
LOG(Log::ERR, LogComponentLevels::netioNext()) << "At SCA with address: '" + getAddress() + "' avoiding possibly extra large netIO frame. (size=" << (int)size << " bytes)";
return;
}
{
LOG(Log::ERR, LogComponentLevels::netioNext()) << "At SCA with address: '" + getAddress() + "' avoiding possibly extra large netIO frame. (size=" << (int)size << " bytes)";
return;
}
std::vector<uint8_t> netioNextFrame (data, data + size);
// Valid SCA frame sizes are 8, 10 and 12 bytes.
// Valid SCA HDLC frames can also be 4 (UA) and 6 (SREJ) bytes.
switch(netioNextFrame.size()) {
case 8 :
case 10 :
case 12 :
break;
case 4 :
case 6 : {
HdlcFrameTranslator HdlcFrameTranslator(netioNextFrame, m_netioNextAddress);
return;
}
default: {
LOG(Log::ERR, LogComponentLevels::netioNext()) << "At SCA with address: '" + getAddress() + "' "
// Valid SCA HDLC frames can also be 4 (UA) and 6 (SREJ) bytes.
switch(netioNextFrame.size()) {
case 8 :
case 10 :
case 12 :
break;
case 4 :
case 6 : {
HdlcFrameTranslator HdlcFrameTranslator(netioNextFrame, m_netioNextAddress);
return;
}
default: {
LOG(Log::ERR, LogComponentLevels::netioNext()) << "At SCA with address: '" + getAddress() + "' "
<< "discarding incoming netio-next frame containg an SCA reply of unexpected size. SCA reply size was "
<< netioNextFrame.size() << " bytes (expected SCA replies sizes are 4, 6, 8, 10 or 12 bytes)";
LOG(Log::DBG, LogComponentLevels::netioNext()) << "At SCA with address: '" + getAddress() + "' raw bytes of the netio-next frame with unexpected size: 0x " << vectorAsHex(netioNextFrame);
return;
}
}
return;
}
}
// Validate HDLC FCS
if (!validateFcs(netioNextFrame.begin(), netioNextFrame.end()))
if (!validateFcs(netioNextFrame.begin(), netioNextFrame.end()))
{
LOG(Log::ERR, LogComponentLevels::netioNext()) << "At SCA with address: '" + getAddress() + "' HDLC checksum mismatch on incoming frame, discarding";
LOG(Log::DBG, LogComponentLevels::netioNext()) << "At SCA with address: '" + getAddress() + "' raw bytes of the netIO frame with invalid FCS: 0x " << vectorAsHex(netioNextFrame);
......@@ -259,19 +294,19 @@ void HdlcBackend::on_data(uint64_t fid, const uint8_t* data, size_t size, uint8_
}
// Cut the Address and the Control field from the HDLC frame | and the FCS at the end -- Paris
uint8_t* hdlcPayloadPtr = &netioNextFrame[ HDLC_FRAME_PAYLOAD_OFFSET ];
uint8_t* hdlcPayloadPtr = &netioNextFrame[ HDLC_FRAME_PAYLOAD_OFFSET ];
try // the following may throw if the reply is mutilated, too big, etc.
{
try // the following may throw if the reply is mutilated, too big, etc.
{
Hdlc::Payload payload( hdlcPayloadPtr, netioNextFrame.size() - HDLC_FRAME_PAYLOAD_OFFSET - HDLC_FRAME_TRAILER_SIZE);
std::for_each( m_receivers.begin(), m_receivers.end(), [&payload]( ReceiveCallBack& cb){ cb(payload); });
}
catch (const std::exception& e)
{
LOG(Log::TRC, LogComponentLevels::netioNext()) << "At SCA with address: '" + getAddress() + "' ignoring reply: " << e.what();
}
}
catch (const std::exception& e)
{
LOG(Log::TRC, LogComponentLevels::netioNext()) << "At SCA with address: '" + getAddress() + "' ignoring reply: " << e.what();
}
m_statistician.onFrameReceived();
m_statistician.onFrameReceived();
}
......
......@@ -21,8 +21,8 @@ NetioNextAddress::NetioNextAddress (const std::string& stringAddress):
// Address concept idea attributed to Piotr
boost::regex fidAddressRegex( "^fid\\/"
"(?<felixbus>[a-zA-Z0-9][a-zA-Z0-9-]+(?:\\.[a-zA-Z0-9-]+)*)\\/"
"(?<fid_from_sca>(0[xX])?[0-9a-fA-F]+)\\/"
"(?<fid_to_sca>(0[xX])?[0-9a-fA-F]+)"
"(?<fid_to_sca>(0[xX])?[0-9a-fA-F]+)\\/"
"(?<fid_from_sca>(0[xX])?[0-9a-fA-F]+)"
"$"
);
boost::smatch matchResults;
......
......@@ -10,15 +10,14 @@ https://gitlab.cern.ch/atlas-dcs-common-software/ScaSoftware/-/releases
For building standalone SCA SW, just use
```
source setup_paths.sh
build_standalone.sh
build_sca_next.sh
```
Note that:
1. By default, the software builds with netio and other parts of the TDAQ FELIX Software.
You can remove netio dependency by changing, in build_standalone, HAVE_NETIO to 0.
1. By default, the software builds with netio-next, netio and other parts of the TDAQ FELIX Software.
You can remove netio-next and netio dependencies by changing, in build_sca_next, HAVE_NETIO_NEXT and/or HAVE_NETIO to 0.
2. The easiest way to get netio and TDAQ FELIX is to get the distro from:
2. The easiest way to get netio-next/netio and TDAQ FELIX is to get the distro from:
https://atlas-project-felix.web.cern.ch/atlas-project-felix/user/dist/software/apps/
3. Please note that you should use exactly same compiler as the one used for TDAQ FELIX chain. For that source the setup_paths.sh to define your environment.
......
......@@ -5,7 +5,8 @@ echo You need to provide a valid FELIX_ROOT which should contain the dependancie
rm -Rf build
mkdir build
cd build
cmake ../ -DSTANDALONE_SCA_SOFTWARE=1 -DHAVE_NETIO_NEXT=1 -DSTANDALONE_WITH_EVENT_RECORDER=OFF -DCMAKE_BUILD_TYPE=Debug
make -j `nproc` || exit 1
cmake ../ -DSTANDALONE_SCA_SOFTWARE=1 -DHAVE_NETIO_NEXT=1 -DHAVE_NETIO=1 -DSTANDALONE_WITH_EVENT_RECORDER=OFF -DCMAKE_BUILD_TYPE=Debug
NUM_JOBS=$((2*`nproc`))
make -j $NUM_JOBS || exit 1
cd ..
echo "Built standalone ScaSoftware with netio-next"
......@@ -35,7 +35,7 @@ namespace Hdlc {
std::string toString() const;
uint8_t operator[](unsigned int index) const { if ( index >= m_dataSize ) THROW_WITH_ORIGIN(std::runtime_error,"out-of-bounds"); return m_data[ index ]; }
uint8_t operator[](unsigned int index) const;
//! STL type const-iterators
const uint8_t* cbegin() const { return m_data; }
......
......@@ -3,6 +3,7 @@
#include <memory>
#include <list>
#include <mutex>
#include <condition_variable>
#include <Hdlc/Backend.h>
#include <Hdlc/Payload.h>
......@@ -47,6 +48,8 @@ private:
unsigned int m_seqnr; // HDLC sequence number
bool m_clientSubscribed;
std::mutex m_subscribeSynchronizationMutex;
std::condition_variable m_subscribedConditionVariable;
std::mutex m_transmitSynchronizationMutex;
......
......@@ -47,6 +47,10 @@ public:
enum SlotState { Unused, Expected, Received };
struct SlotInformation
{
SlotInformation (SlotState initState = SlotState::Unused) :
state(initState),
replyIndex(0)
{}
SlotState state;
unsigned char replyIndex;
......@@ -55,7 +59,7 @@ public:
void clear()
{
// put the whole array to UNUSED state
m_slots.assign( m_slots.size(), SlotInformation{.state = SlotState::Unused} );
m_slots.assign( m_slots.size(), SlotInformation(SlotState::Unused) );
}
/*
......
#!/usr/bin/env bash
echo "Package tools: trying to create a package for commit id $1"
DIR=ScaSoftwareTools-$1
rm -Rf $DIR $DIR".tar.gz"
mkdir $DIR
cp build/Demonstrators/Timing/timing build/Demonstrators/SimulatorOverNetIo/simulator_netio build/Demonstrators/StandaloneI2cSimulation/standalone_i2c build/Demonstrators/GbtxConfiguration/gbtx_configuration build/Demonstrators/HenksFScaJtag/fscajtag build/Demonstrators/PingSca/ping_sca build/Demonstrators/StandaloneAdcSimulation/standalone_adc build/Demonstrators/StandaloneDacSimulation/standalone_dac build/Demonstrators/StandaloneSpiSimulation/standalone_spi $DIR
cp build/Demonstrators/Timing/timing build/Demonstrators/SimulatorOverNetIo/simulator_netio build/Demonstrators/StandaloneI2cSimulation/standalone_i2c build/Demonstrators/GbtxConfiguration/gbtx_configuration build/Demonstrators/HenksFScaJtag/fscajtag build/Demonstrators/PingSca/ping_sca build/Demonstrators/StandaloneAdcSimulation/standalone_adc build/Demonstrators/StandaloneDacSimulation/standalone_dac build/Demonstrators/StandaloneSpiSimulation/standalone_spi Demonstrators/README.md $DIR
tar cf $DIR".tar" $DIR
gzip -9 $DIR".tar"
\ No newline at end of file
gzip -9 $DIR".tar"
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