-- wiresCreate3.mesa DIRECTORY SystemDefs:FROM"SystemDefs", AltoFileDefs:FROM"AltoFileDefs", DirectoryDefs:FROM"DirectoryDefs", DisplayDefs:FROM"DisplayDefs", GraphicsDefs:FROM"GraphicsDefs", SegmentDefs:FROM"SegmentDefs", StreamDefs:FROM"StreamDefs", StringDefs:FROM"StringDefs", WiresDefs:FROM"WiresDefs", PressDefs:FROM"PressDefs", IODefs:FROM"IODefs"; WiresCreate:PROGRAM IMPORTS GraphicsDefs, PressDefs, SystemDefs, IODefs, StreamDefs, DirectoryDefs,StringDefs,WiresDefs EXPORTS WiresDefs =BEGIN OPEN WiresDefs; Error:SIGNAL=CODE; nullLoc: Location=[NULL,127,127]; circuitName: STRING_[30]; outFileName: STRING_[40]; EnumerateCircuit:PROCEDURE[call:OnI]= BEGIN i:INTEGER; FOR i IN [0..topCircuit) DO call[i]; ENDLOOP; END; --//////////////WIRE LIST Stuff/////////////// wireListArray:TYPE=ARRAY [0..maxWireNo] OF Wire; wireList:POINTER TO wireListArray_NIL; maxWireNo:INTEGER=200; topWire:INTEGER; EnumerateWires:PUBLIC PROCEDURE[call:PROCEDURE[WirePtr]]=BEGIN i:INTEGER; FOR i IN [0..topWire) DO call[@wireList[i]]; ENDLOOP; END; WireLength:PUBLIC PROCEDURE[i,j:Location] RETURNS[INTEGER]=BEGIN RETURN[ABS[i.i-j.i]+ABS[i.j-j.j]]; END; MakeWireList:PUBLIC PROCEDURE[print:BOOLEAN]= BEGIN MakeTrack[]; -- chain the transistors topWire_0; EnumerateCircuit[WireListOneCircuit]; SortWireList[]; IF print THEN PrintWireList; END; AddToWireList:PROCEDURE[w:Wire]=BEGIN wireList[topWire]_w; topWire_topWire+1; IF topWire>maxWireNo THEN Error; END; PrintWireList:PUBLIC PROCEDURE=BEGIN EnumerateWires[PrintWireListEntry]; END; PrintWireListEntry:PROCEDURE[w:WirePtr]=BEGIN OPEN IODefs; WriteString[" Circuit"]; WriteNumber[w.circuit,[10,FALSE,TRUE,3]]; WriteString[" length"]; WriteNumber[w.l,[10,FALSE,TRUE,3]]; WriteString[" from "]; WriteLocation[w.a]; WriteString[" to "]; WriteLocation[w.b]; WriteChar[CR]; END; colorStrings:ARRAY Color OF STRING=["none "," red ","green","blue "]; WriteLocation:PROCEDURE[l:Location]=BEGIN OPEN IODefs; WriteNumber[l.i,[10,FALSE,TRUE,2]]; WriteChar[',]; WriteNumber[l.j,[10,FALSE,TRUE,2]]; WriteString[SELECT l.contact FROM chanA=>" chanA", gate=>" gate", chanB=>" chanB", ENDCASE=>ERROR]; END; thisW:INTEGER; WireListOneCircuit:PROCEDURE[i:INTEGER]=BEGIN -- IF i=vdd OR i=gnd THEN RETURN; thisW_i; InitTemp[]; EnumerateTrack[i,AddToTemp]; EnumerateTemp[InitSep]; EnumerateTemp[FindAndUseNextSmallestTemp]; END; SortWireList:PROCEDURE=BEGIN i,j:INTEGER; FOR i IN [0..topWire) DO FOR j IN (i..topWire) DO IF ShorterWire[j,i] THEN BEGIN temp:Wire_wireList[i]; wireList[i]_wireList[j]; wireList[j]_temp; END; ENDLOOP; ENDLOOP; END; ShorterWire:PROCEDURE[i,j:INTEGER] RETURNS[BOOLEAN]=BEGIN wi:WirePtr_@wireList[i]; wj:WirePtr_@wireList[j]; nonGreeni:BOOLEAN_wi.a.contact=gate OR wi.b.contact=gate; nonGreenj:BOOLEAN_wj.a.contact=gate OR wj.b.contact=gate; circuiti:INTEGER_SELECT wi.circuit FROM gnd=>3,vdd=>2,ENDCASE=>1; circuitj:INTEGER_SELECT wj.circuit FROM gnd=>3,vdd=>2,ENDCASE=>1; RETURN[IF circuiti#circuitj THEN circuitimaxTemp THEN Error; END; FindAndUseNextSmallestTemp:PROCEDURE[i:INTEGER]=BEGIN bestj:INTEGER; best:INTEGER_10000; k:INTEGER=i; FindClosest:OnI=BEGIN l:INTEGER_WireLength[wireTemp[i],wireTemp[k]]; IF wireSep[k]#wireSep[i] AND ltrack[l.i][l.j].a , gate=>track[l.i][l.j].b, chanB=>track[l.i][l.j].c, ENDCASE => ERROR UNTIL l=nullLoc DO Call[l]; ENDLOOP; END; ValidCircuit:PROCEDURE[i:INTEGER] RETURNS[BOOLEAN]= BEGIN RETURN[circuits[i]#nullLoc];END; ClearCircuit:PROCEDURE[i:INTEGER]=BEGIN circuits[i]_nullLoc; END; ClearTrack:PROCEDURE[i,j:INTEGER]= BEGIN track[i][j]_[nullLoc,nullLoc,nullLoc]; END; BuildTrack:PROCEDURE[i,j:INTEGER]=BEGIN s,t,w:Circuit; [s,t,w]_grid[i][j]; IF s ~IN [0..topCircuit] OR t ~IN [0..topCircuit] OR w ~IN [0..topCircuit] THEN Error; track[i][j]_[circuits[s],circuits[t],circuits[w]]; IF t=s THEN track[i][j].b_[chanA,i,j] -- Handle pullups ELSE IF t=w THEN track[i][j].b_[chanB,i,j]; circuits[s]_[chanA,i,j]; circuits[w]_[chanB,i,j]; circuits[t]_[gate,i,j]; -- If s=t or w=t this will override. It's OK. END; --//////////////INPUT STUFF/////////////// GetInput:PUBLIC PROCEDURE[print:BOOLEAN]=BEGIN OPEN AltoFileDefs,IODefs,DirectoryDefs,StreamDefs, SegmentDefs,StringDefs; kbdStream,otherStream,currentStream: StreamHandle; pInFileFP: POINTER TO FP; inFileFP: FP; fileNameValid,readFromKbd: BOOLEAN; inFileName: STRING _ [40]; inputLine: STRING _ [80]; tempString: STRING_[10]; inputTail: SubString; ChompDecimal: PROCEDURE[src: SubString] RETURNS[INTEGER]=BEGIN OPEN StringDefs; i,j,sign,wall: INTEGER; wall _src.offset+src.length-1; -- mark the end of line i _ src.offset; j _ 0; WHILE IF i<= wall THEN src.base.text[i]=' ELSE FALSE DO i _ i+1; ENDLOOP; -- skip blanks IF src.base.text[i]='- THEN BEGIN sign_-1; i_i+1 END ELSE sign_1; IF src.base.text[i] NOT IN ['0..'9] THEN Error; WHILE IF i<= wall THEN src.base.text[i] IN ['0..'9] ELSE FALSE DO j _ 10*j+(src.base.text[i]-'0); i _ i + 1; ENDLOOP; src.length_src.length-(i-src.offset); src.offset_i; RETURN[sign*j]; END; ChompID: PROCEDURE[src: SubString, dest:STRING]=BEGIN OPEN StringDefs; i,wall: INTEGER; temp: SubString; tempD: SubStringDescriptor; temp _ @tempD; tempD.base_src.base; dest.length_0; wall _src.offset+src.length-1; -- mark the end of line i _ src.offset; WHILE IF i<= wall THEN src.base.text[i]=' ELSE FALSE DO i _ i+1; ENDLOOP; -- skip initial blanks tempD.offset_i; tempD.length_0; WHILE IF i<= wall THEN src.base.text[i]#' ELSE FALSE DO i _ i + 1; tempD.length_tempD.length+1; ENDLOOP; AppendSubString[dest,temp]; src.length_src.length-(i-src.offset); src.offset_i; END; ParseTransistor: PRIVATE PROCEDURE RETURNS[BOOLEAN]=BEGIN OPEN IODefs, StreamDefs, StringDefs; a,b,c: INTEGER; i,j: INTEGER; IF (IF currentStream#kbdStream THEN TRUE ELSE ~currentStream.endof[currentStream]) -- blame kbdStream lossage THEN BEGIN -- parse a line -- ReadLine[inputLine]; inputTail^ _SubStringDescriptor[inputLine,0,inputLine.length]; i _ ChompDecimal[inputTail]; IF i < 0 THEN RETURN[FALSE]; j _ ChompDecimal[inputTail]; IF (i NOT IN [1..side]) OR (j NOT IN [1..side]) THEN Error; ChompID[inputTail,tempString]; a _ CPTI[tempString]; ChompID[inputTail,tempString]; b _ CPTI[tempString]; ChompID[inputTail,tempString]; c _ CPTI[tempString]; grid[i][j]_[a,b,c]; END ELSE RETURN[FALSE]; RETURN[TRUE]; END; -- of ParseTransistor -- pInFileFP_@inFileFP; fileNameValid _ readFromKbd _ FALSE; UNTIL fileNameValid DO WriteString["Enter the Name of the File for Input:"]; ReadID[inFileName]; WriteChar[CR]; IF inFileName.length=0 THEN fileNameValid _ readFromKbd _ TRUE ELSE fileNameValid_DirectoryLookup[pInFileFP,inFileName,FALSE]; ENDLOOP; circuitName.length_0; WHILE circuitName.length<20 AND inFileName.text[circuitName.length]#'. DO circuitName.text[circuitName.length]_inFileName.text[circuitName.length]; circuitName.length_circuitName.length+1; ENDLOOP; currentStream _ kbdStream _ GetInputStream[]; IF readFromKbd THEN WriteLine["Input from Keyboard Requested. Proceed."] ELSE BEGIN currentStream _ otherStream _NewByteStream[inFileName,Read]; SetInputStream[otherStream]; END; -- Get first line to decide on the size -- ReadLine[inputLine]; inputTail^ _[inputLine,0,inputLine.length]; side _ ChompDecimal[inputTail]; InitAtoms[]; EnumerateGridPlusTwo[ClearGrid]; WHILE ParseTransistor[] DO NULL; ENDLOOP; IF ~readFromKbd THEN BEGIN SetInputStream[kbdStream]; otherStream.destroy[otherStream]; END; IF print THEN PrintG[]; END; --///////////////PRINTING////////////// PrintG:PUBLIC PROCEDURE=BEGIN OPEN IODefs,StreamDefs; i,j: INTEGER; output: StreamHandle; output_GetOutputStream[]; printGrid_grid; IODefs.WriteChar[CR]; -- Write a Header Line IODefs.WriteString["j(y)\i(x)"]; FOR i IN (0..side] DO IODefs.OutNumber[output,i, NumberFormat[10,FALSE,FALSE,11] ]; ENDLOOP; IODefs.WriteChar[CR]; IODefs.WriteChar[CR]; -- Write out the Grid. FOR j DECREASING IN (0..side] DO -- handle the y's IODefs.OutNumber[output,j,NumberFormat[10,FALSE,FALSE,11] ]; FOR i IN (0..side] DO -- x coordinate PrintGrid[i,j]; ENDLOOP; IODefs.WriteChar[CR]; ENDLOOP; END; PrintGSection:PUBLIC PROCEDURE=BEGIN printGrid_grid; IODefs.WriteChar[CR]; EnumerateGrid[PrintGridSection]; END; PrintGrid:PROCEDURE[i,j:INTEGER]=BEGIN OPEN IODefs; WriteChar[' ]; WriteId[printGrid[i][j].a]; WriteId[printGrid[i][j].b]; WriteId[printGrid[i][j].c]; WriteChar[' ]; END; PrintGridSection:PROCEDURE[i,j:INTEGER]=BEGIN OPEN IODefs; x:INTEGER; IF j=0 THEN WriteChar[CR]; x_MAX[FindSectionId[printGrid[i][j].a], FindSectionId[printGrid[i][j].b], FindSectionId[printGrid[i][j].c]]; WriteChar[SELECT x FROM -1=>'x,0=>'0,1=>'1,2=>'2,3=>'3,4=>'4, 5=>'5,6=>'6,7=>'7,8=>'8,ENDCASE=>'9]; END; WriteId:PROCEDURE[a:INTEGER]=BEGIN IF a=nullCircuit THEN IODefs.WriteString[" "] ELSE BEGIN IODefs.WriteChar[' ]; IODefs.WriteChar[atoms[a].a]; IODefs.WriteChar[atoms[a].b]; END; END; FindSectionId:PROCEDURE[a:INTEGER] RETURNS[INTEGER]=BEGIN IF a=gnd THEN RETURN[-1]; RETURN[SELECT atoms[a].a FROM '0,' =>0, '1=>1, '2=>2, '3=>3, '4=>4, '5=>5, '6=>6, '7=>7, '8=>8, ENDCASE=>-1]; END; --/////////////ATOMS////////////// Id:TYPE=RECORD[a,b:CHARACTER]; atoms:ARRAY[0..maxAtom+3] OF Id; maxAtom:INTEGER=500; topAtom,vdd,gnd:INTEGER; tempString:STRING_[6]; InitAtoms:PROCEDURE=BEGIN gd: STRING="gd"; vd: STRING="vd"; topAtom_0; gnd_CPTI["gd"]; vdd_CPTI["vd"]; END; CPTI:PROCEDURE[inStr:STRING] RETURNS[b:INTEGER]=BEGIN id: Id; i:INTEGER; IF inStr.length=1 THEN id _[' ,inStr.text[0]] ELSE id _[inStr.text[0],inStr.text[1]]; FOR i IN [0..topAtom) DO IF id=atoms[i] THEN RETURN[i]; ENDLOOP; atoms[topAtom]_id; topAtom_topAtom+1; IF topAtom>maxAtom THEN Error; RETURN[topAtom-1]; END; --/////////////GRAPHICS////////////// maxX,maxY: INTEGER; cornerX,cornerY: CARDINAL; halfHeight:INTEGER=12000; halfWidth:INTEGER=8000; display:BOOLEAN_TRUE; press:PressDefs.PressFileDescriptor; Screen:POINTER TO GraphicsDefs.Bitmap; OldDCB:CARDINAL; DCBHead: POINTER TO CARDINAL= LOOPHOLE[420B]; MouseButtons: POINTER TO CARDINAL = LOOPHOLE[177030B]; KeyBoard1: POINTER TO CARDINAL = LOOPHOLE[177034B]; KeyBoard2: POINTER TO CARDINAL = LOOPHOLE[177035B]; MouseX: POINTER TO CARDINAL = LOOPHOLE[426B]; MouseY: POINTER TO CARDINAL = LOOPHOLE[427B]; PrintGeometry:PUBLIC PROCEDURE[name:STRING]= BEGIN tScale: INTEGER_scale; display_FALSE; scale_scale*35; -- assumes 72+a tad screen dots per inch cornerX_35*xOrg; cornerY_35*(808-yOrg); PressDefs.InitPressFileDescriptor[@press,name]; PrintStickDiagram[]; PressDefs.ClosePressFile[@press]; display_TRUE; scale_tScale; END;--print geom scale:INTEGER; debugPrint:PUBLIC BOOLEAN_FALSE; first:PUBLIC BOOLEAN; PutBox:PUBLIC PROCEDURE[color:Color,x,y,m,n:CARDINAL]=BEGIN pressWidth: CARDINAL=20000; pressheight: CARDINAL=25000; x1,y1,w1,w2:INTEGER; IF debugPrint THEN BEGIN IODefs.WriteChar[SELECT color FROM g=>'g,r=>'r,ENDCASE=>'b]; IODefs.WriteNumber[x,[10,FALSE,TRUE,4]]; IODefs.WriteNumber[y,[10,FALSE,TRUE,4]]; IODefs.WriteNumber[m,[10,FALSE,TRUE,3]]; IODefs.WriteNumber[n,[10,FALSE,TRUE,3]]; IODefs.WriteChar[CR]; RETURN; END; IF m NOT IN [1..1000) OR n NOT IN [1..1000) THEN RETURN; IF display THEN BEGIN DisplayBox[color,x,y,m,n]; RETURN; END; IF silFile THEN BEGIN feat:SilFeature; t:[0..16)_SELECT color FROM r=>1, g=>3, b=>4, ENDCASE=>0; IF x>77777B THEN x_1; IF y>77777B THEN y_1; IF x>500 THEN x_500; IF y>silYMax THEN y_silYMax-1; feat_[macro:177777B, xUL:[0,xOrg+scale*x], yUL:[0,yOrg-scale*(y+n)], xLR:[t,xOrg+scale*(x+m)], yLR:[14,yOrg-scale*y]]; WriteSilFeature[feat]; RETURN; END; -- // Default: produce a PRESS file // SELECT color FROM r=>PressDefs.SetColor[@press,220,128,255]; g=>PressDefs.SetColor[@press,080,128,255]; b=>PressDefs.SetColor[@press,140,064,255]; none=>PressDefs.SetColor[@press,140,000,000]; ENDCASE; x1_cornerX+scale*x; y1_cornerY+scale*y; w1_scale*m; w2_scale*n; IF x1>pressWidth OR y1>pressheight THEN RETURN; IF x1+w1>pressWidth THEN w1_pressWidth-x1; IF y1+w2>pressheight THEN w2_pressheight-y1; PressDefs.PutRectangle[@press,x1,y1,w1,w2]; END;--PutBox MakeSilFile:PUBLIC PROCEDURE[s:STRING]= BEGIN OPEN StreamDefs; outputStream_NewWordStream[s,Write+Append]; outputStream.reset[outputStream]; outputStream.put[outputStream,34562B]; display_FALSE; silFile_TRUE; PrintStickDiagram[]; display_TRUE; silFile_FALSE; outputStream.destroy[outputStream]; END; silFile:PUBLIC BOOLEAN_FALSE; silYMax:CARDINAL=750; SilWord:TYPE=RECORD[a:[0..17B],b:[0..7777B]]; SilFeature:TYPE=RECORD[macro:CARDINAL,xUL,yUL,xLR,yLR:SilWord]; outputStream:StreamDefs.DiskHandle; WriteSilFeature:PROCEDURE[feat:SilFeature]=BEGIN outputStream.put[outputStream,feat.macro]; outputStream.put[outputStream,feat.xUL]; outputStream.put[outputStream,feat.yUL]; outputStream.put[outputStream,feat.xLR]; outputStream.put[outputStream,feat.yLR]; END; -- -- Graphics Display Procedures -- xOrg,yOrg: CARDINAL; --origin of the image dxMax:CARDINAL; dyMax:CARDINAL; --size of the display screen smallDisplay:BOOLEAN_FALSE; StartDisplay:PUBLIC PROCEDURE= BEGIN --initialize the screen dxMax_dyMax_IF smallDisplay THEN 256 ELSE 512; GraphicsDefs.SetDefaultBitmap[dxMax,dyMax]; OldDCB_ DCBHead^; Screen _ GraphicsDefs.TurnOnGraphics[]; END; Display:PUBLIC PROCEDURE= BEGIN GraphicsDefs.EraseArea[0,0,dxMax,dyMax]; xOrg_ 8; yOrg_ dyMax-8; scale_ MIN[dxMax/(maxX+16),dyMax/(maxY+16)]; IODefs.WriteString["scale="]; IODefs.WriteNumber[scale,[10,FALSE,TRUE,6]]; IODefs.WriteLine[""]; IF scale<1 THEN Error; PrintStickDiagram[]; END; ManipulateDisplay:PUBLIC PROCEDURE RETURNS[print:BOOLEAN]= BEGIN DO SELECT TRUE FROM BlueButton[] => Display[]; YellowButton[] => -- Reset the scale BEGIN scale_ (MouseX^-xOrg)/maxX; GraphicsDefs.EraseArea[0,0,dxMax,dyMax]; PrintStickDiagram[]; END; RedButton[] => BEGIN xOrg_MouseX^; yOrg_MouseY^; GraphicsDefs.EraseArea[0,0,dxMax,dyMax]; PrintStickDiagram[]; END; KeyBoard1^= 177757B =>BEGIN print_TRUE; EXIT; END; --p was hit KeyBoard2^= 167777B =>BEGIN print_FALSE; EXIT; END; --q was hit ENDCASE; ENDLOOP; TurnOffGraphics[]; DCBHead^_ OldDCB; []_ IODefs.ReadChar[]; END; RedButton:PROCEDURE RETURNS[BOOLEAN]= BEGIN IF (MouseButtons^ MOD 8) < 4 THEN BEGIN UNTIL (MouseButtons^ MOD 8) > 3 DO ENDLOOP; RETURN [TRUE]; END ELSE RETURN [FALSE]; END; BlueButton:PROCEDURE RETURNS[BOOLEAN]= BEGIN IF (MouseButtons^ MOD 4) < 2 THEN BEGIN UNTIL (MouseButtons^ MOD 4) > 1 DO ENDLOOP; RETURN [TRUE]; END ELSE RETURN [FALSE]; END; YellowButton:PROCEDURE RETURNS[BOOLEAN]= BEGIN IF (MouseButtons^ MOD 2) = 0 THEN BEGIN UNTIL (MouseButtons^ MOD 2) # 0 DO ENDLOOP; RETURN [TRUE]; END ELSE RETURN [FALSE]; END; TurnOffGraphics:PROCEDURE= BEGIN DCBHead^_ 0; SystemDefs.FreeSegment[Screen.bits- 4]; Screen.bits_ NIL; END; DisplayBox:PROCEDURE[color:Color,x,y,m,n:CARDINAL]=BEGIN x1,y1,x2,y2: CARDINAL; x1_xOrg+scale*x; y1_yOrg-scale*y; x2_xOrg+scale*(x+m); y2_yOrg-scale*(y+n); IF INTEGER[x1]<0 OR INTEGER[x2]<0 OR INTEGER[y1]<0 OR INTEGER[y2]<0 THEN Error; SELECT color FROM b=>GraphicsDefs.SetGrayLevel[14]; --light grey g=>GraphicsDefs.SetGrayLevel[10]; --dark grey r=>GraphicsDefs.SetGrayLevel[3]; --almost black none=>GraphicsDefs.SetGrayLevel[0];--black ENDCASE; GraphicsDefs.PutGray[x1,y1,x2,y2]; END;--DisplayBox DoOutputs: PUBLIC PROCEDURE[name:STRING,limitX,limitY:INTEGER]=BEGIN maxX_limitX; maxY_limitY; StartDisplay[]; Display[]; [] _ ManipulateDisplay[]; -- This guy sets up the graphic transformation. -- Note that it will always print. outFileName.length_0; StringDefs.AppendString[outFileName,circuitName]; StringDefs.AppendString[outFileName,".press"]; PrintGeometry[outFileName]; outFileName.length_0; StringDefs.AppendString[outFileName,circuitName]; StringDefs.AppendString[outFileName,".sil"]; MakeSilFile[outFileName]; END; END.. altoYMax:CARDINAL=1000; SilFile:TYPE=RECORD[password:CARDINAL,data:ARRAY MANY OF SilFeature]; SilFeature:TYPE=RECORD[ macro:CARDINAL, null:[4-bits], x:[12-bits], null:[4-bits], yMax:[16 bits], color:[4-bits], xMax:[12-bits], font:[4-bits], y:[12-bits]] password must be 34562B or 34563B macro must be 177777B Color:{xx,red,yellow,green,blue,xx,xx,xx,xx,orange,xx,xx,xx,xx,xx,xx} y is measured down from the upper left corner! font must be 14 (font<14 is a bcpl format string following, to be ignored) (1792)\i3I12i6I1009b14B230b12B192b13B2105b13B89b8B72b9B110b26B13376b28B26i19I35i26I29b13B26i23I166b7B303b17B441i9I57i10I21i2I70b9B181b10B182b12B182b15B104b10B305i10I42i9I42i12I42i5I71b9B