Skip to main content

Packed data structure specifications for multi-language hardware projects

Project description

Packtype

Tests

Packtype 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:

Language Constants Enumerations Structures Unions Packages
Python Yes Yes Yes Yes Yes
SystemVerilog Yes Yes Yes Yes Yes
C Yes Yes Yes No [1] No [2]
C++ Yes Yes Yes No [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 a namespace construct 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.

Installation

The easiest way to install Packtype is to use PyPI:

$> python3 -m pip install packtype

Alternatively, you can install the latest version directly from this repository:

$> python3 -m pip install git+git://github.com/Intuity/packtype

Using Packtype

Packtype provides the packtype command 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
$> packtype path/to/spec.py path/to/output/dir --render py --render sv

Two positional arguments can be provided:

  1. SPEC - provides the path to the Packtype specification file.
  2. 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 are py, sv, c, cpp.
  • --debug - generate debug messages as the tool runs.
  • --help - show the help prompt.

Examples

A number of examples are provided in the examples folder - each of these can be run by executing the test.sh file within the directory.

Packtype Specifications

Packtype 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.

Decorators

The 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.

Package

Constants, enumerations, structures, and unions must be associated to a named package - this helps to cleanly namespace the generated types as a project grows.

import packtype

@packtype.package()
class MyPackage:
    """ My package of constants, enumerations, and data structures """
    pass

Constants

Numeric constants can be attached to the root of a package to share fixed values between different parts of implementation, verification, and firmware.

import packtype
from packtype import Constant

@packtype.package()
class MyPackage:
    """ My package of constants, enumerations, and data structures """
    # Sizing
    GRID_WIDTH : Constant("Number of cells wide") = 9
    GRID_DEPTH : Constant("Number of cells deep") = 7
    # Identity
    HW_IDENTIFIER : Constant("Identifier for the device"   ) = 0x4D594857 # MYHW
    HW_MAJOR_VERS : Constant("Major revision of the device") = 3
    HW_MINOR_VERS : Constant("Major revision of the device") = 1

Enumerations

Enumerations can be declared with explicit or automatically incrementing values. Different modes of enumeration are provided for convenience, which are selected using the mode=Enum.INDEXED argument 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.
import packtype
from packtype import Enum

# ...declaration of package...

@packtype.enum(package=MyPackage, mode=Enum.ONEHOT)
class DecoderState:
    """ 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)
class MessageType:
    """ Different message types with explicit values """
    PINGPONG : Constant("Ping-pong keepalive"    ) = 0x123
    SHUTDOWN : Constant("Request system shutdown") = 0x439
    POWERUP  : Constant("Request system power-up") = 0x752

Structs

Packed data structures can be declared with fixed size scalar fields, or with references to other data structures and enumerated values.

import packtype
from packtype import Scalar

# ...declaration of package...

@packtype.struct(package=MyPackage, width=32)
class MessageHeader:
    """ 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 sizes
class PingPongPayload:
    """ 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)
class PingPongMessage:
    """ Full message including header and payload """
    header  : MessageHeader("Header of the message")
    payload : PingPongPayload("Payload of the message")

Unions

Unions 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.

import packtype
from packtype import Scalar

@packtype.union(package=MyPackage)
class MessageBus:
    """ 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")

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

packtype-1.0.tar.gz (25.2 kB view details)

Uploaded Source

Built Distributions

packtype-1.0-py3.9.egg (73.3 kB view details)

Uploaded Source

packtype-1.0-py3-none-any.whl (29.1 kB view details)

Uploaded Python 3

File details

Details for the file packtype-1.0.tar.gz.

File metadata

  • Download URL: packtype-1.0.tar.gz
  • Upload date:
  • Size: 25.2 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/3.4.2 importlib_metadata/4.8.1 pkginfo/1.7.1 requests/2.26.0 requests-toolbelt/0.9.1 tqdm/4.62.2 CPython/3.9.5

File hashes

Hashes for packtype-1.0.tar.gz
Algorithm Hash digest
SHA256 eb9dea85b050a88ab85a5ed52d459e3bea518bc5d888522f234c84d980ca2179
MD5 d97519ed7eddc6bf2214099e8c15ee21
BLAKE2b-256 d197220985191f31ca1c4ef61614e9e14e8bf6ff8b4d640581ecdf35ff70134c

See more details on using hashes here.

File details

Details for the file packtype-1.0-py3.9.egg.

File metadata

  • Download URL: packtype-1.0-py3.9.egg
  • Upload date:
  • Size: 73.3 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/3.4.2 importlib_metadata/4.8.1 pkginfo/1.7.1 requests/2.26.0 requests-toolbelt/0.9.1 tqdm/4.62.2 CPython/3.9.5

File hashes

Hashes for packtype-1.0-py3.9.egg
Algorithm Hash digest
SHA256 297d202b612b6a293742361209a1cad85633da306a0647c63b566a916d20caf4
MD5 dadeda34799264dbe93f8f91af3a20ae
BLAKE2b-256 7e34b3af745c78c2dd08ac4222c68759c477b3f62defd570263af8e6f685489b

See more details on using hashes here.

File details

Details for the file packtype-1.0-py3-none-any.whl.

File metadata

  • Download URL: packtype-1.0-py3-none-any.whl
  • Upload date:
  • Size: 29.1 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/3.4.2 importlib_metadata/4.8.1 pkginfo/1.7.1 requests/2.26.0 requests-toolbelt/0.9.1 tqdm/4.62.2 CPython/3.9.5

File hashes

Hashes for packtype-1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 ba620cde892534ced2130b29e39773c2e6415f8050abad60131ff0d75179b8c2
MD5 44884468173aae9cf9df2d242577e54d
BLAKE2b-256 5d931d91a04d735ce962ee5dab0f3d076fe524db793d995f97a389359760a7d5

See more details on using hashes here.

Supported by

AWS AWS Cloud computing and Security Sponsor Datadog Datadog Monitoring Fastly Fastly CDN Google Google Download Analytics Microsoft Microsoft PSF Sponsor Pingdom Pingdom Monitoring Sentry Sentry Error logging StatusPage StatusPage Status page