One of the main difference between the board design tools we work on, and mainstream schematic tools is the much more expressive and rich data model. Instead of simply a netlist (components, pins, and connections between them) with very little additional data, we have the notion of blocks, ports, and links, all of them with strong types and parameters. This additional data allows the system too automatically solve for lower-level details (for example, knowing the input voltage to a LED-resistor circuit means it can solve for the resistor value) and helps encode a design space (for example, a generic step-down voltage converter block can be substituted by several different buck converter subcircuits). As such, much of the power of the design system stems from the data model, as does much of its complexity. The compiler must be able to work with this core data model, and ultimately fully expand out a user design into something that can be fabricated.

The two upcoming major features, array types and multipack devices (will be discussed more in a future post - or if you're adventurous, feel free to read the GitHub issues), all are projected to add significant complexity to the core compiler. So now would be the time to refactor and simplify the existing compiler where possible. Especially since that compiler was actually (re)written a year ago, during the mad dash to the UIST'21 deadline. As things have calmed down since then (and as we've built more examples), some design decisions no longer make sense.

One of those things to simplify the generator system, which allows the compiler to invoke arbitrary user Python code to construct a block, optionally relying on some solved parameters in the design. The current implementation nominally supports multiple generators for a single block, nominally each contributing a piece of the block. But this was never implemented fully (nor was the algebra to do so fully fleshed out), and in retrospect it seems unnecessary and there are other structures that should enable the same use cases and expressive power. So this week's work has been on fleshing out the restrictions on generators and generally cleaning up the compiler. In short, the idea is that blocks can go from un-elaborated (only containing the type), to optionally a pending generator (waiting on dependency parameters), to fully elaborated (containing its internal ports, links, and sub-blocks). Each transition is one-way, and can happen at most once. This should simplify a lot of code and eliminate certain bugs, though at the potential cost of needing to refactor some existing designs (but it might also make them cleaner!).

It's been a lot of trying to understand the code I wrote a year ago, then planning to refactor and simplify it. And implementing the refactor... slowly... reveng

Next Post Previous Post