TamarinUCodeImpl.mesa
Copyright © 1987 by Xerox Corporation. All rights reserved.
Last Edited by: Alan Bell October 1, 1987 8:44:55 am PDT
Krivacic September 17, 1987 12:17:36 pm PDT
DIRECTORY
CD,
CDSequencer,
Core USING [CellType],
CoreCreate,
CoreClasses,
IO,
List,
Ports,
Rope,
Sisyph USING [Context, ES],
Tam,
TerminalIO,
TamarinUtil,
TilingClass USING [CreateTiling, SchematicsNeighborX, SchematicsNeighborY,
TileArray, TileArrayRec, TileRec, TileRowRec];
TamarinUCodeImpl: CEDAR PROGRAM
IMPORTS CoreCreate, IO, List, Sisyph, Tam, TamarinUtil, TerminalIO, TilingClass, CoreClasses, Ports
EXPORTS Tam = BEGIN
LORA: TYPE = List.LORA;
uCodeOrder: LORA ← NIL;
extractUCode: BOOLTRUE;  -- Extract real UCode or use a Behavioral Proc
n: INT;
-- Constants - These should be in config file.
sMI: NAT = 120;
uCodeAddrSize: NAT = 8;
uCode: TilingClass.TileArray;
uCell: Core.CellType;
FieldType: TYPE = {latch, unlatched, both, spacer};
BitPosRef: TYPE = RECORD[bitType: FieldType, bitPos: INT];
BitPos: TYPE = REF BitPosRef;
CreateRealUCodeRom: PUBLIC PROC [tamarinCx: Sisyph.Context] RETURNS [cellType: Core.CellType] = {
Create the UCode Rom.
-- Types
RomCellType: TYPE = {A, B0, B1, C, D0000, D0001, D0010, D0011, D0100, D0101, D0110, D0111, D1000, D1001, D1010, D1011, D1100, D1101, D1110, D1111, E, F, G0, G1, H};
RowCells: TYPE = ARRAY RomCellType OF Core.CellType;
-- Vars
nMI: NAT;
wMI: NAT;
-- Cells
romTA: Core.CellType ← Sisyph.ES["RomTA.sch", tamarinCx];
romTB: Core.CellType ← Sisyph.ES["RomTB.sch", tamarinCx];
romTBl: Core.CellType ← Sisyph.ES["RomTB1.sch", tamarinCx];
romTC: Core.CellType ← Sisyph.ES["RomTC.sch", tamarinCx];
romTD: Core.CellType ← Sisyph.ES["RomTD.sch", tamarinCx];
romTE: Core.CellType ← Sisyph.ES["RomTE.sch", tamarinCx];
romTF: Core.CellType ← Sisyph.ES["RomTF.sch", tamarinCx];
romTG: Core.CellType ← Sisyph.ES["RomTG.sch", tamarinCx];
romTH: Core.CellType ← Sisyph.ES["RomTH.sch", tamarinCx];
romHA: Core.CellType ← Sisyph.ES["RomHA.sch", tamarinCx];
romHB: Core.CellType ← Sisyph.ES["RomHB.sch", tamarinCx];
romHC: Core.CellType ← Sisyph.ES["RomHC.sch", tamarinCx];
romHD: Core.CellType ← Sisyph.ES["RomHD.sch", tamarinCx];
romHE: Core.CellType ← Sisyph.ES["RomHE.sch", tamarinCx];
romHF: Core.CellType ← Sisyph.ES["RomHF.sch", tamarinCx];
romHG: Core.CellType ← Sisyph.ES["RomHG.sch", tamarinCx];
romHH: Core.CellType ← Sisyph.ES["RomHH.sch", tamarinCx];
romUA: Core.CellType ← Sisyph.ES["RomUA.sch", tamarinCx];
romUB0: Core.CellType ← Sisyph.ES["RomUB0.sch", tamarinCx];
romUB1: Core.CellType ← Sisyph.ES["RomUB1.sch", tamarinCx];
romUC: Core.CellType ← Sisyph.ES["RomUC.sch", tamarinCx];
romUD0000: Core.CellType ← Sisyph.ES["RomU0000.sch", tamarinCx];
romUD0001: Core.CellType ← Sisyph.ES["RomU0001.sch", tamarinCx];
romUD0010: Core.CellType ← Sisyph.ES["RomU0010.sch", tamarinCx];
romUD0011: Core.CellType ← Sisyph.ES["RomU0011.sch", tamarinCx];
romUD0100: Core.CellType ← Sisyph.ES["RomU0100.sch", tamarinCx];
romUD0101: Core.CellType ← Sisyph.ES["RomU0101.sch", tamarinCx];
romUD0110: Core.CellType ← Sisyph.ES["RomU0110.sch", tamarinCx];
romUD0111: Core.CellType ← Sisyph.ES["RomU0111.sch", tamarinCx];
romUD1000: Core.CellType ← Sisyph.ES["RomU1000.sch", tamarinCx];
romUD1001: Core.CellType ← Sisyph.ES["RomU1001.sch", tamarinCx];
romUD1010: Core.CellType ← Sisyph.ES["RomU1010.sch", tamarinCx];
romUD1011: Core.CellType ← Sisyph.ES["RomU1011.sch", tamarinCx];
romUD1100: Core.CellType ← Sisyph.ES["RomU1100.sch", tamarinCx];
romUD1101: Core.CellType ← Sisyph.ES["RomU1101.sch", tamarinCx];
romUD1110: Core.CellType ← Sisyph.ES["RomU1110.sch", tamarinCx];
romUD1111: Core.CellType ← Sisyph.ES["RomU1111.sch", tamarinCx];
romUE: Core.CellType ← Sisyph.ES["RomUE.sch", tamarinCx];
romUF: Core.CellType ← Sisyph.ES["RomUF.sch", tamarinCx];
romUG0: Core.CellType ← Sisyph.ES["RomUG0.sch", tamarinCx];
romUG1: Core.CellType ← Sisyph.ES["RomUG1.sch", tamarinCx];
romUH: Core.CellType ← Sisyph.ES["RomUH.sch", tamarinCx];
romDA: Core.CellType ← Sisyph.ES["RomDA.sch", tamarinCx];
romDB0: Core.CellType ← Sisyph.ES["RomDB0.sch", tamarinCx];
romDB1: Core.CellType ← Sisyph.ES["RomDB1.sch", tamarinCx];
romDC: Core.CellType ← Sisyph.ES["RomDC.sch", tamarinCx];
romDD0000: Core.CellType ← Sisyph.ES["RomD0000.sch", tamarinCx];
romDD0001: Core.CellType ← Sisyph.ES["RomD0001.sch", tamarinCx];
romDD0010: Core.CellType ← Sisyph.ES["RomD0010.sch", tamarinCx];
romDD0011: Core.CellType ← Sisyph.ES["RomD0011.sch", tamarinCx];
romDD0100: Core.CellType ← Sisyph.ES["RomD0100.sch", tamarinCx];
romDD0101: Core.CellType ← Sisyph.ES["RomD0101.sch", tamarinCx];
romDD0110: Core.CellType ← Sisyph.ES["RomD0110.sch", tamarinCx];
romDD0111: Core.CellType ← Sisyph.ES["RomD0111.sch", tamarinCx];
romDD1000: Core.CellType ← Sisyph.ES["RomD1000.sch", tamarinCx];
romDD1001: Core.CellType ← Sisyph.ES["RomD1001.sch", tamarinCx];
romDD1010: Core.CellType ← Sisyph.ES["RomD1010.sch", tamarinCx];
romDD1011: Core.CellType ← Sisyph.ES["RomD1011.sch", tamarinCx];
romDD1100: Core.CellType ← Sisyph.ES["RomD1100.sch", tamarinCx];
romDD1101: Core.CellType ← Sisyph.ES["RomD1101.sch", tamarinCx];
romDD1110: Core.CellType ← Sisyph.ES["RomD1110.sch", tamarinCx];
romDD1111: Core.CellType ← Sisyph.ES["RomD1111.sch", tamarinCx];
romDE: Core.CellType ← Sisyph.ES["RomDE.sch", tamarinCx];
romDF: Core.CellType ← Sisyph.ES["RomDF.sch", tamarinCx];
romDG0: Core.CellType ← Sisyph.ES["RomDG0.sch", tamarinCx];
romDG1: Core.CellType ← Sisyph.ES["RomDG1.sch", tamarinCx];
romDH: Core.CellType ← Sisyph.ES["RomDH.sch", tamarinCx];
romBA: Core.CellType ← Sisyph.ES["RomBA.sch", tamarinCx];
romBB: Core.CellType ← Sisyph.ES["RomBB.sch", tamarinCx];
romBC: Core.CellType ← Sisyph.ES["RomBC.sch", tamarinCx];
romBD: Core.CellType ← Sisyph.ES["RomBD.sch", tamarinCx];
romBE: Core.CellType ← Sisyph.ES["RomBE.sch", tamarinCx];
romBF: Core.CellType ← Sisyph.ES["RomBF.sch", tamarinCx];
romBG: Core.CellType ← Sisyph.ES["RomBG.sch", tamarinCx];
romBH: Core.CellType ← Sisyph.ES["RomBH.sch", tamarinCx];
tRowCells: RowCells ← [romTA, romTB, romTBl, romTC, romTD, romTD, romTD, romTD, romTD, romTD, romTD, romTD, romTD, romTD, romTD, romTD, romTD, romTD, romTD, romTD, romTE, romTF, romTG, romTG, romTH];
hRowCells: RowCells ← [romHA, romHB, romHB, romHC, romHD, romHD, romHD, romHD, romHD, romHD, romHD, romHD, romHD, romHD, romHD, romHD, romHD, romHD, romHD, romHD, romHE, romHF, romHG, romHG, romHH];
uRowCells: RowCells ← [romUA, romUB0, romUB1, romUC, romUD0000, romUD0001, romUD0010, romUD0011, romUD0100, romUD0101, romUD0110, romUD0111, romUD1000, romUD1001, romUD1010, romUD1011, romUD1100, romUD1101, romUD1110, romUD1111, romUE, romUF, romUG0, romUG1, romUH];
dRowCells: RowCells ← [romDA, romDB0, romDB1, romDC, romDD0000, romDD0001, romDD0010, romDD0011, romDD0100, romDD0101, romDD0110, romDD0111, romDD1000, romDD1001, romDD1010, romDD1011, romDD1100, romDD1101, romDD1110, romDD1111, romDE, romDF, romDG0, romDG1, romDH];
bRowCells: RowCells ← [romBA, romBB, romBB, romBC, romBD, romBD, romBD, romBD, romBD, romBD, romBD, romBD, romBD, romBD, romBD, romBD, romBD, romBD, romBD, romBD,romBE, romBF, romBG, romBG, romBH];
romCellSelect: ARRAY [0..15] OF RomCellType ← [D0000, D0001, D0010, D0011, D0100, D0101, D0110, D0111, D1000, D1001, D1010, D1011, D1100, D1101, D1110, D1111];
-- Vars
tileArray: TilingClass.TileArray;
-- Wire Sequences
aAddrWire: CoreCreate.Wire ← CoreCreate.Seq["aAddr", uCodeAddrSize];
bAddrWire: CoreCreate.Wire ← CoreCreate.Seq["bAddr", uCodeAddrSize];
miWire: CoreCreate.Wire ← CoreCreate.Seq["MI", sMI];
milWire: CoreCreate.Wire ← CoreCreate.Seq["MIL", sMI];
opcodeWire: CoreCreate.Wire ← CoreCreate.Seq["newOpcode", uCodeAddrSize];
precondWire: CoreCreate.Wire ← CoreCreate.Seq["Precond", 3];
nUCodeMuxSel: CoreCreate.Wire ← CoreCreate.Seq["nUCodeMuxSel", 4];
MakeUCodeRow: PROC [type: NAT, row: NAT, aAddr, bAddr: NAT, deMI, doMI, ueMI, uoMI: Rope.ROPE, order: LORA] RETURNS [] = {
BoolToInt: PROC [val: BOOLEAN, index: NAT] RETURNS [i: NAT] = {
i ← (IF val THEN index ELSE 0);
};
cells: RowCells ← (SELECT type FROM
0 => tRowCells,
1 => hRowCells,
2 => uRowCells,
3 => dRowCells,
4 => bRowCells,  
ENDCASE => ERROR);
tileArray[row] ← NEW[TilingClass.TileRowRec[wMI+uCodeAddrSize+uCodeAddrSize+2]];
tileArray[row][0] ← NEW[TilingClass.TileRec ← [
type: cells[A],
renaming: LIST[["Vdd", "Vdd"], ["Gnd", "Gnd"]]
]];
IF type=0
THEN FOR i: NAT IN [0..uCodeAddrSize-1) DO
tileArray[row][1+i] ← NEW[TilingClass.TileRec ← [
type: (IF i<5 THEN cells[B0] ELSE cells[B1]),
flatten: FALSE, 
renaming: (IF i<5 THEN LIST[["AAddr", aAddrWire[i]], ["Opcode", opcodeWire[i]], ["Vdd", "Vdd"], ["Gnd", "Gnd"]]
ELSE LIST[["AAddr", aAddrWire[i]], ["Opcode", opcodeWire[i]], ["PreCondAddr", precondWire[i-5]], ["Vdd", "Vdd"], ["Gnd", "Gnd"]])
]];
ENDLOOP
ELSE FOR i: NAT IN [0..uCodeAddrSize-1) DO
tileArray[row][1+i] ← NEW[TilingClass.TileRec ← [
type: (IF TamarinUtil.BitOnP[aAddr, uCodeAddrSize-i-1] THEN cells[B0] ELSE cells[B1]),
renaming: (SELECT type FROM
1 => NIL,
2,3 => LIST[["Gnd", "Gnd"]],
4 => LIST[["Vdd", "Vdd"], ["Gnd", "Gnd"]],
ENDCASE => ERROR)
]];
ENDLOOP;
tileArray[row][uCodeAddrSize] ← NEW[TilingClass.TileRec ← [
type: cells[C],
renaming: (SELECT type FROM
0 => LIST[["AAddr", aAddrWire[uCodeAddrSize-1]], ["Opcode", opcodeWire[uCodeAddrSize-1]], ["PreCondAddr", precondWire[2]], ["nClock", "nClock"], ["nUCodeMuxSel", nUCodeMuxSel], ["Vdd", "Vdd"], ["Gnd", "Gnd"]],
1,2,3,4 => LIST[["Vdd", "Vdd"], ["Gnd", "Gnd"]],
ENDCASE => ERROR)
]];
FOR i: INT IN [0..wMI) DO
bitPos: BitPos ← NARROW[List.NthElement[order, i+1]];
ue: BOOLEAN ← TamarinUtil.RopeBitOnP[ueMI, bitPos.bitPos];
uo: BOOLEAN ← TamarinUtil.RopeBitOnP[uoMI, bitPos.bitPos];
de: BOOLEAN ← TamarinUtil.RopeBitOnP[deMI, bitPos.bitPos];
do: BOOLEAN ← TamarinUtil.RopeBitOnP[doMI, bitPos.bitPos];
IF bitPos.bitType=spacer
THEN
tileArray[row][1+uCodeAddrSize+i] ← NEW[TilingClass.TileRec ← [
type: cells[E],
flatten: FALSE,
renaming: (SELECT type FROM
1,2,3 => LIST[["Gnd", "Gnd"]],
0,4=> LIST[["Vdd", "Vdd"], ["Gnd", "Gnd"]],
ENDCASE => ERROR) ]]
ELSE
tileArray[row][1+uCodeAddrSize+i] ← NEW[TilingClass.TileRec ← [
type:
cells[romCellSelect[
BoolToInt[~ue, 8] + BoolToInt[~de, 4] + BoolToInt[~uo, 2] + BoolToInt[~do, 1]
]],
renaming: (SELECT type FROM
0 => (IF bitPos.bitType=latch THEN
LIST[["MIL", miWire[bitPos.bitPos]], ["Vdd", "Vdd"], ["Gnd", "Gnd"]]
ELSE LIST[["MI", miWire[bitPos.bitPos]], ["Vdd", "Vdd"], ["Gnd", "Gnd"]]),
1,2,3 => LIST[["Gnd", "Gnd"]],
4 => LIST[["Vdd", "Vdd"], ["Gnd", "Gnd"]],
ENDCASE => ERROR) ]];
ENDLOOP;
tileArray[row][1+uCodeAddrSize+wMI] ← NEW[TilingClass.TileRec ← [
type: cells[F],
renaming: (SELECT type FROM
0=> LIST[["AddrIn", bAddrWire[uCodeAddrSize-1]], ["UCodeSel", "UCodeSel"], ["nStall", "nStall"], ["Vdd", "Vdd"], ["Gnd", "Gnd"]],
1,2,3,4 => LIST[["Vdd", "Vdd"], ["Gnd", "Gnd"]],
ENDCASE => ERROR)
]];
FOR i: NAT IN [0..uCodeAddrSize-1) DO
tileArray[row][i+2+uCodeAddrSize+wMI] ← NEW[TilingClass.TileRec ← [
type: (IF TamarinUtil.BitOnP[bAddr, uCodeAddrSize-i-1] THEN cells[G0] ELSE cells[G1]),
renaming: (SELECT type FROM
0=> LIST[["AddrIn", bAddrWire[i]], ["Vdd", "Vdd"], ["Gnd", "Gnd"]],
1 => NIL,
2,3 => LIST[["Gnd", "Gnd"]],
4 => LIST[["Vdd", "Vdd"], ["Gnd", "Gnd"]],
ENDCASE => ERROR)
]];
ENDLOOP;
tileArray[row][1+uCodeAddrSize+wMI+uCodeAddrSize] ← NEW[TilingClass.TileRec ← [
type: cells[H],
renaming: LIST[["Vdd", "Vdd"], ["Gnd", "Gnd"]]
]];
};
uCodeContents: LORA ← TamarinUtil.GetUCodeContents[];
line: NAT ← 0;
tapFreq: NAT ← 4;
dUC: Rope.ROPENARROW[List.NthElement[uCodeContents, 1], TamarinUtil.UCodeWord].beMI;
nMI ← List.Length[uCodeContents];
wMI ← List.Length[uCodeOrder];
tileArray ← NEW[TilingClass.TileArrayRec[nMI+2+nMI/2/tapFreq]];

MakeUCodeRow[4, line, 0, 0, dUC, dUC, dUC, dUC, uCodeOrder];
line← 1;
FOR row: NAT IN [0..nMI/2) DO
up: TamarinUtil.UCodeWord ← NARROW[List.NthElement[uCodeContents, row*2+2]];
dn: TamarinUtil.UCodeWord ← NARROW[List.NthElement[uCodeContents, row*2+1]];
IF row MOD tapFreq = tapFreq/2 THEN {
MakeUCodeRow[1, line, 0, 0, dUC, dUC, dUC, dUC, uCodeOrder];
line ← line + 1 };
MakeUCodeRow[3, line, dn.aAddr, dn.bAddr, dn.beMI, dn.boMI, up.beMI, up.boMI, uCodeOrder];
MakeUCodeRow[2, line+1, up.aAddr, up.bAddr, dn.aeMI, dn.aoMI, up.aeMI, up.aoMI, uCodeOrder];
line ← line + 2;
ENDLOOP;
MakeUCodeRow[0, line, 0, 0, dUC, dUC, dUC, dUC, uCodeOrder];
TerminalIO.PutF["Creating UCodeRom: %g x %g", IO.int[nMI], IO.int[wMI]];
cellType ← TilingClass.CreateTiling[
name: "UCodeRom",
public: CoreCreate.WireList[LIST["Vdd", "Gnd", "nClock", "UCodeSel", "nStall", aAddrWire, bAddrWire, miWire, opcodeWire, precondWire, nUCodeMuxSel]],
public: CoreCreate.WireList[LIST["Vdd", "Gnd"]],
tileArray: tileArray,
neighborX: TilingClass.SchematicsNeighborX,
neighborY: TilingClass.SchematicsNeighborY
];
uCode ← tileArray;
uCell ← cellType;
};
CreateUCodeRom: PUBLIC PROC [tamarinCx: Sisyph.Context] RETURNS [cellType: Core.CellType] = {
IF extractUCode THEN cellType ← CreateRealUCodeRom[tamarinCx]
ELSE {
cellType 𡤌oreClasses.CreateUnspecified[CoreCreate.WireList[LIST["Vdd", "Gnd", "nClock", "UCodeSel", "nStall", CoreCreate.Seq["Precond", 3], CoreCreate.Seq["aAddr", 8], CoreCreate.Seq["bAddr", 8], CoreCreate.Seq["newOpcode", 8], CoreCreate.Seq["nUCodeMuxSel", 4], CoreCreate.Seq["MI", 120], CoreCreate.Seq["MIL", 120]], "UCodeRomPublics"], "UCodeRom"];
[] ← Ports.InitPorts[cellType, l, none, "Vdd", "Gnd", "nClock", "UCodeSel", "nStall"];
[] ← Ports.InitPorts[cellType, ls, none, "Precond", "aAddr", "bAddr", "newOpcode", "nUCodeMuxSel"];
[] ← Ports.InitPorts[cellType, ls, drive, "MI", "MIL"];
};
};
AddUcodeField: PROC [name: ATOM, size: ATOM, fieldType: FieldType] = {
FOR i: INT IN [Tam.C[name]..Tam.C[name]+Tam.C[size]) DO
uCodeOrder ← CONS[NEW[BitPosRef← [fieldType, i]] , uCodeOrder];
ENDLOOP;
};
FOR i: INT ← sMI-1, i-1 WHILE i >= 0 DO
IF i MOD 8 = 4 THEN uCodeOrder ← CONS[NEW[INT ← -1] , uCodeOrder];
uCodeOrder ← CONS[NEW[INT ← i] , uCodeOrder];
ENDLOOP;
AddUcodeField[$pAltCxt, $sAltCxt, unlatched];   -- unlatched
AddUcodeField[$pByteAddr, $sByteAddr, latch];
AddUcodeField[$pDone, $sDone, latch];
AddUcodeField[$pDpCCode, $sDpCCode, latch];
AddUcodeField[$pDswap, $sDswap, latch];
AddUcodeField[$pEUop, $sEUop, latch];
AddUcodeField[$pEuCCode, $sEuCCode, latch];
AddUcodeField[$pForceDone, $sForceDone, latch];
AddUcodeField[$pInvertCCode, $sInvertCCode, latch];
AddUcodeField[$pK, $sK, unlatched];    -- unlatched
AddUcodeField[$pK2, $sK2, latch];
AddUcodeField[$pLatchFetchPc, $sLatchFetchPc, latch];
AddUcodeField[$pLatchPc, $sLatchPc, latch];
AddUcodeField[$pMemCCode, $sMemCCode, latch];
AddUcodeField[$pMemLatchSrc, $sMemLatchSrc, latch];
AddUcodeField[$pMemOffset, $sMemOffset, latch];
AddUcodeField[$pMemOp, $sMemOp, latch];
AddUcodeField[$pMisc, $sMisc, latch];
AddUcodeField[$pMuxBus, $sMuxBus, latch];
AddUcodeField[$pMuxCCode, $sMuxCCode, latch];
AddUcodeField[$pNewArg, $sNewArg, latch];
AddUcodeField[$pNewArg2, $sNewArg2, latch];
AddUcodeField[$pNewBotCxt, $sNewBotCxt, latch];
AddUcodeField[$pNewTopCxt, $sNewTopCxt, latch];
AddUcodeField[$pNewTos, $sNewTos, latch];
AddUcodeField[$pNextInstA, $sNextInstA, latch];
AddUcodeField[$pNextInstB, $sNextInstB, latch];
AddUcodeField[$pOpLength, $sOpLength, unlatched];  -- unlatched
AddUcodeField[$pOpMask, $sOpMask, latch];
AddUcodeField[$pPcSrc, $sPcSrc, latch];
AddUcodeField[$pPhysAddrSrc, $sPhysAddrSrc, latch];
AddUcodeField[$pRCxt, $sRCxt, unlatched];   -- unlatched
AddUcodeField[$pRD1addr, $sRD1addr, latch];
AddUcodeField[$pRD2addr, $sRD2addr, latch];
AddUcodeField[$pRaddr, $sRaddr, unlatched];   -- unlatched
AddUcodeField[$pTag, $sTag, latch];
AddUcodeField[$pW2addr, $sW2addr, latch];
AddUcodeField[$pWCxt, $sWCxt, latch];
AddUcodeField[$pWaddr, $sWaddr, latch];
AddUcodeField[$pWriteF, $sWriteF, latch];
AddUcodeField[$pWriteOctal, $sWriteOctal, latch];
AddUcodeField[$pWriteT, $sWriteT, latch];
AddUcodeField[$pWriteTags, $sWriteTags, latch];
AddUcodeField[$pWriteData, $sWriteData, latch];
n 𡤀
FOR i: LORA ← uCodeOrder, i.rest UNTIL i=NIL DO
IF n MOD 8 = 4 THEN i.rest ← CONS[NEW[BitPosRef← [spacer, 0]] , i.rest];
n ← n+1;
ENDLOOP;
END.