<> <> DIRECTORY AbSets, Atom, BasicTime, BiRels, CedarProcess, CoreFiddling, FS, FunsimToCore, IO, IOClasses, Lichen, LichenDataOps, LichenDataStructure, LichenFiling, LichenFlatPrivate, LichenFromCore, LichenFromExt, LichenPrinting, Rope, SafeStorage, SetBasics, TiogaMenuOps, ViewerIO; LichenKeyImpl: CEDAR PROGRAM IMPORTS AbSets, Atom, BasicTime, BiRels, CedarProcess, CoreFiddling, FS, FunsimToCore, IO, IOClasses, LichenDataOps, LichenDataStructure, LichenFiling, LichenFlatPrivate, LichenFromCore, LichenFromExt, LichenPrinting, Rope, SafeStorage, SetBasics, TiogaMenuOps, ViewerIO EXPORTS Lichen = BEGIN OPEN Sets:AbSets, Lichen, LichenDataStructure, LDO:LichenDataOps; StepKind: TYPE ~ {work, io}; Do: PUBLIC PROC [prefix, suffix: ROPE, Key: KeyProc, from, to: INT, startD: Design _ NIL] RETURNS [Design] ~ { dName: ROPE ~ prefix.Concat[suffix]; logScript: IO.STREAM ~ ViewerIO.CreateViewerStreams[dName].out; logFile, log: IO.STREAM _ NIL; d: Design _ NIL; at: INT _ INT.FIRST; doing: BOOL _ FALSE; allocd: INT _ SafeStorage.NWordsAllocated[]; recld: INT _ SafeStorage.NWordsReclaimed[]; phaseSecs, totSecs: ARRAY StepKind OF INT _ ALL[0]; At: PROC [i: INT] ~ { toDo: BOOL ~ i IN [from .. to); CheckStep: PROC ~ {LDO.CheckDesign[d]}; PrettyPrintStep: PROC ~ { rootName: ROPE ~ IO.PutFR["%g/%g.d%d", [rope[dName]], [rope[Describe[d, d.root, d]]], [integer[i]]]; LichenPrinting.PrintDesignOnFiles[d: d, fnPrefix: dName, fnSuffix: IO.PutFR["d%d", [integer[i]]], pacify: log]; [] _ TiogaMenuOps.Open[rootName]; RETURN}; WriteStep: PROC ~ { binName: ROPE ~ IO.PutFR["%g.des%d", [rope[dName]], [integer[i]]]; fullBin: ROPE; binBytes: INT; binCreated: BasicTime.GMT; [] _ LichenFiling.WriteDesign[binName, d, log]; [fullBin,,,binBytes,binCreated,] _ FS.FileInfo[binName]; log.PutF["%g %g %g\n", [rope[fullBin]], [integer[binBytes]], [time[binCreated]]]; }; at _ i; IF doing THEN { DoStep[io, IO.PutFR["Check at point %g", [integer[i]]], CheckStep]; IF i>0 THEN DoStep[io, IO.PutFR["PrettyPrint at point %g", [integer[i]]], PrettyPrintStep]; DoStep[io, IO.PutFR["Write at point %g", [integer[i]]], WriteStep]; FOR kind: StepKind IN StepKind DO totSecs[kind] _ totSecs[kind] + phaseSecs[kind] ENDLOOP; log.PutF["Phase %d took %d work & %d I/O seconds; totals are now %d & %d\n", [integer[i]], [integer[phaseSecs[work]]], [integer[phaseSecs[io]]], [integer[totSecs[work]]], [integer[totSecs[io]]]]; phaseSecs _ ALL[0]; logFile.Close[]; logFile _ NIL; logScript.PutRope["\n"]; }; IF toDo THEN { logFile _ FS.StreamOpen[fileName: IO.PutFR["log-%g-%d.txt", [rope[dName]], [integer[i+1]]], accessOptions: create, keep: 10]; log _ IOClasses.CreateDribbleOutputStream[logFile, logScript]; }; IF doing = toDo THEN RETURN; doing _ toDo; IF NOT doing THEN RETURN; IF i >= 0 THEN IF startD=NIL THEN { file: ROPE ~ IO.PutFR["%g.des%d", [rope[dName]], [integer[i]]]; ReadStep: PROC ~ { d _ LichenFiling.ReadDesign[file, log]; Atom.PutProp[$d, $d, d]}; DoStep[io, Rope.Cat["Read ", file], ReadStep]; DoStep[io, "Check after read", CheckStep]} ELSE { IF NOT startD.names.HasMemA[dName] THEN ERROR; d _ startD; log.PutRope["Starting with given design "]; startD.names.PrintSet[log]; log.PutRope["\n"]} ELSE IF startD#NIL THEN ERROR; RETURN}; DoStep: PROC [kind: StepKind, descr: ROPE, Step: PROC] ~ {IF doing THEN { log.PutF["\n%g starting at %g\n", [rope[descr]], [time[BasicTime.Now[]]]]; log.Flush[]; SafeStorage.ReclaimCollectibleObjects[]; {am: INT ~ SafeStorage.NWordsAllocated[]; rm: INT ~ SafeStorage.NWordsReclaimed[]; tm: BasicTime.GMT ~ BasicTime.Now[]; Step[ !ABORTED => log.PutF["ABORTED at %g\n", [time[BasicTime.Now[]]]] ]; SafeStorage.ReclaimCollectibleObjects[]; {af: INT ~ SafeStorage.NWordsAllocated[]; rf: INT ~ SafeStorage.NWordsReclaimed[]; tf: BasicTime.GMT ~ BasicTime.Now[]; secs: INT ~ BasicTime.Period[tm, tf]; log.PutFL["%g %gs (%g+%g=%g) - (%g+%g=%g) = %g+%g = %g\n", LIST[ [rope[descr]], [integer[secs]], [integer[am-allocd]], [integer[af-am]], [integer[af-allocd]], [integer[rm-recld]], [integer[rf-rm]], [integer[rf-recld]], [integer[am-allocd-(rm-recld)]], [integer[af-am-(rf-rm)]], [integer[af-allocd-(rf-recld)]] ]]; allocd _ af; recld _ rf; phaseSecs[kind] _ phaseSecs[kind] + secs}}}; RETURN}; ReadExt: PROC [rootCellFileName, clippingFileName: ROPE, readPorts: BOOL, labelCellTypes: REF ANY] ~ { ReadExtStep: PROC ~ { d _ LichenFromExt.ReadDesign[rootCellFileName, IF readPorts THEN readPorts ELSE none, NIL, clippingFileName]; Atom.PutProp[$d, $d, d]; {labCells: Set--of CellType-- ~ ToTSet[labelCellTypes]; [] _ d.labelCellTypes.AddSet[labCells]; LDO.CheckDesign[d]; RETURN}}; DoStep[io, "ReadExt", ReadExtStep]}; ExtractPads: PROC ~ { ExtractPadsStep: PROC ~ { exCells: BiRel; newPorts: Set; [exCells, newPorts] _ LDO.ExtractPads[d, log]; log.PutRope["exCells="]; exCells.PrintBiRel[log]; log.PutRope["\nnewPorts="]; newPorts.PrintSet[log]; log.PutRope["\n"]}; DoStep[work, "ExtractPads", ExtractPadsStep]}; ReadPorts: PROC [fileName: ROPE] ~ { ReadPortsStep: PROC ~ { found: BOOL; names: Set--of SteppyName--; [found, names] _ ReadSteppyNameSet[fileName]; IF NOT found THEN log.PutF["File %g not found.\n", [rope[fileName]]] ELSE [] _ LDO.ExtractNamed[d.root, names]; RETURN}; DoStep[work, "ReadPorts", ReadPortsStep]}; ReadFunsim: PROC [rootName: ROPE] ~ { ReadFunsimStep: PROC ~ { rt: FunsimToCore.Table; cs: FunsimToCore.Counts; CoreFiddling.log _ log; [rt, cs] _ FunsimToCore.Convert[rootName.Concat["-Funsim.str"]]; CoreFiddling.SortPublics[rt]; CoreFiddling.PrintCellTypeGraph[log, FunsimToCore.callOrder]; CoreFiddling.PrintCellInstanceGraph[log, FunsimToCore.callOrder]; CoreFiddling.PrintCellTypes[log, FunsimToCore.callOrder]; d _ LichenFromCore.GetDesign[rt, rootName, "-f", log]; Atom.PutProp[$d, $d, d]; LDO.CheckDesign[d]; RETURN}; DoStep[io, "ReadFunsim", ReadFunsimStep]}; RipoutTransistors: PROC [inA: REF ANY] ~ { RipoutTransistorsStep: PROC ~ { xstrs: Set ~ d.ciType.Image[d.transistorCellTypes, rightToLeft]; in: CellType ~ ToT[inA]; goners: Set ~ in.Subcells[].Intersection[xstrs].CreateHashCopy[]; [] _ LDO.DeleteInsts[d, goners, TRUE, FALSE, log]}; DoStep[work, "RipoutTransistors", RipoutTransistorsStep]}; RipoutInsts: PROC [parentA, cisA: REF ANY] ~ { RipoutInstsStep: PROC ~ { parent: CellType ~ ToT[parentA]; cis: Set ~ TopISet[parent, cisA]; [] _ LDO.DeleteInsts[d, cis, TRUE, TRUE, log]}; DoStep[work, "RipoutInsts", RipoutInstsStep]}; MergeWireKludge: PROC [wiresA: REF ANY] ~ { MergeWireKludgeStep: PROC ~ { wires: Set ~ TopWSet[d.root, wiresA]; ports: Set ~ d.root.asu.exports.Image[wires, rightToLeft].CreateHashCopy[]; [] _ LDO.MergeWireSet[d, wires, TRUE]; IF ports.NonTrivial[] THEN [] _ LDO.MergePorts[d.root, ports]; RETURN}; DoStep[work, "MergeWireKludge", MergeWireKludgeStep]}; ExternallyMerged: PROC [portsA: REF ANY] ~ { ExternallyMergedStep: PROC ~ { ports: Set ~ TopPSet[d.root, portsA].CreateHashCopy[]; wires: Set ~ d.root.asu.exports.Image[ports].CreateHashCopy[]; IF NOT ports.Size[] = wires.Size[] THEN ERROR; [] _ LDO.MergeWireSet[d, wires, TRUE]; [] _ LDO.MergePorts[d.root, ports]}; DoStep[work, "ExternallyMerged", ExternallyMergedStep]}; UndistinguishPorts: PROC ~ { UndistinguishPortsStep: PROC ~ {[] _ LDO.UndistinguishPorts[d, log]}; DoStep[work, "UndistinguishPorts", UndistinguishPortsStep]}; ImportAtomicWireOnceToRoot: PROC [name: ROPE] RETURNS [internal: Wire _ NIL] ~ { ImportAtomicWireOnceToRootStep: PROC ~ { names: Set ~ OneSteppy[ParseSteppyName[name]]; internal _ LDO.CreateWire[d.root, names, FALSE, FALSE, FALSE, nilBiRel]; [] _ LDO.FullySfwdlyExportWires[d.root, Sets.CreateSingleA[internal, d.eSpace]]}; DoStep[work, "ImportAtomicWireOnceToRoot", ImportAtomicWireOnceToRootStep]}; ImportAtomicWireOnce: PROC [ctA, fromA: REF ANY] RETURNS [internal: Wire _ NIL] ~ { ImportAtomicWireOnceStep: PROC ~ { ct: CellType ~ ToT[ctA]; from: Wire ~ ToW[fromA]; internal _ LDO.ImportAtomicWireOnce[d, ct, from].internal}; DoStep[work, "ImportAtomicWireOnce", ImportAtomicWireOnceStep]}; ExportWires: PROC [ctA, wiresA: REF ANY] ~ { ExportWiresStep: PROC ~ { ct: CellType ~ ToT[ctA]; wires: Set ~ TopWSet[ct, wiresA]; [] _ LDO.FullySfwdlyExportWires[ct, wires]; RETURN}; DoStep[work, "ExportWires", ExportWiresStep]}; DeduceWireStructure: PROC ~ { DeduceWireStructureStep: PROC ~ {LDO.AddDeducedStructureToDesign[d, log]}; DoStep[work, "DeduceWireStructure", DeduceWireStructureStep]}; CleanupDesign: PROC ~ { CleanupDesignStep: PROC ~ {[] _ LDO.CleanDesign[d, log]}; DoStep[work, "CleanupDesign", CleanupDesignStep]}; Group: PROC [iName, tName: ROPE, parentA, sibsA: REF ANY] ~ { GroupStep: PROC ~ { [] _ LichenFlatPrivate.GroupInstancesToNewCT[d, TopISet[parentA, sibsA], iName, OneRope[tName]]; RETURN}; DoStep[work, "Group", GroupStep]}; ExpandInstance: PROC [instA: REF ANY] ~ { ExpandInstanceStep: PROC ~ { [] _ LDO.ExpandInstance[d, ToI[instA]]; }; DoStep[work, "ExpandInstance", ExpandInstanceStep]}; ExpandType: PROC [tName: ROPE] ~ { ExpandTypeStep: PROC ~ { [] _ LDO.ExpandType[d, ToT[tName]]; }; DoStep[work, "ExpandType", ExpandTypeStep]}; FlattenArrays: PROC ~ { FlattenArraysStep: PROC ~ { arrays: Set ~ d.arrayElt.SetOn[left].CreateHashCopy[]; dblArrays: Set ~ d.arrayElt.Image[arrays, rightToLeft].CreateHashCopy[]; oks: Set--of CellType--; errs: Fn--CellType [oks, errs] _ LDO.FlattenArrays[d, dblArrays, TRUE, log]; log.PutRope["OK: "]; oks.PrintSet[log]; log.PutRope[", errs: "]; errs.PrintBiRel[log]; log.PutRope["\n"]}; DoStep[work, "FlattenArrays", FlattenArraysStep]}; RaiseGCs: PROC [childA, gcsA: REF ANY] RETURNS [sibs: RefSet--of raised instances-- _ NIL] ~ { RaiseGCsStep: PROC ~ { gcs: Set ~ TopISet[childA, gcsA]; sibs _ LichenFlatPrivate.RaiseGCs[d, gcs].Refify}; DoStep[work, "RaiseGCs", RaiseGCsStep]}; LowerKidsOnce: PROC [parentA, kidsA, sibA: REF ANY] RETURNS [loweredKids: RefSet--of CellInstance-- _ NIL] ~ { LowerKidsOnceStep: PROC ~ { parent: CellType ~ ToT[parentA]; kids: Set ~ TopISet[parent, kidsA]; sib: CellInstance ~ TopI[parent, sibA]; loweredKids _ LichenFlatPrivate.LowerKidsOnce[d, kids, sib].Refify}; DoStep[work, "LowerKidsOnce", LowerKidsOnceStep]}; ShortenArrayInstance: PROC [inst: REF ANY, end: ArrayEnd, sDim: Dim3 _ Z, by: NAT _ 1] ~ { ShortenArrayInstanceStep: PROC ~ { LDO.ShortenArrayInstance[d, ToI[inst], end, sDim, by]; }; DoStep[work, "ShortenArrayInstance", ShortenArrayInstanceStep]}; LowerArrayStructure: PROC [outerA: REF ANY] ~ { LowerArrayStructureStep: PROC ~ {LDO.LowerArrayStructure[ToT[outerA]]}; DoStep[work, "LowerArrayStructure", LowerArrayStructureStep]}; SimilarizeArrays: PROC ~ { SimilarizeArraysStep: PROC ~ {[] _ LDO.SimilarizeArrays[d, d.cellTypes]}; DoStep[work, "SimilarizeArrays", SimilarizeArraysStep]}; PrefixifyDesign: PROC ~ { PrefixifyDesignStep: PROC ~ {LDO.PrefixifyDesign[d]}; DoStep[work, "PrefixifyDesign", PrefixifyDesignStep]}; InheritNames: PROC [renamesFileName: ROPE] ~ { InheritNamesStep: PROC ~ { renames: Fn; renamesCount: INT; [renames, renamesCount] _ LDO.ReadRenames[d, renamesFileName]; log.PutF["%g renaming statements read.\n", [integer[renamesCount]]]; LDO.InheritNames[d, TRUE, FALSE, renames]}; DoStep[work, "InheritNames", InheritNamesStep]}; CleanupNames: PROC ~ { CleanupNamesStep: PROC ~ {LDO.CleanupDesignNames[d]}; DoStep[work, "CleanupNames", CleanupNamesStep]}; DropPhysical: PROC ~ { DropPhysicalStep: PROC ~ {LDO.DropPhysical[d]}; DoStep[work, "DropPhysical", DropPhysicalStep]}; DeduceArrayness: PROC [ctsA: REF ANY] ~ { DeduceArraynessStep: PROC ~ {[] _ LDO.DeduceArrayness[d, ToTSet[ctsA], log]}; DoStep[work, "DeduceArrayness", DeduceArraynessStep]}; MinimizeArrayPeriods: PROC ~ { MinimizeArrayPeriodsStep: PROC ~ { arrays: Set ~ d.arrayElt.SetOn[left].CreateHashCopy[]; periods: Fn ~ LDO.MinimizeArraysPeriod[d, arrays, log]; periods.PrintBiRel[log]; log.PutRope["\n"]}; DoStep[work, "MinimizeArrayPeriods", MinimizeArrayPeriodsStep]}; Subcells: PROC [parentName: ROPE, instanceTypes, instanceNames: REF ANY] RETURNS [--constant--RefSet] ~ { IF doing THEN { parent: CellType ~ ToT[parentName]; cis: Set _ parent.CTParts[i]; IF instanceTypes#NIL THEN { icts: Set ~ ToTSet[instanceTypes]; x: Set ~ d.ciType.Image[icts, rightToLeft]; cis _ cis.Intersection[x]}; IF instanceNames#NIL THEN { x: Set ~ TopISet[parent, instanceNames]; cis _ cis.Intersection[x]}; RETURN [cis.CreateHashCopy[].Refify]} ELSE RETURN [NIL]}; ToTSet: PROC [ra: REF ANY] RETURNS [Set--of CellType--] ~ {WITH ra SELECT FROM ct: CellType => RETURN [Sets.CreateSingleA[ct, d.eSpace]]; rope: ROPE => RETURN d.ctName.Image[Sets.RopesMatching[[rope, TRUE, star]], rightToLeft]; x: REF READONLY TEXT => RETURN ToTSet[Rope.FromRefText[x]]; x: REF TEXT => RETURN ToTSet[Rope.FromRefText[x]]; x: RefSet => RETURN [x^]; x: LORA => { cts: Set ~ Sets.CreateHashSet[d.eSpace]; FOR y: LORA _ x, y.rest WHILE y#NIL DO sub: Set ~ ToTSet[y.first]; IF sub.Empty THEN ERROR; [] _ cts.AddSet[sub]; ENDLOOP; RETURN [cts]}; ENDCASE => ERROR}; ToT: PROC [ra: REF ANY] RETURNS [CellType] ~ { WITH ra SELECT FROM x: CellType => RETURN [x]; x: ROPE => RETURN [NARROW[d.ctName.InvApplyA[x].MA]]; x: REF READONLY TEXT => RETURN ToT[Rope.FromRefText[x]]; x: REF TEXT => RETURN ToT[Rope.FromRefText[x]]; ENDCASE => ERROR}; TopISet: PROC [parentA, ra: REF ANY] RETURNS [Set--of CellInstance--] ~ { parent: CellType ~ ToT[parentA]; WITH ra SELECT FROM x: ROPE => {sn: SteppyName ~ ParseSteppyName[x]; RETURN [parent.fullName[i].Mapping[sn.SnV, rightToLeft].CreateHashCopy]}; x: REF READONLY TEXT => RETURN TopISet[parent, Rope.FromRefText[x]]; x: REF TEXT => RETURN TopISet[parent, Rope.FromRefText[x]]; lora: LORA => { cis: Set ~ Sets.CreateHashSet[d.eSpace]; FOR l: LORA _ lora, l.rest WHILE l#NIL DO subs: Set ~ TopISet[parent, l.first]; IF subs.Empty THEN ERROR; [] _ cis.AddSet[subs]; ENDLOOP; RETURN [cis]}; x: RefSet => RETURN [x^]; ENDCASE => ERROR}; ToI: PROC [ra: REF ANY] RETURNS [CellInstance] ~ {WITH ra SELECT FROM x: CellInstance => RETURN [x]; x: ROPE => {path: SteppyName ~ ParseSteppyName[x]; tName: ROPE ~ NARROW[path.steps.first]; iName: SteppyName ~ path.SNTail; cct: CellType ~ ToT[tName]; RETURN [NARROW[cct.fullName[i].InvApply[SnV[iName]].MA]]}; x: REF READONLY TEXT => RETURN ToI[Rope.FromRefText[x]]; x: REF TEXT => RETURN ToI[Rope.FromRefText[x]]; ENDCASE => ERROR}; TopI: PROC [cct: CellType, ra: REF ANY] RETURNS [CellInstance] ~ {WITH ra SELECT FROM x: CellInstance => RETURN [x]; x: ROPE => {sn: SteppyName ~ ParseSteppyName[x]; RETURN [NARROW[cct.fullName[i].InvApply[SnV[sn]].MA]]}; x: REF READONLY TEXT => RETURN TopI[cct, Rope.FromRefText[x]]; x: REF TEXT => RETURN TopI[cct, Rope.FromRefText[x]]; ENDCASE => ERROR}; ToW: PROC [ra: REF ANY] RETURNS [Wire] ~ {WITH ra SELECT FROM x: Wire => RETURN [x]; x: ROPE => {path: SteppyName ~ ParseSteppyName[x]; tName: ROPE ~ NARROW[path.steps.first]; wName: SteppyName ~ path.SNTail; cct: CellType ~ ToT[tName]; RETURN [NARROW[cct.fullName[w].InvApply[SnV[wName]].MA]]}; x: REF READONLY TEXT => RETURN ToW[Rope.FromRefText[x]]; x: REF TEXT => RETURN ToW[Rope.FromRefText[x]]; ENDCASE => ERROR}; TopWSet: PROC [parentA, ra: REF ANY] RETURNS [Set--of Wire--] ~ { parent: CellType ~ ToT[parentA]; WITH ra SELECT FROM x: ROPE => {sn: SteppyName ~ ParseSteppyName[x]; RETURN [parent.fullName[w].Mapping[sn.SnV, rightToLeft].CreateHashCopy]}; x: REF READONLY TEXT => RETURN TopWSet[parent, Rope.FromRefText[x]]; x: REF TEXT => RETURN TopWSet[parent, Rope.FromRefText[x]]; lora: LORA => { ws: Set ~ Sets.CreateHashSet[d.eSpace]; FOR l: LORA _ lora, l.rest WHILE l#NIL DO subs: Set ~ TopWSet[parent, l.first]; IF subs.Empty THEN ERROR; [] _ ws.AddSet[subs]; ENDLOOP; RETURN [ws]}; x: RefSet => RETURN [x^]; ENDCASE => ERROR}; TopPSet: PROC [parentA, ra: REF ANY] RETURNS [Set--of Port--] ~ { parent: CellType ~ ToT[parentA]; WITH ra SELECT FROM x: ROPE => {sn: SteppyName ~ ParseSteppyName[x]; RETURN [parent.fullName[p].Mapping[sn.SnV, rightToLeft].CreateHashCopy]}; x: REF READONLY TEXT => RETURN TopPSet[parent, Rope.FromRefText[x]]; x: REF TEXT => RETURN TopPSet[parent, Rope.FromRefText[x]]; lora: LORA => { ps: Set ~ Sets.CreateHashSet[d.eSpace]; FOR l: LORA _ lora, l.rest WHILE l#NIL DO subs: Set ~ TopPSet[parent, l.first]; IF subs.Empty THEN ERROR; [] _ ps.AddSet[subs]; ENDLOOP; RETURN [ps]}; x: RefSet => RETURN [x^]; ENDCASE => ERROR}; Action: PROC ~ { ENABLE UNWIND => IF logFile#NIL THEN logFile.Close[]; At[-1]; Key[RipoutTransistors, RipoutInsts, MergeWireKludge, ExternallyMerged, UndistinguishPorts, ImportAtomicWireOnceToRoot, ImportAtomicWireOnce, ExportWires, DeduceWireStructure, CleanupDesign, Group, ExpandInstance, ExpandType, FlattenArrays, RaiseGCs, LowerKidsOnce, ShortenArrayInstance, LowerArrayStructure, SimilarizeArrays, PrefixifyDesign, InheritNames, CleanupNames, DropPhysical, DeduceArrayness, MinimizeArrayPeriods, Subcells, At, ReadExt, ExtractPads, ReadPorts, ReadFunsim]; RETURN}; CedarProcess.DoWithPriority[background, Action]; RETURN [d]}; END.