Files
Jungfraujoch/tools/jfjoch_pcie_status.cpp
2025-04-14 11:52:06 +02:00

169 lines
11 KiB
C++

// SPDX-FileCopyrightText: 2024 Filip Leonarski, Paul Scherrer Institute <filip.leonarski@psi.ch>
// SPDX-License-Identifier: GPL-3.0-only
#include <iostream>
#include <bitset>
#include "../common/NetworkAddressConvert.h"
#include "../fpga/host_library/JungfraujochDevice.h"
#include <map>
std::string FIFO_check(uint64_t fifo_register,
uint16_t pos_empty,
uint16_t pos_full) {
if (std::bitset<64>(fifo_register).test(pos_empty))
return "empty";
else if (std::bitset<64>(fifo_register).test(pos_full))
return "full";
else
return "partial";
}
void FIFO_check(uint64_t fifo_register) {
std::map<std::string, std::string> fifo_map;
fifo_map["Frame generator"] = FIFO_check(fifo_register, 24, 25);
fifo_map["UDP"] = FIFO_check(fifo_register, 6, 7);
fifo_map["Pre-HBM input (data)"] = FIFO_check(fifo_register, 0, 1);
fifo_map["Pre-HBM input (cmd)"] = FIFO_check(fifo_register, 2, 3);
fifo_map["Post-HBM input (data)"] = FIFO_check(fifo_register, 34, 35);
fifo_map["Post-HBM input (cmd)"] = FIFO_check(fifo_register, 36, 37);
fifo_map["Processing FIFO (integration -> spot finding)"] = FIFO_check(fifo_register, 4, 5);
fifo_map["Writer input (data)"] = FIFO_check(fifo_register, 16, 17);
fifo_map["Writer input (cmd)"] = FIFO_check(fifo_register, 18, 19);
fifo_map["C2H (data)"] = FIFO_check(fifo_register, 8, 9);
fifo_map["C2H (cmd)"] = FIFO_check(fifo_register, 10, 11);
fifo_map["H2C (data)"] = FIFO_check(fifo_register, 20, 21);
fifo_map["H2C (cmd)"] = FIFO_check(fifo_register, 22, 23);
fifo_map["HBM completion"] = FIFO_check(fifo_register, 28, 29);
fifo_map["HBM handles #0"] = FIFO_check(fifo_register, 30, 31);
fifo_map["HBM handles #1"] = FIFO_check(fifo_register, 32, 33);
std::cout << "FIFO status" << std::endl;
for (const auto &[x,y]: fifo_map)
std::cout << " " << x << ": " << y << std::endl;
}
int main(int argc, char **argv) {
if (argc != 2) {
std::cout << "Usage: ./jfjoch_pcie_status <device name>" << std::endl;
exit(EXIT_FAILURE);
}
std::cout << "Device " << argv[1] << std::endl;
std::cout << std::endl;
try {
JungfraujochDevice device(argv[1], false);
auto fpga_status = device.GetDataCollectionStatus();
auto fpga_env_data = device.GetDeviceStatus();
auto spot_finder_settings = device.GetSpotFinderParameters();
auto config = device.GetConfig();
std::cout << "PCIe/JFJoch card detected " << std::endl;
std::cout << "PCIe ID " << fpga_env_data.device_number << std::endl;
std::cout << "Version " << fpga_env_data.fpga_firmware_version << std::endl;
std::cout << std::endl;
std::cout << "Git SHA1 " << std::hex << fpga_status.git_sha1 << std::endl;
std::cout << "Max modules " << std::dec << fpga_status.max_modules << std::endl;
std::cout << "NUMA node " << device.GetNumaNode() << std::endl;
if (fpga_status.jfjoch_fpga_variant == JFJOCH_FPGA_VARIANT_100G)
std::cout << "FPGA variant " << "100G" << std::endl;
else
std::cout << "FPGA variant " << "8x10G" << std::endl;
std::cout << "Ethernet status (*=link) ";
for (int i = 0; i < fpga_env_data.eth_link_count; i++)
std::cout << (((fpga_env_data.eth_link_status & (1U<<i)) != 0) ? "*" : "-");
std::cout << std::endl;
std::cout << "FPGA serial number " << fpga_env_data.serial_number << std::endl;
std::cout << "FPGA 12V rail current [A] " << fpga_env_data.fpga_pcie_12V_I_mA / 1000.0 << std::endl;
std::cout << "FPGA 12V rail voltage [V] " << fpga_env_data.fpga_pcie_12V_V_mV / 1000.0 << std::endl;
std::cout << "FPGA 3.3V rail current [A] " << fpga_env_data.fpga_pcie_3p3V_I_mA / 1000.0 << std::endl;
std::cout << "FPGA 3.3V rail voltage [V] " << fpga_env_data.fpga_pcie_3p3V_V_mV / 1000.0 << std::endl;
std::cout << "FPGA temperature " << fpga_env_data.fpga_temp_C << std::endl;
std::cout << "HBM temperature #0 " << fpga_env_data.hbm_0_temp_C << std::endl;
std::cout << "HBM temperature #1 " << fpga_env_data.hbm_1_temp_C << std::endl;
std::cout << "QSFP cage 0 temperature " << fpga_env_data.qsfp_cage_0_temp_C << std::endl;
std::cout << "QSFP cage 1 temperature " << fpga_env_data.qsfp_cage_1_temp_C << std::endl;
std::cout << "PCIe link " << "Gen" << (uint32_t) fpga_env_data.pcie_link_speed
<< "x" << (uint32_t) fpga_env_data.pcie_link_width << std::endl;
std::cout << "HBM size (MiB) " << fpga_status.hbm_size_bytes / static_cast<double>(1024 * 1024) << std::endl;
std::cout << "Data acquisition run count " << fpga_status.run_counter << std::endl;
std::cout << "Data collection idle " << device.IsIdle() << std::endl;
std::cout << "Host writer idle " << ((fpga_status.ctrl_reg & (1<<4)) ? 1 : 0) << std::endl;
std::cout << "Data collection cancel " << ((fpga_status.ctrl_reg & (1<<2)) ? 1 : 0) << std::endl;
std::cout << "Mailbox status " << std::hex << fpga_env_data.mailbox_status_reg << std::dec << std::endl;
std::cout << "Mailbox error " << std::hex << fpga_env_data.mailbox_err_reg << std::dec << std::endl;
std::cout << "Mailbox interrupt status " << std::hex << fpga_env_data.mailbox_interrupt_status << std::dec << std::endl;
std::cout << "Mailbox interrupt 0 " << ((fpga_status.ctrl_reg & (1<<16)) ? 1 : 0) << std::endl;
std::cout << "Mailbox interrupt 1 " << ((fpga_status.ctrl_reg & (1<<17)) ? 1 : 0) << std::endl;
std::cout << "Full status register " << std::bitset<32>(fpga_status.ctrl_reg) << std::endl;
std::cout << "Work completion FIFO avail " << fpga_env_data.work_compl_fifo_avail << std::endl;
std::cout << "Active handles " << fpga_env_data.active_handles << std::endl;
std::cout << "AXI-STREAM beats encountered " << std::endl;
std::cout << " - before HBM cache " << fpga_status.pipeline_beats_hbm << std::endl;
std::cout << " - before host mem " << fpga_status.pipeline_beats_host << std::endl;
std::cout << "Pipeline stalls" << std::endl;
std::cout << " - before HBM cache " << fpga_status.pipeline_stalls_hbm << std::endl;
std::cout << " - before host mem " << fpga_status.pipeline_stalls_host << std::endl;
std::cout << "HBM ignored frames " << fpga_status.hbm_ignored << std::endl;
std::cout << "Input FIFO count (curr) " << fpga_status.in_fifo_count << std::endl;
std::cout << "Input FIFO count (max) " << fpga_status.in_fifo_count_max << std::endl;
std::cout << "Output FIFO count (curr) " << fpga_status.out_fifo_count << std::endl;
std::cout << "Output FIFO count (max) " << fpga_status.out_fifo_count_max << std::endl;
std::cout << "ROI count " << fpga_status.fpga_roi_count << std::endl;
DataCollectionConfig cfg = device.GetConfig();
std::cout << "MAC address " << MacAddressToStr(device.GetMACAddress()) << std::endl;
std::cout << "IPv4 address " << IPv4AddressToStr(device.GetIPv4Address()) << std::endl;
std::cout << "Data collection mode (hex) " << std::hex << (cfg.mode & 0xFFFF) << std::dec << std::endl;
std::cout << "Data collection ID (hex) " << std::hex << ((cfg.mode & 0xFFFF0000) >> 16) << std::dec << std::endl;
std::cout << "Modules " << std::dec << cfg.nmodules << std::endl;
std::cout << "Frames int. pkt. gen. " << std::dec << cfg.nframes << std::endl;
std::cout << "Pulse ID " << fpga_status.current_pulseid << std::endl;
std::cout << std::endl;
std::cout << "Mode config reg. " << std::bitset<32>(config.mode) << std::endl;
std::cout << "Summation " << config.nsummation + 1 << std::endl;
std::cout << "Energy keV " << config.energy_kev << std::endl;
std::cout << std::endl;
std::cout << "Spot finder settings " << std::endl;
std::cout << "Count threshold " << spot_finder_settings.count_threshold << std::endl;
std::cout << "SNR threshold " << spot_finder_settings.snr_threshold / 4.0f << std::endl;
std::cout << std::endl;
FIFO_check(fpga_status.fifo_status);
std::cout << "FIFO ever full " << std::bitset<32>(fpga_status.fifo_ever_full) << std::endl;
std::cout << std::endl;
std::cout << "Packet counters - UDP " << fpga_status.packets_udp << std::endl;
std::cout << " - SLS " << fpga_status.packets_sls << std::endl;
std::cout << " - JFJoch " << fpga_status.packets_processed << std::endl;
std::cout << std::endl;
std::cout << " - err. ETH " << fpga_status.udp_err_eth << std::endl;
std::cout << " - err. len. " << fpga_status.udp_err_len << std::endl;
std::cout << std::endl;
std::cout << "User interrupts mask: " << std::bitset<32>(fpga_env_data.pcie_user_interrupt_mask)
<< " pending: " << std::bitset<32>(fpga_env_data.pcie_user_interrupt_pending)
<< " request: " << std::bitset<32>(fpga_env_data.pcie_user_interrupt_request) << std::endl;
std::cout << "DMA interrupts mask: " << std::bitset<32>(fpga_env_data.pcie_dma_interrupt_mask)
<< " pending: " << std::bitset<32>(fpga_env_data.pcie_dma_interrupt_pending)
<< " request: " << std::bitset<32>(fpga_env_data.pcie_dma_interrupt_request) << std::endl;
std::cout << "H2C descriptors:" << fpga_env_data.pcie_h2c_descriptors << " beats: " << fpga_env_data.pcie_h2c_beats
<< " status:" << fpga_env_data.pcie_h2c_status << std::endl;
std::cout << "C2H descriptors:" << fpga_env_data.pcie_c2h_descriptors << " beats: " << fpga_env_data.pcie_c2h_beats
<< " status:" << fpga_env_data.pcie_c2h_status << std::endl;
std::cout << std::endl;
} catch (const std::runtime_error &e) {
std::cout << e.what() << std::endl;
std::cout << std::endl;
}
}