SimulationHandle Property
Only 1 simulation per design, because the simulation handle is stored on a property on the cd design.
simulationHandleProp: ATOM ← $SinixSimulationHandle;
SimulationHandle: TYPE = REF SimulationHandleRec;
SimulationHandleRec:
TYPE =
RECORD [
simulation: RoseControl.Simulation,
instance: CD.Instance, -- instance being simulated
flatten: Core.CellType -- flattened instance
];
Commands from the menu
Extract:
PROC [command: CDSequencer.Command] = {
Extracts all selected instances
time: BasicTime.GMT ← BasicTime.Now[]; -- Start the stop watch
count: INT ← 0;
TerminalIO.WriteRope["Extraction started ...\n"];
FOR list:
CD.InstanceList ← CDOps.InstList[command.design], list.rest
WHILE list#
NIL
DO
obj: CD.Object ← list.first.ob;
IF list.first.selected
THEN {
count ← count+1;
[] ← ExtractObj[obj];
};
ENDLOOP;
TerminalIO.WriteF[NIL, IO.int[count], IO.rope[" objects extracted in "], IO.int[BasicTime.Period[time, BasicTime.Now[]]], IO.rope[" seconds\n"]];
};
DescribeWire:
PROC [command: CDSequencer.Command] = {
Finds a (the first one) wire belonging to the set of extracted cells at the click position, highlights it, and prints all the known information about it (properties).
wire: Core.Wire ← NIL; position: CD.Position; orientation: CD.Orientation;
[wire, position, orientation] ← FindWireAtPos[command.design, command.pos];
IF wire=NIL THEN {TerminalIO.WriteRope[Rope.Cat["No Core.Wire in the extracted cells at this location\n"]]; RETURN};
TerminalIO.WriteRope[Rope.Cat["At this location, Core.Wire name: ", wire.name, "\n"]];
FOR viewers:
LIST
OF ViewerClasses.Viewer ← CDViewer.ViewersOf[command.design], viewers.rest
WHILE viewers#
NIL
DO
HighLightWire[viewers.first, wire, position, orientation];
ENDLOOP;
};
InitializeSimulation:
PROC [command: CDSequencer.Command] = {
multiple: BOOL;
rootCellType: Core.CellType ← NIL;
handle: SimulationHandle ← NEW [SimulationHandleRec];
[handle.instance, multiple] ← CDOps.SelectedInstance[command.design];
IF multiple THEN {TerminalIO.WriteRope["Only 1 selection\n"]; RETURN};
rootCellType ← ExtractObj[handle.instance.ob];
CDProperties.PutPropOnDesign[command.design, simulationHandleProp, handle];
TerminalIO.WriteRope["Flattening ...\n"];
handle.flatten ← SinixFlatten.Flatten[rootCellType, SinixFlatten.NonTransistorsExpand].flat;
TerminalIO.WriteRope["Flattening completed\n"];
TerminalIO.WriteRope["Initializing simulation ...\n"];
handle.simulation ← RoseControl.Instantiate[rootCellType];
RoseControl.Initialize[handle.simulation];
TerminalIO.WriteRope["Initialization of simulation completed\n"];
};
Settle:
PROC [command: CDSequencer.Command] = {
handle: SimulationHandle ← NARROW [CDProperties.GetPropFromDesign[command.design, simulationHandleProp]];
TerminalIO.WriteRope["Stepping simulation ...\n"];
RoseControl.Settle[handle.simulation];
TerminalIO.WriteRope["Stepping simulation done!\n"];
};
FetchValue:
PROC [command: CDSequencer.Command] = {
handle: SimulationHandle ← NARROW [CDProperties.GetPropFromDesign[command.design, simulationHandleProp]];
wire: Core.Wire ← NIL; position: CD.Position; orientation: CD.Orientation;
[wire, position, orientation] ← FindWireAtPos[command.design, command.pos];
IF wire=NIL THEN {TerminalIO.WriteRope["No Core.Wire in the extracted cells at this location\n"]; RETURN};
TerminalIO.WriteRope[Rope.Cat["At this location, Core.Wire name: ", wire.name, "\n"]];
TerminalIO.WriteRope[Rope.Cat["Value of wire ", wire.name, " is: ", RoseControl.FetchValue[handle.simulation, wire]]];
};
ForceValue:
PROC [command: CDSequencer.Command] = {
handle: SimulationHandle ← NARROW [CDProperties.GetPropFromDesign[command.design, simulationHandleProp]];
wire: Core.Wire ← NIL; position: CD.Position; orientation: CD.Orientation;
[wire, position, orientation] ← FindWireAtPos[command.design, command.pos];
IF wire=NIL THEN {TerminalIO.WriteRope[Rope.Cat["No Core.Wire in the extracted cells at this location\n"]]; RETURN};
TerminalIO.WriteRope[Rope.Cat["At this location, Core.Wire name: ", wire.name, "\n"]];
RoseControl.ForceValue[handle.simulation, wire, TerminalIO.RequestRope[Rope.Cat["New Value of wire ", wire.name, " : "]]];
};
Auxiliary functions for the commands
ExtractObj:
PROC [obj:
CD.Object]
RETURNS [extractedCellType: Core.CellType] = {
ok: BOOL;
[extractedCellType, ok] ← Sinix.ExtractObj[obj];
TerminalIO.WriteF[NIL, IO.rope["Extraction of "], IO.rope[CDDirectory.Name[obj]], IO.rope[IF ok THEN " **** errors\n" ELSE " ok\n"]];
};
FindWireAtPos:
PROC [cdDesign:
CD.Design, pos:
CD.Position]
RETURNS [wire: Core.Wire ←
NIL, position:
CD.Position, orientation:
CD.Orientation] = {
wire=NIL means wire not found. position and orientation are relative to the design.
FOR list:
CD.InstanceList ← CDOps.InstList[cdDesign], list.rest
WHILE list#
NIL
DO
cdInstance: CD.Instance ← list.first;
obj: CD.Object ← cdInstance.ob;
cellType: Core.CellType ← NARROW [CDProperties.GetPropFromObject[obj, Sinix.extractedCoreProp]];
IF cellType=NIL THEN LOOP;
[wire, position, orientation] ← FindWireAtPosInCellType[cellType, CDOrient.DeMapPoint[pos, obj.size, cdInstance.orientation, cdInstance.location]];
IF wire#
NIL
THEN
RETURN [
wire,
CDOrient.MapPoint[position, cdInstance.ob.size, cdInstance.orientation, cdInstance.location],
CDOrient.ComposeOrient[orientation, cdInstance.orientation]
];
ENDLOOP;
};
FindWireAtPosInCellType:
PROC [cellType: Core.CellType, pos:
CD.Position]
RETURNS [wire: Core.Wire ←
NIL, position:
CD.Position ← [0, 0], orientation:
CD.Orientation ← 0] = {
wire=NIL means wire not found. position and orientation are for the [0, 0] of the cellType containing wire
elements: Core.WireSequence ← cellType.public.elements;
FOR i:
NAT
IN [0 .. elements.size)
DO
wire ← elements[i];
IF PosInInstanceList[pos, Sinix.GetWireGeometryPropFromWire[wire]] THEN RETURN;
ENDLOOP;
SELECT cellType.class
FROM
CoreClasses.recordCellClass => {
data: CoreClasses.RecordCellType ← NARROW [cellType.data];
internalElements: Core.WireSequence ← data.internal.elements;
FOR i:
NAT
IN [0 .. internalElements.size)
DO
wire ← internalElements[i];
IF PosInInstanceList[pos, Sinix.GetWireGeometryPropFromWire[wire]] THEN RETURN;
ENDLOOP;
FOR instances: CoreClasses.CellInstanceList ← data.instances, instances.rest
WHILE instances#
NIL
DO
cdInstance: CD.Instance ← NARROW [CoreProperties.GetCellInstanceProp[instances.first, Sinix.instanceProp]];
[wire, position, orientation] ← FindWireAtPosInCellType[instances.first.type, CDOrient.DeMapPoint[pos, cdInstance.ob.size, cdInstance.orientation, cdInstance.location]];
IF wire#
NIL
THEN
RETURN [
wire,
CDOrient.MapPoint[position, cdInstance.ob.size, cdInstance.orientation, cdInstance.location],
CDOrient.ComposeOrient[orientation, cdInstance.orientation]
];
ENDLOOP;
};
CoreClasses.transistorCellClass => {};
ENDCASE => ERROR;
wire ← NIL;
};
HighLightWire:
PROC [viewer: ViewerClasses.Viewer, wire: Core.Wire, position:
CD.Position, orientation:
CD.Orientation, removeOthers:
BOOL ←
TRUE] = {
instances: LIST OF CD.Instance ← HighLightListInst[NARROW[CoreProperties.GetProp[wire.properties, Sinix.wireGeometryProp]]];
cell: CD.Object ← CDCells.CreateEmptyCell[];
cellPtr: CD.CellPtr ← NARROW [cell.specificRef];
instance: CD.Instance ← NEW [CD.InstanceRep ← [ob: cell, location: position, orientation: orientation]];
cellPtr.contents ← instances;
CDViewHighlight.ShowInstance[viewer, instance, removeOthers];
};
HighLightListInst:
PROC [instances:
LIST
OF
CD.Instance]
RETURNS [hlist:
LIST
OF
CD.Instance ←
NIL] = {
WHILE instances#
NIL
DO
hlist ← CONS[HighLightInst[instances.first], hlist]; instances ← instances.rest;
ENDLOOP;
};
HighLightInst:
PROC [inst:
CD.Instance]
RETURNS [hinst:
CD.Instance] = {
hinst ←
NEW [
CD.InstanceRep ← [
ob: IF inst.ob.class.objectType=$PinOb0 THEN CDRects.CreateRect[inst.ob.size, CD.highLightShade] ELSE HighLightOb[inst.ob],
location: inst.location, orientation: inst.orientation]];
};
HighLightOb:
PROC [ob:
CD.Object]
RETURNS [hob:
CD.Object] = {
SELECT ob.class.objectType
FROM
$Rect => hob ← CDRects.CreateRect[ob.size, CD.highLightShade];
$Cell => {
cellPtr, hcellPtr: CD.CellPtr;
hob ← CDCells.CreateEmptyCell[];
cellPtr ← NARROW [ob.specificRef];
hcellPtr ← NARROW [hob.specificRef];
hcellPtr.contents ← HighLightListInst[cellPtr.contents];
hob.size ← ob.size;
};
ENDCASE => {
hob ← CDDirectory.ExpandHard[ob, NIL, NIL];
IF hob=NIL THEN RETURN[CDRects.CreateRect[ob.size, CD.combined]];
hob ← HighLightOb[hob];
};
};
PosInInstanceList:
PROC [pos:
CD.Position, instances:
LIST
OF
CD.Instance]
RETURNS [yes:
BOOL ←
FALSE] = {
WHILE instances#
NIL
DO
IF PosInInstance[pos, instances.first] THEN RETURN [TRUE];
instances ← instances.rest;
ENDLOOP;
};
PosInInstance:
PROC [pos:
CD.Position, instance:
CD.Instance]
RETURNS [yes:
BOOL ←
FALSE] = {
yes ← PosInObject[CDOrient.DeMapPoint[pos, instance.ob.size, instance.orientation, instance.location], instance.ob];
};
PosInObject:
PROC [pos:
CD.Position, ob:
CD.Object]
RETURNS [yes:
BOOL ←
FALSE] = {
SELECT ob.class.objectType
FROM
$Rect => yes ← CDBasics.InsidePos[pos, CDBasics.RectAt[[0, 0], ob.size]];
$Cell => yes ← PosInInstanceList[pos, NARROW [ob.specificRef, CD.CellPtr].contents];
ENDCASE => {
ob ← CDDirectory.ExpandHard[ob, NIL, NIL];
IF ob#NIL THEN yes ← PosInObject[pos, ob];
};
};
Initialization
BEGIN
[] ← CDProperties.RegisterProperty[simulationHandleProp, $Sinix];
CDSequencer.ImplementCommand[$Extract, Extract];
CDMenus.CreateEntry[$RectProgramMenu, "Extract selected", $Extract];
CDSequencer.ImplementCommand[$DescribeWire, DescribeWire];
CDMenus.CreateEntry[$RectProgramMenu, "DescribeWire at pos", $DescribeWire];
CDSequencer.ImplementCommand[$InitializeSimulation, InitializeSimulation];
CDMenus.CreateEntry[$RectProgramMenu, "Initializes simulation", $InitializeSimulation];
CDSequencer.ImplementCommand[$Settle, Settle];
CDMenus.CreateEntry[$RectProgramMenu, "Steps simulation", $Settle];
CDSequencer.ImplementCommand[$FetchValue, FetchValue];
CDMenus.CreateEntry[$RectProgramMenu, "Fetch the value of a wire", $FetchValue];
CDSequencer.ImplementCommand[$ForceValue, ForceValue];
CDMenus.CreateEntry[$RectProgramMenu, "Stores the value of a wire", $ForceValue];
END;