rogue
Loading...
Searching...
No Matches
SrpV3.cpp
Go to the documentation of this file.
1
17#include "rogue/Directives.h"
18
20
21#include <inttypes.h>
22#include <stdint.h>
23
24#include <cstring>
25#include <memory>
26#include <thread>
27
28#include "rogue/GilRelease.h"
29#include "rogue/Logging.h"
39
40namespace rps = rogue::protocols::srp;
43
44#ifndef NO_PYTHON
45 #include <boost/python.hpp>
46namespace bp = boost::python;
47#endif
48
50rps::SrpV3Ptr rps::SrpV3::create() {
51 rps::SrpV3Ptr p = std::make_shared<rps::SrpV3>();
52 return (p);
53}
54
56void rps::SrpV3::setup_python() {
57#ifndef NO_PYTHON
58 bp::class_<rps::SrpV3, rps::SrpV3Ptr, bp::bases<ris::Master, ris::Slave, rim::Slave>, boost::noncopyable>(
59 "SrpV3",
60 bp::init<>())
61 .def("_setHardwareTimeout", &rps::SrpV3::setHardwareTimeout);
62 bp::implicitly_convertible<rps::SrpV3Ptr, ris::MasterPtr>();
63 bp::implicitly_convertible<rps::SrpV3Ptr, ris::SlavePtr>();
64 bp::implicitly_convertible<rps::SrpV3Ptr, rim::SlavePtr>();
65#endif
66}
67
69rps::SrpV3::SrpV3() : ris::Master(), ris::Slave(), rim::Slave(4, 4096) {
70 log_ = rogue::Logging::create("SrpV3");
71}
72
74rps::SrpV3::~SrpV3() {}
75
77void rps::SrpV3::setHardwareTimeout(uint8_t val) {
78 timeout_ = val;
79}
80
82bool rps::SrpV3::setupHeader(rim::TransactionPtr tran, uint32_t* header, uint32_t& frameLen, bool tx) {
83 bool doWrite = true;
84
85 // Bits 7:0 of first 32-bit word are version
86 header[0] = 0x03;
87
88 // Bits 9:8: 0x0 = read, 0x1 = write, 0x2 = posted write
89 switch (tran->type()) {
90 case rim::Write:
91 header[0] |= 0x100;
92 break;
93 case rim::Post:
94 header[0] |= 0x200;
95 break;
96 default:
97 doWrite = false;
98 break; // Read or verify
99 }
100
101 // Bits 13:10 not used in gen frame
102 // Bit 14 = ignore mem resp
103 // Bit 23:15 = Unused
104 // Bit 31:24 = timeout count
105 header[0] |= (timeout_ << 24 | 0x00000000);
106
107 // Header word 1, transaction ID
108 header[1] = tran->id();
109
110 // Header word 2, lower address
111 header[2] = tran->address() & 0xFFFFFFFF;
112
113 // Header word 3, upper address
114 header[3] = (tran->address() >> 32) & 0xFFFFFFFF;
115
116 // Header word 4, request size
117 header[4] = tran->size() - 1;
118
119 // Determine frame length
120 frameLen = HeadLen;
121
122 // Transmit with write data
123 if (tx && doWrite) frameLen += tran->size();
124
125 // Receive frames
126 else if (!tx)
127 frameLen += tran->size() + TailLen;
128
129 return doWrite;
130}
131
133void rps::SrpV3::doTransaction(rim::TransactionPtr tran) {
134 ris::FrameIterator fIter;
135 rim::Transaction::iterator tIter;
136 ris::FramePtr frame;
137 uint32_t frameSize;
138 uint32_t header[HeadLen / 4];
139 bool doWrite;
140
141 // Size error
142 if ((tran->address() % min()) != 0) {
143 tran->error("Transaction address 0x%" PRIx64 " is not aligned to min size %" PRIu32, tran->address(), min());
144 return;
145 }
146
147 // Size error
148 if ((tran->size() % min()) != 0 || tran->size() < min()) {
149 tran->error("Transaction size 0x%" PRIx32 " is not aligned to min size %" PRIu32, tran->size(), min());
150 return;
151 }
152
153 if (tran->size() > max()) {
154 tran->error("Transaction size %" PRIu32 " exceeds max size %" PRIu32, tran->size(), max());
155 return;
156 }
157
158 // Compute header and frame size
159 doWrite = setupHeader(tran, header, frameSize, true);
160
161 // Request frame
162 frame = reqFrame(frameSize, true);
163 frame->setPayload(frameSize);
164
165 // Setup iterators
166 rogue::GilRelease noGil;
167 rim::TransactionLockPtr lock = tran->lock();
168 fIter = frame->begin();
169 tIter = tran->begin();
170
171 // Write header
172 ris::toFrame(fIter, HeadLen, header);
173
174 // Write data
175 if (doWrite) ris::toFrame(fIter, tran->size(), tIter);
176
177 if (tran->type() == rim::Post)
178 tran->done();
179 else
180 addTransaction(tran);
181
182 log_->debug("Send frame for id=%" PRIu32 ", addr 0x%0.8" PRIx64 ". Size=%" PRIu32 ", type=%" PRIu32,
183 tran->id(),
184 tran->address(),
185 tran->size(),
186 tran->type());
187 log_->debug("Send frame for id=%" PRIu32 ", header: 0x%0.8" PRIx32 " 0x%0.8" PRIx32 " 0x%0.8" PRIx32
188 " 0x%0.8" PRIx32 " 0x%0.8" PRIx32,
189 tran->id(),
190 header[0],
191 header[1],
192 header[2],
193 header[3],
194 header[4]);
195
196 sendFrame(frame);
197}
198
200void rps::SrpV3::acceptFrame(ris::FramePtr frame) {
201 ris::FrameIterator fIter;
202 rim::Transaction::iterator tIter;
204 uint32_t header[HeadLen / 4];
205 uint32_t expHeader[HeadLen / 4];
206 uint32_t expFrameLen;
207 uint32_t tail[TailLen / 4];
208 uint32_t id;
209 bool doWrite;
210 uint32_t fSize;
211
212 rogue::GilRelease noGil;
213 ris::FrameLockPtr frLock = frame->lock();
214
215 if (frame->getError()) {
216 log_->warning("Got errored frame = 0x%" PRIx8, frame->getError());
217 return; // Invalid frame, drop it
218 }
219
220 // Check frame size
221 if ((fSize = frame->getPayload()) < (HeadLen + TailLen)) {
222 log_->warning("Got undersized frame size = %" PRIu32, fSize);
223 return; // Invalid frame, drop it
224 }
225
226 // Get the tail
227 fIter = frame->end() - TailLen;
228 ris::fromFrame(fIter, TailLen, tail);
229
230 // Get the header
231 fIter = frame->begin();
232 ris::fromFrame(fIter, HeadLen, header);
233
234 // Extract the id
235 id = header[1];
236 log_->debug("Got frame id=%" PRIu32 ", header: 0x%0.8" PRIx32 " 0x%0.8" PRIx32 " 0x%0.8" PRIx32 " 0x%0.8" PRIx32
237 " 0x%0.8" PRIx32 " tail: 0x%0.8" PRIx32,
238 id,
239 header[0],
240 header[1],
241 header[2],
242 header[3],
243 header[4],
244 tail[0]);
245
246 // Find Transaction
247 if ((tran = getTransaction(id)) == NULL) {
248 log_->warning("Failed to find transaction id=%" PRIu32, id);
249 return; // Bad id or post, drop frame
250 }
251
252 // Lock transaction
253 rim::TransactionLockPtr lock = tran->lock();
254
255 // Transaction expired
256 if (tran->expired()) {
257 tran->error("Transaction expired: Id=%" PRIu32
258 " (increase root->timeout value if this ID matches a previous timeout message)",
259 id);
260 return;
261 }
262 tIter = tran->begin();
263
264 // Setup expect header and length
265 doWrite = setupHeader(tran, expHeader, expFrameLen, false);
266
267 // Check header
268 if (((header[0] & 0xFFFFC3FF) != expHeader[0]) || (header[1] != expHeader[1]) || (header[2] != expHeader[2]) ||
269 (header[3] != expHeader[3]) || (header[4] != expHeader[4])) {
270 log_->warning("Bad header for %" PRIu32, id);
271 tran->error("Received SRPV3 message did not match expected protocol");
272 return;
273 }
274
275 // Check tail
276 if (tail[0] != 0) {
277 if (tail[0] & 0x2000)
278 tran->error("FPGA register bus lockup detected in hardware. Power cycle required.");
279 else if (tail[0] & 0x0100)
280 tran->error("FPGA register bus timeout detected in hardware");
281 else
282 tran->error("Non zero status message returned on fpga register bus in hardware: 0x%" PRIx32, tail[0]);
283 log_->warning("Error detected for ID id=%" PRIu32 ", tail=0x%0.8" PRIx32, id, tail[0]);
284 return;
285 }
286
287 // Verify frame size, drop frame
288 if ((fSize != expFrameLen) || (header[4] + 1) != tran->size()) {
289 log_->warning("Size mismatch id=%" PRIu32 ". fsize=%" PRIu32 ", exp=%" PRIu32 ", tsize=%" PRIu32
290 ", header=%" PRIu32,
291 id,
292 fSize,
293 expFrameLen,
294 tran->size(),
295 header[4] + 1);
296 tran->error("Received SRPV3 message had a header size mismatch");
297 return;
298 }
299
300 // Copy data if read
301 if (!doWrite) ris::fromFrame(fIter, tran->size(), tIter);
302
303 tran->done();
304}
RAII helper that releases the Python GIL for a scope.
Definition GilRelease.h:36
static std::shared_ptr< rogue::Logging > create(const std::string &name, bool quiet=false)
Creates a logger instance.
Definition Logging.cpp:60
Random-access byte iterator across a Frame payload.
std::shared_ptr< rogue::interfaces::memory::TransactionLock > TransactionLockPtr
Shared pointer alias for TransactionLock.
static const uint32_t Write
Memory write transaction type.
Definition Constants.h:43
std::shared_ptr< rogue::interfaces::memory::Transaction > TransactionPtr
Shared pointer alias for Transaction.
static const uint32_t Post
Memory posted write transaction type.
Definition Constants.h:50
static void fromFrame(rogue::interfaces::stream::FrameIterator &iter, uint32_t size, void *dst)
Copies bytes from a frame iterator to a destination pointer.
std::shared_ptr< rogue::interfaces::stream::Frame > FramePtr
Shared pointer alias for Frame.
Definition Frame.h:549
static void toFrame(rogue::interfaces::stream::FrameIterator &iter, uint32_t size, void *src)
Copies bytes from a source pointer into a frame iterator.
std::shared_ptr< rogue::interfaces::stream::FrameLock > FrameLockPtr
Shared pointer alias for FrameLock.
Definition FrameLock.h:110
std::shared_ptr< rogue::protocols::srp::SrpV3 > SrpV3Ptr
Definition SrpV3.h:164