Click here to Skip to main content
15,883,940 members
Articles / Web Development / HTML

Circuit Engine

Rate me:
Please Sign up or sign in to vote.
4.93/5 (103 votes)
18 Oct 2018GPL355 min read 248K   8.6K   212  
A System for Simulation and Analysis of Logic Circuits
/*
This file is part of Circuit Engine.
 
Circuit Engine is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
 
Circuit Engine is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
 
You should have received a copy of the GNU General Public License
along with Circuit Engine.  If not, see <http://www.gnu.org/licenses/>.
-----------------------------------------------------------------------
	BreadBoard.h : handles and manipulates the connections between CEs
*/

#pragma once
#include "BBNode.h"
#include "CircuitElement.h"



class BreadBoard
{
	friend CircuitElement;
	BBNode ***NodeHead;
	BBNode *CurrentHole;
    Binary ***NodeMapHead; //shows hole's availability.

	unsigned int nof_rows;//nof_rows * nof_cols = nof nodes.
	unsigned int nof_cols;
	unsigned int nof_holes_in_a_node;

	static unsigned int CurrentCableNodeID; //is set before call of SendCableNodeID recursion.

	void NewCurrentHole(void);
	void SetCurrentHole(Gate *GateInfo);
	void AddCurrentHole(unsigned int BBrow, unsigned int BBcol, unsigned int BBstride, CircuitElement* DontTriggerCable);
	void RemoveHole( unsigned int BBrow, unsigned int BBcol, Gate *RemGate, CircuitElement* DontTriggerCable);
	void SendCableNodeID(unsigned int BBrow,unsigned int BBcol, CircuitElement *DontTriggerCable);

	void GiveError(char *e);
	void CheckTableRange(unsigned int BBrow, unsigned int BBcol, unsigned int BBstride);
	Gate *IsThereOutputGateInBBNode(unsigned int BBrow, unsigned int BBcol);
	void CalculateCable(CircuitElement *Cable, unsigned int OutputRow, unsigned int OutputCol, bool OutputInsertion);

public:
    BreadBoard(unsigned int row, unsigned int col, unsigned int stride);
	~BreadBoard();

	void ToggleHole(unsigned int BBrow, unsigned int BBcol, unsigned int BBstride);
	bool IsHoleUsing(unsigned int BBrow, unsigned int BBcol, unsigned int BBstride);
	unsigned int GetStrideValue(){return nof_holes_in_a_node;}
	void SetLegPlugAbility(CircuitElement *CE);
	void PlugCE(CircuitElement *CE);
	void UnPlugCE(CircuitElement *CE);
	void debugprint(void);
	void debugInsertVG(Gate *V,Gate *G);
	void debugListCableNodes(CircuitElement *Cable);
	void BreadBoard::ListBBNode(unsigned int BBrow, unsigned int BBcol);
};

unsigned int BreadBoard::CurrentCableNodeID = 0;

void BreadBoard::GiveError(char *e)
{
	printf("\n(e)BreadBoard: %s",e);
	exit(1);
}
BreadBoard::BreadBoard(unsigned int row, unsigned int col, unsigned int stride)
{
	unsigned int i,j;

	nof_rows = row;
	nof_cols = col;
	nof_holes_in_a_node = stride;	

	//init NodeHead.
	printf("\nInitializing BreadBoard Node Table(r%d,c%d)...",nof_rows,nof_cols);
    NodeHead = (BBNode ***) malloc( sizeof(BBNode**) * nof_rows ); //create column pointers.
	if(NodeHead == NULL) GiveError("Initializing failed. (Not enough memory)");
	for(i=0 ; i<nof_rows  ; i++)
	{
		NodeHead[i] = (BBNode **) malloc( sizeof(BBNode*) * nof_cols );
	    if(NodeHead[i] == NULL) GiveError("Initializing failed. (Not enough memory)");
		for(j = 0 ; j < nof_cols ; j++)
			NodeHead[i][j] = NULL; //Init Node Heads as NULL...
	}
	printf("\nBreadBoard Node Table is ready.");
	//BBNodeHead Array is ready.

    CurrentHole = NULL;

	//init NodeMapHead.
	printf("\nInitializing BreadBoard Node Map Table(h%d)...",nof_holes_in_a_node);
	NodeMapHead = (Binary***) malloc( sizeof(Binary**) * nof_rows );
	if(NodeMapHead == NULL) GiveError("Initializing failed. (Not enough memory)");
	for(i = 0 ; i < nof_rows ; i++)
	{
		NodeMapHead[i] = (Binary**) malloc(sizeof(Binary*) * nof_cols );
		if(NodeMapHead[i] == NULL) GiveError("Initializing failed. (Not enough memory)");
		for(j = 0 ; j < nof_cols ; j++)
            NodeMapHead[i][j] = new Binary(nof_holes_in_a_node); //Init corresponding Binary Arrays...
	}
	printf("\nBreadBoard Node Map Table is ready.");
	//NodeMapHead is ready.
}

BreadBoard::~BreadBoard()
{

	unsigned int i,j;
	BBNode *del_1, *del_2;

    printf("\nDeallocating BreadBoard Node Table...");//clear NodeHead***
	for(i = 0 ; i < nof_rows ; i++)
	{
		for(j = 0 ; j < nof_cols ; j++)
		{
			del_1 = NodeHead[i][j];
			for(;del_1 != NULL;)
			{//free the linked list whose head is in (node [i][j]).
				del_2 = del_1->GetNextHole();
                delete del_1; //free the BBNode list element (the Hole).
				del_1 = del_2;
			}
		}
		free(NodeHead[i]);
	}
	free(NodeHead);


	printf("\nDeallocating BreadBoard Node Map Table...");
	for(i = 0 ; i < nof_rows ; i++)
	{
		for(j = 0 ; j < nof_cols ; j++)
            delete NodeMapHead[i][j];
        free(NodeMapHead[i]);
	}
	free(NodeMapHead);

	printf("\nDeallocation of BreadBoard is completed.");
}

void BreadBoard::debugprint(void)
{

	printf("\n<BB:INSIDE BBNodes listing>...\n");
	for(unsigned int i = 0; i < nof_rows; i++)
	{
		for(unsigned int j =0; j < nof_cols; j++)
		{
			printf("[%d,%d]:[",i,j);
			for(BBNode *pick_Hole = NodeHead[i][j]; pick_Hole != NULL; pick_Hole = pick_Hole->GetNextHole())
				if(pick_Hole->GetGateInfo()->GetGateType() == gtCable)
					printf("%p:%d-%d:%p(%d)",pick_Hole->GetGateInfo()->next_gate,((CircuitElement*)(pick_Hole->GetGateInfo()->next_gate))->GetID(),((CircuitElement*)(pick_Hole->GetGateInfo()->next_gate))->V.leg_no ,pick_Hole->GetGateInfo()->Input[0],pick_Hole->GetNodeMapIndex());
			printf("]");
		}
		printf("\n");

	}
	/*printf("\n<BB: BBNodeMaps listing>...\n");
	for(i = 0 ; i<nof_rows; i++)//node map of each node...
	{
        for(unsigned int j = 0; j<nof_cols; j++)
		{
			printf("[%d,%d]<",i,j);
			NodeMapHead[i][j]->debugprint();
			printf(">");
		}
		printf("\n");
	}*/
}
void BreadBoard::CheckTableRange(unsigned int BBrow, unsigned int BBcol, unsigned int BBstride)
{
	if(NodeMapHead == NULL) GiveError("Node Map couldn't found.");
	if(BBrow > nof_rows) GiveError("BBrow is too big.");
	if(BBcol > nof_cols) GiveError("BBcol is too big.");
	if(BBstride > nof_holes_in_a_node) GiveError("BBstride is too big.");
}
void BreadBoard::ToggleHole(unsigned int BBrow, unsigned int BBcol, unsigned int BBstride)
{
	CheckTableRange(BBrow, BBcol, BBstride);
	NodeMapHead[BBrow][BBcol][0][BBstride] == 0 ? NodeMapHead[BBrow][BBcol][0].SetIndex(BBstride) : NodeMapHead[BBrow][BBcol][0].ResetIndex(BBstride);
}
bool BreadBoard::IsHoleUsing(unsigned int BBrow, unsigned int BBcol, unsigned int BBstride)
{
	CheckTableRange(BBrow, BBcol, BBstride);
    return NodeMapHead[BBrow][BBcol][0][BBstride];
}

void BreadBoard::NewCurrentHole(void)
{
	if( CurrentHole != NULL )
		GiveError("BB::NewCurrentHole() : Missing AddCurrentHole().");
	CurrentHole = new BBNode();	//Current-Hole-Block start...
}
void BreadBoard::SetCurrentHole(Gate *GateInfo)
{
	if( CurrentHole == NULL ) GiveError("BB:SetCurrentHole() : Missing NewCurrentHole().");
    CurrentHole->SetGateInfo(GateInfo);
}
void BreadBoard::AddCurrentHole(unsigned int BBrow, unsigned int BBcol, unsigned int BBstride, CircuitElement* DontTriggerCable)
{
	BBNode * pick_HOLE;
	bool GateIsOutput = false;

	if(BBrow > this->nof_rows || BBcol > this->nof_cols || BBstride > this->nof_holes_in_a_node)
		GiveError("Fatal : Add Current Hole request exceeds the size of the BreadBoard");

	if((CurrentBBstride != BBstride) && (*(NodeMapHead[BBrow][BBcol]))[BBstride])
	{ //if the hole addition is not an output duplication && the corresponding hole is not empty phsically.
		GiveError("Fatal : BreadBoard::AddCurrentHole() - leg occupation physics crash (second insertion was requested on the same hole)");
	}

	NodeMapHead[BBrow][BBcol]->SetIndex(BBstride);// Set the corresponding map bit.
	CurrentHole->SetNodeMapIndex(BBstride);//save stride, to which hole the leg belongs to

	//if BBNode list is not empty && the inserting BBNode is not of a cable.
	if(NodeHead[BBrow][BBcol] != NULL && CurrentHole->GetGateInfo()->GetGateType() != gtCable) 
	{//don't make connection for cables (they are different than other CEs.)
		if(GateIsOutput = Gate::IsOutputtingGate(CurrentHole->GetGateInfo()->GetGateType()))
		{//make all inputting gates point to this new output leg(gate)
			for(pick_HOLE = NodeHead[BBrow][BBcol]; pick_HOLE != NULL; pick_HOLE = pick_HOLE->GetNextHole())
				if( pick_HOLE->GetGateInfo()->GetGateType() != gtCable ) //ignore cable BBNodes
					pick_HOLE->GetGateInfo()->Connect(0, CurrentHole->GetGateInfo());
		}
		else//if new leg is inputting and there is an outputting leg in the node.
		{//make new inputting gate point to the outputting gate.(IsThere...() returns NULL if there is not an output gate)
			CurrentHole->GetGateInfo()->Connect(0, IsThereOutputGateInBBNode(BBrow, BBcol));
		}
		//else: there is only inputting gates in the list and the new leg is inputting also
		//		so, do nothing about the connections...
	}

	//insert into corresponding list.

	//if this is the first BBNode in the list (Cable or Gate) 
	if(NodeHead[BBrow][BBcol] == NULL)
		NodeHead[BBrow][BBcol] = CurrentHole;
	else
	{//add after cable(s) (cables are always first in the list).
		
		//if this is the first cable insertion. (Gate)
		if(CurrentHole->GetGateInfo()->GetGateType() == gtCable && NodeHead[BBrow][BBcol]->GetGateInfo()->GetGateType() != gtCable)
		{//insert the cable as first hole element.
			CurrentHole->SetNextHole( NodeHead[BBrow][BBcol] );
			NodeHead[BBrow][BBcol] = CurrentHole;
		}
		else
		{//(Cable or Gate)
			//even if this is a cable insertion, it also places after previously inserted cables.		
			//pick_HOLE proceeds onto the last gtCable Node:
			for(pick_HOLE = NodeHead[BBrow][BBcol]; pick_HOLE->GetNextHole() != NULL && pick_HOLE->GetNextHole()->GetGateInfo()->GetGateType()==gtCable ; pick_HOLE=pick_HOLE->GetNextHole());
			CurrentHole->SetNextHole(pick_HOLE->GetNextHole());
			pick_HOLE->SetNextHole(CurrentHole);//the input/output node is placed into the list.
		}

		//there is/are cable(s),so output insertion triggers the cable(s).
		if(GateIsOutput) // (Gate)
		{//trigger the cable(s) for duplication.
			CurrentHole = NULL;//end of Current-Hole-Block... (In Calculate Cable, other insertion blocks are used also)
			for(pick_HOLE = NodeHead[BBrow][BBcol]; pick_HOLE->GetGateInfo()->GetGateType()==gtCable; pick_HOLE=pick_HOLE->GetNextHole())
				if(DontTriggerCable==NULL || (CircuitElement*)pick_HOLE->GetGateInfo()->next_gate != DontTriggerCable)
					//next gate of V in CABLE element points to the CE:CABLE which has this V.
                    CalculateCable((CircuitElement*)(pick_HOLE->GetGateInfo()->next_gate),BBrow,BBcol, true);
		}

	}
	
	CurrentHole = NULL;//end of Current-Hole-Block...

}
void BreadBoard::SetLegPlugAbility(CircuitElement *CE)
{//KIMT : coordinates X and Y in BBDS are swapped in GUI...
	int NofLegsOverTwo = CE->GetNofLegs()/2;
	int i;																//leg index counter
	unsigned int FLrow = CE->GetPositionY();							//first leg row coord.
	unsigned int FLcol = CE->GetPositionX()/(nof_holes_in_a_node+2);	//first leg col coord.
	unsigned int FLstride = CE->GetPositionX()%(nof_holes_in_a_node+2);	//first leg stride coord.

	CE->LegPlugAbility.Clear();	//make all RED at first

	switch(CE->GetType())
	{
	case cetCHIP:

		for( i = 0 ; i < NofLegsOverTwo ; i++)//for left legs up to down
		{
			//goto corr. hole map (leg position) and check if there is already any other plugged.
			if(NodeMapHead[FLrow + i][FLcol][0][FLstride])			
				continue;	//There is already plugged one, so leave it as RED (not pluggable)... <<<
			
			//if hole is empty, proceed for logical test (there cannot be more than 1 outputting gate within the same node)
			if( !CE->IsOutputtingLeg(i) )	//Is this leg of CE an inputting gate?
			{
				CE->LegPlugAbility.SetIndex(i);	//if it's not an outputting gate make it pluggable... <<< (N/A legs interpreted as input gates...)
				continue;
			}			

			//It's an outputting gate,so check if there is any other in the node.
			if(!IsThereOutputGateInBBNode(FLrow+i,FLcol))
			{
				CE->LegPlugAbility.SetIndex(i);	//if no any other outputting, make it pluggable... <<<
				continue;
			}
			
		}
		i--;
		FLcol = (CE->GetPositionX()+3)/(nof_holes_in_a_node+2);	//first leg col coord.
		FLstride = (CE->GetPositionX()+3)%(nof_holes_in_a_node+2);	//first leg stride coord.
		for(; i >= 0 ; i--)//for right legs down to up.
		{
			//goto corr. hole map (leg position) and check if there is already any other plugged.//CE->GetPositionX()+3 for chip
			if(NodeMapHead[FLrow + i][FLcol][0][FLstride])
				continue;//There is already plugged one, so leave it as RED (not pluggable)... <<<
			
			//if hole is empty, proceed for logical test (there cannot be more than 1 outputting gate within the same node)
			if( !CE->IsOutputtingLeg(CE->GetNofLegs() - i - 1) )		//Is this leg of CE an outputting gate?
			{
				CE->LegPlugAbility.SetIndex(CE->GetNofLegs() - i - 1); //if it's not an outputting gate make it pluggable... <<<
				continue;
			}

			//It's an outputting gate,so check if there is any other in the node.
			if(!IsThereOutputGateInBBNode(FLrow+i,FLcol))
			{
				CE->LegPlugAbility.SetIndex(CE->GetNofLegs() - i - 1);	//if no any other outputting make it pluggable... <<<
				continue;
			}			
			
		}
		break;
	case cetLED:
		if(!NodeMapHead[FLrow][FLcol][0][FLstride])//if up leg hole is not occupied
			CE->LegPlugAbility.SetIndex(0);		

		if(!NodeMapHead[FLrow+1][FLcol][0][FLstride])//if down leg hole is not occupied
			CE->LegPlugAbility.SetIndex(1);
		break;
	case cetCABLE:

		//first leg's position is already calculating for all CEs before the 'switch', so here is just for second leg.
		unsigned int SLrow = CE->GetPositionY2(); //CABLE second leg row position.
		unsigned int SLcol = CE->GetPositionX2()/(nof_holes_in_a_node + 2); //CABLE second leg col position.
		unsigned int SLstride = CE->GetPositionX2()%(nof_holes_in_a_node + 2); //CABLE second leg stride position.
		unsigned int SELrow, SELcol, SELstride;

		for(int i=0; i<2; i++)
		{	//SEL - selected , SL - second leg.
			SELrow = i ? SLrow : FLrow;	// 0 - first leg, 1 - second leg.
			SELcol = i ? SLcol : FLcol;
			SELstride = i ? SLstride : FLstride;

			if(!CE->CEInfo[ceqHover1 + i])	//if the leg i is already plugged, make its ability of plugging TRUE.
			{
				CE->LegPlugAbility.SetIndex(i);
				continue;
			}

			if(!NodeMapHead[SELrow][SELcol][0][SELstride])//if corrs. hole is physically empty.
			{
				if(CE->CEInfo[ceqHover2 - i] || CE->V.Input[0] == NULL || //if other is hover or there is no output report.
					!IsThereOutputGateInBBNode(SELrow,SELcol) )// or there is no output in selected leg's node.
					CE->LegPlugAbility.SetIndex(i);				

				if(NodeHead[SELrow][SELcol]!=NULL && NodeHead[SELrow][SELcol]->GetGateInfo()->GetGateType()==gtCable && CE->V.leg_no == NodeHead[SELrow][SELcol]->GetGateInfo()->leg_no)//if corresponding hole is the same node(connecting the two edges of the cable at the same node is meaningless)				
                    CE->LegPlugAbility.ResetIndex(i);					
				
			}
		}
		//if other is plugged and other has O and selected has output, leave it as RED.

		break;
	}
}


void BreadBoard::PlugCE(CircuitElement *CE)
{//before this procedure, the SetLegPlugAbility() must be called for circuit consistency and for GUI feedback.
 //(in this procedure the possibility of a second outputting gate in a BBNode list is not checked)
		
	/*printf("\nPrinting BBDS before PlugCE() (CE = %s:%p)",CE->GetName(),CE);
	debugprint();*/

	int i = 0;														//leg index counter
	unsigned int FLrow = CE->GetPositionY();						//first leg row coord.
	unsigned int FLcol = CE->GetPositionX()/(nof_holes_in_a_node+2);	//first leg col coord.
	unsigned int FLstride = CE->GetPositionX()%(nof_holes_in_a_node+2);	//first leg stride coord.
	Gate *AddrOfLegI; // the address of the gate which is connected to the leg number I.

	switch(CE->GetType())
	{
	case cetCHIP:
		for( ; i<(int)CE->GetNofLegs()/2 ; i++) //left legs
		{
			//printf("\nBB:PCE():Plugging Leg(row<%d>col<%d>str<%d>)",FLrow+i,FLcol,FLstride);//DEBUG

			AddrOfLegI = CE->GetGateAddrOfLeg(i);
			if(AddrOfLegI == NULL)
			{
				NodeMapHead[FLrow + i][FLcol][0].SetIndex(FLstride); //N/A leg only fills physically.
				continue;//It is a N/A leg, so proceed to next leg without any action.
			}

			//Create a new BBNode
			NewCurrentHole();
			//Load gate info into the BBNode
			SetCurrentHole( AddrOfLegI );

			//Add BBNode into the BBNode list and (this procedure also sets corresponding NodeMap bit)
			AddCurrentHole(FLrow + i, FLcol, FLstride, NULL);
		}
		i--;
		FLcol = (CE->GetPositionX()+3)/(nof_holes_in_a_node+2);
		FLstride = (CE->GetPositionX()+3)%(nof_holes_in_a_node+2);
		for( ; i>=0 ; i--) //right legs
		{
			//printf("\nBB:PCE():Plugging Leg(row<%d>col<%d>str<%d>)",FLrow+i,FLcol,FLstride);//DEBUG

			AddrOfLegI = CE->GetGateAddrOfLeg(CE->GetNofLegs() - i - 1);
			if(AddrOfLegI == NULL)
			{
				NodeMapHead[FLrow +i][FLcol][0].SetIndex(FLstride); //N/A leg only fills physically.
				continue;//It is a N/A leg, so proceed to next leg without doing nothing.
			}
			//Create a new BBNode
			NewCurrentHole();
			//Load gate info into the BBNode
			SetCurrentHole( AddrOfLegI );

			//Add BBNode into the BBNode list and (this procedure also sets corresponding NodeMap bit)
			AddCurrentHole(FLrow + i, FLcol, FLstride, NULL);//stride is 0 for right legs.
		}

		break;
	case cetLED:
		//insert necessary BBNodes for up and down leg and mark the corresponding Node Map bits
		for(i=0; i<2; i++) // for voltage and ground legs only.(up leg is the voltage)
		{
			NewCurrentHole();
			SetCurrentHole(CE->GetGateAddrOfLeg(i));
			AddCurrentHole(FLrow+i, FLcol, FLstride, NULL); //this proced. also sets corresponding map bit.
		}
		break;
	case cetCABLE:
		//cable BBNode insertion realizes the original output if there is in other side or selected side,
		//and if found, duplicates it into the selected leg's or the other leg's BBNode respectively.

		bool SelL = CE->V.output;												// get selected leg. 0 = first leg, 1 = second leg
		unsigned int SLrow = CE->GetPositionY2();								//CABLE second leg row position.
		unsigned int SLcol = CE->GetPositionX2()/(nof_holes_in_a_node + 2);		//CABLE second leg col position.
		unsigned int SLstride = CE->GetPositionX2()%(nof_holes_in_a_node + 2);	//CABLE second leg stride position.

		unsigned int SELrow = SelL?SLrow:FLrow;
		unsigned int SELcol = SelL?SLcol:FLcol;
		unsigned int OTHERrow = SelL?FLrow:SLrow;
		unsigned int OTHERcol = SelL?FLcol:SLcol;

		//printf("\n\nprocessing PLUGGING REQUEST FOR CABLE %p for %s leg :",CE,CE->V.output?"Second":"First");//DEBUG

		//insert the BBNode for cable.
		//printf("\n Inserting cable BBNode into node [%d,%d], the leg is in plugged state now.",SELrow,SELcol); //DEBUG
        CE->CEInfo.ResetIndex(ceqHover1 + SelL); //make plugged the selected leg.
		NewCurrentHole();
		SetCurrentHole(&(CE->V)); //this is the CABLE specific BBNode which specifies that the node has this CABLE plugged.
		AddCurrentHole(SELrow, SELcol, SelL?SLstride:FLstride, NULL);//insert the cable BBNode into the selected's node list.

		//PLUGGING CABLE LEG

		if(CE->CEInfo[ceqHover2-SelL]) 
		{//if other is not plugged
            //printf("\n cable's other leg is in hover mode."); // DEBUG
			CE->V.Input[0] = IsThereOutputGateInBBNode(SELrow,SELcol); // report Output if there is one.
			//printf("\n Output Report is done as %p.",CE->V.Input[0]); //DEBUG

			//CABLE_NODE_ID SETTING
			if(NodeHead[SELrow][SELcol]->GetGateInfo()->GetGateType() == gtCable) //if there is another cable in the node
			{//get the cable node id of other cables.
				CE->V.leg_no = NodeHead[SELrow][SELcol]->GetGateInfo()->leg_no;
				//printf("\n CNID is taken as %d.\n",CE->V.leg_no); // DEBUG
			}
		}
		else
		{//if other is plugged

			//printf("\n cable's other leg is plugged.\n pocessing CNID diffuseness..."); //DEBUG

			//CABLE_NODE_ID SETTING
			//inherit the cabe node id to the currently plugging and consecutive cables.
			if((CircuitElement*)(NodeHead[SELrow][SELcol]->GetGateInfo()->next_gate) != CE && NodeHead[SELrow][SELcol]->GetGateInfo()->GetGateType() == gtCable)//if there is other cables.
			{
				//give the CNID of the already existing first cable in the list to the new plugging.
				CurrentCableNodeID = CE->V.leg_no = NodeHead[SELrow][SELcol]->GetGateInfo()->leg_no;
				//printf("\n CurrentCableNodeID = %d",CurrentCableNodeID); //DEBUG
				//and attenuate the ID also on the other node.
				//printf("\n Sending CNID into its %s node.\n",CE,CE->V.output?"First Leg":"Second Leg"); //DEBUG
				SendCableNodeID(OTHERrow,OTHERcol, CE); // trigger cables on other node to make the CNID diffuseness (other than CE)
			}
			//EOF CABLE_NODE_ID SETTING

			//printf("\n EOF CNID diffuseness.\n\n checking output report..."); //DEBUG

            if(CE->V.Input[0])//if there is report => commit to the other side
			{//copy Od to this node
				//printf("\n output report is found as %p.", CE->V.Input[0]); //DEBUG

				//printf("\n Inserting Od into plugging node > (%d,%d).",SELrow,SELcol); //DEBUG
                NewCurrentHole();
				SetCurrentHole(CE->V.Input[0]);//this is Od which has been reported by other leg.
				AddCurrentHole(SELrow,SELcol, nof_holes_in_a_node, CE); //with stride nof_holes_in_a_node; it doesn't occupy a hole physically.

				CE->CEInfo.SetIndex(ceqHasOd1 + CE->V.output);

				//printf("\n The HasOd%d flag is set as %d", CE->V.output + 1, CE->CEInfo[ceqHasOd1 + CE->V.output]); //DEBUG
			}
			else
			{//if there is no report
				//printf("\n no output report found.\n Checking if there is an output in the plugging node..."); //DEBUG
				//check if this has O
				if(CE->V.Input[0] = IsThereOutputGateInBBNode(SELrow,SELcol))
				{//report it and copy Od to other
					//printf("\n output BBNode found as %p > Cable->V.Input[0] = %p",IsThereOutputGateInBBNode(SELrow,SELcol),CE->V.Input[0]); //DEBUG

					NewCurrentHole();
					SetCurrentHole(CE->V.Input[0]);//this is Od which will be reported to other leg.
					AddCurrentHole(OTHERrow, OTHERcol, nof_holes_in_a_node, CE);

					//printf("\n Output is duplicated into %s node (%d,%d) as %p.", CE->V.output?"First Leg":"Second Leg", OTHERrow, OTHERcol, CE->V.Input[0]); // DEBUG
					//indicate that the OTHER leg has Od.
					CE->CEInfo.SetIndex(ceqHasOd2 - CE->V.output);
					//printf("\n The HasOd%d flag is set as %d", 2 - CE->V.output, CE->CEInfo[ceqHasOd2 - CE->V.output]); //DEBUG
				}
				//else printf("\n no output BBNode found in the plugging node."); //DEBUG

			}


		}

		//printf("\nPLUGGING FOR CABLE process is completed."); // DEBUG

		SetLegPlugAbility(CE);
		break;
	}

	//printf("\nPrinting BBDS after PlugCE() (CE = %s:%p)",CE->GetName(),CE);
	//debugprint();

}
void BreadBoard::UnPlugCE(CircuitElement *CE)
{
	int i;																//leg index counter
	unsigned int FLrow = CE->GetPositionY();							//first leg row coord.
	unsigned int FLcol = CE->GetPositionX()/(nof_holes_in_a_node+2);	//first leg col coord.
	unsigned int FLstride = CE->GetPositionX()%(nof_holes_in_a_node+2);	//first leg stride coord.
	Gate *AddrOfLegI;

	/*printf("\nPrinting BBDS before UnPlugCE() (CE = %s:%p)",CE->GetName(),CE);
	debugprint();*/

	switch(CE->GetType())
	{
	case cetCHIP:
		for(i = 0 ; i < (int)CE->GetNofLegs()/2 ; i++)//left legs
		{
			AddrOfLegI = CE->GetGateAddrOfLeg(i);
			if(AddrOfLegI == NULL)
			{
				NodeMapHead[FLrow +i][FLcol][0].ResetIndex(FLstride); //N/A leg only fills physically.
				continue;//It is a N/A leg, so proceed to next leg without doing nothing.
			}
			RemoveHole(FLrow+i,FLcol,AddrOfLegI, NULL);

		}
		i--;
		FLcol = (CE->GetPositionX()+3)/(nof_holes_in_a_node+2); //set col and row positions for right legs.
		FLstride = (CE->GetPositionX()+3)%(nof_holes_in_a_node+2);
		for( ; i >= 0 ; i--) //right legs
		{
			AddrOfLegI = CE->GetGateAddrOfLeg(CE->GetNofLegs() - i - 1);
			if(AddrOfLegI == NULL)
			{
				NodeMapHead[FLrow +i][FLcol][0].ResetIndex(FLstride); //N/A leg only fills physically.
				continue;//It is a N/A leg, so proceed to next leg without doing nothing.
			}
			RemoveHole(FLrow+i,FLcol,AddrOfLegI, NULL);
		}

		break;
	case cetLED:
		//remove and delete BBNodes of V and G for up and down leg and unmark the corresponding Node Map bits
		for(i = 0 ; i<2 ; i++)
		{
			AddrOfLegI = CE->GetGateAddrOfLeg(i);
			RemoveHole(FLrow+i,FLcol,AddrOfLegI, NULL);
		}
		break;
	case cetCABLE:
		//remove dublication Od, if there is one at any side of the cable.
		//unmark corrs. node map bit.

		unsigned int SLrow = CE->GetPositionY2(); //CABLE second leg row position.
		unsigned int SLcol = CE->GetPositionX2()/(nof_holes_in_a_node + 2); //CABLE second leg col position.
		unsigned int SLstride = CE->GetPositionX2()%(nof_holes_in_a_node + 2); //CABLE second leg stride position.

		unsigned int SELrow = CE->V.output?SLrow:FLrow;
		unsigned int SELcol = CE->V.output?SLcol:FLcol;
		unsigned int OTHERrow = CE->V.output?FLrow:SLrow;
		unsigned int OTHERcol = CE->V.output?FLcol:SLcol;

		//remove the cable leg's node
		RemoveHole(SELrow,SELcol, &CE->V, NULL);

		//UNPLUGGING CABLE LEG
		if(CE->CEInfo[ceqHover2 - CE->V.output])
		{//if other is not plugged

			//delete report if any
            CE->V.Input[0] = NULL;

			//Cable Node Id setting
			CE->V.leg_no = CE->GetID(); //other leg is hover and SEL leg is also hover, so get initial CNID,which is the CEID.
		}
		else
		{//if other is plugged

			//if there is report
			if(CE->V.Input[0])
			{
				//if the removing (this) side has Od (Other node has original output O)
                if(CE->CEInfo[ceqHasOd1 + CE->V.output])
				{//remove Od from this and trigger >other cables!< in this node

					RemoveHole(SELrow,SELcol,CE->V.Input[0], NULL);		//remove Od and trigger remaining cables
						CE->CEInfo.ResetIndex(ceqHasOd1 + CE->V.output);	//indicate that this has no duplication.

				}
				//if other has Od (removing (this) leg has original output O)
				else
				{//remove Od from other and trigger cables in that node

					RemoveHole(OTHERrow, OTHERcol, CE->V.Input[0],CE); //remove Od, and trigger other cables in OTHER node.

					CE->V.Input[0] = NULL; //delete report
					CE->CEInfo.ResetIndex(ceqHasOd2 - CE->V.output); //OTHER has no more dublication
				}
			}

			//and send this CEID as CNID to other leg's node.
			CurrentCableNodeID = CE->GetID();
            SendCableNodeID(OTHERrow,OTHERcol, NULL);

		}

		//(Unplugging Side) set CNID of the remaining cables as the first cabe's CEID in the list.
		if(NodeHead[SELrow][SELcol]!=NULL && NodeHead[SELrow][SELcol]->GetGateInfo()->GetGateType()==gtCable)
		{
			//diffuse the ID of first plugged CABLE.
			CurrentCableNodeID = ((CircuitElement*)(NodeHead[SELrow][SELcol]->GetGateInfo()->next_gate ))->GetID();
			SendCableNodeID(SELrow,SELcol,NULL);
		}

		/*printf("\nLISTING AFTER UNPLUGGING");
		printf("\nSELHasOd?= %d OTHERHasOd? = %d", CE->CEInfo[ceqHasOd1 + CE->V.output], CE->CEInfo[ceqHasOd2 - CE->V.output]);
		printf("\nSEL corrs. BB Node:");
		ListBBNode(SELrow,SELcol);
		printf("\nOTHER corrs. BB Node:");
		ListBBNode(OTHERrow,OTHERcol);
		SetLegPlugAbility(CE);*/

		break;
	}

	//printf("\nPrinting BBDS after UnPlugCE() (CE = %s:%p)",CE->GetName(),CE);
	//debugprint();
}
Gate *BreadBoard::IsThereOutputGateInBBNode(unsigned int BBrow, unsigned int BBcol)
{
    for(BBNode *pick_HOLE = NodeHead[BBrow][BBcol]; pick_HOLE!=NULL; pick_HOLE = pick_HOLE->GetNextHole())
	{
		if(Gate::IsOutputtingGate(pick_HOLE->GetGateInfo()->GetGateType()))
		{
			//printf("\nBB:IsThereOutputtingLeg(): YES");//DEBUG
			return pick_HOLE->GetGateInfo();
		}
	}
	//printf("\nBB:IsThereOutputtingLeg(): NO");//DEBUG
	return NULL;
}
void BreadBoard::debugInsertVG(Gate *V,Gate *G)
{//DEBUG
    NewCurrentHole();
	SetCurrentHole(V);
	AddCurrentHole(0,0,0, NULL);

    NewCurrentHole();
	SetCurrentHole(G);
	AddCurrentHole(1,0,0, NULL);
}

void BreadBoard::RemoveHole( unsigned int BBrow, unsigned int BBcol, Gate *RemGate, CircuitElement* DontTriggerCable)
{
	BBNode *pick_HOLE, *IsolatedBBNode;

	//isolation of BBNode of the corresponding gate from BBNode list:
	pick_HOLE = NodeHead[BBrow][BBcol];

	if(pick_HOLE->GetNextHole()==NULL)
	{//if this is the last leg in the node, just remove it
		NodeHead[BBrow][BBcol] = NULL;
		NodeMapHead[BBrow][BBcol][0].ResetIndex(pick_HOLE->GetNodeMapIndex());
		delete pick_HOLE;
		return; //go on to the next leg.
	}
	else if( pick_HOLE->GetGateInfo() == RemGate)
	{//if it is the first leg in the list.
		IsolatedBBNode = NodeHead[BBrow][BBcol];
		NodeHead[BBrow][BBcol] = IsolatedBBNode->GetNextHole();
	}
	else //if it is in the middle of the list or at the end of the list.
	{
		//proceed onto the previous of the BBNode which will be isolated.
		for(pick_HOLE = NodeHead[BBrow][BBcol]; pick_HOLE->GetNextHole()->GetGateInfo() != RemGate ; pick_HOLE = pick_HOLE->GetNextHole());
		IsolatedBBNode = pick_HOLE->GetNextHole();
		pick_HOLE->SetNextHole(IsolatedBBNode->GetNextHole()); // <<<isolating...
	}
	//end of isolation of the unplugging leg.

	//adjust the connections other than the isolated(unplugging) one:
	if(Gate::IsOutputtingGate(IsolatedBBNode->GetGateInfo()->GetGateType()))
	{//the isolated leg is an outputting gate => make all (input) gates in the BBNode list point to NULL
		//pass cables
		for(pick_HOLE = NodeHead[BBrow][BBcol]; pick_HOLE!=NULL && pick_HOLE->GetGateInfo()->GetGateType()==gtCable; pick_HOLE=pick_HOLE->GetNextHole());
		for(;pick_HOLE != NULL; pick_HOLE = pick_HOLE->GetNextHole())
			pick_HOLE->GetGateInfo()->Connect(0, NULL);
		//if there any cable in the BBNode list, trigger them to make necessary alterations over other connected nodes.
		for(pick_HOLE = NodeHead[BBrow][BBcol];  pick_HOLE != NULL && pick_HOLE->GetGateInfo()->GetGateType()==gtCable; pick_HOLE = pick_HOLE->GetNextHole())
			if(DontTriggerCable == NULL || (CircuitElement*)pick_HOLE->GetGateInfo()->next_gate != DontTriggerCable)
				CalculateCable((CircuitElement*)(pick_HOLE->GetGateInfo()->next_gate), BBrow, BBcol, false);
	}
	else if(IsolatedBBNode->GetGateInfo()->GetGateType() != gtCable)//if the isolated leg is an inputting gate other than gtCable
	{//only make this input gate point to NULL
		IsolatedBBNode->GetGateInfo()->Connect(0, NULL);
	}

	//reset the corresponding NodeMap bit
	NodeMapHead[BBrow][BBcol][0].ResetIndex(IsolatedBBNode->GetNodeMapIndex());
	//destroy the isolated BBNode
	delete IsolatedBBNode;
}
//CALCULATECABLE WORKS, if:
//1) triggered by cable plug/unplug, it occurs when it is plugged or unplugged.
//2) triggered by Output gates,it occurs when an Output gate insertion/deletion is made.
void BreadBoard::CalculateCable(CircuitElement *Cable, unsigned int OutputRow, unsigned int OutputCol, bool OutputInsertion)
{
	unsigned int FLrow =	Cable->GetPositionY();								//first leg row coord.
	unsigned int FLcol =	Cable->GetPositionX()/(nof_holes_in_a_node+2);		//first leg col coord.
	unsigned int FLstride = Cable->GetPositionX()%(nof_holes_in_a_node+2);		//first leg stride coord.
	unsigned int SLrow =	Cable->GetPositionY2();								//CABLE second leg row position.
	unsigned int SLcol =	Cable->GetPositionX2()/(nof_holes_in_a_node + 2);	//CABLE second leg col position.
	unsigned int SLstride = Cable->GetPositionX2()%(nof_holes_in_a_node + 2);	//CABLE second leg stride position.


	bool triggered_leg = (OutputRow==SLrow)&&(OutputCol==SLcol); // 0 - leg_1 (FL), 1 - leg_2 (SL)
	unsigned int OTHERrow = triggered_leg?FLrow:SLrow;
	unsigned int OTHERcol =	triggered_leg?FLcol:SLcol;
	unsigned int OTHERstride = triggered_leg?FLstride:SLstride;


	if(OutputInsertion)
	{//if an O is inserted
		//printf("\nCalcCable(%p:%d) O insertion request : triggered from r.%d,c.%d",Cable,Cable->GetID(),OutputRow,OutputCol); //DEBUG

		//Report that the O gate has been had
		Cable->V.Input[0] = IsThereOutputGateInBBNode(OutputRow,OutputCol);
		//indicate that the leg other than the triggered has the Od
		Cable->CEInfo.SetIndex(ceqHasOd2 - triggered_leg);

		//printf(" -- Duplication request to other node r.%d,c.%d",OTHERrow,OTHERcol); //DEBUG
		//prepare BBNode for Od
		NewCurrentHole();
		SetCurrentHole(Cable->V.Input[0]);
        AddCurrentHole(OTHERrow,OTHERcol,CurrentBBstride, Cable);// call adding without triggering this cable.
		//the BBNode Od does not occupy physical hole; that's why the stride value is CurrentBBstride.

		//now, the cable is in the hasOutput state(i.e. it conducts)
	}
	else
	{//if an O is removed
		//printf("\nCalcCable(%p:%d) O removal request : triggered from r.%d,c.%d",Cable,Cable->GetID(),OutputRow,OutputCol); //DEBUG

		//printf(" -- Removing Od request to other node r.%d,c.%d",OTHERrow,OTHERcol); //DEBUG
		//remove the remaining Od from other node as no giving a triggering to itself.
		RemoveHole(OTHERrow,OTHERcol, Cable->V.Input[0], Cable);

		//indicate that the cable has no Od any more
		Cable->CEInfo.ResetIndex(ceqHasOd2 - triggered_leg);
		//Report that there is no O gate any more
		Cable->V.Input[0] = NULL;

		//now, the cable is in the hasNoOuput state(i.e. it doesn't conduct)
	}

}

void BreadBoard::ListBBNode(unsigned int BBrow, unsigned int BBcol)
{
    BBNode *pick_HOLE = NodeHead[BBrow][BBcol];
	printf("\nHole[%d][%d] Inside (",BBrow,BBcol);

	NodeMapHead[BBrow][BBcol]->debugprint();

	printf(")");

	for(;pick_HOLE!=NULL; pick_HOLE = pick_HOLE->GetNextHole())
		printf("\nGateType = %d,   ",pick_HOLE->GetGateInfo()->GetGateType());
	printf("\n");
}
unsigned int FLrow,FLcol,SLrow,SLcol;
CircuitElement *Cable;

void BreadBoard::SendCableNodeID(unsigned int BBrow,unsigned int BBcol, CircuitElement *DontTriggerCable)
{//diffuses the CNID over the given node coord. in order to distinguish Cable Nodes.
	//printf("\nCNID(%d) diffuse request at r.%d,c.%d donttouchcable(%p)",CurrentCableNodeID, BBrow, BBcol, DontTriggerCable); //DEBUG

	//for each cable on the node (BBrow,BBcol) except the cable DontTriggerCable:
	for(BBNode *pick_HOLE = NodeHead[BBrow][BBcol]; pick_HOLE != NULL && pick_HOLE->GetGateInfo()->GetGateType() == gtCable; pick_HOLE = pick_HOLE->GetNextHole())
	{
		if((CircuitElement*)(pick_HOLE->GetGateInfo()->next_gate) != DontTriggerCable)
		{
			
			pick_HOLE->GetGateInfo()->leg_no = CurrentCableNodeID;//give Cable Node ID to the cable			
			//send the ID to other node also
			Cable = (CircuitElement*)(pick_HOLE->GetGateInfo()->next_gate);
			FLrow =	Cable->GetPositionY();								//first leg row coord.
			FLcol =	Cable->GetPositionX()/(nof_holes_in_a_node+2);		//first leg col coord.
			SLrow =	Cable->GetPositionY2();								//CABLE second leg row position.
			SLcol =	Cable->GetPositionX2()/(nof_holes_in_a_node + 2);	//CABLE second leg col position.
			
			//printf("\nTrg->Cable(%p,l1(r.%d,c.%d),l2(r.%d,c.%d)) CNID : %d",pick_HOLE->GetGateInfo()->next_gate,FLrow,FLcol,SLrow,SLcol,pick_HOLE->GetGateInfo()->leg_no); // DEBUG

			if(BBrow == FLrow && BBcol == FLcol)
			{
				if(!Cable->CEInfo[ceqHover2])//if second leg is plugged, affect the others on the second leg's node.
				{
					//printf("\nrequesting other node (r.%d,c.%d)",SLrow,SLcol); //DEBUG					
					SendCableNodeID(SLrow,SLcol,Cable);
					//printf("\nEnd of CNID diffuse request at (%d,%d)",SLrow,SLcol); //DEBUG
				}
			}
			else
			{
				if(!Cable->CEInfo[ceqHover1])//if first leg is not hover affect the others on the first leg's node.
				{
					//printf("\n requesting other node (r.%d,c.%d)",FLrow,FLcol); //DEBUG
                    SendCableNodeID(FLrow,FLcol,Cable);
					//printf("\nEnd of CNID diffuse request at (%d,%d)",FLrow,FLcol); //DEBUG
				}
			}
			
		}
	}
}

void BreadBoard::debugListCableNodes(CircuitElement *Cable)
{
	if(Cable->GetType() != cetCABLE) return;
	//list the node lists under the corresponding cable legs.
	unsigned int FLrow =	Cable->GetPositionY();								//first leg row coord.
	unsigned int FLcol =	Cable->GetPositionX()/(nof_holes_in_a_node+2);		//first leg col coord.	
	unsigned int SLrow =	Cable->GetPositionY2();								//CABLE second leg row position.
	unsigned int SLcol =	Cable->GetPositionX2()/(nof_holes_in_a_node + 2);	//CABLE second leg col position.

	BBNode *pick_HOLE;
	unsigned int i;

    //list the first leg's node.
	printf("\nLISTING FIRST LEG'S NODE OF CABLE %p at (%d,%d)...\n", Cable, FLrow,FLcol);
	if(pick_HOLE = NodeHead[FLrow][FLcol])
	{
        for(i=0;pick_HOLE!=NULL; pick_HOLE = pick_HOLE->GetNextHole(), i++)
		{
			printf("\n  BBNode %d :", i);
			printf("\n  Pointing Gate Address : %p", pick_HOLE->GetGateInfo());
			if(pick_HOLE->GetGateInfo()->GetGateType() == gtCable) 
				printf(" (CE - %p)",pick_HOLE->GetGateInfo()->next_gate);
			printf("\n  Pointing Gate Type : %s", GateNames[pick_HOLE->GetGateInfo()->GetGateType()]);
			if(pick_HOLE->GetGateInfo()->GetGateType() == gtInput)
				printf(" (getting input from %p)",pick_HOLE->GetGateInfo()->Input[0]);
			printf("\n  Node Map Index : %d", pick_HOLE->GetNodeMapIndex());
			if(Gate::IsOutputtingGate(pick_HOLE->GetGateInfo()->GetGateType()))
				if(pick_HOLE->GetNodeMapIndex() == CurrentBBstride)
					printf(" (diffuse)");
				else
					printf(" (original)");
		}
		printf("\n");
	}
	else printf("\n  empty node list.\n");
	printf("\nEND OF FIRST LEG'S NODE LIST.");

	//list the second leg's node.
	printf("\nLISTING SECOND LEG'S NODE OF CABLE %p at (%d,%d)...\n", Cable, SLrow,SLcol);
	if(pick_HOLE = NodeHead[SLrow][SLcol])
	{
        for(i=0;pick_HOLE!=NULL; pick_HOLE = pick_HOLE->GetNextHole(), i++)
		{
			printf("\n  BBNode %d :", i);
			printf("\n  Pointing Gate Address : %p", pick_HOLE->GetGateInfo());
			if(pick_HOLE->GetGateInfo()->GetGateType() == gtCable) 
				printf(" (CE - %p)",pick_HOLE->GetGateInfo()->next_gate);
			printf("\n  Pointing Gate Type : %s", GateNames[pick_HOLE->GetGateInfo()->GetGateType()]);
			if(pick_HOLE->GetGateInfo()->GetGateType() == gtInput)
				printf(" (getting input from %p)",pick_HOLE->GetGateInfo()->Input[0]);
			printf("\n  Node Map Index : %d", pick_HOLE->GetNodeMapIndex());
			if(Gate::IsOutputtingGate(pick_HOLE->GetGateInfo()->GetGateType()))
				if(pick_HOLE->GetNodeMapIndex() == CurrentBBstride)
					printf(" (diffuse)");
				else
					printf(" (original)");
		}
		printf("\n");
	}
	else printf("\n  empty node list.\n");
	printf("\nEND OF SECOND LEG'S NODE LIST.");

}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The GNU General Public License (GPLv3)


Written By
Engineer Siemens
Turkey Turkey
I've graduated from computer engineering department in 2004 July, and developed the Circuit Engine as my graduation project at Eastern Mediterranean University (EMU). I've also graduated from MBA, Istanbul University in 2008 February. From 2004 until now, I've developed many web sites (B2B, B2C). Currently work for Siemens AG (http://siemens.com/ingenuityforlife) as a R&D Engineer (IoT) and I still continue to develop my personal projects about encryption algorithms, maths, OpenGL, Stock Exchange Market Analyses and Real-time Systems, MultiThreaded Applications and Web Solutions (mostly ASP.NET C#, JQuery/JS, MVC, WinForms, Win/Web Services, T-SQL and less PHP, ASP, MySQL and some possible other methods about problem solving if necessary). Also personal profession of photography : https://www.instagram.com/egldgn/


Circuit Engine base URL : https://sites.google.com/view/circuitengine


Comments and Discussions