ra8-firmware 0.1.0
Bare-metal firmware for the Renesas RA8 family (RA8D2 / RA8P1)
Loading...
Searching...
No Matches
board_periph_doc.c
Go to the documentation of this file.
1
31
32#include <stdint.h>
33#include <stdio.h>
34
35#include "board_periph_block.h"
37
39typedef enum : uint32_t {
40 k_u32_all = 0xFFFFFFFFU,
41 k_u16_full = 0x0000FFFFU,
42} doc_lit_t;
43
45typedef enum : uint64_t {
46 k_doc_base = 0x40311000UL,
47 k_doc_span = 0x20UL,
48 k_doc_off_docr = 0x00UL,
49 k_doc_off_dosr = 0x04UL,
50 k_doc_off_doscr = 0x08UL,
51 k_doc_off_dodir = 0x0CUL,
54} doc_map_t;
55
57typedef enum : uint32_t {
62 k_doc_dopcf = 0x01U,
64
66typedef enum : uint32_t {
71
73typedef enum : uint32_t {
76
78typedef struct {
79 uint8_t docr;
80 uint8_t dopcf;
81 uint32_t dodsr0;
82 uint32_t dodsr1;
83 uint32_t ops;
85
87
99{
100 return ((s_doc.docr & (uint8_t)k_doc_dobw_mask) != 0U) ? (uint32_t)k_u32_all
101 : (uint32_t)k_u16_full;
102}
103
113RA8_INTERNAL static void internal_doc_apply(uint32_t dodir)
114{
115 const uint32_t mode = (uint32_t)(s_doc.docr & (uint8_t)k_doc_oms_mask);
116 const uint32_t mask = internal_doc_width_mask();
117 const uint32_t in = dodir & mask;
118 const uint32_t cur = s_doc.dodsr0 & mask;
119 if (mode == (uint32_t)k_doc_mode_add) {
120 const uint32_t sum = cur + in;
121 s_doc.dopcf = ((sum & ~mask) != 0U) ? (uint8_t)k_doc_dopcf : s_doc.dopcf;
122 s_doc.dodsr0 = sum & mask;
123 } else if (mode == (uint32_t)k_doc_mode_subtract) {
124 s_doc.dopcf = (in > cur) ? (uint8_t)k_doc_dopcf : s_doc.dopcf; /* borrow */
125 s_doc.dodsr0 = (cur - in) & mask;
126 } else {
127 /* Compare: DCSEL selects the relation that latches DOPCF. DCSEL=1 matches
128 * on equality; everything else (including 0) latches on mismatch. */
129 const uint32_t dcsel =
130 (uint32_t)((s_doc.docr & (uint8_t)k_doc_dcsel_mask) >> (uint32_t)k_doc_dcsel_shift);
131 const bool equal = (in == cur);
132 const bool hit = (dcsel == 1U) ? equal : !equal;
133 if (hit) {
134 s_doc.dopcf = (uint8_t)k_doc_dopcf;
135 }
136 }
137 s_doc.ops++;
138}
139
149{
150 s_doc.docr = 0U;
151 s_doc.dopcf = 0U;
152 s_doc.dodsr0 = 0U;
153 s_doc.dodsr1 = 0U;
154 s_doc.ops = 0U;
155}
156
170RA8_INTERNAL static uint64_t internal_doc_read(uc_engine* uc, uint64_t addr, unsigned size)
171{
172 (void)uc;
173 (void)size;
174 const uint64_t off = addr - (uint64_t)k_doc_base;
175 if (off == (uint64_t)k_doc_off_docr) {
176 return s_doc.docr;
177 }
178 if (off == (uint64_t)k_doc_off_dosr) {
179 return s_doc.dopcf;
180 }
181 if (off == (uint64_t)k_doc_off_dodsr0) {
182 return s_doc.dodsr0;
183 }
184 if (off == (uint64_t)k_doc_off_dodsr1) {
185 return s_doc.dodsr1;
186 }
187 return 0U;
188}
189
202RA8_INTERNAL static void
203internal_doc_write(uc_engine* uc, uint64_t addr, unsigned size, uint64_t value)
204{
205 (void)uc;
206 (void)size;
207 const uint64_t off = addr - (uint64_t)k_doc_base;
208 if (off == (uint64_t)k_doc_off_docr) {
209 s_doc.docr = (uint8_t)value;
210 } else if (off == (uint64_t)k_doc_off_doscr) {
211 if (((uint8_t)value & (uint8_t)k_doc_dopcf) != 0U) {
212 s_doc.dopcf = 0U; /* DOPCFCL clears the flag. */
213 }
214 } else if (off == (uint64_t)k_doc_off_dodir) {
215 internal_doc_apply((uint32_t)value);
216 } else if (off == (uint64_t)k_doc_off_dodsr0) {
217 s_doc.dodsr0 = (uint32_t)value; /* Seed operand A. */
218 } else if (off == (uint64_t)k_doc_off_dodsr1) {
219 s_doc.dodsr1 = (uint32_t)value;
220 }
221}
222
232{
233 if (s_doc.ops == 0U) {
234 return; /* Untouched: stay quiet. */
235 }
236 (void)priv_emu_io_errf(" DOC : OMS=%u DODSR0=0x%08X DOPCF=%u ops=%u\n",
237 (unsigned)(s_doc.docr & (uint8_t)k_doc_oms_mask),
238 s_doc.dodsr0,
239 (unsigned)s_doc.dopcf,
240 s_doc.ops);
241}
242
245 .base = (uint32_t)k_doc_base,
246 .span = (uint32_t)k_doc_span,
247 .order = (uint32_t)k_doc_block_order,
248 .read = internal_doc_read,
250 .tick = nullptr,
251 .reset = internal_doc_reset,
252 .report = internal_doc_report,
253 .name = "DOC",
254};
255
257[[gnu::constructor]] RA8_INTERNAL static void internal_doc_block_register(void)
258{
260}
Decentralized peripheral-block registry for the board emulator core.
void board_periph_register_block(const board_periph_block_t *block)
Register a peripheral block's descriptor with the core registry.
@ k_u32_all
32-bit all-ones.
doc_field_t
DOCR / DOSR field masks (ra8_doc_regs.h).
@ k_doc_dobw_mask
DOBW: 0 = 16-bit, 1 = 32-bit.
@ k_doc_dcsel_mask
DCSEL[2:0] compare condition.
@ k_doc_dcsel_shift
DCSEL field position.
@ k_doc_dopcf
DOSR DOPCF flag / DOSCR clear.
@ k_doc_oms_mask
OMS[1:0] mode select.
doc_map_t
DOC block geometry (ra8_doc_regs.h).
@ k_doc_span
Register window.
@ k_doc_base
DOC base (HUM Ch 57.2).
@ k_doc_off_doscr
DOSCR status clear, 8b.
@ k_doc_off_docr
DOCR control (OMS/DOBW/DCSEL), 8b.
@ k_doc_off_dodsr1
DODSR1 upper threshold.
@ k_doc_off_dodsr0
DODSR0 reference / result.
@ k_doc_off_dosr
DOSR status (DOPCF), 8b.
@ k_doc_off_dodir
DODIR data input.
doc_lit_t
Result-width masks for the DOC unit (32-bit vs 16-bit mode).
@ k_u16_full
16-bit result mask.
static RA8_INTERNAL void internal_doc_write(uc_engine *uc, uint64_t addr, unsigned size, uint64_t value)
MMIO write inside the DOC window.
doc_mode_t
DOCR.OMS operation modes.
@ k_doc_mode_compare
Compare (set DOPCF on DCSEL hit).
@ k_doc_mode_subtract
DODSR0 -= DODIR.
@ k_doc_mode_add
DODSR0 += DODIR.
static doc_state_t s_doc
static RA8_INTERNAL void internal_doc_apply(uint32_t dodir)
Apply one DODIR operand to DODSR0 per the current DOCR.OMS mode.
static RA8_INTERNAL void internal_doc_report(void)
End-of-run DOC section: mode, last result, op count.
static RA8_INTERNAL uint64_t internal_doc_read(uc_engine *uc, uint64_t addr, unsigned size)
MMIO read inside the DOC window.
static RA8_INTERNAL uint32_t internal_doc_width_mask(void)
Width mask selected by DOCR.DOBW (0 = 16-bit, 1 = 32-bit).
static RA8_INTERNAL void internal_doc_reset(void)
Reset the DOC unit to power-on state.
doc_order_t
Per-tick order slot for the DOC block (relative order only).
@ k_doc_block_order
After the CRC block; report order.
static RA8_INTERNAL void internal_doc_block_register(void)
Register the DOC block before main (host constructor).
static const board_periph_block_t s_k_doc_block
DOC block descriptor (self-registered with the core).
Bounded raw-descriptor I/O seam for the RA8 emulator.
emu_io_result_t priv_emu_io_errf(const char *format,...)
Format bounded text and write it to the injected error descriptor.
-proof
#define RA8_INTERNAL
Marker that a function is intended to be static (file-local).
A modelled peripheral block's self-description for the core registry.
DOC register state.
uint8_t docr
DOCR shadow (OMS/DOBW/DCSEL).
uint32_t ops
Operations performed.
uint32_t dodsr0
Reference / running result.
uint8_t dopcf
DOSR.DOPCF latch.
uint32_t dodsr1
Upper threshold (compare).