-
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 True
There 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 port
In 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 anothercdatatype
be defined in PyHCL library, which isClock
. However, theclock
andreset
port of a module are pre-defined in based class, so we don't have to worry about how to useClock
type.
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 array
We 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.
Vec
in 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 porta
above, 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
Bundle
is still an experimental feature of PyHCL, we suggest that you only include basic types inBundle
.