From 820235a8c6ce2e020d61a8bc9491b7b779a18019 Mon Sep 17 00:00:00 2001 From: tomeichlersmith Date: Wed, 12 Nov 2025 09:46:29 -0600 Subject: [PATCH 01/28] update justfile recipes --- justfile | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/justfile b/justfile index ea0ea7e8..a22cf130 100644 --- a/justfile +++ b/justfile @@ -42,9 +42,13 @@ hexdump *args: hexdump -v -e '1/4 "%08x" "\n"' {{ args }} # run the decoder -decode *args: +pfdecoder *args: denv ./build/pfdecoder {{ args }} +# run the econd-decoder +econd-decoder *args: + denv ./build/econd-decoder {{ args }} + # open the test menu test-menu: denv ./build/test-menu From 091679eea438a83d50e67a4d55bdff530bb53027 Mon Sep 17 00:00:00 2001 From: tomeichlersmith Date: Wed, 12 Nov 2025 12:36:42 -0600 Subject: [PATCH 02/28] working from a file of ECOND pedestals --- CMakeLists.txt | 1 + app/econd_decoder.cxx | 8 +-- .../packing/SoftWrappedECONDEventPacket.h | 44 +++++++++++++ .../packing/SoftWrappedECONDEventPacket.cxx | 65 +++++++++++++++++++ 4 files changed, 113 insertions(+), 5 deletions(-) create mode 100644 include/pflib/packing/SoftWrappedECONDEventPacket.h create mode 100644 src/pflib/packing/SoftWrappedECONDEventPacket.cxx diff --git a/CMakeLists.txt b/CMakeLists.txt index ba2602fc..2e98cd7d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -61,6 +61,7 @@ add_library(packing SHARED src/pflib/packing/SingleROCEventPacket.cxx src/pflib/packing/ECONDEventPacket.cxx src/pflib/packing/MultiSampleECONDEventPacket.cxx + src/pflib/packing/SoftWrappedECONDEventPacket.cxx ) target_include_directories(packing PUBLIC "$" diff --git a/app/econd_decoder.cxx b/app/econd_decoder.cxx index 33220d8e..9910dcf7 100644 --- a/app/econd_decoder.cxx +++ b/app/econd_decoder.cxx @@ -7,7 +7,7 @@ #include "pflib/Logging.h" #include "pflib/packing/FileReader.h" #include "pflib/packing/Hex.h" -#include "pflib/packing/MultiSampleECONDEventPacket.h" +#include "pflib/packing/SoftWrappedECONDEventPacket.h" #include "pflib/version/Version.h" static void usage() { @@ -145,7 +145,7 @@ int main(int argc, char* argv[]) { o << std::boolalpha; o << pflib::packing::ECONDEventPacket::to_csv_header << '\n'; - pflib::packing::MultiSampleECONDEventPacket ep(n_links); + pflib::packing::SoftWrappedECONDEventPacket ep(n_links); // count is NOT written into output file, // we use the event number from the links // this is just to allow users to limit the number of entries in @@ -157,9 +157,7 @@ int main(int argc, char* argv[]) { r >> ep; pflib_log(debug) << "r.eof(): " << std::boolalpha << r.eof() << " and bool(r): " << bool(r); - for (const auto& sample : ep.samples) { - sample.to_csv(o); - } + ep.data.to_csv(o); count++; if (nevents > 0 and count >= nevents) { break; diff --git a/include/pflib/packing/SoftWrappedECONDEventPacket.h b/include/pflib/packing/SoftWrappedECONDEventPacket.h new file mode 100644 index 00000000..4ae49edd --- /dev/null +++ b/include/pflib/packing/SoftWrappedECONDEventPacket.h @@ -0,0 +1,44 @@ +#pragma once + +#include "pflib/packing/ECONDEventPacket.h" +#include "pflib/packing/Reader.h" + +namespace pflib::packing { + +/** + * Unpack an event packet that includes an extra header inserted by + * the software + * + * @see ECONDEventPacket for how a single sample from a single ECOND + * is unpacked. + */ +class SoftWrappedECONDEventPacket { + /// handle to logging source + mutable ::pflib::logging::logger the_log_{::pflib::logging::get("decoding")}; + + public: + /// provide number of links (eRx) on the ECOND + SoftWrappedECONDEventPacket(std::size_t n_links); + /** + * Corruption bits + * + * Index | Description + * ------|------------ + * 0 | sw header version mismatch + */ + std::array corruption; + /// L1A index for this packet + int il1a; + /// contributor ID specifying ECOND + int contrib_id; + /// whether this packet is the sample-of-interest + bool is_soi; + /// actual data packet from ECOND + ECONDEventPacket data; + /// unpack the given data into this structure + void from(std::span frame); + /// read into this structure from the input Reader + Reader& read(Reader& r); +}; + +} // namespace pflib::packing diff --git a/src/pflib/packing/SoftWrappedECONDEventPacket.cxx b/src/pflib/packing/SoftWrappedECONDEventPacket.cxx new file mode 100644 index 00000000..0d172484 --- /dev/null +++ b/src/pflib/packing/SoftWrappedECONDEventPacket.cxx @@ -0,0 +1,65 @@ +#include "pflib/packing/SoftWrappedECONDEventPacket.h" + +#include "pflib/packing/Hex.h" +#include "pflib/packing/Mask.h" + +namespace pflib::packing { + +SoftWrappedECONDEventPacket::SoftWrappedECONDEventPacket(std::size_t n_links) + : data{n_links} {} + +void SoftWrappedECONDEventPacket::from(std::span frame) { + /** + * The software emulation adds another header before the ECOND packet, + * which looks like + * + * 4b flag | 9b ECON ID | 4b il1a | S | 0 | 8b length + * + * - flag is hardcoded to 0b0001 right now in software + * - ECOND ID is what it was configured in the software to be + * - il1a is the index of the sample relative to this event + * - S signals if this is the sample of interest (1) or not (0) + * - length is the total length of this link subpacket including this header + * word + */ + std::size_t offset{0}; + uint32_t link_len = (frame[offset] & mask<8>); + is_soi = (((frame[offset] >> (8+4)) & mask<1>) == 1); + il1a = ((frame[offset] >> (8+4+1)) & mask<4>); + contrib_id = ((frame[offset] >> (8+4+1+4)) & mask<9>); + uint32_t vers = ((frame[offset] >> 28) & mask<4>); + pflib_log(trace) << hex(frame[offset]) + << " -> link_len, il1a, contrib_id, is_soi = " + << link_len << ", " << il1a << ", " << contrib_id << ", " + << is_soi; + + corruption[0] = (vers != 1); + if (corruption[0]) { + pflib_log(warn) << "version transmitted in header " + << vers << " != 1"; + } + + data.from(frame.subspan(offset+1, link_len)); +} + +Reader& SoftWrappedECONDEventPacket::read(Reader& r) { + /** + * DANGER + * Without signal trailer words, this assumes that the data + * stream is word aligned and we aren't starting on the wrong + * word. + */ + uint32_t word{0}; + if (!(r >> word)) { + return r; + } + std::vector frame = {word}; + uint32_t econd_len = word & mask<8>; + pflib_log(trace) << "using " << hex(word) << " to get econd length = " << econd_len; + if (r.read(frame, econd_len, 1)) { + from(frame); + } + return r; +} + +} // namespace pflib::packing From 9f5987c546cbd3a5dad6b45aaa977d8701a9c2ab Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Wed, 12 Nov 2025 18:46:56 +0000 Subject: [PATCH 03/28] Apply clang-format --style=Google --- .../packing/SoftWrappedECONDEventPacket.cxx | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/src/pflib/packing/SoftWrappedECONDEventPacket.cxx b/src/pflib/packing/SoftWrappedECONDEventPacket.cxx index 0d172484..1cfc9d09 100644 --- a/src/pflib/packing/SoftWrappedECONDEventPacket.cxx +++ b/src/pflib/packing/SoftWrappedECONDEventPacket.cxx @@ -24,22 +24,20 @@ void SoftWrappedECONDEventPacket::from(std::span frame) { */ std::size_t offset{0}; uint32_t link_len = (frame[offset] & mask<8>); - is_soi = (((frame[offset] >> (8+4)) & mask<1>) == 1); - il1a = ((frame[offset] >> (8+4+1)) & mask<4>); - contrib_id = ((frame[offset] >> (8+4+1+4)) & mask<9>); + is_soi = (((frame[offset] >> (8 + 4)) & mask<1>) == 1); + il1a = ((frame[offset] >> (8 + 4 + 1)) & mask<4>); + contrib_id = ((frame[offset] >> (8 + 4 + 1 + 4)) & mask<9>); uint32_t vers = ((frame[offset] >> 28) & mask<4>); pflib_log(trace) << hex(frame[offset]) - << " -> link_len, il1a, contrib_id, is_soi = " - << link_len << ", " << il1a << ", " << contrib_id << ", " - << is_soi; + << " -> link_len, il1a, contrib_id, is_soi = " << link_len + << ", " << il1a << ", " << contrib_id << ", " << is_soi; corruption[0] = (vers != 1); if (corruption[0]) { - pflib_log(warn) << "version transmitted in header " - << vers << " != 1"; + pflib_log(warn) << "version transmitted in header " << vers << " != 1"; } - data.from(frame.subspan(offset+1, link_len)); + data.from(frame.subspan(offset + 1, link_len)); } Reader& SoftWrappedECONDEventPacket::read(Reader& r) { @@ -55,7 +53,8 @@ Reader& SoftWrappedECONDEventPacket::read(Reader& r) { } std::vector frame = {word}; uint32_t econd_len = word & mask<8>; - pflib_log(trace) << "using " << hex(word) << " to get econd length = " << econd_len; + pflib_log(trace) << "using " << hex(word) + << " to get econd length = " << econd_len; if (r.read(frame, econd_len, 1)) { from(frame); } From 88155628c50a43bb1f4d72b07028845103ce9465 Mon Sep 17 00:00:00 2001 From: tomeichlersmith Date: Wed, 12 Nov 2025 12:55:47 -0600 Subject: [PATCH 04/28] fixup violinplot --- ana/pedestal/violinplot.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ana/pedestal/violinplot.py b/ana/pedestal/violinplot.py index bec45842..6130ccd1 100644 --- a/ana/pedestal/violinplot.py +++ b/ana/pedestal/violinplot.py @@ -15,7 +15,7 @@ if args.output is None: if len(args.pedestals) == 1: - args.output = args.pedestals.parent / (args.pedestals.stem + '-violinplot.png') + args.output = args.pedestals[0].parent / (args.pedestals[0].stem + '-violinplot.png') else: args.output = 'violinplot.png' From dcf5d9b125ff7010ab6b21aaeff0d41099afeb41 Mon Sep 17 00:00:00 2001 From: tomeichlersmith Date: Wed, 12 Nov 2025 12:55:54 -0600 Subject: [PATCH 05/28] rename len for clarity --- src/pflib/packing/SoftWrappedECONDEventPacket.cxx | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/src/pflib/packing/SoftWrappedECONDEventPacket.cxx b/src/pflib/packing/SoftWrappedECONDEventPacket.cxx index 1cfc9d09..1f3f002e 100644 --- a/src/pflib/packing/SoftWrappedECONDEventPacket.cxx +++ b/src/pflib/packing/SoftWrappedECONDEventPacket.cxx @@ -19,17 +19,16 @@ void SoftWrappedECONDEventPacket::from(std::span frame) { * - ECOND ID is what it was configured in the software to be * - il1a is the index of the sample relative to this event * - S signals if this is the sample of interest (1) or not (0) - * - length is the total length of this link subpacket including this header - * word + * - length is the length of the econd subpacket NOT including this header */ std::size_t offset{0}; - uint32_t link_len = (frame[offset] & mask<8>); + uint32_t econd_len = (frame[offset] & mask<8>); is_soi = (((frame[offset] >> (8 + 4)) & mask<1>) == 1); il1a = ((frame[offset] >> (8 + 4 + 1)) & mask<4>); contrib_id = ((frame[offset] >> (8 + 4 + 1 + 4)) & mask<9>); uint32_t vers = ((frame[offset] >> 28) & mask<4>); pflib_log(trace) << hex(frame[offset]) - << " -> link_len, il1a, contrib_id, is_soi = " << link_len + << " -> econd_len, il1a, contrib_id, is_soi = " << econd_len << ", " << il1a << ", " << contrib_id << ", " << is_soi; corruption[0] = (vers != 1); @@ -37,7 +36,7 @@ void SoftWrappedECONDEventPacket::from(std::span frame) { pflib_log(warn) << "version transmitted in header " << vers << " != 1"; } - data.from(frame.subspan(offset + 1, link_len)); + data.from(frame.subspan(offset + 1, econd_len)); } Reader& SoftWrappedECONDEventPacket::read(Reader& r) { From dc631773ef76ffdc1a61c96ac07995f33afdc220 Mon Sep 17 00:00:00 2001 From: tomeichlersmith Date: Wed, 12 Nov 2025 13:24:48 -0600 Subject: [PATCH 06/28] rename contrib to econ id --- include/pflib/packing/SoftWrappedECONDEventPacket.h | 4 ++-- src/pflib/packing/SoftWrappedECONDEventPacket.cxx | 12 ++++++------ 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/include/pflib/packing/SoftWrappedECONDEventPacket.h b/include/pflib/packing/SoftWrappedECONDEventPacket.h index 4ae49edd..6e522a6b 100644 --- a/include/pflib/packing/SoftWrappedECONDEventPacket.h +++ b/include/pflib/packing/SoftWrappedECONDEventPacket.h @@ -29,8 +29,8 @@ class SoftWrappedECONDEventPacket { std::array corruption; /// L1A index for this packet int il1a; - /// contributor ID specifying ECOND - int contrib_id; + /// ID specifying ECOND we are reading + int econ_id; /// whether this packet is the sample-of-interest bool is_soi; /// actual data packet from ECOND diff --git a/src/pflib/packing/SoftWrappedECONDEventPacket.cxx b/src/pflib/packing/SoftWrappedECONDEventPacket.cxx index 1f3f002e..420b6282 100644 --- a/src/pflib/packing/SoftWrappedECONDEventPacket.cxx +++ b/src/pflib/packing/SoftWrappedECONDEventPacket.cxx @@ -22,14 +22,14 @@ void SoftWrappedECONDEventPacket::from(std::span frame) { * - length is the length of the econd subpacket NOT including this header */ std::size_t offset{0}; - uint32_t econd_len = (frame[offset] & mask<8>); - is_soi = (((frame[offset] >> (8 + 4)) & mask<1>) == 1); - il1a = ((frame[offset] >> (8 + 4 + 1)) & mask<4>); - contrib_id = ((frame[offset] >> (8 + 4 + 1 + 4)) & mask<9>); uint32_t vers = ((frame[offset] >> 28) & mask<4>); + econ_id = ((frame[offset] >> 18) & mask<10>); + il1a = ((frame[offset] >> 13) & mask<5>); + is_soi = (((frame[offset] >> 12) & mask<1>) == 1); + uint32_t econd_len = (frame[offset] & mask<12>); pflib_log(trace) << hex(frame[offset]) - << " -> econd_len, il1a, contrib_id, is_soi = " << econd_len - << ", " << il1a << ", " << contrib_id << ", " << is_soi; + << " -> econd_len, il1a, econ_id, is_soi = " << econd_len + << ", " << il1a << ", " << econ_id << ", " << is_soi; corruption[0] = (vers != 1); if (corruption[0]) { From 6abf88c537260794d786674777c8fb3527da23fe Mon Sep 17 00:00:00 2001 From: tomeichlersmith Date: Wed, 12 Nov 2025 13:24:58 -0600 Subject: [PATCH 07/28] limit econ id to 10bits so it doesn't overwrite version --- src/pflib/zcu/HcalBackplaneZCU.cxx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/pflib/zcu/HcalBackplaneZCU.cxx b/src/pflib/zcu/HcalBackplaneZCU.cxx index 828038f3..ec61d80e 100644 --- a/src/pflib/zcu/HcalBackplaneZCU.cxx +++ b/src/pflib/zcu/HcalBackplaneZCU.cxx @@ -362,9 +362,9 @@ class HcalBackplaneZCUTarget : public Target { if (format_ == Target::DaqFormat::ECOND_SW_HEADERS) { for (int ievt = 0; ievt < zcuhcal_->daq().samples_per_ror(); ievt++) { - std::vector subpacket = - zcuhcal_->daq().getLinkData(0); // only one elink right now - buf.push_back((0x1 << 28) | ((zcuhcal_->daq().econid() & 0xFFF) << 18) | + // only one elink right now + std::vector subpacket = zcuhcal_->daq().getLinkData(0); + buf.push_back((0x1 << 28) | ((zcuhcal_->daq().econid() & 0x3ff) << 18) | (ievt << 13) | ((ievt == zcuhcal_->daq().soi()) ? (1 << 12) : (0)) | (subpacket.size())); From 29931a0ed3091b22935e64bef11814f306b878e2 Mon Sep 17 00:00:00 2001 From: tomeichlersmith Date: Wed, 12 Nov 2025 13:47:59 -0600 Subject: [PATCH 08/28] start outline of live decoding looking at templating over DaqRunConsumer derived classes, getting complicated quickly unfortunately --- app/tool/algorithm/level_pedestals.cxx | 3 +- app/tool/daq.cxx | 30 ++++++++++++++++-- app/tool/daq_run.cxx | 43 ++++++++++++++------------ app/tool/daq_run.h | 32 +++++++++---------- 4 files changed, 69 insertions(+), 39 deletions(-) diff --git a/app/tool/algorithm/level_pedestals.cxx b/app/tool/algorithm/level_pedestals.cxx index 633d36d2..4d113a77 100644 --- a/app/tool/algorithm/level_pedestals.cxx +++ b/app/tool/algorithm/level_pedestals.cxx @@ -18,8 +18,9 @@ * Calib and Common Mode channels are ignored. * TOT/TOA and the sample Tp/Tc flags are ignored. */ +template static std::array get_adc_medians( - const std::vector& data) { + const std::vector& data) { std::array medians; /// reserve a vector of the appropriate size to avoid repeating allocation /// time for all 72 channels diff --git a/app/tool/daq.cxx b/app/tool/daq.cxx index cee19ae3..d0cf33b6 100644 --- a/app/tool/daq.cxx +++ b/app/tool/daq.cxx @@ -350,8 +350,34 @@ static void daq(const std::string& cmd, Target* pft) { pftool::readline_bool("Should we decode the packet into CSV?", true); if (decoding) { - DecodeAndWriteToCSV writer{all_channels_to_csv(fname + ".csv")}; - daq_run(pft, cmd, writer, nevents, pftool::state.daq_rate); + std::unique_ptr consumer; + switch(pftool::state.daq_format_mode) { + case Target::DaqFormat::ECOND_SW_HEADERS: + consumer = std::make_unique>( + fname+".csv", + [](std::ofstream& f) { + f << std::boolalpha; + f << pflib::packing::SoftWrappedECONDEventPacket::to_csv_header << '\n'; + }, + [](std::ofstream& f, const pflib::packing::SoftWrappedECONDEventPacket& ep) { + ep.to_csv(f); + }); + break; + case Target::DaqFormat::SIMPLEROC: + consumer = std::make_unique>( + fname+".csv", + [](std::ofstream& f) { + f << std::boolalpha; + f << pflib::packing::SingleROCEventPacket::to_csv_header << '\n'; + }, + [](std::ofstream& f, const pflib::packing::SingleROCEventPacket& ep) { + ep.to_csv(f); + }); + break; + default: + PFEXCEPTION_RAISE("BadConf", "Unable to do live decoding for the currently configured format."); + } + daq_run(pft, cmd, *consumer, nevents, pftool::state.daq_rate); } else { WriteToBinaryFile writer{fname + ".raw"}; daq_run(pft, cmd, writer, nevents, pftool::state.daq_rate); diff --git a/app/tool/daq_run.cxx b/app/tool/daq_run.cxx index 3541066c..a4c2b000 100644 --- a/app/tool/daq_run.cxx +++ b/app/tool/daq_run.cxx @@ -77,7 +77,8 @@ void WriteToBinaryFile::consume(std::vector& event) { fwrite(&(event[0]), sizeof(uint32_t), event.size(), fp_); } -void DecodeAndWrite::consume(std::vector& event) { +template +void DecodeAndWrite::consume(std::vector& event) { // we have to manually check the size so that we can do the reinterpret_cast if (event.size() == 0) { pflib_log(warn) << "event with zero words passed in, skipping"; @@ -91,13 +92,13 @@ void DecodeAndWrite::consume(std::vector& event) { write_event(ep_); } -DecodeAndWriteToCSV::DecodeAndWriteToCSV( +template +DecodeAndWriteToCSV::DecodeAndWriteToCSV( const std::string& file_name, std::function write_header, - std::function + std::function write_event) - : DecodeAndWrite(), file_{file_name}, write_event_{write_event} { + : DecodeAndWrite(), file_{file_name}, write_event_{write_event} { if (not file_) { PFEXCEPTION_RAISE("FileOpen", "unable to open " + file_name + " for writing"); @@ -105,29 +106,31 @@ DecodeAndWriteToCSV::DecodeAndWriteToCSV( write_header(file_); } -void DecodeAndWriteToCSV::write_event( - const pflib::packing::SingleROCEventPacket& ep) { +template +void DecodeAndWriteToCSV::write_event(const EventPacket& ep) { write_event_(file_, ep); } -DecodeAndWriteToCSV all_channels_to_csv(const std::string& file_name) { - return DecodeAndWriteToCSV( +template +DecodeAndWriteToCSV all_channels_to_csv(const std::string& file_name) { + return DecodeAndWriteToCSV( file_name, [](std::ofstream& f) { f << std::boolalpha; - f << pflib::packing::SingleROCEventPacket::to_csv_header << '\n'; + f << EventPacket::to_csv_header << '\n'; }, - [](std::ofstream& f, const pflib::packing::SingleROCEventPacket& ep) { + [](std::ofstream& f, const EventPacket& ep) { ep.to_csv(f); }); } -DecodeAndBuffer::DecodeAndBuffer(int nevents) : DecodeAndWrite() { +template +DecodeAndBuffer::DecodeAndBuffer(int nevents) : DecodeAndWrite() { set_buffer_size(nevents); } -void DecodeAndBuffer::write_event( - const pflib::packing::SingleROCEventPacket& ep) { +template +void DecodeAndBuffer::write_event(const EventPacket& ep) { if (ep_buffer_.size() > ep_buffer_.capacity()) { pflib_log(warn) << "Trying to push more elements to buffer than allocated " "capacity. Skipping!"; @@ -135,14 +138,16 @@ void DecodeAndBuffer::write_event( } ep_buffer_.push_back(ep); } + +template +void DecodeAndBuffer::start_run() { ep_buffer_.clear(); } -void DecodeAndBuffer::start_run() { ep_buffer_.clear(); } - -const std::vector& -DecodeAndBuffer::get_buffer() const { +template +const std::vector& DecodeAndBuffer::get_buffer() const { return ep_buffer_; } -void DecodeAndBuffer::set_buffer_size(int nevents) { +template +void DecodeAndBuffer::set_buffer_size(int nevents) { ep_buffer_.reserve(nevents); } diff --git a/app/tool/daq_run.h b/app/tool/daq_run.h index 74bc0060..c05fd659 100644 --- a/app/tool/daq_run.h +++ b/app/tool/daq_run.h @@ -55,6 +55,7 @@ class WriteToBinaryFile : public DAQRunConsumer { * other code just needs to write functions that define how the * decoded data should be written out. */ +template class DecodeAndWrite : public DAQRunConsumer { public: virtual ~DecodeAndWrite() = default; @@ -65,7 +66,7 @@ class DecodeAndWrite : public DAQRunConsumer { virtual void consume(std::vector& event) final; /// pure virtual function for writing out decoded event - virtual void write_event(const pflib::packing::SingleROCEventPacket& ep) = 0; + virtual void write_event(const EventPacket& ep) = 0; protected: /// logging for warning messages on empty events @@ -73,35 +74,32 @@ class DecodeAndWrite : public DAQRunConsumer { private: /// event packet for decoding - pflib::packing::SingleROCEventPacket ep_; + EventPacket ep_; }; /** * specializatin of DecodeAndWrite that holds a std::ofstream * for the user with functions for writing the header and events */ -class DecodeAndWriteToCSV : public DecodeAndWrite { +template +class DecodeAndWriteToCSV : public DecodeAndWrite { /// output file writing to std::ofstream file_; /// function that writes row(s) to csv given an event - std::function - write_event_; + std::function write_event_; public: DecodeAndWriteToCSV( const std::string& file_name, std::function write_header, - std::function - write_event); + std::function write_event); virtual ~DecodeAndWriteToCSV() = default; /// call write_event with our file handle - virtual void write_event( - const pflib::packing::SingleROCEventPacket& ep) final; + virtual void write_event(const EventPacket& ep) final; }; -DecodeAndWriteToCSV all_channels_to_csv(const std::string& file_name); +template +DecodeAndWriteToCSV all_channels_to_csv(const std::string& file_name); /** * Consume an event packet, decode it, and save to buffer. @@ -119,21 +117,21 @@ DecodeAndWriteToCSV all_channels_to_csv(const std::string& file_name); * const auto& events{buffer.get_buffer()}; * ``` */ -class DecodeAndBuffer : public DecodeAndWrite { +template +class DecodeAndBuffer : public DecodeAndWrite { public: DecodeAndBuffer(int nevents); virtual ~DecodeAndBuffer() = default; /// get buffer - const std::vector& get_buffer() const; + const std::vector& get_buffer() const; /// Set the buffer size void set_buffer_size(int nevents); /// Save to buffer - virtual void write_event( - const pflib::packing::SingleROCEventPacket& ep) override; + virtual void write_event(const EventPacket& ep) override; /// Check that the buffer was read and flushed since last run virtual void start_run() override; private: /// Buffer for event packets - std::vector ep_buffer_; + std::vector ep_buffer_; }; From d1c361422b89bc80ceaeaab3a1dbcc49df50d9c1 Mon Sep 17 00:00:00 2001 From: joshgreaves332 Date: Thu, 13 Nov 2025 11:18:55 -0500 Subject: [PATCH 09/28] added tasks/level_pedestals.cxx to algorithm/level_pedestals.cxx and replaced hardcoded SIMPLEROC with pftool::state.daq_format_mode, set by DAQ->SETTINGS->FORMAT --- app/tool/algorithm/level_pedestals.cxx | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/app/tool/algorithm/level_pedestals.cxx b/app/tool/algorithm/level_pedestals.cxx index 4d113a77..1ee8ecfe 100644 --- a/app/tool/algorithm/level_pedestals.cxx +++ b/app/tool/algorithm/level_pedestals.cxx @@ -1,5 +1,7 @@ #include "level_pedestals.h" +#include "../tasks/level_pedestals.h" + #include "../daq_run.h" #include "pflib/utility/median.h" #include "pflib/utility/string_format.h" @@ -18,9 +20,8 @@ * Calib and Common Mode channels are ignored. * TOT/TOA and the sample Tp/Tc flags are ignored. */ -template static std::array get_adc_medians( - const std::vector& data) { + const std::vector& data) { std::array medians; /// reserve a vector of the appropriate size to avoid repeating allocation /// time for all 72 channels @@ -43,7 +44,12 @@ std::map> level_pedestals( /// do three runs of 100 samples each to have well defined pedestals static const std::size_t n_events = 100; - tgt->setup_run(1, Target::DaqFormat::SIMPLEROC, 1); + // tgt->setup_run(1, Target::DaqFormat::SIMPLEROC, 1); + // Use the DAQ format selected in the pftool DAQ->FORMAT menu so the + // format mode can be chosen interactively by the user. + tgt->setup_run(1, pftool::state.daq_format_mode, 1); + pflib_log(info) << "Using DAQ format mode: " + << static_cast(pftool::state.daq_format_mode); std::array target; std::array baseline, highend, lowend; From d81481dba676f0844899bc19a7fad0c7042cde0d Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Thu, 13 Nov 2025 16:22:34 +0000 Subject: [PATCH 10/28] Apply clang-format --style=Google --- app/tool/algorithm/level_pedestals.cxx | 3 +- app/tool/daq.cxx | 28 ++++++++++------ app/tool/daq_run.cxx | 44 ++++++++++++++------------ app/tool/daq_run.h | 11 ++++--- 4 files changed, 49 insertions(+), 37 deletions(-) diff --git a/app/tool/algorithm/level_pedestals.cxx b/app/tool/algorithm/level_pedestals.cxx index 1ee8ecfe..5c57a4fd 100644 --- a/app/tool/algorithm/level_pedestals.cxx +++ b/app/tool/algorithm/level_pedestals.cxx @@ -1,8 +1,7 @@ #include "level_pedestals.h" -#include "../tasks/level_pedestals.h" - #include "../daq_run.h" +#include "../tasks/level_pedestals.h" #include "pflib/utility/median.h" #include "pflib/utility/string_format.h" diff --git a/app/tool/daq.cxx b/app/tool/daq.cxx index d0cf33b6..418e05b2 100644 --- a/app/tool/daq.cxx +++ b/app/tool/daq.cxx @@ -351,31 +351,39 @@ static void daq(const std::string& cmd, Target* pft) { if (decoding) { std::unique_ptr consumer; - switch(pftool::state.daq_format_mode) { + switch (pftool::state.daq_format_mode) { case Target::DaqFormat::ECOND_SW_HEADERS: - consumer = std::make_unique>( - fname+".csv", + consumer = std::make_unique< + DecodeAndWriteToCSV>( + fname + ".csv", [](std::ofstream& f) { f << std::boolalpha; - f << pflib::packing::SoftWrappedECONDEventPacket::to_csv_header << '\n'; + f << pflib::packing::SoftWrappedECONDEventPacket::to_csv_header + << '\n'; }, - [](std::ofstream& f, const pflib::packing::SoftWrappedECONDEventPacket& ep) { + [](std::ofstream& f, + const pflib::packing::SoftWrappedECONDEventPacket& ep) { ep.to_csv(f); }); break; case Target::DaqFormat::SIMPLEROC: - consumer = std::make_unique>( - fname+".csv", + consumer = std::make_unique< + DecodeAndWriteToCSV>( + fname + ".csv", [](std::ofstream& f) { f << std::boolalpha; - f << pflib::packing::SingleROCEventPacket::to_csv_header << '\n'; + f << pflib::packing::SingleROCEventPacket::to_csv_header + << '\n'; }, - [](std::ofstream& f, const pflib::packing::SingleROCEventPacket& ep) { + [](std::ofstream& f, + const pflib::packing::SingleROCEventPacket& ep) { ep.to_csv(f); }); break; default: - PFEXCEPTION_RAISE("BadConf", "Unable to do live decoding for the currently configured format."); + PFEXCEPTION_RAISE("BadConf", + "Unable to do live decoding for the currently " + "configured format."); } daq_run(pft, cmd, *consumer, nevents, pftool::state.daq_rate); } else { diff --git a/app/tool/daq_run.cxx b/app/tool/daq_run.cxx index a4c2b000..241c56eb 100644 --- a/app/tool/daq_run.cxx +++ b/app/tool/daq_run.cxx @@ -77,7 +77,7 @@ void WriteToBinaryFile::consume(std::vector& event) { fwrite(&(event[0]), sizeof(uint32_t), event.size(), fp_); } -template +template void DecodeAndWrite::consume(std::vector& event) { // we have to manually check the size so that we can do the reinterpret_cast if (event.size() == 0) { @@ -92,13 +92,14 @@ void DecodeAndWrite::consume(std::vector& event) { write_event(ep_); } -template +template DecodeAndWriteToCSV::DecodeAndWriteToCSV( const std::string& file_name, std::function write_header, - std::function - write_event) - : DecodeAndWrite(), file_{file_name}, write_event_{write_event} { + std::function write_event) + : DecodeAndWrite(), + file_{file_name}, + write_event_{write_event} { if (not file_) { PFEXCEPTION_RAISE("FileOpen", "unable to open " + file_name + " for writing"); @@ -106,30 +107,30 @@ DecodeAndWriteToCSV::DecodeAndWriteToCSV( write_header(file_); } -template +template void DecodeAndWriteToCSV::write_event(const EventPacket& ep) { write_event_(file_, ep); } -template -DecodeAndWriteToCSV all_channels_to_csv(const std::string& file_name) { +template +DecodeAndWriteToCSV all_channels_to_csv( + const std::string& file_name) { return DecodeAndWriteToCSV( file_name, [](std::ofstream& f) { f << std::boolalpha; f << EventPacket::to_csv_header << '\n'; }, - [](std::ofstream& f, const EventPacket& ep) { - ep.to_csv(f); - }); + [](std::ofstream& f, const EventPacket& ep) { ep.to_csv(f); }); } -template -DecodeAndBuffer::DecodeAndBuffer(int nevents) : DecodeAndWrite() { +template +DecodeAndBuffer::DecodeAndBuffer(int nevents) + : DecodeAndWrite() { set_buffer_size(nevents); } -template +template void DecodeAndBuffer::write_event(const EventPacket& ep) { if (ep_buffer_.size() > ep_buffer_.capacity()) { pflib_log(warn) << "Trying to push more elements to buffer than allocated " @@ -138,16 +139,19 @@ void DecodeAndBuffer::write_event(const EventPacket& ep) { } ep_buffer_.push_back(ep); } - -template -void DecodeAndBuffer::start_run() { ep_buffer_.clear(); } -template -const std::vector& DecodeAndBuffer::get_buffer() const { +template +void DecodeAndBuffer::start_run() { + ep_buffer_.clear(); +} + +template +const std::vector& DecodeAndBuffer::get_buffer() + const { return ep_buffer_; } -template +template void DecodeAndBuffer::set_buffer_size(int nevents) { ep_buffer_.reserve(nevents); } diff --git a/app/tool/daq_run.h b/app/tool/daq_run.h index c05fd659..dd7468b1 100644 --- a/app/tool/daq_run.h +++ b/app/tool/daq_run.h @@ -55,7 +55,7 @@ class WriteToBinaryFile : public DAQRunConsumer { * other code just needs to write functions that define how the * decoded data should be written out. */ -template +template class DecodeAndWrite : public DAQRunConsumer { public: virtual ~DecodeAndWrite() = default; @@ -81,7 +81,7 @@ class DecodeAndWrite : public DAQRunConsumer { * specializatin of DecodeAndWrite that holds a std::ofstream * for the user with functions for writing the header and events */ -template +template class DecodeAndWriteToCSV : public DecodeAndWrite { /// output file writing to std::ofstream file_; @@ -98,8 +98,9 @@ class DecodeAndWriteToCSV : public DecodeAndWrite { virtual void write_event(const EventPacket& ep) final; }; -template -DecodeAndWriteToCSV all_channels_to_csv(const std::string& file_name); +template +DecodeAndWriteToCSV all_channels_to_csv( + const std::string& file_name); /** * Consume an event packet, decode it, and save to buffer. @@ -117,7 +118,7 @@ DecodeAndWriteToCSV all_channels_to_csv(const std::string& file_nam * const auto& events{buffer.get_buffer()}; * ``` */ -template +template class DecodeAndBuffer : public DecodeAndWrite { public: DecodeAndBuffer(int nevents); From 74a6cdcbb2eb78bad397c6cb93519640a922711b Mon Sep 17 00:00:00 2001 From: Tom Eichlersmith <31970302+tomeichlersmith@users.noreply.github.com> Date: Tue, 18 Nov 2025 08:58:15 -0800 Subject: [PATCH 11/28] switch base image to Rogue (#260) * switch base image to Rogue * define env var so CMake can find Rogue --- env/Containerfile.bittware-host | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/env/Containerfile.bittware-host b/env/Containerfile.bittware-host index c3b2e5ae..25b3ad1a 100644 --- a/env/Containerfile.bittware-host +++ b/env/Containerfile.bittware-host @@ -1,5 +1,6 @@ -FROM ubuntu:22.04 +FROM ghcr.io/slaclab/rogue:v6.6.2 LABEL maintainer="Tom Eichlersmith " +ENV ROGUE_DIR=/usr/local RUN apt-get update &&\ apt-get --yes install \ gcc \ From cb992712333a30b58b905669d50acc72ae57fa91 Mon Sep 17 00:00:00 2001 From: Tom Eichlersmith <31970302+tomeichlersmith@users.noreply.github.com> Date: Tue, 18 Nov 2025 09:08:11 -0800 Subject: [PATCH 12/28] some small compiler warnings that have been bugging me (#263) * various small compiler warnings that have been bugging me * Apply clang-format --style=Google --------- Co-authored-by: github-actions[bot] --- app/tool/econ.cxx | 2 +- src/pflib/Bias.cxx | 7 +++++-- src/pflib/FastControlCMS_MMap.cxx | 3 +-- src/pflib/bittware/bittware_optolink.cxx | 4 +++- src/pflib/lpgbt/lpGBT_ConfigTransport_I2C.cxx | 2 +- 5 files changed, 11 insertions(+), 7 deletions(-) diff --git a/app/tool/econ.cxx b/app/tool/econ.cxx index 4c17d452..5b090dc1 100644 --- a/app/tool/econ.cxx +++ b/app/tool/econ.cxx @@ -69,7 +69,7 @@ static void econ_expert(const std::string& cmd, Target* tgt) { uint64_t value = pftool::readline_int("Value to write (hex): ", 0x0); econ.setValue(address, value, nbytes); - printf("Wrote 0x%llx to register 0x%04x (%d bytes)\n", value, address, + printf("Wrote 0x%lx to register 0x%04x (%d bytes)\n", value, address, nbytes); } } diff --git a/src/pflib/Bias.cxx b/src/pflib/Bias.cxx index 3ef80424..c15ca9e4 100644 --- a/src/pflib/Bias.cxx +++ b/src/pflib/Bias.cxx @@ -33,8 +33,11 @@ std::vector MAX5825::get(uint8_t channel) { void MAX5825::set(uint8_t channel, uint16_t code) { uint8_t cmd = (uint8_t)(0xB0 | (channel & 0x07)); - std::vector retval = i2c_->general_write_read( - our_addr_, {cmd, (code << 4) >> 8, (code << 4) & 0xFF}, 0); + std::vector retval = + i2c_->general_write_read(our_addr_, + {cmd, static_cast((code << 4) >> 8), + static_cast((code << 4) & 0xFF)}, + 0); } /* diff --git a/src/pflib/FastControlCMS_MMap.cxx b/src/pflib/FastControlCMS_MMap.cxx index 744d1766..1788a1c0 100644 --- a/src/pflib/FastControlCMS_MMap.cxx +++ b/src/pflib/FastControlCMS_MMap.cxx @@ -240,8 +240,7 @@ class FastControlCMS_MMap : public FastControl { void bx_custom(int bx_addr, int bx_mask, int bx_new) { uint32_t bx_out = uio_.readMasked(bx_addr, bx_mask); uint32_t bxout2 = uio_.read(bx_addr); - printf("Read FC BX: ", bxout2); - printf("\n"); + printf("Read FC BX: %d\n", bxout2); // // uint32_t bx_out_write = uio_.writeMasked(bx_addr, bx_mask, bx_new); // std::cout << "readMasked (after write): " << bx_out << std::endl; } diff --git a/src/pflib/bittware/bittware_optolink.cxx b/src/pflib/bittware/bittware_optolink.cxx index 5ac128c8..d7a298c2 100644 --- a/src/pflib/bittware/bittware_optolink.cxx +++ b/src/pflib/bittware/bittware_optolink.cxx @@ -162,6 +162,8 @@ std::map BWOptoLink::opto_rates() { int BWOptoLink::get_elink_tx_mode(int elink) { if (elink < 0 || elink > 3 || !isdaq_) return -1; + // TODO + return 0; } void BWOptoLink::set_elink_tx_mode(int elink, int mode) { if (elink < 0 || elink > 3 || !isdaq_) return; @@ -335,7 +337,7 @@ std::vector BWlpGBT_Transport::read_regs(uint16_t reg, int n) { tries++; if (retval.size() != n) { snprintf(message, 256, - "Read register 0x%x tried to read %d, actually got %d", reg, n, + "Read register 0x%x tried to read %d, actually got %ld", reg, n, retval.size()); } } while (tries < 4 && retval.size() != n); diff --git a/src/pflib/lpgbt/lpGBT_ConfigTransport_I2C.cxx b/src/pflib/lpgbt/lpGBT_ConfigTransport_I2C.cxx index 11f6bd36..f711fb1e 100644 --- a/src/pflib/lpgbt/lpGBT_ConfigTransport_I2C.cxx +++ b/src/pflib/lpgbt/lpGBT_ConfigTransport_I2C.cxx @@ -16,7 +16,7 @@ lpGBT_ConfigTransport_I2C::lpGBT_ConfigTransport_I2C( ioctl(handle_, I2C_SLAVE, i2c_addr); if (handle_ < 0) { char msg[1000]; - snprintf(msg, 1000, "Error %s (%d) opening I2C device file", + snprintf(msg, 1000, "Error %s (%d) opening I2C device file %s", strerror(errno), errno, bus_dev.c_str()); PFEXCEPTION_RAISE("I2CException", msg); } From 93d8edc37044204313c9b1cdd6ed7f01a230f575 Mon Sep 17 00:00:00 2001 From: tomeichlersmith Date: Tue, 18 Nov 2025 09:59:21 -0800 Subject: [PATCH 13/28] don't build yaml-cpp tests --- env/Containerfile.zcu | 1 + 1 file changed, 1 insertion(+) diff --git a/env/Containerfile.zcu b/env/Containerfile.zcu index beb2125e..eca2a662 100644 --- a/env/Containerfile.zcu +++ b/env/Containerfile.zcu @@ -31,6 +31,7 @@ RUN mkdir src &&\ -S src/ \ -B src/build \ -DYAML_BUILD_SHARED_LIBS=ON \ + -DYAML_CPP_BUILD_TESTS=OFF \ &&\ cmake --build src/build --target install &&\ rm -rf src From d0c3147d2e339369f2d3bb82fc04323c4d3888c0 Mon Sep 17 00:00:00 2001 From: tomeichlersmith Date: Tue, 18 Nov 2025 11:58:09 -0800 Subject: [PATCH 14/28] store ROCs type_version in ROC --- include/pflib/ROC.h | 2 ++ src/pflib/ROC.cxx | 5 +++++ 2 files changed, 7 insertions(+) diff --git a/include/pflib/ROC.h b/include/pflib/ROC.h index d0676073..0131df26 100644 --- a/include/pflib/ROC.h +++ b/include/pflib/ROC.h @@ -23,6 +23,7 @@ class ROC { void setRunMode(bool active = true); bool isRunMode(); + const std::string& type() const; std::vector readPage(int ipage, int len); uint8_t getValue(int page, int offset); @@ -183,6 +184,7 @@ class ROC { private: I2C& i2c_; uint8_t roc_base_; + std::string type_version_; Compiler compiler_; mutable ::pflib::logging::logger the_log_{::pflib::logging::get("roc")}; }; diff --git a/src/pflib/ROC.cxx b/src/pflib/ROC.cxx index 2e657ada..f997f3ec 100644 --- a/src/pflib/ROC.cxx +++ b/src/pflib/ROC.cxx @@ -14,10 +14,15 @@ namespace pflib { ROC::ROC(I2C& i2c, uint8_t roc_base_addr, const std::string& type_version) : i2c_{i2c}, roc_base_{roc_base_addr}, + type_version_{type_version}, compiler_{Compiler::get(type_version)} { pflib_log(debug) << "base addr " << packing::hex(roc_base_); } +const std::string& ROC::type() const { + return type_version_; +} + std::vector ROC::readPage(int ipage, int len) { i2c_.set_bus_speed(1400); From a9181e92c8eb1f28a10130725d79290d181af2c6 Mon Sep 17 00:00:00 2001 From: Jeremiah Mans Date: Wed, 19 Nov 2025 09:52:56 -0600 Subject: [PATCH 15/28] Create basic support for ECAL Single Module Motherboard (SMM) (#267) * Single-module motherboard setup added * Break out HCAL pieces which can be reused for ECAL * Progress in creating ECAL * Adding more ECAL support pieces, but elink is unhappy. also the ECON-D isn't counting FC, but same issue for backplane from bittware... * Apply clang-format --style=Google --------- Co-authored-by: Jeremiah Mans Co-authored-by: github-actions[bot] --- CMakeLists.txt | 4 + app/lpgbt/main.cxx | 7 + app/tool/daq.cxx | 6 + app/tool/econ.cxx | 5 +- app/tool/main.cxx | 13 ++ app/tool/pftool.h | 1 + config/econ/econd_smm_init.yaml | 28 +++ config/pftool/ecal-smm-zcu.yaml | 3 + include/pflib/Ecal.h | 84 +++---- include/pflib/HcalBackplane.h | 4 +- include/pflib/Target.h | 5 +- include/pflib/lpgbt/lpGBT_standard_configs.h | 8 + include/pflib/zcu/zcu_daq.h | 34 +++ include/pflib/zcu/zcu_elinks.h | 28 +++ src/pflib/Ecal.cxx | 70 ++++++ src/pflib/HcalBackplane.cxx | 4 +- src/pflib/ROC.cxx | 4 +- src/pflib/lpgbt/lpGBT_standard_configs.cxx | 59 +++++ src/pflib/zcu/EcalSMMTarget.cxx | 118 ++++++++++ src/pflib/zcu/HcalBackplaneZCU.cxx | 221 +------------------ src/pflib/zcu/zcu_DAQ.cxx | 142 ++++++++++++ src/pflib/zcu/zcu_elinks.cxx | 58 +++++ 22 files changed, 644 insertions(+), 262 deletions(-) create mode 100644 config/econ/econd_smm_init.yaml create mode 100644 config/pftool/ecal-smm-zcu.yaml create mode 100644 include/pflib/zcu/zcu_daq.h create mode 100644 include/pflib/zcu/zcu_elinks.h create mode 100644 src/pflib/Ecal.cxx create mode 100644 src/pflib/zcu/EcalSMMTarget.cxx create mode 100644 src/pflib/zcu/zcu_DAQ.cxx create mode 100644 src/pflib/zcu/zcu_elinks.cxx diff --git a/CMakeLists.txt b/CMakeLists.txt index 97e45a99..810ceaa5 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -111,8 +111,12 @@ set(pflib_src src/pflib/zcu/UIO.cxx src/pflib/zcu/Elinks_zcu.cxx src/pflib/zcu/lpGBT_ICEC_ZCU_Simple.cxx + src/pflib/zcu/zcu_elinks.cxx + src/pflib/zcu/zcu_DAQ.cxx src/pflib/zcu/zcu_optolink.cxx src/pflib/zcu/HcalBackplaneZCU.cxx + src/pflib/zcu/EcalSMMTarget.cxx + src/pflib/Ecal.cxx src/pflib/Bias.cxx ) diff --git a/app/lpgbt/main.cxx b/app/lpgbt/main.cxx index c20c562f..c3eaa68e 100644 --- a/app/lpgbt/main.cxx +++ b/app/lpgbt/main.cxx @@ -151,6 +151,12 @@ void general(const std::string& cmd, ToolBox* target) { pflib::lpgbt::standard_config::setup_hcal_trig(*target->lpgbt_ec); printf("Applied standard HCAL TRIG configuration\n"); } + if (cmd == "STANDARD_ECAL") { + pflib::lpgbt::standard_config::setup_ecal( + *target->lpgbt_ic, pflib::lpgbt::standard_config::ECAL_lpGBT_Config:: + DAQ_SingleModuleMotherboard); + printf("Applied standard ECAL DAQ configuration\n"); + } if (cmd == "MODE") { LPGBT_Mezz_Tester tester(target->coder_name); printf("MODE1 = 1 for Transceiver, MODE1=0 for Transmit-only\n"); @@ -752,6 +758,7 @@ auto gen = ->line("STATUS", "Status summary", general) ->line("MODE", "Setup the lpGBT ADDR and MODE1", general) ->line("STANDARD_HCAL", "Apply standard HCAL lpGBT setups", general) + ->line("STANDARD_ECAL", "Apply standard ECAL lpGBT setups", general) ->line("EXPERT_STANDARD_HCAL_DAQ", "Apply just standard HCAL DAQ lpGBT setup", general) ->line("EXPERT_STANDARD_HCAL_TRIG", diff --git a/app/tool/daq.cxx b/app/tool/daq.cxx index 7af7d1c6..2e796e09 100644 --- a/app/tool/daq.cxx +++ b/app/tool/daq.cxx @@ -56,6 +56,9 @@ static void daq_setup(const std::string& cmd, Target* pft) { if (pftool::state.readout_config() == pftool::State::CFG_HCALOPTO) { printf("Only acceptable format for now is ECOND_SW_HEADERS\n"); pftool::state.daq_format_mode = Target::DaqFormat::ECOND_SW_HEADERS; + } else if (pftool::state.readout_config() == pftool::State::CFG_ECALOPTO) { + printf("Only acceptable format for now is ECOND_SW_HEADERS\n"); + pftool::state.daq_format_mode = Target::DaqFormat::ECOND_SW_HEADERS; } else { printf("Format options:\n"); printf(" (1) ROC with ad-hoc headers as in TB2022\n"); @@ -164,6 +167,9 @@ static void daq_setup_standard(Target* tgt) { if (pftool::state.readout_config() == pftool::State::CFG_HCALOPTO) { pftool::state.daq_format_mode = Target::DaqFormat::ECOND_SW_HEADERS; } + if (pftool::state.readout_config() == pftool::State::CFG_ECALOPTO) { + pftool::state.daq_format_mode = Target::DaqFormat::ECOND_SW_HEADERS; + } if (pftool::state.readout_config() == pftool::State::CFG_HCALFMC) { /** diff --git a/app/tool/econ.cxx b/app/tool/econ.cxx index 5b090dc1..98ef033c 100644 --- a/app/tool/econ.cxx +++ b/app/tool/econ.cxx @@ -168,7 +168,10 @@ static void econ(const std::string& cmd, Target* pft) { bool isRunMode = econ.isRunMode(); isRunMode = pftool::readline_bool("Set ECON runbit: ", ~isRunMode); int edgesel = 0; - int invertfcmd = 1; + int invertfcmd = 0; + if (pftool::state.readout_config() == pftool::State::CFG_HCALOPTO) { + invertfcmd = 1; + } econ.setRunMode(isRunMode, edgesel, invertfcmd); // read status again econ.isRunMode(); diff --git a/app/tool/main.cxx b/app/tool/main.cxx index c5954870..aa4bcce7 100644 --- a/app/tool/main.cxx +++ b/app/tool/main.cxx @@ -329,6 +329,19 @@ int main(int argc, char* argv[]) { auto boardmask = target.get("boardmask", 0xff); tgt.reset(pflib::makeTargetHcalBackplaneZCU(ilink, boardmask)); readout_cfg = pftool::State::CFG_HCALOPTO; + } else if (target_type == "EcalSMMZCU") { + if (not is_fw_active(FW_SHORTNAME_UIO_ZCU)) { + pflib_log(fatal) << "'" << FW_SHORTNAME_UIO_ZCU + << "' firmware is not active on ZCU."; + pflib_log(fatal) << "Connection will likely fail."; + } + // need ilink to be in configuration + auto ilink = target.get("ilink"); + if (ilink < 0 or ilink > 1) { + PFEXCEPTION_RAISE("BadLink", "ZCU EcalSMM ilink can only be 0 or 1"); + } + tgt.reset(pflib::makeTargetEcalSMMZCU(ilink)); + readout_cfg = pftool::State::CFG_ECALOPTO; } else if (target_type == "HcalBackplaneBittware") { #ifdef USE_ROGUE // need ilink to be in configuration diff --git a/app/tool/pftool.h b/app/tool/pftool.h index a62b175a..4ff1a850 100644 --- a/app/tool/pftool.h +++ b/app/tool/pftool.h @@ -42,6 +42,7 @@ class pftool : public pflib::menu::Menu { public: static constexpr int CFG_HCALFMC = 1; static constexpr int CFG_HCALOPTO = 2; + static constexpr int CFG_ECALOPTO = 3; private: /// list of page names for tab completion per ROC ID diff --git a/config/econ/econd_smm_init.yaml b/config/econ/econd_smm_init.yaml new file mode 100644 index 00000000..2fde74dc --- /dev/null +++ b/config/econ/econd_smm_init.yaml @@ -0,0 +1,28 @@ +ERX: + 0_ENABLE: 1 + 1_ENABLE: 1 + 2_ENABLE: 1 + 3_ENABLE: 1 + 4_ENABLE: 1 + 5_ENABLE: 1 + 6_ENABLE: 1 + 7_ENABLE: 1 + 8_ENABLE: 1 + 9_ENABLE: 1 + 10_ENABLE: 1 + 11_ENABLE: 1 +ETX: + 0_INVERT_DATA: 0 # invert data +ELINKPROCESSORS: + GLOBAL_V_RECONSTRUCT_THRESH: 0 # number of erxs that should have the same + GLOBAL_VETO_PASS_FAIL: 0xFFFF # select all of the possible combinations of event status bits (E, HT, EBO, and M) as ok +FORMATTERBUFFER: + GLOBAL_ACTIVE_ETXS: 1 # only 1 active etx + GLOBAL_IDLE_PATTERN: 0x1277cc +ROCDAQCTRL: + GLOBAL_PASS_THRU_MODE: 1 + GLOBAL_MATCH_THRESHOLD: 0 + GLOBAL_ACTIVE_ERXS: 0xFFF +ALIGNER: + GLOBAL_FREEZE_OUTPUT_ENABLE: 0 # use this since channels might not be locked + GLOBAL_FREEZE_OUTPUT_ENABLE_ALL_CHANNELS_LOCKED: 0 diff --git a/config/pftool/ecal-smm-zcu.yaml b/config/pftool/ecal-smm-zcu.yaml new file mode 100644 index 00000000..402cbce7 --- /dev/null +++ b/config/pftool/ecal-smm-zcu.yaml @@ -0,0 +1,3 @@ +target: + type: "EcalSMMZCU" + ilink: 0 diff --git a/include/pflib/Ecal.h b/include/pflib/Ecal.h index 398e8752..e5d3363c 100644 --- a/include/pflib/Ecal.h +++ b/include/pflib/Ecal.h @@ -1,72 +1,82 @@ #pragma once +#include +#include +#include + #include "pflib/ECON.h" +#include "pflib/I2C.h" #include "pflib/ROC.h" -#include "pflib/Target.h" +#include "pflib/lpGBT.h" namespace pflib { /** - * Abstract class holding a set of ROCs and ECONs representing a HexaModule + * Class holding a set of ROCs and ECONs representing a HexaModule * - * One "ECal Group" is one DMA access coming out of the firmware. */ -class EcalGroup { +class EcalModule { public: - /** number of hgcrocs */ - virtual int nrocs() override { return modules_.rocs_.size(); } + EcalModule(lpGBT& lpgbt, int i2cbus, int modulenumber); + /** number of hgcrocs */ + int nrocs() const { return 6; } /// number of econds - virtual int necons() override { return modules_.econs_.size(); } + int necons() const { return 2; } /** do we have a roc with this id? */ - virtual bool have_roc(int iroc) const override; + bool have_roc(int iroc) const { return iroc >= 0 && iroc <= nrocs(); } + + static constexpr const int ECON_D = 0; + static constexpr const int ECON_T = 1; /** do we have an econ with this id? */ - virtual bool have_econ(int iecon) const override; + bool have_econ(int iecon) const { return iecon == ECON_D || iecon == ECON_T; } /** get a list of the IDs we have set up */ - virtual std::vector roc_ids() const override; + std::vector roc_ids() const; /** get a list of the econ IDs we have set up */ - virtual std::vector econ_ids() const override; + std::vector econ_ids() const; - /** Get a ROC interface for the given HGCROC board */ - virtual ROC roc(int which) override; + /** Get a ROC interface for the given HGCROC */ + ROC& roc(int which); - /** get a ECON interface for the given econ board */ - virtual ECON econ(int which) override; + /** get a ECON interface for the given ECON */ + ECON& econ(int which); /** Generate a hard reset to all the HGCROC boards */ - virtual void hardResetROCs() override; + void hardResetROCs(); /** generate a hard reset to all the ECON boards */ - virtual void hardResetECONs() override; + void hardResetECONs(); - /** Get the firmware version */ - virtual uint32_t getFirmwareVersion() override; + /** Generate a soft reset */ + void softResetROC(); - /** Generate a soft reset to a specific HGCROC board, -1 for all */ - virtual void softResetROC(int which = -1) override; - - /** Generate a soft reset to a specific ECON board, -1 for all */ - virtual void softResetECON(int which = -1) override; + /** Generate a soft reset */ + void softResetECON(); protected: + lpGBT& lpGBT_; + int i2cbus_; + int imodule_; + std::unique_ptr i2c_; /// representation of Ecal HexaModule - struct Module { - std::array rocs_; - ECON econ_d_; - ECON econ_t_; - }; - std::vector modules_; - - /// an Ecal Motherboard - struct Motherboard { - lpGBT daq_lpgbt_; - lpGBT trg_lpgbt_; - }; - std::vector motherboards_; + std::vector rocs_; + std::vector econs_; +}; + +class EcalMotherboard { + public: + EcalMotherboard() {} + /// create a module + void createModule(int imodule, lpGBT& lpGBT, int i2cbus); + /// get a module + EcalModule& module(int imodule); + + private: + std::vector> modules_; }; } // namespace pflib diff --git a/include/pflib/HcalBackplane.h b/include/pflib/HcalBackplane.h index 4781a163..b4ad7543 100644 --- a/include/pflib/HcalBackplane.h +++ b/include/pflib/HcalBackplane.h @@ -36,10 +36,10 @@ class HcalBackplane : public Target { virtual std::vector econ_ids() const override; /** Get a ROC interface for the given HGCROC board */ - virtual ROC roc(int which) override; + virtual ROC& roc(int which) override; /** get a ECON interface for the given econ board */ - virtual ECON econ(int which) override; + virtual ECON& econ(int which) override; /** Get an I2C interface for the given HGCROC board's bias bus */ Bias bias(int which); diff --git a/include/pflib/Target.h b/include/pflib/Target.h index 03bb1c49..d5c558d3 100644 --- a/include/pflib/Target.h +++ b/include/pflib/Target.h @@ -43,13 +43,13 @@ class Target { virtual std::vector econ_ids() const { return {}; } /** Get a ROC interface for the given HGCROC board */ - virtual ROC roc(int which) { + virtual ROC& roc(int which) { PFEXCEPTION_RAISE( "NoImp", "ROC Access has not been implemented for the current target."); } /** get a ECON interface for the given econ board */ - virtual ECON econ(int which) { + virtual ECON& econ(int which) { PFEXCEPTION_RAISE( "NoImp", "ECON Access has not been implemented for the current target."); @@ -113,6 +113,7 @@ class Target { Target* makeTargetFiberless(); Target* makeTargetHcalBackplaneZCU(int ilink, uint8_t board_mask); Target* makeTargetHcalBackplaneBittware(int ilink, uint8_t board_mask); +Target* makeTargetEcalSMMZCU(int ilink); } // namespace pflib diff --git a/include/pflib/lpgbt/lpGBT_standard_configs.h b/include/pflib/lpgbt/lpGBT_standard_configs.h index 0ea931c7..08f60a0d 100644 --- a/include/pflib/lpgbt/lpGBT_standard_configs.h +++ b/include/pflib/lpgbt/lpGBT_standard_configs.h @@ -16,6 +16,14 @@ void setup_hcal_trig(pflib::lpGBT&); /** Setup the lpGBT to train the eRx phase */ void setup_erxtraining(pflib::lpGBT&, bool prbs_on); +enum class ECAL_lpGBT_Config { + DAQ_SingleModuleMotherboard = 101, + TRIG_SingleModuleMotherboard = 201, +}; + +/** Setup the standard set of I/Os for ECAL, depending on the use case */ +void setup_ecal(pflib::lpGBT&, ECAL_lpGBT_Config); + } // namespace standard_config } // namespace lpgbt } // namespace pflib diff --git a/include/pflib/zcu/zcu_daq.h b/include/pflib/zcu/zcu_daq.h new file mode 100644 index 00000000..1f6302f3 --- /dev/null +++ b/include/pflib/zcu/zcu_daq.h @@ -0,0 +1,34 @@ +#include "pflib/DAQ.h" +#include "pflib/zcu/UIO.h" + +namespace pflib { +namespace zcu { + +class ZCU_Capture : public DAQ { + public: + ZCU_Capture(); + virtual void reset(); + virtual int getEventOccupancy(); + virtual void setupLink(int ilink, int l1a_delay, int l1a_capture_width) { + // none of these parameters are relevant for the econd capture, which is + // data-pattern based + } + virtual void getLinkSetup(int ilink, int& l1a_delay, int& l1a_capture_width) { + l1a_delay = -1; + l1a_capture_width = -1; + } + virtual void bufferStatus(int ilink, bool& empty, bool& full); + virtual void setup(int econid, int samples_per_ror, int soi); + virtual void enable(bool doenable); + virtual bool enabled(); + virtual std::vector getLinkData(int ilink); + virtual void advanceLinkReadPtr(); + virtual std::map get_debug(uint32_t ask); + + private: + UIO capture_; + bool per_econ_; +}; + +} // namespace zcu +} // namespace pflib diff --git a/include/pflib/zcu/zcu_elinks.h b/include/pflib/zcu/zcu_elinks.h new file mode 100644 index 00000000..a67920fb --- /dev/null +++ b/include/pflib/zcu/zcu_elinks.h @@ -0,0 +1,28 @@ +#include "pflib/Elinks.h" +#include "pflib/lpGBT.h" +#include "pflib/zcu/UIO.h" + +namespace pflib { +namespace zcu { + +/** Currently represents all elinks for dual-link configuration */ +class OptoElinksZCU : public Elinks { + public: + OptoElinksZCU(lpGBT* lpdaq, lpGBT* lptrig, int itarget); + virtual std::vector spy(int ilink); + virtual void setBitslip(int ilink, int bitslip); + virtual int getBitslip(int ilink); + virtual int scanBitslip(int ilink) { return -1; } + virtual uint32_t getStatusRaw(int ilink) { return 0; } + virtual void clearErrorCounters(int ilink) {} + virtual void resetHard() { + // not meaningful here + } + + private: + lpGBT *lp_daq_, *lp_trig_; + UIO uiodecoder_; +}; + +} // namespace zcu +} // namespace pflib diff --git a/src/pflib/Ecal.cxx b/src/pflib/Ecal.cxx new file mode 100644 index 00000000..2ac869f5 --- /dev/null +++ b/src/pflib/Ecal.cxx @@ -0,0 +1,70 @@ +#include "pflib/Ecal.h" + +#include "pflib/lpgbt/I2C.h" +#include "pflib/utility/string_format.h" + +namespace pflib { + +static constexpr int I2C_ECON_D = 0x64; +static constexpr int I2C_ECON_T = 0x24; +static constexpr int I2C_ROCS[] = {0x08, 0x18, 0x28, 0x48, 0x58, 0x68}; + +EcalModule::EcalModule(lpGBT& lpgbt, int i2cbus, int imodule) + : lpGBT_{lpgbt}, i2cbus_{i2cbus}, imodule_{imodule} { + i2c_ = std::make_unique(lpGBT_, i2cbus_); + econs_.push_back(ECON(*i2c_, I2C_ECON_D, "econd")); + econs_.push_back(ECON(*i2c_, I2C_ECON_T, "econt")); + for (int i = 0; i < nrocs(); i++) + rocs_.push_back(ROC(*i2c_, I2C_ROCS[i], + "si_rocv3b")); // confirm this is the right version +} + +std::vector EcalModule::roc_ids() const { + std::vector ids; + for (int i = 0; i < nrocs(); i++) ids.push_back(i); + return ids; +} +std::vector EcalModule::econ_ids() const { + std::vector ids; + for (int i = 0; i < necons(); i++) ids.push_back(i); + return ids; +} + +ROC& EcalModule::roc(int which) { + if (which < 0 || which >= nrocs()) { + PFEXCEPTION_RAISE("InvalidROC", "Invalid ROC requested"); + } + return rocs_[which]; +} + +ECON& EcalModule::econ(int which) { + if (which < 0 || which >= nrocs()) { + PFEXCEPTION_RAISE("InvalidECON", "Invalid ECON requested"); + } + return econs_[which]; +} + +using pflib::utility::string_format; + +void EcalModule::hardResetROCs() { + GPIO& gpio = lpGBT_.gpio_interface(); + gpio.setGPO(string_format("M%d_ROC_RE_Hb", imodule_), false); + gpio.setGPO(string_format("M%d_ROC_RE_Hb", imodule_), true); +} +void EcalModule::hardResetECONs() { + GPIO& gpio = lpGBT_.gpio_interface(); + gpio.setGPO(string_format("M%d_ECON_RE_Hb", imodule_), false); + gpio.setGPO(string_format("M%d_ECON_RE_Hb", imodule_), true); +} +void EcalModule::softResetROC() { + GPIO& gpio = lpGBT_.gpio_interface(); + gpio.setGPO(string_format("M%d_ROC_RE_Sb", imodule_), false); + gpio.setGPO(string_format("M%d_ROC_RE_Sb", imodule_), true); +} +void EcalModule::softResetECON() { + GPIO& gpio = lpGBT_.gpio_interface(); + gpio.setGPO(string_format("M%d_ECON_RE_Sb", imodule_), false); + gpio.setGPO(string_format("M%d_ECON_RE_Sb", imodule_), true); +} + +} // namespace pflib diff --git a/src/pflib/HcalBackplane.cxx b/src/pflib/HcalBackplane.cxx index e05784ae..61612e2a 100644 --- a/src/pflib/HcalBackplane.cxx +++ b/src/pflib/HcalBackplane.cxx @@ -68,7 +68,7 @@ void HcalBackplane::add_econ(int iecon, uint8_t econ_baseaddr, econ_connections_.emplace(iecon, ECONConnection{.econ_ = econ, .i2c_ = i2c}); } -ROC HcalBackplane::roc(int which) { +ROC& HcalBackplane::roc(int which) { auto roc_it{roc_connections_.find(which)}; if (roc_it == roc_connections_.end()) { PFEXCEPTION_RAISE("InvalidROCid", pflib::utility::string_format( @@ -77,7 +77,7 @@ ROC HcalBackplane::roc(int which) { return roc_it->second.roc_; } -ECON HcalBackplane::econ(int which) { +ECON& HcalBackplane::econ(int which) { auto econ_it{econ_connections_.find(which)}; if (econ_it == econ_connections_.end()) { PFEXCEPTION_RAISE("InvalidECONid", pflib::utility::string_format( diff --git a/src/pflib/ROC.cxx b/src/pflib/ROC.cxx index f997f3ec..7eb7a4a5 100644 --- a/src/pflib/ROC.cxx +++ b/src/pflib/ROC.cxx @@ -19,9 +19,7 @@ ROC::ROC(I2C& i2c, uint8_t roc_base_addr, const std::string& type_version) pflib_log(debug) << "base addr " << packing::hex(roc_base_); } -const std::string& ROC::type() const { - return type_version_; -} +const std::string& ROC::type() const { return type_version_; } std::vector ROC::readPage(int ipage, int len) { i2c_.set_bus_speed(1400); diff --git a/src/pflib/lpgbt/lpGBT_standard_configs.cxx b/src/pflib/lpgbt/lpGBT_standard_configs.cxx index cbb0cd45..873bab5d 100644 --- a/src/pflib/lpgbt/lpGBT_standard_configs.cxx +++ b/src/pflib/lpgbt/lpGBT_standard_configs.cxx @@ -109,6 +109,65 @@ void setup_erxtraining(pflib::lpGBT&, bool prbs_on) { /// TODO setup eRx for training mode } +void setup_ecal(pflib::lpGBT& lpgbt, ECAL_lpGBT_Config mode) { + if (mode == ECAL_lpGBT_Config::DAQ_SingleModuleMotherboard) { + lpgbt.gpio_cfg_set( + 4, + lpGBT::GPIO_IS_OUTPUT | lpGBT::GPIO_IS_PULLDOWN | lpGBT::GPIO_IS_STRONG, + "M0_POWER_EN"); + lpgbt.gpio_set(4, true); + lpgbt.gpio_cfg_set( + 5, + lpGBT::GPIO_IS_OUTPUT | lpGBT::GPIO_IS_PULLUP | lpGBT::GPIO_IS_STRONG, + "M0_ROC_RE_Hb"); + lpgbt.gpio_set(5, true); + lpgbt.gpio_cfg_set( + 6, + lpGBT::GPIO_IS_OUTPUT | lpGBT::GPIO_IS_PULLUP | lpGBT::GPIO_IS_STRONG, + "M0_ROC_RE_Sb"); + lpgbt.gpio_set(6, true); + lpgbt.gpio_cfg_set( + 7, + lpGBT::GPIO_IS_OUTPUT | lpGBT::GPIO_IS_PULLDOWN | lpGBT::GPIO_IS_STRONG, + "M0_ECON_RE_Hb"); + lpgbt.gpio_set(7, true); + lpgbt.gpio_cfg_set( + 8, + lpGBT::GPIO_IS_OUTPUT | lpGBT::GPIO_IS_PULLDOWN | lpGBT::GPIO_IS_STRONG, + "M0_ECON_RE_Sb"); + lpgbt.gpio_set(8, true); + + /* + lpgbt.gpio_cfg_set(0, lpGBT::GPIO_IS_OUTPUT | lpGBT::GPIO_IS_PULLDOWN | + lpGBT::GPIO_IS_STRONG, "DELAY_PICK0"); lpgbt.gpio_cfg_set(1, + lpGBT::GPIO_IS_OUTPUT | lpGBT::GPIO_IS_PULLDOWN | lpGBT::GPIO_IS_STRONG, + "DELAY_PICK1"); lpgbt.gpio_set(0,false); lpgbt.gpio_set(1,false); + */ + + lpgbt.setup_eclk(0, 320); // MODULE0 CLK320 + lpgbt.setup_eclk(7, 40); // REFCLK_TO_TRIG + + lpgbt.setup_etx(0, true); // MODULE0 FCMD + + // setup the one input... + lpgbt.setup_erx(0, 0); + + // setup the EC link + lpgbt.setup_ec(false, 4, false, 0, false, true, false, true); + + // finalize the setup + lpgbt.finalize_setup(); + } + if (mode == ECAL_lpGBT_Config::TRIG_SingleModuleMotherboard) { + // setup the high speed inputs + for (int i = 0; i < 6; i++) { + lpgbt.setup_erx(i, 0); + } + // finalize the setup + lpgbt.finalize_setup(); + } +} + } // namespace standard_config } // namespace lpgbt } // namespace pflib diff --git a/src/pflib/zcu/EcalSMMTarget.cxx b/src/pflib/zcu/EcalSMMTarget.cxx new file mode 100644 index 00000000..c800a8e1 --- /dev/null +++ b/src/pflib/zcu/EcalSMMTarget.cxx @@ -0,0 +1,118 @@ +#include "pflib/Ecal.h" +#include "pflib/Target.h" +#include "pflib/lpgbt/lpGBT_standard_configs.h" +#include "pflib/utility/string_format.h" +#include "pflib/zcu/zcu_daq.h" +#include "pflib/zcu/zcu_elinks.h" +#include "pflib/zcu/zcu_optolink.h" + +namespace pflib { + +static constexpr int ADDR_ECAL_SMM_DAQ = 0x78 | 0x04; +static constexpr int ADDR_ECAL_SMM_TRIG = 0x78; +static constexpr int I2C_BUS_M0 = 1; + +class EcalSMMTargetZCU : public Target { + public: + EcalSMMTargetZCU(int itarget) { + using namespace pflib::zcu; + // first, setup the optical links + std::string uio_coder = + pflib::utility::string_format("standardLpGBTpair-%d", itarget); + + daq_tport_ = std::make_unique( + uio_coder, false, ADDR_ECAL_SMM_DAQ); + trig_tport_ = std::make_unique( + uio_coder, true, ADDR_ECAL_SMM_TRIG); + daq_lpgbt_ = std::make_unique(*daq_tport_); + trig_lpgbt_ = std::make_unique(*trig_tport_); + + ecalModule_ = + std::make_shared(*daq_lpgbt_, I2C_BUS_M0, 0); + + elinks_ = std::make_unique(&(*daq_lpgbt_), &(*trig_lpgbt_), + itarget); + daq_ = std::make_unique(); + + using namespace pflib::lpgbt::standard_config; + + setup_ecal(*daq_lpgbt_, ECAL_lpGBT_Config::DAQ_SingleModuleMotherboard); + + try { + setup_ecal(*trig_lpgbt_, ECAL_lpGBT_Config::TRIG_SingleModuleMotherboard); + } catch (std::exception& e) { + printf("Problem (non critical) setting up TRIGGER lpgbt\n"); + } + + fc_ = std::shared_ptr(make_FastControlCMS_MMap()); + } + + virtual int nrocs() { return ecalModule_->nrocs(); } + virtual int necons() { return ecalModule_->necons(); } + virtual bool have_roc(int iroc) const { return ecalModule_->have_roc(iroc); } + virtual bool have_econ(int iecon) const { + return ecalModule_->have_econ(iecon); + } + virtual std::vector roc_ids() const { return ecalModule_->roc_ids(); } + virtual std::vector econ_ids() const { return ecalModule_->econ_ids(); } + + virtual ROC& roc(int which) { return ecalModule_->roc(which); } + virtual ECON& econ(int which) { return ecalModule_->econ(which); } + + virtual void softResetROC(int which) override { ecalModule_->softResetROC(); } + + virtual void softResetECON(int which = -1) override { + ecalModule_->softResetECON(); + } + + virtual void hardResetROCs() override { ecalModule_->hardResetROCs(); } + + virtual void hardResetECONs() override { ecalModule_->hardResetECONs(); } + + virtual Elinks& elinks() override { return *elinks_; } + + virtual DAQ& daq() override { return *daq_; } + + virtual FastControl& fc() override { return *fc_; } + + virtual void setup_run(int irun, Target::DaqFormat format, int contrib_id) { + format_ = format; + contrib_id_ = contrib_id; + } + + virtual std::vector read_event() override { + std::vector buf; + + if (format_ == Target::DaqFormat::ECOND_SW_HEADERS) { + for (int ievt = 0; ievt < daq().samples_per_ror(); ievt++) { + // only one elink right now + std::vector subpacket = daq().getLinkData(0); + buf.push_back((0x1 << 28) | ((daq().econid() & 0x3ff) << 18) | + (ievt << 13) | ((ievt == daq().soi()) ? (1 << 12) : (0)) | + (subpacket.size())); + buf.insert(buf.end(), subpacket.begin(), subpacket.end()); + daq().advanceLinkReadPtr(); + } + } else { + PFEXCEPTION_RAISE("NoImpl", + "HcalBackplaneZCUTarget::read_event not implemented " + "for provided DaqFormat"); + } + + return buf; + } + + private: + std::unique_ptr daq_tport_, trig_tport_; + std::shared_ptr ecalModule_; + std::unique_ptr daq_lpgbt_, trig_lpgbt_; + std::unique_ptr elinks_; + std::unique_ptr daq_; + std::shared_ptr fc_; + Target::DaqFormat format_; + int contrib_id_; +}; + +Target* makeTargetEcalSMMZCU(int ilink) { return new EcalSMMTargetZCU(ilink); } + +} // namespace pflib diff --git a/src/pflib/zcu/HcalBackplaneZCU.cxx b/src/pflib/zcu/HcalBackplaneZCU.cxx index cb8438c0..6df52ba3 100644 --- a/src/pflib/zcu/HcalBackplaneZCU.cxx +++ b/src/pflib/zcu/HcalBackplaneZCU.cxx @@ -3,6 +3,8 @@ #include "pflib/lpgbt/lpGBT_standard_configs.h" #include "pflib/utility/string_format.h" #include "pflib/zcu/lpGBT_ICEC_ZCU_Simple.h" +#include "pflib/zcu/zcu_daq.h" +#include "pflib/zcu/zcu_elinks.h" #include "pflib/zcu/zcu_optolink.h" namespace pflib { @@ -16,221 +18,10 @@ static constexpr int I2C_BUS_BOARD = 0; // TRIG static constexpr int ADDR_MUX_BIAS = 0x70; static constexpr int ADDR_MUX_BOARD = 0x71; -/** Currently represents all elinks for dual-link configuration */ -class OptoElinksZCU : public Elinks { - public: - OptoElinksZCU(lpGBT* lpdaq, lpGBT* lptrig, int itarget) - : Elinks(6 * 2), - lp_daq_(lpdaq), - lp_trig_(lptrig), - uiodecoder_( - pflib::utility::string_format("standardLpGBTpair-%d", itarget)) { - // deactivate all the links except DAQ link 0 for now - for (int i = 1; i < 6 * 2; i++) markActive(i, false); - } - std::vector spy(int ilink) { - std::vector retval; - // spy now... - static constexpr int REG_CAPTURE_ENABLE = 16; - static constexpr int REG_CAPTURE_OLINK = 17; - static constexpr int REG_CAPTURE_ELINK = 18; - static constexpr int REG_CAPTURE_PTR = 19; - static constexpr int REG_CAPTURE_WINDOW = 20; - uiodecoder_.write(REG_CAPTURE_OLINK, ilink % 6); - uiodecoder_.write(REG_CAPTURE_ELINK, (ilink / 6 + 1) & 0x7); - uiodecoder_.write(REG_CAPTURE_ENABLE, 0); - uiodecoder_.write(REG_CAPTURE_ENABLE, 1); - usleep(1000); - uiodecoder_.write(REG_CAPTURE_ENABLE, 0); - for (int i = 0; i < 64; i++) { - uiodecoder_.write(REG_CAPTURE_PTR, i); - usleep(1); - retval.push_back(uiodecoder_.read(REG_CAPTURE_WINDOW)); - } - return retval; - } - - virtual void setBitslip(int ilink, int bitslip) { - static constexpr int REG_UPLINK_PHASE = 21; - uint32_t val = uiodecoder_.read(REG_UPLINK_PHASE + ilink / 6); - uint32_t mask = 0x1F << ((ilink % 6) * 5); - // set to zero - val = val | mask; - val = val ^ mask; - // mask in new phase - val = val | ((bitslip & 0x1F) << ((ilink % 6) * 5)); - uiodecoder_.write(REG_UPLINK_PHASE + ilink / 6, val); - } - virtual int getBitslip(int ilink) { - static constexpr int REG_UPLINK_PHASE = 21; - uint32_t val = uiodecoder_.read(REG_UPLINK_PHASE + (ilink / 6)); - return (val >> ((ilink % 6) * 5)) & 0x1F; - } - virtual int scanBitslip(int ilink) { return -1; } - virtual uint32_t getStatusRaw(int ilink) { return 0; } - virtual void clearErrorCounters(int ilink) {} - virtual void resetHard() { - // not meaningful here - } - - private: - lpGBT *lp_daq_, *lp_trig_; - UIO uiodecoder_; -}; - -class HcalBackplaneZCU_Capture : public DAQ { - static constexpr uint32_t ADDR_IDLE_PATTERN = 0x604 / 4; - static constexpr uint32_t ADDR_HEADER_MARKER = 0x600 / 4; - static constexpr uint32_t MASK_HEADER_MARKER = 0x0001FF00; - static constexpr uint32_t ADDR_ENABLE = 0x600 / 4; - static constexpr uint32_t MASK_ENABLE = 0x00000001; - static constexpr uint32_t ADDR_EVB_CLEAR = 0x100 / 4; - static constexpr uint32_t MASK_EVB_CLEAR = 0x00000001; - static constexpr uint32_t ADDR_ADV_IO = 0x080 / 4; - static constexpr uint32_t MASK_ADV_IO = 0x00000001; - static constexpr uint32_t ADDR_ADV_AXIS = 0x080 / 4; - static constexpr uint32_t MASK_ADV_AXIS = 0x00000002; - - static constexpr uint32_t ADDR_PACKET_SETUP = 0x400 / 4; - static constexpr uint32_t MASK_ECON_ID = 0x000003FF; - static constexpr uint32_t MASK_L1A_PER_PACKET = 0x00007C00; - static constexpr uint32_t MASK_SOI = 0x000F8000; - static constexpr uint32_t AXIS_ENABLE = 0x80000000; - - static constexpr uint32_t ADDR_UPPER_ADDR = 0x404 / 4; - static constexpr uint32_t MASK_UPPER_ADDR = 0x0000003F; - - static constexpr uint32_t ADDR_INFO = 0x800 / 4; - static constexpr uint32_t MASK_IO_NEVENTS = 0x0000007F; - static constexpr uint32_t MASK_IO_SIZE_NEXT = 0x0000FF80; - static constexpr uint32_t MASK_AXIS_NWORDS = 0x1FFF0000; - static constexpr uint32_t MASK_TVALID_DAQ = 0x20000000; - static constexpr uint32_t MASK_TREADY_DAQ = 0x40000000; - - static constexpr uint32_t ADDR_PAGED_READ = 0x800 / 4; - static constexpr uint32_t ADDR_BASE_COUNTER = 0x900 / 4; - - public: - HcalBackplaneZCU_Capture() : DAQ(1), capture_("econd-buffer-0") { - // printf("Firmware type and version: %08x %08x - // %08x\n",capture_.read(0),capture_.read(ADDR_IDLE_PATTERN),capture_.read(ADDR_HEADER_MARKER)); - // setting up with expected capture parameters - capture_.write(ADDR_IDLE_PATTERN, 0x1277cc); - capture_.writeMasked(ADDR_HEADER_MARKER, MASK_HEADER_MARKER, - 0x1E6); // 0xAA followed by one bit... - per_econ_ = true; // reading from the per-econ buffer, not the AXIS buffer - } - virtual void reset() { - capture_.write(ADDR_EVB_CLEAR, MASK_EVB_CLEAR); // auto-clear - } - virtual int getEventOccupancy() { - capture_.writeMasked(ADDR_UPPER_ADDR, MASK_UPPER_ADDR, 0); // get on page 0 - if (per_econ_) - return capture_.readMasked(ADDR_INFO, MASK_IO_NEVENTS) / - samples_per_ror(); - else if (capture_.readMasked(ADDR_INFO, MASK_AXIS_NWORDS) != 0) - return 1; - else - return 0; - } - virtual void setupLink(int ilink, int l1a_delay, int l1a_capture_width) { - // none of these parameters are relevant for the econd capture, which is - // data-pattern based - } - virtual void getLinkSetup(int ilink, int& l1a_delay, int& l1a_capture_width) { - l1a_delay = -1; - l1a_capture_width = -1; - } - virtual void bufferStatus(int ilink, bool& empty, bool& full) { - int nevt = getEventOccupancy(); - empty = (nevt == 0); - full = (nevt == 0x7f); - } - virtual void setup(int econid, int samples_per_ror, int soi) { - pflib::DAQ::setup(econid, samples_per_ror, soi); - capture_.writeMasked(ADDR_PACKET_SETUP, MASK_ECON_ID, econid); - capture_.writeMasked(ADDR_PACKET_SETUP, MASK_L1A_PER_PACKET, - samples_per_ror); - capture_.writeMasked(ADDR_PACKET_SETUP, MASK_SOI, soi); - } - virtual void enable(bool doenable) { - if (doenable) - capture_.rmw(ADDR_ENABLE, MASK_ENABLE, MASK_ENABLE); - else - capture_.rmw(ADDR_ENABLE, MASK_ENABLE, 0); - if (!per_econ_ && doenable) - capture_.rmw(ADDR_PACKET_SETUP, AXIS_ENABLE, AXIS_ENABLE); - else - capture_.rmw(ADDR_PACKET_SETUP, AXIS_ENABLE, 0); - pflib::DAQ::enable(doenable); - } - virtual bool enabled() { - return capture_.readMasked(ADDR_ENABLE, MASK_ENABLE); - } - virtual std::vector getLinkData(int ilink) { - uint32_t words = 0; - std::vector retval; - static const uint32_t UBITS = 0x3F00; - static const uint32_t LBITS = 0x00FF; - - capture_.writeMasked(ADDR_UPPER_ADDR, MASK_UPPER_ADDR, - 0); // must be on basic page - - if (per_econ_) - words = capture_.readMasked(ADDR_INFO, MASK_IO_SIZE_NEXT); - else - words = capture_.readMasked(ADDR_INFO, MASK_AXIS_NWORDS); - - uint32_t iold = 0xFFFFFF; - for (uint32_t i = 0; i < words; i++) { - if ((iold & UBITS) != (i & UBITS)) // new upper address block - if (per_econ_) - capture_.writeMasked(ADDR_UPPER_ADDR, MASK_UPPER_ADDR, - (i >> 8) | 0x04); - else - capture_.writeMasked(ADDR_UPPER_ADDR, MASK_UPPER_ADDR, - (i >> 8) | 0x20); - retval.push_back(capture_.read(ADDR_PAGED_READ + (i & LBITS))); - } - return retval; - } - virtual void advanceLinkReadPtr() { - if (per_econ_) - capture_.write(ADDR_ADV_IO, MASK_ADV_IO); // auto-clear - else - capture_.write(ADDR_ADV_AXIS, MASK_ADV_AXIS); // auto-clear - } - - virtual std::map get_debug(uint32_t ask) { - std::map dbg; - capture_.writeMasked(ADDR_UPPER_ADDR, MASK_UPPER_ADDR, 0); - static const int stepsize = 1; - FILE* f = fopen("dump.txt", "w"); - - for (int i = 0; i < 0xFFF / 4; i++) - fprintf(f, "%03x %03x %08x\n", i * 4, i, capture_.read(i)); - fclose(f); - - dbg["COUNT_IDLES"] = capture_.read(ADDR_BASE_COUNTER); - dbg["COUNT_NONIDLES"] = capture_.read(ADDR_BASE_COUNTER + stepsize * 1); - dbg["COUNT_STARTS"] = capture_.read(ADDR_BASE_COUNTER + stepsize * 2); - dbg["COUNT_STOPS"] = capture_.read(ADDR_BASE_COUNTER + stepsize * 3); - dbg["COUNT_WORDS"] = capture_.read(ADDR_BASE_COUNTER + stepsize * 4); - dbg["COUNT_IO_ADV"] = capture_.read(ADDR_BASE_COUNTER + stepsize * 5); - dbg["COUNT_TLAST"] = capture_.read(ADDR_BASE_COUNTER + stepsize * 6); - dbg["QUICKSPY"] = capture_.read(ADDR_BASE_COUNTER + 0x10); - dbg["STATE"] = capture_.read(ADDR_BASE_COUNTER + 0x11); - return dbg; - } - - private: - UIO capture_; - bool per_econ_; -}; - class HcalBackplaneZCU : public HcalBackplane { public: HcalBackplaneZCU(int itarget, uint8_t board_mask) { + using namespace pflib::zcu; // first, setup the optical links std::string uio_coder = pflib::utility::string_format("standardLpGBTpair-%d", itarget); @@ -271,7 +62,7 @@ class HcalBackplaneZCU : public HcalBackplane { elinks_ = std::make_unique(&(*daq_lpgbt_), &(*trig_lpgbt_), itarget); - daq_ = std::make_unique(); + daq_ = std::make_unique(); pflib::lpgbt::standard_config::setup_hcal_trig(*trig_lpgbt_); pflib::lpgbt::standard_config::setup_hcal_daq(*daq_lpgbt_); @@ -368,8 +159,8 @@ class HcalBackplaneZCU : public HcalBackplane { std::unique_ptr daq_tport_, trig_tport_; std::unique_ptr daq_lpgbt_, trig_lpgbt_; std::shared_ptr roc_i2c_, econ_i2c_; - std::unique_ptr elinks_; - std::unique_ptr daq_; + std::unique_ptr elinks_; + std::unique_ptr daq_; std::shared_ptr fc_; Target::DaqFormat format_; int contrib_id_; diff --git a/src/pflib/zcu/zcu_DAQ.cxx b/src/pflib/zcu/zcu_DAQ.cxx new file mode 100644 index 00000000..d328d003 --- /dev/null +++ b/src/pflib/zcu/zcu_DAQ.cxx @@ -0,0 +1,142 @@ +#include "pflib/zcu/zcu_daq.h" + +namespace pflib { +namespace zcu { + +static constexpr uint32_t ADDR_IDLE_PATTERN = 0x604 / 4; +static constexpr uint32_t ADDR_HEADER_MARKER = 0x600 / 4; +static constexpr uint32_t MASK_HEADER_MARKER = 0x0001FF00; +static constexpr uint32_t ADDR_ENABLE = 0x600 / 4; +static constexpr uint32_t MASK_ENABLE = 0x00000001; +static constexpr uint32_t ADDR_EVB_CLEAR = 0x100 / 4; +static constexpr uint32_t MASK_EVB_CLEAR = 0x00000001; +static constexpr uint32_t ADDR_ADV_IO = 0x080 / 4; +static constexpr uint32_t MASK_ADV_IO = 0x00000001; +static constexpr uint32_t ADDR_ADV_AXIS = 0x080 / 4; +static constexpr uint32_t MASK_ADV_AXIS = 0x00000002; + +static constexpr uint32_t ADDR_PACKET_SETUP = 0x400 / 4; +static constexpr uint32_t MASK_ECON_ID = 0x000003FF; +static constexpr uint32_t MASK_L1A_PER_PACKET = 0x00007C00; +static constexpr uint32_t MASK_SOI = 0x000F8000; +static constexpr uint32_t AXIS_ENABLE = 0x80000000; + +static constexpr uint32_t ADDR_UPPER_ADDR = 0x404 / 4; +static constexpr uint32_t MASK_UPPER_ADDR = 0x0000003F; + +static constexpr uint32_t ADDR_INFO = 0x800 / 4; +static constexpr uint32_t MASK_IO_NEVENTS = 0x0000007F; +static constexpr uint32_t MASK_IO_SIZE_NEXT = 0x0000FF80; +static constexpr uint32_t MASK_AXIS_NWORDS = 0x1FFF0000; +static constexpr uint32_t MASK_TVALID_DAQ = 0x20000000; +static constexpr uint32_t MASK_TREADY_DAQ = 0x40000000; + +static constexpr uint32_t ADDR_PAGED_READ = 0x800 / 4; +static constexpr uint32_t ADDR_BASE_COUNTER = 0x900 / 4; + +ZCU_Capture::ZCU_Capture() : DAQ(1), capture_("econd-buffer-0") { + // printf("Firmware type and version: %08x %08x + // %08x\n",capture_.read(0),capture_.read(ADDR_IDLE_PATTERN),capture_.read(ADDR_HEADER_MARKER)); + // setting up with expected capture parameters + capture_.write(ADDR_IDLE_PATTERN, 0x1277cc); + capture_.writeMasked(ADDR_HEADER_MARKER, MASK_HEADER_MARKER, + 0x1E6); // 0xAA followed by one bit... + per_econ_ = true; // reading from the per-econ buffer, not the AXIS buffer +} +void ZCU_Capture::reset() { + capture_.write(ADDR_EVB_CLEAR, MASK_EVB_CLEAR); // auto-clear +} +int ZCU_Capture::getEventOccupancy() { + capture_.writeMasked(ADDR_UPPER_ADDR, MASK_UPPER_ADDR, 0); // get on page 0 + if (per_econ_) + return capture_.readMasked(ADDR_INFO, MASK_IO_NEVENTS) / samples_per_ror(); + else if (capture_.readMasked(ADDR_INFO, MASK_AXIS_NWORDS) != 0) + return 1; + else + return 0; +} + +void ZCU_Capture::bufferStatus(int ilink, bool& empty, bool& full) { + int nevt = getEventOccupancy(); + empty = (nevt == 0); + full = (nevt == 0x7f); +} +void ZCU_Capture::setup(int econid, int samples_per_ror, int soi) { + pflib::DAQ::setup(econid, samples_per_ror, soi); + capture_.writeMasked(ADDR_PACKET_SETUP, MASK_ECON_ID, econid); + capture_.writeMasked(ADDR_PACKET_SETUP, MASK_L1A_PER_PACKET, samples_per_ror); + capture_.writeMasked(ADDR_PACKET_SETUP, MASK_SOI, soi); +} +void ZCU_Capture::enable(bool doenable) { + if (doenable) + capture_.rmw(ADDR_ENABLE, MASK_ENABLE, MASK_ENABLE); + else + capture_.rmw(ADDR_ENABLE, MASK_ENABLE, 0); + if (!per_econ_ && doenable) + capture_.rmw(ADDR_PACKET_SETUP, AXIS_ENABLE, AXIS_ENABLE); + else + capture_.rmw(ADDR_PACKET_SETUP, AXIS_ENABLE, 0); + pflib::DAQ::enable(doenable); +} + +bool ZCU_Capture::enabled() { + return capture_.readMasked(ADDR_ENABLE, MASK_ENABLE); +} + +std::vector ZCU_Capture::getLinkData(int ilink) { + uint32_t words = 0; + std::vector retval; + static const uint32_t UBITS = 0x3F00; + static const uint32_t LBITS = 0x00FF; + + capture_.writeMasked(ADDR_UPPER_ADDR, MASK_UPPER_ADDR, + 0); // must be on basic page + + if (per_econ_) + words = capture_.readMasked(ADDR_INFO, MASK_IO_SIZE_NEXT); + else + words = capture_.readMasked(ADDR_INFO, MASK_AXIS_NWORDS); + + uint32_t iold = 0xFFFFFF; + for (uint32_t i = 0; i < words; i++) { + if ((iold & UBITS) != (i & UBITS)) // new upper address block + if (per_econ_) + capture_.writeMasked(ADDR_UPPER_ADDR, MASK_UPPER_ADDR, (i >> 8) | 0x04); + else + capture_.writeMasked(ADDR_UPPER_ADDR, MASK_UPPER_ADDR, (i >> 8) | 0x20); + retval.push_back(capture_.read(ADDR_PAGED_READ + (i & LBITS))); + } + return retval; +} + +void ZCU_Capture::advanceLinkReadPtr() { + if (per_econ_) + capture_.write(ADDR_ADV_IO, MASK_ADV_IO); // auto-clear + else + capture_.write(ADDR_ADV_AXIS, MASK_ADV_AXIS); // auto-clear +} + +std::map ZCU_Capture::get_debug(uint32_t ask) { + std::map dbg; + capture_.writeMasked(ADDR_UPPER_ADDR, MASK_UPPER_ADDR, 0); + static const int stepsize = 1; + FILE* f = fopen("dump.txt", "w"); + + for (int i = 0; i < 0xFFF / 4; i++) + fprintf(f, "%03x %03x %08x\n", i * 4, i, capture_.read(i)); + fclose(f); + + dbg["COUNT_IDLES"] = capture_.read(ADDR_BASE_COUNTER); + dbg["COUNT_NONIDLES"] = capture_.read(ADDR_BASE_COUNTER + stepsize * 1); + dbg["COUNT_STARTS"] = capture_.read(ADDR_BASE_COUNTER + stepsize * 2); + dbg["COUNT_STOPS"] = capture_.read(ADDR_BASE_COUNTER + stepsize * 3); + dbg["COUNT_WORDS"] = capture_.read(ADDR_BASE_COUNTER + stepsize * 4); + dbg["COUNT_IO_ADV"] = capture_.read(ADDR_BASE_COUNTER + stepsize * 5); + dbg["COUNT_TLAST"] = capture_.read(ADDR_BASE_COUNTER + stepsize * 6); + dbg["QUICKSPY"] = capture_.read(ADDR_BASE_COUNTER + 0x10); + dbg["STATE"] = capture_.read(ADDR_BASE_COUNTER + 0x11); + return dbg; +} + +} // namespace zcu +} // namespace pflib diff --git a/src/pflib/zcu/zcu_elinks.cxx b/src/pflib/zcu/zcu_elinks.cxx new file mode 100644 index 00000000..f41ed693 --- /dev/null +++ b/src/pflib/zcu/zcu_elinks.cxx @@ -0,0 +1,58 @@ +#include "pflib/zcu/zcu_elinks.h" + +#include "pflib/utility/string_format.h" + +namespace pflib { +namespace zcu { + +/** Currently represents all elinks for dual-link configuration */ +OptoElinksZCU::OptoElinksZCU(lpGBT* lpdaq, lpGBT* lptrig, int itarget) + : Elinks(6 * 2), + lp_daq_(lpdaq), + lp_trig_(lptrig), + uiodecoder_( + pflib::utility::string_format("standardLpGBTpair-%d", itarget)) { + // deactivate all the links except DAQ link 0 for now + for (int i = 1; i < 6 * 2; i++) markActive(i, false); +} +std::vector OptoElinksZCU::spy(int ilink) { + std::vector retval; + // spy now... + static constexpr int REG_CAPTURE_ENABLE = 16; + static constexpr int REG_CAPTURE_OLINK = 17; + static constexpr int REG_CAPTURE_ELINK = 18; + static constexpr int REG_CAPTURE_PTR = 19; + static constexpr int REG_CAPTURE_WINDOW = 20; + uiodecoder_.write(REG_CAPTURE_OLINK, ilink % 6); + uiodecoder_.write(REG_CAPTURE_ELINK, (ilink / 6 + 1) & 0x7); + uiodecoder_.write(REG_CAPTURE_ENABLE, 0); + uiodecoder_.write(REG_CAPTURE_ENABLE, 1); + usleep(1000); + uiodecoder_.write(REG_CAPTURE_ENABLE, 0); + for (int i = 0; i < 64; i++) { + uiodecoder_.write(REG_CAPTURE_PTR, i); + usleep(1); + retval.push_back(uiodecoder_.read(REG_CAPTURE_WINDOW)); + } + return retval; +} + +void OptoElinksZCU::setBitslip(int ilink, int bitslip) { + static constexpr int REG_UPLINK_PHASE = 21; + uint32_t val = uiodecoder_.read(REG_UPLINK_PHASE + ilink / 6); + uint32_t mask = 0x1F << ((ilink % 6) * 5); + // set to zero + val = val | mask; + val = val ^ mask; + // mask in new phase + val = val | ((bitslip & 0x1F) << ((ilink % 6) * 5)); + uiodecoder_.write(REG_UPLINK_PHASE + ilink / 6, val); +} +int OptoElinksZCU::getBitslip(int ilink) { + static constexpr int REG_UPLINK_PHASE = 21; + uint32_t val = uiodecoder_.read(REG_UPLINK_PHASE + (ilink / 6)); + return (val >> ((ilink % 6) * 5)) & 0x1F; +} + +} // namespace zcu +} // namespace pflib From a79650353d3eec71393b93308db7a9bfb225d4a1 Mon Sep 17 00:00:00 2001 From: tomeichlersmith Date: Wed, 19 Nov 2025 08:17:04 -0800 Subject: [PATCH 16/28] check only file stem I had 'testbeam' in my path which meant the compilation failed since all of the register_maps for the econs were put into the econ{d/t}_test namespace --- register_maps/econ-to-header.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/register_maps/econ-to-header.py b/register_maps/econ-to-header.py index 7cd570e5..25a65248 100644 --- a/register_maps/econ-to-header.py +++ b/register_maps/econ-to-header.py @@ -238,9 +238,12 @@ def compile_registers(yaml_file, output_file): with open(yaml_file, "r") as f: data = yaml.safe_load(f) - econ_type = "d" if "ECOND" in yaml_file else "t" - if "test" in yaml_file: + filename = Path(yaml_file).stem + + econ_type = "d" if "ECOND" in filename else "t" + if "test" in filename: econ_type += "_test" + content = generate_header(yaml_file, data, econ_type) with open(output_file, "w") as f: f.write(content) From d524ea3668db23b0d1fcc122f0853c17bb590750 Mon Sep 17 00:00:00 2001 From: Jeremiah Mans Date: Wed, 19 Nov 2025 13:12:53 -0600 Subject: [PATCH 17/28] Add support for BITTWARE fast-controll (#270) * Cleanup compilation * Add separate ROR method * Change how command counters are returned * Add the bittware fast control controller * Small fixes * Also for ECON-T * Apply clang-format --style=Google --------- Co-authored-by: Jeremiah Mans Co-authored-by: Tom Eichlersmith <31970302+tomeichlersmith@users.noreply.github.com> Co-authored-by: github-actions[bot] --- CMakeLists.txt | 1 + app/tool/econ.cxx | 6 +- app/tool/expert.cxx | 21 +-- include/pflib/FastControl.h | 20 ++- include/pflib/bittware/bittware_FastControl.h | 50 +++++++ register_maps/register_maps_types.h | 2 + src/pflib/FastControlCMS_MMap.cxx | 25 +++- src/pflib/bittware/HcalBackplaneBittware.cxx | 11 +- src/pflib/bittware/bittware_FastControl.cxx | 130 ++++++++++++++++++ src/pflib/lpGBT.cxx | 2 + 10 files changed, 238 insertions(+), 30 deletions(-) create mode 100644 include/pflib/bittware/bittware_FastControl.h create mode 100644 src/pflib/bittware/bittware_FastControl.cxx diff --git a/CMakeLists.txt b/CMakeLists.txt index 810ceaa5..0f936a4b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -124,6 +124,7 @@ if (${Rogue_FOUND}) list(APPEND pflib_src src/pflib/bittware/bittware_axilite.cxx src/pflib/bittware/bittware_optolink.cxx + src/pflib/bittware/bittware_FastControl.cxx src/pflib/bittware/HcalBackplaneBittware.cxx ) endif() diff --git a/app/tool/econ.cxx b/app/tool/econ.cxx index 98ef033c..5168b539 100644 --- a/app/tool/econ.cxx +++ b/app/tool/econ.cxx @@ -80,7 +80,11 @@ static void econ_status(const std::string& cmd, Target* tgt) { // request that the counters are synchronously copied from internal to // readable registers avoiding compiler overhead for these parameters since // the compiler is very slow - econ.setValue(0x40f + 2, 1, 1); + if (pftool::state.iecon == 0) { + econ.setValue(0x40f, (1 << 2), 1); + } else { + econ.setValue(0xce0, (1 << 1), 1); + } // read fast command counters static const int fctrl_base = 0x3ab; static const std::vector> counters = { diff --git a/app/tool/expert.cxx b/app/tool/expert.cxx index 5d2b6979..8d2708dc 100644 --- a/app/tool/expert.cxx +++ b/app/tool/expert.cxx @@ -262,27 +262,12 @@ static void fc(const std::string& cmd, Target* pft) { pft->fc().getErrorCounters(sbe,dbe); printf(" Single bit errors: %d Double bit errors: %d\n",sbe,dbe); */ - std::vector cnt = pft->fc().getCmdCounters(); - for (int i = 0; i < cnt.size(); i++) { - std::string comment{""}; - if (auto it{bit_comments.find(i)}; it != bit_comments.end()) { - comment = it->second; - } - printf(" Bit %2d count: %10u (%s)\n", i, cnt[i], comment.c_str()); + std::map cnt = pft->fc().getCmdCounters(); + for (const auto& pair : cnt) { + printf(" %-30s: %10u \n", pair.first.c_str(), pair.second); } printf(" ELink Event Occupancy: %d\n", pft->daq().getEventOccupancy()); - /** - * FastControl::read_counters is default defined to do nothing, - * FastControlCMS_MMap does not override this default definition - * so nothing interesting happens - * - int spill_count, header_occ, event_count, vetoed_counter; - pft->fc().read_counters(spill_count, header_occ, event_count, - vetoed_counter); - printf(" Spills: %d Events: %d Header occupancy: %d Vetoed L1A: %d\n", - spill_count, event_count, header_occ, vetoed_counter); - */ } } diff --git a/include/pflib/FastControl.h b/include/pflib/FastControl.h index cffdc971..514f6858 100644 --- a/include/pflib/FastControl.h +++ b/include/pflib/FastControl.h @@ -2,6 +2,8 @@ #define PFLIB_FastControl_H_ #include +#include +#include #include namespace pflib { @@ -11,10 +13,12 @@ namespace pflib { */ class FastControl { public: + FastControl() : l1a_per_ror_{1} {} + /** * Get the counters for all the different fast control commands */ - virtual std::vector getCmdCounters() = 0; + virtual std::map getCmdCounters() = 0; /** * clear the counters @@ -30,6 +34,17 @@ class FastControl { /** send a single L1A */ virtual void sendL1A() = 0; + /** send a single ROR */ + virtual void sendROR() { + for (int i = 0; i < l1a_per_ror_; i++) sendL1A(); + } + + /** set the number of L1A per ROR */ + virtual void setL1AperROR(int n) { l1a_per_ror_ = n; } + + /** get the number of L1A per ROR */ + virtual int getL1AperROR() { return l1a_per_ror_; } + /** send a link reset */ virtual void linkreset_rocs() = 0; @@ -82,6 +97,9 @@ class FastControl { /** set the period in us for the timer trigger */ virtual void fc_timer_setup(int usdelay) {} + + protected: + int l1a_per_ror_; }; // factories diff --git a/include/pflib/bittware/bittware_FastControl.h b/include/pflib/bittware/bittware_FastControl.h new file mode 100644 index 00000000..93d4c609 --- /dev/null +++ b/include/pflib/bittware/bittware_FastControl.h @@ -0,0 +1,50 @@ +#ifndef PFLIB_bittware_FastControl_H_ +#define PFLIB_bittware_FastControl_H_ + +#include "pflib/FastControl.h" +#include "pflib/bittware/bittware_axilite.h" + +namespace pflib { +namespace bittware { + +/** + * Representation of FastControl controller + */ +class BWFastControl : public FastControl { + public: + BWFastControl(); + virtual std::map getCmdCounters(); + virtual void resetCounters(); + virtual void sendL1A(); + virtual void sendROR(); + virtual void setL1AperROR(int n); + virtual int getL1AperROR(); + virtual void linkreset_rocs(); + + virtual void bx_custom(int bx_addr, int bx_mask, int bx_new) {} + + virtual void linkreset_econs(); + virtual void bufferclear(); + virtual void orbit_count_reset(); + virtual void chargepulse(); + virtual void ledpulse(); + virtual void clear_run(); + virtual void fc_setup_calib(int charge_to_l1a); + virtual int fc_get_setup_calib(); + virtual void fc_setup_led(int charge_to_l1a); + virtual int fc_get_setup_led(); + + /** check the enables for various trigger/spill sources */ + virtual void fc_enables_read(bool& ext_l1a, bool& ext_spill, bool& timer_l1a); + + /** set the enables for various trigger/spill sources */ + virtual void fc_enables(bool ext_l1a, bool ext_spill, bool timer_l1a); + + private: + AxiLite axi_; +}; + +} // namespace bittware +} // namespace pflib + +#endif // PFLIB_bittware_FastControl_H_ diff --git a/register_maps/register_maps_types.h b/register_maps/register_maps_types.h index 7f73a573..1abc6647 100644 --- a/register_maps/register_maps_types.h +++ b/register_maps/register_maps_types.h @@ -11,6 +11,8 @@ #pragma once // need maps and strings for the LUTs +#include + #include #include #include diff --git a/src/pflib/FastControlCMS_MMap.cxx b/src/pflib/FastControlCMS_MMap.cxx index 1788a1c0..255319d6 100644 --- a/src/pflib/FastControlCMS_MMap.cxx +++ b/src/pflib/FastControlCMS_MMap.cxx @@ -192,9 +192,26 @@ class FastControlCMS_MMap : public FastControl { virtual void sendL1A() override { periodic(PEDESTAL_PERIODIC).request(); } - virtual std::vector getCmdCounters() override { - std::vector retval; - for (int i = 65; i <= 89; i++) retval.push_back(uio_.read(i)); + virtual std::map getCmdCounters() override { + static constexpr int COUNTER_START = 68; + static constexpr int COUNTER_LAST = 80; + static constexpr const char* names[] = {"L1A", + "L1A_NZS", + "ORBIT_SYNC", + "ORBIT_COUNT_RESET", + "CALIB_INT", + "CALIB_EXT", + "CHIPSYNC", + "ECR", + "EBR", + "LINKRESET_ROCT", + "LINKRESET_ROCD", + "LINKRESET_ECONT", + "LINKRESET_ECOND", + 0}; + std::map retval; + for (int i = COUNTER_START; i <= COUNTER_LAST; i++) + retval[names[i - COUNTER_START]] = uio_.read(i); return retval; } @@ -241,7 +258,7 @@ class FastControlCMS_MMap : public FastControl { uint32_t bx_out = uio_.readMasked(bx_addr, bx_mask); uint32_t bxout2 = uio_.read(bx_addr); printf("Read FC BX: %d\n", bxout2); - // // uint32_t bx_out_write = uio_.writeMasked(bx_addr, bx_mask, bx_new); + // uint32_t bx_out_write = uio_.writeMasked(bx_addr, bx_mask, bx_new); // std::cout << "readMasked (after write): " << bx_out << std::endl; } diff --git a/src/pflib/bittware/HcalBackplaneBittware.cxx b/src/pflib/bittware/HcalBackplaneBittware.cxx index a4a0ed7a..baf63acc 100644 --- a/src/pflib/bittware/HcalBackplaneBittware.cxx +++ b/src/pflib/bittware/HcalBackplaneBittware.cxx @@ -1,4 +1,5 @@ #include "pflib/HcalBackplane.h" +#include "pflib/bittware/bittware_FastControl.h" #include "pflib/bittware/bittware_optolink.h" #include "pflib/lpgbt/I2C.h" #include "pflib/lpgbt/lpGBT_standard_configs.h" @@ -299,9 +300,9 @@ class HcalBackplaneBW : public HcalBackplane { elinks_ = std::make_unique(&(*daq_lpgbt_), &(*trig_lpgbt_), itarget); daq_ = std::make_unique(); - - fc_ = std::shared_ptr(make_FastControlCMS_MMap()); */ + + fc_ = std::make_shared(); } virtual void softResetROC(int which) override { @@ -353,9 +354,7 @@ class HcalBackplaneBW : public HcalBackplane { PFEXCEPTION_RAISE("NoImpl", "DAQ not implemented"); } - virtual FastControl& fc() override { - PFEXCEPTION_RAISE("NoImpl", "FastControl not implemented"); - } + virtual FastControl& fc() override { return *fc_; } virtual void setup_run(int irun, Target::DaqFormat format, int contrib_id) { format_ = format; @@ -374,7 +373,7 @@ class HcalBackplaneBW : public HcalBackplane { std::shared_ptr roc_i2c_, econ_i2c_; // std::unique_ptr elinks_; // std::unique_ptr daq_; - // std::shared_ptr fc_; + std::shared_ptr fc_; Target::DaqFormat format_; int contrib_id_; }; diff --git a/src/pflib/bittware/bittware_FastControl.cxx b/src/pflib/bittware/bittware_FastControl.cxx new file mode 100644 index 00000000..def1e4fa --- /dev/null +++ b/src/pflib/bittware/bittware_FastControl.cxx @@ -0,0 +1,130 @@ +#include "pflib/bittware/bittware_FastControl.h" + +#include + +namespace pflib { +namespace bittware { + +static constexpr int REG_PULSE = 0x100; +static constexpr int REG_CTL = 0x600; +static constexpr uint32_t MASK_ENABLE_L1A = 0x00000001; +static constexpr uint32_t MASK_DISABLE_EXTERNAL = 0x00000002; +static constexpr uint32_t MASK_USE_NZS = 0x00000004; +static constexpr uint32_t MASK_L1A_PER_ROR = 0x00001F00; +static constexpr uint32_t MASK_LINK_RESET_BX = 0xFFF00000; +static constexpr int REG_CALIB_INT = 0x604; +static constexpr int REG_CALIB_EXT = 0x608; +static constexpr uint32_t MASK_CALIB_BX = 0x00000FFF; +static constexpr uint32_t MASK_CALIB_DELTA = 0x000FF000; + +static constexpr int BIT_FIRE_BCR = 0; +static constexpr int BIT_FIRE_L1A = 1; +static constexpr int BIT_FIRE_L1ACHAIN = 2; +static constexpr int BIT_FIRE_OCR = 4; +static constexpr int BIT_FIRE_EBR = 5; +static constexpr int BIT_FIRE_ECR = 6; +static constexpr int BIT_FIRE_LINKRESET_ROCD = 7; +static constexpr int BIT_FIRE_LINKRESET_ROCT = 8; +static constexpr int BIT_FIRE_LINKRESET_ECOND = 9; +static constexpr int BIT_FIRE_LINKRESET_ECONT = 10; +static constexpr int BIT_FIRE_CALIB_INT = 11; +static constexpr int BIT_FIRE_CALIB_EXT = 12; +static constexpr int BIT_RESET_COUNTERS = 30; + +static constexpr int REG_COUNTER_BASE = 0xC10; + +BWFastControl::BWFastControl() : axi_(0x1000) { + static const int BX_FOR_CALIB = 42; + axi_.writeMasked(REG_CALIB_INT, MASK_CALIB_BX, BX_FOR_CALIB); + axi_.writeMasked(REG_CALIB_EXT, MASK_CALIB_BX, BX_FOR_CALIB); + static const int BX_FOR_LINK_RESET = 40 * 64 - 64; + axi_.writeMasked(REG_CTL, MASK_LINK_RESET_BX, BX_FOR_LINK_RESET); +} + +static constexpr const char* names[] = {"BCR", + "OCR", + "ECR", + "EBR", + "CALIB_INT", + "CALIB_EXT", + "LINKRESET_ROCT", + "LINKRESET_ROCD", + "LINKRESET_ECONT", + "LINKRESET_ECOND", + "L1A", + "L1A_NZS", + "INT_ROR", + "EXT_ROR", + 0}; + +std::map BWFastControl::getCmdCounters() { + std::map retval; + for (int i = 0; names[i] != 0; i++) { + retval[names[i]] = axi_.read(REG_COUNTER_BASE + 4 * i); + } + return retval; +} +void BWFastControl::resetCounters() { + axi_.write(REG_PULSE, 1 << BIT_RESET_COUNTERS); +} +void BWFastControl::sendL1A() { axi_.write(REG_PULSE, 1 << BIT_FIRE_L1A); } +void BWFastControl::sendROR() { axi_.write(REG_PULSE, 1 << BIT_FIRE_L1ACHAIN); } +void BWFastControl::setL1AperROR(int n) { + l1a_per_ror_ = n & 0x1F; + return axi_.writeMasked(REG_CTL, MASK_L1A_PER_ROR, l1a_per_ror_); +} +int BWFastControl::getL1AperROR() { + return axi_.readMasked(REG_CTL, MASK_L1A_PER_ROR); +} +void BWFastControl::linkreset_rocs() { + axi_.write(REG_PULSE, 1 << BIT_FIRE_LINKRESET_ROCD); + usleep(1000); + axi_.write(REG_PULSE, 1 << BIT_FIRE_LINKRESET_ROCT); +} +void BWFastControl::linkreset_econs() { + axi_.write(REG_PULSE, 1 << BIT_FIRE_LINKRESET_ECOND); + usleep(1000); + axi_.write(REG_PULSE, 1 << BIT_FIRE_LINKRESET_ECONT); +} +void BWFastControl::bufferclear() { axi_.write(REG_PULSE, 1 << BIT_FIRE_EBR); } +void BWFastControl::orbit_count_reset() { + axi_.write(REG_PULSE, 1 << BIT_FIRE_OCR); +} +void BWFastControl::chargepulse() { + axi_.write(REG_PULSE, 1 << BIT_FIRE_CALIB_INT); +} +void BWFastControl::ledpulse() { + axi_.write(REG_PULSE, 1 << BIT_FIRE_CALIB_EXT); +} +void BWFastControl::clear_run() { + bufferclear(); + resetCounters(); +} +void BWFastControl::fc_setup_calib(int charge_to_l1a) { + axi_.writeMasked(REG_CALIB_INT, MASK_CALIB_DELTA, charge_to_l1a); +} +int BWFastControl::fc_get_setup_calib() { + return axi_.readMasked(REG_CALIB_INT, MASK_CALIB_DELTA); +} +void BWFastControl::fc_setup_led(int charge_to_l1a) { + axi_.writeMasked(REG_CALIB_EXT, MASK_CALIB_DELTA, charge_to_l1a); +} +int BWFastControl::fc_get_setup_led() { + return axi_.readMasked(REG_CALIB_EXT, MASK_CALIB_DELTA); +} + +void BWFastControl::fc_enables_read(bool& ext_l1a, bool& ext_spill, + bool& timer_l1a) { + ext_spill = false; + timer_l1a = false; + ext_l1a = (axi_.readMasked(REG_CTL, MASK_DISABLE_EXTERNAL) == 0); +} +void BWFastControl::fc_enables(bool ext_l1a, bool ext_spill, bool timer_l1a) { + if (ext_l1a) + axi_.writeMasked(REG_CTL, MASK_DISABLE_EXTERNAL, 0); + else + axi_.writeMasked(REG_CTL, MASK_DISABLE_EXTERNAL, 1); +} + +} // namespace bittware +} // namespace pflib diff --git a/src/pflib/lpGBT.cxx b/src/pflib/lpGBT.cxx index c6e41c27..b7c6bf6a 100644 --- a/src/pflib/lpGBT.cxx +++ b/src/pflib/lpGBT.cxx @@ -2,6 +2,8 @@ #include +#include + namespace pflib { std::vector lpGBT_ConfigTransport::read_regs(uint16_t reg, int n) { From 802a4a2fdd57f8986bf4ee17ced786a3152cb548 Mon Sep 17 00:00:00 2001 From: Cristina Mantilla Suarez Date: Wed, 19 Nov 2025 16:08:10 -0500 Subject: [PATCH 18/28] Select ROC and ECON in phase word alignment task (#271) * get iecon and iroc from pftool state * use type instead of iecon * Apply clang-format --style=Google --------- Co-authored-by: github-actions[bot] --- app/tool/econ.cxx | 2 +- app/tool/tasks/align_phase_word.cxx | 10 +++++++--- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/app/tool/econ.cxx b/app/tool/econ.cxx index 5168b539..dc798884 100644 --- a/app/tool/econ.cxx +++ b/app/tool/econ.cxx @@ -80,7 +80,7 @@ static void econ_status(const std::string& cmd, Target* tgt) { // request that the counters are synchronously copied from internal to // readable registers avoiding compiler overhead for these parameters since // the compiler is very slow - if (pftool::state.iecon == 0) { + if (econ.type() == "econd") { econ.setValue(0x40f, (1 << 2), 1); } else { econ.setValue(0xce0, (1 << 1), 1); diff --git a/app/tool/tasks/align_phase_word.cxx b/app/tool/tasks/align_phase_word.cxx index b8a933e3..f05e2545 100644 --- a/app/tool/tasks/align_phase_word.cxx +++ b/app/tool/tasks/align_phase_word.cxx @@ -50,10 +50,14 @@ void print_roc_status(pflib::ROC& roc) { } void align_phase_word(Target* tgt) { - debug_checks = pftool::readline_bool("Enable debug checks?", false); + debug_checks = pftool::readline_bool("Enable debug checks?", true); - auto roc = tgt->roc(pftool::state.iroc); - auto econ = tgt->econ(pftool::state.iecon); + int iroc = pftool::readline_int("Which ROC to manage: ", pftool::state.iroc); + int iecon = + pftool::readline_int("Which ECON to manage: ", pftool::state.iecon); + + auto roc = tgt->roc(iroc); + auto econ = tgt->econ(iecon); // TODO: get channels from user std::vector channels = {6, 7}; From ef91a8d8728c35f947e122eb5fe8336a4131f9e7 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Wed, 19 Nov 2025 23:09:17 +0000 Subject: [PATCH 19/28] Apply clang-format --style=Google --- app/tool/algorithm/level_pedestals.cxx | 2 +- app/tool/daq.cxx | 28 ++++++++++------ app/tool/daq_run.cxx | 44 ++++++++++++++------------ app/tool/daq_run.h | 11 ++++--- 4 files changed, 49 insertions(+), 36 deletions(-) diff --git a/app/tool/algorithm/level_pedestals.cxx b/app/tool/algorithm/level_pedestals.cxx index 91bdb99d..24310fd1 100644 --- a/app/tool/algorithm/level_pedestals.cxx +++ b/app/tool/algorithm/level_pedestals.cxx @@ -19,7 +19,7 @@ * Calib and Common Mode channels are ignored. * TOT/TOA and the sample Tp/Tc flags are ignored. */ -template +template static std::array get_adc_medians( const std::vector& data) { std::array medians; diff --git a/app/tool/daq.cxx b/app/tool/daq.cxx index cb15ba20..b73aa2b8 100644 --- a/app/tool/daq.cxx +++ b/app/tool/daq.cxx @@ -351,31 +351,39 @@ static void daq(const std::string& cmd, Target* pft) { if (decoding) { std::unique_ptr consumer; - switch(pftool::state.daq_format_mode) { + switch (pftool::state.daq_format_mode) { case Target::DaqFormat::ECOND_SW_HEADERS: - consumer = std::make_unique>( - fname+".csv", + consumer = std::make_unique< + DecodeAndWriteToCSV>( + fname + ".csv", [](std::ofstream& f) { f << std::boolalpha; - f << pflib::packing::SoftWrappedECONDEventPacket::to_csv_header << '\n'; + f << pflib::packing::SoftWrappedECONDEventPacket::to_csv_header + << '\n'; }, - [](std::ofstream& f, const pflib::packing::SoftWrappedECONDEventPacket& ep) { + [](std::ofstream& f, + const pflib::packing::SoftWrappedECONDEventPacket& ep) { ep.to_csv(f); }); break; case Target::DaqFormat::SIMPLEROC: - consumer = std::make_unique>( - fname+".csv", + consumer = std::make_unique< + DecodeAndWriteToCSV>( + fname + ".csv", [](std::ofstream& f) { f << std::boolalpha; - f << pflib::packing::SingleROCEventPacket::to_csv_header << '\n'; + f << pflib::packing::SingleROCEventPacket::to_csv_header + << '\n'; }, - [](std::ofstream& f, const pflib::packing::SingleROCEventPacket& ep) { + [](std::ofstream& f, + const pflib::packing::SingleROCEventPacket& ep) { ep.to_csv(f); }); break; default: - PFEXCEPTION_RAISE("BadConf", "Unable to do live decoding for the currently configured format."); + PFEXCEPTION_RAISE("BadConf", + "Unable to do live decoding for the currently " + "configured format."); } daq_run(pft, cmd, *consumer, nevents, pftool::state.daq_rate); } else { diff --git a/app/tool/daq_run.cxx b/app/tool/daq_run.cxx index 8244c396..026f178e 100644 --- a/app/tool/daq_run.cxx +++ b/app/tool/daq_run.cxx @@ -77,7 +77,7 @@ void WriteToBinaryFile::consume(std::vector& event) { fwrite(&(event[0]), sizeof(uint32_t), event.size(), fp_); } -template +template void DecodeAndWrite::consume(std::vector& event) { // we have to manually check the size so that we can do the reinterpret_cast if (event.size() == 0) { @@ -92,13 +92,14 @@ void DecodeAndWrite::consume(std::vector& event) { write_event(ep_); } -template +template DecodeAndWriteToCSV::DecodeAndWriteToCSV( const std::string& file_name, std::function write_header, - std::function - write_event) - : DecodeAndWrite(), file_{file_name}, write_event_{write_event} { + std::function write_event) + : DecodeAndWrite(), + file_{file_name}, + write_event_{write_event} { if (not file_) { PFEXCEPTION_RAISE("FileOpen", "unable to open " + file_name + " for writing"); @@ -106,30 +107,30 @@ DecodeAndWriteToCSV::DecodeAndWriteToCSV( write_header(file_); } -template +template void DecodeAndWriteToCSV::write_event(const EventPacket& ep) { write_event_(file_, ep); } -template -DecodeAndWriteToCSV all_channels_to_csv(const std::string& file_name) { +template +DecodeAndWriteToCSV all_channels_to_csv( + const std::string& file_name) { return DecodeAndWriteToCSV( file_name, [](std::ofstream& f) { f << std::boolalpha; f << EventPacket::to_csv_header << '\n'; }, - [](std::ofstream& f, const EventPacket& ep) { - ep.to_csv(f); - }); + [](std::ofstream& f, const EventPacket& ep) { ep.to_csv(f); }); } -template -DecodeAndBuffer::DecodeAndBuffer(int nevents) : DecodeAndWrite() { +template +DecodeAndBuffer::DecodeAndBuffer(int nevents) + : DecodeAndWrite() { set_buffer_size(nevents); } -template +template void DecodeAndBuffer::write_event(const EventPacket& ep) { if (ep_buffer_.size() > ep_buffer_.capacity()) { pflib_log(warn) << "Trying to push more elements to buffer than allocated " @@ -138,16 +139,19 @@ void DecodeAndBuffer::write_event(const EventPacket& ep) { } ep_buffer_.push_back(ep); } - -template -void DecodeAndBuffer::start_run() { ep_buffer_.clear(); } -template -const std::vector& DecodeAndBuffer::get_buffer() const { +template +void DecodeAndBuffer::start_run() { + ep_buffer_.clear(); +} + +template +const std::vector& DecodeAndBuffer::get_buffer() + const { return ep_buffer_; } -template +template void DecodeAndBuffer::set_buffer_size(int nevents) { ep_buffer_.reserve(nevents); } diff --git a/app/tool/daq_run.h b/app/tool/daq_run.h index a6570ad0..60fe2c0e 100644 --- a/app/tool/daq_run.h +++ b/app/tool/daq_run.h @@ -55,7 +55,7 @@ class WriteToBinaryFile : public DAQRunConsumer { * other code just needs to write functions that define how the * decoded data should be written out. */ -template +template class DecodeAndWrite : public DAQRunConsumer { public: virtual ~DecodeAndWrite() = default; @@ -81,7 +81,7 @@ class DecodeAndWrite : public DAQRunConsumer { * specializatin of DecodeAndWrite that holds a std::ofstream * for the user with functions for writing the header and events */ -template +template class DecodeAndWriteToCSV : public DecodeAndWrite { /// output file writing to std::ofstream file_; @@ -98,8 +98,9 @@ class DecodeAndWriteToCSV : public DecodeAndWrite { virtual void write_event(const EventPacket& ep) final; }; -template -DecodeAndWriteToCSV all_channels_to_csv(const std::string& file_name); +template +DecodeAndWriteToCSV all_channels_to_csv( + const std::string& file_name); /** * Consume an event packet, decode it, and save to buffer. @@ -117,7 +118,7 @@ DecodeAndWriteToCSV all_channels_to_csv(const std::string& file_nam * const auto& events{buffer.get_buffer()}; * ``` */ -template +template class DecodeAndBuffer : public DecodeAndWrite { public: DecodeAndBuffer(int nevents); From 17879afc9077ee0176a38dc701c7b24149ed4c08 Mon Sep 17 00:00:00 2001 From: joshgreaves332 Date: Wed, 19 Nov 2025 20:58:51 -0500 Subject: [PATCH 20/28] adding templated helper function to get pedestal runs, utilizing eventPacket template --- app/tool/algorithm/level_pedestals.cxx | 122 +++++++++++++++---------- 1 file changed, 76 insertions(+), 46 deletions(-) diff --git a/app/tool/algorithm/level_pedestals.cxx b/app/tool/algorithm/level_pedestals.cxx index 24310fd1..e7fbf582 100644 --- a/app/tool/algorithm/level_pedestals.cxx +++ b/app/tool/algorithm/level_pedestals.cxx @@ -19,6 +19,64 @@ * Calib and Common Mode channels are ignored. * TOT/TOA and the sample Tp/Tc flags are ignored. */ + +// Helper function to pull the 3 runs +template +static void pedestal_runs( + Target* tgt, ROC& roc, + std::array& baseline, + std::array& highend, + std::array& lowend, + std::array& target, + size_t n_events) + { + DecodeAndBuffer buffer{n_events}; + + {//baseline run scope + pflib_log(info) << "100 event baseline run"; + auto test_handle = roc.testParameters() + .add_all_channels("SIGN_DAC", 0) + .add_all_channels("DACB", 0) + .add_all_channels("TRIM_INV", 0) + .apply(); + daq_run(tgt, "PEDESTAL", buffer, n_events, 100); + pflib_log(trace) << "baseline run done, getting channel medians"; + auto medians = get_adc_medians(buffer.get_buffer()); + baseline = medians; + pflib_log(trace) << "got channel medians, getting link medians"; + for (int i_link{0}; i_link < 2; i_link++) { + auto start{medians.begin() + 36 * i_link}; + auto end{start + 36}; + auto halfway{start + 18}; + std::nth_element(start, halfway, end); + target[i_link] = *halfway; + } + pflib_log(trace) << "got link medians"; + } + + { // highend run scope + pflib_log(info) << "100 event highend run"; + auto test_handle = roc.testParameters() + .add_all_channels("SIGN_DAC", 0) + .add_all_channels("DACB", 0) + .add_all_channels("TRIM_INV", 63) + .apply(); + daq_run(tgt, "PEDESTAL", buffer, n_events, 100); + highend = get_adc_medians(buffer.get_buffer()); + } + + { // lowend run + pflib_log(info) << "100 event lowend run"; + auto test_handle = roc.testParameters() + .add_all_channels("SIGN_DAC", 1) + .add_all_channels("DACB", 31) + .add_all_channels("TRIM_INV", 0) + .apply(); + daq_run(tgt, "PEDESTAL", buffer, n_events, 100); + lowend = get_adc_medians(buffer.get_buffer()); + } + } + template static std::array get_adc_medians( const std::vector& data) { @@ -53,57 +111,29 @@ std::map> level_pedestals( std::array target; std::array baseline, highend, lowend; - DecodeAndBuffer buffer{n_events}; - - // for future devs: - // I do this weird extra brackets to limit the scope - // of the test_handle object and force it to destruct - // after the run is over (unsetting the parameters). - - { // baseline run - pflib_log(info) << "100 event baseline run"; - auto test_handle = roc.testParameters() - .add_all_channels("SIGN_DAC", 0) - .add_all_channels("DACB", 0) - .add_all_channels("TRIM_INV", 0) - .apply(); - daq_run(tgt, "PEDESTAL", buffer, n_events, 100); - pflib_log(trace) << "baseline run done, getting channel medians"; - auto medians = get_adc_medians(buffer.get_buffer()); - baseline = medians; - pflib_log(trace) << "got channel medians, getting link medians"; - for (int i_link{0}; i_link < 2; i_link++) { - auto start{medians.begin() + 36 * i_link}; - auto end{start + 36}; - auto halfway{start + 18}; - std::nth_element(start, halfway, end); - target[i_link] = *halfway; - } - pflib_log(trace) << "got link medians"; - } - { // highend run - pflib_log(info) << "100 event highend run"; - auto test_handle = roc.testParameters() - .add_all_channels("SIGN_DAC", 0) - .add_all_channels("DACB", 0) - .add_all_channels("TRIM_INV", 63) - .apply(); - daq_run(tgt, "PEDESTAL", buffer, n_events, 100); - highend = get_adc_medians(buffer.get_buffer()); + // DecodeAndBuffer buffer{n_events}; + if (pftool::state.daq_format_mode == Target::DaqFormat::SIMPLEROC) { + + pedestal_runs( + tgt, roc, baseline, highend, lowend, target, n_events); + } + else if (pftool::state.daq_format_mode == Target::DaqFormat::ECOND_SW_HEADERS) { - { // lowend run - pflib_log(info) << "100 event lowend run"; - auto test_handle = roc.testParameters() - .add_all_channels("SIGN_DAC", 1) - .add_all_channels("DACB", 31) - .add_all_channels("TRIM_INV", 0) - .apply(); - daq_run(tgt, "PEDESTAL", buffer, n_events, 100); - lowend = get_adc_medians(buffer.get_buffer()); + pedestal_runs( + tgt, roc, baseline, highend, lowend, target, n_events); + + } + else { + pflib_log(warn) + << "Unsupported DAQ format (" + << static_cast(pftool::state.daq_format_mode) + << ") in level_pedestals. Skipping pedestal leveling..."; } + + pflib_log(info) << "sample collections done, deducing settings"; std::map> settings; for (int ch{0}; ch < 72; ch++) { From 2efea56e7fc40817205000448f829a6cec33e3d5 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Thu, 20 Nov 2025 01:59:48 +0000 Subject: [PATCH 21/28] Apply clang-format --style=Google --- app/tool/algorithm/level_pedestals.cxx | 120 ++++++++++++------------- 1 file changed, 55 insertions(+), 65 deletions(-) diff --git a/app/tool/algorithm/level_pedestals.cxx b/app/tool/algorithm/level_pedestals.cxx index e7fbf582..3b11e85e 100644 --- a/app/tool/algorithm/level_pedestals.cxx +++ b/app/tool/algorithm/level_pedestals.cxx @@ -21,61 +21,57 @@ */ // Helper function to pull the 3 runs -template -static void pedestal_runs( - Target* tgt, ROC& roc, - std::array& baseline, - std::array& highend, - std::array& lowend, - std::array& target, - size_t n_events) - { - DecodeAndBuffer buffer{n_events}; - - {//baseline run scope - pflib_log(info) << "100 event baseline run"; - auto test_handle = roc.testParameters() - .add_all_channels("SIGN_DAC", 0) - .add_all_channels("DACB", 0) - .add_all_channels("TRIM_INV", 0) - .apply(); - daq_run(tgt, "PEDESTAL", buffer, n_events, 100); - pflib_log(trace) << "baseline run done, getting channel medians"; - auto medians = get_adc_medians(buffer.get_buffer()); - baseline = medians; - pflib_log(trace) << "got channel medians, getting link medians"; - for (int i_link{0}; i_link < 2; i_link++) { - auto start{medians.begin() + 36 * i_link}; - auto end{start + 36}; - auto halfway{start + 18}; - std::nth_element(start, halfway, end); - target[i_link] = *halfway; - } - pflib_log(trace) << "got link medians"; +template +static void pedestal_runs(Target* tgt, ROC& roc, std::array& baseline, + std::array& highend, + std::array& lowend, + std::array& target, size_t n_events) { + DecodeAndBuffer buffer{n_events}; + + { // baseline run scope + pflib_log(info) << "100 event baseline run"; + auto test_handle = roc.testParameters() + .add_all_channels("SIGN_DAC", 0) + .add_all_channels("DACB", 0) + .add_all_channels("TRIM_INV", 0) + .apply(); + daq_run(tgt, "PEDESTAL", buffer, n_events, 100); + pflib_log(trace) << "baseline run done, getting channel medians"; + auto medians = get_adc_medians(buffer.get_buffer()); + baseline = medians; + pflib_log(trace) << "got channel medians, getting link medians"; + for (int i_link{0}; i_link < 2; i_link++) { + auto start{medians.begin() + 36 * i_link}; + auto end{start + 36}; + auto halfway{start + 18}; + std::nth_element(start, halfway, end); + target[i_link] = *halfway; } + pflib_log(trace) << "got link medians"; + } - { // highend run scope - pflib_log(info) << "100 event highend run"; - auto test_handle = roc.testParameters() - .add_all_channels("SIGN_DAC", 0) - .add_all_channels("DACB", 0) - .add_all_channels("TRIM_INV", 63) - .apply(); - daq_run(tgt, "PEDESTAL", buffer, n_events, 100); - highend = get_adc_medians(buffer.get_buffer()); - } + { // highend run scope + pflib_log(info) << "100 event highend run"; + auto test_handle = roc.testParameters() + .add_all_channels("SIGN_DAC", 0) + .add_all_channels("DACB", 0) + .add_all_channels("TRIM_INV", 63) + .apply(); + daq_run(tgt, "PEDESTAL", buffer, n_events, 100); + highend = get_adc_medians(buffer.get_buffer()); + } - { // lowend run - pflib_log(info) << "100 event lowend run"; - auto test_handle = roc.testParameters() - .add_all_channels("SIGN_DAC", 1) - .add_all_channels("DACB", 31) - .add_all_channels("TRIM_INV", 0) - .apply(); - daq_run(tgt, "PEDESTAL", buffer, n_events, 100); - lowend = get_adc_medians(buffer.get_buffer()); - } + { // lowend run + pflib_log(info) << "100 event lowend run"; + auto test_handle = roc.testParameters() + .add_all_channels("SIGN_DAC", 1) + .add_all_channels("DACB", 31) + .add_all_channels("TRIM_INV", 0) + .apply(); + daq_run(tgt, "PEDESTAL", buffer, n_events, 100); + lowend = get_adc_medians(buffer.get_buffer()); } +} template static std::array get_adc_medians( @@ -114,25 +110,19 @@ std::map> level_pedestals( // DecodeAndBuffer buffer{n_events}; if (pftool::state.daq_format_mode == Target::DaqFormat::SIMPLEROC) { - pedestal_runs( - tgt, roc, baseline, highend, lowend, target, n_events); - - } - else if (pftool::state.daq_format_mode == Target::DaqFormat::ECOND_SW_HEADERS) { + tgt, roc, baseline, highend, lowend, target, n_events); + } else if (pftool::state.daq_format_mode == + Target::DaqFormat::ECOND_SW_HEADERS) { pedestal_runs( - tgt, roc, baseline, highend, lowend, target, n_events); + tgt, roc, baseline, highend, lowend, target, n_events); + } else { + pflib_log(warn) << "Unsupported DAQ format (" + << static_cast(pftool::state.daq_format_mode) + << ") in level_pedestals. Skipping pedestal leveling..."; } - else { - pflib_log(warn) - << "Unsupported DAQ format (" - << static_cast(pftool::state.daq_format_mode) - << ") in level_pedestals. Skipping pedestal leveling..."; - } - - pflib_log(info) << "sample collections done, deducing settings"; std::map> settings; From ec1501b163de1fe82af322b9b8349c9872640547 Mon Sep 17 00:00:00 2001 From: joshgreaves332 Date: Thu, 20 Nov 2025 13:15:00 -0500 Subject: [PATCH 22/28] level_pedestals.cxx needed scope adjustment --- app/tool/algorithm/level_pedestals.cxx | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/app/tool/algorithm/level_pedestals.cxx b/app/tool/algorithm/level_pedestals.cxx index 3b11e85e..d1fa74cf 100644 --- a/app/tool/algorithm/level_pedestals.cxx +++ b/app/tool/algorithm/level_pedestals.cxx @@ -20,6 +20,9 @@ * TOT/TOA and the sample Tp/Tc flags are ignored. */ + +namespace pflib::algorithm { + // Helper function to pull the 3 runs template static void pedestal_runs(Target* tgt, ROC& roc, std::array& baseline, @@ -89,7 +92,6 @@ static std::array get_adc_medians( return medians; } -namespace pflib::algorithm { std::map> level_pedestals( Target* tgt, ROC roc) { From 70b4827a5b8500142ad5b240fb2bd2f135850698 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Thu, 20 Nov 2025 18:19:39 +0000 Subject: [PATCH 23/28] Apply clang-format --style=Google --- app/tool/algorithm/level_pedestals.cxx | 2 -- 1 file changed, 2 deletions(-) diff --git a/app/tool/algorithm/level_pedestals.cxx b/app/tool/algorithm/level_pedestals.cxx index d1fa74cf..7eb65918 100644 --- a/app/tool/algorithm/level_pedestals.cxx +++ b/app/tool/algorithm/level_pedestals.cxx @@ -20,7 +20,6 @@ * TOT/TOA and the sample Tp/Tc flags are ignored. */ - namespace pflib::algorithm { // Helper function to pull the 3 runs @@ -92,7 +91,6 @@ static std::array get_adc_medians( return medians; } - std::map> level_pedestals( Target* tgt, ROC roc) { static auto the_log_{::pflib::logging::get("level_pedestals")}; From b30e8facfde19f9ed5cf78dbb5d901ff77062fe5 Mon Sep 17 00:00:00 2001 From: joshgreaves332 Date: Thu, 20 Nov 2025 13:39:32 -0500 Subject: [PATCH 24/28] adding multi sample packet header in place of 'soft wrapped.h' for econd --- app/tool/algorithm/level_pedestals.cxx | 10 +++++----- app/tool/daq_run.h | 1 + 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/app/tool/algorithm/level_pedestals.cxx b/app/tool/algorithm/level_pedestals.cxx index 7eb65918..313414b0 100644 --- a/app/tool/algorithm/level_pedestals.cxx +++ b/app/tool/algorithm/level_pedestals.cxx @@ -23,12 +23,12 @@ namespace pflib::algorithm { // Helper function to pull the 3 runs -template +template // any use of is a placeholder for what the function gets called with. static void pedestal_runs(Target* tgt, ROC& roc, std::array& baseline, std::array& highend, std::array& lowend, std::array& target, size_t n_events) { - DecodeAndBuffer buffer{n_events}; + DecodeAndBuffer buffer{n_events}; { // baseline run scope pflib_log(info) << "100 event baseline run"; @@ -39,7 +39,7 @@ static void pedestal_runs(Target* tgt, ROC& roc, std::array& baseline, .apply(); daq_run(tgt, "PEDESTAL", buffer, n_events, 100); pflib_log(trace) << "baseline run done, getting channel medians"; - auto medians = get_adc_medians(buffer.get_buffer()); + auto medians = get_adc_medians(buffer.get_buffer()); baseline = medians; pflib_log(trace) << "got channel medians, getting link medians"; for (int i_link{0}; i_link < 2; i_link++) { @@ -60,7 +60,7 @@ static void pedestal_runs(Target* tgt, ROC& roc, std::array& baseline, .add_all_channels("TRIM_INV", 63) .apply(); daq_run(tgt, "PEDESTAL", buffer, n_events, 100); - highend = get_adc_medians(buffer.get_buffer()); + highend = get_adc_medians(buffer.get_buffer()); } { // lowend run @@ -71,7 +71,7 @@ static void pedestal_runs(Target* tgt, ROC& roc, std::array& baseline, .add_all_channels("TRIM_INV", 0) .apply(); daq_run(tgt, "PEDESTAL", buffer, n_events, 100); - lowend = get_adc_medians(buffer.get_buffer()); + lowend = get_adc_medians(buffer.get_buffer()); } } diff --git a/app/tool/daq_run.h b/app/tool/daq_run.h index 60fe2c0e..6e54e4fe 100644 --- a/app/tool/daq_run.h +++ b/app/tool/daq_run.h @@ -11,6 +11,7 @@ #include "pflib/Target.h" #include "pflib/logging/Logging.h" #include "pflib/packing/SingleROCEventPacket.h" +#include "pflib/packing/MultiSampleECONDEventPacket.h" // in place of SoftWrappedECONDEventPacket.h /** * Abstract base class for consuming event packets From 6368261a49cc60954a1c14a10589406ad1c08493 Mon Sep 17 00:00:00 2001 From: joshgreaves332 Date: Thu, 20 Nov 2025 13:43:17 -0500 Subject: [PATCH 25/28] softwrapped->multi in level_peds --- app/tool/algorithm/level_pedestals.cxx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/tool/algorithm/level_pedestals.cxx b/app/tool/algorithm/level_pedestals.cxx index 313414b0..9c447ded 100644 --- a/app/tool/algorithm/level_pedestals.cxx +++ b/app/tool/algorithm/level_pedestals.cxx @@ -115,7 +115,7 @@ std::map> level_pedestals( } else if (pftool::state.daq_format_mode == Target::DaqFormat::ECOND_SW_HEADERS) { - pedestal_runs( + pedestal_runs( tgt, roc, baseline, highend, lowend, target, n_events); } else { From 3b55e9b23d513bbe8750ea90c838c1ea824ceabc Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Thu, 20 Nov 2025 18:44:08 +0000 Subject: [PATCH 26/28] Apply clang-format --style=Google --- app/tool/algorithm/level_pedestals.cxx | 13 ++++++++----- app/tool/daq_run.h | 2 +- 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/app/tool/algorithm/level_pedestals.cxx b/app/tool/algorithm/level_pedestals.cxx index 9c447ded..b2611feb 100644 --- a/app/tool/algorithm/level_pedestals.cxx +++ b/app/tool/algorithm/level_pedestals.cxx @@ -23,11 +23,14 @@ namespace pflib::algorithm { // Helper function to pull the 3 runs -template // any use of is a placeholder for what the function gets called with. -static void pedestal_runs(Target* tgt, ROC& roc, std::array& baseline, - std::array& highend, - std::array& lowend, - std::array& target, size_t n_events) { +template // any use of is a placeholder for + // what the function gets called with. + static void pedestal_runs( + Target* tgt, ROC& roc, + std::array& baseline, + std::array& highend, + std::array& lowend, + std::array& target, size_t n_events) { DecodeAndBuffer buffer{n_events}; { // baseline run scope diff --git a/app/tool/daq_run.h b/app/tool/daq_run.h index 6e54e4fe..71915a62 100644 --- a/app/tool/daq_run.h +++ b/app/tool/daq_run.h @@ -10,8 +10,8 @@ #include "pflib/Target.h" #include "pflib/logging/Logging.h" -#include "pflib/packing/SingleROCEventPacket.h" #include "pflib/packing/MultiSampleECONDEventPacket.h" // in place of SoftWrappedECONDEventPacket.h +#include "pflib/packing/SingleROCEventPacket.h" /** * Abstract base class for consuming event packets From 987cd15c0792882ded43adc35e3fa7b488b2015c Mon Sep 17 00:00:00 2001 From: joshgreaves332 Date: Thu, 20 Nov 2025 15:23:43 -0500 Subject: [PATCH 27/28] added another declaration of the_log_ in pedestal_runs function --- app/tool/algorithm/level_pedestals.cxx | 1 + 1 file changed, 1 insertion(+) diff --git a/app/tool/algorithm/level_pedestals.cxx b/app/tool/algorithm/level_pedestals.cxx index b2611feb..25a8a8c7 100644 --- a/app/tool/algorithm/level_pedestals.cxx +++ b/app/tool/algorithm/level_pedestals.cxx @@ -32,6 +32,7 @@ template // any use of is a placeholder for std::array& lowend, std::array& target, size_t n_events) { DecodeAndBuffer buffer{n_events}; + static auto the_log_{::pflib::logging::get("level_pedestals")}; { // baseline run scope pflib_log(info) << "100 event baseline run"; From 7b397e7e00381feb79bacf195af827f81b68dbc1 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Thu, 20 Nov 2025 20:25:31 +0000 Subject: [PATCH 28/28] Apply clang-format --style=Google --- app/tool/algorithm/level_pedestals.cxx | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/app/tool/algorithm/level_pedestals.cxx b/app/tool/algorithm/level_pedestals.cxx index 25a8a8c7..6f311095 100644 --- a/app/tool/algorithm/level_pedestals.cxx +++ b/app/tool/algorithm/level_pedestals.cxx @@ -25,12 +25,10 @@ namespace pflib::algorithm { // Helper function to pull the 3 runs template // any use of is a placeholder for // what the function gets called with. - static void pedestal_runs( - Target* tgt, ROC& roc, - std::array& baseline, - std::array& highend, - std::array& lowend, - std::array& target, size_t n_events) { +static void pedestal_runs(Target* tgt, ROC& roc, std::array& baseline, + std::array& highend, + std::array& lowend, + std::array& target, size_t n_events) { DecodeAndBuffer buffer{n_events}; static auto the_log_{::pflib::logging::get("level_pedestals")};