XilinxIOImpl.mesa
Copyright © 1986 by Xerox Corporation. All rights reserved.
Barth, November 7, 1989 8:20:31 am PST
Last Edited by: Gasbarro July 18, 1989 6:23:49 pm PDT
DIRECTORY Atom, CDCommandOps, CDSequencer, Core, CoreCDUser, CoreClasses, CoreFlat, CoreOps, CoreProperties, FS, RefTab, Sequence, Sisyph, SymTab, TerminalIO, IO, Rope, XilinxIO;
XilinxIOImpl: CEDAR PROGRAM
IMPORTS Atom, CDCommandOps, CoreCDUser, CoreClasses, CoreFlat, CoreOps, CoreProperties, FS, RefTab, Sisyph, SymTab, TerminalIO, IO, Rope
EXPORTS XilinxIO
SHARES Sisyph
= BEGIN OPEN XilinxIO;
Types and Globals
ROPE: TYPE = Rope.ROPE;
LOR: TYPE = LIST OF ROPE;
seqProp: ATOM = $XilinxIOSeqProp;
SeqData: TYPE = REF SeqDataRec;
SeqDataRec: TYPE = RECORD [
axis: Axis,
startIndex: NAT,
orthogonalIndex: NAT,
delta: INT];
BindList: TYPE = LIST OF RECORD[wire: Core.Wire, name: ROPE];
Primitive Data Base
primitives: SymTab.Ref ← SymTab.Create[]; -- cell type name to Primitive
Primitive: TYPE = REF PrimitiveRec;
PrimitiveRec: TYPE = RECORD [
translate: TranslateProc,
data: REF ANY];
TranslateProc: TYPE = PROC [circuit: FlatCircuit, root, cell: Core.CellType, instance: CoreClasses.CellInstance, name: ROPE, flatCell: CoreFlat.FlatCellTypeRec, flatWireToSignal, bindings: RefTab.Ref, part2000: BOOL, data: REF ANY];
Pins: TYPE = LIST OF Pin;
PinRecList : TYPE = LIST OF PinRec;
Pin: TYPE = REF PinRec;
PinRec: TYPE = RECORD [
coreName: ROPE,
xilinxName: ROPE,
direction: InOrOut,
physicalPin: BOOLFALSE,
tristate: BOOLFALSE,
invert: BOOLFALSE];
InOrOut: TYPE = {In, Out};
directionNames: ARRAY InOrOut OF ROPE ← ["I", "O"];
Flattened Circuit
FlatCircuit: TYPE = REF FlatCircuitRec;
FlatCircuitRec: TYPE = RECORD [
symbols: Symbols ← NIL,
signals: Signals ← NIL,
partType: ROPENIL];
Symbols: TYPE = LIST OF Symbol;
Symbol: TYPE = REF SymbolRec;
SymbolRec: TYPE = RECORD [
name: ROPENIL,
type: ROPENIL,
connections: SymbolSignalPins ← NIL,
parameters: LORNIL,
configs: LORNIL];
SymbolSignalPins: TYPE = LIST OF SymbolSignalPin;
SymbolSignalPin: TYPE = REF SymbolSignalPinRec;
SymbolSignalPinRec: TYPE = RECORD [
symbol: Symbol ← NIL,
signal: Signal ← NIL,
pin: Pin ← NIL,
parameters: LORNIL];
Signals: TYPE = LIST OF Signal;
Signal: TYPE = REF SignalRec;
SignalRec: TYPE = RECORD [
name: ROPENIL,
connections: SymbolSignalPins ← NIL,
pin: ROPENIL, -- NIL => not forced
unbonded: BOOLFALSE,
parameters: LORNIL];
some connections' pin.physicalPin = TRUE causes an EXT record to be emitted using unbonded, pin, and parameters
all connections' pin.physicalPin = FALSE and parameters#NIL causes a SIG record to be emitted
PinSignals: TYPE = LIST OF PinSignalRec;
PinSignalRec: TYPE = RECORD [
pin: Pin ← NIL,
signal: Signal ← NIL];
Placement
Loc: PUBLIC PROC [cx: Sisyph.Context, x, y: INT] RETURNS [trash: NAT ← 0] = {
SELECT TRUE FROM
x>=0 AND y>=0 => Sisyph.AddProp[cx, $ParLoc, IO.PutFR["\"LOC=%g%g\"", IO.char[NumToLet[y]], IO.char[NumToLet[x]]], TRUE];
x<0 AND y<0 => NULL;
ENDCASE => ERROR;
};
Set: PUBLIC PROC [cx: Sisyph.Context, x, y: INT, axis: Axis ← ax] RETURNS [trash: NAT ← 0] = {
Sisyph.Store[cx, "x", NEW[INT ← x]];
Sisyph.Store[cx, "y", NEW[INT ← y]];
Sisyph.Store[cx, "axis", NEW[Axis ← axis]];
};
Seq: PUBLIC PROC [cx: Sisyph.Context, axis: Axis, startIndex, orthogonalIndex: NAT, delta: INT ← 1] RETURNS [trash: NAT ← 0] = {
previousProps: Core.Properties ← Sisyph.GetCoreInstProps[cx];
Sisyph.Store[cx, Sisyph.coreInstPropsRope, NEW [Core.Properties ← CoreProperties.PutProp[previousProps, seqProp, NEW[SeqDataRec ← [axis, startIndex, orthogonalIndex, delta]]]]];
};
Functions
SaveCellType: PUBLIC PROC [cellType: Core.CellType, fileName: ROPENIL] RETURNS [multiplyDriven: LORNIL] = {
circuit: FlatCircuit ← FlattenCircuit[cellType];
pruned: RefTab.Ref ← PruneFlattenedCircuit[circuit];
multiplyDriven ← CheckMultipleDrivers[circuit];
IF fileName=NIL THEN fileName ← Rope.Cat[CoreOps.GetCellTypeName[cellType], ".xnf"];
WriteFlattenedCircuit[circuit, pruned, fileName];
};
FlattenCircuit: PROC [cellType: Core.CellType] RETURNS [circuit: FlatCircuit] = {
PushPins: CoreOps.EachWireProc = {
pinList: ROPENARROW[CoreProperties.GetWireProp[wire, $Pins]];
IF pinList#NIL THEN {
ris: IO.STREAMIO.RIS[pinList];
FOR i: INT IN [0..wire.size) DO
pin: ROPEIO.GetCedarTokenRope[ris].token;
currentValue: ROPENARROW[CoreProperties.GetWireProp[wire[i], $Pin]];
IF i#(wire.size-1) THEN {
kind: IO.TokenKind;
token: IO.ROPE;
[kind, token] ← IO.GetCedarTokenRope[ris];
IF kind#tokenSINGLE OR NOT Rope.Equal[token, ","] THEN ERROR;
};
IF wire[i].size#0 THEN ERROR;
IF currentValue=NIL THEN CoreProperties.PutWireProp[wire[i], $Pin, pin];
ENDLOOP;
};
};
FlattenCellType: CoreFlat.BoundFlatCellProc = {
GetParms: CoreOps.EachWireProc = {
FindParms: PROC [prop: ATOM, val: REF ANY] = {
propName: ROPE ← Atom.GetPName[prop];
IF Rope.Match["Par*", propName, FALSE] THEN {
SetParm: PROC [wire: Core.Wire] = {
signal: Signal ← CreateBoundSignal[wire, circuit, cellType, flatWireToSignal, bindings, flatCell];
signal.parameters ← CONS[parm, signal.parameters];
};
parm: ROPENARROW[val];
IF wire.size#0 THEN [] ← CoreOps.VisitRootAtomics[wire, SetParm]
ELSE SetParm[wire];
};
};
CoreProperties.Enumerate[wire.properties, FindParms];
};
name: ROPE ← CoreOps.GetCellTypeName[cell];
primitive: Primitive ← NARROW[SymTab.Fetch[primitives, name].val];
clbMapProp: REF BOOLNARROW[CoreProperties.GetCellTypeProp[cell, $CLBMap]];
IF clbMapProp#NIL AND clbMapProp^ THEN CreateCLBMap[circuit, cellType, cell, instance, name, flatCell, flatWireToSignal, bindings, part2000, NIL];
IF cell.class=CoreClasses.recordCellClass THEN {
rct: CoreClasses.RecordCellType ← NARROW[cell.data];
FOR instanceIndex: NAT IN [0..rct.size) DO
seqData: SeqData ← NARROW[CoreProperties.GetCellInstanceProp[rct[instanceIndex], seqProp]];
IF seqData#NIL THEN {
child: Core.CellType ← rct[instanceIndex].type;
sct: Sequence.SequenceCellType ← NARROW[child.data];
recast: Core.CellType ← CoreOps.Recast[child];
recastRCT: CoreClasses.RecordCellType ← NARROW[recast.data];
FOR subInstanceIndex: NAT IN [0..recastRCT.size) DO
seqIndex: NAT ← seqData.startIndex + (subInstanceIndex*seqData.delta);
x, y: NAT ← 0;
SELECT seqData.axis FROM
ax => {x ← seqIndex; y ← seqData.orthogonalIndex};
ay => {x ← seqData.orthogonalIndex; y ← seqIndex};
ENDCASE => ERROR;
CoreProperties.PutCellInstanceProp[recastRCT[subInstanceIndex], $ParLoc, IO.PutFR["LOC=%g%g", IO.char[NumToLet[y]], IO.char[NumToLet[x]]]];
ENDLOOP;
};
ENDLOOP;
[] ← CoreOps.VisitWireSeq[NARROW[cell.data, CoreClasses.RecordCellType].internal, GetParms];
};
IF primitive=NIL THEN CoreFlat.NextBoundCellType[cell, target, flatCell, instance, index, parent, flatParent, data, bindings, FlattenCellType]
ELSE primitive.translate[circuit, cellType, cell, instance, name, flatCell, flatWireToSignal, bindings, part2000, primitive.data];
};
flatWireToSignal: RefTab.Ref ← RefTab.Create[hash: CoreFlat.FlatWireHash, equal: CoreFlat.FlatWireEqual];
part2000: BOOLFALSE;
circuit ← NEW[FlatCircuitRec];
circuit.partType ← NARROW[CoreProperties.InheritCellTypeProp[cellType, $XilinxPartType]];
IF circuit.partType=NIL THEN circuit.partType ← "2064PC68-33";
part2000 ← Rope.Fetch[circuit.partType]='2;
[] ← CoreOps.VisitWire[cellType.public, PushPins];
FlattenCellType[cell: cellType, bindings: CoreFlat.InitialBindingTable[cellType]];
};
clbMapPins: Pins ← PinRecListToPinList[LIST[
["A", "A", In],
["B", "B", In],
["C", "C", In],
["D", "D", In],
["E", "E", In],
["DI", "DI", In],
["CE", "CE", In],
["K", "K", In],
["RD", "RD", In],
["X", "X", In],
["Y", "Y", In]]];
CreateCLBMap: TranslateProc = {
MakeBind: PROC [wire: Core.Wire] = {
coreName: ROPENARROW[CoreProperties.GetWireProp[wire, $Pin]];
IF coreName=NIL AND NOT GlobalDelete[CoreOps.GetFullWireName[public, wire]] THEN ERROR;
IF coreName#NIL THEN bindlist ← CONS[[wire, coreName], bindlist];
};
bindlist: BindList ← NIL;
symbol: Symbol ← NIL;
public: Core.Wire ← cell.public;
CoreOps.VisitRootAtomics[public, MakeBind];
symbol ← MakeSymbol[CoreFlat.CellTypePathRope[root, flatCell], "CLBMAP", bindlist, clbMapPins, circuit, root, flatCell, flatWireToSignal, bindings];
GetParameters[symbol, instance];
};
trace: BOOLFALSE;
PruneFlattenedCircuit: PROC [circuit: FlatCircuit] RETURNS [pruned: RefTab.Ref] = {
CheckSignal: RefTab.EachPairAction = {
signal: Signal ← NARROW[key];
sensed, physical: BOOLFALSE;
IF RefTab.Fetch[pruned, signal].found THEN RETURN;
[sensed, physical] ← SensedPhysicalDrivenTristate[signal, pruned];
IF NOT sensed AND (signal.unbonded OR NOT physical) THEN {
IF trace THEN TerminalIO.PutF["\npruning signal: %g", IO.rope[signal.name]];
IF NOT RefTab.Insert[pruned, signal, signal] THEN ERROR;
FOR cl: SymbolSignalPins ← signal.connections, cl.rest UNTIL cl=NIL DO
ssp: SymbolSignalPin ← cl.first;
IF ssp.pin.direction=Out THEN IF NOT RefTab.Insert[pruned, ssp, ssp] THEN ERROR;
[] ← RefTab.Insert[symbolCheck, ssp.symbol, ssp.symbol];
ENDLOOP;
};
};
CheckSymbol: RefTab.EachPairAction = {
symbol: Symbol ← NARROW[key];
IF RefTab.Fetch[pruned, symbol].found THEN RETURN;
FOR cl: SymbolSignalPins ← symbol.connections, cl.rest UNTIL cl=NIL DO
ssp: SymbolSignalPin ← cl.first;
IF ssp.pin.direction=Out AND NOT RefTab.Fetch[pruned, ssp].found THEN RETURN;
ENDLOOP;
IF trace THEN TerminalIO.PutF["\npruning symbol: %g", IO.rope[symbol.name]];
IF NOT RefTab.Insert[pruned, symbol, symbol] THEN ERROR;
FOR cl: SymbolSignalPins ← symbol.connections, cl.rest UNTIL cl=NIL DO
ssp: SymbolSignalPin ← cl.first;
IF ssp.pin.direction=In THEN IF NOT RefTab.Insert[pruned, ssp, ssp] THEN ERROR;
[] ← RefTab.Insert[signalCheck, ssp.signal, ssp.signal];
ENDLOOP;
};
signalCheck: RefTab.Ref ← RefTab.Create[];
symbolCheck: RefTab.Ref ← RefTab.Create[];
pruned ← RefTab.Create[];
FOR sl: Signals ← circuit.signals, sl.rest UNTIL sl=NIL DO
IF NOT RefTab.Insert[signalCheck, sl.first, sl.first] THEN ERROR;
ENDLOOP;
UNTIL RefTab.GetSize[symbolCheck]=0 AND RefTab.GetSize[signalCheck]=0 DO
[] ← RefTab.Pairs[signalCheck, CheckSignal];
RefTab.Erase[signalCheck];
[] ← RefTab.Pairs[symbolCheck, CheckSymbol];
RefTab.Erase[symbolCheck];
ENDLOOP;
};
CheckMultipleDrivers: PROC [circuit: FlatCircuit] RETURNS [names: LORNIL]= {
Driven: TYPE = {Never, Always, Tristate};
FOR sl: Signals ← circuit.signals, sl.rest UNTIL sl=NIL DO
driven: Driven ← Never;
FOR cl: SymbolSignalPins ← sl.first.connections, cl.rest UNTIL cl=NIL DO
ssp: SymbolSignalPin ← cl.first;
IF ssp.pin.direction=Out THEN {
IF driven=Always OR (driven=Tristate AND NOT ssp.pin.tristate) THEN {
names ← CONS[sl.first.name, names];
EXIT;
};
driven ← IF ssp.pin.tristate THEN Tristate ELSE Always;
};
ENDLOOP;
ENDLOOP;
};
WriteFlattenedCircuit: PROC [circuit: FlatCircuit, pruned: RefTab.Ref, fileName: ROPE] = {
WriteRecord: PROC [record: ROPE, parameters: LORNIL] = {
FOR rl: LOR ← parameters, rl.rest UNTIL rl=NIL DO
record ← Rope.Cat[record, ",", rl.first];
ENDLOOP;
IF Rope.Length[record]>=253 THEN ERROR;
IO.PutF[stream, "%g\n", IO.rope[record]];
};
stream: IO.STREAMFS.StreamOpen[fileName, $create];
WriteRecord["LCANET,2"];
WriteRecord[IO.PutFR["PROG,Core2XNF,1,%g", IO.time[]]];
WriteRecord[Rope.Cat["PART,", circuit.partType]];
FOR sl: Symbols ← circuit.symbols, sl.rest UNTIL sl=NIL DO
symbol: Symbol ← sl.first;
IF NOT RefTab.Fetch[pruned, symbol].found THEN {
WriteRecord[IO.PutFR["SYM,%g,%g", IO.rope[symbol.name], IO.rope[symbol.type]], symbol.parameters];
FOR cl: SymbolSignalPins ← symbol.connections, cl.rest UNTIL cl=NIL DO
ssp: SymbolSignalPin ← cl.first;
pinRecord: ROPEIO.PutFR["PIN,%g,%g,%g", IO.rope[ssp.pin.xilinxName], IO.rope[directionNames[ssp.pin.direction]], IO.rope[ssp.signal.name]];
IF ssp.pin.invert OR ssp.parameters#NIL THEN pinRecord ← Rope.Cat[pinRecord, ","];
IF ssp.pin.invert THEN pinRecord ← Rope.Cat[pinRecord, ",INV"];
WriteRecord[pinRecord, ssp.parameters];
ENDLOOP;
FOR rl: LOR ← symbol.configs, rl.rest UNTIL rl=NIL DO
WriteRecord[Rope.Cat["CFG,", rl.first]];
ENDLOOP;
WriteRecord["END"];
};
ENDLOOP;
WriteRecord["PWR,1,public-$Vdd"];
WriteRecord["PWR,0,public-$Gnd"];
FOR sl: Signals ← circuit.signals, sl.rest UNTIL sl=NIL DO
signal: Signal ← sl.first;
sensed, physical, driven, tristate: BOOLFALSE;
[sensed, physical, driven, tristate] ← SensedPhysicalDrivenTristate[signal, pruned];
IF physical OR signal.parameters#NIL THEN {
signalRecord: ROPEIF physical THEN "EXT," ELSE "SIG,";
signalRecord ← Rope.Cat[signalRecord, signal.name];
IF physical THEN {
signalRecord ← Rope.Cat[signalRecord, SELECT TRUE FROM
signal.unbonded => ",U",
driven AND sensed => ",B",
driven AND tristate => ",T",
driven => ",O",
sensed => ",I",
ENDCASE => ERROR];
IF signal.pin#NIL OR signal.parameters#NIL THEN
signalRecord ← Rope.Cat[signalRecord, SELECT TRUE FROM
signal.pin#NIL => IO.PutFR[",,LOC=%g%g", IO.rope[IF Rope.Fetch[signal.pin] IN ['0..'9] THEN "P" ELSE NIL], IO.rope[signal.pin]],
signal.parameters#NIL => ",",
ENDCASE => ERROR];
};
WriteRecord[signalRecord, signal.parameters];
};
ENDLOOP;
WriteRecord["EOF"];
IO.Close[stream];
};
Simple
SimpleData: TYPE = REF SimpleDataRec;
SimpleDataRec: TYPE = RECORD [
xilinxType: ROPE,
pins: Pins];
RegisterSimplePrimitive: PROC [coreName: ROPE, xilinxType: ROPE, pins: PinRecList, aliases: LORNIL] = {
simpleData: SimpleData ← NEW[SimpleDataRec ← [
xilinxType: xilinxType,
pins: PinRecListToPinList[pins]]];
RegisterPrimitive[coreName, FlattenSimplePrimitive, simpleData];
FOR al: LOR ← aliases, al.rest UNTIL al=NIL DO
RegisterPrimitive[al.first, FlattenSimplePrimitive, simpleData];
ENDLOOP;
};
FlattenSimplePrimitive: TranslateProc = {
simpleData: SimpleData ← NARROW[data];
symbol: Symbol ← MakeSymbol[CoreFlat.CellTypePathRope[root, flatCell], simpleData.xilinxType, MakeBindList[cell.public], simpleData.pins, circuit, root, flatCell, flatWireToSignal, bindings];
GetParameters[symbol, instance];
};
CLB
CLBData: TYPE = REF CLBDataRec;
CLBDataRec: TYPE = RECORD [
config: ROPE,
equate: ROPE];
clbPins: Pins ← PinRecListToPinList[LIST[
["A", "A", In],
["B", "B", In],
["C", "C", In],
["D", "D", In],
["X", "X", Out]]];
RegisterCLBPrimitive: PROC [coreName: ROPE, config: ROPE, equate: ROPE] = {
clbData: CLBData ← NEW[CLBDataRec ← [
config: config,
equate: equate]];
RegisterPrimitive[coreName, FlattenCLBPrimitive, clbData];
};
FlattenCLBPrimitive: TranslateProc = {
clbData: CLBData ← NARROW[data];
configs: LORLIST[Rope.Cat["EQUATE F=", clbData.equate]];
symbol: Symbol;
configs ← CONS[Rope.Cat["CONFIG X:F F:", clbData.config], configs];
configs ← CONS[Rope.Cat["BASE ", IF part2000 THEN "F" ELSE "FG"], configs];
symbol ← MakeSymbol[CoreFlat.CellTypePathRope[root, flatCell], "CLB", MakeBindList[cell.public], clbPins, circuit, root, flatCell, flatWireToSignal, bindings, NIL, configs];
GetParameters[symbol, instance];
};
Flop
flopPins: Pins ← PinRecListToPinList[LIST[
["D", "D", In],
["CK", "C", In],
["Q", "Q", Out]]];
flopEnPins: Pins ← PinRecListToPinList[LIST[
["D", "D", In],
["CK", "C", In],
["Q", "Q", Out],
["en", "CE", In]]];
flopReg1Pins: Pins ← PinRecListToPinList[LIST[
["Input", "D", In],
["CK", "C", In],
["Output", "Q", Out],
["en", "CE", In]]];
invPins: Pins ← PinRecListToPinList[LIST[
["I", "I", In],
["X", "O", Out]]];
FlattenFlopPrimitive: TranslateProc = {
symbol: Symbol;
flatName: ROPE ← CoreFlat.CellTypePathRope[root, flatCell];
lora: LIST OF REF ANYNARROW[data];
nqName: ROPE ← CoreOps.FixStupidRef[lora.first];
pins: Pins ← NARROW[lora.rest.first];
d: Core.Wire ← CoreOps.FindWire[cell.public, pins.first.coreName];
c: Core.Wire ← CoreOps.FindWire[cell.public, pins.rest.first.coreName];
q: Core.Wire ← CoreOps.FindWire[cell.public, pins.rest.rest.first.coreName];
en: Core.Wire ← IF pins.rest.rest.rest=NIL THEN NIL ELSE CoreOps.FindWire[cell.public, pins.rest.rest.rest.first.coreName];
nq: Core.Wire ← CoreOps.FindWire[cell.public, nqName];
bindList: BindList ← LIST[[d, pins.first.coreName], [c, pins.rest.first.coreName], [q, pins.rest.rest.first.coreName]];
IF en#NIL THEN bindList ← CONS[[en, pins.rest.rest.rest.first.coreName], bindList];
symbol ← MakeSymbol[flatName, "DFF", bindList, pins, circuit, root, flatCell, flatWireToSignal, bindings];
[] ← MakeSymbol[Rope.Cat[flatName, "ManufacturedInverter"], "INV", LIST[[q, "I"], [nq, "X"]], invPins, circuit, root, flatCell, flatWireToSignal, bindings];
GetParameters[symbol, instance];
};
SymDriver
symPins: Pins ← PinRecListToPinList[LIST[
["I", "I", In],
["X", "O", Out]]];
FlattenSymDriverPrimitive: TranslateProc = {
flatName: ROPE ← CoreFlat.CellTypePathRope[root, flatCell];
i: Core.Wire ← CoreOps.FindWire[cell.public, "I"];
x: Core.Wire ← CoreOps.FindWire[cell.public, "X"];
nx: Core.Wire ← CoreOps.FindWire[cell.public, "nX"];
[] ← MakeSymbol[Rope.Cat[flatName, "ManufacturedBuffer"], "BUF", LIST[[i, "I"], [x, "X"]], symPins, circuit, root, flatCell, flatWireToSignal, bindings];
[] ← MakeSymbol[Rope.Cat[flatName, "ManufacturedInverter"], "INV", LIST[[i, "I"], [nx, "X"]], symPins, circuit, root, flatCell, flatWireToSignal, bindings];
};
Tristate Driver
tPin: Pin ← NEW[PinRec ← ["?", "T", In]];
iPin: Pin ← NEW[PinRec ← ["I", "I", In]];
oPin: Pin ← NEW[PinRec ← ["X", "O", Out,,TRUE]];
FlattenTristateDriver: TranslateProc = {
symbol: Symbol;
flatName: ROPE ← CoreFlat.CellTypePathRope[root, flatCell];
en: Signal ← CreateBoundSignal[CoreOps.FindWire[cell.public, "EN"], circuit, root, flatWireToSignal, bindings, flatCell];
i: Signal ← CreateBoundSignal[CoreOps.FindWire[cell.public, "I"], circuit, root, flatWireToSignal, bindings, flatCell];
x: Signal ← CreateBoundSignal[CoreOps.FindWire[cell.public, "X"], circuit, root, flatWireToSignal, bindings, flatCell];
nenb: Signal ← CreateSignal[circuit];
[] ← AddSymbol[circuit, Rope.Cat[flatName, "ManufacturedEnableInverter"], "INV", LIST[[iPin, en], [oPin, nenb]]];
symbol ← AddSymbol[circuit, Rope.Cat[flatName, "ManufacturedTristate"], "TBUF", LIST[[tPin, nenb], [iPin, i], [oPin, x]]];
GetParameters[symbol, instance];
};
FlattenTristateDriverInv: TranslateProc = {
symbol: Symbol;
flatName: ROPE ← CoreFlat.CellTypePathRope[root, flatCell];
en: Signal ← CreateBoundSignal[CoreOps.FindWire[cell.public, "EN"], circuit, root, flatWireToSignal, bindings, flatCell];
i: Signal ← CreateBoundSignal[CoreOps.FindWire[cell.public, "I"], circuit, root, flatWireToSignal, bindings, flatCell];
x: Signal ← CreateBoundSignal[CoreOps.FindWire[cell.public, "X"], circuit, root, flatWireToSignal, bindings, flatCell];
nenb: Signal ← CreateSignal[circuit];
nd: Signal ← CreateSignal[circuit];
[] ← AddSymbol[circuit, Rope.Cat[flatName, "ManufacturedEnableInverter"], "INV", LIST[[iPin, en], [oPin, nenb]]];
[] ← AddSymbol[circuit, Rope.Cat[flatName, "ManufacturedDataInverter"], "INV", LIST[[iPin, i], [oPin, nd]]];
symbol ← AddSymbol[circuit, Rope.Cat[flatName, "ManufacturedTristate"], "TBUF", LIST[[tPin, nenb], [iPin, nd], [oPin, x]]];
GetParameters[symbol, instance];
};
Interactive Command
WriteXNF: PROC [command: CDSequencer.Command] = {
XNFOne: CoreCDUser.EachRootCellTypeProc ~ {
md: LOR ← SaveCellType[root];
FOR lor: LOR ← md, lor.rest UNTIL lor=NIL DO
TerminalIO.PutF["\nMultiply driven: %g", IO.rope[lor.first]];
ENDLOOP;
TerminalIO.PutF["\nXNF written: %g", IO.rope[CoreOps.GetCellTypeName[root]]];
};
[] ← CoreCDUser.EnumerateSelectedCellTypes[command.design, XNFOne];
};
Utilities
NumToLet: PROC [n: NAT] RETURNS [l: CHAR] = {
l ← LOOPHOLE[LOOPHOLE['A, NAT] + n];
};
RegisterPrimitive: PROC [coreName: ROPE, proc: TranslateProc, data: REF ANYNIL] = {
primitive: Primitive ← NEW[PrimitiveRec ← [
translate: proc,
data: data]];
IF NOT SymTab.Insert[primitives, coreName, primitive] THEN ERROR;
};
PinRecListToPinList: PROC [pins: PinRecList] RETURNS [refPins: Pins ← NIL] = {
t: Pins ← NIL;
FOR pl: PinRecList ← pins, pl.rest UNTIL pl=NIL DO
t ← CONS[NEW[PinRec ← pl.first], t];
ENDLOOP;
FOR pl: Pins ← t, pl.rest UNTIL pl=NIL DO
refPins ← CONS[pl.first, refPins];
ENDLOOP;
};
MakeBindList: PROC [public: Core.Wire] RETURNS [bindlist: BindList ← NIL] = {
MakeBind: PROC [wire: Core.Wire] = {
coreName: ROPE ← CoreOps.GetFullWireName[public, wire];
IF NOT GlobalDelete[coreName] THEN bindlist ← CONS[[wire, coreName], bindlist];
};
CoreOps.VisitRootAtomics[public, MakeBind];
};
MakeSymbol: PROC [name, type: ROPE, bind: BindList, pins: Pins, circuit: FlatCircuit, root: Core.CellType, flatCell: CoreFlat.FlatCellTypeRec, flatWireToSignal, bindings: RefTab.Ref, parameters, configs: LORNIL] RETURNS [symbol: Symbol] = {
symbol ← CreateSymbol[circuit, name, type, parameters, configs];
FOR bl: BindList ← bind, bl.rest UNTIL bl=NIL DO
IF NOT GlobalDelete[bl.first.name] THEN FOR pl: Pins ← pins, pl.rest UNTIL pl=NIL DO
IF Rope.Equal[pl.first.coreName, bl.first.name] THEN {
signal: Signal ← CreateBoundSignal[bl.first.wire, circuit, root, flatWireToSignal, bindings, flatCell];
CreateSSP[symbol, pl.first, signal];
EXIT;
};
REPEAT FINISHED => ERROR;
ENDLOOP;
ENDLOOP;
};
AddSymbol: PROC [circuit: FlatCircuit, name, type: ROPE, bindings: PinSignals] RETURNS [symbol: Symbol] = {
symbol ← CreateSymbol[circuit, name, type];
FOR ps: PinSignals ← bindings, ps.rest UNTIL ps=NIL DO
CreateSSP[symbol, ps.first.pin, ps.first.signal];
ENDLOOP;
};
CreateSymbol: PROC [circuit: FlatCircuit, name, type: ROPE, parameters, configs: LORNIL] RETURNS [symbol: Symbol] = {
symbol ← NEW[SymbolRec];
symbol.name ← name;
symbol.type ← type;
symbol.parameters ← parameters;
symbol.configs ← configs;
circuit.symbols ← CONS[symbol, circuit.symbols];
};
CreateBoundSignal: PROC [wire: Core.Wire, circuit: FlatCircuit, root: Core.CellType, flatWireToSignal: RefTab.Ref, bindings: RefTab.Ref, flatCell: CoreFlat.FlatCellTypeRec] RETURNS [signal: Signal] = {
flatWire: CoreFlat.FlatWire ← NARROW[RefTab.Fetch[bindings, wire].val];
IF flatWire=NIL THEN {
flatWire ← NEW[CoreFlat.FlatWireRec];
flatWire.wire ← wire;
flatWire.flatCell ← flatCell;
};
signal ← NARROW[RefTab.Fetch[flatWireToSignal, flatWire].val];
IF signal=NIL THEN {
signal ← CreateSignal[circuit, SignalName[root, flatWire]];
IF NOT RefTab.Insert[flatWireToSignal, NEW[CoreFlat.FlatWireRec ← flatWire^], signal] THEN ERROR;
signal.pin ← NARROW[CoreProperties.GetWireProp[flatWire.wire, $Pin]];
};
};
CreateSignal: PROC [circuit: FlatCircuit, name: ROPENIL] RETURNS [signal: Signal] = {
signal ← NEW[SignalRec];
IF name=NIL THEN name ← SignalName[NIL, NIL];
signal.name ← name;
circuit.signals ← CONS[signal, circuit.signals];
};
CreateSSP: PROC [symbol: Symbol, pin: Pin, signal: Signal] = {
ssp: SymbolSignalPin ← NEW[SymbolSignalPinRec];
ssp.symbol ← symbol;
ssp.pin ← pin;
ssp.signal ← signal;
symbol.connections ← CONS[ssp, symbol.connections];
signal.connections ← CONS[ssp, signal.connections];
};
GlobalDelete: PROC [name: ROPE] RETURNS [yes: BOOLFALSE] = {
yes ← Rope.Equal[name, "Vdd"] OR Rope.Equal[name, "Gnd"] OR Rope.Equal[name, "RosemaryLogicTime"];
};
nameCount: INT ← 0;
SignalName: PROC [cellType: Core.CellType, flatWire: CoreFlat.FlatWire] RETURNS [name: ROPENIL] = {
CoreFlat uses Letter Digit / ( ) [ ] . *
LCA allows Letter Digit $ — - < > /
but / is reserved for path names and names are case insensitive
BuildNew: Rope.ActionType = {
c ← SELECT c FROM
'/ => '$,
'(, '[ => '<,
'), '] => '>,
'. => '-,
'* => '←,
ENDCASE => c;
IF c IN ['A..'Z] THEN name ← Rope.Concat[name, "$"];
name ← Rope.Concat[name, Rope.FromChar[c]];
};
ManufactureName: PROC = {
name ← IO.PutFR["N%g", IO.int[nameCount]];
nameCount ← nameCount + 1;
};
IF cellType=NIL OR flatWire=NIL THEN ManufactureName[]
ELSE {
old: ROPE ← CoreFlat.WirePathRope[cellType, flatWire^];
shortName: ROPE ← CoreOps.GetShortWireName[flatWire.wire];
SELECT TRUE FROM
Rope.Equal[shortName, "Vdd"] => name ← "public-$Vdd";
Rope.Equal[shortName, "Gnd"] => name ← "public-$Gnd";
Rope.Fetch[old]#'/ => [] ← Rope.Map[base: old, action: BuildNew];
ENDCASE => ManufactureName[];
};
};
SensedPhysicalDrivenTristate: PROC [signal: Signal, pruned: RefTab.Ref] RETURNS [sensed, physical, driven, tristate: BOOLFALSE] = {
FOR cl: SymbolSignalPins ← signal.connections, cl.rest UNTIL cl=NIL DO
ssp: SymbolSignalPin ← cl.first;
IF NOT RefTab.Fetch[pruned, ssp].found THEN {
sensed ← sensed OR ssp.pin.direction=In;
physical ← physical OR ssp.pin.physicalPin;
driven ← driven OR ssp.pin.direction=Out;
tristate ← tristate OR ssp.pin.tristate;
};
ENDLOOP;
};
GetParameters: PROC [symbol: Symbol, instance: CoreClasses.CellInstance] = {
FindParms: PROC [prop: ATOM, val: REF ANY] = {
propName: ROPE ← Atom.GetPName[prop];
IF Rope.Match["Par*", propName, FALSE] THEN {
parm: ROPENARROW[val];
symbol.parameters ← CONS[parm, symbol.parameters];
};
};
CoreProperties.Enumerate[instance.properties, FindParms];
};
Registration
Really should load the primitive definitions by scanning a cell in Xilinx.dale
I/O Symbols
RegisterSimplePrimitive["IBuf", "IBUF", LIST[
["I", "I", In, TRUE],
["X", "O", Out]]];
RegisterSimplePrimitive["OBuf", "OBUF", LIST[
["I", "I", In],
["X", "O", Out, TRUE]]];
RegisterSimplePrimitive["OBufZ", "OBUFZ", LIST[
["I", "I", In],
["EN", "T", In,,,TRUE],
["X", "O", Out, TRUE, TRUE]]];
RegisterSimplePrimitive["OutFF", "OUTFF", LIST[
["D", "D", In],
["CK", "C", In],
["Q", "Q", Out, TRUE]]];
RegisterSimplePrimitive["OutFFZ", "OUTFFZ", LIST[
["D", "D", In],
["EN", "T", In,,,TRUE],
["CK", "C", In],
["X", "O", Out, TRUE, TRUE]]];
RegisterSimplePrimitive["InFF", "INFF", LIST[
["D", "D", In, TRUE],
["CK", "C", In],
["Q", "Q", Out]]];
RegisterSimplePrimitive["InFFBuf", "INFF", LIST[
["D", "D", In, TRUE],
["CK", "C", In],
["O", "O", Out],
["Q", "Q", Out]]];
RegisterSimplePrimitive["InLatch", "INLAT", LIST[
["D", "D", In, TRUE],
["E", "L", In],
["X", "O", In],
["Q", "Q", Out]]];
Inverters, Buffers
RegisterSimplePrimitive["inv", "INV", LIST[
["I", "I", In],
["X", "O", Out]], LIST["invP", "invB", "invPB", "invBuffer", "invDriver"]];
RegisterSimplePrimitive["driver", "BUF", LIST[
["I", "I", In],
["X", "O", Out]]];
RegisterPrimitive["symDriver", FlattenSymDriverPrimitive, NIL];
RegisterPrimitive["3BufferI", FlattenTristateDriverInv, NIL];
RegisterPrimitive["3BufferNI", FlattenTristateDriver, NIL];
RegisterSimplePrimitive["3BufferNI", "TBUF", LIST[
["I", "I", In],
["EN", "T", In,,,TRUE],
["X", "O", Out, FALSE, TRUE]]];
RegisterSimplePrimitive["AClk", "ACLK", LIST[
["I", "I", In],
["X", "O", Out]]];
RegisterSimplePrimitive["GClk", "GCLK", LIST[
["I", "I", In],
["X", "O", Out]]];
Gates: 2, 3, and 4 input
RegisterSimplePrimitive["and2", "AND", LIST[
["I-A", "1", In],
["I-B", "2", In],
["X", "O", Out]]];
RegisterSimplePrimitive["and3", "AND", LIST[
["I-A", "1", In],
["I-B", "2", In],
["I-C", "3", In],
["X", "O", Out]]];
RegisterSimplePrimitive["and4", "AND", LIST[
["I-A", "1", In],
["I-B", "2", In],
["I-C", "3", In],
["I-D", "4", In],
["X", "O", Out]]];
RegisterSimplePrimitive["or2", "OR", LIST[
["I-A", "1", In],
["I-B", "2", In],
["X", "O", Out]]];
RegisterSimplePrimitive["or3", "OR", LIST[
["I-A", "1", In],
["I-B", "2", In],
["I-C", "3", In],
["X", "O", Out]]];
RegisterSimplePrimitive["or4", "OR", LIST[
["I-A", "1", In],
["I-B", "2", In],
["I-C", "3", In],
["I-D", "4", In],
["X", "O", Out]]];
RegisterSimplePrimitive["nand2", "NAND", LIST[
["I-A", "1", In],
["I-B", "2", In],
["X", "O", Out]]];
RegisterSimplePrimitive["nand3", "NAND", LIST[
["I-A", "1", In],
["I-B", "2", In],
["I-C", "3", In],
["X", "O", Out]]];
RegisterSimplePrimitive["nand4", "NAND", LIST[
["I-A", "1", In],
["I-B", "2", In],
["I-C", "3", In],
["I-D", "4", In],
["X", "O", Out]]];
RegisterSimplePrimitive["nor2", "NOR", LIST[
["I-A", "1", In],
["I-B", "2", In],
["X", "O", Out]]];
RegisterSimplePrimitive["nor3", "NOR", LIST[
["I-A", "1", In],
["I-B", "2", In],
["I-C", "3", In],
["X", "O", Out]]];
RegisterSimplePrimitive["nor4", "NOR", LIST[
["I-A", "1", In],
["I-B", "2", In],
["I-C", "3", In],
["I-D", "4", In],
["X", "O", Out]]];
RegisterSimplePrimitive["xor2", "XOR", LIST[
["I-A", "1", In],
["I-B", "2", In],
["X", "O", Out]]];
RegisterSimplePrimitive["xnor2", "XNOR", LIST[
["I-A", "1", In],
["I-B", "2", In],
["X", "O", Out]]];
Gates, compound
RegisterCLBPrimitive["a22o2iP", "A:B:C:D", "~((A*B)+(C*D))"];
RegisterCLBPrimitive["a22o2i", "A:B:C:D", "~((A*B)+(C*D))"];
RegisterCLBPrimitive["o22a2iP", "A:B:C:D", "~((A+B)*(C+D))"];
RegisterCLBPrimitive["o22a2i", "A:B:C:D", "~((A+B)*(C+D))"];
RegisterCLBPrimitive["a21o2i", "A:B:C", "~((A*B)+C)"];
RegisterCLBPrimitive["o21a2i", "A:B:C", "~((A+B)*C)"];
Flops
RegisterSimplePrimitive["DFF", "DFF", LIST[
["D", "D", In],
["ap", "SD", In],
["ar", "RD", In],
["CK", "C", In],
["Q", "Q", Out]]];
RegisterSimplePrimitive["ffAR", "DFF", LIST[
["D", "D", In],
["r", "RD", In],
["CK", "C", In],
["Q", "Q", Out]]];
RegisterPrimitive["ff", FlattenFlopPrimitive, LIST["NQ", flopPins]];
RegisterPrimitive["ffEn", FlattenFlopPrimitive, LIST["NQ", flopEnPins]];
RegisterPrimitive["reg1", FlattenFlopPrimitive, LIST["nOutput", flopReg1Pins]];
Misc.
RegisterSimplePrimitive["pullUp", "PULLUP", LIST[
["out", "O", Out, FALSE, FALSE]]];
RegisterSimplePrimitive["Osc", "OSC", LIST[
["X", "O", Out]]];
CDCommandOps.RegisterWithMenu[$SpecialMenu, "WriteXNF", "Extract selected cells and write xnf files", $WriteXNF, WriteXNF];
END.