C++ code generator

A complete C++ class can be generated with methods that read or write the registers. This is done with a call to RegisterList.create_cpp_interface(), RegisterList.create_cpp_header(), or RegisterList.create_cpp_implementation(). The first call will create an abstract interface header that can be used for mocking in a unit test environment.

Interface header

Below is the resulting interface header code, generated from the TOML format example:

Example interface header
// This file is automatically generated by hdl_registers.
// Generated 2022-05-11 06:40 from file regs_example.toml at commit f957ef89efba5ca6.

#pragma once

#include <cassert>
#include <cstdint>
#include <cstdlib>

namespace fpga_regs
{

class IExample
{
public:
  // Register constant.
  static const int axi_data_width = 64L;
  // Register constant.
  static const int address_alignment = 4096L;

  // Number of registers within this register map.
  static const size_t num_registers = 9uL;

  // Length of the "base_addresses" register array
  static const size_t base_addresses_array_length = 3uL;

  virtual ~IExample() { }

  // ---------------------------------------------------------------------------
  // Methods for the "configuration" register. Mode "Read, Write".

  // Getter that will read the whole register's value over the register bus.
  virtual uint32_t get_configuration() const = 0;

  // Setter that will write the whole register's value over the register bus.
  virtual void set_configuration(uint32_t register_value) const = 0;

  // Getter for the "enable" field in the "configuration" register,
  // which will read register value over the register bus.
  virtual uint32_t get_configuration_enable() const = 0;
  // Getter for the "enable" field in the "configuration" register,
  // given the register's current value.
  virtual uint32_t get_configuration_enable_from_value(uint32_t register_value) const = 0;
  // Setter for the "enable" field in the "configuration" register,
  // which will read-modify-write over the register bus.
  virtual void set_configuration_enable(uint32_t field_value) const = 0;
  // Setter for the "enable" field in the "configuration" register,
  // given the register's current value, which will return an updated value.
  virtual uint32_t set_configuration_enable_from_value(uint32_t register_value, uint32_t field_value) const = 0;

  // Getter for the "data_tag" field in the "configuration" register,
  // which will read register value over the register bus.
  virtual uint32_t get_configuration_data_tag() const = 0;
  // Getter for the "data_tag" field in the "configuration" register,
  // given the register's current value.
  virtual uint32_t get_configuration_data_tag_from_value(uint32_t register_value) const = 0;
  // Setter for the "data_tag" field in the "configuration" register,
  // which will read-modify-write over the register bus.
  virtual void set_configuration_data_tag(uint32_t field_value) const = 0;
  // Setter for the "data_tag" field in the "configuration" register,
  // given the register's current value, which will return an updated value.
  virtual uint32_t set_configuration_data_tag_from_value(uint32_t register_value, uint32_t field_value) const = 0;


  // ---------------------------------------------------------------------------
  // Methods for the "status" register. Mode "Read".

  // Getter that will read the whole register's value over the register bus.
  virtual uint32_t get_status() const = 0;

  // Getter for the "idle" field in the "status" register,
  // which will read register value over the register bus.
  virtual uint32_t get_status_idle() const = 0;
  // Getter for the "idle" field in the "status" register,
  // given the register's current value.
  virtual uint32_t get_status_idle_from_value(uint32_t register_value) const = 0;

  // Getter for the "stalling" field in the "status" register,
  // which will read register value over the register bus.
  virtual uint32_t get_status_stalling() const = 0;
  // Getter for the "stalling" field in the "status" register,
  // given the register's current value.
  virtual uint32_t get_status_stalling_from_value(uint32_t register_value) const = 0;

  // Getter for the "counter" field in the "status" register,
  // which will read register value over the register bus.
  virtual uint32_t get_status_counter() const = 0;
  // Getter for the "counter" field in the "status" register,
  // given the register's current value.
  virtual uint32_t get_status_counter_from_value(uint32_t register_value) const = 0;


  // ---------------------------------------------------------------------------
  // Methods for the "command" register. Mode "Write-pulse".

  // Setter that will write the whole register's value over the register bus.
  virtual void set_command(uint32_t register_value) const = 0;

  // Setter for the "start" field in the "command" register,
  // which will set the field to the given value, and all other bits to zero.
  virtual void set_command_start(uint32_t field_value) const = 0;
  // Setter for the "start" field in the "command" register,
  // given the register's current value, which will return an updated value.
  virtual uint32_t set_command_start_from_value(uint32_t register_value, uint32_t field_value) const = 0;

  // Setter for the "flush" field in the "command" register,
  // which will set the field to the given value, and all other bits to zero.
  virtual void set_command_flush(uint32_t field_value) const = 0;
  // Setter for the "flush" field in the "command" register,
  // given the register's current value, which will return an updated value.
  virtual uint32_t set_command_flush_from_value(uint32_t register_value, uint32_t field_value) const = 0;


  // ---------------------------------------------------------------------------
  // Methods for the "read_address" register within the "base_addresses" register array. Mode "Read, Write".

  // Getter that will read the whole register's value over the register bus.
  virtual uint32_t get_base_addresses_read_address(size_t array_index) const = 0;

  // Setter that will write the whole register's value over the register bus.
  virtual void set_base_addresses_read_address(size_t array_index, uint32_t register_value) const = 0;

  // Getter for the "address" field in the "read_address" register within the "base_addresses" register array,
  // which will read register value over the register bus.
  virtual uint32_t get_base_addresses_read_address_address(size_t array_index) const = 0;
  // Getter for the "address" field in the "read_address" register within the "base_addresses" register array,
  // given the register's current value.
  virtual uint32_t get_base_addresses_read_address_address_from_value(uint32_t register_value) const = 0;
  // Setter for the "address" field in the "read_address" register within the "base_addresses" register array,
  // which will read-modify-write over the register bus.
  virtual void set_base_addresses_read_address_address(size_t array_index, uint32_t field_value) const = 0;
  // Setter for the "address" field in the "read_address" register within the "base_addresses" register array,
  // given the register's current value, which will return an updated value.
  virtual uint32_t set_base_addresses_read_address_address_from_value(uint32_t register_value, uint32_t field_value) const = 0;


  // ---------------------------------------------------------------------------
  // Methods for the "write_address" register within the "base_addresses" register array. Mode "Read, Write".

  // Getter that will read the whole register's value over the register bus.
  virtual uint32_t get_base_addresses_write_address(size_t array_index) const = 0;

  // Setter that will write the whole register's value over the register bus.
  virtual void set_base_addresses_write_address(size_t array_index, uint32_t register_value) const = 0;

  // Getter for the "address" field in the "write_address" register within the "base_addresses" register array,
  // which will read register value over the register bus.
  virtual uint32_t get_base_addresses_write_address_address(size_t array_index) const = 0;
  // Getter for the "address" field in the "write_address" register within the "base_addresses" register array,
  // given the register's current value.
  virtual uint32_t get_base_addresses_write_address_address_from_value(uint32_t register_value) const = 0;
  // Setter for the "address" field in the "write_address" register within the "base_addresses" register array,
  // which will read-modify-write over the register bus.
  virtual void set_base_addresses_write_address_address(size_t array_index, uint32_t field_value) const = 0;
  // Setter for the "address" field in the "write_address" register within the "base_addresses" register array,
  // given the register's current value, which will return an updated value.
  virtual uint32_t set_base_addresses_write_address_address_from_value(uint32_t register_value, uint32_t field_value) const = 0;

};

} /* namespace fpga_regs */

Class header

Below is the generated class header:

Example class header
// This file is automatically generated by hdl_registers.
// Generated 2022-05-11 06:40 from file regs_example.toml at commit f957ef89efba5ca6.

#pragma once

#include "i_example.h"

namespace fpga_regs
{

class Example : public IExample
{
private:
  volatile uint32_t *m_registers;

public:
  Example(volatile uint8_t *base_address);

  virtual ~Example() { }

  // ---------------------------------------------------------------------------
  // Methods for the "configuration" register. See interface header for documentation.
  virtual uint32_t get_configuration() const override;
  virtual uint32_t get_configuration_enable() const override;
  virtual uint32_t get_configuration_enable_from_value(uint32_t register_value) const override;
  virtual uint32_t get_configuration_data_tag() const override;
  virtual uint32_t get_configuration_data_tag_from_value(uint32_t register_value) const override;
  virtual void set_configuration(uint32_t register_value) const override;
  virtual void set_configuration_enable(uint32_t field_value) const override;
  virtual uint32_t set_configuration_enable_from_value(uint32_t register_value, uint32_t field_value) const override;
  virtual void set_configuration_data_tag(uint32_t field_value) const override;
  virtual uint32_t set_configuration_data_tag_from_value(uint32_t register_value, uint32_t field_value) const override;

  // ---------------------------------------------------------------------------
  // Methods for the "status" register. See interface header for documentation.
  virtual uint32_t get_status() const override;
  virtual uint32_t get_status_idle() const override;
  virtual uint32_t get_status_idle_from_value(uint32_t register_value) const override;
  virtual uint32_t get_status_stalling() const override;
  virtual uint32_t get_status_stalling_from_value(uint32_t register_value) const override;
  virtual uint32_t get_status_counter() const override;
  virtual uint32_t get_status_counter_from_value(uint32_t register_value) const override;

  // ---------------------------------------------------------------------------
  // Methods for the "command" register. See interface header for documentation.
  virtual void set_command(uint32_t register_value) const override;
  virtual void set_command_start(uint32_t field_value) const override;
  virtual uint32_t set_command_start_from_value(uint32_t register_value, uint32_t field_value) const override;
  virtual void set_command_flush(uint32_t field_value) const override;
  virtual uint32_t set_command_flush_from_value(uint32_t register_value, uint32_t field_value) const override;

  // ---------------------------------------------------------------------------
  // Methods for the "read_address" register within the "base_addresses" register array. See interface header for documentation.
  virtual uint32_t get_base_addresses_read_address(size_t array_index) const override;
  virtual uint32_t get_base_addresses_read_address_address(size_t array_index) const override;
  virtual uint32_t get_base_addresses_read_address_address_from_value(uint32_t register_value) const override;
  virtual void set_base_addresses_read_address(size_t array_index, uint32_t register_value) const override;
  virtual void set_base_addresses_read_address_address(size_t array_index, uint32_t field_value) const override;
  virtual uint32_t set_base_addresses_read_address_address_from_value(uint32_t register_value, uint32_t field_value) const override;

  // ---------------------------------------------------------------------------
  // Methods for the "write_address" register within the "base_addresses" register array. See interface header for documentation.
  virtual uint32_t get_base_addresses_write_address(size_t array_index) const override;
  virtual uint32_t get_base_addresses_write_address_address(size_t array_index) const override;
  virtual uint32_t get_base_addresses_write_address_address_from_value(uint32_t register_value) const override;
  virtual void set_base_addresses_write_address(size_t array_index, uint32_t register_value) const override;
  virtual void set_base_addresses_write_address_address(size_t array_index, uint32_t field_value) const override;
  virtual uint32_t set_base_addresses_write_address_address_from_value(uint32_t register_value, uint32_t field_value) const override;
};

} /* namespace fpga_regs */

Implementation

Below is the generated class implementation:

Example class implementation
// This file is automatically generated by hdl_registers.
// Generated 2022-05-11 06:40 from file regs_example.toml at commit f957ef89efba5ca6.

#include "include/example.h"

namespace fpga_regs
{

Example::Example(volatile uint8_t *base_address)
    : m_registers(reinterpret_cast<volatile uint32_t *>(base_address))
{
  // Empty
}


// -----------------------------------------------------------------------------
// Methods for the "configuration" register. See interface header for documentation.

uint32_t Example::get_configuration() const
{
  const size_t index = 0;
  const uint32_t result = m_registers[index];

  return result;
}

uint32_t Example::get_configuration_enable() const
{
  const uint32_t register_value = get_configuration();
  const uint32_t result = get_configuration_enable_from_value(register_value);

  return result;
}

uint32_t Example::get_configuration_enable_from_value(uint32_t register_value) const
{
  const uint32_t shift = 0uL;
  const uint32_t mask_at_base = 0b1uL;
  const uint32_t mask_shifted = mask_at_base << shift;

  const uint32_t result_masked = register_value & mask_shifted;
  const uint32_t result_shifted = result_masked >> shift;

  return result_shifted;
}

uint32_t Example::get_configuration_data_tag() const
{
  const uint32_t register_value = get_configuration();
  const uint32_t result = get_configuration_data_tag_from_value(register_value);

  return result;
}

uint32_t Example::get_configuration_data_tag_from_value(uint32_t register_value) const
{
  const uint32_t shift = 1uL;
  const uint32_t mask_at_base = 0b1111uL;
  const uint32_t mask_shifted = mask_at_base << shift;

  const uint32_t result_masked = register_value & mask_shifted;
  const uint32_t result_shifted = result_masked >> shift;

  return result_shifted;
}

void Example::set_configuration(uint32_t register_value) const
{
  const size_t index = 0;
  m_registers[index] = register_value;
}

void Example::set_configuration_enable(uint32_t field_value) const
{
  // Get the current value of any other fields by reading register on the bus.
  const uint32_t current_register_value = get_configuration();
  const uint32_t result_register_value =  set_configuration_enable_from_value(current_register_value, field_value);
  set_configuration(result_register_value);
}

uint32_t Example::set_configuration_enable_from_value(uint32_t register_value, uint32_t field_value) const
{
  const uint32_t shift = 0uL;
  const uint32_t mask_at_base = 0b1uL;
  const uint32_t mask_shifted = mask_at_base << shift;

  const uint32_t field_value_masked = field_value & mask_at_base;
  const uint32_t field_value_masked_and_shifted = field_value_masked << shift;

  const uint32_t mask_shifted_inverse = ~mask_shifted;
  const uint32_t register_value_masked = register_value & mask_shifted_inverse;

  const uint32_t result_register_value = register_value_masked | field_value_masked_and_shifted;

  return result_register_value;
}

void Example::set_configuration_data_tag(uint32_t field_value) const
{
  // Get the current value of any other fields by reading register on the bus.
  const uint32_t current_register_value = get_configuration();
  const uint32_t result_register_value =  set_configuration_data_tag_from_value(current_register_value, field_value);
  set_configuration(result_register_value);
}

uint32_t Example::set_configuration_data_tag_from_value(uint32_t register_value, uint32_t field_value) const
{
  const uint32_t shift = 1uL;
  const uint32_t mask_at_base = 0b1111uL;
  const uint32_t mask_shifted = mask_at_base << shift;

  const uint32_t field_value_masked = field_value & mask_at_base;
  const uint32_t field_value_masked_and_shifted = field_value_masked << shift;

  const uint32_t mask_shifted_inverse = ~mask_shifted;
  const uint32_t register_value_masked = register_value & mask_shifted_inverse;

  const uint32_t result_register_value = register_value_masked | field_value_masked_and_shifted;

  return result_register_value;
}


// -----------------------------------------------------------------------------
// Methods for the "status" register. See interface header for documentation.

uint32_t Example::get_status() const
{
  const size_t index = 1;
  const uint32_t result = m_registers[index];

  return result;
}

uint32_t Example::get_status_idle() const
{
  const uint32_t register_value = get_status();
  const uint32_t result = get_status_idle_from_value(register_value);

  return result;
}

uint32_t Example::get_status_idle_from_value(uint32_t register_value) const
{
  const uint32_t shift = 0uL;
  const uint32_t mask_at_base = 0b1uL;
  const uint32_t mask_shifted = mask_at_base << shift;

  const uint32_t result_masked = register_value & mask_shifted;
  const uint32_t result_shifted = result_masked >> shift;

  return result_shifted;
}

uint32_t Example::get_status_stalling() const
{
  const uint32_t register_value = get_status();
  const uint32_t result = get_status_stalling_from_value(register_value);

  return result;
}

uint32_t Example::get_status_stalling_from_value(uint32_t register_value) const
{
  const uint32_t shift = 1uL;
  const uint32_t mask_at_base = 0b1uL;
  const uint32_t mask_shifted = mask_at_base << shift;

  const uint32_t result_masked = register_value & mask_shifted;
  const uint32_t result_shifted = result_masked >> shift;

  return result_shifted;
}

uint32_t Example::get_status_counter() const
{
  const uint32_t register_value = get_status();
  const uint32_t result = get_status_counter_from_value(register_value);

  return result;
}

uint32_t Example::get_status_counter_from_value(uint32_t register_value) const
{
  const uint32_t shift = 2uL;
  const uint32_t mask_at_base = 0b11111111uL;
  const uint32_t mask_shifted = mask_at_base << shift;

  const uint32_t result_masked = register_value & mask_shifted;
  const uint32_t result_shifted = result_masked >> shift;

  return result_shifted;
}


// -----------------------------------------------------------------------------
// Methods for the "command" register. See interface header for documentation.

void Example::set_command(uint32_t register_value) const
{
  const size_t index = 2;
  m_registers[index] = register_value;
}

void Example::set_command_start(uint32_t field_value) const
{
  // This register type's currently written value can not be read back.
  // Hence set all other bits to zero when writing the value.
  const uint32_t current_register_value = 0;
  const uint32_t result_register_value =  set_command_start_from_value(current_register_value, field_value);
  set_command(result_register_value);
}

uint32_t Example::set_command_start_from_value(uint32_t register_value, uint32_t field_value) const
{
  const uint32_t shift = 0uL;
  const uint32_t mask_at_base = 0b1uL;
  const uint32_t mask_shifted = mask_at_base << shift;

  const uint32_t field_value_masked = field_value & mask_at_base;
  const uint32_t field_value_masked_and_shifted = field_value_masked << shift;

  const uint32_t mask_shifted_inverse = ~mask_shifted;
  const uint32_t register_value_masked = register_value & mask_shifted_inverse;

  const uint32_t result_register_value = register_value_masked | field_value_masked_and_shifted;

  return result_register_value;
}

void Example::set_command_flush(uint32_t field_value) const
{
  // This register type's currently written value can not be read back.
  // Hence set all other bits to zero when writing the value.
  const uint32_t current_register_value = 0;
  const uint32_t result_register_value =  set_command_flush_from_value(current_register_value, field_value);
  set_command(result_register_value);
}

uint32_t Example::set_command_flush_from_value(uint32_t register_value, uint32_t field_value) const
{
  const uint32_t shift = 1uL;
  const uint32_t mask_at_base = 0b1uL;
  const uint32_t mask_shifted = mask_at_base << shift;

  const uint32_t field_value_masked = field_value & mask_at_base;
  const uint32_t field_value_masked_and_shifted = field_value_masked << shift;

  const uint32_t mask_shifted_inverse = ~mask_shifted;
  const uint32_t register_value_masked = register_value & mask_shifted_inverse;

  const uint32_t result_register_value = register_value_masked | field_value_masked_and_shifted;

  return result_register_value;
}


// -----------------------------------------------------------------------------
// Methods for the "read_address" register within the "base_addresses" register array. See interface header for documentation.

uint32_t Example::get_base_addresses_read_address(size_t array_index) const
{
  assert(array_index < base_addresses_array_length);
  const size_t index = 3 + array_index * 2 + 0;
  const uint32_t result = m_registers[index];

  return result;
}

uint32_t Example::get_base_addresses_read_address_address(size_t array_index) const
{
  const uint32_t register_value = get_base_addresses_read_address(array_index);
  const uint32_t result = get_base_addresses_read_address_address_from_value(register_value);

  return result;
}

uint32_t Example::get_base_addresses_read_address_address_from_value(uint32_t register_value) const
{
  const uint32_t shift = 0uL;
  const uint32_t mask_at_base = 0b1111111111111111111111111111uL;
  const uint32_t mask_shifted = mask_at_base << shift;

  const uint32_t result_masked = register_value & mask_shifted;
  const uint32_t result_shifted = result_masked >> shift;

  return result_shifted;
}

void Example::set_base_addresses_read_address(size_t array_index, uint32_t register_value) const
{
  assert(array_index < base_addresses_array_length);
  const size_t index = 3 + array_index * 2 + 0;
  m_registers[index] = register_value;
}

void Example::set_base_addresses_read_address_address(size_t array_index, uint32_t field_value) const
{
  // Get the current value of any other fields by reading register on the bus.
  const uint32_t current_register_value = get_base_addresses_read_address(array_index);
  const uint32_t result_register_value =  set_base_addresses_read_address_address_from_value(current_register_value, field_value);
  set_base_addresses_read_address(array_index, result_register_value);
}

uint32_t Example::set_base_addresses_read_address_address_from_value(uint32_t register_value, uint32_t field_value) const
{
  const uint32_t shift = 0uL;
  const uint32_t mask_at_base = 0b1111111111111111111111111111uL;
  const uint32_t mask_shifted = mask_at_base << shift;

  const uint32_t field_value_masked = field_value & mask_at_base;
  const uint32_t field_value_masked_and_shifted = field_value_masked << shift;

  const uint32_t mask_shifted_inverse = ~mask_shifted;
  const uint32_t register_value_masked = register_value & mask_shifted_inverse;

  const uint32_t result_register_value = register_value_masked | field_value_masked_and_shifted;

  return result_register_value;
}


// -----------------------------------------------------------------------------
// Methods for the "write_address" register within the "base_addresses" register array. See interface header for documentation.

uint32_t Example::get_base_addresses_write_address(size_t array_index) const
{
  assert(array_index < base_addresses_array_length);
  const size_t index = 3 + array_index * 2 + 1;
  const uint32_t result = m_registers[index];

  return result;
}

uint32_t Example::get_base_addresses_write_address_address(size_t array_index) const
{
  const uint32_t register_value = get_base_addresses_write_address(array_index);
  const uint32_t result = get_base_addresses_write_address_address_from_value(register_value);

  return result;
}

uint32_t Example::get_base_addresses_write_address_address_from_value(uint32_t register_value) const
{
  const uint32_t shift = 0uL;
  const uint32_t mask_at_base = 0b1111111111111111111111111111uL;
  const uint32_t mask_shifted = mask_at_base << shift;

  const uint32_t result_masked = register_value & mask_shifted;
  const uint32_t result_shifted = result_masked >> shift;

  return result_shifted;
}

void Example::set_base_addresses_write_address(size_t array_index, uint32_t register_value) const
{
  assert(array_index < base_addresses_array_length);
  const size_t index = 3 + array_index * 2 + 1;
  m_registers[index] = register_value;
}

void Example::set_base_addresses_write_address_address(size_t array_index, uint32_t field_value) const
{
  // Get the current value of any other fields by reading register on the bus.
  const uint32_t current_register_value = get_base_addresses_write_address(array_index);
  const uint32_t result_register_value =  set_base_addresses_write_address_address_from_value(current_register_value, field_value);
  set_base_addresses_write_address(array_index, result_register_value);
}

uint32_t Example::set_base_addresses_write_address_address_from_value(uint32_t register_value, uint32_t field_value) const
{
  const uint32_t shift = 0uL;
  const uint32_t mask_at_base = 0b1111111111111111111111111111uL;
  const uint32_t mask_shifted = mask_at_base << shift;

  const uint32_t field_value_masked = field_value & mask_at_base;
  const uint32_t field_value_masked_and_shifted = field_value_masked << shift;

  const uint32_t mask_shifted_inverse = ~mask_shifted;
  const uint32_t register_value_masked = register_value & mask_shifted_inverse;

  const uint32_t result_register_value = register_value_masked | field_value_masked_and_shifted;

  return result_register_value;
}


} /* namespace fpga_regs */

Note that when the register is part of an array, the register setter/getter takes a second argument array_index. There is an assert that the user-provided array index is within the bounds of the array.

Getters

It can be noted, most clearly in the Interface header, that there are three ways to read a register field:

  1. The method that reads the whole register, e.g. get_configuration().

  2. The method that reads the register and then slices out the field value, e.g. get_configuration_enable().

  3. The method that slices out the field value given a previously read register value, e.g. get_configuration_enable_from_value(register_value).

Method (2) is the most convenient in most cases. However if we want to read out more than one field from a register it would be very inefficient to read the register value more than once over the register bus, which would be the result of calling (2) multiple times. Instead we can call (1) once and then (3) multiple times to get our field values.

Setters

Conversely there are three ways to write a register field:

  1. The method that writes the whole register, e.g. set_configuration().

  2. The method that reads the register, updates the value of the field, and then writes the register back, e.g. set_configuration_enable().

  3. The method that updates the value of the field given a previously read register value, and returns an updated register value, e.g. set_configuration_enable_from_value(register_value).

Method (2) is the most convenient in most cases. However if we want to update more than one field of a register it would be very inefficient to read and write the register more than once over the register bus, which would be the result of calling (2) multiple times. Instead we can call a register getter once, e.g. get_configuration(), and then (3) multiple times to get our updated register value. This value is then written over the register bus using (1).

Exceptions

The discussion about setters above is valid for “read write” mode registers, which is arguably the most common type. However there are three register modes where the previously written register value can not be read back over the bus and then modified: “write only”, “write pulse”, and “read, write pulse”. The field setters for registers of this mode will write all bits outside of the current field as zero. This can for example be seen in the setter set_command_start() in the generated code above.