//
// Gate
//
// An Objective-C class for simulating digital logic which
// simulates a generic n-input, m-bit gate.
//


#import "Gate.h"


@implementation Gate


- initNumBits:(int)nbits
	in:innode
	out:outnode
{
    [super init];
    
    INITDEVTYPE("Gate");
    
    if(nbits < 1) {
        fprintf(stderr, "Gate: Attempt to create Gate with %d bits per input!\n", nbits);
	exit(-1);
    }
    
    numbits = nbits;
    
    multiinput = NO;
    
    TESTNODE("IN", innode, numbits);
    TESTNODE("OUT", outnode, 1);
    
    IN = innode;
    OUT = outnode;
    
    return self;
}

	
- initNumInputs:(int)n inputs:(id *)inparray numBits:(int)nbits out:outnode
{
    int		i;
    char	nodenum[20];
    
    [super init];
    
    multiinput = YES;
    
    if(n < 2) {
        fprintf(stderr, "Gate: Attempt to create multi-input Gate with %d inputs!\n", n);
	exit(-1);
    }
    if(nbits < 1) {
        fprintf(stderr, "Gate: Attempt to create Gate with %d bits per input!\n", nbits);
	exit(-1);
    }
    
    numinputs = n;
    numbits = nbits;
    
    inputs = (id *)malloc(numinputs * sizeof(id));
    
    INITDEVTYPE("Gate");
    
    for(i = 0; i < numinputs; i++) {
        sprintf(nodenum, "IN[%d]", i);
        TESTNODE(nodenum, inparray[i], numbits);
        inputs[i] = inparray[i];
    }
    TESTNODE("OUT", outnode, numbits);
    
    OUT = outnode;
	
    temp = (bit *)malloc(numbits * sizeof(bit));		// Temporary answer storage.
    if(temp == NULL) {
        fprintf(stderr, "Gate: Unable to allocate temporary storage!\n");
	exit(-1);
    }
    
    return self;
}


- free
{
    if(!multiinput) {
        
    }
    else {
	free(inputs);
	free(temp);
    }
    
    return [super free];
}


- (bit)op:(bit)a :(bit)b
{
    fprintf(stderr, "Gate: Warning! Call to Gate's op:: method probably shouldn't occur!\n");
    
    return 0;							// Default gate zeros.
}


- cycle
{
    int i, j;
    bit *inp;
    
    if(!multiinput) {					// If single input:
        inp = [IN getBits];
        tempbit = inp[0];

	for(i = 1; i < numbits; i++) {
	    tempbit = [self op:tempbit :inp[i]];	// Perform bit operation.
	}
	
	[OUT setBits:&tempbit];				// Copy answer to output node.
    }
    else {
        inp = [inputs[0] getBits];
	for(i = 0; i < numbits; i++)			// Initialize answer.
	   temp[i] = inp[i];
    	
	for(j = 1; j < numinputs; j++) {
	    inp = [inputs[j] getBits];			// Get an input's bits.
	    for(i = 0; i < numbits; i++) {
		temp[i] = [self op:temp[i] :inp[i]];	// Perform operation on bits.
	    }
	}
	
	[OUT setBits:temp];				// Copy answer to output node.
    }
    
    
    return self;
}


@end


//
// End of file.
//