DIRECTORY CD, CDSimpleRules, CMosB, CoreCreate, CoreOps, CoreProperties, CoreGeometry, EUInner, EUUtils, PWCore, PWObjects, Rope; EURegsImpl: CEDAR PROGRAM IMPORTS CD, CDSimpleRules, CMosB, CoreCreate, CoreOps, CoreProperties, CoreGeometry, EUUtils, PWCore, PWObjects, Rope EXPORTS EUInner = BEGIN OPEN CoreCreate, EUInner; l: INT = CMosB.cmosB.lambda; dpPitch: INT = 140*l; -- Should be changed whenever the pitch of the DataPath changes! dReadBus: ROPE _ "cBus"; -- the bus used for debugging Bus: TYPE = EUUtils.Bus; Source: TYPE = EUUtils.Source; DPBus: PROC [index: EUUtils.BusRange] RETURNS [EUUtils.Bus]~{ RETURN[EUUtils.buses[index]]}; DPSource: PROC [index: EUUtils.SourceRange] RETURNS [EUUtils.Source]~{ RETURN[EUUtils.sources[index]]}; AllBuses: PROC [reg: Source] RETURNS [Wire] ~ { names: LIST OF WR _ NIL; FOR busIndex: EUUtils.BusRange IN EUUtils.BusRange DO bus: Bus _ DPBus[busIndex]; IF IsBusInReg[bus, reg] THEN names _ CONS[bus.name, names]; ENDLOOP; RETURN [IF names=NIL THEN NIL ELSE WireList[names]]; }; ConnectedBuses: PROC [reg: Source] RETURNS [buses: Wire] ~ { dReadBusPresent: BOOL _ FALSE; names: LIST OF WR _ NIL; name: ROPE; FOR i: NAT IN [0..reg.sizeSel) DO name _ DPBus[reg.inputs[i]].name; -- name of one input bus IF Rope.Equal[name, dReadBus] THEN dReadBusPresent _ TRUE; names _ CONS[name, names]; ENDLOOP; name _ DPBus[reg.output].name; -- name of the output of the source names _ CONS[name, names]; IF Rope.Equal[name, dReadBus] THEN dReadBusPresent _ TRUE; IF ~dReadBusPresent THEN names _ CONS[dReadBus, names]; buses _ WireList[names]; }; -- Creates the buses on the right side of the cell; CreateBuses: PROC [reg: Source, leftCT: CellType, horizontalWire: Wire] RETURNS [cellType: CellType] ~ { public: Wire _ CoreOps.CopyWire[Union[AllBuses[reg], horizontalWire]]; -- do not forget the copy wire! (otherwise, wires are shared and that might result in 815!!!) cellType _ Cell[name: "CreateBuses", public: public, instances: NIL]; PWCore.SetLayout[cellType, $CreateBusesLayout, $LeftCellType, leftCT]; CoreProperties.PutCellTypeProp[cellType, $Reg, reg]; }; IsBus: PROC [name: ROPE] RETURNS [Bus] ~ { FOR bus: EUUtils.BusRange IN EUUtils.BusRange DO IF Rope.Equal[EUUtils.buses[bus].name, name] THEN RETURN [EUUtils.buses[bus]]; ENDLOOP; RETURN[NIL] }; NameToBus: PROC [name: ROPE] RETURNS [bus: Bus] ~ { bus _ IsBus[name]; IF bus=NIL THEN ERROR -- unknown bus }; FindBusPosX: PROC [name: ROPE] RETURNS [INT] ~ { RETURN[(NameToBus[name].trackPosX*8+2)*CMosB.lambda]; }; IsTopBus: PROC [name: ROPE, reg: Source] RETURNS [BOOL _ FALSE] ~ { RETURN [DPSource[NameToBus[name].bottom] = reg]; }; IsBotBus: PROC [name: ROPE, reg: Source] RETURNS [BOOL _ FALSE] ~ { RETURN [DPSource[NameToBus[name].top] = reg]; }; IsBusInReg: PROC [bus: Bus, reg: Source] RETURNS [BOOL] ~ { RETURN[DPSource[bus.top].position<= reg.position AND reg.position<=DPSource[bus.bottom].position]; }; IsVBus: PROC [name: ROPE, reg: Source] RETURNS [BOOL _ FALSE] ~ { bus: Bus _ IsBus[name]; RETURN[IF bus=NIL THEN FALSE ELSE IsBusInReg[bus, reg]]; }; CreateBusesLayout: PWCore.LayoutProc = { DrawNet: PROC [wire: Wire] ~ { geometry: LIST OF PWObjects.PlacedObject _ NIL; name: ROPE _ CoreOps.GetFullWireName[cellType.public, wire]; leftWire: Wire _ CoreCreate.FindWire[leftCT.public, name]; SELECT TRUE FROM leftWire=NIL => geometry _ LIST [ [CDSimpleRules.Rect[[4*l, sizeY], CMosB.met2], [FindBusPosX[name], 0]]]; NOT IsVBus[name, reg] => { DrawHoriz: CoreGeometry.EachPinProc = { IF side=right AND layer=CMosB.met THEN geometry _ CONS [ [CDSimpleRules.Rect[[sizeX, max-min], CMosB.met], [0, min]], geometry]; }; [] _ CoreGeometry.EnumerateSides[PWCore.extractMode.decoration, leftCT, leftWire, DrawHoriz]; }; ENDCASE => { DrawContact: CoreGeometry.EachPinProc = { IF side#right THEN RETURN; IF layer#CMosB.met THEN RETURN; geometry _ CONS [ [CDSimpleRules.Rect[[posX, max-min], CMosB.met], [0, min]], geometry]; geometry _ CONS [ [CDSimpleRules.Contact[CMosB.met, CMosB.met2], [posX, min]], geometry]; y1 _ MIN [y1, min]; y2 _ MAX [y2, max]; }; posX: INT _ FindBusPosX[name]; y1: INT _ IF IsTopBus[name, reg] THEN LAST[INT] ELSE 0; y2: INT _ IF IsBotBus[name, reg] THEN FIRST[INT] ELSE sizeY; [] _ CoreGeometry.EnumerateSides[PWCore.extractMode.decoration, leftCT, leftWire, DrawContact]; geometry _ CONS [ [CDSimpleRules.Rect[[4*l, y2-y1], CMosB.met2], [posX, y1]], geometry]; }; nodes _ CONS [PWObjects.CreateNode[geometry, LIST [[key: $InstanceName, val: name]]], nodes]; }; leftCT: CellType _ NARROW [CoreProperties.GetCellTypeProp[cellType, $LeftCellType]]; leftSize: CD.Position _ CD.InterestSize[PWCore.Layout[leftCT]]; sizeX: INT _ dpPitch-leftSize.x; sizeY: INT _ leftSize.y; reg: Source _ NARROW [CoreProperties.GetCellTypeProp[cellType, $Reg], Source]; nodes: LIST OF PWObjects.Node _ NIL; CoreOps.VisitRootAtomics[cellType.public, DrawNet]; obj _ PWObjects.CreateRouting[[0, 0, sizeX, sizeY], nodes]; }; CreateRegAndMuxOnly: PROC [reg: Source] RETURNS [cellType: CellType] ~ { -- The select lines, i.e. selLeftSrc[0..3), and all public of reg, except "in" sel: Wire _ Seq["sel", reg.sizeSel+2]; muxTop: CellType _ EUUtils.Extract["RegMuxTop.sch"]; -- Vdd, Gnd, sel, muxIn, muxOut mux: CellType _ EUUtils.Extract["RegMux.sch"]; -- Vdd, Gnd, sel, muxIn, muxOut muxOut: Wire _ CoreOps.CreateWire[name: "muxOut"]; tristate: BOOL _ reg.tristate; ct: CellType _ EUUtils.Extract[IF tristate THEN "Tristate.sch" ELSE "Register.sch"]; instances: LIST OF CellInstance _ LIST[ Instance[muxTop, ["sel", Index[sel, 0]], ["muxIn", DPBus[reg.inputs[0]].name], ["muxOut", muxOut]]]; FOR i: NAT IN [1..reg.sizeSel) DO instances _ CONS[ Instance[mux, ["sel", Index[sel, i]], ["muxIn", DPBus[reg.inputs[i]].name], ["muxOut", muxOut]], instances]; ENDLOOP; instances _ CONS[ -- sel[max] = write cBus Instance[mux, ["sel", sel[reg.sizeSel]], ["muxIn", dReadBus], ["muxOut", muxOut]], instances]; instances _ CONS[ Instance[ct, -- Vdd, Gnd, in, out, dRead or sel[max+1], dOut ["in", muxOut], ["out", DPBus[reg.output].name], ["enW", Index[sel, reg.sizeSel+1]], IF tristate THEN [] ELSE ["dOut", dReadBus] ], instances]; cellType _ Cell[ name: "RegAndMuxOnly", public: Union[ConnectedBuses[reg], Wires[sel, "Vdd", "Gnd"]], onlyInternal: Wires[muxOut], instances: instances ]; PWCore.SetAbutY[cellType]; }; CreateRegCell: PROC [reg: Source] RETURNS [cellType: CellType] ~ { sel: Wire _ Seq["sel", reg.sizeSel+2]; -- including enW leftCt: CellType _ CreateRegAndMuxOnly[reg]; cellType _ Cell[ name: "Reg", public: Union[AllBuses[reg], Wires[sel, "Vdd", "Gnd"]], instances: LIST[ Instance[leftCt], Instance[CreateBuses[reg, leftCt, Wires[sel]]]] ]; PWCore.SetAbutX[cellType]; }; CreateReg: PUBLIC PROC [regIndex: EUUtils.PipeRange] RETURNS [cellType: CellType] = { reg: Source _ DPSource[regIndex]; cellType _ SequenceCell[ name: "RegWithMux", baseCell: CreateRegCell[reg: reg], count: 32, sequencePorts: AllBuses[reg]]; -- the only "vertical" wires PWCore.SetArrayX[cellType]; }; CreatePDriver: PUBLIC PROC RETURNS [cellType: CellType] = { leftCt, thisPDriver, onePDriver: CellType; reg: Source _ DPSource[EUUtils.pDriverRow]; leftCt _ EUUtils.Extract["PDriver.sch"]; -- binding to the real buses thisPDriver _ Cell[ name: "thisPDriver", public: Wires["r2B", "st3A", "pDriver", "phA", "phB", "nPhA", "nPhB", "Vdd", "Gnd"], instances: LIST[Instance[leftCt, ["inA", "r2B"], ["inB", "st3A"], ["out", "pDriver"]]] ]; PWCore.SetAbutX[thisPDriver]; -- adding the buses onePDriver _ Cell[ name: "PDriverWithBuses", public: Union[AllBuses[reg], Wires["phA", "phB", "nPhA", "nPhB", "Vdd", "Gnd"]], instances: LIST[ Instance[thisPDriver], Instance[CreateBuses[reg, thisPDriver, Wires["phA", "phB", "nPhA", "nPhB", "Vdd", "Gnd"]]]] ]; PWCore.SetAbutX[onePDriver]; -- a sequence of 32 cellType _ SequenceCell[ name: "PDriver", baseCell: onePDriver, count: 32, sequencePorts: AllBuses[reg]]; -- the only "vertical" wires PWCore.SetArrayX[cellType]; }; CreateShRegDriver: PUBLIC PROC RETURNS [cellType: CellType] = { cellType _ EUUtils.CSeqX["shRegDriver", EUUtils.Extract["shReg.sch"], 32, LIST["out", "ramA", "ramB", "in", "cBus", "ifuIn"]]; }; CreatekRegAndShift: PUBLIC PROC [] RETURNS [ct: CellType] = { ct _ EUUtils.Fetch["kRegAndShift"]; IF ct=NIL THEN { ct _ EUUtils.Extract["kRegAndShift.sch"]; EUUtils.Store["kRegAndShift", ct]; }; }; [] _ PWCore.RegisterLayoutAtom[$CreateBusesLayout, CreateBusesLayout, PWCore.DecorateValue]; END. ฎEURegsImpl.mesa Copyright c 1985 by Xerox Corporation. All rights reserved. Louis Monier June 19, 1986 4:43:22 pm PDT Barth, April 22, 1986 12:27:26 pm PST Bertrand Serlet August 26, 1986 1:37:24 am PDT Last Edited by: Louis Monier October 29, 1986 12:30:57 pm PST -- All the buses at the level of this source -- All the buses used as input or output, including the bus for debugging (dReadBus) -- no bus is both an input and an output -- add the dReadBus if not yet present -- Returns NIL if not a datapath bus -- control line or contact on this bus, i.e. pins found on the right side of leftCT -- contact on this bus -- Assemble the register (ev. with a tristate driver) with the muxes -- The inputs in EUUtils.sources[reg].inputs must be in order, i.e. for left: sel[0]->ramA -- write from cBus (for debugging only) is mapped onto sel[max+1] -- dRead is mapped onto sel[max+2], unless tristate; then enWrite is mapped onto sel[max+2] -- Instances: the register and all mux transistors -- the top mux has a slightly different layout -- Assemble a register with its mux and adds the routing on the right using a table in EUUtils -- Just a replication of 32 register+mux -- Special guys ส +– "cedar" style˜codešœ™Kšœ ฯmœ1™