C This file contains routines that are specific to the printed circuit
C design programs. The names of the subroutines in this file are:
C TYPE,SETB,UNSET,PUNT,PUNTB,SAVE,CONV,BACK,CHECK,SETM,CPEN,ICPEN
C SET,RESTOR,INCREM
C
C    ***** LAST UPDATE 4-09-84 *****
C
C
      SUBROUTINE ICPEN(IX,ILY,IP)
C
C THIS ROUTINE DRAWS A BASIC IC LAY-OUT. THE FIRST PEN HAS A POSITION
C INDICATED WITH GRIDCOORDINATES IX,IY. IN THE GRID EACH PEN IS SET
C WITH THREE POINTS TO IMPROVE ROUTING AROUND PENS
C
      CALL TYPE(IMX,IMY,ILY)
      IY=IABS(ILY)
      IPP=IABS(IP)
      IF(IP.GT.60) GOTO 10
      IF(IP.GT.0) IPP=IPP/2
      IFAC=6
      IF(IP.LE.0) IFAC=0
      IF(IP.GE.24) IFAC=12
      IX0=IX+IMX+IMX
      IX1=IX0+IMY*IFAC
      IY0=IY+IMY+IMY
C
C THE MINUS SIGN INDICATES A ROTATION OVER -90 DEGREES
C IF THE SIGN OF THE SECOND COORDINATE OF THE FIRST PEN IS NEGATIVE
C
      IY1=IY0-IMX*IFAC
      DO 20 J=1,IPP
      IX0=IX0-IMX-IMX
      IY0=IY0-IMY-IMY
      CALL PPEN(IX0,IY0,IMX,IMY)
C
C SET THE POINTS BENEATH THE PENS PERPENDICULAR TO THE ROW
C
      CALL SET(IX0,IY0)
      CALL SET(IX0+IMY,IY0+IMX)
      CALL SET(IX0-IMY,IY0-IMX)
C
C PREVENT DRAWING OF NOT NEEDED SECOND LINE
C
      IF(IP.LT.0) GOTO 200
      IX1=IX1-IMX-IMX
      IY1=IY1-IMY-IMY
      CALL SET(IX1,IY1)
      CALL SET(IX1+IMY,IY1+IMX)
      CALL SET(IX1-IMY,IY1-IMX)
      CALL PPEN(IX1,IY1,IMX,IMY)
  200 CONTINUE
   20 CONTINUE
      RETURN
   10 WRITE(5,1)
    1 FORMAT(' NO IC POSSIBLE WITH MORE THAN 60 PINS, TERMINATED')
      STOP
      END
      SUBROUTINE CPEN(IX,IY,NR,NPEN,IMX,IMY)
C
C THIS ROUTINE GIVES THE GRID COORDINATES OF AN IC PEN
C AS A FUNCTION OF THE IC NUMBER AND OF THE PENNUMBER.
C  PARAMETERS:        NR : NUMBER IC
C                   NPEN : NUMBER OF THE PEN
C  OUTPUT:            IX : X-GRIDCOORDINATE PEN
C                     IY : Y-GRIDCOORDINATE PEN
C                IMX,IMY : VECTOR INDICATING DIRECTION OF DRAWING
C
      LOGICAL ROW2
      INTEGER ICPOS(60,3)
      COMMON /PLDATA/ICPOS
      COMMON /NXNY/ NX,NY,NGX,NGY,ISIZE
C
C IF AN IC NUMBER IS NEGATIVE, IT IS INTERPRETED AS A DIRECT GRID
C COORDINATE OF THE X DIRECTION. NPEN IS THEN INTERPRETED AS THE Y
C COORDINATE. IMX AND IMY GIVE THE DIRECTION VECTOR OF THE ROW. THE
C DIRECTION VECTOR IS 0,0 IF THE POINT DOES NOT BELONG TO A ROW
C
      ROW2=.FALSE.
      IMX=0
      IMY=0
      IF(NR.LE.0) GOTO 10
      IX=ICPOS(NR,1)
      IY=ICPOS(NR,2)
      IP=ICPOS(NR,3)
C
C CHECK FOR HORIZONTAL OR VERTICAL TYPE
C
      CALL TYPE(IMX,IMY,IY)
      IY=IABS(IY)
      IPP=IABS(IP)
C
C CHECK FOR POSITION ON FIRST OR ON POSSIBLE SECOND ROW OF PENS
C
      IF(IP.GT.0.AND.NPEN.GT.IP/2) ROW2=.TRUE.
C
C CHECK FOR PENNUMBER LARGER THAN NUMBER OF PENS
C
      IF(NPEN.GT.IPP) GOTO 20
      IFAC=0
      IF(ROW2) IFAC=6
      IF(IP.GE.24) IFAC=IFAC*2
      IF(ROW2) NPEN=IPP-NPEN+1
      IX=IX+IMY*IFAC-(NPEN-1)*2*IMX
      IY=IY-IMX*IFAC-(NPEN-1)*2*IMY
      IF(IX.GT.NX.OR.IY.GT.NY) GOTO 50
      IF(IX.LE.0.OR.IY.LE.0) GOTO 50
      RETURN
   10 IX=-NR
      IY=NPEN
      IF(IX.GT.NX.OR.IY.GT.NY) GOTO 50
      IF(IX.LE.0.OR.IY.LE.0) GOTO 50
      RETURN
   30 WRITE(5,1)
    1 FORMAT(' PEN-NUMBER',I3,' OF IC',I3,' TOO LARGE, TERMINATED')
   20 WRITE(5,1) NPEN,NR
      STOP
   40 FORMAT(' GRIDCOORDINATES TOO LARGE OR TOO SMALL: X,Y=',I4,',',I4/
     1' IC NUMBER=',I4,' PEN:',I4)
   50 WRITE(5,40) IX,IY,NR,NPEN
      STOP
      END
      SUBROUTINE SETM(MOV)
C
C the movement MOV is applied to the running coordinates
C
      LOGICAL MOV
      COMMON /PCOORD/LX,LY
      GOTO (1,2,3,4),MOV
    1 LX=LX+1
      RETURN
    2 LY=LY+1
      RETURN
    3 LX=LX-1
      RETURN
    4 LY=LY-1
      RETURN
      END
      SUBROUTINE CHECK(MOV,COND,NAD)
C
C this subroutine checks the possibility of the move MOV, from the
C current point LX,LY. COND is returned .TRUE. iff MOV is possible
C NAD is true iff the movement gives an approach
C
      LOGICAL MOV,COND,NAD
      COMMON /PCOORD/LX,LY,LX2,LY2
      NAD=0
      GOTO(10,20,30,40),MOV
   10 CALL PUNT(LX+1,LY,COND)
      IF(LX.LT.LX2) NAD=-1
      RETURN
   20 CALL PUNT(LX,LY+1,COND)
      IF(LY.LT.LY2) NAD=-1
      RETURN
   30 CALL PUNT(LX-1,LY,COND)
      IF(LX.GT.LX2) NAD=-1
      RETURN
   40 CALL PUNT(LX,LY-1,COND)
      IF(LY.GT.LY2) NAD=-1
      RETURN
      END
      SUBROUTINE BACK(DIR)
C
C SUBROUTINE FOR THE COMPLEMENTARY ACTION OF SETM

      LOGICAL DIR
      COMMON /PCOORD/LX,LY
      GOTO (1,2,3,4),DIR
    1 LX=LX-1
      RETURN
    2 LY=LY-1
      RETURN
    3 LX=LX+1
      RETURN
    4 LY=LY+1
      RETURN
      END
      SUBROUTINE INCREM(INCX,INCY,MOV)
      LOGICAL MOV
      INCX=0
      INCY=0
      GOTO (1,2,3,4),MOV
    1 INCX=1
      RETURN
    2 INCY=1
      RETURN
    3 INCX=-1
      RETURN
    4 INCY=-1
      RETURN
      END
      SUBROUTINE CONV(IX,IY,DIR,NR,IEINDX,IEINDY)
C
C This routine uses the array dir to draw the path.
C 90' shifts are changed in two 45' turns in the plotfield
C
      LOGICAL DIR(1),MOV,optimi,NOP
C
C THE COMMON LASTMO HAS AS FUNCTION TO SUPPRES PLOTTING IN THE
C PLOTFIELD WHEN OPTIMIZING, TO SPEED UP THINGS
C
      COMMON /LASTMO/MOV,optimi
C     CALL RESGRA(2)
      NOP=.NOT.optimi
      ITX=IX
      ITY=IY
C
C SET THE PLOTTER AT THE INITIAL POINT
C
      IF(NOP) CALL JPLOT(ITX,ITY,3)
      K=1
      IF(DIR(K).EQ.0) RETURN
      CALL INCREM(INCX,INCY,DIR(K))
C
C SET THE TRACE
C
   15 ITX=ITX+INCX
      ITY=ITY+INCY
      CALL SET(ITX,ITY)
      K=K+1
C
C CHECK THE END OF THE ROUTE
C
      IF(DIR(K).LE.0) GOTO 20
C
C REPEAT IF THE DIRECTION REMAINS THE SAME
C
      IF(DIR(K-1).EQ.DIR(K)) GOTO 15
C
C CHECK IF THERE IS ONLY A CORNER AND NO SHIFT
C
      IF(DIR(K-1).EQ.DIR(K+1)) GOTO 80
C
C compute the new increment
C
      CALL INCREM(INCX,INCY,DIR(K))
C
C draw the line up to the corner
C
      IF(NOP) CALL JPLOT(ITX,ITY,2)
C
C AT LEAST ONE MOVEMENT IS LEFT
C
      GOTO 15
C
C THIS PART IS REACHED WHEN THERE ARE TWO CONSECUTIVE TURNS
C THERE ARE TWO TYPES, DEPENDING ON THE DIRECTION CHANGE
C THE EFFECT IS THAT TURNS IN OPPOSITE DIRECTION ARE SYMMETRIC
C STORE THE SHIFT MOVEMENT IN INCX2 AND INCY2
C
   80 CALL INCREM(INCX2,INCY2,DIR(K))
      IF(DIR(K).GE.3) GOTO 90
C
C THIS IS THE TYPE 1 TURN: TO THE RIGHT OR UPWARDS
C THE FIRST CORNER IS NOT ELIMINATED. THIS RESULTS IN CLOSELY
C MATCHING PATTERNS IF THE LINES ARE DRAWN BEGINNING AT THE
C ORIGIN, ESSENTIAL FOR POINT TO POINT IC CONNECTIONS
C
      IF(NOP) CALL JPLOT(ITX,ITY,2)
C
C THE OLD INCREMENT REMAINS THE SAME AFTER THE SHIFT
C
      ITX=ITX+INCX2
      ITY=ITY+INCY2
      ITX=ITX+INCX
      ITY=ITY+INCY
      K=K+2
      CALL SET(ITX,ITY)
      IF(NOP) CALL JPLOT(ITX,ITY,2)
C
C CHECK FOR ENDPOINT IMMEDIATELY AFTER THE TURN
C
      IF(DIR(K).LE.0) GOTO 70
C
C COMPUTE THE NEW INCREMENT
C
      CALL INCREM(INCX,INCY,DIR(K))
      GOTO 15
   90 CONTINUE
C
C THIS IS THE TYPE 2 TURN: TO THE LEFT OR DOWNWARDS
C THE FIRST CORNER IS ELIMINATED
C
      CALL UNSET(ITX,ITY)
      ITX=ITX-INCX
      ITY=ITY-INCY
      IF(NOP) CALL JPLOT(ITX,ITY,2)
      ITX=ITX+INCX
      ITY=ITY+INCY
      ITX=ITX+INCX2
      ITY=ITY+INCY2
C
C DRAW AND SET THE NEW POINT OF DEPARTURE
C
      IF(NOP) CALL JPLOT(ITX,ITY,2)
      K=K+1
      CALL SET(ITX,ITY)
C
C THE DIRECTION IS THE SAME AS BEFORE, RETURN TO THE STANDARD LOOP
C THERE IS AT LEAST ONE MOVEMENT TO GO
C
      GOTO 15
   20 CONTINUE
      IF(NOP) CALL JPLOT(ITX,ITY,2)
   70 CONTINUE
C     CALL RESGRA(1)
      IF((ITX.EQ.IEINDX).AND.(ITY.EQ.IEINDY)) RETURN
      WRITE(5,99) ITX,ITY,IEINDX,IEINDY
   99 FORMAT(' PROGRAM ERROR: ITX,ITY,IEINDX,IEINDY',5I4)
      RETURN
      END
      SUBROUTINE SAVE
C
C STORE ALL ELEMENTS IN A SECOND ARRAY.
C
      LOGICAL DATA(3780)
      COMMON /GRID/ DATA
      DO 1 I=1,1260
    1 DATA(I+1260)=DATA(I)
      RETURN
      END
      SUBROUTINE RESTOR
C
C RESTORE THE GRID TO THE SITUATION BEFORE A SEARCH
C
      LOGICAL DATA(1260),SAVE(1260)
      COMMON /GRID/ DATA,SAVE
      DO 1 I=1,1260
    1 DATA(I)=SAVE(I)
      RETURN
      END
      SUBROUTINE PUNTB(LX,LY,HULP)
C
C THIS ROUTINE CHECKS IF A GRIDPOINT HAS BEEN SET OR NOT IN THE
C SECOND PLANE. IT IS A COPY OF THE ROUTINE PUNT
C
      LOGICAL HULP,IHULP(8),DAT(1)
      COMMON /GRID/ DAT
      COMMON /NXNY/ NX,NY,NGX,NGY,ISIZE
      DATA IHULP/1,2,4,8,16,32,64,-128/
C
C OUTSIDE THE GRID ALL POINTS ARE CONSIDERED TO BE SET
C
      HULP=0
C
C CHECK IF GRIDPOINT INDICATED IS DEFINED
C
      IF((LX.LE. 0).OR.(LY.LE.0)) RETURN
      IF((LX.GT.NX).OR.(LY.GT.NY)) RETURN
      HULP=-1
      LYH=LY-1
      IBIT=MOD(LYH,8)+1
      IAD=LX+(LYH/8)*NX+2520
      IF(DAT(IAD).AND.IHULP(IBIT)) HULP=0
      RETURN
      END
      SUBROUTINE PUNT(LX,LY,HULP)
C
C THIS ROUTINE CHECKS IF A GRIDPOINT HAS BEEN SET OR NOT.
C PUNT IS FALSE IF A POINT HAS BEEN SET
C
      LOGICAL HULP,IHULP(8),DAT(1)
      COMMON /GRID/ DAT
      COMMON /NXNY/ NX,NY,NGX,NGY,ISIZE
      DATA IHULP/1,2,4,8,16,32,64,-128/
C
C OUTSIDE THE GRID ALL POINTS ARE CONSIDERED TO BE SET
C
      HULP=0
C
C CHECK IF GRIDPOINT INDICATED IS DEFINED
C
      IF((LX.LE. 0).OR.(LY.LE.0)) RETURN
      IF((LX.GT.NX).OR.(LY.GT.NY)) RETURN
      HULP=-1
      LYH=LY-1
      IBIT=MOD(LYH,8)+1
      IAD=LX+(LYH/8)*NX
      IF(DAT(IAD).AND.IHULP(IBIT)) HULP=0
      RETURN
      END
      SUBROUTINE UNSET(LX,LY)
C
C SUBROUTINE TO CLEAR A GRIDPOINT
C
      LOGICAL IHULP(8),DATA(1)
      COMMON /GRID/ DATA
      COMMON /NXNY/ NX,NY,NGX,NGY,ISIZE
      DATA IHULP/254,253,251,247,239,223,191,127/
      IF((LX.LE. 0).OR.(LY.LE.0)) RETURN
      IF((LX.GT.NX).OR.(LY.GT.NY)) RETURN
      LYH=LY-1
      IBIT=MOD(LYH,8)+1
      IAD=LX+(LYH/8)*NX
      DATA(IAD)=DATA(IAD).AND.IHULP(IBIT)
      RETURN
      END
      SUBROUTINE SETB(LX,LY)
C
C SUBROUTINE TO SET A GRIDPOINT IN THE SECOND AREA
C
      LOGICAL IHULP(8),DATA(1)
      COMMON /GRID/ DATA
      COMMON /NXNY/ NX,NY,NGX,NGY,ISIZE
      DATA IHULP/1,2,4,8,16,32,64,-128/
C
C IF YOU ARE SURE THAT ALL PARAMETERS ARE WITHIN BOUNDS, YOU MAY
C ELIMINATE THE TWO STATEMENTS BELOW
C
      IF((LX.LE. 0).OR.(LY.LE.0)) RETURN
      IF((LX.GT.NX).OR.(LY.GT.NY)) RETURN
      LYH=LY-1
      IBIT=MOD(LYH,8)+1
      IAD=LX+(LYH/8)*NX+2520
      DATA(IAD)=DATA(IAD).OR.IHULP(IBIT)
      RETURN
      END
      SUBROUTINE SET(LX,LY)
C
C SUBROUTINE TO SET A GRIDPOINT
C
      LOGICAL IHULP(8),DATA(1)
      COMMON /GRID/ DATA
      COMMON /NXNY/ NX,NY,NGX,NGY,ISIZE
      DATA IHULP/1,2,4,8,16,32,64,-128/
C
C IF YOU ARE SURE THAT ALL PARAMETERS ARE WITHIN BOUNDS, YOU MAY
C ELIMINATE THE TWO STATEMENTS BELOW
C
      IF((LX.LE. 0).OR.(LY.LE.0)) RETURN
      IF((LX.GT.NX).OR.(LY.GT.NY)) RETURN
C
C THE TWO CALLS TO TERM1 ARE NECESSARY WHEN USING A TERM1 GRAPHICS
C TERMINAL
C     CALL TERM1(LX*4,LY*3,3)
C     CALL TERM1(LX*4,LY*3,2)
      LYH=LY-1
      IBIT=MOD(LYH,8)+1
      IAD=LX+(LYH/8)*NX
      DATA(IAD)=DATA(IAD).OR.IHULP(IBIT)
      RETURN
      END
      SUBROUTINE TYPE(IX,IY,ISEL)
C
C THIS SUBROUTINE SELECTS BETWEEN A HORIZONTAL OR VERTICAL
C POSITIONED IC LAY OUT, USING THE SIGN OF ISEL, FOR ABSOLUTE
C POINTS THE VECTOR IS SET TO ZERO
C
      IX=0
      IY=0
      IF(IX.LT.0) RETURN
      IF(ISEL.LT.0) GOTO 20
      IY=1
      RETURN
   20 IX=1
      RETURN
      END
      RETURN
   20 IX=1
      RETURN
      END
D





