SatCat5
sim_cfgbus.cc
1 // Copyright 2021-2025 The Aerospace Corporation.
3 // This file is a part of SatCat5, licensed under CERN-OHL-W v2 or later.
5 
6 #include <cstdio>
7 #include <hal_test/sim_cfgbus.h>
8 
14 
15 CfgRegister::CfgRegister()
16  : m_rd_mode(ReadMode::UNSAFE)
17  , m_rd_dval(0)
18  , m_rd_count(0)
19  , m_wr_count(0)
20 {
21  // Nothing else to initialize.
22 }
23 
25  m_rd_mode = ReadMode::STRICT;
26  m_rd_dval = 0;
27 }
28 
30  m_rd_mode = ReadMode::ECHO;
31  m_rd_dval = 0;
32 }
33 
35  m_rd_mode = ReadMode::CONSTANT;
36  m_rd_dval = val;
37 }
38 
39 void CfgRegister::read_push(u32 val) {
40  m_queue_rd.push_back(val);
41 }
42 
43 unsigned CfgRegister::read_count() const
44  { return m_rd_count; }
45 unsigned CfgRegister::read_queue() const
46  { return m_queue_wr.size(); }
47 unsigned CfgRegister::write_count() const
48  { return m_wr_count; }
49 unsigned CfgRegister::write_queue() const
50  { return m_queue_wr.size(); }
51 
53  if (m_queue_wr.empty()) {
54  fprintf(stderr, "Write queue empty.\n");
55  return 0; // Error
56  } else {
57  u32 next = m_queue_wr.front();
58  m_queue_wr.pop_front();
59  return next; // Next item from queue
60  }
61 }
62 
63 IoStatus CfgRegister::read(unsigned regaddr, u32& rdval) {
64  ++m_rd_count;
65  if (m_rd_mode == ReadMode::UNSAFE) {
66  // Read from an undefined register.
67  fprintf(stderr, "Unsafe register read: %u\n", regaddr);
68  rdval = 0; // Memory access error
69  return IoStatus::BUSERROR;
70  } else if (m_queue_rd.empty()) {
71  // If the read-queue is empty, return the specified default.
72  // (In strict mode, this is an error condition.)
73  if (m_rd_mode == ReadMode::STRICT)
74  fprintf(stderr, "Unqueued register read: %u\n", regaddr);
75  rdval = m_rd_dval; // Constant or echo mode
76  return IoStatus::OK;
77  } else {
78  // If anything is in the queue, return the next value.
79  u32 next = m_queue_rd.front();
80  m_queue_rd.pop_front();
81  rdval = next; // Next item from queue
82  return IoStatus::OK;
83  }
84 }
85 
86 IoStatus CfgRegister::write(unsigned regaddr, u32 wrval) {
87  ++m_wr_count;
88  if (m_rd_mode == ReadMode::UNSAFE) {
89  fprintf(stderr, "Unsafe register write: %u\n", regaddr);
90  return IoStatus::BUSERROR;
91  } else if (m_rd_mode == ReadMode::ECHO) {
92  m_rd_dval = wrval;
93  }
94  m_queue_wr.push_back(wrval);
95  return IoStatus::OK;
96 }
97 
99  for (unsigned a = 0 ; a < REGS_PER_DEVICE ; ++a)
100  reg[a].read_default_none();
101 }
102 
104  for (unsigned a = 0 ; a < REGS_PER_DEVICE ; ++a)
105  reg[a].read_default_echo();
106 }
107 
108 void CfgDevice::read_default(u32 val) {
109  for (unsigned a = 0 ; a < REGS_PER_DEVICE ; ++a)
110  reg[a].read_default(val);
111 }
112 
113 IoStatus CfgDevice::read(unsigned regaddr, u32 &rdval) {
114  regaddr = regaddr % REGS_PER_DEVICE;
115  return reg[regaddr].read(regaddr, rdval);
116 }
117 
118 IoStatus CfgDevice::write(unsigned regaddr, u32 wrval) {
119  regaddr = regaddr % REGS_PER_DEVICE;
120  return reg[regaddr].write(regaddr, wrval);
121 }
122 
123 IoStatus CfgSpace::read(unsigned regaddr, u32& val) {
124  auto& cfg = get_device(regaddr / REGS_PER_DEVICE);
125  return cfg.read(regaddr % REGS_PER_DEVICE, val);
126 }
127 
128 IoStatus CfgSpace::write(unsigned regaddr, u32 wrval) {
129  auto& cfg = get_device(regaddr / REGS_PER_DEVICE);
130  return cfg.write(regaddr % REGS_PER_DEVICE, wrval);
131 }
132 
133 void CfgSpace::add_device(unsigned devaddr, ConfigBus& cfg) {
134  m_devs.emplace(devaddr, cfg);
135 }
136 
138  auto it = m_devs.find(devaddr);
139  return (it == m_devs.end()) ? m_undef : it->second;
140 }
IoStatus
Status codes for ConfigBus read/write operations.
Definition: cfgbus_core.h:99
const unsigned REGS_PER_DEVICE
Fixed ConfigBus gateware interface parameters.
Definition: cfgbus_core.h:45
Generic ConfigBus API.
Definition: cfgbus_core.h:124
Simulated bank of ConfigBus registers.
Definition: sim_cfgbus.h:94
satcat5::cfg::IoStatus read(unsigned regaddr, u32 &val) override
Basic single-register read operation.
Definition: sim_cfgbus.cc:113
void read_default_none()
Set read mode for all contained registers.
Definition: sim_cfgbus.cc:98
void read_default_echo()
Set read mode for all contained registers.
Definition: sim_cfgbus.cc:103
void read_default(u32 val)
Set read mode for all contained registers.
Definition: sim_cfgbus.cc:108
satcat5::cfg::IoStatus write(unsigned regaddr, u32 wrval) override
Basic single-register write operation.
Definition: sim_cfgbus.cc:118
Simulation of a single ConfigBus register.
Definition: sim_cfgbus.h:30
void read_default(u32 val)
Set default value for reads when the queue is empty.
Definition: sim_cfgbus.cc:34
unsigned read_count() const
Total reads from this register.
Definition: sim_cfgbus.cc:43
void read_push(u32 val)
Queue up a read for this register.
Definition: sim_cfgbus.cc:39
satcat5::cfg::IoStatus read(unsigned regaddr, u32 &rdval) override
Basic single-register read operation.
Definition: sim_cfgbus.cc:63
u32 write_pop()
Pop one value from the recent write queue.
Definition: sim_cfgbus.cc:52
void read_default_echo()
Set default value for reads when the queue is empty.
Definition: sim_cfgbus.cc:29
satcat5::cfg::IoStatus write(unsigned regaddr, u32 wrval) override
Basic single-register write operation.
Definition: sim_cfgbus.cc:86
void read_default_none()
Set default value for reads when the queue is empty.
Definition: sim_cfgbus.cc:24
unsigned read_queue() const
Number of queued responses.
Definition: sim_cfgbus.cc:45
unsigned write_count() const
Total writes to this register.
Definition: sim_cfgbus.cc:47
Simulated ConfigBus address space with many devices.
Definition: sim_cfgbus.h:122
satcat5::cfg::IoStatus read(unsigned regaddr, u32 &val) override
Basic single-register read operation.
Definition: sim_cfgbus.cc:123
satcat5::cfg::ConfigBus & get_device(unsigned devaddr)
Access the designated device handler, by device-address.
Definition: sim_cfgbus.cc:137
void add_device(unsigned devaddr, satcat5::cfg::ConfigBus &cfg)
Register a handler for a specific device address.
Definition: sim_cfgbus.cc:133
satcat5::cfg::IoStatus write(unsigned regaddr, u32 wrval) override
Basic single-register write operation.
Definition: sim_cfgbus.cc:128
General-purpose ConfigBus emulator utilities.