DUNE-DAQ
DUNE Trigger and Data Acquisition software
Loading...
Searching...
No Matches
TimestampGeneratorNode.cpp
Go to the documentation of this file.
1
10
11#include "timing/toolbox.hpp"
12#include "logging/Logging.hpp"
13
14#include <string>
15
16namespace dunedaq {
17namespace timing {
18
19UHAL_REGISTER_DERIVED_NODE(TimestampGeneratorNode)
20
21//-----------------------------------------------------------------------------
22TimestampGeneratorNode::TimestampGeneratorNode(const uhal::Node& node)
23 : TimingNode(node)
24{}
25//-----------------------------------------------------------------------------
26
27//-----------------------------------------------------------------------------
28TimestampGeneratorNode::~TimestampGeneratorNode() {}
29//-----------------------------------------------------------------------------
30
31//-----------------------------------------------------------------------------
32std::string
33TimestampGeneratorNode::get_status(bool print_out) const
34{
35 std::stringstream status;
36 status << "Current timestamp: 0x" << std::hex << read_timestamp() << std::endl;
37 status << "Start timestamp: 0x" << std::hex << read_start_timestamp() << std::endl;
38 status << "SW init timestamp: 0x" << std::hex << read_sw_init_timestamp() << std::endl;
39
40 auto ctrl_subnodes = read_sub_nodes(getNode("csr.ctrl"));
41 status << format_reg_table(ctrl_subnodes, "TS gen ctrl");
42
43 auto stat_subnodes = read_sub_nodes(getNode("csr.stat"));
44 status << format_reg_table(stat_subnodes, "TS gen state");
45
46
47 if (print_out)
48 TLOG() << status.str();
49 return status.str();
50}
51//-----------------------------------------------------------------------------
52
53//-----------------------------------------------------------------------------
54uhal::ValVector<uint32_t> // NOLINT(build/unsigned)
55TimestampGeneratorNode::read_raw_timestamp(bool dispatch) const
56{
57 auto timestamp = getNode("ctr").readBlock(2);
58 if (dispatch)
59 getClient().dispatch();
60 return timestamp;
61}
62//-----------------------------------------------------------------------------
63
64//-----------------------------------------------------------------------------
65uint64_t // NOLINT(build/unsigned)
66TimestampGeneratorNode::read_timestamp() const
67{
68 return tstamp2int(read_raw_timestamp());
69}
70//-----------------------------------------------------------------------------
71
72//-----------------------------------------------------------------------------
73uint64_t // NOLINT(build/unsigned)
74TimestampGeneratorNode::read_start_timestamp() const
75{
76 auto start_ts_l = getNode("csr.tstamp_start_l").read();
77 auto start_ts_h = getNode("csr.tstamp_start_h").read();
78 getClient().dispatch();
79 return (uint64_t)start_ts_l.value() + ((uint64_t)start_ts_h.value() << 32);
80}
81//-----------------------------------------------------------------------------
82
83//-----------------------------------------------------------------------------
84uint64_t // NOLINT(build/unsigned)
85TimestampGeneratorNode::read_sw_init_timestamp() const
86{
87 auto sw_init_ts_l = getNode("csr.tstamp_sw_init_l").read();
88 auto sw_init_ts_h = getNode("csr.tstamp_sw_init_h").read();
89 getClient().dispatch();
90 return (uint64_t)sw_init_ts_l.value() + ((uint64_t)sw_init_ts_h.value() << 32);
91}
92//-----------------------------------------------------------------------------
93
94//-----------------------------------------------------------------------------
95void
96TimestampGeneratorNode::set_timestamp(TimestampSource source) const // NOLINT(build/unsigned)
97{
98 // TODO put somewhere more accessible
99 const uint clock_frequency_hz = 62500000;
100
101 const uint64_t old_timestamp = read_timestamp(); // NOLINT(build/unsigned)
102 TLOG() << "Reading old timestamp: " << format_reg_value(old_timestamp) << ", " << format_timestamp(old_timestamp, clock_frequency_hz);
103
104 getNode("csr.ctrl.rst").write(0x1);
105 getNode("csr.ctrl.tstamp_source_sel").write(source);
106 getClient().dispatch();
107
108 uint64_t now_timestamp;
109 if (source == kSoftware)
110 {
111 now_timestamp = get_milliseconds_since_epoch() * (clock_frequency_hz / 1000); // NOLINT(build/unsigned)
112 }
113 else if (source == kMixed)
114 {
115 now_timestamp = get_seconds_since_epoch() * clock_frequency_hz ; // NOLINT(build/unsigned)
116 }
117 else
118 {
119 throw UnknownTimestampSource(ERS_HERE, source);
120 now_timestamp=0;
121 }
122
123 if (source != kUpstream)
124 {
125 TLOG() << "New software timestamp: " << format_reg_value(now_timestamp) << ", " << format_timestamp(now_timestamp, clock_frequency_hz);
126 // Take the timestamp and split it up
127 uint32_t now_ts_low = (now_timestamp >> 0) & ((1UL << 32) - 1); // NOLINT(build/unsigned)
128 uint32_t now_ts_high = (now_timestamp >> 32) & ((1UL << 32) - 1); // NOLINT(build/unsigned)
129
130 getNode("csr.tstamp_sw_init_l").write(now_ts_low);
131 getNode("csr.tstamp_sw_init_h").write(now_ts_high);
132 }
133
134 getNode("csr.ctrl.rst").write(0x0);
135 getNode("csr.ctrl.load").write(0x1);
136 getNode("csr.ctrl.load").write(0x0);
137 getClient().dispatch();
138
139 auto start = std::chrono::high_resolution_clock::now();
140 while (true) {
141 auto ts_loaded = getNode("csr.stat.tstamp_loaded").read();
142 auto ts_error = getNode("csr.stat.tstamp_error").read();
143 getClient().dispatch();
144
145 TLOG_DEBUG(6) << std::hex << "ts loaded: 0x" << ts_loaded.value() << ", ts error: " << ts_error.value();
146
147 if (ts_loaded.value() && !ts_error.value())
148 {
149 const uint64_t start_ts = read_start_timestamp();
150 TLOG() << "Timestamp initialised with: " << format_reg_value(start_ts) << ", " << format_timestamp(start_ts, clock_frequency_hz);
151 break;
152 }
153
154 auto now = std::chrono::high_resolution_clock::now();
155 auto ms_since_start = std::chrono::duration_cast<std::chrono::milliseconds>(now - start);
156
157 if (ms_since_start.count() > 1000)
158 throw TimestampNotReady(ERS_HERE, ts_loaded.value(), ts_error.value());
159
160 std::this_thread::sleep_for(std::chrono::microseconds(10));
161 }
162
163 const uint64_t new_timestamp = read_timestamp(); // NOLINT(build/unsigned)
164 TLOG() << "Reading new timestamp: " << format_reg_value(new_timestamp) << ", " << format_timestamp(new_timestamp, clock_frequency_hz);
165
166 getClient().dispatch();
167}
168//-----------------------------------------------------------------------------
169
170} // namespace timing
171} // namespace dunedaq
#define ERS_HERE
static int64_t now()
#define TLOG_DEBUG(lvl,...)
Definition Logging.hpp:112
#define TLOG(...)
Definition macro.hpp:22
int64_t get_seconds_since_epoch()
Definition toolbox.cpp:183
int64_t get_milliseconds_since_epoch()
Definition toolbox.cpp:201
std::string format_reg_table(T data, std::string title, std::vector< std::string > headers)
Format reg-value table.
Definition toolbox.hxx:166
std::string format_timestamp(uhal::ValVector< uint32_t > raw_timestamp, uint32_t clock_frequency_hz)
Definition toolbox.cpp:233
uint64_t tstamp2int(uhal::ValVector< uint32_t > raw_timestamp)
Definition toolbox.cpp:175
std::string format_reg_value(T reg_value, uint32_t base)
Definition toolbox.hxx:117
Including Qt Headers.