Debugging

The quadric SDK offers functions to print the contents of tensors in OCM, qVar, and static variables, as well as EPU registers, all formatted automatically.

The debugPrint and debugOCMPrint functions are very helpful when debugging kernels in ArchSim.

Note

Calls to debugPrint and debugOCMPrint are disregarded in the FPGA or on EPU hardware, and are only valid when using ArchSim.

debugPrint

The debugPrint function can print constants, qVar(s), and registers on the EPU system.

Examples

  std::int32_t            i32  = argc;
  FixedPoint32<8>         fx8  = 52.25;
  qVar_t<std::int32_t>    qI32 = qNorth<>;
  qVar_t<FixedPoint32<8>> qFx8 = qWest<FixedPoint32<8>>;

  // Scalars, no message
  debugPrint(i32);
  debugPrint(i32, DebugPrintFmt::HEX);
  debugPrint(fx8);

  // Scalars, with message
  debugPrint(i32, "i32");
  debugPrint(i32, DebugPrintFmt::HEX, "i32h");
  debugPrint(fx8, "fx8");

  // Special regs, no message
  debugPrint(qWest<>);
  debugPrint(qEast<>, DebugPrintFmt::HEX);
  debugPrint(qSouth<FixedPoint32<8>>);

  // Special regs, with message
  debugPrint(qWest<>, "qWest<>");
  debugPrint(qEast<>, DebugPrintFmt::HEX, "qEast<>h");
  debugPrint(qSouth<FixedPoint32<8>>, "qSouth<FX8>");

  // qVar, no message
  debugPrint(qI32);
  debugPrint(qI32, DebugPrintFmt::HEX);
  debugPrint(qFx8);

  // qVar, with message
  debugPrint(qI32, "qI32");
  debugPrint(qI32, DebugPrintFmt::HEX, "qI32h");
  debugPrint(qFx8, "qFx8");

We can also use debugPrint to examine the configuration of our EPU. For example:

debugPrint(qCol<>);  //Output is shown below
[-4]  [-3]  [-2]  [-1]   | [0]  [1]  [2]  [3]  [4]  [5]  [6]  [7]   | [8]  [9]  [10]  [11]
[-4]  [-3]  [-2]  [-1]   | [0]  [1]  [2]  [3]  [4]  [5]  [6]  [7]   | [8]  [9]  [10]  [11]
[-4]  [-3]  [-2]  [-1]   | [0]  [1]  [2]  [3]  [4]  [5]  [6]  [7]   | [8]  [9]  [10]  [11]
[-4]  [-3]  [-2]  [-1]   | [0]  [1]  [2]  [3]  [4]  [5]  [6]  [7]   | [8]  [9]  [10]  [11]
------------------------------------------------------------------------------------------------
[-4]  [-3]  [-2]  [-1]   | [0]  [1]  [2]  [3]  [4]  [5]  [6]  [7]   | [8]  [9]  [10]  [11]
[-4]  [-3]  [-2]  [-1]   | [0]  [1]  [2]  [3]  [4]  [5]  [6]  [7]   | [8]  [9]  [10]  [11]
[-4]  [-3]  [-2]  [-1]   | [0]  [1]  [2]  [3]  [4]  [5]  [6]  [7]   | [8]  [9]  [10]  [11]
[-4]  [-3]  [-2]  [-1]   | [0]  [1]  [2]  [3]  [4]  [5]  [6]  [7]   | [8]  [9]  [10]  [11]
[-4]  [-3]  [-2]  [-1]   | [0]  [1]  [2]  [3]  [4]  [5]  [6]  [7]   | [8]  [9]  [10]  [11]
[-4]  [-3]  [-2]  [-1]   | [0]  [1]  [2]  [3]  [4]  [5]  [6]  [7]   | [8]  [9]  [10]  [11]
[-4]  [-3]  [-2]  [-1]   | [0]  [1]  [2]  [3]  [4]  [5]  [6]  [7]   | [8]  [9]  [10]  [11]
[-4]  [-3]  [-2]  [-1]   | [0]  [1]  [2]  [3]  [4]  [5]  [6]  [7]   | [8]  [9]  [10]  [11]
------------------------------------------------------------------------------------------------
[-4]  [-3]  [-2]  [-1]   | [0]  [1]  [2]  [3]  [4]  [5]  [6]  [7]   | [8]  [9]  [10]  [11]
[-4]  [-3]  [-2]  [-1]   | [0]  [1]  [2]  [3]  [4]  [5]  [6]  [7]   | [8]  [9]  [10]  [11]
[-4]  [-3]  [-2]  [-1]   | [0]  [1]  [2]  [3]  [4]  [5]  [6]  [7]   | [8]  [9]  [10]  [11]
[-4]  [-3]  [-2]  [-1]   | [0]  [1]  [2]  [3]  [4]  [5]  [6]  [7]   | [8]  [9]  [10]  [11]
debugPrint(qRow<>);  //Output is shown below
[-4]  [-4]  [-4]  [-4]   | [-4]  [-4]  [-4]  [-4]  [-4]  [-4]  [-4]  [-4]   | [-4]  [-4]  [-4]  [-4]
[-3]  [-3]  [-3]  [-3]   | [-3]  [-3]  [-3]  [-3]  [-3]  [-3]  [-3]  [-3]   | [-3]  [-3]  [-3]  [-3]
[-2]  [-2]  [-2]  [-2]   | [-2]  [-2]  [-2]  [-2]  [-2]  [-2]  [-2]  [-2]   | [-2]  [-2]  [-2]  [-2]
[-1]  [-1]  [-1]  [-1]   | [-1]  [-1]  [-1]  [-1]  [-1]  [-1]  [-1]  [-1]   | [-1]  [-1]  [-1]  [-1]
------------------------------------------------------------------------------------------------
[ 0]  [ 0]  [ 0]  [ 0]   | [ 0]  [ 0]  [ 0]  [ 0]  [ 0]  [ 0]  [ 0]  [ 0]   | [ 0]  [ 0]  [ 0]  [ 0]
[ 1]  [ 1]  [ 1]  [ 1]   | [ 1]  [ 1]  [ 1]  [ 1]  [ 1]  [ 1]  [ 1]  [ 1]   | [ 1]  [ 1]  [ 1]  [ 1]
[ 2]  [ 2]  [ 2]  [ 2]   | [ 2]  [ 2]  [ 2]  [ 2]  [ 2]  [ 2]  [ 2]  [ 2]   | [ 2]  [ 2]  [ 2]  [ 2]
[ 3]  [ 3]  [ 3]  [ 3]   | [ 3]  [ 3]  [ 3]  [ 3]  [ 3]  [ 3]  [ 3]  [ 3]   | [ 3]  [ 3]  [ 3]  [ 3]
[ 4]  [ 4]  [ 4]  [ 4]   | [ 4]  [ 4]  [ 4]  [ 4]  [ 4]  [ 4]  [ 4]  [ 4]   | [ 4]  [ 4]  [ 4]  [ 4]
[ 5]  [ 5]  [ 5]  [ 5]   | [ 5]  [ 5]  [ 5]  [ 5]  [ 5]  [ 5]  [ 5]  [ 5]   | [ 5]  [ 5]  [ 5]  [ 5]
[ 6]  [ 6]  [ 6]  [ 6]   | [ 6]  [ 6]  [ 6]  [ 6]  [ 6]  [ 6]  [ 6]  [ 6]   | [ 6]  [ 6]  [ 6]  [ 6]
[ 7]  [ 7]  [ 7]  [ 7]   | [ 7]  [ 7]  [ 7]  [ 7]  [ 7]  [ 7]  [ 7]  [ 7]   | [ 7]  [ 7]  [ 7]  [ 7]
------------------------------------------------------------------------------------------------
[ 8]  [ 8]  [ 8]  [ 8]   | [ 8]  [ 8]  [ 8]  [ 8]  [ 8]  [ 8]  [ 8]  [ 8]   | [ 8]  [ 8]  [ 8]  [ 8]
[ 9]  [ 9]  [ 9]  [ 9]   | [ 9]  [ 9]  [ 9]  [ 9]  [ 9]  [ 9]  [ 9]  [ 9]   | [ 9]  [ 9]  [ 9]  [ 9]
[10]  [10]  [10]  [10]   | [10]  [10]  [10]  [10]  [10]  [10]  [10]  [10]   | [10]  [10]  [10]  [10]
[11]  [11]  [11]  [11]   | [11]  [11]  [11]  [11]  [11]  [11]  [11]  [11]   | [11]  [11]  [11]  [11]

Above, the debugPrint statements display the column and row of each core in the EPU. Notably, the border cores have values below 0 or greater than 7, which makes sense as the examples above were generated by a q8, which has 8 cores per side.

debugOCMPrint

The debugOCMPrint function gives the user the ability to print out the data stored in the On Chip Memory (OCM). Usage of debugOCMPrint function mirrors the usage of the debugPrint function, although it’s used only for OcmTensor type objects.

OcmInOutShape ocmInp; // Already allocated and populated previously...
debugOCMPrint(ocmInp)

Output of a call to debugOCMPrint will look look like this:

ocm[0x00000000]= 0x00000000 0x00000001 0x00000002 0x00000003 0x00000004 0x00000005 0x00000006 0x00000007
ocm[0x00000001]= 0x00000008 0x00000009 0x0000000a 0x0000000b 0x0000000c 0x0000000d 0x0000000e 0x0000000f
ocm[0x00000002]= 0x00000010 0x00000011 0x00000012 0x00000013 0x00000014 0x00000015 0x00000016 0x00000017
ocm[0x00000003]= 0x00000018 0x00000019 0x0000001a 0x0000001b 0x0000001c 0x0000001d 0x0000001e 0x0000001f
ocm[0x00000004]= 0x00000020 0x00000021 0x00000022 0x00000023 0x00000024 0x00000025 0x00000026 0x00000027
ocm[0x00000005]= 0x00000028 0x00000029 0x0000002a 0x0000002b 0x0000002c 0x0000002d 0x0000002e 0x0000002f
ocm[0x00000006]= 0x00000030 0x00000031 0x00000032 0x00000033 0x00000034 0x00000035 0x00000036 0x00000037
ocm[0x00000007]= 0x00000038 0x00000039 0x0000003a 0x0000003b 0x0000003c 0x0000003d 0x0000003e 0x0000003f
ocm[0x00000008]= 0x00000800 0x00000801 0x00000802 0x00000803 0x00000804 0x00000805 0x00000806 0x00000807

Each of the above lines represents a line of OCM memory (on a q8, which the example above represents, 1 OCM line is 32 bytes). The data is represented with the least significant byte at the lowest address (little endian).