-- a program to run within Chipmonk

-- last modified by Petit, October 8, 1981  2:20 PM
-- written by Petit, October 5, 1981  6:45 PM

DIRECTORY
  ppddefs,
  ppdefs,
  rldefs,
  ppdddefs,
  StringDefs;

rlgate: PROGRAM
  IMPORTS ppddefs, ppdefs, ppdddefs, StringDefs EXPORTS rldefs =
  BEGIN OPEN ppddefs, rldefs, ppdefs, ppdddefs, StringDefs;


-- gate creation routines:

parma:ARRAY parmaCnt OF POINTER TO gateTypeRecord ←
	[@gtr1,@gtr2,@gtr3,@gtr4,@gtr5];

currentParameters:POINTER TO gateTypeRecord;
currentParamNumber:parmaCnt;

gtr1:gateTypeRecord ← [
	wWid:4,
	mwWid:8,
	norWireOff:2,
	standWidth:16,
	strtY:30,
	invOff:10,
	putWid:4,
	putLen:4,
	makAnd:mAnd1,
	makPu:mPu1,
	makConts:mCont1,
	makTopWire:mTW1,
	calcMaxy:mCalc1
];
gtr2:gateTypeRecord ← [
	wWid:4,
	mwWid:8,
	norWireOff:2,
	standWidth:32,
	strtY:30,
	invOff:10,
	putWid:8,
	putLen:4,
	makAnd:mAnd1,
	makPu:mPu1,
	makConts:mCont1,
	makTopWire:mTW1,
	calcMaxy:mCalc1
];
gtr3:gateTypeRecord ← [
	wWid:4,
	mwWid:8,
	norWireOff:2,
	standWidth:48,
	strtY:30,
	invOff:10,
	putWid:12,
	putLen:4,
	makAnd:mAnd1,
	makPu:mPu1,
	makConts:mCont1,
	makTopWire:mTW1,
	calcMaxy:mCalc1
];
gtr4:gateTypeRecord ← [
	wWid:4,
	mwWid:8,
	norWireOff:2,
	standWidth:8,
	strtY:28, -- putLen+20
	invOff:6,
	putWid:4,
	putLen:8,
	makAnd:mAnd1,
	makPu:mPu2,
	makConts:mCont1,
	makTopWire:mTW1,
	calcMaxy:mCalc1
];
gtr5:gateTypeRecord ← [
	wWid:4,
	mwWid:8,
	norWireOff:2,
	standWidth:4,
	strtY:36, -- putLen+20
	invOff:6,
	putWid:4,
	putLen:16,
	makAnd:mAnd1,
	makPu:mPu2,
	makConts:mCont1,
	makTopWire:mTW1,
	calcMaxy:mCalc1
];

gateList:LONG POINTER TO gate←NIL;

getGate:PUBLIC PROCEDURE[gc:LONG POINTER TO gateCharac,parms:INTEGER]
	RETURNS[gat:LONG POINTER TO gate] =
    BEGIN
	gat←gateList;
	WHILE gat#NIL DO
	  IF gat.parmNum = parms AND gcSame[gc,gat.charac] THEN RETURN;
	  gat←gat.nxt;
	ENDLOOP;
	gat←makeGate[gc,parms];
	gat.nxt←gateList;
	gateList←gat;
    END;
gcSame:PROCEDURE[a,b:LONG POINTER TO gateCharac] RETURNS[BOOLEAN] =
    BEGIN
	IF a.inCnt#b.inCnt OR a.norCnt#b.norCnt THEN RETURN[FALSE];
	FOR i:INTEGER IN [0..a.norCnt) DO
	  IF a.ands[i] # b.ands[i] THEN RETURN[FALSE];
	ENDLOOP;
	RETURN[TRUE];
    END;

makeGate:PROCEDURE[gc:LONG POINTER TO gateCharac,parms:parmaCnt]
	RETURNS[gat:LONG POINTER TO gate] =
    BEGIN
	OPEN currentParameters;
	lp:LONG POINTER TO list;--←NIL;
	ob:LONG POINTER TO object;
	cp:LONG POINTER TO cList;
	x:locNum;
	y:locNum;
	i,inIdx,acnt,mx,maxy:INTEGER;
	topx1,topx2,dx,width,botx:INTEGER;
	currentParameters←parma[parms];
	currentParamNumber←parms;
	gat←GetSpace[SIZE[gate[gc.inCnt]]];
	gat.inCnt←gc.inCnt;
	gat.nxt←NIL;
	gat.charac←gc;
	gat.parmNum←currentParamNumber;
	mx←0;
	y←strtY;
	maxy←y+calcMaxy[gc];
	x←-2;
	[dx,,lp]←makConts[0,gc.ands[0],x,y,maxy,NIL,gc.inCnt];
	x←x+dx;
	botx←0;
	inIdx←0;
	FOR i IN [0..gc.norCnt) DO
	  acnt←gc.ands[i];
	  [dx,width,lp]←makAnd[acnt,x,y,lp,inIdx,gat,gc.inCnt];
	  inIdx←inIdx+acnt;
	  mx←MAX[mx,x+width];
	  x←x+dx;
	  IF i=0 THEN topx1←x+norWireOff;
	  IF i MOD 2 = 0 THEN
	    BEGIN
		topx2←x+norWireOff+wWid;
		[dx,lp]←makTopWire[x+norWireOff,lp,gc.inCnt];
		x←x+dx;
		mx←MAX[mx,topx2];
	    END
	 ELSE
	    BEGIN
		[dx,width,lp]←makConts[acnt,(IF i=gc.norCnt-1 THEN 0
			ELSE gc.ands[i+1]),x,y,maxy,lp,gc.inCnt];
		botx←x+2;
		mx←MAX[mx,x+width];
		x←x+dx;
	    END;
	ENDLOOP;
	[dx,lp]←makPu[topx1,topx2,mx,lp,gat,gc.inCnt];
	mx←MAX[mx,dx];
	IF botx>0 THEN
	    BEGIN
		lp←insertList[lp,makeList[makeWire[botx+mwWid,6,met]
			,0,maxy-2,2,0]];
	    END;
	gat.gnd←[botx+2,maxy-2];
	ob←makeCell[mx,maxy+4,0,lp];
	cp←alocCList[];
	cp.ob←ob;
	cp.name←makeCellName[gc];
	ob.returnable←FALSE;
	gat.cell←cp;
	cp.nxt←cellList;
	cellList←cp;
    END;

makeCellName:PROCEDURE[gc:LONG POINTER TO gateCharac] RETURNS[s:STRING] =
    BEGIN
	ss:STRING←[101];
	ss.length←0;
	AppendString[ss,"GATE"];
	AppendDecimal[ss,currentParamNumber];
	AppendChar[ss,'-];
	AppendDecimal[ss,gc.norCnt];
	FOR i:INTEGER IN [0..gc.norCnt) DO
	  IF ss.length>92 THEN BEGIN AppendString[ss,".ETC"];EXIT;END;
	  IF gc.ands[i]>1 THEN
	    BEGIN
		AppendChar[ss,'-];
		AppendChar[ss,('A+i)];
		AppendDecimal[ss,gc.ands[i]];
	    END;
	ENDLOOP;
	s←newString[ss];
    END;

mAnd1:mAndProcd =
    BEGIN
	OPEN currentParameters;
	i:INTEGER;
	ll:LONG POINTER TO list;
	dx←0;
	gat.firstInTopAvail←TRUE;
	IF totIns=1 THEN
	    BEGIN
		y←y+invOff;
		ll←makeList[makeXstr[standWidth,cLength],x,y-4,0,0];
		lp←insertList[lp,ll];
		gat.ins[0]←[x,y];
		gat.firstInTop←[x-2,y+4];
		gat.rSpac←2;
		gat.lSpac←3;
		dx←standWidth+2;
		nl←lp;
		wid←dx+6;
		RETURN;
	    END;
	IF inputs=0 THEN gat.lSpac←gat.rSpac←1;
	FOR i IN [0..aCnt) DO
	  ll←makeList[makeXstr[standWidth*aCnt,cLength],x+dx,y,2,0];
	  lp←insertList[lp,ll];
	  gat.ins[inputs+i]←[x+dx+4+cLength/2,y+standWidth*aCnt+6];
	  IF inputs+i=0 THEN gat.firstInTop←[x+dx+4+cLength/2,y+2];
	  dx←dx+8;
	ENDLOOP;
	nl←lp;
	wid←dx+4;
    END;
mPu1:mPuProcd =
    BEGIN
	OPEN currentParameters;
	lpp:LONG POINTER TO list;
	wid:INTEGER←putWid+12;
	t:INTEGER←x2-wid;
	ox:INTEGER←mx+gat.rSpac*2;
	y:INTEGER←16;
	IF totIns=1 THEN
	    BEGIN
		x2←x1;
		x1←x1-standWidth;
		t←x2-wid;
		y←y+invOff;
	    END;
	IF t<x1 THEN t←MIN[x1,mx-wid];
	IF t<0 THEN t←0;
	x1←MIN[t,x1];
	x2←MAX[x2,t+wid];
	lpp←makeList[makeWire[x2-x1,wWid,dif],x1,y+8,2,0];
	lp←insertList[lp,lpp];
	lpp←makeList[makeButcon[],t,y,0,0];
	lp←insertList[lp,lpp];
	lpp←makeList[makeDifcon[MAX[8,putWid]],t+12,0,2,0];
	lp←insertList[lp,lpp];
	dx←MAX[t+wid+4,x2];
	IF t+wid+2<ox THEN
	    BEGIN
		dx←MAX[ox+2,dx];
		lpp←makeList[makeWire[ox-t-wid,4,pol],t+wid+2,y+2,2,0];
		lp←insertList[lp,lpp];
		gat.out←[ox+2,y+2];
	    END
	 ELSE
	    BEGIN
		gat.out←[t+wid+4,y+2];
	    END;
	lpp←makeList[makeWire[y-6,putWid,dif],t+12,6,0,0];
	lp←insertList[lp,lpp];
	lpp←makeList[makeXstr[putWid,putLen,TRUE],t+8,y-2,0,0];
	nl←insertList[lp,lpp];
    END;
mPu2:mPuProcd =
    BEGIN
	OPEN currentParameters;
	lpp:LONG POINTER TO list;
	wid:INTEGER=10;
	t:INTEGER←x2-wid;
	ox:INTEGER←mx+gat.rSpac*2;
	y:INTEGER←strtY-12;
	IF totIns=1 THEN
	    BEGIN
		x2←x1;
		x1←x1-standWidth;
		t←x2-wid;
		y←y+invOff;
	    END;
	IF t<x1-2 THEN t←MIN[x1-2,mx-wid];
	IF t<0 THEN t←0;
	x1←MIN[t+2,x1];
	x2←MAX[x2,t+wid];
	lpp←makeList[makeWire[x2-x1,wWid,dif],x1,y+6,2,0];
	lp←insertList[lp,lpp];
	lpp←makeList[makeDifcon[8],t+2,0,2,0];
	lp←insertList[lp,lpp];
	dx←MAX[t+wid+2,x2];
	IF t+wid<ox THEN
	    BEGIN
		dx←MAX[ox+2,dx];
		lpp←makeList[makeWire[ox-t-wid,4,pol],t+wid+2,y,2,0];
		lp←insertList[lp,lpp];
		gat.out←[ox+2,y];
	    END
	 ELSE
	    BEGIN
		gat.out←[t+wid+4,y];
	    END;
	lpp←makeList[makePullup[putWid,putLen],t,
		(IF totIns>1 THEN 8 ELSE invOff+8),0,0];
	nl←insertList[lp,lpp];
	IF totIns=1 THEN
	    BEGIN
		lpp←makeList[makeWire[invOff+4,putWid,dif],t+4,6,0,0];
		nl←insertList[nl,lpp];
	    END;
    END;
mTW1:mTWProcd =
    BEGIN
	IF totIns=1 THEN {dx←10;nl←lp;RETURN};
	nl←makeList[makeWire[14,currentParameters.wWid,dif],
		x,currentParameters.strtY-6,0,0];
	nl←insertList[lp,nl];
	dx←currentParameters.wWid;
    END;
mCont1:mContProcd =
    BEGIN
	OPEN currentParameters;
	lh,rh,ny,c:INTEGER;
	lh←standWidth*lCnt;
	rh←standWidth*rCnt;
	IF totIns=1 THEN
	    BEGIN
		x←x+6;
		y←y-2+invOff;
		ny←y + 8;
		nl←makeList[makeDifcon[8],x,ny,0,0];
		lp←insertList[lp,nl];
		nl←makeList[makeWire[lh,4,dif],x,ny+2,2,0];
		lp←insertList[lp,nl];
		IF maxy-ny>2 THEN
		    BEGIN
			nl←makeList[makeWire[maxy-ny+2,mwWid,met],x,ny+2,0,0];
			nl←insertList[lp,nl];
		    END;
		dx←2;
		wid←2;
		RETURN;
	    END;
	x←x+2;
	c←IF MAX[rh,lh]<12 THEN 1 ELSE (MAX[rh,lh]-8)/16+1;
	y←y+4;
	ny←y + ((MAX[rh,lh]-8)MOD 16);
	FOR i:INTEGER IN [0..c) DO
	  nl←makeList[makeDifcon[8],x,ny+i*16,0,0];
	  lp←insertList[lp,nl];
	ENDLOOP;
	nl←makeList[makeWire[MAX[rh,lh],4,dif],x+2,y,0,0];
	lp←insertList[lp,nl];
	nl←makeList[makeWire[maxy-ny+4,mwWid,met],x,ny,0,0];
	nl←insertList[lp,nl];
	dx←8;
	wid←10;
    END;
mCalc1:calcMyProcd =
    BEGIN
	my←0;
	FOR i:INTEGER IN [0..gc.norCnt) DO
	  my←MAX[my,gc.ands[i]];
	ENDLOOP;
	my←my*currentParameters.standWidth+8;
    END;


  END. -- of rlgate