<> <> <> <> DIRECTORY Core, CoreClasses, CoreFlatten, CoreOps, CoreProperties, IO, Properties, Rope, RoseBind, RoseBindPrivate, RoseControl, RoseEngine, RosePrivates, RoseSimTypes, RoseWireTwiddling, RoseWireTypes, RoseWiring; RoseInstantiateImpl: CEDAR PROGRAM IMPORTS CoreOps, CoreProperties, Properties, RoseBind, RoseBindPrivate, RoseWireTwiddling, RoseWiring, RoseWireTypes EXPORTS RoseControl, RoseEngine, RoseSimTypes = BEGIN OPEN CP: CoreProperties, RoseWireTypes, RoseSimTypes, RoseEngine, RWTg: RoseWireTwiddling; <> <> <> <> BehaviorClass: TYPE = REF BehaviorClassRec; BehaviorClassRec: PUBLIC TYPE = RoseBindPrivate.BehaviorClassRec; Simulation: TYPE = REF SimulationRec; SimulationRec: PUBLIC TYPE = RoseSimTypes.SimulationRec; RoseWireRep: PUBLIC TYPE = RoseSimTypes.RoseWireRep; WireBehaviorKind: TYPE = {simple, switch, mixed, unspecified}; notInWireList: PUBLIC RoseWire _ NEW [RoseWireRep]; notInCellList: PUBLIC RoseCellInstance _ NEW [RoseCellInstanceRep]; roseWireTypeKey: PUBLIC ATOM _ CP.RegisterProperty[$RoseWireTypeKey]; roseWireKey: PUBLIC ATOM _ CP.RegisterProperty[$RoseWireKey]; roseCellKey: PUBLIC ATOM _ CP.RegisterProperty[$RoseCellKey]; wireGroupKey: ATOM = CP.RegisterProperty[$RoseWireGroup]; wireBehaviorKindKey: ATOM = CP.RegisterProperty[$RoseWireBehaviorKind]; coreCellTypeToRoseCellType: ATOM = CP.RegisterProperty[$RoseCellTypeFromCoreCellType]; Instantiate: PUBLIC PROC [cellType: CellType] RETURNS [simulation: Simulation] = { simulation _ NEW [SimulationRec _ [ flatRootType: cellType, rootRecordType: NARROW[cellType.data], sch: NEW [SchedulingRep _ [sim: NIL]] ]]; simulation.sch.sim _ simulation; MakeUpPointers[simulation.rootRecordType.internal, NIL]; ComputeBehaviorKinds[simulation]; FindLeafWires[simulation]; MakeRoseWires[simulation]; MakeRoseCells[simulation]; }; upPointerKey: ATOM = CP.RegisterProperty[$RoseUpPointer]; MakeUpPointers: PROC [wire: Wire, parent: Wire] = { CP.PutWireProp[wire, upPointerKey, parent]; IF wire.elements # NIL THEN { wire _ wire; FOR i: INT IN [0 .. wire.elements.size) DO MakeUpPointers[wire.elements[i], wire]; ENDLOOP; wire _ wire; }; }; GetInternalParent: PUBLIC PROC [wire: Wire] RETURNS [parent: Wire] = {parent _ NARROW[CP.GetWireProp[wire, upPointerKey]]}; IsInternal: PROC [sim: Simulation, wire: Wire] RETURNS [is: BOOL] = {is _ wire=sim.rootRecordType.internal OR CP.GetWireProp[wire, upPointerKey]#NIL}; ComputeBehaviorKinds: PROC [sim: Simulation] = { GetPWPWBK: PROC [publicWirePrototype: Wire, specIn: WireBehaviorKind] RETURNS [pwpWBK: WireBehaviorKind] = { pwpWBK _ GetWBK[publicWirePrototype]; IF pwpWBK = unspecified THEN { thisSpec: WireBehaviorKind _ SELECT CP.GetWireProp[publicWirePrototype, RoseBind.switchWire] FROM =NIL => specIn, #NIL => switch, ENDCASE => ERROR; SELECT StructureOfWire[publicWirePrototype] FROM atom => pwpWBK _ IF thisSpec # unspecified THEN thisSpec ELSE simple; sequence => { IF publicWirePrototype.elements.size = 0 THEN ERROR; FOR i: NAT IN [0 .. publicWirePrototype.elements.size) DO this: WireBehaviorKind _ GetPWPWBK[publicWirePrototype.elements[i], thisSpec]; IF i = 0 THEN pwpWBK _ this ELSE IF pwpWBK # this THEN ERROR; ENDLOOP; pwpWBK _ pwpWBK }; record => { someSwitch, someSimple, some: BOOL _ FALSE; sim _ sim; FOR i: NAT IN [0 .. publicWirePrototype.elements.size) DO sub: WireBehaviorKind _ GetPWPWBK[publicWirePrototype.elements[i], thisSpec]; some _ TRUE; SELECT sub FROM simple => someSimple _ TRUE; switch => someSwitch _ TRUE; mixed => someSimple _ someSwitch _ TRUE; unspecified => ERROR; ENDCASE => ERROR; ENDLOOP; IF NOT some THEN ERROR; pwpWBK _ IF someSimple THEN IF someSwitch THEN mixed ELSE simple ELSE IF someSwitch THEN switch ELSE ERROR; }; ENDCASE => ERROR; SetWBK[publicWirePrototype, pwpWBK]; }; IF specIn # unspecified AND specIn # pwpWBK THEN ERROR; }; GetWBKCopy: PROC [from, to: Wire, proto: BOOL] RETURNS [wbk: WireBehaviorKind] = { wbk _ GetWBK[to]; IF wbk # unspecified THEN RETURN; SELECT StructureOfWire[to] FROM atom => NULL; record, sequence => { from _ from; FOR i: NAT IN [0 .. to.elements.size) DO fromI: NAT _ IF proto AND StructureOfWire[from]=sequence THEN 0 ELSE i; [] _ GetWBKCopy[from.elements[fromI], to.elements[i], proto]; ENDLOOP; to _ to; }; ENDCASE => ERROR; SetWBK[to, wbk _ GetWBK[from]]; IF wbk = unspecified THEN ERROR; }; sim _ sim; FOR il: CellInstanceList _ sim.rootRecordType.instances, il.rest WHILE il # NIL DO ci: CellInstance _ il.first; cic: BehaviorClass _ RoseBindPrivate.GetBehaviorClass[ci.type, FALSE, FALSE, FALSE].class; [] _ GetPWPWBK[cic.publicWirePrototype, unspecified]; [] _ GetWBKCopy[cic.publicWirePrototype, ci.type.public, TRUE]; ENDLOOP; sim _ sim; }; GetWBK: PROC [wire: Wire] RETURNS [wbk: WireBehaviorKind] = { val: REF ANY _ CP.GetWireProp[wire, wireBehaviorKindKey]; wbk _ SELECT val FROM $simple => simple, $switch => switch, $mixed => mixed, NIL => unspecified, ENDCASE => ERROR; }; SetWBK: PROC [wire: Wire, wbk: WireBehaviorKind] = { CP.PutWireProp[ wire, wireBehaviorKindKey, SELECT wbk FROM simple => $simple, switch => $switch, mixed => $mixed, ENDCASE => ERROR ]; }; FindLeafWires: PROC [sim: Simulation] = { FlwAwWork: PROC [public, actual: Wire, drive: RoseWireType] = { pwWBK: WireBehaviorKind _ GetWBK[public]; IF pwWBK=unspecified THEN ERROR; SELECT (IsInternal[sim, actual] AND StructureOfWire[drive.class]=atom AND pwWBK IN [simple..switch]) FROM FALSE => { SELECT StructureOfWire[actual] FROM atom => ERROR; sequence, record => { actual _ actual; FOR i: NAT IN [0 .. actual.elements.size) DO FlwAwWork[ public.elements[i], actual.elements[i], RWTg.SubType[drive, i, TRUE] ]; ENDLOOP; IF CP.GetWireProp[actual, wireGroupKey] = NIL THEN MarkAboveLeaf[actual]; }; ENDCASE => ERROR; }; TRUE => { group: WireGroup _ GetWireGroup[actual]; awWBK: WireBehaviorKind _ GetWBK[actual]; newAWwbk: WireBehaviorKind _ SELECT TRUE FROM awWBK=unspecified => pwWBK, awWBK=mixed => ERROR, awWBK=pwWBK => awWBK, ENDCASE => switch; IF awWBK#pwWBK THEN SetWBK[actual, newAWwbk]; SELECT group FROM aboveLeaf, leaf => NULL; belowLeaf => BreakWire[GetInternalParent[actual]]; ENDCASE => ERROR; }; ENDCASE => ERROR; }; rootWire: Wire _ sim.rootRecordType.internal; MarkAsLeaf[rootWire]; FOR il: CellInstanceList _ sim.rootRecordType.instances, il.rest WHILE il # NIL DO ci: CellInstance _ il.first; cic: BehaviorClass _ RoseBindPrivate.GetBehaviorClass[ci.type, FALSE, FALSE, TRUE].class; driveType: RoseWireType _ cic.wiring[drive].super.GetType[cic.wiring[drive], ci.actual]; FlwAwWork[ci.type.public, ci.actual, driveType]; ENDLOOP; sim _ sim; }; MarkAsLeaf: PROC [wire: Wire] = { CP.PutWireProp[wire, wireGroupKey, $Leaf]; }; MarkAboveLeaf: PROC [wire: Wire] = { CP.PutWireProp[wire, wireGroupKey, $AboveLeaf]; }; GetWireGroup: PUBLIC PROC [wire: Wire] RETURNS [wg: WireGroup] = { val: ATOM _ NARROW[CP.GetWireProp[wire, wireGroupKey]]; wg _ SELECT val FROM $Leaf => leaf, $AboveLeaf => aboveLeaf, NIL => belowLeaf, ENDCASE => ERROR; }; BreakWire: PROC [wire: Wire] = { pg: WireGroup _ GetWireGroup[wire]; FOR i: NAT IN [0 .. wire.elements.size) DO child: Wire _ wire.elements[i]; cg: WireGroup _ GetWireGroup[child]; SELECT cg FROM belowLeaf => MarkAsLeaf[child]; leaf, aboveLeaf => NULL; ENDCASE => ERROR; ENDLOOP; MarkAboveLeaf[wire]; SELECT pg FROM belowLeaf => BreakWire[GetInternalParent[wire]]; leaf => NULL; aboveLeaf => ERROR; ENDCASE => ERROR; }; MakeRoseWires: PROC [sim: Simulation] = { Work: PROC [wire: Wire] = { wg: WireGroup _ GetWireGroup[wire]; SELECT wg FROM belowLeaf => ERROR; aboveLeaf => { wire _ wire; FOR i: INT IN [0 .. wire.elements.size) DO Work[wire.elements[i]]; ENDLOOP; wire _ wire; }; leaf => { rw: RoseWire; rwc: RoseWireClass; rwt: RoseWireType; wbk: WireBehaviorKind _ GetWBK[wire]; rwc _ RoseWiring.GetWiring[ wire, SELECT wbk FROM simple => simple, switch => switch, ENDCASE => ERROR ]; rwt _ rwc.super.GetType[rwc, wire]; CP.PutWireProp[wire, roseWireTypeKey, rwt]; rw _ NEW [RoseWireRep _ [ schIn: sim.sch, core: wire, type: rwt, valPtr: RWTg.CreateUntypedInstance[rwt], bitCount: rwt.class.super.Bits[rwt.class], group: wg, nextPerturbed: notInWireList, nextAffected: notInWireList, nextDelayed: notInWireList, prevDelayed: notInWireList ]]; SetRoseWire[sim, wire, rw]; }; ENDCASE => ERROR; }; Work[sim.rootRecordType.internal]; }; MakeRoseCells: PROC [sim: Simulation] = { FOR il: CellInstanceList _ sim.rootRecordType.instances, il.rest WHILE il # NIL DO ci: CellInstance = NARROW[il.first]; args: REF ANY = CP.GetCellTypeProp[ci.type, RoseBind.argsKey]; rct: RoseCellType = GetRoseCellType[ci.type, TRUE, TRUE]; bc: BehaviorClass = rct.behaviorClass; pw: Wire = ci.type.public; rci: RoseCellInstance _ NEW [RoseCellInstanceRep _ [ schIn: sim.sch, core: ci, args: args, type: rct, effectivePorts: NIL, connectedWires: NIL, schedNext: notInCellList, nextNeeded: notInCellList, nextNoted: notInCellList, switchIO: bc.private.createSwitch[pw], newIO: bc.private.createSimple[pw], oldIO: bc.private.createSimple[pw], newDrive: bc.private.createDrive[pw], oldDrive: bc.private.createDrive[pw] ]]; IF rci.type.behaviorClass.details.CreateState # NIL THEN rci.state _ rci.type.behaviorClass.details.CreateState[args]; [rci.effectivePorts, rci.connectedWires, rci.hasTransducedPort] _ ComputeEffectiveInterface[rci]; CP.PutCellInstanceProp[ ci, roseCellKey, Properties.PutProp[ NARROW[CP.GetCellInstanceProp[ci, roseCellKey]], sim, rci]]; ENDLOOP; sim _ sim; }; GetRoseCellType: PUBLIC PROC [ct: CellType, details, privates: BOOL] RETURNS [rct: RoseCellType] = { rct _ NARROW[CP.GetCellTypeProp[ct, coreCellTypeToRoseCellType]]; IF rct = NIL THEN { bc: BehaviorClass; [bc] _ RoseBindPrivate.GetBehaviorClass[ct, FALSE, FALSE, TRUE]; rct _ NEW [RoseCellTypeRep _ [ behaviorClass: bc, wireTypes: [ switch: bc.wiring[switch].super.GetType[bc.wiring[switch], ct.public], simple: bc.wiring[simple].super.GetType[bc.wiring[simple], ct.public], drive: bc.wiring[drive].super.GetType[bc.wiring[drive], ct.public] ] ]]; CP.PutCellTypeProp[ct, coreCellTypeToRoseCellType, rct]; }; IF details OR privates THEN { goodDetails, goodPrivate: BOOL; [goodDetails, goodPrivate] _ RoseBindPrivate.EnsureBCParts[rct.behaviorClass, details, privates]; IF (details AND NOT goodDetails) OR (privates AND NOT goodPrivate) THEN ERROR; }; }; ComputeEffectiveInterface: PROC [rci: RoseCellInstance] RETURNS [effectivePorts: EffectivePortS, connectedWires: RoseWireS, hasTransducedPort: BOOL] = { length, index: NAT _ 0; Count: PROC [wire: Wire] = { wg: WireGroup _ GetWireGroup[wire]; SELECT wg FROM belowLeaf => ERROR; aboveLeaf => { wire _ wire; FOR i: INT IN [0 .. wire.elements.size) DO Count[wire.elements[i]]; ENDLOOP; wire _ wire; }; leaf => length _ length + 1; ENDCASE => ERROR; }; Fillin: PROC [public, actual: Wire, switchType, simpleType, driveType: RoseWireType, switch, newSimple, oldSimple, newDrive, oldDrive: Ptr, path: PortPath] = { wg: WireGroup _ GetWireGroup[actual]; SELECT wg FROM belowLeaf => ERROR; aboveLeaf => { actual _ actual; FOR i: INT IN [0 .. actual.elements.size) DO Fillin[ public.elements[i], actual.elements[i], RWTg.SubType[switchType, i], RWTg.SubType[simpleType, i], RWTg.SubType[driveType, i, TRUE], RWTg.SubPtr[switchType, switch, i], RWTg.SubPtr[simpleType, newSimple, i], RWTg.SubPtr[simpleType, oldSimple, i], RWTg.SubPtr[driveType, newDrive, i, TRUE], RWTg.SubPtr[driveType, oldDrive, i, TRUE], PathAppend[path, i] ]; ENDLOOP; actual _ actual; }; leaf => { rw: RoseWire _ GetRoseWire[rci.schIn.sim, actual]; wbkP: WireBehaviorKind _ GetWBK[public]; wbkA: WireBehaviorKind _ GetWBK[actual]; pSimple: BOOL _ SELECT wbkP FROM simple => TRUE, switch => FALSE, ENDCASE => ERROR; aSimple: BOOL _ SELECT wbkA FROM simple => TRUE, switch => FALSE, ENDCASE => ERROR; transduced: BOOL = (aSimple # pSimple); me: Slot = [rci, index]; modelType: RoseWireType = IF pSimple THEN simpleType ELSE switchType; IF transduced AND aSimple THEN ERROR; IF transduced THEN hasTransducedPort _ TRUE; effectivePorts[index] _ [ switch: switch, newSimple: newSimple, oldSimple: oldSimple, newDrive: newDrive, oldDrive: oldDrive, type: modelType, implType: IF transduced THEN switchType ELSE modelType, path: path, input: TRUE, output: TRUE, XPhobic: pSimple, transduced: transduced ]; SELECT aSimple FROM TRUE => { initialStrength: Strength = none; prev: Slot = rw.byStrength[initialStrength].last; effectivePorts[index].curStrength _ initialStrength; effectivePorts[index].strengthNext _ nilSlot; effectivePorts[index].strengthPrev _ prev; IF prev = nilSlot THEN rw.byStrength[initialStrength].first _ me ELSE prev.cell.effectivePorts[prev.effectivePortIndex].strengthNext _ me; rw.byStrength[initialStrength].last _ me; }; FALSE => { rw.switchConnections _ CONS[me, rw.switchConnections]; rw.XPhobic _ rw.XPhobic OR effectivePorts[index].XPhobic; }; ENDCASE => ERROR; connectedWires[index] _ rw; index _ index + 1; }; ENDCASE => ERROR; }; hasTransducedPort _ FALSE; Count[rci.core.actual]; effectivePorts _ NEW [EffectivePortSeq[length]]; connectedWires _ NEW [RoseWireSeq[length]]; Fillin[ rci.core.type.public, rci.core.actual, rci.type.wireTypes[switch], rci.type.wireTypes[simple], rci.type.wireTypes[drive], RWTg.RefToPtr[rci.switchIO, rci.type.wireTypes[switch]], RWTg.RefToPtr[rci.newIO, rci.type.wireTypes[simple]], RWTg.RefToPtr[rci.oldIO, rci.type.wireTypes[simple]], RWTg.RefToPtr[rci.newDrive, rci.type.wireTypes[drive]], RWTg.RefToPtr[rci.oldDrive, rci.type.wireTypes[drive]], NIL ]; IF index # length THEN ERROR; }; PathAppend: PROC [path: PortPath, index: INT] RETURNS [longer: PortPath] = { RETURN [IF path = NIL THEN LIST[index] ELSE CONS[path.first, PathAppend[path.rest, index]]]; }; GetRoseCell: PUBLIC PROC [sim: Simulation, ci: CellInstance] RETURNS [rci: RoseCellInstance] = { propList: Properties.PropList _ NARROW[CP.GetProp[ci.properties, roseCellKey]]; rci _ NARROW[Properties.GetProp[propList, sim]]; }; SetRoseWire: PROC [sim: Simulation, wire: Wire, rw: RoseWire] = { CP.PutWireProp[ wire, roseWireKey, Properties.PutProp[ NARROW[CP.GetWireProp[wire, roseWireKey]], sim, rw]]; }; GetRoseWire: PUBLIC PROC [sim: Simulation, w: Wire] RETURNS [rw: RoseWire] = { propList: Properties.PropList _ NARROW[CP.GetProp[w.properties, roseWireKey]]; rw _ NARROW[Properties.GetProp[propList, sim]]; }; LookupRoseWire: PUBLIC PROC [sim: Simulation, w: Wire] RETURNS [rw: RoseWire] = { Work: PROC [sim: Simulation, w: Wire, parent: RoseWire, index: NAT, valPtr: Ptr] RETURNS [rw: RoseWire] = { rw _ GetRoseWire[sim, w]; IF parent # NIL THEN { IF rw.parent = NIL THEN { rw.parent _ parent; rw.myIndex _ index; } ELSE { IF rw.parent # parent OR rw.myIndex # index THEN ERROR; }; }; IF rw = NIL THEN { group: WireGroup = GetWireGroup[w]; flavor: WireFlavor = GetWireFlavor[sim, w]; rwc: RoseWireClass = RoseWiring.GetWiring[w, flavor]; rwt: RoseWireType = rwc.super.GetType[rwc, w]; CP.PutWireProp[w, roseWireTypeKey, rwt]; rw _ NEW [RoseWireRep _ [ schIn: sim.sch, core: w, type: rwt, bitCount: rwt.class.super.Bits[rwt.class], group: group, nextPerturbed: notInWireList, nextAffected: notInWireList, nextDelayed: notInWireList, prevDelayed: notInWireList ]]; SELECT group FROM aboveLeaf => { rw.valPtr _ IF parent # NIL THEN valPtr ELSE RWTg.CreateUntypedInstance[rwt]; rw.subWires _ NEW [RoseWireSeq[w.elements.size]]; FOR i: NAT IN [0 .. rw.subWires.length) DO subPtr: Ptr = RWTg.SubPtr[rwt, rw.valPtr, i]; rw.subWires[i] _ Work[sim, w.elements[i], rw, i, subPtr]; ENDLOOP; rw _ rw; }; leaf => ERROR; belowLeaf => { parent: Wire = GetInternalParent[w]; myIndex: NAT = GetIndex[parent, w]; rw.parent _ Work[sim, parent, NIL, LAST[NAT], nilPtr]; rw.myIndex _ myIndex; rw.valPtr _ RWTg.SubPtr[rw.parent.type, rw.parent.valPtr, myIndex]; }; ENDCASE => ERROR; SetRoseWire[sim, w, rw]; }; }; rw _ Work[sim, w, NIL, LAST[NAT], nilPtr]; }; RoseWireSource: PUBLIC PROC [rw: RoseWire] RETURNS [sim: Simulation, w: Wire] = { sim _ rw.schIn.sim; w _ rw.core; }; GetWireFlavor: PROC [sim: Simulation, w: Wire] RETURNS [flavor: WireFlavor] = { group: WireGroup = GetWireGroup[w]; SELECT group FROM aboveLeaf => { flavor _ simple; FOR i: INT IN [0 .. w.elements.size) DO sf: WireFlavor = GetWireFlavor[sim, w.elements[i]]; SELECT sf FROM simple => NULL; switch => {flavor _ switch; EXIT}; drive => ERROR; ENDCASE => ERROR; ENDLOOP; }; leaf => flavor _ GetRoseWire[sim, w].type.class.super.flavor; belowLeaf => { parent: Wire = GetInternalParent[w]; flavor _ GetWireFlavor[sim, parent]; }; ENDCASE => ERROR; }; GetIndex: PROC [parent, child: Wire] RETURNS [index: NAT] = { FOR index IN [0 .. parent.elements.size) DO IF parent.elements[index] = child THEN RETURN; ENDLOOP; ERROR; }; flattenToBehavior: PUBLIC CoreFlatten.FlattenControl _ NEW [CoreFlatten.FlattenControlRec _ [DecideByBehavior, NIL]]; DecideByBehavior: PROC [data: REF ANY, who: CoreFlatten.InstantiationPath] RETURNS [ed: CoreFlatten.ExpandDecision] = { ci: CellInstance = who.first; ed _ IF RoseBindPrivate.GetBehaviorClass[ci.type, TRUE, FALSE, FALSE].goodDetails THEN leaf ELSE expand; }; FlattenStructure: PUBLIC PROC [from: Core.CellType] RETURNS [fc: CoreFlatten.FlattenControl] = { fc _ NEW [CoreFlatten.FlattenControlRec _ [DecideByStructure, from]]; }; DecideByStructure: PROC [data: REF ANY, who: CoreFlatten.InstantiationPath] RETURNS [ed: CoreFlatten.ExpandDecision] = { ct: CellType _ IF who # NIL THEN who.first.type ELSE NARROW[data]; WHILE ct.class.recast # NIL DO ct _ CoreOps.Recast[ct]; ENDLOOP; WITH ct.data SELECT FROM rct: CoreClasses.RecordCellType => RETURN [expand]; ENDCASE => RETURN [leaf]; }; END.