LichenDataImpl2.Mesa
Last tweaked by Mike Spreitzer on June 8, 1988 5:15:46 pm 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, LichenIntBasics, PrintTV, SetBasics
EXPORTS LichenDataOps
=
BEGIN OPEN LIB:LichenIntBasics, LIB, LichenDataStructure, LichenDataOps, Sets:AbSets;
startInheriting: BOOLFALSE;
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.eSetSpace ← Sets.CreateSetSpace[d.eSpace];
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];
d.ciXfm ← BiRels.CreateHashTable[[d.eSpace, xfmSpace]];
d.scale ← 0.0;
d.other ← BiRels.CreateHashTable[];
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, bbox: Range2, 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,
isDeduced: [
p: [
FALSE: Sets.CreateHashSet[],
TRUE: Sets.CreateHashSet[]],
w: [
FALSE: Sets.CreateHashSet[],
TRUE: Sets.CreateHashSet[]]],
bbox: bbox,
other: BiRels.CreateHashTable[]
]];
IF flavor=unorganized THEN {
exports: BiRel ~ BiRels.CreateHashFn[[d.eSpace, d.eSpace]];
wires: Set ~ ct.CTParts[w];
w2i: Fn ~ BiRels.FnFromProc[WireToInstances, [d.eSpace, d.eSetSpace], d];
i2w: Fn ~ BiRels.FnFromProc[InstanceToWires, [d.eSpace, d.eSetSpace], d];
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,
iwConns: BiRels.CreateFromHalves[
spaces: ALL[d.eSpace],
halves: [[dullHalfClass, i2w], [dullHalfClass, w2i]]],
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};
dullHalfClass: BiRels.HalfClass ~ NEW [BiRels.HalfClassPrivate ← [NIL]];
WireToInstances: PROC [data: REF ANY, v: Sets.Value] RETURNS [mv: Sets.MaybeValue] ~ {
w: Wire ~ NARROW[v.VA];
d: Design ~ NARROW[data];
RETURN [[TRUE, w.conns.SetOn[right].SV[]]]};
InstanceToWires: PROC [data: REF ANY, v: Sets.Value] RETURNS [mv: Sets.MaybeValue] ~ {
ci: CellInstance ~ NARROW[v.VA];
d: Design ~ NARROW[data];
RETURN [[TRUE, ci.conns.SetOn[right].SV[]]]};
TestExportable: PROC [val: Sets.Value, data: REF ANYNIL] 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--, deduced, 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, FALSE, 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];
IF NOT ct.isDeduced[p][deduced].AddA[p] THEN ERROR;
KnowPortNames[ct, p, fullNames, FALSE];
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--, deduced, 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];
IF NOT ct.isDeduced[w][deduced].AddA[w] THEN ERROR;
KnowVertexNames[ct, w, fullNames, FALSE];
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, xfm: Transform, offset: Int2, names: Set--of SteppyName--] RETURNS [ci: CellInstance] ~ {
d: Design ~ ict.d;
ci ← NEW [VertexPrivate.i ← [variant: i[BiRels.CreateHashFn[[d.eSpace, d.eSpace]], offset]]];
d.cct[i].AddNewAA[ci, cct];
d.ciType.AddNewAA[ci, ict];
d.ciXfm.AddNewPair[[AV[ci], XfmV[xfm]]];
IF NOT Range2Empty[ict.bbox] THEN cct.bbox ← Range2Mbb[cct.bbox, TransOffRange2[xfm, offset, ict.bbox]];
KnowVertexNames[cct, ci, names, FALSE];
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, 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};
KnowPartName: PUBLIC PROC [ct: CellType, class: PartClass, part: Part, fullName: SteppyName, onlyIfGood: BOOL]
~ {KnowPartNames[ct, class, part, Sets.CreateSingleton[SnV[fullName], steppyNameSpace], onlyIfGood]};
KnowPartNames: PUBLIC PROC [ct: CellType, class: PartClass, part: Part, fullNames: Set--of SteppyName--, onlyIfGood: BOOL] ~ {
IF onlyIfGood THEN {
bestNewM: Sets.MaybeValue ~ fullNames.AnElt[Sets.fwd];
IF NOT bestNewM.found THEN RETURN;
{bestNew: SteppyName ~ VSn[bestNewM.it];
bestOldM: Sets.MaybeValue ~ ct.fullName[class].Lookup[goal: AV[part], side: left];
IF bestOldM.found THEN {
bestOld: SteppyName ~ VSn[bestOldM.it];
IF GrossSteppyNameGradeCompare[bestOld.grade, bestNew.grade] < equal THEN RETURN};
}};
[] ← ct.fullName[class].AddSet[BiRels.CreateProduct[[Sets.CreateSingleA[part, ct.d.eSpace], fullNames]]];
RETURN};
ForgetPartName: PUBLIC PROC [ct: CellType, class: PartClass, part: Part, fullName: SteppyName] ~ {
[] ← ct.fullName[class].RemPair[[AV[part], SnV[fullName]]];
RETURN};
GrossSteppyNameGradeCompare: PROC [g1, g2: SteppyNameGrade] RETURNS [SetBasics.TotalComparison] ~ {
RETURN [SELECT TRUE FROM
g1.global<g2.global => greater,
g1.global>g2.global => less,
g1.gend<g2.gend => less,
g1.gend>g2.gend => greater,
ENDCASE => equal];
};
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, 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, FALSE, 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] ~ {
cct: CellType ~ d.WCct[wire];
conns: Fn--Port b Wire--;
WITH site SELECT FROM
ci: CellInstance => conns ← ci.conns;
ct: CellType => {conns ← ct.asu.exports; IF ct#cct THEN ERROR};
ENDCASE => ERROR;
[] ← conns.AddAA[port, wire];
[] ← wire.conns.AddAA[port, site];
RETURN};
RaTv: PROC [ra: REF ANY] RETURNS [AMTypes.TV] ~ TRUSTED {
RETURN AMBridge.TVForReferent[NEW [REF ANY ← ra], const]};
Start: PROC ~ {
RETURN};
Start[];
END.