HxS Language

This sections describes the HxS language constructs and how to design hardware / software interfaces with it.

Language Concepts

HxS is a domain-specific language that has been created having the following points in mind.

  • Reduce complexity
  • Be concise
  • Support interface design
  • Declarative description of hardware-software interfaces
  • Support readability
  • Support reusability
  • Support documentation
  • Have namespaces
  • Have sensible defaults to reduce verbosity
  • Deduce values were possible to reduce manual work

Keywords

  • use
  • namespace
  • interface
  • block
  • register
  • delegate
  • data
  • enum
  • reserved
  • value
  • reset
  • select

Scopes

HxS objects such as namespaces, interfaces or blocks create scopes. A HxS object's id is only visible in the scope where it is declared, but it can be referred to from anywhere using its qualified name. The qualified name consists of the namespace and the object hierarchy.


    namespace Eccelerators.Docs
    {
        interface ExampleInterface { }
    }
                        

ExampleInterface is referrable within the same namespace using the id ExampleInterface. If it where to be referred to from another namespace, the qualified name Eccelerators.Docs.ExampleInterface has to be used instead.

Objects

All language elements of the HxS language are represented using objects. Objects have an identifier and a qualified name supporting namespaces. Objects consist of a list of properties and may containt themselves other objects. This is an example of the interface object. It has several properties such as Name, Description and Blocks.


    namespace Eccelerators.Docs
    {
        interface ExampleInterface
        {
            Name = "Example Hardware / Software Interface";
            Description = "A lengthy hardware / software interface description.";
            Blocks = [
                ReferenceToBlock0,
                ReferenceToBlock1
            ];
        }
    }
                        

Properties

All HxS objects provide a set of properties used to describe their part of a hardware / software interface. Each property expects a specific type for its value assignment. Properties cannot be declared, instead the name and type is predefined by the HxS language.


    namespace Eccelerators.Docs
    {
        interface ExampleInterface
        {
            Name = ''; // Expects a string
            Description = ''; // Expects a string
            BusDescription = ''; // Expects a string
            Blocks = []; // Expects a list
        }
    }
                        

Types

The HxS language has several types used to describe properties of hardware / software interfaces.

Strings

The language supports single quoted and double quoted strings. Single quoted strings are plain strings, whereas double quoted strings are interpolated and can contain references to object properties.

Numbers

Numbers are represented as decimal (e.g. 0, 10, 1234), hexadecimal (e.g. 0x0, 0x10, 0x1234), or in binary format (e.g. 0b1, 0b0, 0b1111_0000).

Bit Values

Bit values are different than plain binary values. Bit values may have wildcards in their bit sequence such as a R which stands for remaining bits or a *. Examples are: 0b01R or 0b01*

Reset Values

Reset values are also special and use their own notation. Reset values may have undefined bits in their value description. Therefore reset values may contain an U for undefined (e.g. 0b01U). A wildcard * and R for remaining bits is not allowed.

Lists

Properties of type list contain multiple elements of the same type.


    namespace Eccelerators.Docs
    {
        interface ExampleInterface
        {
            Name = "Example Interface";
            Description = "A example interface description.";
            Blocks = [
                ReferenceToBlock0,
                ReferenceToBlock1
            ];
        }
    }
                        

Dictionaries

Properties that expect a value of type dictionary assign keys to values. Here is an example specifying an enum.


    namespace Eccelerators.Docs
    {
        enum RedLed
        {
            Name = "Red LED";
            Description = "Switches the red LED on or off.";
            Values = {
                0b0 : "Off",
                0b1 : "On"
            };
        }
    }
                        

References

References are a fundamental concept for reusability. In the example below the interface ExampleInterface refers to ExampleBlock multiple times.


    namespace Eccelerators.Examples.Interfaces
    {
        interface ExampleInterface
        {
            Name = "Example Interface";
            Description = "Example interface description.";
            Blocks = [
                ExampleBlock,
                ExampleBlock,
                ExampleBlock
            ];
        }

        block ExampleBlock { }
    }
                        

Namespaces

Namespaces are used to group objects, whether they are in the same file or spread throughout multiple files. Thus, they are fundamental to build libraries of reusable objects. In the example below the interface ExampleInterface refers to ExampleBlock. ExampleBlock resides in another file using another namespace that is brought into scope using the use statement at the top of the snippet.


    // FileA.hxs
    use Eccelerators.Example.Blocks.*;

    namespace Eccelerators.Examples.Interfaces
    {
        interface ExampleInterface
        {
            Name = "Example Interface";
            Description = "Example interface description.";
            Blocks = [
                ExampleBlock,
                ExampleBlock,
                ExampleBlock
            ];
        }
    }

    // FileB.hxs
    namespace Eccelerators.Example.Blocks
    {
        block ExampleBlock { }
    }
                        

Annotations

Annotations are a way to set configurations for generators. Here is an example that forces the VHDL generator to use snake case for its output.


    namespace Eccelerators.HxS.Tests
    {
        @Generator('vhdl.letter_case', 'snake_case')
        interface ExampleInterface
        {
            Name = "Example Interface";
            Description = "Example interface description.";
        }
    }
                        

Parameter Syntax

The parameter syntax is a shortcut for overriding properties. Instead of having to create multiple different objects, a common object can be referenced and adjusted as needed.


    namespace Eccelerators.Docs
    {
        interface ExampleInterface
        {
            Name = "Example Interface";
            Description = "Example interface description.";
            Blocks = [
                ExampleBlock(Name="Example Block 1"),
                ExampleBlock(Name="Example Block 2"),
                ExampleBlock(Name="Example Block 3")
            ];
        }

        block ExampleBlock
        {
            Name = "Example Block";
        }
    }
                        

String Interpolation

Single quoted strings are simple and do not support string interpolation. Double quoted strings use french quotes (i.e. « and ») to specify references to HxS object properties (e.g. «ExampleInterface.Id»).


    namespace Eccelerators.HxS.Docs
    {
        interface ExampleInterface
        {
            Name = 'Example Interface';
            Description = "
                This is my id: «ExampleInterface.Id»
                This is my fully qualified name: «ExampleInterface.FQN»
                This is my name: «ExampleInterface.Name»
            ";
        }
    }
                        

Text Property Reuse

Using string interpolation it is possible to reuse text properties and extend them like in the following example.


    namespace Eccelerators.HxS.Docs
    {
        interface ExampleInterfaceA
        {
            Name = "Example Interface A";
            Description = "Description of example interface A.";
        }

        interface ExampleInterfaceB
        {
            Name = "Example Interface B";
            Description = "
                «ExampleInterfaceA.Description»

                Additional description of interface B.
            ";
        }
    }
                        

Inheritance

Using inheritance an object derives properties and their assigned values from another object. Inheritance can be used to extend or override properties of objects.


    namespace Eccelerators.HxS.Docs
    {
        interface ExampleInterfaceA
        {
            Name = "Example Interface A";
            Description = "Description of example interface A.";
        }

        interface ExampleInterfaceB : ExampleInterfaceA
        {
            Name = "Overriden Name of Example Interface B";
        }
    }
                        

Auto-Calculations

The following HxS objects use automatic calculations for their offset, address, width, or position properties. It is notable that auto-calculations can be overriden at any time specifying the particular property explicitly.

HxS Object HxS Property
Interface Size
Block Size, BaseAddress
Register Address, Offset, Width
Enum Position, Width
Data Position
Reserved Position

Versioning

Every object has a version property, that is a string that can be used to version objects for reusability.

Libraries

Libraries of objects may be created for maximum reusability.