Data Conserving Channel Primitives

A short note.

Many aspects of system design, in hardware or software, require that data is moved from one place to another with little or no modification, other than perhaps a repacking or `marshalling'. It is reasonable that in a super high-level language, facilities to do this are built in. An obvious example is the serialize() method found in Java.

A useful paradigm for data movement is found in the blocking channel operators ! and ? used in Occam and many other process algebras. To write the value of an expression to a channel one writes

and to make a blocking read from a channel one writes

where ch is the channel name. A channel is strongly-typed and transfers exactly one expression of that type, which may be aggregate, per operation. The type of a channel does not entirely define its low-level data format, since multiple low-level operations typically occur for any transfer. Further, when we introduce automatic remarshalling, below, the transmitted type does not have to be the same as the received type.

Where desired, we can eliminate the explicit operators from our syntax treat all references to unbound variables as channel reads and treat all writes to variables that are shared with nominated other sections as code channel writes.

A hardware implementation of the channel consists of a number of wires:

where the data itself is passed over the n data wires with the som (start of message) bit being asserted for the first n bits of a multi-bit transfer. The guard and busy signals execute a four-phase handshake with data being driven valid while the guard signal is high. The source must not assert guard while the sink is asserting busy. This hardware definition is suitable both for synchronous and asynchonrous operation and for gatewaying between them.

There are many different software implementations of the channel but a main difference is whether the thread(s) that peform the operation block or return a flag saying whether the operation was successful. Thus we have both blocking and nonblocking implementations of our blocking channel.

Marshalling and queueing are operations that can be automatically provided in an implementation of channels for a super high-level language. Where a channel is created between design entities that use different types, a standard library of data formats is consulted to determine how to perform the actual interconnection. Typical examples are endianness conversion and converting from serial to parallel.

This automatic data conversion is being built in to our H2 language.