Contents

1. Introduction

1.1 Four years of watching code generation improve

1.2 The verification problem

1.3 A calibration case: the multimeter simulator

2. Moving from software to hardware

2.1 Why SPICE is the right starting point

2.2 First experiment: synthesising an arbitrary waveform

2.3 From netlist to schematic

3. Raising the complexity: analog Pong

3.1 Specification

3.2 Discrete BJT implementation

3.3 Operational amplifier implementation

3.4 Principle of operation

4. A complete instrument on paper: the I–V curve tracer

4.1 The request

4.2 Why the design stopped there

5. Building something real: an ultrasonic range meter

5.1 Constraining the design to available parts

5.2 The generated design package

5.3 Schematic capture and PCB layout

5.4 Bring-up: three errors

5.5 Results

6. Discussion

6.1 What worked

6.2 Where it failed

6.3 A workflow that follows from this

7. Conclusion

1. Introduction

1.1 Four years of watching code generation improve

Four years ago I ran my first serious test of language models as software designers: a small project that generated an effectively infinite supply of playable Pong games in MicroPython. Since then the models have improved release after release. They have always been able to emit text in any notation you ask for — assembly, C, Python, Verilog — but producing code and producing working code are not the same thing.

The early output was slop. It looked like working code, but it contained bugs, conceptual mistakes, and calls to functions that simply did not exist. In the best case there were only a handful of defects, and you discovered them at run time. That was a serious problem, because it forced you to test everything with no assurance that your tests covered all the paths. Nobody wants to adopt someone else’s code, however impressive the demo, if it hides a few bugs — and nobody wants to be obliged to read all two thousand generated lines to find them.

That has changed. Current models produce code of acceptable quality. They will write the assembly kernel for your matrix multiplication routine, drive your terminal, write Verilog, or draw a detailed SVG. The example below is a thirty-minute South Park episode rendered in HTML, with multiple scenes and coherent, genuinely funny dialogue, produced in a single pass.

Figure 1. A 30-minute South Park episode generated as a single HTML application, with multiple scenes and coherent dialogue (Opus 5).

1.2 The verification problem

The difficulty with generated artefacts is not writing them, it is verifying them. How do you check code you did not write, whose internal structure you do not know, and whose full feature set you cannot enumerate? You never know whether some untried combination of two actions hides a defect, or whether a given behaviour is intended. Verification is hard precisely when you have neither a specification nor a mental model of how the thing is supposed to work.

One way around this is to build trust indirectly. Ask the model for something you already understand completely, so that you can act as the specification yourself. Pong would qualify — except that Pong is everywhere in the training data, so a good result proves nothing beyond retrieval. The test case has to satisfy two conditions at once: you must know exactly how it should behave, and it must be uncommon enough that the model cannot simply be reciting.

1.3 A calibration case: the multimeter simulator

The instrument simulator below meets both conditions. Every feature is verifiable by a user who has held the real instrument — ranges, autoranging, polarity, the behaviour of a diode test on an LED — and an interactive simulator of this specific meter is unlikely to be well represented in any dataset.

Figure 2. Interactive multimeter simulator. Behaviour is fully verifiable by the user, and the application is unlikely to be common in the training data.

It worked correctly. That result does...

Read more »