<> <> <> <> <> <> <<>> DIRECTORY Ascii, Atom, CedarProcess, Convert, Core, CoreClasses, CoreDirectory, CoreIO, CoreOps, CoreProperties, FS, GList, IO, ProcessProps, RefTab, RefTabExtras, Rope, SymTab; CoreIOImpl: CEDAR PROGRAM IMPORTS Atom, CedarProcess, Convert, CoreClasses, CoreOps, CoreProperties, FS, GList, IO, ProcessProps, RefTab, RefTabExtras, Rope, SymTab EXPORTS CoreIO = BEGIN OPEN CoreIO; <> coreWriteProcProp: ATOM = $CoreWriteProc; coreReadProcProp: ATOM = $CoreReadProc; calledFromDir: Core.ROPE _ NIL; classRegistry: RefTab.Ref _ RefTab.Create[equal: RefTabExtras.EqualRope, hash: RefTabExtras.HashRope]; PutSpace: PROC [h: Handle] = INLINE {IO.PutChar[h.stream, Ascii.SP]}; <> UnknownProperty: PUBLIC SIGNAL [propKey: ATOM] = CODE; UnknownCellClass: PUBLIC SIGNAL [class: Core.CellClass] = CODE; ReportSaveCellType: PUBLIC PROC [cellType: Core.CellType, fileName: ROPE _ NIL] RETURNS [props: LIST OF ATOM _ NIL, classes: LIST OF Core.CellClass _ NIL] = { SaveCellType[cellType, fileName ! UnknownProperty => { IF NOT GList.Member[propKey, props] THEN props _ CONS [propKey, props]; RESUME; }; UnknownCellClass => { IF NOT GList.Member[class, classes] THEN classes _ CONS [class, classes]; RESUME; }]; }; <<>> SaveCellType: PUBLIC PROC [cellType: Core.CellType, fileName: ROPE _ NIL] = { h: Handle _ NEW [HandleRec]; IF fileName=NIL THEN fileName _ Rope.Cat[CoreOps.GetCellTypeName[cellType], ".core"]; h.stream _ FS.StreamOpen[fileName, $create]; h.cellTypeIDTab _ RefTab.Create[]; h.ropeIDTab _ RefTab.Create[equal: RefTabExtras.EqualRope, hash: RefTabExtras.HashRope]; h.atomIDTab _ RefTab.Create[]; WriteCellType[h, cellType]; IO.Close[h.stream]; }; <<>> importCellClass: PUBLIC Core.CellClass _ CoreOps.SetClassPrintProc[NEW [Core.CellClassRec _ [name: "Import", recast: RecastImport, layersProps: TRUE]], PrintImport]; ReadFile: PROC [name: Core.ROPE] RETURNS [s: IO.STREAM _ NIL] ~ { s _ FS.StreamOpen[fileName: name ! FS.Error => CONTINUE]; IF s=NIL THEN s _ FS.StreamOpen[fileName: name, wDir: calledFromDir]; }; RestoreCellType: PUBLIC PROC [cellName: ROPE _ NIL, fileName: ROPE _ NIL] RETURNS [cellType: Core.CellType] = { h: Handle _ NEW[HandleRec]; IF fileName=NIL AND cellName=NIL THEN ERROR; IF fileName=NIL THEN fileName _ Rope.Cat[cellName, ".core"]; h.fileName _ fileName; h.stream _ ReadFile[fileName]; h.cellTypeIDTab _ RefTab.Create[equal: RefTabExtras.EqualRope, hash: RefTabExtras.HashRope]; h.ropeIDTab _ RefTab.Create[equal: RefTabExtras.EqualRope, hash: RefTabExtras.HashRope]; h.atomIDTab _ RefTab.Create[equal: RefTabExtras.EqualRope, hash: RefTabExtras.HashRope]; [cellType, h.wireIDTab] _ ReadCellTypePublic[h]; cellType.class _ importCellClass; cellType.data _ h; }; RecastImport: Core.RecastProc = { h: Handle _ NARROW [me.data]; me.data _ NIL; ReadCellTypeRest[h, me, h.wireIDTab]; new _ me; }; PrintImport: CoreOps.PrintClassProc = { h: Handle _ NARROW [data]; CoreOps.PrintIndent[indent, out]; IO.PutF[out, "Import of : %g", IO.rope[h.fileName]]; }; WriteImport: ClassWriteProc = { WriteWireIDPair: HashWriteProc = { id: ROPE _ NARROW[key]; wire: Core.Wire _ NARROW[value]; WriteID[h, id]; WriteWire[h, wireIDTab, wire]; }; child: Handle _ NARROW [cellType.data]; WriteRope[h, child.fileName]; WriteInt[h, IO.GetIndex[child.stream]]; WriteHashTable[h, child.cellTypeIDTab, WriteCellTypeIDPair]; WriteHashTable[h, child.ropeIDTab, WriteRopeIDPair]; WriteHashTable[h, child.atomIDTab, WriteAtomIDPair]; WriteHashTable[h, child.wireIDTab, WriteWireIDPair]; WriteProperties[h, child.properties]; }; <<>> ReadImport: ClassReadProc = { ReadWireIDPair: HashReadProc = { key _ ReadID[h]; value _ ReadWire[h, wireIDTab]; }; child: Handle _ NEW[HandleRec]; child.cellType _ NIL; -- I'm not sure what's right here child.wire _ NIL; -- I'm not sure what's right here child.fileName _ ReadRope[h]; child.stream _ ReadFile[child.fileName]; IO.SetIndex[child.stream, ReadInt[h]]; child.cellTypeIDTab _ ReadHashTable[h, ReadCellTypeIDPair, RefTabExtras.EqualRope, RefTabExtras.HashRope]; child.ropeIDTab _ ReadHashTable[h, ReadRopeIDPair, RefTabExtras.EqualRope, RefTabExtras.HashRope]; child.atomIDTab _ ReadHashTable[h, ReadAtomIDPair, RefTabExtras.EqualRope, RefTabExtras.HashRope]; child.wireIDTab _ ReadHashTable[h, ReadWireIDPair, RefTabExtras.EqualRope, RefTabExtras.HashRope]; child.properties _ ReadProperties[h]; cellType.data _ child; }; <> SaveLibrary: PUBLIC PROC [library: CoreDirectory.Library, fileName: ROPE] = { EachLibraryItem: SymTab.EachPairAction = { WriteRope[h, key]; WriteCellType[h, NARROW [val] ! UnknownProperty => RESUME; UnknownCellClass => RESUME]; }; h: Handle _ NEW [HandleRec]; fileName _ Rope.Cat[fileName, ".corelib"]; h.stream _ FS.StreamOpen[fileName, $create]; h.cellTypeIDTab _ RefTab.Create[]; h.ropeIDTab _ RefTab.Create[equal: RefTabExtras.EqualRope, hash: RefTabExtras.HashRope]; h.atomIDTab _ RefTab.Create[]; WriteInt[h, SymTab.GetSize[library]]; [] _ SymTab.Pairs[library, EachLibraryItem]; IO.Close[h.stream]; }; <<>> RestoreLibrary: PUBLIC PROC [fileName: ROPE] RETURNS [library: CoreDirectory.Library] = { h: Handle _ NEW[HandleRec]; size: INT; fileName _ Rope.Cat[fileName, ".corelib"]; h.fileName _ fileName; h.stream _ ReadFile[fileName]; h.cellTypeIDTab _ RefTab.Create[equal: RefTabExtras.EqualRope, hash: RefTabExtras.HashRope]; h.ropeIDTab _ RefTab.Create[equal: RefTabExtras.EqualRope, hash: RefTabExtras.HashRope]; h.atomIDTab _ RefTab.Create[equal: RefTabExtras.EqualRope, hash: RefTabExtras.HashRope]; size _ ReadInt[h]; library _ SymTab.Create[(size/2)*2+1]; THROUGH [0 .. size) DO key: ROPE _ ReadRope[h]; cellType: Core.CellType _ ReadCellType[h]; [] _ SymTab.Store[library, key, cellType]; ENDLOOP; IO.Close[h.stream]; }; <> RegisterClass: PUBLIC PROC [class: Core.CellClass, write: ClassWriteProc, read: ClassReadProc] RETURNS [sameClass: Core.CellClass] = { sameClass _ class; CoreProperties.PutCellClassProp[class, coreWriteProcProp, NEW[ClassWriteProc _ write]]; CoreProperties.PutCellClassProp[class, coreReadProcProp, NEW[ClassReadProc _ read]]; [] _ RefTab.Store[classRegistry, class.name, class]; }; RegisterProperty: PUBLIC PROC [prop: ATOM, write: PropWriteProc, read: PropReadProc] RETURNS [sameProp: ATOM] = { props: Core.Properties _ CoreProperties.FetchProperties[prop]; props _ CoreProperties.PutProp[props, coreWriteProcProp, NEW[PropWriteProc _ write]]; props _ CoreProperties.PutProp[props, coreReadProcProp, NEW[PropReadProc _ read]]; CoreProperties.StoreProperties[prop, props]; sameProp _ prop; }; <> WriteCellType: PUBLIC PROC [h: Handle, cellType: Core.CellType] = { cellTypeID: ROPE _ NARROW [RefTab.Fetch[h.cellTypeIDTab, cellType].val]; IF cellTypeID=NIL THEN { parentCellType: Core.CellType _ h.cellType; wireIDTab: RefTab.Ref _ RefTab.Create[]; classWrite: REF ClassWriteProc _ NARROW[CoreProperties.GetCellClassProp[from: cellType.class, prop: coreWriteProcProp]]; IF classWrite=NIL THEN { SIGNAL UnknownCellClass[cellType.class]; cellType _ CoreOps.Recast[cellType]; IF cellType=NIL THEN ERROR; WriteCellType[h, cellType]; RETURN; }; cellTypeID _ Rope.Cat["C", Convert.RopeFromInt[from: RefTab.GetSize[h.cellTypeIDTab], base: 16, showRadix: FALSE]]; IF NOT RefTab.Insert[h.cellTypeIDTab, cellType, cellTypeID] THEN ERROR; h.cellType _ cellType; WriteID[h, cellTypeID]; WriteWire[h, wireIDTab, cellType.public]; WriteProperties[h, cellType.properties]; WriteRope[h, cellType.class.name]; classWrite^[h, cellType, wireIDTab]; h.cellType _ parentCellType; } ELSE WriteID[h, cellTypeID]; }; ReadCellType: PUBLIC PROC [h: Handle] RETURNS [cellType: Core.CellType] = { wireIDTab: RefTab.Ref _ NIL; parentCellType: Core.CellType _ h.cellType; [cellType, wireIDTab] _ ReadCellTypePublic[h]; IF wireIDTab#NIL THEN ReadCellTypeRest[h, cellType, wireIDTab]; h.cellType _ parentCellType; }; ReadCellTypePublic: PUBLIC PROC [h: Handle] RETURNS [cellType: Core.CellType, wireIDTab: RefTab.Ref] = { cellTypeID: ROPE _ ReadID[h]; IF Rope.Fetch[cellTypeID]#'C THEN ERROR; cellType _ NARROW[RefTab.Fetch[h.cellTypeIDTab, cellTypeID].val]; IF cellType=NIL THEN { cellType _ NEW[Core.CellTypeRec]; IF NOT RefTab.Insert[h.cellTypeIDTab, cellTypeID, cellType] THEN ERROR; h.cellType _ cellType; wireIDTab _ RefTab.Create[equal: RefTabExtras.EqualRope, hash: RefTabExtras.HashRope]; cellType.public _ ReadWire[h, wireIDTab]; cellType.properties _ ReadProperties[h]; }; }; ReadCellTypeRest: PUBLIC PROC [h: Handle, cellType: Core.CellType, wireIDTab: RefTab.Ref] = { className: ROPE _ ReadRope[h]; classRead: REF ClassReadProc _ NIL; cellType.class _ NARROW[RefTab.Fetch[classRegistry, className].val]; classRead _ NARROW[CoreProperties.GetCellClassProp[from: cellType.class, prop: coreReadProcProp]]; classRead^[h, cellType, wireIDTab]; }; WriteWire: PUBLIC PROC [h: Handle, wireIDTab: RefTab.Ref, wire: Core.Wire] = { wireID: ROPE _ NARROW[RefTab.Fetch[wireIDTab, wire].val]; IF wireID=NIL THEN { parentWire: Core.Wire _ h.wire; wireID _ Rope.Cat["W", Convert.RopeFromInt[from: RefTab.GetSize[wireIDTab], base: 16, showRadix: FALSE]]; IF NOT RefTab.Insert[wireIDTab, wire, wireID] THEN ERROR; WriteID[h, wireID]; WriteInt[h, wire.size]; h.wire _ wire; WriteProperties[h, wire.properties]; FOR w: NAT IN [0 .. wire.size) DO WriteWire[h, wireIDTab, wire[w]]; ENDLOOP; h.wire _ parentWire; } ELSE WriteID[h, wireID]; }; ReadWire: PUBLIC PROC [h: Handle, wireIDTab: RefTab.Ref] RETURNS [wire: Core.Wire] = { wireID: ROPE _ ReadID[h]; IF Rope.Fetch[wireID]#'W THEN ERROR; wire _ NARROW[RefTab.Fetch[wireIDTab, wireID].val]; IF wire=NIL THEN { parentWire: Core.Wire _ h.wire; wireSize: NAT _ ReadInt[h]; wire _ NEW[Core.WireRec[wireSize]]; IF NOT RefTab.Insert[wireIDTab, wireID, wire] THEN ERROR; h.wire _ wire; wire.properties _ ReadProperties[h]; FOR w: NAT IN [0 .. wire.size) DO wire[w] _ ReadWire[h, wireIDTab]; ENDLOOP; h.wire _ parentWire; }; }; WriteProperties: PUBLIC PROC [h: Handle, properties: Core.Properties] = { propCount: INT _ 0; CedarProcess.CheckAbort[]; FOR props: Core.Properties _ properties, props.rest UNTIL props=NIL DO propKey: ATOM _ NARROW[props.first.key]; propVal: REF ANY _ props.first.val; propWrite: REF PropWriteProc _ NARROW[CoreProperties.GetProp[from: CoreProperties.FetchProperties[propKey], prop: coreWriteProcProp]]; IF propWrite#NIL OR ISTYPE[propVal, ROPE] OR ISTYPE[propVal, LIST OF ROPE] OR ISTYPE[propVal, REF INT] OR ISTYPE[propVal, REF NAT] OR ISTYPE[propVal, ATOM] OR ISTYPE[propVal, REF REAL] OR ISTYPE[propVal, REF BOOL] THEN propCount _ propCount + 1; ENDLOOP; WriteInt[h, propCount]; FOR props: Core.Properties _ properties, props.rest UNTIL props=NIL DO StartProp: PROC [type: ROPE] = { WriteAtom[h, propKey]; IF type#NIL THEN WriteID[h, type]; }; propKey: ATOM _ NARROW[props.first.key]; propWrite: REF PropWriteProc _ NARROW[CoreProperties.GetProp[from: CoreProperties.FetchProperties[propKey], prop: coreWriteProcProp]]; IF propWrite=NIL THEN WITH props.first.val SELECT FROM r: ROPE => {StartProp["r"]; WriteRope[h, r]}; lor: LIST OF ROPE => {StartProp["lor"]; WriteListOfRope[h, lor]}; i: REF INT => {StartProp["i"]; WriteInt[h, i^]}; n: REF NAT => {StartProp["n"]; WriteInt[h, n^]}; a: ATOM => {StartProp["a"]; WriteAtom[h, a]}; real: REF REAL => {StartProp["real"]; WriteReal[h, real^]}; rb: REF BOOL => {StartProp["rb"]; WriteBool[h, rb^]}; ENDCASE => SIGNAL UnknownProperty[propKey] ELSE {StartProp[NIL]; propWrite^[h, propKey, props.first.val]}; ENDLOOP; }; ReadProperties: PUBLIC PROC [h: Handle] RETURNS [properties: Core.Properties _ NIL] = { propCount: INT _ ReadInt[h]; CedarProcess.CheckAbort[]; FOR c: INT IN [0..propCount) DO key: ATOM _ ReadAtom[h]; val: REF ANY; propRead: REF PropReadProc _ NARROW[CoreProperties.GetProp[from: CoreProperties.FetchProperties[key], prop: coreReadProcProp]]; IF propRead=NIL THEN { type: ROPE _ ReadID[h]; val _ SELECT TRUE FROM Rope.Equal["r", type] => ReadRope[h], Rope.Equal["lor", type] => ReadListOfRope[h], Rope.Equal["i", type] => NEW[INT _ ReadInt[h]], Rope.Equal["n", type] => NEW[NAT _ ReadInt[h]], Rope.Equal["a", type] => ReadAtom[h], Rope.Equal["real", type] => NEW[REAL _ ReadReal[h]], Rope.Equal["rb", type] => NEW[BOOL _ ReadBool[h]], ENDCASE => ERROR UnknownProperty[Atom.MakeAtom[type]]; } ELSE val _ propRead^[h, key]; properties _ CONS [[key, val], properties]; ENDLOOP; }; WriteID: PUBLIC PROC [h: Handle, id: ROPE] = { IO.PutRope[h.stream, id]; PutSpace[h]; }; ReadID: PUBLIC PROC [h: Handle] RETURNS [id: ROPE] = { id _ IO.GetID[h.stream]; }; WriteAtom: PUBLIC PROC [h: Handle, atom: ATOM] = { atomID: ROPE _ NARROW[RefTab.Fetch[h.atomIDTab, atom].val]; IF atomID=NIL THEN { atomID _ Rope.Cat["A", Convert.RopeFromInt[from: RefTab.GetSize[h.atomIDTab], base: 16, showRadix: FALSE]]; IF NOT RefTab.Insert[h.atomIDTab, atom, atomID] THEN ERROR; WriteID[h, atomID]; IO.Put1[h.stream, IO.atom[atom]]; PutSpace[h]; } ELSE WriteID[h, atomID]; }; ReadAtom: PUBLIC PROC [h: Handle] RETURNS [atom: ATOM] = { atomID: ROPE _ ReadID[h]; IF Rope.Fetch[atomID]#'A THEN ERROR; atom _ NARROW[RefTab.Fetch[h.atomIDTab, atomID].val]; IF atom=NIL THEN { atom _ IO.GetAtom[h.stream]; IF NOT RefTab.Insert[h.atomIDTab, atomID, atom] THEN ERROR; }; }; doubleQuote: CHAR = '"; backSlash: CHAR = '\\; doubleQuoteRope: ROPE = Rope.FromChar[doubleQuote]; WriteRope: PUBLIC PROC [h: Handle, rope: ROPE] = { ropeID: ROPE _ NARROW[RefTab.Fetch[h.ropeIDTab, rope].val]; IF ropeID=NIL THEN { ropeID _ Rope.Cat["R", Convert.RopeFromInt[from: RefTab.GetSize[h.ropeIDTab], base: 16, showRadix: FALSE]]; IF NOT RefTab.Insert[h.ropeIDTab, rope, ropeID] THEN ERROR; WriteID[h, ropeID]; IO.PutChar[h.stream, doubleQuote]; <> WHILE NOT Rope.IsEmpty[rope] DO index: INT _ Rope.Find[rope, doubleQuoteRope]; IF index<0 THEN {IO.PutRope[h.stream, rope]; rope _ NIL} ELSE { IO.PutRope[h.stream, rope, 0, index]; IO.PutChar[h.stream, backSlash]; IO.PutChar[h.stream, doubleQuote]; rope _ Rope.Substr[rope, index+1]; }; ENDLOOP; IO.PutChar[h.stream, doubleQuote]; PutSpace[h]; } ELSE WriteID[h, ropeID]; }; ReadRope: PUBLIC PROC [h: Handle] RETURNS [rope: ROPE] = { ropeID: ROPE _ ReadID[h]; IF Rope.Fetch[ropeID]#'R THEN ERROR; rope _ NARROW[RefTab.Fetch[h.ropeIDTab, ropeID].val]; IF rope=NIL THEN { rope _ IO.GetRopeLiteral[h.stream]; IF NOT RefTab.Insert[h.ropeIDTab, ropeID, rope] THEN ERROR; }; }; WriteListOfRope: PUBLIC PROC [h: Handle, ropes: LIST OF ROPE] = { count: INT _ 0; FOR rl: LIST OF ROPE _ ropes, rl.rest UNTIL rl=NIL DO count _ count + 1; ENDLOOP; WriteInt[h, count]; FOR rl: LIST OF ROPE _ ropes, rl.rest UNTIL rl=NIL DO WriteRope[h, rl.first]; ENDLOOP; }; ReadListOfRope: PUBLIC PROC [h: Handle] RETURNS [ropes: LIST OF ROPE] = { count: INT _ ReadInt[h]; lor: LIST OF ROPE _ NIL; FOR c: INT IN [0..count) DO lor _ CONS[ReadRope[h], lor]; ENDLOOP; FOR rl: LIST OF ROPE _ lor, rl.rest UNTIL rl=NIL DO ropes _ CONS[rl.first, ropes]; ENDLOOP; }; WriteInt: PUBLIC PROC [h: Handle, int: INT] = { <> IO.Put1[h.stream, IO.int[int]]; PutSpace[h]; }; ReadInt: PUBLIC PROC [h: Handle] RETURNS [int: INT] = { int _ IO.GetInt[h.stream]; }; WriteReal: PUBLIC PROC [h: Handle, real: REAL] = { IO.Put1[h.stream, IO.real[real]]; PutSpace[h]; }; ReadReal: PUBLIC PROC [h: Handle] RETURNS [real: REAL] = { real _ IO.GetReal[h.stream]; }; WriteBool: PUBLIC PROC [h: Handle, bool: BOOL] = { WriteInt[h, IF bool THEN 1 ELSE 0]; }; ReadBool: PUBLIC PROC [h: Handle] RETURNS [bool: BOOL] = { bool _ ReadInt[h]#0; }; WriteHashTable: PUBLIC PROC [h: Handle, table: RefTab.Ref, eachPair: HashWriteProc] = { HashPair: RefTab.EachPairAction = { eachPair[h, key, val]; }; WriteInt[h, RefTab.GetSize[table]]; IF RefTab.Pairs[table, HashPair] THEN ERROR; }; ReadHashTable: PUBLIC PROC [h: Handle, eachPair: HashReadProc, equal: RefTab.EqualProc _ NIL, hash: RefTab.HashProc _ NIL] RETURNS [table: RefTab.Ref] = { table _ RefTab.Create[equal: equal, hash: hash]; THROUGH [1..ReadInt[h]] DO key, value: REF ANY _ NIL; [key, value] _ eachPair[h]; IF NOT RefTab.Insert[table, key, value] THEN ERROR; ENDLOOP; }; WriteCellTypeIDPair: PUBLIC HashWriteProc = { id: ROPE _ NARROW[key]; cellType: Core.CellType _ NARROW[value]; WriteID[h, id]; WriteCellType[h, cellType]; }; ReadCellTypeIDPair: PUBLIC HashReadProc = { key _ ReadID[h]; value _ ReadCellType[h]; }; WriteRopeIDPair: PUBLIC HashWriteProc = { id: ROPE _ NARROW[key]; rope: ROPE _ NARROW[value]; WriteID[h, id]; WriteRope[h, rope]; }; ReadRopeIDPair: PUBLIC HashReadProc = { key _ ReadID[h]; value _ ReadRope[h]; }; WriteAtomIDPair: PUBLIC HashWriteProc = { id: ROPE _ NARROW[key]; atom: ATOM _ NARROW[value]; WriteID[h, id]; WriteAtom[h, atom]; }; ReadAtomIDPair: PUBLIC HashReadProc = { key _ ReadID[h]; value _ ReadAtom[h]; }; <> WriteRecordCell: ClassWriteProc = { rct: CoreClasses.RecordCellType _ NARROW[cellType.data]; WriteInt[h, rct.size]; WriteWire[h, wireIDTab, rct.internal]; FOR in: NAT IN [0..rct.size) DO instance: CoreClasses.CellInstance _ rct[in]; WriteWire[h, wireIDTab, instance.actual]; WriteProperties[h, instance.properties]; WriteCellType[h, instance.type]; ENDLOOP; }; <<>> ReadRecordCell: ClassReadProc = { rct: CoreClasses.RecordCellType _ NEW[CoreClasses.RecordCellTypeRec[ReadInt[h]]]; rct.internal _ ReadWire[h, wireIDTab]; FOR in: NAT IN [0..rct.size) DO instance: CoreClasses.CellInstance _ NEW[CoreClasses.CellInstanceRec]; rct[in] _ instance; instance.actual _ ReadWire[h, wireIDTab]; instance.properties _ ReadProperties[h]; instance.type _ ReadCellType[h]; ENDLOOP; cellType.data _ rct; }; <<>> WriteTransistor: ClassWriteProc = { tran: CoreClasses.Transistor _ NARROW[cellType.data]; WriteID[h, CoreClasses.transistorTypeNames[tran.type]]; }; <<>> ReadTransistor: ClassReadProc = { tran: CoreClasses.Transistor _ NEW[CoreClasses.TransistorRec]; type: ROPE _ ReadID[h]; FOR t: CoreClasses.TransistorType IN CoreClasses.TransistorType DO IF Rope.Equal[CoreClasses.transistorTypeNames[t], type] THEN { tran.type _ t; EXIT; }; REPEAT FINISHED => ERROR; ENDLOOP; cellType.data _ tran; }; WriteUnspecified: ClassWriteProc = {}; <<>> ReadUnspecified: ClassReadProc = {cellType.data _ NIL}; <<>> WriteSequence: ClassWriteProc = { WriteSequenceSet: PROC [set: CoreClasses.SequenceSet] = { IF set=NIL THEN WriteInt[h, -1] ELSE { WriteInt[h, set.length]; FOR i: NAT IN [0..set.length) DO WriteInt[h, set[i]]; ENDLOOP; }; }; seq: CoreClasses.SequenceCellType _ NARROW[cellType.data]; WriteCellType[h, seq.base]; WriteInt[h, seq.count]; WriteSequenceSet[seq.sequence]; WriteSequenceSet[seq.flatSequence]; }; <<>> ReadSequence: ClassReadProc = { ReadSequenceSet: PROC RETURNS [set: CoreClasses.SequenceSet _ NIL] = { length: INT _ ReadInt[h]; IF length >= 0 THEN { set _ NEW[CoreClasses.SequenceSetRec[length]]; FOR i: NAT IN [0..set.length) DO set[i] _ ReadInt[h]; ENDLOOP; }; }; seq: CoreClasses.SequenceCellType _ NEW[CoreClasses.SequenceCellTypeRec]; seq.base _ ReadCellType[h]; seq.count _ ReadInt[h]; seq.sequence _ ReadSequenceSet[]; seq.flatSequence _ ReadSequenceSet[]; cellType.data _ seq; }; <> [] _ RegisterClass[CoreClasses.recordCellClass, WriteRecordCell, ReadRecordCell]; [] _ RegisterClass[CoreClasses.transistorCellClass, WriteTransistor, ReadTransistor]; [] _ RegisterClass[CoreClasses.unspecifiedCellClass, WriteUnspecified, ReadUnspecified]; [] _ RegisterClass[CoreClasses.sequenceCellClass, WriteSequence, ReadSequence]; [] _ RegisterClass[importCellClass, WriteImport, ReadImport]; calledFromDir _ NARROW[ProcessProps.GetProp[$WorkingDirectory]]; END. <> restoreProp: ATOM = $CoreRestoreCellType; CoreProperties.PutCellTypeProp[cellType, restoreProp, fileName]; WriteCellType: PUBLIC PROC [h: Handle, cellType: Core.CellType] = { cellTypeID: ROPE _ NARROW [RefTab.Fetch[h.cellTypeIDTab, cellType].val]; IF cellTypeID=NIL THEN { restoreFileName: ROPE _ NARROW[CoreProperties.GetCellTypeProp[cellType, restoreProp]]; IF restoreFileName=NIL THEN { parentCellType: Core.CellType _ h.cellType; wireIDTab: RefTab.Ref _ RefTab.Create[]; classWrite: REF ClassWriteProc _ NARROW[CoreProperties.GetCellClassProp[from: cellType.class, prop: coreWriteProcProp]]; IF classWrite=NIL THEN { SIGNAL UnknownCellClass[cellType.class]; cellType _ CoreOps.Recast[cellType]; IF cellType=NIL THEN ERROR; WriteCellType[h, cellType]; RETURN; }; cellTypeID _ Rope.Cat["C", Convert.RopeFromInt[from: RefTab.GetSize[h.cellTypeIDTab], base: 16, showRadix: FALSE]]; IF NOT RefTab.Insert[h.cellTypeIDTab, cellType, cellTypeID] THEN ERROR; h.cellType _ cellType; WriteID[h, cellTypeID]; WriteWire[h, wireIDTab, cellType.public]; WriteProperties[h, cellType.properties]; WriteRope[h, cellType.class.name]; classWrite^[h, cellType, wireIDTab]; h.cellType _ parentCellType; } ELSE { cellTypeID _ Rope.Cat["I", Convert.RopeFromInt[from: RefTab.GetSize[h.cellTypeIDTab], base: 16, showRadix: FALSE]]; IF NOT RefTab.Insert[h.cellTypeIDTab, cellType, cellTypeID] THEN ERROR; WriteID[h, cellTypeID]; WriteRope[h, restoreFileName]; }; } ELSE WriteID[h, cellTypeID]; }; ReadCellTypePublic: PUBLIC PROC [h: Handle] RETURNS [cellType: Core.CellType, wireIDTab: RefTab.Ref] = { cellTypeID: ROPE _ ReadID[h]; cellType _ NARROW[RefTab.Fetch[h.cellTypeIDTab, cellTypeID].val]; IF cellType=NIL THEN { SELECT Rope.Fetch[cellTypeID] FROM 'C => { cellType _ NEW[Core.CellTypeRec]; IF NOT RefTab.Insert[h.cellTypeIDTab, cellTypeID, cellType] THEN ERROR; h.cellType _ cellType; wireIDTab _ RefTab.Create[equal: RefTabExtras.EqualRope, hash: RefTabExtras.HashRope]; cellType.public _ ReadWire[h, wireIDTab]; cellType.properties _ ReadProperties[h]; }; 'I => cellType _ RestoreCellType[fileName: ReadRope[h]]; ENDCASE => ERROR; }; };