<<>> <> <> <> <> <<>> DIRECTORY Ascii, Combinatorial, Core, CoreFlat, CoreOps, DABasics, GList, IO, PrincOps, Real, RefTab, Rope, Rsh, SoftHdwBasics, SoftHdwCompiler, SymTab, TerminalIO, UnixRemoteFile, UserCredentials; SoftHdwPlacer: CEDAR PROGRAM IMPORTS Ascii, Combinatorial, CoreFlat, CoreOps, GList, IO, Real, RefTab, Rope, Rsh, SoftHdwBasics, SymTab, TerminalIO, UnixRemoteFile, UserCredentials EXPORTS SoftHdwCompiler = BEGIN OPEN SoftHdwCompiler; <> <> primitiveTypes: SymTab.Ref _ SymTab.Create[]; PrimitiveType: TYPE = {ignore, equate, and, nand, or, nor, xor2, xnor2, a22o2i, o22a2i, a21o2i, o21a2i, ff, ffEn, tstDriver}; PrimitiveSimpleType: TYPE = PrimitiveType[and..nor]; invertInputs: ARRAY PrimitiveSimpleType OF BOOL _ [FALSE, FALSE, TRUE, TRUE]; invertOutput: ARRAY PrimitiveSimpleType OF BOOL _ [TRUE, FALSE, FALSE, TRUE]; RopeList: TYPE = LIST OF Rope.ROPE; LoadPrimitiveTypes: PROC = { InsertList: PROC [ropes: RopeList, type: PrimitiveType] = { FOR rl: RopeList _ ropes, rl.rest UNTIL rl=NIL DO Insert[rl.first, type]; ENDLOOP; }; Insert: PROC [rope: Rope.ROPE, type: PrimitiveType] = { [] _ SymTab.Insert[primitiveTypes, rope, NEW[PrimitiveType _ type]]; }; InsertList[LIST["pd", "pdw", "puw"], ignore]; InsertList[LIST["inv", "invBuffer", "rec2V"], equate]; InsertList[LIST["and2", "and3", "and4"], and]; InsertList[LIST["nand2", "nand3", "nand4"], nand]; InsertList[LIST["or2", "or3", "or4"], or]; InsertList[LIST["nor2", "nor3", "nor4"], nor]; Insert["xor2", xor2]; Insert["xnor2", xnor2]; Insert["a22o2i", a22o2i]; Insert["o22a2i", o22a2i]; Insert["a21o2i", a21o2i]; Insert["o21a2i", o21a2i]; Insert["ff", ff]; Insert["ffEn", ffEn]; Insert["tstDriver", tstDriver]; }; <> TriData: TYPE = REF TriDataRec; TriDataRec: TYPE = RECORD [ count: NAT _ 0, lastInput: CoreFlat.FlatWire _ NIL, next: CoreFlat.FlatWire _ NIL]; Flatten: PUBLIC PROC [root: Core.CellType] RETURNS [flat: FlatCell] = { Equate: CoreFlat.BoundFlatCellProc = { EquateWire: PROC [from, to: Rope.ROPE] = { flatFrom: CoreFlat.FlatWire _ GetNamedWire[bindings, cell.public, flatCell, from]; flatTo: CoreFlat.FlatWire _ GetNamedWire[bindings, cell.public, flatCell, to]; [] _ RefTab.Insert[equivalence, flatFrom, flatTo]; }; name: Rope.ROPE _ CoreOps.GetCellTypeName[cell]; primitiveType: REF PrimitiveType _ NARROW[SymTab.Fetch[primitiveTypes, name].val]; IF primitiveType=NIL THEN CoreFlat.NextBoundCellType[cell, target, flatCell, instance, index, parent, flatParent, data, bindings, Equate] ELSE SELECT primitiveType^ FROM ff => EquateWire["NQ", "Q"]; equate => EquateWire["X", "I"]; tstDriver => { x: CoreFlat.FlatWire _ GetNamedWire[bindings, cell.public, flatCell, "X"]; i: CoreFlat.FlatWire _ GetNamedWire[bindings, cell.public, flatCell, "I"]; triData: TriData _ NARROW[RefTab.Fetch[triDataTable, x].val]; IF triData=NIL THEN { triData _ NEW[TriDataRec]; IF NOT RefTab.Store[triDataTable, x, triData] THEN ERROR; }; triData.lastInput _ i; triData.count _ triData.count + 1; }; ENDCASE; }; EquateTristate: RefTab.EachPairAction = { x: CoreFlat.FlatWire _ NARROW[key]; triData: TriData _ NARROW[val]; IF triData.count<2 THEN [] _ RefTab.Insert[equivalence, x, triData.lastInput] ELSE triData.next _ x; }; Flatten: CoreFlat.BoundFlatCellProc = { name: Rope.ROPE _ CoreOps.GetCellTypeName[cell]; primitiveType: REF PrimitiveType _ NARROW[SymTab.Fetch[primitiveTypes, name].val]; IF primitiveType=NIL THEN CoreFlat.NextBoundCellType[cell, target, flatCell, instance, index, parent, flatParent, data, bindings, Flatten] ELSE SELECT primitiveType^ FROM ignore, equate => NULL; and, nand, or, nor => { flatOutput: CoreFlat.FlatWire _ GetNamedWire[bindings, cell.public, flatCell, "X"]; flatInputs: PolarizedInputs _ NIL; Combinatorial.MakeCombinatorial[cell]; FOR wl: Core.Wires _ Combinatorial.GetTypedWires[cell, input], wl.rest UNTIL wl=NIL DO flatInput: CoreFlat.FlatWire _ CanonizeWire[bindings, flatCell, wl.first]; flatInputs _ CONS[[flatInput, invertInputs[primitiveType^]], flatInputs]; ENDLOOP; AddPrimitive[flatCell, flatOutput, invertOutput[primitiveType^], flatInputs]; }; xor2, xnor2 => { a: CoreFlat.FlatWire _ GetNamedWire[bindings, cell.public, flatCell, "I-A"]; b: CoreFlat.FlatWire _ GetNamedWire[bindings, cell.public, flatCell, "I-B"]; x: CoreFlat.FlatWire _ GetNamedWire[bindings, cell.public, flatCell, "X"]; i1: CoreFlat.FlatWire _ CreateWire[flatCell]; i2: CoreFlat.FlatWire _ CreateWire[flatCell]; AddPrimitive[flatCell, i1, FALSE, LIST[[a, TRUE], [b, FALSE]]]; AddPrimitive[flatCell, i2, FALSE, LIST[[a, FALSE], [b, TRUE]]]; AddPrimitive[flatCell, x, primitiveType^=xnor2, LIST[[i1, FALSE], [i2, FALSE]]]; }; a22o2i, o22a2i => { a: CoreFlat.FlatWire _ GetNamedWire[bindings, cell.public, flatCell, "A"]; b: CoreFlat.FlatWire _ GetNamedWire[bindings, cell.public, flatCell, "B"]; c: CoreFlat.FlatWire _ GetNamedWire[bindings, cell.public, flatCell, "C"]; d: CoreFlat.FlatWire _ GetNamedWire[bindings, cell.public, flatCell, "D"]; x: CoreFlat.FlatWire _ GetNamedWire[bindings, cell.public, flatCell, "X"]; i1: CoreFlat.FlatWire _ CreateWire[flatCell]; i2: CoreFlat.FlatWire _ CreateWire[flatCell]; invertInputs: BOOL _ primitiveType^=o22a2i; AddPrimitive[flatCell, i1, FALSE, LIST[[a, invertInputs], [b, invertInputs]]]; AddPrimitive[flatCell, i2, FALSE, LIST[[c, invertInputs], [d, invertInputs]]]; AddPrimitive[flatCell, x, NOT invertInputs, LIST[[i1, FALSE], [i2, FALSE]]]; }; a21o2i, o21a2i => { a: CoreFlat.FlatWire _ GetNamedWire[bindings, cell.public, flatCell, "A"]; b: CoreFlat.FlatWire _ GetNamedWire[bindings, cell.public, flatCell, "B"]; c: CoreFlat.FlatWire _ GetNamedWire[bindings, cell.public, flatCell, "C"]; x: CoreFlat.FlatWire _ GetNamedWire[bindings, cell.public, flatCell, "X"]; i: CoreFlat.FlatWire _ CreateWire[flatCell]; invert: BOOL _ primitiveType^=o21a2i; AddPrimitive[flatCell, i, FALSE, LIST[[a, invert], [b, invert]]]; AddPrimitive[flatCell, x, NOT invert, LIST[[i, FALSE], [c, NOT invert]]]; }; ff => { q: CoreFlat.FlatWire _ GetNamedWire[bindings, cell.public, flatCell, "Q"]; d: CoreFlat.FlatWire _ GetNamedWire[bindings, cell.public, flatCell, "D"]; ck: CoreFlat.FlatWire _ GetNamedWire[bindings, cell.public, flatCell, "CK"]; AddPrimitive[flatCell, q, FALSE, LIST[[d, TRUE]], ck]; }; ffEn => { en: CoreFlat.FlatWire _ GetNamedWire[bindings, cell.public, flatCell, "en"]; d: CoreFlat.FlatWire _ GetNamedWire[bindings, cell.public, flatCell, "D"]; q: CoreFlat.FlatWire _ GetNamedWire[bindings, cell.public, flatCell, "Q"]; ck: CoreFlat.FlatWire _ GetNamedWire[bindings, cell.public, flatCell, "CK"]; i1: CoreFlat.FlatWire _ CreateWire[flatCell]; i2: CoreFlat.FlatWire _ CreateWire[flatCell]; i3: CoreFlat.FlatWire _ CreateWire[flatCell]; AddPrimitive[flatCell, i1, FALSE, LIST[[en, FALSE], [d, FALSE]]]; AddPrimitive[flatCell, i2, FALSE, LIST[[en, TRUE], [q, FALSE]]]; AddPrimitive[flatCell, i3, FALSE, LIST[[i1, FALSE], [i2, FALSE]], ck]; }; tstDriver => { x: CoreFlat.FlatWire _ GetNamedWire[bindings, cell.public, flatCell, "X"]; triData: TriData _ NARROW[RefTab.Fetch[triDataTable, x].val]; IF triData.count>1 THEN { i: CoreFlat.FlatWire _ GetNamedWire[bindings, cell.public, flatCell, "I"]; en: CoreFlat.FlatWire _ GetNamedWire[bindings, cell.public, flatCell, "EN"]; i1: CoreFlat.FlatWire _ CreateWire[flatCell]; i2: CoreFlat.FlatWire _ CreateWire[flatCell]; previous: CoreFlat.FlatWire _ IF triData.count=2 THEN triData.lastInput ELSE CreateWire[flatCell]; AddPrimitive[flatCell, i1, FALSE, LIST[[en, FALSE], [i, FALSE]]]; AddPrimitive[flatCell, i2, FALSE, LIST[[en, TRUE], [previous, FALSE]]]; AddPrimitive[flatCell, triData.next, FALSE, LIST[[i1, FALSE], [i2, FALSE]]]; triData.count _ triData.count - 1; triData.next _ previous; }; }; ENDCASE => ERROR; }; FillSourcesAndSinks: RefTab.EachPairAction = { p: Primitive _ NARROW[val]; FOR index: CARDINAL IN [0..p.size) DO p[index].source _ NARROW[RefTab.Fetch[flat.wires, p[index].flatInput].val]; IF p[index].source#NIL THEN p[index].source.sinks _ CONS[p, p[index].source.sinks]; ENDLOOP; }; PeepHoleFlops: RefTab.EachPairAction = { p: Primitive _ NARROW[val]; clock: CoreFlat.FlatWire _ NIL; parity: BOOL; oldSinks: Primitives _ p.sinks; IF p.flatClock#NIL THEN RETURN; -- already used the flop FOR sinks: Primitives _ p.sinks, sinks.rest UNTIL sinks=NIL DO sink: Primitive _ sinks.first; IF NOT (sink.flatClock#NIL AND sink.size=1) THEN RETURN; IF clock#NIL THEN { IF clock#sink.flatClock THEN RETURN; IF parity#(sink.negateOutput#sink.inputs[0].negate) THEN RETURN; }; clock _ sink.flatClock; parity _ sink.negateOutput#sink.inputs[0].negate; ENDLOOP; p.flatClock _ clock; p.negateOutput _ p.negateOutput#parity; p.sinks _ NIL; FOR sinks: Primitives _ oldSinks, sinks.rest UNTIL sinks=NIL DO sink: Primitive _ sinks.first; FOR nextSinks: Primitives _ sink.sinks, nextSinks.rest UNTIL nextSinks=NIL DO nextSink: Primitive _ nextSinks.first; foundAtLeastOne: BOOL _ FALSE; FOR index: CARDINAL IN [0..nextSink.size) DO IF nextSink[index].source=sink THEN { nextSink[index].source _ p; nextSink[index].flatInput _ p.flatOutput; foundAtLeastOne _ TRUE; }; REPEAT FINISHED => IF NOT foundAtLeastOne THEN ERROR; ENDLOOP; p.sinks _ CONS[nextSink, p.sinks]; ENDLOOP; IF NOT RefTab.Delete[flat.wires, sink.flatOutput] THEN ERROR; combinedFlops _ combinedFlops+1; ENDLOOP; }; AddPrimitive: PROC [flatCell: CoreFlat.FlatCellTypeRec, output: CoreFlat.FlatWire, negateOutput: BOOL, inputs: PolarizedInputs, clock: CoreFlat.FlatWire _ NIL] = { p: Primitive; index: CARDINAL _ 0; size: CARDINAL _ 0; FOR il: PolarizedInputs _ inputs, il.rest UNTIL il=NIL DO size _ size + 1; ENDLOOP; p _ NEW[PrimitiveRec[size]]; p.flatCell _ flatCell; p.flatOutput _ FetchUnique[output]; IF clock#NIL THEN p.flatClock _ FetchUnique[clock]; p.negateOutput _ negateOutput; FOR fws: PolarizedInputs _ inputs, fws.rest UNTIL fws=NIL DO equivalent: CoreFlat.FlatWire; polarity: BOOL; [equivalent, polarity] _ GetEquivalent[fws.first.flatInput, fws.first.negate]; p.inputs[index].flatInput _ FetchUnique[equivalent]; p.inputs[index].negate _ polarity; p.inputs[index].source _ NIL; index _ index + 1; ENDLOOP; IF NOT RefTab.Insert[flat.wires, output, p] THEN { ep: Primitive _ NARROW[RefTab.Fetch[flat.wires, output].val]; IF p.flatOutput#ep.flatOutput THEN ERROR; IF p.negateOutput#ep.negateOutput THEN ERROR; IF p.size#ep.size THEN ERROR; IF p.flatClock#ep.flatClock THEN ERROR; FOR index: CARDINAL IN [0..size) DO IF p.inputs[index].flatInput#ep.inputs[index].flatInput THEN ERROR; IF p.inputs[index].negate#ep.inputs[index].negate THEN ERROR; ENDLOOP; }; }; CreateWire: PROC [flatCell: CoreFlat.FlatCellTypeRec] RETURNS [flatWire: CoreFlat.FlatWire] = { flatWire _ NEW[CoreFlat.FlatWireRec]; flatWire.flatCell _ flatCell; flatWire.wire _ CoreOps.CreateWire[]; }; GetNamedWire: PROC [bindings: CoreFlat.Bindings, public: Core.Wire, flatCell: CoreFlat.FlatCellTypeRec, name: Rope.ROPE] RETURNS [flatWire: CoreFlat.FlatWire] = { wire: Core.Wire _ CoreOps.FindWire[public, name]; IF wire=NIL THEN ERROR; flatWire _ CanonizeWire[bindings, flatCell, wire]; }; GetEquivalent: PROC [from: CoreFlat.FlatWire, initialPolarity: BOOL _ FALSE] RETURNS [to: CoreFlat.FlatWire, polarity: BOOL, clock: CoreFlat.FlatWire _ NIL] = { polarity _ initialPolarity; DO to _ from; from _ NARROW[RefTab.Fetch[equivalence, from].val]; IF from=NIL THEN EXIT; polarity _ NOT polarity; ENDLOOP; }; CanonizeWire: PROC [bindings: CoreFlat.Bindings, flatCell: CoreFlat.FlatCellTypeRec, wire: Core.Wire] RETURNS [flatWire: CoreFlat.FlatWire] = { flatWire _ NARROW[RefTab.Fetch[bindings, wire].val]; IF flatWire=NIL THEN { flatWire _ NEW[CoreFlat.FlatWireRec]; flatWire.flatCell _ flatCell; flatWire.wire _ wire; }; }; FetchUnique: PROC [from: CoreFlat.FlatWire] RETURNS [to: CoreFlat.FlatWire] = { to _ NARROW[RefTab.Fetch[unique, from].val]; IF to=NIL THEN { IF NOT RefTab.Insert[unique, from, from] THEN ERROR; to _ from; }; }; unique: RefTab.Ref _ RefTab.Create[hash: CoreFlat.FlatWireHash, equal: CoreFlat.FlatWireEqual]; equivalence: RefTab.Ref _ RefTab.Create[hash: CoreFlat.FlatWireHash, equal: CoreFlat.FlatWireEqual]; triDataTable: RefTab.Ref _ RefTab.Create[hash: CoreFlat.FlatWireHash, equal: CoreFlat.FlatWireEqual]; combinedFlops: INT _ 0; flat _ NEW[FlatCellRec]; flat.root _ root; flat.wires _ RefTab.Create[hash: CoreFlat.FlatWireHash, equal: CoreFlat.FlatWireEqual]; Equate[root]; [] _ RefTab.Pairs[triDataTable, EquateTristate]; Flatten[root]; [] _ RefTab.Pairs[flat.wires, FillSourcesAndSinks]; [] _ RefTab.Pairs[flat.wires, PeepHoleFlops]; TerminalIO.PutF["\nCombined flops: %g", IO.int[combinedFlops]]; flat.root _ root; }; <> fileHost: Rope.ROPE _ "palain-NFS"; cpuHost: Rope.ROPE _ "lyrane"; serverDir: Rope.ROPE _ "/timberwolf/"; remoteServer: Rope.ROPE _ "/palain/"; twCmd: Rope.ROPE _ "/usr/datools/TimberWolfSC "; fileMode: UnixRemoteFile.Mode _ 0666B; lastMsg: Rope.ROPE _ NIL; Place: PROC [flatCell: FlatCell, sizes: ArrayPosition, attPerCell: INT _ 50] RETURNS [placement: Placement] = { grainPositions: GrainPositions _ TimberWolf[flatCell, sizes, attPerCell]; placement _ HayBaler[flatCell, sizes, grainPositions]; }; GrainDimension: PROC [size: ArrayPosition] RETURNS [coord: INT] ~ { coord _ SELECT size.orientation FROM Horizontal => size.grain.y, Vertical => size.grain.x, ENDCASE => ERROR; }; HayBaler: PUBLIC PROC [flatCell: FlatCell, sizes: ArrayPosition, grainPositions: GrainPositions] RETURNS [placement: Placement] = { grainSize: INT _ GrainDimension[sizes]; placement _ NEW[PlacementRec]; placement.maxChip _ [0, 0]; placement.positions _ RefTab.Create[]; FOR rowIndex: CARDINAL _ 0, rowIndex+grainSize UNTIL rowIndex>=grainPositions.size DO rowMinors: MinorArrays _ NIL; lastRowMinor: MinorArrays _ NIL; columnCount: CARDINAL _ 0; maxRowSize: CARDINAL _ 0; FOR subRowIndex: DABasics.Number IN [0..grainSize) DO y: CARDINAL _ rowIndex+subRowIndex; IF y>=grainPositions.size THEN EXIT; maxRowSize _ MAX[maxRowSize, grainPositions[y].size]; ENDLOOP; FOR columnIndex: CARDINAL IN [0..maxRowSize) DO FOR subRowIndex: DABasics.Number IN [0..grainSize) DO y: CARDINAL _ rowIndex+subRowIndex; pa: PrimitiveAssignment; t: Orientation; grain: DABasics.Number; minor: MinorArray; p: Primitive; IF y>=grainPositions.size THEN EXIT; IF columnIndex>=grainPositions[y].size THEN LOOP; p _ grainPositions[y][columnIndex]; pa _ NEW[PrimitiveAssignmentRec[p.size]]; [t, grain, minor] _ GrainFirstFit[grainSize, p, rowMinors, pa]; IF minor=NIL THEN { nt: Orientation; minor _ NEW[MinorArrayRec]; minor.rowIndex _ columnCount; columnCount _ columnCount + 1; FOR o: Orientation IN Orientation DO minor.primitives[o] _ NEW[GrainSequenceRec[grainSize]]; FOR index: DABasics.Number IN [0..grainSize) DO minor.primitives[o][index].output _ NIL; minor.primitives[o][index].input _ NIL; minor.primitives[o][index].inputIndex _ 0; ENDLOOP; ENDLOOP; t _ Horizontal; grain _ 0; IF rowMinors=NIL THEN { rowMinors _ LIST[minor]; lastRowMinor _ rowMinors; } ELSE { lastRowMinor.rest _ LIST[minor]; lastRowMinor _ lastRowMinor.rest; <4 THEN rowMinors _ rowMinors.rest;>> }; minor.primitives[t][grain].output _ p; nt _ IF t=Vertical THEN Horizontal ELSE Vertical; FOR index: CARDINAL IN [0..p.size) DO minor.primitives[nt][index].input _ p; minor.primitives[nt][index].inputIndex _ index; pa[index] _ index; ENDLOOP; }; { chipX: INT _ minor.rowIndex/sizes.minorArray.x; chipY: INT _ (rowIndex/grainSize)/sizes.minorArray.y; grainX: INT _ SELECT t FROM Horizontal => 0, Vertical => grain, ENDCASE => ERROR; grainY: INT _ SELECT t FROM Horizontal => grain, Vertical => 0, ENDCASE => ERROR; pa.position _ SoftHdwBasics.CreateArrayPosition[Output, t, [grainX, grainY], [minor.rowIndex MOD sizes.minorArray.x, (rowIndex/grainSize) MOD sizes.minorArray.y], [chipX, chipY]]; IF NOT RefTab.Insert[placement.positions, p, pa] THEN ERROR; IF chipX>=sizes.chip.x OR chipY>=sizes.chip.y THEN ERROR; placement.maxChip.x _ MAX[chipX, placement.maxChip.x]; placement.maxChip.y _ MAX[chipY, placement.maxChip.y]; }; ENDLOOP; ENDLOOP; ENDLOOP; placement.flatCell _ flatCell; placement.sizes _ sizes; }; GrainFirstFit: PROC [grainSize: DABasics.Number, p: Primitive, minors: MinorArrays, pa: PrimitiveAssignment] RETURNS [t: Orientation, grain: DABasics.Number, minor: MinorArray] = { FOR lm: MinorArrays _ minors, lm.rest UNTIL lm=NIL DO minor _ lm.first; FOR t IN Orientation DO nt: Orientation _ IF t=Vertical THEN Horizontal ELSE Vertical; FOR grain IN [0..grainSize) DO IF minor.primitives[t][grain].output=NIL THEN { klip: InputPositions _ NIL; FOR inputIndex: CARDINAL IN [0..p.size) DO FOR searchIndex: DABasics.Number IN [0..grainSize) DO searchGrain: GrainRec _ minor.primitives[nt][searchIndex]; IF searchGrain.input=NIL OR (searchGrain.input[searchGrain.inputIndex].flatInput = p[inputIndex].flatInput AND searchGrain.input[searchGrain.inputIndex].negate = p[inputIndex].negate) THEN { IF searchGrain.input=NIL THEN klip _ CONS[searchIndex, klip]; minor.primitives[nt][searchIndex].input _ p; minor.primitives[nt][searchIndex].inputIndex _ inputIndex; pa[inputIndex] _ searchIndex; EXIT; }; REPEAT FINISHED => { FOR lip: InputPositions _ klip, lip.rest UNTIL lip=NIL DO minor.primitives[nt][lip.first].input _ NIL; ENDLOOP; GOTO IncompatibleInputs; }; ENDLOOP; REPEAT FINISHED => { minor.primitives[t][grain].output _ p; RETURN; }; ENDLOOP; }; REPEAT IncompatibleInputs => NULL; ENDLOOP; ENDLOOP; ENDLOOP; minor _ NIL; }; TimberWolf: PUBLIC PROC [flatCell: FlatCell, sizes: ArrayPosition, attPerCell: INT _ 50] RETURNS [grainPositions: GrainPositions] = { rootName, directoryPath, filePathName: Rope.ROPE; cellNames: SymTab.Ref; [rootName, directoryPath, filePathName, cellNames] _ WriteTimberWolf[flatCell, sizes, attPerCell]; lastMsg _ Rsh.RSH[ remoteMachine: cpuHost, command: Rope.Cat["cd ", directoryPath, ";", twCmd, rootName], in: IO.noInputStream, out: TerminalIO.TOS[]]; grainPositions _ ReadTimberWolf[filePathName, cellNames]; }; WriteTimberWolf: PROC [flatCell: FlatCell, sizes: ArrayPosition, attPerCell: INT] RETURNS [rootName, directoryPath, filePathName: Rope.ROPE, cellNames: SymTab.Ref] = { grainSize: INT _ GrainDimension[sizes]; rowCount: INT _ (grainSize*Real.Round[Real.SqRt[RefTab.GetSize[flatCell.wires]]])/2; blockRadius: INT _ grainSize+2; server: UnixRemoteFile.UnixServerHandle _ UnixRemoteFile.CreateHandle[fileHost]; rootName _ CoreOps.GetCellTypeName[flatCell.root]; directoryPath _ Rope.Cat[remoteServer, GuessUnixName[], serverDir]; filePathName _ Rope.Cat[directoryPath, rootName]; { -- first the net file netStream: IO.STREAM _ UnixRemoteFile.OpenWriteStream[server, [Rope.Cat[filePathName, ".net"]], fileMode]; IO.Put[netStream, IO.rope["allnets HVweights 1.0 1.0\l"]]; IO.Flush[netStream]; IO.Close[netStream]; }; { -- next the parameter file parStream: IO.STREAM _ UnixRemoteFile.OpenWriteStream[server, [Rope.Cat[filePathName, ".par"]], fileMode]; IO.Put[parStream, IO.rope["att.per.cell "], IO.int[attPerCell], IO.rope["\l"]]; IO.Put[parStream, IO.rope["rowSep 0.0\l"]]; IO.Put[parStream, IO.rope["indent 1.0\l"]]; IO.Flush[parStream]; IO.Close[parStream]; }; { -- next the row definitions blkStream: IO.STREAM _ UnixRemoteFile.OpenWriteStream[server, [Rope.Cat[filePathName, ".blk"]], fileMode]; FOR row: INT IN [1 .. rowCount] DO IO.Put[blkStream, IO.rope["block height "], IO.int[2*blockRadius], IO.rope[" class 1 nofeeds\l"]]; ENDLOOP; IO.Flush[blkStream]; IO.Close[blkStream]; }; { -- finally the connectivity EmitPrimitive: RefTab.EachPairAction = { WritePin: PROC [pinName: Rope.ROPE, signal: CoreFlat.FlatWire, position: INT] = { micronPosition: INT _ 2*position-blockRadius+1; signalName: Rope.ROPE _ NARROW[RefTab.Fetch[wireToName, signal].val]; IF signalName=NIL THEN { signalName _ IO.PutFR["w%g", IO.int[wireCount]]; IF NOT RefTab.Insert[wireToName, signal, signalName] THEN ERROR; wireCount _ wireCount + 1; }; IO.PutF[celStream, " pin name %g signal %g %g %g\l", IO.rope[pinName], IO.rope[signalName], IO.int[micronPosition], IO.int[blockRadius]]; IO.PutF[celStream, " equiv name %g %g %g\l", IO.rope[pinName], IO.int[micronPosition], IO.int[-blockRadius]]; }; p: Primitive _ NARROW[val]; cellName: Rope.ROPE _ IO.PutFR["c%g", IO.int[cellCount]]; IF NOT SymTab.Insert[cellNames, cellName, p] THEN ERROR; IO.PutF[celStream, "cell %g %g\l", IO.int[cellCount], IO.rope[cellName]]; IO.PutRope[celStream, " nomirror\l"]; IO.PutF[celStream, " left -%g right %g bottom -%g top %g\l", IO.int[blockRadius], IO.int[blockRadius], IO.int[blockRadius], IO.int[blockRadius]]; WritePin["out", p.flatOutput, blockRadius-1]; FOR index: CARDINAL IN [0..p.size) DO WritePin[inputNames[index], p.inputs[index].flatInput, index]; ENDLOOP; cellCount _ cellCount + 1; }; celStream: IO.STREAM _ UnixRemoteFile.OpenWriteStream[server, [Rope.Cat[filePathName, ".cel"]], fileMode]; cellCount: INT _ 0; wireCount: INT _ 0; wireToName: RefTab.Ref _ RefTab.Create[hash: CoreFlat.FlatWireHash, equal: CoreFlat.FlatWireEqual]; inputNames: RopeSequence _ NEW[RopeSequenceRec[grainSize]]; FOR index: INT IN [0..grainSize) DO inputNames[index] _ IO.PutFR["in%g", IO.int[index]]; ENDLOOP; cellNames _ SymTab.Create[]; [] _ RefTab.Pairs[flatCell.wires, EmitPrimitive]; IO.Flush[celStream]; IO.Close[celStream]; UnixRemoteFile.DestroyHandle[server]; }; }; ReadTimberWolf: PROC [filePathName: Rope.ROPE, cellNames: SymTab.Ref] RETURNS [grainPositions: GrainPositions] = { ConsColumnPrimitives: PROC = { IF columnPrimitives#NIL THEN { rowPrimitives _ CONS[columnPrimitives, rowPrimitives]; columnPrimitives _ NIL; rowCount _ rowCount + 1; }; }; server: UnixRemoteFile.UnixServerHandle _ UnixRemoteFile.CreateHandle[fileHost]; placeStream: IO.STREAM _ UnixRemoteFile.OpenReadStream[server, [Rope.Cat[filePathName, ".pl1"]]]; rowCount, lastRow: INT _ 0; rowPrimitives: LIST OF Primitives _ NIL; columnPrimitives: Primitives _ NIL; [] _ IO.SkipWhitespace[placeStream]; WHILE ~IO.EndOf[placeStream] DO name: Rope.ROPE _ IO.GetTokenRope[placeStream, IO.IDProc].token; p: Primitive _ NARROW[SymTab.Fetch[cellNames, name].val]; left: INT _ IO.GetInt[placeStream]; lower: INT _ IO.GetInt[placeStream]; right: INT _ IO.GetInt[placeStream]; upper: INT _ IO.GetInt[placeStream]; orient: INT _ IO.GetInt[placeStream]; row: INT _ IO.GetInt[placeStream]; [] _ IO.SkipWhitespace[placeStream]; IF row#lastRow THEN ConsColumnPrimitives[]; columnPrimitives _ CONS[p, columnPrimitives]; lastRow _ row; ENDLOOP; ConsColumnPrimitives[]; IO.Close[placeStream]; UnixRemoteFile.DestroyHandle[server]; grainPositions _ NEW[GrainPositionsRec[rowCount]]; FOR rowIndex: INT DECREASING IN [0..rowCount) DO columnPrimitives: Primitives _ rowPrimitives.first; columnCount: CARDINAL _ GList.Length[columnPrimitives]; grainPositions[rowIndex] _ NEW[GrainRowRec[columnCount]]; FOR columnIndex: CARDINAL DECREASING IN [0..columnCount) DO grainPositions[rowIndex][columnIndex] _ columnPrimitives.first; columnPrimitives _ columnPrimitives.rest; ENDLOOP; IF columnPrimitives#NIL THEN ERROR; rowPrimitives _ rowPrimitives.rest; ENDLOOP; IF rowPrimitives#NIL THEN ERROR; }; GuessUnixName: PROC RETURNS [unixName: Rope.ROPE] ~ { <> unixName _ UserCredentials.Get[].name; unixName _ Rope.Substr[unixName, 0, MIN[8, Rope.Index[unixName, 0, "."]]]; unixName _ Rope.Translate[base: unixName, translator: MyLower]; }; MyLower: Rope.TranslatorType ~ {RETURN[Ascii.Lower[old]]}; AddChannels: PUBLIC PROC [old: Placement, channelSize: NAT _ 1] RETURNS [new: Placement] = { Adjust: RefTab.EachPairAction = { p: Primitive _ NARROW[key]; oldPA: PrimitiveAssignment _ NARROW[val]; newPA: PrimitiveAssignment _ NEW[PrimitiveAssignmentRec[oldPA.size]]; oldPos: ArrayPosition _ oldPA.position; newPos: ArrayPositionRec; newX: INT _ channelSize + (1+channelSize)*(oldPos.minorArray.x + oldPos.chip.x*old.sizes.minorArray.x); newY: INT _ channelSize + (1+channelSize)*(oldPos.minorArray.y + oldPos.chip.y*old.sizes.minorArray.y); newPos _ oldPos^; newPos.minorArray.x _ newX MOD old.sizes.minorArray.x; newPos.chip.x _ newX / old.sizes.minorArray.x; newPos.minorArray.y _ newY MOD old.sizes.minorArray.y; newPos.chip.y _ newY / old.sizes.minorArray.y; IF newPos.chip.x>=old.sizes.chip.x OR newPos.chip.y>=old.sizes.chip.y THEN ERROR; new.maxChip.x _ MAX[newPos.chip.x, new.maxChip.x]; new.maxChip.y _ MAX[newPos.chip.y, new.maxChip.y]; newPA.position _ SoftHdwBasics.CreateArrayPosition[newPos.type, newPos.orientation, newPos.grain, newPos.minorArray, newPos.chip]; FOR index: CARDINAL IN [0..oldPA.size) DO newPA[index] _ oldPA[index]; ENDLOOP; IF NOT RefTab.Insert[new.positions, p, newPA] THEN ERROR; }; new _ NEW[PlacementRec]; new^ _ old^; new.positions _ RefTab.Create[]; [] _ RefTab.Pairs[old.positions, Adjust]; }; <> LoadPrimitiveTypes[]; END.