Proposed DSDL spec simplifications for Cyphal v1.1

One of the core design goals of Cyphal is simplicity. Whenever we add a new feature, we must likewise consider if any of the old features remain necessary and whether the complexity that they introduce is justifiable, otherwise there’s risk undermining the appeal of Cyphal as a simple solution. In Cyphal v1.1 we are going to add named topics with basic service discovery and reliable delivery along with simplified RPC as outlined in RFC: Early preview of Cyphal v1.1. Here, I will provide a list of features that I propose for deprecation and eventual removal from the spec to compensate for the added material. None of the proposed changes affect wire compatibility.

DSDL cast modes

Cast modes are defined for unsigned and floating-point primitives and are specified using the truncated and saturated keywords; if omitted, saturated is implied:

saturated uint4 foo
truncated float16 bar
uint63 baz # saturated by omission

From where I stand, it seems like this feature is rarely used in the field, and its utility is comparatively low because typically DSDL code is generated such that the native type that represents a primitive is chosen to be as narrow as possible, meaning that the possible information loss at assignment/computation may occur before the DSDL serialization takes place.

My proposal is to remove the cast mode and make narrowing assignments implementation-defined.

GitHub issue: Cyphal v1.1 should deprecate or remove the cast mode specifier (saturated/truncated) · Issue #149 · OpenCyphal/specification · GitHub

DSDL file naming simplification

I propose to deprecate the ability to specify the fixed port-ID in the file name, and instead introduce a new directive. Where it used to be 7509.Heartbeat.1.0.dsdl, we will have Heartbeat.1.0.dsdl with the following directive inside the definition:

@fixed_port_id 7509
# ... rest unchanged ...

This is expected to slightly simplify file lookup and arguably make the language more internally consistent.

GitHub issue: Add `@fixed_port_id` directive; deprecate specifying the fixed port-ID in the file name · Issue #150 · OpenCyphal/specification · GitHub

Do not require infinite precision rationals

The current spec requires big int rationals. They are a no-brainer in higher-level languages but closer to the metal they become a little cumbersome to deal with. I propose changing the wording such that the Spec requires rationals with at least 63 bits plus sign in the numerator and at least 64 bits in the denominator (unsigned).

For reference, here is the comparison of the resolution of an i64/u64 rational vs. IEEE 754 binary64 (double). We prefer rationals over floats because they can exactly represent integers across \left[-2^{-63}, +2^{63} \right) and are free from the usual floating point pitfalls.

Simplify compile-time expressions

The most complex part of the language is related to expression evaluation and does not directly affect serialization. It is certainly valuable as it allows static layout validation, but the implementation complexity cost might be too high to justify it. Currently, DSDL expressions define UTF-8 strings, sets, bit length sets, print directives, assertion directives, and also allow the usage of evaluated expressions in array length expressions, which is the only point that couples expression evaluation with serialization. The bit length set expressions are particularly problematic because they require symbolic expression evaluation to avoid combinatorial explosion; see Combinatorial explosion · Issue #23 · OpenCyphal/pydsdl · GitHub

I propose to simplify this by removing print and assertion check directives, sets, bit length sets, _offset_ attribute, and UTF-8 strings. Based on the dsdl.c experiment, I predict these changes will simplify implementations by a factor of four at least in terms of the lines of code needed to reach spec compliance.

We can optionally compensate for the lost static layout correctness guarantees by introducing hooks for non-spec validation tools.

1 Like

DSDL cast modes

I don’t support this proposal. It’s a differentiating feature that shows DSDL’s commitment to formality and platform independence.

DSDL file naming simplification

Yeah, this is actually long overdue. It makes a lot of sense.

Do not require infinite precision rationals

Still thinking about this…

Simplify compile-time expressions

Still thinking about this…


What would you think about cutting DSDL loose from Cyphal as being required and, instead, defining it as a separate technology while introducing nanopb as an optional profile for Cyphal messaging?

1 Like

I don’t see why not. My latest draft of Cyphal v1.1 actually does not depend on DSDL at all. I will post an update soonish explaining this. I think it makes sense to have two independent specs, one for serialization and one for the pub/sub protocol.