Pattern unification & Matterhorn Changes (#1303)
Some checks failed
Build on RHEL9 / build (push) Failing after 3m7s
Build on RHEL8 / build (push) Failing after 4m58s

* update ctb regDefs, included fill level of adc, transceiver and DBit fifos, added enable registers for cont. readout

* fix fifo fill level range bug

* updated ctb RegDefs, increased size of fifo fill level register

* added register to read the firmware git hash

* ctb: added altchip_id read register

* start with unification of pattern machinery for xctb, ctb, mythen

* udate addrs for d-server internal matterhorn startup

* update xctb reg defs

* move pattern loopdef start

* added zero trimbits to matterhorn config

* Revert "added zero trimbits to matterhorn config"

This reverts commit 7c347badd5.

* added adjustable clocks on Xilinx-CTB

* added support for fractional dividers of runclk

* XCTB: make frequencies adjustable from python gui

* update docs

* added support for patternstart command to XCTB

* XCTB: map pattern_ram directly into memory, removed rw strobe

* refactor Mythen pattern control addresses

* test altera ctb with common addresses, removed ifdefs

* change ordering of regdefs

* updated python help for dbitclk, adcclk and runclk (khz)

* xilinx: moved the wait for firmware to measure the actual frequency to the server side and removed it in the pyctbgui side

* will not be anymore in developer branch

* make format (exception RegisterDefs.h), rewrite XILINX PLL to have less consstants in the code

* bug: mixing && for &

---------

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-17 17:28:17 +02:00
committed by GitHub
parent 6e006665ef
commit e7a91d38f2
33 changed files with 795 additions and 951 deletions

View File

@@ -0,0 +1,200 @@
// SPDX-License-Identifier: LGPL-3.0-or-other
// Copyright (C) 2021 Contributors to the SLS Detector Package
#include "XILINX_PLL.h"
#include "arm64.h"
#include "clogger.h"
#include <math.h>
#include <stdbool.h>
#include <unistd.h>
// https://docs.amd.com/r/en-US/pg065-clk-wiz/Register-Space (simplified, we
// leave some things away)
// clang-format off
#define XILINX_PLL_INPUT_FREQ (100000) // 100 MHz
#define XILINX_PLL_MIN_FREQ (10000)
#define XILINX_PLL_MAX_FREQ (250000)
#define XILINX_PLL_MAX_CLK_DIV (256)
#define XILINX_PLL_NUM_CLKS (7)
#define XILINX_PLL_MAX_NUM_CLKS_FOR_GET (3)
#define XILINX_PLL_STEP_SIZE (125)
#define XILINX_PLL_HALF_STEP_SIZE (62)
#define XILINX_PLL_BASE_ADDR (0x0)
#define XILINX_PLL_MEASURE_BASE_ADDR0 (0x1000) // added externally, not part of CLKWIZ core for clks 0 and 1
#define XILINX_PLL_MEASURE_BASE_ADDR0_MAX_CLKS (2)
#define XILINX_PLL_MEASURE_BASE_ADDR1 (0x2000) // for clks 2 to 6
#define XILINX_PLL_MEASURE_WIDTH (8) // per clock
#define XILINX_PLL_RESET_REG (0x000)
#define XILINX_PLL_RESET_VAL (0xA)
#define XILINX_PLL_STATUS_REG (0x004)
#define XILINX_PLL_STATUS_LOCKED_OFST (0)
#define XILINX_PLL_STATUS_LOCKED_MSK (0x00000001 << XILINX_PLL_STATUS_LOCKED_OFST)
#define XILINX_PLL_CLKCONFIG_REG (XILINX_PLL_BASE_ADDR + 0x200)
#define XILINX_PLL_DIVCLK_DIVIDE_OFST (0)
#define XILINX_PLL_DIVCLK_DIVIDE_MSK (0x000000FF << XILINX_PLL_DIVCLK_DIVIDE_OFST)
#define XILINX_PLL_CLKFBOUT_MULT_OFST (8)
#define XILINX_PLL_CLKFBOUT_MULT_MSK (0x000000FF << XILINX_PLL_CLKFBOUT_MULT_OFST)
#define XILINX_PLL_CLKFBOUT_FRAC_OFST (16)
#define XILINX_PLL_CLKFBOUT_FRAC_MSK (0x000003FF << XILINX_PLL_CLKFBOUT_FRAC_OFST)
// The value from 0 to 875 representing the fractional multiplied by 1000
#define XILINX_PLL_CLKFBOUT_FRAC_MAX_VAL (875)
#define XILINX_PLL_CLKCONFIG_BASE_ADDR (XILINX_PLL_BASE_ADDR + 0x208)
#define XILINX_PLL_CLKCONFIG_WIDTH (3 * 4) // per clock (7 clocks)
#define XILINX_PLL_CLK_DIV_REG_OFST (0)
#define XILINX_PLL_CLK_DIV_DIVIDE_OFST (0)
#define XILINX_PLL_CLK_DIV_DIVIDE_MSK (0x000000FF << XILINX_PLL_CLK_DIV_DIVIDE_OFST)
#define XILINX_PLL_CLK_DIV_FRAC_OFST (8) // works on IDX 0 only
#define XILINX_PLL_CLK_DIV_FRAC_MSK (0x000003FF << XILINX_PLL_CLK_DIV_FRAC_OFST)
#define XILINX_PLL_CLK_PHASE_REG_OFST (4) // signed num for +/- phase
#define XILINX_PLL_CLK_PHASE_OFST (0)
#define XILINX_PLL_CLK_PHASE_MSK (0x0000FFFF << XILINX_PLL_CLK_PHASE_OFST)
#define XILINX_PLL_CLK_DUTY_REG_OFST (8) // (in %) * 1000
#define XILINX_PLL_CLK_DUTY_OFST (0)
#define XILINX_PLL_CLK_DUTY_MSK (0x0000FFFF << XILINX_PLL_CLK_DUTY_OFST)
#define XILINX_PLL_LOAD_REG (0x25C)
#define XILINX_PLL_LOAD_RECONFIGURE_OFST (0) // load and reconfigure state machine
#define XILINX_PLL_LOAD_RECONFIGURE_MSK (0x00000001 << XILINX_PLL_LOAD_RECONFIGURE_OFST)
#define XILINX_PLL_LOAD_FROM_REGS_OFST (1) // 0 for default values as compiled into firmware
#define XILINX_PLL_LOAD_FROM_REGS_MSK (0x00000001 << XILINX_PLL_LOAD_FROM_REGS_OFST)
// clang-format on
// freq in kHz !!
void 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;
}
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;
}
// calculate base clock frequency
uint32_t global_reg = bus_r_csp2(XILINX_PLL_CLKCONFIG_REG);
#ifdef VIRTUAL
global_reg = 3073;
#endif
uint32_t clkfbout_mult = ((global_reg & XILINX_PLL_CLKFBOUT_MULT_MSK) >>
XILINX_PLL_CLKFBOUT_MULT_OFST);
uint32_t clkfbout_frac = ((global_reg & XILINX_PLL_CLKFBOUT_FRAC_MSK) >>
XILINX_PLL_CLKFBOUT_FRAC_OFST);
uint32_t divclk_divide = ((global_reg & XILINX_PLL_DIVCLK_DIVIDE_MSK) >>
XILINX_PLL_DIVCLK_DIVIDE_OFST);
uint32_t base_clk_freq = clkfbout_mult * XILINX_PLL_INPUT_FREQ;
base_clk_freq += (clkfbout_frac * XILINX_PLL_INPUT_FREQ /
XILINX_PLL_CLKFBOUT_FRAC_MAX_VAL);
base_clk_freq /= divclk_divide;
// calcualte clock divider
uint32_t clk_div = base_clk_freq / 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;
}
uint32_t clk_div_frac = 0;
// the first clock supports fractional division, increase the precision for
// that one fractional divide is not allowed in fixed or dynamic phase shift
// mode !!!!
if (clk_index == 0) {
float clk_div_frac_f =
(float)base_clk_freq / freq - clk_div; // eg. 2.333 => 0.333
clk_div_frac = (uint32_t)round(clk_div_frac_f * 1000); // 0.333 => 333
clk_div_frac = ((clk_div_frac + XILINX_PLL_HALF_STEP_SIZE) /
XILINX_PLL_STEP_SIZE) *
XILINX_PLL_STEP_SIZE; // round to multiples of step size,
// 333 = > 375
if (clk_div_frac == 1000) {
clk_div_frac = 0;
clk_div++;
}
}
LOG(logINFOBLUE, ("XILINX_PLL: Setting clock divider to %u.%u\n", clk_div,
clk_div_frac));
uint32_t clk_addr = XILINX_PLL_CLKCONFIG_BASE_ADDR +
clk_index * XILINX_PLL_CLKCONFIG_WIDTH +
XILINX_PLL_CLK_DIV_REG_OFST;
uint32_t clk_config_val = ((clk_div << XILINX_PLL_CLK_DIV_DIVIDE_OFST) &
XILINX_PLL_CLK_DIV_DIVIDE_MSK) |
((clk_div_frac << XILINX_PLL_CLK_DIV_FRAC_OFST) &
XILINX_PLL_CLK_DIV_FRAC_MSK);
bus_w_csp2(clk_addr, clk_config_val);
XILINX_PLL_load();
XILINX_PLL_waitForLock();
// wait for firmware to measure the actual frequency
usleep(2 * 1000 * 1000);
}
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;
}
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;
}
uint32_t base_addr = XILINX_PLL_MEASURE_BASE_ADDR0;
if (clk_index >= XILINX_PLL_MEASURE_BASE_ADDR0_MAX_CLKS) {
clk_index -= XILINX_PLL_MEASURE_BASE_ADDR0_MAX_CLKS;
base_addr = XILINX_PLL_MEASURE_BASE_ADDR1;
}
uint32_t addr = base_addr + clk_index * XILINX_PLL_MEASURE_WIDTH;
uint32_t counter_val = bus_r_csp2(addr);
// Hz => round to nearest kHz
uint32_t freq_kHz = (counter_val + 500) / 1000; // round to nearest kHz
return freq_kHz;
}
bool XILINX_PLL_isLocked() {
uint32_t status = bus_r_csp2(XILINX_PLL_BASE_ADDR + XILINX_PLL_STATUS_REG);
return ((status & XILINX_PLL_STATUS_LOCKED_MSK) >>
XILINX_PLL_STATUS_LOCKED_OFST);
}
void XILINX_PLL_reset() {
bus_w_csp2(XILINX_PLL_BASE_ADDR + XILINX_PLL_RESET_REG,
XILINX_PLL_RESET_VAL);
}
void XILINX_PLL_load() {
bus_w_csp2(
XILINX_PLL_BASE_ADDR + XILINX_PLL_LOAD_REG,
(XILINX_PLL_LOAD_RECONFIGURE_MSK | XILINX_PLL_LOAD_FROM_REGS_MSK));
}
void XILINX_PLL_waitForLock() {
#ifdef VIRTUAL
return;
#endif
int timeout_us = 10 * 1000;
int count = 500;
while (count > 0) {
usleep(timeout_us);
if (XILINX_PLL_isLocked())
return;
count--;
}
LOG(logERROR, ("XILINX_PLL: Timeout waiting for PLL to lock (%d ms)\n",
(count * timeout_us) / 1000));
}

View File

@@ -13,11 +13,14 @@
/* global variables */
#define CSP0 (0xB0080000)
#define CSP1 (0xB0050000) // udp
#define MEM_SIZE_CSP0 (0x10000)
#define CSP2 (0xA0000000)
#define MEM_SIZE_CSP0 (0x20000)
#define MEM_SIZE_CSP1 (0x2000) // smaller size for udp
#define MEM_SIZE_CSP2 (0x4000)
u_int32_t *csp0base = 0;
u_int32_t *csp1base = 0;
u_int32_t *csp2base = 0;
void bus_w(u_int32_t offset, u_int32_t data) {
volatile u_int32_t *ptr1;
@@ -31,6 +34,18 @@ u_int32_t bus_r(u_int32_t offset) {
return *ptr1;
}
void bus_w_csp2(u_int32_t offset, u_int32_t data) {
volatile u_int32_t *ptr1;
ptr1 = (u_int32_t *)(csp2base + offset / (sizeof(u_int32_t)));
*ptr1 = data;
}
u_int32_t bus_r_csp2(u_int32_t offset) {
volatile u_int32_t *ptr1;
ptr1 = (u_int32_t *)(csp2base + offset / (sizeof(u_int32_t)));
return *ptr1;
}
uint64_t getU64BitReg(int aLSB, int aMSB) {
uint64_t retval = bus_r(aMSB);
retval = (retval << 32) | bus_r(aLSB);
@@ -51,12 +66,12 @@ u_int32_t writeRegister(u_int32_t offset, u_int32_t data) {
int mapCSP0(void) {
LOG(logINFO, ("Mapping memory\n"));
u_int32_t csps[2] = {CSP0, CSP1};
u_int32_t **cspbases[2] = {&csp0base, &csp1base};
u_int32_t memsize[2] = {MEM_SIZE_CSP0, MEM_SIZE_CSP1};
char names[2][10] = {"csp0base", "csp1base"};
u_int32_t csps[3] = {CSP0, CSP1, CSP2};
u_int32_t **cspbases[3] = {&csp0base, &csp1base, &csp2base};
u_int32_t memsize[3] = {MEM_SIZE_CSP0, MEM_SIZE_CSP1, MEM_SIZE_CSP2};
char names[3][10] = {"csp0base", "csp1base", "csp2base"};
for (int i = 0; i < 2; ++i) {
for (int i = 0; i < 3; ++i) {
// if not mapped
if (*cspbases[i] == 0) {
LOG(logINFO, ("\tMapping memory for %s\n", names[i]));

View File

@@ -13,7 +13,7 @@
extern enum TLogLevel trimmingPrint;
extern uint32_t clkDivider[];
#endif
#ifdef CHIPTESTBOARDD
#if defined(CHIPTESTBOARDD) || defined(XILINX_CHIPTESTBOARDD)
extern uint32_t clkFrequency[];
#endif
@@ -54,27 +54,12 @@ void initializePatternWord() {
memset(virtual_pattern, 0, sizeof(virtual_pattern));
}
#endif
#endif
#if defined(CHIPTESTBOARDD) || defined(XILINX_CHIPTESTBOARDD)
uint64_t validate_readPatternIOControl() {
#if defined(CHIPTESTBOARDD)
return getU64BitReg(PATTERN_IO_CNTRL_LSB_REG, PATTERN_IO_CNTRL_MSB_REG);
#elif defined(XILINX_CHIPTESTBOARDD)
return (uint64_t)(bus_r(PINIOCTRLREG));
#endif
}
int validate_writePatternIOControl(char *message, uint64_t arg) {
// validate input
#ifdef XILINX_CHIPTESTBOARDD
if (arg > BIT32_MSK) {
strcpy(message, "Could not set pattern IO Control. Must be 32 bit for "
"this detector\n");
LOG(logERROR, (message));
return FAIL;
}
#endif
writePatternIOControl(arg);
@@ -95,15 +80,9 @@ int validate_writePatternIOControl(char *message, uint64_t arg) {
}
void writePatternIOControl(uint64_t word) {
#ifdef CHIPTESTBOARDD
LOG(logINFO,
("Setting Pattern I/O Control: 0x%llx\n", (long long int)word));
setU64BitReg(word, PATTERN_IO_CNTRL_LSB_REG, PATTERN_IO_CNTRL_MSB_REG);
#elif defined(XILINX_CHIPTESTBOARDD)
uint32_t val = (uint32_t)word;
LOG(logINFO, ("Setting Pattern I/O Control: 0x%x\n", val));
bus_w(PINIOCTRLREG, val);
#endif
}
#endif
@@ -122,7 +101,7 @@ int validate_readPatternWord(char *message, int addr, uint64_t *word) {
}
uint64_t readPatternWord(int addr) {
#ifdef MYTHEN3D
#if defined(MYTHEN3D) || defined(XILINX_CHIPTESTBOARDD)
LOG(logDEBUG1, (" Reading Pattern Word (addr:0x%x)\n", addr));
// the first word in RAM as base plus the offset of the word to write (addr)
uint32_t reg_lsb = PATTERN_STEP0_LSB_REG + addr * REG_OFFSET * 2;
@@ -182,7 +161,7 @@ void writePatternWord(int addr, uint64_t word) {
LOG(logDEBUG1, ("Setting Pattern Word (addr:0x%x, word:0x%llx)\n", addr,
(long long int)word));
#ifndef MYTHEN3D
#ifdef CHIPTESTBOARDD
uint32_t reg = PATTERN_CNTRL_REG;
// write word
@@ -199,7 +178,6 @@ void writePatternWord(int addr, uint64_t word) {
#ifdef VIRTUAL
virtual_pattern[addr] = word;
#endif
// mythen
#else
// the first word in RAM as base plus the offset of the word to write (addr)
uint32_t reg_lsb = PATTERN_STEP0_LSB_REG + addr * REG_OFFSET * 2;
@@ -223,29 +201,15 @@ int validate_getPatternWaitAddresses(char *message, int level, int *addr) {
}
int getPatternWaitAddress(int level) {
switch (level) {
case 0:
return ((bus_r(PATTERN_WAIT_0_ADDR_REG) & PATTERN_WAIT_0_ADDR_MSK) >>
PATTERN_WAIT_0_ADDR_OFST);
case 1:
return ((bus_r(PATTERN_WAIT_1_ADDR_REG) & PATTERN_WAIT_1_ADDR_MSK) >>
PATTERN_WAIT_1_ADDR_OFST);
case 2:
return ((bus_r(PATTERN_WAIT_2_ADDR_REG) & PATTERN_WAIT_2_ADDR_MSK) >>
PATTERN_WAIT_2_ADDR_OFST);
#ifndef MYTHEN3D
case 3:
return ((bus_r(PATTERN_WAIT_3_ADDR_REG) & PATTERN_WAIT_3_ADDR_MSK) >>
PATTERN_WAIT_3_ADDR_OFST);
case 4:
return ((bus_r(PATTERN_WAIT_4_ADDR_REG) & PATTERN_WAIT_4_ADDR_MSK) >>
PATTERN_WAIT_4_ADDR_OFST);
case 5:
return ((bus_r(PATTERN_WAIT_5_ADDR_REG) & PATTERN_WAIT_5_ADDR_MSK) >>
PATTERN_WAIT_5_ADDR_OFST);
#endif
default:
if (level < 0 || level >= MAX_LEVELS) {
return -1;
} else {
return ((bus_r(PATTERN_LOOPDEF_BASE +
(PATTERN_WAIT_ADDR_WORD_OFST +
level * PATTERN_LOOPDEF_NWORDS_OFST) *
REG_OFFSET) &
PATTERN_WAIT_ADDR_MSK) >>
PATTERN_WAIT_ADDR_OFST);
}
}
@@ -289,35 +253,13 @@ void setPatternWaitAddress(int level, int addr) {
LOG(logINFO,
#endif
("Setting Pattern Wait Address (level:%d, addr:0x%x)\n", level, addr));
switch (level) {
case 0:
bus_w(PATTERN_WAIT_0_ADDR_REG,
((addr << PATTERN_WAIT_0_ADDR_OFST) & PATTERN_WAIT_0_ADDR_MSK));
break;
case 1:
bus_w(PATTERN_WAIT_1_ADDR_REG,
((addr << PATTERN_WAIT_1_ADDR_OFST) & PATTERN_WAIT_1_ADDR_MSK));
break;
case 2:
bus_w(PATTERN_WAIT_2_ADDR_REG,
((addr << PATTERN_WAIT_2_ADDR_OFST) & PATTERN_WAIT_2_ADDR_MSK));
break;
#ifndef MYTHEN3D
case 3:
bus_w(PATTERN_WAIT_3_ADDR_REG,
((addr << PATTERN_WAIT_3_ADDR_OFST) & PATTERN_WAIT_3_ADDR_MSK));
break;
case 4:
bus_w(PATTERN_WAIT_4_ADDR_REG,
((addr << PATTERN_WAIT_4_ADDR_OFST) & PATTERN_WAIT_4_ADDR_MSK));
break;
case 5:
bus_w(PATTERN_WAIT_5_ADDR_REG,
((addr << PATTERN_WAIT_5_ADDR_OFST) & PATTERN_WAIT_5_ADDR_MSK));
break;
#endif
default:
if (level < 0 || level >= MAX_LEVELS) {
return;
} else {
bus_w(PATTERN_LOOPDEF_BASE + (PATTERN_WAIT_ADDR_WORD_OFST +
level * PATTERN_LOOPDEF_NWORDS_OFST) *
REG_OFFSET,
((addr << PATTERN_WAIT_ADDR_OFST) & PATTERN_WAIT_ADDR_MSK));
}
}
@@ -340,39 +282,24 @@ int validate_getPatternWaitClocksAndInterval(char *message, int level,
}
uint64_t getPatternWaitClocks(int level) {
switch (level) {
case 0:
return getU64BitReg(PATTERN_WAIT_TIMER_0_LSB_REG,
PATTERN_WAIT_TIMER_0_MSB_REG);
case 1:
return getU64BitReg(PATTERN_WAIT_TIMER_1_LSB_REG,
PATTERN_WAIT_TIMER_1_MSB_REG);
case 2:
return getU64BitReg(PATTERN_WAIT_TIMER_2_LSB_REG,
PATTERN_WAIT_TIMER_2_MSB_REG);
#ifndef MYTHEN3D
case 3:
return getU64BitReg(PATTERN_WAIT_TIMER_3_LSB_REG,
PATTERN_WAIT_TIMER_3_MSB_REG);
case 4:
return getU64BitReg(PATTERN_WAIT_TIMER_4_LSB_REG,
PATTERN_WAIT_TIMER_4_MSB_REG);
case 5:
return getU64BitReg(PATTERN_WAIT_TIMER_5_LSB_REG,
PATTERN_WAIT_TIMER_5_MSB_REG);
#endif
default:
if (level < 0 || level >= MAX_LEVELS) {
return -1;
} else {
return getU64BitReg(
PATTERN_LOOPDEF_BASE + (PATTERN_WAIT_TIMER_LSB_WORD_OFST +
level * PATTERN_LOOPDEF_NWORDS_OFST) *
REG_OFFSET,
PATTERN_LOOPDEF_BASE + (PATTERN_WAIT_TIMER_MSB_WORD_OFST +
level * PATTERN_LOOPDEF_NWORDS_OFST) *
REG_OFFSET);
}
}
uint64_t getPatternWaitInterval(int level) {
uint64_t numClocks = getPatternWaitClocks(level);
int runclk = 0;
#ifdef CHIPTESTBOARDD
#if defined(CHIPTESTBOARDD) || defined(XILINX_CHIPTESTBOARDD)
runclk = clkFrequency[RUN_CLK];
#elif XILINX_CHIPTESTBOARDD
runclk = RUN_CLK;
#elif MYTHEN3D
runclk = clkDivider[SYSTEM_C0];
#endif
@@ -425,35 +352,18 @@ void setPatternWaitClocks(int level, uint64_t t) {
#endif
("Setting Pattern Wait Time in clocks (level:%d) :%lld\n", level,
(long long int)t));
switch (level) {
case 0:
setU64BitReg(t, PATTERN_WAIT_TIMER_0_LSB_REG,
PATTERN_WAIT_TIMER_0_MSB_REG);
break;
case 1:
setU64BitReg(t, PATTERN_WAIT_TIMER_1_LSB_REG,
PATTERN_WAIT_TIMER_1_MSB_REG);
break;
case 2:
setU64BitReg(t, PATTERN_WAIT_TIMER_2_LSB_REG,
PATTERN_WAIT_TIMER_2_MSB_REG);
break;
#ifndef MYTHEN3D
case 3:
setU64BitReg(t, PATTERN_WAIT_TIMER_3_LSB_REG,
PATTERN_WAIT_TIMER_3_MSB_REG);
break;
case 4:
setU64BitReg(t, PATTERN_WAIT_TIMER_4_LSB_REG,
PATTERN_WAIT_TIMER_4_MSB_REG);
break;
case 5:
setU64BitReg(t, PATTERN_WAIT_TIMER_5_LSB_REG,
PATTERN_WAIT_TIMER_5_MSB_REG);
break;
#endif
default:
if (level < 0 || level >= MAX_LEVELS) {
return;
} else {
return setU64BitReg(
t,
PATTERN_LOOPDEF_BASE + (PATTERN_WAIT_TIMER_LSB_WORD_OFST +
level * PATTERN_LOOPDEF_NWORDS_OFST) *
REG_OFFSET,
PATTERN_LOOPDEF_BASE + (PATTERN_WAIT_TIMER_MSB_WORD_OFST +
level * PATTERN_LOOPDEF_NWORDS_OFST) *
REG_OFFSET);
}
}
@@ -466,12 +376,10 @@ void setPatternWaitInterval(int level, uint64_t t) {
("Setting Pattern Wait Time (level:%d) :%lld ns\n", level,
(long long int)t));
int runclk = 0;
#ifdef CHIPTESTBOARDD
#if defined(CHIPTESTBOARDD) || defined(XILINX_CHIPTESTBOARDD)
runclk = clkFrequency[RUN_CLK];
#elif XILINX_CHIPTESTBOARDD
runclk = RUN_CLK;
#elif MYTHEN3D
runclk = clkDivider[SYSTEM_C0];
runclk = clkDivider[SYSTEM_C0];
#endif
uint64_t numClocks = t * (1E-3 * runclk);
setPatternWaitClocks(level, numClocks);
@@ -491,23 +399,13 @@ int validate_getPatternLoopCycles(char *message, int level, int *numLoops) {
}
int getPatternLoopCycles(int level) {
switch (level) {
case 0:
return bus_r(PATTERN_LOOP_0_ITERATION_REG);
case 1:
return bus_r(PATTERN_LOOP_1_ITERATION_REG);
case 2:
return bus_r(PATTERN_LOOP_2_ITERATION_REG);
#ifndef MYTHEN3D
case 3:
return bus_r(PATTERN_LOOP_3_ITERATION_REG);
case 4:
return bus_r(PATTERN_LOOP_4_ITERATION_REG);
case 5:
return bus_r(PATTERN_LOOP_5_ITERATION_REG);
#endif
default:
if (level < 0 || level >= MAX_LEVELS) {
return -1;
} else {
return bus_r(PATTERN_LOOPDEF_BASE +
(PATTERN_LOOP_ITERATION_WORD_OFST +
level * PATTERN_LOOPDEF_NWORDS_OFST) *
REG_OFFSET);
}
}
@@ -546,29 +444,13 @@ void setPatternLoopCycles(int level, int nLoop) {
LOG(logINFO,
#endif
("Setting Pattern Loop Cycles(level:%d, nLoop:%d)\n", level, nLoop));
switch (level) {
case 0:
bus_w(PATTERN_LOOP_0_ITERATION_REG, nLoop);
break;
case 1:
bus_w(PATTERN_LOOP_1_ITERATION_REG, nLoop);
break;
case 2:
bus_w(PATTERN_LOOP_2_ITERATION_REG, nLoop);
break;
#ifndef MYTHEN3D
case 3:
bus_w(PATTERN_LOOP_3_ITERATION_REG, nLoop);
break;
case 4:
bus_w(PATTERN_LOOP_4_ITERATION_REG, nLoop);
break;
case 5:
bus_w(PATTERN_LOOP_5_ITERATION_REG, nLoop);
break;
#endif
default:
if (level < 0 || level >= MAX_LEVELS) {
return;
} else {
bus_w(PATTERN_LOOPDEF_BASE + (PATTERN_LOOP_ITERATION_WORD_OFST +
level * PATTERN_LOOPDEF_NWORDS_OFST) *
REG_OFFSET,
nLoop);
}
}
@@ -639,59 +521,22 @@ int validate_getPatternLoopAddresses(char *message, int level, int *startAddr,
}
void getPatternLoopAddresses(int level, int *startAddr, int *stopAddr) {
switch (level) {
case 0:
*startAddr =
((bus_r(PATTERN_LOOP_0_ADDR_REG) & PATTERN_LOOP_0_ADDR_STRT_MSK) >>
PATTERN_LOOP_0_ADDR_STRT_OFST);
*stopAddr =
((bus_r(PATTERN_LOOP_0_ADDR_REG) & PATTERN_LOOP_0_ADDR_STP_MSK) >>
PATTERN_LOOP_0_ADDR_STP_OFST);
break;
case 1:
*startAddr =
((bus_r(PATTERN_LOOP_1_ADDR_REG) & PATTERN_LOOP_1_ADDR_STRT_MSK) >>
PATTERN_LOOP_1_ADDR_STRT_OFST);
*stopAddr =
((bus_r(PATTERN_LOOP_1_ADDR_REG) & PATTERN_LOOP_1_ADDR_STP_MSK) >>
PATTERN_LOOP_1_ADDR_STP_OFST);
break;
case 2:
*startAddr =
((bus_r(PATTERN_LOOP_2_ADDR_REG) & PATTERN_LOOP_2_ADDR_STRT_MSK) >>
PATTERN_LOOP_2_ADDR_STRT_OFST);
*stopAddr =
((bus_r(PATTERN_LOOP_2_ADDR_REG) & PATTERN_LOOP_2_ADDR_STP_MSK) >>
PATTERN_LOOP_2_ADDR_STP_OFST);
break;
#ifndef MYTHEN3D
case 3:
*startAddr =
((bus_r(PATTERN_LOOP_3_ADDR_REG) & PATTERN_LOOP_3_ADDR_STRT_MSK) >>
PATTERN_LOOP_3_ADDR_STRT_OFST);
*stopAddr =
((bus_r(PATTERN_LOOP_3_ADDR_REG) & PATTERN_LOOP_3_ADDR_STP_MSK) >>
PATTERN_LOOP_3_ADDR_STP_OFST);
break;
case 4:
*startAddr =
((bus_r(PATTERN_LOOP_4_ADDR_REG) & PATTERN_LOOP_4_ADDR_STRT_MSK) >>
PATTERN_LOOP_4_ADDR_STRT_OFST);
*stopAddr =
((bus_r(PATTERN_LOOP_4_ADDR_REG) & PATTERN_LOOP_4_ADDR_STP_MSK) >>
PATTERN_LOOP_4_ADDR_STP_OFST);
break;
case 5:
*startAddr =
((bus_r(PATTERN_LOOP_5_ADDR_REG) & PATTERN_LOOP_5_ADDR_STRT_MSK) >>
PATTERN_LOOP_5_ADDR_STRT_OFST);
*stopAddr =
((bus_r(PATTERN_LOOP_5_ADDR_REG) & PATTERN_LOOP_5_ADDR_STP_MSK) >>
PATTERN_LOOP_5_ADDR_STP_OFST);
break;
#endif
default:
return;
if (level < 0 || level >= MAX_LEVELS) {
*startAddr = -1;
*stopAddr = -1;
} else {
*startAddr = ((bus_r(PATTERN_LOOPDEF_BASE +
(PATTERN_LOOP_ADDR_WORD_OFST +
level * PATTERN_LOOPDEF_NWORDS_OFST) *
REG_OFFSET) &
PATTERN_LOOP_ADDR_STRT_MSK) >>
PATTERN_LOOP_ADDR_STRT_OFST);
*stopAddr = ((bus_r(PATTERN_LOOPDEF_BASE +
(PATTERN_LOOP_ADDR_WORD_OFST +
level * PATTERN_LOOPDEF_NWORDS_OFST) *
REG_OFFSET) &
PATTERN_LOOP_ADDR_STP_MSK) >>
PATTERN_LOOP_ADDR_STP_OFST);
}
}
@@ -747,53 +592,16 @@ void setPatternLoopAddresses(int level, int startAddr, int stopAddr) {
("Setting Pattern Loop Address (level:%d, startaddr:0x%x, "
"stopaddr:0x%x)\n",
level, startAddr, stopAddr));
switch (level) {
case 0:
bus_w(PATTERN_LOOP_0_ADDR_REG,
((startAddr << PATTERN_LOOP_0_ADDR_STRT_OFST) &
PATTERN_LOOP_0_ADDR_STRT_MSK) |
((stopAddr << PATTERN_LOOP_0_ADDR_STP_OFST) &
PATTERN_LOOP_0_ADDR_STP_MSK));
break;
case 1:
bus_w(PATTERN_LOOP_1_ADDR_REG,
((startAddr << PATTERN_LOOP_1_ADDR_STRT_OFST) &
PATTERN_LOOP_1_ADDR_STRT_MSK) |
((stopAddr << PATTERN_LOOP_1_ADDR_STP_OFST) &
PATTERN_LOOP_1_ADDR_STP_MSK));
break;
case 2:
bus_w(PATTERN_LOOP_2_ADDR_REG,
((startAddr << PATTERN_LOOP_2_ADDR_STRT_OFST) &
PATTERN_LOOP_2_ADDR_STRT_MSK) |
((stopAddr << PATTERN_LOOP_2_ADDR_STP_OFST) &
PATTERN_LOOP_2_ADDR_STP_MSK));
break;
#ifndef MYTHEN3D
case 3:
bus_w(PATTERN_LOOP_3_ADDR_REG,
((startAddr << PATTERN_LOOP_3_ADDR_STRT_OFST) &
PATTERN_LOOP_3_ADDR_STRT_MSK) |
((stopAddr << PATTERN_LOOP_3_ADDR_STP_OFST) &
PATTERN_LOOP_3_ADDR_STP_MSK));
break;
case 4:
bus_w(PATTERN_LOOP_4_ADDR_REG,
((startAddr << PATTERN_LOOP_4_ADDR_STRT_OFST) &
PATTERN_LOOP_4_ADDR_STRT_MSK) |
((stopAddr << PATTERN_LOOP_4_ADDR_STP_OFST) &
PATTERN_LOOP_4_ADDR_STP_MSK));
break;
case 5:
bus_w(PATTERN_LOOP_5_ADDR_REG,
((startAddr << PATTERN_LOOP_5_ADDR_STRT_OFST) &
PATTERN_LOOP_5_ADDR_STRT_MSK) |
((stopAddr << PATTERN_LOOP_5_ADDR_STP_OFST) &
PATTERN_LOOP_5_ADDR_STP_MSK));
break;
#endif
default:
if (level < 0 || level >= MAX_LEVELS) {
return;
} else {
bus_w(PATTERN_LOOPDEF_BASE + (PATTERN_LOOP_ADDR_WORD_OFST +
level * PATTERN_LOOPDEF_NWORDS_OFST) *
REG_OFFSET,
((startAddr << PATTERN_LOOP_ADDR_STRT_OFST) &
PATTERN_LOOP_ADDR_STRT_MSK) |
((stopAddr << PATTERN_LOOP_ADDR_STP_OFST) &
PATTERN_LOOP_ADDR_STP_MSK));
}
}
@@ -826,6 +634,17 @@ void startPattern() {
LOG(logINFOBLUE, ("Pattern done\n"));
}
#endif
#ifdef XILINX_CHIPTESTBOARDD
void startPattern() {
LOG(logINFOBLUE, ("Starting Pattern\n"));
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);
}
LOG(logINFOBLUE, ("Pattern done\n"));
}
#endif
char *getPatternFileName() { return clientPatternfile; }

View File

@@ -5798,7 +5798,7 @@ int set_clock_frequency(int file_des) {
return printSocketReadError();
LOG(logDEBUG1, ("Setting clock (%d) frequency : %u\n", args[0], args[1]));
#if !defined(CHIPTESTBOARDD)
#if !defined(CHIPTESTBOARDD) && !defined(XILINX_CHIPTESTBOARDD)
functionNotImplemented();
#else
@@ -5811,7 +5811,7 @@ int set_clock_frequency(int file_des) {
case ADC_CLOCK:
c = ADC_CLK;
break;
#ifdef CHIPTESTBOARDD
#if defined(CHIPTESTBOARDD) || defined(XILINX_CHIPTESTBOARDD)
case DBIT_CLOCK:
c = DBIT_CLK;
break;
@@ -5843,7 +5843,11 @@ int set_clock_frequency(int file_des) {
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);
#endif
}
}
}
@@ -5861,13 +5865,14 @@ int get_clock_frequency(int file_des) {
return printSocketReadError();
LOG(logDEBUG1, ("Getting clock (%d) frequency\n", arg));
#if !defined(CHIPTESTBOARDD) && !defined(GOTTHARD2D) && !defined(MYTHEN3D)
#if !defined(CHIPTESTBOARDD) && !defined(GOTTHARD2D) && !defined(MYTHEN3D) && \
!defined(XILINX_CHIPTESTBOARDD)
functionNotImplemented();
#else
// get only
enum CLKINDEX c = 0;
switch (arg) {
#if defined(CHIPTESTBOARDD)
#if defined(CHIPTESTBOARDD) || defined(XILINX_CHIPTESTBOARDD)
case ADC_CLOCK:
c = ADC_CLK;
break;
@@ -7463,7 +7468,7 @@ int start_pattern(int file_des) {
memset(mess, 0, sizeof(mess));
LOG(logDEBUG1, ("Starting Pattern\n"));
#ifndef MYTHEN3D
#if !defined(MYTHEN3D) && !defined(XILINX_CHIPTESTBOARDD)
functionNotImplemented();
#else
// only set