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 if (source != kUpstream)
118 {
119 throw UnknownTimestampSource(ERS_HERE, source);
120 }
121
122 if (source != kUpstream)
123 {
124 TLOG() << "New software timestamp: " << format_reg_value(now_timestamp) << ", " << format_timestamp(now_timestamp, clock_frequency_hz);
125 // Take the timestamp and split it up
126 uint32_t now_ts_low = (now_timestamp >> 0) & ((1UL << 32) - 1); // NOLINT(build/unsigned)
127 uint32_t now_ts_high = (now_timestamp >> 32) & ((1UL << 32) - 1); // NOLINT(build/unsigned)
128
129 getNode("csr.tstamp_sw_init_l").write(now_ts_low);
130 getNode("csr.tstamp_sw_init_h").write(now_ts_high);
131 }
132
133 getNode("csr.ctrl.rst").write(0x0);
134 getNode("csr.ctrl.load").write(0x1);
135 getNode("csr.ctrl.load").write(0x0);
136 getClient().dispatch();
137
138 auto start = std::chrono::high_resolution_clock::now();
139 while (true) {
140 auto ts_loaded = getNode("csr.stat.tstamp_loaded").read();
141 auto ts_error = getNode("csr.stat.tstamp_error").read();
142 getClient().dispatch();
143
144 TLOG_DEBUG(6) << std::hex << "ts loaded: 0x" << ts_loaded.value() << ", ts error: " << ts_error.value();
145
146 if (ts_loaded.value() && !ts_error.value())
147 {
148 const uint64_t start_ts = read_start_timestamp();
149 TLOG() << "Timestamp initialised with: " << format_reg_value(start_ts) << ", " << format_timestamp(start_ts, clock_frequency_hz);
150 break;
151 }
152
153 auto now = std::chrono::high_resolution_clock::now();
154 auto ms_since_start = std::chrono::duration_cast<std::chrono::milliseconds>(now - start);
155
156 if (ms_since_start.count() > 1000)
157 throw TimestampNotReady(ERS_HERE, ts_loaded.value(), ts_error.value());
158
159 std::this_thread::sleep_for(std::chrono::microseconds(10));
160 }
161
162 const uint64_t new_timestamp = read_timestamp(); // NOLINT(build/unsigned)
163 TLOG() << "Reading new timestamp: " << format_reg_value(new_timestamp) << ", " << format_timestamp(new_timestamp, clock_frequency_hz);
164
165 getClient().dispatch();
166}
167//-----------------------------------------------------------------------------
168
169} // namespace timing
170} // 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
The DUNE-DAQ namespace.
Definition DataStore.hpp:57