CoreBeauImpl.mesa
Copyright © 1985 by Xerox Corporation. All rights reserved.
Created by Bertrand Serlet, November 13, 1985 2:59:33 pm PST
Bertrand Serlet, November 13, 1985 7:48:15 pm PST
DIRECTORY
Core, CoreBeau, CoreClasses, CoreOps, CoreProperties, CoreSequence,
IO, Rope;
CoreBeauImpl: CEDAR PROGRAM
IMPORTS CoreClasses, CoreOps, CoreProperties, CoreSequence, IO, Rope
EXPORTS CoreBeau =
BEGIN OPEN CoreBeau;
Internal utilities
UnionSequences: PROC [wireSeq1, wireSeq2: WireSequence] RETURNS [wireSeq: WireSequence] = {
wireSeq ← CoreOps.CreateBasicSequenceWire[wireSeq1.size+wireSeq2.size].elements;
FOR i: NAT IN [0 .. wireSeq1.size) DO wireSeq[i] ← wireSeq1[i] ENDLOOP;
FOR i: NAT IN [0 .. wireSeq2.size) DO wireSeq[i+wireSeq1.size] ← wireSeq2[i] ENDLOOP;
};
WRsToWires: PROC [wrs: LIST OF WR] RETURNS [wires: LIST OF Wire ← NIL] = {
WHILE wrs#NIL DO
IF wrs.first#NIL THEN wires ← CONS [WRToWire[wrs.first], wires];
wrs ← wrs.rest;
ENDLOOP;
wires ← CoreOps.Reverse[wires];
};
WRToWire: PROC [wr: WR] RETURNS [Wire] = {
WITH wr SELECT FROM
wire: Wire  => RETURN [wire];
wireSeq: WireSequence => RETURN [CoreOps.WireSequenceToWire[wireSeq]];
rope: ROPE  => RETURN [CoreOps.CreateAtomWire[name: rope]];
ENDCASE  => ERROR
};
FindWireInWireSeq: PROC [wr: WR, wireSeq: WireSequence] RETURNS [Wire] = {
matchingWires: LIST OF Wire ← NIL;
FindInEach: CoreOps.EachWireProc = {
name: ROPE ← CoreOps.GetWireName[wire];
match: BOOLFALSE;
WITH wr SELECT FROM
wrwire: Wire  =>
match ← wire=wrwire OR (name#NIL AND Rope.Equal[name, CoreOps.GetWireName[wrwire]]);
wrwireSeq: WireSequence  => match ← wire.elements=wrwireSeq;
wrrope: ROPE  => match ← Rope.Equal[name, wrrope];
ENDCASE  => ERROR;
IF match THEN matchingWires ← CONS [wire, matchingWires];
};
[] ← CoreOps.VisitWireSequence[wireSeq, FindInEach];
RETURN [IF matchingWires=NIL THEN NIL ELSE matchingWires.first];
};
ListifyBindings: PROC [pas: LIST OF PA] RETURNS [revpas: LIST OF PANIL] = {
We just get rid of the [] ones
WHILE pas#NIL DO
IF pas.first#[] THEN revpas ← CONS [pas.first, revpas];
pas ← pas.rest;
ENDLOOP;
};
IndexInPublic: PROC [wire: Wire, public: WireSequence] RETURNS [index: INT ← -1] = {
FOR i: NAT IN [0 .. public.size) DO IF public[i]=wire THEN RETURN [i] ENDLOOP;
};
Creation of Wires
Wires: PUBLIC PROC [wr1, wr2, wr3, wr4, wr5, wr6, wr7: WRNIL] RETURNS [WireSequence] = {
RETURN [CoreOps.WiresToWireSequence[WRsToWires[LIST [wr1, wr2, wr3, wr4, wr5, wr6, wr7]]]];
};
Seq: PUBLIC PROC [wr: WR, length: NAT] RETURNS [WireSequence] = {
WITH wr SELECT FROM
wire: Wire => RETURN [CoreOps.CreateBasicSequenceWire[length].elements];
rope: ROPE => RETURN [CoreOps.CreateBasicSequenceWire[length, rope].elements];
ENDCASE => ERROR
};
Index: PUBLIC PROC [wr: WR, index: NAT] RETURNS [WR] = {
WITH wr SELECT FROM
wire: Wire  => RETURN [wire.elements[index]];
wireSeq: WireSequence => RETURN [wireSeq[index]];
rope: ROPE  => RETURN [IO.PutFR["%g[%g]", IO.rope[rope], IO.int[index]]];
ENDCASE  => ERROR
};
Indexes: PUBLIC PROC [wr: WR, start: NAT ← 0, length: NAT] RETURNS [WireSequence] = {
WITH wr SELECT FROM
wire: Wire  => RETURN [CoreOps.SubrangeWire[wire, start, length].elements];
wireSeq: WireSequence => RETURN [CoreOps.SubrangeWire[CoreOps.WireSequenceToWire[wireSeq], start, length].elements];
rope: ROPE  => {
subWires: LIST OF Wire ← NIL;
FOR i: NAT DECREASING IN [0 .. length) DO
subWires ← CONS [CoreOps.CreateAtomWire[IO.PutFR["%g[%g]", IO.rope[rope], IO.int[i]]], subWires];
ENDLOOP;
RETURN [CoreOps.CreateSequenceWire[subWires].elements];
};
ENDCASE  => ERROR
};
Bindings, Instances and RecordCell
Instance: PUBLIC PROC [type: CellType, pa1, pa2, pa3, pa4, pa5, pa6: PA ← []] RETURNS [CellInstance] = {
pas: LIST OF PA ← ListifyBindings[LIST [pa1, pa2, pa3, pa4, pa5, pa6]];
actual: WireSequence ← CoreOps.CopyWireSequence[type.public];
ReplaceBinding: CoreOps.EachWirePairProc = {
replacementActuals: LIST OF Wire ← NIL;
FOR bindings: LIST OF PA ← pas, bindings.rest WHILE bindings#NIL DO
IF bindings.first.public=publicWire THEN replacementActuals ← CONS [WRToWire[bindings.first.actual], replacementActuals];
ENDLOOP;
IF replacementActuals#NIL AND replacementActuals.rest#NIL THEN ERROR; -- more than one actual for the same public. replacementActuals gives all the actuals
IF replacementActuals#NIL THEN {
actualWire^ ← replacementActuals.first^; subWires ← FALSE;
};
};
FOR bindings: LIST OF PA ← pas, bindings.rest WHILE bindings#NIL DO
we make sure each of the given public is really a public, and we replace in the bindings so that we will only have to do pointer comparison later
bindings.first.public ← FindWireInWireSeq[bindings.first.public, type.public];
ENDLOOP;
[] ← CoreOps.VisitBinding[actual, type.public, ReplaceBinding];
IF type=NIL THEN ERROR; -- early detection of this error might be useful
RETURN [NEW [CoreClasses.CellInstanceRec ← [actual: actual, type: type]]];
};
Cell: PUBLIC PROC [name: ROPENIL, public, onlyInternal: WireSequence ← NIL, instances: LIST OF CellInstance] RETURNS [CellType] = {
data: CoreClasses.RecordCellType ← NEW [CoreClasses.RecordCellTypeRec ← [internal: UnionSequences[public, onlyInternal], instances: instances]];
This PROC would be different if we allow the DAG
ReplaceABI: PROC [actualWire: Wire, internal: WireSequence] RETURNS [newActualWire: Wire] = {
newActualWire ← FindWireInWireSeq[actualWire, internal];
IF newActualWire#NIL THEN RETURN;
IF actualWire.elements=NIL THEN ERROR; -- non structured wire not found in the internal
newActualWire ← CoreOps.WireSequenceToWire[ReplaceActualByInternal[actualWire.elements, internal]];
};
ReplaceActualByInternal: PROC [actual, internal: WireSequence] RETURNS [newActual: WireSequence] = {
wire: Wire ← FindWireInWireSeq[actual, internal];
IF wire#NIL THEN RETURN [wire.elements];
newActual ← CoreOps.CreateBasicSequenceWire[actual.size].elements;
FOR i: NAT IN [0 .. actual.size) DO
newActual[i] ← ReplaceABI[actual[i], internal];
ENDLOOP;
};
cellType: CellType;
IF public=NIL THEN public ← CoreOps.CreateBasicSequenceWire[0].elements;
IF onlyInternal=NIL THEN onlyInternal ← CoreOps.CreateBasicSequenceWire[0].elements;
cellType ← CoreOps.CreateCellType[class: CoreClasses.recordCellClass, public: public, data: data, name: name];
we replace all actual wires by wires having the same name than part of the public
FOR insts: LIST OF CellInstance ← instances, insts.rest WHILE insts#NIL DO
insts.first.actual ← ReplaceActualByInternal[insts.first.actual, data.internal];
ENDLOOP;
RETURN [cellType];
};
Other cell type creation
Transistor: PUBLIC PROC [name: ROPENIL, type: TransistorType ← nE, length: NAT ← 2, width: NAT ← 4] RETURNS [CellType] = {
cellType: CellType ← CoreClasses.TransistorCreate[[
type: type, length: length, width: width
]];
CoreProperties.PutCellTypeProp[cellType, CoreOps.nameProp, name];
RETURN [cellType];
};
SequenceCell: PUBLIC PROC [name: ROPENIL, baseCell: CellType, count: NAT, sequencePorts: WireSequence ← NIL] RETURNS [CellType] = {
cellType: CellType;
seqCell: CoreSequence.SequenceCellType;
IF sequencePorts=NIL THEN sequencePorts ← CoreOps.CreateBasicSequenceWire[0].elements;
seqCell ← NEW [CoreSequence.SequenceCellTypeRec[sequencePorts.size]];
FOR i: INT IN [0 .. sequencePorts.size) DO
publicWire: Wire ← FindWireInWireSeq[sequencePorts[i], baseCell.public];
IF publicWire=NIL THEN ERROR;
IF (seqCell.sequence[i] ← IndexInPublic[publicWire, baseCell.public])=-1 THEN ERROR;
ENDLOOP;
seqCell.base ← baseCell;
seqCell.count ← count;
cellType ← CoreSequence.Create[name: name, args: seqCell];
RETURN [cellType];
};
Utility
FindWire: PUBLIC PROC [cell: CellType, wr: WR] RETURNS [Wire] = {
RETURN [FindWireInWireSeq[wr, IF cell.class=CoreClasses.recordCellClass
THEN NARROW[cell.data, CoreClasses.RecordCellType].internal
ELSE cell.public]];
};
END.