<> <> <> <> <<>> DIRECTORY Convert, Core, CoreClasses, CoreOps, FS, RefTab, IO, Rope, ScaldIO; ScaldIOImpl: CEDAR PROGRAM IMPORTS Convert, CoreClasses, CoreOps, FS, RefTab, IO, Rope EXPORTS ScaldIO = BEGIN OPEN ScaldIO; ROPE: TYPE = Core.ROPE; Handle: TYPE = REF HandleRec; HandleRec: TYPE = RECORD[ stream: Core.STREAM _ NIL, cellTypeInfoTab: RefTab.Ref _ NIL, cellID: NAT _ 0]; <<>> CellTypeInfo: TYPE = REF CellTypeInfoRec; CellTypeInfoRec: TYPE = RECORD[ name: ROPE _ NIL, written: BOOL _ FALSE]; <<>> SaveCellType: PUBLIC PROC [cellType: Core.CellType, fileName: ROPE _ NIL] = { h: Handle _ NEW[HandleRec]; cellType _ CoreOps.ToBasic[cellType]; IF fileName=NIL THEN fileName _ Rope.Cat[CoreOps.GetCellTypeName[cellType], ".scald"]; h.stream _ FS.StreamOpen[fileName, $create]; h.cellTypeInfoTab _ RefTab.Create[]; WriteCellType[h, cellType]; IO.Close[h.stream]; }; <<>> WriteCellType: PUBLIC PROC [h: Handle, cellType: Core.CellType] = { cellTypeInfo: CellTypeInfo; cellType _ CoreOps.ToBasic[cellType]; cellTypeInfo _ NARROW[RefTab.Fetch[h.cellTypeInfoTab, cellType].val]; IF cellTypeInfo=NIL OR NOT cellTypeInfo.written THEN { RemoveDots: PROC [old: ROPE] RETURNS [new: ROPE] = { pos: INT; new _ old; WHILE (pos _ Rope.Find[new, "."])>-1 DO new _ Rope.Replace[base: new, start: pos, len: 1, with: "x"]; ENDLOOP; }; GenInfo: PROC [cellType: Core.CellType] RETURNS [cellTypeInfo: CellTypeInfo] = { cellTypeID: ROPE _ Rope.Cat["Cell", Convert.RopeFromCard[from: h.cellID, showRadix: FALSE]]; h.cellID _ h.cellID + 1; cellType _ CoreOps.ToBasic[cellType]; cellTypeID _ Rope.Cat[cellTypeID, RemoveDots[CoreOps.GetCellTypeName[cellType]]]; cellTypeInfo _ NEW[CellTypeInfoRec]; cellTypeInfo.name _ cellTypeID; IF NOT RefTab.Insert[h.cellTypeInfoTab, cellType, cellTypeInfo] THEN ERROR; }; IF cellTypeInfo=NIL THEN cellTypeInfo _ GenInfo[cellType]; cellTypeInfo.written _ TRUE; SELECT cellType.class FROM CoreClasses.transistorCellClass => NULL; CoreClasses.recordCellClass => { WritePublic: PROC [publicWire: Core.Wire, name: ROPE] = { IF publicWire.size=0 THEN { IF wireCount=0 THEN IO.PutRope[h.stream, "PARAMETER = "] ELSE IO.PutRope[h.stream, ", "]; IO.PutRope[h.stream, name]; IF NOT RefTab.Insert[wireIDTab, publicWire, name] THEN ERROR; wireCount _ wireCount+1; } ELSE FOR i: NAT IN [0..publicWire.size) DO subWire: Core.Wire _ publicWire[i]; subName: ROPE _ PublicName[subWire, name, i]; WritePublic[subWire, subName]; ENDLOOP; }; PublicName: PROC [publicWire: Core.Wire, prefix: ROPE, index: NAT] RETURNS [name: ROPE] = { name _ CoreOps.GetShortWireName[publicWire]; IF name=NIL THEN name _ Convert.RopeFromCard[from: index, showRadix: FALSE]; name _ Rope.Cat[prefix, "x", name]; }; WriteBind: PROC [actual, public: Core.Wire, publicName: ROPE] = { IF actual.size>0 THEN FOR i: NAT IN [0..actual.size) DO WriteBind[actual[i], public[i], PublicName[public[i], publicName, i]]; ENDLOOP ELSE { actualName: ROPE _ NARROW[RefTab.Fetch[wireIDTab, actual].val]; IF wireCount>0 THEN IO.PutRope[h.stream, ", "]; IO.PutRope[h.stream, publicName]; IO.PutRope[h.stream, "="]; IF actualName=NIL THEN { actualName _ Rope.Cat["NUL%", Convert.RopeFromCard[from: idCount, showRadix: FALSE]]; idCount _ idCount + 1; IF NOT RefTab.Insert[wireIDTab, actual, actualName] THEN ERROR; }; IO.PutRope[h.stream, actualName]; wireCount _ wireCount+1; }; }; wireIDTab: RefTab.Ref _ RefTab.Create[]; wireCount: NAT _ 0; idCount: NAT _ 0; rct: CoreClasses.RecordCellType _ NARROW[cellType.data]; IO.PutRope[h.stream, "\nMNAME = "]; IO.PutRope[h.stream, cellTypeInfo.name]; IO.PutRope[h.stream, ";\n"]; FOR i: NAT IN [0..cellType.public.size) DO subWire: Core.Wire _ cellType.public[i]; WritePublic[subWire, PublicName[subWire, NIL, i]]; ENDLOOP; IF wireCount>0 THEN IO.PutRope[h.stream, ";\n"]; FOR instance: NAT IN [0..rct.size) DO subType: Core.CellType _ rct[instance].type; subName: ROPE; SELECT subType.class FROM CoreClasses.transistorCellClass => { tran: CoreClasses.Transistor _ NARROW[subType.data]; subName _ CoreClasses.transistorTypeNames[tran.type]; }; CoreClasses.recordCellClass => { subInfo: CellTypeInfo _ NARROW[RefTab.Fetch[h.cellTypeInfoTab, subType].val]; IF subInfo=NIL THEN subInfo _ GenInfo[subType]; subName _ subInfo.name; }; ENDCASE => ERROR; IO.PutRope[h.stream, subName]; wireCount _ 0; IO.PutRope[h.stream, "("]; WriteBind[rct[instance].actual, subType.public, NIL]; IO.PutRope[h.stream, ");\n"]; ENDLOOP; IO.PutRope[h.stream, "END;\n"]; FOR instance: NAT IN [0..rct.size) DO WriteCellType[h, rct[instance].type]; ENDLOOP; }; ENDCASE => ERROR; }; }; END.