From 370aada49055b74d24a741d237da54f72a7a7d38 Mon Sep 17 00:00:00 2001 From: Alice Date: Wed, 4 Mar 2026 21:38:48 +0100 Subject: [PATCH] generated register defs from csv file --- etc/generate_registerdefs.py | 98 ++++++++++ .../matterhonServer/include/RegisterDefs.hpp | 184 ++++++++++++++++++ .../include/RegisterHelperStructs.hpp | 25 +++ 3 files changed, 307 insertions(+) create mode 100644 etc/generate_registerdefs.py create mode 100644 slsDetectorServers/matterhonServer/include/RegisterDefs.hpp create mode 100644 slsDetectorServers/matterhonServer/include/RegisterHelperStructs.hpp diff --git a/etc/generate_registerdefs.py b/etc/generate_registerdefs.py new file mode 100644 index 000000000..2649f7609 --- /dev/null +++ b/etc/generate_registerdefs.py @@ -0,0 +1,98 @@ +import pandas as pd +import argparse + +def Ip_core_name_to_enum_type(ip_core_name : str) -> str: + """Convert IP core name to enum type IPCore.""" + if pd.isna(ip_core_name): + return "IPCore::UNKNOWN" + else: + return f"IPCore::{ip_core_name.upper()}" + +def create_bitmask_and_offset(from_bit : int, to_bit : int) -> tuple[int, int]: + """Create a bitmask for a register field given the from_bit and to_bit.""" + if from_bit < 0 or to_bit < 0 or from_bit > to_bit: + raise ValueError(f"Invalid bit range: from_bit={from_bit}, to_bit={to_bit}") + + offset = from_bit + num_bits = to_bit - from_bit + 1 + adress_space = 0xFFFFFFFF # Assuming a 32-bit address space for the bitmask + mask = (adress_space >> (32 - num_bits)) + return mask, offset # to get value of field: (register_value >> offset) & mask, to set value of field: register_value = (register_value & ~(mask << offset)) | ((field_value & mask) << offset) + +def argument_parser(): + parser = argparse.ArgumentParser(description="Generate register definitions from a CSV file.") + parser.add_argument("--csv_file", required=True, help="Path to the CSV file containing register definitions.") + parser.add_argument("--output_header_file", required=True, help="Path to the output header file to write the register definitions to.") + parser.add_argument( + "--overwrite", + action="store_true", + help="Overwrite the output file instead of appending.", + ) + return parser.parse_args() + +# TODO: should be configurable +header = r""" +#include "RegisterHelperStructs.hpp" + +/// @brief Enum for IP cores, value are adresses +constexpr enum class IPCore : uint32_t { + MH_RO_SM_AXI = 0, // dummy adresses for now + FHDR_AXI = 1, + AURORA_STATUS = 2, + AURORA_STATUS2 = 3, + PACKETIZERREG = 4, + UNKNOWN = 5 +}; +""" + +def main(): + + args = argument_parser() + + registers_list = pd.read_csv(args.csv_file) + + registers = registers_list.drop_duplicates(subset=["Reg_name", "Address"]) + + file_mode = "w" if args.overwrite else "a" + header_file = open(args.output_header_file, file_mode) + + if args.overwrite: + header_file.write(header) + header_file.write("\n\n") + + header_file.write("// Register definitions") + header_file.write("\n") + + for index, row in registers.iterrows(): + local_address_offset_in_bytes = row["Address"] + register_name = row["Reg_name"] + ip_core_name = row["Interface"] + + define_register_string = f'constexpr Register {register_name}{{{Ip_core_name_to_enum_type(ip_core_name)}, {local_address_offset_in_bytes}}};' + + header_file.write(f"{define_register_string}\n") + header_file.write("\n") + + header_file.write("\n") + header_file.write("\n") + + header_file.write("// Register fields") + header_file.write("\n") + + for index, row in registers_list.iterrows(): + register_name = row["Reg_name"] + field_name = row["Name"] + from_bit = row["From_bit"] + to_bit = row["To_bit"] + mask, offset = create_bitmask_and_offset(from_bit, to_bit) + + define_registerfield_string = f"constexpr RegisterField {field_name}{{{register_name}, {hex(mask)}, {offset}}};" + + header_file.write(f"{define_registerfield_string}\n") + header_file.write("\n") + + header_file.close() + + +if __name__ == "__main__": + main() diff --git a/slsDetectorServers/matterhonServer/include/RegisterDefs.hpp b/slsDetectorServers/matterhonServer/include/RegisterDefs.hpp new file mode 100644 index 000000000..6a8e38ee9 --- /dev/null +++ b/slsDetectorServers/matterhonServer/include/RegisterDefs.hpp @@ -0,0 +1,184 @@ + +#include "RegisterHelperStructs.hpp" + +/// @brief Enum for IP cores, value are adresses +constexpr enum class IPCore : uint32_t { + MH_RO_SM_AXI = 0, // dummy adresses for now + FHDR_AXI = 1, + AURORA_STATUS = 2, + AURORA_STATUS2 = 3, + PACKETIZERREG = 4, + UNKNOWN = 5 +}; + + +// Register definitions +constexpr Register CTRL_Reg{IPCore::UNKNOWN, 0}; + +constexpr Register Status_Reg{IPCore::UNKNOWN, 4}; + +constexpr Register FPGAVersionReg{IPCore::UNKNOWN, 8}; + +constexpr Register FPGA_GIT_HEAD{IPCore::UNKNOWN, C}; + +constexpr Register FixedPatternReg{IPCore::UNKNOWN, 10}; + +constexpr Register ApiVersionReg{IPCore::UNKNOWN, 14}; + +constexpr Register Chip_ID_Reg{IPCore::UNKNOWN, 18}; + +constexpr Register MH_SM_Ctrl_Reg{IPCore::MH_RO_SM_AXI, 0}; + +constexpr Register MH_SM_Exposure_Reg{IPCore::MH_RO_SM_AXI, 4}; + +constexpr Register MH_SM_Period_Reg{IPCore::MH_RO_SM_AXI, 8}; + +constexpr Register MH_SM_Frames_Reg{IPCore::MH_RO_SM_AXI, C}; + +constexpr Register MH_SM_StoreLength_Reg{IPCore::MH_RO_SM_AXI, 10}; + +constexpr Register MH_SM_ResetMHLength_Reg{IPCore::MH_RO_SM_AXI, 14}; + +constexpr Register Frame_HDR_Set_Reg{IPCore::FHDR_AXI, 0}; + +constexpr Register Frame_HDR_FrameNumLSB_Reg{IPCore::FHDR_AXI, 4}; + +constexpr Register Frame_HDR_FrameNumMSB_Reg{IPCore::FHDR_AXI, 8}; + +constexpr Register Frame_HDR_TimestampLSB_Reg{IPCore::FHDR_AXI, C}; + +constexpr Register Frame_HDR_TimestampMSB_Reg{IPCore::FHDR_AXI, 10}; + +constexpr Register Frame_HDR_ModCoord_LSB_Reg{IPCore::FHDR_AXI, 14}; + +constexpr Register Frame_HDR_ModCoord_MSB_Reg{IPCore::FHDR_AXI, 18}; + +constexpr Register Frame_HDR_PktctrMax_Reg{IPCore::FHDR_AXI, 1C}; + +constexpr Register Aurora_Valid_DW_Reg{IPCore::AURORA_STATUS, 0}; + +constexpr Register Aurora_Valid_Bytes_Reg{IPCore::AURORA_STATUS, 4}; + +constexpr Register Aurora_Busy_Up_Cycles_Reg{IPCore::AURORA_STATUS, 8}; + +constexpr Register Aurora_Hard_Errors_Reg{IPCore::AURORA_STATUS, C}; + +constexpr Register Aurora_Soft_Errors_Reg{IPCore::AURORA_STATUS, 10}; + +constexpr Register Aurora_Channel_n_Lanes_Up_Reg{IPCore::AURORA_STATUS, 14}; + +constexpr Register Aurora_GT_PLL_Lock_Reg{IPCore::AURORA_STATUS2, 0}; + +constexpr Register PktPacketLengthReg{IPCore::PACKETIZERREG, A100}; + +constexpr Register PktNoPacketsReg{IPCore::PACKETIZERREG, A104}; + +constexpr Register PktCtrlReg{IPCore::PACKETIZERREG, A108}; + +constexpr Register PktCoordReg1{IPCore::PACKETIZERREG, A10C}; + +constexpr Register PktCoordReg2{IPCore::PACKETIZERREG, A110}; + + + +// Register fields +constexpr RegisterField Power_VIO{CTRL_Reg, 0x1, 0}; + +constexpr RegisterField Power_Vcc_A{CTRL_Reg, 0x1, 1}; + +constexpr RegisterField Power_Vcc_B{CTRL_Reg, 0x1, 2}; + +constexpr RegisterField Power_Vcc_C{CTRL_Reg, 0x1, 3}; + +constexpr RegisterField Power_Vcc_D{CTRL_Reg, 0x1, 4}; + +constexpr RegisterField MH_Enable_Enable{CTRL_Reg, 0x1, 5}; + +constexpr RegisterField MH_Clk_Enable{CTRL_Reg, 0x1, 6}; + +constexpr RegisterField sm_busy{Status_Reg, 0x1, 0}; + +constexpr RegisterField FPGACompDate{FPGAVersionReg, 0xffffff, 0}; + +constexpr RegisterField FPGADetType{FPGAVersionReg, 0xff, 24}; + +constexpr RegisterField FPGA_GIT_HEAD{FPGA_GIT_HEAD, 0xffffffff, 0}; + +constexpr RegisterField FixedPattern{FixedPatternReg, 0xffffffff, 0}; + +constexpr RegisterField ApiCompDate{ApiVersionReg, 0xffffff, 0}; + +constexpr RegisterField ApiDetType{ApiVersionReg, 0xff, 24}; + +constexpr RegisterField ChipID{Chip_ID_Reg, 0x7, 0}; + +constexpr RegisterField Start_Acquistion{MH_SM_Ctrl_Reg, 0x1, 0}; + +constexpr RegisterField Stop_Acquistion{MH_SM_Ctrl_Reg, 0x1, 1}; + +constexpr RegisterField MH_Readout_Exposure_Time{MH_SM_Exposure_Reg, 0xffffffff, 0}; + +constexpr RegisterField MH_Readout_Period_Time{MH_SM_Period_Reg, 0xffffffff, 0}; + +constexpr RegisterField MH_Readout_Frames{MH_SM_Frames_Reg, 0xffffffff, 0}; + +constexpr RegisterField MH_SM_StoreLength{MH_SM_StoreLength_Reg, 0xffffffff, 0}; + +constexpr RegisterField MH_SM_ResetMHLength{MH_SM_ResetMHLength_Reg, 0xffffffff, 0}; + +constexpr RegisterField Frame_Hdr_Set_Framenumber{Frame_HDR_Set_Reg, 0x1, 0}; + +constexpr RegisterField Frame_Hdr_Set_Timestamp{Frame_HDR_Set_Reg, 0x1, 1}; + +constexpr RegisterField Frame_Hdr_Framenumber_LSB{Frame_HDR_FrameNumLSB_Reg, 0xffffffff, 0}; + +constexpr RegisterField Frame_Hdr_Framenumber_MSB{Frame_HDR_FrameNumMSB_Reg, 0xffffffff, 0}; + +constexpr RegisterField Frame_Hdr_Timestamp_LSB{Frame_HDR_TimestampLSB_Reg, 0xffffffff, 0}; + +constexpr RegisterField Frame_Hdr_Timestamp_MSB{Frame_HDR_TimestampMSB_Reg, 0xffffffff, 0}; + +constexpr RegisterField Frame_HDR_ModCoord_LSB{Frame_HDR_ModCoord_LSB_Reg, 0xffffffff, 0}; + +constexpr RegisterField Frame_HDR_ModCoord_MSB{Frame_HDR_ModCoord_MSB_Reg, 0xffffffff, 0}; + +constexpr RegisterField Frame_HDR_PktctrMax{Frame_HDR_PktctrMax_Reg, 0xff, 0}; + +constexpr RegisterField Aurora_Number_Valid_DW{Aurora_Valid_DW_Reg, 0xffffffff, 0}; + +constexpr RegisterField Aurora_Valid_Bytes{Aurora_Valid_Bytes_Reg, 0xffffffff, 0}; + +constexpr RegisterField Aurora_Busy_Up_Cycles{Aurora_Busy_Up_Cycles_Reg, 0xffffffff, 0}; + +constexpr RegisterField Aurora_Hard_Errors{Aurora_Hard_Errors_Reg, 0xffffffff, 0}; + +constexpr RegisterField Aurora_Soft_Errors{Aurora_Soft_Errors_Reg, 0xffffffff, 0}; + +constexpr RegisterField Aurora_Lanes_Up{Aurora_Channel_n_Lanes_Up_Reg, 0xf, 0}; + +constexpr RegisterField Aurora_Channel_Up{Aurora_Channel_n_Lanes_Up_Reg, 0x1, 4}; + +constexpr RegisterField Aurora_GT_PLL_Lock{Aurora_GT_PLL_Lock_Reg, 0x1, 0}; + +constexpr RegisterField Aurora_GT_PLL_Lock_Counter{Aurora_GT_PLL_Lock_Reg, 0x1ffffff, 4}; + +constexpr RegisterField PacketLength1G{PktPacketLengthReg, 0xffff, 0}; + +constexpr RegisterField PacketLength10G{PktPacketLengthReg, 0xffff, 16}; + +constexpr RegisterField NoPackets1G{PktNoPacketsReg, 0x3f, 0}; + +constexpr RegisterField NoPackets10G{PktNoPacketsReg, 0x3f, 16}; + +constexpr RegisterField NoServers{PktCtrlReg, 0x3f, 0}; + +constexpr RegisterField ServerStart{PktCtrlReg, 0x1f, 8}; + +constexpr RegisterField EthInterf{PktCtrlReg, 0x1, 16}; + +constexpr RegisterField Coordx{PktCoordReg1, 0xffff, 0}; + +constexpr RegisterField Coordy{PktCoordReg1, 0xffff, 16}; + +constexpr RegisterField Coordz{PktCoordReg2, 0xffff, 0}; + diff --git a/slsDetectorServers/matterhonServer/include/RegisterHelperStructs.hpp b/slsDetectorServers/matterhonServer/include/RegisterHelperStructs.hpp new file mode 100644 index 000000000..224095b69 --- /dev/null +++ b/slsDetectorServers/matterhonServer/include/RegisterHelperStructs.hpp @@ -0,0 +1,25 @@ +#include +#include + +enum class IPCore : uint32_t; // forward declaration of IPCore enum class + +struct Register { + /// @brief IP core address space + const IPCore ip_core{}; // TODO replace by enum type + + /// @brief Offset of the register in bytes from the base address of the IP + /// core + const uint32_t offset_in_bytes{}; +}; + +struct RegisterField { + /// @brief Register to which the field belongs + const Register register_{}; + + /// @brief Bitmask for the field + const uint32_t bitmask{}; + + /// @brief Bit position of the least significant bit of the field in the + /// register + const uint32_t bit_position{}; +}; \ No newline at end of file