#define TABLE_SIZE_MAX 0x10000 I64 output_found, passes, table_size; U8 *gate_type_table = NULL, *displayed_design = NULL, *added_this_pass = NULL; U16 *input1_table = NULL, *input2_table = NULL, *input3_table = NULL; #define CONNECT_WIDTH 16 #define GATE_WIDTH 37 /* Graphics Not Rendered in HTML */ /* Graphics Not Rendered in HTML */ /* Graphics Not Rendered in HTML */ /* Graphics Not Rendered in HTML */ /* Graphics Not Rendered in HTML */ /* Graphics Not Rendered in HTML */ /* Graphics Not Rendered in HTML */ /* Graphics Not Rendered in HTML */ /* Graphics Not Rendered in HTML */ /* Graphics Not Rendered in HTML */ U8 *gate_type_list = "NULL\0OUTPUT\0INPUT\0" "NOT\0AND\0OR\0NAND\0NOR\0XOR\0AND3\0OR3\0NAND3\0NOR3\0"; #define GT_NULL 0 //Specifies that table entry has not been filled-in #define GT_OUTPUT 1 //Specifies the table entry is a desired output #define GT_INPUT 2 //Specifies that table entry comes from an input signal #define GT_FIRST_REAL_GATE 3 #define GT_NOT 3 #define GT_AND 4 #define GT_OR 5 #define GT_NAND 6 #define GT_NOR 7 #define GT_XOR 8 #define GT_AND3 9 #define GT_OR3 10 #define GT_NAND3 11 #define GT_NOR3 12 #define GT_ENTRIES_NUM 13 #define SEL_GATES_NUM 128 U8 *imgs[GT_ENTRIES_NUM] = {NULL, NULL, NULL, <NOT>, <AND>, <OR>, <NAND>, <NOR>, <XOR>, <AND3>, <OR3>, <NAND3>, <NOR3>}; I64 num_inputs_entered, num_outputs_entered; I64 num_sel_gates, sel_gates[SEL_GATES_NUM]; U0 GetGates() { I64 i; U8 *st; "\nEnter the available gate types in the order you prefer them to be used.\n" "Your choices are:\n"; for (i = GT_FIRST_REAL_GATE; i < GT_ENTRIES_NUM; i++) "%z ", i, gate_type_list; '\n'; num_sel_gates = 0; while (num_sel_gates < GT_ENTRIES_NUM) { "%d", num_sel_gates; st = StrGet(" Gate: "); if (!*st) { Free(st); return; } i = ListMatch(st, gate_type_list, LMF_IGNORE_CASE); Free(st); if (i < GT_FIRST_REAL_GATE) "Invalid response\n"; else sel_gates[num_sel_gates++] = i; } } U0 Init() { I64 i; do { table_size = I64Get("\nTable size in hex (3 input=0x100,4=0x10000): ", 0); if (table_size > TABLE_SIZE_MAX) "Too large\n"; else if (table_size < 1) { "No table specified, aborting.\n"; throw; } } while (table_size > TABLE_SIZE_MAX); gate_type_table = CAlloc(table_size * sizeof(U8)); displayed_design = MAlloc((table_size + 7) / 8); added_this_pass = MAlloc((table_size + 7) / 8); input1_table = MAlloc(table_size * sizeof(U16)); input2_table = MAlloc(table_size * sizeof(U16)); input3_table = MAlloc(table_size * sizeof(U16)); "\nEnter the hex truth table column values of inputs.\n"; if (table_size <= 0x100) "For example, enter A=0xF0, B=0xCC and C=0xAA.\n"; else "For example, enter A=0xFF00, B=0xF0F0, C=0xCCCC and D=0xAAAA.\n"; num_inputs_entered = 0; while (TRUE) { "Input %C: ", 'A' + num_inputs_entered; i = I64Get("", -1); if (i < 0) break; if (i > table_size) "Too large\n"; else { if (gate_type_table[i]) "Duplicate\n"; else { gate_type_table[i] = GT_INPUT; input1_table[i] = num_inputs_entered++; } } } if (!num_inputs_entered) { "No inputs specified, aborting.\n"; throw; } "\nEnter the hex truth table columns values of the outputs.\n"; num_outputs_entered = 0; while (TRUE) { "Output %C: ", 'A' + num_outputs_entered; i = I64Get("", -1); if (i < 0) break; if (i > table_size) "Too large\n"; else { if (gate_type_table[i] == GT_INPUT) "To produce this output, connect to input %C\n", 'A' + input1_table[i]; else if (gate_type_table[i] == GT_OUTPUT) "Duplicate\n"; else { gate_type_table[i] = GT_OUTPUT; input1_table[i] = num_outputs_entered++; } } } if (!num_outputs_entered) { "No output specified, aborting.\n"; throw; } } U0 DrawDesign(CDC *dc, I64 *_y, I64 output, I64 depth, I64 *_x_out, I64 *_y_out) { I64 y = *_y, type = gate_type_table[output], xx = (passes - depth) * (GATE_WIDTH + CONNECT_WIDTH), yy = y, x1, y1, x2, y2, x3, y3; if (_x_out) *_x_out = xx; if (_y_out) *_y_out = yy; if (Bt(displayed_design, output) && type != GT_INPUT) { dc->color = GREEN; GrPrint(dc, xx - FONT_WIDTH * 3, y - 4, "Dup"); y += 10; } else switch (type) { case GT_INPUT: dc->color = GREEN; GrPrint(dc, xx - FONT_WIDTH - 4, y - 4, "%C", 'A' + input1_table[output]); y += 10; break; case GT_NOT: if (!Bt(displayed_design, output)) { y += 16; DrawDesign(dc, &y, input1_table[output], depth + 1, &x1, &y1); yy = y1; dc->color = BLUE; Sprite3(dc, xx, yy, 0, imgs[type]); dc->color = RED; GrLine(dc, xx - GATE_WIDTH, yy, x1, y1); if (_y_out) *_y_out = yy; } break; case GT_AND: case GT_OR: case GT_NAND: case GT_NOR: case GT_XOR: if (!Bt(displayed_design, output)) { y += 24; DrawDesign(dc, &y, input1_table[output], depth + 1, &x1, &y1); DrawDesign(dc, &y, input2_table[output], depth + 1, &x2, &y2); yy = (y1 + y2) / 2; dc->color = BLUE; Sprite3(dc, xx, yy, 0, imgs[type]); dc->color = RED; GrLine(dc, xx - GATE_WIDTH, yy - 4, x1, y1); GrLine(dc, xx - GATE_WIDTH, yy + 4, x2, y2); if (_y_out) *_y_out = yy; } break; case GT_AND3: case GT_OR3: case GT_NAND3: case GT_NOR3: if (!Bt(displayed_design, output)) { y += 32; DrawDesign(dc, &y, input1_table[output], depth + 1, &x1, &y1); DrawDesign(dc, &y, input2_table[output], depth + 1, &x2, &y2); DrawDesign(dc, &y, input3_table[output], depth + 1, &x3, &y3); yy = (y1 + y2 + y3) / 3; dc->color = BLUE; Sprite3(dc, xx, yy, 0, imgs[type]); dc->color = RED; GrLine(dc, xx - GATE_WIDTH, yy - 8, x1, y1); GrLine(dc, xx - GATE_WIDTH, yy, x2, y2); GrLine(dc, xx - GATE_WIDTH, yy + 8, x3, y3); if (_y_out) *_y_out = yy; } break; } dc->color = BLACK; GrPrint(dc, xx, yy + 3, "%04X", output); Bts(displayed_design, output); if (_y) *_y = y; } U0 DrawIt(CTask *, CDC *dc) { I64 y = 0; MemSet(displayed_design, 0, (table_size + 7) / 8 * sizeof(Bool)); DrawDesign(dc, &y, output_found, 0, NULL, NULL); } U0 FillNot(Bool *chged, I64 *num_outputs_found) { I64 i, j, old_type; for (i = 0; i < table_size; i++) if (gate_type_table[i] > GT_OUTPUT && !Bt(added_this_pass, i)) { progress1 = i; j= (~i) & (table_size - 1); old_type = gate_type_table[j]; if (old_type < GT_INPUT) { gate_type_table[j] = GT_NOT; input1_table[j] = i; Bts(added_this_pass, j); *chged = TRUE; if (old_type == GT_OUTPUT) { if (output_found < 0) output_found = j; *num_outputs_found = *num_outputs_found + 1; } } } } U0 FillAnd(Bool *chged, I64 *num_outputs_found) { I64 i, j, k, old_type; for (i = 0; i < table_size; i++) if (gate_type_table[i] > GT_OUTPUT && !Bt(added_this_pass, i)) for (k = 0; k < table_size; k++) if (gate_type_table[k] > GT_OUTPUT && !Bt(added_this_pass, k)) { progress1 = i; j= (i & k) & (table_size - 1); old_type = gate_type_table[j]; if (old_type < GT_INPUT) { gate_type_table[j] = GT_AND; input1_table[j] = i; input2_table[j] = k; Bts(added_this_pass, j); *chged = TRUE; if (old_type == GT_OUTPUT) { if (output_found < 0) output_found = j; *num_outputs_found = *num_outputs_found + 1; } } } } U0 FillOr(Bool *chged, I64 *num_outputs_found) { I64 i, j, k, old_type; for (i = 0; i < table_size; i++) if (gate_type_table[i] > GT_OUTPUT && !Bt(added_this_pass, i)) for (k = 0; k < table_size; k++) if (gate_type_table[k] > GT_OUTPUT && !Bt(added_this_pass, k)) { progress1 = i; j= (i | k) & (table_size - 1); old_type = gate_type_table[j]; if (old_type < GT_INPUT) { gate_type_table[j] = GT_OR; input1_table[j] = i; input2_table[j] = k; Bts(added_this_pass, j); *chged = TRUE; if (old_type == GT_OUTPUT) { if (output_found < 0) output_found = j; *num_outputs_found = *num_outputs_found + 1; } } } } U0 FillNAnd(Bool *chged, I64 *num_outputs_found) { I64 i, j, k, old_type; for (i = 0; i < table_size; i++) if (gate_type_table[i] > GT_OUTPUT && !Bt(added_this_pass, i)) for (k = 0; k < table_size; k++) if (gate_type_table[k] > GT_OUTPUT && !Bt(added_this_pass, k)) { progress1 = i; j= (~ (i & k)) & (table_size - 1); old_type = gate_type_table[j]; if (old_type < GT_INPUT) { gate_type_table[j] = GT_NAND; input1_table[j] = i; input2_table[j] = k; Bts(added_this_pass, j); *chged = TRUE; if (old_type == GT_OUTPUT) { if (output_found < 0) output_found = j; *num_outputs_found = *num_outputs_found + 1; } } } } U0 FillNOr(Bool *chged, I64 *num_outputs_found) { I64 i, j, k, old_type; for (i = 0; i < table_size; i++) if (gate_type_table[i] > GT_OUTPUT && !Bt(added_this_pass, i)) for (k = 0; k < table_size; k++) if (gate_type_table[k] > GT_OUTPUT && !Bt(added_this_pass, k)) { progress1 = i; j= (~ (i | k)) & (table_size - 1); old_type = gate_type_table[j]; if (old_type < GT_INPUT) { gate_type_table[j] = GT_NOR; input1_table[j] = i; input2_table[j] = k; Bts(added_this_pass, j); *chged = TRUE; if (old_type == GT_OUTPUT) { if (output_found < 0) output_found = j; *num_outputs_found = *num_outputs_found + 1; } } } } U0 FillXor(Bool *chged, I64 *num_outputs_found) { I64 i, j, k, old_type; for (i = 0; i < table_size; i++) if (gate_type_table[i] > GT_OUTPUT && !Bt(added_this_pass, i)) for (k = 0; k < table_size; k++) if (gate_type_table[k] > GT_OUTPUT && !Bt(added_this_pass, k)) { progress1 = i; j= (i ^ k) & (table_size - 1); old_type = gate_type_table[j]; if (old_type < GT_INPUT) { gate_type_table[j] = GT_XOR; input1_table[j] = i; input2_table[j] = k; Bts(added_this_pass, j); *chged = TRUE; if (old_type == GT_OUTPUT) { if (output_found < 0) output_found = j; *num_outputs_found = *num_outputs_found + 1; } } } } U0 FillAnd3(Bool *chged, I64 *num_outputs_found) { I64 i, j, k, l, old_type; for (i = 0; i < table_size; i++) if (gate_type_table[i] > GT_OUTPUT && !Bt(added_this_pass, i)) for (k = 0; k < table_size; k++) if (gate_type_table[k] > GT_OUTPUT && !Bt(added_this_pass, k)) for (l = 0; l < table_size; l++) if (gate_type_table[l] > GT_OUTPUT && !Bt(added_this_pass, l)) { progress1 = i; j= (i & k & l) & (table_size - 1); old_type = gate_type_table[j]; if (old_type < GT_INPUT) { gate_type_table[j] = GT_AND3; input1_table[j] = i; input2_table[j] = k; input3_table[j] = l; Bts(added_this_pass, j); *chged = TRUE; if (old_type == GT_OUTPUT) { if (output_found < 0) output_found = j; *num_outputs_found = *num_outputs_found + 1; } } } } U0 FillOr3(Bool *chged, I64 *num_outputs_found) { I64 i, j, k, l, old_type; for (i = 0; i < table_size; i++) if (gate_type_table[i] > GT_OUTPUT && !Bt(added_this_pass, i)) for (k = 0; k < table_size; k++) if (gate_type_table[k] > GT_OUTPUT && !Bt(added_this_pass, k)) for (l = 0; l < table_size; l++) if (gate_type_table[l] > GT_OUTPUT && !Bt(added_this_pass, l)) { progress1 = i; j= (i | k | l) & (table_size - 1); old_type = gate_type_table[j]; if (old_type < GT_INPUT) { gate_type_table[j] = GT_OR3; input1_table[j] = i; input2_table[j] = k; input3_table[j] = l; Bts(added_this_pass, j); *chged = TRUE; if (old_type == GT_OUTPUT) { if (output_found < 0) output_found = j; *num_outputs_found = *num_outputs_found + 1; } } } } U0 FillNAnd3(Bool *chged, I64 *num_outputs_found) { I64 i, j, k, l, old_type; for (i = 0; i < table_size; i++) if (gate_type_table[i] > GT_OUTPUT && !Bt(added_this_pass, i)) for (k = 0; k < table_size; k++) if (gate_type_table[k] > GT_OUTPUT && !Bt(added_this_pass, k)) for (l = 0; l < table_size; l++) if (gate_type_table[l] > GT_OUTPUT && !Bt(added_this_pass, l)) { progress1 = i; j= (~(i & k & l)) & (table_size - 1); old_type = gate_type_table[j]; if (old_type < GT_INPUT) { gate_type_table[j] = GT_NAND3; input1_table[j] = i; input2_table[j] = k; input3_table[j] = l; Bts(added_this_pass, j); *chged = TRUE; if (old_type == GT_OUTPUT) { if (output_found < 0) output_found = j; *num_outputs_found = *num_outputs_found + 1; } } } } U0 FillNOr3(Bool *chged, I64 *num_outputs_found) { I64 i, j, k, l, old_type; for (i = 0; i < table_size; i++) if (gate_type_table[i] > GT_OUTPUT && !Bt(added_this_pass, i)) for (k = 0; k < table_size; k++) if (gate_type_table[k] > GT_OUTPUT && !Bt(added_this_pass, k)) for (l = 0; l < table_size; l++) if (gate_type_table[l] > GT_OUTPUT && !Bt(added_this_pass, l)) { progress1 = i; j= (~(i | k | l)) & (table_size - 1); old_type = gate_type_table[j]; if (old_type < GT_INPUT) { gate_type_table[j] = GT_NOR3; input1_table[j] = i; input2_table[j] = k; input3_table[j] = l; Bts(added_this_pass, j); *chged = TRUE; if (old_type == GT_OUTPUT) { if (output_found < 0) output_found = j; *num_outputs_found = *num_outputs_found + 1; } } } } I64 FillGateTable() { I64 current_gate, num_outputs_found = 0; Bool chged = TRUE; passes = 1; output_found = -1; ProgressBarsReset; progress1_max = table_size; '\n'; while (num_outputs_found<num_outputs_entered && chged) { "Pass : %d\n", passes++; chged = FALSE; MemSet(added_this_pass, 0, (table_size + 7) / 8); for (current_gate = 0; current_gate < num_sel_gates && num_outputs_found < num_outputs_entered; current_gate++) { switch (sel_gates[current_gate]) { case GT_NOT: FillNot (&chged, &num_outputs_found); break; case GT_AND: FillAnd (&chged, &num_outputs_found); break; case GT_OR: FillOr (&chged, &num_outputs_found); break; case GT_NAND: FillNAnd (&chged, &num_outputs_found); break; case GT_NOR: FillNOr (&chged, &num_outputs_found); break; case GT_XOR: FillXor (&chged, &num_outputs_found); break; case GT_AND3: FillAnd3 (&chged, &num_outputs_found); break; case GT_OR3: FillOr3 (&chged, &num_outputs_found); break; case GT_NAND3: FillNAnd3(&chged, &num_outputs_found); break; case GT_NOR3: FillNOr3 (&chged, &num_outputs_found); break; } } } ProgressBarsReset; return num_outputs_found; } U0 CleanUp() { Free(gate_type_table); Free(displayed_design); Free(added_this_pass); Free(input1_table); Free(input2_table); Free(input3_table); } U0 DigitalLogic() { gate_type_table = NULL; displayed_design = NULL; added_this_pass = NULL; input1_table = NULL; input2_table = NULL; input3_table = NULL; SettingsPush; //See SettingsPush AutoComplete; WinBorder(ON); WinMax; DocClear; GetGates; try { Init; if (FillGateTable) { DocCursor; DocClear; Fs->draw_it = &DrawIt; CharGet; DocClear; Refresh(2, TRUE); DocBottom; } } catch PutExcept; SettingsPop; CleanUp; }