LichenDataImpl2.Mesa
Last tweaked by Mike Spreitzer on May 6, 1988 10:05:46 am PDT
DIRECTORY AbSets, AMBridge, AMTypes, BasicTime, BiRels, IntStuff, IO, LichenDataOps, LichenDataStructure, LichenIntBasics, PrintTV, Rope, SetBasics;
LichenDataImpl2:
CEDAR
PROGRAM
IMPORTS AbSets, AMBridge, BiRels, IntStuff, IO, LichenDataOps, LichenDataStructure, PrintTV, SetBasics
EXPORTS LichenDataOps
=
BEGIN OPEN IB:LichenIntBasics, IB, LichenDataStructure, LichenDataOps, Sets:AbSets;
startInheriting: BOOL ← FALSE;
CreateDesign:
PUBLIC
PROC [names: Set
--of ROPE--]
RETURNS [d: Design] ~ {
IF names.SpaceOf[] # SetBasics.ropes[TRUE] THEN ERROR;
IF names.Empty[] THEN ERROR;
d ← NEW [DesignPrivate];
d.names ← Sets.CreateHashCopy[names];
d.eSpace ← CreateEntitySpace[d];
d.cellTypes ← Sets.CreateHashSet[d.eSpace];
d.sub ← BiRels.CreateHashFn[spaces: [d.eSpace, SetBasics.refs], invable: FALSE];
d.parent ← BiRels.CreateHashFn[spaces: ALL[d.eSpace], invable: TRUE];
d.ancest ← d.parent.TransitiveFnClosure[TRUE];
d.cct ← [
p: BiRels.CreateHashFn[spaces: [d.eSpace, d.eSpace], invable: TRUE],
w: BiRels.CreateHashFn[spaces: [d.eSpace, d.eSpace], invable: TRUE],
i: BiRels.CreateHashFn[spaces: [d.eSpace, d.eSpace], invable: TRUE]];
d.partses ← [d.cct[p].SetOn[left], d.cct[w].SetOn[left], d.cct[i].SetOn[left]];
d.pws ← d.partses[p].Union[d.partses[w]];
d.parts ← d.pws.Union[d.partses[i]];
d.isntTop ← d.parent.SetOn[left];
d.isComposite ← d.sub.SetOn[left];
d.isTop ← d.pws.Difference[d.isntTop];
d.isAtomic ← d.pws.Difference[d.isComposite];
d.ciType ← BiRels.CreateHashFn[spaces: [d.eSpace, d.eSpace], invable: TRUE];
d.ctName ← BiRels.CreateHashReln[spaces: [d.eSpace, SetBasics.ropes[TRUE]]];
d.arrayElt ← BiRels.CreateHashFn[spaces: ALL[d.eSpace], invable: TRUE];
RETURN};
CreateEntitySpace:
PROC [d: Design]
RETURNS [Sets.Space] ~ {
RETURN [
NEW [SetBasics.SpacePrivate ← [
Contains: EntityContains,
Equal: SetBasics.refs.Equal,
AHash: SetBasics.refs.AHash,
ACompare: SetBasics.refs.ACompare,
Print: EntityPrint,
name: IO.PutFR["entities of %g", [rope[NARROW[d.names.AnElt[].MA] ]] ],
data: d
]]]};
EntityContains:
PROC [data:
REF
ANY, v: Sets.Value]
RETURNS [
BOOL] ~ {
d: Design ~ NARROW[data];
IF v.i#0 THEN RETURN [FALSE];
WITH v.ra
SELECT
FROM
ct: CellType => RETURN [TRUE];
v: Vertex => RETURN [TRUE];
p: Port => RETURN [TRUE];
ENDCASE => RETURN [FALSE]};
EntityPrint:
PROC [data:
REF
ANY, v: Sets.Value, to:
IO.
STREAM, depth, length:
INT, verbose:
BOOL] ~ {
d: Design ~ NARROW[data];
ra: REF ANY ~ v.VA;
WITH ra
SELECT
FROM
ct: CellType => {
name: ROPE ~ ct.ACtName[];
to.PutRope[name];
};
ENDCASE => {
class: PartClass ~
WITH ra
SELECT
FROM
p: Port => p,
w: Wire => w,
ci: CellInstance => i,
ENDCASE => ERROR;
cct: CellType ~ NARROW[d.cct[class].Apply[v].MA];
mv: Sets.MaybeValue ~ cct.fullName[class].Lookup[goal: v, side: left];
IF mv.found
THEN to.PutRope[UnparseSteppyName[VSn[mv.it]]]
ELSE PrintTV.Print[RaTv[ra], to, depth, length, verbose];
RETURN};
};
namingHints: BiRels.HintPair ~ [
leftToRight: [
fn: [$Hash],
set: [$List, LIST[[$RelOrder, $fwd]]]
],
rightToLeft: [
fn: [$Hash],
set: [$Hash]
]];
CreateCellType:
PUBLIC
PROC [d: Design, flavor: CellFlavor, names: Set
--of ROPE--]
RETURNS [ct: CellType] ~ {
ct ←
NEW [CellTypePrivate ← [
d: d,
fullName: [
p: BiRels.GenCreate[spaces: [d.eSpace, steppyNameSpace], hints: namingHints],
w: nilBiRel,
i: nilBiRel],
inheritNames: startInheriting
]];
IF flavor=unorganized
THEN {
exports: BiRel ~ BiRels.CreateHashFn[[d.eSpace, d.eSpace]];
wires: Set ~ ct.CTParts[w];
ct.fullName[w] ← BiRels.GenCreate[spaces: [d.eSpace, steppyNameSpace], hints: namingHints];
ct.fullName[i] ← BiRels.GenCreate[spaces: [d.eSpace, steppyNameSpace], hints: namingHints];
ct.asu ←
NEW [UnorganizedPrivate ← [
exports: exports,
publics: exports.SetOn[right]
]];
ct.asu.exportable ← wires.Intersection[Sets.CreateFilter[[TestExportable, d.eSpace, ct]]];
ct.asu.publicOrExportable ← ct.asu.publics.Union[ct.asu.exportable];
ct.asu.stuck ← wires.Difference[ct.asu.publicOrExportable];
};
IF NOT d.cellTypes.AddA[ct] THEN ERROR;
[] ← d.ctName.AddSet[BiRels.CreateProduct[[Sets.CreateSingleA[ct, d.eSpace], names]]];
RETURN};
TestExportable:
PROC [val: Sets.Value, data:
REF
ANY ←
NIL]
RETURNS [
BOOL] ~ {
ct: CellType ~ NARROW[data];
w: Wire ~ NARROW[val.VA];
IF ct.asu.publics.HasMember[val] THEN RETURN [FALSE];
{kids: Seq ~ BiRels.DeRef[ct.d.sub.ApplyA[w].MDA];
IF kids=nilBiRel THEN RETURN [TRUE];
RETURN ct.ExportableKids[kids]}};
CreatePort:
PUBLIC
PROC [ct: CellType, fullNames: Set
--of SteppyName--, addum, fixExpConns, fixInstConns, fixWExpConns, fixWInstConns:
BOOL, children: Seq
--of Port-- ← nilBiRel]
RETURNS [p: Port] ~ {
d: Design ~ ct.d;
atomic: BOOL ~ children = nilBiRel;
FixUse:
PROC [use: CellUse] ~ {
WITH use
SELECT
FROM
ci: CellInstance => {
cct: CellType ~ d.CiCct[ci];
kidWires: Seq ← nilBiRel;
w: Wire ← NIL;
{
IF
NOT atomic
THEN {
kidWires ← children.Compose[ci.conns];
IF kidWires.Size#children.Size THEN GOTO DontConnect;
{ssi: SubsIndex ~ d.SubseqIndex[kidWires];
IF ssi.multiparents THEN GOTO DontConnect;
IF ssi.full THEN {w ← NARROW[ssi.parent]; GOTO Connect};
IF NOT addum THEN GOTO DontConnect;
IF ssi.parent#NIL THEN GOTO DontConnect;
kidWires ← kidWires.CreateVectorCopy}}
ELSE IF NOT addum THEN GOTO DontConnect;
w ← CreateWire[cct, IF cct.inheritNames THEN ActualNames[cct.INames[ci], fullNames] ELSE emptySteppySet, fixWExpConns, fixWInstConns, kidWires];
EXITS Connect => use ← use};
Connect[d, w, p, ci];
RETURN
EXITS DontConnect => ct ← ct};
act: CellType => NoteNewEltPort[act, p];
ENDCASE => ERROR};
p ← NEW [PortPrivate ← []];
d.cct[p].AddNewAA[p, ct];
KnowPortNames[d, p, fullNames];
IF children # nilBiRel
THEN {
d.sub.AddNewAA[p, children.Refify];
[]← d.parent.AddSet[BiRels.CreateProduct[[children.SetOn[right], Sets.CreateSingleA[p, d.eSpace]]]];
IF fixExpConns
THEN {
IF ct.asu#NIL THEN ClosePortsConnectivity[d, p, children, ct.asu.exports, ct];
IF ct.asArray#NIL THEN NoteNewArrayPort[ct, p]};
};
IF addum OR (fixInstConns AND NOT atomic) THEN ct.EnumerateUses[FixUse];
RETURN};
ClosePortsConnectivity:
PROC [d: Design, parent: Port, kidPorts: Seq
--of Port--, conns: Fn
--Port
b Wire--, site: Cell] ~ {
kidWires: Seq--of Wire-- ~ kidPorts.Compose[conns];
IF kidWires.Size#kidPorts.Size THEN RETURN;
{si: SubsIndex ~ d.SubseqIndex[kidWires];
IF NOT si.full THEN RETURN;
IF si.parent=NIL THEN ERROR;
Connect[d, NARROW[si.parent], parent, site];
RETURN}};
CreateWire:
PUBLIC
PROC [ct: CellType, fullNames: Set
--of SteppyName--, fixExpConns, fixInstConns:
BOOL, children: Seq
--of Wire-- ← nilBiRel]
RETURNS [w: Wire] ~ {
d: Design ~ ct.d;
FixConn:
PROC [porta:
REF
ANY, site: Cell] ~ {
p0: Port ~ NARROW[porta];
pp: Port ~ d.PParent[p0];
IF pp=NIL THEN RETURN;
IF NOT ((fixExpConns AND fixInstConns) OR (WITH site SELECT FROM ci: CellInstance => fixInstConns, ct: CellType => fixExpConns, ENDCASE => ERROR)) THEN RETURN;
{kidPorts: Seq ~ BiRels.DeRef[d.sub.ApplyA[pp].MA];
kidWires: Seq ~ kidPorts.Compose[SiteConns[site]];
IF kidWires.Equal[children] THEN Connect[d, w, pp, site];
RETURN}};
w ← NEW [VertexPrivate[w] ← [variant: w[conns: BiRels.CreateHashReln[spaces: [d.eSpace, d.eSpace]]] ]];
d.cct[w].AddNewAA[w, ct];
KnowVertexNames[d, w, fullNames];
IF children # nilBiRel
THEN {
d.sub.AddNewAA[w, children.Refify];
[]← d.parent.AddSet[BiRels.CreateProduct[[children.SetOn[right], Sets.CreateSingleA[w, d.eSpace]]]];
IF fixExpConns
OR fixInstConns
THEN {
c0: Wire ~ NARROW[children.ApplyI[0].MA];
c0.conns.EnumAA[FixConn];
w ← w};
w ← w};
RETURN};
Instantiate:
PUBLIC
PROC [ict, cct: CellType, addum:
BOOL, names: Set
--of SteppyName--]
RETURNS [ci: CellInstance] ~ {
d: Design ~ ict.d;
ci ← NEW [VertexPrivate.i ← [variant: i[BiRels.CreateHashFn[[d.eSpace, d.eSpace]] ]]];
d.cct[i].AddNewAA[ci, cct];
d.ciType.AddNewAA[ci, ict];
KnowVertexNames[d, ci, names];
IF addum
THEN {
do: Set--of Port-- ← ict.CTParts[p];
UNTIL do.Empty
DO
wait: Set--of Port-- ~ Sets.CreateHashSet[d.eSpace];
DumPort:
PROC [pval: Sets.Value]
RETURNS [
BOOL] ~ {
p: Port ~ NARROW[pval.VA];
kidPorts: Seq--of Port-- ~ BiRels.DeRef[d.sub.Apply[pval].MDA];
kidWires: Seq--of Wire-- ~ IF kidPorts#nilBiRel THEN kidPorts.Compose[ci.conns] ELSE nilBiRel;
IF kidPorts#nilBiRel
AND kidPorts.Size # kidWires.Size
THEN {
IF NOT wait.AddElt[pval] THEN ERROR;
RETURN [FALSE]};
{w: Wire ~ CreateWire[cct, IF cct.inheritNames THEN ActualNames[names, ict.PNames[p]] ELSE emptySteppySet, FALSE--don't bother, we know it's private--, FALSE--don't bother, it's taken care of by me--, kidWires];
Connect[d, w, p, ci];
RETURN [FALSE]}};
IF do.Scan[DumPort].found THEN ERROR;
do ← wait;
ENDLOOP;
ci ← ci};
RETURN};
KnowVertexNames:
PUBLIC
PROC [d: Design, v: Vertex, fullNames: Set
--of SteppyName--] ~ {
bestNewM: Sets.MaybeValue ~ fullNames.AnElt[Sets.fwd];
IF NOT bestNewM.found THEN RETURN;
{bestNew: SteppyName ~ VSn[bestNewM.it];
ct: CellType ~ NARROW[d.cct[v.class].ApplyA[v].MA];
bestOldM: Sets.MaybeValue ~ ct.fullName[v.class].Lookup[goal: AV[v], side: left];
IF bestOldM.found
THEN {
bestOld: SteppyName ~ VSn[bestOldM.it];
IF SteppyNameGradeCompare[bestOld.grade, bestNew.grade] < equal THEN RETURN};
[] ← ct.fullName[v.class].AddSet[BiRels.CreateProduct[[Sets.CreateSingleA[v, d.eSpace], fullNames]]];
RETURN}};
ForgetVertexName:
PUBLIC
PROC [d: Design, v: Vertex, fullName: SteppyName] ~ {
ct: CellType ~ NARROW[d.cct[v.class].ApplyA[v].MA];
[] ← ct.fullName[v.class].RemPair[[AV[v], SnV[fullName]]];
RETURN};
KnowPortNames:
PUBLIC
PROC [d: Design, p: Port, fullNames: Set
--of SteppyName--] ~ {
ct: CellType ~ d.PCct[p];
[] ← ct.fullName[p].AddSet[BiRels.CreateProduct[[Sets.CreateSingleA[p, d.eSpace], fullNames]]];
RETURN};
ForgetPortName:
PUBLIC
PROC [d: Design, p: Port, fullName: SteppyName] ~ {
ct: CellType ~ NARROW[d.cct[p].ApplyA[p].MA];
[] ← ct.fullName[p].RemPair[[AV[p], SnV[fullName]]];
RETURN};
PortForWire:
PUBLIC
PROC [ct: CellType, internal: Wire, mayAdd:
BOOL]
RETURNS [port: Port] ~ {
mv: Sets.MaybeValue ← ct.asu.exports.Lookup[goal: AV[internal], order: Sets.alleq];
IF
NOT mv.found
THEN {
FullySfwdlyExportWires[ct, NonPublicDescendants[ct, internal]];
mv ← ct.asu.exports.Lookup[goal: AV[internal], order: Sets.alleq]};
IF NOT mv.found THEN ERROR;
RETURN [NARROW[mv.MA]]};
FullySfwdlyExportWires:
PUBLIC
PROC [ct: CellType, wires: Set] ~ {
d: Design ~ ct.d;
childWires: Set ~ d.parent.Image[wires, rightToLeft];
badKids: Set ~ childWires.Difference[wires.Union[ct.asu.publics]];
newPorts: Seq--of Port-- ~ CreateSeq[dense: TRUE];
DoWire:
PROC [w: Wire]
RETURNS [p: Port] ~ {
p ← AConndPort[ct, w];
IF p#NIL THEN RETURN;
{kidWires: Seq--of Wire-- ~ BiRels.DeRef[d.sub.ApplyA[w].MDA];
kidPorts: Seq--of Port-- ← nilBiRel;
IF kidWires#nilBiRel
THEN {
kidPorts ← BiRels.CreateVector[rightSpace: d.eSpace];
FOR i:
LNAT
IN [0 .. kidWires.Size.
EN)
DO
kidWire: Wire ~ NARROW[kidWires.ApplyI[i].MA];
kidPort: Port ~ DoWire[kidWire];
kidPorts.AddNewIA[i, kidPort];
w ← w; ENDLOOP;
w ← w};
p ← CreatePort[ct, IF ct.inheritNames THEN WNames[ct, w] ELSE emptySteppySet, FALSE, FALSE, FALSE, FALSE, FALSE, kidPorts];
Connect[d, w, p, ct];
newPorts.AppendA[p];
RETURN}};
StartExport:
PROC [val: Sets.Value]
RETURNS [
BOOL] ~ {
[] ← DoWire[NARROW[val.VA]];
RETURN [FALSE]};
FixUse:
PROC [use: CellUse] ~ {
WITH use
SELECT
FROM
ci: CellInstance => {
cct: CellType ~ d.CiCct[ci];
FOR i:
LNAT
IN [0 .. newPorts.Size.
EN)
DO{
p: Port ~ NARROW[newPorts.ApplyI[i].MA];
kidPorts: Seq--of Port-- ~ BiRels.DeRef[d.sub.ApplyA[p].MDA];
kidWires: Seq--of Wire-- ← nilBiRel;
w: Wire;
{
IF kidPorts#nilBiRel
THEN {
kidWires ← kidPorts.Compose[ci.conns];
IF kidWires.Size # kidPorts.Size THEN GOTO DontDoit;
{ssi: SubsIndex ~ d.SubseqIndex[kidWires];
IF ssi.multiparents THEN GOTO DontDoit;
IF ssi.full THEN {w ← NARROW[ssi.parent]; GOTO GotIt};
IF ssi.parent#NIL THEN GOTO DontDoit;
IF NOT cct.ExportableKids[kidWires] THEN GOTO DontDoit;
}};
w ← CreateWire[cct, IF ct.inheritNames THEN ActualNames[cct.INames[ci], ct.PNames[p]] ELSE emptySteppySet, TRUE, TRUE, kidWires];
w ← w;
EXITS GotIt => use ← use};
Connect[d, w, p, ci];
w ← w;
EXITS DontDoit => ct ← ct
}ENDLOOP;
RETURN};
act: CellType => {
FOR i:
LNAT
IN [0 .. newPorts.Size.
EN)
DO
p: Port ~ NARROW[newPorts.ApplyI[i].MA];
NoteNewEltPort[act, p];
ct ← ct; ENDLOOP;
RETURN};
ENDCASE => ERROR};
IF NOT badKids.Empty THEN ERROR;
IF NOT wires.Intersection[ct.asu.publics].Empty THEN ERROR;
IF wires.Scan[StartExport].found THEN ERROR;
ct.EnumerateUses[FixUse];
RETURN};
Connect:
PUBLIC
PROC [d: Design, wire: Wire, port: Port, site: Cell] ~ {
conns: Fn
--Port
b Wire-- ~
WITH site
SELECT
FROM
ci: CellInstance => ci.conns,
ct: CellType => ct.asu.exports,
ENDCASE => ERROR;
[] ← conns.AddAA[port, wire];
[] ← wire.conns.AddAA[port, site];
RETURN};
MergeNets:
PUBLIC
PROC [d: Design, w1, w2: Wire]
RETURNS [merged, deleted: Wire] ~ {
ct: CellType ~ d.WCct[w1];
SwitchConn:
PROC [cell:
REF
ANY] ~ {
WITH cell
SELECT
FROM
ci: CellInstance => ci.conns.SubstituteA[deleted, merged, right];
cct: CellType => IF ct # cct THEN ERROR;
ENDCASE => ERROR};
IF w1=w2 THEN ERROR;
IF ct # d.WCct[w2] THEN ERROR;
IF ct.asu.publics.HasMemA[w1] OR ct.asu.publics.HasMemA[w2] THEN ERROR;
IF d.isntTop.HasMemA[w1] OR d.isntTop.HasMemA[w2] THEN ERROR;
IF NOT (d.Atomic[w1] AND d.Atomic[w2]) THEN ERROR;
merged ← w1;
deleted ← w2;
IF NOT d.cct[w].DeleteA[deleted] THEN ERROR;
ct.asu.exports.SubstituteA[deleted, merged, right];
deleted.conns.SetOn[right].EnumA[SwitchConn];
[] ← merged.conns.AddSet[deleted.conns];
ct.fullName[w].SubstituteA[deleted, merged, left];
RETURN};
RaTv:
PROC [ra:
REF
ANY]
RETURNS [AMTypes.
TV] ~
TRUSTED {
RETURN AMBridge.TVForReferent[NEW [REF ANY ← ra], const]};
Start[];
END.