Line data Source code
1 : #ifndef CFO_AND_DTC_REGISTERS_H
2 : #define CFO_AND_DTC_REGISTERS_H
3 :
4 : // #include <bitset> // std::bitset
5 : // #include <cstdint> // uint8_t, uint16_t
6 : #include <functional> // std::bind, std::function
7 : #include <optional>
8 : #include <vector> // std::vector
9 :
10 : #include "mu2edev.h"
11 :
12 : #define DTCLIB_COMMON_REGISTERS \
13 : CFOandDTC_Register_DesignVersion = 0x9000, \
14 : CFOandDTC_Register_DesignDate = 0x9004, \
15 : CFOandDTC_Register_DesignStatus = 0x9008, \
16 : CFOandDTC_Register_VivadoVersion = 0x900C, \
17 : CFOandDTC_Register_FPGA_Temperature = 0x9010, \
18 : CFOandDTC_Register_FPGA_VCCINT = 0x9014, \
19 : CFOandDTC_Register_FPGA_VCCAUX = 0x9018, \
20 : CFOandDTC_Register_FPGA_VCCBRAM = 0x901C, \
21 : CFOandDTC_Register_FPGA_MonitorAlarm = 0x9020, \
22 : CFOandDTC_Register_TimeAlive = 0x9024, \
23 : CFOandDTC_Register_Scratch = 0x9030, \
24 : CFOandDTC_Register_Control = 0x9100, \
25 : CFOandDTC_Register_DMATransferLength = 0x9104, \
26 : CFOandDTC_Register_SERDES_LoopbackEnable = 0x9108, \
27 : CFOandDTC_Register_ClockOscillatorStatus = 0x910C, \
28 : CFOandDTC_Register_LinkEnable = 0x9114, \
29 : CFOandDTC_Register_SERDES_Reset = 0x9118, \
30 : CFOandDTC_Register_SERDES_RXDisparityError = 0x911C, \
31 : CFOandDTC_Register_SERDES_RXCharacterNotInTableError = 0x9120, \
32 : CFOandDTC_Register_SERDES_UnlockError = 0x9124, \
33 : CFOandDTC_Register_SERDES_PLLLocked = 0x9128, /* not in CFO (?) */ \
34 : CFOandDTC_Register_SERDES_PLLPowerDown = 0x912C, /* not in CFO (?) */ \
35 : CFOandDTC_Register_SERDES_CDRLockCommaCount = 0x9130, \
36 : CFOandDTC_Register_SERDES_RXStatus = 0x9134, \
37 : CFOandDTC_Register_SERDES_ResetDone = 0x9138, \
38 : CFOandDTC_Register_SERDESClock_IICBusLow = 0x9168, \
39 : CFOandDTC_Register_SERDESClock_IICBusHigh = 0x916C, \
40 : CFOandDTC_Register_FireflyTX_IICBusControl = 0x9284, \
41 : CFOandDTC_Register_FireflyTX_IICBusConfigLow = 0x9288, \
42 : CFOandDTC_Register_FireflyTX_IICBusConfigHigh = 0x928C, \
43 : CFOandDTC_Register_FireflyRX_IICBusControl = 0x9294, \
44 : CFOandDTC_Register_FireflyRX_IICBusConfigLow = 0x9298, \
45 : CFOandDTC_Register_FireflyRX_IICBusConfigHigh = 0x929C, \
46 : CFOandDTC_Register_FireflyTXRX_IICBusControl = 0x92A4, \
47 : CFOandDTC_Register_FireflyTXRX_IICBusConfigLow = 0x92A8, \
48 : CFOandDTC_Register_FireflyTXRX_IICBusConfigHigh = 0x92AC, \
49 : CFOandDTC_Register_FireFlyControlStatus = 0x93A0
50 :
51 : namespace DTCLib
52 : {
53 :
54 : typedef uint16_t CFOandDTC_Register; // defined enum in CFOandDTC_Registers.cpp
55 :
56 : /// <summary>
57 : /// The RegisterFormatter class is used to print a DTC register in a human-readable format
58 : /// </summary>
59 : struct RegisterFormatter
60 : {
61 : /// <summary>
62 : /// Default Constructor with zero values
63 : /// </summary>
64 0 : RegisterFormatter()
65 0 : : address(0)
66 0 : , value(0)
67 0 : , descWidth(28)
68 0 : , description("")
69 0 : , vals() {}
70 :
71 : /// <summary>
72 : /// Default Copy Consturctor
73 : /// </summary>
74 : /// <param name="r">RegisterFormatter to copy</param>
75 : RegisterFormatter(const RegisterFormatter& r) = default;
76 : /// <summary>
77 : /// Default Move Constructor
78 : /// </summary>
79 : /// <param name="r">RegisterFormatter rvalue</param>
80 : RegisterFormatter(RegisterFormatter&& r) = default;
81 : uint16_t address; ///< Address of the register
82 : uint32_t value; ///< Value of the register
83 : int descWidth; ///< Display width of description field
84 : std::string description; ///< Description of the register (name)
85 : std::vector<std::string> vals; ///< Human-readable descriptions of register values (bits, etc)
86 :
87 : /// <summary>
88 : /// Default Copy Assignment Operator
89 : /// </summary>
90 : /// <param name="r">RHS</param>
91 : /// <returns>RegisterFormatter regerence</returns>
92 : RegisterFormatter& operator=(const RegisterFormatter& r) = default;
93 :
94 : /// <summary>
95 : /// Write out the RegisterFormatter to the given stream. This function uses setw to make sure that fields for
96 : /// different registers still line up.
97 : /// Format is: " 0xADDR | 0xVALUEXXX | DESCRIPTION: Variable size, minimum of 28 chars | Value 1
98 : /// | Value 2 ..."
99 : /// </summary>
100 : /// <param name="stream">Stream to write register data to</param>
101 : /// <param name="reg">RegisterFormatter to write</param>
102 : /// <returns>Stream reference for continued streaming</returns>
103 0 : friend std::ostream& operator<<(std::ostream& stream, const RegisterFormatter& reg)
104 : {
105 0 : stream << std::hex << std::setfill('0');
106 : { // move address to right-align with values
107 0 : std::string placeholder = "";
108 0 : placeholder.resize(reg.descWidth - 6, ' ');
109 0 : stream << placeholder;
110 0 : }
111 0 : stream << "0x" << std::setw(4) << static_cast<int>(reg.address) << " | 0x" << std::setw(8)
112 0 : << static_cast<int>(reg.value) << " | ";
113 0 : auto tmp = reg.description;
114 0 : tmp.resize(reg.descWidth, ' ');
115 : stream << '\n'
116 0 : << tmp << " | ";
117 :
118 0 : if(!reg.vals.empty())
119 : {
120 0 : auto first = true;
121 0 : for(auto i : reg.vals)
122 : {
123 0 : if(!first)
124 : {
125 0 : std::string placeholder = "";
126 0 : placeholder.resize(reg.descWidth, ' ');
127 : stream << //" " <<
128 0 : placeholder << " | ";
129 0 : }
130 0 : stream << i << std::endl;
131 0 : first = false;
132 0 : }
133 : }
134 : else
135 : {
136 0 : stream << std::endl;
137 : }
138 :
139 0 : return stream;
140 0 : } // end << operator
141 :
142 : // Overloaded operator+ for RegisterFormatter + std::string
143 0 : std::string operator+(const std::string& rhs) const
144 : {
145 0 : std::stringstream ss;
146 0 : ss << *this;
147 0 : return ss.str() + rhs;
148 0 : }
149 :
150 : // Friend function operator+ for std::string + RegisterFormatter
151 0 : friend std::string operator+(const std::string& lhs, const RegisterFormatter& reg)
152 : {
153 0 : std::stringstream ss;
154 0 : ss << reg;
155 0 : return lhs + ss.str();
156 0 : }
157 : }; // end RegisterFormatter class
158 :
159 : /// <summary>
160 : /// The CFOandDTC_Registers class represents the common CFO-and-DTC Register space, and all the methods necessary to read and write those
161 : /// registers. Each register has, at the very least, a read method, a write method, and a RegisterFormatter method
162 : /// which formats the register value in a human-readable way.
163 : /// </summary>
164 : class CFOandDTC_Registers
165 : {
166 : public:
167 : explicit CFOandDTC_Registers();
168 :
169 : virtual ~CFOandDTC_Registers();
170 :
171 : /// <summary>
172 : /// Get a pointer to the device handle
173 : /// </summary>
174 : /// <returns>mu2edev* pointer</returns>
175 0 : mu2edev* GetDevice() { return &device_; }
176 :
177 : /// <summary>
178 : /// Get the current DTC UID for this instance
179 : /// </summary>
180 : /// <returns>The current DTC UID for this instance</returns>
181 0 : std::string getDeviceUID() { return GetDevice()->getDeviceUID(); }
182 :
183 : std::string FormattedRegDump(int width, const std::vector<std::function<RegisterFormatter()>>& regVec);
184 : virtual const std::vector<std::function<RegisterFormatter()>>& getFormattedDumpFunctions() = 0; // pure virtual
185 : virtual const std::vector<std::function<RegisterFormatter()>>& getFormattedSimpleDumpFunctions() = 0; // pure virtual
186 :
187 : //
188 : // Register IO Functions ----------------
189 : //
190 :
191 : virtual void ResetPCIe() = 0; // pure virtual
192 : virtual void FlashLEDs() = 0; // pure virtual
193 :
194 : // Desgin Version/Date Registers
195 : std::string ReadDesignVersion();
196 : RegisterFormatter FormatDesignVersion();
197 : std::string ReadDesignDate(std::optional<uint32_t> val = std::nullopt);
198 : bool isCRVDTCDesignFlavour(std::optional<uint32_t> val = std::nullopt);
199 : bool isNonCRVDTCDesignFlavour(std::optional<uint32_t> val = std::nullopt);
200 : bool isCFODesignFlavour(std::optional<uint32_t> val = std::nullopt);
201 : RegisterFormatter FormatDesignDate();
202 : std::string ReadDesignVersionNumber(std::optional<uint32_t> val = std::nullopt);
203 : std::string ReadDesignLinkSpeed(std::optional<uint32_t> val = std::nullopt);
204 : std::string ReadDesignType(std::optional<uint32_t> val = std::nullopt);
205 :
206 : // Vivado Version Register
207 : virtual std::string ReadVivadoVersionNumber(std::optional<uint32_t> val = std::nullopt);
208 : virtual RegisterFormatter FormatVivadoVersion();
209 :
210 : // FPGA Temperature Register
211 : double ReadFPGATemperature(std::optional<uint32_t> val = std::nullopt);
212 : RegisterFormatter FormatFPGATemperature();
213 :
214 : // FPGA VCCINT Voltage Register
215 : double ReadFPGAVCCINTVoltage(std::optional<uint32_t> val = std::nullopt);
216 : RegisterFormatter FormatFPGAVCCINT();
217 :
218 : // FPGA VCCAUX Voltage Register
219 : double ReadFPGAVCCAUXVoltage(std::optional<uint32_t> val = std::nullopt);
220 : RegisterFormatter FormatFPGAVCCAUX();
221 :
222 : // FPGA VCCBRAM Voltage Register
223 : double ReadFPGAVCCBRAMVoltage(std::optional<uint32_t> val = std::nullopt);
224 : RegisterFormatter FormatFPGAVCCBRAM();
225 :
226 : // FPGA Monitor Alarm Register
227 : bool ReadFPGADieTemperatureAlarm(std::optional<uint32_t> val = std::nullopt);
228 : void ResetFPGADieTemperatureAlarm(std::optional<uint32_t> val = std::nullopt);
229 : bool ReadFPGAAlarms(std::optional<uint32_t> val = std::nullopt);
230 : void ResetFPGAAlarms(std::optional<uint32_t> val = std::nullopt);
231 : bool ReadVCCBRAMAlarm(std::optional<uint32_t> val = std::nullopt);
232 : void ResetVCCBRAMAlarm(std::optional<uint32_t> val = std::nullopt);
233 : bool ReadVCCAUXAlarm(std::optional<uint32_t> val = std::nullopt);
234 : void ResetVCCAUXAlarm(std::optional<uint32_t> val = std::nullopt);
235 : bool ReadVCCINTAlarm(std::optional<uint32_t> val = std::nullopt);
236 : void ResetVCCINTAlarm(std::optional<uint32_t> val = std::nullopt);
237 : bool ReadFPGAUserTemperatureAlarm(std::optional<uint32_t> val = std::nullopt);
238 : void ResetFPGAUserTemperatureAlarm(std::optional<uint32_t> val = std::nullopt);
239 : RegisterFormatter FormatFPGAAlarms();
240 :
241 : // Time Alive Register
242 : RegisterFormatter FormatDeviceTimeAlive();
243 :
244 : // Scratch Register (Device Hash)
245 : RegisterFormatter FormatDeviceHash();
246 :
247 : // CFO and DTC Control Register B31 is Soft Reset
248 : void SoftReset(); // B31
249 : bool ReadSoftReset(std::optional<uint32_t> val = std::nullopt); // B31
250 : void SetPunchEnable(); // B9
251 : void ClearPunchEnable(); // B9
252 : bool ReadPunchEnable(std::optional<uint32_t> val = std::nullopt); // B9
253 : void ResetSERDES(); // B8
254 : bool ReadResetSERDES(std::optional<uint32_t> val = std::nullopt); // B8
255 : void RunCableDelayLoopbackTest(); // B3
256 : void HardReset(); // B0
257 : bool ReadHardReset(std::optional<uint32_t> val = std::nullopt); // B0
258 : void ClearControlRegister(); // 32-bit clear
259 :
260 : // Jitter Attenuator CSR Register
261 : virtual std::bitset<2> ReadJitterAttenuatorSelect(std::optional<uint32_t> val = std::nullopt) = 0; // pure virtual
262 : virtual void SetJitterAttenuatorSelect(std::bitset<2> data, bool alsoResetJA = false) = 0; // pure virtual
263 : virtual bool ReadJitterAttenuatorReset(std::optional<uint32_t> val = std::nullopt) = 0; // pure virtual
264 : virtual bool ReadJitterAttenuatorLocked(std::optional<uint32_t> val = std::nullopt) = 0; // pure virtual
265 : virtual void ResetJitterAttenuator() = 0; // pure virtual
266 : virtual RegisterFormatter FormatJitterAttenuatorCSR() = 0; // pure virtual
267 :
268 : std::bitset<2> ReadJitterAttenuatorSelect(CFOandDTC_Register JAreg, std::optional<uint32_t> val = std::nullopt);
269 : void SetJitterAttenuatorSelect(CFOandDTC_Register JAreg, std::bitset<2> data, bool alsoResetJA);
270 : bool ReadJitterAttenuatorReset(CFOandDTC_Register JAreg, std::optional<uint32_t> val = std::nullopt);
271 : bool ReadJitterAttenuatorLocked(CFOandDTC_Register JAreg, std::optional<uint32_t> val = std::nullopt);
272 : void ResetJitterAttenuator(CFOandDTC_Register JAreg, std::optional<uint32_t> val = std::nullopt);
273 : RegisterFormatter FormatJitterAttenuatorCSR(CFOandDTC_Register JAreg);
274 : // virtual void ConfigureJitterAttenuator() = 0; //pure virtual
275 : void ConfigureJitterAttenuator();
276 :
277 : void WriteSERDESIICInterface(DTC_IICSERDESBusAddress device, uint8_t address, uint8_t data);
278 : uint8_t ReadSERDESIICInterface(DTC_IICSERDESBusAddress device, uint8_t address);
279 : RegisterFormatter FormatSERDESOscillatorParameterLow();
280 : RegisterFormatter FormatSERDESOscillatorParameterHigh();
281 :
282 : // Firefly TX IIC Registers
283 : bool ReadFireflyTXIICInterfaceReset(std::optional<uint32_t> val = std::nullopt);
284 : void ResetFireflyTXIICInterface();
285 : void WriteFireflyTXIICInterface(uint8_t device, uint8_t address, uint8_t data);
286 : uint8_t ReadFireflyTXIICInterface(uint8_t device, uint8_t address);
287 : RegisterFormatter FormatFireflyTXIICControl();
288 : RegisterFormatter FormatFireflyTXIICParameterLow();
289 : RegisterFormatter FormatFireflyTXIICParameterHigh();
290 :
291 : // Firefly RX IIC Registers
292 : bool ReadFireflyRXIICInterfaceReset(std::optional<uint32_t> val = std::nullopt);
293 : void ResetFireflyRXIICInterface();
294 : void WriteFireflyRXIICInterface(uint8_t device, uint8_t address, uint8_t data);
295 : uint8_t ReadFireflyRXIICInterface(uint8_t device, uint8_t address);
296 : RegisterFormatter FormatFireflyRXIICControl();
297 : RegisterFormatter FormatFireflyRXIICParameterLow();
298 : RegisterFormatter FormatFireflyRXIICParameterHigh();
299 :
300 : // Firefly TXRX IIC Registers
301 : bool ReadFireflyTXRXIICInterfaceReset(std::optional<uint32_t> val = std::nullopt);
302 : void ResetFireflyTXRXIICInterface();
303 : void WriteFireflyTXRXIICInterface(uint8_t device, uint8_t address, uint8_t data);
304 : uint8_t ReadFireflyTXRXIICInterface(uint8_t device, uint8_t address);
305 : RegisterFormatter FormatFireflyTXRXIICControl();
306 : RegisterFormatter FormatFireflyTXRXIICParameterLow();
307 : RegisterFormatter FormatFireflyTXRXIICParameterHigh();
308 :
309 : // Firefly CSR Register
310 : bool ReadTXRXFireflyPresent(std::optional<uint32_t> val = std::nullopt);
311 : bool ReadRXFireflyPresent(std::optional<uint32_t> val = std::nullopt);
312 : bool ReadTXFireflyPresent(std::optional<uint32_t> val = std::nullopt);
313 : bool ReadTXRXFireflyInterrupt(std::optional<uint32_t> val = std::nullopt);
314 : bool ReadRXFireflyInterrupt(std::optional<uint32_t> val = std::nullopt);
315 : bool ReadTXFireflyInterrupt(std::optional<uint32_t> val = std::nullopt);
316 : bool ReadTXRXFireflySelect(std::optional<uint32_t> val = std::nullopt);
317 : void SetTXRXFireflySelect(bool select);
318 : bool ReadTXFireflySelect(std::optional<uint32_t> val = std::nullopt);
319 : void SetTXFireflySelect(bool select);
320 : bool ReadRXFireflySelect(std::optional<uint32_t> val = std::nullopt);
321 : void SetRXFireflySelect(bool select);
322 : bool ReadResetTXRXFirefly(std::optional<uint32_t> val = std::nullopt);
323 : void ResetTXRXFirefly();
324 : bool ReadResetTXFirefly(std::optional<uint32_t> val = std::nullopt);
325 : void ResetTXFirefly();
326 : bool ReadResetRXFirefly(std::optional<uint32_t> val = std::nullopt);
327 : void ResetRXFirefly();
328 : RegisterFormatter FormatFireflyCSR();
329 :
330 : uint32_t WriteRegister_(uint32_t data, const CFOandDTC_Register& address);
331 :
332 : protected:
333 : uint32_t ReadRegister_(const CFOandDTC_Register& address);
334 : virtual bool NeedToVerifyRegisterWrite_(const CFOandDTC_Register& address) = 0;
335 : virtual void VerifyRegisterWrite_(const CFOandDTC_Register& address, uint32_t readbackValue, uint32_t dataToWrite) = 0;
336 : bool CFOandDTCVerifyRegisterWrite_(const CFOandDTC_Register& address, uint32_t readbackValue, uint32_t dataToWrite);
337 :
338 : /// <summary>
339 : /// Initializes a RegisterFormatter for the given CFOandDTC_Register
340 : /// </summary>
341 : /// <param name="address">Address of register to format</param>
342 : /// <returns>RegisterFormatter with address and raw value set</returns>
343 0 : RegisterFormatter CreateFormatter(const CFOandDTC_Register& address, bool getValue = true)
344 : {
345 0 : RegisterFormatter form;
346 0 : form.descWidth = formatterWidth_;
347 0 : form.address = address;
348 0 : if(getValue)
349 0 : form.value = ReadRegister_(address);
350 0 : return form;
351 0 : }
352 :
353 : bool GetBit_(const CFOandDTC_Register& address, size_t bit);
354 : void SetBit_(const CFOandDTC_Register& address, size_t bit, bool value);
355 : bool ToggleBit_(const CFOandDTC_Register& address, size_t bit)
356 : {
357 : auto val = GetBit_(address, bit);
358 : SetBit_(address, bit, !val);
359 : return !val;
360 : }
361 :
362 : mu2edev device_; ///< Device handle
363 : int formatterWidth_ = 28; ///< Description field width, in characters (must be initialized or RegisterFormatter can resize to crazy large values!)
364 :
365 : }; // end CFOandDTC_Registers class
366 : } // namespace DTCLib
367 :
368 : #endif // CFO_AND_DTC_REGISTERS_H
|