dev_util — A Python module for writing device model tests.
import dev_util
It has three major parts:
It uses the Simics API and can only be used by Python code running in Simics.
class dev_util.Error
Baseclass of all exceptions specified in this module.
class dev_util.InvalidBitfieldException
Signals that a bitfield’s parameters are invalid.
class dev_util.RangeError(msg, re=None)
Signals that a value is out of range for a bitfield.
class dev_util.MemoryError
Signals that a memory operation failed.
class dev_util.Bitfield(
fields=None,
ones=0,
little_endian=True,
bits=None,
**kwargs
)
Utility for bitfield manipulations.
fields{'field-name' : bit-number,
'field-name' : (start-bit, stop-bit),
'field-name' : (start-bit, sub-field)
}
oneslittle_endianbits**kwargsfields, but specified using keyword argumentsdev_util.Bitfield.fields(value)
Parse an integer into a dict with one item per field.
Returns a dict consisting of all fields and their values, taken from the value argument.
dev_util.Bitfield.mask(**dict)
Returns a mask from the fields in dict.
dev_util.Bitfield.mk_bitfield_map(m, prefix='', oset=0)
Make bitfield map.
Convert a nested layout type to a map suitable for construction of a dev_util.Bitfield object.
dev_util.Bitfield.value(*args, **kwargs)
Returns the value of the fields given by **kwargs.
For example, pass foo=5 to return the value when field foo is 5. If the value is a list or dict rather than an integer, then a field array is assumed; e.g. foo=[1,2] is a shorthand for setting field foo[0] to 1 and field foo[1] to 2, and foo={1:4} is a shorthand for setting field foo[1] to 4.
An optional positional argument can be supplied, to provide the values of bits not covered by the given fields.
class dev_util.Bitfield_LE(fields=None, ones=0, **kwargs)
Little-endian bitfield.
fields{'field-name' : bit-number,
'field-name' : (start-bit, stop-bit),
'field-name' : (start-bit, sub-field)
}
ones**kwargsfields, but specified using keyword argumentsclass dev_util.Bitfield_BE(fields=None, ones=0, bits=None, **kwargs)
Big-endian bitfield.
fields{'field-name' : bit-number,
'field-name' : (start-bit, stop-bit),
'field-name' : (start-bit, sub-field)
}
ones**kwargsfields, but specified using keyword argumentsclass dev_util.AbstractRegister(size=4, bitfield=None, little_endian=True)
Abstract register class.
This class handles generic register stuff, like bitfield mapping and value construction/deconstruction. It depends on a subclass to implement the backend for data storage.
Subclasses are expected to implement two functions:
raw_read(self)raw_write(self, bytes)bytes byte string to storageOptionally, a bitfield can be applied to a register. For such a register, a specific field can be read through reg.field.FIELDNAME.read(). The write() method also has support for bitfields. Please see the documentation for write() for more information.
There is an alternative deprecated shorthand for accessing fields: reg.FIELDNAME triggers a read that filters out the given field, and similarly, reg.FIELDNAME = value reads the field, adjusts the given field, and writes back the value. This syntax is deprecated, because it is not consistent with the API exposed by register objects that both support accesses with and without side-effects.
sizebitfieldlittle_endiandev_util.AbstractRegister.fields()
Shortcut to read the bitfield representation of a device register.
dev_util.AbstractRegister.read()
Read value.
dev_util.AbstractRegister.write(*args, **fields)
Write value. The value will be truncated to the register size.
You can either pass a single integer, or pass the fields as arguments, i.e., write(field0=1, field1=23). For field arrays, the syntax write(field=[1,23]) or write(field={0: 1, 1: 23}) can be used to set the fields named field[0] and field[1].
If only a subset of fields is given, a positional arg should also be passed for the base value, which defines what to write to remaining bits. The value READ denotes that the read() method is called to retrieve the base value.
class dev_util.Register(
bank,
offset,
size=4,
bitfield=None,
little_endian=True,
initiator=None
)
This class allows you to easily access a device register.
The bank argument is normally the bank object. However, for backward compatibility it can also be a tuple (obj, bank, ofs); in this case the offset argument should be left out. The tuple denotes:
objbankoffsetThe tuple syntax was useful in old Simics versions where banks were not separate objects. It should be avoided in new versions.
The initiator argument denotes the initiator of transactions accessing the register.
See the AbstractRegister documentation for information about the rest of the parameters.
dev_util.Register.raw_read()
Read raw data from the register.
dev_util.Register.raw_write(val)
Write raw data to the register.
class dev_util.Register_LE(bank, offset, size=4, bitfield=None, initiator=None)
Little-endian device register.
All arguments have the same semantics as in dev_util.Register.
class dev_util.Register_BE(bank, offset, size=4, bitfield=None, initiator=None)
Big-endian device register.
All arguments have the same semantics as in dev_util.Register.
class dev_util.GRegister(size=4, bitfield=None, init=0)
This class allows provides a standalone register.
dev_util.GRegister.raw_read()
Reads the raw contents of the register.
dev_util.GRegister.raw_write(value)
Write the raw contents of the register.
class dev_util.IRegister(data, size=None, bitfield=None)
Register from int_register.
This class allows you to easily access registers through the int_register interface. If the object obj does not implement the processor_info you have to specify the size in size.
dev_util.IRegister.raw_read()
Reads the raw contents of the register.
dev_util.IRegister.raw_write(value)
Write the raw contents of the register.
dev_util.bank_regs(bank, inquiry=False, prefix='')
Return structure containing object to access a bank’s registers.
Given a bank object, return a structure containing objects to access its registers. The returned structure can be a hierarchy of objects; e.g., if a register instance is named "g[2][3].r[1]", and the returned structure is o, then the corresponding register object can be obtained as o.g[2][3].g[1]. The set of registers is extracted using the register_view interface, and uses offsets and bitfields as returned by that interface. The inquiry argument is deprecated and should not be used. If prefix is given, then the returned structure will only contain registers whose full name matches this prefix.
The returned register objects have methods read() and write() that work like their AbstractRegister counterparts, reading and writing the register with side-effects. The register value can be read and written without side-effects objects by getting and setting a property .val, or by calling a method set(). The latter accepts keyword arguments for fields just like the write() method; bits not covered by fields are retrieved by reading .val. The positional argument of the write() method is required and may be either an integer, or READ to denote that previous values are retrieved using read(), or VAL to denote that they are retrieved using .val.
In addition to the val property and set, read and write methods mentioned above, register objects also have the following properties:
bank: The Simics configuration object of the banksize, offset: the register’s location within the bankbitfield: a dev_util.Bitfield describing thename: the name of the register, relative to the bank.Objects that represent the fields of a register can be retrieved as reg.field.FIELDNAME; e.g., if a register reg has a field named "a.b[2]" then the field object is accessed as reg.field.a.b[2]. The field object has one method read() for performing a full-register read with side-effects and returning the bits corresponding to the field, and a property .val that allows side-effect free access to the field’s bits. Field objects provide a read method, which reads the parent register and returns the bits corresponding to the field, but it does not have a write method; writes must be done from the register object to ensure that remaining bits are explicitly specified. Field objects also provide the following properties:
reg: The parent register objectlsb, bits: the bit range within the parent registername: the name of the field, relative to the parent registerclass dev_util.Dev(iface_list=[], create_sim_obj=True, name=None)
Deprecated. A Simics class with a single instance.
Implements zero or more interfaces based on instances of Iface. Presents zero or more ports, implementing one or more interfaces each.
The obj attribute contains the instance of the Simics class, and the cls_name attribute contains the name of the Simics class.
iface_listcreate_sim_objnameEach interface will be instantiated and can be accessed through dev.iface-name, or dev.port.iface-name.
dev = Dev([SimpleInterrupt,
('sreset', Signal),
('hreset', Signal)])
dev.simple_interrupt
dev.sreset.signal
dev.hreset.signal
dev_util.Dev.configure_pre_object(pre_obj)
Called before SIM_add_configuration.
Override to e.g. set attributes.
dev_util.Dev.finalize()
Called after the Simics object has been instantiated.
dev_util.Dev.register_simics_class()
Register the Simics class created by this object.
class dev_util.Iface()
Deprecated. Base class for fake interfaces.
To create an interface, inherit this class, define a class variable iface to the interface name, and define all methods that the interface defines.
dev_util.Iface.fail(msg)
Signal a failure when running an interface method.
Called by the default method stubs.
dev_util.iface(name)
Deprecated. Returns an Iface subclass which implements the name interface.
All the interface methods in the class will raise an exception when called. Convenient when creating a fake device that is required to implement an interface, but you know that the interface should be unused in the given test.
class dev_util.Memory()
Deprecated.
Legacy wrapper around an instance of the sparse-memory class. Provides an interface compatible with the deprecated Memory class.
The obj attribute contains an instance of memory-space, mapping to the memory. The real_obj attribute contains an instance of the ‘sparse-memory’ class. The mem attribute is an alias to the mem attribute of real_obj.
dev_util.Memory.clear(*args)
Clear the contents of the memory.
dev_util.Memory.is_range_touched(start, length)
Return True if any of this memory’s slots in the range contain data.
dev_util.Memory.read(addr, n)
Read bytes from this memory.
addrnThrows an exception if any byte in the read range is empty.
dev_util.Memory.write(addr, data)
Write bytes to this memory.
Arguments:
addrdataFills in empty slots in the memory and overwrites already existing data.
class dev_util.Layout(mem, ofs, regs, little_endian)
This class implements a memory layout.
Testing devices that does DMA transfers usually requires setting up DMA descriptors. These can often be seen as register sets located in memory. This class allows you to define the layout of those registers, including bitfields within the registers.
Registers without bitfields can be accessed through:
layout.reg-name
while registers with bitfields can be accessed through:
layout.reg-name.field-name
or
layout.reg-name.read(),
layout.reg-name.write()
Layouts are mapped ontop of Memory, i.e. NOT ontop of normal Simics RAM.
memofslittle_endianregs{'reg-name' : (offset, size),
'reg-name' : (offset, size, bitfield)}
offsetsizebitfielddev_util.Layout.clear()
Set all of the fields in this layout to 0.
dev_util.Layout.read(ofs, size)
Returns the value at ofs.
dev_util.Layout.write(ofs, value, size)
Writes value to ofs.
class dev_util.Layout_LE(mem, ofs, regs)
Little-endian layout.
class dev_util.Layout_BE(mem, ofs, regs)
Big-endian layout.
dev_util.value_to_tuple_be(val, bytes)
Deprecated, use tuple(val.to_bytes(bytes, 'big')) instead.
dev_util.value_to_tuple_le(val, bytes)
Deprecated, use tuple(val.to_bytes(bytes, 'little')) instead.
dev_util.tuple_to_value_be(t)
Deprecated, use int.from_bytes(t, 'big') instead.
dev_util.tuple_to_value_le(t)
Deprecated, use int.from_bytes(t, 'little') instead.