DIRECTORY BitOps, Core, CoreFlat, Ports, PW, Rope, Rosemary, RosemaryUser, Sisyph, TerminalIO;

RosemaryExample: CEDAR PROGRAM
IMPORTS CoreFlat, Ports, PW, Rosemary, RosemaryUser, Sisyph, TerminalIO
= BEGIN
myDesignName: Rope.ROPE = "MyDesign";
-- the name of the ChipNDale file MyCell resides in
myCx: Sisyph.Context _ Sisyph.Create[PW.OpenDesign[myDesignName]];
-- the Sisyph context derived from this design; needed for extraction

Error: PROC [msg: Rope.ROPE] ~ {TerminalIO.PutRopes[msg, "\n"]; ERROR};
MyCellName: Rope.ROPE = Rosemary.Register[roseClassName: "MyCell", init: MyCellInit, evalSimple: MyCellSimple];

MyCell: PROC RETURNS [ct: Core.CellType] = {
ct _ Sisyph.ES[name: "MyCell", cx: myCx];

[] _ Rosemary.BindCellType[cellType: ct, roseClassName: MyCellName];

Ports.InitPorts[ct, l, none, "Vdd", "Gnd", "Clock"];	-- level (H, L, X), and inputs only
Ports.InitPorts[ct, ls, none, "In"];		-- level sequence, and input only
Ports.InitPorts[ct, ls, drive, "Out"];		-- level sequence, and output only
};

MyCellState: TYPE = REF MyCellStateRec;
MyCellStateRec: TYPE = RECORD [
in, out, vdd, gnd, ck: NAT _ LAST[NAT],
previousClock: Ports.Level _ L,
master, slave: Ports.LevelSequence
];

MyCellInit: Rosemary.InitProc = { -- PROC [cellType: Core.CellType, p: Ports.Port, oldStateAny: REF ANY _ NIL, steady: BOOL _ FALSE] RETURNS [stateAny: REF ANY _ NIL]n: NAT _ NARROW[CoreProperties.GetCellTypeProp[cellType, $n], REF NAT]^ 
state: MyCellState _ IF oldStateAny#NIL THEN NARROW[oldStateAny] ELSE NEW[MyCellStateRec];
[state.in, state.out, state.vdd, state.gnd, state.ck] _ Ports.PortIndexes[cellType.public, "In", "Out", "Vdd", "Gnd", "Clock"];
state.master _ NEW[Ports.LevelSequenceRec[4]];
state.slave _ NEW[Ports.LevelSequenceRec[4]];
Ports.SetLS[state.master, X];
Ports.SetLS[state.slave, X];
-- initialize the state
stateAny _ state;
-- you have to return the state as a REF ANY, so don't forget this
};

MyCellSimple: Rosemary.EvalProc = { -- PROC [p: Ports.Port, stateAny: REF ANY]
state: MyCellState _ NARROW[stateAny];
IF p[state.vdd].l#H OR p[state.gnd].l#L THEN Error["Turn on the power supply, please"];
SELECT p[state.ck].l FROM
L => Ports.CopyLS[from: p[state.in].ls, to: state.master];
H => IF state.previousClock=L THEN Ports.CopyLS[from: state.master, to: state.slave];
-- up transition
ENDCASE => NULL;
Ports.CopyLS[from: state.slave, to: p[state.out].ls];		-- always
state.previousClock _ p[state.ck].l;
};

MyCellTest: RosemaryUser.TestProc = { -- PROC [cellType: Core.CellType, p: Ports.Port, Eval: PROC]
in, out, vdd, gnd, ck: NAT _ LAST[NAT];
[in, out, vdd, gnd, ck] _ Ports.PortIndexes[cellType.public, "In", "Out", "Vdd", "Gnd", "Clock"];
[] _ Rosemary.SetFixedWire[cellType.public[vdd], H];
[] _ Rosemary.SetFixedWire[cellType.public[gnd], L];
[] _ Ports.InitPort[cellType.public[ck], l];
[] _ Ports.InitTesterDrive[cellType.public[ck], force];

[] _ Ports.InitPort[cellType.public[in], ls];
[] _ Ports.InitTesterDrive[cellType.public[in], force];

[] _ Ports.InitPort[cellType.public[out], ls];
[] _ Ports.InitTesterDrive[cellType.public[out], none];

Ports.LCToLS[0FH, p[in].ls];	-- initial value, in hex notation

p[ck].l _ L;
p[out].d _ none;
Eval[];

p[ck].l _ H;
Eval[];

p[ck].l _ L;
p[out].d _ none;
Eval[];

p[ck].l _ H;
Ports.LCToLS[0FH, p[out].ls];	-- the expected value
p[out].d _ expect;
Eval[];
};

CreateSimulation: PROC [ct: Core.CellType, cutSets: LIST OF Rope.ROPE _ NIL] = {
tester: RosemaryUser.Tester _ RosemaryUser.TestProcedureViewer[
cellType: ct, 
testButtons: LIST["OnOfTheManyPossibleTests"], 
name: "MyCellTest", 
displayWires: RosemaryUser.DisplayPortLeafWires[ct], 
cutSet: CoreFlat.CreateCutSet[cellTypes: cutSets]
];
Rosemary.Initialize[simulation: tester.display.simulation, steady: FALSE]
};

RosemaryUser.RegisterTestProc["MyCellTest", MyCellTest];	
-- associates a test proc with a button
[] _ CreateSimulation[ct: MyCell[], cutSets: LIST[MyCellName]];

END.
MyCellName: Rope.ROPE = Rosemary.Register[roseClassName: "MyCell", init: MyCellInit, evalSimple: MyCellSimple];
MyCell: PROC RETURNS [ct: Core.CellType] = {
ct _ either extract the cell or calls a proc;
[] _ Rosemary.BindCellType[cellType: ct, roseClassName: MyCellName];
Ports.InitPorts[ct, l, ls, b, c, lc, none, drive, "Vdd", "Gnd", "Clock"];
};
MyCellState: TYPE = REF MyCellStateRec;
MyCellStateRec: TYPE = RECORD [
in, out, vdd, gnd, ck: NAT _ LAST[NAT],
any other state: any type, including Ports.Level and Ports.LevelSequence
];
MyCellInit: Rosemary.InitProc = { 
state: MyCellState _ IF oldStateAny#NIL THEN NARROW[oldStateAny] ELSE NEW[MyCellStateRec];
[state.in, state.out] _ Ports.PortIndexes[cellType.public, "In", "Out"];
stateAny _ state;
-- you have to return the state as a REF ANY, so don't forget this
};
MyCellSimple: Rosemary.EvalProc = {
state: MyCellState _ NARROW[stateAny];
body of the proc
};

MyCellTest: RosemaryUser.TestProc = { -- PROC [cellType: Core.CellType, p: Ports.Port, Eval: PROC]
in, out: NAT _ Ports.PortIndex[cellType.public, "In", "Out"];
[] _ Rosemary.SetFixedWire[cellType.public[vdd], H];
[] _ Rosemary.SetFixedWire[cellType.public[gnd], L];
[] _ Ports.InitPort[cellType.public[ck], l, ls, b, c, lc];
[] _ Ports.InitTesterDrive[cellType.public[ck], none, force, expect];

set values and drives on ports
Eval[];
set values and drives on ports
Eval[];
};
CreateSimulation: PROC [ct: CellType, cutSets: LIST OF Rope.ROPE _ NIL] = {
tester _ RosemaryUser.TestProcedureViewer[
cellType: ct, 
testButtons: LIST["OnOfTheManyPossibleTests"], 
name: "MyCellTest", 
displayWires: RosemaryUser.DisplayPortLeafWires[ct], 
cutSet: CoreFlat.CreateCutSet[cellTypes: cutSets]
];
Rosemary.Initialize[simulation: tester.display.simulation, steady: FALSE]
};

RosemaryUser.RegisterTestProc["MyCellTest", MyCellTest];	
[] _ CreateSimulation[ct: MyCell[], cutSets: LIST[MyCellName]];



���²��RosemaryExample.tioga
Copyright c 1987 by Xerox Corporation.  All rights reserved.
Last Edited by: Louis Monier January 5, 1987 8:15:51 pm PST
Barth, January 30, 1987 2:50:55 pm PST

-- This is an example of simulation using Rosemary; three parts:
-- how to get a cellType (by extracting an icon in a CD design);
-- how to define a high-level behavioral simulation procedure for this cellType;
-- how to write a test procedure for this a cellType;
-- Generic advice: go take a look at the Ports and BitOps interfaces.
Convenient thingies
-- The generic error
MyCell
-- This binds a pair of procs (initialization and simulation) with the name under which a cellType will be registered
-- This proc returns the cellType;
-- We suppose that there is a cell "MyCell.icon" in the design "MyDesign".
-- extract the cell by name
-- we supoose that the public wires are "Vdd", "Gnd", "Clock", Seq["In", 4], Seq["Out", 4];
-- register this cellType with Rosemary; 
-- the pair of procs cited above can now be used for simulation
-- specify the type and direction of wires for simulation
-- This is the safest way to proceed: for every public wire, you need an index in order to get the the value on the coprresponding port; nothing garantees the order in which wires appear, so if you hide these indexes in the global frame, you might get a stale value. The best place is in this record. It is a pain to redefine such a record for every cellType you simulate, but it is sooooo much safer...
-- with LAST[NAT] you'll catch non-initializes values
-- the state associated with the cell: in this case two LevelSequence
-- This proc is called once before the simulation starts; it was registered above
-- create a new state or reuse an old one
-- finds the index of public wires in the cellType
-- This proc is called by Rosemary whenever ... (RICK, HELP!!!!)
-- This is an example of edge-triggered latch where the output is always a copy of `slave': when the clock is low, it samples the input into master; on an up-transition of the clock, it copies the value of master into the slave and stop sampling the input.
-- Rosemary can call this proc whenever it pleases, so we need to keep in the state a value of the previous clock in order to differentiate.
-- can't hurt!
-- level sequences are refs, so you need this proc to copy the values
-- This proc is called once per Eval[]
-- port indexes, again

-- power on

-- the clock is a level (one bit, values among L, H, X), and the tester forces its value
-- the input is a level sequence, and the tester forces its value
-- the output is a sequence, and the tester ignores its value initially
-- the register now contains 0FH; output is ignored (because of `none')
-- Because of expect, the computed value will be compared with the value we specify.
-- If the output is incorrect, an error window will open.
-- Final call: this creates a tester panel
-- creates a simulation; the cutset specifies to use the simulation proc defined for this cell


�ÊU��˜�codešœ™Kšœ
Ïmœ1™<K™;K™&K™�—•StartOfExpansion[]™@K™@K™PK™5—K™EK˜�K˜�KšÏk	œU˜^K˜�šÐlnœžœž˜Kšžœ@˜GKšœž˜—head™šœžœ˜%KšÏc3˜3—šœ%žœ˜BKš E˜E—K˜�šÏnœžœžœ%žœ˜GK™——™K™uKš¡
œžœZ˜oK˜�K™"K™Jš¡œžœžœ˜,šœžœ˜)K™K™[—K˜�šœD˜DK™)K™?—K˜�Kšœ5 #˜XKšœ& !˜Gšœ( "˜JK™9—Kšœ˜—K˜�K™“Kšœ
žœžœ˜'šœžœžœ˜šœžœžœžœ˜'Kšœ5™5—K˜šœ"˜"KšœE™E—Kšœ˜—K˜�K™Qš¡
œÏsÐcs̘îš
œžœ
žœžœžœžœžœ˜ZK™)—šœ˜K™2—Kšœžœ˜.Kšœžœ˜-Kšœ˜šœ˜Kš ˜—šœ˜Kš B˜B—Kšœ˜K˜�—K™@K™€K™Œš¡œ¢£*˜NKšœžœ˜&šžœžœžœ+˜WKš ™—šžœž˜šœ:˜:Kš E™E—šœžœžœ3˜UKš ˜—Kšžœžœ˜—Kšœ7 	˜@Kšœ$˜$Kšœ˜—K˜�K™&š¡
œ £9˜bKšœžœžœžœ˜'šœa˜aKš ™K™�—Kšœ4˜4šœ4˜4K™K™�—Kšœ,˜,šœ7˜7K™X—K˜�Kšœ-˜-šœ7˜7K™A—K˜�Kšœ.˜.šœ7˜7K™G—K˜�Kšœ !˜>K˜�Kšœ˜Kšœ˜J˜J˜�Kšœ˜˜JšœG™G—K˜�Kšœ˜Kšœ˜J˜J˜�Kšœ˜Kšœ ˜3Kšœ˜˜KšœT™TK™9—K˜—K˜�K™*š¡œžœžœžœžœžœ˜Pšœ?˜?Kšœ˜Kšœ
žœ˜/Kšœ˜Kšœ5˜5Kšœ1˜1Kšœ˜—JšœCžœ˜IK˜—K˜�šœ9˜9Kš '˜'—šœ-žœ˜?K™^——K˜�Kšžœ˜K™�KšÏt¡
¤œžœ$¤œ¤œ¤œ
¤œ¤œ¤œ˜wš¤¡¤œžœžœ¤œ¤œ˜0Kš¤œ¤œ¤œ'¤œ˜1Kš	œ%¤œ¤œ¤œ
¤œ˜HKšœ¤œ¤œ¤œ¤œ¤œ¤œ¤œ¤œ¤œ¤œ˜SKšœ˜—Kš¤œ¤œžœžœ¤œ¤œ˜+š¤œ¤œžœžœ˜!Kš
¤œ¤œžœžœžœ˜)Kš¤œ¤<˜LKšœ˜—š¤¡
¤œ¢˜$Kšœ¤œ¤œžœ
žœžœžœžœžœ¤œ¤œ˜^Kš	œ¤œ¤œ'¤œ¤œ˜Lšœ˜Kš B˜B—Kšœ˜—š¤¡¤œ˜%Kšœ¤œ¤œžœ˜(Kš¤œ¤˜Kšœ˜—K˜�š¡
œ £9˜bKš
¤œ¤œžœ$¤œ¤œ˜AKšœ4˜4šœ4˜4K™�—Kš	œ$¤œ¤œ¤œ¤œ˜>Kš	œ+¤œ¤œ¤œ¤œ˜IK˜�Jš¤œ¤˜ J˜Jš¤œ¤˜ J˜K˜—š¡œžœžœžœžœžœ˜Kšœ*˜*Kšœ˜Kšœ
žœ¤œ¤œ˜1Kšœ¤œ¤œ˜Kšœ5˜5Kšœ1˜1Kšœ˜—JšœCžœ˜IK˜—K˜�Kš	œ¤œ¤œ¤œ
¤œ˜=Kšœ¤œ¤œžœ¤œ
¤œ˜CK˜�Inil˜�J˜�—�…—����0��*7��