<> <> <> <<>> <> DIRECTORY Core, CoreClasses, CoreCreate, Ports, Rope, Rosemary, RosemaryUser; <<>> DAToolsIntroAdder4BehProc: CEDAR PROGRAM <> IMPORTS CoreClasses, CoreCreate, Ports, Rosemary ~ BEGIN CellType : TYPE = Core.CellType; CellTypes: TYPE = LIST OF Core.CellType; Level: TYPE = Ports.Level; Properties : TYPE = Core.Properties; ROPE: TYPE = Core.ROPE; Wire: TYPE = Core.Wire; Wires: TYPE = Core.Wires; << PA is a binding between a public wire of the celltype and the corresponding actual wire of a cellInstance>> PA: TYPE = CoreCreate.PA; WR: TYPE = CoreCreate.WR; FlipFlop: TYPE = RECORD[master, slave: Ports.Level]; FlipFlops: TYPE = RECORD[master, slave: Ports.LevelSequence]; AdderState: TYPE = REF AdderStateRec; AdderStateRec: TYPE = RECORD [ reg1: FlipFlop, -- holds the carry out reg4: FlipFlops, -- holds the sum en, CIN, A, B, SUM, Cout, Clock: NAT ]; Adder4Definition: PUBLIC PROC [] RETURNS [ct: CellType] = { <> public: Wire _ CoreCreate.WireList[ LIST[ CoreCreate.Seq["SUM",4], CoreCreate.Seq["A",4], CoreCreate.Seq["B",4], "en", "Clock", "Cout", "CIN" ]]; <> ct _ CoreClasses.CreateUnspecified[public: public]; [] _ Rosemary.BindCellType[cellType: ct, roseClassName: Adder4BehProcName]; <<>> <> <> <> <<>> Ports.InitPorts[ct, ls, none, "A", "B"]; Ports.InitPorts[ct, l, none, "en", "Clock", "CIN"]; Ports.InitPorts[ct, l, drive, "Cout"]; Ports.InitPorts[ct, ls, drive,"SUM"]; }; Adder4BehProcInit: Rosemary.InitProc = { <<--PROC [cellType: Core.CellType, p: Ports.Port, oldStateAny: REF ANY _ NIL] RETURNS [stateAny: REF ANY _ NIL]-->> adderstate: AdderState _ IF oldStateAny=NIL THEN NEW[AdderStateRec] ELSE NARROW[oldStateAny, AdderState]; adderstate.reg4.master _ NEW[Ports.LevelSequenceRec[4]]; adderstate.reg4.slave _ NEW[Ports.LevelSequenceRec[4]]; Ports.SetLS[adderstate.reg4.master, X]; Ports.SetLS[adderstate.reg4.slave, X]; adderstate.reg1.master _ X; adderstate.reg1.slave _ X; << This next procedure call is a convenience. It returns the indices of the wires in the public. Names are chosen to allow the sequence of port wires to be indexed by familiar names rather than numbers.>> {OPEN adderstate; -- to avoid having to say adderstate.mumble ... -- [en, CIN, A, B, SUM, Cout, Clock] _ Ports.PortIndexes[cellType.public, "en", "CIN", "A", "B","SUM", "Cout", "Clock"]; }; stateAny _ adderstate; }; Adder4BehProcEval: Rosemary.EvalProc = { <<--PROC [p: Ports.Port, stateAny: REF ANY, clockEval: BOOL]-->> <> i, numHigh: INT; adderstate: AdderState _ NARROW[stateAny]; {OPEN adderstate; << >> <> <<>> <> IF ~clockEval AND p[Clock].l=L AND p[en].l=H THEN { sum: Ports.Level; carry: Ports.Level _ p[CIN].l; numHigh _ 0; FOR i DECREASING IN [0..3] DO [carry, sum] _ Ports.SumL[p[A].ls[i], p[B].ls[i], carry]; adderstate.reg4.master[i] _ sum; ENDLOOP; adderstate.reg1.master _ carry; }; <> IF ~clockEval AND p[Clock].l=H THEN{ Ports.CopyLS[from: adderstate.reg4.master, to: adderstate.reg4.slave]; adderstate.reg1.slave _ adderstate.reg1.master; }; <> p[Cout].l _ adderstate.reg1.slave; Ports.CopyLS[from: adderstate.reg4.slave, to: p[SUM].ls]; }}; <> Adder4BehProcName: ROPE = Rosemary.Register[roseClassName: "Adder4Definition", init: Adder4BehProcInit, evalSimple: Adder4BehProcEval, scheduleIfClockEval: TRUE]; END. <<>>