@@ -8,8 +8,7 @@ Everything in the msg library is in the `msg` namespace.
8
8
=== Fields
9
9
10
10
A `field` represents a value, specified in bits, inside a unit of addressable
11
- storage. Currently in the _cib_ library, storage is assumed to be in units of
12
- `std::uint32_t`. A field is a view type: it defines how to access storage, but
11
+ storage. A field is a view type: it defines how to access storage, but
13
12
it is an empty type.
14
13
15
14
Two things specify a `field`:
@@ -32,7 +31,7 @@ A field may also specify a xref:match.adoc#_what_is_a_matcher[`matcher`]; this
32
31
can be used to verify that a particular storage area contains the field. By
33
32
default this is xref:match.adoc#_basic_matchers[`match::always`].
34
33
35
- For example, a field type looks like this:
34
+ For example, a field declaration looks like this:
36
35
[source,cpp]
37
36
----
38
37
using namespace msg;
@@ -44,17 +43,44 @@ using my_field =
44
43
24_lsb}>; // least significant bit
45
44
----
46
45
46
+ Or like this:
47
+ [source,cpp]
48
+ ----
49
+ using namespace msg;
50
+ using my_field_spec = field<"my field", std::uint32_t>;
51
+
52
+ // these two declarations specify the same locations
53
+ using my_field1 = my_field_spec::located_at<{1_dw, 23_msb, 20_lsb}>;
54
+ using my_field2 = my_field_spec::located_at<{55_msb, 52_lsb}>;
55
+ ----
56
+ The 32-bit word offset in storage may be omitted in favour of using "raw" bit
57
+ positions, according to convention.
58
+
47
59
A field can specify multiple `at` arguments if it has several disjoint parts. In
48
60
that case, earlier `at` arguments specify more significant bits in the field,
49
61
with later `at` arguments being less significant. For example:
50
62
[source,cpp]
51
63
----
52
64
using namespace msg;
53
65
using my_field =
54
- field<"my field", // name
55
- std::uint16_t> // type
56
- ::located<at{0_dw, 31_msb, 24_lsb}, // high byte
57
- at{0_dw, 7_msb, 0_lsb}>; // low byte
66
+ field<"my field", std::uint16_t>
67
+ ::located<at{0_dw, 31_msb, 24_lsb}, // high byte
68
+ at{0_dw, 7_msb, 0_lsb}>; // low byte
69
+ ----
70
+
71
+ The maximum size of a field is 64 bits.
72
+
73
+ NOTE: It is a compile-time error to specify a field location where the number of
74
+ bits in storage exceeds the capacity of the field's type. (The inverse is fine:
75
+ it's common to have limited bits in storage handled by larger types.)
76
+ [source,cpp]
77
+ ----
78
+ using namespace msg;
79
+
80
+ // this is a compilation error:
81
+ // the field location is 9 bits, but the field type only holds 8 bits
82
+ using my_field = field<"my field", std::uint8_t>
83
+ ::located<at{8_msb, 0_lsb}>;
58
84
----
59
85
60
86
Fields also expose several matcher aliases which can typically be used to
@@ -78,7 +104,7 @@ For example, a message type looks like this:
78
104
----
79
105
using my_message_defn = msg::message<
80
106
"my_message", // name
81
- my_field::with_required<0x80>>; // field(s)
107
+ my_field::with_required<0x80>>; // field(s)
82
108
83
109
using my_message = msg::owning<my_message_defn>;
84
110
----
@@ -155,7 +181,7 @@ using msg_defn = extend<
155
181
----
156
182
157
183
The combined definition incorporates all the fields of the messages. And as
158
- shown, the combination might typically be `extend`ed with a constraint on the
184
+ shown, the combination might typically be `extend` ed with a constraint on the
159
185
header field.
160
186
161
187
Other times it is useful to automatically concatenate or `pack` messages
0 commit comments