DIRECTORY Core, CoreClasses, CoreOps, CoreProperties, GList, IO, RefTab, RefTabExtras, Rope; CoreClassesImpl: CEDAR PROGRAM IMPORTS CoreOps, CoreProperties, GList, IO, RefTab, RefTabExtras, Rope EXPORTS CoreClasses = BEGIN OPEN Core, CoreClasses; recordCellClass: PUBLIC CellClass _ CoreOps.SetClassPrintProc[NEW [CellClassRec _ [name: "Record", layersProps: FALSE]], PropRecordPrint]; PropRecordPrint: CoreOps.PrintClassProc = { recordCellType: RecordCellType _ NARROW [data]; CoreOps.PrintIndent[indent, out]; IO.PutRope[out, "Internal wire:"]; CoreOps.PrintWire[recordCellType.internal, out, indent, level]; CoreOps.PrintIndent[indent, out]; IO.PutF[out, "%g instances", IO.int[recordCellType.size]]; FOR i: NAT IN [0 .. recordCellType.size) DO instance: CellInstance = recordCellType.instances[i]; EachWirePair: CoreOps.EachWirePairProc = { publicName: ROPE = CoreOps.GetFullWireName[instance.type.public, publicWire]; actualName: ROPE = CoreOps.GetFullWireName[recordCellType.internal, actualWire]; subWires _ CoreOps.GetShortWireName[publicWire]=NIL AND 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]]; }; CoreOps.PrintIndent[indent, out]; IO.PutF[out, "CellInstance %g: %g", [rope[GetCellInstanceName[instance]]], [rope[CoreOps.GetCellTypeName[instance.type]]]]; CoreOps.PrintIndent[indent, out]; IO.PutRope[out, " Actual wire: "]; IF NOT CoreOps.Conform[instance.actual, instance.type.public] THEN out.PutF["\n*** Actual and Public do not conform\n"]; FOR j: NAT IN [0 .. instance.type.public.size) DO [] _ CoreOps.VisitBinding[instance.actual[j], instance.type.public[j], EachWirePair]; ENDLOOP; CoreProperties.PrintProperties[props: instance.properties, out: out, indent: 1, level: level]; ENDLOOP; }; givenNameProp: ATOM _ CoreProperties.RegisterProperty[$GivenName, CoreProperties.Props[[CoreProperties.propPrint, CoreProperties.PropDontPrint]]]; CreateRecordCell: PUBLIC PROC [public: WireSeq, internal: WireSeq, instances: LIST OF CellInstance, name: ROPE _ NIL, props: Properties _ NIL, giveNames: BOOL _ FALSE] RETURNS [recordCell: CellType] = { internals: RefTab.Ref _ RefTab.Create[internal.size]; AddInInternals: CoreOps.EachWireProc = {[] _ RefTab.Store[internals, wire, wire]}; data: RecordCellType; size: NAT _ GList.Length[instances]; data _ NEW [RecordCellTypeRec[size]]; size _ 0; FOR i: NAT IN [0 .. internal.size) DO [] _ CoreOps.VisitWire[internal[i], AddInInternals]; ENDLOOP; FOR i: NAT IN [0 .. public.size) DO IF ~RefTab.Fetch[internals, public[i]].found THEN ERROR; -- public public[i] is not part of internal ENDLOOP; FOR list: LIST OF CellInstance _ instances, list.rest WHILE list#NIL DO data[size] _ list.first; size _ size+1; IF NOT CoreOps.Conform[list.first.actual, list.first.type.public] THEN ERROR; FOR i: NAT IN [0 .. list.first.actual.size) DO IF ~RefTab.Fetch[internals, list.first.actual[i]].found THEN ERROR; -- actual list.first.actual[i] is not part of internal ENDLOOP; ENDLOOP; data.internal _ internal; IF giveNames THEN { Fetch: PROC [table: RefTab.Ref, key: REF] RETURNS [value: REF] = { value _ RefTab.Fetch[table, key].val; IF value=$None THEN value _ NIL; }; Store: PROC [table: RefTab.Ref, key: REF, value: REF] = { [] _ RefTab.Store[table, key, IF RefTab.Fetch[table, key].val=NIL THEN value ELSE $None]; }; FindPossibleName: CoreOps.EachWirePairProc = { value: REF; name: ROPE _ CoreOps.GetShortWireName[publicWire]; IF CoreOps.GetShortWireName[actualWire]#NIL THEN RETURN; IF name=NIL THEN RETURN; value _ RefTab.Fetch[actualPossibleNames, actualWire].val; IF value=$None THEN RETURN; IF Rope.Equal[NARROW [value], name] THEN RETURN; Store[actualPossibleNames, actualWire, name]; }; AddInExistingNames: CoreOps.EachWireProc = { name: ROPE _ CoreOps.GetShortWireName[wire]; IF name=NIL THEN { value: REF _ Fetch[actualPossibleNames, wire]; IF value=NIL THEN RETURN; Store[existingNames, value, wire]; } ELSE Store[existingNames, name, wire]; }; AddName: CoreOps.EachWireProc = { name: ROPE _ CoreOps.GetShortWireName[wire]; value: REF; IF name#NIL THEN RETURN [subWires: FALSE]; value _ Fetch[actualPossibleNames, wire]; IF value=NIL OR Fetch[existingNames, value]#wire THEN RETURN; CoreProperties.PutWireProp[wire, $GivenName, $GivenName]; [] _ CoreOps.SetShortWireName[wire, NARROW [value]]; }; actualPossibleNames: RefTab.Ref _ RefTab.Create[]; -- association actual -> possible name for the actual. $None indicates at least two different names. existingNames: RefTab.Ref _ RefTab.Create[equal: RefTabExtras.EqualRope, hash: RefTabExtras.HashRope]; -- association name -> wire that will get that name. $None indicates a conflict FOR i: NAT IN [0 .. data.size) DO [] _ CoreOps.VisitBinding[data[i].actual, data[i].type.public, FindPossibleName]; ENDLOOP; [] _ CoreOps.VisitWire[internal, AddInExistingNames]; [] _ CoreOps.VisitWire[internal, AddName]; }; CoreOps.FlushNameCaches[internal]; recordCell _ CoreOps.CreateCellType[recordCellClass, public, data, name, props]; }; CreateInstance: PUBLIC PROC [actual: WireSeq, type: CellType, name: ROPE _ NIL, props: Properties _ NIL] RETURNS [instance: CellInstance] = { instance _ NEW [CellInstanceRec _ [actual: actual, type: type, properties: props]]; IF name#NIL THEN instance _ SetCellInstanceName[instance, name]; }; GetCellInstanceName: PUBLIC PROC [instance: CellInstance] RETURNS [name: ROPE] = { name _ NARROW [CoreProperties.GetCellInstanceProp[instance, CoreOps.nameProp]]; }; SetCellInstanceName: PUBLIC PROC [instance: CellInstance, name: ROPE] RETURNS [sameInstance: CellInstance] = { CoreProperties.PutCellInstanceProp[on: instance, prop: CoreOps.nameProp, value: name]; sameInstance _ instance; }; CorrespondingActual: PUBLIC PROC [instance: CellInstance, public: Wire] RETURNS [actual: Wire _ NIL] = { EachWirePair: CoreOps.EachWirePairProc = { IF publicWire=public THEN {actual _ actualWire; quit _ TRUE}; }; [] _ CoreOps.VisitBinding[instance.actual, instance.type.public, EachWirePair]; }; Compose: PROC [xToY, yToZ, xToZ: RefTab.Ref] RETURNS [ok: BOOL _ TRUE, overWritten: BOOL _ FALSE] = { EachX: RefTab.EachPairAction = { found: BOOL; z: RefTab.Val; [found, z] _ RefTab.Fetch[yToZ, val]; IF NOT found THEN {ok _ FALSE; quit _ TRUE; RETURN}; overWritten _ overWritten OR NOT RefTab.Store[xToZ, key, z]; }; ok _ NOT RefTab.Pairs[xToY, EachX]; }; CreatePermutedRecordCell: PUBLIC PROC [iconPublic: WireSeq, schCell: CellType, table: RefTab.Ref, name: ROPE _ NIL, props: Properties _ NIL] RETURNS [recordCell: CellType] = { AddInternal: PROC [wire: Wire] = { IF NOT CoreOps.Member[internals, wire] THEN internals _ CONS [wire, internals]; }; internals: LIST OF Wire _ NIL; public: Wire _ CoreOps.CopyWire[iconPublic]; actual: Wire; schPublicsToRecordPublics: RefTab.Ref _ RefTab.Create[]; BEGIN -- fill public and initialize schPublicsToRecordPublics RegisterPublicMapping: CoreOps.EachWirePairProc = { [] _ RefTab.Store[iconToRecord, actualWire, publicWire]; }; iconToRecord: RefTab.Ref _ RefTab.Create[]; [] _ CoreOps.VisitBinding[iconPublic, public, RegisterPublicMapping]; FOR i: NAT IN [0 .. public.size) DO AddInternal[public[i]] ENDLOOP; IF NOT Compose[table, iconToRecord, schPublicsToRecordPublics].ok THEN ERROR; END; BEGIN -- fill actual while filling schPublicsToRecordPublics Map: PROC [schPublic: Wire] RETURNS [actual: Wire] = { actual _ NARROW [RefTab.Fetch[schPublicsToRecordPublics, schPublic].val]; IF actual#NIL THEN RETURN; actual _ CoreOps.CreateWires[size: schPublic.size]; [] _ RefTab.Store[schPublicsToRecordPublics, schPublic, actual]; FOR i: NAT IN [0 .. actual.size) DO actual[i] _ Map[schPublic[i]] ENDLOOP; }; actual _ Map[schCell.public]; FOR i: NAT IN [0 .. actual.size) DO AddInternal[actual[i]] ENDLOOP; END; recordCell _ CreateRecordCell [public: public, internal: CoreOps.CreateWire[internals], instances: LIST [CreateInstance[actual, schCell]], name: name, props: props]; }; ReverseCellInstances: PUBLIC PROC [instances: CellInstances] RETURNS [rev: CellInstances _ NIL] = { rev _ NARROW [GList.Reverse[instances]]; }; InstanceIndex: PUBLIC PROC [recordCell: CellType, instance: CellInstance] RETURNS [index: INT _ -1] = { rct: RecordCellType _ NARROW [recordCell.data]; FOR i: NAT IN [0 .. rct.size) DO IF rct[i]=instance THEN RETURN [i]; ENDLOOP; }; transistorCellClass: PUBLIC CellClass _ CoreOps.SetClassPrintProc[NEW [CellClassRec _ [name: "Transistor", layersProps: FALSE]], PrintTransistor]; transistorTypeNames: PUBLIC ARRAY TransistorType OF ROPE _ ["nE", "pE", "nD"]; transistorPortNames: PUBLIC ARRAY TransistorPort OF ROPE _ ["gate", "ch1", "ch2", "Vdd"]; lengthProp: PUBLIC ATOM _ $CoreTransistorLength; widthProp: PUBLIC ATOM _ $CoreTransistorWidth; PrintTransistor: CoreOps.PrintClassProc = { tran: Transistor _ NARROW [data]; IO.PutF[out, "\n\ntype: %g", IO.rope[transistorTypeNames[tran.type]]]; }; CreateTransistor: PUBLIC PROC [type: TransistorType, length: INT _ -1, width: INT _ -1, name: ROPE _ NIL, props: Properties _ NIL] RETURNS [cellType: CellType] = { tranPublic: Wires _ NIL; IF type=pE THEN tranPublic _ CONS[CoreOps.CreateWire[name: transistorPortNames[Vdd]], tranPublic]; tranPublic _ CONS[CoreOps.CreateWire[name: transistorPortNames[ch2]], tranPublic]; tranPublic _ CONS[CoreOps.CreateWire[name: transistorPortNames[ch1]], tranPublic]; tranPublic _ CONS[CoreOps.CreateWire[name: transistorPortNames[gate]], tranPublic]; cellType _ CoreOps.CreateCellType[ class: transistorCellClass, public: CoreOps.CreateWire[tranPublic], data: NEW [TransistorRec _ [type]], name: name, props: props]; IF length#-1 THEN CoreProperties.PutCellTypeProp[cellType, lengthProp, NEW[INT _ length]]; IF width#-1 THEN CoreProperties.PutCellTypeProp[cellType, widthProp, NEW[INT _ width]]; }; unspecifiedCellClass: PUBLIC CellClass _ NEW [CellClassRec _ [name: "Unspecified", layersProps: FALSE]]; CreateUnspecified: PUBLIC PROC [public: WireSeq, name: ROPE _ NIL, props: Properties _ NIL] RETURNS [cellType: CellType] = { cellType _ CoreOps.CreateCellType[ class: unspecifiedCellClass, public: public, data: NIL, name: name, props: props]; }; sequenceCellClass: PUBLIC CellClass _ CoreOps.SetClassPrintProc[NEW [CellClassRec _ [name: "Sequence", recast: RecastSequence, layersProps: FALSE]], PrintSequence]; PrintSequence: CoreOps.PrintClassProc = { cell: SequenceCellType _ NARROW [data]; IO.PutF[out, "\n\nBase cell type: %g", IO.rope[CoreOps.GetCellTypeName[cell.base]]]; IO.PutF[out, ", count: %g", IO.int[cell.count]]; IO.PutRope[out, "\nsequence wires:"]; IF cell.sequence#NIL THEN FOR seq: NAT IN [0 .. cell.sequence.length) DO IO.PutF[out, " %g", IO.rope[CoreOps.GetShortWireName[ cell.base.public[cell.sequence[seq]]]]]; ENDLOOP; IO.PutRope[out, "\nflat sequence wires:"]; IF cell.flatSequence#NIL THEN FOR seq: NAT IN [0 .. cell.flatSequence.length) DO IO.PutF[out, " %g", IO.rope[CoreOps.GetShortWireName[ cell.base.public[cell.flatSequence[seq]]]]]; ENDLOOP; IO.PutRope[out, "\nstitch wires:"]; IF cell.stitch#NIL THEN FOR seq: NAT IN [0 .. cell.stitch.length) DO IO.PutF[out, " [%g, &g]", IO.rope[CoreOps.GetShortWireName[ cell.base.public[cell.stitch[seq].this]]], IO.rope[CoreOps.GetShortWireName[ cell.base.public[cell.stitch[seq].that]]]]; ENDLOOP; }; RecastSequence: RecastProc = { seqCell: SequenceCellType _ NARROW[me.data]; public: Wire _ CoreOps.CopyWire[me.public]; newInternal: Wire _ NEW [WireRec[public.size+seqCell.count]]; instances: LIST OF CoreClasses.CellInstance _ NIL; FOR w: NAT IN [0..public.size) DO newInternal[w] _ public[w]; ENDLOOP; FOR cell: NAT DECREASING IN [0..seqCell.count) DO newWire: Wire _ NEW[WireRec[public.size]]; cellTypeName: ROPE _ CoreOps.GetCellTypeName[seqCell.base]; newWire.properties _ public.properties; FOR i: NAT IN [0 .. public.size) DO newWire[i] _ public[i] ENDLOOP; IF seqCell.sequence#NIL THEN FOR seqWire: NAT IN [0..seqCell.sequence.length) DO seqElement: NAT _ seqCell.sequence[seqWire]; newWire[seqElement] _ newWire[seqElement][cell]; ENDLOOP; IF seqCell.flatSequence#NIL THEN FOR seqWire: NAT IN [0..seqCell.flatSequence.length) DO seqElement: NAT _ seqCell.flatSequence[seqWire]; size: NAT _ seqCell.base.public[seqElement].size; actWire: Wire _ NEW[WireRec[size]]; FOR i: NAT IN [0..size) DO actWire[i] _ newWire[seqElement][(size*cell)+i]; ENDLOOP; newWire[seqElement] _ actWire; ENDLOOP; IF seqCell.stitch#NIL AND seqCell.count>1 AND cell˜¥Kšœ˜K˜—š žœœœœœ˜cJšœœ˜(J˜J˜—š ž œœœ0œ œ ˜gKšœœ˜/šœœœ˜ Kšœœœ˜#Kšœ˜—Kšœ˜——šž ™ Kšœœ'œ3œ˜’K˜š œœœœœ˜NK˜—š œœœœœ!˜YK˜—šœ œœ˜0K˜—šœ œœ˜.K˜—šžœ˜+Jšœœ˜!Kšœœ'˜FKšœ˜K˜—šžœœœ œœ œœœœ˜£Kšœœ˜Kšœ œœA˜bKšœ œA˜RKšœ œA˜RKšœ œB˜Sšœ"˜"Jšœ˜Jšœ'˜'Jšœœ˜#Jšœ˜—Kšœ œ6œœ ˜ZKšœ œ5œœ ˜WKšœ˜——šž ™ Kšœœ œ4œ˜hK˜šžœœœœœœœ˜|šœ"˜"Kšœ˜Kšœ˜Kšœœ˜ Kšœ ˜ Kšœ˜—Kšœ˜——šž™Kšœœ'œIœ˜¥K˜šŸ œ˜)Jšœœ˜'Kšœ%œ+˜TKšœœ˜0Kšœ#˜%š œœœœœœ˜HKšœœH˜^Kšœ˜—Kšœ(˜*š œœœœœœ!˜PKšœœL˜bKšœ˜—Kšœ!˜#š œ œœœœœ˜DKšœœKœK˜´Kšœ˜—Kšœ˜K˜—šžœ˜Kšœœ ˜,Kšœ+˜+Kšœœ&˜=Kšœ œœœ˜2šœœœ˜!Kšœ˜Kšœ˜—š œœ œœ˜1Jšœœ˜*Jšœœ)˜;Kšœ'˜'Kš œœœœœ˜Cš œœœœ œœ˜PKšœ œ˜,Jšœ0˜0Kšœ˜—š œœœœ œœ"˜XKšœ œ!˜0Jšœœ(˜1Kšœœ˜#šœœœ ˜Kšœ0˜0Kšœ˜—Jšœ˜Kšœ˜—šœœœœœœ œœ˜yKšœœ ˜)Kšœœ ˜)Kšœœ˜„Kšœ˜—šœ œ˜!Kšœ˜Kšœ˜Kšœœœœœœœœœ ˜_Kšœ ˜ —Kšœ(˜(Kšœ˜—šœ˜Kšœ˜Kšœ˜Kšœ˜Kšœ"˜"Kšœœ˜ —Kšœ˜K˜—šžœœœ œœœœ˜€Kšœ2˜2š œœœœœœ˜FKšœ(˜(Kšœœ˜)šœœœ˜"Kšœ>œ˜CKšœ˜—Kšœ_˜_Kšœ˜—š œœœœœœ˜NKšœ,˜,Kšœœ˜+Kšœœ˜*Kšœ œœ˜šœœœ˜"Kšœ@œ˜EKšœ˜—Kšœb˜bKšœ˜—šœ"˜"Kšœ˜Kšœ˜Kšœ ˜ Kšœ ˜ Kšœ˜—Kšœ˜K˜K˜——Kšœ˜K˜—…—7üJG