LichenKeyImpl.Mesa
Last tweaked by Mike Spreitzer on May 6, 1989 9:08:23 am PDT
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.STREAMNIL;
d: Design ← NIL;
at: INTINT.FIRST;
doing: BOOLFALSE;
allocd: INT ← SafeStorage.NWordsAllocated[];
recld: INT ← SafeStorage.NWordsReclaimed[];
phaseSecs, totSecs: ARRAY StepKind OF INTALL[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 b err msg--;
[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.