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 27, 1985 11:06:54 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 [wire1, wire2: Wire] RETURNS [wire: Wire] = {
wire ← CoreOps.CreateWire[size: wire1.size+wire2.size];
FOR i: NAT IN [0 .. wire1.size) DO wire[i] ← wire1[i] ENDLOOP;
FOR i: NAT IN [0 .. wire2.size) DO wire[i+wire1.size] ← wire2[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];
rope: ROPE  => RETURN [CoreOps.CreateWire[name: rope]];
text: REF TEXT => RETURN [CoreOps.CreateWire[name: IO.PutR1[IO.text[text]]]];
ENDCASE  => ERROR
};
FindWireInWireSeq: PROC [wr: WR, wire: Wire] RETURNS [Wire] = {
matchingWires: LIST OF Wire ← NIL;
FindInEach: PROC [wire: Wire, name: ROPENIL] = {
match: BOOLWITH wr SELECT FROM
wrwire: Wire =>
match ← wire=wrwire OR (name#NIL AND Rope.Equal[name, CoreOps.GetWireName[wrwire]]),
wrrope: ROPE => match ← Rope.Equal[name, wrrope],
text: REF TEXT => match ← Rope.Equal[name, IO.PutR1[IO.text[text]]],
ENDCASE  => ERROR;
IF match THEN matchingWires ← CONS [wire, matchingWires];
FOR i: NAT IN [0 .. wire.size) DO
subName: ROPE ← CoreOps.GetWireName[wire[i]];
new: ROPESELECT TRUE FROM
CoreProperties.GetWireProp[wire, CoreOps.sequenceProp]#NIL
=> IO.PutFR["%g[%g]", IO.rope[name], IO.int[i]],
subName#NIL
=> IF name=NIL THEN subName ELSE Rope.Cat[name, ".", subName],
ENDCASE
=> IF name=NIL THEN "?" ELSE Rope.Cat[name, ".?"];
FindInEach[wire[i], new];
ENDLOOP;
};
FindInEach[wire];
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: Wire] RETURNS [index: INT] = {
FOR i: NAT IN [0 .. public.size) DO
IF Rope.Equal[CoreOps.GetWireName[public[i]], CoreOps.GetWireName[wire]]
THEN RETURN [i];
ENDLOOP;
ERROR; -- not found
};
Creation of Wires
WireList: PUBLIC PROC [wrs: LIST OF WRNIL] RETURNS [Wire] = {
RETURN [CoreOps.WiresToWire[WRsToWires[wrs]]];
};
Wires: PUBLIC PROC [wr1, wr2, wr3, wr4, wr5, wr6, wr7, wr8, wr9, wr10, wr11, wr12, wr13: WRNIL] RETURNS [Wire] = {
RETURN [WireList[LIST [wr1, wr2, wr3, wr4, wr5, wr6, wr7, wr8, wr9, wr10, wr11, wr12, wr13]]];
};
Seq: PUBLIC PROC [wr: WR, size: NAT] RETURNS [Wire] = {
RETURN [CoreOps.CreateWire[
size: size,
name: WITH wr SELECT FROM
wire: Wire  => CoreOps.GetWireName[wire],
rope: ROPE  => rope,
text: REF TEXT => IO.PutR1[IO.text[text]],
ENDCASE  => ERROR,
props: CoreProperties.Props[[CoreOps.sequenceProp, CoreOps.sequenceProp]]]];
};
Index: PUBLIC PROC [wr: WR, index: NAT] RETURNS [WR] = {
WITH wr SELECT FROM
wire: Wire  => RETURN [wire[index]];
rope: ROPE  => RETURN [IO.PutFR["%g[%g]", IO.rope[rope], IO.int[index]]];
text: REF TEXT => RETURN [IO.PutFR["%g[%g]", IO.text[text], IO.int[index]]];
ENDCASE  => ERROR
};
Indexes: PUBLIC PROC [wr: WR, start: NAT ← 0, length: NAT] RETURNS [Wire] = {
WITH wr SELECT FROM
wire: Wire  => RETURN [CoreOps.SubrangeWire[wire, start, length]];
rope: ROPE  => {
subWires: LIST OF Wire ← NIL;
FOR i: NAT DECREASING IN [0 .. length) DO
subWires ← CONS [CoreOps.CreateWire[name: IO.PutFR["%g[%g]", IO.rope[rope], IO.int[i+start]]], subWires];
ENDLOOP;
RETURN [CoreOps.WiresToWire[subWires]];
};
text: REF TEXT => {
subWires: LIST OF Wire ← NIL;
FOR i: NAT DECREASING IN [0 .. length) DO
subWires ← CONS [CoreOps.CreateWire[name: IO.PutFR["%g[%g]", IO.text[text], IO.int[i+start]]], subWires];
ENDLOOP;
RETURN [CoreOps.WiresToWire[subWires]];
};
ENDCASE  => ERROR
};
Bindings, Instances and RecordCell
Instance: PUBLIC PROC [type: CellType, pa1, pa2, pa3, pa4, pa5, pa6, pa7, pa8, pa9, pa10, pa11, pa12, pa13: PA ← []] RETURNS [CellInstance] = {
pas: LIST OF PA ← ListifyBindings[LIST [pa1, pa2, pa3, pa4, pa5, pa6, pa7, pa8, pa9, pa10, pa11, pa12, pa13]];
actual: Wire ← CoreOps.CopyWire[type.public];
ReplaceBinding: PROC [public: Wire] RETURNS [actual: Wire] = {
replacementActuals: LIST OF Wire ← NIL;
FOR bindings: LIST OF PA ← pas, bindings.rest WHILE bindings#NIL DO
IF bindings.first.public=public 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 AND ~CoreOps.Conform[replacementActuals.first, public] THEN ERROR;
IF replacementActuals#NIL THEN RETURN [replacementActuals.first];
actual ← CoreOps.CopyWire[public];
FOR i: NAT IN [0 .. public.size) DO actual[i] ← ReplaceBinding[public[i]] ENDLOOP;
};
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;
IF type=NIL THEN ERROR; -- early detection of this error might be useful
RETURN [NEW [CoreClasses.CellInstanceRec ← [actual: ReplaceBinding[type.public], type: type]]];
};
Cell: PUBLIC PROC [name: ROPENIL, public, onlyInternal: Wire ← NIL, instances: LIST OF CellInstance] RETURNS [CellType] = {
data: CoreClasses.RecordCellType;
This PROC would be different if we allow the DAG
ReplaceActualByInternal: PROC [actual, internal: Wire] RETURNS [newActual: Wire] = {
wire: Wire ← FindWireInWireSeq[actual, internal];
IF wire#NIL THEN RETURN [wire]; -- found!
IF actual.size=0 THEN ERROR; -- non structured wire not found in the internal
newActual ← CoreOps.CreateWire[size: actual.size];
FOR i: NAT IN [0 .. actual.size) DO
newActual[i] ← ReplaceActualByInternal[actual[i], internal];
ENDLOOP;
};
cellType: CellType;
IF public=NIL THEN public ← CoreOps.CreateWire[0];
IF onlyInternal=NIL THEN onlyInternal ← CoreOps.CreateWire[0];
cellType ← CoreClasses.CreateRecordCell[public: public, internal: UnionSequences[public, onlyInternal], instances: instances, name: name];
we replace all actual wires by wires having the same name than part of the public
data ← NARROW [cellType.data];
FOR i: NAT IN [0 .. data.size) DO
data[i].actual ← ReplaceActualByInternal[data[i].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.CreateTransistor[[
type: type, length: length, width: width
]];
CoreProperties.PutCellTypeProp[cellType, CoreOps.nameProp, name];
RETURN [cellType];
};
SequenceCell: PUBLIC PROC [name: ROPENIL, baseCell: CellType, count: NAT, sequencePorts: Wire ← NIL] RETURNS [CellType] = {
cellType: CellType;
seqCell: CoreSequence.SequenceCellType;
IF sequencePorts=NIL THEN sequencePorts ← CoreOps.CreateWire[size: 0];
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;
seqCell.sequence[i] ← IndexInPublic[publicWire, baseCell.public];
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 [IF cell.class=CoreClasses.recordCellClass
THEN FindWireInWireSeq[wr, NARROW [cell.data, CoreClasses.RecordCellType].internal]
ELSE FindWireInWireSeq[wr, cell.public]
];
};
END.