SatCat5
sim_utils.h
Go to the documentation of this file.
1 // Copyright 2021-2025 The Aerospace Corporation.
3 // This file is a part of SatCat5, licensed under CERN-OHL-W v2 or later.
12 
13 #pragma once
14 
15 #include <hal_posix/posix_utils.h>
16 #include <satcat5/cfgbus_core.h>
17 #include <satcat5/cfgbus_interrupt.h>
18 #include <satcat5/ethernet.h>
19 #include <satcat5/interrupts.h>
20 #include <satcat5/ip_stack.h>
21 #include <satcat5/log.h>
22 #include <satcat5/polling.h>
23 #include <satcat5/ptp_source.h>
24 #include <satcat5/timeref.h>
25 #include <string>
26 
27 // Enable CBOR features?
28 #if SATCAT5_CBOR_ENABLE
29 #include <qcbor/qcbor_decode.h>
30 #endif
31 
34 #define SATCAT5_MAKE_STRING(x) (std::string(x, x + sizeof(x)))
35 
39 #define SATCAT5_TEST_START \
40  CHECK(satcat5::irq::pre_test_reset()); \
41  CHECK(satcat5::log::pre_test_reset()); \
42  CHECK(satcat5::poll::pre_test_reset()); \
43  CHECK(satcat5::test::pre_test_reset()); \
44  satcat5::log::ToConsole log;
45 
46 namespace satcat5 {
47  namespace test {
49  bool pre_test_reset();
50 
53  u8 rand_u8();
54  u32 rand_u32();
55  u64 rand_u64();
57 
62  std::string sim_filename(const char* pre, const char* ext);
63 
66  bool write(satcat5::io::Writeable* dst,
67  unsigned nbytes, const u8* data);
68  bool write(satcat5::io::Writeable* dst,
69  const std::string& dat);
71 
76  bool read(satcat5::io::Readable* src,
77  unsigned nbytes, const u8* data);
78  bool read(satcat5::io::Readable* src,
79  const std::string& ref);
80  bool read(satcat5::io::ArrayRead src,
81  const std::string& ref);
83 
85  void write_random_bytes(satcat5::io::Writeable* dst, unsigned nbytes);
87  bool write_random_final(satcat5::io::Writeable* dst, unsigned nbytes);
88 
90  bool read_equal(
92  satcat5::io::Readable* src2);
93 
95  class CborParser {
96  public:
98  explicit CborParser(satcat5::io::Readable* src, bool verbose=false);
99 
102  #if SATCAT5_CBOR_ENABLE
103  QCBORItem get(const char* key) const;
104  QCBORItem get(u32 key) const;
105  #endif
107 
108  protected:
109  u8 m_dat[2048];
110  unsigned m_len;
111  };
112 
117  class CountHelper {
118  public:
120  unsigned count() const {return m_count;}
122  void count_reset() {m_count = 0;}
123  protected:
125  CountHelper() : m_count(0) {}
126  ~CountHelper() {}
127  unsigned m_count;
128  };
129 
131  class CountAlways final
132  : public CountHelper, public satcat5::poll::Always {
133  public:
134  CountAlways() {}
135  void poll_always() override {++m_count;}
136  };
137 
139  class CountArpResponse final
140  : public CountHelper, public satcat5::eth::ArpListener {
141  public:
142  explicit CountArpResponse(satcat5::ip::Dispatch* iface)
143  : m_arp(iface->arp()) {m_arp->add(this);}
144  virtual ~CountArpResponse() {m_arp->remove(this);}
145  protected:
146  void arp_event(const satcat5::eth::MacAddr& mac, const satcat5::ip::Addr& ip) override {++m_count;}
147  void gateway_change(const satcat5::ip::Addr& dstaddr, const satcat5::ip::Addr& gateway) override {}
148  satcat5::eth::ProtoArp* const m_arp;
149  };
150 
152  class CountOnDemand final
153  : public CountHelper, public satcat5::poll::OnDemand {
154  public:
155  CountOnDemand() {}
156  protected:
157  void poll_demand() override {++m_count;}
158  };
159 
161  class CountPingResponse final
162  : public CountHelper, public satcat5::ip::PingListener {
163  public:
165  : m_icmp(iface->icmp()) {m_icmp->add(this);}
166  virtual ~CountPingResponse() {m_icmp->remove(this);}
167  protected:
168  void ping_event(const satcat5::ip::Addr& from, u32 elapsed_usec) {++m_count;}
169  satcat5::ip::ProtoIcmp* const m_icmp;
170  };
171 
173  class CountPtpCallback final
174  : public CountHelper, public satcat5::ptp::Callback {
175  public:
177  void ptp_ready(const satcat5::ptp::Measurement& data) override {++m_count;}
178  };
179 
181  class CountTimer final
182  : public CountHelper, public satcat5::poll::Timer {
183  public:
184  CountTimer() {}
185  void timer_event() override {++m_count;}
186  };
187 
192 
193  // Implement the minimum required API.
194  satcat5::net::Dispatch* iface() const override
195  { return 0; }
196  satcat5::io::Writeable* open_write(unsigned len) override
197  { m_rx.write_abort(); return &m_rx; }
198  void close() override
199  { m_rx.write_finalize(); }
200  bool ready() const
201  { return true; }
202  };
203 
208  public:
209  FastPosixTimer() : satcat5::util::TimeRef(1000000) {}
210  u32 raw() override { return m_timer.raw() << 8; }
211  protected:
213  };
214 
216  class IoEventCounter final
217  : public CountHelper, public satcat5::io::EventListener {
218  public:
219  IoEventCounter() {}
220  protected:
221  void data_rcvd(satcat5::io::Readable* src) {++m_count;}
222  };
223 
226  public:
228  LogProtocol(
229  satcat5::eth::Dispatch* dispatch,
230  const satcat5::eth::MacType& ethertype);
231  // Required API from eth::Protocol.
232  void frame_rcvd(satcat5::io::LimitedRead& src) override;
233  };
234 
239  public:
243  void clear_all(u32 val = 0);
245  void clear_dev(unsigned devaddr, u32 val = 0);
247  void irq_event();
248 
249  protected:
251  u32 m_regs[satcat5::cfg::MAX_TOTAL_REGS];
252  };
253 
256  public:
258  explicit MockInterrupt(satcat5::cfg::ConfigBus* cfg);
259 
261  MockInterrupt(satcat5::cfg::ConfigBus* cfg, unsigned regaddr);
262 
264  void fire();
265 
266  protected:
267  void irq_event() override {++m_count;}
268 
269  satcat5::cfg::ConfigBus* const m_cfg;
270  unsigned m_regaddr;
271  };
272 
276  , public satcat5::io::ArrayRead {
277  public:
279  explicit RandomSource(unsigned len);
283  inline unsigned len() const {return m_len;}
285  inline void notify() {read_notify();}
287  inline const u8* raw() const {return m_buffptr;}
288  protected:
289  const unsigned m_len;
290  };
291 
293  class Statistics {
294  public:
295  Statistics();
296  void add(double x);
297  double mean() const;
298  double msq() const;
299  double rms() const;
300  double std() const;
301  double var() const;
302  double min() const;
303  double max() const;
304  protected:
305  unsigned m_count;
306  double m_sum;
307  double m_sumsq;
308  double m_min;
309  double m_max;
310  };
311 
314  public:
315  // Implement the TimeRef API.
316  TimerSimulation();
317  ~TimerSimulation();
318  u32 raw() override;
319 
321  void sim_step();
323  void sim_wait(unsigned dly_msec);
324 
325  protected:
326  u32 m_tref, m_tnow;
327  };
328  }
329 }
ConfigBus core definitions.
Generic ConfigBus API.
Definition: cfgbus_core.h:124
Memory-mapped local ConfigBus.
Definition: cfgbus_core.h:199
Event-handler for individual ConfigBus interrupts.
Callback interface for responding to ARP and ICMP events.
Definition: eth_arp.h:46
Implemention of "net::Dispatch" for Ethernet frames.
Definition: eth_dispatch.h:21
Protocol handler for Ethernet-to-IPv4 ARP queries and replies.
Definition: eth_arp.h:68
void add(satcat5::eth::ArpListener *evt)
Register an event-listener.
Definition: eth_arp.h:76
void remove(satcat5::eth::ArpListener *evt)
Unregister an event-listener.
Definition: eth_arp.h:79
Accept incoming Ethernet packets by EtherType.
Definition: eth_protocol.h:24
Ephemeral Readable interface for a simple array.
Definition: io_readable.h:206
Event-handler interface for newly received data.
Definition: io_readable.h:43
Limited read of next N bytes.
Definition: io_readable.h:255
PacketBuffer with heap allocation (in packet mode).
Definition: posix_utils.h:128
bool write_finalize() override
Mark end of frame and release temporary working data.
Definition: pkt_buffer.cc:105
void write_abort() override
If possible, abort the current partially-written packet.
Definition: pkt_buffer.cc:89
Abstract API for reading byte-streams and packets.
Definition: io_readable.h:68
void read_notify()
Attempt notification by calling m_callback->data_rcvd().
Definition: io_readable.cc:254
Abstract API for writing byte-streams and packets.
Definition: io_writeable.h:24
Protocol handler and dispatch unit for Internet Protocol v4 (IPv4).
Definition: ip_dispatch.h:43
Callback API for handling "ping" reponses.
Definition: ip_icmp.h:62
Protocol handler for the Internet Control Message Protocol (ICMP).
Definition: ip_icmp.h:81
void remove(satcat5::ip::PingListener *cb)
Add/remove callback handlers for Ping responses.
Definition: ip_icmp.h:118
void add(satcat5::ip::PingListener *cb)
Add/remove callback handlers for Ping responses.
Definition: ip_icmp.h:116
Defines a generic API for sending data to a specific destination, such as a MAC address,...
Definition: net_address.h:30
The "Dispatch" is a generic interface that knows how to read a designated protocol layer and sort inc...
Definition: net_dispatch.h:36
An "Always" object is polled whenever service() is called.
Definition: polling.h:96
An "OnDemand" object is polled only on request.
Definition: polling.h:131
Timer objects are polled after a fixed delay or at a regular interval.
Definition: polling.h:213
PTP callback accepts each complete measurement from the Source.
Definition: ptp_source.h:38
Callback(satcat5::ptp::Source *source)
If a source pointer is provided, call add_callback.
Definition: ptp_source.cc:21
A source for ptp::Measurement events, usually a ptp::Client.
Definition: ptp_source.h:19
A simple CBOR decoder for use in unit tests.
Definition: sim_utils.h:95
QCBORItem get(const char *key) const
Attempt to fetch top-level QCBOR item for the given key.
Definition: sim_utils.cc:208
CborParser(satcat5::io::Readable *src, bool verbose=false)
Copy received message to local buffer.
Definition: sim_utils.cc:157
Count calls to poll_always().
Definition: sim_utils.h:132
void poll_always() override
Child class MUST override this method.
Definition: sim_utils.h:135
Count calls to arp_event().
Definition: sim_utils.h:140
void arp_event(const satcat5::eth::MacAddr &mac, const satcat5::ip::Addr &ip) override
Callback for any announced MAC/IP address pair.
Definition: sim_utils.h:146
void gateway_change(const satcat5::ip::Addr &dstaddr, const satcat5::ip::Addr &gateway) override
Callback for changes to gateway configuration.
Definition: sim_utils.h:147
Base object for counting specific callback or event types.
Definition: sim_utils.h:117
void count_reset()
Reset the counter to zero.
Definition: sim_utils.h:122
CountHelper()
Constructor is only accessible to the child object.
Definition: sim_utils.h:125
unsigned count() const
Returns the current counter value.
Definition: sim_utils.h:120
Count calls to poll_demand().
Definition: sim_utils.h:153
void poll_demand() override
Deferred event handler, called after request().
Definition: sim_utils.h:157
Count calls to ping_event().
Definition: sim_utils.h:162
void ping_event(const satcat5::ip::Addr &from, u32 elapsed_usec)
Callback method when a ping response is received.
Definition: sim_utils.h:168
Count calls to ptp_ready().
Definition: sim_utils.h:174
void ptp_ready(const satcat5::ptp::Measurement &data) override
The child class MUST override this method.
Definition: sim_utils.h:177
Count calls to timer_event().
Definition: sim_utils.h:182
void timer_event() override
Child class MUST override this method.
Definition: sim_utils.h:185
Dummy implementation of net::Address that writes data to a buffer.
Definition: sim_utils.h:189
void close() override
Close any open connections and revert to idle.
Definition: sim_utils.h:198
satcat5::net::Dispatch * iface() const override
Fetch a pointer to the underlying interface.
Definition: sim_utils.h:194
satcat5::io::Writeable * open_write(unsigned len) override
Open a new frame to the designated address and type.
Definition: sim_utils.h:196
bool ready() const
Is this address object ready for use? Child MUST override this method.
Definition: sim_utils.h:200
satcat5::io::PacketBufferHeap m_rx
Received-data buffer is directly accessible.
Definition: sim_utils.h:191
Accelerated version of PosixTimer is 256x real-time.
Definition: sim_utils.h:207
u32 raw() override
Read current time in arbitrary "ticks".
Definition: sim_utils.h:210
Count calls to data_rcvd().
Definition: sim_utils.h:217
void data_rcvd(satcat5::io::Readable *src)
The data_rcvd() callback is polled whenever data is available.
Definition: sim_utils.h:221
Log any received Ethernet traffic of the designated type.
Definition: sim_utils.h:225
LogProtocol(satcat5::eth::Dispatch *dispatch, const satcat5::eth::MacType &ethertype)
Attach this object to an Ethernet interface and set filter.
Definition: sim_utils.cc:239
void frame_rcvd(satcat5::io::LimitedRead &src) override
Dispatch calls frame_rcvd(...) for each incoming frame with with a matching net::Type value.
Definition: sim_utils.cc:247
Mockup for a memory-mapped ConfigBus.
Definition: sim_utils.h:238
void clear_all(u32 val=0)
Clear all registers for all devices.
Definition: sim_utils.cc:259
u32 m_regs[satcat5::cfg::MAX_TOTAL_REGS]
Simulated register-map for up to 256 devices.
Definition: sim_utils.h:251
void clear_dev(unsigned devaddr, u32 val=0)
Clear all registers for the specified device-ID.
Definition: sim_utils.cc:264
void irq_event()
Make event-handler accessible (normally private)
Definition: sim_utils.cc:270
MockConfigBusMmap()
Create this mock interface.
Definition: sim_utils.cc:253
Mockup for a ConfigBus interrupt register.
Definition: sim_utils.h:255
void irq_event() override
Interrupt service routine.
Definition: sim_utils.h:267
void fire()
Trigger a virtual interrupt.
Definition: sim_utils.cc:293
MockInterrupt(satcat5::cfg::ConfigBus *cfg)
No associated register, assumes interrupt has fired.
Definition: sim_utils.cc:274
Readable source for a pseudorandom block of data.
Definition: sim_utils.h:276
const u8 * raw() const
Raw access to the underlying buffer.
Definition: sim_utils.h:287
RandomSource(unsigned len)
Generate a pseudorandom block of data.
Definition: sim_utils.cc:306
satcat5::io::Readable * read()
Prepare to read or re-read data from start of block.
Definition: sim_utils.cc:315
unsigned len() const
Length of the internal block.
Definition: sim_utils.h:283
void notify()
Issue the read_notify / data_rcvd callback.
Definition: sim_utils.h:285
Measure various statistics of a discrete-time series.
Definition: sim_utils.h:293
double m_max
Running maximum.
Definition: sim_utils.h:309
double rms() const
Root-mean-square.
Definition: sim_utils.cc:342
double var() const
Variance.
Definition: sim_utils.cc:346
Statistics()
Create an empty dataset.
Definition: sim_utils.cc:320
double std() const
Standard deviation.
Definition: sim_utils.cc:344
void add(double x)
Add a new data point.
Definition: sim_utils.cc:330
double min() const
Minimum over all inputs.
Definition: sim_utils.cc:348
double msq() const
Mean-square.
Definition: sim_utils.cc:340
double m_sumsq
Sum of squares.
Definition: sim_utils.h:307
double max() const
Maximum over all inputs.
Definition: sim_utils.cc:350
double m_sum
Sum of inputs.
Definition: sim_utils.h:306
unsigned m_count
Number of data points.
Definition: sim_utils.h:305
double m_min
Running minimum.
Definition: sim_utils.h:308
double mean() const
Mean of all data points.
Definition: sim_utils.cc:338
Timekeeper object for granular simulation of elapsed time.
Definition: sim_utils.h:313
void sim_step()
Step forward one millisecond.
Definition: sim_utils.cc:377
void sim_wait(unsigned dly_msec)
Step forward N milliseconds.
Definition: sim_utils.cc:388
u32 raw() override
Read current time in arbitrary "ticks".
Definition: sim_utils.cc:365
Helper object for heap allocation.
Definition: posix_utils.h:37
u8 *const m_buffptr
Pointer to the underlying buffer.
Definition: posix_utils.h:52
Timer object using ctime::clock().
Definition: posix_utils.h:172
u32 raw() override
Read current time in arbitrary "ticks".
Definition: posix_utils.cc:221
The TimeRef API provides access to a monotonic time-counter.
Definition: timeref.h:142
Diagnostic logging to UART and/or Ethernet ports.
Core event-processing loop for SatCat5 software.
Miscellaneous POSIX wrappers (e.g., heap allocation, log to console...)
Define the API for generating ptp::Measurement events.
Platform-agnostic API for interrupt management.
An Ethernet MAC address (with serializable interface).
Definition: eth_header.h:29
EtherType field (uint16) is used a protocol-ID [1536..65535].
Definition: eth_header.h:96
IPv4 address is a 32-bit unsigned integer.
Definition: ip_core.h:15
Timestamps and metadata for a two-way time-transfer handshake.
TimeRef and TimeVal define the API for monotonic timers.