SoftHdwPlacer.mesa
Copyright Ó 1988 by Xerox Corporation. All rights reserved.
Minsky, July 31, 1989 2:57:48 am PDT
Barth, September 6, 1989 12:41:14 pm PDT
DIRECTORY Ascii, Combinatorial, Core, CoreFlat, CoreOps, DABasics, GList, IO, PrincOps, Real, RefTab, Rope, Rsh, SoftHdwCompiler, SymTab, TerminalIO, UnixRemoteFile, UserCredentials;
SoftHdwPlacer: CEDAR PROGRAM
IMPORTS Ascii, Combinatorial, CoreFlat, CoreOps, GList, IO, Real, RefTab, Rope, Rsh, SymTab, TerminalIO, UnixRemoteFile, UserCredentials
EXPORTS SoftHdwCompiler
= BEGIN OPEN SoftHdwCompiler;
Primitives
SoftHdwCoreA, SoftHdwCoreF, and SoftHdwCoreK are not handled by the following classification.
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];
};
Flatten
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: BOOLFALSE;
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: BOOLFALSE] 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;
};
Place
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.ROPENIL;
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;
IF columnCount>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: INTSELECT t FROM
Horizontal => 0,
Vertical => grain,
ENDCASE => ERROR;
grainY: INTSELECT t FROM
Horizontal => grain,
Vertical => 0,
ENDCASE => ERROR;
pa.position ← NEW[ArrayPositionRec ← [
chip: [chipX, chipY],
minorArray: [minor.rowIndex MOD sizes.minorArray.x, (rowIndex/grainSize) MOD sizes.minorArray.y],
grain: [grainX, grainY], -- Only one dimension used at a time,
orientation: t,
type: Output]];
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.ROPENARROW[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.ROPEIO.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.ROPEIO.GetTokenRope[placeStream, IO.IDProc].token;
p: Primitive ← NARROW[SymTab.Fetch[cellNames, name].val];
left: INTIO.GetInt[placeStream];
lower: INTIO.GetInt[placeStream];
right: INTIO.GetInt[placeStream];
upper: INTIO.GetInt[placeStream];
orient: INTIO.GetInt[placeStream];
row: INTIO.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] ~ {
get rid of the ".pa" & truncate to 8 char, put in lower case.
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: ArrayPosition ← NEW[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 ← newPos;
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];
};
Initialization
LoadPrimitiveTypes[];
END.