<> <> <> <> <<>> DIRECTORY Core, CoreBeau, CoreClasses, CoreOps, CoreProperties, CoreSequence, IO, Rope; CoreBeauImpl: CEDAR PROGRAM IMPORTS CoreClasses, CoreOps, CoreProperties, CoreSequence, IO, Rope EXPORTS CoreBeau = BEGIN OPEN CoreBeau; <> UnionSequences: PROC [wireSeq1, wireSeq2: WireSequence] RETURNS [wireSeq: WireSequence] = { wireSeq _ CoreOps.CreateBasicSequenceWire[wireSeq1.size+wireSeq2.size].elements; FOR i: NAT IN [0 .. wireSeq1.size) DO wireSeq[i] _ wireSeq1[i] ENDLOOP; FOR i: NAT IN [0 .. wireSeq2.size) DO wireSeq[i+wireSeq1.size] _ wireSeq2[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]; wireSeq: WireSequence => RETURN [CoreOps.WireSequenceToWire[wireSeq]]; rope: ROPE => RETURN [CoreOps.CreateAtomWire[name: rope]]; ENDCASE => ERROR }; FindWireInWireSeq: PROC [wr: WR, wireSeq: WireSequence] RETURNS [Wire] = { matchingWires: LIST OF Wire _ NIL; FindInEach: CoreOps.EachWireProc = { name: ROPE _ CoreOps.GetWireName[wire]; match: BOOL _ FALSE; WITH wr SELECT FROM wrwire: Wire => match _ wire=wrwire OR (name#NIL AND Rope.Equal[name, CoreOps.GetWireName[wrwire]]); wrwireSeq: WireSequence => match _ wire.elements=wrwireSeq; wrrope: ROPE => match _ Rope.Equal[name, wrrope]; ENDCASE => ERROR; IF match THEN matchingWires _ CONS [wire, matchingWires]; }; [] _ CoreOps.VisitWireSequence[wireSeq, FindInEach]; RETURN [IF matchingWires=NIL THEN NIL ELSE matchingWires.first]; }; ListifyBindings: PROC [pas: LIST OF PA] RETURNS [revpas: LIST OF PA _ NIL] = { <> WHILE pas#NIL DO IF pas.first#[] THEN revpas _ CONS [pas.first, revpas]; pas _ pas.rest; ENDLOOP; }; IndexInPublic: PROC [wire: Wire, public: WireSequence] RETURNS [index: INT _ -1] = { FOR i: NAT IN [0 .. public.size) DO IF public[i]=wire THEN RETURN [i] ENDLOOP; }; <> Wires: PUBLIC PROC [wr1, wr2, wr3, wr4, wr5, wr6, wr7: WR _ NIL] RETURNS [WireSequence] = { RETURN [CoreOps.WiresToWireSequence[WRsToWires[LIST [wr1, wr2, wr3, wr4, wr5, wr6, wr7]]]]; }; <<>> Seq: PUBLIC PROC [wr: WR, length: NAT] RETURNS [WireSequence] = { WITH wr SELECT FROM wire: Wire => RETURN [CoreOps.CreateBasicSequenceWire[length].elements]; rope: ROPE => RETURN [CoreOps.CreateBasicSequenceWire[length, rope].elements]; ENDCASE => ERROR }; <<>> Index: PUBLIC PROC [wr: WR, index: NAT] RETURNS [WR] = { WITH wr SELECT FROM wire: Wire => RETURN [wire.elements[index]]; wireSeq: WireSequence => RETURN [wireSeq[index]]; rope: ROPE => RETURN [IO.PutFR["%g[%g]", IO.rope[rope], IO.int[index]]]; ENDCASE => ERROR }; <<>> Indexes: PUBLIC PROC [wr: WR, start: NAT _ 0, length: NAT] RETURNS [WireSequence] = { WITH wr SELECT FROM wire: Wire => RETURN [CoreOps.SubrangeWire[wire, start, length].elements]; wireSeq: WireSequence => RETURN [CoreOps.SubrangeWire[CoreOps.WireSequenceToWire[wireSeq], start, length].elements]; rope: ROPE => { subWires: LIST OF Wire _ NIL; FOR i: NAT DECREASING IN [0 .. length) DO subWires _ CONS [CoreOps.CreateAtomWire[IO.PutFR["%g[%g]", IO.rope[rope], IO.int[i]]], subWires]; ENDLOOP; RETURN [CoreOps.CreateSequenceWire[subWires].elements]; }; ENDCASE => ERROR }; <> Instance: PUBLIC PROC [type: CellType, pa1, pa2, pa3, pa4, pa5, pa6: PA _ []] RETURNS [CellInstance] = { pas: LIST OF PA _ ListifyBindings[LIST [pa1, pa2, pa3, pa4, pa5, pa6]]; actual: WireSequence _ CoreOps.CopyWireSequence[type.public]; ReplaceBinding: CoreOps.EachWirePairProc = { replacementActuals: LIST OF Wire _ NIL; FOR bindings: LIST OF PA _ pas, bindings.rest WHILE bindings#NIL DO IF bindings.first.public=publicWire 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 THEN { actualWire^ _ replacementActuals.first^; subWires _ FALSE; }; }; FOR bindings: LIST OF PA _ pas, bindings.rest WHILE bindings#NIL DO <> bindings.first.public _ FindWireInWireSeq[bindings.first.public, type.public]; ENDLOOP; [] _ CoreOps.VisitBinding[actual, type.public, ReplaceBinding]; IF type=NIL THEN ERROR; -- early detection of this error might be useful RETURN [NEW [CoreClasses.CellInstanceRec _ [actual: actual, type: type]]]; }; <<>> Cell: PUBLIC PROC [name: ROPE _ NIL, public, onlyInternal: WireSequence _ NIL, instances: LIST OF CellInstance] RETURNS [CellType] = { data: CoreClasses.RecordCellType _ NEW [CoreClasses.RecordCellTypeRec _ [internal: UnionSequences[public, onlyInternal], instances: instances]]; <> ReplaceABI: PROC [actualWire: Wire, internal: WireSequence] RETURNS [newActualWire: Wire] = { newActualWire _ FindWireInWireSeq[actualWire, internal]; IF newActualWire#NIL THEN RETURN; IF actualWire.elements=NIL THEN ERROR; -- non structured wire not found in the internal newActualWire _ CoreOps.WireSequenceToWire[ReplaceActualByInternal[actualWire.elements, internal]]; }; ReplaceActualByInternal: PROC [actual, internal: WireSequence] RETURNS [newActual: WireSequence] = { wire: Wire _ FindWireInWireSeq[actual, internal]; IF wire#NIL THEN RETURN [wire.elements]; newActual _ CoreOps.CreateBasicSequenceWire[actual.size].elements; FOR i: NAT IN [0 .. actual.size) DO newActual[i] _ ReplaceABI[actual[i], internal]; ENDLOOP; }; cellType: CellType; IF public=NIL THEN public _ CoreOps.CreateBasicSequenceWire[0].elements; IF onlyInternal=NIL THEN onlyInternal _ CoreOps.CreateBasicSequenceWire[0].elements; cellType _ CoreOps.CreateCellType[class: CoreClasses.recordCellClass, public: public, data: data, name: name]; <> FOR insts: LIST OF CellInstance _ instances, insts.rest WHILE insts#NIL DO insts.first.actual _ ReplaceActualByInternal[insts.first.actual, data.internal]; ENDLOOP; RETURN [cellType]; }; <> Transistor: PUBLIC PROC [name: ROPE _ NIL, type: TransistorType _ nE, length: NAT _ 2, width: NAT _ 4] RETURNS [CellType] = { cellType: CellType _ CoreClasses.TransistorCreate[[ type: type, length: length, width: width ]]; CoreProperties.PutCellTypeProp[cellType, CoreOps.nameProp, name]; RETURN [cellType]; }; <<>> SequenceCell: PUBLIC PROC [name: ROPE _ NIL, baseCell: CellType, count: NAT, sequencePorts: WireSequence _ NIL] RETURNS [CellType] = { cellType: CellType; seqCell: CoreSequence.SequenceCellType; IF sequencePorts=NIL THEN sequencePorts _ CoreOps.CreateBasicSequenceWire[0].elements; 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; IF (seqCell.sequence[i] _ IndexInPublic[publicWire, baseCell.public])=-1 THEN ERROR; ENDLOOP; seqCell.base _ baseCell; seqCell.count _ count; cellType _ CoreSequence.Create[name: name, args: seqCell]; RETURN [cellType]; }; <> FindWire: PUBLIC PROC [cell: CellType, wr: WR] RETURNS [Wire] = { RETURN [FindWireInWireSeq[wr, IF cell.class=CoreClasses.recordCellClass THEN NARROW[cell.data, CoreClasses.RecordCellType].internal ELSE cell.public]]; }; END.