0

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.

BraVeHurt
  • 11
  • 2
  • 1
    I think you need to consider what `eval` does in each and every case within. Remember: both `a` and `b` are indeterminate unless assigned by those `a = ...` and `b = ...` lines respectively. That's important, especially in the case where only *one* of them was assigned. I think you'd be *possibly* closer if `eval` initialized `a` and `b` to zero (i.e. `int a=0,b=0;` then did your two tests for `x->in1` and `x->in2` as you have them to overwrite `a` and/or `b`, throw out the third if-test+block entirely and just hard return your else body, but without the else. – WhozCraig May 30 '23 at 17:35
  • Just noticing: You can swap 0 and 1 much more easily by simply having `result = !result`, but you can actually get the desired value directly if you adjust the comparison already: `a + b == 0` – and `xor` you can much more easily by `a != b`. Sure, breaks if one of is not 0 or 1, if you want to be robust against you could instead have `(a == 0) != (b == 0)`, assuming you want to consider any value unequal zero as 'true'... – Aconcagua May 30 '23 at 17:36
  • The *'outputs'* from the previous gates? Don't you mean the *'inputs'*? I would assume you want to use the same inputs for the operation and the respective negated operation – is this correct? Then the main problem with your code is that all you have is operations, but these are entirely *stateless*. You will have to extend your entire design such that you can store a state as well. Once you've done that you wouldn't call `createGate` for the negated operations, but provide them the same stateful gates you provided to the non-negated operations. – Aconcagua May 30 '23 at 17:48
  • By the way, as is you would not need to create multiple `getinput` gates, you could provide all the calculating gates (twice) with the one and only really necessary instance (stateless anyway, remember?) – changes, of course as soon as you do add states ;) – Aconcagua May 30 '23 at 17:51
  • @Aconcagua i want the outputs from the gates to work as inputs to the next gates... i dont know if you get me... for example i have three gates each takes two inputs. the first is "and gate" and i give it 0 and 1. it returns 0. the second is an "or gate" and i give it 0 and 0. it returns 0. now i want to use the two outputs, i mean 0 and 0, as inputs to the last gate – BraVeHurt May 30 '23 at 17:54
  • Does the output of a given gate _only_ go to the input of a _single_ gate? If so, you can add `struct gate *out` to your gate struct. Also, you'll need an `int idx;` to indicate whether `out` is connected to `in1` or `in2` of the next gate (i.e. `out`). Otherwise, you'll need a more complicated way to connect them. – Craig Estey May 30 '23 at 18:01
  • @CraigEstey it doesnt go as input to only one gate so can you guide me a bit more – BraVeHurt May 30 '23 at 18:04
  • Well, then again the same: You need *stateful* gates! You need to be able by some means to *store* the previous result. You could add another `int` to your `gate` struct, then you would need to store the value there somehow. You could change `eval` such that it would calcualate the value as long as there's no storage, otherwise return the stored value. Either use a separate variable remembering if storage took place or use a sentinel value (e.g. initialise to -1 on creation to indicate 'nothing yet stored'). Then you could set up the operands for subsequent gates with the existing ones. – Aconcagua May 30 '23 at 18:05
  • @CraigEstey explain me a bit more how i can adjust what yoy said to my programm – BraVeHurt May 30 '23 at 18:05
  • Okay, I misspoke. You do _not_ want: `struct gate *out;` in the struct. But, as Aconcagua said, you want an `int out;`. Then, it's how you connect them. You want to change your logic functions (e.g.): `void myand(struct gate *gate) { gate->out = gate->in1->out & gate->in2->out; }` You'll need to organize them in a tree that matches the way you connect the gates. – Craig Estey May 30 '23 at 18:15
  • Then, you want the equivalent of a depth first search. Except that when you visit a node (i.e. a gate), you call its function to set its output. – Craig Estey May 30 '23 at 18:17
  • corect my code where necessary and send it if you can please – BraVeHurt May 30 '23 at 18:26

1 Answers1

1

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
Craig Estey
  • 30,627
  • 4
  • 24
  • 48