Deep-Symmetry/bytefield-svg

Add support for bit fields

brunchboy opened this issue · 5 comments

More ideas coming out of the current reverse-engineering project @Swiftb0y is working on:

It would be nice to make it easier for people to draw bit fields. One foundational step is to enhance the automatic label creation logic so that boolean? values are rendered as one-digit hex-style 0 and 1 labels. Then we could add functions like this:

(defn- normalize-bit
  "Converts a value to either `true` or `false`. All non-zero numbers
  become `true`. Other values are tested for truthiness and translated
  to `true` or `false` accordingly."
  [value]
  (cond
    (number? value)
    (zero? value)

    :else
    (if value true false)))

(defn- number-as-bits
  "Takes a number and transforms it into a sequence of `boolean` bit
  values of the specified length."
  [number length]
  (map #(normalize-bit (bit-test number %)) (reverse (range length))))

Which would support diagrams like this:

(def box-width 20)
(def boxes-per-row 8)
(draw-column-headers {:labels (reverse (take 8 column-labels))})
(draw-related-boxes (number-as-bits 0xd3 8))

It might also be nice to add something like (draw-bitfield-headers 8) which would set boxes-per-row and draw the appropriate number of reversed column headers. Adjusting the box width and margins should still be up to the diagram author, though, as it depends on the content they are rendering, and whether the bit field spans multiple lines.

Related to this is that we have been using packetdiag for drawing register images. Packetdiag's svg output is however terrible and often do not render in a web browser without custom additional CSS (our antora site had blank images, while the asciidoctor-pdf alternative looked great).

I just looked into bytefield-svg for this purpose and must say that it looks great so far. It solves the issue with antora and packetdiag for sure.

Our main use here is essentially fixed width registers which have three rows. The first row has field names, the second row reset values and the third row access permissions for the field (e.g. ro, wo, rw).

Like with packetdiag we have had the same issues when small bit fields have long names. In the case of packetdiag we could rotate the labels in these cases and increase the row height of the first row, I have not yet figured out how to do this with bytefield-svg yet.

Hello, Mattias! I am not familiar with packetdiag, unfortunately: I very quickly dismissed its output as being inadequate for my needs when I was first creating my diagrams, and then went and learned LaTeX bytefield before creating this package. So I am not certain exactly of the results you are trying to achieve. If you could point me at an example (even if the SVG is ugly) it will help me understand better.

Given what I can understand from the context here, it sounds like you want to be able to rotate column labels. You’re right that I did not build anything like that into bytefield-svg yet, as none of my diagrams needed it. However I can certainly understand the value of such a feature. Luckily we can add features to the package without even releasing new versions, because diagram source can write new functions using effectively the full power of the language in which I created bytefield-svg, Clojure. So let’s start by seeing if we can come up with some code to embed in the diagrams to draw your rotated labels, and then once we are happy with it, we can fold it into the package itself to make it easier for others to benefit from.

The first step for me would be an example diagram you want to create. Then I can try to find some time to help you write the code, although I’d certainly be happy if you could take a crack at it yourself as well. 😄 I think I put some resources for learning Clojure in the user guide. But I also fully understand that is likely to be too deep a detour, so I remain happy to help sketch things out myself.

We should probably open a new issue to track rotated headers. I haven’t had time to do any serious research yet, but from what I remember of SVG, it is possible to rotate the transformation matrix, and I think that should be our approach: rotate it a quarter turn in the proper direction, draw the label, and restore it.

It was not the column labels, but rather the labels in the boxes that need rotating.

I can point at this PDF at the moment (from other people, but it shows the general idea): http://ww1.microchip.com/downloads/en/DeviceDoc/doc7703.pdf

I think Table 81 and 84 is a good example illustrating what we are trying to achieve. Basically when a label in a bit field becomes longer than the field itself, we would need to rotate it and increase the row height (preferably only for one row). Our hacky way around this with packetdiag was a heuristic about bit counts and label length in characters, which is not perfect, but it worked reasonably ok (we are generating the diagrams from other descriptions in the end so we can always do stuff like that).

I'll see if I can produce some more dedicated figures next week and I will raise a box text rotation issue instead.

Raised issue #15