Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 14 additions & 17 deletions p4-16/spec/P4-16-spec.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -3630,10 +3630,20 @@ Bit-strings also support the following operations:
`+0 <= L <= H < W+` are checked statically (where `W` is
the length of the source bit-string). Note that both endpoints of
the extraction are inclusive. The bounds are required to be
local compile-time known values so that the width of the result can be computed at compile time. Slices are also l-values, which means that P4 supports assigning to a slice: `e[H:L] = x`.
local compile-time known values so that the width of the result can be computed
at compile time. Slices are also l-values, which means that P4 supports
assigning to a slice: `e[H:L] = x`.
The effect of this statement is to set bits `H` through `L` (inclusive of
both) of `e` to the bit-pattern represented by `x`, and leaves all other bits
of `e` unchanged. A slice of an unsigned integer is an unsigned integer.
of `e` unchanged. A slice is always an unsigned integer.
A slice may also be specified as `[L+:W]` where `L` is the lowest bit of the slice
and `W` is the width of the slice. In this case, only `W` must be a non-negative
local compile-time known numeric value. `L` must also be a numeric value and
some architectures may require it to be compile-time known. It must also be
non-negative and in-range for the type. Some architectures may allow variable indexing,
in which case an out of range value will be equivalent to a shift of that amount.
Comment on lines +3642 to +3644
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I suggest wording this as for shifts, allowing only int or bit<W>, not int<W> (https://p4.org/wp-content/uploads/2024/10/P4-16-spec-v1.2.5.html#sec-a-note-about-shifts). This also matches what was discussed on the last LDWG. We cannot defer to the shift for the int<W> index as shift does not allow int<W> to avoid probelems with negative values.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe add a precise definition for "non-negative" somewhere -- either a bit<W> value or a compile time known value that is >= 0. I don't think we need to (or should) specifically disallow int<W> compile-time-known values.

Copy link
Member

@vlstill vlstill Mar 26, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the formulation that is used for RHS of shifts permits that:

[...] the right operand of shifts must be either an expression of type bit<S> or a compile-time known value that is a non-negative integer.

I suggest we use the same.

I think a restriction to operation types is something important enough to have it written in the operation description and not hidden in a definition of non-negativity.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@ChrisDodd Any thoughts on updates to this PR to address this comment?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I added a line here to clarify that the index must be a bit<W> type if it is not compile-time-known, in order to be compatible with shift.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see. @vlstill Any additional comments, or does it look good to you?

An index that is not compile-time known must be a `bit<W>` type in order to ensure that
it is non-negative.
* Concatenation of bit-strings and/or fixed-width signed integers, denoted by `++`.
The two operands must be either `bit<W>` or `int<W>`, and they can be of
different signedness and width. The result has the same signedness as the
Expand Down Expand Up @@ -3710,21 +3720,8 @@ The `int<W>` datatype also support the following operations:
** all result bits are zero when shifting a non-negative value right
** all result bits are one when shifting a negative value right
* Extraction of a set of contiguous bits, also known as a slice,
denoted by `[H:L]`, where `H` and `L` must be expressions that evaluate to
non-negative, local compile-time known values, and `H >= L` must be true.
The types of `H` and `L` (which do not need to be identical)
must be numeric (<<sec-numeric-values>>).
The result is an unsigned bit-string of width `H - L + 1`, including the bits
numbered from `L` (which becomes the least significant bit of the result)
to `H` (the most significant bit of the result) from the source operand.
The conditions `+0 <= L <= H < W+` are checked statically (where `W` is
the length of the source bit-string). Note that both endpoints of
the extraction are inclusive. The bounds are required to be values
that are known at compile time so that the width of the result can be
computed at compile time. Slices are also l-values, which means that P4
supports assigning to a slice: `e[H:L] = x`.
The effect of this statement is to set bits `H` through `L` of `e` to the
bit-pattern represented by `x`, and leaves all other bits of `e` unchanged.
denoted by `[H:L]` or `[L+:W]`, with the same semantics as slices of
bit strings.
A slice of a signed integer is treated as an unsigned integer.
* Concatenation of bit-strings and/or fixed-width signed integers, denoted by `++`.
The two operands must be either `bit<W>` or `int<W>`, and they can be of different signedness and width.
Expand Down
3 changes: 3 additions & 0 deletions p4-16/spec/grammar.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -1097,6 +1097,7 @@ lvalue
| lvalue "." member
| lvalue "[" expression "]"
| lvalue "[" expression ":" expression "]"
| lvalue "[" expression "+" ":" expression "]"
| "(" lvalue ")"
;
// end::lvalue[]
Expand Down Expand Up @@ -1130,6 +1131,7 @@ expression
| prefixedNonTypeName
| expression "[" expression "]"
| expression "[" expression ":" expression "]"
| expression "[" expression "+" ":" expression "]"
| "{" expressionList optTrailingComma "}"
| "{#}"
| "{" kvList optTrailingComma "}"
Expand Down Expand Up @@ -1180,6 +1182,7 @@ nonBraceExpression
| prefixedNonTypeName
| nonBraceExpression "[" expression "]"
| nonBraceExpression "[" expression ":" expression "]"
| nonBraceExpression "[" expression "+" ":" expression "]"
| "(" expression ")"
| "!" expression %prec PREFIX
| "~" expression %prec PREFIX
Expand Down