top | item 43965389

(no title)

Lramseyer | 9 months ago

Love to see this at the top of HN! I haven't written anything with this language yet, but I have met some of the developers of this language. They're pretty great and they are doing a lot of really good work in the open source hardware community. Another project they maintain is Surfer: https://surfer-project.org/

The challenge of a HDL over a regular sequential programming (software) language is that a software language is programmed in time, whereas a HDL is programmed in both space and time. As one HDL theory expert once told me "Too many high level HDLs try to abstract out time, when what they really need to do is expose time."

discuss

order

thezoq2|9 months ago

Thanks for the kind words!

> The challenge of a HDL over a regular sequential programming (software) language is that a software language is programmed in time, whereas a HDL is programmed in both space and time. As one HDL theory expert once told me "Too many high level HDLs try to abstract out time, when what they really need to do is expose time."

That's an excellent quote, I might steal it :D In general, I think good abstractions are the ones that make important details explicit rather than ones that hide "uninteresting" details.

VonTum|9 months ago

> As one HDL theory expert once told me "Too many high level HDLs try to abstract out time, when what they really need to do is expose time."

Exactly! It's astounding how often the documentation of some vendor component has in the documentation: "data_out is valid 2 cycles after read_enable is asserted", and NOTHING in the actual module definition makes a mention of this. There's so much dumb and error-prone mental arithmetic designers have to do to synchronize such latencies.

Spade does make a nod at this, with its pipelining notation. The issue I have with it is that it takes a too simplistic approach to said port timings. In a Spade pipeline you separate "pipeline stages" by adding a "reg;" statement on its own line. (It's an approach shared by another language called TL-Verilog.). A consequence of this style is that all inputs arrive at the sime time (say cycle 0), and all results are produced at a second time (say cycle 5). This is irrespective of if an input is actually only ever needed in a final addition in cycle 4. It'll insert the 4 extra registers regardless. Likewise, it leads to unnatural expression of subpipelines, where syntactically you can already see a value, but can only _access_ it 3 pipeline stages later.

With SUS, I have a solution to this: Latency Counting. (Intro here: https://m.youtube.com/watch?v=jJvtZvcimyM&t=937). A similar philosophy is also followed by Filament, though they go a step further with adding validity intervals too.

The gist of Latency Counting is that Instead of explicitly marking and naming "Pipeline stages", you annotate a statement to say that it "takes one cycle", and through exploring the dependency graph between your wires, it assigns a unique "absolute latency" to every wire, and places registers accordingly. (And now it can even infer submodule parameters based on this pipelining, in a bid to do HLS-style design in an RTL language).

etep|9 months ago

Surfer deserves to hit the front page also. Much better than gtk wave. Nice work Spade & Surfer!