Skip to main content

A bitfield diagram renderer

Project description

bit_field

A Python 3 port of the JavaScript bit-field library by Aliaksei Chapyzhenka and a Fork of Arth-ur. The renderer produces SVG diagrams from a simple JSON description and is also available as a Sphinx extension: sphinxcontrib-bitfield.

Features

  • Render register/bit-field layouts to SVG from simple bits/name dictionaries
  • Optional [JSON5] input support via the json5 extra
  • Per-field type descriptors with predefined colours or explicit RGB values
  • Unknown-length gaps using array descriptors
  • Cross-lane connector support through arrow_jumps
  • Legends driven by the legend mapping or config.types overrides
  • Per-bit attribute display with the attr list, only usable when compact = false is
  • Vertical lane labels defined via label_lines, start_line/end_line, layout, and angle
  • Layout controls through compact, uneven, hflip, vflip, lanes, and bits

Installation

pip install bitfield-extended

To install with JSON5 support:

pip install bitfield-extended[JSON5]

Library usage

Basic rendering

from bit_field import render, jsonml_stringify

reg = [
    {"name": "IPO",   "bits": 8, "attr": "RO"},
    {"bits": 7},
    {"name": "BRK",   "bits": 5, "attr": ["0b1011", "RW"], "type": 4},
    {"name": "CPK",   "bits": 5, "type": [120, 180, 255]},  # custom colour
    {"name": "Clear", "bits": 7},
    {"array": 64, "type": 4, "name": "gap", "gap_width":2 , "gap_fill": "black"}, # unknown-length field
    {"bits": 8},
]

jsonml = render(reg, bits=16, legend={"Status": 2, "Control": 4})
svg = jsonml_stringify(jsonml)
# <svg...>

attr using

Example

{ "attr": "RW" }
{ "name": "IPO",   "bits": 4, "attr": ["0b1011", "RW"] }    // bit labels for each bit     
{ "attr": [["Ctrl", 90], "RW"] } // rotated text plus normal text

Vertical lane labels

Add horizontal labels spanning multiple lanes by including objects with a "label_lines" key in your descriptor list. Newline characters (\n) create multiple lines. The optional angle parameter rotates the text around its centre. Set "reserved": true to draw the connecting arrow a little above the start line when you need to indicate a reserved region:

Supported keys for a label entry

  • label_lines (required) – string or list of strings to show; \n makes multiple lines.
  • font_size (required) – text size in px; defaults to renderer fontsize when labels are provided globally.
  • start_line, end_line (required) – zero-based lane indices defining the vertical span; end_line must be ≥ start_line + 1.
  • layout (required)left or right, defining which side of the diagram hosts the label.
  • angle – rotate the text in degrees; vertical text automatically uses extra spacing.
  • reserved – boolean; if true the arrow sits slightly above the bracket to highlight reserved blocks.
  • Internal _offset and _margin are assigned automatically when labels overlap; no need to set them manually.
[
  {"bits": 8, "name": "data"},
  {"label_lines": "Line1\nLine2", "font_size": 6, "start_line": 0, "end_line": 3, "layout": "right", "angle": 30},
  {"label_lines": "reserved", "font_size": 6, "start_line": 4, "end_line": 7, "layout": "right", "reserved": true},
  {"label_lines": "Other", "font_size": 6, "start_line": 4, "end_line": 7, "layout": "right"}
]

Each label is drawn outside the bitfield on the requested side. Labels are rendered only if end_line - start_line < 0.

Arrow-head jumps

Route cross-lane references with dedicated arrow-head jump descriptors. They run vertically from a start_line, step through two intermediate lanes, then end on the requested bit column with an arrow head pointing to the destination field. Arrow-head length automatically scales with the stroke_width, so thicker lines give a more pronounced head without any additional parameters.

You can supply arrow jumps either via the arrow_jumps argument to render() or by embedding objects that contain an "arrow_jump" key inside your descriptor list (they are stripped out before field rendering).

Supported keys for an arrow-head descriptor

  • arrow_jump (required) – bit index in the source lane that the arrow leaves from.
  • start_line (required) – zero-based lane where the arrow starts.
  • jump_to_first, jump_to_second (required) – intermediate lanes that the two vertical legs run through before the final horizontal segment.
  • end_bit (required) – bit index in the target lane that the arrow head points to.
  • layout (required)left or right, deciding on which side of the diagram the detour is routed.
  • stroke_width – thickness of the path; also scales the arrow head length.
  • outer_distance – minimum spacing, in SVG units, between the diagram edge and the outer vertical run (default 10).
  • max_outer_distance – hard cap for automatic margin adjustments when the arrow head would overlap the target bit (default 25).
reg = [
  {"name": "CTRL", "bits": 8},
  {"name": "DATA", "bits": 8},
  {"name": "STATUS", "bits": 8},
]

arrow = {
  "arrow_jump": 2,
  "start_line": 0,
  "jump_to_first": 1,
  "jump_to_second": 2,
  "end_bit": 6,
  "layout": "right",
  "stroke_width": 4,
}

svg = jsonml_stringify(render(reg, bits=8, arrow_jumps=arrow, compact=True))

Array gaps

Use an {"array": length} descriptor to draw a wedge representing an unknown-length field or gap. The optional type and name keys colour and label the gap, and gap_width adjusts the wedge width as a fraction of a single bit (default 0.5):

Supported keys for an array descriptor

  • array (required) – number of bits covered by the gap; can also be a list where the last entry is interpreted as the length.
  • name – label shown inside the wedge.
  • type – numeric ID or RGB triplet used to colour both the wedge border and its background fill; overrides fill/gap_fill.
  • gap_width – width multiplier relative to a single bit cell; controls the wedge thickness (default 0.5).
  • gap_fill – colour of the wedge polygon; defaults to fill or white if omitted.
  • fill – legacy alias for gap_fill; used only when gap_fill is absent.
  • hide_lines – boolean; if true, suppresses the outline so the gap blends with adjacent fields. Hidden gaps still keep the final lane boundary for following fields.
  • font_size – allows matching text height to neighbouring fields when a name is provided.
reg = [
  {"name": "start", "bits": 8},
  {"array": 8, "type": 4, "name": "gap", "gap_width": 0.75},
  {"name": "end", "bits": 8},
]
render(reg, bits=16)

Legends

Pass a mapping of legend names to field types to add a legend above the bitfield:

legend = {"Status": 2, "Control": 4}
render(reg, legend=legend)

The numbers refer to the type values used in the field descriptors and can also be RGB triplets [r, g, b].

CLI usage

bit_field [options] input > out.svg

Options

input                           input JSON filename (required)
--input                         compatibility option
--vspace VSPACE                 vertical space (default 80)
--hspace HSPACE                 horizontal space (default 800)
--lanes LANES                   rectangle lanes (computed if omitted)
--bits BITS                     bits per lane (default 32)
--fontfamily FONTFAMILY         font family (default sans-serif)
--fontweight FONTWEIGHT         font weight (default normal)
--fontsize FONTSIZE             font size (default 14)
--strokewidth STROKEWIDTH       stroke width (default 1)
--hflip                         horizontal flip
--vflip                         vertical flip
--compact                       compact rendering mode
--trim TRIM                     trim long bitfield names
--uneven                        uneven lanes
--legend NAME TYPE              add legend item (repeatable)
--beautify                      pretty-print SVG
--json5                         force JSON5 input
--no-json5                      disable JSON5 input

Example JSON

[
    { "name": "Lorem ipsum dolor", "bits": 32 , "type": 1},
    { "name": "consetetur sadipsci", "bits": 32 , "type": 1},
    { "name": "ipsum dolor ", "bits": 32 , "type": 1},
    { "name": "t dolore ", "bits": 8 , "type": 1},
    { "name": "dolores ", "bits": 8, "type": 1},
    { "name": "ea takima", "bits": 8 , "type": 1},
    { "name": "s est Lorem", "bits": 8 , "type": [125,36,200]},
    { "array": 64, "name": "et accusa","type": 3},

    { "name": "et accusa", "bits": 32 , "type": 4},
    { "array": 64, "type": 4, "name": " accu","font_size": 12, "gap_width": 3,"gap_fill":"red", "hide_lines": true},

    {"label_lines": "Line Cover1", "font_size": 12, "start_line": 0, "end_line": 3, "layout": "left"},
    {"label_lines": "Line Cover2", "font_size": 12, "start_line": 4, "end_line": 4, "layout": "left"},
    {"label_lines": "Length", "font_size": 12, "start_line": 5, "end_line": 8, "layout": "right", "reserved": true, "angle":-90},
    {"label_lines": "Length", "font_size": 12, "start_line": 2, "end_line": 4, "layout": "right", "angle":90},
    {"arrow_jump": 2,"start_line": 0,"jump_to_first": 1,"jump_to_second": 2,"end_bit": 6,"layout": "left","stroke_width": 1}
    
]

Add a types mapping inside config to override the colors associated with field types and to use human-readable labels in your payload:

{
  "config": {
    "bits": 32,
    "types": {
      "gray": {
        "color": "#D9D9D9",
        "label": "test"
      }
    }
  },
  "payload": [
    { "name": "Lorem ipsum dolor", "bits": 32, "type": "test" }
  ]
}

Disable the bit number labels drawn above each field by setting "number_draw": false in your configuration:

{
  "config": {
    "number_draw": false
  },
  "payload": [
    { "name": "Lorem ipsum dolor", "bits": 32 }
  ]
}

Json Example

Rendering with the CLI:

bit_field alpha.json > alpha.svg

Licensing

This work is based on original work by Aliaksei Chapyzhenka under the MIT license (see LICENSE-ORIGINAL).

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

bitfield_extended-1.2.0.tar.gz (22.6 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

bitfield_extended-1.2.0-py3-none-any.whl (20.7 kB view details)

Uploaded Python 3

File details

Details for the file bitfield_extended-1.2.0.tar.gz.

File metadata

  • Download URL: bitfield_extended-1.2.0.tar.gz
  • Upload date:
  • Size: 22.6 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for bitfield_extended-1.2.0.tar.gz
Algorithm Hash digest
SHA256 348fb9dd5f085a410009913b055400bd5b451b35ee820cb0f42c334741c0f240
MD5 389fe3921fad4c6708864bdaa4b4d70b
BLAKE2b-256 fb48de376d1ffea251c7d397aec57151fcd83c5cdbdbf99f4c4cc8c6c883a8dc

See more details on using hashes here.

File details

Details for the file bitfield_extended-1.2.0-py3-none-any.whl.

File metadata

File hashes

Hashes for bitfield_extended-1.2.0-py3-none-any.whl
Algorithm Hash digest
SHA256 15cc66f5cab4f2fd57fd0bae5ed65ba08dda705f137e2cc9a563504c7d0f981d
MD5 d596591de6d334bbf8749b7251cf47ad
BLAKE2b-256 12f55ec3809ead7789bcb293db55552a1e1e60a88a8487c443ca52b04762b6fd

See more details on using hashes here.

Supported by

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