Loop Timing Witness
Native controller and runtime interfaces; hardware qualification pending
Loading...
Searching...
No Matches
process_protocol.h
Go to the documentation of this file.
1// SPDX-License-Identifier: AGPL-3.0-or-later
2// Commercial license available
3// © Concepts 1996–2026 Miroslav Šotek. All rights reserved.
4// © Code 2020–2026 Miroslav Šotek. All rights reserved.
5// ORCID: 0009-0009-3560-0851
6// Contact: www.anulum.li | protoscience@anulum.li
7// Loop Timing Witness — shared native register process protocol
8
12
13#ifndef WITNESS_PROCESS_PROTOCOL_H
14#define WITNESS_PROCESS_PROTOCOL_H
15
16#include <charconv>
17#include "refusal.h"
18#include <cstdint>
19#include <iostream>
20#include <limits>
21#include <sstream>
22#include <stdexcept>
23#include <string>
24
25namespace witness {
27constexpr std::uint64_t advance_limit = 10000000;
30 unsigned response;
31 std::uint32_t data;
32};
33
35inline std::uint64_t number(std::istream &input, std::uint64_t maximum) {
36 std::string token;
37 if (!(input >> token) || token.find_first_not_of("0123456789") != std::string::npos)
38 throw witness::RuntimeRefused("invalid unsigned argument");
39 std::uint64_t value = 0;
40 const auto parsed = std::from_chars(token.data(), token.data() + token.size(), value);
41 if (parsed.ec != std::errc{} || parsed.ptr != token.data() + token.size() || value > maximum)
42 throw witness::RuntimeRefused("argument outside range");
43 return value;
44}
45
47inline void end_request(std::istream &input) {
48 std::string extra;
49 if (input >> extra)
50 throw witness::RuntimeRefused("unexpected argument");
51}
52
53template <class Device> int serve(Device &device) {
54 std::string line;
55 while (std::getline(std::cin, line)) {
56 std::istringstream input(line);
57 std::string operation;
58 input >> operation;
59 ProtocolReply result{};
60 if (operation == "R") {
61 const auto address = number(input, 255);
62 end_request(input);
63 const auto reply = device.read(static_cast<std::uint8_t>(address));
64 result = {reply.response, reply.data};
65 } else if (operation == "W") {
66 const auto address = number(input, 255);
67 const auto data = number(input, std::numeric_limits<std::uint32_t>::max());
68 const auto strobes = number(input, 15);
69 end_request(input);
70 const auto reply =
71 device.write(static_cast<std::uint8_t>(address), static_cast<std::uint32_t>(data),
72 static_cast<std::uint8_t>(strobes));
73 result = {reply.response, reply.data};
74 result.data = 0;
75 } else if (operation == "T" || operation == "I") {
76 const auto duration = number(input, advance_limit);
77 end_request(input);
78 if (operation == "T")
79 device.advance(duration);
80 else
81 result.data = device.wait_interrupt(duration);
82 } else if (operation == "Q") {
83 end_request(input);
84 return 0;
85 } else
86 throw witness::RuntimeRefused("unknown request");
87 std::cout << result.response << ',' << result.data << ',' << device.time() << std::endl;
88 if (!std::cout)
89 throw witness::RuntimeRefused("cannot write AXI response");
90 }
91 if (!std::cin.eof())
92 throw witness::RuntimeRefused("cannot read AXI request");
93 return 0;
94}
95} // namespace witness
102
103#endif
std::uint64_t number(std::istream &input, std::uint64_t maximum)
void end_request(std::istream &input)
int serve(Device &device)
constexpr std::uint64_t advance_limit