DIRECTORY
CD USING [Design, Position, Rect],
CDInstances USING [InstRectO],
CDOrient USING [CreateTransform],
CDProperties USING [GetProp],
Convert USING [RopeFromRope],
Core USING [CellType, CellTypeRec, Design, Properties, StructureError, Wire],
CoreOps USING [CreateAtomWire, CreateRecordWire, FetchCellType, InsertCellType],
CoreProperties USING [GetProp, propCompare, PropCompareProc, propCopy, PropCopyProc, propPrint, PropPrintProc, PutProp, RegisterProperty, StoreProperties],
CoreClasses USING [CellInstance, CellInstanceRec, RecordCellType, recordCellClass],
ImagerTransformation USING [Copy, Equal, Transformation],
IO USING [atom, int, PutF, rope, STREAM],
Rope USING [Compare, Equal, ROPE],
SX USING [AreaPerimRec, NodeLocation, SpinifexLayerIndex, TechHandle, TechInfo, TechRec],
SXAtoms USING [cdCellHint, cdDesignHint, crystalAttr, instanceTransf, locInfo, spinifex, strayInfo, techInfo],
SXAccess,
SXOutputPrivate USING [GetAName, PrintActualProc, PrintFormalProc, PrintHeadProc, PrintInstanceEndProc, PrintInstanceHeadProc, PrintLocalNodeProc, PrintStartBodyProc, PrintStrayProc, QuoteProc]
;
SXOutputImplC:
CEDAR PROGRAM
IMPORTS CDInstances, CDOrient, CDProperties, Convert, Core, CoreProperties, CoreOps, CoreClasses, ImagerTransformation, IO, Rope, SXAtoms, SXAccess, SXOutputPrivate
EXPORTS SXOutputPrivate =
Stuff for SXOutputImplA
coreDesign: PUBLIC Core.Design;
coreCellBuffer: PUBLIC Core.CellType;
coreCellInstance: PUBLIC CoreClasses.RecordCellType;
coreInstanceBuffer: PUBLIC CoreClasses.CellInstance;
corePortBuffer, coreNodeBuffer, corePortInstances: PUBLIC LIST OF Core.Wire ← NIL;
strayBuffer: PUBLIC Core.Properties;
QuoteCore:
PUBLIC QuoteProc =
Actually does not quote !
BEGIN
RETURN [Convert.RopeFromRope[from: name, quote: FALSE]]
END; -- QuoteCore
ComputeStray:
PUBLIC PrintStrayProc =
Traverse and copy instance list transforming to l units
BEGIN
stray: LIST OF SX.AreaPerimRec ← NIL; -- unordered
ti: SX.TechInfo = NARROW [CoreProperties.GetProp [coreDesign.properties, SXAtoms.techInfo]];
strayBuffer ← NIL;
FOR i:
LIST
OF
SX.AreaPerimRec ← node.dim, i.rest
WHILE i #
NIL
DO
e: SX.AreaPerimRec;
e.layer ← i.first.layer;
e.area ← i.first.area/(SXAccess.design.technology.lambda*SXAccess.design.technology.lambda);
e.perim ← i.first.perim/SXAccess.design.technology.lambda;
strayBuffer ← CoreProperties.PutProp [strayBuffer, ti.layers[e.layer].id, e]
This scheme cannot be used, because it would require that the layer ids be registered with Core. We want to avoid this registration because it is technology dependent. The information on the technology is attached as a property to the Core design.
It has been suggested with little success that Core owns a standard set of properties required to interchange information between tools. This scheme would allow the tools to be really independent, and Core would be the central data structure it claims to be.
stray ← CONS [e, stray]
ENDLOOP;
strayBuffer ← CoreProperties.PutProp [strayBuffer, SXAtoms.strayInfo, stray]
Note that Core copies around the properties and there is no canonical order mantained.
END; -- ComputeStray
InsertCell:
PUBLIC PrintHeadProc =
BEGIN
coreCellBuffer ← NEW [Core.CellTypeRec];
coreCellBuffer.name ← name;
coreCellBuffer.class ← CoreClasses.recordCellClass;
CoreOps.InsertCellType [design: coreDesign,
cellType: coreCellBuffer
! Core.StructureError => GOTO duplicate];
END; -- InsertCell
InsertPort:
PUBLIC PrintFormalProc =
BEGIN
dummy: IO.STREAM;
port: Core.Wire ← CoreOps.CreateAtomWire [name: qName];
internalNode: Core.Wire ← CoreOps.CreateAtomWire [name: qName];
ComputeStray [dummy, node];
port.properties ← internalNode.properties ← strayBuffer;
corePortBuffer ← CONS [port, corePortBuffer];
coreNodeBuffer ← CONS [internalNode, coreNodeBuffer]
END; -- InsertPort
EndPortList:
PUBLIC PrintStartBodyProc =
[cellName: ROPE]
BEGIN
coreCellBuffer.public ← CoreOps.CreateRecordWire [name: "ports", components: corePortBuffer];
corePortBuffer ← NIL
END;
InsertNode:
PUBLIC PrintLocalNodeProc =
BEGIN
dummy: IO.STREAM;
internalNode: Core.Wire ← CoreOps.CreateAtomWire [name: GetAName[node]];
ComputeStray [dummy, node];
internalNode.properties ← strayBuffer;
coreNodeBuffer ← CONS [internalNode, coreNodeBuffer]
END; -- InsertNode
CreateInstance:
PUBLIC PrintInstanceHeadProc =
BEGIN
cell: Core.CellType = CoreOps.FetchCellType [coreDesign, defName];
t: ImagerTransformation.Transformation;
pos, size: CD.Position;
ir: CD.Rect;
IF cell = NIL THEN ERROR;
coreInstanceBuffer ← NEW [CoreClasses.CellInstanceRec];
coreInstanceBuffer.name ← QuoteCore [GetAName[inst]];
coreInstanceBuffer.actual ← NIL;
coreInstanceBuffer.type ← cell;
ir ← CDInstances.InstRectO [inst];
pos ← [x: ir.x1, y: ir.y1]; size ← [x: ir.x2 - ir.x1, y: ir.y2 - ir.y1];
t ← CDOrient.CreateTransform [cellSize: size, cellInstOrient: inst.orientation, cellInstPos: pos];
coreInstanceBuffer.properties ← CoreProperties.PutProp [on: coreInstanceBuffer.properties, prop: SXAtoms.cdCellHint, value: inst];
coreInstanceBuffer.properties ← CoreProperties.PutProp [on: coreInstanceBuffer.properties, prop: SXAtoms.instanceTransf, value: t]
END; -- CreateInstance
InsertPortInstance:
PUBLIC PrintActualProc =
BEGIN
portInst: Core.Wire ← CoreOps.CreateAtomWire [name: qActualNode];
corePortInstances ← CONS [portInst, corePortInstances]
END; -- InsertPortInstance
EndPortInstanceList:
PUBLIC PrintInstanceEndProc =
BEGIN
coreInstanceBuffer.actual ← CoreOps.CreateRecordWire [name: "port instances", components: corePortInstances];
coreCellInstance.instances ← CONS [coreInstanceBuffer, coreCellInstance.instances];
corePortInstances ← NIL
END; -- EndPortInstanceList
InsertInstances: PUBLIC PrintBodyEndProc =
BEGIN
END; -- InsertInstances
Stuff for Core
Compare: CoreProperties.PropCompareProc =
TYPE = PROC [prop: ATOM, value1, value2: REF ANY] RETURNS [equal: BOOL ← FALSE];
BEGIN
Stray: TYPE = REF SX.AreaPerimRec;
WireLocation: TYPE = REF SX.NodeLocation;
SELECT prop
FROM
SXAtoms.techInfo => {
t1: SX.TechInfo = NARROW [value1]; t2: SX.TechInfo = NARROW [value2];
RETURN [(Rope.Compare[t1.name, t2.name]=equal)]};
SXAtoms.strayInfo =>
We don't compare for now, because these are unordered lists.
RETURN [TRUE];
SXAtoms.locInfo => {
l1: WireLocation = NARROW [value1]; l2: WireLocation = NARROW [value2];
RETURN [(l1.xy.x=l2.xy.x)AND(l1.xy.y=l2.xy.y)AND(l1.layer=l2.layer)]};
SXAtoms.crystalAttr => RETURN [Rope.Equal[NARROW[value1, Rope.ROPE], NARROW[value2, Rope.ROPE], TRUE]];
SXAtoms.cdDesignHint, SXAtoms.cdCellHint => RETURN [(value1 = value2)];
SXAtoms.instanceTransf => RETURN [ImagerTransformation.Equal[NARROW[value1, ImagerTransformation.Transformation], NARROW[value2, ImagerTransformation.Transformation]]];
ENDCASE => [] ← SIGNAL Core.StructureError [InvariantFailed, "programming error"]
END; -- Compare
Copy: CoreProperties.PropCopyProc =
TYPE = PROC [prop: ATOM, value: REF ANY] RETURNS [valCopy: REF ANY];
BEGIN
Stray: TYPE = LIST OF SX.AreaPerimRec;
WireLocation: TYPE = REF SX.NodeLocation;
SELECT prop
FROM
SXAtoms.techInfo => {
oldT: SX.TechInfo = NARROW [value];
valCopy ← NEW [SX.TechRec ← oldT^]};
SXAtoms.strayInfo => {
newS: Stray ← NIL;
oldS: Stray = NARROW [value];
FOR s: Stray ← oldS, s.rest
WHILE s #
NIL
DO
newS ← CONS [s.first, newS]
By definition the list is unordered !
ENDLOOP;
valCopy ← newS};
SXAtoms.locInfo => {
oldL: WireLocation = NARROW [value];
valCopy ← NEW [SX.NodeLocation ← oldL^]};
SXAtoms.crystalAttr => {
new: Rope.ROPE ← NARROW [value, Rope.ROPE];
valCopy ← new};
SXAtoms.cdDesignHint, SXAtoms.cdCellHint => valCopy ← value;
SXAtoms.instanceTransf => valCopy ← ImagerTransformation.Copy [NARROW[value, ImagerTransformation.Transformation]];
ENDCASE => [] ← SIGNAL Core.StructureError [InvariantFailed, "programming error"]
END; -- Copy
Print: CoreProperties.PropPrintProc ~
BEGIN
TYPE = PROC [to: IO.STREAM, prop: ATOM, context, val: REF ANY]
SELECT prop
FROM
SXAtoms.techInfo => {
techProp: SX.TechInfo = NARROW [val, SX.TechInfo];
IO.PutF [stream: to,
format: "The technology of the design is %l%g%l\n",
v1: IO.rope ["b"],
v2: IO.rope [techProp.name],
v3: IO.rope ["B"]];
FOR i:
SX.SpinifexLayerIndex
IN SX.SpinifexLayerIndex
DO
IO.PutF [stream: to,
format: "%g\t\t\t%g\t\t\t%g\n",
v1: IO.int [i],
v2: IO.atom [techProp.layers[i].id],
v3: IO.rope [techProp.layers[i].thymeName]]
ENDLOOP};
SXAtoms.strayInfo => {
stray: LIST OF SX.AreaPerimRec = NARROW [val, LIST OF SX.AreaPerimRec];
FOR s:
LIST
OF
SX.AreaPerimRec ← stray, s.rest
WHILE s #
NIL
DO
IO.PutF [stream: to,
format: "(layer = %g, a = %g, p = %g) ",
v1: IO.int [s.first.layer],
v2: IO.int [s.first.area],
v3: IO.int [s.first.perim]]
ENDLOOP};
SXAtoms.locInfo => {
loc: REF SX.NodeLocation = NARROW [val, REF SX.NodeLocation];
IO.PutF [stream: to,
format: "(layer = %g, x = %g, y = %g) ",
v1: IO.int [loc.layer],
v2: IO.int [loc.xy.x],
v3: IO.int [loc.xy.x]]};
SXAtoms.crystalAttr =>
IO.PutF [stream: to, format: "%g", v1: IO.rope [NARROW [val, Rope.ROPE]]];
SXAtoms.cdDesignHint, SXAtoms.cdCellHint =>
IO.PutF [stream: to,
format: "CD hint %g",
v1: IO.rope [IF val=NIL THEN "= NIL" ELSE "# NIL"]];
SXAtoms.instanceTransf => {
t: ImagerTransformation.Transformation ← NARROW [val, ImagerTransformation.Transformation];
IF t.integerTrans
THEN
IO.PutF [stream: to,
format: "Translation: (tx = %g, ty = %g)",
v1: IO.int [t.tx],
v2: IO.int [t.ty]]
ELSE IO.PutF [stream: to, format: "Transformation looks insane"]};
ENDCASE => IO.PutF [stream: to, format: "Unknown property"];
END; -- Print
Write: CoreProperties.PropWriteProc ~ BEGIN
TYPE = PROC [out: IO.STREAM, val: REF ANY, context: REF ANY ← NIL]
SELECT context FROM
SXAtoms.techInfo => {
techProp: SX.TechInfo = NARROW [val, SX.TechInfo];
CoreProperties.PropRopeWrite [out, techProp.name, context];
FOR i: SX.SpinifexLayerIndex IN SX.SpinifexLayerIndex DO
Stored only once per design, so don't care for compactness.
CoreProperties.PropAtomWrite [out, techProp.layers[i].id, context];
CoreProperties.PropRopeWrite [out, techProp.layers[i].thymeName, context]
ENDLOOP};
SXAtoms.strayInfo => {
stray: LIST OF SX.AreaPerimRec = NARROW [val, LIST OF SX.AreaPerimRec];
FOR s: LIST OF SX.AreaPerimRec ← stray, s.rest WHILE s # NIL DO
CoreProperties.PropIntWrite [out, s.first.layer, context];
CoreProperties.PropIntWrite [out, s.first.area, context];
CoreProperties.PropIntWrite [out, s.first.perim, context]
ENDLOOP};
SXAtoms.locInfo => {
loc: REF SX.NodeLocation = NARROW [val, REF SX.NodeLocation];
CoreProperties.PropIntWrite [out, loc.layer, context];
CoreProperties.PropIntWrite [out, loc.xy.x, context];
CoreProperties.PropIntWrite [out, loc.xy.x, context]
SXAtoms.crystalAttr =>
CoreProperties.PropRopeWrite [out, NARROW [val, Rope.ROPE], context];
SXAtoms.cdDesignHint, SXAtoms.cdCellHint => NULL;
SXAtoms.instanceTransf => {
t: ImagerTransformation.Transformation ← NARROW [val, ImagerTransformation.Transformation];
CoreProperties.PropRealWrite [out, t.a, context];
CoreProperties.PropRealWrite [out, t.b, context];
CoreProperties.PropRealWrite [out, t.c, context];
CoreProperties.PropRealWrite [out, t.d, context];
CoreProperties.PropRealWrite [out, t.e, context];
CoreProperties.PropRealWrite [out, t.f, context];
CoreProperties.PropIntWrite [out, t.tx, context];
CoreProperties.PropIntWrite [out, t.ty, context];
CoreProperties.PropBoolWrite [out, t.integerTrans, context];
CoreProperties.PropNatWrite [out, t.form, context]};
ENDCASE => IO.PutF [stream: to, format: "Unknown property"];
END; -- Write
Read: CoreProperties.PropWriteProc ~ BEGIN
TYPE = PROC [in: IO.STREAM, context: REF ANY ← NIL] RETURNS [val: REF ANY]
END; -- Read
SetDesignProp:
PUBLIC
PROCEDURE [cdD:
CD.Design, coreD: Core.Design] =
Set a property on the design containing the technology and the definition of the layers. May raise Core.StructureError [MissingParameter].
BEGIN
techProp: SX.TechInfo;
technologyHandle: REF SX.TechHandle ← NARROW [CDProperties.GetProp [from: cdD.technology, prop: SXAtoms.spinifex]];
Check tech info is there.
IF (technologyHandle =
NIL)
THEN
[] ← SIGNAL Core.StructureError [type: MissingParameter, message: "Design has not a Spinifex technology"];
Store the technology and layer names.
techProp ← NEW [SX.TechRec];
techProp.name ← cdD.technology.name;
FOR layer:
SX.SpinifexLayerIndex
IN [0 .. technologyHandle.numSpinifexLayers)
DO
techProp.layers[layer].id ← technologyHandle.spinifexLayerNames[layer].layerId;
techProp.layers[layer].thymeName ← technologyHandle.spinifexLayerNames[layer].thymeName
ENDLOOP;
coreD.properties ← CoreProperties.PutProp [on: coreD.properties, prop: SXAtoms.techInfo, value: techProp];
coreD.properties ← CoreProperties.PutProp [on: coreD.properties, prop: SXAtoms.cdDesignHint, value: cdD]
END; -- SetDesignProp
Register:
PROC [property:
ATOM] ~
BEGIN
We use an intermediate procedure call because we vary only one parameter. And because the Core interface has increased in complexity.
propertyProperties: Core.Properties ← NIL;
compare: REF CoreProperties.PropCompareProc = NEW [CoreProperties.PropCompareProc ← Compare];
copy: REF CoreProperties.PropCopyProc = NEW [CoreProperties.PropCopyProc ← Copy];
print: REF CoreProperties.PropPrintProc = NEW [CoreProperties.PropPrintProc ← Print];
[] ← CoreProperties.RegisterProperty [property];
propertyProperties ← CoreProperties.PutProp [on: propertyProperties, prop: CoreProperties.propCompare, value: compare];
propertyProperties ← CoreProperties.PutProp [on: propertyProperties, prop: CoreProperties.propCopy, value: copy];
propertyProperties ← CoreProperties.PutProp [on: propertyProperties, prop: CoreProperties.propPrint, value: print];
CoreProperties.StoreProperties [prop: property, properties: propertyProperties];
END; -- Register