// http://neil.franklin.ch/Projects/PDP-10/pdp10.java
//   - PDP-10 clone microprocessor, main (and presently only) source file
// author Neil Franklin, last modification 2001.12.29


// ------ prerequisites section

// to really understand this code you should
//   have an understanding of the basics of
//     how a computer/processor executes machine code
//     designing logic circuits, such as with [74|74LS|74F]xx(x) chips
//     basics of how programmable logic works, particularly FPGAs
//   have read the specifics from the
//     PDP-10 reference manual http://www.36bit.org/dec/manual/ad-h391a-t1.pdf
//     Xilinx Virtex data sheet http://www.xilinx.com/partinfo/ds003.pdf
//     Xilinx JBits docs (with the software, to get both mail jbits@xilinx.com)


// ------ program status section

// finished implemented are so far:
//   LUT logic and place-and-routing of
//   data path and control circuits and state machine for:
// temporary memory (32 words 00..1F) and its address and mux
//   system to load memory with test programs and data
// program counter PC and its incrementer its load mux
// instruction register IR and instruction loading, modifying IR.X, .I and .MA
//   with central instruction execution finite state machine (FSM)
// memory address MA register and 0,,E calculation, consuming IR.X and IR.I
// arithmetic register AR for temporary holding C(E) or C(AC) input parameters
// input parameter selection mux for AR (C(E) or C(AC)) vs MA (0,,E)
// memory data write mux with one port for each of 8 instruction groups output
// 100ffffmm boolean logic instruction unit data path and mode execution FSM
// 011tttmmm arithmetic testing instruction unit data path and mode exec FSM

// working on:
// see http://neil.franklin.ch/Projects/PDP-10/Logfile


// ------ Java import section

import java.lang.*;
import java.io.*;
import java.util.*;
import java.text.*;

import com.xilinx.JBits.Virtex.Bitstream;
import com.xilinx.JBits.Virtex.JBits;
import com.xilinx.JBits.Virtex.Devices;
import com.xilinx.JBits.Virtex.ConfigurationException;

import com.xilinx.JBits.Virtex.Bits.LUT;
import com.xilinx.JBits.Virtex.Bits.S0Control;
import com.xilinx.JBits.Virtex.Bits.S1Control;
import com.xilinx.JBits.Virtex.Bits.S0Clk;
import com.xilinx.JBits.Virtex.Bits.S1Clk;
import com.xilinx.JBits.Virtex.Bits.S0RAM;
import com.xilinx.JBits.Virtex.Bits.S1RAM;

import com.xilinx.JBits.Virtex.Util;

import com.xilinx.JBits.CoreTemplate.Pin;
import com.xilinx.JRoute2.Virtex.JRoute;
import com.xilinx.JRoute2.Virtex.ResourceDB.CenterWires;
import com.xilinx.JRoute2.Virtex.RouteException;


// ------ Java/JBits startup/shutdown overhead section

public class pdp10 {

  public static JBits Fpga;

  public static JRoute Router;

  final public static int DeviceMaxRow = 31, DeviceMaxCol = 47;
  final public static String DeviceName = "XCV300";

  public static void main(String args[]) {

    // set up what we are going to do
    String InFileName = "/usr/local/JBits/data/Bitstream/XCV300/null300.bit";
    String OutFileName = "pdp10.bit";

    // get the device type
    int DeviceType = Devices.getDeviceType(DeviceName);
    if (DeviceType == Devices.UNKNOWN_DEVICE) {
      System.out.println("Did not recognize device type " + DeviceName);
      System.exit(-2); }
    // test if the device is supported
    if (Devices.isSupported(DeviceType) == false) {
      System.out.println("Unsupported device type. Exiting");
      System.exit(-3); }

    // initialise device storage
    Fpga = new JBits(DeviceType);

    // and make using the router possible
    Router = new JRoute(Fpga);

    // read the null bitstream
    System.out.println("reading in " + InFileName + " ...");
    try {
      Fpga.read(InFileName); }
    catch (FileNotFoundException Fe) {
      System.out.println("File " + InFileName + " not found");
      System.out.println(Fe); }
    catch (IOException Io) {
      System.out.println("Error reading the bitstream file");
      System.out.println(Io); }
    catch (ConfigurationException Ce) {
      System.out.println("Internal error detected in the Bitstream");
      System.out.println(Ce); }

    // set up font for LUT texts
    text_init_font();

    // modify the bitstream
    System.out.println("modifying bits ...");
    pdp10();

    // write the bitstream
    System.out.println("writing out " + OutFileName + " ...");
    try {
      Fpga.write(OutFileName); }
    catch (IOException Io) {
      System.out.println("Error writing the bitstream file");
      System.out.println(Io); } }


// ------ LUT setting auxilary code section

  // set LUTs faster than com.xilinx.JBits.Virtex.Expr, as no run time parsing
  // also no run time parse errors to test and trap for, and not F/G dependant

  // bit patterns for out = in<n>, for n=1..4, use Java ~&|^ to combine them
  final public static int I1 = 0xAAAA, I2 = 0xCCCC, I3 = 0xF0F0, I4 = 0xFF00;

  // just to save code size and make source more readable
  public static int[] L(int Pattern) {
    return (Util.InvertIntArray(Util.IntToIntArray(Pattern, 16))); }


// ------ LUT writting auxilary code section

  // allow putting patterns in unused LUTs that appear in chip viewers as text
  // uses LUT 16 bits displayed 0123/4567/89AB/CDEF as 4x4 pixel font

  // store pixel bit patterns
  final public static int Font[] = new int[128];

  // set patterns for the font
  public static void text_init_font() {
    Font['0'] = 0x6996; Font['1'] = 0xE464; Font['2'] = 0xF687;
    Font['3'] = 0x786F; Font['4'] = 0x4F51; Font['5'] = 0x787F;
    Font['6'] = 0x6972; Font['7'] = 0x448F; Font['8'] = 0x6966;
    Font['9'] = 0x4E96; Font['.'] = 0x4000; Font[':'] = 0x4040;
    Font['A'] = 0x9F96; Font['B'] = 0x79F7; Font['C'] = 0xE11E;
    Font['D'] = 0x7997; Font['E'] = 0xF17F; Font['F'] = 0x171F;
    Font['G'] = 0xE91E; Font['H'] = 0x99F9; Font['I'] = 0xE44E;
    Font['J'] = 0x344E; Font['K'] = 0x9759; Font['L'] = 0xF111;
    Font['M'] = 0x9BF9; Font['N'] = 0x9DB9; Font['O'] = 0x6996;
    Font['P'] = 0x1797; Font['Q'] = 0x6D96; Font['R'] = 0x9797;
    Font['S'] = 0x7C3E; Font['T'] = 0x444F; Font['U'] = 0x6999;
    Font['V'] = 0x2699; Font['W'] = 0x6BB9; Font['X'] = 0x9669;
    Font['Y'] = 0x2269; Font['Z'] = 0xF24F; Font['-'] = 0x0F00; }


// --------- actual PDP-10 implementation sections from here on

  public static void pdp10() {

    try {


// ------ debugging support

      // drive various FFs, for debugging display in BoardScope/DeviceSimulator
      // do not drive them in production systems, to reduce heat generation
      final int DebugDisp = 1;

      // prevent writing of RAM, making it ROM, so no need to track changes
      final int DebugMemROM = 0;


// ------ setting up the basics section

      // PDP-10 system constants
      // data and address bus widths
      final int DataBits = 36, AddrBits = 18;
      // PDP-10 is big endian, so data bits are numbered MSB as 0 and LSB as 35
      final int DataMSB = 0, DataLSB = DataBits-1;
      // operators console panel shows address numbered MSB as 18 and LSB as 35
      final int AddrMSB = DataMSB+(DataBits-AddrBits), AddrLSB = DataLSB;

      // place in device, all circuits are relative to this point
      //   placing starts at bottom/left point of FPGA
      //   each section reserves space by calculating new PlaceCol
      int PlaceCol = 0; int PlaceRow = 0;
      System.out.println("placing starts at " + PlaceCol + "|" + PlaceRow);

      // Xilinx south->north carry chains and my south->north row allocation
      //   results in building data path LSB->MSB
      //   36/2=18 CLB rows data, Row 0 bit 35 and 34 .. Row 17 bit 1 and 0
      // some usefull index variables for computing LUT/FF placing
      int Bit = 0, Row = 0, Col = 0;
      // for debugging output cut&paste the next line (without //)
      //System.out.println("Bit " + Bit + " Col " + Col + " Row " + Row);


// ------ revision text in chip viewer section

      // place text for revision info and for pointing out sections
      //   visible in DeviceSimulator or chip viewer
      int TextRow = DeviceMaxRow, TextCol = DeviceMaxCol;

      // get date for revision info text
      Date TextDate = new Date();
      SimpleDateFormat TextDateform = new SimpleDateFormat("yyyy.MM.dd");
      String TextDateString = TextDateform.format(TextDate);

      // generate revision info text
      String TextRev = "PDP10.BIT - NEIL FRANKLIN - " +
        TextDateString + " - " + DeviceName;

      // put revision info text into last column
      Row = TextRow; Col = TextCol;
      for (int Char = 0; Char < TextRev.length() ; Char++) {
        if (Char%2 == 0) {
          Fpga.set(Row, Col, LUT.SLICE0_G, L(Font[TextRev.charAt(Char)])); }
        else {
          Fpga.set(Row, Col, LUT.SLICE0_F, L(Font[TextRev.charAt(Char)]));
          Row--; } }


// ------ read-in test program and data section

      // read in an test program and data for testing
      // implemented as a strings of 36 0/1 chars, one for each word

      // presently 32 (octal 040) words for memory made of 32bit LUT-RAMs
      String Rin[] = new String[040];

      // bit      0         1         2         3
      //          012345678901234567890123456789012345
      // fill the 16 registers
      // data for C(MA)
      Rin[000] = "000000000000000000000000000000000000";
      Rin[001] = "111111111111111111111111111111111111";
      Rin[002] = "010101010101010101010101010101010101";
      Rin[003] = "001100110011001100110011001100110011";
      Rin[004] = "000111000111000111000111000111000111";
      Rin[005] = "000011110000111100001111000011110000";
      Rin[006] = "000001111100000111110000011111000001";
      Rin[007] = "000000111111000000111111000000111111";
      // index registers, for MA(IR.X)
      Rin[010] = "000000000000000000000000000000000001";
      Rin[011] = "000000000000000000000000000000000010";
      Rin[012] = "000000000000000000000000000000000100";
      Rin[013] = "000000000000000000000000000000001000";
      // data space, for C(AC), to process and overwrite
      Rin[014] = "001110010101010100001010111110110000";
      Rin[015] = "001001010101101101100010110111000111";
      Rin[016] = "100101011101110000000110110111100001";
      Rin[017] = "001111010101000001110110111000000110";
      // fill the rest of memory
      // program code, to execute
      //          OOOOOOOOOAAAAIXXXXYYYYYYYYYYYYYYYYYY   // PDP-10 instr format
      //          100ffffmm...........................   // bool logic sub form
      Rin[020] = "100000000110000000000000000000000001"; // SETZ    14,1
      Rin[021] = "100000101110100000010010110001100100"; // AND   I 15,226144
      Rin[022] = "100001010111000000000000000000000010"; // ANDCA M 16,2
      Rin[023] = "100001111110000000000000000000000100"; // SETM  B 14,4
      Rin[024] = "100010000110101000000000000000000010"; // ANDCM   15,2(10)
      Rin[025] = "100010101111001001000000000000000101"; // SETA  I 16,5(11)
      Rin[026] = "100100010111010000000000000000000110"; // ANDCB M 16,@7
      Rin[027] = "100100111110010000000000000000000010"; // EQV   B 14,@2
      //          011tttmmm...........................   // arith test sub form
      Rin[030] = "011000011111100000000100101001101000"; // CAI  LE 17,45150
      Rin[031] = "011001010111000000000000000000000100"; // CAM  E  16,4
      Rin[032] = "011011001110100000000000000000000011"; // SKIP L  15,3
      Rin[033] = "011101000110001010000000000000000110"; // AOS     14,6(12)
      Rin[034] = "011111111111100000000000000000000001"; // SOS  G  17,1
      Rin[035] = "011100110000100000000000000000011010"; // AOJ  N   1,32
      Rin[036] = "011110101110100000000000000000011001"; // SOJ  GE 15,31
      Rin[037] = "011010100110000000000000000000011000"; // JUMP A  14,30

      // where to start, for setting initial program counter
      int RinStartAt = 037;

// ------ memory section

      // temporary memory implementation, for testing, LUT-RAM based, 32 words
      //   real memory will later be off-chip SRAM or DRAM
      // 2 LUT-RAMs per bit, so Col 0 bit 35/33/.., Col 1 bit 34/32/..
      // 2 columns and NOT 2 slices, because only 1 TBUF readback per CLB
      //   this may change if I give up entirely on using TBUFs, that is likely

      Col = PlaceCol; Row = PlaceRow;
      // reserve space for this sections logic
      PlaceCol += 2;
      // mark this colums function with an single character of text
      Fpga.set(TextRow, Col, LUT.SLICE0_G, L(Font['M']));
      // announce what we are doing
      System.out.print("memory at " + Col + "|" + Row);

      // use array of pins for each single LUT to be addressed
      // duplicate 35..32 address definitions because actually 2*16word memory
      Pin MemAddr35F[] = new Pin[DataBits], MemAddr35G[] = new Pin[DataBits],
          MemAddr34F[] = new Pin[DataBits], MemAddr34G[] = new Pin[DataBits],
          MemAddr33F[] = new Pin[DataBits], MemAddr33G[] = new Pin[DataBits],
          MemAddr32F[] = new Pin[DataBits], MemAddr32G[] = new Pin[DataBits],
          MemAddr31[] = new Pin[DataBits], MemIn[] = new Pin[DataBits],
          MemWrEn[] = new Pin[DataBits], MemOut[] = new Pin[DataBits];

      // decrement Bit number, because PDP-10 has big endian bit numbering
      for (Bit = DataLSB; Bit >= DataMSB; Bit--) {
        int MemLUT;
        MemAddr35F[Bit] = new Pin(Pin.CLB, Row, Col, CenterWires.S0_F1);
        MemAddr35G[Bit] = new Pin(Pin.CLB, Row, Col, CenterWires.S0_G1);
        MemAddr34F[Bit] = new Pin(Pin.CLB, Row, Col, CenterWires.S0_F2);
        MemAddr34G[Bit] = new Pin(Pin.CLB, Row, Col, CenterWires.S0_G2);
        MemAddr33F[Bit] = new Pin(Pin.CLB, Row, Col, CenterWires.S0_F3);
        MemAddr33G[Bit] = new Pin(Pin.CLB, Row, Col, CenterWires.S0_G3);
        MemAddr32F[Bit] = new Pin(Pin.CLB, Row, Col, CenterWires.S0_F4);
        MemAddr32G[Bit] = new Pin(Pin.CLB, Row, Col, CenterWires.S0_G4);
        MemAddr31[Bit] = new Pin(Pin.CLB, Row, Col, CenterWires.S0_BX);
        MemIn[Bit] = new Pin(Pin.CLB, Row, Col, CenterWires.S0_BY);
        MemWrEn[Bit] = new Pin(Pin.CLB, Row, Col, CenterWires.S0_CE);
        Fpga.set(Row, Col, S0Clk.S0Clk, S0Clk.GCLK1);
        // insert memory contents into LUTs
        MemLUT = 0;
        for (int Line = 15; Line >= 0; Line--) {
          char MemBitChar = Rin[Line].charAt(Bit);
          int MemBit = (MemBitChar == '1') ? 1 : 0;
          // shift in bit from LSB of LUT
          MemLUT = MemLUT*2+MemBit; }
        Fpga.set(Row, Col, LUT.SLICE0_F, L(MemLUT));
        MemLUT = 0;
        for (int Line = 31; Line >= 16; Line--) {
          char MemBitChar = Rin[Line].charAt(Bit);
          int MemBit = (MemBitChar == '1') ? 1 : 0;
          MemLUT = MemLUT*2+MemBit; }
        Fpga.set(Row, Col, LUT.SLICE0_G, L(MemLUT));
        // configure LUT pairs to be 32bit LUT-RAMs, writable, BX selected
        Fpga.set(Row, Col, S0RAM.DUAL_MODE, S0RAM.ON);
        Fpga.set(Row, Col, S0RAM.F_LUT_RAM, S0RAM.ON);
        Fpga.set(Row, Col, S0RAM.G_LUT_RAM, S0RAM.ON);
        Fpga.set(Row, Col, S0RAM.LUT_MODE, S0RAM.OFF);
        Fpga.set(Row, Col, S0RAM.RAM_32_X_1, S0RAM.ON);
        Fpga.set(Row, Col, S0Control.X.X, S0Control.X.F5);
        // invert BX, because F5-Mux is wired 0/1=G/F
        Fpga.set(Row, Col, S0Control.BxInvert, S0Control.ON);
        if (DebugDisp == 1) {
          // XQ shows old memory data, make YQ show new MemIn data written
          Fpga.set(Row, Col, S0Control.YDin.YDin, S0Control.YDin.BY); }
        MemOut[Bit] = new Pin(Pin.CLB, Row, Col, CenterWires.S0_X);
        // zigzag placing, first bit to next Col, then Col back and to next Row
        Col = Bit%2==1 ? Col+1 : Col-1; Row = Bit%2==1 ? Row : Row+1; }

      System.out.print(".." + (Row-1));

      // comments with  // #  are for auto-generating pdp10.lf by the lf script
      // #control ClkE-Mem = ...|atestClkE-Mem|logClkE-Mem|...
      //   this will grow with other instruction groups adding subparts
      Pin MemClkEAtest = new Pin(Pin.CLB, Row, Col, CenterWires.S0_F1);
      Pin MemClkELog = new Pin(Pin.CLB, Row, Col, CenterWires.S0_F2);
      if (DebugMemROM == 1) {
        Fpga.set(Row, Col, LUT.SLICE0_F, L(0x0000)); }
      else {
        Fpga.set(Row, Col, LUT.SLICE0_F, L(I1|I2)); }
      Pin MemClkE = new Pin(Pin.CLB, Row, Col, CenterWires.S0_X);
      Router.route(MemClkE, MemWrEn);
      Row++;

      // announce how much space was used
      System.out.println(",c.." + (Row-1));


// ------ memory address mux section

      // select what address source addresses memory, PC or IR.X or MA or IR.AC
      //   extend 4bit addresses of IR.X and IR.AC with zeros to 18bit
      // 4:1-Mux with 4 separate enables, wide-OR of 2 LUTs as 2ANDs+OR
      //   so Col 0 bit 35/33/.., Col 1 bit 34/32/..

      Col = PlaceCol; Row = PlaceRow;
      PlaceCol += 2;
      Fpga.set(TextRow, Col, LUT.SLICE0_G, L(Font['A']));
      System.out.print("memory address mux at " + Col + "|" + Row);

      Pin MamIridx[] = new Pin[DataBits], MamIridxEn[] = new Pin[DataBits],
          MamIrac[] = new Pin[DataBits], MamIracEn[] = new Pin[DataBits],
          MamProg[] = new Pin[DataBits], MamProgEn[] = new Pin[DataBits],
          MamMaddr[] = new Pin[DataBits], MamMaddrEn[] = new Pin[DataBits],
          MamOut[] = new Pin[DataBits];

      for (Bit = DataLSB; Bit >= DataMSB; Bit--) {
        // for lowest 4 bits all 4 inputs, addressable by AC or X fields
        if (Bit >= AddrLSB-3) {
          MamIridx[Bit] = new Pin(Pin.CLB, Row, Col, CenterWires.S0_F1);
          MamIrac[Bit] = new Pin(Pin.CLB, Row, Col, CenterWires.S0_F3); }
        // rest of address bits only 2:1-Mux PC or MA, zero if IR.X or IR.AC
        // allocating all Pins would eliminate error checking on 4bit addresses
        if (Bit >= AddrMSB) {
          MamProg[Bit] = new Pin(Pin.CLB, Row, Col, CenterWires.S0_G1);
          MamMaddr[Bit] = new Pin(Pin.CLB, Row, Col, CenterWires.S0_G3); }
        // rest of bits, only connect the enables, useless, but easier code so
        //   because Java array 0..n limit workaround, else need [Bit-AddrBits]
        MamIridxEn[Bit] = new Pin(Pin.CLB, Row, Col, CenterWires.S0_F2);
        MamIracEn[Bit] = new Pin(Pin.CLB, Row, Col, CenterWires.S0_F4);
        MamProgEn[Bit] = new Pin(Pin.CLB, Row, Col, CenterWires.S0_G2);
        MamMaddrEn[Bit] = new Pin(Pin.CLB, Row, Col, CenterWires.S0_G4);
        if (Bit >= AddrLSB-3) {
          // lowest 4 bits, also from IR.AC or IR.X, use Wide-OR
          Fpga.set(Row, Col, LUT.SLICE0_F, L(~(I1&I2|I3&I4)));
          Fpga.set(Row, Col, LUT.SLICE0_G, L(~(I1&I2|I3&I4)));
          // wide-OR with LUT=0 -> !BX (=0) and LUT=1 -> AndMux.ONE (=1)
          Fpga.set(Row, Col, S0Control.XCarrySelect.XCarrySelect,
            S0Control.XCarrySelect.LUT_CONTROL);
          Fpga.set(Row, Col, S0Control.YCarrySelect.YCarrySelect,
            S0Control.YCarrySelect.LUT_CONTROL);
          Fpga.set(Row, Col, S0Control.AndMux.AndMux, S0Control.AndMux.ONE);
          Fpga.set(Row, Col, S0Control.Cin.Cin, S0Control.Cin.BX);
          Fpga.set(Row, Col, S0Control.BxInvert, S0Control.ON);
          if (DebugDisp == 1) {
            // show what address Mam selected for last memory access
            // make XQ show blank to not distract, take it from !BX = !1 = 0
            Fpga.set(Row, Col, S0Control.XDin.XDin, S0Control.XDin.BX);
            // make YQ show MamOut, from YB via BY to Y/YQ
            Router.route(new Pin(Pin.CLB, Row, Col, CenterWires.S0_YB),
              new Pin(Pin.CLB, Row, Col, CenterWires.S0_BY));
            Fpga.set(Row, Col, S0Control.YDin.YDin, S0Control.YDin.BY);
            Fpga.set(Row, Col, S0Clk.S0Clk, S0Clk.GCLK1); }
          MamOut[Bit] = new Pin(Pin.CLB, Row, Col, CenterWires.S0_YB); }
        else {
          // other address bits simply default to 0 when IR.AC or IR.X
          if (Bit >= AddrMSB) {
            Fpga.set(Row, Col, LUT.SLICE0_G, L(I1&I2|I3&I4));
            if (DebugDisp == 1) {
              // XQ will be blank (F LUT=0), make YQ show MamOut (G LUT)
              Fpga.set(Row, Col, S0Clk.S0Clk, S0Clk.GCLK1); }
            MamOut[Bit] = new Pin(Pin.CLB, Row, Col, CenterWires.S0_Y); } }
        Col = Bit%2==1 ? Col+1 : Col-1; Row = Bit%2==1 ? Row : Row+1; }

      // connect address mux outputs to memory address inputs
      Router.route(MamOut[31], MemAddr31);
      Router.route(MamOut[32], MemAddr32F);
      Router.route(MamOut[32], MemAddr32G);
      Router.route(MamOut[33], MemAddr33F);
      Router.route(MamOut[33], MemAddr33G);
      Router.route(MamOut[34], MemAddr34F);
      Router.route(MamOut[34], MemAddr34G);
      Router.route(MamOut[35], MemAddr35F);
      Router.route(MamOut[35], MemAddr35G);

      System.out.print(".." + (Row-1));

      // #buffer MAM-Mux=PC = insMAM-Mux=PC
      Pin MamEnProgIrma = new Pin(Pin.CLB, Row, Col, CenterWires.S0_F1);
      // no logic, just buffer signals to reduce fan-out load
      //   gives faster instruction decode, slower mux switching irrelevant
      Fpga.set(Row, Col, LUT.SLICE0_F, L(I1));
      Pin MamEnProg = new Pin(Pin.CLB, Row, Col, CenterWires.S0_X);
      Router.route(MamEnProg, MamProgEn);
      Row++;
      // #buffer MAM-Mux=IR.X = insMAM-Mux=IR.X
      Pin MamEnIridxIrma = new Pin(Pin.CLB, Row, Col, CenterWires.S0_F1);
      Fpga.set(Row, Col, LUT.SLICE0_F, L(I1));
      Pin MamEnIridx = new Pin(Pin.CLB, Row, Col, CenterWires.S0_X);
      Router.route(MamEnIridx, MamIridxEn);
      Row++;
      // #control MAM-Mux=MA = insMAM-Mux=MA|..
      // #                     ..|atestMAM-Mux=MA|logMAM-Mux=MA|...
      //   this will grow with other instruction groups adding subparts
      Pin MamEnMaddrIrma = new Pin(Pin.CLB, Row, Col, CenterWires.S0_F1);
      Pin MamEnMaddrAtest = new Pin(Pin.CLB, Row, Col, CenterWires.S0_F2);
      Pin MamEnMaddrLog = new Pin(Pin.CLB, Row, Col, CenterWires.S0_F3);
      Fpga.set(Row, Col, LUT.SLICE0_F, L(I1|I2|I3));
      Pin MamEnMaddr = new Pin(Pin.CLB, Row, Col, CenterWires.S0_X);
      Router.route(MamEnMaddr, MamMaddrEn);
      Row++;
      // #control MAM-Mux=IR.AC = ...|atestMAM-Mux=IR.AC|logMAM-Mux=IR.AC|...
      //   this will grow with other instruction groups adding subparts
      Pin MamEnIracAtest = new Pin(Pin.CLB, Row, Col, CenterWires.S0_F1);
      Pin MamEnIracLog = new Pin(Pin.CLB, Row, Col, CenterWires.S0_F2);
      Fpga.set(Row, Col, LUT.SLICE0_F, L(I1|I2));
      Pin MamEnIrac = new Pin(Pin.CLB, Row, Col, CenterWires.S0_X);
      Router.route(MamEnIrac, MamIracEn);
      Row++;

      System.out.println(",c.." + (Row-1));


// ------ program counter register and incrementer section

      // generate addresses of fetching instructions - increment, skip, jump
      // PC in FFs, 2:1-Mux with common select, jump 0,,E/MA or incr/skip PC+1

      Col = PlaceCol; Row = PlaceRow;
      PlaceCol += 1;
      Fpga.set(TextRow, Col, LUT.SLICE0_G, L(Font['P']));
      System.out.print("program counter at " + Col + "|" + Row);

      // ProgIncrSeed as 1 element array because compiler bug
      //   aborts with "may not be initialised" error instead of just warning
      Pin ProgCarryin[] = new Pin[1], ProgMux[] = new Pin[DataBits],
          ProgOld[] = new Pin[DataBits], ProgMaddr[] = new Pin[DataBits],
          ProgWrEn[] = new Pin[DataBits/2], ProgOut[] = new Pin[DataBits];

      for (Bit = DataLSB; Bit >= DataMSB; Bit--) {
        if (Bit == DataLSB) {
          // increment from carry-in via BX so add LUTs need no const 1 imput
          Fpga.set(Row, Col, S0Control.Cin.Cin, S0Control.Cin.BX);
          ProgCarryin[0] = new Pin(Pin.CLB, Row, Col, CenterWires.S0_BX); }
        if (Bit%2 == 1) {
          // bit 35, 33, 31, ..., 1 are in F LUTs
          // Mux incr is F1=1 and old PC F2 because condit add w mult-and gate
          ProgMux[Bit] = new Pin(Pin.CLB, Row, Col, CenterWires.S0_F1);
          if (Bit >= AddrMSB) {
            ProgOld[Bit] = new Pin(Pin.CLB, Row, Col, CenterWires.S0_F2);
            ProgMaddr[Bit] = new Pin(Pin.CLB, Row, Col, CenterWires.S0_F3);
            Fpga.set(Row, Col, LUT.SLICE0_F, L(I1&I2|(~I1)&I3));
            // carry conditional on F/G1 add Cin=1, from BX=1
            Fpga.set(Row, Col, S0Control.XCarrySelect.XCarrySelect,
              S0Control.XCarrySelect.LUT_CONTROL);
            Fpga.set(Row, Col, S0Control.AndMux.AndMux,
              S0Control.AndMux.IN1_AND_IN2);
            // and use carry adder result
            Fpga.set(Row, Col, S0Control.X.X, S0Control.X.FOUT_XOR_CARRY); }
          ProgWrEn[Bit/2] = new Pin(Pin.CLB, Row, Col, CenterWires.S0_CE);
          if (Bit >= AddrMSB) {
            Fpga.set(Row, Col, S0Clk.S0Clk, S0Clk.GCLK1);
            // set initial program counter to address of last read-in mem word
            if ((RinStartAt & (1<<(DataLSB-Bit))) != 0) {
              Fpga.set(Row, Col, S0Control.XffSetResetSelect, S0Control.ON); }
            ProgOut[Bit] = new Pin(Pin.CLB, Row, Col, CenterWires.S0_XQ); } }
        else {
          // bit 34, 32, 30, ..., 0 are in G LUTs, so need duplicate code
          ProgMux[Bit] = new Pin(Pin.CLB, Row, Col, CenterWires.S0_G1);
          if (Bit >= AddrMSB) {
            ProgOld[Bit] = new Pin(Pin.CLB, Row, Col, CenterWires.S0_G2);
            ProgMaddr[Bit] = new Pin(Pin.CLB, Row, Col, CenterWires.S0_G3);
            Fpga.set(Row, Col, LUT.SLICE0_G, L(I1&I2|(~I1)&I3));
            Fpga.set(Row, Col, S0Control.YCarrySelect.YCarrySelect,
              S0Control.YCarrySelect.LUT_CONTROL);
            // S0Control.AndMux.IN1_AND_IN2 is same setting for G/Y as for F/X
            Fpga.set(Row, Col, S0Control.Y.Y, S0Control.Y.GOUT_XOR_CARRY); }
          // ProgWrEn CenterWires.S0_CE is same setting for G/Y as for F/X
          if (Bit >= AddrMSB) {
            if ((RinStartAt & (1<<(DataLSB-Bit))) != 0) {
              Fpga.set(Row, Col, S0Control.YffSetResetSelect, S0Control.ON); }
            ProgOut[Bit] = new Pin(Pin.CLB, Row, Col, CenterWires.S0_YQ); } }
        if (Bit >= AddrMSB) {
          Router.route(ProgOut[Bit], ProgOld[Bit]);
          Router.route(ProgOut[Bit], MamProg[Bit]); }
        // no zigzag Col here, just next Row every 2 bits
        Row = Bit%2==1 ? Row : Row+1; }

      System.out.print(".." + (Row-1));

      // #control PC-Mux=PC+1 = insPC-Mux=PC+1|..|atestPC-Mux=PC+1|...
      //   this will grow when skip instructions are added
      //   default (non-skip) selection of Mux is to load/jump from MA
      Pin ProgMuxIncrIrma = new Pin(Pin.CLB, Row, Col, CenterWires.S0_F1);
      Pin ProgMuxIncrAtest = new Pin(Pin.CLB, Row, Col, CenterWires.S0_F2);
      Fpga.set(Row, Col, LUT.SLICE0_F, L(I1|I2));
      Pin ProgMuxIncr = new Pin(Pin.CLB, Row, Col, CenterWires.S0_X);
      Router.route(ProgMuxIncr, ProgMux);
      Row++;
      // #control PCcarry-in = PC-Mux=PC+1
      //   increment/SKIP: I+1, carry-in 1
      //   JUMP:           I+0, carry-in 0
      //   so carry-in is same as incrementer Mux control
      Router.route(ProgMuxIncr, ProgCarryin);
      Row+=0;
      // #control ClkE-PC = insClkE-PC|..|atestClkE-PC|...
      //   this will grow when skip or jump instructions are added
      Pin ProgClkEIrma = new Pin(Pin.CLB, Row, Col, CenterWires.S0_F1);
      Pin ProgClkEAtest = new Pin(Pin.CLB, Row, Col, CenterWires.S0_F2);
      Fpga.set(Row, Col, LUT.SLICE0_F, L(I1|I2));
      Pin ProgCLkE = new Pin(Pin.CLB, Row, Col, CenterWires.S0_X);
      Router.route(ProgCLkE, ProgWrEn);
      Row++;

      System.out.println(",c.." + (Row-1));


// ------ instruction and memory address register section

      // hold/modify the current instruction for later decoding it
      // IR in FFs bits 0..17, 2:1-Mux with complex enables for MD or IR or 0

      // hold/compute the current value of 0,,E/MA for addressing memory
      // MA in FFs bits 18..35, 2:1-Mux with complex enables for MD or MA+MD

      // comments with  // @  are for auto-generat pdp10.sld by the sld script
      // @central part of processor state logic diagram
      // @in state insget (Instruction Get)
      // @  MAM-Mux=PC
      // @  IR.OP-Mux=IR.AC-Mux=IR.I-Mux=IR.X-Mux=MA-Mux=MD
      // @  ClkE-IR+MA=1
      // @  PC-Mux=PC+1
      // @  ClkE-PC=1
      // @  state=insexec
      // @in state insexec (Instruction Execute)
      // @  if IR.X
      // @    MAM-Mux=IR.X
      // @    IR.OP-Mux=IR.AC-Mux=IR.I-Mux=IR
      // @    IR.X-Mux=0
      // @    MA-Mux=MA+MD
      // @    ClkE-IR+MA=1
      // @    state=insexec
      // @  elseif IR.I
      // @    MAM-Mux=MA
      // @    IR.OP-Mux=IR.AC-Mux=IR
      // @    IR.I-Mux=IR.X-Mux=MA-Mux=MD
      // @    ClkE-IR+MA=1
      // @    state=insexec
      // @  elseif ... insdecode (Instruction Decode)
      // @    see the instruction unit sections for elseif continuations
      // @  else
      // @    unimplemented opcode, not tested for, FSM simply hangs
      // @    in the end all opcodes will be accounted for, until then avoid

      Col = PlaceCol; Row = PlaceRow;
      PlaceCol += 1;
      Fpga.set(TextRow, Col, LUT.SLICE0_G, L(Font['I']));
      System.out.print("instruction and mem addr regs at " + Col + "|" + Row);

      Pin IrmaIndex[] = new Pin[DataBits], IrmaIndir[] = new Pin[DataBits],
          IrmaOld[] = new Pin[DataBits], IrmaMem[] = new Pin[DataBits],
          IrmaWrEn[] = new Pin[DataBits/2], IrmaOut[] = new Pin[DataBits];

      // need so many connections from IrmaOut bit 0..8 that run out of muxes
      //   this is because JBits routes each route from scratch from XQ/YQ Pin
      // so make 9 instruction bus arrays and route each bit once at end
      //   instead of Router.route(IrmaOut[?], <target-Pin-name>);
      //     at each Pin use IrmaBus?[IrmaPos?++] = <target-Pin-name>;
      //   at end of all defining do once Router.route(IrmaOut[?], IrmaBus?);
      // size of each array must be adjusted to fit after each new sink added
      Pin IrmaBus0[] = new Pin[3], IrmaBus1[] = new Pin[3],
          IrmaBus2[] = new Pin[3], IrmaBus3[] = new Pin[8],
          IrmaBus4[] = new Pin[6], IrmaBus5[] = new Pin[7],
          IrmaBus6[] = new Pin[2], IrmaBus7[] = new Pin[6],
          IrmaBus8[] = new Pin[6], IrmaBus13[] = new Pin[5];
      int IrmaPos0 = 0, IrmaPos1 = 0, IrmaPos2 = 0, IrmaPos3 = 0,
          IrmaPos4 = 0, IrmaPos5 = 0, IrmaPos6 = 0, IrmaPos7 = 0,
          IrmaPos8 = 0, IrmaPos13 = 0;

      for (Bit = DataLSB; Bit >= DataMSB; Bit--) {
        if (Bit == DataLSB) {
          // clear index add carry-in, BX is 1 not connect, so invert for Cin=0
          Fpga.set(Row, Col, S0Control.Cin.Cin, S0Control.Cin.BX);
          Fpga.set(Row, Col, S0Control.BxInvert, S0Control.ON); }
        if (Bit%2 == 1) {
          // index is F1=1 and old MA F2 because index cond add w mult-and gate
          IrmaIndex[Bit] = new Pin(Pin.CLB, Row, Col, CenterWires.S0_F1);
          IrmaIndir[Bit] = new Pin(Pin.CLB, Row, Col, CenterWires.S0_F3);
          IrmaOld[Bit] = new Pin(Pin.CLB, Row, Col, CenterWires.S0_F2);
          IrmaMem[Bit] = new Pin(Pin.CLB, Row, Col, CenterWires.S0_F4);
          Router.route(MemOut[Bit], IrmaMem[Bit]);
          // PDP-10 instruction format OOOOOOOOOAAAAIXXXXYYYYYYYYYYYYYYYYYY
          //                       IR. OP       AC  I X  Y
          if (Bit >= AddrMSB) {
            // MA: insget/indir (I1=0) load mem data (I4)
            //     index (I1=1) add mem data (I4) to old (I2)
            Fpga.set(Row, Col, LUT.SLICE0_F, L((~I1)&I4|I1&(I2^I4)));
            // carry add Cin=0 with !BX=0
            Fpga.set(Row, Col, S0Control.XCarrySelect.XCarrySelect,
              S0Control.XCarrySelect.LUT_CONTROL);
            Fpga.set(Row, Col, S0Control.AndMux.AndMux,
              S0Control.AndMux.IN1_AND_IN2);
            // and use carry adder result
            Fpga.set(Row, Col, S0Control.X.X, S0Control.X.FOUT_XOR_CARRY); }
          if (17 >= Bit && Bit >= 14) {
            // IR.X: insget/indir (I1=0) load mem data (I4)
            //       index (I1=1) clear (set to zero)
            Fpga.set(Row, Col, LUT.SLICE0_F, L((~I1)&I4)); }
          if (Bit == 13) {
            // IR.I: insget/indir (I1=0) load mem data (I4)
            //       index (I1=1) keep old (I2)
            Fpga.set(Row, Col, LUT.SLICE0_F, L((~I1)&I4|I1&I2)); }
          if (12 >= Bit) {
            // IR.AC+.OP: insget (I1=0 AND I3=0) load mem data (I4)
            //            index/indir (I1=1 OR I3=1) keep old (I2)
            Fpga.set(Row, Col, LUT.SLICE0_F, L((~I1)&(~I3)&I4|(I1|I3)&I2)); }
          IrmaWrEn[Bit/2] = new Pin(Pin.CLB, Row, Col, CenterWires.S0_CE);
          Fpga.set(Row, Col, S0Clk.S0Clk, S0Clk.GCLK1);
          IrmaOut[Bit] = new Pin(Pin.CLB, Row, Col, CenterWires.S0_XQ); }
        else {
          IrmaIndex[Bit] = new Pin(Pin.CLB, Row, Col, CenterWires.S0_G1);
          IrmaIndir[Bit] = new Pin(Pin.CLB, Row, Col, CenterWires.S0_G3);
          IrmaOld[Bit] = new Pin(Pin.CLB, Row, Col, CenterWires.S0_G2);
          IrmaMem[Bit] = new Pin(Pin.CLB, Row, Col, CenterWires.S0_G4);
          Router.route(MemOut[Bit], IrmaMem[Bit]);
          if (Bit >= AddrMSB) {
            Fpga.set(Row, Col, LUT.SLICE0_G, L((~I1)&I4|I1&(I2^I4)));
            Fpga.set(Row, Col, S0Control.YCarrySelect.YCarrySelect,
              S0Control.YCarrySelect.LUT_CONTROL);
            Fpga.set(Row, Col, S0Control.Y.Y, S0Control.Y.GOUT_XOR_CARRY); }
          if (17 >= Bit && Bit >= 14) {
            Fpga.set(Row, Col, LUT.SLICE0_G, L((~I1)&I4)); }
          if (Bit == 13) {
            Fpga.set(Row, Col, LUT.SLICE0_G, L((~I1)&I4|I1&I2)); }
          if (12 >= Bit) {
            Fpga.set(Row, Col, LUT.SLICE0_G, L((~I1)&(~I3)&I4|(I1|I3)&I2)); }
          IrmaOut[Bit] = new Pin(Pin.CLB, Row, Col, CenterWires.S0_YQ); }
        // wire MA and IR.X and IR.AC bits to their memory address mux inputs
        Router.route(IrmaOut[Bit], IrmaOld[Bit]);
        if (Bit >= AddrMSB) {
          Router.route(IrmaOut[Bit], MamMaddr[Bit]);
          Router.route(IrmaOut[Bit], ProgMaddr[Bit]); }
        if (17 >= Bit && Bit >= 14) {
          Router.route(IrmaOut[Bit], MamIridx[Bit+18]); }
        if (12 >= Bit && Bit >= 9) {
          Router.route(IrmaOut[Bit], MamIrac[Bit+23]); }
        Row = Bit%2==1 ? Row : Row+1; }

      System.out.print(".." + (Row-1));

      // #buffer IR-MuxselIdx = insindex
      Pin IrmaSelIndexIdx = new Pin(Pin.CLB, Row, Col, CenterWires.S0_F1);
      // no logic, just buffer insindex to reduce fan-out
      //   gives faster instruction decode, slower mux switching irrelevant
      Fpga.set(Row, Col, LUT.SLICE0_F, L(I1));
      Pin IrmaSelIndex = new Pin(Pin.CLB, Row, Col, CenterWires.S0_X);
      Router.route(IrmaSelIndex, IrmaIndex);
      Row++;
      // #control IR-MuxselInd = (~insindex)&IR.I
      Pin IrmaSelIndirInsidx = new Pin(Pin.CLB, Row, Col, CenterWires.S0_F1);
      Pin IrmaSelIndirIrind13 = new Pin(Pin.CLB, Row, Col, CenterWires.S0_F2);
      IrmaBus13[IrmaPos13++] = IrmaSelIndirIrind13;
      Fpga.set(Row, Col, LUT.SLICE0_F, L((~I1)&I2));
      Pin IrmaSelIndir = new Pin(Pin.CLB, Row, Col, CenterWires.S0_X);
      Router.route(IrmaSelIndir, IrmaIndir);
      Row++;
      // #control ClkE-IR+MA = insget|insexec&(insindex|IR.I)
      Pin IrmaClkEInsget = new Pin(Pin.CLB, Row, Col, CenterWires.S0_F1);
      Pin IrmaClkEInsexec = new Pin(Pin.CLB, Row, Col, CenterWires.S0_F2);
      Pin IrmaClkEInsidx = new Pin(Pin.CLB, Row, Col, CenterWires.S0_F3);
      Pin IrmaClkEIrind13 = new Pin(Pin.CLB, Row, Col, CenterWires.S0_F4);
      IrmaBus13[IrmaPos13++] = IrmaClkEIrind13;
      Fpga.set(Row, Col, LUT.SLICE0_F, L(I1|I2&(I3|I4)));
      Pin IrmaCLkE = new Pin(Pin.CLB, Row, Col, CenterWires.S0_X);
      Router.route(IrmaCLkE, IrmaWrEn);
      Row++;

      System.out.print(",c.." + (Row-1));

      // #control subpart insMAM-Mux=PC = insget
      Pin IrmaMamEnProgInsget = MamEnProgIrma;
      // one input, no logic, no need for a LUT, wire direct from only input
      //   have Row+=0, despite no effect, for visual consistency of separators
      Row+=0;
      // #control subpart insMAM-Mux=IR.X = insexec&insindex
      Pin IrmaMamEnIdxInsexec = new Pin(Pin.CLB, Row, Col, CenterWires.S0_F1);
      Pin IrmaMamEnIdxInsidx = new Pin(Pin.CLB, Row, Col, CenterWires.S0_F2);
      Fpga.set(Row, Col, LUT.SLICE0_F, L(I1&I2));
      Pin IrmaMamEnIdx = new Pin(Pin.CLB, Row, Col, CenterWires.S0_X);
      Router.route(IrmaMamEnIdx, MamEnIridxIrma);
      Row++;
      // #control subpart insMAM-Mux=MA = insexec&(~insindex)&IR.I
      Pin IrmaMamEnMadInsexec = new Pin(Pin.CLB, Row, Col, CenterWires.S0_F1);
      Pin IrmaMamEnMadInsidx = new Pin(Pin.CLB, Row, Col, CenterWires.S0_F2);
      Pin IrmaMamEnMadIrind13 = new Pin(Pin.CLB, Row, Col, CenterWires.S0_F3);
      IrmaBus13[IrmaPos13++] = IrmaMamEnMadIrind13;
      Fpga.set(Row, Col, LUT.SLICE0_F, L(I1&(~I2)&I3));
      Pin IrmaMamEnMad = new Pin(Pin.CLB, Row, Col, CenterWires.S0_X);
      Router.route(IrmaMamEnMad, MamEnMaddrIrma);
      Row++;
      // #control subpart insPC-Mux=PC+1 = insget
      Pin IrmaProgMuxIncrInsget = ProgMuxIncrIrma;
      Row+=0;
      // #control subpart insClkE-PC = insget
      Pin IrmaProgClkEInsget = ProgClkEIrma;
      Row+=0;

      System.out.print(",p.." + (Row-1));

      // central part of instruction execution Finite State Machine
      //   implementated as "one hot" FSM, this has an bit "hopping" around
      //     from one active state to the next, creating an "dance"
      //   one FF (and its LUT) is used to hold each state
      //     various auxillary LUT functions are used to detect conditions
      //   LUTs implement "come from" logic to select when their state is due
      //     as opposed to the processor state logic diagrams "go to" logic
      // #state insget = ...|atestinsget|loginsget|...
      //   if come from just finishing an instruction, any of 8 groups
      //     this will grow with other instruction groups adding subparts
      Pin IrmaInsgetAtest = new Pin(Pin.CLB, Row, Col, CenterWires.S0_F1);
      Pin IrmaInsgetLog = new Pin(Pin.CLB, Row, Col, CenterWires.S0_F2);
      Fpga.set(Row, Col, LUT.SLICE0_F, L(I1|I2));
      Fpga.set(Row, Col, S0Clk.S0Clk, S0Clk.GCLK1);
      // use CenterWires.S0_XQ to use Flip-Flop as FSM bit for this state
      Pin IrmaInsget = new Pin(Pin.CLB, Row, Col, CenterWires.S0_XQ);
      // set execution FSM bit to start-up in insget state
      Fpga.set(Row, Col, S0Control.XffSetResetSelect, S0Control.ON);
      Router.route(IrmaInsget, IrmaMamEnProgInsget);
      Router.route(IrmaInsget, IrmaProgMuxIncrInsget);
      Router.route(IrmaInsget, IrmaProgClkEInsget);
      Router.route(IrmaInsget, IrmaClkEInsget);
      Row++;
      // #detect insacc = IR.AC.0|IR.AC.1|IR.AC.2|IR.AC.3
      //   detect if this is an accumulator !=0 instruction
      //   no use in decoder, but in mult instr units, for facultative AC store
      Pin IrmaInsaccIracc9 = new Pin(Pin.CLB, Row, Col, CenterWires.S0_F1);
      Router.route(IrmaOut[9], IrmaInsaccIracc9);
      Pin IrmaInsaccIracc10 = new Pin(Pin.CLB, Row, Col, CenterWires.S0_F2);
      Router.route(IrmaOut[10], IrmaInsaccIracc10);
      Pin IrmaInsaccIracc11 = new Pin(Pin.CLB, Row, Col, CenterWires.S0_F3);
      Router.route(IrmaOut[11], IrmaInsaccIracc11);
      Pin IrmaInsaccIracc12 = new Pin(Pin.CLB, Row, Col, CenterWires.S0_F4);
      Router.route(IrmaOut[12], IrmaInsaccIracc12);
      Fpga.set(Row, Col, LUT.SLICE0_F, L(I1|I2|I3|I4));
      Pin IrmaInsacc = new Pin(Pin.CLB, Row, Col, CenterWires.S0_X);
      Row++;
      // #detect insindex = IR.X.0|IR.X.1|IR.X.2|IR.X.3
      //   detect if this is an indexed instruction, to be de-indexed
      Pin IrmaInsindexIridx14 = new Pin(Pin.CLB, Row, Col, CenterWires.S0_F1);
      Router.route(IrmaOut[14], IrmaInsindexIridx14);
      Pin IrmaInsindexIridx15 = new Pin(Pin.CLB, Row, Col, CenterWires.S0_F2);
      Router.route(IrmaOut[15], IrmaInsindexIridx15);
      Pin IrmaInsindexIridx16 = new Pin(Pin.CLB, Row, Col, CenterWires.S0_F3);
      Router.route(IrmaOut[16], IrmaInsindexIridx16);
      Pin IrmaInsindexIridx17 = new Pin(Pin.CLB, Row, Col, CenterWires.S0_F4);
      Router.route(IrmaOut[17], IrmaInsindexIridx17);
      Fpga.set(Row, Col, LUT.SLICE0_F, L(I1|I2|I3|I4));
      Pin IrmaInsindex = new Pin(Pin.CLB, Row, Col, CenterWires.S0_X);
      Router.route(IrmaInsindex, IrmaMamEnIdxInsidx);
      Router.route(IrmaInsindex, IrmaMamEnMadInsidx);
      Router.route(IrmaInsindex, IrmaSelIndexIdx);
      Router.route(IrmaInsindex, IrmaSelIndirInsidx);
      Router.route(IrmaInsindex, IrmaClkEInsidx);
      Row++;
      // #state insexec = insget|insexec&(insindex|IR.I)
      //   if come from insget or were insexec and do de-indexing or deref'ing
      Pin IrmaInsexecInsget = new Pin(Pin.CLB, Row, Col, CenterWires.S0_F1);
      Router.route(IrmaInsget, IrmaInsexecInsget);
      Pin IrmaInsexecInsexec = new Pin(Pin.CLB, Row, Col, CenterWires.S0_F2);
      Pin IrmaInsexecInsidx = new Pin(Pin.CLB, Row, Col, CenterWires.S0_F3);
      Router.route(IrmaInsindex, IrmaInsexecInsidx);
      Pin IrmaInsexecIrind13 = new Pin(Pin.CLB, Row, Col, CenterWires.S0_F4);
      IrmaBus13[IrmaPos13++] = IrmaInsexecIrind13;
      Fpga.set(Row, Col, LUT.SLICE0_F, L(I1|I2&(I3|I4)));
      Fpga.set(Row, Col, S0Clk.S0Clk, S0Clk.GCLK1);
      Pin IrmaInsexec = new Pin(Pin.CLB, Row, Col, CenterWires.S0_XQ);
      Router.route(IrmaInsexec, IrmaMamEnIdxInsexec);
      Router.route(IrmaInsexec, IrmaMamEnMadInsexec);
      Router.route(IrmaInsexec, IrmaClkEInsexec);
      Row++;
      // #detect insdecode = insexec&(~insindex)&(~IR.I)
      //   if in insexec and neither index nor indir, is ready to decode
      //   further decoding will be completed in appropriate instr units below
      Pin IrmaInsdecodeExec = new Pin(Pin.CLB, Row, Col, CenterWires.S0_F1);
      Router.route(IrmaInsexec, IrmaInsdecodeExec);
      Pin IrmaInsdecodeIndex = new Pin(Pin.CLB, Row, Col, CenterWires.S0_F2);
      Router.route(IrmaInsindex, IrmaInsdecodeIndex);
      Pin IrmaInsdecodeIrind13 = new Pin(Pin.CLB, Row, Col, CenterWires.S0_F3);
      IrmaBus13[IrmaPos13++] = IrmaInsdecodeIrind13;
      Fpga.set(Row, Col, LUT.SLICE0_F, L(I1&(~I2)&(~I3)));
      Pin IrmaInsdecode = new Pin(Pin.CLB, Row, Col, CenterWires.S0_X);
      Row++;
      // this FSM is extended in various instruction unit sections
      //   general pattern is there:
      //     decode if instruction group, from insdecode and IR.OP.0 to 2
      //     decode if subinstructions of group, from above and IR.OP.3 to 8
      //     drive further states from these decoders and IR.OP.3 to 8
      //     at end an state subpart of insget to get control to come back

      System.out.println(",s.." + (Row-1));


// ------ arithmetic register section

      // hold the current data being operated on
      // AR in FFs, no LUT logic for generating input, direct from memory
      // in real PDP-10 AR is used for entire calculation, until write to mem
      //   here it is only used for temp holding of C(E) or C(AC) inputs
      // this is so because all instruction units have own work/result "AR"s
      //   is done to avoid an large (ca 16:1) Mux, expensive in FPGAs
      //   also gets rid of lots of wiring back and forward, less delay, faster

      Col = PlaceCol; Row = PlaceRow;
      PlaceCol += 1;
      Fpga.set(TextRow, Col, LUT.SLICE0_G, L(Font['A']));
      System.out.print("arithmetic register at " + Col + "|" + Row);

      Pin ArithMem[] = new Pin[DataBits], ArithWrEn[] = new Pin[DataBits/2],
          ArithOut[] = new Pin[DataBits];

      for (Bit = DataLSB; Bit >= DataMSB; Bit--) {
        if (Bit%2 == 1) {
          ArithMem[Bit] = new Pin(Pin.CLB, Row, Col, CenterWires.S0_F1);
          Router.route(MemOut[Bit], ArithMem[Bit]);
          Fpga.set(Row, Col, LUT.SLICE0_F, L(I1));
          ArithWrEn[Bit/2] = new Pin(Pin.CLB, Row, Col, CenterWires.S0_CE);
          Fpga.set(Row, Col, S0Clk.S0Clk, S0Clk.GCLK1);
          ArithOut[Bit] = new Pin(Pin.CLB, Row, Col, CenterWires.S0_XQ); }
        else {
          ArithMem[Bit] = new Pin(Pin.CLB, Row, Col, CenterWires.S0_G1);
          Router.route(MemOut[Bit], ArithMem[Bit]);
          Fpga.set(Row, Col, LUT.SLICE0_G, L(I1));
          ArithOut[Bit] = new Pin(Pin.CLB, Row, Col, CenterWires.S0_YQ); }
        Row = Bit%2==1 ? Row : Row+1; }

      System.out.print(".." + (Row-1));

      // #control ClkE-AR = ...|atestClkE-AR|logClkE-AR|...
      //   this will grow with other instruction groups adding subparts 
      Pin ArithClkEAtest = new Pin(Pin.CLB, Row, Col, CenterWires.S0_F1);
      Pin ArithClkELog = new Pin(Pin.CLB, Row, Col, CenterWires.S0_F2);
      Fpga.set(Row, Col, LUT.SLICE0_F, L(I1|I2));
      Pin ArithClkE = new Pin(Pin.CLB, Row, Col, CenterWires.S0_X);
      Router.route(ArithClkE, ArithWrEn);
      Row++;

      System.out.println(",c.." + (Row-1));


// ------ immediate mode mux section

      // switch an input between ArithOut/IrmaOut, AR=C(E|AC)/MA=0,,E contents
      // 2:1-Mux with common select line, in from various instr exec units
      // uses LUT and no FFs, Arith uses FFs and no LUT, they could be merged

      Col = PlaceCol; Row = PlaceRow;
      PlaceCol += 1;
      Fpga.set(TextRow, Col, LUT.SLICE0_G, L(Font['I']));
      System.out.print("immediate mode mux at " + Col + "|" + Row);

      Pin ImmedMux[] = new Pin[DataBits], ImmedArith[] = new Pin[DataBits],
          ImmedMaddr[] = new Pin[DataBits], ImmedOut[] = new Pin[DataBits];

      for (Bit = DataLSB; Bit >= DataMSB; Bit--) {
        if (Bit%2 == 1) {
          ImmedMux[Bit] = new Pin(Pin.CLB, Row, Col, CenterWires.S0_F1);
          ImmedArith[Bit] = new Pin(Pin.CLB, Row, Col, CenterWires.S0_F2);
          Router.route(ArithOut[Bit], ImmedArith[Bit]);
          if (Bit >= AddrMSB) {
            ImmedMaddr[Bit] = new Pin(Pin.CLB, Row, Col, CenterWires.S0_F3);
            Router.route(IrmaOut[Bit], ImmedMaddr[Bit]);
            // classic 2:1-Mux only for E width of bits
            Fpga.set(Row, Col, LUT.SLICE0_F, L((~I1)&I2|I1&I3)); }
          else {
            // just gate AR for rest of bits, zero when 0,,E selected
            Fpga.set(Row, Col, LUT.SLICE0_F, L((~I1)&I2)); }
          if (DebugDisp == 1) {
            // show what data Immed selected for last operation
            Fpga.set(Row, Col, S0Clk.S0Clk, S0Clk.GCLK1); }
          ImmedOut[Bit] = new Pin(Pin.CLB, Row, Col, CenterWires.S0_X); }
        else {
          ImmedMux[Bit] = new Pin(Pin.CLB, Row, Col, CenterWires.S0_G1);
          ImmedArith[Bit] = new Pin(Pin.CLB, Row, Col, CenterWires.S0_G2);
          Router.route(ArithOut[Bit], ImmedArith[Bit]);
          if (Bit >= AddrMSB) {
            ImmedMaddr[Bit] = new Pin(Pin.CLB, Row, Col, CenterWires.S0_G3);
            Router.route(IrmaOut[Bit], ImmedMaddr[Bit]);
            Fpga.set(Row, Col, LUT.SLICE0_G, L((~I1)&I2|I1&I3)); }
          else {
            Fpga.set(Row, Col, LUT.SLICE0_G, L((~I1)&I2)); }
          ImmedOut[Bit] = new Pin(Pin.CLB, Row, Col, CenterWires.S0_Y); }
        Row = Bit%2==1 ? Row : Row+1; }

      System.out.print(".." + (Row-1));

      // #control Imm-Mux=E = ...|atestImm-Mux=E|logImm-Mux=E|...
      //   this will grow with other instruction groups adding subparts
      Pin ImmedMuxImmAtest = new Pin(Pin.CLB, Row, Col, CenterWires.S0_F1);
      Pin ImmedMuxImmLog = new Pin(Pin.CLB, Row, Col, CenterWires.S0_F2);
      Fpga.set(Row, Col, LUT.SLICE0_F, L(I1|I2));
      Pin ImmedMuxImm = new Pin(Pin.CLB, Row, Col, CenterWires.S0_X);
      Router.route(ImmedMuxImm, ImmedMux);
      Row++;

      System.out.println(",c.." + (Row-1));


// ------ memory data write mux section

      // select which instruction group unit can write back to memory
      //   allows one "AR" per instr group, if more "AR"s then use an local Mux
      // 8:1-Mux with 3 common select lines in from all 8 instr group units
      //   done as 2:1-Mux (F6) of 2 2:1-Mux (F5) of 4 2:1-Muxes (4 LUTs)

      Col = PlaceCol; Row = PlaceRow;
      PlaceCol += 2;
      Fpga.set(TextRow, Col, LUT.SLICE0_G, L(Font['W']));
      System.out.print("memory data write mux at " + Col + "|" + Row);

      Pin MdmIn0[] = new Pin[DataBits], MdmIn1[] = new Pin[DataBits],
          MdmIn2[] = new Pin[DataBits], MdmIn3[] = new Pin[DataBits],
          MdmIn4[] = new Pin[DataBits], MdmIn5[] = new Pin[DataBits],
          MdmIn6[] = new Pin[DataBits], MdmIn7[] = new Pin[DataBits],
          MdmSel1Sl0F[] = new Pin[DataBits], MdmSel1Sl0G[] = new Pin[DataBits],
          MdmSel1Sl1F[] = new Pin[DataBits], MdmSel1Sl1G[] = new Pin[DataBits],
          MdmSel2Sl0[] = new Pin[DataBits], MdmSel2Sl1[] = new Pin[DataBits],
          MdmSel4[] = new Pin[DataBits], MdmOut[] = new Pin[DataBits];

      for (Bit = DataLSB; Bit >= DataMSB; Bit--) {
        MdmIn0[Bit] = new Pin(Pin.CLB, Row, Col, CenterWires.S0_F1);
        MdmIn1[Bit] = new Pin(Pin.CLB, Row, Col, CenterWires.S0_F2);
        MdmIn2[Bit] = new Pin(Pin.CLB, Row, Col, CenterWires.S0_G1);
        MdmIn3[Bit] = new Pin(Pin.CLB, Row, Col, CenterWires.S0_G2);
        MdmIn4[Bit] = new Pin(Pin.CLB, Row, Col, CenterWires.S1_F1);
        MdmIn5[Bit] = new Pin(Pin.CLB, Row, Col, CenterWires.S1_F2);
        MdmIn6[Bit] = new Pin(Pin.CLB, Row, Col, CenterWires.S1_G1);
        MdmIn7[Bit] = new Pin(Pin.CLB, Row, Col, CenterWires.S1_G2);
        MdmSel1Sl0F[Bit] = new Pin(Pin.CLB, Row, Col, CenterWires.S0_F3);
        MdmSel1Sl0G[Bit] = new Pin(Pin.CLB, Row, Col, CenterWires.S0_G3);
        MdmSel1Sl1F[Bit] = new Pin(Pin.CLB, Row, Col, CenterWires.S1_F3);
        MdmSel1Sl1G[Bit] = new Pin(Pin.CLB, Row, Col, CenterWires.S1_G3);
        MdmSel2Sl0[Bit] = new Pin(Pin.CLB, Row, Col, CenterWires.S0_BX);
        MdmSel2Sl1[Bit] = new Pin(Pin.CLB, Row, Col, CenterWires.S1_BX);
        MdmSel4[Bit] = new Pin(Pin.CLB, Row, Col, CenterWires.S0_BY);
        Fpga.set(Row, Col, LUT.SLICE0_F, L(I1&(~I3)|I2&I3));
        Fpga.set(Row, Col, LUT.SLICE0_G, L(I1&(~I3)|I2&I3));
        Fpga.set(Row, Col, LUT.SLICE1_F, L(I1&(~I3)|I2&I3));
        Fpga.set(Row, Col, LUT.SLICE1_G, L(I1&(~I3)|I2&I3));
        // invert BX, because F5-Mux is 0/1:G/F (!)
        Fpga.set(Row, Col, S0Control.BxInvert, S0Control.ON);
        Fpga.set(Row, Col, S1Control.BxInvert, S1Control.ON);
        // invert BY, because F6-Mux is 0/1:Sl1/Sl0 (!)
        Fpga.set(Row, Col, S0Control.ByInvert, S0Control.ON);
        // set Y output to use F5 and G6 Muxes for full 8:1 Mux
        Fpga.set(Row, Col, S0Control.Y.Y, S0Control.Y.F6);
        if (DebugDisp == 1) {
          // show what data Mdm sent to Mem for last write
          // only Y relevant, X has 2:1-Mux of groups 0 and 1
          Fpga.set(Row, Col, S0Clk.S0Clk, S0Clk.GCLK1); }
        MdmOut[Bit] = new Pin(Pin.CLB, Row, Col, CenterWires.S0_Y);
        Router.route(MdmOut[Bit], MemIn[Bit]);
        Col = Bit%2==1 ? Col+1 : Col-1; Row = Bit%2==1 ? Row : Row+1; }

      System.out.print(".." + (Row-1));

      // #buffer MDM-Muxsel1 = IR.OP.2
      Pin MdmSelBuf1Irop2 = new Pin(Pin.CLB, Row, Col, CenterWires.S0_F1);
      IrmaBus2[IrmaPos2++] = MdmSelBuf1Irop2;
      // no logic, just buffer IR bits to reduce fan-out of IR.OP outputs
      //   gives faster instruction decode, slower mux switching irrelevant
      Fpga.set(Row, Col, LUT.SLICE0_F, L(I1));
      Pin MdmSelBuf1 = new Pin(Pin.CLB, Row, Col, CenterWires.S0_X);
      Router.route(MdmSelBuf1, MdmSel1Sl0F);
      Router.route(MdmSelBuf1, MdmSel1Sl1F);
      Router.route(MdmSelBuf1, MdmSel1Sl0G);
      Router.route(MdmSelBuf1, MdmSel1Sl1G);
      Row++;
      // #buffer MDM-Muxsel2 = IR.OP.1
      Pin MdmSelBuf2Irop1 = new Pin(Pin.CLB, Row, Col, CenterWires.S0_F1);
      IrmaBus1[IrmaPos1++] = MdmSelBuf2Irop1;
      Fpga.set(Row, Col, LUT.SLICE0_F, L(I1));
      Pin MdmSelBuf2 = new Pin(Pin.CLB, Row, Col, CenterWires.S0_X);
      Router.route(MdmSelBuf2, MdmSel2Sl0);
      Router.route(MdmSelBuf2, MdmSel2Sl1);
      Row++;
      // #buffer MDM-Muxsel4 = IR.OP.0
      Pin MdmSelBuf4Irop0 = new Pin(Pin.CLB, Row, Col, CenterWires.S0_F1);
      IrmaBus0[IrmaPos0++] = MdmSelBuf4Irop0;
      Fpga.set(Row, Col, LUT.SLICE0_F, L(I1));
      Pin MdmSelBuf4 = new Pin(Pin.CLB, Row, Col, CenterWires.S0_X);
      Router.route(MdmSelBuf4, MdmSel4);
      Row++;

      System.out.println(",c.." + (Row-1));


// ------ 000mooooo unimplemented user operations instruction unit section

      // implement the 000mooooo unimplemented user operations
      //   2 types of UUOs with each 32 unused subtypes

      // m UUO mode, from PDP-10 Reference Manual, page 2-123 to 2-127
      // Mnemonic Instruction       IR m 3
      // LUUOn    Local Unimp User Op    0
      // MUUOn    Monitor Unimp User Op  1

      // LUUOs in user mode do IR->C(40), C(41)->PC
      //   wait until memory is large enough for 040 to exist
      // MUUOs in user require mode switching to monitor
      //   and all UUOs in monitor mode require memory managment
      //   wait until memory managment and monitor mode is implemented


// ------ 001xxxxxx double, byte, floating point instruction unit section

      // implement the 001xxxxxx double, byte, floating point instructions
      //               ...000x0x (unimp before KL-10 UJEN/101/JSYS/ADJSP)
      //               ...000x1x (unimp before KL-10 GFAD/GFSB/GFMP/GFDV)
      //               ...0010xx DFAD/DFSB/DFMP/DFDV
      //               ...0011xx (unimp before KL-10 DADD/DSUB/DMUL/DDIV)
      //               ...010x0x DMOVE/DMOVN
      //               ...010x1x FIX/FIXR/FLTR (and unimp before KL-10 EXTEND)
      //               ...011xxx UFA/DFN/FSC and IBP/ILDB/LDB/IDPB/DPB
      //               ...1ffrmm FAD(R)/FSB(R)/FMP(R)/FDV(R)
      // multiple instruction formats will require multiple subsections

      // are the most complicated instructions, and least often used
      //   will be implemented last, possibly even after monitor mode and IO


// ------ 010xxxxxx move, fixed point, subroutine instruction unit section

      // implement the 010xxxxxx move, fixed point, subroutine instructions
      //               ...00ccmm MOVE/MOVS/MOVN/MOVM
      //               ...01oimm IMUL/MUL/IDIV/DIV
      //               ...100xxx ASH(C)/ROT(C)/LSH(C) and JFFO and 247
      //               ...101xxx EXCH/BLT/AOBJP/AOBJN/JRST/JFCL/XCT/MAP
      //               ...1100xx PUSHJ/PUSH/POP/POJ
      //               ...1101xx JSR/JSP/JSA/JRA
      //               ...111omm ADD/SUB
      // multiple instruction formats will require multiple subsections

      // mainly simple instructions, but subsectioning will make it large
      //   will be implemented before 000/111/001, but after 110/101


// ------ 011tttmmm arithmetic testing instruction unit section

      // implement the 011tttmmm arithmetic testing instructions
      //   8 operand/test combinations with each 8 skip/jump condition modes

      // ttt test type, from PDP-10 Reference Manual, page 2-43 to 2-46
      // Mnemonic  Instruction  IR ttt 3 4 5  Arithmetic    Action
      // CAI(m)    Comp AC Immed       0 0 0  C(AC) - 0,,E  if doit PC=PC+1
      // CAM(m)    Comp AC Mem         0 0 1  C(AC) - C(E)  if doit PC=PC+1
      // JUMP(m)   Jump if AC          0 1 0  C(AC) - 0     if doit PC=E
      // SKIP(m)   Skip if Memory      0 1 1  C(E) - 0      if doit PC=PC+1
      //                                                    if AC#0 C(AC)=C(E)
      // AOJ(m)    Add One AC Jump     1 0 0  C(AC)=C(AC)+1 if doit PC=E
      // AOS(m)    Add One Mem Skip    1 0 1  C(E) =C(E)+1  if doit PC=PC+1
      //                                                    if AC#0 C(AC)=C(E)
      // SOJ(m)    Sub One AC Jump     1 1 0  C(AC)=C(AC)-1 if doit PC=E
      // SOS(m)    Sub One Mem Skip    1 1 1  C(E) =C(E)-1  if doit PC=PC+1
      //                                                    if AC#0 C(AC)=C(E)

      // mmm condition mode, from PDP-10 Reference Manual, page 2-42
      // Suffix  Condition  IR mmm 6 7 8  doit on
      // -       Never             0 0 0  nothing
      // L       Lower             0 0 1  negative (bit 0 = 1)
      // E       Equal             0 1 0  zero (OR of bits 0..35 = 0)
      // LE      Lower or Equal    0 1 1  negative OR zero
      // A       Always            1 0 0  inverse of -
      // GE      Greater or Equal  1 0 1  inverse of L
      // N       Not Equal         1 1 0  inverse of E
      // G       Greater           1 1 1  inverse of LE
      // IR.6 is invert test, IR.7 is test zero, IR.8 is test negative

      // AO*/SO* set flags, 0 <-> -1 Carry0 and Carry1
      //                            max <-> min Trap1 Overflow and Carry0 or C1
      // see flags discussion from PDP-10 Reference Manual, page 2-11 and 2-65
      // to do: no flags implemented yet, as only visible in PC store and JFCL
      //   wait until subroutine and JFCL stuff implemented

      // AR in FFs (for SKIP/AO*/SO* writeback), addition/subtraction in LUTs
      //   and wide-NOR to detect zero/non-zero, positive/negative is bit 0

      // @arithmethic testing unit extension of processor state logic diagram
      // @in state insexec (Instruction Execute), continued from Irma insexec
      // @  elseif IR.OP=011000mmm atestcai (Atest Comp AC Immed)
      // @    MAM-Mux=IR.AC               # 1st operand C(AC)
      // @    Imm-Mux=E                   # 2nd operand 0,,E
      // @    PC-Mux=PC+1                 # skip
      // @    if doit                     # apply t:sub and test
      // @      ClkE-PC=1
      // @    state=insget                # we are done
      // @  elseif IR.OP=011001mmm atestcam (Atest Comp AC Mem)
      // @    MAM-Mux=MA                  # 2nd operand C(MA)
      // @    ClkE-AR=1                   # store to AR
      // @    state=atestcam2             # get second operand and test
      // @  elseif IR.OP=01101tmmm atestjump (Jump if AC)
      // @    MAM-Mux=IR.AC               # 1st operand C(AC)
      // @    PC-Mux=MA                   # jump to 0,,E
      // @    if doit                     # apply t:sub-zero and test
      // @      ClkE-PC=1
      // @    state=insget                # we are done
      // @  elseif IR.OP=01101tmmm atestskip (Skip if Memory)
      // @    MAM-Mux=MA                  # 1st operand C(MA)
      // @    PC-Mux=PC+1                 # skip
      // @    if doit                     # apply t:sub-zero and test
      // @      ClkE-PC=1
      // @    if IR.AC                    # if write C(E) to C(AC)
      // @      ClkE-atestAR=1              # store to atestAR
      // @      state=atestwracc          # we are done
      // @    else
      // @      state=insget              # we are done
      // @  elseif IR.OP=0111t0mmm atestasoj (Atest Add or Sub One a Jump)
      // @    MAM-Mux=IR.AC               # 1st operand C(AC)
      // @    PC-Mux=MA                   # jump to 0,,E
      // @    if doit                     # apply t:add-one/sub-one and test
      // @      ClkE-PC=1
      // @    ClkE-atestAR=1                # store to atestAR
      // @    state=atestwracc
      // @  elseif IR.OP=0111t1mmm atestasos (Atest Add or Sub One a Skip)
      // @    MAM-Mux=MA                  # 1nd operand C(MA)
      // @    PC-Mux=PC+1                 # skip
      // @    if doit                     # apply t:add/sub-one and test
      // @      ClkE-PC=1
      // @    ClkE-atestAR=1                # store to atestAR
      // @    state=atestwrmem
      // @in state atestcam2 (Atest Compare Acc Mem second fetch)
      // @  MAM-Mux=IR.AC                 # 1st operand C(AC)
      // @  Imm-Mux=AR                    # 2nd operand from AR
      // @  PC-Mux=PC+1                   # skip
      // @  if doit                       # apply t:sub and test
      // @    ClkE-PC=1
      // @  state=insget                  # we are done
      // @in state atestwracc (Atest Write Result to Accumulator)
      // @  MAM-Mux=IR.AC
      // @  MD-Mux=atest
      // @  ClkE-Mem=1
      // @  state=insget                  # we are done
      // @in state atestwrmem (Atest Write Result to Memory)
      // @  MAM-Mux=IR.MA
      // @  MD-Mux=atest
      // @  ClkE-Mem=1
      // @  if IR.AC                      # also write C(E) to C(AC)
      // @    state=atestwracc
      // @  else
      // @    state=insget                # we are done

      Col = PlaceCol; Row = PlaceRow;
      PlaceCol += 1;
      Fpga.set(TextRow, Col, LUT.SLICE0_G, L(Font['3']));
      System.out.print("arithmetic testing unit at " + Col + "|" + Row);

      // AtestCarryin, AtestNegative and AtestZero as 1 element arrays
      //   because compiler bug aborts with "may not be initialised" error
      //   instead of just warning
      Pin AtestCarryin[] = new Pin[1], AtestDatMem[] = new Pin[DataBits],
          AtestDatImm[] = new Pin[DataBits], AtestFunct0[] = new Pin[DataBits],
          AtestFunct1[] = new Pin[DataBits], AtestWrEn[] = new Pin[DataBits/2],
          AtestOut[] = new Pin[DataBits], AtestOutval[] = new Pin[DataBits],
          AtestZeroin[] = new Pin[DataBits], AtestNegative[] = new Pin[1],
          AtestZero[] = new Pin[1];

      for (Bit = DataLSB; Bit >= DataMSB; Bit--) {
        if (Bit == DataLSB) {
          // carry/borrow-in via BX from carry generator
          Fpga.set(Row, Col, S0Control.Cin.Cin, S0Control.Cin.BX);
          AtestCarryin[0] = new Pin(Pin.CLB, Row, Col, CenterWires.S0_BX);
          // wide-NOR = not wide-OR = wide-AND of not, in BX = 1, LUTs force 0
          Fpga.set(Row, Col, S1Control.Cin.Cin, S1Control.Cin.BX); }
        if (Bit%2 == 1) {
          // C(AC) or C(E) direct as comparison subtrahend
          AtestDatMem[Bit] = new Pin(Pin.CLB, Row, Col, CenterWires.S0_F1);
          Router.route(MemOut[Bit], AtestDatMem[Bit]);
          // C(E) or 0,,E from Imm as comparison subtractor
          AtestDatImm[Bit] = new Pin(Pin.CLB, Row, Col, CenterWires.S0_F2);
          Router.route(ImmedOut[Bit], AtestDatImm[Bit]);
          // compare function: CA* I1-I2, JUMP/SKIP I1-0, AO* I1+1, SO* I1-1
          AtestFunct0[Bit] = new Pin(Pin.CLB, Row, Col, CenterWires.S0_F3);
          AtestFunct1[Bit] = new Pin(Pin.CLB, Row, Col, CenterWires.S0_F4);
          // compute:  CA*:       I1-I2 = I1+(-I2)
          //           JUMP/SKIP: I1-0 = I1
          //           AO*:       I1+1, use carry = 1 for +1, so I1+0 = I1
          //           SO*:       I1-1 = I1+(-1), -1 is all ones, XOR 1 = not
          Fpga.set(Row, Col, LUT.SLICE0_F, L((I1^(~I2)) &(~I3)&(~I4)|
                                             I1         &(~I3)&  I4 |
                                             I1         &  I3 &(~I4)|
                                             (~I1)      &  I3 &  I4  ));
          Fpga.set(Row, Col, S0Control.XCarrySelect.XCarrySelect,
            S0Control.XCarrySelect.LUT_CONTROL);
          Fpga.set(Row, Col, S0Control.AndMux.AndMux, S0Control.AndMux.IN1);
          // and use carry adder result
          Fpga.set(Row, Col, S0Control.X.X, S0Control.X.FOUT_XOR_CARRY);
          // atest arithmetic register for AO* and SO*, to then write back
          AtestWrEn[Bit/2] = new Pin(Pin.CLB, Row, Col, CenterWires.S0_CE);
          Fpga.set(Row, Col, S0Clk.S0Clk, S0Clk.GCLK1);
          AtestOut[Bit] = new Pin(Pin.CLB, Row, Col, CenterWires.S0_XQ);
          Router.route(AtestOut[Bit], MdmIn3[Bit]);
          // wide-NOR = not wide-OR = wide-AND of not OR = wide-AND of NOR
          //   ripple time of 36-LUT wide-NOR is hidden behind arithmetic above
          AtestOutval[Bit] = new Pin(Pin.CLB, Row, Col, CenterWires.S0_X);
          AtestZeroin[Bit] = new Pin(Pin.CLB, Row, Col, CenterWires.S1_F1);
          Router.route(AtestOutval[Bit], AtestZeroin[Bit]);
          // NOR actually only 1 input per LUT, because 1 LUT per bit, = NOT
          Fpga.set(Row, Col, LUT.SLICE1_F, L(~I1));
          Fpga.set(Row, Col, S1Control.XCarrySelect.XCarrySelect,
            S1Control.XCarrySelect.LUT_CONTROL);
          // wide-AND of not OR, BX = 1, LUTs force 0
          Fpga.set(Row, Col, S1Control.AndMux.AndMux, S1Control.AndMux.ZERO); }
        else {
          AtestDatMem[Bit] = new Pin(Pin.CLB, Row, Col, CenterWires.S0_G1);
          Router.route(MemOut[Bit], AtestDatMem[Bit]);
          AtestDatImm[Bit] = new Pin(Pin.CLB, Row, Col, CenterWires.S0_G2);
          Router.route(ImmedOut[Bit], AtestDatImm[Bit]);
          AtestFunct0[Bit] = new Pin(Pin.CLB, Row, Col, CenterWires.S0_G3);
          AtestFunct1[Bit] = new Pin(Pin.CLB, Row, Col, CenterWires.S0_G4);
          Fpga.set(Row, Col, LUT.SLICE0_G, L((I1^(~I2)) &(~I3)&(~I4)|
                                             I1         &(~I3)&  I4 |
                                             I1         &  I3 &(~I4)|
                                             (~I1)      &  I3 &  I4  ));
          Fpga.set(Row, Col, S0Control.YCarrySelect.YCarrySelect,
            S0Control.YCarrySelect.LUT_CONTROL);
          Fpga.set(Row, Col, S0Control.Y.Y, S0Control.Y.GOUT_XOR_CARRY);
          AtestOut[Bit] = new Pin(Pin.CLB, Row, Col, CenterWires.S0_YQ);
          Router.route(AtestOut[Bit], MdmIn3[Bit]);
          AtestOutval[Bit] = new Pin(Pin.CLB, Row, Col, CenterWires.S0_Y);
          AtestZeroin[Bit] = new Pin(Pin.CLB, Row, Col, CenterWires.S1_G1);
          Router.route(AtestOutval[Bit], AtestZeroin[Bit]);
          Fpga.set(Row, Col, LUT.SLICE1_G, L(~I1));
          Fpga.set(Row, Col, S1Control.YCarrySelect.YCarrySelect,
            S1Control.YCarrySelect.LUT_CONTROL); }
        if (Bit == DataMSB) {
          // and directly use non-registered MSB for negative test result
          AtestNegative[0] = new Pin(Pin.CLB, Row, Col, CenterWires.S0_Y);
          // grab wide-NOR carry output for zero test result
          Fpga.set(Row, Col, S1Control.YB.YB, S1Control.YB.COUT);
          AtestZero[0] = new Pin(Pin.CLB, Row, Col, CenterWires.S1_YB); }
        Row = Bit%2==1 ? Row : Row+1; }

      System.out.print(".." + (Row-1));

      // #buffer atest-Funct1 = IR.OP.4
      Pin AtestFunctBuf1Irop4 = new Pin(Pin.CLB, Row, Col, CenterWires.S0_F1);
      IrmaBus4[IrmaPos4++] = AtestFunctBuf1Irop4;
      // no logic, just buffer IR bits to reduce fan-out of IR.OP outputs
      //   gives faster instruction decode, slower function select irrelevant
      Fpga.set(Row, Col, LUT.SLICE0_F, L(I1));
      Pin AtestFunctBuf1 = new Pin(Pin.CLB, Row, Col, CenterWires.S0_X);
      Router.route(AtestFunctBuf1, AtestFunct1);
      // fit next LUT into same CLB, to reduce space use, else design too large
      Row+=0;
      // #buffer atest-Funct0 = IR.OP.3
      Pin AtestFunctBuf0Irop3 = new Pin(Pin.CLB, Row, Col, CenterWires.S0_G1);
      IrmaBus3[IrmaPos3++] = AtestFunctBuf0Irop3;
      Fpga.set(Row, Col, LUT.SLICE0_G, L(I1));
      Pin AtestFunctBuf0 = new Pin(Pin.CLB, Row, Col, CenterWires.S0_Y);
      Router.route(AtestFunctBuf0, AtestFunct0);
      Row++;
      // #control atest-carry = ~atest-Funct1
      //   CA* subtract: I1-I2, no borrow,               carry-in 1
      //   JUMP/SKIP:    I1+0, no carry,                 carry-in 0
      //   AO*:          I1+1, add 1 from carry=1        carry-in 1
      //   SO*:          I1+(-1), no carry,              carry-in 0
      //   so carry-in is NOT(JUMP OR SKIP OR SO*) is NOT(Funct1)
      Pin AtestCarryFunct1 = new Pin(Pin.CLB, Row, Col, CenterWires.S0_F1);
      Router.route(AtestFunctBuf1, AtestCarryFunct1);
      Fpga.set(Row, Col, LUT.SLICE0_F, L(~I1));
      Pin AtestCarry = new Pin(Pin.CLB, Row, Col, CenterWires.S0_X);
      Router.route(AtestCarry, AtestCarryin[0]);
      Row+=0;
      // #control ClkE-atestAR = atestskip&insacc|atestasoj|atestasos
      //   hold test value, if we will be later storing, to Acc or to Mem
      Pin AtestClkESkip = new Pin(Pin.CLB, Row, Col, CenterWires.S0_G1);
      Pin AtestClkEInsacc = new Pin(Pin.CLB, Row, Col, CenterWires.S0_G2);
      Router.route(IrmaInsacc, AtestClkEInsacc);
      Pin AtestClkEAsoj = new Pin(Pin.CLB, Row, Col, CenterWires.S0_G3);
      Pin AtestClkEAsos = new Pin(Pin.CLB, Row, Col, CenterWires.S0_G4);
      if (DebugDisp == 1) {
        // always set AR, so that the test value is visible
        Fpga.set(Row, Col, LUT.SLICE0_G, L(0xFFFF)); }
      else {
        Fpga.set(Row, Col, LUT.SLICE0_G, L(I1&I2|I3|I4)); }
      Pin AtestClkE = new Pin(Pin.CLB, Row, Col, CenterWires.S0_Y);
      Router.route(AtestClkE, AtestWrEn);
      Row++;

      System.out.print(",c.." + (Row-1));

      // #control subpart atestClkE-Mem = atestwracc|atestwrmem
      Pin AtestMemClkEWracc = new Pin(Pin.CLB, Row, Col, CenterWires.S0_F1);
      Pin AtestMemClkEWrmem = new Pin(Pin.CLB, Row, Col, CenterWires.S0_F2);
      Fpga.set(Row, Col, LUT.SLICE0_F, L(I1|I2));
      Pin AtestMemClkE = new Pin(Pin.CLB, Row, Col, CenterWires.S0_X);
      Router.route(AtestMemClkE, MemClkEAtest);
      // fit next LUT into same CLB, to reduce space use, else design too large
      Row+=0;
      // #control subpart atestMAM-Mux=MA =
      // #  atestcam|atestskip|atestasos|atestwrmem
      Pin AtestMamEnMaddrCam = new Pin(Pin.CLB, Row, Col, CenterWires.S0_G1);
      Pin AtestMamEnMaddrSkip = new Pin(Pin.CLB, Row, Col, CenterWires.S0_G2);
      Pin AtestMamEnMaddrAsos = new Pin(Pin.CLB, Row, Col, CenterWires.S0_G3);
      Pin AtestMamEnMaddrWrmem = new Pin(Pin.CLB, Row, Col, CenterWires.S0_G4);
      Fpga.set(Row, Col, LUT.SLICE0_G, L(I1|I2|I3|I4));
      Pin AtestMamEnMaddr = new Pin(Pin.CLB, Row, Col, CenterWires.S0_Y);
      Router.route(AtestMamEnMaddr, MamEnMaddrAtest);
      Row++;
      // #control subpart atestMAM-Mux=IR.AC =
      // #  atestcai|atestjump|atestasoj|atestcam2|atestwracc
      Pin AtestMamEnIracCai = new Pin(Pin.CLB, Row, Col, CenterWires.S0_F1);
      Pin AtestMamEnIracJump = new Pin(Pin.CLB, Row, Col, CenterWires.S0_F2);
      Pin AtestMamEnIracAsoj = new Pin(Pin.CLB, Row, Col, CenterWires.S0_F3);
      Pin AtestMamEnIracCam2 = new Pin(Pin.CLB, Row, Col, CenterWires.S0_F4);
      Fpga.set(Row, Col, LUT.SLICE0_F, L(I1|I2|I3|I4));
      Pin AtestMamEnIracWracc = new Pin(Pin.CLB, Row, Col, CenterWires.S0_G1);
      Fpga.set(Row, Col, LUT.SLICE0_G, L(I1));
      // mem addressing is speed critical, use F5 FF as an OR for LUTs F and G
      Router.route(new Pin(Pin.CLB, Row, Col, CenterWires.S0_Y),
        new Pin(Pin.CLB, Row, Col, CenterWires.S0_BX));
      // invert BX, because F5-Mux is wired 0/1=G/F
      Fpga.set(Row, Col, S0Control.BxInvert, S0Control.ON);
      Fpga.set(Row, Col, S0Control.X.X, S0Control.X.F5);
      Pin AtestMamEnIrac = new Pin(Pin.CLB, Row, Col, CenterWires.S0_X);
      Router.route(AtestMamEnIrac, MamEnIracAtest);
      Row++;
      // #control subpart atestPC-Mux=PC+1 =
      // #  atestcai|atestskip|atestasos|atestcam2
      Pin AtestProgMuxIncrCai = new Pin(Pin.CLB, Row, Col, CenterWires.S0_F1);
      Pin AtestProgMuxIncrSkip = new Pin(Pin.CLB, Row, Col, CenterWires.S0_F2);
      Pin AtestProgMuxIncrAsos = new Pin(Pin.CLB, Row, Col, CenterWires.S0_F3);
      Pin AtestProgMuxIncrCam2 = new Pin(Pin.CLB, Row, Col, CenterWires.S0_F4);
      Fpga.set(Row, Col, LUT.SLICE0_F, L(I1|I2|I3|I4));
      Pin AtestProgMuxIncr = new Pin(Pin.CLB, Row, Col, CenterWires.S0_X);
      Router.route(AtestProgMuxIncr, ProgMuxIncrAtest);
      // fit next LUT into same CLB, to reduce space use, else design too large
      Row+=0;
      // #control subpart atestClkE-PC =
      // #  atestPC-Mux=PC+1|atestjump|atestasoj
      // not used directly, as jump/skip is conditional
      Pin AtestProgClkEIncr = new Pin(Pin.CLB, Row, Col, CenterWires.S0_G1);
      Router.route(AtestProgMuxIncr, AtestProgClkEIncr);
      Pin AtestProgClkEJump = new Pin(Pin.CLB, Row, Col, CenterWires.S0_G2);
      Pin AtestProgClkEAsoj = new Pin(Pin.CLB, Row, Col, CenterWires.S0_G3);
      Fpga.set(Row, Col, LUT.SLICE0_G, L(I1|I2|I3));
      Pin AtestProgClkE = new Pin(Pin.CLB, Row, Col, CenterWires.S0_Y);
      // fit next LUT into same CLB, to reduce space use, else design too large
      Row+=0;
      // #control test atestcond = negative&IR.OP.8|zero&IR.OP.7
      //   select which conditions are allowed to trigger jump/skip
      Pin AtestCondNegative = new Pin(Pin.CLB, Row, Col, CenterWires.S1_F1);
      Router.route(AtestNegative[0], AtestCondNegative);
      Pin AtestCondIrop8 = new Pin(Pin.CLB, Row, Col, CenterWires.S1_F2);
      IrmaBus8[IrmaPos8++] = AtestCondIrop8;
      Pin AtestCondZero = new Pin(Pin.CLB, Row, Col, CenterWires.S1_F3);
      Router.route(AtestZero[0], AtestCondZero);
      Pin AtestCondIrop7 = new Pin(Pin.CLB, Row, Col, CenterWires.S1_F4);
      IrmaBus7[IrmaPos7++] = AtestCondIrop7;
      Fpga.set(Row, Col, LUT.SLICE1_F, L(I1&I2|I3&I4));
      Pin AtestCond = new Pin(Pin.CLB, Row, Col, CenterWires.S1_X);
      // fit next LUT into same CLB, to reduce space use, else design too large
      Row+=0;
      // #control test atestdoit = (arithcond^IR.OP.6)&atestClkE-PC
      //   select whether trigger shall be inverted and gate jump/skip signal
      Pin AtestDoitCond = new Pin(Pin.CLB, Row, Col, CenterWires.S1_G1);
      Router.route(AtestCond, AtestDoitCond);
      Pin AtestDoitIrop6 = new Pin(Pin.CLB, Row, Col, CenterWires.S1_G2);
      IrmaBus6[IrmaPos6++] = AtestDoitIrop6;
      Pin AtestDoitClkE = new Pin(Pin.CLB, Row, Col, CenterWires.S1_G3);
      Router.route(AtestProgClkE, AtestDoitClkE);
      Fpga.set(Row, Col, LUT.SLICE1_G, L((I1^I2)&I3));
      Pin AtestDoit = new Pin(Pin.CLB, Row, Col, CenterWires.S1_Y);
      Router.route(AtestDoit, ProgClkEAtest);
      Row++;
      // #control subpart atestClkE-AR = atestcam
      Pin AtestArithClkECam = ArithClkEAtest;
      // one input, no logic, no need for a LUT, wire direct from only input
      Row+=0;
      // #control subpart atestImm-Mux=E = atestcai
      Pin AtestImmedMuxImmCai = ImmedMuxImmAtest;
      Row+=0;

      System.out.print(",p.." + (Row-1));

      // aritmetic testing unit extension of instruction execution FSM
      // #decode atestinstr = insdecode&(~IR.OP.0)&IR.OP.1&IR.OP.2
      //   decode if start of an 011tttmmm aritmetic testing instruction
      Pin AtestInstrInsdecode = new Pin(Pin.CLB, Row, Col, CenterWires.S0_F1);
      Router.route(IrmaInsdecode, AtestInstrInsdecode);
      Pin AtestInstrIrop0 = new Pin(Pin.CLB, Row, Col, CenterWires.S0_F2);
      IrmaBus0[IrmaPos0++] = AtestInstrIrop0;
      Pin AtestInstrIrop1 = new Pin(Pin.CLB, Row, Col, CenterWires.S0_F3);
      IrmaBus1[IrmaPos1++] = AtestInstrIrop1;
      Pin AtestInstrIrop2 = new Pin(Pin.CLB, Row, Col, CenterWires.S0_F4);
      IrmaBus2[IrmaPos2++] = AtestInstrIrop2;
      Fpga.set(Row, Col, LUT.SLICE0_F, L(I1&(~I2)&I3&I4));
      Pin AtestInstr = new Pin(Pin.CLB, Row, Col, CenterWires.S0_X);
      Row++;
      // #decode atestcai = atestinstr&(~IR.OP.3)&(~IR.OP.4)&(~IR.OP.5)
      //   decode if start of an CAI arith testing instruction
      Pin AtestCaiInstr = new Pin(Pin.CLB, Row, Col, CenterWires.S0_F1);
      Router.route(AtestInstr, AtestCaiInstr);
      Pin AtestCaiIrop3 = new Pin(Pin.CLB, Row, Col, CenterWires.S0_F2);
      IrmaBus3[IrmaPos3++] = AtestCaiIrop3;
      Pin AtestCaiIrop4 = new Pin(Pin.CLB, Row, Col, CenterWires.S0_F3);
      IrmaBus4[IrmaPos4++] = AtestCaiIrop4;
      Pin AtestCaiIrop5 = new Pin(Pin.CLB, Row, Col, CenterWires.S0_F4);
      IrmaBus5[IrmaPos5++] = AtestCaiIrop5;
      Fpga.set(Row, Col, LUT.SLICE0_F, L(I1&(~I2)&(~I3)&(~I4)));
      Pin AtestCai = new Pin(Pin.CLB, Row, Col, CenterWires.S0_X);
      Router.route(AtestCai, AtestMamEnIracCai);
      Router.route(AtestCai, AtestProgMuxIncrCai);
      Router.route(AtestCai, AtestImmedMuxImmCai);
      Row++;
      // #decode atestcam = atestinstr&(~IR.OP.3)&(~IR.OP.4)&IR.OP.5
      //   decode if start of an CAM arith testing instruction
      Pin AtestCamInstr = new Pin(Pin.CLB, Row, Col, CenterWires.S0_F1);
      Router.route(AtestInstr, AtestCamInstr);
      Pin AtestCamIrop3 = new Pin(Pin.CLB, Row, Col, CenterWires.S0_F2);
      IrmaBus3[IrmaPos3++] = AtestCamIrop3;
      Pin AtestCamIrop4 = new Pin(Pin.CLB, Row, Col, CenterWires.S0_F3);
      IrmaBus4[IrmaPos4++] = AtestCamIrop4;
      Pin AtestCamIrop5 = new Pin(Pin.CLB, Row, Col, CenterWires.S0_F4);
      IrmaBus5[IrmaPos5++] = AtestCamIrop5;
      Fpga.set(Row, Col, LUT.SLICE0_F, L(I1&(~I2)&(~I3)&I4));
      Pin AtestCam = new Pin(Pin.CLB, Row, Col, CenterWires.S0_X);
      Router.route(AtestCam, AtestMamEnMaddrCam);
      Router.route(AtestCam, AtestArithClkECam);
      // following state same logic function, no own LUT, just add FF and Pin
      Row+=0;
      // #state atestcam2 = atestcam
      //   if come from atestcam, always fetch second operand
      Fpga.set(Row, Col, S0Clk.S0Clk, S0Clk.GCLK1);
      Pin AtestCam2 = new Pin(Pin.CLB, Row, Col, CenterWires.S0_XQ);
      Router.route(AtestCam2, AtestMamEnIracCam2);
      Router.route(AtestCam2, AtestProgMuxIncrCam2);
      Row++;
      // #decode atestjump = atestinstr&(~IR.OP.3)&IR.OP.4&(~IR.OP.5)
      //   decode if start of an JUMP arith testing instruction
      Pin AtestJumpInstr = new Pin(Pin.CLB, Row, Col, CenterWires.S0_F1);
      Router.route(AtestInstr, AtestJumpInstr);
      Pin AtestJumpIrop3 = new Pin(Pin.CLB, Row, Col, CenterWires.S0_F2);
      IrmaBus3[IrmaPos3++] = AtestJumpIrop3;
      Pin AtestJumpIrop4 = new Pin(Pin.CLB, Row, Col, CenterWires.S0_F3);
      IrmaBus4[IrmaPos4++] = AtestJumpIrop4;
      Pin AtestJumpIrop5 = new Pin(Pin.CLB, Row, Col, CenterWires.S0_F4);
      IrmaBus5[IrmaPos5++] = AtestJumpIrop5;
      Fpga.set(Row, Col, LUT.SLICE0_F, L(I1&(~I2)&I3&(~I4)));
      Pin AtestJump = new Pin(Pin.CLB, Row, Col, CenterWires.S0_X);
      Router.route(AtestJump, AtestMamEnIracJump);
      Router.route(AtestJump, AtestProgClkEJump);
      Row++;
      // #decode atestskip = atestinstr&(~IR.OP.3)&IR.OP.4&IR.OP.5
      //   decode if start of an SKIP arith testing instruction
      Pin AtestSkipInstr = new Pin(Pin.CLB, Row, Col, CenterWires.S0_F1);
      Router.route(AtestInstr, AtestSkipInstr);
      Pin AtestSkipIrop3 = new Pin(Pin.CLB, Row, Col, CenterWires.S0_F2);
      IrmaBus3[IrmaPos3++] = AtestSkipIrop3;
      Pin AtestSkipIrop4 = new Pin(Pin.CLB, Row, Col, CenterWires.S0_F3);
      IrmaBus4[IrmaPos4++] = AtestSkipIrop4;
      Pin AtestSkipIrop5 = new Pin(Pin.CLB, Row, Col, CenterWires.S0_F4);
      IrmaBus5[IrmaPos5++] = AtestSkipIrop5;
      Fpga.set(Row, Col, LUT.SLICE0_F, L(I1&(~I2)&I3&I4));
      Pin AtestSkip = new Pin(Pin.CLB, Row, Col, CenterWires.S0_X);
      Router.route(AtestSkip, AtestMamEnMaddrSkip);
      Router.route(AtestSkip, AtestProgMuxIncrSkip);
      Router.route(AtestSkip, AtestClkESkip);
      Row++;
      // #decode atestasoj = atestinstr&IR.OP.3&(~IR.OP.5)
      //   decode if start of an AOJ/SOJ arith testing instruction
      Pin AtestAsojInstr = new Pin(Pin.CLB, Row, Col, CenterWires.S0_F1);
      Router.route(AtestInstr, AtestAsojInstr);
      Pin AtestAsojIrop3 = new Pin(Pin.CLB, Row, Col, CenterWires.S0_F2);
      IrmaBus3[IrmaPos3++] = AtestAsojIrop3;
      Pin AtestAsojIrop5 = new Pin(Pin.CLB, Row, Col, CenterWires.S0_F4);
      IrmaBus5[IrmaPos5++] = AtestAsojIrop5;
      Fpga.set(Row, Col, LUT.SLICE0_F, L(I1&I2&(~I4)));
      Pin AtestAsoj = new Pin(Pin.CLB, Row, Col, CenterWires.S0_X);
      Router.route(AtestAsoj, AtestMamEnIracAsoj);
      Router.route(AtestAsoj, AtestProgClkEAsoj);
      Router.route(AtestAsoj, AtestClkEAsoj);
      Row++;
      // #decode atestasos = atestinstr&IR.OP.3&IR.OP.5
      //   decode if start of an AOS/SOS arith testing instruction
      Pin AtestAsosInstr = new Pin(Pin.CLB, Row, Col, CenterWires.S0_F1);
      Router.route(AtestInstr, AtestAsosInstr);
      Pin AtestAsosIrop3 = new Pin(Pin.CLB, Row, Col, CenterWires.S0_F2);
      IrmaBus3[IrmaPos3++] = AtestAsosIrop3;
      Pin AtestAsosIrop5 = new Pin(Pin.CLB, Row, Col, CenterWires.S0_F4);
      IrmaBus5[IrmaPos5++] = AtestAsosIrop5;
      Fpga.set(Row, Col, LUT.SLICE0_F, L(I1&I2&I4));
      Pin AtestAsos = new Pin(Pin.CLB, Row, Col, CenterWires.S0_X);
      Router.route(AtestAsos, AtestMamEnMaddrAsos);
      Router.route(AtestAsos, AtestProgMuxIncrAsos);
      Router.route(AtestAsos, AtestClkEAsos);
      // following state same logic function, no own LUT, just add FF and Pin
      Row+=0;
      // #state atestwrmem = atestasos
      //   if come from atestasos, always fetch second operand
      Fpga.set(Row, Col, S0Clk.S0Clk, S0Clk.GCLK1);
      Pin AtestWrmem = new Pin(Pin.CLB, Row, Col, CenterWires.S0_XQ);
      Router.route(AtestWrmem, AtestMemClkEWrmem);
      Router.route(AtestWrmem, AtestMamEnMaddrWrmem);
      Row++;
      // #state atestwracc = atestskip&insacc|atestasoj|atestwrmem&insacc
      //   if come from SKIP and AC!=0 or AOJ/SOJ or written AOS/SOS and AC!=0
      Pin AtestWraccSkip = new Pin(Pin.CLB, Row, Col, CenterWires.S0_F1);
      Router.route(AtestSkip, AtestWraccSkip);
      Pin AtestWraccInsacc = new Pin(Pin.CLB, Row, Col, CenterWires.S0_F2);
      Router.route(IrmaInsacc, AtestWraccInsacc);
      Pin AtestWraccAsoj = new Pin(Pin.CLB, Row, Col, CenterWires.S0_F3);
      Router.route(AtestAsoj, AtestWraccAsoj);
      Pin AtestWraccWrmem = new Pin(Pin.CLB, Row, Col, CenterWires.S0_F4);
      Router.route(AtestWrmem, AtestWraccWrmem);
      Fpga.set(Row, Col, LUT.SLICE0_F, L(I1&I2|I3|I4&I2));
      Fpga.set(Row, Col, S0Clk.S0Clk, S0Clk.GCLK1);
      Pin AtestWracc = new Pin(Pin.CLB, Row, Col, CenterWires.S0_XQ);
      Router.route(AtestWracc, AtestMemClkEWracc);
      Router.route(AtestWracc, AtestMamEnIracWracc);
      Row++;
      // #state subpart atestinsget = atestcai|atestcam2|atestjump|
      // #  atestskip&(~insacc)|atestwracc|atestwrmem&(~insacc)
      //   if come from CAI or CAM second or JUMP or
      //     SKIP and AC=0 or AOJ/SOJ second or AOS/SOS second and AC=0
      Pin AtestInsgetCai = new Pin(Pin.CLB, Row, Col, CenterWires.S0_F1);
      Router.route(AtestCai, AtestInsgetCai);
      Pin AtestInsgetCam2 = new Pin(Pin.CLB, Row, Col, CenterWires.S0_F2);
      Router.route(AtestCam2, AtestInsgetCam2);
      Pin AtestInsgetJump = new Pin(Pin.CLB, Row, Col, CenterWires.S0_F3);
      Router.route(AtestJump, AtestInsgetJump);
      Fpga.set(Row, Col, LUT.SLICE0_F, L(I1|I2|I3));
      Pin AtestInsgetSkip = new Pin(Pin.CLB, Row, Col, CenterWires.S0_G1);
      Router.route(AtestSkip, AtestInsgetSkip);
      Pin AtestInsgetInsacc = new Pin(Pin.CLB, Row, Col, CenterWires.S0_G2);
      Router.route(IrmaInsacc, AtestInsgetInsacc);
      Pin AtestInsgetWracc = new Pin(Pin.CLB, Row, Col, CenterWires.S0_G3);
      Router.route(AtestWracc, AtestInsgetWracc);
      Pin AtestInsgetWrmem = new Pin(Pin.CLB, Row, Col, CenterWires.S0_G4);
      Router.route(AtestWrmem, AtestInsgetWrmem);
      Fpga.set(Row, Col, LUT.SLICE0_G, L(I1&(~I2)|I3|I4&(~I2)));
      // use F5 FF as an OR for LUTs F and G
      Router.route(new Pin(Pin.CLB, Row, Col, CenterWires.S0_Y),
        new Pin(Pin.CLB, Row, Col, CenterWires.S0_BX));
      // invert BX, because F5-Mux is wired 0/1=G/F
      Fpga.set(Row, Col, S0Control.BxInvert, S0Control.ON);
      Fpga.set(Row, Col, S0Control.X.X, S0Control.X.F5);
      Pin AtestInsget = new Pin(Pin.CLB, Row, Col, CenterWires.S0_X);
      Router.route(AtestInsget, IrmaInsgetAtest);
      Row++;

      System.out.println(",s.." + (Row-1));


// ------ 100ffffmm bitwise boolean logic instruction unit section

      // implement the 100ffffmm bitwise boolean logic instructions
      //   16 boolean logic functions with 4 operand selection modes

      // ffff function table, from PDP-10 Reference Manual, page 2-38
      // C(AC)                          0 1 0 1
      // C(E)/0,,E                      0 0 1 1
      // --------------------------------------
      // Mnemonic  Instruction  IR ffff 3 4 5 6
      // SETZ(m)   Set Zero             0 0 0 0
      // AND(m)    And                  0 0 0 1
      // ANDCA(m)  And Compl Acc        0 0 1 0
      // SETM(m)   Set Memory           0 0 1 1
      // ANDCM(m)  And Compl Mem        0 1 0 0
      // SETA(m)   Set Accu             0 1 0 1
      // XOR(m)    Exclusive Or         0 1 1 0
      // IOR(m)    Inclusive Or         0 1 1 1
      // ANDCB(m)  And Compl Both       1 0 0 0
      // EQV(m)    Equivalent           1 0 0 1
      // SETCA(m)  Set Compl Acc        1 0 1 0
      // ORCA(m)   Or Compl Acc         1 0 1 1
      // SETCM(m)  Set Compl Mem        1 1 0 0
      // ORCM(m)   Or Compl Mem         1 1 0 1
      // ORCB(m)   Or Compl Both        1 1 1 0
      // SETO(m)   Set One              1 1 1 1

      // mm operand mode, from PDP-10 Reference Manual, page 2-32
      // Suffix  Mode  IR mm 7 8  Sources         Destination
      // -       Basic       0 0  C(E) and C(AC)  AC
      // I       Immediate   0 1  0,,E and C(AC)  AC
      // M       Memory      1 0  C(E) and C(AC)  E
      // B       Both        1 1  C(E) and C(AC)  AC and E

      // AR in FFs, is 4:1-Mux of instructions bits 3..6
      //   selected by 2 * C(E)/0,,E + C(AC)
      // used 2:1-Mux (F5) of 2 2:1-Muxes (2 LUTs F and G)

      // @boolean logic unit extension of processor state logic diagram
      // @in state insexec (Instruction Execute), continued from Irma insexec
      // @  elseif IR.OP=100ffff01 logimmed (Logic Immediate)
      // @    MAM-Mux=IR.AC               # 1st operand C(AC)
      // @    Imm-Mux=E                   # 2nd operand 0,,E
      // @    ClkE-logAR=1                # apply ffff, store to logAR
      // @    state=logstoac              # store logAR to C(AC)
      // @  elseif IR.OP=100ffffmm lognonimm (Logic non-Immedate)
      // @    MAM-Mux=MA                  # 2nd operand C(MA)
      // @    ClkE-AR=1                   # store to AR
      // @    state=lognon2               # get second operand and operate
      // @in state lognon2 (Logic non-Immedate second fetch)
      // @  MAM-Mux=IR.AC                 # 1st operand C(AC)
      // @  Imm-Mux=AR                    # 2nd operand from AR
      // @  ClkE-logAR=1                  # apply ffff, store to logAR
      // @  if IR.OP=100ffff10            # memory mode
      // @    state=logstomem             # store logAR to C(MA)
      // @  else
      // @    state=logstoac              # store logAR to C(AC)
      // @in state logstoac (Logic Store to Accumulator)
      // @  MAM-Mux=IR.AC
      // @  MD-Mux=log
      // @  ClkE-Mem=1
      // @  if IR.OP=100ffff11            # both mode
      // @    state=logmem                # store logAR also to C(MA)
      // @  else
      // @    state=insget                # we are done
      // @in state logstomem (Logic Store to Memory)
      // @  MAM-Mux=MA
      // @  MD-Mux=log
      // @  ClkE-Mem=1
      // @  state=insget                  # we are done

      Col = PlaceCol; Row = PlaceRow;
      PlaceCol += 2;
      Fpga.set(TextRow, Col, LUT.SLICE0_G, L(Font['4']));
      System.out.print("boolean logic unit at " + Col + "|" + Row);

      Pin LogicFunct0[] = new Pin[DataBits], LogicFunct1[] = new Pin[DataBits],
          LogicFunct2[] = new Pin[DataBits], LogicFunct3[] = new Pin[DataBits],
          LogicDatMDF[] = new Pin[DataBits], LogicDatMDG[] = new Pin[DataBits],
          LogicDatImm[] = new Pin[DataBits], LogicWrEn[] = new Pin[DataBits],
          LogicOut[] = new Pin[DataBits];

      for (Bit = DataLSB; Bit >= DataMSB; Bit--) {
        // logic function F1..2 IR.OP bits 3..4 and G1..2 IR.OP bits 5..6
        LogicFunct0[Bit] = new Pin(Pin.CLB, Row, Col, CenterWires.S0_F1);
        LogicFunct1[Bit] = new Pin(Pin.CLB, Row, Col, CenterWires.S0_F2);
        LogicFunct2[Bit] = new Pin(Pin.CLB, Row, Col, CenterWires.S0_G1);
        LogicFunct3[Bit] = new Pin(Pin.CLB, Row, Col, CenterWires.S0_G2);
        // lower selection bit, F3 and G3, from C(E) = AR
        LogicDatMDF[Bit] = new Pin(Pin.CLB, Row, Col, CenterWires.S0_F3);
        Router.route(MemOut[Bit], LogicDatMDF[Bit]);
        LogicDatMDG[Bit] = new Pin(Pin.CLB, Row, Col, CenterWires.S0_G3);
        Router.route(MemOut[Bit], LogicDatMDG[Bit]);
        Fpga.set(Row, Col, LUT.SLICE0_F, L(I1&(~I3)|I2&I3));
        Fpga.set(Row, Col, LUT.SLICE0_G, L(I1&(~I3)|I2&I3));
        // upper selection bit, BX, from C(AC) = MD
        LogicDatImm[Bit] = new Pin(Pin.CLB, Row, Col, CenterWires.S0_BX);
        Router.route(ImmedOut[Bit], LogicDatImm[Bit]);
        // invert BX, because F5-Mux is 0/1:G/F
        Fpga.set(Row, Col, S0Control.BxInvert, S0Control.ON);
        Fpga.set(Row, Col, S0Control.X.X, S0Control.X.F5);
        if (DebugDisp == 1) {
          // make YQ show blank to not distract, take it from !BY = !1 = 0
          Fpga.set(Row, Col, S0Control.ByInvert, S0Control.ON);
          Fpga.set(Row, Col, S0Control.YDin.YDin, S0Control.YDin.BY); }
        // logic units result arithmetic register
        LogicWrEn[Bit] = new Pin(Pin.CLB, Row, Col, CenterWires.S0_CE);
        Fpga.set(Row, Col, S0Clk.S0Clk, S0Clk.GCLK1);
        LogicOut[Bit] = new Pin(Pin.CLB, Row, Col, CenterWires.S0_XQ);
        Router.route(LogicOut[Bit], MdmIn4[Bit]);
        Col = Bit%2==1 ? Col+1 : Col-1; Row = Bit%2==1 ? Row : Row+1; }

      System.out.print(".." + (Row-1));

      // #buffer log-Funct3 = IR.OP.6
      Pin LogicFunctBuf3Irop6 = new Pin(Pin.CLB, Row, Col, CenterWires.S0_F1);
      IrmaBus6[IrmaPos6++] = LogicFunctBuf3Irop6;
      // no logic, just buffer IR bits to reduce fan-out of IR.OP outputs
      //   gives faster instruction decode, slower function select irrelevant
      Fpga.set(Row, Col, LUT.SLICE0_F, L(I1));
      Pin LogicFunctBuf3 = new Pin(Pin.CLB, Row, Col, CenterWires.S0_X);
      Router.route(LogicFunctBuf3, LogicFunct3);
      Row++;
      // #buffer log-Funct2 = IR.OP.5
      Pin LogicFunctBuf2Irop5 = new Pin(Pin.CLB, Row, Col, CenterWires.S0_F1);
      IrmaBus5[IrmaPos5++] = LogicFunctBuf2Irop5;
      Fpga.set(Row, Col, LUT.SLICE0_F, L(I1));
      Pin LogicFunctBuf2 = new Pin(Pin.CLB, Row, Col, CenterWires.S0_X);
      Router.route(LogicFunctBuf2, LogicFunct2);
      Row++;
      // #buffer log-Funct1 = IR.OP.4
      Pin LogicFunctBuf1Irop4 = new Pin(Pin.CLB, Row, Col, CenterWires.S0_F1);
      IrmaBus4[IrmaPos4++] = LogicFunctBuf1Irop4;
      Fpga.set(Row, Col, LUT.SLICE0_F, L(I1));
      Pin LogicFunctBuf1 = new Pin(Pin.CLB, Row, Col, CenterWires.S0_X);
      Router.route(LogicFunctBuf1, LogicFunct1);
      Row++;
      // #buffer log-Funct0 = IR.OP.3
      Pin LogicFunctBuf0Irop3 = new Pin(Pin.CLB, Row, Col, CenterWires.S0_F1);
      IrmaBus3[IrmaPos3++] = LogicFunctBuf0Irop3;
      Fpga.set(Row, Col, LUT.SLICE0_F, L(I1));
      Pin LogicFunctBuf0 = new Pin(Pin.CLB, Row, Col, CenterWires.S0_X);
      Router.route(LogicFunctBuf0, LogicFunct0);
      Row++;
      // #control ClkE-logAR = lognon2|logimmed
      Pin LogClkENon2 = new Pin(Pin.CLB, Row, Col, CenterWires.S0_F1);
      Pin LogClkEImmed = new Pin(Pin.CLB, Row, Col, CenterWires.S0_F2);
      if (DebugDisp == 1) {
        // always set AR, so that the result is visible
        Fpga.set(Row, Col, LUT.SLICE0_F, L(0xFFFF)); }
      else {
        Fpga.set(Row, Col, LUT.SLICE0_F, L(I1|I2)); }
      Pin LogClkE = new Pin(Pin.CLB, Row, Col, CenterWires.S0_X);
      Router.route(LogClkE, LogicWrEn);
      Row++;

      System.out.print(",c.." + (Row-1));

      // #control subpart logClkE-Mem = logstoac|logstomem
      Pin LogMemClkEStoac = new Pin(Pin.CLB, Row, Col, CenterWires.S0_F1);
      Pin LogMemClkEStomem = new Pin(Pin.CLB, Row, Col, CenterWires.S0_F2);
      Fpga.set(Row, Col, LUT.SLICE0_F, L(I1|I2));
      Pin LogMemClkE = new Pin(Pin.CLB, Row, Col, CenterWires.S0_X);
      Router.route(LogMemClkE, MemClkELog);
      Row++;
      // #control subpart logMAM-Mux=MA = lognonimm|logstomem
      Pin LogMamEnMaddrNonimm = new Pin(Pin.CLB, Row, Col, CenterWires.S0_F1);
      Pin LogMamEnMaddrStomem = new Pin(Pin.CLB, Row, Col, CenterWires.S0_F2);
      Fpga.set(Row, Col, LUT.SLICE0_F, L(I1|I2));
      Pin LogMamEnMaddr = new Pin(Pin.CLB, Row, Col, CenterWires.S0_X);
      Router.route(LogMamEnMaddr, MamEnMaddrLog);
      Row++;
      // #control subpart logMAM-Mux=IR.AC = lognon2|logimmed|logstoac
      Pin LogMamEnIracNon2 = new Pin(Pin.CLB, Row, Col, CenterWires.S0_F1);
      Pin LogMamEnIracImmed = new Pin(Pin.CLB, Row, Col, CenterWires.S0_F2);
      Pin LogMamEnIracStoac = new Pin(Pin.CLB, Row, Col, CenterWires.S0_F3);
      Fpga.set(Row, Col, LUT.SLICE0_F, L(I1|I2|I3));
      Pin LogMamEnIrac = new Pin(Pin.CLB, Row, Col, CenterWires.S0_X);
      Router.route(LogMamEnIrac, MamEnIracLog);
      Row++;
      // #control subpart logClkE-AR = lognonimm
      Pin LogArithClkENonimm = ArithClkELog;
      // one input, no logic, no need for a LUT, wire direct from only input
      Row+=0;
      // #control subpart logImm-Mux=E = logimmed
      Pin LogImmedMuxImmImmed = ImmedMuxImmLog;
      Row+=0;

      System.out.print(",p.." + (Row-1));

      // boolean logic unit extension of instruction execution FSM
      // #decode loginstr = insdecode&IR.OP.0&(~IR.OP.1)&(~IR.OP.2)
      //   decode if start of an 100ffffmm bitwise boolean logic instruction
      Pin LogicInstrInsdecode = new Pin(Pin.CLB, Row, Col, CenterWires.S0_F1);
      Router.route(IrmaInsdecode, LogicInstrInsdecode);
      Pin LogicInstrIrop0 = new Pin(Pin.CLB, Row, Col, CenterWires.S0_F2);
      IrmaBus0[IrmaPos0++] = LogicInstrIrop0;
      Pin LogicInstrIrop1 = new Pin(Pin.CLB, Row, Col, CenterWires.S0_F3);
      IrmaBus1[IrmaPos1++] = LogicInstrIrop1;
      Pin LogicInstrIrop2 = new Pin(Pin.CLB, Row, Col, CenterWires.S0_F4);
      IrmaBus2[IrmaPos2++] = LogicInstrIrop2;
      Fpga.set(Row, Col, LUT.SLICE0_F, L(I1&I2&(~I3)&(~I4)));
      Pin LogicInstr = new Pin(Pin.CLB, Row, Col, CenterWires.S0_X);
      Row++;
      // #decode logimmed = loginstr&(~IR.OP.7)&IR.OP.8
      //   decode if start of an immediate mode logic instruction
      Pin LogicImmedInstr = new Pin(Pin.CLB, Row, Col, CenterWires.S0_F1);
      Router.route(LogicInstr, LogicImmedInstr);
      Pin LogicImmedIrop7 = new Pin(Pin.CLB, Row, Col, CenterWires.S0_F2);
      IrmaBus7[IrmaPos7++] = LogicImmedIrop7;
      Pin LogicImmedIrop8 = new Pin(Pin.CLB, Row, Col, CenterWires.S0_F3);
      IrmaBus8[IrmaPos8++] = LogicImmedIrop8;
      Fpga.set(Row, Col, LUT.SLICE0_F, L(I1&(~I2)&I3));
      Pin LogicImmed = new Pin(Pin.CLB, Row, Col, CenterWires.S0_X);
      Router.route(LogicImmed, LogMamEnIracImmed);
      Router.route(LogicImmed, LogImmedMuxImmImmed);
      Router.route(LogicImmed, LogClkEImmed);
      Row++;
      // #decode lognonimm = loginstr&(~((~IR.OP.7)&IR.OP.8))
      //   decode if start of an non-immediate mode logic instruction
      Pin LogicNonimmInstr = new Pin(Pin.CLB, Row, Col, CenterWires.S0_F1);
      Router.route(LogicInstr, LogicNonimmInstr);
      Pin LogicNonimmIrop7 = new Pin(Pin.CLB, Row, Col, CenterWires.S0_F2);
      IrmaBus7[IrmaPos7++] = LogicNonimmIrop7;
      Pin LogicNonimmIrop8 = new Pin(Pin.CLB, Row, Col, CenterWires.S0_F3);
      IrmaBus8[IrmaPos8++] = LogicNonimmIrop8;
      Fpga.set(Row, Col, LUT.SLICE0_F, L(I1&(~((~I2)&I3))));
      Pin LogicNonimm = new Pin(Pin.CLB, Row, Col, CenterWires.S0_X);
      Router.route(LogicNonimm, LogMamEnMaddrNonimm);
      Router.route(LogicNonimm, LogArithClkENonimm);
      // following state same logic function, no own LUT, just add FF and Pin
      Row+=0;
      // #state lognon2 = lognonimm
      //   if come from lognonimm, always fetch second operand
      Fpga.set(Row, Col, S0Clk.S0Clk, S0Clk.GCLK1);
      Pin LogicNon2 = new Pin(Pin.CLB, Row, Col, CenterWires.S0_XQ);
      Router.route(LogicNon2, LogMamEnIracNon2);
      Router.route(LogicNon2, LogClkENon2);
      Row++;
      // #state logstoac = logimmed|lognon2&(~(IR.OP.7&(~IR.OP.8)))
      //   if come from logimmed or come from lognon2 and is non-memory mode
      Pin LogicStoacImmed = new Pin(Pin.CLB, Row, Col, CenterWires.S0_F1);
      Router.route(LogicImmed, LogicStoacImmed);
      Pin LogicStoacNon2 = new Pin(Pin.CLB, Row, Col, CenterWires.S0_F2);
      Router.route(LogicNon2, LogicStoacNon2);
      Pin LogicStoacIrop7 = new Pin(Pin.CLB, Row, Col, CenterWires.S0_F3);
      IrmaBus7[IrmaPos7++] = LogicStoacIrop7;
      Pin LogicStoacIrop8 = new Pin(Pin.CLB, Row, Col, CenterWires.S0_F4);
      IrmaBus8[IrmaPos8++] = LogicStoacIrop8;
      Fpga.set(Row, Col, LUT.SLICE0_F, L(I1|I2&(~(I3&(~I4)))));
      Fpga.set(Row, Col, S0Clk.S0Clk, S0Clk.GCLK1);
      Pin LogicStoac = new Pin(Pin.CLB, Row, Col, CenterWires.S0_XQ);
      Router.route(LogicStoac, LogMemClkEStoac);
      Router.route(LogicStoac, LogMamEnIracStoac);
      Row++;
      // #state logstomem = lognon2&IR.OP.7&(~IR.OP.8)|logstoac&IR.OP.7&IR.OP.8
      //   if come from lognon2 and is memory mode
      //   or come from logstoac and both mode
      Pin LogicStomemNon2 = new Pin(Pin.CLB, Row, Col, CenterWires.S0_F1);
      Router.route(LogicNon2, LogicStomemNon2);
      Pin LogicStomemIrop7 = new Pin(Pin.CLB, Row, Col, CenterWires.S0_F2);
      IrmaBus7[IrmaPos7++] = LogicStomemIrop7;
      Pin LogicStomemIrop8 = new Pin(Pin.CLB, Row, Col, CenterWires.S0_F3);
      IrmaBus8[IrmaPos8++] = LogicStomemIrop8;
      Pin LogicStomemStoac = new Pin(Pin.CLB, Row, Col, CenterWires.S0_F4);
      Router.route(LogicStoac, LogicStomemStoac);
      Fpga.set(Row, Col, LUT.SLICE0_F, L(I1&I2&(~I3)|I4&I2&I3));
      Fpga.set(Row, Col, S0Clk.S0Clk, S0Clk.GCLK1);
      Pin LogicStomem = new Pin(Pin.CLB, Row, Col, CenterWires.S0_XQ);
      Router.route(LogicStomem, LogMemClkEStomem);
      Router.route(LogicStomem, LogMamEnMaddrStomem);
      Row++;
      // #state subpart loginsget = logstoac&(~(IR.OP.7&IR.OP.8))|logstomem
      //   if come from logstoac and non-both mode or come from logstomem
      Pin LogicInsgetStoac = new Pin(Pin.CLB, Row, Col, CenterWires.S0_F1);
      Router.route(LogicStoac, LogicInsgetStoac);
      Pin LogicInsgetIrop7 = new Pin(Pin.CLB, Row, Col, CenterWires.S0_F2);
      IrmaBus7[IrmaPos7++] = LogicInsgetIrop7;
      Pin LogicInsgetIrop8 = new Pin(Pin.CLB, Row, Col, CenterWires.S0_F3);
      IrmaBus8[IrmaPos8++] = LogicInsgetIrop8;
      Pin LogicInsgetStomem = new Pin(Pin.CLB, Row, Col, CenterWires.S0_F4);
      Router.route(LogicStomem, LogicInsgetStomem);
      Fpga.set(Row, Col, LUT.SLICE0_F, L(I1&(~(I2&I3))|I4));
      Pin LogicInsget = new Pin(Pin.CLB, Row, Col, CenterWires.S0_X);
      Router.route(LogicInsget, IrmaInsgetLog);
      Row++;

      System.out.println(",s.." + (Row-1));


// ------ 101tootmm half word instruction unit section

      // implement the 101tootmm half word instructions
      //   4 halfword transfers with 4 modifications and 4 operand select modes

      // tt transfer type, from PDP-10 Reference Manual, page 2-55
      // Mnemonic  Instruction     IR tt 3 6
      // HLL(o)(m) Half Word Left Left   0 0
      // HRL(o)(m) Half Word Right Left  0 1
      // HRR(o)(m) Half Word Right Right 1 0
      // HLR(o)(m) Half Word Left Right  1 1
      // IR.3 is select main destination half, IR.6 is swap L and R of input

      // oo modification, from PDP-10 Reference Manual, page 2-55
      // Suffix  Modification  IR oo 4 5  Other (not main) Destination Half
      // -       Do Nothing          0 0  leave unchanged
      // Z       Zeros               0 1  all zeros
      // O       Ones                1 0  all ones
      // E       Extend              1 1  top bit of main half

      // mm operand mode, from PDP-10 Reference Manual, page 2-55
      // Suffix  Mode  IR mm 7 8  Source  Destination
      // -       Basic       0 0  C(E)    C(AC)
      // I       Immediate   0 1  0,,E    C(AC)
      // M       Memory      1 0  C(AC)   C(E)
      // S       Self        1 1  C(E)    C(E), if AC#0 C(AC)=C(E)

      // 2:1Mux for IR.6 left/right half swapping input from Immed
      //   4:1Mux of self/zero/one/other-top modif for other half
      //   AR in FFs with 2:1 Mux for main swapped or other modified

      // @half word unit extension of processor state logic diagram
      // @in state insexec (Instruction Execute), continued from Irma insexec
      // @  implement after separate memory and registers, to avoid re-doing

// ------ 110ooamma bit testing instruction unit section

      // implement the 110ooamma bit testing instructions
      //   4 operand tests with 4 modifications and 4 skip condition modes

      // aa test mask, from PDP-10 Reference Manual, page 2-47
      // Mnemonic  Instruction  IR aa 5 8  C(AC) AND with xxx
      // TRo(m)    Test Right         0 0  0,,E
      // TLo(m)    Test Left          0 1  E,,0
      // TDo(m)    Test Direct        1 0  C(E)
      // TSo(m)    Test Swapped       1 1  right(C(E))+left(C(E))
      // IR.5 is 0,,E vs C(E), IR.8 is swap L and R of input from 0,,E or C(E)

      // oo modification, from PDP-10 Reference Manual, page 2-47
      // Suffix  Modification  IR oo 3 4  C(AC) set to
      // N       No                  0 0  no writeback
      // Z       Zeros               0 1  C(AC) ANDCM xxx
      // C       Complement          1 0  C(AC) XOR xxx
      // O       Ones                1 1  C(AC) OR xxx

      // mm condition mode, from PDP-10 Reference Manual, page 2-48
      // Suffix  Mode  IR mm 6 7  skip on
      // -       Never       0 0  nothing
      // E       Equal       0 1  zero(OR of masked bits 0..35 = 0)
      // A       Always      1 0  inverse of -
      // N       Not Equal   1 1  inverse of E
      // IR.6 is invert test, IR.7 is test zero, this is similar to arith test

      // 2:1Mux for IR.8 left/right half swapping input from Immed
      //   bitwise AND with wide-NOR to detect zero/non-zero
      //   AR in FFs (for Z/C/O writeback) with AC/ANDCM/XOR/OR logic unit

      // @bit testing unit extension of processor state logic diagram
      // @in state insexec (Instruction Execute), continued from Irma insexec
      // @  implement after separate memory and registers, to avoid re-doing


// ------ 111dddddd.dooo input/output instruction unit section

      // implement the 111dddddd.dooo input/output instructions
      //   8 operations with 128 devices

      // ooo operation, from PDP-10 Reference Manual, page 2-133 to 2-134
      // Mnemonic  Instruction  IR ooo 10 11 12  Action if no Device
      // BLKI      Block In             0  0  0  incr C(E), zero C(C(E)), *
      // DATAI     Data In              0  0  1  zero C(E) 
      // BLKO      Block Out            0  1  0  incr C(E), NOP, *
      // DATAO     Data Out             0  1  1  NOP
      // CONO      Conditions Out       1  0  0  NOP
      // CONI      Conditions In        1  0  1  zero C(E)
      // CONSZ     Condit In Skip Zero  1  1  0  SKIP
      // CONSO     Condit In Skip One   1  1  1  NOP
      // * = if left(C(E)) != 0 SKIP

      // dddddd.d address to select device used

      // so these do nearly nothing so long there is no IO device attached
      //   and are only used inside drivers, wait until implementing IO devices


// ------ we are finished with placing stuff

      System.out.println("space unused from " + PlaceCol + "," + PlaceRow);


// ------ final stuff for routing of InstBus

      // this is needed to tidy up from use of single-routing for instruct bus
      Router.route(IrmaOut[0], IrmaBus0);
      Router.route(IrmaOut[1], IrmaBus1);
      Router.route(IrmaOut[2], IrmaBus2);
      Router.route(IrmaOut[3], IrmaBus3);
      Router.route(IrmaOut[4], IrmaBus4);
      Router.route(IrmaOut[5], IrmaBus5);
      Router.route(IrmaOut[6], IrmaBus6);
      Router.route(IrmaOut[7], IrmaBus7);
      Router.route(IrmaOut[8], IrmaBus8);
      Router.route(IrmaOut[13], IrmaBus13);


// ------ debugging display of the state of all control logic outputs

      if (DebugDisp == 1) {
        for (Col = 0; Col < PlaceCol; Col++) {
          for (Row = DataBits/2; Row <= DeviceMaxRow; Row++ ) {
            // show the state of all FFs in this CLB
            Fpga.set(Row, Col, S0Clk.S0Clk, S0Clk.GCLK1);
            Fpga.set(Row, Col, S1Clk.S1Clk, S1Clk.GCLK1); } } } }


// ------ JBits finishing off section

    catch (RouteException Re) {
      System.out.println("Problem modifiying Bitstream");
      System.out.println(Re); }
    catch (ConfigurationException Ce) {
      System.out.println("Problem modifiying Bitstream");
      System.out.println(Ce); } } }
