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: 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 = { 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; {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 = { 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. ςDAToolsIntroAdder4BehProc.mesa Bland, October 9, 1987 12:07:21 pm PDT Louis Monier October 9, 1987 9:56:34 am PDT The Directory Statement lists all interfaces needed at compile time. The Import Statement lists all interfaces needed at run time. PA is a binding between a public wire of the celltype and the corresponding actual wire of a cellInstance The name and size of all structured public wires must be given. Atomic public wires are named without size. This creates a celltype with the two things that Rosemary needs: the celltype's public wire sequence and its property list. ls = level sequence, used for structured wires. l = level, used for atomic wires. The Oracle's inputs, Cout and SUM, have drive. Its outputs do not. --PROC [cellType: Core.CellType, p: Ports.Port, oldStateAny: REF ANY _ NIL] RETURNS [stateAny: REF ANY _ NIL]-- 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. --PROC [p: Ports.Port, stateAny: REF ANY, clockEval: BOOL]-- This procedure models an edge-triggered flipflop. The purpose of the clockEval is to decompose each settle in two phases in order to let the clocks settle before using them to modify states. A typical test proc is composed of two calls to the Eval proc, one with clockEval=TRUE, during which all combinatorial paths settle, including clocks, but during which no state depending on a clock is changed; then one with clockEval=FALSE where everything must be evaluated. Inputs are copied into the master portion of the flipflop while the clock is low and enable is high. Values are output by the slave portion of the edge-triggered flipflop when the clock is high. (Enable is only an input to the master part of the flipflop, c.f. Logic.) Always assign the values of the registers to the output wires. Most important: If the cell has edge-triggered behavior, register it with scheduleIfClockEval: TRUE Κε˜deaulft™Icode™&L™+—™L™D—šΟk ˜ LšœC˜C—J™šΡblnœœ˜(L™=Lšœ)˜0—šœ˜˜Lšœ œ˜ Lšœ œœœ˜(Lšœœ˜Lšœ œ˜$Lšœœœ˜Lšœœ ˜šœœ˜Lšœœ[Οc ™j—Lšœœœ˜Lšœœœ˜L˜Lšœ œœ˜4Lšœ œœ%˜=Lšœ œœ˜%šœœœ˜LšœŸ˜&LšœŸ˜!Lšœœœ˜$Lšœ˜——L˜šžœœœœ˜;Lšœo™ošœ#˜#šœ˜Lšœ˜Lšœ˜Lšœ˜Lšœ˜Lšœ ˜ Lšœ˜Lšœ˜—Lšœ˜—L™{Lšœ4˜4L˜LšœK˜KL™L™/L™!L™CL™Lšœ(˜(Lšœ3˜3Lšœ&˜&Lšœ%˜%Lšœ˜L˜—šžœ˜(LšŸo™oL˜Lš œœ œœœœœ˜iLšœœ˜8Lšœœ˜7Lšœ'˜'Lšœ&˜&Lšœ˜Lšœ˜L™ΚšœœŸ/˜DLšœv˜v—Lšœ˜Lšœ˜Lšœ˜L˜—šžœ˜(LšŸ*œ Ÿ™