SoftHdwFlat.mesa
Copyright Ó 1988 by Xerox Corporation. All rights reserved.
Barth, January 1, 1989 2:21:09 pm PST
DIRECTORY Ascii, CD, CDBasics, CDCurves, CDInstances, CDOps, CDProperties, CDRects, Combinatorial, Core, CoreFlat, CoreOps, DABasics, GList, IO, PrincOps, PW, Real, RefTab, Rope, Rsh, SymTab, TerminalIO, UnixRemoteFile, UserCredentials, VM;
SoftHdwFlat: CEDAR PROGRAM
IMPORTS Ascii, CD, CDBasics, CDCurves, CDInstances, CDOps, CDProperties, CDRects, Combinatorial, CoreFlat, CoreOps, GList, IO, PW, Real, RefTab, Rope, Rsh, SymTab, TerminalIO, UnixRemoteFile, UserCredentials, VM
EXPORTS
= BEGIN
Types
FlatCell: TYPE = REF FlatCellRec;
FlatCellRec: TYPE = RECORD [
root: Core.CellType,
wires: RefTab.Ref]; -- maps CoreFlat.FlatWire to Primitive
Primitives: TYPE = LIST OF Primitive;
Primitive: TYPE = REF PrimitiveRec;
PrimitiveRec: TYPE = RECORD [
flatClock: CoreFlat.FlatWire, -- not NIL => sequential element
flatCell: CoreFlat.FlatCellTypeRec,
flatOutput: CoreFlat.FlatWire,
negateOutput: BOOL,
sinks: Primitives ← NIL, -- NIL => primary output or unused
inputs: SEQUENCE size: CARDINAL OF PolarizedInputRec];
PolarizedInputs: TYPE = LIST OF PolarizedInputRec;
PolarizedInputRec: TYPE = RECORD [
flatInput: CoreFlat.FlatWire,
negate: BOOL,
source: Primitive ← NIL]; -- NIL => primary input
Placement: TYPE = REF PlacementRec;
PlacementRec: TYPE = RECORD [
flatCell: FlatCell,
sizes: ArrayPosition,
maxChip: DABasics.Position,
positions: RefTab.Ref]; -- maps Primitive to PrimitiveAssignment
PrimitiveAssignment: TYPE = REF PrimitiveAssignmentRec;
PrimitiveAssignmentRec: TYPE = RECORD [
position: ArrayPosition,
inputIndicies: SEQUENCE size: CARDINAL OF CARDINAL];
ArrayPositions: TYPE = LIST OF ArrayPositionRec;
ArrayPosition: TYPE = REF ArrayPositionRec;
ArrayPositionRec: TYPE = RECORD [
chip: DABasics.Position,
minor: DABasics.Position,
grain: DABasics.Number,
orientation: Orientation,
type: NodeType];
Orientation: TYPE = {vertical, horizontal};
Surface: TYPE = REF SurfaceRec;
SurfaceRec: TYPE = RECORD [
sizes: ArrayPosition,
nodes: ARRAY NodeType OF NodeArrays];
NodeArrays: TYPE = RECORD [
base: NodeArray,
maxNeighbors: DABasics.Number,
nodeSize: DABasics.Number,
grainSize: DABasics.Number,
orientSize: DABasics.Number,
chipXSize: DABasics.Number,
chipYSize: DABasics.Number,
minorXSize: DABasics.Number];
NodeType: TYPE = {interchipVertical, interchipHorizontal, longVertical, longHorizontal, short, output};
NodeArray: TYPE = RECORD [
pages: INT,
base: LONG POINTER];
{short, output} => ARRAY [grain, chip.x, chip.y, orientation, minor.x, minor.y] OF NodeRec
{longVertical} => ARRAY [grain, chip.x, chip.y, minor.x] OF NodeRec
{longHorizontal} => ARRAY [grain, chip.x, chip.y, minor.y] OF NodeRec
{interchipVertical} => ARRAY [grain, chip.x, chip.y, minor.x] OF NodeRec
{interchipHorizontal} => ARRAY [grain, chip.x, chip.y, minor.y] OF NodeRec
NodeLabel: TYPE = LONG POINTER; -- really CoreFlat.FlatWire
Nodes: TYPE = LIST OF Node;
Node: TYPE = LONG POINTER TO NodeRec;
NodeRec: TYPE = RECORD [
fifoNext: Node,
position: ArrayPositionRec,
label: NodeLabel,
back: Node,
size: CARDINAL,
neighbors: SEQUENCE COMPUTED CARDINAL OF Node];
A Path is a tree representation of a route.
Path: TYPE = REF PathRec;
PathRec: TYPE = RECORD [
subPaths: SubPaths ← NIL,
path: SEQUENCE size: CARDINAL OF ArrayPositionRec];
SubPaths: TYPE = REF SubPathsRec;
SubPathsRec: TYPE = RECORD [
paths: SEQUENCE size: CARDINAL OF Path];
NetEndList: TYPE = LIST OF NetEnds;
NetEnds: TYPE = REF NetEndsRec;
NetEndsRec: TYPE = RECORD [
source: Node ← NIL,
destinations: Nodes ← NIL];
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: PROC [root: Core.CellType] RETURNS [flat: FlatCell] = {
Equate: CoreFlat.BoundFlatCellProc = {
EquateWire: PROC [from, to: Rope.ROPE] = {
fromWire: Core.Wire ← CoreOps.FindWire[cell.public, from];
flatFrom: CoreFlat.FlatWire ← CanonizeWire[bindings, flatCell, fromWire];
toWire: Core.Wire ← CoreOps.FindWire[cell.public, to];
flatTo: CoreFlat.FlatWire ← CanonizeWire[bindings, flatCell, toWire];
IF fromWire=NIL OR toWire=NIL THEN ERROR;
[] ← 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 = {
AddPrimitive: PROC [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.flatClock ← IF clock=NIL THEN NIL ELSE FetchUnique[clock];
p.flatCell ← flatCell;
p.flatOutput ← FetchUnique[output];
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.flatClock#ep.flatClock THEN ERROR;
IF p.flatOutput#ep.flatOutput THEN ERROR;
IF p.negateOutput#ep.negateOutput THEN ERROR;
IF p.size#ep.size 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;
};
};
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[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[i1, FALSE, LIST[[a, TRUE], [b, FALSE]]];
AddPrimitive[i2, FALSE, LIST[[a, FALSE], [b, TRUE]]];
AddPrimitive[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[i1, FALSE, LIST[[a, invertInputs], [b, invertInputs]]];
AddPrimitive[i2, FALSE, LIST[[c, invertInputs], [d, invertInputs]]];
AddPrimitive[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[i, FALSE, LIST[[a, invert], [b, invert]]];
AddPrimitive[x, NOT invert, LIST[[i, FALSE], [c, NOT invert]]];
};
ff => {
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"];
AddPrimitive[q, FALSE, LIST[[d, FALSE]], 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[i1, FALSE, LIST[[en, FALSE], [d, FALSE]]];
AddPrimitive[i2, FALSE, LIST[[en, TRUE], [q, FALSE]]];
AddPrimitive[i3, FALSE, LIST[[i1, FALSE], [i2, FALSE]]];
AddPrimitive[q, FALSE, LIST[[i3, 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[i1, FALSE, LIST[[en, FALSE], [i, FALSE]]];
AddPrimitive[i2, FALSE, LIST[[en, TRUE], [previous, FALSE]]];
AddPrimitive[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;
};
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];
flatWire ← CanonizeWire[bindings, flatCell, wire];
};
GetEquivalent: PROC [from: CoreFlat.FlatWire, initialPolarity: BOOLFALSE] RETURNS [to: CoreFlat.FlatWire, polarity: BOOL] = {
polarity ← initialPolarity;
WHILE from#NIL DO
to ← from;
polarity ← NOT polarity;
from ← NARROW[RefTab.Fetch[equivalence, from].val]
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];
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];
flat.root ← root;
};
Place
fileHost: Rope.ROPE ← "palain-NFS";
cpuHost: Rope.ROPE ← "palain";
serverDir: Rope.ROPE ← "/timberwolf/";
remoteServer: Rope.ROPE ← "/palain/";
twCmd: Rope.ROPE ← "/usr/datools/TimberWolfSCrsh ";
fileMode: UnixRemoteFile.Mode ← 0666B;
lastMsg: Rope.ROPENIL;
RopeSequence: TYPE = REF RopeSequenceRec;
RopeSequenceRec: TYPE = RECORD [ropes: SEQUENCE size: CARDINAL OF Rope.ROPE];
GrainPositions: TYPE = REF GrainPositionsRec;
GrainPositionsRec: TYPE = RECORD [rows: SEQUENCE size: CARDINAL OF GrainRow];
GrainRow: TYPE = REF GrainRowRec;
GrainRowRec: TYPE = RECORD [columns: SEQUENCE size: CARDINAL OF Primitive];
MinorArrays: TYPE = LIST OF MinorArray;
MinorArray: TYPE = REF MinorArrayRec;
MinorArrayRec: TYPE = RECORD [
rowIndex: CARDINAL ← 0,
primitives: ARRAY Orientation OF GrainSequence ← ALL[NIL]];
GrainSequence: TYPE = REF GrainSequenceRec;
GrainSequenceRec: TYPE = RECORD [
elements: SEQUENCE size: CARDINAL OF GrainRec];
GrainRec: TYPE = RECORD [
input: Primitive,
inputIndex: CARDINAL,
output: Primitive];
InputPositions: TYPE = LIST OF CARDINAL;
Place: PROC [flatCell: FlatCell, sizes: ArrayPosition, attPerCell: INT ← 50] RETURNS [placement: Placement] = {
grainPositions: GrainPositions ← TimberWolf[flatCell, sizes, attPerCell];
placement ← HayBaler[flatCell, sizes, grainPositions];
};
HayBaler: PROC [flatCell: FlatCell, sizes: ArrayPosition, grainPositions: GrainPositions] RETURNS [placement: Placement] = {
placement ← NEW[PlacementRec];
placement.maxChip ← [0, 0];
placement.positions ← RefTab.Create[];
FOR rowIndex: CARDINAL ← 0, rowIndex+sizes.grain UNTIL rowIndex>=grainPositions.size DO
rowMinors: MinorArrays ← NIL;
lastRowMinor: MinorArrays ← NIL;
columnCount: CARDINAL ← 0;
maxRowSize: CARDINAL ← 0;
FOR subRowIndex: DABasics.Number IN [0..sizes.grain) 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..sizes.grain) 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[sizes.grain, 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[sizes.grain]];
FOR index: DABasics.Number IN [0..sizes.grain) 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.minor.x;
chipY: INT ← (rowIndex/sizes.grain)/sizes.minor.y;
pa.position ← NEW[ArrayPositionRec ← [
chip: [chipX, chipY],
minor: [minor.rowIndex MOD sizes.minor.x, (rowIndex/sizes.grain) MOD sizes.minor.y],
grain: grain,
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: PROC [flatCell: FlatCell, sizes: ArrayPosition, attPerCell: INT ← 50] RETURNS [grainPositions: GrainPositions] = {
rootName, filePathName: Rope.ROPE;
cellNames: SymTab.Ref;
[rootName, filePathName, cellNames] ← WriteTimberWolf[flatCell, sizes, attPerCell];
lastMsg ← Rsh.RSH[
remoteMachine: cpuHost,
command: Rope.Cat[twCmd, rootName],
in: IO.noInputStream, out: TerminalIO.TOS[]];
grainPositions ← ReadTimberWolf[filePathName, cellNames];
};
WriteTimberWolf: PROC [flatCell: FlatCell, sizes: ArrayPosition, attPerCell: INT] RETURNS [rootName, filePathName: Rope.ROPE, cellNames: SymTab.Ref] = {
rowCount: INT ← (sizes.grain*Real.Round[Real.SqRt[RefTab.GetSize[flatCell.wires]]])/2;
blockRadius: INT ← sizes.grain+2;
server: UnixRemoteFile.UnixServerHandle ← UnixRemoteFile.CreateHandle[fileHost];
rootName ← CoreOps.GetCellTypeName[flatCell.root];
filePathName ← Rope.Cat[Rope.Cat[remoteServer, GuessUnixName[], serverDir], 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];
IF p.flatClock#NIL THEN WritePin["clock", p.flatClock, blockRadius-2];
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[sizes.grain]];
FOR index: INT IN [0..sizes.grain) 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: 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.minor.x + oldPos.chip.x*old.sizes.minor.x);
newY: INT ← channelSize + (1+channelSize)*(oldPos.minor.y + oldPos.chip.y*old.sizes.minor.y);
newPos^ ← oldPos^;
newPos.minor.x ← newX MOD old.sizes.minor.x;
newPos.chip.x ← newX / old.sizes.minor.x;
newPos.minor.y ← newY MOD old.sizes.minor.y;
newPos.chip.y ← newY / old.sizes.minor.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];
};
Route
CreateSurfaceAndRoute: PROC [placement: Placement] RETURNS [route: RefTab.Ref, incompleteNetEnds: NetEndList, incomplete: INT ← 0] = {
sizes: ArrayPosition ← NEW[ArrayPositionRec];
surface: Surface;
sizes^ ← placement.sizes^;
sizes.chip.x ← placement.maxChip.x + 1;
sizes.chip.y ← placement.maxChip.y + 1;
surface ← CreateSurface[sizes];
[route, incompleteNetEnds] ← RouteSurface[placement, surface];
FOR nel: NetEndList ← incompleteNetEnds, nel.rest UNTIL nel=NIL DO
incomplete ← incomplete + 1;
ENDLOOP;
};
FreeSurface: PROC [surface: Surface] = {
FOR nt: NodeType IN NodeType DO
FreeNodeArray[surface.nodes[nt].base];
ENDLOOP;
};
CreateSurface: PROC [sizes: ArrayPosition] RETURNS [surface: Surface] = {
position: ArrayPosition ← NEW[ArrayPositionRec];
surface ← NEW[SurfaceRec];
FOR nt: NodeType IN NodeType DO
surface.nodes[nt].maxNeighbors ← SELECT nt FROM
longVertical => sizes.minor.y+2,
longHorizontal => sizes.minor.x+2,
short => 3+sizes.grain,
output, interchipVertical, interchipHorizontal => 4,
ENDCASE => ERROR;
surface.nodes[nt].nodeSize ← SIZE[NodeRec]+(surface.nodes[nt].maxNeighbors*SIZE[Node]);
surface.nodes[nt].grainSize ← surface.nodes[nt].nodeSize*sizes.grain;
surface.nodes[nt].chipXSize ← surface.nodes[nt].grainSize*sizes.chip.x;
surface.nodes[nt].chipYSize ← surface.nodes[nt].chipXSize*sizes.chip.y;
surface.nodes[nt].orientSize ← surface.nodes[nt].chipYSize*2;
surface.nodes[nt].minorXSize ← surface.nodes[nt].orientSize*sizes.minor.x;
surface.nodes[nt].base ← AllocateNodeArray[SELECT nt FROM
interchipVertical, longVertical => surface.nodes[nt].chipYSize*sizes.minor.x,
interchipHorizontal, longHorizontal => surface.nodes[nt].chipYSize*sizes.minor.y,
short, output => surface.nodes[nt].minorXSize*sizes.minor.y,
ENDCASE => ERROR];
ENDLOOP;
surface.sizes ← sizes;
EnumerateNodes[surface, position, InitializeNode];
position.orientation ← vertical;
FOR chipX: INT IN [0..sizes.chip.x) DO
position.chip.x ← chipX;
FOR chipY: INT IN [0..sizes.chip.y) DO
position.chip.y ← chipY;
FOR minorX: INT IN [0..sizes.minor.x) DO
position.minor.x ← minorX;
FOR grain: INT IN [0..sizes.grain) DO
long: Node;
position.grain ← grain;
position.type ← longVertical;
long ← PositionToNode[surface, position];
IF chipY<sizes.chip.y-1 THEN {
interchip, other: Node;
position.type ← interchipVertical;
interchip ← PositionToNode[surface, position];
CreateArc[surface, interchip, long];
CreateArc[surface, long, interchip];
position.minor.y ← sizes.minor.y-1;
position.type ← short;
other ← PositionToNode[surface, position];
CreateArc[surface, interchip, other];
CreateArc[surface, other, interchip];
position.type ← output;
other ← PositionToNode[surface, position];
CreateArc[surface, other, interchip];
position.chip.y ← chipY+1;
position.type ← longVertical;
other ← PositionToNode[surface, position];
CreateArc[surface, interchip, other];
CreateArc[surface, other, interchip];
position.minor.y ← 0;
position.type ← short;
other ← PositionToNode[surface, position];
CreateArc[surface, interchip, other];
CreateArc[surface, other, interchip];
position.type ← output;
other ← PositionToNode[surface, position];
CreateArc[surface, other, interchip];
position.chip.y ← chipY;
};
FOR minorY: INT IN [0..sizes.minor.y) DO
short, output: Node;
position.minor.y ← minorY;
position.type ← short;
short ← PositionToNode[surface, position];
position.type ← output;
output ← PositionToNode[surface, position];
CreateArc[surface, short, long];
CreateArc[surface, long, short];
CreateArc[surface, output, short];
CreateArc[surface, output, long];
IF minorY>0 THEN {
neighbor: Node;
position.minor.y ← minorY - 1;
position.type ← short;
neighbor ← PositionToNode[surface, position];
CreateArc[surface, neighbor, short];
position.type ← output;
neighbor ← PositionToNode[surface, position];
CreateArc[surface, neighbor, short];
};
IF minorY<sizes.minor.y-1 THEN {
neighbor: Node;
position.minor.y ← minorY + 1;
position.type ← short;
neighbor ← PositionToNode[surface, position];
CreateArc[surface, neighbor, short];
position.type ← output;
neighbor ← PositionToNode[surface, position];
CreateArc[surface, neighbor, short];
};
ENDLOOP;
ENDLOOP;
ENDLOOP;
ENDLOOP;
ENDLOOP;
position.orientation ← horizontal;
FOR chipX: INT IN [0..sizes.chip.x) DO
position.chip.x ← chipX;
FOR chipY: INT IN [0..sizes.chip.y) DO
position.chip.y ← chipY;
FOR minorY: INT IN [0..sizes.minor.y) DO
position.minor.y ← minorY;
FOR grain: INT IN [0..sizes.grain) DO
long: Node;
position.grain ← grain;
position.type ← longHorizontal;
long ← PositionToNode[surface, position];
IF chipX<sizes.chip.x-1 THEN {
interchip, other: Node;
position.type ← interchipHorizontal;
interchip ← PositionToNode[surface, position];
CreateArc[surface, interchip, long];
CreateArc[surface, long, interchip];
position.minor.x ← sizes.minor.x-1;
position.type ← short;
other ← PositionToNode[surface, position];
CreateArc[surface, interchip, other];
CreateArc[surface, other, interchip];
position.type ← output;
other ← PositionToNode[surface, position];
CreateArc[surface, other, interchip];
position.chip.x ← chipX+1;
position.type ← longHorizontal;
other ← PositionToNode[surface, position];
CreateArc[surface, interchip, other];
CreateArc[surface, other, interchip];
position.minor.x ← 0;
position.type ← short;
other ← PositionToNode[surface, position];
CreateArc[surface, interchip, other];
CreateArc[surface, other, interchip];
position.type ← output;
other ← PositionToNode[surface, position];
CreateArc[surface, other, interchip];
position.chip.x ← chipX;
};
FOR minorX: INT IN [0..sizes.minor.x) DO
short, output: Node;
position.minor.x ← minorX;
position.type ← short;
short ← PositionToNode[surface, position];
position.type ← output;
output ← PositionToNode[surface, position];
CreateArc[surface, short, long];
CreateArc[surface, long, short];
CreateArc[surface, output, short];
CreateArc[surface, output, long];
IF minorX>0 THEN {
neighbor: Node;
position.minor.x ← minorX - 1;
position.type ← short;
neighbor ← PositionToNode[surface, position];
CreateArc[surface, neighbor, short];
position.type ← output;
neighbor ← PositionToNode[surface, position];
CreateArc[surface, neighbor, short];
};
IF minorX<sizes.minor.x-1 THEN {
neighbor: Node;
position.minor.x ← minorX + 1;
position.type ← short;
neighbor ← PositionToNode[surface, position];
CreateArc[surface, neighbor, short];
position.type ← output;
neighbor ← PositionToNode[surface, position];
CreateArc[surface, neighbor, short];
};
ENDLOOP;
ENDLOOP;
ENDLOOP;
ENDLOOP;
ENDLOOP;
FOR chipX: INT IN [0..sizes.chip.x) DO
position.chip.x ← chipX;
FOR chipY: INT IN [0..sizes.chip.y) DO
position.chip.y ← chipY;
FOR minorX: INT IN [0..sizes.minor.x) DO
position.minor.x ← minorX;
FOR minorY: INT IN [0..sizes.minor.y) DO
position.minor.y ← minorY;
FOR grainX: INT IN [0..sizes.grain) DO
verticalShort, verticalOutput: Node;
position.orientation ← vertical;
position.grain ← grainX;
position.type ← short;
verticalShort ← PositionToNode[surface, position];
position.type ← output;
verticalOutput ← PositionToNode[surface, position];
FOR grainY: INT IN [0..sizes.grain) DO
horizontalShort, horizontalOutput: Node;
position.orientation ← horizontal;
position.grain ← grainY;
position.type ← short;
horizontalShort ← PositionToNode[surface, position];
position.type ← output;
horizontalOutput ← PositionToNode[surface, position];
CreateArc[surface, verticalShort, horizontalOutput];
CreateArc[surface, horizontalShort, verticalOutput];
ENDLOOP;
ENDLOOP;
ENDLOOP;
ENDLOOP;
ENDLOOP;
ENDLOOP;
};
AllocateNodeArray: PROC [words: INT] RETURNS [array: NodeArray] = {
pageCount: INTVM.PagesForWords[words];
interval: VM.Interval ← VM.SimpleAllocate[pageCount];
IF interval.count#pageCount THEN ERROR;
array.pages ← pageCount;
array.base ← VM.AddressForPageNumber[interval.page];
};
FreeNodeArray: PROC [array: NodeArray] = TRUSTED {
VM.Free[[LOOPHOLE[array.base, INT]/PrincOps.wordsPerPage, array.pages]];
};
InitializeNode: EachNodeProc = TRUSTED {
node: Node ← PositionToNode[surface, position];
node.position ← position^;
node.label ← NIL;
node.back ← NIL;
node.size ← surface.nodes[position.type].maxNeighbors;
FOR index: INT IN [0..node.size) DO
node.neighbors[index] ← NIL;
ENDLOOP;
};
CreateArc: PROC [surface: Surface, source: Node, destination: Node] = TRUSTED {
FOR nodeIndex: INT IN [0..source.size) DO
IF source[nodeIndex]=NIL THEN {
source[nodeIndex] ← destination;
RETURN;
};
ENDLOOP;
ERROR;
};
PositionToNode: PROC [surface: Surface, position: ArrayPosition] RETURNS [node: Node] = {
type: NodeType ← position.type;
nodeAddress: LONG CARDINALLOOPHOLE[surface.nodes[type].base.base];
nodeAddress ← nodeAddress +
surface.nodes[type].nodeSize*position.grain +
surface.nodes[type].grainSize*position.chip.x +
surface.nodes[type].chipXSize*position.chip.y;
nodeAddress ← nodeAddress + (SELECT type FROM
short, output => surface.nodes[type].chipYSize*(IF position.orientation=vertical THEN 1 ELSE 0) + surface.nodes[type].orientSize*position.minor.x + surface.nodes[type].minorXSize* position.minor.y,
interchipVertical, longVertical => surface.nodes[type].chipYSize*position.minor.x,
interchipHorizontal, longHorizontal => surface.nodes[type].chipYSize*position.minor.y,
ENDCASE => ERROR);
node ← LOOPHOLE[nodeAddress];
};
maxNodeCount: NAT ← 0;
route maps CoreFlat.FlatWire to Path
RouteSurface: PROC [placement: Placement, surface: Surface] RETURNS [route: RefTab.Ref, incomplete: NetEndList] = {
EachPrimitivePosition: RefTab.EachPairAction = TRUSTED {
p: Primitive ← NARROW[key];
pa: PrimitiveAssignment ← NARROW[val];
node: Node ← PositionToNode[surface, pa.position];
ne: NetEnds ← FetchNetEnds[p.flatOutput];
node.label ← LOOPHOLE[p.flatOutput];
IF ne.source#NIL THEN ERROR;
ne.source ← node;
position^ ← pa.position^;
position.orientation ← IF position.orientation=vertical THEN horizontal ELSE vertical;
position.type ← short;
FOR index: CARDINAL IN [0..p.size) DO
label: NodeLabel ← LOOPHOLE[p[index].flatInput];
ne: NetEnds ← FetchNetEnds[p[index].flatInput];
position.grain ← pa[index];
node ← PositionToNode[surface, position];
IF node.label#NIL AND node.label#label THEN ERROR;
node.label ← label;
ne.destinations ← CONS[node, ne.destinations];
ENDLOOP;
};
RouteWire: RefTab.EachPairAction = TRUSTED {
wire: CoreFlat.FlatWire ← NARROW[key];
ne: NetEnds ← NARROW[val];
sourceDestinations: Nodes ← ne.destinations;
IF sourceDestinations#NIL THEN {
seed: Node;
destinations: Nodes ← NIL;
IF ne.source=NIL THEN seed ← sourceDestinations.first
ELSE seed ← ne.source;
FOR il: Nodes ← sourceDestinations, il.rest UNTIL il=NIL DO
IF il.first#seed THEN destinations ← CONS[il.first, destinations];
ENDLOOP;
IF destinations#NIL THEN {
somePath: BOOLFALSE;
label: NodeLabel ← seed.label;
fifoFirst: Node ← seed;
fifoLast: Node ← fifoFirst;
fifoLast.fifoNext ← NIL;
UNTIL fifoFirst=NIL DO
trail: Nodes ← NIL;
FOR il: Nodes ← destinations, il.rest UNTIL il=NIL DO
IF il.first.back=NIL THEN trail ← il
ELSE {
nodeCount: NAT ← 0;
assign: Node ← il.first;
UNTIL assign=NIL DO
assign.label ← label;
assign ← assign.back;
nodeCount ← nodeCount + 1;
ENDLOOP;
maxNodeCount ← MAX[maxNodeCount, nodeCount];
IF trail=NIL THEN destinations ← il.rest
ELSE trail.rest ← il.rest;
somePath ← TRUE;
};
ENDLOOP;
IF destinations=NIL THEN EXIT;
{
current: Node ← fifoFirst;
fifoFirst ← fifoFirst.fifoNext;
IF fifoFirst=NIL THEN fifoLast ← NIL;
FOR ni: CARDINAL IN [0..current.size) DO
neighbor: Node ← current[ni];
IF neighbor=NIL THEN EXIT;
IF (neighbor.label=NIL OR (neighbor#seed AND neighbor.label=label)) AND neighbor.back=NIL THEN {
neighbor.back ← current;
IF fifoLast=NIL THEN {
fifoFirst ← neighbor;
fifoLast ← fifoFirst;
}
ELSE {
fifoLast.fifoNext ← neighbor;
fifoLast ← fifoLast.fifoNext;
};
fifoLast.fifoNext ← NIL;
};
ENDLOOP;
};
REPEAT FINISHED => incomplete ← CONS[NEW[NetEndsRec ← [source: seed, destinations: destinations]], incomplete];
ENDLOOP;
IF somePath THEN IF NOT RefTab.Insert[route, wire, MakePath[seed]] THEN ERROR;
CleanUpBackPointers[seed];
};
};
};
FetchNetEnds: PROC [flatWire: CoreFlat.FlatWire] RETURNS [ne: NetEnds] = {
ne ← NARROW[RefTab.Fetch[netEnds, flatWire].val];
IF ne=NIL THEN {
ne ← NEW[NetEndsRec];
IF NOT RefTab.Insert[netEnds, flatWire, ne] THEN ERROR;
};
};
netEnds: RefTab.Ref ← RefTab.Create[hash: CoreFlat.FlatWireHash, equal: CoreFlat.FlatWireEqual];
position: ArrayPosition ← NEW[ArrayPositionRec];
EnumerateNodes[surface, position, ScrubNode];
[] ← RefTab.Pairs[placement.positions, EachPrimitivePosition];
route ← RefTab.Create[hash: CoreFlat.FlatWireHash, equal: CoreFlat.FlatWireEqual];
[] ← RefTab.Pairs[netEnds, RouteWire];
};
ScrubNode: EachNodeProc = TRUSTED {
node: Node ← PositionToNode[surface, position];
node.label ← NIL;
node.back ← NIL;
};
CleanUpBackPointers: PROC [seed: Node] = TRUSTED {
fifoFirst: Node ← seed;
fifoLast: Node ← fifoFirst;
fifoLast.fifoNext ← NIL;
UNTIL fifoFirst=NIL DO
current: Node ← fifoFirst;
fifoFirst ← fifoFirst.fifoNext;
IF fifoFirst=NIL THEN fifoLast ← NIL;
FOR ni: CARDINAL IN [0..current.size) DO
neighbor: Node ← current[ni];
IF neighbor=NIL THEN EXIT;
IF neighbor.back#NIL THEN {
neighbor.back ← NIL;
IF fifoLast=NIL THEN {
fifoFirst ← neighbor;
fifoLast ← fifoFirst;
}
ELSE {
fifoLast.fifoNext ← neighbor;
fifoLast ← fifoLast.fifoNext;
};
fifoLast.fifoNext ← NIL;
};
ENDLOOP;
ENDLOOP;
};
MakePath: PROC [current: Node] RETURNS [path: Path] = TRUSTED {
ListToSequence: PROC RETURNS [path: Path] = TRUSTED {
size: CARDINAL ← 0;
FOR pl: ArrayPositions ← positions, pl.rest UNTIL pl=NIL DO
size ← size + 1;
ENDLOOP;
path ← NEW[PathRec[size]];
FOR index: CARDINAL DECREASING IN [0..size) DO
path[index] ← positions.first;
positions ← positions.rest;
ENDLOOP;
IF positions#NIL THEN ERROR;
};
positions: ArrayPositions ← LIST[current.position];
DO
neighbors: Nodes ← NIL;
neighborCount: CARDINAL ← 0;
FOR ni: CARDINAL IN [0..current.size) DO
neighbor: Node ← current[ni];
IF neighbor=NIL THEN EXIT;
IF neighbor.back=current AND neighbor.label=current.label THEN {
neighbors ← CONS[neighbor, neighbors];
neighborCount ← neighborCount + 1;
};
ENDLOOP;
SELECT TRUE FROM
neighborCount=0 => { -- tree leaf
path ← ListToSequence[];
EXIT;
};
neighborCount=1 => { -- branch continues
current ← neighbors.first;
positions ← CONS[current.position, positions];
};
ENDCASE => { -- tree branches
subPaths: SubPaths ← NEW[SubPathsRec[neighborCount]];
path ← ListToSequence[];
path.subPaths ← subPaths;
FOR index: CARDINAL DECREASING IN [0..neighborCount) DO
subPaths[index] ← MakePath[neighbors.first];
neighbors ← neighbors.rest;
ENDLOOP;
EXIT;
};
ENDLOOP;
};
EachNodeProc: TYPE = PROC [surface: Surface, position: ArrayPosition];
EnumerateNodes: PROC [surface: Surface, position: ArrayPosition, eachNode: EachNodeProc] = {
FOR chipX: INT IN [0..surface.sizes.chip.x) DO
position.chip.x ← chipX;
FOR chipY: INT IN [0..surface.sizes.chip.y) DO
position.chip.y ← chipY;
FOR minorX: INT IN [0..surface.sizes.minor.x) DO
position.minor.x ← minorX;
FOR minorY: INT IN [0..surface.sizes.minor.y) DO
position.minor.y ← minorY;
FOR o: Orientation IN Orientation DO
position.orientation ← o;
FOR grain: INT IN [0..surface.sizes.grain) DO
position.grain ← grain;
position.type ← short;
eachNode[surface, position];
position.type ← output;
eachNode[surface, position];
ENDLOOP;
ENDLOOP;
ENDLOOP;
ENDLOOP;
ENDLOOP;
ENDLOOP;
FOR chipX: INT IN [0..surface.sizes.chip.x) DO
position.chip.x ← chipX;
FOR chipY: INT IN [0..surface.sizes.chip.y) DO
position.chip.y ← chipY;
FOR minorX: INT IN [0..surface.sizes.minor.x) DO
position.minor.x ← minorX;
FOR grain: INT IN [0..surface.sizes.grain) DO
position.grain ← grain;
position.type ← longVertical;
eachNode[surface, position];
position.type ← interchipVertical;
eachNode[surface, position];
ENDLOOP;
ENDLOOP;
ENDLOOP;
ENDLOOP;
FOR chipX: INT IN [0..surface.sizes.chip.x) DO
position.chip.x ← chipX;
FOR chipY: INT IN [0..surface.sizes.chip.y) DO
position.chip.y ← chipY;
FOR minorY: INT IN [0..surface.sizes.minor.y) DO
position.minor.y ← minorY;
FOR grain: INT IN [0..surface.sizes.grain) DO
position.grain ← grain;
position.type ← longHorizontal;
eachNode[surface, position];
position.type ← interchipHorizontal;
eachNode[surface, position];
ENDLOOP;
ENDLOOP;
ENDLOOP;
ENDLOOP;
};
CheckRoute: PROC [route: RefTab.Ref] = {
EachRoutedWire: RefTab.EachPairAction = {
path: Path ← NARROW[val];
CheckPath[path];
};
CheckPath: PROC [path: Path] = {
FOR index: CARDINAL IN [0..path.size) DO
position: ArrayPosition ← NEW[ArrayPositionRec];
position^ ← path[index];
IF NOT RefTab.Insert[nodeTable, position, $Used] THEN ERROR;
ENDLOOP;
IF path.subPaths#NIL THEN FOR index: CARDINAL IN [0..path.subPaths.size) DO
CheckPath[path.subPaths[index]];
ENDLOOP;
};
nodeTable: RefTab.Ref ← RefTab.Create[hash: ArrayPositionHash, equal: ArrayPositionEqual];
[] ← RefTab.Pairs[route, EachRoutedWire];
};
ArrayPositionHash: RefTab.HashProc = {
Fold: PROC [current: CARD32, next: DABasics.Number] RETURNS [new: CARD32] = {
new ← LOOPHOLE[Basics.DoubleXor[LOOPHOLE[current], LOOPHOLE[next]]];
};
position: ArrayPosition ← NARROW[key];
long: CARD32 ← position.chip.x;
long ← Fold[long, position.chip.y];
long ← Fold[long, position.minor.x];
long ← Fold[long, position.minor.y];
long ← Fold[long, position.grain];
RETURN[Basics.LowHalf[long]];
};
ArrayPositionEqual: RefTab.EqualProc = {
position1: ArrayPosition ← NARROW[key1];
position2: ArrayPosition ← NARROW[key2];
IF position1.type#position2.type THEN RETURN[FALSE];
SELECT position1.type FROM
interchipVertical, longVertical => RETURN[position1.chip=position2.chip AND position1.minor.x=position2.minor.x AND position1.grain=position2.grain];
interchipHorizontal, longHorizontal => RETURN[position1.chip=position2.chip AND position1.minor.y=position2.minor.y AND position1.grain=position2.grain];
short, output => RETURN[position1^=position2^];
ENDCASE => ERROR;
};
Output
AssemblyPrimitive: TYPE = {SToI, LToI, OToI, IToS, IToL, SToS, ComplexOToS, SimpleOToS, ProgramVertical, ProgramHorizontal, OToL, OToS, SToL, LToS};
assemblyPrimitives: ARRAY AssemblyPrimitive OF CD.Object ← ALL[NIL];
assemblyPrimitiveNames: ARRAY AssemblyPrimitive OF Rope.ROPE ← ["SToI", "LToI", "OToI", "IToS", "IToL", "SToS", "ComplexOToS", "SimpleOToS", "ProgramVertical", "ProgramHorizontal", "OToL", "OToS", "SToL", "LToS"];
RectangleColor: TYPE = {black, red, green, blue, yellow};
rectangleAtoms: ARRAY RectangleColor OF ATOM ← [$comment, $red, $green, $blue, $yellow];
rectangleLayers: ARRAY RectangleColor OF CD.Layer;
minorSize: DABasics.Number ← 72*8;
interChipSize: DABasics.Number ← 8*8;
interChipOffset: DABasics.Number ← 4*8;
longIndent: DABasics.Number ← 8*8;
grainSpacing: DABasics.Number ← 16*8;
shortOutputOffset: DABasics.Number ← 12*8;
shortOutputIndent: DABasics.Number ← 4*8;
outputOffset: DABasics.Number ← 4*8;
LoadAssemblyPrimitives: PROC = {
design: CD.Design ← PW.OpenDesign["SoftHdwFlat.dale"];
CDOps.SetMutability[design, readonly];
FOR ap: AssemblyPrimitive IN AssemblyPrimitive DO
assemblyPrimitives[ap] ← PW.Get[design, assemblyPrimitiveNames[ap]];
ENDLOOP;
FOR rc: RectangleColor IN RectangleColor DO
rectangleLayers[rc] ← CD.FetchLayer[NIL, rectangleAtoms[rc]];
ENDLOOP;
};
PrintPlaceAndRoute: PROC [placement: Placement, route: RefTab.Ref, incompleteNetEnds: NetEndList] RETURNS [design: CD.Design] = {
PrintPlacement: RefTab.EachPairAction = {
pa: PrimitiveAssignment ← NARROW[val];
CreateRectangle[pa.position, green];
position^ ← pa.position^;
position.orientation ← IF position.orientation=vertical THEN horizontal ELSE vertical;
position.type ← short;
FOR index: CARDINAL IN [0..pa.size) DO
position.grain ← pa[index];
CreateRectangle[position, red];
CreateArc[position, pa.position];
ENDLOOP;
};
PrintRoute: RefTab.EachPairAction = {
path: Path ← NARROW[val];
PrintPath[path]
};
PrintPath: PROC [path: Path] = {
FOR index: CARDINAL IN [0..path.size) DO
position^ ← path[index];
CreateRectangle[position, blue];
IF index<path.size-1 THEN {
nextPosition^ ← path[index+1];
CreateArc[position, nextPosition];
};
ENDLOOP;
IF path.subPaths#NIL THEN FOR index: CARDINAL IN [0..path.subPaths.size) DO
PrintPath[path.subPaths[index]];
position^ ← path[path.size-1];
nextPosition^ ← path.subPaths[index][0];
CreateArc[position, nextPosition];
ENDLOOP;
};
CreateRectangle: PROC [position: ArrayPosition, color: RectangleColor] = {
size: DABasics.Position ← [0, 4];
orient: DABasics.Orientation ← original; -- or rotate90X
off: DABasics.Position ← PositionCoordinates[position^];
size.x ← SELECT position.type FROM
longVertical => minorSize*placement.sizes.minor.y,
longHorizontal => minorSize*placement.sizes.minor.x,
interchipVertical, interchipHorizontal => interChipSize,
short, output => minorSize-2*shortOutputIndent,
ENDCASE => ERROR;
orient ← SELECT position.type FROM
interchipVertical, longVertical => rotate90X,
interchipHorizontal, longHorizontal => original,
short, output => (IF position.orientation=vertical THEN rotate90X ELSE original),
ENDCASE => ERROR;
il ← CONS[CDInstances.NewInst[CDRects.CreateRect[size, rectangleLayers[color]], [off, orient]], il];
CDProperties.PutInstanceProp[il.first, $SoftHdwArrayPosition, NEW[ArrayPositionRec ← position^]];
};
CreateArc: PROC [from, to: ArrayPosition] = {
Direction: TYPE = {left, right, up, down, sideways};
direction: Direction ← SELECT TRUE FROM
to.chip.x=from.chip.x AND to.minor.x=from.minor.x AND to.chip.y=from.chip.y AND to.minor.y=from.minor.y => sideways,
to.chip.x>from.chip.x OR to.minor.x>from.minor.x => right,
to.chip.y>from.chip.y OR to.minor.y>from.minor.y => up,
to.chip.x<from.chip.x OR to.minor.x<from.minor.x => left,
to.chip.y<from.chip.y OR to.minor.y<from.minor.y => down,
ENDCASE => ERROR;
arcType: AssemblyPrimitive ← SELECT from.type FROM
interchipVertical, interchipHorizontal => SELECT to.type FROM
longVertical, longHorizontal => IToL,
short => IToS,
ENDCASE => ERROR,
longVertical, longHorizontal => SELECT to.type FROM
interchipVertical, interchipHorizontal => LToI,
short => LToS,
ENDCASE => ERROR,
short => SELECT to.type FROM
interchipVertical, interchipHorizontal => SToI,
longVertical, longHorizontal => SToL,
short => SToS,
output => IF to.orientation=vertical THEN ProgramVertical ELSE ProgramHorizontal,
ENDCASE => ERROR,
output => SELECT to.type FROM
interchipVertical, interchipHorizontal => OToI,
longVertical, longHorizontal => OToL,
short => SELECT direction FROM
sideways => OToS,
up, right => SimpleOToS,
down, left => ComplexOToS,
ENDCASE => ERROR,
ENDCASE => ERROR,
ENDCASE => ERROR;
orient: DABasics.Orientation;
off: DABasics.Position← [0, 0];
off.x ← from.chip.x*(placement.sizes.minor.x*minorSize+2*interChipSize);
off.y ← from.chip.y*(placement.sizes.minor.y*minorSize + 2*interChipSize);
SELECT arcType FROM
SToI, LToI, OToI => {
direction ← SELECT to.type FROM
interchipHorizontal => (IF from.chip.x=to.chip.x THEN right ELSE left),
interchipVertical => (IF from.chip.y=to.chip.y THEN up ELSE down),
ENDCASE => ERROR;
SELECT direction FROM
right => {
orient ← original;
off.x ← off.x + placement.sizes.minor.x*minorSize - shortOutputIndent;
off.y ← off.y + to.minor.y*minorSize + to.grain*grainSpacing + shortOutputIndent;
};
up => {
orient ← rotate90X;
off.x ← off.x + to.minor.x*minorSize + to.grain*grainSpacing + shortOutputIndent;
off.y ← off.y + placement.sizes.minor.y*minorSize - shortOutputIndent;
};
down => {
orient ← rotate270;
off.x ← off.x + to.minor.x*minorSize + to.grain*grainSpacing + shortOutputIndent;
off.y ← off.y - interChipOffset;
};
left => {
orient ← mirrorX;
off.x ← off.x - interChipOffset;
off.y ← off.y + to.minor.y*minorSize + to.grain*grainSpacing + shortOutputIndent;
};
ENDCASE => ERROR;
};
IToS, IToL => {
direction ← SELECT from.type FROM
interchipHorizontal => (IF from.chip.x=to.chip.x THEN left ELSE right),
interchipVertical => (IF from.chip.y=to.chip.y THEN down ELSE up),
ENDCASE => ERROR;
SELECT direction FROM
left => {
orient ← mirrorX;
off.x ← off.x + placement.sizes.minor.x*minorSize - shortOutputIndent;
off.y ← off.y + to.minor.y*minorSize + to.grain*grainSpacing + shortOutputIndent;
};
down => {
orient ← rotate270;
off.x ← off.x + to.minor.x*minorSize + to.grain*grainSpacing + shortOutputIndent;
off.y ← off.y + placement.sizes.minor.y*minorSize - shortOutputIndent;
};
up => {
orient ← rotate90X;
off.x ← off.x + to.minor.x*minorSize + to.grain*grainSpacing + shortOutputIndent;
off.y ← off.y + placement.sizes.minor.y*minorSize + interChipOffset + interChipSize;
};
right => {
orient ← original;
off.x ← off.x + placement.sizes.minor.x*minorSize + interChipOffset + interChipSize;
off.y ← off.y + to.minor.y*minorSize + to.grain*grainSpacing + shortOutputIndent;
};
ENDCASE => ERROR;
};
SToS, ComplexOToS, SimpleOToS => SELECT direction FROM
right => {
orient ← original;
off.x ← off.x + to.minor.x*minorSize - shortOutputIndent;
off.y ← off.y + to.minor.y*minorSize + to.grain*grainSpacing + shortOutputIndent;
};
up => {
orient ← rotate90X;
off.x ← off.x + to.minor.x*minorSize + to.grain*grainSpacing + shortOutputIndent;
off.y ← off.y + to.minor.y*minorSize - shortOutputIndent;
};
down => {
orient ← rotate270;
off.x ← off.x + from.minor.x*minorSize + from.grain*grainSpacing + shortOutputIndent;
off.y ← off.y + from.minor.y*minorSize - shortOutputIndent;
};
left => {
orient ← mirrorX;
off.x ← off.x + from.minor.x*minorSize - shortOutputIndent;
off.y ← off.y + from.minor.y*minorSize + from.grain*grainSpacing + shortOutputIndent;
};
ENDCASE => ERROR;
OToL, OToS, SToL => {
IF from.orientation=vertical THEN {
orient ← original;
off.x ← off.x + from.minor.x*minorSize + from.grain*grainSpacing + shortOutputIndent;
off.y ← off.y + from.minor.y*minorSize;
}
ELSE {
orient ← rotate90X;
off.x ← off.x + from.minor.x*minorSize;
off.y ← off.y + from.minor.y*minorSize + from.grain*grainSpacing + shortOutputIndent;
};
};
LToS => {
IF to.orientation=vertical THEN {
orient ← original;
off.x ← off.x + to.minor.x*minorSize + to.grain*grainSpacing + shortOutputIndent;
off.y ← off.y + to.minor.y*minorSize;
}
ELSE {
orient ← rotate90X;
off.x ← off.x + to.minor.x*minorSize;
off.y ← off.y + to.minor.y*minorSize + to.grain*grainSpacing + shortOutputIndent;
};
};
ProgramVertical => {
orient ← original;
off.x ← off.x + to.minor.x*minorSize + to.grain*grainSpacing + shortOutputIndent;
off.y ← off.y + from.minor.y*minorSize + from.grain*grainSpacing + shortOutputIndent;
};
ProgramHorizontal => {
orient ← original;
off.x ← off.x + from.minor.x*minorSize + from.grain*grainSpacing + shortOutputIndent;
off.y ← off.y + to.minor.y*minorSize + to.grain*grainSpacing + shortOutputIndent;
};
ENDCASE => ERROR;
{
base: DABasics.Position ← CD.InterestBase[assemblyPrimitives[arcType]];
tbase: DABasics.Position ← CDBasics.MapPoint[base, [[0, 0], orient]];
toff: DABasics.Position ← CDBasics.SubPoints[off, tbase];
size: DABasics.Position ← CD.InterestSize[assemblyPrimitives[arcType]];
SELECT orient FROM
rotate270 => toff.y ← toff.y + size.x;
mirrorX => toff.x ← toff.x + size.x;
ENDCASE;
il ← CONS[CDInstances.NewInst[assemblyPrimitives[arcType], [toff, orient]], il];
CDProperties.PutInstanceProp[il.first, $SoftHdwFromArrayPosition, NEW[ArrayPositionRec ← from^]];
CDProperties.PutInstanceProp[il.first, $SoftHdwToArrayPosition, NEW[ArrayPositionRec ← to^]];
};
};
PositionCoordinates: PROC [position: ArrayPositionRec] RETURNS [coordinates: CD.Position] = {
coordinates.x ← position.chip.x*(placement.sizes.minor.x*minorSize+2*interChipSize);
coordinates.y ← position.chip.y*(placement.sizes.minor.y*minorSize + 2*interChipSize);
SELECT position.type FROM
short, output => {
grainOffset: DABasics.Number ← shortOutputOffset + position.grain*grainSpacing + (IF position.type=output THEN outputOffset ELSE 0);
coordinates.x ← coordinates.x + position.minor.x*minorSize;
coordinates.y ← coordinates.y + position.minor.y*minorSize;
IF position.orientation=vertical THEN {
coordinates.x ← coordinates.x + grainOffset;
coordinates.y ← coordinates.y + shortOutputIndent;
}
ELSE {
coordinates.x ← coordinates.x + shortOutputIndent;
coordinates.y ← coordinates.y + grainOffset;
};
};
longVertical => coordinates.x ← coordinates.x + position.minor.x*minorSize + longIndent + position.grain*grainSpacing;
longHorizontal => coordinates.y ← coordinates.y + position.minor.y*minorSize + longIndent + position.grain*grainSpacing;
interchipVertical => {
coordinates.x ← coordinates.x + position.minor.x*minorSize + shortOutputOffset + position.grain*grainSpacing;
coordinates.y ← coordinates.y + placement.sizes.minor.y*minorSize + interChipOffset;
};
interchipHorizontal => {
coordinates.y ← coordinates.y + position.minor.y*minorSize + shortOutputOffset + position.grain*grainSpacing;
coordinates.x ← coordinates.x + placement.sizes.minor.x*minorSize + interChipOffset;
};
ENDCASE => ERROR;
};
il: CD.InstanceList ← NIL;
position: ArrayPosition ← NEW[ArrayPositionRec];
nextPosition: ArrayPosition ← NEW[ArrayPositionRec];
[] ← RefTab.Pairs[placement.positions, PrintPlacement];
[] ← RefTab.Pairs[route, PrintRoute];
{
NodeCoordinates: PROC [node: Node] RETURNS [position: CD.Position] = TRUSTED {
position ← PositionCoordinates[node.position];
SELECT node.position.type FROM
interchipVertical, interchipHorizontal, longVertical, longHorizontal => ERROR; -- no net end should be on these nodes
short, output => SELECT node.position.orientation FROM
vertical => {
position.x ← position.x + 2;
position.y ← position.y + minorSize/2 - shortOutputIndent/2;
};
horizontal => {
position.x ← position.x + minorSize/2 - shortOutputIndent/2;
position.y ← position.y + 2;
};
ENDCASE => ERROR;
ENDCASE => ERROR;
};
FOR nel: NetEndList ← incompleteNetEnds, nel.rest UNTIL nel=NIL DO
ne: NetEnds ← nel.first;
from: CD.Position ← NodeCoordinates[ne.source];
FOR nl: Nodes ← ne.destinations, nl.rest UNTIL nl=NIL DO
to: CD.Position ← NodeCoordinates[nl.first];
line: CD.Object;
offset: CD.Position;
w: DABasics.Number ← 8;
w2: INTMAX[1, (w+1)/2];
min: CD.Position ← CDBasics.MinPoint[from, to];
max: CD.Position ← CDBasics.MaxPoint[from, to];
r: CD.Rect;
min ← [min.x-w2, min.y-w2];
max ← [max.x+w2, max.y+w2];
r ← CDBasics.ToRect[min, max];
IF (r.x2-r.x1)>LAST[NAT] OR (r.y2-r.y1)>LAST[NAT] THEN {
TerminalIO.PutRope["\nSome disconnect line is too long"];
}
ELSE {
[line, offset] ← CDCurves.CreateLine[LIST[from, to], w, rectangleLayers[yellow]];
il ← CONS[CDInstances.NewInst[line, [offset, original]], il];
CDProperties.PutInstanceProp[il.first, $SoftHdwFromArrayPosition, NEW[CD.Position ← from]];
CDProperties.PutInstanceProp[il.first, $SoftHdwToArrayPosition, NEW[CD.Position ← to]];
};
ENDLOOP;
ENDLOOP;
};
design ← PW.Draw[PW.CreateCell[il]]
};
InsertPrimitive: PROC [placement: Placement, minorx, minory: DABasics.Number, orientation: Orientation, grain: DABasics.Number, inputs: LIST OF DABasics.Number] = {
position: ArrayPosition ← NEW[ArrayPositionRec ← [
chip: [0, 0],
minor: [minorx, minory],
grain: grain,
orientation: orientation,
type: output]];
p: Primitive ← NEW[PrimitiveRec];
pa: PrimitiveAssignment;
size: INT ← 0;
FOR il: LIST OF DABasics.Number ← inputs, il.rest UNTIL il=NIL DO
size ← size + 1;
ENDLOOP;
pa ← NEW[PrimitiveAssignmentRec[size]];
pa.position ← position;
FOR index: INT IN [0..pa.size) DO
pa[index] ← inputs.first;
inputs ← inputs.rest;
ENDLOOP;
[] ← RefTab.Insert[placement.positions, p, pa];
};
PathElements: TYPE = LIST OF PathElement;
PathElement: TYPE = RECORD [
nodeType: NodeType,
minorx, minory: DABasics.Number,
orientation: Orientation,
grain: DABasics.Number,
chipx, chipy:DABasics.Number ← 0];
MakeSimplePath: PROC [route: RefTab.Ref, elements: PathElements] = {
flatWire: CoreFlat.FlatWire ← NEW[CoreFlat.FlatWireRec ← [wire: NEW[Core.WireRec[0]]]];
path: Path;
size: INT ← 0;
FOR el: PathElements ← elements, el.rest UNTIL el=NIL DO
size ← size + 1;
ENDLOOP;
path ← NEW[PathRec[size]];
FOR index: INT IN [0..path.size) DO
el: PathElement ← elements.first;
path[index] ← [
chip: [el.chipx, el.chipy],
minor: [el.minorx, el.minory],
grain: el.grain,
orientation: el.orientation,
type: el.nodeType];
elements ← elements.rest;
ENDLOOP;
[] ← RefTab.Insert[route, flatWire, path];
};
MakePlaceAndRoute: PROC RETURNS[placement: Placement, route: RefTab.Ref] = {
placement ← NEW[PlacementRec];
placement.flatCell ← NIL;
placement.sizes ← NEW[ArrayPositionRec ← [[4,4],[16,16],4,horizontal,output]];
placement.maxChip ← [1, 1];
placement.positions ← RefTab.Create[];
route ← RefTab.Create[hash: CoreFlat.FlatWireHash, equal: CoreFlat.FlatWireEqual];
};
Initialization
LoadPrimitiveTypes[];
LoadAssemblyPrimitives[];
[] ← CDProperties.Register[$SoftHdwArrayPosition, [makeCopy: CDProperties.CopyVal], $SoftHdw];
[] ← CDProperties.Register[$SoftHdwFromArrayPosition, [makeCopy: CDProperties.CopyVal], $SoftHdw];
[] ← CDProperties.Register[$SoftHdwToArrayPosition, [makeCopy: CDProperties.CopyVal], $SoftHdw];
END.