diff --git a/scripts/generate_configs.sh b/scripts/generate_configs.sh new file mode 100644 index 0000000000000000000000000000000000000000..119c71dd67519aa79030fe110da62756e0c395ab --- /dev/null +++ b/scripts/generate_configs.sh @@ -0,0 +1,78 @@ +#!/bin/bash + +# TODO: beware, some numbers/strings here have to be considered just as an example +# TODO: and to run local tests. For production purposes, we might need to update some +# TODO: fields here +source=$1 +scone_board=$2 +source_id_min=$3 +tcp_dest_port_min=$4 +threads=$5 +out_force_write=$6 +loglevel=$7 +rc_port=$8 + + +if [ ${source} == "ugmt" ]; then + nstreams=1 + source_id=($(for (( c=1; c<=${nstreams}; c++)) ; do echo -n $(((c-1)+source_id_min)); echo -n " " ; done)) + out_prefix="scout_GMT" + out_base="/fff/ramdisk/BU0/" + out_suffix=(".raw") + processor_type=($(for (( c=1; c<=${nstreams}; c++)) ; do echo -n "GMT"; echo -n " " ; done)) + tcp_dest_port=($(for (( c=1; c<=${nstreams}; c++)) ; do echo -n $((10*(c-1)+tcp_dest_port_min)); echo -n " " ; done)) + primitive_type=($(for (( c=1; c<=${nstreams}; c++)) ; do echo -n "MUON"; echo -n " " ; done)) +elif [ ${source} == "calo" ]; then + nstreams=4 + source_id=($(for (( c=1; c<=${nstreams}; c++)) ; do echo -n $(((c-1)+source_id_min)); echo -n " " ; done)) + # source_id=(2 3 4 5) + out_prefix="scout_CALO" + out_base="/fff/ramdisk/BU0/" + out_suffix=($(for (( c=1; c<=4; c++)) ; do echo -n ".raw_${c}"; echo -n " " ; done)) + processor_type=("CALOOBJ" "CALOOBJ" "CALOSUM" "CALOOBJ") + tcp_dest_port=($(for (( c=1; c<=${nstreams}; c++)) ; do echo -n $((10*(c-1)+tcp_dest_port_min)); echo -n " " ; done)) + primitive_type=("JET" "EGAMMA" "SUM" "TAU") +elif [ ${source} == "bmtf" ]; then + nstreams=12 + source_id=($(for (( c=1; c<=${nstreams}; c++)) ; do echo -n $(((c-1)+source_id_min)); echo -n " " ; done)) + out_prefix="scout_BMTF" + out_base="/fff/ramdisk/BU2/" + out_suffix=($(for (( c=6; c<=17; c++)) ; do echo -n ".raw_${c}"; echo -n " " ; done)) + processor_type=($(for (( c=1; c<=${nstreams}; c++)) ; do echo -n "BMTF"; echo -n " " ; done)) + tcp_dest_port=($(for (( c=1; c<=${nstreams}; c++)) ; do echo -n $((10*(c-1)+tcp_dest_port_min)); echo -n " " ; done)) + primitive_type=($(for (( c=1; c<=${nstreams}; c++)) ; do echo -n "STUB"; echo -n " " ; done)) +elif [ ${source} == "ugt" ]; then + nstreams=1 + source_id=($(for (( c=1; c<=${nstreams}; c++)) ; do echo -n $(((c-1)+source_id_min)); echo -n " " ; done)) + out_prefix="scout_UGT" + out_base="/fff/ramdisk/BU3/" + out_suffix=(".raw_5") + processor_type=("UGT") + tcp_dest_port=($(for (( c=1; c<=${nstreams}; c++)) ; do echo -n $((10*(c-1)+tcp_dest_port_min)); echo -n " " ; done)) + primitive_type=($(for (( c=1; c<=${nstreams}; c++)) ; do echo -n "ALGOBIT"; echo -n " " ; done)) +fi + + +for i in `seq 1 ${nstreams}`; do + cp scdaq-template.conf scdaq-${source}${i}.conf + idx=$((i-1)) + tcp_dest_port_i=${tcp_dest_port[$idx]} + source_id_i=${source_id[$idx]} + out_suffix_i=${out_suffix[$idx]} + processor_type_i=${processor_type[$idx]} + primitive_type_i=${primitive_type[$idx]} + + echo "${source_id_i} ${tcp_dest_port_i} ${processor_type_i} ${primitive_type_i} ${out_base} ${out_suffix_i}" + sed -i -e "s/log_min_severity:/log_min_severity:${loglevel}/g" scdaq-${source}${i}.conf + sed -i -e "s/threads:/threads:${threads}/g" scdaq-${source}${i}.conf + sed -i -e "s/tcpDestPort:/tcpDestPort:${tcp_dest_port_i}/g" scdaq-${source}${i}.conf + sed -i -e "s/source_id:/source_id:${source_id_i}/g" scdaq-${source}${i}.conf + sed -i -e "s/output_filename_prefix:/output_filename_prefix:${out_prefix}/g" scdaq-${source}${i}.conf + sed -i -e "s|output_filename_base:|output_filename_base:${out_base}|g" scdaq-${source}${i}.conf + sed -i -e "s/output_filename_suffix:/output_filename_suffix:${out_suffix_i}/g" scdaq-${source}${i}.conf + sed -i -e "s/output_force_write:/output_force_write:${out_force_write}/g" scdaq-${source}${i}.conf + sed -i -e "s/processor_type:/processor_type:${processor_type_i}/g" scdaq-${source}${i}.conf + sed -i -e "s/primitive_type:/primitive_type:${primitive_type_i}/g" scdaq-${source}${i}.conf + sed -i -e "s/scone_board:/scone_board:${scone_board}/g" scdaq-${source}${i}.conf + sed -i -e "s/ port:/port:${rc_port}/g" scdaq-${source}${i}.conf +done diff --git a/src/calo_obj_orbit_processor.h b/src/calo_obj_orbit_processor.h index dcd361c192397ae03fce1828161e76cd0fe343cd..0fbf91955861d380e5703ea3b14c766acd4f75f4 100644 --- a/src/calo_obj_orbit_processor.h +++ b/src/calo_obj_orbit_processor.h @@ -34,12 +34,12 @@ class CaloObjOrbitProcessor : public OrbitProcessor { BxMetadata meta) override; inline uint32_t GetPacketSize() const override { - // size of calo object packet is 4bytes*(3headerWords + 2frames*8dataWords)=76 - return 4 * (3 + (2 * 8)); + // maximum size of calo object packet is 4bytes*(3headerWords + 12objects)=60 + return 4 * (3 + 12); } inline uint32_t GetOrbitSizeInBytes(const FillOrbitMetadata &meta) const override { - return GetPacketSize() * meta.filled_bxs; + return meta.counts * 4 + 12 * meta.filled_bxs; } uint32_t shiftsCaloObjEt; diff --git a/src/calo_sum_orbit_processor.h b/src/calo_sum_orbit_processor.h index 0f45816440ca0e6485cad342dba28cedbcbe1e62..f13fafa62bb5fe20ff2d38c68fc5998b1b86aad1 100644 --- a/src/calo_sum_orbit_processor.h +++ b/src/calo_sum_orbit_processor.h @@ -11,8 +11,8 @@ class CaloSumOrbitProcessor : public OrbitProcessor { BxMetadata meta) override; inline uint32_t GetPacketSize() const override { - // size of calo sums packet is 4bytes*(2headerWords + 1frames*8dataWords)=40 - return 4 * (2 + (1 * 8)); + // size of calo sums packet is 4bytes*(2headerWords + 6sums)=32 + return 4 * (2 + 6); } inline uint32_t GetOrbitSizeInBytes(const FillOrbitMetadata &meta) const override { diff --git a/src/format.h b/src/format.h index 50a350163e1800525744144b34a610db6b61fb40..fe1248bf1f9c216a90a294f36e0862ee0c3be1a1 100644 --- a/src/format.h +++ b/src/format.h @@ -31,12 +31,12 @@ struct block_calo_packed { }; struct blockMuon { - uint32_t orbit[8]; - uint32_t bx[8]; - uint32_t mu1f[8]; - uint32_t mu1s[8]; - uint32_t mu2f[8]; - uint32_t mu2s[8]; + uint32_t orbit[4]; + uint32_t bx[4]; + uint32_t mu1f[4]; + uint32_t mu1s[4]; + uint32_t mu2f[4]; + uint32_t mu2s[4]; }; struct blockBmtf { diff --git a/src/muon_orbit_processor.cc b/src/muon_orbit_processor.cc index 215bbfda3770d88f19f2eafb45203e97b351d79b..8b14375d70c30bf6ef93f9256cab50f84c5af150 100644 --- a/src/muon_orbit_processor.cc +++ b/src/muon_orbit_processor.cc @@ -14,7 +14,7 @@ int MuonOrbitProcessor::ProcessBlock(MemRegion &readable_block, WriteMemRegion & using SourceDataType = blockMuon; using SinkDataType = MuonLinkData; - const uint32_t source_data_length = 8; // Dictates maximum size comported by the sink + const uint32_t source_data_length = 4; // Dictates maximum size comported by the sink assert(readable_block.CheckBounds(sizeof(SourceDataType))); SourceDataType *bl = readable_block.Scan<SourceDataType>(); @@ -25,14 +25,12 @@ int MuonOrbitProcessor::ProcessBlock(MemRegion &readable_block, WriteMemRegion & const auto pt1 = uint32_t{(bl->mu1f[i] >> shifts::pt) & masks::pt}; const auto pt2 = uint32_t{(bl->mu2f[i] >> shifts::pt) & masks::pt}; - // mu.extra is a copy of bl->bx with a change to the first bit. + // mu.extra is a copy of bl->bx if (((pt1 > 0) || (doZS == 0))) { - // set bit0 to "0" for first muon - bx_data_1.Add({bl->mu1f[i], bl->mu1s[i], bl->bx[i] &= ~0x1}); + bx_data_1.Add({bl->mu1f[i], bl->mu1s[i], bl->bx[i]}); } if (((pt2 > 0) || (doZS == 0))) { - // set bit0 to "1" for second muon - bx_data_2.Add({bl->mu2f[i], bl->mu2s[i], bl->bx[i] |= 0x1}); + bx_data_2.Add({bl->mu2f[i], bl->mu2s[i], bl->bx[i]}); } } diff --git a/src/muon_orbit_processor.h b/src/muon_orbit_processor.h index d2f87f46159969721de900ffd83734681267580e..bc5c084eb6000ad7c3b457d87e259d18baf0a11a 100644 --- a/src/muon_orbit_processor.h +++ b/src/muon_orbit_processor.h @@ -10,7 +10,7 @@ class MuonOrbitProcessor : public OrbitProcessor { int ProcessBlock(MemRegion &readable_block, WriteMemRegion &writeable_block, BxMetadata meta) override; - inline uint32_t GetPacketSize() const override { return (3 + 2 * 8 * 3) * 4; } + inline uint32_t GetPacketSize() const override { return (3 + 8 * 3) * 4; } inline uint32_t GetOrbitSizeInBytes(const FillOrbitMetadata &meta) const override { // 12 bytes for each muon/count then 12 bytes for each bx header diff --git a/src/orbit_processor.cc b/src/orbit_processor.cc index 970dc49a3462e4067925bb8fe2488cfa89c8e382..866d986dae2b81baa6a82257cf21804ca7df14ea 100644 --- a/src/orbit_processor.cc +++ b/src/orbit_processor.cc @@ -101,55 +101,41 @@ size_t OrbitProcessor::fillFRDEventHeader_V6(char *wr_ptr_FRDHead, uint32_t inpu OrbitProcessor::FillOrbitMetadata OrbitProcessor::FillOrbit(orbit_trailer *trailer, char *rd_ptr, char *wr_ptr, const char *rd_end_ptr, const char *wr_end_ptr) { + // TODO: need to be careful! If orbit number is 0 (not allowed in CMSSW) for whatever reason, + // TODO: we might want to return an empty slice in order to avoid unexepected files/events + // TODO: to appear and that would let CMSSW crash std::pair<uint32_t, bool> orbit_header = std::pair<uint32_t, bool>{ProcessOrbitHeader(rd_ptr)}; //.second is the warning test enable bit rd_ptr += 32; // +32 to account for orbit header if (cmsswHeaders) { - wr_ptr += sizeof(FRDFileHeader_v2); + wr_ptr += sizeof(FRDEventHeader_V6) + 4; } // reserving space for cmssw orbit header - uint32_t orbit = uint32_t{orbit_header.first} - - 1; // Starting with orbit number one lower than what is in the header - // because the "link orbit" contains a few BXs of the previous orbit + uint32_t orbit = uint32_t{orbit_header.first}; auto counts = uint32_t{0}; uint32_t filled_bxs = 0; // We loop over the BX map from the orbit trailer and then match the filled - // BXs to the data we got. The logic below is annoyingly convoluted: The first - // BX we get in the data stream is from BX 3555, however the BX map starts at - // BX 1, we therefore need to start reading the BX map from the 3555th bit. - // 3555//32 = 111, so we start at the 111th word; 3555 mod 32 = 3, however we - // start counting at BX1, so the start bit is 2. - // We start at 3554 here, because we increment by 1 immediately after starting the loops. - uint32_t bx = 3554; - size_t word = 111; - size_t bit = 1; // Will be incremented immediately after starting the loop - for (size_t pseudo_bx = 0; pseudo_bx < 3564; ++pseudo_bx) { - // Looping over at most an entire orbit here. - if (word == 14 * 8 - 1 && bit == 11) { - // Bit 11 in word 111 is the last valid BX (3564), so we roll over afterwards. - // (== 11 because that's the one we worked on in the previous loop iteration) - word = 0; - bit = 0; - bx = 0; // Will be immediately incremented to 1. - ++orbit; - } else if (bit < 31) { - ++bit; - } else { - bit = 0; - ++word; - } - ++bx; - if ((trailer->bx_map[word] & (1 << bit)) == 0) { - continue; // If the bit is zero that BX was empty and we continue. - } - - ++filled_bxs; - + // BXs to the data we got. + size_t word; + size_t bit; + for (size_t bx = 1; bx <= 3564; ++bx) { + // firstly check if we have BX data in orbit if (CheckOrbitTrailerStart(const_cast<const char *>(rd_ptr))) { // orbit trailer has been reached, end of orbit data break; } + // update word and bit... + word = (bx-1) / 32; + bit = (bx-1) % 32; + // ...and check if BX is empty... + if ((trailer->bx_map[word] & (1 << bit)) == 0) { + continue; + } + // ...otherwise we have something + ++filled_bxs; + + // fill MemRegion readable_block(&rd_ptr, rd_end_ptr); WriteMemRegion writeable_block(&wr_ptr, wr_end_ptr); assert(writeable_block.CheckBounds(GetPacketSize())); // Max size a decoded block can use @@ -163,6 +149,7 @@ OrbitProcessor::FillOrbitMetadata OrbitProcessor::FillOrbit(orbit_trailer *trail counts += ret_counts; } } + return {counts, orbit, filled_bxs}; } @@ -222,33 +209,4 @@ void OrbitProcessor::ProcessSliceImpl(Slice &input, Slice &out) { rd_ptr += 32 + meta.filled_bxs * bsize + constants::orbit_trailer_size; // 32 for orbit header, + - // nBXs + orbit trailer - assert(wr_ptr <= wr_end_ptr); - assert(rd_ptr <= rd_end_ptr); - counts += orbitCount; - if (firstOrbit) { - out.set_firstOrbitN(meta.orbit); - firstOrbit = false; - } - - if (rd_ptr < input.end()) { - auto *dma_trailer_word = (uint32_t *)(rd_ptr); - if (*dma_trailer_word == constants::deadbeef) { - out.set_end(wr_ptr); - out.set_counts(counts); - return; - } - - if (orbit_per_packet_count > nOrbitsPerPacket) { - LOG(WARNING) << "expected DMA trailer word deadbeef, found " << std::hex - << *dma_trailer_word << ". Orbits per packet count " << orbit_per_packet_count - << ", > expected, (" << nOrbitsPerPacket << ") skipping packet."; - if (stats.excess_orbits_per_packet_count % 10000 == 0) { - LOG(WARNING) << "count of packets with excess # orbits " - << stats.excess_orbits_per_packet_count; - } - return; - } - } - } -} + \ No newline at end of file diff --git a/test/config/scdaq-template.conf b/test/config/scdaq-template.conf new file mode 100644 index 0000000000000000000000000000000000000000..7ff63cce2276b4b0434dbea9167264bc5be1e859 --- /dev/null +++ b/test/config/scdaq-template.conf @@ -0,0 +1,140 @@ +################################################################################ +## +## Input settings +## +################################################################################ + +# Input settings, allowed values are: +# "wzdma" for DMA driver from Wojciech M. Zabolotny +# "dma" for XILINX DMA driver +# "filedma" for reading from file and simulating DMA +# "micronDMA" for PICO driver +# "tcpip" for TCP/IP input receving + +input:tcpip + +## Settings for DMA input + +# DMA device +dma_dev:/dev/xdma0_c2h_0 + +# Max received packet size in bytes (buffer to reserve) +dma_packet_buffer_size:1261568 + +# Number of packet buffers to allocate +dma_number_of_packet_buffers:10000 + +# Print report each N packets, use 0 to disable +packets_per_report:100000 + +# number of orbits per packet, in decimal +nOrbitsPerPacket:1 + +# prescale factor, used for *calo* data only +prescale_factor:1 + +## Extra settings for "filedma" input + +#input_file:/dev/shm/testdata.bin +#input_file:/home/glazzari/repos/scdaq/test/data/passthrough_test1.dat +input_file:./test/data/calo_testfile.dat + +## Extra settings for "tcpip" input +log_min_severity: +threads: +tcpDestPort: +source_id: +output_filename_prefix: +output_filename_base: +output_filename_suffix: +output_force_write: +processor_type: +primitive_type: + +################################################################################ +## +## Stream processor settings +## +################################################################################ + +enable_stream_processor:yes + +# Define processing type (unpacking), allowed values are: +# "PASS_THROUGH" +# "GMT" +# "CALO" +# Note: When changing the processing type, change also "output_filename_prefix" +# in the file output section. +# + +# Enable software zero-supression +doZS:yes + +################################################################################ +## +## File output settings +## +################################################################################ + +max_file_size:8589934592 + +# Always write data to a file regardless of the run status, useful for debugging + + +################################################################################ +## +## Elastics processor settings (obsolete) +## +################################################################################ + +enable_elastic_processor:no + +# heading space left here on purpose in order to avoid sed to replace the scone port + port: +elastic_url:http://something.somewhere +pt_cut:7 +quality_cut:12 + + +################################################################################ +## +## SCDAQ Generic Settings +## +################################################################################ + +# enable development functionalities (e.g. TCP input filter) +dev_TCPAutoReconnectOnFailure:true + +## Logging, supported LOG severities: +# TRACE +# DEBUG +# INFO +# WARNING +# ERROR +# FATAL +# +# Log only severities at the same level or more severe than the log_min_severity +# Use TRACE to log everything +# + +# Pipeline settings + +# verbosity level, currently supports 0 and 1 +verbosity:1 + +# N orbits to store to each file +# Configured to store fixed number of orbits per file when nOrbitsPerFile > 1 +# Set to 0 to use fixed file size instead +nOrbitsPerFile:4096 + +# Headers for vcu128 support +dthHeaders:yes + +# Headers for cmssw support +cmsswHeaders:yes + +## Information necessary to issue a reset request for the board +scone_host:localhost +scone_port:8090 +# Currently can be one of kcu1500_ugmt and kcu1500_demux +scone_board: \ No newline at end of file