-
Notifications
You must be signed in to change notification settings - Fork 14
Datatypes
All circuit elements that defined in PyHCL have to specify their datatyps. The circuit elements supported by PyHCL will describe in details later in section 5. Now we just need to know some of them which are common to use, such as Reg, Wire, and I/O ports.
The datatypes in PyHCL could be divided into two categories: the basic/grand datatypes and the composite types. The basic datatypes include unsigned integer, signed integer, and boolean. Corresponds to U, S, and Bool respectively. First we give some example of constant or literal values of those datatypes:
U(1) # 1-bit unsigend decimal value 1
U(0x126) # 12-bit unsigned hexadecimal value 0x126
U.w(4)(10) # 4-bit unsigned decimal value 10
S.w(16)(0x11) # 16-bit signed hexadecimal value 0x11
Bool(True) # Boolean literal values TrueThere are two ways to specify a unsigned or signed integer literal values:
U(12) # without width
U.w(4)(12) # with width In general, format of defined a unsigned or signed integer literal values is:
U.w(<width>)(<values>)The values could be decimal, octal, hexadecimal, and binarial in Python format. We give some examples that define several circuit elements using basic datatypes:
s = Reg(U.w(16)) # 16-bit unsigned integer register
alt = Wire(S.w(32)) # 32-bit signed integer wire
cout = Output(Bool) # Boolean output portIn PyHCL implementation, Bool is actually a 1-bit unsigned integer. For basic datatypes, unsigned integer and signed integer could not put together for operation, they must cast to the same datatype. We use to_uint() and to_sint() for casting:
S(12).to_uint() # Cast signed integer to unsigned integer
U.w(4)(3).to_sint() # Cast signed integer to signed integer
s.to_sint() # Cast unsigned integer register 's' to signed integer (see above)Note that Bool is 1-bit unsigned integer, so it could directy operate with unsigned integers.
In PyHCL library core, basic datatypes are call
cdatatype. There is actually anothercdatatypebe defined in PyHCL library, which isClock. However, theclockandresetport of a module are pre-defined in based class, so we don't have to worry about how to useClocktype.
Vector is most commonly used to defined an array of register. To defined a vector, we use Vec to do so:
Vec(<size>, <cdatatype>)size indicate the size of the vector, cdatatype indicate the datatype of the vector, and it must be a basic datatype(U, S, Bool). For example, we define an array of register:
rarray = Reg(Vec(4, U.w(16))) # A 16-bit 4 length unsigned integer register arrayWe could also index the register array with the operator [], as the built-in operator of Python:
# rarray = [U(0), U(1), U(2), U(3)]
for i in range(0, 4):
rarray[i] <<= U(i)Another commonly used of Vec is using in I/O ports. We define a input port a using Vec:
a=Input(Vec(4, U.w(16)))Which is convenience for multiple inputs or outputs.
Vecin PyHCL would translate as the array definition in FIRRTL, and compile to Verilog. However, the array features may lost in Verilog code. For example, the vector of input portaabove, after compile to Verilog:input [15:0] io_a_0, input [15:0] io_a_1, input [15:0] io_a_2, input [15:0] io_a_3,We could see that it has divide into 4 individual ports.
Bundle is a collection of different datatypes. It is similar to Chisel Bundle. Actually, in PyHCL's core library, IO is actually a Bundle and translate to FIRRTL later on. As a beginner of PyHCL, you could simply treat Bundle as the struct data structure of C/C++. The way we define a Bundle is similar to IO:
bun = Bundle(
x=U.w(16),
y=S.w(16),
z=Bool
)x, y, and z are the subfield of Bundle. Bundle is a datatype, so it must used in a circuit element:
breg = Reg(Bundle(
x=U.w(16),
y=S.w(16),
z=Bool
))We use . operator to access the subfield of the Bundle, similar to IO:
breg.x <<= U(12)
breg.y <<= S(4)
breg.z <<= Bool(False)
io.out <<= breg.x
Bundleis still an experimental feature of PyHCL, we suggest that you only include basic types inBundle.