Package: packtype
PacktypePacktype is a Python framework for describing packed data structures for use in low-level hardware design, verification, and firmware development. From this single specification, equivalent implementations for different languages can be generated (for example C, C++, SystemVerilog).The support matrix below shows the current support:LanguageConstantsEnumerationsStructuresUnionsPackagesPythonYesYesYesYesYesSystemVerilogYesYesYesYesYesCYesYesYesNo [1]No [2]C++YesYesYesNo [1]Yes[1] While C and C++ have native support for unions, this is not used by Packtype. This is because support for true packed data structures is inconsistent across compilers, so instead Packtype uses non-packed data structures and provides methods for packing/unpacking into byte arrays.[2] C++ uses anamespaceconstruct to represent a package, but this doesn't exist in C. Instead the names of each construct are just prefixed with the name of the packag.InstallationThe easiest way to install Packtype is to use PyPI:$> python3 -m pip install packtypeAlternatively, you can install the latest version directly from this repository:$> python3 -m pip install git+git://github.com/Intuity/packtypeUsing PacktypePacktype provides thepacktypecommand line utility which can be used in conjuction with a specification (detailed below) to generate the different language definitions:# Render SystemVerilog and Python versions of the specification$>packtypepath/to/spec.pypath/to/output/dir--renderpy--rendersvTwo positional arguments can be provided:SPEC- provides the path to the Packtype specification file.OUTDIR- an optional path to the output folder for generated files (defaults to the current directory).Then options are available to modify the behaviour:-r py/--render py- generate the code for a certain language - the supported values arepy,sv,c,cpp.--debug- generate debug messages as the tool runs.--help- show the help prompt.ExamplesA number of examples are provided in theexamplesfolder - each of these can be run by executing thetest.shfile within the directory.Packtype SpecificationsPacktype specifications use a decorators and classes to declare the different data structures. Once a specification has been written, the Packtype utility can be used to generate code for different languages.DecoratorsThe following decorators are available:@packtype.package()- signifies a package (collection of types).@packtype.enum()- signifies an enumeration is declared by the following class.@packtype.struct()- signifies a structure is declared by the following class.@packtype.union()- signifies a union is declared by the following class.The@packtype.enum(),@packtype.struct(), and@packtype.union()decorators all accept the following arguments:package=MyPackage- associates the enum, struct, or union with the named package.width=32- declares the bit width of the enum, struct, or union - if omitted this is determined automatically.These decorators and arguments are demonstrated in the examples below.PackageConstants, enumerations, structures, and unions must be associated to a named package - this helps to cleanly namespace the generated types as a project grows.importpacktype@packtype.package()classMyPackage:""" My package of constants, enumerations, and data structures """passConstantsNumeric constants can be attached to the root of a package to share fixed values between different parts of implementation, verification, and firmware.importpacktypefrompacktypeimportConstant@packtype.package()classMyPackage:""" My package of constants, enumerations, and data structures """# SizingGRID_WIDTH:Constant("Number of cells wide")=9GRID_DEPTH:Constant("Number of cells deep")=7# IdentityHW_IDENTIFIER:Constant("Identifier for the device")=0x4D594857# MYHWHW_MAJOR_VERS:Constant("Major revision of the device")=3HW_MINOR_VERS:Constant("Major revision of the device")=1EnumerationsEnumerations can be declared with explicit or automatically incrementing values. Different modes of enumeration are provided for convenience, which are selected using themode=Enum.INDEXEDargument to the@packtype.enum()decorator:INDEXED- Each value increments by one, starting at zero.ONEHOT- Each value sets exactly one bit position high (e.g.1,2,4,8).GRAY- Values form a Gray code where only one bit flips between any two consecutive values.importpacktypefrompacktypeimportEnum# ...declaration of package...@packtype.enum(package=MyPackage,mode=Enum.ONEHOT)classDecoderState:""" Gray-coded states of the decoder FSM """DISABLED:Constant("FSM disabled")IDLE:Constant("Waiting for stimulus")HEADER:Constant("Header received")PAYLOAD:Constant("Payload received")@packtype.enum(package=MyPackage,width=12)classMessageType:""" Different message types with explicit values """PINGPONG:Constant("Ping-pong keepalive")=0x123SHUTDOWN:Constant("Request system shutdown")=0x439POWERUP:Constant("Request system power-up")=0x752StructsPacked data structures can be declared with fixed size scalar fields, or with references to other data structures and enumerated values.importpacktypefrompacktypeimportScalar# ...declaration of package...@packtype.struct(package=MyPackage,width=32)classMessageHeader:""" Common header for all messages """target_id:Scalar(width=8,desc="Target node for the message")msg_type:MessageType(desc="Encoded message type")@packtype.struct(package=MyPackage)# Width calculated from field sizesclassPingPongPayload:""" Payload of a ping-pong keepalive message """source_id:Scalar(width=8,desc="Node that sent the message")is_pong:Scalar(width=1,desc="Is this a ping or a pong")ping_value:Scalar(width=15,desc="Value to include in the response")timestamp:Scalar(width=8,desc="Timestamp message was sent")@packtype.struct(package=MyPackage)classPingPongMessage:""" Full message including header and payload """header:MessageHeader("Header of the message")payload:PingPongPayload("Payload of the message")By default, fields are packed into data structures from the LSB - but this can be reversed to pack from the MSB by providing thepack=Struct.FROM_MSBargument to the decorator. When using this mode, thewidthof the data structure must be explicitly specified. For example:importpacktypefrompacktypeimportScalar,Struct@packtype.struct(package=MyPackage,pack=Struct.FROM_MSB,width=32)classPingPongPayload:""" Payload of a ping-pong keepalive message """source_id:Scalar(width=8,desc="Node that sent the message")is_pong:Scalar(width=1,desc="Is this a ping or a pong")ping_value:Scalar(width=15,desc="Value to include in the response")timestamp:Scalar(width=8,desc="Timestamp message was sent")UnionsUnions allow different data structures to be overlapped on the same data - this is especially useful in protocol decoders where a bus may carry different formats and structures of data in different cycles. All components of a union must be of the same size, otherwise the tool will raise an error.NOTE:It is not possible to support unions in all languages due to their poor native support for packed data types, check the compatibility matrix above for details.importpacktypefrompacktypeimportScalar@packtype.union(package=MyPackage)classMessageBus:""" Union of the different message phases of the bus """raw:Scalar(desc="Raw bus value",width=32)header:MessageHeader(desc="Header phase")ping_pong:PingPongPayload(desc="Payload of the ping-pong request")