Difference between revisions of "Metadata"
Line 30: | Line 30: | ||
The overflow and underflow and rounding behaviour of floating point operations is captures in a neumber of flags. On conventional processors those tend to be global state flags. On the Mill this wouldn't work because global state flags introduce unnecessary data dependencies and prevent speculation. For this reason every operand carries its own state flags. | The overflow and underflow and rounding behaviour of floating point operations is captures in a neumber of flags. On conventional processors those tend to be global state flags. On the Mill this wouldn't work because global state flags introduce unnecessary data dependencies and prevent speculation. For this reason every operand carries its own state flags. | ||
+ | |||
+ | == Rationale == | ||
+ | |||
+ | The two main tasks of metadata are to vastly improve code density by giving operands types they carry around with them and to enable aggressive speculative execution of branches. It also helps a lot in debugging. | ||
+ | |||
+ | A few extra bits in the central data paths are cheap compared to the complex functional hardware and instruction set creep on conventional machines that provide the same features. |
Revision as of 22:31, 28 July 2014
All operands on the belt, additionally to the actual byte pattern that makes up the value, carry around a few bits of metadata that inform and augment how the vast majority of operations on those operands work.
This metadata is not restricted to the Belt, but is preserved in the Scratchpad and carries through the result registers in the Slots and so forth. The metadata is lost on stores. But loads intialize it together with the value, since load operations have the basic metadata tags hardcoded into them.
Contents
The Metadata Fields
Width
Every operand value is tagged with its byte width, i.e. 1, 2, 4, 8, 16. The width doesn't say anything about the interpretation of the bits. An 8 byte value can serve as input for signed and unsigned interger arithmetics, for double float operations and for pointer arithmetics. How successful those operations work out of course depends on the specific bitpattern and the operation semantics. NaN bitpatterns can cause Faults with IEEE 754 operations and work perfectly fine as integers.
There are narrow and widen instructions to change the width of an operand.
Scalarity
Any operand can be a SIMD vector, or slice for short, usually with 4 elements. Although the SIMD element count depends on the Specification of the processor, it can be more. The width of these elements can be any of the available widths of scalars on the processor.
Most operations are polymorphic over the Width and Scalarity tags, i.e. the same opcode performs 8bit to 128bit integer arithmetics for scalars and vectors depending on the metadata of the input operands.
Narrow and widen work for slices too, although widen produces 2 outputs with doubled width elements to avoid overflows for the maximum widths.
None and NaR
Every operand, and every element in a SIMD slice, has a bit that determines whether a value is valid or not. When the actual value content of the operand is zero, this is a None value, an invalid operand that just gets ignored and/or propagated by any operation performed on it. In fact whenever a new belt is created for a new frame, this is the value all belt positions are initalized to by default.
When the operand value is something else from zero it is a NaR value. Also an invalid value that gets propagated by any operation performed on it. But some operations, when they encounter a NaR raise a fault.
Nones and NaRs come in very handy for Speculation and Debugging, more on that there.
IEEE 754 Floating Point Flags
The overflow and underflow and rounding behaviour of floating point operations is captures in a neumber of flags. On conventional processors those tend to be global state flags. On the Mill this wouldn't work because global state flags introduce unnecessary data dependencies and prevent speculation. For this reason every operand carries its own state flags.
Rationale
The two main tasks of metadata are to vastly improve code density by giving operands types they carry around with them and to enable aggressive speculative execution of branches. It also helps a lot in debugging.
A few extra bits in the central data paths are cheap compared to the complex functional hardware and instruction set creep on conventional machines that provide the same features.