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 Interface";
Description = "Example interface description.";
Blocks = [];
}
}
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.