61 const std::string &command =
"") {
62 parseParams(paramsPath);
63 selectCommand(command, paramsPath);
64 scratchpadBo = run.get_ctrl_scratchpad_bo();
65 boMap = scratchpadBo.map<uint32_t *>();
66 if (scratchpadBo.size() < scratchpadSizeBytes)
67 throw std::runtime_error(
"ParameterScratchpad: BO size (" +
68 std::to_string(scratchpadBo.size()) +
69 ") < required scratchpad size (" +
70 std::to_string(scratchpadSizeBytes) +
")");
80 const std::string ¶msPath,
81 const std::string &command =
"")
83 parseParams(paramsPath);
84 selectCommand(command, paramsPath);
85 if (bufferSizeBytes < scratchpadSizeBytes)
86 throw std::runtime_error(
"ParameterScratchpad: buffer size (" +
87 std::to_string(bufferSizeBytes) +
88 ") < required scratchpad size (" +
89 std::to_string(scratchpadSizeBytes) +
")");
98 void writeBytes(
const std::string &name,
const void *data,
size_t len) {
100 std::memcpy(&bits, data, std::min(len,
sizeof(bits)));
111 void writeBits(
const std::string &name, uint32_t bits) {
112 if (unslotted.count(name))
113 throw std::runtime_error(
"ParameterScratchpad: no command reads "
115 name +
"', so it has no slot");
116 auto it = paramMap.find(name);
117 if (it == paramMap.end()) {
118 throw std::runtime_error(
"ParameterScratchpad: unknown parameter '" +
121 if (!members.count(name))
122 throw std::runtime_error(
"ParameterScratchpad: command '" + command +
123 "' does not read parameter '" + name +
124 "', whose slot another of its parameters may "
126 if (
auto range = ranges.find(name); range != ranges.end()) {
127 int32_t value =
static_cast<int32_t
>(bits);
128 if (value < range->second.first || value > range->second.second)
129 throw std::invalid_argument(
130 "ParameterScratchpad: value " + std::to_string(value) +
" of '" +
131 name +
"' is outside [" + std::to_string(range->second.first) +
132 ", " + std::to_string(range->second.second) +
"], " +
133 (repeatParams.count(name)
134 ?
"its task's largest repeat count"
135 :
"which keeps its DMA transfers within their buffers"));
136 values[name] = value;
138 uint8_t idx = it->second;
139 uint32_t encoded = bits;
140 if (coreParams.count(name)) {
144 }
else if (repeatParams.count(name)) {
145 encoded = bits << 16;
147 boMap[idx] = encoded;
158 template <
typename T>
159 void write(
const std::string &name, T value) {
160 static_assert(
sizeof(T) <= 4,
"Parameter values must be at most 32 bits");
162 std::memcpy(&bits, &value,
sizeof(T));
170 for (
const JointBound &bound : jointBounds) {
171 int64_t offset = values.at(bound.offset);
172 int64_t length = values.at(bound.length);
173 int64_t end = offset + bound.lengthStep * length;
175 throw std::invalid_argument(
176 "ParameterScratchpad: '" + bound.offset +
177 "' = " + std::to_string(offset) +
" plus " +
178 std::to_string(bound.lengthStep) +
" * '" + bound.length +
179 "' = " + std::to_string(length) +
" is " + std::to_string(end) +
180 ", above " + std::to_string(bound.max) +
181 ", so a DMA transfer using both runs past its buffer");
185#if TEST_UTILS_USE_XRT
190 scratchpadBo.sync(XCL_BO_SYNC_BO_TO_DEVICE);
195 std::vector<std::string>
names()
const {
196 return std::vector<std::string>(members.begin(), members.end());
200 uint32_t
read(
const std::string &name)
const {
201 if (unslotted.count(name))
202 throw std::runtime_error(
"ParameterScratchpad: no command reads "
204 name +
"', so it has no slot");
205 auto it = paramMap.find(name);
206 if (it == paramMap.end()) {
207 throw std::runtime_error(
"ParameterScratchpad: unknown parameter '" +
210 return boMap[it->second];
214#if TEST_UTILS_USE_XRT
215 xrt::bo scratchpadBo;
217 uint32_t *boMap =
nullptr;
218 size_t scratchpadSizeBytes = 0;
219 std::unordered_map<std::string, uint8_t> paramMap;
220 std::unordered_set<std::string> unslotted;
221 std::unordered_set<std::string> coreParams;
222 std::unordered_set<std::string> repeatParams;
223 std::unordered_map<std::string, std::pair<int32_t, int32_t>> ranges;
224 std::unordered_map<std::string, int32_t> values;
226 std::string length, offset;
227 int64_t lengthStep, max;
229 std::vector<JointBound> jointBounds;
231 std::unordered_map<std::string, std::unordered_set<std::string>> commands;
232 std::vector<std::string> commandNames;
234 std::unordered_set<std::string> members;
236 void selectCommand(
const std::string &name,
const std::string &path) {
239 if (commandNames.empty())
240 throw std::runtime_error(
"ParameterScratchpad: '" + path +
241 "' lists no command to hold parameters for");
242 if (commandNames.size() > 1) {
243 std::string available;
244 for (
const std::string &entry : commandNames)
245 available += (available.empty() ?
"" :
", ") + entry;
246 throw std::runtime_error(
247 "ParameterScratchpad: '" + path +
"' lists " +
248 std::to_string(commandNames.size()) +
249 " commands, whose parameters may share slots: name the one this "
250 "scratchpad is for, of " +
253 command = commandNames.front();
255 auto it = commands.find(command);
256 if (it == commands.end())
257 throw std::runtime_error(
"ParameterScratchpad: '" + path +
258 "' has no command '" + name +
"'");
259 members = it->second;
263 for (
size_t i = 0; i < scratchpadSizeBytes / 4; i++) {
268 void parseParams(
const std::string &path) {
269 std::ifstream file(path);
270 if (!file.is_open()) {
271 throw std::runtime_error(
"ParameterScratchpad: cannot open '" + path +
289 unsigned numParams = 0, numSlots = 0;
290 file >> numParams >> numSlots;
292 throw std::runtime_error(
293 "ParameterScratchpad: missing parameter and slot counts in '" + path +
295 scratchpadSizeBytes = numSlots * 4;
297 for (
unsigned i = 0; i < numParams; i++) {
298 std::string name, slot, type, kind, min, max;
299 file >> name >> slot >> type >> kind >> min >> max;
301 throw std::runtime_error(
"ParameterScratchpad: malformed entry " +
302 std::to_string(i) +
" in '" + path +
"'");
303 if (paramMap.count(name) || unslotted.count(name))
304 throw std::runtime_error(
305 "ParameterScratchpad: duplicate parameter name '" + name +
"'");
307 unslotted.insert(name);
309 unsigned long idx = 0;
311 idx = std::stoul(slot);
312 }
catch (
const std::logic_error &) {
313 throw std::runtime_error(
"ParameterScratchpad: malformed slot '" +
314 slot +
"' for parameter '" + name +
315 "' in '" + path +
"'");
318 throw std::runtime_error(
"ParameterScratchpad: state_table_idx " +
319 std::to_string(idx) +
" for '" + name +
320 "' is past the " + std::to_string(numSlots) +
321 " slots of '" + path +
"'");
322 paramMap[name] =
static_cast<uint8_t
>(idx);
324 if (kind !=
"core" && kind !=
"addr" && kind !=
"repeat") {
325 throw std::runtime_error(
"ParameterScratchpad: invalid kind '" + kind +
326 "' for parameter '" + name +
"'");
327 }
else if (kind ==
"core") {
328 coreParams.insert(name);
329 }
else if (kind ==
"repeat") {
330 repeatParams.insert(name);
334 ranges[name] = {std::stoi(min), std::stoi(max)};
335 }
catch (
const std::logic_error &) {
336 throw std::runtime_error(
"ParameterScratchpad: malformed range '" +
337 min +
" " + max +
"' for parameter '" +
338 name +
"' in '" + path +
"'");
344 unsigned numJointBounds = 0;
345 file >> numJointBounds;
347 throw std::runtime_error(
348 "ParameterScratchpad: missing joint bound count in '" + path +
"'");
349 for (
unsigned i = 0; i < numJointBounds; i++) {
351 file >> bound.length >> bound.offset >> bound.lengthStep >> bound.max;
353 throw std::runtime_error(
"ParameterScratchpad: malformed joint bound " +
354 std::to_string(i) +
" in '" + path +
"'");
355 for (
const std::string &name : {bound.length, bound.offset})
356 if (!ranges.count(name))
357 throw std::runtime_error(
"ParameterScratchpad: joint bound " +
358 std::to_string(i) +
" names '" + name +
359 "', which has no range, in '" + path +
"'");
360 jointBounds.push_back(bound);
363 unsigned numCommands = 0;
366 throw std::runtime_error(
367 "ParameterScratchpad: missing command count in '" + path +
"'");
368 for (
unsigned i = 0; i < numCommands; i++) {
370 unsigned numRead = 0;
371 file >> name >> numRead;
372 commandNames.push_back(name);
373 std::unordered_set<std::string> &reads = commands[name];
374 for (
unsigned j = 0; j < numRead; j++) {
377 if (file && !paramMap.count(param))
378 throw std::runtime_error(
"ParameterScratchpad: command '" + name +
379 "' names unknown parameter '" + param +
380 "' in '" + path +
"'");
384 throw std::runtime_error(
"ParameterScratchpad: malformed command " +
385 std::to_string(i) +
" in '" + path +
"'");