Standard Cell Optimization and Construction
InitialPlace:
PUBLIC
PROC [handle:
SC.Handle, numRows:
NAT ← 0] = {
Determine an initial placement for the instances.
layoutData: SCPrivate.LayoutData ← NARROW[handle.layoutData];
p: Process.Priority ← Process.GetPriority[];
Process.SetPriority[Process.priorityBackground];
SCSmash.RemoveSmash[handle];
SCPlaceUtil.ClrCurPlac[handle, TRUE];
SCInitialPlace.PrePlace[handle: handle, numRows: numRows, routingFactor: 2.5, initialized: TRUE];
SCInitialPlace.RowInit[handle];
SCInitialPlace.PosInit[handle];
[layoutData.lgRows.maxRowWidth, layoutData.lgRows.numMaxRows] ← SCRowUtil.FindMaxRow[handle];
SCChanUtil.InitChanWidths[handle];
SCInstUtil.AsgnChanPos[handle];
layoutData.initTotWidth ← layoutData.totWidth;
layoutData.initTotHeight ← layoutData.totHeight;
IF debug THEN SCPlaceUtil.WriteCurPlace[handle];
[] ← SCUtil.WriteResults["End initial placement\n initial size: ", handle, 0];
Process.SetPriority[p]};
PosImprove: PUBLIC PROC [handle: SC.Handle, maxCycles: INT] = {
Improve the positions of instances whithin rows.
p: Process.Priority ← Process.GetPriority[];
Process.SetPriority[Process.priorityBackground];
SCPrivate.PosImprove[handle, areaFom, maxCycles];
IF debug THEN SCPlaceUtil.WriteCurPlace[handle];
PosImproveWL: PUBLIC PROC [handle: SC.Handle, maxCycles: INT] = {
Improve the positions of instances whithin rows using wire lenght as figure of merit.
p: Process.Priority ← Process.GetPriority[];
Process.SetPriority[Process.priorityBackground];
SCPrivate.PosImprove[handle, wlFom, maxCycles];
IF debug THEN SCPlaceUtil.WriteCurPlace[handle];
OrientImprove: PUBLIC PROC [handle: SC.Handle, maxCycles: INT] = {
Improve the orientation of instances.
p: Process.Priority ← Process.GetPriority[];
Process.SetPriority[Process.priorityBackground];
SCPrivate.OrientImprove[handle, areaFom, maxCycles];
IF debug THEN SCPlaceUtil.WriteCurPlace[handle];
OrientImproveWL: PUBLIC PROC [handle: SC.Handle, maxCycles: INT] = {
Improve the orientation of instances using wire lenght as figure of merit.
p: Process.Priority ← Process.GetPriority[];
Process.SetPriority[Process.priorityBackground];
SCPrivate.OrientImprove[handle, wlFom, maxCycles];
IF debug THEN SCPlaceUtil.WriteCurPlace[handle];
FTImprove: PUBLIC PROC [handle: SC.Handle, maxCycles: INT] = {
Improve the positions of instances whithin rows.
p: Process.Priority ← Process.GetPriority[];
Process.SetPriority[Process.priorityBackground];
SCPrivate.FTImprove[handle, wlFom, maxCycles];
IF debug THEN SCPlaceUtil.WriteCurPlace[handle];
SAInitialPlace: PUBLIC PROC [handle: SC.Handle, widthFactor: REAL, seed: INT] RETURNS [initialResult: SC.SAInitialResult] = {
Initialize for simulated annealing improvement.
p: Process.Priority ← Process.GetPriority[];
Process.SetPriority[Process.priorityBackground];
initialResult ← SCPrivate.SAInitialPlace[handle, widthFactor, seed];
SAGetParms: PUBLIC PROC [handle: SC.Handle, initialResult: SC.SAInitialResult, cellType: Core.CellType] RETURNS [saParms: SC.SAParms] = {
determine parameters for simulated placement.
p: Process.Priority ← Process.GetPriority[];
Process.SetPriority[Process.priorityBackground];
saParms ← SCPrivate.SAGetParms[handle, initialResult, cellType];
Process.SetPriority[p]};
SAPlaceImprove: PUBLIC PROC [handle: SC.Handle, saParms: SC.SAParms, widthFactor: REAL, seed: INT] = {
Improve the placement for the instances (one at a time) by simulated annealing.
p: Process.Priority ← Process.GetPriority[];
Process.SetPriority[Process.priorityBackground];
SCPrivate.SAPlaceImprove[handle, saParms, widthFactor, seed];
IF debug THEN SCPlaceUtil.WriteCurPlace[handle];
SAPlaceImproveM: PUBLIC PROC [handle: SC.Handle, saParms: SC.SAParms, widthFactor: REAL, seed: INT] = {
Improve the placement for the instances (one at a time) by simulated annealing.
p: Process.Priority ← Process.GetPriority[];
Process.SetPriority[Process.priorityBackground];
SCPrivate.SAPlaceImproveM[handle, saParms, widthFactor, seed];
IF debug THEN SCPlaceUtil.WriteCurPlace[handle];
PlaceImprove: PUBLIC PROC [handle: SC.Handle, maxCycles: INT] = {
Improve the placement for the instances by exhaustive search.
p: Process.Priority ← Process.GetPriority[];
Process.SetPriority[Process.priorityBackground];
SCPrivate.PlaceImprove[handle, maxCycles];
IF debug THEN SCPlaceUtil.WriteCurPlace[handle];
GlobalRoute:
PUBLIC
PROC [handle:
SC.Handle] = {
Determine strategic paths for the wiring that must cross cell rows.
p: Process.Priority ← Process.GetPriority[];
Process.SetPriority[Process.priorityBackground];
SCSmash.RemoveSmash[handle];
SCSmash.SmashAllNets[handle, FALSE];
Process.SetPriority[p]};
ExprGlobalRoute: PUBLIC PROC [handle: SC.Handle] = {
Determine strategic paths for the wiring that must cross cell rows.
Uses minimum Stiener tree global routing
p: Process.Priority ← Process.GetPriority[];
Process.SetPriority[Process.priorityBackground];
SCExprGlobalRoute.GlobalRouteAllNets[handle];
Process.SetPriority[p]};
DetailRoute:
PUBLIC
PROC [handle:
SC.Handle]
RETURNS [result:
SC.Result] = {
Determine actual wiring paths.
p: Process.Priority ← Process.GetPriority[];
Process.SetPriority[Process.priorityBackground];
result ← SCPrivate.DetailRoute[handle];
Process.SetPriority[p]};
ExprDetailRoute: PUBLIC PROC [handle: SC.Handle] RETURNS [result: SC.Result] = {
Determine actual wiring paths.
Works with ExprGlobalRoute
p: Process.Priority ← Process.GetPriority[];
Process.SetPriority[Process.priorityBackground];
result ← SCExprGlobalRoute.DetailRoute[handle];
Process.SetPriority[p]};
CreateLayout: PUBLIC PROC [technologyKey: ATOM, horizLayer, vertLayer: Rope.ROPE, rowDirection: SC.Direction, numRows: NAT, cellType: Core.CellType, flattenCellType: RTCoreUtil.FlattenCellTypeProc, libName: Rope.ROPE ← NIL, name: Rope.ROPE ← NIL] RETURNS [object: CD.Object] = {
Create a standard cell object by performing the above operations
widthFactor: REAL ← MAX[1.0, MIN[2.0, RTCoreUtil.GetCoreRealProp[cellType, SC.widthFactorProp, 1.1]]];
designRules: SC.DesignRules ← SC.CreateDesignRules[technologyKey, horizLayer, vertLayer, rowDirection];
handle: SC.Handle ← SC.CreateHandle[cellType, flattenCellType, libName, designRules, name];
SC.InitialPlace[handle, RTCoreUtil.GetCoreIntProp[cellType, SC.numRows, 0]];
SC.SAPlaceImprove[handle, SC.SAGetParms[handle, SC.SAInitialPlace[handle, widthFactor], cellType], widthFactor];
SC.GlobalRoute[handle];
object ← SC.DetailRoute[handle].object;
};
Destroy:
PUBLIC
PROC [handle:
SC.Handle] ~ {
Remove circular references so garbage collection can work
SCPrivate.DestroyLayout[handle];
SCPrivate.DestroyStructure[handle];
SCUtil.DestroyRules[handle];
SCUtil.DestroyParms[handle];
CoreProperties.PutCellTypeProp[handle.coreCellType, SC.handleAtom, NIL]; -- remove handle
handle^ ← [];
};
PWCore Interface
The cellType to layout is a record cellType containing elements from MSI; the layout proc flattens the Core description and calls the standard cell router. Placement is obtained from timberwolf.
StandardCellRoute: PWCore.LayoutProc = {
hMaterial: Rope.ROPE ← "metal";
vMaterial: Rope.ROPE ← "metal2";
widthFactor: REAL ← MAX[1.0, MIN[2.0, RTCoreUtil.GetCoreRealProp[cellType, SC.widthFactorProp, 1.1]]];
rules: SC.DesignRules ← SC.CreateDesignRules[technologyKey, hMaterial, vMaterial, horizontal];
handle: SC.Handle ← SC.CreateHandle[cellType: cellType, flattenCellType: RTCoreUtil.defaultFlatten, libName: libName, designRules: rules];
SCUtil.ReadTWPlace[handle: handle];
SC.InitialPlace[handle, RTCoreUtil.GetCoreIntProp[cellType, SC.numRows, 0]];
SC.GlobalRoute[handle];
obj ← SC.DetailRoute[handle].object;
};
The cellType to layout is a record cellType containing elements from MSI; the layout proc flattens the Core description and calls the standard cell router. Placement is obtained from timberwolf.
StandardCellRouteX: PWCore.LayoutProc = {
hMaterial: Rope.ROPE ← "metal";
vMaterial: Rope.ROPE ← "metal2";
widthFactor: REAL ← MAX[1.0, MIN[2.0, RTCoreUtil.GetCoreRealProp[cellType, SC.widthFactorProp, 1.1]]];
rules: SC.DesignRules ← SC.CreateDesignRules[technologyKey, hMaterial, vMaterial, horizontal];
handle: SC.Handle ← SC.CreateHandle[cellType: cellType, flattenCellType: RTCoreUtil.defaultFlatten, libName: libName, designRules: rules];
SCUtil.ReadTWPlace[handle: handle];
SC.InitialPlace[handle, RTCoreUtil.GetCoreIntProp[cellType, SC.numRows, 0]];
SCExprGlobalRoute.GlobalRouteAllNets[handle];
obj ← SC.ExprDetailRoute[handle].object;
};
The cellType to layout is a record cellType containing elements from MSI; the layout proc flattens the Core description and calls the standard cell placer and router.
StandardCellLayout: PWCore.LayoutProc = {
saParms: SC.SAParms;
initialResult: SC.SAInitialResult;
hMaterial: Rope.ROPE ← "metal";
vMaterial: Rope.ROPE ← "metal2";
widthFactor: REAL ← MAX[1.0, MIN[2.0, RTCoreUtil.GetCoreRealProp[cellType, SC.widthFactorProp, 1.1]]];
rules: SC.DesignRules ← SC.CreateDesignRules[technologyKey, hMaterial, vMaterial, horizontal];
handle: SC.Handle ← SC.CreateHandle[cellType: cellType, flattenCellType: RTCoreUtil.defaultFlatten, libName: libName, designRules: rules];
SC.InitialPlace[handle, RTCoreUtil.GetCoreIntProp[cellType, SC.numRows, 0]];
initialResult ← SC.SAInitialPlace[handle, widthFactor];
saParms ← SC.SAGetParms[handle, initialResult, cellType];
SC.SAPlaceImprove[handle: handle, saParms: saParms, widthFactor: widthFactor];
SC.GlobalRoute[handle];
obj ← SC.DetailRoute[handle].object;
};
The cellType to layout is a record cellType containing elements from MSI; the layout proc flattens the Core description and calls the standard cell placer and router.
StandardCellLayoutTW: PWCore.LayoutProc = {
twMsg: Rope.ROPE;
hMaterial: Rope.ROPE ← "metal";
vMaterial: Rope.ROPE ← "metal2";
widthFactor: REAL ← MAX[1.0, MIN[2.0, RTCoreUtil.GetCoreRealProp[cellType, SC.widthFactorProp, 1.1]]];
rules: SC.DesignRules ← SC.CreateDesignRules[technologyKey, hMaterial, vMaterial, horizontal];
handle: SC.Handle ← SC.CreateHandle[cellType: cellType, flattenCellType: RTCoreUtil.defaultFlatten, libName: libName, designRules: rules];
SC.InitialPlace[handle, RTCoreUtil.GetCoreIntProp[cellType, SC.numRows, 0]];
SCUtil.WriteTWFiles[handle: handle];
twMsg ← SCUtil.TWIt[handle.name];
IF twMsg#NIL THEN SC.Error[callingError, Rope.Cat[twMsg, ", Problem on Unix Placement Server. Check file ", handle.name, ".out"]];
SCUtil.ReadTWPlace[handle: handle];
SC.InitialPlace[handle, RTCoreUtil.GetCoreIntProp[cellType, SC.numRows, 0]];
SC.GlobalRoute[handle];
SC.ExprGlobalRouteAllNets[handle];
obj ← SC.DetailRoute[handle].object;
};
The cellType to layout is a record cellType containing elements from MSI; the layout proc flattens the Core description and calls the TimberWolf standard cell placer and SC router. Uses an experimental version of the Global Router
StandardCellLayoutTWX: PWCore.LayoutProc = {
twMsg: Rope.ROPE;
hMaterial: Rope.ROPE ← "metal";
vMaterial: Rope.ROPE ← "metal2";
widthFactor: REAL ← MAX[1.0, MIN[2.0, RTCoreUtil.GetCoreRealProp[cellType, SC.widthFactorProp, 1.1]]];
rules: SC.DesignRules ← SC.CreateDesignRules[technologyKey, hMaterial, vMaterial, horizontal];
handle: SC.Handle ← SC.CreateHandle[cellType: cellType, flattenCellType: RTCoreUtil.defaultFlatten, libName: libName, designRules: rules];
SC.InitialPlace[handle, RTCoreUtil.GetCoreIntProp[cellType, SC.numRows, 0]];
SCUtil.WriteTWFiles[handle: handle];
twMsg ← SCUtil.TWIt[handle.name];
IF twMsg#NIL THEN SC.Error[callingError, Rope.Cat[twMsg, ", Problem on Unix Placement Server. Check file ", handle.name, ".out"]];
SCUtil.ReadTWPlace[handle: handle];
SC.InitialPlace[handle, RTCoreUtil.GetCoreIntProp[cellType, SC.numRows, 0]];
SCExprGlobalRoute.GlobalRouteAllNets[handle];
obj ← SC.ExprDetailRoute[handle].object;
};
StandardCellDecorate:
PUBLIC PWCore.DecorateProc = {
PROC [cellType: CellType, obj: Object];
call back proc to map wires to labels
WireToLabels:
PROC [wire: Core.Wire]
RETURNS [
LIST
OF Route.Label] ~ {
Called only for atomic publics
net: SCPrivate.Net ← SCNetUtil.FindPublicNet[handle, wire];
RETURN[IF net.numberOfRegions <= 0 THEN LIST[net.name] ELSE net.brokenNets]};
call back proc to order objects
ComparePos:
PROC [pos1, pos2:
CD.Position]
RETURNS [
BOOL] ~ {
IF pos1.y = pos2.y THEN RETURN[pos1.x < pos2.x]
ELSE RETURN[pos1.y < pos2.y]};
call back proc to order cellTypes
CompareCT: CoreRoute.CompareFlatCTProc ~ {
PROC [root: Core.CellType, flatCT1, flatCT2: CoreFlat.FlatCellTypeRec] RETURNS [BOOL];
instance1: SCPrivate.Instance = SCInstUtil.FindSourceInstance[handle, NEW [CoreFlat.FlatCellTypeRec ← flatCT1]];
instance2: SCPrivate.Instance = SCInstUtil.FindSourceInstance[handle, NEW [CoreFlat.FlatCellTypeRec ← flatCT2]];
IF instance1.curRow = instance2.curRow THEN RETURN[instance1.curPos < instance2.curPos]
ELSE RETURN[instance1.curRow < instance2.curRow]};
handle: SC.Handle ← NARROW[CoreProperties.GetCellTypeProp[cellType, SC.handleAtom]];
IF handle #
NIL
THEN {
SmashPins:
PROC [wire: Core.Wire] = {
CoreGeometry.PutPins[mode.decoration, wire, NIL];
};
mode: Sinix.Mode = NARROW [handle.parms, SCPrivate.Parms].mode;
CoreOps.VisitRootAtomics[cellType.public, SmashPins];
CoreRoute.DecorateRoutedArea[cellType: cellType, obj: obj, wireToLabels: WireToLabels,
compareIR: CoreRoute.CompareXorYStack, compareCT: CompareCT];
SC.Destroy[handle]}};
Puts on public wires their side as a property
StandardCellAttibutes:
PUBLIC PWCore.AttributesProc = {
-- [cellType: Core.CellType]
SideAndPositionForPin:
PROC [wire: Core.Wire, side: DABasics.Side, index:
INT] = {
process wire on side at index
PushPropOnAtomic:
PROC [wire: Core.Wire] ~ {
sideVal: REF ANY ← CoreProperties.GetWireProp[wire, sideProp];
positionVal: REF ANY ← CoreProperties.GetWireProp[wire, positionProp];
IF sideVal = NIL THEN CoreProperties.PutWireProp[wire, sideProp, NEW[BOOL ← TRUE]];
IF positionVal = NIL THEN CoreProperties.PutWireProp[wire, positionProp, NEW[INT ← index]]};
sideProp:
ATOM ←
SELECT side
FROM
bottom => bottomSideProp,
top => topSideProp,
right => rightSideProp,
left => leftSideProp,
ENDCASE => SC.Error[programmingError, "Not suppose to happen."];
positionProp:
ATOM ←
SELECT side
FROM
bottom => bottomPositionProp,
top => topPositionProp,
right => rightPositionProp,
left => leftPositionProp,
ENDCASE => SC.Error[programmingError, "Not suppose to happen."];
IF wire.size=0 THEN PushPropOnAtomic[wire]
ELSE CoreOps.VisitRootAtomics[wire, PushPropOnAtomic]};
DO
IF CoreGeometry.HasObject[Sisyph.mode.decoration, cellType]
THEN {
this cellType has decorations, run through the pins on the sides
FOR side: DABasics.Side
IN DABasics.Side
DO
wires: Core.Wires ← CoreRoute.OrderedAtomicSchWires[cellType: cellType, side: side];
index: INT ← 0;
FOR wireList: Core.Wires ← wires, wireList.rest
WHILE wireList #
NIL
DO
index ← index + 1;
SideAndPositionForPin[wireList.first, side, index];
ENDLOOP;
ENDLOOP;
CoreRoute.FlushSchPinCache[cellType: cellType];
EXIT};
IF cellType.class.recast = NIL THEN EXIT;
cellType ← CoreOps.Recast[cellType]
ENDLOOP};
SCLayoutAtom: ATOM ← PWCore.RegisterLayoutAtom[$SC, StandardCellLayout, StandardCellDecorate, StandardCellAttibutes];
SCRouteAtom: ATOM ← PWCore.RegisterLayoutAtom[$SCRoute, StandardCellRoute, StandardCellDecorate, StandardCellAttibutes];
SCTWAtom: ATOM ← PWCore.RegisterLayoutAtom[$SCRemote, StandardCellLayoutTW, StandardCellDecorate, StandardCellAttibutes];
Experimental Layout ATOMS
SCRouteXAtom: ATOM ← PWCore.RegisterLayoutAtom[$SCRouteX, StandardCellRouteX, StandardCellDecorate, StandardCellAttibutes];
SCTWXAtom: ATOM ← PWCore.RegisterLayoutAtom[$SCRemoteX, StandardCellLayoutTWX, StandardCellDecorate, StandardCellAttibutes];
technologyKey: PUBLIC ATOM ← $cmosB; -- $cmosA or $cmosB
libName: PUBLIC Rope.ROPE ← "CMOSB";
Properties
row and logic cell properties
numRows:
PUBLIC
ATOM ← $numRows;
Used to specify the number of rows for a standard cell assembly. Should be a property on Core cellType being laid out
rowProp:
PUBLIC
ATOM ← $Row;
Used to specify the row on which a logic cell is to be placed. rowProp and and INT row number should be a property/value on a logic cell insatance
positionProp:
PUBLIC
ATOM ← $Position;
Used to specify the position of a logic within a row or of an public pin on a side. Should be used with INT value on logic cell instance.
side and public properties
bottomSideProp: PUBLIC ATOM ← $BottomSide;
rightSideProp: PUBLIC ATOM ← $RightSide;
topSideProp: PUBLIC ATOM ← $TopSide;
leftSideProp:
PUBLIC
ATOM ← $LeftSide;
Used to specify the side on which a public pin is to be placed. (mumble)SideProp should be a TRUE on a public wire if it is to appear on (mumble) side
bottomPositionProp: PUBLIC ATOM ← $BottomPosition;
rightPositionProp: PUBLIC ATOM ← $RightPosition;
topPositionProp: PUBLIC ATOM ← $TopPosition;
leftPositionProp:
PUBLIC
ATOM ← $LeftPosition;
Used to specify the position (INT) in which a public pin is to be placed on a side. (mumble)SideProp must be true on that side; should be a property/value on a public wire
usePublicPositionsProp:
PUBLIC
ATOM ← $UsePublicPositions;
Used to specify the position of a public in the schematic is to be retained int the layout; value must be TRUE
bottomMaxExits: PUBLIC ATOM ← $BottomMaxExits;
rightMaxExits: PUBLIC ATOM ← $RightMaxExits;
topMaxExits: PUBLIC ATOM ← $TopMaxExits;
leftMaxExits:
PUBLIC
ATOM ← $LeftMaxExits;
Used to specify the maximum number or publics on a side.
bottomExitSpacing: PUBLIC ATOM ← $BottomExitSpacing;
rightExitSpacing: PUBLIC ATOM ← $RightExitSpacing;
topExitSpacing: PUBLIC ATOM ← $TopExitSpacing;
leftExitSpacing:
PUBLIC
ATOM ← $LeftExitSpacing;
Used to specify the HINT for publics spacing on a side.
placement properties
investmentProp:
PUBLIC
ATOM ← $Investment;
veryLongValue: PUBLIC ATOM ← $veryLong;
longValue: PUBLIC ATOM ← $long;
mediumValue: PUBLIC ATOM ← $medium;
shortValue: PUBLIC ATOM ← $short;
veryShortValue:
PUBLIC
ATOM ← $veryShort;
Used to specify the investment to make in placement.
t0SA: PUBLIC ATOM ← $t0SA;
maxTStepSA: PUBLIC ATOM ← $maxTStepSA;
lambdaSA: PUBLIC ATOM ← $lambdaSA;
tableSizeSA: PUBLIC ATOM ← $tableSizeSA;
limitSA:
PUBLIC
ATOM ← $limitSA;
Used to specify simulated aneealing partameters to be used for placement
widthFactorProp:
PUBLIC
ATOM ← $widthFactor;
specifies the allowed length of the longest row compared to the minimun distance longest row
internal use
handleAtom:
PUBLIC
ATOM ← CoreProperties.RegisterProperty[$SCHandle];
for internal use only
interestingProperties:
PUBLIC RTCoreUtil.PropertyKeys ←
NEW[RTCoreUtil.PropertyKeysRec[27]];
Cedar does not allow initialization of a sequence in the NEW!
interestingProperties.p[0] ← numRows;
interestingProperties.p[1] ← rowProp;
interestingProperties.p[2] ← positionProp;
interestingProperties.p[3] ← bottomSideProp;
interestingProperties.p[4] ← rightSideProp;
interestingProperties.p[5] ← topSideProp;
interestingProperties.p[6] ← leftSideProp;
interestingProperties.p[7] ← bottomPositionProp;
interestingProperties.p[8] ← rightPositionProp;
interestingProperties.p[9] ← topPositionProp;
interestingProperties.p[10] ← leftPositionProp;
interestingProperties.p[11] ← usePublicPositionsProp;
interestingProperties.p[12] ← bottomMaxExits;
interestingProperties.p[13] ← rightMaxExits;
interestingProperties.p[14] ← topMaxExits;
interestingProperties.p[15] ← leftMaxExits;
interestingProperties.p[16] ← bottomExitSpacing;
interestingProperties.p[17] ← rightExitSpacing;
interestingProperties.p[18] ← topExitSpacing;
interestingProperties.p[19] ← leftExitSpacing;
interestingProperties.p[20] ← investmentProp;
interestingProperties.p[21] ← t0SA;
interestingProperties.p[22] ← maxTStepSA;
interestingProperties.p[23] ← lambdaSA;
interestingProperties.p[24] ← limitSA;
interestingProperties.p[25] ← widthFactorProp;
interestingProperties.p[26] ← handleAtom;
Used to specify all the properties that are interesting to SC
}.