DIRECTORY Atom, Convert, Core, CoreClasses, CoreIO, CoreOps, CoreProperties, FS, HashTable, IO, Rope; CoreIOImpl: CEDAR PROGRAM IMPORTS Atom, Convert, CoreClasses, CoreOps, CoreProperties, FS, HashTable, IO, Rope EXPORTS CoreIO SHARES Core = BEGIN OPEN CoreIO; CoreWriteProcProp: ATOM = $CoreWriteProc; CoreReadProcProp: ATOM = $CoreReadProc; CoreIOInitProcProp: ATOM = $CoreIOInitProc; classRegistry: HashTable.Table _ HashTable.Create[equal: HashTable.RopeEqual, hash: HashTable.HashRope]; 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 => { FOR pl: LIST OF ATOM _ props, pl.rest UNTIL pl=NIL DO IF pl.first=propKey THEN EXIT; REPEAT FINISHED => props _ CONS[propKey, props]; ENDLOOP; RESUME; }; UnknownCellClass => { FOR cl: LIST OF Core.CellClass _ classes, cl.rest UNTIL cl=NIL DO IF cl.first=class THEN EXIT; REPEAT FINISHED => classes _ CONS[class, classes]; ENDLOOP; 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 _ HashTable.Create[]; h.ropeIDTab _ HashTable.Create[equal: HashTable.RopeEqual, hash: HashTable.HashRope]; h.atomIDTab _ HashTable.Create[]; WriteCellType[h, cellType]; IO.Close[h.stream]; }; 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.stream _ FS.StreamOpen[fileName]; h.cellTypeIDTab _ HashTable.Create[equal: HashTable.RopeEqual, hash: HashTable.HashRope]; h.ropeIDTab _ HashTable.Create[equal: HashTable.RopeEqual, hash: HashTable.HashRope]; h.atomIDTab _ HashTable.Create[equal: HashTable.RopeEqual, hash: HashTable.HashRope]; cellType _ ReadCellType[h]; IO.Close[h.stream]; }; RegisterClass: PUBLIC PROC [class: Core.CellClass, write: ClassWriteProc, read: ClassReadProc, init: IOInitProc _ NIL] RETURNS [sameClass: Core.CellClass] = { sameClass _ class; CoreProperties.PutCellClassProp[class, CoreWriteProcProp, NEW[ClassWriteProc _ write]]; CoreProperties.PutCellClassProp[class, CoreReadProcProp, NEW[ClassReadProc _ read]]; [] _ HashTable.Store[classRegistry, class.name, class]; IF init#NIL THEN ERROR; -- not implemented }; RegisterProperty: PUBLIC PROC [prop: ATOM, write: PropWriteProc, read: PropReadProc, init: IOInitProc _ NIL] 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; IF init#NIL THEN ERROR; -- not implemented }; WriteCellType: PUBLIC PROC [h: Handle, cellType: Core.CellType] = { cellTypeID: ROPE _ NARROW[HashTable.Fetch[h.cellTypeIDTab, cellType].value]; IF cellTypeID=NIL THEN { wireIDTab: HashTable.Table _ HashTable.Create[]; classWrite: REF ClassWriteProc _ NARROW[CoreProperties.GetCellClassProp[from: cellType.class, prop: CoreWriteProcProp]]; cellTypeID _ Rope.Cat["C", Convert.RopeFromInt[from: HashTable.GetSize[h.cellTypeIDTab], base: 16, showRadix: FALSE]]; IF NOT HashTable.Insert[h.cellTypeIDTab, cellType, cellTypeID] THEN ERROR; IF classWrite=NIL THEN { SIGNAL UnknownCellClass[cellType.class]; cellType _ CoreOps.ToBasic[cellType]; classWrite _ NARROW[CoreProperties.GetCellClassProp[from: cellType.class, prop: CoreWriteProcProp]]; IF classWrite=NIL THEN ERROR; }; WriteID[h, cellTypeID]; WriteWire[h, wireIDTab, cellType.public]; WriteProperties[h, cellType.properties]; WriteRope[h, cellType.class.name]; classWrite^[h, cellType, wireIDTab]; } ELSE WriteID[h, cellTypeID]; }; ReadCellType: PUBLIC PROC [h: Handle] RETURNS [cellType: Core.CellType] = { cellTypeID: ROPE _ ReadID[h]; IF Rope.Fetch[cellTypeID]#'C THEN ERROR; cellType _ NARROW[HashTable.Fetch[h.cellTypeIDTab, cellTypeID].value]; IF cellType=NIL THEN { wireIDTab: HashTable.Table _ HashTable.Create[equal: HashTable.RopeEqual, hash: HashTable.HashRope]; className: ROPE; classRead: REF ClassReadProc; cellType _ NEW[Core.CellTypeRec]; IF NOT HashTable.Insert[h.cellTypeIDTab, cellTypeID, cellType] THEN ERROR; cellType.public _ ReadWire[h, wireIDTab]; cellType.properties _ ReadProperties[h]; className _ ReadRope[h]; cellType.class _ NARROW[HashTable.Fetch[classRegistry, className].value]; classRead _ NARROW[CoreProperties.GetCellClassProp[from: cellType.class, prop: CoreReadProcProp]]; classRead^[h, cellType, wireIDTab]; }; }; WriteWire: PUBLIC PROC [h: Handle, wireIDTab: HashTable.Table, wire: Core.Wire] = { wireID: ROPE _ NARROW[HashTable.Fetch[wireIDTab, wire].value]; IF wireID=NIL THEN { wireID _ Rope.Cat["W", Convert.RopeFromInt[from: HashTable.GetSize[wireIDTab], base: 16, showRadix: FALSE]]; IF NOT HashTable.Insert[wireIDTab, wire, wireID] THEN ERROR; WriteID[h, wireID]; WriteInt[h, wire.size]; WriteProperties[h, wire.properties]; FOR w: NAT IN [0..wire.size) DO WriteWire[h, wireIDTab, wire[w]]; ENDLOOP; } ELSE WriteID[h, wireID]; }; ReadWire: PUBLIC PROC [h: Handle, wireIDTab: HashTable.Table] RETURNS [wire: Core.Wire] = { wireID: ROPE _ ReadID[h]; IF Rope.Fetch[wireID]#'W THEN ERROR; wire _ NARROW[HashTable.Fetch[wireIDTab, wireID].value]; IF wire=NIL THEN { wireSize: NAT _ ReadInt[h]; wire _ NEW[Core.WireRec[wireSize]]; IF NOT HashTable.Insert[wireIDTab, wireID, wire] THEN ERROR; wire.properties _ ReadProperties[h]; FOR w: NAT IN [0..wire.size) DO wire[w] _ ReadWire[h, wireIDTab]; ENDLOOP; }; }; WriteProperties: PUBLIC PROC [h: Handle, properties: Core.Properties] = { propCount: INT _ 0; 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] 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"]; IO.PutF[h.stream, "%g ", IO.int[i^]]}; n: REF NAT => {StartProp["n"]; IO.PutF[h.stream, "%g ", IO.int[n^]]}; a: ATOM => {StartProp["a"]; WriteAtom[h, a]}; 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]; 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 _ IO.GetInt[h.stream]], Rope.Equal["n", type] => NEW[NAT _ IO.GetInt[h.stream]], Rope.Equal["a", type] => ReadAtom[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]; IO.PutRope[h.stream, " "]; }; ReadID: PUBLIC PROC [h: Handle] RETURNS [id: ROPE] = { id _ IO.GetID[h.stream]; }; WriteAtom: PUBLIC PROC [h: Handle, atom: ATOM] = { atomID: ROPE _ NARROW[HashTable.Fetch[h.atomIDTab, atom].value]; IF atomID=NIL THEN { atomID _ Rope.Cat["A", Convert.RopeFromInt[from: HashTable.GetSize[h.atomIDTab], base: 16, showRadix: FALSE]]; IF NOT HashTable.Insert[h.atomIDTab, atom, atomID] THEN ERROR; WriteID[h, atomID]; IO.PutF[h.stream, "%g ", IO.atom[atom]]; } 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[HashTable.Fetch[h.atomIDTab, atomID].value]; IF atom=NIL THEN { atom _ IO.GetAtom[h.stream]; IF NOT HashTable.Insert[h.atomIDTab, atomID, atom] THEN ERROR; }; }; WriteRope: PUBLIC PROC [h: Handle, rope: ROPE] = { ropeID: ROPE _ NARROW[HashTable.Fetch[h.ropeIDTab, rope].value]; IF ropeID=NIL THEN { ropeID _ Rope.Cat["R", Convert.RopeFromInt[from: HashTable.GetSize[h.ropeIDTab], base: 16, showRadix: FALSE]]; IF NOT HashTable.Insert[h.ropeIDTab, rope, ropeID] THEN ERROR; WriteID[h, ropeID]; IO.PutRope[h.stream, "\""]; IO.PutRope[h.stream, rope]; -- cannot use IO.PutF that truncates long ropes! (BS) IO.PutRope[h.stream, "\" "]; } 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[HashTable.Fetch[h.ropeIDTab, ropeID].value]; IF rope=NIL THEN { rope _ IO.GetRopeLiteral[h.stream]; IF NOT HashTable.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, val: INT] = { IO.PutF[h.stream, "%g ", IO.int[val]]; }; ReadInt: PUBLIC PROC [h: Handle] RETURNS [int: INT] = { int _ IO.GetInt[h.stream]; }; 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]]; WriteInt[h, tran.length]; WriteInt[h, tran.width]; }; 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; tran.length _ ReadInt[h]; tran.width _ ReadInt[h]; cellType.data _ tran; }; [] _ RegisterClass[CoreClasses.recordCellClass, WriteRecordCell, ReadRecordCell]; [] _ RegisterClass[CoreClasses.transistorCellClass, WriteTransistor, ReadTransistor]; END. βCoreIOImpl.mesa Copyright c 1985 by Xerox Corporation. All rights reserved. Barth, May 23, 1986 9:20:31 am PDT Bertrand Serlet May 23, 1986 0:17:02 am PDT Cell Type IO IO Registration IO Utilities Cell Class IO Κ=– "cedar" style˜codešœ™Kšœ Οmœ1™˜>Kšœ9žœ˜UKšœ8žœ˜RKšœ,˜,Kšœ˜Kš žœžœžœžœ‘˜*Kšœ˜K˜——™ š  œžœžœ)˜CKšœ žœžœ3˜Lšžœ žœžœ˜Kšœ0˜0Kšœ žœžœQ˜xKšœnžœ˜vKšžœžœ9žœžœ˜Jšžœ žœžœž˜Kšžœ"˜(Kšœ%˜%Kšœ žœQ˜dKšžœ žœžœžœ˜K˜—Kšœ˜Kšœ)˜)Kšœ(˜(Kšœ"˜"Kšœ$˜$K˜—Kšžœ˜K˜K˜—š  œžœžœ žœ˜KKšœ žœ ˜Kšžœžœžœ˜(Kšœ žœ5˜Fšžœ žœžœ˜Kšœd˜dKšœ žœ˜Kšœ žœ˜Kšœ žœ˜!Kšžœžœ9žœžœ˜JKšœ)˜)Kšœ(˜(Kšœ˜Kšœžœ2˜IKšœ žœP˜bKšœ#˜#K˜—K˜K˜—š  œžœžœ=˜SKšœžœžœ)˜>šžœžœžœ˜Kšœdžœ˜lKšžœžœ+žœžœ˜Kšœ˜Kšžœžœ ˜(K˜—Kšžœ˜K˜K˜—š  œžœžœ žœžœ˜:Kšœžœ ˜Kšžœžœžœ˜$Kšœžœ-˜:šžœžœžœ˜Kšœžœ˜Kšžœžœ-žœžœ˜>K˜—K˜K˜—š  œžœžœžœ˜2Kšœžœžœ+˜@šžœžœžœ˜Kšœfžœ˜nKšžœžœ-žœžœ˜>Kšœ˜Kšžœ˜Kšžœ‘5˜QKšžœ˜K˜—Kšžœ˜K˜K˜—š  œžœžœ žœžœ˜:Kšœžœ ˜Kšžœžœžœ˜$Kšœžœ-˜:šžœžœžœ˜Kšœžœ˜#Kšžœžœ-žœžœ˜>K˜—K˜K˜—š œžœžœž œ˜AKšœžœ˜š žœžœžœžœžœžœž˜5Kšœ˜Kšžœ˜—Kšœ˜š žœžœžœžœžœžœž˜5Kšœ˜Kšžœ˜—K˜K˜—š  œžœžœ žœ ž œ˜IKšœžœ˜Kš œžœžœžœžœ˜šžœžœžœ ž˜Kšœžœ˜Kšžœ˜—š žœžœžœžœžœžœž˜3Kšœžœ˜Kšžœ˜—K˜K˜—š œžœžœžœ˜/Kšžœžœ ˜&K˜K˜—š  œžœžœ žœžœ˜7Kšœžœ˜K˜K˜——™ š œ˜#Kšœ"žœ˜8K˜Kšœ&˜&šžœžœžœž˜Kšœ-˜-Kšœ)˜)Kšœ(˜(K˜ Kšžœ˜—K˜K™—š œ˜!Kšœ"žœ,˜QKšœ&˜&šžœžœžœž˜Kšœ%žœ˜FKšœ˜Kšœ*˜*Kšœ(˜(Kšœ ˜ Kšžœ˜—Kšœ˜K˜K™—š œ˜#Kšœžœ˜5Kšœ7˜7Kšœ˜Kšœ˜K˜K™—š œ˜!Kšœžœ˜>Kšœžœ ˜šžœžœž˜Bšžœ6žœ˜>K˜Kšžœ˜K˜—Kšžœžœžœ˜Kšžœ˜—Kšœ˜Kšœ˜Kšœ˜K˜K™——KšœQ˜QKšœU˜UK˜Kšžœ˜—…—/^?}