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: 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.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
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--, 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[];
END.