I think this is backwards. Knowing that a signal is the clock, reset, data valid, adder result is far more important than the gate that drove it. The gates barely need names. Sadly, I think starting with that concept leads to a rather different language.
I was curious how the language compiles to C, what the resulting code does, and how one interacts with it. It took a while of reading to find it, so maybe this could be linked from places where compilation is mentioned. This part is my favorite, it's cool how it works. Especially since you mention "anti-abstraction", I like seeing how the DSL maps to C.
https://github.com/rafa-rrayes/SHDL/blob/master/docs/docs/ar...
> Compiles circuits to C so that they can run anywhere
Input (Base SHDL):
component Buffer(A) -> (B) {
n1: NOT;
n2: NOT;
connect {
A -> n1.A;
n1.O -> n2.A;
n2.O -> B;
}
}
Output (C code): #include <stdint.h>
#include <string.h>
typedef struct {
uint64_t NOT_O_0;
} State;
static inline State tick(State s, uint64_t A) {
State n = s;
// NOT gate inputs
uint64_t NOT_0_A = 0ull;
NOT_0_A |= ((uint64_t)-( (A & 1u) )) & 0x1ull;
NOT_0_A |= ((uint64_t)-( ((s.NOT_O_0 >> 0) & 1u) )) & 0x2ull;
// Evaluate NOT gates
n.NOT_O_0 = (~NOT_0_A) & 0x3ull; // 2 active lanes
return n;
}
static inline uint64_t extract_B(const State *s) {
return (s->NOT_O_0 >> 1) & 1ull; // B from lane 1
}
...If you removed the explicit declaration of every gate in a preamble and then their wiring as a separate step, you could reduce the boilerplate a lot. This example could look like this:
component FullAdder(A, B, Cin) -> (Sum, Cout)
{
A XOR B -> AxB
A AND B -> AB
AxB XOR Cin -> S
(AxB AND Cin) OR AB -> C
Sum: S
Cout: C
}https://drive.google.com/file/d/1dPj4XNby9iuAs-47U9k3xtYy9hJ...
honorary mention: https://www.funghisoft.com/mhrd