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.1.tar.gz (28.9 kB view details)

Uploaded Source

Built Distribution

packtype-1.0.1-py3-none-any.whl (37.4 kB view details)

Uploaded Python 3

File details

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

File metadata

  • Download URL: packtype-1.0.1.tar.gz
  • Upload date:
  • Size: 28.9 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.1.tar.gz
Algorithm Hash digest
SHA256 a468d3f4319e6ab495dc023edf35553a4d454168d05e3b0f5f28b5ec2c1be543
MD5 e4ef2492583290415886ceb966937a9b
BLAKE2b-256 a91fae845a89a970d30c19e43827dd13e57dbf1fa3cde02ed1d98d4ce1dc5b03

See more details on using hashes here.

File details

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

File metadata

  • Download URL: packtype-1.0.1-py3-none-any.whl
  • Upload date:
  • Size: 37.4 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.1-py3-none-any.whl
Algorithm Hash digest
SHA256 8980a863d3fdfd3488d8ce86c2c436a22e769dd1e7fe4945d40c5a24f65f2586
MD5 af8b5fff497e8c4a6741bb6edbf664a4
BLAKE2b-256 ee4bbafdd0deddbf46919a13e4213f9ff05098f7b719074ada1b3a52cb026ee6

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