/* Core.c
*/
#include "stdio.h"
#include "CoreBasics.h"
#include "Core.h"
/* Miscellaneous */
String Index(name, index)
String name;
Nat index;
{
String indexString=StringFromNat(index);
StringCat(StringCat(StringCat(name, "["), indexString), "]");
return(indexString);
};
/* Wire */
Ref GetWireProp(wire, prop)
Wire wire;
Atom prop;
{
return(PropertyGet(wire->properties, prop));
};
void PutWireProp(wire, prop, value)
Wire wire;
Atom prop;
Ref value;
{
wire->properties=PropertyPut(wire->properties, prop, value);
};
Atom nameProp;
String GetShortWireName(wire)
Wire wire;
{
return(GetWireProp(wire, nameProp));
};
void SetShortWireName(wire, name)
Wire wire;
String name;
{
PutWireProp(wire, nameProp, name);
};
Nat CountBits(wire, visitTab)
Wire wire;
HashTable visitTab;
{
Nat bits=0;
Nat i;
if (HashTableGet(visitTab, wire)!=nil) return(0);
HashTablePut(visitTab, wire, true);
if (wire->size==0) return(1);
for (i=0; i<wire->size; i++) bits+=CountBits(wire->elements[i], visitTab);
return(bits);
};
Nat WireBits(wire)
Wire wire;
{
HashTable visitTab=HashTableCreate(17, nil, nil);
Nat bits=CountBits(wire, visitTab);
HashTableFree(visitTab);
return(bits);
};
void SetName(wire, name, wireToNames, nameToWire)
Wire wire;
String name;
HashTable wireToNames;
HashTable nameToWire;
{
ListOfString names=(ListOfString)HashTableGet(wireToNames, wire);
Wire previousWire=(Wire)HashTableGet(nameToWire, name);
Nat i;
if (name!=nil && !ListMemberString(names, name)) {
names=(ListOfString)ListCons(names, name);
HashTablePut(wireToNames, wire, names);
};
if (name!=nil && HashTableGet(nameToWire, name)!=nil && previousWire!=wire) {
printf("The name, %s, is applied to two different wires", name);
Die;
};
HashTablePut(nameToWire, name, wire);
for (i=0; i<wire->size; i++) {
String shortName=GetShortWireName(wire->elements[i]);
String subName=nil;
if (shortName==nil) subName=Index(name, i);
else if (name==nil) subName=shortName;
else subName=StringCat(name, StringCat(".", shortName));
SetName(wire->elements[i], subName, wireToNames, nameToWire);
};
};
Atom wireToNamesCacheProp;
Atom nameToWireCacheProp;
void FillFullWireNameCaches(root)
WireSeq root;
{
Nat rootSize=WireBits(root);
HashTable wireToNames=HashTableCreate(rootSize, nil, nil);
HashTable nameToWire=HashTableCreate(rootSize, HashTableHashString, StringEqual);
/* SetName has GetShortWireName[wire] instead of NIL to make full names also work for wires in their own context. */
SetName(root, GetShortWireName(root), wireToNames, nameToWire);
PutWireProp(root, wireToNamesCacheProp, wireToNames);
PutWireProp(root, nameToWireCacheProp, nameToWire);
};
ListOfString GetFullWireNames(root, wire)
WireSeq root;
Wire wire;
{
ListOfString names=nil;
HashTable wireToNames=(HashTable)GetWireProp(root, wireToNamesCacheProp);
if (wireToNames==nil) {
FillFullWireNameCaches(root);
wireToNames=(HashTable)GetWireProp(root, wireToNamesCacheProp);
if (wireToNames==nil) Die;
};
names=(ListOfString)HashTableGet(wireToNames, wire);
if (names==nil) Die;
return(names);
};
String GetFullWireName(root, wire)
WireSeq root;
Wire wire;
{
String name=nil;
ListOfString names=GetFullWireNames(root, wire);
while (names!=nil) {
if (name==nil || (name[0]=='[' && names->first[0]!='[') || StringLength(names->first)<StringLength(name) || (StringLength(names->first)==StringLength(name) && StringEqual(names->first, name)<0)) name=names->first;
names=names->rest;
};
return(name);
};
typedef struct InsertWireContextRec {
Wire parent;
Nat index;
} InsertWireContextRec;
typedef InsertWireContextRec *InsertWireContext;
Bool InsertWire(item, context)
Ref item;
Ref context;
{
Wire wire=(Wire)item;
InsertWireContext insertContext=(InsertWireContext)context;
insertContext->parent->elements[insertContext->index]=wire;
insertContext->index+=1;
return(false);
};
Wire CreateWire(wires, name, properties)
List wires;
String name;
Properties properties;
{
Nat size=ListLength(wires);
Wire wire=CreateWires(size, name, properties);
InsertWireContextRec insertContext;
insertContext.parent=wire;
insertContext.index=0;
ListEnumerate(wires, InsertWire, &insertContext);
return(wire);
};
Wire CreateWires(size, name, properties)
Nat size;
String name;
Properties properties;
{
Wire wire;
wire=NewSeq(Wire, WireRec, Wire, size);
wire->properties=properties;
wire->size=size;
SetShortWireName(wire, name);
return(wire);
};
Wire CopyWireUsingTable(old, oldToNew, copyName)
Wire old;
HashTable oldToNew;
Bool copyName;
{
Wire new=(Wire)HashTableGet(oldToNew, old);
String name=nil;
Nat i;
if (new!=nil) return(new);
if (copyName) name=GetShortWireName(old);
new=CreateWires(old->size, name, nil);
HashTablePut(oldToNew, old, new);
for (i=0; i<old->size; i++) new->elements[i]=CopyWireUsingTable(old->elements[i], oldToNew, copyName);
return(new);
};
Wire CopyWire(wire)
Wire wire;
{
Wire new;
if (wire==nil) new=nil;
else {
HashTable oldToNew=HashTableCreate(17, nil, nil);
new=CopyWireUsingTable(wire, oldToNew, true);
HashTableFree(oldToNew);
};
return(new);
};
void PrintAWire(wire, indent, level, name, cr, firstWire, recur)
Wire wire;
Nat indent;
Nat level;
String name;
Bool cr;
Bool firstWire;
Nat recur;
{
Nat i;
StringPrintIndent(indent, (cr || firstWire));
printf("%s", name);
/*!! if (recur==1 && Rope.Match["[*]", name] THEN out.PutF["(%g↑)", IO.int[LOOPHOLE[wire]]]; */
if (wire->size!=0) printf(", %d elements", wire->size);
PropertyPrint(wire->properties, indent+1, cr, level);
/*!! if (wire->size!=0 && (level==0 || AllSimpleAtomics(wire))) printf(" [...]") */
if (wire->size!=0 && level==0) printf(" [...]");
else for (i=0; i<wire->size; i++) {
String subName;
subName=GetShortWireName(wire->elements[i]);
/*!! if (subName==nil) subName=Index(nil, i); */
if (subName==nil) subName="indexed";
PrintAWire(wire->elements[i], indent+1, level-1, subName, cr && (wire->size<=32), cr && i==0, recur+1);
};
};
Wire FindWire(root, name)
WireSeq root;
String name;
{
Wire wire;
HashTable nameToWire=(HashTable)GetWireProp(root, nameToWireCacheProp);
if (nameToWire==nil) {
FillFullWireNameCaches(root);
nameToWire=(HashTable)GetWireProp(root, nameToWireCacheProp);
if (nameToWire==nil) Die;
};
wire=(Wire)HashTableGet(nameToWire, name);
return(wire);
};
void PrintWire(wire, indent, level)
Wire wire;
Nat indent;
Nat level;
{
String name;
name=GetShortWireName(wire);
if (name==nil) name="<no name>";
PrintAWire(wire, indent, level, name, true, true, 0);
};
void VisitAtomicWires(wire, each, context)
Wire wire;
EachWirePairProc each;
Ref context;
{
Nat i;
if (wire->size==0) each(wire, context);
else for (i=0; i<wire->size; i++) VisitAtomicWires(wire->elements[i], each, context);
};
void VisitRootAtomics(root, each, context)
Wire root;
EachWirePairProc each;
Ref context;
{
Nat i;
for (i=0; i<root->size; i++) VisitAtomicWires(root->elements[i], each, context);
};
Bool VisitBinding(actual, public, each, context)
Wire actual;
Wire public;
EachWirePairProc each;
Ref context;
{
Nat i;
Bool subWires;
Bool quit;
if (actual->size!=public->size) return(true);
quit=each(actual, public, context, &subWires);
if (quit || !subWires) return(quit);
for (i=0; i<actual->size; i++) if (VisitBinding(actual->elements[i], public->elements[i], each, context)) return (true);
return(false);
};
Bool VisitBindingSeq(actual, public, each, context)
WireSeq actual;
WireSeq public;
EachWirePairProc each;
Ref context;
{
Nat i;
for (i=0; i<actual->size; i++) if (VisitBinding(actual->elements[i], public->elements[i], each, context)) return (true);
return(false);
};
/* Cell Class */
Ref GetCellClassProp(cellClass, prop)
CellClass cellClass;
Atom prop;
{
return(PropertyGet(cellClass->properties, prop));
};
void PutCellClassProp(cellClass, prop, value)
CellClass cellClass;
Atom prop;
Ref value;
{
cellClass->properties=PropertyPut(cellClass->properties, prop, value);
};
CellClass CreateCellClass(name, recast, properties, layersProps)
String name;
RecastProc recast;
Properties properties;
Bool layersProps;
{
CellClass cellClass;
cellClass=New(CellClass, CellClassRec);
cellClass->name=name;
cellClass->recast=(Ref (*)())recast;
cellClass->properties=properties;
cellClass->layersProps=layersProps;
return(cellClass);
};
Atom printClassProcProp;
CellClass SetClassPrintProc(cellClass, proc)
CellClass cellClass;
PrintClassProc proc;
{
PutCellClassProp(cellClass, printClassProcProp, proc);
return(cellClass);
};
/* Cell Type */
Ref GetCellTypeProp(cellType, prop)
CellType cellType;
Atom prop;
{
return(PropertyGet(cellType->properties, prop));
};
void PutCellTypeProp(cellType, prop, value)
CellType cellType;
Atom prop;
Ref value;
{
cellType->properties=PropertyPut(cellType->properties, prop, value);
};
String GetCellTypeName(cellType)
CellType cellType;
{
return(GetCellTypeProp(cellType, nameProp));
};
CellType SetCellTypeName(cellType, name)
CellType cellType;
String name;
{
PutCellTypeProp(cellType, nameProp, name);
return(cellType);
};
CellType CreateCellType(class, public, data, name, properties)
CellClass class;
WireSeq public;
Ref data;
String name;
Properties properties;
{
CellType cellType=New(CellType, CellTypeRec);
cellType->class=class;
cellType->public=public;
cellType->data=data;
cellType->properties=properties;
if (name!=nil) cellType=SetCellTypeName(cellType, name);
return(cellType);
};
void PrintCellType(cellType, indent, level)
CellType cellType;
Nat indent;
Nat level;
{
PrintClassProc classProc=nil;
String name;
if (cellType->class==nil) name="<nil class pointer>";
else {
name=cellType->class->name;
classProc=(PrintClassProc)GetCellClassProp(cellType->class, printClassProcProp);
};
printf("\n\n%s: %s Cell Type", GetCellTypeName(cellType), name);
if (cellType->public!=nil) {
printf("\nPublic wire:");
PrintWire(cellType->public, indent+1, level);
};
if (classProc!=nil) classProc(cellType->data, indent, level);
PropertyPrint(cellType->properties, indent, true, level);
};
/* Record Cell Class */
CellClass recordCellClass;
Ref GetCellInstanceProp(instance, prop)
CellInstance instance;
Atom prop;
{
return(PropertyGet(instance->properties, prop));
};
void PutCellInstanceProp(instance, prop, value)
CellInstance instance;
Atom prop;
Ref value;
{
instance->properties=PropertyPut(instance->properties, prop, value);
};
String GetCellInstanceName(instance)
CellInstance instance;
{
return(GetCellInstanceProp(instance, nameProp));
};
CellInstance SetCellInstanceName(instance, name)
CellInstance instance;
String name;
{
PutCellInstanceProp(instance, nameProp, name);
return(instance);
};
CellInstance CreateCellInstance(actual, type, name, properties)
WireSeq actual;
CellType type;
String name;
Properties properties;
{
CellInstance cellInstance;
cellInstance=New(CellInstance, CellInstanceRec);
cellInstance->actual=actual;
cellInstance->type=type;
cellInstance->properties=properties;
if(name!=nil) SetCellInstanceName(cellInstance, name);
return(cellInstance);
};
typedef struct InsertInstanceContextRec {
RecordCellType data;
Nat elementIndex;
} InsertInstanceContextRec;
typedef InsertInstanceContextRec *InsertInstanceContext;
Bool InsertInstance (item, context)
Ref item;
Ref context;
{
InsertInstanceContext insertContext=(InsertInstanceContext)context;
insertContext->data->cellInstances[insertContext->elementIndex]=(CellInstance)item;
insertContext->elementIndex+=1;
return(false);
};
CellType CreateRecordCell(public, internal, cellInstances, name, properties, giveNames)
WireSeq public;
WireSeq internal;
List cellInstances;
String name;
Properties properties;
Bool giveNames;
{
InsertInstanceContextRec insertContext;
Nat size=ListLength(cellInstances);
RecordCellType data=NewSeq(RecordCellType, RecordCellTypeRec, CellInstance, size);
data->internal=internal;
data->size=size;
insertContext.data=data;
insertContext.elementIndex=0;
ListEnumerate(cellInstances, InsertInstance, &insertContext);
return(CreateCellType(recordCellClass, public, data, name, properties));
};
typedef struct PrintInstanceBindingContextRec {
Wire public;
Wire internal;
} PrintInstanceBindingContextRec;
typedef PrintInstanceBindingContextRec *PrintInstanceBindingContext;
Bool PrintInstanceBinding(actualWire, publicWire, context, subWires)
Wire actualWire;
Wire publicWire;
Ref context;
Bool *subWires;
{
PrintInstanceBindingContext printInstanceContext=(PrintInstanceBindingContext)context;
String publicName=GetFullWireName(printInstanceContext->public, publicWire);
String actualName=GetFullWireName(printInstanceContext->internal, actualWire);
*subWires=GetShortWireName(publicWire)==nil && publicWire->size>0;
/*!! IF NOT subWires THEN IF Rope.Match["[*]", actualName]
THEN out.PutF[" %g: %g(%g↑);", IO.rope[publicName], IO.rope[actualName], IO.int[LOOPHOLE[actualWire]]]
ELSE out.PutF[" %g: %g;", IO.rope[publicName], IO.rope[actualName]]; */
if (!*subWires) printf( " %s: %s;", publicName, actualName);
return(false);
};
void RecordPrint(data, indent, level)
Ref data;
Nat indent;
Nat level;
{
Nat i, j;
RecordCellType recordCellType=(RecordCellType)data;
PrintInstanceBindingContextRec printInstanceContext;
printInstanceContext.internal=recordCellType->internal;
StringPrintIndent(indent, true);
printf("Internal wire:");
PrintWire(recordCellType->internal, indent+1, level);
StringPrintIndent(indent, true);
printf("%d instances", recordCellType->size);
for (i=0; i<recordCellType->size; i++) {
CellInstance cellInstance=recordCellType->cellInstances[i];
String instanceName=GetCellInstanceName(cellInstance);
String subCellTypeName=GetCellTypeName(cellInstance->type);
StringPrintIndent(indent, true);
if (instanceName==nil) instanceName="<no name>";
if (subCellTypeName==nil) subCellTypeName="<no name>";
printf("CellInstance %s: %s", instanceName, subCellTypeName);
StringPrintIndent(indent, true);
printf(" Actual wire: ");
/*!! IF NOT CoreOps.Conform[instance.actual, instance.type.public] THEN out.PutF["\n*** Actual and Public do not conform\n"]; */
printInstanceContext.public=cellInstance->type->public;
for (j=0; j<cellInstance->type->public->size; j++) VisitBinding(cellInstance->actual->elements[j], cellInstance->type->public->elements[j], PrintInstanceBinding, &printInstanceContext);
PropertyPrint(cellInstance->properties, 1, true, level);
};
};
/* Transistor Cell Class */
CellClass transistorCellClass;
String transistorTypeNames[3]={"nE", "pE", "nD"};
String transistorPortNames[4]={"gate", "ch1", "ch2", "Vdd"};
void TransistorPrint(data, indent, level)
Ref data;
Nat indent;
Nat level;
{
Transistor transistor=(Transistor)data;
printf("\n\ntype: %s", transistorTypeNames[Val(transistor->type)]);
};
Atom lengthProp;
Atom widthProp;
CellType CreateTransistor(type, length, width, name, properties)
TransistorType type;
int length;
int width;
String name;
Properties properties;
{
Transistor data=New(Transistor, TransistorRec);
CellType cellType;
List tranPublic=nil;
if (type==pE) tranPublic=ListCons(tranPublic, CreateWire(nil, transistorPortNames[Val(Vdd)], nil));
tranPublic=ListCons(tranPublic, CreateWire(nil, transistorPortNames[Val(ch2)], nil));
tranPublic=ListCons(tranPublic, CreateWire(nil, transistorPortNames[Val(ch1)], nil));
tranPublic=ListCons(tranPublic, CreateWire(nil, transistorPortNames[Val(gate)], nil));
data->type=type;
cellType=CreateCellType(transistorCellClass, CreateWire(tranPublic, nil, nil), data, name, properties);
if (length!=-1) PutCellTypeProp(cellType, lengthProp, length);
if (width!=-1) PutCellTypeProp(cellType, widthProp, width);
return(cellType);
};
/* Initialization */
void CoreInitialize()
{
nameProp=PropertyRegister("CoreName", nil);
printClassProcProp=PropertyRegister("CorePrintClassProc", nil);
wireToNamesCacheProp=PropertyRegister("wireToNamesCacheProp", nil);
nameToWireCacheProp=PropertyRegister("nameToWireCacheProp", nil);
lengthProp=PropertyRegister("lengthProp", nil);
widthProp=PropertyRegister("widthProp", nil);
recordCellClass=SetClassPrintProc(CreateCellClass("Record", nil, nil, false), RecordPrint);
transistorCellClass=SetClassPrintProc(CreateCellClass("Transistor", nil, nil, false), TransistorPrint);
};