/* 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; isize; 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; isize; 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)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; isize; 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; isize; 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=""; 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; isize; i++) VisitAtomicWires(wire->elements[i], each, context); }; void VisitRootAtomics(root, each, context) Wire root; EachWirePairProc each; Ref context; { Nat i; for (i=0; isize; 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; isize; 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; isize; 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=""; 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; isize; i++) { CellInstance cellInstance=recordCellType->cellInstances[i]; String instanceName=GetCellInstanceName(cellInstance); String subCellTypeName=GetCellTypeName(cellInstance->type); StringPrintIndent(indent, true); if (instanceName==nil) instanceName=""; if (subCellTypeName==nil) subCellTypeName=""; 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; jtype->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); };