#include <math.h>
#include <string.h>
#include "Reo__Matrix_Mult.h"
#include "Circuit.h"

VReoCircuit *create_circuit(SlaveVP *animVP) {

	/* Declare variables. */
	VReoCircuit  *circuit;
	VReoBridge   *bridge, *bridges, **boundaryBridges;
	VReoIsland   *islands, *island;
	VReoO1island *o1islands, *o1island;
	VReoCheckerFn *bridgeReaderCheckerFns, *bridgeWriterCheckerFns;
	VReoDoerFn   *bridgeReaderDoerFns, *bridgeWriterDoerFns;
	PrivQueueStruc *offerQ0, *offerQ1;
	VReoPartnerQStruct *partnerQStruct0, *partnerQStruct1;

	/* Allocate memory for bridges, islands, and the circuit. */
	bridges = PR_WL__malloc(NUM_BRIDGES * sizeof(VReoBridge));
	islands = PR_WL__malloc((NUM_ISLANDS == 0 ? 1 : NUM_ISLANDS) * sizeof(VReoIsland));
	o1islands = PR_WL__malloc((NUM_O1ISLANDS == 0 ? 1 : NUM_O1ISLANDS) * sizeof(VReoO1island));
	circuit = (VReoCircuit *) PR_WL__malloc(sizeof(VReoCircuit));

	//
	// INITIALIZE BRIDGES
	//

	/* Initialize bridge Broad_0. */
	bridge = &(bridges[CKT_BRIDGE_Broad_0]);
	bridge->buffer = NULL;
	bridge->bridgeIsFull = FALSE;
        bridge->writerType   = None;
        bridge->readerType   = None;
	bridge->waitingReaderVP = NULL;
	bridge->waitingWriterVP = NULL;
	bridge->readerPartnerQStruct = NULL;
	bridge->writerPartnerQStruct = NULL;

	/* Initialize bridge In_0. */
	bridge = &(bridges[CKT_BRIDGE_In_0]);
	bridge->buffer = NULL;
	bridge->bridgeIsFull = FALSE;
	bridge->waitingReaderVP = NULL;
	bridge->waitingWriterVP = NULL;
	bridge->readerPartnerQStruct = NULL;
	bridge->writerPartnerQStruct = NULL;

	/* Initialize bridge In_1. */
	bridge = &(bridges[CKT_BRIDGE_In_1]);
	bridge->buffer = NULL;
	bridge->bridgeIsFull = FALSE;
	bridge->waitingReaderVP = NULL;
	bridge->waitingWriterVP = NULL;
	bridge->readerPartnerQStruct = NULL;
	bridge->writerPartnerQStruct = NULL;

	/* Initialize bridge Out_0. */
	bridge = &(bridges[CKT_BRIDGE_Out_0]);
	bridge->buffer = NULL;
	bridge->bridgeIsFull = FALSE;
	bridge->waitingReaderVP = NULL;
	bridge->waitingWriterVP = NULL;
	bridge->readerPartnerQStruct = NULL;
	bridge->writerPartnerQStruct = NULL;

	/* Initialize bridge Out_1. */
	bridge = &(bridges[CKT_BRIDGE_Out_1]);
	bridge->buffer = NULL;
	bridge->bridgeIsFull = FALSE;
	bridge->waitingReaderVP = NULL;
	bridge->waitingWriterVP = NULL;
	bridge->readerPartnerQStruct = NULL;
	bridge->writerPartnerQStruct = NULL;

	/* Initialize bridge FIFO0. */
	bridge = &(bridges[CKT_BRIDGE_FIFO0]);
	bridge->buffer = NULL;
	bridge->bridgeIsFull = FALSE;
   bridge->waitingReaderVP = NULL;
	bridge->waitingWriterVP = NULL;
	bridge->readerPartnerQStruct = NULL;
	bridge->writerPartnerQStruct = NULL;

	/* Initialize bridge FIFO1. */
	bridge = &(bridges[CKT_BRIDGE_FIFO1]);
	bridge->buffer = malloc(1);
	bridge->bridgeIsFull = TRUE;
	bridge->waitingReaderVP = NULL;
	bridge->waitingWriterVP = NULL;
	bridge->readerPartnerQStruct = NULL;
	bridge->writerPartnerQStruct = NULL;

	/* Initialize bridge FIFO2. */
	bridge = &(bridges[CKT_BRIDGE_FIFO2]);
	bridge->buffer = NULL;
	bridge->bridgeIsFull = FALSE;
   bridge->waitingReaderVP = NULL;
	bridge->waitingWriterVP = NULL;
	bridge->readerPartnerQStruct = NULL;
	bridge->writerPartnerQStruct = NULL;

	/* Initialize bridge FIFO3. */
	bridge = &(bridges[CKT_BRIDGE_FIFO3]);
	bridge->buffer = malloc(1);
	bridge->bridgeIsFull = TRUE;
	bridge->waitingReaderVP = NULL;
	bridge->waitingWriterVP = NULL;
	bridge->readerPartnerQStruct = NULL;
	bridge->writerPartnerQStruct = NULL;

	/* Initialize boundary bridges. */
	boundaryBridges = PR_WL__malloc(NUM_BOUNDARY_BRIDGES * sizeof(VReoBridge*));
	boundaryBridges[0] = &(bridges[CKT_BRIDGE_Broad_0]);
	boundaryBridges[1] = &(bridges[CKT_BRIDGE_In_0]);
	boundaryBridges[2] = &(bridges[CKT_BRIDGE_In_1]);
	boundaryBridges[3] = &(bridges[CKT_BRIDGE_Out_0]);
	boundaryBridges[4] = &(bridges[CKT_BRIDGE_Out_1]);

	//
	// INITIALIZE ISLANDS
	//

	/* Initialize Island 0. */
	island = &(islands[CKT_I0]);

	island->numCheckerFns = 1;
	island->numBridges = 4;

	island->checkerFns = PR_WL__malloc(island->numCheckerFns * sizeof(VReoCheckerFn));
	island->checkerFns[0] = &Checker_0__I0;

	island->doerFns = PR_WL__malloc(island->numCheckerFns * sizeof(VReoDoerFn));
	island->doerFns[0] = &Doer_0__I0;

	island->bridges = PR_WL__malloc(island->numBridges * sizeof(VReoBridge *));
	island->bridges[I0_BRIDGE_Broad_0] = &(bridges[CKT_BRIDGE_Broad_0]);
	island->bridges[I0_BRIDGE_Broad_0Output1] = &(bridges[CKT_BRIDGE_Broad_0Output1]);
	island->bridges[I0_BRIDGE_Broad_0Output2] = &(bridges[CKT_BRIDGE_Broad_0Output2]);
	island->bridges[I0_BRIDGE_Out_1] = &(bridges[CKT_BRIDGE_Out_1]);

	/* 
	 * Initialize Island 0: register Island 0 as a reader on 
	 * bridge Broad_0. 
	 */
	bridgeReaderCheckerFns = PR_WL__malloc( NUM_I0_CHECKERS_INVOLVE_BRIDGE_Broad_0 * sizeof(VReoCheckerFn *) );
	bridgeReaderDoerFns = PR_WL__malloc( NUM_I0_CHECKERS_INVOLVE_BRIDGE_Broad_0 * sizeof(VReoDoerFn *) );
	bridgeReaderCheckerFns[0] = (VReoCheckerFn) &CHECKER3_I0;
	bridgeReaderDoerFns[0] = (VReoDoerFn) &DOER3_I0;

	bridge = &(bridges[CKT_BRIDGE_Broad_0]);
	bridge->reader = &(islands[CKT_I0]);
	bridge->readerType = Island;
	bridge->numReaderCheckerFns = NUM_I0_CHECKERS_INVOLVE_BRIDGE_Broad_0;
	bridge->readerCheckerFns = (VReoCheckerFn *) bridgeReaderCheckerFns;
	bridge->readerDoerFns = (VReoDoerFn *) bridgeReaderDoerFns;

	/* 
	 * Initialize Island 0: register Island 0 as a writer on 
	 * bridge Broad_0Output1.
	 */
	bridgeWriterCheckerFns = PR_WL__malloc( NUM_I0_CHECKERS_INVOLVE_BRIDGE_Broad_0Output1 * sizeof(VReoCheckerFn *) );
	bridgeWriterDoerFns = PR_WL__malloc( NUM_I0_CHECKERS_INVOLVE_BRIDGE_Broad_0Output1 * sizeof(VReoDoerFn *) );
	bridgeWriterCheckerFns[0] = (VReoCheckerFn) &CHECKER3_I0;
	bridgeWriterDoerFns[0] = (VReoDoerFn) &DOER3_I0;

	bridge = &(bridges[CKT_BRIDGE_Broad_0Output1]);
	bridge->writer = &(islands[CKT_I0]);
	bridge->writerType = Island;
	bridge->numWriterCheckerFns = NUM_I0_CHECKERS_INVOLVE_BRIDGE_Broad_0Output1;
	bridge->writerCheckerFns = (VReoCheckerFn *) bridgeWriterCheckerFns;
	bridge->writerDoerFns = (VReoDoerFn *) bridgeWriterDoerFns;

	/* 
	 * Initialize Island 0: register Island 0 as a writer on 
	 * bridge Broad_0Output2.
	 */
	bridgeWriterCheckerFns = PR_WL__malloc( NUM_I0_CHECKERS_INVOLVE_BRIDGE_Broad_0Output2 * sizeof(VReoCheckerFn *) );
	bridgeWriterDoerFns = PR_WL__malloc( NUM_I0_CHECKERS_INVOLVE_BRIDGE_Broad_0Output2 * sizeof(VReoDoerFn *) );
	bridgeWriterCheckerFns[0] = (VReoCheckerFn) &CHECKER3_I0;
	bridgeWriterDoerFns[0] = (VReoDoerFn) &DOER3_I0;

	bridge = &(bridges[CKT_BRIDGE_Broad_0Output2]);
	bridge->writer = &(islands[CKT_I0]);
	bridge->writerType = Island;
	bridge->numWriterCheckerFns = NUM_I0_CHECKERS_INVOLVE_BRIDGE_Broad_0Output2;
	bridge->writerCheckerFns = (VReoCheckerFn *) bridgeWriterCheckerFns;
	bridge->writerDoerFns = (VReoDoerFn *) bridgeWriterDoerFns;

	/* 
	 * Initialize Island 0: register Island 0 as a writer on 
	 * bridge Out_1.
	 */
	bridgeWriterCheckerFns = PR_WL__malloc( NUM_I0_CHECKERS_INVOLVE_BRIDGE_Out_1 * sizeof(VReoCheckerFn *) );
	bridgeWriterDoerFns = PR_WL__malloc( NUM_I0_CHECKERS_INVOLVE_BRIDGE_Out_1 * sizeof(VReoDoerFn *) );
	bridgeWriterCheckerFns[0] = (VReoCheckerFn) &CHECKER3_I0;
	bridgeWriterDoerFns[0] = (VReoDoerFn) &DOER3_I0;

	bridge = &(bridges[CKT_BRIDGE_Out_1]);
	bridge->writer = &(islands[CKT_I0]);
	bridge->writerType = Island;
	bridge->numWriterCheckerFns = NUM_I0_CHECKERS_INVOLVE_BRIDGE_Out_1;
	bridge->writerCheckerFns = (VReoCheckerFn *) bridgeWriterCheckerFns;
	bridge->writerDoerFns = (VReoDoerFn *) bridgeWriterDoerFns;

	/* Initialize Island 1. */
	island = &(islands[CKT_I1]);

	island->numCheckerFns = 1;
	island->numBridges = 3;

	island->checkerFns = PR_WL__malloc(island->numCheckerFns * sizeof(VReoCheckerFn));
	island->checkerFns[0] = &Checker_0__I1;

	island->doerFns = PR_WL__malloc(island->numCheckerFns * sizeof(VReoDoerFn));
	island->doerFns[0] = &Doer_0__I1;

	island->bridges = PR_WL__malloc(island->numBridges * sizeof(VReoBridge *));
	island->bridges[I1_BRIDGE_X_0Input0] = &(bridges[CKT_BRIDGE_X_0Input0]);
	island->bridges[I1_BRIDGE_In_0] = &(bridges[CKT_BRIDGE_In_0]);
	island->bridges[I1_BRIDGE_In_0Output1] = &(bridges[CKT_BRIDGE_In_0Output1]);

	/* 
	 * Initialize Island 1: register Island 1 as a reader on 
	 * bridge X_0Input0. 
	 */
	bridgeReaderCheckerFns = PR_WL__malloc( NUM_I1_CHECKERS_INVOLVE_BRIDGE_X_0Input0 * sizeof(VReoCheckerFn *) );
	bridgeReaderDoerFns = PR_WL__malloc( NUM_I1_CHECKERS_INVOLVE_BRIDGE_X_0Input0 * sizeof(VReoDoerFn *) );
	bridgeReaderCheckerFns[0] = (VReoCheckerFn) &CHECKER2_I1;
	bridgeReaderDoerFns[0] = (VReoDoerFn) &DOER2_I1;

	bridge = &(bridges[CKT_BRIDGE_X_0Input0]);
	bridge->reader = &(islands[CKT_I1]);
	bridge->readerType = Island;
	bridge->numReaderCheckerFns = NUM_I1_CHECKERS_INVOLVE_BRIDGE_X_0Input0;
	bridge->readerCheckerFns = (VReoCheckerFn *) bridgeReaderCheckerFns;
	bridge->readerDoerFns = (VReoDoerFn *) bridgeReaderDoerFns;

	/* 
	 * Initialize Island 1: register Island 1 as a reader on 
	 * bridge In_0. 
	 */
	bridgeReaderCheckerFns = PR_WL__malloc( NUM_I1_CHECKERS_INVOLVE_BRIDGE_In_0 * sizeof(VReoCheckerFn *) );
	bridgeReaderDoerFns = PR_WL__malloc( NUM_I1_CHECKERS_INVOLVE_BRIDGE_In_0 * sizeof(VReoDoerFn *) );
	bridgeReaderCheckerFns[0] = (VReoCheckerFn) &CHECKER2_I1;
	bridgeReaderDoerFns[0] = (VReoDoerFn) &DOER2_I1;

	bridge = &(bridges[CKT_BRIDGE_In_0]);
	bridge->reader = &(islands[CKT_I1]);
	bridge->readerType = Island;
	bridge->numReaderCheckerFns = NUM_I1_CHECKERS_INVOLVE_BRIDGE_In_0;
	bridge->readerCheckerFns = (VReoCheckerFn *) bridgeReaderCheckerFns;
	bridge->readerDoerFns = (VReoDoerFn *) bridgeReaderDoerFns;

	/* 
	 * Initialize Island 1: register Island 1 as a writer on 
	 * bridge In_0Output1.
	 */
	bridgeWriterCheckerFns = PR_WL__malloc( NUM_I1_CHECKERS_INVOLVE_BRIDGE_In_0Output1 * sizeof(VReoCheckerFn *) );
	bridgeWriterDoerFns = PR_WL__malloc( NUM_I1_CHECKERS_INVOLVE_BRIDGE_In_0Output1 * sizeof(VReoDoerFn *) );
	bridgeWriterCheckerFns[0] = (VReoCheckerFn) &CHECKER2_I1;
	bridgeWriterDoerFns[0] = (VReoDoerFn) &DOER2_I1;

	bridge = &(bridges[CKT_BRIDGE_In_0Output1]);
	bridge->writer = &(islands[CKT_I1]);
	bridge->writerType = Island;
	bridge->numWriterCheckerFns = NUM_I1_CHECKERS_INVOLVE_BRIDGE_In_0Output1;
	bridge->writerCheckerFns = (VReoCheckerFn *) bridgeWriterCheckerFns;
	bridge->writerDoerFns = (VReoDoerFn *) bridgeWriterDoerFns;

	/* Initialize Island 2. */
	island = &(islands[CKT_I2]);

	island->numCheckerFns = 1;
	island->numBridges = 3;

	island->checkerFns = PR_WL__malloc(island->numCheckerFns * sizeof(VReoCheckerFn));
	island->checkerFns[0] = &Checker_0__I2;

	island->doerFns = PR_WL__malloc(island->numCheckerFns * sizeof(VReoDoerFn));
	island->doerFns[0] = &Doer_0__I2;

	island->bridges = PR_WL__malloc(island->numBridges * sizeof(VReoBridge *));
	island->bridges[I2_BRIDGE_In_1] = &(bridges[CKT_BRIDGE_In_1]);
	island->bridges[I2_BRIDGE_X_1Input0] = &(bridges[CKT_BRIDGE_X_1Input0]);
	island->bridges[I2_BRIDGE_In_1Output0] = &(bridges[CKT_BRIDGE_In_1Output0]);

	/* 
	 * Initialize Island 2: register Island 2 as a reader on 
	 * bridge In_1. 
	 */
	bridgeReaderCheckerFns = PR_WL__malloc( NUM_I2_CHECKERS_INVOLVE_BRIDGE_In_1 * sizeof(VReoCheckerFn *) );
	bridgeReaderDoerFns = PR_WL__malloc( NUM_I2_CHECKERS_INVOLVE_BRIDGE_In_1 * sizeof(VReoDoerFn *) );
	bridgeReaderCheckerFns[0] = (VReoCheckerFn) &CHECKER3_I2;
	bridgeReaderDoerFns[0] = (VReoDoerFn) &DOER3_I2;

	bridge = &(bridges[CKT_BRIDGE_In_1]);
	bridge->reader = &(islands[CKT_I2]);
	bridge->readerType = Island;
	bridge->numReaderCheckerFns = NUM_I2_CHECKERS_INVOLVE_BRIDGE_In_1;
	bridge->readerCheckerFns = (VReoCheckerFn *) bridgeReaderCheckerFns;
	bridge->readerDoerFns = (VReoDoerFn *) bridgeReaderDoerFns;

	/* 
	 * Initialize Island 2: register Island 2 as a reader on 
	 * bridge X_1Input0. 
	 */
	bridgeReaderCheckerFns = PR_WL__malloc( NUM_I2_CHECKERS_INVOLVE_BRIDGE_X_1Input0 * sizeof(VReoCheckerFn *) );
	bridgeReaderDoerFns = PR_WL__malloc( NUM_I2_CHECKERS_INVOLVE_BRIDGE_X_1Input0 * sizeof(VReoDoerFn *) );
	bridgeReaderCheckerFns[0] = (VReoCheckerFn) &CHECKER3_I2;
	bridgeReaderDoerFns[0] = (VReoDoerFn) &DOER3_I2;

	bridge = &(bridges[CKT_BRIDGE_X_1Input0]);
	bridge->reader = &(islands[CKT_I2]);
	bridge->readerType = Island;
	bridge->numReaderCheckerFns = NUM_I2_CHECKERS_INVOLVE_BRIDGE_X_1Input0;
	bridge->readerCheckerFns = (VReoCheckerFn *) bridgeReaderCheckerFns;
	bridge->readerDoerFns = (VReoDoerFn *) bridgeReaderDoerFns;

	/* 
	 * Initialize Island 2: register Island 2 as a writer on 
	 * bridge In_1Output0.
	 */
	bridgeWriterCheckerFns = PR_WL__malloc( NUM_I2_CHECKERS_INVOLVE_BRIDGE_In_1Output0 * sizeof(VReoCheckerFn *) );
	bridgeWriterDoerFns = PR_WL__malloc( NUM_I2_CHECKERS_INVOLVE_BRIDGE_In_1Output0 * sizeof(VReoDoerFn *) );
	bridgeWriterCheckerFns[0] = (VReoCheckerFn) &CHECKER3_I2;
	bridgeWriterDoerFns[0] = (VReoDoerFn) &DOER3_I2;

	bridge = &(bridges[CKT_BRIDGE_In_1Output0]);
	bridge->writer = &(islands[CKT_I2]);
	bridge->writerType = Island;
	bridge->numWriterCheckerFns = NUM_I2_CHECKERS_INVOLVE_BRIDGE_In_1Output0;
	bridge->writerCheckerFns = (VReoCheckerFn *) bridgeWriterCheckerFns;
	bridge->writerDoerFns = (VReoDoerFn *) bridgeWriterDoerFns;

	/* Initialize O1Island 0. */
	o1island = &(o1islands[CKT_O1I0]);

	o1island->numBridges = 3;
	o1island->bridges = PR_WL__malloc(o1island->numBridges * sizeof(VReoBridge *));
	o1island->bridges[O1I0_BRIDGE_Out_0Input1] = &(bridges[CKT_BRIDGE_Out_0Input1]);
	o1island->bridges[O1I0_BRIDGE_Out_0Input0] = &(bridges[CKT_BRIDGE_Out_0Input0]);
	o1island->bridges[O1I0_BRIDGE_Out_0] = &(bridges[CKT_BRIDGE_Out_0]);

	/* 
	 * Initialize O1Island 0: create queues (queue 0 holds puts of input 
	 * bridges; queue 1 holds gets of the output bridge). 
	 */
	offerQ0 = makePrivQ();
	offerQ1 = makePrivQ();

	partnerQStruct0 = PR_WL__malloc( sizeof(VReoPartnerQStruct) );
	partnerQStruct0->numQs = 1;
	partnerQStruct0->partnerQs = PR_WL__malloc( partnerQStruct0->numQs * sizeof(PrivQueueStruc *) );
	partnerQStruct0->doerFns = PR_WL__malloc( partnerQStruct0->numQs * sizeof(VReoO1islandDoerFn) );
	partnerQStruct0->doerFns[0] = &o1islandReadBridgeToWrittenBridgeDoer;
	partnerQStruct0->partnerQs[0] = offerQ1;

	partnerQStruct1 = PR_WL__malloc( sizeof(VReoPartnerQStruct) );
	partnerQStruct1->numQs = 1;
	partnerQStruct1->partnerQs = PR_WL__malloc( partnerQStruct1->numQs * sizeof(PrivQueueStruc *) );
	partnerQStruct1->doerFns = PR_WL__malloc( partnerQStruct1->numQs * sizeof(VReoO1islandDoerFn) );
	partnerQStruct1->doerFns[0] = &o1islandReadBridgeToWrittenBridgeDoer;
	partnerQStruct1->partnerQs[0] = offerQ0;

	/* 
	 * Initialize O1Island 0: register O1Island 0 as a reader on 
	 * bridge Out_0Input1. 
	 */
	bridge = &(bridges[CKT_BRIDGE_Out_0Input1]);
	bridge->reader = &(o1island);
	bridge->readerType = O1island;
	bridge->readerPartnerQStruct = partnerQStruct0;
	bridge->readerOfferQ = offerQ0;

	/* 
	 * Initialize O1Island 0: register O1Island 0 as a reader on 
	 * bridge Out_0Input0. 
	 */
	bridge = &(bridges[CKT_BRIDGE_Out_0Input0]);
	bridge->reader = &(o1island);
	bridge->readerType = O1island;
	bridge->readerPartnerQStruct = partnerQStruct0;
	bridge->readerOfferQ = offerQ0;

	/* 
	 * Initialize O1Island 0: register O1Island 0 as the only 
	 * writer on bridge Out_0.
	 */
	bridge = &(bridges[CKT_BRIDGE_Out_0]);
	bridge->writer = &(o1island);
	bridge->writerType = O1island;
	bridge->writerPartnerQStruct = partnerQStruct1;
	bridge->writerOfferQ = offerQ1;

	//
	// INITIALIZE QUEUES
	//

	/* Assumption: (writerType != NULL) implies (writerType != VP) */
	bridge = &(bridges[CKT_BRIDGE_Out_0Input1]);
	if (bridge->writerType != None && bridge->bridgeIsFull)
		writePrivQ( bridge, bridge->readerOfferQ );

	/* Assumption: (writerType != NULL) implies (writerType != VP) */
	bridge = &(bridges[CKT_BRIDGE_Out_0Input0]);
	if (bridge->writerType != None && bridge->bridgeIsFull)
		writePrivQ( bridge, bridge->readerOfferQ );

	/* Assumption: (readerType != NULL) implies (readerType != VP) */
	bridge = &(bridges[CKT_BRIDGE_Out_0]);
	if (bridge->readerType != None && !bridge->bridgeIsFull)
		writePrivQ( bridge, bridge->writerOfferQ );

	//
	// INITIALIZE CIRCUIT
	//

	/* Initialize circuit. */
	circuit->numIslands = NUM_ISLANDS;
	circuit->numO1islands = NUM_O1ISLANDS;
	circuit->numBridges = NUM_BRIDGES;
	circuit->islands = islands;
	circuit->o1islands = o1islands;
	circuit->bridges = bridges;
	circuit->boundaryBridges = boundaryBridges;
	circuit->VPs = NULL;

	/* Return. */
	return (circuit);
}

void create_VPs_w_init_and_connect( VReoCircuit *circuit, void **initDatums,
                                    SlaveVP *animVP) 
 {
	/* Declare variables. */
	VReoBridge **boundaryBridges, *bridges, **bridgesForVP;
	SlaveVP **VPs;

	VPParams *prodParams;
	VPParams *consParams;

	/* Initialize (boundary) bridges. */
	boundaryBridges = circuit->boundaryBridges;
	bridges = circuit->bridges;

	/* Allocate memory for VPs. */
	VPs = PR_WL__malloc(NUM_VPs * sizeof(SlaveVP *));

	/* Create Producer VP 0. */
	bridgesForVP = PR_WL__malloc(1 * sizeof(VReoBridge *));
	bridgesForVP[0] = boundaryBridges[CKT_VP_PROD0];

	prodParams = PR_WL__malloc(sizeof(MatrixMultWorkUnit));
	prodParams->inBridges = NULL;
	prodParams->outBridges = bridgesForVP;
        prodParams->initData  = initDatums[CKT_VP_PROD0];

	VPs[CKT_VP_PROD0] = VReo__create_VP(&producer_Fn, prodParams, circuit, animVP);

	boundaryBridges[CKT_VP_PROD0]->writer = VPs[CKT_VP_PROD0];
	boundaryBridges[CKT_VP_PROD0]->writerType = VP;

	/* Create Producer VP 1. */
	bridgesForVP = PR_WL__malloc(1 * sizeof(VReoBridge *));
	bridgesForVP[0] = boundaryBridges[CKT_VP_PROD1];

	prodParams = PR_WL__malloc(sizeof(MatrixMultWorkUnit));
	prodParams->inBridges = NULL;
	prodParams->outBridges = bridgesForVP;
   prodParams->initData  = initDatums[CKT_VP_PROD1];

	VPs[CKT_VP_PROD1] = VReo__create_VP(&producer_Fn, prodParams, circuit, animVP);

	boundaryBridges[CKT_VP_PROD1]->writer = VPs[CKT_VP_PROD1];
	boundaryBridges[CKT_VP_PROD1]->writerType = VP;

	/* Create Producer VP 2. */
	bridgesForVP = PR_WL__malloc(1 * sizeof(VReoBridge *));
	bridgesForVP[0] = boundaryBridges[CKT_VP_PROD2];

	prodParams = PR_WL__malloc(sizeof(MatrixMultWorkUnit));
	prodParams->inBridges = NULL;
	prodParams->outBridges = bridgesForVP;
   prodParams->initData  = initDatums[CKT_VP_PROD2];

	VPs[CKT_VP_PROD2] = VReo__create_VP(&producer_Fn, prodParams, circuit, animVP);

	boundaryBridges[CKT_VP_PROD2]->writer = VPs[CKT_VP_PROD2];
	boundaryBridges[CKT_VP_PROD2]->writerType = VP;

//	/* Create Consumer VP 0. */
//	consParams = PR_WL__malloc(sizeof(TestAppConsumerParams));
//	
//	//bridgesForVP = PR_WL__malloc(1 * sizeof(VReoBridge *));
//	//bridgesForVP[0] = boundaryBridges[CKT_VP_CONS0];
//	
//	bridgesForVP = PR_WL__malloc(2 * sizeof(VReoBridge *));
//	bridgesForVP[0] = bridges[CKT_BRIDGE_Out_0];
//	bridgesForVP[0] = bridges[CKT_BRIDGE_Out_1];
//	
//	consParams->inBridges = bridgesForVP;
//	consParams->outBridges = NULL;
//	
//	VPs[CKT_VP_CONS0] = VReo__create_VP(&consumer_Fn, consParams, circuit, animVP);
//	boundaryBridges[CKT_VP_CONS0]->reader = VPs[CKT_VP_CONS0];
//	boundaryBridges[CKT_VP_CONS0]->readerType = VP;

//	/* Create Consumer VP 1. */
//	consParams = PR_WL__malloc(sizeof(TestAppConsumerParams));
//	
//	//bridgesForVP = PR_WL__malloc(1 * sizeof(VReoBridge *));
//	//bridgesForVP[0] = boundaryBridges[CKT_VP_CONS1];
//	
//	bridgesForVP = PR_WL__malloc(2 * sizeof(VReoBridge *));
//	bridgesForVP[0] = bridges[CKT_BRIDGE_Out_0];
//	bridgesForVP[0] = bridges[CKT_BRIDGE_Out_1];
//	
//	consParams->inBridges = bridgesForVP;
//	consParams->outBridges = NULL;
//	
//	VPs[CKT_VP_CONS1] = VReo__create_VP(&consumer_Fn, consParams, circuit, animVP);
//	boundaryBridges[CKT_VP_CONS1]->reader = VPs[CKT_VP_CONS1];
//	boundaryBridges[CKT_VP_CONS1]->readerType = VP;

	/* Create Consumer VP. */
	consParams = PR_WL__malloc(sizeof(VPParams));

	bridgesForVP = PR_WL__malloc(2 * sizeof(VReoBridge *));
	bridgesForVP[0] = &(bridges[CKT_BRIDGE_Out_0]);
	bridgesForVP[1] = &(bridges[CKT_BRIDGE_Out_1]);

	consParams->inBridges  = bridgesForVP;
	consParams->outBridges = NULL;
   consParams->initData   = initDatums[CKT_VP_CONS0];

	VPs[CKT_VP_CONS0] = VReo__create_VP(&consumer_Fn, consParams, circuit, animVP);

	bridges[CKT_BRIDGE_Out_0].reader = VPs[CKT_VP_CONS0];
	bridges[CKT_BRIDGE_Out_1].reader = VPs[CKT_VP_CONS0];
	bridges[CKT_BRIDGE_Out_0].readerType = VP;
	bridges[CKT_BRIDGE_Out_1].readerType = VP;

	/* Start circuit. */
	VReo__start_circuit(circuit, animVP);
}

//==============================================================================

/* Checkers for Island 0. */

bool32 Checker_0__I0( VReoIsland *island ) {
	VReoBridge *bridgeBroad_0Output1, *bridgeBroad_0Output2, *bridgeOut_1, *bridgeBroad_0;
	bool32 satisfied;

	bridgeBroad_0Output1 = (island->bridges)[I0_BRIDGE_Broad_0Output1];
	bridgeBroad_0Output2 = (island->bridges)[I0_BRIDGE_Broad_0Output2];
	bridgeOut_1 = (island->bridges)[I0_BRIDGE_Out_1];
	bridgeBroad_0 = (island->bridges)[I0_BRIDGE_Broad_0];
	satisfied = READY_FOR_READ_BRIDGE_Broad_0 && READY_FOR_WRITE_BRIDGE_Broad_0Output1 && READY_FOR_WRITE_BRIDGE_Broad_0Output2 && READY_FOR_WRITE_BRIDGE_Out_1;
	return satisfied;
}

/* Checkers for Island 1. */

bool32 Checker_0__I1( VReoIsland *island ) {
	VReoBridge *bridgeX_0Input0, *bridgeIn_0, *bridgeIn_0Output1;
	bool32 satisfied;

	bridgeX_0Input0 = (island->bridges)[I1_BRIDGE_X_0Input0];
	bridgeIn_0 = (island->bridges)[I1_BRIDGE_In_0];
	bridgeIn_0Output1 = (island->bridges)[I1_BRIDGE_In_0Output1];
	satisfied = READY_FOR_READ_BRIDGE_X_0Input0 && READY_FOR_READ_BRIDGE_In_0 && READY_FOR_WRITE_BRIDGE_In_0Output1;
	return satisfied;
}

/* Checkers for Island 2. */

bool32 Checker_0__I2( VReoIsland *island ) {
	VReoBridge *bridgeIn_1Output0, *bridgeIn_1, *bridgeX_1Input0;
	bool32 satisfied;

	bridgeIn_1Output0 = (island->bridges)[I2_BRIDGE_In_1Output0];
	bridgeIn_1 = (island->bridges)[I2_BRIDGE_In_1];
	bridgeX_1Input0 = (island->bridges)[I2_BRIDGE_X_1Input0];
	satisfied = READY_FOR_READ_BRIDGE_In_1 && READY_FOR_READ_BRIDGE_X_1Input0 && READY_FOR_WRITE_BRIDGE_In_1Output0;
	return satisfied;
}

//==============================================================================

/* Declaration of auxiliary doers. */

void Auxdoer_for_bridge_Broad_0( VReoBridge *bridge );
void Auxdoer_for_bridge_In_0( VReoBridge *bridge );
void Auxdoer_for_bridge_In_1( VReoBridge *bridge );
void Auxdoer_for_bridge_Out_0( VReoBridge *bridge );
void Auxdoer_for_bridge_Out_1( VReoBridge *bridge );
void Auxdoer_for_bridge_In_0Output1( VReoBridge *bridge );
void Auxdoer_for_bridge_Out_0Input1( VReoBridge *bridge );

void Auxdoer_for_bridge_Broad_0Output1( VReoBridge *bridge );
void Auxdoer_for_bridge_X_0Input0( VReoBridge *bridge );

void Auxdoer_for_bridge_In_1Output0( VReoBridge *bridge );
void Auxdoer_for_bridge_Out_0Input0( VReoBridge *bridge );

void Auxdoer_for_bridge_Broad_0Output2( VReoBridge *bridge );
void Auxdoer_for_bridge_X_1Input0( VReoBridge *bridge );

/* Doers for Island 0. */

void Doer_0__I0( VReoIsland *island ) {
	VReoBridge *bridgeBroad_0Output1, *bridgeBroad_0Output2, *bridgeOut_1, *bridgeBroad_0;

	/* Initialize bridges. */
	bridgeBroad_0Output1 = (island->bridges)[I0_BRIDGE_Broad_0Output1];
	bridgeBroad_0Output2 = (island->bridges)[I0_BRIDGE_Broad_0Output2];
	bridgeOut_1 = (island->bridges)[I0_BRIDGE_Out_1];
	bridgeBroad_0 = (island->bridges)[I0_BRIDGE_Broad_0];

	/* Distribute data. */
	bridgeBroad_0Output1->buffer = bridgeBroad_0->buffer;
	bridgeBroad_0Output2->buffer = bridgeBroad_0->buffer;
	bridgeOut_1->buffer = bridgeBroad_0->buffer;

	/* Update bridge status. */
	bridgeBroad_0->bridgeIsFull = FALSE;
	bridgeBroad_0Output1->bridgeIsFull = TRUE;
	bridgeBroad_0Output2->bridgeIsFull = TRUE;
	bridgeOut_1->bridgeIsFull = TRUE;

	/* Prepare reader VPs. */
	PR_PI__make_slave_ready_for_lang(bridgeOut_1->waitingReaderVP, VReo_MAGIC_NUMBER);
	bridgeOut_1->waitingReaderVP->dataRetFromReq = bridgeOut_1->buffer;
	bridgeOut_1->waitingReaderVP = NULL;
	bridgeOut_1->bridgeIsFull = FALSE;

	/* Prepare writer VPs. */
	PR_PI__make_slave_ready_for_lang(bridgeBroad_0->waitingWriterVP, VReo_MAGIC_NUMBER);
	bridgeBroad_0->waitingWriterVP = NULL;

	/* Call auxiliary doers to complete this transition. */
	Auxdoer_for_bridge_Broad_0Output1(bridgeBroad_0Output1);
	Auxdoer_for_bridge_Broad_0Output2(bridgeBroad_0Output2);
	Auxdoer_for_bridge_Out_1(bridgeOut_1);
	Auxdoer_for_bridge_Broad_0(bridgeBroad_0);
}

/* Doers for Island 1. */

void Doer_0__I1( VReoIsland *island ) {
	VReoBridge *bridgeX_0Input0, *bridgeIn_0, *bridgeIn_0Output1;

	/* Initialize bridges. */
	bridgeX_0Input0 = (island->bridges)[I1_BRIDGE_X_0Input0];
	bridgeIn_0 = (island->bridges)[I1_BRIDGE_In_0];
	bridgeIn_0Output1 = (island->bridges)[I1_BRIDGE_In_0Output1];

	/* Distribute data. */
	bridgeIn_0Output1->buffer = bridgeIn_0->buffer;

	/* Update bridge status. */
	bridgeX_0Input0->bridgeIsFull = FALSE;
	bridgeIn_0->bridgeIsFull = FALSE;
	bridgeIn_0Output1->bridgeIsFull = TRUE;

	/* Prepare reader VPs. */

	/* Prepare writer VPs. */
	PR_PI__make_slave_ready_for_lang(bridgeIn_0->waitingWriterVP, VReo_MAGIC_NUMBER);
	bridgeIn_0->waitingWriterVP = NULL;

	/* Call auxiliary doers to complete this transition. */
	Auxdoer_for_bridge_X_0Input0(bridgeX_0Input0);
	Auxdoer_for_bridge_In_0(bridgeIn_0);
	Auxdoer_for_bridge_In_0Output1(bridgeIn_0Output1);
}

/* Doers for Island 2. */

void Doer_0__I2( VReoIsland *island ) {
	VReoBridge *bridgeIn_1Output0, *bridgeIn_1, *bridgeX_1Input0;

	/* Initialize bridges. */
	bridgeIn_1Output0 = (island->bridges)[I2_BRIDGE_In_1Output0];
	bridgeIn_1 = (island->bridges)[I2_BRIDGE_In_1];
	bridgeX_1Input0 = (island->bridges)[I2_BRIDGE_X_1Input0];

	/* Distribute data. */
	bridgeIn_1Output0->buffer = bridgeIn_1->buffer;

	/* Update bridge status. */
	bridgeIn_1->bridgeIsFull = FALSE;
	bridgeX_1Input0->bridgeIsFull = FALSE;
	bridgeIn_1Output0->bridgeIsFull = TRUE;

	/* Prepare reader VPs. */

	/* Prepare writer VPs. */
	PR_PI__make_slave_ready_for_lang(bridgeIn_1->waitingWriterVP, VReo_MAGIC_NUMBER);
	bridgeIn_1->waitingWriterVP = NULL;

	/* Call auxiliary doers to complete this transition. */
	Auxdoer_for_bridge_In_1Output0(bridgeIn_1Output0);
	Auxdoer_for_bridge_In_1(bridgeIn_1);
	Auxdoer_for_bridge_X_1Input0(bridgeX_1Input0);
}

//==============================================================================

/* Auxiliary doers for input bridges. */

void Auxdoer_for_bridge_Broad_0( VReoBridge *bridge ) {
	;
}

void Auxdoer_for_bridge_In_0( VReoBridge *bridge ) {
	;
}

void Auxdoer_for_bridge_In_1( VReoBridge *bridge ) {
	;
}

/* Auxiliary doers for output bridges. */

void Auxdoer_for_bridge_Out_0( VReoBridge *bridge ) {
	;
}

void Auxdoer_for_bridge_Out_1( VReoBridge *bridge ) {
	;
}

/* Auxiliary doers for FIFO bridges. */

void Auxdoer_for_bridge_In_0Output1( VReoBridge *bridge ) {
	int32 numCheckerFns;
	VReoIsland *islandOnOtherSide;
	VReoCheckerFn *checkerFns;
	VReoDoerFn *doerFns;

	VReoO1island *o1islandOnOtherSide;
	VReoPartnerQStruct *partnerQstruct;

	if (bridge->readerType == Island) {
		islandOnOtherSide = (VReoIsland*) bridge->reader;
		numCheckerFns = bridge->numReaderCheckerFns;
		checkerFns = bridge->readerCheckerFns;
		doerFns = bridge->readerDoerFns;

		VReo__check_an_island( islandOnOtherSide, numCheckerFns, checkerFns, doerFns );
    }

    else if (bridge->readerType == O1island) { 
    	o1islandOnOtherSide = (VReoO1island *)bridge->reader;
    	partnerQstruct =  bridge->readerPartnerQStruct;

    	VReo__check_an_o1island_that_reads_bridge( o1islandOnOtherSide, bridge, partnerQstruct );
    }
}
void Auxdoer_for_bridge_Out_0Input1( VReoBridge *bridge ) {
	int32 numCheckerFns;
	VReoIsland *islandOnOtherSide;
	VReoCheckerFn *checkerFns;
	VReoDoerFn *doerFns;

	VReoO1island *o1islandOnOtherSide;
	VReoPartnerQStruct *partnerQstruct;

	if (bridge->writerType == Island) {
		islandOnOtherSide = (VReoIsland*) bridge->writer;
		numCheckerFns = bridge->numWriterCheckerFns;
		checkerFns = bridge->writerCheckerFns;
		doerFns = bridge->writerDoerFns;

		VReo__check_an_island( islandOnOtherSide, numCheckerFns, checkerFns, doerFns );
    }

	else if (bridge->writerType == O1island) { 
		o1islandOnOtherSide = (VReoO1island *)bridge->writer;
		partnerQstruct = bridge->writerPartnerQStruct;

		VReo__check_an_o1island_that_writes_bridge( o1islandOnOtherSide, bridge, partnerQstruct );
    }
}

void Auxdoer_for_bridge_Broad_0Output1( VReoBridge *bridge ) {
	int32 numCheckerFns;
	VReoIsland *islandOnOtherSide;
	VReoCheckerFn *checkerFns;
	VReoDoerFn *doerFns;

	VReoO1island *o1islandOnOtherSide;
	VReoPartnerQStruct *partnerQstruct;

	if (bridge->readerType == Island) {
		islandOnOtherSide = (VReoIsland*) bridge->reader;
		numCheckerFns = bridge->numReaderCheckerFns;
		checkerFns = bridge->readerCheckerFns;
		doerFns = bridge->readerDoerFns;

		VReo__check_an_island( islandOnOtherSide, numCheckerFns, checkerFns, doerFns );
    }

    else if (bridge->readerType == O1island) { 
    	o1islandOnOtherSide = (VReoO1island *)bridge->reader;
    	partnerQstruct =  bridge->readerPartnerQStruct;

    	VReo__check_an_o1island_that_reads_bridge( o1islandOnOtherSide, bridge, partnerQstruct );
    }
}
void Auxdoer_for_bridge_X_0Input0( VReoBridge *bridge ) {
	int32 numCheckerFns;
	VReoIsland *islandOnOtherSide;
	VReoCheckerFn *checkerFns;
	VReoDoerFn *doerFns;

	VReoO1island *o1islandOnOtherSide;
	VReoPartnerQStruct *partnerQstruct;

	if (bridge->writerType == Island) {
		islandOnOtherSide = (VReoIsland*) bridge->writer;
		numCheckerFns = bridge->numWriterCheckerFns;
		checkerFns = bridge->writerCheckerFns;
		doerFns = bridge->writerDoerFns;

		VReo__check_an_island( islandOnOtherSide, numCheckerFns, checkerFns, doerFns );
    }

	else if (bridge->writerType == O1island) { 
		o1islandOnOtherSide = (VReoO1island *)bridge->writer;
		partnerQstruct = bridge->writerPartnerQStruct;

		VReo__check_an_o1island_that_writes_bridge( o1islandOnOtherSide, bridge, partnerQstruct );
    }
}

void Auxdoer_for_bridge_In_1Output0( VReoBridge *bridge ) {
	int32 numCheckerFns;
	VReoIsland *islandOnOtherSide;
	VReoCheckerFn *checkerFns;
	VReoDoerFn *doerFns;

	VReoO1island *o1islandOnOtherSide;
	VReoPartnerQStruct *partnerQstruct;

	if (bridge->readerType == Island) {
		islandOnOtherSide = (VReoIsland*) bridge->reader;
		numCheckerFns = bridge->numReaderCheckerFns;
		checkerFns = bridge->readerCheckerFns;
		doerFns = bridge->readerDoerFns;

		VReo__check_an_island( islandOnOtherSide, numCheckerFns, checkerFns, doerFns );
    }

    else if (bridge->readerType == O1island) { 
    	o1islandOnOtherSide = (VReoO1island *)bridge->reader;
    	partnerQstruct =  bridge->readerPartnerQStruct;

    	VReo__check_an_o1island_that_reads_bridge( o1islandOnOtherSide, bridge, partnerQstruct );
    }
}
void Auxdoer_for_bridge_Out_0Input0( VReoBridge *bridge ) {
	int32 numCheckerFns;
	VReoIsland *islandOnOtherSide;
	VReoCheckerFn *checkerFns;
	VReoDoerFn *doerFns;

	VReoO1island *o1islandOnOtherSide;
	VReoPartnerQStruct *partnerQstruct;

	if (bridge->writerType == Island) {
		islandOnOtherSide = (VReoIsland*) bridge->writer;
		numCheckerFns = bridge->numWriterCheckerFns;
		checkerFns = bridge->writerCheckerFns;
		doerFns = bridge->writerDoerFns;

		VReo__check_an_island( islandOnOtherSide, numCheckerFns, checkerFns, doerFns );
    }

	else if (bridge->writerType == O1island) { 
		o1islandOnOtherSide = (VReoO1island *)bridge->writer;
		partnerQstruct = bridge->writerPartnerQStruct;

		VReo__check_an_o1island_that_writes_bridge( o1islandOnOtherSide, bridge, partnerQstruct );
    }
}

void Auxdoer_for_bridge_Broad_0Output2( VReoBridge *bridge ) {
	int32 numCheckerFns;
	VReoIsland *islandOnOtherSide;
	VReoCheckerFn *checkerFns;
	VReoDoerFn *doerFns;

	VReoO1island *o1islandOnOtherSide;
	VReoPartnerQStruct *partnerQstruct;

	if (bridge->readerType == Island) {
		islandOnOtherSide = (VReoIsland*) bridge->reader;
		numCheckerFns = bridge->numReaderCheckerFns;
		checkerFns = bridge->readerCheckerFns;
		doerFns = bridge->readerDoerFns;

		VReo__check_an_island( islandOnOtherSide, numCheckerFns, checkerFns, doerFns );
    }

    else if (bridge->readerType == O1island) { 
    	o1islandOnOtherSide = (VReoO1island *)bridge->reader;
    	partnerQstruct =  bridge->readerPartnerQStruct;

    	VReo__check_an_o1island_that_reads_bridge( o1islandOnOtherSide, bridge, partnerQstruct );
    }
}
void Auxdoer_for_bridge_X_1Input0( VReoBridge *bridge ) {
	int32 numCheckerFns;
	VReoIsland *islandOnOtherSide;
	VReoCheckerFn *checkerFns;
	VReoDoerFn *doerFns;

	VReoO1island *o1islandOnOtherSide;
	VReoPartnerQStruct *partnerQstruct;

	if (bridge->writerType == Island) {
		islandOnOtherSide = (VReoIsland*) bridge->writer;
		numCheckerFns = bridge->numWriterCheckerFns;
		checkerFns = bridge->writerCheckerFns;
		doerFns = bridge->writerDoerFns;

		VReo__check_an_island( islandOnOtherSide, numCheckerFns, checkerFns, doerFns );
    }

	else if (bridge->writerType == O1island) { 
		o1islandOnOtherSide = (VReoO1island *)bridge->writer;
		partnerQstruct = bridge->writerPartnerQStruct;

		VReo__check_an_o1island_that_writes_bridge( o1islandOnOtherSide, bridge, partnerQstruct );
    }
}