/* CoreTest.c
	*/
	
#include "stdio.h"

#include "CoreBasics.h"
#include "Core.h"
#include "CoreFlat.h"
#include "Rosemary.h"
#include "RosemaryUser.h"
	
/* Inverter Creation */
	
	CellType CreateInverter()
		{
		CellType cellType=nil;
		Wire In=CreateWire(nil, "In", nil);
		Wire Out=CreateWire(nil, "Out", nil);
		Wire Gnd=CreateWire(nil, "Gnd", nil);
		Wire Vdd=CreateWire(nil, "Vdd", nil);
		List nTransActuals=ListCons(ListCons(ListCons(nil, Gnd), Out), In);
		List pTransActuals=ListCons(ListCons(ListCons(ListCons(nil, Vdd), Vdd), Out), In);
		List publicWires=ListCons(ListCons(ListCons(ListCons(nil, Vdd), Gnd), Out), In);
		List cellInstances=nil;
		cellInstances=ListCons(cellInstances, CreateCellInstance(CreateWire(pTransActuals, nil, nil), CreateTransistor(pE, -1, -1, nil, nil), nil, nil));
		cellInstances=ListCons(cellInstances, CreateCellInstance(CreateWire(nTransActuals, nil, nil), CreateTransistor(nE, -1, -1, nil, nil), nil, nil));
		cellType=CreateRecordCell(CreateWire(publicWires, nil, nil), CreateWire(publicWires, nil, nil), cellInstances, "Inverter", nil, false);
		return(cellType);
		};
		
	CellType Create2Inverter()
		{
		CellType cellType=nil;
		Wire In=CreateWire(nil, "In", nil);
		Wire Out=CreateWire(nil, "Out", nil);
		Wire Gnd=CreateWire(nil, "Gnd", nil);
		Wire Vdd=CreateWire(nil, "Vdd", nil);
		Wire Intern=CreateWire(nil, "Intern", nil);
		List publicWires=ListCons(ListCons(ListCons(ListCons(nil, Vdd), Gnd), Out), In);
		List internalWires=ListCons(ListCons(ListCons(ListCons(ListCons(nil, Intern), Vdd), Gnd), Out), In);
		List firstActual=ListCons(ListCons(ListCons(ListCons(nil, Vdd), Gnd), Intern), In);
		List secondActual=ListCons(ListCons(ListCons(ListCons(nil, Vdd), Gnd), Out), Intern);
		CellType inverter=CreateInverter();
		List cellInstances=nil;
		cellInstances=ListCons(cellInstances, CreateCellInstance(CreateWire(firstActual, nil, nil), inverter, nil, nil));
		cellInstances=ListCons(cellInstances, CreateCellInstance(CreateWire(secondActual, nil, nil), inverter, nil, nil));
		cellType=CreateRecordCell(CreateWire(publicWires, nil, nil), CreateWire(internalWires, nil, nil), cellInstances, "Inverter2", nil, false);
		return(cellType);
		};
		
/* Flatten */
	
	void TestFlattenCell(cell, target, flatCell, instance, index, parent, flatParent, data, bindings)
		CellType cell;
		FlatCellTypeRec target;
		FlatCellTypeRec flatCell;
		CellInstance instance;
		Nat index;
		CellType parent;
		FlatCellTypeRec flatParent;
		Ref data;
		HashTable bindings;
		{
		if (cell->class==transistorCellClass) printf("\nTransistor");
		else if (cell->class==recordCellClass) {
			printf("\nRecord");
			NextBoundCellType(cell, target, flatCell, instance, index, parent, flatParent, data, bindings, TestFlattenCell);
			}
		else NextBoundCellType(cell, target, flatCell, instance, index, parent, flatParent, data, bindings, TestFlattenCell);
		};
		
/* Test */
	
	main()
		{
		Property p;
		Wire w;
		String n;
		Atom someProp;
		CellType cell;
		CellType recordCell;
		CellType inverter;
		CellType inverter2;
		List cellInstances=nil;
		Wire public;
		Wire actual;
		HashTable table;
		RoseSimulation simulation;
		RoseProbe In, Out;
		printf("\nStarting Core test\n");
		table=HashTableCreate(17, nil, nil);
		HashTablePut(table, nil, nil);
		CoreInitialize();
		CoreFlatInitialize();
		someProp=PropertyRegister("someProp", PropertyPrintString);
		p=nil;
		p=PropertyPut(p, someProp, "someName");
		n=(String)PropertyGet(p, someProp);
		printf("Some property: %s\n", n);
		w=CreateWires(1, "parentWireName", nil);
		w->elements[0]=CreateWires(0, "subWireName", nil);
		PrintWire(w, 0, 2);
		cell=CreateCellType(nil, w, nil, "CellName", nil);
		PrintCellType(cell, 0, 2);
		public=CopyWire(w);
		actual=CopyWire(w);
		public->elements[0]=actual->elements[0];
		cellInstances=ListCons(cellInstances, CreateCellInstance(actual, cell, nil, nil));
		recordCell=CreateRecordCell(public, public, cellInstances, "recordCellName", nil, false);
		PrintCellType(recordCell, 0, 2);
		inverter=CreateInverter();
		PrintCellType(inverter, 0, 2);
		inverter2=Create2Inverter();
		PrintCellType(inverter2, 0, 2);
		TestFlattenCell(inverter2, allFlatCells, rootCellType, nil, NatLast, nil, rootCellType, nil, nil);
		printf("\nFinished Core test\n");
		printf("\nStarting Rosemary test\n");
		RoseInitialize();
		RoseSetNamedFixedWire(inverter2, "Vdd", H);
		RoseSetNamedFixedWire(inverter2, "Gnd", L);
		simulation=RoseInstantiate(inverter2);
		In=RoseBindProbe(simulation, inverter2, "In", rootCellType);
		Out=RoseBindProbe(simulation, inverter2, "Out", rootCellType);
		RosePL(In, H, RoseForce);
		RoseSettle(simulation);
		if (RoseGL(Out)!=H) {
			printf("\nOut failed to go high");
			RoseExploreDesign(simulation);
			};
		RosePL(In, L, RoseForce);
		RoseSettle(simulation);
		if (RoseGL(Out)!=L) {
			printf("\nOut failed to go low");
			RoseExploreDesign(simulation);
			};
		printf("\nFinished Rosemary test\n");
		};