rggen-systemrdl 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/LICENSE +21 -0
- data/README.md +66 -0
- data/lib/rggen/systemrdl/converter/addrmap.rb +49 -0
- data/lib/rggen/systemrdl/converter/base.rb +165 -0
- data/lib/rggen/systemrdl/converter/field.rb +514 -0
- data/lib/rggen/systemrdl/converter/mem.rb +23 -0
- data/lib/rggen/systemrdl/converter/reg.rb +29 -0
- data/lib/rggen/systemrdl/converter/regfile.rb +29 -0
- data/lib/rggen/systemrdl/global/ignore_precedence.rb +27 -0
- data/lib/rggen/systemrdl/loader.rb +21 -0
- data/lib/rggen/systemrdl/version.rb +7 -0
- data/lib/rggen/systemrdl.rb +20 -0
- data/notes/bit_field_type_mapping.md +105 -0
- data/notes/bit_field_type_matrix.md +80 -0
- data/notes/external_reg_regfile_mapping.md +37 -0
- data/notes/interrupt_aggregation_policy.md +50 -0
- data/notes/precedence_handling_policy.md +38 -0
- data/notes/systemrdl_rggen_gap_analysis.md +132 -0
- data/notes/systemrdl_to_rggen_mapping.md +264 -0
- data/notes/systemrdl_to_rggen_todo.md +34 -0
- data/notes/udp_handling_policy.md +181 -0
- metadata +80 -0
|
@@ -0,0 +1,264 @@
|
|
|
1
|
+
# SystemRDL → RgGen Mapping: Design Notes
|
|
2
|
+
|
|
3
|
+
This document records confirmed design decisions for the SystemRDL front-end to RgGen
|
|
4
|
+
register-map conversion. The SystemRDL support is an add-on feature; perfect coverage is a
|
|
5
|
+
non-goal. Deferred / not-yet-supported items are tracked separately in `systemrdl_to_rggen_TODO.md`.
|
|
6
|
+
|
|
7
|
+
## Scope
|
|
8
|
+
- Root `addrmap` → RgGen register_block
|
|
9
|
+
- `regfile` → RgGen register_file
|
|
10
|
+
- `reg` → RgGen register
|
|
11
|
+
- `field` → RgGen bit_field
|
|
12
|
+
- Nested `addrmap` → RgGen `external` region on the enclosing map; the addrmap is also converted
|
|
13
|
+
to its own register_block through the normal flow (see "External components" below).
|
|
14
|
+
- External `reg`/`regfile` → ERROR in the first release (deferred; see "External components").
|
|
15
|
+
- `mem` → RgGen `external` register (region reservation only; see "mem" below).
|
|
16
|
+
|
|
17
|
+
## Layer correspondence
|
|
18
|
+
|
|
19
|
+
| SystemRDL | RgGen |
|
|
20
|
+
| ---------------------- | ------------------------------ |
|
|
21
|
+
| root `addrmap` | register_block |
|
|
22
|
+
| `regfile` | register_file |
|
|
23
|
+
| `reg` | register |
|
|
24
|
+
| `field` | bit_field |
|
|
25
|
+
| nested `addrmap` | `external` region + its own register_block |
|
|
26
|
+
| external `reg`/`regfile` | ERROR (first release; deferred) |
|
|
27
|
+
| `mem` | `external` register (region reservation only) |
|
|
28
|
+
|
|
29
|
+
## Array handling & name conversion
|
|
30
|
+
- `reg`, `regfile`, and `addrmap` can be arrays. **`field` is never an array**: in a
|
|
31
|
+
field declaration `foo[4]` specifies bit WIDTH (and `foo[7:0]` specifies msb:lsb), NOT an array
|
|
32
|
+
subscript. So the flatten/`__`-subscript handling below does not apply to fields; a field's
|
|
33
|
+
`[...]` maps to bit_assignment `lsb`/`width` instead (see field layer).
|
|
34
|
+
- Arrays are flattened into individual elements. No reconstruction back into RgGen
|
|
35
|
+
`size` / `sequence_size`.
|
|
36
|
+
- Subscripts are rendered into the name with a double-underscore `__` separator:
|
|
37
|
+
- `foo[0]` → `foo__0`
|
|
38
|
+
- multi-dimensional `foo[1][0]` → `foo__1__0` (all dimensions use `__`, consistently)
|
|
39
|
+
- Conversion-time validation: any SystemRDL instance name (all layers, arrayed or not) that
|
|
40
|
+
itself contains `__` is an ERROR. This reserves `__` exclusively as the array-expansion
|
|
41
|
+
separator, eliminating name-collision ambiguity at its root (rather than merely
|
|
42
|
+
lowering collision probability).
|
|
43
|
+
- SystemRDL lexical rules (spec 5.1.1) permit `__` in identifiers; this restriction is an
|
|
44
|
+
extra constraint imposed only when using the RgGen-conversion add-on feature.
|
|
45
|
+
- Post-conversion duplicate-name detection is delegated to RgGen's existing validation; the
|
|
46
|
+
converter does NOT re-implement duplicate checking.
|
|
47
|
+
|
|
48
|
+
## addrmap (root) → register_block
|
|
49
|
+
|
|
50
|
+
| RgGen register_block | SystemRDL addrmap | Conversion / notes |
|
|
51
|
+
| -------------------- | ------------------------ | ------------------ |
|
|
52
|
+
| `name` | instance name (`name`) | Apply `__` restriction check. Root addrmap is non-arrayed, so no subscript conversion normally. |
|
|
53
|
+
| `byte_size` | addrmap occupied size | Uses the occupied-size value provided by the gem directly (front-end fix requested; see feedback). The converter does not compute it from child placement. |
|
|
54
|
+
| `bus_width` | — | No corresponding concept in SystemRDL. Not mapped; deferred to RgGen config. |
|
|
55
|
+
| `protocol` | — | No corresponding concept in SystemRDL. Not mapped; deferred to RgGen config. |
|
|
56
|
+
| `comment` | `desc` property | Used directly. `display_name` (SystemRDL `name` property) is a short label, not used for comment. |
|
|
57
|
+
|
|
58
|
+
### addrmap: properties that cause an ERROR
|
|
59
|
+
These SystemRDL properties have no corresponding concept in RgGen. If encountered, the converter
|
|
60
|
+
errors out rather than silently ignoring them (silent drop would change the design intent).
|
|
61
|
+
- `sharedextbus` — combines multiple external components into a single bus interface (creates a
|
|
62
|
+
single set of control signals for the whole addrmap instead of per-component). Only meaningful
|
|
63
|
+
when the addrmap contains external components. This is about external-component bus-interface
|
|
64
|
+
generation, NOT the 13.5 multiple-view/bridge feature. RgGen has no feature to combine external
|
|
65
|
+
interfaces into one, so this is a **permanent ERROR** (independent of the external-scope
|
|
66
|
+
decision): even once external components are supported, RgGen still cannot merge their
|
|
67
|
+
interfaces, so `sharedextbus` remains unsupported.
|
|
68
|
+
- bridge / multiple-view related properties (spec 13.5) in general — e.g. `bridge`. No RgGen concept.
|
|
69
|
+
- `bigendian` / `littleendian` — ERROR if either is explicitly true. Even `littleendian` is an
|
|
70
|
+
error: although RgGen is also little-endian, its word-placement model for registers spanning
|
|
71
|
+
multiple words differs from SystemRDL 17.3.2 (Byte ordering), so passing `littleendian` through
|
|
72
|
+
by name would misplace words. If neither is specified, pass through using RgGen's default
|
|
73
|
+
(little-endian).
|
|
74
|
+
- Residual caveat: for registers that span multiple words (`regwidth > accesswidth`), the
|
|
75
|
+
word-placement model differs from SystemRDL 17.3.2 (Byte ordering). This difference is a
|
|
76
|
+
confirmed property of the conversion, not a maybe. The converter does NOT detect or correct
|
|
77
|
+
it; instead, the README states this word-ordering difference as a documented limitation of
|
|
78
|
+
the add-on conversion.
|
|
79
|
+
- `rsvdset` / `rsvdsetX` — control the read value of reserved / unassigned regions (whether
|
|
80
|
+
unassigned bits read as 1, or as X/undefined). RgGen has no mechanism to specify the read value
|
|
81
|
+
of unassigned regions, so there is nowhere to map these. ERROR if set.
|
|
82
|
+
- `msb0` — ERROR if set (true). `msb0` reverses bit numbering so that `regwidth-1` is the least
|
|
83
|
+
significant bit (spec 13.4.1), the opposite of the default `lsb0` mode. RgGen assumes `lsb0`
|
|
84
|
+
numbering; under `msb0` the field `lsb`/`msb` positions would be interpreted in reverse and
|
|
85
|
+
would be misplaced, so the mode cannot be represented. (`lsb0` is the default and needs no
|
|
86
|
+
action; it is not an error. `msb0` and `lsb0` are mutually exclusive per spec 13.4.1.)
|
|
87
|
+
Inference of `msb0` from the first field's explicit bit indices (spec 13.4.2) is unsupported by
|
|
88
|
+
the front-end, so only an explicitly set `msb0` property reaches the converter.
|
|
89
|
+
|
|
90
|
+
### addrmap: properties that are IGNORED (safe to drop)
|
|
91
|
+
- `errextbus` — indicates the (external) addrmap instance has an error input. RgGen's
|
|
92
|
+
`rggen_bus_if` has an error input by default, so RgGen always satisfies the `errextbus`
|
|
93
|
+
behavior. Ignoring the property therefore does not lose design intent (unlike the error-listed
|
|
94
|
+
properties above).
|
|
95
|
+
- `accesswidth` — IGNORED. RgGen derives access width from its `bus_width` (RgGen config, not
|
|
96
|
+
mapped from SystemRDL). Safe to ignore: if `accesswidth` disagrees with `bus_width`, the
|
|
97
|
+
resulting addresses violate RgGen's `address % bus_width == 0` rule and are caught by the later
|
|
98
|
+
address check.
|
|
99
|
+
|
|
100
|
+
## reg → register
|
|
101
|
+
|
|
102
|
+
| RgGen register | SystemRDL reg | Conversion / notes |
|
|
103
|
+
| ---------------- | ----------------------- | ------------------ |
|
|
104
|
+
| `name` | instance name (`name`) | Apply `__` restriction check; arrayed regs are flattened with `__` subscript conversion into individual registers. |
|
|
105
|
+
| `offset_address` | `address` property | Direct copy. Both RgGen `offset_address` and SystemRDL `address` are offsets from the block start, so they coincide and `address` is used as-is. |
|
|
106
|
+
| `size` | (basically unused) | Arrays are flattened, so repetition `size` is not used. First release: single element. |
|
|
107
|
+
| `type` | (fixed `default`) | Normal regs map to `default`. See register-type notes below. |
|
|
108
|
+
| `comment` | `desc` property | Used directly. |
|
|
109
|
+
|
|
110
|
+
### register-type notes
|
|
111
|
+
- `default` — normal reg. Supported (fixed for first release).
|
|
112
|
+
- `external` — an external `reg` (`Reg#external` = true) is NOT supported in the first release →
|
|
113
|
+
ERROR. See the "External components" section (deferred design in `external_reg_regfile_mapping.md`).
|
|
114
|
+
- `indirect` — **permanently not applicable.** RgGen `indirect` multiplexes multiple registers
|
|
115
|
+
at one address, selected by index bit fields. SystemRDL has NO indirect-access mechanism, and
|
|
116
|
+
SystemRDL `alias` is a DIFFERENT concept (a second name/address onto the same storage, not
|
|
117
|
+
index-based multiplexing). `indirect` can therefore never be produced by the conversion.
|
|
118
|
+
- `reserved` / `maskable` / `rw` — SystemRDL-side trigger for these is TBD; not used in first release.
|
|
119
|
+
|
|
120
|
+
### reg: properties that cause an ERROR
|
|
121
|
+
These SystemRDL reg properties have no corresponding concept in RgGen. If encountered, the
|
|
122
|
+
converter errors out rather than silently ignoring them.
|
|
123
|
+
- `shared` — shared component (spec 13.5, bridges / multiple-view address maps). RgGen has a
|
|
124
|
+
single-address-space-per-block model with no multiple-view/shared-storage concept, so there is
|
|
125
|
+
nowhere to map this. Even once the front-end supports it, the converter must error.
|
|
126
|
+
|
|
127
|
+
### reg: properties that are IGNORED (safe to drop)
|
|
128
|
+
- `errextbus` — indicates the (external) regfile has an error input. Same rationale as the
|
|
129
|
+
addrmap `errextbus`: RgGen's `rggen_bus_if` has an error input by default, so ignoring it loses
|
|
130
|
+
no design intent.
|
|
131
|
+
- `accesswidth` — IGNORED (same rationale as addrmap: bus_width is RgGen config; a mismatch is
|
|
132
|
+
caught by the later `address % bus_width == 0` check).
|
|
133
|
+
|
|
134
|
+
## regfile → register_file
|
|
135
|
+
|
|
136
|
+
| RgGen register_file | SystemRDL regfile | Conversion / notes |
|
|
137
|
+
| ------------------- | ------------------------ | ------------------ |
|
|
138
|
+
| `name` | instance name (`name`) | Apply `__` restriction check; arrayed regfiles are flattened with `__` subscript conversion. |
|
|
139
|
+
| `offset_address` | `address` property | Direct copy (offset from the parent). |
|
|
140
|
+
| `size` | (not used) | Arrays are flattened, so repetition `size` is not used. |
|
|
141
|
+
| `comment` | `desc` property | Used directly. |
|
|
142
|
+
|
|
143
|
+
### regfile: properties handled like addrmap/reg
|
|
144
|
+
- `sharedextbus` — ERROR (no RgGen feature to merge external interfaces; same as addrmap).
|
|
145
|
+
- `errextbus` — IGNORED (rggen_bus_if has an error input by default; same as addrmap/reg).
|
|
146
|
+
- `accesswidth` — IGNORED (same as addrmap/reg; bus_width is RgGen config, mismatch caught by the address check).
|
|
147
|
+
- `external` — an external regfile is NOT supported in the first release → ERROR. See the
|
|
148
|
+
"External components" section (deferred design in `external_reg_regfile_mapping.md`).
|
|
149
|
+
|
|
150
|
+
## field → bit_field
|
|
151
|
+
|
|
152
|
+
Bit positions are resolved by the front-end during elaboration, so the model's `msb` / `lsb`
|
|
153
|
+
give the final positions.
|
|
154
|
+
|
|
155
|
+
| RgGen bit_field | SystemRDL field | Conversion / notes |
|
|
156
|
+
| -------------------------------- | ----------------------- | ------------------ |
|
|
157
|
+
| `name` | instance name (`name`) | Apply `__` restriction check. No subscript conversion (fields are not arrays). |
|
|
158
|
+
| `bit_assignment` `lsb` | `lsb` | Direct copy (front-end-assigned). |
|
|
159
|
+
| `bit_assignment` `width` | field width (model accessor) | Use a `width` accessor on the model (front-end fix requested; see feedback) rather than computing `msb - lsb + 1` on the converter side. |
|
|
160
|
+
| `bit_assignment` `sequence_size` / `step` | — | Not used; fields are not arrays. |
|
|
161
|
+
| `initial_value` | `reset` property | Maps the reset value (constant only). If `reset` is absent, `initial_value` is left unset — the converter does NOT substitute 0; RgGen's own validation errors if a type that requires an initial value has none. A `reset` given as a reference (to another field) is unsupported → ERROR. A user-defined `resetsignal` is unsupported → ERROR. See field error list below. |
|
|
162
|
+
| `type` | (sw/hw/onread/onwrite/hwset/hwclr/swwe/swwel/we/swacc/singlepulse/… combination) | Main conversion. See `bit_field_type_mapping.md` for the full RgGen-type ← SystemRDL-property table and the cross-cutting property policies. |
|
|
163
|
+
| `reference` | instance reference (e.g. `next`, swwe/swwel/hwclr/hwset target) | Only SystemRDL **instance** references map to RgGen `reference`. **Property** references → ERROR. Mask-purpose references (`rc`/`w0c`/`w1c`/`wc`) are not specifiable from SystemRDL. See `bit_field_type_mapping.md`. |
|
|
164
|
+
| `comment` | `desc` property | Used directly. |
|
|
165
|
+
|
|
166
|
+
### field: properties / values that cause an ERROR
|
|
167
|
+
- `reset` given as a **reference** (to another field's value) rather than a constant — RgGen
|
|
168
|
+
`initial_value` accepts a constant value only and has no dynamic/reference reset, so a
|
|
169
|
+
reference reset cannot be represented. ERROR.
|
|
170
|
+
- `resetsignal` (user-defined reset signal) — RgGen does not support user-defined reset signals,
|
|
171
|
+
so specifying `resetsignal` is unsupported. ERROR.
|
|
172
|
+
- Properties/values with no corresponding RgGen feature — ERROR if used: `wel`, `swmod`, `anded`,
|
|
173
|
+
`ored`, `xored`, `hwenable`, `hwmask`, `paritycheck`, `ruser` (onread=ruser),
|
|
174
|
+
`wuser` (onwrite=wuser), and `hw = rw1` / `hw = w1` (hardware-side write-once).
|
|
175
|
+
- Property reference used anywhere — ERROR. SystemRDL references come in two kinds: instance
|
|
176
|
+
references and property references (e.g. `other->prop`). RgGen supports instance references
|
|
177
|
+
only. (Applies wherever a reference is used: `ro`/next, rwl/rwe swwe/swwel, rwc/rws hwclr/hwset,
|
|
178
|
+
etc.)
|
|
179
|
+
- Combinations that fit no named RgGen type — ERROR in the first release (`custom` is not used
|
|
180
|
+
yet; see `bit_field_type_mapping.md`).
|
|
181
|
+
|
|
182
|
+
### field: checks delegated to RgGen core (not done by the converter)
|
|
183
|
+
- Bit-field overlap — two or more fields at the same bit position in a register (SystemRDL allows
|
|
184
|
+
this when read/write are mutually exclusive). The converter does NOT detect this; it just emits
|
|
185
|
+
each field's `bit_assignment`, and RgGen's own bit_assignment validation rejects the overlap
|
|
186
|
+
(RgGen has no merged read-only+write-only field — `rowo` is not supported). Listed here so the
|
|
187
|
+
behavior is documented, but it is not a converter-side error.
|
|
188
|
+
|
|
189
|
+
### field: precedence handling
|
|
190
|
+
Handled per a project-level "precedence ignore mode" flag (see rggen/rggen-systemrdl
|
|
191
|
+
`notes/precedence_handling_policy.md`). RgGen fixes hardware precedence; the SystemRDL default is
|
|
192
|
+
`sw`. The flag is set via RgGen configuration, not per-field/per-register.
|
|
193
|
+
- Ignore mode OFF (default): field with effective `precedence=sw` → ERROR; `precedence=hw` →
|
|
194
|
+
accepted. (Elaboration cannot tell an explicit value from a defaulted one, so `sw` is rejected
|
|
195
|
+
regardless; users set `default precedence = hw;` at a scope.)
|
|
196
|
+
- Ignore mode ON: `precedence` is not consulted; all fields generated with hw precedence, no
|
|
197
|
+
diagnostic.
|
|
198
|
+
|
|
199
|
+
## External components
|
|
200
|
+
|
|
201
|
+
### Nested addrmap → external region
|
|
202
|
+
|
|
203
|
+
A nested (non-root) `addrmap` instance represents an independent implementation boundary.
|
|
204
|
+
(`AddrMap` has no `external` property; external/internal does not apply to an addrmap itself, so
|
|
205
|
+
the trigger is structural: any addrmap below the root counts.)
|
|
206
|
+
|
|
207
|
+
For a nested addrmap, the only thing this conversion does is reserve its address region on the
|
|
208
|
+
enclosing map as an RgGen `external` register (its `address`/`size` come from the model).
|
|
209
|
+
|
|
210
|
+
The addrmap's own contents do NOT need a special carve-out step here: an addrmap is itself an RTL
|
|
211
|
+
generation unit with its own definition, so running that definition through the normal
|
|
212
|
+
register_block conversion (the same path used for the root addrmap) produces its register_block.
|
|
213
|
+
|
|
214
|
+
`bridge` is NOT part of the trigger; it only indicates whether the external boundary involves
|
|
215
|
+
bus/protocol conversion.
|
|
216
|
+
|
|
217
|
+
### External reg / external regfile → ERROR (first release)
|
|
218
|
+
|
|
219
|
+
An external `reg` (`Reg#external` = true) and an external `regfile` (`RegFile#external` = true)
|
|
220
|
+
are NOT supported in the first release and are ERRORs. Silently dropping them would lose design
|
|
221
|
+
intent, so the converter errors out rather than ignoring the external boundary.
|
|
222
|
+
|
|
223
|
+
The conversion scheme worked out for them — reserve the region on the enclosing map and wrap the
|
|
224
|
+
contents in a separately-converted register_block (RgGen cannot generate at reg/regfile
|
|
225
|
+
granularity, so the wrapping is required) — is recorded separately in
|
|
226
|
+
`external_reg_regfile_mapping.md` for when the feature is picked up later.
|
|
227
|
+
|
|
228
|
+
|
|
229
|
+
## mem → external register
|
|
230
|
+
|
|
231
|
+
A SystemRDL `mem` is mapped to an RgGen `external` register. `external` is exactly the RgGen
|
|
232
|
+
construct intended for this purpose: it reserves an address region whose contents are provided by
|
|
233
|
+
a user implementation. The memory contents are therefore not generated by RgGen (and not by the
|
|
234
|
+
converter); the converter only reserves the region.
|
|
235
|
+
|
|
236
|
+
Because the contents are a user implementation, a `mem` is NOT handled like the "External
|
|
237
|
+
components" above: it produces no carved-out register_block, only the region reservation on the
|
|
238
|
+
enclosing map.
|
|
239
|
+
|
|
240
|
+
| RgGen external | SystemRDL mem | Conversion / notes |
|
|
241
|
+
| -------------- | ---------------------- | ------------------ |
|
|
242
|
+
| `name` | instance name (`name`) | Apply `__` restriction check; arrayed mems are flattened with `__` subscript conversion. |
|
|
243
|
+
| `offset_address` | `address` property | Direct copy (offset from the parent), same as reg/regfile. |
|
|
244
|
+
| `size` | model `size` (byte size), converted | Element count in `bus_width` units; see below. |
|
|
245
|
+
| `comment` | `desc` property | Used directly. |
|
|
246
|
+
|
|
247
|
+
### mem: size calculation
|
|
248
|
+
RgGen's `external` `size` is an element count expressed in `bus_width` units (how many
|
|
249
|
+
`bus_width`-wide accesses the region occupies), NOT a byte size. The front-end already provides
|
|
250
|
+
the mem's occupied byte size as the model's `size`, so the converter does not compute it from
|
|
251
|
+
`memwidth`/`mementries`; it only converts that byte size into `bus_width` units:
|
|
252
|
+
|
|
253
|
+
```
|
|
254
|
+
size = byte_size / (bus_width / 8)
|
|
255
|
+
```
|
|
256
|
+
|
|
257
|
+
where `byte_size` is the model's `size` (the front-end computes it from `entry_width` — `memwidth`
|
|
258
|
+
rounded up to a power-of-two number of bits — times `mementries`).
|
|
259
|
+
|
|
260
|
+
- `bus_width` is an RgGen config value, not taken from SystemRDL (same policy as `accesswidth`,
|
|
261
|
+
which is IGNORED elsewhere).
|
|
262
|
+
- If `byte_size` is not an integer multiple of `bus_width / 8`, the region cannot be expressed as
|
|
263
|
+
a whole number of `bus_width`-wide elements → ERROR.
|
|
264
|
+
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
# SystemRDL → RgGen Mapping: TODO
|
|
2
|
+
|
|
3
|
+
Not-yet-supported / deferred items. Confirmed design decisions live in
|
|
4
|
+
`systemrdl_to_rggen_mapping.md`.
|
|
5
|
+
|
|
6
|
+
## Deferred
|
|
7
|
+
|
|
8
|
+
### SystemRDL `alias` handling (scope decision)
|
|
9
|
+
- RgGen `alias` register support is tracked in rggen/rggen#287. The original proposal there
|
|
10
|
+
includes field-level attribute overrides (N:1 decoder-to-bitfield connection, per-field access
|
|
11
|
+
attribute arrays).
|
|
12
|
+
- Current stance: full support is not worth the RTL-generation complexity. If implemented at all,
|
|
13
|
+
scope is limited to address multiplexing and register-level r/w switching only. Field-level
|
|
14
|
+
attribute re-assignment will NOT be done.
|
|
15
|
+
- Consequence for SystemRDL conversion: SystemRDL `alias` per spec 10.5.1 rule (e) allows
|
|
16
|
+
per-field overrides of `sw`/`onread`/`onwrite`/`rclr`/`rset`/`woclr`/`woset`. Because the
|
|
17
|
+
intended RgGen scope stops at register-level r/w, SystemRDL alias inputs that vary attributes
|
|
18
|
+
per field cannot be fully represented → such inputs are out of scope (not supported / not
|
|
19
|
+
losslessly convertible). Note this is separate from RgGen `indirect`, which is permanently
|
|
20
|
+
not applicable (see mapping notes).
|
|
21
|
+
|
|
22
|
+
## Open dependencies
|
|
23
|
+
|
|
24
|
+
### `counter` / `intr` field types
|
|
25
|
+
- SystemRDL has `counter` and `intr`, but the front-end does not support them yet → out of
|
|
26
|
+
first-release scope. The RgGen target type is deferred (not decided now); record only as
|
|
27
|
+
"unsupported, front-end does not support them yet".
|
|
28
|
+
|
|
29
|
+
### `custom` bit_field type (held)
|
|
30
|
+
- First release does not use RgGen `custom`. Property combinations that fit no named RgGen type
|
|
31
|
+
are errors in v1. Using `custom` to catch such combinations is possible but the verification
|
|
32
|
+
cost (confirming each combination is faithfully representable) is too high for v1 → future work.
|
|
33
|
+
|
|
34
|
+
|
|
@@ -0,0 +1,181 @@
|
|
|
1
|
+
# UDP Handling Policy for rggen-systemrdl
|
|
2
|
+
|
|
3
|
+
## Background
|
|
4
|
+
|
|
5
|
+
SystemRDL provides a User-Defined Property (UDP) mechanism (Section 15 of the SystemRDL 2.0 specification) that allows tools and users to extend the language with custom properties beyond the standard set. In practice, UDPs are widely used by various SystemRDL tools to implement features that are not covered by the standard:
|
|
6
|
+
|
|
7
|
+
- PeakRDL-regblock uses UDPs such as `buffer_writes`, `wbuffer_trigger`, and others to express features like write-buffered registers, read-buffered registers, signed fields, and fixed-point fields.
|
|
8
|
+
- Commercial EDA tools define their own UDPs for vendor-specific features such as encrypted registers, TMR registers, and shadow registers.
|
|
9
|
+
- Internal company conventions often introduce custom UDPs to capture domain-specific requirements.
|
|
10
|
+
|
|
11
|
+
Since UDPs are vendor-specific and not portable across tools, any SystemRDL adapter must define a clear policy for how to handle them. This document describes the UDP handling policy adopted by rggen-systemrdl.
|
|
12
|
+
|
|
13
|
+
## Design Principles
|
|
14
|
+
|
|
15
|
+
### 1. Core Adapter Handles SystemRDL Standard Only
|
|
16
|
+
|
|
17
|
+
The core of rggen-systemrdl is responsible for converting only the SystemRDL standard range (properties defined in the language specification). It does not interpret any UDP semantics on its own.
|
|
18
|
+
|
|
19
|
+
This keeps the core adapter:
|
|
20
|
+
|
|
21
|
+
- Simple and focused on the standard
|
|
22
|
+
- Independent of any vendor-specific UDP definition
|
|
23
|
+
- Free from the lock-in problems associated with UDP-based extensions
|
|
24
|
+
|
|
25
|
+
### 2. UDP Handling via User-Defined Hooks (Plugins)
|
|
26
|
+
|
|
27
|
+
When the conversion process encounters a node that has any UDP attached, the entire conversion of that node is delegated to a user-defined hook. The hook is responsible for producing the corresponding RgGen data structure for that node.
|
|
28
|
+
|
|
29
|
+
This delegation model:
|
|
30
|
+
|
|
31
|
+
- Respects the SystemRDL property model, where UDPs may interact with other properties in arbitrary ways
|
|
32
|
+
- Keeps the core adapter's responsibility cleanly separated from UDP semantics
|
|
33
|
+
- Allows users to extend support for any UDP without modifying the core
|
|
34
|
+
- Makes the lock-in implications of using a UDP explicit and opt-in
|
|
35
|
+
|
|
36
|
+
Hooks are registered via the plugin mechanism that RgGen already uses for extension, following the existing RgGen conventions for plugin authoring.
|
|
37
|
+
|
|
38
|
+
### 3. Hierarchy-Independent Judgment
|
|
39
|
+
|
|
40
|
+
UDP detection and hook delegation are determined independently at each hierarchy level (addrmap, regfile, reg, field, etc.). The presence of a UDP at one level does not change the conversion behavior of other levels.
|
|
41
|
+
|
|
42
|
+
This is consistent with the SystemRDL scoping rules: a lower component cannot reference properties of its enclosing component, so a UDP at one hierarchy level cannot legitimately alter the semantics of another level.
|
|
43
|
+
|
|
44
|
+
Concretely:
|
|
45
|
+
|
|
46
|
+
- If a register has a UDP but its fields do not, the register conversion is delegated to a hook, while the fields are converted by the default mechanism.
|
|
47
|
+
- If a field has a UDP but its parent register does not, the register conversion uses the default mechanism, while the field conversion is delegated.
|
|
48
|
+
- Each level makes its own decision based only on its own UDPs.
|
|
49
|
+
|
|
50
|
+
In the rare case where a UDP is intended to affect multiple hierarchy levels, the plugin may need to express claim conditions that look beyond a single node (for example, to claim a field based on a UDP attached to its parent register). Allowing plugins to define such cross-hierarchy claim conditions is technically possible but is considered a low-priority extension: well-designed UDPs respect the SystemRDL scoping rules, and the common case is fully covered by hierarchy-independent judgment.
|
|
51
|
+
|
|
52
|
+
### 4. Single Active UDP Plugin
|
|
53
|
+
|
|
54
|
+
Only one UDP plugin may be active at a time. If multiple UDP plugins are loaded simultaneously, rggen-systemrdl rejects the configuration with an error at startup.
|
|
55
|
+
|
|
56
|
+
This constraint reflects the practical reality that a given SystemRDL codebase typically targets a single tool (such as PeakRDL) or a single internal convention, and therefore needs exactly one UDP plugin. Allowing multiple UDP plugins would introduce the need for conflict resolution between competing claims on the same node, with no clear benefit for any realistic use case.
|
|
57
|
+
|
|
58
|
+
If a user genuinely needs to combine multiple UDP sets, the recommended approach is to write a combined plugin that handles both sets coherently. This keeps the single-plugin invariant intact while allowing flexibility for unusual situations.
|
|
59
|
+
|
|
60
|
+
### 5. Strict by Default
|
|
61
|
+
|
|
62
|
+
The default behavior when a UDP is encountered but no hook is registered to handle it is to raise an error. This prevents silent fallback to ill-defined behavior and forces users to make explicit decisions about UDP support.
|
|
63
|
+
|
|
64
|
+
A configuration option may allow this behavior to be relaxed (e.g., to warn or ignore unknown UDPs), but the default is strict.
|
|
65
|
+
|
|
66
|
+
## Conversion Flow
|
|
67
|
+
|
|
68
|
+
For each node in the elaborated SystemRDL hierarchy, the conversion proceeds as follows:
|
|
69
|
+
|
|
70
|
+
1. Check whether the node has any UDP attached to it.
|
|
71
|
+
2. If no UDP is present, perform the default conversion:
|
|
72
|
+
- Translate standard SystemRDL properties to the corresponding RgGen data structure.
|
|
73
|
+
- Recursively process child nodes using the same procedure.
|
|
74
|
+
3. If a UDP is present, look up a registered hook that matches the node:
|
|
75
|
+
- If a matching hook is found, delegate the conversion of this node entirely to the hook.
|
|
76
|
+
- If no matching hook is found, raise an error (in strict mode) or fall back to the configured alternative behavior.
|
|
77
|
+
|
|
78
|
+
The hook receives:
|
|
79
|
+
|
|
80
|
+
- The SystemRDL node, with full access to its standard properties, UDP values, and children.
|
|
81
|
+
- A conversion context that provides access to the default conversion routine, so the hook can choose to invoke the default conversion for child nodes if desired.
|
|
82
|
+
|
|
83
|
+
The hook is expected to return a fully constructed RgGen data structure for the node it handled. The hook is responsible for processing child nodes as appropriate, either by invoking the default conversion via the context or by implementing custom handling.
|
|
84
|
+
|
|
85
|
+
## Plugin Architecture
|
|
86
|
+
|
|
87
|
+
UDP handlers are organized as plugins, separate from the rggen-systemrdl core. This means:
|
|
88
|
+
|
|
89
|
+
- The core adapter ships without any built-in UDP knowledge.
|
|
90
|
+
- Support for specific UDPs (e.g., PeakRDL UDPs, vendor-specific UDPs, internal company UDPs) is provided by independent plugins.
|
|
91
|
+
- Users can install only the UDP plugins they need, and the dependencies between rggen-systemrdl and any specific UDP definition are made explicit.
|
|
92
|
+
|
|
93
|
+
Each plugin declares:
|
|
94
|
+
|
|
95
|
+
- Which UDPs it handles (by name and optionally by combination)
|
|
96
|
+
- The conditions under which it applies (e.g., component type, presence of related UDPs)
|
|
97
|
+
- The conversion logic that produces RgGen data structures
|
|
98
|
+
|
|
99
|
+
This structure allows the community to contribute UDP support for various tools and conventions without burdening the core adapter with vendor-specific code.
|
|
100
|
+
|
|
101
|
+
## Plugin Registration
|
|
102
|
+
|
|
103
|
+
Plugins register UDP hooks following the conventions of the RgGen plugin system. A hook registration declares:
|
|
104
|
+
|
|
105
|
+
- A matching condition that determines when the hook applies to a node
|
|
106
|
+
- A conversion routine that produces the RgGen data structure for that node
|
|
107
|
+
|
|
108
|
+
The exact API is determined at implementation time, but the general shape follows RgGen's existing plugin patterns.
|
|
109
|
+
|
|
110
|
+
## Behavior on Unknown UDPs
|
|
111
|
+
|
|
112
|
+
When a UDP is encountered but no plugin provides a matching hook, the configured behavior applies:
|
|
113
|
+
|
|
114
|
+
- **error** (default): Raise an error indicating that the UDP is not supported, with location information from the SystemRDL source.
|
|
115
|
+
- **warn**: Emit a warning and proceed without applying the UDP's semantics. The default conversion is used as if the UDP were absent.
|
|
116
|
+
- **ignore**: Silently proceed without applying the UDP's semantics.
|
|
117
|
+
|
|
118
|
+
The `warn` and `ignore` modes are provided for cases such as bulk migration from existing SystemRDL codebases, where a complete UDP handler set may not yet be available. They should be used with awareness that the resulting RgGen data may not reflect the original intent.
|
|
119
|
+
|
|
120
|
+
## Rationale for the "Whole-Node Delegation" Choice
|
|
121
|
+
|
|
122
|
+
When a UDP is present at a given node, the adapter delegates the entire conversion of that node, rather than performing a partial conversion and asking the hook to augment it. This choice is motivated by the way SystemRDL is structured:
|
|
123
|
+
|
|
124
|
+
- SystemRDL defines behavior through combinations of properties, and UDPs may participate in those combinations in arbitrary ways.
|
|
125
|
+
- A UDP may change how standard properties at the same level should be interpreted (e.g., `buffer_writes` changes how SW writes to the register are realized).
|
|
126
|
+
- A partial conversion would force the hook to reconcile a half-formed result with the UDP's semantics, leading to complex and error-prone hook implementations.
|
|
127
|
+
|
|
128
|
+
By delegating the whole node, the hook has full control and is responsible for producing a coherent result. If the hook wishes to use the default conversion as a starting point, it may do so explicitly by invoking the conversion context.
|
|
129
|
+
|
|
130
|
+
## Implications and Trade-offs
|
|
131
|
+
|
|
132
|
+
### Lock-In Awareness
|
|
133
|
+
|
|
134
|
+
A SystemRDL file that uses UDPs is, in effect, tool-specific. By making UDP handling explicit through plugins and requiring opt-in, this policy makes the lock-in implications visible to the user. Users adopting a UDP-based feature are also adopting the plugin (and its maintenance burden) needed to interpret that UDP.
|
|
135
|
+
|
|
136
|
+
This is preferable to silent compatibility shims that hide the lock-in.
|
|
137
|
+
|
|
138
|
+
### Migration Path
|
|
139
|
+
|
|
140
|
+
For users migrating SystemRDL files that use vendor-specific UDPs (e.g., PeakRDL UDPs) to rggen-systemrdl:
|
|
141
|
+
|
|
142
|
+
1. They can either install a community-provided plugin that supports those UDPs, or
|
|
143
|
+
2. They can write their own plugin to interpret their UDPs in the way they prefer, or
|
|
144
|
+
3. They can modify the SystemRDL source to remove UDP usage and rewrite the equivalent behavior using RgGen's native facilities.
|
|
145
|
+
|
|
146
|
+
The third option is encouraged as the long-term path, since it removes the SystemRDL-induced lock-in entirely.
|
|
147
|
+
|
|
148
|
+
### No Built-In UDP Knowledge in the Core
|
|
149
|
+
|
|
150
|
+
rggen-systemrdl itself does not ship with any UDP definitions or handlers. This is intentional:
|
|
151
|
+
|
|
152
|
+
- Bundling specific vendor UDP support would implicitly endorse those vendors' design choices.
|
|
153
|
+
- It would also tie the core to the maintenance lifecycle of those vendors' tools.
|
|
154
|
+
- The plugin model lets each community of users maintain the UDP handlers they need, independently from the core's release schedule.
|
|
155
|
+
|
|
156
|
+
## Open Questions
|
|
157
|
+
|
|
158
|
+
The following aspects are deferred to implementation and may be revisited as the adapter evolves:
|
|
159
|
+
|
|
160
|
+
- The exact shape of the plugin registration API
|
|
161
|
+
- Whether plugins can introduce new RgGen types or are limited to existing ones
|
|
162
|
+
- The precise interface through which hooks invoke the default conversion on child nodes
|
|
163
|
+
|
|
164
|
+
The following extension is acknowledged but considered low priority:
|
|
165
|
+
|
|
166
|
+
- Allowing plugins to define claim conditions that span multiple hierarchy levels (for example, claiming a field based on a UDP attached to its parent register). This would extend the adapter's reach to UDPs that intentionally violate SystemRDL's scoping conventions, but the common case is fully covered by hierarchy-independent judgment, so this is not a near-term priority.
|
|
167
|
+
|
|
168
|
+
## Summary
|
|
169
|
+
|
|
170
|
+
| Aspect | Decision |
|
|
171
|
+
| --- | --- |
|
|
172
|
+
| Core adapter scope | SystemRDL standard range only |
|
|
173
|
+
| UDP handling | Delegated to user-defined hooks via plugins |
|
|
174
|
+
| Delegation granularity | Whole-node delegation when a UDP is present |
|
|
175
|
+
| Hierarchy treatment | Independent judgment at each level |
|
|
176
|
+
| Number of active UDP plugins | One at a time; multiple loaded plugins cause a startup error |
|
|
177
|
+
| Default behavior on unknown UDP | Error (strict by default) |
|
|
178
|
+
| UDP definitions in core | None; all UDP support is plugin-provided |
|
|
179
|
+
| Cross-hierarchy claim by plugins | Low-priority extension; not in scope for initial implementation |
|
|
180
|
+
|
|
181
|
+
This policy keeps the rggen-systemrdl core simple, principled, and aligned with RgGen's overall design philosophy of explicit type-based safety, while leaving the door open for the community to provide UDP support through the plugin mechanism.
|
metadata
ADDED
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: rggen-systemrdl
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
version: 0.1.0
|
|
5
|
+
platform: ruby
|
|
6
|
+
authors:
|
|
7
|
+
- Taichi Ishitani
|
|
8
|
+
bindir: bin
|
|
9
|
+
cert_chain: []
|
|
10
|
+
date: 1980-01-02 00:00:00.000000000 Z
|
|
11
|
+
dependencies:
|
|
12
|
+
- !ruby/object:Gem::Dependency
|
|
13
|
+
name: systemrdl
|
|
14
|
+
requirement: !ruby/object:Gem::Requirement
|
|
15
|
+
requirements:
|
|
16
|
+
- - ">="
|
|
17
|
+
- !ruby/object:Gem::Version
|
|
18
|
+
version: 0.2.0
|
|
19
|
+
type: :runtime
|
|
20
|
+
prerelease: false
|
|
21
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
22
|
+
requirements:
|
|
23
|
+
- - ">="
|
|
24
|
+
- !ruby/object:Gem::Version
|
|
25
|
+
version: 0.2.0
|
|
26
|
+
description: SystemRDL loader plugin for RgGen
|
|
27
|
+
email:
|
|
28
|
+
- rggen@googlegroups.com
|
|
29
|
+
executables: []
|
|
30
|
+
extensions: []
|
|
31
|
+
extra_rdoc_files: []
|
|
32
|
+
files:
|
|
33
|
+
- LICENSE
|
|
34
|
+
- README.md
|
|
35
|
+
- lib/rggen/systemrdl.rb
|
|
36
|
+
- lib/rggen/systemrdl/converter/addrmap.rb
|
|
37
|
+
- lib/rggen/systemrdl/converter/base.rb
|
|
38
|
+
- lib/rggen/systemrdl/converter/field.rb
|
|
39
|
+
- lib/rggen/systemrdl/converter/mem.rb
|
|
40
|
+
- lib/rggen/systemrdl/converter/reg.rb
|
|
41
|
+
- lib/rggen/systemrdl/converter/regfile.rb
|
|
42
|
+
- lib/rggen/systemrdl/global/ignore_precedence.rb
|
|
43
|
+
- lib/rggen/systemrdl/loader.rb
|
|
44
|
+
- lib/rggen/systemrdl/version.rb
|
|
45
|
+
- notes/bit_field_type_mapping.md
|
|
46
|
+
- notes/bit_field_type_matrix.md
|
|
47
|
+
- notes/external_reg_regfile_mapping.md
|
|
48
|
+
- notes/interrupt_aggregation_policy.md
|
|
49
|
+
- notes/precedence_handling_policy.md
|
|
50
|
+
- notes/systemrdl_rggen_gap_analysis.md
|
|
51
|
+
- notes/systemrdl_to_rggen_mapping.md
|
|
52
|
+
- notes/systemrdl_to_rggen_todo.md
|
|
53
|
+
- notes/udp_handling_policy.md
|
|
54
|
+
homepage: https://github.com/rggen/rggen-systemrdl
|
|
55
|
+
licenses:
|
|
56
|
+
- MIT
|
|
57
|
+
metadata:
|
|
58
|
+
bug_tracker_uri: https://github.com/rggen/rggen/issues
|
|
59
|
+
mailing_list_uri: https://groups.google.com/d/forum/rggen
|
|
60
|
+
rubygems_mfa_required: 'true'
|
|
61
|
+
source_code_uri: https://github.com/rggen/rggen-systemrdl
|
|
62
|
+
wiki_uri: https://github.com/rggen/rggen/wiki
|
|
63
|
+
rdoc_options: []
|
|
64
|
+
require_paths:
|
|
65
|
+
- lib
|
|
66
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
67
|
+
requirements:
|
|
68
|
+
- - ">="
|
|
69
|
+
- !ruby/object:Gem::Version
|
|
70
|
+
version: '3.2'
|
|
71
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
72
|
+
requirements:
|
|
73
|
+
- - ">="
|
|
74
|
+
- !ruby/object:Gem::Version
|
|
75
|
+
version: '0'
|
|
76
|
+
requirements: []
|
|
77
|
+
rubygems_version: 4.0.3
|
|
78
|
+
specification_version: 4
|
|
79
|
+
summary: rggen-systemrdl-0.1.0
|
|
80
|
+
test_files: []
|