LichenFileOut.Mesa
Last tweaked by Mike Spreitzer on November 7, 1988 12:07:43 pm PST
DIRECTORY AbSets, BiRels, FS, IntStuff, IO, LichenDataOps, LichenDataStructure, LichenFromCore, LichenIntBasics, PBasics, Process, RefText, Rope, SetBasics;
LichenFileOut: CEDAR PROGRAM
IMPORTS AbSets, BiRels, FS, IntStuff, IO, LichenDataStructure, LichenFromCore, PBasics, Process, Rope, SetBasics
=
BEGIN OPEN IS:IntStuff, LIB:LichenIntBasics, LIB, LichenDataStructure, LichenDataOps, Sets:AbSets;
version: INTEGER ← 11;
CacheStats: TYPE ~ RECORD [probes, misses: INT ← 0];
firstNeg: BYTE ~ BYTE.LAST/2+1;
lastPos: BYTE ~ BYTE.LAST/2;
okOther: Set ~ Sets.CreateSingleA[LichenFromCore.implKey, SetBasics.reps];
WriteDesign: PROC [fileName: ROPE, d: Design, pacify: IO.STREAMNIL] RETURNS [refcs, ropecs, slcs: CacheStats ← []] ~ {
out: IO.STREAM ~ FS.StreamOpen[fileName: fileName, accessOptions: create, keep: 10];
refs: Seq ~ CreateSeq[len: d.cellTypes.Size.EN + d.parts.Size.EN, oneToOne: TRUE, dense: TRUE, rightSpace: d.eSpace];
ropes: Seq ~ CreateSeq[len: 1000, oneToOne: TRUE, dense: TRUE, rightSpace: SetBasics.ropes[TRUE]];
steplists: Seq ~ CreateSeq[len: 1000, oneToOne: TRUE, dense: TRUE, rightSpace: steplistSpace];
fullBuf: REF PBasics.FWORD ~ NEW [PBasics.FWORD];
maxRopeLen: INT ← -1;
cellTypeN: INT ← 0;
OutEnd: PROC ~ {
out.PutChar[VAL[lastPos]];
RETURN};
PutInt: PROC [v: Sets.Value] ~ {
f: PBasics.FWORD ~ PBasics.FFromInt32[v.VI];
Process.CheckForAbort[];
IF f.hi = [0, 0] AND f.lo.hi < lastPos OR f.hi = [BYTE.LAST, BYTE.LAST] AND f.lo.hi > firstNeg THEN {
out.PutChar[VAL[f.lo.hi]];
out.PutChar[VAL[f.lo.lo]];
}
ELSE {
out.PutChar[VAL[firstNeg]];
fullBuf^ ← f;
TRUSTED {out.UnsafePutBlock[[base: LOOPHOLE[fullBuf], count: BYTES[PBasics.FWORD]]]};
};
RETURN};
PutReal: PROC [r: REAL] ~ TRUSTED {
out.UnsafePutBlock[[base: @r, count: BYTES[REAL]]];
RETURN};
PutSet: PROC [set: Set, key: CHAR, PutElt: PROC [Sets.Value]] ~ {
out.PutChar[key];
pacify.PutChar[key];
set.Enumerate[PutElt];
OutEnd[];
RETURN};
PutSeq: PROC [seq: Seq, key: CHAR, PutElt: PROC [Sets.Value], pac: BOOLTRUE] ~ {
len: INT ~ seq.Size.EN;
i: INT ← 0;
PutPair: PROC [pair: BiRels.Pair] RETURNS [BOOL] ~ {
IF i # pair[left].VI THEN ERROR;
PutElt[pair[right]];
i ← i + 1;
RETURN [FALSE]};
out.PutChar[key];
IF pac THEN pacify.PutChar[key];
PutInt[[i: len]];
IF seq.Scan[PutPair, BiRels.leftFwd].found THEN ERROR;
IF i # len THEN ERROR;
OutEnd[];
RETURN};
PutBiRel: PROC [br: BiRel, key: CHAR, PutLeft, PutRight: PROC [Sets.Value], pac: BOOLTRUE] ~ {
PutPair: PROC [pair: BiRels.Pair] RETURNS [BOOL] ~ {
PutLeft[pair[left]];
PutRight[pair[right]];
RETURN [FALSE]};
out.PutChar[key];
IF pac THEN pacify.PutChar[key];
IF br.Scan[PutPair].found THEN ERROR;
OutEnd[];
RETURN};
PutNewIndex: PROC [v: Sets.Value] ~ {PutIndex[v, TRUE]};
PutOldIndex: PROC [v: Sets.Value] ~ {PutIndex[v, FALSE]};
PutIndex: PROC [v: Sets.Value, mayBeNew: BOOL] ~ {
mv: Sets.MaybeValue ~ refs.Lookup[goal: v, order: Sets.alleq];
idx: INT;
refcs.probes ← refcs.probes + 1;
IF mv.found THEN {
idx ← mv.MI + 1;
IF idx < 1 THEN ERROR}
ELSE {
IF NOT mayBeNew THEN ERROR;
idx ← refs.Size.EN;
IF idx < 0 THEN ERROR;
refcs.misses ← refcs.misses + 1;
IF refcs.misses # idx THEN ERROR;
refs.AddNewPair[[IV[idx], v]];
idx ← -(idx+1)};
PutInt[[i: idx]];
RETURN};
PutInt2: PROC [i2: Int2] ~ {
PutInt[[i:i2[X]]];
PutInt[[i:i2[Y]]];
RETURN};
PutRange2: PROC [r2: Range2] ~ {
PutInt2[[r2[X].min, r2[Y].min]];
PutInt2[[r2[X].maxPlusOne, r2[Y].maxPlusOne]];
RETURN};
PutRope: PROC [v: Sets.Value] ~ {
mv: Sets.MaybeValue ~ ropes.Lookup[goal: v, order: Sets.alleq];
idx: INT;
ropecs.probes ← ropecs.probes + 1;
IF mv.found THEN idx ← mv.MI ELSE {
idx ← ropes.Size.EN;
IF ropecs.misses # idx THEN ERROR;
ropecs.misses ← ropecs.misses + 1;
ropes.AddNewPair[[IV[idx], v]];
};
IF idx<0 THEN ERROR;
PutInt[[i:(1+idx) * (IF mv.found THEN 1 ELSE -1)]];
IF NOT mv.found THEN {
r: ROPE ~ NARROW[v.VA];
l: INT ~ r.Length;
maxRopeLen ← MAX[maxRopeLen, l];
PutInt[[i: l]];
out.PutRope[r]};
RETURN};
PutStepList: PROC [v: Sets.Value] ~ {
mv: Sets.MaybeValue ~ steplists.Lookup[goal: v, order: Sets.alleq];
idx: INT;
slcs.probes ← slcs.probes + 1;
IF mv.found THEN idx ← mv.MI ELSE {
idx ← steplists.Size.EN;
slcs.misses ← slcs.misses + 1;
IF slcs.misses # idx THEN ERROR;
steplists.AddNewPair[[IV[idx], v]];
};
IF idx<0 THEN ERROR;
IF mv.found THEN PutInt[[i: idx]] ELSE {
sl: NameStepList ~ NARROW[v.VA];
WITH sl.first SELECT FROM
x: ROPE => {PutInt[[i: (idx+1)*-2]]; PutRope[[x]]};
x: REF INT => {PutInt[[i: (idx+1)*-2 + 1]]; PutInt[[i:x^]]};
ENDCASE => ERROR;
PutStepList[[sl.rest]]};
RETURN};
PutSteppyName: PROC [snv: Sets.Value] ~ {
PutInt[[i:snv.i]];
PutStepList[[snv.ra]];
RETURN};
PutPAI: PROC [paiv: Sets.Value] ~ {
pai: PortAtIndex ~ VPai[paiv];
PutOldIndex[AV[pai.port]];
PutInt2[pai.ai];
RETURN};
PutStatVert: PROC [paiv: Sets.Value] ~ PutPAI;
PutSub: PROC [kidsv: Sets.Value] ~ {
kids: Seq ~ BiRels.VB[kidsv];
PutSeq[kids, 'O, PutOldIndex, FALSE];
RETURN};
PutCellTypeBBox: PROC [ctv: Sets.Value] ~ {
ct: CellType ~ NARROW[ctv.VA];
PutOldIndex[ctv];
PutRange2[ct.bbox];
RETURN};
PutCellTypeDetails: PROC [ctv: Sets.Value] ~ {
ct: CellType ~ NARROW[ctv.VA];
IF ct.other.SetOn[left].Difference[okOther].NonEmpty THEN ERROR;
pacify.PutF["\n%g: ", [integer[cellTypeN]]];
cellTypeN ← cellTypeN + 1;
Sets.PrintSet[d.CTNames[ct], pacify];
PutOldIndex[ctv];
PutInt[[i: (IF ct.asTrans#NIL THEN 1 ELSE 0) + (IF ct.asu#NIL THEN 2 ELSE 0) + (IF ct.asArray#NIL THEN 4 ELSE 0)]];
PutBiRel[ct.fullName[p], 'P, PutOldIndex, PutSteppyName];
IF ct.asu#NIL THEN {
PutBiRel[ct.fullName[w], 'Q, PutOldIndex, PutSteppyName];
PutBiRel[ct.fullName[i], 'R, PutOldIndex, PutSteppyName];
PutBiRel[ct.asu.exports, 'a, PutOldIndex, PutOldIndex];
PutSet[ct.Subcells, 'b, PutSubcellDetails];
};
IF ct.asArray#NIL THEN {
a: Array ~ ct.asArray;
PutStatEdge: PROC [sev: Sets.Value] ~ {
se: StatEdge ~ NARROW[sev.VA];
PutStatVert[se.SeRSvV[a.statrep, FALSE]];
PutStatVert[se.SeRSvV[a.statrep, TRUE]];
PutInt2[se.d];
RETURN};
PutDWDetails: PROC [dwv: Sets.Value] ~ {
dw: DumbWire ~ NARROW[dwv.VA];
PutOldIndex[dwv];
PutBiRel[dw.eps, 'k, PutOldIndex, PutInt, FALSE];
IF dw.children=nilBiRel THEN PutInt[[i:0]]
ELSE {
PutInt[[i:1]];
PutSeq[dw.children, 'l, PutOldIndex, FALSE]};
RETURN};
PutInt2[a.size2];
PutInt2[a.basePeriod];
PutInt[[i: (IF a.fXfm#nilBiRel THEN 1 ELSE 0) + (IF a.offsets#NIL THEN 2 ELSE 0)]];
IF a.fXfm#nilBiRel THEN PutBiRel[a.fXfm, 'e, PutInt, PutInt];
IF a.offsets#NIL THEN {
PutInt[IV[a.offsets.length]];
FOR i: NATURAL IN [0 .. a.offsets.length) DO
PutInt2[a.offsets[i].o0];
PutInt2[a.offsets[i].o1];
ENDLOOP;
};
PutSet[a.statrep.edges, 'f, PutStatEdge];
PutBiRel[a.statrep.apToPAI, 'g, PutOldIndex, PutPAI];
PutSet[a.dumrep.wires, 'h, PutNewIndex];
PutSet[a.dumrep.wires, 'i, PutDWDetails];
PutBiRel[a.dumrep.apToWire, 'j, PutOldIndex, PutOldIndex];
};
IF ct.asTrans#NIL THEN {
t: Transistor ~ ct.asTrans;
PutRope[[t.type]];
PutInt[[i: t.length]];
PutInt[[i: t.width]];
PutInt[[i: t.area]];
PutInt[[i: t.perimeter]]};
RETURN};
PutSubcellDetails: PROC [civ: Sets.Value] ~ {
ci: CellInstance ~ NARROW[civ.VA];
PutOldIndex[civ];
PutInt2[ci.offset];
PutBiRel[ci.conns, 'c, PutOldIndex, PutOldIndex, FALSE];
RETURN};
IF NOT d.other.Empty THEN ERROR;
IF pacify=NIL THEN pacify ← IO.noWhereStream;
pacify.PutF["Total: %g cell types\n", [integer[d.cellTypes.Size.EN]]];
steplists.AddNewIA[0, NIL];
refs.AddNewIA[0, NIL];
PutInt[[i:version]];
out.PutRope["123456789"];
out.SetIndex[10];
PutSet[d.names, 'A, PutRope];
PutInt[[i: (IF d.inheritNames THEN 1 ELSE 0) + (IF d.physd THEN 2 ELSE 0)]];
PutRope[[d.root.ACtName[] ]];
PutReal[d.scale];
PutSet[d.cellTypes, 'B, PutNewIndex];
PutSet[d.labelCellTypes, 'Z, PutOldIndex];
PutSet[d.crossedCellTypes, 'Y, PutOldIndex];
PutBiRel[d.cct[p], 'C, PutNewIndex, PutOldIndex];
PutBiRel[d.cct[w], 'D, PutNewIndex, PutOldIndex];
PutBiRel[d.cct[i], 'E, PutNewIndex, PutOldIndex];
PutBiRel[d.sub, 'F, PutOldIndex, PutSub];
PutBiRel[d.ciType, 'J, PutOldIndex, PutOldIndex];
PutBiRel[d.ctName, 'K, PutOldIndex, PutRope];
PutBiRel[d.arrayElt, 'L, PutOldIndex, PutOldIndex];
IF d.physd THEN {
PutBiRel[d.ciXfm, 'M, PutOldIndex, PutInt];
PutSet[d.cellTypes, 'G, PutCellTypeBBox]};
PutSet[d.cellTypes, 'N, PutCellTypeDetails];
pacify.PutRope["\n"];
{tail: INT ~ out.GetIndex[];
out.SetIndex[5];
PutInt[[i: tail]];
out.SetIndex[tail]};
out.PutRope["paSsword "];
PutInt[[i:refs.Size.EN]];
PutInt[[i:ropes.Size.EN]];
PutInt[[i:steplists.Size.EN]];
PutInt[[i:maxRopeLen]];
PutInt[[i:d.cellTypes.Size.EN]];
out.Close[];
RETURN};
PrintCTGraph: PROC [d: Design, fileName: ROPE, omitTransistors: BOOL] RETURNS [nOmitted: INT ← 0] ~ {
out: IO.STREAM ~ FS.StreamOpen[fileName, create];
calls: BiRel ~ d.cct[i].Invert.Compose[d.ciType, ALL[FALSE]].CreateHashCopy[mappable: ALL[TRUE]];
PerCT: PROC [ctv: Sets.Value] RETURNS [BOOL] ~ {
IF omitTransistors AND d.transistorCellTypes.HasMember[ctv] THEN {nOmitted ← nOmitted + 1; RETURN [FALSE]};
{ct: CellType ~ NARROW[ctv.VA];
name: ROPE ~ d.Describe[ct, d];
PrintDep: PROC [dtv: Sets.Value] RETURNS [BOOL] ~ {
IF omitTransistors AND d.transistorCellTypes.HasMember[dtv] THEN RETURN [FALSE];
{dt: CellType ~ NARROW[dtv.VA];
name: ROPE ~ d.Describe[dt, d];
out.PutF[" \"%q\"", [rope[name]]];
RETURN [FALSE]}};
out.PutF["(\"%q\" %g", [rope[name]], [rope[IF calls.MappingEmpty[ctv, rightToLeft] THEN "root" ELSE "NIL"]]];
IF calls.ScanMapping[ctv, PrintDep].found THEN ERROR;
out.PutRope[")\n\n"];
RETURN [FALSE]}};
[] ← calls.AddSet[d.arrayElt];
out.PutRope["(\n\n"];
IF d.cellTypes.Scan[PerCT].found THEN ERROR;
out.PutRope[")\n"];
out.Close[];
RETURN};
END.