tolerance process
Run Simulator Tests on local RHEL9 / build (push) Failing after 12s
Run Simulator Tests on local RHEL8 / build (push) Failing after 24s
Build on RHEL9 docker image / build (push) Failing after 49s
Build on RHEL8 docker image / build (push) Failing after 51s

This commit is contained in:
2026-04-29 16:42:54 +02:00
parent c43959803e
commit d616549f87
8 changed files with 107 additions and 77 deletions
+1 -1
View File
@@ -11,7 +11,7 @@ install(TARGETS slsProjectCSettings
PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}
)
add_subdirectory(ctbDetectorServer)
add_subdirectory(xilinx_ctbDetectorServer)
#add_subdirectory(xilinx_ctbDetectorServer)
add_subdirectory(eigerDetectorServer)
add_subdirectory(jungfrauDetectorServer)
add_subdirectory(mythen3DetectorServer)
@@ -1137,12 +1137,8 @@ int getNumTransceiverSamples() { return ntSamples; }
int setExpTime(int64_t val) {
setPatternWaitInterval(0, val);
// Tolerance: three clock periods in ns.
int64_t retval = getExpTime();
int64_t toleranceNs = 3 * (1000000000 / clkFrequency[RUN_CLK]);
int64_t diff = val - retval;
if (diff < -toleranceNs || diff > toleranceNs) {
if (retval != val) {
return FAIL;
}
return OK;
@@ -1150,55 +1146,68 @@ int setExpTime(int64_t val) {
int64_t getExpTime() { return getPatternWaitInterval(0); }
int setPeriod(int64_t val) {
int setPeriod(int64_t val, char *mess) {
if (val < 0) {
LOG(logERROR, ("Invalid period: %lld ns\n", (long long int)val));
sprintf(mess, "Invalid period: %lld ns\n", (long long int)val);
LOG(logERROR, (mess));
return FAIL;
}
LOG(logINFO, ("Setting period %lld ns\n", (long long int)val));
val *= (NS_TO_CLK_CYCLE * clkFrequency[SYNC_CLK]);
set64BitReg(val, PERIOD_LSB_REG, PERIOD_MSB_REG);
uint64_t numClocks = ns_to_clocks(val, clkFrequency[SYNC_CLK]);
set64BitReg(numClocks, PERIOD_LSB_REG, PERIOD_MSB_REG);
// validate for tolerance
int64_t retval = getPeriod();
val /= (NS_TO_CLK_CYCLE * clkFrequency[SYNC_CLK]);
int64_t toleranceNs = 3 * (1000000000 / clkFrequency[SYNC_CLK]);
int64_t diff = val - retval;
if (diff < -toleranceNs || diff > toleranceNs) {
int64_t retval = 0;
int ret = getPeriod(&retval, mess);
if (ret == FAIL) {
return FAIL;
}
validate64_timer(&ret, mess, val, retval, clkFrequency[SYNC_CLK], "period");
return ret;
}
int getPeriod(int64_t *retval, char *mess) {
if (clkFrequency[SYNC_CLK] == 0) {
sprintf(mess, "Cannot get period. Sync clock frequency is 0.\n");
LOG(logERROR, (mess));
return FAIL;
}
uint64_t numClocks = get64BitReg(PERIOD_LSB_REG, PERIOD_MSB_REG);
*retval = clocks_to_ns(numClocks, clkFrequency[SYNC_CLK]);
return OK;
}
int64_t getPeriod() {
return get64BitReg(PERIOD_LSB_REG, PERIOD_MSB_REG) /
(NS_TO_CLK_CYCLE * clkFrequency[SYNC_CLK]);
}
int setDelayAfterTrigger(int64_t val) {
int setDelayAfterTrigger(int64_t val, char *mess) {
if (val < 0) {
LOG(logERROR,
("Invalid delay after trigger: %lld ns\n", (long long int)val));
sprintf(mess, "Invalid delay after trigger: %lld ns\n",
(long long int)val);
LOG(logERROR, (mess));
return FAIL;
}
LOG(logINFO, ("Setting delay after trigger %lld ns\n", (long long int)val));
val *= (NS_TO_CLK_CYCLE * clkFrequency[SYNC_CLK]);
set64BitReg(val, DELAY_LSB_REG, DELAY_MSB_REG);
uint64_t numClocks = ns_to_clocks(val, clkFrequency[SYNC_CLK]);
set64BitReg(numClocks, DELAY_LSB_REG, DELAY_MSB_REG);
// validate for tolerance
int64_t retval = getDelayAfterTrigger();
val /= (NS_TO_CLK_CYCLE * clkFrequency[SYNC_CLK]);
int64_t toleranceNs = 3 * (1000000000 / clkFrequency[SYNC_CLK]);
int64_t diff = val - retval;
if (diff < -toleranceNs || diff > toleranceNs) {
int64_t retval = 0;
int ret = getDelayAfterTrigger(&retval, mess);
if (ret == FAIL) {
return FAIL;
}
return OK;
validate64_timer(&ret, mess, val, retval, clkFrequency[SYNC_CLK],
"delay after trigger");
return ret;
}
int64_t getDelayAfterTrigger() {
return get64BitReg(DELAY_LSB_REG, DELAY_MSB_REG) /
(NS_TO_CLK_CYCLE * clkFrequency[SYNC_CLK]);
int getDelayAfterTrigger(int64_t *retval, char *mess) {
if (clkFrequency[SYNC_CLK] == 0) {
sprintf(mess, "Cannot get period. Sync clock frequency is 0.\n");
LOG(logERROR, (mess));
return FAIL;
}
uint64_t numClocks = get64BitReg(DELAY_LSB_REG, DELAY_MSB_REG);
*retval = clocks_to_ns(numClocks, clkFrequency[SYNC_CLK]);
return OK;
}
int64_t getNumFramesLeft() {
@@ -100,8 +100,8 @@ void setNumTriggers(int64_t val);
int64_t getNumTriggers();
int setExpTime(int64_t val);
int64_t getExpTime();
int setPeriod(int64_t val);
int64_t getPeriod();
int setPeriod(int64_t val, char *mess);
int getPeriod(int64_t *retval, char *mess);
int setNumAnalogSamples(int val);
int getNumAnalogSamples();
int setNumDigitalSamples(int val);
@@ -111,8 +111,8 @@ int getNumTransceiverSamples();
int64_t getNumFramesLeft();
int64_t getNumTriggersLeft();
int setDelayAfterTrigger(int64_t val);
int64_t getDelayAfterTrigger();
int setDelayAfterTrigger(int64_t val, char *mess);
int getDelayAfterTrigger(int64_t *retval, char *mess);
int64_t getDelayAfterTriggerLeft();
int64_t getPeriodLeft();
int64_t getFramesFromStart();
@@ -21,6 +21,15 @@
enum numberMode { DEC, HEX };
enum PROGRAM_INDEX { PROGRAM_FPGA, PROGRAM_KERNEL, PROGRAM_SERVER };
#define NS_PER_SEC 1000000000ULL
#define HALF_NS_PER_SEC (NS_PER_SEC / 2)
static inline uint64_t ns_to_clocks(uint64_t t, uint32_t freq_hz) {
return (t * (uint64_t)freq_hz + HALF_NS_PER_SEC) / NS_PER_SEC;
}
static inline uint64_t clocks_to_ns(uint64_t clocks, uint32_t freq_hz) {
return (clocks * (uint64_t)NS_PER_SEC + freq_hz / 2) / freq_hz;
}
/**
* Convert a value from a range to a different range (eg voltage to dac or vice
* versa)
@@ -48,6 +57,9 @@ void validate(int *ret, char *mess, int arg, int retval, char *modename,
void validate64(int *ret, char *mess, int64_t arg, int64_t retval,
char *modename, enum numberMode nummode);
void validate64_timer(int *ret, char *message, uint64_t arg, uint64_t retval,
uint32_t runclk_hz, char *modename);
int getModuleIdInFile(int *ret, char *mess, char *fileName);
int verifyChecksumFromBuffer(char *mess, char *functionType,
char *clientChecksum, char *buffer, ssize_t bytes);
@@ -230,6 +230,20 @@ void validate64(int *ret, char *mess, int64_t arg, int64_t retval,
}
}
void validate64_timer(int *ret, char *message, uint64_t arg, uint64_t retval,
uint32_t clk_hz, char *modename) {
uint64_t arg_clks = ns_to_clocks(arg, clk_hz);
uint64_t retval_clks = ns_to_clocks(retval, clk_hz);
int64_t diff = (int64_t)retval_clks - (int64_t)arg_clks;
if (diff < 0) {
diff = -diff;
}
// tolerance = 1 clock
if (diff > 1) {
validate64(ret, message, arg, retval, modename, DEC);
}
}
int getModuleIdInFile(int *ret, char *mess, char *fileName) {
const int fileNameSize = 128;
char fname[fileNameSize];
@@ -277,6 +277,14 @@ int validate_getPatternWaitClocksAndInterval(char *message, int level,
*waittime = getPatternWaitClocks(level);
} else {
*waittime = getPatternWaitInterval(level);
if (*waittime == (uint64_t)-1) {
sprintf(
message,
"Cannot get pattern wait interval for level %d. runclk is 0.\n",
level);
LOG(logERROR, (message));
return FAIL;
}
}
return OK;
}
@@ -297,7 +305,7 @@ uint64_t getPatternWaitClocks(int level) {
uint64_t getPatternWaitInterval(int level) {
uint64_t numClocks = getPatternWaitClocks(level);
int runclk = 0;
uint32_t runclk = 0;
#if defined(CHIPTESTBOARDD) || defined(XILINX_CHIPTESTBOARDD)
runclk = clkFrequency[RUN_CLK];
#elif MYTHEN3D
@@ -307,9 +315,7 @@ uint64_t getPatternWaitInterval(int level) {
LOG(logERROR, ("runclk is 0. Cannot divide by 0. Returning -1.\n"));
return -1;
}
double conv = NS_TO_CLK_CYCLE * runclk;
uint64_t waitNs = (uint64_t)(numClocks / conv + 0.5);
return waitNs;
return clocks_to_ns(numClocks, runclk);
}
int validate_setPatternWaitClocksAndInterval(char *message, int level,
@@ -346,18 +352,18 @@ int validate_setPatternWaitClocksAndInterval(char *message, int level,
if (clocks) {
validate64(&ret, message, waittime, retval, mode, DEC);
} else {
uint32_t runclk = 0;
#if defined(CHIPTESTBOARDD) || defined(XILINX_CHIPTESTBOARDD)
int runclk = 0;
runclk = clkFrequency[RUN_CLK];
int64_t toleranceNs = 3 * (1000000000 / runclk);
int64_t diff = (int64_t)waittime - (int64_t)retval;
if (diff < -toleranceNs || diff > toleranceNs) {
validate64(&ret, message, waittime, retval, mode, DEC);
}
#else
validate64(&ret, message, waittime, retval, mode, DEC);
#elif MYTHEN3D
runclk = clkDivider[SYSTEM_C0];
#endif
if (retval == (uint64_t)-1) {
sprintf(message, "runclk is 0. Cannot divide by 0 for patttern "
"wait interval.\n");
return FAIL;
}
validate64_timer(&ret, message, waittime, retval, runclk, mode);
}
return ret;
}
@@ -393,13 +399,13 @@ void setPatternWaitInterval(int level, uint64_t t) {
#endif
("Setting Pattern Wait Time (level:%d) :%lld ns\n", level,
(long long int)t));
int runclk = 0;
uint32_t runclk = 0;
#if defined(CHIPTESTBOARDD) || defined(XILINX_CHIPTESTBOARDD)
runclk = clkFrequency[RUN_CLK];
#elif MYTHEN3D
runclk = clkDivider[SYSTEM_C0];
#endif
uint64_t numClocks = (uint64_t)(t * (NS_TO_CLK_CYCLE * runclk) + 0.5);
uint64_t numClocks = ns_to_clocks(t, runclk);
setPatternWaitClocks(level, numClocks);
}
@@ -3306,10 +3306,6 @@ int set_pattern_wait_clocks(int file_des) {
if (ret == OK) {
ret = validate_getPatternWaitClocksAndInterval(mess, loopLevel,
&retval, 1);
if ((int64_t)timeval != GET_FLAG) {
validate64(&ret, mess, (int64_t)timeval, retval,
"set pattern wait clocks", DEC);
}
}
}
#endif
@@ -10898,26 +10894,6 @@ int set_pattern_wait_interval(int file_des) {
if (Server_VerifyLock() == OK) {
ret = validate_setPatternWaitClocksAndInterval(mess, loopLevel, timeval,
0);
if (ret == OK) {
uint64_t retval = 0;
ret = validate_getPatternWaitClocksAndInterval(mess, loopLevel,
&retval, 0);
if (ret == OK) { // is this not already validated ? why do this
// again here ?
#if defined(CHIPTESTBOARDD) || defined(XILINX_CHIPTESTBOARDD)
int runclk = getFrequency(RUN_CLK);
int64_t toleranceNs = 3 * (1000000000 / runclk);
int64_t diff = (int64_t)timeval - (int64_t)retval;
if (diff < -toleranceNs || diff > toleranceNs) {
validate64(&ret, mess, (int64_t)timeval, retval,
"set pattern wait interval", DEC);
}
#else
validate64(&ret, mess, (int64_t)timeval, retval,
"set pattern wait interval", DEC);
#endif
}
}
}
#endif
@@ -1048,8 +1048,21 @@ TEST_CASE("runclk", "[.detectorintegration]") {
caller.call("runclk", {}, -1, GET, oss);
REQUIRE(oss.str() == "runclk 15.75MHz\n");
}
// tolerance
auto prev_exptime = det.getExptime();
auto prev_period = det.getPeriod();
auto prev_delay = det.getDelayAfterTrigger();
{
caller.call("runclk", {"80", "MHz"}, -1, PUT);
REQUIRE_NOTHROW(caller.call("exptime", {"10012", "ns"}, -1, PUT));
REQUIRE_NOTHROW(caller.call("period", {"10012", "ns"}, -1, PUT));
REQUIRE_NOTHROW(caller.call("delay", {"10012", "ns"}, -1, PUT));
}
for (int i = 0; i != det.size(); ++i) {
det.setRUNClock(prev_val[i], {i});
det.setExptime(prev_exptime[i], {i});
det.setPeriod(prev_period[i], {i});
det.setDelayAfterTrigger(prev_delay[i], {i});
}
} else {
// clock index might work