<> <> <> <> DIRECTORY BitOps, Convert, Core, CoreCreate, CoreOps, FS, IO, Ports, Rope; Emit74LS163Vectors: CEDAR PROGRAM IMPORTS BitOps, Convert, CoreCreate, CoreOps, FS, IO, Ports, Rope = BEGIN Nibble: TYPE = [0..16); nClear: NAT = 0; Clock: NAT = 1; DataIn: NAT = 2; --4 bits EnableP: NAT = 3; Gnd: NAT = 4; nLoad: NAT = 5; EnableT: NAT = 6; DataOut: NAT = 7; --4 bits RippleCarryOut: NAT = 8; Vcc: NAT = 9; width: NAT = 4; thisTest: Rope.ROPE = "74LS163 Tester"; Init: PROC = { file: IO.STREAM _ FS.StreamOpen["Vectors74LS163.tioga", $create]; port: Ports.Port; ct: Core.CellType _ CoreCreate.Cell[ name: "74LS163", public: CoreCreate.WireList[LIST[ "nClear", "Clock", CoreCreate.Seq["DataIn", width], "EnableP", "Gnd", "nLoad", "EnableT", CoreCreate.Seq["DataOut", width], "RippleCarryOut", "Vcc"]], onlyInternal: NIL, instances: NIL ]; [] _ Ports.InitPort[ct.public[DataIn], c]; [] _ Ports.InitPort[ct.public[DataOut], c]; Ports.InitTesterDrive[ct.public[nClear], force]; Ports.InitTesterDrive[ct.public[Clock], force]; Ports.InitTesterDrive[ct.public[DataIn], force]; Ports.InitTesterDrive[ct.public[EnableP], force]; Ports.InitTesterDrive[ct.public[nLoad], force]; Ports.InitTesterDrive[ct.public[EnableT], force]; Ports.InitTesterDrive[ct.public[DataOut], none]; Ports.InitTesterDrive[ct.public[RippleCarryOut], none]; port _ Ports.CreatePort[ct, TRUE]; WritePortNamesVertically[file, ct.public, port]; DoTest[ct, port, file]; IO.Close[file]; }; DoTest: PROC [cellType: Core.CellType, p: Ports.Port, file: IO.STREAM] = { count: Nibble _ 0; temp: Nibble _ 0; cycleCount: CARD _ 0; targetCycle: CARD = 1; Cycle: PROC = { t: Nibble _ p[DataOut].c; p[DataOut].c _ temp; p[RippleCarryOut].b _ temp=15; temp _ t; WritePortData[file, p, cycleCount=targetCycle]; cycleCount _ cycleCount + 1; }; InitState: PROC ~ { p[nClear].b _ FALSE; p[Clock].b _ TRUE; --fire clock pulse every cycle p[DataIn].c _ 0; p[EnableP].b _ TRUE; p[nLoad].b _ TRUE; p[EnableT].b _ TRUE; p[DataOut].d _ none; p[RippleCarryOut].d _ none; p[DataOut].c _ 0; count _ 0; Cycle[]; p[DataOut].d _ expect; p[RippleCarryOut].d _ expect; }; Clear: PROC ~ { p[nClear].b _ FALSE; p[DataOut].c _ 0; count _ 0; p[RippleCarryOut].b _ FALSE; Cycle[]; p[nClear].b _ TRUE; }; Load: PROC [value: Nibble] ~ { p[nLoad].b _ FALSE; p[DataIn].c _ value; p[DataOut].c _ value; count _ value; p[RippleCarryOut].b _ count=15; Cycle[]; p[nLoad].b _ TRUE; }; IncCount: PROC ~ { count _ IF count=15 THEN 0 ELSE count+1; }; Count: PROC ~ { IncCount[]; p[DataOut].c _ count; p[RippleCarryOut].b _ count=15; Cycle[]; }; InitState[]; Clear[]; THROUGH [0..16) DO Count[]; ENDLOOP; Load[8]; Load[4]; Load[2]; Load[1]; Load[0]; }; WritePortNamesVertically: PROC [stream: IO.STREAM, public: Core.Wire, port: Ports.Port] = { EachWirePortPair: Ports.EachWirePortPairProc = { IF port.levelType#composite THEN { size: INT _ SELECT port.levelType FROM l, b => 1, ls => port.ls.size, bs => port.bs.size, c => 16 - port.fieldStart, lc => 32 - port.fieldStart, q => ERROR, -- not yet implemented ENDCASE => ERROR; size _ (size+3)/4; names _ CONS[[CoreOps.GetFullWireName[public, wire], size], names]; subElements _ FALSE; }; }; NameWidth: TYPE = RECORD [name: Rope.ROPE, width: INT]; names: LIST OF NameWidth _ NIL; reversedNames: LIST OF NameWidth _ NIL; maxLength: INT _ 0; [] _ Ports.VisitBinding[public, port, EachWirePortPair]; FOR nl: LIST OF NameWidth _ names, nl.rest UNTIL nl=NIL DO maxLength _ MAX[maxLength, Rope.Length[nl.first.name]]; reversedNames _ CONS[nl.first, reversedNames]; ENDLOOP; IO.PutF[stream, "\nColumnNames\n"]; FOR charIndex: INT IN [0..maxLength) DO IO.PutF[stream, " "]; FOR nl: LIST OF NameWidth _ reversedNames, nl.rest UNTIL nl=NIL DO name: Rope.ROPE _ nl.first.name; offset: INT _ maxLength-Rope.Length[name]; IO.PutF[stream, "%g", IO.char[IF charIndex >= offset THEN Rope.Fetch[name, charIndex-offset] ELSE ' ]]; THROUGH [0..(6*nl.first.width)-1) DO IO.PutChar[stream, ' ]; ENDLOOP; ENDLOOP; IO.PutF[stream, "\n"]; ENDLOOP; IO.PutF[stream, "Vectors"]; }; WritePortData: PROC [stream: IO.STREAM, p: Ports.Port, targetVector: BOOL] = { RecurseWritePortData: PROC [p: Ports.Port] = { IF p.levelType=composite THEN FOR i: NAT IN [0..p.size) DO RecurseWritePortData[p[i]]; ENDLOOP ELSE { WritePaddedCardinal: PROC [c: LONG CARDINAL, size: INT] = { cAsRope: Rope.ROPE _ Convert.RopeFromCard[c, 16, FALSE]; size _ (size+3)/4; FOR i: INT IN [0..size-Rope.Length[cAsRope]) DO IO.PutChar[stream, '0]; ENDLOOP; IO.PutRope[stream, cAsRope]; }; WriteLevel: PROC [l: Ports.Level] = { WriteBool[l=H]; }; WriteBool: PROC [b: BOOL] = { IO.PutRope[stream, IF b THEN "1" ELSE "0"]; }; inhibit: BitOps.BitDWord _ BitOps.BitDWordZero; mask: BitOps.BitDWord _ BitOps.BitDWordZero; size: INT _ 0; IO.PutRope[stream, " "]; SELECT p.levelType FROM l => {WriteLevel[p.l]; size _ 1}; ls => { size _ p.ls.size; FOR i: NAT IN [0..p.ls.size) DO WriteLevel[p.ls[i]]; ENDLOOP; }; b => {WriteBool[p.b]; size _ 1}; bs => { size _ p.bs.size; FOR i: NAT IN [0..p.bs.size) DO WriteBool[p.bs[i]]; ENDLOOP; }; c => {size _ 16 - p.fieldStart; WritePaddedCardinal[p.c, size]}; lc => {size _ 32 - p.fieldStart; WritePaddedCardinal[p.lc, size]}; q => ERROR; -- not yet implemented ENDCASE => ERROR; IO.PutRope[stream, " "]; SELECT p.driveType FROM aggregate => SELECT p.d FROM none => {mask _ BitOps.doubleMasks[size]; inhibit _ BitOps.doubleMasks[size]}; force => {mask _ BitOps.doubleMasks[size]; inhibit _ BitOps.BitDWordZero}; expect => {mask _ BitOps.BitDWordZero; inhibit _ BitOps.doubleMasks[size]}; ENDCASE => ERROR; separate => ERROR; ENDCASE => ERROR; WritePaddedCardinal[inhibit, size]; IO.PutRope[stream, " "]; WritePaddedCardinal[mask, size]; }; }; IO.PutF[stream, "\n"]; IO.PutRope[stream, IF targetVector THEN "*" ELSE " "]; RecurseWritePortData[p]; }; Init[]; END.