XilinxIOImpl.mesa
Copyright © 1986 by Xerox Corporation. All rights reserved.
Barth, July 18, 1989 6:00:22 pm PDT
Last Edited by: Gasbarro July 18, 1989 6:23:49 pm PDT
DIRECTORY Core, CoreClasses, CoreFlat, CoreOps, CoreProperties, FS, RefTab, SymTab, IO, Rope, TerminalIO, XilinxIO;
XilinxIOImpl: CEDAR PROGRAM
IMPORTS CoreClasses, CoreFlat, CoreOps, CoreProperties, FS, RefTab, SymTab, IO, Rope, TerminalIO
EXPORTS XilinxIO
= BEGIN OPEN XilinxIO;
Types and Globals
ROPE: TYPE = Core.ROPE;
Primitive: TYPE = REF PrimitiveRec;
PrimitiveRec: TYPE = RECORD [
translate: TranslateProc,
data: REF ANY];
TranslateProc: TYPE = PROC [stream: IO.STREAM, root, cell: Core.CellType, name: ROPE, flatCell: CoreFlat.FlatCellTypeRec, iomap: SymTab.Ref, part2000: BOOL, data: REF ANY];
Pins: TYPE = LIST OF Pin;
Pin: TYPE = RECORD [
coreName: ROPE,
xilinxName: ROPE,
direction: InOrOut,
physicalPin: BOOLFALSE];
InOrOut: TYPE = {In, Out};
directionNames: ARRAY InOrOut OF ROPE ← ["I", "O"];
primitives: SymTab.Ref ← SymTab.Create[];
Functions
SaveCellType: PUBLIC PROC [cellType: Core.CellType, fileName: ROPENIL] = {
WriteCellType: CoreFlat.BoundFlatCellProc = {
name: ROPE ← CoreOps.GetCellTypeName[cell];
primitive: Primitive ← NARROW[SymTab.Fetch[primitives, name].val];
IF primitive=NIL THEN CoreFlat.NextBoundCellType[cell, target, flatCell, instance, index, parent, flatParent, data, bindings, WriteCellType]
ELSE primitive.translate[stream, cellType, cell, name, flatCell, iomap, part2000, primitive.data];
};
WriteEXT: PROC [wire: Core.Wire] = {
name: ROPE ← CoreOps.GetFullWireName[cellType.public, wire];
IF NOT GlobalDelete[name] THEN {
signalName: ROPE ← SignalName[cellType, CoreFlat.rootCellType, wire];
pin: REF INTNARROW[CoreProperties.InheritPublicProp[cellType, wire, $Pin], REF INT];
direction: ROPENARROW[SymTab.Fetch[iomap, signalName].val];
IF direction=NIL THEN ERROR;
IO.PutF[stream, "EXT,%g,%g", IO.rope[signalName], IO.rope[direction]];
IF pin#NIL THEN IO.PutF[stream, ",,LOC=P%g", IO.int[pin^]];
IO.PutRope[stream, "\n"];
};
};
stream: IO.STREAMNIL;
iomap: SymTab.Ref ← SymTab.Create[];
partTypeName: ROPENARROW[CoreProperties.InheritCellTypeProp[cellType, $XilinxPartType]];
part2000: BOOLFALSE;
IF fileName=NIL THEN fileName ← Rope.Cat[CoreOps.GetCellTypeName[cellType], ".xnf"];
stream ← FS.StreamOpen[fileName, $create];
IO.PutRope[stream, "LCANET,1\n"];
IO.PutF[stream, "PROG,Core2XNF,1,%g\n", IO.time[]];
IF partTypeName=NIL THEN partTypeName ← "2064PC68-33";
part2000 ← Rope.Fetch[partTypeName]='2;
IO.PutF[stream, "PART,%g\n", IO.rope[partTypeName]];
WriteCellType[cell: cellType, bindings: CoreFlat.InitialBindingTable[cellType]];
IO.PutRope[stream, "PWR,1,public-$Vdd\n"];
IO.PutRope[stream, "PWR,0,public-$Gnd\n"];
CoreOps.VisitRootAtomics[cellType.public, WriteEXT];
IO.PutRope[stream, "EOF\n"];
IO.Close[stream];
};
PrintCoreRecursive: PUBLIC PROC [cellType: Core.CellType] = {
WriteCellType: PROC [cell: Core.CellType, indent: NAT ← 0] = {
name: ROPE ← CoreOps.GetCellTypeName[cell];
IF name#NIL THEN {
FOR i: NAT IN [0..indent) DO IO.PutChar[stream, ' ] ENDLOOP;
IO.PutF[stream, "%g\n", IO.rope[name]];
};
IF RefTab.Fetch[iomap, cell].found THEN RETURN;
IF NOT RefTab.Insert[iomap, cell, $Printed] THEN ERROR;
cell ← CoreOps.ToBasic[cell];
IF cell.class=CoreClasses.recordCellClass THEN {
rct: CoreClasses.RecordCellType ← NARROW[cell.data];
subMap: RefTab.Ref ← RefTab.Create[];
FOR index: NAT IN [0..rct.size) DO
subType: Core.CellType ← rct[index].type;
IF NOT RefTab.Fetch[subMap, subType].found THEN {
IF NOT RefTab.Insert[subMap, subType, $Printed] THEN ERROR;
WriteCellType[subType, indent+2];
};
ENDLOOP;
};
};
stream: IO.STREAM ← TerminalIO.TOS[];
iomap: RefTab.Ref ← RefTab.Create[];
WriteCellType[cellType];
};
Simple
SimpleData: TYPE = REF SimpleDataRec;
SimpleDataRec: TYPE = RECORD [
xilinxType: ROPE,
pins: Pins];
RegisterSimplePrimitive: PROC [coreName: ROPE, xilinxType: ROPE, pins: Pins] = {
simpleData: SimpleData ← NEW[SimpleDataRec ← [
xilinxType: xilinxType,
pins: pins]];
RegisterPrimitive[coreName, WriteSimplePrimitive, simpleData];
};
WriteSimplePrimitive: TranslateProc = {
flatName: ROPE ← CoreFlat.CellTypePathRope[root, flatCell];
simpleData: SimpleData ← NARROW[data];
IO.PutF[stream, "SYM,%g,%g\n", IO.rope[flatName], IO.rope[simpleData.xilinxType]];
WritePinsCleanly[root, flatCell, iomap, cell.public, stream, simpleData.pins];
IO.PutRope[stream, "END\n"];
IF (NOT part2000) AND Rope.Equal[simpleData.xilinxType, "DFF"] THEN ERROR; -- haven't sorted out 2000 vs. 3000 dependencies
};
CLB
CLBData: TYPE = REF CLBDataRec;
CLBDataRec: TYPE = RECORD [
config: ROPE,
equate: ROPE];
clbPins: Pins ← 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, WriteCLBPrimitive, clbData];
};
WriteCLBPrimitive: TranslateProc = {
flatName: ROPE ← CoreFlat.CellTypePathRope[root, flatCell];
clbData: CLBData ← NARROW[data];
IO.PutF[stream, "SYM,%g,%g\n", IO.rope[flatName], IO.rope["CLB"]];
WritePinsCleanly[root, flatCell, iomap, cell.public, stream, clbPins];
IO.PutF[stream, "CFG,BASE %g\n", IO.rope[(IF part2000 THEN "F" ELSE "FG")]];
IO.PutF[stream, "CFG,CONFIG X:F F:%g\n", IO.rope[clbData.config]];
IO.PutF[stream, "CFG,EQUATE F=%g\n", IO.rope[clbData.equate]];
IO.PutRope[stream, "END\n"];
};
Flop
RegisterFlopPrimitive: PROC [coreName: ROPE, pins: Pins] = {
simpleData: SimpleData ← NEW[SimpleDataRec ← [
xilinxType: NIL,
pins: pins]];
RegisterPrimitive[coreName, WriteFlopPrimitive, simpleData];
};
WriteFlopPrimitive: TranslateProc = {
unboundPins: LIST OF ROPENIL;
flatName: ROPE ← CoreFlat.CellTypePathRope[root, flatCell];
simpleData: SimpleData ← NARROW[data];
IO.PutF[stream, "SYM,%g,%g\n", IO.rope[flatName], IO.rope["DFF"]];
unboundPins ← WritePins[root, flatCell, iomap, cell.public, stream, simpleData.pins];
IF unboundPins=NIL OR unboundPins.rest#NIL OR NOT Rope.Equal[unboundPins.first, "nQ", FALSE] THEN ERROR;
IO.PutRope[stream, "END\n"];
{
qSignalName: ROPE ← SignalName[root, flatCell, CoreOps.FindWire[cell.public, "Q"]];
nqSignalName: ROPE ← SignalName[root, flatCell, CoreOps.FindWire[cell.public, "NQ"]];
IO.PutF[stream, "SYM,%g,INV\n", IO.rope[Rope.Cat[flatName, "ManufacturedInverter"]]];
IO.PutF[stream, "PIN,I,%g,%g\n", IO.rope[directionNames[In]], IO.rope[qSignalName]];
IO.PutF[stream, "PIN,O,%g,%g\n", IO.rope[directionNames[Out]], IO.rope[nqSignalName]];
IO.PutRope[stream, "END\n"];
};
};
Utilities
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;
};
GlobalDelete: PROC [name: ROPE] RETURNS [yes: BOOLFALSE] = {
yes ← Rope.Equal[name, "Vdd"] OR Rope.Equal[name, "Gnd"] OR Rope.Equal[name, "RosemaryLogicTime"];
};
SignalName: PROC [cellType: Core.CellType, flatCell: CoreFlat.FlatCellTypeRec, wire: Core.Wire] 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]];
};
canonicalWire: CoreFlat.FlatWireRec ← CoreFlat.CanonizeWire[cellType, [flatCell: flatCell, wire: wire]];
old: ROPE ← CoreFlat.WirePathRope[cellType, canonicalWire];
[] ← Rope.Map[base: old, action: BuildNew];
};
WritePinsCleanly: PROC [root: Core.CellType, flatCell: CoreFlat.FlatCellTypeRec, iomap: SymTab.Ref, public: Core.Wire, stream: IO.STREAM, pins: Pins] = {
IF WritePins[root, flatCell, iomap, public, stream, pins]#NIL THEN ERROR;
};
WritePins: PROC [root: Core.CellType, flatCell: CoreFlat.FlatCellTypeRec, iomap: SymTab.Ref, public: Core.Wire, stream: IO.STREAM, pins: Pins] RETURNS [unboundPins: LIST OF ROPENIL] = {
WritePin: PROC [wire: Core.Wire] = {
coreName: ROPE ← CoreOps.GetFullWireName[public, wire];
signalName: ROPE ← SignalName[root, flatCell, wire];
FOR pl: Pins ← pins, pl.rest UNTIL pl=NIL DO
IF Rope.Equal[pl.first.coreName, coreName] THEN {
IF pl.first.physicalPin THEN {
current: ROPENARROW[SymTab.Fetch[iomap, signalName].val];
IF current=NIL THEN [] ← SymTab.Insert[iomap, signalName, directionNames[pl.first.direction]]
ELSE IF NOT Rope.Equal[current, directionNames[pl.first.direction]] THEN ERROR;
};
IO.PutF[stream, "PIN,%g,%g,%g\n", IO.rope[pl.first.xilinxName], IO.rope[directionNames[pl.first.direction]], IO.rope[signalName]];
RETURN;
};
ENDLOOP;
IF GlobalDelete[coreName] THEN RETURN;
unboundPins ← CONS[coreName, unboundPins];
};
CoreOps.VisitRootAtomics[public, WritePin];
};
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],
["X", "O", Out, 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],
["CK", "C", In],
["Q", "Q", Out, TRUE]]];
RegisterSimplePrimitive["InFF", "INFF", LIST[
["D", "D", In, TRUE],
["CK", "C", In],
["Q", "Q", Out]]];
RegisterSimplePrimitive["InLatch", "INLATCH", LIST[
["D", "D", In, TRUE],
["E", "E", In],
["X", "O", In],
["Q", "Q", Out]]];
Inverters, Buffers
RegisterSimplePrimitive["inv", "INV", LIST[
["I", "I", In],
["X", "O", Out]]];
RegisterSimplePrimitive["invP", "INV", LIST[
["I", "I", In],
["X", "O", Out]]];
RegisterSimplePrimitive["invBuffer", "INV", LIST[
["I", "I", In],
["X", "O", Out]]];
RegisterSimplePrimitive["driver", "BUF", LIST[
["I", "I", In],
["X", "O", Out]]];
RegisterSimplePrimitive["3BufferNI", "TBUF", LIST[
["I", "I", In],
["EN", "T", In],
["X", "O", Out]]];
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]]];
RegisterFlopPrimitive["ff", LIST[
["D", "D", In],
["CK", "C", In],
["Q", "Q", Out]]];
Misc.
RegisterSimplePrimitive["pullUp", "PULLUP", LIST[
["out", "O", Out]]];
RegisterSimplePrimitive["Osc", "OSC", LIST[
["X", "O", Out]]];
END.