ctb: add patternstart command, xilinx: fix frequency (#1307)
Some checks failed
Build on RHEL9 / build (push) Failing after 3m9s
Build on RHEL8 / build (push) Failing after 5m11s

* add patternstart command for CTB, block end of execution udp packets if pattern was started by patternstart command

* update docs

* Dhanya's comments

* more Dhanya comments

* refactored

* fixed tests for startpatttern, also clkfrequency not properly used in server

* xilinx: fixed setfrequency, tick clock (with sync clock), clkfrequency set from getfrequency to get the exact value

* xilinx freq in kHz, updated default values and prints

---------

Co-authored-by: Martin Mueller <martin.mueller@psi.ch>
Co-authored-by: Dhanya Thattil <dhanya.thattil@psi.ch>
This commit is contained in:
Martin Mueller
2025-09-23 12:13:46 +02:00
committed by GitHub
parent e7a91d38f2
commit 2d8f93a426
17 changed files with 124 additions and 59 deletions

View File

@@ -384,6 +384,13 @@
#define PLL_CNTRL_ADDR_OFST (16)
#define PLL_CNTRL_ADDR_MSK (0x0000003F << PLL_CNTRL_ADDR_OFST)
/* Streaming Control RW regiser */
#define STREAMING_CTRL_REG (0x3D << MEM_MAP_SHIFT)
#define STREAMING_CTRL_ENA_OFST (15)
#define STREAMING_CTRL_ENA_MSK (0x00000001 << STREAMING_CTRL_ENA_OFST)
#define STREAMING_CTRL_SELECT_OFST (0)
#define STREAMING_CTRL_SELECT_MSK (0x0000003F << STREAMING_CTRL_SELECT_OFST)
/* Pattern Control RW register */
#define PATTERN_CNTRL_REG (0x88 << MEM_MAP_SHIFT)

View File

@@ -4,7 +4,7 @@
#include <stdbool.h>
#include <stdint.h>
void XILINX_PLL_setFrequency(uint32_t clk_index, uint32_t freq);
int XILINX_PLL_setFrequency(uint32_t clk_index, uint32_t freq);
uint32_t XILINX_PLL_getFrequency(uint32_t clkIDX);
bool XILINX_PLL_isLocked();
void XILINX_PLL_reset();

View File

@@ -58,7 +58,8 @@ uint64_t getPatternMask();
void setPatternBitMask(uint64_t mask);
uint64_t getPatternBitMask();
#if defined(MYTHEN3D) || defined(XILINX_CHIPTESTBOARDD)
#if defined(MYTHEN3D) || defined(XILINX_CHIPTESTBOARDD) || \
defined(CHIPTESTBOARDD)
void startPattern();
#endif
char *getPatternFileName();

View File

@@ -72,14 +72,14 @@
// clang-format on
// freq in kHz !!
void XILINX_PLL_setFrequency(uint32_t clk_index, uint32_t freq) {
int XILINX_PLL_setFrequency(uint32_t clk_index, uint32_t freq) {
if (clk_index >= XILINX_PLL_NUM_CLKS) {
LOG(logERROR, ("XILINX_PLL: Invalid clock index %d\n", clk_index));
return;
return 1;
}
if (freq < XILINX_PLL_MIN_FREQ || freq > XILINX_PLL_MAX_FREQ) {
LOG(logERROR, ("XILINX_PLL: Frequency %d kHz is out of range\n", freq));
return;
return 1;
}
// calculate base clock frequency
@@ -103,7 +103,7 @@ void XILINX_PLL_setFrequency(uint32_t clk_index, uint32_t freq) {
if (clk_div < 1 || clk_div > XILINX_PLL_MAX_CLK_DIV) {
LOG(logERROR,
("XILINX_PLL: Invalid clock divider, need to change base clock\n"));
return;
return 1;
}
uint32_t clk_div_frac = 0;
@@ -140,18 +140,19 @@ void XILINX_PLL_setFrequency(uint32_t clk_index, uint32_t freq) {
// wait for firmware to measure the actual frequency
usleep(2 * 1000 * 1000);
return 0;
}
uint32_t XILINX_PLL_getFrequency(uint32_t clk_index) {
if (clk_index >= XILINX_PLL_NUM_CLKS) {
LOG(logERROR, ("XILINX_PLL: Invalid clock index %d\n", clk_index));
return 0;
return -1;
}
if (clk_index > XILINX_PLL_MAX_NUM_CLKS_FOR_GET) {
LOG(logERROR,
("XILINX_PLL: get frequency not implemented for this clock %d\n",
clk_index));
return 0;
return -1;
}
uint32_t base_addr = XILINX_PLL_MEASURE_BASE_ADDR0;

View File

@@ -623,28 +623,43 @@ uint64_t getPatternBitMask() {
return getU64BitReg(PATTERN_SET_LSB_REG, PATTERN_SET_MSB_REG);
}
#ifdef MYTHEN3D
void startPattern() {
LOG(logINFOBLUE, ("Starting Pattern\n"));
#ifdef MYTHEN3D
bus_w(CONTROL_REG, bus_r(CONTROL_REG) | CONTROL_STRT_PATTERN_MSK);
usleep(1);
while (bus_r(PAT_STATUS_REG) & PAT_STATUS_RUN_BUSY_MSK) {
usleep(1);
}
LOG(logINFOBLUE, ("Pattern done\n"));
}
#endif
#ifdef XILINX_CHIPTESTBOARDD
void startPattern() {
LOG(logINFOBLUE, ("Starting Pattern\n"));
#elif CHIPTESTBOARDD
// we only want to run the pattern here. No acquisition, no UDP packets
// disable 10G UDP temporarily
// except if the pattern explicitly contains udp trigger points
uint32_t conf_reg_tmp = bus_r(CONFIG_REG);
if ((bus_r(STREAMING_CTRL_REG) & STREAMING_CTRL_ENA_MSK) == 0) {
bus_w(CONFIG_REG, conf_reg_tmp & ~CONFIG_GB10_SND_UDP_MSK);
}
// run the pattern, wait till done
bus_w(CONTROL_REG, bus_r(CONTROL_REG) | CONTROL_STRT_ACQSTN_MSK);
bus_w(CONTROL_REG, bus_r(CONTROL_REG) & ~CONTROL_STRT_ACQSTN_MSK);
usleep(1);
while (bus_r(STATUS_REG) & STATUS_RN_BSY_MSK) {
usleep(1);
}
// go back to original config
bus_w(CONFIG_REG, conf_reg_tmp);
#elif XILINX_CHIPTESTBOARDD
bus_w(FLOW_CONTROL_REG, bus_r(FLOW_CONTROL_REG) | START_F_MSK);
usleep(1);
while (bus_r(FLOW_CONTROL_REG) & RSM_BUSY_MSK) {
usleep(1);
}
#endif
LOG(logINFOBLUE, ("Pattern done\n"));
}
#endif
char *getPatternFileName() { return clientPatternfile; }

View File

@@ -5839,15 +5839,24 @@ int set_clock_frequency(int file_des) {
LOG(logINFO, ("Same %s: %d %s\n", modeName, val,
myDetectorType == GOTTHARD2 ? "Hz" : "MHz"));
} else {
setFrequency(c, val);
int retval = getFrequency(c);
LOG(logDEBUG1, ("retval %s: %d %s\n", modeName, retval,
myDetectorType == GOTTHARD2 ? "Hz" : "MHz"));
#if !defined( \
XILINX_CHIPTESTBOARDD) // XCTB will give the actual frequency, which is not
// 100% identical to the set frequency
validate(&ret, mess, val, retval, modeName, DEC);
int ret = setFrequency(c, val);
if (ret == FAIL) {
sprintf(mess, "Could not set %s to %d %s\n", modeName, val,
myDetectorType == XILINX_CHIPTESTBOARD ? "kHz"
: "MHz");
LOG(logERROR, (mess));
} else {
int retval = getFrequency(c);
LOG(logDEBUG1,
("retval %s: %d %s\n", modeName, retval,
myDetectorType == XILINX_CHIPTESTBOARD ? "kHz"
: "MHz"));
#if !defined(XILINX_CHIPTESTBOARDD)
// XCTB will give the actual frequency, which is not
// 100% identical to the set frequency
validate(&ret, mess, val, retval, modeName, DEC);
#endif
}
}
}
}
@@ -5902,8 +5911,11 @@ int get_clock_frequency(int file_des) {
LOG(logDEBUG1,
("retval %s clock (%d) frequency: %d %s\n", clock_names[c], (int)c,
retval,
myDetectorType == GOTTHARD2 || myDetectorType == MYTHEN3 ? "Hz"
: "MHz"));
myDetectorType == XILINX_CHIPTESTBOARD
? "kHz"
: (myDetectorType == GOTTHARD2 || myDetectorType == MYTHEN3
? "Hz"
: "MHz")));
}
#endif
return Server_SendResult(file_des, INT32, &retval, sizeof(retval));
@@ -7468,7 +7480,8 @@ int start_pattern(int file_des) {
memset(mess, 0, sizeof(mess));
LOG(logDEBUG1, ("Starting Pattern\n"));
#if !defined(MYTHEN3D) && !defined(XILINX_CHIPTESTBOARDD)
#if !defined(MYTHEN3D) && !defined(XILINX_CHIPTESTBOARDD) && \
!defined(CHIPTESTBOARDD)
functionNotImplemented();
#else
// only set

View File

@@ -40,8 +40,7 @@ char initErrorMessage[MAX_STR_LENGTH];
int detPos[2] = {0, 0};
uint32_t clkFrequency[NUM_CLOCKS] = {20, 100, 20, 100};
uint32_t clkFrequency[NUM_CLOCKS] = {};
int chipConfigured = 0;
int analogEnable = 0;
int digitalEnable = 0;
@@ -376,6 +375,10 @@ void setupDetector() {
LOG(logINFO, ("Setting up Server for 1 Xilinx Chip Test Board\n"));
// default variables
clkFrequency[RUN_CLK] = DEFAULT_RUN_CLK;
clkFrequency[ADC_CLK] = DEFAULT_ADC_CLK;
clkFrequency[SYNC_CLK] = DEFAULT_SYNC_CLK;
clkFrequency[DBIT_CLK] = DEFAULT_DBIT_CLK;
chipConfigured = 0;
analogEnable = 0;
digitalEnable = 0;
@@ -1061,12 +1064,12 @@ int setPeriod(int64_t val) {
return FAIL;
}
LOG(logINFO, ("Setting period %lld ns\n", (long long int)val));
val *= (1E-3 * RUN_CLK);
val *= (1E-3 * clkFrequency[RUN_CLK]);
setU64BitReg(val, PERIOD_IN_REG_1, PERIOD_IN_REG_2);
// validate for tolerance
int64_t retval = getPeriod();
val /= (1E-3 * RUN_CLK);
val /= (1E-3 * clkFrequency[RUN_CLK]);
if (val != retval) {
return FAIL;
}
@@ -1074,7 +1077,8 @@ int setPeriod(int64_t val) {
}
int64_t getPeriod() {
return getU64BitReg(PERIOD_IN_REG_1, PERIOD_IN_REG_2) / (1E-3 * RUN_CLK);
return getU64BitReg(PERIOD_IN_REG_1, PERIOD_IN_REG_2) /
(1E-3 * clkFrequency[RUN_CLK]);
}
int setDelayAfterTrigger(int64_t val) {
@@ -1083,12 +1087,12 @@ int setDelayAfterTrigger(int64_t val) {
return FAIL;
}
LOG(logINFO, ("Setting delay after trigger %ld ns\n", val));
val *= (1E-3 * RUN_CLK);
val *= (1E-3 * clkFrequency[RUN_CLK]);
setU64BitReg(val, DELAY_IN_REG_1, DELAY_IN_REG_2);
// validate for tolerance
int64_t retval = getDelayAfterTrigger();
val /= (1E-3 * RUN_CLK);
val /= (1E-3 * clkFrequency[RUN_CLK]);
if (val != retval) {
return FAIL;
}
@@ -1096,7 +1100,8 @@ int setDelayAfterTrigger(int64_t val) {
}
int64_t getDelayAfterTrigger() {
return getU64BitReg(DELAY_IN_REG_1, DELAY_IN_REG_2) / (1E-3 * RUN_CLK);
return getU64BitReg(DELAY_IN_REG_1, DELAY_IN_REG_2) /
(1E-3 * clkFrequency[RUN_CLK]);
}
int64_t getNumFramesLeft() {
@@ -1108,11 +1113,13 @@ int64_t getNumTriggersLeft() {
}
int64_t getDelayAfterTriggerLeft() {
return getU64BitReg(DELAY_OUT_REG_1, DELAY_OUT_REG_2) / (1E-3 * RUN_CLK);
return getU64BitReg(DELAY_OUT_REG_1, DELAY_OUT_REG_2) /
(1E-3 * clkFrequency[RUN_CLK]);
}
int64_t getPeriodLeft() {
return getU64BitReg(PERIOD_OUT_REG_1, PERIOD_OUT_REG_2) / (1E-3 * RUN_CLK);
return getU64BitReg(PERIOD_OUT_REG_1, PERIOD_OUT_REG_2) /
(1E-3 * clkFrequency[RUN_CLK]);
}
int64_t getFramesFromStart() {
@@ -1122,12 +1129,12 @@ int64_t getFramesFromStart() {
int64_t getActualTime() {
return getU64BitReg(TIME_FROM_START_OUT_REG_1, TIME_FROM_START_OUT_REG_2) /
(1E-3 * TICK_CLK);
(1E-3 * clkFrequency[SYNC_CLK]);
}
int64_t getMeasurementTime() {
return getU64BitReg(FRAME_TIME_OUT_REG_1, FRAME_TIME_OUT_REG_2) /
(1E-3 * TICK_CLK);
(1E-3 * clkFrequency[SYNC_CLK]);
}
/* parameters - dac, adc, hv */
@@ -1792,10 +1799,16 @@ int setFrequency(enum CLKINDEX ind, int val) {
}
char *clock_names[] = {CLK_NAMES};
LOG(logINFO, ("\tSetting %s clock (%d) frequency to %d MHz\n",
LOG(logINFO, ("\tSetting %s clock (%d) frequency to %d kHz\n",
clock_names[ind], ind, val));
XILINX_PLL_setFrequency(ind, val);
if (XILINX_PLL_setFrequency(ind, val) == FAIL) {
LOG(logERROR, ("\tCould not set %s clock (%d) frequency to %d kHz\n",
clock_names[ind], ind, val));
return FAIL;
}
clkFrequency[ind] = val;
// TODO later: connect setPhase as phase gets reset on freq change
return OK;
}
@@ -1804,5 +1817,8 @@ int getFrequency(enum CLKINDEX ind) {
LOG(logERROR, ("Unknown clock index %d to get frequency\n", ind));
return -1;
}
return XILINX_PLL_getFrequency(ind);
#ifndef VIRTUAL
clkFrequency[ind] = XILINX_PLL_getFrequency(ind);
#endif
return clkFrequency[ind];
}

View File

@@ -71,8 +71,6 @@
#define POWER_RGLTR_MAX (2661)
#define VIO_MIN_MV (1200) // for fpga to function
#define TICK_CLK (20) // MHz (trig_timeFromStart, frametime, timeFromStart)
/* Defines in the Firmware */
#define WAIT_TIME_PATTERN_READ (10)
#define WAIT_TIME_OUT_0US_TIMES (35000) // 2s
@@ -156,4 +154,9 @@ typedef struct udp_header_struct {
#define UDP_IP_HEADER_LENGTH_BYTES (28)
enum CLKINDEX { RUN_CLK, ADC_CLK, SYNC_CLK, DBIT_CLK, NUM_CLOCKS };
#define CLK_NAMES "run", "adc", "sync", "dbit"
#define CLK_NAMES "run", "adc", "sync", "dbit"
#define DEFAULT_RUN_CLK (20000) // 20 MHz
#define DEFAULT_ADC_CLK (100000) // 100 MHz
#define DEFAULT_SYNC_CLK (20000) // 20 MHz
#define DEFAULT_DBIT_CLK (100000) // 100 MHz