Registers defined in the DML files are automatically registered as both object structure variables and attributes. The line:
register aprom_0 size 1 @ 0x00 "Address PROM (MAC address)";
will define a variable in the object structure that contains the value of the register aprom_0. It will also define a corresponding attribute so that the state of the register can be saved and restored during checkpointing.
You can also manually add attributes in DML. All that is required is an attribute declaration, including name, type and configuration type. If the type of the attribute is simple, then the declaration itself is sufficient and the default set/get methods will be used.
The simplest possible attribute holds the value of a simple data type and allows the attribute to be read and written without any side effects. Let us take the example of a counter attribute:
attribute counter { parameter documentation = "A sample counter attribute"; parameter type = "i"; parameter allocate_type = "int64"; parameter configuration = "required"; }
The two type declarations serve different purposes. The "i" tells Simics type system to check the value in set and get operations for an integer type. allocate_type defines the internal representation of the attribute value. It is perfectly possible to let those differ to be incompatible, but if they do, you must provide get/set methods that do the correct conversions. See the DML Reference Manual for details.
When the attribute is more complex, for example if writing an attribute can have side effects, or if it contains by a complex data type, the set/get methods must be provided. They are defined as:
method set(attr_value_t val) { ... } method get() -> (attr_value_t val) { ... }
A slightly more complicated example is a pseudo attribute which, when setting values, will add to the value of the counter, and for which getting is an error.
attribute add_counter { parameter documentation = "A sample pseudo attribute"; parameter type = "i"; parameter configuration = "pseudo"; method set(val) { $counter += val.u.integer; } method get() -> (val) { log "error", 1, 1 : "Get is not allowed"; throw; } }
Note that no type check is required in the set method, since the type "i" is unambiguously checked by Simics. Note also that there is no allocate_type parameter for the attribute. Since it is a pseudo attribute that does not store any value, there is no type to allocate.