SoftHdwStatsImpl.mesa
Copyright Ó 1988 by Xerox Corporation. All rights reserved.
Barth, November 10, 1988 5:30:15 pm PST
DIRECTORY Combinatorial, Core, CoreClasses, CoreFlat, CoreIO, CoreOps, CoreProperties, FS, IO, PWCore, RefTab, Rope, TerminalIO;
SoftHdwStatsImpl: CEDAR PROGRAM
IMPORTS Combinatorial, CoreClasses, CoreFlat, CoreIO, CoreOps, CoreProperties, FS, IO, PWCore, RefTab, Rope, TerminalIO
EXPORTS
= BEGIN
GenerateStats: PROC = {
EachFile: FS.NameProc = {
root: Core.CellType ← CoreIO.RestoreCellType[fileName: fullFName];
IO.PutRope[stats, "\n"];
IO.PutRope[stats, fullFName];
Leaves[root, stats];
continue ← TRUE;
};
stats: IO.STREAMFS.StreamOpen["SoftHdwCoreStats.txt", $create];
FS.EnumerateForNames["SoftHdwCore*.core", EachFile];
IO.Close[stats];
};
Leaves: PROC [root: Core.CellType, stats: IO.STREAM] = {
CellData: TYPE = REF CellDataRec;
CellDataRec: TYPE = RECORD [
layoutAtom: ATOM,
count: INT];
FlattenCell: CoreFlat.BoundFlatCellProc = {
atom: ATOM ← PWCore.GetLayoutAtom[cell];
SELECT TRUE FROM
cell.class=CoreClasses.transistorCellClass => ERROR;
atom#NIL AND atom#$SCRemote => {
cellName: Rope.ROPE ← CoreOps.GetCellTypeName[cell];
cellData: CellData ← NARROW[RefTab.Fetch[cellDataTable, cell].val];
IF cellData=NIL THEN {
cellData: CellData ← NEW[CellDataRec];
cellData.layoutAtom ← atom;
cellData.count ← 1;
IF NOT RefTab.Insert[cellDataTable, cell, cellData] THEN ERROR;
}
ELSE cellData.count ← cellData.count + 1;
IF Rope.Equal[cellName, "ff"] OR Rope.Equal[cellName, "ffEn"] THEN {
clock: Core.Wire ← CoreOps.FindWire[cell.public, "CK"];
flatClock: CoreFlat.FlatWire ← NARROW[RefTab.Fetch[bindings, clock].val];
clockCountRef: REF INTNARROW[RefTab.Fetch[clockWireTable, flatClock].val];
IF clockCountRef=NIL THEN {
clockCountRef ← NEW[INT ← 1];
IF NOT RefTab.Insert[clockWireTable, flatClock, clockCountRef] THEN ERROR;
};
clockCountRef^ ← clockCountRef^ + 1;
};
};
ENDCASE => CoreFlat.NextBoundCellType[cell, target, flatCell, instance, index, parent, flatParent, data, bindings, FlattenCell];
};
PrintCell: RefTab.EachPairAction = {
cellType: Core.CellType ← NARROW[key];
cellData: CellData ← NARROW[val];
IO.PutF[stats, "\n Cell: %g, atom: %g, count: %g", IO.rope[CoreOps.GetCellTypeName[cellType]], IO.atom[cellData.layoutAtom], IO.int[cellData.count]];
cellCount ← cellCount + cellData.count;
};
PrintWire: RefTab.EachPairAction = {
flatClock: CoreFlat.FlatWire ← NARROW[key];
clockCountRef: REF INTNARROW[val];
IO.PutF[stats, " (%g, %g)", IO.rope[CoreFlat.WirePathRope[root, flatClock^]], IO.int[clockCountRef^]];
};
cellDataTable: RefTab.Ref ← RefTab.Create[];
clockWireTable: RefTab.Ref ← RefTab.Create[hash: CoreFlat.FlatWireHash, equal: CoreFlat.FlatWireEqual];
cellCount: INT ← 0;
FlattenCell[cell: root];
IO.PutRope[stats, "\n"];
IO.PutRope[stats, CoreOps.GetCellTypeName[root]];
[] ← RefTab.Pairs[cellDataTable, PrintCell];
IO.PutF[stats, "\n Total cells: %g", IO.int[cellCount]];
IO.PutRope[stats, "\n Clock wires:"];
[] ← RefTab.Pairs[clockWireTable, PrintWire];
IO.PutRope[stats, "\n"];
};
LayoutAtoms: PROC [root: Core.CellType] = {
FlattenCell: CoreFlat.BoundFlatCellProc = {
atom: ATOM ← PWCore.GetLayoutAtom[cell];
IF atom#NIL THEN [] ← RefTab.Insert[atomTable, atom, atom];
IF cell.class#CoreClasses.transistorCellClass THEN CoreFlat.NextBoundCellType[cell, target, flatCell, instance, index, parent, flatParent, data, bindings, FlattenCell];
};
PrintAtom: RefTab.EachPairAction = {
atom: ATOMNARROW[key];
TerminalIO.PutF[" %g", IO.atom[atom]];
};
atomTable: RefTab.Ref ← RefTab.Create[];
FlattenCell[cell: root];
TerminalIO.PutRope["\n"];
[] ← RefTab.Pairs[atomTable, PrintAtom];
TerminalIO.PutRope["\n"];
};
PrintCombinatorial: PROC [root: Core.CellType] = {
outputs: Core.Wires ← Combinatorial.GetTypedWires[root, output];
TerminalIO.PutF["\n\nCell: %g", IO.rope[CoreOps.GetCellTypeName[root]]];
FOR wires: Core.Wires ← outputs, wires.rest UNTIL wires=NIL DO
wire: Core.Wire ← wires.first;
TerminalIO.PutF["\n %g: %g", IO.rope[CoreOps.GetFullWireName[root.public, wire]], IO.rope[Combinatorial.GetOutput[wire]]];
ENDLOOP;
};
FixSoftHdwCoreB: PROC [root: Core.CellType] = {
ParentData: TYPE = REF NAT;
Fix: CoreFlat.BoundFlatCellProc = {
name: Rope.ROPE ← CoreOps.GetCellTypeName[cell];
SELECT TRUE FROM
Rope.Equal[name, "VbDr"] => {
Combinatorial.MakeCombinatorial[cell];
CoreFlat.NextBoundCellType[cell, target, flatCell, instance, index, parent, flatParent, data, bindings, Fix];
};
Rope.Equal[name, "InvBSeq"] OR Rope.Equal[name, "MuxInvDr"] => {
x: Core.Wire ← CoreOps.FindWire[cell.public, "X"];
canonized: CoreFlat.FlatWire ← NARROW[RefTab.Fetch[bindings, x].val];
IF NOT RefTab.Insert[alreadyDriven, canonized, $Driven] THEN {
parentData: ParentData ← NARROW[RefTab.Fetch[parentDataTable, parent].val];
IF parentData=NIL THEN {
parentData ← NEW[NAT ← 0];
IF NOT RefTab.Insert[parentDataTable, parent, parentData] THEN ERROR;
};
{
parentRCT: CoreClasses.RecordCellType ← NARROW[parent.data];
newRCT: CoreClasses.RecordCellType ← NEW[CoreClasses.RecordCellTypeRec[parentRCT.size-1]];
adjustedIndex: NAT ← index-parentData^;
FOR i: NAT IN [0..adjustedIndex) DO
newRCT[i] ← parentRCT[i];
ENDLOOP;
FOR i: NAT IN [adjustedIndex..newRCT.size) DO
newRCT[i] ← parentRCT[i+1];
ENDLOOP;
newRCT.internal ← parentRCT.internal;
parent.data ← newRCT;
parentData^ ← parentData^ + 1;
};
};
CoreProperties.PutCellTypeProp[cell, $Combinatorial, NEW[BOOLTRUE]];
Combinatorial.PutOutput[x, "~I"];
};
cell.class=CoreClasses.transistorCellClass OR cell.class=CoreClasses.unspecifiedCellClass => NULL;
ENDCASE => CoreFlat.NextBoundCellType[cell, target, flatCell, instance, index, parent, flatParent, data, bindings, Fix];
};
alreadyDriven: RefTab.Ref ← RefTab.Create[hash: CoreFlat.FlatWireHash, equal: CoreFlat.FlatWireEqual];
parentDataTable: RefTab.Ref ← RefTab.Create[];
Fix[cell: root, bindings: CoreFlat.InitialBindingTable[root]];
};
PrintLogicalPrimitives: PROC [root: Core.CellType] = {
Walk: CoreFlat.BoundFlatCellProc = {
name: Rope.ROPE ← CoreOps.GetCellTypeName[cell];
SELECT TRUE FROM
cell.class=CoreClasses.transistorCellClass OR cell.class=CoreClasses.unspecifiedCellClass => ERROR;
Combinatorial.IsCombinatorial[cell] OR Combinatorial.IsNonCombinatorial[cell] OR Rope.Equal[name, "ff"] => {
count: REF INTNARROW[RefTab.Fetch[cellTable, cell].val];
IF count=NIL THEN {
count ← NEW[INT ← 0];
IF NOT RefTab.Insert[cellTable, cell, count] THEN ERROR;
};
count^ ← count^ + 1;
};
ENDCASE => CoreFlat.NextBoundCellType[cell, target, flatCell, instance, index, parent, flatParent, data, bindings, Walk];
};
PrintACell: RefTab.EachPairAction = {
cell: Core.CellType ← NARROW[key];
count: REF INTNARROW[val];
TerminalIO.PutF["\n Cell: %g, count: %g", IO.rope[CoreOps.GetCellTypeName[cell]], IO.int[count^]];
cellCount ← cellCount + count^;
IF Combinatorial.IsCombinatorial[cell] THEN {
outputs: Core.Wires ← Combinatorial.GetTypedWires[cell, output];
FOR wires: Core.Wires ← outputs, wires.rest UNTIL wires=NIL DO
wire: Core.Wire ← wires.first;
TerminalIO.PutF["\n %g: %g", IO.rope[CoreOps.GetFullWireName[cell.public, wire]], IO.rope[Combinatorial.GetOutput[wire]]];
ENDLOOP;
};
};
cellTable: RefTab.Ref ← RefTab.Create[];
cellCount: INT ← 0;
Walk[root];
TerminalIO.PutRope["\n\n"];
[] ← RefTab.Pairs[cellTable, PrintACell];
TerminalIO.PutF["\n Total cells: %g", IO.int[cellCount]];
};
Recursive Split
MakeNewSeq: PROC [old: Core.WireSeq, oldToNew: RefTab.Ref] RETURNS [new: Core.WireSeq] = {
new ← CoreOps.CreateWires[size: old.size];
FOR j: NAT IN [0 .. new.size) DO
new[j] ← CoreOps.CopyWireUsingTable[old[j], oldToNew];
ENDLOOP;
};
MakeNewSeqFlat: PROC [old: Core.WireSeq, oldToNew: RefTab.Ref, flatCell: CoreFlat.FlatCellTypeRec] RETURNS [new: Core.WireSeq] = {
CopyWire: PROC [old: CoreFlat.FlatWire] RETURNS [new: Core.Wire] = {
new ← NARROW [RefTab.Fetch[oldToNew, old].val];
IF new#NIL THEN RETURN;
new ← CreateWires[size: old.wire.size, name: GetShortWireName[old.wire]];
[] ← RefTab.Insert[oldToNew, old, new];
DoEach[old.wire, new];
};
DoEach: PROC [old, new: Core.Wire] = {
FOR i: NAT IN [0 .. old.size) DO
flatOld: CoreFlat.FlatWire ← NEW[CoreFlat.FlatWireRec];
flatOld.flatCell ← flatCell;
flatOld.wire ← old[i];
new[i] ← CopyWire[flatOld];
ENDLOOP;
};
new ← CoreOps.CreateWires[size: old.size];
DoEach[old, new];
};
CellData: TYPE = REF CellDataRec;
CellDataRec: TYPE = RECORD [
oldToNew: RefTab.Ref ← NIL,
instances: CoreClasses.Instances ← NIL];
MakeCellData: PROC RETURNS [cellData: CellData] = {
cellData ← NEW[CellDataRec];
cellData.oldToNew ← RefTab.Create[hash: CoreFlat.FlatWireHash, equal: CoreFlat.FlatWireEqual];
};
AddCell: PROC [data: CellData, instance: CoreClasses.CellInstance, parentFlatCell: CoreFlat.FlatCellTypeRec] = {
actual: Core.Wire ← MakeNewSeqFlat[instance.actual, data.oldToNew, parentFlatCell];
new: CoreClasses.CellInstance ← CoreClasses.CreateInstance[actual, instance.type];
data.instances ← CONS[new, data.instances];
};
BuildInternal: PROC [data: CellData] RETURNS [internal: Core.Wire] = {
InsertAnInternal: RefTab.EachPairAction = {
internal[nextInternal] ← NARROW[key];
nextInternal ← nextInternal + 1;
};
actualTable: RefTab.Ref ← RefTab.Create[];
nextInternal: NAT ← 0;
FOR instances: CoreClasses.Instances ← data.instances, instances.rest UNTIL instances=NIL DO
actual: Core.Wire ← instances.first.actual;
FOR i: NAT IN [0..actual.size) DO
[] ← RefTab.Insert[actualTable, actual[i], $Inserted];
ENDLOOP;
ENDLOOP;
internal ← CoreOps.CreateWires[RefTab.Size[actualTable]];
[] ← RefTab.Pairs[actualTable, InsertAnInternal];
IF nextInternal#internal.size THEN ERROR;
};
RecursiveReplace: PROC [
MakeInstance: PROC [data: CellData, other, parent: RefTab.Ref] RETURNS [instance: CoreClasses.CellInstance] = {
CheckPublic: RefTab.EachPairAction = {
old: CoreFlat.FlatWire ← NARROW[key];
new: Core.Wire ← NARROW[val];
IF RefTab.Fetch[other, old].found OR RefTab.Fetch[parent, old].found THEN {
FOR w: Core.Wires ← publics, w.rest UNTIL w=NIL DO
IF CoreOps.RecursiveMember[w.first, new] THEN EXIT;
REPEAT FINISHED => {
publics ← CONS[new, publics];
oldPublics ← CONS[old, oldPublics];
}
ENDLOOP;
};
};
internal: Core.Wire ← BuildInternal[data];
publics: Core.Wires ← NIL;
public: Core.Wire;
oldPublics: CoreFlat.FlatWires ← NIL;
[] ← RefTab.Pairs[data.oldToNew, CheckPublic];
public ← CoreOps.CreateWire[publics];
actual ← CoreOps.CopyWire[public];
FOR nextActual: NAT IN [0..public.size) DO
actual[nextActual] ← RecursiveReplace[
ENDLOOP;
ct: Core.CellType ← CoreClasses.CreateRecordCell[
public: public,
internal: internal,
instances: data.instances];
instance ← CoreClasses.CreateInstance[CoreOps.CreateWire[actuals], ct]
};
MakeNonCombinatorial: PROC [cell: Core.CellType] = {
CoreProperties.PutCellTypeProp[rc, $Combinatorial, NEW [BOOLFALSE]];
};
SplitCombinatorialRecursive: PROC [root: Core.CellType] RETURNS [split: Core.CellType] = {
SplitOne: PROC [cell: Core.CellType] RETURNS [split ← Core.CellType] = {
rc: Core.CellType;
IF Combinatorial.IsCombinatorial[cell] OR Combinatorial.IsNonCombinatorial[cell] THEN RETURN [cell];
rc ← CoreOps.ToBasic[cell];
IF (split ← NARROW[RefTab.Fetch[originalToSplit, rc].val])=NIL THEN {
allNonComb, allComb: BOOLTRUE;
rct: CoreClasses.RecordCellType ← NARROW[rc.data];
combs: CellData ← MakeCellData[];
nonCombs: CellData ← MakeCellData[];
parent: CellData ← MakeCellData[];
public: Core.Wire ← MakeNewSeqFlat[rc.public, parent.oldToNew, CoreFlat.rootCellType];
FOR i: NAT IN [0..rct.size) DO
BinCell: PROC [cell: Core.CellType] RETURNS [BOOL] = {
SELECT TRUE FROM
Combinatorial.IsCombinatorial[cell] => {
AddCell[combs, rct[i], CoreFlat.rootCellType];
allNonComb ← FALSE;
RETURN[FALSE];
};
Combinatorial.IsNonCombinatorial[cell] => {
AddCell[nonCombs, rct[i], CoreFlat.rootCellType];
allComb ← FALSE;
RETURN[FALSE];
};
cell.class=CoreClasses.transistorCellClass OR cell.class=CoreClasses.unspecifiedCellClass => ERROR;
ENDCASE => RETURN[TRUE];
};
subCell: Core.CellType ← rct[i].type;
IF BinCell[subCell] THEN {
subSplit: Core.CellType ← SplitOne[subCell];
IF BinCell[subSplit] THEN {
ssrct: CoreClasses.RecordCellType ← NARROW[subSplit.data];
flatCell: CoreFlat.FlatCellTypeRec ← [CoreFlat.ExtendPath[CoreFlat.nullInstancePath, i, rct], 0];
AddCell[combs, ssrct[0], flatCell];
AddCell[nonCombs, ssrct[1], flatCell];
allNonComb ← FALSE;
allComb ← FALSE;
};
};
ENDLOOP;
SELECT TRUE FROM
allComb AND allNonComb => ERROR;
allComb => {
Combinatorial.MakeCombinatorial[rc];
RETURN[rc];
};
allNonComb => {
MakeNonCombinatorial[rc];
RETURN[rc];
};
ENDCASE => {
comb: CoreClasses.CellInstance ← MakeInstance[combs];
nonComb: CoreClasses.CellInstance ← MakeInstance[nonCombs];
split ← CoreClasses.CreateRecordCell[
public: public,
internal: BuildInternal[parent],
instances: LIST [comb, nonComb]];
IF NOT RefTab.Insert[originalToSplit, rc, split] THEN ERROR;
};
};
};
originalToSplit: RefTab.Ref ← RefTab.Create[];
split ← SplitOne[root];
};
END.