diff --git a/docs/code-prettify/run_prettify.js b/docs/code-prettify/run_prettify.js index 5cf0202be..ba4ac4dfe 100644 --- a/docs/code-prettify/run_prettify.js +++ b/docs/code-prettify/run_prettify.js @@ -489,6 +489,7 @@ var IN_GLOBAL_SCOPE = false; "set," + "severity," + "signal," + + "signed," + "size," + "sizeof," + "stack," + @@ -504,6 +505,7 @@ var IN_GLOBAL_SCOPE = false; "topology," + "type," + "unmatched," + + "unsigned," + "update," + "warning," + "with," + diff --git a/docs/fpp-spec.html b/docs/fpp-spec.html index 5a8cc52b5..41a750a97 100644 --- a/docs/fpp-spec.html +++ b/docs/fpp-spec.html @@ -1301,6 +1301,7 @@

3.1. Reserved Words

set severity signal +signed size sizeof stack @@ -1316,6 +1317,7 @@

3.1. Reserved Words

true type unmatched +unsigned update warning with @@ -3697,8 +3699,12 @@

5.13.1. Syntax

struct-type-member-sequence is an element sequence in which the elements are struct type members, and the terminating punctuation is a comma. -A struct type member has the following syntax:

+A struct type member has one of the following two forms:

+
+
    +
  1. +

    A typed member:

    identifier : [ @@ -3709,6 +3715,20 @@

    5.13.1. Syntax

    format string-literal ]

    +
  2. +
  3. +

    A bit field member:

    +
    +

    identifier : +( signed | unsigned ) +expression +[ +format string-literal +]

    +
    +
  4. +
+

5.13.2. Semantics

@@ -3720,7 +3740,7 @@

5.13.2. Semantics

identifier appearing in the struct type member sequence must be distinct.

-

For each member m,

+

For each typed member m,

+

For each bit field member m,

+
+
+ +
+
+

The bit width affects only the serialized form of the struct type, +not the in-memory representation. +Each maximal sequence of consecutive bit field members in the struct +type member sequence forms a bit field group. +The members of a bit field group are packed into a sequence of bytes +as described in the section on +serialized sizes.

+
+

The expression following the keyword default is optional. If present, it specifies the default value associated with the type. @@ -3792,7 +3865,20 @@

5.13.3. Examples

# The default value of D stores 1 into each of the 3 elements of x struct D { x: [3] U32 -} default { x = 1 } +} default { x = 1 } + +# Defines a struct type E with two bit field members and one +# typed member. +# a and b form a bit field group of 12 bits, which is packed +# into 16 serialized bits (12 bits of data and 4 zero pad bits). +# The type of a is U8; the type of b is I16. +# The serialized size of E is 6 bytes: 2 bytes for the bit field +# group and 4 bytes for x. +struct E { + a: unsigned 3 + b: signed 9 + x: U32 +}
@@ -11554,8 +11640,11 @@

17.19. Serialized Sizes

  • If T is a struct type, then s -the sum of the serialized sizes of the members of T. -For each member m with type \$T_m\$:

    +the sum of the serialized sizes of the members of T +and of the +bit field groups of T, +in declaration order. +For each member m with type \$T_m\$ that is not a bit field member:

  • +

    Each bit field group G of a struct type is serialized as a unit, +as follows:

    +
    + +
    +
  • +
  • If T is an alias type, then s is the serialized size of the underlying type of T.

    @@ -13309,7 +13426,7 @@

    23.4. Translation Tools

    diff --git a/docs/spec/Definitions/Struct-Definitions.adoc b/docs/spec/Definitions/Struct-Definitions.adoc index fbd9d3ce5..2e67ed852 100644 --- a/docs/spec/Definitions/Struct-Definitions.adoc +++ b/docs/spec/Definitions/Struct-Definitions.adoc @@ -15,8 +15,10 @@ _[_ `default` <> _]_ _struct-type-member-sequence_ is an <> in which the elements are struct type members, and the terminating punctuation is a comma. -A *struct type member* has the following syntax: +A *struct type member* has one of the following two forms: +. A *typed member*: ++ <> `:` _[_ `[` <> `]` @@ -26,6 +28,15 @@ _[_ `format` <> _]_ +. A *bit field member*: ++ +<> `:` +( `signed` | `unsigned` ) +<> +_[_ +`format` <> +_]_ + ==== Semantics The identifier is the name _N_ of the type. @@ -34,7 +45,7 @@ The definition associates the name _N_ with a of the specified type. Each identifier appearing in the struct type member sequence must be distinct. -For each member _m_, +For each typed member _m_, * The type name specifies the type stem:[T_m] of the member. @@ -54,6 +65,47 @@ There is one argument to the format string, which is the member value. If the size of the member is greater than one, then the translator applies the format to each element. +For each bit field member _m_, + +* The keyword `signed` or `unsigned` specifies the *signedness* of _m_. + +* The expression following the keyword specifies the *bit width* +stem:[w_m] of _m_. +The expression must have a +<>, and it must +evaluate to a value stem:[w_m] after conversion to +<>, with +stem:[1 <= w_m <= 64]. + +* The type stem:[T_m] of _m_ is the +<> +with the specified signedness and with the smallest width +greater than or equal to stem:[w_m]. +For example, the type of a member `unsigned 4` is `U8`, and +the type of a member `signed 12` is `I16`. +This type governs the use of the member in expressions and its +representation in generated code. + +* The value stored in _m_ must be representable in stem:[w_m] bits: +in the range stem:[[0, 2^(w_m)-1\]] if _m_ is unsigned, and in the range +stem:[[-2^(w_m-1), 2^(w_m-1)-1\]] if _m_ is signed. +In particular, if the default value of the struct type specifies a +value for _m_, then the value must lie in this range. + +* A bit field member represents a single value; it may not have a +size expression `[` _e_ `]`. + +* The optional format specifier behaves as it does for a typed +member. + +The bit width affects only the serialized form of the struct type, +not the in-memory representation. +Each maximal sequence of consecutive bit field members in the struct +type member sequence forms a *bit field group*. +The members of a bit field group are packed into a sequence of bytes +as described in the section on +<>. + The expression following the keyword `default` is optional. If present, it specifies the <> associated with the type. @@ -97,4 +149,17 @@ struct C { struct D { x: [3] U32 } default { x = 1 } + +# Defines a struct type E with two bit field members and one +# typed member. +# a and b form a bit field group of 12 bits, which is packed +# into 16 serialized bits (12 bits of data and 4 zero pad bits). +# The type of a is U8; the type of b is I16. +# The serialized size of E is 6 bytes: 2 bytes for the bit field +# group and 4 bytes for x. +struct E { + a: unsigned 3 + b: signed 9 + x: U32 +} ---- diff --git a/docs/spec/Lexical-Elements.adoc b/docs/spec/Lexical-Elements.adoc index b5aeb168d..6cf4cf596 100644 --- a/docs/spec/Lexical-Elements.adoc +++ b/docs/spec/Lexical-Elements.adoc @@ -125,6 +125,7 @@ serial set severity signal +signed size sizeof stack @@ -140,6 +141,7 @@ topology true type unmatched +unsigned update warning with diff --git a/docs/spec/Types.adoc b/docs/spec/Types.adoc index 573143b72..56e276259 100644 --- a/docs/spec/Types.adoc +++ b/docs/spec/Types.adoc @@ -297,14 +297,37 @@ representation type of _T_. * If _T_ is a <>, then _s_ -the sum of the serialized sizes of the members of _T_. -For each member _m_ with type stem:[T_m]: +the sum of the serialized sizes of the members of _T_ +and of the +<> of _T_, +in declaration order. +For each member _m_ with type stem:[T_m] that is not a bit field member: ** If _m_ has size _n_, then the serialized size of _m_ is _n_ times the serialized size of stem:[T_m]. ** Otherwise the serialized size of _m_ is the serialized size of stem:[T_m]. +* Each bit field group _G_ of a struct type is serialized as a unit, +as follows: + +** Let _w_ be the sum of the bit widths of the members of _G_. +The serialized size of _G_ is _w_ divided by 8, rounded up to the +nearest integer, in bytes. + +** The members of _G_ are packed in declaration order into +the serialized bytes, from the most significant bit of the first +byte towards the least significant bit of the last byte, +with no intervening bits. +Each member occupies exactly its bit width, using the standard +binary representation of an unsigned integer or the two's complement +representation of a signed integer. + +** If _w_ is not a multiple of 8, then the low-order bits of the +last byte that are not occupied by any member are *pad bits*. +Pad bits are zero in the serialized form and are ignored during +deserialization. + * If _T_ is an <>, then _s_ is the serialized size of the <> of _T_. diff --git a/editors/emacs/fpp-mode.el b/editors/emacs/fpp-mode.el index 372635f1f..433e7faf1 100644 --- a/editors/emacs/fpp-mode.el +++ b/editors/emacs/fpp-mode.el @@ -50,9 +50,9 @@ "locate" "low" "match" "on" "opcode" "orange" "output" "param" "passive" "phase" "priority" "queue" "queued" "raw" "recv" "red" - "ref" "reg" "resp" "save" "signal" "serial" "set" "severity" + "ref" "reg" "resp" "save" "signal" "signed" "serial" "set" "severity" "size" "sizeof" "stack" "sync" "telemetry" "text" "throttle" - "time" "true" "unmatched" "update" "enter" "warning" "with" + "time" "true" "unmatched" "unsigned" "update" "enter" "warning" "with" "yellow") "All non-definition keywords for FPP.") diff --git a/editors/vim/fpp.vim b/editors/vim/fpp.vim index 5b7f24e98..36a7f1c79 100644 --- a/editors/vim/fpp.vim +++ b/editors/vim/fpp.vim @@ -93,6 +93,7 @@ syn keyword fppKeyword serial syn keyword fppKeyword set syn keyword fppKeyword severity syn keyword fppKeyword signal +syn keyword fppKeyword signed syn keyword fppKeyword size syn keyword fppKeyword sizeof syn keyword fppKeyword stack @@ -108,6 +109,7 @@ syn keyword fppKeyword topology syn keyword fppKeyword true syn keyword fppKeyword type syn keyword fppKeyword unmatched +syn keyword fppKeyword unsigned syn keyword fppKeyword update syn keyword fppKeyword warning syn keyword fppKeyword with