CreateBarrelShifter:
PUBLIC PROC [cx: Sisyph.Context]
RETURNS [cellType: CellType] = {
sh: Wire ← Seq["sh", 32+1];
shOut: Wire ← Seq["shOut", 32];
left: Wire ← Seq["left", 32];
st2A: Wire ← Seq["st2A", 32];
r2B: Wire ← Seq["r2B", 32];
cBus: Wire ← Seq["cBus", 32];
fuOut: Wire ← Seq["fuOut", 32];
tileArray: TilingClass.TileArray ← NEW[TilingClass.TileArrayRec[35]];
-- 0 is the bottom
tileArray[0] ← NEW[TilingClass.TileRowRec[32]];
FOR i:
NAT
IN [0..32)
DO
tileArray[0][i] ←
NEW[TilingClass.TileRec ← [
type: Sisyph.ES["shRightConnect.sch", cx],
flatten: TRUE,
renaming: LIST[["Vdd", "Vdd"], ["Gnd", "Gnd"], ["st2A", st2A[i]], ["r2B", r2B[i]], ["cBus", cBus[i]], ["fuOut", fuOut[i]], ["shOut", shOut[i]] ]
]];
ENDLOOP;
-- line n of shifter is tileArray[n+1]
FOR row:
NAT
IN [1..33]
DO
tileArray[row] ← NEW[TilingClass.TileRowRec[32]];
FOR i:
NAT
IN [0..32)
DO
tileArray[row][i] ←
NEW[TilingClass.TileRec ← [
type: Sisyph.ES["ShifterCell.sch", cx],
flatten: TRUE,
renaming: LIST[["sh", sh[33-row]]]
]];
ENDLOOP;
ENDLOOP;
-- 34 is the top
tileArray[34] ← NEW[TilingClass.TileRowRec[32]];
FOR i:
NAT
IN [0..32)
DO
tileArray[34][i] ←
NEW[TilingClass.TileRec ← [
type: Sisyph.ES["shLeftConnect.sch", cx],
flatten: TRUE,
renaming: LIST[ ["left", left[i]] ]
]];
ENDLOOP;
cellType ← TilingClass.CreateTiling[
name: "BarrelShifter",
public: Wires[shOut, sh, "Vdd", "Gnd", left, st2A, r2B, cBus, fuOut],
tileArray: tileArray,
neighborX: TilingClass.LayoutNeighborX,
neighborY: TilingClass.LayoutNeighborY
];
};
-- 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].~i[n]+(k[n]=i[n]).F[n-1, k, i], and for 1-bit numbers F[0, k, i]=k[0].~i[0]
In every slice, i is a constant and k an input. Let's decompose according to the value of i[n]:
i[n]=0: F[0, k, i]=k[0] (use k[0])
F[n, k, i]=k[n] + F[n-1, k, i]=Nand [~k[n], ~F[n-1, k, i]] (NOR to Gnd)
i[n]=1: F[0, k, i]=0 (no transistor)
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:
PUBLIC PROC [cx: Sisyph.Context]
RETURNS [cellType: CellType] = {
instances: CellInstances ← NIL;
FOR i: [0..32)
DECREASING
IN [0..32)
DO
instances ←
CONS[
Instance[CreateMasksCell[i, cx],
["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", 6], Seq["shift", 6],
Seq["m1", 32], Seq["m2", 32], Seq["st2A", 32], Seq["r2B", 32], Seq["cBus", 32], Seq["fuOut", 32]],
instances: instances];
PWCore.SetAbutX[cellType];
};
-- "Vdd", "Gnd", "shift[0..6)", "mask[0..6)", "m1", "m2", "st2A", "r2B", "cBus", "fuOut"
CreateMasksCell:
PROC [pos: [0..32), cx: Sisyph.Context]
RETURNS [cellType: CellType] = {
m1: CellType ← CreateMaskCell["mask", "m1", 31-pos, cx];
m2: CellType ← CreateMaskCell["shift", "m2", 31-pos, cx];
bottom: CellType ← Sisyph.ES["masksBottomSep.sch", cx];
cellType ← Cell[
name: "Masks",
public: Wires["Vdd", "Gnd", Seq["mask", 6], Seq["shift", 6], "m1", "m2", "st2A", "r2B", "cBus", "fuOut" ],
instances: LIST[Instance[bottom], 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];
isOne: BOOL ← BitOps.EBFD[k, 31]; -- low-order bit I believe
lowToHi[0] ← IF isOne THEN X ELSE F;
FOR bit:
NAT
IN [1..6)
DO
isOne ← BitHacks.XthBitOfN[bit, k];
isOne ← BitOps.EBFD[k, 31-bit];
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), cx: Sisyph.Context]
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"]];
public: Wire ← Wires["Vdd", "Gnd", Seq[selName, 6], "m1", "m2", "st2A", "r2B", "cBus", "fuOut"];
tiles: TilingClass.TileArray ← NEW [TilingClass.TileArrayRec[8]];
lowToHi: Pat ← Pattern[pos];
tiles[7] ← NEW [TilingClass.TileRowRec[1]];
tiles[7][0] ←
NEW [TilingClass.TileRec ← [
type: Sisyph.ES[Rope.Cat[outName, "top.sch"], cx], renaming: pas
]];
FOR bit:
NAT
IN [0..6)
DO
tiles[bit+1] ← NEW [TilingClass.TileRowRec[1]];
tiles[bit+1][0] ←
NEW [TilingClass.TileRec ← [
type: Sisyph.
ES[
SELECT lowToHi[bit]
FROM
X => "maskX.sch", F => "maskF.sch", S => "maskS.sch", P => "maskP.sch",
ENDCASE => ERROR,
cx],
renaming: CONS [["sel", Index[selName, 5-bit]], pas]
]];
ENDLOOP;
tiles[0] ← NEW [TilingClass.TileRowRec[1]];
tiles[0][0] ←
NEW [TilingClass.TileRec ← [
type: Sisyph.ES["maskBot.sch", cx], renaming: pas
]];
cellType ← TilingClass.CreateTiling[public: public, tileArray: tiles, neighborX: TilingClass.LayoutNeighborX, neighborY: TilingClass.LayoutNeighborY, name: "Mask"];
};