Cocotb Datatypes & Handle Values

Cocotb HDL Datatypes & Handle Values #

This tutorial is about cocotb HDL datatypes and handle values:

Github Link #

Handles #

In short, handles are objects to allow for access to any signal name in your HDL design.

In a previous tutorial, talking to sim, we saw how to get and set values in a simulation via handles. We assign and read values from handles via dut.<signal name>.value.

Handle Values #

Accessing the value property of a handle object will return a BinaryValue object. Any unresolved bits are preserved and can be accessed using the binstr attribute, or a resolved integer value can be accessed using the integer attribute

BinaryValue #

BinaryValue is of the following form:

BinaryValue(value=None, n_bits=None, bigEndian=True, binaryRepresentation=0, bits=None)

And has the following methods:

  • BinaryValue.integer is an integer
  • BinaryValue.signed_integer is a signed integer
  • BinaryValue.binstr is a string of “01xXzZ”
  • BinaryValue.buff is a binary buffer of bytes
  • BinaryValue.value is an integer deprecated

Creating, Reading, and Writing a BinaryValue #

Run the code below to get familiar with BinaryValues manipulations:

# Get familiar with BinaryValue
from cocotb.binary import BinaryRepresentation, BinaryValue

bv = BinaryValue(10, 8, True, BinaryRepresentation.TWOS_COMPLEMENT)
print("BinaryValue(10, 8, True, BinaryRepresentation.TWOS_COMPLEMENT)")
print("bv.get_value(): " + str(bv.get_value()))
print("bv.integer: " + str(bv.integer))


bv =  BinaryValue('XzZx0100', 8, True, BinaryRepresentation.TWOS_COMPLEMENT)
print("BinaryValue('XzZx0100', 8, True, BinaryRepresentation.TWOS_COMPLEMENT)")
print("bv.is_resolvable: "+ str(bv.is_resolvable))
print("bv.binstr: "+ str(bv.binstr))


bv = BinaryValue('10000000', 8, True, BinaryRepresentation.TWOS_COMPLEMENT); 
print("BinaryValue('10000000', 8, True, BinaryRepresentation.TWOS_COMPLEMENT)")
print("bv.get_value_signed(): " + str(bv.get_value_signed()))
print("bv.signed_integer: " + str(bv.signed_integer))


bv = BinaryValue(n_bits=10, bigEndian=False, binaryRepresentation=BinaryRepresentation.TWOS_COMPLEMENT)
bv.integer = -128
print("bv = BinaryValue(n_bits=10, bigEndian=False, binaryRepresentation=BinaryRepresentation.TWOS_COMPLEMENT)")
print("bv.integer = -128")
print("bv.get_value_signed: " + str(bv.signed_integer))
print("bv.get_value_signed: " + str(bv.n_bits))

BinaryRepresentation #

As we saw in the example above, BinaryRepresentation is a argument to BinaryValue which we can set. BinaryRepresentation is a simple class denoting one of three types of binary representations:

class BinaryRepresentation:  # noqa
    UNSIGNED = 0  #: Unsigned format
    SIGNED_MAGNITUDE = 1  #: Sign and magnitude format
    TWOS_COMPLEMENT = 2  #: Two's complement format

BinaryValue Deprecation #

There is talk that BinaryValue will be phased out in upcoming cocotb releases. The Datatypes Logic will take its place which is discussed below.

HDL Datatypes #

From the cocotb docs on HDL Datatypes:

They can be used independently of cocotb for modeling and will replace BinaryValue as the types used by cocotb’s simulator handles.

Bit, Logic & LogicArray #

Logic is a model of the 4-value (0, 1, X, Z) datatype commonly seen in HDLs. Logic can be converted to and from int, str, bool, and Bit by using the appropriate constructor syntax. Logics can be put into LogicArrays.

Bit is a model of a 2-value datatype commonly seen in HDL.

Run the code below to get familiar with Logic and LogicArray manipulations:

from cocotb.types import Bit,Logic, LogicArray
from cocotb.types.range import Range

print('Logic("X"): ' + str(Logic("X")))

print("Logic('X'): " + str(Logic('X')))

print("Logic(True): " + str(Logic(True)))

print("Logic('1'): " + str(Logic('1')))

print("Logic(1): " + str(Logic(1)))

print("Logic(Bit(0)): " + str(Logic(Bit(0))))

print("Logic('0'): " + str(Logic('0')))

print("Logic(): " + str(Logic()))

print('Logic("01XZ").binstr: ' + LogicArray("01XZ").binstr)

print("LogicArray('01XZ', Range(3, 'downto', 0)): " + LogicArray('01XZ', Range(3, 'downto', 0)).binstr)

print('LogicArray([0, True, "X"]): ' + LogicArray([0, True, "X"]).binstr)

print("LogicArray('01X', Range(2, 'downto', 0))" + LogicArray('01X', Range(2, 'downto', 0)).binstr)

print("LogicArray(0xA).integer: " +    str(LogicArray(0xA).integer))         

print("LogicArray('1010', Range(3, 'downto', 0)): " + LogicArray('1010', Range(3, 'downto', 0)).binstr)

print('LogicArray(-4, Range(0, "to", 3)).signed_integer : ' + str(LogicArray(-4, Range(0, "to", 3)).signed_integer)) # will sign-extend

print("LogicArray('1100', Range(0, 'to', 3)): " + str(LogicArray('1100', Range(0, 'to', 3)).integer))

# note ordering
la = LogicArray('1100', Range(0, 'to', 3))
print("la[0]: " + str(la[0]))

# note ordering
la = LogicArray('1100', Range(3, 'downto', 0))
print("la[0]: " + str(la[0]))

# others to know

Bit('1') Copyright © 2023