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: BOOL ← FALSE,
tristate: BOOL ← FALSE,
invert: BOOL ← FALSE];
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: ROPE ← NIL];
Symbols: TYPE = LIST OF Symbol;
Symbol: TYPE = REF SymbolRec;
SymbolRec:
TYPE =
RECORD [
name: ROPE ← NIL,
type: ROPE ← NIL,
connections: SymbolSignalPins ← NIL,
parameters: LOR ← NIL,
configs: LOR ← NIL];
SymbolSignalPins: TYPE = LIST OF SymbolSignalPin;
SymbolSignalPin: TYPE = REF SymbolSignalPinRec;
SymbolSignalPinRec:
TYPE =
RECORD [
symbol: Symbol ← NIL,
signal: Signal ← NIL,
pin: Pin ← NIL,
parameters: LOR ← NIL];
Signals: TYPE = LIST OF Signal;
Signal: TYPE = REF SignalRec;
SignalRec:
TYPE =
RECORD [
name: ROPE ← NIL,
connections: SymbolSignalPins ← NIL,
pin: ROPE ← NIL, -- NIL => not forced
unbonded: BOOL ← FALSE,
parameters: LOR ← NIL];
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:
ROPE ←
NIL]
RETURNS [multiplyDriven:
LOR ←
NIL] = {
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: ROPE ← NARROW[CoreProperties.GetWireProp[wire, $Pins]];
IF pinList#
NIL
THEN {
ris: IO.STREAM ← IO.RIS[pinList];
FOR i:
INT
IN [0..wire.size)
DO
pin: ROPE ← IO.GetCedarTokenRope[ris].token;
currentValue: ROPE ← NARROW[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: ROPE ← NARROW[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 BOOL ← NARROW[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: BOOL ← FALSE;
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: ROPE ← NARROW[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];
};
PruneFlattenedCircuit:
PROC [circuit: FlatCircuit]
RETURNS [pruned: RefTab.Ref] = {
CheckSignal: RefTab.EachPairAction = {
signal: Signal ← NARROW[key];
sensed, physical: BOOL ← FALSE;
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:
LOR ←
NIL]= {
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:
LOR ←
NIL] = {
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.STREAM ← FS.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: ROPE ← IO.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: BOOL ← FALSE;
[sensed, physical, driven, tristate] ← SensedPhysicalDrivenTristate[signal, pruned];
IF physical
OR signal.parameters#
NIL
THEN {
signalRecord: ROPE ← IF 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:
LOR ←
NIL] = {
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: LOR ← LIST[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 ANY ← NARROW[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];
};
Utilities
NumToLet:
PROC [n:
NAT]
RETURNS [l:
CHAR] = {
l ← LOOPHOLE[LOOPHOLE['A, NAT] + n];
};
RegisterPrimitive:
PROC [coreName:
ROPE, proc: TranslateProc, data:
REF
ANY ←
NIL] = {
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:
LOR ←
NIL]
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:
LOR ←
NIL]
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:
ROPE ←
NIL]
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:
BOOL ←
FALSE] = {
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:
ROPE ←
NIL] = {
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:
BOOL ←
FALSE] = {
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: ROPE ← NARROW[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];