diff --git a/nandsimulator.c b/nandsimulator.c new file mode 100644 index 0000000..50bdfd2 --- /dev/null +++ b/nandsimulator.c @@ -0,0 +1,221 @@ +#include +#include +#include +#include + +enum element_type { INPUT, NAND }; + +struct element { + enum element_type type; + int a; + int b; +}; + +struct element_stack { + struct element** data; + int top; + int size; +}; + +struct element_stack* sCreate(int size) { + struct element_stack* e = malloc(sizeof(struct element_stack)); + e->data = malloc(sizeof(struct element*)*size); + e->size = size; + e->top = 0; +} + +int sPush(struct element_stack* stack,struct element* e) { + //printf("Pushed %d %d %d\n", e->a, e->b, stack->top); + if(stack->top == stack->size) return 1; + stack->data[stack->top] = e; + stack->top++; +} + +struct element* sPop(struct element_stack* stack) { + if(stack->top == 0) return NULL; + stack->top--; + struct element* e = stack->data[stack->top]; + //printf("Popped %d %d %d\n", e->a, e->b, stack->top); + return e; +} + +struct element* sGet(struct element_stack* stack, int index) { + if(index < 0 || index >= stack->top) return NULL; + return stack->data[index]; +} + +void sFree(struct element_stack* stack) { + free(stack->data); + free(stack); +} + +void sPrint(struct element_stack* stack) { + for(int i = 0; i < stack->top; i++) { + struct element* e = sGet(stack,i); + if(e->type == INPUT) { + printf("%d: INPUT %d\n",i,e->a); + } else { + printf("%d: NAND %d %d\n",i,e->a,e->b); + } + } +} + +struct element* sFind(struct element_stack* stack, struct element* pattern) { + for(int i = 0; itop; i++) { + struct element* e = stack->data[i]; + if(e->type == pattern->type && e->a == pattern->a && e->b == pattern->b) { + return e; + } + } + return NULL; +} + +struct truth_table { + int z; + int* in; +}; + +int test_truth_table( struct element_stack* stack, const struct truth_table te) { + int* netvalues = malloc(sizeof(int)*stack->top); + int inputs = 0; + for(int i = 0; i < stack->top; i++) { + struct element* e = sGet(stack,i); + if(e->type == INPUT) { + netvalues[i] = te.in[e->a]; + if(inputs <= e->a) inputs = e->a+1; + } else if(e->type == NAND) { + if(netvalues[e->a] == 1 && netvalues[e->b] == 1) { + netvalues[i] = 0; + } else { + netvalues[i] = 1; + } + } + } + int result = netvalues[stack->top-1]; + + free(netvalues); + if(result == te.z) { + return 1; + } else { + return 0; + } +} + +int buildnet( struct element_stack* stack, int inputs, int nands, const struct truth_table* tt ) { + if(stack->top == inputs+nands) { + //sPrint(stack); + for(int i = 0; i < (1 << inputs); i++) { + if(!test_truth_table(stack, tt[i] )) { + return 0; + } + } + return 1; + } else { + struct element* e = malloc(sizeof(struct element)); + e->type = NAND; + sPush(stack,e); + for(int a = 0; a < stack->top-1; a++) { + e->a = a; + for(int b = a; b < stack->top-1; b++) { + e->b = b; + struct element* f = sFind(stack,e); + if(f != NULL && f != e) continue; + if(buildnet(stack, inputs, nands, tt)) { + return 1; + } + } + } + assert(sPop(stack) == e); + free(e); + return 0; + } +} + +struct element_stack* findnet( int inputs, int nands, const struct truth_table* tt ) { + struct element_stack* stack = sCreate(inputs+nands); + // Add inputs to stack + for(int i = 0; i < inputs; i++) { + struct element* e = malloc(sizeof(struct element)); + e->type = INPUT; + e->a = i; + e->b = 0; + sPush(stack,e); + } + + if(buildnet(stack, inputs, nands, tt)) { + return stack; + } else { + while(stack->top > 0) { + free(sPop(stack)); + } + sFree(stack); + return NULL; + } +} + + +int main( int argc, char *argv[] ) { + /*const struct truth_table tt[16] = { + { .in = {0,0,0,0}, .z = 0 }, + { .in = {0,0,0,1}, .z = 0 }, + { .in = {0,0,1,0}, .z = 0 }, + { .in = {0,0,1,1}, .z = 0 }, + { .in = {0,1,0,0}, .z = 1 }, + { .in = {0,1,0,1}, .z = 1 }, + { .in = {0,1,1,0}, .z = 1 }, + { .in = {0,1,1,1}, .z = 0 }, + { .in = {1,0,0,0}, .z = 1 }, + { .in = {1,0,0,1}, .z = 0 }, + { .in = {1,0,1,0}, .z = 1 }, + { .in = {1,0,1,1}, .z = 1 }, + { .in = {1,1,0,0}, .z = 1 }, + { .in = {1,1,0,1}, .z = 1 }, + { .in = {1,1,1,0}, .z = 1 }, + { .in = {1,1,1,1}, .z = 1 } + };*/ + + /*const struct truth_table tt[4] = { + { .in = {0,0}, .z = 0 }, + { .in = {0,1}, .z = 1 }, + { .in = {1,0}, .z = 1 }, + { .in = {1,1}, .z = 0 } + };*/ + + int inputs, z; + printf("number of inputs: "); + scanf("%d",&inputs); + struct truth_table* tt = malloc( sizeof(struct truth_table) * (1<= 0; n--) { + tt[v].in[inputs-n-1] = ((v>>n)&1); + printf("%d ",tt[v].in[inputs-n-1]); + } + printf(" => "); + scanf("%d",&z); + if(z != 0) z = 1; + tt[v].z = z; + } + + struct element_stack* result; + for(int nands = 1; nands <= 20; nands++) { + printf("-- Trying to find solution for %d NANDS\n",nands); + result = findnet(inputs,nands,tt); + if(result != NULL) break; + printf("No solution\n"); + } + + if(result != NULL) { + sPrint(result); + } else { + printf("No result.\n"); + } + + for(int v = 0; v < (1<