rogue
Loading...
Searching...
No Matches
SrpV0.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::SrpV0Ptr rps::SrpV0::create() {
51 rps::SrpV0Ptr p = std::make_shared<rps::SrpV0>();
52 return (p);
53}
54
56void rps::SrpV0::setup_python() {
57#ifndef NO_PYTHON
58
59 bp::class_<rps::SrpV0, rps::SrpV0Ptr, bp::bases<ris::Master, ris::Slave, rim::Slave>, boost::noncopyable>(
60 "SrpV0",
61 bp::init<>());
62#endif
63}
64
66rps::SrpV0::SrpV0() : ris::Master(), ris::Slave(), rim::Slave(4, 2048) {
67 log_ = rogue::Logging::create("SrpV0");
68}
69
71rps::SrpV0::~SrpV0() {}
72
74bool rps::SrpV0::setupHeader(rim::TransactionPtr tran,
75 uint32_t* header,
76 uint32_t& headerLen,
77 uint32_t& frameLen,
78 bool tx) {
79 bool doWrite = false;
80
81 header[0] = tran->id();
82 header[1] = (tran->address() >> 2) & 0x3FFFFFFF;
83 header[2] = (tran->size() / 4) - 1; // reads
84
85 // Build header for write
86 if (tran->type() == rim::Write || tran->type() == rim::Post) {
87 header[1] |= 0x40000000;
88 frameLen = (tran->size() + WrHeadLen + TailLen);
89 headerLen = WrHeadLen;
90 doWrite = true;
91 } else if (tx) {
92 frameLen = RdHeadLen + TailLen;
93 headerLen = RdHeadLen;
94 } else {
95 frameLen = (tran->size() + RxHeadLen + TailLen);
96 headerLen = RxHeadLen;
97 }
98
99 return doWrite;
100}
101
103void rps::SrpV0::doTransaction(rim::TransactionPtr tran) {
104 ris::FrameIterator fIter;
105 rim::Transaction::iterator tIter;
106 ris::FramePtr frame;
107 uint32_t frameSize;
108 uint32_t header[MaxHeadLen / 4];
109 uint32_t tail[TailLen / 4];
110 uint32_t headerLen;
111 bool doWrite;
112
113 // Size error
114 if ((tran->address() % min()) != 0) {
115 tran->error("Transaction address 0x%" PRIx64 " is not aligned to min size %" PRIu32, tran->address(), min());
116 return;
117 }
118
119 // Size error
120 if ((tran->size() % min()) != 0 || tran->size() < min()) {
121 tran->error("Transaction size 0x%" PRIx32 " is not aligned to min size %" PRIu32, tran->size(), min());
122 return;
123 }
124
125 if (tran->size() > max()) {
126 tran->error("Transaction size %" PRIu32 " exceeds max size %" PRIu32, tran->size(), max());
127 return;
128 }
129
130 // Setup header and frame size
131 doWrite = setupHeader(tran, header, headerLen, frameSize, true);
132
133 // Request frame
134 frame = reqFrame(frameSize, true);
135 frame->setPayload(frameSize);
136
137 // Setup iterators
138 rogue::GilRelease noGil;
139 rim::TransactionLockPtr lock = tran->lock();
140 fIter = frame->begin();
141 tIter = tran->begin();
142
143 // Write header
144 ris::toFrame(fIter, headerLen, header);
145
146 // Write data
147 if (doWrite) ris::toFrame(fIter, tran->size(), tIter);
148
149 // Last field is zero
150 tail[0] = 0;
151 ris::toFrame(fIter, TailLen, tail);
152
153 if (tran->type() == rim::Post)
154 tran->done();
155 else
156 addTransaction(tran);
157
158 log_->debug("Send frame for id=%" PRIu32 ", addr 0x%0.8" PRIx64 ". Size=%" PRIu32 ", type=%" PRIu32
159 ", doWrite=%" PRIu8,
160 tran->id(),
161 tran->address(),
162 tran->size(),
163 tran->type(),
164 doWrite);
165 log_->debug("Send frame for id=%" PRIu32 ", header: 0x%0.8" PRIx32 " 0x%0.8" PRIx32 " 0x%0.8" PRIx32,
166 tran->id(),
167 header[0],
168 header[1],
169 header[2]);
170
171 sendFrame(frame);
172}
173
175void rps::SrpV0::acceptFrame(ris::FramePtr frame) {
176 ris::FrameIterator fIter;
177 rim::Transaction::iterator tIter;
179 uint32_t header[MaxHeadLen / 4];
180 uint32_t tail[TailLen / 4];
181 uint32_t id;
182 uint32_t expHeader[MaxHeadLen / 4];
183 uint32_t expHeadLen;
184 uint32_t expFrameLen;
185 bool doWrite;
186 uint32_t fSize;
187
188 rogue::GilRelease noGil;
189 ris::FrameLockPtr fLock = frame->lock();
190
191 // Drop errored frames
192 if (frame->getError()) {
193 log_->warning("Got errored frame = 0x%" PRIx8, frame->getError());
194 return; // Invalid frame, drop it
195 }
196
197 // Check frame size
198 if ((fSize = frame->getPayload()) < 16) {
199 log_->warning("Got undersized frame size = %" PRIu32, fSize);
200 return; // Invalid frame, drop it
201 }
202
203 // Setup frame iterator
204 fIter = frame->begin();
205
206 // Get the header
207 ris::fromFrame(fIter, RxHeadLen, header);
208
209 // Extract id from frame
210 id = header[0];
211 log_->debug("Got frame id=%" PRIu32 " header: 0x%0.8" PRIx32 " 0x%0.8" PRIx32 " 0x%0.8" PRIx32,
212 id,
213 header[0],
214 header[1],
215 header[2]);
216
217 // Find Transaction
218 if ((tran = getTransaction(id)) == NULL) {
219 log_->warning("Invalid ID frame for id=%" PRIu32, id);
220 return; // Bad id or post, drop frame
221 }
222
223 // Setup transaction iterator
224 rim::TransactionLockPtr lock = tran->lock();
225
226 // Transaction expired
227 if (tran->expired()) {
228 log_->warning("Transaction expired. Id=%" PRIu32, id);
229 return;
230 }
231 tIter = tran->begin();
232
233 // Setup header and frame size
234 doWrite = setupHeader(tran, expHeader, expHeadLen, expFrameLen, false);
235
236 // Check frame size
237 if (fSize != expFrameLen) {
238 log_->warning("Bad receive length for %" PRIu32 " exp=%" PRIu32 ", got=%" PRIu32, id, expFrameLen, fSize);
239 return;
240 }
241
242 // Check header
243 if (memcmp(header, expHeader, RxHeadLen) != 0) {
244 log_->warning("Bad header for %" PRIu32, id);
245 return;
246 }
247
248 // Read tail error value, complete if error is set
249 fIter = frame->end() - TailLen;
250 ris::fromFrame(fIter, TailLen, tail);
251 if (tail[0] != 0) {
252 if (tail[0] & 0x20000)
253 tran->error("Axi bus timeout detected in hardware");
254 else if (tail[0] & 0x10000)
255 tran->error("Axi bus returned fail status in hardware");
256 else
257 tran->error("Non zero status message returned on axi bus in hardware: 0x%" PRIu32, tail[0]);
258 log_->warning("Error detected for ID id=%" PRIu32 ", tail=0x%0.8" PRIu32, id, tail[0]);
259 return;
260 }
261
262 // Copy data if read
263 if (!doWrite) {
264 fIter = frame->begin() + RxHeadLen;
265 ris::fromFrame(fIter, tran->size(), tIter);
266 }
267
268 // Done
269 tran->done();
270}
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::SrpV0 > SrpV0Ptr
Definition SrpV0.h:155