Implementing a C programm for logic gates circuit solution

101 Views Asked by At

Logic Gates circuit solution

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define SIZE 10

int myand(int a, int b);
int myor(int a, int b);
int mynand(int a, int b);
int mynor(int a, int b);
int myxor(int a, int b);
typedef int (*CallBack)(int a, int b);
int getinput();


typedef struct function {
    CallBack f;
    char ch[10];
} MyFunction;

typedef struct gate {
    CallBack f;
    struct gate * in1 ;
    struct gate * in2 ; 
    
} Gate;

Gate * creategate(CallBack f);

int eval(Gate *x);


int main() {
    Gate *a_ptr, *a1_ptr, *a2_ptr, *b_ptr, *b1_ptr, *b2_ptr, *c_ptr, *c1_ptr, *c2_ptr, *d_ptr, *e_ptr, *f_ptr;
    
    a_ptr = creategate(mynor);
    a1_ptr = creategate(getinput);
    a2_ptr = creategate(getinput);
    a_ptr->in1 = a1_ptr;
    a_ptr->in2 = a2_ptr;
    printf("First gate's output: %d\n", eval(a_ptr));
    
    b_ptr = creategate(myand);
    b1_ptr = creategate(getinput);
    b2_ptr = creategate(getinput);
    b_ptr->in1 = b1_ptr;
    b_ptr->in2 = b2_ptr;
    printf("Second gate's output: %d\n", eval(b_ptr));
    
    c_ptr = creategate(myor);
    c1_ptr = creategate(getinput);
    c2_ptr = creategate(getinput);
    c_ptr->in1 = c1_ptr;
    c_ptr->in2 = c2_ptr;
    printf("Third gate's output: %d\n", eval(c_ptr));
    
    d_ptr = creategate(mynand);
    d_ptr->in1 = a_ptr;
    d_ptr->in2 = b_ptr;
    printf("Fourth gate's output: %d\n", eval(d_ptr));
    
    e_ptr = creategate(myxor);
    e_ptr->in1 = b_ptr;
    e_ptr->in2 = c_ptr;
    printf("Fifth gate's output: %d\n", eval(e_ptr));
    
    f_ptr = creategate(myor);
    f_ptr->in1 = d_ptr;
    f_ptr->in2 = e_ptr;
    printf("Circuit's output: %d\n", eval(f_ptr));
    

    free(a_ptr);
    free(a1_ptr);
    free(a2_ptr);
    free(b_ptr);
    free(b1_ptr);
    free(b2_ptr);
    free(c_ptr);
    free(c1_ptr);
    free(c2_ptr);
    free(d_ptr);
    free(e_ptr);
    free(f_ptr);
    
    return 0;
}


int myand (int a, int b) {
    return a * b;
}
int myor (int a, int b) {
    return a + b>0;
}
int mynand (int a, int b) {
    int result = a * b;
    if (result == 0) {
        result = 1;
    }
    else {
        result = 0;
    }
    return result;
}
int mynor(int a, int b) {
    int result = a + b>0;
    if (result == 0) {
        result = 1;
    }
    else {
        result = 0;
    }
    return result;
}
int myxor(int a, int b) {
    int a1=0, b1=0;
    if (a==0) {
        a1=1;
    }
    else if (a==1) {
        a1=0;
    }
    
    if (b==0) {
        b1=1;
    }
    else if (b==1) {
        b1=0;
    }
    return ((a*b1) + (a1*b))>0;
}

int getinput() {
    int x;
    printf("Enter input(0 or 1): ");
    scanf("%d", &x);
    return x;
}

Gate * creategate(CallBack f) {
    Gate * temp ;
    temp = malloc(sizeof (Gate));
    temp->f = f;
    temp->in1 = NULL;
    temp->in2 = NULL;
    return temp;
}

int eval(Gate *x) {
    int a, b;
    if (x->in1 != NULL) {
        a = eval(x->in1);
    }
    if (x->in2 != NULL) {
        b = eval(x->in2);
    }
    if (x->in1==NULL && x->in2 == NULL) {
        return (x->f)(0,0);
    }
    else {
        return (x->f)(a,b);
    }

}

I first make the user enter each gate inputs using the getinput function. After entering the first six inputs in the first three gates, i want the programm to take automatically the outputs from the previous gates without the user having to enter something. I tried many ways but i couldnt find a solution. I need to keep the dynamic memory allocation and also all the structures and i can add another function if necessary.

1

There are 1 best solutions below

0
On

A number of issues ...

  1. There is no current [output] "state" in a gate struct.
  2. The "operator" functions (e.g. myand, myor, etc.) return a value instead of setting the output value into the struct.
  3. So, if a gate were connected to multiple outputs, the gate state would be evaluated multiple times (vs once per round).
  4. The ordering of the gate levels is hardwired into the code (in the eval function).
  5. The operator functions can be greatly simplified using C logic operators.
  6. We can dynamically determine the order of evaluation of gates by assigning all gates at the same depth to a different list (i.e. separate list for each logic depth)
  7. For clarity, I added names of the gates and functions to the gate struct.

Here is the refactored code. It is annotated. Unfortunately, I had to rewrite most of it.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <termios.h>

#define SIZE 10

struct gate;
typedef void (*CallBack)(struct gate *);

typedef struct function {
    CallBack f;
    char ch[10];
} MyFunction;

typedef struct gate {
    const char *sym;                    // gate name

    CallBack f;                         // operation function
    const char *fsym;                   // name of operation

    int depth;                          // gate's logic depth
    struct gate *next;                  // peer gate at same logic level

    int out;                            // output state/value
    struct gate *in1;                   // input gate
    struct gate *in2;                   // input gate
} Gate;

// list of gates
typedef struct {
    Gate *head;
} List;

#define CREATE(_sym,_fnc) \
    Gate *_sym = creategate(#_sym,_fnc,#_fnc)

#define MAXDEPTH    100
int bottom_depth;                       // last/maximum depth
List levels[MAXDEPTH];                  // list of gates at a given depth

// leveladd -- add gate to given gate list
void
leveladd(List *list,Gate *add)
{

    Gate *prev = NULL;
    for (Gate *tmp = list->head;  tmp != NULL;  tmp = tmp->next)
        prev = tmp;

    if (prev != NULL)
        prev->next = add;
    else
        list->head = add;

    add->next = NULL;
}

// leveldel -- remove gate from given list
void
leveldel(List *list,Gate *del)
{

    Gate *prev = NULL;
    Gate *cur = list->head;
    for (;  cur != NULL;  cur = cur->next) {
        if (cur == del)
            break;
        prev = cur;
    }

    if (cur == NULL) {
        printf("leveldel: no match -- %s\n",del->sym);
        exit(1);
    }

    if (prev != NULL)
        prev->next = del->next;
    else
        list->head = del->next;

    del->next = NULL;
}

// gatevalue -- current output value of gate
int
gatevalue(Gate *gate)
{

    return gate->out;
}

void
myand(Gate *gate)
{
    int in1 = gatevalue(gate->in1);
    int in2 = gatevalue(gate->in2);

    gate->out = (in1 & in2) != 0;
}

void
myor(Gate *gate)
{
    int in1 = gatevalue(gate->in1);
    int in2 = gatevalue(gate->in2);

    gate->out = (in1 | in2) != 0;
}

void
mynand(Gate *gate)
{
    int in1 = gatevalue(gate->in1);
    int in2 = gatevalue(gate->in2);

    gate->out = (in1 & in2) != 0;
    gate->out = ! gate->out;
}

void
mynor(Gate *gate)
{
    int in1 = gatevalue(gate->in1);
    int in2 = gatevalue(gate->in2);

    gate->out = (in1 | in2) != 0;
    gate->out = ! gate->out;
}

void
myxor(Gate *gate)
{
    int in1 = gatevalue(gate->in1);
    int in2 = gatevalue(gate->in2);

    gate->out = (in1 ^ in2) != 0;
}

void
getinput(Gate *cur)
{
    int x;

    printf("Enter input(0 or 1) for gate '%s': ",cur->sym);
    fflush(stdout);

    char buf[10];
    fgets(buf,sizeof(buf),stdin);

    // echo input if coming from redirected file (e.g.) ./myprogram < inp
    struct termios tio;
    if (tcgetattr(fileno(stdin),&tio) < 0)
        fputs(buf,stdout);

    x = atoi(buf);

    cur->out = x & 1;
}

// creategate -- create a new gate
Gate *
creategate(const char *sym,CallBack f,const char *fsym)
{
    Gate *cur;

    cur = calloc(1,sizeof(Gate));

    // name of this gate
    cur->sym = sym;

    // save the operator function
    cur->f = f;
    cur->fsym = fsym;

    // assume initial depth
    leveladd(&levels[0],cur);

    return cur;
}

// redepth -- [recursively] assign new depth to logic gate
void
redepth(Gate *cur,int newdepth)
{

    if (cur == NULL)
        return;

    if (newdepth > cur->depth)
        cur->depth = newdepth;

    ++newdepth;
    redepth(cur->in1,newdepth);
    redepth(cur->in2,newdepth);
}

// attach -- attach input gates to given gate
void
attach(Gate *a,Gate *b,Gate *c)
{

    a->in1 = b;
    redepth(b,a->depth + 1);

    a->in2 = c;
    redepth(c,a->depth + 1);
}

// gatename -- get name of gate
const char *
gatename(Gate *cur)
{

    if (cur != NULL)
        return cur->sym;

    return NULL;
}

// showgate -- show gate and children
void
showgate(Gate *cur)
{

    printf("  %s -- %s %s %s (DEPTH: %d)",
        cur->sym,gatename(cur->in1),cur->fsym,gatename(cur->in2),cur->depth);
}

// showlevel -- show all gates at given logic level
void
showlevel(List *list)
{

    printf("showlevel: %zu\n",list - levels);
    for (Gate *cur = list->head;  cur != NULL;  cur = cur->next) {
        showgate(cur);
        printf("\n");
    }
}

// showall -- show all logic levels
void
showall(const char *who)
{
    List *list;

    printf("showall: %s\n",who);

    for (list = &levels[0];  list < &levels[MAXDEPTH];  ++list) {
        if (list->head != NULL)
            showlevel(list);
    }
}

// moveall -- move gates to their correct logic level lists
void
moveall(void)
{
    List *old = &levels[0];

    Gate *next;
    for (Gate *cur = old->head;  cur != NULL;  cur = next) {
        next = cur->next;

        if (cur->depth != 0) {
            leveldel(old,cur);
            leveladd(&levels[cur->depth],cur);
        }

        // remember maximum depth
        if (cur->depth > bottom_depth)
            bottom_depth = cur->depth;
    }
}

// eval -- evaluate gate's new value
void
eval(Gate *cur)
{

    printf("\n");
    printf("eval:");
    showgate(cur);
    printf("\n");

    cur->f(cur);
    printf("eval: out=%d\n",cur->out);
}

// doround -- compute values for all gates for single time period
void
doround(void)
{

    for (int curdepth = bottom_depth;  curdepth >= 0;  --curdepth) {
        List *list = &levels[curdepth];
        for (Gate *cur = list->head;  cur != NULL;  cur = cur->next)
            eval(cur);
    }
}

// showround -- compute values for all gates for single time period
void
showround(void)
{

    for (int curdepth = bottom_depth;  curdepth >= 0;  --curdepth) {
        List *list = &levels[curdepth];
        for (Gate *cur = list->head;  cur != NULL;  cur = cur->next)
            printf("showround: %s --> %d\n",gatename(cur),gatevalue(cur));
    }
}

int
main(void)
{

    CREATE(a_ptr,mynor);
    CREATE(a1_ptr,getinput);
    CREATE(a2_ptr,getinput);
    attach(a_ptr,a1_ptr,a2_ptr);

    CREATE(b_ptr,myand);
    CREATE(b1_ptr,getinput);
    CREATE(b2_ptr,getinput);
    attach(b_ptr,b1_ptr,b2_ptr);

    CREATE(c_ptr,myor);
    CREATE(c1_ptr,getinput);
    CREATE(c2_ptr,getinput);
    attach(c_ptr,c1_ptr,c2_ptr);

    CREATE(d_ptr,mynand);
    attach(d_ptr,a_ptr,b_ptr);

    CREATE(e_ptr,myxor);
    attach(e_ptr,b_ptr,c_ptr);

    CREATE(f_ptr,myor);
    attach(f_ptr,d_ptr,e_ptr);

    showall("postadd");

    showall("premove");
    moveall();
    showall("postmove");

    // we can loop here if we wish
    doround();
    showround();

    return 0;
}

Here is the sample input I used:

1
1
1
1
1
0

Here is the output:

showall: postadd
showlevel: 0
  a_ptr -- a1_ptr mynor a2_ptr (DEPTH: 2)
  a1_ptr -- (null) getinput (null) (DEPTH: 3)
  a2_ptr -- (null) getinput (null) (DEPTH: 3)
  b_ptr -- b1_ptr myand b2_ptr (DEPTH: 2)
  b1_ptr -- (null) getinput (null) (DEPTH: 3)
  b2_ptr -- (null) getinput (null) (DEPTH: 3)
  c_ptr -- c1_ptr myor c2_ptr (DEPTH: 2)
  c1_ptr -- (null) getinput (null) (DEPTH: 3)
  c2_ptr -- (null) getinput (null) (DEPTH: 3)
  d_ptr -- a_ptr mynand b_ptr (DEPTH: 1)
  e_ptr -- b_ptr myxor c_ptr (DEPTH: 1)
  f_ptr -- d_ptr myor e_ptr (DEPTH: 0)
showall: premove
showlevel: 0
  a_ptr -- a1_ptr mynor a2_ptr (DEPTH: 2)
  a1_ptr -- (null) getinput (null) (DEPTH: 3)
  a2_ptr -- (null) getinput (null) (DEPTH: 3)
  b_ptr -- b1_ptr myand b2_ptr (DEPTH: 2)
  b1_ptr -- (null) getinput (null) (DEPTH: 3)
  b2_ptr -- (null) getinput (null) (DEPTH: 3)
  c_ptr -- c1_ptr myor c2_ptr (DEPTH: 2)
  c1_ptr -- (null) getinput (null) (DEPTH: 3)
  c2_ptr -- (null) getinput (null) (DEPTH: 3)
  d_ptr -- a_ptr mynand b_ptr (DEPTH: 1)
  e_ptr -- b_ptr myxor c_ptr (DEPTH: 1)
  f_ptr -- d_ptr myor e_ptr (DEPTH: 0)
showall: postmove
showlevel: 0
  f_ptr -- d_ptr myor e_ptr (DEPTH: 0)
showlevel: 1
  d_ptr -- a_ptr mynand b_ptr (DEPTH: 1)
  e_ptr -- b_ptr myxor c_ptr (DEPTH: 1)
showlevel: 2
  a_ptr -- a1_ptr mynor a2_ptr (DEPTH: 2)
  b_ptr -- b1_ptr myand b2_ptr (DEPTH: 2)
  c_ptr -- c1_ptr myor c2_ptr (DEPTH: 2)
showlevel: 3
  a1_ptr -- (null) getinput (null) (DEPTH: 3)
  a2_ptr -- (null) getinput (null) (DEPTH: 3)
  b1_ptr -- (null) getinput (null) (DEPTH: 3)
  b2_ptr -- (null) getinput (null) (DEPTH: 3)
  c1_ptr -- (null) getinput (null) (DEPTH: 3)
  c2_ptr -- (null) getinput (null) (DEPTH: 3)

eval:  a1_ptr -- (null) getinput (null) (DEPTH: 3)
Enter input(0 or 1) for gate 'a1_ptr': 1
eval: out=1

eval:  a2_ptr -- (null) getinput (null) (DEPTH: 3)
Enter input(0 or 1) for gate 'a2_ptr': 1
eval: out=1

eval:  b1_ptr -- (null) getinput (null) (DEPTH: 3)
Enter input(0 or 1) for gate 'b1_ptr': 1
eval: out=1

eval:  b2_ptr -- (null) getinput (null) (DEPTH: 3)
Enter input(0 or 1) for gate 'b2_ptr': 1
eval: out=1

eval:  c1_ptr -- (null) getinput (null) (DEPTH: 3)
Enter input(0 or 1) for gate 'c1_ptr': 1
eval: out=1

eval:  c2_ptr -- (null) getinput (null) (DEPTH: 3)
Enter input(0 or 1) for gate 'c2_ptr': 0
eval: out=0

eval:  a_ptr -- a1_ptr mynor a2_ptr (DEPTH: 2)
eval: out=0

eval:  b_ptr -- b1_ptr myand b2_ptr (DEPTH: 2)
eval: out=1

eval:  c_ptr -- c1_ptr myor c2_ptr (DEPTH: 2)
eval: out=1

eval:  d_ptr -- a_ptr mynand b_ptr (DEPTH: 1)
eval: out=1

eval:  e_ptr -- b_ptr myxor c_ptr (DEPTH: 1)
eval: out=0

eval:  f_ptr -- d_ptr myor e_ptr (DEPTH: 0)
eval: out=1
showround: a1_ptr --> 1
showround: a2_ptr --> 1
showround: b1_ptr --> 1
showround: b2_ptr --> 1
showround: c1_ptr --> 1
showround: c2_ptr --> 0
showround: a_ptr --> 0
showround: b_ptr --> 1
showround: c_ptr --> 1
showround: d_ptr --> 1
showround: e_ptr --> 0
showround: f_ptr --> 1