|
1 | 1 | #!/usr/bin/env python3
|
2 | 2 | import json
|
3 | 3 | import math
|
4 |
| -import pandas |
5 |
| -import textwrap |
6 | 4 | import coloredlogs, logging
|
7 | 5 | from quine_mccluskey import qm
|
8 | 6 | from argparse import ArgumentParser
|
|
75 | 73 | "attrs": {}
|
76 | 74 | }
|
77 | 75 |
|
78 |
| - wokwi_gate_spacing_v = 60 |
79 |
| - wokwi_gate_spacing_h = 120 |
80 |
| - |
81 |
| - # ------------------------------------------------------------------------------ |
82 |
| - # user specific design definition |
83 |
| - |
84 |
| - # the 'logic' dictionary defines the |
85 |
| - # - names of the output variables |
86 |
| - # - the list of integers that describe the input combination (row index of the truth table) when the output function is '1' |
87 |
| - # note: the order of key-value entries inside the dictionary is not relevant |
88 |
| - |
89 |
| - seven_segment_design = True |
90 |
| - seven_segment_design_full = True |
91 |
| - |
92 |
| - adder_design = False #True |
93 |
| - |
94 |
| - smol_design = False |
95 |
| - |
96 |
| - if seven_segment_design: |
97 |
| - if seven_segment_design_full: |
98 |
| - # full version (5 bit ASCII subset to 7 segment wokwi display) |
99 |
| - input_names = ['a', 'b', 'c', 'd', 'e'] |
100 |
| - logic = { |
101 |
| - 'A': [0, 1, 5, 6, 7, 11, 13, 15, 16, 17, 19, 26, 27, 29, 30], |
102 |
| - 'B': [0, 1, 4, 10, 15, 16, 17, 21, 22, 23, 24, 25, 26, 29], |
103 |
| - 'C': [0, 1, 2, 4, 7, 8, 10, 11, 13, 14, 15, 17, 19, 21, 24, 25, 28, 29], |
104 |
| - 'D': [0, 2, 3, 4, 5, 7, 10, 12, 15, 19, 20, 21, 22, 23, 25, 26, 27, 29, 31], |
105 |
| - 'E': [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 18, 20, 21, 24, 26, 27], |
106 |
| - 'F': [1, 2, 5, 6, 7, 8, 9, 11, 12, 15, 16, 17, 19, 20, 21, 22, 23, 24, 25, 27, 28], |
107 |
| - 'G': [0, 1, 2, 3, 4, 5, 6, 8, 11, 14, 16, 17, 18, 19, 20, 23, 24, 25], |
108 |
| - } |
109 |
| - else: |
110 |
| - # reduced version (5 bit ASCII subset to 7 segment wokwi display) |
111 |
| - input_names = ['a', 'b', 'c', 'd', 'e'] |
112 |
| - logic = { |
113 |
| - 'A': [0, 1, 5, 6, 7, 11, 13, 15, 16, 17, 19, 26, 27, 29, 30], |
114 |
| - 'B': [0, 1, 4, 10, 15, 16, 17, 21, 22, 23, 24, 25, 26, 29], |
115 |
| - 'C': [0, 1, 2, 4, 7, 8, 10, 11, 13, 14, 15, 17, 19, 21, 24, 25, 28, 29], |
116 |
| - } |
117 |
| - if adder_design: |
118 |
| - input_names = ['a', 'b'] |
119 |
| - logic = { |
120 |
| - 'S': [1, 2], |
121 |
| - 'C': [3], |
122 |
| - } |
123 |
| - if smol_design: |
124 |
| - input_names = ['a', 'b'] |
125 |
| - logic = { |
126 |
| - 'X': [2, 3], |
127 |
| - 'Y': [1, 3], |
128 |
| - } |
129 |
| - |
130 | 76 | # ------------------------------------------------------------------------------
|
131 | 77 | # user specific output style and laoyut definition
|
132 | 78 |
|
| 79 | + wokwi_gate_spacing_v = 60 |
| 80 | + wokwi_gate_spacing_h = 120 |
| 81 | + |
133 | 82 | sym_negation = '~' # could also be 'NOT '
|
134 | 83 | sym_and = '' # could also be ' AND ' / '*'
|
135 | 84 | sym_or = ' + ' # could also be ' OR '
|
@@ -269,27 +218,47 @@ def allocate_next_free_or_gate_inport():
|
269 | 218 | return retval
|
270 | 219 |
|
271 | 220 |
|
| 221 | + log.info(f"Log level: {log_level}") |
| 222 | + |
272 | 223 | # ------------------------------------------------------------------------------
|
273 | 224 | # generate insights about the design input data, i.e. log them to the console
|
| 225 | + # ------------------------------------------------------------------------------ |
| 226 | + # user specific design definition |
| 227 | + |
| 228 | + # - asume no duplicate names in use |
| 229 | + # - asume order of output values (zeros and ones) matches binary input order |
| 230 | + # (e.g. for three inputs: 000, 001, 010, 011, 100, ..., 110, 111) |
| 231 | + # - make input names optional (and use default ones, e.g. 'a', 'b', 'c', ...) |
| 232 | + |
| 233 | + in_filename = "logic.json" |
| 234 | + in_data = {} |
| 235 | + with open(in_filename, 'r') as f: |
| 236 | + in_data = json.loads( f.read() ) |
| 237 | + log.info(f"Data is read from input file '{in_filename}'" ) |
274 | 238 |
|
275 |
| - output_names = list( logic.keys() ) |
| 239 | + # the 'logic' dictionary used within this script defines the |
| 240 | + # - names of the output variables |
| 241 | + # - the list of integers that describe the input combination (row index of the truth table) when the output function is '1' |
| 242 | + # note: the order of key-value entries inside the dictionary is not relevant |
| 243 | + logic = {} |
| 244 | + |
| 245 | + input_names = in_data["inputs"] |
276 | 246 | num_inputs = len(input_names)
|
| 247 | + output_names = list( in_data["outputs"].keys() ) |
277 | 248 | num_outputs = len(output_names)
|
278 | 249 |
|
279 |
| - log.info(f"Log level: {log_level}") |
280 | 250 | log.info(f"Inputs: {num_inputs:2} {input_names}")
|
281 | 251 | log.info(f"Outputs: {num_outputs:2} {output_names}")
|
282 | 252 |
|
| 253 | + for output in output_names: |
| 254 | + assert len(in_data["outputs"][output]) == 2**num_inputs |
| 255 | + ones = [i for i in range(2**num_inputs) if in_data["outputs"][output][i] == 1] |
| 256 | + log.info(f" Output {output}: {in_data['outputs'][output]}; ones: {ones}") |
| 257 | + logic[output] = ones; |
| 258 | + |
283 | 259 | max_ones_idx = 2**num_inputs - 1
|
284 | 260 | log.debug(f"Max ones idx: 2^{num_inputs} - 1 = {max_ones_idx}")
|
285 | 261 |
|
286 |
| - log.info("Logic:") |
287 |
| - df = pandas.DataFrame.from_dict(logic, orient='index') |
288 |
| - pandas.options.display.float_format = '{:,.0f}'.format # we only have true ints, no need for decimals |
289 |
| - df = df.fillna("") # don't show NaNs |
290 |
| - df = df.rename(columns={col: "" for col in df}) # hide header |
291 |
| - log.info(textwrap.indent(df.to_string(), f"{' '*23}")) # align with previous log outputs |
292 |
| - |
293 | 262 | log.debug("Wokwi design (at start):")
|
294 | 263 | log.debug(wokwi_design)
|
295 | 264 |
|
|
0 commit comments