<> <> <> <> DIRECTORY BitHacks, CD, CoreCreate, EU2FU, EU2LeafUtils, EU2Utils, LayoutCheckpoint, PWCore, Rope; EU2FUImpl: CEDAR PROGRAM IMPORTS BitHacks, CoreCreate, EU2LeafUtils, EU2Utils, LayoutCheckpoint, PWCore, Rope EXPORTS EU2FU = BEGIN OPEN CoreCreate, EU2FU, EU2LeafUtils, EU2Utils; <<-- (left, st2A, r2B, cBus, fuOut)[0..32), insert, (mask, shift)[0..6), sh[0..33)>> CreateFieldUnit: PUBLIC PROC RETURNS [cellType: CellType] = { IF EU2Utils.useFUCheckpoint THEN RETURN [LayoutCheckpoint.Retrieve["FieldUnit"]]; PrintStart["FieldUnit"]; cellType _ Cell[ name: "FieldUnit", public: WireList[LIST["Vdd", "Gnd", Bus["left"], Bus["st2A"], Bus["r2B"], Bus["cBus"], Bus["fuOut"], "insert", Seq["mask", 6], Seq["shift", 6], Seq["sh", wordSize+1] ]], onlyInternal: Wires[Bus["m1"], Bus["m2"], Bus["shOut"], "pass"], instances: LIST [ Instance[CreateMask[]], Instance[CreateCompose[]], Instance[CreateBarrelShifter[]] ] ]; PWCore.SetAbutY[cellType]; PrintStop[]; }; <<>> <<-- A barrel shifter; two inputs (left and st2A), one output (fuOut)>> <<-- sh=0 => out_left; sh=wordSize => out_st2A; shift by zero is on top;>> <<-- The layout is explicit because the shifter is a special type of array not expressible by a Sequence cell (diagonal port is the same on the top and left side). >> <<>> <<-- shOut[0..32), sh[0..33), pass, (left, st2A, r2B, cBus, fuOut)[0..32), Vdd, Gnd>> CreateBarrelShifter: PROC [] RETURNS [cellType: CellType] = { shLine: CellType _ CreateBarrelShifterRow[]; instances: CellInstances _ LIST[Instance[CreateShTop[]]]; -- connect to left sh: Wire _ Seq["sh", wordSize+1]; shOut: Wire _ Bus["shOut"]; left: Wire _ Bus["left"]; st2A: Wire _ Bus["st2A"]; r2B: Wire _ Bus["r2B"]; cBus: Wire _ Bus["cBus"]; fuOut: Wire _ Bus["fuOut"]; public: Wire _ Wires[shOut, sh, "pass", "Vdd", "Gnd", left, st2A, r2B, cBus, fuOut]; FOR row: NAT IN [0..wordSize+1) DO bindings: LIST OF PA _ LIST[["sh", sh[row]], ["shOut", shOut]]; FOR column: NAT IN [0..wordSize) DO sum: NAT _ row+column; to: WR _ IF sum> <<-- in[0..32), shOut[0..32), sh, pass>> CreateBarrelShifterRow: PROC [] RETURNS [cellType: CellType] = { shCell: CellType _ Extract["ShifterCell.sch"]; instances: CellInstances _ NIL; FOR i: NAT DECREASING IN [0..wordSize) DO inst: CellInstance _ Instance[shCell, ["sh", "sh"], ["in", Index["in", i]], ["shOut", Index["shOut", i]], ["st2A", Index["st2A", i]], ["r2B", Index["r2B", i]], ["cBus", Index["cBus", i]], ["fuOut", Index["fuOut", i]], ["pass", IF i=wordSize-1 THEN "pass" ELSE Index["in", i+1] ]]; instances _ CONS[inst, instances]; ENDLOOP; cellType _ Cell[name: "BarrelShifterRow", public: Wires[Bus["in"], "sh", Bus["shOut"], "pass", "Vdd", "Gnd", Bus["st2A"], Bus["r2B"], Bus["cBus"], Bus["fuOut"]], instances: instances]; PWCore.SetAbutX[cellType]; -- it is really an array, but who cares? }; <<>> <<-- The field unit uses a mask generator which takes two 6-bit quantities ("shift" and "mask") and a boolean (insert), and produces a mask of the form:>> <> <> <> <<-- A bit of mask generation theory: let k and i be two n+1-bit numbers, and F[n, k, i]=k>i. By recurring on the high-order bit, we find that >> <> <> <> << F[n, k, i]=k[n] + F[n-1, k, i]=Nand [~k[n], ~F[n-1, k, i]] (NOR to Gnd)>> <> << F[n, k, i]=k[n] . F[n-1, k, i]=Nor [~k[n], ~F[n-1, k, i]] (NAND branch)>> <<-- Note: a NAND branch starting with no tr. still has no tr., i.e. if i=xx0111 then the three bottom transistors are missing! >> <<>> <<-- mask[0..6), shift[0..6), (m1, m2, st2A, r2B, cBus, fuOut)[0..32), Vdd, Gnd, >> CreateMask: PROC RETURNS [cellType: CellType] = { instances: CellInstances _ NIL; FOR i: [0..wordSize) DECREASING IN [0..wordSize) DO instances _ CONS[ Instance[CreateMasksCell[i], ["m1", Index["m1", i]], ["m2", Index["m2", i]], ["st2A", Index["st2A", i]], ["r2B", Index["r2B", i]], ["cBus", Index["cBus", i]], ["fuOut", Index["fuOut", i]]], instances]; ENDLOOP; cellType _ Cell[ name: "Mask", public: Wires["Vdd", "Gnd", Seq["mask", sizeK], Seq["shift", sizeK], Bus["m1"], Bus["m2"], Bus["st2A"], Bus["r2B"], Bus["cBus"], Bus["fuOut"]], instances: instances]; PWCore.SetAbutX[cellType]; }; <<-- "Vdd", "Gnd", "shift[0..6)", "mask[0..6)", "m1", "m2", "st2A", "r2B", "cBus", "fuOut">> CreateMasksCell: PROC [pos: [0..wordSize)] RETURNS [cellType: CellType] = { m1: CellType _ CreateMaskCell["mask", "m1", 31-pos]; m2: CellType _ CreateMaskCell["shift", "m2", 31-pos]; cellType _ Cell[ name: "Masks", public: Wires["Vdd", "Gnd", Seq["mask", sizeK], Seq["shift", sizeK], "m1", "m2", "st2A", "r2B", "cBus", "fuOut" ], instances: LIST[Instance[m2], Instance[m1]]]; PWCore.SetAbutY[cellType]; }; Trits: TYPE = {P, S, F, X}; Pat: TYPE = ARRAY [0..6) OF Trits; Pattern: PROC [k: NAT] RETURNS [lowToHi: Pat] ~ { isOne: BOOL _ BitHacks.XthBitOfN[0, k]; lowToHi[0] _ IF isOne THEN X ELSE F; FOR bit: NAT IN [1..6) DO isOne _ BitHacks.XthBitOfN[bit, k]; lowToHi[bit] _ SELECT TRUE FROM isOne AND lowToHi[bit-1]=X => X, isOne => S, ~isOne AND lowToHi[bit-1]=X => F, ~isOne => P, ENDCASE => ERROR; ENDLOOP; }; <<-- Using a generator of static gates, program maskOut=F(a, pos)>> <<-- "Vdd", "Gnd", "selName[0..6)", "maskOut">> <<-- (selName, outName) can be (mask, m1) or (shift, m2); >> CreateMaskCell: PROC [selName, outName: ROPE, pos: [0..32)] RETURNS [cellType: CellType] = { pas: LIST OF CoreCreate.PA _ LIST[["Vdd", "Vdd"], ["m1", "m1"], ["m2", "m2"], ["Gnd", "Gnd"], ["st2A", "st2A"], ["r2B", "r2B"], ["cBus", "cBus"], ["fuOut", "fuOut"]]; POb: CD.Object _ PWCore.Layout[Extract["maskP.sch"]]; SOb: CD.Object _ PWCore.Layout[Extract["maskS.sch"]]; FOb: CD.Object _ PWCore.Layout[Extract["maskF.sch"]]; XOb: CD.Object _ PWCore.Layout[Extract["maskX.sch"]]; botOb: CD.Object _ PWCore.Layout[Extract["maskBot.sch"]]; public: Wire _ Wires["Vdd", "Gnd", Seq[selName, sizeK], "m1", "m2", "st2A", "r2B", "cBus", "fuOut"]; abutInstances: LIST OF PWCore.AbutInstance _ LIST [ [PWCore.Layout[Extract[Rope.Cat[outName, "top.sch"]]], pas]]; lowToHi: Pat _ Pattern[pos]; FOR bit: NAT DECREASING IN [0..6) DO ob: CD.Object _ SELECT lowToHi[bit] FROM X => XOb, F => FOb, S => SOb, P => POb, ENDCASE => ERROR; abutInstances _ CONS [[ob, CONS[["sel", Index[selName, 5-bit]], pas]], -- check!!! abutInstances]; ENDLOOP; abutInstances _ CONS [[botOb, pas], abutInstances]; cellType _ PWCore.AbutCell[ name: "Mask", public: public, abutInstances: abutInstances, inX: FALSE]; }; <<>> <<-- The composition cell: two masks, two words, insert, and an output>> <<-- Vdd, Gnd, insert, (st2A, r2B, cBus, fuOut, shOut, m1, m2)[0..32)>> CreateCompose: PROC [] RETURNS [cellType: CellType] = { cellType _ SequenceCell[name: "Compose", baseCell: Extract["ComposeCell.sch"], count: wordSize, sequencePorts: Wires["st2A", "r2B", "cBus", "m1", "m2", "shOut", "fuOut"]]; PWCore.SetArrayX[cellType]; }; <<>> END. << TO DO>> Get the function index->mask correct Enlarge nE in shifter <> <> <> <> <> <> <> <> <> <> <> <> <0 THEN {new _ Wires[]; internalList _ CONS[new, internalList]} >> <> <> <> <<["sel", Index[selName, i]], ["n", currentN], ["pHi", currentP], ["pLow", new]], >> <> <<} >> <> <0 THEN {new _ Wires[]; internalList _ CONS[new, internalList]}>> <> <> <> <<["sel", Index[selName, i]], ["p", currentP], ["nHi", currentN], ["nLow", new]], >> <> <<};>> <> <> <> <> <> <> <> <> <> <> <<};>>