Cyclicity CDL Language Specification - Details
Gavin J Stark
v0.01
April 14th 2004
|
This section contains more focussed points on particular aspects
of the language, their semantics, and their purpose and use.
|
|
This section discusses issues to do with types in the language
|
Supported types |
The language supports some basic types, and then supports derived
types also. The basic types are described in the next section; the
derived types are examined here in overview.
The derived types may be one of:
an enumeration of a sized bit vector
a finite state machine (with defined encoding, or unspecified
encoding, or specified as one hot, one cold)
a structure consisting of one or more named elements, each of
which can be any defined type
an array of types
a type reference
Enumerations require a size of bit vector to be specified, and
then items of that enumeration will all have that bit vector size.
Finite state machine types are again sized bit vectors, basically.
They are defined as a set of states, whose assignments to bit vector
values may be given explicitly. Alternatively they may be assigned
bit vector values automatically, and this may be done in a simple
incrementing fashion, or one hot or one cold. Furthermore, each state
can have documentation with it, which should be used to document the
design of the state machine, and each state may also define potential
'predecessor' states and 'successor' states, which the language
implementers may check statically or dynamically for correctness.
Structures are very similar to C structures. They contain a number
of elements, each of which is assigned a name, and each of which may
be of any defined type. Structures are very important inside CDL;
they are a very good mechanism for writing code that is clear in
intent.
Arrays of types are supported as in C, with one vital exception.
Multidimensional arrays are not supported. The basic type of the bit
vector is not an array as such, and so arrays of bit vectors are
supported. But no array may resolve down to an array of array of bit
vectors.
Type references are transparent type references provided for code
clarity only; they are not tightly defining. For example, one could
define 'short' to be a bit vector of size 16, and declare a
combinatorial variable to be of type 'short'. This will actually make
that variable a bit vector of size 16 internally; the type reference
is just transparent.
|
Basic types: sized and unsized bit vectors and strings |
The language supports three basic types for expressions:
Sized bit vectors; these are effectively arrays of bits of
length 1 upwards.
Unsized bit vectors; these are arrays of bits of a
compile-defined maximum length, which can be implicity converted to
any size of sized bit vector.
Strings.
Strings are hardly used as yet.
The fundamental difference between unsized and sized bit vectors
is in casting: sized bit vectors cannot be implicitly cast to be a
bit vector of another size, that cast would have to be done
explicitly by bundling or bit extraction; unsized bit vectors may be
implicitly cast to a bit vector of any size.
As an explicit example: 5+8, 3+4h2, and 6b110011+6h0f are valid
expressions, as the types all match or may be implicitly cast. But
4h2+3h5 is not a valid expression, as the types of the two operands
are both sized bit vectors, but of different size.
|
Enumerations |
Enumerations are a type, and unlike in C they are only
available as a type. This means that a signal may be given an
enumeration type, and it may then only be assigned values within that
enumeration type.
As an example, if there is an
enumeration:
typedef enum [2] { one=1, two=2 } small;
And if there is a combinatorial variable:
comb small my_small;
Then the only two valid assignments to my_small
are one and two
my_small = one; or
my_small = two;
To implement this the language imposes
type scoping on every expression; see the discussion of expressions
below.
|
|
This section discusses issues to do
with expressions in the language
|
Casting |
Implicit casting is performed to
convert the type of an expression to that requried by its context.
Each expression in the language has a type context which can be
determined from the position of the expression in the code.
Explicit casting is not currently
possible; it will be, when a syntax for that has been derived.
|
|
This section discusses issues to do
with lvars in the language
|
Subscripting |
When a bit vector is subscripted in Cyclicity CDL it must produce
another bit vector of a compile-time size. This means that when
subscripting is used to generate a sized bit vector, the size must be
a compile time constant. So the following is valid:
foo <= bar[ 5; jim ]; // This is valid
whereas the following is not
comb bit[2] joe;
foo <= bar[ joe; 0 ]; // This is NEVER valid
|
Bundles |
Unlike in Verilog, where a bundle may
be used as an lvar, lvars in Cyclicity CDL cannot be bundles. Where a
bundle would be used in Verilog an additional combinatorial value may
be required. For example, in verilog:
reg carry, result[30], a[31], b[31];
{carry, result} = a+b;
would require something like:
comb bit[31] a_b_sum;
a_b_sum = a+b;
carry = a_b_sum[30];
result = a_b_sum[30;0];
This makes the language simpler to
interpret from a compiler perspective, but it can also improve the
comprehensibility of code; in the CDL code it is much easier to see
that the signals are of the correct width, and what the code is
actually doing.
|
|
|
|