<> <> <> DIRECTORY BitHacks, CoreClasses, CoreCreate, CoreOps, EU2ALU, EU2LeafUtils, EU2Utils, IO, LayoutCheckpoint, PWCore, PWCoreRoute; EU2ALUImpl: CEDAR PROGRAM IMPORTS BitHacks, CoreCreate, CoreOps, EU2LeafUtils, EU2Utils, IO, LayoutCheckpoint, PWCore, PWCoreRoute EXPORTS EU2ALU = BEGIN OPEN CoreCreate, EU2ALU, EU2LeafUtils, EU2Utils; <<-- Buses: (left, right, aluOut, st2A, r2B, cBus)[0..32), Vdd, Gnd>> <<-- From ctrl: carryIn, op[0..5)>> <<-- To ctrl: p0to31, carry[31], aluOut[0..8), left[0..3), right[0..3), right[19..32)>> <<-- Coming out of this channel: >> <> CreateALU: PUBLIC PROC RETURNS [cellType: CellType] = { <<-- To build the internal and public>> Vdd: Wire _ CoreOps.CreateWire[name: "Vdd"]; Gnd: Wire _ CoreOps.CreateWire[name: "Gnd"]; left: Wire _ Bus["left"]; right: Wire _ Bus["right"]; st2A: Wire _ Bus["st2A"]; r2B: Wire _ Bus["r2B"]; cBus: Wire _ Bus["cBus"]; aluOut: Wire _ Bus["aluOut"]; P: Wire _ Bus["P"]; G: Wire _ Bus["G"]; carry: Wire _ Bus["carry"]; carryOut: Wire _ CoreOps.CreateWire[name: "carryOut"]; op: Wire _ Seq["op", 5]; tree: Wire _ TreeWires[]; internal: Wire _ Union[ WireList[LIST[ Vdd, Gnd, op, carryOut, left, right, st2A, r2B, cBus, aluOut, P, G, carry]], tree]; zero: Wire _ FindWire[internal, "p0to31"]; carryIn: Wire _ FindWire[internal, "carry"][31]; public: Wire _ Wires[Vdd, Gnd, op, carryOut, carryIn, zero, left, right, st2A, r2B, cBus, aluOut]; <<-- To build the channel>> res: Wire _ Range[aluOut, 0, 8]; opL: Wire _ Range[left, 0, 3]; opR: Wire _ Range[right, 0, 3]; fd: Wire _ Range[right, 19, 13]; channelData: PWCoreRoute.ChannelData _ NEW[PWCoreRoute.ChannelDataRec _ [ inX: FALSE, bottomOrLeftWires: LIST[Vdd, Gnd, zero, carryIn, carryOut, res, opL, opR, fd], topOrRightWires: LIST[Vdd, Gnd], trunkLayer: "metal", branchLayer: "metal2", wireWidthProc: PWCoreRoute.GndAndVdd25Met2MinWidth ]]; IF EU2Utils.useALUCheckpoint THEN RETURN [LayoutCheckpoint.Retrieve["ALU"]]; PrintStart["ALU"]; cellType _ Cell[ name: "ALU", public: public, internal: internal, instances: LIST [ Instance[CreateFunctionBlock[]], Instance[CreateCarryProp[]] ] ]; PWCore.SetLayout[cellType, $Channel, $ChannelData, channelData]; PrintStop["ALU"]; }; <<-- Function Blocks: generate P and G, combine C to produce aluOut>> <<-- (left, right, aluOut, st2A, r2B, cBus, G, P, carry)[0..32), op[0..5), Vdd, Gnd>> CreateFunctionBlock: PROC RETURNS [cellType: CellType] = { cellType _ SequenceCell[name: "FunctionBlock", baseCell: Extract["ALUFnBlock.sch"], count: wordSize, sequencePorts: Wires["left", "right", "aluOut", "st2A", "r2B", "cBus", "G", "P", "carry"]]; PWCore.SetArrayX[cellType]; }; <<-- Carry Propagator: a tree laid out as an array>> <<-- top, 0, 0:1, 1, 0:3, 2, 2:3, 3, 0:7, ...>> <<-- Bottom: (P, G, carry)[0..32). >> <<-- Next level p0to1, p2to3, ... then p0to3, p4to7... and finally p0to31; same with g.>> CreateCarryProp: PROC RETURNS [cellType: CellType] = { AttachInst: PROC ~ { left, right, mid: NAT; pas: LIST OF PA _ NIL; FOR pos: NAT DECREASING IN [1..32) DO -- root already placed [left, right, mid] _ F[pos]; pas _ LIST[ ["Cin", Index["carry", right]], ["C", Index["carry", mid]], ["G", IO.PutFR["g%gto%g", IO.int[left], IO.int[right]]], ["P", IO.PutFR["p%gto%g", IO.int[left], IO.int[right]]], ["left", Index["left", pos]], -- just buses ["right", Index["right", pos]], ["st2A", Index["st2A", pos]], ["r2B", Index["r2B", pos]], ["cBus", Index["cBus", pos]] ]; IF BitHacks.ODD[pos] THEN { -- leaf cell pas _ CONS[["Pleft", Index["P", left]], pas]; pas _ CONS[["Gleft", Index["G", left]], pas]; pas _ CONS[["Pright", Index["P", right]], pas]; pas _ CONS[["Gright", Index["G", right]], pas]; } ELSE { pas _ CONS[["Pleft", IO.PutFR["p%gto%g", IO.int[left], IO.int[mid]]], pas]; pas _ CONS[["Gleft", IO.PutFR["g%gto%g", IO.int[left], IO.int[mid]]], pas]; pas _ CONS[["Pright", IO.PutFR["p%gto%g", IO.int[mid+1], IO.int[right]]], pas]; pas _ CONS[["Gright", IO.PutFR["g%gto%g", IO.int[mid+1], IO.int[right]]], pas]; }; instances _ CONS[InstanceList[cp, pas], instances]; ENDLOOP; }; cp: CellType _ Extract["ALUCP.sch"]; instances: LIST OF CellInstance _ NIL; <<-- The tree: 31 instances>> AttachInst[]; <<-- The top, a bit special: just apply f0to31 to carry[0] to get carryOut, ignore the rest>> instances _ CONS[ Instance[cp, ["Gleft", "Gnd"], ["Pleft", "Gnd"], ["Gright", "g0to31"], ["Pright", "p0to31"], ["Cin", "carryOut"], ["C", "carry[0]"], ["G", "fakos"], ["P", "fakos"], ["left", "left[0]"], ["right", "right[0]"], ["st2A", "st2A[0]"], ["r2B", "r2B[0]"], ["cBus", "cBus[0]"]], instances]; cellType _ Cell[ name: "CarryProp", public: Union[ Wires["Vdd", "Gnd", Bus["left"], Bus["right"], Bus["st2A"], Bus["r2B"], Bus["cBus"], Bus["P"], Bus["G"], Bus["carry"], "carryOut"], TreeWires[]], onlyInternal: Wires["fakos"], instances: instances]; PWCore.SetAbutX[cellType]; }; <<-- Wire generation>> F: PROC [pos: NAT] RETURNS [left, right, mid: NAT] ~ { width: NAT _ 1; level: NAT _ pos; WHILE BitHacks.EVEN[level] DO IF level=0 THEN ERROR; -- no infinite loop! width _ 2*width; level _ level/2; ENDLOOP; RETURN[left: pos-width, right: pos+width-1, mid: pos-1]; }; <<>> <<-- All the extra wires that wire up the tree (p0to1, g0to3, ...)>> TreeWires: PROC RETURNS [Wire] ~ { wrs: LIST OF WR_ NIL; <<-- p and g tree>> MakeWire: PROC [first, width: NAT] ~ { mid, half, last: NAT; IF width=1 THEN RETURN; -- bottom already taken care of. -- Up in the tree: f0to3, f4to7 => f0to7 with c7 => c3 last _ first+width-1; <<-- root>> wrs _ CONS[IO.PutFR["p%gto%g", IO.int[first], IO.int[last]], wrs]; wrs _ CONS[IO.PutFR["g%gto%g", IO.int[first], IO.int[last]], wrs]; <<-- siblings>> half _ width/2; mid _ first+half-1; MakeWire[first, half]; MakeWire[mid+1, half]; }; MakeWire[0, 32]; RETURN[WireList[wrs]]; }; END. << TO DO>> <>