<> <> <> <> <> <> <> <> <> <<>> DIRECTORY CD, CDDirectory, Convert, Core, CoreCreate, CoreOps, CoreGeometry, CoreProperties, IO, Ports, PWCore, Rope, Rosemary, Sinix, Sisyph, Sch, TerminalIO, TilingClass; SchImpl: CEDAR PROGRAM IMPORTS CDDirectory, Convert, CoreCreate, CoreOps, CoreGeometry, CoreProperties, IO, PWCore, Rope, Sinix, Sisyph, TerminalIO, TilingClass EXPORTS Sch = BEGIN OPEN Sch; iconRope: ROPE _ ".icon"; schRope: ROPE _ ".sch"; Sch: PUBLIC PROC [cx: Context, name: ROPE] = { CheckObjectName[cx, Rope.Cat[name, schRope]]; Sisyph.Eval[cx, "coreProps _ CoreProperties.PutProp[coreProps, $PWCoreSourceDesign, design]"]; }; <<>> Icon: PUBLIC PROC [cx: Context, name: ROPE] RETURNS [ct: CellType] = { CheckObjectName[cx, Rope.Cat[name, iconRope]]; ct _ Sisyph.ExtractSchematicByName[Rope.Cat[name, schRope], cx]; }; <<>> CheckObjectName: PUBLIC PROC [cx: Context, assertedName: ROPE] = { objectName: ROPE _ CDDirectory.Name[Sisyph.GetCDObj[cx]]; IF NOT Rope.Equal[objectName, assertedName] THEN TerminalIO.PutF["Warning: ChipNDale directory name %g does not correspond to asserted name %g", IO.refAny[objectName], IO.refAny[assertedName]]; }; <<>> Orient: PUBLIC PROC [cx: Context, atom: ATOM] RETURNS [ct: CellType] = { objectName: ROPE _ CDDirectory.Name[Sisyph.GetCDObj[cx]]; baseCell: Core.CellType _ Sisyph.ExtractSchematicByName[objectName, cx]; ct _ PWCore.RotateCellType[baseCell, atom]; Sisyph.Eval[cx, "coreProps _ NIL"]; }; WireSide: PROC [wire: Core.Wire, baseCT: Core.CellType] RETURNS [sides: CoreGeometry.Sides _ CoreGeometry.noSide] ~ { <> EachPin: CoreGeometry.EachPinProc = { sides[side] _ TRUE; }; [] _ CoreGeometry.EnumerateSides[Sisyph.mode.decoration, baseCT, wire, EachPin]; }; WireSideProblem: PROC [wire: Core.Wire, msg: ROPE, baseCT: Core.CellType] ~ { TerminalIO.PutF["\n*** Wire %g %g in cell %g\n", IO.rope[CoreOps.GetFullWireName[baseCT.public, wire]], IO.rope[msg], IO.rope[CoreOps.GetCellTypeName[baseCT]]]; SIGNAL Sinix.CallerBug[]; }; CSeqStitch: PUBLIC PROC [cx: Sisyph.Context, count: NAT, dir: XorY] RETURNS [ct: Core.CellType] = { ct _ CSeqStitchOb[CDDirectory.Name[Sisyph.GetCDObj[cx]], cx, count, dir]; }; CSeqStitchOb: PROC [obName: ROPE, cx: Sisyph.Context, count: NAT, dir: XorY] RETURNS [ct: Core.CellType] = { sWires, fsWires: LIST OF CoreCreate.WR; EachWire: CoreOps.EachWireProc = { sides: CoreGeometry.Sides = WireSide[wire, baseCT]; vertical: BOOL = sides[top] OR sides[bottom]; horizontal: BOOL = sides[left] OR sides[right]; IF ~(vertical OR horizontal) THEN RETURN; -- This wire has no pins, try its sons IF vertical AND horizontal THEN WireSideProblem[wire, "touches adjacent sides", baseCT]; IF (horizontal AND (dir=X OR dir=RX)) OR (vertical AND (dir=Y OR dir=RY)) THEN { wireName: Rope.ROPE _ CoreOps.GetShortWireName[wire]; inWire: BOOL _ Rope.Match["*In", wireName]; IF inWire OR Rope.Match["*Out", wireName] THEN { this: BOOL _ sides[left] OR sides[bottom]; searchName: Rope.ROPE _ Rope.Cat[Rope.Substr[wireName, 0, Rope.Length[wireName] - (IF inWire THEN Rope.Length["In"] ELSE Rope.Length["Out"])], IF inWire THEN "Out" ELSE "In"]; IF (sides[top] AND sides[bottom]) OR (sides[left] AND sides[right]) THEN WireSideProblem[wire, "touches both sides but is a stitch", baseCT]; FOR pas: LIST OF CoreCreate.PA _ stitchPorts, pas.rest UNTIL pas=NIL DO IF Rope.Equal[NARROW[IF this THEN pas.first.actual ELSE pas.first.public], searchName] THEN { IF this THEN pas.first.public _ wireName ELSE pas.first.actual _ wireName; EXIT; }; REPEAT FINISHED => stitchPorts _ CONS[IF this THEN [wireName, NIL] ELSE [NIL, wireName], stitchPorts]; ENDLOOP; } }; IF (vertical AND (dir=X OR dir=RX)) OR (horizontal AND (dir=Y OR dir=RY)) THEN IF wire.size=0 THEN sWires _ CONS[wire, sWires] ELSE fsWires _ CONS[wire, fsWires]; subWires _ FALSE; }; baseCT: Core.CellType _ Sisyph.ExtractSchematicByName[obName, cx]; stitchPorts: LIST OF CoreCreate.PA _ NIL; [] _ CoreOps.VisitWireSeq[baseCT.public, EachWire]; ct _ CoreCreate.SequenceCell[ name: Rope.Cat[obName, "Seq", SELECT dir FROM X => "X", Y => "Y", RX => "RX", RY => "RY", ENDCASE => ERROR], baseCell: baseCT, count: count, sequencePorts: CoreCreate.WireList[sWires], flatSequencePorts: CoreCreate.WireList[fsWires], stitchPorts: stitchPorts]; SELECT dir FROM X => PWCore.SetArrayX[ct]; Y => PWCore.SetArrayY[ct]; RX => PWCore.SetLayout[ct, $ReverseArrayX]; RY => PWCore.SetLayout[ct, $ReverseArrayY]; ENDCASE => ERROR; Sisyph.Eval[cx, "coreProps _ NIL"]; -- To prevent coreProps of the object from overriding }; CSeq: PUBLIC PROC [cx: Sisyph.Context, count: NAT, dir: XorY] RETURNS [ct: Core.CellType] = { ct _ CSeqOb[CDDirectory.Name[Sisyph.GetCDObj[cx]], cx, count, dir]; }; CSeqOb: PUBLIC PROC [obName: ROPE, cx: Sisyph.Context, count: NAT, dir: XorY] RETURNS [ct: Core.CellType] = { sWires, fsWires: LIST OF CoreCreate.WR; EachWire: CoreOps.EachWireProc = { sides: CoreGeometry.Sides = WireSide[wire, baseCT]; vertical: BOOL = sides[top] OR sides[bottom]; horizontal: BOOL = sides[left] OR sides[right]; IF ~(vertical OR horizontal) THEN RETURN; -- This wire has no pins, try its sons IF vertical AND horizontal THEN WireSideProblem[wire, "touches adjacent sides", baseCT]; IF (vertical AND (dir=X OR dir=RX)) OR (horizontal AND (dir=Y OR dir=RY)) THEN IF wire.size=0 THEN sWires _ CONS[wire, sWires] ELSE fsWires _ CONS[wire, fsWires]; subWires _ FALSE; }; baseCT: Core.CellType _ Sisyph.ExtractSchematicByName[obName, cx]; [] _ CoreOps.VisitWireSeq[baseCT.public, EachWire]; ct _ CoreCreate.SequenceCell[ name: Rope.Cat[obName, "Seq", SELECT dir FROM X => "X", Y => "Y", RX => "RX", RY => "RY", ENDCASE => ERROR], baseCell: baseCT, count: count, sequencePorts: CoreCreate.WireList[sWires], flatSequencePorts: CoreCreate.WireList[fsWires] ]; SELECT dir FROM X => PWCore.SetArrayX[ct]; Y => PWCore.SetArrayY[ct]; RX => PWCore.SetLayout[ct, $ReverseArrayX]; RY => PWCore.SetLayout[ct, $ReverseArrayY]; ENDCASE => ERROR; Sisyph.Eval[cx, "coreProps _ NIL"]; -- To prevent coreProps of the object from overriding }; CStitch: PUBLIC PROC [cx: Context, count: NAT, dir: XorY] RETURNS [ct: CellType] = { ct _ CStitchOb[CDDirectory.Name[Sisyph.GetCDObj[cx]], cx, count, dir]; }; CStitchOb: PUBLIC PROC [obName: ROPE, cx: Context, count: NAT, dir: XorY] RETURNS [ct: CellType] = { SELECT dir FROM X => ct _ StitchX[obName, cx, count]; Y => ct _ StitchY[obName, cx, count]; ENDCASE => ERROR; Sisyph.Store[cx, Sisyph.corePropsRope, NEW [Core.Properties _ CoreProperties.Props[[$Layout, CoreProperties.GetCellTypeProp[ct, $Layout]]]]]; }; StitchX: PROC [obName: ROPE, cx: Sisyph.Context, count: NAT] RETURNS [ct: CellType] ~ { public: Wire; tileRow: TilingClass.TileRow _ NEW [TilingClass.TileRowRec[count]]; tileArray: TilingClass.TileArray _ NEW [TilingClass.TileArrayRec[1]]; baseCT: CellType _ Sisyph.ExtractSchematicByName[obName, cx]; publicElements, arrayedWires, leftSideOnlyWires, rightSideOnlyWires, globalWires: Wires _ NIL; EachWire: CoreOps.EachWireProc = { sides: CoreGeometry.Sides = WireSide[wire, baseCT]; vertical: BOOL = sides[top] OR sides[bottom]; IF vertical AND (sides[right] OR sides[left]) THEN WireSideProblem[wire, "touches adjacent sides", baseCT]; IF vertical THEN { newPublic: Wire _ CoreOps.CreateWires[count, CoreOps.GetShortWireName[wire]]; arrayedWires _ CONS[wire, arrayedWires]; FOR i: INT IN [0..count) DO newPublic[i] _ CoreOps.SetShortWireName[CoreOps.CopyWire[wire], NIL]; ENDLOOP; publicElements _ CONS[newPublic, publicElements]; } ELSE { IF sides=CoreGeometry.noSide THEN { IF IsGlobal[wire, cx] THEN { globalWires _ CONS [wire, globalWires]; publicElements _ CONS [wire, publicElements] } } ELSE { IF sides[left] THEN leftSideOnlyWires _ CONS[wire, leftSideOnlyWires]; IF sides[right] THEN rightSideOnlyWires _ CONS[wire, rightSideOnlyWires]; publicElements _ CONS [wire, publicElements] } } }; [] _ CoreOps.VisitWireSeq[baseCT.public, EachWire]; public _ CoreOps.CreateWire[publicElements]; FOR i: INT IN [0..count) DO tileRow[i] _ NEW [TilingClass.TileRec _ [type: baseCT]] ENDLOOP; FOR wl: Wires _ leftSideOnlyWires, wl.rest WHILE wl#NIL DO wireName: ROPE _ CoreOps.GetShortWireName[wl.first]; tileRow[0].renaming _ CONS[[wireName, wireName], tileRow[0].renaming]; ENDLOOP; FOR wl: Wires _ rightSideOnlyWires, wl.rest WHILE wl#NIL DO wireName: ROPE _ CoreOps.GetShortWireName[wl.first]; tileRow[count-1].renaming _ CONS[[wireName, wireName], tileRow[count-1].renaming]; ENDLOOP; FOR wl: Wires _ globalWires, wl.rest WHILE wl#NIL DO wireName: ROPE _ CoreOps.GetShortWireName[wl.first]; FOR i: NAT IN [0..count) DO tileRow[i].renaming _ CONS[[wireName, wireName], tileRow[i].renaming]; ENDLOOP; ENDLOOP; FOR wl: Wires _ arrayedWires, wl.rest WHILE wl#NIL DO wireName: ROPE _ CoreOps.GetShortWireName[wl.first]; FOR i: NAT IN [0..count) DO tileRow[i].renaming _ CONS[[wireName, Rope.Cat[wireName, "[", Convert.RopeFromInt[i], "]"]], tileRow[i].renaming]; ENDLOOP; ENDLOOP; tileArray[0] _ tileRow; <> ct _ TilingClass.CreateTiling[CoreOps.CopyWire[public], tileArray, TilingClass.SchematicsNeighborX, TilingClass.SchematicsNeighborY, Rope.Cat[obName, ".StitchX"]]; }; StitchY: PROC [obName: ROPE, cx: Sisyph.Context, count: NAT] RETURNS [ct: CellType] ~ { public: Wire; tileArray: TilingClass.TileArray _ NEW [TilingClass.TileArrayRec[count]]; baseCT: CellType _ Sisyph.ExtractSchematicByName[obName, cx]; publicElements, arrayedWires, botSideOnlyWires, topSideOnlyWires, globalWires: Wires _ NIL; EachWire: CoreOps.EachWireProc = { sides: CoreGeometry.Sides = WireSide[wire, baseCT]; horizontal: BOOL = sides[left] OR sides[right]; IF horizontal AND (sides[top] OR sides[bottom]) THEN WireSideProblem[wire, "touches adjacent sides", baseCT]; IF horizontal THEN { newPublic: Wire _ CoreOps.CreateWires[count, CoreOps.GetShortWireName[wire]]; arrayedWires _ CONS[wire, arrayedWires]; FOR i: INT IN [0..count) DO newPublic[i] _ CoreOps.SetShortWireName[CoreOps.CopyWire[wire], NIL]; ENDLOOP; publicElements _ CONS[newPublic, publicElements]; } ELSE { IF sides=CoreGeometry.noSide THEN { IF IsGlobal[wire, cx] THEN { globalWires _ CONS [wire, globalWires]; publicElements _ CONS [wire, publicElements] } } ELSE { IF sides[bottom] THEN botSideOnlyWires _ CONS[wire, botSideOnlyWires]; IF sides[top] THEN topSideOnlyWires _ CONS[wire, topSideOnlyWires]; publicElements _ CONS [wire, publicElements] } } }; [] _ CoreOps.VisitWireSeq[baseCT.public, EachWire]; public _ CoreOps.CreateWire[publicElements]; FOR i: INT IN [0..count) DO tileArray[i] _ NEW [TilingClass.TileRowRec[1]]; tileArray[i][0] _ NEW [TilingClass.TileRec _ [type: baseCT]] ENDLOOP; FOR wl: Wires _ botSideOnlyWires, wl.rest WHILE wl#NIL DO wireName: ROPE _ CoreOps.GetShortWireName[wl.first]; tileArray[0][0].renaming _ CONS[[wireName, wireName], tileArray[0][0].renaming]; ENDLOOP; FOR wl: Wires _ topSideOnlyWires, wl.rest WHILE wl#NIL DO wireName: ROPE _ CoreOps.GetShortWireName[wl.first]; tileArray[count-1][0].renaming _ CONS[[wireName, wireName], tileArray[count-1][0].renaming]; ENDLOOP; FOR wl: Wires _ globalWires, wl.rest WHILE wl#NIL DO wireName: ROPE _ CoreOps.GetShortWireName[wl.first]; FOR i: NAT IN [0..count) DO tileArray[i][0].renaming _ CONS[[wireName, wireName], tileArray[i][0].renaming]; ENDLOOP; ENDLOOP; FOR wl: Wires _ arrayedWires, wl.rest WHILE wl#NIL DO wireName: ROPE _ CoreOps.GetShortWireName[wl.first]; FOR i: NAT IN [0..count) DO tileArray[i][0].renaming _ CONS[[wireName, Rope.Cat[wireName, "[", Convert.RopeFromInt[i], "]"]], tileArray[i][0].renaming]; ENDLOOP; ENDLOOP; <> ct _ TilingClass.CreateTiling[CoreOps.CopyWire[public], tileArray, TilingClass.SchematicsNeighborX, TilingClass.SchematicsNeighborY, Rope.Cat[obName, ".StitchY"]]; }; WSeq: PUBLIC PROC [name: ROPE _ NIL, size: NAT] RETURNS [wire: Wire] = { wire _ CoreCreate.Seq[name, size]; }; WRange: PUBLIC PROC [name: ROPE, start: NAT, size: NAT] RETURNS [wire: Core.Wire] = { wire _ CoreCreate.Seq[size: size]; FOR i: NAT IN [0..size) DO [] _ CoreOps.SetShortWireName[wire[i], IO.PutFR["%g[%g]", IO.rope[name], IO.int[start+i]]]; ENDLOOP; }; <<>> WIndex: PUBLIC PROC [name: ROPE, index: NAT] RETURNS [wire: Core.Wire] = { wire _ CoreOps.CreateWire[name: name]; [] _ CoreOps.SetShortWireName[wire, IO.PutFR["%g[%g]", IO.rope[name], IO.int[index]]]; }; <<>> InitPort: PUBLIC PROC [cx: Context, initType: Ports.LevelType _ b, initDrive: Ports.Drive _ none] = { Sisyph.Eval[cx, "coreInstProps _ CoreProperties.PutProp[coreInstProps, $PortData, NEW[Ports.PortDataRec _ [ levelType: initType, driveType: aggregate, drive: initDrive, drives: NIL]]]"]; }; TSize: PUBLIC PROC [cx: Context, size: Rosemary.TransistorSize] = { Sisyph.Eval[cx, "coreInstProps _ CoreProperties.PutProp[coreInstProps, $RoseTransistorSize, NEW[Ports.Drive _ size]]"]; }; SetWire: PUBLIC PROC [cx: Context, level: Ports.Level _ L, size: Rosemary.WireSize _ charge] = { Sisyph.Eval[cx, "coreInstProps _ CoreProperties.PutProp[coreInstProps, $RoseWireData, NEW[Rosemary.RoseWireDataRec _ [level, size]]]"]; }; <> IsGlobal: PROC [w: Wire, cx: Sisyph.Context] RETURNS [BOOL _ FALSE] = { name: ROPE _ CoreOps.GetShortWireName[w]; FOR lr: LIST OF ROPE _ Sisyph.GetGlobalNames[cx], lr.rest WHILE lr#NIL DO IF Rope.Equal[name, lr.first] THEN RETURN [TRUE] ENDLOOP; }; END.