Skip to content

Commit 13247f2

Browse files
committed
Add support for automated in-circuit verification, fix #3
1 parent 68a3d4c commit 13247f2

File tree

4 files changed

+392
-2
lines changed

4 files changed

+392
-2
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,2 @@
11
*.diagram.json
2+
sketch.ino

README.md

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,12 @@ This feature can be used to modify existing designs only. The following command
7474
python3 generate.py -f ./demos/bcd_7segment_lut.logic.json -p | sed 's/[{}]//' | pbcopy
7575
```
7676

77+
Specify an output file for the wokwi schematic; also generate an Arduino sketch for automated verification and add and connect an Arduino MEGA in the wokwi schematic:
78+
79+
```
80+
python3 generate.py -f ./demos/2bit_half_adder.logic.json -o 2bit_half_adder.diagram.json -t
81+
```
82+
7783

7884
After having generated your diagram JSON file, ...
7985

@@ -181,7 +187,7 @@ S = ~a*b + a*~b
181187
C = a*b
182188
```
183189

184-
where
190+
where
185191

186192
* `~` represents inversion (a `NOT` gate),
187193
* `*` represents a logical `AND`(an `AND` gate),
@@ -223,4 +229,3 @@ Further read: [Département d'informatique et de recherche opérationnelle - Uni
223229
some may be unused due to bugs (probably rounding)
224230

225231
Some TODOs or ideas are already visible in the [issues tab](https://github.com/maehw/wokwi-lookup-table-generator/issues). Especially have a look at the issues labeled `good first issue` and `help wanted`.
226-

generate.py

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
import json
33
import math
44
import coloredlogs, logging
5+
from os import linesep
56
from quine_mccluskey import qm
67
from argparse import ArgumentParser, ArgumentDefaultsHelpFormatter, BooleanOptionalAction
78

@@ -38,6 +39,11 @@
3839
help='dump wokwi connections list only',
3940
default=0)
4041

42+
parser.add_argument('-t', '--test',
43+
action=BooleanOptionalAction,
44+
help='add an Arduino MEGA as test framework and generate Arduino verification code',
45+
default=0)
46+
4147
args = parser.parse_args()
4248

4349
# Create and configure logger object
@@ -97,6 +103,15 @@
97103
"attrs": {}
98104
}
99105

106+
wokwi_arduino_mega = {
107+
"type": "wokwi-arduino-mega",
108+
"id": "mega",
109+
"top": -400,
110+
"left": -500,
111+
"rotate": 90,
112+
"attrs": {}
113+
}
114+
100115
# ------------------------------------------------------------------------------
101116
# user specific output style and laoyut definition
102117

@@ -122,6 +137,9 @@
122137
con_color_or_or_interconnect = "green"
123138
con_color_or_output = "cyan"
124139
con_color_termination = "black"
140+
con_color_arduino_interconnect = "black"
141+
142+
arduino_sketch_template_file = "sketch.ino.template"
125143

126144
global global_and_gate_idx
127145
global_and_gate_idx = -1
@@ -237,6 +255,18 @@ def allocate_next_free_or_gate_inport():
237255

238256
return retval
239257

258+
def get_expected_bin_out_vals(output_names, output_data, num_inputs):
259+
# create binary based expectation values for Arduino verification code
260+
# see also: https://www.arduino.cc/reference/en/language/variables/constants/integerconstants/
261+
expected_bin_val = ""
262+
for k in range(2**num_inputs):
263+
expected_bin_val += linesep + " 0b"
264+
for output in output_names:
265+
expected_bin_val += str(output_data[output][k])
266+
expected_bin_val += ","
267+
268+
return expected_bin_val
269+
240270

241271
log.info(f"Log level: {log_level}")
242272

@@ -277,6 +307,7 @@ def allocate_next_free_or_gate_inport():
277307
log.info(f"Outputs: {num_outputs:2} {output_names}")
278308

279309
for output in output_names:
310+
# make sure that we have 2^num_inputs output values!
280311
assert len(in_data["outputs"][output]) == 2**num_inputs
281312
ones = [i for i in range(2**num_inputs) if in_data["outputs"][output][i] == 1]
282313
log.info(f" Output {output}: {in_data['outputs'][output]}; ones: {ones}")
@@ -708,6 +739,64 @@ def allocate_next_free_or_gate_inport():
708739

709740
log.info(f"Finished the wokwi design!")
710741

742+
743+
if args.test:
744+
log.info("Generating verification code and test framework")
745+
arduino_sketch_template = None
746+
with open(arduino_sketch_template_file, 'r') as f:
747+
arduino_sketch = f.read()
748+
if arduino_sketch:
749+
# generate the code, then add parts and connections to the wokwi schematic
750+
751+
# replace the placeholders with actual values
752+
arduino_sketch = arduino_sketch.replace("{DESIGN_NUM_USED_INPUTS_PH}", f"{num_inputs}u")
753+
arduino_sketch = arduino_sketch.replace("{DESIGN_NUM_USED_OUTPUTS_PH}", f"{num_outputs}u")
754+
expected_bin_out_vals = get_expected_bin_out_vals(output_names, in_data["outputs"], num_inputs)
755+
arduino_sketch = arduino_sketch.replace("{VERIFICATION_EXPECTED_OUT_VALS_PH}", expected_bin_out_vals)
756+
757+
# TODO: allow to use non-constant values for placeholders by controlling the from the
758+
# Python generator (e.g. by adding command line arguments)
759+
arduino_sketch = arduino_sketch.replace("{VERIFICATION_STOP_ON_ERROR}", "true")
760+
arduino_sketch = arduino_sketch.replace("{SERIAL_BAUDRATE_PH}", "230400u")
761+
arduino_sketch = arduino_sketch.replace("{VERIFICATION_SETUP_TIME_MS_PH}", "50u")
762+
arduino_sketch = arduino_sketch.replace("{VERIFICATION_HOLD_TIME_MS_PH}", "350u")
763+
764+
# save the generated Arduino sketch
765+
with open("sketch.ino", 'w') as f:
766+
f.write(arduino_sketch)
767+
768+
# add the Arduino MEGA to the wokwi schematic's parts list
769+
wokwi_design["parts"].append(wokwi_arduino_mega)
770+
771+
# add the serial monitor to the wokwi schematic
772+
wokwi_design["serialMonitor"] = {
773+
"display": "always",
774+
"newline": "lf"
775+
}
776+
777+
# connect design inputs to Arduino outputs
778+
arduino_mega_outputs = range(2, 11+1)
779+
out_idx = 0
780+
for input in input_names:
781+
con = [ f"mega:{arduino_mega_outputs[out_idx]}", f"input_{input}:IN",
782+
con_color_arduino_interconnect, default_con_instr ]
783+
log.debug(" Connection: "+str(con))
784+
wokwi_design["connections"].append(con)
785+
out_idx += 1
786+
787+
# connect design outputs to Arduino outputs
788+
arduino_mega_inputs = range(12, 21+1)
789+
in_idx = 0
790+
for output in output_names:
791+
con = [ f"mega:{arduino_mega_inputs[in_idx]}", f"output_{output}:OUT",
792+
con_color_arduino_interconnect, default_con_instr ]
793+
log.debug(" Connection: "+str(con))
794+
wokwi_design["connections"].append(con)
795+
in_idx += 1
796+
797+
else:
798+
log.error("Unable to open Arduino sketch template file.")
799+
711800
#log.debug( json.dumps(logic_meta, indent=4) )
712801

713802
wokwi_design_dump = wokwi_design

0 commit comments

Comments
 (0)