PySHDL 0.1.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,16 @@
1
+ .gitignore
2
+ # Python-generated files
3
+ __pycache__/
4
+ *.py[oc]
5
+ build/
6
+ dist/
7
+ wheels/
8
+ *.egg-info
9
+
10
+ # Virtual environments
11
+ .venv
12
+
13
+
14
+ *.c
15
+ *.so
16
+ .python-version
pyshdl-0.1.0/C_API.md ADDED
@@ -0,0 +1,200 @@
1
+ # SHDL Compiler - Library API Update
2
+
3
+ ## Overview
4
+
5
+ The SHDL compiler generates a **C library APIs** instead of standalone executables. This enables integration with testing frameworks, property-based testing, fuzzing, and scripting languages like Python.
6
+
7
+
8
+ ### Library API
9
+ The compiler generates a basic API with these functions:
10
+
11
+ ```c
12
+ void reset(void);
13
+ void poke(const char *signal_name, uint64_t value);
14
+ uint64_t peek(const char *signal_name);
15
+ void step(int cycles);
16
+ ```
17
+
18
+ ## API Functions
19
+
20
+ ### `void reset(void)`
21
+ Resets all internal state to zero. Call this before starting a test.
22
+
23
+ ```c
24
+ reset();
25
+ ```
26
+
27
+ ### `void poke(const char *signal_name, uint64_t value)`
28
+ Sets an input signal to a specific value. Marks outputs as dirty (requiring recomputation).
29
+
30
+ ```c
31
+ poke("A", 42);
32
+ poke("B", 17);
33
+ poke("Cin", 1);
34
+ ```
35
+
36
+ ### `uint64_t peek(const char *signal_name)`
37
+ Reads the current value of an input or output signal. Automatically computes outputs if needed.
38
+
39
+ ```c
40
+ uint64_t sum = peek("Sum");
41
+ uint64_t cout = peek("Cout");
42
+ ```
43
+
44
+ ### `void step(int cycles)`
45
+ Advances the simulation by the specified number of clock cycles. This commits state changes.
46
+
47
+ ```c
48
+ step(1); // Advance by 1 cycle
49
+ step(10); // Advance by 10 cycles
50
+ ```
51
+
52
+ ## Two-Phase Update Model
53
+
54
+ The simulator uses a two-phase update model for correct timing:
55
+
56
+ 1. **Pending State**: Computed from current state + inputs.
57
+ 2. **Current State**: Committed state after `step()`
58
+
59
+ This ensures:
60
+ - We can write combinational and sequential logic correctly
61
+ - Using feedback loops we can store state
62
+ - Multiple `poke()` calls can be made before evaluation
63
+ - Clock boundaries are clearly defined
64
+
65
+ ## Usage Example
66
+
67
+ ### Basic C Test
68
+
69
+ ```c
70
+ #include "adder16.c"
71
+
72
+ int main(void) {
73
+ reset();
74
+
75
+ // Test case: 42 + 17 + carry_in=1 = 60
76
+ poke("A", 42);
77
+ poke("B", 17);
78
+ poke("Cin", 1);
79
+
80
+ step(4); // Advance time to compute outputs
81
+
82
+ uint64_t sum = peek("Sum");
83
+ uint64_t cout = peek("Cout");
84
+
85
+ printf("Sum: %llu, Cout: %llu\n", sum, cout);
86
+
87
+
88
+ return 0;
89
+ }
90
+ ```
91
+
92
+ ### Python Integration (via ctypes)
93
+
94
+ ```python
95
+ import ctypes
96
+
97
+ # Load the shared library
98
+ lib = ctypes.CDLL("./adder16.so")
99
+
100
+ # Define function signatures
101
+ lib.reset.restype = None
102
+ lib.poke.argtypes = [ctypes.c_char_p, ctypes.c_uint64]
103
+ lib.peek.restype = ctypes.c_uint64
104
+ lib.peek.argtypes = [ctypes.c_char_p]
105
+ lib.step.argtypes = [ctypes.c_int]
106
+
107
+ # Run test
108
+ lib.reset()
109
+ lib.poke(b"A", 42)
110
+ lib.poke(b"B", 17)
111
+ lib.poke(b"Cin", 1)
112
+ lib.step(4)
113
+
114
+ sum_val = lib.peek(b"Sum")
115
+ cout_val = lib.peek(b"Cout")
116
+
117
+ print(f"Sum: {sum_val}, Cout: {cout_val}")
118
+
119
+ # Property-based testing example
120
+ import hypothesis
121
+ from hypothesis import given, strategies as st
122
+
123
+ @given(st.integers(0, 65535), st.integers(0, 65535), st.integers(0, 1))
124
+ def test_adder_properties(a, b, cin):
125
+ lib.reset()
126
+ lib.poke(b"A", a)
127
+ lib.poke(b"B", b)
128
+ lib.poke(b"Cin", cin)
129
+
130
+ lib.step(4)
131
+
132
+ sum_val = lib.peek(b"Sum")
133
+ cout_val = lib.peek(b"Cout")
134
+
135
+ # Verify result
136
+ expected = a + b + cin
137
+ actual = (cout_val << 16) | sum_val
138
+ assert actual == expected, f"{a} + {b} + {cin} = {expected}, got {actual}"
139
+
140
+ # Run property tests
141
+ test_adder_properties()
142
+ ```
143
+
144
+ ## Building the Library
145
+
146
+ ### As a Shared Library (.so)
147
+ ```bash
148
+ gcc -shared -fPIC -O3 adder16.c -o adder16.so
149
+ ```
150
+
151
+ ### As a Static Library (.a)
152
+ ```bash
153
+ gcc -c -O3 adder16.c -o adder16.o
154
+ ar rcs libadder16.a adder16.o
155
+ ```
156
+
157
+ ### With a Test Harness
158
+ ```bash
159
+ gcc -O3 adder16.c test_harness.c -o test_adder
160
+ ./test_adder
161
+ ```
162
+
163
+ ## Benefits
164
+
165
+ 1. **Testability**: Write comprehensive test suites in any language
166
+ 2. **CI Integration**: Automate testing on every commit
167
+ 3. **Property Testing**: Use tools like Hypothesis (Python) or QuickCheck (Haskell)
168
+ 4. **Fuzzing**: Feed random inputs to find edge cases
169
+ 5. **Performance Benchmarking**: Measure throughput easily
170
+ 6. **Debugging**: Inspect intermediate signals at any point
171
+
172
+ ## Internal State Access
173
+
174
+ You can also peek at internal state vectors for debugging:
175
+
176
+ ```c
177
+ uint64_t xor_state = peek("XOR_O_0");
178
+ uint64_t and_state = peek("AND_O_0");
179
+ ```
180
+
181
+ This is useful for understanding the internal behavior of complex designs.
182
+
183
+ ```c
184
+ reset();
185
+ poke("A", 42);
186
+ poke("B", 17);
187
+ poke("Cin", 1);
188
+ step(4);
189
+ printf("Sum=%llu\n", peek("Sum"));
190
+ ```
191
+
192
+ ## Future Enhancements
193
+
194
+ Potential additions to the library API:
195
+
196
+ - **VCD Generation**: Full waveform dumping for debugging.
197
+ - **GPIO Support**: Simulate your circuit with real pins.
198
+ - **GDB like Debugging**: Would be awesome.
199
+ - **Verilog Support**: Compile to Verilog for synthesis or simulation.
200
+