Procs
proc setBitsSlice[T: SomeInteger; V](b: var T; slice: Slice[int]; x: V)
Macros
macro bitfields(name, def: untyped)
-
Create a new distinct integer type with accessors for bitfields that set and get bits for each field. This is more stable than C-style bitfields (see below).
- The basic syntax for a bitfield declarations is:
- fieldname: uint8[4..5]
- - fieldName is the name of the accessors and produces both
- a getter (fieldName) and setter (fieldName=)
- - the range 4..5 is the target bit indexes. The ranges are
- inclusive meaning 6 ... 6 is 1 bit. Ranges are sorted so you can also use 5 .. 4 to match hardware documentation.
- The type uint8 is the type that the bits are converted to/from.
Signed types like int8 are supported and do signed shifts to
- properly extend the sign. For example:
- speed: int8[7..4]
The accessors generated are very simple and what you would generally produce by hand. For example:
bitfields RegConfig(uint16): speed: int8[4..2]
- Generates code similar too:
type RegChannel = distinct uint16 proc speed*(reg: RegChannel): uint8 = result = uint8(bitsliced(uint16(reg), 4 .. 9)) proc speed=*(reg: var RegChannel; x: uint8) = setBitsSlice(uint16(reg), 4 .. 9, x)
This is often preferable to C-style bitfields which Nim does support. C-style bitfields are compiler and architecture dependent and prone to breaking on field alignement, endiannes, and other issues. See https://lwn.net/Articles/478657/
Example:
bitfields RegConfig(uint8): ## define RegConfig integer with accessors for `bitfields` clockEnable: bool[7..7] daisyIn: bool[6..6] speed: int8[5..1] ## Now use it to make a new register field var regConfig: RegConfig regConfig.clockEnable= true regConfig.speed= -10 echo "regConfig.speed ", regConfig.speed assert regConfig.clockEnable == true assert regConfig.speed == -10 ## the type of `RegConfig` is just a `distinct uint8` import typetraits assert distinctBase(typeof(regConfig)) is uint8