SatCat5
sim_router2_offload.cc
1 // Copyright 2024 The Aerospace Corporation.
3 // This file is a part of SatCat5, licensed under CERN-OHL-W v2 or later.
5 // Test cases for the router's hardware-accelerated offload interface
6 
7 #include <hal_test/catch.hpp>
8 #include <hal_test/sim_router2_offload.h>
9 
13 using satcat5::udp::PORT_CBOR_TLM;
14 
15 // Define register map (see "router2_common.vhd")
16 static const unsigned REG_TXRX_DAT = 0;
17 static const unsigned REG_PORT_SHDN = 494;
18 static const unsigned REG_TX_MASK = 499;
19 static const unsigned REG_TBL_SIZE = 508;
20 static const unsigned REG_TX_CTRL = 500;
21 static const unsigned REG_RX_IRQ = 510;
22 static const unsigned REG_RX_CTRL = 511;
23 
24 // Simulate the offload port's memory-mapped interface.
25 MockOffload::MockOffload(unsigned devaddr)
26  : m_dev(m_regs + devaddr * satcat5::cfg::REGS_PER_DEVICE)
27 {
28  m_dev[REG_TX_CTRL] = 0; // Initial state = idle
29  m_dev[REG_TBL_SIZE] = 0; // Count hardware ports
30  m_dev[REG_PORT_SHDN] = 0; // All ports are active
31 }
32 
33 MockOffload::~MockOffload() {
34  for (auto a = m_ports.begin() ; a != m_ports.end() ; ++a) {
35  delete *a; // Cleanup of port objects
36  }
37 }
38 
40  unsigned index = m_ports.size();
41  m_ports.push_back(new Port(index, this, dst, src));
42  m_dev[REG_TBL_SIZE] = m_ports.size(); // Update port count
43 }
44 
45 void MockOffload::port_shdn(u32 mask_shdn) {
46  u32 mask_all = (1u << m_ports.size()) - 1;
47  m_dev[REG_PORT_SHDN] = mask_shdn & mask_all;
48 }
49 
51  const u8* tx_src = (const u8*)(m_dev + REG_TXRX_DAT);
52  u32 tx_len = m_dev[REG_TX_CTRL]; // Any outgoing data?
53  u32 tx_mask = m_dev[REG_TX_MASK]; // Copy to each matching port.
54  if (tx_len && tx_mask) {
55  for (auto a = m_ports.begin() ; a != m_ports.end() ; ++a) {
56  Port* const port = *a; // Copy to each matching port.
57  if (tx_mask & port->port_mask()) {
58  port->m_dst->write_bytes(tx_len, tx_src);
59  CHECK(port->m_dst->write_finalize());
60  }
61  }
62  }
63  m_dev[REG_TX_CTRL] = 0; // Frame consumed, clear length.
64 }
65 
66 bool MockOffload::copy_to_hwbuf(unsigned idx, Readable* src) {
67  if (m_dev[REG_RX_CTRL]) return false; // Still occupied?
68  unsigned len = src->get_read_ready(); // Read incoming data
69  src->read_bytes(len, m_dev + REG_TXRX_DAT);
70  m_dev[REG_RX_CTRL] = u32(len + 65536*idx);
71  m_dev[REG_RX_IRQ] = -1; // Interrupt ready for service
72  irq_event(); // Notify interrupt handler
73  m_dev[REG_RX_IRQ] = 0; // Revert to idle
74  return true; // Success
75 }
76 
77 MockOffload::Port::Port(unsigned index, MockOffload* parent, Writeable* dst, Readable* src)
78  : m_index(index), m_parent(parent), m_dst(dst), m_src(src)
79 {
80  m_src->set_callback(this); // Register data_rcvd callback.
81 }
82 
83 MockOffload::Port::~Port() {
84  if (m_src) m_src->set_callback(0); // Unregister callback (our end).
85 }
86 
88  if (m_parent->copy_to_hwbuf(m_index, src))
89  src->read_finalize(); // Copy OK, consume packet.
90 }
91 
93  m_src = 0; // Unregister callback (far end).
94 }
Abstract API for reading byte-streams and packets.
Definition: io_readable.h:68
virtual bool read_bytes(unsigned nbytes, void *dst)
Read 0 or more bytes into a buffer.
Definition: io_readable.cc:190
virtual void read_finalize()
Consume any remaining bytes in this frame, if applicable.
Definition: io_readable.cc:270
virtual void set_callback(satcat5::io::EventListener *callback)
Update registered callback for data_rcvd() events.
Definition: io_readable.cc:39
virtual unsigned get_read_ready() const =0
How many bytes can be read without blocking?
Abstract API for writing byte-streams and packets.
Definition: io_writeable.h:24
void irq_event()
Make event-handler accessible (normally private)
Definition: sim_utils.cc:270
void data_unlink(satcat5::io::Readable *src) override
Unlink this EventListener from the designated source, because the designated Readable object is being...
void data_rcvd(satcat5::io::Readable *src) override
The data_rcvd() callback is polled whenever data is available.
Simulate the router2::Offload port's ConfigBus interface.
void poll_always() override
Child class MUST override this method.
void add_port(satcat5::io::Writeable *dst, satcat5::io::Readable *src)
Link the next hardware port to a destination and source.
void port_shdn(u32 mask_shdn)
Update the reported port-status flags.