Skip to content

Commit

Permalink
require nands to have all inputs and outputs
Browse files Browse the repository at this point in the history
  • Loading branch information
lets-all-be-stupid-forever committed Sep 18, 2024
1 parent 5c94191 commit 1004d92
Show file tree
Hide file tree
Showing 6 changed files with 72 additions and 5 deletions.
Binary file modified assets/tutorial.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 4 additions & 0 deletions luasrc/ctpd/nand.lua
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,10 @@ The NAND gates can be drawn in any orientation (facing up, down, left or right):
!img:imgs/circuitopedia/nand3.png
Every NAND should have its 2 inputs present, as well as the output, otherwise it will trigger an error when the simulation is launched.
!img:imgs/circuitopedia/nand4.png
Every non-black pixel in the image that is not part of a NAND gate is considered a wire, and has some state associated to it, as described below.
]]
Expand Down
Binary file added luasrc/imgs/circuitopedia/nand4.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified solutions/sol_gcd.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
48 changes: 43 additions & 5 deletions src/sim.c
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,10 @@ static const char CRASH_REASON_MULTIPLE_GATE_CIRCUIT[] =
"Circuits with multiple input gates.";
static const char CRASH_REASON_TOO_MANY_UPDATES[] =
"Circuit updated too many times (infinite loop?).";
static const char CRASH_REASON_MISSING_INPUTS[] =
"NANDs must have its 2 inputs filled";
static const char CRASH_REASON_MISSING_OUTPUT[] =
"NANDs must be connected to an output wire.";
static void MakeNandLut(int* nand_lut);
static void SimQueueInitialInputEvents(Sim* s);

Expand Down Expand Up @@ -530,6 +534,10 @@ void SimLoad(Sim* s, ParsedImage pi, int necomps, ExtComp* ecomps,
s->last_render_state = malloc(s->nc * sizeof(int));
s->graph = malloc(2 * s->nc * sizeof(int));
s->bugged_flag = malloc(s->nc * sizeof(int));
s->nand_error_status = NULL;
if (pi.num_nands > 0) {
s->nand_error_status = malloc(pi.num_nands * sizeof(int));
}
s->max_events = s->nc;
s->ne = 0;
s->events = malloc(2 * s->max_events * sizeof(int));
Expand Down Expand Up @@ -576,6 +584,17 @@ void SimLoad(Sim* s, ParsedImage pi, int necomps, ExtComp* ecomps,

// If it's not connected anywhere, ignore it.
if (cc == 0) {
s->nand_error_status[i] = NAND_STATUS_MISSING_OUTPUT;
s->crash_reason = CRASH_REASON_MISSING_OUTPUT;
s->status = SIMU_STATUS_NAND_MISSING_OUTPUT;
s->ok_creation = false;
continue;
}
if (ca == 0 || cb == 0) {
s->nand_error_status[i] = NAND_STATUS_MISSING_INPUT;
s->crash_reason = CRASH_REASON_MISSING_INPUTS;
s->status = SIMU_STATUS_NAND_MISSING_INPUT;
s->ok_creation = false;
continue;
}

Expand All @@ -600,6 +619,7 @@ void SimLoad(Sim* s, ParsedImage pi, int necomps, ExtComp* ecomps,
s->graph[2 * cc + 0] = ca;
s->graph[2 * cc + 1] = cb;
}
s->nand_error_status[i] = NAND_STATUS_OK;
}

// If there are bugged circuits, no need for fanout calculation
Expand Down Expand Up @@ -913,6 +933,9 @@ void SimUnload(Sim* s) {
UnloadImage(s->simulated[i]);
}
}
if (s->nand_error_status) {
free(s->nand_error_status);
}
free(s->wire_has_changed);
free(s->wire_changed_stack);
free(s->e1);
Expand Down Expand Up @@ -943,6 +966,10 @@ void SimGenImage(Sim* s) {
Color* original_pixels = GetPixels(s->pi.original_image);
Color undefined = MAGENTA;
Color bugged = RED;
if (!s->ok_creation) {
nand.a = 10;
undefined.a = 10;
}
if (s->simulated[0].width == 0) {
s->simulated[0] = GenImageFilled(w, h, black);
// renders nands...
Expand All @@ -951,16 +978,27 @@ void SimGenImage(Sim* s) {
int ix = s->pi.nand_pixels[2 * i + 0];
int iy = s->pi.nand_pixels[2 * i + 1];
int idx = iy * w + ix;
pixels[idx] = ColorWithAlpha(original_pixels[idx], 100);
Color target_color = ColorWithAlpha(original_pixels[idx], 100);
int nand_idx = i / 3;
NandStatusEnum status = s->nand_error_status[nand_idx];
if (s->ok_creation) {
pixels[idx] = target_color;
} else {
switch (status) {
case NAND_STATUS_OK:
pixels[idx] = undefined;
break;
case NAND_STATUS_MISSING_INPUT:
case NAND_STATUS_MISSING_OUTPUT:
pixels[idx] = bugged;
break;
}
}
}
s->simulated[1] = PyramidGenImage(s->simulated[0]);
s->simulated[2] = PyramidGenImage(s->simulated[1]);
}
Color* pixels = GetPixels(s->simulated[0]);
if (!s->ok_creation) {
nand.a = 10;
undefined.a = 10;
}
Color lut[] = {
zero,
one,
Expand Down
25 changes: 25 additions & 0 deletions src/sim.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,26 @@ typedef enum {
// During simulation, a loop was detected (ie, a wire was updated too many
// times).
SIMU_STATUS_LOOP,
// During compilation it found at least one NAND that doesn't have 2 inputs,
// which is not allowed.
SIMU_STATUS_NAND_MISSING_INPUT,
// During compilation it found at least one NAND that doesn't have 2 inputs,
// which is not allowed.
SIMU_STATUS_NAND_MISSING_OUTPUT,
} SimuStatus;

// Status flag for simulation.
typedef enum {
// Nand is OK
NAND_STATUS_OK,
// Nand is missing an input. Either a wire missing or 2 wires missing.
NAND_STATUS_MISSING_INPUT,
// Nand is not connected to an output. Indeed simulation can work with
// unconnected nands, but being stricted makes it easier to find bugs in the
// circuit.
NAND_STATUS_MISSING_OUTPUT,
} NandStatusEnum;

// The 4 possible values for a wire by default
typedef enum {
BIT_0,
Expand Down Expand Up @@ -168,6 +186,13 @@ typedef struct {
bool ok_creation;
// Total number of wires.
int nc;
// Error status for each nand. Processed during the creation of the graph.
// Used for identifying NANDs missing inputs or outputs.
// Possible values:
// NAND_STATUS_OK
// NAND_STATUS_MISSING_OUTPUT
// NAND_STATUS_MISSING_INPUT
int* nand_error_status;
// NAND graph of the circuit.
// Has size `2*nc`, and for each wire contains the two input wires to its
// source NAND. Each wire can have at most 1 NAND connected to it. To make it
Expand Down

0 comments on commit 1004d92

Please sign in to comment.